diff --git a/.gitignore b/.gitignore index 4c771abd2b..dd9c048f1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Test artifacts repo/testdata/ +./config* # Compiled Object files, Static and Dynamic libs (Shared Objects) *.o @@ -35,12 +36,11 @@ dist # Development environment files .ackrc +.vscode .tags* *.sw? -debug -.vscode -config* -openbazaar-go* +marketplace-go* +config_* # macOS .DS_Store diff --git a/.golangci.yml b/.golangci.yml index f50aa0171a..9739814aa2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -48,8 +48,8 @@ linters: - goconst - govet - megacheck + - errcheck disable: - goimports - - errcheck - golint - prealloc diff --git a/.travis.yml b/.travis.yml index dbb3a1d1e6..fb5b8a17aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,11 @@ env: - "PATH=/home/travis/gopath/bin:$PATH" before_install: - go get -u github.com/axw/gocov/gocov github.com/mattn/goveralls github.com/tcnksm/ghr - - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.15.0 + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.23.3 install: - echo "No external dependencies required. Skipping travis default library dependency setup to use vendors..." script: - - $GOPATH/bin/golangci-lint run --deadline 10m + - $GOPATH/bin/golangci-lint run --deadline 10m --new-from-rev= - cd $TRAVIS_BUILD_DIR && go test -i && ./test_compile.sh - goveralls -coverprofile=coverage.out -service travis-ci after_success: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c26a7520c4..087bff7dcc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,10 +11,10 @@ You must run `gofmt` before each commit. Travis will fail if you do not run it. All commits are checked with [golangci-lint](https://github.com/golangci/golangci-lint) using the [.golangci.yml](.golangci.yml) config in the repo. -Additionally, we like to keep the [Go Report Card](https://goreportcard.com/report/github.com/phoreproject/openbazaar-go) score at A or better. So keep those other tests in mind when you commit. +Additionally, we like to keep the [Go Report Card](https://goreportcard.com/report/github.com/phoreproject/pm-go) score at A or better. So keep those other tests in mind when you commit. ## Tests -If you add new code, please submit a unit test with it. We might not accept the PR without it. Additionally, you are expected to make the appropriate changes to existing tests if they are affected by your commits. This also includes the integration tests in the [qa package](https://github.com/phoreproject/openbazaar-go/tree/master/qa). +If you add new code, please submit a unit test with it. We might not accept the PR without it. Additionally, you are expected to make the appropriate changes to existing tests if they are affected by your commits. This also includes the integration tests in the [qa package](https://github.com/phoreproject/pm-go/tree/master/qa). ## Pull Requests If your PR isn't ready to merge make sure you specify this somehow. For example by placing [WIP] in the PR title. Ideally you should include a `task list` in the PR message to track the progress of the PR. diff --git a/Dockerfile b/Dockerfile index 034f3b81ad..cb0f7e9df1 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,27 @@ +# Build stage - Use a full build environment to create a static binary FROM golang:1.11 -WORKDIR /go/src/github.com/OpenBazaar/openbazaar-go -COPY . . -RUN go build --ldflags '-extldflags "-static"' -o /opt/openbazaard . +COPY . /go/src/github.com/phoreproject/pm-go +RUN go build --ldflags '-extldflags "-static"' -o /opt/marketplaced /go/src/github.com/phoreproject/pm-go -FROM openbazaar/base:v1.0.0 +# Final state - Create image containing nothing but the marketplaced binary and +# some base settings +FROM PhoreMarketplace/base:v1.0.0 + +# Document ports in use +# 4002 - HTTP(s) API +# 4001 - libp2p/IPFS TCP port +# 9005 - libp2p/IPFS websocket port EXPOSE 5001 5002 10005 -ENTRYPOINT ["/opt/openbazaard"] -VOLUME /var/lib/openbazaar -CMD ["start", "-d", "/var/lib/openbazaar"] -COPY --from=0 /opt/openbazaard /opt/openbazaard + +# Define a volume to perist data to. This data contains all the important +# elements defining a peer so it must be durable as long as the identity exists +VOLUME /var/lib/marketplace + +# Tell the image what to execute by default. We start a mainnet OB server +# that uses the defined volume for node data +ENTRYPOINT ["/opt/marketplaced"] +CMD ["start", "-d", "/var/lib/marketplace"] + +# Copy the compiled binary into this image. It's COPY'd last since the rest of +# this stage rarely changes while the binary changes every commit +COPY --from=0 /opt/marketplaced /opt/marketplaced diff --git a/Dockerfile.dev b/Dockerfile.dev index d2a77cc739..cf803c1904 100755 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,39 +1,20 @@ -FROM golang:1.11 -VOLUME /var/lib/openbazaar +FROM phoremarketplace/server-qa:0.10 -RUN wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tgz && \ - tar xvf Python-3.6.0.tgz && \ - cd Python-3.6.0 && \ - ./configure --enable-optimizations && \ - make -j8 -RUN apt-get update && apt-get install -yq zlib1g-dev libssl-dev unzip -RUN cd Python-3.6.0 && \ - make altinstall && \ - ln -s /usr/local/bin/python3.6 /usr/local/bin/python3 - -COPY ./qa/requirements.txt ./requirements.txt - -RUN pip3.6 install --upgrade pip && \ - pip3.6 install -r requirements.txt && \ - wget https://bitcoin.org/bin/bitcoin-core-0.16.3/bitcoin-0.16.3-x86_64-linux-gnu.tar.gz && \ - tar -xvzf bitcoin-0.16.3-x86_64-linux-gnu.tar.gz -C /opt - -RUN wget https://github.com/google/protobuf/releases/download/v3.6.0/protoc-3.6.0-linux-x86_64.zip && \ - unzip ./protoc-3.6.0-linux-x86_64.zip -x readme.txt && \ - mv ./include/* /usr/local/include/ && \ - mv ./bin/protoc /usr/local/bin/ && \ - rm -rf ./include ./bin - -WORKDIR /go/src/github.com/phoreproject/openbazaar-go +WORKDIR /go/src/github.com/phoreproject/pm-go RUN go get -u github.com/gogo/protobuf/proto \ github.com/golang/protobuf/protoc-gen-go \ github.com/icrowley/fake \ github.com/derekparker/delve/cmd/dlv \ github.com/tools/godep +RUN cd /go/src/github.com/golang/protobuf && \ + git checkout tags/v1.2.0 -b v1.2.0 && \ + cd protoc-gen-go && \ + go install + RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.15.0 -WORKDIR /go/src/github.com/phoreproject/openbazaar-go +WORKDIR /go/src/github.com/phoreproject/pm-go COPY . . diff --git a/Dockerfile.dummy b/Dockerfile.dummy index c2d47c7c50..1a4cd5a338 100755 --- a/Dockerfile.dummy +++ b/Dockerfile.dummy @@ -1,11 +1,11 @@ # Build stage FROM golang:1.8.1 -WORKDIR /go/src/github.com/phoreproject/openbazaar-go +WORKDIR /go/src/github.com/phoreproject/pm-go COPY . . RUN go build -o /opt/dummy ./dummy # Run stage -FROM openbazaar/server +FROM phoremarketplace/server COPY ./run.sh /opt/run.sh COPY --from=0 /opt/dummy /opt/dummy ENTRYPOINT ["/bin/sh"] diff --git a/Dockerfile.qa b/Dockerfile.qa new file mode 100644 index 0000000000..869e60ab09 --- /dev/null +++ b/Dockerfile.qa @@ -0,0 +1,34 @@ +FROM golang:1.11 + +ENV BITCOIND_VERSION=0.16.3 +ENV BITCOIND_PATH=/opt/bitcoin-${BITCOIND_VERSION} + +# software installs, from most stable to most volatile +RUN apt-get update -y +RUN apt-get install -yq software-properties-common \ + zlib1g-dev \ + libssl-dev \ + unzip \ + python3 \ + python3-pip + +RUN wget https://github.com/google/protobuf/releases/download/v3.6.0/protoc-3.6.0-linux-x86_64.zip && \ + unzip ./protoc-3.6.0-linux-x86_64.zip -x readme.txt && \ + mv ./include/* /usr/local/include/ && \ + mv ./bin/protoc /usr/local/bin/ && \ + rm -rf ./include ./bin + +COPY ./qa/requirements.txt ./requirements.txt + +RUN python3 -m pip install --upgrade pip && \ + pip install -r ./requirements.txt && \ + wget https://bitcoin.org/bin/bitcoin-core-0.16.3/bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz && \ + tar -xvzf bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz -C /opt + +WORKDIR /go/src/github.com/phoreproject/pm-go + +COPY ./Makefile ./Makefile + +VOLUME /go/src/github.com/phoreproject/pm-go + +CMD make qa_test diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 07b012c609..45d848a694 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,19 +1,32 @@ { - "ImportPath": "github.com/phoreproject/openbazaar-go", + "ImportPath": "github.com/phoreproject/pm-go", "GoVersion": "go1.12", "GodepVersion": "v80", "Deps": [ { - "ImportPath": "github.com/OpenBazaar/bitcoind-wallet", - "Rev": "6c59e2405456eac2ea76c13e7472bb51b655bdd3" + "ImportPath": "github.com/disintegration/imaging", + "Comment": "v1.6.0-3-g465faf0", + "Rev": "465faf0892b5c7b3325643b0e47282e1331672e7" }, { - "ImportPath": "github.com/OpenBazaar/go-ethwallet/util", - "Rev": "4303d34a6a57a2d34fb33939a2dd67d98a5a648d" + "ImportPath": "golang.org/x/image/bmp", + "Rev": "f03afa92d3ffad9e5ff762aa549908afe674f01e" }, { - "ImportPath": "github.com/OpenBazaar/go-ethwallet/wallet", - "Rev": "4303d34a6a57a2d34fb33939a2dd67d98a5a648d" + "ImportPath": "golang.org/x/image/tiff", + "Rev": "f03afa92d3ffad9e5ff762aa549908afe674f01e" + }, + { + "ImportPath": "golang.org/x/image/tiff/lzw", + "Rev": "f03afa92d3ffad9e5ff762aa549908afe674f01e" + }, + { + "ImportPath": "github.com/phoreproject/go-ethwallet/util", + "Rev": "f8cc45691dfffa591a606bf180dbe5f6e4dd23cd" + }, + { + "ImportPath": "github.com/phoreproject/go-ethwallet/wallet", + "Rev": "f8cc45691dfffa591a606bf180dbe5f6e4dd23cd" }, { "ImportPath": "github.com/OpenBazaar/golang-socketio", @@ -33,108 +46,100 @@ }, { "ImportPath": "github.com/phoreproject/multiwallet", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/bitcoin", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/bitcoincash", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/cache", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/client", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/client/blockbook", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/client/errors", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/client/insight", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/client/transport", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/config", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/datastore", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/keys", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/litecoin", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/litecoin/address", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/litecoin/params", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/model", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/service", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/util", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/zcash", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/zcash/address", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/phoreproject/multiwallet/phore", - "Rev": "5936dd4d55a6a001a07278da631ccb046d766df4" + "Rev": "c8aac3636b291919484e88c0cd5eae598ed8df61" }, { "ImportPath": "github.com/OpenBazaar/spvwallet", - "Rev": "06f6037251780164889a046526b67b2c2be29107" + "Rev": "41f07b1fdcf5084530526cbf469e79437fbdc5dd" }, { "ImportPath": "github.com/OpenBazaar/spvwallet/exchangerates", - "Rev": "06f6037251780164889a046526b67b2c2be29107" + "Rev": "41f07b1fdcf5084530526cbf469e79437fbdc5dd" }, { "ImportPath": "github.com/OpenBazaar/wallet-interface", "Rev": "ed1c16b1331fc11f83a37810e2a693557c30e8ae" }, - { - "ImportPath": "github.com/OpenBazaar/zcashd-wallet", - "Rev": "2b76590b8874e3eb371c51362eed6cb7a10c09b4" - }, - { - "ImportPath": "github.com/OpenBazaar/zcashd-wallet/exchangerates", - "Rev": "2b76590b8874e3eb371c51362eed6cb7a10c09b4" - }, { "ImportPath": "github.com/agl/ed25519/edwards25519", "Rev": "5312a61534124124185d41f09206b9fef1d88403" @@ -550,8 +555,8 @@ }, { "ImportPath": "github.com/gorilla/websocket", - "Comment": "v1.4.0-5-g483fb8d", - "Rev": "483fb8d7c32fcb4b5636cd293a92e3935932e2f4" + "Comment": "v1.4.1", + "Rev": "c3e18be99d19e6b3e8f1559eea2c161a665c4b6b" }, { "ImportPath": "github.com/gosimple/slug", @@ -914,10 +919,6 @@ "Comment": "v2.1-2-gaee4629", "Rev": "aee4629129445bbdfb69aa565537dcfa16544311" }, - { - "ImportPath": "github.com/nfnt/resize", - "Rev": "891127d8d1b52734debe1b3c3d7e747502b6c366" - }, { "ImportPath": "github.com/op/go-logging", "Comment": "v1-7-g970db52", @@ -2519,6 +2520,11 @@ { "ImportPath": "gx/ipfs/QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6/base32", "Rev": "19b9eacefb7aef6729a55f53fa2646d1e172faff" - } - ] + }, + { + "ImportPath": "github.com/nanmu42/etherscan-api", + "Comment": "v1.1.0", + "Rev": "586884d258b6b8b22d5bd039e270d33572888f54" + } + ] } diff --git a/Makefile b/Makefile index bdd1e8e066..09776bbc1a 100755 --- a/Makefile +++ b/Makefile @@ -1,12 +1,32 @@ +.DEFAULT_GOAL := help + +## +## Global ENV vars +## + +GIT_SHA ?= $(shell git rev-parse --short=8 HEAD) +GIT_TAG ?= $(shell git describe --tags --abbrev=0) + +## +## Helpful Help +## + +.PHONY: help +help: + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + + ## ## Building ## -ios_framework: - gomobile bind -target=ios github.com/phoreproject/openbazaar-go/mobile +.PHONY: ios_framework +ios_framework: ## Build iOS Framework for mobile + gomobile bind -target=ios/arm64,ios/amd64 -iosversion=10 -ldflags="-s -w" github.com/phoreproject/pm-go/mobile -android_framework: - gomobile bind -target=android github.com/phoreproject/openbazaar-go/mobile +.PHONY: android_framework +android_framework: ## Build Android Framework for mobile + gomobile bind -target=android/arm,android/arm64,android/amd64 -ldflags="-s -w" github.com/phoreproject/pm-go/mobile ## ## Protobuf compilation @@ -17,20 +37,62 @@ P_ANY = Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any PKGMAP = $(P_TIMESTAMP),$(P_ANY) .PHONY: protos -protos: +protos: ## Build go files for proto definitions cd pb/protos && PATH=$(PATH):$(GOPATH)/bin protoc --go_out=$(PKGMAP):.. *.proto + +## +## Testing +## +MARKETPLACED_NAME ?= marketplaced-$(GIT_SHA) +BITCOIND_PATH ?= . + +.PHONY: marketplaced +marketplaced: ## Build daemon + $(info "Building Marketplace daemon...") + go build -o ./$(MARKETPLACED_NAME) . + +.PHONY: qa_test +qa_test: marketplaced ## Run QA test suite against current working copy + $(info "Running QA... (marketplaced: ../$(MARKETPLACED_NAME) bitcoind: $(BITCOIND_PATH)/bin/bitcoind)") + (cd qa && ./runtests.sh ../$(MARKETPLACED_NAME) $(BITCOIND_PATH)/bin/bitcoind) + +.PHONY: qa_eth_test +qa_eth_test: openbazaard ## Run ETH-based QA test suite against current working copy + $(info "Running ETH QA... (openbazaard: ../$(OPENBAZAARD_NAME))") + (cd qa && ./runtests_eth.sh ../$(OPENBAZAARD_NAME)) + ## ## Docker ## -DOCKER_PROFILE ?= openbazaar -DOCKER_VERSION ?= $(shell git describe --tags --abbrev=0) -DOCKER_IMAGE_NAME ?= $(DOCKER_PROFILE)/server:$(DOCKER_VERSION) +PUBLIC_DOCKER_REGISTRY ?= PhoreMarketplace +QA_DEV_TAG ?= 0.10 + +DOCKER_SERVER_IMAGE_NAME ?= $(PUBLIC_DOCKER_REGISTRY)/server:$(GIT_TAG) +DOCKER_QA_IMAGE_NAME ?= $(PUBLIC_DOCKER_REGISTRY)/server-qa:$(QA_DEV_TAG) +DOCKER_DEV_IMAGE_NAME ?= $(PUBLIC_DOCKER_REGISTRY)/server-dev:$(QA_DEV_TAG) + + +.PHONY: docker_build +docker_build: ## Build container for daemon + docker build -t $(DOCKER_SERVER_IMAGE_NAME) . + +.PHONY: docker_push +docker_push: docker ## Push container for daemon + docker push $(DOCKER_SERVER_IMAGE_NAME) + +.PHONY: qa_docker_build +qa_docker_build: ## Build container with QA test dependencies included + docker build -t $(DOCKER_QA_IMAGE_NAME) -f ./Dockerfile.qa . + +.PHONY: qa_docker_push +qa_docker_push: qa_docker_build ## Push container for daemon QA test environment + docker push $(DOCKER_QA_IMAGE_NAME) -.PHONY: docker -docker: - docker build -t $(DOCKER_IMAGE_NAME) . +.PHONY: dev_docker_build +dev_docker: ## Build container with dev dependencies included + docker build -t $(DOCKER_DEV_IMAGE_NAME) -f ./Dockerfile.dev . -.PHONY: push_docker -push_docker: - docker push $(DOCKER_IMAGE_NAME) +.PHONY: dev_docker_push +dev_docker_push: dev_docker_build ## Push container for daemon dev environment + docker push $(DOCKER_DEV_IMAGE_NAME) diff --git a/README.md b/README.md index 1f6513777d..fd24976dc7 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# openbazaar-go +# marketplace-go ![banner](https://i.imgur.com/iOnXDXK.png) OpenBazaar Server Daemon in Go -[![Build Status](https://travis-ci.org/OpenBazaar/openbazaar-go.svg?branch=master)](https://travis-ci.org/OpenBazaar/openbazaar-go) -[![Coverage Status](https://coveralls.io/repos/github/OpenBazaar/openbazaar-go/badge.svg?branch=master)](https://coveralls.io/github/OpenBazaar/openbazaar-go?branch=master) -[![Go Report Card](https://goreportcard.com/badge/github.com/phoreproject/openbazaar-go)](https://goreportcard.com/report/github.com/phoreproject/openbazaar-go) +[![Build Status](https://travis-ci.org/phoreproject/pm-go.svg?branch=master)](https://travis-ci.org/phoreproject/pm-go) +[![Coverage Status](https://coveralls.io/repos/github/phoreproject/pm-go/badge.svg?branch=master)](https://coveralls.io/github/phoreproject/pm-go?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/phoreproject/pm-go)](https://goreportcard.com/report/github.com/phoreproject/pm-go) -This repository contains the Phore Marketplace server daemon which handles the heavy lifting for the [Phore Marketplace](https://phore.io/) desktop application. The server combines several technologies: A modified [IPFS](https://ipfs.io) node, which itself combines ideas from Git, BitTorrent, and Kademlia. A lightweight SPV Bitcoin wallet for interacting with the Bitcoin network. And a JSON API which can be used by a user interface to control the node and browse the network. If you are looking for the OpenBazaar user interface code see [here](https://github.com/phoreproject/openbazaar-desktop). +This repository contains the Phore Marketplace server daemon which handles the heavy lifting for the [Phore Marketplace](https://phore.io/) desktop application. The server combines several technologies: A modified [IPFS](https://ipfs.io) node, which itself combines ideas from Git, BitTorrent, and Kademlia. A lightweight SPV Bitcoin wallet for interacting with the Bitcoin network. And a JSON API which can be used by a user interface to control the node and browse the network. If you are looking for the OpenBazaar user interface code see [here](https://github.com/phoreproject/pm-desktop). ## Table of Contents @@ -28,11 +28,19 @@ A typical install of OpenBazaar contains a bundle of the server daemon and user ### Install Pre-built Packages -The easiest way to run the server is to download a pre-built binary. You can find binaries of our latest release for each operating system [here](https://github.com/phoreproject/openbazaar-go/releases/). +The easiest way to run the server is to download a pre-built binary. You can find binaries of our latest release for each operating system [here](https://github.com/phoreproject/pm-go/releases/). ### Build from Source -To build from source you will need to have Go installed and properly configured. Detailed instructions for installing Go and openbazaar-go on each operating system can be found in the [docs package](https://github.com/phoreproject/openbazaar-go/tree/master/docs). +To build from source you will need to have Go installed and properly configured. Detailed instructions for installing Go and marketplace-go on each operating system can be found in the [docs package](https://github.com/phoreproject/pm-go/tree/master/docs). + +### Run via Docker image + +You can also use our Docker Hub image to run openbazaar-go. `latest` points to the latest release, but you can run any other version by matching the release tag to the Docker image tag. + +``` +docker run -it openbazaar/server:latest [OPTIONS] start [start-OPTIONS] +``` ## Dependency Management @@ -44,11 +52,11 @@ We are using a [fork](https://github.com/phoreproject/go-ipfs) of go-ipfs in the ## Updating -You can either pull in remote changes as normal or run `go get -u github.com/phoreproject/openbazaar-go`. +You can either pull in remote changes as normal or run `go get -u github.com/phoreproject/pm-go`. ## Usage -You can run the server with `go run openbazaard.go start`. Ensure you are using at least version `1.10` of Golang, otherwise you might get errors while running. +You can run the server with `go run marketplaced.go start`. Ensure you are using at least version `1.10` of Golang, otherwise you might get errors while running. ### Options @@ -68,8 +76,7 @@ Help Options: -p, --password= the encryption password if the database is encrypted -t, --testnet use the test network -r, --regtest run in regression test mode - -l, --loglevel= set the logging level [debug, info, notice, warning, error, critical] - (default: debug) + -l, --loglevel= set the logging level [debug, info, notice, warning, error, critical] (default: debug) -f, --nologfiles save logs on disk -a, --allowip= only allow API connections from these IPs -s, --stun use stun on µTP IPv4 @@ -77,31 +84,26 @@ Help Options: -c, --authcookie= turn on API authentication and use this specific cookie -u, --useragent= add a custom user-agent field -v, --verbose print openbazaar logs to stdout - --torpassword= Set the tor control password. This will override the tor password in - the config. - --tor Automatically configure the daemon to run as a Tor hidden service and - use Tor exclusively. Requires Tor to be running. - --dualstack Automatically configure the daemon to run as a Tor hidden service IN - ADDITION to using the clear internet. Requires Tor to be running. - WARNING: this mode is not private + --torpassword= Set the tor control password. This will override the tor password in the config. + --tor Automatically configure the daemon to run as a Tor hidden service and use Tor exclusively. Requires + Tor to be running. + --dualstack Automatically configure the daemon to run as a Tor hidden service IN ADDITION to using the clear + internet. Requires Tor to be running. WARNING: this mode is not private --disablewallet disable the wallet functionality of the node --disableexchangerates disable the exchange rate service to prevent api queries - --storage= set the outgoing message storage option [self-hosted, dropbox] - (default=self-hosted) - --bitcoincash use a Bitcoin Cash wallet in a dedicated data directory - --zcash= use a ZCash wallet in a dedicated data directory. To use this you must - pass in the location of the zcashd binary. + --storage= set the outgoing message storage option [self-hosted, dropbox] default=self-hosted + --forcekeypurge repair test for issue OpenBazaar/openbazaar-go#1593; use as instructed only ``` ## Documentation Documentation of the OpenBazaar protocol has not been formalized yet. If you would like to help, please reach out on [Slack](https://openbazaar.org/slack/) or via a new issue on GitHub. -`openbazaar-go` exposes an HTTP API which permits high-level interactions on the network and the internal wallet. Find the HTTP API documentation at [https://api.docs.openbazaar.org](https://api.docs.openbazaar.org). +`marketplace-go` exposes an HTTP API which permits high-level interactions on the network and the internal wallet. Find the HTTP API documentation at [https://api.docs.openbazaar.org](https://api.docs.openbazaar.org). ## Contributing -Contributions are definitely welcome! Please read the Contributing [Guidelines](https://github.com/phoreproject/openbazaar-go/blob/master/CONTRIBUTING.md) before starting. +Contributions are definitely welcome! Please read the Contributing [Guidelines](https://github.com/phoreproject/pm-go/blob/master/CONTRIBUTING.md) before starting. ## License -[MIT](https://github.com/phoreproject/openbazaar-go/blob/master/LICENSE). +[MIT](https://github.com/phoreproject/pm-go/blob/master/LICENSE). diff --git a/api/endpoints.go b/api/endpoints.go index 6c0aa4073e..488db3c70e 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -36,7 +36,7 @@ func post(i *jsonAPIHandler, path string, w http.ResponseWriter, r *http.Request case strings.HasPrefix(path, "/ob/images"): i.POSTImage(w, r) case strings.HasPrefix(path, "/wallet/spend"): - i.POSTSpendCoins(w, r) + checkWalletRequest(i, path, w, r, i.POSTSpendCoins) case strings.HasPrefix(path, "/ob/settings"): i.POSTSettings(w, r) case strings.HasPrefix(path, "/ob/inventory"): @@ -58,9 +58,9 @@ func post(i *jsonAPIHandler, path string, w http.ResponseWriter, r *http.Request case strings.HasPrefix(path, "/ob/refund"): blockingStartupMiddleware(i, w, r, i.POSTRefund) case strings.HasPrefix(path, "/wallet/resyncblockchain"): - i.POSTResyncBlockchain(w, r) + checkWalletRequest(i, path, w, r, i.POSTResyncBlockchain) case strings.HasPrefix(path, "/wallet/bumpfee"): - i.POSTBumpFee(w, r) + checkWalletRequest(i, path, w, r, i.POSTBumpFee) case strings.HasPrefix(path, "/ob/opendispute"): blockingStartupMiddleware(i, w, r, i.POSTOpenDispute) case strings.HasPrefix(path, "/ob/closedispute"): @@ -91,6 +91,8 @@ func post(i *jsonAPIHandler, path string, w http.ResponseWriter, r *http.Request i.POSTShutdown(w, r) case strings.HasPrefix(path, "/ob/estimatetotal"): i.POSTEstimateTotal(w, r) + case strings.HasPrefix(path, "/ob/checkoutbreakdown"): + i.POSTCheckoutBreakdown(w, r) case strings.HasPrefix(path, "/ob/fetchratings"): i.POSTFetchRatings(w, r) case strings.HasPrefix(path, "/ob/sales"): @@ -113,6 +115,26 @@ func post(i *jsonAPIHandler, path string, w http.ResponseWriter, r *http.Request i.POSTPost(w, r) case strings.HasPrefix(path, "/ob/bulkupdatecurrency"): i.POSTBulkUpdateCurrency(w, r) + case strings.HasPrefix(path, "/ob/bulkupdatetermsandconditions"): + i.POSTBulkUpdateTerms(w, r) + case strings.HasPrefix(path, "/ob/bulkupdaterefundpolicy"): + i.POSTBulkUpdateRefundPolicy(w, r) + case strings.HasPrefix(path, "/ob/bulkupdatereturnpolicy"): + i.POSTBulkUpdateRefundPolicy(w, r) + case strings.HasPrefix(path, "/ob/bulkupdateshippingoptions"): + i.POSTBulkUpdateShippingDetails(w, r) + case strings.HasPrefix(path, "/ob/resendordermessage"): + i.POSTResendOrderMessage(w, r) + case strings.HasPrefix(path, "/manage/initwallet"): + i.POSTInitWallet(w, r) + case strings.HasPrefix(path, "/manage/unlockwallet"): + i.POSTUnlockWallet(w, r) + case strings.HasPrefix(path, "/manage/lockwallet"): + i.POSTLockWallet(w, r) + case strings.HasPrefix(path, "/ob/hashmessage"): + i.POSTHashMessage(w, r) + case strings.HasPrefix(path, "/ob/bulkupdateprices"): + i.POSTBulkUpdatePrices(w, r) default: ErrorResponse(w, http.StatusNotFound, "Not Found") } @@ -127,6 +149,8 @@ func get(i *jsonAPIHandler, path string, w http.ResponseWriter, r *http.Request) i.GETPeers(w, r) case strings.HasPrefix(path, "/ob/config"): i.GETConfig(w, r) + case strings.HasPrefix(path, "/wallet/currencies"): + i.GETWalletCurrencyDictionary(w, r) case strings.HasPrefix(path, "/wallet/address"): i.GETAddress(w, r) case strings.HasPrefix(path, "/wallet/mnemonic"): @@ -195,12 +219,18 @@ func get(i *jsonAPIHandler, path string, w http.ResponseWriter, r *http.Request) i.GETWalletStatus(w, r) case strings.HasPrefix(path, "/ob/ipns"): i.GETIPNS(w, r) + case strings.HasPrefix(path, "/ob/resolveipns"): + i.GETResolveIPNS(w, r) case strings.HasPrefix(path, "/ob/peerinfo"): i.GETPeerInfo(w, r) case strings.HasPrefix(path, "/ob/posts"): i.GETPosts(w, r) case strings.HasPrefix(path, "/ob/post"): i.GETPost(w, r) + case strings.HasPrefix(path, "/ob/scanofflinemessages"): + i.GETScanOfflineMessages(w, r) + case strings.HasPrefix(path, "/manage/iswalletlocked"): + i.GETIsWalletLocked(w, r) default: ErrorResponse(w, http.StatusNotFound, "Not Found") } @@ -257,6 +287,16 @@ func gatewayAllowedPath(path, method string) bool { return false } +func checkWalletRequest(i *jsonAPIHandler, path string, w http.ResponseWriter, r *http.Request, requestFunc func(w http.ResponseWriter, r *http.Request)) { + if i.node.IsWalletLocked() { + log.Errorf("Request to %s 403", path) + ErrorResponse(w, http.StatusPreconditionFailed, "Unlock wallet first.") + return + } + + requestFunc(w, r) +} + func blockingStartupMiddleware(i *jsonAPIHandler, w http.ResponseWriter, r *http.Request, requestFunc func(w http.ResponseWriter, r *http.Request)) { i.node.Service.WaitForReady() requestFunc(w, r) diff --git a/api/gateway.go b/api/gateway.go index 82d0c8c1b2..2689e381ad 100644 --- a/api/gateway.go +++ b/api/gateway.go @@ -1,22 +1,22 @@ package api import ( - "net" - "net/http" - "github.com/ipfs/go-ipfs/core/corehttp" "github.com/op/go-logging" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/schema" + "net" + "net/http" ) var log = logging.MustGetLogger("api") // Gateway represents an HTTP API gateway type Gateway struct { - listener net.Listener - handler http.Handler - config schema.APIConfig + listener net.Listener + handler http.Handler + config schema.APIConfig + gatewayRunning chan error } // NewGateway instantiates a new `Gateway` @@ -31,6 +31,7 @@ func NewGateway(n *core.OpenBazaarNode, authCookie http.Cookie, l net.Listener, topMux.Handle("/ob/", jsonAPI) topMux.Handle("/wallet/", jsonAPI) + topMux.Handle("/manage/", jsonAPI) topMux.Handle("/ws", wsAPI) var ( @@ -58,7 +59,7 @@ func (g *Gateway) Close() error { } // Serve begins listening on the configured address -func (g *Gateway) Serve() error { +func (g *Gateway) serve() error { var err error if g.config.SSL { err = http.ListenAndServeTLS(g.listener.Addr().String(), g.config.SSLCert, g.config.SSLKey, g.handler) @@ -67,3 +68,23 @@ func (g *Gateway) Serve() error { } return err } + +func (g *Gateway) Serve(blocking bool) error { + if g.gatewayRunning == nil { + g.gatewayRunning = make(chan error) + go func() { + err := g.serve() + if err != nil { + g.gatewayRunning <- err + } else { + g.gatewayRunning <- nil + } + }() + } + + if blocking { + return <-g.gatewayRunning + } + + return nil +} diff --git a/api/jsonapi.go b/api/jsonapi.go index f2aa9e9629..3e423390f7 100644 --- a/api/jsonapi.go +++ b/api/jsonapi.go @@ -8,9 +8,8 @@ import ( "encoding/hex" "encoding/json" "fmt" - "gx/ipfs/QmQmhotPUzVrMEWNK3x1R5jQ5ZHWyL7tVUrmRPjrBrvyCb/go-ipfs-files" - "gx/ipfs/QmXLwxifxwfc2bAwq6rdjbYqAsGzWsDE9RM5TWMGtykyj6/interface-go-ipfs-core" "io/ioutil" + "math/big" "net/http" "net/http/httputil" "net/url" @@ -24,10 +23,14 @@ import ( "time" ipnspath "gx/ipfs/QmQAgv6Gaoe2tQpcabqwKXKChp2MZ7i3UXv9DqTTaxCaTR/go-path" - cid "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" - datastore "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" - peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + "gx/ipfs/QmQmhotPUzVrMEWNK3x1R5jQ5ZHWyL7tVUrmRPjrBrvyCb/go-ipfs-files" + "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" + "gx/ipfs/QmUwMnKKjH3JwGKNVZ3TcP37W93xzqNA4ECFFiMo6sXkkc/go-ipns" + "gx/ipfs/QmXLwxifxwfc2bAwq6rdjbYqAsGzWsDE9RM5TWMGtykyj6/interface-go-ipfs-core" + "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + "gx/ipfs/QmYxUdYY9S6yg5tSPVin5GFTvtfsLauVcr7reHDD3dM8xf/go-libp2p-routing" ps "gx/ipfs/QmaCTz9RkrU13bm9kMB54f7atgqM4qkjDZpRwRoJiWXEqs/go-libp2p-peerstore" + ggproto "gx/ipfs/QmddjPSGZb3ieihSseFeCfVRpZzcqczPNsD2DvarSwnjJB/gogo-protobuf/proto" mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" "github.com/OpenBazaar/jsonpb" @@ -37,14 +40,14 @@ import ( "github.com/btcsuite/btcutil/base58" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" + ipfscore "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/coreapi" - "github.com/ipfs/go-ipfs/namesys" "github.com/ipfs/go-ipfs/repo/fsrepo" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/schema" ) type JSONAPIConfig struct { @@ -63,6 +66,15 @@ type jsonAPIHandler struct { node *core.OpenBazaarNode } +type APIError struct { + Success bool `json:"success"` + Reason string `json:"reason"` +} + +var lastManualScan time.Time + +const OfflineMessageScanInterval = 1 * time.Minute + func newJSONAPIHandler(node *core.OpenBazaarNode, authCookie http.Cookie, config schema.APIConfig) *jsonAPIHandler { allowedIPs := make(map[string]bool) for _, ip := range config.AllowedIPs { @@ -183,10 +195,6 @@ func (i *jsonAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func ErrorResponse(w http.ResponseWriter, errorCode int, reason string) { - type APIError struct { - Success bool `json:"success"` - Reason string `json:"reason"` - } reason = strings.Replace(reason, `"`, `'`, -1) err := APIError{false, reason} resp, _ := json.MarshalIndent(err, "", " ") @@ -510,16 +518,15 @@ func (i *jsonAPIHandler) POSTImage(w http.ResponseWriter, r *http.Request) { } func (i *jsonAPIHandler) POSTListing(w http.ResponseWriter, r *http.Request) { - ld := new(pb.Listing) - err := jsonpb.Unmarshal(r.Body, ld) + + listingData, err := ioutil.ReadAll(r.Body) if err != nil { - ErrorResponse(w, http.StatusBadRequest, err.Error()) + ErrorResponse(w, http.StatusConflict, err.Error()) return } - - err = i.node.CreateListing(ld) + slug, err := i.node.CreateListing(listingData) if err != nil { - if err == core.ErrListingAlreadyExists { + if err == repo.ErrListingAlreadyExists { ErrorResponse(w, http.StatusConflict, "Listing already exists. Use PUT.") return } @@ -528,20 +535,18 @@ func (i *jsonAPIHandler) POSTListing(w http.ResponseWriter, r *http.Request) { return } - SanitizedResponse(w, fmt.Sprintf(`{"slug": "%s"}`, ld.Slug)) + SanitizedResponse(w, fmt.Sprintf(`{"slug": "%s"}`, slug)) } func (i *jsonAPIHandler) PUTListing(w http.ResponseWriter, r *http.Request) { - ld := new(pb.Listing) - err := jsonpb.Unmarshal(r.Body, ld) + listingData, err := ioutil.ReadAll(r.Body) if err != nil { - ErrorResponse(w, http.StatusBadRequest, err.Error()) + ErrorResponse(w, http.StatusConflict, err.Error()) return } - - err = i.node.UpdateListing(ld, true) + err = i.node.UpdateListing(listingData, true) if err != nil { - if err == core.ErrListingDoesNotExist { + if err == repo.ErrListingDoesNotExist { ErrorResponse(w, http.StatusNotFound, "Listing not found.") return } @@ -580,7 +585,7 @@ func (i *jsonAPIHandler) DELETEListing(w http.ResponseWriter, r *http.Request) { func (i *jsonAPIHandler) POSTPurchase(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) - var data core.PurchaseData + var data repo.PurchaseData err := decoder.Decode(&data) if err != nil { ErrorResponse(w, http.StatusBadRequest, err.Error()) @@ -592,10 +597,10 @@ func (i *jsonAPIHandler) POSTPurchase(w http.ResponseWriter, r *http.Request) { return } type purchaseReturn struct { - PaymentAddress string `json:"paymentAddress"` - Amount uint64 `json:"amount"` - VendorOnline bool `json:"vendorOnline"` - OrderID string `json:"orderId"` + PaymentAddress string `json:"paymentAddress"` + Amount *repo.CurrencyValue `json:"amount"` + VendorOnline bool `json:"vendorOnline"` + OrderID string `json:"orderId"` } ret := purchaseReturn{paymentAddr, amount, online, orderID} b, err := json.MarshalIndent(ret, "", " ") @@ -667,6 +672,36 @@ func (i *jsonAPIHandler) POSTUnfollow(w http.ResponseWriter, r *http.Request) { SanitizedResponse(w, `{}`) } +var allCurrencyMapCache map[string]repo.CurrencyDefinition + +func (i *jsonAPIHandler) GETWalletCurrencyDictionary(w http.ResponseWriter, r *http.Request) { + var ( + resp map[string]repo.CurrencyDefinition + _, lookup = path.Split(r.URL.Path) + ) + if lookup == "currencies" { + if allCurrencyMapCache == nil { + allCurrencyMapCache = repo.AllCurrencies().AsMap() + } + resp = allCurrencyMapCache + } else { + var upperLookup = strings.ToUpper(lookup) + def, err := i.node.LookupCurrency(upperLookup) + if err != nil { + ErrorResponse(w, http.StatusNotFound, fmt.Sprintf("unknown definition for %s", lookup)) + return + } + resp = map[string]repo.CurrencyDefinition{upperLookup: def} + } + out, err := json.MarshalIndent(resp, "", " ") + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + SanitizedResponse(w, string(out)) +} + func (i *jsonAPIHandler) GETAddress(w http.ResponseWriter, r *http.Request) { _, coinType := path.Split(r.URL.Path) if coinType == "address" { @@ -688,31 +723,45 @@ func (i *jsonAPIHandler) GETAddress(w http.ResponseWriter, r *http.Request) { return } addr := wal.CurrentAddress(wallet.EXTERNAL) - SanitizedResponse(w, fmt.Sprintf(`{"address": "%s"}`, addr.EncodeAddress())) + SanitizedResponse(w, fmt.Sprintf(`{"address": "%s"}`, addr.String())) } func (i *jsonAPIHandler) GETMnemonic(w http.ResponseWriter, r *http.Request) { - mn, err := i.node.Datastore.Config().GetMnemonic() + mnemonic, isEncrypted, err := i.node.Datastore.Config().GetMnemonic() if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - SanitizedResponse(w, fmt.Sprintf(`{"mnemonic": "%s"}`, mn)) + if isEncrypted { + mnemonic = hex.EncodeToString([]byte(mnemonic)) + } + SanitizedResponse(w, fmt.Sprintf(`{"mnemonic": "%s", "isEncrypted": "%s"}`, mnemonic, strconv.FormatBool(isEncrypted))) } func (i *jsonAPIHandler) GETBalance(w http.ResponseWriter, r *http.Request) { _, coinType := path.Split(r.URL.Path) type balance struct { - Confirmed int64 `json:"confirmed"` - Unconfirmed int64 `json:"unconfirmed"` - Height uint32 `json:"height"` + Confirmed string `json:"confirmed"` + Unconfirmed string `json:"unconfirmed"` + Currency repo.CurrencyDefinition `json:"currency"` + Height uint32 `json:"height"` } if coinType == "balance" { ret := make(map[string]interface{}) for ct, wal := range i.node.Multiwallet { height, _ := wal.ChainTip() + defn, err := i.node.LookupCurrency(ct.CurrencyCode()) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } confirmed, unconfirmed := wal.Balance() - ret[ct.CurrencyCode()] = balance{Confirmed: confirmed, Unconfirmed: unconfirmed, Height: height} + ret[ct.CurrencyCode()] = balance{ + Confirmed: confirmed.Value.String(), + Unconfirmed: unconfirmed.Value.String(), + Currency: defn, + Height: height, + } } out, err := json.MarshalIndent(ret, "", " ") if err != nil { @@ -722,14 +771,25 @@ func (i *jsonAPIHandler) GETBalance(w http.ResponseWriter, r *http.Request) { SanitizedResponse(w, string(out)) return } + wal, err := i.node.Multiwallet.WalletForCurrencyCode(coinType) if err != nil { - ErrorResponse(w, http.StatusBadRequest, "Unknown wallet type") + ErrorResponse(w, http.StatusBadRequest, "unknown wallet type") return } height, _ := wal.ChainTip() confirmed, unconfirmed := wal.Balance() - bal := balance{Confirmed: confirmed, Unconfirmed: unconfirmed, Height: height} + defn, err := i.node.LookupCurrency(coinType) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + bal := balance{ + Confirmed: confirmed.Value.String(), + Unconfirmed: unconfirmed.Value.String(), + Currency: defn, + Height: height, + } out, err := json.MarshalIndent(bal, "", " ") if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) @@ -759,11 +819,17 @@ func (i *jsonAPIHandler) POSTSpendCoinsForOrder(w http.ResponseWriter, r *http.R return } + err = i.node.SendOrderPayment(result) + if err != nil { + log.Errorf("error sending order with id %s payment: %v", result.OrderID, err) + } + ser, err := json.MarshalIndent(result, "", " ") if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return } + SanitizedResponse(w, string(ser)) } @@ -852,12 +918,17 @@ func (i *jsonAPIHandler) POSTSettings(w http.ResponseWriter, r *http.Request) { continue } blockedIds = append(blockedIds, id) + i.node.Service.DisconnectFromPeer(id) } i.node.BanManager.SetBlockedIds(blockedIds) } if settings.StoreModerators != nil { modsToAdd, modsToDelete := extractModeratorChanges(*settings.StoreModerators, nil) - go i.node.NotifyModerators(modsToAdd, modsToDelete) + go func(modsToAdd, modsToDelete []string) { + if err := i.node.NotifyModerators(modsToAdd, modsToDelete); err != nil { + log.Error(err) + } + }(modsToAdd, modsToDelete) if err := i.node.SetModeratorsOnListings(*settings.StoreModerators); err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) } @@ -908,12 +979,17 @@ func (i *jsonAPIHandler) PUTSettings(w http.ResponseWriter, r *http.Request) { continue } blockedIds = append(blockedIds, id) + i.node.Service.DisconnectFromPeer(id) } i.node.BanManager.SetBlockedIds(blockedIds) } if settings.StoreModerators != nil { modsToAdd, modsToDelete := extractModeratorChanges(*settings.StoreModerators, currentSettings.StoreModerators) - go i.node.NotifyModerators(modsToAdd, modsToDelete) + go func(modsToAdd, modsToDelete []string) { + if err := i.node.NotifyModerators(modsToAdd, modsToDelete); err != nil { + log.Error(err) + } + }(modsToAdd, modsToDelete) if err := i.node.SetModeratorsOnListings(*settings.StoreModerators); err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) } @@ -971,15 +1047,10 @@ func (i *jsonAPIHandler) PATCHSettings(w http.ResponseWriter, r *http.Request) { ErrorResponse(w, http.StatusBadRequest, err.Error()) return } - if settings.StoreModerators != nil { - modsToAdd, modsToDelete := extractModeratorChanges(*settings.StoreModerators, currentSettings.StoreModerators) - go i.node.NotifyModerators(modsToAdd, modsToDelete) - if err := i.node.SetModeratorsOnListings(*settings.StoreModerators); err != nil { - ErrorResponse(w, http.StatusInternalServerError, err.Error()) - } - if err := i.node.SeedNode(); err != nil { - ErrorResponse(w, http.StatusInternalServerError, err.Error()) - } + err = i.node.Datastore.Settings().Update(settings) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return } if settings.BlockedNodes != nil { var blockedIds []peer.ID @@ -989,13 +1060,25 @@ func (i *jsonAPIHandler) PATCHSettings(w http.ResponseWriter, r *http.Request) { continue } blockedIds = append(blockedIds, id) + i.node.Service.DisconnectFromPeer(id) } i.node.BanManager.SetBlockedIds(blockedIds) } - err = i.node.Datastore.Settings().Update(settings) - if err != nil { - ErrorResponse(w, http.StatusInternalServerError, err.Error()) - return + if settings.StoreModerators != nil { + modsToAdd, modsToDelete := extractModeratorChanges(*settings.StoreModerators, currentSettings.StoreModerators) + if err := i.node.SetModeratorsOnListings(*settings.StoreModerators); err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + if err := i.node.SeedNode(); err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + go func(modsToAdd, modsToDelete []string) { + if err := i.node.NotifyModerators(modsToAdd, modsToDelete); err != nil { + log.Error(err) + } + }(modsToAdd, modsToDelete) } SanitizedResponse(w, `{}`) } @@ -1044,7 +1127,12 @@ func (i *jsonAPIHandler) GETExchangeRate(w http.ResponseWriter, r *http.Request) SanitizedResponse(w, string(exchangeRateJSON)) } else { - rate, err := wal.ExchangeRates().GetExchangeRate(core.NormalizeCurrencyCode(currencyCode)) + def, err := i.node.LookupCurrency(currencyCode) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + rate, err := wal.ExchangeRates().GetExchangeRate(def.CurrencyCode().String()) if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return @@ -1236,7 +1324,7 @@ func (i *jsonAPIHandler) POSTInventory(w http.ResponseWriter, r *http.Request) { type inv struct { Slug string `json:"slug"` Variant int `json:"variant"` - Quantity int64 `json:"quantity"` + Quantity string `json:"quantity"` } decoder := json.NewDecoder(r.Body) var invList []inv @@ -1246,7 +1334,12 @@ func (i *jsonAPIHandler) POSTInventory(w http.ResponseWriter, r *http.Request) { return } for _, in := range invList { - err = i.node.Datastore.Inventory().Put(in.Slug, in.Variant, in.Quantity) + q, ok := new(big.Int).SetString(in.Quantity, 10) + if !ok { + ErrorResponse(w, http.StatusBadRequest, "error parsing quantity") + return + } + err = i.node.Datastore.Inventory().Put(in.Slug, in.Variant, q) if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return @@ -1355,8 +1448,20 @@ func (i *jsonAPIHandler) GETListings(w http.ResponseWriter, r *http.Request) { ErrorResponse(w, http.StatusNotFound, err.Error()) return } + normalizedIndex, err := repo.UnmarshalJSONSignedListingIndex(listingsBytes) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to parse listing index: %s", err.Error())) + return + } + + normalizedBytes, err := json.MarshalIndent(normalizedIndex, "", " ") + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to normalize listing index: %s", err.Error())) + return + } + w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%s, immutable", maxAge)) - SanitizedResponse(w, string(listingsBytes)) + SanitizedResponse(w, string(normalizedBytes)) } } @@ -1364,12 +1469,6 @@ func (i *jsonAPIHandler) GETListing(w http.ResponseWriter, r *http.Request) { urlPath, listingID := path.Split(r.URL.Path) _, peerID := path.Split(urlPath[:len(urlPath)-1]) useCache, _ := strconv.ParseBool(r.URL.Query().Get("usecache")) - m := jsonpb.Marshaler{ - EnumsAsInts: false, - EmitDefaults: false, - Indent: " ", - OrigName: false, - } if peerID == "" || strings.ToLower(peerID) == "listing" || peerID == i.node.IPFSIdentityString() { var sl *pb.SignedListing _, err := cid.Decode(listingID) @@ -1394,22 +1493,23 @@ func (i *jsonAPIHandler) GETListing(w http.ResponseWriter, r *http.Request) { sl.Hash = hash } - savedCoupons, err := i.node.Datastore.Coupons().Get(sl.Listing.Slug) - if err != nil { - return + rsl := repo.NewSignedListingFromProtobuf(sl) + + if err := rsl.GetListing().UpdateCouponsFromDatastore(i.node.Datastore.Coupons()); err != nil { + log.Warningf("updating coupons for listing (%s): %s", rsl.GetSlug(), err.Error()) } - err = core.AssignMatchingCoupons(savedCoupons, sl) - if err != nil { - ErrorResponse(w, http.StatusNotFound, "Could not apply coupons to listing.") + + if err := rsl.Normalize(); err != nil { + ErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("normalizing listing: %s", err.Error())) return } - out, err := m.MarshalToString(sl) + out, err := rsl.MarshalJSON() if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - SanitizedResponseM(w, out, new(pb.SignedListing)) + SanitizedResponseM(w, string(out), new(pb.SignedListing)) return } @@ -1444,12 +1544,20 @@ func (i *jsonAPIHandler) GETListing(w http.ResponseWriter, r *http.Request) { return } sl.Hash = hash - out, err := m.MarshalToString(sl) + + rsl := repo.NewSignedListingFromProtobuf(sl) + + if err := rsl.Normalize(); err != nil { + ErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("normalizing listing: %s", err.Error())) + return + } + + out, err := rsl.MarshalJSON() if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - SanitizedResponseM(w, out, new(pb.SignedListing)) + SanitizedResponseM(w, string(out), new(pb.SignedListing)) } func (i *jsonAPIHandler) GETProfile(w http.ResponseWriter, r *http.Request) { @@ -1475,7 +1583,7 @@ func (i *jsonAPIHandler) GETProfile(w http.ResponseWriter, r *http.Request) { return } if profile.PeerID != peerID { - ErrorResponse(w, http.StatusNotFound, "") + ErrorResponse(w, http.StatusNotFound, "invalid profile: peer id mismatch on found profile") return } w.Header().Set("Cache-Control", "public, max-age=600, immutable") @@ -1516,18 +1624,26 @@ func (i *jsonAPIHandler) POSTOrderConfirmation(w http.ResponseWriter, r *http.Re ErrorResponse(w, http.StatusBadRequest, err.Error()) return } - contract, state, funded, records, _, paymentCoin, err := i.node.Datastore.Sales().GetByOrderId(conf.OrderID) + + order, err := i.node.GetOrder(conf.OrderID) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + v5contract := order.Contract + + contract, state, funded, records, _, _, err := i.node.Datastore.Sales().GetByOrderId(conf.OrderID) if err != nil { ErrorResponse(w, http.StatusNotFound, err.Error()) return } // TODO: Remove once broken contracts are migrated - lookupCoin := contract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(lookupCoin) + lookupCoin := v5contract.BuyerOrder.Payment.AmountCurrency.Code + _, err = i.node.LookupCurrency(lookupCoin) if err != nil { log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", lookupCoin, conf.OrderID) - contract.BuyerOrder.Payment.Coin = paymentCoin.String() + //contract.BuyerOrder.Payment.Coin = paymentCoin.String() } if state != pb.OrderState_PENDING { @@ -1539,7 +1655,7 @@ func (i *jsonAPIHandler) POSTOrderConfirmation(w http.ResponseWriter, r *http.Re return } if !conf.Reject { - err := i.node.ConfirmOfflineOrder(contract, records) + err := i.node.ConfirmOfflineOrder(state, contract, records) if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return @@ -1565,18 +1681,23 @@ func (i *jsonAPIHandler) POSTOrderCancel(w http.ResponseWriter, r *http.Request) ErrorResponse(w, http.StatusBadRequest, err.Error()) return } - contract, state, _, records, _, paymentCoin, err := i.node.Datastore.Purchases().GetByOrderId(can.OrderID) + contract, state, _, records, _, _, err := i.node.Datastore.Purchases().GetByOrderId(can.OrderID) + if err != nil { + ErrorResponse(w, http.StatusNotFound, "order not found") + return + } + v5order, err := repo.ToV5Order(contract.BuyerOrder, nil) if err != nil { ErrorResponse(w, http.StatusNotFound, "order not found") return } // TODO: Remove once broken contracts are migrated - lookupCoin := contract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(lookupCoin) + lookupCoin := v5order.Payment.AmountCurrency.Code + _, err = i.node.LookupCurrency(lookupCoin) if err != nil { log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", lookupCoin, can.OrderID) - contract.BuyerOrder.Payment.Coin = paymentCoin.String() + //contract.BuyerOrder.Payment.Coin = paymentCoin.String() } if !((state == pb.OrderState_PENDING || state == pb.OrderState_PROCESSING_ERROR) && len(records) > 0) || !(state == pb.OrderState_PENDING || state == pb.OrderState_PROCESSING_ERROR) || contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED { @@ -1617,53 +1738,11 @@ func (i *jsonAPIHandler) POSTResyncBlockchain(w http.ResponseWriter, r *http.Req func (i *jsonAPIHandler) GETOrder(w http.ResponseWriter, r *http.Request) { _, orderID := path.Split(r.URL.Path) - var ( - err error - isSale bool - contract *pb.RicardianContract - state pb.OrderState - funded bool - records []*wallet.TransactionRecord - read bool - paymentCoin *repo.CurrencyCode - ) - contract, state, funded, records, read, paymentCoin, err = i.node.Datastore.Purchases().GetByOrderId(orderID) - if err != nil { - contract, state, funded, records, read, paymentCoin, err = i.node.Datastore.Sales().GetByOrderId(orderID) - if err != nil { - ErrorResponse(w, http.StatusNotFound, "Order not found") - return - } - isSale = true - } - resp := new(pb.OrderRespApi) - resp.Contract = contract - resp.Funded = funded - resp.Read = read - resp.State = state - - // TODO: Remove once broken contracts are migrated - lookupCoin := contract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(lookupCoin) - if err != nil { - log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", lookupCoin, orderID) - contract.BuyerOrder.Payment.Coin = paymentCoin.String() - } - - paymentTxs, refundTx, err := i.node.BuildTransactionRecords(contract, records, state) + resp, err := i.node.GetOrder(orderID) if err != nil { - ErrorResponse(w, http.StatusInternalServerError, err.Error()) - return - } - resp.PaymentAddressTransactions = paymentTxs - resp.RefundAddressTransaction = refundTx - - unread, err := i.node.Datastore.Chat().GetUnreadCount(orderID) - if err != nil { - ErrorResponse(w, http.StatusInternalServerError, err.Error()) + ErrorResponse(w, http.StatusNotFound, "Order not found") return } - resp.UnreadChatMessages = uint64(unread) m := jsonpb.Marshaler{ EnumsAsInts: false, @@ -1676,11 +1755,7 @@ func (i *jsonAPIHandler) GETOrder(w http.ResponseWriter, r *http.Request) { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - if isSale { - i.node.Datastore.Sales().MarkAsRead(orderID) - } else { - i.node.Datastore.Purchases().MarkAsRead(orderID) - } + SanitizedResponseM(w, out, new(pb.OrderRespApi)) } @@ -1712,7 +1787,7 @@ func (i *jsonAPIHandler) POSTRefund(w http.ResponseWriter, r *http.Request) { ErrorResponse(w, http.StatusBadRequest, err.Error()) return } - contract, state, _, records, _, paymentCoin, err := i.node.Datastore.Sales().GetByOrderId(can.OrderID) + contract, state, _, records, _, _, err := i.node.Datastore.Sales().GetByOrderId(can.OrderID) if err != nil { ErrorResponse(w, http.StatusNotFound, "order not found") return @@ -1723,11 +1798,18 @@ func (i *jsonAPIHandler) POSTRefund(w http.ResponseWriter, r *http.Request) { } // TODO: Remove once broken contracts are migrated - lookupCoin := contract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(lookupCoin) + order, err := i.node.GetOrder(can.OrderID) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + v5contract := order.Contract + + lookupCoin := v5contract.BuyerOrder.Payment.AmountCurrency.Code + _, err = i.node.LookupCurrency(lookupCoin) if err != nil { log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", lookupCoin, can.OrderID) - contract.BuyerOrder.Payment.Coin = paymentCoin.String() + //contract.BuyerOrder.Payment.Coin = paymentCoin.String() } err = i.node.RefundOrder(contract, records) @@ -1764,7 +1846,7 @@ func (i *jsonAPIHandler) GETModerators(w http.ResponseWriter, r *http.Request) { } var mods []string for _, p := range peerInfoList { - id, err := core.ExtractIDFromPointer(p) + id, err := ipfs.ExtractIDFromPointer(p) if err != nil { continue } @@ -1832,7 +1914,12 @@ func (i *jsonAPIHandler) GETModerators(w http.ResponseWriter, r *http.Request) { id := r.URL.Query().Get("asyncID") if id == "" { idBytes := make([]byte, 16) - rand.Read(idBytes) + _, err := rand.Read(idBytes) + if err != nil { + // TODO: if this happens, len(idBytes) != 16 + // how to handle this + log.Error(err) + } id = base58.Encode(idBytes) } @@ -1850,7 +1937,7 @@ func (i *jsonAPIHandler) GETModerators(w http.ResponseWriter, r *http.Request) { foundMu := sync.Mutex{} for p := range peerChan { go func(pi ps.PeerInfo) { - pid, err := core.ExtractIDFromPointer(pi) + pid, err := ipfs.ExtractIDFromPointer(pi) if err != nil { return } @@ -1884,7 +1971,7 @@ func (i *jsonAPIHandler) GETModerators(w http.ResponseWriter, r *http.Request) { if err != nil { return } - i.node.Broadcast <- repo.PremarshalledNotifier{b} + i.node.Broadcast <- repo.PremarshalledNotifier{Payload: b} } else { type wsResp struct { ID string `json:"id"` @@ -1895,7 +1982,7 @@ func (i *jsonAPIHandler) GETModerators(w http.ResponseWriter, r *http.Request) { if err != nil { return } - i.node.Broadcast <- repo.PremarshalledNotifier{data} + i.node.Broadcast <- repo.PremarshalledNotifier{Payload: data} } }(p) } @@ -1911,18 +1998,25 @@ func (i *jsonAPIHandler) POSTOrderFulfill(w http.ResponseWriter, r *http.Request ErrorResponse(w, http.StatusBadRequest, err.Error()) return } - contract, state, _, records, _, paymentCoin, err := i.node.Datastore.Sales().GetByOrderId(fulfill.OrderId) + contract, state, _, records, _, _, err := i.node.Datastore.Sales().GetByOrderId(fulfill.OrderId) if err != nil { ErrorResponse(w, http.StatusNotFound, "order not found") return } // TODO: Remove once broken contracts are migrated - lookupCoin := contract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(lookupCoin) + order, err := i.node.GetOrder(fulfill.OrderId) + if err != nil { + ErrorResponse(w, http.StatusNotFound, "order not found") + return + } + v5contract := order.Contract + + lookupCoin := v5contract.BuyerOrder.Payment.AmountCurrency.Code + _, err = i.node.LookupCurrency(lookupCoin) if err != nil { log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", lookupCoin, fulfill.OrderId) - contract.BuyerOrder.Payment.Coin = paymentCoin.String() + //contract.BuyerOrder.Payment.Coin = paymentCoin.String() } if state != pb.OrderState_AWAITING_FULFILLMENT && state != pb.OrderState_PARTIALLY_FULFILLED { @@ -1952,18 +2046,24 @@ func (i *jsonAPIHandler) POSTOrderComplete(w http.ResponseWriter, r *http.Reques ErrorResponse(w, http.StatusBadRequest, err.Error()) return } - contract, state, _, records, _, paymentCoin, err := i.node.Datastore.Purchases().GetByOrderId(or.OrderID) + contract, state, _, records, _, _, err := i.node.Datastore.Purchases().GetByOrderId(or.OrderID) + if err != nil { + ErrorResponse(w, http.StatusNotFound, "order not found") + return + } + + v5order, err := repo.ToV5Order(contract.BuyerOrder, nil) if err != nil { ErrorResponse(w, http.StatusNotFound, "order not found") return } // TODO: Remove once broken contracts are migrated - lookupCoin := contract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(lookupCoin) + lookupCoin := v5order.Payment.AmountCurrency.Code + _, err = i.node.LookupCurrency(lookupCoin) if err != nil { log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", lookupCoin, or.OrderID) - contract.BuyerOrder.Payment.Coin = paymentCoin.String() + //contract.BuyerOrder.Payment.Coin = paymentCoin.String() } if state != pb.OrderState_FULFILLED && @@ -2030,15 +2130,15 @@ func (i *jsonAPIHandler) POSTOpenDispute(w http.ResponseWriter, r *http.Request) return } var ( - isSale bool - contract *pb.RicardianContract - state pb.OrderState - records []*wallet.TransactionRecord - paymentCoin *repo.CurrencyCode + isSale bool + contract *pb.RicardianContract + state pb.OrderState + records []*wallet.TransactionRecord + //paymentCoin *repo.CurrencyCode ) - contract, state, _, records, _, paymentCoin, err = i.node.Datastore.Purchases().GetByOrderId(d.OrderID) + contract, state, _, records, _, _, err = i.node.Datastore.Purchases().GetByOrderId(d.OrderID) if err != nil { - contract, state, _, records, _, paymentCoin, err = i.node.Datastore.Sales().GetByOrderId(d.OrderID) + contract, state, _, records, _, _, err = i.node.Datastore.Sales().GetByOrderId(d.OrderID) if err != nil { ErrorResponse(w, http.StatusNotFound, "Order not found") return @@ -2047,11 +2147,17 @@ func (i *jsonAPIHandler) POSTOpenDispute(w http.ResponseWriter, r *http.Request) } // TODO: Remove once broken contracts are migrated - lookupCoin := contract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(lookupCoin) + v5order, err := repo.ToV5Order(contract.BuyerOrder, nil) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + lookupCoin := v5order.Payment.AmountCurrency.Code + _, err = i.node.LookupCurrency(lookupCoin) if err != nil { log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", lookupCoin, d.OrderID) - contract.BuyerOrder.Payment.Coin = paymentCoin.String() + //contract.BuyerOrder.Payment.Coin = paymentCoin.String() } if contract.BuyerOrder.Payment.Method != pb.Order_Payment_MODERATED { @@ -2130,6 +2236,16 @@ func (i *jsonAPIHandler) GETCase(w http.ResponseWriter, r *http.Request) { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return } + + if buyerContract.BuyerOrder.Payment.BigAmount == "" { + v5order, err := repo.ToV5Order(buyerContract.BuyerOrder, nil) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + buyerContract.BuyerOrder = v5order + } + resp.BuyerContract = buyerContract resp.VendorContract = vendorContract resp.BuyerOpened = buyerOpened @@ -2160,7 +2276,10 @@ func (i *jsonAPIHandler) GETCase(w http.ResponseWriter, r *http.Request) { return } - i.node.Datastore.Cases().MarkAsRead(orderID) + err = i.node.Datastore.Cases().MarkAsRead(orderID) + if err != nil { + log.Error(err) + } SanitizedResponseM(w, out, new(pb.CaseRespApi)) } @@ -2176,26 +2295,32 @@ func (i *jsonAPIHandler) POSTReleaseFunds(w http.ResponseWriter, r *http.Request return } var ( - contract *pb.RicardianContract - state pb.OrderState - records []*wallet.TransactionRecord - paymentCoin *repo.CurrencyCode + contract *pb.RicardianContract + state pb.OrderState + records []*wallet.TransactionRecord + //paymentCoin *repo.CurrencyCode ) - contract, state, _, records, _, paymentCoin, err = i.node.Datastore.Purchases().GetByOrderId(rel.OrderID) + contract, state, _, records, _, _, err = i.node.Datastore.Purchases().GetByOrderId(rel.OrderID) if err != nil { - contract, state, _, records, _, paymentCoin, err = i.node.Datastore.Sales().GetByOrderId(rel.OrderID) + contract, state, _, records, _, _, err = i.node.Datastore.Sales().GetByOrderId(rel.OrderID) if err != nil { ErrorResponse(w, http.StatusNotFound, "Order not found") return } } + v5order, err := repo.ToV5Order(contract.BuyerOrder, nil) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + // TODO: Remove once broken contracts are migrated - lookupCoin := contract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(lookupCoin) + lookupCoin := v5order.Payment.AmountCurrency.Code + _, err = i.node.LookupCurrency(lookupCoin) if err != nil { log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", lookupCoin, rel.OrderID) - contract.BuyerOrder.Payment.Coin = paymentCoin.String() + //contract.BuyerOrder.Payment.Coin = paymentCoin.String() } if state == pb.OrderState_DECIDED { @@ -2216,10 +2341,10 @@ func (i *jsonAPIHandler) POSTReleaseEscrow(w http.ResponseWriter, r *http.Reques rel struct { OrderID string `json:"orderId"` } - contract *pb.RicardianContract - state pb.OrderState - records []*wallet.TransactionRecord - paymentCoin *repo.CurrencyCode + contract *pb.RicardianContract + state pb.OrderState + records []*wallet.TransactionRecord + //paymentCoin *repo.CurrencyCode ) decoder := json.NewDecoder(r.Body) @@ -2229,18 +2354,24 @@ func (i *jsonAPIHandler) POSTReleaseEscrow(w http.ResponseWriter, r *http.Reques return } - contract, state, _, records, _, paymentCoin, err = i.node.Datastore.Sales().GetByOrderId(rel.OrderID) + contract, state, _, records, _, _, err = i.node.Datastore.Sales().GetByOrderId(rel.OrderID) if err != nil { ErrorResponse(w, http.StatusNotFound, "Order not found") return } // TODO: Remove once broken contracts are migrated - lookupCoin := contract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(lookupCoin) + order, err := i.node.GetOrder(rel.OrderID) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, "Could not retrieve the order") + return + } + + lookupCoin := order.Contract.BuyerOrder.Payment.AmountCurrency.Code + _, err = i.node.LookupCurrency(lookupCoin) if err != nil { log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", lookupCoin, rel.OrderID) - contract.BuyerOrder.Payment.Coin = paymentCoin.String() + //contract.BuyerOrder.Payment.Coin = paymentCoin.String() } if state != pb.OrderState_PENDING && state != pb.OrderState_FULFILLED && state != pb.OrderState_DISPUTED { @@ -2551,11 +2682,20 @@ func (i *jsonAPIHandler) POSTMarkChatAsRead(w http.ResponseWriter, r *http.Reque } } if subject != "" { - go func() { - i.node.Datastore.Purchases().MarkAsRead(subject) - i.node.Datastore.Sales().MarkAsRead(subject) - i.node.Datastore.Cases().MarkAsRead(subject) - }() + go func(subject string) { + err := i.node.Datastore.Purchases().MarkAsRead(subject) + if err != nil { + log.Error(err) + } + err = i.node.Datastore.Sales().MarkAsRead(subject) + if err != nil { + log.Error(err) + } + err = i.node.Datastore.Cases().MarkAsRead(subject) + if err != nil { + log.Error(err) + } + }(subject) } SanitizedResponse(w, `{}`) } @@ -2794,7 +2934,12 @@ func (i *jsonAPIHandler) POSTFetchProfiles(w http.ResponseWriter, r *http.Reques id := r.URL.Query().Get("asyncID") if id == "" { idBytes := make([]byte, 16) - rand.Read(idBytes) + _, err := rand.Read(idBytes) + if err != nil { + // TODO: if this happens, len(idBytes) != 16 + // how to handle this + log.Error(err) + } id = base58.Encode(idBytes) } @@ -2819,7 +2964,7 @@ func (i *jsonAPIHandler) POSTFetchProfiles(w http.ResponseWriter, r *http.Reques if err != nil { return } - i.node.Broadcast <- repo.PremarshalledNotifier{ret} + i.node.Broadcast <- repo.PremarshalledNotifier{Payload: ret} } pro, err := i.node.FetchProfile(pid, useCache) @@ -2844,7 +2989,7 @@ func (i *jsonAPIHandler) POSTFetchProfiles(w http.ResponseWriter, r *http.Reques respondWithError("error Marshalling to JSON") return } - i.node.Broadcast <- repo.PremarshalledNotifier{b} + i.node.Broadcast <- repo.PremarshalledNotifier{Payload: b} }(p) } }() @@ -2864,18 +3009,18 @@ func (i *jsonAPIHandler) GETTransactions(w http.ResponseWriter, r *http.Request) } offsetID := r.URL.Query().Get("offsetId") type Tx struct { - Txid string `json:"txid"` - Value int64 `json:"value"` - Address string `json:"address"` - Status string `json:"status"` - ErrorMessage string `json:"errorMessage"` - Memo string `json:"memo"` - Timestamp time.Time `json:"timestamp"` - Confirmations int32 `json:"confirmations"` - Height int32 `json:"height"` - OrderID string `json:"orderId"` - Thumbnail string `json:"thumbnail"` - CanBumpFee bool `json:"canBumpFee"` + Txid string `json:"txid"` + Value string `json:"value"` + Address string `json:"address"` + Status string `json:"status"` + ErrorMessage string `json:"errorMessage"` + Memo string `json:"memo"` + Timestamp *repo.APITime `json:"timestamp"` + Confirmations int32 `json:"confirmations"` + Height int32 `json:"height"` + OrderID string `json:"orderId"` + Thumbnail string `json:"thumbnail"` + CanBumpFee bool `json:"canBumpFee"` } wal, err := i.node.Multiwallet.WalletForCurrencyCode(coinType) if err != nil { @@ -2899,7 +3044,7 @@ func (i *jsonAPIHandler) GETTransactions(w http.ResponseWriter, r *http.Request) tx := Tx{ Txid: t.Txid, Value: t.Value, - Timestamp: t.Timestamp, + Timestamp: repo.NewAPITime(t.Timestamp), Confirmations: int32(t.Confirmations), Height: t.Height, Status: string(t.Status), @@ -2910,7 +3055,7 @@ func (i *jsonAPIHandler) GETTransactions(w http.ResponseWriter, r *http.Request) if ok { tx.Address = m.Address tx.Memo = m.Memo - tx.OrderID = m.OrderID + tx.OrderID = m.OrderId tx.Thumbnail = m.Thumbnail tx.CanBumpFee = m.CanBumpFee } @@ -3169,7 +3314,12 @@ func (i *jsonAPIHandler) POSTBlockNode(w http.ResponseWriter, r *http.Request) { nodes = append(nodes, pid) } } - go ipfs.RemoveAll(i.node.IpfsNode, peerID, i.node.IPNSQuorumSize) + go func(nd *ipfscore.IpfsNode, peerID string, quorum uint) { + err := ipfs.RemoveAll(nd, peerID, quorum) + if err != nil { + log.Error(err) + } + }(i.node.IpfsNode, peerID, i.node.IPNSQuorumSize) nodes = append(nodes, peerID) settings.BlockedNodes = &nodes if err := i.node.Datastore.Settings().Put(settings); err != nil { @@ -3182,6 +3332,7 @@ func (i *jsonAPIHandler) POSTBlockNode(w http.ResponseWriter, r *http.Request) { return } i.node.BanManager.AddBlockedId(pid) + i.node.Service.DisconnectFromPeer(pid) SanitizedResponse(w, `{}`) } @@ -3260,7 +3411,7 @@ func (i *jsonAPIHandler) POSTBumpFee(w http.ResponseWriter, r *http.Request) { Txid: newTxid.String(), Address: "", Memo: fmt.Sprintf("Fee bump of %s", txid), - OrderID: "", + OrderId: "", Thumbnail: "", CanBumpFee: true, }); err != nil { @@ -3268,25 +3419,34 @@ func (i *jsonAPIHandler) POSTBumpFee(w http.ResponseWriter, r *http.Request) { return } type response struct { - Txid string `json:"txid"` - Amount int64 `json:"amount"` - ConfirmedBalance int64 `json:"confirmedBalance"` - UnconfirmedBalance int64 `json:"unconfirmedBalance"` - Timestamp time.Time `json:"timestamp"` - Memo string `json:"memo"` + Txid string `json:"txid"` + Amount *repo.CurrencyValue `json:"amount"` + ConfirmedBalance *repo.CurrencyValue `json:"confirmedBalance"` + UnconfirmedBalance *repo.CurrencyValue `json:"unconfirmedBalance"` + Timestamp *repo.APITime `json:"timestamp"` + Memo string `json:"memo"` } confirmed, unconfirmed := wal.Balance() + defn, err := i.node.LookupCurrency(wal.CurrencyCode()) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } txn, err := wal.GetTransaction(*newTxid) if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return } + amt0, _ := repo.NewCurrencyValue(txn.Value, defn) + amt0.Amount = new(big.Int).Mod(amt0.Amount, big.NewInt(-1)) + + t := repo.NewAPITime(txn.Timestamp) resp := &response{ Txid: newTxid.String(), - ConfirmedBalance: confirmed, - UnconfirmedBalance: unconfirmed, - Amount: -(txn.Value), - Timestamp: txn.Timestamp, + ConfirmedBalance: &repo.CurrencyValue{Currency: defn, Amount: &confirmed.Value}, + UnconfirmedBalance: &repo.CurrencyValue{Currency: defn, Amount: &unconfirmed.Value}, + Amount: amt0, + Timestamp: t, Memo: fmt.Sprintf("Fee bump of %s", txid), } ser, err := json.MarshalIndent(resp, "", " ") @@ -3302,20 +3462,22 @@ func (i *jsonAPIHandler) GETEstimateFee(w http.ResponseWriter, r *http.Request) fl := r.URL.Query().Get("feeLevel") amt := r.URL.Query().Get("amount") - amount, err := strconv.Atoi(amt) - if err != nil { - ErrorResponse(w, http.StatusBadRequest, err.Error()) + amount, ok := new(big.Int).SetString(amt, 10) //strconv.Atoi(amt) + if !ok { + ErrorResponse(w, http.StatusBadRequest, "invalid amount") return } var feeLevel wallet.FeeLevel switch strings.ToUpper(fl) { case "PRIORITY": - feeLevel = wallet.PRIOIRTY + feeLevel = wallet.PRIORITY case "NORMAL": feeLevel = wallet.NORMAL case "ECONOMIC": feeLevel = wallet.ECONOMIC + case "SUPER_ECONOMIC": + feeLevel = wallet.SUPER_ECONOMIC default: ErrorResponse(w, http.StatusBadRequest, "Unknown feeLevel") return @@ -3327,10 +3489,10 @@ func (i *jsonAPIHandler) GETEstimateFee(w http.ResponseWriter, r *http.Request) return } - fee, err := wal.EstimateSpendFee(int64(amount), feeLevel) + fee, err := wal.EstimateSpendFee(*amount, feeLevel) if err != nil { switch { - case err == wallet.ErrorInsuffientFunds: + case err == wallet.ErrInsufficientFunds: ErrorResponse(w, http.StatusBadRequest, `ERROR_INSUFFICIENT_FUNDS`) return case err == wallet.ErrorDustAmount: @@ -3341,23 +3503,47 @@ func (i *jsonAPIHandler) GETEstimateFee(w http.ResponseWriter, r *http.Request) return } } - fmt.Fprintf(w, `{"estimatedFee": %d}`, fee) + + defn, err := i.node.LookupCurrency(coinType) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + resp := &repo.CurrencyValue{Currency: defn, Amount: &fee} + ser, err := json.MarshalIndent(resp, "", " ") + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + SanitizedResponse(w, string(ser)) } func (i *jsonAPIHandler) GETFees(w http.ResponseWriter, r *http.Request) { _, coinType := path.Split(r.URL.Path) type fees struct { - Priority uint64 `json:"priority"` - Normal uint64 `json:"normal"` - Economic uint64 `json:"economic"` + Priority *repo.CurrencyValue `json:"priority"` + Normal *repo.CurrencyValue `json:"normal"` + Economic *repo.CurrencyValue `json:"economic"` + SuperEconomic *repo.CurrencyValue `json:"superEconomic"` } if coinType == "fees" { ret := make(map[string]interface{}) for ct, wal := range i.node.Multiwallet { - priority := wal.GetFeePerByte(wallet.PRIOIRTY) + priority := wal.GetFeePerByte(wallet.PRIORITY) normal := wal.GetFeePerByte(wallet.NORMAL) economic := wal.GetFeePerByte(wallet.ECONOMIC) - ret[ct.CurrencyCode()] = fees{Priority: priority, Normal: normal, Economic: economic} + superEconomic := wal.GetFeePerByte(wallet.SUPER_ECONOMIC) + defn, err := i.node.LookupCurrency(wal.CurrencyCode()) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + ret[ct.CurrencyCode()] = fees{ + Priority: &repo.CurrencyValue{Currency: defn, Amount: &priority}, + Normal: &repo.CurrencyValue{Currency: defn, Amount: &normal}, + Economic: &repo.CurrencyValue{Currency: defn, Amount: &economic}, + SuperEconomic: &repo.CurrencyValue{Currency: defn, Amount: &superEconomic}, + } } out, err := json.MarshalIndent(ret, "", " ") if err != nil { @@ -3372,10 +3558,21 @@ func (i *jsonAPIHandler) GETFees(w http.ResponseWriter, r *http.Request) { ErrorResponse(w, http.StatusBadRequest, "Unknown wallet type") return } - priority := wal.GetFeePerByte(wallet.PRIOIRTY) + priority := wal.GetFeePerByte(wallet.PRIORITY) normal := wal.GetFeePerByte(wallet.NORMAL) economic := wal.GetFeePerByte(wallet.ECONOMIC) - f := fees{Priority: priority, Normal: normal, Economic: economic} + superEconomic := wal.GetFeePerByte(wallet.SUPER_ECONOMIC) + defn, err := i.node.LookupCurrency(wal.CurrencyCode()) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + f := fees{ + Priority: &repo.CurrencyValue{Currency: defn, Amount: &priority}, + Normal: &repo.CurrencyValue{Currency: defn, Amount: &normal}, + Economic: &repo.CurrencyValue{Currency: defn, Amount: &economic}, + SuperEconomic: &repo.CurrencyValue{Currency: defn, Amount: &superEconomic}, + } out, err := json.MarshalIndent(f, "", " ") if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) @@ -3384,9 +3581,32 @@ func (i *jsonAPIHandler) GETFees(w http.ResponseWriter, r *http.Request) { SanitizedResponse(w, string(out)) } +func (i *jsonAPIHandler) POSTCheckoutBreakdown(w http.ResponseWriter, r *http.Request) { + decoder := json.NewDecoder(r.Body) + var data repo.PurchaseData + err := decoder.Decode(&data) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + cb, err := i.node.CheckoutBreakdown(&data) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + out, err := json.MarshalIndent(cb, "", " ") + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + SanitizedResponse(w, string(out)) +} + func (i *jsonAPIHandler) POSTEstimateTotal(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) - var data core.PurchaseData + var data repo.PurchaseData err := decoder.Decode(&data) if err != nil { ErrorResponse(w, http.StatusBadRequest, err.Error()) @@ -3397,7 +3617,7 @@ func (i *jsonAPIHandler) POSTEstimateTotal(w http.ResponseWriter, r *http.Reques ErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - fmt.Fprintf(w, "%d", int(amount)) + fmt.Fprintf(w, "%s", amount.String()) } func (i *jsonAPIHandler) GETRatings(w http.ResponseWriter, r *http.Request) { @@ -3570,7 +3790,10 @@ func (i *jsonAPIHandler) POSTFetchRatings(w http.ResponseWriter, r *http.Request id := r.URL.Query().Get("asyncID") if id == "" { idBytes := make([]byte, 16) - rand.Read(idBytes) + _, err := rand.Read(idBytes) + if err != nil { + return + } id = base58.Encode(idBytes) } @@ -3594,7 +3817,7 @@ func (i *jsonAPIHandler) POSTFetchRatings(w http.ResponseWriter, r *http.Request if err != nil { return } - i.node.Broadcast <- repo.PremarshalledNotifier{ret} + i.node.Broadcast <- repo.PremarshalledNotifier{Payload: ret} } ratingBytes, err := ipfs.Cat(i.node.IpfsNode, rid, time.Minute) if err != nil { @@ -3633,7 +3856,7 @@ func (i *jsonAPIHandler) POSTFetchRatings(w http.ResponseWriter, r *http.Request respondWithError("error marshalling rating") return } - i.node.Broadcast <- repo.PremarshalledNotifier{b} + i.node.Broadcast <- repo.PremarshalledNotifier{Payload: b} }(r) } } @@ -3647,11 +3870,8 @@ func (i *jsonAPIHandler) POSTImportListings(w http.ResponseWriter, r *http.Reque } defer file.Close() - err = i.node.ImportListings(file) - if err != nil { - ErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } + // TODO: add the import listings function call + // Republish to IPNS if err := i.node.SeedNode(); err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) @@ -3756,6 +3976,7 @@ func (i *jsonAPIHandler) GETWalletStatus(w http.ResponseWriter, r *http.Request) } func (i *jsonAPIHandler) GETIPNS(w http.ResponseWriter, r *http.Request) { + ipfsStore := i.node.IpfsNode.Repo.Datastore() _, peerID := path.Split(r.URL.Path) pid, err := peer.IDB58Decode(peerID) @@ -3764,7 +3985,7 @@ func (i *jsonAPIHandler) GETIPNS(w http.ResponseWriter, r *http.Request) { return } - val, err := i.node.IpfsNode.Repo.Datastore().Get(namesys.IpnsDsKey(pid)) + peerIPNSRecord, err := ipfs.GetCachedIPNSRecord(ipfsStore, pid) if err != nil { // No record in datastore ErrorResponse(w, http.StatusNotFound, err.Error()) return @@ -3773,7 +3994,7 @@ func (i *jsonAPIHandler) GETIPNS(w http.ResponseWriter, r *http.Request) { var keyBytes []byte pubkey := i.node.IpfsNode.Peerstore.PubKey(pid) if pubkey == nil || !pid.MatchesPublicKey(pubkey) { - keyval, err := i.node.IpfsNode.Repo.Datastore().Get(datastore.NewKey(core.KeyCachePrefix + peerID)) + keyval, err := ipfs.GetCachedPubkey(ipfsStore, peerID) if err != nil { ErrorResponse(w, http.StatusNotFound, err.Error()) return @@ -3791,17 +4012,95 @@ func (i *jsonAPIHandler) GETIPNS(w http.ResponseWriter, r *http.Request) { Pubkey string `json:"pubkey"` Record string `json:"record"` } + peerIPNSBytes, err := ggproto.Marshal(peerIPNSRecord) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("marshaling IPNS record: %s", err.Error())) + return + } - ret := KeyAndRecord{hex.EncodeToString(keyBytes), string(val)} + ret := KeyAndRecord{hex.EncodeToString(keyBytes), string(peerIPNSBytes)} retBytes, err := json.MarshalIndent(ret, "", " ") if err != nil { ErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - go ipfs.Resolve(i.node.IpfsNode, pid, time.Minute, i.node.IPNSQuorumSize, false) + go func(nd *ipfscore.IpfsNode, pid peer.ID, timeout time.Duration, quorum uint, useCache bool) { + _, err := ipfs.Resolve(nd, pid, timeout, quorum, useCache) + if err != nil { + log.Error(err) + } + }(i.node.IpfsNode, pid, time.Minute, i.node.IPNSQuorumSize, false) fmt.Fprint(w, string(retBytes)) } +func (i *jsonAPIHandler) GETResolveIPNS(w http.ResponseWriter, r *http.Request) { + _, peerID := path.Split(r.URL.Path) + if len(peerID) == 0 || peerID == "resolveipns" { + peerID = i.node.IpfsNode.Identity.Pretty() + } + + type respType struct { + PeerID string `json:"peerid"` + Record struct { + Hex string `json:"hex"` + } `json:"record"` + } + var response = respType{PeerID: peerID} + + if i.node.IpfsNode.Identity.Pretty() == peerID { + rec, err := ipfs.GetCachedIPNSRecord(i.node.IpfsNode.Repo.Datastore(), i.node.IpfsNode.Identity) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("retrieving self: %s", err)) + return + } + ipnsBytes, err := proto.Marshal(rec) + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("marshaling self: %s", err)) + return + } + response.Record.Hex = hex.EncodeToString(ipnsBytes) + b, err := json.MarshalIndent(response, "", " ") + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("marshal json error: %s", err)) + return + } + + SanitizedResponse(w, string(b)) + return + } + + pid, err := peer.IDB58Decode(peerID) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*180) + _, err = routing.GetPublicKey(i.node.IpfsNode.Routing, ctx, pid) + cancel() + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + ctx, cancel = context.WithTimeout(context.Background(), time.Second*180) + ipnsBytes, err := i.node.IpfsNode.Routing.GetValue(ctx, ipns.RecordKey(pid)) + cancel() + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + response.Record.Hex = hex.EncodeToString(ipnsBytes) + b, err := json.MarshalIndent(response, "", " ") + if err != nil { + ErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("marshal json error: %s", err)) + return + } + + SanitizedResponse(w, string(b)) +} + func (i *jsonAPIHandler) POSTTestEmailNotifications(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) var settings repo.SMTPSettings @@ -3810,6 +4109,12 @@ func (i *jsonAPIHandler) POSTTestEmailNotifications(w http.ResponseWriter, r *ht ErrorResponse(w, http.StatusBadRequest, err.Error()) return } + profile, err := i.node.GetProfile() + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + settings.OpenBazaarName = profile.Name notifier := smtpNotifier{&settings} err = notifier.notify(repo.TestNotification{}) if err != nil { @@ -3843,6 +4148,35 @@ func (i *jsonAPIHandler) GETPeerInfo(w http.ResponseWriter, r *http.Request) { SanitizedResponse(w, string(out)) } +// Enable bulk updating prices for your listings by percentage +func (i *jsonAPIHandler) POSTBulkUpdatePrices(w http.ResponseWriter, r *http.Request) { + type BulkUpdatePriceRequest struct { + Percentage float64 `json:"percentage"` + } + + var bulkUpdate BulkUpdatePriceRequest + err := json.NewDecoder(r.Body).Decode(&bulkUpdate) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + + // Check for bad input + if bulkUpdate.Percentage == 0 { + SanitizedResponse(w, `{"success": "true"}`) + return + } + + log.Infof("Updating all listing prices by %v percent\n", bulkUpdate.Percentage) + err = i.node.SetPriceOnListings(bulkUpdate.Percentage) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + + SanitizedResponse(w, `{"success": "true"}`) +} + func (i *jsonAPIHandler) POSTBulkUpdateCurrency(w http.ResponseWriter, r *http.Request) { // Retrieve attribute and values to update type BulkUpdateRequest struct { @@ -3872,6 +4206,136 @@ func (i *jsonAPIHandler) POSTBulkUpdateCurrency(w http.ResponseWriter, r *http.R SanitizedResponse(w, `{"success": "true"}`) } +func (i *jsonAPIHandler) POSTBulkUpdateTerms(w http.ResponseWriter, r *http.Request) { + // Retrieve attribute and values to update + type BulkUpdateRequest struct { + TermsAndConditions string `json:"termsAndConditions"` + } + + var bulkUpdate BulkUpdateRequest + err := json.NewDecoder(r.Body).Decode(&bulkUpdate) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + + log.Info("Updating terms and conditions for all listings to: ", bulkUpdate.TermsAndConditions) + err = i.node.SetTermsAndConditionsOnListings(bulkUpdate.TermsAndConditions) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + + SanitizedResponse(w, `{"success": "true"}`) +} + +func (i *jsonAPIHandler) POSTBulkUpdateRefundPolicy(w http.ResponseWriter, r *http.Request) { + // Retrieve attribute and values to update + type BulkUpdateRequest struct { + RefundPolicy string `json:"refundPolicy"` + } + + var bulkUpdate BulkUpdateRequest + err := json.NewDecoder(r.Body).Decode(&bulkUpdate) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + + log.Info("Updating return policy for all listings to: ", bulkUpdate.RefundPolicy) + err = i.node.SetRefundPolicyOnListings(bulkUpdate.RefundPolicy) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + + SanitizedResponse(w, `{"success": "true"}`) +} + +func (i *jsonAPIHandler) POSTBulkUpdateShippingDetails(w http.ResponseWriter, r *http.Request) { + // Retrieve attribute and values to update + ld := new(pb.Listing) + err := jsonpb.Unmarshal(r.Body, ld) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + log.Info("Updating shipping details for all listings") + err = i.node.SetShippingDetailsOnListings(ld.ShippingOptions) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + + SanitizedResponse(w, `{"success": "true"}`) +} + +func (i *jsonAPIHandler) POSTInitWallet(w http.ResponseWriter, r *http.Request) { + decoder := json.NewDecoder(r.Body) + var data core.ManageWalletRequest + + err := decoder.Decode(&data) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + err = i.node.UnlockMnemonic(data) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + SanitizedResponse(w, `{"isLocked": "false"}`) +} + +func (i *jsonAPIHandler) POSTUnlockWallet(w http.ResponseWriter, r *http.Request) { + decoder := json.NewDecoder(r.Body) + var data core.ManageWalletRequest + + err := decoder.Decode(&data) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + walletLocked, mnemonicEncrypted, err := i.node.UnlockWallet(data) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + if i.node.IsWalletLocked() && !data.SkipChangeMnemonicState { + // shouldn't be + ErrorResponse(w, http.StatusBadRequest, `{"success": "false", "reason":"Unknown error - wallet was not able to unlock'"}`) + return + } + + SanitizedResponse(w, fmt.Sprintf(`{"isLocked": "%t", "isEncrypted": "%t"}`, + walletLocked, mnemonicEncrypted)) +} + +func (i *jsonAPIHandler) POSTLockWallet(w http.ResponseWriter, r *http.Request) { + decoder := json.NewDecoder(r.Body) + var data core.ManageWalletRequest + + err := decoder.Decode(&data) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + walletLocked, mnemonicEncrypted, err := i.node.LockWallet(data) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + SanitizedResponse(w, fmt.Sprintf(`{"isLocked": "%t", "isEncrypted": "%t"}`, + walletLocked, mnemonicEncrypted)) +} + // POSTS // Post a post @@ -4150,3 +4614,82 @@ func (i *jsonAPIHandler) GETPost(w http.ResponseWriter, r *http.Request) { } SanitizedResponseM(w, out, new(pb.SignedPost)) } + +// POSTSendOrderMessage - used to manually send an order message +func (i *jsonAPIHandler) POSTResendOrderMessage(w http.ResponseWriter, r *http.Request) { + type sendRequest struct { + OrderID string `json:"orderID"` + MessageType string `json:"messageType"` + } + + var args sendRequest + decoder := json.NewDecoder(r.Body) + err := decoder.Decode(&args) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + if args.MessageType == "" { + ErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("missing messageType argument")) + return + } + if args.OrderID == "" { + ErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("missing orderID argument")) + return + } + + msgInt, ok := pb.Message_MessageType_value[strings.ToUpper(args.MessageType)] + if !ok { + ErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("unknown messageType (%s)", args.MessageType)) + return + } + + if err := i.node.ResendCachedOrderMessage(args.OrderID, pb.Message_MessageType(msgInt)); err != nil { + ErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + SanitizedResponse(w, `{}`) +} + +// GETScanOfflineMessages - used to manually trigger offline message scan +func (i *jsonAPIHandler) GETScanOfflineMessages(w http.ResponseWriter, r *http.Request) { + if lastManualScan.IsZero() { + lastManualScan = time.Now() + } else { + if time.Since(lastManualScan) >= OfflineMessageScanInterval { + i.node.MessageRetriever.RunOnce() + lastManualScan = time.Now() + } + } + SanitizedResponse(w, `{}`) +} + +func (i *jsonAPIHandler) GETIsWalletLocked(w http.ResponseWriter, r *http.Request) { + SanitizedResponse(w, fmt.Sprintf(`{"isLocked": "%s", "isInitialized": "%s"}`, + strconv.FormatBool(i.node.IsWalletLocked()), strconv.FormatBool(i.node.Multiwallet != nil))) +} + +func (i *jsonAPIHandler) POSTHashMessage(w http.ResponseWriter, r *http.Request) { + type hashRequest struct { + Content string `json:"content"` + } + var ( + req hashRequest + err = json.NewDecoder(r.Body).Decode(&req) + ) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + messageHash, err := ipfs.EncodeMultihash([]byte(req.Content)) + if err != nil { + ErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + SanitizedResponse(w, fmt.Sprintf(`{"hash": "%s"}`, + messageHash.B58String())) +} diff --git a/api/jsonapi_data_test.go b/api/jsonapi_data_test.go index 39d4a54592..bace129da5 100644 --- a/api/jsonapi_data_test.go +++ b/api/jsonapi_data_test.go @@ -3,7 +3,7 @@ package api import ( "fmt" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) const notFoundJSON = `{"success": false,"reason": "Not Found"}` @@ -55,6 +55,7 @@ const settingsJSON = `{ "mispaymentBuffer": 1, "smtpSettings": { "notifications": true, + "openBazaarName": "", "serverAddress": "smtp.urbanart.com:465", "username": "urbanart", "password": "letmein", @@ -94,6 +95,7 @@ const settingsUpdateJSON = `{ "mispaymentBuffer": 1, "smtpSettings": { "notifications": true, + "openBazaarName": "", "serverAddress": "smtp.urbanart.com:465", "username": "urbanart", "password": "letmein", @@ -142,6 +144,7 @@ const settingsPatchedJSON = `{ "mispaymentBuffer": 1, "smtpSettings": { "notifications": true, + "openBazaarName": "", "serverAddress": "smtp.urbanart.com:465", "username": "urbanart", "password": "letmein", @@ -229,11 +232,11 @@ const avatarValidJSON = `{ }` const avatarValidJSONResponse = `{ - "large": "QmcUNDbsazULoEddnRSsiK1LgUCx6FnujgUG6r17GEviq2", - "medium": "Qmdj2NnzQwGuHN7RZmMhu1VEeLP7APDzFE5KmBKsPxZmuH", + "large": "QmWssRhf5pBARL5eiNSfvxJMC8UptqDsRNs71Vs8JYcquP", + "medium": "QmRCVZ9WSvS69Yv1uSFqwu87UW7TKsjfJY6CwfMNNiimaX", "original": "QmYGE9UNEMvQ8W1qcVAMkJTYLpjNu1JHQtwqvppJ2QXiJe", - "small": "Qmf198F1mX2hhFJKkWUepxLh3vC853Xr79VQuhJFuBizZD", - "tiny": "QmPxXHGMm5J3y2G4S9brxe83CxLgt6D3MZKhxMBkNyKQWn" + "small": "QmcFz5VjvRzsjTARECw8EMX3GD7nW8xnEcCew4hAKTr6Mm", + "tiny": "QmYvRXkk9eW89R97jtWH5E8Uf6woHVvVrT3GqjVtVn8WCc" }` const avatarUnexpectedEOFJSON = `{ @@ -259,14 +262,14 @@ const imageValidJSON = `[{ }]` const imageValidJSONResponse = `[{ - "filename": "blue_tshirt.jpg", - "hashes": { - "large": "Qmcy4pW7cv18RMCprxrxhiihQzUJNaCNr5v2qvZGjGAwsj", - "medium": "QmVGiFSwTkMPjvGnnreHkspb9Ui2upkctYtqMR5sBKncHR", - "original": "QmQ2QdYMLCPWuVpdAvj49Kf7FvbpPrN4bdborHGb3G9jQv", - "small": "QmUBvfRXHYmzNx6uke5USD3C5PgWr5Wa3XHzcK3zaTeytS", - "tiny": "QmNi2H4MUkLe9eBEPmyE9QVQ6Y3F1RwpPxB4B1us5HnxwG" - } + "filename": "blue_tshirt.jpg", + "hashes": { + "large": "Qma36fP81juurtQetNpCABxNoiXyxPSHPaLV2qAsBwfz6u", + "medium": "QmYmEQvMRdrvYPpcy1wWDZw4Qpr82cfYeKBMi7igAGhpT1", + "original": "QmQ2QdYMLCPWuVpdAvj49Kf7FvbpPrN4bdborHGb3G9jQv", + "small": "QmUkYogFP4GAmTfFHiq1dtv8tc7UZGUhBX6DfZ7kfvwidT", + "tiny": "QmW3qn2BKeaxQvNTUJE1yXavLkseeut9VWNYb5Ew4tgjLJ" + } }]` // nolint lll @@ -275,11 +278,11 @@ const headerValidJSON = `{ }` const headerValidJSONResponse = `{ - "large": "QmSqNf7gM4LKMsqej8b4q2su14TButMZduF5FJRodttbTZ", - "medium": "QmZqF47LXvKvKh5YyCerkEAiS4EmVubACeoQTQKXzU79WV", + "large": "QmPDHbQDjqMUfzDRrDAUxhh8KrgMTiijAoPKtN8EvxBN1A", + "medium": "QmP9KPZp1cexqkLr6MHJCQME7X76Z4NaFgty94MbXcxSHZ", "original": "QmYGE9UNEMvQ8W1qcVAMkJTYLpjNu1JHQtwqvppJ2QXiJe", - "small": "QmQHHKV7cBFFE4WDJN9Vojxc3U14dt4dK5ihgtxwphdQij", - "tiny": "QmRheKdYREcdSHBdamY3ejZxh89UmnnjRQcqPPxAoQxn9X" + "small": "QmcnZDDJY9Ss4TZEFNsttUw8vUsr3Hdzqa5uB6P1TndCbd", + "tiny": "QmZrLG7ZSqNvrvcEsy7Zwd2Bb2SSxgAhkX4mrCDCtDJgER" }` // @@ -289,7 +292,7 @@ const headerValidJSONResponse = `{ const inventoryUpdateJSON = `[{ "slug": "ron_swanson_tshirt", "variant": 0, - "quantity": 17 + "quantity": "17" }]` // @@ -298,6 +301,18 @@ const inventoryUpdateJSON = `[{ const bulkUpdateCurrencyJSON = ` { "currencies":["ZEC", "BTC", "BCH", "LTC"] }` +//// +//// Bulk Update Terms and Conditions +//// +// +//const bulkUpdateTermsJSON = ` { "termsAndConditions":"NEW TERMS" }` +// +//// +//// Bulk Update Return Policy +//// +// +//const bulkUpdateReturnPolicyJSON = ` { "returnPolicy":"NEW RETURN POLICY" }` + // // Moderation // @@ -309,8 +324,8 @@ const moderatorValidJSON = `{ "fee": { "feeType": "FIXED_PLUS_PERCENTAGE", "fixedFee": { - "currencyCode": "USD", - "amount": 300 + "currency": {code: "USD", divisibility: 8}, + "amount": "300" }, "percentage": 5 } @@ -320,7 +335,10 @@ const moderatorValidJSON = `{ // Wallet // -const walletMneumonicJSONResponse = `{"mnemonic": "correct horse battery staple"}` +const walletMneumonicJSONResponse = `{ + "isEncrypted": "false", + "mnemonic": "correct horse battery staple" +}` const walletAddressJSONResponse = `{ "TBCH": "qptj7gckxunjzd0dtjhmllm44we5ry9sv5r05a59v8", @@ -331,24 +349,48 @@ const walletAddressJSONResponse = `{ const walletBalanceJSONResponse = `{ "TBCH": { - "confirmed": 0, + "confirmed": "0", + "currency": { + "code": "TBCH", + "currencyType": "crypto", + "divisibility": 8, + "name": "Testnet Bitcoin Cash" + }, "height": 0, - "unconfirmed": 0 + "unconfirmed": "0" }, "TBTC": { - "confirmed": 0, + "confirmed": "0", + "currency": { + "code": "TBTC", + "currencyType": "crypto", + "divisibility": 8, + "name": "Testnet Bitcoin" + }, "height": 0, - "unconfirmed": 0 + "unconfirmed": "0" }, "TLTC": { - "confirmed": 0, + "confirmed": "0", + "currency": { + "code": "TLTC", + "currencyType": "crypto", + "divisibility": 8, + "name": "Testnet Litecoin" + }, "height": 0, - "unconfirmed": 0 + "unconfirmed": "0" }, "TZEC": { - "confirmed": 0, + "confirmed": "0", + "currency": { + "code": "TZEC", + "currencyType": "crypto", + "divisibility": 8, + "name": "Testnet Zcash" + }, "height": 0, - "unconfirmed": 0 + "unconfirmed": "0" } }` @@ -356,18 +398,6 @@ const walletBalanceJSONResponse = `{ // Spending // -const spendJSON = `{ - "wallet": "btc", - "address": "1HYhu8e2wv19LZ2umXoo1pMiwzy2rL32UQ", - "amount": 1700000, - "feeLevel": "NORMAL" -}` - -const insuffientFundsJSON = `{ - "success": false, - "reason": "ERROR_INSUFFICIENT_FUNDS" -}` - const invalidCoinJSON = `{ "success": false, "reason": "multiwallet does not contain an implementation for the given coin" diff --git a/api/jsonapi_helpers_test.go b/api/jsonapi_helpers_test.go index 03984f7116..d74ee23a88 100644 --- a/api/jsonapi_helpers_test.go +++ b/api/jsonapi_helpers_test.go @@ -3,7 +3,6 @@ package api import ( "bytes" "encoding/json" - "fmt" ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" "gx/ipfs/Qmc85NSvmSG4Frn9Vb2cBc1rMyULH6D3TNVEfCzSKoUpip/go-multiaddr-net" @@ -17,7 +16,7 @@ import ( "github.com/OpenBazaar/jsonpb" "github.com/golang/protobuf/proto" "github.com/op/go-logging" - "github.com/phoreproject/openbazaar-go/test" + "github.com/phoreproject/pm-go/test" ) // testURIRoot is the root http URI to hit for testing @@ -60,12 +59,11 @@ func newTestGateway() (*Gateway, error) { // apiTest is a test case to be run against the api blackbox type apiTest struct { - method string - path string - requestBody string + method, path string + requestBody interface{} expectedResponseCode int - expectedResponseBody string + expectedResponseBody interface{} } // setupAction is used to change state before and after a set of []apiTest @@ -119,12 +117,33 @@ func runAPITest(t *testing.T, subject apiTest) { // executeAPITest executes the given test against the blackbox func executeAPITest(t *testing.T, test apiTest) { + var reqBody, expectedResp string + if r, ok := test.requestBody.(string); ok { + reqBody = r + } else { + mr, err := json.MarshalIndent(test.requestBody, "", " ") + if err != nil { + t.Fatalf("marshalling requestBody: %s", err) + } + reqBody = string(mr) + } + if r, ok := test.expectedResponseBody.(string); ok { + expectedResp = r + } else { + mr, err := json.MarshalIndent(test.expectedResponseBody, "", " ") + if err != nil { + t.Fatalf("marshalling expectedResponseBody: %s", err) + } + expectedResp = string(mr) + } + + t.Logf("request body:\n%s", reqBody) // Make the request - req, err := buildRequest(test.method, test.path, test.requestBody) + testRequest, err := buildRequest(test.method, test.path, reqBody) if err != nil { t.Fatal(err) } - resp, err := testHTTPClient.Do(req) + resp, err := testHTTPClient.Do(testRequest) if err != nil { t.Fatal(err) } @@ -151,17 +170,17 @@ func executeAPITest(t *testing.T, test apiTest) { } // Unless explicitly saying any JSON is expected check for equality - if test.expectedResponseBody != anyResponseJSON { + if expectedResp != anyResponseJSON { var expectedJSON interface{} - err = json.Unmarshal([]byte(test.expectedResponseBody), &expectedJSON) + err = json.Unmarshal([]byte(expectedResp), &expectedJSON) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(responseJSON, expectedJSON) { - fmt.Println("expected:", test.expectedResponseBody) - fmt.Println("actual:", string(respBody)) - t.Error("Incorrect response") + t.Error("Error: incorrect response") + t.Logf("expected:\n%s", expectedResp) + t.Logf("actual:\n%s", string(respBody)) } } } diff --git a/api/jsonapi_test.go b/api/jsonapi_test.go index 4cfb774168..ba2b31e0cf 100644 --- a/api/jsonapi_test.go +++ b/api/jsonapi_test.go @@ -2,6 +2,7 @@ package api import ( "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -9,11 +10,13 @@ import ( "testing" "time" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/test" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/OpenBazaar/jsonpb" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test" + "github.com/phoreproject/pm-go/test/factory" ) func TestMain(m *testing.M) { @@ -25,7 +28,7 @@ func TestMain(m *testing.M) { defer gateway.Close() go func() { - err = gateway.Serve() + err = gateway.Serve(true) if err != nil { log.Fatal(err) } @@ -64,6 +67,60 @@ func TestSettings(t *testing.T) { }) } +func TestSettingsSetModerator(t *testing.T) { + var ( + validSettings = factory.MustNewValidSettings() + jsonSettings, sErr = json.Marshal(validSettings) + moderatorUpdate = `{"storeModerators": ["QmeRfQcEiefLYgEFRsNqn1WjjrLjrJVAddt85htU1Up32y"]}` + ) + if sErr != nil { + t.Fatal(sErr) + } + + expected := `{ + "blockedNodes": [], + "country": "United State of Shipping", + "localCurrency": "USD", + "mispaymentBuffer": 1, + "paymentDataInQR": true, + "refundPolicy": "Refund policy.", + "shippingAddresses": [ + { + "addressLineOne": "123 Address Street", + "addressLineTwo": "Suite H", + "addressNotes": "This is a fake yet valid address for testing.", + "city": "Shipping City", + "company": "Shipping Company", + "country": "United States of Shipping", + "name": "Shipping Name", + "postalCode": "12345-6789", + "state": "Shipping State" + } + ], + "showNotifications": true, + "showNsfw": true, + "smtpSettings": { + "notifications": false, + "openBazaarName": "", + "password": "", + "recipientEmail": "", + "senderEmail": "", + "serverAddress": "", + "username": "" + }, + "storeModerators": [ + "QmeRfQcEiefLYgEFRsNqn1WjjrLjrJVAddt85htU1Up32y" + ], + "termsAndConditions": "Terms and Conditions", + "version": "" +}` + runAPITests(t, apiTests{ + {"POST", "/ob/settings", string(jsonSettings), 200, string(jsonSettings)}, + {"PATCH", "/ob/settings", moderatorUpdate, 200, "{}"}, + {"GET", "/ob/settings", "", 200, expected}, + }) +} + func TestProfile(t *testing.T) { // Create, Update runAPITests(t, apiTests{ @@ -74,6 +131,316 @@ func TestProfile(t *testing.T) { }) } +func TestProfileSwitchesFromPercentToFixedWithLegacySchema(t *testing.T) { + var ( + postProfile = `{ + "handle": "test", + "name": "Test User", + "location": "Internet", + "about": "The test fixture", + "shortDescription": "Fixture", + "contactInfo": { + "website": "internet.com", + "email": "email@address.com", + "phoneNumber": "687-5309" + }, + "nsfw": false, + "vendor": false, + "moderator": true, + "moderatorInfo": { + "description": "Percentage. Test moderator account. DO NOT USE.", + "fee": { + "feeType": "PERCENTAGE", + "percentage": 12.0 + } + }, + "colors": { + "primary": "#000000", + "secondary": "#FFD700", + "text": "#ffffff", + "highlight": "#123ABC", + "highlightText": "#DEAD00" + }, + "currencies": ["LTC"] +}` + patchProfile = `{ + "moderatorInfo": { + "fee": { + "feeType": "FIXED", + "fixedFee": { + "bigAmount": "1234", + "amountCurrency": { + "code": "USD", + "divisibility": 2 + } + } + } + } +}` + validateProfileFees = func(testRepo *test.Repository) error { + m, err := schema.NewCustomSchemaManager(schema.SchemaContext{ + DataPath: testRepo.Path, + TestModeEnabled: true, + }) + if err != nil { + return fmt.Errorf("schema setup: %s", err.Error()) + } + profileBytes, err := ioutil.ReadFile(m.DataPathJoin("root", "profile.json")) + if err != nil { + return fmt.Errorf("get profile: %s", err.Error()) + } + + var actualProfile pb.Profile + if err := jsonpb.UnmarshalString(string(profileBytes), &actualProfile); err != nil { + return fmt.Errorf("unmarshal profile: %s", err.Error()) + } + + fees := actualProfile.ModeratorInfo.Fee + if ft := fees.GetFeeType().String(); ft != pb.Moderator_Fee_FIXED.String() { + return fmt.Errorf("expected patched profile fee type to be (%s), but was (%s)", pb.Moderator_Fee_FIXED.String(), ft) + } + + fixedFee := fees.GetFixedFee() + if amt := fixedFee.GetBigAmount(); amt != "1234" { + return fmt.Errorf("expected patched profile fixed fee big amount to be (1234), but was (%s)", amt) + } + if amt := fixedFee.GetAmount(); amt != 1234 { //nolint:staticcheck + return fmt.Errorf("expected patched profile fixed fee amount to be (1234), but was (%d)", amt) + } + if cc := fixedFee.GetAmountCurrency().GetCode(); cc != "USD" { + return fmt.Errorf("expected patched profile fixed fee currency to be (USD), but was (%s)", cc) + } + if cc := fixedFee.GetCurrencyCode(); cc != "USD" { //nolint:staticcheck + return fmt.Errorf("expected patched profile fixed fee currency code to be (USD), but was (%s)", cc) + } + + return nil + } + ) + + runAPITestsWithSetup(t, apiTests{ + {"POST", "/ob/profile", postProfile, 200, anyResponseJSON}, + {"PATCH", "/ob/profile", patchProfile, 200, "{}"}, + }, nil, validateProfileFees) +} + +func TestPatchProfileCurrencyUpdate(t *testing.T) { + var ( + postProfile = `{ + "handle": "test", + "name": "Test User", + "location": "Internet", + "about": "The test fixture", + "shortDescription": "Fixture", + "contactInfo": { + "website": "internet.com", + "email": "email@address.com", + "phoneNumber": "687-5309" + }, + "nsfw": false, + "vendor": false, + "moderator": false, + "colors": { + "primary": "#000000", + "secondary": "#FFD700", + "text": "#ffffff", + "highlight": "#123ABC", + "highlightText": "#DEAD00" + }, + "currencies": ["LTC"] +}` + patchProfile = `{"currencies": ["ETH"]}` + validateProfile = func(testRepo *test.Repository) error { + m, err := schema.NewCustomSchemaManager(schema.SchemaContext{ + DataPath: testRepo.Path, + TestModeEnabled: true, + }) + if err != nil { + return fmt.Errorf("schema setup: %s", err.Error()) + } + profileBytes, err := ioutil.ReadFile(m.DataPathJoin("root", "profile.json")) + if err != nil { + return fmt.Errorf("get profile: %s", err.Error()) + } + + var actualProfile struct { + Currencies []string `json:"currencies"` + } + if err := json.Unmarshal(profileBytes, &actualProfile); err != nil { + return fmt.Errorf("unmarshal profile: %s", err.Error()) + } + + if actualProfile.Currencies[0] != "ETH" { + t.Errorf("expected profile currency to be PATCHed but was not") + t.Logf("expected 'ETH', found '%s'", actualProfile.Currencies[0]) + } + + if len(actualProfile.Currencies) != 1 { + t.Errorf("expected profile currency to have 1 currency, but had %d instead", len(actualProfile.Currencies)) + } + return nil + } + ) + + runAPITestsWithSetup(t, apiTests{ + {"POST", "/ob/profile", postProfile, 200, anyResponseJSON}, + {"PATCH", "/ob/profile", patchProfile, 200, "{}"}, + }, nil, validateProfile) +} + +func TestPatchProfileCanBeInvalid(t *testing.T) { + var ( + // init profile for patch + postProfile = `{ + "handle": "test", + "name": "Test User", + "location": "Internet", + "about": "The test fixture", + "shortDescription": "Fixture", + "contactInfo": { + "website": "internet.com", + "email": "email@address.com", + "phoneNumber": "687-5309" + }, + "nsfw": false, + "vendor": false, + "moderator": false, + "colors": { + "primary": "#000000", + "secondary": "#FFD700", + "text": "#ffffff", + "highlight": "#123ABC", + "highlightText": "#DEAD00" + }, + "currencies": ["LTC"] +}` + // test valid patch + patchProfile = `{ + "moderator": true, + "moderatorInfo": { + "description": "Fix plus percentage. Test moderator account. DO NOT USE.", + "fee": { + "feeType": "FIXED_PLUS_PERCENTAGE", + "fixedFee": { + "amountCurrency": { + "code": "USD", + "divisibility": 2 + }, + "bigAmount": "2" + }, + "percentage": 0.1 + }, + "languages": [ + "en-US" + ], + "termsAndConditions": "Test moderator account. DO NOT USE." + } +}` + // test invalid patch: percentage must be greater than 0 + invalidPatchProfile = `{ + "moderatorInfo": { + "fee": { + "percentage": -1 + } + } +}` + ) + + expectedErr := fmt.Errorf("invalid profile: %s", repo.ErrModeratorFeeHasNegativePercentage) + runAPITests(t, apiTests{ + {"POST", "/ob/profile", postProfile, 200, anyResponseJSON}, + {"PATCH", "/ob/profile", patchProfile, 200, "{}"}, + {"PATCH", "/ob/profile", invalidPatchProfile, 500, errorResponseJSON(expectedErr)}, + }) +} + +func TestProfileSwitchesFromFixedToPercent(t *testing.T) { + var ( + postProfile = `{ + "handle": "test", + "name": "Test User", + "location": "Internet", + "about": "The test fixture", + "shortDescription": "Fixture", + "contactInfo": { + "website": "internet.com", + "email": "email@address.com", + "phoneNumber": "687-5309" + }, + "nsfw": false, + "vendor": false, + "moderator": true, + "moderatorInfo": { + "description": "Fix plus percentage. Test moderator account. DO NOT USE.", + "fee": { + "feeType": "FIXED_PLUS_PERCENTAGE", + "fixedFee": { + "amountCurrency": { + "code": "USD", + "divisibility": 2 + }, + "bigAmount": "2" + }, + "percentage": 0.1 + }, + "languages": [ + "en-US" + ], + "termsAndConditions": "Test moderator account. DO NOT USE." + }, + "colors": { + "primary": "#000000", + "secondary": "#FFD700", + "text": "#ffffff", + "highlight": "#123ABC", + "highlightText": "#DEAD00" + }, + "currencies": ["LTC"] +}` + patchProfile = `{ + "moderatorInfo": { + "fee": { + "feeType": "PERCENTAGE", + "percentage": 0.1 + } + } +}` + validateProfileFees = func(testRepo *test.Repository) error { + m, err := schema.NewCustomSchemaManager(schema.SchemaContext{ + DataPath: testRepo.Path, + TestModeEnabled: true, + }) + if err != nil { + return fmt.Errorf("schema setup: %s", err.Error()) + } + profileBytes, err := ioutil.ReadFile(m.DataPathJoin("root", "profile.json")) + if err != nil { + return fmt.Errorf("get profile: %s", err.Error()) + } + + var actualProfile pb.Profile + if err := jsonpb.UnmarshalString(string(profileBytes), &actualProfile); err != nil { + return fmt.Errorf("unmarshal profile: %s", err.Error()) + } + + fees := actualProfile.ModeratorInfo.Fee + if ft := fees.GetFeeType().String(); ft != pb.Moderator_Fee_PERCENTAGE.String() { + return fmt.Errorf("expected patched profile fee type to be (%s), but was (%s)", pb.Moderator_Fee_PERCENTAGE.String(), ft) + } + + if p := fees.GetPercentage(); p != 0.1 { + return fmt.Errorf("expected patched profile fee percentage to be (0.1), but was (%f)", p) + } + + return nil + } + ) + runAPITestsWithSetup(t, apiTests{ + {"POST", "/ob/profile", postProfile, 200, anyResponseJSON}, + {"PATCH", "/ob/profile", patchProfile, 200, "{}"}, + }, nil, validateProfileFees) +} + func TestAvatar(t *testing.T) { // Setting an avatar fails if we don't have a profile runAPITests(t, apiTests{ @@ -275,7 +642,7 @@ func TestListings(t *testing.T) { {"GET", "/ob/inventory", "", 200, `{}`}, // Invalid creates - {"POST", "/ob/listing", `{`, 400, jsonUnexpectedEOF}, + {"POST", "/ob/listing", `{`, 500, jsonUnexpectedEOF}, {"GET", "/ob/listings", "", 200, `[]`}, {"GET", "/ob/inventory", "", 200, `{}`}, @@ -337,45 +704,40 @@ func TestCryptoListings(t *testing.T) { } func TestCryptoListingsPriceModifier(t *testing.T) { - outOfRangeErr := core.ErrPriceModifierOutOfRange{ - Min: core.PriceModifierMin, - Max: core.PriceModifierMax, + outOfRangeErr := repo.ErrPriceModifierOutOfRange{ + Min: repo.PriceModifierMin, + Max: repo.PriceModifierMax, } listing := factory.NewCryptoListing("crypto") - listing.Metadata.PriceModifier = core.PriceModifierMax + listing.Item.PriceModifier = repo.PriceModifierMax runAPITests(t, apiTests{ {"POST", "/ob/listing", jsonFor(t, listing), 200, `{"slug": "crypto"}`}, {"GET", "/ob/listing/crypto", jsonFor(t, listing), 200, anyResponseJSON}, }) - listing.Metadata.PriceModifier = core.PriceModifierMax + 0.001 + listing.Item.PriceModifier = repo.PriceModifierMax + 0.001 runAPITest(t, apiTest{ "POST", "/ob/listing", jsonFor(t, listing), 200, `{"slug": "crypto"}`, }) - listing.Metadata.PriceModifier = core.PriceModifierMax + 0.01 + listing.Item.PriceModifier = repo.PriceModifierMax + 0.01 runAPITest(t, apiTest{ - "POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(outOfRangeErr), + "POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(fmt.Errorf("validate sellable listing (crypto): %s", outOfRangeErr)), }) - listing.Metadata.PriceModifier = core.PriceModifierMin - 0.001 + listing.Item.PriceModifier = repo.PriceModifierMin - 0.001 runAPITest(t, apiTest{ "POST", "/ob/listing", jsonFor(t, listing), 200, `{"slug": "crypto"}`, }) - listing.Metadata.PriceModifier = core.PriceModifierMin - 1 + listing.Item.PriceModifier = repo.PriceModifierMin - 1 runAPITest(t, apiTest{ - "POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(outOfRangeErr), - }) - - listing.Item.Price = 1 - var f core.ErrMarketPriceListingIllegalField = "item.price" - runAPITest(t, apiTest{ - "POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(f), + "POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(fmt.Errorf("validate sellable listing (crypto): %s", outOfRangeErr)), }) listing.Metadata.Format = pb.Listing_Metadata_FIXED_PRICE + listing.Item.PriceModifier = 0 runAPITest(t, apiTest{ "POST", "/ob/listing", jsonFor(t, listing), 200, `{"slug": "crypto"}`, }) @@ -387,12 +749,12 @@ func TestListingsQuantity(t *testing.T) { "POST", "/ob/listing", jsonFor(t, listing), 200, `{"slug": "crypto"}`, }) - listing.Item.Skus[0].Quantity = 0 + listing.Item.Skus[0].BigQuantity = "0" runAPITest(t, apiTest{ "POST", "/ob/listing", jsonFor(t, listing), 200, anyResponseJSON, }) - listing.Item.Skus[0].Quantity = -1 + listing.Item.Skus[0].BigQuantity = "-1" runAPITest(t, apiTest{ "POST", "/ob/listing", jsonFor(t, listing), 200, anyResponseJSON, }) @@ -404,42 +766,46 @@ func TestCryptoListingsQuantity(t *testing.T) { "POST", "/ob/listing", jsonFor(t, listing), 200, `{"slug": "crypto"}`, }) - listing.Item.Skus[0].Quantity = 0 + listing.Item.Skus[0].BigQuantity = "-1" runAPITest(t, apiTest{ - "POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(core.ErrCryptocurrencySkuQuantityInvalid), + "POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(repo.ErrCryptocurrencySkuQuantityInvalid), }) - listing.Item.Skus[0].Quantity = -1 + listing.Item.Skus[0].BigQuantity = "-1" runAPITest(t, apiTest{ - "POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(core.ErrCryptocurrencySkuQuantityInvalid), + "POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(repo.ErrCryptocurrencySkuQuantityInvalid), }) } +/* func TestCryptoListingsNoCoinType(t *testing.T) { listing := factory.NewCryptoListing("crypto") - listing.Metadata.CoinType = "" + //listing.Metadata.CoinType = "" runAPITests(t, apiTests{ {"POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(core.ErrCryptocurrencyListingCoinTypeRequired)}, }) } +*/ +/* func TestCryptoListingsCoinDivisibilityIncorrect(t *testing.T) { listing := factory.NewCryptoListing("crypto") runAPITests(t, apiTests{ {"POST", "/ob/listing", jsonFor(t, listing), 200, anyResponseJSON}, }) - listing.Metadata.CoinDivisibility = 1e7 + //listing.Metadata.CoinDivisibility = 1e7 runAPITests(t, apiTests{ {"POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(core.ErrListingCoinDivisibilityIncorrect)}, }) - listing.Metadata.CoinDivisibility = 0 + //listing.Metadata.CoinDivisibility = 0 runAPITests(t, apiTests{ {"POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(core.ErrListingCoinDivisibilityIncorrect)}, }) } +*/ func TestCryptoListingsIllegalFields(t *testing.T) { runTest := func(listing *pb.Listing, err error) { @@ -450,34 +816,42 @@ func TestCryptoListingsIllegalFields(t *testing.T) { physicalListing := factory.NewListing("physical") - listing := factory.NewCryptoListing("crypto") - listing.Metadata.PricingCurrency = "btc" - runTest(listing, core.ErrCryptocurrencyListingIllegalField("metadata.pricingCurrency")) + //listing := factory.NewCryptoListing("crypto") + //listing.Metadata.PricingCurrency = &pb.CurrencyDefinition{Code: "BTC", Divisibility: 8} + //runTest(listing, core.ErrCryptocurrencyListingIllegalField("metadata.pricingCurrency")) - listing = factory.NewCryptoListing("crypto") + listing := factory.NewCryptoListing("crypto") listing.Item.Condition = "new" - runTest(listing, core.ErrCryptocurrencyListingIllegalField("item.condition")) + runTest(listing, repo.ErrCryptocurrencyListingIllegalField("item.condition")) listing = factory.NewCryptoListing("crypto") listing.Item.Options = physicalListing.Item.Options - runTest(listing, core.ErrCryptocurrencyListingIllegalField("item.options")) + runTest(listing, repo.ErrCryptocurrencyListingIllegalField("item.options")) listing = factory.NewCryptoListing("crypto") listing.ShippingOptions = physicalListing.ShippingOptions - runTest(listing, core.ErrCryptocurrencyListingIllegalField("shippingOptions")) + runTest(listing, repo.ErrCryptocurrencyListingIllegalField("shippingOptions")) listing = factory.NewCryptoListing("crypto") listing.Coupons = physicalListing.Coupons - runTest(listing, core.ErrCryptocurrencyListingIllegalField("coupons")) + /*[]*pb.Listing_Coupon{} + sampleCoupon := new(pb.Listing_Coupon) + sampleCoupon.Title = "sample coupon" + sampleCoupon.Code = &pb.Listing_Coupon_DiscountCode{DiscountCode: "insider"} + sampleCoupon.Discount = &pb.Listing_Coupon_PercentDiscount{PercentDiscount: 5} + */ + runTest(listing, repo.ErrCryptocurrencyListingIllegalField("coupons")) + } func TestMarketRatePrice(t *testing.T) { listing := factory.NewListing("listing") listing.Metadata.Format = pb.Listing_Metadata_MARKET_PRICE - listing.Item.Price = 1 + listing.Item.BigPrice = "100" + listing.Item.PriceCurrency = &pb.CurrencyDefinition{Code: "BTC", Divisibility: 8} runAPITests(t, apiTests{ - {"POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(core.ErrMarketPriceListingIllegalField("item.price"))}, + {"POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(fmt.Errorf("validate sellable listing (listing): %s", repo.ErrMarketPriceListingIllegalField("item.bigPrice")))}, }) } @@ -493,11 +867,97 @@ func TestWallet(t *testing.T) { {"GET", "/wallet/address", "", 200, walletAddressJSONResponse}, {"GET", "/wallet/balance", "", 200, walletBalanceJSONResponse}, {"GET", "/wallet/mnemonic", "", 200, walletMneumonicJSONResponse}, - {"POST", "/wallet/spend/", spendJSON, 400, insuffientFundsJSON}, // TODO: Test successful spend on regnet with coins }) } +func TestWalletSpendFailures(t *testing.T) { + newSpendRequest := func() *core.SpendRequest { + return &core.SpendRequest{ + CurrencyCode: "TBTC", + Address: "1HYhu8e2wv19LZ2umXoo1pMiwzy2rL32UQ", + Amount: "1234", + FeeLevel: "PRIORITY", + RequireAssociatedOrder: false, + } + } + + insufficientFundsRequest := newSpendRequest() + insufficientFundsRequest.Amount = "1700000" + insufficientFundsResponse := APIError{Reason: core.ErrInsufficientFunds.Error()} + + invalidAmountRequest := newSpendRequest() + invalidAmountRequest.Amount = "" + invalidAmountResponse := APIError{Reason: core.ErrInvalidAmount.Error()} + + missingCurrencyRequest := newSpendRequest() + missingCurrencyRequest.Currency = nil + missingCurrencyRequest.CurrencyCode = "" + missingCurrencyResponse := APIError{Reason: repo.ErrCurrencyDefinitionUndefined.Error()} + + invalidAddrRequest := newSpendRequest() + invalidAddrRequest.Address = "invalid" + invalidAddrResponse := APIError{Reason: core.ErrInvalidSpendAddress.Error()} + + runAPITests(t, apiTests{ + { + "POST", "/wallet/spend", + insufficientFundsRequest, + 400, insufficientFundsResponse, + }, + { + "POST", "/wallet/spend", + invalidAmountRequest, + 400, invalidAmountResponse, + }, + { + "POST", "/wallet/spend", + missingCurrencyRequest, + 400, missingCurrencyResponse, + }, + { + "POST", "/wallet/spend", + invalidAddrRequest, + 400, invalidAddrResponse, + }, + }) +} + +func TestWalletCurrencyDictionary(t *testing.T) { + var expectedResponse, err = json.MarshalIndent(repo.AllCurrencies().AsMap(), "", " ") + if err != nil { + t.Fatal(err) + } + + runAPITests(t, apiTests{ + {"GET", "/wallet/currencies", "", 200, string(expectedResponse)}, + }) +} + +func TestWalletCurrencyDictionaryLookup(t *testing.T) { + var randomLookup string + for currency := range repo.TestnetCurrencies().AsMap() { + // pick any currency string from the dictionary + randomLookup = currency + break + } + + def, err := repo.AllCurrencies().Lookup(randomLookup) + if err != nil { + t.Fatalf("error looking up (%s): %s", randomLookup, err.Error()) + } + entries := map[string]repo.CurrencyDefinition{randomLookup: def} + expectedResponse, err := json.MarshalIndent(entries, "", " ") + if err != nil { + t.Fatal(err) + } + + runAPITests(t, apiTests{ + {"GET", fmt.Sprintf("/wallet/currencies/%s", randomLookup), "", 200, string(expectedResponse)}, + {"GET", fmt.Sprintf("/wallet/currencies/%s", "INVALID"), "", 404, errorResponseJSON(errors.New("unknown definition for INVALID"))}, + }) +} + func TestExchangeRates(t *testing.T) { runAPITests(t, apiTests{ {"GET", "/ob/exchangerates", "", 500, invalidCoinJSON}, @@ -581,7 +1041,7 @@ func TestCloseDisputeBlocksWhenExpired(t *testing.T) { func TestZECSalesCannotReleaseEscrow(t *testing.T) { sale := factory.NewSaleRecord() sale.Contract.VendorListings[0].Metadata.AcceptedCurrencies = []string{"ZEC"} - sale.Contract.BuyerOrder.Payment.Coin = "ZEC" + sale.Contract.BuyerOrder.Payment.AmountCurrency = &pb.CurrencyDefinition{Code: "ZEC", Divisibility: 8} dbSetup := func(testRepo *test.Repository) error { if err := testRepo.DB.Sales().Put(sale.OrderID, *sale.Contract, sale.OrderState, false); err != nil { return err @@ -596,7 +1056,7 @@ func TestZECSalesCannotReleaseEscrow(t *testing.T) { func TestSalesGet(t *testing.T) { sale := factory.NewSaleRecord() sale.Contract.VendorListings[0].Metadata.AcceptedCurrencies = []string{"BTC"} - sale.Contract.VendorListings[0].Metadata.CoinType = "ZEC" + //sale.Contract.VendorListings[0].Metadata.CoinType = "ZEC" sale.Contract.VendorListings[0].Metadata.ContractType = pb.Listing_Metadata_CRYPTOCURRENCY dbSetup := func(testRepo *test.Repository) error { return testRepo.DB.Sales().Put(sale.OrderID, *sale.Contract, sale.OrderState, false) @@ -626,9 +1086,9 @@ func TestSalesGet(t *testing.T) { if actualSale.BuyerId != sale.Contract.BuyerOrder.BuyerID.PeerID { t.Fatal("Incorrect buyerId:", actualSale.BuyerId, "\nwanted:", sale.Contract.BuyerOrder.BuyerID.PeerID) } - if actualSale.CoinType != sale.Contract.VendorListings[0].Metadata.CoinType { - t.Fatal("Incorrect coinType:", actualSale.CoinType, "\nwanted:", sale.Contract.VendorListings[0].Metadata.CoinType) - } + //if actualSale.CoinType != sale.Contract.VendorListings[0].Metadata.CoinType { + // t.Fatal("Incorrect coinType:", actualSale.CoinType, "\nwanted:", sale.Contract.VendorListings[0].Metadata.CoinType) + //} if actualSale.OrderId != sale.OrderID { t.Fatal("Incorrect orderId:", actualSale.OrderId, "\nwanted:", sale.OrderID) } @@ -648,7 +1108,7 @@ func TestSalesGet(t *testing.T) { func TestPurchasesGet(t *testing.T) { purchase := factory.NewPurchaseRecord() purchase.Contract.VendorListings[0].Metadata.AcceptedCurrencies = []string{"BTC"} - purchase.Contract.VendorListings[0].Metadata.CoinType = "ZEC" + //purchase.Contract.VendorListings[0].Metadata.CoinType = "ZEC" purchase.Contract.VendorListings[0].Metadata.ContractType = pb.Listing_Metadata_CRYPTOCURRENCY dbSetup := func(testRepo *test.Repository) error { return testRepo.DB.Purchases().Put(purchase.OrderID, *purchase.Contract, purchase.OrderState, false) @@ -678,9 +1138,9 @@ func TestPurchasesGet(t *testing.T) { if actualPurchase.VendorId != purchase.Contract.VendorListings[0].VendorID.PeerID { t.Fatal("Incorrect vendorId:", actualPurchase.VendorId, "\nwanted:", purchase.Contract.VendorListings[0].VendorID.PeerID) } - if actualPurchase.CoinType != purchase.Contract.VendorListings[0].Metadata.CoinType { - t.Fatal("Incorrect coinType:", actualPurchase.CoinType, "\nwanted:", purchase.Contract.VendorListings[0].Metadata.CoinType) - } + //if actualPurchase.CoinType != purchase.Contract.VendorListings[0].Metadata.CoinType { + // t.Fatal("Incorrect coinType:", actualPurchase.CoinType, "\nwanted:", purchase.Contract.VendorListings[0].Metadata.CoinType) + //} if actualPurchase.OrderId != purchase.OrderID { t.Fatal("Incorrect orderId:", actualPurchase.OrderId, "\nwanted:", purchase.OrderID) } @@ -702,7 +1162,7 @@ func TestCasesGet(t *testing.T) { paymentCoinCode := repo.CurrencyCode("BTC") disputeCaseRecord := factory.NewDisputeCaseRecord() disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.AcceptedCurrencies = []string{"BTC"} - disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.CoinType = "ZEC" + //disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.CoinType = "ZEC" disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.ContractType = pb.Listing_Metadata_CRYPTOCURRENCY disputeCaseRecord.CoinType = "ZEC" disputeCaseRecord.PaymentCoin = &paymentCoinCode @@ -728,9 +1188,9 @@ func TestCasesGet(t *testing.T) { actualCase := respObj.Cases[0] - if actualCase.CoinType != disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.CoinType { - t.Fatal("Incorrect coinType:", actualCase.CoinType, "\nwanted:", disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.CoinType) - } + //if actualCase.CoinType != disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.CoinType { + // t.Fatal("Incorrect coinType:", actualCase.CoinType, "\nwanted:", disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.CoinType) + //} if actualCase.PaymentCoin != disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.AcceptedCurrencies[0] { t.Fatal("Incorrect paymentCoin:", actualCase.PaymentCoin, "\nwanted:", disputeCaseRecord.BuyerContract.VendorListings[0].Metadata.AcceptedCurrencies[0]) } @@ -807,7 +1267,7 @@ func TestNotificationsAreReturnedInExpectedOrder(t *testing.T) { createdAt = time.Unix(837645345, 0) notif1 = &repo.Notification{ ID: "notif1", - CreatedAt: createdAt, + CreatedAt: repo.NewAPITime(createdAt), NotifierType: repo.NotifierTypeFollowNotification, NotifierData: &repo.FollowNotification{ ID: "notif1", @@ -817,7 +1277,7 @@ func TestNotificationsAreReturnedInExpectedOrder(t *testing.T) { } notif2 = &repo.Notification{ ID: "notif2", - CreatedAt: createdAt, + CreatedAt: repo.NewAPITime(createdAt), NotifierType: repo.NotifierTypeFollowNotification, NotifierData: &repo.FollowNotification{ ID: "notif2", @@ -827,7 +1287,7 @@ func TestNotificationsAreReturnedInExpectedOrder(t *testing.T) { } notif3 = &repo.Notification{ ID: "notif3", - CreatedAt: createdAt, + CreatedAt: repo.NewAPITime(createdAt), NotifierType: repo.NotifierTypeFollowNotification, NotifierData: &repo.FollowNotification{ ID: "notif3", @@ -858,6 +1318,43 @@ func TestNotificationsAreReturnedInExpectedOrder(t *testing.T) { }, dbSetup, dbTeardown) } +func TestResendOrderMessage(t *testing.T) { + runAPITests(t, apiTests{ + // supports missing messageType + {"POST", "/ob/resendordermessage", `{"orderID":"123"}`, http.StatusBadRequest, errorResponseJSON(fmt.Errorf("missing messageType argument"))}, + // supports missing order ID + {"POST", "/ob/resendordermessage", `{"messageType":"nonexistant"}`, http.StatusBadRequest, errorResponseJSON(fmt.Errorf("missing orderID argument"))}, + // supports nonexistant message types + {"POST", "/ob/resendordermessage", `{"orderID":"123","messageType":"nonexistant"}`, http.StatusBadRequest, errorResponseJSON(fmt.Errorf("unknown messageType (nonexistant)"))}, + // supports downcased message types, expected not to find order ID + {"POST", "/ob/resendordermessage", `{"orderID":"123","messageType":"order"}`, http.StatusInternalServerError, errorResponseJSON(fmt.Errorf("unable to find message for order ID (123) and message type (ORDER)"))}, + }) +} + +func TestManageWallet(t *testing.T) { + const initWalletResponse = `{"isLocked": "false"}` + const unlockWalletResponse = `{ + "isEncrypted": "false", + "isLocked": "false" + }` + //const lockWalletResponse = `{"isLocked": "true"}` + const unlockFailedResponse = `{ + "success": false, + "reason": "cipher: message authentication failed" + }` + + runAPITests(t, apiTests{ + // init wallet trial + {"POST", "/manage/initwallet", `{"password":"secret"}`, 200, initWalletResponse}, + // wallet not encrypted and skip mnemonic unlocking procedure + {"POST", "/manage/unlockwallet", `{"skipCrypt":true}`, 200, unlockWalletResponse}, + // wallet not encrypted and tries to unlock mnemonic + {"POST", "/manage/unlockwallet", `{"password":"secret"}`, 400, unlockFailedResponse}, + //TODO add lockwallet test, but now it affects another tests. + //{"POST", "/manage/lockwallet", `{"password":"secret"}`, 200, lockWalletResponse}, + }) +} + // TODO: Make NewDisputeCaseRecord return a valid fixture for this valid case to work //func TestCloseDisputeReturnsOK(t *testing.T) { //dbSetup := func(testRepo *test.Repository) error { diff --git a/api/notifier.go b/api/notifier.go index f77fd7b26f..cd5cebdb66 100644 --- a/api/notifier.go +++ b/api/notifier.go @@ -6,8 +6,8 @@ import ( "net/smtp" "strings" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/repo" ) // Notification manager intercepts data form 'inChan' which is embedded @@ -68,7 +68,14 @@ func (m *notificationManager) getNotifiers() []notifier { // SMTP notifier conf := settings.SMTPSettings + + profile, err := m.node.GetProfile() + if err != nil { + return nil + } + if conf != nil && conf.Notifications { + conf.OpenBazaarName = profile.Name notifiers = append(notifiers, &smtpNotifier{settings: conf}) } return notifiers @@ -85,7 +92,7 @@ func (notifier *smtpNotifier) notify(n repo.Notifier) error { "To: %s", "MIME-Version: 1.0", "Content-Type: text/html; charset=UTF-8", - "Subject: [Phore Marketplace] %s\r\n", + "Subject: [Phore Marketplace - %s] %s\r\n", "%s\r\n", }, "\r\n") head, body, ok := n.GetSMTPTitleAndBody() @@ -93,7 +100,7 @@ func (notifier *smtpNotifier) notify(n repo.Notifier) error { return nil } conf := notifier.settings - data := fmt.Sprintf(template, conf.SenderEmail, conf.RecipientEmail, head, body) + data := fmt.Sprintf(template, conf.SenderEmail, conf.RecipientEmail, conf.OpenBazaarName, head, body) return sendEmail(notifier.settings, []byte(data)) } diff --git a/api/utils.go b/api/utils.go index c76ba91484..f30f64a5e0 100644 --- a/api/utils.go +++ b/api/utils.go @@ -5,7 +5,7 @@ import ( "strconv" "strings" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) type TransactionQuery struct { diff --git a/api/ws.go b/api/ws.go index ce7775cbb8..73e650c449 100644 --- a/api/ws.go +++ b/api/ws.go @@ -9,8 +9,8 @@ import ( "github.com/gorilla/websocket" "github.com/op/go-logging" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/schema" ) type connection struct { diff --git a/bitcoin/phored/wallet.go b/bitcoin/phored/wallet.go deleted file mode 100644 index e21f6f968f..0000000000 --- a/bitcoin/phored/wallet.go +++ /dev/null @@ -1,1268 +0,0 @@ -package phored - -import ( - "bytes" - "encoding/hex" - "errors" - "fmt" - "path" - "sort" - "strings" - "sync" - "time" - - "github.com/phoreproject/btcd/blockchain" - "github.com/phoreproject/btcd/btcec" - "github.com/phoreproject/btcd/chaincfg" - "github.com/phoreproject/btcd/chaincfg/chainhash" - "github.com/phoreproject/btcd/rpcclient" - "github.com/phoreproject/btcd/txscript" - "github.com/phoreproject/btcd/wire" - btc "github.com/phoreproject/btcutil" - "github.com/phoreproject/btcutil/coinset" - hd "github.com/phoreproject/btcutil/hdkeychain" - "github.com/phoreproject/btcutil/txsort" - "github.com/phoreproject/btcwallet/wallet/txrules" - "github.com/phoreproject/spvwallet" - "github.com/phoreproject/wallet-interface" - b39 "github.com/tyler-smith/go-bip39" -) - -const ( - // Account is the name for the Bitcoin wallet account - Account = "OpenBazaar" -) - -// RPCWallet represents a wallet based on JSON-RPC and Bitcoind -type RPCWallet struct { - params *chaincfg.Params - - masterPrivateKey *hd.ExtendedKey - masterPublicKey *hd.ExtendedKey - - mnemonic string - - //feeProvider *FeeProvider - - repoPath string - - rpcClient *rpcclient.Client - - keyManager *spvwallet.KeyManager - - txstore *TxStore - connCfg *rpcclient.ConnConfig - notifications *NotificationListener - rpcBasePath string - rpcLock *sync.Mutex - - started bool -} - -// NewRPCWallet creates a new wallet given -func NewRPCWallet(mnemonic string, params *chaincfg.Params, repoPath string, DB wallet.Datastore, host string) (*RPCWallet, error) { - if mnemonic == "" { - ent, _ := b39.NewEntropy(256) - mnemonic, _ = b39.NewMnemonic(ent) - } - - connCfg := &rpcclient.ConnConfig{ - Host: path.Join(host, "rpc"), - HTTPPostMode: true, - DisableTLS: false, - DisableAutoReconnect: false, - DisableConnectOnNew: false, - } - - seed, err := b39.NewSeedWithErrorChecking(mnemonic, "") - if err != nil { - return nil, err - } - - mPrivKey, err := hd.NewMaster(seed, params) - if err != nil { - return nil, err - } - mPubKey, err := mPrivKey.Neuter() - if err != nil { - return nil, err - } - - keyManager, err := spvwallet.NewKeyManager(DB.Keys(), params, mPrivKey, wallet.Phore) - if err != nil { - return nil, err - } - - txstore, err := NewTxStore(params, DB, keyManager) - if err != nil { - return nil, err - } - - w := RPCWallet{ - params: params, - repoPath: repoPath, - masterPrivateKey: mPrivKey, - masterPublicKey: mPubKey, - keyManager: keyManager, - txstore: txstore, - connCfg: connCfg, - rpcBasePath: host, - rpcLock: new(sync.Mutex), - } - return &w, nil -} - -// Start sets up the rpc wallet -func (w *RPCWallet) Start() { - client, _ := rpcclient.New(w.connCfg, nil) - w.rpcClient = client - - ticker := time.NewTicker(time.Second * 30) - go func() { - for range ticker.C { - log.Fatal("Failed to connect to phored") - } - }() - for { - _, err := client.GetBlockCount() - if err == nil { - break - } - time.Sleep(time.Second) - } - ticker.Stop() - - // notification listener must start after rpc connection is stabilized - n, err := startNotificationListener(w) - if err != nil { - log.Error(err) - return - } - w.notifications = n - - err = w.RetrieveTransactions() - if err != nil { - log.Error(err) - return - } - - w.notifications.updateFilterAndSend() - - unbroadcastedTransactions, err := w.txstore.GetPendingInv() - if err != nil { - log.Error(err) - return - } - - for tx := range unbroadcastedTransactions.InvList { - hash := unbroadcastedTransactions.InvList[tx].Hash - log.Debugf("Found transaction unbroadcasted: %s", hash.String()) - txn, err := w.txstore.Txns().Get(hash) - if err != nil { - log.Error(err) - continue - } - - r := bytes.NewReader(txn.Bytes) - transaction := wire.NewMsgTx(wire.TxVersion) - transaction.DeserializeNoWitness(r) - err = w.Broadcast(transaction) - if err != nil { - if strings.HasPrefix(err.Error(), "-27") { - // transaction is already in the blockchain, so go retrieve it - res, err := w.rpcClient.GetRawTransactionVerbose(&hash) - if err != nil { - log.Error(err) - continue - } - - blockHash, err := chainhash.NewHashFromStr(res.BlockHash) - if err != nil { - log.Error(err) - continue - } - - w.rpcLock.Lock() - block, err := w.rpcClient.GetBlockVerbose(blockHash) - w.rpcLock.Unlock() - - if err != nil { - log.Error(err) - continue - } - - transactionBytes, err := hex.DecodeString(res.Hex) - if err != nil { - log.Error(err) - continue - } - - transaction := wire.MsgTx{} - err = transaction.BtcDecode(bytes.NewReader(transactionBytes), 1, wire.BaseEncoding) - if err != nil { - log.Error(err) - continue - } - - w.txstore.Ingest(&transaction, int32(block.Height), time.Unix(block.Time, 0)) - } else if strings.HasPrefix(err.Error(), "-26") { - // transaction is spending inputs already spent, so we should just remove it - w.txstore.Txns().Delete(&hash) - } else { - log.Error(err) - } - } - } - - log.Info("Connected to phored") - w.started = true -} - -// CurrencyCode returns the currency code of the wallet -func (w *RPCWallet) CurrencyCode() string { - if w.params.Name == chaincfg.MainNetParams.Name { - return "phr" - } else { - return "tphr" - } -} - -// IsDust determines if an amount is considered dust -func (w *RPCWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btc.Amount(amount), 25, txrules.DefaultRelayFeePerKb) -} - -// MasterPrivateKey returns the wallet's master private key -func (w *RPCWallet) MasterPrivateKey() *hd.ExtendedKey { - return w.masterPrivateKey -} - -// MasterPublicKey returns the wallet's key used to derive public keys -func (w *RPCWallet) MasterPublicKey() *hd.ExtendedKey { - return w.masterPublicKey -} - -func (w *RPCWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) { - parentFP := []byte{0x00, 0x00, 0x00, 0x00} - var id []byte - if isPrivateKey { - id = w.params.HDPrivateKeyID[:] - } else { - id = w.params.HDPublicKeyID[:] - } - hdKey := hd.NewExtendedKey( - id, - keyBytes, - chaincode, - parentFP, - 0, - 0, - isPrivateKey) - return hdKey.Child(0) -} - -// Mnemonic returns the mnemonic used to generate the wallet -func (w *RPCWallet) Mnemonic() string { - return w.mnemonic -} - -// CurrentAddress returns an unused address -func (w *RPCWallet) CurrentAddress(purpose wallet.KeyPurpose) btc.Address { - key, _ := w.keyManager.GetCurrentKey(purpose) - addr, _ := key.Address(w.params) - return btc.Address(addr) -} - -// NewAddress creates a new address -func (w *RPCWallet) NewAddress(purpose wallet.KeyPurpose) btc.Address { - i, _ := w.txstore.Keys().GetUnused(purpose) - key, _ := w.keyManager.GenerateChildKey(purpose, uint32(i[1])) - addr, _ := key.Address(w.params) - w.txstore.Keys().MarkKeyAsUsed(addr.ScriptAddress()) - w.txstore.PopulateAdrs() - return btc.Address(addr) -} - -// DecodeAddress decodes an address string to an address using the wallet's chain parameters -func (w *RPCWallet) DecodeAddress(addr string) (btc.Address, error) { - return btc.DecodeAddress(addr, w.params) -} - -// ScriptToAddress converts a script to an address -func (w *RPCWallet) ScriptToAddress(script []byte) (btc.Address, error) { - return scriptToAddress(script, w.params) -} - -func scriptToAddress(script []byte, params *chaincfg.Params) (btc.Address, error) { - _, addrs, _, err := txscript.ExtractPkScriptAddrs(script, params) - if err != nil { - return &btc.AddressPubKeyHash{}, err - } - if len(addrs) == 0 { - return &btc.AddressPubKeyHash{}, errors.New("unknown script") - } - return addrs[0], nil -} - -// AddressToScript returns the script for a given address -func (w *RPCWallet) AddressToScript(addr btc.Address) ([]byte, error) { - return txscript.PayToAddrScript(addr) -} - -// HasKey returns true if we have the private key for a given address -func (w *RPCWallet) HasKey(addr btc.Address) bool { - _, err := w.keyManager.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - return false - } - return true -} - -// GetKey gets the private key for a certain address -func (w *RPCWallet) GetKey(addr btc.Address) (*btcec.PrivateKey, error) { - key, err := w.keyManager.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - return nil, err - } - return key.ECPrivKey() -} - -// ListAddresses lists our currently used addresses -func (w *RPCWallet) ListAddresses() []btc.Address { - keys := w.keyManager.GetKeys() - addrs := []btc.Address{} - for _, k := range keys { - addr, err := k.Address(w.params) - if err != nil { - continue - } - addrs = append(addrs, addr) - } - return addrs -} - -// ListKeys lists our currently used keys -func (w *RPCWallet) ListKeys() []btcec.PrivateKey { - keys := w.keyManager.GetKeys() - list := []btcec.PrivateKey{} - for _, k := range keys { - priv, err := k.ECPrivKey() - if err != nil { - continue - } - list = append(list, *priv) - } - return list -} - -// Balance returns the total balance of our addresses -func (w *RPCWallet) Balance() (confirmed, unconfirmed int64) { - utxos, _ := w.txstore.Utxos().GetAll() - stxos, _ := w.txstore.Stxos().GetAll() - for _, utxo := range utxos { - if !utxo.WatchOnly { - if utxo.AtHeight > 0 { - confirmed += utxo.Value - } else { - if w.checkIfStxoIsConfirmed(utxo, stxos) { - confirmed += utxo.Value - } else { - unconfirmed += utxo.Value - } - } - } - } - return confirmed, unconfirmed -} - -// Transactions returns all of the transactions relating to any of our addresses -func (w *RPCWallet) Transactions() ([]wallet.Txn, error) { - height, _ := w.ChainTip() - txns, err := w.txstore.Txns().GetAll(false) - if err != nil { - return txns, err - } - for i, tx := range txns { - var confirmations int32 - var status wallet.StatusCode - confs := int32(height) - tx.Height + 1 - if tx.Height <= 0 { - confs = tx.Height - } - switch { - case confs < 0: - status = wallet.StatusDead - case confs == 0 && time.Since(tx.Timestamp) <= time.Minute*15: - status = wallet.StatusUnconfirmed - case confs == 0 && time.Since(tx.Timestamp) > time.Minute*15: - status = wallet.StatusDead - case confs > 0 && confs < 6: - status = wallet.StatusPending - confirmations = confs - case confs > 5: - status = wallet.StatusConfirmed - confirmations = confs - } - tx.Confirmations = int64(confirmations) - tx.Status = status - txns[i] = tx - } - return txns, nil -} - -// GetTransaction returns the transaction given by a transaction hash -func (w *RPCWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) { - return w.txstore.Txns().Get(txid) -} - -// GetConfirmations returns the number of confirmations and the block number where the transaction was confirmed -func (w *RPCWallet) GetConfirmations(txid chainhash.Hash) (uint32, uint32, error) { - txn, err := w.txstore.Txns().Get(txid) - if err != nil { - return 0, 0, err - } - if txn.Height == 0 { - return 0, 0, nil - } - chainTip, _ := w.ChainTip() - return chainTip - uint32(txn.Height) + 1, uint32(txn.Height), nil -} - -func (w *RPCWallet) checkIfStxoIsConfirmed(utxo wallet.Utxo, stxos []wallet.Stxo) bool { - for _, stxo := range stxos { - if !stxo.Utxo.WatchOnly { - if stxo.SpendTxid.IsEqual(&utxo.Op.Hash) { - if stxo.SpendHeight > 0 { - return true - } else { - return w.checkIfStxoIsConfirmed(stxo.Utxo, stxos) - } - } else if stxo.Utxo.IsEqual(&utxo) { - if stxo.Utxo.AtHeight > 0 { - return true - } else { - return false - } - } - } - } - return false -} - -// Params returns the current wallet's chain params -func (w *RPCWallet) Params() *chaincfg.Params { - return w.params -} - -// AddTransactionListener adds a listener for any wallet transactions -func (w *RPCWallet) AddTransactionListener(callback func(wallet.TransactionCallback)) { - w.txstore.listeners = append(w.txstore.listeners, callback) -} - -// ChainTip returns the tip of the active blockchain -func (w *RPCWallet) ChainTip() (uint32, chainhash.Hash) { - w.rpcLock.Lock() - ch, err := w.rpcClient.GetBestBlockHash() - if err != nil { - return 0, chainhash.Hash{} - } - - height, err := w.rpcClient.GetBlockCount() - if err != nil { - return 0, chainhash.Hash{} - } - w.rpcLock.Unlock() - return uint32(height), *ch -} - -func (w *RPCWallet) AddWatchedAddress(addr btc.Address) error { - script, err := w.AddressToScript(addr) - if err != nil { - return err - } - err = w.txstore.WatchedScripts().Put(script) - w.txstore.PopulateAdrs() - if err != nil { - return err - } - log.Debugf("addWatchedAddress %s\n", addr.String()) - return nil -} - -func (w *RPCWallet) addWatchedScript(addr btc.Address) error { - return w.rpcClient.ImportAddressRescan(addr.EncodeAddress(), "", false) -} - -// ReSyncBlockchain resyncs the addresses used by the SPV wallet -func (w *RPCWallet) ReSyncBlockchain(fromDate time.Time) { - if w.started { - w.txstore.PopulateAdrs() - w.RetrieveTransactions() - w.notifications.updateFilterAndSend() - } -} - -// Close closes the rpc wallet connection -func (w *RPCWallet) Close() { - if w.started { - log.Info("Disconnecting from peers and shutting down") - w.rpcLock.Lock() - defer w.rpcLock.Unlock() - - // add timer to shutdown execution - ch := make(chan bool, 1) - defer close(ch) - - go func() { - w.rpcClient.Shutdown() - ch <- true - }() - - select { - case <-ch: - log.Debugf("RPC client shutdown normally") - case <-time.After(60 * time.Second): - log.Debugf("RPC client shutdown timeout") - } - w.started = false - } -} - -// SweepAddress sweeps any UTXOs from an address in a single transaction -func (w *RPCWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wallet.FeeLevel) (*chainhash.Hash, error) { - var internalAddr btc.Address - if address != nil { - internalAddr = *address - } else { - internalAddr = w.CurrentAddress(wallet.INTERNAL) - } - script, err := txscript.PayToAddrScript(internalAddr) - if err != nil { - return nil, err - } - - var val int64 - var inputs []*wire.TxIn - additionalPrevScripts := make(map[wire.OutPoint][]byte) - for _, in := range ins { - val += in.Value - ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) - if err != nil { - return nil, err - } - script, err := txscript.PayToAddrScript(in.LinkedAddress) - if err != nil { - return nil, err - } - outpoint := wire.NewOutPoint(ch, in.OutpointIndex) - input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) - inputs = append(inputs, input) - additionalPrevScripts[*outpoint] = script - } - out := wire.NewTxOut(val, script) - - txType := spvwallet.P2PKH - if redeemScript != nil { - txType = spvwallet.P2SH_1of2_Multisig - _, err := spvwallet.LockTimeFromRedeemScript(*redeemScript) - if err == nil { - txType = spvwallet.P2SH_Multisig_Timelock_1Sig - } - } - estimatedSize := spvwallet.EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) - - // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) - fee := estimatedSize * feePerByte - - outVal := val - int64(fee) - if outVal < 0 { - outVal = 0 - } - out.Value = outVal - - tx := &wire.MsgTx{ - Version: wire.TxVersion, - TxIn: inputs, - TxOut: []*wire.TxOut{out}, - LockTime: 0, - } - - // BIP 69 sorting - txsort.InPlaceSort(tx) - - // Sign tx - privKey, err := key.ECPrivKey() - if err != nil { - return nil, err - } - pk := privKey.PubKey().SerializeCompressed() - addressPub, err := btc.NewAddressPubKey(pk, w.params) - if err != nil { - return nil, err - } - - getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { - if addressPub.EncodeAddress() == addr.EncodeAddress() { - wif, err := btc.NewWIF(privKey, w.params, true) - if err != nil { - return nil, false, err - } - return wif.PrivKey, wif.CompressPubKey, nil - } - return nil, false, errors.New("Not found") - }) - getScript := txscript.ScriptClosure(func(addr btc.Address) ([]byte, error) { - if redeemScript == nil { - return []byte{}, nil - } - return *redeemScript, nil - }) - - // Check if time locked - if redeemScript != nil { - rs := *redeemScript - if rs[0] == txscript.OP_IF { - tx.Version = wire.TxVersion - for _, txIn := range tx.TxIn { - locktime, err := spvwallet.LockTimeFromRedeemScript(*redeemScript) - if err != nil { - return nil, err - } - txIn.Sequence = locktime - } - } - } - - for i, txIn := range tx.TxIn { - prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] - script, err := txscript.SignTxOutput(w.params, - tx, i, prevOutScript, txscript.SigHashAll, getKey, - getScript, txIn.SignatureScript) - if err != nil { - return nil, errors.New("Failed to sign transaction") - } - txIn.SignatureScript = script - } - - err = w.Broadcast(tx) - if err != nil { - log.Errorf("SweepAddress.Broadcast error: %s", err) - } - txid := tx.TxHash() - return &txid, nil -} - -// GetFeePerByte gets the fee in pSAT per byte -func (w *RPCWallet) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 { - return 25 -} - -// Broadcast a transaction to the network -func (w *RPCWallet) Broadcast(tx *wire.MsgTx) error { - // Our own tx; don't keep track of false positives - _, err := w.txstore.Ingest(tx, 0, time.Now()) - if err != nil { - return err - } - - w.rpcLock.Lock() - _, err = w.rpcClient.SendRawTransaction(tx, false) - w.rpcLock.Unlock() - if err != nil { - return err - } - - w.notifications.updateFilterAndSend() - return nil -} - -// BumpFee attempts to bump the fee for a transaction -func (w *RPCWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { - includeWatchOnly := false - tx, err := w.rpcClient.GetTransaction(&txid, &includeWatchOnly) - if err != nil { - return nil, err - } - if tx.Confirmations > 0 { - return nil, spvwallet.BumpFeeAlreadyConfirmedError - } - unspent, err := w.rpcClient.ListUnspent() - if err != nil { - return nil, err - } - for _, u := range unspent { - if u.TxID == txid.String() { - if u.Confirmations > 0 { - return nil, spvwallet.BumpFeeAlreadyConfirmedError - } - h, err := chainhash.NewHashFromStr(u.TxID) - if err != nil { - continue - } - addr, err := btc.DecodeAddress(u.Address, w.params) - if err != nil { - continue - } - key, err := w.rpcClient.DumpPrivKey(addr) - if err != nil { - continue - } - in := wallet.TransactionInput{ - LinkedAddress: addr, - OutpointIndex: u.Vout, - OutpointHash: h.CloneBytes(), - Value: int64(u.Amount), - } - hdKey := hd.NewExtendedKey(w.params.HDPrivateKeyID[:], key.PrivKey.Serialize(), make([]byte, 32), make([]byte, 4), 0, 0, true) - transactionID, err := w.SweepAddress([]wallet.TransactionInput{in}, nil, hdKey, nil, wallet.FEE_BUMP) - if err != nil { - return nil, err - } - return transactionID, nil - } - } - return nil, spvwallet.BumpFeeNotFoundError -} - -// CreateMultisigSignature creates a multisig signature given the transaction inputs and outputs and the keys -func (w *RPCWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wallet.Signature, error) { - var sigs []wallet.Signature - tx := wire.NewMsgTx(1) - for _, in := range ins { - ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) - if err != nil { - return sigs, err - } - outpoint := wire.NewOutPoint(ch, in.OutpointIndex) - input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) - tx.TxIn = append(tx.TxIn, input) - } - for _, out := range outs { - scriptPubKey, err := w.AddressToScript(out.Address) - if err != nil { - return sigs, err - } - - output := wire.NewTxOut(out.Value, scriptPubKey) - tx.TxOut = append(tx.TxOut, output) - } - - // Subtract fee - txType := spvwallet.P2SH_2of3_Multisig - _, err := spvwallet.LockTimeFromRedeemScript(redeemScript) - if err == nil { - txType = spvwallet.P2SH_Multisig_Timelock_2Sigs - } - estimatedSize := spvwallet.EstimateSerializeSize(len(ins), tx.TxOut, false, txType) - fee := estimatedSize * int(feePerByte) - if len(tx.TxOut) > 0 { - feePerOutput := fee / len(tx.TxOut) - for _, output := range tx.TxOut { - output.Value -= int64(feePerOutput) - } - } - - // BIP 69 sorting - txsort.InPlaceSort(tx) - - signingKey, err := key.ECPrivKey() - if err != nil { - return sigs, err - } - - for i := range tx.TxIn { - sig, err := txscript.RawTxInSignature(tx, i, redeemScript, txscript.SigHashAll, signingKey) - if err != nil { - continue - } - bs := wallet.Signature{InputIndex: uint32(i), Signature: sig} - sigs = append(sigs, bs) - } - return sigs, nil -} - -// EstimateFee estimates the fee of a transaction -func (w *RPCWallet) EstimateFee(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, feePerByte uint64) uint64 { - tx := new(wire.MsgTx) - for _, out := range outs { - scriptPubKey, _ := w.AddressToScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) - tx.TxOut = append(tx.TxOut, output) - } - estimatedSize := spvwallet.EstimateSerializeSize(len(ins), tx.TxOut, false, spvwallet.P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) -} - -// EstimateSpendFee builds a spend transaction for the amount and return the transaction fee -func (w *RPCWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (uint64, error) { - // Since this is an estimate we can use a dummy output address. Let's use a long one so we don't under estimate. - addr, err := btc.DecodeAddress("PARPpSkk5wpji6kE2y9YxHGZ9k96wZPfin", w.params) - if err != nil { - return 0, err - } - tx, err := w.buildTx(amount, addr, feeLevel, nil) - if err != nil { - return 0, err - } - var outval int64 - for _, output := range tx.TxOut { - outval += output.Value - } - var inval int64 - utxos, err := w.txstore.Utxos().GetAll() - if err != nil { - return 0, err - } - for _, input := range tx.TxIn { - for _, utxo := range utxos { - if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value - break - } - } - } - if inval < outval { - return 0, errors.New("Error building transaction: inputs less than outputs") - } - return uint64(inval - outval), err -} - -func (w *RPCWallet) gatherCoins() map[coinset.Coin]*hd.ExtendedKey { - w.rpcLock.Lock() - height, _ := w.rpcClient.GetBlockCount() - w.rpcLock.Unlock() - utxos, _ := w.txstore.Utxos().GetAll() - m := make(map[coinset.Coin]*hd.ExtendedKey) - for _, u := range utxos { - if u.WatchOnly { - continue - } - var confirmations int32 - if u.AtHeight > 0 { - confirmations = int32(height) - u.AtHeight - } - c := spvwallet.NewCoin(u.Op.Hash.CloneBytes(), u.Op.Index, btc.Amount(u.Value), int64(confirmations), u.ScriptPubkey) - addr, err := w.ScriptToAddress(u.ScriptPubkey) - if err != nil { - continue - } - key, err := w.keyManager.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - continue - } - m[c] = key - } - return m -} - -func (w *RPCWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, optionalOutput *wire.TxOut) (*wire.MsgTx, error) { - // Check for dust - script, _ := txscript.PayToAddrScript(addr) - if txrules.IsDustAmount(btc.Amount(amount), len(script), txrules.DefaultRelayFeePerKb) { - return nil, wallet.ErrorDustAmount - } - - var additionalPrevScripts map[wire.OutPoint][]byte - var additionalKeysByAddress map[string]*btc.WIF - var inVals map[wire.OutPoint]int64 - - // Create input source - coinMap := w.gatherCoins() - coins := make([]coinset.Coin, 0, len(coinMap)) - for k := range coinMap { - coins = append(coins, k) - } - inputSource := func(target btc.Amount) (total btc.Amount, inputs []*wire.TxIn, amounts []btc.Amount, scripts [][]byte, err error) { - coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)} - coins, err := coinSelector.CoinSelect(target, coins) - if err != nil { - return total, inputs, []btc.Amount{}, scripts, errors.New("insuffient funds") - } - additionalPrevScripts = make(map[wire.OutPoint][]byte) - inVals = make(map[wire.OutPoint]int64) - additionalKeysByAddress = make(map[string]*btc.WIF) - for _, c := range coins.Coins() { - total += c.Value() - outpoint := wire.NewOutPoint(c.Hash(), c.Index()) - in := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) - inputs = append(inputs, in) - additionalPrevScripts[*outpoint] = c.PkScript() - key := coinMap[c] - addr, err := key.Address(w.params) - if err != nil { - continue - } - privKey, err := key.ECPrivKey() - if err != nil { - continue - } - wif, _ := btc.NewWIF(privKey, w.params, true) - additionalKeysByAddress[addr.EncodeAddress()] = wif - val := c.Value() - sat := val.ToUnit(btc.AmountSatoshi) - inVals[*outpoint] = int64(sat) - } - return total, inputs, []btc.Amount{}, scripts, nil - } - - // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 - - // outputs - out := wire.NewTxOut(amount, script) - - // Create change source - changeSource := func() ([]byte, error) { - addr := w.CurrentAddress(wallet.INTERNAL) - script, err := txscript.PayToAddrScript(addr) - if err != nil { - return []byte{}, err - } - return script, nil - } - - outputs := []*wire.TxOut{out} - if optionalOutput != nil { - outputs = append(outputs, optionalOutput) - } - authoredTx, err := spvwallet.NewUnsignedTransaction(outputs, btc.Amount(feePerKB), inputSource, changeSource) - if err != nil { - return nil, err - } - - // BIP 69 sorting - txsort.InPlaceSort(authoredTx.Tx) - - // Sign tx - getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { - addrStr := addr.EncodeAddress() - wif := additionalKeysByAddress[addrStr] - return wif.PrivKey, wif.CompressPubKey, nil - }) - getScript := txscript.ScriptClosure(func( - addr btc.Address) ([]byte, error) { - return []byte{}, nil - }) - for i, txIn := range authoredTx.Tx.TxIn { - prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] - script, err := txscript.SignTxOutput(w.params, - authoredTx.Tx, i, prevOutScript, txscript.SigHashAll, getKey, - getScript, txIn.SignatureScript) - if err != nil { - return nil, errors.New("Failed to sign transaction") - } - txIn.SignatureScript = script - } - return authoredTx.Tx, nil -} - -// GenerateMultisigScript generates a script representing a multisig wallet -func (w *RPCWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) { - if uint32(timeout.Hours()) > 0 && timeoutKey == nil { - return nil, nil, errors.New("Timeout key must be non nil when using an escrow timeout") - } - - if len(keys) < threshold { - return nil, nil, fmt.Errorf("unable to generate multisig script with "+ - "%d required signatures when there are only %d public "+ - "keys available", threshold, len(keys)) - } - - var ecKeys []*btcec.PublicKey - for _, key := range keys { - ecKey, err := key.ECPubKey() - if err != nil { - return nil, nil, err - } - ecKeys = append(ecKeys, ecKey) - } - - builder := txscript.NewScriptBuilder() - if uint32(timeout.Hours()) == 0 { - - builder.AddInt64(int64(threshold)) - for _, key := range ecKeys { - builder.AddData(key.SerializeCompressed()) - } - builder.AddInt64(int64(len(ecKeys))) - builder.AddOp(txscript.OP_CHECKMULTISIG) - - } else { - ecKey, err := timeoutKey.ECPubKey() - if err != nil { - return nil, nil, err - } - sequenceLock := blockchain.LockTimeToSequence(false, uint32(timeout.Hours()*6)) - builder.AddOp(txscript.OP_IF) - builder.AddInt64(int64(threshold)) - for _, key := range ecKeys { - builder.AddData(key.SerializeCompressed()) - } - builder.AddInt64(int64(len(ecKeys))) - builder.AddOp(txscript.OP_CHECKMULTISIG) - builder.AddOp(txscript.OP_ELSE). - AddInt64(int64(sequenceLock)). - AddOp(txscript.OP_CHECKSEQUENCEVERIFY). - AddOp(txscript.OP_DROP). - AddData(ecKey.SerializeCompressed()). - AddOp(txscript.OP_CHECKSIG). - AddOp(txscript.OP_ENDIF) - } - redeemScript, err = builder.Script() - if err != nil { - return nil, nil, err - } - - addr, err = btc.NewAddressScriptHash(redeemScript, w.params) - if err != nil { - return nil, nil, err - } - return addr, redeemScript, nil -} - -// Multisign signs a multisig transaction -func (w *RPCWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, sigs1 []wallet.Signature, sigs2 []wallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - tx := wire.NewMsgTx(1) - for _, in := range ins { - ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) - if err != nil { - return nil, err - } - outpoint := wire.NewOutPoint(ch, in.OutpointIndex) - input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) - tx.TxIn = append(tx.TxIn, input) - } - for _, out := range outs { - scriptPubKey, err := w.AddressToScript(out.Address) - if err != nil { - return nil, err - } - output := wire.NewTxOut(out.Value, scriptPubKey) - tx.TxOut = append(tx.TxOut, output) - } - - // Subtract fee - txType := spvwallet.P2SH_2of3_Multisig - _, err := spvwallet.LockTimeFromRedeemScript(redeemScript) - if err == nil { - txType = spvwallet.P2SH_Multisig_Timelock_2Sigs - } - estimatedSize := spvwallet.EstimateSerializeSize(len(ins), tx.TxOut, false, txType) - fee := estimatedSize * int(feePerByte) - if len(tx.TxOut) > 0 { - feePerOutput := fee / len(tx.TxOut) - for _, output := range tx.TxOut { - output.Value -= int64(feePerOutput) - } - } - - // BIP 69 sorting - txsort.InPlaceSort(tx) - - // Check if time locked - var timeLocked bool - if redeemScript[0] == txscript.OP_IF { - timeLocked = true - } - - for i, input := range tx.TxIn { - var sig1 []byte - var sig2 []byte - for _, sig := range sigs1 { - if int(sig.InputIndex) == i { - sig1 = sig.Signature - break - } - } - for _, sig := range sigs2 { - if int(sig.InputIndex) == i { - sig2 = sig.Signature - break - } - } - builder := txscript.NewScriptBuilder() - builder.AddOp(txscript.OP_0) - builder.AddData(sig1) - builder.AddData(sig2) - - if timeLocked { - builder.AddOp(txscript.OP_1) - } - - builder.AddData(redeemScript) - scriptSig, err := builder.Script() - if err != nil { - return nil, err - } - input.SignatureScript = scriptSig - } - // broadcast - if broadcast { - w.Broadcast(tx) - } - var buf bytes.Buffer - tx.BtcEncode(&buf, wire.ProtocolVersion, wire.BaseEncoding) - return buf.Bytes(), nil -} - -// Spend spends an amount from an address with a given fee level -func (w *RPCWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLevel) (*chainhash.Hash, error) { - tx, err := w.buildTx(amount, addr, feeLevel, nil) - if err != nil { - return nil, err - } - // Broadcast - err = w.Broadcast(tx) - if err != nil { - return nil, err - } - ch := tx.TxHash() - return &ch, nil -} - -// LookAheadDistance is the number of addresses to look for transactions before assuming the rest are unused -var LookAheadDistance = 5 - -type ReceivedTx struct { - tx wire.MsgTx - blockHeight int32 - blockTime time.Time - blockIndex int32 -} - -// RetrieveTransactions fetches transactions from the rpc server and stores them into the database -func (w *RPCWallet) RetrieveTransactions() error { - w.txstore.addrMutex.Lock() - - addrs := make([]btc.Address, len(w.txstore.adrs)) - - copy(addrs, w.txstore.adrs) - - w.txstore.addrMutex.Unlock() - - // receive transactions for P2PKH and P2PK - transactions := w.receiveTransactions(addrs, false) - - // receive transactions for P2SH - log.Debugf("extracting P2SH script addresses") - scriptAddresses := make([]btc.Address, len(w.txstore.watchedScripts)) - for idx, scriptBytes := range w.txstore.watchedScripts { - _, localScriptAddress, _, err := txscript.ExtractPkScriptAddrs(scriptBytes, w.txstore.params) - if err != nil { - log.Debugf("adding script address (%s) to watch error (%s)", localScriptAddress, err) - continue - } - if len(localScriptAddress) > 1 { - log.Warningf("many addresses %s were exported from script", localScriptAddress) - } - scriptAddresses[idx] = localScriptAddress[0] - } - - transactions = append(transactions, w.receiveTransactions(scriptAddresses, false)...) - sort.SliceStable(transactions, func(i, j int) bool { - return transactions[i].blockHeight < transactions[j].blockHeight || - (transactions[i].blockHeight == transactions[j].blockHeight && transactions[i].blockIndex < transactions[j].blockIndex) - }) - - for _, tx := range transactions { - _, err := w.txstore.Ingest(&tx.tx, tx.blockHeight, tx.blockTime) - if err != nil { - log.Warningf("Ingest error %s", err) - } - log.Debugf("ingested transactions hash %s", tx.tx.TxHash().String()) - } - return nil -} - -func (w *RPCWallet) receiveTransactions(addrs []btc.Address, lookAhead bool) []ReceivedTx { - numEmptyAddrs := 0 - - transactions := []ReceivedTx{} - - for i := range addrs { - log.Debugf("fetching transactions for address %s", addrs[i].String()) - w.rpcLock.Lock() - txs, err := w.rpcClient.SearchRawTransactionsVerbose(addrs[i], 0, 1000000, false, false, []string{}) - if err != nil { - // try download transactions again, rpc use multiple nodes one of them could be not updated yet - log.Warningf("trying to download transactions for address %s again, because of error: %s", addrs[i], err) - txs, err = w.rpcClient.SearchRawTransactionsVerbose(addrs[i], 0, 1000000, false, false, []string{}) - } - w.rpcLock.Unlock() - if err != nil { - log.Errorf("fetching transactions for address %s failed with error: %s", addrs[i].String(), err) - continue - } - - if lookAhead { - if len(txs) == 0 { - numEmptyAddrs++ - } - - if numEmptyAddrs >= LookAheadDistance { - return transactions - } - } - - for t := range txs { - log.Debugf("block hash %s\n", txs[t].BlockHash) - - hash, err := chainhash.NewHashFromStr(txs[t].BlockHash) - if err != nil { - log.Error(err) - continue - } - - w.rpcLock.Lock() - block, err := w.rpcClient.GetBlockVerbose(hash) - if err != nil { - // try download block again, rpc use multiple nodes one of them could be not updated yet - log.Warningf("trying to download block %s again, because of error: %s", hash, err) - block, err = w.rpcClient.GetBlockVerbose(hash) - } - w.rpcLock.Unlock() - - if err != nil { - log.Errorf("Cannot download block %s. %s", hash, err) - continue - } - - transactionBytes, err := hex.DecodeString(txs[t].Hex) - if err != nil { - log.Error(err) - continue - } - - transaction := wire.MsgTx{} - err = transaction.BtcDecode(bytes.NewReader(transactionBytes), 1, wire.BaseEncoding) - if err != nil { - log.Error(err) - continue - } - - // replace this by sending the index of the transaction in the block - index := int32(-1) - - for i, transactionHex := range block.Tx { - if transactionHex == transaction.TxHash().String() { - index = int32(i) - } - } - - if index == -1 { - log.Errorf("could not find transaction in block") - continue - } - - transactions = append(transactions, ReceivedTx{ - tx: transaction, - blockHeight: int32(block.Height), - blockTime: time.Unix(block.Time, 0), - blockIndex: index, - }) - } - } - return transactions -} diff --git a/cmd/convert.go b/cmd/convert.go deleted file mode 100644 index 94d00c27a7..0000000000 --- a/cmd/convert.go +++ /dev/null @@ -1,375 +0,0 @@ -package cmd - -import ( - "bufio" - "context" - "database/sql" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "path" - "strings" - "syscall" - "time" - - "github.com/OpenBazaar/jsonpb" - "github.com/OpenBazaar/wallet-interface" - "github.com/golang/protobuf/proto" - ipfscore "github.com/ipfs/go-ipfs/core" - "github.com/ipfs/go-ipfs/repo/fsrepo" - "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "golang.org/x/crypto/ssh/terminal" -) - -type Convert struct { - Password string `short:"p" long:"password" description:"the encryption password if the database is encrypted"` - DataDir string `short:"d" long:"datadir" description:"specify the data directory to be used"` - Testnet bool `short:"t" long:"testnet" description:"use the test network"` -} - -func (x *Convert) Execute(args []string) error { - if len(args) == 0 { - fmt.Fprintf(os.Stderr, "Please specify the cryptocurrency you wish to convert to. Examples:\nopenbazaar-go convert bitcoin\nopenbazaar-go convert bitcoincash\nopenbazaar-go convert zcash /path/to/zcashd\n") - return nil - } - if strings.ToLower(args[0]) == "zcash" && len(args) == 1 { - fmt.Fprintf(os.Stderr, "When converting to zcash please specify the path to the zcash binary. Example:\nopenbazaar-go convert zcash /path/to/zcashd\n") - return nil - } - if !(strings.ToLower(args[0]) == "bitcoin" || strings.ToLower(args[0]) == "bitcoincash" || strings.ToLower(args[0]) == "zcash") { - fmt.Fprintf(os.Stderr, "Unknown currency type: please enter either bitcoin, bitcoincash, or zcash.\n") - return nil - } - - var str string - var cfgtype string - var currencyCode string - ct := util.ExtendCoinType(wallet.Bitcoin) - switch strings.ToLower(args[0]) { - case "bitcoin": - str = "Bitcoin" - cfgtype = "spvwallet" - currencyCode = "BTC" - case "bitcoincash": - str = "Bitcoin Cash" - cfgtype = "bitcoincash" - currencyCode = "BCH" - ct = util.ExtendCoinType(wallet.BitcoinCash) - case "zcash": - str = "ZCash" - cfgtype = "zcashd" - currencyCode = "ZEC" - ct = util.ExtendCoinType(wallet.Zcash) - } - - if x.Testnet { - currencyCode = "T" + currencyCode - } - - reader := bufio.NewReader(os.Stdin) - fmt.Printf("This command will convert your wallet to %s. It will delete any coins you have in your wallet and will prevent you from completing any outstanding orders. Please make sure you have emptied the wallet and completed all your orders before running this command. You will also need to select a new moderator.\n", str) - fmt.Println("Are you sure you want to continue (y/n)?") - yn, _ := reader.ReadString('\n') - if !(strings.ToLower(yn) == "y\n" || strings.ToLower(yn) == "yes\n" || strings.ToLower(yn)[:1] == "y") { - fmt.Println("No changes made") - return nil - } - - fmt.Println("Are you REALLY sure (y/n)?") - yn, _ = reader.ReadString('\n') - if !(strings.ToLower(yn) == "y\n" || strings.ToLower(yn) == "yes\n" || strings.ToLower(yn)[:1] == "y") { - fmt.Println("No changes made") - return nil - } - - fmt.Println("Working...") - - // Set repo path - repoPath, err := repo.GetRepoPath(x.Testnet) - if err != nil { - return err - } - if x.DataDir != "" { - repoPath = x.DataDir - } - - // Wipe database tables - var dbPath string - if x.Testnet { - dbPath = path.Join(repoPath, "datastore", "testnet.db") - } else { - dbPath = path.Join(repoPath, "datastore", "mainnet.db") - } - sqlitedb, err := sql.Open("sqlite3", dbPath) - if err != nil { - return err - } - if x.Password != "" { - p := "pragma key='" + x.Password + "';" - sqlitedb.Exec(p) - } - - _, err = sqlitedb.Exec("DELETE FROM txns;") - if err != nil { - return err - } - _, err = sqlitedb.Exec("DELETE FROM stxos;") - if err != nil { - return err - } - _, err = sqlitedb.Exec("DELETE FROM utxos;") - if err != nil { - return err - } - _, err = sqlitedb.Exec("DELETE FROM keys;") - if err != nil { - return err - } - - // Update coin type in config file - cf, err := ioutil.ReadFile(path.Join(repoPath, "config")) - if err != nil { - return err - } - var cfgIface interface{} - json.Unmarshal(cf, &cfgIface) - cfgObj, ok := cfgIface.(map[string]interface{}) - if !ok { - return errors.New("invalid config file") - } - - walletIface, ok := cfgObj["Wallet"] - if !ok { - return errors.New("config file missing wallet field") - } - walletCfg, ok := walletIface.(map[string]interface{}) - if !ok { - return errors.New("invalid config file") - } - walletCfg["Type"] = cfgtype - if strings.ToLower(args[0]) == "zcash" { - walletCfg["Binary"] = args[1] - } - out, err := json.MarshalIndent(cfgObj, "", " ") - if err != nil { - return err - } - f, err := os.Create(path.Join(repoPath, "config")) - if err != nil { - return err - } - _, err = f.Write(out) - if err != nil { - return err - } - f.Close() - - // Update listings with new coin type - creationDate := time.Now() - var sqliteDB *db.SQLiteDatastore - sqliteDB, err = InitializeRepo(repoPath, x.Password, "", x.Testnet, creationDate, ct) - if err != nil && err != repo.ErrRepoExists { - return err - } - - // If the database cannot be decrypted, exit - if sqliteDB.Config().IsEncrypted() { - sqliteDB.Close() - fmt.Print("Database is encrypted, enter your password: ") - // nolint:unconvert - bytePassword, _ := terminal.ReadPassword(int(syscall.Stdin)) - fmt.Println("") - pw := string(bytePassword) - sqliteDB, err = InitializeRepo(repoPath, pw, "", x.Testnet, time.Now(), ct) - if err != nil && err != repo.ErrRepoExists { - return err - } - if sqliteDB.Config().IsEncrypted() { - PrintError("Invalid password") - os.Exit(3) - } - } - // Get current identity - identityKey, err := sqliteDB.Config().GetIdentityKey() - if err != nil { - PrintError(err.Error()) - return err - } - identity, err := ipfs.IdentityFromKey(identityKey) - if err != nil { - return err - } - - // IPFS node setup - r, err := fsrepo.Open(repoPath) - if err != nil { - PrintError(err.Error()) - return err - } - cctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cfg, err := r.Config() - if err != nil { - PrintError(err.Error()) - return err - } - - cfg.Identity = identity - - ncfg := &ipfscore.BuildCfg{ - Repo: r, - Online: true, - ExtraOpts: map[string]bool{ - "mplex": true, - }, - Routing: nil, - } - - nd, err := ipfscore.NewNode(cctx, ncfg) - if err != nil { - PrintError(err.Error()) - return err - } - - files, err := ioutil.ReadDir(path.Join(repoPath, "root", "listings")) - if err != nil { - return err - } - - hashes := make(map[string]string) - - for _, f := range files { - file, err := ioutil.ReadFile(path.Join(repoPath, "root", "listings", f.Name())) - if err != nil { - return err - } - sl := new(pb.SignedListing) - err = jsonpb.UnmarshalString(string(file), sl) - if err != nil { - return err - } - sl.Listing.Metadata.AcceptedCurrencies = []string{currencyCode} - sl.Listing.Moderators = []string{} - - serializedListing, err := proto.Marshal(sl.Listing) - if err != nil { - return err - } - idSig, err := nd.PrivateKey.Sign(serializedListing) - if err != nil { - return err - } - sl.Signature = idSig - - m := jsonpb.Marshaler{ - EnumsAsInts: false, - EmitDefaults: false, - Indent: " ", - OrigName: false, - } - out, err := m.MarshalToString(sl) - if err != nil { - return err - } - - if err := ioutil.WriteFile(path.Join(repoPath, "root", "listings", f.Name()), []byte(out), os.ModePerm); err != nil { - return err - } - h, err := ipfs.GetHashOfFile(nd, path.Join(repoPath, "root", "listings", f.Name())) - if err != nil { - return err - } - hashes[sl.Listing.Slug] = h - } - - indexPath := path.Join(repoPath, "root", "listings.json") - indexBytes, err := ioutil.ReadFile(indexPath) - if err != nil { - return err - } - var index []core.ListingData - - err = json.Unmarshal(indexBytes, &index) - if err != nil { - return err - } - - for i, l := range index { - h, ok := hashes[l.Slug] - if !ok { - return errors.New("malformatted index file") - } - l.Hash = h - index[i] = l - } - // Write it back to file - ifile, err := os.Create(indexPath) - if err != nil { - return err - } - defer ifile.Close() - - j, jerr := json.MarshalIndent(index, "", " ") - if jerr != nil { - return jerr - } - _, werr := ifile.Write(j) - if werr != nil { - return werr - } - - // Update profile - pro, err := ioutil.ReadFile(path.Join(repoPath, "root", "profile.json")) - if err != nil { - return err - } - - profile := new(pb.Profile) - err = jsonpb.UnmarshalString(string(pro), profile) - if err != nil { - return err - } - profile.Currencies = []string{currencyCode} - if profile.ModeratorInfo != nil { - profile.ModeratorInfo.AcceptedCurrencies = []string{currencyCode} - m := jsonpb.Marshaler{ - EnumsAsInts: false, - EmitDefaults: false, - Indent: " ", - OrigName: false, - } - out, err := m.MarshalToString(profile) - if err != nil { - return err - } - - if err := ioutil.WriteFile(path.Join(repoPath, "root", "profile.json"), []byte(out), os.ModePerm); err != nil { - return err - } - } - nd.Close() - - // Remove moderators from settings - settings, err := sqliteDB.Settings().Get() - if err == nil { - settings.StoreModerators = &[]string{} - sqliteDB.Settings().Put(settings) - } - - // Remove headers.bin - os.Remove(path.Join(repoPath, "headers.bin")) - - // Remove peers.json - os.Remove(path.Join(repoPath, "peers.json")) - - fmt.Println("Done") - return nil -} diff --git a/cmd/decrypt.go b/cmd/decrypt.go index cee2fc55c3..ccac4054aa 100644 --- a/cmd/decrypt.go +++ b/cmd/decrypt.go @@ -12,8 +12,8 @@ import ( "github.com/OpenBazaar/wallet-interface" "github.com/ipfs/go-ipfs/repo/fsrepo" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" "golang.org/x/crypto/ssh/terminal" ) @@ -30,7 +30,7 @@ func (x *DecryptDatabase) Execute(args []string) error { var testnet bool var err error if x.DataDir == "" { - repoPath, err = repo.GetRepoPath(false) + repoPath, err = repo.GetRepoPath(false, "") if err != nil { log.Error(err) return nil @@ -92,7 +92,11 @@ func (x *DecryptDatabase) Execute(args []string) error { fmt.Println(err) return err } - tmpDB.InitTables("") + err = tmpDB.InitTables("") + if err != nil { + fmt.Println(err) + return err + } if err := sqlliteDB.Copy(path.Join(repoPath, "tmp", "datastore", filename), ""); err != nil { log.Error(err) fmt.Println(err) diff --git a/cmd/encrypt.go b/cmd/encrypt.go index 0f78ade005..9e5b5624f1 100644 --- a/cmd/encrypt.go +++ b/cmd/encrypt.go @@ -12,8 +12,8 @@ import ( "github.com/OpenBazaar/wallet-interface" "github.com/ipfs/go-ipfs/repo/fsrepo" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" "golang.org/x/crypto/ssh/terminal" ) @@ -29,7 +29,7 @@ func (x *EncryptDatabase) Execute(args []string) error { var testnet bool var err error if x.DataDir == "" { - repoPath, err = repo.GetRepoPath(false) + repoPath, err = repo.GetRepoPath(false, "") if err != nil { fmt.Println(err) return nil @@ -121,7 +121,11 @@ func (x *EncryptDatabase) Execute(args []string) error { return err } - tmpDB.InitTables(pw) + err = tmpDB.InitTables(pw) + if err != nil { + fmt.Println(err) + return err + } if err := sqlliteDB.Copy(path.Join(tmpPath, "datastore", filename), pw); err != nil { log.Error(err) fmt.Println(err) @@ -134,6 +138,6 @@ func (x *EncryptDatabase) Execute(args []string) error { return err } os.RemoveAll(path.Join(tmpPath)) - fmt.Println("Success! You must now run openbazaard start with a password.") + fmt.Println("Success! You must now run marketplaced start with a password.") return nil } diff --git a/cmd/gencerts.go b/cmd/gencerts.go index fdc79e8844..373d8886a8 100644 --- a/cmd/gencerts.go +++ b/cmd/gencerts.go @@ -14,7 +14,7 @@ import ( "strings" "time" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type GenerateCertificates struct { @@ -29,7 +29,7 @@ func (x *GenerateCertificates) Execute(args []string) error { flag.Parse() // Set repo path - repoPath, err := repo.GetRepoPath(x.Testnet) + repoPath, err := repo.GetRepoPath(x.Testnet, x.DataDir) if err != nil { return err } @@ -101,7 +101,7 @@ func (x *GenerateCertificates) Execute(args []string) error { } // Create ssl directory - err = os.MkdirAll(path.Join(repoPath, "ssl"), os.ModePerm) + err = os.MkdirAll(path.Join(repoPath, "ssl"), 0755) if err != nil { log.Fatalf("Failed to create ssl directory: %s", err) } @@ -111,7 +111,10 @@ func (x *GenerateCertificates) Execute(args []string) error { if err != nil { log.Fatalf("failed to open cert.pem for writing: %s", err) } - pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + if err != nil { + log.Fatalf("failed to write pem encoding: %s", err) + } certOut.Close() log.Noticef("wrote cert.pem\n") @@ -121,7 +124,10 @@ func (x *GenerateCertificates) Execute(args []string) error { log.Noticef("failed to open key.pem for writing:", err) return err } - pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv.(*rsa.PrivateKey))}) + err = pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv.(*rsa.PrivateKey))}) + if err != nil { + log.Fatalf("failed to write pem encoding: %s", err) + } keyOut.Close() log.Noticef("wrote key.pem\n") diff --git a/cmd/gencerts_test.go b/cmd/gencerts_test.go new file mode 100644 index 0000000000..0666d3f9b9 --- /dev/null +++ b/cmd/gencerts_test.go @@ -0,0 +1,106 @@ +package cmd_test + +import ( + "crypto/x509" + "encoding/pem" + "io/ioutil" + "os" + "path" + "testing" + + "github.com/phoreproject/pm-go/cmd" + "github.com/phoreproject/pm-go/schema" +) + +func buildCertDirectory() (string, func(), error) { + ctx := schema.SchemaContext{ + DataPath: schema.GenerateTempPath(), + TestModeEnabled: true, + } + certSchema := schema.MustNewCustomSchemaManager(ctx) + if err := certSchema.BuildSchemaDirectories(); err != nil { + return "", nil, err + } + return ctx.DataPath, certSchema.DestroySchemaDirectories, nil +} + +func TestGenCertsGenericDefaults(t *testing.T) { + dataDir, destroy, schemaErr := buildCertDirectory() + if schemaErr != nil { + t.Fatal(schemaErr) + } + defer destroy() + + config := cmd.GenerateCertificates{ + DataDir: dataDir, + Testnet: true, + Host: "127.0.0.1", + ValidFor: 1, // 1ns ... 1*1e9 == 1s + } + + args := []string{""} + + if err := config.Execute(args); err != nil { + t.Fatalf("unable to GenerateCertificates: %s", err) + } + + sslPath := path.Join(dataDir, "ssl") + fileInfoSsl, errSsl := os.Stat(sslPath) + if errSsl != nil { + t.Fatalf("unable to find sslPath: %s", errSsl) + } + if fileInfoSsl.Mode().Perm() != 0755 { + t.Fatal("ssl directory does not have 0755 permissions") + } + if !fileInfoSsl.IsDir() { + t.Fatalf("Expecting a directory: %s", dataDir) + } + + certPemPath := path.Join(dataDir, "ssl", "cert.pem") + fileInfoCert, errCert := os.Stat(certPemPath) + if errCert != nil { + t.Fatalf("unable to find certPemPath %s: %s", certPemPath, errCert) + } + if fileInfoCert.Mode().Perm() != 0644 { + t.Fatal("cert.pem does not have 0644 permissions") + } + if !fileInfoCert.Mode().IsRegular() { + t.Fatalf("Expecting a file: %s", certPemPath) + } + + keyPemPath := path.Join(dataDir, "ssl", "key.pem") + fileInfoKey, errKey := os.Stat(keyPemPath) + if errKey != nil { + t.Fatalf("unable to find keyPemPath: %s", errKey) + } + if fileInfoKey.Mode().Perm() != 0600 { + t.Fatal("cert.pem does not have 0600 permissions") + } + if !fileInfoKey.Mode().IsRegular() { + t.Fatalf("Expecting a file: %s", keyPemPath) + } + + certPemBytes, err := ioutil.ReadFile(certPemPath) + if err != nil { + t.Fatalf("unable to read certPemPath: %s", err) + } + block, _ := pem.Decode(certPemBytes) + if block == nil { + t.Fatal("failed to parse PEM block containing the public key") + } + + pub, err := x509.ParseCertificate(block.Bytes) + if err != nil { + t.Fatal("failed to parse DER encoded public key: " + err.Error()) + } + if pub.Issuer.String() != "O=OpenBazaar" { + t.Errorf("unexpected issuer found on certificate: %s != OpenBazaar", pub.Issuer.String()) + } + if err := pub.VerifyHostname("127.0.0.1"); err != nil { + t.Errorf("unable to VerifyHostname 127.0.0.1: %s", err) + } + + if pub.NotAfter.Sub(pub.NotBefore).Seconds() != 0 { + t.Errorf("Certificate NotAfter != NotBefore: %s %s", pub.NotAfter.String(), pub.NotBefore.String()) + } +} diff --git a/cmd/init.go b/cmd/init.go index bae5ec2852..8621d90f28 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -9,7 +9,7 @@ import ( "time" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" "github.com/op/go-logging" ) @@ -27,7 +27,7 @@ type Init struct { func (x *Init) Execute(args []string) error { // Set repo path - repoPath, err := repo.GetRepoPath(x.Testnet) + repoPath, err := repo.GetRepoPath(x.Testnet, x.DataDir) if err != nil { return err } diff --git a/cmd/restore.go b/cmd/restore.go index 648e77baf5..f5458b2336 100644 --- a/cmd/restore.go +++ b/cmd/restore.go @@ -34,11 +34,11 @@ import ( "github.com/OpenBazaar/wallet-interface" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/ipfs" - obnet "github.com/phoreproject/openbazaar-go/net" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/ipfs" + obnet "github.com/phoreproject/pm-go/net" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" "github.com/ipfs/go-ipfs/core" ipfscore "github.com/ipfs/go-ipfs/core" @@ -69,7 +69,7 @@ func (x *Restore) Execute(args []string) error { } // Set repo path - repoPath, err := repo.GetRepoPath(x.Testnet) + repoPath, err := repo.GetRepoPath(x.Testnet, x.DataDir) if err != nil { return err } diff --git a/cmd/setapicreds.go b/cmd/setapicreds.go index b2205e2e74..da54ea55f9 100644 --- a/cmd/setapicreds.go +++ b/cmd/setapicreds.go @@ -13,8 +13,8 @@ import ( "syscall" "github.com/ipfs/go-ipfs/repo/fsrepo" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/schema" "golang.org/x/crypto/ssh/terminal" ) @@ -25,7 +25,7 @@ type SetAPICreds struct { func (x *SetAPICreds) Execute(args []string) error { // Set repo path - repoPath, err := repo.GetRepoPath(x.Testnet) + repoPath, err := repo.GetRepoPath(x.Testnet, x.DataDir) if err != nil { return err } diff --git a/cmd/start.go b/cmd/start.go index 02e12f5d6d..40c4b009b2 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -18,17 +18,15 @@ import ( "syscall" "time" - routinghelpers "gx/ipfs/QmRCrPXk2oUwpK1Cj2FXrUotRpddUxz56setkny2gz13Cx/go-libp2p-routing-helpers" - libp2p "gx/ipfs/QmRxk6AUaGaKCfzS1xSNRojiAPd7h2ih8GuCdjJBF3Y6GK/go-libp2p" - dht "gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht" + "gx/ipfs/QmRCrPXk2oUwpK1Cj2FXrUotRpddUxz56setkny2gz13Cx/go-libp2p-routing-helpers" + "gx/ipfs/QmRxk6AUaGaKCfzS1xSNRojiAPd7h2ih8GuCdjJBF3Y6GK/go-libp2p" + "gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht" ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" - config "gx/ipfs/QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs/go-ipfs-config" - ipnspb "gx/ipfs/QmUwMnKKjH3JwGKNVZ3TcP37W93xzqNA4ECFFiMo6sXkkc/go-ipns/pb" - peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + "gx/ipfs/QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs/go-ipfs-config" + "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" oniontp "gx/ipfs/QmYv2MbwHn7qcvAPFisZ94w85crQVpwUuv8G7TuUeBnfPb/go-onion-transport" ipfslogging "gx/ipfs/QmbkT7eMTyXfpeyB3ZMxxcxg7XH8t6uXp49jqzz4HB7BGF/go-log/writer" - manet "gx/ipfs/Qmc85NSvmSG4Frn9Vb2cBc1rMyULH6D3TNVEfCzSKoUpip/go-multiaddr-net" - proto "gx/ipfs/QmddjPSGZb3ieihSseFeCfVRpZzcqczPNsD2DvarSwnjJB/gogo-protobuf/proto" + "gx/ipfs/Qmc85NSvmSG4Frn9Vb2cBc1rMyULH6D3TNVEfCzSKoUpip/go-multiaddr-net" wi "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg" @@ -38,26 +36,24 @@ import ( "github.com/ipfs/go-ipfs/commands" ipfscore "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/corehttp" - "github.com/ipfs/go-ipfs/namesys" "github.com/ipfs/go-ipfs/repo/fsrepo" "github.com/natefinch/lumberjack" "github.com/op/go-logging" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/api" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/ipfs" - obnet "github.com/phoreproject/openbazaar-go/net" - "github.com/phoreproject/openbazaar-go/net/service" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" - sto "github.com/phoreproject/openbazaar-go/storage" - "github.com/phoreproject/openbazaar-go/storage/dropbox" - "github.com/phoreproject/openbazaar-go/storage/selfhosted" - "github.com/phoreproject/openbazaar-go/wallet" - lis "github.com/phoreproject/openbazaar-go/wallet/listeners" - "github.com/phoreproject/openbazaar-go/wallet/resync" + "github.com/phoreproject/pm-go/api" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/ipfs" + obnet "github.com/phoreproject/pm-go/net" + "github.com/phoreproject/pm-go/net/service" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" + sto "github.com/phoreproject/pm-go/storage" + "github.com/phoreproject/pm-go/storage/dropbox" + "github.com/phoreproject/pm-go/storage/selfhosted" + "github.com/phoreproject/pm-go/wallet" + lis "github.com/phoreproject/pm-go/wallet/listeners" + "github.com/phoreproject/pm-go/wallet/resync" "github.com/tyler-smith/go-bip39" "golang.org/x/crypto/ssh/terminal" @@ -65,11 +61,11 @@ import ( ) var stdoutLogFormat = logging.MustStringFormatter( - `%{color:reset}%{color}%{time:15:04:05.000} [%{level}] [%{module}/%{shortfunc}] %{message}`, + `%{color:reset}%{color}%{time:2006-01-02 15:04:05.000} [%{level}] [%{module}/%{shortfunc}] %{message}`, ) var fileLogFormat = logging.MustStringFormatter( - `%{time:15:04:05.000} [%{level}] [%{module}/%{shortfunc}] %{message}`, + `%{time:2006-01-02 15:04:05.000} [%{level}] [%{module}/%{shortfunc}] %{message}`, ) var ErrNoGateways = errors.New("no gateway addresses configured") @@ -92,10 +88,8 @@ type Start struct { DisableWallet bool `long:"disablewallet" description:"disable the wallet functionality of the node"` DisableExchangeRates bool `long:"disableexchangerates" description:"disable the exchange rate service to prevent api queries"` Storage string `long:"storage" description:"set the outgoing message storage option [self-hosted, dropbox] default=self-hosted"` - BitcoinCash bool `long:"bitcoincash" description:"use a Bitcoin Cash wallet in a dedicated data directory"` - ZCash string `long:"zcash" description:"use a ZCash wallet in a dedicated data directory. To use this you must pass in the location of the zcashd binary."` - ForceKeyCachePurge bool `long:"forcekeypurge" description:"repair test for issue OpenBazaar/openbazaar-go#1593; use as instructed only"` + ForceKeyCachePurge bool `long:"forcekeypurge" description:"repair test for issue phoreproject/pm-go#1593; use as instructed only"` } func (x *Start) Execute(args []string) error { @@ -114,20 +108,12 @@ func (x *Start) Execute(args []string) error { if x.Testnet || x.Regtest { isTestnet = true } - if x.BitcoinCash && x.ZCash != "" { - return errors.New("bitcoin cash and zcash cannot be used at the same time") - } // Set repo path - repoPath, err := repo.GetRepoPath(isTestnet) + repoPath, err := repo.GetRepoPath(isTestnet, x.DataDir) if err != nil { return err } - if x.BitcoinCash { - repoPath += "-bitcoincash" - } else if x.ZCash != "" { - repoPath += "-zcash" - } if x.DataDir != "" { repoPath = x.DataDir } @@ -191,15 +177,7 @@ func (x *Start) Execute(args []string) error { return err } - ct := util.CoinTypePhore - if x.BitcoinCash || strings.Contains(repoPath, "-bitcoincash") { - ct = util.ExtendCoinType(wi.BitcoinCash) - } else if x.ZCash != "" || strings.Contains(repoPath, "-zcash") { - ct = util.ExtendCoinType(wi.Zcash) - } - - migrations.WalletCoinType = ct - sqliteDB, err := InitializeRepo(repoPath, x.Password, "", isTestnet, time.Now(), ct) + sqliteDB, err := InitializeRepo(repoPath, x.Password, "", isTestnet, time.Now(), util.ExtendCoinType(wi.Bitcoin)) if err != nil && err != repo.ErrRepoExists { log.Error("repo init:", err) return err @@ -408,12 +386,8 @@ func (x *Start) Execute(args []string) error { } var dhtRouting *dht.IpfsDHT for _, router := range tiered.Routers { - if r, ok := router.(*ipfs.CachingRouter); ok { - r.APIRouter().Start(torDialer) - dhtRouting, err = r.DHT() - if err != nil { - return err - } + if r, ok := router.(*dht.IpfsDHT); ok { + dhtRouting = r } } if dhtRouting == nil { @@ -421,29 +395,22 @@ func (x *Start) Execute(args []string) error { } // Get current directory root hash - ipnskey := namesys.IpnsDsKey(nd.Identity) - ival, hasherr := nd.Repo.Datastore().Get(ipnskey) + cachedIPNSRecord, hasherr := ipfs.GetCachedIPNSRecord(nd.Repo.Datastore(), nd.Identity) if hasherr != nil { - log.Error("get ipns key:", hasherr) - } - ourIpnsRecord := new(ipnspb.IpnsEntry) - err = proto.Unmarshal(ival, ourIpnsRecord) - if err != nil { - log.Error("unmarshal record value", err) - nd.Repo.Datastore().Delete(ipnskey) + log.Warning(err) + if err := ipfs.DeleteCachedIPNSRecord(nd.Repo.Datastore(), nd.Identity); err != nil { + log.Errorf("deleting invalid IPNS record: %s", err.Error()) + } } if x.ForceKeyCachePurge { log.Infof("forcing key purge from namesys cache...") - nd.Repo.Datastore().Delete(ipnskey) + if err := ipfs.DeleteCachedIPNSRecord(nd.Repo.Datastore(), nd.Identity); err != nil { + log.Errorf("force-purging IPNS record: %s", err.Error()) + } } - // Wallet - mn, err := sqliteDB.Config().GetMnemonic() - if err != nil { - log.Error("get config mnemonic:", err) - return err - } + //Wallet var params chaincfg.Params if x.Testnet { params = chaincfg.TestNet3Params @@ -453,46 +420,6 @@ func (x *Start) Execute(args []string) error { params = chaincfg.MainNetParams } - // Multiwallet setup - var walletLogWriter io.Writer - if x.NoLogFiles { - walletLogWriter = &DummyWriter{} - } else { - walletLogWriter = &lumberjack.Logger{ - Filename: path.Join(repoPath, "logs", "wallet.log"), - MaxSize: 10, // Megabytes - MaxBackups: 3, - MaxAge: 30, // Days - } - } - walletLogFile := logging.NewLogBackend(walletLogWriter, "", 0) - walletFileFormatter := logging.NewBackendFormatter(walletLogFile, fileLogFormat) - walletLogger := logging.MultiLogger(walletFileFormatter) - multiwalletConfig := &wallet.WalletConfig{ - ConfigFile: walletsConfig, - DB: sqliteDB.DB(), - Params: ¶ms, - RepoPath: repoPath, - Logger: walletLogger, - Proxy: torDialer, - WalletCreationDate: creationDate, - Mnemonic: mn, - DisableExchangeRates: x.DisableExchangeRates, - } - mw, err := wallet.NewMultiWallet(multiwalletConfig) - if err != nil { - return err - } - resyncManager := resync.NewResyncManager(sqliteDB.Sales(), mw) - - // Master key setup - seed := bip39.NewSeed(mn, "") - mPrivKey, err := hdkeychain.NewMaster(seed, ¶ms) - if err != nil { - log.Error(err) - return err - } - // Push nodes var pushNodes []peer.ID for _, pnd := range dataSharing.PushTo { @@ -588,27 +515,87 @@ func (x *Start) Execute(args []string) error { subscriber := ipfs.NewPubsubSubscriber(context.Background(), nd.PeerHost, nd.Routing, nd.Repo.Datastore(), nd.PubSub) ps := ipfs.Pubsub{Publisher: publisher, Subscriber: subscriber} + var rootHash string + if cachedIPNSRecord != nil { + rootHash = string(cachedIPNSRecord.Value) + } + // OpenBazaar node setup - core.Node = &core.OpenBazaarNode{ + var obPartialNode = &core.OpenBazaarNode{ AcceptStoreRequests: dataSharing.AcceptStoreRequests, BanManager: bm, Datastore: sqliteDB, IpfsNode: nd, DHT: dhtRouting, - MasterPrivateKey: mPrivKey, - Multiwallet: mw, + MasterPrivateKey: nil, + Multiwallet: nil, OfflineMessageFailoverTimeout: 30 * time.Second, Pubsub: ps, PushNodes: pushNodes, RegressionTestEnable: x.Regtest, RepoPath: repoPath, - RootHash: string(ourIpnsRecord.Value), + RootHash: rootHash, TestnetEnable: x.Testnet, TorDialer: torDialer, UserAgent: core.USERAGENT, IPNSQuorumSize: uint(ipnsExtraConfig.DHTQuorumSize), + WalletLocked: true, + } + obPartialNode.PublishLock.Lock() + + //Multiwallet setup + var walletLogWriter io.Writer + if x.NoLogFiles { + walletLogWriter = &DummyWriter{} + } else { + walletLogWriter = &lumberjack.Logger{ + Filename: path.Join(repoPath, "logs", "wallet.log"), + MaxSize: 10, // Megabytes + MaxBackups: 3, + MaxAge: 30, // Days + } + } + walletLogFile := logging.NewLogBackend(walletLogWriter, "", 0) + walletFileFormatter := logging.NewBackendFormatter(walletLogFile, fileLogFormat) + walletLogger := logging.MultiLogger(walletFileFormatter) + multiwalletConfig := &wallet.WalletConfig{ + ConfigFile: walletsConfig, + DB: sqliteDB.DB(), + Params: ¶ms, + RepoPath: repoPath, + Logger: walletLogger, + Proxy: torDialer, + WalletCreationDate: creationDate, + Mnemonic: "", + DisableExchangeRates: x.DisableExchangeRates, + } + + gateway, err := newHTTPGateway(obPartialNode, ctx, authCookie, *apiConfig, false) + if err != nil { + log.Error(err) + return err + } + + err = gateway.Serve(false) + if err != nil { + return err + } + + err = createOpenBazaarNode(obPartialNode, multiwalletConfig, params) + if err != nil { + log.Error(err) + return err + } + + core.Node = obPartialNode + + resyncManager := resync.NewResyncManager(sqliteDB.Sales(), sqliteDB.Purchases(), core.Node.Multiwallet) + + // assert reserve wallet is available on startup for later usage + _, err = core.Node.ReserveCurrencyConverter() + if err != nil { + return fmt.Errorf("verifying reserve currency converter: %s", err.Error()) } - core.PublishLock.Lock() // Offline messaging storage var storage sto.OfflineMessagingStorage @@ -644,12 +631,6 @@ func (x *Start) Execute(args []string) error { return errors.New("SSL cert and key files must be set when SSL is enabled") } - gateway, err := newHTTPGateway(core.Node, ctx, authCookie, *apiConfig, x.NoLogFiles) - if err != nil { - log.Error(err) - return err - } - if len(cfg.Addresses.API) > 0 && cfg.Addresses.API[0] != "" { if _, err := serveHTTPApi(&ctx); err != nil { log.Error(err) @@ -664,15 +645,15 @@ func (x *Start) Execute(args []string) error { core.Node.WaitForMessageRetrieverCompletion() } TL := lis.NewTransactionListener(core.Node.Multiwallet, core.Node.Datastore, core.Node.Broadcast) - for ct, wal := range mw { + for ct, wal := range core.Node.Multiwallet { WL := lis.NewWalletListener(core.Node.Datastore, core.Node.Broadcast, ct) wal.AddTransactionListener(WL.OnTransactionReceived) wal.AddTransactionListener(TL.OnTransactionReceived) } log.Info("Starting multiwallet...") - su := wallet.NewStatusUpdater(mw, core.Node.Broadcast, nd.Context()) + su := wallet.NewStatusUpdater(core.Node.Multiwallet, core.Node.Broadcast, nd.Context()) go su.Start() - go mw.Start() + go core.Node.Multiwallet.Start() if resyncManager != nil { go resyncManager.Start() go func() { @@ -683,18 +664,19 @@ func (x *Start) Execute(args []string) error { } core.Node.Service = service.New(core.Node, sqliteDB) core.Node.Service.WaitForReady() - log.Info("OpenBazaar Service Ready") + log.Info("Marketplace Service Ready") core.Node.StartMessageRetriever() core.Node.StartPointerRepublisher() core.Node.StartRecordAgingNotifier() + core.Node.StartInboundMsgScanner() - core.PublishLock.Unlock() + core.Node.PublishLock.Unlock() err = core.Node.UpdateFollow() if err != nil { log.Error(err) } - if !core.InitalPublishComplete { + if !core.Node.InitalPublishComplete { err = core.Node.SeedNode() if err != nil { log.Error(err) @@ -704,7 +686,7 @@ func (x *Start) Execute(args []string) error { }() // Start gateway - err = gateway.Serve() + err = gateway.Serve(true) if err != nil { log.Error(err) } @@ -768,6 +750,54 @@ func (d *DummyListener) Close() error { return nil } +func createOpenBazaarNode(node *core.OpenBazaarNode, multiwalletConfig *wallet.WalletConfig, + params chaincfg.Params) error { + + mnemonic, isEncrypted, err := node.Datastore.Config().GetMnemonic() + if err != nil { + log.Error("get config mnemonic:", err) + return err + } + node.WalletLocked = isEncrypted + + if isEncrypted { + log.Warning("mnemonic is encrypted") + mnemonic = waitForDecryptedMnemonic(node) + } + + multiwalletConfig.Mnemonic = mnemonic + node.Multiwallet, err = wallet.NewMultiWallet(multiwalletConfig) + if err != nil { + return err + } + + // Master key setup + seed := bip39.NewSeed(mnemonic, "") + node.MasterPrivateKey, err = hdkeychain.NewMaster(seed, ¶ms) + if err != nil { + log.Error(err) + return err + } + + return nil +} + +func waitForDecryptedMnemonic(node *core.OpenBazaarNode) string { + node.MnemonicChan = make(chan string) + + for { + log.Warning("Waiting for mnemonic password") + decryptedMnemonic := <-node.MnemonicChan + + if !bip39.IsMnemonicValid(decryptedMnemonic) { + log.Warning("Mnemonic not correct") + continue + } + + return decryptedMnemonic + } +} + // Collects options, creates listener, prints status message and starts serving requests func newHTTPGateway(node *core.OpenBazaarNode, ctx commands.Context, authCookie http.Cookie, config schema.APIConfig, noLogFiles bool) (*api.Gateway, error) { // Get API configuration @@ -834,7 +864,6 @@ func newHTTPGateway(node *core.OpenBazaarNode, ctx commands.Context, authCookie apiFile := logging.NewLogBackend(w4, "", 0) apiFileFormatter := logging.NewBackendFormatter(apiFile, fileLogFormat) ml := logging.MultiLogger(apiFileFormatter) - return api.NewGateway(node, authCookie, manet.NetListener(gwLis), config, ml, opts...) } diff --git a/cmd/status.go b/cmd/status.go index 96c5a0304f..6edc46fec1 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -6,9 +6,9 @@ import ( "github.com/ipfs/go-ipfs/repo/fsrepo" "github.com/phoreproject/multiwallet/util" - obnet "github.com/phoreproject/openbazaar-go/net" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" + obnet "github.com/phoreproject/pm-go/net" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" ) type Status struct { @@ -18,7 +18,7 @@ type Status struct { func (x *Status) Execute(args []string) error { // Set repo path - repoPath, err := repo.GetRepoPath(x.Testnet) + repoPath, err := repo.GetRepoPath(x.Testnet, x.DataDir) if err != nil { return err } @@ -46,13 +46,28 @@ func (x *Status) Execute(args []string) error { os.Exit(31) } } else { + _, isEncrypted, err := sqliteDB.Config().GetMnemonic() + if err != nil { + os.Exit(1) + } + if !torAvailable { fmt.Println("Initialized - Not Encrypted") - os.Exit(20) + if isEncrypted { + fmt.Println("Seed Words Encrypted") + os.Exit(25) + } else { + os.Exit(20) + } } else { fmt.Println("Initialized - Not Encrypted") fmt.Println("Tor Available") - os.Exit(21) + if isEncrypted { + fmt.Println("Seed Words Encrypted") + os.Exit(26) + } else { + os.Exit(21) + } } } } else { diff --git a/core/completion.go b/core/completion.go index 7e78e1463c..a4d4bf63c0 100644 --- a/core/completion.go +++ b/core/completion.go @@ -8,8 +8,10 @@ import ( "fmt" libp2p "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" "io/ioutil" + "math/big" "os" "path" + "strings" "time" "github.com/OpenBazaar/jsonpb" @@ -17,9 +19,10 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) const ( @@ -162,26 +165,31 @@ func (n *OpenBazaarNode) CompleteOrder(orderRatings *OrderRatings, contract *pb. oc.Ratings = append(oc.Ratings, rating) } - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } // Payout order if moderated and not disputed - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED && contract.DisputeResolution == nil { + if order.Payment.Method == pb.Order_Payment_MODERATED && contract.DisputeResolution == nil { var ins []wallet.TransactionInput - var outValue int64 + outValue := new(big.Int) for _, r := range records { - if !r.Spent && r.Value > 0 { + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { addr, err := wal.DecodeAddress(r.Address) if err != nil { return err } - outpointHash, err := hex.DecodeString(r.Txid) + outpointHash, err := hex.DecodeString(strings.TrimPrefix(r.Txid, "0x")) if err != nil { return fmt.Errorf("decoding transaction hash: %s", err.Error()) } - outValue += r.Value + outValue.Add(outValue, &r.Value) in := wallet.TransactionInput{ LinkedAddress: addr, OutpointIndex: r.Index, @@ -198,15 +206,14 @@ func (n *OpenBazaarNode) CompleteOrder(orderRatings *OrderRatings, contract *pb. } var output = wallet.TransactionOutput{ Address: payoutAddress, - Value: outValue, + Value: *outValue, } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincode, err := hex.DecodeString(order.Payment.Chaincode) if err != nil { return err } - mPrivKey := n.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := n.MasterPrivateKey.ECPrivKey() if err != nil { return err } @@ -214,12 +221,16 @@ func (n *OpenBazaarNode) CompleteOrder(orderRatings *OrderRatings, contract *pb. if err != nil { return err } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(order.Payment.RedeemScript) if err != nil { return err } - - buyerSignatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, buyerKey, redeemScript, contract.VendorOrderFulfillment[0].Payout.PayoutFeePerByte) + fulfillment := repo.ToV5OrderFulfillment(contract.VendorOrderFulfillment[0]) + n, ok := new(big.Int).SetString(fulfillment.Payout.BigPayoutFeePerByte, 10) + if !ok { + return errors.New("invalid payout fee per byte value") + } + buyerSignatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, buyerKey, redeemScript, *n) if err != nil { return err } @@ -231,15 +242,6 @@ func (n *OpenBazaarNode) CompleteOrder(orderRatings *OrderRatings, contract *pb. pbSigs = append(pbSigs, sig) } oc.PayoutSigs = pbSigs - var vendorSignatures []wallet.Signature - for _, s := range contract.VendorOrderFulfillment[0].Payout.Sigs { - sig := wallet.Signature{InputIndex: s.InputIndex, Signature: s.Signature} - vendorSignatures = append(vendorSignatures, sig) - } - _, err = wal.Multisign(ins, []wallet.TransactionOutput{output}, buyerSignatures, vendorSignatures, redeemScript, contract.VendorOrderFulfillment[0].Payout.PayoutFeePerByte, true) - if err != nil { - return err - } } rc := new(pb.RicardianContract) @@ -308,16 +310,26 @@ func (n *OpenBazaarNode) ReleaseFundsAfterTimeout(contract *pb.RicardianContract } else if active { return ErrPrematureReleaseOfTimedoutEscrowFunds } - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) + if err != nil { + return err + } + defn, err := repo.AllCurrencies().Lookup(order.Payment.AmountCurrency.Code) if err != nil { + log.Errorf("Failed ReleaseFundsAfterTimeout(): %s", err.Error()) return err } - minConfirms := contract.VendorListings[0].Metadata.EscrowTimeoutHours * ConfirmationsPerHour + minConfirms := contract.VendorListings[0].Metadata.EscrowTimeoutHours * + defn.ConfirmationsPerHour() var txInputs []wallet.TransactionInput for _, r := range records { - if !r.Spent && r.Value > 0 { - hash, err := chainhash.NewHashFromStr(r.Txid) + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { + hash, err := chainhash.NewHashFromStr(strings.TrimPrefix(r.Txid, "0x")) if err != nil { return err } @@ -336,7 +348,7 @@ func (n *OpenBazaarNode) ReleaseFundsAfterTimeout(contract *pb.RicardianContract if err != nil { return err } - outpointHash, err := hex.DecodeString(r.Txid) + outpointHash, err := hex.DecodeString(strings.TrimPrefix(r.Txid, "0x")) if err != nil { return fmt.Errorf("decoding transaction hash: %s", err.Error()) } @@ -350,12 +362,15 @@ func (n *OpenBazaarNode) ReleaseFundsAfterTimeout(contract *pb.RicardianContract } } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + if len(txInputs) == 0 { + return errors.New("there are no inputs available for this transaction") + } + + chaincode, err := hex.DecodeString(order.Payment.Chaincode) if err != nil { return err } - mPrivKey := n.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := n.MasterPrivateKey.ECPrivKey() if err != nil { return err } @@ -363,7 +378,7 @@ func (n *OpenBazaarNode) ReleaseFundsAfterTimeout(contract *pb.RicardianContract if err != nil { return err } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(order.Payment.RedeemScript) if err != nil { return err } @@ -392,7 +407,6 @@ func (n *OpenBazaarNode) SignOrderCompletion(contract *pb.RicardianContract) (*p } s := new(pb.Signature) s.Section = pb.Signature_ORDER_COMPLETION - guidSig, err := n.IpfsNode.PrivateKey.Sign(serializedOrderFulfil) if err != nil { return contract, err @@ -455,7 +469,7 @@ func (n *OpenBazaarNode) ValidateAndSaveRating(contract *pb.RicardianContract) ( continue } - mh, err := EncodeMultihash([]byte(ratingJSON)) + mh, err := ipfs.EncodeMultihash([]byte(ratingJSON)) if err != nil { retErr = err continue diff --git a/core/completion_test.go b/core/completion_test.go index 39225a610b..c7f4475c2b 100644 --- a/core/completion_test.go +++ b/core/completion_test.go @@ -7,9 +7,9 @@ import ( "github.com/OpenBazaar/wallet-interface" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" ) func TestReleaseFundsAfterTimeoutErrors(t *testing.T) { diff --git a/core/confirmation.go b/core/confirmation.go index 7668ac1fc3..ca06a71836 100644 --- a/core/confirmation.go +++ b/core/confirmation.go @@ -5,18 +5,23 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strings" + "time" + + "github.com/phoreproject/pm-go/repo" crypto "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" - "time" "github.com/OpenBazaar/wallet-interface" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/pb" + + "github.com/phoreproject/pm-go/pb" ) // NewOrderConfirmation - add order confirmation to the contract -func (n *OpenBazaarNode) NewOrderConfirmation(contract *pb.RicardianContract, addressRequest, calculateNewTotal bool) (*pb.RicardianContract, error) { +func (n *OpenBazaarNode) NewOrderConfirmation(contract *pb.RicardianContract, addressRequest bool) (*pb.RicardianContract, error) { oc := new(pb.OrderConfirmation) // Calculate order ID orderID, err := n.CalcOrderID(contract.BuyerOrder) @@ -25,14 +30,19 @@ func (n *OpenBazaarNode) NewOrderConfirmation(contract *pb.RicardianContract, ad } oc.OrderID = orderID - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return nil, err + } + + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return nil, err } if addressRequest { addr := wal.NewAddress(wallet.EXTERNAL) - oc.PaymentAddress = addr.EncodeAddress() + oc.PaymentAddress = addr.String() } ts, err := ptypes.TimestampProto(time.Now()) @@ -42,13 +52,13 @@ func (n *OpenBazaarNode) NewOrderConfirmation(contract *pb.RicardianContract, ad oc.Timestamp = ts oc.RatingSignatures = []*pb.RatingSignature{} - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED { + if order.Payment.Method == pb.Order_Payment_MODERATED { for _, listing := range contract.VendorListings { metadata := new(pb.RatingSignature_TransactionMetadata) metadata.ListingSlug = listing.Slug - metadata.ModeratorKey = contract.BuyerOrder.Payment.ModeratorKey + metadata.ModeratorKey = order.Payment.ModeratorKey - if contract.BuyerOrder.Version > 0 { + if order.Version > 0 { metadata.ListingTitle = listing.Item.Title if len(listing.Item.Images) > 0 { metadata.Thumbnail = &pb.RatingSignature_TransactionMetadata_Image{ @@ -76,17 +86,10 @@ func (n *OpenBazaarNode) NewOrderConfirmation(contract *pb.RicardianContract, ad oc.RatingSignatures = append(oc.RatingSignatures, rs) } - oc.PaymentAddress = contract.BuyerOrder.Payment.Address + oc.PaymentAddress = order.Payment.Address } - if calculateNewTotal { - oc.RequestedAmount, err = n.CalculateOrderTotal(contract) - if err != nil { - return nil, err - } - } else { - oc.RequestedAmount = contract.BuyerOrder.Payment.Amount - } + oc.BigRequestedAmount = order.Payment.BigAmount contract.VendorOrderConfirmation = oc contract, err = n.SignOrderConfirmation(contract) if err != nil { @@ -96,26 +99,46 @@ func (n *OpenBazaarNode) NewOrderConfirmation(contract *pb.RicardianContract, ad } // ConfirmOfflineOrder - confirm offline order -func (n *OpenBazaarNode) ConfirmOfflineOrder(contract *pb.RicardianContract, records []*wallet.TransactionRecord) error { - contract, err := n.NewOrderConfirmation(contract, false, false) +func (n *OpenBazaarNode) ConfirmOfflineOrder(oldState pb.OrderState, contract *pb.RicardianContract, records []*wallet.TransactionRecord) error { + confirmedContract, err := n.NewOrderConfirmation(contract, false) if err != nil { return err } - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) if err != nil { return err } - if contract.BuyerOrder.Payment.Method != pb.Order_Payment_MODERATED { + + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) + if err != nil { + return err + } + err = n.Datastore.Sales().Put(confirmedContract.VendorOrderConfirmation.OrderID, *confirmedContract, pb.OrderState_AWAITING_FULFILLMENT, false) + if err != nil { + return err + } + + recoverState := func() { + err = n.Datastore.Sales().Put(confirmedContract.VendorOrderConfirmation.OrderID, *contract, oldState, false) + if err != nil { + log.Errorf("failed to recover state on order (%s): %s", confirmedContract.VendorOrderConfirmation.OrderID, err.Error()) + } + } + + if confirmedContract.BuyerOrder.Payment.Method != pb.Order_Payment_MODERATED { // Sweep the temp address into our wallet var txInputs []wallet.TransactionInput for _, r := range records { - if !r.Spent && r.Value > 0 { + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { addr, err := wal.DecodeAddress(r.Address) if err != nil { + recoverState() return err } - outpointHash, err := hex.DecodeString(r.Txid) + outpointHash, err := hex.DecodeString(strings.TrimPrefix(r.Txid, "0x")) if err != nil { + recoverState() return fmt.Errorf("decoding transaction hash: %s", err.Error()) } txInput := wallet.TransactionInput{ @@ -129,36 +152,42 @@ func (n *OpenBazaarNode) ConfirmOfflineOrder(contract *pb.RicardianContract, rec } if len(txInputs) == 0 { + recoverState() return errors.New("no unspent transactions found to fund order") } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincode, err := hex.DecodeString(confirmedContract.BuyerOrder.Payment.Chaincode) if err != nil { + recoverState() return err } - mPrivKey := n.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := n.MasterPrivateKey.ECPrivKey() if err != nil { + recoverState() return err } vendorKey, err := wal.ChildKey(mECKey.Serialize(), chaincode, true) if err != nil { + recoverState() return err } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(confirmedContract.BuyerOrder.Payment.RedeemScript) if err != nil { + recoverState() return err } _, err = wal.SweepAddress(txInputs, nil, vendorKey, &redeemScript, wallet.NORMAL) if err != nil { + recoverState() return err } } - err = n.SendOrderConfirmation(contract.BuyerOrder.BuyerID.PeerID, contract) + err = n.SendOrderConfirmation(confirmedContract.BuyerOrder.BuyerID.PeerID, confirmedContract) if err != nil { - return err + // TODO: local order state is accurate, remote order state needs to be retransmitted + log.Errorf("failed sending confirmation for order (%s): %s", confirmedContract.VendorOrderConfirmation.OrderID, err.Error()) + return nil } - n.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_AWAITING_FULFILLMENT, false) return nil } @@ -174,21 +203,25 @@ func (n *OpenBazaarNode) RejectOfflineOrder(contract *pb.RicardianContract, reco if err != nil { return fmt.Errorf("marshal timestamp: %s", err.Error()) } - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } rejectMsg.Timestamp = ts - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED { + if order.Payment.Method == pb.Order_Payment_MODERATED { var ins []wallet.TransactionInput - var outValue int64 + outValue := *big.NewInt(0) for _, r := range records { - if !r.Spent && r.Value > 0 { + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { addr, err := wal.DecodeAddress(r.Address) if err != nil { return fmt.Errorf("decode prior transactions address: %s", err.Error()) } - outpointHash, err := hex.DecodeString(r.Txid) + outpointHash, err := hex.DecodeString(strings.TrimPrefix(r.Txid, "0x")) if err != nil { return fmt.Errorf("decoding transaction hash: %s", err.Error()) } @@ -199,11 +232,11 @@ func (n *OpenBazaarNode) RejectOfflineOrder(contract *pb.RicardianContract, reco Value: r.Value, } ins = append(ins, in) - outValue += r.Value + outValue = *new(big.Int).Add(&outValue, &r.Value) } } - refundAddress, err := wal.DecodeAddress(contract.BuyerOrder.RefundAddress) + refundAddress, err := wal.DecodeAddress(order.RefundAddress) if err != nil { return fmt.Errorf("decode refund address: %s", err.Error()) } @@ -212,12 +245,11 @@ func (n *OpenBazaarNode) RejectOfflineOrder(contract *pb.RicardianContract, reco Value: outValue, } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincode, err := hex.DecodeString(order.Payment.Chaincode) if err != nil { return fmt.Errorf("decode buyer chaincode: %s", err.Error()) } - mPrivKey := n.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := n.MasterPrivateKey.ECPrivKey() if err != nil { return fmt.Errorf("generate ec private key: %s", err.Error()) } @@ -225,11 +257,15 @@ func (n *OpenBazaarNode) RejectOfflineOrder(contract *pb.RicardianContract, reco if err != nil { return fmt.Errorf("generate child key: %s", err.Error()) } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(order.Payment.RedeemScript) if err != nil { return fmt.Errorf("generate child key: %s", err.Error()) } - signatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, vendorKey, redeemScript, contract.BuyerOrder.RefundFee) + fee, ok := new(big.Int).SetString(order.BigRefundFee, 10) + if !ok { + return errors.New("invalid refund fee value") + } + signatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, vendorKey, redeemScript, *fee) if err != nil { return fmt.Errorf("generate multisig: %s", err.Error()) } @@ -240,7 +276,7 @@ func (n *OpenBazaarNode) RejectOfflineOrder(contract *pb.RicardianContract, reco } rejectMsg.Sigs = sigs } - err = n.SendReject(contract.BuyerOrder.BuyerID.PeerID, rejectMsg) + err = n.SendReject(order.BuyerID.PeerID, rejectMsg) if err != nil { return fmt.Errorf("sending rejection: %s", err.Error()) } @@ -256,17 +292,24 @@ func (n *OpenBazaarNode) ValidateOrderConfirmation(contract *pb.RicardianContrac if err != nil { return err } - if contract.VendorOrderConfirmation.OrderID != orderID { + + orderConfirmation := repo.ToV5OrderConfirmation(contract.VendorOrderConfirmation) + + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + if orderConfirmation.OrderID != orderID { return errors.New("vendor's response contained invalid order ID") } - if contract.VendorOrderConfirmation.RequestedAmount != contract.BuyerOrder.Payment.Amount { + if orderConfirmation.BigRequestedAmount != order.Payment.BigAmount { return errors.New("vendor requested an amount different from what we calculated") } - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED { + if order.Payment.Method == pb.Order_Payment_MODERATED { for _, sig := range contract.VendorOrderConfirmation.RatingSignatures { exists := false for _, listing := range contract.VendorListings { @@ -283,7 +326,7 @@ func (n *OpenBazaarNode) ValidateOrderConfirmation(contract *pb.RicardianContrac return err } - if !bytes.Equal(sig.Metadata.ModeratorKey, contract.BuyerOrder.Payment.ModeratorKey) { + if !bytes.Equal(sig.Metadata.ModeratorKey, order.Payment.ModeratorKey) { return errors.New("rating signature does not contain moderatory key") } ser, err := proto.Marshal(sig.Metadata) @@ -317,7 +360,6 @@ func (n *OpenBazaarNode) SignOrderConfirmation(contract *pb.RicardianContract) ( } s := new(pb.Signature) s.Section = pb.Signature_ORDER_CONFIRMATION - guidSig, err := n.IpfsNode.PrivateKey.Sign(serializedOrderConf) if err != nil { return contract, err diff --git a/core/core.go b/core/core.go index bea00aeae3..241d83baff 100644 --- a/core/core.go +++ b/core/core.go @@ -2,39 +2,38 @@ package core import ( "errors" + "fmt" + "net/http" + "path" + "sync" + "time" "gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht" libp2p "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" cid "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" - "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" routing "gx/ipfs/QmYxUdYY9S6yg5tSPVin5GFTvtfsLauVcr7reHDD3dM8xf/go-libp2p-routing" - "path" - "sync" - "time" - "github.com/phoreproject/multiwallet" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/net" - rep "github.com/phoreproject/openbazaar-go/net/repointer" - ret "github.com/phoreproject/openbazaar-go/net/retriever" - "github.com/phoreproject/openbazaar-go/repo" - sto "github.com/phoreproject/openbazaar-go/storage" - "github.com/btcsuite/btcutil/hdkeychain" - "github.com/gosimple/slug" "github.com/ipfs/go-ipfs/core" logging "github.com/op/go-logging" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/net" + rep "github.com/phoreproject/pm-go/net/repointer" + ret "github.com/phoreproject/pm-go/net/retriever" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + sto "github.com/phoreproject/pm-go/storage" "golang.org/x/net/context" "golang.org/x/net/proxy" ) const ( // VERSION - current version - VERSION = "2.3.1" + VERSION = "2.4.3" // USERAGENT - user-agent header string USERAGENT = "/Phore-Marketplace-go:" + VERSION + "/" ) @@ -117,16 +116,27 @@ type OpenBazaarNode struct { // the slower the query but the less likely we will get an old record. IPNSQuorumSize uint + // Get mnemoniec password from user - used in case of encrypted mnemonic + MnemonicChan chan string + + // Boolean variable which says if wallet state changing REST requests are locked. + WalletLocked bool + + // Locks wallet after period of time + LockTimer *time.Timer + TestnetEnable bool RegressionTestEnable bool -} -// PublishLock seedLock - Unpin the current node repo, re-add it, then publish to IPNS -var PublishLock sync.Mutex -var seedLock sync.Mutex + PublishLock sync.Mutex + seedLock sync.Mutex -// InitalPublishComplete - indicate publish completion -var InitalPublishComplete bool // = false + InitalPublishComplete bool + + // InboundMsgScanner is a worker that scans the messages + // table and tries to retry a failed order message + InboundMsgScanner *inboundMessageScanner +} // TestNetworkEnabled indicates whether the node is operating with test parameters func (n *OpenBazaarNode) TestNetworkEnabled() bool { return n.TestnetEnable } @@ -136,8 +146,11 @@ func (n *OpenBazaarNode) RegressionNetworkEnabled() bool { return n.RegressionTe // SeedNode - publish to IPNS func (n *OpenBazaarNode) SeedNode() error { - seedLock.Lock() - ipfs.UnPinDir(n.IpfsNode, n.RootHash) + n.seedLock.Lock() + err := ipfs.UnPinDir(n.IpfsNode, n.RootHash) + if err != nil { + log.Errorf("unpinning old root: %s", err.Error()) + } var aerr error var rootHash string // There's an IPFS bug on Windows that might be related to the Windows indexer that could cause this to fail @@ -150,12 +163,13 @@ func (n *OpenBazaarNode) SeedNode() error { time.Sleep(time.Millisecond * 500) } if aerr != nil { - seedLock.Unlock() + n.seedLock.Unlock() return aerr } n.RootHash = rootHash - seedLock.Unlock() - InitalPublishComplete = true + + n.seedLock.Unlock() + n.InitalPublishComplete = true go n.publish(rootHash) return nil } @@ -163,8 +177,8 @@ func (n *OpenBazaarNode) SeedNode() error { func (n *OpenBazaarNode) publish(hash string) { // Multiple publishes may have been queued // We only need to publish the most recent - PublishLock.Lock() - defer PublishLock.Unlock() + n.PublishLock.Lock() + defer n.PublishLock.Unlock() if hash != n.RootHash { return } @@ -179,6 +193,27 @@ func (n *OpenBazaarNode) publish(hash string) { return } + go func() { + // Update search endpoint with published hash + peerId, _ := n.GetNodeID() + endpoint := fmt.Sprintf("https://search.phore.io/update/%s/%s", peerId.PeerID, hash) + log.Infof("Publishing new rootHash to: %s\n", endpoint) + + var client *http.Client + if n.TorDialer != nil { + tbTransport := &http.Transport{Dial: n.TorDialer.Dial} + client = &http.Client{Transport: tbTransport, Timeout: time.Second * 30} + } else { + client = &http.Client{Timeout: time.Second * 30} + } + + resp, err := client.Get(endpoint) + if err != nil { + log.Errorf("Search update did not succeed. %v\n", err) + } + log.Debugf("%s response: %v", endpoint, resp) + }() + inflightPublishRequests++ err = ipfs.Publish(n.IpfsNode, hash) @@ -240,7 +275,7 @@ func (n *OpenBazaarNode) retryableSeedStoreToPeer(pid peer.ID, graphHash string, } err := n.SendStore(pid.Pretty(), graph) if err != nil { - if retryTimeout > 60*time.Second { + if retryTimeout > 8*time.Second { log.Errorf("error pushing to peer %s: %s", pid.Pretty(), err.Error()) return } @@ -261,8 +296,14 @@ func (n *OpenBazaarNode) SetUpRepublisher(interval time.Duration) { ticker := time.NewTicker(interval) go func() { for range ticker.C { - n.UpdateFollow() - n.SeedNode() + err := n.UpdateFollow() + if err != nil { + log.Error(err) + } + err = n.SeedNode() + if err != nil { + log.Error(err) + } } }() } @@ -274,8 +315,11 @@ func (n *OpenBazaarNode) EncryptMessage(peerID peer.ID, peerKey *libp2p.PubKey, ctx, cancel := context.WithTimeout(context.Background(), n.OfflineMessageFailoverTimeout) defer cancel() if peerKey == nil { - var pubKey libp2p.PubKey - keyval, err := n.IpfsNode.Repo.Datastore().Get(datastore.NewKey(KeyCachePrefix + peerID.Pretty())) + var ( + pubKey libp2p.PubKey + store = n.IpfsNode.Repo.Datastore() + ) + keyval, err := ipfs.GetCachedPubkey(store, peerID.Pretty()) if err != nil { pubKey, err = routing.GetPublicKey(n.IpfsNode.Routing, ctx, peerID) if err != nil { @@ -307,13 +351,159 @@ func (n *OpenBazaarNode) IPFSIdentityString() string { return n.IpfsNode.Identity.Pretty() } -// createSlugFor Create a slug from a multi-lang string -func createSlugFor(slugName string) string { - l := SentenceMaxCharacters - SlugBuffer +// GetNodeID returns the protobuf representing the node's identity and crypto +// keys with the peer ID +func (n *OpenBazaarNode) GetNodeID() (*pb.ID, error) { + var id = new(pb.ID) + id.PeerID = n.IpfsNode.Identity.Pretty() + + if p, err := n.GetProfile(); err == nil { + id.Handle = p.Handle + } + + p := new(pb.ID_Pubkeys) + pubkey, err := n.IpfsNode.PrivateKey.GetPublic().Bytes() + if err != nil { + return nil, fmt.Errorf("ipfs pubkey bytes: %s", err.Error()) + } + p.Identity = pubkey + coinPubkey, err := n.MasterPrivateKey.ECPubKey() + if err != nil { + return nil, fmt.Errorf("master pubkey: %s", err.Error()) + } + p.Bitcoin = coinPubkey.SerializeCompressed() + id.Pubkeys = p + + coinPrivKey, err := n.MasterPrivateKey.ECPrivKey() + if err != nil { + return nil, fmt.Errorf("master privkey: %s", err.Error()) + } + coinSig, err := coinPrivKey.Sign([]byte(id.PeerID)) + if err != nil { + return nil, fmt.Errorf("sign id: %s", err.Error()) + } + id.BitcoinSig = coinSig.Serialize() + + return id, nil +} + +func (n *OpenBazaarNode) IsWalletLocked() bool { + _, isLocked, err := n.Datastore.Config().GetMnemonic() + if err != nil { + log.Error(err) + } + + if !isLocked { + return false + } + + return n.WalletLocked +} + +func (n *OpenBazaarNode) UnlockMnemonic(unlockWallet ManageWalletRequest) error { + mnemonic, isLocked, err := n.Datastore.Config().GetMnemonic() + if err != nil { + return err + } + + if isLocked { + mnemonic, err = DecryptMnemonic(mnemonic, unlockWallet.WalletPassword) + if err != nil { + return err + } + } + + if n.MnemonicChan != nil { + select { + case n.MnemonicChan <- mnemonic: + default: + if unlockWallet.SkipChangeMnemonicState { + log.Warning("User is asking to unlock wallet for current run only, but no service is waiting for password to unlock.") + } + } + } + + return nil +} + +func (n *OpenBazaarNode) UnlockWallet(unlockWallet ManageWalletRequest) (bool, bool, error) { + mnemonic, isMnemonicEncrypted, err := n.Datastore.Config().GetMnemonic() + if err != nil { + return true, isMnemonicEncrypted, err + } + + // Wallet status unlocked and skip mnemonic unlocking -> nothing to do. TIMESTAMP NOT UPDATED! + if !n.WalletLocked && unlockWallet.SkipChangeMnemonicState { + return n.WalletLocked, isMnemonicEncrypted, nil + } + + // Checks password, fails when mnemonic in not encrypted! + decryptedMnemonic, err := DecryptMnemonic(mnemonic, unlockWallet.WalletPassword) + if err != nil { + return n.WalletLocked, isMnemonicEncrypted, err + } + + // Time lock feature set up. + if unlockWallet.UnlockTimestamp != 0 { + if n.LockTimer != nil { + n.LockTimer.Stop() + } + n.LockTimer = time.AfterFunc(time.Second*time.Duration(unlockWallet.UnlockTimestamp), func() { + n.WalletLocked = true + }) + } + + // Password is correct, time lock set up, so change wallet status to unlock state. + if !isMnemonicEncrypted { + n.WalletLocked = false + return false, isMnemonicEncrypted, nil + } + + // If mnemonic locked and omit decryption not set, additionally decrypt mnemonic in db. + if !unlockWallet.SkipChangeMnemonicState { + err = n.Datastore.Config().UpdateMnemonic(decryptedMnemonic, false) + if err != nil { + return n.WalletLocked, isMnemonicEncrypted, err + } + } + + n.WalletLocked = false + return n.WalletLocked, isMnemonicEncrypted, nil +} + +func (n *OpenBazaarNode) LockWallet(lockWallet ManageWalletRequest) (bool, bool, error) { + mnemonic, isMnemonicLocked, err := n.Datastore.Config().GetMnemonic() + if err != nil { + return false, isMnemonicLocked, err + } + + // wallet is not locked, because have to be encrypted first. + if lockWallet.SkipChangeMnemonicState && !isMnemonicLocked { + return false, isMnemonicLocked, nil + } + + // mnemonic already locked so change wallet state to locked. + if isMnemonicLocked { + n.WalletLocked = true + return true, isMnemonicLocked, nil + } + + // mnemonic is unlocked, so encrypt it first. + encryptedMnemonic, err := EncryptMnemonic(mnemonic, lockWallet.WalletPassword) + if err != nil { + return false, isMnemonicLocked, err + } - slug := slug.Make(slugName) - if len(slug) < SentenceMaxCharacters-SlugBuffer { - l = len(slug) + err = n.Datastore.Config().UpdateMnemonic(encryptedMnemonic, true) + if err != nil { + return false, isMnemonicLocked, err } - return slug[:l] + + n.WalletLocked = true + return n.WalletLocked, isMnemonicLocked, nil +} + +// Sign returns a signature for the payload signed by the IPFS private key +func (n *OpenBazaarNode) Sign(payload []byte) ([]byte, error) { + return n.IpfsNode.PrivateKey.Sign(payload) } diff --git a/core/core_test.go b/core/core_test.go new file mode 100644 index 0000000000..820e27b435 --- /dev/null +++ b/core/core_test.go @@ -0,0 +1,68 @@ +package core_test + +import ( + "regexp" + "strconv" + "testing" + + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/util" +) + +func TestEmojiToHTML(t *testing.T) { + var ( + expected string + container = make(map[string]string) + rx = regexp.MustCompile(util.EmojiPattern) + text = "a #💩 #and #🍦 #😳" + i = -1 + replaced = rx.ReplaceAllStringFunc(text, func(s string) string { + i++ + key := "_$" + strconv.Itoa(i) + "_" + container[key] = s + return key + }) + ) + + expected = "a #_$0_ #and #_$1_ #_$2_" + if replaced != expected { + t.Errorf("expected processed string to be %s, but was %s", expected, replaced) + } + + htmlEnt := repo.ToHtmlEntities(text) + + expected = "a #💩 #and #🍦 #😳" + if htmlEnt != expected { + t.Errorf("expected processed string to be %s, but was %s", expected, replaced) + } + + recovered := regexp.MustCompile(`\_\$\d+\_`).ReplaceAllStringFunc(replaced, func(s string) string { + return container[s] + }) + if recovered != text { + t.Errorf("expected processed string to be %s, but was %s", text, recovered) + } +} + +func TestToHtmlEntities(t *testing.T) { + tests := []struct { + slug string + expected string + }{ + { + "This_listing_is_💩💩", + "This_listing_is_💩💩", + }, + { + "slug-with$-no_#emojis", + "slug-with$-no_#emojis", + }, + } + + for i, test := range tests { + transformed := repo.ToHtmlEntities(test.slug) + if transformed != test.expected { + t.Errorf("Test %d failed. Expected %s got %s", i, test.expected, transformed) + } + } +} diff --git a/core/disputes.go b/core/disputes.go index 53f3d14db1..564584226c 100644 --- a/core/disputes.go +++ b/core/disputes.go @@ -4,29 +4,31 @@ import ( "crypto/sha256" "encoding/hex" "errors" - - libp2p "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" - "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" - + "fmt" + "math/big" "strconv" "sync" "time" + libp2p "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" + "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcutil" hd "github.com/btcsuite/btcutil/hdkeychain" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/net" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" "golang.org/x/net/context" -) -// ConfirmationsPerHour is temporary until the Wallet interface has Attributes() to provide this value -const ConfirmationsPerHour = 6 + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/net" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/util" +) // DisputeWg - waitgroup for disputes var DisputeWg = new(sync.WaitGroup) @@ -49,8 +51,13 @@ func (n *OpenBazaarNode) OpenDispute(orderID string, contract *pb.RicardianContr if !n.verifyEscrowFundsAreDisputeable(contract, records) { return ErrOpenFailureOrderExpired } + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + var isPurchase bool - if n.IpfsNode.Identity.Pretty() == contract.BuyerOrder.BuyerID.PeerID { + if n.IpfsNode.Identity.Pretty() == order.BuyerID.PeerID { isPurchase = true } @@ -70,14 +77,14 @@ func (n *OpenBazaarNode) OpenDispute(orderID string, contract *pb.RicardianContr var outpoints []*pb.Outpoint for _, r := range records { o := new(pb.Outpoint) - o.Hash = r.Txid + o.Hash = util.NormalizeAddress(r.Txid) o.Index = r.Index - o.Value = uint64(r.Value) + o.BigValue = r.Value.String() outpoints = append(outpoints, o) } dispute.Outpoints = outpoints - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } @@ -103,7 +110,7 @@ func (n *OpenBazaarNode) OpenDispute(orderID string, contract *pb.RicardianContr contract.Signatures = append(contract.Signatures, rc.Signatures[0]) // Send to moderator - err = n.SendDisputeOpen(contract.BuyerOrder.Payment.Moderator, nil, rc) + err = n.SendDisputeOpen(order.Payment.Moderator, nil, rc, orderID) if err != nil { return err } @@ -118,44 +125,64 @@ func (n *OpenBazaarNode) OpenDispute(orderID string, contract *pb.RicardianContr return nil } } else { - counterparty = contract.BuyerOrder.BuyerID.PeerID - counterkey, err = libp2p.UnmarshalPublicKey(contract.BuyerOrder.BuyerID.Pubkeys.Identity) + counterparty = order.BuyerID.PeerID + counterkey, err = libp2p.UnmarshalPublicKey(order.BuyerID.Pubkeys.Identity) if err != nil { return nil } } - err = n.SendDisputeOpen(counterparty, &counterkey, rc) + err = n.SendDisputeOpen(counterparty, &counterkey, rc, orderID) if err != nil { return err } // Update database if isPurchase { - n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_DISPUTED, true) + err = n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_DISPUTED, true) + if err != nil { + log.Error(err) + } } else { - n.Datastore.Sales().Put(orderID, *contract, pb.OrderState_DISPUTED, true) + err = n.Datastore.Sales().Put(orderID, *contract, pb.OrderState_DISPUTED, true) + if err != nil { + log.Error(err) + } } return nil } func (n *OpenBazaarNode) verifyEscrowFundsAreDisputeable(contract *pb.RicardianContract, records []*wallet.TransactionRecord) bool { - confirmationsForTimeout := contract.VendorListings[0].Metadata.EscrowTimeoutHours * ConfirmationsPerHour - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return false + } + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) + if err != nil { + log.Errorf("Failed verifyEscrowFundsAreDisputeable(): %s", err.Error()) + return false + } + defn, err := repo.AllCurrencies().Lookup(order.Payment.AmountCurrency.Code) if err != nil { log.Errorf("Failed verifyEscrowFundsAreDisputeable(): %s", err.Error()) return false } for _, r := range records { - hash, err := chainhash.NewHashFromStr(r.Txid) + hash, err := chainhash.NewHashFromStr(util.NormalizeAddress(r.Txid)) if err != nil { log.Errorf("Failed NewHashFromStr(%s): %s", r.Txid, err.Error()) return false } + if hash == nil { + log.Errorf("Nil NewHashFromStr(%s)", r.Txid) + return false + } actualConfirmations, _, err := wal.GetConfirmations(*hash) if err != nil { log.Errorf("Failed GetConfirmations(%s): %s", hash.String(), err.Error()) return false } + confirmationsForTimeout := contract.VendorListings[0].Metadata.EscrowTimeoutHours * + defn.ConfirmationsPerHour() if actualConfirmations >= confirmationsForTimeout { return false } @@ -229,6 +256,8 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str return errors.New("dispute message is nil") } + dispute := repo.ToV5Dispute(rc.Dispute) + // Deserialize contract contract := new(pb.RicardianContract) err := proto.Unmarshal(rc.Dispute.SerializedContract, contract) @@ -239,12 +268,17 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str return errors.New("serialized contract is malformatted") } + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + orderID, err := n.CalcOrderID(contract.BuyerOrder) if err != nil { return err } - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } @@ -255,8 +289,8 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str if len(contract.VendorListings) > 0 && contract.VendorListings[0].Item != nil && len(contract.VendorListings[0].Item.Images) > 0 { thumbnailTiny = contract.VendorListings[0].Item.Images[0].Tiny thumbnailSmall = contract.VendorListings[0].Item.Images[0].Small - if contract.BuyerOrder != nil && contract.BuyerOrder.BuyerID != nil { - buyer = contract.BuyerOrder.BuyerID.PeerID + if order.BuyerID != nil { + buyer = order.BuyerID.PeerID } } @@ -265,32 +299,40 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str var DisputerHandle string var DisputeeID string var DisputeeHandle string - if contract.BuyerOrder.Payment.Moderator == n.IpfsNode.Identity.Pretty() { // Moderator + if order.Payment.Moderator == n.IpfsNode.Identity.Pretty() { // Moderator validationErrors := n.ValidateCaseContract(contract) var err error if contract.VendorListings[0].VendorID.PeerID == peerID { DisputerID = contract.VendorListings[0].VendorID.PeerID DisputerHandle = contract.VendorListings[0].VendorID.Handle - DisputeeID = contract.BuyerOrder.BuyerID.PeerID - DisputeeHandle = contract.BuyerOrder.BuyerID.Handle - err = n.Datastore.Cases().Put(orderID, pb.OrderState_DISPUTED, false, rc.Dispute.Claim, db.PaymentCoinForContract(contract), db.CoinTypeForContract(contract)) + DisputeeID = order.BuyerID.PeerID + DisputeeHandle = order.BuyerID.Handle + paymentCoin, err := db.PaymentCoinForContract(contract) if err != nil { return err } - err = n.Datastore.Cases().UpdateVendorInfo(orderID, contract, validationErrors, rc.Dispute.PayoutAddress, rc.Dispute.Outpoints) + err = n.Datastore.Cases().Put(orderID, pb.OrderState_DISPUTED, false, rc.Dispute.Claim, paymentCoin, db.CoinTypeForContract(contract)) if err != nil { return err } - } else if contract.BuyerOrder.BuyerID.PeerID == peerID { - DisputerID = contract.BuyerOrder.BuyerID.PeerID - DisputerHandle = contract.BuyerOrder.BuyerID.Handle + err = n.Datastore.Cases().UpdateVendorInfo(orderID, contract, validationErrors, rc.Dispute.PayoutAddress, dispute.Outpoints) + if err != nil { + return err + } + } else if order.BuyerID.PeerID == peerID { + DisputerID = order.BuyerID.PeerID + DisputerHandle = order.BuyerID.Handle DisputeeID = contract.VendorListings[0].VendorID.PeerID DisputeeHandle = contract.VendorListings[0].VendorID.Handle - err = n.Datastore.Cases().Put(orderID, pb.OrderState_DISPUTED, true, rc.Dispute.Claim, db.PaymentCoinForContract(contract), db.CoinTypeForContract(contract)) + paymentCoin, err := db.PaymentCoinForContract(contract) + if err != nil { + return err + } + err = n.Datastore.Cases().Put(orderID, pb.OrderState_DISPUTED, true, rc.Dispute.Claim, paymentCoin, db.CoinTypeForContract(contract)) if err != nil { return err } - err = n.Datastore.Cases().UpdateBuyerInfo(orderID, contract, validationErrors, rc.Dispute.PayoutAddress, rc.Dispute.Outpoints) + err = n.Datastore.Cases().UpdateBuyerInfo(orderID, contract, validationErrors, rc.Dispute.PayoutAddress, dispute.Outpoints) if err != nil { return err } @@ -301,13 +343,16 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str return err } } else if contract.VendorListings[0].VendorID.PeerID == n.IpfsNode.Identity.Pretty() { // Vendor - DisputerID = contract.BuyerOrder.BuyerID.PeerID - DisputerHandle = contract.BuyerOrder.BuyerID.Handle + DisputerID = order.BuyerID.PeerID + DisputerHandle = order.BuyerID.Handle DisputeeID = contract.VendorListings[0].VendorID.PeerID DisputeeHandle = contract.VendorListings[0].VendorID.Handle - // Load out version of the contract from the db + // Load our version of the contract from the db myContract, state, _, records, _, _, err := n.Datastore.Sales().GetByOrderId(orderID) if err != nil { + if err := n.SendProcessingError(DisputerID, orderID, pb.Message_DISPUTE_OPEN, nil); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", DisputerID, err) + } return net.OutOfOrderMessage } // Check this order is currently in a state which can be disputed @@ -328,9 +373,9 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str var outpoints []*pb.Outpoint for _, r := range records { o := new(pb.Outpoint) - o.Hash = r.Txid + o.Hash = util.NormalizeAddress(r.Txid) o.Index = r.Index - o.Value = uint64(r.Value) + o.BigValue = r.Value.String() outpoints = append(outpoints, o) } update.Outpoints = outpoints @@ -353,11 +398,11 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str if err != nil { return err } - } else if contract.BuyerOrder.BuyerID.PeerID == n.IpfsNode.Identity.Pretty() { // Buyer + } else if order.BuyerID.PeerID == n.IpfsNode.Identity.Pretty() { // Buyer DisputerID = contract.VendorListings[0].VendorID.PeerID DisputerHandle = contract.VendorListings[0].VendorID.Handle - DisputeeID = contract.BuyerOrder.BuyerID.PeerID - DisputeeHandle = contract.BuyerOrder.BuyerID.Handle + DisputeeID = order.BuyerID.PeerID + DisputeeHandle = order.BuyerID.Handle // Load out version of the contract from the db myContract, state, _, records, _, _, err := n.Datastore.Purchases().GetByOrderId(orderID) @@ -365,6 +410,9 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str return err } if state == pb.OrderState_AWAITING_PAYMENT || state == pb.OrderState_AWAITING_FULFILLMENT || state == pb.OrderState_PARTIALLY_FULFILLED || state == pb.OrderState_PENDING { + if err := n.SendProcessingError(DisputerID, orderID, pb.Message_DISPUTE_OPEN, myContract); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", DisputerID, err) + } return net.OutOfOrderMessage } // Check this order is currently in a state which can be disputed @@ -385,9 +433,9 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str var outpoints []*pb.Outpoint for _, r := range records { o := new(pb.Outpoint) - o.Hash = r.Txid + o.Hash = util.NormalizeAddress(r.Txid) o.Index = r.Index - o.Value = uint64(r.Value) + o.BigValue = r.Value.String() outpoints = append(outpoints, o) } update.Outpoints = outpoints @@ -426,7 +474,10 @@ func (n *OpenBazaarNode) ProcessDisputeOpen(rc *pb.RicardianContract, peerID str Buyer: buyer, } n.Broadcast <- notif - n.Datastore.Notifications().PutRecord(repo.NewNotification(notif, time.Now(), false)) + err = n.Datastore.Notifications().PutRecord(repo.NewNotification(notif, time.Now(), false)) + if err != nil { + log.Error(err) + } return nil } @@ -451,12 +502,6 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer return ErrCloseFailureCaseExpired } - var outpoints = dispute.ResolutionPaymentOutpoints(payDivision) - if outpoints == nil { - log.Errorf("no outpoints to resolve in dispute for order %s", orderID) - return ErrCloseFailureNoOutpoints - } - if dispute.VendorContract == nil && vendorPercentage > 0 { return errors.New("vendor must provide his copy of the contract before you can release funds to the vendor") } @@ -465,13 +510,35 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer dispute.BuyerContract = dispute.VendorContract } preferredContract := dispute.ResolutionPaymentContract(payDivision) + preferredOrder, err := repo.ToV5Order(preferredContract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + + var outpoints = dispute.ResolutionPaymentOutpoints(payDivision) + if outpoints == nil { + log.Errorf("no outpoints to resolve in dispute for order %s", orderID) + return ErrCloseFailureNoOutpoints + } + for i, o := range outpoints { + if preferredContract.VendorListings[0].Metadata.Version < repo.ListingVersion { + if o.BigValue != "" { + n, ok := new(big.Int).SetString(o.BigValue, 10) + if !ok { + return errors.New("invalid amount") + } + outpoints[i].Value = n.Uint64() + outpoints[i].BigValue = "" + } + } + } // TODO: Remove once broken contracts are migrated - paymentCoin := preferredContract.BuyerOrder.Payment.Coin - _, err = repo.LoadCurrencyDefinitions().Lookup(paymentCoin) + paymentCoin := preferredOrder.Payment.AmountCurrency.Code + _, err = n.LookupCurrency(paymentCoin) if err != nil { log.Warningf("invalid BuyerOrder.Payment.Coin (%s) on order (%s)", paymentCoin, orderID) - preferredContract.BuyerOrder.Payment.Coin = paymentCoinHint.String() + //preferredContract.BuyerOrder.Payment.Coin = paymentCoinHint.String() } var d = new(pb.DisputeResolution) @@ -494,9 +561,9 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer var ( vendorID = preferredContract.VendorListings[0].VendorID.PeerID - buyerID = preferredContract.BuyerOrder.BuyerID.PeerID + buyerID = preferredOrder.BuyerID.PeerID ) - buyerKey, err := libp2p.UnmarshalPublicKey(preferredContract.BuyerOrder.BuyerID.Pubkeys.Identity) + buyerKey, err := libp2p.UnmarshalPublicKey(preferredOrder.BuyerID.Pubkeys.Identity) if err != nil { return err } @@ -506,61 +573,75 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer } // Calculate total out value - var totalOut uint64 + totalOut := big.NewInt(0) for _, o := range outpoints { - totalOut += o.Value + var n *big.Int + if o.Value > 0 { + n = big.NewInt(int64(o.Value)) + } else { + ok := false + n, ok = new(big.Int).SetString(o.BigValue, 10) + if !ok { + return errors.New("invalid amount") + } + } + totalOut = new(big.Int).Add(totalOut, n) } - wal, err := n.Multiwallet.WalletForCurrencyCode(preferredContract.BuyerOrder.Payment.Coin) + wal, err := n.Multiwallet.WalletForCurrencyCode(preferredOrder.Payment.AmountCurrency.Code) if err != nil { - return err + return fmt.Errorf("currency (%s) not supported by wallet", preferredOrder.Payment.AmountCurrency.Code) } // Create outputs using full value. We will subtract the fee off each output later. outMap := make(map[string]wallet.TransactionOutput) var outputs []wallet.TransactionOutput var modAddr btcutil.Address - var modValue uint64 + var modValue *big.Int modAddr = wal.CurrentAddress(wallet.EXTERNAL) - modValue, err = n.GetModeratorFee(totalOut, preferredContract.BuyerOrder.Payment.Coin, wal.CurrencyCode()) + modValue, err = n.GetModeratorFee(totalOut, preferredOrder.Payment.AmountCurrency.Code) if err != nil { return err } - if modValue > 0 { + if modValue.Cmp(big.NewInt(0)) > 0 { out := wallet.TransactionOutput{ Address: modAddr, - Value: int64(modValue), + Value: *modValue, + Index: 0, } outputs = append(outputs, out) outMap["moderator"] = out } var buyerAddr btcutil.Address - var buyerValue uint64 + effectiveVal := new(big.Int).Sub(totalOut, modValue) if payDivision.BuyerAny() { buyerAddr, err = wal.DecodeAddress(dispute.BuyerPayoutAddress) if err != nil { return err } - buyerValue = uint64((float64(totalOut) - float64(modValue)) * (float64(buyerPercentage) / 100)) + buyerValue := new(big.Int).Mul(effectiveVal, big.NewInt(int64(buyerPercentage))) + buyerValue = buyerValue.Div(buyerValue, big.NewInt(100)) out := wallet.TransactionOutput{ Address: buyerAddr, - Value: int64(buyerValue), + Value: *buyerValue, + Index: 1, } outputs = append(outputs, out) outMap["buyer"] = out } var vendorAddr btcutil.Address - var vendorValue uint64 if payDivision.VendorAny() { vendorAddr, err = wal.DecodeAddress(dispute.VendorPayoutAddress) if err != nil { return err } - vendorValue = uint64((float64(totalOut) - float64(modValue)) * (float64(vendorPercentage) / 100)) + vendorValue := new(big.Int).Mul(effectiveVal, big.NewInt(int64(vendorPercentage))) + vendorValue = vendorValue.Div(vendorValue, big.NewInt(100)) out := wallet.TransactionOutput{ Address: vendorAddr, - Value: int64(vendorValue), + Value: *vendorValue, + Index: 2, } outputs = append(outputs, out) outMap["vendor"] = out @@ -577,10 +658,20 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer if err != nil { return err } + var n *big.Int + if o.Value > 0 { + n = big.NewInt(int64(o.Value)) + } else { + ok := false + n, ok = new(big.Int).SetString(o.BigValue, 10) + if !ok { + return errors.New("invalid amount") + } + } input := wallet.TransactionInput{ OutpointHash: decodedHash, OutpointIndex: o.Index, - Value: int64(o.Value), + Value: *n, } inputs = append(inputs, input) } @@ -591,20 +682,23 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer // Calculate total fee defaultFee := wal.GetFeePerByte(wallet.NORMAL) - txFee := wal.EstimateFee(inputs, outputs, dispute.ResolutionPaymentFeePerByte(payDivision, defaultFee)) + txFee := wal.EstimateFee(inputs, outputs, *dispute.ResolutionPaymentFeePerByte(payDivision, defaultFee)) // Subtract fee from each output in proportion to output value var outs []wallet.TransactionOutput for role, output := range outMap { - outPercentage := float64(output.Value) / float64(totalOut) - outputShareOfFee := outPercentage * float64(txFee) - val := output.Value - int64(outputShareOfFee) - if !wal.IsDust(val) { + outPercentage := new(big.Float).Quo(new(big.Float).SetInt(&output.Value), new(big.Float).SetInt(totalOut)) + outputShareOfFee := new(big.Float).Mul(outPercentage, new(big.Float).SetInt(&txFee)) + valF := new(big.Float).Sub(new(big.Float).SetInt(&output.Value), outputShareOfFee) + val, _ := valF.Int(nil) + if !wal.IsDust(*val) { o := wallet.TransactionOutput{ - Value: val, + Value: *val, Address: output.Address, Index: output.Index, } + output.Value = *val + outMap[role] = output outs = append(outs, o) } else { delete(outMap, role) @@ -612,13 +706,12 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer } // Create moderator key - chaincode := preferredContract.BuyerOrder.Payment.Chaincode + chaincode := preferredOrder.Payment.Chaincode chaincodeBytes, err := hex.DecodeString(chaincode) if err != nil { return err } - mPrivKey := n.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := n.MasterPrivateKey.ECPrivKey() if err != nil { return err } @@ -644,12 +737,13 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer } // Create signatures - redeemScript := preferredContract.BuyerOrder.Payment.RedeemScript + redeemScript := preferredOrder.Payment.RedeemScript redeemScriptBytes, err := hex.DecodeString(redeemScript) if err != nil { return err } - sigs, err := wal.CreateMultisigSignature(inputs, outs, moderatorKey, redeemScriptBytes, 0) + + sigs, err := wal.CreateMultisigSignature(inputs, outs, moderatorKey, redeemScriptBytes, *big.NewInt(0)) if err != nil { return err } @@ -665,29 +759,42 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer payout := new(pb.DisputeResolution_Payout) payout.Inputs = outpoints payout.Sigs = bitcoinSigs - if _, ok := outMap["buyer"]; ok { - outputShareOfFee := (float64(buyerValue) / float64(totalOut)) * float64(txFee) - amt := int64(buyerValue) - int64(outputShareOfFee) - if amt < 0 { - amt = 0 + if out, ok := outMap["buyer"]; ok { + payout.BuyerOutput = &pb.DisputeResolution_Payout_Output{ + ScriptOrAddress: &pb.DisputeResolution_Payout_Output_Address{Address: buyerAddr.String()}, + } + if preferredContract.VendorListings[0].Metadata.Version >= repo.ListingVersion { + payout.BuyerOutput.BigAmount = out.Value.String() + } else { + payout.BuyerOutput.Amount = out.Value.Uint64() } - payout.BuyerOutput = &pb.DisputeResolution_Payout_Output{ScriptOrAddress: &pb.DisputeResolution_Payout_Output_Address{buyerAddr.String()}, Amount: uint64(amt)} } - if _, ok := outMap["vendor"]; ok { - outputShareOfFee := (float64(vendorValue) / float64(totalOut)) * float64(txFee) - amt := int64(vendorValue) - int64(outputShareOfFee) - if amt < 0 { - amt = 0 + if out, ok := outMap["vendor"]; ok { + payout.VendorOutput = &pb.DisputeResolution_Payout_Output{ + ScriptOrAddress: &pb.DisputeResolution_Payout_Output_Address{Address: vendorAddr.String()}, + } + if preferredContract.VendorListings[0].Metadata.Version >= repo.ListingVersion { + payout.VendorOutput.BigAmount = out.Value.String() + } else { + payout.VendorOutput.Amount = out.Value.Uint64() } - payout.VendorOutput = &pb.DisputeResolution_Payout_Output{ScriptOrAddress: &pb.DisputeResolution_Payout_Output_Address{vendorAddr.String()}, Amount: uint64(amt)} } - if _, ok := outMap["moderator"]; ok { - outputShareOfFee := (float64(modValue) / float64(totalOut)) * float64(txFee) - amt := int64(modValue) - int64(outputShareOfFee) - if amt < 0 { - amt = 0 + if out, ok := outMap["moderator"]; ok { + payout.ModeratorOutput = &pb.DisputeResolution_Payout_Output{ + ScriptOrAddress: &pb.DisputeResolution_Payout_Output_Address{Address: modAddr.String()}, + } + if preferredContract.VendorListings[0].Metadata.Version >= repo.ListingVersion { + payout.ModeratorOutput.BigAmount = out.Value.String() + } else { + payout.ModeratorOutput.Amount = out.Value.Uint64() + } + } + + if preferredContract.VendorListings[0].Metadata.Version >= repo.ListingVersion { + payout.PayoutCurrency = &pb.CurrencyDefinition{ + Code: preferredOrder.Payment.AmountCurrency.Code, + Divisibility: preferredOrder.Payment.AmountCurrency.Divisibility, } - payout.ModeratorOutput = &pb.DisputeResolution_Payout_Output{ScriptOrAddress: &pb.DisputeResolution_Payout_Output_Address{modAddr.String()}, Amount: uint64(amt)} } d.Payout = payout @@ -699,11 +806,11 @@ func (n *OpenBazaarNode) CloseDispute(orderID string, buyerPercentage, vendorPer return err } - err = n.SendDisputeClose(buyerID, &buyerKey, rc) + err = n.SendDisputeClose(buyerID, &buyerKey, rc, orderID) if err != nil { return err } - err = n.SendDisputeClose(vendorID, &vendorKey, rc) + err = n.SendDisputeClose(vendorID, &vendorKey, rc, orderID) if err != nil { return err } @@ -774,7 +881,7 @@ func (n *OpenBazaarNode) ValidateCaseContract(contract *pb.RicardianContract) [] if err != nil { continue } - listingMH, err := EncodeCID(ser) + listingMH, err := ipfs.EncodeCID(ser) if err != nil { continue } @@ -865,12 +972,17 @@ func (n *OpenBazaarNode) ValidateCaseContract(contract *pb.RicardianContract) [] // Verify the redeem script matches all the bitcoin keys if contract.BuyerOrder.Payment != nil { - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + validationErrors = append(validationErrors, fmt.Sprintf("Error converting to v5 order: %s", err)) + return validationErrors + } + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { validationErrors = append(validationErrors, "Contract uses a coin not found in wallet") return validationErrors } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincode, err := hex.DecodeString(order.Payment.Chaincode) if err != nil { validationErrors = append(validationErrors, "Error validating bitcoin address and redeem script") return validationErrors @@ -885,7 +997,7 @@ func (n *OpenBazaarNode) ValidateCaseContract(contract *pb.RicardianContract) [] validationErrors = append(validationErrors, "Error validating bitcoin address and redeem script") return validationErrors } - buyerKey, err := wal.ChildKey(contract.BuyerOrder.BuyerID.Pubkeys.Bitcoin, chaincode, false) + buyerKey, err := wal.ChildKey(order.BuyerID.Pubkeys.Bitcoin, chaincode, false) if err != nil { validationErrors = append(validationErrors, "Error validating bitcoin address and redeem script") return validationErrors @@ -902,11 +1014,11 @@ func (n *OpenBazaarNode) ValidateCaseContract(contract *pb.RicardianContract) [] return validationErrors } - if contract.BuyerOrder.Payment.Address != addr.EncodeAddress() { + if util.NormalizeAddress(order.Payment.Address) != util.NormalizeAddress(addr.String()) { validationErrors = append(validationErrors, "The calculated bitcoin address doesn't match the address in the order") } - if hex.EncodeToString(redeemScript) != contract.BuyerOrder.Payment.RedeemScript { + if hex.EncodeToString(redeemScript) != order.Payment.RedeemScript { validationErrors = append(validationErrors, "The calculated redeem script doesn't match the redeem script in the order") } } @@ -923,14 +1035,18 @@ func (n *OpenBazaarNode) ValidateDisputeResolution(contract *pb.RicardianContrac if contract.DisputeResolution.Payout == nil || len(contract.DisputeResolution.Payout.Sigs) == 0 { return errors.New("DisputeResolution contains invalid payout") } - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } if contract.VendorListings[0].VendorID.PeerID == n.IpfsNode.Identity.Pretty() && contract.DisputeResolution.Payout.VendorOutput != nil { return n.verifyPaymentDestinationIsInWallet(contract.DisputeResolution.Payout.VendorOutput, wal) - } else if contract.BuyerOrder.BuyerID.PeerID == n.IpfsNode.Identity.Pretty() && contract.DisputeResolution.Payout.BuyerOutput != nil { + } else if order.BuyerID.PeerID == n.IpfsNode.Identity.Pretty() && contract.DisputeResolution.Payout.BuyerOutput != nil { return n.verifyPaymentDestinationIsInWallet(contract.DisputeResolution.Payout.BuyerOutput, wal) } return nil @@ -989,17 +1105,40 @@ func (n *OpenBazaarNode) verifySignatureOnDisputeResolution(contract *pb.Ricardi // ReleaseFunds - release funds func (n *OpenBazaarNode) ReleaseFunds(contract *pb.RicardianContract, records []*wallet.TransactionRecord) error { + orderID, err := n.CalcOrderID(contract.BuyerOrder) + if err != nil { + return err + } + + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + + currencyDef, err := n.LookupCurrency(order.Payment.AmountCurrency.Code) + if err != nil { + return fmt.Errorf("unknown currency code (%s) in contract (%s) buyer order", order.Payment.AmountCurrency.Code, orderID) + } + // Create inputs - var inputs []wallet.TransactionInput - for _, o := range contract.DisputeResolution.Payout.Inputs { - decodedHash, err := hex.DecodeString(o.Hash) + var ( + inputs []wallet.TransactionInput + resolution = repo.ToV5DisputeResolution(contract.DisputeResolution) + ) + for _, o := range resolution.Payout.Inputs { + decodedHash, err := hex.DecodeString(util.NormalizeAddress(o.Hash)) if err != nil { return err } + n, ok := new(big.Int).SetString(o.BigValue, 10) + if !ok { + return errors.New("invalid payout input") + } input := wallet.TransactionInput{ OutpointHash: decodedHash, OutpointIndex: o.Index, - Value: int64(o.Value), + Value: *n, + OrderID: orderID, } inputs = append(inputs, input) } @@ -1007,54 +1146,68 @@ func (n *OpenBazaarNode) ReleaseFunds(contract *pb.RicardianContract, records [] if len(inputs) == 0 { return errors.New("transaction has no inputs") } - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } // Create outputs var outputs []wallet.TransactionOutput - if contract.DisputeResolution.Payout.BuyerOutput != nil { - addr, err := pb.DisputeResolutionPayoutOutputToAddress(wal, contract.DisputeResolution.Payout.BuyerOutput) + if resolution.Payout.BuyerOutput != nil { + addr, err := pb.DisputeResolutionPayoutOutputToAddress(wal, resolution.Payout.BuyerOutput) if err != nil { return err } + n, ok := new(big.Int).SetString(resolution.Payout.BuyerOutput.BigAmount, 10) + if !ok { + return errors.New("invalid payout amount") + } output := wallet.TransactionOutput{ Address: addr, - Value: int64(contract.DisputeResolution.Payout.BuyerOutput.Amount), + Value: *n, + OrderID: orderID, } outputs = append(outputs, output) } - if contract.DisputeResolution.Payout.VendorOutput != nil { - addr, err := pb.DisputeResolutionPayoutOutputToAddress(wal, contract.DisputeResolution.Payout.VendorOutput) + if resolution.Payout.VendorOutput != nil { + addr, err := pb.DisputeResolutionPayoutOutputToAddress(wal, resolution.Payout.VendorOutput) if err != nil { return err } + n, ok := new(big.Int).SetString(resolution.Payout.VendorOutput.BigAmount, 10) + if !ok { + return errors.New("invalid payout amount") + } output := wallet.TransactionOutput{ Address: addr, - Value: int64(contract.DisputeResolution.Payout.VendorOutput.Amount), + Value: *n, + OrderID: orderID, } outputs = append(outputs, output) } - if contract.DisputeResolution.Payout.ModeratorOutput != nil { - addr, err := pb.DisputeResolutionPayoutOutputToAddress(wal, contract.DisputeResolution.Payout.ModeratorOutput) + if resolution.Payout.ModeratorOutput != nil { + addr, err := pb.DisputeResolutionPayoutOutputToAddress(wal, resolution.Payout.ModeratorOutput) if err != nil { return err } + n, ok := new(big.Int).SetString(resolution.Payout.ModeratorOutput.BigAmount, 10) + if !ok { + return errors.New("invalid payout amount") + } output := wallet.TransactionOutput{ Address: addr, - Value: int64(contract.DisputeResolution.Payout.ModeratorOutput.Amount), + Value: *n, + OrderID: orderID, } outputs = append(outputs, output) } // Create signing key - chaincodeBytes, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincodeBytes, err := hex.DecodeString(order.Payment.Chaincode) if err != nil { return err } - mPrivKey := n.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := n.MasterPrivateKey.ECPrivKey() if err != nil { return err } @@ -1064,17 +1217,18 @@ func (n *OpenBazaarNode) ReleaseFunds(contract *pb.RicardianContract, records [] } // Create signatures - redeemScriptBytes, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScriptBytes, err := hex.DecodeString(order.Payment.RedeemScript) if err != nil { return err } - mySigs, err := wal.CreateMultisigSignature(inputs, outputs, signingKey, redeemScriptBytes, 0) + + mySigs, err := wal.CreateMultisigSignature(inputs, outputs, signingKey, redeemScriptBytes, *big.NewInt(0)) if err != nil { return err } var moderatorSigs []wallet.Signature - for _, sig := range contract.DisputeResolution.Payout.Sigs { + for _, sig := range resolution.Payout.Sigs { s := wallet.Signature{ Signature: sig.Signature, InputIndex: sig.InputIndex, @@ -1092,14 +1246,18 @@ func (n *OpenBazaarNode) ReleaseFunds(contract *pb.RicardianContract, records [] accept.ClosedBy = n.IpfsNode.Identity.Pretty() contract.DisputeAcceptance = accept - orderID, err := n.CalcOrderID(contract.BuyerOrder) + peerID := order.BuyerID.PeerID + + // Build, sign, and broadcast transaction + txnID, err := wal.Multisign(inputs, outputs, mySigs, moderatorSigs, redeemScriptBytes, *big.NewInt(0), true) if err != nil { return err } // Update database - if n.IpfsNode.Identity.Pretty() == contract.BuyerOrder.BuyerID.PeerID { + if n.IpfsNode.Identity.Pretty() == order.BuyerID.PeerID { err = n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_DECIDED, true) + peerID = contract.VendorListings[0].VendorID.PeerID } else { err = n.Datastore.Sales().Put(orderID, *contract, pb.OrderState_DECIDED, true) } @@ -1107,10 +1265,15 @@ func (n *OpenBazaarNode) ReleaseFunds(contract *pb.RicardianContract, records [] log.Errorf("ReleaseFunds error updating database: %s", err.Error()) } - // Build, sign, and broadcast transaction - _, err = wal.Multisign(inputs, outputs, mySigs, moderatorSigs, redeemScriptBytes, 0, true) + err = n.SendOrderPayment(&SpendResponse{ + Txid: util.NormalizeAddress(hexutil.Encode(txnID)), + Currency: ¤cyDef, + OrderID: orderID, + PeerID: peerID, + ConsumedInput: true, + }) if err != nil { - return err + log.Errorf("error sending order payment: %v", err) } return nil diff --git a/core/errors.go b/core/errors.go index 329aac4861..2da429fb41 100644 --- a/core/errors.go +++ b/core/errors.go @@ -1,22 +1,22 @@ package core import ( + "context" "encoding/json" "errors" - "fmt" + "math/big" "strconv" + + peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + + "github.com/golang/protobuf/ptypes" + "github.com/phoreproject/pm-go/pb" ) var ( // ErrPurchaseUnknownListing - unavailable listing err ErrPurchaseUnknownListing = errors.New("order contains a hash of a listing that is not currently for sale") - // ErrListingDoesNotExist - non-existent listing err - ErrListingDoesNotExist = errors.New("listing doesn't exist") - // ErrListingAlreadyExists - duplicate listing err - ErrListingAlreadyExists = errors.New("listing already exists") - // ErrListingCoinDivisibilityIncorrect - coin divisibility err - ErrListingCoinDivisibilityIncorrect = errors.New("incorrect coinDivisibility") // ErrPriceCalculationRequiresExchangeRates - exchange rates dependency err ErrPriceCalculationRequiresExchangeRates = errors.New("can't calculate price with exchange rates disabled") @@ -27,9 +27,6 @@ var ( // ErrCryptocurrencyPurchasePaymentAddressTooLong - invalid payment address ErrCryptocurrencyPurchasePaymentAddressTooLong = errors.New("paymentAddress required is too long") - // ErrCryptocurrencySkuQuantityInvalid - invalid sku qty err - ErrCryptocurrencySkuQuantityInvalid = errors.New("cryptocurrency listing quantity must be a non-negative integer") - // ErrFulfillIncorrectDeliveryType - incorrect delivery type err ErrFulfillIncorrectDeliveryType = errors.New("incorrect delivery type for order") // ErrFulfillCryptocurrencyTXIDNotFound - missing txn id err @@ -46,6 +43,9 @@ var ( // ErrInsufficientFunds is returned when the wallet is unable to send the amount specified due to the balance being too low ErrInsufficientFunds = errors.New("ERROR_INSUFFICIENT_FUNDS") + // ErrInvalidAmount is returned when the string representation of the amount to spend is not an integer + ErrInvalidAmount = errors.New("Spend amount is invalid or empty") + // ErrSpendAmountIsDust is returned when the requested amount to spend out of the wallet would be considered "dust" by the network. This means the value is too low for the network to bother sending the amount and has a high likelihood of not being accepted or being outright rejected. ErrSpendAmountIsDust = errors.New("ERROR_DUST_AMOUNT") @@ -68,17 +68,17 @@ func (err CodedError) Error() string { // purchasing too many of an item type ErrOutOfInventory struct { CodedError - RemainingInventory int64 `json:"remainingInventory"` + RemainingInventory string `json:"remainingInventory"` } // NewErrOutOfInventory - return out of inventory err with available inventory -func NewErrOutOfInventory(inventoryRemaining int64) ErrOutOfInventory { +func NewErrOutOfInventory(inventoryRemaining *big.Int) ErrOutOfInventory { return ErrOutOfInventory{ CodedError: CodedError{ Reason: "not enough inventory", Code: "ERR_INSUFFICIENT_INVENTORY", }, - RemainingInventory: inventoryRemaining, + RemainingInventory: inventoryRemaining.String(), } } @@ -87,37 +87,34 @@ func (err ErrOutOfInventory) Error() string { return string(jsonBytes) } -// ErrPriceModifierOutOfRange - customize limits for price modifier -type ErrPriceModifierOutOfRange struct { - Min float64 - Max float64 -} - -func (e ErrPriceModifierOutOfRange) Error() string { - return fmt.Sprintf("priceModifier out of range: [%.2f, %.2f]", e.Min, e.Max) -} - -// ErrCryptocurrencyListingIllegalField - invalid field err -type ErrCryptocurrencyListingIllegalField string - -func (e ErrCryptocurrencyListingIllegalField) Error() string { - return illegalFieldString("cryptocurrency listing", string(e)) -} - -// ErrCryptocurrencyPurchaseIllegalField - invalid purchase field err -type ErrCryptocurrencyPurchaseIllegalField string - -func (e ErrCryptocurrencyPurchaseIllegalField) Error() string { - return illegalFieldString("cryptocurrency purchase", string(e)) -} - -// ErrMarketPriceListingIllegalField - invalid listing field err -type ErrMarketPriceListingIllegalField string - -func (e ErrMarketPriceListingIllegalField) Error() string { - return illegalFieldString("market price listing", string(e)) -} +// SendProcessingError will encapsulate the failing state in a message to be sent back to pid +// When pid receives the OrderProcessingError, it will analyze the contract and send the messages +// that this node is missing to resynchronize the order +func (n *OpenBazaarNode) SendProcessingError(pid, oid string, attemptedMessage pb.Message_MessageType, latestContract *pb.RicardianContract) error { + log.Debugf("sending ORDER_PROCESSING_ERROR to peer (%s)", pid) + var ( + procErrMsg = &pb.OrderProcessingFailure{ + OrderID: oid, + AttemptedMessageType: attemptedMessage, + Contract: latestContract, + } + procErrBytes, mErr = ptypes.MarshalAny(procErrMsg) + errMsg = &pb.Message{ + MessageType: pb.Message_ORDER_PROCESSING_FAILURE, + Payload: procErrBytes, + } + p, pErr = peer.IDB58Decode(pid) + ) + if mErr != nil { + log.Errorf("failed marshaling OrderProcessingFailure message for order (%s): %s", oid, mErr) + return mErr + } + if pErr != nil { + log.Errorf("failed decoding peer ID (%s): %s", pid, pErr) + return pErr + } + ctx, cancel := context.WithTimeout(context.Background(), n.OfflineMessageFailoverTimeout) + defer cancel() -func illegalFieldString(objectType string, field string) string { - return fmt.Sprintf("Illegal %s field: %s", objectType, field) + return n.Service.SendMessage(ctx, p, errMsg) } diff --git a/core/fulfillment.go b/core/fulfillment.go index 2b00d90f8b..7f16422f91 100644 --- a/core/fulfillment.go +++ b/core/fulfillment.go @@ -4,15 +4,18 @@ import ( "bytes" "encoding/hex" "errors" + "github.com/phoreproject/pm-go/repo" + "math/big" + "strings" + "time" crypto "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" - "time" - "github.com/OpenBazaar/wallet-interface" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/pb" + + "github.com/phoreproject/pm-go/pb" ) var ( @@ -30,22 +33,23 @@ func (n *OpenBazaarNode) FulfillOrder(fulfillment *pb.OrderFulfillment, contract rc := new(pb.RicardianContract) if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED { payout := new(pb.OrderFulfillment_Payout) - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.AmountCurrency.Code) if err != nil { return err } currentAddress := wal.CurrentAddress(wallet.EXTERNAL) - payout.PayoutAddress = currentAddress.EncodeAddress() - payout.PayoutFeePerByte = wal.GetFeePerByte(wallet.NORMAL) + payout.PayoutAddress = currentAddress.String() + f := wal.GetFeePerByte(wallet.NORMAL) + payout.BigPayoutFeePerByte = f.String() var ins []wallet.TransactionInput - var outValue int64 + outValue := big.NewInt(0) for _, r := range records { - if !r.Spent && r.Value > 0 { - outpointHash, err := hex.DecodeString(r.Txid) + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { + outpointHash, err := hex.DecodeString(strings.TrimPrefix(r.Txid, "0x")) if err != nil { return err } - outValue += r.Value + outValue.Add(outValue, &r.Value) in := wallet.TransactionInput{OutpointIndex: r.Index, OutpointHash: outpointHash, Value: r.Value} ins = append(ins, in) } @@ -53,14 +57,13 @@ func (n *OpenBazaarNode) FulfillOrder(fulfillment *pb.OrderFulfillment, contract var output = wallet.TransactionOutput{ Address: currentAddress, - Value: outValue, + Value: *outValue, } chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) if err != nil { return err } - mPrivKey := n.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := n.MasterPrivateKey.ECPrivKey() if err != nil { return err } @@ -72,8 +75,11 @@ func (n *OpenBazaarNode) FulfillOrder(fulfillment *pb.OrderFulfillment, contract if err != nil { return err } - - signatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, vendorKey, redeemScript, payout.PayoutFeePerByte) + fee, ok := new(big.Int).SetString(payout.BigPayoutFeePerByte, 10) + if !ok { + return errors.New("invalid payout fee value") + } + signatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, vendorKey, redeemScript, *fee) if err != nil { return err } @@ -139,9 +145,7 @@ func (n *OpenBazaarNode) FulfillOrder(fulfillment *pb.OrderFulfillment, contract fulfillment.RatingSignature = rs - var fulfils []*pb.OrderFulfillment - - rc.VendorOrderFulfillment = append(fulfils, fulfillment) + rc.VendorOrderFulfillment = []*pb.OrderFulfillment{fulfillment} rc, err = n.SignOrderFulfillment(rc) if err != nil { return err @@ -161,9 +165,15 @@ func (n *OpenBazaarNode) FulfillOrder(fulfillment *pb.OrderFulfillment, contract } } if n.IsFulfilled(rc) { - n.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_FULFILLED, false) + err = n.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_FULFILLED, false) + if err != nil { + log.Error(err) + } } else { - n.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_PARTIALLY_FULFILLED, false) + err = n.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_PARTIALLY_FULFILLED, false) + if err != nil { + log.Error(err) + } } return nil } @@ -233,8 +243,13 @@ func (n *OpenBazaarNode) ValidateOrderFulfillment(fulfillment *pb.OrderFulfillme return errors.New("failed to verify signature on rating keys") } - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED { - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return err + } + + if order.Payment.Method == pb.Order_Payment_MODERATED { + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } @@ -264,7 +279,7 @@ func (n *OpenBazaarNode) ValidateOrderFulfillment(fulfillment *pb.OrderFulfillme for _, fulfil := range contract.VendorOrderFulfillment { vendorSignedKeys = append(vendorSignedKeys, fulfil.RatingSignature.Metadata.RatingKey) } - for _, bk := range contract.BuyerOrder.RatingKeys { + for _, bk := range order.RatingKeys { if !keyExists(bk, vendorSignedKeys) { return errors.New("vendor failed to send rating signatures covering all ratingKeys") } diff --git a/core/images.go b/core/images.go index 592c36d518..3be6215187 100644 --- a/core/images.go +++ b/core/images.go @@ -3,14 +3,13 @@ package core import ( "bytes" "encoding/base64" - "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" - "image" // load gif + "fmt" + "image" _ "image/gif" - "image/jpeg" // load png + jpeg "image/jpeg" _ "image/png" "io" "io/ioutil" - "net" "net/http" netUrl "net/url" "os" @@ -19,10 +18,12 @@ import ( "time" ipath "gx/ipfs/QmQAgv6Gaoe2tQpcabqwKXKChp2MZ7i3UXv9DqTTaxCaTR/go-path" + cid "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" - "github.com/nfnt/resize" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/disintegration/imaging" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) // SetAvatarImages - set avatar image from the base64 encoded image string @@ -71,27 +72,27 @@ func (n *OpenBazaarNode) SetProductImages(base64ImageData, filename string) (*pb return n.resizeImage(base64ImageData, filename, 120, 120) } -func (n *OpenBazaarNode) resizeImage(base64ImageData, filename string, baseWidth, baseHeight uint) (*pb.Profile_Image, error) { - img, imgCfg, err := decodeImageData(base64ImageData) +func (n *OpenBazaarNode) resizeImage(base64ImageData, filename string, baseWidth, baseHeight int) (*pb.Profile_Image, error) { + img, err := decodeImageData(base64ImageData) if err != nil { return nil, err } imgPath := path.Join(n.RepoPath, "root", "images") - t, err := n.addResizedImage(img, imgCfg, 1*baseWidth, 1*baseHeight, path.Join(imgPath, "tiny", filename)) + t, err := n.addResizedImage(img, 1*baseWidth, 1*baseHeight, path.Join(imgPath, "tiny", filename)) if err != nil { return nil, err } - s, err := n.addResizedImage(img, imgCfg, 2*baseWidth, 2*baseHeight, path.Join(imgPath, "small", filename)) + s, err := n.addResizedImage(img, 2*baseWidth, 2*baseHeight, path.Join(imgPath, "small", filename)) if err != nil { return nil, err } - m, err := n.addResizedImage(img, imgCfg, 4*baseWidth, 4*baseHeight, path.Join(imgPath, "medium", filename)) + m, err := n.addResizedImage(img, 4*baseWidth, 4*baseHeight, path.Join(imgPath, "medium", filename)) if err != nil { return nil, err } - l, err := n.addResizedImage(img, imgCfg, 8*baseWidth, 8*baseHeight, path.Join(imgPath, "large", filename)) + l, err := n.addResizedImage(img, 8*baseWidth, 8*baseHeight, path.Join(imgPath, "large", filename)) if err != nil { return nil, err } @@ -108,32 +109,30 @@ func (n *OpenBazaarNode) addImage(img image.Image, imgPath string) (string, erro if err != nil { return "", err } - jpeg.Encode(out, img, nil) + err = jpeg.Encode(out, img, nil) + if err != nil { + return "", err + } out.Close() return ipfs.AddFile(n.IpfsNode, imgPath) } -func (n *OpenBazaarNode) addResizedImage(img image.Image, imgCfg *image.Config, w, h uint, imgPath string) (string, error) { - width, height := getImageAttributes(w, h, uint(imgCfg.Width), uint(imgCfg.Height)) - newImg := resize.Resize(width, height, img, resize.Lanczos3) +func (n *OpenBazaarNode) addResizedImage(img image.Image, w, h int, imgPath string) (string, error) { + width, height := getImageAttributes(w, h, img.Bounds().Max.X, img.Bounds().Max.Y) + newImg := imaging.Resize(img, width, height, imaging.Lanczos) return n.addImage(newImg, imgPath) } -func decodeImageData(base64ImageData string) (image.Image, *image.Config, error) { +func decodeImageData(base64ImageData string) (image.Image, error) { reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData)) - img, _, err := image.Decode(reader) + img, err := imaging.Decode(reader, imaging.AutoOrientation(true)) if err != nil { - return nil, nil, err - } - reader = base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData)) - imgCfg, _, err := image.DecodeConfig(reader) - if err != nil { - return nil, nil, err + return nil, err } - return img, &imgCfg, err + return img, err } -func getImageAttributes(targetWidth, targetHeight, imgWidth, imgHeight uint) (width, height uint) { +func getImageAttributes(targetWidth, targetHeight, imgWidth, imgHeight int) (width, height int) { targetRatio := float32(targetWidth) / float32(targetHeight) imageRatio := float32(imgWidth) / float32(imgHeight) var h, w float32 @@ -144,7 +143,7 @@ func getImageAttributes(targetWidth, targetHeight, imgWidth, imgHeight uint) (wi w = float32(targetWidth) h = float32(targetWidth) * (float32(imgHeight) / float32(imgWidth)) } - return uint(w), uint(h) + return int(w), int(h) } // FetchAvatar - fetch image avatar from ipfs @@ -169,12 +168,14 @@ func (n *OpenBazaarNode) FetchImage(peerID string, imageType string, size string // GetBase64Image - fetch the image and return it as base64 encoded string func (n *OpenBazaarNode) GetBase64Image(url string) (base64ImageData, filename string, err error) { - dial := net.Dial + var client *http.Client if n.TorDialer != nil { - dial = n.TorDialer.Dial + tbTransport := &http.Transport{Dial: n.TorDialer.Dial} + client = &http.Client{Transport: tbTransport, Timeout: time.Second * 30} + } else { + client = &http.Client{Timeout: time.Second * 30} } - tbTransport := &http.Transport{Dial: dial} - client := &http.Client{Transport: tbTransport, Timeout: time.Second * 30} + resp, err := client.Get(url) if err != nil { return "", "", err @@ -194,49 +195,41 @@ func (n *OpenBazaarNode) GetBase64Image(url string) (base64ImageData, filename s // maybeMigrateImageHashes will iterate over the listing's images and migrate them // to a v0 cid if they are not already v0. -func (n *OpenBazaarNode) maybeMigrateImageHashes(listing *pb.Listing) error { - if listing.Item == nil || len(listing.Item.Images) == 0 { - return nil - } - - maybeMigrateImage := func(imgHash, size, filename string) (string, error) { - id, err := cid.Decode(imgHash) - if err != nil { - return "", err - } - if id.Version() > 0 { - newHash, err := ipfs.AddFile(n.IpfsNode, path.Join(n.RepoPath, "root", "images", size, filename)) - if err != nil { - return "", err +func (n *OpenBazaarNode) maybeMigrateImageHashes(listing *repo.Listing) error { + for _, i := range listing.GetImages() { + var updateHash = func(size, currentHash string, update func(string) error) error { + var cidVer = uint64(1) // if version is unknown, always attempt to update hash + if id, err := cid.Decode(currentHash); err == nil { + cidVer = id.Version() + } + if cidVer > 0 { + var imgPath = path.Join(n.RepoPath, "root", "images", size, i.GetFilename()) + iHash, err := ipfs.AddFile(n.IpfsNode, imgPath) + if err != nil { + return fmt.Errorf("ipfs add (%s): %s", imgPath, err.Error()) + } + if err := update(iHash); err != nil { + return fmt.Errorf("set %s img hash: %s", size, err.Error()) + } } - return newHash, nil + return nil } - return imgHash, nil - } - var err error - for i, image := range listing.Item.Images { - image.Large, err = maybeMigrateImage(image.Large, "large", image.Filename) - if err != nil { + if err := updateHash("tiny", i.GetTiny(), i.SetTiny); err != nil { return err } - image.Medium, err = maybeMigrateImage(image.Medium, "medium", image.Filename) - if err != nil { + if err := updateHash("small", i.GetSmall(), i.SetSmall); err != nil { return err } - image.Small, err = maybeMigrateImage(image.Small, "small", image.Filename) - if err != nil { + if err := updateHash("medium", i.GetMedium(), i.SetMedium); err != nil { return err } - image.Tiny, err = maybeMigrateImage(image.Tiny, "tiny", image.Filename) - if err != nil { + if err := updateHash("large", i.GetLarge(), i.SetLarge); err != nil { return err } - image.Original, err = maybeMigrateImage(image.Original, "original", image.Filename) - if err != nil { + if err := updateHash("original", i.GetOriginal(), i.SetOriginal); err != nil { return err } - listing.Item.Images[i] = image } return nil } diff --git a/core/images_test.go b/core/images_test.go index 1e7127879c..e6d92c456a 100644 --- a/core/images_test.go +++ b/core/images_test.go @@ -8,21 +8,20 @@ import ( "os" "testing" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/schema" coremock "github.com/ipfs/go-ipfs/core/mock" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" ) func TestImageFormats(t *testing.T) { for _, image := range []string{jpgImageB64, gifImageB64, pngImageB64} { - _, cfg, err := decodeImageData(image) + img, err := decodeImageData(image) if err != nil { t.Error(err) } - jpgImageB64 = "jfkdjfkd" - if cfg.Width != 50 || cfg.Height != 50 { + if img.Bounds().Max.X != 50 || img.Bounds().Max.Y != 50 { t.Error("Incorrect sizes decoded") } } @@ -76,7 +75,7 @@ func TestOpenBazaarNode_maybeMigrateImageHashes(t *testing.T) { } } - checkImages := func(image *pb.Listing_Item_Image) { + checkImages := func(image *repo.ListingImage) { checkImage := func(imageHash, size string) { id, err := cid.Decode(imageHash) if err != nil { @@ -86,28 +85,33 @@ func TestOpenBazaarNode_maybeMigrateImageHashes(t *testing.T) { t.Errorf("%s image failed to migrate to v0", size) } } - checkImage(image.Large, "large") - checkImage(image.Medium, "medium") - checkImage(image.Small, "small") - checkImage(image.Tiny, "tiny") - checkImage(image.Original, "original") + checkImage(image.GetLarge(), "large") + checkImage(image.GetMedium(), "medium") + checkImage(image.GetSmall(), "small") + checkImage(image.GetTiny(), "tiny") + checkImage(image.GetOriginal(), "original") + } + + rl, err := repo.NewListingFromProtobuf(listing) + if err != nil { + t.Fatal(err) } // Test converting v1 to v0 - if err := node.maybeMigrateImageHashes(listing); err != nil { + if err := node.maybeMigrateImageHashes(rl); err != nil { t.Fatal(err) } - for _, image := range listing.Item.Images { + for _, image := range rl.GetImages() { checkImages(image) } // Test v0 remaining at v0 - if err := node.maybeMigrateImageHashes(listing); err != nil { + if err := node.maybeMigrateImageHashes(rl); err != nil { t.Fatal(err) } - for _, image := range listing.Item.Images { + for _, image := range rl.GetImages() { checkImages(image) } } diff --git a/core/import.go b/core/import.go deleted file mode 100644 index 4252aa741a..0000000000 --- a/core/import.go +++ /dev/null @@ -1,680 +0,0 @@ -package core - -import ( - "encoding/csv" - "encoding/json" - "errors" - "fmt" - "io" - "net/url" - "os" - "path" - "strconv" - "strings" - "sync" - "time" - - "github.com/OpenBazaar/jsonpb" - "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/pb" -) - -const bufferSize = 5 - -// ImportListings - upload/read listings -func (n *OpenBazaarNode) ImportListings(r io.ReadCloser) error { - reader := csv.NewReader(r) - columns, err := reader.Read() - if err != nil { - return err - } - fields := make(map[string]int) - for i, c := range columns { - fields[strings.ToLower(c)] = i - } - - done := make(chan struct{}) - buf := make(chan struct{}, bufferSize) - errChan := make(chan error, bufferSize) - - countLock := new(sync.Mutex) - count := 0 - - var ld []ListingData - indexLock := new(sync.Mutex) - wg := new(sync.WaitGroup) - -listingLoop: - for { - select { - case err := <-errChan: - return err - case <-done: - break listingLoop - default: - } - buf <- struct{}{} - go func() { - defer func() { - <-buf - }() - - countLock.Lock() - i := count - record, err := reader.Read() - count++ - countLock.Unlock() - if err == io.EOF { - done <- struct{}{} - return - } - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - - wg.Add(1) - - listing := new(pb.Listing) - metadata := new(pb.Listing_Metadata) - item := new(pb.Listing_Item) - var shipping []*pb.Listing_ShippingOption - listing.Metadata = metadata - listing.Item = item - listing.ShippingOptions = shipping - listing.Testnet = n.TestnetEnable - - pos, ok := fields["contract_type"] - if ok { - e, ok := pb.Listing_Metadata_ContractType_value[strings.ToUpper(record[pos])] - if ok { - listing.Metadata.ContractType = pb.Listing_Metadata_ContractType(e) - } - } - pos, ok = fields["format"] - if ok { - e, ok := pb.Listing_Metadata_Format_value[strings.ToUpper(record[pos])] - if ok { - listing.Metadata.Format = pb.Listing_Metadata_Format(e) - } - } - pos, ok = fields["expiry"] - if ok { - t, err := time.Parse(time.RFC3339, record[pos]) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - ts, err := ptypes.TimestampProto(t) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - listing.Metadata.Expiry = ts - } else { - t, err := time.Parse(time.RFC3339, "2037-12-31T05:00:00.000Z") - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - ts, err := ptypes.TimestampProto(t) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - listing.Metadata.Expiry = ts - } - pos, ok = fields["pricing_currency"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "pricing_currency is a mandatory field") - return - } - listing.Metadata.PricingCurrency = strings.ToUpper(record[pos]) - pos, ok = fields["language"] - if ok { - listing.Metadata.Language = record[pos] - } - pos, ok = fields["title"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "title is a mandatory field") - return - } - listing.Item.Title = record[pos] - - listing.Slug, err = n.GenerateSlug(listing.Item.Title) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - - pos, ok = fields["description"] - if ok { - listing.Item.Description = record[pos] - } - pos, ok = fields["processing_time"] - if ok { - listing.Item.ProcessingTime = record[pos] - } - pos, ok = fields["price"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - listing.Item.Price = uint64(f * 100) - } else { - listing.Item.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - pos, ok = fields["nsfw"] - if ok { - listing.Item.Nsfw, err = strconv.ParseBool(record[pos]) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - pos, ok = fields["tags"] - if ok { - listing.Item.Tags = strings.Split(record[pos], ",") - } - pos, ok = fields["image_urls"] - if ok { - listing.Item.Images = []*pb.Listing_Item_Image{} - imageUrls := strings.Split(record[pos], ",") - var l sync.Mutex - var wg sync.WaitGroup - for x, img := range imageUrls { - wg.Add(1) - go func(x int, img string) { - defer wg.Done() - var b64 string - var filename string - testURL, err := url.Parse(img) - if err == nil && (testURL.Scheme == "http" || testURL.Scheme == "https") { - b64, filename, err = n.GetBase64Image(img) - if err != nil { - errChan <- fmt.Errorf("error in record %d: image %d failed to download", i, x) - return - } - } else { - filename = listing.Slug + "_" + strconv.Itoa(x) - b64 = img - } - images, err := n.SetProductImages(b64, filename) - if err != nil { - errChan <- fmt.Errorf("error in record %d: image %d invalid", i, x) - return - } - imgpb := &pb.Listing_Item_Image{ - Filename: filename, - Tiny: images.Tiny, - Small: images.Small, - Medium: images.Medium, - Large: images.Large, - Original: images.Original, - } - l.Lock() - listing.Item.Images = append(listing.Item.Images, imgpb) - l.Unlock() - }(x, img) - } - wg.Wait() - } - pos, ok = fields["categories"] - if ok { - - cats := strings.Split(record[pos], ",") - for _, cat := range cats { - if cat != "" { - listing.Item.Categories = append(listing.Item.Categories, cat) - } - } - } - pos, ok = fields["condition"] - if ok { - listing.Item.Condition = record[pos] - } - quantityPos, quantityOK := fields["quantity"] - skuPos, skuOK := fields["sku_number"] - listing.Item.Skus = []*pb.Listing_Item_Sku{} - if quantityOK || skuOK { - sku := new(pb.Listing_Item_Sku) - sku.ProductID = record[skuPos] - if quantityOK { - quantity, err := strconv.ParseInt(record[quantityPos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - sku.Quantity = quantity - } - listing.Item.Skus = append(listing.Item.Skus, sku) - } - listing.ShippingOptions = []*pb.Listing_ShippingOption{} - pos, ok = fields["shipping_option1_name"] - if ok && record[pos] != "" { - so := new(pb.Listing_ShippingOption) - so.Name = record[pos] - so.Type = pb.Listing_ShippingOption_FIXED_PRICE - so.Regions = []pb.CountryCode{} - so.Services = []*pb.Listing_ShippingOption_Service{} - pos, ok = fields["shipping_option1_countries"] - if ok { - countries := strings.Split(record[pos], ",") - for _, c := range countries { - e, ok := pb.CountryCode_value[strings.ToUpper(c)] - if ok { - so.Regions = append(so.Regions, pb.CountryCode(e)) - } - } - } else { - so.Regions = append(so.Regions, pb.CountryCode_ALL) - } - pos, ok = fields["shipping_option1_service1_name"] - if ok && record[pos] != "" { - service := new(pb.Listing_ShippingOption_Service) - service.Name = record[pos] - pos, ok = fields["shipping_option1_service1_estimated_delivery"] - if ok { - service.EstimatedDelivery = record[pos] - } - pos, ok = fields["shipping_option1_service1_estimated_price"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "shipping_option1_service1_estimated_price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - service.Price = uint64(f * 100) - } else { - service.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - so.Services = append(so.Services, service) - } - pos, ok = fields["shipping_option1_service2_name"] - if ok && record[pos] != "" { - service := new(pb.Listing_ShippingOption_Service) - service.Name = record[pos] - pos, ok = fields["shipping_option1_service2_estimated_delivery"] - if ok { - service.EstimatedDelivery = record[pos] - } - pos, ok = fields["shipping_option1_service2_estimated_price"] - if !ok { - errChan <- errors.New("shipping_option1_service2_estimated_price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - service.Price = uint64(f * 100) - } else { - service.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - so.Services = append(so.Services, service) - } - pos, ok = fields["shipping_option1_service3_name"] - if ok && record[pos] != "" { - service := new(pb.Listing_ShippingOption_Service) - service.Name = record[pos] - pos, ok = fields["shipping_option1_service3_estimated_delivery"] - if ok { - service.EstimatedDelivery = record[pos] - } - pos, ok = fields["shipping_option1_service3_estimated_price"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "shipping_option1_service3_estimated_price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - service.Price = uint64(f * 100) - } else { - service.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - so.Services = append(so.Services, service) - } - listing.ShippingOptions = append(listing.ShippingOptions, so) - } - pos, ok = fields["shipping_option2_name"] - if ok && record[pos] != "" { - so := new(pb.Listing_ShippingOption) - so.Name = record[pos] - so.Type = pb.Listing_ShippingOption_FIXED_PRICE - so.Regions = []pb.CountryCode{} - so.Services = []*pb.Listing_ShippingOption_Service{} - pos, ok = fields["shipping_option2_countries"] - if ok { - countries := strings.Split(record[pos], ",") - for _, c := range countries { - e, ok := pb.CountryCode_value[strings.ToUpper(c)] - if ok { - so.Regions = append(so.Regions, pb.CountryCode(e)) - } - } - } else { - so.Regions = append(so.Regions, pb.CountryCode_ALL) - } - pos, ok = fields["shipping_option2_service1_name"] - if ok && record[pos] != "" { - service := new(pb.Listing_ShippingOption_Service) - service.Name = record[pos] - pos, ok = fields["shipping_option2_service1_estimated_delivery"] - if ok { - service.EstimatedDelivery = record[pos] - } - pos, ok = fields["shipping_option2_service1_estimated_price"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "shipping_option2_service1_estimated_price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - service.Price = uint64(f * 100) - } else { - service.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - so.Services = append(so.Services, service) - } - pos, ok = fields["shipping_option2_service2_name"] - if ok && record[pos] != "" { - service := new(pb.Listing_ShippingOption_Service) - service.Name = record[pos] - pos, ok = fields["shipping_option2_service2_estimated_delivery"] - if ok { - service.EstimatedDelivery = record[pos] - } - pos, ok = fields["shipping_option2_service2_estimated_price"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "shipping_option2_service2_estimated_price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - service.Price = uint64(f * 100) - } else { - service.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - so.Services = append(so.Services, service) - } - pos, ok = fields["shipping_option2_service3_name"] - if ok && record[pos] != "" { - service := new(pb.Listing_ShippingOption_Service) - service.Name = record[pos] - pos, ok = fields["shipping_option2_service3_estimated_delivery"] - if ok { - service.EstimatedDelivery = record[pos] - } - pos, ok = fields["shipping_option2_service3_estimated_price"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "shipping_option2_service3_estimated_price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - service.Price = uint64(f * 100) - } else { - service.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - so.Services = append(so.Services, service) - } - listing.ShippingOptions = append(listing.ShippingOptions, so) - } - pos, ok = fields["shipping_option3_name"] - if ok && record[pos] != "" { - so := new(pb.Listing_ShippingOption) - so.Name = record[pos] - so.Type = pb.Listing_ShippingOption_FIXED_PRICE - so.Regions = []pb.CountryCode{} - so.Services = []*pb.Listing_ShippingOption_Service{} - pos, ok = fields["shipping_option3_countries"] - if ok { - countries := strings.Split(record[pos], ",") - for _, c := range countries { - e, ok := pb.CountryCode_value[strings.ToUpper(c)] - if ok { - so.Regions = append(so.Regions, pb.CountryCode(e)) - } - } - } else { - so.Regions = append(so.Regions, pb.CountryCode_ALL) - } - pos, ok = fields["shipping_option3_service1_name"] - if ok && record[pos] != "" { - service := new(pb.Listing_ShippingOption_Service) - service.Name = record[pos] - pos, ok = fields["shipping_option3_service1_estimated_delivery"] - if ok { - service.EstimatedDelivery = record[pos] - } - pos, ok = fields["shipping_option3_service1_estimated_price"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "shipping_option3_service1_estimated_price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - service.Price = uint64(f * 100) - } else { - service.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - so.Services = append(so.Services, service) - } - pos, ok = fields["shipping_option3_service2_name"] - if ok && record[pos] != "" { - service := new(pb.Listing_ShippingOption_Service) - service.Name = record[pos] - pos, ok = fields["shipping_option3_service2_estimated_delivery"] - if ok { - service.EstimatedDelivery = record[pos] - } - pos, ok = fields["shipping_option3_service2_estimated_price"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "shipping_option1_service2_estimated_price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - service.Price = uint64(f * 100) - } else { - service.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - so.Services = append(so.Services, service) - } - pos, ok = fields["shipping_option3_service3_name"] - if ok && record[pos] != "" { - service := new(pb.Listing_ShippingOption_Service) - service.Name = record[pos] - pos, ok = fields["shipping_option3_service3_estimated_delivery"] - if ok { - service.EstimatedDelivery = record[pos] - } - pos, ok = fields["shipping_option3_service3_estimated_price"] - if !ok { - errChan <- fmt.Errorf("error in record %d: %s", i, "shipping_option3_service3_estimated_price is a mandatory field") - return - } - if !listingCurrencyIsBTC(listing) { - f, err := strconv.ParseFloat(record[pos], 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - service.Price = uint64(f * 100) - } else { - service.Price, err = strconv.ParseUint(record[pos], 10, 64) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - } - so.Services = append(so.Services, service) - } - listing.ShippingOptions = append(listing.ShippingOptions, so) - } - // Set moderators - if len(listing.Moderators) == 0 { - sd, err := n.Datastore.Settings().Get() - if err == nil && sd.StoreModerators != nil { - listing.Moderators = *sd.StoreModerators - } - } - - // Set inventory - err = n.SetListingInventory(listing) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - - // Sign listing - signedListing, err := n.SignListing(listing) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - - // Save to disk - listingPath := path.Join(n.RepoPath, "root", "listings", signedListing.Listing.Slug+".json") - f, err := os.Create(listingPath) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - defer f.Close() - m := jsonpb.Marshaler{ - EnumsAsInts: false, - EmitDefaults: false, - Indent: " ", - OrigName: false, - } - out, err := m.MarshalToString(signedListing) - if err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - - if _, err := f.WriteString(out); err != nil { - errChan <- fmt.Errorf("error in record %d: %s", i, err.Error()) - return - } - - // Add listing data - data, err := n.extractListingData(signedListing) - if err != nil { - errChan <- fmt.Errorf("error extracting listings: %s", err.Error()) - return - } - - indexLock.Lock() - ld = append(ld, data) - indexLock.Unlock() - wg.Done() - }() - } - wg.Wait() - select { - case err := <-errChan: - return err - default: - } - index, err := n.getListingIndex() - if err != nil { - return err - } - index = append(index, ld...) - - // Write it back to file - indexPath := path.Join(n.RepoPath, "root", "listings.json") - f, err := os.Create(indexPath) - if err != nil { - return err - } - defer f.Close() - - j, jerr := json.MarshalIndent(index, "", " ") - if jerr != nil { - return jerr - } - _, werr := f.Write(j) - if werr != nil { - return werr - } - return nil -} - -func listingCurrencyIsBTC(l *pb.Listing) bool { - return NormalizeCurrencyCode(l.Metadata.PricingCurrency) == "BTC" -} diff --git a/core/inbound_message_scanner.go b/core/inbound_message_scanner.go new file mode 100644 index 0000000000..5ea869a6fd --- /dev/null +++ b/core/inbound_message_scanner.go @@ -0,0 +1,123 @@ +package core + +import ( + "time" + + "github.com/op/go-logging" + "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + + "github.com/phoreproject/pm-go/net" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" +) + +const ( + scannerTestingInterval = time.Duration(1) * time.Minute + scannerRegularInterval = time.Duration(10) * time.Minute +) + +type inboundMessageScanner struct { + // PerformTask dependencies + datastore repo.Datastore + service net.NetworkService + getHandler func(t pb.Message_MessageType) func(peer.ID, *pb.Message, interface{}) (*pb.Message, error) + extractID func([]byte) (*peer.ID, error) + broadcast chan repo.Notifier + + // Worker-handling dependencies + intervalDelay time.Duration + logger *logging.Logger + watchdogTimer *time.Ticker + stopWorker chan bool +} + +func peerIDExtractor(data []byte) (*peer.ID, error) { + i := peer.ID(data) + return &i, nil +} + +// StartInboundMsgScanner - start the notifier +func (n *OpenBazaarNode) StartInboundMsgScanner() { + n.InboundMsgScanner = &inboundMessageScanner{ + datastore: n.Datastore, + service: n.Service, + getHandler: n.Service.HandlerForMsgType, + extractID: peerIDExtractor, + broadcast: n.Broadcast, + intervalDelay: n.scannerIntervalDelay(), + logger: logging.MustGetLogger("inboundMessageScanner"), + } + go n.InboundMsgScanner.Run() +} + +func (n *OpenBazaarNode) scannerIntervalDelay() time.Duration { + if n.TestnetEnable { + return scannerTestingInterval + } + return scannerRegularInterval +} + +func (scanner *inboundMessageScanner) Run() { + scanner.watchdogTimer = time.NewTicker(scanner.intervalDelay) + scanner.stopWorker = make(chan bool) + + // Run once on start, then wait for watchdog + scanner.PerformTask() + for { + select { + case <-scanner.watchdogTimer.C: + scanner.PerformTask() + case <-scanner.stopWorker: + scanner.watchdogTimer.Stop() + return + } + } +} + +func (scanner *inboundMessageScanner) Stop() { + scanner.stopWorker <- true + close(scanner.stopWorker) +} + +func (scanner *inboundMessageScanner) PerformTask() { + msgs, err := scanner.datastore.Messages().GetAllErrored() + if err != nil { + scanner.logger.Error(err) + return + } + for _, m := range msgs { + if m.MsgErr == ErrInsufficientFunds.Error() { + // Get handler for this msg type + handler := scanner.getHandler(pb.Message_MessageType(m.MessageType)) + if handler == nil { + scanner.logger.Errorf("err fetching handler for msg: %v", pb.Message_MessageType(m.MessageType)) + continue + } + i, err := scanner.extractID(m.PeerPubkey) + if err != nil { + scanner.logger.Errorf("Error processing message %s. Type %s: %s", m, m.MessageType, err.Error()) + continue + + } + msg := new(repo.Message) + + if len(m.Message) > 0 { + err = msg.UnmarshalJSON(m.Message) + if err != nil { + scanner.logger.Errorf("Error processing message %s. Type %s: %s", m, m.MessageType, err.Error()) + continue + } + } + // Dispatch handler + _, err = handler(*i, &msg.Msg, nil) + if err != nil { + scanner.logger.Errorf("%d handle message error from %s: %s", m.MessageType, m.PeerID, err) + continue + } + err = scanner.datastore.Messages().MarkAsResolved(m) + if err != nil { + scanner.logger.Errorf("marking message resolved: %s", err) + } + } + } +} diff --git a/core/inbound_message_scanner_test.go b/core/inbound_message_scanner_test.go new file mode 100644 index 0000000000..36df7753fd --- /dev/null +++ b/core/inbound_message_scanner_test.go @@ -0,0 +1,128 @@ +package core + +import ( + "errors" + "github.com/phoreproject/multiwallet/util" + "sync" + "testing" + + wi "github.com/OpenBazaar/wallet-interface" + "github.com/op/go-logging" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" + "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" +) + +func TestPerformTaskInboundMessageScanner(t *testing.T) { + var ( + orderMsgWithNoErr = repo.OrderMessage{ + MessageID: "1", + OrderID: "1", + MessageType: int32(pb.Message_ORDER), + Message: []byte("sample message"), + MsgErr: "", + PeerID: "sample", + PeerPubkey: []byte("sample"), + } + + orderMsgWithErr = repo.OrderMessage{ + MessageID: "2", + OrderID: "2", + MessageType: int32(pb.Message_ORDER), + Message: []byte("sample message"), + MsgErr: ErrInsufficientFunds.Error(), + PeerID: "sample", + PeerPubkey: []byte("sample"), + } + + orderMsgWithOtherErr = repo.OrderMessage{ + MessageID: "3", + OrderID: "3", + MessageType: int32(pb.Message_ORDER), + Message: []byte("sample message"), + MsgErr: "not a retryable err", + PeerID: "sample", + PeerPubkey: []byte("sample"), + } + + existingRecords = []repo.OrderMessage{ + orderMsgWithNoErr, + orderMsgWithErr, + orderMsgWithOtherErr, + } + + appSchema = schema.MustNewCustomSchemaManager(schema.SchemaContext{ + DataPath: schema.GenerateTempPath(), + TestModeEnabled: true, + }) + ) + + if err := appSchema.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer appSchema.DestroySchemaDirectories() + if err := appSchema.InitializeDatabase(); err != nil { + t.Fatal(err) + } + + database, err := appSchema.OpenDatabase() + if err != nil { + t.Fatal(err) + } + s, err := database.Prepare("insert into messages (messageID, orderID, message_type, message, peerID, err, pubkey) values (?, ?, ?, ?, ?, ?, ?)") + if err != nil { + t.Fatal(err) + } + + for _, r := range existingRecords { + _, err = s.Exec(r.MessageID, r.OrderID, r.MessageType, r.Message, r.PeerID, r.MsgErr, r.PeerPubkey) + if err != nil { + t.Fatal(err) + } + } + + handler := func(t pb.Message_MessageType) func(peer.ID, *pb.Message, interface{}) (*pb.Message, error) { + return func(peer.ID, *pb.Message, interface{}) (*pb.Message, error) { + if t == pb.Message_ORDER { + return nil, nil + } + return nil, errors.New("unknown message type") + } + } + + extractor := func(data []byte) (*peer.ID, error) { + return nil, nil + } + + datastore := db.NewSQLiteDatastore(database, new(sync.Mutex), util.ExtendCoinType(wi.Bitcoin)) + worker := &inboundMessageScanner{ + datastore: datastore, + logger: logging.MustGetLogger("testInboundMsgScanner"), + getHandler: handler, + extractID: extractor, + } + + worker.PerformTask() + msgs, err := worker.datastore.Messages().GetAllErrored() + if err != nil { + t.Errorf("err fetching msgs : %v", err) + } + + if len(msgs) != 2 { + t.Errorf("did not fetch the correct no of err records") + } + + count := 0 + for _, msg := range msgs { + if msg.MsgErr == ErrInsufficientFunds.Error() { + count++ + } + } + + if count != 1 { + t.Errorf("did not pick the correct no of records to process") + } + +} diff --git a/core/inventory.go b/core/inventory.go index 075e671e5b..dd2f8cebde 100644 --- a/core/inventory.go +++ b/core/inventory.go @@ -3,11 +3,12 @@ package core import ( "encoding/json" "errors" + "math/big" peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" "time" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) var ( @@ -18,7 +19,7 @@ var ( // InventoryListing is the listing representation stored on IPFS type InventoryListing struct { - Inventory int64 `json:"inventory"` + Inventory string `json:"inventory"` LastUpdated string `json:"lastUpdated"` } @@ -33,16 +34,18 @@ func (n *OpenBazaarNode) GetLocalInventory() (Inventory, error) { return nil, err } - inventory := make(Inventory, len(listings)) - var totalCount int64 + var ( + totalCount *big.Int + inventory = make(Inventory, len(listings)) + ) for slug, variants := range listings { - totalCount = 0 + totalCount = big.NewInt(0) for _, variantCount := range variants { - totalCount += variantCount + totalCount = new(big.Int).Add(totalCount, variantCount) } inventory[slug] = &InventoryListing{ - Inventory: totalCount, + Inventory: totalCount.String(), LastUpdated: time.Now().UTC().Format(time.RFC3339), } } @@ -58,13 +61,13 @@ func (n *OpenBazaarNode) GetLocalInventoryForSlug(slug string) (*InventoryListin } var inventory *InventoryListing - var totalCount int64 + totalCount := big.NewInt(0) for _, variantCount := range variants { - totalCount += variantCount + totalCount = new(big.Int).Add(totalCount, variantCount) } inventory = &InventoryListing{ - Inventory: totalCount, + Inventory: totalCount.String(), LastUpdated: time.Now().UTC().Format(time.RFC3339), } diff --git a/core/listings.go b/core/listings.go index 2c8c3e04dd..cb6d0ccee1 100644 --- a/core/listings.go +++ b/core/listings.go @@ -5,289 +5,44 @@ import ( "encoding/json" "errors" "fmt" - "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" - mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" "io/ioutil" + "math/big" "os" "path" "path/filepath" - "strconv" - "strings" "time" "github.com/OpenBazaar/jsonpb" "github.com/golang/protobuf/proto" - "github.com/microcosm-cc/bluemonday" "github.com/op/go-logging" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" -) - -const ( - // ListingVersion - current listing version - ListingVersion = 4 - // TitleMaxCharacters - max size for title - TitleMaxCharacters = 140 - // ShortDescriptionLength - min length for description - ShortDescriptionLength = 160 - // DescriptionMaxCharacters - max length for description - DescriptionMaxCharacters = 50000 - // MaxTags - max permitted tags - MaxTags = 10 - // MaxCategories - max permitted categories - MaxCategories = 10 - // MaxListItems - max items in a listing - MaxListItems = 30 - // FilenameMaxCharacters - max filename size - FilenameMaxCharacters = 255 - // CodeMaxCharacters - max chars for a code - CodeMaxCharacters = 20 - // WordMaxCharacters - max chars for word - WordMaxCharacters = 40 - // SentenceMaxCharacters - max chars for sentence - SentenceMaxCharacters = 70 - // CouponTitleMaxCharacters - max length of a coupon title - CouponTitleMaxCharacters = 70 - // PolicyMaxCharacters - max length for policy - PolicyMaxCharacters = 10000 - // AboutMaxCharacters - max length for about - AboutMaxCharacters = 10000 - // URLMaxCharacters - max length for URL - URLMaxCharacters = 2000 - // MaxCountryCodes - max country codes - MaxCountryCodes = 255 - // EscrowTimeout - escrow timeout in hours - EscrowTimeout = 1080 - // SlugBuffer - buffer size for slug - SlugBuffer = 5 - // PriceModifierMin - min price modifier - PriceModifierMin = -99.99 - // PriceModifierMax = max price modifier - PriceModifierMax = 1000.00 -) - -type price struct { - CurrencyCode string `json:"currencyCode"` - Amount uint64 `json:"amount"` - Modifier float32 `json:"modifier"` -} -type thumbnail struct { - Tiny string `json:"tiny"` - Small string `json:"small"` - Medium string `json:"medium"` -} - -// ListingData - represent a listing -type ListingData struct { - Hash string `json:"hash"` - Slug string `json:"slug"` - Title string `json:"title"` - Tags []string `json:"tags"` - Categories []string `json:"categories"` - NSFW bool `json:"nsfw"` - ContractType string `json:"contractType"` - Format string `json:"format"` - Description string `json:"description"` - Thumbnail thumbnail `json:"thumbnail"` - Price price `json:"price"` - ShipsTo []string `json:"shipsTo"` - FreeShipping []string `json:"freeShipping"` - Language string `json:"language"` - AverageRating float32 `json:"averageRating"` - RatingCount uint32 `json:"ratingCount"` - ModeratorIDs []string `json:"moderators"` - AcceptedCurrencies []string `json:"acceptedCurrencies"` - CoinType string `json:"coinType"` - CoinDivisibility uint32 `json:"coinDivisibility"` - Testnet bool `json:"testnet"` -} -var ( - ErrShippingRegionMustBeSet = errors.New("shipping region must be set") - ErrShippingRegionUndefined = errors.New("undefined shipping region") - ErrShippingRegionMustNotBeContinent = errors.New("cannot specify continent as shipping region") + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) -// GenerateSlug - slugify the title of the listing -func (n *OpenBazaarNode) GenerateSlug(title string) (string, error) { - title = strings.Replace(title, "/", "", -1) - counter := 1 - slugBase := createSlugFor(title) - slugToTry := slugBase - for { - _, err := n.GetListingFromSlug(slugToTry) - if os.IsNotExist(err) { - return slugToTry, nil - } else if err != nil { - return "", err - } - slugToTry = slugBase + strconv.Itoa(counter) - counter++ - } -} - -// SignListing Add our identity to the listing and sign it -func (n *OpenBazaarNode) SignListing(listing *pb.Listing) (*pb.SignedListing, error) { - // Set inventory to the default as it's not part of the contract - for _, s := range listing.Item.Skus { - s.Quantity = 0 - } - - sl := new(pb.SignedListing) - - // Temporary hack to work around test env shortcomings - if n.TestNetworkEnabled() || n.RegressionNetworkEnabled() { - if listing.Metadata.EscrowTimeoutHours == 0 { - listing.Metadata.EscrowTimeoutHours = 1 - } - } else { - listing.Metadata.EscrowTimeoutHours = EscrowTimeout - } - - // Validate accepted currencies - if len(listing.Metadata.AcceptedCurrencies) == 0 { - return sl, errors.New("accepted currencies must be set") - } - if listing.Metadata.ContractType == pb.Listing_Metadata_CRYPTOCURRENCY && len(listing.Metadata.AcceptedCurrencies) != 1 { - return sl, errors.New("a cryptocurrency listing must only have one accepted currency") - } - currencyMap := make(map[string]bool) - for _, acceptedCurrency := range listing.Metadata.AcceptedCurrencies { - _, err := n.Multiwallet.WalletForCurrencyCode(acceptedCurrency) - if err != nil { - return sl, fmt.Errorf("currency %s is not found in multiwallet", acceptedCurrency) - } - if currencyMap[NormalizeCurrencyCode(acceptedCurrency)] { - return sl, errors.New("duplicate accepted currency in listing") - } - currencyMap[NormalizeCurrencyCode(acceptedCurrency)] = true - } - - // Sanitize a few critical fields - if listing.Item == nil { - return sl, errors.New("no item in listing") - } - sanitizer := bluemonday.UGCPolicy() - for _, opt := range listing.Item.Options { - opt.Name = sanitizer.Sanitize(opt.Name) - for _, v := range opt.Variants { - v.Name = sanitizer.Sanitize(v.Name) - } - } - for _, so := range listing.ShippingOptions { - so.Name = sanitizer.Sanitize(so.Name) - for _, serv := range so.Services { - serv.Name = sanitizer.Sanitize(serv.Name) - } - } - - // Check the listing data is correct for continuing - testingEnabled := n.TestNetworkEnabled() || n.RegressionNetworkEnabled() - if err := n.validateListing(listing, testingEnabled); err != nil { - return sl, err - } - - // Set listing version - listing.Metadata.Version = ListingVersion - - // Add the vendor ID to the listing - id := new(pb.ID) - id.PeerID = n.IpfsNode.Identity.Pretty() - pubkey, err := n.IpfsNode.PrivateKey.GetPublic().Bytes() - if err != nil { - return sl, err - } - profile, err := n.GetProfile() - if err == nil { - id.Handle = profile.Handle - } - p := new(pb.ID_Pubkeys) - p.Identity = pubkey - ecPubKey, err := n.MasterPrivateKey.ECPubKey() - if err != nil { - return sl, err - } - p.Bitcoin = ecPubKey.SerializeCompressed() - id.Pubkeys = p - listing.VendorID = id - - // Sign the GUID with the Bitcoin key - ecPrivKey, err := n.MasterPrivateKey.ECPrivKey() - if err != nil { - return sl, err - } - sig, err := ecPrivKey.Sign([]byte(id.PeerID)) - if err != nil { - return sl, err - } - id.BitcoinSig = sig.Serialize() - - // Update coupon db - n.Datastore.Coupons().Delete(listing.Slug) - var couponsToStore []repo.Coupon - for i, coupon := range listing.Coupons { - hash := coupon.GetHash() - code := coupon.GetDiscountCode() - _, err := mh.FromB58String(hash) - if err != nil { - couponMH, err := EncodeMultihash([]byte(code)) - if err != nil { - return sl, err - } - - listing.Coupons[i].Code = &pb.Listing_Coupon_Hash{Hash: couponMH.B58String()} - hash = couponMH.B58String() - } - c := repo.Coupon{Slug: listing.Slug, Code: code, Hash: hash} - couponsToStore = append(couponsToStore, c) - } - err = n.Datastore.Coupons().Put(couponsToStore) - if err != nil { - return sl, err - } - - // Sign listing - serializedListing, err := proto.Marshal(listing) - if err != nil { - return sl, err - } - idSig, err := n.IpfsNode.PrivateKey.Sign(serializedListing) - if err != nil { - return sl, err - } - sl.Listing = listing - sl.Signature = idSig - return sl, nil -} - -/*SetListingInventory Sets the inventory for the listing in the database. Does some basic validation - to make sure the inventory uses the correct variants. */ -func (n *OpenBazaarNode) SetListingInventory(listing *pb.Listing) error { - err := validateListingSkus(listing) +// SetListingInventory sets the inventory for the listing in the database. Does some basic validation +// to make sure the inventory uses the correct variants. +func (n *OpenBazaarNode) SetListingInventory(l repo.Listing) error { + err := l.ValidateSkus() if err != nil { return err } // Grab current inventory - currentInv, err := n.Datastore.Inventory().Get(listing.Slug) + currentInv, err := n.Datastore.Inventory().Get(l.GetSlug()) if err != nil { return err } - // Update inventory - for i, s := range listing.Item.Skus { - err = n.Datastore.Inventory().Put(listing.Slug, i, s.Quantity) - if err != nil { - return err - } - _, ok := currentInv[i] - if ok { - delete(currentInv, i) - } + // Get the listing inventory + listingInv, err := l.GetInventory() + if err != nil { + return err } - // If SKUs were omitted, set a default with unlimited inventry - if len(listing.Item.Skus) == 0 { - err = n.Datastore.Inventory().Put(listing.Slug, 0, -1) + + // If SKUs were omitted, set a default with unlimited inventory + if len(listingInv) == 0 { + err = n.Datastore.Inventory().Put(l.GetSlug(), 0, big.NewInt(-1)) if err != nil { return err } @@ -295,10 +50,23 @@ func (n *OpenBazaarNode) SetListingInventory(listing *pb.Listing) error { if ok { delete(currentInv, 0) } + } else { + // Update w provided inventory + for i, s := range listingInv { + err = n.Datastore.Inventory().Put(l.GetSlug(), i, s) + if err != nil { + return err + } + _, ok := currentInv[i] + if ok { + delete(currentInv, i) + } + } } + // Delete anything that did not update for i := range currentInv { - err = n.Datastore.Inventory().Delete(listing.Slug, i) + err = n.Datastore.Inventory().Delete(l.GetSlug(), i) if err != nil { return err } @@ -313,103 +81,121 @@ func (n *OpenBazaarNode) SetListingInventory(listing *pb.Listing) error { } // CreateListing - add a listing -func (n *OpenBazaarNode) CreateListing(listing *pb.Listing) error { - exists, err := n.listingExists(listing.Slug) +func (n *OpenBazaarNode) CreateListing(r []byte) (string, error) { + listing, err := repo.CreateListing(r, n.TestNetworkEnabled() || n.RegressionNetworkEnabled(), &n.Datastore, n.RepoPath) if err != nil { - return err - } - - if exists { - return ErrListingAlreadyExists - } - - if listing.Slug == "" { - listing.Slug, err = n.GenerateSlug(listing.Item.Title) - if err != nil { - return err - } + return "", err } - - return n.saveListing(listing, true) + return listing.GetSlug(), n.saveListing(listing, true) } // UpdateListing - update the listing -func (n *OpenBazaarNode) UpdateListing(listing *pb.Listing, publish bool) error { - exists, err := n.listingExists(listing.Slug) +func (n *OpenBazaarNode) UpdateListing(r []byte, publish bool) error { + listing, err := repo.UpdateListing(r, n.TestNetworkEnabled() || n.RegressionNetworkEnabled(), &n.Datastore, n.RepoPath) if err != nil { return err } + return n.saveListing(listing, publish) +} - if !exists { - return ErrListingDoesNotExist +func (n *OpenBazaarNode) validateListingIsSellable(l repo.Listing) error { + var isTestnet = n.TestNetworkEnabled() || n.RegressionNetworkEnabled() + + if err := l.ValidateListing(isTestnet); err != nil { + return err } - return n.saveListing(listing, publish) + var acceptedCurrenciesSeen = make(map[string]bool) + for _, c := range l.GetAcceptedCurrencies() { + if _, err := n.Multiwallet.WalletForCurrencyCode(c); err != nil { + return fmt.Errorf("currency (%s) not supported by wallet", c) + } + + currDef, err := repo.AllCurrencies().Lookup(c) + if err != nil { + return fmt.Errorf("lookup currency (%s): %s", c, err.Error()) + } + + if acceptedCurrenciesSeen[currDef.CurrencyCode().String()] { + return errors.New("duplicate accepted currency in listing") + } + acceptedCurrenciesSeen[currDef.CurrencyCode().String()] = true + } + + return nil } -func prepListingForPublish(n *OpenBazaarNode, listing *pb.Listing) error { - if len(listing.Moderators) == 0 { +func (n *OpenBazaarNode) saveListing(l repo.Listing, publish bool) error { + mods := l.GetModerators() + if len(mods) == 0 { sd, err := n.Datastore.Settings().Get() if err == nil && sd.StoreModerators != nil { - listing.Moderators = *sd.StoreModerators + if err := l.SetModerators(*sd.StoreModerators); err != nil { + return err + } } } - if listing.Metadata.ContractType == pb.Listing_Metadata_CRYPTOCURRENCY { - err := n.validateCryptocurrencyListing(listing) - if err != nil { + ct := l.GetContractType() + if pb.Listing_Metadata_ContractType_value[ct] == int32(pb.Listing_Metadata_CRYPTOCURRENCY) { + if err := l.ValidateCryptoListing(); err != nil { return err } - setCryptocurrencyListingDefaults(listing) + if err := l.SetCryptocurrencyListingDefaults(); err != nil { + return err + } } - err := n.SetListingInventory(listing) - if err != nil { + if err := n.validateListingIsSellable(l); err != nil { + return fmt.Errorf("validate sellable listing (%s): %s", l.GetSlug(), err.Error()) + } + + if err := n.SetListingInventory(l); err != nil { return err } - err = n.maybeMigrateImageHashes(listing) - if err != nil { + if err := n.maybeMigrateImageHashes(&l); err != nil { return err } - listing.Testnet = n.TestnetEnable + // Update coupon db + if err := n.updateListingCoupons(&l); err != nil { + return fmt.Errorf("updating (%s) coupons: %s", l.GetSlug(), err.Error()) + } - signedListing, err := n.SignListing(listing) + sl, err := l.Sign(n) if err != nil { return err } - f, err := os.Create(n.getPathForListingSlug(signedListing.Listing.Slug)) + fName, err := repo.GetPathForListingSlug(sl.GetSlug(), n.RepoPath, n.TestNetworkEnabled()) if err != nil { return err } - m := jsonpb.Marshaler{ - EnumsAsInts: false, - EmitDefaults: false, - Indent: " ", - OrigName: false, + f, err := os.Create(fName) + if err != nil { + return err } - out, err := m.MarshalToString(signedListing) + defer f.Close() + + out, err := sl.MarshalJSON() if err != nil { return err } + if _, err := f.Write(out); err != nil { + return err + } - if _, err := f.WriteString(out); err != nil { + ld, err := n.toListingIndexData(&l) + if err != nil { return err } - err = n.updateListingIndex(signedListing) + index, err := n.getListingIndex() if err != nil { return err } - - return nil -} - -func (n *OpenBazaarNode) saveListing(listing *pb.Listing, publish bool) error { - - err := prepListingForPublish(n, listing) + err = n.updateListingOnDisk(index, ld, false) if err != nil { return err } @@ -429,114 +215,91 @@ func (n *OpenBazaarNode) saveListing(listing *pb.Listing, publish bool) error { return nil } -func (n *OpenBazaarNode) listingExists(slug string) (bool, error) { - if slug == "" { - return false, nil - } - _, ferr := os.Stat(n.getPathForListingSlug(slug)) - if slug == "" { - return false, nil - } - if os.IsNotExist(ferr) { - return false, nil - } - if ferr != nil { - return false, ferr +func (n *OpenBazaarNode) updateListingCoupons(l *repo.Listing) error { + cs, err := l.GetCoupons() + if err != nil { + return fmt.Errorf("get coupons: %s", err.Error()) } - return true, nil -} - -func (n *OpenBazaarNode) getPathForListingSlug(slug string) string { - return path.Join(n.RepoPath, "root", "listings", slug+".json") -} + var couponsToSave = make([]repo.Coupon, 0) + for _, c := range cs { + // check for redemption code and only persist if available + cCode, err := c.GetRedemptionCode() + if err != nil { + log.Warningf("not persisting coupon (%s): missing redemption code", c.GetTitle()) + continue + } -func (n *OpenBazaarNode) updateListingIndex(listing *pb.SignedListing) error { - ld, err := n.extractListingData(listing) - if err != nil { - return err + cHash, err := c.GetRedemptionHash() + if err != nil { + return fmt.Errorf("get redemption hash (%s): %s", c.GetTitle(), err.Error()) + } + couponsToSave = append(couponsToSave, repo.Coupon{ + Slug: l.GetSlug(), + Code: cCode, + Hash: cHash, + }) } - index, err := n.getListingIndex() - if err != nil { - return err + if len(couponsToSave) > 0 { + // check if some coupons have codes but not others to avoid missing coupons + if len(couponsToSave) != len(cs) { + return fmt.Errorf("not all coupons for listing (%s) could be persisted due to missing redemption codes", l.GetSlug()) + } + if err := n.Datastore.Coupons().Delete(l.GetSlug()); err != nil { + log.Errorf("failed removing old coupons for listing (%s): %s", l.GetSlug(), err.Error()) + } + if err := n.Datastore.Coupons().Put(couponsToSave); err != nil { + return fmt.Errorf("persisting coupons: %s", err.Error()) + } } - return n.updateListingOnDisk(index, ld, false) -} - -func setCryptocurrencyListingDefaults(listing *pb.Listing) { - listing.Coupons = []*pb.Listing_Coupon{} - listing.Item.Options = []*pb.Listing_Item_Option{} - listing.ShippingOptions = []*pb.Listing_ShippingOption{} + return nil } -func (n *OpenBazaarNode) extractListingData(listing *pb.SignedListing) (ListingData, error) { - listingPath := path.Join(n.RepoPath, "root", "listings", listing.Listing.Slug+".json") +func (n *OpenBazaarNode) toListingIndexData(l *repo.Listing) (repo.ListingIndexData, error) { + var ( + listingPath = path.Join(n.RepoPath, "root", "listings", l.GetSlug()+".json") + shipTo, freeShipTo = l.GetShippingRegions() + previewImg = l.GetImages()[0] + ) listingHash, err := ipfs.GetHashOfFile(n.IpfsNode, listingPath) if err != nil { - return ListingData{}, err - } - - descriptionLength := len(listing.Listing.Item.Description) - if descriptionLength > ShortDescriptionLength { - descriptionLength = ShortDescriptionLength - } - - contains := func(s []string, e string) bool { - for _, a := range s { - if a == e { - return true - } - } - return false + return repo.ListingIndexData{}, fmt.Errorf("get hash: %s", err.Error()) } - - var shipsTo []string - var freeShipping []string - for _, shippingOption := range listing.Listing.ShippingOptions { - for _, region := range shippingOption.Regions { - if !contains(shipsTo, region.String()) { - shipsTo = append(shipsTo, region.String()) - } - for _, service := range shippingOption.Services { - if service.Price == 0 && !contains(freeShipping, region.String()) { - freeShipping = append(freeShipping, region.String()) - } - } - } + priceValue, err := l.GetPrice() + if err != nil { + return repo.ListingIndexData{}, fmt.Errorf("get price: %s", err.Error()) } - ld := ListingData{ - Hash: listingHash, - Slug: listing.Listing.Slug, - Title: listing.Listing.Item.Title, - Tags: listing.Listing.Item.Tags, - Categories: listing.Listing.Item.Categories, - NSFW: listing.Listing.Item.Nsfw, - CoinType: listing.Listing.Metadata.CoinType, - CoinDivisibility: listing.Listing.Metadata.CoinDivisibility, - ContractType: listing.Listing.Metadata.ContractType.String(), - Format: listing.Listing.Metadata.Format.String(), - Description: listing.Listing.Item.Description[:descriptionLength], - Thumbnail: thumbnail{listing.Listing.Item.Images[0].Tiny, listing.Listing.Item.Images[0].Small, listing.Listing.Item.Images[0].Medium}, - Price: price{ - CurrencyCode: listing.Listing.Metadata.PricingCurrency, - Amount: listing.Listing.Item.Price, - Modifier: listing.Listing.Metadata.PriceModifier, + return repo.ListingIndexData{ + Hash: listingHash, + Slug: l.GetSlug(), + Title: l.GetTitle(), + Tags: l.GetTags(), + Categories: l.GetCategories(), + NSFW: l.GetNsfw(), + ContractType: l.GetContractType(), + Format: l.GetFormat(), + Description: l.GetShortDescription(), + Thumbnail: repo.ListingThumbnail{ + previewImg.GetTiny(), + previewImg.GetSmall(), + previewImg.GetMedium(), }, - ShipsTo: shipsTo, - FreeShipping: freeShipping, - Language: listing.Listing.Metadata.Language, - ModeratorIDs: listing.Listing.Moderators, - AcceptedCurrencies: listing.Listing.Metadata.AcceptedCurrencies, - Testnet: listing.Listing.Testnet, - } - return ld, nil -} - -func (n *OpenBazaarNode) getListingIndex() ([]ListingData, error) { + Price: priceValue, + Modifier: l.GetPriceModifier(), + ShipsTo: shipTo, + FreeShipping: freeShipTo, + Language: l.GetLanguage(), + ModeratorIDs: l.GetModerators(), + AcceptedCurrencies: l.GetAcceptedCurrencies(), + CryptoCurrencyCode: l.GetCryptoCurrencyCode(), + }, nil +} + +func (n *OpenBazaarNode) getListingIndex() ([]repo.ListingIndexData, error) { indexPath := path.Join(n.RepoPath, "root", "listings.json") - var index []ListingData + var index []repo.ListingIndexData _, ferr := os.Stat(indexPath) if !os.IsNotExist(ferr) { @@ -554,7 +317,7 @@ func (n *OpenBazaarNode) getListingIndex() ([]ListingData, error) { } // Update the listings.json file in the listings directory -func (n *OpenBazaarNode) updateListingOnDisk(index []ListingData, ld ListingData, updateRatings bool) error { +func (n *OpenBazaarNode) updateListingOnDisk(index []repo.ListingIndexData, ld repo.ListingIndexData, updateRatings bool) error { indexPath := path.Join(n.RepoPath, "root", "listings.json") // Check to see if the listing we are adding already exists in the list. If so delete it. var avgRating float32 @@ -565,7 +328,7 @@ func (n *OpenBazaarNode) updateListingOnDisk(index []ListingData, ld ListingData ratingCount = d.RatingCount if len(index) == 1 { - index = []ListingData{} + index = []repo.ListingIndexData{} break } index = append(index[:i], index[i+1:]...) @@ -603,7 +366,7 @@ func (n *OpenBazaarNode) updateRatingInListingIndex(rating *pb.Rating) error { if err != nil { return err } - var ld ListingData + var ld repo.ListingIndexData exists := false for _, l := range index { if l.Slug == rating.RatingData.VendorSig.Metadata.ListingSlug { @@ -625,10 +388,10 @@ func (n *OpenBazaarNode) updateRatingInListingIndex(rating *pb.Rating) error { // UpdateEachListingOnIndex will visit each listing in the index and execute the function // with a pointer to the listing passed as the argument. The function should return // an error to further processing. -func (n *OpenBazaarNode) UpdateEachListingOnIndex(updateListing func(*ListingData) error) error { +func (n *OpenBazaarNode) UpdateEachListingOnIndex(updateListing func(*repo.ListingIndexData) error) error { indexPath := path.Join(n.RepoPath, "root", "listings.json") - var index []ListingData + var index []repo.ListingIndexData _, ferr := os.Stat(indexPath) if os.IsNotExist(ferr) { @@ -677,7 +440,7 @@ func (n *OpenBazaarNode) GetListingCount() int { return 0 } - var index []ListingData + var index []repo.ListingIndexData err = json.Unmarshal(file, &index) if err != nil { return 0 @@ -703,7 +466,7 @@ func (n *OpenBazaarNode) IsItemForSale(listing *pb.Listing) bool { return false } - var index []ListingData + var index []repo.ListingIndexData err = json.Unmarshal(file, &index) if err != nil { log.Error(err) @@ -740,7 +503,7 @@ func (n *OpenBazaarNode) DeleteListing(slug string) error { if err != nil { return err } - var index []ListingData + var index []repo.ListingIndexData indexPath := path.Join(n.RepoPath, "root", "listings.json") _, ferr := os.Stat(indexPath) if !os.IsNotExist(ferr) { @@ -762,7 +525,7 @@ func (n *OpenBazaarNode) DeleteListing(slug string) error { } if len(index) == 1 { - index = []ListingData{} + index = []repo.ListingIndexData{} break } index = append(index[:i], index[i+1:]...) @@ -808,7 +571,7 @@ func (n *OpenBazaarNode) GetListings() ([]byte, error) { } // Unmarshal the index to check if file contains valid json - var index []ListingData + var index []repo.ListingIndexData err = json.Unmarshal(file, &index) if err != nil { return nil, err @@ -828,7 +591,7 @@ func (n *OpenBazaarNode) GetListingFromHash(hash string) (*pb.SignedListing, err } // Unmarshal the index - var index []ListingData + var index []repo.ListingIndexData err = json.Unmarshal(file, &index) if err != nil { return nil, err @@ -873,537 +636,229 @@ func (n *OpenBazaarNode) GetListingFromSlug(slug string) (*pb.SignedListing, err // Build the inventory list for variant, count := range inventory { - for i, s := range sl.Listing.Item.Skus { + for i := range sl.Listing.Item.Skus { if variant == i { - s.Quantity = count + sl.Listing.Item.Skus[i].BigQuantity = count.String() break } } } - return sl, nil -} -/* Performs a ton of checks to make sure the listing is formatted correctly. We should not allow - invalid listings to be saved or purchased as it can lead to ambiguity when moderating a dispute - or possible attacks. This function needs to be maintained in conjunction with contracts.proto */ -func (n *OpenBazaarNode) validateListing(listing *pb.Listing, testnet bool) (err error) { - defer func() { - if r := recover(); r != nil { - switch x := r.(type) { - case string: - err = errors.New(x) - case error: - err = x - default: - err = errors.New("unknown panic") - } + for _, s := range sl.Listing.Item.Skus { + if s.BigSurcharge == "" { + s.BigSurcharge = "0" } - }() - - // Slug - if listing.Slug == "" { - return errors.New("slug must not be empty") - } - if len(listing.Slug) > SentenceMaxCharacters { - return fmt.Errorf("slug is longer than the max of %d", SentenceMaxCharacters) - } - if strings.Contains(listing.Slug, " ") { - return errors.New("slugs cannot contain spaces") - } - if strings.Contains(listing.Slug, "/") { - return errors.New("slugs cannot contain file separators") } - // Metadata - if listing.Metadata == nil { - return errors.New("missing required field: Metadata") - } - if listing.Metadata.ContractType > pb.Listing_Metadata_CRYPTOCURRENCY { - return errors.New("invalid contract type") - } - if listing.Metadata.Format > pb.Listing_Metadata_MARKET_PRICE { - return errors.New("invalid listing format") - } - if listing.Metadata.Expiry == nil { - return errors.New("missing required field: Expiry") - } - if time.Unix(listing.Metadata.Expiry.Seconds, 0).Before(time.Now()) { - return errors.New("listing expiration must be in the future") - } - if len(listing.Metadata.Language) > WordMaxCharacters { - return fmt.Errorf("language is longer than the max of %d characters", WordMaxCharacters) - } + return sl, nil +} - if !testnet && listing.Metadata.EscrowTimeoutHours != EscrowTimeout { - return fmt.Errorf("escrow timeout must be %d hours", EscrowTimeout) - } - if len(listing.Metadata.AcceptedCurrencies) == 0 { - return errors.New("at least one accepted currency must be provided") - } - if len(listing.Metadata.AcceptedCurrencies) > MaxListItems { - return fmt.Errorf("acceptedCurrencies is longer than the max of %d currencies", MaxListItems) - } - for _, c := range listing.Metadata.AcceptedCurrencies { - if len(c) > WordMaxCharacters { - return fmt.Errorf("accepted currency is longer than the max of %d characters", WordMaxCharacters) - } +func (n *OpenBazaarNode) SetPriceOnListings(percentage float64) error { + absPath, err := filepath.Abs(path.Join(n.RepoPath, "root", "listings")) + if err != nil { + return err } + walkpath := func(p string, f os.FileInfo, err error) error { + if !f.IsDir() && filepath.Ext(p) == ".json" { + signedProto, err := GetSignedListingFromPath(p) + if err != nil { + return err + } - // Item - if listing.Item.Title == "" { - return errors.New("listing must have a title") - } - if listing.Metadata.ContractType != pb.Listing_Metadata_CRYPTOCURRENCY && listing.Item.Price == 0 { - return errors.New("zero price listings are not allowed") - } - if len(listing.Item.Title) > TitleMaxCharacters { - return fmt.Errorf("title is longer than the max of %d characters", TitleMaxCharacters) - } - if len(listing.Item.Description) > DescriptionMaxCharacters { - return fmt.Errorf("description is longer than the max of %d characters", DescriptionMaxCharacters) - } - if len(listing.Item.ProcessingTime) > SentenceMaxCharacters { - return fmt.Errorf("processing time length must be less than the max of %d", SentenceMaxCharacters) - } - if len(listing.Item.Tags) > MaxTags { - return fmt.Errorf("number of tags exceeds the max of %d", MaxTags) - } - for _, tag := range listing.Item.Tags { - if tag == "" { - return errors.New("tags must not be empty") - } - if len(tag) > WordMaxCharacters { - return fmt.Errorf("tags must be less than max of %d", WordMaxCharacters) - } - } - if len(listing.Item.Images) == 0 { - return errors.New("listing must contain at least one image") - } - if len(listing.Item.Images) > MaxListItems { - return fmt.Errorf("number of listing images is greater than the max of %d", MaxListItems) - } - for _, img := range listing.Item.Images { - _, err := cid.Decode(img.Tiny) - if err != nil { - return errors.New("tiny image hashes must be properly formatted CID") - } - _, err = cid.Decode(img.Small) - if err != nil { - return errors.New("small image hashes must be properly formatted CID") - } - _, err = cid.Decode(img.Medium) - if err != nil { - return errors.New("medium image hashes must be properly formatted CID") - } - _, err = cid.Decode(img.Large) - if err != nil { - return errors.New("large image hashes must be properly formatted CID") - } - _, err = cid.Decode(img.Original) - if err != nil { - return errors.New("original image hashes must be properly formatted CID") - } - if img.Filename == "" { - return errors.New("image file names must not be nil") - } - if len(img.Filename) > FilenameMaxCharacters { - return fmt.Errorf("image filename length must be less than the max of %d", FilenameMaxCharacters) - } - } - if len(listing.Item.Categories) > MaxCategories { - return fmt.Errorf("number of categories must be less than max of %d", MaxCategories) - } - for _, category := range listing.Item.Categories { - if category == "" { - return errors.New("categories must not be nil") - } - if len(category) > WordMaxCharacters { - return fmt.Errorf("category length must be less than the max of %d", WordMaxCharacters) - } - } + oldSL := repo.NewSignedListingFromProtobuf(signedProto) + l := oldSL.GetListing() - maxCombos := 1 - variantSizeMap := make(map[int]int) - optionMap := make(map[string]struct{}) - for i, option := range listing.Item.Options { - if _, ok := optionMap[option.Name]; ok { - return errors.New("option names must be unique") - } - if option.Name == "" { - return errors.New("options titles must not be empty") - } - if len(option.Variants) < 2 { - return errors.New("options must have more than one variants") - } - if len(option.Name) > WordMaxCharacters { - return fmt.Errorf("option title length must be less than the max of %d", WordMaxCharacters) - } - if len(option.Description) > SentenceMaxCharacters { - return fmt.Errorf("option description length must be less than the max of %d", SentenceMaxCharacters) - } - if len(option.Variants) > MaxListItems { - return fmt.Errorf("number of variants is greater than the max of %d", MaxListItems) - } - varMap := make(map[string]struct{}) - for _, variant := range option.Variants { - if _, ok := varMap[variant.Name]; ok { - return errors.New("variant names must be unique") + err = l.SetPrices(percentage) + if err != nil { + return err } - if len(variant.Name) > WordMaxCharacters { - return fmt.Errorf("variant name length must be less than the max of %d", WordMaxCharacters) + + lb, err := l.MarshalJSON() + if err != nil { + return fmt.Errorf("marshaling signed listing (%s): %s", l.GetSlug(), err.Error()) } - if variant.Image != nil && (variant.Image.Filename != "" || - variant.Image.Large != "" || variant.Image.Medium != "" || variant.Image.Small != "" || - variant.Image.Tiny != "" || variant.Image.Original != "") { - _, err := cid.Decode(variant.Image.Tiny) - if err != nil { - return errors.New("tiny image hashes must be properly formatted CID") - } - _, err = cid.Decode(variant.Image.Small) - if err != nil { - return errors.New("small image hashes must be properly formatted CID") - } - _, err = cid.Decode(variant.Image.Medium) - if err != nil { - return errors.New("medium image hashes must be properly formatted CID") - } - _, err = cid.Decode(variant.Image.Large) - if err != nil { - return errors.New("large image hashes must be properly formatted CID") - } - _, err = cid.Decode(variant.Image.Original) - if err != nil { - return errors.New("original image hashes must be properly formatted CID") - } - if variant.Image.Filename == "" { - return errors.New("image file names must not be nil") - } - if len(variant.Image.Filename) > FilenameMaxCharacters { - return fmt.Errorf("image filename length must be less than the max of %d", FilenameMaxCharacters) - } + err = n.UpdateListing(lb, false) + if err != nil { + return err } - varMap[variant.Name] = struct{}{} } - variantSizeMap[i] = len(option.Variants) - maxCombos *= len(option.Variants) - optionMap[option.Name] = struct{}{} - } - if len(listing.Item.Skus) > maxCombos { - return errors.New("more skus than variant combinations") + return nil } - comboMap := make(map[string]bool) - for _, sku := range listing.Item.Skus { - if maxCombos > 1 && len(sku.VariantCombo) == 0 { - return errors.New("skus must specify a variant combo when options are used") - } - if len(sku.ProductID) > WordMaxCharacters { - return fmt.Errorf("product ID length must be less than the max of %d", WordMaxCharacters) - } - formatted, err := json.Marshal(sku.VariantCombo) - if err != nil { - return err - } - _, ok := comboMap[string(formatted)] - if !ok { - comboMap[string(formatted)] = true - } else { - return errors.New("duplicate sku") - } - if len(sku.VariantCombo) != len(listing.Item.Options) { - return errors.New("incorrect number of variants in sku combination") - } - for i, combo := range sku.VariantCombo { - if int(combo) > variantSizeMap[i] { - return errors.New("invalid sku variant combination") - } - } + err = filepath.Walk(absPath, walkpath) + if err != nil { + return err } - // Taxes - if len(listing.Taxes) > MaxListItems { - return fmt.Errorf("number of taxes is greater than the max of %d", MaxListItems) - } - for _, tax := range listing.Taxes { - if tax.TaxType == "" { - return errors.New("tax type must be specified") - } - if len(tax.TaxType) > WordMaxCharacters { - return fmt.Errorf("tax type length must be less than the max of %d", WordMaxCharacters) - } - if len(tax.TaxRegions) == 0 { - return errors.New("tax must specify at least one region") - } - if len(tax.TaxRegions) > MaxCountryCodes { - return fmt.Errorf("number of tax regions is greater than the max of %d", MaxCountryCodes) - } - if tax.Percentage == 0 || tax.Percentage > 100 { - return errors.New("tax percentage must be between 0 and 100") - } + err = n.SeedNode() + if err != nil { + return err } + return nil +} - // Coupons - if len(listing.Coupons) > MaxListItems { - return fmt.Errorf("number of coupons is greater than the max of %d", MaxListItems) - } - for _, coupon := range listing.Coupons { - if len(coupon.Title) > CouponTitleMaxCharacters { - return fmt.Errorf("coupon title length must be less than the max of %d", SentenceMaxCharacters) - } - if len(coupon.GetDiscountCode()) > CodeMaxCharacters { - return fmt.Errorf("coupon code length must be less than the max of %d", CodeMaxCharacters) - } - if coupon.GetPercentDiscount() > 100 { - return errors.New("percent discount cannot be over 100 percent") - } - if coupon.GetPriceDiscount() > listing.Item.Price { - return errors.New("price discount cannot be greater than the item price") - } - if coupon.GetPercentDiscount() == 0 && coupon.GetPriceDiscount() == 0 { - return errors.New("coupons must have at least one positive discount value") - } +// SetCurrencyOnListings - set currencies accepted for a listing +func (n *OpenBazaarNode) SetCurrencyOnListings(currencies []string) error { + absPath, err := filepath.Abs(path.Join(n.RepoPath, "root", "listings")) + if err != nil { + return err } + walkpath := func(p string, f os.FileInfo, err error) error { + if !f.IsDir() && filepath.Ext(p) == ".json" { + signedProto, err := GetSignedListingFromPath(p) + if err != nil { + return err + } - // Moderators - if len(listing.Moderators) > MaxListItems { - return fmt.Errorf("number of moderators is greater than the max of %d", MaxListItems) - } - for _, moderator := range listing.Moderators { - _, err := mh.FromB58String(moderator) - if err != nil { - return errors.New("moderator IDs must be multihashes") - } - } + oldSL := repo.NewSignedListingFromProtobuf(signedProto) + l := oldSL.GetListing() - // TermsAndConditions - if len(listing.TermsAndConditions) > PolicyMaxCharacters { - return fmt.Errorf("terms and conditions length must be less than the max of %d", PolicyMaxCharacters) - } + // Cryptocurrency listings can only have one currency listed and since it's + // a trade for one specific currency for another specific currency it isn't + // appropriate to apply the bulk update to this type of listing. + if l.GetContractType() == pb.Listing_Metadata_CRYPTOCURRENCY.String() { + return nil + } + if err := l.SetAcceptedCurrencies(currencies...); err != nil { + return err + } - // RefundPolicy - if len(listing.RefundPolicy) > PolicyMaxCharacters { - return fmt.Errorf("refund policy length must be less than the max of %d", PolicyMaxCharacters) - } + lb, err := l.MarshalJSON() + if err != nil { + return fmt.Errorf("marshaling signed listing (%s): %s", l.GetSlug(), err.Error()) + } + err = n.UpdateListing(lb, false) + if err != nil { + return err + } - // Type-specific validations - if listing.Metadata.ContractType == pb.Listing_Metadata_PHYSICAL_GOOD { - err := validatePhysicalListing(listing) - if err != nil { - return err - } - } else if listing.Metadata.ContractType == pb.Listing_Metadata_CRYPTOCURRENCY { - err := n.validateCryptocurrencyListing(listing) - if err != nil { - return err } + return nil } - // Format-specific validations - if listing.Metadata.Format == pb.Listing_Metadata_MARKET_PRICE { - err := validateMarketPriceListing(listing) - if err != nil { - return err - } + err = filepath.Walk(absPath, walkpath) + if err != nil { + return err } - return nil -} - -func ValidShippingRegion(shippingOption *pb.Listing_ShippingOption) error { - for _, region := range shippingOption.Regions { - if int32(region) == 0 { - return ErrShippingRegionMustBeSet - } - _, ok := proto.EnumValueMap("CountryCode")[region.String()] - if !ok { - return ErrShippingRegionUndefined - } - if ok { - if int32(region) > 500 { - return ErrShippingRegionMustNotBeContinent - } - } + err = n.SeedNode() + if err != nil { + return err } + return nil } -func validatePhysicalListing(listing *pb.Listing) error { - if listing.Metadata.PricingCurrency == "" { - return errors.New("listing pricing currency code must not be empty") - } - if len(listing.Metadata.PricingCurrency) > WordMaxCharacters { - return fmt.Errorf("'PricingCurrency' is longer than the max of %d characters", WordMaxCharacters) - } - if len(listing.Item.Condition) > SentenceMaxCharacters { - return fmt.Errorf("'Condition' length must be less than the max of %d", SentenceMaxCharacters) - } - if len(listing.Item.Options) > MaxListItems { - return fmt.Errorf("number of options is greater than the max of %d", MaxListItems) +func (n *OpenBazaarNode) SetTermsAndConditionsOnListings(termsAndConditions string) error { + absPath, err := filepath.Abs(path.Join(n.RepoPath, "root", "listings")) + if err != nil { + return err } - // ShippingOptions - if len(listing.ShippingOptions) == 0 { - return errors.New("must be at least one shipping option for a physical good") - } - if len(listing.ShippingOptions) > MaxListItems { - return fmt.Errorf("number of shipping options is greater than the max of %d", MaxListItems) - } - var shippingTitles []string - for _, shippingOption := range listing.ShippingOptions { - if shippingOption.Name == "" { - return errors.New("shipping option title name must not be empty") - } - if len(shippingOption.Name) > WordMaxCharacters { - return fmt.Errorf("shipping option service length must be less than the max of %d", WordMaxCharacters) - } - for _, t := range shippingTitles { - if t == shippingOption.Name { - return errors.New("shipping option titles must be unique") - } - } - shippingTitles = append(shippingTitles, shippingOption.Name) - if shippingOption.Type > pb.Listing_ShippingOption_FIXED_PRICE { - return errors.New("unknown shipping option type") - } - if len(shippingOption.Regions) == 0 { - return errors.New("shipping options must specify at least one region") - } - if err := ValidShippingRegion(shippingOption); err != nil { - return fmt.Errorf("invalid shipping option (%s): %s", shippingOption.String(), err.Error()) - } - if len(shippingOption.Regions) > MaxCountryCodes { - return fmt.Errorf("number of shipping regions is greater than the max of %d", MaxCountryCodes) - } - if len(shippingOption.Services) == 0 && shippingOption.Type != pb.Listing_ShippingOption_LOCAL_PICKUP { - return errors.New("at least one service must be specified for a shipping option when not local pickup") - } - if len(shippingOption.Services) > MaxListItems { - return fmt.Errorf("number of shipping services is greater than the max of %d", MaxListItems) - } - var serviceTitles []string - for _, option := range shippingOption.Services { - if option.Name == "" { - return errors.New("shipping option service name must not be empty") - } - if len(option.Name) > WordMaxCharacters { - return fmt.Errorf("shipping option service length must be less than the max of %d", WordMaxCharacters) - } - for _, t := range serviceTitles { - if t == option.Name { - return errors.New("shipping option services names must be unique") - } + walkpath := func(p string, f os.FileInfo, err error) error { + if !f.IsDir() && filepath.Ext(p) == ".json" { + signedProto, err := GetSignedListingFromPath(p) + if err != nil { + return err } - serviceTitles = append(serviceTitles, option.Name) - if option.EstimatedDelivery == "" { - return errors.New("shipping option estimated delivery must not be empty") + + oldSL := repo.NewSignedListingFromProtobuf(signedProto) + l := oldSL.GetListing() + + l.SetTermsAndConditions(termsAndConditions) + + lb, err := l.MarshalJSON() + if err != nil { + return fmt.Errorf("marshaling signed listing (%s): %s", l.GetSlug(), err.Error()) } - if len(option.EstimatedDelivery) > SentenceMaxCharacters { - return fmt.Errorf("shipping option estimated delivery length must be less than the max of %d", SentenceMaxCharacters) + err = n.UpdateListing(lb, false) + if err != nil { + return err } } + return nil } - return nil -} + err = filepath.Walk(absPath, walkpath) + if err != nil { + return err + } -func (n *OpenBazaarNode) validateCryptocurrencyListing(listing *pb.Listing) error { - switch { - case len(listing.Coupons) > 0: - return ErrCryptocurrencyListingIllegalField("coupons") - case len(listing.Item.Options) > 0: - return ErrCryptocurrencyListingIllegalField("item.options") - case len(listing.ShippingOptions) > 0: - return ErrCryptocurrencyListingIllegalField("shippingOptions") - case len(listing.Item.Condition) > 0: - return ErrCryptocurrencyListingIllegalField("item.condition") - case len(listing.Metadata.PricingCurrency) > 0: - return ErrCryptocurrencyListingIllegalField("metadata.pricingCurrency") - case listing.Metadata.CoinType == "": - return ErrCryptocurrencyListingCoinTypeRequired - } - - var expectedDivisibility uint32 - if wallet, err := n.Multiwallet.WalletForCurrencyCode(listing.Metadata.CoinType); err != nil { - expectedDivisibility = DefaultCurrencyDivisibility - } else { - expectedDivisibility = uint32(wallet.ExchangeRates().UnitsPerCoin()) + err = n.SeedNode() + if err != nil { + return err + } + + profile, err := n.GetProfile() + if err != nil { + return err } + profile.TermsAndConditions = termsAndConditions - if listing.Metadata.CoinDivisibility != expectedDivisibility { - return ErrListingCoinDivisibilityIncorrect + err = n.UpdateProfile(&profile) + if err != nil { + return err } return nil } -func validateMarketPriceListing(listing *pb.Listing) error { - if listing.Item.Price > 0 { - return ErrMarketPriceListingIllegalField("item.price") +func (n *OpenBazaarNode) SetRefundPolicyOnListings(refundPolicy string) error { + absPath, err := filepath.Abs(path.Join(n.RepoPath, "root", "listings")) + if err != nil { + return err } - if listing.Metadata.PriceModifier != 0 { - listing.Metadata.PriceModifier = float32(int(listing.Metadata.PriceModifier*100.0)) / 100.0 - } + walkpath := func(p string, f os.FileInfo, err error) error { + if !f.IsDir() && filepath.Ext(p) == ".json" { + signedProto, err := GetSignedListingFromPath(p) + if err != nil { + return err + } - if listing.Metadata.PriceModifier < PriceModifierMin || - listing.Metadata.PriceModifier > PriceModifierMax { - return ErrPriceModifierOutOfRange{ - Min: PriceModifierMin, - Max: PriceModifierMax, - } - } + oldSL := repo.NewSignedListingFromProtobuf(signedProto) + l := oldSL.GetListing() - return nil -} + l.SetRefundPolicy(refundPolicy) -func validateListingSkus(listing *pb.Listing) error { - if listing.Metadata.ContractType == pb.Listing_Metadata_CRYPTOCURRENCY { - for _, sku := range listing.Item.Skus { - if sku.Quantity < 1 { - return ErrCryptocurrencySkuQuantityInvalid + lb, err := l.MarshalJSON() + if err != nil { + return fmt.Errorf("marshaling signed listing (%s): %s", l.GetSlug(), err.Error()) + } + err = n.UpdateListing(lb, false) + if err != nil { + return err } } + return nil } - return nil -} -func verifySignaturesOnListing(sl *pb.SignedListing) error { - // Verify identity signature on listing - if err := verifySignature( - sl.Listing, - sl.Listing.VendorID.Pubkeys.Identity, - sl.Signature, - sl.Listing.VendorID.PeerID, - ); err != nil { - switch err.(type) { - case invalidSigError: - return errors.New("vendor's identity signature on contact failed to verify") - case matchKeyError: - return errors.New("public key in order does not match reported buyer ID") - default: - return err - } + err = filepath.Walk(absPath, walkpath) + if err != nil { + return err } - // Verify the bitcoin signature in the ID - if err := verifyBitcoinSignature( - sl.Listing.VendorID.Pubkeys.Bitcoin, - sl.Listing.VendorID.BitcoinSig, - sl.Listing.VendorID.PeerID, - ); err != nil { - switch err.(type) { - case invalidSigError: - return errors.New("vendor's Bitcoin signature on GUID failed to verify") - default: - return err - } + err = n.SeedNode() + if err != nil { + return err + } + + profile, err := n.GetProfile() + if err != nil { + return err } + profile.RefundPolicy = refundPolicy + + err = n.UpdateProfile(&profile) + if err != nil { + return err + } + return nil } -// SetCurrencyOnListings - set currencies accepted for a listing -func (n *OpenBazaarNode) SetCurrencyOnListings(currencies []string) error { +func (n *OpenBazaarNode) SetShippingDetailsOnListings(shippingDetails []*pb.Listing_ShippingOption) error { absPath, err := filepath.Abs(path.Join(n.RepoPath, "root", "listings")) if err != nil { return err @@ -1411,45 +866,26 @@ func (n *OpenBazaarNode) SetCurrencyOnListings(currencies []string) error { walkpath := func(p string, f os.FileInfo, err error) error { if !f.IsDir() && filepath.Ext(p) == ".json" { - - sl, err := GetSignedListingFromPath(p) + signedProto, err := GetSignedListingFromPath(p) if err != nil { return err } - SetAcceptedCurrencies(sl, currencies) + oldSL := repo.NewSignedListingFromProtobuf(signedProto) + l := oldSL.GetListing() - savedCoupons, err := n.Datastore.Coupons().Get(sl.Listing.Slug) - if err != nil { - return err - } - err = AssignMatchingCoupons(savedCoupons, sl) - if err != nil { - return err - } - - if sl.Listing.Metadata != nil && sl.Listing.Metadata.Version == 1 { - err = ApplyShippingOptions(sl) - if err != nil { - return err - } - } + l.SetShippingOptions(shippingDetails) - inventory, err := n.Datastore.Inventory().Get(sl.Listing.Slug) - if err != nil { - return err - } - err = AssignMatchingQuantities(inventory, sl) + lb, err := l.MarshalJSON() if err != nil { - return err + return fmt.Errorf("marshaling signed listing (%s): %s", l.GetSlug(), err.Error()) } - - err = n.UpdateListing(sl.Listing, false) + err = n.UpdateListing(lb, false) if err != nil { return err } - } + return nil } @@ -1463,5 +899,16 @@ func (n *OpenBazaarNode) SetCurrencyOnListings(currencies []string) error { return err } + profile, err := n.GetProfile() + if err != nil { + return err + } + profile.ShippingOptions = shippingDetails + + err = n.UpdateProfile(&profile) + if err != nil { + return err + } + return nil } diff --git a/core/listings_test.go b/core/listings_test.go new file mode 100644 index 0000000000..5b43ad2822 --- /dev/null +++ b/core/listings_test.go @@ -0,0 +1,79 @@ +package core_test + +import ( + "testing" + + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test" + "github.com/phoreproject/pm-go/test/factory" +) + +func TestOpenBazaarNode_SetCurrencyOnListings(t *testing.T) { + node, err := test.NewNode() + if err != nil { + t.Fatal(err) + } + + var ( + regularListingSlug = "test_regular_listing" + cryptoListingSlug = "test_crypto_listing" + newAcceptedCurrencies = []string{"TBCH", "TLTC"} + cryptoListingCurrency = "TBTC" + ) + + regularListing := factory.NewListing(regularListingSlug) + regularListing.Metadata.AcceptedCurrencies = []string{"TBTC"} + regularRepoListing, err := repo.NewListingFromProtobuf(regularListing) + if err != nil { + t.Fatal(err) + } + + lb, err := regularRepoListing.MarshalJSON() + if err != nil { + t.Fatal(err) + } + if _, err := node.CreateListing(lb); err != nil { + t.Fatal(err) + } + + cryptoListing := factory.NewCryptoListing(cryptoListingSlug) + regularListing.Metadata.AcceptedCurrencies = []string{cryptoListingCurrency} + cryptoRepoListing, err := repo.NewListingFromProtobuf(cryptoListing) + if err != nil { + t.Fatal(err) + } + + clb, err := cryptoRepoListing.MarshalJSON() + if err != nil { + t.Fatal(err) + } + + if _, err := node.CreateListing(clb); err != nil { + t.Fatal(err) + } + + if err := node.SetCurrencyOnListings(newAcceptedCurrencies); err != nil { + t.Fatal(err) + } + + checkListing, err := node.GetListingFromSlug(regularListingSlug) + if err != nil { + t.Fatal(err) + } + if checkListing.Listing.Metadata.AcceptedCurrencies[0] != newAcceptedCurrencies[0] || + checkListing.Listing.Metadata.AcceptedCurrencies[1] != newAcceptedCurrencies[1] || + len(checkListing.Listing.Metadata.AcceptedCurrencies) != len(newAcceptedCurrencies) { + + t.Errorf("Listing %s expected accepted currency list %v, got %v", regularListingSlug, newAcceptedCurrencies, checkListing.Listing.Metadata.AcceptedCurrencies) + } + + checkListing2, err := node.GetListingFromSlug(cryptoListingSlug) + if err != nil { + t.Fatal(err) + } + if len(checkListing2.Listing.Metadata.AcceptedCurrencies) != 1 || checkListing2.Listing.Metadata.AcceptedCurrencies[0] != cryptoListingCurrency { + + t.Errorf("Listing %s expected accepted currency list %v, got %v", cryptoListingSlug, []string{cryptoListingCurrency}, checkListing2.Listing.Metadata.AcceptedCurrencies) + } + +} diff --git a/core/message_retriever.go b/core/message_retriever.go index 9f75d2db94..93ab95ca7a 100644 --- a/core/message_retriever.go +++ b/core/message_retriever.go @@ -1,7 +1,7 @@ package core import ( - net "github.com/phoreproject/openbazaar-go/net/retriever" + net "github.com/phoreproject/pm-go/net/retriever" ) // StartMessageRetriever will collect the required options from the diff --git a/core/moderation.go b/core/moderation.go index 6103350582..29ac95c3d3 100644 --- a/core/moderation.go +++ b/core/moderation.go @@ -3,17 +3,22 @@ package core import ( "crypto/sha256" "errors" - ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" - "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" - + "fmt" "io/ioutil" + "math/big" "os" "path" "path/filepath" + "strconv" + + routing "gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht" + ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" + "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" "github.com/OpenBazaar/jsonpb" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" "golang.org/x/net/context" ) @@ -52,7 +57,7 @@ func (n *OpenBazaarNode) SetSelfAsModerator(moderator *pb.Moderator) error { if moderator.Fee == nil { return errors.New("moderator must have a fee set") } - if (int(moderator.Fee.FeeType) == 0 || int(moderator.Fee.FeeType) == 2) && moderator.Fee.FixedFee == nil { + if (int(moderator.Fee.FeeType) == 0 || int(moderator.Fee.FeeType) == 2) && moderator.Fee.FixedFee.BigAmount == "" && moderator.Fee.FixedFee.Amount == 0 { return errors.New("fixed fee must be set when using a fixed fee type") } @@ -72,7 +77,11 @@ func (n *OpenBazaarNode) SetSelfAsModerator(moderator *pb.Moderator) error { } } for _, cc := range currencies { - moderator.AcceptedCurrencies = append(moderator.AcceptedCurrencies, NormalizeCurrencyCode(cc)) + currency, err := n.LookupCurrency(cc) + if err != nil { + return fmt.Errorf("moderator fee currency (%s) unknown: %s", cc, err) + } + moderator.AcceptedCurrencies = append(moderator.AcceptedCurrencies, currency.CurrencyCode().String()) } profile.Moderator = true @@ -95,14 +104,24 @@ func (n *OpenBazaarNode) SetSelfAsModerator(moderator *pb.Moderator) error { if err != nil { return err } - go ipfs.PublishPointer(n.DHT, ctx, pointer) + go func(dht *routing.IpfsDHT, ctx context.Context, pointer ipfs.Pointer) { + err := ipfs.PublishPointer(dht, ctx, pointer) + if err != nil { + log.Error(err) + } + }(n.DHT, ctx, pointer) pointer.Purpose = ipfs.MODERATOR err = n.Datastore.Pointers().Put(pointer) if err != nil { return err } } else { - go ipfs.PublishPointer(n.DHT, ctx, pointers[0]) + go func(dht *routing.IpfsDHT, ctx context.Context, pointer ipfs.Pointer) { + err := ipfs.PublishPointer(dht, ctx, pointer) + if err != nil { + log.Error(err) + } + }(n.DHT, ctx, pointers[0]) } return nil } @@ -128,56 +147,120 @@ func (n *OpenBazaarNode) RemoveSelfAsModerator() error { return nil } -// GetModeratorFee - fetch moderator fee -func (n *OpenBazaarNode) GetModeratorFee(transactionTotal uint64, paymentCoin, currencyCode string) (uint64, error) { +// GetModeratorFee is called by the Moderator when determining their take of the dispute +func (n *OpenBazaarNode) GetModeratorFee(transactionTotal *big.Int, txCurrencyCode string) (*big.Int, error) { + var curDef *pb.CurrencyDefinition + var bigAmount string + file, err := ioutil.ReadFile(path.Join(n.RepoPath, "root", "profile.json")) if err != nil { - return 0, err + return big.NewInt(0), err } profile := new(pb.Profile) err = jsonpb.UnmarshalString(string(file), profile) if err != nil { - return 0, err + return big.NewInt(0), err + } + txCurrency, err := n.LookupCurrency(txCurrencyCode) + if err != nil { + return big.NewInt(0), fmt.Errorf("lookup dispute transaction currency (%s): %s", txCurrencyCode, err) } - switch profile.ModeratorInfo.Fee.FeeType { case pb.Moderator_Fee_PERCENTAGE: - return uint64(float64(transactionTotal) * (float64(profile.ModeratorInfo.Fee.Percentage) / 100)), nil - case pb.Moderator_Fee_FIXED: + feePercent := new(big.Float).Mul(big.NewFloat(float64(profile.ModeratorInfo.Fee.Percentage)), big.NewFloat(0.01)) + feePercentAmt, _ := repo.NewCurrencyValueFromBigInt(transactionTotal, txCurrency).MulBigFloat(feePercent) + return feePercentAmt.AmountBigInt(), nil - if NormalizeCurrencyCode(profile.ModeratorInfo.Fee.FixedFee.CurrencyCode) == NormalizeCurrencyCode(currencyCode) { - if profile.ModeratorInfo.Fee.FixedFee.Amount >= transactionTotal { - return 0, errors.New("fixed moderator fee exceeds transaction amount") + case pb.Moderator_Fee_FIXED: + if profile.ModeratorInfo.Fee.FixedFee.AmountCurrency == nil { + currency, err := n.LookupCurrency(profile.ModeratorInfo.Fee.FixedFee.CurrencyCode) + if err != nil { + return nil, err + } + curDef = &pb.CurrencyDefinition{ + Code: currency.Code.String(), + Divisibility: uint32(currency.Divisibility), + } + bigAmount = strconv.FormatUint(profile.ModeratorInfo.Fee.FixedFee.Amount, 10) + } else { + currency, err := n.LookupCurrency(profile.ModeratorInfo.Fee.FixedFee.AmountCurrency.Code) + if err != nil { + return nil, err + } + curDef = &pb.CurrencyDefinition{ + Code: currency.Code.String(), + Divisibility: uint32(currency.Divisibility), } - return profile.ModeratorInfo.Fee.FixedFee.Amount, nil + bigAmount = profile.ModeratorInfo.Fee.FixedFee.BigAmount } - // TODO check for CRYPTO + FIX PRICE - fee, err := n.getPriceInSatoshi(paymentCoin, profile.ModeratorInfo.Fee.FixedFee.CurrencyCode, profile.ModeratorInfo.Fee.FixedFee.Amount) + + modFeeValue, err := repo.NewCurrencyValueFromProtobuf(bigAmount, curDef) + if err != nil { + return big.NewInt(0), fmt.Errorf("parse moderator fee currency: %s", err) + } + + cc, err := n.ReserveCurrencyConverter() + if err != nil { + return big.NewInt(0), fmt.Errorf("preparing reserve currency converter: %s", err.Error()) + } + + convertedModFee, _, err := modFeeValue.ConvertTo(txCurrency, cc) if err != nil { - return 0, err - } else if fee >= transactionTotal { - return 0, errors.New("fixed moderator fee exceeds transaction amount") + return big.NewInt(0), fmt.Errorf("convert moderator fee into transaction currency (%s): %s", txCurrency.String(), err) } - return fee, err + if convertedModFee.AmountBigInt().Cmp(transactionTotal) > 0 { + return big.NewInt(0), errors.New("Fixed moderator fee exceeds transaction amount") + } + return convertedModFee.AmountBigInt(), nil case pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE: - var fixed uint64 - if NormalizeCurrencyCode(profile.ModeratorInfo.Fee.FixedFee.CurrencyCode) == NormalizeCurrencyCode(currencyCode) { - fixed = profile.ModeratorInfo.Fee.FixedFee.Amount + if profile.ModeratorInfo.Fee.FixedFee.AmountCurrency == nil { + currency, err := n.LookupCurrency(profile.ModeratorInfo.Fee.FixedFee.CurrencyCode) + if err != nil { + return nil, err + } + curDef = &pb.CurrencyDefinition{ + Code: currency.Code.String(), + Divisibility: uint32(currency.Divisibility), + } + bigAmount = strconv.FormatUint(profile.ModeratorInfo.Fee.FixedFee.Amount, 10) } else { - // TODO check for CRYPTO + FIX PRICE - fixed, err = n.getPriceInSatoshi(paymentCoin, profile.ModeratorInfo.Fee.FixedFee.CurrencyCode, profile.ModeratorInfo.Fee.FixedFee.Amount) + currency, err := n.LookupCurrency(profile.ModeratorInfo.Fee.FixedFee.AmountCurrency.Code) if err != nil { - return 0, err + return nil, err } + curDef = &pb.CurrencyDefinition{ + Code: currency.Code.String(), + Divisibility: uint32(currency.Divisibility), + } + bigAmount = profile.ModeratorInfo.Fee.FixedFee.BigAmount + } + + modFeeValue, err := repo.NewCurrencyValueFromProtobuf(bigAmount, curDef) + if err != nil { + return big.NewInt(0), fmt.Errorf("parse moderator fee currency: %s", err) } - percentage := uint64(float64(transactionTotal) * (float64(profile.ModeratorInfo.Fee.Percentage) / 100)) - if fixed+percentage >= transactionTotal { - return 0, errors.New("fixed moderator fee exceeds transaction amount") + + cc, err := n.ReserveCurrencyConverter() + if err != nil { + return big.NewInt(0), fmt.Errorf("preparing reserve currency converter: %s", err.Error()) + } + + convertedModFee, _, err := modFeeValue.ConvertTo(txCurrency, cc) + if err != nil { + return big.NewInt(0), fmt.Errorf("convert moderator fee into transaction currency (%s): %s", txCurrency.String(), err) + } + + feePercent := new(big.Float).Mul(big.NewFloat(float64(profile.ModeratorInfo.Fee.Percentage)), big.NewFloat(0.01)) + feePercentAmt, _ := repo.NewCurrencyValueFromBigInt(transactionTotal, txCurrency).MulBigFloat(feePercent) + feeTotal := feePercentAmt.AddBigInt(convertedModFee.AmountBigInt()) + if feeTotal.AmountBigInt().Cmp(transactionTotal) > 0 { + return big.NewInt(0), errors.New("Fixed moderator fee exceeds transaction amount") } - return fixed + percentage, nil + return feeTotal.AmountBigInt(), nil + default: - return 0, errors.New("unrecognized fee type") + return big.NewInt(0), errors.New("Unrecognized fee type") } } @@ -190,57 +273,44 @@ func (n *OpenBazaarNode) SetModeratorsOnListings(moderators []string) error { hashes := make(map[string]string) walkpath := func(p string, f os.FileInfo, err error) error { if !f.IsDir() { - file, err := ioutil.ReadFile(p) + listingJSONBytes, err := ioutil.ReadFile(p) if err != nil { return err } - sl := new(pb.SignedListing) - err = jsonpb.UnmarshalString(string(file), sl) + oldSL, err := repo.UnmarshalJSONSignedListing(listingJSONBytes) if err != nil { return err } - coupons, err := n.Datastore.Coupons().Get(sl.Listing.Slug) - if err != nil { - return err - } - couponMap := make(map[string]string) - for _, c := range coupons { - couponMap[c.Hash] = c.Code - } - for _, coupon := range sl.Listing.Coupons { - code, ok := couponMap[coupon.GetHash()] - if ok { - coupon.Code = &pb.Listing_Coupon_DiscountCode{DiscountCode: code} - } + l := oldSL.GetListing() + + if err := l.SetModerators(moderators); err != nil { + return fmt.Errorf("settings moderator on (%s): %s", f.Name(), err.Error()) } - sl.Listing.Moderators = moderators - sl, err = n.SignListing(sl.Listing) + sl, err := l.Sign(n) if err != nil { - return err - } - m := jsonpb.Marshaler{ - EnumsAsInts: false, - EmitDefaults: false, - Indent: " ", - OrigName: false, + return fmt.Errorf("signing listing (%s): %s", l.GetSlug(), err.Error()) } + fi, err := os.Create(p) if err != nil { return err } - out, err := m.MarshalToString(sl) + defer fi.Close() + + slBytes, err := sl.MarshalJSON() if err != nil { - return err + return fmt.Errorf("marshal signed listing (%s): %s", l.GetSlug(), err.Error()) } - if _, err := fi.WriteString(out); err != nil { + + if _, err := fi.Write(slBytes); err != nil { return err } hash, err := ipfs.GetHashOfFile(n.IpfsNode, p) if err != nil { return err } - hashes[sl.Listing.Slug] = hash + hashes[sl.GetSlug()] = hash return nil } @@ -253,7 +323,7 @@ func (n *OpenBazaarNode) SetModeratorsOnListings(moderators []string) error { } // Update moderators and hashes on index - updater := func(listing *ListingData) error { + updater := func(listing *repo.ListingIndexData) error { listing.ModeratorIDs = moderators if hash, ok := hashes[listing.Slug]; ok { listing.Hash = hash @@ -267,10 +337,20 @@ func (n *OpenBazaarNode) SetModeratorsOnListings(moderators []string) error { func (n *OpenBazaarNode) NotifyModerators(addedMods, removedMods []string) error { n.Service.WaitForReady() for _, mod := range addedMods { - go n.SendModeratorAdd(mod) + go func(mod string) { + err := n.SendModeratorAdd(mod) + if err != nil { + log.Error(err) + } + }(mod) } for _, mod := range removedMods { - go n.SendModeratorRemove(mod) + go func(mod string) { + err := n.SendModeratorRemove(mod) + if err != nil { + log.Error(err) + } + }(mod) } return nil } diff --git a/core/net.go b/core/net.go index 9413163637..00d2849ca8 100644 --- a/core/net.go +++ b/core/net.go @@ -2,20 +2,21 @@ package core import ( "errors" + "fmt" + "sync" + "time" libp2p "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" - "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" - "sync" - "time" - "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/any" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" "golang.org/x/net/context" ) @@ -34,6 +35,7 @@ var OfflineMessageWaitGroup sync.WaitGroup func (n *OpenBazaarNode) sendMessage(peerID string, k *libp2p.PubKey, message pb.Message) error { p, err := peer.IDB58Decode(peerID) if err != nil { + log.Errorf("failed to decode peerID: %v", err) return err } ctx, cancel := context.WithTimeout(context.Background(), n.OfflineMessageFailoverTimeout) @@ -96,23 +98,32 @@ func (n *OpenBazaarNode) SendOfflineMessage(p peer.ID, k *libp2p.PubKey, m *pb.M } } log.Debugf("Sending offline message to: %s, Message Type: %s, PointerID: %s, Location: %s", p.Pretty(), m.MessageType.String(), pointer.Cid.String(), pointer.Value.Addrs[0].String()) - OfflineMessageWaitGroup.Add(2) - go func() { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - err := ipfs.PublishPointer(n.DHT, ctx, pointer) - if err != nil { - log.Error(err) - } - // Push provider to our push nodes for redundancy - for _, p := range n.PushNodes { + // We publish our pointers to three different locations: + // 1. The pushnodes + // 2. The DHT + // 3. Pubsub + // Each one is done in a separate goroutine so as to not block but we + // do increment the OfflineMessageWaitGroup which is used to block + // shutdown until all publishing is finished. + OfflineMessageWaitGroup.Add(2 + len(n.PushNodes)) + for _, p := range n.PushNodes { + go func(pid peer.ID) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - err := ipfs.PutPointerToPeer(n.DHT, ctx, p, pointer) + err := ipfs.PutPointerToPeer(n.DHT, ctx, pid, pointer) if err != nil { log.Error(err) } + OfflineMessageWaitGroup.Done() + }(p) + } + go func() { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + err := ipfs.PublishPointer(n.DHT, ctx, pointer) + if err != nil { + log.Error(err) } OfflineMessageWaitGroup.Done() @@ -120,7 +131,7 @@ func (n *OpenBazaarNode) SendOfflineMessage(p peer.ID, k *libp2p.PubKey, m *pb.M go func() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - err := n.Pubsub.Publisher.Publish(ctx, ipfs.MessageTopicPrefix+pointer.Cid.String(), ciphertext) + err := n.Pubsub.Publisher.Publish(ctx, pointer.Cid.String(), ciphertext) if err != nil { log.Error(err) } @@ -142,6 +153,7 @@ func (n *OpenBazaarNode) SendOfflineAck(peerID string, pointerID peer.ID) error func (n *OpenBazaarNode) GetPeerStatus(peerID string) (string, error) { p, err := peer.IDB58Decode(peerID) if err != nil { + log.Errorf("failed to decode peerID: %v", err) return "", err } ctx, cancel := context.WithCancel(context.Background()) @@ -187,6 +199,7 @@ func (n *OpenBazaarNode) Follow(peerID string) error { } pbAny, err := ptypes.MarshalAny(sd) if err != nil { + log.Errorf("failed to marshal the signedData: %v", err) return err } m.Payload = pbAny @@ -239,6 +252,7 @@ func (n *OpenBazaarNode) Unfollow(peerID string) error { } pbAny, err := ptypes.MarshalAny(sd) if err != nil { + log.Errorf("failed to marshal the signedData: %v", err) return err } m.Payload = pbAny @@ -258,10 +272,41 @@ func (n *OpenBazaarNode) Unfollow(peerID string) error { return nil } +// ResendCachedOrderMessage will retrieve the ORDER message from the datastore and resend it to the peerID +// for which it was originally intended +func (n *OpenBazaarNode) ResendCachedOrderMessage(orderID string, msgType pb.Message_MessageType) error { + if _, ok := pb.Message_MessageType_name[int32(msgType)]; !ok { + return fmt.Errorf("invalid order message type (%d)", int(msgType)) + } + + msg, peerID, err := n.Datastore.Messages().GetByOrderIDType(orderID, msgType) + if err != nil || msg == nil || msg.Msg.GetPayload() == nil { + return fmt.Errorf("unable to find message for order ID (%s) and message type (%s)", orderID, msgType.String()) + } + + p, err := peer.IDB58Decode(peerID) + if err != nil { + return fmt.Errorf("unable to decode invalid peer ID for order (%s) and message type (%s)", orderID, msgType.String()) + } + + ctx, cancel := context.WithTimeout(context.Background(), n.OfflineMessageFailoverTimeout) + defer cancel() + + if err = n.Service.SendMessage(ctx, p, &msg.Msg); err != nil { + go func() { + if err := n.SendOfflineMessage(p, nil, &msg.Msg); err != nil { + log.Errorf("error resending offline message for order id (%s) and message type (%+v): %s", orderID, msgType, err.Error()) + } + }() + } + return nil +} + // SendOrder - send order created msg to peer func (n *OpenBazaarNode) SendOrder(peerID string, contract *pb.RicardianContract) (resp *pb.Message, err error) { p, err := peer.IDB58Decode(peerID) if err != nil { + log.Errorf("failed to decode peerID: %v", err) return resp, err } @@ -269,15 +314,28 @@ func (n *OpenBazaarNode) SendOrder(peerID string, contract *pb.RicardianContract defer cancel() pbAny, err := ptypes.MarshalAny(contract) if err != nil { + log.Errorf("failed to marshal the contract: %v", err) return resp, err } m := pb.Message{ MessageType: pb.Message_ORDER, Payload: pbAny, } - + orderID0, err := n.CalcOrderID(contract.BuyerOrder) + if err != nil { + log.Errorf("failed calculating order id: %v", err) + } else { + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID0, int(pb.Message_ORDER)), + orderID0, pb.Message_ORDER, peerID, repo.Message{Msg: m}, + "", 0, []byte{}) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID0, int(pb.Message_ORDER), err) + } + } resp, err = n.Service.SendRequest(ctx, p, &m) if err != nil { + log.Errorf("failed to send order request: %v", err) return resp, err } return resp, nil @@ -292,6 +350,7 @@ func (n *OpenBazaarNode) SendError(peerID string, k *libp2p.PubKey, errorMessage func (n *OpenBazaarNode) SendOrderConfirmation(peerID string, contract *pb.RicardianContract) error { a, err := ptypes.MarshalAny(contract) if err != nil { + log.Errorf("failed to marshal the contract: %v", err) return err } m := pb.Message{ @@ -300,8 +359,21 @@ func (n *OpenBazaarNode) SendOrderConfirmation(peerID string, contract *pb.Ricar } k, err := libp2p.UnmarshalPublicKey(contract.GetBuyerOrder().GetBuyerID().GetPubkeys().Identity) if err != nil { + log.Errorf("failed to unmarshal the publicKey: %v", err) return err } + orderID0 := contract.VendorOrderConfirmation.OrderID + if orderID0 == "" { + log.Errorf("failed fetching orderID") + } else { + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID0, int(pb.Message_ORDER_CONFIRMATION)), + orderID0, pb.Message_ORDER_CONFIRMATION, peerID, repo.Message{Msg: m}, + "", 0, []byte{}) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID0, int(pb.Message_ORDER_CONFIRMATION), err) + } + } return n.sendMessage(peerID, &k, m) } @@ -315,14 +387,24 @@ func (n *OpenBazaarNode) SendCancel(peerID, orderID string) error { //try to get public key from order order, _, _, _, _, _, err := n.Datastore.Purchases().GetByOrderId(orderID) var kp *libp2p.PubKey + var pub []byte if err != nil { //probably implies we can't find the order in the Datastore kp = nil //instead SendOfflineMessage can try to get the key from the peerId + pub = order.BuyerOrder.BuyerID.Pubkeys.Identity } else { k, err := libp2p.UnmarshalPublicKey(order.GetVendorListings()[0].GetVendorID().GetPubkeys().Identity) if err != nil { return err } kp = &k + pub = order.VendorListings[0].VendorID.Pubkeys.Identity + } + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID, int(pb.Message_ORDER_CANCEL)), + orderID, pb.Message_ORDER_CANCEL, peerID, repo.Message{Msg: m}, + "", 0, pub) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID, int(pb.Message_ORDER_CANCEL), err) } return n.sendMessage(peerID, kp, m) } @@ -331,6 +413,7 @@ func (n *OpenBazaarNode) SendCancel(peerID, orderID string) error { func (n *OpenBazaarNode) SendReject(peerID string, rejectMessage *pb.OrderReject) error { a, err := ptypes.MarshalAny(rejectMessage) if err != nil { + log.Errorf("failed to marshal the contract: %v", err) return err } m := pb.Message{ @@ -338,16 +421,26 @@ func (n *OpenBazaarNode) SendReject(peerID string, rejectMessage *pb.OrderReject Payload: a, } var kp *libp2p.PubKey + var pub []byte //try to get public key from order order, _, _, _, _, _, err := n.Datastore.Sales().GetByOrderId(rejectMessage.OrderID) if err != nil { //probably implies we can't find the order in the Datastore kp = nil //instead SendOfflineMessage can try to get the key from the peerId + pub = order.BuyerOrder.BuyerID.Pubkeys.Identity } else { k, err := libp2p.UnmarshalPublicKey(order.GetBuyerOrder().GetBuyerID().GetPubkeys().Identity) if err != nil { + log.Errorf("failed to unmarshal publicKey: %v", err) return err } kp = &k + pub = order.VendorListings[0].VendorID.Pubkeys.Identity + } + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", rejectMessage.OrderID, int(pb.Message_ORDER_REJECT)), + rejectMessage.OrderID, pb.Message_ORDER_REJECT, peerID, repo.Message{Msg: m}, "", 0, pub) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", rejectMessage.OrderID, int(pb.Message_ORDER_REJECT), err) } return n.sendMessage(peerID, kp, m) } @@ -356,14 +449,32 @@ func (n *OpenBazaarNode) SendReject(peerID string, rejectMessage *pb.OrderReject func (n *OpenBazaarNode) SendRefund(peerID string, refundMessage *pb.RicardianContract) error { a, err := ptypes.MarshalAny(refundMessage) if err != nil { + log.Errorf("failed to marshal the contract: %v", err) return err } + // Create the REFUND message m := pb.Message{ MessageType: pb.Message_REFUND, Payload: a, } + + // Save REFUND message to the database for this order for resending if necessary + orderID0 := refundMessage.Refund.OrderID + if orderID0 == "" { + log.Errorf("failed fetching orderID") + } else { + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID0, int(pb.Message_REFUND)), + orderID0, pb.Message_REFUND, peerID, repo.Message{Msg: m}, + "", 0, []byte{}) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID0, int(pb.Message_REFUND), err) + } + } + k, err := libp2p.UnmarshalPublicKey(refundMessage.GetBuyerOrder().GetBuyerID().GetPubkeys().Identity) if err != nil { + log.Errorf("failed to unmarshal publicKey: %v", err) return err } return n.sendMessage(peerID, &k, m) @@ -373,12 +484,25 @@ func (n *OpenBazaarNode) SendRefund(peerID string, refundMessage *pb.RicardianCo func (n *OpenBazaarNode) SendOrderFulfillment(peerID string, k *libp2p.PubKey, fulfillmentMessage *pb.RicardianContract) error { a, err := ptypes.MarshalAny(fulfillmentMessage) if err != nil { + log.Errorf("failed to marshal the contract: %v", err) return err } m := pb.Message{ MessageType: pb.Message_ORDER_FULFILLMENT, Payload: a, } + orderID0 := fulfillmentMessage.VendorOrderFulfillment[0].OrderId + if orderID0 == "" { + log.Errorf("failed fetching orderID") + } else { + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID0, int(pb.Message_ORDER_FULFILLMENT)), + orderID0, pb.Message_ORDER_FULFILLMENT, peerID, repo.Message{Msg: m}, + "", 0, []byte{}) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID0, int(pb.Message_ORDER_FULFILLMENT), err) + } + } return n.sendMessage(peerID, k, m) } @@ -386,25 +510,56 @@ func (n *OpenBazaarNode) SendOrderFulfillment(peerID string, k *libp2p.PubKey, f func (n *OpenBazaarNode) SendOrderCompletion(peerID string, k *libp2p.PubKey, completionMessage *pb.RicardianContract) error { a, err := ptypes.MarshalAny(completionMessage) if err != nil { + log.Errorf("failed to marshal the contract: %v", err) return err } m := pb.Message{ MessageType: pb.Message_ORDER_COMPLETION, Payload: a, } + orderID0 := completionMessage.BuyerOrderCompletion.OrderId + if orderID0 == "" { + log.Errorf("failed fetching orderID") + } else { + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID0, int(pb.Message_ORDER_COMPLETION)), + orderID0, pb.Message_ORDER_COMPLETION, peerID, repo.Message{Msg: m}, + "", 0, []byte{}) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID0, int(pb.Message_ORDER_COMPLETION), err) + } + } return n.sendMessage(peerID, k, m) } // SendDisputeOpen - send open dispute msg to peer -func (n *OpenBazaarNode) SendDisputeOpen(peerID string, k *libp2p.PubKey, disputeMessage *pb.RicardianContract) error { +func (n *OpenBazaarNode) SendDisputeOpen(peerID string, k *libp2p.PubKey, disputeMessage *pb.RicardianContract, orderID string) error { a, err := ptypes.MarshalAny(disputeMessage) if err != nil { + log.Errorf("failed to marshal the contract: %v", err) return err } + + // Create the DISPUTE_OPEN message m := pb.Message{ MessageType: pb.Message_DISPUTE_OPEN, Payload: a, } + + // Save DISPUTE_OPEN message to the database for this order for resending if necessary + orderID0 := orderID + if orderID0 == "" { + log.Errorf("failed fetching orderID") + } else { + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID0, int(pb.Message_DISPUTE_OPEN)), + orderID0, pb.Message_DISPUTE_OPEN, peerID, repo.Message{Msg: m}, + "", 0, []byte{}) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID0, int(pb.Message_DISPUTE_OPEN), err) + } + } + return n.sendMessage(peerID, k, m) } @@ -412,25 +567,61 @@ func (n *OpenBazaarNode) SendDisputeOpen(peerID string, k *libp2p.PubKey, disput func (n *OpenBazaarNode) SendDisputeUpdate(peerID string, updateMessage *pb.DisputeUpdate) error { a, err := ptypes.MarshalAny(updateMessage) if err != nil { + log.Errorf("failed to marshal the contract: %v", err) return err } + + // Create the DISPUTE_UPDATE message m := pb.Message{ MessageType: pb.Message_DISPUTE_UPDATE, Payload: a, } + + // Save DISPUTE_UPDATE message to the database for this order for resending if necessary + orderID0 := updateMessage.OrderId + if orderID0 == "" { + log.Errorf("failed fetching orderID") + } else { + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID0, int(pb.Message_DISPUTE_UPDATE)), + orderID0, pb.Message_DISPUTE_UPDATE, peerID, repo.Message{Msg: m}, + "", 0, []byte{}) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID0, int(pb.Message_DISPUTE_UPDATE), err) + } + } + return n.sendMessage(peerID, nil, m) } // SendDisputeClose - send dispute closed msg to peer -func (n *OpenBazaarNode) SendDisputeClose(peerID string, k *libp2p.PubKey, resolutionMessage *pb.RicardianContract) error { +func (n *OpenBazaarNode) SendDisputeClose(peerID string, k *libp2p.PubKey, resolutionMessage *pb.RicardianContract, orderID string) error { a, err := ptypes.MarshalAny(resolutionMessage) if err != nil { + log.Errorf("failed to marshal the contract: %v", err) return err } + + // Create the DISPUTE_CLOSE message m := pb.Message{ MessageType: pb.Message_DISPUTE_CLOSE, Payload: a, } + + // Save DISPUTE_CLOSE message to the database for this order for resending if necessary + orderID0 := orderID + if orderID0 == "" { + log.Errorf("failed fetching orderID") + } else { + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID0, int(pb.Message_DISPUTE_CLOSE)), + orderID0, pb.Message_DISPUTE_CLOSE, peerID, repo.Message{Msg: m}, + "", 0, []byte{}) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID0, int(pb.Message_DISPUTE_CLOSE), err) + } + } + return n.sendMessage(peerID, k, m) } @@ -438,10 +629,12 @@ func (n *OpenBazaarNode) SendDisputeClose(peerID string, k *libp2p.PubKey, resol func (n *OpenBazaarNode) SendFundsReleasedByVendor(peerID string, marshalledPeerPublicKey []byte, orderID string) error { peerKey, err := libp2p.UnmarshalPublicKey(marshalledPeerPublicKey) if err != nil { + log.Errorf("failed to unmarshal the publicKey: %v", err) return err } payload, err := ptypes.MarshalAny(&pb.VendorFinalizedPayment{OrderID: orderID}) if err != nil { + log.Errorf("failed to marshal the finalized payment: %v", err) return err } message := pb.Message{ @@ -455,6 +648,7 @@ func (n *OpenBazaarNode) SendFundsReleasedByVendor(peerID string, marshalledPeer func (n *OpenBazaarNode) SendChat(peerID string, chatMessage *pb.Chat) error { a, err := ptypes.MarshalAny(chatMessage) if err != nil { + log.Errorf("failed to marshal the chat message: %v", err) return err } m := pb.Message{ @@ -464,6 +658,7 @@ func (n *OpenBazaarNode) SendChat(peerID string, chatMessage *pb.Chat) error { p, err := peer.IDB58Decode(peerID) if err != nil { + log.Errorf("failed to decode peerID: %v", err) return err } ctx, cancel := context.WithTimeout(context.Background(), n.OfflineMessageFailoverTimeout) @@ -471,6 +666,7 @@ func (n *OpenBazaarNode) SendChat(peerID string, chatMessage *pb.Chat) error { err = n.Service.SendMessage(ctx, p, &m) if err != nil && chatMessage.Flag != pb.Chat_TYPING { if err := n.SendOfflineMessage(p, nil, &m); err != nil { + log.Errorf("failed to send offline message: %v", err) return err } } @@ -510,6 +706,7 @@ func (n *OpenBazaarNode) SendModeratorAdd(peerID string) error { } pbAny, err := ptypes.MarshalAny(sd) if err != nil { + log.Errorf("failed to marshal the signed data: %v", err) return err } m.Payload = pbAny @@ -554,6 +751,7 @@ func (n *OpenBazaarNode) SendModeratorRemove(peerID string) error { } pbAny, err := ptypes.MarshalAny(sd) if err != nil { + log.Errorf("failed to marshal the signedData: %v", err) return err } m.Payload = pbAny @@ -580,6 +778,7 @@ func (n *OpenBazaarNode) SendBlock(peerID string, id cid.Cid) error { } a, err := ptypes.MarshalAny(b) if err != nil { + log.Errorf("failed to marshal the block: %v", err) return err } m := pb.Message{ @@ -589,6 +788,7 @@ func (n *OpenBazaarNode) SendBlock(peerID string, id cid.Cid) error { p, err := peer.IDB58Decode(peerID) if err != nil { + log.Errorf("failed to decode peerID: %v", err) return err } return n.Service.SendMessage(context.Background(), p, &m) @@ -605,6 +805,7 @@ func (n *OpenBazaarNode) SendStore(peerID string, ids []cid.Cid) error { a, err := ptypes.MarshalAny(cList) if err != nil { + log.Errorf("failed to marshal the cidList: %v", err) return err } @@ -615,6 +816,7 @@ func (n *OpenBazaarNode) SendStore(peerID string, ids []cid.Cid) error { p, err := peer.IDB58Decode(peerID) if err != nil { + log.Errorf("failed to decode peerID: %v", err) return err } pmes, err := n.Service.SendRequest(context.Background(), p, &m) @@ -633,6 +835,7 @@ func (n *OpenBazaarNode) SendStore(peerID string, ids []cid.Cid) error { resp := new(pb.CidList) err = ptypes.UnmarshalAny(pmes.Payload, resp) if err != nil { + log.Errorf("failed to unmarshal the cidList: %v", err) return err } if len(resp.Cids) == 0 { @@ -663,3 +866,53 @@ func (n *OpenBazaarNode) SendOfflineRelay(peerID string, encryptedMessage []byte } return n.sendMessage(peerID, nil, m) } + +// SendOrderPayment - send order payment msg to seller from buyer +func (n *OpenBazaarNode) SendOrderPayment(spend *SpendResponse) error { + var msg = &pb.OrderPaymentTxn{ + Coin: spend.Currency.Code.String(), + OrderID: spend.OrderID, + TransactionID: spend.Txid, + WithInput: spend.ConsumedInput, + } + + a, err := ptypes.MarshalAny(msg) + if err != nil { + return err + } + + // Create the ORDER_PAYMENT message + m := pb.Message{ + MessageType: pb.Message_ORDER_PAYMENT, + Payload: a, + } + + p, err := peer.IDB58Decode(spend.PeerID) + if err != nil { + return err + } + + // Save ORDER_PAYMENT message to the database for this order for resending if necessary + orderID0 := msg.OrderID + if orderID0 == "" { + log.Errorf("failed fetching orderID") + } else { + err = n.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID0, int(pb.Message_ORDER_PAYMENT)), + orderID0, pb.Message_ORDER_PAYMENT, spend.PeerID, repo.Message{Msg: m}, + "", 0, []byte{}) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID0, int(pb.Message_ORDER_PAYMENT), err) + } + } + + ctx, cancel := context.WithTimeout(context.Background(), n.OfflineMessageFailoverTimeout) + err = n.Service.SendMessage(ctx, p, &m) + cancel() + if err != nil { + if err := n.SendOfflineMessage(p, nil, &m); err != nil { + return err + } + } + return nil +} diff --git a/core/order.go b/core/order.go index 46a7e3efe3..726de77522 100644 --- a/core/order.go +++ b/core/order.go @@ -7,64 +7,27 @@ import ( "encoding/json" "errors" "fmt" - - "github.com/golang/protobuf/ptypes/timestamp" - "github.com/phoreproject/openbazaar-go/ipfs" - - crypto "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" - peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" - mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" - + "math/big" "strconv" "strings" "time" ipfspath "gx/ipfs/QmQAgv6Gaoe2tQpcabqwKXKChp2MZ7i3UXv9DqTTaxCaTR/go-path" + crypto "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" + peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" "github.com/OpenBazaar/jsonpb" "github.com/OpenBazaar/wallet-interface" hd "github.com/btcsuite/btcutil/hdkeychain" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" -) - -type option struct { - Name string `json:"name"` - Value string `json:"value"` -} - -type shippingOption struct { - Name string `json:"name"` - Service string `json:"service"` -} - -type item struct { - ListingHash string `json:"listingHash"` - Quantity uint64 `json:"quantity"` - Options []option `json:"options"` - Shipping shippingOption `json:"shipping"` - Memo string `json:"memo"` - Coupons []string `json:"coupons"` - PaymentAddress string `json:"paymentAddress"` -} + "github.com/golang/protobuf/ptypes/timestamp" -// PurchaseData - record purchase data -type PurchaseData struct { - ShipTo string `json:"shipTo"` - Address string `json:"address"` - City string `json:"city"` - State string `json:"state"` - PostalCode string `json:"postalCode"` - CountryCode string `json:"countryCode"` - AddressNotes string `json:"addressNotes"` - Moderator string `json:"moderator"` - Items []item `json:"items"` - AlternateContactInfo string `json:"alternateContactInfo"` - RefundAddress *string `json:"refundAddress"` //optional, can be left out of json - PaymentCoin string `json:"paymentCoin"` -} + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" +) const ( // We use this to check to see if the approximate fee to release funds from escrow is greater than 1/4th of the amount @@ -78,66 +41,177 @@ const ( CryptocurrencyPurchasePaymentAddressMaxLength = 512 ) +// GetOrder - provide API response order object by orderID +func (n *OpenBazaarNode) GetOrder(orderID string) (*pb.OrderRespApi, error) { + var ( + err error + isSale bool + contract *pb.RicardianContract + state pb.OrderState + funded bool + records []*wallet.TransactionRecord + read bool + //paymentCoin *repo.CurrencyCode + ) + contract, state, funded, records, read, _, err = n.Datastore.Purchases().GetByOrderId(orderID) + if err != nil { + contract, state, funded, records, read, _, err = n.Datastore.Sales().GetByOrderId(orderID) + if err != nil { + return nil, errors.New("order not found") + } + isSale = true + } + + resp := new(pb.OrderRespApi) + resp.Contract = contract + resp.Funded = funded + resp.Read = read + resp.State = state + + if contract.BuyerOrder.Payment.AmountCurrency != nil { + resp.Contract.BuyerOrder = contract.BuyerOrder + } else { + for i, l := range contract.VendorListings { + repoListing, err := repo.NewListingFromProtobuf(l) + if err != nil { + log.Errorf("failed getting contract listing: %s", err.Error()) + return nil, err + } + normalizedListing, err := repoListing.Normalize() + if err != nil { + log.Errorf("failed converting contract listing to v5 schema: %s", err.Error()) + return nil, err + } + contract.VendorListings[i] = normalizedListing.GetProtobuf() + } + + v5Order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + log.Errorf("failed converting contract buyer order to v5 schema: %s", err.Error()) + return nil, err + } + resp.Contract.BuyerOrder = v5Order + } + + paymentTxs, refundTx, err := n.BuildTransactionRecords(contract, records, state) + if err != nil { + log.Errorf(err.Error()) + return nil, err + } + resp.PaymentAddressTransactions = paymentTxs + resp.RefundAddressTransaction = refundTx + + unread, err := n.Datastore.Chat().GetUnreadCount(orderID) + if err != nil { + log.Errorf(err.Error()) + return nil, err + } + resp.UnreadChatMessages = uint64(unread) + + if isSale { + err = n.Datastore.Sales().MarkAsRead(orderID) + if err != nil { + log.Error(err) + } + } else { + err = n.Datastore.Purchases().MarkAsRead(orderID) + if err != nil { + log.Error(err) + } + } + + return resp, nil +} + // Purchase - add ricardian contract -func (n *OpenBazaarNode) Purchase(data *PurchaseData) (orderID string, paymentAddress string, paymentAmount uint64, vendorOnline bool, err error) { +func (n *OpenBazaarNode) Purchase(data *repo.PurchaseData) (orderID string, paymentAddress string, paymentAmount *repo.CurrencyValue, vendorOnline bool, err error) { + retCurrency := &repo.CurrencyValue{} + defn, err := n.LookupCurrency(data.PaymentCoin) + if err != nil { + return "", "", retCurrency, false, err + } + retCurrency.Currency = defn contract, err := n.createContractWithOrder(data) if err != nil { - return "", "", 0, false, err + return "", "", retCurrency, false, err } wal, err := n.Multiwallet.WalletForCurrencyCode(data.PaymentCoin) if err != nil { - return "", "", 0, false, err + return "", "", retCurrency, false, err } - // Add payment data and send to vendor if data.Moderator != "" { // Moderated payment - contract, err := prepareModeratedOrderContract(data, n, contract, wal) if err != nil { - return "", "", 0, false, err + return "", "", retCurrency, false, err } contract, err = n.SignOrder(contract) if err != nil { - return "", "", 0, false, err + return "", "", retCurrency, false, err } // Send to order vendor merchantResponse, err := n.SendOrder(contract.VendorListings[0].VendorID.PeerID, contract) if err != nil { - return processOfflineModeratedOrder(n, contract) + id, addr, amt, err := processOfflineModeratedOrder(n, contract) + retCurrency.Amount = &amt + return id, addr, retCurrency, false, err } - return processOnlineModeratedOrder(merchantResponse, n, contract) + id, addr, amt, f, err := processOnlineModeratedOrder(merchantResponse, n, contract) + retCurrency.Amount = &amt + return id, addr, retCurrency, f, err } // Direct payment payment := new(pb.Order_Payment) payment.Method = pb.Order_Payment_ADDRESS_REQUEST - payment.Coin = data.PaymentCoin + contract.BuyerOrder.Payment = payment + if contract.VendorListings[0].Metadata.Version >= repo.ListingVersion { + payment.AmountCurrency = &pb.CurrencyDefinition{ + Code: defn.Code.String(), + Divisibility: uint32(defn.Divisibility), + } + } else { + payment.Coin = defn.Code.String() + } // Calculate payment amount total, err := n.CalculateOrderTotal(contract) if err != nil { - return "", "", 0, false, err + return "", "", retCurrency, false, err + } + + if wal.IsDust(*total) { + return "", "", retCurrency, false, ErrSpendAmountIsDust + } + + if contract.VendorListings[0].Metadata.Version >= repo.ListingVersion { + payment.BigAmount = total.String() + } else { + payment.Amount = total.Uint64() } - payment.Amount = total contract, err = n.SignOrder(contract) if err != nil { - return "", "", 0, false, err + return "", "", retCurrency, false, err } // Send to order vendor and request a payment address merchantResponse, err := n.SendOrder(contract.VendorListings[0].VendorID.PeerID, contract) if err != nil { - return processOfflineDirectOrder(n, wal, contract, payment) + id, addr, amount, err := processOfflineDirectOrder(n, wal, contract, payment) + retCurrency.Amount = &amount + return id, addr, retCurrency, false, err } - return processOnlineDirectOrder(merchantResponse, n, wal, contract) + id, addr, amt, f, err := processOnlineDirectOrder(merchantResponse, n, wal, contract) + retCurrency.Amount = &amt + return id, addr, retCurrency, f, err } -func prepareModeratedOrderContract(data *PurchaseData, n *OpenBazaarNode, contract *pb.RicardianContract, wal wallet.Wallet) (*pb.RicardianContract, error) { +func prepareModeratedOrderContract(data *repo.PurchaseData, n *OpenBazaarNode, contract *pb.RicardianContract, wal wallet.Wallet) (*pb.RicardianContract, error) { if data.Moderator == n.IpfsNode.Identity.Pretty() { return nil, errors.New("cannot select self as moderator") } @@ -147,7 +221,6 @@ func prepareModeratedOrderContract(data *PurchaseData, n *OpenBazaarNode, contra payment := new(pb.Order_Payment) payment.Method = pb.Order_Payment_MODERATED payment.Moderator = data.Moderator - payment.Coin = NormalizeCurrencyCode(data.PaymentCoin) profile, err := n.FetchProfile(data.Moderator, true) if err != nil { @@ -161,17 +234,43 @@ func prepareModeratedOrderContract(data *PurchaseData, n *OpenBazaarNode, contra return nil, errors.New("moderator is not capable of moderating this transaction") } - if !currencyInAcceptedCurrenciesList(data.PaymentCoin, profile.ModeratorInfo.AcceptedCurrencies) { + if !n.currencyInAcceptedCurrenciesList(data.PaymentCoin, profile.ModeratorInfo.AcceptedCurrencies) { return nil, errors.New("moderator does not accept our currency") } contract.BuyerOrder.Payment = payment + defn, err := n.LookupCurrency(data.PaymentCoin) + if err != nil { + return nil, errors.New("invalid payment coin") + } + if contract.VendorListings[0].Metadata.Version >= repo.ListingVersion { + payment.AmountCurrency = &pb.CurrencyDefinition{ + Code: defn.Code.String(), + Divisibility: uint32(defn.Divisibility), + } + payment.AmountCurrency = &pb.CurrencyDefinition{ + Code: defn.Code.String(), + Divisibility: uint32(defn.Divisibility), + } + } else { + payment.Coin = defn.Code.String() + } + total, err := n.CalculateOrderTotal(contract) if err != nil { return nil, err } - payment.Amount = total + if contract.VendorListings[0].Metadata.Version >= repo.ListingVersion { + payment.BigAmount = total.String() + } else { + payment.Amount = total.Uint64() + } + contract.BuyerOrder.Payment = payment + fpb := wal.GetFeePerByte(wallet.NORMAL) - if (fpb * EscrowReleaseSize) > (payment.Amount / 4) { + f := new(big.Int).Mul(&fpb, big.NewInt(int64(EscrowReleaseSize))) + t := new(big.Int).Div(total, big.NewInt(4)) + + if f.Cmp(t) > 0 { return nil, errors.New("transaction fee too high for moderated payment") } @@ -211,30 +310,35 @@ func prepareModeratedOrderContract(data *PurchaseData, n *OpenBazaarNode, contra payment.Address = addr.EncodeAddress() payment.RedeemScript = hex.EncodeToString(redeemScript) payment.Chaincode = hex.EncodeToString(chaincode) - contract.BuyerOrder.RefundFee = wal.GetFeePerByte(wallet.NORMAL) + fee := wal.GetFeePerByte(wallet.NORMAL) + if contract.VendorListings[0].Metadata.Version >= repo.ListingVersion { + contract.BuyerOrder.BigRefundFee = fee.String() + } else { + contract.BuyerOrder.RefundFee = fee.Uint64() + } - err = wal.AddWatchedAddress(addr) + err = wal.AddWatchedAddresses(addr) if err != nil { return nil, err } return contract, nil } -func processOnlineDirectOrder(resp *pb.Message, n *OpenBazaarNode, wal wallet.Wallet, contract *pb.RicardianContract) (string, string, uint64, bool, error) { +func processOnlineDirectOrder(resp *pb.Message, n *OpenBazaarNode, wal wallet.Wallet, contract *pb.RicardianContract) (string, string, big.Int, bool, error) { // Vendor responded if resp.MessageType == pb.Message_ERROR { - return "", "", 0, false, extractErrorMessage(resp) + return "", "", *big.NewInt(0), false, extractErrorMessage(resp) } if resp.MessageType != pb.Message_ORDER_CONFIRMATION { - return "", "", 0, false, errors.New("vendor responded to the order with an incorrect message type") + return "", "", *big.NewInt(0), false, errors.New("vendor responded to the order with an incorrect message type") } if resp.Payload == nil { - return "", "", 0, false, errors.New("vendor responded with nil payload") + return "", "", *big.NewInt(0), false, errors.New("vendor responded with nil payload") } rc := new(pb.RicardianContract) err := proto.Unmarshal(resp.Payload.Value, rc) if err != nil { - return "", "", 0, false, errors.New("error parsing the vendor's response") + return "", "", *big.NewInt(0), false, errors.New("error parsing the vendor's response") } contract.VendorOrderConfirmation = rc.VendorOrderConfirmation for _, sig := range rc.Signatures { @@ -244,81 +348,101 @@ func processOnlineDirectOrder(resp *pb.Message, n *OpenBazaarNode, wal wallet.Wa } err = n.ValidateOrderConfirmation(contract, true) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), false, err } addr, err := wal.DecodeAddress(contract.VendorOrderConfirmation.PaymentAddress) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), false, err } - err = wal.AddWatchedAddress(addr) + err = wal.AddWatchedAddresses(addr) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), false, err } orderID, err := n.CalcOrderID(contract.BuyerOrder) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), false, err } err = n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_AWAITING_PAYMENT, false) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), false, err } - return orderID, contract.VendorOrderConfirmation.PaymentAddress, contract.BuyerOrder.Payment.Amount, true, nil + + v5Order, err := repo.ToV5Order(contract.BuyerOrder, nil) + if err != nil { + return "", "", *big.NewInt(0), false, err + } + total, ok := new(big.Int).SetString(v5Order.Payment.BigAmount, 10) + if !ok { + return "", "", *big.NewInt(0), false, errors.New("invalid payment amount") + } + return orderID, contract.VendorOrderConfirmation.PaymentAddress, *total, true, nil } -func processOfflineDirectOrder(n *OpenBazaarNode, wal wallet.Wallet, contract *pb.RicardianContract, payment *pb.Order_Payment) (string, string, uint64, bool, error) { +func processOfflineDirectOrder(n *OpenBazaarNode, wal wallet.Wallet, contract *pb.RicardianContract, payment *pb.Order_Payment) (string, string, big.Int, error) { // Vendor offline // Change payment code to direct + v5Order, err := repo.ToV5Order(contract.BuyerOrder, nil) + if err != nil { + return "", "", *big.NewInt(0), err + } - fpb := wal.GetFeePerByte(wallet.NORMAL) - if (fpb * EscrowReleaseSize) > (payment.Amount / 4) { - return "", "", 0, false, errors.New("transaction fee too high for offline 2of2 multisig payment") + total, ok := new(big.Int).SetString(v5Order.Payment.BigAmount, 10) + if !ok { + return "", "", *big.NewInt(0), errors.New("invalid payment amount") + } + fpb := wal.GetFeePerByte(wallet.SUPER_ECONOMIC) + f := new(big.Int).Mul(&fpb, big.NewInt(int64(EscrowReleaseSize))) + t := new(big.Int).Div(total, big.NewInt(4)) + + if f.Cmp(t) > 0 { + return "", "", *big.NewInt(0), errors.New("transaction fee too high for offline 2of2 multisig payment") } payment.Method = pb.Order_Payment_DIRECT /* Generate a payment address using the first child key derived from the buyer's and vendors's masterPubKeys and a random chaincode. */ chaincode := make([]byte, 32) - _, err := rand.Read(chaincode) + _, err = rand.Read(chaincode) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } vendorKey, err := wal.ChildKey(contract.VendorListings[0].VendorID.Pubkeys.Bitcoin, chaincode, false) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } buyerKey, err := wal.ChildKey(contract.BuyerOrder.BuyerID.Pubkeys.Bitcoin, chaincode, false) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } addr, redeemScript, err := wal.GenerateMultisigScript([]hd.ExtendedKey{*buyerKey, *vendorKey}, 1, time.Duration(0), nil) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } payment.Address = addr.EncodeAddress() payment.RedeemScript = hex.EncodeToString(redeemScript) payment.Chaincode = hex.EncodeToString(chaincode) - err = wal.AddWatchedAddress(addr) + err = wal.AddWatchedAddresses(addr) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } // Remove signature and resign contract.Signatures = []*pb.Signature{contract.Signatures[0]} contract, err = n.SignOrder(contract) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } // Send using offline messaging log.Warningf("Vendor %s is offline, sending offline order message", contract.VendorListings[0].VendorID.PeerID) peerID, err := peer.IDB58Decode(contract.VendorListings[0].VendorID.PeerID) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } any, err := ptypes.MarshalAny(contract) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } m := pb.Message{ MessageType: pb.Message_ORDER, @@ -326,35 +450,39 @@ func processOfflineDirectOrder(n *OpenBazaarNode, wal wallet.Wallet, contract *p } k, err := crypto.UnmarshalPublicKey(contract.VendorListings[0].VendorID.Pubkeys.Identity) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } err = n.SendOfflineMessage(peerID, &k, &m) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } orderID, err := n.CalcOrderID(contract.BuyerOrder) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } err = n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_AWAITING_PAYMENT, false) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } - return orderID, contract.BuyerOrder.Payment.Address, contract.BuyerOrder.Payment.Amount, false, err + return orderID, contract.BuyerOrder.Payment.Address, *total, err } -func processOnlineModeratedOrder(resp *pb.Message, n *OpenBazaarNode, contract *pb.RicardianContract) (string, string, uint64, bool, error) { +func processOnlineModeratedOrder(resp *pb.Message, n *OpenBazaarNode, contract *pb.RicardianContract) (string, string, big.Int, bool, error) { + v5Order, err := repo.ToV5Order(contract.BuyerOrder, nil) + if err != nil { + return "", "", *big.NewInt(0), false, err + } // Vendor responded if resp.MessageType == pb.Message_ERROR { - return "", "", 0, false, extractErrorMessage(resp) + return "", "", *big.NewInt(0), false, extractErrorMessage(resp) } if resp.MessageType != pb.Message_ORDER_CONFIRMATION { - return "", "", 0, false, errors.New("vendor responded to the order with an incorrect message type") + return "", "", *big.NewInt(0), false, errors.New("vendor responded to the order with an incorrect message type") } rc := new(pb.RicardianContract) - err := proto.Unmarshal(resp.Payload.Value, rc) + err = proto.Unmarshal(resp.Payload.Value, rc) if err != nil { - return "", "", 0, false, errors.New("error parsing the vendor's response") + return "", "", *big.NewInt(0), false, errors.New("error parsing the vendor's response") } contract.VendorOrderConfirmation = rc.VendorOrderConfirmation for _, sig := range rc.Signatures { @@ -364,33 +492,41 @@ func processOnlineModeratedOrder(resp *pb.Message, n *OpenBazaarNode, contract * } err = n.ValidateOrderConfirmation(contract, true) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), false, err } if contract.VendorOrderConfirmation.PaymentAddress != contract.BuyerOrder.Payment.Address { - return "", "", 0, false, errors.New("vendor responded with incorrect multisig address") + return "", "", *big.NewInt(0), false, errors.New("vendor responded with incorrect multisig address") } orderID, err := n.CalcOrderID(contract.BuyerOrder) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), false, err } err = n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_AWAITING_PAYMENT, false) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), false, err + } + total, ok := new(big.Int).SetString(v5Order.Payment.BigAmount, 10) + if !ok { + return "", "", *big.NewInt(0), false, errors.New("invalid payment amount") } - return orderID, contract.VendorOrderConfirmation.PaymentAddress, contract.BuyerOrder.Payment.Amount, true, nil + return orderID, contract.VendorOrderConfirmation.PaymentAddress, *total, true, nil } -func processOfflineModeratedOrder(n *OpenBazaarNode, contract *pb.RicardianContract) (string, string, uint64, bool, error) { +func processOfflineModeratedOrder(n *OpenBazaarNode, contract *pb.RicardianContract) (string, string, big.Int, error) { + v5Order, err := repo.ToV5Order(contract.BuyerOrder, nil) + if err != nil { + return "", "", *big.NewInt(0), err + } // Vendor offline // Send using offline messaging log.Warningf("Vendor %s is offline, sending offline order message", contract.VendorListings[0].VendorID.PeerID) peerID, err := peer.IDB58Decode(contract.VendorListings[0].VendorID.PeerID) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } any, err := ptypes.MarshalAny(contract) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } m := pb.Message{ MessageType: pb.Message_ORDER, @@ -398,18 +534,25 @@ func processOfflineModeratedOrder(n *OpenBazaarNode, contract *pb.RicardianContr } k, err := crypto.UnmarshalPublicKey(contract.VendorListings[0].VendorID.Pubkeys.Identity) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } err = n.SendOfflineMessage(peerID, &k, &m) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } orderID, err := n.CalcOrderID(contract.BuyerOrder) if err != nil { - return "", "", 0, false, err + return "", "", *big.NewInt(0), err } - n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_AWAITING_PAYMENT, false) - return orderID, contract.BuyerOrder.Payment.Address, contract.BuyerOrder.Payment.Amount, false, err + err = n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_AWAITING_PAYMENT, false) + if err != nil { + log.Error(err) + } + total, ok := new(big.Int).SetString(v5Order.Payment.BigAmount, 10) + if !ok { + return "", "", *big.NewInt(0), errors.New("invalid payment amount") + } + return orderID, v5Order.Payment.Address, *total, err } func extractErrorMessage(m *pb.Message) error { @@ -428,7 +571,7 @@ func extractErrorMessage(m *pb.Message) error { return errors.New(string(m.Payload.Value)) } -func (n *OpenBazaarNode) createContractWithOrder(data *PurchaseData) (*pb.RicardianContract, error) { +func (n *OpenBazaarNode) createContractWithOrder(data *repo.PurchaseData) (*pb.RicardianContract, error) { var ( contract = new(pb.RicardianContract) order = new(pb.Order) @@ -459,11 +602,11 @@ func (n *OpenBazaarNode) createContractWithOrder(data *PurchaseData) (*pb.Ricard order.RefundAddress = wal.NewAddress(wallet.INTERNAL).EncodeAddress() } - contractIdentity, err := getContractIdentity(n) + nodeID, err := n.GetNodeID() if err != nil { return nil, err } - order.BuyerID = contractIdentity + order.BuyerID = nodeID ts, err := ptypes.TimestampProto(time.Now()) if err != nil { @@ -477,7 +620,7 @@ func (n *OpenBazaarNode) createContractWithOrder(data *PurchaseData) (*pb.Ricard } order.RatingKeys = ratingKeys - addedListings := make(map[string]*pb.Listing) + addedListings := make(map[string]*repo.Listing) for _, item := range data.Items { i := new(pb.Order_Item) @@ -488,9 +631,9 @@ func (n *OpenBazaarNode) createContractWithOrder(data *PurchaseData) (*pb.Ricard So let's check to see if that's the case here and handle it. */ _, exists := addedListings[item.ListingHash] - var listing *pb.Listing + var listing *repo.Listing if !exists { - sl, err := getSignedListing(n, contract, item) + sl, err := getListing(n, contract, item) if err != nil { return nil, err } @@ -500,56 +643,68 @@ func (n *OpenBazaarNode) createContractWithOrder(data *PurchaseData) (*pb.Ricard listing = addedListings[item.ListingHash] } - if !currencyInAcceptedCurrenciesList(data.PaymentCoin, listing.Metadata.AcceptedCurrencies) { + if err != nil || !n.currencyInAcceptedCurrenciesList(data.PaymentCoin, listing.GetAcceptedCurrencies()) { return nil, errors.New("listing does not accept the selected currency") } - ser, err := proto.Marshal(listing) + ser, err := listing.MarshalProtobuf() if err != nil { return nil, err } - listingID, err := EncodeCID(ser) + listingID, err := ipfs.EncodeCID(ser) if err != nil { return nil, err } i.ListingHash = listingID.String() - // If purchasing a listing version >=3 then the Quantity64 field must be used - if listing.Metadata.Version < 3 { - i.Quantity = uint32(item.Quantity) - } else { - i.Quantity64 = item.Quantity + // set quantity according to schema version + // TODO: extract to repo package model + switch listing.GetVersion() { + case 5: + i.BigQuantity = item.Quantity + case 4, 3: + q, ok := new(big.Int).SetString(item.Quantity, 10) + if !ok { + return nil, errors.New("invalid quantity format") + } + i.Quantity64 = q.Uint64() + default: + q, ok := new(big.Int).SetString(item.Quantity, 10) + if !ok { + return nil, errors.New("invalid quantity format") + } + i.Quantity = uint32(q.Uint64()) } i.Memo = item.Memo - if listing.Metadata.ContractType != pb.Listing_Metadata_CRYPTOCURRENCY { + if listing.GetContractType() != pb.Listing_Metadata_CRYPTOCURRENCY.String() { // Remove any duplicate coupons i.CouponCodes = dedupeCoupons(item.Coupons) + } - // Validate the selected options - validatedOptions, err := validateListingOptions(listing.Item.Options, item.Options) - if err != nil { - return nil, err - } - i.Options = validatedOptions + // Validate the selected options + if err := listing.ValidatePurchaseItemOptions(item.Options); err != nil { + return nil, fmt.Errorf("validating purchase options: %s", err.Error()) } + i.Options = item.Options.ToOrderOptionSetProtobuf() // Add shipping to physical listings, and include it for digital and service // listings for legacy compatibility - if listing.Metadata.ContractType == pb.Listing_Metadata_PHYSICAL_GOOD || - listing.Metadata.ContractType == pb.Listing_Metadata_DIGITAL_GOOD || - listing.Metadata.ContractType == pb.Listing_Metadata_SERVICE { + if ct := listing.GetContractType(); ct == pb.Listing_Metadata_PHYSICAL_GOOD.String() || + ct == pb.Listing_Metadata_DIGITAL_GOOD.String() || + ct == pb.Listing_Metadata_SERVICE.String() { i.ShippingOption = &pb.Order_Item_ShippingOption{ Name: item.Shipping.Name, Service: item.Shipping.Service, } - } - - if listing.Metadata.ContractType == pb.Listing_Metadata_CRYPTOCURRENCY { + } else if ct == pb.Listing_Metadata_CRYPTOCURRENCY.String() { i.PaymentAddress = item.PaymentAddress - validateCryptocurrencyOrderItem(i) + err = validateCryptocurrencyOrderItem(i) + if err != nil { + return nil, err + } } order.Items = append(order.Items, i) @@ -565,33 +720,6 @@ func (n *OpenBazaarNode) createContractWithOrder(data *PurchaseData) (*pb.Ricard return contract, nil } -func validateListingOptions(listingItemOptions []*pb.Listing_Item_Option, itemOptions []option) ([]*pb.Order_Item_Option, error) { - var validatedListingOptions []*pb.Order_Item_Option - listingOptions := make(map[string]*pb.Listing_Item_Option) - for _, opt := range listingItemOptions { - listingOptions[strings.ToLower(opt.Name)] = opt - } - for _, uopt := range itemOptions { - _, ok := listingOptions[strings.ToLower(uopt.Name)] - if !ok { - return nil, errors.New("selected variant not in listing") - } - delete(listingOptions, strings.ToLower(uopt.Name)) - } - if len(listingOptions) > 0 { - return nil, errors.New("Not all options were selected") - } - - for _, option := range itemOptions { - o := &pb.Order_Item_Option{ - Name: option.Name, - Value: option.Value, - } - validatedListingOptions = append(validatedListingOptions, o) - } - return validatedListingOptions, nil -} - func dedupeCoupons(itemCoupons []string) []string { couponMap := make(map[string]bool) var coupons []string @@ -604,38 +732,36 @@ func dedupeCoupons(itemCoupons []string) []string { return coupons } -func getSignedListing(n *OpenBazaarNode, contract *pb.RicardianContract, item item) (*pb.Listing, error) { +func getListing(n *OpenBazaarNode, contract *pb.RicardianContract, item repo.Item) (*repo.Listing, error) { // Let's fetch the listing, should be cached b, err := ipfs.Cat(n.IpfsNode, item.ListingHash, time.Minute) if err != nil { return nil, err } - sl := new(pb.SignedListing) - err = jsonpb.UnmarshalString(string(b), sl) + + //err = jsonpb.UnmarshalString(string(b), sl) + sl, err := repo.UnmarshalJSONSignedListing(b) if err != nil { return nil, err } - if err := validateVersionNumber(sl.Listing); err != nil { - return nil, err + if sl.GetVersion() > repo.ListingVersion { + return nil, errors.New("unknown listing version, must upgrade to purchase this listing") } - if err := validateVendorID(sl.Listing); err != nil { - return nil, err + if err := sl.GetListing().GetVendorID().Valid(); err != nil { + return nil, fmt.Errorf("invalid vendor info: %s", err.Error()) } - if err := n.validateListing(sl.Listing, n.TestNetworkEnabled() || n.RegressionNetworkEnabled()); err != nil { - return nil, fmt.Errorf("listing failed to validate, reason: %q", err.Error()) + if err := sl.ValidateListing(n.TestNetworkEnabled() || n.RegressionNetworkEnabled()); err != nil { + return nil, fmt.Errorf("validating listing (%s): %s", sl.GetSlug(), err.Error()) } - if err := verifySignaturesOnListing(sl); err != nil { + if err := sl.VerifySignature(); err != nil { return nil, err } - contract.VendorListings = append(contract.VendorListings, sl.Listing) - s := new(pb.Signature) - s.Section = pb.Signature_LISTING - s.SignatureBytes = sl.Signature - contract.Signatures = append(contract.Signatures, s) - return sl.Listing, nil + contract.VendorListings = append(contract.VendorListings, sl.GetListing().GetProtobuf()) + contract.Signatures = append(contract.Signatures, sl.GetListingSigProtobuf()) + return sl.GetListing(), nil } -func getRatingKeysForOrder(data *PurchaseData, n *OpenBazaarNode, ts *timestamp.Timestamp) ([][]byte, error) { +func getRatingKeysForOrder(data *repo.PurchaseData, n *OpenBazaarNode, ts *timestamp.Timestamp) ([][]byte, error) { var ratingKeys [][]byte for range data.Items { // FIXME: bug here. This should use a different key for each item. This code doesn't look like it will do that. @@ -657,51 +783,26 @@ func getRatingKeysForOrder(data *PurchaseData, n *OpenBazaarNode, ts *timestamp. return ratingKeys, nil } -func getContractIdentity(n *OpenBazaarNode) (*pb.ID, error) { - id := new(pb.ID) - profile, err := n.GetProfile() - if err == nil { - id.Handle = profile.Handle - } - - id.PeerID = n.IpfsNode.Identity.Pretty() - pubkey, err := n.IpfsNode.PrivateKey.GetPublic().Bytes() +func (n *OpenBazaarNode) currencyInAcceptedCurrenciesList(checkCode string, acceptedCurrencies []string) bool { + checkDef, err := n.LookupCurrency(checkCode) if err != nil { - return nil, err - } - keys := new(pb.ID_Pubkeys) - keys.Identity = pubkey - ecPubKey, err := n.MasterPrivateKey.ECPubKey() - if err != nil { - return nil, err - } - keys.Bitcoin = ecPubKey.SerializeCompressed() - id.Pubkeys = keys - // Sign the PeerID with the Bitcoin key - ecPrivKey, err := n.MasterPrivateKey.ECPrivKey() - if err != nil { - return nil, err - } - sig, err := ecPrivKey.Sign([]byte(id.PeerID)) - if err != nil { - return nil, err + return false } - id.BitcoinSig = sig.Serialize() - return id, nil -} - -func currencyInAcceptedCurrenciesList(currencyCode string, acceptedCurrencies []string) bool { for _, cc := range acceptedCurrencies { - if NormalizeCurrencyCode(cc) == NormalizeCurrencyCode(currencyCode) { + acceptedDef, err := n.LookupCurrency(cc) + if err != nil { + continue + } + if checkDef.Equal(acceptedDef) { return true } } return false } -func containsPhysicalGood(addedListings map[string]*pb.Listing) bool { +func containsPhysicalGood(addedListings map[string]*repo.Listing) bool { for _, listing := range addedListings { - if listing.Metadata.ContractType == pb.Listing_Metadata_PHYSICAL_GOOD { + if listing.GetContractType() == pb.Listing_Metadata_PHYSICAL_GOOD.String() { return true } } @@ -724,15 +825,15 @@ func validatePhysicalPurchaseOrder(contract *pb.RicardianContract) error { func validateCryptocurrencyOrderItem(item *pb.Order_Item) error { if len(item.Options) > 0 { - return ErrCryptocurrencyPurchaseIllegalField("item.options") + return repo.ErrCryptocurrencyPurchaseIllegalField("item.options") } if len(item.CouponCodes) > 0 { - return ErrCryptocurrencyPurchaseIllegalField("item.couponCodes") + return repo.ErrCryptocurrencyPurchaseIllegalField("item.couponCodes") } if item.PaymentAddress == "" { return ErrCryptocurrencyPurchasePaymentAddressRequired } - if len(item.PaymentAddress) < CryptocurrencyPurchasePaymentAddressMaxLength { + if len(item.PaymentAddress) > CryptocurrencyPurchasePaymentAddressMaxLength { return ErrCryptocurrencyPurchasePaymentAddressTooLong } @@ -740,36 +841,269 @@ func validateCryptocurrencyOrderItem(item *pb.Order_Item) error { } // EstimateOrderTotal - returns order total in satoshi/wei -func (n *OpenBazaarNode) EstimateOrderTotal(data *PurchaseData) (uint64, error) { +func (n *OpenBazaarNode) EstimateOrderTotal(data *repo.PurchaseData) (*big.Int, error) { contract, err := n.createContractWithOrder(data) if err != nil { - return 0, err + return big.NewInt(0), err } payment := new(pb.Order_Payment) - payment.Coin = data.PaymentCoin + defn, err := n.LookupCurrency(data.PaymentCoin) + if err != nil { + return big.NewInt(0), errors.New("invalid payment coin") + } + payment.AmountCurrency = &pb.CurrencyDefinition{ + Code: defn.Code.String(), + Divisibility: uint32(defn.Divisibility), + } contract.BuyerOrder.Payment = payment return n.CalculateOrderTotal(contract) } +// CheckoutBreakdown - returns order total and breakdown of charges +func (n *OpenBazaarNode) CheckoutBreakdown(data *repo.PurchaseData) (repo.CheckoutBreakdown, error) { + var checkoutBreakdown repo.CheckoutBreakdown + emptyCheckoutBreakdown := repo.CheckoutBreakdown{} + + cc, err := n.ReserveCurrencyConverter() + if err != nil { + return emptyCheckoutBreakdown, fmt.Errorf("preparing reserve currency converter: %s", err.Error()) + } + + contract, err := n.createContractWithOrder(data) + if err != nil { + return emptyCheckoutBreakdown, err + } + payment := new(pb.Order_Payment) + defn, err := n.LookupCurrency(data.PaymentCoin) + if err != nil { + return emptyCheckoutBreakdown, errors.New("invalid payment coin") + } + payment.AmountCurrency = &pb.CurrencyDefinition{ + Code: defn.Code.String(), + Divisibility: uint32(defn.Divisibility), + } + contract.BuyerOrder.Payment = payment + + // Get base price of item + v5Order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return emptyCheckoutBreakdown, err + } + firstItem := v5Order.Items[0] + + nrl, err := GetNormalizedListing(firstItem.ListingHash, contract) + if err != nil { + return emptyCheckoutBreakdown, err + } + + itemSurcharge, err := GetItemSurchargeAmount(nrl, firstItem.Options) + if err != nil { + return emptyCheckoutBreakdown, err + } + + itemOriginAmt, err := GetOriginalAmount(nrl, firstItem) + if err != nil { + return emptyCheckoutBreakdown, err + } + + // Calculate total items + totalQuantity := new(big.Int).SetInt64(0) + for _, i := range data.Items { + iCount, ok := new(big.Int).SetString(i.Quantity, 10) + if !ok { + return emptyCheckoutBreakdown, err + } + totalQuantity = totalQuantity.Add(totalQuantity, iCount) + } + + // Calculate total price for the order + totalPrice, err := n.CalculateOrderTotal(contract) + if err != nil { + return emptyCheckoutBreakdown, err + } + + finalBasePrice, _, err := itemOriginAmt.ConvertUsingProtobufDef(v5Order.Payment.AmountCurrency, cc) + if err != nil { + return emptyCheckoutBreakdown, err + } + + // Coupon Codes Discount + listingCurDef, err := n.LookupCurrency(v5Order.Payment.AmountCurrency.Code) + if err != nil { + return emptyCheckoutBreakdown, err + } + totalSurcharge := new(big.Int).Mul(itemSurcharge, totalQuantity) + cv := &repo.CurrencyValue{ + Amount: new(big.Int).Add(itemSurcharge, itemOriginAmt.Amount), + Currency: listingCurDef, + } + couponDiscount, err := GetTotalCouponCodeDiscount(nrl, firstItem.CouponCodes, cv) + if err != nil { + return emptyCheckoutBreakdown, err + } + couponDiscount = couponDiscount.Mul(couponDiscount, new(big.Int).SetInt64(-1)) + couponCurrencyValue := repo.NewCurrencyValueFromBigInt(couponDiscount, listingCurDef) + + finalCouponDiscount, _, err := couponCurrencyValue.ConvertUsingProtobufDef(v5Order.Payment.AmountCurrency, cc) + if err != nil { + return emptyCheckoutBreakdown, err + } + + optionCurrencyValue := repo.NewCurrencyValueFromBigInt(totalSurcharge, listingCurDef) + + finalOptionSurcharge, _, err := optionCurrencyValue.ConvertUsingProtobufDef(v5Order.Payment.AmountCurrency, cc) + if err != nil { + return emptyCheckoutBreakdown, err + } + + // Shipping Costs + isPhysicalGood := false + var physicalGoods = make(map[string]*repo.Listing) + + if nrl.GetContractType() == pb.Listing_Metadata_PHYSICAL_GOOD.String() { + isPhysicalGood = true + physicalGoods[firstItem.ListingHash] = nrl + } + + shippingTotal := new(big.Int).SetInt64(0) + if isPhysicalGood { + shippingTotal, err = getPretaxShippingCost(v5Order, nrl) + if err != nil { + return emptyCheckoutBreakdown, err + } + } + // Convert to final currency + originalPrice, err := nrl.GetPrice() + if err != nil { + return emptyCheckoutBreakdown, err + } + originalPrice.Amount = shippingTotal + + finalShippingTotal, _, err := originalPrice.ConvertUsingProtobufDef(v5Order.Payment.AmountCurrency, cc) + if err != nil { + return emptyCheckoutBreakdown, err + } + + // Taxes + taxesTotal := new(big.Int).SetInt64(0) + for _, tax := range nrl.GetProtobuf().Taxes { + for _, taxRegion := range tax.TaxRegions { + if contract.BuyerOrder.Shipping.Country == taxRegion { + factor := toHundredths(tax.Percentage) + + var taxes *big.Int + amountToTax := new(big.Int).SetInt64(0) + + totalBasePrice := new(big.Int).Mul(itemOriginAmt.Amount, totalQuantity) + amountToTax.Add(totalBasePrice, totalSurcharge) + amountToTax.Sub(amountToTax, couponDiscount) + + if tax.TaxShipping { + amountToTax.Add(amountToTax, shippingTotal) + } + + taxes, _ = new(big.Float).Mul(new(big.Float).SetInt(amountToTax), factor).Int(nil) + taxesTotal = new(big.Int).Add(taxesTotal, taxes) + + break + } + } + } + taxesCurrencyValue := repo.NewCurrencyValueFromBigInt(taxesTotal, listingCurDef) + finalTaxesTotal, _, err := taxesCurrencyValue.ConvertUsingProtobufDef(v5Order.Payment.AmountCurrency, cc) + if err != nil { + return emptyCheckoutBreakdown, err + } + + checkoutBreakdown.Tax = finalTaxesTotal.Amount.String() + checkoutBreakdown.ShippingPrice = finalShippingTotal.Amount.String() + checkoutBreakdown.Coupon = finalCouponDiscount.Amount.String() + checkoutBreakdown.OptionSurcharge = finalOptionSurcharge.Amount.String() + checkoutBreakdown.BasePrice = finalBasePrice.Amount.String() + checkoutBreakdown.TotalPrice = totalPrice.String() + checkoutBreakdown.Quantity = totalQuantity.String() + + return checkoutBreakdown, nil +} + +func getPretaxShippingCost(v5Order *pb.Order, nrl *repo.Listing) (*big.Int, error) { + pretaxShippingCost := new(big.Int).SetInt64(0) + + for _, item := range v5Order.Items { + //shippingOption := item.ShippingOption + + itemQuantity, ok := new(big.Int).SetString(item.BigQuantity, 10) + if !ok { + return new(big.Int).SetInt64(0), errors.New("bad bigQuantity") + } + listingShippingOptions, err := nrl.GetShippingOptions() + if err != nil { + return new(big.Int).SetInt64(0), err + } + + for _, listingShippingOption := range listingShippingOptions { + if inShippingRegions(v5Order.Shipping.Country, listingShippingOption.Regions) { + for _, listingService := range listingShippingOption.Services { + if item.ShippingOption.Service == listingService.Name { + servicePrice, _ := new(big.Int).SetString(listingService.BigPrice, 10) + if err != nil { + return new(big.Int).SetInt64(0), err + } + additionalItemPrice, _ := new(big.Int).SetString(listingService.BigAdditionalItemPrice, 10) + if err != nil { + return new(big.Int).SetInt64(0), err + } + + pretaxShippingCost.Add(pretaxShippingCost, servicePrice) + + if itemQuantity.Cmp(new(big.Int).SetInt64(1)) == 1 { + // Add additional item price for each quantity over 1 + additionalCost := new(big.Int).Mul(additionalItemPrice, itemQuantity) + pretaxShippingCost.Add(pretaxShippingCost, additionalCost) + } + + } + } + } + } + } + + return pretaxShippingCost, nil +} + +func inShippingRegions(needle pb.CountryCode, regions []pb.CountryCode) bool { + for _, region := range regions { + if needle == region || region == pb.CountryCode_ALL { + return true + } + } + return false +} + // CancelOfflineOrder - cancel order func (n *OpenBazaarNode) CancelOfflineOrder(contract *pb.RicardianContract, records []*wallet.TransactionRecord) error { + v5Order, err := repo.ToV5Order(contract.BuyerOrder, nil) + if err != nil { + return err + } + orderID, err := n.CalcOrderID(contract.BuyerOrder) if err != nil { return err } - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + wal, err := n.Multiwallet.WalletForCurrencyCode(v5Order.Payment.AmountCurrency.Code) if err != nil { return err } // Sweep the temp address into our wallet var utxos []wallet.TransactionInput for _, r := range records { - if !r.Spent && r.Value > 0 { + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { addr, err := wal.DecodeAddress(r.Address) if err != nil { return err } - outpointHash, err := hex.DecodeString(r.Txid) + outpointHash, err := hex.DecodeString(strings.TrimPrefix(r.Txid, "0x")) if err != nil { return fmt.Errorf("decoding transaction hash: %s", err.Error()) } @@ -787,12 +1121,11 @@ func (n *OpenBazaarNode) CancelOfflineOrder(contract *pb.RicardianContract, reco return errors.New("cannot cancel order because utxo has already been spent") } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincode, err := hex.DecodeString(v5Order.Payment.Chaincode) if err != nil { return err } - mPrivKey := n.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := n.MasterPrivateKey.ECPrivKey() if err != nil { return err } @@ -800,11 +1133,11 @@ func (n *OpenBazaarNode) CancelOfflineOrder(contract *pb.RicardianContract, reco if err != nil { return err } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(v5Order.Payment.RedeemScript) if err != nil { return err } - refundAddress, err := wal.DecodeAddress(contract.BuyerOrder.RefundAddress) + refundAddress, err := wal.DecodeAddress(v5Order.RefundAddress) if err != nil { return err } @@ -816,7 +1149,10 @@ func (n *OpenBazaarNode) CancelOfflineOrder(contract *pb.RicardianContract, reco if err != nil { return err } - n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_CANCELED, true) + err = n.Datastore.Purchases().Put(orderID, *contract, pb.OrderState_CANCELED, true) + if err != nil { + log.Error(err) + } return nil } @@ -826,160 +1162,241 @@ func (n *OpenBazaarNode) CalcOrderID(order *pb.Order) (string, error) { if err != nil { return "", err } - id, err := EncodeMultihash(ser) + id, err := ipfs.EncodeMultihash(ser) if err != nil { return "", err } return id.B58String(), nil } -// CalculateOrderTotal - calculate the total in satoshi/wei -func (n *OpenBazaarNode) CalculateOrderTotal(contract *pb.RicardianContract) (uint64, error) { - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) +func (n *OpenBazaarNode) CalculateOrderTotal(contract *pb.RicardianContract) (*big.Int, error) { + var ( + total = big.NewInt(0) + physicalGoods = make(map[string]*repo.Listing) + v5Order, err = repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + ) if err != nil { - return 0, err + return big.NewInt(0), fmt.Errorf("normalizing buyer order: %s", err.Error()) } - if wal.ExchangeRates() != nil { - wal.ExchangeRates().GetLatestRate("") // Refresh the exchange rates - } - - var total uint64 - physicalGoods := make(map[string]*pb.Listing) - - // Calculate the price of each item - for _, item := range contract.BuyerOrder.Items { - var ( - satoshis uint64 - itemTotal uint64 - itemQuantity uint64 - ) + for _, item := range v5Order.Items { + var itemOriginAmt *repo.CurrencyValue l, err := ParseContractForListing(item.ListingHash, contract) if err != nil { - return 0, fmt.Errorf("listing not found in contract for item %s", item.ListingHash) + return big.NewInt(0), fmt.Errorf("listing not found in contract for item %s", item.ListingHash) } - // Continue using the old 32-bit quantity field for all listings less than version 3 - itemQuantity = GetOrderQuantity(l, item) + rl, err := repo.NewListingFromProtobuf(l) + if err != nil { + return big.NewInt(0), err + } - if l.Metadata.ContractType == pb.Listing_Metadata_PHYSICAL_GOOD { - physicalGoods[item.ListingHash] = l + nrl, err := rl.Normalize() + if err != nil { + return big.NewInt(0), fmt.Errorf("normalize legacy listing: %s", err.Error()) } - if l.Metadata.Format == pb.Listing_Metadata_MARKET_PRICE { // MARKET + CRYPTO - satoshis, err = n.getMarketPriceInSatoshis(contract.BuyerOrder.Payment.Coin, l.Metadata.CoinType, itemQuantity) - satoshis += uint64(float32(satoshis) * l.Metadata.PriceModifier / 100.0) - itemQuantity = 1 - } else if l.Metadata.ContractType == pb.Listing_Metadata_CRYPTOCURRENCY { // FIXED + CRYPTO - satoshis += l.Item.Price * uint64(float64(itemQuantity)/float64(l.Metadata.CoinDivisibility)) - itemQuantity = 1 - } else { // FIXED + NO CRYPTO - satoshis, err = n.getPriceInSatoshi(contract.BuyerOrder.Payment.Coin, l.Metadata.PricingCurrency, l.Item.Price) + // keep track of physical listings for shipping caluclation + if nrl.GetContractType() == pb.Listing_Metadata_PHYSICAL_GOOD.String() { + physicalGoods[item.ListingHash] = nrl } + + // calculate base amount + itemOriginAmt, err = GetOriginalAmount(nrl, item) if err != nil { - return 0, err + return big.NewInt(0), err } - itemTotal += satoshis - selectedSku, err := GetSelectedSku(l, item.Options) + + // apply surcharges + itemSurcharge, err := GetItemSurchargeAmount(nrl, item.Options) if err != nil { - return 0, err - } - var skuExists bool - for i, sku := range l.Item.Skus { - if selectedSku == i { - skuExists = true - if sku.Surcharge != 0 { - surcharge := uint64(sku.Surcharge) - if sku.Surcharge < 0 { - surcharge = uint64(-sku.Surcharge) - } - satoshis, err := n.getPriceInSatoshi(contract.BuyerOrder.Payment.Coin, l.Metadata.PricingCurrency, surcharge) - if err != nil { - return 0, err - } - if sku.Surcharge < 0 { - itemTotal -= satoshis - } else { - itemTotal += satoshis - } - } - if !skuExists { - return 0, errors.New("selected variant not found in listing") - } - break - } + return big.NewInt(0), err } - // Subtract any coupons - for _, couponCode := range item.CouponCodes { - for _, vendorCoupon := range l.Coupons { - id, err := EncodeMultihash([]byte(couponCode)) - if err != nil { - return 0, err - } - if id.B58String() == vendorCoupon.GetHash() { - if discount := vendorCoupon.GetPriceDiscount(); discount > 0 { - // TODO check for CRYPTO + FIX PRICE - satoshis, err := n.getPriceInSatoshi(contract.BuyerOrder.Payment.Coin, l.Metadata.PricingCurrency, discount) - if err != nil { - return 0, err - } - itemTotal -= satoshis - } else if discount := vendorCoupon.GetPercentDiscount(); discount > 0 { - itemTotal -= uint64(float32(itemTotal) * (discount / 100)) - } - } - } + itemOriginAmt = itemOriginAmt.AddBigInt(itemSurcharge) + + // apply coupon discounts + totalDiscount, err := GetTotalCouponCodeDiscount(nrl, item.CouponCodes, itemOriginAmt) + if err != nil { + return big.NewInt(0), err } - // Apply tax - for _, tax := range l.Taxes { + itemOriginAmt = itemOriginAmt.AddBigInt(totalDiscount) + + // apply taxes + for _, tax := range nrl.GetProtobuf().Taxes { for _, taxRegion := range tax.TaxRegions { if contract.BuyerOrder.Shipping.Country == taxRegion { - itemTotal += uint64(float32(itemTotal) * (tax.Percentage / 100)) + itemOriginAmt = itemOriginAmt.AddBigFloatProduct(toHundredths(tax.Percentage)) break } } } - itemTotal *= itemQuantity - total += itemTotal + + // apply requested quantity + if !(nrl.GetContractType() == pb.Listing_Metadata_CRYPTOCURRENCY.String() && + nrl.GetFormat() == pb.Listing_Metadata_MARKET_PRICE.String()) { + if itemQuantity := GetOrderQuantity(nrl.GetProtobuf(), item); itemQuantity.Cmp(big.NewInt(0)) > 0 { + itemOriginAmt = itemOriginAmt.MulBigInt(itemQuantity) + } else { + log.Debugf("missing quantity for order, assuming quantity 1") + } + } + + // convert subtotal to final currency + cc, err := n.ReserveCurrencyConverter() + if err != nil { + return big.NewInt(0), fmt.Errorf("preparing reserve currency converter: %s", err.Error()) + } + + finalItemAmount, _, err := itemOriginAmt.ConvertUsingProtobufDef(v5Order.Payment.AmountCurrency, cc) + if err != nil { + return big.NewInt(0), err + } + + // add to total + total.Add(total, finalItemAmount.AmountBigInt()) } shippingTotal, err := n.calculateShippingTotalForListings(contract, physicalGoods) if err != nil { - return 0, err + return big.NewInt(0), err } - total += shippingTotal + total.Add(total, shippingTotal) return total, nil } -func (n *OpenBazaarNode) calculateShippingTotalForListings(contract *pb.RicardianContract, listings map[string]*pb.Listing) (uint64, error) { +func GetTotalCouponCodeDiscount(nrl *repo.Listing, couponCodes []string, itemAmount *repo.CurrencyValue) (*big.Int, error) { + totalCouponCodeDiscount := big.NewInt(0) + + for _, couponCode := range couponCodes { + id, err := ipfs.EncodeMultihash([]byte(couponCode)) + if err != nil { + return big.NewInt(0), err + } + coupons := nrl.GetProtobuf().Coupons + for _, vendorCoupon := range coupons { + if id.B58String() == vendorCoupon.GetHash() { + if disc, ok := new(big.Int).SetString(vendorCoupon.GetBigPriceDiscount(), 10); ok && disc.Cmp(big.NewInt(0)) > 0 { + // apply fixed discount + totalCouponCodeDiscount.Sub(totalCouponCodeDiscount, disc) + } else if discountF := vendorCoupon.GetPercentDiscount(); discountF > 0 { + // apply percentage discount + disc := itemAmount.AddBigFloatProduct(toHundredths(-discountF)) + totalCouponCodeDiscount.Sub(totalCouponCodeDiscount, new(big.Int).Sub(itemAmount.Amount, disc.Amount)) + } + } + } + } + return totalCouponCodeDiscount, nil +} + +func GetItemSurchargeAmount(nrl *repo.Listing, options []*pb.Order_Item_Option) (*big.Int, error) { + itemSurchargeAmount := big.NewInt(0) + + selectedSku, err := GetSelectedSku(nrl.GetProtobuf(), options) + if err != nil { + return big.NewInt(0), err + } + skus, err := nrl.GetSkus() + if err != nil { + return big.NewInt(0), err + } + for i, sku := range skus { + if selectedSku == i { + // surcharge may be positive or negative + surcharge, ok := new(big.Int).SetString(sku.BigSurcharge, 10) + if ok && surcharge.Cmp(big.NewInt(0)) != 0 { + itemSurchargeAmount.Add(itemSurchargeAmount, surcharge) + } + break + } + } + return itemSurchargeAmount, nil +} +func toHundredths(f float32) *big.Float { + return new(big.Float).Mul(big.NewFloat(float64(f)), big.NewFloat(0.01)) +} + +func GetNormalizedListing(listingHash string, contract *pb.RicardianContract) (*repo.Listing, error) { + l, err := ParseContractForListing(listingHash, contract) + if err != nil { + return nil, fmt.Errorf("listing not found in contract for item %s", listingHash) + } + + rl, err := repo.NewListingFromProtobuf(l) + if err != nil { + return nil, err + } + + nrl, err := rl.Normalize() + if err != nil { + return nil, fmt.Errorf("normalize legacy listing: %s", err.Error()) + } + + return nrl, nil +} + +func GetOriginalAmount(nrl *repo.Listing, item *pb.Order_Item) (*repo.CurrencyValue, error) { + var itemOriginAmt *repo.CurrencyValue + + if nrl.GetContractType() == pb.Listing_Metadata_CRYPTOCURRENCY.String() && + nrl.GetFormat() == pb.Listing_Metadata_MARKET_PRICE.String() { + var originDef = repo.NewUnknownCryptoDefinition(nrl.GetCryptoCurrencyCode(), uint(nrl.GetCryptoDivisibility())) + itemOriginAmt = repo.NewCurrencyValueFromBigInt(GetOrderQuantity(nrl.GetProtobuf(), item), originDef) + + if priceModifier := nrl.GetPriceModifier(); priceModifier != 0 { + itemOriginAmt = itemOriginAmt.AddBigFloatProduct(toHundredths(priceModifier)) + } + } else if nrl.GetContractType() == pb.Listing_Metadata_CRYPTOCURRENCY.String() { // FIXED + CRYPTO + oAmt, err := nrl.GetPrice() + if err != nil { + return oAmt, err + } + + itemOriginAmt = oAmt.MulBigInt(GetOrderQuantity(nrl.GetProtobuf(), item)) + } else { + oAmt, err := nrl.GetPrice() + if err != nil { + return nil, err + } + itemOriginAmt = oAmt + } + return itemOriginAmt, nil +} + +func (n *OpenBazaarNode) calculateShippingTotalForListings(contract *pb.RicardianContract, listings map[string]*repo.Listing) (*big.Int, error) { type itemShipping struct { - primary uint64 - secondary uint64 + primary *big.Int + secondary *big.Int quantity uint64 shippingTaxPercentage float32 version uint32 } var ( + v5Order, err = repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) is []itemShipping - shippingTotal uint64 + shippingTotal *big.Int ) + if err != nil { + return big.NewInt(0), fmt.Errorf("normalizing buyer order: %s", err.Error()) + } // First loop through to validate and filter out non-physical items - for _, item := range contract.BuyerOrder.Items { - listing, ok := listings[item.ListingHash] + for _, item := range v5Order.Items { + rl, ok := listings[item.ListingHash] if !ok { continue } - // Check selected option exists - shippingOptions := make(map[string]*pb.Listing_ShippingOption) - for _, so := range listing.ShippingOptions { - shippingOptions[strings.ToLower(so.Name)] = so + // Check if physical good + if rl.GetContractType() != pb.Listing_Metadata_PHYSICAL_GOOD.String() { + continue } - option, ok := shippingOptions[strings.ToLower(item.ShippingOption.Name)] - if !ok { - return 0, errors.New("shipping option not found in listing") + + // Check selected option exists + option, err := getShippingOption(rl, item.ShippingOption.Name) + if err != nil { + return big.NewInt(0), err } if option.Type == pb.Listing_ShippingOption_LOCAL_PICKUP { @@ -991,10 +1408,15 @@ func (n *OpenBazaarNode) calculateShippingTotalForListings(contract *pb.Ricardia for _, country := range option.Regions { regions[country] = true } - _, shipsToMe := regions[contract.BuyerOrder.Shipping.Country] + _, shipsToMe := regions[v5Order.Shipping.Country] _, shipsToAll := regions[pb.CountryCode_ALL] if !shipsToMe && !shipsToAll { - return 0, errors.New("listing does ship to selected country") + return big.NewInt(0), errors.New("listing does ship to selected country") + } + + cc, err := n.ReserveCurrencyConverter() + if err != nil { + return big.NewInt(0), fmt.Errorf("preparing reserve currency converter: %s", err.Error()) } // Check service exists @@ -1004,167 +1426,121 @@ func (n *OpenBazaarNode) calculateShippingTotalForListings(contract *pb.Ricardia } service, ok := services[strings.ToLower(item.ShippingOption.Service)] if !ok { - return 0, errors.New("shipping service not found in listing") + return big.NewInt(0), errors.New("shipping service not found in listing") } - shippingSatoshi, err := n.getPriceInSatoshi(contract.BuyerOrder.Payment.Coin, listing.Metadata.PricingCurrency, service.Price) + servicePrice, err := repo.NewCurrencyValueFromProtobuf(service.BigPrice, rl.GetProtobuf().Item.PriceCurrency) if err != nil { - return 0, err + return big.NewInt(0), fmt.Errorf("parsing service price (%v): %s", service.Name, err.Error()) + } + convertedShippingPrice, _, err := servicePrice.ConvertUsingProtobufDef(v5Order.Payment.AmountCurrency, cc) + if err != nil { + return big.NewInt(0), fmt.Errorf("converting service price (%s): %s", service.Name, err.Error()) } - var secondarySatoshi uint64 - if service.AdditionalItemPrice > 0 { - secondarySatoshi, err = n.getPriceInSatoshi(contract.BuyerOrder.Payment.Coin, listing.Metadata.PricingCurrency, service.AdditionalItemPrice) + auxServicePrice, err := repo.NewCurrencyValueFromProtobuf(service.BigAdditionalItemPrice, rl.GetProtobuf().Item.PriceCurrency) + if err != nil { + return big.NewInt(0), fmt.Errorf("parsing aux service price (%v): %s", service.Name, err.Error()) + } + var convertedAuxPrice = repo.NewCurrencyValueFromBigInt(big.NewInt(0), convertedShippingPrice.Currency) + if auxServicePrice.IsPositive() { + finalAux, _, err := auxServicePrice.ConvertUsingProtobufDef(v5Order.Payment.AmountCurrency, cc) if err != nil { - return 0, err + return big.NewInt(0), fmt.Errorf("converting aux service price (%s): %s", service.Name, err.Error()) } + convertedAuxPrice = finalAux } // Calculate tax percentage var shippingTaxPercentage float32 - for _, tax := range listing.Taxes { + for _, tax := range rl.GetProtobuf().Taxes { regions := make(map[pb.CountryCode]bool) for _, taxRegion := range tax.TaxRegions { regions[taxRegion] = true } - _, ok := regions[contract.BuyerOrder.Shipping.Country] + _, ok := regions[v5Order.Shipping.Country] if ok && tax.TaxShipping { shippingTaxPercentage = tax.Percentage / 100 } } + var qty uint64 + if q := quantityForItem(rl.GetVersion(), item); q.IsUint64() { + qty = q.Uint64() + } else { + orderID, _ := n.CalcOrderID(contract.BuyerOrder) + log.Warningf("unable to detect quantity in contract (%s)", orderID) + } is = append(is, itemShipping{ - primary: shippingSatoshi, - secondary: secondarySatoshi, - quantity: quantityForItem(listing.Metadata.Version, item), + primary: convertedShippingPrice.AmountBigInt(), + secondary: convertedAuxPrice.AmountBigInt(), + quantity: qty, shippingTaxPercentage: shippingTaxPercentage, - version: listing.Metadata.Version, + version: rl.GetVersion(), }) } if len(is) == 0 { - return 0, nil + return big.NewInt(0), nil } if len(is) == 1 { - shippingTotal = is[0].primary * uint64(((1+is[0].shippingTaxPercentage)*100)+.5) / 100 + s := int64(((1 + is[0].shippingTaxPercentage) * 100) + .5) + shippingTotalPrimary := new(big.Int).Mul(is[0].primary, big.NewInt(s)) + stp, _ := new(big.Float).Mul(big.NewFloat(0.01), new(big.Float).SetInt(shippingTotalPrimary)).Int(nil) + shippingTotal = stp if is[0].quantity > 1 { if is[0].version == 1 { - shippingTotal += (is[0].primary * uint64(((1+is[0].shippingTaxPercentage)*100)+.5) / 100) * (is[0].quantity - 1) + t1 := new(big.Int).Mul(stp, big.NewInt(int64(is[0].quantity-1))) + shippingTotal = new(big.Int).Add(stp, t1) } else if is[0].version >= 2 { - shippingTotal += (is[0].secondary * uint64(((1+is[0].shippingTaxPercentage)*100)+.5) / 100) * (is[0].quantity - 1) + shippingTotalSecondary := new(big.Int).Mul(is[0].secondary, big.NewInt(s)) + sts, _ := new(big.Float).Mul(big.NewFloat(0.01), new(big.Float).SetInt(shippingTotalSecondary)).Int(nil) + + t1 := new(big.Int).Mul(sts, big.NewInt(int64(is[0].quantity-1))) + shippingTotal = new(big.Int).Add(stp, t1) + } else { - return 0, errors.New("unknown listing version") + return big.NewInt(0), errors.New("unknown listing version") } } return shippingTotal, nil } - var highest uint64 + var highest *big.Int var i int for x, s := range is { - if s.primary > highest { - highest = s.primary + if s.primary.Cmp(highest) > 0 { + highest = new(big.Int).Set(s.primary) i = x } - shippingTotal += (s.secondary * uint64(((1+s.shippingTaxPercentage)*100)+.5) / 100) * s.quantity - } - shippingTotal -= is[i].primary * uint64(((1+is[i].shippingTaxPercentage)*100)+.5) / 100 - shippingTotal += is[i].secondary * uint64(((1+is[i].shippingTaxPercentage)*100)+.5) / 100 - - return shippingTotal, nil -} - -func quantityForItem(version uint32, item *pb.Order_Item) uint64 { - if version < 3 { - return uint64(item.Quantity) - } else { - return item.Quantity64 - } -} - -func (n *OpenBazaarNode) getPriceInSatoshi(paymentCoin, currencyCode string, amount uint64) (uint64, error) { - const reserveCurrency = "BTC" - if NormalizeCurrencyCode(currencyCode) == NormalizeCurrencyCode(paymentCoin) || "T"+NormalizeCurrencyCode(currencyCode) == NormalizeCurrencyCode(paymentCoin) { - return amount, nil - } - - var ( - currencyDict = repo.LoadCurrencyDefinitions() - originCurrencyDef, oErr = currencyDict.Lookup(currencyCode) - paymentCurrencyDef, pErr = currencyDict.Lookup(paymentCoin) - reserveCurrencyDef, rErr = currencyDict.Lookup(reserveCurrency) - ) - if oErr != nil { - return 0, fmt.Errorf("invalid listing currency code: %s", oErr.Error()) - } - if pErr != nil { - return 0, fmt.Errorf("invalid payment currency code: %s", pErr.Error()) - } - if rErr != nil { - return 0, fmt.Errorf("invalid reserve currency code: %s", rErr.Error()) - } - - originValue, err := repo.NewCurrencyValueFromUint(amount, originCurrencyDef) - if err != nil { - return 0, fmt.Errorf("parsing amount: %s", err.Error()) - } - - wal, err := n.Multiwallet.WalletForCurrencyCode(reserveCurrency) - if err != nil { - return 0, fmt.Errorf("%s wallet not found for exchange rates", reserveCurrency) + s0 := int64(((1 + s.shippingTaxPercentage) * 100) + .5) + shippingTotalSec := new(big.Int).Mul(s.secondary, big.NewInt(s0)) + sts0, _ := new(big.Float).Mul(big.NewFloat(0.01), new(big.Float).SetInt(shippingTotalSec)).Int(nil) + shippingTotal0 := new(big.Int).Mul(sts0, big.NewInt(int64(s.quantity))) + shippingTotal = new(big.Int).Add(shippingTotal, shippingTotal0) } + sp := int64(((1 + is[i].shippingTaxPercentage) * 100) + .5) + shippingTotalPrimary0 := new(big.Int).Mul(is[i].primary, big.NewInt(sp)) + stp0, _ := new(big.Float).Mul(big.NewFloat(0.01), new(big.Float).SetInt(shippingTotalPrimary0)).Int(nil) + shippingTotal = new(big.Int).Sub(shippingTotal, stp0) - if wal.ExchangeRates() == nil { - return 0, ErrPriceCalculationRequiresExchangeRates - } - reserveIntoOriginRate, err := wal.ExchangeRates().GetExchangeRate(currencyCode) - if err != nil { - return 0, err - } - originIntoReserveRate := 1 / reserveIntoOriginRate - reserveIntoResultRate, err := wal.ExchangeRates().GetExchangeRate(paymentCoin) - if err != nil { - // TODO: remove hack once ExchangeRates can be made aware of testnet currencies - if strings.HasPrefix(paymentCoin, "T") { - reserveIntoResultRate, err = wal.ExchangeRates().GetExchangeRate(strings.TrimPrefix(paymentCoin, "T")) - if err != nil { - return 0, err - } - } else { - return 0, err - } - } + shippingTotalSecondary0 := new(big.Int).Mul(is[i].secondary, big.NewInt(sp)) + sts0, _ := new(big.Float).Mul(big.NewFloat(0.01), new(big.Float).SetInt(shippingTotalSecondary0)).Int(nil) + shippingTotal = new(big.Int).Add(shippingTotal, sts0) - reserveValue, err := originValue.ConvertTo(reserveCurrencyDef, originIntoReserveRate) - if err != nil { - return 0, fmt.Errorf("converting to reserve: %s", err.Error()) - } - resultValue, err := reserveValue.ConvertTo(paymentCurrencyDef, reserveIntoResultRate) - if err != nil { - return 0, fmt.Errorf("converting from reserve: %s", err.Error()) - } - result, err := resultValue.AmountUint64() - if err != nil { - return 0, fmt.Errorf("unable to represent (%s) as uint64: %s", resultValue.String(), err.Error()) - } - return result, nil + return shippingTotal, nil } -func (n *OpenBazaarNode) getMarketPriceInSatoshis(pricingCurrency, currencyCode string, amount uint64) (uint64, error) { - wal, err := n.Multiwallet.WalletForCurrencyCode(pricingCurrency) - if err != nil { - return 0, err +func getShippingOption(rl *repo.Listing, optionName string) (*pb.Listing_ShippingOption, error) { + shippingOptions := make(map[string]*pb.Listing_ShippingOption) + for _, so := range rl.GetProtobuf().ShippingOptions { + shippingOptions[strings.ToLower(so.Name)] = so } - if wal.ExchangeRates() == nil { - return 0, ErrPriceCalculationRequiresExchangeRates - } - - rate, err := wal.ExchangeRates().GetExchangeRate(currencyCode) - if err != nil { - return 0, err + option, ok := shippingOptions[strings.ToLower(optionName)] + if !ok { + return nil, errors.New("shipping option not found in listing") } - - return uint64(float64(amount) / rate), nil + return option, nil } func verifySignaturesOnOrder(contract *pb.RicardianContract) error { @@ -1228,7 +1604,8 @@ func (n *OpenBazaarNode) ValidateOrder(contract *pb.RicardianContract, checkInve } } - if !currencyInAcceptedCurrenciesList(contract.BuyerOrder.Payment.Coin, contract.VendorListings[0].Metadata.AcceptedCurrencies) { + if !n.currencyInAcceptedCurrenciesList(contract.BuyerOrder.Payment.AmountCurrency.Code, + contract.VendorListings[0].Metadata.AcceptedCurrencies) { return errors.New("payment coin not accepted") } @@ -1274,7 +1651,7 @@ collectListings: if err != nil { return err } - listingID, err := EncodeCID(ser) + listingID, err := ipfs.EncodeCID(ser) if err != nil { return err } @@ -1304,7 +1681,7 @@ collectListings: type inventory struct { Slug string Variant int - Count int64 + Count *big.Int } var inventoryList []inventory for _, item := range contract.BuyerOrder.Items { @@ -1323,7 +1700,6 @@ collectListings: for _, o := range listingMap[item.ListingHash].Item.Options { for _, checkOpt := range userOptions { if strings.EqualFold(o.Name, checkOpt.Name) { - // var validVariant bool validVariant := false for _, v := range o.Variants { if strings.EqualFold(v.Name, checkOpt.Value) { @@ -1347,7 +1723,12 @@ collectListings: return errors.New("not all options were selected") } // Create inventory paths to check later - inv.Count = int64(GetOrderQuantity(listingMap[item.ListingHash], item)) + if q := GetOrderQuantity(listingMap[item.ListingHash], item); q.IsInt64() { + inv.Count = q + } else { + // TODO: https://github.com/OpenBazaar/openbazaar-go/issues/1739 + return errors.New("big inventory quantity not supported") + } inventoryList = append(inventoryList, inv) } @@ -1406,7 +1787,7 @@ collectListings: if err != nil { return errors.New("vendor has no inventory for the selected variant") } - if amt >= 0 && amt < inv.Count { + if amt.Cmp(big.NewInt(0)) >= 0 && amt.Cmp(inv.Count) < 0 { return NewErrOutOfInventory(amt) } } @@ -1460,7 +1841,7 @@ func (n *OpenBazaarNode) ValidateDirectPaymentAddress(order *pb.Order) error { if err != nil { return err } - wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.Coin) + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } @@ -1480,7 +1861,8 @@ func (n *OpenBazaarNode) ValidateDirectPaymentAddress(order *pb.Order) error { if err != nil { return err } - if order.Payment.Address != addr.EncodeAddress() { + + if order.Payment.Address != addr.String() { return errors.New("invalid payment address") } if order.Payment.RedeemScript != hex.EncodeToString(redeemScript) { @@ -1491,7 +1873,7 @@ func (n *OpenBazaarNode) ValidateDirectPaymentAddress(order *pb.Order) error { // ValidateModeratedPaymentAddress - validate moderator address func (n *OpenBazaarNode) ValidateModeratedPaymentAddress(order *pb.Order, timeout time.Duration) error { - wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.Coin) + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return err } @@ -1541,7 +1923,7 @@ func (n *OpenBazaarNode) ValidateModeratedPaymentAddress(order *pb.Order, timeou if err != nil { return err } - if order.Payment.Address != addr.EncodeAddress() { + if strings.TrimPrefix(order.Payment.Address, "0x") != strings.TrimPrefix(addr.String(), "0x") { return errors.New("invalid payment address") } if order.Payment.RedeemScript != hex.EncodeToString(redeemScript) { @@ -1567,53 +1949,19 @@ func (n *OpenBazaarNode) SignOrder(contract *pb.RicardianContract) (*pb.Ricardia return contract, nil } -func validateVendorID(listing *pb.Listing) error { - - if listing == nil { - return errors.New("listing is nil") - } - if listing.VendorID == nil { - return errors.New("vendorID is nil") - } - if listing.VendorID.Pubkeys == nil { - return errors.New("vendor pubkeys is nil") - } - vendorPubKey, err := crypto.UnmarshalPublicKey(listing.VendorID.Pubkeys.Identity) - if err != nil { - return err - } - vendorID, err := peer.IDB58Decode(listing.VendorID.PeerID) - if err != nil { - return err - } - if !vendorID.MatchesPublicKey(vendorPubKey) { - return errors.New("invalid vendorID") - } - return nil -} - -func validateVersionNumber(listing *pb.Listing) error { - if listing == nil { - return errors.New("listing is nil") - } - if listing.Metadata == nil { - return errors.New("listing does not contain metadata") - } - if listing.Metadata.Version > ListingVersion { - return errors.New("unknown listing version, must upgrade to purchase this listing") - } - return nil -} - // ValidatePaymentAmount - validate amount requested -func (n *OpenBazaarNode) ValidatePaymentAmount(requestedAmount, paymentAmount uint64) bool { +func (n *OpenBazaarNode) ValidatePaymentAmount(requestedAmount, paymentAmount *big.Int) bool { settings, _ := n.Datastore.Settings().Get() bufferPercent := float32(0) if settings.MisPaymentBuffer != nil { bufferPercent = *settings.MisPaymentBuffer } - buffer := float32(requestedAmount) * (bufferPercent / 100) - return float32(paymentAmount)+buffer >= float32(requestedAmount) + a := new(big.Float).SetInt(requestedAmount) + buf := new(big.Float).Mul(a, big.NewFloat(float64(bufferPercent))) + buf = new(big.Float).Mul(buf, big.NewFloat(0.01)) + rh := new(big.Float).SetInt(paymentAmount) + rh = new(big.Float).Add(rh, buf) + return rh.Cmp(a) >= 0 } // ParseContractForListing - return the listing identified by the hash from the contract @@ -1623,7 +1971,7 @@ func ParseContractForListing(hash string, contract *pb.RicardianContract) (*pb.L if err != nil { return nil, err } - listingID, err := EncodeCID(ser) + listingID, err := ipfs.EncodeCID(ser) if err != nil { return nil, err } @@ -1681,9 +2029,57 @@ func SameSku(selectedVariants []int, sku *pb.Listing_Item_Sku) bool { } // GetOrderQuantity - return the specified item quantity -func GetOrderQuantity(l *pb.Listing, item *pb.Order_Item) uint64 { - if l.Metadata.Version < 3 { - return uint64(item.Quantity) +func GetOrderQuantity(l *pb.Listing, item *pb.Order_Item) *big.Int { + return quantityForItem(l.Metadata.Version, item) +} + +func quantityForItem(version uint32, item *pb.Order_Item) *big.Int { + switch version { + case 5: + i, _ := new(big.Int).SetString(item.BigQuantity, 10) + return i + case 3, 4: + return new(big.Int).SetUint64(item.Quantity64) + } + return new(big.Int).SetUint64(uint64(item.Quantity)) +} + +// ReserveCurrencyConverter will attempt to build a CurrencyConverter based on +// the reserve currency, or will panic if unsuccessful +func (n *OpenBazaarNode) ReserveCurrencyConverter() (*repo.CurrencyConverter, error) { + // reserve currency whitelist + // TODO: later when the wallet can express whether it can + // provide reliable reserve currency rates, they can be + // reflected upon instead of using an explicit whitelist + var preferredReserveWalletCodes = []string{"BTC"} + for _, code := range preferredReserveWalletCodes { + var reserveCode = code + if n.RegressionTestEnable || n.TestnetEnable { + reserveCode = "T" + code + } + + wal, err := n.Multiwallet.WalletForCurrencyCode(reserveCode) + if err != nil { + continue + } + + if wal.ExchangeRates() == nil { + log.Warningf("%s reserve wallet has exchange rates disabled or unavailable", reserveCode) + continue + } + + if _, err := wal.ExchangeRates().GetAllRates(false); err != nil { + log.Warningf("%s reserve wallet priming exchange rate cache: %s", reserveCode, err.Error()) + continue + } + + cc, err := repo.NewCurrencyConverter(reserveCode, wal.ExchangeRates()) + if err != nil { + log.Warningf("creating %s reserve currency converter: %s", reserveCode, err.Error()) + continue + } + log.Infof("reserve exchange rates provided by %s wallet", reserveCode) + return cc, nil } - return item.Quantity64 + return nil, errors.New("unable to find reserve wallet with exchange rates") } diff --git a/core/order_test.go b/core/order_test.go index 749ccd64fb..f95f60f4a2 100644 --- a/core/order_test.go +++ b/core/order_test.go @@ -1,12 +1,14 @@ package core_test import ( + "fmt" + "github.com/phoreproject/pm-go/ipfs" "testing" "github.com/golang/protobuf/proto" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/test" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/test" + "github.com/phoreproject/pm-go/test/factory" ) func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { @@ -15,39 +17,42 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { t.Error(err) } contract := &pb.RicardianContract{ - VendorListings: []*pb.Listing{{ - Metadata: &pb.Listing_Metadata{ - ContractType: pb.Listing_Metadata_PHYSICAL_GOOD, - Format: pb.Listing_Metadata_FIXED_PRICE, - AcceptedCurrencies: []string{"BTC"}, - PricingCurrency: "BTC", - Version: 2, - }, - Item: &pb.Listing_Item{ - Price: 100000, - }, - ShippingOptions: []*pb.Listing_ShippingOption{ - { - Name: "UPS", - Regions: []pb.CountryCode{pb.CountryCode_UNITED_STATES}, - Type: pb.Listing_ShippingOption_FIXED_PRICE, - Services: []*pb.Listing_ShippingOption_Service{ - { - Name: "Standard shipping", - Price: 25000, - AdditionalItemPrice: 10000, + VendorListings: []*pb.Listing{ + { + Metadata: &pb.Listing_Metadata{ + ContractType: pb.Listing_Metadata_PHYSICAL_GOOD, + Format: pb.Listing_Metadata_FIXED_PRICE, + AcceptedCurrencies: []string{"TBTC"}, + EscrowTimeoutHours: 1080, + Version: 5, + }, + Item: &pb.Listing_Item{ + BigPrice: "100000", + PriceCurrency: &pb.CurrencyDefinition{Code: "TBTC", Divisibility: 8}, + }, + ShippingOptions: []*pb.Listing_ShippingOption{ + { + Name: "UPS", + Regions: []pb.CountryCode{pb.CountryCode_UNITED_STATES}, + Type: pb.Listing_ShippingOption_FIXED_PRICE, + Services: []*pb.Listing_ShippingOption_Service{ + { + Name: "Standard shipping", + BigPrice: "25000", + BigAdditionalItemPrice: "10000", + }, }, }, }, }, - }}, + }, } ser, err := proto.Marshal(contract.VendorListings[0]) if err != nil { t.Error(err) } - listingID, err := core.EncodeCID(ser) + listingID, err := ipfs.EncodeCID(ser) if err != nil { t.Error(err) } @@ -55,7 +60,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { Items: []*pb.Order_Item{ { ListingHash: listingID.String(), - Quantity: 1, + BigQuantity: "1", ShippingOption: &pb.Order_Item_ShippingOption{ Name: "UPS", Service: "Standard shipping", @@ -66,7 +71,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { Country: pb.CountryCode_UNITED_STATES, }, Payment: &pb.Order_Payment{ - Coin: "BTC", + AmountCurrency: &pb.CurrencyDefinition{Code: "TBTC", Divisibility: 8}, }, } contract.BuyerOrder = order @@ -76,22 +81,22 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - if total != 125000 { - t.Errorf("Calculated wrong order total. Wanted %d, got %d", 125000, total) + if total.Int64() != 125000 { + t.Errorf("Calculated wrong order total. Wanted 125000, got %d", total.Int64()) } // Test higher quantity - contract.BuyerOrder.Items[0].Quantity = 2 + contract.BuyerOrder.Items[0].BigQuantity = "2" total, err = node.CalculateOrderTotal(contract) if err != nil { t.Error(err) } - if total != 235000 { - t.Error("Calculated wrong order total") + if total.Int64() != 235000 { + t.Errorf("Calculated wrong order total. Wanted 235000, got %d", total.Int64()) } // Test with options - contract.BuyerOrder.Items[0].Quantity = 1 + contract.BuyerOrder.Items[0].BigQuantity = "1" contract.VendorListings[0].Item.Options = []*pb.Listing_Item_Option{ { Name: "color", @@ -104,7 +109,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { } contract.VendorListings[0].Item.Skus = []*pb.Listing_Item_Sku{ { - Surcharge: 50000, + BigSurcharge: "50000", VariantCombo: []uint32{0}, }, } @@ -118,7 +123,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - listingID, err = core.EncodeCID(ser) + listingID, err = ipfs.EncodeCID(ser) if err != nil { t.Error(err) } @@ -127,14 +132,14 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - if total != 175000 { - t.Error("Calculated wrong order total") + if total.Int64() != 175000 { + t.Errorf("Calculated wrong order total. Wanted 175000, got %d", total.Int64()) } // Test negative surcharge contract.VendorListings[0].Item.Skus = []*pb.Listing_Item_Sku{ { - Surcharge: -50000, + BigSurcharge: "-50000", VariantCombo: []uint32{0}, }, } @@ -142,7 +147,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - listingID, err = core.EncodeCID(ser) + listingID, err = ipfs.EncodeCID(ser) if err != nil { t.Error(err) } @@ -151,12 +156,12 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - if total != 75000 { - t.Error("Calculated wrong order total") + if total.Int64() != 75000 { + t.Errorf("Calculated wrong order total. Wanted 75000, got %d", total.Int64()) } // Test with coupon percent discount - couponHash, err := core.EncodeMultihash([]byte("testcoupon")) + couponHash, err := ipfs.EncodeMultihash([]byte("testcoupon")) if err != nil { t.Error(err) } @@ -172,22 +177,22 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - listingID, err = core.EncodeCID(ser) + listingID, err = ipfs.EncodeCID(ser) if err != nil { t.Error(err) } contract.BuyerOrder.Items[0].CouponCodes = []string{"testcoupon"} contract.BuyerOrder.Items[0].ListingHash = listingID.String() - total, err = node.CalculateOrderTotal(contract) + total1, err := node.CalculateOrderTotal(contract) if err != nil { t.Error(err) } - if total != 70000 { - t.Error("Calculated wrong order total") + if total1.Int64() != 70000 { + t.Errorf("failed calculating correct total, expected (%d), got (%d)", 70000, total1.Int64()) } // Test with coupon percent discount - couponHash, err = core.EncodeMultihash([]byte("testcoupon2")) + couponHash, err = ipfs.EncodeMultihash([]byte("testcoupon2")) if err != nil { t.Error(err) } @@ -195,7 +200,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { { Code: &pb.Listing_Coupon_Hash{Hash: couponHash.B58String()}, Title: "coup", - Discount: &pb.Listing_Coupon_PriceDiscount{PriceDiscount: 6000}, + Discount: &pb.Listing_Coupon_BigPriceDiscount{BigPriceDiscount: "6000"}, }, } @@ -203,7 +208,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - listingID, err = core.EncodeCID(ser) + listingID, err = ipfs.EncodeCID(ser) if err != nil { t.Error(err) } @@ -213,8 +218,8 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - if total != 69000 { - t.Error("Calculated wrong order total") + if total.Int64() != 69000 { + t.Errorf("Calculated wrong order total. Wanted 69000, got %d", total.Int64()) } // Test with tax no tax shipping @@ -230,7 +235,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - listingID, err = core.EncodeCID(ser) + listingID, err = ipfs.EncodeCID(ser) if err != nil { t.Error(err) } @@ -239,8 +244,8 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - if total != 71200 { - t.Error("Calculated wrong order total") + if total.Int64() != 71200 { + t.Errorf("Calculated wrong order total. Wanted 71200, got %d", total.Int64()) } // Test with tax with tax shipping @@ -256,7 +261,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - listingID, err = core.EncodeCID(ser) + listingID, err = ipfs.EncodeCID(ser) if err != nil { t.Error(err) } @@ -265,9 +270,8 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - if total != 72450 { - t.Error("Calculated wrong order total") - return + if total.Int64() != 72450 { + t.Fatalf("Calculated wrong order total. Wanted 72450, got %d", total.Int64()) } // Test local pickup @@ -277,7 +281,7 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - listingID, err = core.EncodeCID(ser) + listingID, err = ipfs.EncodeCID(ser) if err != nil { t.Error(err) } @@ -286,52 +290,61 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { if err != nil { t.Error(err) } - if total != 46200 { - t.Error("Calculated wrong order total") + if total.Int64() != 46200 { + t.Errorf("Calculated wrong order total. Wanted 46200, got %d", total.Int64()) } +} - contract2 := &pb.RicardianContract{ - VendorListings: []*pb.Listing{{ - Metadata: &pb.Listing_Metadata{ - Version: 3, - ContractType: pb.Listing_Metadata_PHYSICAL_GOOD, - Format: pb.Listing_Metadata_FIXED_PRICE, - AcceptedCurrencies: []string{"BTC"}, - PricingCurrency: "BTC", - }, - Item: &pb.Listing_Item{ - Price: 100000, - }, - ShippingOptions: []*pb.Listing_ShippingOption{ - { - Name: "UPS", - Regions: []pb.CountryCode{pb.CountryCode_UNITED_STATES}, - Type: pb.Listing_ShippingOption_FIXED_PRICE, - Services: []*pb.Listing_ShippingOption_Service{ - { - Name: "Standard shipping", - Price: 25000, - AdditionalItemPrice: 10000, +func TestOpenBazaarNode_CalculateOrderTotalWithV4Schema(t *testing.T) { + node, err := test.NewNode() + if err != nil { + t.Error(err) + } + v4Contract := &pb.RicardianContract{ + VendorListings: []*pb.Listing{ + { + Metadata: &pb.Listing_Metadata{ + ContractType: pb.Listing_Metadata_PHYSICAL_GOOD, + Format: pb.Listing_Metadata_FIXED_PRICE, + AcceptedCurrencies: []string{"TBTC"}, + EscrowTimeoutHours: 1080, + PricingCurrency: "TBTC", + Version: 4, + }, + Item: &pb.Listing_Item{ + Price: 100000, + }, + ShippingOptions: []*pb.Listing_ShippingOption{ + { + Name: "UPS", + Regions: []pb.CountryCode{pb.CountryCode_UNITED_STATES}, + Type: pb.Listing_ShippingOption_FIXED_PRICE, + Services: []*pb.Listing_ShippingOption_Service{ + { + Name: "Standard shipping", + Price: 25000, + AdditionalItemPrice: 10000, + }, }, }, }, }, - }}, + }, } - ser, err = proto.Marshal(contract2.VendorListings[0]) + ser, err := proto.Marshal(v4Contract.VendorListings[0]) if err != nil { t.Error(err) } - listingID, err = core.EncodeCID(ser) + listingID, err := ipfs.EncodeCID(ser) if err != nil { t.Error(err) } - order2 := &pb.Order{ + order := &pb.Order{ Items: []*pb.Order_Item{ { ListingHash: listingID.String(), - Quantity64: 10, + Quantity64: 1, ShippingOption: &pb.Order_Item_ShippingOption{ Name: "UPS", Service: "Standard shipping", @@ -342,17 +355,258 @@ func TestOpenBazaarNode_CalculateOrderTotal(t *testing.T) { Country: pb.CountryCode_UNITED_STATES, }, Payment: &pb.Order_Payment{ - Coin: "BTC", + Amount: 125000, + Coin: "TBTC", + }, + } + v4Contract.BuyerOrder = order + + // Basic contract + total, err := node.CalculateOrderTotal(v4Contract) + if err != nil { + t.Error(err) + } + if total.Int64() != 125000 { + t.Errorf("Calculated wrong order total. Wanted 125000, got %d", total.Int64()) + } + + // Test higher quantity + v4Contract.BuyerOrder.Items[0].Quantity64 = 2 + total, err = node.CalculateOrderTotal(v4Contract) + if err != nil { + t.Error(err) + } + if total.Int64() != 235000 { + t.Errorf("Calculated wrong order total. Wanted 235000, got %d", total.Int64()) + } + + // Test with options + v4Contract.BuyerOrder.Items[0].Quantity64 = 1 + v4Contract.VendorListings[0].Item.Options = []*pb.Listing_Item_Option{ + { + Name: "color", + Variants: []*pb.Listing_Item_Option_Variant{ + { + Name: "red", + }, + }, + }, + } + v4Contract.VendorListings[0].Item.Skus = []*pb.Listing_Item_Sku{ + { + Surcharge: 50000, + VariantCombo: []uint32{0}, + }, + } + v4Contract.BuyerOrder.Items[0].Options = []*pb.Order_Item_Option{ + { + Name: "color", + Value: "red", + }, + } + ser, err = proto.Marshal(v4Contract.VendorListings[0]) + if err != nil { + t.Error(err) + } + listingID, err = ipfs.EncodeCID(ser) + if err != nil { + t.Error(err) + } + v4Contract.BuyerOrder.Items[0].ListingHash = listingID.String() + total, err = node.CalculateOrderTotal(v4Contract) + if err != nil { + t.Error(err) + } + if total.Int64() != 175000 { + t.Errorf("Calculated wrong order total. Wanted 175000, got %d", total.Int64()) + } + + // Test negative surcharge + v4Contract.VendorListings[0].Item.Skus = []*pb.Listing_Item_Sku{ + { + Surcharge: -50000, + VariantCombo: []uint32{0}, + }, + } + ser, err = proto.Marshal(v4Contract.VendorListings[0]) + if err != nil { + t.Error(err) + } + listingID, err = ipfs.EncodeCID(ser) + if err != nil { + t.Error(err) + } + v4Contract.BuyerOrder.Items[0].ListingHash = listingID.String() + total, err = node.CalculateOrderTotal(v4Contract) + if err != nil { + t.Error(err) + } + if total.Int64() != 75000 { + t.Errorf("Calculated wrong order total. Wanted 75000, got %d", total.Int64()) + } + + // Test with coupon percent discount + couponHash, err := ipfs.EncodeMultihash([]byte("testcoupon")) + if err != nil { + t.Error(err) + } + v4Contract.VendorListings[0].Coupons = []*pb.Listing_Coupon{ + { + Code: &pb.Listing_Coupon_Hash{Hash: couponHash.B58String()}, + Title: "coup", + Discount: &pb.Listing_Coupon_PercentDiscount{PercentDiscount: 10}, }, } - contract2.BuyerOrder = order2 - // Test quantity64 - total, err = node.CalculateOrderTotal(contract2) + ser, err = proto.Marshal(v4Contract.VendorListings[0]) if err != nil { t.Error(err) } - if total != 1115000 { - t.Error("Calculated wrong order total") + listingID, err = ipfs.EncodeCID(ser) + if err != nil { + t.Error(err) + } + v4Contract.BuyerOrder.Items[0].CouponCodes = []string{"testcoupon"} + v4Contract.BuyerOrder.Items[0].ListingHash = listingID.String() + total, err = node.CalculateOrderTotal(v4Contract) + if err != nil { + t.Error(err) + } + if total.Int64() != 70000 { + t.Errorf("Calculated wrong order total. Wanted 70000, got %d", total.Int64()) + } + + // Test with coupon percent discount + couponHash, err = ipfs.EncodeMultihash([]byte("testcoupon2")) + if err != nil { + t.Error(err) + } + v4Contract.VendorListings[0].Coupons = []*pb.Listing_Coupon{ + { + Code: &pb.Listing_Coupon_Hash{Hash: couponHash.B58String()}, + Title: "coup", + Discount: &pb.Listing_Coupon_BigPriceDiscount{BigPriceDiscount: "6000"}, + }, + } + + ser, err = proto.Marshal(v4Contract.VendorListings[0]) + if err != nil { + t.Error(err) + } + listingID, err = ipfs.EncodeCID(ser) + if err != nil { + t.Error(err) + } + v4Contract.BuyerOrder.Items[0].CouponCodes = []string{"testcoupon2"} + v4Contract.BuyerOrder.Items[0].ListingHash = listingID.String() + total, err = node.CalculateOrderTotal(v4Contract) + if err != nil { + t.Error(err) + } + if total.Int64() != 75000 { + t.Errorf("Calculated wrong order total. Wanted 75000, got %d", total.Int64()) + } + + // Test with tax no tax shipping + v4Contract.VendorListings[0].Taxes = []*pb.Listing_Tax{ + { + Percentage: 5, + TaxShipping: false, + TaxRegions: []pb.CountryCode{pb.CountryCode_UNITED_STATES}, + }, + } + + ser, err = proto.Marshal(v4Contract.VendorListings[0]) + if err != nil { + t.Error(err) + } + listingID, err = ipfs.EncodeCID(ser) + if err != nil { + t.Error(err) + } + v4Contract.BuyerOrder.Items[0].ListingHash = listingID.String() + total, err = node.CalculateOrderTotal(v4Contract) + if err != nil { + t.Error(err) + } + if total.Int64() != 77500 { + t.Errorf("Calculated wrong order total. Wanted 77500, got %d", total.Int64()) + } + + // Test with tax with tax shipping + v4Contract.VendorListings[0].Taxes = []*pb.Listing_Tax{ + { + Percentage: 5, + TaxShipping: true, + TaxRegions: []pb.CountryCode{pb.CountryCode_UNITED_STATES}, + }, + } + + ser, err = proto.Marshal(v4Contract.VendorListings[0]) + if err != nil { + t.Error(err) + } + listingID, err = ipfs.EncodeCID(ser) + if err != nil { + t.Error(err) + } + v4Contract.BuyerOrder.Items[0].ListingHash = listingID.String() + total, err = node.CalculateOrderTotal(v4Contract) + if err != nil { + t.Error(err) + } + if total.Int64() != 78750 { + t.Fatalf("Calculated wrong order total. Wanted 78750, got %d", total.Int64()) + } + + // Test local pickup + v4Contract.VendorListings[0].ShippingOptions[0].Type = pb.Listing_ShippingOption_LOCAL_PICKUP + + ser, err = proto.Marshal(v4Contract.VendorListings[0]) + if err != nil { + t.Error(err) + } + listingID, err = ipfs.EncodeCID(ser) + if err != nil { + t.Error(err) + } + v4Contract.BuyerOrder.Items[0].ListingHash = listingID.String() + total, err = node.CalculateOrderTotal(v4Contract) + if err != nil { + t.Error(err) + } + if total.Int64() != 52500 { + t.Errorf("Calculated wrong order total. Wanted 52500, got %d", total.Int64()) + } +} + +func TestOpenBazaarNode_GetOrder(t *testing.T) { + node, err := test.NewNode() + if err != nil { + t.Fatal(err) + } + + contract := factory.NewContract() + + orderID, err := node.CalcOrderID(contract.BuyerOrder) + if err != nil { + t.Fatal(err) + } + + state := pb.OrderState_AWAITING_PAYMENT + err = node.Datastore.Purchases().Put(orderID, *contract, state, false) + if err != nil { + t.Fatal(err) + } + + orderResponse, err := node.GetOrder(orderID) + if err != nil { + t.Fatal(err) + } + + if orderResponse.State != state { + t.Fatal(fmt.Errorf("expected order state to be %s, but was %s", + pb.OrderState_name[int32(state)], + pb.OrderState_name[int32(orderResponse.State)])) } } diff --git a/core/pointer_republisher.go b/core/pointer_republisher.go index f375ab51a9..88d72351e1 100644 --- a/core/pointer_republisher.go +++ b/core/pointer_republisher.go @@ -1,7 +1,7 @@ package core import ( - net "github.com/phoreproject/openbazaar-go/net/repointer" + net "github.com/phoreproject/pm-go/net/repointer" ) // StartPointerRepublisher - setup republisher for IPNS diff --git a/core/posts.go b/core/posts.go index 6b7e0ddd43..de04827aca 100644 --- a/core/posts.go +++ b/core/posts.go @@ -15,8 +15,9 @@ import ( "github.com/OpenBazaar/jsonpb" "github.com/golang/protobuf/proto" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) // Constants for validation @@ -46,7 +47,7 @@ var ( ErrPostSlugNotEmpty = errors.New("slug must not be empty") // ErrPostSlugTooLong - post slug longer than max characters error - ErrPostSlugTooLong = fmt.Errorf("slug is longer than the max of %d", SentenceMaxCharacters) + ErrPostSlugTooLong = fmt.Errorf("slug is longer than the max of %d", repo.SentenceMaxCharacters) // ErrPostSlugContainsSpaces - post slug has spaces error ErrPostSlugContainsSpaces = errors.New("slugs cannot contain spaces") @@ -88,7 +89,7 @@ var ( ErrPostReferenceContainsSpaces = errors.New("reference cannot contain spaces") // ErrPostImagesTooMany - post images longer than max error - ErrPostImagesTooMany = fmt.Errorf("number of post images is greater than the max of %d", MaxListItems) + ErrPostImagesTooMany = fmt.Errorf("number of post images is greater than the max of %d", repo.MaxListItems) // ErrPostImageTinyFormatInvalid - post tiny image hash incorrectly formatted error ErrPostImageTinyFormatInvalid = errors.New("tiny image hashes must be properly formatted CID") @@ -109,7 +110,7 @@ var ( ErrPostImageFilenameNil = errors.New("image file names must not be nil") // ErrPostImageFilenameTooLong - post image filename length longer than max - ErrPostImageFilenameTooLong = fmt.Errorf("image filename length must be less than the max of %d", FilenameMaxCharacters) + ErrPostImageFilenameTooLong = fmt.Errorf("image filename length must be less than the max of %d", repo.FilenameMaxCharacters) ) // JSON structure returned for each post from GETPosts @@ -135,7 +136,7 @@ type postImage struct { func (n *OpenBazaarNode) GeneratePostSlug(status string) (string, error) { status = strings.Replace(status, "/", "", -1) counter := 1 - slugBase := createSlugFor(status) + slugBase := repo.CreateSlugFor(status) slugToTry := slugBase for { _, err := n.GetPostFromSlug(slugToTry) @@ -547,7 +548,7 @@ func validatePost(post *pb.Post) (err error) { if post.Slug == "" { return ErrPostSlugNotEmpty } - if len(post.Slug) > SentenceMaxCharacters { + if len(post.Slug) > repo.SentenceMaxCharacters { return ErrPostSlugTooLong } if strings.Contains(post.Slug, " ") { @@ -609,7 +610,7 @@ func validatePost(post *pb.Post) (err error) { } // Images - if len(post.Images) > MaxListItems { + if len(post.Images) > repo.MaxListItems { return ErrPostImagesTooMany } for _, img := range post.Images { @@ -636,7 +637,7 @@ func validatePost(post *pb.Post) (err error) { if img.Filename == "" { return ErrPostImageFilenameNil } - if len(img.Filename) > FilenameMaxCharacters { + if len(img.Filename) > repo.FilenameMaxCharacters { return ErrPostImageFilenameTooLong } } diff --git a/core/profile.go b/core/profile.go index 79b352a6da..6bf598bace 100644 --- a/core/profile.go +++ b/core/profile.go @@ -6,7 +6,9 @@ import ( "encoding/json" "errors" "fmt" - "github.com/phoreproject/openbazaar-go/ipfs" + + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/repo" cid "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" @@ -21,11 +23,9 @@ import ( "github.com/OpenBazaar/jsonpb" "github.com/golang/protobuf/ptypes" "github.com/imdario/mergo" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) -const KeyCachePrefix = "/pubkey/" - // ErrorProfileNotFound - profile not found error var ErrorProfileNotFound = errors.New("profile not found") @@ -51,41 +51,46 @@ func (n *OpenBazaarNode) FetchProfile(peerID string, useCache bool) (pb.Profile, if err != nil || len(b) == 0 { return pro, err } - err = jsonpb.UnmarshalString(string(b), &pro) + p, err := repo.UnmarshalJSONProfile(b) if err != nil { + log.Error("Profile fetch error", peerID, err) return pro, err } - return pro, nil + p.NormalizeDataForAllSchemas() + return *p.GetProtobuf(), nil } // UpdateProfile - update user profile func (n *OpenBazaarNode) UpdateProfile(profile *pb.Profile) error { mPubkey, err := n.MasterPrivateKey.ECPubKey() if err != nil { - return err - } - - if err := ValidateProfile(profile); err != nil { - return err + return fmt.Errorf("getting public key: %s", err.Error()) } + profile.Version = repo.ListingVersion profile.BitcoinPubkey = hex.EncodeToString(mPubkey.SerializeCompressed()) - m := jsonpb.Marshaler{ - EnumsAsInts: false, - EmitDefaults: true, - Indent: " ", - OrigName: false, - } - - var acceptedCurrencies []string - settingsData, _ := n.Datastore.Settings().Get() - if settingsData.PreferredCurrencies != nil { - for _, ct := range *settingsData.PreferredCurrencies { - acceptedCurrencies = append(acceptedCurrencies, NormalizeCurrencyCode(ct)) - } - } else { - for ct := range n.Multiwallet { - acceptedCurrencies = append(acceptedCurrencies, NormalizeCurrencyCode(ct.CurrencyCode())) + var acceptedCurrencies = profile.GetCurrencies() + settingsData, err := n.Datastore.Settings().Get() + if err != nil { + log.Debug("settings not set, using default preferred currencies") + } + if len(acceptedCurrencies) == 0 { + if settingsData.PreferredCurrencies != nil { + for _, ct := range *settingsData.PreferredCurrencies { + def, err := n.LookupCurrency(ct) + if err != nil { + return fmt.Errorf("lookup currency (%s): %s", ct, err) + } + acceptedCurrencies = append(acceptedCurrencies, def.CurrencyCode().String()) + } + } else { + for ct := range n.Multiwallet { + def, err := n.LookupCurrency(ct.CurrencyCode()) + if err != nil { + return fmt.Errorf("lookup currency (%s): %s", ct.CurrencyCode(), err) + } + acceptedCurrencies = append(acceptedCurrencies, def.CurrencyCode().String()) + } } } @@ -100,6 +105,16 @@ func (n *OpenBazaarNode) UpdateProfile(profile *pb.Profile) error { return err } profile.LastModified = ts + if err := ValidateProfile(profile); err != nil { + return err + } + + m := jsonpb.Marshaler{ + EnumsAsInts: false, + EmitDefaults: true, + Indent: " ", + OrigName: false, + } out, err := m.MarshalToString(profile) if err != nil { return err @@ -166,7 +181,6 @@ func (n *OpenBazaarNode) PatchProfile(patch map[string]interface{}) error { return err } - // Execute UpdateProfile with new profile newProfile, err := json.Marshal(patch) if err != nil { return err @@ -175,7 +189,26 @@ func (n *OpenBazaarNode) PatchProfile(patch map[string]interface{}) error { if err := jsonpb.Unmarshal(bytes.NewReader(newProfile), p); err != nil { return err } - return n.UpdateProfile(p) + + repoProfile, err := repo.UnmarshalJSONProfile(newProfile) + if err != nil { + return fmt.Errorf("building profile for validation: %s", err.Error()) + } + + repoProfile.NormalizeDataForAllSchemas() + + if repoProfile.GetProtobuf().ModeratorInfo != nil && + repoProfile.GetProtobuf().ModeratorInfo.Fee != nil && + repoProfile.GetProtobuf().ModeratorInfo.Fee.FeeType == pb.Moderator_Fee_PERCENTAGE { + + repoProfile.GetProtobuf().ModeratorInfo.Fee.FixedFee = nil + } + + if err := repoProfile.Valid(); err != nil { + return fmt.Errorf("invalid profile: %s", err.Error()) + } + + return n.UpdateProfile(repoProfile.GetProtobuf()) } func (n *OpenBazaarNode) appendCountsToProfile(profile *pb.Profile) (*pb.Profile, bool) { @@ -270,70 +303,78 @@ func ValidateProfile(profile *pb.Profile) error { if strings.Contains(profile.Handle, "@") { return errors.New("handle should not contain @") } - if len(profile.Handle) > WordMaxCharacters { - return fmt.Errorf("handle character length is greater than the max of %d", WordMaxCharacters) + if len(profile.Handle) > repo.WordMaxCharacters { + return fmt.Errorf("handle character length is greater than the max of %d", repo.WordMaxCharacters) } if len(profile.Name) == 0 { return errors.New("profile name not set") } - if len(profile.Name) > WordMaxCharacters { - return fmt.Errorf("name character length is greater than the max of %d", WordMaxCharacters) + if len(profile.Name) > repo.WordMaxCharacters { + return fmt.Errorf("name character length is greater than the max of %d", repo.WordMaxCharacters) } - if len(profile.Location) > WordMaxCharacters { - return fmt.Errorf("location character length is greater than the max of %d", WordMaxCharacters) + if len(profile.Location) > repo.WordMaxCharacters { + return fmt.Errorf("location character length is greater than the max of %d", repo.WordMaxCharacters) } - if len(profile.About) > AboutMaxCharacters { - return fmt.Errorf("about character length is greater than the max of %d", AboutMaxCharacters) + if len(profile.About) > repo.AboutMaxCharacters { + return fmt.Errorf("about character length is greater than the max of %d", repo.AboutMaxCharacters) } - if len(profile.ShortDescription) > ShortDescriptionLength { - return fmt.Errorf("short description character length is greater than the max of %d", ShortDescriptionLength) + if len(profile.ShortDescription) > repo.ShortDescriptionLength { + return fmt.Errorf("short description character length is greater than the max of %d", repo.ShortDescriptionLength) } if profile.ContactInfo != nil { - if len(profile.ContactInfo.Website) > URLMaxCharacters { - return fmt.Errorf("website character length is greater than the max of %d", URLMaxCharacters) + if len(profile.ContactInfo.Website) > repo.URLMaxCharacters { + return fmt.Errorf("website character length is greater than the max of %d", repo.URLMaxCharacters) } - if len(profile.ContactInfo.Email) > SentenceMaxCharacters { - return fmt.Errorf("email character length is greater than the max of %d", SentenceMaxCharacters) + if len(profile.ContactInfo.Email) > repo.SentenceMaxCharacters { + return fmt.Errorf("email character length is greater than the max of %d", repo.SentenceMaxCharacters) } - if len(profile.ContactInfo.PhoneNumber) > WordMaxCharacters { - return fmt.Errorf("phone number character length is greater than the max of %d", WordMaxCharacters) + if len(profile.ContactInfo.PhoneNumber) > repo.WordMaxCharacters { + return fmt.Errorf("phone number character length is greater than the max of %d", repo.WordMaxCharacters) } - if len(profile.ContactInfo.Social) > MaxListItems { - return fmt.Errorf("number of social accounts is greater than the max of %d", MaxListItems) + if len(profile.ContactInfo.Social) > repo.MaxListItems { + return fmt.Errorf("number of social accounts is greater than the max of %d", repo.MaxListItems) } for _, s := range profile.ContactInfo.Social { - if len(s.Username) > WordMaxCharacters { - return fmt.Errorf("social username character length is greater than the max of %d", WordMaxCharacters) + if len(s.Username) > repo.WordMaxCharacters { + return fmt.Errorf("social username character length is greater than the max of %d", repo.WordMaxCharacters) } - if len(s.Type) > WordMaxCharacters { - return fmt.Errorf("social account type character length is greater than the max of %d", WordMaxCharacters) + if len(s.Type) > repo.WordMaxCharacters { + return fmt.Errorf("social account type character length is greater than the max of %d", repo.WordMaxCharacters) } - if len(s.Proof) > URLMaxCharacters { - return fmt.Errorf("social proof character length is greater than the max of %d", WordMaxCharacters) + if len(s.Proof) > repo.URLMaxCharacters { + return fmt.Errorf("social proof character length is greater than the max of %d", repo.WordMaxCharacters) } } } if profile.ModeratorInfo != nil { - if len(profile.ModeratorInfo.Description) > AboutMaxCharacters { - return fmt.Errorf("moderator description character length is greater than the max of %d", AboutMaxCharacters) + if len(profile.ModeratorInfo.Description) > repo.AboutMaxCharacters { + return fmt.Errorf("moderator description character length is greater than the max of %d", repo.AboutMaxCharacters) } - if len(profile.ModeratorInfo.TermsAndConditions) > PolicyMaxCharacters { - return fmt.Errorf("moderator terms and conditions character length is greater than the max of %d", PolicyMaxCharacters) + if len(profile.ModeratorInfo.TermsAndConditions) > repo.PolicyMaxCharacters { + return fmt.Errorf("moderator terms and conditions character length is greater than the max of %d", repo.PolicyMaxCharacters) } - if len(profile.ModeratorInfo.Languages) > MaxListItems { - return fmt.Errorf("moderator number of languages greater than the max of %d", MaxListItems) + if len(profile.ModeratorInfo.Languages) > repo.MaxListItems { + return fmt.Errorf("moderator number of languages greater than the max of %d", repo.MaxListItems) } for _, l := range profile.ModeratorInfo.Languages { - if len(l) > WordMaxCharacters { - return fmt.Errorf("moderator language character length is greater than the max of %d", WordMaxCharacters) + if len(l) > repo.WordMaxCharacters { + return fmt.Errorf("moderator language character length is greater than the max of %d", repo.WordMaxCharacters) } } if profile.ModeratorInfo.Fee != nil { + var moderatorCurrencyCode string if profile.ModeratorInfo.Fee.FixedFee != nil { - if len(profile.ModeratorInfo.Fee.FixedFee.CurrencyCode) > WordMaxCharacters { - return fmt.Errorf("moderator fee currency code character length is greater than the max of %d", WordMaxCharacters) + if profile.ModeratorInfo.Fee.FixedFee.AmountCurrency == nil { + moderatorCurrencyCode = profile.ModeratorInfo.Fee.FixedFee.CurrencyCode + } else { + moderatorCurrencyCode = profile.ModeratorInfo.Fee.FixedFee.AmountCurrency.Code } } + + if profile.ModeratorInfo.Fee.FeeType != pb.Moderator_Fee_PERCENTAGE && profile.ModeratorInfo.Fee.FixedFee != nil && + len(moderatorCurrencyCode) > repo.WordMaxCharacters { + return fmt.Errorf("moderator fee currency code character length is greater than the max of %d", repo.WordMaxCharacters) + } } } if profile.AvatarHashes != nil && (profile.AvatarHashes.Large != "" || profile.AvatarHashes.Medium != "" || diff --git a/core/ratings.go b/core/ratings.go index a1f29129e6..c92b97773e 100644 --- a/core/ratings.go +++ b/core/ratings.go @@ -15,7 +15,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/golang/protobuf/proto" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) // ValidateRating - validates rating for API GET and Post/Update diff --git a/core/record_aging_notifier.go b/core/record_aging_notifier.go index 6240cdefd6..b857cc749c 100644 --- a/core/record_aging_notifier.go +++ b/core/record_aging_notifier.go @@ -6,7 +6,7 @@ import ( "time" "github.com/op/go-logging" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) const ( @@ -179,7 +179,11 @@ func (notifier *recordAgingNotifier) generateSellerDisputeNotifications() (*noti if err = notifier.datastore.Sales().UpdateSalesLastDisputeTimeoutNotifiedAt(updatedSales); err != nil { return nil, fmt.Errorf("update sales disputeTimeoutNotifiedAt: %s", err.Error()) } - return ¬ifierResult{len(notificationsToAdd), len(updatedSales), "sales"}, nil + return ¬ifierResult{ + notificationsMade: len(notificationsToAdd), + recordsUpdated: len(updatedSales), + subject: "sales", + }, nil } func (notifier *recordAgingNotifier) generateBuyerDisputeTimeoutNotifications() (*notifierResult, error) { @@ -258,7 +262,11 @@ func (notifier *recordAgingNotifier) generateBuyerDisputeTimeoutNotifications() if err = notifier.datastore.Purchases().UpdatePurchasesLastDisputeTimeoutNotifiedAt(updatedPurchases); err != nil { return nil, fmt.Errorf("updating lastDisputeTimeoutNotifiedAt on purchases: %s", err.Error()) } - return ¬ifierResult{len(notificationsToAdd), len(updatedPurchases), "purchaseTimeout"}, nil + return ¬ifierResult{ + notificationsMade: len(notificationsToAdd), + recordsUpdated: len(updatedPurchases), + subject: "purchaseTimeout", + }, nil } func (notifier *recordAgingNotifier) generateBuyerDisputeExpiryNotifications() (*notifierResult, error) { @@ -333,7 +341,11 @@ func (notifier *recordAgingNotifier) generateBuyerDisputeExpiryNotifications() ( if err = notifier.datastore.Purchases().UpdatePurchasesLastDisputeExpiryNotifiedAt(updatedPurchases); err != nil { return nil, fmt.Errorf("updating lastDisputeExpiryNotifiedAt on purchases: %s", err.Error()) } - return ¬ifierResult{len(notificationsToAdd), len(updatedPurchases), "purchaseExpire"}, nil + return ¬ifierResult{ + notificationsMade: len(notificationsToAdd), + recordsUpdated: len(updatedPurchases), + subject: "purchaseExpire", + }, nil } func (notifier *recordAgingNotifier) generateModeratorDisputeExpiryNotifications() (*notifierResult, error) { @@ -412,5 +424,9 @@ func (notifier *recordAgingNotifier) generateModeratorDisputeExpiryNotifications if err = notifier.datastore.Cases().UpdateDisputesLastDisputeExpiryNotifiedAt(updatedDisputes); err != nil { return nil, fmt.Errorf("updating lastDisputeExpiryNotifiedAt on disputes: %s", err.Error()) } - return ¬ifierResult{len(notificationsToAdd), len(updatedDisputes), "dispute"}, nil + return ¬ifierResult{ + notificationsMade: len(notificationsToAdd), + recordsUpdated: len(updatedDisputes), + subject: "dispute", + }, nil } diff --git a/core/record_aging_notifier_test.go b/core/record_aging_notifier_test.go index 8f618b0fec..e498740060 100644 --- a/core/record_aging_notifier_test.go +++ b/core/record_aging_notifier_test.go @@ -10,11 +10,11 @@ import ( "github.com/OpenBazaar/jsonpb" "github.com/op/go-logging" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test/factory" ) // DISPUTE CASES diff --git a/core/refunds.go b/core/refunds.go index c19f1eefb1..c1a87a4254 100644 --- a/core/refunds.go +++ b/core/refunds.go @@ -3,12 +3,15 @@ package core import ( "encoding/hex" "errors" + "github.com/phoreproject/pm-go/repo" + "math/big" + "strings" "time" "github.com/OpenBazaar/wallet-interface" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) // RefundOrder - refund buyer @@ -24,40 +27,43 @@ func (n *OpenBazaarNode) RefundOrder(contract *pb.RicardianContract, records []* return err } refundMsg.Timestamp = ts - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) if err != nil { return err } - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED { + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) + if err != nil { + return err + } + if order.Payment.Method == pb.Order_Payment_MODERATED { var ins []wallet.TransactionInput - var outValue int64 + outValue := big.NewInt(0) for _, r := range records { - if !r.Spent && r.Value > 0 { - outpointHash, err := hex.DecodeString(r.Txid) + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { + outpointHash, err := hex.DecodeString(strings.TrimPrefix(r.Txid, "0x")) if err != nil { return err } - outValue += r.Value + outValue = new(big.Int).Add(outValue, &r.Value) in := wallet.TransactionInput{OutpointIndex: r.Index, OutpointHash: outpointHash, Value: r.Value} ins = append(ins, in) } } - refundAddress, err := wal.DecodeAddress(contract.BuyerOrder.RefundAddress) + refundAddress, err := wal.DecodeAddress(order.RefundAddress) if err != nil { return err } output := wallet.TransactionOutput{ Address: refundAddress, - Value: outValue, + Value: *outValue, } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincode, err := hex.DecodeString(order.Payment.Chaincode) if err != nil { return err } - mPrivKey := n.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := n.MasterPrivateKey.ECPrivKey() if err != nil { return err } @@ -65,12 +71,12 @@ func (n *OpenBazaarNode) RefundOrder(contract *pb.RicardianContract, records []* if err != nil { return err } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(order.Payment.RedeemScript) if err != nil { return err } - - signatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, vendorKey, redeemScript, contract.BuyerOrder.RefundFee) + f, _ := new(big.Int).SetString(order.BigRefundFee, 10) + signatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, vendorKey, redeemScript, *f) if err != nil { return err } @@ -81,23 +87,24 @@ func (n *OpenBazaarNode) RefundOrder(contract *pb.RicardianContract, records []* } refundMsg.Sigs = sigs } else { - var outValue int64 + outValue := big.NewInt(0) for _, r := range records { - if r.Value > 0 { - outValue += r.Value + if r.Value.Cmp(big.NewInt(0)) > 0 { + outValue = new(big.Int).Add(outValue, &r.Value) } } - refundAddr, err := wal.DecodeAddress(contract.BuyerOrder.RefundAddress) + refundAddr, err := wal.DecodeAddress(order.RefundAddress) if err != nil { return err } - txid, err := wal.Spend(outValue, refundAddr, wallet.NORMAL, orderID, false) + txid, err := wal.Spend(*outValue, refundAddr, wallet.NORMAL, orderID, false) if err != nil { return err } txinfo := new(pb.Refund_TransactionInfo) txinfo.Txid = txid.String() - txinfo.Value = uint64(outValue) + txinfo.BigValue = outValue.String() + txinfo.ValueCurrency = contract.BuyerOrder.Payment.AmountCurrency refundMsg.RefundTransaction = txinfo } contract.Refund = refundMsg @@ -105,8 +112,15 @@ func (n *OpenBazaarNode) RefundOrder(contract *pb.RicardianContract, records []* if err != nil { return err } - n.SendRefund(contract.BuyerOrder.BuyerID.PeerID, contract) - n.Datastore.Sales().Put(orderID, *contract, pb.OrderState_REFUNDED, true) + err = n.SendRefund(order.BuyerID.PeerID, contract) + if err != nil { + // TODO: do we retry a failed refund send? + log.Error(err) + } + err = n.Datastore.Sales().Put(orderID, *contract, pb.OrderState_REFUNDED, true) + if err != nil { + log.Error(err) + } return nil } diff --git a/core/security.go b/core/security.go new file mode 100644 index 0000000000..0ae45f5ca3 --- /dev/null +++ b/core/security.go @@ -0,0 +1,89 @@ +package core + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha256" + "errors" + "io" + + "golang.org/x/crypto/hkdf" +) + +// Lock / Unlock wallet request +type ManageWalletRequest struct { + WalletPassword string `json:"password"` + UnlockTimestamp int `json:"unlockTimestamp,omitempty"` + SkipChangeMnemonicState bool `json:"skipCrypt,omitempty"` +} + +func hashPassword(password string) ([]byte, error) { + hkdfReader := hkdf.New(sha256.New, []byte(password), []byte("Mnemonic Encryption Salt"), nil) + aesKey := make([]byte, 32) + _, err := io.ReadFull(hkdfReader, aesKey) + if err != nil { + return nil, err + } + return aesKey, nil +} + +func EncryptMnemonic(mnemonic string, password string) (string, error) { + aesKey, err := hashPassword(password) + if err != nil { + return "", err + } + + block, err := aes.NewCipher(aesKey) + if err != nil { + return "", err + } + + gcm, err := cipher.NewGCM(block) + if err != nil { + return "", err + } + + nonce := make([]byte, gcm.NonceSize()) + _, err = io.ReadFull(rand.Reader, nonce) + if err != nil { + return "", err + } + + encryptedMnemonic := gcm.Seal(nonce, nonce, []byte(mnemonic), nil) + return string(encryptedMnemonic), nil +} + +func DecryptMnemonic(mnemonic string, password string) (string, error) { + aesKey, err := hashPassword(password) + if err != nil { + return "", err + } + + block, err := aes.NewCipher(aesKey) + if err != nil { + return "", err + } + + gcm, err := cipher.NewGCM(block) + if err != nil { + return "", err + } + + if len(mnemonic) < gcm.NonceSize() { + return "", errors.New("malformed ciphertext") + } + + mnemonicBytes := []byte(mnemonic) + + decrypted, err := gcm.Open(nil, + mnemonicBytes[:gcm.NonceSize()], + mnemonicBytes[gcm.NonceSize():], + nil, + ) + if err != nil { + return "", err + } + + return string(decrypted), nil +} diff --git a/core/signatures.go b/core/signatures.go index 9c9edba40a..4ddcc9ca0f 100644 --- a/core/signatures.go +++ b/core/signatures.go @@ -9,7 +9,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/golang/protobuf/proto" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) var ErrInvalidKey = errors.New("invalid key") diff --git a/core/signatures_test.go b/core/signatures_test.go index 84aa503944..cde087c32b 100644 --- a/core/signatures_test.go +++ b/core/signatures_test.go @@ -7,7 +7,7 @@ import ( "testing" coremock "github.com/ipfs/go-ipfs/core/mock" - "github.com/phoreproject/openbazaar-go/core" + "github.com/phoreproject/pm-go/core" ) func TestSigningingPayload(t *testing.T) { diff --git a/core/signed_listings.go b/core/signed_listings.go index 18024a8723..e1b3696b95 100644 --- a/core/signed_listings.go +++ b/core/signed_listings.go @@ -4,8 +4,7 @@ import ( "io/ioutil" "github.com/OpenBazaar/jsonpb" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/pb" ) func GetSignedListingFromPath(p string) (*pb.SignedListing, error) { @@ -21,40 +20,3 @@ func GetSignedListingFromPath(p string) (*pb.SignedListing, error) { } return sl, nil } - -func SetAcceptedCurrencies(sl *pb.SignedListing, currencies []string) { - sl.Listing.Metadata.AcceptedCurrencies = currencies -} - -func AssignMatchingCoupons(savedCoupons []repo.Coupon, sl *pb.SignedListing) error { - for _, coupon := range sl.Listing.Coupons { - for _, c := range savedCoupons { - if coupon.GetHash() == c.Hash { - coupon.Code = &pb.Listing_Coupon_DiscountCode{c.Code} - break - } - } - } - return nil -} - -func AssignMatchingQuantities(inventory map[int]int64, sl *pb.SignedListing) error { - for variant, count := range inventory { - for i, s := range sl.Listing.Item.Skus { - if variant == i { - s.Quantity = count - break - } - } - } - return nil -} - -func ApplyShippingOptions(sl *pb.SignedListing) error { - for _, so := range sl.Listing.ShippingOptions { - for _, ser := range so.Services { - ser.AdditionalItemPrice = ser.Price - } - } - return nil -} diff --git a/core/signed_listings_test.go b/core/signed_listings_test.go index 5530a9043c..9d30b947a4 100644 --- a/core/signed_listings_test.go +++ b/core/signed_listings_test.go @@ -1,18 +1,15 @@ package core_test import ( - "path/filepath" "testing" - "github.com/phoreproject/openbazaar-go/repo" - - "github.com/phoreproject/openbazaar-go/core" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" ) func TestOpenBazaarSignedListings_GetSignedListingFromPath(t *testing.T) { - absPathInvalid, _ := filepath.Abs("../test/contracts/signed_listings_1_invalid.json") - // Check for non-existent file _, err := core.GetSignedListingFromPath("nonsense.file") if err == nil { @@ -20,93 +17,35 @@ func TestOpenBazaarSignedListings_GetSignedListingFromPath(t *testing.T) { } // Check for invalid listing - _, err = core.GetSignedListingFromPath(absPathInvalid) + invalidBytes := []byte(`{ "listings": }`) + _, err = repo.UnmarshalJSONSignedListing(invalidBytes) if err == nil { t.Error(err) } } func TestOpenBazaarSignedListings_SetAcceptedCurrencies(t *testing.T) { - absPath, _ := filepath.Abs("../test/contracts/signed_listings_1.json") - currencies := []string{"TEST"} - - listing, err := core.GetSignedListingFromPath(absPath) - if err != nil { - t.Error(err) - } - oldCurrencies := listing.Listing.Metadata.AcceptedCurrencies - - core.SetAcceptedCurrencies(listing, currencies) - - if EqualStringSlices(listing.Listing.Metadata.AcceptedCurrencies, oldCurrencies) { - t.Error("Accepted currencies were not updated") - } - - if !EqualStringSlices(listing.Listing.Metadata.AcceptedCurrencies, currencies) { - t.Error("Accepted currencies changed but not correctly") - } -} - -func TestOpenBazaarSignedListings_AssignMatchingCoupons(t *testing.T) { - absPath, _ := filepath.Abs("../test/contracts/signed_listings_1.json") - coupons := []repo.Coupon{ - {"signed_listings_1", "test", "QmQ5vueeX64fsSo6fU9Z1dDFMR9rky5FjowEr7m7cSiGd8"}, - {"signed_listings_1", "bad", "BADHASH"}, - } - - listing, err := core.GetSignedListingFromPath(absPath) - if err != nil { - t.Error(err) - } - //old_coupons := listing.Listing.Coupons + currencies := []string{"ETH"} - core.AssignMatchingCoupons(coupons, listing) - - if listing.Listing.Coupons[0].GetDiscountCode() != "test" { - t.Error("Coupons were not assigned") - } - - if listing.Listing.Coupons[0].GetDiscountCode() == "bad" || listing.Listing.Coupons[1].GetDiscountCode() == "bad" { - t.Error("Coupons were assigned improperly") - } -} - -func TestOpenBazaarSignedListings_AssignMatchingQuantities(t *testing.T) { - absPath, _ := filepath.Abs("../test/contracts/signed_listings_1.json") - - inventory := map[int]int64{ - 0: 1000, - } - - listing, err := core.GetSignedListingFromPath(absPath) + fixtureBytes := factory.MustLoadListingFixture("v5-signed-physical-good-2") + slisting, err := repo.UnmarshalJSONSignedListing(fixtureBytes) if err != nil { t.Error(err) } + listing := slisting.GetListing() - err = core.AssignMatchingQuantities(inventory, listing) - if err != nil { - t.Error(err) - } + oldCurrencies := listing.GetAcceptedCurrencies() - if listing.Listing.Item.Skus[0].Quantity != 1000 { - t.Error("Inventory was not set properly") + if err := listing.SetAcceptedCurrencies(currencies...); err != nil { + t.Fatal(err) } -} -func TestOpenBazaarSignedListings_ApplyShippingOptions(t *testing.T) { - absPath, _ := filepath.Abs("../test/contracts/signed_listings_1.json") - - listing, err := core.GetSignedListingFromPath(absPath) - if err != nil { - t.Error(err) + if EqualStringSlices(listing.GetAcceptedCurrencies(), oldCurrencies) { + t.Error("Accepted currencies were not updated") } - option := listing.Listing.ShippingOptions[0].Services[0] - - core.ApplyShippingOptions(listing) - - if option.AdditionalItemPrice != 100 { - t.Error("Shipping options were not applied properly") + if !EqualStringSlices(listing.GetAcceptedCurrencies(), currencies) { + t.Error("Accepted currencies changed but not correctly") } } diff --git a/core/spend.go b/core/spend.go index 619e39ec10..ea3a2a110f 100644 --- a/core/spend.go +++ b/core/spend.go @@ -3,48 +3,78 @@ package core import ( "errors" "fmt" + "math/big" "strings" "time" "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcutil" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) // DefaultCurrencyDivisibility is the Divisibility of the Currency if not // defined otherwise -const DefaultCurrencyDivisibility uint32 = 1e8 +const DefaultCurrencyDivisibility uint = 8 type SpendRequest struct { decodedAddress btcutil.Address - Address string `json:"address"` - Amount int64 `json:"amount"` - FeeLevel string `json:"feeLevel"` - Memo string `json:"memo"` - OrderID string `json:"orderId"` - RequireAssociatedOrder bool `json:"requireOrder"` - Wallet string `json:"wallet"` - SpendAll bool `json:"spendAll"` + Amount string `json:"amount"` + Currency *repo.CurrencyDefinition `json:"currency"` + CurrencyCode string `json:"currencyCode"` + Address string `json:"address"` + FeeLevel string `json:"feeLevel"` + Memo string `json:"memo"` + OrderID string `json:"orderId"` + RequireAssociatedOrder bool `json:"requireOrder"` + SpendAll bool `json:"spendAll"` } type SpendResponse struct { - Amount int64 `json:"amount"` - ConfirmedBalance int64 `json:"confirmedBalance"` - Memo string `json:"memo"` - OrderID string `json:"orderId"` - Timestamp time.Time `json:"timestamp"` - Txid string `json:"txid"` - UnconfirmedBalance int64 `json:"unconfirmedBalance"` + Amount string `json:"amount"` + ConfirmedBalance string `json:"confirmedBalance"` + UnconfirmedBalance string `json:"unconfirmedBalance"` + Currency *repo.CurrencyDefinition `json:"currency"` + Memo string `json:"memo"` + OrderID string `json:"orderId"` + Timestamp time.Time `json:"timestamp"` + Txid string `json:"txid"` + PeerID string `json:"-"` + ConsumedInput bool `json:"-"` } // Spend will attempt to move funds from the node to the destination address described in the // SpendRequest for the amount indicated. func (n *OpenBazaarNode) Spend(args *SpendRequest) (*SpendResponse, error) { - var feeLevel wallet.FeeLevel + var ( + feeLevel wallet.FeeLevel + peerID string + + amt = new(big.Int) + lookupCode = args.CurrencyCode + ) - wal, err := n.Multiwallet.WalletForCurrencyCode(args.Wallet) + if lookupCode == "" && args.Currency != nil { + lookupCode = args.Currency.Code.String() + } + var currencyDef, err = n.LookupCurrency(lookupCode) + if err != nil { + return nil, repo.ErrCurrencyDefinitionUndefined + } + if args.Currency != nil && currencyDef.Divisibility != args.Currency.Divisibility { + currencyDef.Divisibility = args.Currency.Divisibility + if err := currencyDef.Valid(); err != nil { + return nil, err + } + } + + amt, ok := amt.SetString(args.Amount, 10) + if !ok { + return nil, ErrInvalidAmount + } + + wal, err := n.Multiwallet.WalletForCurrencyCode(lookupCode) if err != nil { return nil, ErrUnknownWallet } @@ -62,19 +92,21 @@ func (n *OpenBazaarNode) Spend(args *SpendRequest) (*SpendResponse, error) { switch strings.ToUpper(args.FeeLevel) { case "PRIORITY": - feeLevel = wallet.PRIOIRTY + feeLevel = wallet.PRIORITY case "NORMAL": feeLevel = wallet.NORMAL case "ECONOMIC": feeLevel = wallet.ECONOMIC + case "SUPER_ECONOMIC": + feeLevel = wallet.SUPER_ECONOMIC default: - feeLevel = wallet.NORMAL + feeLevel = wallet.ECONOMIC } - txid, err := wal.Spend(args.Amount, addr, feeLevel, args.OrderID, args.SpendAll) + txid, err := wal.Spend(*amt, addr, feeLevel, args.OrderID, args.SpendAll) if err != nil { switch { - case err == wallet.ErrorInsuffientFunds: + case err == wallet.ErrInsufficientFunds: return nil, ErrInsufficientFunds case err == wallet.ErrorDustAmount: return nil, ErrSpendAmountIsDust @@ -83,16 +115,31 @@ func (n *OpenBazaarNode) Spend(args *SpendRequest) (*SpendResponse, error) { } } + txn, err := wal.GetTransaction(*txid) + if err != nil { + log.Errorf("get txn failed : %v", err.Error()) + return nil, fmt.Errorf("failed retrieving new wallet balance: %s", err) + } + var ( thumbnail string title string memo = args.Memo + toAddress = args.Address ) - if contract != nil { + + if txn.ToAddress != "" { + toAddress = txn.ToAddress + } + + if contract != nil && contract.VendorListings[0] != nil { if contract.VendorListings[0].Item != nil && len(contract.VendorListings[0].Item.Images) > 0 { thumbnail = contract.VendorListings[0].Item.Images[0].Tiny title = contract.VendorListings[0].Item.Title } + if contract.VendorListings[0].VendorID != nil { + peerID = contract.VendorListings[0].VendorID.PeerID + } } if memo == "" && title != "" { memo = title @@ -100,9 +147,9 @@ func (n *OpenBazaarNode) Spend(args *SpendRequest) (*SpendResponse, error) { if err := n.Datastore.TxMetadata().Put(repo.Metadata{ Txid: txid.String(), - Address: args.Address, + Address: toAddress, Memo: memo, - OrderID: args.OrderID, + OrderId: args.OrderID, Thumbnail: thumbnail, CanBumpFee: false, }); err != nil { @@ -110,19 +157,21 @@ func (n *OpenBazaarNode) Spend(args *SpendRequest) (*SpendResponse, error) { } confirmed, unconfirmed := wal.Balance() - txn, err := wal.GetTransaction(*txid) + defn, err := n.LookupCurrency(wal.CurrencyCode()) if err != nil { - return nil, fmt.Errorf("failed retrieving new wallet balance: %s", err) + return nil, fmt.Errorf("wallet currency not found in dictionary") } return &SpendResponse{ Txid: txid.String(), - ConfirmedBalance: confirmed, - UnconfirmedBalance: unconfirmed, - Amount: -(txn.Value), + ConfirmedBalance: confirmed.Value.String(), + UnconfirmedBalance: unconfirmed.Value.String(), + Currency: &defn, + Amount: strings.TrimPrefix(txn.Value, "-"), Timestamp: txn.Timestamp, Memo: memo, OrderID: args.OrderID, + PeerID: peerID, }, nil } diff --git a/core/ulimit_unix.go b/core/ulimit_unix.go index 9f3a676c56..c6ac3f226c 100644 --- a/core/ulimit_unix.go +++ b/core/ulimit_unix.go @@ -31,6 +31,16 @@ func CheckAndSetUlimit() error { setting = true } + // If we're on darwin, work around the fact that Getrlimit reports + // the wrong value. See https://github.com/golang/go/issues/30401 + if runtime.GOOS == "darwin" && rLimit.Cur > 10240 { + // The max file limit is 10240, even though + // the max returned by Getrlimit is 1<<63-1. + // This is OPEN_MAX in sys/syslimits.h. + rLimit.Max = 10240 + rLimit.Cur = 10240 + } + // Try updating the limit. If it fails, try using the previous maximum instead // of our new maximum. Not all users have permissions to increase the maximum. err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) @@ -48,6 +58,6 @@ func CheckAndSetUlimit() error { return nil } - log.Debug("Successfully raised file descriptor limit to", fileDescriptorLimit) + log.Debug("Successfully raised file descriptor limit to", rLimit.Cur) return nil } diff --git a/core/utils.go b/core/utils.go index 7e64c44423..267d794a49 100644 --- a/core/utils.go +++ b/core/utils.go @@ -1,66 +1,21 @@ package core import ( - "crypto/sha256" - "errors" "fmt" + "math/big" + "strings" "time" util "gx/ipfs/QmNohiVssaPw3KVLZik59DBVGTSm2dGvYT9eoXt5DQ36Yz/go-ipfs-util" - ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" - cid "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" - ps "gx/ipfs/QmaCTz9RkrU13bm9kMB54f7atgqM4qkjDZpRwRoJiWXEqs/go-libp2p-peerstore" - mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/golang/protobuf/ptypes" google_protobuf "github.com/golang/protobuf/ptypes/timestamp" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) -// Hash with SHA-256 and encode as a multihash -func EncodeCID(b []byte) (*cid.Cid, error) { - multihash, err := EncodeMultihash(b) - if err != nil { - return nil, err - } - id := cid.NewCidV1(cid.Raw, *multihash) - return &id, err -} - -// EncodeMultihash - sha256 encode -func EncodeMultihash(b []byte) (*mh.Multihash, error) { - h := sha256.Sum256(b) - encoded, err := mh.Encode(h[:], mh.SHA2_256) - if err != nil { - return nil, err - } - multihash, err := mh.Cast(encoded) - if err != nil { - return nil, err - } - return &multihash, err -} - -// ExtractIDFromPointer Certain pointers, such as moderators, contain a peerID. This function -// will extract the ID from the underlying PeerInfo object. -func ExtractIDFromPointer(pi ps.PeerInfo) (string, error) { - if len(pi.Addrs) == 0 { - return "", errors.New("PeerInfo object has no addresses") - } - addr := pi.Addrs[0] - if addr.Protocols()[0].Code != ma.P_IPFS { - return "", errors.New("IPFS protocol not found in address") - } - val, err := addr.ValueForProtocol(ma.P_IPFS) - if err != nil { - return "", err - } - return val, nil -} - // FormatRFC3339PB returns the given `google_protobuf.Timestamp` as a RFC3339 // formatted string func FormatRFC3339PB(ts google_protobuf.Timestamp) string { @@ -71,27 +26,29 @@ func FormatRFC3339PB(ts google_protobuf.Timestamp) string { func (n *OpenBazaarNode) BuildTransactionRecords(contract *pb.RicardianContract, records []*wallet.TransactionRecord, state pb.OrderState) ([]*pb.TransactionRecord, *pb.TransactionRecord, error) { paymentRecords := []*pb.TransactionRecord{} payments := make(map[string]*pb.TransactionRecord) - wal, err := n.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, n.LookupCurrency) + if err != nil { + return nil, nil, err + } + wal, err := n.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return paymentRecords, nil, err } - // Consolidate any transactions with multiple outputs into a single record for _, r := range records { - record, ok := payments[r.Txid] - if ok { - record.Value += r.Value - payments[r.Txid] = record - } else { + _, ok := payments[r.Txid] + if !ok { tx := new(pb.TransactionRecord) tx.Txid = r.Txid - tx.Value = r.Value + tx.BigValue = r.Value.String() + tx.Currency = order.Payment.AmountCurrency + ts, err := ptypes.TimestampProto(r.Timestamp) if err != nil { return paymentRecords, nil, err } tx.Timestamp = ts - ch, err := chainhash.NewHashFromStr(tx.Txid) + ch, err := chainhash.NewHashFromStr(strings.TrimPrefix(tx.Txid, "0x")) if err != nil { return paymentRecords, nil, err } @@ -108,24 +65,31 @@ func (n *OpenBazaarNode) BuildTransactionRecords(contract *pb.RicardianContract, paymentRecords = append(paymentRecords, rec) } var refundRecord *pb.TransactionRecord - if contract != nil && (state == pb.OrderState_REFUNDED || state == pb.OrderState_DECLINED || state == pb.OrderState_CANCELED) && contract.BuyerOrder != nil && contract.BuyerOrder.Payment != nil { + if contract != nil && (state == pb.OrderState_REFUNDED || state == pb.OrderState_DECLINED || state == pb.OrderState_CANCELED) && order.Payment != nil { // For multisig we can use the outgoing from the payment address - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED || state == pb.OrderState_DECLINED || state == pb.OrderState_CANCELED { + if order.Payment.Method == pb.Order_Payment_MODERATED || state == pb.OrderState_DECLINED || state == pb.OrderState_CANCELED { for _, rec := range payments { - if rec.Value < 0 { + val, _ := new(big.Int).SetString(rec.BigValue, 10) + if val.Cmp(big.NewInt(0)) < 0 { refundRecord = new(pb.TransactionRecord) refundRecord.Txid = rec.Txid - refundRecord.Value = -rec.Value + refundRecord.BigValue = rec.BigValue + refundRecord.Currency = rec.Currency refundRecord.Confirmations = rec.Confirmations refundRecord.Height = rec.Height refundRecord.Timestamp = rec.Timestamp + + if !strings.HasPrefix(refundRecord.BigValue, "-") { + refundRecord.BigValue = "-" + refundRecord.BigValue + } break } } } else if contract.Refund != nil && contract.Refund.RefundTransaction != nil && contract.Refund.Timestamp != nil { + refund := repo.ToV5Refund(contract.Refund) refundRecord = new(pb.TransactionRecord) // Direct we need to use the transaction info in the contract's refund object - ch, err := chainhash.NewHashFromStr(contract.Refund.RefundTransaction.Txid) + ch, err := chainhash.NewHashFromStr(strings.TrimPrefix(contract.Refund.RefundTransaction.Txid, "0x")) if err != nil { return paymentRecords, refundRecord, err } @@ -133,9 +97,10 @@ func (n *OpenBazaarNode) BuildTransactionRecords(contract *pb.RicardianContract, if err != nil { return paymentRecords, refundRecord, nil } - refundRecord.Txid = contract.Refund.RefundTransaction.Txid - refundRecord.Value = int64(contract.Refund.RefundTransaction.Value) - refundRecord.Timestamp = contract.Refund.Timestamp + refundRecord.Txid = refund.RefundTransaction.Txid + refundRecord.BigValue = refund.RefundTransaction.BigValue + refundRecord.Currency = refund.RefundTransaction.ValueCurrency + refundRecord.Timestamp = refund.Timestamp refundRecord.Confirmations = confirmations refundRecord.Height = height } @@ -143,14 +108,9 @@ func (n *OpenBazaarNode) BuildTransactionRecords(contract *pb.RicardianContract, return paymentRecords, refundRecord, nil } -// NormalizeCurrencyCode standardizes the format for the given currency code -func NormalizeCurrencyCode(currencyCode string) string { - var c, err = repo.LoadCurrencyDefinitions().Lookup(currencyCode) - if err != nil { - log.Errorf("invalid currency code (%s): %s", currencyCode, err.Error()) - return "" - } - return c.String() +// LookupCurrency looks up the CurrencyDefinition from available currencies +func (n *OpenBazaarNode) LookupCurrency(currencyCode string) (repo.CurrencyDefinition, error) { + return repo.AllCurrencies().Lookup(currencyCode) } func (n *OpenBazaarNode) ValidateMultiwalletHasPreferredCurrencies(data repo.SettingsData) error { diff --git a/docker-compose.yml b/docker-compose.yml index 7e6f94ad3a..ebfe61ca96 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: dockerfile: Dockerfile.dev volumes: - obdata_dev:/var/lib/openbazaar - - .:/go/src/github.com/phoreproject/openbazaar-go + - .:/go/src/github.com/phoreproject/pm-go ports: - "5001:5001" - "5002:5002" @@ -15,7 +15,7 @@ services: security_opt: - seccomp:unconfined #req: delve for golang server: - image: openbazaar/server + image: phoremarketplace/server ports: - 5001 - 5002 diff --git a/docs/altcoins.md b/docs/altcoins.md index 1c7d65004c..9c424dd067 100644 --- a/docs/altcoins.md +++ b/docs/altcoins.md @@ -12,7 +12,7 @@ wallets, however OpenBazaar is a peer-to-peer application which means each addit a web wallet using a third party backend. An altcoin implementation could conceivably talk to a third party backend, but such an integration would be more complex than just plugging in the altcoin daemon. -While multiple wallets is not currently possible, it is possible to run more than one openbazaar-go instance on your machine. This means +While multiple wallets is not currently possible, it is possible to run more than one marketplace-go instance on your machine. This means you could have one store running Bitcoin and another store running an altcoin. The UI provides a convenient toggle to switch between running instances. @@ -22,8 +22,8 @@ The first thing you need to do is create a wallet implementation that conforms t The interface *should* be agnostic enough to support most bitcoin derived altcoins, though if you find it isn't just talk to us and we'll see if we can make the necessary changes. -The default wallet used openbazaar-go is a custom built SPV wallet based on the btcsuite library. However, there is a second wallet implementation -which talks to bitcoind using the JSON-RPC interface. The code, found [here](https://github.com/phoreproject/openbazaar-go/tree/master/bitcoin/bitcoind), could be +The default wallet used marketplace-go is a custom built SPV wallet based on the btcsuite library. However, there is a second wallet implementation +which talks to bitcoind using the JSON-RPC interface. The code, found [here](https://github.com/phoreproject/pm-go/tree/master/bitcoin/bitcoind), could be used as an example of how to integrate an altcoin. It should just be a matter of cloning the code into a new package and making the necessary changes. Most likely you will need to fork the [btcrpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient) to make it work with your altcoin as that library expects the data @@ -33,7 +33,7 @@ be returned and will thrown an error if it sees an altcoin address. The changes ### Exchange rates OpenBazaar has a convenience option to display prices in the user's domestic fiat currency and to price listings in fiat to avoid exchange rate -fluctuations. This functionality is provided by the a package implementing the [ExchangeRates](https://github.com/phoreproject/openbazaar-go/blob/master/bitcoin/exchangerates.go) interface. +fluctuations. This functionality is provided by the a package implementing the [ExchangeRates](https://github.com/phoreproject/pm-go/blob/master/bitcoin/exchangerates.go) interface. Basically it's just querying an external API to get the exchange rates and returning the results. If you want your altcoin implementation to allow pricing and displaying prices in fiat, you will need to swap out the default exchange rate implementation with one that returns the exchange rates for your altcoin. If you don't wish to enable @@ -85,7 +85,7 @@ If you wanted to use Zcash, say, you'd set it this: } ``` -The wallet selection switch can be found [in openbazaard.go](https://github.com/phoreproject/openbazaar-go/blob/master/openbazaard.go): +The wallet selection switch can be found [in marketplaced.go](https://github.com/phoreproject/pm-go/blob/master/marketplaced.go): ```go switch strings.ToLower(walletCfg.Type) { case "spvwallet": diff --git a/docs/bitcoind.md b/docs/bitcoind.md index 62e5ad8b2b..3dea09c94c 100644 --- a/docs/bitcoind.md +++ b/docs/bitcoind.md @@ -1,8 +1,8 @@ Using a Bitcoind Wallet ======================== -The default openbazaar-go wallet uses [simplified payment verification](https://bitcoin.org/en/developer-guide#simplified-payment-verification-spv) (SPV) to validate incoming bitcoin payments. -The benefit of this operating mode is that it achieves a high level of security without much overhead (bandwidth, CPU, etc) and is suitable for the average user. However, there are some downsides -to SPV that might warrant switching to a different wallent: +The SPV marketplace-go wallet uses [simplified payment verification](https://bitcoin.org/en/developer-guide#simplified-payment-verification-spv) to validate incoming bitcoin payments. (Note the +SPV wallet is no longer the default wallet used by marketplace-go and now uses an API-based wallet by default.) The benefit of this operating mode is that it achieves a high level of security without much overhead (bandwidth, CPU, etc) and is suitable for the average user. However, there are some downsides +to SPV that might warrant switching to a different wallet: 1. **Lack of full validation** @@ -46,7 +46,7 @@ Edit the config file to set a username and password: ``` Note: you must remove the # before saving. -Next, edit the following fields in the openbazaar-go config file found in the openbazaar2.0 data folder: +Next, edit the following fields in the marketplace-go config file found in the marketplace data folder: ``` "Wallet": { "Binary": "/path/to/bitcoind", @@ -57,11 +57,33 @@ Next, edit the following fields in the openbazaar-go config file found in the op ``` Obviously replacing the username and password with the username and password you set in the bitcoind config file. -That's it! Just start openbazaar-go. +Finally, edit the marketplace-go config file found within your marketplace data directory to change the `type` of BTC wallet used from "API" to "SPV". + +For example, if your BTC configuration looks like: +``` + "BTC": { + "API": [ + "https://btc.blockbook.api.phore.io/api" + ], + "APITestnet": [ + "https://tbtc.blockbook.api.phore.io/api" + ], + "FeeAPI": "https://btc.fees.openbazaar.org", + "HighFeeDefault": 50, + "LowFeeDefault": 1, + "MaxFee": 200, + "MediumFeeDefault": 10, + "TrustedPeer": "", + "Type": "API", + "WalletOptions": null + }, +``` + +You would update `"Type": "API",` to become `"Type": "SPV",`. + +That's it! Just start marketplace-go. ### Things to consider -- If bitcoind is running when you start openbazaar-go, it will shut it down and restart it. This is done because bitcoind needs to be run -with a specific set of options so that openbazaar-go can detect incoming payments. -- It's highly recommended you do not run bitcoind independently of openbazaar-go. If you receive a transaction while openbazaar-go is not -running, it will not be passed into openbazaar-go. Next time you start openbazaar-go it will not detect the payment. You can force it detect -the payment by running the resync blockchain API call, but it's a very heavyweight operation. +- If bitcoind is running when you start marketplace-go, it will shut it down and restart it. This is done because bitcoind needs to be run +with a specific set of options so that marketplace-go can detect incoming payments. +- The SPV wallet is slowly becoming deprecated on this project and may lag behind with updates. If any problems are found, please report them as a [new issue](https://github.com/phoreproject/pm-go/issues/new). diff --git a/docs/build.md b/docs/build.md index ccd9695dfc..360d3113d4 100644 --- a/docs/build.md +++ b/docs/build.md @@ -1,13 +1,13 @@ ### Build on your local platform You can find step by step tutorial here: -For Linux: [here](https://github.com/phoreproject/openbazaar-go/blob/master/docs/install-linux.md) +For Linux: [here](https://github.com/phoreproject/pm-go/blob/master/docs/install-linux.md) -For MacOS: [here](https://github.com/phoreproject/openbazaar-go/blob/master/docs/install-osx.md) +For MacOS: [here](https://github.com/phoreproject/pm-go/blob/master/docs/install-osx.md) -For Windows: [here](https://github.com/phoreproject/openbazaar-go/blob/master/docs/install-windows.md) +For Windows: [here](https://github.com/phoreproject/pm-go/blob/master/docs/install-windows.md) -For Raspberry: [here](https://github.com/phoreproject/openbazaar-go/blob/master/docs/install-pi3.md) +For Raspberry: [here](https://github.com/phoreproject/pm-go/blob/master/docs/install-pi3.md) ### Multiplatform build @@ -17,7 +17,7 @@ Multiplatform build use docker and go. #### Next steps 1. Start docker daemon -2. go to openbazaar-go directory `cd $GOPATH/src/github.com/phoreproject/openbazaar-go` +2. go to marketplace-go directory `cd $GOPATH/src/github.com/phoreproject/pm-go` 3. start 'build.sh' script `./build.sh` Compilation can take long time. diff --git a/docs/install-linux.md b/docs/install-linux.md index 8cc0dc674f..27124edd56 100644 --- a/docs/install-linux.md +++ b/docs/install-linux.md @@ -43,41 +43,41 @@ source ~/.profile Go should now be installed. -### Install openbazaar-go from master +### Install marketplace-go from master Checkout a copy of the source: ``` -go get github.com/phoreproject/openbazaar-go +go get github.com/phoreproject/pm-go ``` -It will use git to checkout the source code into `$GOPATH/src/github.com/phoreproject/openbazaar-go` +It will use git to checkout the source code into `$GOPATH/src/github.com/phoreproject/pm-go` Checkout a release version: ``` -git checkout v0.13.4 +git checkout v0.13.8 ``` -Note: `go get` leaves the repo pointing at `master` which is a branch used for active development. Running OpenBazaar from `master` is NOT recommended. Check the [release versions](https://github.com/phoreproject/openbazaar-go/releases) for the available versions that you use in checkout. +Note: `go get` leaves the repo pointing at `master` which is a branch used for active development. Running OpenBazaar from `master` is NOT recommended. Check the [release versions](https://github.com/phoreproject/pm-go/releases) for the available versions that you use in checkout. To compile and run the source: ``` ### To compile and run the source: ``` -cd $GOPATH/src/github.com/phoreproject/openbazaar-go -go run openbazaard.go start +cd $GOPATH/src/github.com/phoreproject/pm-go +go run marketplaced.go start ``` NOTE FOR NEW GOLANG HACKERS: In most projects you usually perform a `git clone` of the repository in order to start hacking. -With `openbazaar-go` There's no need to manually `git clone` the project, this is done for you when you issue the `go get github.com/phoreproject/openbazaar-go` command, doing a manual `git clone` will only give you a repository that's missing a lot of recursive dependencies and building headaches. +With `marketplace-go` There's no need to manually `git clone` the project, this is done for you when you issue the `go get github.com/phoreproject/pm-go` command, doing a manual `git clone` will only give you a repository that's missing a lot of recursive dependencies and building headaches. -If you are used to having all your other projects in some other place on disk, just make a symlink from `$GOPATH/src/github.com/phoreproject/openbazaar-go` into your usual workspace folder. +If you are used to having all your other projects in some other place on disk, just make a symlink from `$GOPATH/src/github.com/phoreproject/pm-go` into your usual workspace folder. -To start hacking and committing to your fork make sure to add your git remote into the `$GOPATH/src/github.com/phoreproject/openbazaar-go` folder with: +To start hacking and committing to your fork make sure to add your git remote into the `$GOPATH/src/github.com/phoreproject/pm-go` folder with: ``` -cd $GOPATH/src/github.com/phoreproject/openbazaar-go -git remote add myusername git@github.com:myusername/openbazaar-go.git +cd $GOPATH/src/github.com/phoreproject/pm-go +git remote add myusername git@github.com:myusername/pm-go.git ``` diff --git a/docs/install-osx.md b/docs/install-osx.md index 2593ea570a..cdf582f0db 100644 --- a/docs/install-osx.md +++ b/docs/install-osx.md @@ -44,51 +44,51 @@ source ~/.profile Go should now be ready. -### Install openbazaar-go from master +### Install marketplace-go from master Checkout a copy of the source: ``` -go get github.com/phoreproject/openbazaar-go +go get github.com/phoreproject/pm-go ``` -It will use git to checkout the source code into `$GOPATH/src/github.com/phoreproject/openbazaar-go` +It will use git to checkout the source code into `$GOPATH/src/github.com/phoreproject/pm-go` Checkout a release version: ``` -git checkout v0.13.4 +git checkout v0.13.8 ``` -Note: `go get` leaves the repo pointing at `master` which is a branch used for active development. Running OpenBazaar from `master` is NOT recommended. Check the [release versions](https://github.com/phoreproject/openbazaar-go/releases) for the available versions that you use in checkout. +Note: `go get` leaves the repo pointing at `master` which is a branch used for active development. Running OpenBazaar from `master` is NOT recommended. Check the [release versions](https://github.com/phoreproject/pm-go/releases) for the available versions that you use in checkout. -### Install openbazaar-go from other branch +### Install marketplace-go from other branch ``` cd $GOPATH/src/github.com/phoreproject -git clone --recursive -b BRANCH_NAME git@github.com:phoreproject/openbazaar-go +git clone --recursive -b BRANCH_NAME git@github.com:phoreproject/pm-go ``` ### To compile and run the source: ``` -cd $GOPATH/src/github.com/phoreproject/openbazaar-go -go run openbazaard.go start +cd $GOPATH/src/github.com/phoreproject/pm-go +go run marketplaced.go start ``` NOTE: If you have Xcode installed you may get the response `signal: killed`. If you do try running the following instead. ``` -go run --ldflags -s openbazaard.go start -t +go run --ldflags -s marketplaced.go start -t ``` NOTE FOR NEW GOLANG HACKERS: In most projects you usually perform a `git clone` of the repository in order to start hacking. -With `openbazaar-go` There's no need to manually `git clone` the project, this is done for you when you issue the `go get github.com/phoreproject/openbazaar-go` command, doing a manual `git clone` will only give you a repository that's missing a lot of recursive dependencies and building headaches. +With `pm-go` There's no need to manually `git clone` the project, this is done for you when you issue the `go get github.com/phoreproject/pm-go` command, doing a manual `git clone` will only give you a repository that's missing a lot of recursive dependencies and building headaches. -If you are used to having all your other projects in some other place on disk, just make a symlink from `$GOPATH/src/github.com/phoreproject/openbazaar-go` into your usual workspace folder. +If you are used to having all your other projects in some other place on disk, just make a symlink from `$GOPATH/src/github.com/phoreproject/pm-go` into your usual workspace folder. -To start hacking make sure to add your git remote into the `$GOPATH/src/github.com/phoreproject/openbazaar-go` folder with: +To start hacking make sure to add your git remote into the `$GOPATH/src/github.com/phoreproject/pm-go` folder with: ``` -cd $GOPATH/src/github.com/phoreproject/openbazaar-go -git remote add myusername git@github.com:myusername/openbazaar-go.git +cd $GOPATH/src/github.com/phoreproject/pm-go +git remote add myusername git@github.com:myusername/pm-go.git ``` diff --git a/docs/install-pi3.md b/docs/install-pi3.md index ddbdb82270..c19385cb01 100644 --- a/docs/install-pi3.md +++ b/docs/install-pi3.md @@ -46,24 +46,24 @@ source ~/.profile Go should now be installed. -### Install openbazaar-go +### Install marketplace-go Checkout a copy of the source: ``` -go get github.com/phoreproject/openbazaar-go +go get github.com/phoreproject/pm-go ``` -It will use git to checkout the source code into `$GOPATH/src/github.com/phoreproject/openbazaar-go` +It will use git to checkout the source code into `$GOPATH/src/github.com/phoreproject/pm-go` Checkout a release version: ``` -git checkout v0.13.4 +git checkout v0.13.8 ``` -Note: `go get` leaves the repo pointing at `master` which is a branch used for active development. Running OpenBazaar from `master` is NOT recommended. Check the [release versions](https://github.com/phoreproject/openbazaar-go/releases) for the available versions that you use iin checkout. +Note: `go get` leaves the repo pointing at `master` which is a branch used for active development. Running OpenBazaar from `master` is NOT recommended. Check the [release versions](https://github.com/phoreproject/pm-go/releases) for the available versions that you use iin checkout. To compile and run the source using the path above, WITHOUT encrypting the database: ``` -cd $GOPATH/src/github.com/phoreproject/openbazaar-go -go run openbazaard.go start +cd $GOPATH/src/github.com/phoreproject/pm-go +go run marketplaced.go start ``` diff --git a/docs/install-windows.md b/docs/install-windows.md index de5253b635..4bec5096ab 100644 --- a/docs/install-windows.md +++ b/docs/install-windows.md @@ -3,7 +3,7 @@ WINDOWS INSTALL NOTES ### Install dependencies -You need to have Go, Git, and GCC installed to compile and run the OpenBazaar-Go daemon. +You need to have Go, Git, and GCC installed to compile and run the Marketplace-Go daemon. - **Go v1.11** + https://golang.org/dl @@ -22,13 +22,13 @@ Create a directory to store all your Go projects (e.g. `C:\goprojects`): - Set your GOPATH + Open the command prompt and type: `setx GOPATH "C:\goprojects"` -### Install openbazaar-go +### Install marketplace-go -- Install `openbazaar-go`: - + Open the command prompt and run: `go get github.com/phoreproejct/openbazaar-go`. This will use git to checkout the source code into `%GOPATH%\src\github.com\phoreproject\openbazaar-go`. +- Install `marketplace-go`: + + Open the command prompt and run: `go get github.com/phoreproject/pm-go`. This will use git to checkout the source code into `%GOPATH%\src\github.com\phoreproject\pm-go`. - Checkout an Phore Marketplace release: - + Run `git checkout v0.13.4` to checkout a release version. - + Note: `go get` leaves the repo pointing at `master` which is a branch used for active development. Running Phore Marketplace from `master` is NOT recommended. Check the [release versions](https://github.com/phoreproject/openbazaar-go/releases) for the available versions that you use in checkout. -- To compile and run `openbazaar-go`: - + Open the command prompt and navigate the source directory: `cd %GOPATH%\src\github.com\phoreproject\openbazaar-go` - + Type: `go run openbazaard.go start` + + Run `git checkout v0.13.8` to checkout a release version. + + Note: `go get` leaves the repo pointing at `master` which is a branch used for active development. Running Phore Marketplace from `master` is NOT recommended. Check the [release versions](https://github.com/phoreproject/pm-go/releases) for the available versions that you use in checkout. +- To compile and run `marketplace-go`: + + Open the command prompt and navigate the source directory: `cd %GOPATH%\src\github.com\phoreproject\pm-go` + + Type: `go run marketplaced.go start` diff --git a/docs/multipleInstances.md b/docs/multipleInstances.md index f1ff59693e..17d3943cdc 100644 --- a/docs/multipleInstances.md +++ b/docs/multipleInstances.md @@ -6,8 +6,8 @@ Install and Run Multiple Servers In your server directory, use the datadir option to init the server with a new data directory. This will create the data directory if it doesn't already exist, and generate all the files needed to run the server from that directory. Example: -Windows: `go run openbazaard.go init -d=c://path/to/data/directory` -Linux/MacOS: `go run openbazaard.go init -d=/path/to/data/directory` +Windows: `go run marketplaced.go init -d=c://path/to/data/directory` +Linux/MacOS: `go run marketplaced.go init -d=/path/to/data/directory` ### Change the Ports in the Config File @@ -32,5 +32,5 @@ Example: You can now run an instance of the server from the new data directory with the daradir option. Multiple instances can be run simultaneously, one for each data directory you've created. Example: -Windows: `go run openbazaard.go start -d=c://path/to/data/directory` -Linux/MacOS: `go run openbazaard.go start -d=/path/to/data/directory` +Windows: `go run marketplaced.go start -d=c://path/to/data/directory` +Linux/MacOS: `go run marketplaced.go start -d=/path/to/data/directory` diff --git a/docs/security.md b/docs/security.md index a7508de2a1..1e952b7212 100644 --- a/docs/security.md +++ b/docs/security.md @@ -4,15 +4,15 @@ The following is a list of security features that it's recommended you take to s ### Database Encryption -The openbazaar-go daemon stores all of its user data (keys, orders, sales, metadata, etc) in a sqlite database found in the `~/openbazaar2.0/datastore` +The marketplace-go daemon stores all of its user data (keys, orders, sales, metadata, etc) in a sqlite database found in the `~/PhoreMarketplace/datastore` directory. This database can be encrypted using [sqlcipher](https://www.zetetic.net/sqlcipher/). #### Encrypting the database There are several ways to enable database encryption. -1. Running the openbazaar-go `start` or `init` commands the very first time using the `--password` flag (followed by your password) will encrypt the database with that password. Note: +1. Running the marketplace-go `start` or `init` commands the very first time using the `--password` flag (followed by your password) will encrypt the database with that password. Note: the password will be visible in your terminal if you launch from the terminal. -2. Running the openbazaar-go `encryptdatabase` at any time will enable you to encrypt the database. (Unlike the previous option, the terminal input will be obfuscated.) +2. Running the marketplace-go `encryptdatabase` at any time will enable you to encrypt the database. (Unlike the previous option, the terminal input will be obfuscated.) #### Running with an encrypted database Again two options: @@ -26,11 +26,11 @@ You can decrypt the database by running the `decryptdatabase` command. Note: thi ### API Authentication -If you are running the openbazaar-go daemon on a remote machine you MUST enable API authentication otherwise anyone will be able to log into your +If you are running the marketplace-go daemon on a remote machine you MUST enable API authentication otherwise anyone will be able to log into your node, steal your bitcoins, and view your order/sales history. Additionally, you MUST enable SSL (see below) otherwise your authentication credentials will be sent to the remote node in the clear (unencrypted) ― meaning they could be intercepted by anyone viewing your network traffic. -The settings to enable authentication are found in the config file located in the `openbazaar2.0` data directory. To enable authentication first set the +The settings to enable authentication are found in the config file located in the `PhoreMarketplace` data directory. To enable authentication first set the JSON-API authentication boolean to true: ``` { @@ -63,7 +63,7 @@ Alternatively, you can use basic authentication by setting a username and passwo ``` The password must be saved as the hex-encoded SHA-256 hash of your password. The password you send to authenticate must be the hash preimage as it will hashed and compared to the hash in the config file. -You can have openbazaar-go hash and save the username and password for you by running the `setapicreds` command. +You can have marketplace-go hash and save the username and password for you by running the `setapicreds` command. The username and password need to be included in the request header following [RFC 2617](https://www.ietf.org/rfc/rfc2617.txt) where the username and password are encoded as `base64encode(username + ":" + password)`: ``` @@ -75,7 +75,7 @@ http://username:password@localhost:8080/ob/ ``` ### SSL As mentioned above, NEVER allow outside internet access without both enabling authentication and SSL as your authentication creditials will be sent to the remote node unencrypted otherwise. -The instructions to set up SSL can be found in a separate [doc](https://github.com/phoreproject/openbazaar-go/blob/master/docs/ssl.md). +The instructions to set up SSL can be found in a separate [doc](https://github.com/phoreproject/pm-go/blob/master/docs/ssl.md). ### Restrict Access By IP You can (and probably should) restrict access to the API to specific IP addresses. To do so you can either enter them in the config file: @@ -86,6 +86,6 @@ You can (and probably should) restrict access to the API to specific IP addresse } } ``` -Or pass them in at start up: `openbazaar-go start -a 69.89.31.226` +Or pass them in at start up: `marketplace-go start -a 69.89.31.226` If `AllowIPs` is set to `[]` in the config file and the `-a` flag is omitted at start up, then all IP addresses will be allowed. diff --git a/docs/ssl.md b/docs/ssl.md index 0f00145f66..1e20eaf82b 100644 --- a/docs/ssl.md +++ b/docs/ssl.md @@ -1,14 +1,14 @@ SSL SETUP FOR JSON API ====================== -This guide is for setting up SSL encryption on the openbazaar-go JSON API on Linux-based servers. If you plan on running openbazaar-go on a remote server you MUST use SSL otherwise your authentication information will be sent in the clear, allowing attackers to gain access to your server and steal your bitcoins and OpenBazaar identity (in addition to seeing your purchase/sales history). Follow these three steps exactly to enable SSL. +This guide is for setting up SSL encryption on the marketplace-go JSON API on Linux-based servers. If you plan on running marketplace-go on a remote server you MUST use SSL otherwise your authentication information will be sent in the clear, allowing attackers to gain access to your server and steal your bitcoins and OpenBazaar identity (in addition to seeing your purchase/sales history). Follow these three steps exactly to enable SSL. ### Step 1: Generate SSL certificates If you have an SSL certificate issued to you by a Certificate Authority, you can skip this step. -First, enter the OpenBazaar data directory. +First, enter the PhoreMarketplace data directory. ``` -cd .openbazaar2.0 +cd .PhoreMarketplace ``` Next enter the following commands to generate a self-signed server certificate. If running a remote server, on the fourth line, be sure to replace \ with the ip of your remote server. ``` @@ -23,7 +23,7 @@ The above commands will generate three files that are of interest to us: `server ### Step 2: Edit the config file -You need to edit the openbazaar-go config file (found in the data folder): +You need to edit the marketplace-go config file (found in the data folder): ``` nano config ``` @@ -67,6 +67,6 @@ To download the `OpenBazaar.crt` from your remote server you can use any file tr Once `OpenBazaar.crt` is on your local computer you should just be able to double click it to install it. -From here you can run openbazaar-go as normal. In the client you will need to check `Use SSL` in the server configuration screen. +From here you can run marketplace-go as normal. In the client you will need to check `Use SSL` in the server configuration screen. SSL should now be configured. diff --git a/docs/tor.md b/docs/tor.md index 153c06b443..cd4e0f5b76 100644 --- a/docs/tor.md +++ b/docs/tor.md @@ -46,20 +46,20 @@ Or the following for dual-stack mode: In both cases substituting the onion address above for your onion address found as the prefix of the `.onion_key` file in the same data directory. ##### Via runtime option -For Tor-only mode run openbazaar-go with the `--tor` flag. +For Tor-only mode run marketplace-go with the `--tor` flag. Example: ``` -./openbazaar-go start --tor +./marketplace-go start --tor ``` For dual-stack mode use the `--dualstack` flag. Example: ``` -./openbazaar-go start --dualstack +./marketplace-go start --dualstack ``` The runtime option will override the swarm address configuration in the config file and use default ports. ## Advanced Tor configuration -If you changed the tor control port in your `torrc` file or you require authentication you can set both the control port and your tor control password in the openbazaar-go config file: +If you changed the tor control port in your `torrc` file or you require authentication you can set both the control port and your tor control password in the marketplace-go config file: ``` "Tor-config": { "Password": "yourpassword", @@ -69,11 +69,11 @@ If you changed the tor control port in your `torrc` file or you require authenti Aternatively you can pass the tor control password in as a start up option: ``` -./openbazaar-go start --torpassword yourpassword +./marketplace-go start --torpassword yourpassword ``` ## Configuring the client -The openbazaar-desktop client **must** also be configured to run over Tor as some html tags, such as `IMG`, are allowed in the profile and store data and will trigger the client to make outgoing network calls. +The pm-desktop client **must** also be configured to run over Tor as some html tags, such as `IMG`, are allowed in the profile and store data and will trigger the client to make outgoing network calls. To set tor in the reference client select `Manage Servers` from the menu then check `Use Tor` and make sure the socks5 proxy url is correct. @@ -82,10 +82,10 @@ To set tor in the reference client select `Manage Servers` from the menu then ch ### Important Privacy Considerations All nodes in OpenBazaar are identified by a peer ID such as `QmNgBZN7z1CfMLbwyEwnGoixjbSaBcP9fS5ecMzZwCq3Ku`. Other nodes in the network will associate your peer ID with your -network addresses (whether IPv4, IPv6, or onion). If you run openbazaar-go in the clear even *once*, you must assume *someone* has recorded the mapping between your +network addresses (whether IPv4, IPv6, or onion). If you run marketplace-go in the clear even *once*, you must assume *someone* has recorded the mapping between your peer ID and your IP address. Therefore using a given peer ID in the clear, *then* switching to Tor-only mode will almost certainly blow your privacy. Therefore if you wish to run in Tor-only mode, it is *highly recommended* that you use a fresh peer ID which has never been used on the network and has not had a chance -to get associated with your actual IP address. To get a new peer ID you can just delete your data folder and restart openbazaar-go. It will create a new peer ID on start up. +to get associated with your actual IP address. To get a new peer ID you can just delete your data folder and restart marketplace-go. It will create a new peer ID on start up. -Finally, as noted in the [bitcoind doc](https://github.com/phoreproject/openbazaar-go/blob/master/docs/bitcoind.md) the default SPV wallet has known privacy issues which may allow attackers to associate your bitcoin transactions with your OpenBazaar peer ID. For those looking to maximize privacy it's recommended you switch out the default wallet for bitcoind. See the bitcoind doc for instructions. +Finally, as noted in the [bitcoind doc](https://github.com/phoreproject/pm-go/blob/master/docs/bitcoind.md) the default SPV wallet has known privacy issues which may allow attackers to associate your bitcoin transactions with your OpenBazaar peer ID. For those looking to maximize privacy it's recommended you switch out the default wallet for bitcoind. See the bitcoind doc for instructions. diff --git a/ipfs/add.go b/ipfs/add.go index 496b90f7bd..478b6c4b0a 100644 --- a/ipfs/add.go +++ b/ipfs/add.go @@ -61,7 +61,10 @@ func GetHash(n *core.IpfsNode, reader io.Reader) (string, error) { if err != nil { return "", err } - f.Write(b) + _, err = f.Write(b) + if err != nil { + return "", err + } defer f.Close() return GetHashOfFile(n, f.Name()) } diff --git a/ipfs/add_test.go b/ipfs/add_test.go index 60acb667fd..37b0100a73 100644 --- a/ipfs/add_test.go +++ b/ipfs/add_test.go @@ -10,16 +10,22 @@ import ( ) func TestMain(m *testing.M) { - setup() + mustSetup() retCode := m.Run() teardown() os.Exit(retCode) } -func setup() { - os.MkdirAll(path.Join(os.TempDir(), "root"), os.ModePerm) +func mustSetup() { + err := os.MkdirAll(path.Join(os.TempDir(), "root"), os.ModePerm) + if err != nil { + panic(err.Error()) + } d := []byte("hello world") - ioutil.WriteFile(path.Join(os.TempDir(), "root", "test"), d, os.ModePerm) + err = ioutil.WriteFile(path.Join(os.TempDir(), "root", "test"), d, os.ModePerm) + if err != nil { + panic(err.Error()) + } } func teardown() { diff --git a/ipfs/cid.go b/ipfs/cid.go new file mode 100644 index 0000000000..88b91248ce --- /dev/null +++ b/ipfs/cid.go @@ -0,0 +1,52 @@ +package ipfs + +import ( + "crypto/sha256" + "errors" + + ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" + "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" + ps "gx/ipfs/QmaCTz9RkrU13bm9kMB54f7atgqM4qkjDZpRwRoJiWXEqs/go-libp2p-peerstore" + mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" +) + +// EncodeCID - Hash with SHA-256 and encode as a multihash +func EncodeCID(b []byte) (*cid.Cid, error) { + multihash, err := EncodeMultihash(b) + if err != nil { + return nil, err + } + id := cid.NewCidV1(cid.Raw, *multihash) + return &id, err +} + +// EncodeMultihash - sha256 encode +func EncodeMultihash(b []byte) (*mh.Multihash, error) { + h := sha256.Sum256(b) + encoded, err := mh.Encode(h[:], mh.SHA2_256) + if err != nil { + return nil, err + } + multihash, err := mh.Cast(encoded) + if err != nil { + return nil, err + } + return &multihash, err +} + +// ExtractIDFromPointer Certain pointers, such as moderators, contain a peerID. This function +// will extract the ID from the underlying PeerInfo object. +func ExtractIDFromPointer(pi ps.PeerInfo) (string, error) { + if len(pi.Addrs) == 0 { + return "", errors.New("PeerInfo object has no addresses") + } + addr := pi.Addrs[0] + if addr.Protocols()[0].Code != ma.P_IPFS { + return "", errors.New("IPFS protocol not found in address") + } + val, err := addr.ValueForProtocol(ma.P_IPFS) + if err != nil { + return "", err + } + return val, nil +} diff --git a/ipfs/config.go b/ipfs/config.go index 27e6e0f9af..f3ec28c7b9 100644 --- a/ipfs/config.go +++ b/ipfs/config.go @@ -15,7 +15,7 @@ import ( "github.com/ipfs/go-ipfs/repo" ) -var routerCacheURI string +//var routerCacheURI string // UpdateIPFSGlobalProtocolVars is a hack to manage custom protocol strings // which do not yet have an API to manage their configuration @@ -34,7 +34,7 @@ func UpdateIPFSGlobalProtocolVars(testnetEnable bool) { // PrepareIPFSConfig builds the configuration options for the internal // IPFS node. func PrepareIPFSConfig(r repo.Repo, routerAPIEndpoint string, testEnable, regtestEnable bool) *ipfscore.BuildCfg { - routerCacheURI = routerAPIEndpoint + //routerCacheURI = routerAPIEndpoint ncfg := &ipfscore.BuildCfg{ Repo: r, Online: true, @@ -55,7 +55,7 @@ func PrepareIPFSConfig(r repo.Repo, routerAPIEndpoint string, testEnable, regtes } func constructRouting(ctx context.Context, host p2phost.Host, dstore ds.Batching, validator record.Validator) (routing.IpfsRouting, error) { - dhtRouting, err := dht.New( + return dht.New( ctx, host, dhtopts.Datastore(dstore), dhtopts.Validator(validator), @@ -64,12 +64,6 @@ func constructRouting(ctx context.Context, host p2phost.Host, dstore ds.Batching IPFSProtocolDHTMainnetLegacy, ), ) - if err != nil { - return nil, err - } - apiRouter := NewAPIRouter(routerCacheURI, dhtRouting.Validator) - cachingRouter := NewCachingRouter(dhtRouting, &apiRouter) - return cachingRouter, nil } func constructRegtestRouting(ctx context.Context, host p2phost.Host, dstore ds.Batching, validator record.Validator) (routing.IpfsRouting, error) { @@ -78,28 +72,20 @@ func constructRegtestRouting(ctx context.Context, host p2phost.Host, dstore ds.B dhtopts.Datastore(dstore), dhtopts.Validator(validator), dhtopts.Protocols( - IPFSProtocolKademliaMainnetOne, - IPFSProtocolDHTMainnetLegacy, + IPFSProtocolKademliaTestnetOne, + IPFSProtocolAppTestnetOne, ), ) } func constructTestnetRouting(ctx context.Context, host p2phost.Host, dstore ds.Batching, validator record.Validator) (routing.IpfsRouting, error) { - var ( - dhtRouting, err = dht.New( - ctx, host, - dhtopts.Datastore(dstore), - dhtopts.Validator(validator), - dhtopts.Protocols( - IPFSProtocolKademliaTestnetOne, - IPFSProtocolAppTestnetOne, - ), - ) + return dht.New( + ctx, host, + dhtopts.Datastore(dstore), + dhtopts.Validator(validator), + dhtopts.Protocols( + IPFSProtocolKademliaTestnetOne, + IPFSProtocolAppTestnetOne, + ), ) - if err != nil { - return nil, err - } - apiRouter := NewAPIRouter(routerCacheURI, dhtRouting.Validator) - cachingRouter := NewCachingRouter(dhtRouting, &apiRouter) - return cachingRouter, nil } diff --git a/ipfs/dag.go b/ipfs/dag.go index b4f37147e3..7a3904905e 100644 --- a/ipfs/dag.go +++ b/ipfs/dag.go @@ -63,7 +63,10 @@ func RemoveAll(nd *core.IpfsNode, peerID string, quorum uint) error { return err } for _, id := range graph { - nd.DAG.Remove(context.Background(), id) + err = nd.DAG.Remove(context.Background(), id) + if err != nil { + log.Error(err) + } } return nil } diff --git a/ipfs/identity.go b/ipfs/identity.go index 9555b4697f..5907b49e7b 100644 --- a/ipfs/identity.go +++ b/ipfs/identity.go @@ -16,6 +16,11 @@ func init() { peer.AdvancedEnableInlining = false } +// PubKey wraps IPFS's underlying PubKey dependency +type PubKey interface { + crypto.PubKey +} + // IdentityFromKey returns IPFS peer identity based on private key func IdentityFromKey(privkey []byte) (config.Identity, error) { ident := config.Identity{} @@ -40,7 +45,10 @@ func IdentityFromKey(privkey []byte) (config.Identity, error) { // IdentityKeyFromSeed generates an OpenBazaar seed IPFS key pair func IdentityKeyFromSeed(seed []byte, bits int) ([]byte, error) { hm := hmac.New(sha256.New, []byte("OpenBazaar seed")) - hm.Write(seed) + _, err := hm.Write(seed) + if err != nil { + return nil, err + } reader := bytes.NewReader(hm.Sum(nil)) sk, _, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, bits, reader) if err != nil { diff --git a/ipfs/pin.go b/ipfs/pin.go index 5fea046a4b..547f3e5f44 100644 --- a/ipfs/pin.go +++ b/ipfs/pin.go @@ -2,30 +2,39 @@ package ipfs import ( "context" - - "github.com/ipfs/go-ipfs/core/coreapi" + "fmt" + "strings" coreiface "gx/ipfs/QmXLwxifxwfc2bAwq6rdjbYqAsGzWsDE9RM5TWMGtykyj6/interface-go-ipfs-core" options "gx/ipfs/QmXLwxifxwfc2bAwq6rdjbYqAsGzWsDE9RM5TWMGtykyj6/interface-go-ipfs-core/options" "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/core/coreapi" ) -/* Recursively un-pin a directory given its hash. - This will allow it to be garbage collected. */ +// UnPinDir removes all content from the published root directory to be +// garbage collected later by IPFS. func UnPinDir(n *core.IpfsNode, rootHash string) error { + // attempt to properly handle variations on rootHash + if !strings.HasPrefix(rootHash, "/ipfs/") { + rootHash = fmt.Sprintf("/ipfs/%s", rootHash) + } + if !strings.HasPrefix(rootHash, "/ipfs") && strings.HasPrefix(rootHash, "/") { + rootHash = fmt.Sprintf("/ipfs%s", rootHash) + } + api, err := coreapi.NewCoreAPI(n) if err != nil { - return err + return fmt.Errorf("ipfs api: %s", err) } - p, err := coreiface.ParsePath("/ipfs/" + rootHash) + p, err := coreiface.ParsePath(rootHash) if err != nil { - return err + return fmt.Errorf("parsing ipfs path (%s): %s", rootHash, err) } rp, err := api.ResolvePath(context.Background(), p) if err != nil { - return err + return fmt.Errorf("resolve path (%s): %s", p, err) } return api.Pin().Rm(context.Background(), rp, options.Pin.RmRecursive(true)) diff --git a/ipfs/plugins.go b/ipfs/plugins.go index 835da20a2d..3a6da3b017 100644 --- a/ipfs/plugins.go +++ b/ipfs/plugins.go @@ -8,7 +8,7 @@ import ( var pluginOnce sync.Once // InstallDatabasePlugins installs the default database plugins -// used by openbazaar-go. This function is guarded by a sync.Once +// used by marketplace-go. This function is guarded by a sync.Once // so it isn't accidentally called more than once. func InstallDatabasePlugins() { pluginOnce.Do(func() { diff --git a/ipfs/pointers.go b/ipfs/pointers.go index 4c0a78e1b1..6f871865f2 100644 --- a/ipfs/pointers.go +++ b/ipfs/pointers.go @@ -110,7 +110,10 @@ func addPointer(dht *routing.IpfsDHT, ctx context.Context, k *cid.Cid, pi ps.Pee wg.Add(1) go func(p peer.ID) { defer wg.Done() - putPointer(ctx, dht, p, pi, k.Bytes()) + err := putPointer(ctx, dht, p, pi, k.Bytes()) + if err != nil { + log.Error(err) + } }(p) } wg.Wait() @@ -155,7 +158,10 @@ func getMagicID(entropy []byte) (peer.ID, error) { return "", err } hash := sha256.New() - hash.Write(entropy) + _, err = hash.Write(entropy) + if err != nil { + return "", err + } hashedEntropy := hash.Sum(nil) magicBytes = append(magicBytes, hashedEntropy[:20]...) h, err := multihash.Encode(magicBytes, multihash.SHA2_256) diff --git a/ipfs/pubsub.go b/ipfs/pubsub.go index b17fefbe73..166cf3abf4 100644 --- a/ipfs/pubsub.go +++ b/ipfs/pubsub.go @@ -16,12 +16,7 @@ import ( "time" ) -const ( - MessageTopicPrefix = "/offlinemessage/" - GlobalIPNSTopic = "IPNS" - GlobalBlockTopic = "BLOCK" - GlobalCIDTopic = "CID" -) +const messageTopicPrefix = "/offlinemessage/" type Pubsub struct { Subscriber *PubsubSubscriber @@ -79,40 +74,42 @@ func NewPubsubSubscriber(ctx context.Context, host p2phost.Host, cr routing.Cont func (p *PubsubPublisher) Publish(ctx context.Context, topic string, data []byte) error { p.mx.Lock() - _, ok := p.subs[topic] + id := messageTopicPrefix + topic + _, ok := p.subs[id] if !ok { - p.subs[topic] = struct{}{} + p.subs[id] = struct{}{} p.mx.Unlock() - bootstrapPubsub(p.ctx, p.cr, p.host, topic) + bootstrapPubsub(p.ctx, p.cr, p.host, id) } else { p.mx.Unlock() } - log.Debugf("PubsubPublish: publish data for %s", topic) - return p.ps.Publish(topic, data) + log.Debugf("PubsubPublish: publish data for %s", id) + return p.ps.Publish(id, data) } func (r *PubsubSubscriber) Subscribe(ctx context.Context, topic string) (chan []byte, error) { r.mx.Lock() // see if we already have a pubsub subscription; if not, subscribe - _, ok := r.subs[topic] + id := messageTopicPrefix + topic + _, ok := r.subs[id] resp := make(chan []byte) if !ok { - sub, err := r.ps.Subscribe(topic) + sub, err := r.ps.Subscribe(id) if err != nil { r.mx.Unlock() return nil, err } - log.Debugf("PubsubSubscribe: subscribed to %s", topic) + log.Debugf("PubsubSubscribe: subscribed to %s", id) - r.subs[topic] = sub + r.subs[id] = sub ctx, cancel := context.WithCancel(r.ctx) - go r.handleSubscription(sub, topic, resp, cancel) - go bootstrapPubsub(ctx, r.cr, r.host, topic) + go r.handleSubscription(sub, id, resp, cancel) + go bootstrapPubsub(ctx, r.cr, r.host, id) } r.mx.Unlock() return resp, nil diff --git a/ipfs/resolve.go b/ipfs/resolve.go index 09ef4c1aaf..c30b3a58a7 100644 --- a/ipfs/resolve.go +++ b/ipfs/resolve.go @@ -2,24 +2,26 @@ package ipfs import ( "context" - ds "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" - "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" - + "fmt" + "runtime/debug" "time" ipath "gx/ipfs/QmQAgv6Gaoe2tQpcabqwKXKChp2MZ7i3UXv9DqTTaxCaTR/go-path" + ds "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" ipnspb "gx/ipfs/QmUwMnKKjH3JwGKNVZ3TcP37W93xzqNA4ECFFiMo6sXkkc/go-ipns/pb" + nameopts "gx/ipfs/QmXLwxifxwfc2bAwq6rdjbYqAsGzWsDE9RM5TWMGtykyj6/interface-go-ipfs-core/options/namesys" + "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" "gx/ipfs/QmddjPSGZb3ieihSseFeCfVRpZzcqczPNsD2DvarSwnjJB/gogo-protobuf/proto" "gx/ipfs/QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6/base32" "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/namesys" - - nameopts "gx/ipfs/QmXLwxifxwfc2bAwq6rdjbYqAsGzWsDE9RM5TWMGtykyj6/interface-go-ipfs-core/options/namesys" ) const ( persistentCacheDbPrefix = "/ipns/persistentcache/" + pubkeyCacheDbPrefix = "/pubkey/" + ipnsCacheDbPrefix = "/ipns/" ) // Resolve an IPNS record. This is a multi-step process. @@ -75,7 +77,7 @@ func resolve(n *core.IpfsNode, p peer.ID, timeout time.Duration, quorum uint) (i // TODO [cp]: we should load the record count from our config and set it here. We'll need a // migration for this. - pth, err := n.Namesys.Resolve(cctx, "/ipns/"+p.Pretty(), nameopts.DhtRecordCount(quorum)) + pth, err := n.Namesys.Resolve(cctx, obIPNSCacheKey(p.Pretty()), nameopts.DhtRecordCount(quorum)) if err != nil { return pth, err } @@ -86,7 +88,7 @@ func ResolveAltRoot(n *core.IpfsNode, p peer.ID, altRoot string, timeout time.Du cctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() - pth, err := n.Namesys.Resolve(cctx, "/ipns/"+p.Pretty()+":"+altRoot) + pth, err := n.Namesys.Resolve(cctx, obIPNSCacheKey(p.Pretty()+":"+altRoot)) if err != nil { return "", err } @@ -94,35 +96,77 @@ func ResolveAltRoot(n *core.IpfsNode, p peer.ID, altRoot string, timeout time.Du } // getFromDatastore looks in two places in the database for a record. First is -// under the /ipfs/ key which is sometimes used by the DHT. The value +// under the /ipns/ key which is sometimes used by the DHT. The value // returned by this location is a serialized protobuf record. The second is -// under /ipfs/persistentcache/ which returns only the value (the path) +// under /ipns/persistentcache/ which returns only the value (the path) // inside the protobuf record. func getFromDatastore(datastore ds.Datastore, p peer.ID) (ipath.Path, error) { - ival, err := datastore.Get(namesys.IpnsDsKey(p)) + rec, err := GetCachedIPNSRecord(datastore, p) + if err == nil { + return ipath.ParsePath(string(rec.Value)) + } + + pth, err := datastore.Get(persistentCacheKey(p)) if err != nil { - pth, err := datastore.Get(ipnsCacheDsKey(p)) - if err != nil { - if err == ds.ErrNotFound { - return "", namesys.ErrResolveFailed - } - return "", err + if err == ds.ErrNotFound { + return "", namesys.ErrResolveFailed } - return ipath.ParsePath(string(pth)) + return "", fmt.Errorf("getting cached ipns path: %s", err.Error()) } + return ipath.ParsePath(string(pth)) +} + +func putToDatastoreCache(datastore ds.Datastore, p peer.ID, pth ipath.Path) error { + return datastore.Put(persistentCacheKey(p), []byte(pth.String())) +} +// GetCachedIPNSRecord retrieves the full IPNSEntry from the provided datastore if present +func GetCachedIPNSRecord(store ds.Datastore, id peer.ID) (*ipnspb.IpnsEntry, error) { + ival, err := store.Get(nativeIPNSRecordCacheKey(id)) + if err != nil { + return nil, fmt.Errorf("getting cached ipns record: %s", err.Error()) + } rec := new(ipnspb.IpnsEntry) err = proto.Unmarshal(ival, rec) if err != nil { - return "", err + log.Errorf("failed parsing cached record for peer (%s): %s", id.Pretty(), err.Error()) + log.Debug(debug.Stack()) + return nil, fmt.Errorf("parsing cached ipns record: %s", err.Error()) } - return ipath.ParsePath(string(rec.Value)) + return rec, nil } -func putToDatastoreCache(datastore ds.Datastore, p peer.ID, pth ipath.Path) error { - return datastore.Put(ipnsCacheDsKey(p), []byte(pth.String())) +// DeleteCachedIPNSRecord removes the cached record associated with the provided peer.ID +func DeleteCachedIPNSRecord(store ds.Datastore, id peer.ID) error { + return store.Delete(nativeIPNSRecordCacheKey(id)) +} + +// PutCachedPubkey persists the pubkey using the appropriate key prefix +// from the provided datastore +func PutCachedPubkey(store ds.Datastore, peerID string, pubkey []byte) error { + return store.Put(pubkeyCacheKey(peerID), pubkey) } -func ipnsCacheDsKey(id peer.ID) ds.Key { +// GetCachedPubkey retrieves the pubkey using the appropriate key prefix +// from the provided Datastore +func GetCachedPubkey(store ds.Datastore, peerID string) ([]byte, error) { + return store.Get(pubkeyCacheKey(peerID)) +} + +func pubkeyCacheKey(id string) ds.Key { + return ds.NewKey(pubkeyCacheDbPrefix + id) +} + +func persistentCacheKey(id peer.ID) ds.Key { return ds.NewKey(persistentCacheDbPrefix + base32.RawStdEncoding.EncodeToString([]byte(id))) } + +// nativeIPNSRecordCacheKey applies native IPFS key: "/ipns/" + encoded(id) +func nativeIPNSRecordCacheKey(id peer.ID) ds.Key { + return namesys.IpnsDsKey(id) +} + +// obIPNSCacheKey applies custom IPNS prefix key: "/ipns/" + id +func obIPNSCacheKey(id string) string { + return ipnsCacheDbPrefix + id +} diff --git a/openbazaard.go b/marketplaced.go similarity index 75% rename from openbazaard.go rename to marketplaced.go index b1c5b308bb..ad28855795 100644 --- a/openbazaard.go +++ b/marketplaced.go @@ -9,8 +9,8 @@ import ( "github.com/ipfs/go-ipfs/repo/fsrepo" "github.com/jessevdk/go-flags" "github.com/op/go-logging" - "github.com/phoreproject/openbazaar-go/cmd" - "github.com/phoreproject/openbazaar-go/core" + "github.com/phoreproject/pm-go/cmd" + "github.com/phoreproject/pm-go/core" ) var log = logging.MustGetLogger("main") @@ -33,11 +33,12 @@ func main() { if core.Node != nil { if core.Node.MessageRetriever != nil { core.Node.RecordAgingNotifier.Stop() + core.Node.InboundMsgScanner.Stop() close(core.Node.MessageRetriever.DoneChan) core.Node.MessageRetriever.Wait() } core.OfflineMessageWaitGroup.Wait() - core.PublishLock.Lock() + core.Node.PublishLock.Lock() core.Node.Datastore.Close() repoLockFile := filepath.Join(core.Node.RepoPath, fsrepo.LockFile) os.Remove(repoLockFile) @@ -48,42 +49,62 @@ func main() { } }() - parser.AddCommand("gencerts", + _, err := parser.AddCommand("gencerts", "Generate certificates", - "Generate self-singned certificates", + "Generate self-signed certificates", &cmd.GenerateCertificates{}) - parser.AddCommand("init", + if err != nil { + log.Error(err) + } + _, err = parser.AddCommand("init", "initialize a new repo and exit", "Initializes a new repo without starting the server", &cmd.Init{}) - parser.AddCommand("status", + if err != nil { + log.Error(err) + } + _, err = parser.AddCommand("status", "get the repo status", "Returns the status of the repo ― Uninitialized, Encrypted, Decrypted. Also returns whether Tor is available.", &cmd.Status{}) - parser.AddCommand("setapicreds", + if err != nil { + log.Error(err) + } + _, err = parser.AddCommand("setapicreds", "set API credentials", "The API password field in the config file takes a SHA256 hash of the password. This command will generate the hash for you and save it to the config file.", &cmd.SetAPICreds{}) - parser.AddCommand("start", + if err != nil { + log.Error(err) + } + _, err = parser.AddCommand("start", "start the OpenBazaar-Server", "The start command starts the OpenBazaar-Server", &cmd.Start{}) - parser.AddCommand("encryptdatabase", + if err != nil { + log.Error(err) + } + _, err = parser.AddCommand("encryptdatabase", "encrypt your database", "This command encrypts the database containing your bitcoin private keys, identity key, and contracts", &cmd.EncryptDatabase{}) - parser.AddCommand("decryptdatabase", + if err != nil { + log.Error(err) + } + _, err = parser.AddCommand("decryptdatabase", "decrypt your database", "This command decrypts the database containing your bitcoin private keys, identity key, and contracts.\n [Warning] doing so may put your bitcoins at risk.", &cmd.DecryptDatabase{}) - parser.AddCommand("restore", + if err != nil { + log.Error(err) + } + _, err = parser.AddCommand("restore", "restore user data", "This command will attempt to restore user data (profile, listings, ratings, etc) by downloading them from the network. This will only work if the IPNS mapping is still available in the DHT. Optionally it will take a mnemonic seed to restore from.", &cmd.Restore{}) - parser.AddCommand("convert", - "convert this node to a different coin type", - "This command will convert the node to use a different cryptocurrency", - &cmd.Convert{}) + if err != nil { + log.Error(err) + } if len(os.Args) > 1 && (os.Args[1] == "--version" || os.Args[1] == "-v") { fmt.Println(core.VERSION) return diff --git a/mobile/README.md b/mobile/README.md index 55be583765..78a038d7a6 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -1,6 +1,6 @@ -# openbazaar-go for mobile +# pm-go for mobile ## Purpose -This target allows a version of openbazaar-go to be compiled for use with Android or iOS. The primary changes are shorter timeouts around network requests and tighter resource management with a few details which allows a native frontend to speak with the server process. +This target allows a version of marketplace-go to be compiled for use with Android or iOS. The primary changes are shorter timeouts around network requests and tighter resource management with a few details which allows a native frontend to speak with the server process. ## Prepare There are a few dependencies which must be installed and setup before a build can be completed. @@ -20,8 +20,8 @@ There are a few dependencies which must be installed and setup before a build ca ### iOS -- Execute `make ios_framework` in your local openbazaar-go repo. This should produce a `Mobile.framework` file which may be included in your iOS project. +- Execute `make ios_framework` in your local marketplace-go repo. This should produce a `Mobile.framework` file which may be included in your iOS project. ### Android -- Execute `make android_framework` in your local openbazaar-go repo. These must be executed from the root of the project and cannot be built inside a virtualized container or process. +- Execute `make android_framework` in your local marketplace-go repo. These must be executed from the root of the project and cannot be built inside a virtualized container or process. diff --git a/mobile/cmd/main.go b/mobile/cmd/main.go index f7e50d2310..c1808a42b0 100644 --- a/mobile/cmd/main.go +++ b/mobile/cmd/main.go @@ -2,11 +2,10 @@ package main import ( "fmt" - "os" - "sync" - "github.com/jessevdk/go-flags" - "github.com/phoreproject/openbazaar-go/mobile" + "github.com/phoreproject/pm-go/mobile" + "os" + "path" ) type Options struct { @@ -20,7 +19,7 @@ var ( ) func main() { - var dataPath = "/Users/mg/work/ob/openbazaar-go/config_mobile_test" + var dataPath = path.Join(os.TempDir(), "ob-mobile") if _, err := parser.Parse(); err != nil { if len(os.Args) > 1 && os.Args[1] == "-h" { os.Exit(0) @@ -34,7 +33,6 @@ func main() { } var ( - wg sync.WaitGroup n, err = mobile.NewNodeWithConfig(&mobile.NodeConfig{ RepoPath: dataPath, Testnet: options.TestnetEnabled, @@ -43,9 +41,9 @@ func main() { if err != nil { fmt.Println(err.Error()) } - wg.Add(1) if err := n.Start(); err != nil { fmt.Println(err.Error()) } - wg.Wait() + + select {} } diff --git a/mobile/config.go b/mobile/config.go index b851692303..6d3869eab8 100644 --- a/mobile/config.go +++ b/mobile/config.go @@ -1,16 +1,5 @@ package mobile -import ( - "github.com/OpenBazaar/wallet-interface" - "github.com/op/go-logging" -) - -var stdoutLogFormat = logging.MustStringFormatter( - `%{color:reset}%{color}%{time:15:04:05.000} [%{shortfunc}] [%{level}] %{message}`, -) - -var logger logging.Backend - // NodeConfig struct of the config parameters to be passed when creating a new node type NodeConfig struct { @@ -33,6 +22,6 @@ type NodeConfig struct { DisableWallet bool DisableExchangerates bool - // The coin to use - CoinType wallet.CoinType + // Run the pprof profiler on port 6060 + Profile bool } diff --git a/mobile/node.go b/mobile/node.go index 140f02ea8a..4c3acd3de3 100644 --- a/mobile/node.go +++ b/mobile/node.go @@ -4,26 +4,29 @@ import ( "context" "errors" "fmt" + "io/ioutil" + "net" + "net/http" + "os" + "path" + "path/filepath" + "sync" + "time" + "gx/ipfs/QmRCrPXk2oUwpK1Cj2FXrUotRpddUxz56setkny2gz13Cx/go-libp2p-routing-helpers" "gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht" "gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht/opts" ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" + ipfsconfig "gx/ipfs/QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs/go-ipfs-config" ds "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" p2phost "gx/ipfs/QmYrWiWM4qtrnCeT3R14jY3ZZyirDNJgwK57q4qFYePgbd/go-libp2p-host" "gx/ipfs/QmYxUdYY9S6yg5tSPVin5GFTvtfsLauVcr7reHDD3dM8xf/go-libp2p-routing" "gx/ipfs/QmbeHtaBy9nZsW4cHRcvgVY4CnDhXudE2Dr6qDxS7yg9rX/go-libp2p-record" + ipfslogging "gx/ipfs/QmbkT7eMTyXfpeyB3ZMxxcxg7XH8t6uXp49jqzz4HB7BGF/go-log/writer" "gx/ipfs/Qmc85NSvmSG4Frn9Vb2cBc1rMyULH6D3TNVEfCzSKoUpip/go-multiaddr-net" - "gx/ipfs/QmddjPSGZb3ieihSseFeCfVRpZzcqczPNsD2DvarSwnjJB/gogo-protobuf/proto" - "io/ioutil" - "net/http" - "os" - "path" - "path/filepath" - "time" - ipfsconfig "gx/ipfs/QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs/go-ipfs-config" - ipnspb "gx/ipfs/QmUwMnKKjH3JwGKNVZ3TcP37W93xzqNA4ECFFiMo6sXkkc/go-ipns/pb" + _ "net/http/pprof" wi "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg" @@ -31,26 +34,24 @@ import ( "github.com/ipfs/go-ipfs/commands" ipfscore "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/corehttp" - "github.com/ipfs/go-ipfs/namesys" "github.com/ipfs/go-ipfs/repo/fsrepo" + "github.com/natefinch/lumberjack" "github.com/op/go-logging" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/api" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/ipfs" - obnet "github.com/phoreproject/openbazaar-go/net" - rep "github.com/phoreproject/openbazaar-go/net/repointer" - ret "github.com/phoreproject/openbazaar-go/net/retriever" - "github.com/phoreproject/openbazaar-go/net/service" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" - apiSchema "github.com/phoreproject/openbazaar-go/schema" - "github.com/phoreproject/openbazaar-go/storage/selfhosted" - "github.com/phoreproject/openbazaar-go/wallet" - lis "github.com/phoreproject/openbazaar-go/wallet/listeners" - "github.com/phoreproject/openbazaar-go/wallet/resync" + "github.com/phoreproject/pm-go/api" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/ipfs" + obnet "github.com/phoreproject/pm-go/net" + rep "github.com/phoreproject/pm-go/net/repointer" + ret "github.com/phoreproject/pm-go/net/retriever" + "github.com/phoreproject/pm-go/net/service" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + apiSchema "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/storage/selfhosted" + "github.com/phoreproject/pm-go/wallet" + lis "github.com/phoreproject/pm-go/wallet/listeners" + "github.com/phoreproject/pm-go/wallet/resync" "github.com/tyler-smith/go-bip39" ) @@ -63,17 +64,29 @@ type Node struct { cancel context.CancelFunc ipfsConfig *ipfscore.BuildCfg apiConfig *apiSchema.APIConfig + gateway *api.Gateway + started bool + startMtx sync.Mutex } +var ( + fileLogFormat = logging.MustStringFormatter( + `[Haven] %{time:2006-01-02 15:04:05.000} [%{level}] [%{module}/%{shortfunc}] %{message}`, + ) + publishUnlocked = false + mainLoggingBackend logging.Backend +) + // NewNode create the configuration file for a new node -func NewNode(repoPath string, authenticationToken string, testnet bool, userAgent string, walletTrustedPeer string, password string, mnemonic string) *Node { +func NewNode(repoPath string, authenticationToken string, testnet bool, userAgent string, walletTrustedPeer string, password string, mnemonic string, profile bool) *Node { // Node config nodeconfig := &NodeConfig{ RepoPath: repoPath, - AuthenticationToken: "", + AuthenticationToken: authenticationToken, Testnet: testnet, UserAgent: userAgent, WalletTrustedPeer: walletTrustedPeer, + Profile: profile, } // Use Mobile struct to carry config data @@ -90,14 +103,32 @@ func NewNodeWithConfig(config *NodeConfig, password string, mnemonic string) (*N repoLockFile := filepath.Join(config.RepoPath, fsrepo.LockFile) os.Remove(repoLockFile) - // Logging - backendStdout := logging.NewLogBackend(os.Stdout, "", 0) - logger = logging.NewBackendFormatter(backendStdout, stdoutLogFormat) - logging.SetBackend(logger) - - migrations.WalletCoinType = util.ExtendCoinType(config.CoinType) + ipfs.UpdateIPFSGlobalProtocolVars(config.Testnet) - sqliteDB, err := initializeRepo(config.RepoPath, "", "", true, time.Now(), config.CoinType) + // Logging + ipfsLog := &lumberjack.Logger{ + Filename: path.Join(config.RepoPath, "logs", "ipfs.log"), + MaxSize: 5, // Megabytes + MaxBackups: 3, + MaxAge: 30, // Days + } + ipfslogging.LdJSONFormatter() + ipfslogging.Output(ipfsLog)() + + obLog := &lumberjack.Logger{ + Filename: path.Join(config.RepoPath, "logs", "ob.log"), + MaxSize: 5, // Megabytes + MaxBackups: 3, + MaxAge: 30, // Days + } + obFileBackend := logging.NewLogBackend(obLog, "", 0) + obFileBackendFormatted := logging.NewBackendFormatter(obFileBackend, fileLogFormat) + stdoutBackend := logging.NewLogBackend(os.Stdout, "", 0) + stdoutBackendFormatted := logging.NewBackendFormatter(stdoutBackend, fileLogFormat) + mainLoggingBackend = logging.SetBackend(obFileBackendFormatted, stdoutBackendFormatted) + logging.SetLevel(logging.INFO, "") + + sqliteDB, err := initializeRepo(config.RepoPath, "", "", true, time.Now(), wi.Bitcoin) if err != nil && err != repo.ErrRepoExists { return nil, err } @@ -133,7 +164,10 @@ func NewNodeWithConfig(config *NodeConfig, password string, mnemonic string) (*N // Create user-agent file userAgentBytes := []byte(core.USERAGENT + config.UserAgent) - ioutil.WriteFile(path.Join(config.RepoPath, "root", "user_agent"), userAgentBytes, os.ModePerm) + err = ioutil.WriteFile(path.Join(config.RepoPath, "root", "user_agent"), userAgentBytes, os.ModePerm) + if err != nil { + log.Error(err) + } // IPFS node setup r, err := fsrepo.Open(config.RepoPath) @@ -155,7 +189,19 @@ func NewNodeWithConfig(config *NodeConfig, password string, mnemonic string) (*N return nil, err } cfg.Identity = identity - cfg.Swarm.DisableNatPortMap = true + cfg.Swarm.DisableNatPortMap = false + cfg.Swarm.EnableAutoRelay = true + cfg.Swarm.EnableAutoNATService = false + + // Temporary override of bootstrap nodes + cfg.Bootstrap = []string{ + "/ip6/2604:a880:2:d0::219d:9001/tcp/4001/ipfs/QmWUdwXW3bTXS19MtMjmfpnRYgssmbJCwnq8Lf9vjZwDii", + "/ip6/2604:a880:400:d1::c1d:2001/tcp/4001/ipfs/QmcXwJePGLsP1x7gTXLE51BmE7peUKe2eQuR5LGbmasekt", + "/ip6/2604:a880:400:d1::99a:8001/tcp/4001/ipfs/Qmb8i7uy6rk47hNorNLMVRMer4Nv9YWRhzZrWVqnvk5mSk", + "/ip4/138.68.10.227/tcp/4001/ipfs/QmWUdwXW3bTXS19MtMjmfpnRYgssmbJCwnq8Lf9vjZwDii", + "/ip4/157.230.59.219/tcp/4001/ipfs/QmcXwJePGLsP1x7gTXLE51BmE7peUKe2eQuR5LGbmasekt", + "/ip4/206.189.224.90/tcp/4001/ipfs/Qmb8i7uy6rk47hNorNLMVRMer4Nv9YWRhzZrWVqnvk5mSk", + } // Setup testnet if config.Testnet { @@ -172,11 +218,16 @@ func NewNodeWithConfig(config *NodeConfig, password string, mnemonic string) (*N } // Mnemonic - mn, err := sqliteDB.Config().GetMnemonic() + mn, _, err := sqliteDB.Config().GetMnemonic() if err != nil { return nil, err } - params := chaincfg.MainNetParams + var params chaincfg.Params + if config.Testnet { + params = chaincfg.TestNet3Params + } else { + params = chaincfg.MainNetParams + } // Master key setup seed := bip39.NewSeed(mn, "") @@ -191,7 +242,7 @@ func NewNodeWithConfig(config *NodeConfig, password string, mnemonic string) (*N DB: sqliteDB.DB(), Params: ¶ms, RepoPath: config.RepoPath, - Logger: logger, + Logger: mainLoggingBackend, WalletCreationDate: creationDate, Mnemonic: mn, DisableExchangeRates: config.DisableExchangerates, @@ -201,8 +252,6 @@ func NewNodeWithConfig(config *NodeConfig, password string, mnemonic string) (*N return nil, err } - core.PublishLock.Lock() - // Set up the ban manager settings, err := sqliteDB.Settings().Get() if err != nil && err != db.SettingsNotSetError { @@ -231,12 +280,12 @@ func NewNodeWithConfig(config *NodeConfig, password string, mnemonic string) (*N } // OpenBazaar node setup - core.Node = &core.OpenBazaarNode{ + node := &core.OpenBazaarNode{ BanManager: bm, Datastore: sqliteDB, MasterPrivateKey: mPrivKey, Multiwallet: mw, - OfflineMessageFailoverTimeout: 5 * time.Second, + OfflineMessageFailoverTimeout: 3 * time.Second, PushNodes: pushNodes, RepoPath: config.RepoPath, UserAgent: core.USERAGENT, @@ -252,23 +301,24 @@ func NewNodeWithConfig(config *NodeConfig, password string, mnemonic string) (*N ncfg := ipfs.PrepareIPFSConfig(r, ignoredURI, config.Testnet, config.Testnet) ncfg.Routing = constructMobileRouting - return &Node{OpenBazaarNode: core.Node, config: *config, ipfsConfig: ncfg, apiConfig: apiConfig}, nil + node.PublishLock.Lock() + + // assert reserve wallet is available on startup for later usage + _, err = node.ReserveCurrencyConverter() + if err != nil { + return nil, fmt.Errorf("verifying reserve currency converter: %s", err.Error()) + } + + return &Node{OpenBazaarNode: node, config: *config, ipfsConfig: ncfg, apiConfig: apiConfig, startMtx: sync.Mutex{}}, nil } func constructMobileRouting(ctx context.Context, host p2phost.Host, dstore ds.Batching, validator record.Validator) (routing.IpfsRouting, error) { - dhtRouting, err := dht.New( + return dht.New( ctx, host, dhtopts.Client(true), dhtopts.Datastore(dstore), dhtopts.Validator(validator), ) - if err != nil { - return nil, err - } - apiRouter := ipfs.NewAPIRouter(schema.IPFSCachingRouterDefaultURI, dhtRouting.Validator) - apiRouter.Start(nil) - cachingRouter := ipfs.NewCachingRouter(dhtRouting, &apiRouter) - return cachingRouter, nil } // startIPFSNode start the node @@ -277,6 +327,13 @@ func (n *Node) startIPFSNode(repoPath string, config *ipfscore.BuildCfg) (*ipfsc n.cancel = cancel ctx := commands.Context{} + + ipfscore.DefaultBootstrapConfig = ipfscore.BootstrapConfig{ + MinPeerThreshold: 8, + Period: time.Second * 10, + ConnectionTimeout: time.Second * 10 / 3, + } + nd, err := ipfscore.NewNode(cctx, config) if err != nil { return nil, ctx, err @@ -295,6 +352,26 @@ func (n *Node) startIPFSNode(repoPath string, config *ipfscore.BuildCfg) (*ipfsc // Start start openbazaard (OpenBazaar daemon) func (n *Node) Start() error { + n.startMtx.Lock() + defer n.startMtx.Unlock() + + return n.start() +} + +func (n *Node) mountProfileHandlerAndListen() { + listenAddr := net.JoinHostPort("", "6060") + profileRedirect := http.RedirectHandler("/debug/pprof", + http.StatusSeeOther) + http.Handle("/", profileRedirect) + if err := http.ListenAndServe(listenAddr, nil); err != nil { + log.Errorf("serving debug profiler: %s", err.Error()) + } +} + +func (n *Node) start() error { + if n.config.Profile { + go n.mountProfileHandlerAndListen() + } nd, ctx, err := n.startIPFSNode(n.config.RepoPath, n.ipfsConfig) if err != nil { return err @@ -307,11 +384,8 @@ func (n *Node) Start() error { } var dhtRouting *dht.IpfsDHT for _, router := range tiered.Routers { - if r, ok := router.(*ipfs.CachingRouter); ok { - dhtRouting, err = r.DHT() - if err != nil { - return err - } + if r, ok := router.(*dht.IpfsDHT); ok { + dhtRouting = r } } if dhtRouting == nil { @@ -322,17 +396,15 @@ func (n *Node) Start() error { n.OpenBazaarNode.DHT = dhtRouting // Get current directory root hash - ipnskey := namesys.IpnsDsKey(nd.Identity) - ival, hasherr := nd.Repo.Datastore().Get(ipnskey) - if hasherr != nil { - log.Error("get ipns key:", hasherr) - } - ourIpnsRecord := new(ipnspb.IpnsEntry) - err = proto.Unmarshal(ival, ourIpnsRecord) + rec, err := ipfs.GetCachedIPNSRecord(nd.Repo.Datastore(), nd.Identity) if err != nil { - log.Error("unmarshal record value", err) + log.Warning(err) + if err := ipfs.DeleteCachedIPNSRecord(nd.Repo.Datastore(), nd.Identity); err != nil { + log.Errorf("deleting invalid IPNS record: %s", err.Error()) + } + } else { + n.OpenBazaarNode.RootHash = string(rec.Value) } - n.OpenBazaarNode.RootHash = string(ourIpnsRecord.Value) configFile, err := ioutil.ReadFile(path.Join(n.OpenBazaarNode.RepoPath, "config")) if err != nil { @@ -361,21 +433,26 @@ func (n *Node) Start() error { authCookie.Value = n.config.AuthenticationToken n.apiConfig.Authenticated = true } - gateway, err := newHTTPGateway(core.Node, ctx, authCookie, *n.apiConfig) + gateway, err := newHTTPGateway(n, ctx, authCookie, *n.apiConfig) if err != nil { return err } - go gateway.Serve() + n.gateway = gateway + go func() { + if err := gateway.Serve(false); err != nil { + log.Error(err) + } + }() go func() { - resyncManager := resync.NewResyncManager(n.OpenBazaarNode.Datastore.Sales(), n.OpenBazaarNode.Multiwallet) + resyncManager := resync.NewResyncManager(n.OpenBazaarNode.Datastore.Sales(), n.OpenBazaarNode.Datastore.Purchases(), n.OpenBazaarNode.Multiwallet) if !n.config.DisableWallet { if resyncManager == nil { - core.Node.WaitForMessageRetrieverCompletion() + n.OpenBazaarNode.WaitForMessageRetrieverCompletion() } - TL := lis.NewTransactionListener(n.OpenBazaarNode.Multiwallet, core.Node.Datastore, core.Node.Broadcast) + TL := lis.NewTransactionListener(n.OpenBazaarNode.Multiwallet, n.OpenBazaarNode.Datastore, n.OpenBazaarNode.Broadcast) for ct, wal := range n.OpenBazaarNode.Multiwallet { - WL := lis.NewWalletListener(core.Node.Datastore, core.Node.Broadcast, ct) + WL := lis.NewWalletListener(n.OpenBazaarNode.Datastore, n.OpenBazaarNode.Broadcast, ct) wal.AddTransactionListener(WL.OnTransactionReceived) wal.AddTransactionListener(TL.OnTransactionReceived) } @@ -385,7 +462,7 @@ func (n *Node) Start() error { if resyncManager != nil { go resyncManager.Start() go func() { - core.Node.WaitForMessageRetrieverCompletion() + n.OpenBazaarNode.WaitForMessageRetrieverCompletion() resyncManager.CheckUnfunded() }() } @@ -397,9 +474,9 @@ func (n *Node) Start() error { IPFSNode: n.OpenBazaarNode.IpfsNode, DHT: n.OpenBazaarNode.DHT, BanManger: n.OpenBazaarNode.BanManager, - Service: core.Node.Service, + Service: n.OpenBazaarNode.Service, PrefixLen: 14, - PushNodes: core.Node.PushNodes, + PushNodes: n.OpenBazaarNode.PushNodes, Dialer: nil, SendAck: n.OpenBazaarNode.SendOfflineAck, SendError: n.OpenBazaarNode.SendError, @@ -411,28 +488,86 @@ func (n *Node) Start() error { n.OpenBazaarNode.PointerRepublisher = PR MR.Wait() - core.PublishLock.Unlock() - core.Node.UpdateFollow() - if !core.InitalPublishComplete { - core.Node.SeedNode() + n.OpenBazaarNode.PublishLock.Unlock() + publishUnlocked = true + err = n.OpenBazaarNode.UpdateFollow() + if err != nil { + log.Error(err) } - core.Node.SetUpRepublisher(republishInterval) + if !n.OpenBazaarNode.InitalPublishComplete { + err = n.OpenBazaarNode.SeedNode() + if err != nil { + log.Error(err) + } + } + n.OpenBazaarNode.SetUpRepublisher(republishInterval) }() - + n.started = true return nil } // Stop stop openbazaard func (n *Node) Stop() error { + n.startMtx.Lock() + defer n.startMtx.Unlock() + + return n.stop() +} + +func (n *Node) stop() error { core.OfflineMessageWaitGroup.Wait() - core.Node.Datastore.Close() - repoLockFile := filepath.Join(core.Node.RepoPath, fsrepo.LockFile) - os.Remove(repoLockFile) - core.Node.Multiwallet.Close() - core.Node.IpfsNode.Close() + n.OpenBazaarNode.Datastore.Close() + repoLockFile := filepath.Join(n.OpenBazaarNode.RepoPath, fsrepo.LockFile) + if err := os.Remove(repoLockFile); err != nil { + log.Error(err) + } + n.OpenBazaarNode.Multiwallet.Close() + if err := n.OpenBazaarNode.IpfsNode.Close(); err != nil { + log.Error(err) + } + if err := n.gateway.Close(); err != nil { + log.Error(err) + } + n.started = false return nil } +func (n *Node) Restart() error { + n.startMtx.Lock() + defer n.startMtx.Unlock() + + var wg sync.WaitGroup + + if n.started { + wg.Add(1) + go func() { + defer wg.Done() + if err := n.stop(); err != nil { + log.Error(err) + } + }() + wg.Wait() + } + + // This node has been stopped by the stop command so we need to create + // a new one before starting it again. + newNode, err := NewNodeWithConfig(&n.config, "", "") + if err != nil { + return err + } + n.OpenBazaarNode = newNode.OpenBazaarNode + n.config = newNode.config + n.ipfsConfig = newNode.ipfsConfig + n.apiConfig = newNode.apiConfig + + return n.start() +} + +// PublishUnlocked return true if publish is unlocked +func (n *Node) PublishUnlocked() bool { + return publishUnlocked +} + // initializeRepo create the database func initializeRepo(dataDir, password, mnemonic string, testnet bool, creationDate time.Time, coinType wi.CoinType) (*db.SQLiteDatastore, error) { // Database @@ -450,7 +585,7 @@ func initializeRepo(dataDir, password, mnemonic string, testnet bool, creationDa } // Collects options, creates listener, prints status message and starts serving requests -func newHTTPGateway(node *core.OpenBazaarNode, ctx commands.Context, authCookie http.Cookie, config apiSchema.APIConfig) (*api.Gateway, error) { +func newHTTPGateway(node *Node, ctx commands.Context, authCookie http.Cookie, config apiSchema.APIConfig) (*api.Gateway, error) { // Get API configuration cfg, err := ctx.GetConfig() if err != nil { @@ -482,5 +617,5 @@ func newHTTPGateway(node *core.OpenBazaarNode, ctx commands.Context, authCookie } // Create and return an API gateway - return api.NewGateway(node, authCookie, manet.NetListener(gwLis), config, logger, opts...) + return api.NewGateway(node.OpenBazaarNode, authCookie, manet.NetListener(gwLis), config, mainLoggingBackend, opts...) } diff --git a/mobile/node_test.go b/mobile/node_test.go new file mode 100644 index 0000000000..43a26caf55 --- /dev/null +++ b/mobile/node_test.go @@ -0,0 +1,45 @@ +package mobile_test + +import ( + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/mobile" + "github.com/phoreproject/pm-go/schema" + bitswap "gx/ipfs/QmcSPuzpSbVLU6UHU4e5PwZpm4fHbCn5SbNR5ZNL6Mj63G/go-bitswap/network" + "testing" +) + +func TestBitswapProtocolSetCorrectly(t *testing.T) { + var s, err = schema.NewCustomSchemaManager(schema.SchemaContext{ + DataPath: schema.GenerateTempPath(), + TestModeEnabled: true, + }) + if err != nil { + t.Fatal(err) + } + defer s.DestroySchemaDirectories() + + if err := s.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + + config := &mobile.NodeConfig{ + RepoPath: s.DataPath(), + DisableWallet: true, + DisableExchangerates: true, + Testnet: true, + } + _, err = mobile.NewNodeWithConfig(config, "", "") + if err != nil { + t.Fatal(err) + } + + if bitswap.ProtocolBitswap != ipfs.IPFSProtocolBitswapTestnetOneDotOne { + t.Errorf("expected bitswap protocol latest to be set to '%s' when using testnet, but was not", ipfs.IPFSProtocolBitswapTestnetOneDotOne) + } + if bitswap.ProtocolBitswapOne != ipfs.IPFSProtocolBitswapTestnetOne { + t.Errorf("expected bitswap protocol v1 to be set to '%s' when using testnet, but was not", ipfs.IPFSProtocolBitswapTestnetOne) + } + if bitswap.ProtocolBitswapNoVers != ipfs.IPFSProtocolBitswapTestnetNoVers { + t.Errorf("expected bitswap protocol nover to be set to '%s' when using testnet, but was not", ipfs.IPFSProtocolBitswapTestnetNoVers) + } +} diff --git a/net/encryption.go b/net/encryption.go index f28997ced5..97a93837bb 100644 --- a/net/encryption.go +++ b/net/encryption.go @@ -113,7 +113,10 @@ func encryptCurve25519(pubKey *libp2p.Ed25519PublicKey, plaintext []byte) ([]byt func encryptRSA(pubKey *libp2p.RsaPublicKey, plaintext []byte) ([]byte, error) { // Encrypt random secret key with RSA pubkey secretKey := make([]byte, SecretKeyBytes) - rand.Read(secretKey) + _, err := rand.Read(secretKey) + if err != nil { + return nil, err + } encKey, err := pubKey.Encrypt(secretKey) if err != nil { @@ -155,7 +158,10 @@ func encryptRSA(pubKey *libp2p.RsaPublicKey, plaintext []byte) ([]byte, error) { // Create the HMAC mac := hmac.New(sha256.New, macKey) - mac.Write(ciphertext) + _, err = mac.Write(ciphertext) + if err != nil { + return nil, err + } messageMac := mac.Sum(nil) // Prepend the ciphertext with the encrypted secret key @@ -239,7 +245,10 @@ func decryptRSA(privKey *libp2p.RsaPrivateKey, ciphertext []byte) ([]byte, error // Calculate the HMAC and verify it is correct mac := hmac.New(sha256.New, macKey) - mac.Write(ciphertext[CiphertextVersionBytes+EncryptedSecretKeyBytes : len(ciphertext)-MacBytes]) + _, err = mac.Write(ciphertext[CiphertextVersionBytes+EncryptedSecretKeyBytes : len(ciphertext)-MacBytes]) + if err != nil { + return nil, err + } messageMac := mac.Sum(nil) if !hmac.Equal(messageMac, ciphertext[len(ciphertext)-MacBytes:]) { return nil, ErrInvalidHmac diff --git a/net/networkservice.go b/net/networkservice.go index 452f86baee..9cc8b5d652 100644 --- a/net/networkservice.go +++ b/net/networkservice.go @@ -7,7 +7,7 @@ import ( inet "gx/ipfs/QmY3ArotKMKaL7YGfbQfyDrib6RVraLqZYWXZvVgZktBxp/go-libp2p-net" peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) var ( @@ -29,7 +29,7 @@ type NetworkService interface { SendMessage(ctx context.Context, p peer.ID, pmes *pb.Message) error // Disconnect from the given peer - DisconnectFromPeer(p peer.ID) error + DisconnectFromPeer(p peer.ID) // Block until the service is available WaitForReady() diff --git a/net/repointer/repointer.go b/net/repointer/repointer.go index 5306b2e800..a517737bdc 100644 --- a/net/repointer/repointer.go +++ b/net/repointer/repointer.go @@ -6,8 +6,8 @@ import ( "time" "github.com/op/go-logging" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/repo" "golang.org/x/net/context" ) @@ -54,18 +54,39 @@ func (r *PointerRepublisher) Republish() { switch p.Purpose { case ipfs.MESSAGE: if time.Since(p.Timestamp) > kPointerExpiration { - r.db.Pointers().Delete(p.Value.ID) + err = r.db.Pointers().Delete(p.Value.ID) + if err != nil { + log.Error(err) + } } else { - go ipfs.PublishPointer(r.routing, ctx, p) - for _, peer := range r.pushNodes { - go ipfs.PutPointerToPeer(r.routing, context.Background(), peer, p) + go func(d *dht.IpfsDHT, ctx context.Context, pointer ipfs.Pointer) { + err := ipfs.PublishPointer(d, ctx, pointer) + if err != nil { + log.Error(err) + } + }(r.routing, ctx, p) + for _, peer0 := range r.pushNodes { + go func(d *dht.IpfsDHT, ctx context.Context, peerID peer.ID, pointer ipfs.Pointer) { + err := ipfs.PutPointerToPeer(d, ctx, peerID, pointer) + if err != nil { + log.Error(err) + } + }(r.routing, context.Background(), peer0, p) } } case ipfs.MODERATOR: if republishModerator { - go ipfs.PublishPointer(r.routing, ctx, p) + go func(d *dht.IpfsDHT, ctx context.Context, pointer ipfs.Pointer) { + err := ipfs.PublishPointer(d, ctx, pointer) + if err != nil { + log.Error(err) + } + }(r.routing, ctx, p) } else { - r.db.Pointers().Delete(p.Value.ID) + err = r.db.Pointers().Delete(p.Value.ID) + if err != nil { + log.Error(err) + } } default: continue diff --git a/net/retriever/retriever.go b/net/retriever/retriever.go index 6ea2d73470..f8abce2f8d 100644 --- a/net/retriever/retriever.go +++ b/net/retriever/retriever.go @@ -8,13 +8,11 @@ import ( libp2p "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" - "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" ps "gx/ipfs/QmaCTz9RkrU13bm9kMB54f7atgqM4qkjDZpRwRoJiWXEqs/go-libp2p-peerstore" "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" "io/ioutil" - gonet "net" "net/http" "sync" "time" @@ -22,17 +20,14 @@ import ( "github.com/golang/protobuf/proto" "github.com/ipfs/go-ipfs/core" "github.com/op/go-logging" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/net" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/net" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" "golang.org/x/net/proxy" ) -const ( - DefaultPointerPrefixLength = 14 - KeyCachePrefix = "/pubkey/" -) +const DefaultPointerPrefixLength = 14 var log = logging.MustGetLogger("retriever") @@ -72,13 +67,13 @@ type offlineMessage struct { } func NewMessageRetriever(cfg MRConfig) *MessageRetriever { - dial := gonet.Dial + var client *http.Client if cfg.Dialer != nil { - dial = cfg.Dialer.Dial + tbTransport := &http.Transport{Dial: cfg.Dialer.Dial} + client = &http.Client{Transport: tbTransport, Timeout: time.Second * 30} + } else { + client = &http.Client{Timeout: time.Second * 30} } - - tbTransport := &http.Transport{Dial: dial} - client := &http.Client{Transport: tbTransport, Timeout: time.Second * 30} mr := MessageRetriever{ db: cfg.Db, node: cfg.IPFSNode, @@ -96,58 +91,70 @@ func NewMessageRetriever(cfg MRConfig) *MessageRetriever { WaitGroup: new(sync.WaitGroup), } - mr.Add(1) + mr.Add(2) return &mr } func (m *MessageRetriever) Run() { dht := time.NewTicker(time.Hour) - peers := time.NewTicker(time.Minute * 10) + peers := time.NewTicker(time.Minute) defer dht.Stop() defer peers.Stop() - go m.fetchPointers(true) + go m.fetchPointersFromDHT() + go m.fetchPointersFromPushNodes() for { select { case <-dht.C: m.Add(1) - go m.fetchPointers(true) + go m.fetchPointersFromDHT() case <-peers.C: m.Add(1) - go m.fetchPointers(false) + go m.fetchPointersFromPushNodes() } } } -func (m *MessageRetriever) fetchPointers(useDHT bool) { +// RunOnce - used to fetch messages only once +func (m *MessageRetriever) RunOnce() { + m.Add(1) + go m.fetchPointersFromDHT() + m.Add(1) + go m.fetchPointersFromPushNodes() +} + +func (m *MessageRetriever) fetchPointersFromDHT() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - wg := new(sync.WaitGroup) - downloaded := 0 mh, _ := multihash.FromB58String(m.node.Identity.Pretty()) peerOut := make(chan ps.PeerInfo) go func(c chan ps.PeerInfo) { - pwg := new(sync.WaitGroup) - pwg.Add(1) - go func(c chan ps.PeerInfo) { - out := m.getPointersDataPeers() - for p := range out { - c <- p - } - pwg.Done() - }(c) - if useDHT { - pwg.Add(1) - go func(c chan ps.PeerInfo) { - iout := ipfs.FindPointersAsync(m.routing, ctx, mh, m.prefixLen) - for p := range iout { - c <- p - } - pwg.Done() - }(c) + iout := ipfs.FindPointersAsync(m.routing, ctx, mh, m.prefixLen) + for p := range iout { + c <- p + } + close(c) + + }(peerOut) + + m.downloadMessages(peerOut) +} + +func (m *MessageRetriever) fetchPointersFromPushNodes() { + peerOut := make(chan ps.PeerInfo) + go func(c chan ps.PeerInfo) { + out := m.getPointersDataPeers() + for p := range out { + c <- p } - pwg.Wait() close(c) + }(peerOut) + m.downloadMessages(peerOut) +} + +func (m *MessageRetriever) downloadMessages(peerOut chan ps.PeerInfo) { + wg := new(sync.WaitGroup) + downloaded := 0 inFlight := make(map[string]bool) // Iterate over the pointers, adding 1 to the waitgroup for each pointer found @@ -236,18 +243,22 @@ func (m *MessageRetriever) fetchIPFS(pid peer.ID, n *core.IpfsNode, addr ma.Mult var err error go func() { - ciphertext, err = ipfs.Cat(n, addr.String(), time.Minute*5) + ciphertext, err = ipfs.Cat(n, addr.String(), time.Second*10) c <- struct{}{} }() select { case <-c: if err != nil { - log.Errorf("Error retrieving offline message from %s, %s", addr.String(), err.Error()) + log.Errorf("Error retrieving offline message from: %s, Error: %s", addr.String(), err.Error()) return } - log.Debugf("Successfully downloaded offline message from %s", addr.String()) - m.db.OfflineMessages().Put(addr.String()) + log.Debugf("Successfully downloaded offline message %s from: %s", addr.String(), pid.Pretty()) + + err = m.db.OfflineMessages().Put(addr.String()) + if err != nil { + log.Error(err) + } m.attemptDecrypt(ciphertext, pid, addr) case <-m.DoneChan: return @@ -285,7 +296,10 @@ func (m *MessageRetriever) fetchHTTPS(pid peer.ID, url string, addr ma.Multiaddr return } log.Debugf("Successfully downloaded offline message from %s", addr.String()) - m.db.OfflineMessages().Put(addr.String()) + err = m.db.OfflineMessages().Put(addr.String()) + if err != nil { + log.Error(err) + } m.attemptDecrypt(ciphertext, pid, addr) case <-m.DoneChan: return @@ -299,7 +313,7 @@ func (m *MessageRetriever) attemptDecrypt(ciphertext []byte, pid peer.ID, addr m // Decrypt and unmarshal plaintext plaintext, err := net.Decrypt(m.node.PrivateKey, ciphertext) if err != nil { - log.Warning("Unable to decrypt offline message from %s: %s", addr.String(), err.Error()) + log.Warningf("Unable to decrypt cipher text to plain text, CID: %s: Error:%s\n", addr.String(), err.Error()) return } @@ -307,49 +321,62 @@ func (m *MessageRetriever) attemptDecrypt(ciphertext []byte, pid peer.ID, addr m env := pb.Envelope{} err = proto.Unmarshal(plaintext, &env) if err != nil { - log.Warning("Unable to decrypt offline message from %s: %s", addr.String(), err.Error()) + log.Warningf("Unable to unmarshal plaintext to encrypted Envelope, CID: %s: Error:%s\n", addr.String(), err.Error()) return } // Validate the signature ser, err := proto.Marshal(env.Message) if err != nil { - log.Warning("Unable to decrypt offline message from %s: %s", addr.String(), err.Error()) + log.Warningf("Unable to serialize the encrypted message, CID: %s: Error:%s\n", addr.String(), err.Error()) return } pubkey, err := libp2p.UnmarshalPublicKey(env.Pubkey) if err != nil { - log.Warning("Unable to decrypt offline message from %s: %s", addr.String(), err.Error()) + log.Warningf("Unable to unmarshal the public key from, CID: %s: Error:%s\n", addr.String(), err.Error()) return } valid, err := pubkey.Verify(ser, env.Signature) if err != nil || !valid { - log.Warning("Unable to decrypt offline message from %s: %s", addr.String(), err.Error()) + log.Warningf("Unable to verify message signature, CID: %s: Error:%s\n", addr.String(), err.Error()) return } id, err := peer.IDFromPublicKey(pubkey) if err != nil { - log.Warning("Unable to decrypt offline message from %s: %s", addr.String(), err.Error()) + log.Warningf("Unable to get a peer ID from the pubkey, CID: %s: Error:%s\n", addr.String(), err.Error()) return } + log.Debugf("Received offline message %s from: %s\n", addr.String(), id.Pretty()) + if m.bm.IsBanned(id) { - log.Warning("Received and dropped offline message from banned user: %s ", id.String()) + log.Warningf("Received and dropped offline message from banned user: %s\n", id.Pretty()) return } - m.node.Peerstore.AddPubKey(id, pubkey) - m.node.Repo.Datastore().Put(datastore.NewKey(KeyCachePrefix+id.Pretty()), env.Pubkey) + if err := m.node.Peerstore.AddPubKey(id, pubkey); err != nil { + log.Errorf("adding pubkey to peerstore: %s", err.Error()) + } + store := m.node.Repo.Datastore() + if err := ipfs.PutCachedPubkey(store, id.Pretty(), env.Pubkey); err != nil { + log.Errorf("caching pubkey: %s", err.Error()) + } // Respond with an ACK if env.Message.MessageType != pb.Message_OFFLINE_ACK { - m.sendAck(id.Pretty(), pid) + err = m.sendAck(id.Pretty(), pid) + if err != nil { + log.Error(err) + } } // handle - m.handleMessage(env, addr.String(), nil) + err = m.handleMessage(env, addr.String(), nil) + if err != nil { + log.Error(err) + } } // handleMessage loads the handler for this message type and attempts to process the message. Some message types (such @@ -393,7 +420,10 @@ func (m *MessageRetriever) handleMessage(env pb.Envelope, addr string, id *peer. } } else if env.Message.MessageType == pb.Message_ORDER && resp != nil { log.Errorf("Error processing ORDER message: %s, sending ERROR response", err.Error()) - m.sendError(id.Pretty(), nil, *resp) + err = m.sendError(id.Pretty(), nil, *resp) + if err != nil { + log.Error(err) + } return err } else { log.Errorf("Error processing message %s. Type %s: %s", addr, env.Message.MessageType, err.Error()) @@ -408,6 +438,7 @@ var MessageProcessingOrder = []pb.Message_MessageType{ pb.Message_ORDER_CANCEL, pb.Message_ORDER_REJECT, pb.Message_ORDER_CONFIRMATION, + pb.Message_ORDER_PAYMENT, pb.Message_ORDER_FULFILLMENT, pb.Message_ORDER_COMPLETION, pb.Message_DISPUTE_OPEN, @@ -421,6 +452,7 @@ var MessageProcessingOrder = []pb.Message_MessageType{ pb.Message_MODERATOR_ADD, pb.Message_MODERATOR_REMOVE, pb.Message_OFFLINE_ACK, + pb.Message_OFFLINE_RELAY, } // processQueuedMessages loads all the saved messaged from the database for processing. For each message it sorts them into a @@ -463,6 +495,9 @@ func (m *MessageRetriever) processQueuedMessages() { } // Delete messages that we're successfully processed from the database for _, url := range toDelete { - m.db.OfflineMessages().DeleteMessage(url) + err = m.db.OfflineMessages().DeleteMessage(url) + if err != nil { + log.Error(err) + } } } diff --git a/net/retriever/retriever_test.go b/net/retriever/retriever_test.go index 2ce2deedf6..a6e6bd1e4e 100644 --- a/net/retriever/retriever_test.go +++ b/net/retriever/retriever_test.go @@ -3,7 +3,7 @@ package net import ( "testing" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) // TestEnsureNoOmissionsInMessageProcessingOrder ensures that @@ -17,11 +17,12 @@ func TestEnsureNoOmissionsInMessageProcessingOrder(t *testing.T) { // Add deliberate omissions to this list blackList := map[pb.Message_MessageType]struct{}{ - pb.Message_PING: {}, - pb.Message_OFFLINE_RELAY: {}, - pb.Message_STORE: {}, - pb.Message_BLOCK: {}, - pb.Message_ERROR: {}, + pb.Message_PING: {}, + pb.Message_OFFLINE_RELAY: {}, + pb.Message_STORE: {}, + pb.Message_BLOCK: {}, + pb.Message_ORDER_PROCESSING_FAILURE: {}, + pb.Message_ERROR: {}, } // Inclusion check diff --git a/net/service/handlers.go b/net/service/handlers.go index 2dc75698d1..93622ae747 100644 --- a/net/service/handlers.go +++ b/net/service/handlers.go @@ -4,24 +4,32 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" + "time" libp2p "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" - "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" blocks "gx/ipfs/QmYYLnAzR28nAQ4U5MFniLprnktu6eTFKibeNt96V21EZK/go-block-format" - "strconv" - "time" "github.com/OpenBazaar/wallet-interface" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcutil" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/any" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/net" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/net" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + ut "github.com/phoreproject/pm-go/util" +) + +var ( + // ErrEmptyPayload occurs when an inbound message is provided without the contents + ErrEmptyPayload = errors.New("message payload is empty") ) func (service *OpenBazaarService) HandlerForMsgType(t pb.Message_MessageType) func(peer.ID, *pb.Message, interface{}) (*pb.Message, error) { @@ -68,8 +76,12 @@ func (service *OpenBazaarService) HandlerForMsgType(t pb.Message_MessageType) fu return service.handleVendorFinalizedPayment case pb.Message_STORE: return service.handleStore + case pb.Message_ORDER_PAYMENT: + return service.handleOrderPayment case pb.Message_ERROR: return service.handleError + case pb.Message_ORDER_PROCESSING_FAILURE: + return service.handleOrderProcessingFailure default: return nil } @@ -82,7 +94,7 @@ func (service *OpenBazaarService) handlePing(peer peer.ID, pmes *pb.Message, opt func (service *OpenBazaarService) handleFollow(pid peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } sd := new(pb.SignedData) err := ptypes.UnmarshalAny(pmes.Payload, sd) @@ -118,16 +130,23 @@ func (service *OpenBazaarService) handleFollow(pid peer.ID, pmes *pb.Message, op if err != nil { return nil, err } - n := repo.FollowNotification{repo.NewNotificationID(), "follow", id.Pretty()} + n := repo.FollowNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeFollowNotification, + PeerId: id.Pretty(), + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } log.Debugf("Received FOLLOW message from %s", id.Pretty()) return nil, nil } func (service *OpenBazaarService) handleUnFollow(pid peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } sd := new(pb.SignedData) err := ptypes.UnmarshalAny(pmes.Payload, sd) @@ -161,7 +180,11 @@ func (service *OpenBazaarService) handleUnFollow(pid peer.ID, pmes *pb.Message, if err != nil { return nil, err } - n := repo.UnfollowNotification{repo.NewNotificationID(), "unfollow", id.Pretty()} + n := repo.UnfollowNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeUnfollowNotification, + PeerId: id.Pretty(), + } service.broadcast <- n log.Debugf("Received UNFOLLOW message from %s", id.Pretty()) return nil, nil @@ -196,7 +219,7 @@ func (service *OpenBazaarService) handleOfflineRelay(p peer.ID, pmes *pb.Message // Decrypt and unmarshal plaintext if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } plaintext, err := net.Decrypt(service.node.IpfsNode.PrivateKey, pmes.Payload.Value) if err != nil { @@ -239,9 +262,9 @@ func (service *OpenBazaarService) handleOfflineRelay(p peer.ID, pmes *pb.Message if err != nil { log.Errorf("handleOfflineRelayError: %s", err.Error()) } - err = service.node.IpfsNode.Repo.Datastore().Put(datastore.NewKey(core.KeyCachePrefix+id.Pretty()), env.Pubkey) - if err != nil { - log.Errorf("handleOfflineRelayError: %s", err.Error()) + store := service.node.IpfsNode.Repo.Datastore() + if err := ipfs.PutCachedPubkey(store, id.Pretty(), env.Pubkey); err != nil { + log.Errorf("caching pubkey: %s", err.Error()) } // Get handler for this message type @@ -263,28 +286,41 @@ func (service *OpenBazaarService) handleOfflineRelay(p peer.ID, pmes *pb.Message func (service *OpenBazaarService) handleOrder(peer peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { offline, _ := options.(bool) + + if offline { + log.Debugf("handling offline order from: %s", peer.Pretty()) + } else { + log.Debugf("handling normal order from: %s", peer.Pretty()) + } + contract := new(pb.RicardianContract) var orderId string - errorResponse := func(error string) *pb.Message { + errorResponse := func(errMsg string) *pb.Message { e := &pb.Error{ Code: 0, - ErrorMessage: error, + ErrorMessage: errMsg, OrderID: orderId, } - a, _ := ptypes.MarshalAny(e) + a, err := ptypes.MarshalAny(e) m := &pb.Message{ MessageType: pb.Message_ERROR, Payload: a, } + if err != nil { + log.Errorf("failed marshaling errorResponse (%s) for order (%s): %s", e.ErrorMessage, orderId, err) + return m + } if offline { - contract.Errors = []string{error} - service.node.Datastore.Sales().Put(orderId, *contract, pb.OrderState_PROCESSING_ERROR, false) + contract.Errors = []string{errMsg} + if err := service.node.Datastore.Sales().Put(orderId, *contract, pb.OrderState_PROCESSING_ERROR, false); err != nil { + log.Errorf("failed updating PROCESSING_ERROR on sale (%s): %s", orderId, err) + } } return m } if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } err := ptypes.UnmarshalAny(pmes.Payload, contract) if err != nil { @@ -296,32 +332,59 @@ func (service *OpenBazaarService) handleOrder(peer peer.ID, pmes *pb.Message, op return errorResponse(err.Error()), err } - pro, _ := service.node.GetProfile() + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderId, int(pb.Message_ORDER)), + orderId, pb.Message_ORDER, peer.Pretty(), repo.Message{Msg: *pmes}, + "", time.Now().UnixNano(), []byte(peer)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderId, int(pb.Message_ORDER), err) + } + + pro, err := service.node.GetProfile() + if err != nil { + log.Errorf("unable to read local profile: %s", err) + return errorResponse(fmt.Sprintf("unable to read local profile: %s", err.Error())), err + } + if !pro.Vendor { + log.Debugf("sending message to buyer that our store is not accepting orders") return errorResponse("the vendor turned his store off and is not accepting orders at this time"), errors.New("store is turned off") } err = service.node.ValidateOrder(contract, !offline) - if err != nil && (err != core.ErrPurchaseUnknownListing || !offline) { - return errorResponse(err.Error()), err + if err != nil { + if err != core.ErrPurchaseUnknownListing || !offline { + return errorResponse(err.Error()), err + } else { + log.Debugf("error validating order from %s: %s", err, peer.Pretty()) + } + } + + order, err := repo.ToV5Order(contract.BuyerOrder, service.node.LookupCurrency) + if err != nil { + return nil, err } - currentTime := time.Now() - purchaseTime := time.Unix(contract.BuyerOrder.Timestamp.Seconds, int64(contract.BuyerOrder.Timestamp.Nanos)) - wal, err := service.node.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + wal, err := service.node.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return errorResponse(err.Error()), err } + log.Debugf("incoming order linked to %s wallet", contract.BuyerOrder.Payment.AmountCurrency.Code) - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_ADDRESS_REQUEST { + if order.Payment.Method == pb.Order_Payment_ADDRESS_REQUEST { + log.Debugf("received direct online order from %s", peer.Pretty()) total, err := service.node.CalculateOrderTotal(contract) if err != nil { return errorResponse("Error calculating payment amount"), err } - if !service.node.ValidatePaymentAmount(total, contract.BuyerOrder.Payment.Amount) { + n, ok := new(big.Int).SetString(order.Payment.BigAmount, 10) + if !ok { + return errorResponse("invalid amount"), errors.New("invalid amount") + } + if !service.node.ValidatePaymentAmount(total, n) { return errorResponse("Calculated a different payment amount"), errors.New("calculated different payment amount") } - contract, err = service.node.NewOrderConfirmation(contract, true, false) + contract, err = service.node.NewOrderConfirmation(contract, true) if err != nil { return errorResponse("Error building order confirmation"), err } @@ -329,54 +392,71 @@ func (service *OpenBazaarService) handleOrder(peer peer.ID, pmes *pb.Message, op if err != nil { return errorResponse("Error building order confirmation"), err } - service.node.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_AWAITING_PAYMENT, false) - if currentTime.After(purchaseTime) { - service.node.Datastore.Sales().SetNeedsResync(contract.VendorOrderConfirmation.OrderID, true) + log.Debugf("storing sales order %s into the database and awaiting payment", contract.VendorOrderConfirmation.OrderID) + if err := service.node.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_AWAITING_PAYMENT, false); err != nil { + log.Errorf("failed to put sale (%s): %s", contract.VendorOrderConfirmation.OrderID, err) + return errorResponse("Error persisting order"), err } m := pb.Message{ MessageType: pb.Message_ORDER_CONFIRMATION, Payload: a, } - log.Debugf("Received addr-req ORDER message from %s", peer.Pretty()) + log.Debugf("sending order confirmation message to %s", peer.Pretty()) + log.Debugf("received addr-req ORDER message from %s", peer.Pretty()) return &m, nil - } else if contract.BuyerOrder.Payment.Method == pb.Order_Payment_DIRECT { - err := service.node.ValidateDirectPaymentAddress(contract.BuyerOrder) + } else if order.Payment.Method == pb.Order_Payment_DIRECT { + log.Debugf("received offline direct order from %s", peer.Pretty()) + err := service.node.ValidateDirectPaymentAddress(order) if err != nil { return errorResponse(err.Error()), err } - addr, err := wal.DecodeAddress(contract.BuyerOrder.Payment.Address) + addr, err := wal.DecodeAddress(ut.NormalizeAddress(order.Payment.Address)) if err != nil { return errorResponse(err.Error()), err } - wal.AddWatchedAddress(addr) - service.node.Datastore.Sales().Put(orderId, *contract, pb.OrderState_AWAITING_PAYMENT, false) - if currentTime.After(purchaseTime) { - service.node.Datastore.Sales().SetNeedsResync(orderId, true) + err = wal.AddWatchedAddresses(addr) + if err != nil { + log.Error(err) + } + log.Debugf("added address to wallet to watch: %s", addr) + log.Debugf("storing sales order %s in database", orderId) + err = service.node.Datastore.Sales().Put(orderId, *contract, pb.OrderState_AWAITING_PAYMENT, false) + if err != nil { + log.Error(err) } - log.Debugf("Received direct ORDER message from %s", peer.Pretty()) + log.Debugf("successfully processed direct ORDER message from %s", peer.Pretty()) return nil, nil - } else if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED && !offline { + } else if order.Payment.Method == pb.Order_Payment_MODERATED && !offline { + log.Debugf("processing moderated online order from %s", peer.Pretty()) total, err := service.node.CalculateOrderTotal(contract) if err != nil { return errorResponse("Error calculating payment amount"), errors.New("error calculating payment amount") } - if !service.node.ValidatePaymentAmount(total, contract.BuyerOrder.Payment.Amount) { + n, ok := new(big.Int).SetString(order.Payment.BigAmount, 10) + if !ok { + return errorResponse("invalid amount"), errors.New("invalid amount") + } + if !service.node.ValidatePaymentAmount(total, n) { return errorResponse("Calculated a different payment amount"), errors.New("calculated different payment amount") } timeout, err := time.ParseDuration(strconv.Itoa(int(contract.VendorListings[0].Metadata.EscrowTimeoutHours)) + "h") if err != nil { return errorResponse(err.Error()), err } - err = service.node.ValidateModeratedPaymentAddress(contract.BuyerOrder, timeout) + err = service.node.ValidateModeratedPaymentAddress(order, timeout) if err != nil { return errorResponse(err.Error()), err } - addr, err := wal.DecodeAddress(contract.BuyerOrder.Payment.Address) + addr, err := wal.DecodeAddress(ut.NormalizeAddress(order.Payment.Address)) if err != nil { return errorResponse(err.Error()), err } - wal.AddWatchedAddress(addr) - contract, err = service.node.NewOrderConfirmation(contract, false, false) + err = wal.AddWatchedAddresses(addr) + if err != nil { + log.Error(err) + } + log.Debugf("added watch address (%s) to wallet (%s)", addr, contract.BuyerOrder.Payment.AmountCurrency.Code) + contract, err = service.node.NewOrderConfirmation(contract, false) if err != nil { return errorResponse("Error building order confirmation"), errors.New("error building order confirmation") } @@ -384,49 +464,57 @@ func (service *OpenBazaarService) handleOrder(peer peer.ID, pmes *pb.Message, op if err != nil { return errorResponse("Error building order confirmation"), errors.New("error building order confirmation") } - service.node.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_AWAITING_PAYMENT, false) - if currentTime.After(purchaseTime) { - service.node.Datastore.Sales().SetNeedsResync(contract.VendorOrderConfirmation.OrderID, true) + err = service.node.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_AWAITING_PAYMENT, false) + if err != nil { + log.Error(err) } + log.Debugf("storing sales order %s in database", orderId) m := pb.Message{ MessageType: pb.Message_ORDER_CONFIRMATION, Payload: a, } log.Debugf("Received moderated ORDER message from %s", peer.Pretty()) return &m, nil - } else if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED && offline { + } else if order.Payment.Method == pb.Order_Payment_MODERATED && offline { + log.Debugf("processing moderated offline order from %s", peer.Pretty()) timeout, err := time.ParseDuration(strconv.Itoa(int(contract.VendorListings[0].Metadata.EscrowTimeoutHours)) + "h") if err != nil { log.Error(err) return errorResponse(err.Error()), err } - err = service.node.ValidateModeratedPaymentAddress(contract.BuyerOrder, timeout) + err = service.node.ValidateModeratedPaymentAddress(order, timeout) if err != nil { log.Error(err) return errorResponse(err.Error()), err } - addr, err := wal.DecodeAddress(contract.BuyerOrder.Payment.Address) + addr, err := wal.DecodeAddress(order.Payment.Address) if err != nil { log.Error(err) return errorResponse(err.Error()), err } - wal.AddWatchedAddress(addr) - log.Debugf("Received offline moderated ORDER message from %s", peer.Pretty()) - service.node.Datastore.Sales().Put(orderId, *contract, pb.OrderState_AWAITING_PAYMENT, false) - if currentTime.After(purchaseTime) { - service.node.Datastore.Sales().SetNeedsResync(orderId, true) + err = wal.AddWatchedAddresses(addr) + if err != nil { + log.Error(err) + } + log.Debugf("storing sales order %s in database", orderId) + err = service.node.Datastore.Sales().Put(orderId, *contract, pb.OrderState_AWAITING_PAYMENT, false) + if err != nil { + log.Error(err) } + log.Debugf("successfully processed offline moderated ORDER message from %s", peer.Pretty()) return nil, nil } - log.Error("Unrecognized payment type") + log.Errorf("Unrecognized payment type on order (%s)", contract.VendorOrderConfirmation.OrderID) return errorResponse("Unrecognized payment type"), errors.New("unrecognized payment type") } func (service *OpenBazaarService) handleOrderConfirmation(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { + log.Debugf("received order confirmation message from %s", p.Pretty()) + // Unmarshal payload if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } vendorContract := new(pb.RicardianContract) err := ptypes.UnmarshalAny(pmes.Payload, vendorContract) @@ -441,17 +529,40 @@ func (service *OpenBazaarService) handleOrderConfirmation(p peer.ID, pmes *pb.Me // Calc order ID orderId := vendorContract.VendorOrderConfirmation.OrderID + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderId, int(pb.Message_ORDER_CONFIRMATION)), + orderId, pb.Message_ORDER_CONFIRMATION, p.Pretty(), repo.Message{Msg: *pmes}, + "", time.Now().UnixNano(), []byte(p)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderId, int(pb.Message_ORDER_CONFIRMATION), err) + } + // Load the order + log.Debugf("loading order %s from the database", orderId) contract, state, funded, _, _, _, err := service.datastore.Purchases().GetByOrderId(orderId) if err != nil { + log.Debugf("could not retrieve order %s from the database: %s", orderId, err.Error()) + if err := service.SendProcessingError(p.Pretty(), orderId, pb.Message_ORDER_CONFIRMATION, nil); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } if funded && state == pb.OrderState_AWAITING_FULFILLMENT || !funded && state == pb.OrderState_AWAITING_PAYMENT { + log.Debugf("dropping duplicate order confirmation") return nil, net.DuplicateMessage } + if state != pb.OrderState_PENDING { + log.Debugf("order state (%s) is not what is expected", state.String()) + if err := service.SendProcessingError(p.Pretty(), vendorContract.VendorOrderConfirmation.OrderID, pb.Message_ORDER_CONFIRMATION, contract); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } + return nil, net.OutOfOrderMessage + } + // Validate the order confirmation + log.Debugf("validating order confirmation message") err = service.node.ValidateOrderConfirmation(vendorContract, false) if err != nil { return nil, err @@ -467,10 +578,18 @@ func (service *OpenBazaarService) handleOrderConfirmation(p peer.ID, pmes *pb.Me if funded { // Set message state to AWAITING_FULFILLMENT - service.datastore.Purchases().Put(orderId, *contract, pb.OrderState_AWAITING_FULFILLMENT, false) + log.Debugf("now awaiting fulfillment for order %s", orderId) + err := service.datastore.Purchases().Put(orderId, *contract, pb.OrderState_AWAITING_FULFILLMENT, false) + if err != nil { + log.Errorf("failed setting order (%) to AWAITING_FULFILLMENT: %s", orderId, err.Error()) + } } else { // Set message state to AWAITING_PAYMENT - service.datastore.Purchases().Put(orderId, *contract, pb.OrderState_AWAITING_PAYMENT, false) + log.Debugf("order not funded, awaiting payment for order %s", orderId) + err := service.datastore.Purchases().Put(orderId, *contract, pb.OrderState_AWAITING_PAYMENT, false) + if err != nil { + log.Errorf("failed setting order (%) to AWAITING_PAYMENT: %s", orderId, err.Error()) + } } var thumbnailTiny string @@ -487,31 +606,56 @@ func (service *OpenBazaarService) handleOrderConfirmation(p peer.ID, pmes *pb.Me } // Send notification to websocket - n := repo.OrderConfirmationNotification{repo.NewNotificationID(), "orderConfirmation", orderId, repo.Thumbnail{thumbnailTiny, thumbnailSmall}, vendorHandle, vendorID} + log.Debugf("broadcasting notification to the websocket for order %s", orderId) + n := repo.OrderConfirmationNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeOrderConfirmationNotification, + OrderId: orderId, + Thumbnail: repo.Thumbnail{Tiny: thumbnailTiny, Small: thumbnailSmall}, + VendorHandle: vendorHandle, + VendorID: vendorID, + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) - log.Debugf("Received ORDER_CONFIRMATION message from %s", p.Pretty()) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } + log.Debugf("successfully processed ORDER_CONFIRMATION message from %s", p.Pretty()) return nil, nil } func (service *OpenBazaarService) handleOrderCancel(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } orderId := string(pmes.Payload.Value) // Load the order contract, state, _, _, _, _, err := service.datastore.Sales().GetByOrderId(orderId) if err != nil { + if err := service.SendProcessingError(p.Pretty(), orderId, pb.Message_ORDER_CANCEL, nil); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderId, int(pb.Message_ORDER_CANCEL)), + orderId, pb.Message_ORDER_CANCEL, p.Pretty(), repo.Message{Msg: *pmes}, + "", time.Now().UnixNano(), []byte(p)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderId, int(pb.Message_ORDER_CANCEL), err) + } + if state == pb.OrderState_CANCELED { return nil, net.DuplicateMessage } // Set message state to canceled - service.datastore.Sales().Put(orderId, *contract, pb.OrderState_CANCELED, false) + err = service.datastore.Sales().Put(orderId, *contract, pb.OrderState_CANCELED, false) + if err != nil { + log.Error(err) + } var thumbnailTiny string var thumbnailSmall string @@ -527,9 +671,19 @@ func (service *OpenBazaarService) handleOrderCancel(p peer.ID, pmes *pb.Message, } // Send notification to websocket - n := repo.OrderCancelNotification{repo.NewNotificationID(), "canceled", orderId, repo.Thumbnail{thumbnailTiny, thumbnailSmall}, buyerHandle, buyerID} + n := repo.OrderCancelNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeOrderCancelNotification, + OrderId: orderId, + Thumbnail: repo.Thumbnail{Tiny: thumbnailTiny, Small: thumbnailSmall}, + BuyerHandle: buyerHandle, + BuyerID: buyerID, + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } log.Debugf("Received ORDER_CANCEL message from %s", p.Pretty()) return nil, nil @@ -537,7 +691,7 @@ func (service *OpenBazaarService) handleOrderCancel(p peer.ID, pmes *pb.Message, func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } rejectMsg := new(pb.OrderReject) err := ptypes.UnmarshalAny(pmes.Payload, rejectMsg) @@ -548,6 +702,9 @@ func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, opti // Load the order contract, state, _, records, _, _, err := service.datastore.Purchases().GetByOrderId(rejectMsg.OrderID) if err != nil { + if err := service.SendProcessingError(p.Pretty(), rejectMsg.OrderID, pb.Message_ORDER_REJECT, nil); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } @@ -555,21 +712,34 @@ func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, opti return nil, net.DuplicateMessage } - wal, err := service.node.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, service.node.LookupCurrency) + if err != nil { + return nil, err + } + + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", rejectMsg.OrderID, int(pb.Message_ORDER_REJECT)), + rejectMsg.OrderID, pb.Message_ORDER_REJECT, p.Pretty(), repo.Message{Msg: *pmes}, + "", time.Now().UnixNano(), []byte(p)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", rejectMsg.OrderID, int(pb.Message_ORDER_REJECT), err) + } + + wal, err := service.node.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return nil, err } - if contract.BuyerOrder.Payment.Method != pb.Order_Payment_MODERATED { + if order.Payment.Method != pb.Order_Payment_MODERATED { // Sweep the address into our wallet var txInputs []wallet.TransactionInput for _, r := range records { - if !r.Spent && r.Value > 0 { - hash, err := hex.DecodeString(r.Txid) + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { + hash, err := hex.DecodeString(ut.NormalizeAddress(r.Txid)) if err != nil { return nil, err } - addr, err := wal.DecodeAddress(r.Address) + addr, err := wal.DecodeAddress(ut.NormalizeAddress(r.Address)) if err != nil { return nil, err } @@ -584,12 +754,11 @@ func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, opti } } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincode, err := hex.DecodeString(order.Payment.Chaincode) if err != nil { return nil, err } - mPrivKey := service.node.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := service.node.MasterPrivateKey.ECPrivKey() if err != nil { return nil, err } @@ -597,11 +766,11 @@ func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, opti if err != nil { return nil, err } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(order.Payment.RedeemScript) if err != nil { return nil, err } - refundAddress, err := wal.DecodeAddress(contract.BuyerOrder.RefundAddress) + refundAddress, err := wal.DecodeAddress(ut.NormalizeAddress(order.RefundAddress)) if err != nil { return nil, err } @@ -611,34 +780,33 @@ func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, opti } } else { var ins []wallet.TransactionInput - var outValue int64 + outValue := big.NewInt(0) for _, r := range records { - if !r.Spent && r.Value > 0 { - outpointHash, err := hex.DecodeString(r.Txid) + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { + outpointHash, err := hex.DecodeString(ut.NormalizeAddress(r.Txid)) if err != nil { return nil, err } - outValue += r.Value + outValue = new(big.Int).Add(outValue, &r.Value) in := wallet.TransactionInput{OutpointIndex: r.Index, OutpointHash: outpointHash, Value: r.Value} ins = append(ins, in) } } - refundAddress, err := wal.DecodeAddress(contract.BuyerOrder.RefundAddress) + refundAddress, err := wal.DecodeAddress(ut.NormalizeAddress(order.RefundAddress)) if err != nil { return nil, err } var output = wallet.TransactionOutput{ Address: refundAddress, - Value: outValue, + Value: *outValue, } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincode, err := hex.DecodeString(order.Payment.Chaincode) if err != nil { return nil, err } - mPrivKey := service.node.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := service.node.MasterPrivateKey.ECPrivKey() if err != nil { return nil, err } @@ -646,12 +814,15 @@ func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, opti if err != nil { return nil, err } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(order.Payment.RedeemScript) if err != nil { return nil, err } - - buyerSignatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, buyerKey, redeemScript, contract.BuyerOrder.RefundFee) + fee, ok := new(big.Int).SetString(order.BigRefundFee, 10) + if !ok { + return nil, errors.New("invalid amount") + } + buyerSignatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, buyerKey, redeemScript, *fee) if err != nil { return nil, err } @@ -660,14 +831,17 @@ func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, opti sig := wallet.Signature{InputIndex: s.InputIndex, Signature: s.Signature} vendorSignatures = append(vendorSignatures, sig) } - _, err = wal.Multisign(ins, []wallet.TransactionOutput{output}, buyerSignatures, vendorSignatures, redeemScript, contract.BuyerOrder.RefundFee, true) + _, err = wal.Multisign(ins, []wallet.TransactionOutput{output}, buyerSignatures, vendorSignatures, redeemScript, *fee, true) if err != nil { return nil, err } } // Set message state to rejected - service.datastore.Purchases().Put(rejectMsg.OrderID, *contract, pb.OrderState_DECLINED, false) + err = service.datastore.Purchases().Put(rejectMsg.OrderID, *contract, pb.OrderState_DECLINED, false) + if err != nil { + log.Error(err) + } var thumbnailTiny string var thumbnailSmall string @@ -683,10 +857,20 @@ func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, opti } // Send notification to websocket - n := repo.OrderDeclinedNotification{repo.NewNotificationID(), "declined", rejectMsg.OrderID, repo.Thumbnail{thumbnailTiny, thumbnailSmall}, vendorHandle, vendorID} + n := repo.OrderDeclinedNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeOrderDeclinedNotification, + OrderId: rejectMsg.OrderID, + Thumbnail: repo.Thumbnail{Tiny: thumbnailTiny, Small: thumbnailSmall}, + VendorHandle: vendorHandle, + VendorID: vendorID, + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } log.Debugf("Received REJECT message from %s", p.Pretty()) return nil, nil @@ -694,7 +878,7 @@ func (service *OpenBazaarService) handleReject(p peer.ID, pmes *pb.Message, opti func (service *OpenBazaarService) handleRefund(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } rc := new(pb.RicardianContract) err := ptypes.UnmarshalAny(pmes.Payload, rc) @@ -713,48 +897,63 @@ func (service *OpenBazaarService) handleRefund(p peer.ID, pmes *pb.Message, opti // Load the order contract, state, _, records, _, _, err := service.datastore.Purchases().GetByOrderId(rc.Refund.OrderID) if err != nil { + if err := service.SendProcessingError(p.Pretty(), rc.Refund.OrderID, pb.Message_REFUND, nil); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", rc.Refund.OrderID, int(pb.Message_REFUND)), + rc.Refund.OrderID, pb.Message_REFUND, p.Pretty(), repo.Message{Msg: *pmes}, + "", time.Now().UnixNano(), []byte(p)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", rc.Refund.OrderID, int(pb.Message_REFUND), err) + } + if !(state == pb.OrderState_PARTIALLY_FULFILLED || state == pb.OrderState_AWAITING_FULFILLMENT) { return nil, net.DuplicateMessage } - wal, err := service.node.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, service.node.LookupCurrency) + if err != nil { + return nil, err + } + + wal, err := service.node.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return nil, err } - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED { + if order.Payment.Method == pb.Order_Payment_MODERATED { var ins []wallet.TransactionInput - var outValue int64 + outValue := big.NewInt(0) for _, r := range records { - if !r.Spent && r.Value > 0 { - outpointHash, err := hex.DecodeString(r.Txid) + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { + outpointHash, err := hex.DecodeString(ut.NormalizeAddress(r.Txid)) if err != nil { return nil, err } - outValue += r.Value + outValue = new(big.Int).Add(outValue, &r.Value) in := wallet.TransactionInput{OutpointIndex: r.Index, OutpointHash: outpointHash, Value: r.Value} ins = append(ins, in) } } - refundAddress, err := wal.DecodeAddress(contract.BuyerOrder.RefundAddress) + refundAddress, err := wal.DecodeAddress(ut.NormalizeAddress(order.RefundAddress)) if err != nil { return nil, err } var output = wallet.TransactionOutput{ Address: refundAddress, - Value: outValue, + Value: *outValue, } - chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode) + chaincode, err := hex.DecodeString(order.Payment.Chaincode) if err != nil { return nil, err } - mPrivKey := service.node.MasterPrivateKey - mECKey, err := mPrivKey.ECPrivKey() + mECKey, err := service.node.MasterPrivateKey.ECPrivKey() if err != nil { return nil, err } @@ -762,12 +961,15 @@ func (service *OpenBazaarService) handleRefund(p peer.ID, pmes *pb.Message, opti if err != nil { return nil, err } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(order.Payment.RedeemScript) if err != nil { return nil, err } - - buyerSignatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, buyerKey, redeemScript, contract.BuyerOrder.RefundFee) + fee, ok := new(big.Int).SetString(order.BigRefundFee, 10) + if !ok { + return nil, errors.New("invalid amount") + } + buyerSignatures, err := wal.CreateMultisigSignature(ins, []wallet.TransactionOutput{output}, buyerKey, redeemScript, *fee) if err != nil { return nil, err } @@ -776,7 +978,7 @@ func (service *OpenBazaarService) handleRefund(p peer.ID, pmes *pb.Message, opti sig := wallet.Signature{InputIndex: s.InputIndex, Signature: s.Signature} vendorSignatures = append(vendorSignatures, sig) } - _, err = wal.Multisign(ins, []wallet.TransactionOutput{output}, buyerSignatures, vendorSignatures, redeemScript, contract.BuyerOrder.RefundFee, true) + _, err = wal.Multisign(ins, []wallet.TransactionOutput{output}, buyerSignatures, vendorSignatures, redeemScript, *fee, true) if err != nil { return nil, err } @@ -789,7 +991,10 @@ func (service *OpenBazaarService) handleRefund(p peer.ID, pmes *pb.Message, opti } // Set message state to refunded - service.datastore.Purchases().Put(contract.Refund.OrderID, *contract, pb.OrderState_REFUNDED, false) + err = service.datastore.Purchases().Put(contract.Refund.OrderID, *contract, pb.OrderState_REFUNDED, false) + if err != nil { + log.Error(err) + } var thumbnailTiny string var thumbnailSmall string @@ -805,16 +1010,29 @@ func (service *OpenBazaarService) handleRefund(p peer.ID, pmes *pb.Message, opti } // Send notification to websocket - n := repo.RefundNotification{repo.NewNotificationID(), "refund", contract.Refund.OrderID, repo.Thumbnail{thumbnailTiny, thumbnailSmall}, vendorHandle, vendorID} + n := repo.RefundNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeRefundNotification, + OrderId: contract.Refund.OrderID, + Thumbnail: repo.Thumbnail{Tiny: thumbnailTiny, Small: thumbnailSmall}, + VendorHandle: vendorHandle, + VendorID: vendorID, + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } log.Debugf("Received REFUND message from %s", p.Pretty()) return nil, nil } func (service *OpenBazaarService) handleOrderFulfillment(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { + + log.Debugf("received order fulfillment message from %s", p.Pretty()) + if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } rc := new(pb.RicardianContract) err := ptypes.UnmarshalAny(pmes.Payload, rc) @@ -826,17 +1044,34 @@ func (service *OpenBazaarService) handleOrderFulfillment(p peer.ID, pmes *pb.Mes return nil, errors.New("received FULFILLMENT message with no VendorOrderFulfillment objects") } + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", rc.VendorOrderFulfillment[0].OrderId, int(pb.Message_ORDER_FULFILLMENT)), + rc.VendorOrderFulfillment[0].OrderId, pb.Message_ORDER_FULFILLMENT, p.Pretty(), repo.Message{Msg: *pmes}, + "", time.Now().UnixNano(), []byte(p)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", rc.VendorOrderFulfillment[0].OrderId, int(pb.Message_ORDER_FULFILLMENT), err) + } + // Load the order contract, state, _, _, _, _, err := service.datastore.Purchases().GetByOrderId(rc.VendorOrderFulfillment[0].OrderId) if err != nil { + log.Debugf("unable to find a matching order in the purchases table of the database") + if err := service.SendProcessingError(p.Pretty(), rc.VendorOrderFulfillment[0].OrderId, pb.Message_ORDER_FULFILLMENT, nil); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } if state == pb.OrderState_PENDING || state == pb.OrderState_AWAITING_PAYMENT { + log.Debugf("order state (%s) is not what is expected", state.String()) + if err := service.SendProcessingError(p.Pretty(), rc.VendorOrderFulfillment[0].OrderId, pb.Message_ORDER_FULFILLMENT, contract); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } if !(state == pb.OrderState_PARTIALLY_FULFILLED || state == pb.OrderState_AWAITING_FULFILLMENT) { + log.Debugf("order state (%s) is not what is expected", state.String()) return nil, net.DuplicateMessage } @@ -847,15 +1082,24 @@ func (service *OpenBazaarService) handleOrderFulfillment(p peer.ID, pmes *pb.Mes } } + log.Debugf("validating order fulfillment message") if err := service.node.ValidateOrderFulfillment(rc.VendorOrderFulfillment[0], contract); err != nil { return nil, err } // Set message state to fulfilled if all listings have a matching fulfillment message if service.node.IsFulfilled(contract) { - service.datastore.Purchases().Put(rc.VendorOrderFulfillment[0].OrderId, *contract, pb.OrderState_FULFILLED, false) + log.Debugf("updating order %s in the database to fulfilled", rc.VendorOrderFulfillment[0].OrderId) + err = service.datastore.Purchases().Put(rc.VendorOrderFulfillment[0].OrderId, *contract, pb.OrderState_FULFILLED, false) + if err != nil { + log.Error(err) + } } else { - service.datastore.Purchases().Put(rc.VendorOrderFulfillment[0].OrderId, *contract, pb.OrderState_PARTIALLY_FULFILLED, false) + log.Debugf("updating order %s in the database to partially fulfilled", rc.VendorOrderFulfillment[0].OrderId) + err = service.datastore.Purchases().Put(rc.VendorOrderFulfillment[0].OrderId, *contract, pb.OrderState_PARTIALLY_FULFILLED, false) + if err != nil { + log.Error(err) + } } var thumbnailTiny string @@ -872,10 +1116,20 @@ func (service *OpenBazaarService) handleOrderFulfillment(p peer.ID, pmes *pb.Mes } // Send notification to websocket - n := repo.FulfillmentNotification{repo.NewNotificationID(), "fulfillment", rc.VendorOrderFulfillment[0].OrderId, repo.Thumbnail{thumbnailTiny, thumbnailSmall}, vendorHandle, vendorID} + n := repo.FulfillmentNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeFulfillmentNotification, + OrderId: rc.VendorOrderFulfillment[0].OrderId, + Thumbnail: repo.Thumbnail{Tiny: thumbnailTiny, Small: thumbnailSmall}, + VendorHandle: vendorHandle, + VendorID: vendorID, + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) - log.Debugf("Received ORDER_FULFILLMENT message from %s", p.Pretty()) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } + log.Debugf("successfully processed ORDER_FULFILLMENT message from %s", p.Pretty()) return nil, nil } @@ -883,7 +1137,7 @@ func (service *OpenBazaarService) handleOrderFulfillment(p peer.ID, pmes *pb.Mes func (service *OpenBazaarService) handleOrderCompletion(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } rc := new(pb.RicardianContract) err := ptypes.UnmarshalAny(pmes.Payload, rc) @@ -895,9 +1149,20 @@ func (service *OpenBazaarService) handleOrderCompletion(p peer.ID, pmes *pb.Mess return nil, errors.New("received ORDER_COMPLETION with nil BuyerOrderCompletion object") } + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", rc.BuyerOrderCompletion.OrderId, int(pb.Message_ORDER_COMPLETION)), + rc.BuyerOrderCompletion.OrderId, pb.Message_ORDER_COMPLETION, p.Pretty(), repo.Message{Msg: *pmes}, + "", time.Now().UnixNano(), []byte(p)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", rc.BuyerOrderCompletion.OrderId, int(pb.Message_ORDER_COMPLETION), err) + } + // Load the order contract, state, _, records, _, _, err := service.datastore.Sales().GetByOrderId(rc.BuyerOrderCompletion.OrderId) if err != nil { + if err := service.SendProcessingError(p.Pretty(), rc.BuyerOrderCompletion.OrderId, pb.Message_ORDER_COMPLETION, nil); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } @@ -905,7 +1170,12 @@ func (service *OpenBazaarService) handleOrderCompletion(p peer.ID, pmes *pb.Mess return nil, net.DuplicateMessage } - wal, err := service.node.Multiwallet.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) + order, err := repo.ToV5Order(contract.BuyerOrder, service.node.LookupCurrency) + if err != nil { + return nil, err + } + + wal, err := service.node.Multiwallet.WalletForCurrencyCode(order.Payment.AmountCurrency.Code) if err != nil { return nil, err } @@ -920,23 +1190,28 @@ func (service *OpenBazaarService) handleOrderCompletion(p peer.ID, pmes *pb.Mess if err := service.node.ValidateOrderCompletion(contract); err != nil { return nil, err } - if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED && state != pb.OrderState_DISPUTED && state != pb.OrderState_DECIDED && state != pb.OrderState_RESOLVED && state != pb.OrderState_PAYMENT_FINALIZED { + if order.Payment.Method == pb.Order_Payment_MODERATED && state != pb.OrderState_DISPUTED && state != pb.OrderState_DECIDED && state != pb.OrderState_RESOLVED && state != pb.OrderState_PAYMENT_FINALIZED { var ins []wallet.TransactionInput - var outValue int64 + outValue := big.NewInt(0) for _, r := range records { - if !r.Spent && r.Value > 0 { - outpointHash, err := hex.DecodeString(r.Txid) + if !r.Spent && r.Value.Cmp(big.NewInt(0)) > 0 { + outpointHash, err := hex.DecodeString(ut.NormalizeAddress(r.Txid)) if err != nil { return nil, err } - outValue += r.Value - in := wallet.TransactionInput{OutpointIndex: r.Index, OutpointHash: outpointHash} + outValue = new(big.Int).Add(outValue, &r.Value) + in := wallet.TransactionInput{ + OutpointIndex: r.Index, + OutpointHash: outpointHash, + Value: r.Value, + } ins = append(ins, in) } } var payoutAddress btcutil.Address if len(contract.VendorOrderFulfillment) > 0 { - payoutAddress, err = wal.DecodeAddress(contract.VendorOrderFulfillment[0].Payout.PayoutAddress) + payoutAddress, err = wal.DecodeAddress( + ut.NormalizeAddress(contract.VendorOrderFulfillment[0].Payout.PayoutAddress)) if err != nil { return nil, err } @@ -945,10 +1220,10 @@ func (service *OpenBazaarService) handleOrderCompletion(p peer.ID, pmes *pb.Mess } var output = wallet.TransactionOutput{ Address: payoutAddress, - Value: outValue, + Value: *outValue, } - redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript) + redeemScript, err := hex.DecodeString(order.Payment.RedeemScript) if err != nil { return nil, err } @@ -963,20 +1238,37 @@ func (service *OpenBazaarService) handleOrderCompletion(p peer.ID, pmes *pb.Mess sig := wallet.Signature{InputIndex: s.InputIndex, Signature: s.Signature} buyerSignatures = append(buyerSignatures, sig) } - - _, err = wal.Multisign(ins, []wallet.TransactionOutput{output}, buyerSignatures, vendorSignatures, redeemScript, contract.VendorOrderFulfillment[0].Payout.PayoutFeePerByte, true) + fulfillment := repo.ToV5OrderFulfillment(contract.VendorOrderFulfillment[0]) + payoutFee, ok := new(big.Int).SetString(fulfillment.Payout.BigPayoutFeePerByte, 10) + if !ok { + return nil, errors.New("invalid amount") + } + _, err = wal.Multisign(ins, []wallet.TransactionOutput{output}, buyerSignatures, vendorSignatures, redeemScript, *payoutFee, true) if err != nil { + if err.Error() == "ERROR_INSUFFICIENT_FUNDS" { + err0 := service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", rc.BuyerOrderCompletion.OrderId, int(pb.Message_ORDER_COMPLETION)), + rc.BuyerOrderCompletion.OrderId, pb.Message_ORDER_COMPLETION, p.Pretty(), repo.Message{Msg: *pmes}, + err.Error(), time.Now().UnixNano(), []byte(p)) + if err0 != nil { + log.Errorf("failed putting message (%s-%d): %v", rc.BuyerOrderCompletion.OrderId, int(pb.Message_ORDER_COMPLETION), err0) + } + } + return nil, err } } err = service.node.ValidateAndSaveRating(contract) if err != nil { - log.Error("Error validating rating:", err) + log.Error("error validating rating:", err) } // Set message state to complete - service.datastore.Sales().Put(rc.BuyerOrderCompletion.OrderId, *contract, pb.OrderState_COMPLETED, false) + err = service.datastore.Sales().Put(rc.BuyerOrderCompletion.OrderId, *contract, pb.OrderState_COMPLETED, false) + if err != nil { + log.Error(err) + } var thumbnailTiny string var thumbnailSmall string @@ -985,25 +1277,34 @@ func (service *OpenBazaarService) handleOrderCompletion(p peer.ID, pmes *pb.Mess if len(contract.VendorListings) > 0 && contract.VendorListings[0].Item != nil && len(contract.VendorListings[0].Item.Images) > 0 { thumbnailTiny = contract.VendorListings[0].Item.Images[0].Tiny thumbnailSmall = contract.VendorListings[0].Item.Images[0].Small - if contract.BuyerOrder != nil && contract.BuyerOrder.BuyerID != nil { - buyerID = contract.BuyerOrder.BuyerID.PeerID - buyerHandle = contract.BuyerOrder.BuyerID.Handle + if order.BuyerID != nil { + buyerID = order.BuyerID.PeerID + buyerHandle = order.BuyerID.Handle } } // Send notification to websocket - n := repo.CompletionNotification{repo.NewNotificationID(), "orderComplete", rc.BuyerOrderCompletion.OrderId, repo.Thumbnail{thumbnailTiny, thumbnailSmall}, buyerHandle, buyerID} + n := repo.CompletionNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeCompletionNotification, + OrderId: rc.BuyerOrderCompletion.OrderId, + Thumbnail: repo.Thumbnail{Tiny: thumbnailTiny, Small: thumbnailSmall}, + BuyerHandle: buyerHandle, + BuyerID: buyerID, + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) - log.Debugf("Received ORDER_COMPLETION message from %s", p.Pretty()) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } + log.Debugf("received ORDER_COMPLETION message from %s", p.Pretty()) return nil, nil } func (service *OpenBazaarService) handleDisputeOpen(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { - // Unmarshall if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } rc := new(pb.RicardianContract) err := ptypes.UnmarshalAny(pmes.Payload, rc) @@ -1011,6 +1312,20 @@ func (service *OpenBazaarService) handleDisputeOpen(p peer.ID, pmes *pb.Message, return nil, err } + orderID, err := service.node.CalcOrderID(rc.BuyerOrder) + if err != nil { + log.Errorf("failed calc orderID") + } + + if orderID != "" { + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID, int(pb.Message_DISPUTE_OPEN)), + orderID, pb.Message_DISPUTE_OPEN, p.Pretty(), repo.Message{Msg: *pmes}, "", time.Now().UnixNano(), []byte(p)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID, int(pb.Message_DISPUTE_OPEN), err) + } + } + // Verify signature err = service.node.VerifySignatureOnDisputeOpen(rc, p.Pretty()) if err != nil { @@ -1022,7 +1337,7 @@ func (service *OpenBazaarService) handleDisputeOpen(p peer.ID, pmes *pb.Message, if err != nil { return nil, err } - log.Debugf("Received DISPUTE_OPEN message from %s", p.Pretty()) + log.Debugf("received DISPUTE_OPEN message from %s", p.Pretty()) return nil, nil } @@ -1031,17 +1346,30 @@ func (service *OpenBazaarService) handleDisputeUpdate(p peer.ID, pmes *pb.Messag // Make sure we aren't currently processing any disputes before proceeding core.DisputeWg.Wait() - // Unmarshall if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } update := new(pb.DisputeUpdate) err := ptypes.UnmarshalAny(pmes.Payload, update) if err != nil { return nil, err } + + orderID := update.OrderId + if orderID != "" { + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID, int(pb.Message_DISPUTE_UPDATE)), + orderID, pb.Message_DISPUTE_UPDATE, p.Pretty(), repo.Message{Msg: *pmes}, "", time.Now().UnixNano(), []byte(p)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID, int(pb.Message_DISPUTE_UPDATE), err) + } + } + dispute, err := service.node.Datastore.Cases().GetByCaseID(update.OrderId) if err != nil { + if err := service.SendProcessingError(p.Pretty(), update.OrderId, pb.Message_DISPUTE_UPDATE, nil); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } rc := new(pb.RicardianContract) @@ -1099,19 +1427,31 @@ func (service *OpenBazaarService) handleDisputeUpdate(p peer.ID, pmes *pb.Messag } // Send notification to websocket - n := repo.DisputeUpdateNotification{repo.NewNotificationID(), "disputeUpdate", update.OrderId, repo.Thumbnail{thumbnailTiny, thumbnailSmall}, disputerID, disputerHandle, disputeeID, disputeeHandle, buyer} + n := repo.DisputeUpdateNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeDisputeUpdateNotification, + OrderId: update.OrderId, + Thumbnail: repo.Thumbnail{Tiny: thumbnailTiny, Small: thumbnailSmall}, + DisputerID: disputerID, + DisputerHandle: disputerHandle, + DisputeeID: disputeeID, + DisputeeHandle: disputeeHandle, + Buyer: buyer, + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) - log.Debugf("Received DISPUTE_UPDATE message from %s", p.Pretty()) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } + log.Debugf("received DISPUTE_UPDATE message from %s", p.Pretty()) return nil, nil } func (service *OpenBazaarService) handleDisputeClose(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { - // Unmarshall if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } rc := new(pb.RicardianContract) err := ptypes.UnmarshalAny(pmes.Payload, rc) @@ -1119,6 +1459,16 @@ func (service *OpenBazaarService) handleDisputeClose(p peer.ID, pmes *pb.Message return nil, err } + orderID := rc.DisputeResolution.OrderId + if orderID != "" { + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID, int(pb.Message_DISPUTE_CLOSE)), + orderID, pb.Message_DISPUTE_CLOSE, p.Pretty(), repo.Message{Msg: *pmes}, "", time.Now().UnixNano(), []byte(p)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID, int(pb.Message_DISPUTE_CLOSE), err) + } + } + // Load the order isPurchase := false var contract *pb.RicardianContract @@ -1130,6 +1480,9 @@ func (service *OpenBazaarService) handleDisputeClose(p peer.ID, pmes *pb.Message if err != nil { contract, state, _, _, _, _, err = service.datastore.Purchases().GetByOrderId(rc.DisputeResolution.OrderId) if err != nil { + if err := service.SendProcessingError(p.Pretty(), rc.DisputeResolution.OrderId, pb.Message_DISPUTE_CLOSE, nil); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } isPurchase = true @@ -1149,6 +1502,9 @@ func (service *OpenBazaarService) handleDisputeClose(p peer.ID, pmes *pb.Message } if state != pb.OrderState_DISPUTED { + if err := service.SendProcessingError(p.Pretty(), rc.DisputeResolution.OrderId, pb.Message_DISPUTE_CLOSE, contract); err != nil { + log.Errorf("failed sending ORDER_PROCESSING_FAILURE to peer (%s): %s", p.Pretty(), err) + } return nil, net.OutOfOrderMessage } @@ -1164,11 +1520,19 @@ func (service *OpenBazaarService) handleDisputeClose(p peer.ID, pmes *pb.Message return nil, err } + // If DisputeAcceptance is already set then move the state directly to RESOLVED if isPurchase { - // Set message state to complete - err = service.datastore.Purchases().Put(rc.DisputeResolution.OrderId, *contract, pb.OrderState_DECIDED, false) + if contract.DisputeAcceptance != nil { + err = service.datastore.Purchases().Put(rc.DisputeResolution.OrderId, *contract, pb.OrderState_RESOLVED, false) + } else { + err = service.datastore.Purchases().Put(rc.DisputeResolution.OrderId, *contract, pb.OrderState_DECIDED, false) + } } else { - err = service.datastore.Sales().Put(rc.DisputeResolution.OrderId, *contract, pb.OrderState_DECIDED, false) + if contract.DisputeAcceptance != nil { + err = service.datastore.Sales().Put(rc.DisputeResolution.OrderId, *contract, pb.OrderState_RESOLVED, false) + } else { + err = service.datastore.Sales().Put(rc.DisputeResolution.OrderId, *contract, pb.OrderState_DECIDED, false) + } } if err != nil { return nil, err @@ -1182,19 +1546,112 @@ func (service *OpenBazaarService) handleDisputeClose(p peer.ID, pmes *pb.Message } // Send notification to websocket - n := repo.DisputeCloseNotification{repo.NewNotificationID(), "disputeClose", rc.DisputeResolution.OrderId, repo.Thumbnail{thumbnailTiny, thumbnailSmall}, otherPartyID, otherPartyHandle, buyer} + n := repo.DisputeCloseNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeDisputeCloseNotification, + OrderId: rc.DisputeResolution.OrderId, + Thumbnail: repo.Thumbnail{Tiny: thumbnailTiny, Small: thumbnailSmall}, + OtherPartyID: otherPartyID, + OtherPartyHandle: otherPartyHandle, + Buyer: buyer, + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) - log.Debugf("Received DISPUTE_CLOSE message from %s", p.Pretty()) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } + log.Debugf("received DISPUTE_CLOSE message from %s", p.Pretty()) + return nil, nil +} + +func (service *OpenBazaarService) handleOrderProcessingFailure(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { + if pmes.Payload == nil { + return nil, ErrEmptyPayload + } + procFailure := new(pb.OrderProcessingFailure) + if err := ptypes.UnmarshalAny(pmes.Payload, procFailure); err != nil { + return nil, err + } + + var ( + localContract *pb.RicardianContract + ) + if contract, _, _, _, _, _, err := service.node.Datastore.Sales().GetByOrderId(procFailure.OrderID); err != nil { + localContract = contract + } else if contract, _, _, _, _, _, err := service.node.Datastore.Purchases().GetByOrderId(procFailure.OrderID); err != nil { + localContract = contract + } + if localContract == nil { + return nil, fmt.Errorf("no contract found for order ID (%s)", procFailure.OrderID) + } + // TODO: Validate we aren't in a loop, exit if we are + missingMessageTypes, err := analyzeForMissingMessages(localContract, procFailure) + if err != nil { + return nil, err + } + if missingMessageTypes == nil { + err := fmt.Errorf("unable to determine missing message types for order ID (%s)", procFailure.OrderID) + log.Error(err.Error()) + return nil, err + } + for _, msgType := range missingMessageTypes { + log.Debugf("resending missing ORDER message (%s) to peer (%s)", msgType.String(), p.Pretty()) + if err := service.node.ResendCachedOrderMessage(procFailure.OrderID, msgType); err != nil { + err := fmt.Errorf("resending message type (%s) for order (%s): %s", msgType.String(), procFailure.OrderID, err.Error()) + log.Error(err.Error()) + // TODO: Can we attempt to recreate MessageType? + return nil, err + } + } return nil, nil } +// analyzeForMissingMessages compares the local RicardianContract with the one provided with the +// error message to determine which messages might be missing and need to be resent to the remote +// peer +func analyzeForMissingMessages(lc *pb.RicardianContract, e *pb.OrderProcessingFailure) ([]pb.Message_MessageType, error) { + var msgsToResend = []pb.Message_MessageType{} + if lc == nil { + return nil, fmt.Errorf("no local contract for order ID (%s) to compare to, unable to recover missing messages", e.OrderID) + } + if lc.BuyerOrder != nil && (e.Contract == nil || e.Contract.BuyerOrder == nil) { + msgsToResend = append(msgsToResend, pb.Message_ORDER) + } + if lc.VendorOrderConfirmation != nil && (e.Contract == nil || e.Contract.VendorOrderConfirmation == nil) { + msgsToResend = append(msgsToResend, pb.Message_ORDER_CONFIRMATION) + } + // TODO: How do we detect ORDER_REJECT diff? + // TODO: How do we detect ORDER_CANCEL diff? + if len(lc.VendorOrderFulfillment) != 0 && (e.Contract == nil || len(e.Contract.VendorOrderFulfillment) == 0) { + msgsToResend = append(msgsToResend, pb.Message_ORDER_FULFILLMENT) + } + if lc.Dispute != nil && (e.Contract == nil || e.Contract.Dispute == nil) { + msgsToResend = append(msgsToResend, pb.Message_DISPUTE_OPEN) + msgsToResend = append(msgsToResend, pb.Message_DISPUTE_UPDATE) + } + if lc.DisputeResolution != nil && (e.Contract == nil || e.Contract.DisputeResolution == nil) { + // TODO: Re-broadcast error to moderator so they can resend DISPUTE_CLOSE + msgsToResend = append(msgsToResend, pb.Message_DISPUTE_CLOSE) + } + if lc.DisputeAcceptance != nil && (e.Contract == nil || e.Contract.DisputeAcceptance == nil) { + // TODO: This msg occurs after order is PENDING, FULFILLED, and DISPUTED states, is + // there a better check for resending FINALIZED_PAYMENT? + msgsToResend = append(msgsToResend, pb.Message_VENDOR_FINALIZED_PAYMENT) + } + if lc.Refund != nil && (e.Contract == nil || e.Contract.Refund == nil) { + msgsToResend = append(msgsToResend, pb.Message_REFUND) + } + if lc.BuyerOrderCompletion != nil && (e.Contract == nil || e.Contract.BuyerOrderCompletion == nil) { + msgsToResend = append(msgsToResend, pb.Message_ORDER_COMPLETION) + } + return msgsToResend, nil +} + func (service *OpenBazaarService) handleChat(p peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { - // Unmarshall if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } chat := new(pb.Chat) err := ptypes.UnmarshalAny(pmes.Payload, chat) @@ -1256,28 +1713,37 @@ func (service *OpenBazaarService) handleChat(p peer.ID, pmes *pb.Message, option if chat.Subject != "" { go func() { - service.datastore.Purchases().MarkAsUnread(chat.Subject) - service.datastore.Sales().MarkAsUnread(chat.Subject) - service.datastore.Cases().MarkAsUnread(chat.Subject) + err = service.datastore.Purchases().MarkAsUnread(chat.Subject) + if err != nil { + log.Error(err) + } + err = service.datastore.Sales().MarkAsUnread(chat.Subject) + if err != nil { + log.Error(err) + } + err = service.datastore.Cases().MarkAsUnread(chat.Subject) + if err != nil { + log.Error(err) + } }() } // Push to websocket - n := repo.ChatMessage{ + n := repo.ChatMessageNotification{ MessageId: chat.MessageId, PeerId: p.Pretty(), Subject: chat.Subject, Message: chat.Message, - Timestamp: t, + Timestamp: repo.NewAPITime(t), } service.broadcast <- n - log.Debugf("Received CHAT message from %s", p.Pretty()) + log.Debugf("received CHAT message from %s", p.Pretty()) return nil, nil } func (service *OpenBazaarService) handleModeratorAdd(pid peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } sd := new(pb.SignedData) err := ptypes.UnmarshalAny(pmes.Payload, sd) @@ -1311,14 +1777,15 @@ func (service *OpenBazaarService) handleModeratorAdd(pid peer.ID, pmes *pb.Messa if err != nil { return nil, err } - log.Debugf("Received MODERATOR_ADD message from %s", id.Pretty()) + + log.Debugf("received MODERATOR_ADD message from %s", id.Pretty()) return nil, nil } func (service *OpenBazaarService) handleModeratorRemove(pid peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } sd := new(pb.SignedData) err := ptypes.UnmarshalAny(pmes.Payload, sd) @@ -1352,7 +1819,8 @@ func (service *OpenBazaarService) handleModeratorRemove(pid peer.ID, pmes *pb.Me if err != nil { return nil, err } - log.Debugf("Received MODERATOR_REMOVE message from %s", id.Pretty()) + + log.Debugf("received MODERATOR_REMOVE message from %s", id.Pretty()) return nil, nil } @@ -1365,7 +1833,7 @@ func (service *OpenBazaarService) handleBlock(pid peer.ID, pmes *pb.Message, opt } if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } b := new(pb.Block) err := ptypes.UnmarshalAny(pmes.Payload, b) @@ -1384,13 +1852,13 @@ func (service *OpenBazaarService) handleBlock(pid peer.ID, pmes *pb.Message, opt if err != nil { return nil, err } - log.Debugf("Received BLOCK message from %s", pid.Pretty()) + log.Debugf("received BLOCK message from %s", pid.Pretty()) return nil, nil } func (service *OpenBazaarService) handleVendorFinalizedPayment(pid peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } paymentFinalizedMessage := new(pb.VendorFinalizedPayment) if err := ptypes.UnmarshalAny(pmes.Payload, paymentFinalizedMessage); err != nil { @@ -1405,16 +1873,22 @@ func (service *OpenBazaarService) handleVendorFinalizedPayment(pid peer.ID, pmes if state != pb.OrderState_PENDING && state != pb.OrderState_FULFILLED && state != pb.OrderState_DISPUTED { return nil, errors.New("release escrow can only be called when sale is pending, fulfilled, or disputed") } - service.datastore.Purchases().Put(paymentFinalizedMessage.OrderID, *contract, pb.OrderState_PAYMENT_FINALIZED, false) + err = service.datastore.Purchases().Put(paymentFinalizedMessage.OrderID, *contract, pb.OrderState_PAYMENT_FINALIZED, false) + if err != nil { + log.Error(err) + } n := repo.VendorFinalizedPayment{ ID: repo.NewNotificationID(), Type: repo.NotifierTypeVendorFinalizedPayment, OrderID: paymentFinalizedMessage.OrderID, } - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } service.broadcast <- n - log.Debugf("Received VENDOR_FINALIZED_PAYMENT message from %s", pid.Pretty()) + log.Debugf("received VENDOR_FINALIZED_PAYMENT message from %s", pid.Pretty()) return nil, nil } @@ -1435,12 +1909,12 @@ func (service *OpenBazaarService) handleStore(pid peer.ID, pmes *pb.Message, opt } if pmes.Payload == nil { - return nil, errors.New("payload is nil") + return nil, ErrEmptyPayload } cList := new(pb.CidList) err := ptypes.UnmarshalAny(pmes.Payload, cList) if err != nil { - return errorResponse("Could not unmarshall message"), err + return errorResponse("could not unmarshall message"), err } var need []string for _, id := range cList.Cids { @@ -1469,15 +1943,161 @@ func (service *OpenBazaarService) handleStore(pid peer.ID, pmes *pb.Message, opt return m, nil } -func (service *OpenBazaarService) handleError(peer peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { +func (service *OpenBazaarService) handleOrderPayment(peer peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { + log.Debugf("received order payment message from: %s", peer.Pretty()) + if pmes.Payload == nil { return nil, errors.New("payload is nil") } + paymentDetails := new(pb.OrderPaymentTxn) + err := ptypes.UnmarshalAny(pmes.Payload, paymentDetails) + if err != nil { + return nil, err + } + + orderID := paymentDetails.OrderID + err = service.node.Datastore.Messages().Put( + fmt.Sprintf("%s-%d", orderID, int(pb.Message_ORDER_PAYMENT)), + orderID, pb.Message_ORDER_PAYMENT, peer.Pretty(), repo.Message{Msg: *pmes}, "", time.Now().UnixNano(), []byte(peer)) + if err != nil { + log.Errorf("failed putting message (%s-%d): %v", orderID, int(pb.Message_ORDER_PAYMENT), err) + } + + wal, err := service.node.Multiwallet.WalletForCurrencyCode(paymentDetails.GetCoin()) + if err != nil { + return nil, err + } + + wal0, ok := wal.(wallet.WalletMustManuallyAssociateTransactionToOrder) + if !ok { + return nil, nil + } + + chash, err := chainhash.NewHashFromStr(paymentDetails.GetTransactionID()) + if err != nil { + return nil, err + } + + log.Debugf("retrieving %s transaction %s", paymentDetails.Coin, chash.String()) + txn, err := wal.GetTransaction(*chash) + if err != nil { + return nil, err + } + + log.Debugf("retrieving order %s from the database", paymentDetails.OrderID) + contract, _, _, _, _, _, err := service.datastore.Sales().GetByOrderId(paymentDetails.OrderID) + isVendor := true + if err != nil { + contract, _, _, _, _, _, err = service.datastore.Purchases().GetByOrderId(paymentDetails.OrderID) + if err != nil { + log.Debugf("no matching order was found in the database") + return nil, net.OutOfOrderMessage + } + isVendor = false + } + + if contract.VendorOrderConfirmation != nil && + contract.BuyerOrder.Payment.Method != pb.Order_Payment_MODERATED { + + // the seller has confirmed the direct order, so a simple check of + // the addresses and we are good to proceed + if !ut.AreAddressesEqual(contract.VendorOrderConfirmation.PaymentAddress, txn.ToAddress) { + log.Errorf("mismatched payment address details: orderID: %s, expectedAddr: %s, actualAddr: %s", + paymentDetails.OrderID, contract.VendorOrderConfirmation.PaymentAddress, txn.ToAddress) + return nil, errors.New("mismatched payment addresses") + + } + + } else { + // the seller has not confirmed or this is a moderated purchase, + // so we need to compare the peerID in the vendorListing + // to the node peerID + if isVendor { + if contract.VendorListings[0].VendorID.PeerID != + service.node.IpfsNode.Identity.Pretty() { + log.Errorf("mismatched peerID. wrong node is processing: orderID: %s, contractPeerID: %s", + paymentDetails.OrderID, contract.VendorListings[0].VendorID.PeerID) + return nil, errors.New("mismatched peer id") + } + } else { + if contract.BuyerOrder.BuyerID.PeerID != + service.node.IpfsNode.Identity.Pretty() { + log.Errorf("mismatched peerID. wrong node is processing: orderID: %s, contractPeerID: %s", + paymentDetails.OrderID, contract.BuyerOrder.BuyerID.PeerID) + return nil, errors.New("mismatched peer id") + } + } + + } + + toAddress, err := wal.DecodeAddress(contract.BuyerOrder.Payment.RedeemScript) + if err != nil { + log.Error(err) + } + + tvalue, ok := new(big.Int).SetString(txn.Value, 10) + if ok && tvalue.Cmp(big.NewInt(0)) == 0 { + toAddress, err = wal.DecodeAddress(contract.BuyerOrder.Payment.RedeemScript) + if err != nil { + log.Error(err) + } + } + + outputs := []wallet.TransactionOutput{} + for _, o := range txn.Outputs { + output := wallet.TransactionOutput{ + Address: toAddress, + Value: o.Value, + Index: o.Index, + OrderID: paymentDetails.OrderID, + } + outputs = append(outputs, output) + } + + input := wallet.TransactionInput{} + + txnValue, ok := new(big.Int).SetString(txn.Value, 10) + if !ok { + return nil, errors.New("invalid amount") + } + if paymentDetails.WithInput { + input = wallet.TransactionInput{ + OutpointHash: []byte(txn.Txid[:32]), + OutpointIndex: 1, + LinkedAddress: toAddress, + Value: *txnValue, + OrderID: paymentDetails.OrderID, + } + } + + cb := wallet.TransactionCallback{ + Txid: txn.Txid, + Outputs: outputs, + Inputs: []wallet.TransactionInput{input}, + Height: 0, + Timestamp: time.Now(), + Value: *txnValue, + WatchOnly: false, + } + + log.Debugf("associating tx %s with order %s", txn.Txid, paymentDetails.OrderID) + wal0.AssociateTransactionWithOrder(cb) + + return nil, nil +} + +func (service *OpenBazaarService) handleError(peer peer.ID, pmes *pb.Message, options interface{}) (*pb.Message, error) { + if pmes.Payload == nil { + log.Debugf("received empty ERROR message from peer (%s)", peer.Pretty()) + return nil, ErrEmptyPayload + } errorMessage := new(pb.Error) err := ptypes.UnmarshalAny(pmes.Payload, errorMessage) if err != nil { + log.Debugf("received unmarshalable ERROR message from peer (%s)", peer.Pretty()) return nil, err } + log.Debugf("received ERROR message from peer (%s): %s", peer.Pretty(), errorMessage.ErrorMessage) // Load the order contract, state, _, _, _, _, err := service.datastore.Purchases().GetByOrderId(errorMessage.OrderID) @@ -1490,7 +2110,10 @@ func (service *OpenBazaarService) handleError(peer peer.ID, pmes *pb.Message, op } contract.Errors = []string{errorMessage.ErrorMessage} - service.datastore.Purchases().Put(errorMessage.OrderID, *contract, pb.OrderState_PROCESSING_ERROR, false) + err = service.datastore.Purchases().Put(errorMessage.OrderID, *contract, pb.OrderState_PROCESSING_ERROR, false) + if err != nil { + log.Error(err) + } var thumbnailTiny string var thumbnailSmall string @@ -1506,9 +2129,26 @@ func (service *OpenBazaarService) handleError(peer peer.ID, pmes *pb.Message, op } // Send notification to websocket - n := repo.ProcessingErrorNotification{repo.NewNotificationID(), "processingError", errorMessage.OrderID, repo.Thumbnail{thumbnailTiny, thumbnailSmall}, vendorHandle, vendorID} + n := repo.ProcessingErrorNotification{ + ID: repo.NewNotificationID(), + Type: repo.NotifierTypeProcessingErrorNotification, + OrderId: errorMessage.OrderID, + Thumbnail: repo.Thumbnail{Tiny: thumbnailTiny, Small: thumbnailSmall}, + VendorHandle: vendorHandle, + VendorID: vendorID, + } service.broadcast <- n - service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) - log.Debugf("Received ERROR message from %s:%s", peer.Pretty(), errorMessage.ErrorMessage) + err = service.datastore.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } + log.Debugf("received ERROR message from peer (%s): %s", peer.Pretty(), errorMessage.ErrorMessage) return nil, nil } + +// SendProcessingError produces a ORDER_PROCESSING_FAILURE error message to be sent to peerID regarding +// orderID. This message should cause the peerID to reproduce the missing messages omitted in latestContract +// up-to-and-including the last attemptedMessage +func (service *OpenBazaarService) SendProcessingError(peerID, orderID string, attemptedMessage pb.Message_MessageType, latestContract *pb.RicardianContract) error { + return service.node.SendProcessingError(peerID, orderID, attemptedMessage, latestContract) +} diff --git a/net/service/messagesender.go b/net/service/messagesender.go index 37c2b0a5dd..a88f08f8f9 100644 --- a/net/service/messagesender.go +++ b/net/service/messagesender.go @@ -10,8 +10,8 @@ import ( "sync" "time" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" ) type messageSender struct { @@ -35,14 +35,18 @@ func (service *OpenBazaarService) messageSenderForPeer(ctx context.Context, p pe service.senderlk.Lock() ms, ok := service.sender[p] if ok { + log.Debugf("Found existing message sender for: %s", p.Pretty()) service.senderlk.Unlock() return ms, nil } + + log.Debugf("Creating new message sender for: %s", p.Pretty()) ms = &messageSender{p: p, service: service, requests: make(map[int32]chan *pb.Message, 2)} service.sender[p] = ms service.senderlk.Unlock() if err := ms.ctxPrepOrInvalidate(ctx); err != nil { + log.Debugf("Locking sender for: %s", p.Pretty()) service.senderlk.Lock() defer service.senderlk.Unlock() @@ -60,6 +64,8 @@ func (service *OpenBazaarService) messageSenderForPeer(ctx context.Context, p pe return nil, err } // All ready to go. + + log.Debugf("Stream opened for: %s", p.Pretty()) return ms, nil } @@ -69,7 +75,10 @@ func (service *OpenBazaarService) messageSenderForPeer(ctx context.Context, p pe func (ms *messageSender) invalidate() { ms.invalid = true if ms.s != nil { - ms.s.Reset() + err := ms.s.Reset() + if err != nil { + log.Error(err) + } ms.s = nil } } @@ -102,8 +111,9 @@ func (ms *messageSender) prep() error { if ms.s != nil { return nil } - - nstr, err := ms.service.host.NewStream(ms.service.ctx, ms.p, ipfs.IPFSProtocolAppMainnetOne) + ctx, cancel := context.WithTimeout(ms.service.ctx, 3*time.Second) + defer cancel() + nstr, err := ms.service.host.NewStream(ctx, ms.p, ipfs.IPFSProtocolAppMainnetOne) if err != nil { return err } @@ -132,13 +142,19 @@ func (ms *messageSender) SendMessage(ctx context.Context, pmes *pb.Message) erro err := ms.ctxWriteMsg(ctx, pmes) switch err { case ErrWriteTimeout: - ms.s.Reset() + err = ms.s.Reset() + if err != nil { + log.Error(err) + } ms.s = nil return err case nil: break default: - ms.s.Reset() + err = ms.s.Reset() + if err != nil { + log.Error(err) + } ms.s = nil if retry { @@ -180,13 +196,19 @@ func (ms *messageSender) SendRequest(ctx context.Context, pmes *pb.Message) (*pb err := ms.ctxWriteMsg(ctx, pmes) switch err { case ErrWriteTimeout: - ms.s.Reset() + err = ms.s.Reset() + if err != nil { + log.Error(err) + } ms.s = nil return nil, err case nil: break default: - ms.s.Reset() + err = ms.s.Reset() + if err != nil { + log.Error(err) + } ms.s = nil if retry { @@ -199,7 +221,10 @@ func (ms *messageSender) SendRequest(ctx context.Context, pmes *pb.Message) (*pb mes, err := ms.ctxReadMsg(ctx, returnChan) if err != nil { - ms.s.Reset() + err = ms.s.Reset() + if err != nil { + log.Error(err) + } ms.s = nil return nil, err } diff --git a/net/service/service.go b/net/service/service.go index 2bda57cb83..d765521cc3 100644 --- a/net/service/service.go +++ b/net/service/service.go @@ -17,10 +17,10 @@ import ( ctxio "github.com/jbenet/go-context/io" "github.com/op/go-logging" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) var log = logging.MustGetLogger("service") @@ -57,19 +57,18 @@ func (service *OpenBazaarService) WaitForReady() { <-service.node.DHT.BootstrapChan } -func (service *OpenBazaarService) DisconnectFromPeer(p peer.ID) error { +func (service *OpenBazaarService) DisconnectFromPeer(p peer.ID) { log.Debugf("Disconnecting from %s", p.Pretty()) service.senderlk.Lock() defer service.senderlk.Unlock() ms, ok := service.sender[p] if !ok { - return nil + return } if ms != nil && ms.s != nil { ms.s.Close() } delete(service.sender, p) - return nil } func (service *OpenBazaarService) HandleNewStream(s inet.Stream) { @@ -82,14 +81,17 @@ func (service *OpenBazaarService) handleNewMessage(s inet.Stream) { r := ggio.NewDelimitedReader(cr, inet.MessageSizeMax) mPeer := s.Conn().RemotePeer() + log.Debugf("Received new message from: %s", mPeer.Pretty()) + // Check if banned if service.node.BanManager.IsBanned(mPeer) { + log.Debugf("Message from banned peer dropped: %s", mPeer.Pretty()) return } ms, err := service.messageSenderForPeer(service.ctx, mPeer) if err != nil { - log.Error("Error getting message sender") + log.Error("Error getting message sender and opening stream to peer") return } @@ -97,24 +99,31 @@ func (service *OpenBazaarService) handleNewMessage(s inet.Stream) { select { // end loop on context close case <-service.ctx.Done(): + log.Debugf("Service context closed for: %s", mPeer.Pretty()) return default: } // Receive msg pmes := new(pb.Message) if err := r.ReadMsg(pmes); err != nil { - s.Reset() - if err == io.EOF { - log.Debugf("Disconnected from peer %s", mPeer.Pretty()) + err = s.Reset() + if err != nil { + if err == io.EOF { + log.Debugf("Disconnected from peer %s", mPeer.Pretty()) + } else { + log.Errorf("Error when reading message from %s: %s", mPeer.Pretty(), err.Error()) + } } return } if pmes.IsResponse { + log.Debugf("received response message from %s: %d", mPeer.Pretty(), pmes.RequestId) ms.requestlk.Lock() ch, ok := ms.requests[pmes.RequestId] if ok { // this is a request response + log.Debugf("found matching request for: %d", pmes.RequestId) select { case ch <- pmes: // message returned to requester @@ -128,14 +137,20 @@ func (service *OpenBazaarService) handleNewMessage(s inet.Stream) { log.Debug("received response message with unknown request id: requesting function may have timed out") } ms.requestlk.Unlock() - s.Reset() + err = s.Reset() + if err != nil { + log.Error(err) + } return } // Get handler for this msg type handler := service.HandlerForMsgType(pmes.MessageType) if handler == nil { - s.Reset() + err = s.Reset() + if err != nil { + log.Error(err) + } log.Debug("Got back nil handler from handlerForMsgType") return } @@ -143,7 +158,7 @@ func (service *OpenBazaarService) handleNewMessage(s inet.Stream) { // Dispatch handler rpmes, err := handler(mPeer, pmes, nil) if err != nil { - log.Debugf("%s handle message error: %s", pmes.MessageType.String(), err) + log.Debugf("%s handle message error from %s: %s", pmes.MessageType.String(), mPeer.Pretty(), err) } // If nil response, return it before serializing @@ -156,8 +171,12 @@ func (service *OpenBazaarService) handleNewMessage(s inet.Stream) { rpmes.IsResponse = true // send out response msg + log.Debugf("sending response message to: %s", mPeer.Pretty()) if err := ms.SendMessage(service.ctx, rpmes); err != nil { - s.Reset() + err = s.Reset() + if err != nil { + log.Error(err) + } log.Debugf("send response error: %s", err) return } diff --git a/package.json b/package.json index 42b40f4f41..6dbad34b4b 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { - "name": "openbazaar-go", + "name": "marketplace-go", "author": "Phore Blockchain Company", - "version": "0.13.4", + "version": "0.14.3", "language": "english", "license": "", "bugs": { - "url": "https://github.com/phoreproject/openbazaar-go/issues/new" + "url": "https://github.com/phoreproject/pm-go/issues/new" }, "gxVersion": "0.11.0" } + diff --git a/pb/api.pb.go b/pb/api.pb.go index 01eeb03bec..f968000ce2 100644 --- a/pb/api.pb.go +++ b/pb/api.pb.go @@ -276,10 +276,12 @@ func (m *CaseRespApi) GetResolution() *DisputeResolution { type TransactionRecord struct { Txid string `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` - Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` + Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` // Deprecated: Do not use. Confirmations uint32 `protobuf:"varint,3,opt,name=confirmations,proto3" json:"confirmations,omitempty"` Height uint32 `protobuf:"varint,4,opt,name=height,proto3" json:"height,omitempty"` Timestamp *timestamp.Timestamp `protobuf:"bytes,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Currency *CurrencyDefinition `protobuf:"bytes,6,opt,name=currency,proto3" json:"currency,omitempty"` + BigValue string `protobuf:"bytes,7,opt,name=bigValue,proto3" json:"bigValue,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -317,6 +319,7 @@ func (m *TransactionRecord) GetTxid() string { return "" } +// Deprecated: Do not use. func (m *TransactionRecord) GetValue() int64 { if m != nil { return m.Value @@ -345,6 +348,20 @@ func (m *TransactionRecord) GetTimestamp() *timestamp.Timestamp { return nil } +func (m *TransactionRecord) GetCurrency() *CurrencyDefinition { + if m != nil { + return m.Currency + } + return nil +} + +func (m *TransactionRecord) GetBigValue() string { + if m != nil { + return m.BigValue + } + return "" +} + type PeerAndProfile struct { PeerId string `protobuf:"bytes,1,opt,name=peerId,proto3" json:"peerId,omitempty"` Profile *Profile `protobuf:"bytes,2,opt,name=profile,proto3" json:"profile,omitempty"` @@ -512,48 +529,52 @@ func init() { proto.RegisterType((*RatingWithID)(nil), "RatingWithID") } -func init() { proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) } +func init() { + proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) +} var fileDescriptor_00212fb1f9d3bf1c = []byte{ - // 625 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xcd, 0x6e, 0x13, 0x31, - 0x10, 0x56, 0xfe, 0x93, 0x49, 0x13, 0x84, 0x55, 0xa1, 0x55, 0x24, 0x68, 0x58, 0x71, 0xc8, 0x69, - 0x8b, 0xca, 0xa5, 0xe2, 0x56, 0x52, 0x90, 0x2a, 0x01, 0xad, 0x4c, 0x05, 0x12, 0x9c, 0x9c, 0xf5, - 0x24, 0xb1, 0x94, 0xd8, 0x2b, 0xdb, 0x5b, 0xd1, 0x97, 0xe1, 0x2d, 0x78, 0x20, 0xde, 0x04, 0xd9, - 0xeb, 0x4d, 0x13, 0xd2, 0x6d, 0xc5, 0xcd, 0x33, 0xf3, 0xcd, 0x37, 0xb3, 0x33, 0xdf, 0x2c, 0xf4, - 0x58, 0x26, 0x92, 0x4c, 0x2b, 0xab, 0x46, 0x4f, 0x52, 0x25, 0xad, 0x66, 0xa9, 0x35, 0xc1, 0x71, - 0xa0, 0x34, 0x47, 0x5d, 0x5a, 0x83, 0x4c, 0xab, 0xb9, 0x58, 0x61, 0x30, 0x8f, 0x16, 0x4a, 0x2d, - 0x56, 0x78, 0xec, 0xad, 0x59, 0x3e, 0x3f, 0xb6, 0x62, 0x8d, 0xc6, 0xb2, 0x75, 0x56, 0x00, 0xe2, - 0xd7, 0xd0, 0x9e, 0xaa, 0x3c, 0x53, 0x92, 0x10, 0x68, 0x2e, 0x99, 0x59, 0x46, 0xb5, 0x71, 0x6d, - 0xd2, 0xa3, 0xfe, 0xed, 0x7c, 0xa9, 0xe2, 0x18, 0xd5, 0x0b, 0x9f, 0x7b, 0xc7, 0x7f, 0xea, 0x70, - 0x70, 0xe9, 0x4a, 0x52, 0x34, 0xd9, 0x59, 0x26, 0x48, 0x02, 0xdd, 0xb2, 0x27, 0x9f, 0xdc, 0x3f, - 0x21, 0x09, 0x15, 0x29, 0xd3, 0x5c, 0x30, 0x39, 0x0d, 0x11, 0xba, 0xc1, 0x90, 0x97, 0xd0, 0x32, - 0x96, 0xd9, 0x82, 0x75, 0x78, 0xd2, 0x4f, 0x3c, 0xdb, 0x17, 0xe7, 0xa2, 0x45, 0xc4, 0xd5, 0xd5, - 0xc8, 0x78, 0xd4, 0x18, 0xd7, 0x26, 0x5d, 0xea, 0xdf, 0xe4, 0x19, 0xb4, 0xe7, 0xb9, 0xe4, 0xc8, - 0xa3, 0xa6, 0xf7, 0x06, 0x8b, 0x24, 0x40, 0x72, 0xe9, 0x10, 0xd3, 0x25, 0xb3, 0x9f, 0xd0, 0x18, - 0xb6, 0x40, 0x13, 0xb5, 0xc6, 0xb5, 0x49, 0x93, 0xde, 0x13, 0x21, 0x14, 0x46, 0x19, 0xbb, 0x5d, - 0xa3, 0xb4, 0x67, 0x9c, 0x6b, 0x34, 0xe6, 0x5a, 0x33, 0x69, 0x58, 0x6a, 0x85, 0x92, 0x26, 0x6a, - 0x8f, 0x1b, 0xfe, 0x03, 0xb6, 0x9c, 0x14, 0x53, 0xa5, 0x39, 0x7d, 0x20, 0x8b, 0x7c, 0x86, 0x48, - 0xa3, 0xeb, 0x67, 0x3f, 0x18, 0x75, 0xc2, 0x48, 0xf6, 0x19, 0x2b, 0x73, 0xe2, 0x5f, 0x4d, 0xe8, - 0x4f, 0x99, 0xc1, 0x72, 0xc4, 0xa7, 0xd0, 0xdb, 0x2c, 0x2e, 0xcc, 0x78, 0x94, 0x14, 0xab, 0x4d, - 0xca, 0xd5, 0x26, 0xd7, 0x25, 0x82, 0xde, 0x81, 0xc9, 0x29, 0x0c, 0x66, 0xf9, 0x2d, 0xea, 0x72, - 0x0f, 0x7e, 0xe8, 0xf7, 0x6f, 0x68, 0x17, 0x48, 0xde, 0xc2, 0xf0, 0x06, 0x25, 0x57, 0x77, 0xa9, - 0x8d, 0xca, 0xd4, 0x7f, 0x90, 0xe4, 0x1c, 0x9e, 0xef, 0x90, 0x7d, 0x65, 0x2b, 0xc1, 0x99, 0xfb, - 0xb4, 0xf7, 0x5a, 0x2b, 0x6d, 0xa2, 0xe6, 0xb8, 0x31, 0xe9, 0xd1, 0x87, 0x41, 0xe4, 0x03, 0xbc, - 0xd8, 0xe5, 0xdd, 0xa3, 0x69, 0x79, 0x9a, 0x47, 0x50, 0x77, 0x82, 0x6b, 0x3f, 0x2a, 0xb8, 0xce, - 0x96, 0xe0, 0xc6, 0xd0, 0xf7, 0xfd, 0x5d, 0x66, 0x28, 0x91, 0x47, 0x5d, 0x1f, 0xda, 0x76, 0x91, - 0x43, 0x68, 0xa5, 0x2b, 0x26, 0xd6, 0x51, 0xcf, 0xdf, 0x47, 0x61, 0x54, 0x08, 0x12, 0x2a, 0x05, - 0x79, 0x02, 0xa0, 0xd1, 0xa8, 0x55, 0xee, 0xe5, 0xd2, 0x0f, 0x43, 0x3e, 0x17, 0x26, 0xcb, 0xad, - 0x53, 0x40, 0x88, 0xd0, 0x2d, 0x54, 0xfc, 0xbb, 0x06, 0x4f, 0xf7, 0x04, 0xe5, 0xbe, 0xc2, 0xfe, - 0x14, 0xbc, 0x3c, 0x61, 0xf7, 0x76, 0x3d, 0xde, 0xb0, 0x55, 0x5e, 0x5c, 0x5b, 0x83, 0x16, 0x06, - 0x79, 0x05, 0x83, 0x54, 0xc9, 0xb9, 0xd0, 0x6b, 0x56, 0xe8, 0xde, 0xed, 0x76, 0x40, 0x77, 0x9d, - 0xee, 0xe4, 0x96, 0x28, 0x16, 0x4b, 0xeb, 0x4f, 0x6e, 0x40, 0x83, 0xb5, 0x2b, 0xc7, 0xd6, 0x7f, - 0xc8, 0x31, 0xfe, 0x08, 0xc3, 0x2b, 0x44, 0x7d, 0x26, 0xf9, 0x55, 0xf1, 0x9f, 0x72, 0x35, 0x32, - 0x44, 0x7d, 0x51, 0x76, 0x1d, 0x2c, 0x12, 0x43, 0x27, 0xfc, 0xca, 0x82, 0x64, 0xbb, 0x49, 0x48, - 0xa1, 0x65, 0x20, 0x9e, 0xc1, 0xe1, 0x2e, 0xdb, 0x37, 0x61, 0x97, 0x17, 0xe7, 0x64, 0x08, 0xf5, - 0xcd, 0x14, 0xea, 0x82, 0x6f, 0xd5, 0xa8, 0x57, 0xd5, 0x68, 0x54, 0xd5, 0xf8, 0x01, 0x07, 0x94, - 0x59, 0x21, 0x17, 0x15, 0xdc, 0x23, 0xe8, 0x6a, 0x1f, 0xdf, 0xb0, 0x6f, 0x6c, 0x72, 0x04, 0xed, - 0xe2, 0x1d, 0xe8, 0x3b, 0x49, 0x41, 0x45, 0x83, 0xfb, 0x5d, 0xf3, 0x7b, 0x3d, 0x9b, 0xcd, 0xda, - 0x7e, 0x66, 0x6f, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x3d, 0x96, 0xc3, 0x9b, 0xe6, 0x05, 0x00, - 0x00, + // 670 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xdd, 0x6a, 0x1b, 0x3b, + 0x10, 0xc6, 0xeb, 0xbf, 0xf5, 0x38, 0xf6, 0xe1, 0xe8, 0x84, 0xc3, 0x62, 0x38, 0x27, 0xee, 0xd2, + 0x0b, 0x5f, 0x6d, 0x8a, 0x7b, 0x13, 0x7a, 0x97, 0xd8, 0x2d, 0x04, 0xda, 0x26, 0xa8, 0x21, 0x85, + 0xf6, 0x4a, 0x5e, 0xc9, 0xb6, 0xc0, 0x96, 0x16, 0x49, 0x1b, 0x9a, 0x17, 0xe8, 0x63, 0xf4, 0xdd, + 0xfa, 0x26, 0x45, 0x5a, 0xed, 0xc6, 0xae, 0xb3, 0x09, 0xbd, 0xd3, 0xcc, 0x7c, 0xf3, 0x49, 0x33, + 0xf3, 0x8d, 0xa0, 0x47, 0x32, 0x9e, 0x64, 0x4a, 0x1a, 0x39, 0xfa, 0x2b, 0x95, 0xc2, 0x28, 0x92, + 0x1a, 0xed, 0x1d, 0x47, 0x52, 0x51, 0xa6, 0x4a, 0x6b, 0x90, 0x29, 0xb9, 0xe4, 0x1b, 0xe6, 0xcd, + 0x93, 0x95, 0x94, 0xab, 0x0d, 0x3b, 0x75, 0xd6, 0x22, 0x5f, 0x9e, 0x1a, 0xbe, 0x65, 0xda, 0x90, + 0x6d, 0x56, 0x00, 0xe2, 0x57, 0xd0, 0x99, 0xc9, 0x3c, 0x93, 0x02, 0x21, 0x68, 0xad, 0x89, 0x5e, + 0x47, 0x8d, 0x71, 0x63, 0xd2, 0xc3, 0xee, 0x6c, 0x7d, 0xa9, 0xa4, 0x2c, 0x0a, 0x0a, 0x9f, 0x3d, + 0xc7, 0x3f, 0x03, 0x38, 0xba, 0xb2, 0x57, 0x62, 0xa6, 0xb3, 0xf3, 0x8c, 0xa3, 0x04, 0xc2, 0xf2, + 0x4d, 0x2e, 0xb9, 0x3f, 0x45, 0x09, 0xe6, 0x29, 0x51, 0x94, 0x13, 0x31, 0xf3, 0x11, 0x5c, 0x61, + 0xd0, 0x0b, 0x68, 0x6b, 0x43, 0x4c, 0xc1, 0x3a, 0x9c, 0xf6, 0x13, 0xc7, 0xf6, 0xc9, 0xba, 0x70, + 0x11, 0xb1, 0xf7, 0x2a, 0x46, 0x68, 0xd4, 0x1c, 0x37, 0x26, 0x21, 0x76, 0x67, 0xf4, 0x2f, 0x74, + 0x96, 0xb9, 0xa0, 0x8c, 0x46, 0x2d, 0xe7, 0xf5, 0x16, 0x4a, 0x00, 0xe5, 0xc2, 0x22, 0x66, 0x6b, + 0x62, 0x3e, 0x30, 0xad, 0xc9, 0x8a, 0xe9, 0xa8, 0x3d, 0x6e, 0x4c, 0x5a, 0xf8, 0x91, 0x08, 0xc2, + 0x30, 0xca, 0xc8, 0xfd, 0x96, 0x09, 0x73, 0x4e, 0xa9, 0x62, 0x5a, 0xdf, 0x28, 0x22, 0x34, 0x49, + 0x0d, 0x97, 0x42, 0x47, 0x9d, 0x71, 0xd3, 0x15, 0xb0, 0xe3, 0xc4, 0x2c, 0x95, 0x8a, 0xe2, 0x27, + 0xb2, 0xd0, 0x47, 0x88, 0x14, 0xb3, 0xef, 0x39, 0x0c, 0x46, 0x5d, 0xdf, 0x92, 0x43, 0xc6, 0xda, + 0x9c, 0xf8, 0x47, 0x0b, 0xfa, 0x33, 0xa2, 0x59, 0xd9, 0xe2, 0x33, 0xe8, 0x55, 0x83, 0xf3, 0x3d, + 0x1e, 0x25, 0xc5, 0x68, 0x93, 0x72, 0xb4, 0xc9, 0x4d, 0x89, 0xc0, 0x0f, 0x60, 0x74, 0x06, 0x83, + 0x45, 0x7e, 0xcf, 0x54, 0x39, 0x07, 0xd7, 0xf4, 0xc7, 0x27, 0xb4, 0x0f, 0x44, 0x6f, 0x60, 0x78, + 0xc7, 0x04, 0x95, 0x0f, 0xa9, 0xcd, 0xda, 0xd4, 0xdf, 0x90, 0x68, 0x0e, 0xff, 0xed, 0x91, 0xdd, + 0x92, 0x0d, 0xa7, 0xc4, 0x96, 0xf6, 0x56, 0x29, 0xa9, 0x74, 0xd4, 0x1a, 0x37, 0x27, 0x3d, 0xfc, + 0x34, 0x08, 0xbd, 0x83, 0xff, 0xf7, 0x79, 0x0f, 0x68, 0xda, 0x8e, 0xe6, 0x19, 0xd4, 0x83, 0xe0, + 0x3a, 0xcf, 0x0a, 0xae, 0xbb, 0x23, 0xb8, 0x31, 0xf4, 0xdd, 0xfb, 0xae, 0x32, 0x26, 0x18, 0x8d, + 0x42, 0x17, 0xda, 0x75, 0xa1, 0x63, 0x68, 0xa7, 0x1b, 0xc2, 0xb7, 0x51, 0xcf, 0xed, 0x47, 0x61, + 0xd4, 0x08, 0x12, 0x6a, 0x05, 0x39, 0x05, 0x50, 0x4c, 0xcb, 0x4d, 0xee, 0xe4, 0xd2, 0xf7, 0x4d, + 0x9e, 0x73, 0x9d, 0xe5, 0xc6, 0x2a, 0xc0, 0x47, 0xf0, 0x0e, 0x2a, 0xfe, 0x1e, 0xc0, 0xdf, 0x07, + 0x82, 0xb2, 0x55, 0x98, 0x6f, 0x9c, 0x96, 0x2b, 0x6c, 0xcf, 0x28, 0x82, 0xf6, 0x1d, 0xd9, 0xe4, + 0xc5, 0xb6, 0x35, 0x2f, 0x82, 0xa8, 0x81, 0x0b, 0x07, 0x7a, 0x09, 0x83, 0x54, 0x8a, 0x25, 0x57, + 0x5b, 0x52, 0x68, 0xdf, 0xce, 0x77, 0x80, 0xf7, 0x9d, 0x76, 0xed, 0xd6, 0x8c, 0xaf, 0xd6, 0xc6, + 0xad, 0xdd, 0x00, 0x7b, 0x6b, 0x5f, 0x92, 0xed, 0x3f, 0x91, 0xe4, 0x29, 0x84, 0x69, 0xae, 0x14, + 0x13, 0xe9, 0xbd, 0x9b, 0x48, 0x7f, 0xfa, 0x4f, 0x32, 0xf3, 0x8e, 0x39, 0x5b, 0x72, 0xc1, 0x5d, + 0x49, 0x15, 0x08, 0x8d, 0x20, 0x5c, 0xf0, 0xd5, 0xad, 0xab, 0xa2, 0xeb, 0x4a, 0xab, 0xec, 0xf8, + 0x3d, 0x0c, 0xaf, 0x19, 0x53, 0xe7, 0x82, 0x5e, 0x17, 0x1f, 0x9f, 0x7d, 0x70, 0xc6, 0x98, 0xba, + 0x2c, 0xdb, 0xe0, 0x2d, 0x14, 0x43, 0xd7, 0xff, 0x8d, 0x7e, 0x07, 0xc2, 0xc4, 0xa7, 0xe0, 0x32, + 0x10, 0x2f, 0xe0, 0x78, 0x9f, 0xed, 0x33, 0x37, 0xeb, 0xcb, 0x39, 0x1a, 0x42, 0x50, 0xb5, 0x35, + 0xe0, 0x74, 0xe7, 0x8e, 0xa0, 0xee, 0x8e, 0x66, 0xdd, 0x1d, 0x5f, 0xe1, 0x08, 0x13, 0xc3, 0xc5, + 0xaa, 0x86, 0x7b, 0x04, 0xa1, 0x72, 0xf1, 0x8a, 0xbd, 0xb2, 0xd1, 0x09, 0x74, 0x8a, 0xb3, 0xa7, + 0xef, 0x26, 0x05, 0x15, 0xf6, 0xee, 0x8b, 0xd6, 0x97, 0x20, 0x5b, 0x2c, 0x3a, 0x6e, 0x00, 0xaf, + 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x26, 0xa7, 0xc9, 0x5a, 0x37, 0x06, 0x00, 0x00, } diff --git a/pb/contracts.pb.go b/pb/contracts.pb.go index ffb44699f5..333ae12290 100644 --- a/pb/contracts.pb.go +++ b/pb/contracts.pb.go @@ -52,7 +52,7 @@ func (x Listing_Metadata_ContractType) String() string { } func (Listing_Metadata_ContractType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 0, 0} + return fileDescriptor_b6d125f880f9ca35, []int{2, 0, 0} } type Listing_Metadata_Format int32 @@ -77,7 +77,7 @@ func (x Listing_Metadata_Format) String() string { } func (Listing_Metadata_Format) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 0, 1} + return fileDescriptor_b6d125f880f9ca35, []int{2, 0, 1} } type Listing_ShippingOption_ShippingType int32 @@ -102,7 +102,7 @@ func (x Listing_ShippingOption_ShippingType) String() string { } func (Listing_ShippingOption_ShippingType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 2, 0} + return fileDescriptor_b6d125f880f9ca35, []int{2, 2, 0} } type Order_Payment_Method int32 @@ -130,7 +130,7 @@ func (x Order_Payment_Method) String() string { } func (Order_Payment_Method) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{2, 2, 0} + return fileDescriptor_b6d125f880f9ca35, []int{3, 2, 0} } type Signature_Section int32 @@ -173,7 +173,7 @@ func (x Signature_Section) String() string { } func (Signature_Section) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{17, 0} + return fileDescriptor_b6d125f880f9ca35, []int{19, 0} } type RicardianContract struct { @@ -295,6 +295,53 @@ func (m *RicardianContract) GetErrors() []string { return nil } +type CurrencyDefinition struct { + Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` + Divisibility uint32 `protobuf:"varint,2,opt,name=divisibility,proto3" json:"divisibility,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CurrencyDefinition) Reset() { *m = CurrencyDefinition{} } +func (m *CurrencyDefinition) String() string { return proto.CompactTextString(m) } +func (*CurrencyDefinition) ProtoMessage() {} +func (*CurrencyDefinition) Descriptor() ([]byte, []int) { + return fileDescriptor_b6d125f880f9ca35, []int{1} +} + +func (m *CurrencyDefinition) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CurrencyDefinition.Unmarshal(m, b) +} +func (m *CurrencyDefinition) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CurrencyDefinition.Marshal(b, m, deterministic) +} +func (m *CurrencyDefinition) XXX_Merge(src proto.Message) { + xxx_messageInfo_CurrencyDefinition.Merge(m, src) +} +func (m *CurrencyDefinition) XXX_Size() int { + return xxx_messageInfo_CurrencyDefinition.Size(m) +} +func (m *CurrencyDefinition) XXX_DiscardUnknown() { + xxx_messageInfo_CurrencyDefinition.DiscardUnknown(m) +} + +var xxx_messageInfo_CurrencyDefinition proto.InternalMessageInfo + +func (m *CurrencyDefinition) GetCode() string { + if m != nil { + return m.Code + } + return "" +} + +func (m *CurrencyDefinition) GetDivisibility() uint32 { + if m != nil { + return m.Divisibility + } + return 0 +} + type Listing struct { Slug string `protobuf:"bytes,1,opt,name=slug,proto3" json:"slug,omitempty"` VendorID *ID `protobuf:"bytes,2,opt,name=vendorID,proto3" json:"vendorID,omitempty"` @@ -316,7 +363,7 @@ func (m *Listing) Reset() { *m = Listing{} } func (m *Listing) String() string { return proto.CompactTextString(m) } func (*Listing) ProtoMessage() {} func (*Listing) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1} + return fileDescriptor_b6d125f880f9ca35, []int{2} } func (m *Listing) XXX_Unmarshal(b []byte) error { @@ -407,35 +454,30 @@ func (m *Listing) GetRefundPolicy() string { return "" } -func (m *Listing) GetTestnet() bool { - if m != nil { - return m.Testnet - } - return false -} - type Listing_Metadata struct { - Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` - ContractType Listing_Metadata_ContractType `protobuf:"varint,2,opt,name=contractType,proto3,enum=Listing_Metadata_ContractType" json:"contractType,omitempty"` - Format Listing_Metadata_Format `protobuf:"varint,3,opt,name=format,proto3,enum=Listing_Metadata_Format" json:"format,omitempty"` - Expiry *timestamp.Timestamp `protobuf:"bytes,4,opt,name=expiry,proto3" json:"expiry,omitempty"` - AcceptedCurrencies []string `protobuf:"bytes,5,rep,name=acceptedCurrencies,proto3" json:"acceptedCurrencies,omitempty"` - PricingCurrency string `protobuf:"bytes,6,opt,name=pricingCurrency,proto3" json:"pricingCurrency,omitempty"` - Language string `protobuf:"bytes,7,opt,name=language,proto3" json:"language,omitempty"` - EscrowTimeoutHours uint32 `protobuf:"varint,8,opt,name=escrowTimeoutHours,proto3" json:"escrowTimeoutHours,omitempty"` - CoinType string `protobuf:"bytes,9,opt,name=coinType,proto3" json:"coinType,omitempty"` - CoinDivisibility uint32 `protobuf:"varint,10,opt,name=coinDivisibility,proto3" json:"coinDivisibility,omitempty"` - PriceModifier float32 `protobuf:"fixed32,11,opt,name=priceModifier,proto3" json:"priceModifier,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` + ContractType Listing_Metadata_ContractType `protobuf:"varint,2,opt,name=contractType,proto3,enum=Listing_Metadata_ContractType" json:"contractType,omitempty"` + Format Listing_Metadata_Format `protobuf:"varint,3,opt,name=format,proto3,enum=Listing_Metadata_Format" json:"format,omitempty"` + Expiry *timestamp.Timestamp `protobuf:"bytes,4,opt,name=expiry,proto3" json:"expiry,omitempty"` + AcceptedCurrencies []string `protobuf:"bytes,5,rep,name=acceptedCurrencies,proto3" json:"acceptedCurrencies,omitempty"` + PricingCurrency string `protobuf:"bytes,6,opt,name=pricingCurrency,proto3" json:"pricingCurrency,omitempty"` // Deprecated: Do not use. + Language string `protobuf:"bytes,7,opt,name=language,proto3" json:"language,omitempty"` + EscrowTimeoutHours uint32 `protobuf:"varint,8,opt,name=escrowTimeoutHours,proto3" json:"escrowTimeoutHours,omitempty"` + CryptoCurrencyCode string `protobuf:"bytes,9,opt,name=cryptoCurrencyCode,json=coinType,proto3" json:"cryptoCurrencyCode,omitempty"` + CryptoDivisibility uint32 `protobuf:"varint,10,opt,name=cryptoDivisibility,json=coinDivisibility,proto3" json:"cryptoDivisibility,omitempty"` + PriceModifier float32 `protobuf:"fixed32,11,opt,name=priceModifier,proto3" json:"priceModifier,omitempty"` // Deprecated: Do not use. + ShippingFromCountryCode CountryCode `protobuf:"varint,12,opt,name=shippingFromCountryCode,proto3,enum=CountryCode" json:"shippingFromCountryCode,omitempty"` + ShippingFromPostalCode string `protobuf:"bytes,13,opt,name=shippingFromPostalCode,proto3" json:"shippingFromPostalCode,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Listing_Metadata) Reset() { *m = Listing_Metadata{} } func (m *Listing_Metadata) String() string { return proto.CompactTextString(m) } func (*Listing_Metadata) ProtoMessage() {} func (*Listing_Metadata) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 0} + return fileDescriptor_b6d125f880f9ca35, []int{2, 0} } func (m *Listing_Metadata) XXX_Unmarshal(b []byte) error { @@ -491,6 +533,7 @@ func (m *Listing_Metadata) GetAcceptedCurrencies() []string { return nil } +// Deprecated: Do not use. func (m *Listing_Metadata) GetPricingCurrency() string { if m != nil { return m.PricingCurrency @@ -512,20 +555,21 @@ func (m *Listing_Metadata) GetEscrowTimeoutHours() uint32 { return 0 } -func (m *Listing_Metadata) GetCoinType() string { +func (m *Listing_Metadata) GetCryptoCurrencyCode() string { if m != nil { - return m.CoinType + return m.CryptoCurrencyCode } return "" } -func (m *Listing_Metadata) GetCoinDivisibility() uint32 { +func (m *Listing_Metadata) GetCryptoDivisibility() uint32 { if m != nil { - return m.CoinDivisibility + return m.CryptoDivisibility } return 0 } +// Deprecated: Do not use. func (m *Listing_Metadata) GetPriceModifier() float32 { if m != nil { return m.PriceModifier @@ -533,11 +577,25 @@ func (m *Listing_Metadata) GetPriceModifier() float32 { return 0 } +func (m *Listing_Metadata) GetShippingFromCountryCode() CountryCode { + if m != nil { + return m.ShippingFromCountryCode + } + return CountryCode_NA +} + +func (m *Listing_Metadata) GetShippingFromPostalCode() string { + if m != nil { + return m.ShippingFromPostalCode + } + return "" +} + type Listing_Item struct { Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` ProcessingTime string `protobuf:"bytes,3,opt,name=processingTime,proto3" json:"processingTime,omitempty"` - Price uint64 `protobuf:"varint,4,opt,name=price,proto3" json:"price,omitempty"` + Price uint64 `protobuf:"varint,4,opt,name=price,proto3" json:"price,omitempty"` // Deprecated: Do not use. Nsfw bool `protobuf:"varint,5,opt,name=nsfw,proto3" json:"nsfw,omitempty"` Tags []string `protobuf:"bytes,6,rep,name=tags,proto3" json:"tags,omitempty"` Images []*Listing_Item_Image `protobuf:"bytes,7,rep,name=images,proto3" json:"images,omitempty"` @@ -546,6 +604,9 @@ type Listing_Item struct { Condition string `protobuf:"bytes,10,opt,name=condition,proto3" json:"condition,omitempty"` Options []*Listing_Item_Option `protobuf:"bytes,11,rep,name=options,proto3" json:"options,omitempty"` Skus []*Listing_Item_Sku `protobuf:"bytes,12,rep,name=skus,proto3" json:"skus,omitempty"` + PriceModifier float32 `protobuf:"fixed32,13,opt,name=priceModifier,proto3" json:"priceModifier,omitempty"` + BigPrice string `protobuf:"bytes,14,opt,name=bigPrice,proto3" json:"bigPrice,omitempty"` + PriceCurrency *CurrencyDefinition `protobuf:"bytes,15,opt,name=priceCurrency,proto3" json:"priceCurrency,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -555,7 +616,7 @@ func (m *Listing_Item) Reset() { *m = Listing_Item{} } func (m *Listing_Item) String() string { return proto.CompactTextString(m) } func (*Listing_Item) ProtoMessage() {} func (*Listing_Item) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 1} + return fileDescriptor_b6d125f880f9ca35, []int{2, 1} } func (m *Listing_Item) XXX_Unmarshal(b []byte) error { @@ -597,6 +658,7 @@ func (m *Listing_Item) GetProcessingTime() string { return "" } +// Deprecated: Do not use. func (m *Listing_Item) GetPrice() uint64 { if m != nil { return m.Price @@ -660,6 +722,27 @@ func (m *Listing_Item) GetSkus() []*Listing_Item_Sku { return nil } +func (m *Listing_Item) GetPriceModifier() float32 { + if m != nil { + return m.PriceModifier + } + return 0 +} + +func (m *Listing_Item) GetBigPrice() string { + if m != nil { + return m.BigPrice + } + return "" +} + +func (m *Listing_Item) GetPriceCurrency() *CurrencyDefinition { + if m != nil { + return m.PriceCurrency + } + return nil +} + type Listing_Item_Option struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` @@ -673,7 +756,7 @@ func (m *Listing_Item_Option) Reset() { *m = Listing_Item_Option{} } func (m *Listing_Item_Option) String() string { return proto.CompactTextString(m) } func (*Listing_Item_Option) ProtoMessage() {} func (*Listing_Item_Option) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 1, 0} + return fileDescriptor_b6d125f880f9ca35, []int{2, 1, 0} } func (m *Listing_Item_Option) XXX_Unmarshal(b []byte) error { @@ -727,7 +810,7 @@ func (m *Listing_Item_Option_Variant) Reset() { *m = Listing_Item_Option func (m *Listing_Item_Option_Variant) String() string { return proto.CompactTextString(m) } func (*Listing_Item_Option_Variant) ProtoMessage() {} func (*Listing_Item_Option_Variant) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 1, 0, 0} + return fileDescriptor_b6d125f880f9ca35, []int{2, 1, 0, 0} } func (m *Listing_Item_Option_Variant) XXX_Unmarshal(b []byte) error { @@ -765,8 +848,10 @@ func (m *Listing_Item_Option_Variant) GetImage() *Listing_Item_Image { type Listing_Item_Sku struct { VariantCombo []uint32 `protobuf:"varint,1,rep,packed,name=variantCombo,proto3" json:"variantCombo,omitempty"` ProductID string `protobuf:"bytes,2,opt,name=productID,proto3" json:"productID,omitempty"` - Surcharge int64 `protobuf:"varint,3,opt,name=surcharge,proto3" json:"surcharge,omitempty"` - Quantity int64 `protobuf:"varint,4,opt,name=quantity,proto3" json:"quantity,omitempty"` + Surcharge int64 `protobuf:"varint,3,opt,name=surcharge,proto3" json:"surcharge,omitempty"` // Deprecated: Do not use. + Quantity int64 `protobuf:"varint,4,opt,name=quantity,proto3" json:"quantity,omitempty"` // Deprecated: Do not use. + BigSurcharge string `protobuf:"bytes,5,opt,name=bigSurcharge,proto3" json:"bigSurcharge,omitempty"` + BigQuantity string `protobuf:"bytes,6,opt,name=bigQuantity,proto3" json:"bigQuantity,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -776,7 +861,7 @@ func (m *Listing_Item_Sku) Reset() { *m = Listing_Item_Sku{} } func (m *Listing_Item_Sku) String() string { return proto.CompactTextString(m) } func (*Listing_Item_Sku) ProtoMessage() {} func (*Listing_Item_Sku) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 1, 1} + return fileDescriptor_b6d125f880f9ca35, []int{2, 1, 1} } func (m *Listing_Item_Sku) XXX_Unmarshal(b []byte) error { @@ -811,6 +896,7 @@ func (m *Listing_Item_Sku) GetProductID() string { return "" } +// Deprecated: Do not use. func (m *Listing_Item_Sku) GetSurcharge() int64 { if m != nil { return m.Surcharge @@ -818,6 +904,7 @@ func (m *Listing_Item_Sku) GetSurcharge() int64 { return 0 } +// Deprecated: Do not use. func (m *Listing_Item_Sku) GetQuantity() int64 { if m != nil { return m.Quantity @@ -825,6 +912,20 @@ func (m *Listing_Item_Sku) GetQuantity() int64 { return 0 } +func (m *Listing_Item_Sku) GetBigSurcharge() string { + if m != nil { + return m.BigSurcharge + } + return "" +} + +func (m *Listing_Item_Sku) GetBigQuantity() string { + if m != nil { + return m.BigQuantity + } + return "" +} + type Listing_Item_Image struct { Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"` Original string `protobuf:"bytes,2,opt,name=original,proto3" json:"original,omitempty"` @@ -841,7 +942,7 @@ func (m *Listing_Item_Image) Reset() { *m = Listing_Item_Image{} } func (m *Listing_Item_Image) String() string { return proto.CompactTextString(m) } func (*Listing_Item_Image) ProtoMessage() {} func (*Listing_Item_Image) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 1, 2} + return fileDescriptor_b6d125f880f9ca35, []int{2, 1, 2} } func (m *Listing_Item_Image) XXX_Unmarshal(b []byte) error { @@ -918,7 +1019,7 @@ func (m *Listing_ShippingOption) Reset() { *m = Listing_ShippingOption{} func (m *Listing_ShippingOption) String() string { return proto.CompactTextString(m) } func (*Listing_ShippingOption) ProtoMessage() {} func (*Listing_ShippingOption) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 2} + return fileDescriptor_b6d125f880f9ca35, []int{2, 2} } func (m *Listing_ShippingOption) XXX_Unmarshal(b []byte) error { @@ -968,20 +1069,22 @@ func (m *Listing_ShippingOption) GetServices() []*Listing_ShippingOption_Service } type Listing_ShippingOption_Service struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Price uint64 `protobuf:"varint,2,opt,name=price,proto3" json:"price,omitempty"` - EstimatedDelivery string `protobuf:"bytes,3,opt,name=estimatedDelivery,proto3" json:"estimatedDelivery,omitempty"` - AdditionalItemPrice uint64 `protobuf:"varint,4,opt,name=additionalItemPrice,proto3" json:"additionalItemPrice,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Price uint64 `protobuf:"varint,2,opt,name=price,proto3" json:"price,omitempty"` // Deprecated: Do not use. + EstimatedDelivery string `protobuf:"bytes,3,opt,name=estimatedDelivery,proto3" json:"estimatedDelivery,omitempty"` + AdditionalItemPrice uint64 `protobuf:"varint,4,opt,name=additionalItemPrice,proto3" json:"additionalItemPrice,omitempty"` // Deprecated: Do not use. + BigPrice string `protobuf:"bytes,5,opt,name=bigPrice,proto3" json:"bigPrice,omitempty"` + BigAdditionalItemPrice string `protobuf:"bytes,6,opt,name=bigAdditionalItemPrice,proto3" json:"bigAdditionalItemPrice,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Listing_ShippingOption_Service) Reset() { *m = Listing_ShippingOption_Service{} } func (m *Listing_ShippingOption_Service) String() string { return proto.CompactTextString(m) } func (*Listing_ShippingOption_Service) ProtoMessage() {} func (*Listing_ShippingOption_Service) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 2, 0} + return fileDescriptor_b6d125f880f9ca35, []int{2, 2, 0} } func (m *Listing_ShippingOption_Service) XXX_Unmarshal(b []byte) error { @@ -1009,6 +1112,7 @@ func (m *Listing_ShippingOption_Service) GetName() string { return "" } +// Deprecated: Do not use. func (m *Listing_ShippingOption_Service) GetPrice() uint64 { if m != nil { return m.Price @@ -1023,6 +1127,7 @@ func (m *Listing_ShippingOption_Service) GetEstimatedDelivery() string { return "" } +// Deprecated: Do not use. func (m *Listing_ShippingOption_Service) GetAdditionalItemPrice() uint64 { if m != nil { return m.AdditionalItemPrice @@ -1030,6 +1135,20 @@ func (m *Listing_ShippingOption_Service) GetAdditionalItemPrice() uint64 { return 0 } +func (m *Listing_ShippingOption_Service) GetBigPrice() string { + if m != nil { + return m.BigPrice + } + return "" +} + +func (m *Listing_ShippingOption_Service) GetBigAdditionalItemPrice() string { + if m != nil { + return m.BigAdditionalItemPrice + } + return "" +} + type Listing_Tax struct { TaxType string `protobuf:"bytes,1,opt,name=taxType,proto3" json:"taxType,omitempty"` TaxRegions []CountryCode `protobuf:"varint,2,rep,packed,name=taxRegions,proto3,enum=CountryCode" json:"taxRegions,omitempty"` @@ -1044,7 +1163,7 @@ func (m *Listing_Tax) Reset() { *m = Listing_Tax{} } func (m *Listing_Tax) String() string { return proto.CompactTextString(m) } func (*Listing_Tax) ProtoMessage() {} func (*Listing_Tax) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 3} + return fileDescriptor_b6d125f880f9ca35, []int{2, 3} } func (m *Listing_Tax) XXX_Unmarshal(b []byte) error { @@ -1102,6 +1221,7 @@ type Listing_Coupon struct { // Types that are valid to be assigned to Discount: // *Listing_Coupon_PercentDiscount // *Listing_Coupon_PriceDiscount + // *Listing_Coupon_BigPriceDiscount Discount isListing_Coupon_Discount `protobuf_oneof:"discount"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -1112,7 +1232,7 @@ func (m *Listing_Coupon) Reset() { *m = Listing_Coupon{} } func (m *Listing_Coupon) String() string { return proto.CompactTextString(m) } func (*Listing_Coupon) ProtoMessage() {} func (*Listing_Coupon) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{1, 4} + return fileDescriptor_b6d125f880f9ca35, []int{2, 4} } func (m *Listing_Coupon) XXX_Unmarshal(b []byte) error { @@ -1189,10 +1309,16 @@ type Listing_Coupon_PriceDiscount struct { PriceDiscount uint64 `protobuf:"varint,6,opt,name=priceDiscount,proto3,oneof"` } +type Listing_Coupon_BigPriceDiscount struct { + BigPriceDiscount string `protobuf:"bytes,7,opt,name=bigPriceDiscount,proto3,oneof"` +} + func (*Listing_Coupon_PercentDiscount) isListing_Coupon_Discount() {} func (*Listing_Coupon_PriceDiscount) isListing_Coupon_Discount() {} +func (*Listing_Coupon_BigPriceDiscount) isListing_Coupon_Discount() {} + func (m *Listing_Coupon) GetDiscount() isListing_Coupon_Discount { if m != nil { return m.Discount @@ -1207,6 +1333,7 @@ func (m *Listing_Coupon) GetPercentDiscount() float32 { return 0 } +// Deprecated: Do not use. func (m *Listing_Coupon) GetPriceDiscount() uint64 { if x, ok := m.GetDiscount().(*Listing_Coupon_PriceDiscount); ok { return x.PriceDiscount @@ -1214,6 +1341,13 @@ func (m *Listing_Coupon) GetPriceDiscount() uint64 { return 0 } +func (m *Listing_Coupon) GetBigPriceDiscount() string { + if x, ok := m.GetDiscount().(*Listing_Coupon_BigPriceDiscount); ok { + return x.BigPriceDiscount + } + return "" +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*Listing_Coupon) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -1221,12 +1355,13 @@ func (*Listing_Coupon) XXX_OneofWrappers() []interface{} { (*Listing_Coupon_DiscountCode)(nil), (*Listing_Coupon_PercentDiscount)(nil), (*Listing_Coupon_PriceDiscount)(nil), + (*Listing_Coupon_BigPriceDiscount)(nil), } } type Order struct { RefundAddress string `protobuf:"bytes,1,opt,name=refundAddress,proto3" json:"refundAddress,omitempty"` - RefundFee uint64 `protobuf:"varint,2,opt,name=refundFee,proto3" json:"refundFee,omitempty"` + RefundFee uint64 `protobuf:"varint,2,opt,name=refundFee,proto3" json:"refundFee,omitempty"` // Deprecated: Do not use. Shipping *Order_Shipping `protobuf:"bytes,3,opt,name=shipping,proto3" json:"shipping,omitempty"` BuyerID *ID `protobuf:"bytes,4,opt,name=buyerID,proto3" json:"buyerID,omitempty"` Timestamp *timestamp.Timestamp `protobuf:"bytes,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` @@ -1235,6 +1370,7 @@ type Order struct { RatingKeys [][]byte `protobuf:"bytes,8,rep,name=ratingKeys,proto3" json:"ratingKeys,omitempty"` AlternateContactInfo string `protobuf:"bytes,9,opt,name=alternateContactInfo,proto3" json:"alternateContactInfo,omitempty"` Version uint32 `protobuf:"varint,10,opt,name=version,proto3" json:"version,omitempty"` + BigRefundFee string `protobuf:"bytes,11,opt,name=bigRefundFee,proto3" json:"bigRefundFee,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1244,7 +1380,7 @@ func (m *Order) Reset() { *m = Order{} } func (m *Order) String() string { return proto.CompactTextString(m) } func (*Order) ProtoMessage() {} func (*Order) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{2} + return fileDescriptor_b6d125f880f9ca35, []int{3} } func (m *Order) XXX_Unmarshal(b []byte) error { @@ -1272,6 +1408,7 @@ func (m *Order) GetRefundAddress() string { return "" } +// Deprecated: Do not use. func (m *Order) GetRefundFee() uint64 { if m != nil { return m.RefundFee @@ -1335,6 +1472,13 @@ func (m *Order) GetVersion() uint32 { return 0 } +func (m *Order) GetBigRefundFee() string { + if m != nil { + return m.BigRefundFee + } + return "" +} + type Order_Shipping struct { ShipTo string `protobuf:"bytes,1,opt,name=shipTo,proto3" json:"shipTo,omitempty"` Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` @@ -1352,7 +1496,7 @@ func (m *Order_Shipping) Reset() { *m = Order_Shipping{} } func (m *Order_Shipping) String() string { return proto.CompactTextString(m) } func (*Order_Shipping) ProtoMessage() {} func (*Order_Shipping) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{2, 0} + return fileDescriptor_b6d125f880f9ca35, []int{3, 0} } func (m *Order_Shipping) XXX_Unmarshal(b []byte) error { @@ -1424,13 +1568,14 @@ func (m *Order_Shipping) GetAddressNotes() string { type Order_Item struct { ListingHash string `protobuf:"bytes,1,opt,name=listingHash,proto3" json:"listingHash,omitempty"` - Quantity uint32 `protobuf:"varint,2,opt,name=quantity,proto3" json:"quantity,omitempty"` - Quantity64 uint64 `protobuf:"varint,8,opt,name=quantity64,proto3" json:"quantity64,omitempty"` + Quantity uint32 `protobuf:"varint,2,opt,name=quantity,proto3" json:"quantity,omitempty"` // Deprecated: Do not use. Options []*Order_Item_Option `protobuf:"bytes,3,rep,name=options,proto3" json:"options,omitempty"` ShippingOption *Order_Item_ShippingOption `protobuf:"bytes,4,opt,name=shippingOption,proto3" json:"shippingOption,omitempty"` Memo string `protobuf:"bytes,5,opt,name=memo,proto3" json:"memo,omitempty"` CouponCodes []string `protobuf:"bytes,6,rep,name=couponCodes,proto3" json:"couponCodes,omitempty"` PaymentAddress string `protobuf:"bytes,7,opt,name=paymentAddress,proto3" json:"paymentAddress,omitempty"` + Quantity64 uint64 `protobuf:"varint,8,opt,name=quantity64,proto3" json:"quantity64,omitempty"` // Deprecated: Do not use. + BigQuantity string `protobuf:"bytes,9,opt,name=bigQuantity,proto3" json:"bigQuantity,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1440,7 +1585,7 @@ func (m *Order_Item) Reset() { *m = Order_Item{} } func (m *Order_Item) String() string { return proto.CompactTextString(m) } func (*Order_Item) ProtoMessage() {} func (*Order_Item) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{2, 1} + return fileDescriptor_b6d125f880f9ca35, []int{3, 1} } func (m *Order_Item) XXX_Unmarshal(b []byte) error { @@ -1468,6 +1613,7 @@ func (m *Order_Item) GetListingHash() string { return "" } +// Deprecated: Do not use. func (m *Order_Item) GetQuantity() uint32 { if m != nil { return m.Quantity @@ -1475,13 +1621,6 @@ func (m *Order_Item) GetQuantity() uint32 { return 0 } -func (m *Order_Item) GetQuantity64() uint64 { - if m != nil { - return m.Quantity64 - } - return 0 -} - func (m *Order_Item) GetOptions() []*Order_Item_Option { if m != nil { return m.Options @@ -1517,6 +1656,21 @@ func (m *Order_Item) GetPaymentAddress() string { return "" } +// Deprecated: Do not use. +func (m *Order_Item) GetQuantity64() uint64 { + if m != nil { + return m.Quantity64 + } + return 0 +} + +func (m *Order_Item) GetBigQuantity() string { + if m != nil { + return m.BigQuantity + } + return "" +} + type Order_Item_Option struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` @@ -1529,7 +1683,7 @@ func (m *Order_Item_Option) Reset() { *m = Order_Item_Option{} } func (m *Order_Item_Option) String() string { return proto.CompactTextString(m) } func (*Order_Item_Option) ProtoMessage() {} func (*Order_Item_Option) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{2, 1, 0} + return fileDescriptor_b6d125f880f9ca35, []int{3, 1, 0} } func (m *Order_Item_Option) XXX_Unmarshal(b []byte) error { @@ -1576,7 +1730,7 @@ func (m *Order_Item_ShippingOption) Reset() { *m = Order_Item_ShippingOp func (m *Order_Item_ShippingOption) String() string { return proto.CompactTextString(m) } func (*Order_Item_ShippingOption) ProtoMessage() {} func (*Order_Item_ShippingOption) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{2, 1, 1} + return fileDescriptor_b6d125f880f9ca35, []int{3, 1, 1} } func (m *Order_Item_ShippingOption) XXX_Unmarshal(b []byte) error { @@ -1614,12 +1768,14 @@ func (m *Order_Item_ShippingOption) GetService() string { type Order_Payment struct { Method Order_Payment_Method `protobuf:"varint,1,opt,name=method,proto3,enum=Order_Payment_Method" json:"method,omitempty"` Moderator string `protobuf:"bytes,2,opt,name=moderator,proto3" json:"moderator,omitempty"` - Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` // Deprecated: Do not use. Chaincode string `protobuf:"bytes,4,opt,name=chaincode,proto3" json:"chaincode,omitempty"` Address string `protobuf:"bytes,5,opt,name=address,proto3" json:"address,omitempty"` RedeemScript string `protobuf:"bytes,6,opt,name=redeemScript,proto3" json:"redeemScript,omitempty"` ModeratorKey []byte `protobuf:"bytes,7,opt,name=moderatorKey,proto3" json:"moderatorKey,omitempty"` - Coin string `protobuf:"bytes,8,opt,name=coin,proto3" json:"coin,omitempty"` + Coin string `protobuf:"bytes,8,opt,name=coin,proto3" json:"coin,omitempty"` // Deprecated: Do not use. + BigAmount string `protobuf:"bytes,9,opt,name=bigAmount,proto3" json:"bigAmount,omitempty"` + AmountCurrency *CurrencyDefinition `protobuf:"bytes,10,opt,name=amountCurrency,proto3" json:"amountCurrency,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1629,7 +1785,7 @@ func (m *Order_Payment) Reset() { *m = Order_Payment{} } func (m *Order_Payment) String() string { return proto.CompactTextString(m) } func (*Order_Payment) ProtoMessage() {} func (*Order_Payment) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{2, 2} + return fileDescriptor_b6d125f880f9ca35, []int{3, 2} } func (m *Order_Payment) XXX_Unmarshal(b []byte) error { @@ -1664,6 +1820,7 @@ func (m *Order_Payment) GetModerator() string { return "" } +// Deprecated: Do not use. func (m *Order_Payment) GetAmount() uint64 { if m != nil { return m.Amount @@ -1699,6 +1856,7 @@ func (m *Order_Payment) GetModeratorKey() []byte { return nil } +// Deprecated: Do not use. func (m *Order_Payment) GetCoin() string { if m != nil { return m.Coin @@ -1706,23 +1864,39 @@ func (m *Order_Payment) GetCoin() string { return "" } +func (m *Order_Payment) GetBigAmount() string { + if m != nil { + return m.BigAmount + } + return "" +} + +func (m *Order_Payment) GetAmountCurrency() *CurrencyDefinition { + if m != nil { + return m.AmountCurrency + } + return nil +} + type OrderConfirmation struct { OrderID string `protobuf:"bytes,1,opt,name=orderID,proto3" json:"orderID,omitempty"` Timestamp *timestamp.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Direct payments only - PaymentAddress string `protobuf:"bytes,3,opt,name=paymentAddress,proto3" json:"paymentAddress,omitempty"` - RequestedAmount uint64 `protobuf:"varint,4,opt,name=requestedAmount,proto3" json:"requestedAmount,omitempty"` - RatingSignatures []*RatingSignature `protobuf:"bytes,5,rep,name=ratingSignatures,proto3" json:"ratingSignatures,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + PaymentAddress string `protobuf:"bytes,3,opt,name=paymentAddress,proto3" json:"paymentAddress,omitempty"` + RequestedAmount uint64 `protobuf:"varint,4,opt,name=requestedAmount,proto3" json:"requestedAmount,omitempty"` // Deprecated: Do not use. + RatingSignatures []*RatingSignature `protobuf:"bytes,5,rep,name=ratingSignatures,proto3" json:"ratingSignatures,omitempty"` + BigRequestedAmount string `protobuf:"bytes,6,opt,name=bigRequestedAmount,proto3" json:"bigRequestedAmount,omitempty"` + RequestedAmountCurrency *CurrencyDefinition `protobuf:"bytes,7,opt,name=requestedAmountCurrency,proto3" json:"requestedAmountCurrency,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *OrderConfirmation) Reset() { *m = OrderConfirmation{} } func (m *OrderConfirmation) String() string { return proto.CompactTextString(m) } func (*OrderConfirmation) ProtoMessage() {} func (*OrderConfirmation) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{3} + return fileDescriptor_b6d125f880f9ca35, []int{4} } func (m *OrderConfirmation) XXX_Unmarshal(b []byte) error { @@ -1764,6 +1938,7 @@ func (m *OrderConfirmation) GetPaymentAddress() string { return "" } +// Deprecated: Do not use. func (m *OrderConfirmation) GetRequestedAmount() uint64 { if m != nil { return m.RequestedAmount @@ -1778,6 +1953,20 @@ func (m *OrderConfirmation) GetRatingSignatures() []*RatingSignature { return nil } +func (m *OrderConfirmation) GetBigRequestedAmount() string { + if m != nil { + return m.BigRequestedAmount + } + return "" +} + +func (m *OrderConfirmation) GetRequestedAmountCurrency() *CurrencyDefinition { + if m != nil { + return m.RequestedAmountCurrency + } + return nil +} + type OrderReject struct { OrderID string `protobuf:"bytes,1,opt,name=orderID,proto3" json:"orderID,omitempty"` Timestamp *timestamp.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` @@ -1791,7 +1980,7 @@ func (m *OrderReject) Reset() { *m = OrderReject{} } func (m *OrderReject) String() string { return proto.CompactTextString(m) } func (*OrderReject) ProtoMessage() {} func (*OrderReject) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{4} + return fileDescriptor_b6d125f880f9ca35, []int{5} } func (m *OrderReject) XXX_Unmarshal(b []byte) error { @@ -1845,7 +2034,7 @@ func (m *RatingSignature) Reset() { *m = RatingSignature{} } func (m *RatingSignature) String() string { return proto.CompactTextString(m) } func (*RatingSignature) ProtoMessage() {} func (*RatingSignature) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{5} + return fileDescriptor_b6d125f880f9ca35, []int{6} } func (m *RatingSignature) XXX_Unmarshal(b []byte) error { @@ -1895,7 +2084,7 @@ func (m *RatingSignature_TransactionMetadata) Reset() { *m = RatingSigna func (m *RatingSignature_TransactionMetadata) String() string { return proto.CompactTextString(m) } func (*RatingSignature_TransactionMetadata) ProtoMessage() {} func (*RatingSignature_TransactionMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{5, 0} + return fileDescriptor_b6d125f880f9ca35, []int{6, 0} } func (m *RatingSignature_TransactionMetadata) XXX_Unmarshal(b []byte) error { @@ -1965,10 +2154,12 @@ type RatingSignature_TransactionMetadata_Image struct { func (m *RatingSignature_TransactionMetadata_Image) Reset() { *m = RatingSignature_TransactionMetadata_Image{} } -func (m *RatingSignature_TransactionMetadata_Image) String() string { return proto.CompactTextString(m) } -func (*RatingSignature_TransactionMetadata_Image) ProtoMessage() {} +func (m *RatingSignature_TransactionMetadata_Image) String() string { + return proto.CompactTextString(m) +} +func (*RatingSignature_TransactionMetadata_Image) ProtoMessage() {} func (*RatingSignature_TransactionMetadata_Image) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{5, 0, 0} + return fileDescriptor_b6d125f880f9ca35, []int{6, 0, 0} } func (m *RatingSignature_TransactionMetadata_Image) XXX_Unmarshal(b []byte) error { @@ -2036,7 +2227,7 @@ func (m *BitcoinSignature) Reset() { *m = BitcoinSignature{} } func (m *BitcoinSignature) String() string { return proto.CompactTextString(m) } func (*BitcoinSignature) ProtoMessage() {} func (*BitcoinSignature) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{6} + return fileDescriptor_b6d125f880f9ca35, []int{7} } func (m *BitcoinSignature) XXX_Unmarshal(b []byte) error { @@ -2094,7 +2285,7 @@ func (m *OrderFulfillment) Reset() { *m = OrderFulfillment{} } func (m *OrderFulfillment) String() string { return proto.CompactTextString(m) } func (*OrderFulfillment) ProtoMessage() {} func (*OrderFulfillment) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{7} + return fileDescriptor_b6d125f880f9ca35, []int{8} } func (m *OrderFulfillment) XXX_Unmarshal(b []byte) error { @@ -2190,7 +2381,7 @@ func (m *OrderFulfillment_PhysicalDelivery) Reset() { *m = OrderFulfillm func (m *OrderFulfillment_PhysicalDelivery) String() string { return proto.CompactTextString(m) } func (*OrderFulfillment_PhysicalDelivery) ProtoMessage() {} func (*OrderFulfillment_PhysicalDelivery) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{7, 0} + return fileDescriptor_b6d125f880f9ca35, []int{8, 0} } func (m *OrderFulfillment_PhysicalDelivery) XXX_Unmarshal(b []byte) error { @@ -2237,7 +2428,7 @@ func (m *OrderFulfillment_DigitalDelivery) Reset() { *m = OrderFulfillme func (m *OrderFulfillment_DigitalDelivery) String() string { return proto.CompactTextString(m) } func (*OrderFulfillment_DigitalDelivery) ProtoMessage() {} func (*OrderFulfillment_DigitalDelivery) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{7, 1} + return fileDescriptor_b6d125f880f9ca35, []int{8, 1} } func (m *OrderFulfillment_DigitalDelivery) XXX_Unmarshal(b []byte) error { @@ -2285,7 +2476,7 @@ func (m *OrderFulfillment_CryptocurrencyDelivery) Reset() { func (m *OrderFulfillment_CryptocurrencyDelivery) String() string { return proto.CompactTextString(m) } func (*OrderFulfillment_CryptocurrencyDelivery) ProtoMessage() {} func (*OrderFulfillment_CryptocurrencyDelivery) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{7, 2} + return fileDescriptor_b6d125f880f9ca35, []int{8, 2} } func (m *OrderFulfillment_CryptocurrencyDelivery) XXX_Unmarshal(b []byte) error { @@ -2316,7 +2507,9 @@ func (m *OrderFulfillment_CryptocurrencyDelivery) GetTransactionID() string { type OrderFulfillment_Payout struct { Sigs []*BitcoinSignature `protobuf:"bytes,1,rep,name=sigs,proto3" json:"sigs,omitempty"` PayoutAddress string `protobuf:"bytes,2,opt,name=payoutAddress,proto3" json:"payoutAddress,omitempty"` - PayoutFeePerByte uint64 `protobuf:"varint,3,opt,name=payoutFeePerByte,proto3" json:"payoutFeePerByte,omitempty"` + PayoutFeePerByte uint64 `protobuf:"varint,3,opt,name=payoutFeePerByte,proto3" json:"payoutFeePerByte,omitempty"` // Deprecated: Do not use. + BigPayoutFeePerByte string `protobuf:"bytes,4,opt,name=bigPayoutFeePerByte,proto3" json:"bigPayoutFeePerByte,omitempty"` + PayoutFeeCurrency *CurrencyDefinition `protobuf:"bytes,5,opt,name=payoutFeeCurrency,proto3" json:"payoutFeeCurrency,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2326,7 +2519,7 @@ func (m *OrderFulfillment_Payout) Reset() { *m = OrderFulfillment_Payout func (m *OrderFulfillment_Payout) String() string { return proto.CompactTextString(m) } func (*OrderFulfillment_Payout) ProtoMessage() {} func (*OrderFulfillment_Payout) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{7, 3} + return fileDescriptor_b6d125f880f9ca35, []int{8, 3} } func (m *OrderFulfillment_Payout) XXX_Unmarshal(b []byte) error { @@ -2361,6 +2554,7 @@ func (m *OrderFulfillment_Payout) GetPayoutAddress() string { return "" } +// Deprecated: Do not use. func (m *OrderFulfillment_Payout) GetPayoutFeePerByte() uint64 { if m != nil { return m.PayoutFeePerByte @@ -2368,6 +2562,20 @@ func (m *OrderFulfillment_Payout) GetPayoutFeePerByte() uint64 { return 0 } +func (m *OrderFulfillment_Payout) GetBigPayoutFeePerByte() string { + if m != nil { + return m.BigPayoutFeePerByte + } + return "" +} + +func (m *OrderFulfillment_Payout) GetPayoutFeeCurrency() *CurrencyDefinition { + if m != nil { + return m.PayoutFeeCurrency + } + return nil +} + type OrderCompletion struct { OrderId string `protobuf:"bytes,1,opt,name=orderId,proto3" json:"orderId,omitempty"` Timestamp *timestamp.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` @@ -2382,7 +2590,7 @@ func (m *OrderCompletion) Reset() { *m = OrderCompletion{} } func (m *OrderCompletion) String() string { return proto.CompactTextString(m) } func (*OrderCompletion) ProtoMessage() {} func (*OrderCompletion) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{8} + return fileDescriptor_b6d125f880f9ca35, []int{9} } func (m *OrderCompletion) XXX_Unmarshal(b []byte) error { @@ -2431,6 +2639,61 @@ func (m *OrderCompletion) GetRatings() []*Rating { return nil } +type OrderProcessingFailure struct { + OrderID string `protobuf:"bytes,1,opt,name=orderID,proto3" json:"orderID,omitempty"` + AttemptedMessageType Message_MessageType `protobuf:"varint,2,opt,name=attemptedMessageType,proto3,enum=Message_MessageType" json:"attemptedMessageType,omitempty"` + Contract *RicardianContract `protobuf:"bytes,3,opt,name=contract,proto3" json:"contract,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OrderProcessingFailure) Reset() { *m = OrderProcessingFailure{} } +func (m *OrderProcessingFailure) String() string { return proto.CompactTextString(m) } +func (*OrderProcessingFailure) ProtoMessage() {} +func (*OrderProcessingFailure) Descriptor() ([]byte, []int) { + return fileDescriptor_b6d125f880f9ca35, []int{10} +} + +func (m *OrderProcessingFailure) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OrderProcessingFailure.Unmarshal(m, b) +} +func (m *OrderProcessingFailure) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OrderProcessingFailure.Marshal(b, m, deterministic) +} +func (m *OrderProcessingFailure) XXX_Merge(src proto.Message) { + xxx_messageInfo_OrderProcessingFailure.Merge(m, src) +} +func (m *OrderProcessingFailure) XXX_Size() int { + return xxx_messageInfo_OrderProcessingFailure.Size(m) +} +func (m *OrderProcessingFailure) XXX_DiscardUnknown() { + xxx_messageInfo_OrderProcessingFailure.DiscardUnknown(m) +} + +var xxx_messageInfo_OrderProcessingFailure proto.InternalMessageInfo + +func (m *OrderProcessingFailure) GetOrderID() string { + if m != nil { + return m.OrderID + } + return "" +} + +func (m *OrderProcessingFailure) GetAttemptedMessageType() Message_MessageType { + if m != nil { + return m.AttemptedMessageType + } + return Message_PING +} + +func (m *OrderProcessingFailure) GetContract() *RicardianContract { + if m != nil { + return m.Contract + } + return nil +} + type Rating struct { RatingData *Rating_RatingData `protobuf:"bytes,1,opt,name=ratingData,proto3" json:"ratingData,omitempty"` Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` @@ -2443,7 +2706,7 @@ func (m *Rating) Reset() { *m = Rating{} } func (m *Rating) String() string { return proto.CompactTextString(m) } func (*Rating) ProtoMessage() {} func (*Rating) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{9} + return fileDescriptor_b6d125f880f9ca35, []int{11} } func (m *Rating) XXX_Unmarshal(b []byte) error { @@ -2502,7 +2765,7 @@ func (m *Rating_RatingData) Reset() { *m = Rating_RatingData{} } func (m *Rating_RatingData) String() string { return proto.CompactTextString(m) } func (*Rating_RatingData) ProtoMessage() {} func (*Rating_RatingData) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{9, 0} + return fileDescriptor_b6d125f880f9ca35, []int{11, 0} } func (m *Rating_RatingData) XXX_Unmarshal(b []byte) error { @@ -2636,7 +2899,7 @@ func (m *Dispute) Reset() { *m = Dispute{} } func (m *Dispute) String() string { return proto.CompactTextString(m) } func (*Dispute) ProtoMessage() {} func (*Dispute) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{10} + return fileDescriptor_b6d125f880f9ca35, []int{12} } func (m *Dispute) XXX_Unmarshal(b []byte) error { @@ -2708,7 +2971,7 @@ func (m *DisputeResolution) Reset() { *m = DisputeResolution{} } func (m *DisputeResolution) String() string { return proto.CompactTextString(m) } func (*DisputeResolution) ProtoMessage() {} func (*DisputeResolution) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{11} + return fileDescriptor_b6d125f880f9ca35, []int{13} } func (m *DisputeResolution) XXX_Unmarshal(b []byte) error { @@ -2777,6 +3040,7 @@ type DisputeResolution_Payout struct { BuyerOutput *DisputeResolution_Payout_Output `protobuf:"bytes,3,opt,name=buyerOutput,proto3" json:"buyerOutput,omitempty"` VendorOutput *DisputeResolution_Payout_Output `protobuf:"bytes,4,opt,name=vendorOutput,proto3" json:"vendorOutput,omitempty"` ModeratorOutput *DisputeResolution_Payout_Output `protobuf:"bytes,5,opt,name=moderatorOutput,proto3" json:"moderatorOutput,omitempty"` + PayoutCurrency *CurrencyDefinition `protobuf:"bytes,6,opt,name=payoutCurrency,proto3" json:"payoutCurrency,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2786,7 +3050,7 @@ func (m *DisputeResolution_Payout) Reset() { *m = DisputeResolution_Payo func (m *DisputeResolution_Payout) String() string { return proto.CompactTextString(m) } func (*DisputeResolution_Payout) ProtoMessage() {} func (*DisputeResolution_Payout) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{11, 0} + return fileDescriptor_b6d125f880f9ca35, []int{13, 0} } func (m *DisputeResolution_Payout) XXX_Unmarshal(b []byte) error { @@ -2842,12 +3106,20 @@ func (m *DisputeResolution_Payout) GetModeratorOutput() *DisputeResolution_Payou return nil } +func (m *DisputeResolution_Payout) GetPayoutCurrency() *CurrencyDefinition { + if m != nil { + return m.PayoutCurrency + } + return nil +} + type DisputeResolution_Payout_Output struct { // Types that are valid to be assigned to ScriptOrAddress: // *DisputeResolution_Payout_Output_Script // *DisputeResolution_Payout_Output_Address ScriptOrAddress isDisputeResolution_Payout_Output_ScriptOrAddress `protobuf_oneof:"scriptOrAddress"` - Amount uint64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` + Amount uint64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` // Deprecated: Do not use. + BigAmount string `protobuf:"bytes,4,opt,name=bigAmount,proto3" json:"bigAmount,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2857,7 +3129,7 @@ func (m *DisputeResolution_Payout_Output) Reset() { *m = DisputeResoluti func (m *DisputeResolution_Payout_Output) String() string { return proto.CompactTextString(m) } func (*DisputeResolution_Payout_Output) ProtoMessage() {} func (*DisputeResolution_Payout_Output) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{11, 0, 0} + return fileDescriptor_b6d125f880f9ca35, []int{13, 0, 0} } func (m *DisputeResolution_Payout_Output) XXX_Unmarshal(b []byte) error { @@ -2915,6 +3187,7 @@ func (m *DisputeResolution_Payout_Output) GetAddress() string { return "" } +// Deprecated: Do not use. func (m *DisputeResolution_Payout_Output) GetAmount() uint64 { if m != nil { return m.Amount @@ -2922,6 +3195,13 @@ func (m *DisputeResolution_Payout_Output) GetAmount() uint64 { return 0 } +func (m *DisputeResolution_Payout_Output) GetBigAmount() string { + if m != nil { + return m.BigAmount + } + return "" +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*DisputeResolution_Payout_Output) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -2942,7 +3222,7 @@ func (m *DisputeAcceptance) Reset() { *m = DisputeAcceptance{} } func (m *DisputeAcceptance) String() string { return proto.CompactTextString(m) } func (*DisputeAcceptance) ProtoMessage() {} func (*DisputeAcceptance) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{12} + return fileDescriptor_b6d125f880f9ca35, []int{14} } func (m *DisputeAcceptance) XXX_Unmarshal(b []byte) error { @@ -2980,7 +3260,8 @@ func (m *DisputeAcceptance) GetClosedBy() string { type Outpoint struct { Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` Index uint32 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` - Value uint64 `protobuf:"varint,3,opt,name=value,proto3" json:"value,omitempty"` + Value uint64 `protobuf:"varint,3,opt,name=value,proto3" json:"value,omitempty"` // Deprecated: Do not use. + BigValue string `protobuf:"bytes,4,opt,name=bigValue,proto3" json:"bigValue,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2990,7 +3271,7 @@ func (m *Outpoint) Reset() { *m = Outpoint{} } func (m *Outpoint) String() string { return proto.CompactTextString(m) } func (*Outpoint) ProtoMessage() {} func (*Outpoint) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{13} + return fileDescriptor_b6d125f880f9ca35, []int{15} } func (m *Outpoint) XXX_Unmarshal(b []byte) error { @@ -3025,6 +3306,7 @@ func (m *Outpoint) GetIndex() uint32 { return 0 } +// Deprecated: Do not use. func (m *Outpoint) GetValue() uint64 { if m != nil { return m.Value @@ -3032,6 +3314,13 @@ func (m *Outpoint) GetValue() uint64 { return 0 } +func (m *Outpoint) GetBigValue() string { + if m != nil { + return m.BigValue + } + return "" +} + type Refund struct { OrderID string `protobuf:"bytes,1,opt,name=orderID,proto3" json:"orderID,omitempty"` Timestamp *timestamp.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` @@ -3047,7 +3336,7 @@ func (m *Refund) Reset() { *m = Refund{} } func (m *Refund) String() string { return proto.CompactTextString(m) } func (*Refund) ProtoMessage() {} func (*Refund) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{14} + return fileDescriptor_b6d125f880f9ca35, []int{16} } func (m *Refund) XXX_Unmarshal(b []byte) error { @@ -3104,18 +3393,20 @@ func (m *Refund) GetMemo() string { } type Refund_TransactionInfo struct { - Txid string `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` - Value uint64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Txid string `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` + Value uint64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` // Deprecated: Do not use. + BigValue string `protobuf:"bytes,3,opt,name=bigValue,proto3" json:"bigValue,omitempty"` + ValueCurrency *CurrencyDefinition `protobuf:"bytes,4,opt,name=valueCurrency,proto3" json:"valueCurrency,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Refund_TransactionInfo) Reset() { *m = Refund_TransactionInfo{} } func (m *Refund_TransactionInfo) String() string { return proto.CompactTextString(m) } func (*Refund_TransactionInfo) ProtoMessage() {} func (*Refund_TransactionInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{14, 0} + return fileDescriptor_b6d125f880f9ca35, []int{16, 0} } func (m *Refund_TransactionInfo) XXX_Unmarshal(b []byte) error { @@ -3143,6 +3434,7 @@ func (m *Refund_TransactionInfo) GetTxid() string { return "" } +// Deprecated: Do not use. func (m *Refund_TransactionInfo) GetValue() uint64 { if m != nil { return m.Value @@ -3150,6 +3442,20 @@ func (m *Refund_TransactionInfo) GetValue() uint64 { return 0 } +func (m *Refund_TransactionInfo) GetBigValue() string { + if m != nil { + return m.BigValue + } + return "" +} + +func (m *Refund_TransactionInfo) GetValueCurrency() *CurrencyDefinition { + if m != nil { + return m.ValueCurrency + } + return nil +} + type VendorFinalizedPayment struct { OrderID string `protobuf:"bytes,1,opt,name=orderID,proto3" json:"orderID,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -3161,7 +3467,7 @@ func (m *VendorFinalizedPayment) Reset() { *m = VendorFinalizedPayment{} func (m *VendorFinalizedPayment) String() string { return proto.CompactTextString(m) } func (*VendorFinalizedPayment) ProtoMessage() {} func (*VendorFinalizedPayment) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{15} + return fileDescriptor_b6d125f880f9ca35, []int{17} } func (m *VendorFinalizedPayment) XXX_Unmarshal(b []byte) error { @@ -3203,7 +3509,7 @@ func (m *ID) Reset() { *m = ID{} } func (m *ID) String() string { return proto.CompactTextString(m) } func (*ID) ProtoMessage() {} func (*ID) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{16} + return fileDescriptor_b6d125f880f9ca35, []int{18} } func (m *ID) XXX_Unmarshal(b []byte) error { @@ -3264,7 +3570,7 @@ func (m *ID_Pubkeys) Reset() { *m = ID_Pubkeys{} } func (m *ID_Pubkeys) String() string { return proto.CompactTextString(m) } func (*ID_Pubkeys) ProtoMessage() {} func (*ID_Pubkeys) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{16, 0} + return fileDescriptor_b6d125f880f9ca35, []int{18, 0} } func (m *ID_Pubkeys) XXX_Unmarshal(b []byte) error { @@ -3311,7 +3617,7 @@ func (m *Signature) Reset() { *m = Signature{} } func (m *Signature) String() string { return proto.CompactTextString(m) } func (*Signature) ProtoMessage() {} func (*Signature) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{17} + return fileDescriptor_b6d125f880f9ca35, []int{19} } func (m *Signature) XXX_Unmarshal(b []byte) error { @@ -3359,7 +3665,7 @@ func (m *SignedListing) Reset() { *m = SignedListing{} } func (m *SignedListing) String() string { return proto.CompactTextString(m) } func (*SignedListing) ProtoMessage() {} func (*SignedListing) Descriptor() ([]byte, []int) { - return fileDescriptor_b6d125f880f9ca35, []int{18} + return fileDescriptor_b6d125f880f9ca35, []int{20} } func (m *SignedListing) XXX_Unmarshal(b []byte) error { @@ -3408,6 +3714,7 @@ func init() { proto.RegisterEnum("Order_Payment_Method", Order_Payment_Method_name, Order_Payment_Method_value) proto.RegisterEnum("Signature_Section", Signature_Section_name, Signature_Section_value) proto.RegisterType((*RicardianContract)(nil), "RicardianContract") + proto.RegisterType((*CurrencyDefinition)(nil), "CurrencyDefinition") proto.RegisterType((*Listing)(nil), "Listing") proto.RegisterType((*Listing_Metadata)(nil), "Listing.Metadata") proto.RegisterType((*Listing_Item)(nil), "Listing.Item") @@ -3437,6 +3744,7 @@ func init() { proto.RegisterType((*OrderFulfillment_CryptocurrencyDelivery)(nil), "OrderFulfillment.CryptocurrencyDelivery") proto.RegisterType((*OrderFulfillment_Payout)(nil), "OrderFulfillment.Payout") proto.RegisterType((*OrderCompletion)(nil), "OrderCompletion") + proto.RegisterType((*OrderProcessingFailure)(nil), "OrderProcessingFailure") proto.RegisterType((*Rating)(nil), "Rating") proto.RegisterType((*Rating_RatingData)(nil), "Rating.RatingData") proto.RegisterType((*Dispute)(nil), "Dispute") @@ -3454,215 +3762,241 @@ func init() { proto.RegisterType((*SignedListing)(nil), "SignedListing") } -func init() { proto.RegisterFile("contracts.proto", fileDescriptor_b6d125f880f9ca35) } +func init() { + proto.RegisterFile("contracts.proto", fileDescriptor_b6d125f880f9ca35) +} var fileDescriptor_b6d125f880f9ca35 = []byte{ - // 3307 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5a, 0xbd, 0x73, 0x5b, 0xc7, - 0xb5, 0x17, 0xbe, 0x81, 0x43, 0x90, 0x04, 0x57, 0xb4, 0x8c, 0x87, 0xf1, 0xb3, 0x28, 0x8c, 0xac, - 0x47, 0xcb, 0x32, 0x2c, 0xf3, 0xbd, 0x79, 0xa3, 0x89, 0x33, 0xb6, 0x49, 0x00, 0x34, 0x61, 0x51, - 0x24, 0xb3, 0x80, 0x9c, 0x38, 0x8d, 0x72, 0x79, 0xef, 0x12, 0xdc, 0x08, 0xb8, 0x17, 0xbe, 0x77, - 0x2f, 0x45, 0x24, 0x55, 0xba, 0x14, 0x99, 0x49, 0xe1, 0xc2, 0x45, 0xba, 0x54, 0xf9, 0x1f, 0xe2, - 0x2a, 0x6d, 0x26, 0x4d, 0x8a, 0x8c, 0x53, 0xa5, 0xc9, 0x1f, 0xe0, 0x26, 0x93, 0x22, 0x4d, 0x66, - 0xcf, 0xee, 0xde, 0x2f, 0x80, 0xb2, 0xe4, 0x4c, 0x26, 0x15, 0xef, 0xf9, 0x9d, 0xb3, 0x7b, 0xf7, - 0x9e, 0x3d, 0xdf, 0x20, 0xac, 0xdb, 0x9e, 0x2b, 0x7c, 0xcb, 0x16, 0x41, 0x67, 0xe6, 0x7b, 0xc2, - 0x6b, 0x11, 0xdb, 0x0b, 0x5d, 0xe1, 0xcf, 0x6d, 0xcf, 0x61, 0x06, 0xbb, 0x39, 0xf6, 0xbc, 0xf1, - 0x84, 0xbd, 0x83, 0xd4, 0x69, 0x78, 0xf6, 0x8e, 0xe0, 0x53, 0x16, 0x08, 0x6b, 0x3a, 0x53, 0x02, - 0xed, 0x3f, 0x17, 0x61, 0x83, 0x72, 0xdb, 0xf2, 0x1d, 0x6e, 0xb9, 0x5d, 0xbd, 0x23, 0xb9, 0x0f, - 0x6b, 0x17, 0xcc, 0x75, 0x3c, 0xff, 0x90, 0x07, 0x82, 0xbb, 0xe3, 0xa0, 0x99, 0xdb, 0x2a, 0x6c, - 0xaf, 0xec, 0x54, 0x3b, 0x1a, 0xa0, 0x19, 0x3e, 0xb9, 0x03, 0x70, 0x1a, 0xce, 0x99, 0x7f, 0xec, - 0x3b, 0xcc, 0x6f, 0xe6, 0xb7, 0x72, 0xdb, 0x2b, 0x3b, 0xe5, 0x0e, 0x52, 0x34, 0xc1, 0x21, 0x87, - 0xf0, 0xaa, 0x5a, 0x89, 0x64, 0xd7, 0x73, 0xcf, 0xb8, 0x3f, 0xb5, 0x04, 0xf7, 0xdc, 0x66, 0x01, - 0x17, 0x91, 0xce, 0x02, 0x87, 0x5e, 0xb5, 0x84, 0x0c, 0xe0, 0x46, 0x82, 0xb5, 0x1f, 0x4e, 0xce, - 0xf8, 0x64, 0x32, 0x65, 0xae, 0x68, 0x16, 0xf1, 0xbc, 0x1b, 0x9d, 0x2c, 0x83, 0x5e, 0xb1, 0x80, - 0xf4, 0x60, 0x33, 0x3e, 0x66, 0xd7, 0x9b, 0xce, 0x26, 0x0c, 0x4f, 0x55, 0xc2, 0x53, 0x35, 0x3a, - 0x19, 0x9c, 0x2e, 0x95, 0x26, 0x6d, 0xa8, 0x38, 0x3c, 0x98, 0x85, 0x82, 0x35, 0xcb, 0xb8, 0xb0, - 0xda, 0xe9, 0x29, 0x9a, 0x1a, 0x06, 0xf9, 0x10, 0x36, 0xf4, 0x23, 0x65, 0x81, 0x37, 0x09, 0xf1, - 0x35, 0x15, 0xfd, 0xf1, 0xbd, 0x2c, 0x87, 0x2e, 0x0a, 0x27, 0x76, 0xd8, 0xb5, 0x6d, 0x36, 0x13, - 0x96, 0x6b, 0xb3, 0x66, 0x35, 0xbd, 0x43, 0xcc, 0xa1, 0x8b, 0xc2, 0xe4, 0x26, 0x94, 0x7d, 0x76, - 0x16, 0xba, 0x4e, 0xb3, 0x86, 0xcb, 0x2a, 0x1d, 0x8a, 0x24, 0xd5, 0x30, 0xb9, 0x0b, 0x10, 0xf0, - 0xb1, 0x6b, 0x89, 0xd0, 0x67, 0x41, 0x13, 0x50, 0x9b, 0xd0, 0x19, 0x1a, 0x88, 0x26, 0xb8, 0xe4, - 0x06, 0x94, 0x99, 0xef, 0x7b, 0x7e, 0xd0, 0x5c, 0xd9, 0x2a, 0x6c, 0xd7, 0xa8, 0xa6, 0xda, 0x5f, - 0x6f, 0x42, 0x45, 0x1b, 0x08, 0x21, 0x50, 0x0c, 0x26, 0xe1, 0xb8, 0x99, 0xdb, 0xca, 0x6d, 0xd7, - 0x28, 0x3e, 0x93, 0x9b, 0x50, 0x55, 0x97, 0x31, 0xe8, 0x69, 0x8b, 0x29, 0x74, 0x06, 0x3d, 0x1a, - 0x81, 0xe4, 0x6d, 0xa8, 0x4e, 0x99, 0xb0, 0x1c, 0x4b, 0x58, 0xda, 0x3a, 0x36, 0x8c, 0x01, 0x76, - 0x1e, 0x69, 0x06, 0x8d, 0x44, 0xc8, 0x2d, 0x28, 0x72, 0xc1, 0xa6, 0xcd, 0x22, 0x8a, 0xae, 0x46, - 0xa2, 0x03, 0xc1, 0xa6, 0x14, 0x59, 0x64, 0x17, 0xd6, 0x83, 0x73, 0x3e, 0x9b, 0x71, 0x77, 0x7c, - 0x3c, 0x93, 0xba, 0x0c, 0x9a, 0x25, 0xfc, 0xb6, 0x57, 0x23, 0xe9, 0x61, 0x8a, 0x4f, 0xb3, 0xf2, - 0xa4, 0x0d, 0x25, 0x61, 0x5d, 0xb2, 0xa0, 0x59, 0xc6, 0x85, 0xf5, 0x68, 0xe1, 0xc8, 0xba, 0xa4, - 0x8a, 0x45, 0xde, 0x84, 0x8a, 0xed, 0x85, 0x33, 0xb9, 0x7d, 0x05, 0xa5, 0xd6, 0x23, 0xa9, 0x2e, - 0xe2, 0xd4, 0xf0, 0xc9, 0xeb, 0x00, 0x53, 0xcf, 0x61, 0xbe, 0x25, 0xa4, 0x02, 0xab, 0xa8, 0xc0, - 0x04, 0x42, 0x3a, 0x40, 0x04, 0xf3, 0xa7, 0xc1, 0xae, 0xeb, 0x74, 0x3d, 0xd7, 0xe1, 0xea, 0xd0, - 0x35, 0x54, 0xe3, 0x12, 0x0e, 0x69, 0x43, 0x5d, 0x5d, 0xe1, 0x89, 0x37, 0xe1, 0xf6, 0xbc, 0x09, - 0x28, 0x99, 0xc2, 0x48, 0x13, 0x2a, 0x82, 0x05, 0xc2, 0x65, 0xa2, 0xb9, 0xb2, 0x95, 0xdb, 0xae, - 0x52, 0x43, 0xb6, 0xfe, 0x56, 0x84, 0xaa, 0xd1, 0xac, 0x14, 0xbb, 0x60, 0x7e, 0x20, 0xcd, 0x53, - 0x5e, 0xdb, 0x2a, 0x35, 0x24, 0xd9, 0x83, 0xba, 0x89, 0x3e, 0xa3, 0xf9, 0x8c, 0xe1, 0xed, 0xad, - 0xed, 0xbc, 0xbe, 0x70, 0x39, 0x9d, 0x6e, 0x42, 0x8a, 0xa6, 0xd6, 0x90, 0xfb, 0x50, 0x3e, 0xf3, - 0xa4, 0x23, 0xe3, 0xd5, 0xae, 0xed, 0x34, 0x17, 0x57, 0xef, 0x23, 0x9f, 0x6a, 0x39, 0xb2, 0x03, - 0x65, 0x76, 0x39, 0xe3, 0xfe, 0x5c, 0xdf, 0x70, 0xab, 0xa3, 0xa2, 0x5b, 0xc7, 0x44, 0xb7, 0xce, - 0xc8, 0x44, 0x37, 0xaa, 0x25, 0xa5, 0xfa, 0x2c, 0x34, 0x7b, 0xe6, 0x74, 0x43, 0xdf, 0x67, 0xae, - 0xcd, 0x99, 0xba, 0xf3, 0x1a, 0x5d, 0xc2, 0x21, 0xdb, 0xb0, 0x3e, 0xf3, 0xb9, 0xcd, 0xdd, 0xb1, - 0x06, 0xe7, 0xe8, 0xc8, 0x35, 0x9a, 0x85, 0x49, 0x0b, 0xaa, 0x13, 0xcb, 0x1d, 0x87, 0xd6, 0x98, - 0xa1, 0xf7, 0xd6, 0x68, 0x44, 0xcb, 0xb7, 0xb2, 0xc0, 0xf6, 0xbd, 0x67, 0xf2, 0x40, 0x5e, 0x28, - 0x0e, 0xbc, 0x10, 0x2f, 0x57, 0x2a, 0x71, 0x09, 0x47, 0xee, 0x65, 0x7b, 0xdc, 0x45, 0x5d, 0xaa, - 0xab, 0x8d, 0x68, 0x72, 0x17, 0x1a, 0xf2, 0xb9, 0xc7, 0x2f, 0x78, 0xc0, 0x4f, 0xf9, 0x84, 0x0b, - 0x75, 0xa9, 0xab, 0x74, 0x01, 0x27, 0xb7, 0x61, 0x55, 0x1e, 0x93, 0x3d, 0xf2, 0x1c, 0x7e, 0xc6, - 0x99, 0x8f, 0xd7, 0x9b, 0xa7, 0x69, 0xb0, 0xed, 0x40, 0x3d, 0x79, 0x2f, 0x64, 0x03, 0x56, 0x4f, - 0x0e, 0x3e, 0x1d, 0x0e, 0xba, 0xbb, 0x87, 0x4f, 0x3e, 0x3a, 0x3e, 0xee, 0x35, 0xae, 0x91, 0x06, - 0xd4, 0x7b, 0x83, 0x8f, 0x06, 0x23, 0x83, 0xe4, 0xc8, 0x0a, 0x54, 0x86, 0x7d, 0xfa, 0xc9, 0xa0, - 0xdb, 0x6f, 0xe4, 0xc9, 0x1a, 0x40, 0x97, 0x1e, 0x7f, 0xbf, 0xf7, 0x64, 0xff, 0xf1, 0x51, 0xaf, - 0x51, 0x20, 0x04, 0xd6, 0xba, 0xf4, 0xd3, 0x93, 0xd1, 0x71, 0xf7, 0x31, 0xa5, 0xfd, 0xa3, 0xee, - 0xa7, 0x8d, 0x62, 0xfb, 0x2d, 0x28, 0xab, 0xfb, 0x23, 0xeb, 0xb0, 0xb2, 0x3f, 0xf8, 0x41, 0xbf, - 0xf7, 0xe4, 0x84, 0xca, 0xe5, 0xb8, 0xfb, 0xa3, 0x5d, 0xfa, 0xb0, 0x3f, 0xd2, 0x48, 0xbe, 0xf5, - 0x97, 0x32, 0x14, 0xa5, 0x9b, 0x92, 0x4d, 0x28, 0x09, 0x2e, 0x26, 0x4c, 0x07, 0x0a, 0x45, 0x90, - 0x2d, 0x58, 0x71, 0xa4, 0xda, 0x38, 0xfa, 0x20, 0x9a, 0x5b, 0x8d, 0x26, 0x21, 0x72, 0x07, 0xd6, - 0x66, 0xbe, 0x67, 0xb3, 0x20, 0xe0, 0xee, 0x58, 0xea, 0x16, 0xad, 0xaa, 0x46, 0x33, 0xa8, 0xdc, - 0x1f, 0x95, 0x81, 0x26, 0x54, 0xa4, 0x8a, 0x90, 0xd1, 0xc9, 0x0d, 0xce, 0x9e, 0x61, 0xb0, 0xaf, - 0x52, 0x7c, 0x96, 0x98, 0xb0, 0xc6, 0xca, 0xcd, 0x6b, 0x14, 0x9f, 0xc9, 0x5b, 0x50, 0xe6, 0x53, - 0x6b, 0xcc, 0x8c, 0x5b, 0x5f, 0x4f, 0xc5, 0x98, 0xce, 0x40, 0xf2, 0xa8, 0x16, 0x91, 0x9e, 0x6d, - 0x5b, 0x82, 0x8d, 0x3d, 0x5f, 0x9a, 0x9c, 0xf6, 0xec, 0x18, 0x91, 0x47, 0x19, 0xfb, 0xd6, 0x54, - 0x39, 0x73, 0x9e, 0x2a, 0x82, 0xbc, 0x06, 0x35, 0xdb, 0x78, 0xb3, 0x76, 0xde, 0x18, 0x20, 0x1d, - 0xa8, 0x78, 0x3a, 0x6e, 0xad, 0xe0, 0x09, 0x36, 0xd3, 0x27, 0xd0, 0x41, 0xcb, 0x08, 0x91, 0x37, - 0xa0, 0x18, 0x3c, 0x0d, 0x83, 0x66, 0x5d, 0xa7, 0xc3, 0x94, 0xf0, 0xf0, 0x69, 0x48, 0x91, 0xdd, - 0xfa, 0x5d, 0x0e, 0xca, 0x6a, 0x29, 0xaa, 0xc2, 0x9a, 0x1a, 0xfd, 0xe3, 0xf3, 0x0b, 0xa8, 0xff, - 0x01, 0x54, 0x2f, 0x2c, 0x9f, 0x5b, 0xae, 0x08, 0x9a, 0x05, 0x7c, 0xd7, 0x6b, 0xcb, 0x0e, 0xd6, - 0xf9, 0x44, 0x09, 0xd1, 0x48, 0xba, 0x75, 0x00, 0x15, 0x0d, 0x2e, 0x7d, 0xf5, 0x9b, 0x50, 0x42, - 0x75, 0xea, 0x04, 0xb1, 0x54, 0xe1, 0x4a, 0xa2, 0xf5, 0xb3, 0x1c, 0x14, 0x86, 0x4f, 0x43, 0x19, - 0x01, 0xf5, 0xee, 0x5d, 0x6f, 0x7a, 0xea, 0x61, 0xe9, 0xb2, 0x4a, 0x53, 0x98, 0xd4, 0xf2, 0xcc, - 0xf7, 0x9c, 0xd0, 0x16, 0x3a, 0xf7, 0xd4, 0x68, 0x0c, 0x48, 0x6e, 0x10, 0xfa, 0xf6, 0xb9, 0xe5, - 0x8f, 0x95, 0x1d, 0x15, 0x68, 0x0c, 0x48, 0x67, 0xfd, 0x2c, 0xb4, 0x5c, 0x21, 0x1d, 0xb1, 0x88, - 0xcc, 0x88, 0x6e, 0x7d, 0x91, 0x83, 0x12, 0x1e, 0x4a, 0x4a, 0x9d, 0xf1, 0x09, 0x4b, 0x7c, 0x50, - 0x44, 0x4b, 0x9e, 0xe7, 0xf3, 0x31, 0x77, 0xad, 0x89, 0x7e, 0x79, 0x44, 0x4b, 0xab, 0x98, 0x44, - 0xef, 0xad, 0x51, 0x45, 0xc8, 0x14, 0x3b, 0x65, 0x0e, 0x0f, 0x55, 0x72, 0xab, 0x51, 0x4d, 0x49, - 0xe9, 0x60, 0x6a, 0x4d, 0x26, 0x68, 0xb9, 0x35, 0xaa, 0x08, 0x34, 0x5d, 0xee, 0x9a, 0xc8, 0x85, - 0xcf, 0xad, 0x5f, 0x14, 0x60, 0x2d, 0x9d, 0xda, 0x96, 0xea, 0xfb, 0x01, 0x14, 0x45, 0x1c, 0xd1, - 0x6f, 0x5f, 0x91, 0x15, 0x23, 0x12, 0xe3, 0x3a, 0xae, 0x20, 0x77, 0xa0, 0xe2, 0xb3, 0x31, 0x9a, - 0xa6, 0xb4, 0x80, 0xb5, 0x9d, 0xba, 0xcc, 0x75, 0xb2, 0x20, 0xed, 0x7a, 0x0e, 0xa3, 0x86, 0x49, - 0xde, 0x83, 0x6a, 0xc0, 0xfc, 0x0b, 0x6e, 0x33, 0x93, 0x7b, 0x6f, 0x5e, 0xf9, 0x16, 0x25, 0x47, - 0xa3, 0x05, 0xad, 0xcf, 0x73, 0x50, 0xd1, 0xe8, 0xd2, 0xe3, 0x47, 0xee, 0x9d, 0x4f, 0xba, 0xf7, - 0x3d, 0xd8, 0x60, 0x81, 0xe0, 0x53, 0x4b, 0x30, 0xa7, 0xc7, 0x26, 0xfc, 0x82, 0xf9, 0x73, 0xad, - 0xdf, 0x45, 0x06, 0xb9, 0x0f, 0xd7, 0x2d, 0x47, 0xf9, 0x9b, 0x35, 0x91, 0x66, 0x76, 0x92, 0x08, - 0x18, 0xcb, 0x58, 0xed, 0x77, 0xa1, 0x9e, 0x54, 0x88, 0x8c, 0x6f, 0x87, 0xc7, 0x32, 0x9a, 0x9e, - 0x0c, 0xba, 0x0f, 0x1f, 0x9f, 0x34, 0xae, 0x65, 0x43, 0x60, 0xae, 0xf5, 0xcb, 0x1c, 0x14, 0x46, - 0xd6, 0x25, 0xa6, 0x62, 0xeb, 0x12, 0x03, 0xbf, 0xfa, 0x0e, 0x43, 0x92, 0x7b, 0x00, 0xc2, 0xba, - 0xa4, 0x5a, 0xa5, 0xf9, 0x25, 0x2a, 0x4d, 0xf0, 0xa5, 0x8b, 0x0a, 0xeb, 0xd2, 0x9c, 0x02, 0x3f, - 0xae, 0x4a, 0x93, 0x90, 0x0c, 0x47, 0x33, 0xe6, 0xdb, 0xcc, 0x15, 0xd2, 0x9d, 0x8a, 0x18, 0x73, - 0x12, 0x08, 0xc6, 0x00, 0x55, 0x9c, 0x5c, 0x11, 0x84, 0x37, 0xa1, 0x78, 0x6e, 0x05, 0xe7, 0xca, - 0x62, 0x0f, 0xae, 0x51, 0xa4, 0xc8, 0x6d, 0xa8, 0x3b, 0x3c, 0xc0, 0xd6, 0x43, 0x1e, 0x4a, 0xa9, - 0xf5, 0xe0, 0x1a, 0x4d, 0xa1, 0xe4, 0x2e, 0xac, 0xeb, 0x57, 0xf5, 0x34, 0x8c, 0x16, 0x9b, 0x3f, - 0xc8, 0xd1, 0x2c, 0x83, 0xdc, 0xd1, 0x49, 0x2c, 0x92, 0x94, 0x66, 0x5c, 0x3c, 0xc8, 0xd1, 0x34, - 0xbc, 0x57, 0x86, 0xa2, 0x6c, 0x75, 0xf6, 0x00, 0xaa, 0xe6, 0x5d, 0xed, 0xdf, 0x03, 0x94, 0x54, - 0xa3, 0x71, 0x1b, 0x56, 0x55, 0xcd, 0xb3, 0xeb, 0x38, 0x3e, 0x0b, 0x02, 0xfd, 0x2d, 0x69, 0x50, - 0x7a, 0xba, 0x02, 0xf6, 0x99, 0xb1, 0x99, 0x18, 0x20, 0x6f, 0x41, 0x35, 0x48, 0x6a, 0x54, 0xd6, - 0x71, 0xb8, 0x7b, 0x64, 0xa8, 0x34, 0x12, 0x20, 0xff, 0x0d, 0x15, 0x6c, 0x09, 0x06, 0x3d, 0x5d, - 0x9e, 0x60, 0x31, 0x6b, 0x30, 0xf2, 0x00, 0x6a, 0x51, 0xef, 0xa5, 0x9b, 0x8a, 0xe7, 0xd5, 0x2f, - 0xb1, 0x30, 0xb9, 0x05, 0x25, 0x59, 0xbb, 0x9a, 0x82, 0x73, 0x45, 0x1f, 0x01, 0xab, 0x5a, 0xc5, - 0x21, 0xdb, 0x50, 0x99, 0x59, 0x73, 0x6c, 0x7c, 0x54, 0x23, 0xb1, 0xa6, 0x85, 0x4e, 0x14, 0x4a, - 0x0d, 0x5b, 0x5a, 0x81, 0x6f, 0x49, 0x5f, 0x7b, 0xc8, 0xe6, 0x2a, 0x29, 0xd5, 0x69, 0x02, 0x21, - 0x3b, 0xb0, 0x69, 0x4d, 0x04, 0xf3, 0x5d, 0x4b, 0x30, 0x59, 0x24, 0x58, 0xb6, 0x18, 0xb8, 0x67, - 0x9e, 0xae, 0x4a, 0x96, 0xf2, 0x92, 0x75, 0x22, 0xa4, 0xea, 0xc4, 0xd6, 0x1f, 0x73, 0x50, 0x8d, - 0x0c, 0xf0, 0x06, 0x94, 0xa5, 0xb2, 0x46, 0x9e, 0xbe, 0x0a, 0x4d, 0xc9, 0xe5, 0x96, 0xbe, 0x23, - 0x15, 0x0c, 0x0d, 0x29, 0x3d, 0xdc, 0x96, 0x51, 0x56, 0xb9, 0x2a, 0x3e, 0x63, 0xc4, 0x13, 0x96, - 0x60, 0x3a, 0x10, 0x2a, 0x02, 0x8d, 0xdb, 0x0b, 0x84, 0x35, 0x41, 0x1b, 0x54, 0xc1, 0x30, 0x81, - 0xc8, 0xe0, 0xa4, 0xbb, 0x63, 0xb4, 0xa6, 0x85, 0xe0, 0xa4, 0x99, 0x32, 0x77, 0xe8, 0x97, 0x1f, - 0x79, 0x02, 0xd3, 0x3c, 0x56, 0xcf, 0x49, 0xac, 0xf5, 0x9b, 0x82, 0xae, 0x55, 0xb6, 0x60, 0x65, - 0xa2, 0x02, 0xd7, 0x81, 0xf4, 0x0b, 0xf5, 0x55, 0x49, 0x28, 0x95, 0x2a, 0xf2, 0xa8, 0x9a, 0x88, - 0x96, 0x47, 0x36, 0xcf, 0xff, 0xff, 0x7f, 0x58, 0x1b, 0x16, 0x69, 0x02, 0x21, 0xf7, 0xe2, 0x54, - 0xaf, 0x32, 0x2a, 0x49, 0x5c, 0xfc, 0x42, 0xa2, 0xdf, 0x83, 0xb5, 0x74, 0xa3, 0x12, 0xd5, 0xc8, - 0x89, 0x45, 0x99, 0xd6, 0x26, 0xb3, 0x42, 0xaa, 0x7b, 0xca, 0xa6, 0x9e, 0x56, 0x1f, 0x3e, 0xcb, - 0x6f, 0x54, 0x9d, 0x8a, 0xd4, 0x93, 0x29, 0x86, 0x92, 0x10, 0x56, 0x5e, 0xca, 0xb8, 0x8c, 0xa7, - 0x55, 0x74, 0xe5, 0x95, 0x42, 0x5b, 0x3b, 0xcf, 0x2d, 0x31, 0x36, 0xa1, 0x74, 0x61, 0x4d, 0x42, - 0xa6, 0x4d, 0x40, 0x11, 0xad, 0xf7, 0x5f, 0x28, 0x67, 0x35, 0xa1, 0xa2, 0x13, 0x84, 0x31, 0x20, - 0x4d, 0xb6, 0xbe, 0xcc, 0x43, 0x45, 0xbb, 0x00, 0x79, 0x5b, 0xa6, 0x50, 0x71, 0xee, 0x39, 0xb8, - 0x76, 0x6d, 0xe7, 0x95, 0xb4, 0x8b, 0xc8, 0xae, 0xe3, 0xdc, 0x73, 0xa8, 0x16, 0x92, 0x91, 0x21, - 0xea, 0xc2, 0x4c, 0x85, 0x10, 0x01, 0xd2, 0x96, 0xad, 0x29, 0x06, 0xa7, 0x02, 0x5e, 0x9c, 0xa6, - 0xb0, 0x7a, 0x3b, 0xb7, 0xb8, 0x2b, 0x03, 0x93, 0xb6, 0xd0, 0x18, 0x48, 0x5a, 0x7a, 0x29, 0x6d, - 0xe9, 0xd8, 0xb5, 0x39, 0x8c, 0x4d, 0x87, 0x58, 0x52, 0xe9, 0xcc, 0x9d, 0xc2, 0xa4, 0x4c, 0x74, - 0x80, 0x87, 0x6c, 0x8e, 0x6a, 0xae, 0xd3, 0x14, 0x86, 0x1e, 0xe3, 0x71, 0x17, 0xcd, 0x49, 0x7a, - 0x8c, 0xc7, 0xdd, 0xf6, 0x03, 0x28, 0xab, 0x6f, 0x23, 0xd7, 0x61, 0x7d, 0xb7, 0xd7, 0xa3, 0xfd, - 0xe1, 0xf0, 0x09, 0xed, 0x7f, 0xef, 0x71, 0x7f, 0x38, 0x6a, 0x5c, 0x23, 0x00, 0xe5, 0xde, 0x80, - 0xf6, 0xbb, 0xa3, 0x46, 0x8e, 0xac, 0x42, 0xed, 0xd1, 0x71, 0xaf, 0x4f, 0x77, 0x47, 0xfd, 0x5e, - 0x23, 0xdf, 0xfe, 0x7b, 0x0e, 0x36, 0x16, 0x87, 0x2e, 0x4d, 0xa8, 0x78, 0x12, 0x1c, 0xf4, 0x4c, - 0xca, 0xd2, 0x64, 0x3a, 0xc6, 0xe5, 0x5f, 0x26, 0xc6, 0x2d, 0x1a, 0x51, 0x61, 0x99, 0x11, 0xc9, - 0xf6, 0xcc, 0x67, 0x9f, 0x85, 0x2c, 0x10, 0xcc, 0xd9, 0x55, 0x17, 0xa0, 0xf2, 0x72, 0x16, 0x26, - 0xdf, 0x85, 0x86, 0x0a, 0x6b, 0xc3, 0x78, 0x8c, 0xa1, 0xca, 0x8d, 0x46, 0x87, 0xa6, 0x19, 0x74, - 0x41, 0xb2, 0xfd, 0xf3, 0x1c, 0xac, 0xa8, 0xe1, 0x15, 0xfb, 0x31, 0xb3, 0xc5, 0xbf, 0xe5, 0x9b, - 0x65, 0x6d, 0xce, 0xc7, 0xc6, 0xbb, 0x37, 0x3a, 0x7b, 0x5c, 0xc8, 0xfb, 0x8a, 0x8f, 0x85, 0xec, - 0xf6, 0x57, 0x05, 0x58, 0xcf, 0x1c, 0x98, 0x7c, 0x98, 0x18, 0x8c, 0xe4, 0xf0, 0x9d, 0xb7, 0xb3, - 0x1f, 0xd5, 0x19, 0xf9, 0x96, 0x1b, 0x58, 0xb6, 0xbc, 0xb2, 0x25, 0xb3, 0x12, 0x59, 0xe2, 0x1a, - 0x51, 0x3c, 0x76, 0x9d, 0xc6, 0x40, 0xeb, 0xaf, 0x79, 0xb8, 0xbe, 0x64, 0x7d, 0x22, 0xe2, 0x0d, - 0xe3, 0x61, 0x4e, 0x12, 0xc2, 0x84, 0x6a, 0xb2, 0x89, 0xd9, 0x37, 0x02, 0x16, 0x4c, 0xb8, 0xb0, - 0xc4, 0x84, 0xdb, 0x50, 0xd7, 0x1b, 0x8e, 0xb0, 0x06, 0x51, 0x5e, 0x94, 0xc2, 0xc8, 0x01, 0xd4, - 0xc4, 0x79, 0x38, 0x3d, 0x75, 0x2d, 0x3e, 0xd1, 0xc9, 0xf4, 0xee, 0x8b, 0x28, 0x40, 0x37, 0x0c, - 0xf1, 0xe2, 0xd6, 0x4f, 0x4d, 0xbd, 0x6e, 0x6a, 0xe6, 0x5c, 0x5c, 0x33, 0xc7, 0xd5, 0x75, 0x3e, - 0x59, 0x5d, 0xc7, 0xb5, 0x78, 0x21, 0x5b, 0x8b, 0xab, 0xca, 0xbd, 0x98, 0xac, 0xdc, 0x93, 0xb5, - 0x7e, 0x29, 0x5d, 0xeb, 0xb7, 0x4f, 0xa0, 0x91, 0xbd, 0x74, 0x99, 0x16, 0xb8, 0x3b, 0x0b, 0xc5, - 0xc0, 0x75, 0xd8, 0xa5, 0x9e, 0xbb, 0x24, 0x90, 0xe7, 0x5f, 0x5c, 0xfb, 0x4f, 0x65, 0x68, 0x2c, - 0x8c, 0x36, 0x23, 0xe3, 0x75, 0xd2, 0xc6, 0xeb, 0x44, 0x53, 0xb9, 0x7c, 0x62, 0x2a, 0x97, 0x32, - 0xe8, 0xc2, 0xcb, 0x18, 0xf4, 0x11, 0x34, 0x66, 0xe7, 0xf3, 0x80, 0xdb, 0xd6, 0x24, 0xaa, 0xb2, - 0xd5, 0x1c, 0xb6, 0xbd, 0x30, 0x87, 0xed, 0x9c, 0x64, 0x24, 0xe9, 0xc2, 0x5a, 0xf2, 0x10, 0xd6, - 0x1d, 0x3e, 0xe6, 0x22, 0xb1, 0x9d, 0xf2, 0xe0, 0x5b, 0x8b, 0xdb, 0xf5, 0xd2, 0x82, 0x34, 0xbb, - 0x92, 0xdc, 0x87, 0xf2, 0xcc, 0x9a, 0x7b, 0xa1, 0xd0, 0x83, 0xd9, 0xe6, 0x92, 0x23, 0x21, 0x9f, - 0x6a, 0x39, 0xf2, 0x1d, 0x58, 0xcf, 0xc4, 0x05, 0x5d, 0x5c, 0x2d, 0x06, 0x90, 0xac, 0x20, 0xa6, - 0x29, 0x4f, 0x30, 0x13, 0x87, 0xe5, 0x33, 0xf9, 0x11, 0xdc, 0xb0, 0xfd, 0xf9, 0x4c, 0x78, 0xb6, - 0x1e, 0x21, 0x45, 0x5f, 0x55, 0xc3, 0xaf, 0xda, 0x5e, 0x3c, 0x51, 0x77, 0xa9, 0x3c, 0xbd, 0x62, - 0x9f, 0xd6, 0x08, 0x1a, 0x59, 0xb5, 0x62, 0x72, 0x94, 0x29, 0x94, 0xf9, 0xe6, 0xf2, 0x35, 0x29, - 0x63, 0xae, 0xf0, 0x2d, 0xfb, 0x29, 0x77, 0xc7, 0x47, 0xe1, 0xf4, 0x94, 0x99, 0x34, 0x97, 0x41, - 0x5b, 0x1f, 0xc0, 0x7a, 0x46, 0xbb, 0xa4, 0x01, 0x85, 0xd0, 0x9f, 0xe8, 0x0d, 0xe5, 0xa3, 0x34, - 0xf3, 0x99, 0x15, 0x04, 0xcf, 0x3c, 0xdf, 0x31, 0x2d, 0xad, 0xa1, 0x5b, 0xef, 0xc3, 0x8d, 0xe5, - 0x1f, 0x22, 0x8b, 0x74, 0x11, 0x7b, 0x69, 0x14, 0x5c, 0xd3, 0xa0, 0x6c, 0xec, 0xcb, 0xea, 0x6e, - 0xa2, 0x98, 0x99, 0x7b, 0x6e, 0xcc, 0xc4, 0x39, 0x18, 0x2e, 0xd8, 0x4d, 0x15, 0x96, 0x69, 0x90, - 0xdc, 0x85, 0x86, 0x02, 0xf6, 0x19, 0x3b, 0x61, 0xfe, 0xde, 0x5c, 0x30, 0x9d, 0xce, 0x17, 0xf0, - 0xf6, 0x6f, 0x73, 0xb0, 0x9e, 0x1d, 0xf6, 0x5f, 0xed, 0x57, 0xdf, 0x3e, 0x29, 0xbc, 0x0b, 0xa0, - 0xde, 0x3d, 0x7c, 0x6e, 0x6a, 0x48, 0x08, 0x91, 0x5b, 0x50, 0x51, 0xe6, 0x17, 0x68, 0x6f, 0xab, - 0x68, 0xfb, 0xa4, 0x06, 0x6f, 0xff, 0xa1, 0x08, 0x65, 0x85, 0x91, 0x1d, 0xd3, 0x00, 0xf4, 0xe2, - 0xe4, 0x41, 0xf4, 0x02, 0xfd, 0x47, 0x72, 0x68, 0x42, 0xea, 0x1b, 0x92, 0xc5, 0xd7, 0x05, 0x00, - 0x9a, 0x12, 0x8e, 0x33, 0x40, 0x2e, 0x9b, 0x01, 0xbe, 0x71, 0xe6, 0xdf, 0x81, 0x9a, 0x7a, 0x1e, - 0x72, 0xd3, 0x74, 0x2d, 0xfa, 0x5b, 0x2c, 0xf2, 0x4d, 0x6d, 0xd7, 0x6b, 0x50, 0xc3, 0xc7, 0x23, - 0x59, 0x34, 0xaa, 0xf8, 0x1b, 0x03, 0xd2, 0x6a, 0x91, 0x90, 0xef, 0x2a, 0xe3, 0x51, 0x23, 0x3a, - 0x95, 0xab, 0x24, 0x3f, 0x5b, 0x6e, 0x49, 0x99, 0xd4, 0x3d, 0x57, 0x5f, 0xe6, 0x9e, 0xa5, 0xed, - 0x5c, 0x30, 0x5f, 0x26, 0x97, 0x9a, 0xea, 0x99, 0x34, 0x29, 0x39, 0x9f, 0x85, 0x56, 0x62, 0xcc, - 0x6b, 0xc8, 0xec, 0x18, 0x6e, 0x05, 0xb9, 0xa9, 0x31, 0xdc, 0x6d, 0x58, 0x75, 0xb4, 0x6f, 0x0d, - 0x67, 0x8c, 0x39, 0xcd, 0x3a, 0xca, 0xa4, 0x41, 0x59, 0x44, 0xd9, 0x61, 0x20, 0xbc, 0x29, 0xf3, - 0xf5, 0x2c, 0xa5, 0xb9, 0x8a, 0x72, 0x59, 0x58, 0xa6, 0x3a, 0x9f, 0x5d, 0x70, 0xf6, 0xac, 0xb9, - 0xa6, 0x52, 0x9d, 0xa2, 0xda, 0x5f, 0xe5, 0xa0, 0xa2, 0x7f, 0x67, 0x4a, 0xeb, 0x20, 0xf7, 0x32, - 0x3a, 0xd8, 0x84, 0x92, 0x3d, 0xb1, 0xf8, 0xd4, 0xa4, 0x57, 0x24, 0x16, 0x7d, 0xb7, 0xb0, 0xcc, - 0x77, 0xff, 0x07, 0x6a, 0x5e, 0x28, 0x66, 0x1e, 0x77, 0x85, 0x31, 0xfb, 0x5a, 0xe7, 0x58, 0x23, - 0x34, 0xe6, 0x91, 0x0e, 0x90, 0x80, 0xf9, 0xdc, 0x9a, 0xf0, 0x9f, 0x30, 0xc7, 0x8c, 0xbd, 0xd1, - 0x12, 0xea, 0x74, 0x09, 0xa7, 0xfd, 0xeb, 0x12, 0x6c, 0x2c, 0xfc, 0x08, 0xf7, 0x2f, 0x7c, 0x64, - 0x22, 0x48, 0xe4, 0xd3, 0x41, 0x42, 0xf6, 0xac, 0xbe, 0x37, 0xf3, 0x02, 0xe6, 0xec, 0x99, 0x1e, - 0x37, 0x81, 0x60, 0xab, 0x1e, 0xff, 0x40, 0xa8, 0x8a, 0x8a, 0x04, 0x42, 0xde, 0x8d, 0x32, 0x9a, - 0xaa, 0x80, 0xfe, 0x6b, 0xf1, 0xc7, 0xc3, 0x6c, 0x4a, 0xbb, 0x0f, 0xd7, 0x23, 0xfb, 0x8d, 0x7c, - 0x4a, 0x75, 0x75, 0x75, 0xba, 0x8c, 0xd5, 0xfa, 0xbc, 0xf0, 0xb2, 0xb1, 0xf7, 0x16, 0x94, 0xb1, - 0x5c, 0x51, 0x33, 0xab, 0xd4, 0xb5, 0x68, 0x06, 0xd9, 0x83, 0x15, 0xf5, 0xeb, 0x69, 0x28, 0x66, - 0xa1, 0xd0, 0x5e, 0xbe, 0x75, 0xe5, 0xf1, 0x3b, 0x4a, 0x8e, 0x26, 0x17, 0x91, 0x1e, 0xd4, 0xf5, - 0x2f, 0xb9, 0x6a, 0x93, 0xe2, 0x0b, 0x6e, 0x92, 0x5a, 0x45, 0x3e, 0x86, 0xf5, 0xe8, 0xab, 0xf5, - 0x46, 0xa5, 0x17, 0xdc, 0x28, 0xbb, 0xb0, 0xc5, 0xa1, 0xac, 0x77, 0x6d, 0x42, 0x59, 0xf9, 0xa4, - 0xca, 0x0b, 0x07, 0xd7, 0xa8, 0xa6, 0x49, 0x2b, 0xee, 0x00, 0xcd, 0xa0, 0x2c, 0xea, 0x01, 0xe3, - 0x9e, 0x32, 0x9f, 0xec, 0x29, 0xf7, 0x36, 0x60, 0x5d, 0xad, 0x3e, 0xf6, 0xb5, 0xf5, 0xb7, 0x79, - 0x64, 0xa3, 0x89, 0xdf, 0x74, 0xbf, 0xbd, 0x8d, 0xb6, 0xa0, 0x6a, 0x4f, 0xb4, 0x1d, 0xea, 0xe4, - 0x6d, 0xe8, 0xf6, 0xc7, 0x50, 0x35, 0xf7, 0x27, 0xab, 0x9a, 0xf3, 0x78, 0xd2, 0xa1, 0xe6, 0x7f, - 0x9b, 0x50, 0xe2, 0x58, 0xaa, 0xaa, 0xf9, 0x86, 0x22, 0xe2, 0x76, 0x5e, 0xe5, 0x53, 0x45, 0xb4, - 0x7f, 0x95, 0x87, 0xb2, 0xfa, 0x9d, 0xf9, 0x3f, 0xd8, 0x50, 0x91, 0x3e, 0x6c, 0xa8, 0x11, 0x5f, - 0xa2, 0x41, 0xd0, 0xe6, 0xf3, 0xaa, 0xfe, 0x19, 0x3c, 0xd9, 0x3b, 0x0c, 0xdc, 0x33, 0x8f, 0x2e, - 0xae, 0x58, 0x36, 0x2d, 0x69, 0xbd, 0x07, 0xeb, 0x99, 0x95, 0xd8, 0x57, 0x5c, 0x72, 0x27, 0xea, - 0x2b, 0x2e, 0xb9, 0x93, 0x1e, 0x76, 0x44, 0xda, 0xd9, 0x81, 0x1b, 0x9f, 0xa0, 0x6d, 0xee, 0xcb, - 0xe6, 0x40, 0x06, 0x25, 0x33, 0xba, 0xb8, 0x52, 0x59, 0xed, 0x2f, 0x73, 0x90, 0x1f, 0xf4, 0xa4, - 0xe9, 0xcc, 0x58, 0x82, 0xaf, 0x29, 0x89, 0x9f, 0x5b, 0xae, 0x33, 0x31, 0x83, 0x11, 0x4d, 0x91, - 0x37, 0xa0, 0x32, 0x0b, 0x4f, 0x9f, 0xb2, 0x79, 0xa0, 0x9d, 0x6f, 0xa5, 0x33, 0xe8, 0x75, 0x4e, - 0x14, 0x44, 0x0d, 0x4f, 0x46, 0xa0, 0xd3, 0x48, 0x87, 0xa8, 0xa2, 0x3a, 0x4d, 0x20, 0xad, 0x0f, - 0xa0, 0xa2, 0xd7, 0x48, 0x13, 0xe2, 0x0e, 0x53, 0x93, 0x2e, 0x95, 0xf4, 0x23, 0x5a, 0x1e, 0x5f, - 0x2f, 0xd2, 0xc5, 0x83, 0x21, 0xdb, 0xff, 0xc8, 0x41, 0x2d, 0x2e, 0x9a, 0xef, 0x41, 0x25, 0x60, - 0xea, 0x3a, 0xd4, 0x88, 0x86, 0xc4, 0xff, 0x70, 0xd0, 0x19, 0x2a, 0x0e, 0x35, 0x22, 0xb2, 0x7c, - 0x8d, 0x6a, 0x10, 0x59, 0xa2, 0x05, 0x7a, 0xf3, 0x0c, 0xda, 0xfe, 0x02, 0x7f, 0x32, 0x50, 0x6b, - 0x56, 0xa0, 0x72, 0x38, 0x18, 0x8e, 0x06, 0x47, 0x1f, 0x35, 0xae, 0x91, 0x1a, 0x94, 0x8e, 0x69, - 0xaf, 0x4f, 0x1b, 0x39, 0x72, 0x03, 0x08, 0x3e, 0x3e, 0xe9, 0x1e, 0x1f, 0xed, 0x0f, 0xe8, 0xa3, - 0xdd, 0xd1, 0xe0, 0xf8, 0xa8, 0x91, 0x27, 0xaf, 0xc0, 0x86, 0xc2, 0xf7, 0x1f, 0x1f, 0xee, 0x0f, - 0x0e, 0x0f, 0x1f, 0xf5, 0x8f, 0x46, 0x8d, 0x02, 0xd9, 0x84, 0x86, 0x11, 0x7f, 0x74, 0x72, 0xd8, - 0x47, 0xe1, 0xa2, 0xdc, 0xbc, 0x37, 0x18, 0x9e, 0x3c, 0x1e, 0xf5, 0x1b, 0x25, 0xb9, 0xa3, 0x26, - 0x9e, 0xd0, 0xfe, 0xf0, 0xf8, 0xf0, 0x31, 0x0a, 0x95, 0x09, 0x40, 0x99, 0xf6, 0xf1, 0x57, 0xd3, - 0x4a, 0x9b, 0xc1, 0xaa, 0xfc, 0x3e, 0xe6, 0x98, 0x7f, 0x92, 0x68, 0x43, 0x45, 0xb7, 0xb9, 0xda, - 0x7f, 0xe3, 0xff, 0xb7, 0x31, 0x8c, 0xc8, 0x07, 0xf3, 0x09, 0x1f, 0x4c, 0xd5, 0x67, 0x85, 0x4c, - 0x7d, 0xb6, 0x57, 0xfc, 0x61, 0x7e, 0x76, 0x7a, 0x5a, 0x46, 0xdf, 0xf9, 0xdf, 0x7f, 0x06, 0x00, - 0x00, 0xff, 0xff, 0xfe, 0x1e, 0xab, 0x81, 0x37, 0x24, 0x00, 0x00, + // 3695 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x3a, 0x4b, 0x93, 0x23, 0xc9, + 0x59, 0x53, 0x7a, 0xeb, 0x6b, 0x75, 0x4b, 0x9d, 0xd3, 0xee, 0x11, 0x8a, 0x65, 0xb7, 0xa7, 0x62, + 0xbc, 0xb4, 0x77, 0xc7, 0xe5, 0xd9, 0xc6, 0xb1, 0xb1, 0xc6, 0x84, 0xed, 0x6e, 0x49, 0xbd, 0x2d, + 0xa6, 0x1f, 0x72, 0x4a, 0xb3, 0xb0, 0x5c, 0x86, 0x6a, 0x55, 0xb6, 0x3a, 0x3d, 0x52, 0x95, 0xb6, + 0x1e, 0x3d, 0x2d, 0xb8, 0x10, 0x9c, 0x20, 0x38, 0x70, 0xc3, 0x47, 0xfe, 0x00, 0xc1, 0x1f, 0x80, + 0x13, 0x17, 0x4e, 0x84, 0x23, 0x7c, 0x32, 0x77, 0x0e, 0xdc, 0x20, 0x02, 0x22, 0x88, 0x30, 0x17, + 0x22, 0xbf, 0xcc, 0xac, 0x97, 0xa4, 0xd9, 0x19, 0x13, 0x84, 0x4f, 0xd2, 0xf7, 0xc8, 0xac, 0xcc, + 0xef, 0xfd, 0x7d, 0x55, 0xd0, 0x9c, 0x78, 0x6e, 0xe8, 0xdb, 0x93, 0x30, 0xb0, 0x16, 0xbe, 0x17, + 0x7a, 0x1d, 0x32, 0xf1, 0x22, 0x37, 0xf4, 0x97, 0x13, 0xcf, 0x61, 0x1a, 0xb7, 0x3d, 0x67, 0x41, + 0x60, 0x4f, 0x99, 0x02, 0x3f, 0x98, 0x7a, 0xde, 0x74, 0xc6, 0xbe, 0x83, 0xd0, 0x75, 0x74, 0xf3, + 0x9d, 0x90, 0xcf, 0x59, 0x10, 0xda, 0xf3, 0x85, 0x64, 0x30, 0xff, 0xa5, 0x04, 0xbb, 0x94, 0x4f, + 0x6c, 0xdf, 0xe1, 0xb6, 0xdb, 0x55, 0x0f, 0x20, 0xcf, 0x60, 0xe7, 0x8e, 0xb9, 0x8e, 0xe7, 0x9f, + 0xf3, 0x20, 0xe4, 0xee, 0x34, 0x68, 0x1b, 0x07, 0xc5, 0xc3, 0xad, 0xa3, 0x9a, 0xa5, 0x10, 0x34, + 0x47, 0x27, 0x1f, 0x02, 0x5c, 0x47, 0x4b, 0xe6, 0x5f, 0xf9, 0x0e, 0xf3, 0xdb, 0x85, 0x03, 0xe3, + 0x70, 0xeb, 0xa8, 0x62, 0x21, 0x44, 0x53, 0x14, 0x72, 0x0e, 0x8f, 0xe4, 0x4a, 0x04, 0xbb, 0x9e, + 0x7b, 0xc3, 0xfd, 0xb9, 0x1d, 0x72, 0xcf, 0x6d, 0x17, 0x71, 0x11, 0xb1, 0x56, 0x28, 0x74, 0xd3, + 0x12, 0x32, 0x80, 0xfd, 0x14, 0xe9, 0x34, 0x9a, 0xdd, 0xf0, 0xd9, 0x6c, 0xce, 0xdc, 0xb0, 0x5d, + 0xc2, 0xf3, 0xee, 0x5a, 0x79, 0x02, 0xdd, 0xb0, 0x80, 0xf4, 0x60, 0x2f, 0x39, 0x66, 0xd7, 0x9b, + 0x2f, 0x66, 0x0c, 0x4f, 0x55, 0xc6, 0x53, 0xb5, 0xac, 0x1c, 0x9e, 0xae, 0xe5, 0x26, 0x26, 0x54, + 0x1d, 0x1e, 0x2c, 0xa2, 0x90, 0xb5, 0x2b, 0xb8, 0xb0, 0x66, 0xf5, 0x24, 0x4c, 0x35, 0x81, 0xfc, + 0x08, 0x76, 0xd5, 0x5f, 0xca, 0x02, 0x6f, 0x16, 0xe1, 0x63, 0xaa, 0xea, 0xf2, 0xbd, 0x3c, 0x85, + 0xae, 0x32, 0xa7, 0x76, 0x38, 0x9e, 0x4c, 0xd8, 0x22, 0xb4, 0xdd, 0x09, 0x6b, 0xd7, 0xb2, 0x3b, + 0x24, 0x14, 0xba, 0xca, 0x4c, 0x3e, 0x80, 0x8a, 0xcf, 0x6e, 0x22, 0xd7, 0x69, 0xd7, 0x71, 0x59, + 0xd5, 0xa2, 0x08, 0x52, 0x85, 0x26, 0x1f, 0x01, 0x04, 0x7c, 0xea, 0xda, 0x61, 0xe4, 0xb3, 0xa0, + 0x0d, 0x28, 0x4d, 0xb0, 0x46, 0x1a, 0x45, 0x53, 0x54, 0xb2, 0x0f, 0x15, 0xe6, 0xfb, 0x9e, 0x1f, + 0xb4, 0xb7, 0x0e, 0x8a, 0x87, 0x75, 0xaa, 0x20, 0xf3, 0x1c, 0x48, 0x37, 0xf2, 0x7d, 0xe6, 0x4e, + 0x96, 0x3d, 0x76, 0xc3, 0x5d, 0x8e, 0x87, 0x27, 0x50, 0x12, 0x06, 0xdb, 0x36, 0x0e, 0x8c, 0xc3, + 0x3a, 0xc5, 0xff, 0xc4, 0x84, 0x86, 0xc3, 0xef, 0x78, 0xc0, 0xaf, 0xf9, 0x8c, 0x87, 0x4b, 0xb4, + 0x9f, 0x6d, 0x9a, 0xc1, 0x99, 0xff, 0xd4, 0x86, 0xaa, 0x32, 0x37, 0xb1, 0x47, 0x30, 0x8b, 0xa6, + 0x7a, 0x0f, 0xf1, 0x9f, 0x7c, 0x00, 0x35, 0xa9, 0xda, 0x41, 0x4f, 0xd9, 0x5f, 0xd1, 0x1a, 0xf4, + 0x68, 0x8c, 0x24, 0xdf, 0x86, 0xda, 0x9c, 0x85, 0xb6, 0x63, 0x87, 0xb6, 0xb2, 0xb5, 0x5d, 0x6d, + 0xce, 0xd6, 0x85, 0x22, 0xd0, 0x98, 0x85, 0x3c, 0x86, 0x12, 0x0f, 0xd9, 0xbc, 0x5d, 0x42, 0xd6, + 0xed, 0x98, 0x75, 0x10, 0xb2, 0x39, 0x45, 0x12, 0x39, 0x86, 0x66, 0x70, 0xcb, 0x17, 0x0b, 0xee, + 0x4e, 0xaf, 0x16, 0xe2, 0x72, 0x41, 0xbb, 0x8c, 0x92, 0x7a, 0x14, 0x73, 0x8f, 0x32, 0x74, 0x9a, + 0xe7, 0x27, 0x26, 0x94, 0x43, 0xfb, 0x9e, 0x05, 0xed, 0x0a, 0x2e, 0x6c, 0xc4, 0x0b, 0xc7, 0xf6, + 0x3d, 0x95, 0x24, 0xf2, 0x2d, 0xa8, 0x4e, 0xbc, 0x68, 0x21, 0xb6, 0xaf, 0x22, 0x57, 0x33, 0xe6, + 0xea, 0x22, 0x9e, 0x6a, 0x3a, 0x79, 0x1f, 0x60, 0xee, 0x39, 0xcc, 0xb7, 0x43, 0xa1, 0x8e, 0x1a, + 0xaa, 0x23, 0x85, 0x21, 0x16, 0x90, 0x90, 0xf9, 0xf3, 0xe0, 0xd8, 0x75, 0xba, 0x9e, 0xeb, 0x70, + 0x79, 0xe8, 0x3a, 0x8a, 0x71, 0x0d, 0x45, 0x28, 0x46, 0x1a, 0xc4, 0xd0, 0x9b, 0xf1, 0xc9, 0xb2, + 0x0d, 0xc8, 0x99, 0xc1, 0x75, 0xfe, 0xa2, 0x02, 0x35, 0x2d, 0x3f, 0xd2, 0x86, 0xea, 0x1d, 0xf3, + 0x03, 0x61, 0xd2, 0x06, 0x2a, 0x51, 0x83, 0xe4, 0x04, 0x1a, 0x3a, 0x80, 0x8d, 0x97, 0x0b, 0x86, + 0x3a, 0xda, 0x39, 0x7a, 0x7f, 0x45, 0x05, 0x56, 0x37, 0xc5, 0x45, 0x33, 0x6b, 0xc8, 0x33, 0xa8, + 0xdc, 0x78, 0xc2, 0xf9, 0x51, 0x81, 0x3b, 0x47, 0xed, 0xd5, 0xd5, 0xa7, 0x48, 0xa7, 0x8a, 0x8f, + 0x1c, 0x41, 0x85, 0xdd, 0x2f, 0xb8, 0xbf, 0x54, 0x7a, 0xec, 0x58, 0x32, 0x22, 0x5a, 0x3a, 0x22, + 0x5a, 0x63, 0x1d, 0x11, 0xa9, 0xe2, 0x14, 0x42, 0xb2, 0xd1, 0x55, 0x98, 0xa3, 0xec, 0x97, 0x33, + 0xa9, 0xd9, 0x3a, 0x5d, 0x43, 0x21, 0x4f, 0xa1, 0xb9, 0xf0, 0xf9, 0x84, 0xbb, 0x53, 0x6d, 0xee, + 0xe8, 0xfc, 0xf5, 0x93, 0x42, 0xdb, 0xa0, 0x79, 0x12, 0xe9, 0x40, 0x6d, 0x66, 0xbb, 0xd3, 0xc8, + 0x9e, 0x32, 0xf4, 0xfa, 0x3a, 0x8d, 0x61, 0xf1, 0x64, 0x16, 0x4c, 0x7c, 0xef, 0xb5, 0x38, 0x94, + 0x17, 0x85, 0x67, 0x5e, 0x84, 0x6a, 0x14, 0x82, 0x5c, 0x43, 0x21, 0x4f, 0x80, 0x4c, 0xfc, 0xe5, + 0x22, 0xf4, 0xf4, 0xee, 0x5d, 0xe1, 0x59, 0x52, 0x9d, 0xb5, 0x89, 0xc7, 0x5d, 0x94, 0xda, 0x53, + 0xcd, 0xd5, 0x4b, 0xfb, 0x18, 0xe0, 0xae, 0x2d, 0xc1, 0x95, 0xc6, 0x93, 0x43, 0xd8, 0x16, 0x47, + 0x66, 0x17, 0x9e, 0xc3, 0x6f, 0x38, 0xf3, 0xdb, 0x5b, 0x07, 0xc6, 0x61, 0x01, 0xef, 0x92, 0x25, + 0x90, 0x53, 0x78, 0xa4, 0xcd, 0xf9, 0xd4, 0xf7, 0xe6, 0x5d, 0x99, 0x8d, 0xf0, 0x08, 0x0d, 0x54, + 0x4f, 0xc3, 0x4a, 0xe1, 0xe8, 0x26, 0x66, 0xf2, 0x29, 0xec, 0xa7, 0x49, 0x43, 0x2f, 0x08, 0xed, + 0x19, 0x6e, 0xb3, 0x8d, 0x37, 0xd9, 0x40, 0x35, 0x1d, 0x68, 0xa4, 0x6d, 0x85, 0xec, 0xc2, 0xf6, + 0xf0, 0xec, 0xcb, 0xd1, 0xa0, 0x7b, 0x7c, 0xfe, 0xf2, 0xf3, 0xab, 0xab, 0x5e, 0xeb, 0x01, 0x69, + 0x41, 0xa3, 0x37, 0xf8, 0x7c, 0x30, 0xd6, 0x18, 0x83, 0x6c, 0x41, 0x75, 0xd4, 0xa7, 0x5f, 0x0c, + 0xba, 0xfd, 0x56, 0x81, 0xec, 0x00, 0x74, 0xe9, 0xd5, 0xef, 0xf7, 0x5e, 0x9e, 0xbe, 0xb8, 0xec, + 0xb5, 0x8a, 0x84, 0xc0, 0x4e, 0x97, 0x7e, 0x39, 0x1c, 0x5f, 0x75, 0x5f, 0x50, 0xda, 0xbf, 0xec, + 0x7e, 0xd9, 0x2a, 0x99, 0x1f, 0x43, 0x45, 0xda, 0x14, 0x69, 0xc2, 0xd6, 0xe9, 0xe0, 0x0f, 0xfa, + 0xbd, 0x97, 0x43, 0x2a, 0x96, 0xe3, 0xee, 0x17, 0xc7, 0xf4, 0x79, 0x7f, 0xac, 0x30, 0x85, 0xce, + 0xdf, 0xd5, 0xa0, 0x24, 0x02, 0x04, 0xd9, 0x83, 0x72, 0xc8, 0xc3, 0x99, 0x0e, 0x73, 0x12, 0x20, + 0x07, 0xb0, 0xe5, 0x08, 0x35, 0x72, 0xf4, 0x7e, 0x74, 0x81, 0x3a, 0x4d, 0xa3, 0xc8, 0x87, 0xb0, + 0xb3, 0xf0, 0xbd, 0x09, 0x0b, 0x02, 0xee, 0x4e, 0x85, 0xae, 0xd1, 0xd2, 0xeb, 0x34, 0x87, 0x25, + 0x6d, 0x28, 0xa3, 0x32, 0xd0, 0xac, 0x4b, 0xa8, 0x1d, 0x89, 0x10, 0xb1, 0xd1, 0x0d, 0x6e, 0x5e, + 0x63, 0xe2, 0xaa, 0x51, 0xfc, 0x2f, 0x70, 0xa1, 0x3d, 0x95, 0x41, 0xa6, 0x4e, 0xf1, 0x3f, 0xf9, + 0x18, 0x2a, 0x7c, 0x6e, 0x4f, 0x99, 0x0e, 0x2a, 0x0f, 0x33, 0x11, 0xce, 0x1a, 0x08, 0x1a, 0x55, + 0x2c, 0x22, 0xae, 0x4c, 0xec, 0x90, 0x4d, 0x3d, 0x5f, 0xb8, 0x82, 0x8a, 0x2b, 0x09, 0x46, 0x5c, + 0x77, 0xea, 0xdb, 0x73, 0x19, 0x4a, 0x0a, 0x54, 0x02, 0xe4, 0x3d, 0xa8, 0x4f, 0x74, 0x2c, 0x51, + 0xa1, 0x23, 0x41, 0x10, 0x0b, 0xaa, 0x9e, 0x8a, 0x9a, 0x5b, 0x78, 0x82, 0xbd, 0xec, 0x09, 0x54, + 0xc8, 0xd4, 0x4c, 0xe4, 0x9b, 0x50, 0x0a, 0x5e, 0x45, 0x41, 0xbb, 0xa1, 0x52, 0x7b, 0x86, 0x79, + 0xf4, 0x2a, 0xa2, 0x48, 0x26, 0x4f, 0xf2, 0xf6, 0xbb, 0x8d, 0x47, 0xca, 0xd9, 0x6e, 0x07, 0x6a, + 0xd7, 0x7c, 0x3a, 0x44, 0x11, 0xee, 0x48, 0x7f, 0xd1, 0x30, 0xf9, 0x9e, 0xda, 0x21, 0xf6, 0xe6, + 0x26, 0x86, 0x8e, 0x87, 0xd6, 0x6a, 0x36, 0xa3, 0x59, 0xce, 0xce, 0x3f, 0x1a, 0x50, 0x91, 0xe7, + 0x46, 0x3d, 0xd8, 0xf3, 0x38, 0xcf, 0x89, 0xff, 0x6f, 0xa1, 0xff, 0xcf, 0xa0, 0x76, 0x67, 0xfb, + 0xdc, 0x76, 0xc3, 0xa0, 0x5d, 0xc4, 0x8b, 0xbe, 0xb7, 0x4e, 0x2a, 0xd6, 0x17, 0x92, 0x89, 0xc6, + 0xdc, 0x9d, 0x33, 0xa8, 0x2a, 0xe4, 0xda, 0x47, 0x7f, 0x0b, 0xca, 0xa8, 0x4b, 0x95, 0x1b, 0xd7, + 0x6a, 0x5b, 0x72, 0x74, 0x7e, 0x66, 0x40, 0x71, 0xf4, 0x2a, 0x12, 0xc1, 0x5f, 0xed, 0xde, 0xf5, + 0xe6, 0xd7, 0x1e, 0xd6, 0x80, 0xdb, 0x34, 0x83, 0x13, 0x2a, 0x5e, 0xf8, 0x9e, 0x13, 0x4d, 0x42, + 0x95, 0x76, 0xeb, 0x34, 0x41, 0x90, 0x03, 0xa8, 0x07, 0x91, 0x3f, 0xb9, 0xb5, 0xfd, 0xa9, 0x34, + 0xe4, 0x22, 0x5a, 0x6a, 0x82, 0x24, 0xef, 0x43, 0xed, 0xab, 0xc8, 0x76, 0x43, 0x11, 0x91, 0x4a, + 0x31, 0x43, 0x8c, 0x13, 0x67, 0xb8, 0xe6, 0xd3, 0x51, 0xbc, 0x49, 0x59, 0x26, 0xa0, 0x34, 0x4e, + 0x48, 0xf5, 0x9a, 0x4f, 0x7f, 0xac, 0xb7, 0xa9, 0x48, 0xa9, 0xa6, 0x50, 0x9d, 0x9f, 0x1a, 0x50, + 0xc6, 0x2b, 0x0a, 0xbd, 0xdf, 0xf0, 0x19, 0x4b, 0x89, 0x27, 0x86, 0x05, 0xcd, 0xf3, 0xf9, 0x94, + 0xbb, 0xf6, 0x4c, 0x5d, 0x25, 0x86, 0x85, 0x81, 0xcf, 0xe2, 0x5b, 0xd4, 0xa9, 0x04, 0x44, 0xe5, + 0x33, 0x67, 0x0e, 0x8f, 0x64, 0x95, 0x50, 0xa7, 0x0a, 0x12, 0xdc, 0xc1, 0xdc, 0x9e, 0xcd, 0xd4, + 0x71, 0x25, 0x80, 0x5e, 0xc8, 0x5d, 0x7d, 0x40, 0xfc, 0xdf, 0xf9, 0xb7, 0x22, 0xec, 0x64, 0x6b, + 0x84, 0xb5, 0xda, 0xfb, 0x0c, 0x4a, 0x61, 0x92, 0x34, 0x9f, 0x6c, 0x28, 0x2f, 0x62, 0x10, 0x53, + 0x27, 0xae, 0x20, 0x1f, 0x42, 0xd5, 0x67, 0x53, 0xf4, 0x32, 0x61, 0x4f, 0xf9, 0xa0, 0xac, 0x89, + 0xe4, 0xfb, 0x50, 0x0b, 0x98, 0x7f, 0xc7, 0x27, 0x4c, 0x17, 0x31, 0x1f, 0x6c, 0x7c, 0x8a, 0xe4, + 0xa3, 0xf1, 0x82, 0xce, 0xbf, 0x1b, 0x50, 0x55, 0xd8, 0xb5, 0xc7, 0x8f, 0xa3, 0x55, 0x21, 0x1f, + 0xad, 0x9e, 0xc2, 0x2e, 0x0b, 0x42, 0x3e, 0xb7, 0x43, 0xe6, 0xf4, 0xd8, 0x8c, 0xdf, 0x31, 0x7f, + 0xa9, 0x64, 0xbc, 0x4a, 0x20, 0xdf, 0x85, 0x87, 0xb6, 0x23, 0xc3, 0x87, 0x3d, 0x13, 0x86, 0x3b, + 0xcc, 0xc5, 0xc0, 0x75, 0xe4, 0x8c, 0xaf, 0x97, 0x73, 0xbe, 0xfe, 0x29, 0xec, 0x5f, 0xf3, 0xe9, + 0xf1, 0x9a, 0x4d, 0xa5, 0x96, 0x36, 0x50, 0xcd, 0x4f, 0xa0, 0x91, 0x16, 0xb6, 0x48, 0x05, 0xe7, + 0x57, 0x22, 0xf1, 0x0c, 0x07, 0xdd, 0xe7, 0x2f, 0x86, 0xad, 0x07, 0xf9, 0x6c, 0x61, 0x74, 0xfe, + 0xca, 0x80, 0xe2, 0xd8, 0xbe, 0x17, 0x25, 0x52, 0x68, 0xdf, 0x63, 0x0d, 0x24, 0x65, 0xa4, 0x41, + 0xf2, 0x14, 0x20, 0xb4, 0xef, 0xa9, 0x52, 0x57, 0x61, 0x8d, 0xba, 0x52, 0x74, 0x61, 0xf6, 0xa1, + 0x7d, 0xaf, 0x4f, 0x81, 0x42, 0xab, 0xd1, 0x34, 0x4a, 0x44, 0xed, 0x05, 0xf3, 0x27, 0xcc, 0x0d, + 0x85, 0xe3, 0x97, 0x30, 0x0e, 0xa6, 0x30, 0x9d, 0xff, 0x32, 0xa0, 0x22, 0x2b, 0xc8, 0x0d, 0xf9, + 0x6a, 0x0f, 0x4a, 0xb7, 0x76, 0x70, 0x2b, 0xbd, 0xe1, 0xec, 0x01, 0x45, 0x88, 0x3c, 0x11, 0xd5, + 0x7a, 0x80, 0xcd, 0x27, 0x66, 0xe9, 0xa2, 0xa2, 0x66, 0xb0, 0xe4, 0x23, 0x68, 0xaa, 0x47, 0xf5, + 0x14, 0x1a, 0x85, 0x5f, 0x38, 0x13, 0x35, 0x51, 0x96, 0x40, 0x3e, 0x52, 0x11, 0x37, 0xe6, 0xac, + 0x68, 0x8d, 0x9e, 0xe9, 0xaa, 0x23, 0xe6, 0x7d, 0x0a, 0x2d, 0xad, 0xbd, 0x98, 0x1d, 0xeb, 0xa8, + 0x33, 0x83, 0xae, 0x50, 0x4e, 0x2a, 0xb2, 0xdb, 0x38, 0x01, 0xa8, 0xe9, 0xd3, 0x99, 0x7f, 0xda, + 0x80, 0xb2, 0xec, 0x46, 0x9f, 0xc0, 0xb6, 0x2c, 0x65, 0x8f, 0x1d, 0xc7, 0x67, 0x41, 0xa0, 0x6e, + 0x9f, 0x45, 0x8a, 0x28, 0x26, 0x11, 0xa7, 0x2c, 0x6d, 0xc1, 0x09, 0x92, 0x7c, 0x0c, 0xb5, 0x20, + 0xad, 0x07, 0x51, 0xa2, 0xe3, 0x13, 0x62, 0xd7, 0xa1, 0x31, 0x03, 0xf9, 0x4d, 0xa8, 0x62, 0xef, + 0x38, 0xe8, 0xa9, 0x9a, 0x14, 0xfb, 0x14, 0x8d, 0x23, 0x9f, 0x41, 0x3d, 0x6e, 0xd2, 0x55, 0xf7, + 0xf9, 0xa6, 0xa2, 0x35, 0x61, 0x26, 0x8f, 0xa1, 0x2c, 0xda, 0x12, 0xdd, 0x4b, 0x6c, 0xa9, 0x23, + 0x60, 0xc3, 0x22, 0x29, 0xe4, 0x10, 0xaa, 0x0b, 0x7b, 0x89, 0x1d, 0xb2, 0xec, 0x38, 0x77, 0x14, + 0xd3, 0x50, 0x62, 0xa9, 0x26, 0x0b, 0xdb, 0xf1, 0x6d, 0xe1, 0xfd, 0xcf, 0xd9, 0x52, 0x66, 0xfc, + 0x06, 0x4d, 0x61, 0xc8, 0x11, 0xec, 0xd9, 0xb3, 0x90, 0xf9, 0xae, 0x1d, 0x32, 0x51, 0x85, 0xd9, + 0x93, 0x70, 0xe0, 0xde, 0x78, 0xaa, 0xf8, 0x5c, 0x4b, 0x4b, 0x37, 0x07, 0x90, 0x6d, 0x0e, 0x64, + 0x98, 0xa7, 0xb1, 0x94, 0xb7, 0xe2, 0x30, 0x1f, 0xe3, 0x3a, 0x3f, 0x37, 0xa0, 0x16, 0x9b, 0xf6, + 0x3e, 0x54, 0x84, 0x40, 0xc7, 0x9e, 0x52, 0x99, 0x82, 0xc4, 0x23, 0x6c, 0xa5, 0x4b, 0x19, 0xc2, + 0x35, 0x88, 0x7d, 0xa7, 0x48, 0x0f, 0x45, 0xd5, 0x77, 0x8a, 0xec, 0x22, 0xe2, 0x74, 0x68, 0x87, + 0x4c, 0x85, 0x6f, 0x09, 0xa0, 0xdb, 0x24, 0x35, 0xa8, 0x8c, 0x18, 0x29, 0x8c, 0x08, 0xa9, 0x6a, + 0xf2, 0x82, 0x76, 0xba, 0x12, 0x52, 0x15, 0x51, 0x5c, 0x4a, 0x3d, 0xfc, 0xd2, 0x0b, 0xb1, 0xce, + 0xc2, 0x4b, 0xa5, 0x71, 0x9d, 0x9f, 0x17, 0x55, 0xc1, 0x78, 0x00, 0x5b, 0x33, 0x19, 0x6e, 0xcf, + 0x84, 0xc7, 0xc9, 0x5b, 0xa5, 0x51, 0x99, 0x54, 0x89, 0x0d, 0x72, 0x2e, 0x55, 0x3e, 0x4d, 0xea, + 0x29, 0x59, 0x39, 0x90, 0x94, 0x01, 0xac, 0x54, 0x53, 0x27, 0xb0, 0x93, 0xed, 0x45, 0xe3, 0x06, + 0x29, 0xb5, 0x28, 0xd7, 0xbd, 0xe6, 0x56, 0x08, 0x91, 0xce, 0xd9, 0xdc, 0x53, 0x22, 0xc2, 0xff, + 0xe2, 0x1e, 0xb2, 0x19, 0x15, 0xb2, 0xd0, 0x15, 0x67, 0x1a, 0x85, 0x25, 0xae, 0x34, 0x32, 0xed, + 0x75, 0x55, 0x55, 0xe2, 0x66, 0xb0, 0xc4, 0x04, 0xd0, 0x77, 0xfb, 0xf4, 0xbb, 0xd8, 0x04, 0x49, + 0xbf, 0x4b, 0x61, 0xf3, 0xa9, 0xbf, 0xbe, 0x9a, 0xfa, 0x8f, 0xde, 0x58, 0x90, 0xed, 0x41, 0xf9, + 0xce, 0x9e, 0x45, 0x4c, 0x19, 0x8b, 0x04, 0x3a, 0x3f, 0x78, 0xab, 0x9c, 0xdc, 0x86, 0xaa, 0x4a, + 0x80, 0xda, 0xd4, 0x14, 0xd8, 0xf9, 0x9b, 0x22, 0x54, 0x95, 0x43, 0x91, 0x6f, 0x8b, 0x12, 0x21, + 0xbc, 0xf5, 0x1c, 0x5c, 0xbb, 0x73, 0xf4, 0x8d, 0xac, 0xc3, 0x89, 0xc6, 0xf5, 0xd6, 0x73, 0xa8, + 0x62, 0x12, 0xf5, 0x54, 0xdc, 0xae, 0xeb, 0x7a, 0x2a, 0x46, 0x90, 0x0e, 0x54, 0xec, 0x39, 0x46, + 0xbc, 0x62, 0x2c, 0x0e, 0x85, 0xc1, 0x62, 0xfb, 0xd6, 0xe6, 0x2e, 0x0e, 0x57, 0x4a, 0xaa, 0xd8, + 0xd6, 0x88, 0xb4, 0x5f, 0x94, 0xb3, 0x7e, 0x81, 0x2d, 0xbe, 0xc3, 0xd8, 0x7c, 0x84, 0x45, 0xa8, + 0xca, 0x7b, 0x19, 0x9c, 0xe0, 0x89, 0x0f, 0xf1, 0x9c, 0x2d, 0x51, 0x61, 0x0d, 0x9a, 0xc1, 0x91, + 0x7d, 0x11, 0x69, 0xb9, 0x8b, 0x8a, 0x92, 0xad, 0x2f, 0xc2, 0xe2, 0x5c, 0x22, 0x87, 0xca, 0x63, + 0x4b, 0x05, 0x25, 0x08, 0xf2, 0x7d, 0xd8, 0x91, 0xe7, 0x8f, 0x8b, 0x6d, 0xd8, 0x5c, 0x6c, 0xe7, + 0x58, 0xcd, 0xcf, 0xa0, 0x22, 0xc5, 0x47, 0x1e, 0x42, 0xf3, 0xb8, 0xd7, 0xa3, 0xfd, 0xd1, 0xe8, + 0x25, 0xed, 0xff, 0xf8, 0x45, 0x7f, 0x34, 0x6e, 0x3d, 0x20, 0x00, 0x95, 0xde, 0x80, 0xf6, 0xbb, + 0xe3, 0x96, 0x41, 0xb6, 0xa1, 0x7e, 0x71, 0xd5, 0xeb, 0xd3, 0xe3, 0x71, 0xbf, 0xd7, 0x2a, 0x98, + 0xbf, 0x2c, 0xc0, 0xee, 0xea, 0x38, 0xb1, 0x0d, 0x55, 0x4f, 0x20, 0x07, 0x3d, 0x9d, 0x99, 0x15, + 0x98, 0x0d, 0xca, 0x85, 0x77, 0x09, 0xca, 0xab, 0xd6, 0x5e, 0x5c, 0x6b, 0xed, 0x4f, 0xa1, 0xe9, + 0xb3, 0xaf, 0x22, 0x16, 0x84, 0xcc, 0x51, 0xc2, 0x4a, 0xca, 0x9a, 0x3c, 0x89, 0xfc, 0x2e, 0xb4, + 0x64, 0x2c, 0x1e, 0x25, 0x43, 0x3a, 0x59, 0xb5, 0xb5, 0x2c, 0x9a, 0x25, 0xd0, 0x15, 0x4e, 0x62, + 0x01, 0xc1, 0xc8, 0x9a, 0x7d, 0x9c, 0x54, 0xfc, 0x1a, 0x0a, 0xb9, 0x80, 0x47, 0xb9, 0x03, 0xc4, + 0xda, 0xaa, 0x6e, 0xd6, 0xd6, 0xa6, 0x35, 0xe6, 0x9f, 0x1b, 0xb0, 0x25, 0x27, 0xc3, 0xec, 0x27, + 0x6c, 0x12, 0xfe, 0xbf, 0x88, 0x5d, 0x34, 0x8b, 0x7c, 0xaa, 0x23, 0xe1, 0xae, 0x75, 0xc2, 0x43, + 0x61, 0x8d, 0x89, 0x54, 0x90, 0x6c, 0xfe, 0xa2, 0x08, 0xcd, 0x9c, 0xbc, 0xc8, 0x8f, 0x52, 0x73, + 0x42, 0x03, 0x9f, 0xf9, 0x24, 0x2f, 0x53, 0x6b, 0xec, 0xdb, 0x6e, 0x60, 0x4f, 0xc4, 0x3d, 0xd7, + 0x8c, 0x0e, 0xdf, 0x83, 0x7a, 0x3c, 0x1e, 0xc5, 0x63, 0x37, 0x68, 0x82, 0xe8, 0xfc, 0x6b, 0x01, + 0x1e, 0xae, 0x59, 0x9f, 0xca, 0x00, 0xa3, 0x64, 0xb6, 0x99, 0x46, 0x89, 0x7d, 0xe3, 0x0c, 0xac, + 0xf7, 0x8d, 0x11, 0x2b, 0x4e, 0x5a, 0x5c, 0xe3, 0xa4, 0x26, 0x34, 0xd4, 0x86, 0x63, 0xac, 0xf6, + 0x64, 0x9c, 0xc8, 0xe0, 0xc8, 0x19, 0xd4, 0xc3, 0xdb, 0x68, 0x7e, 0xed, 0xda, 0x7c, 0xa6, 0x0a, + 0x90, 0x8f, 0xde, 0x46, 0x00, 0xaa, 0x89, 0x4c, 0x16, 0x77, 0xfe, 0x44, 0x77, 0x5d, 0xba, 0xf3, + 0x31, 0x92, 0xce, 0x27, 0xe9, 0x91, 0x0a, 0xe9, 0x1e, 0x29, 0xe9, 0xa8, 0x8a, 0xf9, 0x8e, 0x4a, + 0xf6, 0x5f, 0xa5, 0x74, 0xff, 0x95, 0xee, 0xd8, 0xca, 0xd9, 0x8e, 0xcd, 0x1c, 0x42, 0x2b, 0xaf, + 0x74, 0x91, 0xd9, 0xb9, 0xbb, 0x88, 0xc2, 0x81, 0xeb, 0xb0, 0x7b, 0x35, 0xa0, 0x4c, 0x61, 0xde, + 0xac, 0x38, 0xf3, 0x67, 0x55, 0x68, 0xad, 0xbc, 0x37, 0x88, 0x8d, 0xd7, 0xc9, 0x1a, 0xaf, 0x13, + 0x0f, 0xa9, 0x0b, 0xa9, 0x21, 0x75, 0xc6, 0xa0, 0x8b, 0xef, 0x62, 0xd0, 0x97, 0xd0, 0x5a, 0xdc, + 0x2e, 0x03, 0x3e, 0xb1, 0x67, 0x71, 0x9f, 0x24, 0x5f, 0x72, 0x98, 0x2b, 0x2f, 0x39, 0xac, 0x61, + 0x8e, 0x93, 0xae, 0xac, 0x25, 0xcf, 0xa1, 0xe9, 0xf0, 0x29, 0x0f, 0x53, 0xdb, 0xc9, 0x00, 0xf2, + 0x78, 0x75, 0xbb, 0x5e, 0x96, 0x91, 0xe6, 0x57, 0x92, 0x67, 0x50, 0x59, 0xd8, 0x4b, 0x2f, 0x0a, + 0xd5, 0x5b, 0x8f, 0xf6, 0x9a, 0x23, 0x21, 0x9d, 0x2a, 0x3e, 0xf2, 0x3b, 0xd0, 0xcc, 0x85, 0x25, + 0x15, 0x4a, 0x56, 0xe3, 0x57, 0x9e, 0x11, 0x93, 0xb1, 0x17, 0xca, 0x37, 0x1e, 0x22, 0x19, 0x7b, + 0x21, 0x23, 0x7f, 0x04, 0xfb, 0x72, 0xc6, 0x39, 0x89, 0x03, 0x91, 0xba, 0x55, 0x1d, 0x6f, 0x75, + 0xb8, 0x7a, 0xa2, 0xee, 0x5a, 0x7e, 0xba, 0x61, 0x9f, 0xce, 0x18, 0x5a, 0x79, 0xb1, 0x62, 0x09, + 0x20, 0x0a, 0x05, 0xe6, 0x6b, 0xe5, 0x2b, 0x50, 0x84, 0xfd, 0xd0, 0xb7, 0x27, 0xaf, 0xb8, 0x3b, + 0xbd, 0x8c, 0xe6, 0xd7, 0x4c, 0x27, 0xf3, 0x1c, 0xb6, 0xf3, 0x43, 0x68, 0xe6, 0xa4, 0x4b, 0x5a, + 0x50, 0x8c, 0xfc, 0x99, 0xda, 0x50, 0xfc, 0x15, 0x66, 0xbe, 0xb0, 0x83, 0xe0, 0xb5, 0xe7, 0x3b, + 0x7a, 0x30, 0xa1, 0xe1, 0xce, 0x0f, 0x60, 0x7f, 0xfd, 0x45, 0x44, 0x73, 0x13, 0x26, 0x5e, 0x1a, + 0x07, 0xd7, 0x2c, 0xb2, 0xf3, 0x4b, 0x03, 0x2a, 0x52, 0x37, 0x71, 0xcc, 0x34, 0xde, 0x18, 0x33, + 0x71, 0xc0, 0x86, 0x0b, 0x8e, 0x33, 0x85, 0x76, 0x16, 0x49, 0x2c, 0x68, 0x49, 0xc4, 0x29, 0x63, + 0x43, 0xe6, 0x9f, 0x2c, 0x43, 0x96, 0x2a, 0x5a, 0x56, 0x68, 0xe4, 0x19, 0x3c, 0x14, 0xcd, 0x5b, + 0x7e, 0x89, 0x74, 0xf7, 0x75, 0x24, 0x72, 0x0c, 0xbb, 0xf1, 0x2e, 0x71, 0x3e, 0x2a, 0x6f, 0xce, + 0x47, 0xab, 0xdc, 0xe6, 0xdf, 0x1b, 0xd0, 0xcc, 0xbf, 0xc2, 0xdb, 0xec, 0xd0, 0xbf, 0x7a, 0x36, + 0xfa, 0x04, 0x40, 0x3e, 0x7c, 0xf4, 0xc6, 0x9c, 0x94, 0x62, 0x22, 0x8f, 0xa1, 0x2a, 0xed, 0x3e, + 0x50, 0x6e, 0x5e, 0x55, 0x8e, 0x41, 0x35, 0xde, 0xfc, 0x5b, 0x03, 0xf6, 0xf1, 0xf4, 0xc3, 0x78, + 0x36, 0x7c, 0x6a, 0xf3, 0x99, 0x70, 0x91, 0xcd, 0x29, 0xf5, 0x0c, 0xf6, 0xec, 0x30, 0x64, 0xf3, + 0x45, 0xc8, 0x9c, 0x0b, 0xf9, 0xae, 0x38, 0xf5, 0x3a, 0x66, 0xcf, 0x52, 0x38, 0x2b, 0x45, 0xa3, + 0x6b, 0x57, 0x10, 0x0b, 0x6a, 0xfa, 0xe5, 0x4c, 0xfc, 0xee, 0x76, 0xe5, 0x55, 0x32, 0x8d, 0x79, + 0xcc, 0x7f, 0x2e, 0x41, 0x45, 0x5e, 0x81, 0x1c, 0xe9, 0xe6, 0xb2, 0x97, 0x24, 0x59, 0xa2, 0xee, + 0xa7, 0x7e, 0x04, 0x85, 0xa6, 0xb8, 0xbe, 0x26, 0xa9, 0xfe, 0x47, 0x11, 0x80, 0x66, 0x98, 0x93, + 0x4c, 0x69, 0xe4, 0x33, 0xe5, 0xd7, 0xbe, 0x2a, 0xb4, 0xa0, 0x2e, 0xff, 0x8f, 0xb8, 0x6e, 0xe8, + 0x57, 0xe3, 0x52, 0xc2, 0xf2, 0x75, 0x2d, 0xbd, 0x28, 0x81, 0xc5, 0xdf, 0x4b, 0xd1, 0x42, 0x94, + 0x55, 0x09, 0xac, 0x11, 0x38, 0x9e, 0x12, 0x80, 0x78, 0x56, 0x05, 0x8f, 0x1a, 0xc3, 0x99, 0x9c, + 0x2e, 0xe8, 0xf9, 0xc2, 0x5b, 0xf0, 0x64, 0xcc, 0xb2, 0xf6, 0x2e, 0x66, 0x29, 0xac, 0xe4, 0x8e, + 0xf9, 0x22, 0x09, 0xd7, 0x65, 0x3f, 0xae, 0x40, 0x41, 0xf9, 0x2a, 0xb2, 0x53, 0xef, 0x89, 0x34, + 0x98, 0x1f, 0x61, 0x6f, 0x21, 0x35, 0x33, 0xc2, 0x7e, 0x02, 0xdb, 0x8e, 0x8a, 0x41, 0xa3, 0x05, + 0x63, 0x0e, 0xbe, 0x0c, 0xda, 0xa6, 0x59, 0x24, 0x39, 0x84, 0xe6, 0x24, 0x0a, 0x42, 0x6f, 0xce, + 0x7c, 0x35, 0x39, 0xc4, 0x41, 0xfd, 0x36, 0xcd, 0xa3, 0x45, 0x49, 0xe0, 0xb3, 0x3b, 0xce, 0x5e, + 0xab, 0x41, 0xbd, 0x82, 0xcc, 0x5f, 0x18, 0x50, 0x55, 0x2f, 0xbb, 0xb3, 0x32, 0x30, 0xde, 0x45, + 0x06, 0x7b, 0x50, 0x9e, 0xcc, 0x6c, 0x3e, 0xd7, 0x65, 0x08, 0x02, 0xab, 0x31, 0xae, 0xb8, 0x2e, + 0xc6, 0xfd, 0x16, 0xd4, 0xbd, 0x28, 0x5c, 0x78, 0xdc, 0x0d, 0xb5, 0x97, 0xd6, 0xad, 0x2b, 0x85, + 0xa1, 0x09, 0x4d, 0x14, 0xdc, 0x01, 0xf3, 0xb9, 0x3d, 0xe3, 0x7f, 0xcc, 0x1c, 0xed, 0x1a, 0x68, + 0x09, 0x0d, 0xba, 0x86, 0x62, 0xfe, 0x59, 0x05, 0x76, 0x57, 0xbe, 0x04, 0xf8, 0x3f, 0x5c, 0x32, + 0x15, 0xd3, 0x0a, 0xd9, 0x98, 0xf6, 0x3e, 0xc0, 0xc2, 0xf7, 0x16, 0x5e, 0xc0, 0x9c, 0x13, 0x3d, + 0x1b, 0x49, 0x61, 0x70, 0x0c, 0x94, 0x7c, 0xa5, 0x20, 0xa3, 0x71, 0x0a, 0x43, 0x3e, 0x89, 0x33, + 0xbf, 0x8c, 0xbc, 0xbf, 0xb1, 0xfa, 0x05, 0x43, 0x3e, 0xf5, 0x3f, 0x83, 0x87, 0xb1, 0xfd, 0xc6, + 0x3e, 0x25, 0x27, 0x05, 0x0d, 0xba, 0x8e, 0xd4, 0xf9, 0xcf, 0xe2, 0xbb, 0xe6, 0xa8, 0xc7, 0x50, + 0xc1, 0xb2, 0x4e, 0x4e, 0x51, 0x33, 0x6a, 0x51, 0x04, 0x72, 0x02, 0x5b, 0xf2, 0x13, 0x8e, 0x28, + 0x5c, 0x44, 0x3a, 0x82, 0x1d, 0x6c, 0x3c, 0xbe, 0x25, 0xf9, 0x68, 0x7a, 0x11, 0xe9, 0x41, 0x43, + 0x7d, 0x4e, 0x22, 0x37, 0x29, 0xbd, 0xe5, 0x26, 0x99, 0x55, 0xe4, 0xf7, 0xa0, 0x19, 0xdf, 0x5a, + 0x6d, 0x54, 0x7e, 0xcb, 0x8d, 0xf2, 0x0b, 0x45, 0x3f, 0x2d, 0xc5, 0x9c, 0x79, 0x15, 0xbd, 0xa9, + 0x9f, 0xce, 0xb2, 0x76, 0xfe, 0xd2, 0x80, 0x8a, 0xda, 0xa7, 0x0d, 0x15, 0xe9, 0xd1, 0x32, 0x7f, + 0x9c, 0x3d, 0xa0, 0x0a, 0x26, 0x9d, 0x64, 0x92, 0xa0, 0x07, 0xbf, 0xf1, 0x2c, 0x21, 0x99, 0x4f, + 0x14, 0xd6, 0xcd, 0x27, 0x92, 0x39, 0x40, 0x29, 0x37, 0x07, 0x38, 0xd9, 0x85, 0xa6, 0xdc, 0xff, + 0xca, 0x57, 0xde, 0x65, 0xf2, 0xd8, 0x07, 0x52, 0x1f, 0xae, 0xfc, 0xea, 0x3e, 0xd0, 0x81, 0xda, + 0x64, 0xa6, 0xec, 0x5c, 0x15, 0x51, 0x1a, 0x36, 0x7f, 0x02, 0x35, 0x6d, 0x1f, 0xa2, 0xba, 0xbc, + 0x4d, 0x26, 0x70, 0x72, 0xe2, 0xbd, 0x07, 0x65, 0x8e, 0x2d, 0x83, 0xfc, 0x30, 0x45, 0x02, 0xa4, + 0xad, 0x87, 0x47, 0x49, 0x5d, 0x23, 0x11, 0xea, 0x8d, 0xc3, 0x17, 0x48, 0x2c, 0xc5, 0x6f, 0x1c, + 0x10, 0x36, 0xff, 0xbb, 0x00, 0x15, 0x39, 0xd4, 0xfc, 0x35, 0x36, 0xbe, 0xa4, 0x0f, 0xbb, 0x72, + 0x7c, 0x9d, 0x6a, 0xe4, 0x94, 0xf9, 0x3e, 0x52, 0xdf, 0x02, 0xa5, 0x7b, 0xbc, 0x81, 0x7b, 0xe3, + 0xd1, 0xd5, 0x15, 0xeb, 0x26, 0x80, 0x9d, 0xbf, 0x36, 0xa0, 0x99, 0x5b, 0x8a, 0x0d, 0xe0, 0x3d, + 0x77, 0xe2, 0x06, 0xf0, 0x9e, 0x3b, 0x89, 0xf8, 0x0a, 0x6f, 0x12, 0x5f, 0x31, 0x2b, 0x3e, 0xf2, + 0x3d, 0xd8, 0x46, 0xa6, 0xd8, 0xbe, 0x4b, 0x6f, 0x78, 0x39, 0x9b, 0xe1, 0x34, 0x8f, 0x60, 0xff, + 0x0b, 0xf4, 0xbb, 0x53, 0xd1, 0x20, 0x8a, 0x80, 0xab, 0x87, 0x74, 0x1b, 0x15, 0x61, 0xfe, 0x83, + 0x01, 0x85, 0x41, 0x4f, 0xe4, 0xa0, 0x05, 0x4b, 0xd1, 0x15, 0x24, 0xf0, 0xb7, 0xb6, 0xeb, 0xcc, + 0xf4, 0x08, 0x50, 0x41, 0xe4, 0x9b, 0x50, 0x5d, 0x44, 0xd7, 0xaf, 0xd8, 0x32, 0x50, 0x81, 0x65, + 0xcb, 0x1a, 0xf4, 0xac, 0xa1, 0x44, 0x51, 0x4d, 0x13, 0xd1, 0xf5, 0x3a, 0xd6, 0x0f, 0xde, 0xa4, + 0x41, 0x53, 0x98, 0xce, 0x0f, 0xa1, 0xaa, 0xd6, 0x08, 0x99, 0x70, 0x87, 0xc9, 0x31, 0xa7, 0x2c, + 0x68, 0x62, 0x58, 0x1c, 0x5f, 0x2d, 0x52, 0x85, 0x91, 0x06, 0xcd, 0xff, 0x31, 0xa0, 0x9e, 0x34, + 0x4e, 0x4f, 0xa1, 0x1a, 0x30, 0xa9, 0x6a, 0x39, 0x8c, 0x24, 0xc9, 0x17, 0x5d, 0xd6, 0x48, 0x52, + 0xa8, 0x66, 0x11, 0x2d, 0x4c, 0x5c, 0x5f, 0x89, 0x82, 0x3b, 0x50, 0x9b, 0xe7, 0xb0, 0xe6, 0x4f, + 0xf1, 0xe5, 0x9f, 0x5c, 0xb3, 0x05, 0xd5, 0xf3, 0xc1, 0x68, 0x3c, 0xb8, 0xfc, 0xbc, 0xf5, 0x80, + 0xd4, 0xa1, 0x7c, 0x45, 0x7b, 0x7d, 0xda, 0x32, 0xc8, 0x3e, 0x10, 0xfc, 0xfb, 0xb2, 0x7b, 0x75, + 0x79, 0x3a, 0xa0, 0x17, 0xc7, 0xe3, 0xc1, 0xd5, 0x65, 0xab, 0x40, 0xbe, 0x01, 0xbb, 0x12, 0x7f, + 0xfa, 0xe2, 0xfc, 0x74, 0x70, 0x7e, 0x7e, 0xd1, 0xbf, 0x1c, 0xb7, 0x8a, 0x64, 0x0f, 0x5a, 0x9a, + 0xfd, 0x62, 0x78, 0xde, 0x47, 0xe6, 0x92, 0xd8, 0xbc, 0x37, 0x18, 0x0d, 0x5f, 0x8c, 0xfb, 0xad, + 0xb2, 0xd8, 0x51, 0x01, 0x2f, 0x69, 0x7f, 0x74, 0x75, 0xfe, 0x02, 0x99, 0x2a, 0x04, 0xa0, 0x42, + 0xfb, 0xf8, 0x39, 0x47, 0xd5, 0x64, 0xb0, 0x2d, 0xee, 0xc7, 0x1c, 0xfd, 0xdd, 0x98, 0x09, 0x55, + 0x35, 0xea, 0x50, 0xb1, 0x23, 0xf9, 0xa0, 0x51, 0x13, 0x62, 0xff, 0x2f, 0xa4, 0xfc, 0x3f, 0x53, + 0x7b, 0x16, 0x73, 0xb5, 0xe7, 0x49, 0xe9, 0x0f, 0x0b, 0x8b, 0xeb, 0xeb, 0x0a, 0xfa, 0xe5, 0x6f, + 0xff, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5b, 0x59, 0xc6, 0x05, 0xa7, 0x29, 0x00, 0x00, } diff --git a/pb/countrycodes.pb.go b/pb/countrycodes.pb.go index 2cbe9d1e80..2ca6dc3977 100644 --- a/pb/countrycodes.pb.go +++ b/pb/countrycodes.pb.go @@ -817,7 +817,9 @@ func init() { proto.RegisterEnum("CountryCode", CountryCode_name, CountryCode_value) } -func init() { proto.RegisterFile("countrycodes.proto", fileDescriptor_18ecd71e04cfbc43) } +func init() { + proto.RegisterFile("countrycodes.proto", fileDescriptor_18ecd71e04cfbc43) +} var fileDescriptor_18ecd71e04cfbc43 = []byte{ // 2291 bytes of a gzipped FileDescriptorProto diff --git a/pb/message.pb.go b/pb/message.pb.go index d1fd727d54..e5f2a75e56 100644 --- a/pb/message.pb.go +++ b/pb/message.pb.go @@ -46,7 +46,9 @@ const ( Message_STORE Message_MessageType = 18 Message_BLOCK Message_MessageType = 19 Message_VENDOR_FINALIZED_PAYMENT Message_MessageType = 20 + Message_ORDER_PAYMENT Message_MessageType = 21 Message_ERROR Message_MessageType = 500 + Message_ORDER_PROCESSING_FAILURE Message_MessageType = 501 ) var Message_MessageType_name = map[int32]string{ @@ -71,7 +73,9 @@ var Message_MessageType_name = map[int32]string{ 18: "STORE", 19: "BLOCK", 20: "VENDOR_FINALIZED_PAYMENT", + 21: "ORDER_PAYMENT", 500: "ERROR", + 501: "ORDER_PROCESSING_FAILURE", } var Message_MessageType_value = map[string]int32{ @@ -96,7 +100,9 @@ var Message_MessageType_value = map[string]int32{ "STORE": 18, "BLOCK": 19, "VENDOR_FINALIZED_PAYMENT": 20, + "ORDER_PAYMENT": 21, "ERROR": 500, + "ORDER_PROCESSING_FAILURE": 501, } func (x Message_MessageType) String() string { @@ -575,6 +581,69 @@ func (m *Error) GetOrderID() string { return "" } +type OrderPaymentTxn struct { + Coin string `protobuf:"bytes,1,opt,name=coin,proto3" json:"coin,omitempty"` + OrderID string `protobuf:"bytes,2,opt,name=orderID,proto3" json:"orderID,omitempty"` + TransactionID string `protobuf:"bytes,3,opt,name=transactionID,proto3" json:"transactionID,omitempty"` + WithInput bool `protobuf:"varint,4,opt,name=withInput,proto3" json:"withInput,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OrderPaymentTxn) Reset() { *m = OrderPaymentTxn{} } +func (m *OrderPaymentTxn) String() string { return proto.CompactTextString(m) } +func (*OrderPaymentTxn) ProtoMessage() {} +func (*OrderPaymentTxn) Descriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{7} +} + +func (m *OrderPaymentTxn) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OrderPaymentTxn.Unmarshal(m, b) +} +func (m *OrderPaymentTxn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OrderPaymentTxn.Marshal(b, m, deterministic) +} +func (m *OrderPaymentTxn) XXX_Merge(src proto.Message) { + xxx_messageInfo_OrderPaymentTxn.Merge(m, src) +} +func (m *OrderPaymentTxn) XXX_Size() int { + return xxx_messageInfo_OrderPaymentTxn.Size(m) +} +func (m *OrderPaymentTxn) XXX_DiscardUnknown() { + xxx_messageInfo_OrderPaymentTxn.DiscardUnknown(m) +} + +var xxx_messageInfo_OrderPaymentTxn proto.InternalMessageInfo + +func (m *OrderPaymentTxn) GetCoin() string { + if m != nil { + return m.Coin + } + return "" +} + +func (m *OrderPaymentTxn) GetOrderID() string { + if m != nil { + return m.OrderID + } + return "" +} + +func (m *OrderPaymentTxn) GetTransactionID() string { + if m != nil { + return m.TransactionID + } + return "" +} + +func (m *OrderPaymentTxn) GetWithInput() bool { + if m != nil { + return m.WithInput + } + return false +} + func init() { proto.RegisterEnum("Message_MessageType", Message_MessageType_name, Message_MessageType_value) proto.RegisterEnum("Chat_Flag", Chat_Flag_name, Chat_Flag_value) @@ -586,60 +655,68 @@ func init() { proto.RegisterType((*CidList)(nil), "CidList") proto.RegisterType((*Block)(nil), "Block") proto.RegisterType((*Error)(nil), "Error") + proto.RegisterType((*OrderPaymentTxn)(nil), "OrderPaymentTxn") } -func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) } +func init() { + proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) +} var fileDescriptor_33c57e4bae7b9afd = []byte{ - // 787 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x41, 0x8f, 0x9b, 0x46, - 0x14, 0x0e, 0x36, 0x5e, 0xec, 0x87, 0x77, 0x33, 0x3b, 0xdd, 0x46, 0x74, 0x95, 0xa6, 0x16, 0x87, - 0xca, 0xbd, 0x10, 0x69, 0x23, 0x55, 0xbd, 0xb2, 0x30, 0xa4, 0x34, 0x18, 0xac, 0x31, 0x4e, 0xb5, - 0xb9, 0x58, 0xd8, 0x4c, 0x5c, 0x1a, 0x1b, 0x28, 0xe0, 0x56, 0xee, 0xad, 0x87, 0xfe, 0xa2, 0xfe, - 0x9e, 0xfe, 0x8b, 0x9e, 0xab, 0x6a, 0x86, 0xa1, 0xde, 0x4d, 0xa5, 0x95, 0x7a, 0xe2, 0xbd, 0xef, - 0x7d, 0xbc, 0x79, 0xef, 0x9b, 0x0f, 0xe0, 0x7c, 0xcf, 0xea, 0x3a, 0xd9, 0x32, 0xab, 0xac, 0x8a, - 0xa6, 0xb8, 0xfe, 0x6c, 0x5b, 0x14, 0xdb, 0x1d, 0x7b, 0x29, 0xb2, 0xf5, 0xe1, 0xfd, 0xcb, 0x24, - 0x3f, 0xca, 0xd2, 0x17, 0x1f, 0x97, 0x9a, 0x6c, 0xcf, 0xea, 0x26, 0xd9, 0x97, 0x2d, 0xc1, 0xfc, - 0x43, 0x05, 0x6d, 0xd6, 0x76, 0xc3, 0x5f, 0x83, 0x2e, 0x1b, 0xc7, 0xc7, 0x92, 0x19, 0xca, 0x44, - 0x99, 0x5e, 0xdc, 0x5c, 0x59, 0xb2, 0xdc, 0x3d, 0x79, 0x8d, 0xde, 0x27, 0x62, 0x0b, 0xb4, 0x32, - 0x39, 0xee, 0x8a, 0x24, 0x35, 0x7a, 0x13, 0x65, 0xaa, 0xdf, 0x5c, 0x59, 0xed, 0xb1, 0x56, 0x77, - 0xac, 0x65, 0xe7, 0x47, 0xda, 0x91, 0xf0, 0x73, 0x18, 0x55, 0xec, 0xa7, 0x03, 0xab, 0x1b, 0x3f, - 0x35, 0xfa, 0x13, 0x65, 0x3a, 0xa0, 0x27, 0x00, 0xbf, 0x00, 0xc8, 0x6a, 0xca, 0xea, 0xb2, 0xc8, - 0x6b, 0x66, 0xa8, 0x13, 0x65, 0x3a, 0xa4, 0xf7, 0x10, 0xf3, 0xb7, 0x3e, 0xe8, 0xf7, 0x46, 0xc1, - 0x43, 0x50, 0xe7, 0x7e, 0xf8, 0x1a, 0x3d, 0xe1, 0x91, 0xf3, 0xad, 0x1d, 0x23, 0x05, 0x03, 0x9c, - 0x79, 0x51, 0x10, 0x44, 0xdf, 0xa3, 0x1e, 0x1e, 0xc3, 0x70, 0x19, 0xca, 0xac, 0x8f, 0x47, 0x30, - 0x88, 0xa8, 0x4b, 0x28, 0x52, 0x31, 0x82, 0xb1, 0x08, 0x57, 0x94, 0x7c, 0x47, 0x9c, 0x18, 0x0d, - 0x4e, 0x88, 0x63, 0x87, 0x0e, 0x09, 0xd0, 0x19, 0x7e, 0x06, 0x58, 0x22, 0x51, 0xe8, 0xf9, 0x74, - 0x66, 0xc7, 0x7e, 0x14, 0x22, 0x0d, 0x7f, 0x0a, 0x97, 0x2d, 0xee, 0x2d, 0x03, 0xcf, 0x0f, 0x82, - 0x19, 0x09, 0x63, 0x34, 0xc4, 0x57, 0x80, 0x3a, 0xfa, 0x6c, 0x1e, 0x10, 0x41, 0x1e, 0xf1, 0xb6, - 0xae, 0xbf, 0x98, 0x2f, 0x63, 0xb2, 0x8a, 0xe6, 0x24, 0x44, 0x80, 0x31, 0x5c, 0x74, 0xc8, 0x72, - 0xee, 0xda, 0x31, 0x41, 0x3a, 0xbe, 0x84, 0xf3, 0x0e, 0x73, 0x82, 0x68, 0x41, 0xd0, 0x98, 0xaf, - 0x41, 0x89, 0xb7, 0x0c, 0x5d, 0x74, 0x8e, 0x9f, 0x82, 0x1e, 0x79, 0x5e, 0xe0, 0x87, 0x64, 0x65, - 0x3b, 0x6f, 0xd0, 0x05, 0xe7, 0x77, 0x00, 0x25, 0x81, 0x7d, 0x87, 0x9e, 0x72, 0x68, 0x16, 0xb9, - 0x84, 0xda, 0x71, 0x44, 0x57, 0xb6, 0xeb, 0x22, 0xc4, 0x27, 0x3a, 0x41, 0x94, 0xcc, 0xa2, 0xb7, - 0x04, 0x5d, 0x72, 0x15, 0x16, 0x71, 0x44, 0x09, 0xc2, 0x3c, 0xbc, 0x0d, 0x22, 0xe7, 0x0d, 0xfa, - 0x04, 0x3f, 0x07, 0xe3, 0x2d, 0x09, 0xdd, 0x88, 0xae, 0x3c, 0x3f, 0xb4, 0x03, 0xff, 0x1d, 0x71, - 0x57, 0x73, 0xfb, 0x4e, 0xec, 0x76, 0x85, 0x01, 0x06, 0x84, 0xd2, 0x88, 0xa2, 0xbf, 0xfa, 0x66, - 0x0a, 0x43, 0x92, 0xff, 0xcc, 0x76, 0x45, 0xc9, 0xb0, 0x09, 0x9a, 0x34, 0x83, 0x70, 0x8c, 0x7e, - 0x33, 0xec, 0x9c, 0x42, 0xbb, 0x02, 0x7e, 0x06, 0x67, 0xe5, 0x61, 0xfd, 0x81, 0x1d, 0x85, 0x41, - 0xc6, 0x54, 0x66, 0xdc, 0x09, 0x75, 0xb6, 0xcd, 0x93, 0xe6, 0x50, 0x31, 0xe1, 0x84, 0x31, 0x3d, - 0x01, 0xe6, 0x9f, 0x0a, 0xa8, 0xce, 0x0f, 0x49, 0xc3, 0x69, 0xb2, 0x93, 0x9f, 0x8a, 0x43, 0x46, - 0xf4, 0x04, 0x60, 0x03, 0xb4, 0xfa, 0xb0, 0xfe, 0x91, 0x6d, 0x1a, 0xd1, 0x7d, 0x44, 0xbb, 0x94, - 0x57, 0xba, 0xd1, 0xfa, 0x6d, 0xa5, 0x1b, 0xe8, 0x1b, 0x18, 0xfd, 0xfb, 0x25, 0x08, 0x8f, 0xe9, - 0x37, 0xd7, 0xff, 0x31, 0x6d, 0xdc, 0x31, 0xe8, 0x89, 0x8c, 0x5f, 0x80, 0xfa, 0x7e, 0x97, 0x6c, - 0x8d, 0x81, 0xf8, 0x3a, 0xc0, 0xe2, 0x03, 0x5a, 0xde, 0x2e, 0xd9, 0x52, 0x81, 0x9b, 0x5f, 0x81, - 0xca, 0x33, 0xac, 0x83, 0x36, 0x23, 0x8b, 0x85, 0xfd, 0x9a, 0xa0, 0x27, 0xfc, 0x22, 0xe3, 0x3b, - 0xe1, 0x52, 0x85, 0xbb, 0x94, 0x12, 0xdb, 0x45, 0x3d, 0xf3, 0x6f, 0x05, 0x60, 0x91, 0x6d, 0x73, - 0x96, 0xba, 0x49, 0x93, 0x60, 0x13, 0xc6, 0x35, 0xcb, 0x53, 0x56, 0xcd, 0x5b, 0xa9, 0x14, 0xa1, - 0xc7, 0x03, 0x0c, 0x7f, 0x09, 0x17, 0x35, 0xab, 0xb2, 0x64, 0x97, 0xfd, 0xda, 0xbe, 0x25, 0x05, - 0xfd, 0x08, 0x7d, 0x5c, 0xd8, 0xeb, 0xdf, 0x15, 0xd0, 0x9c, 0x62, 0xbf, 0x4f, 0xf2, 0x54, 0x5c, - 0x0d, 0x63, 0x95, 0xef, 0x4a, 0x61, 0x65, 0x86, 0xa7, 0xa0, 0x36, 0xfc, 0x2f, 0xd0, 0x7b, 0xe4, - 0x2f, 0x20, 0x18, 0x0f, 0xb5, 0xec, 0xff, 0x0f, 0x2d, 0xcd, 0xcf, 0x41, 0x73, 0xb2, 0x34, 0xc8, - 0xea, 0x06, 0x63, 0x50, 0x37, 0x59, 0x5a, 0x1b, 0xca, 0xa4, 0x3f, 0x1d, 0x51, 0x11, 0x9b, 0xaf, - 0x60, 0x70, 0xbb, 0x2b, 0x36, 0x1f, 0xf8, 0x3d, 0x56, 0xc9, 0x2f, 0x62, 0xdd, 0x56, 0x94, 0x2e, - 0xc5, 0x08, 0xfa, 0x9b, 0x2c, 0x95, 0xf7, 0xce, 0x43, 0xf3, 0x0e, 0x06, 0xa4, 0xaa, 0x8a, 0x4a, - 0x74, 0x2c, 0xd2, 0xd6, 0x94, 0xe7, 0x54, 0xc4, 0x5c, 0x62, 0xc6, 0x8b, 0x72, 0x09, 0xf9, 0xde, - 0x03, 0x8c, 0x1f, 0x56, 0x54, 0xa9, 0x50, 0x44, 0x9a, 0x46, 0xa6, 0xb7, 0xea, 0xbb, 0x5e, 0xb9, - 0x5e, 0x9f, 0x89, 0x9d, 0x5e, 0xfd, 0x13, 0x00, 0x00, 0xff, 0xff, 0x67, 0x2d, 0xb7, 0x8c, 0x85, - 0x05, 0x00, 0x00, + // 873 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x41, 0x8f, 0xdb, 0x44, + 0x14, 0xae, 0x63, 0x67, 0x93, 0xbc, 0x64, 0x77, 0x67, 0x87, 0x6d, 0x65, 0x56, 0x6d, 0x89, 0x2c, + 0x84, 0xc2, 0x25, 0x95, 0xb6, 0x12, 0xe2, 0xea, 0xb5, 0xc7, 0x8b, 0xa9, 0x63, 0x47, 0x13, 0xa7, + 0x68, 0x7b, 0x89, 0x9c, 0x78, 0x9a, 0x9a, 0x26, 0xb6, 0xb1, 0x1d, 0x4a, 0xb8, 0x22, 0x7e, 0x11, + 0xbf, 0x87, 0x23, 0xff, 0x00, 0xae, 0x08, 0xcd, 0x78, 0xdc, 0x6c, 0x8a, 0x54, 0xa9, 0xa7, 0xbc, + 0xf7, 0xbd, 0x2f, 0xef, 0xcd, 0x7c, 0xef, 0xf3, 0xc0, 0xe9, 0x96, 0x95, 0x65, 0xb4, 0x66, 0xe3, + 0xbc, 0xc8, 0xaa, 0xec, 0xea, 0xf3, 0x75, 0x96, 0xad, 0x37, 0xec, 0x99, 0xc8, 0x96, 0xbb, 0xd7, + 0xcf, 0xa2, 0x74, 0x2f, 0x4b, 0x5f, 0x7c, 0x58, 0xaa, 0x92, 0x2d, 0x2b, 0xab, 0x68, 0x9b, 0xd7, + 0x04, 0xe3, 0x2f, 0x0d, 0x3a, 0x93, 0xba, 0x1b, 0xfe, 0x06, 0xfa, 0xb2, 0x71, 0xb8, 0xcf, 0x99, + 0xae, 0x0c, 0x95, 0xd1, 0xd9, 0xf5, 0xe5, 0x58, 0x96, 0x9b, 0x5f, 0x5e, 0xa3, 0xf7, 0x89, 0x78, + 0x0c, 0x9d, 0x3c, 0xda, 0x6f, 0xb2, 0x28, 0xd6, 0x5b, 0x43, 0x65, 0xd4, 0xbf, 0xbe, 0x1c, 0xd7, + 0x63, 0xc7, 0xcd, 0xd8, 0xb1, 0x99, 0xee, 0x69, 0x43, 0xc2, 0x8f, 0xa1, 0x57, 0xb0, 0x9f, 0x76, + 0xac, 0xac, 0xdc, 0x58, 0x57, 0x87, 0xca, 0xa8, 0x4d, 0x0f, 0x00, 0x7e, 0x0a, 0x90, 0x94, 0x94, + 0x95, 0x79, 0x96, 0x96, 0x4c, 0xd7, 0x86, 0xca, 0xa8, 0x4b, 0xef, 0x21, 0xc6, 0x1f, 0x2a, 0xf4, + 0xef, 0x1d, 0x05, 0x77, 0x41, 0x9b, 0xba, 0xfe, 0x2d, 0x7a, 0xc0, 0x23, 0xeb, 0x3b, 0x33, 0x44, + 0x0a, 0x06, 0x38, 0x71, 0x02, 0xcf, 0x0b, 0x7e, 0x40, 0x2d, 0x3c, 0x80, 0xee, 0xdc, 0x97, 0x99, + 0x8a, 0x7b, 0xd0, 0x0e, 0xa8, 0x4d, 0x28, 0xd2, 0x30, 0x82, 0x81, 0x08, 0x17, 0x94, 0x7c, 0x4f, + 0xac, 0x10, 0xb5, 0x0f, 0x88, 0x65, 0xfa, 0x16, 0xf1, 0xd0, 0x09, 0x7e, 0x04, 0x58, 0x22, 0x81, + 0xef, 0xb8, 0x74, 0x62, 0x86, 0x6e, 0xe0, 0xa3, 0x0e, 0x7e, 0x08, 0x17, 0x35, 0xee, 0xcc, 0x3d, + 0xc7, 0xf5, 0xbc, 0x09, 0xf1, 0x43, 0xd4, 0xc5, 0x97, 0x80, 0x1a, 0xfa, 0x64, 0xea, 0x11, 0x41, + 0xee, 0xf1, 0xb6, 0xb6, 0x3b, 0x9b, 0xce, 0x43, 0xb2, 0x08, 0xa6, 0xc4, 0x47, 0x80, 0x31, 0x9c, + 0x35, 0xc8, 0x7c, 0x6a, 0x9b, 0x21, 0x41, 0x7d, 0x7c, 0x01, 0xa7, 0x0d, 0x66, 0x79, 0xc1, 0x8c, + 0xa0, 0x01, 0xbf, 0x06, 0x25, 0xce, 0xdc, 0xb7, 0xd1, 0x29, 0x3e, 0x87, 0x7e, 0xe0, 0x38, 0x9e, + 0xeb, 0x93, 0x85, 0x69, 0xbd, 0x40, 0x67, 0x9c, 0xdf, 0x00, 0x94, 0x78, 0xe6, 0x1d, 0x3a, 0xe7, + 0xd0, 0x24, 0xb0, 0x09, 0x35, 0xc3, 0x80, 0x2e, 0x4c, 0xdb, 0x46, 0x88, 0x9f, 0xe8, 0x00, 0x51, + 0x32, 0x09, 0x5e, 0x12, 0x74, 0xc1, 0x55, 0x98, 0x85, 0x01, 0x25, 0x08, 0xf3, 0xf0, 0xc6, 0x0b, + 0xac, 0x17, 0xe8, 0x33, 0xfc, 0x18, 0xf4, 0x97, 0xc4, 0xb7, 0x03, 0xba, 0x70, 0x5c, 0xdf, 0xf4, + 0xdc, 0x57, 0xc4, 0x5e, 0x4c, 0xcd, 0x3b, 0x71, 0xb7, 0x4b, 0x31, 0x4f, 0xdc, 0xad, 0x81, 0x1e, + 0x62, 0x80, 0x36, 0xa1, 0x34, 0xa0, 0xe8, 0x6f, 0x15, 0x3f, 0x01, 0x5d, 0x96, 0x69, 0x60, 0x91, + 0xd9, 0xcc, 0xf5, 0x6f, 0x17, 0x8e, 0xe9, 0x7a, 0x73, 0x4a, 0xd0, 0x3f, 0xaa, 0x11, 0x43, 0x97, + 0xa4, 0x3f, 0xb3, 0x4d, 0x96, 0x33, 0x6c, 0x40, 0x47, 0xda, 0x47, 0x78, 0xac, 0x7f, 0xdd, 0x6d, + 0xbc, 0x45, 0x9b, 0x02, 0x7e, 0x04, 0x27, 0xf9, 0x6e, 0xf9, 0x96, 0xed, 0x85, 0xa5, 0x06, 0x54, + 0x66, 0xdc, 0x3b, 0x65, 0xb2, 0x4e, 0xa3, 0x6a, 0x57, 0x30, 0xe1, 0x9d, 0x01, 0x3d, 0x00, 0xc6, + 0x9f, 0x0a, 0x68, 0xd6, 0x9b, 0xa8, 0xe2, 0x34, 0xd9, 0xc9, 0x8d, 0xc5, 0x90, 0x1e, 0x3d, 0x00, + 0x58, 0x87, 0x4e, 0xb9, 0x5b, 0xfe, 0xc8, 0x56, 0x95, 0xe8, 0xde, 0xa3, 0x4d, 0xca, 0x2b, 0xcd, + 0xd1, 0xd4, 0xba, 0xd2, 0x1c, 0xe8, 0x5b, 0xe8, 0xbd, 0xff, 0x76, 0x84, 0x2b, 0xfb, 0xd7, 0x57, + 0xff, 0xb3, 0x79, 0xd8, 0x30, 0xe8, 0x81, 0x8c, 0x9f, 0x82, 0xf6, 0x7a, 0x13, 0xad, 0xf5, 0xb6, + 0xf8, 0x9e, 0x60, 0xcc, 0x0f, 0x38, 0x76, 0x36, 0xd1, 0x9a, 0x0a, 0xdc, 0xf8, 0x1a, 0x34, 0x9e, + 0xe1, 0x3e, 0x74, 0x26, 0x64, 0x36, 0x33, 0x6f, 0x09, 0x7a, 0xc0, 0x57, 0x1f, 0xde, 0x09, 0x5f, + 0x2b, 0xdc, 0xd7, 0x94, 0x98, 0x36, 0x6a, 0x19, 0xff, 0x2a, 0x00, 0xb3, 0x64, 0x9d, 0xb2, 0xd8, + 0x8e, 0xaa, 0x08, 0x1b, 0x30, 0x28, 0x59, 0x1a, 0xb3, 0x62, 0x5a, 0x4b, 0xa5, 0x08, 0x3d, 0x8e, + 0x30, 0xfc, 0x15, 0x9c, 0x95, 0xac, 0x48, 0xa2, 0x4d, 0xf2, 0x6b, 0xfd, 0x2f, 0x29, 0xe8, 0x07, + 0xe8, 0xc7, 0x85, 0xbd, 0xfa, 0x5d, 0x81, 0x8e, 0x95, 0x6d, 0xb7, 0x51, 0x1a, 0x8b, 0xd5, 0x30, + 0x56, 0xb8, 0xb6, 0x14, 0x56, 0x66, 0x78, 0x04, 0x5a, 0xc5, 0xdf, 0x8d, 0xd6, 0x47, 0xde, 0x0d, + 0xc1, 0x38, 0xd6, 0x52, 0xfd, 0x04, 0x2d, 0x8d, 0x27, 0xd0, 0xb1, 0x92, 0xd8, 0x4b, 0xca, 0x0a, + 0x63, 0xd0, 0x56, 0x49, 0x5c, 0xea, 0xca, 0x50, 0x1d, 0xf5, 0xa8, 0x88, 0x8d, 0xe7, 0xd0, 0xbe, + 0xd9, 0x64, 0xab, 0xb7, 0x7c, 0x8f, 0x45, 0xf4, 0x4e, 0x5c, 0xb7, 0x16, 0xa5, 0x49, 0x31, 0x02, + 0x75, 0x95, 0xc4, 0x72, 0xef, 0x3c, 0x34, 0xee, 0xa0, 0x4d, 0x8a, 0x22, 0x2b, 0x44, 0xc7, 0x2c, + 0xae, 0x4d, 0x79, 0x4a, 0x45, 0xcc, 0x25, 0x66, 0xbc, 0x28, 0x2f, 0x21, 0xff, 0x77, 0x84, 0xf1, + 0x61, 0x59, 0x11, 0x0b, 0x45, 0xa4, 0x69, 0x64, 0x6a, 0xfc, 0xa6, 0xc0, 0x79, 0xc0, 0xe3, 0x69, + 0xb4, 0xdf, 0xb2, 0xb4, 0x0a, 0x7f, 0x49, 0xeb, 0x29, 0x49, 0x2a, 0xc5, 0x13, 0xf1, 0xfd, 0x0e, + 0xad, 0xa3, 0x0e, 0xf8, 0x4b, 0x38, 0xad, 0x8a, 0x28, 0x2d, 0xa3, 0x55, 0x95, 0x64, 0xe9, 0xfb, + 0x09, 0xc7, 0x20, 0x5f, 0xde, 0xbb, 0xa4, 0x7a, 0xe3, 0xa6, 0xf9, 0xae, 0x92, 0x4f, 0xe6, 0x01, + 0xb8, 0xd1, 0x5e, 0xb5, 0xf2, 0xe5, 0xf2, 0x44, 0x28, 0xfb, 0xfc, 0xbf, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x0b, 0x9f, 0x9a, 0x3b, 0x3d, 0x06, 0x00, 0x00, } diff --git a/pb/moderator.pb.go b/pb/moderator.pb.go index 91066c2968..2d043298a4 100644 --- a/pb/moderator.pb.go +++ b/pb/moderator.pb.go @@ -175,11 +175,13 @@ func (m *Moderator_Fee) GetFeeType() Moderator_Fee_FeeType { } type Moderator_Price struct { - CurrencyCode string `protobuf:"bytes,1,opt,name=currencyCode,proto3" json:"currencyCode,omitempty"` - Amount uint64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + CurrencyCode string `protobuf:"bytes,1,opt,name=currencyCode,proto3" json:"currencyCode,omitempty"` // Deprecated: Do not use. + Amount uint64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` // Deprecated: Do not use. + BigAmount string `protobuf:"bytes,3,opt,name=bigAmount,proto3" json:"bigAmount,omitempty"` + AmountCurrency *CurrencyDefinition `protobuf:"bytes,4,opt,name=amountCurrency,proto3" json:"amountCurrency,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Moderator_Price) Reset() { *m = Moderator_Price{} } @@ -207,6 +209,7 @@ func (m *Moderator_Price) XXX_DiscardUnknown() { var xxx_messageInfo_Moderator_Price proto.InternalMessageInfo +// Deprecated: Do not use. func (m *Moderator_Price) GetCurrencyCode() string { if m != nil { return m.CurrencyCode @@ -214,6 +217,7 @@ func (m *Moderator_Price) GetCurrencyCode() string { return "" } +// Deprecated: Do not use. func (m *Moderator_Price) GetAmount() uint64 { if m != nil { return m.Amount @@ -221,6 +225,20 @@ func (m *Moderator_Price) GetAmount() uint64 { return 0 } +func (m *Moderator_Price) GetBigAmount() string { + if m != nil { + return m.BigAmount + } + return "" +} + +func (m *Moderator_Price) GetAmountCurrency() *CurrencyDefinition { + if m != nil { + return m.AmountCurrency + } + return nil +} + type DisputeUpdate struct { OrderId string `protobuf:"bytes,1,opt,name=orderId,proto3" json:"orderId,omitempty"` PayoutAddress string `protobuf:"bytes,2,opt,name=payoutAddress,proto3" json:"payoutAddress,omitempty"` @@ -292,35 +310,40 @@ func init() { proto.RegisterType((*DisputeUpdate)(nil), "DisputeUpdate") } -func init() { proto.RegisterFile("moderator.proto", fileDescriptor_44f20453d9230215) } +func init() { + proto.RegisterFile("moderator.proto", fileDescriptor_44f20453d9230215) +} var fileDescriptor_44f20453d9230215 = []byte{ - // 429 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xdf, 0x6a, 0xdb, 0x30, - 0x14, 0x87, 0xe7, 0x38, 0x69, 0xe6, 0x93, 0x36, 0x0d, 0x82, 0x15, 0x2f, 0x8c, 0x61, 0xc2, 0x60, - 0xbe, 0x18, 0x66, 0x64, 0x0f, 0x30, 0x32, 0x37, 0x19, 0x85, 0xfd, 0x09, 0x5a, 0x0b, 0x63, 0x37, - 0x45, 0x95, 0x4e, 0x82, 0xa0, 0x91, 0x84, 0x24, 0xc3, 0xb2, 0x27, 0xda, 0x93, 0xec, 0x25, 0xf6, - 0x32, 0xc5, 0x8a, 0xd3, 0x3a, 0x90, 0x0b, 0x5f, 0xe8, 0xfb, 0x7e, 0xc8, 0xe7, 0xe8, 0x1c, 0x38, - 0xdf, 0x68, 0x81, 0x96, 0x79, 0x6d, 0x0b, 0x63, 0xb5, 0xd7, 0xe3, 0x73, 0xae, 0x95, 0xb7, 0x8c, - 0x7b, 0xb7, 0x03, 0x93, 0xff, 0x31, 0x24, 0x5f, 0xf7, 0x21, 0x92, 0xc1, 0x40, 0xa0, 0xe3, 0x56, - 0x1a, 0x2f, 0xb5, 0x4a, 0xa3, 0x2c, 0xca, 0x13, 0xda, 0x46, 0xa4, 0x00, 0xe2, 0xd1, 0x6e, 0xdc, - 0x4c, 0x89, 0x52, 0x2b, 0x21, 0x6b, 0xe8, 0xd2, 0x4e, 0x08, 0x1e, 0x31, 0xe4, 0x15, 0x24, 0xf7, - 0x4c, 0xad, 0x2b, 0xb6, 0x46, 0x97, 0xc6, 0x59, 0x9c, 0x27, 0xf4, 0x09, 0xd4, 0xb7, 0x31, 0xce, - 0xd1, 0x78, 0x14, 0x65, 0x65, 0x2d, 0x2a, 0x2e, 0xd1, 0xa5, 0xdd, 0x10, 0x3b, 0x62, 0x48, 0x06, - 0xf1, 0x0a, 0x31, 0xed, 0x65, 0x51, 0x3e, 0x98, 0x0e, 0x8b, 0xc7, 0xc2, 0x8b, 0x05, 0x22, 0xad, - 0xd5, 0xf8, 0x5f, 0x04, 0xf1, 0x02, 0x91, 0xbc, 0x83, 0xe7, 0x2b, 0xf9, 0x1b, 0xc5, 0x02, 0x31, - 0xb4, 0x31, 0x98, 0x8e, 0x5a, 0xf1, 0xa5, 0x95, 0x1c, 0xe9, 0x63, 0x82, 0xbc, 0x06, 0x30, 0x68, - 0x39, 0x2a, 0xcf, 0xd6, 0x18, 0xba, 0xe9, 0xd0, 0x16, 0x21, 0xef, 0xa1, 0xbf, 0x42, 0xbc, 0xde, - 0x1a, 0x4c, 0xe3, 0x2c, 0xca, 0x87, 0xd3, 0x8b, 0xc3, 0x7f, 0xd7, 0x5f, 0x6d, 0xe9, 0x3e, 0x36, - 0xf9, 0x08, 0xfd, 0x86, 0x91, 0x04, 0x7a, 0x8b, 0xab, 0x9f, 0xf3, 0xcb, 0xd1, 0x33, 0x32, 0x04, - 0x58, 0xce, 0x69, 0x39, 0xff, 0x76, 0x3d, 0xfb, 0x3c, 0x1f, 0x45, 0xe4, 0x25, 0xbc, 0x08, 0xea, - 0x76, 0xf9, 0xe5, 0xe6, 0xc7, 0x6d, 0x4b, 0x75, 0xc6, 0x25, 0xf4, 0x42, 0x95, 0x64, 0x02, 0xa7, - 0x7c, 0xf7, 0x02, 0xdb, 0x52, 0x0b, 0x6c, 0x86, 0x72, 0xc0, 0xc8, 0x05, 0x9c, 0xb0, 0x8d, 0xae, - 0x94, 0x0f, 0xb5, 0x77, 0x69, 0x73, 0x9a, 0xfc, 0x8d, 0xe0, 0xec, 0x52, 0x3a, 0x53, 0x79, 0xbc, - 0x31, 0x82, 0x79, 0x24, 0x29, 0xf4, 0xb5, 0x15, 0x68, 0xaf, 0x44, 0x73, 0xd1, 0xfe, 0x48, 0xde, - 0xc0, 0x99, 0x61, 0x5b, 0x5d, 0xf9, 0x99, 0x10, 0x16, 0xdd, 0x7e, 0xa8, 0x87, 0x90, 0xbc, 0x85, - 0x44, 0x57, 0xde, 0x68, 0xa9, 0xfc, 0x6e, 0x9e, 0x83, 0x69, 0x52, 0x7c, 0x6f, 0x08, 0x7d, 0x72, - 0xf5, 0x68, 0x1d, 0x5a, 0xc9, 0xee, 0xe5, 0x1f, 0xac, 0x17, 0x22, 0x6c, 0x5d, 0xda, 0xcd, 0xa2, - 0xfc, 0x94, 0x1e, 0x31, 0x9f, 0xba, 0xbf, 0x3a, 0xe6, 0xee, 0xee, 0x24, 0x6c, 0xe5, 0x87, 0x87, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x85, 0xeb, 0x32, 0x4a, 0xb9, 0x02, 0x00, 0x00, + // 469 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xdb, 0x8b, 0xd3, 0x40, + 0x14, 0xc6, 0xcd, 0xa5, 0x5b, 0x73, 0xba, 0xdb, 0x2d, 0x23, 0x4a, 0x2c, 0x22, 0xa1, 0x88, 0xf6, + 0x41, 0x82, 0xd4, 0x47, 0x1f, 0xa4, 0xdb, 0x8b, 0x2c, 0x78, 0x29, 0xe3, 0x2e, 0x88, 0x2f, 0xcb, + 0x34, 0x73, 0x5a, 0x06, 0xb6, 0x33, 0xc3, 0x64, 0x02, 0xd6, 0x3f, 0x48, 0xfc, 0x2f, 0x7c, 0xf3, + 0xef, 0x92, 0x4c, 0x92, 0x5e, 0xa4, 0x0f, 0x79, 0xc8, 0xef, 0xfb, 0x48, 0xce, 0x77, 0xce, 0x07, + 0x97, 0x1b, 0xc5, 0xd1, 0x30, 0xab, 0x4c, 0xaa, 0x8d, 0xb2, 0xaa, 0x7f, 0x99, 0x29, 0x69, 0x0d, + 0xcb, 0x6c, 0x5e, 0x81, 0xc1, 0x9f, 0x10, 0xa2, 0x4f, 0x8d, 0x89, 0x24, 0xd0, 0xe1, 0x98, 0x67, + 0x46, 0x68, 0x2b, 0x94, 0x8c, 0xbd, 0xc4, 0x1b, 0x46, 0xf4, 0x10, 0x91, 0x14, 0x88, 0x45, 0xb3, + 0xc9, 0xc7, 0x92, 0x4f, 0x94, 0xe4, 0xa2, 0x84, 0x79, 0xec, 0x3b, 0xe3, 0x09, 0x85, 0x3c, 0x83, + 0xe8, 0x9e, 0xc9, 0x75, 0xc1, 0xd6, 0x98, 0xc7, 0x41, 0x12, 0x0c, 0x23, 0xba, 0x07, 0xe5, 0xd7, + 0x58, 0x96, 0xa1, 0xb6, 0xc8, 0x27, 0x85, 0x31, 0x28, 0x33, 0x81, 0x79, 0x1c, 0x3a, 0xdb, 0x09, + 0x85, 0x24, 0x10, 0xac, 0x10, 0xe3, 0x56, 0xe2, 0x0d, 0x3b, 0xa3, 0x6e, 0xba, 0x1b, 0x3c, 0x9d, + 0x23, 0xd2, 0x52, 0xea, 0xff, 0xf5, 0x20, 0x98, 0x23, 0x92, 0xd7, 0xf0, 0x70, 0x25, 0x7e, 0x20, + 0x9f, 0x23, 0xba, 0x18, 0x9d, 0x51, 0xef, 0xc0, 0xbe, 0x30, 0x22, 0x43, 0xba, 0x73, 0x90, 0xe7, + 0x00, 0x1a, 0x4d, 0x86, 0xd2, 0xb2, 0x35, 0xba, 0x34, 0x3e, 0x3d, 0x20, 0xe4, 0x0d, 0xb4, 0x57, + 0x88, 0x37, 0x5b, 0x8d, 0x71, 0x90, 0x78, 0xc3, 0xee, 0xe8, 0xc9, 0xf1, 0xbf, 0xcb, 0xa7, 0x54, + 0x69, 0x63, 0x1b, 0xbc, 0x87, 0x76, 0xcd, 0x48, 0x04, 0xad, 0xf9, 0xf5, 0xb7, 0xd9, 0xb4, 0xf7, + 0x80, 0x74, 0x01, 0x16, 0x33, 0x3a, 0x99, 0x7d, 0xbe, 0x19, 0x7f, 0x98, 0xf5, 0x3c, 0xf2, 0x14, + 0x1e, 0x3b, 0xe9, 0x6e, 0xf1, 0xf1, 0xf6, 0xeb, 0xdd, 0x81, 0xe4, 0xf7, 0x7f, 0x79, 0xd0, 0x72, + 0x63, 0x92, 0x97, 0x70, 0x9e, 0x55, 0x2b, 0xd8, 0x4e, 0x14, 0xaf, 0xe2, 0x44, 0x57, 0x7e, 0xec, + 0xd1, 0x23, 0x4e, 0xfa, 0x70, 0xc6, 0x36, 0xaa, 0x90, 0xd6, 0x05, 0x08, 0x9d, 0xa3, 0x26, 0xe5, + 0x19, 0x96, 0x62, 0x3d, 0xae, 0xe4, 0xc0, 0x5d, 0x6b, 0x0f, 0xc8, 0x3b, 0xe8, 0x56, 0xbe, 0x7a, + 0xd5, 0xdb, 0x38, 0x74, 0x2b, 0x7b, 0x94, 0x36, 0x60, 0x8a, 0x2b, 0x21, 0xdd, 0x49, 0xe9, 0x7f, + 0xd6, 0xc1, 0x6f, 0x0f, 0x2e, 0xa6, 0x22, 0xd7, 0x85, 0xc5, 0x5b, 0xcd, 0x99, 0x45, 0x12, 0x43, + 0x5b, 0x19, 0x8e, 0xe6, 0x9a, 0xd7, 0x0d, 0x6a, 0x5e, 0xc9, 0x0b, 0xb8, 0xd0, 0x6c, 0xab, 0x0a, + 0x3b, 0xe6, 0xdc, 0x60, 0xde, 0x14, 0xe7, 0x18, 0x92, 0x57, 0x10, 0xa9, 0xc2, 0x6a, 0x25, 0xa4, + 0xad, 0x3a, 0xd3, 0x19, 0x45, 0xe9, 0x97, 0x9a, 0xd0, 0xbd, 0x56, 0xd6, 0x27, 0x47, 0x23, 0xd8, + 0xbd, 0xf8, 0x89, 0x65, 0xe9, 0x5c, 0xb3, 0xdd, 0xec, 0xe7, 0xf4, 0x84, 0x72, 0x15, 0x7e, 0xf7, + 0xf5, 0x72, 0x79, 0xe6, 0x9a, 0xff, 0xf6, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x4d, 0x72, + 0x42, 0x1d, 0x03, 0x00, 0x00, } diff --git a/pb/orders.pb.go b/pb/orders.pb.go index 095d2bd9c2..b190183ffb 100644 --- a/pb/orders.pb.go +++ b/pb/orders.pb.go @@ -108,7 +108,9 @@ func init() { proto.RegisterEnum("OrderState", OrderState_name, OrderState_value) } -func init() { proto.RegisterFile("orders.proto", fileDescriptor_e0f5d4cf0fc9e41b) } +func init() { + proto.RegisterFile("orders.proto", fileDescriptor_e0f5d4cf0fc9e41b) +} var fileDescriptor_e0f5d4cf0fc9e41b = []byte{ // 243 bytes of a gzipped FileDescriptorProto diff --git a/pb/posts.pb.go b/pb/posts.pb.go index 0deb6cfcbb..233231a930 100644 --- a/pb/posts.pb.go +++ b/pb/posts.pb.go @@ -301,7 +301,9 @@ func init() { proto.RegisterType((*SignedPost)(nil), "SignedPost") } -func init() { proto.RegisterFile("posts.proto", fileDescriptor_b14bd1586479c33d) } +func init() { + proto.RegisterFile("posts.proto", fileDescriptor_b14bd1586479c33d) +} var fileDescriptor_b14bd1586479c33d = []byte{ // 429 bytes of a gzipped FileDescriptorProto diff --git a/pb/profile.pb.go b/pb/profile.pb.go index d5043d3b37..4ef042f81f 100644 --- a/pb/profile.pb.go +++ b/pb/profile.pb.go @@ -22,27 +22,31 @@ var _ = math.Inf const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type Profile struct { - PeerID string `protobuf:"bytes,1,opt,name=peerID,proto3" json:"peerID,omitempty"` - Handle string `protobuf:"bytes,2,opt,name=handle,proto3" json:"handle,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - Location string `protobuf:"bytes,4,opt,name=location,proto3" json:"location,omitempty"` - About string `protobuf:"bytes,5,opt,name=about,proto3" json:"about,omitempty"` - ShortDescription string `protobuf:"bytes,6,opt,name=shortDescription,proto3" json:"shortDescription,omitempty"` - Nsfw bool `protobuf:"varint,7,opt,name=nsfw,proto3" json:"nsfw,omitempty"` - Vendor bool `protobuf:"varint,8,opt,name=vendor,proto3" json:"vendor,omitempty"` - Moderator bool `protobuf:"varint,9,opt,name=moderator,proto3" json:"moderator,omitempty"` - ModeratorInfo *Moderator `protobuf:"bytes,10,opt,name=moderatorInfo,proto3" json:"moderatorInfo,omitempty"` - ContactInfo *Profile_Contact `protobuf:"bytes,11,opt,name=contactInfo,proto3" json:"contactInfo,omitempty"` - Colors *Profile_Colors `protobuf:"bytes,12,opt,name=colors,proto3" json:"colors,omitempty"` - AvatarHashes *Profile_Image `protobuf:"bytes,13,opt,name=avatarHashes,proto3" json:"avatarHashes,omitempty"` - HeaderHashes *Profile_Image `protobuf:"bytes,14,opt,name=headerHashes,proto3" json:"headerHashes,omitempty"` - Stats *Profile_Stats `protobuf:"bytes,15,opt,name=stats,proto3" json:"stats,omitempty"` - BitcoinPubkey string `protobuf:"bytes,16,opt,name=bitcoinPubkey,proto3" json:"bitcoinPubkey,omitempty"` - LastModified *timestamp.Timestamp `protobuf:"bytes,17,opt,name=lastModified,proto3" json:"lastModified,omitempty"` - Currencies []string `protobuf:"bytes,18,rep,name=currencies,proto3" json:"currencies,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + PeerID string `protobuf:"bytes,1,opt,name=peerID,proto3" json:"peerID,omitempty"` + Handle string `protobuf:"bytes,2,opt,name=handle,proto3" json:"handle,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Location string `protobuf:"bytes,4,opt,name=location,proto3" json:"location,omitempty"` + About string `protobuf:"bytes,5,opt,name=about,proto3" json:"about,omitempty"` + ShortDescription string `protobuf:"bytes,6,opt,name=shortDescription,proto3" json:"shortDescription,omitempty"` + Nsfw bool `protobuf:"varint,7,opt,name=nsfw,proto3" json:"nsfw,omitempty"` + Vendor bool `protobuf:"varint,8,opt,name=vendor,proto3" json:"vendor,omitempty"` + Moderator bool `protobuf:"varint,9,opt,name=moderator,proto3" json:"moderator,omitempty"` + ModeratorInfo *Moderator `protobuf:"bytes,10,opt,name=moderatorInfo,proto3" json:"moderatorInfo,omitempty"` + ContactInfo *Profile_Contact `protobuf:"bytes,11,opt,name=contactInfo,proto3" json:"contactInfo,omitempty"` + Colors *Profile_Colors `protobuf:"bytes,12,opt,name=colors,proto3" json:"colors,omitempty"` + AvatarHashes *Profile_Image `protobuf:"bytes,13,opt,name=avatarHashes,proto3" json:"avatarHashes,omitempty"` + HeaderHashes *Profile_Image `protobuf:"bytes,14,opt,name=headerHashes,proto3" json:"headerHashes,omitempty"` + Stats *Profile_Stats `protobuf:"bytes,15,opt,name=stats,proto3" json:"stats,omitempty"` + BitcoinPubkey string `protobuf:"bytes,16,opt,name=bitcoinPubkey,proto3" json:"bitcoinPubkey,omitempty"` + LastModified *timestamp.Timestamp `protobuf:"bytes,17,opt,name=lastModified,proto3" json:"lastModified,omitempty"` + Currencies []string `protobuf:"bytes,18,rep,name=currencies,proto3" json:"currencies,omitempty"` + RefundPolicy string `protobuf:"bytes,19,opt,name=refundPolicy,proto3" json:"refundPolicy,omitempty"` + TermsAndConditions string `protobuf:"bytes,20,opt,name=termsAndConditions,proto3" json:"termsAndConditions,omitempty"` + ShippingOptions []*Listing_ShippingOption `protobuf:"bytes,21,rep,name=shippingOptions,proto3" json:"shippingOptions,omitempty"` + Version uint32 `protobuf:"varint,22,opt,name=version,proto3" json:"version,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Profile) Reset() { *m = Profile{} } @@ -196,6 +200,13 @@ func (m *Profile) GetCurrencies() []string { return nil } +func (m *Profile) GetVersion() uint32 { + if m != nil { + return m.Version + } + return 0 +} + type Profile_Contact struct { Website string `protobuf:"bytes,1,opt,name=website,proto3" json:"website,omitempty"` Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` @@ -544,53 +555,55 @@ func init() { proto.RegisterType((*Profile_Stats)(nil), "Profile.Stats") } -func init() { proto.RegisterFile("profile.proto", fileDescriptor_744bf7a47b381504) } +func init() { + proto.RegisterFile("profile.proto", fileDescriptor_744bf7a47b381504) +} var fileDescriptor_744bf7a47b381504 = []byte{ - // 705 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x94, 0xdf, 0x6e, 0xdb, 0x36, - 0x14, 0xc6, 0xe1, 0xff, 0x31, 0x6d, 0x27, 0x19, 0x31, 0x04, 0x84, 0x30, 0x6c, 0x46, 0x10, 0x6c, - 0xc6, 0x2e, 0x94, 0xc1, 0xbb, 0x1f, 0xb0, 0x25, 0x17, 0xcb, 0x45, 0x8a, 0x40, 0x49, 0x6f, 0x7a, - 0x47, 0x49, 0xc7, 0x12, 0x51, 0x49, 0x14, 0x48, 0x2a, 0xa9, 0xd1, 0x47, 0xe8, 0x0b, 0xf4, 0xed, - 0xfa, 0x18, 0xbd, 0x2d, 0x78, 0x48, 0xc9, 0x56, 0xda, 0x3b, 0x7e, 0xbf, 0xf3, 0x1d, 0xfa, 0x90, - 0xfe, 0x28, 0xb2, 0xaa, 0x95, 0xdc, 0x89, 0x02, 0xc2, 0x5a, 0x49, 0x23, 0x83, 0xdf, 0x32, 0x29, - 0xb3, 0x02, 0xae, 0x51, 0xc5, 0xcd, 0xee, 0xda, 0x88, 0x12, 0xb4, 0xe1, 0x65, 0xed, 0x0d, 0x67, - 0xa5, 0x4c, 0x41, 0x71, 0x23, 0x95, 0x03, 0x97, 0x5f, 0x09, 0x99, 0x3d, 0xb8, 0x3d, 0xe8, 0x05, - 0x99, 0xd6, 0x00, 0xea, 0xee, 0x96, 0x0d, 0xd6, 0x83, 0xcd, 0x3c, 0xf2, 0xca, 0xf2, 0x9c, 0x57, - 0x69, 0x01, 0x6c, 0xe8, 0xb8, 0x53, 0x94, 0x92, 0x71, 0xc5, 0x4b, 0x60, 0x23, 0xa4, 0xb8, 0xa6, - 0x01, 0x39, 0x29, 0x64, 0xc2, 0x8d, 0x90, 0x15, 0x1b, 0x23, 0xef, 0x34, 0xfd, 0x99, 0x4c, 0x78, - 0x2c, 0x1b, 0xc3, 0x26, 0x58, 0x70, 0x82, 0xfe, 0x49, 0xce, 0x75, 0x2e, 0x95, 0xb9, 0x05, 0x9d, - 0x28, 0x51, 0x63, 0xe7, 0x14, 0x0d, 0xdf, 0x71, 0xfc, 0x45, 0xbd, 0x7b, 0x61, 0xb3, 0xf5, 0x60, - 0x73, 0x12, 0xe1, 0xda, 0x4e, 0xf7, 0x0c, 0x55, 0x2a, 0x15, 0x3b, 0x41, 0xea, 0x15, 0xfd, 0x85, - 0xcc, 0xbb, 0xc3, 0xb2, 0x39, 0x96, 0x0e, 0x80, 0xfe, 0x45, 0x56, 0x9d, 0xb8, 0xab, 0x76, 0x92, - 0x91, 0xf5, 0x60, 0xb3, 0xd8, 0x92, 0xf0, 0xbe, 0xa5, 0x51, 0xdf, 0x40, 0xb7, 0x64, 0x91, 0xc8, - 0xca, 0xf0, 0xc4, 0xa0, 0x7f, 0x81, 0xfe, 0xf3, 0xd0, 0x5f, 0x5e, 0x78, 0xe3, 0x6a, 0xd1, 0xb1, - 0x89, 0xfe, 0x41, 0xa6, 0x89, 0x2c, 0xa4, 0xd2, 0x6c, 0x89, 0xf6, 0xb3, 0x23, 0xbb, 0xc5, 0x91, - 0x2f, 0xd3, 0x2d, 0x59, 0xf2, 0x67, 0x6e, 0xb8, 0xfa, 0x9f, 0xeb, 0x1c, 0x34, 0x5b, 0xa1, 0xfd, - 0xb4, 0xb3, 0xdf, 0x95, 0x3c, 0x83, 0xa8, 0xe7, 0xb1, 0x3d, 0x39, 0xf0, 0x14, 0xda, 0x9e, 0xd3, - 0x1f, 0xf7, 0x1c, 0x7b, 0xe8, 0x15, 0x99, 0x68, 0xc3, 0x8d, 0x66, 0x67, 0xaf, 0xcc, 0x8f, 0x96, - 0x46, 0xae, 0x48, 0xaf, 0xc8, 0x2a, 0x16, 0x26, 0x91, 0xa2, 0x7a, 0x68, 0xe2, 0xf7, 0xb0, 0x67, - 0xe7, 0xf8, 0x7f, 0xf4, 0x21, 0xfd, 0x87, 0x2c, 0x0b, 0xae, 0xcd, 0xbd, 0x4c, 0xc5, 0x4e, 0x40, - 0xca, 0x7e, 0xc2, 0x2d, 0x83, 0xd0, 0x65, 0x30, 0x6c, 0x33, 0x18, 0x3e, 0xb5, 0x19, 0x8c, 0x7a, - 0x7e, 0xfa, 0x2b, 0x21, 0x49, 0xa3, 0x14, 0x54, 0x89, 0x00, 0xcd, 0xe8, 0x7a, 0xb4, 0x99, 0x47, - 0x47, 0x24, 0xf8, 0x34, 0x20, 0x33, 0x7f, 0xab, 0x94, 0x91, 0xd9, 0x0b, 0xc4, 0x5a, 0x18, 0xf0, - 0xd9, 0x6c, 0xa5, 0x0d, 0x15, 0x94, 0x5c, 0x14, 0x3e, 0x9b, 0x4e, 0xd0, 0x35, 0x59, 0xd4, 0xb9, - 0xac, 0xe0, 0x4d, 0x53, 0xc6, 0xa0, 0x7c, 0x42, 0x8f, 0x11, 0x0d, 0xc9, 0x54, 0xcb, 0x44, 0xf0, - 0x82, 0x8d, 0xd7, 0xa3, 0xcd, 0x62, 0x7b, 0x71, 0xb8, 0x0a, 0xc4, 0xff, 0x26, 0x89, 0x6c, 0x2a, - 0x13, 0x79, 0x57, 0xf0, 0x96, 0xac, 0x7a, 0x05, 0x9b, 0x45, 0xb3, 0xaf, 0xdb, 0x79, 0x70, 0x6d, - 0xd3, 0xdf, 0x68, 0x50, 0xf8, 0x2a, 0xdc, 0x3c, 0x9d, 0xb6, 0x83, 0xd6, 0x4a, 0xca, 0x9d, 0x1f, - 0xc6, 0x89, 0xe0, 0x23, 0x99, 0xe0, 0xff, 0x84, 0xdb, 0x89, 0x6a, 0xdf, 0x6d, 0x27, 0xaa, 0xbd, - 0x6d, 0xd1, 0x25, 0x2f, 0xba, 0xb3, 0xa1, 0xb0, 0x81, 0x2f, 0x21, 0x15, 0x4d, 0xe9, 0x77, 0xf2, - 0xca, 0xba, 0x0b, 0xae, 0x32, 0xf0, 0xef, 0xce, 0x09, 0x3b, 0x92, 0x54, 0x22, 0x13, 0x15, 0x2f, - 0xfc, 0xbb, 0xeb, 0x74, 0xf0, 0x79, 0x40, 0xa6, 0x2e, 0x88, 0xf6, 0x82, 0x6b, 0x25, 0x4a, 0xae, - 0xda, 0x09, 0x5a, 0x69, 0xdf, 0x91, 0x86, 0x44, 0x56, 0xa9, 0xad, 0xb9, 0x41, 0x0e, 0x00, 0xc7, - 0x86, 0x0f, 0xa6, 0xfd, 0x06, 0xd8, 0xb5, 0xed, 0xc8, 0x45, 0x96, 0x17, 0x22, 0xcb, 0x8d, 0x1f, - 0xe6, 0x00, 0x6c, 0xb8, 0x3a, 0xf1, 0x64, 0x5b, 0xdd, 0x54, 0x7d, 0x18, 0x7c, 0x19, 0x90, 0xc9, - 0x63, 0x1b, 0xc6, 0x9d, 0x2c, 0x0a, 0xf9, 0x02, 0xea, 0xc6, 0x5e, 0x3c, 0xce, 0xb7, 0x8a, 0xfa, - 0x90, 0xfe, 0x4e, 0x4e, 0x1d, 0x10, 0x55, 0xe6, 0x6c, 0x43, 0xb4, 0xbd, 0xa2, 0xf4, 0x92, 0x2c, - 0x0b, 0xa1, 0x4d, 0xe7, 0x1a, 0xa1, 0xab, 0xc7, 0x6c, 0x78, 0x14, 0x3f, 0x58, 0xc6, 0x68, 0x39, - 0x46, 0xf6, 0x84, 0xb5, 0xd4, 0xc6, 0xd5, 0x27, 0x58, 0x3f, 0x00, 0x3b, 0x31, 0x7f, 0x06, 0x65, - 0x5f, 0x1f, 0xf6, 0xe0, 0xe7, 0x6c, 0x18, 0xf5, 0xe1, 0x7f, 0xe3, 0x77, 0xc3, 0x3a, 0x8e, 0xa7, - 0xf8, 0x4c, 0xfe, 0xfe, 0x16, 0x00, 0x00, 0xff, 0xff, 0x8b, 0x91, 0xda, 0x73, 0xc9, 0x05, 0x00, - 0x00, + // 716 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x94, 0xcf, 0x6e, 0xc3, 0x44, + 0x10, 0xc6, 0xe5, 0xfc, 0x6d, 0x36, 0x49, 0x5b, 0x16, 0x54, 0xad, 0x2c, 0x04, 0x51, 0x55, 0x41, + 0xc4, 0xc1, 0x45, 0xe1, 0x8e, 0x04, 0xed, 0x81, 0x1e, 0x8a, 0x2a, 0xb7, 0x5c, 0xb8, 0xad, 0xed, + 0x89, 0xbd, 0xc2, 0xf6, 0x5a, 0xbb, 0xeb, 0x94, 0x88, 0x47, 0xe0, 0xc4, 0x8d, 0xb7, 0xe3, 0x55, + 0xd0, 0xce, 0xae, 0x9d, 0xb8, 0x70, 0xf3, 0xf7, 0x9b, 0x6f, 0x36, 0xe3, 0xcd, 0x37, 0x26, 0xeb, + 0x46, 0xc9, 0xbd, 0x28, 0x21, 0x6a, 0x94, 0x34, 0x32, 0xfc, 0x32, 0x97, 0x32, 0x2f, 0xe1, 0x1e, + 0x55, 0xd2, 0xee, 0xef, 0x8d, 0xa8, 0x40, 0x1b, 0x5e, 0x35, 0xde, 0x70, 0x55, 0xc9, 0x0c, 0x14, + 0x37, 0x52, 0x39, 0x70, 0xfb, 0xd7, 0x92, 0xcc, 0x5f, 0xdc, 0x19, 0xf4, 0x86, 0xcc, 0x1a, 0x00, + 0xf5, 0xf4, 0xc8, 0x82, 0x4d, 0xb0, 0x5d, 0xc4, 0x5e, 0x59, 0x5e, 0xf0, 0x3a, 0x2b, 0x81, 0x8d, + 0x1c, 0x77, 0x8a, 0x52, 0x32, 0xa9, 0x79, 0x05, 0x6c, 0x8c, 0x14, 0x9f, 0x69, 0x48, 0x2e, 0x4a, + 0x99, 0x72, 0x23, 0x64, 0xcd, 0x26, 0xc8, 0x7b, 0x4d, 0x3f, 0x23, 0x53, 0x9e, 0xc8, 0xd6, 0xb0, + 0x29, 0x16, 0x9c, 0xa0, 0xdf, 0x90, 0x6b, 0x5d, 0x48, 0x65, 0x1e, 0x41, 0xa7, 0x4a, 0x34, 0xd8, + 0x39, 0x43, 0xc3, 0x7f, 0x38, 0xfe, 0xa2, 0xde, 0xbf, 0xb3, 0xf9, 0x26, 0xd8, 0x5e, 0xc4, 0xf8, + 0x6c, 0xa7, 0x3b, 0x40, 0x9d, 0x49, 0xc5, 0x2e, 0x90, 0x7a, 0x45, 0x3f, 0x27, 0x8b, 0xfe, 0x65, + 0xd9, 0x02, 0x4b, 0x27, 0x40, 0xbf, 0x25, 0xeb, 0x5e, 0x3c, 0xd5, 0x7b, 0xc9, 0xc8, 0x26, 0xd8, + 0x2e, 0x77, 0x24, 0x7a, 0xee, 0x68, 0x3c, 0x34, 0xd0, 0x1d, 0x59, 0xa6, 0xb2, 0x36, 0x3c, 0x35, + 0xe8, 0x5f, 0xa2, 0xff, 0x3a, 0xf2, 0x97, 0x17, 0x3d, 0xb8, 0x5a, 0x7c, 0x6e, 0xa2, 0x5f, 0x93, + 0x59, 0x2a, 0x4b, 0xa9, 0x34, 0x5b, 0xa1, 0xfd, 0xea, 0xcc, 0x6e, 0x71, 0xec, 0xcb, 0x74, 0x47, + 0x56, 0xfc, 0xc0, 0x0d, 0x57, 0x3f, 0x71, 0x5d, 0x80, 0x66, 0x6b, 0xb4, 0x5f, 0xf6, 0xf6, 0xa7, + 0x8a, 0xe7, 0x10, 0x0f, 0x3c, 0xb6, 0xa7, 0x00, 0x9e, 0x41, 0xd7, 0x73, 0xf9, 0xff, 0x3d, 0xe7, + 0x1e, 0x7a, 0x47, 0xa6, 0xda, 0x70, 0xa3, 0xd9, 0xd5, 0x07, 0xf3, 0xab, 0xa5, 0xb1, 0x2b, 0xd2, + 0x3b, 0xb2, 0x4e, 0x84, 0x49, 0xa5, 0xa8, 0x5f, 0xda, 0xe4, 0x37, 0x38, 0xb2, 0x6b, 0xfc, 0x3f, + 0x86, 0x90, 0x7e, 0x4f, 0x56, 0x25, 0xd7, 0xe6, 0x59, 0x66, 0x62, 0x2f, 0x20, 0x63, 0x9f, 0xe0, + 0x91, 0x61, 0xe4, 0x32, 0x18, 0x75, 0x19, 0x8c, 0xde, 0xba, 0x0c, 0xc6, 0x03, 0x3f, 0xfd, 0x82, + 0x90, 0xb4, 0x55, 0x0a, 0xea, 0x54, 0x80, 0x66, 0x74, 0x33, 0xde, 0x2e, 0xe2, 0x33, 0x42, 0x19, + 0x99, 0x1f, 0x40, 0x69, 0x9b, 0x87, 0x4f, 0x37, 0xc1, 0x76, 0x1d, 0x77, 0x32, 0xfc, 0x33, 0x20, + 0x73, 0x7f, 0xdf, 0xd6, 0xf5, 0x0e, 0x89, 0x16, 0x06, 0x7c, 0x6a, 0x3b, 0x69, 0xe3, 0x06, 0x15, + 0x17, 0xa5, 0x4f, 0xad, 0x13, 0x74, 0x43, 0x96, 0x4d, 0x21, 0x6b, 0xf8, 0xb9, 0xad, 0x12, 0x50, + 0x3e, 0xbb, 0xe7, 0x88, 0x46, 0x64, 0xa6, 0x65, 0x2a, 0x78, 0xc9, 0x26, 0x9b, 0xf1, 0x76, 0xb9, + 0xbb, 0x39, 0x5d, 0x12, 0xe2, 0x1f, 0xd2, 0x54, 0xb6, 0xb5, 0x89, 0xbd, 0x2b, 0xfc, 0x85, 0xac, + 0x07, 0x05, 0x9b, 0x52, 0x73, 0x6c, 0xba, 0x79, 0xf0, 0xd9, 0xee, 0x45, 0xab, 0x41, 0xe1, 0xbe, + 0xb8, 0x79, 0x7a, 0x6d, 0x07, 0x6d, 0x94, 0x94, 0x7b, 0x3f, 0x8c, 0x13, 0xe1, 0x1f, 0x64, 0x8a, + 0xff, 0x20, 0x1e, 0x27, 0xea, 0x63, 0x7f, 0x9c, 0xa8, 0x8f, 0xb6, 0x45, 0x57, 0xbc, 0xec, 0xdf, + 0x0d, 0x85, 0x5d, 0x85, 0x0a, 0x32, 0xd1, 0x56, 0xfe, 0x24, 0xaf, 0xac, 0xbb, 0xe4, 0x2a, 0x07, + 0xbf, 0x91, 0x4e, 0xd8, 0x91, 0xa4, 0x12, 0xb9, 0xa8, 0x79, 0xe9, 0x37, 0xb2, 0xd7, 0xe1, 0xdf, + 0x01, 0x99, 0xb9, 0x88, 0xda, 0x0b, 0x6e, 0x94, 0xa8, 0xb8, 0xea, 0x26, 0xe8, 0xa4, 0xdd, 0x30, + 0x0d, 0xa9, 0xac, 0x33, 0x5b, 0x73, 0x83, 0x9c, 0x00, 0x8e, 0x0d, 0xbf, 0x9b, 0xee, 0xeb, 0x60, + 0x9f, 0x6d, 0x47, 0x21, 0xf2, 0xa2, 0x14, 0x79, 0x61, 0xfc, 0x30, 0x27, 0x60, 0x63, 0xd7, 0x8b, + 0x37, 0xdb, 0xea, 0xa6, 0x1a, 0xc2, 0xf0, 0x9f, 0x80, 0x4c, 0x5f, 0xbb, 0x98, 0xee, 0x65, 0x59, + 0xca, 0x77, 0x50, 0x0f, 0xf6, 0xe2, 0x71, 0xbe, 0x75, 0x3c, 0x84, 0xf4, 0x2b, 0x72, 0xe9, 0x80, + 0xa8, 0x73, 0x67, 0x1b, 0xa1, 0xed, 0x03, 0xa5, 0xb7, 0x64, 0x55, 0x0a, 0x6d, 0x7a, 0xd7, 0x18, + 0x5d, 0x03, 0x66, 0xc3, 0xa3, 0xf8, 0xc9, 0x32, 0x41, 0xcb, 0x39, 0xb2, 0x6f, 0xd8, 0x48, 0x6d, + 0x5c, 0x7d, 0x8a, 0xf5, 0x13, 0xb0, 0x13, 0xf3, 0x03, 0x28, 0xbb, 0x97, 0xd8, 0x83, 0x1f, 0xba, + 0x51, 0x3c, 0x84, 0x3f, 0x4e, 0x7e, 0x1d, 0x35, 0x49, 0x32, 0xc3, 0x05, 0xfa, 0xee, 0xdf, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x5e, 0x37, 0x9d, 0x98, 0xe3, 0x05, 0x00, 0x00, } diff --git a/pb/protos/api.proto b/pb/protos/api.proto index 5374955254..aec50955a3 100644 --- a/pb/protos/api.proto +++ b/pb/protos/api.proto @@ -44,10 +44,12 @@ message CaseRespApi { message TransactionRecord { string txid = 1; - int64 value = 2; + int64 value = 2 [deprecated = true]; uint32 confirmations = 3; uint32 height = 4; google.protobuf.Timestamp timestamp = 5; + CurrencyDefinition currency = 6; + string bigValue = 7; } message PeerAndProfile { @@ -65,4 +67,4 @@ message RatingWithID { string id = 1; string ratingId = 2; Rating rating = 3; -} \ No newline at end of file +} diff --git a/pb/protos/contracts.proto b/pb/protos/contracts.proto index 8344efb522..c643ba40b8 100644 --- a/pb/protos/contracts.proto +++ b/pb/protos/contracts.proto @@ -3,6 +3,7 @@ option go_package = "pb"; import "countrycodes.proto"; +import "message.proto"; import "google/protobuf/timestamp.proto"; message RicardianContract { @@ -19,6 +20,11 @@ message RicardianContract { repeated string errors = 11; } +message CurrencyDefinition { + string code = 1; + uint32 divisibility = 2; +} // added schema v5 + message Listing { string slug = 1; ID vendorID = 2; @@ -33,17 +39,19 @@ message Listing { bool testnet = 11; message Metadata { - uint32 version = 1; - ContractType contractType = 2; - Format format = 3; - google.protobuf.Timestamp expiry = 4; - repeated string acceptedCurrencies = 5; - string pricingCurrency = 6; - string language = 7; - uint32 escrowTimeoutHours = 8; - string coinType = 9; - uint32 coinDivisibility = 10; - float priceModifier = 11; + uint32 version = 1; + ContractType contractType = 2; + Format format = 3; + google.protobuf.Timestamp expiry = 4; + repeated string acceptedCurrencies = 5; + string pricingCurrency = 6 [deprecated = true]; + string language = 7; + uint32 escrowTimeoutHours = 8; + string cryptoCurrencyCode = 9 [json_name = "coinType"]; + uint32 cryptoDivisibility = 10 [json_name = "coinDivisibility"]; + float priceModifier = 11 [deprecated = true]; + CountryCode shippingFromCountryCode = 12; + string shippingFromPostalCode = 13; enum ContractType { PHYSICAL_GOOD = 0; @@ -60,18 +68,21 @@ message Listing { } message Item { - string title = 1; - string description = 2; - string processingTime = 3; - uint64 price = 4; - bool nsfw = 5; - repeated string tags = 6; - repeated Image images = 7; - repeated string categories = 8; - float grams = 9; - string condition = 10; - repeated Option options = 11; - repeated Sku skus = 12; + string title = 1; + string description = 2; + string processingTime = 3; + uint64 price = 4 [deprecated = true]; + bool nsfw = 5; + repeated string tags = 6; + repeated Image images = 7; + repeated string categories = 8; + float grams = 9; + string condition = 10; + repeated Option options = 11; + repeated Sku skus = 12; + float priceModifier = 13; + string bigPrice = 14; // added schema v5 + CurrencyDefinition priceCurrency = 15; // added schema v5 message Option { string name = 1; @@ -85,10 +96,12 @@ message Listing { } message Sku { - repeated uint32 variantCombo = 1; - string productID = 2; - int64 surcharge = 3; - int64 quantity = 4; // Not saved with listing + repeated uint32 variantCombo = 1; + string productID = 2; + int64 surcharge = 3 [deprecated = true]; + int64 quantity = 4 [deprecated = true]; // prefer bigQuantity + string bigSurcharge = 5; // added schema v5 + string bigQuantity = 6; // added schema v5 } message Image { @@ -113,10 +126,12 @@ message Listing { } message Service { - string name = 1; - uint64 price = 2; - string estimatedDelivery = 3; - uint64 additionalItemPrice = 4; + string name = 1; + uint64 price = 2 [deprecated = true]; // prefer bigPrice + string estimatedDelivery = 3; + uint64 additionalItemPrice = 4 [deprecated = true]; // prefer bigAdditionalItemPrice + string bigPrice = 5; // added schema v5 + string bigAdditionalItemPrice = 6; // added schema v5 } } @@ -135,14 +150,15 @@ message Listing { } oneof discount { float percentDiscount = 5; - uint64 priceDiscount = 6; + uint64 priceDiscount = 6 [deprecated = true]; // prefer bigPriceDiscount + string bigPriceDiscount = 7; // added schema v5 } } } message Order { string refundAddress = 1; - uint64 refundFee = 2; + uint64 refundFee = 2 [deprecated = true]; // prefer bigRefundFee Shipping shipping = 3; ID buyerID = 4; google.protobuf.Timestamp timestamp = 5; @@ -151,6 +167,7 @@ message Order { repeated bytes ratingKeys = 8; string alternateContactInfo = 9; uint32 version = 10; + string bigRefundFee = 11; // added schema v5 message Shipping { string shipTo = 1; @@ -164,13 +181,14 @@ message Order { message Item { string listingHash = 1; - uint32 quantity = 2; // order version < 2 used with listing version < 3 - uint64 quantity64 = 8; // order version >= 2 used with listing version >= 3 + uint32 quantity = 2 [deprecated = true]; // order version < 2 used with listing version < 3 repeated Option options = 3; ShippingOption shippingOption = 4; string memo = 5; repeated string couponCodes = 6; string paymentAddress = 7; + uint64 quantity64 = 8 [deprecated = true]; // order version >= 2 used with listing version >= 3 + string bigQuantity = 9; // added schema v5 message Option { string name = 1; @@ -184,14 +202,16 @@ message Order { } message Payment { - Method method = 1; - string moderator = 2; - uint64 amount = 3; // Satoshis - string chaincode = 4; // Hex encoded - string address = 5; // B58check encoded - string redeemScript = 6; // Hex encoded - bytes moderatorKey = 7; - string coin = 8; + Method method = 1; + string moderator = 2; + uint64 amount = 3 [deprecated = true]; // Satoshis + string chaincode = 4; // Hex encoded + string address = 5; // B58check encoded + string redeemScript = 6; // Hex encoded + bytes moderatorKey = 7; + string coin = 8 [deprecated = true]; + string bigAmount = 9; // added schema v5 + CurrencyDefinition amountCurrency = 10; // added schema v5 enum Method { ADDRESS_REQUEST = 0; @@ -202,13 +222,15 @@ message Order { } message OrderConfirmation { - string orderID = 1; - google.protobuf.Timestamp timestamp = 2; + string orderID = 1; + google.protobuf.Timestamp timestamp = 2; // Direct payments only - string paymentAddress = 3; - uint64 requestedAmount = 4; + string paymentAddress = 3; + uint64 requestedAmount = 4 [deprecated = true]; - repeated RatingSignature ratingSignatures = 5; + repeated RatingSignature ratingSignatures = 5; + string bigRequestedAmount = 6; // added schema v5 + CurrencyDefinition requestedAmountCurrency = 7; // added schema v5 } message OrderReject { @@ -282,9 +304,11 @@ message OrderFulfillment { } message Payout { - repeated BitcoinSignature sigs = 1; - string payoutAddress = 2; - uint64 payoutFeePerByte = 3; + repeated BitcoinSignature sigs = 1; + string payoutAddress = 2; + uint64 payoutFeePerByte = 3 [deprecated = true]; + string bigPayoutFeePerByte = 4; // added schema v5 + CurrencyDefinition payoutFeeCurrency = 5; // added schema v5 } } @@ -295,6 +319,12 @@ message OrderCompletion { repeated Rating ratings = 4; } +message OrderProcessingFailure { + string orderID = 1; + Message.MessageType attemptedMessageType = 2; + RicardianContract contract = 3; +} + message Rating { RatingData ratingData = 1; bytes signature = 2; @@ -337,18 +367,20 @@ message DisputeResolution { repeated bytes moderatorRatingSigs = 6; // Used in ratings message Payout { - repeated BitcoinSignature sigs = 1; - repeated Outpoint inputs = 2; - Output buyerOutput = 3; - Output vendorOutput = 4; - Output moderatorOutput = 5; + repeated BitcoinSignature sigs = 1; + repeated Outpoint inputs = 2; + Output buyerOutput = 3; + Output vendorOutput = 4; + Output moderatorOutput = 5; + CurrencyDefinition payoutCurrency = 6; // added schema v5 message Output { oneof scriptOrAddress { - string script = 1; - string address = 3; + string script = 1; + string address = 3; } - uint64 amount = 2; + uint64 amount = 2 [deprecated = true]; + string bigAmount = 4; // added schema v5 } } } @@ -359,9 +391,10 @@ message DisputeAcceptance { } message Outpoint { - string hash = 1; // Hex encoded - uint32 index = 2; - uint64 value = 3; + string hash = 1; // Hex encoded + uint32 index = 2; + uint64 value = 3 [deprecated = true]; + string bigValue = 4; // added schema v5 } message Refund { @@ -372,8 +405,10 @@ message Refund { string memo = 5; message TransactionInfo { - string txid = 1; - uint64 value = 2; + string txid = 1; + uint64 value = 2 [deprecated = true]; + string bigValue = 3; // added schema v5 + CurrencyDefinition valueCurrency = 4; // added schema v5 } } diff --git a/pb/protos/message.proto b/pb/protos/message.proto index 22bd33adbb..edbe183ab3 100644 --- a/pb/protos/message.proto +++ b/pb/protos/message.proto @@ -33,7 +33,9 @@ message Message { STORE = 18; BLOCK = 19; VENDOR_FINALIZED_PAYMENT = 20; + ORDER_PAYMENT = 21; ERROR = 500; + ORDER_PROCESSING_FAILURE = 501; } } @@ -82,4 +84,11 @@ message Error { uint32 code = 1; string errorMessage = 2; string orderID = 3; -} \ No newline at end of file +} + +message OrderPaymentTxn { + string coin = 1; + string orderID = 2; + string transactionID = 3; + bool withInput = 4; +} diff --git a/pb/protos/moderator.proto b/pb/protos/moderator.proto index 6483277e93..beac784be6 100644 --- a/pb/protos/moderator.proto +++ b/pb/protos/moderator.proto @@ -24,8 +24,10 @@ message Moderator { } message Price { - string currencyCode = 1; - uint64 amount = 2; // Bitcoins must be in satoshi + string currencyCode = 1 [deprecated = true]; + uint64 amount = 2 [deprecated = true]; + string bigAmount = 3; + CurrencyDefinition amountCurrency = 4; } } diff --git a/pb/protos/profile.proto b/pb/protos/profile.proto index 76daefc448..2df10263d3 100644 --- a/pb/protos/profile.proto +++ b/pb/protos/profile.proto @@ -4,6 +4,7 @@ option go_package = "pb"; import "google/protobuf/timestamp.proto"; import "moderator.proto"; +import "contracts.proto"; message Profile { string peerID = 1; @@ -36,6 +37,14 @@ message Profile { repeated string currencies = 18; + string refundPolicy = 19; + + string termsAndConditions = 20; + + repeated Listing.ShippingOption shippingOptions = 21; + + uint32 version = 22; + message Contact { string website = 1; string email = 2; diff --git a/qa/README.md b/qa/README.md index 351c4e399f..bce8895dd5 100644 --- a/qa/README.md +++ b/qa/README.md @@ -4,5 +4,5 @@ This package allows us to spin up any number of OpenBazaar nodes and connect the To run this test suite: ``` -./runtests.sh /path/to/openbazaar-go-binary /path/to/bitcoind-binary +./runtests.sh /path/to/marketplace-go-binary /path/to/bitcoind-binary ``` \ No newline at end of file diff --git a/qa/cancel_direct_offline.py b/qa/cancel_direct_offline.py index eb208e2c42..5d354efafc 100644 --- a/qa/cancel_direct_offline.py +++ b/qa/cancel_direct_offline.py @@ -30,15 +30,20 @@ def run_test(self): time.sleep(20) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) if r.status_code == 404: @@ -66,10 +71,10 @@ def run_test(self): time.sleep(4) # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId - order_json["paymentCoin"] = "t" + self.cointype + order_json["paymentCoin"] = "T" + self.cointype api_url = bob["gateway_url"] + "ob/purchase" r = requests.post(api_url, data=json.dumps(order_json, indent=4)) if r.status_code == 404: @@ -97,18 +102,23 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: raise TestFailure("CancelDirectOfflineTest - FAIL: Spend post endpoint not found") elif r.status_code != 200: resp = json.loads(r.text) - raise TestFailure("CancelDirectOfflineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + raise TestFailure("CancelDirectOfflineTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) time.sleep(20) # check bob detected payment @@ -147,8 +157,8 @@ def run_test(self): raise TestFailure("CancelDirectOfflineTest - FAIL: Bob failed to detect outgoing payment") # startup alice again - self.start_node(alice) - self.send_bitcoin_cmd("generate", 1) + self.start_node(1, alice) + self.send_bitcoin_cmd("generatetoaddress", 1, self.bitcoin_address) time.sleep(45) # check alice detected order @@ -161,19 +171,24 @@ def run_test(self): raise TestFailure("CancelDirectOfflineTest - FAIL: Alice failed to detect order cancellation") # Check the funds moved into bob's wallet - api_url = bob["gateway_url"] + "wallet/balance/" + self.cointype + api_url = bob["gateway_url"] + "wallet/balance/" + "T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) confirmed = int(resp["confirmed"]) #unconfirmed = int(resp["unconfirmed"]) - if confirmed <= 50 - payment_amount: - raise TestFailure("CancelDirectOfflineTest - FAIL: Bob failed to receive the multisig payout") + if self.buyer_version == 4: + if confirmed <= 50 - payment_amount: + raise TestFailure("CancelDirectOfflineTest - FAIL: Bob failed to receive the multisig payout") + else: + if confirmed <= 50 - int(payment_amount["amount"]): + raise TestFailure("CancelDirectOfflineTest - FAIL: Bob failed to receive the multisig payout") else: raise TestFailure("CancelDirectOfflineTest - FAIL: Failed to query Bob's balance") print("CancelDirectOfflineTest - PASS") + if __name__ == '__main__': print("Running CancelDirectOfflineTest") CancelDirectOfflineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/chat_offline.py b/qa/chat_offline.py index 351f77d6af..f4897b501e 100644 --- a/qa/chat_offline.py +++ b/qa/chat_offline.py @@ -67,7 +67,7 @@ def run_test(self): raise TestFailure("ChatOfflineTest - FAIL: Did not record new conversation") # startup bob again - self.start_node(bob) + self.start_node(2, bob) time.sleep(45) # check bob saved message correctly @@ -123,4 +123,4 @@ def run_test(self): if __name__ == '__main__': print("Running ChatOfflineTest") - ChatOfflineTest().main(["--regtest", "--disableexchangerates"]) \ No newline at end of file + ChatOfflineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/complete_direct_online.py b/qa/complete_direct_online.py index 02a252aa17..7fcb792f33 100644 --- a/qa/complete_direct_online.py +++ b/qa/complete_direct_online.py @@ -27,18 +27,23 @@ def run_test(self): else: raise TestFailure("CompleteDirectOnlineTest - FAIL: Unknown response") self.send_bitcoin_cmd("sendtoaddress", address, 10) - time.sleep(40) + time.sleep(20) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) if r.status_code == 404: @@ -59,7 +64,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -99,11 +104,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -111,7 +121,7 @@ def run_test(self): elif r.status_code != 200: resp = json.loads(r.text) raise TestFailure("CompleteDirectOnlineTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) - time.sleep(20) + time.sleep(30) # check bob detected payment api_url = bob["gateway_url"] + "ob/order/" + orderId @@ -134,9 +144,9 @@ def run_test(self): raise TestFailure("CompleteDirectOnlineTest - FAIL: Alice failed to detect payment") if resp["funded"] == False: raise TestFailure("CompleteDirectOnlineTest - FAIL: Alice incorrectly saved as unfunded") - + # alice send order fulfillment - with open('testdata/fulfillment.json') as fulfillment_file: + with open('testdata/'+ self.vendor_version +'/fulfillment.json') as fulfillment_file: fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) fulfillment_json["orderId"] = orderId fulfillment_json["slug"] = slug @@ -211,6 +221,7 @@ def run_test(self): print("CompleteDirectOnlineTest - PASS") + if __name__ == '__main__': print("Running CompleteDirectOnlineTest") CompleteDirectOnlineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/complete_disputed.py b/qa/complete_disputed.py index e46b747a68..a0c4afcee1 100644 --- a/qa/complete_disputed.py +++ b/qa/complete_disputed.py @@ -43,7 +43,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -56,15 +56,20 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["moderators"] = [moderatorId] api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -86,7 +91,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -128,11 +133,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -165,7 +175,7 @@ def run_test(self): raise TestFailure("CompleteDisputedTest - FAIL: Alice incorrectly saved as unfunded") # alice send order fulfillment - with open('testdata/fulfillment.json') as fulfillment_file: + with open('testdata/'+ self.vendor_version +'/fulfillment.json') as fulfillment_file: fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) fulfillment_json["orderId"] = orderId fulfillment_json["slug"] = slug @@ -177,7 +187,7 @@ def run_test(self): resp = json.loads(r.text) raise TestFailure("CompleteDisputedTest - FAIL: Fulfillment POST failed. Reason: %s", resp["reason"]) time.sleep(4) - + # Bob open dispute dispute = { "orderId": orderId, @@ -276,17 +286,22 @@ def run_test(self): raise TestFailure("CompleteDisputedTest - FAIL: ReleaseFunds POST failed. Reason: %s", resp["reason"]) time.sleep(20) - self.send_bitcoin_cmd("generate", 1) - time.sleep(2) + self.send_bitcoin_cmd("generatetoaddress", 1, self.bitcoin_address) + time.sleep(5) # Check bob received payout - api_url = bob["gateway_url"] + "wallet/balance/" + self.cointype + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) confirmed = int(resp["confirmed"]) #unconfirmed = int(resp["unconfirmed"]) - if confirmed <= (generated_coins*100000000) - payment_amount: + amt = 0 + if self.buyer_version == "v4": + amt = payment_amount + else: + amt = int(payment_amount["amount"]) + if confirmed <= (generated_coins*100000000) - amt: raise TestFailure("CompleteDisputedTest - FAIL: Bob failed to detect dispute payout") elif r.status_code == 404: raise TestFailure("CompleteDisputedTest - FAIL: Receive coins endpoint not found") @@ -359,6 +374,7 @@ def run_test(self): print("CompleteDisputedTest - PASS") + if __name__ == '__main__': print("Running CompleteDisputedTest") CompleteDisputedTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/complete_moderated_online.py b/qa/complete_moderated_online.py index 96e6c5afcc..6db5fc4a7e 100644 --- a/qa/complete_moderated_online.py +++ b/qa/complete_moderated_online.py @@ -42,7 +42,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -55,15 +55,19 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] slug = listing_json["slug"] listing_json["moderators"] = [moderatorId] api_url = alice["gateway_url"] + "ob/listing" @@ -86,7 +90,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -128,11 +132,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -165,7 +174,7 @@ def run_test(self): raise TestFailure("CompleteModeratedOnlineTest - FAIL: Alice incorrectly saved as unfunded") # alice send order fulfillment - with open('testdata/fulfillment.json') as fulfillment_file: + with open('testdata/'+ self.vendor_version +'/fulfillment.json') as fulfillment_file: fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) fulfillment_json["slug"] = slug fulfillment_json["orderId"] = orderId @@ -197,7 +206,7 @@ def run_test(self): raise TestFailure("CompleteModeratedOnlineTest - FAIL: Alice failed to order fulfillment") # bob send order completion - with open('testdata/completion.json') as completion_file: + with open('testdata/'+ self.buyer_version +'/completion.json') as completion_file: completion_json = json.load(completion_file, object_pairs_hook=OrderedDict) completion_json["orderId"] = orderId completion_json["ratings"][0]["slug"] = slug @@ -232,7 +241,7 @@ def run_test(self): time.sleep(2) # Check the funds moved into alice's wallet - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) diff --git a/qa/complete_moderated_with_timeout.py b/qa/complete_moderated_with_timeout.py index 7953e33b03..58928abac3 100644 --- a/qa/complete_moderated_with_timeout.py +++ b/qa/complete_moderated_with_timeout.py @@ -42,7 +42,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -55,15 +55,19 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] slug = listing_json["slug"] listing_json["moderators"] = [moderatorId] listing_json["metadata"]["escrowTimeoutHours"] = 1000 @@ -87,7 +91,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -129,11 +133,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -166,7 +175,7 @@ def run_test(self): raise TestFailure("CompleteModeratedWithTimeout - FAIL: Alice incorrectly saved as unfunded") # alice send order fulfillment - with open('testdata/fulfillment.json') as fulfillment_file: + with open('testdata/'+ self.vendor_version +'/fulfillment.json') as fulfillment_file: fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) fulfillment_json["slug"] = slug fulfillment_json["orderId"] = orderId @@ -198,7 +207,7 @@ def run_test(self): raise TestFailure("CompleteModeratedWithTimeout - FAIL: Alice failed to order fulfillment") # bob send order completion - with open('testdata/completion.json') as completion_file: + with open('testdata/'+ self.buyer_version +'/completion.json') as completion_file: completion_json = json.load(completion_file, object_pairs_hook=OrderedDict) completion_json["orderId"] = orderId completion_json["ratings"][0]["slug"] = slug @@ -233,7 +242,7 @@ def run_test(self): time.sleep(2) # Check the funds moved into alice's wallet - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) diff --git a/qa/dispute_close_buyer.py b/qa/dispute_close_buyer.py index f228380101..c02f6dbb0e 100644 --- a/qa/dispute_close_buyer.py +++ b/qa/dispute_close_buyer.py @@ -43,7 +43,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -56,15 +56,19 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] listing_json["moderators"] = [moderatorId] api_url = alice["gateway_url"] + "ob/listing" @@ -85,7 +89,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -127,11 +131,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -162,7 +171,7 @@ def run_test(self): raise TestFailure("DisputeCloseBuyerTest - FAIL: Alice failed to detect payment") if resp["funded"] == False: raise TestFailure("DisputeCloseBuyerTest - FAIL: Alice incorrectly saved as unfunded") - + # Bob open dispute dispute = { "orderId": orderId, @@ -265,13 +274,18 @@ def run_test(self): time.sleep(5) # Check bob received payout - api_url = bob["gateway_url"] + "wallet/balance/" + self.cointype + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) confirmed = int(resp["confirmed"]) #unconfirmed = int(resp["unconfirmed"]) - if confirmed <= (generated_coins*100000000) - payment_amount: + amt = 0 + if self.buyer_version == "v4": + amt = payment_amount + else: + amt = int(payment_amount["amount"]) + if confirmed <= (generated_coins*100000000) - amt: raise TestFailure("DisputeCloseBuyerTest - FAIL: Bob failed to detect dispute payout") elif r.status_code == 404: raise TestFailure("DisputeCloseBuyerTest - FAIL: Receive coins endpoint not found") @@ -302,6 +316,7 @@ def run_test(self): print("DisputeCloseBuyerTest - PASS") + if __name__ == '__main__': print("Running DisputeCloseBuyerTest") DisputeCloseBuyerTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/dispute_close_split.py b/qa/dispute_close_split.py index 182677ca1c..7b39a4fb07 100644 --- a/qa/dispute_close_split.py +++ b/qa/dispute_close_split.py @@ -43,7 +43,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -56,15 +56,19 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] listing_json["moderators"] = [moderatorId] api_url = alice["gateway_url"] + "ob/listing" @@ -85,7 +89,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -127,11 +131,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -139,7 +148,7 @@ def run_test(self): elif r.status_code != 200: resp = json.loads(r.text) raise TestFailure("DisputeCloseSplitTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) - time.sleep(20) + time.sleep(30) # check bob detected payment api_url = bob["gateway_url"] + "ob/order/" + orderId @@ -261,30 +270,39 @@ def run_test(self): raise TestFailure("DisputeCloseSplitTest - FAIL: ReleaseFunds POST failed. Reason: %s", resp["reason"]) time.sleep(20) + self.send_bitcoin_cmd("generate", 1) + time.sleep(30) + # Check bob received payout - api_url = bob["gateway_url"] + "wallet/balance/" + self.cointype + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) confirmed = int(resp["confirmed"]) unconfirmed = int(resp["unconfirmed"]) - if confirmed + unconfirmed <= (generated_coins*100000000) - payment_amount: + amt = 0 + if self.buyer_version == "v4": + amt = payment_amount + else: + amt = int(payment_amount["amount"]) + + if confirmed + unconfirmed <= (generated_coins*100000000) - amt: raise TestFailure("DisputeCloseSplitTest - FAIL: Bob failed to detect dispute payout") elif r.status_code == 404: raise TestFailure("DisputeCloseSplitTest - FAIL: Receive coins endpoint not found") else: raise TestFailure("DisputeCloseSplitTest - FAIL: Unknown response") - self.send_bitcoin_cmd("generate", 1) - time.sleep(2) + # Check alice received payout - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype + time.sleep(20) r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) confirmed = int(resp["confirmed"]) - #unconfirmed = int(resp["unconfirmed"]) + unconfirmed = int(resp["unconfirmed"]) if confirmed <= 0: raise TestFailure("DisputeCloseSplitTest - FAIL: Alice failed to detect dispute payout") elif r.status_code == 404: diff --git a/qa/dispute_close_vendor.py b/qa/dispute_close_vendor.py index 3b98dfd9ea..86b9bc4025 100644 --- a/qa/dispute_close_vendor.py +++ b/qa/dispute_close_vendor.py @@ -43,7 +43,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -56,15 +56,19 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] listing_json["moderators"] = [moderatorId] api_url = alice["gateway_url"] + "ob/listing" @@ -87,7 +91,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version+'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -129,11 +133,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -166,7 +175,7 @@ def run_test(self): raise TestFailure("DisputeCloseVendorTest - FAIL: Alice incorrectly saved as unfunded") # alice send order fulfillment - with open('testdata/fulfillment.json') as fulfillment_file: + with open('testdata/'+ self.vendor_version +'/fulfillment.json') as fulfillment_file: fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) fulfillment_json["orderId"] = orderId fulfillment_json["slug"] = slug @@ -196,7 +205,7 @@ def run_test(self): resp = json.loads(r.text) if resp["state"] != "FULFILLED": raise TestFailure("FulfillDirectOnlineTest - FAIL: Alice failed to order fulfillment") - + # Alice open dispute dispute = { "orderId": orderId, @@ -295,10 +304,10 @@ def run_test(self): time.sleep(20) self.send_bitcoin_cmd("generate", 1) - time.sleep(2) + time.sleep(20) # Check alice received payout - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) @@ -335,6 +344,7 @@ def run_test(self): print("DisputeCloseVendorTest - PASS") + if __name__ == '__main__': print("Running DisputeCloseVendorTest") DisputeCloseVendorTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/escrow_release_after_timeout.py b/qa/escrow_release_after_timeout.py index e0d4c78582..ebda8ba9b1 100644 --- a/qa/escrow_release_after_timeout.py +++ b/qa/escrow_release_after_timeout.py @@ -42,7 +42,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -55,15 +55,19 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] slug = listing_json["slug"] listing_json["moderators"] = [moderatorId] listing_json["metadata"]["escrowTimeoutHours"] = 1 @@ -87,7 +91,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -129,11 +133,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -166,7 +175,7 @@ def run_test(self): raise TestFailure("EscrowTimeoutRelease - FAIL: Alice incorrectly saved as unfunded") # alice send order fulfillment - with open('testdata/fulfillment.json') as fulfillment_file: + with open('testdata/'+ self.vendor_version +'/fulfillment.json') as fulfillment_file: fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) fulfillment_json["slug"] = slug fulfillment_json["orderId"] = orderId @@ -229,7 +238,7 @@ def run_test(self): time.sleep(2) # Check the funds moved into alice's wallet - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) diff --git a/qa/eth_cancel_direct_offline.py b/qa/eth_cancel_direct_offline.py new file mode 100644 index 0000000000..48d62a6d42 --- /dev/null +++ b/qa/eth_cancel_direct_offline.py @@ -0,0 +1,176 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthCancelDirectOfflineTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + + # initial bob balance + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + bob_balance = int(resp["confirmed"]) + elif r.status_code == 404: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Unknown response") + time.sleep(20) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob fetch listing to cache + api_url = bob["gateway_url"] + "ipfs/" + listingId + requests.get(api_url) + + # shutdown alice + api_url = alice["gateway_url"] + "ob/shutdown" + requests.post(api_url, data="") + time.sleep(4) + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + if resp["vendorOnline"] == True: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Purchase returned vendor is online") + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Bob incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + time.sleep(40) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if len(resp["paymentAddressTransactions"]) <= 0: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Bob incorrectly saved as unfunded") + if resp["state"] != "PENDING": + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Bob purchase saved in incorrect state") + + # bob cancel order + api_url = bob["gateway_url"] + "ob/ordercancel" + cancel = {"orderId": orderId} + r = requests.post(api_url, data=json.dumps(cancel, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Cancel POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # bob check order canceled correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "CANCELED": + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Bob failed to save as canceled") + + # startup alice again + self.start_node(1, alice) + time.sleep(160) + + # check alice detected order + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Couldn't load order from Alice %s", r.status_code) + resp = json.loads(r.text) + if resp["state"] != "CANCELED": + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Alice failed to detect order cancellation") + + # Check the funds moved into bob's wallet + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + else: + raise TestFailure("EthCancelDirectOfflineTest - FAIL: Failed to query Bob's balance") + + print("EthCancelDirectOfflineTest - PASS") + + +if __name__ == '__main__': + print("Running EthCancelDirectOfflineTest") + EthCancelDirectOfflineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_complete_direct_online.py b/qa/eth_complete_direct_online.py new file mode 100644 index 0000000000..eaefd69a08 --- /dev/null +++ b/qa/eth_complete_direct_online.py @@ -0,0 +1,224 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthCompleteDirectOnlineTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Unknown response") + time.sleep(20) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + print("api_url : ", api_url) + print(json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + slug = resp["slug"] + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + print("################################") + print("before spend post : ", api_url) + print(json.dumps(spend, indent=4)) + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(60) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Alice incorrectly saved as unfunded") + + # alice send order fulfillment + with open('testdata/v5/fulfillment.json') as fulfillment_file: + fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) + fulfillment_json["orderId"] = orderId + fulfillment_json["slug"] = slug + api_url = alice["gateway_url"] + "ob/orderfulfillment" + r = requests.post(api_url, data=json.dumps(fulfillment_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Fulfillment post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Fulfillment POST failed. Reason: %s", resp["reason"]) + time.sleep(5) + + # check bob received fulfillment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Bob failed to detect order fulfillment") + + # check alice set fulfillment correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Alice failed to order fulfillment") + + # bob send order completion + oc = { + "orderId": orderId, + "ratings": [ + { + "slug": slug, + "overall": 4, + "quality": 5, + "description": 5, + "customerService": 4, + "deliverySpeed": 3, + "review": "I love it!" + } + ] + } + api_url = bob["gateway_url"] + "ob/ordercompletion" + r = requests.post(api_url, data=json.dumps(oc, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Completion post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Completion POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # check alice received completion + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "COMPLETED": + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Alice failed to detect order completion") + + # check bob set completion correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "COMPLETED": + raise TestFailure("EthCompleteDirectOnlineTest - FAIL: Bob failed to order completion") + + print("EthCompleteDirectOnlineTest - PASS") + + +if __name__ == '__main__': + print("Running EthCompleteDirectOnlineTest") + EthCompleteDirectOnlineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_complete_disputed.py b/qa/eth_complete_disputed.py new file mode 100644 index 0000000000..0385db201c --- /dev/null +++ b/qa/eth_complete_disputed.py @@ -0,0 +1,365 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthCompleteDisputedTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # check bob's initial balance + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + bob_balance = int(resp["confirmed"]) + elif r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthCompleteDisputedTest - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDisputedTest - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDisputedTest - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + listing_json["moderators"] = [moderatorId] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDisputedTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + slug = resp["slug"] + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + self.print_logs(alice, "ob.log") + raise TestFailure("EthCompleteDisputedTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthCompleteDisputedTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthCompleteDisputedTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthCompleteDisputedTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthCompleteDisputedTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDisputedTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthCompleteDisputedTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthCompleteDisputedTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthCompleteDisputedTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthCompleteDisputedTest - FAIL: Alice incorrectly saved as unfunded") + + # alice send order fulfillment + with open('testdata/v5/fulfillment.json') as fulfillment_file: + fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) + fulfillment_json["orderId"] = orderId + fulfillment_json["slug"] = slug + api_url = alice["gateway_url"] + "ob/orderfulfillment" + r = requests.post(api_url, data=json.dumps(fulfillment_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: Fulfillment post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDisputedTest - FAIL: Fulfillment POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # Bob open dispute + dispute = { + "orderId": orderId, + "claim": "Bastard ripped me off" + } + api_url = bob["gateway_url"] + "ob/opendispute/" + r = requests.post(api_url, data=json.dumps(dispute, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: OpenDispute post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDisputedTest - FAIL: OpenDispute POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # Bob check dispute opened correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "DISPUTED": + raise TestFailure("EthCompleteDisputedTest - FAIL: Bob failed to detect his dispute") + + # Alice check dispute opened correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DISPUTED": + raise TestFailure("EthCompleteDisputedTest - FAIL: Alice failed to detect the dispute") + + # Charlie check dispute opened correctly + api_url = charlie["gateway_url"] + "ob/case/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load case from Clarlie") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "DISPUTED": + raise TestFailure("EthCompleteDisputedTest - FAIL: Charlie failed to detect the dispute") + + # Charlie close dispute + dispute_resolution = { + "OrderID": orderId, + "Resolution": "I'm siding with Bob", + "BuyerPercentage": 100, + "VendorPercentage": 0 + } + api_url = charlie["gateway_url"] + "ob/closedispute/" + r = requests.post(api_url, data=json.dumps(dispute_resolution, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: CloseDispute post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDisputedTest - FAIL: CloseDispute POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # Alice check dispute closed correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DECIDED": + self.print_logs(alice, "ob.log") + raise TestFailure("EthCompleteDisputedTest - FAIL: Alice failed to detect the dispute resolution") + + # Bob check dispute closed correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "DECIDED": + raise TestFailure("EthCompleteDisputedTest - FAIL: Bob failed to detect the dispute resolution") + + # Charlie check dispute closed correctly + api_url = charlie["gateway_url"] + "ob/case/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load case from Charlie") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "RESOLVED": + raise TestFailure("EthCompleteDisputedTest - FAIL: Charlie failed to detect the dispute resolution") + + # Bob release funds + release = { + "OrderID": orderId, + } + api_url = bob["gateway_url"] + "ob/releasefunds/" + r = requests.post(api_url, data=json.dumps(release, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: ReleaseFunds post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDisputedTest - FAIL: ReleaseFunds POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + time.sleep(5) + + # Check bob received payout + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + #if confirmed <= (bob_balance) - int(payment_amount["amount"]): + # raise TestFailure("EthCompleteDisputedTest - FAIL: Bob failed to detect dispute payout") + elif r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: Receive coins endpoint not found") + else: + raise TestFailure("EthCompleteDisputedTest - FAIL: Unknown response") + + # Bob check payout transaction recorded + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if len(resp["paymentAddressTransactions"]) != 2: + raise TestFailure("EthCompleteDisputedTest - FAIL: Bob failed to record payout transaction") + if resp["state"] != "RESOLVED": + raise TestFailure("EthCompleteDisputedTest - FAIL: Bob failed to set state to RESOLVED") + + # Alice check payout transaction recorded + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if len(resp["paymentAddressTransactions"]) != 2: + raise TestFailure("EthCompleteDisputedTest - FAIL: Alice failed to record payout transaction") + if resp["state"] != "RESOLVED": + raise TestFailure("EthCompleteDisputedTest - FAIL: Alice failed to set state to RESOLVED") + + # bob send order completion + oc = { + "orderId": orderId, + "ratings": [ + { + "slug": slug, + "overall": 4, + "quality": 5, + "description": 5, + "customerService": 4, + "deliverySpeed": 3, + "Review": "I love it!" + } + ] + } + api_url = bob["gateway_url"] + "ob/ordercompletion" + r = requests.post(api_url, data=json.dumps(oc, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteDisputedTest - FAIL: Completion post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteDisputedTest - FAIL: Completion POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # check alice received completion + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "COMPLETED": + raise TestFailure("EthCompleteDisputedTest - FAIL: Alice failed to detect order completion") + + # check bob set completion correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteDisputedTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "COMPLETED": + raise TestFailure("EthCompleteDisputedTest - FAIL: Bob failed to order completion") + + print("EthCompleteDisputedTest - PASS") + + +if __name__ == '__main__': + print("Running EthCompleteDisputedTest") + EthCompleteDisputedTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_complete_moderated_online.py b/qa/eth_complete_moderated_online.py new file mode 100644 index 0000000000..b556efe619 --- /dev/null +++ b/qa/eth_complete_moderated_online.py @@ -0,0 +1,254 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthCompleteModeratedOnlineTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + slug = listing_json["slug"] + listing_json["moderators"] = [moderatorId] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + slug = resp["slug"] + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + self.print_logs(alice, "ob.log") + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Alice incorrectly saved as unfunded") + + # alice send order fulfillment + with open('testdata/v5/fulfillment.json') as fulfillment_file: + fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) + fulfillment_json["slug"] = slug + fulfillment_json["orderId"] = orderId + api_url = alice["gateway_url"] + "ob/orderfulfillment" + r = requests.post(api_url, data=json.dumps(fulfillment_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Fulfillment post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Fulfillment POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # check bob received fulfillment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Bob failed to detect order fulfillment") + + # check alice set fulfillment correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Alice failed to order fulfillment") + + # bob send order completion + with open('testdata/v5/completion.json') as completion_file: + completion_json = json.load(completion_file, object_pairs_hook=OrderedDict) + completion_json["orderId"] = orderId + completion_json["ratings"][0]["slug"] = slug + api_url = bob["gateway_url"] + "ob/ordercompletion" + r = requests.post(api_url, data=json.dumps(completion_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Completion post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Completion POST failed. Reason: %s", resp["reason"]) + time.sleep(160) + + # check alice received completion + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + print("############ $$$$$$$$$$$$$$") + print(resp["state"]) + if resp["state"] != "COMPLETED": + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Alice failed to detect order completion") + + # check bob set completion correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "COMPLETED": + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Bob failed to order completion") + + time.sleep(2) + + # Check the funds moved into alice's wallet + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + if confirmed <= 0: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Alice failed to receive the multisig payout") + else: + raise TestFailure("EthCompleteModeratedOnlineTest - FAIL: Failed to query Alice's balance") + + print("EthCompleteModeratedOnlineTest - PASS") + + +if __name__ == '__main__': + print("Running EthCompleteModeratedOnlineTest") + EthCompleteModeratedOnlineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_complete_moderated_with_timeout.py b/qa/eth_complete_moderated_with_timeout.py new file mode 100644 index 0000000000..04d7e67cf3 --- /dev/null +++ b/qa/eth_complete_moderated_with_timeout.py @@ -0,0 +1,254 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthCompleteModeratedWithTimeout(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Address endpoint not found") + else: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + slug = listing_json["slug"] + listing_json["moderators"] = [moderatorId] + listing_json["metadata"]["escrowTimeoutHours"] = 1000 + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + slug = resp["slug"] + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + self.print_logs(alice, "ob.log") + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Alice incorrectly saved as unfunded") + + # alice send order fulfillment + with open('testdata/v5/fulfillment.json') as fulfillment_file: + fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) + fulfillment_json["slug"] = slug + fulfillment_json["orderId"] = orderId + api_url = alice["gateway_url"] + "ob/orderfulfillment" + r = requests.post(api_url, data=json.dumps(fulfillment_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Fulfillment post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Fulfillment POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # check bob received fulfillment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Bob failed to detect order fulfillment") + + # check alice set fulfillment correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Alice failed to order fulfillment") + + # bob send order completion + with open('testdata/v5/completion.json') as completion_file: + completion_json = json.load(completion_file, object_pairs_hook=OrderedDict) + completion_json["orderId"] = orderId + completion_json["ratings"][0]["slug"] = slug + api_url = bob["gateway_url"] + "ob/ordercompletion" + r = requests.post(api_url, data=json.dumps(completion_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Completion post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Completion POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + time.sleep(160) + + # check alice received completion + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "COMPLETED": + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Alice failed to detect order completion") + + # check bob set completion correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "COMPLETED": + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Bob failed to order completion") + + time.sleep(2) + + # Check the funds moved into alice's wallet + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + if confirmed <= 0: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Alice failed to receive the multisig payout") + else: + raise TestFailure("EthCompleteModeratedWithTimeout - FAIL: Failed to query Alice's balance") + + print("EthCompleteModeratedWithTimeout - PASS") + +if __name__ == '__main__': + print("Running EthCompleteModeratedWithTimeout") + EthCompleteModeratedWithTimeout().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_dispute_close_buyer.py b/qa/eth_dispute_close_buyer.py new file mode 100644 index 0000000000..2b31c70481 --- /dev/null +++ b/qa/eth_dispute_close_buyer.py @@ -0,0 +1,307 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthDisputeCloseBuyerTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Unknown response") + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + listing_json["moderators"] = [moderatorId] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + self.print_logs(alice, "ob.log") + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(120) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Alice incorrectly saved as unfunded") + + # Bob open dispute + dispute = { + "orderId": orderId, + "claim": "Bastard ripped me off" + } + api_url = bob["gateway_url"] + "ob/opendispute/" + r = requests.post(api_url, data=json.dumps(dispute, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: OpenDispute post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: OpenDispute POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # Bob check dispute opened correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "DISPUTED": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Bob failed to detect his dispute") + + # Alice check dispute opened correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DISPUTED": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Alice failed to detect the dispute") + + # Charlie check dispute opened correctly + api_url = charlie["gateway_url"] + "ob/case/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load case from Clarlie") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "DISPUTED": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Charlie failed to detect the dispute") + + # Charlie close dispute + dispute_resolution = { + "OrderID": orderId, + "Resolution": "I'm siding with Bob", + "BuyerPercentage": 100, + "VendorPercentage": 0 + } + api_url = charlie["gateway_url"] + "ob/closedispute/" + r = requests.post(api_url, data=json.dumps(dispute_resolution, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: CloseDispute post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: CloseDispute POST failed. Reason: %s", resp["reason"]) + time.sleep(40) + + # Alice check dispute closed correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DECIDED": + self.print_logs(alice, "ob.log") + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Alice failed to detect the dispute resolution") + + # Bob check dispute closed correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "DECIDED": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Bob failed to detect the dispute resolution") + + # Charlie check dispute closed correctly + api_url = charlie["gateway_url"] + "ob/case/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load case from Charlie") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "RESOLVED": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Charlie failed to detect the dispute resolution") + + # Bob release funds + release = { + "OrderID": orderId, + } + api_url = bob["gateway_url"] + "ob/releasefunds/" + r = requests.post(api_url, data=json.dumps(release, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: ReleaseFunds post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: ReleaseFunds POST failed. Reason: %s", resp["reason"]) + time.sleep(120) + + # Check bob received payout + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + ##if confirmed <= (generated_coins*100000000) - int(payment_amount["amount"]): + ## raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Bob failed to detect dispute payout") + elif r.status_code == 404: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Receive coins endpoint not found") + else: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Unknown response") + + # Bob check payout transaction recorded + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + print("bob: no of pyment txns: ", len(resp["paymentAddressTransactions"])) + if len(resp["paymentAddressTransactions"]) != 2: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Bob failed to record payout transaction") + if resp["state"] != "RESOLVED": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Bob failed to set state to RESOLVED") + + # Alice check payout transaction recorded + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + print("alice: no of pyment txns: ", len(resp["paymentAddressTransactions"])) + print(resp["state"]) + if len(resp["paymentAddressTransactions"]) != 2: + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Alice failed to record payout transaction") + if resp["state"] != "RESOLVED": + raise TestFailure("EthDisputeCloseBuyerTest - FAIL: Alice failed to set state to RESOLVED") + + print("EthDisputeCloseBuyerTest - PASS") + + +if __name__ == '__main__': + print("Running EthDisputeCloseBuyerTest") + EthDisputeCloseBuyerTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_dispute_close_split.py b/qa/eth_dispute_close_split.py new file mode 100644 index 0000000000..14989d7651 --- /dev/null +++ b/qa/eth_dispute_close_split.py @@ -0,0 +1,325 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthDisputeCloseSplitTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # generate some coins and send them to bob + generated_coins = 10 + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + listing_json["moderators"] = [moderatorId] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + self.print_logs(alice, "ob.log") + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(30) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Alice incorrectly saved as unfunded") + + # Bob open dispute + dispute = { + "orderId": orderId, + "claim": "Bastard ripped me off" + } + api_url = bob["gateway_url"] + "ob/opendispute/" + r = requests.post(api_url, data=json.dumps(dispute, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: OpenDispute post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseSplitTest - FAIL: OpenDispute POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # Bob check dispute opened correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "DISPUTED": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Bob failed to detect his dispute") + + # Alice check dispute opened correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DISPUTED": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Alice failed to detect the dispute") + + # Charlie check dispute opened correctly + api_url = charlie["gateway_url"] + "ob/case/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load case from Clarlie") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "DISPUTED": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Charlie failed to detect the dispute") + + # Charlie close dispute + dispute_resolution = { + "OrderID": orderId, + "Resolution": "I'm siding with Bob but like Alice too", + "BuyerPercentage": 50, + "VendorPercentage": 50 + } + api_url = charlie["gateway_url"] + "ob/closedispute/" + r = requests.post(api_url, data=json.dumps(dispute_resolution, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: CloseDispute post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseSplitTest - FAIL: CloseDispute POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # Alice check dispute closed correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DECIDED": + self.print_logs(alice, "ob.log") + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Alice failed to detect the dispute resolution") + + # Bob check dispute closed correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "DECIDED": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Bob failed to detect the dispute resolution") + + # Charlie check dispute closed correctly + api_url = charlie["gateway_url"] + "ob/case/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load case from Clarlie") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "RESOLVED": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Charlie failed to detect the dispute resolution") + + # Bob release funds + release = { + "OrderID": orderId, + } + api_url = bob["gateway_url"] + "ob/releasefunds/" + r = requests.post(api_url, data=json.dumps(release, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: ReleaseFunds post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseSplitTest - FAIL: ReleaseFunds POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + time.sleep(30) + + # Check bob received payout + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + unconfirmed = int(resp["unconfirmed"]) + ##if confirmed + unconfirmed <= (generated_coins*100000000) - int(payment_amount["amount"]): + ## raise TestFailure("EthDisputeCloseSplitTest - FAIL: Bob failed to detect dispute payout") + elif r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Receive coins endpoint not found") + else: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Unknown response") + + + + # Check alice received payout + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype + time.sleep(20) + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + unconfirmed = int(resp["unconfirmed"]) + if confirmed <= 0: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Alice failed to detect dispute payout") + elif r.status_code == 404: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Receive coins endpoint not found") + else: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Unknown response") + + # Bob check payout transaction recorded + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if len(resp["paymentAddressTransactions"]) != 2: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Bob failed to record payout transaction") + if resp["state"] != "RESOLVED": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Bob failed to set state to RESOLVED") + + # Alice check payout transaction recorded + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if len(resp["paymentAddressTransactions"]) != 2: + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Alice failed to record payout transaction") + if resp["state"] != "RESOLVED": + raise TestFailure("EthDisputeCloseSplitTest - FAIL: Alice failed to set state to RESOLVED") + + print("EthDisputeCloseSplitTest - PASS") + +if __name__ == '__main__': + print("Running EthDisputeCloseSplitTest") + EthDisputeCloseSplitTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_dispute_close_vendor.py b/qa/eth_dispute_close_vendor.py new file mode 100644 index 0000000000..92919897c4 --- /dev/null +++ b/qa/eth_dispute_close_vendor.py @@ -0,0 +1,345 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthDisputeCloseVendorTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # generate some coins and send them to bob + time.sleep(4) + generated_coins = 10 + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + listing_json["moderators"] = [moderatorId] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + slug = resp["slug"] + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + self.print_logs(alice, "ob.log") + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Alice incorrectly saved as unfunded") + + # alice send order fulfillment + with open('testdata/v5/fulfillment.json') as fulfillment_file: + fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) + fulfillment_json["orderId"] = orderId + fulfillment_json["slug"] = slug + api_url = alice["gateway_url"] + "ob/orderfulfillment" + r = requests.post(api_url, data=json.dumps(fulfillment_json, indent=4)) + if r.status_code == 404: + raise TestFailure("FulfillDirectOnlineTest - FAIL: Fulfillment post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("FulfillDirectOnlineTest - FAIL: Fulfillment POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # check bob received fulfillment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("FulfillDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("FulfillDirectOnlineTest - FAIL: Bob failed to detect order fulfillment") + + # check alice set fulfillment correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("FulfillDirectOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("FulfillDirectOnlineTest - FAIL: Alice failed to order fulfillment") + + # Alice open dispute + dispute = { + "orderId": orderId, + "claim": "Bastard ripped me off" + } + api_url = alice["gateway_url"] + "ob/opendispute/" + r = requests.post(api_url, data=json.dumps(dispute, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: OpenDispute post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseVendorTest - FAIL: OpenDispute POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # Alice check dispute opened correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DISPUTED": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Alice failed to detect his dispute resolution") + + # Bob check dispute opened correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "DISPUTED": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Bob failed to detect the dispute resolution") + + # Charlie check dispute opened correctly + api_url = charlie["gateway_url"] + "ob/case/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load case from Clarlie") + resp = json.loads(r.text) + if resp["state"] != "DISPUTED": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Charlie failed to detect the dispute resolution") + + # Charlie close dispute + dispute_resolution = { + "OrderID": orderId, + "Resolution": "I'm siding with Bob", + "BuyerPercentage": 0, + "VendorPercentage": 100 + } + api_url = charlie["gateway_url"] + "ob/closedispute/" + r = requests.post(api_url, data=json.dumps(dispute_resolution, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: CloseDispute post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseVendorTest - FAIL: CloseDispute POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # Alice check dispute closed correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DECIDED": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Alice failed to detect the dispute resolution") + + # Bob check dispute closed correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "DECIDED": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Bob failed to detect the dispute resolution") + + # Charlie check dispute closed correctly + api_url = charlie["gateway_url"] + "ob/case/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load case from Clarlie") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if resp["state"] != "RESOLVED": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Charlie failed to detect the dispute resolution") + + # Alice release funds + release = { + "OrderID": orderId, + } + api_url = alice["gateway_url"] + "ob/releasefunds/" + r = requests.post(api_url, data=json.dumps(release, indent=4)) + if r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: ReleaseFunds post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthDisputeCloseVendorTest - FAIL: ReleaseFunds POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + time.sleep(2) + + # Check alice received payout + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + if confirmed <= 0: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Alice failed to detect dispute payout") + elif r.status_code == 404: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Receive coins endpoint not found") + else: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Unknown response") + + # Alice check payout transaction recorded + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + if len(resp["paymentAddressTransactions"]) != 2: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Alice failed to record payout transaction") + if resp["state"] != "RESOLVED": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Alice failed to set state to RESOLVED") + + time.sleep(30) + # Bob check payout transaction recorded + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text, object_pairs_hook=OrderedDict) + print("bobs paymnt txns : ", len(resp["paymentAddressTransactions"])) + print("state : ", resp["state"]) + ##if len(resp["paymentAddressTransactions"]) != 2: + ## raise TestFailure("EthDisputeCloseVendorTest - FAIL: Bob failed to record payout transaction") + if resp["state"] != "RESOLVED": + raise TestFailure("EthDisputeCloseVendorTest - FAIL: Bob failed to set state to RESOLVED") + + print("EthDisputeCloseVendorTest - PASS") + + +if __name__ == '__main__': + print("Running EthDisputeCloseVendorTest") + EthDisputeCloseVendorTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_escrow_release_after_timeout.py b/qa/eth_escrow_release_after_timeout.py new file mode 100644 index 0000000000..23c15d2916 --- /dev/null +++ b/qa/eth_escrow_release_after_timeout.py @@ -0,0 +1,271 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +## This test takes over 1 hour to complete because the smart contract cannot be +## simulated into releasing the escrow funds earlier than what has been set as timeout +## and the minimum value for escrowtimeout is 1 hour +class EthEscrowTimeoutRelease(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + print("bob's locn : ", api_url) + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + print("bob's addr : ", address) + elif r.status_code == 404: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Address endpoint not found") + else: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + slug = listing_json["slug"] + listing_json["moderators"] = [moderatorId] + listing_json["metadata"]["escrowTimeoutHours"] = 1 + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + slug = resp["slug"] + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + self.print_logs(alice, "ob.log") + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Alice incorrectly saved as unfunded") + + # alice send order fulfillment + with open('testdata/v5/fulfillment.json') as fulfillment_file: + fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) + fulfillment_json["slug"] = slug + fulfillment_json["orderId"] = orderId + api_url = alice["gateway_url"] + "ob/orderfulfillment" + r = requests.post(api_url, data=json.dumps(fulfillment_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Fulfillment post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Fulfillment POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # check bob received fulfillment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Bob failed to detect order fulfillment") + + # check alice set fulfillment correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Alice failed to order fulfillment") + + # Alice attempt to release funds before timeout hit + release = { + "OrderID": orderId, + } + api_url = alice["gateway_url"] + "ob/releaseescrow/" + r = requests.post(api_url, data=json.dumps(release, indent=4)) + if r.status_code == 500: + resp = json.loads(r.text) + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Release escrow internal server error %s", resp["reason"]) + elif r.status_code != 401: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Failed to raise error when releasing escrow before timeout") + + for i in range(6): + time.sleep(900) + + # Alice attempt to release funds again + release = { + "OrderID": orderId, + } + api_url = alice["gateway_url"] + "ob/releaseescrow/" + r = requests.post(api_url, data=json.dumps(release, indent=4)) + if r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Release escrow error %s", resp["reason"]) + + time.sleep(20) + + time.sleep(2) + + # Check the funds moved into alice's wallet + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + if confirmed <= 0: + raise TestFailure("RefundDirectTest - FAIL: Alice failed to receive the multisig payout") + else: + raise TestFailure("RefundDirectTest - FAIL: Failed to query Alice's balance") + + # check alice's order was set to payment finalized + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "PAYMENT_FINALIZED": + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Alice failed to set order to payment finalized") + + # check bob's order was set to payment finalized + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "PAYMENT_FINALIZED": + raise TestFailure("EthEscrowTimeoutRelease - FAIL: Bob failed to set order to payment finalized") + + print("EthEscrowTimeoutRelease - PASS") + + +if __name__ == '__main__': + print("Running EthEscrowTimeoutRelease") + EthEscrowTimeoutRelease().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_fulfill_direct_online.py b/qa/eth_fulfill_direct_online.py new file mode 100644 index 0000000000..d62c4a238f --- /dev/null +++ b/qa/eth_fulfill_direct_online.py @@ -0,0 +1,178 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthFulfillDirectOnlineTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Unknown response") + time.sleep(20) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + slug = resp["slug"] + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Alice incorrectly saved as unfunded") + + # alice send order fulfillment + with open('testdata/v5/fulfillment.json') as fulfillment_file: + fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) + fulfillment_json["orderId"] = orderId + fulfillment_json["slug"] = slug + api_url = alice["gateway_url"] + "ob/orderfulfillment" + r = requests.post(api_url, data=json.dumps(fulfillment_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Fulfillment post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Fulfillment POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # check bob received fulfillment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Bob failed to detect order fulfillment") + + # check alice set fulfillment correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthFulfillDirectOnlineTest - FAIL: Alice failed to order fulfillment") + + print("EthFulfillDirectOnlineTest - PASS") + + +if __name__ == '__main__': + print("Running EthFulfillDirectOnlineTest") + EthFulfillDirectOnlineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_market_price_modifier.py b/qa/eth_market_price_modifier.py new file mode 100644 index 0000000000..db5dd8f4ae --- /dev/null +++ b/qa/eth_market_price_modifier.py @@ -0,0 +1,146 @@ +import requests +import json +import time +from copy import deepcopy +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthMarketPriceModifierTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + self.price_modifier = 10.25 + + def run_test(self): + vendor = self.nodes[1] + buyer = self.nodes[2] + + # generate some coins and send them to buyer + time.sleep(4) + api_url = buyer["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Unknown response") + time.sleep(20) + + # post profile for vendor + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = vendor["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listings to vendor + with open('testdata/v5/eth_listing_crypto.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["metadata"]["coinType"] = "TETH" + listing_json["metadata"]["coinDivisibility"] = 18 + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + listing_json_with_modifier = deepcopy(listing_json) + listing_json_with_modifier["item"]["priceModifier"] = self.price_modifier + + api_url = vendor["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthMarketPriceModifierTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + slug = json.loads(r.text)["slug"] + + api_url = vendor["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json_with_modifier, indent=4)) + if r.status_code == 404: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthMarketPriceModifierTest - FAIL: Listing POST 2 failed. Reason: %s", resp["reason"]) + slug_with_modifier = json.loads(r.text)["slug"] + + # check vendor's local listings and check for modifier + api_url = vendor["gateway_url"] + "ob/listings" + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Couldn't get vendor local listings") + resp = json.loads(r.text) + for listing in resp: + if "modifier" not in listing: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Vendor's local listings index doesn't include price modifier") + + # check vendor's listings from buyer and check for modifier + api_url = buyer["gateway_url"] + "ob/listings/" + vendor["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Couldn't get vendor listings from buyer") + resp = json.loads(r.text) + for listing in resp: + if "modifier" not in listing: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Vendor's listings don't include price modifier from buyer") + + # get listing hashes + api_url = vendor["gateway_url"] + "ipns/" + vendor["peerId"] + "/listings.json" + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listing_id = resp[0]["hash"] + listing_id_with_modifier = resp[1]["hash"] + + # get second listing and check for modifier + slug = resp[1]["slug"] + api_url = buyer["gateway_url"] + "ob/listing/" + vendor["peerId"] + "/" + slug + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Couldn't get vendor listings") + resp = json.loads(r.text) + if "priceModifier" not in resp["listing"]["metadata"]: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Listing doesn't include priceModifier") + + # buyer send orders + with open('testdata/v5/order_crypto.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listing_id + order_json["paymentCoin"] = "T" + self.cointype + api_url = buyer["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthMarketPriceModifierTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + payment_address = resp["paymentAddress"] + payment_amount = int(resp["amount"]["amount"]) + + with open('testdata/v5/order_crypto.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listing_id_with_modifier + order_json["paymentCoin"] = "T" + self.cointype + api_url = buyer["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthMarketPriceModifierTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthMarketPriceModifierTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + payment_address_with_modifier = resp["paymentAddress"] + payment_amount_with_modifier = int(resp["amount"]["amount"]) + + # Check that modified price is different than regular price + pct_change = round((payment_amount-payment_amount_with_modifier) / payment_amount * -100, 2) + if pct_change != self.price_modifier: + raise TestFailure(f"EthMarketPriceModifierTest - FAIL: Incorrect price modification: wanted {self.price_modifier} but got {pct_change}") + + print("EthMarketPriceModifierTest - PASS") + + +if __name__ == '__main__': + print("Running EthMarketPriceModifierTest") + EthMarketPriceModifierTest().main(["--regtest"]) diff --git a/qa/eth_purchase_crypto_listing.py b/qa/eth_purchase_crypto_listing.py new file mode 100644 index 0000000000..d7b69e2362 --- /dev/null +++ b/qa/eth_purchase_crypto_listing.py @@ -0,0 +1,206 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthPurchaseCryptoListingTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + + def run_test(self): + vendor = self.nodes[1] + buyer = self.nodes[2] + + # generate some coins and send them to buyer + time.sleep(4) + api_url = buyer["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Unknown response") + time.sleep(20) + + # post profile for vendor + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = vendor["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to vendor + with open('testdata/v5/eth_listing_crypto.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + api_url = vendor["gateway_url"] + "ob/listing" + print("api_url ", api_url) + print(json.dumps(listing_json, indent=4)) + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + slug = json.loads(r.text)["slug"] + + # check inventory + api_url = vendor["gateway_url"] + "ob/inventory" + r = requests.get(api_url, data=json.dumps(listing_json, indent=4)) + resp = json.loads(r.text) + if r.status_code != 200: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Inventory get endpoint failed") + if resp["ether"]["inventory"] != '350000000000000000': + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Inventory incorrect: %d", resp["ether"]["inventory"]) + + # get listing hash + api_url = vendor["gateway_url"] + "ob/listings/" + vendor["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + if resp[0]["coinType"] != "TETH": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Vendor incorrectly saved listings.json without a coinType") + listingId = resp[0]["hash"] + + # buyer send order + with open('testdata/v5/order_crypto.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = buyer["gateway_url"] + "ob/purchase" + print("before order purchase", api_url) + print(json.dumps(order_json, indent=4)) + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + if int(payment_amount["amount"]) <= 0: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Purchase POST failed: paymentAmount is <= 0") + + # check the purchase saved correctly + api_url = buyer["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Couldn't load order from Buyer") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer incorrectly saved as funded") + if resp["contract"]["vendorListings"][0]["metadata"]["coinType"] != "TETH": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer incorrectly saved without a coinType") + if resp["contract"]["buyerOrder"]["items"][0]["paymentAddress"] != "crypto_payment_address": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer incorrectly saved without a paymentAddress") + + # check the sale saved correctly + api_url = vendor["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Couldn't load order from Vendor") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Vendor purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Vendor incorrectly saved as funded") + if resp["contract"]["vendorListings"][0]["metadata"]["coinType"] != "TETH": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Vendor incorrectly saved without a coinType") + if resp["contract"]["buyerOrder"]["items"][0]["paymentAddress"] != "crypto_payment_address": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Vendor incorrectly saved without a paymentAddress") + if resp["contract"]["buyerOrder"]["items"][0]["memo"] != "thanks!": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Vendor incorrectly saved without a memo") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = buyer["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check buyer detected payment + api_url = buyer["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Couldn't load order from Buyer") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer incorrectly saved as unfunded") + if resp["contract"]["vendorListings"][0]["metadata"]["coinType"] != "TETH": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer incorrectly saved without a coinType") + if resp["contract"]["buyerOrder"]["items"][0]["paymentAddress"] != "crypto_payment_address": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer incorrectly saved without a paymentAddress") + + # check vendor detected payment + time.sleep(120) + api_url = vendor["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Couldn't load order from Vendor") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Vendor failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Vendor incorrectly saved as unfunded") + + with open('testdata/v5/fulfillment_crypto.json') as fulfillment_file: + fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) + fulfillment_json["orderId"] = orderId + fulfillment_json["slug"] = slug + api_url = vendor["gateway_url"] + "ob/orderfulfillment" + r = requests.post(api_url, data=json.dumps(fulfillment_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Fulfillment post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Fulfillment POST failed. Reason: %s", resp["reason"]) + + # check buyer received fulfillment + api_url = buyer["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Couldn't load order from Buyer") + resp = json.loads(r.text) + if resp["state"] != "FULFILLED": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer failed to detect order fulfillment") + if resp["contract"]["vendorOrderFulfillment"][0]["cryptocurrencyDelivery"][0]["transactionID"] != "crypto_transaction_id": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Buyer failed to detect transactionID") + + api_url = vendor["gateway_url"] + "ob/inventory" + r = requests.get(api_url, data=json.dumps(listing_json, indent=4)) + resp = json.loads(r.text) + if r.status_code != 200: + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Inventory get endpoint failed") + if resp["ether"]["inventory"] != "349999999900000000": + raise TestFailure("EthPurchaseCryptoListingTest - FAIL: Inventory incorrect: %d", resp["ether"]["inventory"]) + + print("EthPurchaseCryptoListingTest - PASS") + + +if __name__ == '__main__': + print("Running EthPurchaseCryptoListingTest") + EthPurchaseCryptoListingTest().main(["--regtest"]) diff --git a/qa/eth_purchase_digital.py b/qa/eth_purchase_digital.py new file mode 100644 index 0000000000..4764469d6a --- /dev/null +++ b/qa/eth_purchase_digital.py @@ -0,0 +1,146 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthPurchaseDigital(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthPurchaseDigital - FAIL: Address endpoint not found") + else: + raise TestFailure("EthPurchaseDigital - FAIL: Unknown response") + time.sleep(20) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_digital.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDigital - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDigital - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDigital - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_digital.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + print("before purchase : ", api_url) + print(json.dumps(order_json, indent=4)) + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDigital - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDigital - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDigital - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseDigital - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseDigital - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDigital - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseDigital - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseDigital - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDigital - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDigital - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDigital - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthPurchaseDigital - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseDigital - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDigital - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthPurchaseDigital - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseDigital - FAIL: Alice incorrectly saved as unfunded") + + print("EthPurchaseDigital - PASS") + + +if __name__ == '__main__': + print("Running EthPurchaseDigital") + EthPurchaseDigital().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_purchase_direct_offline.py b/qa/eth_purchase_direct_offline.py new file mode 100644 index 0000000000..700cb9d4df --- /dev/null +++ b/qa/eth_purchase_direct_offline.py @@ -0,0 +1,214 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthPurchaseDirectOfflineTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob fetch listing to cache + api_url = bob["gateway_url"] + "ipfs/" + listingId + requests.get(api_url) + + # generate some coins and send them to bob + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Unknown response") + time.sleep(3) + + # shutdown alice + api_url = alice["gateway_url"] + "ob/shutdown" + requests.post(api_url, data="") + time.sleep(10) + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + if resp["vendorOnline"] == True: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Purchase returned vendor is online") + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Bob incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if len(resp["paymentAddressTransactions"]) <= 0: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Bob incorrectly saved as unfunded") + if resp["state"] != "PENDING": + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Bob purchase saved in incorrect state") + + + + # startup alice again + self.start_node(1, alice) + time.sleep(60) + + # check alice detected order and payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "PENDING": + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Alice incorrectly saved as unfunded") + + # check alice balance is zero + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + unconfirmed = int(resp["unconfirmed"]) + #if confirmed + unconfirmed > 0: + # raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Alice should have zero balance at this point") + else: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Failed to query Alice's balance") + time.sleep(1) + + # alice confirm offline order + api_url = alice["gateway_url"] + "ob/orderconfirmation" + oc = { + "orderId": orderId, + "reject": False + } + r = requests.post(api_url, data=json.dumps(oc, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Order confirmation post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: order confirmation POST failed. Reason: %s", resp["reason"]) + time.sleep(10) + + time.sleep(2) + + # Check the funds moved into alice's wallet + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + if confirmed <= 0: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Alice failed to receive the multisig payout") + else: + raise TestFailure("EthPurchaseDirectOfflineTest - FAIL: Failed to query Alice's balance") + + # check bob detected order confirmation and outgoing transaction + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Bob failed to set state correctly") + if resp["funded"] == False: + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice set state correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Alice failed to detect payment2") + if resp["funded"] == False: + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Alice incorrectly saved as unfunded") + + print("EthPurchaseDirectOfflineTest - PASS") + + +if __name__ == '__main__': + print("Running EthPurchaseDirectOfflineTest") + EthPurchaseDirectOfflineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_purchase_direct_online.py b/qa/eth_purchase_direct_online.py new file mode 100644 index 0000000000..5f59fda892 --- /dev/null +++ b/qa/eth_purchase_direct_online.py @@ -0,0 +1,173 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthPurchaseDirectOnlineTest(OpenBazaarTestFramework): + + def __init__(self): + print("i am in pur init....") + super().__init__() + self.num_nodes = 3 + + def run_test(self): + vendor = self.nodes[1] + buyer = self.nodes[2] + + # generate some coins and send them to buyer + api_url = buyer["gateway_url"] + "wallet/address/" + self.cointype + print("see the wallet address : ", api_url) + r = requests.get(api_url) + print("raw resp : ") + print(r) + if r.status_code == 200: + print("resp : ", json.loads(r.text)) + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Unknown response") + time.sleep(20) + + # post profile for vendor + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = vendor["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to vendor + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + api_url = vendor["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = vendor["gateway_url"] + "ob/listings/" + vendor["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + + # buyer send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = buyer["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + + # check the purchase saved correctly + api_url = buyer["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Couldn't load order from Buyer") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Buyer purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Buyer incorrectly saved as funded") + + # check the sale saved correctly + api_url = vendor["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Couldn't load order from Vendor") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Vendor purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Vendor incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = buyer["gateway_url"] + "ob/orderspend" + print("orderspend spend ... ", api_url) + print("payload : ", json.dumps(spend, indent=4)) + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check buyer detected payment + api_url = buyer["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Couldn't load order from Buyer") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Buyer failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Buyer incorrectly saved as unfunded") + + # check vendor detected payment + api_url = vendor["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Couldn't load order from Vendor") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Vendor failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Vendor incorrectly saved as unfunded") + + # buyer send order + with open('testdata/v5/order_direct_too_much_quantity.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = buyer["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + resp = json.loads(r.text) + print("after purchasing too much stuff, the response : ") + print(r.status_code) + print(resp) + if r.status_code == 200: + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Purchase POST should have failed failed.") + if resp["reason"] != "not enough inventory": + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Purchase POST failed with incorrect reason: %s", resp["reason"]) + if resp["code"] != "ERR_INSUFFICIENT_INVENTORY": + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Purchase POST failed with incorrect code: %s", resp["code"]) + if resp["remainingInventory"] != '6': + raise TestFailure("EthPurchaseDirectOnlineTest - FAIL: Purchase POST failed with incorrect remainingInventory: %d", resp["remainingInventory"]) + + print("EthPurchaseDirectOnlineTest - PASS") + + +if __name__ == '__main__': + print("Running EthEthPurchaseDirectOnlineTest") + EthPurchaseDirectOnlineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_purchase_moderated_offline.py b/qa/eth_purchase_moderated_offline.py new file mode 100644 index 0000000000..bf1f289170 --- /dev/null +++ b/qa/eth_purchase_moderated_offline.py @@ -0,0 +1,226 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthPurchaseModeratedOfflineTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + api_url = alice["gateway_url"] + "ob/listing" + listing_json["moderators"] = [moderatorId] + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob fetch listing to cache + api_url = bob["gateway_url"] + "ipfs/" + listingId + requests.get(api_url) + + # shutdown alice + api_url = alice["gateway_url"] + "ob/shutdown" + requests.post(api_url, data="") + time.sleep(10) + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + if resp["vendorOnline"] == True: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Purchase returned vendor is online") + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Bob incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if len(resp["paymentAddressTransactions"]) <= 0: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Bob incorrectly saved as unfunded") + if resp["state"] != "PENDING": + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Bob purchase saved in incorrect state") + + # startup alice again + self.start_node(1, alice) + time.sleep(80) + + # check alice detected order and payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Couldn't load order from Alice %s", r.status_code) + resp = json.loads(r.text) + if resp["state"] != "PENDING": + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Alice failed to detect initial payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Alice incorrectly saved as unfunded") + + # check alice balance is zero + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + unconfirmed = int(resp["unconfirmed"]) + ##if confirmed + unconfirmed > 0: + ## raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Alice should have zero balance at this point") + else: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Failed to query Alice's balance") + time.sleep(1) + + # alice confirm offline order + api_url = alice["gateway_url"] + "ob/orderconfirmation" + oc = { + "orderId": orderId, + "reject": False + } + r = requests.post(api_url, data=json.dumps(oc, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Order confirmation post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOfflineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + time.sleep(10) + + # check bob detected order confirmation + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Bob failed to set state correctly") + if resp["funded"] == False: + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice set state correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Alice incorrectly saved as unfunded") + + print("EthPurchaseModeratedOfflineTest - PASS") + + +if __name__ == '__main__': + print("Running EthPurchaseModeratedOfflineTest") + EthPurchaseModeratedOfflineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_purchase_moderated_online.py b/qa/eth_purchase_moderated_online.py new file mode 100644 index 0000000000..75468cda51 --- /dev/null +++ b/qa/eth_purchase_moderated_online.py @@ -0,0 +1,174 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthPurchaseModeratedOnlineTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + listing_json["moderators"] = [moderatorId] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + self.print_logs(alice, "ob.log") + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(60) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + print("lets see bob's resp : ") + print(resp) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthPurchaseModeratedOnlineTest - FAIL: Alice incorrectly saved as unfunded") + + print("EthPurchaseModeratedOnlineTest - PASS") + + +if __name__ == '__main__': + print("Running EthPurchaseModeratedOnlineTest") + EthPurchaseModeratedOnlineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_purchase_offline_error.py b/qa/eth_purchase_offline_error.py new file mode 100644 index 0000000000..3dc2bac87e --- /dev/null +++ b/qa/eth_purchase_offline_error.py @@ -0,0 +1,129 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthPurchaseOfflineErrorTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob fetch listing to cache + api_url = bob["gateway_url"] + "ipfs/" + listingId + requests.get(api_url) + + # generate some coins and send them to bob + api_url = bob["gateway_url"] + "wallet/address/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Unknown response") + time.sleep(3) + + # shutdown alice + api_url = alice["gateway_url"] + "ob/shutdown" + requests.post(api_url, data="") + time.sleep(30) + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + + # set empty shipping address to trigger error + order_json["address"] = "" + order_json["paymentCoin"] = "T" + self.cointype + + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + if resp["vendorOnline"] == True: + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Purchase returned vendor is online") + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Bob incorrectly saved as funded") + + # startup alice again + self.start_node(1, alice) + time.sleep(45) + + # check alice detected processing error + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "PROCESSING_ERROR": + raise TestFailure("EthPurchaseOfflineErrorTest - FAIL: Alice failed to detect processing error") + + # check bob detected error message from alice + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "PROCESSING_ERROR": + raise TestFailure("PurchaseDirectOnlineTest - FAIL: Bob failed to set state correctly") + + print("EthPurchaseOfflineErrorTest - PASS") + + +if __name__ == '__main__': + print("Running EthPurchaseOfflineErrorTest") + EthPurchaseOfflineErrorTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_refund_direct.py b/qa/eth_refund_direct.py new file mode 100644 index 0000000000..43806f8183 --- /dev/null +++ b/qa/eth_refund_direct.py @@ -0,0 +1,204 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthRefundDirectTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthRefundDirectTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthRefundDirectTest - FAIL: Unknown response") + time.sleep(2) + + # generate some coins and send them to alice + time.sleep(4) + api_url = alice["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthRefundDirectTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthRefundDirectTest - FAIL: Unknown response") + time.sleep(20) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundDirectTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRefundDirectTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundDirectTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundDirectTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRefundDirectTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundDirectTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthRefundDirectTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthRefundDirectTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundDirectTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthRefundDirectTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthRefundDirectTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundDirectTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRefundDirectTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundDirectTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthRefundDirectTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthRefundDirectTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundDirectTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthRefundDirectTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthRefundDirectTest - FAIL: Alice incorrectly saved as unfunded") + + # alice refund order + api_url = alice["gateway_url"] + "ob/refund" + refund = {"orderId": orderId} + r = requests.post(api_url, data=json.dumps(refund, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundDirectTest - FAIL: Refund endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRefundDirectTest - FAIL: Refund POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # alice check order refunded correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundDirectTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "REFUNDED": + raise TestFailure("EthRefundDirectTest - FAIL: Alice failed to save as rejected") + if "refundAddressTransaction" not in resp: + raise TestFailure("EthRefundDirectTest - FAIL: Alice failed to record refund payment") + + # bob check order refunded correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundDirectTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "REFUNDED": + raise TestFailure("EthRefundDirectTest - FAIL: Bob failed to save as rejected") + if "refundAddressTransaction" not in resp: + raise TestFailure("EthRefundDirectTest - FAIL: Bob failed to record refund payment") + + time.sleep(2) + + # Check the funds moved into bob's wallet + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + #if confirmed <= 50 - int(payment_amount["amount"]): + # raise TestFailure("EthRefundDirectTest - FAIL: Bob failed to receive the multisig payout") + else: + raise TestFailure("EthRefundDirectTest - FAIL: Failed to query Bob's balance") + + print("EthRefundDirectTest - PASS") + + +if __name__ == '__main__': + print("Running EthRefundDirectTest") + EthRefundDirectTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_refund_moderated.py b/qa/eth_refund_moderated.py new file mode 100644 index 0000000000..8d2fbaee51 --- /dev/null +++ b/qa/eth_refund_moderated.py @@ -0,0 +1,224 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthRefundModeratedTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthRefundModeratedTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthRefundModeratedTest - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundModeratedTest - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRefundModeratedTest - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundModeratedTest - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRefundModeratedTest - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + listing_json["moderators"] = [moderatorId] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundModeratedTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRefundModeratedTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundModeratedTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundModeratedTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + self.print_logs(alice, "ob.log") + raise TestFailure("EthRefundModeratedTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundModeratedTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthRefundModeratedTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthRefundModeratedTest - FAIL: Bob incorrectly saved as funded") + + # check the sale saved correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundModeratedTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthRefundModeratedTest - FAIL: Alice purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthRefundModeratedTest - FAIL: Alice incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundModeratedTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRefundModeratedTest - FAIL: Spend POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundModeratedTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthRefundModeratedTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthRefundModeratedTest - FAIL: Bob incorrectly saved as unfunded") + + # check alice detected payment + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundModeratedTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_FULFILLMENT": + raise TestFailure("EthRefundModeratedTest - FAIL: Alice failed to detect payment") + if resp["funded"] == False: + raise TestFailure("EthRefundModeratedTest - FAIL: Alice incorrectly saved as unfunded") + time.sleep(5) + + # alice refund order + api_url = alice["gateway_url"] + "ob/refund" + refund = {"orderId": orderId} + r = requests.post(api_url, data=json.dumps(refund, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRefundModeratedTest - FAIL: Refund endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRefundModeratedTest - FAIL: Refund POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # alice check order refunded correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundModeratedTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "REFUNDED": + raise TestFailure("EthRefundModeratedTest - FAIL: Alice failed to save as rejected") + #if len(resp["paymentAddressTransactions"]) != 2: + # raise TestFailure("EthRefundModeratedTest - FAIL: Alice failed to detect outgoing payment") + #if "refundAddressTransaction" not in resp or resp["refundAddressTransaction"] == {}: + # raise TestFailure("EthRefundModeratedTest - FAIL: Alice failed to detect refund payment") + + # bob check order refunded correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRefundModeratedTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "REFUNDED": + raise TestFailure("EthRefundModeratedTest - FAIL: Bob failed to save as rejected") + #if len(resp["paymentAddressTransactions"]) != 2: + # raise TestFailure("EthRefundModeratedTest - FAIL: Bob failed to detect outgoing payment") + #if "refundAddressTransaction" not in resp or resp["refundAddressTransaction"] == {}: + # raise TestFailure("EthRefundModeratedTest - FAIL: Alice failed to detect refund payment") + + time.sleep(2) + + # Check the funds moved into bob's wallet + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + #if confirmed <= 50 - int(payment_amount["amount"]): + # raise TestFailure("EthRefundModeratedTest - FAIL: Bob failed to receive the multisig payout") + else: + raise TestFailure("EthRefundModeratedTest - FAIL: Failed to query Bob's balance") + + print("EthRefundModeratedTest - PASS") + + +if __name__ == '__main__': + print("Running EthRefundModeratedTest") + EthRefundModeratedTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_reject_direct_offline.py b/qa/eth_reject_direct_offline.py new file mode 100644 index 0000000000..5e246d8652 --- /dev/null +++ b/qa/eth_reject_direct_offline.py @@ -0,0 +1,189 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthRejectDirectOfflineTest(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + + # generate some coins and send them to bob + time.sleep(4) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Address endpoint not found") + else: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Unknown response") + time.sleep(20) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob fetch listing to cache + api_url = bob["gateway_url"] + "ipfs/" + listingId + requests.get(api_url) + + # shutdown alice + api_url = alice["gateway_url"] + "ob/shutdown" + requests.post(api_url, data="") + time.sleep(4) + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + if resp["vendorOnline"] == True: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Purchase returned vendor is online") + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Bob incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if len(resp["paymentAddressTransactions"]) <= 0: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Bob incorrectly saved as unfunded") + if resp["state"] != "PENDING": + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Bob purchase saved in incorrect state") + + # startup alice again + self.start_node(1, alice) + time.sleep(60) + + # alice reject order + api_url = alice["gateway_url"] + "ob/orderconfirmation" + oc = { + "orderId": orderId, + "reject": True + } + r = requests.post(api_url, data=json.dumps(oc, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Order confirmation post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRejectDirectOfflineTest - FAIL: OrderConfirmation POST failed. Reason: %s", resp["reason"]) + time.sleep(120) + + # alice check order rejected correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DECLINED": + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Alice failed to save as declined") + #if len(resp["paymentAddressTransactions"]) != 2: + # raise TestFailure("EthRejectDirectOfflineTest - FAIL: Alice failed to detect outgoing payment") + + # bob check order rejected correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "DECLINED": + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Bob failed to save as declined") + #if len(resp["paymentAddressTransactions"]) != 2: + # raise TestFailure("EthRejectDirectOfflineTest - FAIL: Bob failed to detect outgoing payment") + + time.sleep(2) + + # Check the funds moved into bob's wallet + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + #if confirmed <= 50 - int(payment_amount["amount"]): + # raise TestFailure("EthRejectDirectOfflineTest - FAIL: Bob failed to receive the multisig payout") + else: + raise TestFailure("EthRejectDirectOfflineTest - FAIL: Failed to query Bob's balance") + + print("EthRejectDirectOfflineTest - PASS") + + +if __name__ == '__main__': + print("Running EthRejectDirectOfflineTest") + EthRejectDirectOfflineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/eth_reject_moderated_offline.py b/qa/eth_reject_moderated_offline.py new file mode 100644 index 0000000000..44cbd4889d --- /dev/null +++ b/qa/eth_reject_moderated_offline.py @@ -0,0 +1,218 @@ +import requests +import json +import time +from collections import OrderedDict +from test_framework.test_framework import OpenBazaarTestFramework, TestFailure + + +class EthRejectModeratedOffline(OpenBazaarTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + + def run_test(self): + alice = self.nodes[1] + bob = self.nodes[2] + charlie = self.nodes[3] + + # generate some coins and send them to bob + time.sleep(3) + api_url = bob["gateway_url"] + "wallet/address/" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + address = resp["address"] + elif r.status_code == 404: + raise TestFailure("EthRejectModeratedOffline - FAIL: Address endpoint not found") + else: + raise TestFailure("EthRejectModeratedOffline - FAIL: Unknown response") + time.sleep(20) + + # create a profile for charlie + pro = {"name": "Charlie"} + api_url = charlie["gateway_url"] + "ob/profile" + r = requests.post(api_url, data=json.dumps(pro, indent=4)) + if r.status_code == 404: + raise TestFailure("PurchaseModeratedOnlineTest - FAIL: Profile post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("PurchaseModeratedOnlineTest - FAIL: Profile POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # make charlie a moderator + with open('testdata/v5/moderation.json') as listing_file: + moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) + api_url = charlie["gateway_url"] + "ob/moderator" + r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) + if r.status_code == 404: + raise TestFailure("PurchaseModeratedOnlineTest - FAIL: Moderator post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("PurchaseModeratedOnlineTest - FAIL: Moderator POST failed. Reason: %s", resp["reason"]) + moderatorId = charlie["peerId"] + time.sleep(4) + + # post profile for alice + with open('testdata/v5/profile.json') as profile_file: + profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) + api_url = alice["gateway_url"] + "ob/profile" + requests.post(api_url, data=json.dumps(profile_json, indent=4)) + + # post listing to alice + with open('testdata/v5/eth_listing.json') as listing_file: + listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) + listing_json["item"]["priceCurrency"]["code"] = "T" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] + + listing_json["moderators"] = [moderatorId] + api_url = alice["gateway_url"] + "ob/listing" + r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRejectModeratedOffline - FAIL: Listing post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRejectModeratedOffline - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + time.sleep(4) + + # get listing hash + api_url = alice["gateway_url"] + "ob/listings/" + alice["peerId"] + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectModeratedOffline - FAIL: Couldn't get listing index") + resp = json.loads(r.text) + listingId = resp[0]["hash"] + + # bob fetch listing to cache + api_url = bob["gateway_url"] + "ipfs/" + listingId + requests.get(api_url) + + # shutdown alice + api_url = alice["gateway_url"] + "ob/shutdown" + requests.post(api_url, data="") + time.sleep(4) + + # bob send order + with open('testdata/v5/order_direct.json') as order_file: + order_json = json.load(order_file, object_pairs_hook=OrderedDict) + order_json["items"][0]["listingHash"] = listingId + order_json["moderator"] = moderatorId + order_json["paymentCoin"] = "T" + self.cointype + api_url = bob["gateway_url"] + "ob/purchase" + r = requests.post(api_url, data=json.dumps(order_json, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRejectModeratedOffline - FAIL: Purchase post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRejectModeratedOffline - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + resp = json.loads(r.text) + orderId = resp["orderId"] + payment_address = resp["paymentAddress"] + payment_amount = resp["amount"] + if resp["vendorOnline"] == True: + raise TestFailure("EthRejectModeratedOffline - FAIL: Purchase returned vendor is online") + + # check the purchase saved correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectModeratedOffline - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "AWAITING_PAYMENT": + raise TestFailure("EthRejectModeratedOffline - FAIL: Bob purchase saved in incorrect state") + if resp["funded"] == True: + raise TestFailure("EthRejectModeratedOffline - FAIL: Bob incorrectly saved as funded") + + # fund order + spend = { + "currencyCode": "T" + self.cointype, + "address": payment_address, + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": True, + "orderID": orderId + } + api_url = bob["gateway_url"] + "ob/orderspend" + r = requests.post(api_url, data=json.dumps(spend, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRejectModeratedOffline - FAIL: Spend post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRejectModeratedOffline - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) + time.sleep(20) + + # check bob detected payment + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectModeratedOffline - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if len(resp["paymentAddressTransactions"]) <= 0: + raise TestFailure("EthRejectModeratedOffline - FAIL: Bob failed to detect his payment") + if resp["funded"] == False: + raise TestFailure("EthRejectModeratedOffline - FAIL: Bob incorrectly saved as unfunded") + if resp["state"] != "PENDING": + raise TestFailure("EthRejectModeratedOffline - FAIL: Bob purchase saved in incorrect state") + + + # startup alice again + self.start_node(1, alice) + time.sleep(45) + + # alice reject order + api_url = alice["gateway_url"] + "ob/orderconfirmation" + oc = { + "orderId": orderId, + "reject": True + } + r = requests.post(api_url, data=json.dumps(oc, indent=4)) + if r.status_code == 404: + raise TestFailure("EthRejectModeratedOffline - FAIL: Order confirmation post endpoint not found") + elif r.status_code != 200: + resp = json.loads(r.text) + raise TestFailure("EthRejectModeratedOffline - FAIL: OrderConfirmation POST failed. Reason: %s", resp["reason"]) + time.sleep(120) + + # alice check order rejected correctly + api_url = alice["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectModeratedOffline - FAIL: Couldn't load order from Alice") + resp = json.loads(r.text) + if resp["state"] != "DECLINED": + raise TestFailure("EthRejectModeratedOffline - FAIL: Alice failed to save as declined") + #if len(resp["paymentAddressTransactions"]) != 2: + # raise TestFailure("EthRejectModeratedOffline - FAIL: Alice failed to detect outgoing payment") + + # bob check order rejected correctly + api_url = bob["gateway_url"] + "ob/order/" + orderId + r = requests.get(api_url) + if r.status_code != 200: + raise TestFailure("EthRejectModeratedOffline - FAIL: Couldn't load order from Bob") + resp = json.loads(r.text) + if resp["state"] != "DECLINED": + raise TestFailure("EthRejectModeratedOffline - FAIL: Bob failed to save as declined") + #if len(resp["paymentAddressTransactions"]) != 2: + # raise TestFailure("EthRejectModeratedOffline - FAIL: Bob failed to detect outgoing payment") + + + time.sleep(2) + + # Check the funds moved into bob's wallet + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype + r = requests.get(api_url) + if r.status_code == 200: + resp = json.loads(r.text) + confirmed = int(resp["confirmed"]) + #unconfirmed = int(resp["unconfirmed"]) + #if confirmed <= 50 - int(payment_amount["amount"]): + # raise TestFailure("EthRejectModeratedOffline - FAIL: Bob failed to receive the multisig payout") + else: + raise TestFailure("EthRejectModeratedOffline - FAIL: Failed to query Bob's balance") + + print("EthRejectModeratedOffline - PASS") + + +if __name__ == '__main__': + print("Running EthRejectModeratedOffline") + EthRejectModeratedOffline().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/fulfill_direct_online.py b/qa/fulfill_direct_online.py index 20a82f81ec..1f7524e4ab 100644 --- a/qa/fulfill_direct_online.py +++ b/qa/fulfill_direct_online.py @@ -30,15 +30,19 @@ def run_test(self): time.sleep(20) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -60,7 +64,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -100,11 +104,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -135,9 +144,9 @@ def run_test(self): raise TestFailure("FulfillDirectOnlineTest - FAIL: Alice failed to detect payment") if resp["funded"] == False: raise TestFailure("FulfillDirectOnlineTest - FAIL: Alice incorrectly saved as unfunded") - + # alice send order fulfillment - with open('testdata/fulfillment.json') as fulfillment_file: + with open('testdata/'+ self.vendor_version +'/fulfillment.json') as fulfillment_file: fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) fulfillment_json["orderId"] = orderId fulfillment_json["slug"] = slug @@ -170,6 +179,7 @@ def run_test(self): print("FulfillDirectOnlineTest - PASS") + if __name__ == '__main__': print("Running FulfillDirectOnlineTest") FulfillDirectOnlineTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/listings.py b/qa/listings.py index 3361eb2e4e..7fece4c8f8 100644 --- a/qa/listings.py +++ b/qa/listings.py @@ -14,7 +14,7 @@ def setup_network(self): def run_test(self): vendor = self.nodes[1] - browser = self.nodes[2] + buyer = self.nodes[2] currency = "tbtc" @@ -33,9 +33,13 @@ def run_test(self): raise TestFailure("ListingsTest - FAIL: Listings GET failed. Reason: %s", resp["reason"]) # POST listing - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: ljson = json.load(listing_file, object_pairs_hook=OrderedDict) - ljson["metadata"]["pricingCurrency"] = "T" + self.cointype + if self.vendor_version == "v4": + ljson["metadata"]["priceCurrency"] = "t" + self.cointype + else: + ljson["item"]["priceCurrency"]["code"] = "t" + self.cointype + ljson["metadata"]["acceptedCurrencies"] = ["t" + self.cointype.lower()] currency = "T" + self.cointype api_url = vendor["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(ljson, indent=4)) @@ -79,7 +83,7 @@ def run_test(self): raise TestFailure("ListingsTest - FAIL: Listing should have acceptedCurrences in metadata") # check vendor's index from another node - api_url = browser["gateway_url"] + "ob/listings/" + vendor["peerId"] + api_url = buyer["gateway_url"] + "ob/listings/" + vendor["peerId"] r = requests.get(api_url) if r.status_code == 404: raise TestFailure("ListingsTest - FAIL: Listings get endpoint not found") @@ -109,4 +113,4 @@ def run_test(self): if __name__ == '__main__': print("Running ListingTest") - ListingsTest().main() + ListingsTest().main(["--regtest", "--disableexchangerates"]) diff --git a/qa/manage_crypto_listings.py b/qa/manage_crypto_listings.py index 2643037b6c..e7c125586c 100644 --- a/qa/manage_crypto_listings.py +++ b/qa/manage_crypto_listings.py @@ -15,7 +15,7 @@ def run_test(self): vendor = self.nodes[1] # post profile for vendor - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = vendor["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) @@ -27,10 +27,10 @@ def run_test(self): raise TestFailure("ManageCryptoListingsTest - FAIL: Incorrect listing count: %d", len(resp)) # post listing to vendor - with open('testdata/listing_crypto.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing_crypto.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] + listing_json["coinType"] = "TETH" api_url = vendor["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) if r.status_code != 200: @@ -45,8 +45,8 @@ def run_test(self): raise TestFailure("ManageCryptoListingsTest - FAIL: Incorrect listing count: %d", len(resp)) for listing in resp: if listing['contractType'] == 'CRYPTOCURRENCY': - if listing["coinType"] != "ETH": - raise TestFailure("ManageCryptoListingsTest - FAIL: coinType incorrect: %s", listing["coinType"]) + if listing["coinType"] != "TETH": + raise TestFailure("ManageCryptoListingsTest - FAIL: cryptoCurrencyCode incorrect: %s", listing["cryptoCurrencyCode"]) # delete listing api_url = vendor["gateway_url"] + "ob/listing/"+slug diff --git a/qa/market_price_modifier.py b/qa/market_price_modifier.py index 163046f0c1..9b0f0eb498 100644 --- a/qa/market_price_modifier.py +++ b/qa/market_price_modifier.py @@ -32,17 +32,23 @@ def run_test(self): time.sleep(20) # post profile for vendor - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = vendor["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listings to vendor - with open('testdata/listing_crypto.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing_crypto.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] + if self.vendor_version == "v5": + listing_json["metadata"]["coinType"] = "TBCH" + listing_json["metadata"]["coinDivisibility"] = 8 + listing_json["metadata"]["acceptedCurrencies"] = ["T" + self.cointype] listing_json_with_modifier = deepcopy(listing_json) - listing_json_with_modifier["metadata"]["priceModifier"] = self.price_modifier + if self.vendor_version == "v4": + listing_json_with_modifier["metadata"]["priceModifier"] = self.price_modifier + else: + listing_json_with_modifier["item"]["priceModifier"] = self.price_modifier api_url = vendor["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -59,7 +65,7 @@ def run_test(self): raise TestFailure("MarketPriceModifierTest - FAIL: Listing post endpoint not found") elif r.status_code != 200: resp = json.loads(r.text) - raise TestFailure("MarketPriceModifierTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) + raise TestFailure("MarketPriceModifierTest - FAIL: Listing POST 2 failed. Reason: %s", resp["reason"]) slug_with_modifier = json.loads(r.text)["slug"] # check vendor's local listings and check for modifier @@ -69,7 +75,7 @@ def run_test(self): raise TestFailure("MarketPriceModifierTest - FAIL: Couldn't get vendor local listings") resp = json.loads(r.text) for listing in resp: - if "modifier" not in listing["price"]: + if "modifier" not in listing: raise TestFailure("MarketPriceModifierTest - FAIL: Vendor's local listings index doesn't include price modifier") # check vendor's listings from buyer and check for modifier @@ -79,7 +85,7 @@ def run_test(self): raise TestFailure("MarketPriceModifierTest - FAIL: Couldn't get vendor listings from buyer") resp = json.loads(r.text) for listing in resp: - if "modifier" not in listing["price"]: + if "modifier" not in listing: raise TestFailure("MarketPriceModifierTest - FAIL: Vendor's listings don't include price modifier from buyer") # get listing hashes @@ -102,10 +108,10 @@ def run_test(self): raise TestFailure("MarketPriceModifierTest - FAIL: Listing doesn't include priceModifier") # buyer send orders - with open('testdata/order_crypto.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_crypto.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listing_id - order_json["paymentCoin"] = "t" + self.cointype + order_json["paymentCoin"] = "T" + self.cointype api_url = buyer["gateway_url"] + "ob/purchase" r = requests.post(api_url, data=json.dumps(order_json, indent=4)) if r.status_code == 404: @@ -115,12 +121,12 @@ def run_test(self): raise TestFailure("MarketPriceModifierTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) resp = json.loads(r.text) payment_address = resp["paymentAddress"] - payment_amount = resp["amount"] + payment_amount = int(resp["amount"]["amount"]) - with open('testdata/order_crypto.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_crypto.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listing_id_with_modifier - order_json["paymentCoin"] = "t" + self.cointype + order_json["paymentCoin"] = "T" + self.cointype api_url = buyer["gateway_url"] + "ob/purchase" r = requests.post(api_url, data=json.dumps(order_json, indent=4)) if r.status_code == 404: @@ -130,7 +136,10 @@ def run_test(self): raise TestFailure("MarketPriceModifierTest - FAIL: Purchase POST failed. Reason: %s", resp["reason"]) resp = json.loads(r.text) payment_address_with_modifier = resp["paymentAddress"] - payment_amount_with_modifier = resp["amount"] + if self.buyer_version == "v4": + payment_address_with_modifier = resp["amount"] + else: + payment_amount_with_modifier = int(resp["amount"]["amount"]) # Check that modified price is different than regular price pct_change = round((payment_amount-payment_amount_with_modifier) / payment_amount * -100, 2) diff --git a/qa/out_of_inventory.py b/qa/out_of_inventory.py index 058578028e..f9a627805b 100644 --- a/qa/out_of_inventory.py +++ b/qa/out_of_inventory.py @@ -16,15 +16,19 @@ def run_test(self): bob = self.nodes[2] # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == 4: + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] listing_json["item"]["skus"][4]["quantity"] = 0 api_url = alice["gateway_url"] + "ob/listing" @@ -67,7 +71,7 @@ def run_test(self): time.sleep(10) # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -98,11 +102,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == 4: + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -129,7 +138,7 @@ def run_test(self): self.send_bitcoin_cmd("generate", 1) # startup alice again - self.start_node(alice) + self.start_node(1, alice) time.sleep(45) # check alice detected order and payment @@ -144,7 +153,7 @@ def run_test(self): raise TestFailure("OutOfInventoryTest - FAIL: Alice incorrectly saved as unfunded") # check alice balance is zero - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) @@ -174,7 +183,7 @@ def run_test(self): time.sleep(2) # Check the funds moved into alice's wallet - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) diff --git a/qa/purchase_crypto_listing.py b/qa/purchase_crypto_listing.py index 33d881d24c..6642e3da6b 100644 --- a/qa/purchase_crypto_listing.py +++ b/qa/purchase_crypto_listing.py @@ -30,13 +30,13 @@ def run_test(self): time.sleep(20) # post profile for vendor - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = vendor["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to vendor - with open('testdata/listing_crypto.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing_crypto.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] @@ -55,8 +55,9 @@ def run_test(self): resp = json.loads(r.text) if r.status_code != 200: raise TestFailure("PurchaseCryptoListingTest - FAIL: Inventory get endpoint failed") - if resp[0]["quantity"] != 350000000: - raise TestFailure("PurchaseCryptoListingTest - FAIL: Inventory incorrect: %d", resp[0]["quantity"]) + + if int(resp["ether"]["inventory"]) != 350000000000000000: + raise TestFailure("PurchaseCryptoListingTest - FAIL: Inventory incorrect: %d", resp["ether"]["inventory"]) # get listing hash api_url = vendor["gateway_url"] + "ipns/" + vendor["peerId"] + "/listings.json" @@ -64,12 +65,12 @@ def run_test(self): if r.status_code != 200: raise TestFailure("PurchaseCryptoListingTest - FAIL: Couldn't get listing index") resp = json.loads(r.text) - if resp[0]["coinType"] != "ETH": + if resp[0]["coinType"] != "TETH": raise TestFailure("PurchaseCryptoListingTest - FAIL: Vendor incorrectly saved listings.json without a coinType") listingId = resp[0]["hash"] # buyer send order - with open('testdata/order_crypto.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_crypto.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -84,7 +85,12 @@ def run_test(self): orderId = resp["orderId"] payment_address = resp["paymentAddress"] payment_amount = resp["amount"] - if payment_amount <= 0: + amt = 0 + if self.buyer_version == "v4": + amt = payment_amount + else: + amt = int(payment_amount["amount"]) + if amt <= 0: raise TestFailure("PurchaseCryptoListingTest - FAIL: Purchase POST failed: paymentAmount is <= 0") # check the purchase saved correctly @@ -97,7 +103,7 @@ def run_test(self): raise TestFailure("PurchaseCryptoListingTest - FAIL: Buyer purchase saved in incorrect state") if resp["funded"] == True: raise TestFailure("PurchaseCryptoListingTest - FAIL: Buyer incorrectly saved as funded") - if resp["contract"]["vendorListings"][0]["metadata"]["coinType"] != "ETH": + if resp["contract"]["vendorListings"][0]["metadata"]["coinType"] != "TETH": raise TestFailure("PurchaseCryptoListingTest - FAIL: Buyer incorrectly saved without a coinType") if resp["contract"]["buyerOrder"]["items"][0]["paymentAddress"] != "crypto_payment_address": raise TestFailure("PurchaseCryptoListingTest - FAIL: Buyer incorrectly saved without a paymentAddress") @@ -112,7 +118,7 @@ def run_test(self): raise TestFailure("PurchaseCryptoListingTest - FAIL: Vendor purchase saved in incorrect state") if resp["funded"] == True: raise TestFailure("PurchaseCryptoListingTest - FAIL: Vendor incorrectly saved as funded") - if resp["contract"]["vendorListings"][0]["metadata"]["coinType"] != "ETH": + if resp["contract"]["vendorListings"][0]["metadata"]["coinType"] != "TETH": raise TestFailure("PurchaseCryptoListingTest - FAIL: Vendor incorrectly saved without a coinType") if resp["contract"]["buyerOrder"]["items"][0]["paymentAddress"] != "crypto_payment_address": raise TestFailure("PurchaseCryptoListingTest - FAIL: Vendor incorrectly saved without a paymentAddress") @@ -121,11 +127,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = buyer["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -145,12 +156,13 @@ def run_test(self): raise TestFailure("PurchaseCryptoListingTest - FAIL: Buyer failed to detect his payment") if resp["funded"] == False: raise TestFailure("PurchaseCryptoListingTest - FAIL: Buyer incorrectly saved as unfunded") - if resp["contract"]["vendorListings"][0]["metadata"]["coinType"] != "ETH": + if resp["contract"]["vendorListings"][0]["metadata"]["coinType"] != "TETH": raise TestFailure("PurchaseCryptoListingTest - FAIL: Buyer incorrectly saved without a coinType") if resp["contract"]["buyerOrder"]["items"][0]["paymentAddress"] != "crypto_payment_address": raise TestFailure("PurchaseCryptoListingTest - FAIL: Buyer incorrectly saved without a paymentAddress") # check vendor detected payment + time.sleep(20) api_url = vendor["gateway_url"] + "ob/order/" + orderId r = requests.get(api_url) if r.status_code != 200: @@ -161,7 +173,7 @@ def run_test(self): if resp["funded"] == False: raise TestFailure("PurchaseCryptoListingTest - FAIL: Vendor incorrectly saved as unfunded") - with open('testdata/fulfillment_crypto.json') as fulfillment_file: + with open('testdata/'+ self.vendor_version +'/fulfillment_crypto.json') as fulfillment_file: fulfillment_json = json.load(fulfillment_file, object_pairs_hook=OrderedDict) fulfillment_json["orderId"] = orderId fulfillment_json["slug"] = slug @@ -189,8 +201,13 @@ def run_test(self): resp = json.loads(r.text) if r.status_code != 200: raise TestFailure("PurchaseCryptoListingTest - FAIL: Inventory get endpoint failed") - if resp[0]["quantity"] != 250000000: - raise TestFailure("PurchaseCryptoListingTest - FAIL: Inventory incorrect: %d", resp[0]["quantity"]) + + if self.buyer_version == "v4": + if int(resp["ether"]["inventory"]) != 340000000000000000: + raise TestFailure("PurchaseCryptoListingTest - FAIL: Inventory incorrect: %d", resp["ether"]["inventory"]) + if self.vendor_version == "v4": + if int(resp["ether"]["inventory"]) != 350000000: + raise TestFailure("PurchaseCryptoListingTest - FAIL: Inventory incorrect: %d", resp["ether"]["inventory"]) print("PurchaseCryptoListingTest - PASS") diff --git a/qa/purchase_digital.py b/qa/purchase_digital.py index 85c5376264..7925400ea5 100644 --- a/qa/purchase_digital.py +++ b/qa/purchase_digital.py @@ -30,15 +30,19 @@ def run_test(self): time.sleep(20) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/digital.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/digital.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -58,7 +62,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_digital.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_digital.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -98,11 +102,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: diff --git a/qa/purchase_direct_offline.py b/qa/purchase_direct_offline.py index 6deb13381c..4657052076 100644 --- a/qa/purchase_direct_offline.py +++ b/qa/purchase_direct_offline.py @@ -16,15 +16,20 @@ def run_test(self): bob = self.nodes[2] # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] + if self.vendor_version == 4: + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -66,7 +71,7 @@ def run_test(self): time.sleep(10) # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -97,11 +102,15 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == 4: + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -128,7 +137,7 @@ def run_test(self): self.send_bitcoin_cmd("generate", 1) # startup alice again - self.start_node(alice) + self.start_node(1, alice) time.sleep(60) # check alice detected order and payment @@ -143,7 +152,7 @@ def run_test(self): raise TestFailure("PurchaseDirectOfflineTest - FAIL: Alice incorrectly saved as unfunded") # check alice balance is zero - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) @@ -173,7 +182,7 @@ def run_test(self): time.sleep(2) # Check the funds moved into alice's wallet - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) diff --git a/qa/purchase_direct_online.py b/qa/purchase_direct_online.py index fecd7ca1ab..44a44d7ecb 100644 --- a/qa/purchase_direct_online.py +++ b/qa/purchase_direct_online.py @@ -29,15 +29,19 @@ def run_test(self): time.sleep(20) # post profile for vendor - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = vendor["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to vendor - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] + if self.vendor_version == "v4": + listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype api_url = vendor["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -58,7 +62,7 @@ def run_test(self): # buyer send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -74,7 +78,6 @@ def run_test(self): payment_address = resp["paymentAddress"] payment_amount = resp["amount"] - # check the purchase saved correctly api_url = buyer["gateway_url"] + "ob/order/" + orderId r = requests.get(api_url) @@ -99,11 +102,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == 4: + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = buyer["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -136,7 +144,7 @@ def run_test(self): raise TestFailure("PurchaseDirectOnlineTest - FAIL: Vendor incorrectly saved as unfunded") # buyer send order - with open('testdata/order_direct_too_much_quantity.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct_too_much_quantity.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId @@ -150,7 +158,7 @@ def run_test(self): raise TestFailure("PurchaseDirectOnlineTest - FAIL: Purchase POST failed with incorrect reason: %s", resp["reason"]) if resp["code"] != "ERR_INSUFFICIENT_INVENTORY": raise TestFailure("PurchaseDirectOnlineTest - FAIL: Purchase POST failed with incorrect code: %s", resp["code"]) - if resp["remainingInventory"] != 6: + if int(resp["remainingInventory"]) != 6: raise TestFailure("PurchaseDirectOnlineTest - FAIL: Purchase POST failed with incorrect remainingInventory: %d", resp["remainingInventory"]) print("PurchaseDirectOnlineTest - PASS") diff --git a/qa/purchase_moderated_offline.py b/qa/purchase_moderated_offline.py index cc96c53e43..5384848afe 100644 --- a/qa/purchase_moderated_offline.py +++ b/qa/purchase_moderated_offline.py @@ -42,7 +42,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -55,15 +55,19 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == 4: + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] api_url = alice["gateway_url"] + "ob/listing" listing_json["moderators"] = [moderatorId] @@ -93,7 +97,7 @@ def run_test(self): time.sleep(10) # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -125,11 +129,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == 4: + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -156,7 +165,7 @@ def run_test(self): self.send_bitcoin_cmd("generate", 1) # startup alice again - self.start_node(alice) + self.start_node(1, alice) time.sleep(80) # check alice detected order and payment @@ -171,7 +180,7 @@ def run_test(self): raise TestFailure("PurchaseModeratedOfflineTest - FAIL: Alice incorrectly saved as unfunded") # check alice balance is zero - api_url = alice["gateway_url"] + "wallet/balance/" + self.cointype + api_url = alice["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) diff --git a/qa/purchase_moderated_online.py b/qa/purchase_moderated_online.py index b3ef28e604..54426ec389 100644 --- a/qa/purchase_moderated_online.py +++ b/qa/purchase_moderated_online.py @@ -42,7 +42,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -55,15 +55,19 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] listing_json["moderators"] = [moderatorId] api_url = alice["gateway_url"] + "ob/listing" @@ -84,7 +88,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -126,11 +130,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: diff --git a/qa/purchase_offline_error.py b/qa/purchase_offline_error.py index adde5fa731..8b017ae99f 100644 --- a/qa/purchase_offline_error.py +++ b/qa/purchase_offline_error.py @@ -16,15 +16,19 @@ def run_test(self): bob = self.nodes[2] # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == 4: + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -66,7 +70,7 @@ def run_test(self): time.sleep(30) # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId @@ -100,7 +104,7 @@ def run_test(self): raise TestFailure("PurchaseOfflineErrorTest - FAIL: Bob incorrectly saved as funded") # startup alice again - self.start_node(alice) + self.start_node(1, alice) time.sleep(45) # check alice detected processing error diff --git a/qa/receive_coins.py b/qa/receive_coins.py index 464b48719a..b744879fbc 100644 --- a/qa/receive_coins.py +++ b/qa/receive_coins.py @@ -24,7 +24,7 @@ def run_test(self): raise TestFailure("ReceiveCoinsTest - FAIL: Unknown response") self.send_bitcoin_cmd("sendtoaddress", address, 10) time.sleep(20) - api_url = self.nodes[0]["gateway_url"] + "wallet/balance/" + self.cointype + api_url = self.nodes[0]["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) diff --git a/qa/refund_direct.py b/qa/refund_direct.py index a63dc2e9c8..0e30e7d0b6 100644 --- a/qa/refund_direct.py +++ b/qa/refund_direct.py @@ -44,15 +44,19 @@ def run_test(self): time.sleep(20) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == 4: + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -72,7 +76,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -112,11 +116,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == 4: + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -185,13 +194,18 @@ def run_test(self): time.sleep(2) # Check the funds moved into bob's wallet - api_url = bob["gateway_url"] + "wallet/balance/" + self.cointype + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) confirmed = int(resp["confirmed"]) + amt = 0 + if self.buyer_version == 4: + amt = payment_amount + else: + amt = int(payment_amount["amount"]) #unconfirmed = int(resp["unconfirmed"]) - if confirmed <= 50 - payment_amount: + if confirmed <= 50 - amt: raise TestFailure("RefundDirectTest - FAIL: Bob failed to receive the multisig payout") else: raise TestFailure("RefundDirectTest - FAIL: Failed to query Bob's balance") diff --git a/qa/refund_moderated.py b/qa/refund_moderated.py index cc495ec360..04ecd59a60 100644 --- a/qa/refund_moderated.py +++ b/qa/refund_moderated.py @@ -42,7 +42,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -55,15 +55,19 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] listing_json["moderators"] = [moderatorId] api_url = alice["gateway_url"] + "ob/listing" @@ -84,7 +88,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -126,11 +130,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == 4: + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -204,13 +213,18 @@ def run_test(self): time.sleep(2) # Check the funds moved into bob's wallet - api_url = bob["gateway_url"] + "wallet/balance/" + self.cointype + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) confirmed = int(resp["confirmed"]) + amt = 0 + if self.buyer_version == 4: + amt = payment_amount + else: + amt = int(payment_amount["amount"]) #unconfirmed = int(resp["unconfirmed"]) - if confirmed <= 50 - payment_amount: + if confirmed <= 50 - amt: raise TestFailure("RefundModeratedTest - FAIL: Bob failed to receive the multisig payout") else: raise TestFailure("RefundModeratedTest - FAIL: Failed to query Bob's balance") diff --git a/qa/reject_direct_offline.py b/qa/reject_direct_offline.py index b2df0e42ff..7bc2892c64 100644 --- a/qa/reject_direct_offline.py +++ b/qa/reject_direct_offline.py @@ -30,15 +30,20 @@ def run_test(self): time.sleep(20) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] + api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) if r.status_code == 404: @@ -66,7 +71,7 @@ def run_test(self): time.sleep(4) # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -97,11 +102,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -128,7 +138,7 @@ def run_test(self): self.send_bitcoin_cmd("generate", 1) # startup alice again - self.start_node(alice) + self.start_node(1, alice) time.sleep(60) # alice reject order @@ -139,10 +149,12 @@ def run_test(self): } r = requests.post(api_url, data=json.dumps(oc, indent=4)) if r.status_code == 404: + print(r.text, r.status_code) raise TestFailure("RejectDirectOfflineTest - FAIL: Order confirmation post endpoint not found") elif r.status_code != 200: resp = json.loads(r.text) raise TestFailure("RejectDirectOfflineTest - FAIL: OrderConfirmation POST failed. Reason: %s", resp["reason"]) + time.sleep(20) # alice check order rejected correctly @@ -171,13 +183,18 @@ def run_test(self): time.sleep(2) # Check the funds moved into bob's wallet - api_url = bob["gateway_url"] + "wallet/balance/" + self.cointype + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) confirmed = int(resp["confirmed"]) + amt = 0 + if self.buyer_version == 4: + amt = payment_amount + else: + amt = int(payment_amount["amount"]) #unconfirmed = int(resp["unconfirmed"]) - if confirmed <= 50 - payment_amount: + if confirmed <= 50 - amt: raise TestFailure("RejectDirectOfflineTest - FAIL: Bob failed to receive the multisig payout") else: raise TestFailure("RejectDirectOfflineTest - FAIL: Failed to query Bob's balance") diff --git a/qa/reject_moderated_offline.py b/qa/reject_moderated_offline.py index 9fa83839b5..c2a4a1c949 100644 --- a/qa/reject_moderated_offline.py +++ b/qa/reject_moderated_offline.py @@ -42,7 +42,7 @@ def run_test(self): time.sleep(4) # make charlie a moderator - with open('testdata/moderation.json') as listing_file: + with open('testdata/'+ self.moderator_version +'/moderation.json') as listing_file: moderation_json = json.load(listing_file, object_pairs_hook=OrderedDict) api_url = charlie["gateway_url"] + "ob/moderator" r = requests.put(api_url, data=json.dumps(moderation_json, indent=4)) @@ -55,15 +55,20 @@ def run_test(self): time.sleep(4) # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == 4: + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] + listing_json["moderators"] = [moderatorId] api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -92,7 +97,7 @@ def run_test(self): time.sleep(4) # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["moderator"] = moderatorId @@ -124,11 +129,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == 4: + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: @@ -155,7 +165,7 @@ def run_test(self): self.send_bitcoin_cmd("generate", 1) # startup alice again - self.start_node(alice) + self.start_node(1, alice) time.sleep(45) # alice reject order @@ -198,13 +208,18 @@ def run_test(self): time.sleep(2) # Check the funds moved into bob's wallet - api_url = bob["gateway_url"] + "wallet/balance/" + self.cointype + api_url = bob["gateway_url"] + "wallet/balance/T" + self.cointype r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) confirmed = int(resp["confirmed"]) + amt = 0 + if self.buyer_version == 4: + amt = payment_amount + else: + amt = int(payment_amount["amount"]) #unconfirmed = int(resp["unconfirmed"]) - if confirmed <= 50 - payment_amount: + if confirmed <= 50 - amt: raise TestFailure("RejectModeratedOffline - FAIL: Bob failed to receive the multisig payout") else: raise TestFailure("RejectModeratedOffline - FAIL: Failed to query Bob's balance") diff --git a/qa/runtests.sh b/qa/runtests.sh index defad89bcc..5cfeefa4b8 100755 --- a/qa/runtests.sh +++ b/qa/runtests.sh @@ -1,11 +1,28 @@ #!/bin/bash -for SCRIPT in * +# $1 is the openbazaar binary path +# $2 is the bitcoind path +# $3 will filter to match against script name +for SCRIPT in `ls | grep -v "eth_"` do b=$(basename $SCRIPT) extension="${b##*.}" p="py" - if [ $extension = $p ] - then - python3 $SCRIPT -b $1 -d $2 $3 + if [[ $extension = $p ]]; then + if [[ -z $3 ]]; then + echo "python3 $SCRIPT -b $1 -d $2" + python3 $SCRIPT -b $1 -d $2 + #if [[ $? -ne 0 ]]; then + #kill -1 $$ + #fi + else + # filter only the scripts of interest + if [[ $SCRIPT == *"$3"* ]]; then + echo "python3 $SCRIPT -b $1 -d $2" + python3 $SCRIPT -b $1 -d $2 + #if [[ $? -ne 0 ]]; then + #kill -1 $$ + #fi + fi + fi fi done diff --git a/qa/runtests_eth.sh b/qa/runtests_eth.sh new file mode 100755 index 0000000000..6192d681dd --- /dev/null +++ b/qa/runtests_eth.sh @@ -0,0 +1,14 @@ +#!/bin/bash +for SCRIPT in `ls | grep "eth_"` +do + b=$(basename $SCRIPT) + extension="${b##*.}" + p="py" + if [ $extension = $p ] + then + python3 $SCRIPT -b $1 -c "ETH" $2 + #if [[ $? -ne 0 ]]; then + #kill -1 $$ + #fi + fi +done diff --git a/qa/smtp_notification.py b/qa/smtp_notification.py index d6344f82fd..7024c143fe 100644 --- a/qa/smtp_notification.py +++ b/qa/smtp_notification.py @@ -21,7 +21,7 @@ def run_test(self): bob = self.nodes[2] # post profile for alice - with open('testdata/profile.json') as profile_file: + with open('testdata/'+ self.vendor_version +'/profile.json') as profile_file: profile_json = json.load(profile_file, object_pairs_hook=OrderedDict) api_url = alice["gateway_url"] + "ob/profile" requests.post(api_url, data=json.dumps(profile_json, indent=4)) @@ -77,9 +77,13 @@ def run_test(self): time.sleep(20) # post listing to alice - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] api_url = alice["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) @@ -99,7 +103,7 @@ def run_test(self): listingId = resp[0]["hash"] # bob send order - with open('testdata/order_direct.json') as order_file: + with open('testdata/'+ self.buyer_version +'/order_direct.json') as order_file: order_json = json.load(order_file, object_pairs_hook=OrderedDict) order_json["items"][0]["listingHash"] = listingId order_json["paymentCoin"] = "t" + self.cointype @@ -117,11 +121,16 @@ def run_test(self): # fund order spend = { - "wallet": self.cointype, + "currencyCode": "T" + self.cointype, "address": payment_address, - "amount": payment_amount, - "feeLevel": "NORMAL" + "amount": payment_amount["amount"], + "feeLevel": "NORMAL", + "requireAssociateOrder": False } + if self.buyer_version == "v4": + spend["amount"] = payment_amount + spend["wallet"] = "T" + self.cointype + api_url = bob["gateway_url"] + "wallet/spend" r = requests.post(api_url, data=json.dumps(spend, indent=4)) if r.status_code == 404: diff --git a/qa/test_framework/__init__.pyc b/qa/test_framework/__init__.pyc index e7aa527790..b526f44bf1 100644 Binary files a/qa/test_framework/__init__.pyc and b/qa/test_framework/__init__.pyc differ diff --git a/qa/test_framework/smtp_server.pyc b/qa/test_framework/smtp_server.pyc index e5c321e772..d5bb4bc7c3 100644 Binary files a/qa/test_framework/smtp_server.pyc and b/qa/test_framework/smtp_server.pyc differ diff --git a/qa/test_framework/test_framework.py b/qa/test_framework/test_framework.py index a1072eca3b..5055e00400 100644 --- a/qa/test_framework/test_framework.py +++ b/qa/test_framework/test_framework.py @@ -41,14 +41,17 @@ class OpenBazaarTestFramework(object): def __init__(self): self.nodes = [] self.bitcoin_api = None + self.vendor_version = "v5" + self.buyer_version = "v5" + self.moderator_version = "v5" def setup_nodes(self): for i in range(self.num_nodes): self.configure_node(i) - self.start_node(self.nodes[i]) + self.start_node(i, self.nodes[i]) def setup_network(self): - if self.bitcoind is not None: + if self.bitcoind is not None and self.cointype == "BTC": self.start_bitcoind() self.setup_nodes() @@ -58,13 +61,28 @@ def run_test(self): def send_bitcoin_cmd(self, *args): try: return self.bitcoin_api.call(*args) + except ConnectionResetError: + self.bitcoin_api = rpc.Proxy(btc_conf_file=self.btc_config) + return self.send_bitcoin_cmd(*args) except BrokenPipeError: self.bitcoin_api = rpc.Proxy(btc_conf_file=self.btc_config) return self.send_bitcoin_cmd(*args) def configure_node(self, n): - dir_path = os.path.join(self.temp_dir, "openbazaar-go", str(n)) - args = [self.binary, "init", "-d", dir_path, "--testnet"] + dir_path = os.path.join(self.temp_dir, "marketplace-go", str(n)) + args = [] + + if n == 1 and self.v4vendor_binary: + self.vendor_version = "v4" + args = [self.v4vendor_binary, "init", "-d", dir_path, "--testnet"] + elif n == 2 and self.v4buyer_binary: + self.buyer_version = "v4" + args = [self.v4buyer_binary, "init", "-d", dir_path, "--testnet"] + elif n == 3 and self.v4moderator_binary: + self.moderator_version = "v4" + args = [self.v4moderator_binary, "init", "-d", dir_path, "--testnet"] + else: + args = [self.binary, "init", "-d", dir_path, "--testnet"] if n < 3: args.extend(["-m", BOOTSTAP_MNEMONICS[n]]) process = subprocess.Popen(args, stdout=PIPE) @@ -82,11 +100,17 @@ def configure_node(self, n): config["Swarm"]["DisableNatPortMap"] = True self.cointype = self.cointype.upper() + coinConfig = config["Wallets"][self.cointype] - config["Wallets"][self.cointype]["Type"] = "SPV" - config["Wallets"][self.cointype]["TrustedPeer"] = "127.0.0.1:18444" - config["Wallets"][self.cointype]["FeeAPI"] = "" + del config["Wallets"] + config["Wallets"] = {} + config["Wallets"]["BTC"] = coinConfig + config["Wallets"]["BTC"]["Type"] = "SPV" + config["Wallets"]["BTC"]["TrustedPeer"] = "127.0.0.1:18444" + config["Wallets"]["BTC"]["FeeAPI"] = "" + if self.cointype != "BTC": + config["Wallets"][self.cointype] = coinConfig with open(os.path.join(dir_path, "config"), 'w') as outfile: outfile.write(json.dumps(config, indent=4)) @@ -107,8 +131,22 @@ def wait_for_init_success(process): if "OpenBazaar repo initialized" in str(o): return - def start_node(self, node): - args = [self.binary, "start", "-v", "-d", node["data_dir"], *self.options] + def start_node(self, n, node): + args = [] + if n == 1 and self.v4vendor_binary is not None: + self.vendor_version = "v4" + args = [self.v4vendor_binary, "start", "-v", "-d", node["data_dir"], *self.options] + elif n == 2 and self.v4buyer_binary is not None: + self.buyer_version = "v4" + args = [self.v4buyer_binary, "start", "-v", "-d", node["data_dir"], *self.options] + elif n == 3 and self.v4moderator_binary is not None: + self.moderator_version = "v4" + args = [self.v4moderator_binary, "start", "-v", "-d", node["data_dir"], *self.options] + else: + args = [self.binary, "start", "-v", "-d", node["data_dir"], *self.options] + if self.useTor: + args.append("--tor") + process = subprocess.Popen(args, stdout=PIPE) peerId = self.wait_for_start_success(process, node) node["peerId"] = peerId @@ -128,7 +166,7 @@ def wait_for_start_success(process, node): def start_bitcoind(self): SelectParams('regtest') - dir_path = os.path.join(self.temp_dir, "openbazaar-go", "bitcoin") + dir_path = os.path.join(self.temp_dir, "marketplace-go", "bitcoin") if not os.path.exists(dir_path): os.makedirs(dir_path) btc_conf_file = os.path.join(dir_path, "bitcoin.conf") @@ -142,7 +180,6 @@ def start_bitcoind(self): def init_blockchain(self): self.send_bitcoin_cmd("generate", 1) self.bitcoin_address = self.send_bitcoin_cmd("getnewaddress") - self.send_bitcoin_cmd("generatetoaddress", 1, self.bitcoin_address) self.send_bitcoin_cmd("generate", 435) def wait_for_bitcoind_start(self, process, btc_conf_file): @@ -182,19 +219,27 @@ def main(self, options=["--disablewallet", "--testnet", "--disableexchangerates" description="OpenBazaar Test Framework", usage="python3 test_framework.py [options]" ) - parser.add_argument('-b', '--binary', required=True, help="the openbazaar-go binary") + parser.add_argument('-b', '--binary', help="the openbazaar-go binary") + parser.add_argument('--v4buyer', help="path to a v4 binary if you want to use one") + parser.add_argument('--v4vendor', help="path to a v4 binary if you want to use one") + parser.add_argument('--v4moderator', help="path to a v4 binary if you want to use one") parser.add_argument('-d', '--bitcoind', help="the bitcoind binary") parser.add_argument('-t', '--tempdir', action='store_true', help="temp directory to store the data folders", default="/tmp/") - parser.add_argument('-c', '--cointype', help="cointype to test", action='store_true', default="BTC") + parser.add_argument('-c', '--cointype', help="cointype to test", default="BTC") + parser.add_argument('-T', '--tor', help="use tor in QA testing", action='store_true') args = parser.parse_args(sys.argv[1:]) self.binary = args.binary + self.v4buyer_binary = args.v4buyer + self.v4vendor_binary = args.v4vendor + self.v4moderator_binary = args.v4moderator self.temp_dir = args.tempdir self.bitcoind = args.bitcoind self.cointype = args.cointype + self.useTor = args.tor self.options = options try: - shutil.rmtree(os.path.join(self.temp_dir, "openbazaar-go")) + shutil.rmtree(os.path.join(self.temp_dir, "marketplace-go")) except: pass diff --git a/qa/testdata/bitcoin.conf b/qa/testdata/bitcoin.conf index c80b50b643..29cf690bae 100644 --- a/qa/testdata/bitcoin.conf +++ b/qa/testdata/bitcoin.conf @@ -1,3 +1,3 @@ rpcuser=hal rpcpassword=letmein -rpcport=18443 +rpcport=18443 \ No newline at end of file diff --git a/qa/testdata/v4/completion.json b/qa/testdata/v4/completion.json new file mode 100644 index 0000000000..aee5d5d6f3 --- /dev/null +++ b/qa/testdata/v4/completion.json @@ -0,0 +1,15 @@ +{ + "orderId": "", + "ratings": [ + { + "slug": "", + "overall": 4, + "quality": 5, + "description": 5, + "customerService": 4, + "deliverySpeed": 3, + "review": "I love it!", + "anonymous": true + } + ] +} \ No newline at end of file diff --git a/qa/testdata/v4/digital.json b/qa/testdata/v4/digital.json new file mode 100644 index 0000000000..2b55e948a8 --- /dev/null +++ b/qa/testdata/v4/digital.json @@ -0,0 +1,49 @@ +{ + "slug": "", + "metadata": { + "version": 1, + "contractType": "DIGITAL_GOOD", + "format": "FIXED_PRICE", + "expiry": "2030-08-17T04:52:19.000Z", + "pricingCurrency": "tbtc", + "acceptedCurrencies": ["tbtc", "tbch", "tltc", "tzec"] + }, + "item": { + "title": "Citizenfour", + "description": "A documentarian and a reporter travel to Hong Kong for the first of many meetings with Edward Snowden.", + "processingTime": "1 confirmation", + "price": 12000000, + "tags": [ + "documentary" + ], + "images": [ + { + "tiny": "QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs", + "small": "QmXSEqXLCzpCByJU4wqbJ37TcBEj77FKMUWUP1qLh56847", + "medium": "QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h", + "large": "QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9", + "original": "QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6", + "filename": "citizenfour.jpg" + } + ], + "categories": [ + "movies" + ], + "condition": "New", + "skus": [ + ] + }, + "taxes": [ + { + "taxType": "Sales tax", + "taxRegions": [ + "UNITED_STATES" + ], + "taxShipping": false, + "percentage": 7 + } + ], + "moderators": [], + "termsAndConditions": "NA", + "refundPolicy": "No refuns for you. All sales are final." +} \ No newline at end of file diff --git a/qa/testdata/v4/fulfillment.json b/qa/testdata/v4/fulfillment.json new file mode 100644 index 0000000000..d1495f8316 --- /dev/null +++ b/qa/testdata/v4/fulfillment.json @@ -0,0 +1,10 @@ +{ + "orderId": "", + "slug": "", + "physicalDelivery": [ + { + "shipper": "UPS", + "trackingNumber": "1234" + } + ] +} \ No newline at end of file diff --git a/qa/testdata/v4/fulfillment_crypto.json b/qa/testdata/v4/fulfillment_crypto.json new file mode 100644 index 0000000000..b9a34f6193 --- /dev/null +++ b/qa/testdata/v4/fulfillment_crypto.json @@ -0,0 +1,7 @@ +{ + "orderId": "", + "slug": "", + "cryptocurrencyDelivery": [{ + "transactionID": "crypto_transaction_id" + }] +} \ No newline at end of file diff --git a/qa/testdata/listing.json b/qa/testdata/v4/listing.json similarity index 75% rename from qa/testdata/listing.json rename to qa/testdata/v4/listing.json index 1c022fb912..f1b108c024 100644 --- a/qa/testdata/listing.json +++ b/qa/testdata/v4/listing.json @@ -121,63 +121,63 @@ ] }, "shippingOptions": [ - { - "name": "Domestic Shipping", - "type": "FIXED_PRICE", - "regions": [ - "UNITED_STATES" - ], - "services": [ - { - "name": "Standard", - "price": 6000000, - "estimatedDelivery": "4-6 days" - }, - { - "name": "Express", - "price": 12000000, - "estimatedDelivery": "1-3 days" - } - ] - }, - { - "name": "International Shipping", - "type": "FIXED_PRICE", - "regions": [ - "ALL" - ], - "services": [ - { - "name": "Standard", - "price": 8000000, - "estimatedDelivery": "6-8 days" - }, - { - "name": "Express", - "price": 150000000, - "estimatedDelivery": "2-3 days" - } - ] - } + { + "name": "Domestic Shipping", + "type": "FIXED_PRICE", + "regions": [ + "UNITED_STATES" + ], + "services": [ + { + "name": "Standard", + "price": 6000000, + "estimatedDelivery": "4-6 days" + }, + { + "name": "Express", + "price": 12000000, + "estimatedDelivery": "1-3 days" + } + ] + }, + { + "name": "International Shipping", + "type": "FIXED_PRICE", + "regions": [ + "ALL" + ], + "services": [ + { + "name": "Standard", + "price": 8000000, + "estimatedDelivery": "6-8 days" + }, + { + "name": "Express", + "price": 150000000, + "estimatedDelivery": "2-3 days" + } + ] + } ], "taxes": [ - { - "taxType": "Sales tax", - "taxRegions": [ - "UNITED_STATES" - ], - "taxShipping": true, - "percentage": 7 - } + { + "taxType": "Sales tax", + "taxRegions": [ + "UNITED_STATES" + ], + "taxShipping": true, + "percentage": 7 + } ], "coupons": [ - { - "title": "10% off", - "discountCode": "radio", - "percentDiscount": 10.0 - } + { + "title": "10% off", + "discountCode": "radio", + "percentDiscount": 10.0 + } ], "moderators": [], "termsAndConditions": "NA", "refundPolicy": "No refuns for you. All sales are final." -} +} \ No newline at end of file diff --git a/qa/testdata/v4/listing_crypto.json b/qa/testdata/v4/listing_crypto.json new file mode 100644 index 0000000000..2e6ae12b6e --- /dev/null +++ b/qa/testdata/v4/listing_crypto.json @@ -0,0 +1,33 @@ +{ + "slug": "", + "metadata": { + "version": 1, + "contractType": "CRYPTOCURRENCY", + "format": "MARKET_PRICE", + "expiry": "2030-08-17T04:52:19.000Z", + "coinType": "ETH", + "coinDivisibility": 100000000 + }, + "item": { + "title": "Ether", + "description": "", + "processingTime": "1 to 2 hours", + "price": 0, + "images": [{ + "tiny": "QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs", + "small": "QmXSEqXLCzpCByJU4wqbJ37TcBEj77FKMUWUP1qLh56847", + "medium": "QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h", + "large": "QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9", + "original": "QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6", + "filename": "ether.jpg" + }], + "grams": 0, + "options": [], + "skus": [{ + "quantity": 350000000 + }] + }, + "moderators": [], + "termsAndConditions": "NA", + "refundPolicy": "No refunds for you. All sales are final." +} \ No newline at end of file diff --git a/qa/testdata/v4/moderation.json b/qa/testdata/v4/moderation.json new file mode 100644 index 0000000000..cdb283ecd3 --- /dev/null +++ b/qa/testdata/v4/moderation.json @@ -0,0 +1,9 @@ +{ + "description": "I am a moderator!!!", + "termsAndConditions": "I moderate stuff", + "languages": ["english"], + "fee": { + "feeType": "PERCENTAGE", + "percentage": 10.0 + } +} \ No newline at end of file diff --git a/qa/testdata/v4/order_crypto.json b/qa/testdata/v4/order_crypto.json new file mode 100644 index 0000000000..4b9d2c36bb --- /dev/null +++ b/qa/testdata/v4/order_crypto.json @@ -0,0 +1,10 @@ + +{ + "moderator": "", + "items": [{ + "listingHash": "", + "quantity": 100000000, + "paymentAddress": "crypto_payment_address", + "memo": "thanks!" + }] +} \ No newline at end of file diff --git a/qa/testdata/v4/order_digital.json b/qa/testdata/v4/order_digital.json new file mode 100644 index 0000000000..03da37d4fe --- /dev/null +++ b/qa/testdata/v4/order_digital.json @@ -0,0 +1,10 @@ +{ + "moderator": "", + "items": [ + { + "listingHash": "", + "quantity": 1, + "memo": "thanks!" + } + ] +} \ No newline at end of file diff --git a/qa/testdata/v4/order_direct.json b/qa/testdata/v4/order_direct.json new file mode 100644 index 0000000000..e0580dacdc --- /dev/null +++ b/qa/testdata/v4/order_direct.json @@ -0,0 +1,33 @@ +{ + "shipTo": "Seymour Butts", + "address": "31 Spooner Street", + "city": "Quahog", + "state": "RI", + "postalCode": "00093", + "countryCode": "UNITED_STATES", + "addressNotes": "", + "moderator": "", + "paymentCoin": "", + "items": [ + { + "listingHash": "", + "quantity": 1, + "options": [ + { + "name": "Color", + "value": "Red" + }, + { + "name": "Size", + "value": "Large" + } + ], + "shipping": { + "name": "Domestic Shipping", + "service": "Standard" + }, + "memo": "thanks!", + "coupons": ["discount"] + } + ] +} \ No newline at end of file diff --git a/qa/testdata/v4/order_direct_too_much_quantity.json b/qa/testdata/v4/order_direct_too_much_quantity.json new file mode 100644 index 0000000000..50f41ade34 --- /dev/null +++ b/qa/testdata/v4/order_direct_too_much_quantity.json @@ -0,0 +1,29 @@ +{ + "shipTo": "Satoshi Nakamoto", + "address": "31 Spooner Street", + "city": "Quahog", + "state": "RI", + "postalCode": "00093", + "countryCode": "UNITED_STATES", + "addressNotes": "", + "moderator": "", + "items": [{ + "listingHash": "", + "quantity": 999999999999, + "options": [{ + "name": "Color", + "value": "Red" + }, + { + "name": "Size", + "value": "Large" + } + ], + "shipping": { + "name": "Domestic Shipping", + "service": "Standard" + }, + "memo": "thanks!", + "coupons": ["discount"] + }] +} \ No newline at end of file diff --git a/qa/testdata/profile.json b/qa/testdata/v4/profile.json similarity index 100% rename from qa/testdata/profile.json rename to qa/testdata/v4/profile.json diff --git a/qa/testdata/completion.json b/qa/testdata/v5/completion.json similarity index 100% rename from qa/testdata/completion.json rename to qa/testdata/v5/completion.json diff --git a/qa/testdata/v5/digital.json b/qa/testdata/v5/digital.json new file mode 100644 index 0000000000..e47383533e --- /dev/null +++ b/qa/testdata/v5/digital.json @@ -0,0 +1,51 @@ +{ + "slug": "", + "metadata": { + "version": 5, + "contractType": "DIGITAL_GOOD", + "format": "FIXED_PRICE", + "expiry": "2030-08-17T04:52:19.000Z", + "acceptedCurrencies": ["TBTC", "TBCH", "TLTC", "TZEC"] + }, + "item": { + "title": "Citizenfour", + "description": "A documentarian and a reporter travel to Hong Kong for the first of many meetings with Edward Snowden.", + "processingTime": "1 confirmation", + "bigPrice": "12000000", + "priceCurrency": { + "code": "TBTC", + "divisibility": 8 + }, + "tags": [ + "documentary" + ], + "images": [ + { + "tiny": "QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs", + "small": "QmXSEqXLCzpCByJU4wqbJ37TcBEj77FKMUWUP1qLh56847", + "medium": "QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h", + "large": "QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9", + "original": "QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6", + "filename": "citizenfour.jpg" + } + ], + "categories": [ + "movies" + ], + "condition": "New", + "skus": [] + }, + "taxes": [ + { + "taxType": "Sales tax", + "taxRegions": [ + "UNITED_STATES" + ], + "taxShipping": false, + "percentage": 7 + } + ], + "moderators": [], + "termsAndConditions": "NA", + "refundPolicy": "No refuns for you. All sales are final." +} diff --git a/qa/testdata/digital.json b/qa/testdata/v5/eth_digital.json similarity index 75% rename from qa/testdata/digital.json rename to qa/testdata/v5/eth_digital.json index 8f539ec431..c75bc3d47f 100644 --- a/qa/testdata/digital.json +++ b/qa/testdata/v5/eth_digital.json @@ -1,18 +1,23 @@ { "slug": "", "metadata": { - "version": 1, + "version": 5, "contractType": "DIGITAL_GOOD", "format": "FIXED_PRICE", "expiry": "2030-08-17T04:52:19.000Z", - "pricingCurrency": "tbtc", - "acceptedCurrencies": ["tbtc", "tbch", "tltc", "tzec"] + "acceptedCurrencies": ["TETH"] }, "item": { "title": "Citizenfour", "description": "A documentarian and a reporter travel to Hong Kong for the first of many meetings with Edward Snowden.", "processingTime": "1 confirmation", - "price": 12000000, + "bigPrice": "12000000", + "priceCurrency": { + "code": "TETH", + "divisibility": 18, + "name": "Eth", + "currencyType": "crypto" + }, "tags": [ "documentary" ], @@ -34,14 +39,14 @@ ] }, "taxes": [ - { - "taxType": "Sales tax", - "taxRegions": [ - "UNITED_STATES" - ], - "taxShipping": false, - "percentage": 7 - } + { + "taxType": "Sales tax", + "taxRegions": [ + "UNITED_STATES" + ], + "taxShipping": false, + "percentage": 7 + } ], "moderators": [], "termsAndConditions": "NA", diff --git a/qa/testdata/v5/eth_listing.json b/qa/testdata/v5/eth_listing.json new file mode 100644 index 0000000000..c731ae2dca --- /dev/null +++ b/qa/testdata/v5/eth_listing.json @@ -0,0 +1,190 @@ +{ + "slug": "", + "metadata": { + "version": 5, + "contractType": "PHYSICAL_GOOD", + "format": "FIXED_PRICE", + "expiry": "2030-08-17T04:52:19.000Z", + "acceptedCurrencies": ["TETH"], + "escrowTimeoutHours": 1080 + }, + "item": { + "title": "Ron Swanson Tshirt", + "description": "Kick ass ron swanson tshirt in yellow", + "processingTime": "1 to 2 Business days", + "priceCurrency": { + "code": "TETH", + "divisibility": 18, + "name": "A", + "currencyType": "A" + }, + "bigPrice": "4500000000000000", + "tags": [ + "tshirts", + "clothing", + "ron swanson" + ], + "images": [ + { + "tiny": "QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs", + "small": "QmXSEqXLCzpCByJU4wqbJ37TcBEj77FKMUWUP1qLh56847", + "medium": "QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h", + "large": "QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9", + "original": "QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6", + "filename": "swanson.jpg" + } + ], + "categories": [ + "clothing" + ], + "grams": 28, + "condition": "New", + "options": [ + { + "name": "Size", + "description": "What size do you want your shirt?", + "variants": [ + { + "name": "Small", + "image": { + "tiny": "QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs", + "small": "QmXSEqXLCzpCByJU4wqbJ37TcBEj77FKMUWUP1qLh56847", + "medium": "QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h", + "large": "QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9", + "original": "QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6", + "filename": "swanson.jpg" + } + }, + { + "name": "Medium" + }, + { + "name": "Large" + }, + { + "name": "XL" + } + ] + }, + { + "name": "Color", + "description": "What color do you want your shirt?", + "variants": [ + { + "name": "Red" + }, + { + "name": "Yellow" + } + ] + } + ], + "skus": [ + { + "variantCombo": [0,0], + "productID": "932-33-2945", + "bigSurcharge": "0", + "bigQuantity": "12" + }, + { + "variantCombo": [0,1], + "bigSurcharge": "0", + "bigQuantity": "100" + }, + { + "variantCombo": [1,0], + "productID": "123-99-1111", + "bigSurcharge": "0", + "bigQuantity": "44" + }, + { + "variantCombo": [1,1], + "productID": "229-00-3333", + "bigSurcharge": "0", + "bigQuantity": "19" + }, + { + "variantCombo": [2,0], + "productID": "987-54-3456", + "bigSurcharge": "0", + "bigQuantity": "7" + }, + { + "variantCombo": [2,1], + "bigSurcharge": "0", + "bigQuantity": "3" + }, + { + "variantCombo": [3,0], + "bigSurcharge": "1000", + "bigQuantity": "16" + }, + { + "variantCombo": [3,1], + "bigSurcharge": "1000", + "bigQuantity": "12" + } + ] + }, + "shippingOptions": [ + { + "name": "Domestic Shipping", + "type": "FIXED_PRICE", + "regions": [ + "UNITED_STATES" + ], + "services": [ + { + "name": "Standard", + "bigPrice": "600000000", + "estimatedDelivery": "4-6 days" + }, + { + "name": "Express", + "bigPrice": "1200000000", + "estimatedDelivery": "1-3 days" + } + ] + }, + { + "name": "International Shipping", + "type": "FIXED_PRICE", + "regions": [ + "ALL" + ], + "services": [ + { + "name": "Standard", + "bigPrice": "800000000", + "estimatedDelivery": "6-8 days", + "bigAdditionalItemPrice": "100000000" + }, + { + "name": "Express", + "bigPrice": "15000000000", + "estimatedDelivery": "2-3 days" + } + ] + } + ], + "taxes": [ + { + "taxType": "Sales tax", + "taxRegions": [ + "UNITED_STATES" + ], + "taxShipping": true, + "percentage": 7 + } + ], + "coupons": [ + { + "title": "10% off", + "discountCode": "radio", + "percentDiscount": 10.0 + } + ], + "moderators": [], + "termsAndConditions": "NA", + "refundPolicy": "No refuns for you. All sales are final." +} diff --git a/qa/testdata/listing_crypto.json b/qa/testdata/v5/eth_listing_crypto.json similarity index 78% rename from qa/testdata/listing_crypto.json rename to qa/testdata/v5/eth_listing_crypto.json index d455c62309..c0cf9292fa 100644 --- a/qa/testdata/listing_crypto.json +++ b/qa/testdata/v5/eth_listing_crypto.json @@ -1,18 +1,20 @@ { "slug": "", "metadata": { - "version": 1, + "version": 5, "contractType": "CRYPTOCURRENCY", "format": "MARKET_PRICE", "expiry": "2030-08-17T04:52:19.000Z", - "coinType": "ETH", - "coinDivisibility": 100000000 + "acceptedCurrencies": ["TBTC"], + "escrowTimeoutHours": 1080, + "coinType": "TETH", + "coinDivisibility": 18 }, "item": { "title": "Ether", "description": "", "processingTime": "1 to 2 hours", - "price": 0, + "price": "0", "images": [{ "tiny": "QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs", "small": "QmXSEqXLCzpCByJU4wqbJ37TcBEj77FKMUWUP1qLh56847", @@ -23,11 +25,9 @@ }], "grams": 0, "options": [], - "skus": [{ - "quantity": 350000000 - }] + "skus": [{"bigQuantity":"350000000000000000"}] }, "moderators": [], "termsAndConditions": "NA", "refundPolicy": "No refunds for you. All sales are final." -} \ No newline at end of file +} diff --git a/qa/testdata/fulfillment.json b/qa/testdata/v5/fulfillment.json similarity index 100% rename from qa/testdata/fulfillment.json rename to qa/testdata/v5/fulfillment.json diff --git a/qa/testdata/fulfillment_crypto.json b/qa/testdata/v5/fulfillment_crypto.json similarity index 100% rename from qa/testdata/fulfillment_crypto.json rename to qa/testdata/v5/fulfillment_crypto.json diff --git a/qa/testdata/v5/listing.json b/qa/testdata/v5/listing.json new file mode 100644 index 0000000000..41eef9b9f5 --- /dev/null +++ b/qa/testdata/v5/listing.json @@ -0,0 +1,189 @@ +{ + "slug": "", + "metadata": { + "version": 5, + "contractType": "PHYSICAL_GOOD", + "format": "FIXED_PRICE", + "expiry": "2030-08-17T04:52:19.000Z", + "acceptedCurrencies": ["TBTC"], + "escrowTimeoutHours": 1 + }, + "item": { + "title": "Ron Swanson Tshirt", + "description": "Kick ass ron swanson tshirt in yellow", + "processingTime": "1 to 2 Business days", + "priceCurrency": { + "code": "TBTC", + "divisibility": 8, + "name": "A", + "currencyType": "A" + }, + "bigPrice": "12000000", + "tags": [ + "tshirts", + "clothing", + "ron swanson" + ], + "images": [ + { + "tiny": "QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs", + "small": "QmXSEqXLCzpCByJU4wqbJ37TcBEj77FKMUWUP1qLh56847", + "medium": "QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h", + "large": "QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9", + "original": "QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6", + "filename": "swanson.jpg" + } + ], + "categories": [ + "clothing" + ], + "grams": 28, + "condition": "New", + "options": [ + { + "name": "Size", + "description": "What size do you want your shirt?", + "variants": [ + { + "name": "Small", + "image": { + "tiny": "QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs", + "small": "QmXSEqXLCzpCByJU4wqbJ37TcBEj77FKMUWUP1qLh56847", + "medium": "QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h", + "large": "QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9", + "original": "QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6", + "filename": "swanson.jpg" + } + }, + { + "name": "Medium" + }, + { + "name": "Large" + }, + { + "name": "XL" + } + ] + }, + { + "name": "Color", + "description": "What color do you want your shirt?", + "variants": [ + { + "name": "Red" + }, + { + "name": "Yellow" + } + ] + } + ], + "skus": [ + { + "variantCombo": [0,0], + "productID": "932-33-2945", + "bigSurcharge": "0", + "bigQuantity": "12" + }, + { + "variantCombo": [0,1], + "bigSurcharge": "0", + "bigQuantity": "100" + }, + { + "variantCombo": [1,0], + "productID": "123-99-1111", + "bigSurcharge": "0", + "bigQuantity": "44" + }, + { + "variantCombo": [1,1], + "productID": "229-00-3333", + "bigSurcharge": "0", + "bigQuantity": "19" + }, + { + "variantCombo": [2,0], + "productID": "987-54-3456", + "bigSurcharge": "0", + "bigQuantity": "7" + }, + { + "variantCombo": [2,1], + "bigSurcharge": "0", + "bigQuantity": "3" + }, + { + "variantCombo": [3,0], + "bigSurcharge": "1000", + "bigQuantity": "16" + }, + { + "variantCombo": [3,1], + "bigSurcharge": "1000", + "bigQuantity": "12" + } + ] + }, + "shippingOptions": [ + { + "name": "Domestic Shipping", + "type": "FIXED_PRICE", + "regions": [ + "UNITED_STATES" + ], + "services": [ + { + "name": "Standard", + "bigPrice": "6000000", + "estimatedDelivery": "4-6 days" + }, + { + "name": "Express", + "bigPrice": "12000000", + "estimatedDelivery": "1-3 days" + } + ] + }, + { + "name": "International Shipping", + "type": "FIXED_PRICE", + "regions": [ + "ALL" + ], + "services": [ + { + "name": "Standard", + "bigPrice": "8000000", + "estimatedDelivery": "6-8 days" + }, + { + "name": "Express", + "bigPrice": "150000000", + "estimatedDelivery": "2-3 days" + } + ] + } + ], + "taxes": [ + { + "taxType": "Sales tax", + "taxRegions": [ + "UNITED_STATES" + ], + "taxShipping": true, + "percentage": 7 + } + ], + "coupons": [ + { + "title": "10% off", + "discountCode": "radio", + "percentDiscount": 10.0 + } + ], + "moderators": [], + "termsAndConditions": "NA", + "refundPolicy": "No refuns for you. All sales are final." +} diff --git a/qa/testdata/v5/listing_crypto.json b/qa/testdata/v5/listing_crypto.json new file mode 100644 index 0000000000..1c23376509 --- /dev/null +++ b/qa/testdata/v5/listing_crypto.json @@ -0,0 +1,36 @@ +{ + "slug": "", + "metadata": { + "version": 5, + "contractType": "CRYPTOCURRENCY", + "format": "MARKET_PRICE", + "expiry": "2030-08-17T04:52:19.000Z", + "acceptedCurrencies": ["TBTC"], + "escrowTimeoutHours": 1080, + "coinType": "TETH", + "coinDivisibility": 18 + }, + "item": { + "title": "Ether", + "description": "", + "processingTime": "1 to 2 hours", + "price": "0", + "images": [{ + "tiny": "QmUAuYuiafnJRZxDDX7MuruMNsicYNuyub5vUeAcupUBNs", + "small": "QmXSEqXLCzpCByJU4wqbJ37TcBEj77FKMUWUP1qLh56847", + "medium": "QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h", + "large": "QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9", + "original": "QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6", + "filename": "ether.jpg" + }], + "grams": 0, + "options": [], + "skus": [{ + "bigQuantity": "350000000000000000", + "bigSurcharge": "0" + }] + }, + "moderators": [], + "termsAndConditions": "NA", + "refundPolicy": "No refunds for you. All sales are final." +} diff --git a/qa/testdata/moderation.json b/qa/testdata/v5/moderation.json similarity index 100% rename from qa/testdata/moderation.json rename to qa/testdata/v5/moderation.json diff --git a/qa/testdata/order_crypto.json b/qa/testdata/v5/order_crypto.json similarity index 77% rename from qa/testdata/order_crypto.json rename to qa/testdata/v5/order_crypto.json index 83f4d75d29..6302140a44 100644 --- a/qa/testdata/order_crypto.json +++ b/qa/testdata/v5/order_crypto.json @@ -2,8 +2,8 @@ "moderator": "", "items": [{ "listingHash": "", - "quantity": 100000000, + "bigQuantity": "1000000000000000", "paymentAddress": "crypto_payment_address", "memo": "thanks!" }] -} \ No newline at end of file +} diff --git a/qa/testdata/order_digital.json b/qa/testdata/v5/order_digital.json similarity index 79% rename from qa/testdata/order_digital.json rename to qa/testdata/v5/order_digital.json index ab79b08399..d4a4a73c48 100644 --- a/qa/testdata/order_digital.json +++ b/qa/testdata/v5/order_digital.json @@ -3,7 +3,7 @@ "items": [ { "listingHash": "", - "quantity": 1, + "bigQuantity": "1", "memo": "thanks!" } ] diff --git a/qa/testdata/order_direct.json b/qa/testdata/v5/order_direct.json similarity index 95% rename from qa/testdata/order_direct.json rename to qa/testdata/v5/order_direct.json index 932c165f88..3ebf5c87bc 100644 --- a/qa/testdata/order_direct.json +++ b/qa/testdata/v5/order_direct.json @@ -11,7 +11,7 @@ "items": [ { "listingHash": "", - "quantity": 1, + "bigQuantity": "1", "options": [ { "name": "Color", diff --git a/qa/testdata/order_direct_too_much_quantity.json b/qa/testdata/v5/order_direct_too_much_quantity.json similarity index 94% rename from qa/testdata/order_direct_too_much_quantity.json rename to qa/testdata/v5/order_direct_too_much_quantity.json index fdb98efb4b..d1934286ae 100644 --- a/qa/testdata/order_direct_too_much_quantity.json +++ b/qa/testdata/v5/order_direct_too_much_quantity.json @@ -9,7 +9,7 @@ "moderator": "", "items": [{ "listingHash": "", - "quantity": 999999999999, + "bigQuantity": "500", "options": [{ "name": "Color", "value": "Red" diff --git a/qa/testdata/v5/profile.json b/qa/testdata/v5/profile.json new file mode 100644 index 0000000000..377243c156 --- /dev/null +++ b/qa/testdata/v5/profile.json @@ -0,0 +1,4 @@ +{ + "name": "alice", + "vendor": true +} \ No newline at end of file diff --git a/qa/upload_listing.py b/qa/upload_listing.py index 5cf22171f4..5302e3d859 100644 --- a/qa/upload_listing.py +++ b/qa/upload_listing.py @@ -8,30 +8,35 @@ class UploadListingTest(OpenBazaarTestFramework): def __init__(self): super().__init__() - self.num_nodes = 1 + self.num_nodes = 2 def setup_network(self): self.setup_nodes() def run_test(self): - with open('testdata/listing.json') as listing_file: + with open('testdata/'+ self.vendor_version +'/listing.json') as listing_file: listing_json = json.load(listing_file, object_pairs_hook=OrderedDict) - listing_json["metadata"]["pricingCurrency"] = "t" + self.cointype - api_url = self.nodes[0]["gateway_url"] + "ob/listing" + if self.vendor_version == "v4": + listing_json["metadata"]["priceCurrency"] = "t" + self.cointype + else: + listing_json["item"]["priceCurrency"]["code"] = "t" + self.cointype + listing_json["item"]["priceCurrency"]["divisibility"] = 8 + listing_json["metadata"]["acceptedCurrencies"] = ["t" + self.cointype] + api_url = self.nodes[1]["gateway_url"] + "ob/listing" r = requests.post(api_url, data=json.dumps(listing_json, indent=4)) if r.status_code == 404: raise TestFailure("UploadListingTest - FAIL: Listing post endpoint not found") elif r.status_code != 200: resp = json.loads(r.text) raise TestFailure("UploadListingTest - FAIL: Listing POST failed. Reason: %s", resp["reason"]) - api_url = self.nodes[0]["gateway_url"] + "ob/inventory" + api_url = self.nodes[1]["gateway_url"] + "ob/inventory" r = requests.get(api_url) if r.status_code == 200: resp = json.loads(r.text) inv = resp["ron-swanson-tshirt"] if inv == None: raise TestFailure("UploadListingTest - FAIL: Did not return inventory for listing") - if inv["inventory"] != 213: + if int(inv["inventory"]) != 213: raise TestFailure("UploadListingTest - FAIL: Returned incorrect amount of inventory: %d", inv["inventory"]) elif r.status_code == 404: raise TestFailure("UploadListingTest - FAIL: Listing post endpoint not found") diff --git a/repo/api_time.go b/repo/api_time.go new file mode 100644 index 0000000000..da8d1b2345 --- /dev/null +++ b/repo/api_time.go @@ -0,0 +1,41 @@ +package repo + +import ( + "errors" + "fmt" + "time" +) + +var ErrUnknownAPITimeFormat = errors.New("unknown api time format") + +const JSONAPITimeFormat = `"2006-01-02T15:04:05.999999999Z07:00"` // time.RFC3339Nano + +type APITime struct { + time.Time +} + +// NewAPITime returns a pointer to a new APITime instance +func NewAPITime(t time.Time) *APITime { + var val = APITime{t} + return &val +} + +func (t APITime) MarshalJSON() ([]byte, error) { + return []byte(t.Time.Format(JSONAPITimeFormat)), nil +} + +func (t *APITime) UnmarshalJSON(b []byte) error { + if value, err := time.Parse(q(time.RFC3339), string(b)); err == nil { + *t = APITime{value} + return nil + } + return ErrUnknownAPITimeFormat +} + +func q(format string) string { + return fmt.Sprintf(`"%s"`, format) +} + +func (t APITime) String() string { + return t.Time.String() +} diff --git a/repo/api_time_test.go b/repo/api_time_test.go new file mode 100644 index 0000000000..0335fea270 --- /dev/null +++ b/repo/api_time_test.go @@ -0,0 +1,78 @@ +package repo_test + +import ( + "bytes" + "encoding/json" + "fmt" + "testing" + "time" + + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" +) + +func TestAPITimeMarshalJSON(t *testing.T) { + var ( + when = time.Now() + subject = factory.NewAPITime(when) + expected = []byte(when.Format(fmt.Sprintf(`"%s"`, time.RFC3339Nano))) + ) + actual, err := json.Marshal(&subject) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(actual, expected) { + t.Errorf("expected (%s) to equal (%s), but did not", actual, expected) + } +} + +func TestAPITimeUnmarshalJSONSupportsRFC3339(t *testing.T) { + var ( + when = time.Now().Truncate(time.Second) + format = time.RFC3339 + marshaledExample = []byte(fmt.Sprintf(`"%s"`, when.Format(format))) + + actual repo.APITime + ) + if err := json.Unmarshal(marshaledExample, &actual); err != nil { + t.Logf("output: %s", string(marshaledExample)) + t.Fatal(err) + } + if !when.Equal(actual.Time) { + t.Errorf("expected (%s) to equal (%s), but did not when using format (%s)", actual.Time, when, format) + } +} + +func TestAPITimeUnmarshalJSONSupportsRFC3339Nano(t *testing.T) { + var ( + when = time.Now().Add(1 * time.Nanosecond) + format = time.RFC3339Nano + marshaledExample = []byte(fmt.Sprintf(`"%s"`, when.Format(format))) + + actual repo.APITime + ) + if err := json.Unmarshal(marshaledExample, &actual); err != nil { + t.Logf("output: %s", string(marshaledExample)) + t.Fatal(err) + } + if !when.Equal(actual.Time) { + t.Errorf("expected (%s) to equal (%s), but did not when using format (%s)", actual.Time, when, format) + } +} + +func TestAPITimeMarshalIsReciprocal(t *testing.T) { + var when = repo.NewAPITime(time.Now()) + subjectBytes, err := json.Marshal(&when) + if err != nil { + t.Fatal(err) + } + + var actual repo.APITime + if err := json.Unmarshal(subjectBytes, &actual); err != nil { + t.Fatal(err) + } + + if !when.Equal(actual.Time) { + t.Errorf("expected (%s) to equal (%s), but did not", actual, when) + } +} diff --git a/repo/buyer_order.go b/repo/buyer_order.go new file mode 100644 index 0000000000..01637f8388 --- /dev/null +++ b/repo/buyer_order.go @@ -0,0 +1,56 @@ +package repo + +import ( + "math/big" + + "github.com/golang/protobuf/proto" + "github.com/phoreproject/pm-go/pb" +) + +// ToV5Order scans through the order looking for any deprecated fields and turns them into their v5 counterpart. +func ToV5Order(order *pb.Order, lookupFunc func(currencyCode string) (CurrencyDefinition, error)) (*pb.Order, error) { + if lookupFunc == nil { + lookupFunc = AllCurrencies().Lookup + } + newOrder := proto.Clone(order).(*pb.Order) + + if order.RefundFee != 0 && order.BigRefundFee == "" { + newOrder.BigRefundFee = big.NewInt(int64(order.RefundFee)).String() + newOrder.RefundFee = 0 + } + + for i, item := range order.Items { + if item.Quantity != 0 && item.BigQuantity == "" { + newOrder.Items[i].BigQuantity = big.NewInt(int64(item.Quantity)).String() + newOrder.Items[i].Quantity = 0 + } + + if item.Quantity64 != 0 && item.BigQuantity == "" { + newOrder.Items[i].BigQuantity = big.NewInt(int64(item.Quantity64)).String() + newOrder.Items[i].Quantity64 = 0 + } + } + + if order.Payment.Amount != 0 && order.Payment.BigAmount == "" { + newOrder.Payment.BigAmount = big.NewInt(int64(order.Payment.Amount)).String() + newOrder.Payment.Amount = 0 + } + + if order.Payment.AmountCurrency == nil && order.Payment.Coin == "" { + order.Payment.Coin = "BTC" + } + + if order.Payment.Coin != "" && order.Payment.AmountCurrency == nil { + def, err := lookupFunc(order.Payment.Coin) + if err != nil { + return nil, err + } + newOrder.Payment.AmountCurrency = &pb.CurrencyDefinition{ + Code: def.Code.String(), + Divisibility: uint32(def.Divisibility), + } + newOrder.Payment.Coin = "" + } + + return newOrder, nil +} diff --git a/repo/buyer_order_test.go b/repo/buyer_order_test.go new file mode 100644 index 0000000000..3188fc86f8 --- /dev/null +++ b/repo/buyer_order_test.go @@ -0,0 +1,86 @@ +package repo + +import ( + "testing" + + "github.com/OpenBazaar/jsonpb" + "github.com/phoreproject/pm-go/pb" +) + +func TestToV5Order(t *testing.T) { + m := jsonpb.Marshaler{ + Indent: "", + } + + tests := []struct { + name string + oldFormatOrder *pb.Order + expected string + }{ + { + name: "refund fee test", + oldFormatOrder: &pb.Order{ + RefundFee: 1000, + Payment: &pb.Order_Payment{}, + }, + expected: `{"payment":{"method":"ADDRESS_REQUEST","amountCurrency":{"code":"BTC","divisibility":8}},"bigRefundFee":"1000"}`, + }, + { + name: "item quantity test", + oldFormatOrder: &pb.Order{ + Items: []*pb.Order_Item{ + { + Quantity: 19, + }, + }, + Payment: &pb.Order_Payment{}, + }, + expected: `{"items":[{"bigQuantity":"19"}],"payment":{"method":"ADDRESS_REQUEST","amountCurrency":{"code":"BTC","divisibility":8}}}`, + }, + { + name: "item quantity64 test", + oldFormatOrder: &pb.Order{ + Items: []*pb.Order_Item{ + { + Quantity64: 19, + }, + }, + Payment: &pb.Order_Payment{}, + }, + expected: `{"items":[{"bigQuantity":"19"}],"payment":{"method":"ADDRESS_REQUEST","amountCurrency":{"code":"BTC","divisibility":8}}}`, + }, + { + name: "payment amount test", + oldFormatOrder: &pb.Order{ + Payment: &pb.Order_Payment{ + Amount: 2000, + }, + }, + expected: `{"payment":{"method":"ADDRESS_REQUEST","bigAmount":"2000","amountCurrency":{"code":"BTC","divisibility":8}}}`, + }, + { + name: "payment amount currency", + oldFormatOrder: &pb.Order{ + Payment: &pb.Order_Payment{ + Coin: "BTC", + }, + }, + expected: `{"payment":{"method":"ADDRESS_REQUEST","amountCurrency":{"code":"BTC","divisibility":8}}}`, + }, + } + + for _, test := range tests { + order, err := ToV5Order(test.oldFormatOrder, MainnetCurrencies().Lookup) + if err != nil { + t.Errorf("Test %s conversion failed: %s", test.name, err) + } + + out, err := m.MarshalToString(order) + if err != nil { + t.Errorf("Test %s marshalling failed: %s", test.name, err) + } + if out != test.expected { + t.Errorf("Test %s incorrect output: Expected %s, got %s", test.name, test.expected, out) + } + } +} diff --git a/repo/chat_message.go b/repo/chat_message.go new file mode 100644 index 0000000000..c9d57c2eb4 --- /dev/null +++ b/repo/chat_message.go @@ -0,0 +1,25 @@ +package repo + +type ChatMessage struct { + MessageId string `json:"messageId"` + PeerId string `json:"peerId"` + Subject string `json:"subject"` + Message string `json:"message"` + Read bool `json:"read"` + Outgoing bool `json:"outgoing"` + Timestamp *APITime `json:"timestamp"` +} + +type ChatConversation struct { + PeerId string `json:"peerId"` + Unread int `json:"unread"` + Last string `json:"lastMessage"` + Timestamp *APITime `json:"timestamp"` + Outgoing bool `json:"outgoing"` +} + +type GroupChatMessage struct { + PeerIds []string `json:"peerIds"` + Subject string `json:"subject"` + Message string `json:"message"` +} diff --git a/repo/checkout.go b/repo/checkout.go new file mode 100644 index 0000000000..b1d29473ff --- /dev/null +++ b/repo/checkout.go @@ -0,0 +1,22 @@ +package repo + +type CheckoutVariant struct { + Name string `json:"name"` + Value string `json:"value"` + Price string `json:"price"` +} + +type CheckoutCurrency struct { + Code string `json:"code"` + Divisibility int `json:"divisibility"` +} + +type CheckoutBreakdown struct { + BasePrice string `json:"basePrice"` + Coupon string `json:"coupon"` + OptionSurcharge string `json:"optionSurcharge"` + Quantity string `json:"quantity"` + ShippingPrice string `json:"shippingPrice"` + Tax string `json:"tax"` + TotalPrice string `json:"totalPrice"` +} diff --git a/repo/currency.go b/repo/currency.go index 1d0912107a..64d0e31f7c 100644 --- a/repo/currency.go +++ b/repo/currency.go @@ -1,11 +1,13 @@ package repo import ( + "encoding/json" "errors" "fmt" - "math" "math/big" "strconv" + + "github.com/phoreproject/pm-go/pb" ) const ( @@ -14,115 +16,321 @@ const ( ) var ( - ErrCurrencyValueInsufficientPrecision = errors.New("unable to accurately represent value as int64") - ErrCurrencyValueNegativeRate = errors.New("conversion rate must be greater than zero") - ErrCurrencyValueAmountInvalid = errors.New("invalid amount") - ErrCurrencyValueDefinitionInvalid = errors.New("invalid currency definition") + ErrCurrencyValueInsufficientPrecision = errors.New("unable to accurately represent value as int64") + ErrCurrencyValueNegativeRate = errors.New("conversion rate must be greater than zero") + ErrCurrencyValueAmountInvalid = errors.New("invalid amount") + ErrCurrencyValueDefinitionInvalid = errors.New("invalid currency definition") + ErrCurrencyValueInvalidCmpDifferentCurrencies = errors.New("unable to compare two different currencies") ) // CurrencyValue represents the amount and variety of currency type CurrencyValue struct { Amount *big.Int - Currency *CurrencyDefinition + Currency CurrencyDefinition +} + +func (c *CurrencyValue) MarshalJSON() ([]byte, error) { + var value = struct { + Amount string `json:"amount"` + Currency CurrencyDefinition `json:"currency"` + }{ + Amount: "0", + Currency: c.Currency, + } + if c.Amount != nil { + value.Amount = c.Amount.String() + } + + return json.Marshal(value) + +} + +func (c *CurrencyValue) UnmarshalJSON(b []byte) error { + var value struct { + Amount string `json:"amount"` + Currency CurrencyDefinition `json:"currency"` + } + err := json.Unmarshal(b, &value) + if err != nil { + return err + } + amt, ok := new(big.Int).SetString(value.Amount, 10) + if !ok { + return fmt.Errorf("invalid amount (%s)", value.Amount) + } + + c.Amount = amt + c.Currency = value.Currency + return err +} + +// NewCurrencyValueWithLookup accepts a string value as a base10 integer +// and uses the currency code to lookup the CurrencyDefinition +func NewCurrencyValueWithLookup(amount, currencyCode string) (*CurrencyValue, error) { + def, err := AllCurrencies().Lookup(currencyCode) + if err != nil { + return nil, err + } + if amount == "" { + return NewCurrencyValue("0", def) + } + return NewCurrencyValue(amount, def) +} + +// NewCurrencyValueFromProtobuf consumes the string and pb.CurrencyDefinition +// objects from parsed Listings and converts them into CurrencyValue objects +func NewCurrencyValueFromProtobuf(amount string, currency *pb.CurrencyDefinition) (*CurrencyValue, error) { + if currency == nil { + return nil, ErrCurrencyDefinitionUndefined + } + value, err := NewCurrencyValueWithLookup(amount, currency.Code) + if err != nil { + return nil, err + } + value.Currency.Divisibility = uint(currency.Divisibility) + return value, nil } // NewCurrencyValueFromInt is a convenience function which converts an int64 // into a string and passes the arguments to NewCurrencyValue -func NewCurrencyValueFromInt(amount int64, currency *CurrencyDefinition) (*CurrencyValue, error) { +func NewCurrencyValueFromInt(amount int64, currency CurrencyDefinition) (*CurrencyValue, error) { return NewCurrencyValue(strconv.FormatInt(amount, 10), currency) } // NewCurrencyValueFromUint is a convenience function which converts an int64 // into a string and passes the arguments to NewCurrencyValue -func NewCurrencyValueFromUint(amount uint64, currency *CurrencyDefinition) (*CurrencyValue, error) { +func NewCurrencyValueFromUint(amount uint64, currency CurrencyDefinition) (*CurrencyValue, error) { return NewCurrencyValue(strconv.FormatUint(amount, 10), currency) } +// NewCurrencyValueFromBigInt is a convenience function which converts a big.Int +// and CurrencyDefinition into a new CurrencyValue +func NewCurrencyValueFromBigInt(amt *big.Int, def CurrencyDefinition) *CurrencyValue { + return &CurrencyValue{ + Amount: new(big.Int).Set(amt), + Currency: def, + } +} + // NewCurrencyValue accepts string amounts and currency codes, and creates // a valid CurrencyValue -func NewCurrencyValue(amount string, currency *CurrencyDefinition) (*CurrencyValue, error) { - var ( - i = new(big.Int) - ok bool - ) - if _, ok = i.SetString(amount, 0); !ok { +func NewCurrencyValue(amount string, currency CurrencyDefinition) (*CurrencyValue, error) { + var i, ok = new(big.Int).SetString(amount, 10) + if !ok { return nil, ErrCurrencyValueAmountInvalid } return &CurrencyValue{Amount: i, Currency: currency}, nil } // AmountInt64 returns a valid int64 or an error -func (v *CurrencyValue) AmountInt64() (int64, error) { - if !v.Amount.IsInt64() { +func (c *CurrencyValue) AmountInt64() (int64, error) { + if !c.Amount.IsInt64() { return 0, ErrCurrencyValueInsufficientPrecision } - return v.Amount.Int64(), nil + return c.Amount.Int64(), nil } // AmountUint64 returns a valid int64 or an error -func (v *CurrencyValue) AmountUint64() (uint64, error) { - if !v.Amount.IsUint64() { +func (c *CurrencyValue) AmountUint64() (uint64, error) { + if !c.Amount.IsUint64() { return 0, ErrCurrencyValueInsufficientPrecision } - return v.Amount.Uint64(), nil + return c.Amount.Uint64(), nil +} + +// AmountString returns the string representation of the amount +func (c *CurrencyValue) AmountString() string { + if c == nil || c.Amount == nil { + return "0" + } + return c.Amount.String() +} + +// AmountBigInt returns the big.Int representation of the amount +func (c *CurrencyValue) AmountBigInt() *big.Int { + return new(big.Int).Set(c.Amount) } // String returns a string representation of a CurrencyValue -func (v *CurrencyValue) String() string { - return fmt.Sprintf("%s %s", v.Amount.String(), v.Currency.String()) +func (c *CurrencyValue) String() string { + if c == nil { + return new(CurrencyValue).String() + } + return fmt.Sprintf("%s %s", c.Amount.String(), c.Currency.String()) } // Valid returns an error if the CurrencyValue is invalid -func (v *CurrencyValue) Valid() error { - if v.Amount == nil { +func (c *CurrencyValue) Valid() error { + if c.Amount == nil { return ErrCurrencyValueAmountInvalid } - if err := v.Currency.Valid(); err != nil { + if err := c.Currency.Valid(); err != nil { return err } return nil } // Equal indicates if the amount and variety of currency is equivalent -func (v *CurrencyValue) Equal(other *CurrencyValue) bool { - if v == nil || other == nil { +func (c *CurrencyValue) Equal(other *CurrencyValue) bool { + if c == nil && other == nil { + return true + } + if c == nil || other == nil { return false } - if !v.Currency.Equal(other.Currency) { + if !c.Currency.Equal(other.Currency) { + if c.Currency.Code == other.Currency.Code { + cN, err := c.Normalize() + if err != nil { + return false + } + oN, err := other.Normalize() + if err != nil { + return false + } + return cN.Amount.Cmp(oN.Amount) == 0 + } return false } - return v.Amount.Cmp(other.Amount) == 0 + return c.Amount.Cmp(other.Amount) == 0 +} + +// Normalize updates the CurrencyValue to match the divisibility of the locally defined CurrencyDefinition +func (c *CurrencyValue) Normalize() (*CurrencyValue, error) { + localDef, err := AllCurrencies().Lookup(string(c.Currency.Code)) + if err != nil { + return nil, err + } + val, _, err := c.AdjustDivisibility(localDef.Divisibility) + return val, err +} + +// AdjustDivisibility updates the Currency.Divisibility and adjusts the Amount to match the new +// value. An error will be returned if the new divisibility is invalid or produces an unreliable +// result. This is a helper function which is equivalent to ConvertTo using a copy of the +// CurrencyDefinition using the updated divisibility and an exchangeRatio of 1.0 +func (c *CurrencyValue) AdjustDivisibility(div uint) (*CurrencyValue, big.Accuracy, error) { + if c.Currency.Divisibility == div { + return c, 0, nil + } + defWithNewDivisibility := c.Currency + defWithNewDivisibility.Divisibility = div + return c.ConvertTo(defWithNewDivisibility, NewEquivalentConverter()) } -// ConvertTo will perform the following math given its arguments are valid: -// v.Amount * exchangeRate * (final.Currency.Divisibility/v.Currency.Divisibility) -// where v is the receiver, exchangeRate is the ratio of (1 final.Currency/v.Currency) -// v and final must both be Valid() and exchangeRate must not be zero. -func (v *CurrencyValue) ConvertTo(final *CurrencyDefinition, exchangeRate float64) (*CurrencyValue, error) { - if err := v.Valid(); err != nil { - return nil, fmt.Errorf("cannot convert invalid value: %s", err.Error()) +// ConvertTo will convert c.Amount into the final CurrencyDefinition through the +// reserve CurrencyConverter. As long as the provided reserveConverter has rates +// between the reserve currency and the current and final CurrencyDefintions, it +// will provide the result. Errors are raised if any rate is unavailable. The accuracy +// indicates if decimal values were trimmed when converting the value back to integer. +func (c *CurrencyValue) ConvertTo(final CurrencyDefinition, reserveConverter *CurrencyConverter) (*CurrencyValue, big.Accuracy, error) { + if err := c.Valid(); err != nil { + return nil, 0, fmt.Errorf("cannot convert invalid value: %s", err.Error()) } if err := final.Valid(); err != nil { - return nil, fmt.Errorf("cannot convert to invalid currency: %s", err.Error()) + return nil, 0, fmt.Errorf("cannot convert to invalid currency: %s", err.Error()) } - if exchangeRate <= 0 { - return nil, ErrCurrencyValueNegativeRate + + convertedAmt, acc, err := reserveConverter.GetFinalPrice(c, final) + if err != nil { + return nil, 0, fmt.Errorf("converting currency: %s", err.Error()) } + return convertedAmt, acc, nil +} - var ( - j = new(big.Float) - currencyRate = new(big.Float) - divisibilityRate = new(big.Float) +// ConvertUsingProtobufDef will use the currency code provided in pb.CurrencyDefinition +// to find the locally defined currency and exchange rate and will convert the amount into +// target currency. If the divisibility provided by the pb.CurrencyDefinition is different +// than the one provided for the exchange rate, the converted amount will be adjusted to +// match the provided divisibility. +func (c *CurrencyValue) ConvertUsingProtobufDef(convertTo *pb.CurrencyDefinition, reserve *CurrencyConverter) (*CurrencyValue, big.Accuracy, error) { + var repoCurrencyDef CurrencyDefinition + if c, err := AllCurrencies().Lookup(convertTo.Code); err != nil { + repoCurrencyDef = c + } else { + repoCurrencyDef = NewUnknownCryptoDefinition(convertTo.Code, uint(convertTo.Divisibility)) + } + return c.ConvertTo(repoCurrencyDef, reserve) +} - divRateFloat = math.Pow10(int(final.Divisibility)) / math.Pow10(int(v.Currency.Divisibility)) +// Cmp exposes the (*big.Int).Cmp behavior after verifying currency and adjusting +// for different currency divisibilities. +func (c *CurrencyValue) Cmp(other *CurrencyValue) (int, error) { + if c.Currency.Code.String() != other.Currency.Code.String() { + return 0, ErrCurrencyValueInvalidCmpDifferentCurrencies + } + if c.Currency.Equal(other.Currency) { + return c.Amount.Cmp(other.Amount), nil + } + if c.Currency.Divisibility > other.Currency.Divisibility { + adjOther, _, err := other.AdjustDivisibility(c.Currency.Divisibility) + if err != nil { + return 0, fmt.Errorf("adjusting other divisibility: %s", err.Error()) + } + return c.Amount.Cmp(adjOther.Amount), nil + } + selfAdj, _, err := c.AdjustDivisibility(other.Currency.Divisibility) + if err != nil { + return 0, fmt.Errorf("adjusting self divisibility: %s", err.Error()) + } + return selfAdj.Amount.Cmp(other.Amount), nil +} + +// IsZero returns true if Amount is valid and equal to zero +func (c *CurrencyValue) IsZero() bool { + if c.Amount == nil { + return false + } + return c.Amount.Cmp(big.NewInt(0)) == 0 +} + +// IsNegative returns true if Amount is valid and less-than zero +func (c *CurrencyValue) IsNegative() bool { + if c.Amount == nil { + return false + } + return c.Amount.Cmp(big.NewInt(0)) == -1 +} + +// IsPositive returns true if Amount is valid and greater-than zero +func (c *CurrencyValue) IsPositive() bool { + if c.Amount == nil { + return false + } + return c.Amount.Cmp(big.NewInt(0)) == 1 +} + +// AddBigFloatProduct will add to itself the product of itself and the float argument +// and return the result +func (c *CurrencyValue) AddBigFloatProduct(factor *big.Float) *CurrencyValue { + var ( + result, _ = new(big.Float).Mul(new(big.Float).SetInt(c.Amount), factor).Int(nil) + returnVal = NewCurrencyValueFromBigInt(c.Amount, c.Currency) ) + returnVal.Amount = returnVal.Amount.Add(returnVal.Amount, result) + return returnVal +} + +// AddBigInt will add the addend to the amount and return the value sum +func (c *CurrencyValue) AddBigInt(addend *big.Int) *CurrencyValue { + var result = new(big.Int).Add(c.Amount, addend) + return NewCurrencyValueFromBigInt(result, c.Currency) +} + +// SubBigInt will subtract the subtrahend from the amount and return the value difference +func (c *CurrencyValue) SubBigInt(subtrahend *big.Int) *CurrencyValue { + return c.AddBigInt(new(big.Int).Neg(subtrahend)) +} - currencyRate.SetFloat64(exchangeRate) - divisibilityRate.SetFloat64(divRateFloat) +// MulBigInt will multiply the amount and the factor and return the product result +func (c *CurrencyValue) MulBigInt(factor *big.Int) *CurrencyValue { + var result = new(big.Int).Mul(c.Amount, factor) + return NewCurrencyValueFromBigInt(result, c.Currency) +} - j.SetInt(v.Amount) - j.Mul(j, currencyRate) - j.Mul(j, divisibilityRate) - result, _ := j.Int(nil) - return &CurrencyValue{Amount: result, Currency: final}, nil +// MulBigFloat will multiple the amount and the factor and return the product result +// cast to a big.Int along with the big.Accuracy of the cast +func (c *CurrencyValue) MulBigFloat(factor *big.Float) (*CurrencyValue, big.Accuracy) { + var result, acc = new(big.Float).Mul(new(big.Float).SetInt(c.Amount), factor).Int(nil) + return NewCurrencyValueFromBigInt(result, c.Currency), acc } diff --git a/repo/currency_converter.go b/repo/currency_converter.go new file mode 100644 index 0000000000..c171a0d85d --- /dev/null +++ b/repo/currency_converter.go @@ -0,0 +1,130 @@ +package repo + +import ( + "errors" + "fmt" + "math/big" + "strings" +) + +var ( + // ErrPriceCalculationRequiresExchangeRates - exchange rates dependency err + ErrPriceCalculationRequiresExchangeRates = errors.New("can't calculate price with exchange rates disabled") +) + +type rater interface { + GetExchangeRate(string) (float64, error) +} + +type equivRater struct{} + +func (equivRater) GetExchangeRate(_ string) (float64, error) { return 1.0, nil } + +// NewEquivalentConverter returns a currency converter where all rates are +// always returns as 1.0 making all currencies equivalent to one another +func NewEquivalentConverter() *CurrencyConverter { + return &CurrencyConverter{reserveCode: "EQL", reserveRater: equivRater{}} +} + +// CurrencyConverter is suitable for converting a currency from one CurrencyDefinition +// to another, accounting for their differing divisibility as well as their differing +// exchange rate as provided by the rater. The rater can represent all rates for the +// reserve currency code provided. +type CurrencyConverter struct { + reserveCode string + reserveRater rater +} + +// NewCurrencyConverter returns a valid CurrencyConverter. The rater is verified by +// ensuring the rate of its reserveCode is 1.0 (ensuring it is equivalent to itself). +func NewCurrencyConverter(reserveCode string, rater rater) (*CurrencyConverter, error) { + var cc = &CurrencyConverter{reserveCode: reserveCode, reserveRater: rater} + if rate, err := cc.getExchangeRate(cc.reserveCode); err != nil { + return nil, fmt.Errorf("unable to get reserve rate (%s): %s", cc.reserveCode, err.Error()) + } else if rate != 1.0 { + return nil, fmt.Errorf("reserve exchange rate was not 1.0 (%f)", rate) + } + return cc, nil +} + +func (c CurrencyConverter) getExchangeRate(code string) (float64, error) { + // TODO: remove hack once ExchangeRates can be made aware of testnet currencies + r, err := c.reserveRater.GetExchangeRate(strings.TrimPrefix(code, "T")) + if err != nil { + return 0.0, fmt.Errorf("get rate for (%s): %s", code, err.Error()) + } + if r <= 0 { + return 0.0, fmt.Errorf("rate (%f) for (%s) must be greater than zero", r, code) + } + return r, nil +} + +func (c *CurrencyConverter) getReserveToCurrencyRate(destinationCurrencyCode string) (*big.Float, error) { + reserveIntoOriginRate, err := c.getExchangeRate(destinationCurrencyCode) + if err != nil { + return big.NewFloat(0), err + } + + // Convert to big.Float + return new(big.Float).SetFloat64(reserveIntoOriginRate), nil +} + +func (c *CurrencyConverter) getConversionRate(originCurrencyCode string, destinationCurrencyCode string) (*big.Float, error) { + originRate, err := c.getReserveToCurrencyRate(originCurrencyCode) + if err != nil { + return big.NewFloat(0), err + } + paymentRate, err := c.getReserveToCurrencyRate(destinationCurrencyCode) + if err != nil { + return big.NewFloat(0), err + } + return new(big.Float).Quo(paymentRate, originRate), nil +} + +func (c *CurrencyConverter) getDivisibilityRate(origin, destination CurrencyDefinition) (*big.Float, error) { + if err := origin.Valid(); err != nil { + return nil, fmt.Errorf("invalid origin currency: %s", err.Error()) + } + if err := destination.Valid(); err != nil { + return nil, fmt.Errorf("invalid destination currency: %s", err.Error()) + } + originDiv := new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), new(big.Int).SetUint64(uint64(origin.Divisibility)), nil)) + destDiv := new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), new(big.Int).SetUint64(uint64(destination.Divisibility)), nil)) + return new(big.Float).Quo(destDiv, originDiv), nil +} + +// GetFinalPrice returns the resulting CurrencyValue after converting the amount +// and divisibility of the originAmount to the target currency +func (c CurrencyConverter) GetFinalPrice(originAmount *CurrencyValue, resultCurrency CurrencyDefinition) (*CurrencyValue, big.Accuracy, error) { + originalAmount := new(big.Float).SetInt(originAmount.Amount) + + // get conversion ratio into/out-of reserve currency + convRate, err := c.getConversionRate(originAmount.Currency.Code.String(), resultCurrency.Code.String()) + if err != nil { + return nil, 0, err + } + + // get divisibility ratio between currencies + divRate, err := c.getDivisibilityRate(originAmount.Currency, resultCurrency) + if err != nil { + return nil, 0, err + } + + // apply the conversion and divisibility ratios to the amount + finalFloat := new(big.Float).Mul(convRate, originalAmount) + finalFloat = finalFloat.Mul(finalFloat, divRate) + finalPrice, acc := finalFloat.Int(nil) + + // round decimal away from zero + if acc == big.Above { + finalPrice.Add(finalPrice, big.NewInt(-1)) + } + if acc == big.Below { + finalPrice.Add(finalPrice, big.NewInt(1)) + } + + // return -acc because we have rounded to the other side of + // decimal (0.5 -> 1 which is Above instead of normal behavior + // of 0.5 -> 0 which is Below) + return NewCurrencyValueFromBigInt(finalPrice, resultCurrency), -acc, nil +} diff --git a/repo/currency_definition.go b/repo/currency_definition.go index 573905b34c..002b048eff 100644 --- a/repo/currency_definition.go +++ b/repo/currency_definition.go @@ -3,34 +3,86 @@ package repo import ( "errors" "fmt" - "runtime/debug" "strings" + "time" +) + +func init() { + if err := bootstrapCurrencyDictionaries(); err != nil { + panic(err) + } +} + +type ( + // CurrencyCode is a string-based currency symbol + CurrencyCode string + // CurrencyDefinition defines the characteristics of a currency + CurrencyDefinition struct { + // Name describes the colloquial term for the currency + Name string `json:"name,omitempty"` + // Code describes the currency as an uppercase string similar to ISO 4217 + Code CurrencyCode `json:"code"` + // Divisibility indicates the number of decimal places the currency can be divided in + // base10. Ex: 8 suggests a maximum divisibility of 0.00000001 + Divisibility uint `json:"divisibility"` + // CurrencyType indicates whether the currency is "fiat" or "crypto" currency + CurrencyType string `json:"currencyType,omitempty"` + // BlockTime is the general/approximate duration for a block to be mined + BlockTime time.Duration `json:"-"` + } + // CurrencyDictionaryProcessingError represents a list of errors after + // processing a CurrencyDictionary + CurrencyDictionaryProcessingError map[string]error + // CurrencyDictionary represents a collection of CurrencyDefinitions keyed + // by their CurrencyCode in string form + CurrencyDictionary struct { + definitions map[string]CurrencyDefinition + } ) const ( Fiat = "fiat" Crypto = "crypto" + + DefaultCryptoDivisibility = 8 + NilCurrencyCode = CurrencyCode("") + DefaultBlockTime = 10 * time.Minute ) var ( ErrCurrencyCodeLengthInvalid = errors.New("invalid length for currency code, must be three characters or four characters and begin with a 'T'") ErrCurrencyCodeTestSymbolInvalid = errors.New("invalid test indicator for currency code, four characters must begin with a 'T'") - ErrCurrencyDefinitionUndefined = errors.New("currency definition is not defined") + ErrCurrencyDefinitionUndefined = errors.New("unknown currency") ErrCurrencyTypeInvalid = errors.New("currency type must be crypto or fiat") ErrCurrencyDivisibilityNonPositive = errors.New("currency divisibility most be greater than zero") ErrDictionaryIndexMismatchedCode = errors.New("dictionary index mismatched with definition currency code") + ErrDictionaryCurrencyCodeCollision = errors.New("currency code is used by more than one currency") + + NilCurrencyDefinition = CurrencyDefinition{Name: "", Code: NilCurrencyCode, Divisibility: 0, CurrencyType: "", BlockTime: 0 * time.Second} - validatedMainnetCurrencyDefs map[string]*CurrencyDefinition - mainnetCurrencyDefinitions = map[string]*CurrencyDefinition{ - // Crypto - "BTC": {Name: "Bitcoin", Code: CurrencyCode("BTC"), CurrencyType: Crypto, Divisibility: 8}, - "BCH": {Name: "Bitcoin Cash", Code: CurrencyCode("BCH"), CurrencyType: Crypto, Divisibility: 8}, - "LTC": {Name: "Litecoin", Code: CurrencyCode("LTC"), CurrencyType: Crypto, Divisibility: 8}, - "ZEC": {Name: "Zcash", Code: CurrencyCode("ZEC"), CurrencyType: Crypto, Divisibility: 8}, - "ETH": {Name: "Ethereum", Code: CurrencyCode("ETH"), CurrencyType: Crypto, Divisibility: 18}, - "PHR": {Name: "Phore", Code: CurrencyCode("PHR"), CurrencyType: Crypto, Divisibility: 8}, + // holds validated dictionary singleton after initial load + validatedMainnetCurrencies *CurrencyDictionary + validatedTestnetCurrencies *CurrencyDictionary + validatedFiatCurrencies *CurrencyDictionary + validatedAllCurrencies *CurrencyDictionary - // Fiat + mainnetCryptoDefinitions = map[string]CurrencyDefinition{ + "BTC": {Name: "Bitcoin", Code: CurrencyCode("BTC"), CurrencyType: Crypto, Divisibility: 8, BlockTime: DefaultBlockTime}, + "BCH": {Name: "Bitcoin Cash", Code: CurrencyCode("BCH"), CurrencyType: Crypto, Divisibility: 8, BlockTime: DefaultBlockTime}, + "LTC": {Name: "Litecoin", Code: CurrencyCode("LTC"), CurrencyType: Crypto, Divisibility: 8, BlockTime: 150 * time.Second}, + "ZEC": {Name: "Zcash", Code: CurrencyCode("ZEC"), CurrencyType: Crypto, Divisibility: 8, BlockTime: DefaultBlockTime}, + "PHR": {Name: "Phore", Code: CurrencyCode("PHR"), CurrencyType: Crypto, Divisibility: 8, BlockTime: time.Minute}, + "ETH": {Name: "Ethereum", Code: CurrencyCode("ETH"), CurrencyType: Crypto, Divisibility: 18, BlockTime: 10 * time.Second}, + } + testnetCryptoDefinitions = map[string]CurrencyDefinition{ + "TBTC": {Name: "Testnet Bitcoin", Code: CurrencyCode("TBTC"), CurrencyType: Crypto, Divisibility: 8, BlockTime: DefaultBlockTime}, + "TBCH": {Name: "Testnet Bitcoin Cash", Code: CurrencyCode("TBCH"), CurrencyType: Crypto, Divisibility: 8, BlockTime: DefaultBlockTime}, + "TLTC": {Name: "Testnet Litecoin", Code: CurrencyCode("TLTC"), CurrencyType: Crypto, Divisibility: 8, BlockTime: 150 * time.Second}, + "TZEC": {Name: "Testnet Zcash", Code: CurrencyCode("TZEC"), CurrencyType: Crypto, Divisibility: 8, BlockTime: DefaultBlockTime}, + "TPHR": {Name: "Testnet Phore", Code: CurrencyCode("TPHR"), CurrencyType: Crypto, Divisibility: 8, BlockTime: time.Minute}, + "TETH": {Name: "Testnet Ethereum", Code: CurrencyCode("TETH"), CurrencyType: Crypto, Divisibility: 18, BlockTime: 10 * time.Second}, + } + fiatDefinitions = map[string]CurrencyDefinition{ "AED": {Name: "UAE Dirham", Code: CurrencyCode("AED"), CurrencyType: Fiat, Divisibility: 2}, "AFN": {Name: "Afghani", Code: CurrencyCode("AFN"), CurrencyType: Fiat, Divisibility: 2}, "ALL": {Name: "Lek", Code: CurrencyCode("ALL"), CurrencyType: Fiat, Divisibility: 2}, @@ -165,7 +217,7 @@ var ( "TJS": {Name: "Somoni", Code: CurrencyCode("TJS"), CurrencyType: Fiat, Divisibility: 2}, "TMT": {Name: "Turkmenistan New Manat", Code: CurrencyCode("TMT"), CurrencyType: Fiat, Divisibility: 2}, "TND": {Name: "Tunisian Dinar", Code: CurrencyCode("TND"), CurrencyType: Fiat, Divisibility: 2}, - "TOP": {Name: "Pa\"anga", Code: CurrencyCode("TOP"), CurrencyType: Fiat, Divisibility: 2}, + "TOP": {Name: "Paanga", Code: CurrencyCode("TOP"), CurrencyType: Fiat, Divisibility: 2}, "TRY": {Name: "Turkish Lira", Code: CurrencyCode("TRY"), CurrencyType: Fiat, Divisibility: 2}, "TTD": {Name: "Trinidad and Tobago Dollar", Code: CurrencyCode("TTD"), CurrencyType: Fiat, Divisibility: 2}, "TWD": {Name: "New Taiwan Dollar", Code: CurrencyCode("TWD"), CurrencyType: Fiat, Divisibility: 2}, @@ -191,57 +243,118 @@ var ( } ) -type ( - // CurrencyCode is a string-based currency symbol - CurrencyCode string - // CurrencyDefinition defines the characteristics of a currency - CurrencyDefinition struct { - Name string - Code CurrencyCode - Divisibility uint - CurrencyType string +// String returns a readable representation of CurrencyCode +func (c CurrencyCode) String() string { + if string(c) == "" { + return "NIL" } - // CurrencyDictionaryProcessingError represents a list of errors after - // processing a CurrencyDictionary - CurrencyDictionaryProcessingError map[string]error - // CurrencyDictionary represents a collection of CurrencyDefinitions keyed - // by their CurrencyCode in string form - CurrencyDictionary map[string]*CurrencyDefinition -) + return string(c) +} -// String returns a readable representation of CurrencyCode -func (c CurrencyCode) String() string { return string(c) } +// NewUnknownCryptoDefinition returns a suitable crypto definition +// when one does not already exist in local dictionaries +func NewUnknownCryptoDefinition(code string, div uint) CurrencyDefinition { + if div == 0 { + div = DefaultCryptoDivisibility + } + return CurrencyDefinition{ + Name: fmt.Sprintf("Unknown Currency (%s)", code), + Code: CurrencyCode(code), + Divisibility: div, + CurrencyType: Crypto, + } +} // String returns a readable representation of CurrencyDefinition -func (c *CurrencyDefinition) String() string { - if c == nil { - log.Errorf("returning nil CurrencyCode, please report this bug") - debug.PrintStack() - return "nil" +func (c CurrencyDefinition) String() string { + if c == NilCurrencyDefinition { + return fmt.Sprintf("%s (%sdiv%d)", "nil", c.Code.String(), 0) } - return c.Code.String() + return fmt.Sprintf("%s (%sdiv%d)", c.Name, c.Code.String(), c.Divisibility) } // CurrencyCode returns the CurrencyCode of the definition -func (c *CurrencyDefinition) CurrencyCode() *CurrencyCode { return &c.Code } +func (c CurrencyDefinition) CurrencyCode() CurrencyCode { return c.Code } +// Error satisfies the Error interface without needing the process the set of errors func (c CurrencyDictionaryProcessingError) Error() string { return fmt.Sprintf("dictionary contains %d invalid definitions", len(c)) } -// LoadCurrencyDefinitions returns the mainnet CurrencyDictionary singleton which -// references all pre-defined mainnet CurrencyDefinitions -func LoadCurrencyDefinitions() CurrencyDictionary { - if validatedMainnetCurrencyDefs == nil { - dict, _ := NewCurrencyDictionary(mainnetCurrencyDefinitions) - validatedMainnetCurrencyDefs = dict - } - return validatedMainnetCurrencyDefs +func (c CurrencyDictionaryProcessingError) All() []string { + var errs []string + for code, err := range c { + errs = append(errs, fmt.Sprintf("%s: %s", code, err.Error())) + } + return errs +} + +func bootstrapCurrencyDictionaries() error { + var err error + validatedMainnetCurrencies, err = NewCurrencyDictionary(mainnetCryptoDefinitions) + if err != nil { + return fmt.Errorf("building mainnet currency dictionary: %s", err) + } + validatedTestnetCurrencies, err = NewCurrencyDictionary(testnetCryptoDefinitions) + if err != nil { + return fmt.Errorf("building testnet currency dictionary: %s", err) + } + validatedFiatCurrencies, err = NewCurrencyDictionary(fiatDefinitions) + if err != nil { + return fmt.Errorf("building fiat currency dictionary: %s", err) + } + var allDefs = make(map[string]CurrencyDefinition) + for i, d := range fiatDefinitions { + if _, ok := allDefs[i]; ok { + return fmt.Errorf("unhandled currency code collision for (%s)", i) + } + allDefs[i] = d + } + for i, d := range testnetCryptoDefinitions { + if _, ok := allDefs[i]; ok { + return fmt.Errorf("unhandled currency code collision for (%s)", i) + } + allDefs[i] = d + } + for i, d := range mainnetCryptoDefinitions { + if _, ok := allDefs[i]; ok { + return fmt.Errorf("unhandled currency code collision for (%s)", i) + } + allDefs[i] = d + } + validatedAllCurrencies, err = NewCurrencyDictionary(allDefs) + if err != nil { + return fmt.Errorf("building all currency dictionary: %s", err) + } + return nil +} + +// MainnetCurrencies returns the mainnet crypto currency definition singleton +func MainnetCurrencies() *CurrencyDictionary { + return validatedMainnetCurrencies +} + +// TestnetCurrencies returns the mainnet crypto currency definition singleton +func TestnetCurrencies() *CurrencyDictionary { + return validatedTestnetCurrencies +} + +// FiatCurrencies returns the mainnet crypto currency definition singleton +func FiatCurrencies() *CurrencyDictionary { + return validatedFiatCurrencies +} + +// AllCurrencies returns the singleton representing all known currency definitions +func AllCurrencies() *CurrencyDictionary { + return validatedAllCurrencies } // NewCurrencyDictionary returns a CurrencyDictionary for managing CurrencyDefinitions -func NewCurrencyDictionary(defs map[string]*CurrencyDefinition) (CurrencyDictionary, error) { - var errs = make(CurrencyDictionaryProcessingError) +func NewCurrencyDictionary(defs map[string]CurrencyDefinition) (*CurrencyDictionary, error) { + var ( + errs = make(CurrencyDictionaryProcessingError) + validDefs = make(map[string]CurrencyDefinition) + ) for code, def := range defs { if err := def.Valid(); err != nil { errs[code] = err @@ -251,23 +364,22 @@ func NewCurrencyDictionary(defs map[string]*CurrencyDefinition) (CurrencyDiction errs[code] = ErrDictionaryIndexMismatchedCode continue } + validDefs[code] = def } if len(errs) > 0 { - return nil, errs + return &CurrencyDictionary{}, errs } - return CurrencyDictionary(defs), nil + return &CurrencyDictionary{definitions: validDefs}, nil } -func (c *CurrencyDefinition) Valid() error { - if c == nil { +// Valid asserts that the CurrencyDefinition is either valid or has at least one error +func (c CurrencyDefinition) Valid() error { + if c.Equal(NilCurrencyDefinition) { return ErrCurrencyDefinitionUndefined } - if len(c.Code) < CurrencyCodeValidMinimumLength || len(c.Code) > CurrencyCodeValidMaximumLength { + if c.Code == NilCurrencyCode { return ErrCurrencyCodeLengthInvalid } - if len(c.Code) == 4 && strings.Index(strings.ToLower(string(c.Code)), "t") != 0 { - return ErrCurrencyCodeTestSymbolInvalid - } if c.CurrencyType != Crypto && c.CurrencyType != Fiat { return ErrCurrencyTypeInvalid } @@ -280,10 +392,7 @@ func (c *CurrencyDefinition) Valid() error { // Equal indicates if the receiver and other have the same code // and divisibility -func (c *CurrencyDefinition) Equal(other *CurrencyDefinition) bool { - if c == nil || other == nil { - return false - } +func (c CurrencyDefinition) Equal(other CurrencyDefinition) bool { if c.Code != other.Code { return false } @@ -296,36 +405,40 @@ func (c *CurrencyDefinition) Equal(other *CurrencyDefinition) bool { return true } -// LookupCurrencyDefinition returns the CurrencyDefinition out of the loaded dictionary. -// Lookup normalizes the code before lookup and recommends using CurrencyDefinition.Code -// from the response as a normalized code. -func (c CurrencyDictionary) Lookup(code string) (*CurrencyDefinition, error) { - var ( - upcase = strings.ToUpper(code) - isTestnet = strings.HasPrefix(upcase, "T") +// ConfirmationsPerHour will calculate the no of confirmations in 1 hr +// this is valid only for a crypto +func (c CurrencyDefinition) ConfirmationsPerHour() uint32 { + if c.CurrencyType != "crypto" { + return 1 + } + if c.BlockTime.Seconds() <= 0 { + return 1 + } + return uint32((1.0 * 60 * 60) / c.BlockTime.Seconds()) +} - def *CurrencyDefinition - ok bool - ) - if isTestnet { - def, ok = c[strings.TrimPrefix(upcase, "T")] - } else { - def, ok = c[upcase] +// Lookup returns the CurrencyDefinition out of the loaded dictionary. Lookup normalizes the code +// before lookup and recommends using CurrencyDefinition.CurrencyCode().String() from the +// response as a normalized code. +func (c CurrencyDictionary) Lookup(code string) (CurrencyDefinition, error) { + if len(c.definitions) == 0 { + return NilCurrencyDefinition, ErrCurrencyDefinitionUndefined } + var ( + upcase = strings.ToUpper(code) + def, ok = c.definitions[upcase] + ) if !ok { - return nil, ErrCurrencyDefinitionUndefined - } - if isTestnet { - return NewTestnetDefinition(def), nil + return NilCurrencyDefinition, ErrCurrencyDefinitionUndefined } return def, nil } -func NewTestnetDefinition(def *CurrencyDefinition) *CurrencyDefinition { - return &CurrencyDefinition{ - Name: def.Name, - Code: CurrencyCode(fmt.Sprintf("T%s", def.Code)), - Divisibility: def.Divisibility, - CurrencyType: def.CurrencyType, +// AsMap returns a cloned map of all known the definitions +func (c CurrencyDictionary) AsMap() map[string]CurrencyDefinition { + var defCopy = make(map[string]CurrencyDefinition, len(c.definitions)) + for i, d := range c.definitions { + defCopy[i] = d } + return defCopy } diff --git a/repo/currency_definition_test.go b/repo/currency_definition_test.go index a6c2c1ab20..534893a675 100644 --- a/repo/currency_definition_test.go +++ b/repo/currency_definition_test.go @@ -2,60 +2,60 @@ package repo_test import ( "reflect" + "strings" "testing" + "time" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" ) func TestCurrencyDefinitionsAreEqual(t *testing.T) { - var ( - validDef = factory.NewCurrencyDefinition("BTC") - matchingDef = factory.NewCurrencyDefinition("BTC") - differentCodeDef = factory.NewCurrencyDefinition("ETH") - differentTypeDef = factory.NewCurrencyDefinition("BTC") - differentDivisibilityDef = factory.NewCurrencyDefinition("BTC") - differentNameDef = factory.NewCurrencyDefinition("BTC") - examples = []struct { - value *repo.CurrencyDefinition - other *repo.CurrencyDefinition - expected bool - }{ - { // currency and divisibility matching should be equal - value: validDef, - other: matchingDef, - expected: true, - }, - { // different names should be true - value: validDef, - other: differentNameDef, - expected: true, - }, - { // nils should be false - value: nil, - other: nil, - expected: false, - }, - { // different code should be false - value: validDef, - other: differentCodeDef, - expected: false, - }, - { // different divisibility should be false - value: validDef, - other: differentDivisibilityDef, - expected: false, - }, - { // different type should be false - value: validDef, - other: differentTypeDef, - expected: false, - }, - } - ) + validDef := factory.NewCurrencyDefinition("BTC") + matchingDef := factory.NewCurrencyDefinition("BTC") + differentCodeDef := factory.NewCurrencyDefinition("ETH") + differentTypeDef := factory.NewCurrencyDefinition("BTC") + differentTypeDef.CurrencyType = "invalid" + differentDivisibilityDef := factory.NewCurrencyDefinition("BTC") differentDivisibilityDef.Divisibility = 10 + differentNameDef := factory.NewCurrencyDefinition("BTC") differentNameDef.Name = "Something else" - differentTypeDef.CurrencyType = "invalid" + examples := []struct { + value repo.CurrencyDefinition + other repo.CurrencyDefinition + expected bool + }{ + { // currency and divisibility matching should be equal + value: validDef, + other: matchingDef, + expected: true, + }, + { // different names should be true + value: validDef, + other: differentNameDef, + expected: true, + }, + { // nils should be true + value: repo.NilCurrencyDefinition, + other: repo.NilCurrencyDefinition, + expected: true, + }, + { // different code should be false + value: validDef, + other: differentCodeDef, + expected: false, + }, + { // different divisibility should be false + value: validDef, + other: differentDivisibilityDef, + expected: false, + }, + { // different type should be false + value: validDef, + other: differentTypeDef, + expected: false, + }, + } for _, c := range examples { if c.value.Equal(c.other) != c.expected { @@ -73,11 +73,11 @@ func TestCurrencyDefinitionsAreEqual(t *testing.T) { func TestCurrencyDefinitionValidation(t *testing.T) { var examples = []struct { expectErr error - input *repo.CurrencyDefinition + input repo.CurrencyDefinition }{ { // valid mainnet currency expectErr: nil, - input: &repo.CurrencyDefinition{ + input: repo.CurrencyDefinition{ Code: repo.CurrencyCode("BTC"), Divisibility: 8, CurrencyType: repo.Crypto, @@ -85,31 +85,15 @@ func TestCurrencyDefinitionValidation(t *testing.T) { }, { // valid testnet currency expectErr: nil, - input: &repo.CurrencyDefinition{ + input: repo.CurrencyDefinition{ Code: repo.CurrencyCode("TBTC"), Divisibility: 8, CurrencyType: repo.Crypto, }, }, - { // error invalid 4-char currency code - expectErr: repo.ErrCurrencyCodeTestSymbolInvalid, - input: &repo.CurrencyDefinition{ - Code: repo.CurrencyCode("XBTC"), - Divisibility: 8, - CurrencyType: repo.Crypto, - }, - }, - { // error invalid currency code length - expectErr: repo.ErrCurrencyCodeLengthInvalid, - input: &repo.CurrencyDefinition{ - Code: repo.CurrencyCode("BT"), - Divisibility: 8, - CurrencyType: repo.Crypto, - }, - }, { // error empty currency code expectErr: repo.ErrCurrencyCodeLengthInvalid, - input: &repo.CurrencyDefinition{ + input: repo.CurrencyDefinition{ Code: repo.CurrencyCode(""), Divisibility: 8, CurrencyType: repo.Crypto, @@ -117,7 +101,7 @@ func TestCurrencyDefinitionValidation(t *testing.T) { }, { // error invalid currency type expectErr: repo.ErrCurrencyTypeInvalid, - input: &repo.CurrencyDefinition{ + input: repo.CurrencyDefinition{ Code: repo.CurrencyCode("123"), Divisibility: 1, CurrencyType: "invalid", @@ -125,7 +109,7 @@ func TestCurrencyDefinitionValidation(t *testing.T) { }, { // error non-positive divisibility expectErr: repo.ErrCurrencyDivisibilityNonPositive, - input: &repo.CurrencyDefinition{ + input: repo.CurrencyDefinition{ Code: repo.CurrencyCode("234"), Divisibility: 0, CurrencyType: repo.Crypto, @@ -133,7 +117,7 @@ func TestCurrencyDefinitionValidation(t *testing.T) { }, { // error nil definition expectErr: repo.ErrCurrencyDefinitionUndefined, - input: nil, + input: repo.NilCurrencyDefinition, }, } @@ -159,38 +143,38 @@ func TestCurrencyDefinitionValidation(t *testing.T) { func TestCurrencyDictionaryLookup(t *testing.T) { var ( - expected = factory.NewCurrencyDefinition("ABC") - dict = repo.CurrencyDictionary{ + code = "ABC" + expected = factory.NewCurrencyDefinition(code) + defs = map[string]repo.CurrencyDefinition{ expected.Code.String(): expected, } - - examples = []struct { - lookup string - expected *repo.CurrencyDefinition - expectedErr error - }{ - { // upcase lookup - lookup: "ABC", - expected: expected, - expectedErr: nil, - }, - { // lowercase lookup - lookup: "abc", - expected: expected, - expectedErr: nil, - }, - { // testnet lookup - lookup: "TABC", - expected: factory.NewCurrencyDefinition("TABC"), - expectedErr: nil, - }, - { // undefined key - lookup: "FAIL", - expected: nil, - expectedErr: repo.ErrCurrencyDefinitionUndefined, - }, - } ) + dict, err := repo.NewCurrencyDictionary(defs) + if err != nil { + t.Fatal(err) + } + + var examples = []struct { + lookup string + expected repo.CurrencyDefinition + expectedErr error + }{ + { // upcase lookup + lookup: code, + expected: expected, + expectedErr: nil, + }, + { // lowercase lookup + lookup: strings.ToLower(code), + expected: expected, + expectedErr: nil, + }, + { // undefined key + lookup: "FAIL", + expected: repo.NilCurrencyDefinition, + expectedErr: repo.ErrCurrencyDefinitionUndefined, + }, + } for _, e := range examples { var def, err = dict.Lookup(e.lookup) @@ -215,34 +199,27 @@ func TestCurrencyDictionaryLookup(t *testing.T) { } func TestCurrencyDictionaryValid(t *testing.T) { - var ( - valid = factory.NewCurrencyDefinition("BTC") - invalidOne = factory.NewCurrencyDefinition("LTC") - invalidTwo = factory.NewCurrencyDefinition("BCH") - ) + valid := factory.NewCurrencyDefinition("BTC") + // invalidOne is invalid because the divisibility is 0 + invalidOne := factory.NewCurrencyDefinition("LTC") invalidOne.Divisibility = 0 - invalidTwo.Code = "X" + // colliding is invalid because the code collides with BTC above + colliding := factory.NewCurrencyDefinition("BTC") errOne := invalidOne.Valid() if errOne == nil { t.Fatalf("expected invalidOne to be invalid, but was not") } - errTwo := invalidTwo.Valid() - if errOne == nil { - t.Fatalf("expected invalidTwo to be invalid, but was not") - } - //nolint + expectedErrs := map[string]error{ - invalidOne.Code.String(): errOne, - invalidTwo.Code.String(): errTwo, - "DIF": repo.ErrDictionaryIndexMismatchedCode, + invalidOne.CurrencyCode().String(): errOne, + "DIF": repo.ErrDictionaryIndexMismatchedCode, } - //nolint - _, err := repo.NewCurrencyDictionary(map[string]*repo.CurrencyDefinition{ - valid.Code.String(): valid, - invalidOne.Code.String(): invalidOne, - invalidTwo.Code.String(): invalidTwo, - "DIF": valid, + _, err := repo.NewCurrencyDictionary(map[string]repo.CurrencyDefinition{ + valid.CurrencyCode().String(): valid, + colliding.CurrencyCode().String(): colliding, + invalidOne.CurrencyCode().String(): invalidOne, + "DIF": valid, }) var mappedErrs map[string]error @@ -255,3 +232,90 @@ func TestCurrencyDictionaryValid(t *testing.T) { t.Fatalf("expected error map to match, but did not") } } + +func TestNilCodeCollision(t *testing.T) { + subject := repo.NilCurrencyCode + if _, err := repo.AllCurrencies().Lookup(subject.String()); err == nil { + t.Fatal("expected nil currency lookup to error, but did not") + } +} + +func TestCurrencyDefinitionBlockTime(t *testing.T) { + dict := repo.AllCurrencies() + var examples = []struct { + input string + expectedBlockTime time.Duration + expectedConfirmationsPerHour uint32 + }{ + { + input: "BTC", + expectedBlockTime: 10 * time.Minute, + expectedConfirmationsPerHour: 6, + }, + { + input: "TBTC", + expectedBlockTime: 10 * time.Minute, + expectedConfirmationsPerHour: 6, + }, + { + input: "BCH", + expectedBlockTime: 10 * time.Minute, + expectedConfirmationsPerHour: 6, + }, + { + input: "TBCH", + expectedBlockTime: 10 * time.Minute, + expectedConfirmationsPerHour: 6, + }, + { + input: "LTC", + expectedBlockTime: 150 * time.Second, + expectedConfirmationsPerHour: 24, + }, + { + input: "TLTC", + expectedBlockTime: 150 * time.Second, + expectedConfirmationsPerHour: 24, + }, + { + input: "ZEC", + expectedBlockTime: 10 * time.Minute, + expectedConfirmationsPerHour: 6, + }, + { + input: "TZEC", + expectedBlockTime: 10 * time.Minute, + expectedConfirmationsPerHour: 6, + }, + { + input: "ETH", + expectedBlockTime: 10 * time.Second, + expectedConfirmationsPerHour: 360, + }, + { + input: "TETH", + expectedBlockTime: 10 * time.Second, + expectedConfirmationsPerHour: 360, + }, + { + input: "USD", + expectedBlockTime: 0 * time.Second, + expectedConfirmationsPerHour: 1, + }, + } + + for _, e := range examples { + defn, err := dict.Lookup(e.input) + if err != nil { + t.Errorf("lookup should not fail for code : %s with error : %s", e.input, err.Error()) + } + if defn.BlockTime != e.expectedBlockTime { + t.Errorf("blocktime validation fail for code : %s, expected : %v , actual : %v", + e.input, e.expectedBlockTime, defn.BlockTime) + } + if defn.ConfirmationsPerHour() != e.expectedConfirmationsPerHour { + t.Errorf("confirmations per hour validation fail for code : %s, expected : %v , actual : %v", + e.input, e.expectedConfirmationsPerHour, defn.BlockTime) + } + } +} diff --git a/repo/currency_definitions_validity_test.go b/repo/currency_definitions_validity_test.go index ac4edddc9b..86f52d0423 100644 --- a/repo/currency_definitions_validity_test.go +++ b/repo/currency_definitions_validity_test.go @@ -2,10 +2,8 @@ package repo import "testing" -func TestMainnetCurrencyDictionaryIsValid(t *testing.T) { - if _, err := NewCurrencyDictionary(mainnetCurrencyDefinitions); err != nil { - var mappedErrs = map[string]error(err.(CurrencyDictionaryProcessingError)) - t.Logf("invalid currencies: %s", mappedErrs) +func TestValidDictionaries(t *testing.T) { + if err := bootstrapCurrencyDictionaries(); err != nil { t.Fatal(err) } } diff --git a/repo/currency_test.go b/repo/currency_test.go index 8b02c57e05..22af2be4eb 100644 --- a/repo/currency_test.go +++ b/repo/currency_test.go @@ -1,12 +1,13 @@ package repo_test import ( - "encoding/json" + "math/big" "strings" "testing" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" ) func mustNewCurrencyValue(t *testing.T, amount, currencyCode string) *repo.CurrencyValue { @@ -25,7 +26,7 @@ func TestCurrencyValueMarshalsToJSON(t *testing.T) { var ( examples = []struct { value string - currency *repo.CurrencyDefinition + currency repo.CurrencyDefinition }{ { // valid currency value value: "123456789012345678", @@ -41,19 +42,20 @@ func TestCurrencyValueMarshalsToJSON(t *testing.T) { for _, e := range examples { var ( example, err = repo.NewCurrencyValue(e.value, e.currency) - actual *repo.CurrencyValue + //actual *repo.CurrencyValue ) + actual := &repo.CurrencyValue{} if err != nil { t.Errorf("unable to parse valid input '%s': %s", e.value, err.Error()) continue } - j, err := json.Marshal(example) + j, err := example.MarshalJSON() if err != nil { t.Errorf("marshaling %s: %s", example.String(), err) continue } - if err := json.Unmarshal(j, &actual); err != nil { + if err := actual.UnmarshalJSON(j); err != nil { t.Errorf("unmarhsaling %s, %s", example.String(), err) continue } @@ -75,7 +77,7 @@ func TestCurrencyValuesAreValid(t *testing.T) { }, { // invalid nil value value: func() *repo.CurrencyValue { - var value = factory.NewCurrencyValue("123", "BTC") + var value = factory.MustNewCurrencyValue("123", "BTC") value.Amount = nil return value }, @@ -83,15 +85,15 @@ func TestCurrencyValuesAreValid(t *testing.T) { }, { // invalid nil currency value: func() *repo.CurrencyValue { - var value = factory.NewCurrencyValue("123", "BTC") - value.Currency = nil + var value = factory.MustNewCurrencyValue("123", "BTC") + value.Currency = repo.NilCurrencyDefinition return value }, expectedErr: repo.ErrCurrencyDefinitionUndefined, }, { // invalid currency definition makes value invalid (0 divisibility) value: func() *repo.CurrencyValue { - var value = factory.NewCurrencyValue("123", "BTC") + var value = factory.MustNewCurrencyValue("123", "BTC") value.Currency.Divisibility = 0 return value }, @@ -123,13 +125,33 @@ func TestCurrencyValuesAreEqual(t *testing.T) { other *repo.CurrencyValue expected bool }{ + { // value and currency divisibility different but + // equal after normalizing + value: &repo.CurrencyValue{ + Amount: big.NewInt(1234), + Currency: repo.CurrencyDefinition{ + Code: "BTC", + Divisibility: 2, + CurrencyType: "crypto", + }, + }, + other: &repo.CurrencyValue{ + Amount: big.NewInt(123400), + Currency: repo.CurrencyDefinition{ + Code: "BTC", + Divisibility: 4, + CurrencyType: "crypto", + }, + }, + expected: true, + }, { // value and currency matching should be equal value: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1"), + Amount: big.NewInt(1), Currency: factory.NewCurrencyDefinition("BTC"), }, other: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1"), + Amount: big.NewInt(1), Currency: factory.NewCurrencyDefinition("BTC"), }, expected: true, @@ -137,19 +159,19 @@ func TestCurrencyValuesAreEqual(t *testing.T) { { // nils should not be equal value: nil, other: nil, - expected: false, + expected: true, }, { // nil should not match with a value value: nil, other: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1"), + Amount: big.NewInt(1), Currency: factory.NewCurrencyDefinition("BTC"), }, expected: false, }, { // value should not match with nil value: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1"), + Amount: big.NewInt(1), Currency: factory.NewCurrencyDefinition("BTC"), }, other: nil, @@ -157,33 +179,33 @@ func TestCurrencyValuesAreEqual(t *testing.T) { }, { // value difference value: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1"), + Amount: big.NewInt(1), Currency: factory.NewCurrencyDefinition("BTC"), }, other: &repo.CurrencyValue{ - Amount: factory.NewBigInt("2"), + Amount: big.NewInt(2), Currency: factory.NewCurrencyDefinition("BTC"), }, expected: false, }, { // currency code difference value: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1"), + Amount: big.NewInt(1), Currency: factory.NewCurrencyDefinition("BTC"), }, other: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1"), + Amount: big.NewInt(1), Currency: factory.NewCurrencyDefinition("ETH"), }, expected: false, }, { // currency code missing value: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1"), - Currency: nil, + Amount: big.NewInt(1), + Currency: repo.NilCurrencyDefinition, }, other: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1"), + Amount: big.NewInt(1), Currency: factory.NewCurrencyDefinition("ETH"), }, expected: false, @@ -198,152 +220,559 @@ func TestCurrencyValuesAreEqual(t *testing.T) { t.Errorf("expected %s to not equal %s but did", c.value.String(), c.other.String()) } } + + // test that equal is communitive + if c.other.Equal(c.value) != c.expected { + if c.expected { + t.Errorf("expected %s to equal %s but did not", c.other.String(), c.value.String()) + } else { + t.Errorf("expected %s to not equal %s but did", c.other.String(), c.value.String()) + } + } } } func TestCurrencyValuesConvertCorrectly(t *testing.T) { var ( - zeroRateErr = "rate must be greater than zero" - undefinedCurrencyErr = "currency definition is not defined" + zeroRateErr = "must be greater than zero" + undefinedCurrencyErr = "unknown currency" invalidErr = "cannot convert invalid value" + reserveCurrency = "BTC" examples = []struct { - value *repo.CurrencyValue - convertTo *repo.CurrencyDefinition - exchangeRate float64 - expected *repo.CurrencyValue - expectedErr *string + value *repo.CurrencyValue + convertTo repo.CurrencyDefinition + exchangeRates map[string]float64 + expected *repo.CurrencyValue + expectedAcc int8 + expectedErr *string }{ - { // errors when definition is nil - value: factory.NewCurrencyValue("0", "BTC"), - convertTo: nil, - exchangeRate: 0.99999, - expected: nil, - expectedErr: &undefinedCurrencyErr, - }, - { // errors zero rate - value: factory.NewCurrencyValue("123", "BTC"), - convertTo: factory.NewCurrencyDefinition("BCH"), - exchangeRate: 0, - expected: nil, - expectedErr: &zeroRateErr, - }, - { // errors negative rate - value: factory.NewCurrencyValue("123", "BTC"), - convertTo: factory.NewCurrencyDefinition("BCH"), - exchangeRate: -0.1, - expected: nil, - expectedErr: &zeroRateErr, - }, - { // rounds down - value: factory.NewCurrencyValue("1", "BTC"), - convertTo: factory.NewCurrencyDefinition("BCH"), - exchangeRate: 0.9, - expected: factory.NewCurrencyValue("0", "BCH"), - expectedErr: nil, - }, - { // handles negative values - value: factory.NewCurrencyValue("-100", "BTC"), - convertTo: factory.NewCurrencyDefinition("BCH"), - exchangeRate: 0.123, - expected: factory.NewCurrencyValue("-12", "BCH"), - expectedErr: nil, - }, - { // handles zero - value: factory.NewCurrencyValue("0", "BTC"), - convertTo: factory.NewCurrencyDefinition("BCH"), - exchangeRate: 0.99999, - expected: factory.NewCurrencyValue("0", "BCH"), - expectedErr: nil, - }, - { // handles invalid value + { // 0. errors when definition is nil + value: factory.MustNewCurrencyValue("0", "BTC"), + convertTo: repo.NilCurrencyDefinition, + exchangeRates: map[string]float64{ + "BCH": 0.99999, + }, + expected: nil, + expectedAcc: 0, + expectedErr: &undefinedCurrencyErr, + }, + { // 1. errors zero rate + value: factory.MustNewCurrencyValue("123", "BTC"), + convertTo: factory.NewCurrencyDefinition("BCH"), + exchangeRates: map[string]float64{ + "BCH": 0, + }, + expected: nil, + expectedAcc: 0, + expectedErr: &zeroRateErr, + }, + { // 2. errors negative rate + value: factory.MustNewCurrencyValue("123", "BTC"), + convertTo: factory.NewCurrencyDefinition("BCH"), + exchangeRates: map[string]float64{ + "BCH": -0.1, + }, + expected: nil, + expectedAcc: 0, + expectedErr: &zeroRateErr, + }, + { // 3. rounds up + value: factory.MustNewCurrencyValue("1", "BTC"), + convertTo: factory.NewCurrencyDefinition("BCH"), + exchangeRates: map[string]float64{ + "BCH": 0.9, + }, + expected: factory.MustNewCurrencyValue("1", "BCH"), + expectedAcc: 1, + expectedErr: nil, + }, + { // 4. handles negative values + value: factory.MustNewCurrencyValue("-100", "BTC"), + convertTo: factory.NewCurrencyDefinition("BCH"), + exchangeRates: map[string]float64{ + "BCH": 0.123, + }, + expected: factory.MustNewCurrencyValue("-13", "BCH"), + expectedAcc: -1, + expectedErr: nil, + }, + { // 5. handles zero + value: factory.MustNewCurrencyValue("0", "BTC"), + convertTo: factory.NewCurrencyDefinition("BCH"), + exchangeRates: map[string]float64{ + "BCH": 0.99999, + }, + expected: factory.MustNewCurrencyValue("0", "BCH"), + expectedAcc: 0, + expectedErr: nil, + }, + { // 6. handles invalid value value: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1000"), - Currency: nil, + Amount: big.NewInt(1000), + Currency: repo.NilCurrencyDefinition, + }, + convertTo: factory.NewCurrencyDefinition("BCH"), + exchangeRates: map[string]float64{ + "BCH": 0.5, }, - convertTo: factory.NewCurrencyDefinition("BTC"), - exchangeRate: 0.5, - expected: nil, - expectedErr: &invalidErr, + expected: nil, + expectedAcc: 0, + expectedErr: &invalidErr, }, - { // handles conversions between different divisibility + { // 7. handles conversions between different divisibility value: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1000"), - Currency: &repo.CurrencyDefinition{ + Amount: big.NewInt(1000), + Currency: repo.CurrencyDefinition{ Name: "United States Dollar", Code: "USD", Divisibility: 2, CurrencyType: repo.Fiat, }, }, - convertTo: &repo.CurrencyDefinition{ + convertTo: repo.CurrencyDefinition{ Name: "SimpleCoin", Code: "SPC", Divisibility: 6, CurrencyType: repo.Crypto, }, - exchangeRate: 0.5, + exchangeRates: map[string]float64{ + "USD": 1, + "SPC": 0.5, + }, expected: &repo.CurrencyValue{ - Amount: factory.NewBigInt("5000000"), - Currency: &repo.CurrencyDefinition{ + Amount: big.NewInt(5000000), + Currency: repo.CurrencyDefinition{ Name: "SimpleCoin", Code: "SPC", Divisibility: 6, CurrencyType: repo.Crypto, }, }, + expectedAcc: 0, expectedErr: nil, }, - { // handles conversions between different - // divisibility w inverse rate - value: &repo.CurrencyValue{ - Amount: factory.NewBigInt("1000000"), - Currency: &repo.CurrencyDefinition{ + { // 8. handles conversions between different + // divisibility and rates + value: &repo.CurrencyValue{ // 99.123456 SPC + Amount: big.NewInt(99123456), + Currency: repo.CurrencyDefinition{ Name: "SimpleCoin", Code: "SPC", Divisibility: 6, CurrencyType: repo.Crypto, }, }, - convertTo: &repo.CurrencyDefinition{ + convertTo: repo.CurrencyDefinition{ Name: "United States Dollar", Code: "USD", Divisibility: 2, CurrencyType: repo.Fiat, }, - exchangeRate: 2, - expected: &repo.CurrencyValue{ - Amount: factory.NewBigInt("200"), - Currency: &repo.CurrencyDefinition{ + exchangeRates: map[string]float64{ + "SPC": 0.5, + "USD": 2, + }, + expected: &repo.CurrencyValue{ // 99.123456 SPC * (2/0.5 USD/SPC * 100/1000000) (rounded up to next largest int) + Amount: big.NewInt(39650), + Currency: repo.CurrencyDefinition{ Name: "United States Dollar", Code: "USD", Divisibility: 2, CurrencyType: repo.Fiat, }, }, + expectedAcc: 1, + expectedErr: nil, + }, + { // 9. handles conversions which reduce significant figures + value: &repo.CurrencyValue{ + Amount: big.NewInt(7654321), + Currency: repo.CurrencyDefinition{ + Name: "SimpleCoin", + Code: "SPC", + Divisibility: 4, + CurrencyType: repo.Crypto, + }, + }, + convertTo: repo.CurrencyDefinition{ + Name: "SimpleCoin", + Code: "SPC", + Divisibility: 2, + CurrencyType: repo.Crypto, + }, + exchangeRates: map[string]float64{ + "SPC": 1.0, + }, + expected: &repo.CurrencyValue{ + Amount: big.NewInt(76544), + Currency: repo.CurrencyDefinition{ + Name: "SimpleCoin", + Code: "SPC", + Divisibility: 2, + CurrencyType: repo.Crypto, + }, + }, + expectedAcc: 1, expectedErr: nil, }, } ) - for _, e := range examples { - actual, err := e.value.ConvertTo(e.convertTo, e.exchangeRate) + for i, e := range examples { + cc, err := factory.NewCurrencyConverter(reserveCurrency, e.exchangeRates) if err != nil { - if e.expectedErr != nil && !strings.Contains(err.Error(), *e.expectedErr) { - t.Errorf("expected value (%s) to error with (%s) but returned: %s", e.value, *e.expectedErr, err.Error()) + t.Errorf("failed to create currency converter: %s", err.Error()) + t.Logf("with rates: %v", e.exchangeRates) + continue + } + + actual, actualAcc, err := e.value.ConvertTo(e.convertTo, cc) + if err != nil { + if e.expectedErr != nil { + if !strings.Contains(err.Error(), *e.expectedErr) { + t.Errorf("expected value (%s) to error with (%s) but returned: %s", e.value, *e.expectedErr, err.Error()) + } + } else { + t.Errorf("unexpected error for example (%d): %s", i, err.Error()) } continue } else { if e.expectedErr != nil { t.Errorf("expected error (%s) but produced none", *e.expectedErr) - t.Logf("\tfor value: (%s) convertTo: (%s) rate: (%f)", e.value, e.convertTo, e.exchangeRate) + t.Logf("\texample: (%d) for value: (%s) convertTo: (%s) rates: (%v)", i, e.value, e.convertTo, e.exchangeRates) } } if !actual.Equal(e.expected) { t.Errorf("expected converted value to be %s, but was %s", e.expected, actual) - t.Logf("\tfor value: (%s) convertTo: (%s) rate: (%f)", e.value, e.convertTo, e.exchangeRate) + t.Logf("\texample: (%d) for value: (%s) convertTo: (%s) rates: (%v)", i, e.value, e.convertTo, e.exchangeRates) continue } + + if expectedAcc := big.Accuracy(e.expectedAcc); actualAcc != expectedAcc { + t.Errorf("expected converted accuracy to be %s, but was %s", expectedAcc.String(), actualAcc.String()) + t.Logf("\texample: (%d) for value: (%s) convertTo: (%s) rates: (%v)", i, e.value, e.convertTo, e.exchangeRates) + } + } +} + +func TestConvertUsingProtobufDef(t *testing.T) { + subject := factory.MustNewCurrencyValue("10", "USD") + subject.Currency.Divisibility = 2 + conv, err := factory.NewCurrencyConverter("BTC", map[string]float64{ + "USD": 2, + "BCH": 0.5, + }) + if err != nil { + t.Fatal(err) + } + convertTo := &pb.CurrencyDefinition{ + Code: "TBCH", + Divisibility: 8, + } + expected := &repo.CurrencyValue{ + Amount: big.NewInt(2500000), // 10 * (1/2 BTC/USD) * (1/2 BCH/BTC) * 1000000 (divisibility) + Currency: repo.CurrencyDefinition{ + Code: "TBCH", + CurrencyType: repo.Crypto, + Divisibility: 8, + }, + } + + cv, acc, err := subject.ConvertUsingProtobufDef(convertTo, conv) + if err != nil { + t.Fatal(err) + } + + if acc != big.Exact { + t.Errorf("expected result to be exact, but was (%s)", acc.String()) + } + + if !cv.Equal(expected) { + t.Errorf("expected result amount to be (%v), but was (%v)", expected, cv) + } +} + +func TestNewCurrencyValueWithLookup(t *testing.T) { + _, err := repo.NewCurrencyValueWithLookup("0", "") + if err == nil { + t.Errorf("expected empty code to return an error, but did not") + } + + _, err = repo.NewCurrencyValueWithLookup("0", "invalid") + if err == nil { + t.Errorf("expected invalid/undefined code to return an error, but did not") + } + + subject, err := repo.NewCurrencyValueWithLookup("", "USD") + if err != nil { + t.Errorf("expected empty value to be accepted, but returned error: %s", err.Error()) + } + if subject.String() != "0 United States Dollar (USDdiv2)" { + t.Errorf("expected empty value to be set as (0 United State Dollar (USDdiv2)), but was (%s)", subject.String()) + } + + _, err = repo.NewCurrencyValueWithLookup("1234567890987654321", "ETH") + if err != nil { + t.Errorf("expected large value to be accepted, but returned error: %s", err.Error()) + } +} + +func TestCurrencyValueAmount(t *testing.T) { + subject := &repo.CurrencyValue{} + actual := subject.AmountString() + if actual != "0" { + t.Errorf("expected zero value amount string to be (0), but was (%s)", actual) + } + + subject = &repo.CurrencyValue{Amount: big.NewInt(100)} + actual = subject.AmountString() + if actual != "100" { + t.Errorf("expected set value to be (%s), but was (%s)", "100", actual) + } +} + +func TestCurrencyValueAdjustDivisibility(t *testing.T) { + sameDiv := uint(8) + subject := factory.MustNewCurrencyValue("123000000", "BTC") + subject.Currency.Divisibility = sameDiv + + if newValue, _, err := subject.AdjustDivisibility(sameDiv); err != nil { + t.Fatalf("expected same divisibility to not return an error, but did: %s", err.Error()) + } else { + if !newValue.Currency.Equal(subject.Currency) { + t.Errorf("expected same divisibility to produce equal currencies, but did not") + } + } + + if newValue, _, err := subject.AdjustDivisibility(2); err != nil { + t.Fatalf("expected new divisibility to not return an error, but did: %s", err.Error()) + } else { + if newValue.Currency.Equal(subject.Currency) { + t.Errorf("expected new divisibility to produce different currency, but did not") + } + } +} + +func TestCurrencyValueCmp(t *testing.T) { + var examples = []struct { + subject *repo.CurrencyValue + other *repo.CurrencyValue + expected int + expectedErr error + }{ + { // success case + subject: factory.MustNewCurrencyValue("1234", "USD"), + other: factory.MustNewCurrencyValue("12345", "USD"), + expected: -1, // subject.Amount.Cmp(other.Amount) == -1 + }, + { // different divisibilities handled + subject: factory.MustNewCurrencyValueUsingDiv("1234", "USD", 2), + other: factory.MustNewCurrencyValueUsingDiv("123456", "USD", 4), + expected: -1, // subject.AdjustDivisibility(4).Amount.Cmp(other.Amount) == -1 + }, + { // different divisibilities (reverse suject/other) handled + subject: factory.MustNewCurrencyValueUsingDiv("123456", "USD", 4), + other: factory.MustNewCurrencyValueUsingDiv("1234", "USD", 2), + expected: 1, // subject.AdjustDivisibility(4).Amount.Cmp(other.Amount) == 1 + }, + { // different currencies return error + subject: factory.MustNewCurrencyValue("1234", "USD"), + other: factory.MustNewCurrencyValue("1234", "NOTUSD"), + expectedErr: repo.ErrCurrencyValueInvalidCmpDifferentCurrencies, + }, + } + + for _, e := range examples { + t.Logf("subject (%+v), other (%+v)", e.subject, e.other) + actual, err := e.subject.Cmp(e.other) + if e.expectedErr != nil { + if err != e.expectedErr { + t.Errorf("expected err (%s), but was (%s)", e.expectedErr.Error(), err.Error()) + } + } else { + if err != nil { + t.Errorf("unexpected err: %s", err) + continue + } + } + if e.expected != actual { + t.Errorf("expected comparison result (%d), but was (%d)", e.expected, actual) + } + } +} + +func TestCurrencyValueIsZero(t *testing.T) { + subject := factory.MustNewCurrencyValue("0", "BTC") + + subject.Amount = nil + if subject.IsZero() { + t.Errorf("expected IsZero to be false for (%s), but was not", subject) + } + subject.Amount = big.NewInt(0) + if !subject.IsZero() { + t.Errorf("expected IsZero to be true for (%s), but was not", subject) + } + subject.Amount = big.NewInt(-1) + if subject.IsZero() { + t.Errorf("expected IsZero to be false for (%s), but was not", subject) + } + subject.Amount = big.NewInt(1) + if subject.IsZero() { + t.Errorf("expected IsZero to be false for (%s), but was not", subject) + } +} + +func TestCurrencyValueIsNegative(t *testing.T) { + subject := factory.MustNewCurrencyValue("0", "BTC") + + subject.Amount = nil + if subject.IsNegative() { + t.Errorf("expected IsNegative to be false for (%s), but was not", subject) + } + subject.Amount = big.NewInt(0) + if subject.IsNegative() { + t.Errorf("expected IsNegative to be false for (%s), but was not", subject) + } + subject.Amount = big.NewInt(-1) + if !subject.IsNegative() { + t.Errorf("expected IsNegative to be true for (%s), but was not", subject) + } + subject.Amount = big.NewInt(1) + if subject.IsNegative() { + t.Errorf("expected IsNegative to be false for (%s), but was not", subject) + } +} + +func TestCurrencyValueAddBigFloatProduct(t *testing.T) { + var ( + subject = factory.MustNewCurrencyValue("100", "BTC") + examples = []struct { + example *big.Float + expected *repo.CurrencyValue + }{ + { // add zero + example: big.NewFloat(0.0), + expected: factory.MustNewCurrencyValue("100", "BTC"), + }, + { // add one percent + example: big.NewFloat(0.01), + expected: factory.MustNewCurrencyValue("101", "BTC"), + }, + { // add negative one percent + example: big.NewFloat(-0.01), + expected: factory.MustNewCurrencyValue("99", "BTC"), + }, + { // add double + example: big.NewFloat(2.0), + expected: factory.MustNewCurrencyValue("300", "BTC"), + }, + } + ) + + for _, e := range examples { + if actual := subject.AddBigFloatProduct(e.example); !actual.Equal(e.expected) { + t.Errorf("expected (%v) to be (%v), for (%s + (%s * (%s))", actual.AmountString(), e.expected.AmountString(), subject.AmountString(), subject.AmountString(), e.example.String()) + } + } + + if !subject.Equal(factory.MustNewCurrencyValue("100", "BTC")) { + t.Errorf("expected subject to not be mutated, but was") + } +} + +func TestCurrencyValueAddBigInt(t *testing.T) { + var ( + subject = factory.MustNewCurrencyValue("100", "BTC") + examples = []struct { + example *big.Int + expected *repo.CurrencyValue + }{ + { // add one + example: big.NewInt(1), + expected: factory.MustNewCurrencyValue("101", "BTC"), + }, + { // add negative one + example: big.NewInt(-1), + expected: factory.MustNewCurrencyValue("99", "BTC"), + }, + { // add zero + example: big.NewInt(0), + expected: factory.MustNewCurrencyValue("100", "BTC"), + }, + } + ) + + for _, e := range examples { + if actual := subject.AddBigInt(e.example); !actual.Equal(e.expected) { + t.Errorf("expected (%v) to be (%v), for (%s + %s)", actual.AmountString(), e.expected.AmountString(), subject.AmountString(), e.example.String()) + } + } + + if !subject.Equal(factory.MustNewCurrencyValue("100", "BTC")) { + t.Errorf("expected subject to not be mutated, but was") + } +} + +func TestCurrencyValueSubBigInt(t *testing.T) { + var ( + subject = factory.MustNewCurrencyValue("100", "BTC") + examples = []struct { + example *big.Int + expected *repo.CurrencyValue + }{ + { // sub one + example: big.NewInt(1), + expected: factory.MustNewCurrencyValue("99", "BTC"), + }, + { // sub negative one + example: big.NewInt(-1), + expected: factory.MustNewCurrencyValue("101", "BTC"), + }, + { // sub zero + example: big.NewInt(0), + expected: factory.MustNewCurrencyValue("100", "BTC"), + }, + } + ) + + for _, e := range examples { + if actual := subject.SubBigInt(e.example); !actual.Equal(e.expected) { + t.Errorf("expected (%v) to be (%v), for (%s + %s)", actual.AmountString(), e.expected.AmountString(), subject.AmountString(), e.example.String()) + } + } + + if !subject.Equal(factory.MustNewCurrencyValue("100", "BTC")) { + t.Errorf("expected subject to not be mutated, but was") + } +} + +func TestCurrencyValueMulBigInt(t *testing.T) { + var ( + subject = factory.MustNewCurrencyValue("100", "BTC") + examples = []struct { + example *big.Int + expected *repo.CurrencyValue + }{ + { // multiply zero + example: big.NewInt(0), + expected: factory.MustNewCurrencyValue("0", "BTC"), + }, + { // multiply 3 + example: big.NewInt(3), + expected: factory.MustNewCurrencyValue("300", "BTC"), + }, + } + ) + + for _, e := range examples { + if actual := subject.MulBigInt(e.example); !actual.Equal(e.expected) { + t.Errorf("expected (%v) to be (%v), for (%s * %s)", actual.AmountString(), e.expected.AmountString(), subject.AmountString(), e.example.String()) + } + } + + if !subject.Equal(factory.MustNewCurrencyValue("100", "BTC")) { + t.Errorf("expected subject to not be mutated, but was") } } diff --git a/repo/datastore.go b/repo/datastore.go index 4fa9412b39..2c51c28f79 100644 --- a/repo/datastore.go +++ b/repo/datastore.go @@ -2,14 +2,15 @@ package repo import ( "database/sql" + "math/big" peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" "time" "github.com/OpenBazaar/wallet-interface" btc "github.com/btcsuite/btcutil" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" ) type Datastore interface { @@ -28,6 +29,7 @@ type Datastore interface { Coupons() CouponStore TxMetadata() TransactionMetadataStore ModeratedStores() ModeratedStore + Messages() MessageStore Ping() error Close() } @@ -47,7 +49,10 @@ type Config interface { Init(mnemonic string, identityKey []byte, password string, creationDate time.Time) error // Return the mnemonic string - GetMnemonic() (string, error) + GetMnemonic() (string, bool, error) + + // Update mnemonic in database - used to encrypt / decrypt it + UpdateMnemonic(string, bool) error // Return the identity key GetIdentityKey() ([]byte, error) @@ -161,16 +166,16 @@ type InventoryStore interface { /* Put an inventory count for a listing Override the existing count if it exists */ - Put(slug string, variantIndex int, count int64) error + Put(slug string, variantIndex int, count *big.Int) error // Return the count for a specific listing including variants - GetSpecific(slug string, variantIndex int) (int64, error) + GetSpecific(slug string, variantIndex int) (*big.Int, error) // Get the count for all variants of a given listing - Get(slug string) (map[int]int64, error) + Get(slug string) (map[int]*big.Int, error) // Fetch all inventory maps for each slug - GetAll() (map[string]map[int]int64, error) + GetAll() (map[string]map[int]*big.Int, error) // Delete a listing and related count Delete(slug string, variant int) error @@ -206,6 +211,9 @@ type PurchaseStore interface { // Return the metadata for all purchases. Also returns the original size of the query. GetAll(stateFilter []pb.OrderState, searchTerm string, sortByAscending bool, sortByRead bool, limit int, exclude []string) ([]Purchase, int, error) + // Return unfunded orders. + GetUnfunded() ([]UnfundedOrder, error) + // Return the number of purchases in the database Count() int @@ -251,11 +259,8 @@ type SaleStore interface { // Return the metadata for all sales. Also returns the original size of the query. GetAll(stateFilter []pb.OrderState, searchTerm string, sortByAscending bool, sortByRead bool, limit int, exclude []string) ([]Sale, int, error) - // Return unfunded orders which failed to detect funding because the chain was synced passed the block containing the transaction when the order was recorded. - GetNeedsResync() ([]UnfundedSale, error) - - // Set whether the given order needs a blockchain resync - SetNeedsResync(orderID string, needsResync bool) error + // Return unfunded orders. + GetUnfunded() ([]UnfundedOrder, error) // Return the number of sales in the database Count() int @@ -435,3 +440,21 @@ type WatchedScriptStore interface { Queryable wallet.WatchedScripts } + +// MessageStore is the messages table interface +type MessageStore interface { + Queryable + + // Save a new message + Put(messageID, orderID string, mType pb.Message_MessageType, peerID string, msg Message, err string, receivedAt int64, pubkey []byte) error + + // GetByOrderIDType returns the message for specified order and type + GetByOrderIDType(orderID string, mType pb.Message_MessageType) (*Message, string, error) + + // GetAllErrored returns the all messages with error + GetAllErrored() ([]OrderMessage, error) + + // MarkAsResolved sets the message as resolved and will no longer return + // with GetAllErrored + MarkAsResolved(OrderMessage) error +} diff --git a/repo/db/cases.go b/repo/db/cases.go index 69073db14d..9c0468060e 100644 --- a/repo/db/cases.go +++ b/repo/db/cases.go @@ -5,12 +5,13 @@ import ( "encoding/json" "errors" "fmt" + "math/big" "sync" "time" "github.com/OpenBazaar/jsonpb" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) type CasesDB struct { @@ -25,22 +26,22 @@ func (c *CasesDB) PutRecord(dispute *repo.DisputeCaseRecord) error { c.lock.Lock() defer c.lock.Unlock() + if dispute.PaymentCoin.String() == "" { + return errors.New("payment coin field is empty") + } + var readInt, buyerOpenedInt uint if dispute.IsBuyerInitiated { buyerOpenedInt = 1 } - tx, err := c.db.Begin() - if err != nil { - return err - } stm := `insert or replace into cases(caseID, state, read, timestamp, buyerOpened, claim, buyerPayoutAddress, vendorPayoutAddress, paymentCoin, coinType) values(?,?,?,?,?,?,?,?,?,?)` - stmt, err := tx.Prepare(stm) + stmt, err := c.PrepareQuery(stm) if err != nil { return err } - defer stmt.Close() + _, err = stmt.Exec( dispute.CaseID, int(dispute.OrderState), @@ -54,27 +55,24 @@ func (c *CasesDB) PutRecord(dispute *repo.DisputeCaseRecord) error { dispute.CoinType, ) if err != nil { - rErr := tx.Rollback() - if rErr != nil { - return fmt.Errorf("case put fail: %s\nand rollback failed: %s\n", err.Error(), rErr.Error()) - } - return err + return fmt.Errorf("update dispute case: %s", err.Error()) } - return tx.Commit() + return nil } func (c *CasesDB) Put(caseID string, state pb.OrderState, buyerOpened bool, claim string, paymentCoin string, coinType string) error { - def, err := repo.LoadCurrencyDefinitions().Lookup(paymentCoin) + def, err := repo.AllCurrencies().Lookup(paymentCoin) if err != nil { return fmt.Errorf("verifying paymentCoin: %s", err.Error()) } + cc := def.CurrencyCode() record := &repo.DisputeCaseRecord{ CaseID: caseID, Claim: claim, IsBuyerInitiated: buyerOpened, OrderState: state, - PaymentCoin: def.CurrencyCode(), + PaymentCoin: &cc, CoinType: coinType, Timestamp: time.Now(), } @@ -247,48 +245,65 @@ func (c *CasesDB) GetAll(stateFilter []pb.OrderState, searchTerm string, sortByA if buyerOpenedInt > 0 { buyerOpened = true } - var total uint64 + total := new(big.Int) var title, thumbnail, vendorId, vendorHandle, buyerId, buyerHandle string contract := new(pb.RicardianContract) err := jsonpb.UnmarshalString(string(buyerContract), contract) if err != nil { - jsonpb.UnmarshalString(string(vendorContract), contract) + err = jsonpb.UnmarshalString(string(vendorContract), contract) + if err != nil { + log.Errorf("Error unmarshaling case contract: %s", err) + continue + } } var slug string - if contract != nil { - if len(contract.VendorListings) > 0 { - slug = contract.VendorListings[0].Slug - if contract.VendorListings[0].VendorID != nil { - vendorId = contract.VendorListings[0].VendorID.PeerID - vendorHandle = contract.VendorListings[0].VendorID.Handle - } - if contract.VendorListings[0].Item != nil { - title = contract.VendorListings[0].Item.Title - if len(contract.VendorListings[0].Item.Images) > 0 { - thumbnail = contract.VendorListings[0].Item.Images[0].Tiny - } - } + if len(contract.VendorListings) > 0 { + slug = contract.VendorListings[0].Slug + if contract.VendorListings[0].VendorID != nil { + vendorId = contract.VendorListings[0].VendorID.PeerID + vendorHandle = contract.VendorListings[0].VendorID.Handle } - if contract.BuyerOrder != nil { - slug = contract.VendorListings[0].Slug - if contract.BuyerOrder.BuyerID != nil { - buyerId = contract.BuyerOrder.BuyerID.PeerID - buyerHandle = contract.BuyerOrder.BuyerID.Handle + if contract.VendorListings[0].Item != nil { + title = contract.VendorListings[0].Item.Title + if len(contract.VendorListings[0].Item.Images) > 0 { + thumbnail = contract.VendorListings[0].Item.Images[0].Tiny } - if contract.BuyerOrder.Payment != nil { - total = contract.BuyerOrder.Payment.Amount + } + + if contract.VendorListings[0].Metadata != nil && contract.VendorListings[0].Metadata.ContractType != pb.Listing_Metadata_CRYPTOCURRENCY { + coinType = "" + } + } + if contract.BuyerOrder != nil { + slug = contract.VendorListings[0].Slug + if contract.BuyerOrder.BuyerID != nil { + buyerId = contract.BuyerOrder.BuyerID.PeerID + buyerHandle = contract.BuyerOrder.BuyerID.Handle + } + if contract.BuyerOrder.Payment != nil { + if contract.BuyerOrder.Payment.BigAmount != "" { + total0, _ := new(big.Int).SetString(contract.BuyerOrder.Payment.BigAmount, 10) + total = total0 + } else { + total1 := new(big.Int).SetUint64(contract.BuyerOrder.Payment.Amount) + total = total1 } } } + cv, err := repo.NewCurrencyValueWithLookup(total.String(), paymentCoin) + if err != nil { + return nil, 0, err + } + ret = append(ret, repo.Case{ CaseId: caseID, Slug: slug, Timestamp: time.Unix(int64(timestamp), 0), Title: title, Thumbnail: thumbnail, - Total: total, + Total: *cv, VendorId: vendorId, VendorHandle: vendorHandle, BuyerId: buyerId, @@ -316,21 +331,24 @@ func (c *CasesDB) GetAll(stateFilter []pb.OrderState, searchTerm string, sortByA func (c *CasesDB) GetCaseMetadata(caseID string) (buyerContract, vendorContract *pb.RicardianContract, buyerValidationErrors, vendorValidationErrors []string, state pb.OrderState, read bool, timestamp time.Time, buyerOpened bool, claim string, resolution *pb.DisputeResolution, err error) { c.lock.Lock() defer c.lock.Unlock() - stmt, err := c.db.Prepare("select buyerContract, vendorContract, buyerValidationErrors, vendorValidationErrors, state, read, timestamp, buyerOpened, claim, disputeResolution from cases where caseID=?") + stmt, err := c.PrepareQuery("select buyerContract, vendorContract, buyerValidationErrors, vendorValidationErrors, state, read, timestamp, buyerOpened, claim, disputeResolution from cases where caseID=?") if err != nil { return nil, nil, []string{}, []string{}, pb.OrderState(0), false, time.Time{}, false, "", nil, err } defer stmt.Close() - var buyerCon []byte - var vendorCon []byte - var buyerErrors []byte - var vendorErrors []byte - var stateInt int - var readInt *int - var ts int - var buyerOpenedInt int - var disputResolution []byte - err = stmt.QueryRow(caseID).Scan(&buyerCon, &vendorCon, &buyerErrors, &vendorErrors, &stateInt, &readInt, &ts, &buyerOpenedInt, &claim, &disputResolution) + + var ( + buyerCon []byte + vendorCon []byte + buyerErrors []byte + vendorErrors []byte + stateInt int + readInt *int + ts int + buyerOpenedInt int + disputeResolution []byte + ) + err = stmt.QueryRow(caseID).Scan(&buyerCon, &vendorCon, &buyerErrors, &vendorErrors, &stateInt, &readInt, &ts, &buyerOpenedInt, &claim, &disputeResolution) if err != nil { return nil, nil, []string{}, []string{}, pb.OrderState(0), false, time.Time{}, false, "", nil, err } @@ -366,21 +384,21 @@ func (c *CasesDB) GetCaseMetadata(caseID string) (buyerContract, vendorContract if string(buyerErrors) != "" { err = json.Unmarshal(buyerErrors, &berr) if err != nil { - return nil, nil, []string{}, []string{}, pb.OrderState(0), false, time.Time{}, false, "", nil, err + return nil, nil, []string{}, []string{}, pb.OrderState(0), false, time.Time{}, false, "", nil, fmt.Errorf("unmarshal dispute case: %s", err.Error()) } } var verr []string if string(vendorErrors) != "" { err = json.Unmarshal(vendorErrors, &verr) if err != nil { - return nil, nil, []string{}, []string{}, pb.OrderState(0), false, time.Time{}, false, "", nil, err + return nil, nil, []string{}, []string{}, pb.OrderState(0), false, time.Time{}, false, "", nil, fmt.Errorf("unmarshal dispute vendor errors: %s", err.Error()) } } resolution = new(pb.DisputeResolution) - if string(disputResolution) != "" { - err = jsonpb.UnmarshalString(string(disputResolution), resolution) + if string(disputeResolution) != "" { + err = jsonpb.UnmarshalString(string(disputeResolution), resolution) if err != nil { - return nil, nil, []string{}, []string{}, pb.OrderState(0), false, time.Time{}, false, "", nil, err + return nil, nil, []string{}, []string{}, pb.OrderState(0), false, time.Time{}, false, "", nil, fmt.Errorf("unmarhsal dispute case resolution: %s", err.Error()) } } else { resolution = nil @@ -406,16 +424,18 @@ func (c *CasesDB) GetByCaseID(caseID string) (*repo.DisputeCaseRecord, error) { vendorOuts []byte ) - stmt, err := c.db.Prepare("select buyerContract, vendorContract, buyerPayoutAddress, vendorPayoutAddress, buyerOutpoints, vendorOutpoints, state, buyerOpened, timestamp, paymentCoin from cases where caseID=?") + stmt, err := c.PrepareQuery("select buyerContract, vendorContract, buyerPayoutAddress, vendorPayoutAddress, buyerOutpoints, vendorOutpoints, state, buyerOpened, timestamp, paymentCoin from cases where caseID=?") if err != nil { return nil, err } + defer stmt.Close() + err = stmt.QueryRow(caseID).Scan(&buyerCon, &vendorCon, &buyerAddr, &vendorAddr, &buyerOuts, &vendorOuts, &stateInt, &isBuyerInitiated, &createdAt, &paymentCoin) if err != nil { return nil, err } - def, err := repo.LoadCurrencyDefinitions().Lookup(paymentCoin) + def, err := repo.AllCurrencies().Lookup(paymentCoin) if err != nil { return nil, fmt.Errorf("validating payment coin: %s", err.Error()) } @@ -469,6 +489,7 @@ func (c *CasesDB) GetByCaseID(caseID string) (*repo.DisputeCaseRecord, error) { } return ret } + cc := def.CurrencyCode() return &repo.DisputeCaseRecord{ BuyerContract: brc, BuyerOutpoints: toPointer(buyerOutpointsOut), @@ -476,7 +497,7 @@ func (c *CasesDB) GetByCaseID(caseID string) (*repo.DisputeCaseRecord, error) { CaseID: caseID, IsBuyerInitiated: buyerInitiated, OrderState: pb.OrderState(stateInt), - PaymentCoin: def.CurrencyCode(), + PaymentCoin: &cc, Timestamp: time.Unix(createdAt, 0), VendorContract: vrc, VendorOutpoints: toPointer(vendorOutpointsOut), @@ -489,7 +510,10 @@ func (c *CasesDB) Count() int { defer c.lock.Unlock() row := c.db.QueryRow("select Count(*) from cases") var count int - row.Scan(&count) + err := row.Scan(&count) + if err != nil { + log.Error(err) + } return count } @@ -557,18 +581,24 @@ func (c *CasesDB) UpdateDisputesLastDisputeExpiryNotifiedAt(disputeCases []*repo c.lock.Lock() defer c.lock.Unlock() - tx, err := c.db.Begin() + tx, err := c.BeginTransaction() if err != nil { return fmt.Errorf("begin update disputes transaction: %s", err.Error()) } for _, d := range disputeCases { _, err = tx.Exec("update cases set lastDisputeExpiryNotifiedAt = ? where caseID = ?", int(d.LastDisputeExpiryNotifiedAt.Unix()), d.CaseID) if err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("update dispute case: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) + } return fmt.Errorf("update dispute case: %s", err.Error()) } } if err = tx.Commit(); err != nil { - return fmt.Errorf("commit update disputes transaction: %s", err.Error()) + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("commit dispute case: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) + } + return fmt.Errorf("commit disputes case: %s", err.Error()) } return nil diff --git a/repo/db/cases_test.go b/repo/db/cases_test.go index fedcb919e6..ec814698e1 100644 --- a/repo/db/cases_test.go +++ b/repo/db/cases_test.go @@ -13,11 +13,11 @@ import ( "github.com/OpenBazaar/jsonpb" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test/factory" ) func buildNewCaseStore() (repo.CaseStore, func(), error) { @@ -231,8 +231,12 @@ func TestMarkCaseAsUnread(t *testing.T) { func TestUpdateBuyerInfo(t *testing.T) { var ( casesdb, teardown, err = buildNewCaseStore() - buyerTestOutpoints = []*pb.Outpoint{{Hash: "hash1", Index: 0, Value: 5}} - contract = factory.NewContract() + buyerTestOutpoints = []*pb.Outpoint{{ + Hash: "hash1", + Index: 0, + BigValue: "5", + }} + contract = factory.NewContract() ) if err != nil { t.Fatal(err) @@ -275,8 +279,8 @@ func TestUpdateBuyerInfo(t *testing.T) { if string(buyerErrors) != `["someError","anotherError"]` { t.Errorf("Expected %s, got %s", `["someError","anotherError"]`, string(buyerErrors)) } - if string(buyerOuts) != `[{"hash":"hash1","value":5}]` { - t.Errorf("Expected %s got %s", `[{"hash":"hash1","value":5}]`, string(buyerOuts)) + if string(buyerOuts) != `[{"hash":"hash1","bigValue":"5"}]` { + t.Errorf("Expected %s got %s", `[{"hash":"hash1","bigValue":"5"}]`, string(buyerOuts)) } } @@ -284,7 +288,11 @@ func TestUpdateVendorInfo(t *testing.T) { var ( casesdb, teardown, err = buildNewCaseStore() contract = factory.NewContract() - vendorTestOutpoints = []*pb.Outpoint{{Hash: "hash2", Index: 1, Value: 11}} + vendorTestOutpoints = []*pb.Outpoint{{ + Hash: "hash2", + Index: 1, + BigValue: "11", + }} ) if err != nil { t.Fatal(err) @@ -327,8 +335,8 @@ func TestUpdateVendorInfo(t *testing.T) { if string(vendorErrors) != `["someError","anotherError"]` { t.Errorf("Expected %s, got %s", `["someError","anotherError"]`, string(vendorErrors)) } - if string(vendorOuts) != `[{"hash":"hash2","index":1,"value":11}]` { - t.Errorf("Expected %s got %s", `[{"hash":"hash2",index:1,value":11}]`, string(vendorOuts)) + if string(vendorOuts) != `[{"hash":"hash2","index":1,"bigValue":"11"}]` { + t.Errorf("Expected %s got %s", `[{"hash":"hash2",index:1,,"bigValue":"11"}]`, string(vendorOuts)) } } @@ -336,8 +344,16 @@ func TestCasesGetCaseMetaData(t *testing.T) { var ( casesdb, teardown, err = buildNewCaseStore() contract = factory.NewContract() - buyerTestOutpoints = []*pb.Outpoint{{Hash: "hash1", Index: 0, Value: 5}} - vendorTestOutpoints = []*pb.Outpoint{{Hash: "hash2", Index: 1, Value: 11}} + buyerTestOutpoints = []*pb.Outpoint{{ + Hash: "hash1", + Index: 0, + BigValue: "5", + }} + vendorTestOutpoints = []*pb.Outpoint{{ + Hash: "hash2", + Index: 1, + BigValue: "11", + }} ) if err != nil { t.Fatal(err) @@ -408,11 +424,19 @@ func TestCasesGetCaseMetaData(t *testing.T) { func TestGetByCaseID(t *testing.T) { var ( - expectedPaymentCoin = "BCH" - casesdb, teardown, err = buildNewCaseStore() - contract = factory.NewContract() - expectedBuyerOutpoints = []*pb.Outpoint{{Hash: "hash1", Index: 0, Value: 5}} - expectedVendorOutpoints = []*pb.Outpoint{{Hash: "hash2", Index: 1, Value: 11}} + expectedPaymentCoin = "BCH" + casesdb, teardown, err = buildNewCaseStore() + contract = factory.NewContract() + expectedBuyerOutpoints = []*pb.Outpoint{{ + Hash: "hash1", + Index: 0, + BigValue: "5", + }} + expectedVendorOutpoints = []*pb.Outpoint{{ + Hash: "hash2", + Index: 1, + BigValue: "11", + }} ) if err != nil { t.Fatal(err) @@ -459,8 +483,8 @@ func TestGetByCaseID(t *testing.T) { if o.Index != expectedBuyerOutpoints[i].Index { t.Errorf("Expected outpoint index %v got %v", o.Index, expectedBuyerOutpoints[i].Index) } - if o.Value != expectedBuyerOutpoints[i].Value { - t.Errorf("Expected outpoint value %v got %v", o.Value, expectedBuyerOutpoints[i].Value) + if o.BigValue != expectedBuyerOutpoints[i].BigValue { + t.Errorf("Expected outpoint value %v got %v", o.BigValue, expectedBuyerOutpoints[i].BigValue) } } if len(dispute.VendorOutpoints) != len(expectedVendorOutpoints) { @@ -473,8 +497,8 @@ func TestGetByCaseID(t *testing.T) { if o.Index != expectedVendorOutpoints[i].Index { t.Errorf("Expected outpoint index %v got %v", o.Index, expectedVendorOutpoints[i].Index) } - if o.Value != expectedVendorOutpoints[i].Value { - t.Errorf("Expected outpoint value %v got %v", o.Value, expectedVendorOutpoints[i].Value) + if o.BigValue != expectedVendorOutpoints[i].BigValue { + t.Errorf("Expected outpoint value %v got %v", o.BigValue, expectedVendorOutpoints[i].BigValue) } } if dispute.OrderState != pb.OrderState_DISPUTED { @@ -489,8 +513,16 @@ func TestMarkAsClosed(t *testing.T) { var ( casesdb, teardown, err = buildNewCaseStore() contract = factory.NewContract() - buyerTestOutpoints = []*pb.Outpoint{{Hash: "hash1", Index: 0, Value: 5}} - vendorTestOutpoints = []*pb.Outpoint{{Hash: "hash2", Index: 1, Value: 11}} + buyerTestOutpoints = []*pb.Outpoint{{ + Hash: "hash1", + Index: 0, + BigValue: "5", + }} + vendorTestOutpoints = []*pb.Outpoint{{ + Hash: "hash2", + Index: 1, + BigValue: "5", + }} ) if err != nil { t.Fatal(err) @@ -531,8 +563,16 @@ func TestCasesDB_GetAll(t *testing.T) { var ( casesdb, teardown, err = buildNewCaseStore() contract = factory.NewContract() - buyerTestOutpoints = []*pb.Outpoint{{Hash: "hash1", Index: 0, Value: 5}} - vendorTestOutpoints = []*pb.Outpoint{{Hash: "hash2", Index: 1, Value: 11}} + buyerTestOutpoints = []*pb.Outpoint{{ + Hash: "hash1", + Index: 0, + BigValue: "5", + }} + vendorTestOutpoints = []*pb.Outpoint{{ + Hash: "hash2", + Index: 1, + BigValue: "11", + }} ) if err != nil { t.Fatal(err) @@ -661,9 +701,10 @@ func TestGetDisputesForDisputeExpiryReturnsRelevantRecords(t *testing.T) { ShipTo: "Buyer Name", }, Payment: &pb.Order_Payment{ - Amount: 10, - Method: pb.Order_Payment_DIRECT, - Address: "3BDbGsH5h5ctDiFtWMmZawcf3E7iWirVms", + Method: pb.Order_Payment_DIRECT, + Address: "3BDbGsH5h5ctDiFtWMmZawcf3E7iWirVms", + BigAmount: "10", + AmountCurrency: &pb.CurrencyDefinition{Code: "BTC", Divisibility: 8}, }, Timestamp: nowData, } @@ -817,9 +858,10 @@ func TestGetDisputesForDisputeExpiryAllowsMissingContracts(t *testing.T) { ShipTo: "Buyer Name", }, Payment: &pb.Order_Payment{ - Amount: 10, - Method: pb.Order_Payment_DIRECT, - Address: "3BDbGsH5h5ctDiFtWMmZawcf3E7iWirVms", + BigAmount: "10", + AmountCurrency: &pb.CurrencyDefinition{Code: "BTC", Divisibility: 8}, + Method: pb.Order_Payment_DIRECT, + Address: "3BDbGsH5h5ctDiFtWMmZawcf3E7iWirVms", }, Timestamp: nowData, } @@ -985,8 +1027,9 @@ func TestCasesDB_Put_PaymentCoin(t *testing.T) { } contract.VendorListings[0].Metadata.AcceptedCurrencies = test.acceptedCurrencies - contract.BuyerOrder.Payment.Coin = test.paymentCoin - paymentCoin := repo.CurrencyCode(test.paymentCoin) + //contract.BuyerOrder.Payment.Coin = test.paymentCoin + paymentCoin := repo.CurrencyCode(test.paymentCoin) //repo.NewCurrencyCode(test.paymentCoin) + err = casesdb.PutRecord(&repo.DisputeCaseRecord{ CaseID: "paymentCoinTest", BuyerContract: contract, @@ -998,6 +1041,11 @@ func TestCasesDB_Put_PaymentCoin(t *testing.T) { t.Error(err) } + err = casesdb.UpdateBuyerInfo("paymentCoinTest", contract, nil, "", nil) + if err != nil { + t.Error(err) + } + cases, count, err := casesdb.GetAll(nil, "", false, false, 1, nil) if err != nil { t.Error(err) @@ -1014,30 +1062,55 @@ func TestCasesDB_Put_PaymentCoin(t *testing.T) { func TestCasesDB_Put_CoinType(t *testing.T) { var ( - testsCoins = []string{"TBTC", "TETH"} - contract = factory.NewContract() + contract = factory.NewContract() + testCoins = []struct { + coinType string + cryptoListing bool + }{ + { + "TBTC", + true, + }, + { + "TETH", + true, + }, + { + "TBCH", + false, + }, + } ) - for _, testCoin := range testsCoins { + for _, test := range testCoins { var casesdb, teardown, err = buildNewCaseStore() if err != nil { t.Fatal(err) } - contract.VendorListings[0].Metadata.CoinType = testCoin - paymentCoin := repo.CurrencyCode(testCoin) + paymentCoin := repo.CurrencyCode(test.coinType) + + if test.cryptoListing { + contract.VendorListings[0].Metadata.ContractType = pb.Listing_Metadata_CRYPTOCURRENCY + } else { + contract.VendorListings[0].Metadata.ContractType = pb.Listing_Metadata_PHYSICAL_GOOD + } err = casesdb.PutRecord(&repo.DisputeCaseRecord{ CaseID: "paymentCoinTest", BuyerContract: contract, VendorContract: contract, IsBuyerInitiated: true, - CoinType: testCoin, + CoinType: test.coinType, PaymentCoin: &paymentCoin, }) if err != nil { t.Error(err) } + err = casesdb.UpdateBuyerInfo("paymentCoinTest", contract, nil, "", nil) + if err != nil { + t.Error(err) + } cases, count, err := casesdb.GetAll(nil, "", false, false, 1, nil) if err != nil { @@ -1046,8 +1119,10 @@ func TestCasesDB_Put_CoinType(t *testing.T) { if count != 1 { t.Errorf(`Expected %d record got %d`, 1, count) } - if cases[0].CoinType != testCoin { - t.Errorf(`Expected %s got %s`, testCoin, cases[0].CoinType) + if test.cryptoListing && cases[0].CoinType != test.coinType { + t.Errorf(`Expected %s got %s`, test.coinType, cases[0].CoinType) + } else if !test.cryptoListing && cases[0].CoinType != "" { + t.Errorf(`Expected "" got %s`, cases[0].CoinType) } err = casesdb.Delete(cases[0].CaseId) if err != nil { diff --git a/repo/db/chat.go b/repo/db/chat.go index 4a102f932f..f3707d492a 100644 --- a/repo/db/chat.go +++ b/repo/db/chat.go @@ -2,11 +2,12 @@ package db import ( "database/sql" + "fmt" "strconv" "sync" "time" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type ChatDB struct { @@ -21,15 +22,19 @@ func (c *ChatDB) Put(messageId string, peerID string, subject string, message st c.lock.Lock() defer c.lock.Unlock() - tx, err := c.db.Begin() - if err != nil { - return err + // timestamp.UnixNano() is undefined when time has a zero value + if timestamp.IsZero() { + log.Warningf("putting chat message (%s): recieved zero timestamp, using current time", messageId) + timestamp = time.Now() } + stm := `insert into chat(messageID, peerID, subject, message, read, timestamp, outgoing) values(?,?,?,?,?,?,?)` - stmt, err := tx.Prepare(stm) + stmt, err := c.PrepareQuery(stm) if err != nil { - return err + return fmt.Errorf("prepare chat sql: %s", err.Error()) } + defer stmt.Close() + readInt := 0 if read { readInt = 1 @@ -40,21 +45,18 @@ func (c *ChatDB) Put(messageId string, peerID string, subject string, message st outgoingInt = 1 } - defer stmt.Close() _, err = stmt.Exec( messageId, peerID, subject, message, readInt, - int(timestamp.Unix()), + int(timestamp.UnixNano()), outgoingInt, ) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit chat: %s", err.Error()) } - tx.Commit() return nil } @@ -70,32 +72,40 @@ func (c *ChatDB) GetConversations() []repo.ChatConversation { } var ids []string for rows.Next() { - var peerID string - if err := rows.Scan(&peerID); err != nil { + var peerId string + if err := rows.Scan(&peerId); err != nil { continue } - ids = append(ids, peerID) + ids = append(ids, peerId) } defer rows.Close() - for _, peerID := range ids { - stm := "select Count(*) from chat where peerID='" + peerID + "' and read=0 and subject='' and outgoing=0;" - row := c.db.QueryRow(stm) - var count int - row.Scan(&count) - stm = "select max(timestamp), message, outgoing from chat where peerID='" + peerID + "' and subject=''" + for _, peerId := range ids { + var ( + count int + m string + ts int64 + outInt int + stm = "select Count(*) from chat where peerID='" + peerId + "' and read=0 and subject='' and outgoing=0;" + row = c.db.QueryRow(stm) + ) + err = row.Scan(&count) + if err != nil { + log.Error(err) + } + stm = "select max(timestamp), message, outgoing from chat where peerID='" + peerId + "' and subject=''" row = c.db.QueryRow(stm) - var m string - var ts int - var outInt int - row.Scan(&ts, &m, &outInt) + err = row.Scan(&ts, &m, &outInt) + if err != nil { + log.Error(err) + } outgoing := false if outInt > 0 { outgoing = true } - timestamp := time.Unix(int64(ts), 0) + timestamp := repo.NewAPITime(time.Unix(0, ts)) convo := repo.ChatConversation{ - PeerId: peerID, + PeerId: peerId, Unread: count, Last: m, Timestamp: timestamp, @@ -128,12 +138,14 @@ func (c *ChatDB) GetMessages(peerID string, subject string, offsetID string, lim return ret } for rows.Next() { - var msgID string - var pid string - var message string - var readInt int - var timestampInt int - var outgoingInt int + var ( + msgID string + pid string + message string + readInt int + timestampInt int64 + outgoingInt int + ) if err := rows.Scan(&msgID, &pid, &message, &readInt, ×tampInt, &outgoingInt); err != nil { continue } @@ -145,7 +157,7 @@ func (c *ChatDB) GetMessages(peerID string, subject string, offsetID string, lim if outgoingInt == 1 { outgoing = true } - timestamp := time.Unix(int64(timestampInt), 0) + timestamp := repo.NewAPITime(time.Unix(0, timestampInt)) chatMessage := repo.ChatMessage{ PeerId: pid, MessageId: msgID, @@ -168,84 +180,36 @@ func (c *ChatDB) MarkAsRead(peerID string, subject string, outgoing bool, messag if outgoing { outgoingInt = 1 } - var stmt *sql.Stmt - var tx *sql.Tx - var err error + + var ( + peerStm, messageStm string + updateArgs = []interface{}{subject, outgoingInt} + ) + if peerID != "" { + peerStm = " and peerID=?" + updateArgs = append(updateArgs, peerID) + } if messageId != "" { - stm := "select messageID from chat where peerID=? and subject=? and outgoing=? and read=0 and timestamp<=(select timestamp from chat where messageID=?) limit 1" - rows, err := c.db.Query(stm, peerID, subject, outgoingInt, messageId) - if err != nil { - return "", updated, err - } - if rows.Next() { - updated = true - } - rows.Close() - tx, err = c.db.Begin() - if err != nil { - return "", updated, err - } - stmt, err = tx.Prepare("update chat set read=1 where peerID=? and subject=? and outgoing=? and timestamp<=(select timestamp from chat where messageID=?)") - if err != nil { - return "", updated, err - } - _, err = stmt.Exec(peerID, subject, outgoingInt, messageId) - if err != nil { - return "", updated, err - } - } else { - var peerStm string - if peerID != "" { - peerStm = " and peerID=?" - } + messageStm = " and timestamp<=(select timestamp from chat where messageID=?)" + updateArgs = append(updateArgs, messageId) + } - stm := "select messageID from chat where subject=?" + peerStm + " and outgoing=? and read=0 limit 1" - var rows *sql.Rows - var err error - if peerID != "" { - rows, err = c.db.Query(stm, subject, peerID, outgoingInt) - } else { - rows, err = c.db.Query(stm, subject, outgoingInt) - } - if err != nil { - return "", updated, err - } - if rows.Next() { + result, err := c.db.Exec("update chat set read=1 where subject=? and outgoing=?"+peerStm+messageStm, updateArgs...) + if err != nil { + return "", false, fmt.Errorf("mark chat as read: %s", err) + } + if count, err := result.RowsAffected(); err != nil { + log.Error("mark chat as read: unable to determine rows affected, assuming not updated") + } else { + if count > 0 { updated = true } - rows.Close() - tx, err = c.db.Begin() - if err != nil { - return "", updated, err - } - stmt, err = tx.Prepare("update chat set read=1 where subject=?" + peerStm + " and outgoing=?") - if err != nil { - return "", updated, err - } - if peerID != "" { - _, err = stmt.Exec(subject, peerID, outgoingInt) - } else { - _, err = stmt.Exec(subject, outgoingInt) - } - if err != nil { - return "", updated, err - } } - defer stmt.Close() - if err != nil { - tx.Rollback() - return "", updated, err - } - tx.Commit() - - var peerStm string - if peerID != "" { - peerStm = " and peerID=?" - } + // get last message ID stmt2, err := c.db.Prepare("select max(timestamp), messageID from chat where subject=?" + peerStm + " and outgoing=?") if err != nil { - return "", updated, err + return "", updated, fmt.Errorf("prepare get last message id sql: %s", err.Error()) } defer stmt2.Close() var ( @@ -258,7 +222,7 @@ func (c *ChatDB) MarkAsRead(peerID string, subject string, outgoing bool, messag err = stmt2.QueryRow(subject, outgoingInt).Scan(×tamp, &msgId) } if err != nil { - return "", updated, err + return "", updated, fmt.Errorf("query get last message id: %s", err.Error()) } return msgId.String, updated, nil } @@ -277,13 +241,17 @@ func (c *ChatDB) GetUnreadCount(subject string) (int, error) { func (c *ChatDB) DeleteMessage(msgID string) error { c.lock.Lock() defer c.lock.Unlock() - c.db.Exec("delete from chat where messageID=?", msgID) + _, err := c.db.Exec("delete from chat where messageID=?", msgID) + if err != nil { + log.Error(err) + } return nil } -func (c *ChatDB) DeleteConversation(peerID string) error { +func (c *ChatDB) DeleteConversation(peerId string) error { c.lock.Lock() defer c.lock.Unlock() - c.db.Exec("delete from chat where peerID=? and subject=''", peerID) + _, err := c.db.Exec("delete from chat where peerId=? and subject=''", peerId) + log.Error(err) return nil } diff --git a/repo/db/chat_test.go b/repo/db/chat_test.go index d814c5695d..8235372fc6 100644 --- a/repo/db/chat_test.go +++ b/repo/db/chat_test.go @@ -1,13 +1,15 @@ package db_test import ( + "fmt" + "math/rand" "sync" "testing" "time" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func buildNewChatStore() (repo.ChatStore, func(), error) { @@ -257,8 +259,8 @@ func TestChatDB_MarkAsRead(t *testing.T) { t.Error(err) } messages := chdb.GetMessages("abc", "", "", -1) - if len(messages) == 0 { - t.Error("Returned incorrect number of messages") + if len(messages) != 2 { + t.Errorf("expected 2 messages, but found %d instead", len(messages)) return } last, updated, err := chdb.MarkAsRead("abc", "", true, "") @@ -335,7 +337,10 @@ func TestChatDB_MarkAsRead(t *testing.T) { for rows.Next() { var msgID string var read int - rows.Scan(&read, &msgID) + err = rows.Scan(&read, &msgID) + if err != nil { + t.Log(err) + } if msgID == "33333" && read == 0 { t.Error("Failed to set message as read") } @@ -456,3 +461,45 @@ func TestChatDB_DeleteConversation(t *testing.T) { } stmt.Close() } + +// https://github.com/phoreproject/pm-go/issues/1545 +func TestChatDB_DeterministicNanosecondOrdering_Issue1545(t *testing.T) { + var ( + numMessages = 10 + startTime = time.Now() + chdb, teardown, err = buildNewChatStore() + ) + if err != nil { + t.Fatal(err) + } + defer teardown() + + // send numMessages in a random order where + // msg index 0 has the earliest timetstamp and index numMessages has the latest + for _, msgID := range rand.Perm(numMessages) { + var ( + n = fmt.Sprintf("%d", msgID) + u = startTime.Add(time.Millisecond * time.Duration(msgID)) + ) + err = chdb.Put(n, "peerid", "subject", n, u, false, true) + if err != nil { + t.Fatal(err) + } + } + + messages := chdb.GetMessages("peerid", "subject", "", -1) + if len(messages) != numMessages { + t.Fatalf("expected %d messages, but got %d", numMessages, len(messages)) + return + } + // msgs should be in chronological order from most recent to oldest, thus never + // having an older time than the previous message + var latestTime = time.Now() + for _, m := range messages { + if m.Timestamp.After(latestTime) { + t.Fatalf("expected the messages to return in decending timestamp order, but were not") + t.Logf("\tmessages recieved: %+v", messages) + } + latestTime = m.Timestamp.Time + } +} diff --git a/repo/db/coupons.go b/repo/db/coupons.go index 3cf52f7c34..a7c51183c8 100644 --- a/repo/db/coupons.go +++ b/repo/db/coupons.go @@ -2,9 +2,10 @@ package db import ( "database/sql" + "fmt" "sync" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type CouponDB struct { @@ -18,17 +19,25 @@ func NewCouponStore(db *sql.DB, lock *sync.Mutex) repo.CouponStore { func (c *CouponDB) Put(coupons []repo.Coupon) error { c.lock.Lock() defer c.lock.Unlock() - tx, _ := c.db.Begin() + tx, _ := c.BeginTransaction() for _, coupon := range coupons { stmt, _ := tx.Prepare("insert or replace into coupons(slug, code, hash) values(?,?,?)") defer stmt.Close() + _, err := stmt.Exec(coupon.Slug, coupon.Code, coupon.Hash) if err != nil { - tx.Rollback() - return err + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("add coupon: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) + } + return fmt.Errorf("add coupon: %s", err.Error()) + } + } + if err := tx.Commit(); err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("commit coupon: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) } + return fmt.Errorf("commit coupon: %s", err.Error()) } - tx.Commit() return nil } @@ -47,8 +56,11 @@ func (c *CouponDB) Get(slug string) ([]repo.Coupon, error) { var slug string var code string var hash string - rows.Scan(&slug, &code, &hash) - ret = append(ret, repo.Coupon{slug, code, hash}) + err = rows.Scan(&slug, &code, &hash) + if err != nil { + log.Error(err) + } + ret = append(ret, repo.Coupon{Slug: slug, Code: code, Hash: hash}) } return ret, nil } diff --git a/repo/db/coupons_test.go b/repo/db/coupons_test.go index 03f9c3d926..3d61c4dcf7 100644 --- a/repo/db/coupons_test.go +++ b/repo/db/coupons_test.go @@ -4,9 +4,9 @@ import ( "sync" "testing" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func buildNewCouponStore() (repo.CouponStore, func(), error) { @@ -35,8 +35,8 @@ func TestPutCoupons(t *testing.T) { defer teardown() coupons := []repo.Coupon{ - {"slug", "code1", "hash1"}, - {"slug", "code2", "hash2"}, + {Slug: "slug", Code: "code1", Hash: "hash1"}, + {Slug: "slug", Code: "code2", Hash: "hash2"}, } err = couponDB.Put(coupons) if err != nil { @@ -54,8 +54,11 @@ func TestPutCoupons(t *testing.T) { var slug string var code string var hash string - rows.Scan(&slug, &code, &hash) - ret = append(ret, repo.Coupon{slug, code, hash}) + err = rows.Scan(&slug, &code, &hash) + if err != nil { + t.Log(err) + } + ret = append(ret, repo.Coupon{Slug: slug, Code: code, Hash: hash}) } if len(ret) != 2 { t.Error("Failed to return correct number of coupons") @@ -76,8 +79,8 @@ func TestGetCoupons(t *testing.T) { defer teardown() coupons := []repo.Coupon{ - {"s", "code1", "hash1"}, - {"s", "code2", "hash2"}, + {Slug: "s", Code: "code1", Hash: "hash1"}, + {Slug: "s", Code: "code2", Hash: "hash2"}, } err = couponDB.Put(coupons) if err != nil { @@ -106,8 +109,8 @@ func TestDeleteCoupons(t *testing.T) { defer teardown() coupons := []repo.Coupon{ - {"slug", "code1", "hash1"}, - {"slug", "code2", "hash2"}, + {Slug: "slug", Code: "code1", Hash: "hash1"}, + {Slug: "slug", Code: "code2", Hash: "hash2"}, } err = couponDB.Put(coupons) if err != nil { diff --git a/repo/db/db.go b/repo/db/db.go index eb610b7339..4199acfed9 100644 --- a/repo/db/db.go +++ b/repo/db/db.go @@ -2,6 +2,7 @@ package db import ( "database/sql" + "fmt" "path" "sync" "time" @@ -10,8 +11,8 @@ import ( _ "github.com/mutecomm/go-sqlcipher" "github.com/op/go-logging" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/schema" ) var log = logging.MustGetLogger("db") @@ -37,6 +38,7 @@ type SQLiteDatastore struct { coupons repo.CouponStore txMetadata repo.TransactionMetadataStore moderatedStores repo.ModeratedStore + messages repo.MessageStore db *sql.DB lock *sync.Mutex } @@ -54,7 +56,10 @@ func Create(repoPath, password string, testnet bool, coinType util.ExtCoinType) } if password != "" { p := "pragma key='" + password + "';" - conn.Exec(p) + _, err := conn.Exec(p) + if err != nil { + log.Error(err) + } } l := new(sync.Mutex) return NewSQLiteDatastore(conn, l, coinType), nil @@ -62,7 +67,7 @@ func Create(repoPath, password string, testnet bool, coinType util.ExtCoinType) func NewSQLiteDatastore(db *sql.DB, l *sync.Mutex, coinType util.ExtCoinType) *SQLiteDatastore { return &SQLiteDatastore{ - config: &ConfigDB{db: db, lock: l}, + config: &ConfigDB{modelStore{db: db, lock: l}}, followers: NewFollowerStore(db, l), following: NewFollowingStore(db, l), offlineMessages: NewOfflineMessageStore(db, l), @@ -82,6 +87,7 @@ func NewSQLiteDatastore(db *sql.DB, l *sync.Mutex, coinType util.ExtCoinType) *S coupons: NewCouponStore(db, l), txMetadata: NewTransactionMetadataStore(db, l), moderatedStores: NewModeratedStore(db, l), + messages: NewMessageStore(db, l), db: db, lock: l, } @@ -184,6 +190,11 @@ func (d *SQLiteDatastore) ModeratedStores() repo.ModeratedStore { return d.moderatedStores } +// Messages - return the messages datastore +func (d *SQLiteDatastore) Messages() repo.MessageStore { + return d.messages +} + func (d *SQLiteDatastore) Copy(dbPath string, password string) error { d.lock.Lock() defer d.lock.Unlock() @@ -232,8 +243,7 @@ func initDatabaseTables(db *sql.DB, password string) (err error) { } type ConfigDB struct { - db *sql.DB - lock *sync.Mutex + modelStore } func (c *ConfigDB) Init(mnemonic string, identityKey []byte, password string, creationDate time.Time) error { @@ -242,54 +252,99 @@ func (c *ConfigDB) Init(mnemonic string, identityKey []byte, password string, cr if err := initDatabaseTables(c.db, password); err != nil { return err } - tx, err := c.db.Begin() - if err != nil { - return err - } - stmt, err := tx.Prepare("insert into config(key, value) values(?,?)") + stmt, err := c.PrepareQuery("insert into config(key, value) values(?,?)") if err != nil { return err } defer stmt.Close() + _, err = stmt.Exec("mnemonic", mnemonic) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("set mnemonic: %s", err.Error()) } _, err = stmt.Exec("identityKey", identityKey) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("set identity key: %s", err.Error()) } _, err = stmt.Exec("creationDate", creationDate.Format(time.RFC3339)) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("set creation date: %s", err.Error()) } - tx.Commit() return nil } -func (c *ConfigDB) GetMnemonic() (string, error) { +func (c *ConfigDB) GetMnemonic() (string, bool, error) { c.lock.Lock() defer c.lock.Unlock() - stmt, err := c.db.Prepare("select value from config where key=?") + stmt, err := c.PrepareQuery("select value from config where key=?") if err != nil { log.Fatal(err) + return "", false, err } defer stmt.Close() var mnemonic string err = stmt.QueryRow("mnemonic").Scan(&mnemonic) if err != nil { - log.Fatal(err) + return "", false, err + } + + // is mnemonic locked + isMnemonicEncryptedStmt, err := c.PrepareQuery("select value from config where key=?") + if err != nil { + return "", false, err + } + defer isMnemonicEncryptedStmt.Close() + var isMnemonicEncrypted sql.NullString + err = isMnemonicEncryptedStmt.QueryRow("isMnemonicEncrypted").Scan(&isMnemonicEncrypted) + + if isMnemonicEncrypted.Valid { + return mnemonic, isMnemonicEncrypted.String == "1", nil + } else if err == sql.ErrNoRows { + return mnemonic, false, nil + } + + return mnemonic, false, err +} + +func (c *ConfigDB) UpdateMnemonic(mnemonic string, isEncrypted bool) error { + c.lock.Lock() + defer c.lock.Unlock() + + tx, err := c.BeginTransaction() + if err != nil { + return err + } + + stmt, err := tx.Prepare("insert or replace into config(key, value) values(?,?)") + if err != nil { + return err + } + defer stmt.Close() + + _, err = stmt.Exec("mnemonic", mnemonic) + if err != nil { + rollbackErr := tx.Rollback() + if rollbackErr != nil { + log.Error(rollbackErr) + } + return err } - return mnemonic, nil + _, err = stmt.Exec("isMnemonicEncrypted", isEncrypted) + if err != nil { + rollbackErr := tx.Rollback() + if rollbackErr != nil { + log.Error(rollbackErr) + } + return err + } + + return tx.Commit() } func (c *ConfigDB) GetIdentityKey() ([]byte, error) { c.lock.Lock() defer c.lock.Unlock() - stmt, err := c.db.Prepare("select value from config where key=?") + stmt, err := c.PrepareQuery("select value from config where key=?") if err != nil { return nil, err } @@ -306,7 +361,7 @@ func (c *ConfigDB) GetCreationDate() (time.Time, error) { c.lock.Lock() defer c.lock.Unlock() var t time.Time - stmt, err := c.db.Prepare("select value from config where key=?") + stmt, err := c.PrepareQuery("select value from config where key=?") if err != nil { return t, err } @@ -323,6 +378,6 @@ func (c *ConfigDB) IsEncrypted() bool { c.lock.Lock() defer c.lock.Unlock() pwdCheck := "select count(*) from sqlite_master;" - _, err := c.db.Exec(pwdCheck) // Fails if wrong password is entered + _, err := c.ExecuteQuery(pwdCheck) // Fails if wrong password is entered return err != nil } diff --git a/repo/db/db_test.go b/repo/db/db_test.go index a2dc1baec0..8a89cb236b 100644 --- a/repo/db/db_test.go +++ b/repo/db/db_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/schema" ) func buildNewDatastore() (*SQLiteDatastore, func(), error) { @@ -64,7 +64,7 @@ func TestInit(t *testing.T) { t.Fatal(err) } - mn, err := testDB.Config().GetMnemonic() + mn, _, err := testDB.Config().GetMnemonic() if err != nil { t.Error(err) } diff --git a/repo/db/followers.go b/repo/db/followers.go index ba4c1d931c..436a43024a 100644 --- a/repo/db/followers.go +++ b/repo/db/followers.go @@ -2,10 +2,11 @@ package db import ( "database/sql" + "fmt" "strconv" "sync" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type FollowerDB struct { @@ -19,16 +20,16 @@ func NewFollowerStore(db *sql.DB, lock *sync.Mutex) repo.FollowerStore { func (f *FollowerDB) Put(follower string, proof []byte) error { f.lock.Lock() defer f.lock.Unlock() - tx, _ := f.db.Begin() - stmt, _ := tx.Prepare("insert into followers(peerID, proof) values(?,?)") + stmt, err := f.PrepareQuery("insert into followers(peerID, proof) values(?,?)") + if err != nil { + return fmt.Errorf("prepare followers sql: %s", err.Error()) + } defer stmt.Close() - _, err := stmt.Exec(follower, proof) + _, err = stmt.Exec(follower, proof) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("update followers: %s", err.Error()) } - tx.Commit() return nil } @@ -51,8 +52,11 @@ func (f *FollowerDB) Get(offsetID string, limit int) ([]repo.Follower, error) { for rows.Next() { var peerID string var proof []byte - rows.Scan(&peerID, &proof) - ret = append(ret, repo.Follower{peerID, proof}) + err = rows.Scan(&peerID, &proof) + if err != nil { + log.Error(err) + } + ret = append(ret, repo.Follower{PeerId: peerID, Proof: proof}) } return ret, nil } @@ -72,7 +76,10 @@ func (f *FollowerDB) Count() int { defer f.lock.Unlock() row := f.db.QueryRow("select Count(*) from followers") var count int - row.Scan(&count) + err := row.Scan(&count) + if err != nil { + log.Error(err) + } return count } diff --git a/repo/db/followers_test.go b/repo/db/followers_test.go index 3dfa6ea958..724d8b7c5c 100644 --- a/repo/db/followers_test.go +++ b/repo/db/followers_test.go @@ -6,9 +6,9 @@ import ( "sync" "testing" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func buildNewFollowerStore() (repo.FollowerStore, func(), error) { @@ -83,16 +83,34 @@ func TestCountFollowers(t *testing.T) { } defer teardown() - fdb.Put("abc", []byte("proof")) - fdb.Put("123", []byte("proof")) - fdb.Put("xyz", []byte("proof")) + err = fdb.Put("abc", []byte("proof")) + if err != nil { + t.Error(err) + } + err = fdb.Put("123", []byte("proof")) + if err != nil { + t.Error(err) + } + err = fdb.Put("xyz", []byte("proof")) + if err != nil { + t.Error(err) + } x := fdb.Count() if x != 3 { t.Errorf("Expected 3 got %d", x) } - fdb.Delete("abc") - fdb.Delete("123") - fdb.Delete("xyz") + err = fdb.Delete("abc") + if err != nil { + t.Error(err) + } + err = fdb.Delete("123") + if err != nil { + t.Error(err) + } + err = fdb.Delete("xyz") + if err != nil { + t.Error(err) + } } func TestDeleteFollower(t *testing.T) { @@ -102,15 +120,24 @@ func TestDeleteFollower(t *testing.T) { } defer teardown() - fdb.Put("abc", []byte("proof")) + err = fdb.Put("abc", []byte("proof")) + if err != nil { + t.Error(err) + } err = fdb.Delete("abc") if err != nil { t.Error(err) } - stmt, _ := fdb.PrepareQuery("select peerID from followers where peerID=?") + stmt, err := fdb.PrepareQuery("select peerID from followers where peerID=?") + if err != nil { + t.Log(err) + } defer stmt.Close() var follower string - stmt.QueryRow("abc").Scan(&follower) + err = stmt.QueryRow("abc").Scan(&follower) + if err != nil { + t.Log(err) + } if follower != "" { t.Error("Failed to delete follower") } @@ -124,7 +151,10 @@ func TestGetFollowers(t *testing.T) { defer teardown() for i := 0; i < 100; i++ { - fdb.Put(strconv.Itoa(i), []byte("proof")) + err = fdb.Put(strconv.Itoa(i), []byte("proof")) + if err != nil { + t.Log(err) + } } followers, err := fdb.Get("", 100) if err != nil { @@ -173,7 +203,10 @@ func TestFollowsMe(t *testing.T) { } defer teardown() - fdb.Put("abc", []byte("proof")) + err = fdb.Put("abc", []byte("proof")) + if err != nil { + t.Log(err) + } if !fdb.FollowsMe("abc") { t.Error("Follows Me failed to return correctly") } diff --git a/repo/db/following.go b/repo/db/following.go index 8f89475f2c..5953e87084 100644 --- a/repo/db/following.go +++ b/repo/db/following.go @@ -2,10 +2,11 @@ package db import ( "database/sql" + "fmt" "strconv" "sync" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type FollowingDB struct { @@ -19,15 +20,15 @@ func NewFollowingStore(db *sql.DB, lock *sync.Mutex) repo.FollowingStore { func (f *FollowingDB) Put(follower string) error { f.lock.Lock() defer f.lock.Unlock() - tx, _ := f.db.Begin() - stmt, _ := tx.Prepare("insert into following(peerID) values(?)") + stmt, err := f.PrepareQuery("insert into following(peerID) values(?)") + if err != nil { + return fmt.Errorf("prepare following sql: %s", err.Error()) + } defer stmt.Close() - _, err := stmt.Exec(follower) + _, err = stmt.Exec(follower) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit following: %s", err.Error()) } - tx.Commit() return nil } @@ -48,7 +49,10 @@ func (f *FollowingDB) Get(offsetID string, limit int) ([]string, error) { defer rows.Close() for rows.Next() { var peerID string - rows.Scan(&peerID) + err = rows.Scan(&peerID) + if err != nil { + log.Error(err) + } ret = append(ret, peerID) } return ret, nil @@ -69,7 +73,10 @@ func (f *FollowingDB) Count() int { defer f.lock.Unlock() row := f.db.QueryRow("select Count(*) from following") var count int - row.Scan(&count) + err := row.Scan(&count) + if err != nil { + log.Error(err) + } return count } diff --git a/repo/db/following_test.go b/repo/db/following_test.go index 4fd08f418b..82f32d05f8 100644 --- a/repo/db/following_test.go +++ b/repo/db/following_test.go @@ -5,9 +5,9 @@ import ( "sync" "testing" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func buildNewFollowingStore() (repo.FollowingStore, func(), error) { @@ -61,7 +61,10 @@ func TestPutDuplicateFollowing(t *testing.T) { } defer teardown() - fldb.Put("abc") + err = fldb.Put("abc") + if err != nil { + t.Error(err) + } err = fldb.Put("abc") if err == nil { t.Error("Expected unquire constriant error to be thrown") @@ -75,16 +78,34 @@ func TestCountFollowing(t *testing.T) { } defer teardown() - fldb.Put("abc") - fldb.Put("123") - fldb.Put("xyz") + err = fldb.Put("abc") + if err != nil { + t.Error(err) + } + err = fldb.Put("123") + if err != nil { + t.Error(err) + } + err = fldb.Put("xyz") + if err != nil { + t.Error(err) + } x := fldb.Count() if x != 3 { t.Errorf("Expected 3 got %d", x) } - fldb.Delete("abc") - fldb.Delete("123") - fldb.Delete("xyz") + err = fldb.Delete("abc") + if err != nil { + t.Error(err) + } + err = fldb.Delete("123") + if err != nil { + t.Error(err) + } + err = fldb.Delete("xyz") + if err != nil { + t.Error(err) + } } func TestDeleteFollowing(t *testing.T) { @@ -94,7 +115,10 @@ func TestDeleteFollowing(t *testing.T) { } defer teardown() - fldb.Put("abc") + err = fldb.Put("abc") + if err != nil { + t.Error(err) + } err = fldb.Delete("abc") if err != nil { t.Error(err) @@ -102,7 +126,10 @@ func TestDeleteFollowing(t *testing.T) { stmt, _ := fldb.PrepareQuery("select peerID from followers where peerID=?") defer stmt.Close() var follower string - stmt.QueryRow("abc").Scan(&follower) + err = stmt.QueryRow("abc").Scan(&follower) + if err != nil { + t.Log(err) + } if follower != "" { t.Error("Failed to delete follower") } @@ -116,7 +143,10 @@ func TestGetFollowing(t *testing.T) { defer teardown() for i := 0; i < 100; i++ { - fldb.Put(strconv.Itoa(i)) + err = fldb.Put(strconv.Itoa(i)) + if err != nil { + t.Error(err) + } } followers, err := fldb.Get("", 100) if err != nil { @@ -165,7 +195,10 @@ func TestIFollow(t *testing.T) { } defer teardown() - fldb.Put("abc") + err = fldb.Put("abc") + if err != nil { + t.Error(err) + } if !fldb.IsFollowing("abc") { t.Error("I follow failed to return correctly") } diff --git a/repo/db/inventory.go b/repo/db/inventory.go index c9a9b0ddef..170b1bb72c 100644 --- a/repo/db/inventory.go +++ b/repo/db/inventory.go @@ -4,10 +4,13 @@ import ( "crypto/sha256" "database/sql" "encoding/hex" + "errors" + "fmt" + "math/big" "strconv" "sync" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type InventoryDB struct { @@ -18,47 +21,48 @@ func NewInventoryStore(db *sql.DB, lock *sync.Mutex) repo.InventoryStore { return &InventoryDB{modelStore{db, lock}} } -func (i *InventoryDB) Put(slug string, variantIndex int, count int64) error { +func (i *InventoryDB) Put(slug string, variantIndex int, count *big.Int) error { i.lock.Lock() defer i.lock.Unlock() id := sha256.Sum256([]byte(slug + strconv.Itoa(variantIndex))) - tx, _ := i.db.Begin() - stmt, err := tx.Prepare("insert or replace into inventory(invID, slug, variantIndex, count) values(?,?,?,?)") + stmt, err := i.PrepareQuery("insert or replace into inventory(invID, slug, variantIndex, count) values(?,?,?,?)") if err != nil { - return err + return fmt.Errorf("prepare inventory sql: %s", err.Error()) } defer stmt.Close() - _, err = stmt.Exec(hex.EncodeToString(id[:]), slug, variantIndex, count) + _, err = stmt.Exec(hex.EncodeToString(id[:]), slug, variantIndex, count.String()) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("update inventory: %s", err.Error()) } - tx.Commit() return nil } -func (i *InventoryDB) GetSpecific(slug string, variantIndex int) (int64, error) { +func (i *InventoryDB) GetSpecific(slug string, variantIndex int) (*big.Int, error) { i.lock.Lock() defer i.lock.Unlock() stmt, err := i.db.Prepare("select count from inventory where slug=? and variantIndex=?") if err != nil { - return 0, err + return big.NewInt(0), err } defer stmt.Close() - var count int64 - err = stmt.QueryRow(slug, variantIndex).Scan(&count) + var countStr string + err = stmt.QueryRow(slug, variantIndex).Scan(&countStr) if err != nil { - return 0, err + return big.NewInt(0), err + } + count, ok := new(big.Int).SetString(countStr, 10) + if !ok { + return nil, errors.New("error parsing count") } return count, nil } -func (i *InventoryDB) Get(slug string) (map[int]int64, error) { +func (i *InventoryDB) Get(slug string) (map[int]*big.Int, error) { i.lock.Lock() defer i.lock.Unlock() - ret := make(map[int]int64) + ret := make(map[int]*big.Int) stmt, err := i.db.Prepare("select slug, variantIndex, count from inventory where slug=?") if err != nil { return ret, err @@ -71,19 +75,30 @@ func (i *InventoryDB) Get(slug string) (map[int]int64, error) { defer rows.Close() for rows.Next() { var slug string - var count int64 + var countStr string var variantIndex int - rows.Scan(&slug, &variantIndex, &count) + err = rows.Scan(&slug, &variantIndex, &countStr) + if err != nil { + log.Errorf("scanning inventory for (%s): %s", slug, err.Error()) + } + count, ok := new(big.Int).SetString(countStr, 10) + if !ok { + log.Errorf("scanning inventory for (%s): error parsing count", slug) + count = big.NewInt(0) + } ret[variantIndex] = count } + if err := rows.Err(); err != nil { + log.Errorf("scanning inventory for (%s): %s", slug, err.Error()) + } return ret, nil } -func (i *InventoryDB) GetAll() (map[string]map[int]int64, error) { +func (i *InventoryDB) GetAll() (map[string]map[int]*big.Int, error) { i.lock.Lock() defer i.lock.Unlock() - ret := make(map[string]map[int]int64) + ret := make(map[string]map[int]*big.Int) stm := "select slug, variantIndex, count from inventory" rows, err := i.db.Query(stm) if err != nil { @@ -92,12 +107,21 @@ func (i *InventoryDB) GetAll() (map[string]map[int]int64, error) { defer rows.Close() for rows.Next() { var slug string - var count int64 + var countStr string var variantIndex int - rows.Scan(&slug, &variantIndex, &count) + err = rows.Scan(&slug, &variantIndex, &countStr) + if err != nil { + log.Error(err) + } + count, ok := new(big.Int).SetString(countStr, 10) + if !ok { + log.Errorf("scanning inventory for (%s): error parsing count", slug) + count = big.NewInt(0) + } + m, ok := ret[slug] if !ok { - r := make(map[int]int64) + r := make(map[int]*big.Int) r[variantIndex] = count ret[slug] = r } else { diff --git a/repo/db/inventory_test.go b/repo/db/inventory_test.go index 162af1e550..4243837db6 100644 --- a/repo/db/inventory_test.go +++ b/repo/db/inventory_test.go @@ -1,22 +1,15 @@ package db_test import ( + "math/big" "sync" "testing" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) -//var ivdb repo.InventoryStore - -//func init() { -//conn, _ := sql.Open("sqlite3", ":memory:") -//initDatabaseTables(conn, "") -//ivdb = NewInventoryStore(conn, new(sync.Mutex)) -//} - func buildNewInventoryStore() (repo.InventoryStore, func(), error) { appSchema := schema.MustNewCustomSchemaManager(schema.SchemaContext{ DataPath: schema.GenerateTempPath(), @@ -42,7 +35,7 @@ func TestPutInventory(t *testing.T) { } defer teardown() - err = ivdb.Put("slug", 0, 5) + err = ivdb.Put("slug", 0, big.NewInt(5)) if err != nil { t.Error(err) } @@ -76,8 +69,11 @@ func TestPutReplaceInventory(t *testing.T) { } defer teardown() - ivdb.Put("slug", 0, 6) - err = ivdb.Put("slug", 0, 5) + err = ivdb.Put("slug", 0, big.NewInt(6)) + if err != nil { + t.Log(err) + } + err = ivdb.Put("slug", 0, big.NewInt(5)) if err != nil { t.Error("Error replacing inventory value") } @@ -90,9 +86,12 @@ func TestGetSpecificInventory(t *testing.T) { } defer teardown() - ivdb.Put("slug", 0, 5) + err = ivdb.Put("slug", 0, big.NewInt(5)) + if err != nil { + t.Log(err) + } count, err := ivdb.GetSpecific("slug", 0) - if err != nil || count != 5 { + if err != nil || count.Cmp(big.NewInt(5)) != 0 { t.Error("Error in inventory get") } _, err = ivdb.GetSpecific("xyz", 0) @@ -108,7 +107,10 @@ func TestDeleteInventory(t *testing.T) { } defer teardown() - ivdb.Put("slug", 0, 5) + err = ivdb.Put("slug", 0, big.NewInt(5)) + if err != nil { + t.Log(err) + } err = ivdb.Delete("slug", 0) if err != nil { t.Error(err) @@ -116,7 +118,10 @@ func TestDeleteInventory(t *testing.T) { stmt, _ := ivdb.PrepareQuery("select slug from inventory where slug=?") defer stmt.Close() var slug string - stmt.QueryRow("inventory").Scan(&slug) + err = stmt.QueryRow("inventory").Scan(&slug) + if err != nil { + t.Log(err) + } if slug != "" { t.Error("Failed to delete inventory") } @@ -129,8 +134,14 @@ func TestDeleteAllInventory(t *testing.T) { } defer teardown() - ivdb.Put("slug", 0, 5) - ivdb.Put("slug", 1, 10) + err = ivdb.Put("slug", 0, big.NewInt(5)) + if err != nil { + t.Log(err) + } + err = ivdb.Put("slug", 1, big.NewInt(10)) + if err != nil { + t.Log(err) + } err = ivdb.DeleteAll("slug") if err != nil { t.Error(err) @@ -138,7 +149,10 @@ func TestDeleteAllInventory(t *testing.T) { stmt, _ := ivdb.PrepareQuery("select slug from inventory where slug=?") defer stmt.Close() var slug string - stmt.QueryRow("slug").Scan(&slug) + err = stmt.QueryRow("slug").Scan(&slug) + if err != nil { + t.Log(err) + } if slug != "" { t.Error("Failed to delete inventory") } @@ -152,10 +166,16 @@ func TestGetAllInventory(t *testing.T) { defer teardown() for i := 0; i < 100; i++ { - ivdb.Put("slug1", i, int64(i)) + err = ivdb.Put("slug1", i, big.NewInt(int64(i))) + if err != nil { + t.Log(err) + } } for i := 0; i < 100; i++ { - ivdb.Put("slug2", i, int64(i)) + err = ivdb.Put("slug2", i, big.NewInt(int64(i))) + if err != nil { + t.Log(err) + } } inventory, err := ivdb.GetAll() if err != nil { @@ -180,7 +200,10 @@ func TestGetInventory(t *testing.T) { defer teardown() for i := 0; i < 100; i++ { - ivdb.Put("slug", i, int64(i)) + err = ivdb.Put("slug", i, big.NewInt(int64(i))) + if err != nil { + t.Log(err) + } } inventory, err := ivdb.Get("slug") if err != nil { diff --git a/repo/db/keys.go b/repo/db/keys.go index 8c03ec1d21..61d2915aa1 100644 --- a/repo/db/keys.go +++ b/repo/db/keys.go @@ -4,13 +4,14 @@ import ( "database/sql" "encoding/hex" "errors" + "fmt" "strconv" "sync" "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/btcec" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type KeysDB struct { @@ -25,64 +26,47 @@ func NewKeyStore(db *sql.DB, lock *sync.Mutex, coinType util.ExtCoinType) repo.K func (k *KeysDB) Put(scriptAddress []byte, keyPath wallet.KeyPath) error { k.lock.Lock() defer k.lock.Unlock() - tx, err := k.db.Begin() + stmt, err := k.PrepareQuery("insert into keys(coin, scriptAddress, purpose, keyIndex, used) values(?,?,?,?,?)") if err != nil { - return err - } - stmt, err := tx.Prepare("insert into keys(coin, scriptAddress, purpose, keyIndex, used) values(?,?,?,?,?)") - if err != nil { - return err + return fmt.Errorf("prepare key sql: %s", err.Error()) } defer stmt.Close() + _, err = stmt.Exec(k.coinType.CurrencyCode(), hex.EncodeToString(scriptAddress), int(keyPath.Purpose), keyPath.Index, 0) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit key: %s", err.Error()) } - tx.Commit() return nil } func (k *KeysDB) ImportKey(scriptAddress []byte, key *btcec.PrivateKey) error { k.lock.Lock() defer k.lock.Unlock() - tx, err := k.db.Begin() - if err != nil { - return err - } - stmt, err := tx.Prepare("insert into keys(coin, scriptAddress, purpose, used, key) values(?,?,?,?,?)") + stmt, err := k.PrepareQuery("insert into keys(coin, scriptAddress, purpose, used, key) values(?,?,?,?,?)") if err != nil { - return err + return fmt.Errorf("prepare key sql: %s", err.Error()) } defer stmt.Close() _, err = stmt.Exec(k.coinType.CurrencyCode(), hex.EncodeToString(scriptAddress), -1, 0, hex.EncodeToString(key.Serialize())) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit key: %s", err.Error()) } - tx.Commit() return nil } func (k *KeysDB) MarkKeyAsUsed(scriptAddress []byte) error { k.lock.Lock() defer k.lock.Unlock() - tx, err := k.db.Begin() + stmt, err := k.PrepareQuery("update keys set used=1 where scriptAddress=? and coin=?") if err != nil { - return err + return fmt.Errorf("prepare key sql: %s", err.Error()) } - stmt, err := tx.Prepare("update keys set used=1 where scriptAddress=? and coin=?") - if err != nil { - return err - } - defer stmt.Close() + _, err = stmt.Exec(hex.EncodeToString(scriptAddress), k.coinType.CurrencyCode()) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit key update: %s", err.Error()) } - tx.Commit() return nil } diff --git a/repo/db/keys_test.go b/repo/db/keys_test.go index 7b7cd013f8..b2e5bcccfb 100644 --- a/repo/db/keys_test.go +++ b/repo/db/keys_test.go @@ -1,32 +1,52 @@ -package db +package db_test import ( "bytes" "crypto/rand" - "database/sql" "encoding/hex" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" "sync" "testing" "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/btcec" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) -var kdb repo.KeyStore - -func init() { - conn, _ := sql.Open("sqlite3", ":memory:") - initDatabaseTables(conn, "") - kdb = NewKeyStore(conn, new(sync.Mutex), util.CoinTypePhore) +func buildNewKeyStore() (repo.KeyStore, func(), error) { + appSchema := schema.MustNewCustomSchemaManager(schema.SchemaContext{ + DataPath: schema.GenerateTempPath(), + TestModeEnabled: true, + }) + if err := appSchema.BuildSchemaDirectories(); err != nil { + return nil, nil, err + } + if err := appSchema.InitializeDatabase(); err != nil { + return nil, nil, err + } + database, err := appSchema.OpenDatabase() + if err != nil { + return nil, nil, err + } + return db.NewKeyStore(database, new(sync.Mutex), util.CoinTypePhore), appSchema.DestroySchemaDirectories, nil } func TestGetAll(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + for i := 0; i < 100; i++ { b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, i}) + _, err = rand.Read(b) + if err != nil { + t.Log(err) + } + err := kdb.Put(b, wallet.KeyPath{Purpose: wallet.EXTERNAL, Index: i}) if err != nil { t.Error(err) } @@ -38,8 +58,14 @@ func TestGetAll(t *testing.T) { } func TestPutKey(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + b := make([]byte, 32) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 0}) + err = kdb.Put(b, wallet.KeyPath{Purpose: wallet.EXTERNAL, Index: 0}) if err != nil { t.Error(err) } @@ -69,6 +95,12 @@ func TestPutKey(t *testing.T) { } func TestKeysDB_GetImported(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Error(err) @@ -91,6 +123,12 @@ func TestKeysDB_GetImported(t *testing.T) { } func TestImportKey(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Error(err) @@ -133,17 +171,31 @@ func TestImportKey(t *testing.T) { } func TestPutDuplicateKey(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + b := make([]byte, 32) - kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 0}) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 0}) + if err := kdb.Put(b, wallet.KeyPath{Purpose: wallet.EXTERNAL, Index: 0}); err != nil { + t.Fatal(err) + } + err = kdb.Put(b, wallet.KeyPath{Purpose: wallet.EXTERNAL, Index: 0}) if err == nil { t.Error("Expected duplicate key error") } } func TestMarkKeyAsUsed(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + b := make([]byte, 33) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 0}) + err = kdb.Put(b, wallet.KeyPath{Purpose: wallet.EXTERNAL, Index: 0}) if err != nil { t.Error(err) } @@ -168,11 +220,20 @@ func TestMarkKeyAsUsed(t *testing.T) { } func TestGetLastKeyIndex(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + var last []byte for i := 0; i < 100; i++ { b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, i}) + _, err = rand.Read(b) + if err != nil { + t.Log(err) + } + err := kdb.Put(b, wallet.KeyPath{Purpose: wallet.EXTERNAL, Index: i}) if err != nil { t.Error(err) } @@ -182,7 +243,10 @@ func TestGetLastKeyIndex(t *testing.T) { if err != nil || idx != 99 || used { t.Error("Failed to fetch correct last index") } - kdb.MarkKeyAsUsed(last) + err = kdb.MarkKeyAsUsed(last) + if err != nil { + t.Log(err) + } _, used, err = kdb.GetLastKeyIndex(wallet.EXTERNAL) if err != nil || !used { t.Error("Failed to fetch correct last index") @@ -190,9 +254,18 @@ func TestGetLastKeyIndex(t *testing.T) { } func TestGetPathForKey(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 15}) + _, err = rand.Read(b) + if err != nil { + t.Log(err) + } + err = kdb.Put(b, wallet.KeyPath{Purpose: wallet.EXTERNAL, Index: 15}) if err != nil { t.Error(err) } @@ -206,6 +279,12 @@ func TestGetPathForKey(t *testing.T) { } func TestGetKey(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Error(err) @@ -228,19 +307,37 @@ func TestGetKey(t *testing.T) { } func TestKeyNotFound(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + b := make([]byte, 32) - rand.Read(b) - _, err := kdb.GetPathForKey(b) + _, err = rand.Read(b) + if err != nil { + t.Log(err) + } + _, err = kdb.GetPathForKey(b) if err == nil { t.Error("Return key when it shouldn't have") } } func TestGetUnsed(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + for i := 0; i < 100; i++ { b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.INTERNAL, i}) + _, err = rand.Read(b) + if err != nil { + t.Log(err) + } + err := kdb.Put(b, wallet.KeyPath{Purpose: wallet.INTERNAL, Index: i}) if err != nil { t.Error(err) } @@ -255,24 +352,42 @@ func TestGetUnsed(t *testing.T) { } func TestGetLookaheadWindows(t *testing.T) { + var kdb, teardown, err = buildNewKeyStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + for i := 0; i < 100; i++ { b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, i}) + _, err = rand.Read(b) + if err != nil { + t.Log(err) + } + err := kdb.Put(b, wallet.KeyPath{Purpose: wallet.EXTERNAL, Index: i}) if err != nil { t.Error(err) } if i < 50 { - kdb.MarkKeyAsUsed(b) + err = kdb.MarkKeyAsUsed(b) + if err != nil { + t.Log(err) + } } b = make([]byte, 32) - rand.Read(b) - err = kdb.Put(b, wallet.KeyPath{wallet.INTERNAL, i}) + _, err = rand.Read(b) + if err != nil { + t.Log(err) + } + err = kdb.Put(b, wallet.KeyPath{Purpose: wallet.INTERNAL, Index: i}) if err != nil { t.Error(err) } if i < 50 { - kdb.MarkKeyAsUsed(b) + err = kdb.MarkKeyAsUsed(b) + if err != nil { + t.Log(err) + } } } windows := kdb.GetLookaheadWindows() diff --git a/repo/db/messages.go b/repo/db/messages.go new file mode 100644 index 0000000000..8d54b81600 --- /dev/null +++ b/repo/db/messages.go @@ -0,0 +1,141 @@ +package db + +import ( + "database/sql" + "fmt" + "sync" + "time" + + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" +) + +// MessagesDB represents the messages table +type MessagesDB struct { + modelStore +} + +// NewMessageStore return new MessagesDB +func NewMessageStore(db *sql.DB, lock *sync.Mutex) repo.MessageStore { + return &MessagesDB{modelStore{db, lock}} +} + +// Put will insert a record into the messages +func (o *MessagesDB) Put(messageID, orderID string, mType pb.Message_MessageType, peerID string, msg repo.Message, rErr string, receivedAt int64, pubkey []byte) error { + o.lock.Lock() + defer o.lock.Unlock() + + stm := `insert or replace into messages(messageID, orderID, message_type, message, peerID, err, received_at, pubkey, created_at) values(?,?,?,?,?,?,?,?,?)` + stmt, err := o.PrepareQuery(stm) + if err != nil { + return fmt.Errorf("prepare message sql: %s", err.Error()) + } + defer stmt.Close() + + msg0, err := msg.MarshalJSON() + if err != nil { + return fmt.Errorf("marshal message: %s", err.Error()) + } + + _, err = stmt.Exec( + messageID, + orderID, + int(mType), + msg0, + peerID, + rErr, + receivedAt, + pubkey, + time.Now().Unix(), + ) + if err != nil { + return fmt.Errorf("err inserting message: %s", err.Error()) + } + + return nil +} + +// GetByOrderIDType returns the message for the specified order and message type +func (o *MessagesDB) GetByOrderIDType(orderID string, mType pb.Message_MessageType) (*repo.Message, string, error) { + o.lock.Lock() + defer o.lock.Unlock() + var ( + msg0 []byte + peerID string + ) + + stmt, err := o.db.Prepare("select message, peerID from messages where orderID=? and message_type=?") + if err != nil { + return nil, "", err + } + err = stmt.QueryRow(orderID, mType).Scan(&msg0, &peerID) + if err != nil { + return nil, "", err + } + + msg := new(repo.Message) + + if len(msg0) > 0 { + err = msg.UnmarshalJSON(msg0) + if err != nil { + return nil, "", err + } + } + + return msg, peerID, nil +} + +// GetAllErrored returns all messages which have an error state +func (o *MessagesDB) GetAllErrored() ([]repo.OrderMessage, error) { + o.lock.Lock() + defer o.lock.Unlock() + + stmt := `select messageID, orderID, message_type, message, peerID, err, pubkey from messages where err != ""` + var ret []repo.OrderMessage + rows, err := o.db.Query(stmt) + if err != nil { + return ret, err + } + defer rows.Close() + + for rows.Next() { + var messageID, orderID, peerID, rErr string + var msg0, pkey []byte + var mType int32 + err = rows.Scan(&messageID, &orderID, &mType, &msg0, &peerID, &rErr, &pkey) + if err != nil { + log.Error(err) + } + ret = append(ret, repo.OrderMessage{ + PeerID: peerID, + MessageID: messageID, + OrderID: orderID, + MessageType: mType, + Message: msg0, + MsgErr: rErr, + PeerPubkey: pkey, + }) + } + return ret, nil +} + +// MarkAsResolved sets a provided message as resolved +func (o *MessagesDB) MarkAsResolved(m repo.OrderMessage) error { + var ( + stmt = `update messages set err = "" where messageID == ?` + msg = new(repo.Message) + ) + + if len(m.Message) > 0 { + err := msg.UnmarshalJSON(m.Message) + if err != nil { + log.Errorf("failed extracting message (%+v): %s", m, err.Error()) + return err + } + } + _, err := o.db.Exec(stmt, m.MessageID) + if err != nil { + return fmt.Errorf("marking msg (%s) as resolved: %s", m.MessageID, err.Error()) + } + return nil +} diff --git a/repo/db/messages_test.go b/repo/db/messages_test.go new file mode 100644 index 0000000000..db1f23e4b4 --- /dev/null +++ b/repo/db/messages_test.go @@ -0,0 +1,130 @@ +package db_test + +import ( + "errors" + "fmt" + "sync" + "testing" + + "github.com/golang/protobuf/ptypes/any" + + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test/factory" +) + +func buildNewMessageStore() (repo.MessageStore, func(), error) { + appSchema := schema.MustNewCustomSchemaManager(schema.SchemaContext{ + DataPath: schema.GenerateTempPath(), + TestModeEnabled: true, + }) + if err := appSchema.BuildSchemaDirectories(); err != nil { + return nil, nil, err + } + if err := appSchema.InitializeDatabase(); err != nil { + return nil, nil, err + } + database, err := appSchema.OpenDatabase() + if err != nil { + return nil, nil, err + } + return db.NewMessageStore(database, new(sync.Mutex)), appSchema.DestroySchemaDirectories, nil +} + +func TestMessageDB_Put(t *testing.T) { + SampleErr := errors.New("sample error") + var ( + messagesdb, teardown, err = buildNewMessageStore() + orderID = "orderID1" + mType = pb.Message_ORDER + payload = "sample message" + peerID = "jack" + recErr = SampleErr.Error() + ) + if err != nil { + t.Fatal(err) + } + defer teardown() + + msg := repo.Message{ + Msg: pb.Message{ + MessageType: mType, + Payload: &any.Any{Value: []byte(payload)}, + }, + } + + err = messagesdb.Put(fmt.Sprintf("%s-%d", orderID, mType), orderID, mType, peerID, msg, recErr, 0, nil) + if err != nil { + t.Error(err) + } + + retMsg, peer, err := messagesdb.GetByOrderIDType(orderID, mType) + if err != nil || retMsg == nil { + t.Error(err) + } + + if string(retMsg.GetPayload().Value) != payload { + t.Error("incorrect payload") + } + + if peer != peerID { + t.Error("incorrect peerID") + } +} + +func TestMessageDB_MarkAsResolved(t *testing.T) { + var ( + messagesdb, teardown, err = buildNewMessageStore() + orderID = "orderID1" + unexpectedOrderID = "unexpectedOrderID2" + msg = factory.NewMessageWithOrderPayload() + peerID = "QmSomepeerid" + recErr = "error message" + ) + if err != nil { + t.Fatal(err) + } + defer teardown() + + err = messagesdb.Put(fmt.Sprintf("%s-%d", orderID, msg.Msg.MessageType), orderID, msg.Msg.MessageType, peerID, msg, recErr, 0, nil) + if err != nil { + t.Fatal(err) + } + + err = messagesdb.Put(fmt.Sprintf("%s-%d", unexpectedOrderID, msg.Msg.MessageType), unexpectedOrderID, msg.Msg.MessageType, peerID, msg, "", 0, nil) + if err != nil { + t.Fatal(err) + } + + erroredMsgs, err := messagesdb.GetAllErrored() + if err != nil { + t.Fatal(err) + } + + if len(erroredMsgs) != 1 { + t.Errorf("expected one error message, but found (%d)", len(erroredMsgs)) + } + + actual := erroredMsgs[0] + if actual.PeerID != peerID { + t.Errorf("expected peerID (%s), but found (%s)", peerID, actual.PeerID) + } + if actual.OrderID != orderID { + t.Errorf("expected orderID (%s), but found (%s)", orderID, actual.OrderID) + } + + if err := messagesdb.MarkAsResolved(actual); err != nil { + t.Fatal(err) + } + + erroredMsgs, err = messagesdb.GetAllErrored() + if err != nil { + t.Fatal(err) + } + + if len(erroredMsgs) != 0 { + t.Errorf("expected no error messages, but found (%d)", len(erroredMsgs)) + } +} diff --git a/repo/db/moderatedstores.go b/repo/db/moderatedstores.go index c7cd4faac8..748c1abcdc 100644 --- a/repo/db/moderatedstores.go +++ b/repo/db/moderatedstores.go @@ -2,10 +2,11 @@ package db import ( "database/sql" + "fmt" "strconv" "sync" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type ModeratedDB struct { @@ -19,16 +20,16 @@ func NewModeratedStore(db *sql.DB, lock *sync.Mutex) repo.ModeratedStore { func (m *ModeratedDB) Put(peerId string) error { m.lock.Lock() defer m.lock.Unlock() - tx, _ := m.db.Begin() - stmt, _ := tx.Prepare("insert into moderatedstores(peerID) values(?)") - + stmt, err := m.PrepareQuery("insert into moderatedstores(peerID) values(?)") + if err != nil { + return fmt.Errorf("prepare moderated store sql: %s", err.Error()) + } defer stmt.Close() - _, err := stmt.Exec(peerId) + + _, err = stmt.Exec(peerId) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit moderated store: %s", err.Error()) } - tx.Commit() return nil } @@ -50,7 +51,10 @@ func (m *ModeratedDB) Get(offsetId string, limit int) ([]string, error) { for rows.Next() { var peerID string - rows.Scan(&peerID) + err = rows.Scan(&peerID) + if err != nil { + log.Error(err) + } ret = append(ret, peerID) } return ret, nil @@ -59,6 +63,9 @@ func (m *ModeratedDB) Get(offsetId string, limit int) ([]string, error) { func (m *ModeratedDB) Delete(follower string) error { m.lock.Lock() defer m.lock.Unlock() - m.db.Exec("delete from moderatedstores where peerID=?", follower) + _, err := m.db.Exec("delete from moderatedstores where peerID=?", follower) + if err != nil { + log.Error(err) + } return nil } diff --git a/repo/db/moderatedstores_test.go b/repo/db/moderatedstores_test.go index 95b4d5a5c1..4981d2d126 100644 --- a/repo/db/moderatedstores_test.go +++ b/repo/db/moderatedstores_test.go @@ -5,9 +5,9 @@ import ( "sync" "testing" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func buildNewModeratedStore() (repo.ModeratedStore, func(), error) { @@ -61,7 +61,10 @@ func TestModeratedDB_Put_Duplicate(t *testing.T) { } defer teardown() - modDB.Put("abc") + err = modDB.Put("abc") + if err != nil { + t.Log(err) + } err = modDB.Put("abc") if err == nil { t.Error("Expected unquire constriant error to be thrown") @@ -75,7 +78,10 @@ func TestModeratedDB_Delete(t *testing.T) { } defer teardown() - modDB.Put("abc") + err = modDB.Put("abc") + if err != nil { + t.Log(err) + } err = modDB.Delete("abc") if err != nil { t.Error(err) @@ -83,7 +89,10 @@ func TestModeratedDB_Delete(t *testing.T) { stmt, _ := modDB.PrepareQuery("select peerID from moderatedstores where peerID=?") defer stmt.Close() var peerId string - stmt.QueryRow("abc").Scan(&peerId) + err = stmt.QueryRow("abc").Scan(&peerId) + if err != nil { + t.Log(err) + } if peerId != "" { t.Error("Failed to delete moderated store") } @@ -97,7 +106,10 @@ func TestModeratedDB_Get(t *testing.T) { defer teardown() for i := 0; i < 100; i++ { - modDB.Put(strconv.Itoa(i)) + err = modDB.Put(strconv.Itoa(i)) + if err != nil { + t.Log(err) + } } stores, err := modDB.Get("", 100) if err != nil { diff --git a/repo/db/notifications.go b/repo/db/notifications.go index d3bfa0c606..0e29c1a660 100644 --- a/repo/db/notifications.go +++ b/repo/db/notifications.go @@ -9,7 +9,7 @@ import ( "sync" "time" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type NotficationsDB struct { @@ -117,7 +117,7 @@ func (n *NotficationsDB) GetAll(offsetID string, limit int, typeFilter []string) read = true } notification.IsRead = read - notification.CreatedAt = time.Unix(int64(timestampInt), 0).UTC() + notification.CreatedAt = repo.NewAPITime(time.Unix(int64(timestampInt), 0).UTC()) // END ret = append(ret, notification) @@ -134,19 +134,16 @@ func (n *NotficationsDB) GetAll(offsetID string, limit int, typeFilter []string) func (n *NotficationsDB) MarkAsRead(notifID string) error { n.lock.Lock() defer n.lock.Unlock() - tx, err := n.db.Begin() + stmt, err := n.PrepareQuery("update notifications set read=1 where notifID=?") if err != nil { - return err + return fmt.Errorf("prepare notification sql: %s", err.Error()) } - stmt, _ := tx.Prepare("update notifications set read=1 where notifID=?") - defer stmt.Close() + _, err = stmt.Exec(notifID) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit notification as read: %s", err.Error()) } - tx.Commit() return nil } diff --git a/repo/db/notifications_test.go b/repo/db/notifications_test.go index 1fb9952335..800179a4a4 100644 --- a/repo/db/notifications_test.go +++ b/repo/db/notifications_test.go @@ -6,9 +6,9 @@ import ( "testing" "time" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func newNotificationStore() (repo.NotificationStore, func(), error) { @@ -101,7 +101,7 @@ func TestNotficationsDB_Delete(t *testing.T) { } defer teardown() - n := repo.FollowNotification{"1", repo.NotifierTypeFollowNotification, "abc"} + n := repo.FollowNotification{ID: "1", Type: repo.NotifierTypeFollowNotification, PeerId: "abc"} err = notificationDb.PutRecord(repo.NewNotification(n, time.Now(), false)) if err != nil { t.Error(err) @@ -129,17 +129,17 @@ func TestNotficationsDB_GetAll(t *testing.T) { } defer teardown() - f := repo.FollowNotification{"1", repo.NotifierTypeFollowNotification, "abc"} + f := repo.FollowNotification{ID: "1", Type: repo.NotifierTypeFollowNotification, PeerId: "abc"} err = notificationDb.PutRecord(repo.NewNotification(f, time.Now(), false)) if err != nil { t.Error(err) } - u := repo.UnfollowNotification{"2", repo.NotifierTypeUnfollowNotification, "123"} + u := repo.UnfollowNotification{ID: "2", Type: repo.NotifierTypeUnfollowNotification, PeerId: "123"} err = notificationDb.PutRecord(repo.NewNotification(u, time.Now().Add(time.Second), false)) if err != nil { t.Error(err) } - u = repo.UnfollowNotification{"3", repo.NotifierTypeUnfollowNotification, "56778"} + u = repo.UnfollowNotification{ID: "3", Type: repo.NotifierTypeUnfollowNotification, PeerId: "56778"} err = notificationDb.PutRecord(repo.NewNotification(u, time.Now().Add(time.Second*2), false)) if err != nil { t.Error(err) @@ -188,7 +188,7 @@ func TestNotficationsDB_MarkAsRead(t *testing.T) { } defer teardown() - n := repo.FollowNotification{"5", repo.NotifierTypeFollowNotification, "abc"} + n := repo.FollowNotification{ID: "5", Type: repo.NotifierTypeFollowNotification, PeerId: "abc"} err = notificationDb.PutRecord(repo.NewNotification(n, time.Now(), false)) if err != nil { t.Error(err) @@ -219,12 +219,12 @@ func TestNotficationsDB_MarkAllAsRead(t *testing.T) { } defer teardown() - n := repo.FollowNotification{"6", repo.NotifierTypeFollowNotification, "abc"} + n := repo.FollowNotification{ID: "6", Type: repo.NotifierTypeFollowNotification, PeerId: "abc"} err = notificationDb.PutRecord(repo.NewNotification(n, time.Now(), false)) if err != nil { t.Error(err) } - n = repo.FollowNotification{"7", repo.NotifierTypeFollowNotification, "123"} + n = repo.FollowNotification{ID: "7", Type: repo.NotifierTypeFollowNotification, PeerId: "123"} err = notificationDb.PutRecord(repo.NewNotification(n, time.Now(), false)) if err != nil { t.Error(err) @@ -249,7 +249,7 @@ func TestNotificationDB_GetUnreadCount(t *testing.T) { } defer teardown() - n := repo.FollowNotification{"8", repo.NotifierTypeFollowNotification, "abc"} + n := repo.FollowNotification{ID: "8", Type: repo.NotifierTypeFollowNotification, PeerId: "abc"} err = notificationDb.PutRecord(repo.NewNotification(n, time.Now(), false)) if err != nil { t.Error(err) @@ -258,7 +258,7 @@ func TestNotificationDB_GetUnreadCount(t *testing.T) { if err != nil { t.Error(err) } - n = repo.FollowNotification{"9", repo.NotifierTypeFollowNotification, "xyz"} + n = repo.FollowNotification{ID: "9", Type: repo.NotifierTypeFollowNotification, PeerId: "xyz"} err = notificationDb.PutRecord(repo.NewNotification(n, time.Now(), false)) if err != nil { t.Error(err) diff --git a/repo/db/offinemessages.go b/repo/db/offinemessages.go index bf1c8371e2..f977a31ee3 100644 --- a/repo/db/offinemessages.go +++ b/repo/db/offinemessages.go @@ -2,10 +2,11 @@ package db import ( "database/sql" + "fmt" "sync" "time" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type OfflineMessagesDB struct { @@ -19,21 +20,16 @@ func NewOfflineMessageStore(db *sql.DB, lock *sync.Mutex) repo.OfflineMessageSto func (o *OfflineMessagesDB) Put(url string) error { o.lock.Lock() defer o.lock.Unlock() - tx, err := o.db.Begin() + stmt, err := o.PrepareQuery("insert into offlinemessages(url, timestamp) values(?,?)") if err != nil { - return err - } - stmt, err := tx.Prepare("insert into offlinemessages(url, timestamp) values(?,?)") - if err != nil { - return err + return fmt.Errorf("prepare offline message sql: %s", err.Error()) } defer stmt.Close() + _, err = stmt.Exec(url, int(time.Now().Unix())) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit offline message: %s", err.Error()) } - tx.Commit() return nil } @@ -75,7 +71,10 @@ func (o *OfflineMessagesDB) GetMessages() (map[string][]byte, error) { for rows.Next() { var url string var message []byte - rows.Scan(&url, &message) + err = rows.Scan(&url, &message) + if err != nil { + log.Error(err) + } ret[url] = message } return ret, nil diff --git a/repo/db/offlinemessages_test.go b/repo/db/offlinemessages_test.go index eef072ac27..617902c395 100644 --- a/repo/db/offlinemessages_test.go +++ b/repo/db/offlinemessages_test.go @@ -5,9 +5,9 @@ import ( "sync" "testing" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func buildNewOfflineMessageStore() (repo.OfflineMessageStore, func(), error) { diff --git a/repo/db/pointers.go b/repo/db/pointers.go index 9854730a01..35c1799371 100644 --- a/repo/db/pointers.go +++ b/repo/db/pointers.go @@ -2,18 +2,18 @@ package db import ( "database/sql" + "fmt" + "strconv" + "sync" + "time" ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" cid "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" ps "gx/ipfs/QmaCTz9RkrU13bm9kMB54f7atgqM4qkjDZpRwRoJiWXEqs/go-libp2p-peerstore" - "strconv" - "sync" - "time" - - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/repo" ) type PointersDB struct { @@ -27,25 +27,21 @@ func NewPointerStore(db *sql.DB, lock *sync.Mutex) repo.PointerStore { func (p *PointersDB) Put(pointer ipfs.Pointer) error { p.lock.Lock() defer p.lock.Unlock() - tx, err := p.db.Begin() + + stmt, err := p.PrepareQuery("insert into pointers(pointerID, key, address, cancelID, purpose, timestamp) values(?,?,?,?,?,?)") if err != nil { - return err - } - stmt, err := tx.Prepare("insert into pointers(pointerID, key, address, cancelID, purpose, timestamp) values(?,?,?,?,?,?)") - if err != nil { - return err + return fmt.Errorf("prepare pointer sql: %s", err.Error()) } defer stmt.Close() + var cancelID string if pointer.CancelID != nil { cancelID = pointer.CancelID.Pretty() } _, err = stmt.Exec(pointer.Value.ID.Pretty(), pointer.Cid.String(), pointer.Value.Addrs[0].String(), cancelID, pointer.Purpose, int(time.Now().Unix())) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit pointer: %s", err.Error()) } - tx.Commit() return nil } diff --git a/repo/db/pointers_test.go b/repo/db/pointers_test.go index 4d8bf96301..23fe6033d4 100644 --- a/repo/db/pointers_test.go +++ b/repo/db/pointers_test.go @@ -13,15 +13,18 @@ import ( "testing" "time" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func mustNewPointer() ipfs.Pointer { randBytes := make([]byte, 32) - rand.Read(randBytes) + _, err := rand.Read(randBytes) + if err != nil { + panic(err) + } h, err := multihash.Encode(randBytes, multihash.SHA2_256) if err != nil { panic(err) @@ -43,14 +46,14 @@ func mustNewPointer() ipfs.Pointer { panic(err) } return ipfs.Pointer{ - &k, - ps.PeerInfo{ + Cid: &k, + Value: ps.PeerInfo{ ID: id, Addrs: []ma.Multiaddr{maAddr}, }, - ipfs.MESSAGE, - time.Now(), - &cancelID, + Purpose: ipfs.MESSAGE, + Timestamp: time.Now(), + CancelID: &cancelID, } } @@ -115,7 +118,10 @@ func TestDeletePointer(t *testing.T) { defer teardown() pointer := mustNewPointer() - pdb.Put(pointer) + err = pdb.Put(pointer) + if err != nil { + t.Log(err) + } err = pdb.Delete(pointer.Value.ID) if err != nil { t.Error("Pointer delete failed") @@ -139,7 +145,10 @@ func TestDeleteAllPointers(t *testing.T) { p := mustNewPointer() p.Purpose = ipfs.MODERATOR - pdb.Put(p) + err = pdb.Put(p) + if err != nil { + t.Log(err) + } err = pdb.DeleteAll(ipfs.MODERATOR) if err != nil { t.Error("Pointer delete failed") @@ -162,7 +171,10 @@ func TestGetAllPointers(t *testing.T) { defer teardown() pointer := mustNewPointer() - pdb.Put(pointer) + err = pdb.Put(pointer) + if err != nil { + t.Log(err) + } pointers, err := pdb.GetAll() if err != nil { t.Error("Get all pointers returned error") @@ -190,22 +202,28 @@ func TestPointersDB_GetByPurpose(t *testing.T) { } defer teardown() - pdb.Put(mustNewPointer()) + err = pdb.Put(mustNewPointer()) + if err != nil { + t.Log(err) + } randBytes := make([]byte, 32) - rand.Read(randBytes) + _, err = rand.Read(randBytes) + if err != nil { + t.Log(err) + } h, _ := multihash.Encode(randBytes, multihash.SHA2_256) id, _ := peer.IDFromBytes(h) maAddr, _ := ma.NewMultiaddr("/ipfs/QmamudHQGtztShX7Nc9HcczehdpGGWpFBWu2JvKWcpELxr/") k, _ := cid.Decode("QmamudHQGtztShX7Nc9HcczehdpGGWpFBWu2JvKWcpELxr") m := ipfs.Pointer{ - &k, - ps.PeerInfo{ + Cid: &k, + Value: ps.PeerInfo{ ID: id, Addrs: []ma.Multiaddr{maAddr}, }, - ipfs.MODERATOR, - time.Now(), - nil, + Purpose: ipfs.MODERATOR, + Timestamp: time.Now(), + CancelID: nil, } err = pdb.Put(m) if err != nil { @@ -241,22 +259,28 @@ func TestPointersDB_Get(t *testing.T) { } defer teardown() - pdb.Put(mustNewPointer()) + err = pdb.Put(mustNewPointer()) + if err != nil { + t.Log(err) + } randBytes := make([]byte, 32) - rand.Read(randBytes) + _, err = rand.Read(randBytes) + if err != nil { + t.Log(err) + } h, _ := multihash.Encode(randBytes, multihash.SHA2_256) id, _ := peer.IDFromBytes(h) maAddr, _ := ma.NewMultiaddr("/ipfs/QmamudHQGtztShX7Nc9HcczehdpGGWpFBWu2JvKWcpELxr/") k, _ := cid.Decode("QmamudHQGtztShX7Nc9HcczehdpGGWpFBWu2JvKWcpELxr") m := ipfs.Pointer{ - &k, - ps.PeerInfo{ + Cid: &k, + Value: ps.PeerInfo{ ID: id, Addrs: []ma.Multiaddr{maAddr}, }, - ipfs.MODERATOR, - time.Now(), - nil, + Purpose: ipfs.MODERATOR, + Timestamp: time.Now(), + CancelID: nil, } err = pdb.Put(m) if err != nil { diff --git a/repo/db/purchases.go b/repo/db/purchases.go index 175f0740bb..798261c98b 100644 --- a/repo/db/purchases.go +++ b/repo/db/purchases.go @@ -4,14 +4,16 @@ import ( "database/sql" "encoding/json" "fmt" + "math/big" + "strings" "sync" "time" "github.com/OpenBazaar/jsonpb" "github.com/OpenBazaar/wallet-interface" btc "github.com/btcsuite/btcutil" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) type PurchasesDB struct { @@ -41,15 +43,12 @@ func (p *PurchasesDB) Put(orderID string, contract pb.RicardianContract, state p return err } - tx, err := p.db.Begin() - if err != nil { - return err - } stm := `insert or replace into purchases(orderID, contract, state, read, timestamp, total, thumbnail, vendorID, vendorHandle, title, shippingName, shippingAddress, paymentAddr, paymentCoin, coinType, funded, transactions, disputedAt) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,(select funded from purchases where orderID="` + orderID + `"),(select transactions from purchases where orderID="` + orderID + `"),?)` - stmt, err := tx.Prepare(stm) + stmt, err := p.db.Prepare(stm) if err != nil { return err } + defer stmt.Close() var ( paymentAddr, shippingName, shippingAddress string disputedAt int @@ -70,15 +69,17 @@ func (p *PurchasesDB) Put(orderID string, contract pb.RicardianContract, state p if dispute != nil { disputedAt = int(dispute.Timestamp.Seconds) } - - defer stmt.Close() + paymentCoin, err := PaymentCoinForContract(&contract) + if err != nil { + return err + } _, err = stmt.Exec( orderID, out, int(state), readInt, int(contract.BuyerOrder.Timestamp.Seconds), - int(contract.BuyerOrder.Payment.Amount), + contract.BuyerOrder.Payment.BigAmount, contract.VendorListings[0].Item.Images[0].Tiny, contract.VendorListings[0].VendorID.PeerID, handle, @@ -86,15 +87,14 @@ func (p *PurchasesDB) Put(orderID string, contract pb.RicardianContract, state p shippingName, shippingAddress, paymentAddr, - PaymentCoinForContract(&contract), + paymentCoin, CoinTypeForContract(&contract), disputedAt, ) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit purchase: %s", err.Error()) } - return tx.Commit() + return nil } func (p *PurchasesDB) MarkAsRead(orderID string) error { @@ -172,8 +172,9 @@ func (p *PurchasesDB) GetAll(stateFilter []pb.OrderState, searchTerm string, sor for rows.Next() { var orderID, title, thumbnail, vendorID, vendorHandle, shippingName, shippingAddr, coinType, paymentCoin string var contract []byte - var timestamp, total, stateInt, readInt int - if err := rows.Scan(&orderID, &contract, ×tamp, &total, &title, &thumbnail, &vendorID, &vendorHandle, &shippingName, &shippingAddr, &stateInt, &readInt, &coinType, &paymentCoin); err != nil { + var timestamp, stateInt, readInt int + totalStr := "" + if err := rows.Scan(&orderID, &contract, ×tamp, &totalStr, &title, &thumbnail, &vendorID, &vendorHandle, &shippingName, &shippingAddr, &stateInt, &readInt, &coinType, &paymentCoin); err != nil { return ret, 0, err } read := false @@ -190,17 +191,49 @@ func (p *PurchasesDB) GetAll(stateFilter []pb.OrderState, searchTerm string, sor if len(rc.VendorListings) > 0 { slug = rc.VendorListings[0].Slug } + + // Convert buyerOrder to v5 + v5order, err := repo.ToV5Order(rc.BuyerOrder, nil) + if err != nil { + return nil, 0, err + } + rc.BuyerOrder = v5order + if rc.BuyerOrder != nil && rc.BuyerOrder.Payment != nil && rc.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED { moderated = true } + if len(rc.VendorListings) > 0 && rc.VendorListings[0].Metadata != nil && rc.VendorListings[0].Metadata.ContractType != pb.Listing_Metadata_CRYPTOCURRENCY { + coinType = "" + } + + if totalStr == "" { + log.Warningf("the database total is empty when it should contain a value") + totalStr = rc.BuyerOrder.Payment.BigAmount + } + + if strings.Contains(totalStr, "e") { + flt, _, err := big.ParseFloat(totalStr, 10, 0, big.ToNearestEven) + if err != nil { + return nil, 0, err + } + var i = new(big.Int) + i, _ = flt.Int(i) + totalStr = i.String() + } + + cv, err := repo.NewCurrencyValueWithLookup(totalStr, paymentCoin) + if err != nil { + return nil, 0, err + } + ret = append(ret, repo.Purchase{ OrderId: orderID, Slug: slug, Timestamp: time.Unix(int64(timestamp), 0), Title: title, Thumbnail: thumbnail, - Total: uint64(total), + Total: *cv, VendorId: vendorID, VendorHandle: vendorHandle, ShippingName: shippingName, @@ -225,6 +258,45 @@ func (p *PurchasesDB) GetAll(stateFilter []pb.OrderState, searchTerm string, sor return ret, count, nil } +func (p *PurchasesDB) GetUnfunded() ([]repo.UnfundedOrder, error) { + p.lock.Lock() + defer p.lock.Unlock() + var ret []repo.UnfundedOrder + rows, err := p.db.Query(`select orderID, contract, timestamp, paymentAddr from purchases where state=?`, 1) + if err != nil { + return ret, err + } + defer rows.Close() + for rows.Next() { + var orderID, paymentAddr string + var timestamp int + var contractBytes []byte + err := rows.Scan(&orderID, &contractBytes, ×tamp, &paymentAddr) + if err != nil { + return ret, err + } + if timestamp > 0 { + rc := new(pb.RicardianContract) + err = jsonpb.UnmarshalString(string(contractBytes), rc) + if err != nil { + return ret, err + } + v5Order, err := repo.ToV5Order(rc.BuyerOrder, repo.AllCurrencies().Lookup) + if err != nil { + log.Errorf("failed converting contract buyer order to v5 schema: %s", err.Error()) + return nil, err + } + ret = append(ret, repo.UnfundedOrder{ + OrderId: orderID, + Timestamp: time.Unix(int64(timestamp), 0), + PaymentCoin: v5Order.Payment.AmountCurrency.Code, + PaymentAddress: paymentAddr, + }) + } + } + return ret, nil +} + func (p *PurchasesDB) GetByPaymentAddress(addr btc.Address) (*pb.RicardianContract, pb.OrderState, bool, []*wallet.TransactionRecord, error) { if addr == nil { return nil, pb.OrderState(0), false, nil, fmt.Errorf("unable to find purchase with nil payment address") @@ -301,13 +373,19 @@ func (p *PurchasesDB) GetByOrderId(orderId string) (*pb.RicardianContract, pb.Or if readInt != nil && *readInt == 1 { read = true } - def, err := repo.LoadCurrencyDefinitions().Lookup(paymentCoin) + def, err := repo.AllCurrencies().Lookup(paymentCoin) if err != nil { return nil, pb.OrderState(0), false, nil, false, nil, fmt.Errorf("validating payment coin: %s", err.Error()) } var records []*wallet.TransactionRecord - json.Unmarshal(serializedTransactions, &records) - return rc, pb.OrderState(stateInt), funded, records, read, def.CurrencyCode(), nil + if len(serializedTransactions) > 0 { + err = json.Unmarshal(serializedTransactions, &records) + if err != nil { + return nil, pb.OrderState(0), false, nil, false, nil, fmt.Errorf("unmarshal purchase transactions: %s", err.Error()) + } + } + cc := def.CurrencyCode() + return rc, pb.OrderState(stateInt), funded, records, read, &cc, nil } func (p *PurchasesDB) Count() int { @@ -315,7 +393,11 @@ func (p *PurchasesDB) Count() int { defer p.lock.Unlock() row := p.db.QueryRow("select Count(*) from purchases") var count int - row.Scan(&count) + err := row.Scan(&count) + if err != nil { + log.Errorf("failed scanning purchase count: %s", err.Error()) + return 0 + } return count } @@ -423,17 +505,23 @@ func (p *PurchasesDB) UpdatePurchasesLastDisputeTimeoutNotifiedAt(purchases []*r p.lock.Lock() defer p.lock.Unlock() - tx, err := p.db.Begin() + tx, err := p.BeginTransaction() if err != nil { return fmt.Errorf("begin update purchase transaction: %s", err.Error()) } for _, p := range purchases { _, err = tx.Exec("update purchases set lastDisputeTimeoutNotifiedAt = ? where orderID = ?", int(p.LastDisputeTimeoutNotifiedAt.Unix()), p.OrderID) if err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("update purchase: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) + } return fmt.Errorf("update purchase: %s", err.Error()) } } if err = tx.Commit(); err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("commit purchase: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) + } return fmt.Errorf("commit update purchase transaction: %s", err.Error()) } @@ -448,17 +536,23 @@ func (p *PurchasesDB) UpdatePurchasesLastDisputeExpiryNotifiedAt(purchases []*re p.lock.Lock() defer p.lock.Unlock() - tx, err := p.db.Begin() + tx, err := p.BeginTransaction() if err != nil { return fmt.Errorf("begin update purchase transaction: %s", err.Error()) } for _, p := range purchases { _, err = tx.Exec("update purchases set lastDisputeExpiryNotifiedAt = ? where orderID = ?", int(p.LastDisputeExpiryNotifiedAt.Unix()), p.OrderID) if err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("update purchase error: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) + } return fmt.Errorf("update purchase: %s", err.Error()) } } if err = tx.Commit(); err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("commit purchase error: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) + } return fmt.Errorf("commit update purchase transaction: %s", err.Error()) } diff --git a/repo/db/purchases_test.go b/repo/db/purchases_test.go index 66e99db18d..12cd620b91 100644 --- a/repo/db/purchases_test.go +++ b/repo/db/purchases_test.go @@ -2,6 +2,7 @@ package db_test import ( "reflect" + "strconv" "sync" "testing" "time" @@ -11,11 +12,11 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test/factory" ) func buildNewPurchaseStore() (repo.PurchaseStore, func(), error) { @@ -74,7 +75,7 @@ func TestPutPurchase(t *testing.T) { var state int var read int var date int - var total int + var total string var thumbnail string var vendorID string var vendorHandle string @@ -97,8 +98,8 @@ func TestPutPurchase(t *testing.T) { if date != int(contract.BuyerOrder.Timestamp.Seconds) { t.Errorf("Expected %d got %d", int(contract.BuyerOrder.Timestamp.Seconds), date) } - if total != int(contract.BuyerOrder.Payment.Amount) { - t.Errorf("Expected %d got %d", int(contract.BuyerOrder.Payment.Amount), total) + if total != contract.BuyerOrder.Payment.BigAmount { + t.Errorf("Expected %s got %s", contract.BuyerOrder.Payment.BigAmount, total) } if thumbnail != contract.VendorListings[0].Item.Images[0].Tiny { t.Errorf("Expected %s got %s", contract.VendorListings[0].Item.Images[0].Tiny, thumbnail) @@ -128,7 +129,10 @@ func TestDeletePurchase(t *testing.T) { defer teardown() contract := factory.NewContract() - purdb.Put("orderID", *contract, 0, false) + err = purdb.Put("orderID", *contract, 0, false) + if err != nil { + t.Log(err) + } err = purdb.Delete("orderID") if err != nil { t.Error("Purchase delete failed") @@ -155,7 +159,10 @@ func TestMarkPurchaseAsRead(t *testing.T) { defer teardown() contract := factory.NewContract() - purdb.Put("orderID", *contract, 0, false) + err = purdb.Put("orderID", *contract, 0, false) + if err != nil { + t.Log(err) + } err = purdb.MarkAsRead("orderID") if err != nil { t.Error(err) @@ -181,7 +188,10 @@ func TestMarkPurchaseAsUnread(t *testing.T) { defer teardown() contract := factory.NewContract() - purdb.Put("orderID", *contract, 0, false) + err = purdb.Put("orderID", *contract, 0, false) + if err != nil { + t.Log(err) + } err = purdb.MarkAsRead("orderID") if err != nil { t.Error(err) @@ -300,7 +310,10 @@ func TestPurchasesGetByPaymentAddress(t *testing.T) { defer teardown() contract := factory.NewContract() - purdb.Put("orderID", *contract, 0, false) + err = purdb.Put("orderID", *contract, 0, false) + if err != nil { + t.Log(err) + } addr, err := btcutil.DecodeAddress(contract.BuyerOrder.Payment.Address, &chaincfg.MainNetParams) if err != nil { t.Error(err) @@ -336,7 +349,7 @@ func TestPurchasesGetByOrderId(t *testing.T) { } contract := factory.NewContract() - contract.BuyerOrder.Payment.Coin = expectedCoin + //contract.BuyerOrder.Payment.Coin = expectedCoin if err := purdb.Put("orderID", *contract, 0, false); err != nil { t.Fatal(err) } @@ -360,15 +373,24 @@ func TestPurchasesDB_GetAll(t *testing.T) { c0 := factory.NewContract() ts, _ := ptypes.TimestampProto(time.Now()) c0.BuyerOrder.Timestamp = ts - purdb.Put("orderID", *c0, 0, false) + err = purdb.Put("orderID", *c0, 0, false) + if err != nil { + t.Log(err) + } c1 := factory.NewContract() ts, _ = ptypes.TimestampProto(time.Now().Add(time.Minute)) c1.BuyerOrder.Timestamp = ts - purdb.Put("orderID2", *c1, 1, false) + err = purdb.Put("orderID2", *c1, 1, false) + if err != nil { + t.Log(err) + } c2 := factory.NewContract() ts, _ = ptypes.TimestampProto(time.Now().Add(time.Hour)) c2.BuyerOrder.Timestamp = ts - purdb.Put("orderID3", *c2, 1, false) + err = purdb.Put("orderID3", *c2, 1, false) + if err != nil { + t.Log(err) + } // Test no offset no limit purchases, ct, err := purdb.GetAll([]pb.OrderState{}, "", false, false, -1, []string{}) if err != nil { @@ -454,6 +476,51 @@ func TestPurchasesDB_GetAll(t *testing.T) { } } +func TestPurchasesDB_GetUnfunded(t *testing.T) { + var purdb, teardown, err = buildNewPurchaseStore() + if err != nil { + t.Fatal(err) + } + defer teardown() + + contract := factory.NewContract() + if err := purdb.Put("orderID", *contract, 1, false); err != nil { + t.Fatal(err) + } + if err := purdb.Put("orderID1", *contract, 1, false); err != nil { + t.Fatal(err) + } + if err := purdb.Put("x0", *contract, 0, false); err != nil { + t.Fatal(err) + } + for i := 2; i < 15; i++ { + if err := purdb.Put("x"+strconv.Itoa(i), *contract, pb.OrderState(i), false); err != nil { + t.Fatal(err) + } + } + unfunded, err := purdb.GetUnfunded() + if err != nil { + t.Error(err) + } + if len(unfunded) != 2 { + t.Error("Return incorrect number of unfunded orders") + } + var a, b bool + for _, uf := range unfunded { + if uf.OrderId == "orderID" { + a = true + } else if uf.OrderId == "orderID1" { + b = true + } + if uf.PaymentAddress != contract.BuyerOrder.Payment.Address { + t.Errorf("Incorrect payment address. Expected %s, got %s", contract.BuyerOrder.Payment.Address, uf.PaymentAddress) + } + } + if !a || !b { + t.Error("Failed to return correct unfunded orders") + } +} + func TestGetPurchasesForDisputeTimeoutReturnsRelevantRecords(t *testing.T) { appSchema := schema.MustNewCustomSchemaManager(schema.SchemaContext{ DataPath: schema.GenerateTempPath(), @@ -866,7 +933,6 @@ func TestPurchasesDB_Put_PaymentCoin(t *testing.T) { {[]string{"TBTC", "TBCH"}, "TBCH", "TBCH"}, {[]string{"TBTC", "TBCH"}, "", "TBTC"}, {[]string{"TBCH", "TBTC"}, "", "TBCH"}, - {[]string{}, "", ""}, } ) @@ -877,7 +943,8 @@ func TestPurchasesDB_Put_PaymentCoin(t *testing.T) { } contract.VendorListings[0].Metadata.AcceptedCurrencies = test.acceptedCurrencies - contract.BuyerOrder.Payment.Coin = test.paymentCoin + //contract.BuyerOrder.Payment.Coin = test.paymentCoin + contract.BuyerOrder.Payment.AmountCurrency = &pb.CurrencyDefinition{Code: test.paymentCoin, Divisibility: 8} err = purdb.Put("orderID", *contract, 0, false) if err != nil { @@ -901,31 +968,62 @@ func TestPurchasesDB_Put_PaymentCoin(t *testing.T) { func TestPurchasesDB_Put_CoinType(t *testing.T) { var ( contract = factory.NewContract() - testsCoins = []string{"", "TBTC", "TETH"} + testsCoins = []struct { + coinType string + cryptoListing bool + }{ + { + "", + true, + }, + { + "TBTC", + true, + }, + { + "TETH", + true, + }, + { + "TBCH", + false, + }, + } ) - for _, testCoin := range testsCoins { + for _, test := range testsCoins { var purdb, teardown, err = buildNewPurchaseStore() if err != nil { t.Fatal(err) } - contract.VendorListings[0].Metadata.CoinType = testCoin + contract.VendorListings[0].Item.PriceCurrency = &pb.CurrencyDefinition{ + Code: test.coinType, + Divisibility: 8, + } + if test.cryptoListing { + contract.VendorListings[0].Metadata.CryptoCurrencyCode = test.coinType + contract.VendorListings[0].Metadata.ContractType = pb.Listing_Metadata_CRYPTOCURRENCY + } else { + contract.VendorListings[0].Metadata.ContractType = pb.Listing_Metadata_PHYSICAL_GOOD + } err = purdb.Put("orderID", *contract, 0, false) if err != nil { - t.Error(err) + t.Fatal(err) } purchases, count, err := purdb.GetAll(nil, "", false, false, 1, nil) if err != nil { - t.Error(err) + t.Fatal(err) } if count != 1 { - t.Errorf(`Expected %d record got %d`, 1, count) + t.Fatalf(`Expected %d record got %d`, 1, count) } - if purchases[0].CoinType != testCoin { - t.Errorf(`Expected %s got %s`, testCoin, purchases[0].CoinType) + if test.cryptoListing && purchases[0].CoinType != test.coinType { + t.Errorf(`Expected %s got %s`, test.coinType, purchases[0].CoinType) + } else if !test.cryptoListing && purchases[0].CoinType != "" { + t.Errorf(`Expected "" got %s`, purchases[0].CoinType) } teardown() } diff --git a/repo/db/query.go b/repo/db/query.go index 6d7086714c..14bca489c3 100644 --- a/repo/db/query.go +++ b/repo/db/query.go @@ -4,7 +4,7 @@ import ( "strconv" "strings" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) type query struct { diff --git a/repo/db/query_test.go b/repo/db/query_test.go index 49607de83b..4543329008 100644 --- a/repo/db/query_test.go +++ b/repo/db/query_test.go @@ -3,7 +3,7 @@ package db import ( "testing" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) func Test_filterQuery(t *testing.T) { diff --git a/repo/db/sales.go b/repo/db/sales.go index 46747ba2a3..a12aa88ec3 100644 --- a/repo/db/sales.go +++ b/repo/db/sales.go @@ -5,14 +5,16 @@ import ( "encoding/json" "errors" "fmt" + "math/big" + "strings" "sync" "time" "github.com/OpenBazaar/jsonpb" "github.com/OpenBazaar/wallet-interface" btc "github.com/btcsuite/btcutil" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) type SalesDB struct { @@ -46,15 +48,12 @@ func (s *SalesDB) Put(orderID string, contract pb.RicardianContract, state pb.Or return err } - tx, err := s.db.Begin() - if err != nil { - return err - } stm := `insert or replace into sales(orderID, contract, state, read, timestamp, total, thumbnail, buyerID, buyerHandle, title, shippingName, shippingAddress, paymentAddr, paymentCoin, coinType, funded, transactions) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,(select funded from sales where orderID="` + orderID + `"),(select transactions from sales where orderID="` + orderID + `"))` - stmt, err := tx.Prepare(stm) + stmt, err := s.db.Prepare(stm) if err != nil { - return err + return fmt.Errorf("prepare sale sql: %s", err.Error()) } + defer stmt.Close() handle := contract.BuyerOrder.BuyerID.Handle shippingName := "" @@ -70,14 +69,18 @@ func (s *SalesDB) Put(orderID string, contract pb.RicardianContract, state pb.Or address = contract.VendorOrderConfirmation.PaymentAddress } - defer stmt.Close() + paymentCoin, err := PaymentCoinForContract(&contract) + if err != nil { + return err + } + _, err = stmt.Exec( orderID, out, int(state), readInt, int(contract.BuyerOrder.Timestamp.Seconds), - int(contract.BuyerOrder.Payment.Amount), + contract.BuyerOrder.Payment.BigAmount, contract.VendorListings[0].Item.Images[0].Tiny, contract.BuyerOrder.BuyerID.PeerID, handle, @@ -85,15 +88,14 @@ func (s *SalesDB) Put(orderID string, contract pb.RicardianContract, state pb.Or shippingName, shippingAddress, address, - PaymentCoinForContract(&contract), + paymentCoin, CoinTypeForContract(&contract), ) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit sale: %s", err.Error()) } - return tx.Commit() + return nil } func (s *SalesDB) MarkAsRead(orderID string) error { @@ -169,9 +171,10 @@ func (s *SalesDB) GetAll(stateFilter []pb.OrderState, searchTerm string, sortByA var ret []repo.Sale for rows.Next() { var orderID, title, thumbnail, buyerID, buyerHandle, shippingName, shippingAddr, coinType, paymentCoin string - var timestamp, total, stateInt, readInt int + var timestamp, stateInt, readInt int var contract []byte - if err := rows.Scan(&orderID, &contract, ×tamp, &total, &title, &thumbnail, &buyerID, &buyerHandle, &shippingName, &shippingAddr, &stateInt, &readInt, &coinType, &paymentCoin); err != nil { + totalStr := "" + if err := rows.Scan(&orderID, &contract, ×tamp, &totalStr, &title, &thumbnail, &buyerID, &buyerHandle, &shippingName, &shippingAddr, &stateInt, &readInt, &coinType, &paymentCoin); err != nil { return ret, 0, err } read := false @@ -193,13 +196,32 @@ func (s *SalesDB) GetAll(stateFilter []pb.OrderState, searchTerm string, sortByA moderated = true } + if len(rc.VendorListings) > 0 && rc.VendorListings[0].Metadata != nil && rc.VendorListings[0].Metadata.ContractType != pb.Listing_Metadata_CRYPTOCURRENCY { + coinType = "" + } + + if strings.Contains(totalStr, "e") { + flt, _, err := big.ParseFloat(totalStr, 10, 0, big.ToNearestEven) + if err != nil { + return nil, 0, err + } + var i = new(big.Int) + i, _ = flt.Int(i) + totalStr = i.String() + } + + cv, err := repo.NewCurrencyValueWithLookup(totalStr, paymentCoin) + if err != nil { + return nil, 0, err + } + ret = append(ret, repo.Sale{ OrderId: orderID, Slug: slug, Timestamp: time.Unix(int64(timestamp), 0), Title: title, Thumbnail: thumbnail, - Total: uint64(total), + Total: *cv, BuyerId: buyerID, BuyerHandle: buyerHandle, ShippingName: shippingName, @@ -300,13 +322,19 @@ func (s *SalesDB) GetByOrderId(orderId string) (*pb.RicardianContract, pb.OrderS if readInt != nil && *readInt == 1 { read = true } - def, err := repo.LoadCurrencyDefinitions().Lookup(paymentCoin) + def, err := repo.AllCurrencies().Lookup(paymentCoin) if err != nil { return nil, pb.OrderState(0), false, nil, false, nil, fmt.Errorf("validating payment coin: %s", err.Error()) } var records []*wallet.TransactionRecord - json.Unmarshal(serializedTransactions, &records) - return rc, pb.OrderState(stateInt), funded, records, read, def.CurrencyCode(), nil + if len(serializedTransactions) > 0 { + err = json.Unmarshal(serializedTransactions, &records) + if err != nil { + return nil, pb.OrderState(0), false, nil, false, nil, fmt.Errorf("unmarshal purchase transactions: %s", err.Error()) + } + } + cc := def.CurrencyCode() + return rc, pb.OrderState(stateInt), funded, records, read, &cc, nil } func (s *SalesDB) Count() int { @@ -314,24 +342,28 @@ func (s *SalesDB) Count() int { defer s.lock.Unlock() row := s.db.QueryRow("select Count(*) from sales") var count int - row.Scan(&count) + err := row.Scan(&count) + if err != nil { + log.Error(err) + } return count } -func (s *SalesDB) GetNeedsResync() ([]repo.UnfundedSale, error) { +func (s *SalesDB) GetUnfunded() ([]repo.UnfundedOrder, error) { s.lock.Lock() defer s.lock.Unlock() - var ret []repo.UnfundedSale - rows, err := s.db.Query(`select orderID, contract, timestamp from sales where state=? and needsSync=?`, 1, 1) + var ret []repo.UnfundedOrder + rows, err := s.db.Query(`select orderID, contract, timestamp, paymentAddr from sales where state=?`, 1) if err != nil { return ret, err } + defer rows.Close() for rows.Next() { - var orderID string + var orderID, paymentAddr string var timestamp int var contractBytes []byte - err := rows.Scan(&orderID, &contractBytes, ×tamp) + err := rows.Scan(&orderID, &contractBytes, ×tamp, &paymentAddr) if err != nil { return ret, err } @@ -341,27 +373,16 @@ func (s *SalesDB) GetNeedsResync() ([]repo.UnfundedSale, error) { if err != nil { return ret, err } - ret = append(ret, repo.UnfundedSale{OrderId: orderID, Timestamp: time.Unix(int64(timestamp), 0), PaymentCoin: rc.BuyerOrder.Payment.Coin}) + order, err := repo.ToV5Order(rc.BuyerOrder, repo.AllCurrencies().Lookup) + if err != nil { + return ret, err + } + ret = append(ret, repo.UnfundedOrder{OrderId: orderID, Timestamp: time.Unix(int64(timestamp), 0), PaymentCoin: order.Payment.AmountCurrency.Code, PaymentAddress: paymentAddr}) } } return ret, nil } -func (s *SalesDB) SetNeedsResync(orderId string, needsResync bool) error { - s.lock.Lock() - defer s.lock.Unlock() - - resyncInt := 0 - if needsResync { - resyncInt = 1 - } - _, err := s.db.Exec("update sales set needsSync=? where orderID=?", resyncInt, orderId) - if err != nil { - return err - } - return nil -} - // GetSalesForDisputeTimeoutNotification returns []*SaleRecord including // each record which needs Notifications to be generated. func (s *SalesDB) GetSalesForDisputeTimeoutNotification() ([]*repo.SaleRecord, error) { @@ -419,18 +440,24 @@ func (s *SalesDB) UpdateSalesLastDisputeTimeoutNotifiedAt(sales []*repo.SaleReco s.lock.Lock() defer s.lock.Unlock() - tx, err := s.db.Begin() + tx, err := s.BeginTransaction() if err != nil { return fmt.Errorf("begin update sale transaction: %s", err.Error()) } for _, sale := range sales { _, err = tx.Exec("update sales set lastDisputeTimeoutNotifiedAt = ? where orderID = ?", int(sale.LastDisputeTimeoutNotifiedAt.Unix()), sale.OrderID) if err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("update sale: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) + } return fmt.Errorf("update sale: %s", err.Error()) } } if err = tx.Commit(); err != nil { - return fmt.Errorf("commit update sale transaction: %s", err.Error()) + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("commit sale: (%s) w rollback error: (%s)", err.Error(), rErr.Error()) + } + return fmt.Errorf("commit sale: %s", err.Error()) } return nil diff --git a/repo/db/sales_test.go b/repo/db/sales_test.go index 348c55bd29..7a43e44034 100644 --- a/repo/db/sales_test.go +++ b/repo/db/sales_test.go @@ -1,7 +1,9 @@ package db_test import ( + "fmt" "reflect" + "strconv" "strings" "sync" "testing" @@ -12,11 +14,11 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test/factory" ) func buildNewSaleStore() (repo.SaleStore, func(), error) { @@ -25,14 +27,14 @@ func buildNewSaleStore() (repo.SaleStore, func(), error) { TestModeEnabled: true, }) if err := appSchema.BuildSchemaDirectories(); err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("build schema at path (%s): %s", appSchema.DataPath(), err) } if err := appSchema.InitializeDatabase(); err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("init db at path (%s): %s", appSchema.DataPath(), err) } database, err := appSchema.OpenDatabase() if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("open db at path (%s): %s", appSchema.DataPath(), err) } return db.NewSaleStore(database, new(sync.Mutex)), appSchema.DestroySchemaDirectories, nil } @@ -63,7 +65,8 @@ func TestPutSale(t *testing.T) { defer teardown() contract := factory.NewContract() - contract.BuyerOrder.Payment.Coin = "BTC" + //contract.BuyerOrder.Payment.Coin = "BTC" + contract.BuyerOrder.Payment.AmountCurrency = &pb.CurrencyDefinition{Code: "BTC", Divisibility: 8} err = saldb.Put("orderID", *contract, 0, false) if err != nil { @@ -77,7 +80,7 @@ func TestPutSale(t *testing.T) { var state int var read int var date int - var total int + var total string var thumbnail string var buyerID string var buyerHandle string @@ -102,8 +105,8 @@ func TestPutSale(t *testing.T) { if date != int(contract.BuyerOrder.Timestamp.Seconds) { t.Errorf("Expected %d got %d", int(contract.BuyerOrder.Timestamp.Seconds), date) } - if total != int(contract.BuyerOrder.Payment.Amount) { - t.Errorf("Expected %d got %d", int(contract.BuyerOrder.Payment.Amount), total) + if total != contract.BuyerOrder.Payment.BigAmount { + t.Errorf("Expected %s got %s", contract.BuyerOrder.Payment.BigAmount, total) } if thumbnail != contract.VendorListings[0].Item.Images[0].Tiny { t.Errorf("Expected %s got %s", contract.VendorListings[0].Item.Images[0].Tiny, thumbnail) @@ -123,8 +126,8 @@ func TestPutSale(t *testing.T) { if shippingAddress != contract.BuyerOrder.Shipping.Address { t.Errorf(`Expected %s got %s`, strings.ToLower(contract.BuyerOrder.Shipping.Address), shippingAddress) } - if paymentCoin != contract.BuyerOrder.Payment.Coin { - t.Errorf(`Expected %s got %s`, contract.BuyerOrder.Payment.Coin, paymentCoin) + if paymentCoin != contract.BuyerOrder.Payment.AmountCurrency.Code { + t.Errorf(`Expected %s got %s`, contract.BuyerOrder.Payment.AmountCurrency.Code, paymentCoin) } if coinType != "" { t.Errorf(`Expected empty string got %s`, coinType) @@ -139,7 +142,10 @@ func TestDeleteSale(t *testing.T) { defer teardown() contract := factory.NewContract() - saldb.Put("orderID", *contract, 0, false) + err = saldb.Put("orderID", *contract, 0, false) + if err != nil { + t.Log(err) + } err = saldb.Delete("orderID") if err != nil { t.Error("Sale delete failed") @@ -165,7 +171,10 @@ func TestMarkSaleAsRead(t *testing.T) { defer teardown() contract := factory.NewContract() - saldb.Put("orderID", *contract, 0, false) + err = saldb.Put("orderID", *contract, 0, false) + if err != nil { + t.Log(err) + } err = saldb.MarkAsRead("orderID") if err != nil { t.Error(err) @@ -191,7 +200,10 @@ func TestMarkSaleAsUnread(t *testing.T) { defer teardown() contract := factory.NewContract() - saldb.Put("orderID", *contract, 0, false) + err = saldb.Put("orderID", *contract, 0, false) + if err != nil { + t.Log(err) + } err = saldb.MarkAsRead("orderID") if err != nil { t.Error(err) @@ -310,7 +322,10 @@ func TestSalesGetByPaymentAddress(t *testing.T) { defer teardown() contract := factory.NewContract() - saldb.Put("orderID", *contract, 0, false) + err = saldb.Put("orderID", *contract, 0, false) + if err != nil { + t.Log(err) + } addr, err := btcutil.DecodeAddress(contract.BuyerOrder.Payment.Address, &chaincfg.MainNetParams) if err != nil { t.Error(err) @@ -345,7 +360,7 @@ func TestSalesGetByOrderId(t *testing.T) { } contract := factory.NewContract() - contract.BuyerOrder.Payment.Coin = expectedCoin + //contract.BuyerOrder.Payment.Coin = expectedCoin if err := saldb.Put("orderID", *contract, 0, false); err != nil { t.Fatal(err) } @@ -369,15 +384,24 @@ func TestSalesDB_GetAll(t *testing.T) { c0 := factory.NewContract() ts, _ := ptypes.TimestampProto(time.Now()) c0.BuyerOrder.Timestamp = ts - saldb.Put("orderID", *c0, 0, false) + err = saldb.Put("orderID", *c0, 0, false) + if err != nil { + t.Log(err) + } c1 := factory.NewContract() ts, _ = ptypes.TimestampProto(time.Now().Add(time.Minute)) c1.BuyerOrder.Timestamp = ts - saldb.Put("orderID2", *c1, 1, false) + err = saldb.Put("orderID2", *c1, 1, false) + if err != nil { + t.Log(err) + } c2 := factory.NewContract() ts, _ = ptypes.TimestampProto(time.Now().Add(time.Hour)) c2.BuyerOrder.Timestamp = ts - saldb.Put("orderID3", *c2, 1, false) + err = saldb.Put("orderID3", *c2, 1, false) + if err != nil { + t.Log(err) + } // Test no offset no limit sales, ct, err := saldb.GetAll([]pb.OrderState{}, "", false, false, -1, []string{}) if err != nil { @@ -463,7 +487,7 @@ func TestSalesDB_GetAll(t *testing.T) { } } -func TestSalesDB_SetNeedsResync(t *testing.T) { +func TestSalesDB_GetUnfunded(t *testing.T) { var saldb, teardown, err = buildNewSaleStore() if err != nil { t.Fatal(err) @@ -471,53 +495,21 @@ func TestSalesDB_SetNeedsResync(t *testing.T) { defer teardown() contract := factory.NewContract() - saldb.Put("orderID", *contract, 0, false) - err = saldb.SetNeedsResync("orderID", true) - if err != nil { - t.Error(err) - } - stmt, _ := saldb.PrepareQuery("select needsSync from sales where orderID=?") - defer stmt.Close() - var needsSyncInt int - err = stmt.QueryRow("orderID").Scan(&needsSyncInt) - if err != nil { - t.Error(err) - } - if needsSyncInt != 1 { - t.Errorf(`Expected %d got %d`, 1, needsSyncInt) - } - err = saldb.SetNeedsResync("orderID", false) - if err != nil { - t.Error(err) - } - err = stmt.QueryRow("orderID").Scan(&needsSyncInt) - if err != nil { - t.Error(err) - } - if needsSyncInt != 0 { - t.Errorf(`Expected %d got %d`, 0, needsSyncInt) + if err := saldb.Put("orderID", *contract, 1, false); err != nil { + t.Fatal(err) } -} - -func TestSalesDB_GetNeedsResync(t *testing.T) { - var saldb, teardown, err = buildNewSaleStore() - if err != nil { + if err := saldb.Put("orderID1", *contract, 1, false); err != nil { t.Fatal(err) } - defer teardown() - - contract := factory.NewContract() - saldb.Put("orderID", *contract, 1, false) - saldb.Put("orderID1", *contract, 1, false) - err = saldb.SetNeedsResync("orderID", true) - if err != nil { - t.Error(err) + if err := saldb.Put("x0", *contract, 0, false); err != nil { + t.Fatal(err) } - err = saldb.SetNeedsResync("orderID1", true) - if err != nil { - t.Error(err) + for i := 2; i < 15; i++ { + if err := saldb.Put("x"+strconv.Itoa(i), *contract, pb.OrderState(i), false); err != nil { + t.Fatal(err) + } } - unfunded, err := saldb.GetNeedsResync() + unfunded, err := saldb.GetUnfunded() if err != nil { t.Error(err) } @@ -531,6 +523,9 @@ func TestSalesDB_GetNeedsResync(t *testing.T) { } else if uf.OrderId == "orderID1" { b = true } + if uf.PaymentAddress != contract.BuyerOrder.Payment.Address { + t.Errorf("Incorrect payment address. Expected %s, got %s", contract.BuyerOrder.Payment.Address, uf.PaymentAddress) + } } if !a || !b { t.Error("Failed to return correct unfunded orders") @@ -742,18 +737,18 @@ func TestSalesDB_Put_PaymentCoin(t *testing.T) { {[]string{"TBTC", "TBCH"}, "TBCH", "TBCH"}, {[]string{"TBTC", "TBCH"}, "", "TBTC"}, {[]string{"TBCH", "TBTC"}, "", "TBCH"}, - {[]string{}, "", ""}, } ) for _, test := range tests { + //t.Logf("testing acc: %+v paymentCoin: %s expected: %s", test.acceptedCurrencies, test.paymentCoin, test.expected) saldb, teardown, err := buildNewSaleStore() if err != nil { t.Fatal(err) } contract.VendorListings[0].Metadata.AcceptedCurrencies = test.acceptedCurrencies - contract.BuyerOrder.Payment.Coin = test.paymentCoin + contract.BuyerOrder.Payment.AmountCurrency = &pb.CurrencyDefinition{Code: test.paymentCoin, Divisibility: 8} err = saldb.Put("orderID", *contract, 0, false) if err != nil { @@ -775,15 +770,47 @@ func TestSalesDB_Put_PaymentCoin(t *testing.T) { } func TestSalesDB_Put_CoinType(t *testing.T) { - var contract = factory.NewContract() + var ( + contract = factory.NewContract() + testCoins = []struct { + coinType string + cryptoListing bool + }{ + { + "", + true, + }, + { + "TBTC", + true, + }, + { + "TETH", + true, + }, + { + "TBCH", + false, + }, + } + ) - for _, testCoin := range []string{"", "TBTC", "TETH"} { + for _, test := range testCoins { var saldb, teardown, err = buildNewSaleStore() if err != nil { t.Fatal(err) } - contract.VendorListings[0].Metadata.CoinType = testCoin + contract.VendorListings[0].Item.PriceCurrency = &pb.CurrencyDefinition{ + Code: test.coinType, + Divisibility: 8, + } + if test.cryptoListing { + contract.VendorListings[0].Metadata.CryptoCurrencyCode = test.coinType + contract.VendorListings[0].Metadata.ContractType = pb.Listing_Metadata_CRYPTOCURRENCY + } else { + contract.VendorListings[0].Metadata.ContractType = pb.Listing_Metadata_PHYSICAL_GOOD + } err = saldb.Put("orderID", *contract, 0, false) if err != nil { @@ -797,8 +824,10 @@ func TestSalesDB_Put_CoinType(t *testing.T) { if count != 1 { t.Errorf(`Expected %d record got %d`, 1, count) } - if sales[0].CoinType != testCoin { - t.Errorf(`Expected %s got %s`, testCoin, sales[0].CoinType) + if test.cryptoListing && sales[0].CoinType != test.coinType { + t.Errorf(`Expected %s got %s`, test.coinType, sales[0].CoinType) + } else if !test.cryptoListing && sales[0].CoinType != "" { + t.Errorf(`Expected "" got %s`, sales[0].CoinType) } teardown() } diff --git a/repo/db/settings.go b/repo/db/settings.go index e7a3326e39..bf9b878b88 100644 --- a/repo/db/settings.go +++ b/repo/db/settings.go @@ -7,7 +7,7 @@ import ( "fmt" "sync" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) var SettingsNotSetError = errors.New("settings not set") @@ -23,29 +23,20 @@ func NewConfigurationStore(db *sql.DB, lock *sync.Mutex) repo.ConfigurationStore func (s *SettingsDB) Put(settings repo.SettingsData) error { s.lock.Lock() defer s.lock.Unlock() - tx, err := s.db.Begin() - if err != nil { - return err - } + b, err := json.MarshalIndent(&settings, "", " ") if err != nil { - return err + return fmt.Errorf("marshal settings: %s", err.Error()) } - stmt, err := tx.Prepare("insert or replace into config(key, value) values(?,?)") + stmt, err := s.PrepareQuery("insert or replace into config(key, value) values(?,?)") if err != nil { - return err + return fmt.Errorf("prepare settings sql: %s", err.Error()) } defer stmt.Close() _, err = stmt.Exec("settings", string(b)) if err != nil { - if errRollback := tx.Rollback(); errRollback != nil { - return fmt.Errorf("rollback: %s\n also: %s", errRollback.Error(), err.Error()) - } - return err - } - if err := tx.Commit(); err != nil { - return err + return fmt.Errorf("commit settings: %s", err.Error()) } return nil } diff --git a/repo/db/settings_test.go b/repo/db/settings_test.go index bfd1b2ed4e..6be203964f 100644 --- a/repo/db/settings_test.go +++ b/repo/db/settings_test.go @@ -5,9 +5,9 @@ import ( "sync" "testing" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func buildConfigurationStore() (repo.ConfigurationStore, func(), error) { @@ -79,10 +79,16 @@ func TestInvalidSettingsGet(t *testing.T) { _, err = stmt.Exec("settings", string("Test fail")) if err != nil { - tx.Rollback() + err0 := tx.Rollback() + if err0 != nil { + t.Log(err0) + } + t.Error(err) + } + err = tx.Commit() + if err != nil { t.Error(err) } - tx.Commit() _, err = sdb.Get() if err == nil { t.Error("settings get didn't error with invalid data") @@ -128,7 +134,7 @@ func TestSettingsUpdate(t *testing.T) { if err != nil { t.Error(err) } - l := "/openbazaar-go:0.4/" + l := "/marketplace-go:0.4/" setUpdt := repo.SettingsData{ Version: &l, } @@ -151,7 +157,7 @@ func TestSettingsUpdate(t *testing.T) { if *set.Country != "UNITED_STATES" { t.Error("Settings update failed to put correct value") } - if *set.Version != "/openbazaar-go:0.4/" { + if *set.Version != "/marketplace-go:0.4/" { t.Error("Settings update failed to put correct value") } if *set.TermsAndConditions != "None" { diff --git a/repo/db/stxo.go b/repo/db/stxo.go index bf5ecc3849..6271b4bc7e 100644 --- a/repo/db/stxo.go +++ b/repo/db/stxo.go @@ -3,6 +3,7 @@ package db import ( "database/sql" "encoding/hex" + "fmt" "strconv" "strings" "sync" @@ -11,7 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type StxoDB struct { @@ -26,24 +27,21 @@ func NewSpentTransactionStore(db *sql.DB, lock *sync.Mutex, coinType util.ExtCoi func (s *StxoDB) Put(stxo wallet.Stxo) error { s.lock.Lock() defer s.lock.Unlock() - tx, _ := s.db.Begin() - stmt, err := tx.Prepare("insert or replace into stxos(coin, outpoint, value, height, scriptPubKey, watchOnly, spendHeight, spendTxid) values(?,?,?,?,?,?,?,?)") + stmt, err := s.PrepareQuery("insert or replace into stxos(coin, outpoint, value, height, scriptPubKey, watchOnly, spendHeight, spendTxid) values(?,?,?,?,?,?,?,?)") if err != nil { - tx.Rollback() - return err + return fmt.Errorf("prepare stxo sql: %s", err.Error()) } defer stmt.Close() + watchOnly := 0 if stxo.Utxo.WatchOnly { watchOnly = 1 } outpoint := stxo.Utxo.Op.Hash.String() + ":" + strconv.Itoa(int(stxo.Utxo.Op.Index)) - _, err = stmt.Exec(s.coinType.CurrencyCode(), outpoint, int(stxo.Utxo.Value), int(stxo.Utxo.AtHeight), hex.EncodeToString(stxo.Utxo.ScriptPubkey), watchOnly, int(stxo.SpendHeight), stxo.SpendTxid.String()) + _, err = stmt.Exec(s.coinType.CurrencyCode(), outpoint, stxo.Utxo.Value, int(stxo.Utxo.AtHeight), hex.EncodeToString(stxo.Utxo.ScriptPubkey), watchOnly, int(stxo.SpendHeight), stxo.SpendTxid.String()) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit stxo: %s", err.Error()) } - tx.Commit() return nil } @@ -59,7 +57,7 @@ func (s *StxoDB) GetAll() ([]wallet.Stxo, error) { defer rows.Close() for rows.Next() { var outpoint string - var value int + var value string var height int var scriptPubKey string var spendHeight int @@ -92,7 +90,7 @@ func (s *StxoDB) GetAll() ([]wallet.Stxo, error) { utxo := wallet.Utxo{ Op: *wire.NewOutPoint(shaHash, uint32(index)), AtHeight: int32(height), - Value: int64(value), + Value: value, ScriptPubkey: scriptBytes, WatchOnly: watchOnly, } diff --git a/repo/db/stxo_test.go b/repo/db/stxo_test.go index bd5c891897..19f484c072 100644 --- a/repo/db/stxo_test.go +++ b/repo/db/stxo_test.go @@ -11,8 +11,8 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/schema" ) func mustNewStxo() wallet.Stxo { @@ -22,7 +22,7 @@ func mustNewStxo() wallet.Stxo { utxo := wallet.Utxo{ Op: *outpoint, AtHeight: 300000, - Value: 100000000, + Value: "100000000", ScriptPubkey: []byte("scriptpubkey"), WatchOnly: false, } @@ -67,7 +67,7 @@ func TestStxoPut(t *testing.T) { defer stmt.Close() var outpoint string - var value int + var value string var height int var scriptPubkey string var spendHeight int @@ -81,7 +81,7 @@ func TestStxoPut(t *testing.T) { if outpoint != o { t.Error("Stxo db returned wrong outpoint") } - if value != int(stxo.Utxo.Value) { + if value != stxo.Utxo.Value { t.Error("Stxo db returned wrong value") } if height != int(stxo.Utxo.AtHeight) { diff --git a/repo/db/txmetadata.go b/repo/db/txmetadata.go index a2e1e0696b..157a6a2dde 100644 --- a/repo/db/txmetadata.go +++ b/repo/db/txmetadata.go @@ -4,7 +4,7 @@ import ( "database/sql" "sync" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type TxMetadataDB struct { @@ -18,10 +18,9 @@ func NewTransactionMetadataStore(db *sql.DB, lock *sync.Mutex) repo.TransactionM func (t *TxMetadataDB) Put(m repo.Metadata) error { t.lock.Lock() defer t.lock.Unlock() - tx, _ := t.db.Begin() - stmt, err := tx.Prepare("insert or replace into txmetadata(txid, address, memo, orderID, thumbnail, canBumpFee) values(?,?,?,?,?,?)") + stmt, err := t.db.Prepare("insert or replace into txmetadata(txid, address, memo, orderID, thumbnail, canBumpFee) values(?,?,?,?,?,?)") if err != nil { - tx.Rollback() + log.Errorf("prepring txmetadata sql for order (%s): %s", m.OrderId, err.Error()) return err } defer stmt.Close() @@ -29,12 +28,11 @@ func (t *TxMetadataDB) Put(m repo.Metadata) error { if m.CanBumpFee { bumpable = 1 } - _, err = stmt.Exec(m.Txid, m.Address, m.Memo, m.OrderID, m.Thumbnail, bumpable) + _, err = stmt.Exec(m.Txid, m.Address, m.Memo, m.OrderId, m.Thumbnail, bumpable) if err != nil { - tx.Rollback() + log.Errorf("putting txmetadata for order (%s): %s", m.OrderId, err.Error()) return err } - tx.Commit() return nil } @@ -57,7 +55,7 @@ func (t *TxMetadataDB) Get(txid string) (repo.Metadata, error) { if canBumpFee > 0 { bumpable = true } - m = repo.Metadata{id, address, memo, orderId, thumbnail, bumpable} + m = repo.Metadata{Txid: id, Address: address, Memo: memo, OrderId: orderId, Thumbnail: thumbnail, CanBumpFee: bumpable} return m, nil } @@ -85,7 +83,7 @@ func (t *TxMetadataDB) GetAll() (map[string]repo.Metadata, error) { Txid: txid, Address: address, Memo: memo, - OrderID: orderId, + OrderId: orderId, Thumbnail: thumbnail, CanBumpFee: bumpable, } diff --git a/repo/db/txmetadata_test.go b/repo/db/txmetadata_test.go index 1e4fa1d403..78f813d8e1 100644 --- a/repo/db/txmetadata_test.go +++ b/repo/db/txmetadata_test.go @@ -4,9 +4,9 @@ import ( "sync" "testing" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" ) func buildNewTransactionStore() (repo.TransactionMetadataStore, func(), error) { @@ -34,7 +34,14 @@ func TestTxMetadataDB_Put(t *testing.T) { } defer teardown() - m := repo.Metadata{"16e4a210d8c798f7d7a32584038c1f55074377bdd19f4caa24edb657fff9538f", "1Xtkf3Rdq6eix4tFXpEuHdXfubt3Mt452", "Some memo", "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG", "QmZY1kx6VrNjgDB4SJDByxvSVuiBfsisRLdUMJRDppTTsS", false} + m := repo.Metadata{ + Txid: "16e4a210d8c798f7d7a32584038c1f55074377bdd19f4caa24edb657fff9538f", + Address: "1Xtkf3Rdq6eix4tFXpEuHdXfubt3Mt452", + Memo: "Some memo", + OrderId: "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG", + Thumbnail: "QmZY1kx6VrNjgDB4SJDByxvSVuiBfsisRLdUMJRDppTTsS", + CanBumpFee: false, + } err = metDB.Put(m) if err != nil { t.Error(err) @@ -59,7 +66,7 @@ func TestTxMetadataDB_Put(t *testing.T) { if memo != m.Memo { t.Error("TxMetadataDB failed to put memo") } - if orderId != m.OrderID { + if orderId != m.OrderId { t.Error("TxMetadataDB failed to put order ID") } if thumbnail != m.Thumbnail { @@ -77,7 +84,14 @@ func TestTxMetadataDB_Get(t *testing.T) { } defer teardown() - m := repo.Metadata{"16e4a210d8c798f7d7a32584038c1f55074377bdd19f4caa24edb657fff9538f", "1Xtkf3Rdq6eix4tFXpEuHdXfubt3Mt452", "Some memo", "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG", "QmZY1kx6VrNjgDB4SJDByxvSVuiBfsisRLdUMJRDppTTsS", false} + m := repo.Metadata{ + Txid: "16e4a210d8c798f7d7a32584038c1f55074377bdd19f4caa24edb657fff9538f", + Address: "1Xtkf3Rdq6eix4tFXpEuHdXfubt3Mt452", + Memo: "Some memo", + OrderId: "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG", + Thumbnail: "QmZY1kx6VrNjgDB4SJDByxvSVuiBfsisRLdUMJRDppTTsS", + CanBumpFee: false, + } err = metDB.Put(m) if err != nil { t.Error(err) @@ -95,7 +109,7 @@ func TestTxMetadataDB_Get(t *testing.T) { if ret.Memo != m.Memo { t.Error("TxMetadataDB failed to get memo") } - if ret.OrderID != m.OrderID { + if ret.OrderId != m.OrderId { t.Error("TxMetadataDB failed to get order ID") } if ret.Thumbnail != m.Thumbnail { @@ -113,7 +127,14 @@ func TestTxMetadataDB_GetAll(t *testing.T) { } defer teardown() - m := repo.Metadata{"16e4a210d8c798f7d7a32584038c1f55074377bdd19f4caa24edb657fff9538f", "1Xtkf3Rdq6eix4tFXpEuHdXfubt3Mt452", "Some memo", "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG", "QmZY1kx6VrNjgDB4SJDByxvSVuiBfsisRLdUMJRDppTTsS", false} + m := repo.Metadata{ + Txid: "16e4a210d8c798f7d7a32584038c1f55074377bdd19f4caa24edb657fff9538f", + Address: "1Xtkf3Rdq6eix4tFXpEuHdXfubt3Mt452", + Memo: "Some memo", + OrderId: "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG", + Thumbnail: "QmZY1kx6VrNjgDB4SJDByxvSVuiBfsisRLdUMJRDppTTsS", + CanBumpFee: false, + } err = metDB.Put(m) if err != nil { t.Error(err) @@ -138,7 +159,7 @@ func TestTxMetadataDB_GetAll(t *testing.T) { if ret.Memo != m.Memo { t.Error("TxMetadataDB failed to get memo") } - if ret.OrderID != m.OrderID { + if ret.OrderId != m.OrderId { t.Error("TxMetadataDB failed to get order ID") } if ret.Thumbnail != m.Thumbnail { @@ -156,7 +177,14 @@ func TestTxMetadataDB_Delete(t *testing.T) { } defer teardown() - m := repo.Metadata{"16e4a210d8c798f7d7a32584038c1f55074377bdd19f4caa24edb657fff9538f", "1Xtkf3Rdq6eix4tFXpEuHdXfubt3Mt452", "Some memo", "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG", "QmZY1kx6VrNjgDB4SJDByxvSVuiBfsisRLdUMJRDppTTsS", false} + m := repo.Metadata{ + Txid: "16e4a210d8c798f7d7a32584038c1f55074377bdd19f4caa24edb657fff9538f", + Address: "1Xtkf3Rdq6eix4tFXpEuHdXfubt3Mt452", + Memo: "Some memo", + OrderId: "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG", + Thumbnail: "QmZY1kx6VrNjgDB4SJDByxvSVuiBfsisRLdUMJRDppTTsS", + CanBumpFee: false, + } err = metDB.Put(m) if err != nil { t.Error(err) diff --git a/repo/db/txns.go b/repo/db/txns.go index b4b92fb9bd..c4cb9703c5 100644 --- a/repo/db/txns.go +++ b/repo/db/txns.go @@ -2,13 +2,14 @@ package db import ( "database/sql" + "fmt" "sync" "time" "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type TxnsDB struct { @@ -20,29 +21,24 @@ func NewTransactionStore(db *sql.DB, lock *sync.Mutex, coinType util.ExtCoinType return &TxnsDB{modelStore{db, lock}, coinType} } -func (t *TxnsDB) Put(raw []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error { +func (t *TxnsDB) Put(raw []byte, txid, value string, height int, timestamp time.Time, watchOnly bool) error { t.lock.Lock() defer t.lock.Unlock() - tx, err := t.db.Begin() + + stmt, err := t.PrepareQuery("insert or replace into txns(coin, txid, value, height, timestamp, watchOnly, tx) values(?,?,?,?,?,?,?)") if err != nil { - return err - } - stmt, err := tx.Prepare("insert or replace into txns(coin, txid, value, height, timestamp, watchOnly, tx) values(?,?,?,?,?,?,?)") - if err != nil { - tx.Rollback() - return err + return fmt.Errorf("prepare txn sql: %s", err.Error()) } defer stmt.Close() + watchOnlyInt := 0 if watchOnly { watchOnlyInt = 1 } _, err = stmt.Exec(t.coinType.CurrencyCode(), txid, value, height, int(timestamp.Unix()), watchOnlyInt, raw) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("update txn: %s", err.Error()) } - tx.Commit() return nil } @@ -58,7 +54,7 @@ func (t *TxnsDB) Get(txid chainhash.Hash) (wallet.Txn, error) { var raw []byte var height int var timestamp int - var value int + var value string var watchOnlyInt int err = stmt.QueryRow(txid.String(), t.coinType.CurrencyCode()).Scan(&raw, &value, &height, ×tamp, &watchOnlyInt) if err != nil { @@ -70,7 +66,7 @@ func (t *TxnsDB) Get(txid chainhash.Hash) (wallet.Txn, error) { } txn = wallet.Txn{ Txid: txid.String(), - Value: int64(value), + Value: value, Height: int32(height), Timestamp: time.Unix(int64(timestamp), 0), WatchOnly: watchOnly, @@ -92,7 +88,7 @@ func (t *TxnsDB) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) { for rows.Next() { var raw []byte var txid string - var value int + var value string var height int var timestamp int var watchOnlyInt int @@ -110,7 +106,7 @@ func (t *TxnsDB) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) { txn := wallet.Txn{ Txid: txid, - Value: int64(value), + Value: value, Height: int32(height), Timestamp: time.Unix(int64(timestamp), 0), WatchOnly: watchOnly, @@ -135,20 +131,15 @@ func (t *TxnsDB) Delete(txid *chainhash.Hash) error { func (t *TxnsDB) UpdateHeight(txid chainhash.Hash, height int, timestamp time.Time) error { t.lock.Lock() defer t.lock.Unlock() - tx, err := t.db.Begin() - if err != nil { - return err - } - stmt, err := tx.Prepare("update txns set height=?, timestamp=? where txid=? and coin=?") + + stmt, err := t.PrepareQuery("update txns set height=?, timestamp=? where txid=? and coin=?") if err != nil { - return err + return fmt.Errorf("prepare txn sql: %s", err.Error()) } defer stmt.Close() _, err = stmt.Exec(height, int(timestamp.Unix()), txid.String(), t.coinType.CurrencyCode()) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("update txns: %s", err.Error()) } - tx.Commit() return nil } diff --git a/repo/db/txns_test.go b/repo/db/txns_test.go index 508818a710..7001c5735d 100644 --- a/repo/db/txns_test.go +++ b/repo/db/txns_test.go @@ -10,8 +10,8 @@ import ( "github.com/phoreproject/multiwallet/util" "github.com/btcsuite/btcd/wire" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/schema" ) func buildNewTransactionStore() (repo.TransactionStore, func(), error) { @@ -44,9 +44,12 @@ func TestTxnsPut(t *testing.T) { txHex := "01000000018b5d47ec7ae47ae2e158345069fd38a1460f436c486fd3376de24b5df8da62a201000000da00483045022100d9dfd2bd3762fbb06d4b7d37ba3544aefd2ea9913a728b90b446abf530eed03d0220066f3fe0e7a652d2383cfa3b06188301e7ff02320d3a9b32675d1b0d62e9de740147304402206271eb865f0a5f92fdb4306711c17f53c959a09d401cd375bf60904191f70e080220231368d0bacde1775505f6978486b2732179f3d3f971aa67690475763c3d96de01475221024760c9ba5fa6241da6ee8601f0266f0e0592f53735703f0feaae23eda6673ae821038cfa8e97caaafbe21455803043618440c28c501ec32d6ece6865003165a0d4d152aeffffffff0224eb1400000000001976a91411a23852c4554182abb97f811509d60015071a5188acc4c59d260000000017a9140be09225644b4cfdbb472028d8ccaf6df736025c8700000000" raw, _ := hex.DecodeString(txHex) r := bytes.NewReader(raw) - tx.Deserialize(r) + err = tx.Deserialize(r) + if err != nil { + t.Log(err) + } - err = txdb.Put(raw, tx.TxHash().String(), 5, 1, time.Now(), false) + err = txdb.Put(raw, tx.TxHash().String(), "5", 1, time.Now(), false) if err != nil { t.Error(err) } @@ -88,10 +91,13 @@ func TestTxnsGet(t *testing.T) { txHex := "0100000001a8c3a68b7bec7ed52ea4a5787e5005e02adbcedb2ac1a38bb3ae499def8994db01000000d900473044022025bd8408492d4c55bc1aba94c0857ff8ce9e0030b4a2e464986411b917d83f4a022070336fb42b2b0e141f428e98e543ba0e5c0c00d7dd3142a3c01f6e4b3c0518600147304402202744e1c27d05d62502d4d2091082bf97ba92f25247e75bcc2856e1f7de472a7002206c64ff5ddf6a039375f296f620b384d9529ff658a449179c094dc588b43497b301475221024760c9ba5fa6241da6ee8601f0266f0e0592f53735703f0feaae23eda6673ae821038cfa8e97caaafbe21455803043618440c28c501ec32d6ece6865003165a0d4d152aeffffffff0249cc4a00000000001976a914429d80ec4980e5e30a9d888f92e087b9bb55f66588ac709246260000000017a9140be09225644b4cfdbb472028d8ccaf6df736025c8700000000" raw, _ := hex.DecodeString(txHex) r := bytes.NewReader(raw) - tx.Deserialize(r) + err = tx.Deserialize(r) + if err != nil { + t.Log(err) + } now := time.Now() - err = txdb.Put(raw, tx.TxHash().String(), 0, 1, now, false) + err = txdb.Put(raw, tx.TxHash().String(), "0", 1, now, false) if err != nil { t.Error(err) } @@ -100,7 +106,10 @@ func TestTxnsGet(t *testing.T) { t.Error(err) } tx2 := wire.NewMsgTx(wire.TxVersion) - tx2.Deserialize(bytes.NewReader(txn.Bytes)) + err = tx2.Deserialize(bytes.NewReader(txn.Bytes)) + if err != nil { + t.Log(err) + } if tx.TxHash().String() != tx2.TxHash().String() { t.Error("Txn db get failed") } @@ -126,9 +135,12 @@ func TestTxnsGetAll(t *testing.T) { txHex := "0100000001867aee4c46da655cca2fa7a16c39883d34a05b1af416beda611c42bb4769f97601000000d900473044022035c352425d3dfff6df3a7196017df1e758079748b9ef022c0ced3c7e90218710022079016e302accec5d2aaf5e34676c10749767e3a34a64f80a0d0aa489027b7689014730440220612b2be46cb24bcd314827ea1682df8f82ff1fa0106cf8e9cf48b3b46ea6b0cf022052ed5da8dbc6052afd40db80cba6f87129ec6828ceffc48c9f3b6f2b855a246001475221024760c9ba5fa6241da6ee8601f0266f0e0592f53735703f0feaae23eda6673ae821038cfa8e97caaafbe21455803043618440c28c501ec32d6ece6865003165a0d4d152aeffffffff0200360500000000001976a91487dc690fcfe267307762c3d7bdfd96b357d6dde188ac87b069250000000017a9140be09225644b4cfdbb472028d8ccaf6df736025c8700000000" raw, _ := hex.DecodeString(txHex) r := bytes.NewReader(raw) - tx.Deserialize(r) + err = tx.Deserialize(r) + if err != nil { + t.Log(err) + } - err = txdb.Put(raw, tx.TxHash().String(), 1, 5, time.Now(), true) + err = txdb.Put(raw, tx.TxHash().String(), "1", 5, time.Now(), true) if err != nil { t.Error(err) } @@ -152,9 +164,12 @@ func TestDeleteTxns(t *testing.T) { txHex := "0100000001cbfe4948ebc9113244b802a96e4940fa063c0455a16ca1f39a1e1db03837d9c701000000da004830450221008994e3dba54cb0ea23ca008d0e361b4339ee7b44b5e9101f6837e6a1a89ce044022051be859c68a547feaf60ffacc43f528cf2963c088bde33424d859274505e3f450147304402206cd4ef92cc7f2862c67810479013330fcafe4d468f1370563d4dff6be5bcbedc02207688a09163e615bc82299a29e987e1d718cb99a91d46a1ab13d18c0f6e616a1601475221024760c9ba5fa6241da6ee8601f0266f0e0592f53735703f0feaae23eda6673ae821038cfa8e97caaafbe21455803043618440c28c501ec32d6ece6865003165a0d4d152aeffffffff029ae2c700000000001976a914f72f20a739ec3c3df1a1fd7eff122d13bd5ca39188acb64784240000000017a9140be09225644b4cfdbb472028d8ccaf6df736025c8700000000" raw, _ := hex.DecodeString(txHex) r := bytes.NewReader(raw) - tx.Deserialize(r) + err = tx.Deserialize(r) + if err != nil { + t.Log(err) + } - err = txdb.Put(raw, tx.TxHash().String(), 0, 1, time.Now(), false) + err = txdb.Put(raw, tx.TxHash().String(), "0", 1, time.Now(), false) if err != nil { t.Error(err) } @@ -190,7 +205,7 @@ func TestTxnsDB_UpdateHeight(t *testing.T) { t.Error(err) } - err = txdb.Put(raw, tx.TxHash().String(), 0, 1, time.Now(), false) + err = txdb.Put(raw, tx.TxHash().String(), "0", 1, time.Now(), false) if err != nil { t.Error(err) } diff --git a/repo/db/util.go b/repo/db/util.go index 0a792a9503..45b510185b 100644 --- a/repo/db/util.go +++ b/repo/db/util.go @@ -1,26 +1,27 @@ package db -import "github.com/phoreproject/openbazaar-go/pb" +import ( + "errors" + "github.com/phoreproject/pm-go/pb" +) -func PaymentCoinForContract(contract *pb.RicardianContract) string { - paymentCoin := contract.BuyerOrder.Payment.Coin - if paymentCoin != "" { - return paymentCoin +func PaymentCoinForContract(contract *pb.RicardianContract) (string, error) { + if contract.BuyerOrder.Payment.AmountCurrency != nil && + contract.BuyerOrder.Payment.AmountCurrency.Code != "" { + return contract.BuyerOrder.Payment.AmountCurrency.Code, nil + } + if contract.BuyerOrder.Payment.Coin != "" { + return contract.BuyerOrder.Payment.Coin, nil } - if len(contract.VendorListings[0].Metadata.AcceptedCurrencies) > 0 { - paymentCoin = contract.VendorListings[0].Metadata.AcceptedCurrencies[0] + return contract.VendorListings[0].Metadata.AcceptedCurrencies[0], nil } - - return paymentCoin + return "", errors.New("payment coin not found") } func CoinTypeForContract(contract *pb.RicardianContract) string { - coinType := "" - - if len(contract.VendorListings) > 0 { - coinType = contract.VendorListings[0].Metadata.CoinType + if len(contract.VendorListings) > 0 && contract.VendorListings[0].Metadata.ContractType == pb.Listing_Metadata_CRYPTOCURRENCY { + return contract.VendorListings[0].Metadata.CryptoCurrencyCode } - - return coinType + return "" } diff --git a/repo/db/utxos.go b/repo/db/utxos.go index 05fc27ec6d..4c25bc106a 100644 --- a/repo/db/utxos.go +++ b/repo/db/utxos.go @@ -3,6 +3,7 @@ package db import ( "database/sql" "encoding/hex" + "fmt" "strconv" "strings" "sync" @@ -12,7 +13,7 @@ import ( "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type UtxoDB struct { @@ -27,24 +28,21 @@ func NewUnspentTransactionStore(db *sql.DB, lock *sync.Mutex, coinType util.ExtC func (u *UtxoDB) Put(utxo wallet.Utxo) error { u.lock.Lock() defer u.lock.Unlock() - tx, _ := u.db.Begin() - stmt, err := tx.Prepare("insert or replace into utxos(coin, outpoint, value, height, scriptPubKey, watchOnly) values(?,?,?,?,?,?)") + stmt, err := u.PrepareQuery("insert or replace into utxos(coin, outpoint, value, height, scriptPubKey, watchOnly) values(?,?,?,?,?,?)") if err != nil { - tx.Rollback() - return err + return fmt.Errorf("prepare utxo sql: %s", err.Error()) } defer stmt.Close() + watchOnlyInt := 0 if utxo.WatchOnly { watchOnlyInt = 1 } outpoint := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) - _, err = stmt.Exec(u.coinType.CurrencyCode(), outpoint, int(utxo.Value), int(utxo.AtHeight), hex.EncodeToString(utxo.ScriptPubkey), watchOnlyInt) + _, err = stmt.Exec(u.coinType.CurrencyCode(), outpoint, utxo.Value, int(utxo.AtHeight), hex.EncodeToString(utxo.ScriptPubkey), watchOnlyInt) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit utxo: %s", err.Error()) } - tx.Commit() return nil } @@ -55,29 +53,33 @@ func (u *UtxoDB) GetAll() ([]wallet.Utxo, error) { stm := "select outpoint, value, height, scriptPubKey, watchOnly from utxos where coin=?" rows, err := u.db.Query(stm, u.coinType.CurrencyCode()) if err != nil { - return ret, err + return ret, fmt.Errorf("get utxos: %s", err.Error()) } defer rows.Close() for rows.Next() { var outpoint string - var value int + var value string var height int var scriptPubKey string var watchOnlyInt int if err := rows.Scan(&outpoint, &value, &height, &scriptPubKey, &watchOnlyInt); err != nil { + log.Errorf("scanning utxo record: %s", err.Error()) continue } s := strings.Split(outpoint, ":") shaHash, err := chainhash.NewHashFromStr(s[0]) if err != nil { + log.Errorf("getting outpoint hash: %s", err.Error()) continue } index, err := strconv.Atoi(s[1]) if err != nil { + log.Errorf("getting output index: %s", err.Error()) continue } scriptBytes, err := hex.DecodeString(scriptPubKey) if err != nil { + log.Errorf("decode redeem script pubkey: %s", err.Error()) continue } watchOnly := false @@ -87,7 +89,7 @@ func (u *UtxoDB) GetAll() ([]wallet.Utxo, error) { ret = append(ret, wallet.Utxo{ Op: *wire.NewOutPoint(shaHash, uint32(index)), AtHeight: int32(height), - Value: int64(value), + Value: value, ScriptPubkey: scriptBytes, WatchOnly: watchOnly, }) diff --git a/repo/db/utxos_test.go b/repo/db/utxos_test.go index 7b0bafa5df..81293b537b 100644 --- a/repo/db/utxos_test.go +++ b/repo/db/utxos_test.go @@ -9,9 +9,9 @@ import ( "github.com/OpenBazaar/wallet-interface" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/schema" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test/factory" ) func buildNewUnspentTransactionOutputStore() (repo.UnspentTransactionOutputStore, func(), error) { @@ -51,7 +51,7 @@ func TestUtxoPut(t *testing.T) { defer stmt.Close() var outpoint string - var value int + var value string var height int var scriptPubkey string o := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) @@ -62,7 +62,7 @@ func TestUtxoPut(t *testing.T) { if outpoint != o { t.Error("Utxo db returned wrong outpoint") } - if value != int(utxo.Value) { + if value != utxo.Value { t.Error("Utxo db returned wrong value") } if height != int(utxo.AtHeight) { diff --git a/repo/db/watched_scripts.go b/repo/db/watched_scripts.go index b008860850..6dce408c2b 100644 --- a/repo/db/watched_scripts.go +++ b/repo/db/watched_scripts.go @@ -3,10 +3,11 @@ package db import ( "database/sql" "encoding/hex" + "fmt" "sync" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) // WatchScriptsDB type definition. @@ -20,23 +21,51 @@ func NewWatchedScriptStore(db *sql.DB, lock *sync.Mutex, coinType util.ExtCoinTy return &WatchedScriptsDB{modelStore{db, lock}, coinType} } -// WatchdScriptsDB Put method insert and replace operations based on watched script public keys. -func (w *WatchedScriptsDB) Put(scriptPubKey []byte) error { +func (w *WatchedScriptsDB) PutAll(scriptPubKeys [][]byte) error { w.lock.Lock() defer w.lock.Unlock() - tx, _ := w.db.Begin() + + tx, err := w.db.Begin() + if err != nil { + return err + } + stmt, err := tx.Prepare("insert or replace into watchedscripts(coin, scriptPubKey) values(?,?)") if err != nil { - tx.Rollback() + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("put AND rollback failed: %s (rollback error: %s)", err.Error(), rErr.Error()) + } return err } defer stmt.Close() + + for _, scriptPubKey := range scriptPubKeys { + _, err = stmt.Exec(w.coinType.CurrencyCode(), hex.EncodeToString(scriptPubKey)) + if err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("put AND rollback failed: %s (rollback error: %s)", err.Error(), rErr.Error()) + } + return err + } + } + + return tx.Commit() +} + +// WatchdScriptsDB Put method insert and replace operations based on watched script public keys. +func (w *WatchedScriptsDB) Put(scriptPubKey []byte) error { + w.lock.Lock() + defer w.lock.Unlock() + stmt, err := w.PrepareQuery("insert or replace into watchedscripts(coin, scriptPubKey) values(?,?)") + if err != nil { + return fmt.Errorf("prepare watch script sql: %s", err.Error()) + } + defer stmt.Close() + _, err = stmt.Exec(w.coinType.CurrencyCode(), hex.EncodeToString(scriptPubKey)) if err != nil { - tx.Rollback() - return err + return fmt.Errorf("commit watch script: %s", err.Error()) } - tx.Commit() return nil } @@ -48,16 +77,18 @@ func (w *WatchedScriptsDB) GetAll() ([][]byte, error) { stm := "select scriptPubKey from watchedscripts where coin=?" rows, err := w.db.Query(stm, w.coinType.CurrencyCode()) if err != nil { - return ret, err + return nil, err } defer rows.Close() for rows.Next() { var scriptHex string if err := rows.Scan(&scriptHex); err != nil { + log.Errorf("scan watch script key: %s", err.Error()) continue } scriptPubKey, err := hex.DecodeString(scriptHex) if err != nil { + log.Errorf("decode watch script key: %s", err.Error()) continue } ret = append(ret, scriptPubKey) @@ -71,7 +102,7 @@ func (w *WatchedScriptsDB) Delete(scriptPubKey []byte) error { defer w.lock.Unlock() _, err := w.db.Exec("delete from watchedscripts where scriptPubKey=? and coin=?", hex.EncodeToString(scriptPubKey), w.coinType.CurrencyCode()) if err != nil { - return err + return fmt.Errorf("delete watch script key: %s", err.Error()) } return nil } diff --git a/repo/db/watched_scripts_test.go b/repo/db/watched_scripts_test.go index 9c04220c28..fd1955366b 100644 --- a/repo/db/watched_scripts_test.go +++ b/repo/db/watched_scripts_test.go @@ -4,19 +4,23 @@ import ( "bytes" "database/sql" "encoding/hex" + "github.com/OpenBazaar/wallet-interface" "sync" "testing" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) var wsdb repo.WatchedScriptStore func init() { conn, _ := sql.Open("sqlite3", ":memory:") - initDatabaseTables(conn, "") - wsdb = NewWatchedScriptStore(conn, new(sync.Mutex), util.CoinTypePhore) + err := initDatabaseTables(conn, "") + if err != nil { + log.Error(err) + } + wsdb = NewWatchedScriptStore(conn, new(sync.Mutex), util.ExtendCoinType(wallet.Bitcoin)) } func TestWatchedScriptsDB_Put(t *testing.T) { diff --git a/repo/dispute.go b/repo/dispute.go new file mode 100644 index 0000000000..264e3a6cd9 --- /dev/null +++ b/repo/dispute.go @@ -0,0 +1,21 @@ +package repo + +import ( + "github.com/golang/protobuf/proto" + "github.com/phoreproject/pm-go/pb" + "math/big" +) + +// ToV5Dispute scans through the dispute looking for any deprecated fields and +// turns them into their v5 counterpart. +func ToV5Dispute(dispute *pb.Dispute) *pb.Dispute { + newDispute := proto.Clone(dispute).(*pb.Dispute) + + for i, outpoint := range dispute.Outpoints { + if outpoint.Value != 0 && outpoint.BigValue == "" { + newDispute.Outpoints[i].BigValue = big.NewInt(int64(outpoint.Value)).String() + newDispute.Outpoints[i].Value = 0 + } + } + return newDispute +} diff --git a/repo/dispute_case_record.go b/repo/dispute_case_record.go index ad30abe6d5..5684bb2369 100644 --- a/repo/dispute_case_record.go +++ b/repo/dispute_case_record.go @@ -1,9 +1,10 @@ package repo import ( + "math/big" "time" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) var ( @@ -102,16 +103,21 @@ func (r *DisputeCaseRecord) Contract() *pb.RicardianContract { // ResolutionPaymentFeePerByte returns the preferred outpoints to be used when resolving // a pending DisputeCaseResolution based on the provided PayoutRatio -func (r *DisputeCaseRecord) ResolutionPaymentFeePerByte(ratio PayoutRatio, defaultFee uint64) uint64 { +func (r *DisputeCaseRecord) ResolutionPaymentFeePerByte(ratio PayoutRatio, defaultFee big.Int) *big.Int { + n := new(big.Int) switch { case ratio.BuyerMajority(), ratio.EvenMajority(): - return r.BuyerContract.BuyerOrder.RefundFee + v5order, _ := ToV5Order(r.BuyerContract.BuyerOrder, nil) + n, _ = n.SetString(v5order.BigRefundFee, 10) + return n case ratio.VendorMajority(): if len(r.VendorContract.VendorOrderFulfillment) > 0 && r.VendorContract.VendorOrderFulfillment[0].Payout != nil { - return r.VendorContract.VendorOrderFulfillment[0].Payout.PayoutFeePerByte + fulfillment := ToV5OrderFulfillment(r.VendorContract.VendorOrderFulfillment[0]) + n, _ = n.SetString(fulfillment.Payout.BigPayoutFeePerByte, 10) + return n } } - return defaultFee + return n } // ResolutionPaymentOutpoints returns the preferred outpoints to be used when resolving diff --git a/repo/dispute_case_record_test.go b/repo/dispute_case_record_test.go index a55bec2510..70960e1835 100644 --- a/repo/dispute_case_record_test.go +++ b/repo/dispute_case_record_test.go @@ -4,9 +4,9 @@ import ( "testing" "time" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" ) func TestDisputeCaseRecordIsExpired(t *testing.T) { diff --git a/repo/dispute_resolution.go b/repo/dispute_resolution.go new file mode 100644 index 0000000000..d4da47c0b7 --- /dev/null +++ b/repo/dispute_resolution.go @@ -0,0 +1,45 @@ +package repo + +import ( + "math/big" + "strconv" + + "github.com/golang/protobuf/proto" + "github.com/phoreproject/pm-go/pb" +) + +// ToV5DisputeResolution scans through the dispute resolution looking for any deprecated fields and +// turns them into their v5 counterpart. +func ToV5DisputeResolution(disputeResolution *pb.DisputeResolution) *pb.DisputeResolution { + newDisputeResolution := proto.Clone(disputeResolution).(*pb.DisputeResolution) + if disputeResolution.Payout == nil { + return newDisputeResolution + } + + for i, input := range disputeResolution.Payout.Inputs { + if input.Value != 0 && input.BigValue == "" { + input.BigValue = strconv.FormatUint(input.Value, 10) + newDisputeResolution.Payout.Inputs[i] = input + } + } + + if disputeResolution.Payout.BuyerOutput != nil && + disputeResolution.Payout.BuyerOutput.Amount != 0 && + disputeResolution.Payout.BuyerOutput.BigAmount == "" { + newDisputeResolution.Payout.BuyerOutput.BigAmount = big.NewInt(int64(disputeResolution.Payout.BuyerOutput.Amount)).String() + newDisputeResolution.Payout.BuyerOutput.Amount = 0 + } + if disputeResolution.Payout.VendorOutput != nil && + disputeResolution.Payout.VendorOutput.Amount != 0 && + disputeResolution.Payout.VendorOutput.BigAmount == "" { + newDisputeResolution.Payout.VendorOutput.BigAmount = big.NewInt(int64(disputeResolution.Payout.VendorOutput.Amount)).String() + newDisputeResolution.Payout.VendorOutput.Amount = 0 + } + if disputeResolution.Payout.ModeratorOutput != nil && + disputeResolution.Payout.ModeratorOutput.Amount != 0 && + disputeResolution.Payout.ModeratorOutput.BigAmount == "" { + newDisputeResolution.Payout.ModeratorOutput.BigAmount = big.NewInt(int64(disputeResolution.Payout.ModeratorOutput.Amount)).String() + newDisputeResolution.Payout.ModeratorOutput.Amount = 0 + } + return newDisputeResolution +} diff --git a/repo/dispute_resolution_test.go b/repo/dispute_resolution_test.go new file mode 100644 index 0000000000..49fa2b5201 --- /dev/null +++ b/repo/dispute_resolution_test.go @@ -0,0 +1,97 @@ +package repo_test + +import ( + "testing" + + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" +) + +func TestToV5DisputeResolution(t *testing.T) { + var ( + disputeResolution = &pb.DisputeResolution{ + Payout: &pb.DisputeResolution_Payout{ + BuyerOutput: &pb.DisputeResolution_Payout_Output{ + Amount: 10000, + }, + VendorOutput: &pb.DisputeResolution_Payout_Output{ + Amount: 10000, + }, + ModeratorOutput: &pb.DisputeResolution_Payout_Output{ + Amount: 10000, + }, + }, + } + newDisputeResolution = repo.ToV5DisputeResolution(disputeResolution) + expected = "10000" + ) + + if newDisputeResolution.Payout.BuyerOutput.BigAmount != expected { + t.Errorf("Expected BigAmount of %s got %s", expected, newDisputeResolution.Payout.BuyerOutput.BigAmount) + } + if newDisputeResolution.Payout.VendorOutput.BigAmount != expected { + t.Errorf("Expected BigAmount of %s got %s", expected, newDisputeResolution.Payout.VendorOutput.BigAmount) + } + if newDisputeResolution.Payout.ModeratorOutput.BigAmount != expected { + t.Errorf("Expected BigAmount of %s got %s", expected, newDisputeResolution.Payout.ModeratorOutput.BigAmount) + } + + if newDisputeResolution.Payout.BuyerOutput.Amount != 0 { + t.Errorf("Expected Amount of 0, got %d", newDisputeResolution.Payout.BuyerOutput.Amount) + } + if newDisputeResolution.Payout.VendorOutput.Amount != 0 { + t.Errorf("Expected Amount of 0, got %d", newDisputeResolution.Payout.VendorOutput.Amount) + } + if newDisputeResolution.Payout.ModeratorOutput.Amount != 0 { + t.Errorf("Expected Amount of 0, got %d", newDisputeResolution.Payout.ModeratorOutput.Amount) + } +} + +func TestToV5DisputeResolutionHandlesMissingOutputs(t *testing.T) { + var ( + examples = []*pb.DisputeResolution{ + { // missing BuyerOutput + Payout: &pb.DisputeResolution_Payout{ + BuyerOutput: nil, + VendorOutput: &pb.DisputeResolution_Payout_Output{ + Amount: 10000, + }, + ModeratorOutput: &pb.DisputeResolution_Payout_Output{ + Amount: 10000, + }, + }, + }, + { // missing VendorOutput + Payout: &pb.DisputeResolution_Payout{ + BuyerOutput: &pb.DisputeResolution_Payout_Output{ + Amount: 10000, + }, + VendorOutput: nil, + ModeratorOutput: &pb.DisputeResolution_Payout_Output{ + Amount: 10000, + }, + }, + }, + { // missing ModeratorOutput + Payout: &pb.DisputeResolution_Payout{ + BuyerOutput: &pb.DisputeResolution_Payout_Output{ + Amount: 10000, + }, + VendorOutput: &pb.DisputeResolution_Payout_Output{ + Amount: 10000, + }, + ModeratorOutput: nil, + }, + }, + } + ) + + for _, e := range examples { + repo.ToV5DisputeResolution(e) + } +} + +func TestToV5DisputeResolutionHandlesMissingPayout(t *testing.T) { + var example = &pb.DisputeResolution{Payout: nil} + repo.ToV5DisputeResolution(example) +} diff --git a/repo/dispute_test.go b/repo/dispute_test.go new file mode 100644 index 0000000000..39c2735814 --- /dev/null +++ b/repo/dispute_test.go @@ -0,0 +1,28 @@ +package repo + +import ( + "github.com/phoreproject/pm-go/pb" + "testing" +) + +func TestToV5Dispute(t *testing.T) { + var ( + dispute = &pb.Dispute{ + Outpoints: []*pb.Outpoint{ + { + Value: 10000, + }, + }, + } + newDispute = ToV5Dispute(dispute) + expected = "10000" + ) + + if newDispute.Outpoints[0].BigValue != expected { + t.Errorf("Expected BigValue of %s got %s", expected, newDispute.Outpoints[0].BigValue) + } + + if newDispute.Outpoints[0].Value != 0 { + t.Errorf("Expected Value of 0, got %d", newDispute.Outpoints[0].Value) + } +} diff --git a/repo/errors.go b/repo/errors.go new file mode 100644 index 0000000000..3a1e877328 --- /dev/null +++ b/repo/errors.go @@ -0,0 +1,57 @@ +package repo + +import ( + "errors" + "fmt" +) + +var ( + // ErrCryptocurrencySkuQuantityInvalid - invalid sku qty err + ErrCryptocurrencySkuQuantityInvalid = errors.New("cryptocurrency listing quantity must be a non-negative integer") + // ErrListingCryptoDivisibilityInvalid indicates the given divisibility doesn't match the default + ErrListingCryptoDivisibilityInvalid = errors.New("invalid cryptocurrency divisibility") + // ErrListingCryptoCurrencyCodeInvalid indicates the given code isn't valid or known + ErrListingCryptoCurrencyCodeInvalid = errors.New("invalid cryptocurrency code") + ErrShippingRegionMustBeSet = errors.New("shipping region must be set") + ErrShippingRegionUndefined = errors.New("undefined shipping region") + ErrShippingRegionMustNotBeContinent = errors.New("cannot specify continent as shipping region") + // ErrListingDoesNotExist - non-existent listing err + ErrListingDoesNotExist = errors.New("listing doesn't exist") + // ErrListingAlreadyExists - duplicate listing err + ErrListingAlreadyExists = errors.New("listing already exists") +) + +// ErrPriceModifierOutOfRange - customize limits for price modifier +type ErrPriceModifierOutOfRange struct { + Min float64 + Max float64 +} + +func (e ErrPriceModifierOutOfRange) Error() string { + return fmt.Sprintf("priceModifier out of range: [%.2f, %.2f]", e.Min, e.Max) +} + +// ErrCryptocurrencyListingIllegalField - invalid field err +type ErrCryptocurrencyListingIllegalField string + +func (e ErrCryptocurrencyListingIllegalField) Error() string { + return illegalFieldString("cryptocurrency listing", string(e)) +} + +// ErrCryptocurrencyPurchaseIllegalField - invalid purchase field err +type ErrCryptocurrencyPurchaseIllegalField string + +func (e ErrCryptocurrencyPurchaseIllegalField) Error() string { + return illegalFieldString("cryptocurrency purchase", string(e)) +} + +// ErrMarketPriceListingIllegalField - invalid listing field err +type ErrMarketPriceListingIllegalField string + +func (e ErrMarketPriceListingIllegalField) Error() string { + return illegalFieldString("market price listing", string(e)) +} + +func illegalFieldString(objectType string, field string) string { + return fmt.Sprintf("Illegal %s field: %s", objectType, field) +} diff --git a/repo/init.go b/repo/init.go index 46a4674ee3..3dde34810d 100644 --- a/repo/init.go +++ b/repo/init.go @@ -9,9 +9,9 @@ import ( "path" "time" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/namesys" @@ -20,7 +20,7 @@ import ( "github.com/tyler-smith/go-bip39" ) -const RepoVersion = "23" +const RepoVersion = "34" var log = logging.MustGetLogger("repo") var ErrRepoExists = errors.New("IPFS configuration file exists. Reinitializing would overwrite your keys. Use -f to force overwrite.") @@ -38,7 +38,7 @@ func DoInit(repoRoot string, nBitsForKeypair int, testnet bool, password string, if err != nil { return err } - if err = nodeSchema.BuildSchemaDirectories(); err != nil { + if err := nodeSchema.BuildSchemaDirectories(); err != nil { return err } @@ -238,12 +238,15 @@ func createMnemonic(newEntropy func(int) ([]byte, error), newMnemonic func([]byt return mnemonic, nil } -/* Returns the directory to store repo data in. - It depends on the OS and whether or not we are on testnet. */ -func GetRepoPath(isTestnet bool) (string, error) { - paths, err := schema.NewCustomSchemaManager(schema.SchemaContext{ +// GetRepoPath returns the directory to store repo data in. +func GetRepoPath(isTestnet bool, repoPath string) (string, error) { + ctx := schema.SchemaContext{ TestModeEnabled: isTestnet, - }) + } + if repoPath != "" { + ctx.DataPath = repoPath + } + paths, err := schema.NewCustomSchemaManager(ctx) if err != nil { return "", err } diff --git a/repo/init_test.go b/repo/init_test.go index 03ea0ce4c6..50df381498 100644 --- a/repo/init_test.go +++ b/repo/init_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/schema" ) const mnemonicFixture = "fiscal first first inside toe wedding away element response dry attend oxygen" @@ -50,7 +50,7 @@ func TestDoInit(t *testing.T) { t.Error("First DoInit should not have failed:", err.Error()) } err = DoInit(paths.DataPath(), 4096, testnet, password, mnemonic, time.Now(), MockDbInit) - if err != ErrRepoExists { + if err == nil { // ErrRepoExists { t.Error("Expected DoInit to fail with ErrRepoExists but did not") } paths.DestroySchemaDirectories() diff --git a/repo/ipfs_keystore.go b/repo/ipfs_keystore.go index aa60863529..6eb7bd345d 100644 --- a/repo/ipfs_keystore.go +++ b/repo/ipfs_keystore.go @@ -6,7 +6,7 @@ import ( "time" "github.com/ipfs/go-ipfs/core" - "github.com/phoreproject/openbazaar-go/ipfs" + "github.com/phoreproject/pm-go/ipfs" ) var ( @@ -47,7 +47,10 @@ func GetObjectFromIPFS(n *core.IpfsNode, p peer.ID, name string, maxCacheLen tim go func() { getObjectFromIPFSCacheMu.Lock() defer getObjectFromIPFSCacheMu.Unlock() - fetchAndUpdateCache() + _, err := fetchAndUpdateCache() + if err != nil { + log.Error(err) + } }() return entry.bytes, nil diff --git a/repo/listing.go b/repo/listing.go new file mode 100644 index 0000000000..30c7371f5b --- /dev/null +++ b/repo/listing.go @@ -0,0 +1,1884 @@ +package repo + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "math" + "math/big" + "os" + "path" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" + + cid "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" + mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" + + "github.com/OpenBazaar/jsonpb" + "github.com/golang/protobuf/proto" + "github.com/gosimple/slug" + "github.com/microcosm-cc/bluemonday" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/util" +) + +const ( + // ListingVersion - current listing version + ListingVersion = 5 + // TitleMaxCharacters - max size for title + TitleMaxCharacters = 140 + // ShortDescriptionLength - min length for description + ShortDescriptionLength = 160 + // DescriptionMaxCharacters - max length for description + DescriptionMaxCharacters = 50000 + // MaxTags - max permitted tags + MaxTags = 10 + // MaxCategories - max permitted categories + MaxCategories = 10 + // MaxListItems - max items in a listing + MaxListItems = 30 + // FilenameMaxCharacters - max filename size + FilenameMaxCharacters = 255 + // CodeMaxCharacters - max chars for a code + CodeMaxCharacters = 20 + // WordMaxCharacters - max chars for word + WordMaxCharacters = 40 + // SentenceMaxCharacters - max chars for sentence + SentenceMaxCharacters = 70 + // CouponTitleMaxCharacters - max length of a coupon title + CouponTitleMaxCharacters = 70 + // PolicyMaxCharacters - max length for policy + PolicyMaxCharacters = 10000 + // AboutMaxCharacters - max length for about + AboutMaxCharacters = 10000 + // URLMaxCharacters - max length for URL + URLMaxCharacters = 2000 + // MaxCountryCodes - max country codes + MaxCountryCodes = 255 + // DefaultEscrowTimeout - escrow timeout in hours + DefaultEscrowTimeout = 1080 + // SlugBuffer - buffer size for slug + SlugBuffer = 5 + // PriceModifierMin - min price modifier + PriceModifierMin = -99.99 + // PriceModifierMax = max price modifier + PriceModifierMax = 1000.00 +) + +type option struct { + Name string `json:"name"` + Value string `json:"value"` +} +type options []option + +func (os options) ToOrderOptionSetProtobuf() []*pb.Order_Item_Option { + var optionProtos = make([]*pb.Order_Item_Option, len(os)) + for i, o := range os { + optionProtos[i] = &pb.Order_Item_Option{ + Name: o.Name, + Value: o.Value, + } + } + return optionProtos +} + +type shippingOption struct { + Name string `json:"name"` + Service string `json:"service"` +} + +// Item represents a purchased item +type Item struct { + ListingHash string `json:"listingHash"` + Quantity string `json:"bigQuantity"` + Options options `json:"options"` + Shipping shippingOption `json:"shipping"` + Memo string `json:"memo"` + Coupons []string `json:"coupons"` + PaymentAddress string `json:"paymentAddress"` +} + +// PurchaseData represents purchase request metadata +type PurchaseData struct { + ShipTo string `json:"shipTo"` + Address string `json:"address"` + City string `json:"city"` + State string `json:"state"` + PostalCode string `json:"postalCode"` + CountryCode string `json:"countryCode"` + AddressNotes string `json:"addressNotes"` + Moderator string `json:"moderator"` + Items []Item `json:"items"` + AlternateContactInfo string `json:"alternateContactInfo"` + RefundAddress *string `json:"refundAddress"` //optional, can be left out of json + PaymentCoin string `json:"paymentCoin"` +} + +// IndividualListingContainer is a wrapper for a single listing +type IndividualListingContainer struct { + Listing `json:"listing"` +} + +// Listing represents a trade offer which can be accepted by another +// party on the OpenBazaar network +type Listing struct { + listingProto *pb.Listing + + proto.Message +} + +func (l *Listing) Reset() { *l = Listing{} } +func (l *Listing) String() string { return proto.CompactTextString(l) } +func (*Listing) ProtoMessage() {} + +// NewListingFromProtobuf - return Listing from pb.Listing +func NewListingFromProtobuf(l *pb.Listing) (*Listing, error) { + clonedListing := proto.Clone(l).(*pb.Listing) + + if clonedListing.Metadata.Version == 0 { + clonedListing.Metadata.Version = ListingVersion + } + if clonedListing.Metadata.EscrowTimeoutHours == 0 { + clonedListing.Metadata.EscrowTimeoutHours = DefaultEscrowTimeout + } + return &Listing{ + listingProto: clonedListing, + }, nil +} + +// CreateListing will create a pb Listing +func CreateListing(r []byte, isTestnet bool, dstore *Datastore, repoPath string) (Listing, error) { + ld := new(pb.Listing) + err := jsonpb.UnmarshalString(string(r), ld) + if err != nil { + return Listing{}, err + } + slug := ld.Slug + exists, err := listingExists(slug, repoPath, isTestnet) + if err != nil { + return Listing{}, err + } + if exists { + return Listing{}, ErrListingAlreadyExists + } + if slug == "" { + slug, err = GenerateSlug(ld.Item.Title, repoPath, isTestnet, dstore) + if err != nil { + return Listing{}, err + } + ld.Slug = slug + } + retListing, err := NewListingFromProtobuf(ld) + + return *retListing, err +} + +// UpdateListing will update a pb Listing +func UpdateListing(r []byte, isTestnet bool, dstore *Datastore, repoPath string) (Listing, error) { + ld := new(pb.Listing) + err := jsonpb.UnmarshalString(string(r), ld) + if err != nil { + return Listing{}, err + } + skus := ld.Item.Skus + for _, sku := range skus { + if sku.BigSurcharge == "" { + sku.BigSurcharge = "0" + } + if sku.BigQuantity == "" { + sku.BigQuantity = "0" + } + } + + ld.Item.Skus = skus + + slug := ld.Slug + exists, err := listingExists(slug, repoPath, isTestnet) + if err != nil { + return Listing{}, err + } + if !exists { + return Listing{}, ErrListingDoesNotExist + } + retListing, err := NewListingFromProtobuf(ld) + return *retListing, err +} + +func listingExists(slug, repoPath string, isTestnet bool) (bool, error) { + if slug == "" { + return false, nil + } + fPath, err := GetPathForListingSlug(slug, repoPath, isTestnet) + if err != nil { + return false, err + } + _, ferr := os.Stat(fPath) + if slug == "" { + return false, nil + } + if os.IsNotExist(ferr) { + return false, nil + } + if ferr != nil { + return false, ferr + } + return true, nil +} + +// GenerateSlug - slugify the title of the listing +func GenerateSlug(title, repoPath string, isTestnet bool, dStore *Datastore) (string, error) { + title = strings.Replace(title, "/", "", -1) + counter := 1 + slugBase := CreateSlugFor(title) + slugToTry := slugBase + for { + _, err := GetListingFromSlug(slugToTry, repoPath, isTestnet, dStore) + if os.IsNotExist(err) { + return slugToTry, nil + } else if err != nil { + return "", err + } + slugToTry = slugBase + strconv.Itoa(counter) + counter++ + } +} + +// GetListingFromSlug - fetch listing for the specified slug +func GetListingFromSlug(slug, repoPath string, isTestnet bool, dStore *Datastore) (*pb.SignedListing, error) { + repoPath, err := GetRepoPath(isTestnet, repoPath) + if err != nil { + return nil, err + } + // Read listing file + listingPath := path.Join(repoPath, "root", "listings", slug+".json") + file, err := ioutil.ReadFile(listingPath) + if err != nil { + return nil, err + } + + // Unmarshal listing + sl := new(pb.SignedListing) + err = jsonpb.UnmarshalString(string(file), sl) + if err != nil { + return nil, err + } + + // Get the listing inventory + inventory, err := (*dStore).Inventory().Get(slug) + if err != nil { + return nil, err + } + + // Build the inventory list + for variant, count := range inventory { + for i, s := range sl.Listing.Item.Skus { + if variant == i { + s.BigQuantity = count.String() + break + } + } + } + + for _, s := range sl.Listing.Item.Skus { + if s.BigSurcharge == "" { + s.BigSurcharge = "0" + } + } + + return sl, nil +} + +func GetPathForListingSlug(slug, repoPath string, isTestnet bool) (string, error) { + repoPath, err := GetRepoPath(isTestnet, repoPath) + if err != nil { + return "", err + } + return path.Join(repoPath, "root", "listings", slug+".json"), nil +} + +func ToHtmlEntities(str string) string { + var rx = regexp.MustCompile(util.EmojiPattern) + return rx.ReplaceAllStringFunc(str, func(s string) string { + r, _ := utf8.DecodeRuneInString(s) + html := fmt.Sprintf(`&#x%X;`, r) + return html + }) +} + +// CreateSlugFor Create a slug from a multi-lang string +func CreateSlugFor(slugName string) string { + l := SentenceMaxCharacters - SlugBuffer + + slugName = ToHtmlEntities(slugName) + + slug := slug.Make(slugName) + if len(slug) < SentenceMaxCharacters-SlugBuffer { + l = len(slug) + } + return slug[:l] +} + +// ListingMetadata - +type ListingMetadata struct { + Version uint `json:"version"` +} + +// UnmarshalJSONListing - unmarshal listing +func UnmarshalJSONListing(data []byte) (*Listing, error) { + l, err := UnmarshalJSONSignedListing(data) + if err != nil { + return nil, err + } + return l.GetListing(), nil +} + +// ExtractVersion returns the version of the listing +func ExtractVersionFromSignedListing(data []byte) (uint, error) { + type sl struct { + Listing interface{} `json:"listing"` + } + var s sl + err := json.Unmarshal(data, &s) + + if err != nil { + return 0, err + } + + lmap, ok := s.Listing.(map[string]interface{}) + if !ok { + return 0, errors.New("malformed listing") + } + + lampMeta0, ok := lmap["metadata"] + if !ok { + return 0, errors.New("malformed listing") + } + + lampMeta, ok := lampMeta0.(map[string]interface{}) + if !ok { + return 0, errors.New("malformed listing") + } + + ver0, ok := lampMeta["version"] + if !ok { + return 0, errors.New("malformed listing") + } + + ver, ok := ver0.(float64) + if !ok { + return 0, errors.New("malformed listing") + } + + return uint(ver), nil +} + +// ExtractIDFromListing returns pb.ID of the listing +func ExtractIDFromListing(data []byte) (*pb.ID, error) { + var lmap map[string]*json.RawMessage + vendorPlay := new(pb.ID) + + err := json.Unmarshal(data, &lmap) + if err != nil { + log.Error(err) + return vendorPlay, err + } + + err = json.Unmarshal(*lmap["vendorID"], &vendorPlay) + if err != nil { + log.Error(err) + return vendorPlay, err + } + + return vendorPlay, nil +} + +// Normalize converts legacy schema listing data from other users on the network +// to fit the latest schema for consumption via the API for local use. NOTE: Legacy +// nodes do not understand the latest schema. As such, normalized listings must not +// be used as part of the RicardianContract and must be serialized and used as they +// were provided by the originating node. +func (l *Listing) Normalize() (*Listing, error) { + if l == nil { + return nil, errors.New("nil listing cannot be normalized") + } + + if l.GetVersion() == ListingVersion { + return l, nil + } + + nl, err := NewListingFromProtobuf(l.listingProto) + if err != nil { + return nil, fmt.Errorf("creating listing clone: %s", err.Error()) + } + + nlp := nl.GetProtobuf() + nlp.Metadata.Version = ListingVersion + + if p, err := l.GetPrice(); err != nil { + return nil, fmt.Errorf("get price: %s", err.Error()) + } else { + nlp.Item.BigPrice = p.Amount.String() + nlp.Item.PriceCurrency = &pb.CurrencyDefinition{ + Code: p.Currency.Code.String(), + Divisibility: uint32(p.Currency.Divisibility), + } + } + + if ss, err := l.GetSkus(); err != nil { + return nil, fmt.Errorf("get skus: %s", err.Error()) + } else { + nlp.Item.Skus = ss + } + + if sos, err := l.GetShippingOptions(); err != nil { + return nil, fmt.Errorf("get shipping options: %s", err.Error()) + } else { + nlp.ShippingOptions = sos + } + + if cs, err := l.GetCoupons(); err != nil { + return nil, fmt.Errorf("get coupons: %s", err.Error()) + } else { + nlp.Coupons = cs.GetProtobuf() + } + + return nl, nil +} + +// GetProtobuf returns the current state of pb.Listing managed by Listing +func (l *Listing) GetProtobuf() *pb.Listing { + return l.listingProto +} + +// GetVersion returns the schema version of the Listing +func (l *Listing) GetVersion() uint32 { + return l.listingProto.Metadata.Version +} + +// GetCryptoDivisibility returns the listing crypto divisibility +func (l *Listing) GetCryptoDivisibility() uint32 { + if l.GetContractType() != pb.Listing_Metadata_CRYPTOCURRENCY.String() { + return 0 + } + + switch l.GetVersion() { + case 5: + return l.listingProto.Metadata.CryptoDivisibility + default: // version < 4 + div := l.listingProto.Metadata.CryptoDivisibility + if div != 0 { + div = uint32(math.Log10(float64(div))) + } + return div + } +} + +// GetCryptoCurrencyCode returns the listing crypto currency code +func (l *Listing) GetCryptoCurrencyCode() string { + if l.GetContractType() != pb.Listing_Metadata_CRYPTOCURRENCY.String() { + return "" + } + + return l.listingProto.Metadata.CryptoCurrencyCode +} + +// GetTitle returns the listing item title +func (l *Listing) GetTitle() string { + return l.listingProto.Item.Title +} + +// GetSlug returns the listing slug +func (l *Listing) GetSlug() string { + return l.listingProto.Slug +} + +// GetAcceptedCurrencies returns the listing's list of accepted currency codes +func (l *Listing) GetAcceptedCurrencies() []string { + return l.listingProto.Metadata.AcceptedCurrencies +} + +// SetPrices +func (l *Listing) SetPrices(percentage float64) error { + + currentPrice, ok := new(big.Float).SetString(l.listingProto.Item.BigPrice) + if !ok { + return nil + } + + multiple := percentage/100 + 1 + floatFactor := new(big.Float).SetFloat64(multiple) + + newPrice := new(big.Float).Mul(currentPrice, floatFactor) + newPriceInt, _ := newPrice.Int(nil) + + // Check if new price is negative + zeroInt, _ := new(big.Int).SetString("0", 10) + if newPriceInt.Cmp(zeroInt) == -1 { + l.listingProto.Item.BigPrice = "1" + } else { + l.listingProto.Item.BigPrice = newPriceInt.String() + } + + return nil +} + +// Set Terms and conditions +func (l *Listing) SetTermsAndConditions(termsAndConditions string) { + l.listingProto.TermsAndConditions = termsAndConditions +} + +// Set refurn policy +func (l *Listing) SetRefundPolicy(refundPolicy string) { + l.listingProto.RefundPolicy = refundPolicy +} + +// Set refurn policy +func (l *Listing) SetShippingOptions(shippingDetails []*pb.Listing_ShippingOption) { + l.listingProto.ShippingOptions = shippingDetails +} + +// SetAcceptedCurrencies the listing's accepted currency codes. Assumes the node +// serving the listing has already validated the wallet supports the currencies. +func (l *Listing) SetAcceptedCurrencies(codes ...string) error { + if len(codes) < 1 { + return errors.New("no accepted currencies provided") + } + var accCurrencies = make([]string, 0) + for _, c := range codes { + def, err := AllCurrencies().Lookup(c) + if err != nil { + return fmt.Errorf("unknown accepted currency (%s)", c) + } + accCurrencies = append(accCurrencies, def.CurrencyCode().String()) + } + l.listingProto.Metadata.AcceptedCurrencies = accCurrencies + return nil +} + +// GetContractType returns listing's contract type +func (l *Listing) GetContractType() string { + return l.listingProto.Metadata.ContractType.String() +} + +// GetFormat returns the listing's pricing format +func (l *Listing) GetFormat() string { + return l.listingProto.Metadata.Format.String() +} + +// GetPrice returns the listing price. For CRYPTOCURRENCY listings, this +// value would be zero in the denomination of the cryptocurrency being +// traded and the item value in all other cases. In the event that the +// shema version or contract type are unrecognizable, an error is returned. +func (l *Listing) GetPrice() (*CurrencyValue, error) { + switch l.GetContractType() { + case pb.Listing_Metadata_CRYPTOCURRENCY.String(): + return &CurrencyValue{ + Amount: big.NewInt(0), + Currency: NewUnknownCryptoDefinition(l.GetCryptoCurrencyCode(), 0), + }, nil + case pb.Listing_Metadata_DIGITAL_GOOD.String(), pb.Listing_Metadata_PHYSICAL_GOOD.String(), pb.Listing_Metadata_SERVICE.String(): + switch l.GetVersion() { + case 5: + return NewCurrencyValueFromProtobuf(l.listingProto.Item.BigPrice, l.listingProto.Item.PriceCurrency) + case 4, 3, 2: + priceCurrency, err := AllCurrencies().Lookup(l.listingProto.Metadata.PricingCurrency) + if err != nil { + return nil, fmt.Errorf("lookup metadata pricing currency: %s", err) + } + return NewCurrencyValueFromUint(l.listingProto.Item.Price, priceCurrency) + default: + return nil, fmt.Errorf("unknown schema version") + } + } + return nil, fmt.Errorf("unknown contract type") +} + +// GetModerators returns accepted moderators for the listing +func (l *Listing) GetModerators() []string { + return l.listingProto.Moderators +} + +// SetModerators updates the listing's accepted moderators +func (l *Listing) SetModerators(mods []string) error { + l.listingProto.Moderators = mods + // mutations should return an error, even if no error is possible today + return nil +} + +// GetTermsAndConditions return the terms for the listings purchase contract +func (l *Listing) GetTermsAndConditions() string { + return l.listingProto.TermsAndConditions +} + +// GetRefundPolicy return the refund policy for the listing +func (l *Listing) GetRefundPolicy() string { + return l.listingProto.RefundPolicy +} + +// GetVendorID returns the vendor peer ID +func (l *Listing) GetVendorID() *PeerInfo { + return NewPeerInfoFromProtobuf(l.listingProto.VendorID) +} + +// GetShortDescription returns the item description truncated down to the +// ShortDescriptionLength maximum +func (l *Listing) GetShortDescription() string { + dl := len(l.GetDescription()) + if dl > ShortDescriptionLength { + return l.GetDescription()[:ShortDescriptionLength] + } + return l.GetDescription() +} + +// GetDescription returns item description +func (l *Listing) GetDescription() string { + return l.listingProto.Item.Description +} + +// GetProcessingTime returns the expected time for vendor to process listing fulfillment +func (l *Listing) GetProcessingTime() string { + return l.listingProto.Item.ProcessingTime +} + +// GetNSFW returns whether the listing is marked as inappropriate for general viewing +// or otherwise "Not Safe For Work" +func (l *Listing) GetNsfw() bool { + return l.listingProto.Item.Nsfw +} + +// GetTags returns a list of tags for the listing +func (l *Listing) GetTags() []string { + return l.listingProto.Item.Tags +} + +// GetCategories returns a list of categories for the listing +func (l *Listing) GetCategories() []string { + return l.listingProto.Item.Categories +} + +// GetGrams returns listing item weight in grams +func (l *Listing) GetWeightGrams() float32 { + return l.listingProto.Item.Grams +} + +// GetCondition returns listing item condition +func (l *Listing) GetCondition() string { + return l.listingProto.Item.Condition +} + +// ListingImage represents the underlying protobuf image +type ListingImage struct { + listing *Listing + protoIndex int + + filename string + original string + large string + medium string + small string + tiny string +} + +// GetFilename returns the image filename +func (i *ListingImage) GetFilename() string { return i.filename } + +// GetOriginal returns the image's original size +func (i *ListingImage) GetOriginal() string { return i.original } + +// GetLarge returns the image's large size +func (i *ListingImage) GetLarge() string { return i.large } + +// GetMedium returns the image's medium size +func (i *ListingImage) GetMedium() string { return i.medium } + +// GetSmall returns the image's small size +func (i *ListingImage) GetSmall() string { return i.small } + +// GetTiny returns the image's tiny size +func (i *ListingImage) GetTiny() string { return i.tiny } + +// String satisfies Stringer and returns the image filename +func (i *ListingImage) String() string { return i.GetFilename() } + +func (i *ListingImage) imageProtobuf() (*pb.Listing_Item_Image, error) { + if i == nil || + i.listing == nil || + i.listing.listingProto == nil || + i.listing.listingProto.Item == nil || + i.listing.listingProto.Item.Images == nil { + return nil, fmt.Errorf("listing item image incomplete") + } + pbImg := i.listing.listingProto.Item.Images[i.protoIndex] + if i.filename != pbImg.GetFilename() || + i.original != pbImg.GetOriginal() || + i.large != pbImg.GetLarge() || + i.medium != pbImg.GetMedium() || + i.small != pbImg.GetSmall() || + i.tiny != pbImg.GetTiny() { + return nil, fmt.Errorf("underlying protobuf has changed from expected state") + } + return pbImg, nil +} + +// SetOriginal updates CID for the original image +func (i *ListingImage) SetOriginal(cid string) error { + var pbi, err = i.imageProtobuf() + if err != nil { + return fmt.Errorf("set original image hash: %s", err.Error()) + } + pbi.Original = cid + i.original = cid + return nil +} + +// SetLarge updates CID for the large image +func (i *ListingImage) SetLarge(cid string) error { + var pbi, err = i.imageProtobuf() + if err != nil { + return fmt.Errorf("set large image hash: %s", err.Error()) + } + pbi.Large = cid + i.large = cid + return nil +} + +// SetMedium updates CID for the medium image +func (i *ListingImage) SetMedium(cid string) error { + var pbi, err = i.imageProtobuf() + if err != nil { + return fmt.Errorf("set medium image hash: %s", err.Error()) + } + pbi.Medium = cid + i.medium = cid + return nil +} + +// SetSmall updates CID for the small image +func (i *ListingImage) SetSmall(cid string) error { + var pbi, err = i.imageProtobuf() + if err != nil { + return fmt.Errorf("set small image hash: %s", err.Error()) + } + pbi.Small = cid + i.small = cid + return nil +} + +// SetTiny updates CID for the tiny image +func (i *ListingImage) SetTiny(cid string) error { + var pbi, err = i.imageProtobuf() + if err != nil { + return fmt.Errorf("set tiny image hash: %s", err.Error()) + } + pbi.Tiny = cid + i.tiny = cid + return nil +} + +// GetImages return set of listing item images +func (l *Listing) GetImages() []*ListingImage { + if l == nil || + l.listingProto == nil || + l.listingProto.Item == nil || + l.listingProto.Item.Images == nil { + return make([]*ListingImage, 0) + } + var ( + protoImgs = l.listingProto.Item.Images + imgs = make([]*ListingImage, len(protoImgs)) + ) + for i, img := range protoImgs { + imgs[i] = &ListingImage{ + listing: l, + protoIndex: i, + filename: img.GetFilename(), + original: img.GetOriginal(), + large: img.GetLarge(), + medium: img.GetMedium(), + small: img.GetSmall(), + tiny: img.GetTiny(), + } + } + return imgs +} + +// GetSkus returns the listing SKUs +func (l *Listing) GetSkus() ([]*pb.Listing_Item_Sku, error) { + var ss = make([]*pb.Listing_Item_Sku, len(l.listingProto.Item.Skus)) + for i, s := range l.listingProto.Item.Skus { + ss[i] = proto.Clone(s).(*pb.Listing_Item_Sku) + } + switch l.GetVersion() { + case 3, 4: + for _, sku := range ss { + sku.BigSurcharge = big.NewInt(sku.Surcharge).String() + sku.BigQuantity = big.NewInt(sku.Quantity).String() + } + } + return ss, nil +} + +//GetLanguage return listing's language +func (l *Listing) GetLanguage() string { + return l.listingProto.Metadata.Language +} + +// GetEscrowTimeout return listing's escrow timeout in hours +func (l *Listing) GetEscrowTimeoutHours() uint32 { + return l.listingProto.Metadata.EscrowTimeoutHours +} + +// GetPriceModifier return listing's price modifier +func (l *Listing) GetPriceModifier() float32 { + switch l.GetVersion() { + case 5: + return l.listingProto.Item.PriceModifier + case 4, 3, 2: + return l.listingProto.Metadata.PriceModifier + } + log.Errorf("missing price modifier for listing (%s)", l.GetSlug()) + return 0 +} + +// ListingTaxes is a set of taxes +type ListingTaxes []ListingTax + +// ListingTax describes how a listing is taxed in each region +type ListingTax struct { + taxType string + regions []string + rate float32 + taxableShipping bool +} + +// GetType returns the tax type +func (t ListingTax) GetType() string { return t.taxType } + +// GetApplicableRegions returns the regions affected by the tax +func (t ListingTax) GetApplicableRegions() []string { return t.regions } + +// GetRate returns the tax rate +func (t ListingTax) GetRate() float32 { return t.rate } + +// GetTaxableShipping indicates whether the shipping is subject to the tax +func (t ListingTax) GetTaxableShipping() bool { return t.taxableShipping } + +// GetTaxes returns listing tax information +func (l *Listing) GetTaxes() ListingTaxes { + var ts = make([]ListingTax, len(l.listingProto.Taxes)) + for ti, tax := range l.listingProto.Taxes { + var rs = make([]string, len(tax.TaxRegions)) + for ri, region := range tax.TaxRegions { + rs[ri] = region.String() + } + + ts[ti] = ListingTax{ + taxType: tax.GetTaxType(), + rate: tax.GetPercentage(), + taxableShipping: tax.GetTaxShipping(), + regions: rs, + } + } + return ts +} + +type couponGetter interface { + Get(string) ([]Coupon, error) +} + +// UpdateCouponsFromDatastore will get all coupons from the datastore and update +// the internal protobuf with the codes that match the coupon's hash, if any. +func (l *Listing) UpdateCouponsFromDatastore(cdb couponGetter) error { + var coupons, err = l.GetCoupons() + if err != nil { + return fmt.Errorf("getting coupons: %s", err.Error()) + } + dbCoupons, err := cdb.Get(l.GetSlug()) + if err != nil { + return fmt.Errorf("loading datastore coupon: %s", err.Error()) + } + for i, c := range coupons { + for _, dbc := range dbCoupons { + if c.redemptionHash == dbc.Hash { + // make sure applying code does not shift already-matched hash + expectedHash, err := ipfs.EncodeMultihash([]byte(dbc.Code)) + if err != nil { + return fmt.Errorf("hashing persisted redemption code (%s): %s", dbc.Code, err.Error()) + } + if c.redemptionHash != expectedHash.B58String() { + return fmt.Errorf("update coupon code (%s) results in mismatched published hash", dbc.Code) + } + if err := coupons[i].SetRedemptionCode(dbc.Code); err != nil { + return fmt.Errorf("setting redemption code: %s", err.Error()) + } + } + } + } + l.listingProto.Coupons = coupons.GetProtobuf() + return nil +} + +// GetCoupons returns listing coupons with discount amount normalized as a +// CurrencyValue +func (l *Listing) GetCoupons() (ListingCoupons, error) { + var ( + protoCoupons = l.listingProto.GetCoupons() + cs = make([]*ListingCoupon, len(protoCoupons)) + listingVersion = l.GetVersion() + discPrice, err = l.GetPrice() + ) + if err != nil { + return nil, fmt.Errorf("get listing price for coupon: %s", err.Error()) + } + + for i, c := range protoCoupons { + var ( + discAmt string + discValue *CurrencyValue + ) + switch listingVersion { + case 5: + discAmt = c.GetBigPriceDiscount() + default: + //nolint:staticcheck + discAmt = strconv.FormatUint(c.GetPriceDiscount(), 10) + } + if discAmt != "" { + dv, err := NewCurrencyValue(discAmt, discPrice.Currency) + if err != nil { + return nil, fmt.Errorf("unable to create coupon discount value for amount (%s %s): %s", discAmt, discPrice.Currency, err.Error()) + } + discValue = dv + } else { + discValue = nil + } + + cs[i] = &ListingCoupon{ + listing: l, + title: c.GetTitle(), + redemptionCode: c.GetDiscountCode(), + redemptionHash: c.GetHash(), + discountPercent: c.GetPercentDiscount(), + discountAmount: discValue, + } + } + return cs, nil +} + +// ListingCoupons is a set of listing coupons +type ListingCoupons []*ListingCoupon + +// GetProtobuf converts ListingCoupons into its protobuf representation +func (cs ListingCoupons) GetProtobuf() []*pb.Listing_Coupon { + var cspb = make([]*pb.Listing_Coupon, len(cs)) + for i, c := range cs { + cspb[i] = &pb.Listing_Coupon{ + Title: c.GetTitle(), + } + if c.GetPercentOff() > 0 { + cspb[i].Discount = &pb.Listing_Coupon_PercentDiscount{ + PercentDiscount: c.GetPercentOff(), + } + } else if c.GetAmountOff() != nil { + cspb[i].Discount = &pb.Listing_Coupon_BigPriceDiscount{ + BigPriceDiscount: c.GetAmountOff().Amount.String(), + } + } + if hash, err := c.GetRedemptionHash(); err == nil { + cspb[i].Code = &pb.Listing_Coupon_Hash{Hash: hash} + } + if code, err := c.GetRedemptionCode(); err == nil { + cspb[i].Code = &pb.Listing_Coupon_DiscountCode{DiscountCode: code} + } + } + return cspb +} + +// ListingCoupon represents an coupon which can be applied to a listing for a discount +type ListingCoupon struct { + listing *Listing + + title string + redemptionCode string + redemptionHash string + + discountPercent float32 + discountAmount *CurrencyValue +} + +// GetListingSlug returns the slug for the coupon's listing +func (c *ListingCoupon) GetListingSlug() string { return c.listing.GetSlug() } + +// GetTitle returns the coupon's title +func (c *ListingCoupon) GetTitle() string { return c.title } + +// GetRedemptionCode returns the coupon redemption code +func (c *ListingCoupon) GetRedemptionCode() (string, error) { + if c.redemptionCode != "" { + return c.redemptionCode, nil + } + return "", errors.New("redemption code not set") +} + +// GetRedemptionHash returns the hashed representation of the code +func (c *ListingCoupon) GetRedemptionHash() (string, error) { + _, err := mh.FromB58String(c.redemptionHash) + if err != nil { + // if hash is invalid, let's try to produce a new one + if c.redemptionCode == "" { + return "", errors.New("hash invalid and code missing") + } + if err := c.SetRedemptionCode(c.redemptionCode); err != nil { + return "", err + } + } + return c.redemptionHash, nil +} + +// GetPercentOff returns the percentage amount to reduce listing by +func (c *ListingCoupon) GetPercentOff() float32 { return c.discountPercent } + +// GetAmountOff returns the value to reduce listing by +func (c *ListingCoupon) GetAmountOff() *CurrencyValue { return c.discountAmount } + +// SetRedemptionCode sets the coupon's redemption code +func (c *ListingCoupon) SetRedemptionCode(code string) error { + newHash, err := ipfs.EncodeMultihash([]byte(code)) + if err != nil { + return fmt.Errorf("hashing redemption code: %s", err.Error()) + } + // update proto first, otherwise ListingCoupon hash/code can't + // be used to match against the correct proto to update + if err := c.updateProtoHash(newHash.B58String()); err != nil { + return err + } + c.redemptionCode = code + c.redemptionHash = newHash.B58String() + return nil +} + +func (c *ListingCoupon) updateProtoHash(hash string) error { + for _, pc := range c.listing.listingProto.Coupons { + if pc.GetDiscountCode() == c.redemptionCode || + pc.GetHash() == c.redemptionHash { + pc.Code = &pb.Listing_Coupon_Hash{Hash: hash} + return nil + } + } + return errors.New("unable to update missing coupon proto") +} + +// GetShippingOptions returns all shipping options +func (l *Listing) GetShippingOptions() ([]*pb.Listing_ShippingOption, error) { + var so = make([]*pb.Listing_ShippingOption, len(l.listingProto.ShippingOptions)) + for i, s := range l.listingProto.ShippingOptions { + so[i] = proto.Clone(s).(*pb.Listing_ShippingOption) + } + switch l.GetVersion() { + case 3, 4: + for a, o := range so { + for x, s := range o.Services { + so[a].Services[x].BigPrice = big.NewInt(int64(s.Price)).String() + so[a].Services[x].BigAdditionalItemPrice = big.NewInt(int64(s.AdditionalItemPrice)).String() + } + } + case 5: + for a, o := range so { + for x, s := range o.Services { + if s.BigPrice == "" { + so[a].Services[x].BigPrice = "0" + } + if s.BigAdditionalItemPrice == "" { + so[a].Services[x].BigAdditionalItemPrice = "0" + } + } + } + } + return so, nil + +} + +// GetShippingRegions returns all region strings for the defined shipping +// services +func (l *Listing) GetShippingRegions() ([]string, []string) { + var ( + shipsTo = make(map[string]struct{}) + freeShippingTo = make(map[string]struct{}) + ) + for _, shipOption := range l.listingProto.ShippingOptions { + for _, shipRegion := range shipOption.Regions { + shipsTo[shipRegion.String()] = struct{}{} + for _, shipService := range shipOption.Services { + servicePrice, ok := new(big.Int).SetString(shipService.BigPrice, 10) + if ok && servicePrice.Cmp(big.NewInt(0)) == 0 { + freeShippingTo[shipRegion.String()] = struct{}{} + } + } + } + } + + var returnShipTo = make([]string, 0) + for s := range shipsTo { + returnShipTo = append(returnShipTo, s) + } + var returnFreeShipTo = make([]string, 0) + for s := range freeShippingTo { + returnFreeShipTo = append(returnFreeShipTo, s) + } + return returnShipTo, returnFreeShipTo +} + +// MarshalProtobuf returns the byte serialization of the underlying protobuf +func (l *Listing) MarshalProtobuf() ([]byte, error) { + return proto.Marshal(l.listingProto) +} + +type listingSigner interface { + TestNetworkEnabled() bool + RegressionNetworkEnabled() bool + GetNodeID() (*pb.ID, error) + Sign([]byte) ([]byte, error) +} + +// MarshalJSON returns the json serialization of the underlying protobuf +func (l *Listing) MarshalJSON() ([]byte, error) { + m := jsonpb.Marshaler{ + EnumsAsInts: false, + EmitDefaults: false, + Indent: " ", + OrigName: false, + } + lb, err := m.MarshalToString(l.listingProto) + if err != nil { + return nil, err + } + return []byte(lb), nil +} + +// Sign verifies the Listing and returns a SignedListing +func (l *Listing) Sign(n listingSigner) (*SignedListing, error) { + var ( + timeout = l.GetEscrowTimeoutHours() + isTestnet = n.TestNetworkEnabled() || n.RegressionNetworkEnabled() + ) + + // Temporary hack to work around test env shortcomings + if isTestnet { + timeout = 1 + } + l.listingProto.Metadata.EscrowTimeoutHours = timeout + + // Set inventory to the default as it's not part of the contract + for _, s := range l.listingProto.Item.Skus { + s.Quantity = 0 + s.BigQuantity = "0" + } + + // Check the listing data is correct for continuing + if err := l.ValidateListing(isTestnet); err != nil { + return nil, err + } + + // Sanitize a few critical fields + sanitizer := bluemonday.UGCPolicy() + for _, opt := range l.listingProto.Item.Options { + opt.Name = sanitizer.Sanitize(opt.Name) + for _, v := range opt.Variants { + v.Name = sanitizer.Sanitize(v.Name) + } + } + for _, so := range l.listingProto.ShippingOptions { + so.Name = sanitizer.Sanitize(so.Name) + for _, serv := range so.Services { + serv.Name = sanitizer.Sanitize(serv.Name) + } + } + + // Add the vendor ID to the listing + id, err := n.GetNodeID() + if err != nil { + return nil, fmt.Errorf("vendor id: %s", err.Error()) + } + l.listingProto.VendorID = id + + // Sign listing + serializedListing, err := l.MarshalProtobuf() + if err != nil { + return nil, fmt.Errorf("serializing listing: %s", err.Error()) + } + listingSig, err := n.Sign(serializedListing) + if err != nil { + return nil, fmt.Errorf("signing listing: %s", err.Error()) + } + + sl := new(pb.SignedListing) + sl.Listing = l.listingProto + sl.Signature = listingSig + + return &SignedListing{ + signedListingProto: sl, + }, nil +} + +// ValidateSkus ensures valid SKU state +func (l *Listing) ValidateSkus() error { + if l.listingProto.Metadata.ContractType == pb.Listing_Metadata_CRYPTOCURRENCY { + return validateCryptocurrencyQuantity(l.listingProto) + } + return nil +} + +func validateCryptocurrencyQuantity(listing *pb.Listing) error { + var checkFn func(*pb.Listing_Item_Sku) error + switch listing.Metadata.Version { + case 5: + checkFn = func(s *pb.Listing_Item_Sku) error { + if s == nil { + return fmt.Errorf("cannot validate nil sku") + } + if s.BigQuantity == "" { + return fmt.Errorf("sku quantity empty") + } + if ba, ok := new(big.Int).SetString(s.BigQuantity, 10); ok && ba.Cmp(big.NewInt(0)) < 0 { + return fmt.Errorf("sku quantity cannot be negative") + } + return nil + } + default: + checkFn = func(s *pb.Listing_Item_Sku) error { + if s == nil { + return fmt.Errorf("cannot validate nil sku") + } + if s.Quantity <= 0 { + return fmt.Errorf("sku quantity zero or less") + } + return nil + } + } + for _, sku := range listing.Item.Skus { + if err := checkFn(sku); err != nil { + return ErrCryptocurrencySkuQuantityInvalid + } + } + return nil +} + +// GetInventory - returns a map of skus and quantityies +func (l *Listing) GetInventory() (map[int]*big.Int, error) { + inventory := make(map[int]*big.Int) + for i, s := range l.listingProto.Item.Skus { + var amtStr string + switch l.GetVersion() { + case 5: + if s.BigQuantity == "" { + continue + } + amtStr = s.BigQuantity + default: + amtStr = strconv.Itoa(int(s.Quantity)) + } + amt, ok := new(big.Int).SetString(amtStr, 10) + if !ok { + return nil, errors.New("error parsing inventory") + } + inventory[i] = amt + } + return inventory, nil +} + +// ValidateListing ensures all listing state is valid +func (l *Listing) ValidateListing(testnet bool) (err error) { + defer func() { + if r := recover(); r != nil { + switch x := r.(type) { + case string: + err = errors.New(x) + case error: + err = x + default: + err = errors.New("unknown panic") + } + } + }() + + // Slug + if l.listingProto.Slug == "" { + return errors.New("slug must not be empty") + } + if len(l.listingProto.Slug) > SentenceMaxCharacters { + return fmt.Errorf("slug is longer than the max of %d", SentenceMaxCharacters) + } + if strings.Contains(l.listingProto.Slug, " ") { + return errors.New("slugs cannot contain spaces") + } + if strings.Contains(l.listingProto.Slug, "/") { + return errors.New("slugs cannot contain file separators") + } + + // Metadata + if l.listingProto.Metadata == nil { + return errors.New("missing required field: Metadata") + } + if l.listingProto.Metadata.ContractType > pb.Listing_Metadata_CRYPTOCURRENCY { + return errors.New("invalid contract type") + } + if l.listingProto.Metadata.Format > pb.Listing_Metadata_MARKET_PRICE { + return errors.New("invalid listing format") + } + if l.listingProto.Metadata.Expiry == nil { + return errors.New("missing required field: Expiry") + } + if time.Unix(l.listingProto.Metadata.Expiry.Seconds, 0).Before(time.Now()) { + return errors.New("listing expiration must be in the future") + } + if len(l.listingProto.Metadata.Language) > WordMaxCharacters { + return fmt.Errorf("language is longer than the max of %d characters", WordMaxCharacters) + } + + if !testnet && l.listingProto.Metadata.EscrowTimeoutHours != DefaultEscrowTimeout { + return fmt.Errorf("escrow timeout must be %d hours", DefaultEscrowTimeout) + } + if len(l.listingProto.Metadata.AcceptedCurrencies) == 0 { + return errors.New("at least one accepted currency must be provided") + } + if len(l.listingProto.Metadata.AcceptedCurrencies) > MaxListItems { + return fmt.Errorf("acceptedCurrencies is longer than the max of %d currencies", MaxListItems) + } + for _, c := range l.listingProto.Metadata.AcceptedCurrencies { + if len(c) > WordMaxCharacters { + return fmt.Errorf("accepted currency is longer than the max of %d characters", WordMaxCharacters) + } + } + + // Item + if l.listingProto.Item == nil { + return errors.New("no item in listing") + } + if l.listingProto.Item.Title == "" { + return errors.New("listing must have a title") + } + if l.listingProto.Metadata.ContractType != pb.Listing_Metadata_CRYPTOCURRENCY && l.listingProto.Item.BigPrice == "0" { + return errors.New("zero price listings are not allowed") + } + if len(l.listingProto.Item.Title) > TitleMaxCharacters { + return fmt.Errorf("title is longer than the max of %d characters", TitleMaxCharacters) + } + if len(l.listingProto.Item.Description) > DescriptionMaxCharacters { + return fmt.Errorf("description is longer than the max of %d characters", DescriptionMaxCharacters) + } + if len(l.listingProto.Item.ProcessingTime) > SentenceMaxCharacters { + return fmt.Errorf("processing time length must be less than the max of %d", SentenceMaxCharacters) + } + if len(l.listingProto.Item.Tags) > MaxTags { + return fmt.Errorf("number of tags exceeds the max of %d", MaxTags) + } + for _, tag := range l.listingProto.Item.Tags { + if tag == "" { + return errors.New("tags must not be empty") + } + if len(tag) > WordMaxCharacters { + return fmt.Errorf("tags must be less than max of %d", WordMaxCharacters) + } + } + if len(l.listingProto.Item.Images) == 0 { + return errors.New("listing must contain at least one image") + } + if len(l.listingProto.Item.Images) > MaxListItems { + return fmt.Errorf("number of listing images is greater than the max of %d", MaxListItems) + } + for _, img := range l.listingProto.Item.Images { + _, err := cid.Decode(img.Tiny) + if err != nil { + return errors.New("tiny image hashes must be properly formatted CID") + } + _, err = cid.Decode(img.Small) + if err != nil { + return errors.New("small image hashes must be properly formatted CID") + } + _, err = cid.Decode(img.Medium) + if err != nil { + return errors.New("medium image hashes must be properly formatted CID") + } + _, err = cid.Decode(img.Large) + if err != nil { + return errors.New("large image hashes must be properly formatted CID") + } + _, err = cid.Decode(img.Original) + if err != nil { + return errors.New("original image hashes must be properly formatted CID") + } + if img.Filename == "" { + return errors.New("image file names must not be nil") + } + if len(img.Filename) > FilenameMaxCharacters { + return fmt.Errorf("image filename length must be less than the max of %d", FilenameMaxCharacters) + } + } + if len(l.listingProto.Item.Categories) > MaxCategories { + return fmt.Errorf("number of categories must be less than max of %d", MaxCategories) + } + for _, category := range l.listingProto.Item.Categories { + if category == "" { + return errors.New("categories must not be nil") + } + if len(category) > WordMaxCharacters { + return fmt.Errorf("category length must be less than the max of %d", WordMaxCharacters) + } + } + + maxCombos := 1 + variantSizeMap := make(map[int]int) + optionMap := make(map[string]struct{}) + for i, option := range l.listingProto.Item.Options { + if _, ok := optionMap[option.Name]; ok { + return errors.New("option names must be unique") + } + if option.Name == "" { + return errors.New("options titles must not be empty") + } + if len(option.Variants) < 2 { + return errors.New("options must have more than one variants") + } + if len(option.Name) > WordMaxCharacters { + return fmt.Errorf("option title length must be less than the max of %d", WordMaxCharacters) + } + if len(option.Description) > SentenceMaxCharacters { + return fmt.Errorf("option description length must be less than the max of %d", SentenceMaxCharacters) + } + if len(option.Variants) > MaxListItems { + return fmt.Errorf("number of variants is greater than the max of %d", MaxListItems) + } + varMap := make(map[string]struct{}) + for _, variant := range option.Variants { + if _, ok := varMap[variant.Name]; ok { + return errors.New("variant names must be unique") + } + if len(variant.Name) > WordMaxCharacters { + return fmt.Errorf("variant name length must be less than the max of %d", WordMaxCharacters) + } + if variant.Image != nil && (variant.Image.Filename != "" || + variant.Image.Large != "" || variant.Image.Medium != "" || variant.Image.Small != "" || + variant.Image.Tiny != "" || variant.Image.Original != "") { + _, err := cid.Decode(variant.Image.Tiny) + if err != nil { + return errors.New("tiny image hashes must be properly formatted CID") + } + _, err = cid.Decode(variant.Image.Small) + if err != nil { + return errors.New("small image hashes must be properly formatted CID") + } + _, err = cid.Decode(variant.Image.Medium) + if err != nil { + return errors.New("medium image hashes must be properly formatted CID") + } + _, err = cid.Decode(variant.Image.Large) + if err != nil { + return errors.New("large image hashes must be properly formatted CID") + } + _, err = cid.Decode(variant.Image.Original) + if err != nil { + return errors.New("original image hashes must be properly formatted CID") + } + if variant.Image.Filename == "" { + return errors.New("image file names must not be nil") + } + if len(variant.Image.Filename) > FilenameMaxCharacters { + return fmt.Errorf("image filename length must be less than the max of %d", FilenameMaxCharacters) + } + } + varMap[variant.Name] = struct{}{} + } + variantSizeMap[i] = len(option.Variants) + maxCombos *= len(option.Variants) + optionMap[option.Name] = struct{}{} + } + + if len(l.listingProto.Item.Skus) > maxCombos { + return errors.New("more skus than variant combinations") + } + comboMap := make(map[string]bool) + for _, sku := range l.listingProto.Item.Skus { + if maxCombos > 1 && len(sku.VariantCombo) == 0 { + return errors.New("skus must specify a variant combo when options are used") + } + if len(sku.ProductID) > WordMaxCharacters { + return fmt.Errorf("product ID length must be less than the max of %d", WordMaxCharacters) + } + formatted, err := json.Marshal(sku.VariantCombo) + if err != nil { + return err + } + _, ok := comboMap[string(formatted)] + if !ok { + comboMap[string(formatted)] = true + } else { + return errors.New("duplicate sku") + } + if len(sku.VariantCombo) != len(l.listingProto.Item.Options) { + return errors.New("incorrect number of variants in sku combination") + } + for i, combo := range sku.VariantCombo { + if int(combo) > variantSizeMap[i] { + return errors.New("invalid sku variant combination") + } + } + + } + + // Taxes + if len(l.listingProto.Taxes) > MaxListItems { + return fmt.Errorf("number of taxes is greater than the max of %d", MaxListItems) + } + for _, tax := range l.listingProto.Taxes { + if tax.TaxType == "" { + return errors.New("tax type must be specified") + } + if len(tax.TaxType) > WordMaxCharacters { + return fmt.Errorf("tax type length must be less than the max of %d", WordMaxCharacters) + } + if len(tax.TaxRegions) == 0 { + return errors.New("tax must specify at least one region") + } + if len(tax.TaxRegions) > MaxCountryCodes { + return fmt.Errorf("number of tax regions is greater than the max of %d", MaxCountryCodes) + } + if tax.Percentage == 0 || tax.Percentage > 100 { + return errors.New("tax percentage must be between 0 and 100") + } + } + + // Coupons + if len(l.listingProto.Coupons) > MaxListItems { + return fmt.Errorf("number of coupons is greater than the max of %d", MaxListItems) + } + for _, coupon := range l.listingProto.Coupons { + if len(coupon.Title) > CouponTitleMaxCharacters { + return fmt.Errorf("coupon title length must be less than the max of %d", SentenceMaxCharacters) + } + if len(coupon.GetDiscountCode()) > CodeMaxCharacters { + return fmt.Errorf("coupon code length must be less than the max of %d", CodeMaxCharacters) + } + if coupon.GetPercentDiscount() > 100 { + return errors.New("percent discount cannot be over 100 percent") + } + price, err := l.GetPrice() + if err != nil { + return err + } + if coupon.GetBigPriceDiscount() != "" { + discount0, ok := new(big.Int).SetString(coupon.GetBigPriceDiscount(), 10) + if !ok { + return errors.New("coupon discount was invalid") + } + if price.Amount.Cmp(discount0) < 0 { + return errors.New("price discount cannot be greater than the item price") + } + } + if coupon.GetPercentDiscount() == 0 && coupon.GetBigPriceDiscount() == "" { + return errors.New("coupons must have at least one positive discount value") + } + if coupon.GetPercentDiscount() != 0 && coupon.GetBigPriceDiscount() != "" { + return errors.New("coupons must have either a percent discount or a fixed amount discount, but not both") + } + } + + // Moderators + if len(l.listingProto.Moderators) > MaxListItems { + return fmt.Errorf("number of moderators is greater than the max of %d", MaxListItems) + } + for _, moderator := range l.listingProto.Moderators { + _, err := mh.FromB58String(moderator) + if err != nil { + return errors.New("moderator IDs must be multihashes") + } + } + + // TermsAndConditions + if len(l.listingProto.TermsAndConditions) > PolicyMaxCharacters { + return fmt.Errorf("terms and conditions length must be less than the max of %d", PolicyMaxCharacters) + } + + // RefundPolicy + if len(l.listingProto.RefundPolicy) > PolicyMaxCharacters { + return fmt.Errorf("refund policy length must be less than the max of %d", PolicyMaxCharacters) + } + + // Type-specific validations + if l.listingProto.Metadata.ContractType == pb.Listing_Metadata_PHYSICAL_GOOD { + err := l.validatePhysicalListing() + if err != nil { + return err + } + } else if l.listingProto.Metadata.ContractType == pb.Listing_Metadata_CRYPTOCURRENCY { + err := l.ValidateCryptoListing() + if err != nil { + return err + } + } + + // Non-crypto validations + if l.listingProto.Metadata.ContractType != pb.Listing_Metadata_CRYPTOCURRENCY { + price, err := l.GetPrice() + if err != nil { + return err + } + if price.Currency.Code == "" { + return errors.New("pricing currency is missing") + } + if priceCurrency, err := AllCurrencies().Lookup(price.Currency.Code.String()); err != nil { + return errors.New("invalid pricing currency") + } else { + if price.Currency.Divisibility > priceCurrency.Divisibility { + return errors.New("pricing currency divisibility is too large") + } + } + } + + // Format-specific validations + if l.listingProto.Metadata.Format == pb.Listing_Metadata_MARKET_PRICE { + err := validateMarketPriceListing(l.listingProto) + if err != nil { + return err + } + } + + return nil +} + +func (l *Listing) validatePhysicalListing() error { + if len(l.listingProto.Item.Condition) > SentenceMaxCharacters { + return fmt.Errorf("'Condition' length must be less than the max of %d", SentenceMaxCharacters) + } + if len(l.listingProto.Item.Options) > MaxListItems { + return fmt.Errorf("number of options is greater than the max of %d", MaxListItems) + } + + // ShippingOptions + if len(l.listingProto.ShippingOptions) == 0 { + return errors.New("must be at least one shipping option for a physical good") + } + if len(l.listingProto.ShippingOptions) > MaxListItems { + return fmt.Errorf("number of shipping options is greater than the max of %d", MaxListItems) + } + var shippingTitles []string + shippingOptions, err := l.GetShippingOptions() + if err != nil { + return err + } + for _, shippingOption := range shippingOptions { + if shippingOption.Name == "" { + return errors.New("shipping option title name must not be empty") + } + if len(shippingOption.Name) > WordMaxCharacters { + return fmt.Errorf("shipping option service length must be less than the max of %d", WordMaxCharacters) + } + for _, t := range shippingTitles { + if t == shippingOption.Name { + return errors.New("shipping option titles must be unique") + } + } + shippingTitles = append(shippingTitles, shippingOption.Name) + if shippingOption.Type > pb.Listing_ShippingOption_FIXED_PRICE { + return errors.New("unknown shipping option type") + } + if len(shippingOption.Regions) == 0 { + return errors.New("shipping options must specify at least one region") + } + if err := ValidateShippingRegion(shippingOption); err != nil { + return fmt.Errorf("invalid shipping option (%s): %s", shippingOption.String(), err.Error()) + } + if len(shippingOption.Regions) > MaxCountryCodes { + return fmt.Errorf("number of shipping regions is greater than the max of %d", MaxCountryCodes) + } + if len(shippingOption.Services) == 0 && shippingOption.Type != pb.Listing_ShippingOption_LOCAL_PICKUP { + return errors.New("at least one service must be specified for a shipping option when not local pickup") + } + if len(shippingOption.Services) > MaxListItems { + return fmt.Errorf("number of shipping services is greater than the max of %d", MaxListItems) + } + var serviceTitles []string + for _, option := range shippingOption.Services { + if option.Name == "" { + return errors.New("shipping option service name must not be empty") + } + if len(option.Name) > WordMaxCharacters { + return fmt.Errorf("shipping option service length must be less than the max of %d", WordMaxCharacters) + } + for _, t := range serviceTitles { + if t == option.Name { + return errors.New("shipping option services names must be unique") + } + } + serviceTitles = append(serviceTitles, option.Name) + + if option.EstimatedDelivery == "" { + return errors.New("shipping option estimated delivery must not be empty") + } + if len(option.EstimatedDelivery) > SentenceMaxCharacters { + return fmt.Errorf("shipping option estimated delivery length must be less than the max of %d", SentenceMaxCharacters) + } + if _, ok := new(big.Int).SetString(option.BigPrice, 10); !ok { + return errors.New("invalid shipping service price amount") + } + } + } + + return nil +} + +func (l *Listing) ValidateCryptoListing() error { + if len(l.listingProto.Metadata.AcceptedCurrencies) != 1 { + return errors.New("cryptocurrency listing must only have one accepted currency") + } + + if len(l.listingProto.Coupons) > 0 { + return ErrCryptocurrencyListingIllegalField("coupons") + } + if len(l.listingProto.Item.Options) > 0 { + return ErrCryptocurrencyListingIllegalField("item.options") + } + if len(l.listingProto.ShippingOptions) > 0 { + return ErrCryptocurrencyListingIllegalField("shippingOptions") + } + if len(l.listingProto.Item.Condition) > 0 { + return ErrCryptocurrencyListingIllegalField("item.condition") + } + if l.listingProto.Item.PriceCurrency != nil && + len(l.listingProto.Item.PriceCurrency.Code) > 0 { + return ErrCryptocurrencyListingIllegalField("item.pricingCurrency") + } + if len(l.listingProto.Metadata.CryptoCurrencyCode) == 0 { + return ErrListingCryptoCurrencyCodeInvalid + } + + cryptoDivisibility := l.GetCryptoDivisibility() + if cryptoDivisibility == 0 { + return ErrListingCryptoDivisibilityInvalid + } + def := NewUnknownCryptoDefinition(l.listingProto.Metadata.CryptoCurrencyCode, uint(cryptoDivisibility)) + if err := def.Valid(); err != nil { + return fmt.Errorf("cryptocurrency metadata invalid: %s", err) + } + return nil +} + +// SetCryptocurrencyListingDefaults ensures appropriate defaults are set for Crypto listings +func (l *Listing) SetCryptocurrencyListingDefaults() error { + l.listingProto.Coupons = []*pb.Listing_Coupon{} + l.listingProto.Item.Options = []*pb.Listing_Item_Option{} + l.listingProto.ShippingOptions = []*pb.Listing_ShippingOption{} + l.listingProto.Metadata.Format = pb.Listing_Metadata_MARKET_PRICE + return nil +} + +func validateMarketPriceListing(listing *pb.Listing) error { + var ( + priceModifier float32 + roundHundredths = func(f float32) float32 { return float32(int(f*100.0)) / 100.0 } + n, ok = new(big.Int).SetString(listing.Item.BigPrice, 10) + ) + + if ok && n.Cmp(big.NewInt(0)) != 0 { + return ErrMarketPriceListingIllegalField("item.bigPrice") + } + + if listing.Metadata.PriceModifier != 0 { + priceModifier = roundHundredths(listing.Metadata.PriceModifier) + listing.Metadata.PriceModifier = priceModifier + } else if listing.Item.PriceModifier != 0 { + priceModifier = roundHundredths(listing.Item.PriceModifier) + listing.Item.PriceModifier = priceModifier + } + + if priceModifier < PriceModifierMin || + priceModifier > PriceModifierMax { + return ErrPriceModifierOutOfRange{ + Min: PriceModifierMin, + Max: PriceModifierMax, + } + } + + return nil +} + +// ValidateShippingRegion ensures shipping options are valid +func ValidateShippingRegion(shippingOption *pb.Listing_ShippingOption) error { + for _, region := range shippingOption.Regions { + if int32(region) == 0 { + return ErrShippingRegionMustBeSet + } + _, ok := proto.EnumValueMap("CountryCode")[region.String()] + if !ok { + return ErrShippingRegionUndefined + } + if ok { + if int32(region) > 500 { + return ErrShippingRegionMustNotBeContinent + } + } + } + return nil +} + +// ValidatePurchaseItemOptions ensures item options are valid +func (l *Listing) ValidatePurchaseItemOptions(itemOptions []option) error { + if l.GetContractType() == pb.Listing_Metadata_CRYPTOCURRENCY.String() && + len(itemOptions) > 0 { + return fmt.Errorf("options on a %s listing were provided, but are not supported", pb.Listing_Metadata_CRYPTOCURRENCY.String()) + } + + var ( + optSet = make(map[string]struct{}) + checkedOpt = make(map[string]struct{}) + ) + // create an option set + for _, lo := range l.listingProto.Item.Options { + optSet[lo.Name] = struct{}{} + } + // walk through purchase options and verify + for _, po := range itemOptions { + // that they are available on the listing + if _, ok := optSet[po.Name]; !ok { + return fmt.Errorf("unknown item option (%s)", po.Name) + } + // that they haven't already been applied + if _, ok := checkedOpt[po.Name]; ok { + return fmt.Errorf("item option (%s) applied more than once", po.Name) + } + checkedOpt[po.Name] = struct{}{} + } + return nil +} + +// ValidateListingOptions is a helper to ensure item options are valid +func ValidateListingOptions(listingItemOptions []*pb.Listing_Item_Option, itemOptions []option) ([]*pb.Order_Item_Option, error) { + var validatedListingOptions []*pb.Order_Item_Option + listingOptions := make(map[string]*pb.Listing_Item_Option) + for _, opt := range listingItemOptions { + listingOptions[strings.ToLower(opt.Name)] = opt + } + for _, uopt := range itemOptions { + _, ok := listingOptions[strings.ToLower(uopt.Name)] + if !ok { + return nil, errors.New("selected variant not in listing") + } + delete(listingOptions, strings.ToLower(uopt.Name)) + } + if len(listingOptions) > 0 { + return nil, errors.New("Not all options were selected") + } + + for _, option := range itemOptions { + o := &pb.Order_Item_Option{ + Name: option.Name, + Value: option.Value, + } + validatedListingOptions = append(validatedListingOptions, o) + } + return validatedListingOptions, nil +} diff --git a/repo/listing_index.go b/repo/listing_index.go new file mode 100644 index 0000000000..aed26b0641 --- /dev/null +++ b/repo/listing_index.go @@ -0,0 +1,147 @@ +package repo + +import ( + "encoding/json" + "fmt" +) + +type ( + ListingThumbnail struct { + Tiny string `json:"tiny"` + Small string `json:"small"` + Medium string `json:"medium"` + } + + // ListingIndexData reprents a single node in the Listing index + ListingIndexData struct { + Hash string `json:"hash"` + Slug string `json:"slug"` + Title string `json:"title"` + Tags []string `json:"tags"` + Categories []string `json:"categories"` + NSFW bool `json:"nsfw"` + ContractType string `json:"contractType"` + Format string `json:"format"` + Description string `json:"description"` + Thumbnail ListingThumbnail `json:"thumbnail"` + Price *CurrencyValue `json:"price"` + Modifier float32 `json:"modifier"` + ShipsTo []string `json:"shipsTo"` + FreeShipping []string `json:"freeShipping"` + Language string `json:"language"` + AverageRating float32 `json:"averageRating"` + RatingCount uint32 `json:"ratingCount"` + ModeratorIDs []string `json:"moderators"` + AcceptedCurrencies []string `json:"acceptedCurrencies"` + CryptoCurrencyCode string `json:"coinType"` + } +) + +// UnmarshalJSONSignedListingIndex consumes a []byte payload of JSON representing +// a list of SignedListings and returns a parsed instance or an error if the payload +// cannot be successfully parsed +func UnmarshalJSONSignedListingIndex(data []byte) ([]ListingIndexData, error) { + var ( + rawIndex []json.RawMessage + listingIndex []ListingIndexData + ) + if err := json.Unmarshal(data, &rawIndex); err != nil { + return nil, err + } + + // best effort parse + // TODO: intelligently parse payload based on + // detection of the correct version. + for _, listingJSON := range rawIndex { + l, err := parseUnknownSchemaData(listingJSON) + if err != nil { + return nil, err + } + listingIndex = append(listingIndex, l) + } + return listingIndex, nil +} + +func parseUnknownSchemaData(data []byte) (ListingIndexData, error) { + sl, err := parseV5Data(data) + if err == nil { + return sl, nil + } else { + log.Debugf("failed attempt to parse as v5 listing index: %s", err) + } + sl, err = parseV4Data(data) + if err == nil { + return sl, nil + } else { + log.Debugf("failed attempt to parse as v4 listing index: %s", err) + } + return ListingIndexData{}, fmt.Errorf("failed parsing listing in index: %s", err) +} + +func parseV5Data(data []byte) (ListingIndexData, error) { + var v5 ListingIndexData + if err := json.Unmarshal(data, &v5); err != nil { + return ListingIndexData{}, err + } + return v5, nil +} + +func parseV4Data(data []byte) (ListingIndexData, error) { + var v4 struct { + Hash string `json:"hash"` + Slug string `json:"slug"` + Title string `json:"title"` + Categories []string `json:"categories"` + NSFW bool `json:"nsfw"` + ContractType string `json:"contractType"` + Description string `json:"description"` + Thumbnail ListingThumbnail `json:"thumbnail"` + Price struct { + CurrencyCode string `json:"currencyCode"` + Amount uint `json:"amount"` + Modifier float32 `json:"modifier"` + } `json:"price"` + ShipsTo []string `json:"shipsTo"` + FreeShipping []string `json:"freeShipping"` + Language string `json:"language"` + AverageRating float32 `json:"averageRating"` + RatingCount uint32 `json:"ratingCount"` + ModeratorIDs []string `json:"moderators"` + AcceptedCurrencies []string `json:"acceptedCurrencies"` + CryptoCurrencyCode string `json:"coinType"` + } + if err := json.Unmarshal(data, &v4); err != nil { + return ListingIndexData{}, err + } + var priceValue *CurrencyValue + if v4.Price.CurrencyCode != "" { + priceDef, err := AllCurrencies().Lookup(v4.Price.CurrencyCode) + if err != nil { + return ListingIndexData{}, err + } + priceValue, err = NewCurrencyValueFromUint(uint64(v4.Price.Amount), priceDef) + if err != nil { + return ListingIndexData{}, err + } + } + return ListingIndexData{ + Hash: v4.Hash, + Slug: v4.Slug, + Title: v4.Title, + Categories: v4.Categories, + NSFW: v4.NSFW, + ContractType: v4.ContractType, + Description: v4.Description, + Thumbnail: v4.Thumbnail, + Modifier: v4.Price.Modifier, + Price: priceValue, + ShipsTo: v4.ShipsTo, + FreeShipping: v4.FreeShipping, + Language: v4.Language, + AverageRating: v4.AverageRating, + RatingCount: v4.RatingCount, + ModeratorIDs: v4.ModeratorIDs, + AcceptedCurrencies: v4.AcceptedCurrencies, + CryptoCurrencyCode: v4.CryptoCurrencyCode, + }, nil +} diff --git a/repo/listing_index_test.go b/repo/listing_index_test.go new file mode 100644 index 0000000000..d63aa2d194 --- /dev/null +++ b/repo/listing_index_test.go @@ -0,0 +1,106 @@ +package repo_test + +import ( + "math/big" + "reflect" + "testing" + + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" +) + +func TestListingIndexUnmarshalJSON(t *testing.T) { + var examples = map[string][]repo.ListingIndexData{ + "v4-index": { + { + Hash: "QmbAhieQdN7WzDktpkZ3ZDuv3AKF3DxG3SMFyEcVg3HGcP", + Slug: "test-service", + Title: "Test Service", + Categories: []string{"test"}, + NSFW: true, + ContractType: "SERVICE", + Description: "Test service listing", + Thumbnail: repo.ListingThumbnail{ + Tiny: "zb2rhfN4RQyNP6eZszvEBfwBRMZxaysoqF72MYWPKoofV5AQr", + Small: "zb2rhfMZFaaWZxZGvkqAPCMUbmdxNHhAaCby5XCkRrV13bew8", + Medium: "zb2rhnppMGkZYp6Zg7Qf2irDH9z1ZM5jc2VcAXfy6mEnifoEy", + }, + Price: &repo.CurrencyValue{ + Amount: big.NewInt(25), + Currency: repo.CurrencyDefinition{ + Name: "United States Dollar", + Code: "USD", + Divisibility: 2, + CurrencyType: "fiat", + }, + }, + Modifier: 0, + ShipsTo: []string{}, + FreeShipping: []string{}, + Language: "English", + AverageRating: 0, + RatingCount: 0, + ModeratorIDs: []string{ + "QmQifVhzhnHRu9bGT9WNcbbuc5EF2bXRF6iJpSzNj7yRtQ", + }, + AcceptedCurrencies: []string{ + "BTC", + "BCH", + "ZEC", + "LTC", + }, + }, + }, + "v5-index": { + { + Hash: "QmcCcbMysMUY4jFUoyYzgrLhJX6N6y5NhRpauCAr8etYn5", + Slug: "ron-swanson-tshirt", + Title: "Ron Swanson Tshirt", + Categories: []string{"tshirts"}, + NSFW: true, + ContractType: "PHYSICAL_GOOD", + Description: "Example item", + Thumbnail: repo.ListingThumbnail{ + Tiny: "QmUy4jh5mGNZvLkjies1RWM4YuvJh5o2FYopNPVYwrRVGV", + Small: "QmUy4jh5mGNZvLkjies1RWM4YuvJh5o2FYopNPVYwrRVGV", + Medium: "QmUy4jh5mGNZvLkjies1RWM4YuvJh5o2FYopNPVYwrRVGV", + }, + Price: &repo.CurrencyValue{ + Amount: big.NewInt(500000), + Currency: repo.CurrencyDefinition{ + Name: "Litecoin", + Code: "TLTC", + Divisibility: 8, + CurrencyType: "crypto", + }, + }, + Modifier: 0, + ShipsTo: []string{"ALL"}, + FreeShipping: []string{}, + Language: "Klingon", + AverageRating: 0, + RatingCount: 0, + ModeratorIDs: nil, + AcceptedCurrencies: []string{ + "TBTC", + "TLTC", + }, + }, + }, + } + + for fixtureName, expected := range examples { + var ( + fixtureBytes = factory.MustLoadListingFixture(fixtureName) + l, err = repo.UnmarshalJSONSignedListingIndex(fixtureBytes) + ) + if err != nil { + t.Errorf("error parsing fixture (%s): %s", fixtureName, err) + } + if !reflect.DeepEqual(expected, l) { + t.Errorf("failed to parse (%s)", fixtureName) + t.Logf("\texpected: %+v", expected) + t.Logf("\t actual: %+v", l) + } + } +} diff --git a/repo/listing_test.go b/repo/listing_test.go new file mode 100644 index 0000000000..808f6e07d3 --- /dev/null +++ b/repo/listing_test.go @@ -0,0 +1,314 @@ +package repo_test + +import ( + "bytes" + "fmt" + "math/big" + "testing" + + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" +) + +func TestListingUnmarshalJSON(t *testing.T) { + var examples = []string{ + "v3-physical-good", + "v4-physical-good", + "v4-digital-good", + "v4-service", + "v4-cryptocurrency", + "v5-physical-good", + } + + for _, e := range examples { + var ( + fixtureBytes = factory.MustLoadListingFixture(e) + _, err = repo.UnmarshalJSONListing(fixtureBytes) + ) + if err != nil { + t.Errorf("exmaple (%s): %s", e, err) + } + } +} + +// nolint:dupl +func TestListingAttributes(t *testing.T) { + var examples = []struct { + fixtureName string + expectedVersion uint32 + expectedTitle string + expectedSlug string + expectedPrice *repo.CurrencyValue + expectedAcceptedCurrencies []string + expectedCryptoDivisibility uint32 + expectedCryptoCurrencyCode string + }{ + { + fixtureName: "v3-physical-good", + expectedVersion: 3, + expectedTitle: "Physical Listing", + expectedSlug: "physical-listing", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(1235000000), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("BCH"), + Divisibility: 8, + CurrencyType: "crypto", + }, + }, + expectedAcceptedCurrencies: []string{"BCH"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + { + fixtureName: "v4-physical-good", + expectedVersion: 4, + expectedTitle: "Physical Good Listing", + expectedSlug: "physical-good-listing", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(12345678000), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("BCH"), + Divisibility: 8, + CurrencyType: "crypto", + }, + }, + expectedAcceptedCurrencies: []string{"ZEC", "LTC", "BTC", "BCH"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + { + fixtureName: "v4-digital-good", + expectedVersion: 4, + expectedTitle: "Digital Good Listing", + expectedSlug: "digital-good-listing", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(1320), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("USD"), + Divisibility: 2, + CurrencyType: "fiat", + }, + }, + expectedAcceptedCurrencies: []string{"ZEC"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + { + fixtureName: "v4-service", + expectedVersion: 4, + expectedTitle: "Service Listing", + expectedSlug: "service-listing", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(9877000000), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("BTC"), + Divisibility: 8, + CurrencyType: "crypto", + }, + }, + expectedAcceptedCurrencies: []string{"ZEC", "LTC", "BCH", "BTC"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + { + fixtureName: "v4-cryptocurrency", + expectedVersion: 4, + expectedTitle: "LTC-XMR", + expectedSlug: "ltc-xmr", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(0), + Currency: repo.NewUnknownCryptoDefinition("XMR", 0), + }, + expectedAcceptedCurrencies: []string{"LTC"}, + expectedCryptoDivisibility: 8, + expectedCryptoCurrencyCode: "XMR", + }, + { + fixtureName: "v5-physical-good", + expectedVersion: 5, + expectedTitle: "ETH - $1", + expectedSlug: "eth-1", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(100), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("USD"), + Divisibility: 2, + CurrencyType: "fiat", + }, + }, + expectedAcceptedCurrencies: []string{"BTC", "BCH", "ZEC", "LTC", "ETH"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + } + + for _, e := range examples { + t.Logf("example listing (%s)", e.fixtureName) + var ( + fixtureBytes = factory.MustLoadListingFixture(e.fixtureName) + l, err = repo.UnmarshalJSONListing(fixtureBytes) + ) + if err != nil { + t.Errorf("unable to unmarshal example (%s)", e.fixtureName) + continue + } + if l.GetVersion() != e.expectedVersion { + t.Errorf("expected to have version response (%+v), but instead was (%+v)", e.expectedVersion, l.GetVersion()) + } + if title := l.GetTitle(); title != e.expectedTitle { + t.Errorf("expected to have title response (%+v), but instead was (%+v)", e.expectedTitle, title) + } + if slug := l.GetSlug(); slug != e.expectedSlug { + t.Errorf("expected to have slug response (%+v), but instead was (%+v)", e.expectedSlug, slug) + } + if price, err := l.GetPrice(); err == nil { + if !price.Equal(e.expectedPrice) { + t.Errorf("expected to have price response (%+v), but instead was (%+v)", e.expectedPrice, price) + } + } else { + t.Errorf("get price: %s", err.Error()) + } + if acceptedCurrencies := l.GetAcceptedCurrencies(); len(acceptedCurrencies) != len(e.expectedAcceptedCurrencies) { + t.Errorf("expected to have acceptedCurrencies response (%+v), but instead was (%+v)", e.expectedAcceptedCurrencies, acceptedCurrencies) + } + if actual := l.GetCryptoDivisibility(); actual != e.expectedCryptoDivisibility { + t.Errorf("expected to have divisibility (%d), but was (%d)", e.expectedCryptoDivisibility, actual) + } + if actual := l.GetCryptoCurrencyCode(); actual != e.expectedCryptoCurrencyCode { + t.Errorf("expected to have currency code (%s), but was (%s)", e.expectedCryptoCurrencyCode, actual) + } + } +} + +func TestListingFromProtobuf(t *testing.T) { + var ( + subject = factory.NewListing("slug") + actual, err = repo.NewListingFromProtobuf(subject) + ) + if err != nil { + t.Fatal(err) + } + + if subject.GetSlug() != actual.GetSlug() { + t.Errorf("expected slug to be (%s), but was (%s)", subject.GetSlug(), actual.GetSlug()) + } + if subject.GetTermsAndConditions() != actual.GetTermsAndConditions() { + t.Errorf("expected terms/conditions to be (%s), but was (%s)", subject.GetTermsAndConditions(), actual.GetTermsAndConditions()) + } + if subject.GetRefundPolicy() != actual.GetRefundPolicy() { + t.Errorf("expected refund policy to be (%s), but was (%s)", subject.GetRefundPolicy(), actual.GetRefundPolicy()) + } + if subject.Metadata.GetVersion() != actual.GetVersion() { + t.Errorf("expected vesion to be (%d), but was (%d)", subject.Metadata.GetVersion(), actual.GetVersion()) + } + if hash, err := actual.GetVendorID().Hash(); err != nil && subject.VendorID.PeerID != hash { + t.Errorf("expected hash to be (%s), but was (%s)", subject.VendorID.PeerID, hash) + t.Logf("hash had an error: %s", err) + + } + if !bytes.Equal(subject.VendorID.BitcoinSig, actual.GetVendorID().BitcoinSignature()) { + t.Errorf("expected refund policy to be (%s), but was (%s)", subject.VendorID.BitcoinSig, actual.GetVendorID().BitcoinSignature()) + } +} + +func TestV4PhysicalGoodDataNormalizesToLatestSchema(t *testing.T) { + var ( + expectedPrice uint64 = 100000 + expectedPriceCurrency = "EUR" + expectedSkuSurcharge int64 = 200 + expectedSkuQuantity int64 = 12 + expectedShippingPrice uint64 = 30 + expectedCouponDiscount uint64 = 50 + v4Proto = &pb.Listing{ + Metadata: &pb.Listing_Metadata{ + Version: 4, + ContractType: pb.Listing_Metadata_PHYSICAL_GOOD, + PricingCurrency: expectedPriceCurrency, + }, + Item: &pb.Listing_Item{ + Price: expectedPrice, + Skus: []*pb.Listing_Item_Sku{ + { + Surcharge: expectedSkuSurcharge, + Quantity: expectedSkuQuantity, + }, + }, + }, + ShippingOptions: []*pb.Listing_ShippingOption{ + { + Services: []*pb.Listing_ShippingOption_Service{ + { + Price: expectedShippingPrice, + AdditionalItemPrice: expectedShippingPrice + 1, + }, + }, + }, + }, + Coupons: []*pb.Listing_Coupon{ + { + Discount: &pb.Listing_Coupon_PriceDiscount{PriceDiscount: expectedCouponDiscount}, + }, + }, + } + ) + + l, err := repo.NewListingFromProtobuf(v4Proto) + if err != nil { + t.Fatal(err) + } + + nl, err := l.Normalize() + if err != nil { + t.Fatal(err) + } + + nlp := nl.GetProtobuf() + if v := nlp.Metadata.GetVersion(); v != repo.ListingVersion { + t.Errorf("expected version to be (%d), but was (%d)", repo.ListingVersion, v) + } + + if p := nlp.Item.BigPrice; p != fmt.Sprintf("%d", expectedPrice) { + t.Errorf("expected price to be (%d), but was (%s)", expectedPrice, p) + } + + if pc := nlp.Item.PriceCurrency; pc == nil { + t.Error("expected to have pricing currency set, but was nil") + } else { + if pcc := pc.Code; pcc != expectedPriceCurrency { + t.Errorf("expected price currency to be (%s), but was (%s)", expectedPriceCurrency, pcc) + } + } + + if s := nlp.Item.Skus[0]; s == nil { + t.Error("expected sku to be present, but was nil") + } else { + if ss := s.BigSurcharge; ss != fmt.Sprintf("%d", expectedSkuSurcharge) { + t.Errorf("expected surcharge to be (%d), but was (%s)", expectedSkuSurcharge, ss) + } + if sq := s.BigQuantity; sq != fmt.Sprintf("%d", expectedSkuQuantity) { + t.Errorf("expected quantity to be (%d), but was (%s)", expectedSkuQuantity, sq) + } + } + + if s := nlp.ShippingOptions[0]; s == nil { + t.Error("expected shipping options to be present, but was nil") + } else { + if ss := s.Services[0]; ss == nil { + t.Error("expected shipping option services to be present, but was nil") + } else { + if ssp := ss.BigPrice; ssp != fmt.Sprintf("%d", expectedShippingPrice) { + t.Errorf("expected shipping option price to be (%d), but was (%s)", expectedShippingPrice, ssp) + } + } + } + + if c := nlp.Coupons[0]; c == nil { + t.Error("expected coupon to be present, but was nil") + } else { + if cd := c.GetBigPriceDiscount(); cd != fmt.Sprintf("%d", expectedCouponDiscount) { + t.Errorf("expected coupon discount to be (%d), but was (%s)", expectedCouponDiscount, cd) + } + } +} diff --git a/repo/message.go b/repo/message.go new file mode 100644 index 0000000000..578e10e8fb --- /dev/null +++ b/repo/message.go @@ -0,0 +1,38 @@ +package repo + +import ( + "encoding/json" + "errors" + + "github.com/golang/protobuf/ptypes/any" + + "github.com/phoreproject/pm-go/pb" +) + +// ErrUnknownMessage - notify an invalid message +var ErrUnknownMessage = errors.New("unknown or invalid message") + +// Message - wrapper for pb.Message +type Message struct { + Msg pb.Message +} + +// MarshalJSON - invoke the pb.Message marshaller +func (m *Message) MarshalJSON() ([]byte, error) { + return json.Marshal(m.Msg) +} + +// UnmarshalJSON - invoke the pb.Message unmarshaller +func (m *Message) UnmarshalJSON(b []byte) error { + return json.Unmarshal(b, &m.Msg) +} + +// GetMessageType - return the pb.Message messageType +func (m *Message) GetMessageType() pb.Message_MessageType { + return m.Msg.MessageType +} + +// GetPayload - return the pb.Message payload +func (m *Message) GetPayload() *any.Any { + return m.Msg.Payload +} diff --git a/repo/message_test.go b/repo/message_test.go new file mode 100644 index 0000000000..72652c38cd --- /dev/null +++ b/repo/message_test.go @@ -0,0 +1,46 @@ +package repo_test + +import ( + "bytes" + "testing" + + "github.com/golang/protobuf/ptypes/any" + + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" +) + +func TestMessage(t *testing.T) { + var ( + mType = pb.Message_ORDER + payload = "sample message" + ) + + msg := pb.Message{ + MessageType: mType, + Payload: &any.Any{Value: []byte(payload)}, + } + + repoMsg := repo.Message{Msg: msg} + + repoMsgBytes, err := repoMsg.MarshalJSON() + if err != nil { + t.Error(err) + } + + var retRepoMsg repo.Message + + err = retRepoMsg.UnmarshalJSON(repoMsgBytes) + if err != nil { + t.Error(err) + } + + if retRepoMsg.GetMessageType() != pb.Message_ORDER { + t.Error("wrong msg type") + } + + if !bytes.Equal(retRepoMsg.GetPayload().GetValue(), []byte(payload)) { + t.Error("wrong msg type") + } + +} diff --git a/repo/migration.go b/repo/migration.go index d11fb8cae0..e60bb863de 100644 --- a/repo/migration.go +++ b/repo/migration.go @@ -8,7 +8,7 @@ import ( "strconv" "strings" - "github.com/phoreproject/openbazaar-go/repo/migrations" + "github.com/phoreproject/pm-go/repo/migrations" ) type Migration interface { @@ -43,6 +43,17 @@ var ( migrations.Migration020{}, migrations.Migration021{}, migrations.Migration022{}, + migrations.Migration023{}, + migrations.Migration024{}, + migrations.Migration025{}, + migrations.Migration026{}, + migrations.Migration027{}, + migrations.Migration028{}, + migrations.Migration029{}, + migrations.Migration030{}, + migrations.Migration031{}, + migrations.Migration032{}, + migrations.Migration033{}, } ) diff --git a/repo/migrations/Migration000.go b/repo/migrations/Migration000.go index ced5273b73..6f0f9e8ef0 100644 --- a/repo/migrations/Migration000.go +++ b/repo/migrations/Migration000.go @@ -16,7 +16,10 @@ func (Migration000) Up(repoPath string, dbPassword string, testnet bool) error { return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") @@ -73,7 +76,10 @@ func (Migration000) Down(repoPath string, dbPassword string, testnet bool) error return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") diff --git a/repo/migrations/Migration000_test.go b/repo/migrations/Migration000_test.go index ec29e2ce1a..cb4f05a753 100644 --- a/repo/migrations/Migration000_test.go +++ b/repo/migrations/Migration000_test.go @@ -27,7 +27,10 @@ func TestMigration000(t *testing.T) { if err != nil { t.Error(err) } - f.Write([]byte(testConfig)) + _, err = f.Write([]byte(testConfig)) + if err != nil { + t.Error(err) + } f.Close() var m Migration000 diff --git a/repo/migrations/Migration001.go b/repo/migrations/Migration001.go index a2ea3dae26..2704b3683d 100644 --- a/repo/migrations/Migration001.go +++ b/repo/migrations/Migration001.go @@ -16,7 +16,10 @@ func (Migration001) Up(repoPath string, dbPassword string, testnet bool) error { return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") @@ -119,7 +122,10 @@ func (Migration001) Down(repoPath string, dbPassword string, testnet bool) error return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") diff --git a/repo/migrations/Migration001_test.go b/repo/migrations/Migration001_test.go index 512bbdad29..893a746b54 100644 --- a/repo/migrations/Migration001_test.go +++ b/repo/migrations/Migration001_test.go @@ -32,7 +32,10 @@ func TestMigration001(t *testing.T) { if err != nil { t.Error(err) } - f.Write([]byte(testConfig1)) + _, err = f.Write([]byte(testConfig1)) + if err != nil { + t.Error(err) + } f.Close() var m Migration001 diff --git a/repo/migrations/Migration002.go b/repo/migrations/Migration002.go index 75daa4d8c9..8d8c2e2b4c 100644 --- a/repo/migrations/Migration002.go +++ b/repo/migrations/Migration002.go @@ -16,7 +16,10 @@ func (Migration002) Up(repoPath string, dbPassword string, testnet bool) error { return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") @@ -66,7 +69,10 @@ func (Migration002) Down(repoPath string, dbPassword string, testnet bool) error return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") diff --git a/repo/migrations/Migration002_test.go b/repo/migrations/Migration002_test.go index 5db612b8b3..b14182784b 100644 --- a/repo/migrations/Migration002_test.go +++ b/repo/migrations/Migration002_test.go @@ -19,7 +19,10 @@ func TestMigration002(t *testing.T) { if err != nil { t.Error(err) } - f.Write([]byte(testConfig2)) + _, err = f.Write([]byte(testConfig2)) + if err != nil { + t.Error(err) + } f.Close() var m Migration002 diff --git a/repo/migrations/Migration003.go b/repo/migrations/Migration003.go index 54cbf1a5ad..c886f29b7b 100644 --- a/repo/migrations/Migration003.go +++ b/repo/migrations/Migration003.go @@ -16,7 +16,10 @@ func (Migration003) Up(repoPath string, dbPassword string, testnet bool) error { return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") @@ -56,7 +59,10 @@ func (Migration003) Down(repoPath string, dbPassword string, testnet bool) error return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") diff --git a/repo/migrations/Migration003_test.go b/repo/migrations/Migration003_test.go index b9cb12b77c..0b1cc665df 100644 --- a/repo/migrations/Migration003_test.go +++ b/repo/migrations/Migration003_test.go @@ -16,7 +16,10 @@ func TestMigration003(t *testing.T) { if err != nil { t.Error(err) } - f.Write([]byte(testConfig3)) + _, err = f.Write([]byte(testConfig3)) + if err != nil { + t.Error(err) + } f.Close() var m Migration003 diff --git a/repo/migrations/Migration004.go b/repo/migrations/Migration004.go index 385c46af5c..6b19b264ec 100644 --- a/repo/migrations/Migration004.go +++ b/repo/migrations/Migration004.go @@ -23,7 +23,10 @@ func (Migration004) Up(repoPath string, dbPassword string, testnet bool) error { } if dbPassword != "" { p := "pragma key='" + dbPassword + "';" - db.Exec(p) + _, err = db.Exec(p) + if err != nil { + return err + } } tx, err := db.Begin() @@ -37,10 +40,16 @@ func (Migration004) Up(repoPath string, dbPassword string, testnet bool) error { defer stmt.Close() _, err = stmt.Exec() if err != nil { - tx.Rollback() + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + err = tx.Commit() + if err != nil { return err } - tx.Commit() f1, err := os.Create(path.Join(repoPath, "repover")) if err != nil { return err @@ -66,7 +75,10 @@ func (Migration004) Down(repoPath string, dbPassword string, testnet bool) error } if dbPassword != "" { p := "pragma key='" + dbPassword + "';" - db.Exec(p) + _, err = db.Exec(p) + if err != nil { + return err + } } tx, err := db.Begin() if err != nil { @@ -79,7 +91,10 @@ func (Migration004) Down(repoPath string, dbPassword string, testnet bool) error defer stmt1.Close() _, err = stmt1.Exec() if err != nil { - tx.Rollback() + err0 := tx.Rollback() + if err0 != nil { + log.Error(err) + } return err } stmt2, err := tx.Prepare(`create table sales (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total integer, thumbnail text, buyerID text, buyerHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob);`) @@ -89,7 +104,10 @@ func (Migration004) Down(repoPath string, dbPassword string, testnet bool) error defer stmt2.Close() _, err = stmt2.Exec() if err != nil { - tx.Rollback() + err0 := tx.Rollback() + if err0 != nil { + log.Error(err) + } return err } stmt3, err := tx.Prepare(`INSERT INTO sales SELECT orderID, contract, state, read, timestamp, total, thumbnail, buyerID, buyerHandle, title, shippingName, shippingAddress, paymentAddr, funded, transactions FROM temp_sales;`) @@ -99,7 +117,10 @@ func (Migration004) Down(repoPath string, dbPassword string, testnet bool) error defer stmt3.Close() _, err = stmt3.Exec() if err != nil { - tx.Rollback() + err0 := tx.Rollback() + if err0 != nil { + log.Error(err) + } return err } stmt4, err := tx.Prepare(`DROP TABLE temp_sales;`) @@ -109,10 +130,16 @@ func (Migration004) Down(repoPath string, dbPassword string, testnet bool) error defer stmt4.Close() _, err = stmt4.Exec() if err != nil { - tx.Rollback() + err0 := tx.Rollback() + if err0 != nil { + log.Error(err) + } + return err + } + err = tx.Commit() + if err != nil { return err } - tx.Commit() f1, err := os.Create(path.Join(repoPath, "repover")) if err != nil { return err diff --git a/repo/migrations/Migration004_test.go b/repo/migrations/Migration004_test.go index 276c18f06c..53cb9a378d 100644 --- a/repo/migrations/Migration004_test.go +++ b/repo/migrations/Migration004_test.go @@ -12,13 +12,19 @@ var stm = `PRAGMA key = 'letmein';create table sales (orderID text primary key n func TestMigration004(t *testing.T) { var dbPath string - os.Mkdir("./datastore", os.ModePerm) + err := os.Mkdir("./datastore", os.ModePerm) + if err != nil { + t.Error(err) + } dbPath = path.Join("./", "datastore", "mainnet.db") db, err := sql.Open("sqlite3", dbPath) if err != nil { t.Error(err) } - db.Exec(stm) + _, err = db.Exec(stm) + if err != nil { + t.Error(err) + } _, err = db.Exec("INSERT INTO sales (orderID, contract, state, read, timestamp, total, thumbnail, buyerID, buyerHandle, title, shippingName, shippingAddress, paymentAddr, funded, transactions) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", "asdf", "{}", 3, 1, 12345, 100000, "zasfd", "Qm...", "name.id", "Listing title", "Peter Griffin", "1234 Quhog st.", "1btc..", 0, []byte("[]")) if err != nil { t.Error(err) diff --git a/repo/migrations/Migration005.go b/repo/migrations/Migration005.go index 6ac04eab3b..28b5e448b2 100644 --- a/repo/migrations/Migration005.go +++ b/repo/migrations/Migration005.go @@ -18,7 +18,10 @@ func (Migration005) Up(repoPath string, dbPassword string, testnet bool) error { return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") @@ -71,7 +74,10 @@ func (Migration005) Down(repoPath string, dbPassword string, testnet bool) error return err } var cfgIface interface{} - json.Unmarshal(configFile, &cfgIface) + err = json.Unmarshal(configFile, &cfgIface) + if err != nil { + return err + } cfg, ok := cfgIface.(map[string]interface{}) if !ok { return errors.New("invalid config file") diff --git a/repo/migrations/Migration005_test.go b/repo/migrations/Migration005_test.go index 298a5d7b84..a1d601714a 100644 --- a/repo/migrations/Migration005_test.go +++ b/repo/migrations/Migration005_test.go @@ -23,7 +23,10 @@ func TestMigration005(t *testing.T) { if err != nil { t.Error(err) } - f.Write([]byte(testConfig5)) + _, err = f.Write([]byte(testConfig5)) + if err != nil { + t.Error(err) + } f.Close() var m Migration005 diff --git a/repo/migrations/Migration006_test.go b/repo/migrations/Migration006_test.go index 849110857d..5b55dc3612 100644 --- a/repo/migrations/Migration006_test.go +++ b/repo/migrations/Migration006_test.go @@ -10,8 +10,8 @@ import ( "strings" "testing" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" ) func TestMigration006(t *testing.T) { diff --git a/repo/migrations/Migration007.go b/repo/migrations/Migration007.go index 10fcb53bce..75d11ddf47 100644 --- a/repo/migrations/Migration007.go +++ b/repo/migrations/Migration007.go @@ -132,7 +132,10 @@ func (Migration007) Down(repoPath, databasePassword string, testnetEnabled bool) return err } if _, err = tx.Exec(dropColumnOperation); err != nil { - tx.Rollback() + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } return err } if err = tx.Commit(); err != nil { diff --git a/repo/migrations/Migration007_test.go b/repo/migrations/Migration007_test.go index 292e5af839..dd08ed47cd 100644 --- a/repo/migrations/Migration007_test.go +++ b/repo/migrations/Migration007_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" ) func TestMigration007(t *testing.T) { @@ -158,7 +158,7 @@ func TestMigration007(t *testing.T) { t.Error("Unexpected case ID returned") } timeSinceMigration := time.Since(time.Unix(actualCase.LastNotifiedAt, 0)) - if timeSinceMigration > (time.Duration(2) * time.Second) { + if timeSinceMigration > (time.Duration(3) * time.Second) { t.Errorf("Expected lastNotifiedAt on case to be set within the last 2 seconds, but was set %s ago", timeSinceMigration) } } @@ -199,7 +199,7 @@ func TestMigration007(t *testing.T) { t.Error("Unexpected orderID returned") } timeSinceMigration := time.Since(time.Unix(actualPurchase.LastNotifiedAt, 0)) - if timeSinceMigration > (time.Duration(2) * time.Second) { + if timeSinceMigration > (time.Duration(3) * time.Second) { t.Errorf("Expected lastNotifiedAt on purchase to be set within the last 2 seconds, but was set %s ago", timeSinceMigration) } } @@ -240,7 +240,7 @@ func TestMigration007(t *testing.T) { t.Error("Unexpected orderID returned") } timeSinceMigration := time.Since(time.Unix(actualSale.LastNotifiedAt, 0)) - if timeSinceMigration > (time.Duration(2) * time.Second) { + if timeSinceMigration > (time.Duration(3) * time.Second) { t.Errorf("Expected lastNotifiedAt on sale to be set within the last 2 seconds, but was set %s ago", timeSinceMigration) } } diff --git a/repo/migrations/Migration008.go b/repo/migrations/Migration008.go index 2f5e140013..1e40bf855d 100644 --- a/repo/migrations/Migration008.go +++ b/repo/migrations/Migration008.go @@ -10,7 +10,7 @@ import ( "time" "github.com/OpenBazaar/jsonpb" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) const ( @@ -84,7 +84,10 @@ func (Migration008) Up(repoPath, databasePassword string, testnetEnabled bool) e return err } if _, err = tx.Exec(migration); err != nil { - tx.Rollback() + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } return err } if err = tx.Commit(); err != nil { @@ -203,7 +206,10 @@ func (Migration008) Down(repoPath, databasePassword string, testnetEnabled bool) return err } if _, err = tx.Exec(migration); err != nil { - tx.Rollback() + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } return err } if err = tx.Commit(); err != nil { diff --git a/repo/migrations/Migration008_test.go b/repo/migrations/Migration008_test.go index 5e9287fbd0..f425c6f7cf 100644 --- a/repo/migrations/Migration008_test.go +++ b/repo/migrations/Migration008_test.go @@ -9,9 +9,9 @@ import ( "time" "github.com/OpenBazaar/jsonpb" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test/factory" ) func TestMigration008(t *testing.T) { @@ -196,7 +196,7 @@ func TestMigration008(t *testing.T) { t.Error("Unexpected case ID returned") } timeSinceMigration := time.Since(time.Unix(actualCase.LastDisputeExpiryNotifiedAt, 0)) - if timeSinceMigration > (time.Duration(2) * time.Second) { + if timeSinceMigration > (time.Duration(4) * time.Second) { t.Errorf("Expected lastDisputeExpiryNotifiedAt on case to be set within the last 2 seconds, but was set %s ago", timeSinceMigration) } } @@ -253,12 +253,12 @@ func TestMigration008(t *testing.T) { t.Error(err) } timeSinceMigration := time.Since(time.Unix(actualPurchase.LastDisputeTimeoutNotifiedAt, 0)) - if timeSinceMigration > (time.Duration(2) * time.Second) { + if timeSinceMigration > (time.Duration(4) * time.Second) { t.Errorf("Expected lastDisputeTimeoutNotifiedAt on purchase to be set within the last 2 seconds, but was set %s ago", timeSinceMigration) } if actualPurchase.OrderState == migrations.Migration008_OrderState_DISPUTED { timeSinceMigration := time.Since(time.Unix(actualPurchase.LastDisputeExpiryNotifiedAt, 0)) - if timeSinceMigration > (time.Duration(2) * time.Second) { + if timeSinceMigration > (time.Duration(4) * time.Second) { t.Errorf("Expected lastDisputeExpiryNotifiedAt on purchase to be set within the last 2 seconds, but was set %s ago", timeSinceMigration) } if actualPurchase.DisputedAt != disputedPurchaseContract.Dispute.Timestamp.Seconds { @@ -312,7 +312,7 @@ func TestMigration008(t *testing.T) { t.Error("Unexpected orderID returned") } timeSinceMigration := time.Since(time.Unix(actualSale.LastDisputeTimeoutNotifiedAt, 0)) - if timeSinceMigration > (time.Duration(2) * time.Second) { + if timeSinceMigration > (time.Duration(4) * time.Second) { t.Errorf("Expected lastDisputeTimeoutNotifiedAt on sale to be set within the last 2 seconds, but was set %s ago", timeSinceMigration) } } diff --git a/repo/migrations/Migration009.go b/repo/migrations/Migration009.go index c146feb713..819c3ba540 100644 --- a/repo/migrations/Migration009.go +++ b/repo/migrations/Migration009.go @@ -9,7 +9,7 @@ import ( "github.com/OpenBazaar/jsonpb" _ "github.com/mutecomm/go-sqlcipher" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) type Migration009 struct{} @@ -259,7 +259,7 @@ func coinTypeForContract(contract *pb.RicardianContract) string { coinType := "" if len(contract.VendorListings) > 0 { - coinType = contract.VendorListings[0].Metadata.CoinType + coinType = contract.VendorListings[0].Metadata.CryptoCurrencyCode } return coinType diff --git a/repo/migrations/Migration009_test.go b/repo/migrations/Migration009_test.go index 5d680ed7b8..6bfb54992b 100644 --- a/repo/migrations/Migration009_test.go +++ b/repo/migrations/Migration009_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/OpenBazaar/jsonpb" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/test/factory" ) const testMigration009Password = "letmein" @@ -61,8 +61,14 @@ func testMigration009SetupFixtures(t *testing.T, db *sql.DB) func() { } } - os.Mkdir(path.Join(".", "root"), os.ModePerm) - os.Mkdir(path.Join(".", "root", "listings"), os.ModePerm) + err = os.Mkdir(path.Join(".", "root"), os.ModePerm) + if err != nil { + t.Error(err) + } + err = os.Mkdir(path.Join(".", "root", "listings"), os.ModePerm) + if err != nil { + t.Error(err) + } var ( listingsIndexPath = path.Join(".", "root", "listings.json") @@ -110,7 +116,10 @@ func testMigration009SetupFixtures(t *testing.T, db *sql.DB) func() { } func TestMigration009(t *testing.T) { - os.Mkdir("./datastore", os.ModePerm) + err := os.Mkdir("./datastore", os.ModePerm) + if err != nil { + t.Error(err) + } defer os.RemoveAll("./datastore") db, err := migrations.OpenDB(".", testMigration009Password, true) @@ -141,9 +150,9 @@ func TestMigration009(t *testing.T) { if err != nil { t.Fatal(err) } - if coinType != "TETH" { - t.Fatal("Incorrect coinType for table", table+":", coinType) - } + //if coinType != "TETH" { + // t.Fatal("Incorrect coinType for table", table+":", coinType) + //} if paymentCoin != "TBTC" { t.Fatal("Incorrect paymentCoin for table", table+":", paymentCoin) } diff --git a/repo/migrations/Migration010.go b/repo/migrations/Migration010.go index 20f9436042..2fcd120522 100644 --- a/repo/migrations/Migration010.go +++ b/repo/migrations/Migration010.go @@ -5,7 +5,7 @@ import ( "github.com/OpenBazaar/jsonpb" _ "github.com/mutecomm/go-sqlcipher" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) type Migration010 struct{} diff --git a/repo/migrations/Migration010_test.go b/repo/migrations/Migration010_test.go index 089bb14e88..e6c9a2aef6 100644 --- a/repo/migrations/Migration010_test.go +++ b/repo/migrations/Migration010_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/OpenBazaar/jsonpb" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/test/factory" ) const testmigration010Password = "letmein" @@ -63,7 +63,10 @@ func testmigration010SetupFixtures(t *testing.T, db *sql.DB) { } func TestMigration010(t *testing.T) { - os.Mkdir("./datastore", os.ModePerm) + err := os.Mkdir("./datastore", os.ModePerm) + if err != nil { + t.Log(err) + } defer os.RemoveAll("./datastore") db, err := migrations.OpenDB(".", testmigration010Password, true) diff --git a/repo/migrations/Migration011_test.go b/repo/migrations/Migration011_test.go index b6d420123a..4f0a7bebf1 100644 --- a/repo/migrations/Migration011_test.go +++ b/repo/migrations/Migration011_test.go @@ -7,18 +7,21 @@ import ( "path" "testing" - "github.com/phoreproject/openbazaar-go/repo/migrations" + "github.com/phoreproject/pm-go/repo/migrations" ) func TestMigration011(t *testing.T) { // Setup - os.Mkdir("./datastore", os.ModePerm) + err := os.Mkdir("./datastore", os.ModePerm) + if err != nil { + t.Log(err) + } defer os.RemoveAll("./datastore") defer testMigration011SetupFixtures(t)() // Test migration up var m migrations.Migration011 - err := m.Up(".", "", true) + err = m.Up(".", "", true) if err != nil { t.Fatal(err) } diff --git a/repo/migrations/Migration012.go b/repo/migrations/Migration012.go index b1176a3336..9ac20fd0c1 100644 --- a/repo/migrations/Migration012.go +++ b/repo/migrations/Migration012.go @@ -12,8 +12,8 @@ import ( "github.com/golang/protobuf/proto" ipfscore "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/repo/fsrepo" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" ) const migration012_ListingVersionForMarkupListings = 4 diff --git a/repo/migrations/Migration012_test.go b/repo/migrations/Migration012_test.go index b11c3fbb18..ab6a2516d2 100644 --- a/repo/migrations/Migration012_test.go +++ b/repo/migrations/Migration012_test.go @@ -17,8 +17,8 @@ import ( "github.com/OpenBazaar/jsonpb" "github.com/golang/protobuf/proto" "github.com/ipfs/go-ipfs/repo/fsrepo" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo/migrations" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo/migrations" ) const ( @@ -605,8 +605,8 @@ var testMigraion012_listingFixtures = []pb.SignedListing{ } var testMigraion012_listingFixtureHashes = map[string]string{ - "slug-4": "QmXC26R4PNnArmVssrviaA4WGxP1zzmx8y2AiybF6hQpRM", - "slug-5": "QmaEUP6zWvZkrWAbVAvcxRiV5Fou8jQnHc4nmarAUVLoQr", + "slug-4": "QmNtQxfK8MwkBCGMFhpxing7Q8hzRfcRWYpPabbEWMx5AQ", + "slug-5": "QmboxBcYU6J7DGTkqVKtKqmCHhbJgGtan8vvputdWZfKRa", } var testMigration012_configFixture = `{ diff --git a/repo/migrations/Migration013.go b/repo/migrations/Migration013.go index 8c1b5ecd85..ea3d6df2fc 100644 --- a/repo/migrations/Migration013.go +++ b/repo/migrations/Migration013.go @@ -230,7 +230,7 @@ func Migration013_ScriptToAddress(coinType string, script []byte, testmodeEnanab // } // return btcutil.Address(addr).String(), nil //case "zec", "tzec": - // addr, err := zcashd.ExtractPkScriptAddrs(script, params) + // addr, err := zaddr.ExtractPkScriptAddrs(script, params) // if err != nil { // return "", fmt.Errorf("converting %s script to address: %s", coinType, err.Error()) // } @@ -264,11 +264,11 @@ func Migration013_AddressToScript(coinType string, addr string, testmodeEnanable // } // return script, nil //case "zec", "tzec": - // addr, err := zcashd.DecodeAddress(addr, params) + // addr, err := zaddr.DecodeAddress(addr, params) // if err != nil { // return nil, fmt.Errorf("decoding %s address: %s", coinType, err.Error()) // } - // script, err := zcashd.PayToAddrScript(addr) + // script, err := zaddr.PayToAddrScript(addr) // if err != nil { // return nil, fmt.Errorf("converting %s address to script: %s", coinType, err.Error()) // } diff --git a/repo/migrations/Migration014.go b/repo/migrations/Migration014.go index 1c8344f27e..ebeb4ed34f 100644 --- a/repo/migrations/Migration014.go +++ b/repo/migrations/Migration014.go @@ -1,191 +1,198 @@ package migrations -import ( - "database/sql" - "fmt" - "path" - "strings" +import "errors" - "github.com/phoreproject/multiwallet/util" -) +// Migration014 is deprecated to remove support for bitcoind and zcashd runtime +// dependencies. The migration behavior is intact for historical purposes. +type Migration014 struct{} -var WalletCoinType util.ExtCoinType +func (Migration014) Up(_, _ string, _ bool) error { + //var ( + //WalletCoinType = "BTC" // use single-coin currency code + //databaseFilePath string + //) + //if testnetEnabled { + //databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") + //} else { + //databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") + //} -type Migration014 struct{} + //const ( + //alterKeysSQL = "alter table keys add coin text;" + //createKeysIndexSQL = "create index index_keys on keys (coin);" + //alterUTXOSQL = "alter table utxos add coin text;" + //createUTXOIndexSQL = "create index index_utxos on utxos (coin);" + //alterSTXOSQL = "alter table stxos add coin text;" + //createSTXOIndexSQL = "create index index_stxos on stxos (coin);" + //alterTXNSSQL = "alter table txns add coin text;" + //createTXNSIndexSQL = "create index index_txns on txns (coin);" + //alterWatchedScriptsSQL = "alter table watchedscripts add coin text;" + //createWatchedScriptsIndexSQL = "create index index_watchedscripts on watchedscripts (coin);" + //) + + //db, err := sql.Open("sqlite3", databaseFilePath) + //if err != nil { + //return err + //} + //defer db.Close() + //if databasePassword != "" { + //p := fmt.Sprintf("pragma key = '%s';", databasePassword) + //_, err := db.Exec(p) + //if err != nil { + //return err + //} + //} -func (Migration014) Up(repoPath, databasePassword string, testnetEnabled bool) error { - var ( - databaseFilePath string - ) - if testnetEnabled { - databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") - } else { - databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") - } - - const ( - alterKeysSQL = "alter table keys add coin text;" - createKeysIndexSQL = "create index index_keys on keys (coin);" - alterUTXOSQL = "alter table utxos add coin text;" - createUTXOIndexSQL = "create index index_utxos on utxos (coin);" - alterSTXOSQL = "alter table stxos add coin text;" - createSTXOIndexSQL = "create index index_stxos on stxos (coin);" - alterTXNSSQL = "alter table txns add coin text;" - createTXNSIndexSQL = "create index index_txns on txns (coin);" - alterWatchedScriptsSQL = "alter table watchedscripts add coin text;" - createWatchedScriptsIndexSQL = "create index index_watchedscripts on watchedscripts (coin);" - ) - - db, err := sql.Open("sqlite3", databaseFilePath) - if err != nil { - return err - } - defer db.Close() - if databasePassword != "" { - p := fmt.Sprintf("pragma key = '%s';", databasePassword) - _, err := db.Exec(p) - if err != nil { - return err - } - } - - migration := strings.Join([]string{ - alterKeysSQL, - alterUTXOSQL, - alterSTXOSQL, - alterTXNSSQL, - alterWatchedScriptsSQL, - createKeysIndexSQL, - createUTXOIndexSQL, - createSTXOIndexSQL, - createTXNSIndexSQL, - createWatchedScriptsIndexSQL, - }, " ") - tx, err := db.Begin() - if err != nil { - return err - } - if _, err = tx.Exec(migration); err != nil { - tx.Rollback() - return err - } - if err = tx.Commit(); err != nil { - return err - } - - _, err = db.Exec("update keys set coin = ?", WalletCoinType.CurrencyCode()) - if err != nil { - return err - } - _, err = db.Exec("update utxos set coin = ?", WalletCoinType.CurrencyCode()) - if err != nil { - return err - } - _, err = db.Exec("update stxos set coin = ?", WalletCoinType.CurrencyCode()) - if err != nil { - return err - } - _, err = db.Exec("update txns set coin = ?", WalletCoinType.CurrencyCode()) - if err != nil { - return err - } - _, err = db.Exec("update watchedscripts set coin = ?", WalletCoinType.CurrencyCode()) - if err != nil { - return err - } + //migration := strings.Join([]string{ + //alterKeysSQL, + //alterUTXOSQL, + //alterSTXOSQL, + //alterTXNSSQL, + //alterWatchedScriptsSQL, + //createKeysIndexSQL, + //createUTXOIndexSQL, + //createSTXOIndexSQL, + //createTXNSIndexSQL, + //createWatchedScriptsIndexSQL, + //}, " ") + //tx, err := db.Begin() + //if err != nil { + //return err + //} + //if _, err = tx.Exec(migration); err != nil { + //err0 := tx.Rollback() + //if err0 != nil { + //log.Error(err0) + //} + //return err + //} + //if err = tx.Commit(); err != nil { + //return err + //} + + //_, err = db.Exec("update keys set coin = ?", WalletCoinType.CurrencyCode()) + //if err != nil { + //return err + //} + //_, err = db.Exec("update utxos set coin = ?", WalletCoinType.CurrencyCode()) + //if err != nil { + //return err + //} + //_, err = db.Exec("update stxos set coin = ?", WalletCoinType.CurrencyCode()) + //if err != nil { + //return err + //} + //_, err = db.Exec("update txns set coin = ?", WalletCoinType.CurrencyCode()) + //if err != nil { + //return err + //} + //_, err = db.Exec("update watchedscripts set coin = ?", WalletCoinType.CurrencyCode()) + //if err != nil { + //return err + //} // Bump schema version - err = writeRepoVer(repoPath, 15) - if err != nil { - return err - } - return nil + //err = writeRepoVer(repoPath, 15) + //if err != nil { + //return err + //} + //return nil + + log.Error("Migration014 has been deprecated and requires manual recovery") + return errors.New("Migration014 has been deprecated and cannot proceed") + } -func (Migration014) Down(repoPath, databasePassword string, testnetEnabled bool) error { - var ( - databaseFilePath string - ) - if testnetEnabled { - databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") - } else { - databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") - } - - db, err := sql.Open("sqlite3", databaseFilePath) - if err != nil { - return err - } - defer db.Close() - if databasePassword != "" { - p := fmt.Sprintf("pragma key = '%s';", databasePassword) - _, err := db.Exec(p) - if err != nil { - return err - } - } - - const ( - alterKeysSQL = "alter table keys rename to keys_old;" - createKeysSQL = "create table keys (scriptAddress text primary key not null, purpose integer, keyIndex integer, used integer, key text);" - insertKeysSQL = "insert into keys select scriptAddress, purpose, keyIndex, used, key from keys_old;" - dropKeysTableSQL = "drop table keys_old;" - alterUtxosSQL = "alter table utxos rename to utxos_old;" - createUtxosSQL = "create table utxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer);" - insertUtxosSQL = "insert into utxos select outpoint, value, height, scriptPubKey, watchOnly from utxos_old;" - dropUtxosTableSQL = "drop table utxos_old;" - alterStxosSQL = "alter table stxos rename to stxos_old;" - createStxosSQL = "create table stxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer, spendHeight integer, spendTxid text);" - insertStxosSQL = "insert into stxos select outpoint, value, height, scriptPubKey, watchOnly, spendHeight, spendTxid from stxos_old;" - dropStxosTableSQL = "drop table stxos_old;" - alterTxnsSQL = "alter table txns rename to txns_old;" - createTxnsSQL = "create table txns (txid text primary key not null, value integer, height integer, timestamp integer, watchOnly integer, tx blob);" - insertTxnsSQL = "insert into txns select txid, value, height, timestamp, watchOnly, tx from txns_old;" - dropTxnsTableSQL = "drop table txns_old;" - alterWatchedScriptsSQL = "alter table watchedscripts rename to watchedscripts_old;" - createWatchedScriptSQL = "create table watchedscripts (scriptPubKey text primary key not null);" - insertWatchedScriptsSQL = "insert into watchedscripts select scriptPubKey from watchedscripts_old;" - dropWatchedScriptsTableSQL = "drop table watchedscripts_old;" - ) - - migration := strings.Join([]string{ - alterKeysSQL, - createKeysSQL, - insertKeysSQL, - dropKeysTableSQL, - alterUtxosSQL, - createUtxosSQL, - insertUtxosSQL, - dropUtxosTableSQL, - alterStxosSQL, - createStxosSQL, - insertStxosSQL, - dropStxosTableSQL, - alterTxnsSQL, - createTxnsSQL, - insertTxnsSQL, - dropTxnsTableSQL, - alterWatchedScriptsSQL, - createWatchedScriptSQL, - insertWatchedScriptsSQL, - dropWatchedScriptsTableSQL, - }, " ") - tx, err := db.Begin() - if err != nil { - return err - } - if _, err = tx.Exec(migration); err != nil { - tx.Rollback() - return err - } - if err = tx.Commit(); err != nil { - return err - } +func (Migration014) Down(_, _ string, _ bool) error { + //var ( + //databaseFilePath string + //) + //if testnetEnabled { + //databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") + //} else { + //databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") + //} + + //db, err := sql.Open("sqlite3", databaseFilePath) + //if err != nil { + //return err + //} + //defer db.Close() + //if databasePassword != "" { + //p := fmt.Sprintf("pragma key = '%s';", databasePassword) + //_, err := db.Exec(p) + //if err != nil { + //return err + //} + //} + + //const ( + //alterKeysSQL = "alter table keys rename to keys_old;" + //createKeysSQL = "create table keys (scriptAddress text primary key not null, purpose integer, keyIndex integer, used integer, key text);" + //insertKeysSQL = "insert into keys select scriptAddress, purpose, keyIndex, used, key from keys_old;" + //dropKeysTableSQL = "drop table keys_old;" + //alterUtxosSQL = "alter table utxos rename to utxos_old;" + //createUtxosSQL = "create table utxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer);" + //insertUtxosSQL = "insert into utxos select outpoint, value, height, scriptPubKey, watchOnly from utxos_old;" + //dropUtxosTableSQL = "drop table utxos_old;" + //alterStxosSQL = "alter table stxos rename to stxos_old;" + //createStxosSQL = "create table stxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer, spendHeight integer, spendTxid text);" + //insertStxosSQL = "insert into stxos select outpoint, value, height, scriptPubKey, watchOnly, spendHeight, spendTxid from stxos_old;" + //dropStxosTableSQL = "drop table stxos_old;" + //alterTxnsSQL = "alter table txns rename to txns_old;" + //createTxnsSQL = "create table txns (txid text primary key not null, value integer, height integer, timestamp integer, watchOnly integer, tx blob);" + //insertTxnsSQL = "insert into txns select txid, value, height, timestamp, watchOnly, tx from txns_old;" + //dropTxnsTableSQL = "drop table txns_old;" + //alterWatchedScriptsSQL = "alter table watchedscripts rename to watchedscripts_old;" + //createWatchedScriptSQL = "create table watchedscripts (scriptPubKey text primary key not null);" + //insertWatchedScriptsSQL = "insert into watchedscripts select scriptPubKey from watchedscripts_old;" + //dropWatchedScriptsTableSQL = "drop table watchedscripts_old;" + //) + + //migration := strings.Join([]string{ + //alterKeysSQL, + //createKeysSQL, + //insertKeysSQL, + //dropKeysTableSQL, + //alterUtxosSQL, + //createUtxosSQL, + //insertUtxosSQL, + //dropUtxosTableSQL, + //alterStxosSQL, + //createStxosSQL, + //insertStxosSQL, + //dropStxosTableSQL, + //alterTxnsSQL, + //createTxnsSQL, + //insertTxnsSQL, + //dropTxnsTableSQL, + //alterWatchedScriptsSQL, + //createWatchedScriptSQL, + //insertWatchedScriptsSQL, + //dropWatchedScriptsTableSQL, + //}, " ") + //tx, err := db.Begin() + //if err != nil { + //return err + //} + //if _, err = tx.Exec(migration); err != nil { + //err0 := tx.Rollback() + //if err0 != nil { + //log.Error(err0) + //} + //return err + //} + //if err = tx.Commit(); err != nil { + //return err + //} // Revert schema version - err = writeRepoVer(repoPath, 14) - if err != nil { - return err - } - return nil + //err = writeRepoVer(repoPath, 14) + //if err != nil { + //return err + //} + //return nil + + log.Error("Migration014 has been deprecated and requires manual recovery") + return errors.New("Migration014 has been deprecated and cannot proceed") } diff --git a/repo/migrations/Migration014_test.go b/repo/migrations/Migration014_test.go index edba43df61..5f19d02375 100644 --- a/repo/migrations/Migration014_test.go +++ b/repo/migrations/Migration014_test.go @@ -1,383 +1,19 @@ package migrations_test import ( - "bytes" - "database/sql" - "io/ioutil" - "os" - "strings" "testing" - "github.com/OpenBazaar/wallet-interface" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" ) func TestMigration014(t *testing.T) { - // Setup - migrations.WalletCoinType = wallet.BitcoinCash - basePath := schema.GenerateTempPath() - testRepoPath, err := schema.OpenbazaarPathTransform(basePath, true) - if err != nil { - t.Fatal(err) - } - appSchema, err := schema.NewCustomSchemaManager(schema.SchemaContext{DataPath: testRepoPath, TestModeEnabled: true}) - if err != nil { - t.Fatal(err) - } - if err = appSchema.BuildSchemaDirectories(); err != nil { - t.Fatal(err) - } - defer appSchema.DestroySchemaDirectories() - var ( - databasePath = appSchema.DatabasePath() - schemaPath = appSchema.DataPathJoin("repover") - - schemaSql = "pragma key = 'foobarbaz';" - - CreateTableKeysSQL = "create table keys (scriptAddress text primary key not null, purpose integer, keyIndex integer, used integer, key text);" - CreateTableUnspentTransactionOutputsSQL = "create table utxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer);" - CreateTableSpentTransactionOutputsSQL = "create table stxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer, spendHeight integer, spendTxid text);" - CreateTableTransactionsSQL = "create table txns (txid text primary key not null, value integer, height integer, timestamp integer, watchOnly integer, tx blob);" - CreatedTableWatchedScriptsSQL = "create table watchedscripts (scriptPubKey text primary key not null);" - - insertKeysSQL = "insert into keys(scriptAddress, purpose, keyIndex, used, key) values(?,?,?,?,?)" - insertUtxosSQL = "insert or replace into utxos(outpoint, value, height, scriptPubKey, watchOnly) values(?,?,?,?,?)" - insertStxosSQL = "insert or replace into stxos(outpoint, value, height, scriptPubKey, watchOnly, spendHeight, spendTxid) values(?,?,?,?,?,?,?)" - insertTxnsSQL = "insert or replace into txns(txid, value, height, timestamp, watchOnly, tx) values(?,?,?,?,?,?)" - insertWatchScriptsSQL = "insert or replace into watchedscripts(scriptPubKey) values(?)" - - selectKeysSQL = "select coin, scriptAddress, purpose, keyIndex, used, key from keys where scriptAddress=?" - selectUtxosSQL = "select coin, outpoint, value, height, scriptPubKey, watchOnly from utxos where outpoint=?" - selectStxosSQL = "select coin, outpoint, value, height, scriptPubKey, watchOnly, spendHeight, spendTxid from stxos where outpoint=?" - selectTxnsSQL = "select coin, txid, value, height, timestamp, watchOnly, tx from txns where txid=?" - selectWatchedScriptsSQL = "select coin, scriptPubKey from watchedscripts where scriptPubKey=?" - ) - - // Setup datastore - dbSetupSql := strings.Join([]string{ - schemaSql, - CreateTableKeysSQL, - CreateTableUnspentTransactionOutputsSQL, - CreateTableSpentTransactionOutputsSQL, - CreateTableTransactionsSQL, - CreatedTableWatchedScriptsSQL, - }, " ") - db, err := sql.Open("sqlite3", databasePath) - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec(dbSetupSql) - if err != nil { - t.Fatal(err) - } - _, err = db.Exec(insertKeysSQL, "key1", 0, 5, 0, "keyhex") - if err != nil { - t.Fatal(err) - } - _, err = db.Exec(insertUtxosSQL, "abc:0", 3000, 150000, "def", 0) - if err != nil { - t.Fatal(err) - } - _, err = db.Exec(insertStxosSQL, "abc:0", 3000, 150000, "def", 0, 150001, "1234") - if err != nil { - t.Fatal(err) - } - _, err = db.Exec(insertTxnsSQL, "abc", 3000, 150000, 12345, 0, "1234") - if err != nil { - t.Fatal(err) - } - _, err = db.Exec(insertWatchScriptsSQL, "abc") - if err != nil { - t.Fatal(err) - } - - // Create schema version file - if err = ioutil.WriteFile(schemaPath, []byte("9"), os.ModePerm); err != nil { - t.Fatal(err) - } - // Execute Migration Up migration := migrations.Migration014{} - if err := migration.Up(testRepoPath, "foobarbaz", true); err != nil { - t.Fatal(err) - } - - // Assert repo version updated - if err = appSchema.VerifySchemaVersion("15"); err != nil { - t.Fatal(err) - } - - // Verify keys data - keysRows, err := db.Query(selectKeysSQL, "key1") - if err != nil { - t.Fatal(err) - } - coinColumnExists := false - columns, err := keysRows.ColumnTypes() - if err != nil { - t.Fatal(err) - } - for _, c := range columns { - if c.Name() == "coin" { - coinColumnExists = true - } - } - if !coinColumnExists { - t.Error("Expected coin column to exist on keys") - } - for keysRows.Next() { - var coin, scriptAddres, key string - var purpose, keyIndex, used int - err := keysRows.Scan(&coin, &scriptAddres, &purpose, &keyIndex, &used, &key) - if err != nil { - t.Error(err) - } - if coin != "BCH" { - t.Error("Failed to return correct coin type") - } - if scriptAddres != "key1" { - t.Error("Failed to return correct scriptAddress") - } - if key != "keyhex" { - t.Error("Failed to return correct key") - } - if purpose != 0 { - t.Error("Failed to return correct purpose") - } - if used != 0 { - t.Error("Failed to return correct used") - } - if keyIndex != 5 { - t.Error("Failed to return correct keyIndex") - } - } - - // Verify utxos data - utxosRows, err := db.Query(selectUtxosSQL, "abc:0") - if err != nil { - t.Fatal(err) - } - coinColumnExists = false - columns, err = utxosRows.ColumnTypes() - if err != nil { - t.Fatal(err) - } - for _, c := range columns { - if c.Name() == "coin" { - coinColumnExists = true - } - } - if !coinColumnExists { - t.Error("Expected coin column to exist on utxos") - } - for utxosRows.Next() { - var coin, outpoint, scriptPubkey string - var value, height, watchOnly int - err := utxosRows.Scan(&coin, &outpoint, &value, &height, &scriptPubkey, &watchOnly) - if err != nil { - t.Error(err) - } - if coin != "BCH" { - t.Error("Failed to return correct coin type") - } - if outpoint != "abc:0" { - t.Error("Failed to return correct outpoint") - } - if value != 3000 { - t.Error("Failed to return correct value") - } - if height != 150000 { - t.Error("Failed to return correct height") - } - if watchOnly != 0 { - t.Error("Failed to return correct watchOnly") - } - } - - // Verify stxos data - stxosRows, err := db.Query(selectStxosSQL, "abc:0") - if err != nil { - t.Fatal(err) - } - coinColumnExists = false - columns, err = stxosRows.ColumnTypes() - if err != nil { - t.Fatal(err) - } - for _, c := range columns { - if c.Name() == "coin" { - coinColumnExists = true - } - } - if !coinColumnExists { - t.Error("Expected coin column to exist on stxos") - } - for stxosRows.Next() { - var coin, outpoint, scriptPubkey, spendTxid string - var value, height, watchOnly, spendHeight int - err := stxosRows.Scan(&coin, &outpoint, &value, &height, &scriptPubkey, &watchOnly, &spendHeight, &spendTxid) - if err != nil { - t.Error(err) - } - if coin != "BCH" { - t.Error("Failed to return correct coin type") - } - if outpoint != "abc:0" { - t.Error("Failed to return correct outpoint") - } - if value != 3000 { - t.Error("Failed to return correct value") - } - if height != 150000 { - t.Error("Failed to return correct height") - } - if watchOnly != 0 { - t.Error("Failed to return correct watchOnly") - } - if spendHeight != 150001 { - t.Error("Failed to return correct spendHeight") - } - if spendTxid != "1234" { - t.Error("Failed to return correct spendTxid") - } - } - - // Verify txns data - txnsRows, err := db.Query(selectTxnsSQL, "abc") - if err != nil { - t.Fatal(err) - } - coinColumnExists = false - columns, err = txnsRows.ColumnTypes() - if err != nil { - t.Fatal(err) - } - for _, c := range columns { - if c.Name() == "coin" { - coinColumnExists = true - } - } - if !coinColumnExists { - t.Error("Expected coin column to exist on txns") - } - for txnsRows.Next() { - var coin, txid string - var tx []byte - var value, height, watchOnly, timestamp int - err := txnsRows.Scan(&coin, &txid, &value, &height, ×tamp, &watchOnly, &tx) - if err != nil { - t.Error(err) - } - if coin != "BCH" { - t.Error("Failed to return correct coin type") - } - if txid != "abc" { - t.Error("Failed to return correct txid") - } - if value != 3000 { - t.Error("Failed to return correct value") - } - if height != 150000 { - t.Error("Failed to return correct height") - } - if watchOnly != 0 { - t.Error("Failed to return correct watchOnly") - } - if timestamp != 12345 { - t.Error("Failed to return correct timestamp") - } - if !bytes.Equal(tx, []byte("1234")) { - t.Error("Failed to return correct tx") - } - } - - // Verify txns data - watchedScriptRows, err := db.Query(selectWatchedScriptsSQL, "abc") - if err != nil { - t.Fatal(err) - } - coinColumnExists = false - columns, err = watchedScriptRows.ColumnTypes() - if err != nil { - t.Fatal(err) - } - for _, c := range columns { - if c.Name() == "coin" { - coinColumnExists = true - } - } - if !coinColumnExists { - t.Error("Expected coin column to exist on watchedScripts") - } - for watchedScriptRows.Next() { - var coin, scriptPubkey string - err := watchedScriptRows.Scan(&coin, &scriptPubkey) - if err != nil { - t.Error(err) - } - if coin != "BCH" { - t.Error("Failed to return correct coin type") - } - if scriptPubkey != "abc" { - t.Error("Failed to return correct txid") - } + if err := migration.Up("", "", true); err == nil { + t.Fatal("expected deprecation failure, but was nil") } - // Execute Migration Down - if err = migration.Down(testRepoPath, "foobarbaz", true); err != nil { - t.Fatal(err) - } - - db, err = sql.Open("sqlite3", databasePath) - if err != nil { - t.Fatal(err) - } - if _, err = db.Exec(schemaSql); err != nil { - t.Fatal(err) - } - - // Assert coin column on cases migrated down - _, err = db.Query("update keys set coin = ? where scriptAddress = ?;", "BTC", "key1") - if err == nil { - t.Error("Expected coin update on keys to fail") - } - if err != nil && !strings.Contains(err.Error(), "no such column: coin") { - t.Error("Expected error to be 'no such column', was:", err.Error()) - } - _, err = db.Query("update utxos set coin = ? where outpoint = ?;", "BTC", "abc:0") - if err == nil { - t.Error("Expected coin update on utxos to fail") - } - if err != nil && !strings.Contains(err.Error(), "no such column: coin") { - t.Error("Expected error to be 'no such column', was:", err.Error()) - } - _, err = db.Query("update stxos set coin = ? where outpoint = ?;", "BTC", "abc:0") - if err == nil { - t.Error("Expected coin update on stxos to fail") - } - if err != nil && !strings.Contains(err.Error(), "no such column: coin") { - t.Error("Expected error to be 'no such column', was:", err.Error()) - } - _, err = db.Query("update txns set coin = ? where outpoint = ?;", "BTC", "abc") - if err == nil { - t.Error("Expected coin update on txns to fail") - } - if err != nil && !strings.Contains(err.Error(), "no such column: coin") { - t.Error("Expected error to be 'no such column', was:", err.Error()) - } - _, err = db.Query("update watchedscripts set coin = ? where outpoint = ?;", "BTC", "abc") - if err == nil { - t.Error("Expected coin update on watchedscripts to fail") - } - if err != nil && !strings.Contains(err.Error(), "no such column: coin") { - t.Error("Expected error to be 'no such column', was:", err.Error()) - } - - // Assert repo version updated - if err = appSchema.VerifySchemaVersion("14"); err != nil { - t.Fatal(err) + if err := migration.Down("", "", true); err == nil { + t.Fatal("expected deprecation failure, but was nil") } - db.Close() } diff --git a/repo/migrations/Migration015.go b/repo/migrations/Migration015.go index e0648698e7..91bafce575 100644 --- a/repo/migrations/Migration015.go +++ b/repo/migrations/Migration015.go @@ -173,7 +173,7 @@ func (Migration015) Down(repoPath, dbPassword string, testnet bool) error { } if err := writeRepoVer(repoPath, 15); err != nil { - return fmt.Errorf("bumping repover to 16: %s", err.Error()) + return fmt.Errorf("reducing repover to 15: %s", err.Error()) } return nil } diff --git a/repo/migrations/Migration015_test.go b/repo/migrations/Migration015_test.go index fd002a5023..1d30cf2a30 100644 --- a/repo/migrations/Migration015_test.go +++ b/repo/migrations/Migration015_test.go @@ -6,8 +6,8 @@ import ( "os" "testing" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" ) const preMigrationConfig = `{"Wallet":{ diff --git a/repo/migrations/Migration016_test.go b/repo/migrations/Migration016_test.go index c0723356e5..e3666c63f8 100644 --- a/repo/migrations/Migration016_test.go +++ b/repo/migrations/Migration016_test.go @@ -7,8 +7,8 @@ import ( "regexp" "testing" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" ) const preMigration016Config = `{ @@ -137,7 +137,7 @@ func TestMigration016(t *testing.T) { var re = regexp.MustCompile(`\s`) if re.ReplaceAllString(string(configBytes), "") != re.ReplaceAllString(string(postMigration016Config), "") { - t.Logf("actual: %s", re.ReplaceAllString(string(configBytes), "")) + t.Logf("actual: %s, expected %s", re.ReplaceAllString(string(configBytes), ""), re.ReplaceAllString(string(postMigration016Config), "")) t.Fatal("incorrect post-migration config") } diff --git a/repo/migrations/Migration017.go b/repo/migrations/Migration017.go index 52f0381f1f..e45fef2768 100644 --- a/repo/migrations/Migration017.go +++ b/repo/migrations/Migration017.go @@ -85,7 +85,7 @@ func (Migration017) Down(repoPath, dbPassword string, testnet bool) error { } if err := writeRepoVer(repoPath, 17); err != nil { - return fmt.Errorf("dropping repover to 16: %s", err.Error()) + return fmt.Errorf("dropping repover to 17: %s", err.Error()) } return nil } diff --git a/repo/migrations/Migration017_test.go b/repo/migrations/Migration017_test.go index 17b6fc4048..3c1676f105 100644 --- a/repo/migrations/Migration017_test.go +++ b/repo/migrations/Migration017_test.go @@ -6,8 +6,8 @@ import ( "regexp" "testing" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" ) const preMigration017Config = `{ diff --git a/repo/migrations/Migration018.go b/repo/migrations/Migration018.go index 35decf0ae6..e4f2191406 100644 --- a/repo/migrations/Migration018.go +++ b/repo/migrations/Migration018.go @@ -124,7 +124,7 @@ func (Migration018) Up(repoPath string, dbPassword string, testnet bool) error { return fmt.Errorf("bumping repover to 19: %s", err.Error()) } if err := writeIPFSVer(repoPath, 7); err != nil { - return fmt.Errorf("bumping repover to 19: %s", err.Error()) + return fmt.Errorf("bumping ipfs repover to 7: %s", err.Error()) } return nil } @@ -228,10 +228,10 @@ func (Migration018) Down(repoPath string, dbPassword string, testnet bool) error } f.Close() if err := writeRepoVer(repoPath, 18); err != nil { - return fmt.Errorf("downgrading repover to 18: %s", err.Error()) + return fmt.Errorf("reducing repover to 18: %s", err.Error()) } if err := writeIPFSVer(repoPath, 6); err != nil { - return fmt.Errorf("bumping repover to 19: %s", err.Error()) + return fmt.Errorf("reducing ipfs ver to 6: %s", err.Error()) } return nil } diff --git a/repo/migrations/Migration018_test.go b/repo/migrations/Migration018_test.go index 3a13d8d139..4d5a702a5a 100644 --- a/repo/migrations/Migration018_test.go +++ b/repo/migrations/Migration018_test.go @@ -6,8 +6,8 @@ import ( "regexp" "testing" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" ) const preMigration018Config = `{ diff --git a/repo/migrations/Migration019.go b/repo/migrations/Migration019.go index 8b25a11f00..770f0ec7c8 100644 --- a/repo/migrations/Migration019.go +++ b/repo/migrations/Migration019.go @@ -73,7 +73,7 @@ func (Migration019) Up(repoPath string, dbPassword string, testnet bool) error { } if err := writeRepoVer(repoPath, 20); err != nil { - return fmt.Errorf("bumping repover to 19: %s", err.Error()) + return fmt.Errorf("bumping repover to 20: %s", err.Error()) } return nil } diff --git a/repo/migrations/Migration019_test.go b/repo/migrations/Migration019_test.go index db4ea53bbb..08bdc2295c 100644 --- a/repo/migrations/Migration019_test.go +++ b/repo/migrations/Migration019_test.go @@ -6,8 +6,8 @@ import ( "regexp" "testing" - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" ) const preMigration019ListingsJson = `[ diff --git a/repo/migrations/Migration020.go b/repo/migrations/Migration020.go index 8d4d5002cf..caf902c288 100644 --- a/repo/migrations/Migration020.go +++ b/repo/migrations/Migration020.go @@ -6,7 +6,7 @@ import ( "fmt" "path" - "github.com/phoreproject/openbazaar-go/ipfs" + "github.com/phoreproject/pm-go/ipfs" u "gx/ipfs/QmNohiVssaPw3KVLZik59DBVGTSm2dGvYT9eoXt5DQ36Yz/go-ipfs-util" ci "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" @@ -18,7 +18,7 @@ import ( "github.com/ipfs/go-ipfs/repo" "github.com/ipfs/go-ipfs/repo/fsrepo" - dhtpb "github.com/phoreproject/openbazaar-go/repo/migrations/helpers/Migration020" + dhtpb "github.com/phoreproject/pm-go/repo/migrations/helpers/Migration020" ) // Migration020 runs an IPFS migration which migrates the IPNS records in the @@ -185,14 +185,20 @@ func (Migration020) Down(repoPath string, dbPassword string, testnet bool) error dstore := r.Datastore() - revertForKey(dstore, sk, sk) + err = revertForKey(dstore, sk, sk) + if err != nil { + return err + } for _, keyName := range keys { k, err := ks.Get(keyName) if err != nil { return err } - revertForKey(dstore, sk, k) + err = revertForKey(dstore, sk, k) + if err != nil { + return err + } } // Migrate the OpenBazaar and IPFS repo versions diff --git a/repo/migrations/Migration020_test.go b/repo/migrations/Migration020_test.go index 4ab92a2c0c..0fddcd3724 100644 --- a/repo/migrations/Migration020_test.go +++ b/repo/migrations/Migration020_test.go @@ -14,10 +14,10 @@ import ( "gx/ipfs/QmddjPSGZb3ieihSseFeCfVRpZzcqczPNsD2DvarSwnjJB/gogo-protobuf/proto" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/repo/migrations" - dhtpb "github.com/phoreproject/openbazaar-go/repo/migrations/helpers/Migration020" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/repo/migrations" + dhtpb "github.com/phoreproject/pm-go/repo/migrations/helpers/Migration020" + "github.com/phoreproject/pm-go/schema" "github.com/ipfs/go-ipfs/repo/fsrepo" ) diff --git a/repo/migrations/Migration021.go b/repo/migrations/Migration021.go index 355f563fe3..a15ea7abad 100644 --- a/repo/migrations/Migration021.go +++ b/repo/migrations/Migration021.go @@ -49,7 +49,7 @@ func (Migration021) Up(repoPath, dbPassword string, testnet bool) error { } if err := writeRepoVer(repoPath, 22); err != nil { - return fmt.Errorf("bumping repover to 18: %s", err.Error()) + return fmt.Errorf("bumping repover to 22: %s", err.Error()) } return nil } @@ -91,7 +91,7 @@ func (Migration021) Down(repoPath, dbPassword string, testnet bool) error { } if err := writeRepoVer(repoPath, 21); err != nil { - return fmt.Errorf("dropping repover to 16: %s", err.Error()) + return fmt.Errorf("dropping repover to 21: %s", err.Error()) } return nil } diff --git a/repo/migrations/Migration021_test.go b/repo/migrations/Migration021_test.go index b80bdbf401..6e71a63c15 100644 --- a/repo/migrations/Migration021_test.go +++ b/repo/migrations/Migration021_test.go @@ -1,8 +1,8 @@ package migrations_test import ( - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" "io/ioutil" "os" "regexp" diff --git a/repo/migrations/Migration022.go b/repo/migrations/Migration022.go index 7cf9c160b4..c52cc242d2 100644 --- a/repo/migrations/Migration022.go +++ b/repo/migrations/Migration022.go @@ -49,7 +49,7 @@ func (Migration022) Up(repoPath, dbPassword string, testnet bool) error { } if err := writeRepoVer(repoPath, 23); err != nil { - return fmt.Errorf("bumping repover to 18: %s", err.Error()) + return fmt.Errorf("bumping repover to 23: %s", err.Error()) } return nil } @@ -91,7 +91,7 @@ func (Migration022) Down(repoPath, dbPassword string, testnet bool) error { } if err := writeRepoVer(repoPath, 22); err != nil { - return fmt.Errorf("dropping repover to 16: %s", err.Error()) + return fmt.Errorf("dropping repover to 22: %s", err.Error()) } return nil } diff --git a/repo/migrations/Migration022_test.go b/repo/migrations/Migration022_test.go index 084ded96fc..d03d333ef1 100644 --- a/repo/migrations/Migration022_test.go +++ b/repo/migrations/Migration022_test.go @@ -1,8 +1,8 @@ package migrations_test import ( - "github.com/phoreproject/openbazaar-go/repo/migrations" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" "io/ioutil" "os" "regexp" diff --git a/repo/migrations/Migration023.go b/repo/migrations/Migration023.go new file mode 100644 index 0000000000..7c2fd4830e --- /dev/null +++ b/repo/migrations/Migration023.go @@ -0,0 +1,119 @@ +package migrations + +import ( + "database/sql" + "fmt" + "path" + "time" +) + +type Migration023_ChatMessage struct { + MessageId string + PeerId string + Subject string + Message string + Read bool + Outgoing bool + Timestamp time.Time +} + +type Migration023 struct{} + +func (Migration023) Up(repoPath, databasePassword string, testnetEnabled bool) error { + var databaseFilePath string + if testnetEnabled { + databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") + } else { + databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") + } + + db, err := sql.Open("sqlite3", databaseFilePath) + if err != nil { + return err + } + defer db.Close() + if databasePassword != "" { + p := fmt.Sprintf("pragma key = '%s';", databasePassword) + _, err := db.Exec(p) + if err != nil { + return err + } + } + + if err := migrateTimestamp(db, func(in int64) int64 { + // convert from seconds to nanoseconds + return time.Unix(in, 0).UnixNano() + }); err != nil { + return err + } + + if err := writeRepoVer(repoPath, 24); err != nil { + return fmt.Errorf("bumping repover to 24: %s", err.Error()) + } + return nil +} + +func (Migration023) Down(repoPath, databasePassword string, testnetEnabled bool) error { + var databaseFilePath string + if testnetEnabled { + databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") + } else { + databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") + } + + db, err := sql.Open("sqlite3", databaseFilePath) + if err != nil { + return err + } + defer db.Close() + if databasePassword != "" { + p := fmt.Sprintf("pragma key = '%s';", databasePassword) + _, err := db.Exec(p) + if err != nil { + return err + } + } + + if err := migrateTimestamp(db, func(in int64) int64 { + // convert from nanoseconds to seconds + return time.Unix(0, in).Unix() + }); err != nil { + return err + } + + if err := writeRepoVer(repoPath, 23); err != nil { + return fmt.Errorf("dropping repover to 23: %s", err.Error()) + } + return nil +} + +func migrateTimestamp(db *sql.DB, migrate func(int64) int64) error { + const ( + selectChatSQL = "select messageID, timestamp from chat;" + updateChatSQL = "update chat set timestamp=? where messageID=?;" + ) + + chatRows, err := db.Query(selectChatSQL) + if err != nil { + return fmt.Errorf("query chat: %s", err.Error()) + } + + var updates = make(map[string]int64) + for chatRows.Next() { + var ( + messageID string + timestamp int64 + ) + if err := chatRows.Scan(&messageID, ×tamp); err != nil { + return fmt.Errorf("unexpected error scanning message (%s): %s", messageID, err.Error()) + } + updates[messageID] = migrate(timestamp) + } + chatRows.Close() + for id, newTime := range updates { + if _, err := db.Exec(updateChatSQL, newTime, id); err != nil { + return fmt.Errorf("updating record (%s): %s", id, err.Error()) + } + } + return nil +} diff --git a/repo/migrations/Migration023_test.go b/repo/migrations/Migration023_test.go new file mode 100644 index 0000000000..121225f745 --- /dev/null +++ b/repo/migrations/Migration023_test.go @@ -0,0 +1,158 @@ +package migrations_test + +import ( + "database/sql" + "fmt" + "io/ioutil" + "os" + "strings" + "testing" + "time" + + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" +) + +func TestMigration023(t *testing.T) { + var ( + basePath = schema.GenerateTempPath() + testRepoPath, err = schema.OpenbazaarPathTransform(basePath, true) + ) + if err != nil { + t.Fatal(err) + } + appSchema, err := schema.NewCustomSchemaManager(schema.SchemaContext{DataPath: testRepoPath, TestModeEnabled: true}) + if err != nil { + t.Fatal(err) + } + if err = appSchema.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer appSchema.DestroySchemaDirectories() + + var ( + databasePath = appSchema.DatabasePath() + schemaPath = appSchema.DataPathJoin("repover") + + schemaSQL = "pragma key = 'foobarbaz';" + CreateTableChatSQL = "create table chat (messageID text primary key not null, peerID text, subject text, message text, read integer, timestamp integer, outgoing integer);" + insertChatSQL = "insert into chat(messageID, peerID, subject, message, read, timestamp, outgoing) values(?,?,?,?,?,?,?);" + selectChatSQL = "select messageID, timestamp from chat;" + setupSQL = strings.Join([]string{ + schemaSQL, + CreateTableChatSQL, + }, " ") + ) + fmt.Println("test path:", databasePath) + db, err := sql.Open("sqlite3", databasePath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if _, err = db.Exec(setupSQL); err != nil { + t.Fatal(err) + } + + // create chat records + var examples = []migrations.Migration023_ChatMessage{ + { + MessageId: "message1", + PeerId: "peerid", + Timestamp: time.Date(2210, 1, 2, 3, 4, 5, 0, time.UTC), + }, + { + MessageId: "message2", + PeerId: "peerid", + Timestamp: time.Date(2018, 1, 2, 3, 4, 5, 0, time.UTC), + }, + { + MessageId: "message3", + PeerId: "peerid", + Timestamp: time.Date(2010, 1, 2, 3, 4, 5, 0, time.UTC), + }, + } + for _, e := range examples { + _, err = db.Exec(insertChatSQL, + e.MessageId, + e.PeerId, + e.Subject, + e.Message, + false, + e.Timestamp.Unix(), + false, + ) + if err != nil { + t.Fatal(err) + } + } + + // create schema version file + if err = ioutil.WriteFile(schemaPath, []byte("22"), os.ModePerm); err != nil { + t.Fatal(err) + } + + // execute migration up + m := migrations.Migration023{} + if err := m.Up(testRepoPath, "foobarbaz", true); err != nil { + t.Fatal(err) + } + + // assert repo version updated + if err = appSchema.VerifySchemaVersion("24"); err != nil { + t.Fatal(err) + } + + // verify change was applied properly + chatRows, err := db.Query(selectChatSQL) + if err != nil { + t.Fatal(err) + } + + for chatRows.Next() { + var ( + messageID string + timestampInt int64 + ) + if err := chatRows.Scan(&messageID, ×tampInt); err != nil { + t.Fatal(err) + } + for _, e := range examples { + if messageID == e.MessageId && timestampInt != e.Timestamp.UnixNano() { + t.Errorf("expected message (%s) to have nanosecond-based timestamp, but was not", e.MessageId) + } + } + } + chatRows.Close() + + // execute migration down + if err := m.Down(testRepoPath, "foobarbaz", true); err != nil { + t.Fatal(err) + } + + // assert repo version reverted + if err = appSchema.VerifySchemaVersion("23"); err != nil { + t.Fatal(err) + } + + // verify change was reverted properly + chatRows, err = db.Query(selectChatSQL) + if err != nil { + t.Fatal(err) + } + + for chatRows.Next() { + var ( + messageID string + timestampInt int64 + ) + if err := chatRows.Scan(&messageID, ×tampInt); err != nil { + t.Fatal(err) + } + for _, e := range examples { + if messageID == e.MessageId && timestampInt != e.Timestamp.Unix() { + t.Errorf("expected message (%s) to have second-based timestamp, but did not", e.MessageId) + } + } + } + chatRows.Close() +} diff --git a/repo/migrations/Migration024.go b/repo/migrations/Migration024.go new file mode 100644 index 0000000000..c522a5e861 --- /dev/null +++ b/repo/migrations/Migration024.go @@ -0,0 +1,186 @@ +package migrations + +import ( + "database/sql" + "fmt" + "io/ioutil" + "os" + "path" +) + +const ( + // MigrationCreateMessagesAM06MessagesCreateSQL the messages create sql + MigrationCreateMessagesAM06MessagesCreateSQL = "create table messages (messageID text primary key not null, orderID text, message_type integer, message blob, peerID text, url text, acknowledged bool, tries integer, created_at integer, updated_at integer);" + // MigrationCreateMessagesAM06CreateIndexMessagesSQLMessageID the messages index on messageID sql + MigrationCreateMessagesAM06CreateIndexMessagesSQLMessageID = "create index index_messages_messageID on messages (messageID);" + // MigrationCreateMessagesAM06CreateIndexMessagesSQLOrderIDMType the messages composite index on orderID and messageType create sql + MigrationCreateMessagesAM06CreateIndexMessagesSQLOrderIDMType = "create index index_messages_orderIDmType on messages (orderID, message_type);" + // MigrationCreateMessagesAM06CreateIndexMessagesSQLPeerIDMType the messages composite index on peerID and messageType create sql + MigrationCreateMessagesAM06CreateIndexMessagesSQLPeerIDMType = "create index index_messages_peerIDmType on messages (peerID, message_type);" + // MigrationCreateMessagesAM06MessagesDeleteSQL the messages delete sql + MigrationCreateMessagesAM06MessagesDeleteSQL = "drop table if exists messages;" + // MigrationCreateMessagesAM06DeleteIndexMessagesSQLMessageID delete the messages index on messageID sql + MigrationCreateMessagesAM06DeleteIndexMessagesSQLMessageID = "drop index if exists index_messages_messageID;" + // MigrationCreateMessagesAM06DeleteIndexMessagesSQLOrderIDMType delete the messages composite index on orderID and messageType create sql + MigrationCreateMessagesAM06DeleteIndexMessagesSQLOrderIDMType = "drop index if exists index_messages_orderIDmType;" + // MigrationCreateMessagesAM06DeleteIndexMessagesSQLPeerIDMType delete the messages composite index on peerID and messageType create sql + MigrationCreateMessagesAM06DeleteIndexMessagesSQLPeerIDMType = "drop index if exists index_messages_peerIDmType;" + // MigrationCreateMessagesAM06UpVer set the repo Up version + MigrationCreateMessagesAM06UpVer = "25" + // MigrationCreateMessagesAM06DownVer set the repo Down version + MigrationCreateMessagesAM06DownVer = "24" +) + +// MigrationCreateMessagesAM06 local migration struct +type MigrationCreateMessagesAM06 struct{} + +// Migration024 migration struct +type Migration024 struct { + MigrationCreateMessagesAM06 +} + +func createMessages(repoPath, databasePassword, rVer string, testnetEnabled bool) error { + var ( + databaseFilePath string + repoVersionFilePath = path.Join(repoPath, "repover") + ) + if testnetEnabled { + databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") + } else { + databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") + } + + db, err := sql.Open("sqlite3", databaseFilePath) + if err != nil { + return err + } + defer db.Close() + if databasePassword != "" { + p := fmt.Sprintf("pragma key = '%s';", databasePassword) + _, err := db.Exec(p) + if err != nil { + return err + } + } + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(MigrationCreateMessagesAM06MessagesCreateSQL); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if _, err = tx.Exec(MigrationCreateMessagesAM06CreateIndexMessagesSQLMessageID); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if _, err = tx.Exec(MigrationCreateMessagesAM06CreateIndexMessagesSQLOrderIDMType); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if _, err = tx.Exec(MigrationCreateMessagesAM06CreateIndexMessagesSQLPeerIDMType); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + + // Bump schema version + err = ioutil.WriteFile(repoVersionFilePath, []byte(rVer), os.ModePerm) + if err != nil { + return err + } + return nil +} + +func deleteMessages(repoPath, databasePassword, rVer string, testnetEnabled bool) error { + var ( + databaseFilePath string + repoVersionFilePath = path.Join(repoPath, "repover") + ) + if testnetEnabled { + databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") + } else { + databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") + } + + db, err := sql.Open("sqlite3", databaseFilePath) + if err != nil { + return err + } + defer db.Close() + if databasePassword != "" { + p := fmt.Sprintf("pragma key = '%s';", databasePassword) + _, err := db.Exec(p) + if err != nil { + return err + } + } + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(MigrationCreateMessagesAM06DeleteIndexMessagesSQLMessageID); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if _, err = tx.Exec(MigrationCreateMessagesAM06DeleteIndexMessagesSQLOrderIDMType); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if _, err = tx.Exec(MigrationCreateMessagesAM06DeleteIndexMessagesSQLPeerIDMType); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if _, err = tx.Exec(MigrationCreateMessagesAM06MessagesDeleteSQL); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + + // Bump schema version + err = ioutil.WriteFile(repoVersionFilePath, []byte(rVer), os.ModePerm) + if err != nil { + return err + } + return nil +} + +// Up the migration Up code +func (MigrationCreateMessagesAM06) Up(repoPath, databasePassword string, testnetEnabled bool) error { + return createMessages(repoPath, databasePassword, MigrationCreateMessagesAM06UpVer, testnetEnabled) +} + +// Down the migration Down code +func (MigrationCreateMessagesAM06) Down(repoPath, databasePassword string, testnetEnabled bool) error { + return deleteMessages(repoPath, databasePassword, MigrationCreateMessagesAM06DownVer, testnetEnabled) +} diff --git a/repo/migrations/Migration024_test.go b/repo/migrations/Migration024_test.go new file mode 100644 index 0000000000..595cb222bd --- /dev/null +++ b/repo/migrations/Migration024_test.go @@ -0,0 +1,88 @@ +package migrations_test + +import ( + "database/sql" + "io/ioutil" + "os" + "testing" + + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" +) + +func TestMigration024(t *testing.T) { + var ( + basePath = schema.GenerateTempPath() + testRepoPath, err = schema.OpenbazaarPathTransform(basePath, true) + ) + if err != nil { + t.Fatal(err) + } + appSchema, err := schema.NewCustomSchemaManager(schema.SchemaContext{DataPath: testRepoPath, TestModeEnabled: true}) + if err != nil { + t.Fatal(err) + } + if err = appSchema.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer appSchema.DestroySchemaDirectories() + + var ( + databasePath = appSchema.DatabasePath() + schemaPath = appSchema.DataPathJoin("repover") + + schemaSQL = "pragma key = 'foobarbaz';" + selectMessagesSQL = "select * from messages;" + //setupSQL = strings.Join([]string{ + // schemaSQL, + //}, " ") + ) + + // create schema version file + if err = ioutil.WriteFile(schemaPath, []byte("23"), os.ModePerm); err != nil { + t.Fatal(err) + } + + // execute migration up + m := migrations.Migration024{} + if err := m.Up(testRepoPath, "foobarbaz", true); err != nil { + t.Fatal(err) + } + + db, err := sql.Open("sqlite3", databasePath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if _, err = db.Exec(schemaSQL); err != nil { + t.Fatal(err) + } + + // assert repo version updated + if err = appSchema.VerifySchemaVersion("25"); err != nil { + t.Fatal(err) + } + + // verify change was applied properly + _, err = db.Exec(selectMessagesSQL) + if err != nil { + t.Fatal(err) + } + + // execute migration down + if err := m.Down(testRepoPath, "foobarbaz", true); err != nil { + t.Fatal(err) + } + + // assert repo version reverted + if err = appSchema.VerifySchemaVersion("24"); err != nil { + t.Fatal(err) + } + + // verify change was reverted properly + _, err = db.Exec(selectMessagesSQL) + if err == nil { + t.Fatal(err) + } + +} diff --git a/repo/migrations/Migration025.go b/repo/migrations/Migration025.go new file mode 100644 index 0000000000..61489ccbb4 --- /dev/null +++ b/repo/migrations/Migration025.go @@ -0,0 +1,78 @@ +package migrations + +import ( + "fmt" + "strings" +) + +type Migration025 struct{} + +func (Migration025) Up(repoPath, databasePassword string, testnetEnabled bool) error { + db, err := OpenDB(repoPath, databasePassword, testnetEnabled) + if err != nil { + return fmt.Errorf("opening db: %s", err.Error()) + } + + const ( + alterSalesSQL = "alter table sales rename to sales_old;" + createNewSalesSQL = "create table sales (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total integer, thumbnail text, buyerID text, buyerHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, lastDisputeTimeoutNotifiedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" + insertSalesSQL = "insert into sales select orderID, contract, state, read, timestamp, total, thumbnail, buyerID, buyerHandle, title, shippingName, shippingAddress, paymentAddr, funded, transactions, lastDisputeTimeoutNotifiedAt, coinType, paymentCoin from sales_old;" + dropSalesTableSQL = "drop table sales_old;" + ) + + migration := strings.Join([]string{ + alterSalesSQL, + createNewSalesSQL, + insertSalesSQL, + dropSalesTableSQL, + }, " ") + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(migration); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + if err := writeRepoVer(repoPath, 26); err != nil { + return fmt.Errorf("bumping repover to 26: %s", err.Error()) + } + return nil +} + +func (Migration025) Down(repoPath, databasePassword string, testnetEnabled bool) error { + db, err := OpenDB(repoPath, databasePassword, testnetEnabled) + if err != nil { + return fmt.Errorf("opening db: %s", err.Error()) + } + + const ( + alterSalesSQL = "alter table sales add needsSync integer;" + ) + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(alterSalesSQL); err != nil { + err0 := tx.Rollback() + if err0 != nil { + log.Error(err0) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + if err := writeRepoVer(repoPath, 25); err != nil { + return fmt.Errorf("dropping repover to 25: %s", err.Error()) + } + return nil +} diff --git a/repo/migrations/Migration025_test.go b/repo/migrations/Migration025_test.go new file mode 100644 index 0000000000..ec1d27114e --- /dev/null +++ b/repo/migrations/Migration025_test.go @@ -0,0 +1,68 @@ +package migrations + +import ( + "github.com/phoreproject/pm-go/schema" + "testing" +) + +func TestMigration025(t *testing.T) { + // Setup + basePath := schema.GenerateTempPath() + testRepoPath, err := schema.OpenbazaarPathTransform(basePath, true) + if err != nil { + t.Fatal(err) + } + appSchema, err := schema.NewCustomSchemaManager(schema.SchemaContext{DataPath: testRepoPath, TestModeEnabled: true}) + if err != nil { + t.Fatal(err) + } + if err = appSchema.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer appSchema.DestroySchemaDirectories() + var ( + //repoVerPath = appSchema.DataPathJoin("repover") + + column = "needsSync" + selectSQL = "select orderID from sales where " + column + "=1" + ) + + if err := appSchema.InitializeDatabase(); err != nil { + t.Fatal(err) + } + + migration := Migration025{} + if err := migration.Up(appSchema.DataPath(), "", true); err != nil { + t.Fatal(err) + } + + db, err := appSchema.OpenDatabase() + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec(selectSQL) + expectedErr := "no such column: " + column + if err == nil || err.Error() != expectedErr { + t.Errorf("Expected %s got %s", expectedErr, err) + } + + // assert repo version reverted + if err = appSchema.VerifySchemaVersion("26"); err != nil { + t.Fatal(err) + } + + if err := migration.Down(appSchema.DataPath(), "", true); err != nil { + t.Fatal(err) + } + + _, err = db.Exec(selectSQL) + if err != nil { + t.Errorf("Expected nil error got %s", err) + } + + // assert repo version reverted + if err = appSchema.VerifySchemaVersion("25"); err != nil { + t.Fatal(err) + } +} diff --git a/repo/migrations/Migration026.go b/repo/migrations/Migration026.go new file mode 100644 index 0000000000..c6b8ff39e2 --- /dev/null +++ b/repo/migrations/Migration026.go @@ -0,0 +1,76 @@ +package migrations + +import ( + "fmt" + "strings" + + "github.com/ipfs/go-ipfs/repo/fsrepo" + ds "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" + dsq "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore/query" + ipnspb "gx/ipfs/QmUwMnKKjH3JwGKNVZ3TcP37W93xzqNA4ECFFiMo6sXkkc/go-ipns/pb" + "gx/ipfs/QmddjPSGZb3ieihSseFeCfVRpZzcqczPNsD2DvarSwnjJB/gogo-protobuf/proto" +) + +var cleanIPNSMigrationNumber = 26 // should match name + +type ( + cleanIPNSRecordsFromDatastore struct{} + Migration026 struct { + cleanIPNSRecordsFromDatastore + } +) + +// Should we ever update these packages (which functionally changes their +// behavior) the migrations should be made into a no-op. +func (cleanIPNSRecordsFromDatastore) Up(repoPath, databasePassword string, testnetEnabled bool) error { + r, err := fsrepo.Open(repoPath) + if err != nil { + return err + } + defer func() { + if err := r.Close(); err != nil { + log.Errorf("closing repo: %s", err.Error()) + } + }() + + resultCh, err := r.Datastore().Query(dsq.Query{Prefix: "/ipns/"}) + if err != nil { + return err + } + defer func() { + if err := resultCh.Close(); err != nil { + log.Errorf("closing result channel: %s", err.Error()) + } + }() + + results, err := resultCh.Rest() + if err != nil { + return err + } + + log.Debugf("found %d IPNS records to cull...", len(results)) + for _, rawResult := range results { + if strings.HasPrefix(rawResult.Key, "/ipns/persistentcache") { + continue + } + rec := new(ipnspb.IpnsEntry) + if err = proto.Unmarshal(rawResult.Value, rec); err != nil { + log.Warningf("failed unmarshaling record (%s): %s", rawResult.Key, err.Error()) + if err := r.Datastore().Delete(ds.NewKey(rawResult.Key)); err != nil { + log.Errorf("failed dropping cached record (%s): %s", rawResult.Key, err.Error()) + } + } + } + + if err := writeRepoVer(repoPath, cleanIPNSMigrationNumber+1); err != nil { + return fmt.Errorf("updating repover to %d: %s", cleanIPNSMigrationNumber+1, err.Error()) + } + return nil +} + +func (cleanIPNSRecordsFromDatastore) Down(repoPath, databasePassword string, testnetEnabled bool) error { + if err := writeRepoVer(repoPath, cleanIPNSMigrationNumber); err != nil { + return fmt.Errorf("updating repover to %d: %s", cleanIPNSMigrationNumber, err.Error()) + } + return nil +} diff --git a/repo/migrations/Migration026_test.go b/repo/migrations/Migration026_test.go new file mode 100644 index 0000000000..599eee923c --- /dev/null +++ b/repo/migrations/Migration026_test.go @@ -0,0 +1,96 @@ +package migrations + +import ( + "bytes" + "testing" + + "github.com/ipfs/go-ipfs/repo/fsrepo" + "github.com/phoreproject/pm-go/schema" + + ds "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" +) + +func TestCleanIPNSRecordsMigration(t *testing.T) { + var ( + basePath = schema.GenerateTempPath() + ipnsKey = "/ipns/shoulddelete" + ipnsFalsePositiveKey = "/ipns/persistentcache/shouldNOTdelete" + otherKey = "/ipfs/shouldNOTdelete" + migration = cleanIPNSRecordsFromDatastore{} + + testRepoPath, err = schema.OpenbazaarPathTransform(basePath, true) + ) + if err != nil { + t.Fatal(err) + } + + appSchema, err := schema.NewCustomSchemaManager(schema.SchemaContext{DataPath: testRepoPath, TestModeEnabled: true}) + if err != nil { + t.Fatal(err) + } + + if err = appSchema.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer appSchema.DestroySchemaDirectories() + + if err := fsrepo.Init(appSchema.DataPath(), schema.MustDefaultConfig()); err != nil { + t.Fatal(err) + } + + r, err := fsrepo.Open(testRepoPath) + if err != nil { + t.Fatalf("opening repo: %s", err.Error()) + } + + err = r.Datastore().Put(ds.NewKey(ipnsKey), []byte("randomdata")) + if err != nil { + t.Fatal("unable to put ipns record") + } + err = r.Datastore().Put(ds.NewKey(ipnsFalsePositiveKey), []byte("randomdata")) + if err != nil { + t.Fatal("unable to put other record") + } + err = r.Datastore().Put(ds.NewKey(otherKey), []byte("randomdata")) + if err != nil { + t.Fatal("unable to put other record") + } + + // run migration up + if err := migration.Up(appSchema.DataPath(), "", true); err != nil { + t.Fatal(err) + } + + // validate state + if _, err := r.Datastore().Get(ds.NewKey(ipnsKey)); err != ds.ErrNotFound { + t.Errorf("expected the IPNS record to be removed, but was not") + } + if val, err := r.Datastore().Get(ds.NewKey(ipnsFalsePositiveKey)); err != nil { + t.Errorf("expected the false-positive record to be present, but was not") + } else { + if !bytes.Equal([]byte("randomdata"), val) { + t.Errorf("expected the false-positive record data to be intact, but was not") + } + } + if val, err := r.Datastore().Get(ds.NewKey(otherKey)); err != nil { + t.Errorf("expected the other record to be present, but was not") + } else { + if !bytes.Equal([]byte("randomdata"), val) { + t.Errorf("expected the other record data to be intact, but was not") + } + } + + if err = appSchema.VerifySchemaVersion("27"); err != nil { + t.Fatal(err) + } + + // run migration down + if err := migration.Down(appSchema.DataPath(), "", true); err != nil { + t.Fatal(err) + } + + // validate state + if err = appSchema.VerifySchemaVersion("26"); err != nil { + t.Fatal(err) + } +} diff --git a/repo/migrations/Migration027.go b/repo/migrations/Migration027.go new file mode 100644 index 0000000000..227b7c8762 --- /dev/null +++ b/repo/migrations/Migration027.go @@ -0,0 +1,97 @@ +package migrations + +import ( + "encoding/json" + "io/ioutil" + "os" + "path" + + "github.com/ipfs/go-ipfs/core/mock" + "github.com/phoreproject/pm-go/ipfs" +) + +type Migration027 struct{ UpdateListingHash } + +// UpdateListingHash will update the hashes of each listing in the listing index with +// the newest hash format. +type UpdateListingHash struct{} + +type UpdateListingHash_Price struct { + CurrencyCode string `json:"currencyCode"` + Amount uint64 `json:"amount"` + Modifier float32 `json:"modifier"` +} +type UpdateListingHash_Thumbnail struct { + Tiny string `json:"tiny"` + Small string `json:"small"` + Medium string `json:"medium"` +} + +type UpdateListingHash_ListingData struct { + Hash string `json:"hash"` + Slug string `json:"slug"` + Title string `json:"title"` + Categories []string `json:"categories"` + NSFW bool `json:"nsfw"` + ContractType string `json:"contractType"` + Description string `json:"description"` + Thumbnail UpdateListingHash_Thumbnail `json:"thumbnail"` + Price UpdateListingHash_Price `json:"price"` + ShipsTo []string `json:"shipsTo"` + FreeShipping []string `json:"freeShipping"` + Language string `json:"language"` + AverageRating float32 `json:"averageRating"` + RatingCount uint32 `json:"ratingCount"` + ModeratorIDs []string `json:"moderators"` + AcceptedCurrencies []string `json:"acceptedCurrencies"` + CoinType string `json:"coinType"` +} + +func (UpdateListingHash) Up(repoPath, databasePassword string, testnetEnabled bool) error { + listingsFilePath := path.Join(repoPath, "root", "listings.json") + + // Non-vendors might not have an listing.json and we don't want to error here if that's the case + indexExists := true + if _, err := os.Stat(listingsFilePath); os.IsNotExist(err) { + indexExists = false + } + + if indexExists { + var listingIndex []UpdateListingHash_ListingData + listingsJSON, err := ioutil.ReadFile(listingsFilePath) + if err != nil { + return err + } + if err = json.Unmarshal(listingsJSON, &listingIndex); err != nil { + return err + } + n, err := coremock.NewMockNode() + if err != nil { + return err + } + for i, listing := range listingIndex { + hash, err := ipfs.GetHashOfFile(n, path.Join(repoPath, "root", "listings", listing.Slug+".json")) + if err != nil { + return err + } + + listingIndex[i].Hash = hash + } + migratedJSON, err := json.MarshalIndent(&listingIndex, "", " ") + if err != nil { + return err + } + err = ioutil.WriteFile(listingsFilePath, migratedJSON, os.ModePerm) + if err != nil { + return err + } + } + + return writeRepoVer(repoPath, 27) +} + +func (UpdateListingHash) Down(repoPath, databasePassword string, testnetEnabled bool) error { + // Down migration is a no-op (outside of updating the version) + // We can't calculate the old style hash format anymore. + return writeRepoVer(repoPath, 26) +} diff --git a/repo/migrations/Migration027_test.go b/repo/migrations/Migration027_test.go new file mode 100644 index 0000000000..b28983a844 --- /dev/null +++ b/repo/migrations/Migration027_test.go @@ -0,0 +1,145 @@ +package migrations_test + +import ( + "encoding/json" + "io/ioutil" + "os" + "strconv" + "testing" + + "github.com/OpenBazaar/jsonpb" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test/factory" +) + +func TestUpdateListingHash(t *testing.T) { + var testRepo, err = schema.NewCustomSchemaManager(schema.SchemaContext{ + DataPath: schema.GenerateTempPath(), + TestModeEnabled: true, + }) + if err != nil { + t.Fatal(err) + } + + if err = testRepo.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer testRepo.DestroySchemaDirectories() + + var ( + repoverPath = testRepo.DataPathJoin("repover") + listingIndexPath = testRepo.DataPathJoin("root", "listings.json") + testListingSlug = "UpdateListingHash_test_listing" + testListingPath = testRepo.DataPathJoin("root", "listings", testListingSlug+".json") + + // This listing hash is generated using the default IPFS hashing algorithm as of v0.4.19 + // If the default hashing algorithm changes at any point in the future you can expect this + // test to fail and it will need to be updated to maintain the functionality of this migration. + expectedListingHash = "QmaBUK5FQcnT1qwPfLMV3L1XDpi3Ya24uVKRJhoPAoeB8m" + + listing = factory.NewListing(testListingSlug) + m = jsonpb.Marshaler{ + Indent: " ", + EmitDefaults: true, + } + ) + + f, err := os.Create(testListingPath) + if err != nil { + t.Fatal(err) + } + if err := m.Marshal(f, listing); err != nil { + t.Fatal(err) + } + + index := []*migrations.UpdateListingHash_ListingData{extractListingData26(listing)} + indexJSON, err := json.MarshalIndent(&index, "", " ") + if err != nil { + t.Fatal(err) + } + + if err := ioutil.WriteFile(listingIndexPath, indexJSON, os.ModePerm); err != nil { + t.Fatal(err) + } + + var migration migrations.UpdateListingHash + if err := migration.Up(testRepo.DataPath(), "", true); err != nil { + t.Fatal(err) + } + + var listingIndex []migrations.UpdateListingHash_ListingData + listingsJSON, err := ioutil.ReadFile(listingIndexPath) + if err != nil { + t.Fatal(err) + } + if err = json.Unmarshal(listingsJSON, &listingIndex); err != nil { + t.Fatal(err) + } + + // See comment above on expectedListingHash + if listingIndex[0].Hash != expectedListingHash { + t.Errorf("Expected listing hash %s got %s", expectedListingHash, listingIndex[0].Hash) + } + + assertCorrectRepoVer(t, repoverPath, "27") + + if err := migration.Down(testRepo.DataPath(), "", true); err != nil { + t.Fatal(err) + } + + assertCorrectRepoVer(t, repoverPath, "26") +} + +func extractListingData26(listing *pb.Listing) *migrations.UpdateListingHash_ListingData { + descriptionLength := len(listing.Item.Description) + + contains := func(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false + } + + var shipsTo []string + var freeShipping []string + for _, shippingOption := range listing.ShippingOptions { + for _, region := range shippingOption.Regions { + if !contains(shipsTo, region.String()) { + shipsTo = append(shipsTo, region.String()) + } + for _, service := range shippingOption.Services { + if service.BigPrice == "0" && !contains(freeShipping, region.String()) { + freeShipping = append(freeShipping, region.String()) + } + } + } + } + + amt, _ := strconv.ParseUint(listing.Item.BigPrice, 10, 64) + + ld := &migrations.UpdateListingHash_ListingData{ + Hash: "aabbcc", + Slug: listing.Slug, + Title: listing.Item.Title, + Categories: listing.Item.Categories, + NSFW: listing.Item.Nsfw, + ContractType: listing.Metadata.ContractType.String(), + Description: listing.Item.Description[:descriptionLength], + Thumbnail: migrations.UpdateListingHash_Thumbnail{listing.Item.Images[0].Tiny, listing.Item.Images[0].Small, listing.Item.Images[0].Medium}, + Price: migrations.UpdateListingHash_Price{ + CurrencyCode: listing.Item.PriceCurrency.Code, + Amount: amt, + Modifier: listing.Metadata.PriceModifier, + }, + ShipsTo: shipsTo, + FreeShipping: freeShipping, + Language: listing.Metadata.Language, + ModeratorIDs: listing.Moderators, + AcceptedCurrencies: listing.Metadata.AcceptedCurrencies, + } + return ld +} diff --git a/repo/migrations/Migration028.go b/repo/migrations/Migration028.go new file mode 100644 index 0000000000..875fb1436e --- /dev/null +++ b/repo/migrations/Migration028.go @@ -0,0 +1,785 @@ +package migrations + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "math/big" + "os" + "path" + "strconv" + "strings" + + crypto "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" + + "github.com/OpenBazaar/jsonpb" + "github.com/golang/protobuf/proto" + coremock "github.com/ipfs/go-ipfs/core/mock" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" +) + +type Migration028 struct{ migrateListingsToV5Schema } + +type migrateListingsToV5Schema struct{} + +type ( + MigrateListingsToV5Schema_ListingThumbnail struct { + Tiny string `json:"tiny"` + Small string `json:"small"` + Medium string `json:"medium"` + } + + MigrateListingsToV5Schema_V5CurrencyValue struct { + Amount *big.Int `json:"amount"` + Currency MigrateListingsToV5Schema_V5CurrencyDefinition `json:"currency"` + } + + MigrateListingsToV5Schema_V5CurrencyCode string + + MigrateListingsToV5Schema_V5CurrencyDefinition struct { + Code MigrateListingsToV5Schema_V5CurrencyCode `json:"code"` + Divisibility uint `json:"divisibility"` + } + + MigrateListingsToV5Schema_V5ListingIndexData struct { + Hash string `json:"hash"` + Slug string `json:"slug"` + Title string `json:"title"` + Categories []string `json:"categories"` + NSFW bool `json:"nsfw"` + ContractType string `json:"contractType"` + Description string `json:"description"` + Thumbnail MigrateListingsToV5Schema_ListingThumbnail `json:"thumbnail"` + Price *MigrateListingsToV5Schema_V5CurrencyValue `json:"price"` + Modifier float32 `json:"modifier"` + ShipsTo []string `json:"shipsTo"` + FreeShipping []string `json:"freeShipping"` + Language string `json:"language"` + AverageRating float32 `json:"averageRating"` + RatingCount uint32 `json:"ratingCount"` + ModeratorIDs []string `json:"moderators"` + AcceptedCurrencies []string `json:"acceptedCurrencies"` + CryptoCurrencyCode string `json:"coinType"` + } + + MigrateListingsToV5Schema_V4price struct { + CurrencyCode string `json:"currencyCode"` + Amount uint `json:"amount"` + Modifier float32 `json:"modifier"` + } + + MigrateListingsToV5Schema_V4ListingIndexData struct { + Hash string `json:"hash"` + Slug string `json:"slug"` + Title string `json:"title"` + Categories []string `json:"categories"` + NSFW bool `json:"nsfw"` + ContractType string `json:"contractType"` + Description string `json:"description"` + Thumbnail MigrateListingsToV5Schema_ListingThumbnail `json:"thumbnail"` + Price MigrateListingsToV5Schema_V4price `json:"price"` + ShipsTo []string `json:"shipsTo"` + FreeShipping []string `json:"freeShipping"` + Language string `json:"language"` + AverageRating float32 `json:"averageRating"` + RatingCount uint32 `json:"ratingCount"` + ModeratorIDs []string `json:"moderators"` + AcceptedCurrencies []string `json:"acceptedCurrencies"` + CryptoCurrencyCode string `json:"coinType"` + } +) + +func (c *MigrateListingsToV5Schema_V5CurrencyValue) MarshalJSON() ([]byte, error) { + var value = struct { + Amount string `json:"amount"` + Currency MigrateListingsToV5Schema_V5CurrencyDefinition `json:"currency"` + }{ + Amount: "0", + Currency: c.Currency, + } + if c.Amount != nil { + value.Amount = c.Amount.String() + } + + return json.Marshal(value) + +} + +func (c *MigrateListingsToV5Schema_V5CurrencyValue) UnmarshalJSON(b []byte) error { + var value struct { + Amount string `json:"amount"` + Currency MigrateListingsToV5Schema_V5CurrencyDefinition `json:"currency"` + } + err := json.Unmarshal(b, &value) + if err != nil { + return err + } + amt, ok := new(big.Int).SetString(value.Amount, 10) + if !ok { + return fmt.Errorf("invalid amount (%s)", value.Amount) + } + + c.Amount = amt + c.Currency = value.Currency + return err +} + +var divisibilityMap = map[string]uint{ + "BTC": 8, + "BCH": 8, + "LTC": 8, + "ZEC": 8, +} + +func parseV5intoV4(v5 MigrateListingsToV5Schema_V5ListingIndexData) MigrateListingsToV5Schema_V4ListingIndexData { + if v5.ModeratorIDs == nil { + v5.ModeratorIDs = []string{} + } + if v5.ShipsTo == nil { + v5.ShipsTo = []string{} + } + if v5.FreeShipping == nil { + v5.FreeShipping = []string{} + } + if v5.Categories == nil { + v5.Categories = []string{} + } + if v5.AcceptedCurrencies == nil { + v5.AcceptedCurrencies = []string{} + } + + return MigrateListingsToV5Schema_V4ListingIndexData{ + Hash: v5.Hash, + Slug: v5.Slug, + Title: v5.Title, + Categories: v5.Categories, + NSFW: v5.NSFW, + ContractType: v5.ContractType, + Description: v5.Description, + Thumbnail: v5.Thumbnail, + Price: MigrateListingsToV5Schema_V4price{ + CurrencyCode: string(v5.Price.Currency.Code), + Amount: uint(v5.Price.Amount.Uint64()), + Modifier: v5.Modifier, + }, + ShipsTo: v5.ShipsTo, + FreeShipping: v5.FreeShipping, + Language: v5.Language, + AverageRating: v5.AverageRating, + RatingCount: v5.RatingCount, + ModeratorIDs: v5.ModeratorIDs, + AcceptedCurrencies: v5.AcceptedCurrencies, + CryptoCurrencyCode: v5.CryptoCurrencyCode, + } +} + +func parseV4intoV5(v4 MigrateListingsToV5Schema_V4ListingIndexData) MigrateListingsToV5Schema_V5ListingIndexData { + var priceValue *MigrateListingsToV5Schema_V5CurrencyValue + divisibility, ok := divisibilityMap[strings.ToUpper(v4.Price.CurrencyCode)] + if !ok { + divisibility = 2 + } + + priceValue = &MigrateListingsToV5Schema_V5CurrencyValue{ + Amount: new(big.Int).SetInt64(int64(v4.Price.Amount)), + Currency: MigrateListingsToV5Schema_V5CurrencyDefinition{ + Code: MigrateListingsToV5Schema_V5CurrencyCode(v4.Price.CurrencyCode), + Divisibility: divisibility, + }, + } + if v4.ModeratorIDs == nil { + v4.ModeratorIDs = []string{} + } + if v4.ShipsTo == nil { + v4.ShipsTo = []string{} + } + if v4.FreeShipping == nil { + v4.FreeShipping = []string{} + } + if v4.Categories == nil { + v4.Categories = []string{} + } + if v4.AcceptedCurrencies == nil { + v4.AcceptedCurrencies = []string{} + } + + return MigrateListingsToV5Schema_V5ListingIndexData{ + Hash: v4.Hash, + Slug: v4.Slug, + Title: v4.Title, + Categories: v4.Categories, + NSFW: v4.NSFW, + ContractType: v4.ContractType, + Description: v4.Description, + Thumbnail: v4.Thumbnail, + Modifier: v4.Price.Modifier, + Price: priceValue, + ShipsTo: v4.ShipsTo, + FreeShipping: v4.FreeShipping, + Language: v4.Language, + AverageRating: v4.AverageRating, + RatingCount: v4.RatingCount, + ModeratorIDs: v4.ModeratorIDs, + AcceptedCurrencies: v4.AcceptedCurrencies, + CryptoCurrencyCode: v4.CryptoCurrencyCode, + } +} + +func (migrateListingsToV5Schema) Up(repoPath, databasePassword string, testnetEnabled bool) error { + listingsFilePath := path.Join(repoPath, "root", "listings.json") + + // Non-vendors might not have an listing.json and we don't want to error here if that's the case + indexExists := true + if _, err := os.Stat(listingsFilePath); os.IsNotExist(err) { + indexExists = false + } + + if indexExists { + // Setup signing capabilities + identityKey, err := migration027_GetIdentityKey(repoPath, databasePassword, testnetEnabled) + if err != nil { + return err + } + + sk, err := crypto.UnmarshalPrivateKey(identityKey) + if err != nil { + return err + } + + nd, err := coremock.NewMockNode() + if err != nil { + return err + } + + listingHashMap := make(map[string]string) + + m := jsonpb.Marshaler{ + Indent: " ", + } + + var listingIndex []MigrateListingsToV5Schema_V5ListingIndexData + listingsJSON, err := ioutil.ReadFile(listingsFilePath) + if err != nil { + return err + } + if err = json.Unmarshal(listingsJSON, &listingIndex); err == nil { + return writeRepoVer(repoPath, 28) + } + + var oldListingIndex []MigrateListingsToV5Schema_V4ListingIndexData + listingsJSON, err = ioutil.ReadFile(listingsFilePath) + if err != nil { + return err + } + if err = json.Unmarshal(listingsJSON, &oldListingIndex); err != nil { + return err + } + + newListingIndex := make([]MigrateListingsToV5Schema_V5ListingIndexData, len(oldListingIndex)) + for i, listing := range oldListingIndex { + newListingIndex[i] = parseV4intoV5(listing) + } + + for _, listing := range newListingIndex { + listingPath := path.Join(repoPath, "root", "listings", listing.Slug+".json") + listingBytes, err := ioutil.ReadFile(listingPath) + if err != nil { + return err + } + var signedListingJSON map[string]interface{} + if err = json.Unmarshal(listingBytes, &signedListingJSON); err != nil { + return err + } + + listingJSON, listingExists := signedListingJSON["listing"] + if !listingExists { + continue + } + listing := listingJSON.(map[string]interface{}) + + metadataJSON, metadataExists := listing["metadata"] + if !metadataExists { + continue + } + metadata := metadataJSON.(map[string]interface{}) + metadata["version"] = 5 + itemJSON, itemExists := listing["item"] + if !itemExists { + continue + } + item := itemJSON.(map[string]interface{}) + + var ( + skus []interface{} + shippingOptions []interface{} + coupons []interface{} + ) + + skusJSON := item["skus"] + if skusJSON != nil { + skus = skusJSON.([]interface{}) + } + shippingOptionsJSON := listing["shippingOptions"] + if shippingOptionsJSON != nil { + shippingOptions = shippingOptionsJSON.([]interface{}) + } + couponsJSON := listing["coupons"] + if couponsJSON != nil { + coupons = couponsJSON.([]interface{}) + } + + pricingCurrencyJSON, pricingCurrencyExists := metadata["pricingCurrency"] + if pricingCurrencyExists { + pricingCurrency := pricingCurrencyJSON.(string) + divisibility, ok := divisibilityMap[strings.ToUpper(pricingCurrency)] + if !ok { + divisibility = 2 + } + + item["priceCurrency"] = struct { + Code string `json:"code"` + Divisibility uint32 `json:"divisibility"` + }{ + Code: pricingCurrency, + Divisibility: uint32(divisibility), + } + + delete(metadata, "pricingCurrency") + } + + var modifier float64 + modifierJSON := metadata["priceModifier"] + if modifierJSON != nil { + modifier = modifierJSON.(float64) + } + + item["priceModifier"] = modifier + + delete(metadata, "priceModifier") + + priceJSON, priceExists := item["price"] + if priceExists { + price := priceJSON.(float64) + + item["bigPrice"] = strconv.Itoa(int(price)) + + delete(item, "price") + } + + for _, skuJSON := range skus { + sku := skuJSON.(map[string]interface{}) + + quantityJSON, quantityExists := sku["quantity"] + if quantityExists { + quantity := quantityJSON.(float64) + + sku["bigQuantity"] = strconv.Itoa(int(quantity)) + + delete(sku, "quantity") + } + + surchargeJSON, surchargeExists := sku["surcharge"] + if surchargeExists { + surcharge := surchargeJSON.(float64) + + sku["bigSurcharge"] = strconv.Itoa(int(surcharge)) + + delete(sku, "surcharge") + } + } + + for i, shippingOptionJSON := range shippingOptions { + so := shippingOptionJSON.(map[string]interface{}) + var services []interface{} + servicesJSON := so["services"] + if servicesJSON != nil { + services = servicesJSON.([]interface{}) + } + + for x, serviceJSON := range services { + service := serviceJSON.(map[string]interface{}) + + priceJSON := service["price"] + price, priceExists := priceJSON.(float64) + + if priceExists { + service["bigPrice"] = strconv.Itoa(int(price)) + + delete(service, "price") + } + + additionalItemPriceJSON, additionalPriceExists := service["additionalItemPrice"] + if additionalPriceExists { + additionalItemPrice := additionalItemPriceJSON.(float64) + + service["bigAdditionalItemPrice"] = strconv.Itoa(int(additionalItemPrice)) + + delete(service, "additionalItemPrice") + } + + services[x] = service + } + + so["services"] = services + shippingOptions[i] = so + } + + for _, couponJSON := range coupons { + coupon := couponJSON.(map[string]interface{}) + + priceDiscountJSON, ok := coupon["priceDiscount"] + if ok { + priceDiscount := priceDiscountJSON.(float64) + + coupon["bigPriceDiscount"] = strconv.Itoa(int(priceDiscount)) + + delete(coupon, "priceDiscount") + } + } + + out, err := json.MarshalIndent(signedListingJSON, "", " ") + if err != nil { + return err + } + + sl := new(pb.SignedListing) + if err := jsonpb.UnmarshalString(string(out), sl); err != nil { + return err + } + + ser, err := proto.Marshal(sl.Listing) + if err != nil { + return err + } + + sig, err := sk.Sign(ser) + if err != nil { + return err + } + + sl.Signature = sig + + signedOut, err := m.MarshalToString(sl) + if err != nil { + return err + } + + err = ioutil.WriteFile(listingPath, []byte(signedOut), os.ModePerm) + if err != nil { + return err + } + + hash, err := ipfs.GetHashOfFile(nd, listingPath) + if err != nil { + return err + } + + listingHashMap[sl.Listing.Slug] = hash + } + + for i, listing := range newListingIndex { + newListingIndex[i].Hash = listingHashMap[listing.Slug] + } + + migratedJSON, err := json.MarshalIndent(&newListingIndex, "", " ") + if err != nil { + return err + } + + err = ioutil.WriteFile(listingsFilePath, migratedJSON, os.ModePerm) + if err != nil { + return err + } + } + + return writeRepoVer(repoPath, 28) +} + +func (migrateListingsToV5Schema) Down(repoPath, databasePassword string, testnetEnabled bool) error { + listingsFilePath := path.Join(repoPath, "root", "listings.json") + + // Non-vendors might not have an listing.json and we don't want to error here if that's the case + indexExists := true + if _, err := os.Stat(listingsFilePath); os.IsNotExist(err) { + indexExists = false + } + + if indexExists { + // Setup signing capabilities + identityKey, err := migration027_GetIdentityKey(repoPath, databasePassword, testnetEnabled) + if err != nil { + return err + } + + sk, err := crypto.UnmarshalPrivateKey(identityKey) + if err != nil { + return err + } + + nd, err := coremock.NewMockNode() + if err != nil { + return err + } + + listingHashMap := make(map[string]string) + + m := jsonpb.Marshaler{ + Indent: " ", + } + + var oldListingIndex []MigrateListingsToV5Schema_V5ListingIndexData + listingsJSON, err := ioutil.ReadFile(listingsFilePath) + if err != nil { + return err + } + if err = json.Unmarshal(listingsJSON, &oldListingIndex); err != nil { + return err + } + + newListingIndex := make([]MigrateListingsToV5Schema_V4ListingIndexData, len(oldListingIndex)) + for i, listing := range oldListingIndex { + newListingIndex[i] = parseV5intoV4(listing) + } + + for _, listing := range newListingIndex { + listingPath := path.Join(repoPath, "root", "listings", listing.Slug+".json") + listingBytes, err := ioutil.ReadFile(listingPath) + if err != nil { + return err + } + var signedListingJSON map[string]interface{} + if err = json.Unmarshal(listingBytes, &signedListingJSON); err != nil { + return err + } + + listingJSON, listingExists := signedListingJSON["listing"] + if !listingExists { + continue + } + listing := listingJSON.(map[string]interface{}) + + metadataJSON, metadataExists := listing["metadata"] + if !metadataExists { + continue + } + metadata := metadataJSON.(map[string]interface{}) + metadata["version"] = 4 + itemJSON, itemExists := listing["item"] + if !itemExists { + continue + } + item := itemJSON.(map[string]interface{}) + + var ( + skus []interface{} + shippingOptions []interface{} + coupons []interface{} + ) + + skusJSON := item["skus"] + if skusJSON != nil { + skus = skusJSON.([]interface{}) + } + shippingOptionsJSON := listing["shippingOptions"] + if shippingOptionsJSON != nil { + shippingOptions = shippingOptionsJSON.([]interface{}) + } + couponsJSON := listing["coupons"] + if couponsJSON != nil { + coupons = couponsJSON.([]interface{}) + } + + pricingCurrencyJSON, pricingCurrencyExists := item["priceCurrency"] + if pricingCurrencyExists { + pricingCurrency := pricingCurrencyJSON.(map[string]interface{}) + + priceCurrencyCodeJSON, currencyCodeExists := pricingCurrency["code"] + if currencyCodeExists { + priceCurrencyCode := priceCurrencyCodeJSON.(string) + + metadata["pricingCurrency"] = priceCurrencyCode + + delete(item, "priceCurrency") + } + } + + var modifier float64 + modifierJSON := item["priceModifier"] + if modifierJSON != nil { + modifier = modifierJSON.(float64) + } + + metadata["priceModifier"] = modifier + + delete(item, "priceModifier") + + priceJSON, priceExists := item["bigPrice"] + if priceExists { + price := priceJSON.(string) + + p, ok := new(big.Int).SetString(price, 10) + if ok { + item["price"] = p.Uint64() + } + delete(item, "bigPrice") + } + + for _, skuJSON := range skus { + sku := skuJSON.(map[string]interface{}) + quantityJSON, quantityExists := sku["bigQuantity"] + if quantityExists { + quantity := quantityJSON.(string) + + p, ok := new(big.Int).SetString(quantity, 10) + if ok { + sku["quantity"] = p.Uint64() + } + + delete(sku, "bigQuantity") + } + + surchargeJSON, ok := sku["bigSurcharge"] + if ok { + surcharge := surchargeJSON.(string) + + s, ok := new(big.Int).SetString(surcharge, 10) + if ok { + sku["surcharge"] = s.Uint64() + } + + delete(sku, "bigSurcharge") + } + } + + for i, shippingOptionJSON := range shippingOptions { + so := shippingOptionJSON.(map[string]interface{}) + var services []interface{} + servicesJSON := so["services"] + if servicesJSON != nil { + services = servicesJSON.([]interface{}) + } + + for x, serviceJSON := range services { + service := serviceJSON.(map[string]interface{}) + + priceJSON, priceExists := service["bigPrice"] + if priceExists { + price := priceJSON.(string) + + p, ok := new(big.Int).SetString(price, 10) + if ok { + service["price"] = p.Uint64() + } + + delete(service, "bigPrice") + } + + additionalItemPriceJSON, additionalPriceExists := service["bigAdditionalItemPrice"] + if additionalPriceExists { + additionalItemPrice := additionalItemPriceJSON.(string) + + a, ok := new(big.Int).SetString(additionalItemPrice, 10) + if ok { + service["additionalItemPrice"] = a.Uint64() + } + + delete(service, "bigAdditionalItemPrice") + } + + services[x] = service + } + + shippingOptions[i] = so + } + + for _, couponJSON := range coupons { + coupon := couponJSON.(map[string]interface{}) + + priceDiscountJSON, priceDiscountExists := coupon["bigPriceDiscount"] + if priceDiscountExists { + priceDiscount := priceDiscountJSON.(string) + + a, ok := new(big.Int).SetString(priceDiscount, 10) + if ok { + coupon["priceDiscount"] = a.Uint64() + } + + delete(coupon, "bigPriceDiscount") + } + } + + out, err := json.MarshalIndent(signedListingJSON, "", " ") + if err != nil { + return err + } + + sl := new(pb.SignedListing) + if err := jsonpb.UnmarshalString(string(out), sl); err != nil { + return err + } + + ser, err := proto.Marshal(sl.Listing) + if err != nil { + return err + } + + sig, err := sk.Sign(ser) + if err != nil { + return err + } + + sl.Signature = sig + + signedOut, err := m.MarshalToString(sl) + if err != nil { + return err + } + + err = ioutil.WriteFile(listingPath, []byte(signedOut), os.ModePerm) + if err != nil { + return err + } + + hash, err := ipfs.GetHashOfFile(nd, listingPath) + if err != nil { + return err + } + + listingHashMap[sl.Listing.Slug] = hash + } + + for i, listing := range newListingIndex { + newListingIndex[i].Hash = listingHashMap[listing.Slug] + } + + migratedJSON, err := json.MarshalIndent(&newListingIndex, "", " ") + if err != nil { + return err + } + + err = ioutil.WriteFile(listingsFilePath, migratedJSON, os.ModePerm) + if err != nil { + return err + } + } + + return writeRepoVer(repoPath, 27) +} + +func migration027_GetIdentityKey(repoPath, databasePassword string, testnetEnabled bool) ([]byte, error) { + db, err := OpenDB(repoPath, databasePassword, testnetEnabled) + if err != nil { + return nil, err + } + defer db.Close() + + var identityKey []byte + err = db. + QueryRow("select value from config where key=?", "identityKey"). + Scan(&identityKey) + if err != nil { + return nil, err + } + return identityKey, nil +} diff --git a/repo/migrations/Migration028_test.go b/repo/migrations/Migration028_test.go new file mode 100644 index 0000000000..20de8c5d21 --- /dev/null +++ b/repo/migrations/Migration028_test.go @@ -0,0 +1,543 @@ +package migrations_test + +import ( + "encoding/base64" + "encoding/json" + crypto "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" + "io/ioutil" + "os" + "strconv" + "testing" + + "github.com/OpenBazaar/jsonpb" + "github.com/golang/protobuf/proto" + coremock "github.com/ipfs/go-ipfs/core/mock" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" + "github.com/phoreproject/pm-go/test/factory" +) + +const ( + testMigrateListingsToV5Schema_IdentityPrivateKeyBase64 = "CAESYHwrVuRp5s2u0w5ykibsR77aHWBmvpcaDq+vU9pv8lOqae31NJYJbdDsOlxVRqQZS/eDfssdd7N/rJmoVbQvPytp7fU0lglt0Ow6XFVGpBlL94N+yx13s3+smahVtC8/Kw==" +) + +var ( + preMigrateListingsToV5Schema_ListingJSON = `{ + "listing": { + "slug": "migrateListingsToV5Schema_test_listing", + "metadata": { + "version": 4, + "contractType": "PHYSICAL_GOOD", + "format": "FIXED_PRICE", + "pricingCurrency": "BTC", + "priceModifier": 1, + "shippingFromCountryCode": "NA" + }, + "item": { + "price": 100, + "skus": [ + { + "surcharge": 9, + "quantity": 10 + } + ] + }, + "shippingOptions": [ + { + "type": "LOCAL_PICKUP", + "services": [ + { + "price": 10, + "additionalItemPrice": 5 + } + ] + } + ], + "coupons": [ + { + "priceDiscount": 10 + } + ] + }, + "signature": "hPwbbj3zEPf5hVnrXMvPpZBCzZ+brkyI5tGV/0k28YFvzATgvk/YXqJE8CsoYYXZsBkCfrho5NU2B/+MCxebDA==" +}` + + preMigrateListingsToV5Schema_CryptoListingJSON = `{ + "listing": { + "slug": "migrateListingsToV5Schema_test_crypto_listing", + "metadata": { + "version": 4, + "contractType": "CRYPTOCURRENCY", + "format": "MARKET_PRICE", + "coinType": "BAT", + "coinDivisibility": 8, + "priceModifier": 50, + "shippingFromCountryCode": "NA" + }, + "item": { + "skus": [ + { + "quantity": 10 + } + ] + } + }, + "signature": "9Sy3dD9Z008NSJZZI2217mceI4kd5dEDWpUg+AWZ9wFguD/yowgd2wftPrLp/2sAfzYuvBPAP8ngmXIEYVCFAw==" +}` + + postMigrateListingsToV5Schema_ListingJSON = `{ + "listing": { + "slug": "migrateListingsToV5Schema_test_listing", + "metadata": { + "version": 5, + "contractType": "PHYSICAL_GOOD", + "format": "FIXED_PRICE", + "shippingFromCountryCode": "NA" + }, + "item": { + "skus": [ + { + "bigSurcharge": "9", + "bigQuantity": "10" + } + ], + "priceModifier": 1, + "bigPrice": "100", + "priceCurrency": { + "code": "BTC", + "divisibility": 8 + } + }, + "shippingOptions": [ + { + "type": "LOCAL_PICKUP", + "services": [ + { + "bigPrice": "10", + "bigAdditionalItemPrice": "5" + } + ] + } + ], + "coupons": [ + { + "bigPriceDiscount": "10" + } + ] + }, + "signature": "kRmdBCJ+fRiBcKeac/ue6FI1KKzPboTQYZc6rxQayo6kWzD8OJIK/mJeLBNSARlxvbANMtodFt7zrnOewi0xBQ==" +}` + + postMigrateListingsToV5Schema_CryptoListingJSON = `{ + "listing": { + "slug": "migrateListingsToV5Schema_test_crypto_listing", + "metadata": { + "version": 5, + "contractType": "CRYPTOCURRENCY", + "format": "MARKET_PRICE", + "coinType": "BAT", + "coinDivisibility": 8, + "shippingFromCountryCode": "NA" + }, + "item": { + "skus": [ + { + "bigQuantity": "10" + } + ], + "priceModifier": 50 + } + }, + "signature": "+hIQOWSLs9PWybo6dYHcMroOlz6bb9VK1hKJ/sUl5mAfdtfoeKF+Fa2lWHgqmGwHlorYDLHKGFgZHs6qRXvMBQ==" +}` +) + +func TestMigrateListingsToV5Schema(t *testing.T) { + var testRepo, err = schema.NewCustomSchemaManager(schema.SchemaContext{ + DataPath: schema.GenerateTempPath(), + TestModeEnabled: true, + }) + if err != nil { + t.Fatal(err) + } + + if err = testRepo.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + if err := testRepo.InitializeDatabase(); err != nil { + t.Fatal(err) + } + defer testRepo.DestroySchemaDirectories() + + var ( + repoverPath = testRepo.DataPathJoin("repover") + listingIndexPath = testRepo.DataPathJoin("root", "listings.json") + testListingSlug = "migrateListingsToV5Schema_test_listing" + testCryptoListingSlug = "migrateListingsToV5Schema_test_crypto_listing" + testListingPath = testRepo.DataPathJoin("root", "listings", testListingSlug+".json") + testCryptoListingPath = testRepo.DataPathJoin("root", "listings", testCryptoListingSlug+".json") + + listing = factory.NewListing(testListingSlug) + cryptoListing = factory.NewListing(testCryptoListingSlug) + ) + + db, err := migrations.OpenDB(testRepo.DataPath(), "", true) + if err != nil { + t.Fatal(err) + } + + identityKey, err := base64.StdEncoding.DecodeString(testMigrateListingsToV5Schema_IdentityPrivateKeyBase64) + if err != nil { + t.Fatal(err) + } + + sk, err := crypto.UnmarshalPrivateKey(identityKey) + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("INSERT INTO config(key,value) VALUES('identityKey', ?)", identityKey) + if err != nil { + t.Fatal(err) + } + + f, err := os.Create(testListingPath) + if err != nil { + t.Fatal(err) + } + if _, err := f.Write([]byte(preMigrateListingsToV5Schema_ListingJSON)); err != nil { + t.Fatal(err) + } + + f2, err := os.Create(testCryptoListingPath) + if err != nil { + t.Fatal(err) + } + if _, err := f2.Write([]byte(preMigrateListingsToV5Schema_CryptoListingJSON)); err != nil { + t.Fatal(err) + } + + index := []*migrations.MigrateListingsToV5Schema_V4ListingIndexData{extractListingData27(listing), extractListingData27(cryptoListing)} + indexJSON, err := json.MarshalIndent(&index, "", " ") + if err != nil { + t.Fatal(err) + } + + if err := ioutil.WriteFile(listingIndexPath, indexJSON, os.ModePerm); err != nil { + t.Fatal(err) + } + + var migration migrations.Migration028 + if err := migration.Up(testRepo.DataPath(), "", true); err != nil { + t.Fatal(err) + } + + upMigratedListing, err := ioutil.ReadFile(testListingPath) + if err != nil { + t.Fatal(err) + } + + upMigratedCryptoListing, err := ioutil.ReadFile(testCryptoListingPath) + if err != nil { + t.Fatal(err) + } + + if string(upMigratedListing) != postMigrateListingsToV5Schema_ListingJSON { + t.Log(string(upMigratedListing)) + t.Log(postMigrateListingsToV5Schema_ListingJSON) + t.Error("Failed to migrate listing up") + } + + if string(upMigratedCryptoListing) != postMigrateListingsToV5Schema_CryptoListingJSON { + t.Log(string(upMigratedCryptoListing)) + t.Log(postMigrateListingsToV5Schema_CryptoListingJSON) + t.Error("Failed to migrate crypto listing up") + } + + sl := new(pb.SignedListing) + if err := jsonpb.UnmarshalString(string(upMigratedListing), sl); err != nil { + t.Fatal(err) + } + + ser, err := proto.Marshal(sl.Listing) + if err != nil { + t.Fatal(err) + } + + valid, err := sk.GetPublic().Verify(ser, sl.Signature) + if err != nil { + t.Fatal(err) + } + + if !valid { + t.Errorf("Failed to validate up migrated listing signature") + } + + sl2 := new(pb.SignedListing) + if err := jsonpb.UnmarshalString(string(upMigratedCryptoListing), sl2); err != nil { + t.Fatal(err) + } + + ser2, err := proto.Marshal(sl2.Listing) + if err != nil { + t.Fatal(err) + } + + valid2, err := sk.GetPublic().Verify(ser2, sl2.Signature) + if err != nil { + t.Fatal(err) + } + + if !valid2 { + t.Errorf("Failed to validate up migrated crypto listing signature") + } + + nd, err := coremock.NewMockNode() + if err != nil { + t.Fatal(err) + } + + listingHash, err := ipfs.GetHashOfFile(nd, testListingPath) + if err != nil { + t.Fatal(err) + } + + listingHash2, err := ipfs.GetHashOfFile(nd, testCryptoListingPath) + if err != nil { + t.Fatal(err) + } + + var listingIndex []migrations.MigrateListingsToV5Schema_V5ListingIndexData + listingsJSON, err := ioutil.ReadFile(listingIndexPath) + if err != nil { + t.Fatal(err) + } + if err = json.Unmarshal(listingsJSON, &listingIndex); err != nil { + t.Fatal(err) + } + + for _, l := range listingIndex { + if l.ModeratorIDs == nil { + t.Errorf("ModeratorIDs is null") + } + if l.ShipsTo == nil { + t.Errorf("ShipsTo is null") + } + if l.FreeShipping == nil { + t.Errorf("FreeShipping is null") + } + if l.Categories == nil { + t.Errorf("Categories is null") + } + if l.AcceptedCurrencies == nil { + t.Errorf("AcceptedCurrencies is null") + } + } + + if listingIndex[0].Price.Amount.String() != strconv.Itoa(int(index[0].Price.Amount)) { + t.Errorf("Incorrect price set") + } + + if listingIndex[0].Hash != listingHash { + t.Errorf("Incorrect hash set") + } + + if string(listingIndex[0].Price.Currency.Code) != index[0].Price.CurrencyCode { + t.Errorf("Incorrect currency code set") + } + + if listingIndex[1].Price.Amount.String() != strconv.Itoa(int(index[1].Price.Amount)) { + t.Errorf("Incorrect price set") + } + + if listingIndex[1].Hash != listingHash2 { + t.Errorf("Incorrect hash set") + } + + if string(listingIndex[1].Price.Currency.Code) != index[1].Price.CurrencyCode { + t.Errorf("Incorrect currency code set") + } + + assertCorrectRepoVer(t, repoverPath, "28") + + if err := migration.Down(testRepo.DataPath(), "", true); err != nil { + t.Fatal(err) + } + + downMigratedListing, err := ioutil.ReadFile(testListingPath) + if err != nil { + t.Fatal(err) + } + + downMigratedCryptoListing, err := ioutil.ReadFile(testCryptoListingPath) + if err != nil { + t.Fatal(err) + } + + if string(downMigratedListing) != preMigrateListingsToV5Schema_ListingJSON { + t.Log(string(downMigratedListing)) + t.Log(preMigrateListingsToV5Schema_ListingJSON) + t.Error("Failed to migrate listing down") + } + + if string(downMigratedCryptoListing) != preMigrateListingsToV5Schema_CryptoListingJSON { + t.Log(string(downMigratedCryptoListing)) + t.Log(preMigrateListingsToV5Schema_CryptoListingJSON) + t.Error("Failed to migrate crypto listing down") + } + + sl = new(pb.SignedListing) + if err := jsonpb.UnmarshalString(string(downMigratedListing), sl); err != nil { + t.Fatal(err) + } + + ser, err = proto.Marshal(sl.Listing) + if err != nil { + t.Fatal(err) + } + + valid, err = sk.GetPublic().Verify(ser, sl.Signature) + if err != nil { + t.Fatal(err) + } + + if !valid { + t.Errorf("Failed to validate down migrated listing signature") + } + + sl2 = new(pb.SignedListing) + if err := jsonpb.UnmarshalString(string(downMigratedCryptoListing), sl2); err != nil { + t.Fatal(err) + } + + ser, err = proto.Marshal(sl.Listing) + if err != nil { + t.Fatal(err) + } + + valid, err = sk.GetPublic().Verify(ser, sl.Signature) + if err != nil { + t.Fatal(err) + } + + if !valid { + t.Errorf("Failed to validate down migrated listing signature") + } + + listingHash, err = ipfs.GetHashOfFile(nd, testListingPath) + if err != nil { + t.Fatal(err) + } + + listingHash2, err = ipfs.GetHashOfFile(nd, testCryptoListingPath) + if err != nil { + t.Fatal(err) + } + + var listingIndex2 []migrations.MigrateListingsToV5Schema_V4ListingIndexData + listingsJSON, err = ioutil.ReadFile(listingIndexPath) + if err != nil { + t.Fatal(err) + } + if err = json.Unmarshal(listingsJSON, &listingIndex2); err != nil { + t.Fatal(err) + } + + for _, l := range listingIndex2 { + if l.ModeratorIDs == nil { + t.Errorf("ModeratorIDs is null") + } + if l.ShipsTo == nil { + t.Errorf("ShipsTo is null") + } + if l.FreeShipping == nil { + t.Errorf("FreeShipping is null") + } + if l.Categories == nil { + t.Errorf("Categories is null") + } + if l.AcceptedCurrencies == nil { + t.Errorf("AcceptedCurrencies is null") + } + } + + if listingIndex[0].Price.Amount.String() != strconv.Itoa(int(listingIndex2[0].Price.Amount)) { + t.Errorf("Incorrect price set") + } + + if listingIndex2[0].Hash != listingHash { + t.Errorf("Incorrect hash set") + } + + if string(listingIndex[0].Price.Currency.Code) != listingIndex2[0].Price.CurrencyCode { + t.Errorf("Incorrect currency code set") + } + + if listingIndex[1].Price.Amount.String() != strconv.Itoa(int(listingIndex2[1].Price.Amount)) { + t.Errorf("Incorrect price set") + } + + if listingIndex2[1].Hash != listingHash2 { + t.Errorf("Incorrect hash set") + } + + if string(listingIndex[1].Price.Currency.Code) != listingIndex2[1].Price.CurrencyCode { + t.Errorf("Incorrect currency code set") + } + + assertCorrectRepoVer(t, repoverPath, "27") +} + +func extractListingData27(listing *pb.Listing) *migrations.MigrateListingsToV5Schema_V4ListingIndexData { + descriptionLength := len(listing.Item.Description) + + contains := func(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false + } + + var shipsTo []string + var freeShipping []string + for _, shippingOption := range listing.ShippingOptions { + for _, region := range shippingOption.Regions { + if !contains(shipsTo, region.String()) { + shipsTo = append(shipsTo, region.String()) + } + for _, service := range shippingOption.Services { + if service.BigPrice == "0" && !contains(freeShipping, region.String()) { + freeShipping = append(freeShipping, region.String()) + } + } + } + } + + amt, _ := strconv.ParseUint(listing.Item.BigPrice, 10, 64) + + ld := &migrations.MigrateListingsToV5Schema_V4ListingIndexData{ + Hash: "aabbcc", + Slug: listing.Slug, + Title: listing.Item.Title, + Categories: listing.Item.Categories, + NSFW: listing.Item.Nsfw, + ContractType: listing.Metadata.ContractType.String(), + Description: listing.Item.Description[:descriptionLength], + Thumbnail: migrations.MigrateListingsToV5Schema_ListingThumbnail{listing.Item.Images[0].Tiny, listing.Item.Images[0].Small, listing.Item.Images[0].Medium}, + Price: migrations.MigrateListingsToV5Schema_V4price{ + CurrencyCode: listing.Item.PriceCurrency.Code, + Amount: uint(amt), + Modifier: listing.Metadata.PriceModifier, + }, + ShipsTo: shipsTo, + FreeShipping: freeShipping, + Language: listing.Metadata.Language, + ModeratorIDs: listing.Moderators, + AcceptedCurrencies: listing.Metadata.AcceptedCurrencies, + } + return ld +} diff --git a/repo/migrations/Migration029.go b/repo/migrations/Migration029.go new file mode 100644 index 0000000000..7f52b962af --- /dev/null +++ b/repo/migrations/Migration029.go @@ -0,0 +1,155 @@ +package migrations + +import ( + "database/sql" + "fmt" + "os" + "path" + "strings" + + _ "github.com/mutecomm/go-sqlcipher" +) + +var ( + AM02_up_create_sales = "create table sales (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total text, thumbnail text, buyerID text, buyerHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, lastDisputeTimeoutNotifiedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" + AM02_down_create_sales = "create table sales (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total integer, thumbnail text, buyerID text, buyerHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, lastDisputeTimeoutNotifiedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" + AM02_temp_sales = "ALTER TABLE sales RENAME TO temp_sales;" + AM02_insert_sales = "INSERT INTO sales SELECT orderID, contract, state, read, timestamp, total, thumbnail, buyerID, buyerHandle, title, shippingName, shippingAddress, paymentAddr, funded, transactions, lastDisputeTimeoutNotifiedAt, coinType, paymentCoin FROM temp_sales;" + AM02_drop_temp_sales = "DROP TABLE temp_sales;" + + AM02_up_update_purchases = "update purchases set lastDisputeExpiryNotifiedAt = 0 where lastDisputeExpiryNotifiedAt is NULL;" + AM02_up_create_purchases = "create table purchases (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total text, thumbnail text, vendorID text, vendorHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, lastDisputeTimeoutNotifiedAt integer not null default 0, lastDisputeExpiryNotifiedAt integer not null default 0, disputedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" + AM02_down_create_purchases = "create table purchases (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total integer, thumbnail text, vendorID text, vendorHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, lastDisputeTimeoutNotifiedAt integer not null default 0, lastDisputeExpiryNotifiedAt integer not null default 0, disputedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" + AM02_temp_purchases = "ALTER TABLE purchases RENAME TO temp_purchases;" + AM02_insert_purchases = "INSERT INTO purchases SELECT orderID, contract, state, read, timestamp, total, thumbnail, vendorID, vendorHandle, title, shippingName, shippingAddress, paymentAddr, funded, transactions, lastDisputeTimeoutNotifiedAt, lastDisputeExpiryNotifiedAt, disputedAt, coinType, paymentCoin FROM temp_purchases;" + AM02_drop_temp_purchases = "DROP TABLE temp_purchases;" + + AM02_up_create_inventory = "create table inventory (invID text primary key not null, slug text, variantIndex integer, count text);" + AM02_down_create_inventory = "create table inventory (invID text primary key not null, slug text, variantIndex integer, count integer);" + AM02_temp_inventory = "ALTER TABLE inventory RENAME TO temp_inventory;" + AM02_insert_inventory = "INSERT INTO inventory SELECT invID, slug, variantIndex, count FROM temp_inventory;" + AM02_drop_temp_inventory = "DROP TABLE temp_inventory;" +) + +type Migration029 struct{ AM02 } + +type AM02 struct{} + +var AM02UpVer = "30" +var AM02DownVer = "29" + +func (AM02) Up(repoPath string, dbPassword string, testnet bool) error { + var dbPath string + if testnet { + dbPath = path.Join(repoPath, "datastore", "testnet.db") + } else { + dbPath = path.Join(repoPath, "datastore", "mainnet.db") + } + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return err + } + if dbPassword != "" { + p := "pragma key='" + dbPassword + "';" + if _, err := db.Exec(p); err != nil { + return err + } + } + + upSequence := strings.Join([]string{ + AM02_up_update_purchases, + AM02_temp_sales, + AM02_up_create_sales, + AM02_insert_sales, + AM02_drop_temp_sales, + AM02_temp_purchases, + AM02_up_create_purchases, + AM02_insert_purchases, + AM02_drop_temp_purchases, + AM02_temp_inventory, + AM02_up_create_inventory, + AM02_insert_inventory, + AM02_drop_temp_inventory, + }, " ") + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(upSequence); err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("failed rollback: (%s) due to (%s)", rErr.Error(), err.Error()) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + f1, err := os.Create(path.Join(repoPath, "repover")) + if err != nil { + return err + } + _, err = f1.Write([]byte(AM02UpVer)) + if err != nil { + return err + } + f1.Close() + return nil +} + +func (AM02) Down(repoPath string, dbPassword string, testnet bool) error { + var dbPath string + if testnet { + dbPath = path.Join(repoPath, "datastore", "testnet.db") + } else { + dbPath = path.Join(repoPath, "datastore", "mainnet.db") + } + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return err + } + if dbPassword != "" { + p := "pragma key='" + dbPassword + "';" + if _, err := db.Exec(p); err != nil { + return err + } + } + downSequence := strings.Join([]string{ + AM02_temp_sales, + AM02_down_create_sales, + AM02_insert_sales, + AM02_drop_temp_sales, + AM02_temp_purchases, + AM02_down_create_purchases, + AM02_insert_purchases, + AM02_drop_temp_purchases, + AM02_temp_inventory, + AM02_down_create_inventory, + AM02_insert_inventory, + AM02_drop_temp_inventory, + }, " ") + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(downSequence); err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("failed rollback: (%s) due to (%s)", rErr.Error(), err.Error()) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + f1, err := os.Create(path.Join(repoPath, "repover")) + if err != nil { + return err + } + _, err = f1.Write([]byte(AM02DownVer)) + if err != nil { + return err + } + f1.Close() + return nil +} diff --git a/repo/migrations/Migration029_test.go b/repo/migrations/Migration029_test.go new file mode 100644 index 0000000000..b13aee2726 --- /dev/null +++ b/repo/migrations/Migration029_test.go @@ -0,0 +1,141 @@ +package migrations_test + +import ( + "database/sql" + "io/ioutil" + "testing" + + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" +) + +var stmt = `PRAGMA key = 'letmein'; + create table sales (orderID text primary key not null, + contract blob, state integer, read integer, + timestamp integer, total integer, thumbnail text, + buyerID text, buyerHandle text, title text, + shippingName text, shippingAddress text, + paymentAddr text, funded integer, transactions blob, + needsSync integer, lastDisputeTimeoutNotifiedAt integer not null default 0, + coinType not null default '', paymentCoin not null default ''); + create table purchases (orderID text primary key not null, + contract blob, state integer, read integer, + timestamp integer, total integer, thumbnail text, + vendorID text, vendorHandle text, title text, + shippingName text, shippingAddress text, paymentAddr text, + funded integer, transactions blob, + lastDisputeTimeoutNotifiedAt integer default 0, + lastDisputeExpiryNotifiedAt integer default 0, + disputedAt integer not null default 0, coinType not null default '', + paymentCoin not null default ''); + create table inventory (invID text primary key not null, slug text, variantIndex integer, count integer);` + +func TestMigration029(t *testing.T) { + basePath := schema.GenerateTempPath() + appSchema, err := schema.NewCustomSchemaManager(schema.SchemaContext{DataPath: basePath, TestModeEnabled: true}) + if err != nil { + t.Fatal(err) + } + if err = appSchema.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer appSchema.DestroySchemaDirectories() + + var dbPath = appSchema.DataPathJoin("datastore", "mainnet.db") + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + t.Fatal(err) + } + if _, err := db.Exec(stmt); err != nil { + t.Fatal(err) + } + if _, err := db.Exec("INSERT INTO sales (orderID, total) values (?,?)", "asdf", 3); err != nil { + t.Fatal(err) + } + if _, err := db.Exec("INSERT INTO purchases (orderID, total, lastDisputeExpiryNotifiedAt) values (?,?, NULL)", "asdf", 3); err != nil { + t.Fatal(err) + } + if _, err := db.Exec("INSERT INTO inventory (invID, count) values (?,?)", "asdf", "3"); err != nil { + t.Fatal(err) + } + var m migrations.Migration029 + if err := m.Up(basePath, "letmein", false); err != nil { + t.Fatal(err) + } + + var ( + orderID string + total string + total1 int + invID string + count string + count1 int + ) + + r := db.QueryRow("select orderID, total from sales where orderID=?", "asdf") + if err := r.Scan(&orderID, &total); err != nil { + t.Error(err) + } + if total != "3" { + t.Errorf("expected total to be 3, but was %s", total) + } + r = db.QueryRow("select orderID, total from purchases where orderID=?", "asdf") + if err := r.Scan(&orderID, &total); err != nil { + t.Error(err) + } + if total != "3" { + t.Errorf("expected total to be 3, but was %s", total) + } + r = db.QueryRow("select invID, count from inventory where invID=?", "asdf") + if err := r.Scan(&invID, &count); err != nil { + t.Error(err) + } + if count != "3" { + t.Errorf("expected count to be 3, but was %s", total) + } + + repoVer, err := ioutil.ReadFile(appSchema.DataPathJoin("repover")) + if err != nil { + t.Error(err) + } + if string(repoVer) != "30" { + t.Error("Failed to write new repo version") + } + + err = m.Down(basePath, "letmein", false) + if err != nil { + t.Fatal(err) + } + + r = db.QueryRow("select orderID, total from sales where orderID=?", "asdf") + if err := r.Scan(&orderID, &total1); err != nil { + t.Error(err) + } + if total1 != 3 { + t.Errorf("expected total to be 3, but was %d", total1) + } + + r = db.QueryRow("select orderID, total from purchases where orderID=?", "asdf") + if err := r.Scan(&orderID, &total1); err != nil { + t.Error(err) + } + if total1 != 3 { + t.Errorf("expected total to be 3, but was %d", total1) + } + + r = db.QueryRow("select invID, count from inventory where invID=?", "asdf") + if err := r.Scan(&invID, &count1); err != nil { + t.Error(err) + } + if count1 != 3 { + t.Errorf("expected count to be 3, but was %d", total1) + } + + repoVer, err = ioutil.ReadFile(appSchema.DataPathJoin("repover")) + if err != nil { + t.Error(err) + } + if string(repoVer) != "29" { + t.Error("Failed to write old repo version") + } +} diff --git a/repo/migrations/Migration030.go b/repo/migrations/Migration030.go new file mode 100644 index 0000000000..047e6e0fc9 --- /dev/null +++ b/repo/migrations/Migration030.go @@ -0,0 +1,150 @@ +package migrations + +import ( + "database/sql" + "fmt" + "os" + "path" + "strings" + + _ "github.com/mutecomm/go-sqlcipher" +) + +var ( + am03_up_create_utxos = "create table utxos (outpoint text primary key not null, value text, height integer, scriptPubKey text, watchOnly integer, coin text);" + am03_down_create_utxos = "create table utxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer, coin text);" + am03_temp_utxos = "ALTER TABLE utxos RENAME TO temp_utxos;" + am03_insert_utxos = "INSERT INTO utxos SELECT outpoint, value, height, scriptPubKey, watchOnly, coin FROM temp_utxos;" + am03_drop_temp_utxos = "DROP TABLE temp_utxos;" + + am03_up_create_stxos = "create table stxos (outpoint text primary key not null, value text, height integer, scriptPubKey text, watchOnly integer, spendHeight integer, spendTxid text, coin text);" + am03_down_create_stxos = "create table stxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer, spendHeight integer, spendTxid text, coin text);" + am03_temp_stxos = "ALTER TABLE stxos RENAME TO temp_stxos;" + am03_insert_stxos = "INSERT INTO stxos SELECT outpoint, value, height, scriptPubKey, watchOnly, spendHeight, spendTxid, coin FROM temp_stxos;" + am03_drop_temp_stxos = "DROP TABLE temp_stxos;" + + am03_up_create_txns = "create table txns (txid text primary key not null, value text, height integer, timestamp integer, watchOnly integer, tx blob, coin text);" + am03_down_create_txns = "create table txns (txid text primary key not null, value integer, height integer, timestamp integer, watchOnly integer, tx blob, coin text);" + am03_temp_txns = "ALTER TABLE txns RENAME TO temp_txns;" + am03_insert_txns = "INSERT INTO txns SELECT txid, value, height, timestamp, watchOnly, tx, coin FROM temp_txns;" + am03_drop_temp_txns = "DROP TABLE temp_txns;" +) + +type Migration030 struct{ AM03 } + +type AM03 struct{} + +func (AM03) Up(repoPath string, dbPassword string, testnet bool) error { + var dbPath string + if testnet { + dbPath = path.Join(repoPath, "datastore", "testnet.db") + } else { + dbPath = path.Join(repoPath, "datastore", "mainnet.db") + } + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return err + } + if dbPassword != "" { + p := "pragma key='" + dbPassword + "';" + if _, err := db.Exec(p); err != nil { + return err + } + } + + upSequence := strings.Join([]string{ + am03_temp_utxos, + am03_up_create_utxos, + am03_insert_utxos, + am03_drop_temp_utxos, + am03_temp_stxos, + am03_up_create_stxos, + am03_insert_stxos, + am03_drop_temp_stxos, + am03_temp_txns, + am03_up_create_txns, + am03_insert_txns, + am03_drop_temp_txns, + }, " ") + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(upSequence); err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("rollback failed: (%s) due to (%s)", rErr.Error(), err.Error()) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + f1, err := os.Create(path.Join(repoPath, "repover")) + if err != nil { + return err + } + _, err = f1.Write([]byte("31")) + if err != nil { + return err + } + f1.Close() + return nil +} + +func (AM03) Down(repoPath string, dbPassword string, testnet bool) error { + var dbPath string + if testnet { + dbPath = path.Join(repoPath, "datastore", "testnet.db") + } else { + dbPath = path.Join(repoPath, "datastore", "mainnet.db") + } + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return err + } + if dbPassword != "" { + p := "pragma key='" + dbPassword + "';" + if _, err := db.Exec(p); err != nil { + return err + } + } + downSequence := strings.Join([]string{ + am03_temp_utxos, + am03_down_create_utxos, + am03_insert_utxos, + am03_drop_temp_utxos, + am03_temp_stxos, + am03_down_create_stxos, + am03_insert_stxos, + am03_drop_temp_stxos, + am03_temp_txns, + am03_down_create_txns, + am03_insert_txns, + am03_drop_temp_txns, + }, " ") + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(downSequence); err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("rollback failed: (%s) due to (%s)", rErr.Error(), err.Error()) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + f1, err := os.Create(path.Join(repoPath, "repover")) + if err != nil { + return err + } + _, err = f1.Write([]byte("30")) + if err != nil { + return err + } + f1.Close() + return nil +} diff --git a/repo/migrations/Migration030_test.go b/repo/migrations/Migration030_test.go new file mode 100644 index 0000000000..cdcce9f6bf --- /dev/null +++ b/repo/migrations/Migration030_test.go @@ -0,0 +1,123 @@ +package migrations_test + +import ( + "database/sql" + "io/ioutil" + "testing" + + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" +) + +var stm = `PRAGMA key = 'letmein'; + create table utxos (outpoint text primary key not null, + value integer, height integer, scriptPubKey text, + watchOnly integer, coin text); + create table stxos (outpoint text primary key not null, + value integer, height integer, scriptPubKey text, + watchOnly integer, spendHeight integer, spendTxid text, + coin text); + create table txns (txid text primary key not null, + value integer, height integer, timestamp integer, + watchOnly integer, tx blob, coin text);` + +func TestMigration030(t *testing.T) { + basePath := schema.GenerateTempPath() + appSchema, err := schema.NewCustomSchemaManager(schema.SchemaContext{DataPath: basePath, TestModeEnabled: true}) + if err != nil { + t.Fatal(err) + } + if err = appSchema.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer appSchema.DestroySchemaDirectories() + + var dbPath = appSchema.DataPathJoin("datastore", "mainnet.db") + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + t.Fatal(err) + } + if _, err := db.Exec(stm); err != nil { + t.Fatal(err) + } + _, err = db.Exec("INSERT INTO utxos (outpoint, value, height, scriptPubKey, watchOnly, coin) values (?,?,?,?,?,?)", "asdf", 3, 1, "key1", 1, "TBTC") + if err != nil { + t.Fatal(err) + } + _, err = db.Exec("INSERT INTO stxos (outpoint, value, height, scriptPubKey, watchOnly, coin) values (?,?,?,?,?,?)", "asdf", 3, 1, "key1", 1, "TBTC") + if err != nil { + t.Fatal(err) + } + _, err = db.Exec("INSERT INTO txns (txid, value, height, timestamp, watchOnly, coin) values (?,?,?,?,?,?)", "asdf", 3, 1, 234, 1, "TBTC") + if err != nil { + t.Fatal(err) + } + var m migrations.Migration030 + err = m.Up(basePath, "letmein", false) + if err != nil { + t.Error(err) + } + + var outpoint string + var value string + var height int + var scriptPubKey string + var watchOnlyInt int + var value1 int + + r := db.QueryRow("select outpoint, value, height, scriptPubKey, watchOnly from utxos where coin=?", "TBTC") + + if err := r.Scan(&outpoint, &value, &height, &scriptPubKey, &watchOnlyInt); err != nil || value != "3" { + t.Fatal(err) + } + + r = db.QueryRow("select outpoint, value, height, scriptPubKey, watchOnly from stxos where coin=?", "TBTC") + + if err := r.Scan(&outpoint, &value, &height, &scriptPubKey, &watchOnlyInt); err != nil || value != "3" { + t.Fatal(err) + } + + r = db.QueryRow("select txid, value, height, watchOnly from txns where coin=?", "TBTC") + + if err := r.Scan(&outpoint, &value, &height, &watchOnlyInt); err != nil || value != "3" { + t.Fatal(err) + } + + repoVer, err := ioutil.ReadFile(appSchema.DataPathJoin("repover")) + if err != nil { + t.Error(err) + } + if string(repoVer) != "31" { + t.Error("Failed to write new repo version") + } + + err = m.Down(basePath, "letmein", false) + if err != nil { + t.Fatal(err) + } + r = db.QueryRow("select outpoint, value, height, scriptPubKey, watchOnly from utxos where coin=?", "TBTC") + + if err := r.Scan(&outpoint, &value1, &height, &scriptPubKey, &watchOnlyInt); err != nil || value1 != 3 { + t.Fatal(err) + } + + r = db.QueryRow("select outpoint, value, height, scriptPubKey, watchOnly from stxos where coin=?", "TBTC") + + if err := r.Scan(&outpoint, &value1, &height, &scriptPubKey, &watchOnlyInt); err != nil || value1 != 3 { + t.Fatal(err) + } + + r = db.QueryRow("select txid, value, height, watchOnly from txns where coin=?", "TBTC") + + if err := r.Scan(&outpoint, &value1, &height, &watchOnlyInt); err != nil || value1 != 3 { + t.Fatal(err) + } + + repoVer, err = ioutil.ReadFile(appSchema.DataPathJoin("repover")) + if err != nil { + t.Error(err) + } + if string(repoVer) != "30" { + t.Error("Failed to write new repo version") + } +} diff --git a/repo/migrations/Migration031.go b/repo/migrations/Migration031.go new file mode 100644 index 0000000000..4d674fb245 --- /dev/null +++ b/repo/migrations/Migration031.go @@ -0,0 +1,175 @@ +package migrations + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "os" + "path" +) + +const ( + am01EthereumRegistryAddressMainnet = "0x5c69ccf91eab4ef80d9929b3c1b4d5bc03eb0981" + am01EthereumRegistryAddressRinkeby = "0x5cEF053c7b383f430FC4F4e1ea2F7D31d8e2D16C" + am01EthereumRegistryAddressRopsten = "0x403d907982474cdd51687b09a8968346159378f3" + am01UpVersion = 31 + am01DownVersion = 30 +) + +// am01 - required migration struct +type am01 struct{} + +type Migration031 struct{ am01 } + +// Up - upgrade the state +func (am01) Up(repoPath, dbPassword string, testnet bool) error { + var ( + configMap = map[string]interface{}{} + configBytes, err = ioutil.ReadFile(path.Join(repoPath, "config")) + ) + if err != nil { + return fmt.Errorf("reading config: %s", err.Error()) + } + + if err = json.Unmarshal(configBytes, &configMap); err != nil { + return fmt.Errorf("unmarshal config: %s", err.Error()) + } + + c, ok := configMap["Wallets"] + if !ok { + return errors.New("invalid config: missing key Wallets") + } + + walletCfg, ok := c.(map[string]interface{}) + if !ok { + return errors.New("invalid config: invalid key Wallets") + } + + btc, ok := walletCfg["BTC"] + if !ok { + return errors.New("invalid config: missing BTC Wallet") + } + + btcWalletCfg, ok := btc.(map[string]interface{}) + if !ok { + return errors.New("invalid config: invalid BTC Wallet") + } + + btcWalletCfg["APIPool"] = []string{"https://btc.api.openbazaar.org/api"} + btcWalletCfg["APITestnetPool"] = []string{"https://tbtc.api.openbazaar.org/api"} + + eth, ok := walletCfg["ETH"] + if !ok { + return errors.New("invalid config: missing ETH Wallet") + } + + if eth == nil { + eth = map[string]interface{}{} + walletCfg["ETH"] = eth + } + + ethWalletCfg, ok := eth.(map[string]interface{}) + if !ok { + return errors.New("invalid config: invalid ETH Wallet") + } + + ethWalletCfg["Type"] = "API" + ethWalletCfg["FeeAPI"] = "" + ethWalletCfg["API"] = []string{"https://mainnet.infura.io"} + ethWalletCfg["APIPool"] = []string{"https://mainnet.infura.io"} + ethWalletCfg["APITestnetPool"] = []string{"https://rinkeby.infura.io"} + ethWalletCfg["WalletOptions"] = map[string]interface{}{ + "RegistryAddress": am01EthereumRegistryAddressMainnet, + "RinkebyRegistryAddress": am01EthereumRegistryAddressRinkeby, + "RopstenRegistryAddress": am01EthereumRegistryAddressRopsten, + } + ethWalletCfg["LowFeeDefault"] = 7 + ethWalletCfg["MediumFeeDefault"] = 15 + ethWalletCfg["HighFeeDefault"] = 30 + ethWalletCfg["MaxFee"] = 200 + + newConfigBytes, err := json.MarshalIndent(configMap, "", " ") + if err != nil { + return fmt.Errorf("marshal migrated config: %s", err.Error()) + } + + if err := ioutil.WriteFile(path.Join(repoPath, "config"), newConfigBytes, os.ModePerm); err != nil { + return fmt.Errorf("writing migrated config: %s", err.Error()) + } + + if err := writeRepoVer(repoPath, am01UpVersion); err != nil { + return fmt.Errorf("bumping repover to %d: %s", am01UpVersion, err.Error()) + } + return nil +} + +// Down - downgrade/restore the state +func (am01) Down(repoPath, dbPassword string, testnet bool) error { + var ( + configMap = map[string]interface{}{} + configBytes, err = ioutil.ReadFile(path.Join(repoPath, "config")) + ) + if err != nil { + return fmt.Errorf("reading config: %s", err.Error()) + } + + if err = json.Unmarshal(configBytes, &configMap); err != nil { + return fmt.Errorf("unmarshal config: %s", err.Error()) + } + + c, ok := configMap["Wallets"] + if !ok { + return errors.New("invalid config: missing key Wallets") + } + + walletCfg, ok := c.(map[string]interface{}) + if !ok { + return errors.New("invalid config: invalid key Wallets") + } + + btc, ok := walletCfg["BTC"] + if !ok { + return errors.New("invalid config: missing BTC Wallet") + } + + btcWalletCfg, ok := btc.(map[string]interface{}) + if !ok { + return errors.New("invalid config: invalid BTC Wallet") + } + + btcWalletCfg["APIPool"] = []string{"https://btc.blockbook.api.openbazaar.org/api"} + btcWalletCfg["APITestnetPool"] = []string{"https://tbtc.blockbook.api.openbazaar.org/api"} + + eth, ok := walletCfg["ETH"] + if !ok { + return errors.New("invalid config: missing ETH Wallet") + } + + ethWalletCfg, ok := eth.(map[string]interface{}) + if !ok { + return errors.New("invalid config: invalid ETH Wallet") + } + + ethWalletCfg["APIPool"] = []string{"https://mainnet.infura.io"} + ethWalletCfg["APITestnetPool"] = []string{"https://rinkeby.infura.io"} + ethWalletCfg["WalletOptions"] = map[string]interface{}{ + "RegistryAddress": am01EthereumRegistryAddressMainnet, + "RinkebyRegistryAddress": am01EthereumRegistryAddressRinkeby, + "RopstenRegistryAddress": am01EthereumRegistryAddressRopsten, + } + + newConfigBytes, err := json.MarshalIndent(configMap, "", " ") + if err != nil { + return fmt.Errorf("marshal migrated config: %s", err.Error()) + } + + if err := ioutil.WriteFile(path.Join(repoPath, "config"), newConfigBytes, os.ModePerm); err != nil { + return fmt.Errorf("writing migrated config: %s", err.Error()) + } + + if err := writeRepoVer(repoPath, am01DownVersion); err != nil { + return fmt.Errorf("dropping repover to %d: %s", am01DownVersion, err.Error()) + } + return nil +} diff --git a/repo/migrations/Migration032.go b/repo/migrations/Migration032.go new file mode 100644 index 0000000000..26913486bc --- /dev/null +++ b/repo/migrations/Migration032.go @@ -0,0 +1,198 @@ +package migrations + +import ( + "database/sql" + "encoding/json" + "fmt" + "math/big" + "time" +) + +type Migration032 struct { + AM01 +} + +// AM01 migrates the listing and order data to use higher precision. +type AM01 struct{} + +var AM01UpVer = 33 +var AM01DownVer = 32 + +type AM01_TransactionRecord_beforeMigration struct { + Txid string + Index uint32 + Value int64 + Address string + Spent bool + Timestamp time.Time +} + +type AM01_TransactionRecord_afterMigration struct { + Txid string + Index uint32 + Value big.Int + Address string + Spent bool + Timestamp time.Time +} + +type AM01_record struct { + orderID string + coin string + unmigratedTransactions []AM01_TransactionRecord_beforeMigration + migratedTransactions []AM01_TransactionRecord_afterMigration +} + +func (AM01) Up(repoPath string, dbPassword string, testnet bool) (err error) { + db, err := OpenDB(repoPath, dbPassword, testnet) + if err != nil { + return fmt.Errorf("opening db: %s", err.Error()) + } + saleMigrationRecords, err := AM01_extractRecords(db, "select orderID, transactions, paymentCoin from sales;", false) + if err != nil { + return fmt.Errorf("get sales rows: %s", err.Error()) + } + purchaseMigrationRecords, err := AM01_extractRecords(db, "select orderID, transactions, paymentCoin from purchases;", false) + if err != nil { + return fmt.Errorf("get purchase rows: %s", err.Error()) + } + + if err := withTransaction(db, func(tx *sql.Tx) error { + err := AM01_updateRecords(tx, saleMigrationRecords, "update sales set transactions = ? where orderID = ?", testnet, false) + if err != nil { + return fmt.Errorf("update sales: %s", err.Error()) + } + err = AM01_updateRecords(tx, purchaseMigrationRecords, "update purchases set transactions = ? where orderID = ?", testnet, false) + if err != nil { + return fmt.Errorf("update purchases: %s", err.Error()) + } + return nil + }); err != nil { + return fmt.Errorf("migrating up: %s", err.Error()) + } + + return writeRepoVer(repoPath, AM01UpVer) +} + +func (AM01) Down(repoPath string, dbPassword string, testnet bool) (err error) { + db, err := OpenDB(repoPath, dbPassword, testnet) + if err != nil { + return fmt.Errorf("opening db: %s", err.Error()) + } + saleMigrationRecords, err := AM01_extractRecords(db, "select orderID, transactions, paymentCoin from sales;", true) + if err != nil { + return fmt.Errorf("get sales rows: %s", err.Error()) + } + purchaseMigrationRecords, err := AM01_extractRecords(db, "select orderID, transactions, paymentCoin from purchases;", true) + if err != nil { + return fmt.Errorf("get purchase rows: %s", err.Error()) + } + + if err := withTransaction(db, func(tx *sql.Tx) error { + err := AM01_updateRecords(tx, saleMigrationRecords, "update sales set transactions = ? where orderID = ?", testnet, true) + if err != nil { + return fmt.Errorf("update sales: %s", err.Error()) + } + err = AM01_updateRecords(tx, purchaseMigrationRecords, "update purchases set transactions = ? where orderID = ?", testnet, true) + if err != nil { + return fmt.Errorf("update purchases: %s", err.Error()) + } + return nil + }); err != nil { + return fmt.Errorf("migrating down: %s", err.Error()) + } + + return writeRepoVer(repoPath, AM01DownVer) +} + +func AM01_extractRecords(db *sql.DB, query string, migrateDown bool) ([]AM01_record, error) { + var ( + results = make([]AM01_record, 0) + rows, err = db.Query(query) + ) + if err != nil { + return nil, fmt.Errorf("selecting rows: %s", err.Error()) + } + defer rows.Close() + for rows.Next() { + var ( + serializedTransactions sql.NullString + r = AM01_record{} + ) + if err := rows.Scan(&r.orderID, &serializedTransactions, &r.coin); err != nil { + return nil, fmt.Errorf("scanning rows: %s", err.Error()) + } + if !serializedTransactions.Valid { + continue + } + if migrateDown { + if err := json.Unmarshal([]byte(serializedTransactions.String), &r.migratedTransactions); err != nil { + return nil, fmt.Errorf("unmarshal migrated transactions: %s", err.Error()) + } + } else { + if err := json.Unmarshal([]byte(serializedTransactions.String), &r.unmigratedTransactions); err != nil { + return nil, fmt.Errorf("unmarshal unmigrated transactions: %s", err.Error()) + } + } + results = append(results, r) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("iterating rows: %s", err.Error()) + } + return results, nil +} + +func AM01_updateRecords(tx *sql.Tx, records []AM01_record, query string, testMode bool, migrateDown bool) error { + var update, err = tx.Prepare(query) + if err != nil { + return fmt.Errorf("prepare update statement: %s", err.Error()) + } + defer update.Close() + for _, beforeRecord := range records { + + if migrateDown { + var migratedTransactionRecords = make([]AM01_TransactionRecord_beforeMigration, 0) + for _, beforeTx := range beforeRecord.migratedTransactions { + var migratedRecord = AM01_TransactionRecord_beforeMigration{ + Txid: beforeTx.Txid, + Index: beforeTx.Index, + Value: beforeTx.Value.Int64(), + Spent: beforeTx.Spent, + Timestamp: beforeTx.Timestamp, + Address: beforeTx.Address, + } + migratedTransactionRecords = append(migratedTransactionRecords, migratedRecord) + } + serializedTransactionRecords, err := json.Marshal(migratedTransactionRecords) + if err != nil { + return fmt.Errorf("marshal transactions: %s", err.Error()) + } + if _, err := update.Exec(string(serializedTransactionRecords), beforeRecord.orderID); err != nil { + return fmt.Errorf("updating record: %s", err.Error()) + } + } else { + var migratedTransactionRecords = make([]AM01_TransactionRecord_afterMigration, 0) + for _, beforeTx := range beforeRecord.unmigratedTransactions { + n := big.NewInt(beforeTx.Value) + var migratedRecord = AM01_TransactionRecord_afterMigration{ + Txid: beforeTx.Txid, + Index: beforeTx.Index, + Value: *n, + Spent: beforeTx.Spent, + Timestamp: beforeTx.Timestamp, + Address: beforeTx.Address, + } + migratedTransactionRecords = append(migratedTransactionRecords, migratedRecord) + } + serializedTransactionRecords, err := json.Marshal(migratedTransactionRecords) + if err != nil { + return fmt.Errorf("marhsal transactions: %s", err.Error()) + } + if _, err := update.Exec(string(serializedTransactionRecords), beforeRecord.orderID); err != nil { + return fmt.Errorf("updating record: %s", err.Error()) + } + } + + } + return nil +} diff --git a/repo/migrations/Migration032_test.go b/repo/migrations/Migration032_test.go new file mode 100644 index 0000000000..735093ac64 --- /dev/null +++ b/repo/migrations/Migration032_test.go @@ -0,0 +1,268 @@ +package migrations_test + +import ( + "database/sql" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "strings" + "testing" + + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" +) + +func TestMigration032(t *testing.T) { + // Setup + appSchema := schema.MustNewCustomSchemaManager(schema.SchemaContext{ + DataPath: schema.GenerateTempPath(), + TestModeEnabled: true, + }) + if err := appSchema.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer appSchema.DestroySchemaDirectories() + + var ( + dbPassword = "foobarbaz" + repoVerPath = appSchema.DataPathJoin("repover") + + encryptDB = fmt.Sprintf("pragma key = '%s';", dbPassword) + buildPurchaseSchemaSQL = "create table purchases (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total integer, thumbnail text, vendorID text, vendorHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, lastDisputeTimeoutNotifiedAt integer not null default 0, lastDisputeExpiryNotifiedAt integer not null default 0, disputedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" + buildSalesSchemaSQL = "create table sales (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total integer, thumbnail text, buyerID text, buyerHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, lastDisputeTimeoutNotifiedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" + + db, err = sql.Open("sqlite3", appSchema.DatabasePath()) + ) + + if err != nil { + t.Fatal(err) + } + _, err = db.Exec(strings.Join([]string{ + encryptDB, + buildPurchaseSchemaSQL, + buildSalesSchemaSQL, + }, " ")) + if err != nil { + t.Fatal(err) + } + + examples := map[string]migrations.AM01_TransactionRecord_beforeMigration{ + "BTC": {Txid: "BTC", Index: 0, Address: "76a9143c75da9d9a5e8019c966f0d2f527da2256bdfd1a88ac", Value: 12345678}, + "BCH": {Txid: "BCH", Index: 0, Address: "76a914f1c075a01882ae0972f95d3a4177c86c852b7d9188ac", Value: 12345678}, + "ZEC": {Txid: "ZEC", Index: 0, Address: "76a9141bdb7bfbf8ce043c4edaebc88d53dacffb56630788ac", Value: 12345678}, + "TBTC": {Txid: "TBTC", Index: 0, Address: "76a914406ccf980b91476c89dbf129b028b8cbc81a52d688ac", Value: 12345678}, + "TBCH": {Txid: "TBCH", Index: 0, Address: "76a9149dd551e0809fed1e7afdb62e8559563fbe1ece7288ac", Value: 12345678}, + "TZEC": {Txid: "TZEC", Index: 0, Address: "76a91436d138db609a730bf67cf5ed2bd0989c65f627b488ac", Value: 12345678}, + } + insertPurchaseStatement, err := db.Prepare("insert into purchases(orderID, transactions, paymentCoin) values(?, ?, ?);") + if err != nil { + t.Fatal(err) + } + insertSalesStatement, err := db.Prepare("insert into sales(orderID, transactions, paymentCoin) values(?, ?, ?);") + if err != nil { + t.Fatal(err) + } + insertNullTransactionsSaleStatement, err := db.Prepare("insert into sales(orderID, transactions, paymentCoin) values(?, NULL, ?);") + if err != nil { + t.Fatal(err) + } + insertNullTransactionsPurchaseStatement, err := db.Prepare("insert into purchases(orderID, transactions, paymentCoin) values(?, NULL, ?);") + if err != nil { + t.Fatal(err) + } + for _, tx := range examples { + transactions, err := json.Marshal([]migrations.AM01_TransactionRecord_beforeMigration{tx}) + if err != nil { + t.Fatal(err) + } + _, err = insertPurchaseStatement.Exec(tx.Txid, string(transactions), tx.Txid) + if err != nil { + t.Fatal(err) + } + _, err = insertSalesStatement.Exec(tx.Txid, string(transactions), tx.Txid) + if err != nil { + t.Fatal(err) + } + _, err = insertNullTransactionsSaleStatement.Exec(fmt.Sprintf("NULLED%s", tx.Txid), tx.Txid) + if err != nil { + t.Fatal(err) + } + _, err = insertNullTransactionsPurchaseStatement.Exec(fmt.Sprintf("NULLED%s", tx.Txid), tx.Txid) + if err != nil { + t.Fatal(err) + } + } + insertPurchaseStatement.Close() + insertSalesStatement.Close() + + // Create schema version file + if err = ioutil.WriteFile(repoVerPath, []byte("31"), os.ModePerm); err != nil { + t.Fatal(err) + } + + // Test migration up + if err := (migrations.AM01{}).Up(appSchema.DataPath(), dbPassword, true); err != nil { + t.Fatal(err) + } + + // Validate purchases are converted + purchaseRows, err := db.Query("select orderID, transactions, paymentCoin from purchases") + if err != nil { + t.Fatal(err) + } + for purchaseRows.Next() { + var ( + marshaledTransactions sql.NullString + orderID, paymentCoin string + actualTransactions []migrations.AM01_TransactionRecord_afterMigration + ) + if err := purchaseRows.Scan(&orderID, &marshaledTransactions, &paymentCoin); err != nil { + t.Error(err) + continue + } + if !marshaledTransactions.Valid { + continue + } + if err := json.Unmarshal([]byte(marshaledTransactions.String), &actualTransactions); err != nil { + t.Error(err) + continue + } + + AM01_assertTransaction(t, examples, actualTransactions) + } + if err := purchaseRows.Err(); err != nil { + t.Error(err) + } + purchaseRows.Close() + + // Validate sales are converted + saleRows, err := db.Query("select orderID, transactions, paymentCoin from sales") + if err != nil { + t.Fatal(err) + } + for saleRows.Next() { + var ( + orderID, paymentCoin string + marshaledTransactions sql.NullString + actualTransactions []migrations.AM01_TransactionRecord_afterMigration + ) + if err := saleRows.Scan(&orderID, &marshaledTransactions, &paymentCoin); err != nil { + t.Error(err) + continue + } + if !marshaledTransactions.Valid { + continue + } + if err := json.Unmarshal([]byte(marshaledTransactions.String), &actualTransactions); err != nil { + t.Error(err) + continue + } + + AM01_assertTransaction(t, examples, actualTransactions) + + } + if err := saleRows.Err(); err != nil { + t.Error(err) + } + if err := saleRows.Close(); err != nil { + t.Error(err) + } + + assertCorrectRepoVer(t, repoVerPath, "33") + + // Test migration down + if err := (migrations.AM01{}).Down(appSchema.DataPath(), dbPassword, true); err != nil { + t.Fatal(err) + } + + // Validate purchases are reverted + purchaseRows, err = db.Query("select orderID, transactions, paymentCoin from purchases") + if err != nil { + t.Fatal(err) + } + for purchaseRows.Next() { + var ( + marshaledTransactions sql.NullString + orderID, paymentCoin string + actualTransactions []migrations.AM01_TransactionRecord_beforeMigration + ) + if err := purchaseRows.Scan(&orderID, &marshaledTransactions, &paymentCoin); err != nil { + t.Error(err) + continue + } + if !marshaledTransactions.Valid { + continue + } + if err := json.Unmarshal([]byte(marshaledTransactions.String), &actualTransactions); err != nil { + t.Error(err) + continue + } + + for _, actualTx := range actualTransactions { + if examples[actualTx.Txid].Address != actualTx.Address { + t.Errorf("Expected address to be converted for example %s, but did not match", actualTx.Txid) + t.Errorf("Example: %+v", examples[actualTx.Txid]) + t.Errorf("Actual: %+v", actualTx) + } + } + } + if err := purchaseRows.Err(); err != nil { + t.Error(err) + } + purchaseRows.Close() + + // Validate sales are reverted + saleRows, err = db.Query("select orderID, transactions, paymentCoin from sales") + if err != nil { + t.Fatal(err) + } + for saleRows.Next() { + var ( + marshaledTransactions sql.NullString + orderID, paymentCoin string + actualTransactions []migrations.AM01_TransactionRecord_beforeMigration + ) + if err := saleRows.Scan(&orderID, &marshaledTransactions, &paymentCoin); err != nil { + t.Error(err) + continue + } + if !marshaledTransactions.Valid { + continue + } + if err := json.Unmarshal([]byte(marshaledTransactions.String), &actualTransactions); err != nil { + t.Error(err) + continue + } + + for _, actualTx := range actualTransactions { + if examples[actualTx.Txid].Address != actualTx.Address { + t.Errorf("Expected address to be converted for example %s, but did not match", actualTx.Txid) + t.Errorf("Example: %+v", examples[actualTx.Txid]) + t.Errorf("Actual: %+v", actualTx) + } + } + + } + if err := saleRows.Err(); err != nil { + t.Error(err) + } + if err := saleRows.Close(); err != nil { + t.Error(err) + } + + assertCorrectRepoVer(t, repoVerPath, "32") +} + +func AM01_assertTransaction(t *testing.T, examples map[string]migrations.AM01_TransactionRecord_beforeMigration, actual []migrations.AM01_TransactionRecord_afterMigration) { + for _, actualTx := range actual { + var exampleName = actualTx.Txid + originalValue := examples[exampleName].Value + expectedValue := actualTx.Value.Int64() + if originalValue != expectedValue { + t.Errorf("Expected value to be converted for example %s, but did not match", exampleName) + t.Errorf("Example: %+v", examples[actualTx.Txid]) + t.Errorf("Actual: %+v", actualTx) + } + } +} diff --git a/repo/migrations/Migration033.go b/repo/migrations/Migration033.go new file mode 100644 index 0000000000..c660e37843 --- /dev/null +++ b/repo/migrations/Migration033.go @@ -0,0 +1,146 @@ +package migrations + +import ( + "database/sql" + "fmt" + "path" + "strings" + + _ "github.com/mutecomm/go-sqlcipher" +) + +const ( + // migrationAlterMessagesAM09Err alters the table to add the err column. + migrationAlterMessagesAM09Err = "alter table messages add err text;" + // migrationAlterMessagesAM09ReceivedAt alters the table to add the received_at column. + migrationAlterMessagesAM09ReceivedAt = "alter table messages add received_at integer;" + // migrationAlterMessagesAM09Pubkey alters the table to add the pubkey column. + migrationAlterMessagesAM09Pubkey = "alter table messages add pubkey blob;" + // MigrationCreateMessagesAM09MessagesCreateSQLDown the messages create sql + MigrationCreateMessagesAM09MessagesCreateSQLDown = "create table messages (messageID text primary key not null, orderID text, message_type integer, message blob, peerID text, url text, acknowledged bool, tries integer, created_at integer, updated_at integer);" + // migrationRenameMessagesAM09MessagesCreateSQL the messages create sql + migrationRenameMessagesAM09MessagesCreateSQL = "ALTER TABLE messages RENAME TO temp_messages;" + // migrationInsertMessagesAM09Messages the messages create sql + migrationInsertMessagesAM09Messages = "INSERT INTO messages SELECT messageID, orderID, message_type, message, peerID, url, acknowledged, tries, created_at, updated_at FROM temp_messages;" + // migrationCreateMessagesAM09MessagesDeleteSQL the messages delete sql + migrationCreateMessagesAM09MessagesDeleteSQL = "drop table if exists temp_messages;" + // migrationCreateMessagesAM09UpVer set the repo Up version + migrationCreateMessagesAM09UpVer = 34 + // migrationCreateMessagesAM09DownVer set the repo Down version + migrationCreateMessagesAM09DownVer = 33 +) + +// Migration033 migration struct +type Migration033 struct{} + +// Up the migration Up code +func (Migration033) Up(repoPath, databasePassword string, testnetEnabled bool) error { + var ( + databaseFilePath string + ) + if testnetEnabled { + databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") + } else { + databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") + } + + db, err := sql.Open("sqlite3", databaseFilePath) + if err != nil { + return err + } + defer db.Close() + if databasePassword != "" { + p := fmt.Sprintf("pragma key = '%s';", databasePassword) + _, err := db.Exec(p) + if err != nil { + return err + } + } + + upSequence := strings.Join([]string{ + migrationAlterMessagesAM09Err, + migrationAlterMessagesAM09ReceivedAt, + migrationAlterMessagesAM09Pubkey, + }, " ") + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(upSequence); err != nil { + if err.Error() == "duplicate column name: err" { + err = writeRepoVer(repoPath, migrationCreateMessagesAM09UpVer) + if err != nil { + return err + } + return nil + } + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("rollback failed: (%s) due to (%s)", rErr.Error(), err.Error()) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + + // Bump schema version + err = writeRepoVer(repoPath, migrationCreateMessagesAM09UpVer) + if err != nil { + return err + } + return nil +} + +// Down the migration Down code +func (Migration033) Down(repoPath, databasePassword string, testnetEnabled bool) error { + var ( + databaseFilePath string + ) + if testnetEnabled { + databaseFilePath = path.Join(repoPath, "datastore", "testnet.db") + } else { + databaseFilePath = path.Join(repoPath, "datastore", "mainnet.db") + } + + db, err := sql.Open("sqlite3", databaseFilePath) + if err != nil { + return err + } + defer db.Close() + if databasePassword != "" { + p := fmt.Sprintf("pragma key = '%s';", databasePassword) + _, err := db.Exec(p) + if err != nil { + return err + } + } + + downSequence := strings.Join([]string{ + migrationRenameMessagesAM09MessagesCreateSQL, + MigrationCreateMessagesAM09MessagesCreateSQLDown, + migrationInsertMessagesAM09Messages, + migrationCreateMessagesAM09MessagesDeleteSQL, + }, " ") + + tx, err := db.Begin() + if err != nil { + return err + } + if _, err = tx.Exec(downSequence); err != nil { + if rErr := tx.Rollback(); rErr != nil { + return fmt.Errorf("rollback failed: (%s) due to (%s)", rErr.Error(), err.Error()) + } + return err + } + if err = tx.Commit(); err != nil { + return err + } + + // Bump schema version + err = writeRepoVer(repoPath, migrationCreateMessagesAM09DownVer) + if err != nil { + return err + } + return nil +} diff --git a/repo/migrations/Migration033_test.go b/repo/migrations/Migration033_test.go new file mode 100644 index 0000000000..63ba40dd1c --- /dev/null +++ b/repo/migrations/Migration033_test.go @@ -0,0 +1,96 @@ +package migrations_test + +import ( + "database/sql" + "io/ioutil" + "os" + "testing" + + "github.com/phoreproject/pm-go/repo/migrations" + "github.com/phoreproject/pm-go/schema" +) + +func TestMigration033(t *testing.T) { + var ( + basePath = schema.GenerateTempPath() + testRepoPath, err = schema.OpenbazaarPathTransform(basePath, true) + + testMigration033SchemaStmts = []string{ + "DROP TABLE IF EXISTS messages;", + migrations.MigrationCreateMessagesAM09MessagesCreateSQLDown, + } + ) + if err != nil { + t.Fatal(err) + } + appSchema, err := schema.NewCustomSchemaManager(schema.SchemaContext{DataPath: testRepoPath, TestModeEnabled: true}) + if err != nil { + t.Fatal(err) + } + if err = appSchema.BuildSchemaDirectories(); err != nil { + t.Fatal(err) + } + defer appSchema.DestroySchemaDirectories() + + if err := appSchema.InitializeDatabase(); err != nil { + t.Fatal(err) + } + + var ( + databasePath = appSchema.DatabasePath() + schemaPath = appSchema.DataPathJoin("repover") + + insertSQL = "insert into messages(messageID, err, received_at) values(?,?,?)" + ) + + // create schema version file + if err = ioutil.WriteFile(schemaPath, []byte("33"), os.ModePerm); err != nil { + t.Fatal(err) + } + + db, err := sql.Open("sqlite3", databasePath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + for _, stmt := range testMigration033SchemaStmts { + _, err := db.Exec(stmt) + if err != nil { + t.Fatal(err) + } + } + + // execute migration up + m := migrations.Migration033{} + if err := m.Up(testRepoPath, "", true); err != nil { + t.Fatal(err) + } + + // assert repo version updated + if err = appSchema.VerifySchemaVersion("34"); err != nil { + t.Fatal(err) + } + + // verify change was applied properly + _, err = db.Exec(insertSQL, "abc", "", 0) + if err != nil { + t.Fatal(err) + } + + // execute migration down + if err := m.Down(testRepoPath, "", true); err != nil { + t.Fatal(err) + } + + // assert repo version reverted + if err = appSchema.VerifySchemaVersion("33"); err != nil { + t.Fatal(err) + } + + // verify change was reverted properly + _, err = db.Exec(insertSQL, "abc", "", 0) + if err == nil { + t.Fatal(err) + } +} diff --git a/repo/migrations/log.go b/repo/migrations/log.go new file mode 100644 index 0000000000..d48cea9508 --- /dev/null +++ b/repo/migrations/log.go @@ -0,0 +1,5 @@ +package migrations + +import logging "github.com/op/go-logging" + +var log = logging.MustGetLogger("migrations") diff --git a/repo/models.go b/repo/models.go index bed9ee5c41..c75f824a0b 100644 --- a/repo/models.go +++ b/repo/models.go @@ -40,6 +40,7 @@ type SMTPSettings struct { Password string `json:"password"` SenderEmail string `json:"senderEmail"` RecipientEmail string `json:"recipientEmail"` + OpenBazaarName string `json:"openBazaarName"` } type Follower struct { @@ -53,88 +54,85 @@ type Coupon struct { Hash string } -type GroupChatMessage struct { - PeerIds []string `json:"peerIds"` - Subject string `json:"subject"` - Message string `json:"message"` -} - -type ChatConversation struct { - PeerId string `json:"peerId"` - Unread int `json:"unread"` - Last string `json:"lastMessage"` - Timestamp time.Time `json:"timestamp"` - Outgoing bool `json:"outgoing"` -} - type Metadata struct { Txid string Address string Memo string - OrderID string + OrderId string Thumbnail string CanBumpFee bool } type Purchase struct { - OrderId string `json:"orderId"` - Slug string `json:"slug"` - Timestamp time.Time `json:"timestamp"` - Title string `json:"title"` - Thumbnail string `json:"thumbnail"` - Total uint64 `json:"total"` - VendorId string `json:"vendorId"` - VendorHandle string `json:"vendorHandle"` - ShippingName string `json:"shippingName"` - ShippingAddress string `json:"shippingAddress"` - CoinType string `json:"coinType"` - PaymentCoin string `json:"paymentCoin"` - State string `json:"state"` - Read bool `json:"read"` - Moderated bool `json:"moderated"` - UnreadChatMessages int `json:"unreadChatMessages"` + OrderId string `json:"orderId"` + Slug string `json:"slug"` + Timestamp time.Time `json:"timestamp"` + Title string `json:"title"` + Thumbnail string `json:"thumbnail"` + Total CurrencyValue `json:"total"` + VendorId string `json:"vendorId"` + VendorHandle string `json:"vendorHandle"` + ShippingName string `json:"shippingName"` + ShippingAddress string `json:"shippingAddress"` + CoinType string `json:"coinType"` + PaymentCoin string `json:"paymentCoin"` + State string `json:"state"` + Read bool `json:"read"` + Moderated bool `json:"moderated"` + UnreadChatMessages int `json:"unreadChatMessages"` } type Sale struct { - OrderId string `json:"orderId"` - Slug string `json:"slug"` - Timestamp time.Time `json:"timestamp"` - Title string `json:"title"` - Thumbnail string `json:"thumbnail"` - Total uint64 `json:"total"` - BuyerId string `json:"buyerId"` - BuyerHandle string `json:"buyerHandle"` - ShippingName string `json:"shippingName"` - ShippingAddress string `json:"shippingAddress"` - CoinType string `json:"coinType"` - PaymentCoin string `json:"paymentCoin"` - State string `json:"state"` - Read bool `json:"read"` - Moderated bool `json:"moderated"` - UnreadChatMessages int `json:"unreadChatMessages"` + OrderId string `json:"orderId"` + Slug string `json:"slug"` + Timestamp time.Time `json:"timestamp"` + Title string `json:"title"` + Thumbnail string `json:"thumbnail"` + Total CurrencyValue `json:"total"` + BuyerId string `json:"buyerId"` + BuyerHandle string `json:"buyerHandle"` + ShippingName string `json:"shippingName"` + ShippingAddress string `json:"shippingAddress"` + CoinType string `json:"coinType"` + PaymentCoin string `json:"paymentCoin"` + State string `json:"state"` + Read bool `json:"read"` + Moderated bool `json:"moderated"` + UnreadChatMessages int `json:"unreadChatMessages"` } type Case struct { - CaseId string `json:"caseId"` - Slug string `json:"slug"` - Timestamp time.Time `json:"timestamp"` - Title string `json:"title"` - Thumbnail string `json:"thumbnail"` - Total uint64 `json:"total"` - BuyerId string `json:"buyerId"` - BuyerHandle string `json:"buyerHandle"` - VendorId string `json:"vendorId"` - VendorHandle string `json:"vendorHandle"` - CoinType string `json:"coinType"` - PaymentCoin string `json:"paymentCoin"` - BuyerOpened bool `json:"buyerOpened"` - State string `json:"state"` - Read bool `json:"read"` - UnreadChatMessages int `json:"unreadChatMessages"` + CaseId string `json:"caseId"` + Slug string `json:"slug"` + Timestamp time.Time `json:"timestamp"` + Title string `json:"title"` + Thumbnail string `json:"thumbnail"` + Total CurrencyValue `json:"total"` + BuyerId string `json:"buyerId"` + BuyerHandle string `json:"buyerHandle"` + VendorId string `json:"vendorId"` + VendorHandle string `json:"vendorHandle"` + CoinType string `json:"coinType"` + PaymentCoin string `json:"paymentCoin"` + BuyerOpened bool `json:"buyerOpened"` + State string `json:"state"` + Read bool `json:"read"` + UnreadChatMessages int `json:"unreadChatMessages"` +} + +type UnfundedOrder struct { + OrderId string + Timestamp time.Time + PaymentCoin string + PaymentAddress string } -type UnfundedSale struct { - OrderId string - Timestamp time.Time - PaymentCoin string +type OrderMessage struct { + MessageID string `json:"messageID"` + OrderID string `json:"orderID"` + MessageType int32 `json:"message_type"` + Message []byte `json:"message"` + MsgErr string `json:"error"` + PeerID string `json:"peerID"` + PeerPubkey []byte `json:"pubkey"` } diff --git a/repo/notification.go b/repo/notification.go index 2aff318b44..5c03834f2f 100644 --- a/repo/notification.go +++ b/repo/notification.go @@ -5,6 +5,7 @@ import ( "encoding/json" //"errors" "fmt" mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" + "math/big" "time" ) @@ -39,7 +40,7 @@ type Notifier interface { func NewNotification(n Notifier, createdAt time.Time, isRead bool) *Notification { return &Notification{ ID: n.GetID(), - CreatedAt: createdAt.UTC(), + CreatedAt: NewAPITime(createdAt.UTC()), IsRead: isRead, NotifierData: n, NotifierType: n.GetType(), @@ -55,7 +56,7 @@ func NewNotification(n Notifier, createdAt time.Time, isRead bool) *Notification // serializations to match in the Notifications Datastore type Notification struct { ID string `json:"-"` - CreatedAt time.Time `json:"timestamp"` + CreatedAt *APITime `json:"timestamp"` IsRead bool `json:"read"` NotifierData Notifier `json:"notification"` NotifierType NotificationType `json:"-"` @@ -77,7 +78,7 @@ func (n *Notification) Data() ([]byte, error) { return json.MarshalInde func (n *Notification) WebsocketData() ([]byte, error) { return n.Data() } type notificationTransporter struct { - CreatedAt time.Time `json:"timestamp"` + CreatedAt *APITime `json:"timestamp"` IsRead bool `json:"read"` NotifierData json.RawMessage `json:"notification"` NotifierType NotificationType `json:"type"` @@ -313,7 +314,27 @@ func (n *Notification) UnmarshalJSON(data []byte) error { case NotifierTypeOrderNewNotification: var notifier = OrderNotification{} if err := json.Unmarshal(payload.NotifierData, ¬ifier); err != nil { - return err + notifierLegacy := OrderNotificationV4{} + if err2 := json.Unmarshal(payload.NotifierData, ¬ifierLegacy); err2 != nil { + return err2 + } + notifier.OrderId = notifierLegacy.OrderId + notifier.BuyerHandle = notifierLegacy.BuyerHandle + notifier.BuyerID = notifierLegacy.BuyerID + notifier.ID = notifierLegacy.ID + notifier.Price = &CurrencyValue{ + Amount: new(big.Int).SetUint64(notifierLegacy.Price.Amount), + Currency: CurrencyDefinition{ + Code: CurrencyCode(notifierLegacy.Price.CurrencyCode), + Divisibility: uint(notifierLegacy.Price.CoinDivisibility), + }, + } + notifier.PriceModifier = notifierLegacy.PriceModifier + notifier.Slug = notifierLegacy.Slug + notifier.Type = notifierLegacy.Type + notifier.ListingType = notifierLegacy.ListingType + notifier.Thumbnail = notifierLegacy.Thumbnail + notifier.Title = notifierLegacy.Title } n.NotifierData = notifier case NotifierTypePaymentNotification: @@ -399,6 +420,20 @@ type messageTypingWrapper struct { MessageRead Notifier `json:"messageTyping"` } +type OrderNotification struct { + BuyerHandle string `json:"buyerHandle"` + BuyerID string `json:"buyerId"` + ID string `json:"notificationId"` + ListingType string `json:"listingType"` + OrderId string `json:"orderId"` + Price *CurrencyValue `json:"price"` + PriceModifier float32 `json:"priceModifier"` + Slug string `json:"slug"` + Thumbnail Thumbnail `json:"thumbnail"` + Title string `json:"title"` + Type NotificationType `json:"type"` +} + type ListingPrice struct { Amount uint64 `json:"amount"` CurrencyCode string `json:"currencyCode"` @@ -406,17 +441,18 @@ type ListingPrice struct { CoinDivisibility uint32 `json:"coinDivisibility"` } -type OrderNotification struct { - BuyerHandle string `json:"buyerHandle"` - BuyerID string `json:"buyerId"` - ID string `json:"notificationId"` - ListingType string `json:"listingType"` - OrderId string `json:"orderId"` - Price ListingPrice `json:"price"` - Slug string `json:"slug"` - Thumbnail Thumbnail `json:"thumbnail"` - Title string `json:"title"` - Type NotificationType `json:"type"` +type OrderNotificationV4 struct { + BuyerHandle string `json:"buyerHandle"` + BuyerID string `json:"buyerId"` + ID string `json:"notificationId"` + ListingType string `json:"listingType"` + OrderId string `json:"orderId"` + Price ListingPrice `json:"price"` + PriceModifier float32 `json:"priceModifier"` + Slug string `json:"slug"` + Thumbnail Thumbnail `json:"thumbnail"` + Title string `json:"title"` + Type NotificationType `json:"type"` } func (n OrderNotification) Data() ([]byte, error) { @@ -442,7 +478,7 @@ type PaymentNotification struct { ID string `json:"notificationId"` Type NotificationType `json:"type"` OrderId string `json:"orderId"` - FundingTotal uint64 `json:"fundingTotal"` + FundingTotal *CurrencyValue `json:"fundingTotal"` CoinType string `json:"coinType"` } @@ -456,7 +492,7 @@ func (n PaymentNotification) GetID() string { return n.ID } func (n PaymentNotification) GetType() NotificationType { return NotifierTypePaymentNotification } func (n PaymentNotification) GetSMTPTitleAndBody() (string, string, bool) { form := "Payment for order \"%s\" received (total %d)." - return "Payment received", fmt.Sprintf(form, n.OrderId, n.FundingTotal), true + return "Payment received", fmt.Sprintf(form, n.OrderId, n.FundingTotal.Amount), true } type OrderConfirmationNotification struct { @@ -804,21 +840,16 @@ func (n StatusNotification) GetID() string { retur func (n StatusNotification) GetType() NotificationType { return NotifierTypeStatusUpdateNotification } func (n StatusNotification) GetSMTPTitleAndBody() (string, string, bool) { return "", "", false } -type ChatMessage struct { - MessageId string `json:"messageId"` - PeerId string `json:"peerId"` - Subject string `json:"subject"` - Message string `json:"message"` - Read bool `json:"read"` - Outgoing bool `json:"outgoing"` - Timestamp time.Time `json:"timestamp"` -} +// ChatMessageNotification handles serialization of ChatMessages for notifications +type ChatMessageNotification ChatMessage -func (n ChatMessage) Data() ([]byte, error) { return json.MarshalIndent(messageWrapper{n}, "", " ") } -func (n ChatMessage) WebsocketData() ([]byte, error) { return n.Data() } -func (n ChatMessage) GetID() string { return "" } // Not persisted, ID is ignored -func (n ChatMessage) GetType() NotificationType { return NotifierTypeChatMessage } -func (n ChatMessage) GetSMTPTitleAndBody() (string, string, bool) { return "", "", false } +func (n ChatMessageNotification) Data() ([]byte, error) { + return json.MarshalIndent(messageWrapper{n}, "", " ") +} +func (n ChatMessageNotification) WebsocketData() ([]byte, error) { return n.Data() } +func (n ChatMessageNotification) GetID() string { return "" } // Not persisted, ID is ignored +func (n ChatMessageNotification) GetType() NotificationType { return NotifierTypeChatMessage } +func (n ChatMessageNotification) GetSMTPTitleAndBody() (string, string, bool) { return "", "", false } type ChatRead struct { MessageId string `json:"messageId"` @@ -847,18 +878,17 @@ func (n ChatTyping) GetType() NotificationType { return Notifi func (n ChatTyping) GetSMTPTitleAndBody() (string, string, bool) { return "", "", false } type IncomingTransaction struct { - Wallet string `json:"wallet"` - Txid string `json:"txid"` - Value int64 `json:"value"` - Address string `json:"address"` - Status string `json:"status"` - Memo string `json:"memo"` - Timestamp time.Time `json:"timestamp"` - Confirmations int32 `json:"confirmations"` - OrderId string `json:"orderId"` - Thumbnail string `json:"thumbnail"` - Height int32 `json:"height"` - CanBumpFee bool `json:"canBumpFee"` + Txid string `json:"txid"` + Value *CurrencyValue `json:"value"` + Address string `json:"address"` + Status string `json:"status"` + Memo string `json:"memo"` + Timestamp time.Time `json:"timestamp"` + Confirmations int32 `json:"confirmations"` + OrderId string `json:"orderId"` + Thumbnail string `json:"thumbnail"` + Height int32 `json:"height"` + CanBumpFee bool `json:"canBumpFee"` } func (n IncomingTransaction) Data() ([]byte, error) { diff --git a/repo/notifications_test.go b/repo/notifications_test.go index e028ebdd94..15dda6f9f1 100644 --- a/repo/notifications_test.go +++ b/repo/notifications_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) func TestDataIsUnmarshalable(t *testing.T) { diff --git a/repo/order_confirmation.go b/repo/order_confirmation.go new file mode 100644 index 0000000000..0a59f21790 --- /dev/null +++ b/repo/order_confirmation.go @@ -0,0 +1,19 @@ +package repo + +import ( + "github.com/golang/protobuf/proto" + "github.com/phoreproject/pm-go/pb" + "math/big" +) + +// ToV5OrderConfirmation scans through the order confirmation looking for any deprecated fields and +// turns them into their v5 counterpart. +func ToV5OrderConfirmation(orderConfirmation *pb.OrderConfirmation) *pb.OrderConfirmation { + newOrderConfirmation := proto.Clone(orderConfirmation).(*pb.OrderConfirmation) + + if orderConfirmation.RequestedAmount != 0 && orderConfirmation.BigRequestedAmount == "" { + newOrderConfirmation.BigRequestedAmount = big.NewInt(int64(orderConfirmation.RequestedAmount)).String() + newOrderConfirmation.RequestedAmount = 0 + } + return newOrderConfirmation +} diff --git a/repo/order_confirmation_test.go b/repo/order_confirmation_test.go new file mode 100644 index 0000000000..16a88ae2f3 --- /dev/null +++ b/repo/order_confirmation_test.go @@ -0,0 +1,24 @@ +package repo + +import ( + "github.com/phoreproject/pm-go/pb" + "testing" +) + +func TestToV5OrderConfirmation(t *testing.T) { + var ( + orderConfirmation = &pb.OrderConfirmation{ + RequestedAmount: 10000, + } + newOrderConfirmation = ToV5OrderConfirmation(orderConfirmation) + expected = "10000" + ) + + if newOrderConfirmation.BigRequestedAmount != expected { + t.Errorf("Expected BigRequestedAmount of %s got %s", expected, orderConfirmation.BigRequestedAmount) + } + + if newOrderConfirmation.RequestedAmount != 0 { + t.Errorf("Expected RequestedAmount of 0, got %d", newOrderConfirmation.RequestedAmount) + } +} diff --git a/repo/order_fulfillment.go b/repo/order_fulfillment.go new file mode 100644 index 0000000000..bd9f5f0e46 --- /dev/null +++ b/repo/order_fulfillment.go @@ -0,0 +1,19 @@ +package repo + +import ( + "github.com/golang/protobuf/proto" + "github.com/phoreproject/pm-go/pb" + "math/big" +) + +// ToV5OrderFulfillment scans through the order fulfillment looking for any deprecated fields and +// turns them into their v5 counterpart. +func ToV5OrderFulfillment(orderFulfillment *pb.OrderFulfillment) *pb.OrderFulfillment { + newOrderFulfillment := proto.Clone(orderFulfillment).(*pb.OrderFulfillment) + + if orderFulfillment.Payout.PayoutFeePerByte != 0 && orderFulfillment.Payout.BigPayoutFeePerByte == "" { + newOrderFulfillment.Payout.BigPayoutFeePerByte = big.NewInt(int64(orderFulfillment.Payout.PayoutFeePerByte)).String() + newOrderFulfillment.Payout.PayoutFeePerByte = 0 + } + return newOrderFulfillment +} diff --git a/repo/order_fulfillment_test.go b/repo/order_fulfillment_test.go new file mode 100644 index 0000000000..5112623b04 --- /dev/null +++ b/repo/order_fulfillment_test.go @@ -0,0 +1,26 @@ +package repo + +import ( + "github.com/phoreproject/pm-go/pb" + "testing" +) + +func TestToV5OrderFulfillment(t *testing.T) { + var ( + orderFulfillment = &pb.OrderFulfillment{ + Payout: &pb.OrderFulfillment_Payout{ + PayoutFeePerByte: 10, + }, + } + newOrderFulfillment = ToV5OrderFulfillment(orderFulfillment) + expected = "10" + ) + + if newOrderFulfillment.Payout.BigPayoutFeePerByte != expected { + t.Errorf("Expected BigPayoutFeePerByte of %s got %s", expected, newOrderFulfillment.Payout.BigPayoutFeePerByte) + } + + if newOrderFulfillment.Payout.PayoutFeePerByte != 0 { + t.Errorf("Expected PayoutFeePerByte of 0, got %d", newOrderFulfillment.Payout.PayoutFeePerByte) + } +} diff --git a/repo/peer_info.go b/repo/peer_info.go new file mode 100644 index 0000000000..7d68fd7a63 --- /dev/null +++ b/repo/peer_info.go @@ -0,0 +1,213 @@ +package repo + +import ( + "bytes" + "errors" + "fmt" + + crypto "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" + peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + + "github.com/btcsuite/btcd/btcec" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" +) + +var ( + ErrInvalidInlinePeerID = errors.New("inline hash does not match produced hash") + ErrPeerInfoIsNil = errors.New("peer info is nil") +) + +func init() { + peer.AdvancedEnableInlining = false +} + +// NewPeerInfoFromProtobuf translates a pb.ID protobuf into a PeerInfo +func NewPeerInfoFromProtobuf(id *pb.ID) *PeerInfo { + return &PeerInfo{ + protobufPeerID: id.PeerID, + handle: id.Handle, + keychain: &PeerKeychain{ + identity: id.Pubkeys.Identity, + bitcoin: id.Pubkeys.Bitcoin, + }, + bitcoinSignature: id.BitcoinSig, + } +} + +// PeerKeychain holds bytes representing key material suitable for extracting with libp2p-crypto +type PeerKeychain struct { + bitcoin []byte + identity []byte +} + +// PeerInfo represents a signed identity on OpenBazaar +type PeerInfo struct { + protobufPeerID string + + handle string + keychain *PeerKeychain + bitcoinSignature []byte +} + +func (p *PeerInfo) String() string { + return fmt.Sprintf("&PeerInfo{protobufPeerID:%s handle:%s bitcoinSignature:%v keychain: &PeerKeychain{bitcoin:%v identity:%v}}", + p.protobufPeerID, + p.handle, + p.bitcoinSignature, + p.keychain.bitcoin, + p.keychain.identity, + ) +} + +func (p *PeerInfo) Handle() string { return p.handle } +func (p *PeerInfo) BitcoinSignature() []byte { + if p == nil { + return nil + } + var sig = make([]byte, len(p.bitcoinSignature)) + copy(sig, p.bitcoinSignature) + return sig +} + +// Hash returns the public hash based on the PeerKeychain.Identity key material +func (p *PeerInfo) Hash() (string, error) { + if p == nil { + return "", ErrPeerInfoIsNil + } + if p.protobufPeerID == "" { + return "", ErrInvalidInlinePeerID + } + return p.protobufPeerID, nil +} + +func (p *PeerInfo) GeneratePeerIDFromIdentityKey() (string, error) { + key, err := p.IdentityKey() + if err != nil { + return "", err + } + id, err := peer.IDFromPublicKey(key) + if err != nil { + return "", err + } + return id.Pretty(), nil +} +func (p *PeerInfo) BitcoinKey() []byte { + var key = make([]byte, len(p.keychain.bitcoin)) + copy(key, p.keychain.bitcoin) + return key +} +func (p *PeerInfo) IdentityKeyBytes() []byte { + var key = make([]byte, len(p.keychain.identity)) + copy(key, p.keychain.identity) + return key +} +func (p *PeerInfo) IdentityKey() (ipfs.PubKey, error) { + key, err := crypto.UnmarshalPublicKey(p.IdentityKeyBytes()) + if err != nil { + return nil, fmt.Errorf("unmarshaling identity key bytes: %s", err) + } + return key.(ipfs.PubKey), nil +} + +func (p *PeerInfo) Equal(other *PeerInfo) bool { + if p == nil || other == nil { + return false + } + if !bytes.Equal(p.IdentityKeyBytes(), other.IdentityKeyBytes()) { + return false + } + if !bytes.Equal(p.BitcoinKey(), other.BitcoinKey()) { + return false + } + if !bytes.Equal(p.BitcoinSignature(), other.BitcoinSignature()) { + return false + } + if p.handle != other.handle { + return false + } + tHash, err := p.Hash() + if err != nil { + return false + } + oHash, err := other.Hash() + if err != nil { + return false + } + if tHash != oHash { + return false + } + return true +} + +// Valid ensures the PeerInfo is valid as derived by the provided protobuf +func (p *PeerInfo) Valid() error { + if p == nil { + return ErrPeerInfoIsNil + } + if err := p.VerifyIdentity(); err != nil { + return err + } + if err := p.VerifyBitcoinSignature(); err != nil { + return err + } + // TODO: validate BitcoinSignature comes from bitcoin identity + return nil +} + +// VerifyIdentity checks that the peer id, identity key both agree +func (p *PeerInfo) VerifyIdentity() error { + hash, err := p.Hash() + if err != nil { + return fmt.Errorf("unable to produce peer hash: %s", err.Error()) + } + + peerID, err := peer.IDB58Decode(hash) + if err != nil { + return fmt.Errorf("decoding peer hash: %s", err.Error()) + } + pub, err := crypto.UnmarshalPublicKey(p.IdentityKeyBytes()) + if err != nil { + return fmt.Errorf("parsing identity key: %s", err.Error()) + } + if !peerID.MatchesPublicKey(pub) { + return ErrInvalidInlinePeerID + } + return nil +} + +// VerifyBitcoinSignature checks that the bitcoin key and the peer id both agree +func (p *PeerInfo) VerifyBitcoinSignature() error { + bitcoinPubkey, err := btcec.ParsePubKey(p.BitcoinKey(), btcec.S256()) + if err != nil { + return fmt.Errorf("parse bitcoin pubkey: %s", err.Error()) + } + bitcoinSig, err := btcec.ParseSignature(p.BitcoinSignature(), btcec.S256()) + if err != nil { + return fmt.Errorf("parse bitcoin signature: %s", err.Error()) + } + pid, err := p.Hash() + if err != nil { + return fmt.Errorf("get peer id: %s", err.Error()) + } + if !bitcoinSig.Verify([]byte(pid), bitcoinPubkey) { + return errors.New("bitcoin signature on peer id did not verify successfully") + } + return nil +} + +func (p *PeerInfo) Protobuf() *pb.ID { + peerHash, err := p.Hash() + if err != nil && p.protobufPeerID != "" { + peerHash = p.protobufPeerID + } + return &pb.ID{ + PeerID: peerHash, + Handle: p.handle, + Pubkeys: &pb.ID_Pubkeys{ + Bitcoin: p.BitcoinKey(), + Identity: p.IdentityKeyBytes(), + }, + BitcoinSig: p.bitcoinSignature, + } +} diff --git a/repo/peer_info_test.go b/repo/peer_info_test.go new file mode 100644 index 0000000000..1224dfb20d --- /dev/null +++ b/repo/peer_info_test.go @@ -0,0 +1,78 @@ +package repo_test + +import ( + "bytes" + "testing" + + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" +) + +func TestPeerInfoFromProtobuf(t *testing.T) { + var ( + validFixture = factory.MustNewPeerIDProtobuf() + subject = repo.NewPeerInfoFromProtobuf(validFixture) + ) + + if hash, err := subject.Hash(); err == nil && hash != validFixture.PeerID { + t.Errorf("expected Hash() to be (%s), but was (%s)", validFixture.PeerID, hash) + } + + if subject.Handle() != validFixture.Handle { + t.Errorf("expected Handle() to be (%s), but was (%s)", validFixture.Handle, subject.Handle()) + } + + if !bytes.Equal(subject.BitcoinSignature(), validFixture.BitcoinSig) { + t.Errorf("expected BitcoinSignature() to be (%s), but was (%s)", validFixture.BitcoinSig, subject.BitcoinSignature()) + } + + if !bytes.Equal(subject.BitcoinKey(), validFixture.Pubkeys.Bitcoin) { + t.Errorf("expected BitcoinKey() to be (%s), but was (%s)", validFixture.Pubkeys.Bitcoin, subject.BitcoinKey()) + } + + if !bytes.Equal(subject.IdentityKeyBytes(), validFixture.Pubkeys.Identity) { + t.Errorf("expected IdentityKey() to be (%s), but was (%s)", validFixture.Pubkeys.Identity, subject.IdentityKeyBytes()) + } + + newProto := subject.Protobuf() + duplicateSubject := repo.NewPeerInfoFromProtobuf(newProto) + + if !subject.Equal(duplicateSubject) { + t.Error("expected Protobuf() to produce recipricol of NewPeerInfoFromProtobuf, but did not") + t.Logf("\texpected: %+v\n", subject) + t.Logf("\tactual: %+v\n", duplicateSubject) + } +} + +func TestPeerInfoValid(t *testing.T) { + // MustNewValidPeerInfo forces a panic in the event internal logic has changed + factory.MustNewValidPeerInfo() + + var pp = factory.MustNewPeerIDProtobuf() + pp.PeerID = "invalidstring" + p := repo.NewPeerInfoFromProtobuf(pp) + + err := p.Valid() + if err == nil { + t.Fatal("expected peer info to not be valid") + } +} + +func TestNilPeerInfo(t *testing.T) { + var nilPeer *repo.PeerInfo + if nilPeer.Equal(nilPeer) { + t.Errorf("expected nil *PeerInfo.Equal() to be false, but was not") + } + + if err := nilPeer.Valid(); err == nil { + t.Errorf("expected nil *PeerInfo to be invalid, but was valid") + } + + h, err := nilPeer.Hash() + if h != "" { + t.Errorf("expected nil *PeerInfo.Hash() to be empty, but was not") + } + if err != repo.ErrPeerInfoIsNil { + t.Errorf("expected nil *PeerInfo.Hash() respond with the appropriate error, but did not") + } +} diff --git a/repo/profile.go b/repo/profile.go new file mode 100644 index 0000000000..442c856d84 --- /dev/null +++ b/repo/profile.go @@ -0,0 +1,292 @@ +package repo + +import ( + "errors" + "fmt" + "math/big" + "strconv" + + "github.com/OpenBazaar/jsonpb" + "github.com/golang/protobuf/proto" + "github.com/phoreproject/pm-go/pb" +) + +var ( + // ErrModeratorInfoMissing indicates when the moderator information is + // missing while also indicating they are a moderator + ErrModeratorInfoMissing = errors.New("moderator is enabled but information is missing") + // ErrMissingModeratorFee indicates the fee schedule is missing + ErrMissingModeratorFee = errors.New("moderator info is missing fee schedule") + // ErrUnknownModeratorFeeType indicates the feeType is unknown + ErrUnknownModeratorFeeType = errors.New("moderator fee type is unknown") + // ErrModeratorFeeHasNegativePercentage indicates when the percentage is non-positive but should be + ErrModeratorFeeHasNegativePercentage = errors.New("percentage moderator fee should not be negative") + // ErrFixedFeeHasNonZeroPercentage indicates when the percentage is not zero but should be + ErrFixedFeeHasNonZeroPercentage = errors.New("fixed moderator fee should have a zero percentage amount") + // ErrPercentageFeeHasFixedFee indicates that a fixed fee is included when there should not be + ErrPercentageFeeHasFixedFee = fmt.Errorf("percentage moderator fee should not include a fixed fee or should use (%s) feeType", pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE.String()) + // ErrModeratorFixedFeeIsMissing indicates when the fixed fee is missing + ErrModeratorFixedFeeIsMissing = fmt.Errorf("fixed moderator fee is missing or should use (%s) feeType", pb.Moderator_Fee_PERCENTAGE.String()) + // ErrModeratorFixedFeeAmountIsEmpty indicates the fee is defined with an empty amount + ErrModeratorFixedFeeAmountIsEmpty = errors.New("fixed moderator fee amount is missing or not a parseable number") + // ErrModeratorFixedFeeIsNegative indicates that the fixed fee is non-positive + ErrModeratorFixedFeeIsNegative = errors.New("fixed moderator fee is negative or not a parsable number") +) + +// Profile presents the user's metadata. The profile state is maintained within +// a *pb.Profile internally which captures all state changes suitable to be persisted +// via marshaling to JSON. This struct should ensure the integrity of *pb.Profile to +// its data as indicated by the set schema version. +type Profile struct { + profileProto *pb.Profile +} + +// UnmarshalJSONProfile consumes a JSON byte slice and returns a Profile-wrapped +// unmarshaled protobuf +func UnmarshalJSONProfile(data []byte) (*Profile, error) { + var ( + p = new(pb.Profile) + err = jsonpb.UnmarshalString(string(data), p) + ) + if err != nil { + return nil, err + } + return NewProfileFromProtobuf(p) +} + +// NewProfileFromProtobuf returns a Profile wrapped around a profile protobuf +func NewProfileFromProtobuf(p *pb.Profile) (*Profile, error) { + clonedProfile := proto.Clone(p).(*pb.Profile) + return &Profile{profileProto: clonedProfile}, nil +} + +// NormalizeDataForAllSchemas converts existing data from its current schema +// into legacy schema. This does not guarantee success as legacy schema that +// was abandoned due to unacceptable constraints will not be able to fulfill +// the full capability of the newer schema. (Ex: FixedFee.BigAmount can support +// full precision, whereas FixedFee.Amount is limited to math.MaxInt64 +func (p *Profile) NormalizeDataForAllSchemas() *Profile { + p.normalizeFees() + return p +} + +// GetProtobuf returns the underlying protobuf which represents the persistable +// state of the profile. (Note: This method is a shim to access data which isn't +// represented in this package's Profile methods. Consider adding missing getters +// and setters which repsect the schema version instead of using the protobuf +// directly for manipulation.) +func (p *Profile) GetProtobuf() *pb.Profile { + return p.profileProto +} + +// GetVersion returns the schema version for the profile protobuf +func (p *Profile) GetVersion() uint32 { + return p.profileProto.GetVersion() +} + +// GetModeratedFixedFee returns the fixed CurrencyValue for moderator services +// currently set on the Profile +func (p *Profile) GetModeratedFixedFee() (*CurrencyValue, error) { + if p.IsModerationEnabled() && + p.profileProto.ModeratorInfo.Fee != nil && + p.profileProto.ModeratorInfo.Fee.FixedFee != nil { + switch p.GetVersion() { + case 5: + var ( + amt = p.profileProto.ModeratorInfo.Fee.FixedFee.BigAmount + code = p.profileProto.ModeratorInfo.Fee.FixedFee.AmountCurrency + ) + return NewCurrencyValueFromProtobuf(amt, code) + default: // v4 and earlier + var ( + amt = strconv.Itoa(int(p.profileProto.ModeratorInfo.Fee.FixedFee.Amount)) + code = p.profileProto.ModeratorInfo.Fee.FixedFee.CurrencyCode + ) + return NewCurrencyValueWithLookup(amt, code) + + } + } + return nil, fmt.Errorf("fixed fee not found") +} + +// Valid indicates whether the Profile is valid by returning an error when +// any part of the data is not as expected +func (p *Profile) Valid() error { + if err := p.validateModeratorFees(); err != nil { + return err + } + return nil +} + +// IsModerationEnabled checks if the Moderator flag and info are present +func (p *Profile) IsModerationEnabled() bool { + return p != nil && + p.profileProto != nil && + p.profileProto.Moderator && + p.profileProto.ModeratorInfo != nil +} + +func (p *Profile) validateModeratorFees() error { + if p.profileProto.Moderator && p.profileProto.ModeratorInfo == nil { + return ErrModeratorInfoMissing + } + if !p.IsModerationEnabled() { + return nil + } + + // Moderator is true, Info is present + if p.profileProto.ModeratorInfo.Fee == nil { + return ErrMissingModeratorFee + } + + var validateFixedFee = func() error { + if p.profileProto.ModeratorInfo.Fee.FixedFee == nil { + return ErrModeratorFixedFeeIsMissing + } + if p.profileProto.ModeratorInfo.Fee.FixedFee.BigAmount == "" { + return ErrModeratorFixedFeeAmountIsEmpty + } + + feeCurrency, err := NewCurrencyValueFromProtobuf( + p.profileProto.ModeratorInfo.Fee.FixedFee.BigAmount, + p.profileProto.ModeratorInfo.Fee.FixedFee.AmountCurrency, + ) + if err != nil { + return err + } + if err := feeCurrency.Valid(); err != nil { + return fmt.Errorf("invalid fixed fee currency: %s", err.Error()) + } + if feeCurrency.IsNegative() { + return ErrModeratorFixedFeeIsNegative + } + return nil + } + + switch p.profileProto.ModeratorInfo.Fee.FeeType { + case pb.Moderator_Fee_FIXED: + if p.profileProto.ModeratorInfo.Fee.Percentage != 0 { + return ErrFixedFeeHasNonZeroPercentage + } + if err := validateFixedFee(); err != nil { + return err + } + case pb.Moderator_Fee_PERCENTAGE: + if p.profileProto.ModeratorInfo.Fee.Percentage < 0 { + return ErrModeratorFeeHasNegativePercentage + } + if p.profileProto.ModeratorInfo.Fee.FixedFee != nil { + amt, ok := new(big.Int).SetString(p.profileProto.ModeratorInfo.Fee.FixedFee.BigAmount, 10) + if ok && amt.Cmp(big.NewInt(0)) != 0 { + return ErrPercentageFeeHasFixedFee + } + } + case pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE: + if p.profileProto.ModeratorInfo.Fee.Percentage < 0 { + return ErrModeratorFeeHasNegativePercentage + } + if err := validateFixedFee(); err != nil { + return err + } + default: + return ErrUnknownModeratorFeeType + } + + return nil +} + +// DisableModeration sets the profile so moderationr is disabled and +// all fee schedules are removed +func (p *Profile) DisableModeration() error { + p.profileProto.Moderator = false + p.profileProto.ModeratorInfo = nil + return nil +} + +// normalizeFees ensures the fee schedule is readable for as +// many other nodes as possible by populating prior version schema +func (p *Profile) normalizeFees() { + if p.profileProto.ModeratorInfo != nil && p.profileProto.ModeratorInfo.Fee != nil { + var fees = p.profileProto.ModeratorInfo.Fee + switch fees.FeeType { + case pb.Moderator_Fee_FIXED: + fees.Percentage = 0 + case pb.Moderator_Fee_PERCENTAGE: + fees.FixedFee = nil + } + + if ff, err := p.GetModeratedFixedFee(); err == nil { + switch p.GetVersion() { + case 5: + var amtInt uint64 + if ai, err := strconv.Atoi(p.profileProto.ModeratorInfo.Fee.FixedFee.BigAmount); err == nil { + amtInt = uint64(ai) + } + p.profileProto.ModeratorInfo.Fee.FixedFee.CurrencyCode = ff.Currency.Code.String() + p.profileProto.ModeratorInfo.Fee.FixedFee.Amount = amtInt + default: // v4 and earlier + p.profileProto.ModeratorInfo.Fee.FixedFee.AmountCurrency = &pb.CurrencyDefinition{ + Code: ff.Currency.Code.String(), + Divisibility: uint32(ff.Currency.Divisibility), + } + p.profileProto.ModeratorInfo.Fee.FixedFee.BigAmount = ff.Amount.String() + } + } + } +} + +// SetModeratorFixedFee sets the profile to be a moderator with a +// fixed fee schedule +func (p *Profile) SetModeratorFixedFee(fee *CurrencyValue) error { + p.profileProto.Moderator = true + p.profileProto.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED, + FixedFee: &pb.Moderator_Price{ + BigAmount: fee.Amount.String(), + AmountCurrency: &pb.CurrencyDefinition{ + Code: fee.Currency.Code.String(), + Divisibility: uint32(fee.Currency.Divisibility), + }, + }, + Percentage: 0, + }, + } + p.normalizeFees() + return nil +} + +// SetModeratorFixedPlusPercentageFee sets the profile to be a moderator +// with a fixed fee plus percentage schedule +func (p *Profile) SetModeratorFixedPlusPercentageFee(fee *CurrencyValue, percentage float32) error { + p.profileProto.Moderator = true + p.profileProto.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE, + FixedFee: &pb.Moderator_Price{ + BigAmount: fee.Amount.String(), + AmountCurrency: &pb.CurrencyDefinition{ + Code: fee.Currency.Code.String(), + Divisibility: uint32(fee.Currency.Divisibility), + }, + }, + Percentage: percentage, + }, + } + p.normalizeFees() + return nil +} + +// SetModeratorPercentageFee sets the profile to be a moderator with a +// percentage fee schedule +func (p *Profile) SetModeratorPercentageFee(percentage float32) error { + p.profileProto.Moderator = true + p.profileProto.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_PERCENTAGE, + FixedFee: nil, + Percentage: percentage, + }, + } + return nil +} diff --git a/repo/profile_test.go b/repo/profile_test.go new file mode 100644 index 0000000000..5d4f246f5e --- /dev/null +++ b/repo/profile_test.go @@ -0,0 +1,720 @@ +package repo_test + +import ( + "strconv" + "strings" + "testing" + + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test/factory" +) + +func TestProfileFromProtobufMissingModInfo(t *testing.T) { + p := factory.MustNewProfileProtobuf() + p.ModeratorInfo = nil + + if _, err := repo.NewProfileFromProtobuf(p); err != nil { + t.Errorf("expected missing ModeratorInfo to be valid, but errored (%s)", err.Error()) + } +} + +func TestProfileNormalizeSchema(t *testing.T) { + var ( + exampleFee = &pb.Moderator_Price{ + BigAmount: "10", + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + } + ) + var examples = []struct { + example func() *pb.Profile + validate func(*pb.Profile) + }{ + { // profile with percent fee should remove non-percent fee values + example: func() *pb.Profile { + p := factory.MustNewProfileProtobuf() + p.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_PERCENTAGE + p.ModeratorInfo.Fee.FixedFee = exampleFee + p.ModeratorInfo.Fee.Percentage = 1.1 + return p + }, + validate: func(p *pb.Profile) { + if p.ModeratorInfo.Fee.FixedFee != nil { + t.Errorf("expected fixed fee to be removed, but was not") + } + }, + }, + { // profile with fixed fee should zero percentage + example: func() *pb.Profile { + p := factory.MustNewProfileProtobuf() + p.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_FIXED + p.ModeratorInfo.Fee.FixedFee = exampleFee + p.ModeratorInfo.Fee.Percentage = 1.1 + return p + }, + validate: func(p *pb.Profile) { + if p.ModeratorInfo.Fee.Percentage != 0 { + t.Errorf("expected percentage to be zero, but was not") + } + }, + }, + { // profile with fixed fee should populate legacy schema + example: func() *pb.Profile { + p := factory.MustNewProfileProtobuf() + p.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_FIXED + p.ModeratorInfo.Fee.FixedFee = exampleFee + return p + }, + validate: func(p *pb.Profile) { + if actual := p.ModeratorInfo.Fee.FixedFee.CurrencyCode; actual != exampleFee.AmountCurrency.Code { + t.Errorf("expected legacy code to be (%s), but was (%s)", exampleFee.AmountCurrency.Code, actual) + } + expectedAmt, err := strconv.Atoi(exampleFee.BigAmount) + if err != nil { + t.Error(err) + return + } + if actualAmt := p.ModeratorInfo.Fee.FixedFee.Amount; actualAmt != uint64(expectedAmt) { + t.Errorf("expected legacy amount to be (%d), but was (%d)", expectedAmt, actualAmt) + } + }, + }, + { // legacy v4 profile with fixed fee should populate current schema + example: func() *pb.Profile { + pb := factory.MustLoadProfileFixture("v4-profile-moderator-fixed-fee") + rp, err := repo.UnmarshalJSONProfile(pb) + if err != nil { + t.Fatal(err) + } + p := rp.GetProtobuf() + p.ModeratorInfo.Fee.FixedFee.CurrencyCode = "BTC" + p.ModeratorInfo.Fee.FixedFee.Amount = 10 + return p + }, + validate: func(p *pb.Profile) { + if actual := p.ModeratorInfo.Fee.FixedFee.AmountCurrency.Code; actual != "BTC" { + t.Errorf("expected fee amount currency code to be (%s), but was (%s)", "BTC", actual) + } + if actualAmt := p.ModeratorInfo.Fee.FixedFee.BigAmount; actualAmt != "10" { + t.Errorf("expected fee amount to be (%s), but was (%s)", "10", actualAmt) + } + }, + }, + } + + for i, e := range examples { + var ( + subject = e.example() + p, err = repo.NewProfileFromProtobuf(subject) + ) + if err != nil { + t.Errorf("failed normalization on example (%d): %s", i, err) + continue + } + p.NormalizeDataForAllSchemas() + e.validate(p.GetProtobuf()) + } +} + +func TestProfileFactoryIsValid(t *testing.T) { + p := factory.MustNewProfile() + if err := p.Valid(); err != nil { + t.Log(err) + t.Error("expected factory profile to be valid") + } +} + +func TestProfileInvalidWithUnknownFeeType(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_FeeType(-1) + + if err := p.Valid(); err == nil { + t.Errorf("expected profile to be invalid with unknown fee type") + } else if err != repo.ErrUnknownModeratorFeeType { + t.Errorf("expected ErrUnknownModeratorFeeType error, but was (%s)", err.Error()) + } +} + +func TestProfileValidWithoutModeratorInfo(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.Moderator = false + pp.ModeratorInfo = nil + + if err := p.Valid(); err != nil { + t.Error("expected profile to be valid without moderator info, but wasn't") + } +} + +func TestProfileValidWithModeratorInfoAndModerationDisabled(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.Moderator = false + pp.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_PERCENTAGE, + Percentage: 0, + }, + } + + if err := p.Valid(); err != nil { + t.Errorf("expected profile to be valid with moderator info and moderation disabled, but errored (%s)", err) + } +} + +func TestProfileInvalidWithoutModeratorFee(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo.Fee = nil + + if err := p.Valid(); err == nil { + t.Errorf("expected profile without fee schedule to be invalid") + } else if err != repo.ErrMissingModeratorFee { + t.Errorf("expected ErrMissingModeratorFee error, but was (%s)", err.Error()) + } +} + +func TestProfileInvalidWithMissingFixedFee(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_FIXED + pp.ModeratorInfo.Fee.FixedFee = nil + + if err := p.Valid(); err == nil { + t.Errorf("expected profile with fixed feeType but missing fee to be invalid") + } else if err != repo.ErrModeratorFixedFeeIsMissing { + t.Errorf("expected ErrModeratorFixedFeeIsMissing error, but was (%s)", err.Error()) + } +} + +func TestProfileInvalidWithInvalidFixedFeeCurrency(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo.Fee.FixedFee = &pb.Moderator_Price{ + BigAmount: "1", + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 0, // 0 divisibility is invalid + }, + } + + // test fixed fee + pp.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_FIXED + if err := p.Valid(); err == nil { + t.Errorf("expected profile with invalid currency to be invalid") + } else if !strings.Contains(err.Error(), "invalid fixed fee currency") { + t.Errorf("expected (invalid fixed fee currency) in error, but got (%s)", err.Error()) + } + + // test fixed fee plus percentage + pp.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE + pp.ModeratorInfo.Fee.Percentage = 1.1 + if err := p.Valid(); err == nil { + t.Errorf("expected profile with invalid currency to be invalid") + } else if !strings.Contains(err.Error(), "invalid fixed fee currency") { + t.Errorf("expected (invalid fixed fee currency) in error, but got (%s)", err.Error()) + } +} + +func TestProfileInvalidWithZeroFixedFee(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + + // test fixed fee + pp.ModeratorInfo.Fee = &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED, + FixedFee: &pb.Moderator_Price{ + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + BigAmount: "0", + }, + } + if err := p.Valid(); err != nil { + t.Errorf("expected profile with zero fee to be valid, but errored: %s", err.Error()) + } + + pp.ModeratorInfo.Fee = &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED, + FixedFee: &pb.Moderator_Price{ + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + BigAmount: "-1", + }, + } + if err := p.Valid(); err == nil { + t.Errorf("expected profile with negative fee to be invalid") + } else if err != repo.ErrModeratorFixedFeeIsNegative { + t.Errorf("expected ErrModeratorFixedFeeIsNegative error, but was (%s)", err.Error()) + } + + pp.ModeratorInfo.Fee = &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED, + FixedFee: &pb.Moderator_Price{ + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + BigAmount: "", + }, + } + if err := p.Valid(); err == nil { + t.Errorf("expected profile with empty fee amount to be invalid") + } else if err != repo.ErrModeratorFixedFeeAmountIsEmpty { + t.Errorf("expected ErrModeratorFixedFeeAmountIsEmpty error, but was (%s)", err.Error()) + } + + // test fixed fee plus percentage + pp.ModeratorInfo.Fee = &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE, + FixedFee: &pb.Moderator_Price{ + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + BigAmount: "0", + }, + Percentage: 1.1, + } + if err := p.Valid(); err != nil { + t.Errorf("expected profile with zero fee to be valid, but errored: %s", err.Error()) + } + + pp.ModeratorInfo.Fee = &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE, + FixedFee: &pb.Moderator_Price{ + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + BigAmount: "-1", + }, + Percentage: 1.1, + } + if err := p.Valid(); err == nil { + t.Errorf("expected profile with negative fee to be invalid") + } else if err != repo.ErrModeratorFixedFeeIsNegative { + t.Errorf("expected ErrModeratorFixedFeeIsNegative error, but was (%s)", err.Error()) + } + + pp.ModeratorInfo.Fee = &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE, + FixedFee: &pb.Moderator_Price{ + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + BigAmount: "", + }, + Percentage: 1.1, + } + if err := p.Valid(); err == nil { + t.Errorf("expected profile with empty fee amount to be invalid") + } else if err != repo.ErrModeratorFixedFeeAmountIsEmpty { + t.Errorf("expected ErrModeratorFixedFeeAmountIsEmpty error, but was (%s)", err.Error()) + } +} + +func TestProfileValidFixedFee(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + + pp.ModeratorInfo.Fee = &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED, + FixedFee: &pb.Moderator_Price{ + BigAmount: "1234", + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + }, + Percentage: 0, + } + + if err := p.Valid(); err != nil { + t.Error("expected profile example to be valid") + } + + pp.ModeratorInfo.Fee.Percentage = 1.1 + if err := p.Valid(); err == nil { + t.Errorf("expected non-zero percentage to be invalid") + } else if err != repo.ErrFixedFeeHasNonZeroPercentage { + t.Errorf("expected ErrFixedFeeHasNonZeroPercentage error, but was (%s)", err.Error()) + } +} + +func TestProfileValidPercentageFee(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_PERCENTAGE, + Percentage: 1.1, + }, + } + + if err := p.Valid(); err != nil { + t.Errorf("expected profile example to be valid") + } +} + +func TestProfileValidPercentageFeeZero(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_PERCENTAGE, + Percentage: 0, + }, + } + + if err := p.Valid(); err != nil { + t.Errorf("expected profile example to be valid") + } +} + +func TestProfileInvalidPercentageFeeWithFixedFee(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_PERCENTAGE, + Percentage: 1, + FixedFee: &pb.Moderator_Price{ + BigAmount: "1234", + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + }, + }, + } + + if err := p.Valid(); err == nil { + t.Errorf("expected percentage fee with fixed fee to be invalid") + } else if err != repo.ErrPercentageFeeHasFixedFee { + t.Errorf("expected ErrPercentageFeeHasFixedFee error, but was (%s)", err.Error()) + } +} + +func TestProfileValidPercentageWithFixedFee(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE, + Percentage: 1, + FixedFee: &pb.Moderator_Price{ + BigAmount: "1234", + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + }, + }, + } + + if err := p.Valid(); err != nil { + t.Errorf("expected profile exmaple to be valid") + } +} + +func TestProfileValidPercentWithFixedHavingZeroPercent(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE, + Percentage: 0, + FixedFee: &pb.Moderator_Price{ + BigAmount: "1234", + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + }, + }, + } + + if err := p.Valid(); err != nil { + t.Errorf("expected profile exmaple to be valid") + } +} + +func TestProfileInvalidPercentWithFixedHavingNegativePercent(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE, + Percentage: -1, + FixedFee: &pb.Moderator_Price{ + BigAmount: "1234", + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + }, + }, + } + + if err := p.Valid(); err == nil { + t.Errorf("expected percentage with fixed fee but negative percentage to be invalid") + } else if err != repo.ErrModeratorFeeHasNegativePercentage { + t.Errorf("expected ErrModeratorFeeHasNegativePercentage error, but got (%s)", err.Error()) + } +} + +func TestProfileInvalidPercentWithFixedHavingNoFixedFee(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo = &pb.Moderator{ + Fee: &pb.Moderator_Fee{ + FeeType: pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE, + Percentage: 1.1, + FixedFee: nil, + }, + } + + if err := p.Valid(); err == nil { + t.Errorf("expected percentage with fixed fee but fixed fee is missing to be invalid") + } else if err != repo.ErrModeratorFixedFeeIsMissing { + t.Errorf("expected ErrModeratorFixedFeeIsMissing error, but got (%s)", err.Error()) + } +} + +func TestProfileInvalidAsModeratorWithoutInfo(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.Moderator = true + pp.ModeratorInfo = nil + + if err := p.Valid(); err == nil { + t.Errorf("expected moderator without info to be invalid") + } else if err != repo.ErrModeratorInfoMissing { + t.Errorf("expected ErrModeratorInfoMissing error, but got (%s)", err.Error()) + } +} + +func TestProfileGetModeratedFixedFee(t *testing.T) { + var examples = []string{ + "v0-profile-moderator-fixed-fee", + "v4-profile-moderator-fixed-fee", + "v5-profile-moderator-fixed-fee", + } + + for _, e := range examples { + var ( + fixtureBytes = factory.MustLoadProfileFixture(e) + actualProfile, err = repo.UnmarshalJSONProfile(fixtureBytes) + ) + if err != nil { + t.Errorf("unmarshal (%s): %s", e, err) + continue + } + + fee, err := actualProfile.GetModeratedFixedFee() + if err != nil { + t.Errorf("fixed fee (%s): %s", e, err) + continue + } + + // all profile fixtures have equivalent data + // validate they are intepreted from their resepctive schemas + if fee.Amount.String() != "100" { + t.Errorf("amount (%s): expected (%s), got (%s)", e, "100", fee.Amount.String()) + } + if fee.Currency.Code.String() != "USD" { + t.Errorf("currency code (%s): expected (%s), got (%s)", e, "USD", fee.Currency.Code.String()) + } + if fee.Currency.Divisibility != 2 { + t.Errorf("currency code (%s): expected (%d), got (%d)", e, 2, fee.Currency.Divisibility) + } + } +} + +func TestProfileSetModeratorFixedFee(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE + pp.ModeratorInfo.Fee.FixedFee = nil + pp.ModeratorInfo.Fee.Percentage = 1.1 + + fee, err := repo.NewCurrencyValueWithLookup("123", "USD") + if err != nil { + t.Fatalf("failed creating fee value: %s", err.Error()) + } + + if err := p.SetModeratorFixedFee(fee); err != nil { + t.Fatalf("failed setting fee: %s", err.Error()) + } + + if !pp.Moderator { + t.Errorf("expected Moderator flag to be true") + } + if pp.ModeratorInfo.Fee.FeeType != pb.Moderator_Fee_FIXED { + t.Errorf("expected feeType to be (%s), but was (%s)", pb.Moderator_Fee_FIXED.String(), pp.ModeratorInfo.Fee.FeeType) + } + if pp.ModeratorInfo.Fee.Percentage != 0 { + t.Fatalf("expected percentage to be zero") + } + if pp.ModeratorInfo.Fee.FixedFee == nil { + t.Fatalf("expected fixedFee to not be nil") + } + actualValue, err := repo.NewCurrencyValueFromProtobuf( + pp.ModeratorInfo.Fee.FixedFee.BigAmount, + pp.ModeratorInfo.Fee.FixedFee.AmountCurrency, + ) + if err != nil { + t.Fatal(err) + } + if !fee.Equal(actualValue) { + t.Errorf("expected fixed fee amount currency to be (%s), but was (%s)", fee.String(), actualValue.String()) + } +} + +func TestProfileSetModeratorFixedPlusPercentageFee(t *testing.T) { + percentage := float32(2.5) + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_PERCENTAGE + pp.ModeratorInfo.Fee.FixedFee = nil + pp.ModeratorInfo.Fee.Percentage = 1.1 + + fee, err := repo.NewCurrencyValueWithLookup("123", "USD") + if err != nil { + t.Fatalf("failed creating fee value: %s", err.Error()) + } + + if err := p.SetModeratorFixedPlusPercentageFee(fee, percentage); err != nil { + t.Fatalf("failed setting fee: %s", err.Error()) + } + + if !pp.Moderator { + t.Errorf("expected Moderator flag to be true") + } + if pp.ModeratorInfo.Fee.FeeType != pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE { + t.Errorf("expected feeType to be (%s), but was (%s)", pb.Moderator_Fee_FIXED_PLUS_PERCENTAGE.String(), pp.ModeratorInfo.Fee.FeeType) + } + if pp.ModeratorInfo.Fee.Percentage != percentage { + t.Fatalf("expected percentage to be zero") + } + if pp.ModeratorInfo.Fee.FixedFee == nil { + t.Fatalf("expected fixedFee to not be nil") + } + actualValue, err := repo.NewCurrencyValueFromProtobuf( + pp.ModeratorInfo.Fee.FixedFee.BigAmount, + pp.ModeratorInfo.Fee.FixedFee.AmountCurrency, + ) + if err != nil { + t.Fatal(err) + } + if !fee.Equal(actualValue) { + t.Errorf("expected fixed fee amount currency to be (%s), but was (%s)", fee.String(), actualValue.String()) + } +} + +func TestProfileSetModeratorPercentageFee(t *testing.T) { + percentage := float32(2.5) + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_FIXED + pp.ModeratorInfo.Fee.FixedFee = &pb.Moderator_Price{ + BigAmount: "1230", + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + } + pp.ModeratorInfo.Fee.Percentage = 0 + + if err := p.SetModeratorPercentageFee(percentage); err != nil { + t.Fatalf("failed setting fee: %s", err.Error()) + } + + if !pp.Moderator { + t.Errorf("expected Moderator flag to be true") + } + if pp.ModeratorInfo.Fee.FeeType != pb.Moderator_Fee_PERCENTAGE { + t.Errorf("expected feeType to be (%s), but was (%s)", pb.Moderator_Fee_PERCENTAGE.String(), pp.ModeratorInfo.Fee.FeeType) + } + if pp.ModeratorInfo.Fee.Percentage != percentage { + t.Fatalf("expected percentage to be zero") + } + if pp.ModeratorInfo.Fee.FixedFee != nil { + t.Fatalf("expected fixedFee to be nil") + } +} + +func TestProfileDisableModeration(t *testing.T) { + var ( + p = factory.MustNewProfile() + pp = p.GetProtobuf() + ) + pp.Moderator = true + pp.ModeratorInfo.Fee.FeeType = pb.Moderator_Fee_FIXED + pp.ModeratorInfo.Fee.FixedFee = &pb.Moderator_Price{ + BigAmount: "1230", + AmountCurrency: &pb.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + }, + } + pp.ModeratorInfo.Fee.Percentage = 0 + + if err := p.DisableModeration(); err != nil { + t.Fatalf("failed disabling moderation: %s", err.Error()) + } + + if pp.Moderator { + t.Errorf("expected Moderator flag to be false") + } + if pp.ModeratorInfo != nil { + t.Errorf("expected ModeratorInfo to be nil") + } +} diff --git a/repo/purchase_record.go b/repo/purchase_record.go index 251f81b77a..79d563db9d 100644 --- a/repo/purchase_record.go +++ b/repo/purchase_record.go @@ -3,7 +3,7 @@ package repo import ( "time" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) var ( diff --git a/repo/purchase_record_test.go b/repo/purchase_record_test.go index 61acf04896..9273870f9b 100644 --- a/repo/purchase_record_test.go +++ b/repo/purchase_record_test.go @@ -3,8 +3,8 @@ package repo_test import ( "testing" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/test/factory" ) func TestPurchaseRecordIsDisputeable(t *testing.T) { diff --git a/repo/refund.go b/repo/refund.go new file mode 100644 index 0000000000..a11d4036db --- /dev/null +++ b/repo/refund.go @@ -0,0 +1,19 @@ +package repo + +import ( + "github.com/golang/protobuf/proto" + "github.com/phoreproject/pm-go/pb" + "math/big" +) + +// ToV5Refund scans through the refund looking for any deprecated fields and +// turns them into their v5 counterpart. +func ToV5Refund(refund *pb.Refund) *pb.Refund { + newRefund := proto.Clone(refund).(*pb.Refund) + + if refund.RefundTransaction.Value != 0 && refund.RefundTransaction.BigValue == "" { + newRefund.RefundTransaction.BigValue = big.NewInt(int64(refund.RefundTransaction.Value)).String() + newRefund.RefundTransaction.Value = 0 + } + return newRefund +} diff --git a/repo/refund_test.go b/repo/refund_test.go new file mode 100644 index 0000000000..cd129c7e7b --- /dev/null +++ b/repo/refund_test.go @@ -0,0 +1,26 @@ +package repo + +import ( + "github.com/phoreproject/pm-go/pb" + "testing" +) + +func TestToV5OrderRefund(t *testing.T) { + var ( + refund = &pb.Refund{ + RefundTransaction: &pb.Refund_TransactionInfo{ + Value: 10000, + }, + } + newRefund = ToV5Refund(refund) + expected = "10000" + ) + + if newRefund.RefundTransaction.BigValue != expected { + t.Errorf("Expected BigValue of %s got %s", expected, newRefund.RefundTransaction.BigValue) + } + + if newRefund.RefundTransaction.Value != 0 { + t.Errorf("Expected Value of 0, got %d", newRefund.RefundTransaction.Value) + } +} diff --git a/repo/sale_record.go b/repo/sale_record.go index 405ee6ae52..2f36eee162 100644 --- a/repo/sale_record.go +++ b/repo/sale_record.go @@ -4,7 +4,7 @@ import ( "strings" "time" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) var ( @@ -27,7 +27,7 @@ type SaleRecord struct { func (r *SaleRecord) SupportsTimedEscrowRelease() bool { if r.Contract.BuyerOrder != nil && r.Contract.BuyerOrder.Payment != nil { - switch strings.ToUpper(r.Contract.BuyerOrder.Payment.Coin) { + switch strings.ToUpper(r.Contract.BuyerOrder.Payment.AmountCurrency.Code) { case "BTC": return true case "TBTC": @@ -44,6 +44,10 @@ func (r *SaleRecord) SupportsTimedEscrowRelease() bool { return false case "TZEC": return false + case "ETH": + return true + case "TETH": + return true } } return false diff --git a/repo/sale_record_test.go b/repo/sale_record_test.go index 0f6d55ca98..71b2e24e9a 100644 --- a/repo/sale_record_test.go +++ b/repo/sale_record_test.go @@ -3,8 +3,8 @@ package repo_test import ( "testing" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/test/factory" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/test/factory" ) func TestSaleRecordIsDisputeable(t *testing.T) { @@ -101,7 +101,7 @@ func TestSaleRecord_SupportsTimedEscrowRelease(t *testing.T) { } subject := factory.NewSaleRecord() for _, test := range tests { - subject.Contract.BuyerOrder.Payment.Coin = test.currency + subject.Contract.BuyerOrder.Payment.AmountCurrency = &pb.CurrencyDefinition{Code: test.currency, Divisibility: 8} supportsEscrowRelease := subject.SupportsTimedEscrowRelease() if supportsEscrowRelease != test.supportsEscrowRelease { t.Errorf("SupportsEscrowRelease test failed for %s."+ diff --git a/repo/signed_listing.go b/repo/signed_listing.go new file mode 100644 index 0000000000..a1016a4185 --- /dev/null +++ b/repo/signed_listing.go @@ -0,0 +1,159 @@ +package repo + +import ( + "errors" + "fmt" + + peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + + "github.com/OpenBazaar/jsonpb" + "github.com/golang/protobuf/proto" + "github.com/phoreproject/pm-go/pb" +) + +// UnmarshalJSONSignedListing extracts a SignedListing from marshaled JSON +func UnmarshalJSONSignedListing(data []byte) (SignedListing, error) { + var ( + sl = new(pb.SignedListing) + err = jsonpb.UnmarshalString(string(data), sl) + ) + if err != nil { + return SignedListing{}, err + } + return SignedListing{ + signedListingProto: sl, + }, nil +} + +func NewSignedListingFromProtobuf(sl *pb.SignedListing) SignedListing { + return SignedListing{ + signedListingProto: sl, + } +} + +// SignedListing represents a finalized listing which has been +// signed by the vendor +type SignedListing struct { + signedListingProto *pb.SignedListing + + proto.Message +} + +func (l *SignedListing) Reset() { *l = SignedListing{} } +func (l *SignedListing) String() string { return proto.CompactTextString(l) } +func (*SignedListing) ProtoMessage() {} + +// Normalize is a helper method which will mutate the listing protobuf +// in-place but maintain the original signature for external verification +// purposes. +func (l *SignedListing) Normalize() error { + nl, err := l.GetListing().Normalize() + if err != nil { + return err + } + + l.signedListingProto.Listing = nl.listingProto + return nil +} + +// GetListing returns the underlying repo.Listing object +func (l SignedListing) GetListing() *Listing { + return &Listing{ + listingProto: l.signedListingProto.Listing, + } +} + +// GetVersion returns the schema version +func (l SignedListing) GetVersion() uint32 { return l.GetListing().GetVersion() } + +// GetVendorID returns the PeerInfo for the listing +func (l SignedListing) GetVendorID() *PeerInfo { return l.GetListing().GetVendorID() } + +// GetTitle returns the title +func (l SignedListing) GetTitle() string { return l.GetListing().GetTitle() } + +// GetSlug returns the slug +func (l SignedListing) GetSlug() string { return l.GetListing().GetSlug() } + +// GetPrice returns the price +func (l SignedListing) GetPrice() (*CurrencyValue, error) { return l.GetListing().GetPrice() } + +// GetAcceptedCurrencies returns the list of currencies which the listing +// may be purchased with +func (l SignedListing) GetAcceptedCurrencies() []string { + return l.GetListing().GetAcceptedCurrencies() +} + +// GetCryptoDivisibility returns the divisibility of a cryptocurrency's +// listing sold inventory +func (l SignedListing) GetCryptoDivisibility() uint32 { return l.GetListing().GetCryptoDivisibility() } + +// GetCryptoCurrencyCode returns the currency code of the sold +// cryptocurrency listing +func (l SignedListing) GetCryptoCurrencyCode() string { return l.GetListing().GetCryptoCurrencyCode() } + +// GetSignature returns the signature on the listing +func (l SignedListing) GetSignature() []byte { + return l.signedListingProto.GetSignature() +} + +// GetListingSigProtobuf returns the protobuf signature suitable for attaching +// to a pb.RicardianContract +func (l SignedListing) GetListingSigProtobuf() *pb.Signature { + return &pb.Signature{ + Section: pb.Signature_LISTING, + SignatureBytes: l.GetSignature(), + } +} + +func (l SignedListing) MarshalJSON() ([]byte, error) { + m := jsonpb.Marshaler{ + EnumsAsInts: false, + EmitDefaults: false, + Indent: " ", + OrigName: false, + } + lb, err := m.MarshalToString(l.signedListingProto) + if err != nil { + return nil, err + } + return []byte(lb), nil +} + +// ValidateListing ensures all listing state is valid +func (l SignedListing) ValidateListing(isTestnet bool) error { + return l.GetListing().ValidateListing(isTestnet) +} + +// VerifySignature checks the listings signature was produced by the vendor's +// Identity key and that the key was derived from the vendor's peerID +func (l SignedListing) VerifySignature() error { + ser, err := l.GetListing().MarshalProtobuf() + if err != nil { + return fmt.Errorf("marshaling listing: %s", err.Error()) + } + pubkey, err := l.GetListing().GetVendorID().IdentityKey() + if err != nil { + return fmt.Errorf("getting identity pubkey: %s", err.Error()) + } + valid, err := pubkey.Verify(ser, l.GetSignature()) + if err != nil { + return fmt.Errorf("verifying signature: %s", err.Error()) + } + if !valid { + return errors.New("identity signature on contract failed to verify") + } + + peerHash, err := l.GetListing().GetVendorID().Hash() + if err != nil { + return fmt.Errorf("get peer id: %s", err.Error()) + } + pid, err := peer.IDB58Decode(peerHash) + if err != nil { + return fmt.Errorf("decoding peer id: %s", err.Error()) + } + if !pid.MatchesPublicKey(pubkey) { + return errors.New("vendor's identity key does not match peer id") + } + return nil +} diff --git a/repo/signed_listing_test.go b/repo/signed_listing_test.go new file mode 100644 index 0000000000..8b8e2512b1 --- /dev/null +++ b/repo/signed_listing_test.go @@ -0,0 +1,326 @@ +package repo_test + +import ( + "bytes" + "crypto/rand" + crypto "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto" + peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" + "math/big" + "testing" + + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/test" + "github.com/phoreproject/pm-go/test/factory" +) + +func TestListingUnmarshalJSONSignedListing(t *testing.T) { + var examples = []string{ + "v3-physical-good", + "v4-physical-good", + "v4-digital-good", + "v4-service", + "v4-cryptocurrency", + "v5-physical-good", + } + + for _, e := range examples { + var ( + fixtureBytes = factory.MustLoadListingFixture(e) + _, err = repo.UnmarshalJSONSignedListing(fixtureBytes) + ) + if err != nil { + t.Errorf("exmaple (%s): %s", e, err) + } + } +} + +// nolint:dupl +func TestSignedListingAttributes(t *testing.T) { + var examples = []struct { + fixtureName string + expectedSchemaVersion uint32 + expectedTitle string + expectedSlug string + expectedPrice *repo.CurrencyValue + expectedAcceptedCurrencies []string + expectedCryptoDivisibility uint32 + expectedCryptoCurrencyCode string + }{ + { + fixtureName: "v3-physical-good", + expectedSchemaVersion: 3, + expectedTitle: "Physical Listing", + expectedSlug: "physical-listing", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(1235000000), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("BCH"), + Divisibility: 8, + CurrencyType: "crypto", + }, + }, + expectedAcceptedCurrencies: []string{"BCH"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + { + fixtureName: "v4-physical-good", + expectedSchemaVersion: 4, + expectedTitle: "Physical Good Listing", + expectedSlug: "physical-good-listing", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(12345678000), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("BCH"), + Divisibility: 8, + CurrencyType: "crypto", + }, + }, + expectedAcceptedCurrencies: []string{"ZEC", "LTC", "BTC", "BCH"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + { + fixtureName: "v4-digital-good", + expectedSchemaVersion: 4, + expectedTitle: "Digital Good Listing", + expectedSlug: "digital-good-listing", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(1320), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("USD"), + Divisibility: 2, + CurrencyType: "fiat", + }, + }, + expectedAcceptedCurrencies: []string{"ZEC"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + { + fixtureName: "v4-service", + expectedSchemaVersion: 4, + expectedTitle: "Service Listing", + expectedSlug: "service-listing", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(9877000000), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("BTC"), + Divisibility: 8, + CurrencyType: "crypto", + }, + }, + expectedAcceptedCurrencies: []string{"ZEC", "LTC", "BCH", "BTC"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + { + fixtureName: "v4-cryptocurrency", + expectedSchemaVersion: 4, + expectedTitle: "LTC-XMR", + expectedSlug: "ltc-xmr", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(0), + Currency: repo.NewUnknownCryptoDefinition("XMR", 0), + }, + expectedAcceptedCurrencies: []string{"LTC"}, + expectedCryptoDivisibility: 8, + expectedCryptoCurrencyCode: "XMR", + }, + { + fixtureName: "v5-physical-good", + expectedSchemaVersion: 5, + expectedTitle: "ETH - $1", + expectedSlug: "eth-1", + expectedPrice: &repo.CurrencyValue{ + Amount: big.NewInt(100), + Currency: repo.CurrencyDefinition{ + Code: repo.CurrencyCode("USD"), + Divisibility: 2, + CurrencyType: "fiat", + }, + }, + expectedAcceptedCurrencies: []string{"BTC", "BCH", "ZEC", "LTC", "ETH"}, + expectedCryptoDivisibility: 0, + expectedCryptoCurrencyCode: "", + }, + } + + for _, e := range examples { + t.Logf("example listing (%s)", e.fixtureName) + var ( + fixtureBytes = factory.MustLoadListingFixture(e.fixtureName) + l, err = repo.UnmarshalJSONSignedListing(fixtureBytes) + ) + if err != nil { + t.Errorf("unable to unmarshal example (%s)", e.fixtureName) + continue + } + + // test version + if l.GetVersion() != e.expectedSchemaVersion { + t.Errorf("expected to have version response (%+v), but instead was (%+v)", e.expectedSchemaVersion, l.GetVersion()) + } + + // test title + if title := l.GetTitle(); title != e.expectedTitle { + t.Errorf("expected to have title response (%+v), but instead was (%+v)", e.expectedTitle, title) + } + + // test slug + if slug := l.GetSlug(); slug != e.expectedSlug { + t.Errorf("expected to have slug response (%+v), but instead was (%+v)", e.expectedSlug, slug) + } + + // test price + if price, err := l.GetPrice(); err == nil { + if !price.Equal(e.expectedPrice) { + t.Errorf("expected to have price response (%+v), but instead was (%+v)", e.expectedPrice, price) + } + } else { + t.Errorf("get price: %s", err.Error()) + } + + // test accepted currencies + if acceptedCurrencies := l.GetAcceptedCurrencies(); len(acceptedCurrencies) != len(e.expectedAcceptedCurrencies) { + t.Errorf("expected to have acceptedCurrencies response (%+v), but instead was (%+v)", e.expectedAcceptedCurrencies, acceptedCurrencies) + } + + // test crypto divisibility + if actual := l.GetCryptoDivisibility(); actual != e.expectedCryptoDivisibility { + t.Errorf("expected to have divisibility (%d), but was (%d)", e.expectedCryptoDivisibility, actual) + } + + // test crypto currency code + if actual := l.GetCryptoCurrencyCode(); actual != e.expectedCryptoCurrencyCode { + t.Errorf("expected to have currency code (%s), but was (%s)", e.expectedCryptoCurrencyCode, actual) + } + } +} + +func TestSignAndVerifyListing(t *testing.T) { + testnode, err := test.NewNode() + if err != nil { + t.Fatalf("create test node: %v", err) + } + + priv, pub, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + t.Fatal(err) + } + + pid, err := peer.IDFromPublicKey(pub) + if err != nil { + t.Fatal(err) + } + + testnode.IpfsNode.Identity = pid + testnode.IpfsNode.PrivateKey = priv + + lpb := factory.NewListing("test") + l, err := repo.NewListingFromProtobuf(lpb) + if err != nil { + t.Fatalf("create repo listing: %v", err) + } + + sl, err := l.Sign(testnode) + if err != nil { + t.Fatalf("sign listing: %v", err) + } + + // get identities from node and listing and compare + nodeID, err := testnode.GetNodeID() + if err != nil { + t.Fatalf("get node id: %v", err) + } + nodeIdentityBytes := nodeID.GetPubkeys().GetIdentity() + listingIdentityBytes := sl.GetListing().GetVendorID().IdentityKeyBytes() + if !bytes.Equal(nodeIdentityBytes, listingIdentityBytes) { + t.Fatal("expected listing and node identity bytes to match, but did not") + } + + // get peer IDs from node and listing and compare + listingPeerHash, err := sl.GetListing().GetVendorID().Hash() + if err != nil { + t.Fatalf("get listing peer hash: %v", err) + } + if listingPeerHash != nodeID.PeerID { + t.Errorf("expected listing has to be (%s), but was (%s)", nodeID.PeerID, listingPeerHash) + } + + // get listing signature and ensure it's as expected + serializedListing, err := l.MarshalProtobuf() + if err != nil { + t.Fatalf("serialize listing: %v", err) + } + expectedSig, err := testnode.IpfsNode.PrivateKey.Sign(serializedListing) + if err != nil { + t.Fatalf("sign listing: %v", err) + } + actualSig := sl.GetSignature() + if !bytes.Equal(expectedSig, actualSig) { + t.Fatal("expected signature on listing to match generated signature, but did not") + } + + if err := sl.VerifySignature(); err != nil { + t.Errorf("verify signed listing: %v", err) + } +} + +func TestNormalize(t *testing.T) { + testnode, err := test.NewNode() + if err != nil { + t.Fatalf("create test node: %v", err) + } + + priv, pub, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + t.Fatal(err) + } + + pid, err := peer.IDFromPublicKey(pub) + if err != nil { + t.Fatal(err) + } + + testnode.IpfsNode.Identity = pid + testnode.IpfsNode.PrivateKey = priv + + // v4 listing is guaranteed to mutate when normalized + lb := factory.MustLoadListingFixture("v4-cryptocurrency") + l, err := repo.UnmarshalJSONSignedListing(lb) + if err != nil { + t.Fatalf("unmarshal fixtured listing: %v", err) + } + + // sign replaces listing vendor ID with the one from the testnode + sl, err := l.GetListing().Sign(testnode) + if err != nil { + t.Fatalf("sign listing: %v", err) + } + + origSig := sl.GetSignature() + origListingJSON, err := sl.MarshalJSON() + if err != nil { + t.Fatalf("marshal listing: %v", err) + } + + if err := sl.Normalize(); err != nil { + t.Fatalf("normalize listing: %v", err) + } + + if sig := sl.GetSignature(); !bytes.Equal(origSig, sig) { + t.Errorf("expected normalized signature to not change, but did") + } + + if listingJSON, err := sl.MarshalJSON(); err != nil { + t.Errorf("marshal normalized listing: %v", err) + } else { + // when normalizing a signed listing, the listing data mutates in place, but + // the signature should remain matched to the original (unchanged) + if bytes.Equal(origListingJSON, listingJSON) { + t.Errorf("expected listing JSON to change from normalization, but did not") + t.Logf("orig: %s\nactual: %s\n", string(origListingJSON), string(listingJSON)) + } + } +} diff --git a/schema/configuration.go b/schema/configuration.go index 25a36a1b48..a20e823c9a 100644 --- a/schema/configuration.go +++ b/schema/configuration.go @@ -2,7 +2,8 @@ package schema import ( "encoding/json" - "errors" + "fmt" + "strings" "time" ) @@ -39,16 +40,17 @@ type WalletsConfig struct { } type CoinConfig struct { - Type string `json:"Type"` - APIPool []string `json:"API"` - APITestnetPool []string `json:"APITestnet"` - MaxFee uint64 `json:"MaxFee"` - FeeAPI string `json:"FeeAPI"` - HighFeeDefault uint64 `json:"HighFeeDefault"` - MediumFeeDefault uint64 `json:"MediumFeeDefault"` - LowFeeDefault uint64 `json:"LowFeeDefault"` - TrustedPeer string `json:"TrustedPeer"` - WalletOptions map[string]interface{} `json:"WalletOptions"` + Type string `json:"Type"` + APIPool []string `json:"API"` + APITestnetPool []string `json:"APITestnet"` + MaxFee uint64 `json:"MaxFee"` + FeeAPI string `json:"FeeAPI"` + SuperLowFeeDefault uint64 `json:"SuperLowFeeDefault"` + HighFeeDefault uint64 `json:"HighFeeDefault"` + MediumFeeDefault uint64 `json:"MediumFeeDefault"` + LowFeeDefault uint64 `json:"LowFeeDefault"` + TrustedPeer string `json:"TrustedPeer"` + WalletOptions map[string]interface{} `json:"WalletOptions"` } type DataSharing struct { @@ -56,7 +58,20 @@ type DataSharing struct { PushTo []string } -var MalformedConfigError = errors.New("config file is malformed") +type malformedConfigError struct { + path []string +} + +func malformedConfigKey(pathArgs ...string) malformedConfigError { + return malformedConfigError{path: pathArgs} +} + +func (err malformedConfigError) Error() string { + if len(err.path) != 0 { + return fmt.Sprintf("malformed config: %s", strings.Join(err.path, ".")) + } + return "malformed config" +} func DefaultWalletsConfig() *WalletsConfig { var feeAPI = "https://btc.fees.openbazaar.org" @@ -83,128 +98,152 @@ func DefaultWalletsConfig() *WalletsConfig { MaxFee: 200, WalletOptions: nil, }, + ETH: &CoinConfig{ + Type: WalletTypeAPI, + APIPool: CoinPoolETH, + APITestnetPool: CoinPoolTETH, + FeeAPI: "", // intentionally blank + LowFeeDefault: 7, + MediumFeeDefault: 15, + HighFeeDefault: 30, + MaxFee: 200, + WalletOptions: EthereumDefaultOptions(), + }, } } func GetAPIConfig(cfgBytes []byte) (*APIConfig, error) { + const ( + KeyAllowedIPs = "AllowedIPs" + KeyAuthenticated = "Authenticated" + KeyCORS = "CORS" + KeyEnabled = "Enabled" + KeyHTTPHeaders = "HTTPHeaders" + KeyJSONAPI = "JSON-API" + KeyPassword = "Password" + KeySSL = "SSL" + KeySSLCert = "SSLCert" + KeySSLKey = "SSLKey" + KeyUsername = "Username" + ) var cfgIface interface{} err := json.Unmarshal(cfgBytes, &cfgIface) if err != nil { - return nil, MalformedConfigError + return nil, malformedConfigError{} } cfg, ok := cfgIface.(map[string]interface{}) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigError{} } - apiIface, ok := cfg["JSON-API"] + apiIface, ok := cfg[KeyJSONAPI] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI) } api, ok := apiIface.(map[string]interface{}) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI) } var headers map[string]interface{} - h, ok := api["HTTPHeaders"] + h, ok := api[KeyHTTPHeaders] if h == nil || !ok { headers = nil } else { headers, ok = h.(map[string]interface{}) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyHTTPHeaders) } } - enabled, ok := api["Enabled"] + enabled, ok := api[KeyEnabled] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyEnabled) } enabledBool, ok := enabled.(bool) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyEnabled) } - authenticated := api["Authenticated"] + authenticated := api[KeyAuthenticated] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyAuthenticated) } authenticatedBool, ok := authenticated.(bool) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyAuthenticated) } - allowedIPs, ok := api["AllowedIPs"] + allowedIPs, ok := api[KeyAllowedIPs] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyAllowedIPs) } allowedIPsIface, ok := allowedIPs.([]interface{}) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyAllowedIPs) } var allowedIPstrings []string for _, ip := range allowedIPsIface { ipStr, ok := ip.(string) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyAllowedIPs) } allowedIPstrings = append(allowedIPstrings, ipStr) } - username, ok := api["Username"] + username, ok := api[KeyUsername] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyUsername) } usernameStr, ok := username.(string) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyUsername) } - password, ok := api["Password"] + password, ok := api[KeyPassword] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyPassword) } passwordStr, ok := password.(string) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyPassword) } - c, ok := api["CORS"] + c, ok := api[KeyCORS] var cors *string if c == nil || !ok { cors = nil } else { crs, ok := c.(string) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeyCORS) } cors = &crs } - sslEnabled, ok := api["SSL"] + sslEnabled, ok := api[KeySSL] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeySSL) } sslEnabledBool, ok := sslEnabled.(bool) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeySSL) } - certFile, ok := api["SSLCert"] + certFile, ok := api[KeySSLCert] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeySSLCert) } certFileStr, ok := certFile.(string) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeySSLCert) } - keyFile, ok := api["SSLKey"] + keyFile, ok := api[KeySSLKey] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeySSLKey) } keyFileStr, ok := keyFile.(string) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyJSONAPI, KeySSLKey) } apiConfig := &APIConfig{ @@ -224,15 +263,16 @@ func GetAPIConfig(cfgBytes []byte) (*APIConfig, error) { } func GetWalletsConfig(cfgBytes []byte) (*WalletsConfig, error) { + const KeyWallets = "Wallets" var cfgIface map[string]interface{} err := json.Unmarshal(cfgBytes, &cfgIface) if err != nil { - return nil, MalformedConfigError + return nil, malformedConfigError{} } - walletIface, ok := cfgIface["Wallets"] + walletIface, ok := cfgIface[KeyWallets] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyWallets) } b, err := json.Marshal(walletIface) @@ -248,130 +288,142 @@ func GetWalletsConfig(cfgBytes []byte) (*WalletsConfig, error) { } func GetTorConfig(cfgBytes []byte) (*TorConfig, error) { + const ( + KeyPassword = "Password" + KeyTorConfig = "Tor-config" + KeyTorControl = "TorControl" + ) var cfgIface interface{} err := json.Unmarshal(cfgBytes, &cfgIface) if err != nil { - return nil, MalformedConfigError + return nil, malformedConfigError{} } cfg, ok := cfgIface.(map[string]interface{}) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigError{} } - tcIface, ok := cfg["Tor-config"] + tcIface, ok := cfg[KeyTorConfig] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyTorConfig) } tc, ok := tcIface.(map[string]interface{}) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyTorConfig) } - pw, ok := tc["Password"] + pw, ok := tc[KeyPassword] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyTorConfig, KeyPassword) } pwStr, ok := pw.(string) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyTorConfig, KeyPassword) } - controlUrl, ok := tc["TorControl"] + controlUrl, ok := tc[KeyTorControl] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyTorConfig, KeyTorControl) } controlUrlStr, ok := controlUrl.(string) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyTorConfig, KeyTorControl) } return &TorConfig{TorControl: controlUrlStr, Password: pwStr}, nil } func GetIPNSExtraConfig(cfgBytes []byte) (*IpnsExtraConfig, error) { + const ( + KeyAPIRouter = "APIRouter" + KeyDHTQuorumSize = "DHTQuorumSize" + KeyIpnsExtra = "IpnsExtra" + ) var cfgIface interface{} err := json.Unmarshal(cfgBytes, &cfgIface) if err != nil { - return nil, MalformedConfigError + return nil, malformedConfigError{} } cfg, ok := cfgIface.(map[string]interface{}) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigError{} } - ieIface, ok := cfg["IpnsExtra"] + ieIface, ok := cfg[KeyIpnsExtra] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyIpnsExtra) } ieCfg, ok := ieIface.(map[string]interface{}) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyIpnsExtra) } - quorumSize, ok := ieCfg["DHTQuorumSize"] + quorumSize, ok := ieCfg[KeyDHTQuorumSize] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyIpnsExtra, KeyDHTQuorumSize) } qsInt, ok := quorumSize.(float64) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyIpnsExtra, KeyDHTQuorumSize) } - apiRouter, ok := ieCfg["APIRouter"] + apiRouter, ok := ieCfg[KeyAPIRouter] if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyIpnsExtra, KeyAPIRouter) } apiRouterStr, ok := apiRouter.(string) if !ok { - return nil, MalformedConfigError + return nil, malformedConfigKey(KeyIpnsExtra, KeyAPIRouter) } return &IpnsExtraConfig{int(qsInt), apiRouterStr}, nil } func GetDropboxApiToken(cfgBytes []byte) (string, error) { + const KeyDropboxApiToken = "Dropbox-api-token" var cfgIface interface{} err := json.Unmarshal(cfgBytes, &cfgIface) if err != nil { - return "", MalformedConfigError + return "", malformedConfigError{} } cfg, ok := cfgIface.(map[string]interface{}) if !ok { - return "", MalformedConfigError + return "", malformedConfigError{} } - token, ok := cfg["Dropbox-api-token"] + token, ok := cfg[KeyDropboxApiToken] if !ok { - return "", MalformedConfigError + return "", malformedConfigKey(KeyDropboxApiToken) } tokenStr, ok := token.(string) if !ok { - return "", MalformedConfigError + return "", malformedConfigKey(KeyDropboxApiToken) } return tokenStr, nil } func GetRepublishInterval(cfgBytes []byte) (time.Duration, error) { + const KeyRepublishInterval = "RepublishInterval" var cfgIface interface{} err := json.Unmarshal(cfgBytes, &cfgIface) if err != nil { - return time.Duration(0), MalformedConfigError + return time.Duration(0), malformedConfigError{} } cfg, ok := cfgIface.(map[string]interface{}) if !ok { - return time.Duration(0), MalformedConfigError + return time.Duration(0), malformedConfigError{} } - interval, ok := cfg["RepublishInterval"] + interval, ok := cfg[KeyRepublishInterval] if !ok { - return time.Duration(0), MalformedConfigError + return time.Duration(0), malformedConfigKey(KeyRepublishInterval) } intervalStr, ok := interval.(string) if !ok { - return time.Duration(0), MalformedConfigError + return time.Duration(0), malformedConfigKey(KeyRepublishInterval) } if intervalStr == "" { return time.Duration(0), nil @@ -384,51 +436,57 @@ func GetRepublishInterval(cfgBytes []byte) (time.Duration, error) { } func GetDataSharing(cfgBytes []byte) (*DataSharing, error) { + const ( + KeyAcceptStoreRequest = "AcceptStoreRequests" + KeyDataSharing = "DataSharing" + KeyPushTo = "PushTo" + ) + var cfgIface interface{} err := json.Unmarshal(cfgBytes, &cfgIface) if err != nil { - return nil, MalformedConfigError + return nil, malformedConfigError{} } dataSharing := new(DataSharing) cfg, ok := cfgIface.(map[string]interface{}) if !ok { - return dataSharing, MalformedConfigError + return dataSharing, malformedConfigError{} } - dscfg, ok := cfg["DataSharing"] + dscfg, ok := cfg[KeyDataSharing] if !ok { - return dataSharing, MalformedConfigError + return dataSharing, malformedConfigKey(KeyDataSharing) } ds, ok := dscfg.(map[string]interface{}) if !ok { - return dataSharing, MalformedConfigError + return dataSharing, malformedConfigKey(KeyDataSharing) } - acceptcfg, ok := ds["AcceptStoreRequests"] + acceptcfg, ok := ds[KeyAcceptStoreRequest] if !ok { - return dataSharing, MalformedConfigError + return dataSharing, malformedConfigKey(KeyDataSharing, KeyAcceptStoreRequest) } accept, ok := acceptcfg.(bool) if !ok { - return dataSharing, MalformedConfigError + return dataSharing, malformedConfigKey(KeyDataSharing, KeyAcceptStoreRequest) } dataSharing.AcceptStoreRequests = accept - pushcfg, ok := ds["PushTo"] + pushcfg, ok := ds[KeyPushTo] if !ok { - return dataSharing, MalformedConfigError + return dataSharing, malformedConfigKey(KeyDataSharing, KeyPushTo) } pushList, ok := pushcfg.([]interface{}) if !ok { - return dataSharing, MalformedConfigError + return dataSharing, malformedConfigKey(KeyDataSharing, KeyPushTo) } for _, nd := range pushList { ndStr, ok := nd.(string) if !ok { - return dataSharing, MalformedConfigError + return dataSharing, malformedConfigKey(KeyDataSharing, KeyPushTo) } dataSharing.PushTo = append(dataSharing.PushTo, ndStr) } @@ -436,32 +494,33 @@ func GetDataSharing(cfgBytes []byte) (*DataSharing, error) { } func GetTestnetBootstrapAddrs(cfgBytes []byte) ([]string, error) { + const KeyBootstrapTestnet = "Bootstrap-testnet" var cfgIface interface{} err := json.Unmarshal(cfgBytes, &cfgIface) if err != nil { - return nil, MalformedConfigError + return nil, malformedConfigError{} } var addrs []string cfg, ok := cfgIface.(map[string]interface{}) if !ok { - return addrs, MalformedConfigError + return addrs, malformedConfigError{} } - bootstrap, ok := cfg["Bootstrap-testnet"] + bootstrap, ok := cfg[KeyBootstrapTestnet] if !ok { - return addrs, MalformedConfigError + return addrs, malformedConfigKey(KeyBootstrapTestnet) } addrList, ok := bootstrap.([]interface{}) if !ok { - return addrs, MalformedConfigError + return addrs, malformedConfigKey(KeyBootstrapTestnet) } for _, addr := range addrList { addrStr, ok := addr.(string) if !ok { - return addrs, MalformedConfigError + return addrs, malformedConfigKey(KeyBootstrapTestnet) } addrs = append(addrs, addrStr) } diff --git a/schema/configuration_test.go b/schema/configuration_test.go index b7a4fdce3f..97c7d877ef 100644 --- a/schema/configuration_test.go +++ b/schema/configuration_test.go @@ -59,10 +59,10 @@ func TestGetWalletsConfig(t *testing.T) { if config.BTC.Type != "API" { t.Error("Type does not equal expected value") } - if len(config.BTC.APIPool) == 0 || config.BTC.APIPool[0] != "https://btc.blockbook.api.openbazaar.org/api" { + if len(config.BTC.APIPool) == 0 || config.BTC.APIPool[0] != "https://btc.api.openbazaar.org/api" { t.Error("BTC APIPool does not equal expected value") } - if len(config.BTC.APITestnetPool) == 0 || config.BTC.APITestnetPool[0] != "https://tbtc.blockbook.api.openbazaar.org/api" { + if len(config.BTC.APITestnetPool) == 0 || config.BTC.APITestnetPool[0] != "https://tbtc.api.openbazaar.org/api" { t.Error("BTC APITestnetPool does not equal expected value") } if config.BTC.LowFeeDefault != 1 { @@ -81,10 +81,10 @@ func TestGetWalletsConfig(t *testing.T) { if config.BCH.Type != "API" { t.Error("Type does not equal expected value") } - if len(config.BCH.APIPool) == 0 || config.BCH.APIPool[0] != "https://bch.blockbook.api.openbazaar.org/api" { + if len(config.BCH.APIPool) == 0 || config.BCH.APIPool[0] != "https://bch.api.openbazaar.org/api" { t.Error("BCH APIPool does not equal expected value") } - if len(config.BCH.APITestnetPool) == 0 || config.BCH.APITestnetPool[0] != "https://tbch.blockbook.api.openbazaar.org/api" { + if len(config.BCH.APITestnetPool) == 0 || config.BCH.APITestnetPool[0] != "https://tbch.api.openbazaar.org/api" { t.Error("BCH APITestnetPool does not equal expected value") } @@ -104,10 +104,10 @@ func TestGetWalletsConfig(t *testing.T) { if config.LTC.Type != "API" { t.Error("Type does not equal expected value") } - if len(config.LTC.APIPool) == 0 || config.LTC.APIPool[0] != "https://ltc.blockbook.api.openbazaar.org/api" { + if len(config.LTC.APIPool) == 0 || config.LTC.APIPool[0] != "https://ltc.api.openbazaar.org/api" { t.Error("LTC APIPool does not equal expected value") } - if len(config.LTC.APITestnetPool) == 0 || config.LTC.APITestnetPool[0] != "https://tltc.blockbook.api.openbazaar.org/api" { + if len(config.LTC.APITestnetPool) == 0 || config.LTC.APITestnetPool[0] != "https://tltc.api.openbazaar.org/api" { t.Error("LTC APITestnetPool does not equal expected value") } if config.LTC.LowFeeDefault != 5 { @@ -126,10 +126,10 @@ func TestGetWalletsConfig(t *testing.T) { if config.ZEC.Type != "API" { t.Error("Type does not equal expected value") } - if len(config.ZEC.APIPool) == 0 || config.ZEC.APIPool[0] != "https://zec.blockbook.api.openbazaar.org/api" { + if len(config.ZEC.APIPool) == 0 || config.ZEC.APIPool[0] != "https://zec.api.openbazaar.org/api" { t.Error("ZEC APIPool does not equal expected value") } - if len(config.ZEC.APITestnetPool) == 0 || config.ZEC.APITestnetPool[0] != "https://tzec.blockbook.api.openbazaar.org/api" { + if len(config.ZEC.APITestnetPool) == 0 || config.ZEC.APITestnetPool[0] != "https://tzec.api.openbazaar.org/api" { t.Error("ZEC APITestnetPool does not equal expected value") } if config.ZEC.LowFeeDefault != 5 { @@ -349,10 +349,10 @@ func configFixture() []byte { "BTC": { "Type": "API", "API": [ - "https://btc.blockbook.api.openbazaar.org/api" + "https://btc.api.openbazaar.org/api" ], "APITestnet": [ - "https://tbtc.blockbook.api.openbazaar.org/api" + "https://tbtc.api.openbazaar.org/api" ], "MaxFee": 200, "FeeAPI": "https://btc.fees.openbazaar.org", @@ -365,10 +365,10 @@ func configFixture() []byte { "BCH": { "Type": "API", "API": [ - "https://bch.blockbook.api.openbazaar.org/api" + "https://bch.api.openbazaar.org/api" ], "APITestnet": [ - "https://tbch.blockbook.api.openbazaar.org/api" + "https://tbch.api.openbazaar.org/api" ], "MaxFee": 200, "FeeAPI": "https://btc.fees.openbazaar.org", @@ -381,10 +381,10 @@ func configFixture() []byte { "LTC": { "Type": "API", "API": [ - "https://ltc.blockbook.api.openbazaar.org/api" + "https://ltc.api.openbazaar.org/api" ], "APITestnet": [ - "https://tltc.blockbook.api.openbazaar.org/api" + "https://tltc.api.openbazaar.org/api" ], "MaxFee": 200, "FeeAPI": "https://btc.fees.openbazaar.org", @@ -397,10 +397,10 @@ func configFixture() []byte { "ZEC": { "Type": "API", "API": [ - "https://zec.blockbook.api.openbazaar.org/api" + "https://zec.api.openbazaar.org/api" ], "APITestnet": [ - "https://tzec.blockbook.api.openbazaar.org/api" + "https://tzec.api.openbazaar.org/api" ], "MaxFee": 200, "FeeAPI": "https://btc.fees.openbazaar.org", @@ -413,7 +413,7 @@ func configFixture() []byte { "ETH": { "Type": "API", "API": [ - "https://rinkeby.infura.io" + "https://mainnet.infura.io" ], "APITestnet": [ "https://rinkeby.infura.io" @@ -425,8 +425,8 @@ func configFixture() []byte { "LowFeeDefault": 7, "TrustedPeer": "", "WalletOptions": { - "RegistryAddress": "0x403d907982474cdd51687b09a8968346159378f3", - "RinkebyRegistryAddress": "0x403d907982474cdd51687b09a8968346159378f3", + "RegistryAddress": "0x5c69ccf91eab4ef80d9929b3c1b4d5bc03eb0981", + "RinkebyRegistryAddress": "0x5cEF053c7b383f430FC4F4e1ea2F7D31d8e2D16C", "RopstenRegistryAddress": "0x403d907982474cdd51687b09a8968346159378f3" } } diff --git a/schema/constants.go b/schema/constants.go index fb660ea5bb..741f9cb76f 100644 --- a/schema/constants.go +++ b/schema/constants.go @@ -12,18 +12,18 @@ const ( CreateTablePointersSQL = "create table pointers (pointerID text primary key not null, key text, address text, cancelID text, purpose integer, timestamp integer);" CreateTableKeysSQL = "create table keys (scriptAddress text primary key not null, purpose integer, keyIndex integer, used integer, key text, coin text);" CreateIndexKeysSQL = "create index index_keys on keys (coin);" - CreateTableUnspentTransactionOutputsSQL = "create table utxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer, coin text);" + CreateTableUnspentTransactionOutputsSQL = "create table utxos (outpoint text primary key not null, value text, height integer, scriptPubKey text, watchOnly integer, coin text);" CreateIndexUnspentTransactionOutputsSQL = "create index index_utxos on utxos (coin);" - CreateTableSpentTransactionOutputsSQL = "create table stxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer, spendHeight integer, spendTxid text, coin text);" + CreateTableSpentTransactionOutputsSQL = "create table stxos (outpoint text primary key not null, value text, height integer, scriptPubKey text, watchOnly integer, spendHeight integer, spendTxid text, coin text);" CreateIndexSpentTransactionOutputsSQL = "create index index_stxos on stxos (coin);" - CreateTableTransactionsSQL = "create table txns (txid text primary key not null, value integer, height integer, timestamp integer, watchOnly integer, tx blob, coin text);" + CreateTableTransactionsSQL = "create table txns (txid text primary key not null, value text, height integer, timestamp integer, watchOnly integer, tx blob, coin text);" CreateIndexTransactionsSQL = "create index index_txns on txns (coin);" CreateTableTransactionMetadataSQL = "create table txmetadata (txid text primary key not null, address text, memo text, orderID text, thumbnail text, canBumpFee integer);" CreateTableInventorySQL = "create table inventory (invID text primary key not null, slug text, variantIndex integer, count integer);" CreateIndexInventorySQL = "create index index_inventory on inventory (slug);" CreateTablePurchasesSQL = "create table purchases (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total integer, thumbnail text, vendorID text, vendorHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, lastDisputeTimeoutNotifiedAt integer not null default 0, lastDisputeExpiryNotifiedAt integer not null default 0, disputedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" CreateIndexPurchasesSQL = "create index index_purchases on purchases (paymentAddr, timestamp);" - CreateTableSalesSQL = "create table sales (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total integer, thumbnail text, buyerID text, buyerHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, needsSync integer, lastDisputeTimeoutNotifiedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" + CreateTableSalesSQL = "create table sales (orderID text primary key not null, contract blob, state integer, read integer, timestamp integer, total integer, thumbnail text, buyerID text, buyerHandle text, title text, shippingName text, shippingAddress text, paymentAddr text, funded integer, transactions blob, lastDisputeTimeoutNotifiedAt integer not null default 0, coinType not null default '', paymentCoin not null default '');" CreateIndexSalesSQL = "create index index_sales on sales (paymentAddr, timestamp);" CreatedTableWatchedScriptsSQL = "create table watchedscripts (scriptPubKey text primary key not null, coin text);" CreateIndexWatchedScriptsSQL = "create index index_watchscripts on watchedscripts (coin);" @@ -36,11 +36,15 @@ const ( CreateTableCouponsSQL = "create table coupons (slug text, code text, hash text);" CreateIndexCouponsSQL = "create index index_coupons on coupons (slug);" CreateTableModeratedStoresSQL = "create table moderatedstores (peerID text primary key not null);" + CreateMessagesSQL = "create table messages (messageID text primary key not null, orderID text, message_type integer, message blob, peerID text, url text, acknowledged bool, tries integer, created_at integer, updated_at integer, err string, received_at integer, pubkey blob);" + CreateIndexMessagesSQLMessageID = "create index index_messages_messageID on messages (messageID);" + CreateIndexMessagesSQLOrderIDMType = "create index index_messages_orderIDmType on messages (orderID, message_type);" + CreateIndexMessagesSQLPeerIDMType = "create index index_messages_peerIDmType on messages (peerID, message_type);" // End SQL Statements // Configuration defaults - EthereumRegistryAddressMainnet = "0x403d907982474cdd51687b09a8968346159378f3" - EthereumRegistryAddressRinkeby = "0x403d907982474cdd51687b09a8968346159378f3" + EthereumRegistryAddressMainnet = "0x5c69ccf91eab4ef80d9929b3c1b4d5bc03eb0981" + EthereumRegistryAddressRinkeby = "0x5cEF053c7b383f430FC4F4e1ea2F7D31d8e2D16C" EthereumRegistryAddressRopsten = "0x403d907982474cdd51687b09a8968346159378f3" DataPushNodeOne = "QmWbi8z4uPkEdrWHtgxCkQGE5vxJnrStXAeEQnupmQnKRh" @@ -101,15 +105,19 @@ const ( const ( CoinAPIOpenBazaarPHR = "https://phr.blockbook.api.phore.io/api" CoinAPIOpenBazaarBTC = "https://btc.blockbook.api.phore.io/api" + CoinAPIOpenBazaarETH = "https://mainnet.infura.io" CoinAPIOpenBazaarTPHR = "https://tphr.blockbook.api.phore.io/api" CoinAPIOpenBazaarTBTC = "https://tbtc.blockbook.api.phore.io/api" + CoinAPIOpenBazaarTETH = "https://rinkeby.infura.io" ) var ( CoinPoolPHR = []string{CoinAPIOpenBazaarPHR} CoinPoolBTC = []string{CoinAPIOpenBazaarBTC} + CoinPoolETH = []string{CoinAPIOpenBazaarETH} CoinPoolTPHR = []string{CoinAPIOpenBazaarTPHR} CoinPoolTBTC = []string{CoinAPIOpenBazaarTBTC} + CoinPoolTETH = []string{CoinAPIOpenBazaarTETH} ) diff --git a/schema/manager.go b/schema/manager.go index 0d8ba17d40..46734241cc 100644 --- a/schema/manager.go +++ b/schema/manager.go @@ -17,7 +17,7 @@ import ( "github.com/ipfs/go-ipfs/repo/fsrepo" _ "github.com/mutecomm/go-sqlcipher" - "github.com/phoreproject/openbazaar-go/ipfs" + "github.com/phoreproject/pm-go/ipfs" "github.com/tyler-smith/go-bip39" ) @@ -305,6 +305,10 @@ func InitializeDatabaseSQL(encryptionPassword string) string { CreateTableCouponsSQL, CreateIndexCouponsSQL, CreateTableModeratedStoresSQL, + CreateMessagesSQL, + CreateIndexMessagesSQLMessageID, + CreateIndexMessagesSQLOrderIDMType, + CreateIndexMessagesSQLPeerIDMType, } return strings.Join(initializeStatement, " ") } diff --git a/schema/manager_test.go b/schema/manager_test.go index a99dcf2e26..07147e8019 100644 --- a/schema/manager_test.go +++ b/schema/manager_test.go @@ -4,6 +4,7 @@ import ( "bytes" "database/sql" "encoding/json" + "errors" "fmt" "io/ioutil" "os" @@ -13,7 +14,7 @@ import ( "testing" "time" - "github.com/phoreproject/openbazaar-go/ipfs" + "github.com/phoreproject/pm-go/ipfs" "github.com/tyler-smith/go-bip39" ) @@ -411,36 +412,42 @@ func TestOpenbazaarSchemaManager_CleanIdentityFromConfig(t *testing.T) { t.Error(err) } - loadConfig := func() map[string]interface{} { + loadConfig := func() (map[string]interface{}, error) { configPath := path.Join(subject.dataPath, "config") configFile, err := ioutil.ReadFile(configPath) if err != nil { - t.Error(err) + return map[string]interface{}{}, err } var cfgIface interface{} if err := json.Unmarshal(configFile, &cfgIface); err != nil { - t.Error(err) + return map[string]interface{}{}, err } cfg, ok := cfgIface.(map[string]interface{}) if !ok { - t.Error("invalid config file") + return map[string]interface{}{}, errors.New("invalid config file") } - return cfg + return cfg, nil } // First load the config and make sure the identity object is indeed set. - cfg := loadConfig() + cfg, err := loadConfig() + if err != nil { + t.Error("config can not be loaded") + } _, ok := cfg["Identity"] if !ok { - t.Error("Identity object does not exist in config but should") + t.Error("identity object does not exist in config but should") } // Now clean and check again if err := subject.CleanIdentityFromConfig(); err != nil { t.Error(err) } - cfg = loadConfig() + cfg, err = loadConfig() + if err != nil { + t.Error("config can not be loaded") + } _, ok = cfg["Identity"] if ok { t.Error("Identity object was not deleted from config") diff --git a/storage/selfhosted/selfhostedstorage.go b/storage/selfhosted/selfhostedstorage.go index ac0e9b0267..c8a0dd50e2 100644 --- a/storage/selfhosted/selfhostedstorage.go +++ b/storage/selfhosted/selfhostedstorage.go @@ -3,6 +3,7 @@ package selfhosted import ( "crypto/sha256" "encoding/hex" + "log" ma "gx/ipfs/QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL/go-multiaddr" "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" @@ -12,7 +13,7 @@ import ( "path" "github.com/ipfs/go-ipfs/core" - "github.com/phoreproject/openbazaar-go/ipfs" + "github.com/phoreproject/pm-go/ipfs" ) type SelfHostedStorage struct { @@ -54,7 +55,12 @@ func (s *SelfHostedStorage) Store(peerID peer.ID, ciphertext []byte) (ma.Multiad } for _, peer := range s.pushNodes { - go s.store(peer.Pretty(), []cid.Cid{id}) + go func(peerID string, cid []cid.Cid) { + err := s.store(peerID, cid) + if err != nil { + log.Println(err) + } + }(peer.Pretty(), []cid.Cid{id}) } maAddr, err := ma.NewMultiaddr("/ipfs/" + addr + "/") if err != nil { diff --git a/test/config.go b/test/config.go index 56e52eb26e..96a67f815b 100644 --- a/test/config.go +++ b/test/config.go @@ -6,7 +6,7 @@ import ( "os" "path" - "github.com/phoreproject/openbazaar-go/schema" + "github.com/phoreproject/pm-go/schema" ) // NewAPIConfig returns a new config object for the API tests diff --git a/test/contracts/signed_listings_1_invalid.json b/test/contracts/signed_listings_1_invalid.json deleted file mode 100644 index 02a06cc010..0000000000 --- a/test/contracts/signed_listings_1_invalid.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "listing" -} \ No newline at end of file diff --git a/test/factory/api_time.go b/test/factory/api_time.go new file mode 100644 index 0000000000..5a94da96d0 --- /dev/null +++ b/test/factory/api_time.go @@ -0,0 +1,11 @@ +package factory + +import ( + "time" + + "github.com/phoreproject/pm-go/repo" +) + +func NewAPITime(t time.Time) *repo.APITime { + return repo.NewAPITime(t) +} diff --git a/test/factory/contract.go b/test/factory/contract.go index 7f634b1550..6d577ec06b 100644 --- a/test/factory/contract.go +++ b/test/factory/contract.go @@ -6,7 +6,7 @@ import ( "time" "github.com/golang/protobuf/ptypes" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" ) func NewContract() *pb.RicardianContract { @@ -23,10 +23,10 @@ func NewContract() *pb.RicardianContract { ShipTo: "Buyer Name", }, Payment: &pb.Order_Payment{ - Amount: 10, - Method: pb.Order_Payment_DIRECT, - Address: "3BDbGsH5h5ctDiFtWMmZawcf3E7iWirVms", - Coin: "BTC", + BigAmount: "10", + AmountCurrency: &pb.CurrencyDefinition{Code: "BTC", Divisibility: 8}, + Method: pb.Order_Payment_DIRECT, + Address: "3BDbGsH5h5ctDiFtWMmZawcf3E7iWirVms", }, Timestamp: nowData, } diff --git a/test/factory/currency.go b/test/factory/currency.go index b166ccea3f..a81a38f050 100644 --- a/test/factory/currency.go +++ b/test/factory/currency.go @@ -3,33 +3,44 @@ package factory import ( "fmt" "math/big" + "time" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) -func NewBigInt(amount string) *big.Int { - var i = new(big.Int) - if _, ok := i.SetString(amount, 0); !ok { - i.SetString("0", 0) - } - return i -} - -func NewCurrencyDefinition(code string) *repo.CurrencyDefinition { +func NewCurrencyDefinition(code string) repo.CurrencyDefinition { if code == "" { code = "BTC" } - return &repo.CurrencyDefinition{ + bt := repo.DefaultBlockTime + if code == "LTC" || code == "TLTC" { + bt = 150 * time.Second + } + return repo.CurrencyDefinition{ Name: fmt.Sprintf("%scoin", code), Code: repo.CurrencyCode(code), Divisibility: 8, CurrencyType: repo.Crypto, + BlockTime: bt, } } -func NewCurrencyValue(amount, code string) *repo.CurrencyValue { +func MustNewCurrencyValue(amount, code string) *repo.CurrencyValue { + amt, ok := new(big.Int).SetString(amount, 10) + if !ok { + panic(fmt.Sprintf("invalid CurrencyValue amount: %s", amount)) + } return &repo.CurrencyValue{ - Amount: NewBigInt(amount), + Amount: amt, Currency: NewCurrencyDefinition(code), } } + +func MustNewCurrencyValueUsingDiv(amount, code string, customDiv uint) *repo.CurrencyValue { + if customDiv == 0 { + panic("custom divisibility must be greater than 0") + } + v := MustNewCurrencyValue(amount, code) + v.Currency.Divisibility = customDiv + return v +} diff --git a/test/factory/currency_converter.go b/test/factory/currency_converter.go new file mode 100644 index 0000000000..b241ac761d --- /dev/null +++ b/test/factory/currency_converter.go @@ -0,0 +1,28 @@ +package factory + +import ( + "fmt" + + "github.com/phoreproject/pm-go/repo" +) + +type mockRater struct { + rates map[string]float64 +} + +func (m mockRater) GetExchangeRate(code string) (float64, error) { + if r, ok := m.rates[code]; ok { + return r, nil + } + return 0.0, fmt.Errorf("rate for code (%s) not found", code) +} + +func NewCurrencyConverter(reserveCode string, mockRates map[string]float64) (*repo.CurrencyConverter, error) { + r, ok := mockRates[reserveCode] + if !ok { + mockRates[reserveCode] = 1.0 + } else if r != 1.0 { + return nil, fmt.Errorf("reserve currency rate is not 1.0") + } + return repo.NewCurrencyConverter(reserveCode, mockRater{mockRates}) +} diff --git a/test/factory/dispute_case_record.go b/test/factory/dispute_case_record.go index 1a7b6dcb2f..dd50e61250 100644 --- a/test/factory/dispute_case_record.go +++ b/test/factory/dispute_case_record.go @@ -3,8 +3,8 @@ package factory import ( "time" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" ) func NewDisputeCaseRecord() *repo.DisputeCaseRecord { diff --git a/test/factory/fixtures/listings/v3-physical-good.json b/test/factory/fixtures/listings/v3-physical-good.json new file mode 100644 index 0000000000..019f214de9 --- /dev/null +++ b/test/factory/fixtures/listings/v3-physical-good.json @@ -0,0 +1,151 @@ +{ + "listing": { + "slug": "physical-listing", + "vendorID": { + "peerID": "Qmdxhx4PMb8ovRG1FW6CuF1ZBaY3KXWp8e9ND2vPfaGdv1", + "pubkeys": { + "identity": "CAESIO09q05xH2g6aoOrK9TBURLvBZIqZrejpPhek+YTWeBl", + "bitcoin": "AiLFa8gc1En/4n9xzHO0JfQ6ymebxcl02WGnFjkd9MZS" + }, + "bitcoinSig": "MEQCIBfHyKAEyYgp2vb32u2BB79MBAl0a1hs8TZ71KK7HeGSAiBZyZtGEX1UcrqQ16GoviuTesblZUzCzfW3L97bCNvETA==" + }, + "metadata": { + "version": 3, + "contractType": "PHYSICAL_GOOD", + "format": "FIXED_PRICE", + "expiry": "2037-12-31T05:00:00.000Z", + "acceptedCurrencies": [ + "BCH" + ], + "pricingCurrency": "BCH", + "escrowTimeoutHours": 1080, + "coinDivisibility": 100000000 + }, + "item": { + "title": "Physical Listing", + "description": "Description of a physical listing", + "price": 1235000000, + "tags": [ + "test" + ], + "images": [ + { + "filename": "sanic-too-slow.gif", + "original": "zb2rhd8G4d6vmkUVFyzF8wjQngY86CRRzy4NdE3zdVp4K9cSJ", + "large": "zb2rhodiuogttcVGgabxdGsmzRHoMmSgTkCmrhFZSgaasV4dj", + "medium": "zb2rhgfPd1QT98RoXMr8F4xLyE1hCWEmWqfxKXUp7mEUDoT42", + "small": "zb2rhb2iWYwMc7sSSmUi4Fe8ifRQrEj6rfzX46XCJc6ozpCtB", + "tiny": "zb2rhgfm6R7SXqn1H4bRqBqfEBn5ts1iDzpspjJ2UmEenDYr1" + } + ], + "categories": [ + "cheap-goods" + ], + "condition": "NEW", + "options": [ + { + "name": "Color", + "variants": [ + { + "name": "Red" + }, + { + "name": "Blue" + } + ] + } + ], + "skus": [ + { + "variantCombo": [ + 0 + ], + "productID": "SKU12Red" + }, + { + "variantCombo": [ + 1 + ], + "productID": "SKU12Blue" + } + ] + }, + "shippingOptions": [ + { + "name": "EU Shipping", + "type": "FIXED_PRICE", + "regions": [ + "AUSTRIA", + "BELGIUM", + "BULGARIA", + "CROATIA", + "CYPRUS", + "CZECH_REPUBLIC", + "DENMARK", + "ESTONIA", + "FINLAND", + "FRANCE", + "GERMANY", + "GREECE", + "HUNGARY", + "IRELAND", + "ITALY", + "LATVIA", + "LITHUANIA", + "LUXEMBOURG", + "MALTA", + "NETHERLANDS", + "POLAND", + "PORTUGAL", + "ROMANIA", + "SLOVAKIA", + "SLOVENIA", + "SPAIN", + "SWEDEN", + "UNITED_KINGDOM" + ], + "services": [ + { + "name": "EU Express", + "price": 1000000000, + "estimatedDelivery": "1 week", + "additionalItemPrice": 100000000 + }, + { + "name": "EU Lost Package", + "price": 50000000, + "estimatedDelivery": "1 month" + } + ] + }, + { + "name": "US Only", + "type": "FIXED_PRICE", + "regions": [ + "UNITED_STATES" + ], + "services": [ + { + "name": "US Express", + "price": 500000000, + "estimatedDelivery": "5 days", + "additionalItemPrice": 100000000 + } + ] + } + ], + "coupons": [ + { + "title": "50% Off", + "hash": "QmQcuGE7tPcF9CYhgLHVmaRofSGhvxZnZGq6dRTmUHa8o5", + "percentDiscount": 50 + } + ], + "moderators": [ + "QmRjZqsCr4EgV1RhMWTHcXE6MM77nxDSCwgNNrzWkYSNwt" + ], + "termsAndConditions": "Terms and Conditions", + "refundPolicy": "Return Policy" + }, + "signature": "8MAXoVKz/dbrrMfF9mwoEZEs0UL4dJgLHGSBMjxYcGPoKa43Z6sx7km/N4Exs7XXTRcVGMXu1PUr2TJkFAliBw==" +} \ No newline at end of file diff --git a/test/factory/fixtures/listings/v4-cryptocurrency.json b/test/factory/fixtures/listings/v4-cryptocurrency.json new file mode 100644 index 0000000000..bb87bf9c9a --- /dev/null +++ b/test/factory/fixtures/listings/v4-cryptocurrency.json @@ -0,0 +1,62 @@ +{ + "listing": { + "slug": "ltc-xmr", + "vendorID": { + "peerID": "QmVisrQ9apmvTLnq9FSNKbP8dYvBvkP4AeeysHZg89oB9q", + "pubkeys": { + "identity": "CAESIBHz9BLX+9JlUN7cfPdaoh1QFN/a4gjJBzmVOZfSFD5G", + "bitcoin": "Ai4YTSiFiBLqNxjV/iLcKilp4iaJCIvnatSf15EV25M2" + }, + "bitcoinSig": "MEUCIQC7jvfG23aHIpPjvQjT1unn23PuKNSykh9v/Hc7v3vmoQIgMFI8BBtju7tAgpI66jKAL6PKWGb7jImVBo1DcDoNbpI=" + }, + "metadata": { + "version": 4, + "contractType": "CRYPTOCURRENCY", + "format": "MARKET_PRICE", + "expiry": "2037-12-31T05:00:00.000Z", + "acceptedCurrencies": [ + "LTC" + ], + "escrowTimeoutHours": 1080, + "coinType": "XMR", + "coinDivisibility": 100000000, + "priceModifier": 0.05 + }, + "item": { + "title": "LTC-XMR", + "description": "Cryptocurrency listing with 0.05% markup.", + "tags": [ + "test" + ], + "images": [ + { + "filename": "sanic-too-slow.gif", + "original": "QmXyed6vsnUWxxC97Uo8eb2j91tVUgu4y6d8htSAHXjLEQ", + "large": "QmQieQ8yUx98wzXmgW8mYyAA824dGFA6NYLMAnNjGUkjtS", + "medium": "QmZAVH8cRE8rTydrg9aTgkXtNroGpq53hAcwo1jSTaXM83", + "small": "QmTgMSgckmBFat6noQrg3f3A1LZMkujSsnqYwoJ4uhPi8Q", + "tiny": "QmdKLLsLGpYTmzNePPuJsRNcchqQNXqA5VQYinVvUH7VJd" + } + ], + "categories": [ + "cheap-goods" + ], + "options": [ + ], + "skus": [ + { + + } + ] + }, + "shippingOptions": [ + ], + "coupons": [ + ], + "moderators": [ + ], + "termsAndConditions": "Terms and Conditions", + "refundPolicy": "Return policy" + }, + "signature": "9AAIv/qr6qo8nDgZhlVmkhkEs7cnM38xWE4TC4ivBaVyrLXz/fSXsA4MOpk1E8HSKaEDl/kqU7Ndyh9prDpiCA==" +} \ No newline at end of file diff --git a/test/factory/fixtures/listings/v4-digital-good.json b/test/factory/fixtures/listings/v4-digital-good.json new file mode 100644 index 0000000000..45c080acff --- /dev/null +++ b/test/factory/fixtures/listings/v4-digital-good.json @@ -0,0 +1,89 @@ +{ + "listing": { + "slug": "digital-good-listing", + "vendorID": { + "peerID": "QmVisrQ9apmvTLnq9FSNKbP8dYvBvkP4AeeysHZg89oB9q", + "pubkeys": { + "identity": "CAESIBHz9BLX+9JlUN7cfPdaoh1QFN/a4gjJBzmVOZfSFD5G", + "bitcoin": "Ai4YTSiFiBLqNxjV/iLcKilp4iaJCIvnatSf15EV25M2" + }, + "bitcoinSig": "MEUCIQC7jvfG23aHIpPjvQjT1unn23PuKNSykh9v/Hc7v3vmoQIgMFI8BBtju7tAgpI66jKAL6PKWGb7jImVBo1DcDoNbpI=" + }, + "metadata": { + "version": 4, + "contractType": "DIGITAL_GOOD", + "format": "FIXED_PRICE", + "expiry": "2037-12-31T05:00:00.000Z", + "acceptedCurrencies": [ + "ZEC" + ], + "pricingCurrency": "USD", + "escrowTimeoutHours": 1080, + "coinDivisibility": 100 + }, + "item": { + "title": "Digital Good Listing", + "description": "Description", + "price": 1320, + "tags": [ + "test" + ], + "images": [ + { + "filename": "sanic-too-slow.gif", + "original": "QmXyed6vsnUWxxC97Uo8eb2j91tVUgu4y6d8htSAHXjLEQ", + "large": "QmQieQ8yUx98wzXmgW8mYyAA824dGFA6NYLMAnNjGUkjtS", + "medium": "QmZAVH8cRE8rTydrg9aTgkXtNroGpq53hAcwo1jSTaXM83", + "small": "QmTgMSgckmBFat6noQrg3f3A1LZMkujSsnqYwoJ4uhPi8Q", + "tiny": "QmdKLLsLGpYTmzNePPuJsRNcchqQNXqA5VQYinVvUH7VJd" + } + ], + "categories": [ + "cheap-goods" + ], + "condition": "NEW", + "options": [ + { + "name": "Size", + "variants": [ + { + "name": "Economy" + }, + { + "name": "Regular" + } + ] + } + ], + "skus": [ + { + "variantCombo": [ + 0 + ], + "productID": "SKU45E" + }, + { + "variantCombo": [ + 1 + ], + "productID": "SKU45", + "surcharge": 150 + } + ] + }, + "shippingOptions": [ + ], + "coupons": [ + { + "title": "50% off", + "hash": "QmQcuGE7tPcF9CYhgLHVmaRofSGhvxZnZGq6dRTmUHa8o5", + "percentDiscount": 50 + } + ], + "moderators": [ + ], + "termsAndConditions": "Terms and conditions", + "refundPolicy": "Retrun policy" + }, + "signature": "YhtFsTFTJblxQtfo8nPOmI2UbcJ8HRPBLn3w4zbIzMlF/+q8yHzFEBXE+7bgjS2EuEZuqDY7DRTwLCe2lVeECA==" +} diff --git a/test/factory/fixtures/listings/v4-index.json b/test/factory/fixtures/listings/v4-index.json new file mode 100644 index 0000000000..30a52267e5 --- /dev/null +++ b/test/factory/fixtures/listings/v4-index.json @@ -0,0 +1,36 @@ +[ + { + "hash": "QmbAhieQdN7WzDktpkZ3ZDuv3AKF3DxG3SMFyEcVg3HGcP", + "slug": "test-service", + "title": "Test Service", + "categories": ["test"], + "nsfw": true, + "contractType": "SERVICE", + "description": "Test service listing", + "thumbnail": { + "tiny": "zb2rhfN4RQyNP6eZszvEBfwBRMZxaysoqF72MYWPKoofV5AQr", + "small": "zb2rhfMZFaaWZxZGvkqAPCMUbmdxNHhAaCby5XCkRrV13bew8", + "medium": "zb2rhnppMGkZYp6Zg7Qf2irDH9z1ZM5jc2VcAXfy6mEnifoEy" + }, + "price": { + "currencyCode": "USD", + "amount": 25, + "modifier": 0 + }, + "shipsTo": [], + "freeShipping": [], + "language": "English", + "averageRating": 0, + "ratingCount": 0, + "moderators": [ + "QmQifVhzhnHRu9bGT9WNcbbuc5EF2bXRF6iJpSzNj7yRtQ" + ], + "acceptedCurrencies": [ + "BTC", + "BCH", + "ZEC", + "LTC" + ], + "coinType": "" + } +] diff --git a/test/factory/fixtures/listings/v4-physical-good.json b/test/factory/fixtures/listings/v4-physical-good.json new file mode 100644 index 0000000000..700df60f86 --- /dev/null +++ b/test/factory/fixtures/listings/v4-physical-good.json @@ -0,0 +1,154 @@ +{ + "listing": { + "slug": "physical-good-listing", + "vendorID": { + "peerID": "QmVisrQ9apmvTLnq9FSNKbP8dYvBvkP4AeeysHZg89oB9q", + "pubkeys": { + "identity": "CAESIBHz9BLX+9JlUN7cfPdaoh1QFN/a4gjJBzmVOZfSFD5G", + "bitcoin": "Ai4YTSiFiBLqNxjV/iLcKilp4iaJCIvnatSf15EV25M2" + }, + "bitcoinSig": "MEUCIQC7jvfG23aHIpPjvQjT1unn23PuKNSykh9v/Hc7v3vmoQIgMFI8BBtju7tAgpI66jKAL6PKWGb7jImVBo1DcDoNbpI=" + }, + "metadata": { + "version": 4, + "contractType": "PHYSICAL_GOOD", + "format": "FIXED_PRICE", + "expiry": "2037-12-31T05:00:00.000Z", + "acceptedCurrencies": [ + "ZEC", + "LTC", + "BTC", + "BCH" + ], + "pricingCurrency": "BCH", + "escrowTimeoutHours": 1080, + "coinDivisibility": 100000000 + }, + "item": { + "title": "Physical Good Listing", + "description": "A short description. (because a picture is worth a thousand words)", + "price": 12345678000, + "tags": [ + "test" + ], + "images": [ + { + "filename": "sanic-too-slow.gif", + "original": "QmXyed6vsnUWxxC97Uo8eb2j91tVUgu4y6d8htSAHXjLEQ", + "large": "QmQieQ8yUx98wzXmgW8mYyAA824dGFA6NYLMAnNjGUkjtS", + "medium": "QmZAVH8cRE8rTydrg9aTgkXtNroGpq53hAcwo1jSTaXM83", + "small": "QmTgMSgckmBFat6noQrg3f3A1LZMkujSsnqYwoJ4uhPi8Q", + "tiny": "QmdKLLsLGpYTmzNePPuJsRNcchqQNXqA5VQYinVvUH7VJd" + } + ], + "categories": [ + "cheap-goods" + ], + "condition": "NEW", + "options": [ + { + "name": "Color", + "variants": [ + { + "name": "Blue" + }, + { + "name": "Red" + } + ] + } + ], + "skus": [ + { + "variantCombo": [ + 0 + ], + "productID": "SKU12Blue" + }, + { + "variantCombo": [ + 1 + ], + "productID": "SKU12Red" + } + ] + }, + "shippingOptions": [ + { + "name": "EU Shipping", + "type": "FIXED_PRICE", + "regions": [ + "AUSTRIA", + "BELGIUM", + "BULGARIA", + "CROATIA", + "CYPRUS", + "CZECH_REPUBLIC", + "DENMARK", + "ESTONIA", + "FINLAND", + "FRANCE", + "GERMANY", + "GREECE", + "HUNGARY", + "IRELAND", + "ITALY", + "LATVIA", + "LITHUANIA", + "LUXEMBOURG", + "MALTA", + "NETHERLANDS", + "POLAND", + "PORTUGAL", + "ROMANIA", + "SLOVAKIA", + "SLOVENIA", + "SPAIN", + "SWEDEN", + "UNITED_KINGDOM" + ], + "services": [ + { + "name": "EU Express", + "price": 1000000000, + "estimatedDelivery": "1 week", + "additionalItemPrice": 100000000 + }, + { + "name": "EU Lost Package", + "price": 200000000, + "estimatedDelivery": "1 month", + "additionalItemPrice": 50000000 + } + ] + }, + { + "name": "US Only", + "type": "FIXED_PRICE", + "regions": [ + "UNITED_STATES" + ], + "services": [ + { + "name": "US Express", + "price": 500000000, + "estimatedDelivery": "5 days", + "additionalItemPrice": 100000000 + } + ] + } + ], + "coupons": [ + { + "title": "50% off", + "hash": "QmbN4rDGYgWPkrKGeb72QWVXQ8wMUXLGhzShbAmuD6uucu", + "percentDiscount": 50 + } + ], + "moderators": [ + ], + "termsAndConditions": "All sales final.", + "refundPolicy": "Returns are not allowed." + }, + "signature": "U1NrZmH+Txqt5S5RbRAN0mAKBj4173SxytatUNAv2aKT9tPqEPDZvRnc9xtfxlD8lL98qFF2L9OTb3VoNRzCBA==" +} \ No newline at end of file diff --git a/test/factory/fixtures/listings/v4-service.json b/test/factory/fixtures/listings/v4-service.json new file mode 100644 index 0000000000..88669721f9 --- /dev/null +++ b/test/factory/fixtures/listings/v4-service.json @@ -0,0 +1,92 @@ +{ + "listing": { + "slug": "service-listing", + "vendorID": { + "peerID": "QmVisrQ9apmvTLnq9FSNKbP8dYvBvkP4AeeysHZg89oB9q", + "pubkeys": { + "identity": "CAESIBHz9BLX+9JlUN7cfPdaoh1QFN/a4gjJBzmVOZfSFD5G", + "bitcoin": "Ai4YTSiFiBLqNxjV/iLcKilp4iaJCIvnatSf15EV25M2" + }, + "bitcoinSig": "MEUCIQC7jvfG23aHIpPjvQjT1unn23PuKNSykh9v/Hc7v3vmoQIgMFI8BBtju7tAgpI66jKAL6PKWGb7jImVBo1DcDoNbpI=" + }, + "metadata": { + "version": 4, + "contractType": "SERVICE", + "format": "FIXED_PRICE", + "expiry": "2037-12-31T05:00:00.000Z", + "acceptedCurrencies": [ + "ZEC", + "LTC", + "BCH", + "BTC" + ], + "pricingCurrency": "BTC", + "escrowTimeoutHours": 1080, + "coinDivisibility": 100000000 + }, + "item": { + "title": "Service Listing", + "description": "Description", + "price": 9877000000, + "tags": [ + "test" + ], + "images": [ + { + "filename": "sanic-too-slow.gif", + "original": "QmXyed6vsnUWxxC97Uo8eb2j91tVUgu4y6d8htSAHXjLEQ", + "large": "QmQieQ8yUx98wzXmgW8mYyAA824dGFA6NYLMAnNjGUkjtS", + "medium": "QmZAVH8cRE8rTydrg9aTgkXtNroGpq53hAcwo1jSTaXM83", + "small": "QmTgMSgckmBFat6noQrg3f3A1LZMkujSsnqYwoJ4uhPi8Q", + "tiny": "QmdKLLsLGpYTmzNePPuJsRNcchqQNXqA5VQYinVvUH7VJd" + } + ], + "categories": [ + "cheap-goods" + ], + "condition": "NEW", + "options": [ + { + "name": "Turnaround", + "variants": [ + { + "name": "Regular" + }, + { + "name": "Priority" + } + ] + } + ], + "skus": [ + { + "variantCombo": [ + 0 + ], + "productID": "SKU67" + }, + { + "variantCombo": [ + 1 + ], + "productID": "SKU67-Priority", + "surcharge": 500000000 + } + ] + }, + "shippingOptions": [ + ], + "coupons": [ + { + "title": "50% off", + "hash": "QmQcuGE7tPcF9CYhgLHVmaRofSGhvxZnZGq6dRTmUHa8o5", + "percentDiscount": 50 + } + ], + "moderators": [ + ], + "termsAndConditions": "Terms and Conditions", + "refundPolicy": "Return policy" + }, + "signature": "lW4FwBNY/Xza7maSWAqlnpiJhyNYKYJw86O7LeGJjwIrPDJXLuHqBNVYudtrtN+vBocCwvrI5tkMASXMIv2+Dg==" +} \ No newline at end of file diff --git a/test/factory/fixtures/listings/v5-index.json b/test/factory/fixtures/listings/v5-index.json new file mode 100644 index 0000000000..b6d01182e0 --- /dev/null +++ b/test/factory/fixtures/listings/v5-index.json @@ -0,0 +1,41 @@ +[ + { + "hash": "QmcCcbMysMUY4jFUoyYzgrLhJX6N6y5NhRpauCAr8etYn5", + "slug": "ron-swanson-tshirt", + "title": "Ron Swanson Tshirt", + "categories": [ + "tshirts" + ], + "nsfw": true, + "contractType": "PHYSICAL_GOOD", + "description": "Example item", + "thumbnail": { + "tiny": "QmUy4jh5mGNZvLkjies1RWM4YuvJh5o2FYopNPVYwrRVGV", + "small": "QmUy4jh5mGNZvLkjies1RWM4YuvJh5o2FYopNPVYwrRVGV", + "medium": "QmUy4jh5mGNZvLkjies1RWM4YuvJh5o2FYopNPVYwrRVGV" + }, + "currencyCode": "TLTC", + "price": { + "amount": "500000", + "currency": { + "name": "Litecoin", + "code": "TLTC", + "divisibility": 8, + "currencyType": "crypto" + } + }, + "modifier": 0, + "shipsTo": [ + "ALL" + ], + "freeShipping": [], + "language": "Klingon", + "averageRating": 0, + "ratingCount": 0, + "moderators": null, + "acceptedCurrencies": [ + "TBTC", + "TLTC" + ] + } +] diff --git a/test/factory/fixtures/listings/v5-physical-good.json b/test/factory/fixtures/listings/v5-physical-good.json new file mode 100644 index 0000000000..e5281eb85d --- /dev/null +++ b/test/factory/fixtures/listings/v5-physical-good.json @@ -0,0 +1,222 @@ +{ + "listing": { + "slug": "eth-1", + "vendorID": { + "peerID": "QmTu37nuzs6DVKyFQf9UZmuL2gQMpALcfzsmEQ8WzZof9y", + "pubkeys": { + "identity": "CAESIABU8HRiB7Wkj/zRzzI2fZNzWhH8AojrgFsH5ZFghikw", + "bitcoin": "AuZe/azbdpyeRmD9ed+/y3FJgkfux3sZw9GzoadksGyK" + }, + "bitcoinSig": "MEUCIQDleSZUT0APmo0+y9F3j/kzbplVb/2+66AnfBHyZkgZ6wIgHtSUVim7RHqOPr67mlg11rE/xqphGCpvLrMRs8KYjUg=" + }, + "metadata": { + "version": 5, + "contractType": "PHYSICAL_GOOD", + "format": "FIXED_PRICE", + "expiry": "2037-12-31T05:00:00.000Z", + "acceptedCurrencies": [ + "BTC", + "BCH", + "ZEC", + "LTC", + "ETH" + ], + "escrowTimeoutHours": 1, + "shippingFromCountryCode": "NA" + }, + "item": { + "title": "ETH - $1", + "description": "This is a listing example.", + "processingTime": "3 days", + "priceCurrency": { + "code": "USD", + "divisibility": 2 + }, + "bigPrice": "100", + "tags": [ + "vintage dress" + ], + "images": [ + { + "filename": "front", + "original": "QmNexx7SaJCVCjyGGG3j2k7fenn3iVhtWdm9RvKvT7GTLq", + "large": "QmfTKL3Z67mWKTKf9XKSCj1ptmDRaZLr5yjPS4JrVDgo5h", + "medium": "QmTJfeeapZwFM8EoZAuf16JsSJyxZtKaAR6hmWiMf4CTcF", + "small": "QmVsoT9iabv6GZhxhvtjSpQMJA6QyMivGTs6MmHJr6TBm9", + "tiny": "QmbjyAxYee4y3443kAMLcmRVwggZsRDKiyXnXus1qdJJWz" + } + ], + "categories": [ + "👚 Apparel & Accessories" + ], + "condition": "New", + "options": [ + { + "name": "Color", + "description": "Color of the dress.", + "variants": [ + { + "name": "Red", + "image": { + "filename": "front", + "original": "QmNexx7SaJCVCjyGGG3j2k7fenn3iVhtWdm9RvKvT7GTLq", + "large": "QmfTKL3Z67mWKTKf9XKSCj1ptmDRaZLr5yjPS4JrVDgo5h", + "medium": "QmTJfeeapZwFM8EoZAuf16JsSJyxZtKaAR6hmWiMf4CTcF", + "small": "QmVsoT9iabv6GZhxhvtjSpQMJA6QyMivGTs6MmHJr6TBm9", + "tiny": "QmbjyAxYee4y3443kAMLcmRVwggZsRDKiyXnXus1qdJJWz" + } + }, + { + "name": "Cream", + "image": { + "filename": "cream", + "original": "QmTEUnCjuQPj1ggj5UL5vJujkgBiNYY4jkteugnogiCJny", + "large": "QmNsFdsX2LNALG2WBxw6E6FTPZWgJcRAcLHnKdWczrCNf9", + "medium": "QmQaSzaoHzp8raZLtPEFyCjTnwfXvDGKdXFM83STDVWG43", + "small": "QmP3BVFuga7N4XEX8iU2MFYC7pc6mfTRQRrpZbKiVy2Csr", + "tiny": "QmU1cBgjyHpuzDYbEd4iDVuPzxgKM3CqhRhDJqkHWCKBXq" + } + }, + { + "name": "Black", + "image": { + "filename": "black", + "original": "QmZsZ78FJwt281gfeUvGzDnsBW7WNjPWW3aJWDKskhpCRr", + "large": "QmXixGseetihe6vZiWcTw9N1pieok1YtRoxwvyd5d7jz6s", + "medium": "QmZydpAJoLsJWbP5vmh59W6bW1kuiCV34yD62hq28AtP7b", + "small": "QmcADxUo89ZsEAWiYsuUk7hrgjWDMKXL1CtoA9sTNrQFFP", + "tiny": "QmdA3Nmc8VnwSvt98Deo2RQztEiCsAkNLhron73bnBzARe" + } + } + ] + }, + { + "name": "Sizes", + "description": "Size of the dress.", + "variants": [ + { + "name": "Small" + }, + { + "name": "Medium" + }, + { + "name": "Large" + }, + { + "name": "Extra Large" + } + ] + } + ], + "skus": [ + { + "variantCombo": [ + 0, + 0 + ], + "productID": "dress-red-small", + "bigSurcharge": "0" + }, + { + "variantCombo": [ + 0, + 1 + ], + "productID": "dress-red-medium", + "bigSurcharge": "100" + }, + { + "variantCombo": [ + 0, + 2 + ], + "productID": "dress-red-large", + "bigSurcharge": "0" + }, + { + "variantCombo": [ + 1, + 0 + ], + "productID": "dress-cream-small", + "bigSurcharge": "0" + }, + { + "variantCombo": [ + 1, + 1 + ], + "productID": "dress-cream-medium", + "bigSurcharge": "0" + }, + { + "variantCombo": [ + 1, + 2 + ], + "productID": "dress-cream-large", + "bigSurcharge": "0" + }, + { + "variantCombo": [ + 2, + 0 + ], + "productID": "dress-black-small", + "bigSurcharge": "0" + }, + { + "variantCombo": [ + 2, + 1 + ], + "productID": "dress-black-medium", + "bigSurcharge": "0" + }, + { + "variantCombo": [ + 2, + 2 + ], + "productID": "dress-black-large", + "bigSurcharge": "0" + } + ] + }, + "shippingOptions": [ + { + "name": "Worldwide", + "type": "FIXED_PRICE", + "regions": [ + "ALL" + ], + "services": [ + { + "name": "Standard", + "bigPrice": "0", + "estimatedDelivery": "3 days", + "bigAdditionalItemPrice": "0" + }, + { + "name": "Express", + "bigPrice": "0", + "estimatedDelivery": "3 days", + "bigAdditionalItemPrice": "0" + } + ] + } + ], + "taxes": [ + ], + "coupons": [ + ], + "moderators": [ + "QmdEB7us3cUQx7pZqvXmS6gj5cAm8q4KwwtsLbQ2VyCGjA", + "Qmc6X28HFbeBRvFPWszhJPGnHUMtrxVK9fDK2zY1oF93cr" + ], + "termsAndConditions": "These are my terms and conditions.", + "refundPolicy": "This is my refund policy." + }, + "signature": "fVFuw2LF3iCeKa6w+whuRsyd6M2pu7ir1rzkm3WJiaI/m9l8i/NPurj9i3dzKN3CAxjppJmyGeHjD+4CxTZ9Bw==" +} diff --git a/test/contracts/signed_listings_1.json b/test/factory/fixtures/listings/v5-signed-physical-good-2.json similarity index 86% rename from test/contracts/signed_listings_1.json rename to test/factory/fixtures/listings/v5-signed-physical-good-2.json index 485d64f3f0..f66e8c000f 100644 --- a/test/contracts/signed_listings_1.json +++ b/test/factory/fixtures/listings/v5-signed-physical-good-2.json @@ -10,7 +10,7 @@ "bitcoinSig": "MEQCIGqBDqGyLGs8tVewab+b8BIMCY73uGrxg7wPro3+JuVmAiBa2wk55FwGWWQoyLYW1mGhP62FLHyk6pfkAt59A1tU8Q==" }, "metadata": { - "version": 4, + "version": 5, "contractType": "PHYSICAL_GOOD", "format": "FIXED_PRICE", "expiry": "2037-12-31T05:00:00.000Z", @@ -20,14 +20,17 @@ "BTC", "BCH" ], - "pricingCurrency": "USD", "escrowTimeoutHours": 1080, - "coinDivisibility": 100000000 + "shippingFromCountryCode": "NA" }, "item": { "title": "EXAMPLE FILE 1", "description": "THIS IS A TEST FILE.", - "price": 1000, + "priceCurrency": { + "code": "USD", + "divisibility": 2 + }, + "bigAmount": "1000", "tags": [ ], "images": [ @@ -80,7 +83,7 @@ 0 ], "productID": "A", - "surcharge": 100 + "bigSurcharge": "100" }, { "variantCombo": [ @@ -88,7 +91,7 @@ 1 ], "productID": "B", - "surcharge": 100 + "bigSurcharge": "100" }, { "variantCombo": [ @@ -96,7 +99,7 @@ 2 ], "productID": "C", - "surcharge": 100 + "bigSurcharge": "100" }, { "variantCombo": [ @@ -104,7 +107,7 @@ 0 ], "productID": "D", - "surcharge": 100 + "bigSurcharge": "100" }, { "variantCombo": [ @@ -112,7 +115,7 @@ 1 ], "productID": "E", - "surcharge": 100 + "bigSurcharge": "100" }, { "variantCombo": [ @@ -120,7 +123,7 @@ 2 ], "productID": "F", - "surcharge": 100 + "bigSurcharge": "100" }, { "variantCombo": [ @@ -128,7 +131,7 @@ 0 ], "productID": "G", - "surcharge": 100 + "bigSurcharge": "100" }, { "variantCombo": [ @@ -136,7 +139,7 @@ 1 ], "productID": "H", - "surcharge": 100 + "bigSurcharge": "100" }, { "variantCombo": [ @@ -144,7 +147,7 @@ 2 ], "productID": "I", - "surcharge": 100 + "bigSurcharge": "100" } ] }, @@ -158,9 +161,9 @@ "services": [ { "name": "USPS", - "price": 100, + "bigPrice": "100", "estimatedDelivery": "1-2 Days", - "additionalItemPrice": 100 + "bigAdditionalItemPrice": "100" } ] } @@ -174,11 +177,11 @@ { "title": "ALMOSTFREE", "hash": "QmbrfL76FTwBzkMvKiLzUdwuzWUtEMwg2wYhZ2kTo3WQyS", - "percentDiscount": 25 + "bigPriceDiscount": "1" } ], "moderators": [ ] }, "signature": "yfz4mplL2nDrbAp20bNTvy0bq19eYPPfrAbzHSBImpv10QACHVWLXSsYmScAluKE0U/m8iKRqZWBEjWxo/TvBg==" -} \ No newline at end of file +} diff --git a/test/factory/fixtures/listings/v5-signed-physical-good.json b/test/factory/fixtures/listings/v5-signed-physical-good.json new file mode 100644 index 0000000000..8f27471269 --- /dev/null +++ b/test/factory/fixtures/listings/v5-signed-physical-good.json @@ -0,0 +1,321 @@ +{ + "listing": { + "slug": "eth-1", + "vendorID": { + "peerID": "QmTu37nuzs6DVKyFQf9UZmuL2gQMpALcfzsmEQ8WzZof9y", + "pubkeys": { + "identity": "CAESIABU8HRiB7Wkj/zRzzI2fZNzWhH8AojrgFsH5ZFghikw", + "bitcoin": "AuZe/azbdpyeRmD9ed+/y3FJgkfux3sZw9GzoadksGyK" + }, + "bitcoinSig": "MEUCIQDleSZUT0APmo0+y9F3j/kzbplVb/2+66AnfBHyZkgZ6wIgHtSUVim7RHqOPr67mlg11rE/xqphGCpvLrMRs8KYjUg=" + }, + "metadata": { + "version": 5, + "contractType": "PHYSICAL_GOOD", + "format": "FIXED_PRICE", + "expiry": "2037-12-31T05:00:00.000Z", + "acceptedCurrencies": [ + "BTC", + "BCH", + "ZEC", + "LTC", + "ETH" + ], + "pricingCurrency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "escrowTimeoutHours": 1, + "shippingFromCountryCode": "NA" + }, + "item": { + "title": "ETH - $1", + "description": "This is a listing example.", + "processingTime": "3 days", + "price": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "100" + }, + "tags": [ + "vintage dress" + ], + "images": [ + { + "filename": "front", + "original": "QmNexx7SaJCVCjyGGG3j2k7fenn3iVhtWdm9RvKvT7GTLq", + "large": "QmfTKL3Z67mWKTKf9XKSCj1ptmDRaZLr5yjPS4JrVDgo5h", + "medium": "QmTJfeeapZwFM8EoZAuf16JsSJyxZtKaAR6hmWiMf4CTcF", + "small": "QmVsoT9iabv6GZhxhvtjSpQMJA6QyMivGTs6MmHJr6TBm9", + "tiny": "QmbjyAxYee4y3443kAMLcmRVwggZsRDKiyXnXus1qdJJWz" + } + ], + "categories": [ + "👚 Apparel & Accessories" + ], + "condition": "New", + "options": [ + { + "name": "Color", + "description": "Color of the dress.", + "variants": [ + { + "name": "Red", + "image": { + "filename": "front", + "original": "QmNexx7SaJCVCjyGGG3j2k7fenn3iVhtWdm9RvKvT7GTLq", + "large": "QmfTKL3Z67mWKTKf9XKSCj1ptmDRaZLr5yjPS4JrVDgo5h", + "medium": "QmTJfeeapZwFM8EoZAuf16JsSJyxZtKaAR6hmWiMf4CTcF", + "small": "QmVsoT9iabv6GZhxhvtjSpQMJA6QyMivGTs6MmHJr6TBm9", + "tiny": "QmbjyAxYee4y3443kAMLcmRVwggZsRDKiyXnXus1qdJJWz" + } + }, + { + "name": "Cream", + "image": { + "filename": "cream", + "original": "QmTEUnCjuQPj1ggj5UL5vJujkgBiNYY4jkteugnogiCJny", + "large": "QmNsFdsX2LNALG2WBxw6E6FTPZWgJcRAcLHnKdWczrCNf9", + "medium": "QmQaSzaoHzp8raZLtPEFyCjTnwfXvDGKdXFM83STDVWG43", + "small": "QmP3BVFuga7N4XEX8iU2MFYC7pc6mfTRQRrpZbKiVy2Csr", + "tiny": "QmU1cBgjyHpuzDYbEd4iDVuPzxgKM3CqhRhDJqkHWCKBXq" + } + }, + { + "name": "Black", + "image": { + "filename": "black", + "original": "QmZsZ78FJwt281gfeUvGzDnsBW7WNjPWW3aJWDKskhpCRr", + "large": "QmXixGseetihe6vZiWcTw9N1pieok1YtRoxwvyd5d7jz6s", + "medium": "QmZydpAJoLsJWbP5vmh59W6bW1kuiCV34yD62hq28AtP7b", + "small": "QmcADxUo89ZsEAWiYsuUk7hrgjWDMKXL1CtoA9sTNrQFFP", + "tiny": "QmdA3Nmc8VnwSvt98Deo2RQztEiCsAkNLhron73bnBzARe" + } + } + ] + }, + { + "name": "Sizes", + "description": "Size of the dress.", + "variants": [ + { + "name": "Small" + }, + { + "name": "Medium" + }, + { + "name": "Large" + }, + { + "name": "Extra Large" + } + ] + } + ], + "skus": [ + { + "variantCombo": [ + 0, + 0 + ], + "productID": "dress-red-small", + "surcharge": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + }, + { + "variantCombo": [ + 0, + 1 + ], + "productID": "dress-red-medium", + "surcharge": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "100" + } + }, + { + "variantCombo": [ + 0, + 2 + ], + "productID": "dress-red-large", + "surcharge": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + }, + { + "variantCombo": [ + 1, + 0 + ], + "productID": "dress-cream-small", + "surcharge": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + }, + { + "variantCombo": [ + 1, + 1 + ], + "productID": "dress-cream-medium", + "surcharge": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + }, + { + "variantCombo": [ + 1, + 2 + ], + "productID": "dress-cream-large", + "surcharge": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + }, + { + "variantCombo": [ + 2, + 0 + ], + "productID": "dress-black-small", + "surcharge": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + }, + { + "variantCombo": [ + 2, + 1 + ], + "productID": "dress-black-medium", + "surcharge": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + }, + { + "variantCombo": [ + 2, + 2 + ], + "productID": "dress-black-large", + "surcharge": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + } + ] + }, + "shippingOptions": [ + { + "name": "Worldwide", + "type": "FIXED_PRICE", + "regions": [ + "ALL" + ], + "services": [ + { + "name": "Standard", + "price": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + }, + "estimatedDelivery": "3 days", + "additionalItemPrice": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + }, + { + "name": "Express", + "price": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "100" + }, + "estimatedDelivery": "3 days", + "additionalItemPrice": { + "currency": { + "code": "USD", + "divisibility": 2, + "currencyType": "fiat" + }, + "amount": "0" + } + } + ] + } + ], + "taxes": [ + ], + "coupons": [ + ], + "moderators": [ + "QmdEB7us3cUQx7pZqvXmS6gj5cAm8q4KwwtsLbQ2VyCGjA", + "Qmc6X28HFbeBRvFPWszhJPGnHUMtrxVK9fDK2zY1oF93cr" + ], + "termsAndConditions": "These are my terms and conditions.", + "refundPolicy": "This is my refund policy." + }, + "signature": "fVFuw2LF3iCeKa6w+whuRsyd6M2pu7ir1rzkm3WJiaI/m9l8i/NPurj9i3dzKN3CAxjppJmyGeHjD+4CxTZ9Bw==" +} diff --git a/test/factory/fixtures/profiles/v0-profile-moderator-fixed-fee.json b/test/factory/fixtures/profiles/v0-profile-moderator-fixed-fee.json new file mode 100644 index 0000000000..e5537e944c --- /dev/null +++ b/test/factory/fixtures/profiles/v0-profile-moderator-fixed-fee.json @@ -0,0 +1,61 @@ +{ + "peerID": "QmQifVhzhnHRu9bGT9WNcbbuc5EF2bXRF6iJpSzNj7yRtQ", + "handle": "", + "name": "Moderator", + "location": "", + "about": "", + "shortDescription": "2.3 (0.13.0) Moderator", + "nsfw": false, + "vendor": true, + "moderator": true, + "moderatorInfo": { + "description": "I'm a test moderator. Please do not use me.", + "termsAndConditions": "Test moderation only. Will resolve all disputes 50/50.", + "languages": [ + "en-US" + ], + "acceptedCurrencies": [ + "ZEC", + "LTC", + "BTC", + "BCH" + ], + "fee": { + "fixedFee": { + "currencyCode": "USD", + "amount": 100 + }, + "percentage": 0, + "feeType": "FIXED" + } + }, + "contactInfo": { + "website": "", + "email": "", + "phoneNumber": "", + "social": [ + ] + }, + "colors": { + "primary": "#FFFFFF", + "secondary": "#ECEEF2", + "text": "#252525", + "highlight": "#2BAD23", + "highlightText": "#252525" + }, + "avatarHashes": { + "tiny": "zb2rhfLcAfDqyRudWcTxzZztdCNmRD2iEH2wt964QNQznZv8Y", + "small": "zb2rhXQbxyCzYD7aZ9PVfAx7D5hdRdjZU6MctGS5fbN76BDwc", + "medium": "zb2rhXowgKjLbEBEVGC9HPhxtuHKzjtzmEinmGWGm8nztnqjd", + "large": "zb2rhoZUSE7eWk8Tb1RQhFfrapgZ2Zt5Xp4XhLJwaa7oondCZ", + "original": "zb2rhmx8WX4nTL35kJGySgQuS1wzfsBbn9WvvArkxDTQW2Bqy" + }, + "bitcoinPubkey": "02951689e5abda5d499607c15bb60d9c7a3b072dc7d4d1211f825334d20908b4f5", + "lastModified": "2019-03-15T14:50:58.913432876Z", + "currencies": [ + "ZEC", + "LTC", + "BTC", + "BCH" + ] +} diff --git a/test/factory/fixtures/profiles/v4-profile-moderator-fixed-fee.json b/test/factory/fixtures/profiles/v4-profile-moderator-fixed-fee.json new file mode 100644 index 0000000000..a86a79c33d --- /dev/null +++ b/test/factory/fixtures/profiles/v4-profile-moderator-fixed-fee.json @@ -0,0 +1,62 @@ +{ + "peerID": "QmQifVhzhnHRu9bGT9WNcbbuc5EF2bXRF6iJpSzNj7yRtQ", + "handle": "", + "name": "Moderator", + "location": "", + "about": "", + "shortDescription": "2.3 (0.13.0) Moderator", + "nsfw": false, + "vendor": true, + "moderator": true, + "moderatorInfo": { + "description": "I'm a test moderator. Please do not use me.", + "termsAndConditions": "Test moderation only. Will resolve all disputes 50/50.", + "languages": [ + "en-US" + ], + "acceptedCurrencies": [ + "ZEC", + "LTC", + "BTC", + "BCH" + ], + "fee": { + "fixedFee": { + "currencyCode": "USD", + "amount": 100 + }, + "percentage": 0, + "feeType": "FIXED" + } + }, + "contactInfo": { + "website": "", + "email": "", + "phoneNumber": "", + "social": [ + ] + }, + "colors": { + "primary": "#FFFFFF", + "secondary": "#ECEEF2", + "text": "#252525", + "highlight": "#2BAD23", + "highlightText": "#252525" + }, + "avatarHashes": { + "tiny": "zb2rhfLcAfDqyRudWcTxzZztdCNmRD2iEH2wt964QNQznZv8Y", + "small": "zb2rhXQbxyCzYD7aZ9PVfAx7D5hdRdjZU6MctGS5fbN76BDwc", + "medium": "zb2rhXowgKjLbEBEVGC9HPhxtuHKzjtzmEinmGWGm8nztnqjd", + "large": "zb2rhoZUSE7eWk8Tb1RQhFfrapgZ2Zt5Xp4XhLJwaa7oondCZ", + "original": "zb2rhmx8WX4nTL35kJGySgQuS1wzfsBbn9WvvArkxDTQW2Bqy" + }, + "bitcoinPubkey": "02951689e5abda5d499607c15bb60d9c7a3b072dc7d4d1211f825334d20908b4f5", + "lastModified": "2019-03-15T14:50:58.913432876Z", + "currencies": [ + "ZEC", + "LTC", + "BTC", + "BCH" + ], + "version": 4 +} diff --git a/test/factory/fixtures/profiles/v5-profile-moderator-fixed-fee.json b/test/factory/fixtures/profiles/v5-profile-moderator-fixed-fee.json new file mode 100644 index 0000000000..84846e5d5d --- /dev/null +++ b/test/factory/fixtures/profiles/v5-profile-moderator-fixed-fee.json @@ -0,0 +1,67 @@ +{ + "peerID": "QmQifVhzhnHRu9bGT9WNcbbuc5EF2bXRF6iJpSzNj7yRtQ", + "handle": "", + "name": "Moderator", + "location": "", + "about": "", + "shortDescription": "2.3 (0.13.0) Moderator", + "nsfw": false, + "vendor": true, + "moderator": true, + "moderatorInfo": { + "description": "I'm a test moderator. Please do not use me.", + "termsAndConditions": "Test moderation only. Will resolve all disputes 50/50.", + "languages": [ + "en-US" + ], + "acceptedCurrencies": [ + "ZEC", + "LTC", + "BTC", + "BCH" + ], + "fee": { + "fixedFee": { + "currencyCode": "", + "amount": 0, + "bigAmount": "100", + "amountCurrency": { + "code": "USD", + "divisibility": 2 + } + }, + "percentage": 0, + "feeType": "FIXED" + } + }, + "contactInfo": { + "website": "", + "email": "", + "phoneNumber": "", + "social": [ + ] + }, + "colors": { + "primary": "#FFFFFF", + "secondary": "#ECEEF2", + "text": "#252525", + "highlight": "#2BAD23", + "highlightText": "#252525" + }, + "avatarHashes": { + "tiny": "zb2rhfLcAfDqyRudWcTxzZztdCNmRD2iEH2wt964QNQznZv8Y", + "small": "zb2rhXQbxyCzYD7aZ9PVfAx7D5hdRdjZU6MctGS5fbN76BDwc", + "medium": "zb2rhXowgKjLbEBEVGC9HPhxtuHKzjtzmEinmGWGm8nztnqjd", + "large": "zb2rhoZUSE7eWk8Tb1RQhFfrapgZ2Zt5Xp4XhLJwaa7oondCZ", + "original": "zb2rhmx8WX4nTL35kJGySgQuS1wzfsBbn9WvvArkxDTQW2Bqy" + }, + "bitcoinPubkey": "02951689e5abda5d499607c15bb60d9c7a3b072dc7d4d1211f825334d20908b4f5", + "lastModified": "2019-03-15T14:50:58.913432876Z", + "currencies": [ + "ZEC", + "LTC", + "BTC", + "BCH" + ], + "version": 5 +} diff --git a/test/factory/helper.go b/test/factory/helper.go new file mode 100644 index 0000000000..b4ef0e8ff5 --- /dev/null +++ b/test/factory/helper.go @@ -0,0 +1,16 @@ +package factory + +import ( + "os" + "path/filepath" +) + +func fixtureLoadPath() string { + gopath := os.Getenv("GOPATH") + repoPath := filepath.Join("src", "github.com", "phoreproject", "pm-go") + fixturePath, err := filepath.Abs(filepath.Join(gopath, repoPath, "test", "factory", "fixtures")) + if err != nil { + panic("cannot create absolute path") + } + return fixturePath +} diff --git a/test/factory/image.go b/test/factory/image.go index 17faf087d7..744dee79d8 100644 --- a/test/factory/image.go +++ b/test/factory/image.go @@ -1,6 +1,6 @@ package factory -import "github.com/phoreproject/openbazaar-go/pb" +import "github.com/phoreproject/pm-go/pb" func NewImage() *pb.Listing_Item_Image { return &pb.Listing_Item_Image{ diff --git a/test/factory/listing.go b/test/factory/listing.go index 75c7fc2f30..c32c5a2c87 100644 --- a/test/factory/listing.go +++ b/test/factory/listing.go @@ -1,19 +1,51 @@ package factory import ( + "fmt" + "io/ioutil" + "path/filepath" + "github.com/golang/protobuf/ptypes/timestamp" - "github.com/phoreproject/openbazaar-go/pb" + "github.com/phoreproject/pm-go/pb" + + "github.com/OpenBazaar/jsonpb" ) +// MustLoadListingFixture - load listing json from fixtures +func MustLoadListingFixture(fixtureName string) []byte { + filename := filepath.Join(fixtureLoadPath(), "listings", fmt.Sprintf("%s.json", fixtureName)) + b, err := ioutil.ReadFile(filename) + if err != nil { + panic(fmt.Errorf("cannot find fixture (%s): %s", fixtureName, err)) + } + return b +} + +// NewListing - return new pb.Listing func NewListing(slug string) *pb.Listing { + var ( + idJSON = `{ + "peerID": "QmVisrQ9apmvTLnq9FSNKbP8dYvBvkP4AeeysHZg89oB9q", + "pubkeys": { + "identity": "CAESIBHz9BLX+9JlUN7cfPdaoh1QFN/a4gjJBzmVOZfSFD5G", + "bitcoin": "Ai4YTSiFiBLqNxjV/iLcKilp4iaJCIvnatSf15EV25M2" + }, + "bitcoinSig": "MEUCIQC7jvfG23aHIpPjvQjT1unn23PuKNSykh9v/Hc7v3vmoQIgMFI8BBtju7tAgpI66jKAL6PKWGb7jImVBo1DcDoNbpI=" + }` + vendorID = new(pb.ID) + ) + if err := jsonpb.UnmarshalString(idJSON, vendorID); err != nil { + panic(err) + } + return &pb.Listing{ Slug: slug, TermsAndConditions: "Sample Terms and Conditions", RefundPolicy: "Sample Refund policy", + VendorID: vendorID, Metadata: &pb.Listing_Metadata{ - Version: 1, + Version: 5, AcceptedCurrencies: []string{"TBTC"}, - PricingCurrency: "TBTC", Expiry: ×tamp.Timestamp{Seconds: 2147483647}, Format: pb.Listing_Metadata_FIXED_PRICE, ContractType: pb.Listing_Metadata_PHYSICAL_GOOD, @@ -21,14 +53,14 @@ func NewListing(slug string) *pb.Listing { Item: &pb.Listing_Item{ Skus: []*pb.Listing_Item_Sku{ { - Surcharge: 0, - Quantity: 12, + BigSurcharge: "0", + BigQuantity: "12", ProductID: "1", VariantCombo: []uint32{0, 0}, }, { - Surcharge: 0, - Quantity: 44, + BigSurcharge: "0", + BigQuantity: "44", ProductID: "2", VariantCombo: []uint32{0, 1}, }, @@ -55,7 +87,8 @@ func NewListing(slug string) *pb.Listing { }, Nsfw: false, Description: "Example item", - Price: 100, + BigPrice: "2000", + PriceCurrency: &pb.CurrencyDefinition{Code: "TBTC", Divisibility: 8}, ProcessingTime: "3 days", Categories: []string{"tshirts"}, Grams: 14, @@ -78,7 +111,7 @@ func NewListing(slug string) *pb.Listing { Services: []*pb.Listing_ShippingOption_Service{ { Name: "standard", - Price: 20, + BigPrice: "20", EstimatedDelivery: "3 days", }, }, @@ -87,29 +120,32 @@ func NewListing(slug string) *pb.Listing { Coupons: []*pb.Listing_Coupon{ { Title: "Insider's Discount", - Code: &pb.Listing_Coupon_DiscountCode{"insider"}, - Discount: &pb.Listing_Coupon_PercentDiscount{5}, + Code: &pb.Listing_Coupon_DiscountCode{DiscountCode: "insider"}, + Discount: &pb.Listing_Coupon_BigPriceDiscount{BigPriceDiscount: "5"}, }, }, } } +// NewCryptoListing - return new crypto listing func NewCryptoListing(slug string) *pb.Listing { listing := NewListing(slug) - listing.Metadata.CoinType = "TETH" - listing.Metadata.CoinDivisibility = 1e8 + listing.Metadata.CryptoCurrencyCode = "TETH" + listing.Metadata.CryptoDivisibility = 18 listing.Metadata.ContractType = pb.Listing_Metadata_CRYPTOCURRENCY listing.Metadata.Format = pb.Listing_Metadata_MARKET_PRICE - listing.Item.Skus = []*pb.Listing_Item_Sku{{Quantity: 1e8}} + listing.Item.Skus = []*pb.Listing_Item_Sku{{BigQuantity: "100000000"}} listing.Metadata.PricingCurrency = "" listing.ShippingOptions = nil listing.Item.Condition = "" listing.Item.Options = nil - listing.Item.Price = 0 + listing.Item.BigPrice = "0" + listing.Item.PriceCurrency = nil listing.Coupons = nil return listing } +// NewListingWithShippingRegions - return new listing with shipping region func NewListingWithShippingRegions(slug string) *pb.Listing { listing := NewListing(slug) listing.ShippingOptions = []*pb.Listing_ShippingOption{ @@ -120,7 +156,7 @@ func NewListingWithShippingRegions(slug string) *pb.Listing { Services: []*pb.Listing_ShippingOption_Service{ { Name: "standard", - Price: 20, + BigPrice: "20", EstimatedDelivery: "3 days", }, }, diff --git a/test/factory/message.go b/test/factory/message.go new file mode 100644 index 0000000000..aba6bef773 --- /dev/null +++ b/test/factory/message.go @@ -0,0 +1,17 @@ +package factory + +import ( + "github.com/golang/protobuf/ptypes/any" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" +) + +func NewMessageWithOrderPayload() repo.Message { + payload := []byte("test payload") + return repo.Message{ + Msg: pb.Message{ + MessageType: pb.Message_ORDER, + Payload: &any.Any{Value: payload}, + }, + } +} diff --git a/test/factory/peer_info.go b/test/factory/peer_info.go new file mode 100644 index 0000000000..31f597ea9f --- /dev/null +++ b/test/factory/peer_info.go @@ -0,0 +1,77 @@ +package factory + +import ( + "encoding/base64" + "fmt" + + "github.com/btcsuite/btcd/btcec" + "github.com/golang/protobuf/jsonpb" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" +) + +func NewPeerIDProtobuf() *pb.ID { + privKey := MustNewBitcoinPrivKey() + bitcoinSig, err := privKey.Sign([]byte("QmeJ3vRqsYVJXtFZr2MRo47KS9LStvW9g4LRK8uqGX2bt5")) + if err != nil { + panic(fmt.Sprintf("signing peerid: %s", err.Error())) + } + return &pb.ID{ + PeerID: "QmeJ3vRqsYVJXtFZr2MRo47KS9LStvW9g4LRK8uqGX2bt5", + Handle: "", + Pubkeys: MustNewPubkeysProtobuf(privKey), + BitcoinSig: bitcoinSig.Serialize(), + } +} + +func MustNewPubkeysIdentityKeyBytes() []byte { + keyBytes, err := base64.StdEncoding.DecodeString("CAESIII6nbBUBtCkK0blWtYRwm2lKS4kuAm36sElyoeC0n0u") + if err != nil { + panic(err) + } + return keyBytes +} + +func MustNewBitcoinPrivKey() *btcec.PrivateKey { + priv, err := btcec.NewPrivateKey(btcec.S256()) + if err != nil { + panic(err) + } + return priv +} + +func MustNewPubkeysProtobuf(bitcoinKey *btcec.PrivateKey) *pb.ID_Pubkeys { + if bitcoinKey == nil { + panic("nil bitcoin pubkey cannot produce pubkey protobuf") + } + return &pb.ID_Pubkeys{ + Identity: MustNewPubkeysIdentityKeyBytes(), + Bitcoin: bitcoinKey.PubKey().SerializeCompressed(), + } +} + +// MustNewPeerIDProtobuf returns a PeerID protobuf example that is known to be valid +func MustNewPeerIDProtobuf() *pb.ID { + var idJSON = `{ + "peerID": "QmSsRdJtKLHueUA6vsjZVoZo6N6fjQrMjao29CcVW7pX4g", + "pubkeys": { + "identity": "CAESIFD3dGlUgpYv1RsEIwZPriU/NnKLjOXOFPolx35Be6ff", + "bitcoin": "AgcLRxnvq37Yt3nCpez8Sj7Y7fzdpkJpULQh/B3vzl7C" + }, + "bitcoinSig": "MEQCIEf8jOQquW3yCXo29NTdhMyh5pIcGTOgZSYJVL4QO5kyAiAk25Bl1q1SktRev4Oo+ZwAuSuNCM1YwtndqZp/0ET/ow==" +}` + pbID := new(pb.ID) + if err := jsonpb.UnmarshalString(idJSON, pbID); err != nil { + panic(err) + } + return pbID +} + +// NewValidPeerInfo returns a PeerInfo example that is known to be valid +func MustNewValidPeerInfo() *repo.PeerInfo { + var p = repo.NewPeerInfoFromProtobuf(MustNewPeerIDProtobuf()) + if err := p.Valid(); err != nil { + panic(fmt.Sprintf("invalid peer: %+v", err)) + } + return p +} diff --git a/test/factory/profile.go b/test/factory/profile.go new file mode 100644 index 0000000000..e8a075f64a --- /dev/null +++ b/test/factory/profile.go @@ -0,0 +1,41 @@ +package factory + +import ( + "fmt" + "io/ioutil" + "path/filepath" + + "github.com/OpenBazaar/jsonpb" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" +) + +const defaultProfileFixture = "v5-profile-moderator-fixed-fee" + +func MustLoadProfileFixture(fixtureName string) []byte { + filename := filepath.Join(fixtureLoadPath(), "profiles", fmt.Sprintf("%s.json", fixtureName)) + b, err := ioutil.ReadFile(filename) + if err != nil { + panic(fmt.Sprintf("cannot find fixture (%s): %s", filename, err)) + } + return b +} + +func MustNewProfile() *repo.Profile { + p, err := repo.NewProfileFromProtobuf(MustNewProfileProtobuf()) + if err != nil { + panic(err.Error()) + } + return p +} + +func MustNewProfileProtobuf() *pb.Profile { + var ( + p = new(pb.Profile) + err = jsonpb.UnmarshalString(string(MustLoadProfileFixture(defaultProfileFixture)), p) + ) + if err != nil { + panic(err.Error()) + } + return p +} diff --git a/test/factory/purchase_record.go b/test/factory/purchase_record.go index 1b9b3b58e5..72ddbe60b9 100644 --- a/test/factory/purchase_record.go +++ b/test/factory/purchase_record.go @@ -3,7 +3,7 @@ package factory import ( "time" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) func NewPurchaseRecord() *repo.PurchaseRecord { diff --git a/test/factory/sale_record.go b/test/factory/sale_record.go index eeb95cf41e..7c9369cc63 100644 --- a/test/factory/sale_record.go +++ b/test/factory/sale_record.go @@ -1,7 +1,7 @@ package factory import ( - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) func NewSaleRecord() *repo.SaleRecord { diff --git a/test/factory/settings.go b/test/factory/settings.go new file mode 100644 index 0000000000..7f14b0fc10 --- /dev/null +++ b/test/factory/settings.go @@ -0,0 +1,58 @@ +package factory + +import ( + "encoding/json" + + "github.com/phoreproject/pm-go/repo" +) + +func MustNewValidSettings() repo.SettingsData { + var ( + validSettings = `{ + "paymentDataInQR": true, + "showNotifications": true, + "showNsfw": true, + "shippingAddresses": [], + "localCurrency": "USD", + "country": "United State of Shipping", + "termsAndConditions": "Terms and Conditions", + "refundPolicy": "Refund policy.", + "blockedNodes": [], + "storeModerators": [], + "mispaymentBuffer": 1, + "smtpSettings" : { + "notifications": false, + "openBazaarName": "", + "password": "", + "recipientEmail": "", + "senderEmail": "", + "serverAddress": "", + "username": "" + }, + "version": "", + "preferredCurrencies": ["BTC", "BCH"] + }` + settings repo.SettingsData + ) + if err := json.Unmarshal([]byte(validSettings), &settings); err != nil { + panic(err) + } + settings.ShippingAddresses = &[]repo.ShippingAddress{ + NewValidShippingAddress(), + } + return settings +} + +func NewValidShippingAddress() repo.ShippingAddress { + return repo.ShippingAddress{ + Name: "Shipping Name", + Company: "Shipping Company", + AddressLineOne: "123 Address Street", + AddressLineTwo: "Suite H", + City: "Shipping City", + State: "Shipping State", + Country: "United States of Shipping", + PostalCode: "12345-6789", + AddressNotes: "This is a fake yet valid address for testing.", + } +} diff --git a/test/factory/utxo.go b/test/factory/utxo.go index cb6ce98885..55675cb183 100644 --- a/test/factory/utxo.go +++ b/test/factory/utxo.go @@ -15,7 +15,7 @@ func NewUtxo() wallet.Utxo { return wallet.Utxo{ Op: *outpoint, AtHeight: 300000, - Value: 100000000, + Value: "100000000", ScriptPubkey: []byte("scriptpubkey"), WatchOnly: false, } diff --git a/test/node.go b/test/node.go index c7b0f7fede..e72753ed12 100644 --- a/test/node.go +++ b/test/node.go @@ -12,10 +12,10 @@ import ( "github.com/btcsuite/btcutil/hdkeychain" "github.com/phoreproject/multiwallet" "github.com/phoreproject/multiwallet/config" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/ipfs" - "github.com/phoreproject/openbazaar-go/net" - "github.com/phoreproject/openbazaar-go/net/service" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/net" + "github.com/phoreproject/pm-go/net/service" coremock "github.com/ipfs/go-ipfs/core/mock" "github.com/tyler-smith/go-bip39" @@ -59,7 +59,7 @@ func NewNode() (*core.OpenBazaarNode, error) { ipfsNode.Identity = id // Create test wallet - mnemonic, err := repository.DB.Config().GetMnemonic() + mnemonic, _, err := repository.DB.Config().GetMnemonic() if err != nil { return nil, err } @@ -100,6 +100,7 @@ func NewNode() (*core.OpenBazaarNode, error) { BanManager: net.NewBanManager([]peer.ID{}), MasterPrivateKey: mPrivKey, DHT: routing, + TestnetEnable: true, } node.Service = service.New(node, repository.DB) diff --git a/test/repo.go b/test/repo.go index 179ef057af..b105464fb2 100644 --- a/test/repo.go +++ b/test/repo.go @@ -6,8 +6,8 @@ import ( "time" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" ) // Repository represents a test (temporary/volitile) repository diff --git a/tools/getrev.sh b/tools/getrev.sh new file mode 100644 index 0000000000..e69de29bb2 diff --git a/util/utils.go b/util/utils.go new file mode 100644 index 0000000000..cde76f84e6 --- /dev/null +++ b/util/utils.go @@ -0,0 +1,74 @@ +package util + +import ( + "strings" +) + +const EmojiPattern = "[\\x{2712}\\x{2714}\\x{2716}\\x{271d}\\x{2721}\\x{2728}\\x{2733}" + + "\\x{2734}\\x{2744}\\x{2747}\\x{274c}\\x{274e}\\x{2753}-\\x{2755}\\x{2757}" + + "\\x{2763}\\x{2764}\\x{2795}-\\x{2797}\\x{27a1}\\x{27b0}\\x{27bf}\\x{2934}" + + "\\x{2935}\\x{2b05}-\\x{2b07}\\x{2b1b}\\x{2b1c}\\x{2b50}\\x{2b55}\\x{3030}" + + "\\x{303d}\\x{1f004}\\x{1f0cf}\\x{1f170}\\x{1f171}\\x{1f17e}\\x{1f17f}" + + "\\x{1f18e}\\x{1f191}-\\x{1f19a}\\x{1f201}\\x{1f202}\\x{1f21a}\\x{1f22f}" + + "\\x{1f232}-\\x{1f23a}\\x{1f250}\\x{1f251}\\x{1f300}-\\x{1f321}\\x{1f324}-" + + "\\x{1f393}\\x{1f396}\\x{1f397}\\x{1f399}-\\x{1f39b}\\x{1f39e}-\\x{1f3f0}" + + "\\x{1f3f3}-\\x{1f3f5}\\x{1f3f7}-\\x{1f4fd}\\x{1f4ff}-\\x{1f53d}\\x{1f549}-" + + "\\x{1f54e}\\x{1f550}-\\x{1f567}\\x{1f56f}\\x{1f570}\\x{1f573}-\\x{1f579}" + + "\\x{1f587}\\x{1f58a}-\\x{1f58d}\\x{1f590}\\x{1f595}\\x{1f596}\\x{1f5a5}" + + "\\x{1f5a8}\\x{1f5b1}\\x{1f5b2}\\x{1f5bc}\\x{1f5c2}-\\x{1f5c4}\\x{1f5d1}-" + + "\\x{1f5d3}\\x{1f5dc}-\\x{1f5de}\\x{1f5e1}\\x{1f5e3}\\x{1f5ef}\\x{1f5f3}" + + "\\x{1f5fa}-\\x{1f64f}\\x{1f680}-\\x{1f6c5}\\x{1f6cb}-\\x{1f6d0}\\x{1f6e0}-" + + "\\x{1f6e5}\\x{1f6e9}\\x{1f6eb}\\x{1f6ec}\\x{1f6f0}\\x{1f6f3}\\x{1f910}-" + + "\\x{1f918}\\x{1f980}-\\x{1f984}\\x{1f9c0}\\x{3297}\\x{3299}\\x{a9}\\x{ae}" + + "\\x{203c}\\x{2049}\\x{2122}\\x{2139}\\x{2194}-\\x{2199}\\x{21a9}\\x{21aa}" + + "\\x{231a}\\x{231b}\\x{2328}\\x{2388}\\x{23cf}\\x{23e9}-\\x{23f3}\\x{23f8}-" + + "\\x{23fa}\\x{24c2}\\x{25aa}\\x{25ab}\\x{25b6}\\x{25c0}\\x{25fb}-\\x{25fe}" + + "\\x{2600}-\\x{2604}\\x{260e}\\x{2611}\\x{2614}\\x{2615}\\x{2618}\\x{261d}" + + "\\x{2620}\\x{2622}\\x{2623}\\x{2626}\\x{262a}\\x{262e}\\x{262f}\\x{2638}-" + + "\\x{263a}\\x{2648}-\\x{2653}\\x{2660}\\x{2663}\\x{2665}\\x{2666}\\x{2668}" + + "\\x{267b}\\x{267f}\\x{2692}-\\x{2694}\\x{2696}\\x{2697}\\x{2699}\\x{269b}" + + "\\x{269c}\\x{26a0}\\x{26a1}\\x{26aa}\\x{26ab}\\x{26b0}\\x{26b1}\\x{26bd}" + + "\\x{26be}\\x{26c4}\\x{26c5}\\x{26c8}\\x{26ce}\\x{26cf}\\x{26d1}\\x{26d3}" + + "\\x{26d4}\\x{26e9}\\x{26ea}\\x{26f0}-\\x{26f5}\\x{26f7}-\\x{26fa}\\x{26fd}" + + "\\x{2702}\\x{2705}\\x{2708}-\\x{270d}\\x{270f}]|\\x{23}\\x{20e3}|\\x{2a}" + + "\\x{20e3}|\\x{30}\\x{20e3}|\\x{31}\\x{20e3}|\\x{32}\\x{20e3}|\\x{33}\\x{20e3}|" + + "\\x{34}\\x{20e3}|\\x{35}\\x{20e3}|\\x{36}\\x{20e3}|\\x{37}\\x{20e3}|\\x{38}" + + "\\x{20e3}|\\x{39}\\x{20e3}|\\x{1f1e6}[\\x{1f1e8}-\\x{1f1ec}\\x{1f1ee}" + + "\\x{1f1f1}\\x{1f1f2}\\x{1f1f4}\\x{1f1f6}-\\x{1f1fa}\\x{1f1fc}\\x{1f1fd}" + + "\\x{1f1ff}]|\\x{1f1e7}[\\x{1f1e6}\\x{1f1e7}\\x{1f1e9}-\\x{1f1ef}\\x{1f1f1}-" + + "\\x{1f1f4}\\x{1f1f6}-\\x{1f1f9}\\x{1f1fb}\\x{1f1fc}\\x{1f1fe}\\x{1f1ff}]|" + + "\\x{1f1e8}[\\x{1f1e6}\\x{1f1e8}\\x{1f1e9}\\x{1f1eb}-\\x{1f1ee}\\x{1f1f0}-" + + "\\x{1f1f5}\\x{1f1f7}\\x{1f1fa}-\\x{1f1ff}]|\\x{1f1e9}[\\x{1f1ea}\\x{1f1ec}" + + "\\x{1f1ef}\\x{1f1f0}\\x{1f1f2}\\x{1f1f4}\\x{1f1ff}]|\\x{1f1ea}[\\x{1f1e6}" + + "\\x{1f1e8}\\x{1f1ea}\\x{1f1ec}\\x{1f1ed}\\x{1f1f7}-\\x{1f1fa}]|\\x{1f1eb}[" + + "\\x{1f1ee}-\\x{1f1f0}\\x{1f1f2}\\x{1f1f4}\\x{1f1f7}]|\\x{1f1ec}[\\x{1f1e6}" + + "\\x{1f1e7}\\x{1f1e9}-\\x{1f1ee}\\x{1f1f1}-\\x{1f1f3}\\x{1f1f5}-\\x{1f1fa}" + + "\\x{1f1fc}\\x{1f1fe}]|\\x{1f1ed}[\\x{1f1f0}\\x{1f1f2}\\x{1f1f3}\\x{1f1f7}" + + "\\x{1f1f9}\\x{1f1fa}]|\\x{1f1ee}[\\x{1f1e8}-\\x{1f1ea}\\x{1f1f1}-\\x{1f1f4}" + + "\\x{1f1f6}-\\x{1f1f9}]|\\x{1f1ef}[\\x{1f1ea}\\x{1f1f2}\\x{1f1f4}\\x{1f1f5}]" + + "|\\x{1f1f0}[\\x{1f1ea}\\x{1f1ec}-\\x{1f1ee}\\x{1f1f2}\\x{1f1f3}\\x{1f1f5}" + + "\\x{1f1f7}\\x{1f1fc}\\x{1f1fe}\\x{1f1ff}]|\\x{1f1f1}[\\x{1f1e6}-\\x{1f1e8}" + + "\\x{1f1ee}\\x{1f1f0}\\x{1f1f7}-\\x{1f1fb}\\x{1f1fe}]|\\x{1f1f2}[\\x{1f1e6}" + + "\\x{1f1e8}-\\x{1f1ed}\\x{1f1f0}-\\x{1f1ff}]|\\x{1f1f3}[\\x{1f1e6}\\x{1f1e8}" + + "\\x{1f1ea}-\\x{1f1ec}\\x{1f1ee}\\x{1f1f1}\\x{1f1f4}\\x{1f1f5}\\x{1f1f7}" + + "\\x{1f1fa}\\x{1f1ff}]|\\x{1f1f4}\\x{1f1f2}|\\x{1f1f5}[\\x{1f1e6}\\x{1f1ea}-" + + "\\x{1f1ed}\\x{1f1f0}-\\x{1f1f3}\\x{1f1f7}-\\x{1f1f9}\\x{1f1fc}\\x{1f1fe}]|" + + "\\x{1f1f6}\\x{1f1e6}|\\x{1f1f7}[\\x{1f1ea}\\x{1f1f4}\\x{1f1f8}\\x{1f1fa}" + + "\\x{1f1fc}]|\\x{1f1f8}[\\x{1f1e6}-\\x{1f1ea}\\x{1f1ec}-\\x{1f1f4}\\x{1f1f7}-" + + "\\x{1f1f9}\\x{1f1fb}\\x{1f1fd}-\\x{1f1ff}]|\\x{1f1f9}[\\x{1f1e6}\\x{1f1e8}" + + "\\x{1f1e9}\\x{1f1eb}-\\x{1f1ed}\\x{1f1ef}-\\x{1f1f4}\\x{1f1f7}\\x{1f1f9}" + + "\\x{1f1fb}\\x{1f1fc}\\x{1f1ff}]|\\x{1f1fa}[\\x{1f1e6}\\x{1f1ec}\\x{1f1f2}" + + "\\x{1f1f8}\\x{1f1fe}\\x{1f1ff}]|\\x{1f1fb}[\\x{1f1e6}\\x{1f1e8}\\x{1f1ea}" + + "\\x{1f1ec}\\x{1f1ee}\\x{1f1f3}\\x{1f1fa}]|\\x{1f1fc}[\\x{1f1eb}\\x{1f1f8}]|" + + "\\x{1f1fd}\\x{1f1f0}|\\x{1f1fe}[\\x{1f1ea}\\x{1f1f9}]|\\x{1f1ff}[\\x{1f1e6}" + + "\\x{1f1f2}\\x{1f1fc}]" + +// NormalizeAddress is used to strip the 0x prefix +func NormalizeAddress(addr string) string { + return strings.TrimPrefix(addr, "0x") +} + +// AreAddressesEqual - check if addresses are equal after normalizing them +func AreAddressesEqual(addr1, addr2 string) bool { + return NormalizeAddress(addr1) == NormalizeAddress(addr2) +} diff --git a/vendor/github.com/OpenBazaar/bitcoind-wallet/.gitignore b/vendor/github.com/OpenBazaar/bitcoind-wallet/.gitignore new file mode 100644 index 0000000000..2621f4ad2c --- /dev/null +++ b/vendor/github.com/OpenBazaar/bitcoind-wallet/.gitignore @@ -0,0 +1,42 @@ +# Test artifacts + +repo/testdata/ + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so +*.pyc + +# Folders +_obj +_test +__pycache__ + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +.idea/ +*.iml +.gx/ +dist + +# Development environment files +.ackrc +.tags* +*.sw? + +# macOS +.DS_Store diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/LICENSE b/vendor/github.com/OpenBazaar/bitcoind-wallet/LICENSE similarity index 100% rename from vendor/github.com/OpenBazaar/go-ethwallet/LICENSE rename to vendor/github.com/OpenBazaar/bitcoind-wallet/LICENSE diff --git a/vendor/github.com/OpenBazaar/bitcoind-wallet/README.md b/vendor/github.com/OpenBazaar/bitcoind-wallet/README.md new file mode 100644 index 0000000000..df0d899579 --- /dev/null +++ b/vendor/github.com/OpenBazaar/bitcoind-wallet/README.md @@ -0,0 +1,2 @@ +# bitcoind-wallet +OpenBazaar plugin for a bitcoind based wallet diff --git a/vendor/github.com/OpenBazaar/bitcoind-wallet/notify.go b/vendor/github.com/OpenBazaar/bitcoind-wallet/notify.go new file mode 100644 index 0000000000..2d2db44b18 --- /dev/null +++ b/vendor/github.com/OpenBazaar/bitcoind-wallet/notify.go @@ -0,0 +1,111 @@ +package bitcoind + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "time" + + "github.com/OpenBazaar/wallet-interface" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + btcrpcclient "github.com/btcsuite/btcd/rpcclient" +) + +type NotificationListener struct { + client *btcrpcclient.Client + listeners []func(wallet.TransactionCallback) + params *chaincfg.Params +} + +func (l *NotificationListener) notify(w http.ResponseWriter, r *http.Request) { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + return + } + txid := string(b) + hash, err := chainhash.NewHashFromStr(txid) + if err != nil { + log.Error(err) + return + } + tx, err := l.client.GetRawTransaction(hash) + if err != nil { + log.Error(err) + return + } + watchOnly := false + txInfo, err := l.client.GetTransaction(hash, &watchOnly) + if err != nil { + watchOnly = true + } + var outputs []wallet.TransactionOutput + for i, txout := range tx.MsgTx().TxOut { + addr, _ := scriptToAddress(txout.PkScript, l.params) + out := wallet.TransactionOutput{Address: addr, Value: txout.Value, Index: uint32(i)} + outputs = append(outputs, out) + } + var inputs []wallet.TransactionInput + for _, txin := range tx.MsgTx().TxIn { + in := wallet.TransactionInput{OutpointHash: txin.PreviousOutPoint.Hash.CloneBytes(), OutpointIndex: txin.PreviousOutPoint.Index} + prev, err := l.client.GetRawTransaction(&txin.PreviousOutPoint.Hash) + if err != nil { + inputs = append(inputs, in) + continue + } + addr, _ := scriptToAddress(prev.MsgTx().TxOut[txin.PreviousOutPoint.Index].PkScript, l.params) + in.LinkedAddress = addr + in.Value = prev.MsgTx().TxOut[txin.PreviousOutPoint.Index].Value + inputs = append(inputs, in) + } + + height := int32(0) + if txInfo.Confirmations > 0 { + hash, err := chainhash.NewHashFromStr(txInfo.BlockHash) + if err != nil { + log.Error(err) + return + } + h := `` + if hash != nil { + h += `"` + hash.String() + `"` + } + resp, err := l.client.RawRequest("getblockheader", []json.RawMessage{json.RawMessage(h)}) + if err != nil { + log.Error(err) + return + } + type Respose struct { + Height int32 `json:"height"` + } + r := new(Respose) + err = json.Unmarshal([]byte(resp), r) + if err != nil { + log.Error(err) + return + } + height = r.Height + } + cb := wallet.TransactionCallback{ + Txid: tx.Hash().String(), + Inputs: inputs, + Outputs: outputs, + WatchOnly: watchOnly, + Value: int64(txInfo.Amount * 100000000), + Timestamp: time.Unix(txInfo.TimeReceived, 0), + Height: height, + } + for _, lis := range l.listeners { + lis(cb) + } +} + +func StartNotificationListener(client *btcrpcclient.Client, params *chaincfg.Params, listeners []func(wallet.TransactionCallback)) { + l := NotificationListener{ + client: client, + listeners: listeners, + params: params, + } + http.HandleFunc("/", l.notify) + http.ListenAndServe(":8330", nil) +} diff --git a/vendor/github.com/OpenBazaar/bitcoind-wallet/wallet.go b/vendor/github.com/OpenBazaar/bitcoind-wallet/wallet.go new file mode 100644 index 0000000000..37da804d0b --- /dev/null +++ b/vendor/github.com/OpenBazaar/bitcoind-wallet/wallet.go @@ -0,0 +1,1154 @@ +package bitcoind + +import ( + "bufio" + "bytes" + "crypto/rand" + "crypto/sha256" + "encoding/base64" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "os" + "os/exec" + "path" + "runtime" + "strconv" + "strings" + "time" + + "github.com/OpenBazaar/spvwallet" + "github.com/OpenBazaar/spvwallet/exchangerates" + "github.com/OpenBazaar/wallet-interface" + "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + btcrpcclient "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + btc "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcutil/coinset" + hd "github.com/btcsuite/btcutil/hdkeychain" + "github.com/btcsuite/btcutil/txsort" + "github.com/btcsuite/btcwallet/wallet/txrules" + "github.com/op/go-logging" + b39 "github.com/tyler-smith/go-bip39" + "golang.org/x/net/proxy" +) + +var log = logging.MustGetLogger("bitcoind") + +const ( + Account = "OpenBazaar" +) + +type BitcoindWallet struct { + params *chaincfg.Params + repoPath string + trustedPeer string + masterPrivateKey *hd.ExtendedKey + masterPublicKey *hd.ExtendedKey + listeners []func(wallet.TransactionCallback) + rpcClient *btcrpcclient.Client + binary string + controlPort int + useTor bool + addrsToWatch []btc.Address + initChan chan struct{} + exchangeRates wallet.ExchangeRates +} + +var connCfg *btcrpcclient.ConnConfig = &btcrpcclient.ConnConfig{ + Host: "localhost:8332", + HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode + DisableTLS: true, // Bitcoin core does not provide TLS by default + DisableAutoReconnect: false, + DisableConnectOnNew: false, +} + +func NewBitcoindWallet(mnemonic string, params *chaincfg.Params, repoPath string, trustedPeer string, binary string, useTor bool, torControlPort int, proxy proxy.Dialer, disableExchangeRates bool) (*BitcoindWallet, error) { + seed := b39.NewSeed(mnemonic, "") + mPrivKey, _ := hd.NewMaster(seed, params) + mPubKey, _ := mPrivKey.Neuter() + + if params.Name == chaincfg.TestNet3Params.Name || params.Name == chaincfg.RegressionNetParams.Name { + connCfg.Host = "localhost:18332" + } + + dataDir := path.Join(repoPath, "zcash") + var err error + connCfg.User, connCfg.Pass, err = GetCredentials(repoPath) + if err != nil { + return nil, err + } + + if trustedPeer != "" { + trustedPeer = strings.Split(trustedPeer, ":")[0] + } + + w := BitcoindWallet{ + params: params, + repoPath: dataDir, + trustedPeer: trustedPeer, + masterPrivateKey: mPrivKey, + masterPublicKey: mPubKey, + binary: binary, + controlPort: torControlPort, + useTor: useTor, + initChan: make(chan struct{}), + } + if !disableExchangeRates { + w.exchangeRates = exchangerates.NewBitcoinPriceFetcher(proxy) + } + return &w, nil +} + +// TestNetworkEnabled indicates if the current network being used is Test Network +func (w *BitcoindWallet) TestNetworkEnabled() bool { + return w.params.Name == chaincfg.TestNet3Params.Name +} + +// RegressionNetworkEnabled indicates if the current network being used is Regression Network +func (w *BitcoindWallet) RegressionNetworkEnabled() bool { + return w.params.Name == chaincfg.RegressionNetParams.Name +} + +// MainNetworkEnabled indicates if the current network being used is the live Network +func (w *BitcoindWallet) MainNetworkEnabled() bool { + return w.params.Name == chaincfg.MainNetParams.Name +} + +func GetCredentials(repoPath string) (username, password string, err error) { + p := path.Join(repoPath, "bitcoin", "bitcoin.conf") + if _, err := os.Stat(p); os.IsNotExist(err) { + dataDir := path.Join(repoPath, "bitcoin") + os.Mkdir(dataDir, os.ModePerm) + + r := make([]byte, 32) + _, err := rand.Read(r) + if err != nil { + return "", "", err + } + password := base64.StdEncoding.EncodeToString(r) + + user := fmt.Sprintf(`rpcuser=%s`, "OpenBazaar") + pass := fmt.Sprintf(`rpcpassword=%s`, password) + + f, err := os.Create(p) + if err != nil { + return "", "", err + } + defer f.Close() + wr := bufio.NewWriter(f) + fmt.Fprintln(wr, user) + fmt.Fprintln(wr, pass) + wr.Flush() + return "OpenBazaar", password, nil + } else { + file, err := os.Open(p) + if err != nil { + log.Fatal(err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + var unExists, pwExists bool + for scanner.Scan() { + if strings.Contains(scanner.Text(), "rpcuser=") { + username = scanner.Text()[8:] + unExists = true + } else if strings.Contains(scanner.Text(), "rpcpassword=") { + password = scanner.Text()[12:] + pwExists = true + } + } + if !unExists || !pwExists { + return "", "", errors.New("Bitcoin config file does not contain a username and password") + } + + if err := scanner.Err(); err != nil { + return "", "", err + } + return username, password, nil + } +} + +func (w *BitcoindWallet) addQueuedWatchAddresses() { + for _, addr := range w.addrsToWatch { + w.addWatchedScript(addr) + } +} + +func (w *BitcoindWallet) InitChan() chan struct{} { + return w.initChan +} + +func (w *BitcoindWallet) BuildArguments(rescan bool) []string { + var notify string + switch runtime.GOOS { + case "windows": + notify = `powershell.exe Invoke-WebRequest -Uri http://localhost:8330/ -Method POST -Body %s` + default: + notify = `curl -d %s http://localhost:8330/` + } + args := []string{"-walletnotify=" + notify, "-server", "-wallet=ob-wallet.dat", "-conf=" + path.Join(w.repoPath, "bitcoin.conf")} + if rescan { + args = append(args, "-rescan") + } + args = append(args, "-torcontrol=127.0.0.1:"+strconv.Itoa(w.controlPort)) + + if w.TestNetworkEnabled() { + args = append(args, "-testnet") + } else if w.RegressionNetworkEnabled() { + args = append(args, "-regtest") + } + if w.trustedPeer != "" { + args = append(args, "-connect="+w.trustedPeer) + } + if w.useTor { + socksPort := DefaultSocksPort(w.controlPort) + args = append(args, "-listen", "-proxy:127.0.0.1:"+strconv.Itoa(socksPort), "-onlynet=onion") + } + return args +} + +func (w *BitcoindWallet) Start() { + w.shutdownIfActive() + args := w.BuildArguments(false) + client, _ := btcrpcclient.New(connCfg, nil) + w.rpcClient = client + go StartNotificationListener(client, w.params, w.listeners) + + cmd := exec.Command(w.binary, args...) + go cmd.Start() + ticker := time.NewTicker(time.Second * 30) + go func() { + for range ticker.C { + log.Fatal("Failed to connect to bitcoind") + } + }() + for { + _, err := client.GetBlockCount() + if err == nil { + break + } + time.Sleep(time.Second) + } + ticker.Stop() + log.Info("Connected to bitcoind") + close(w.initChan) + go w.addQueuedWatchAddresses() +} + +// If bitcoind is already running let's shut it down so we restart it with our options +func (w *BitcoindWallet) shutdownIfActive() { + client, err := btcrpcclient.New(connCfg, nil) + if err != nil { + return + } + client.RawRequest("stop", []json.RawMessage{}) + client.Shutdown() + time.Sleep(5 * time.Second) +} + +func (w *BitcoindWallet) CurrencyCode() string { + if w.MainNetworkEnabled() { + return "btc" + } else { + return "tbtc" + } +} + +func (w *BitcoindWallet) IsDust(amount int64) bool { + return txrules.IsDustAmount(btc.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +} + +func (w *BitcoindWallet) MasterPrivateKey() *hd.ExtendedKey { + return w.masterPrivateKey +} + +func (w *BitcoindWallet) MasterPublicKey() *hd.ExtendedKey { + return w.masterPublicKey +} + +func (w *BitcoindWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) { + parentFP := []byte{0x00, 0x00, 0x00, 0x00} + var id []byte + if isPrivateKey { + id = w.params.HDPrivateKeyID[:] + } else { + id = w.params.HDPublicKeyID[:] + } + hdKey := hd.NewExtendedKey( + id, + keyBytes, + chaincode, + parentFP, + 0, + 0, + isPrivateKey) + return hdKey.Child(0) +} + +func (w *BitcoindWallet) CurrentAddress(purpose wallet.KeyPurpose) btc.Address { + <-w.initChan + addr, _ := w.rpcClient.GetAccountAddress(Account) + return addr +} + +func (w *BitcoindWallet) NewAddress(purpose wallet.KeyPurpose) btc.Address { + <-w.initChan + addr, _ := w.rpcClient.GetNewAddress(Account) + return addr +} + +func (w *BitcoindWallet) DecodeAddress(addr string) (btc.Address, error) { + return btc.DecodeAddress(addr, w.params) +} + +func (w *BitcoindWallet) ScriptToAddress(script []byte) (btc.Address, error) { + return scriptToAddress(script, w.params) +} + +func scriptToAddress(script []byte, params *chaincfg.Params) (btc.Address, error) { + _, addrs, _, err := txscript.ExtractPkScriptAddrs(script, params) + if err != nil { + return nil, err + } + if len(addrs) == 0 { + return nil, errors.New("unknown script") + } + return addrs[0], nil +} + +func (w *BitcoindWallet) AddressToScript(addr btc.Address) ([]byte, error) { + return txscript.PayToAddrScript(addr) +} + +func (w *BitcoindWallet) HasKey(addr btc.Address) bool { + <-w.initChan + _, err := w.rpcClient.DumpPrivKey(addr) + if err != nil { + return false + } + return true +} + +func (w *BitcoindWallet) Balance() (confirmed, unconfirmed int64) { + <-w.initChan + resp, _ := w.rpcClient.RawRequest("getwalletinfo", []json.RawMessage{}) + type walletInfo struct { + Balance float64 `json:"balance"` + Unconfirmed float64 `json:"unconfirmed_balance"` + } + respBytes, _ := resp.MarshalJSON() + i := new(walletInfo) + json.Unmarshal(respBytes, i) + c, _ := btc.NewAmount(i.Balance) + u, _ := btc.NewAmount(i.Unconfirmed) + return int64(c.ToUnit(btc.AmountSatoshi)), int64(u.ToUnit(btc.AmountSatoshi)) +} + +func (w *BitcoindWallet) GetBlockHeight(hash *chainhash.Hash) (int32, error) { + <-w.initChan + blockinfo, err := w.rpcClient.GetBlockHeaderVerbose(hash) + if err != nil { + return 0, err + } + return blockinfo.Height, nil +} + +func (w *BitcoindWallet) Transactions() ([]wallet.Txn, error) { + <-w.initChan + var ret []wallet.Txn + resp, err := w.rpcClient.ListTransactions(Account) + if err != nil { + return ret, err + } + for _, r := range resp { + amt, err := btc.NewAmount(r.Amount) + if err != nil { + return ret, err + } + ts := time.Unix(r.TimeReceived, 0) + height := int32(0) + if r.Confirmations > 0 { + h, err := chainhash.NewHashFromStr(r.BlockHash) + if err != nil { + return ret, err + } + height, err = w.GetBlockHeight(h) + if err != nil { + return ret, err + } + } + + var confirmations int32 + var status wallet.StatusCode + confs := int32(height) - height + 1 + if height <= 0 { + confs = height + } + switch { + case confs < 0: + status = wallet.StatusDead + case confs == 0 && time.Since(ts) <= time.Hour*6: + status = wallet.StatusUnconfirmed + case confs == 0 && time.Since(ts) > time.Hour*6: + status = wallet.StatusStuck + case confs > 0 && confs < 6: + status = wallet.StatusPending + confirmations = confs + case confs > 5: + status = wallet.StatusConfirmed + confirmations = confs + } + + t := wallet.Txn{ + Txid: r.TxID, + Value: int64(amt.ToUnit(btc.AmountSatoshi)), + Height: height, + Timestamp: ts, + Confirmations: int64(confirmations), + Status: status, + } + ret = append(ret, t) + } + return ret, nil +} + +func (w *BitcoindWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) { + <-w.initChan + includeWatchOnly := false + t := wallet.Txn{} + resp, err := w.rpcClient.GetTransaction(&txid, &includeWatchOnly) + if err != nil { + return t, err + } + + t.Txid = resp.TxID + t.Value = int64(resp.Amount * 100000000) + t.Height = int32(resp.BlockIndex) + t.Timestamp = time.Unix(resp.TimeReceived, 0) + t.WatchOnly = false + + raw, err := w.rpcClient.GetRawTransaction(&txid) + if err != nil { + return t, err + } + + outs := []wallet.TransactionOutput{} + for i, out := range raw.MsgTx().TxOut { + var addr btc.Address + _, addrs, _, err := txscript.ExtractPkScriptAddrs(out.PkScript, w.params) + if err != nil { + log.Warningf("error extracting address from txn pkscript: %v\n", err) + } + if len(addrs) != 0 { + addr = addrs[0] + } + tout := wallet.TransactionOutput{ + Address: addr, + Value: out.Value, + Index: uint32(i), + } + outs = append(outs, tout) + } + t.Outputs = outs + + return t, nil +} + +func (w *BitcoindWallet) GetConfirmations(txid chainhash.Hash) (uint32, uint32, error) { + <-w.initChan + includeWatchOnly := true + resp, err := w.rpcClient.GetTransaction(&txid, &includeWatchOnly) + if err != nil { + return 0, 0, err + } + return uint32(resp.Confirmations), uint32(resp.BlockIndex), nil +} + +func (w *BitcoindWallet) ChainTip() (uint32, chainhash.Hash) { + <-w.initChan + var ch chainhash.Hash + info, err := w.rpcClient.GetInfo() + if err != nil { + return uint32(0), ch + } + h, err := w.rpcClient.GetBestBlockHash() + if err != nil { + return uint32(0), ch + } + return uint32(info.Blocks), *h +} + +func (w *BitcoindWallet) gatherCoins() (map[coinset.Coin]*hd.ExtendedKey, error) { + <-w.initChan + m := make(map[coinset.Coin]*hd.ExtendedKey) + utxos, err := w.rpcClient.ListUnspent() + if err != nil { + return m, err + } + for _, u := range utxos { + if !u.Spendable { + continue + } + txhash, err := chainhash.NewHashFromStr(u.TxID) + if err != nil { + return m, err + } + addr, err := btc.DecodeAddress(u.Address, w.params) + if err != nil { + return m, err + } + scriptPubkey, err := w.AddressToScript(addr) + if err != nil { + return m, err + } + c := spvwallet.NewCoin(txhash.CloneBytes(), u.Vout, btc.Amount(u.Amount*100000000), u.Confirmations, scriptPubkey) + + wif, err := w.rpcClient.DumpPrivKey(addr) + if err != nil { + return m, err + } + key := hd.NewExtendedKey( + w.params.HDPrivateKeyID[:], + wif.PrivKey.Serialize(), + make([]byte, 32), + []byte{0x00, 0x00, 0x00, 0x00}, + 0, + 0, + true) + m[c] = key + } + return m, nil +} + +func (w *BitcoindWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLevel) (*chainhash.Hash, error) { + <-w.initChan + tx, err := w.buildTx(amount, addr, feeLevel) + if err != nil { + return nil, err + } + return w.rpcClient.SendRawTransaction(tx, false) +} + +func (w *BitcoindWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeLevel) (*wire.MsgTx, error) { + script, _ := txscript.PayToAddrScript(addr) + if txrules.IsDustAmount(btc.Amount(amount), len(script), txrules.DefaultRelayFeePerKb) { + return nil, wallet.ErrorDustAmount + } + + var additionalPrevScripts map[wire.OutPoint][]byte + var additionalKeysByAddress map[string]*btc.WIF + + // Create input source + coinMap, err := w.gatherCoins() + if err != nil { + return nil, err + } + coins := make([]coinset.Coin, 0, len(coinMap)) + for k := range coinMap { + coins = append(coins, k) + } + inputSource := func(target btc.Amount) (total btc.Amount, inputs []*wire.TxIn, amounts []btc.Amount, scripts [][]byte, err error) { + coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)} + coins, err := coinSelector.CoinSelect(target, coins) + if err != nil { + return total, inputs, []btc.Amount{}, scripts, wallet.ErrorInsuffientFunds + } + additionalPrevScripts = make(map[wire.OutPoint][]byte) + additionalKeysByAddress = make(map[string]*btc.WIF) + for _, c := range coins.Coins() { + total += c.Value() + outpoint := wire.NewOutPoint(c.Hash(), c.Index()) + in := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) + in.Sequence = 0 // Opt-in RBF so we can bump fees + inputs = append(inputs, in) + additionalPrevScripts[*outpoint] = c.PkScript() + key := coinMap[c] + addr, err := key.Address(w.params) + if err != nil { + continue + } + privKey, err := key.ECPrivKey() + if err != nil { + continue + } + wif, _ := btc.NewWIF(privKey, w.params, true) + additionalKeysByAddress[addr.EncodeAddress()] = wif + } + return total, inputs, []btc.Amount{}, scripts, nil + } + + // Get the fee per kilobyte + feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + + // outputs + out := wire.NewTxOut(amount, script) + + // Create change source + changeSource := func() ([]byte, error) { + addr := w.CurrentAddress(wallet.INTERNAL) + script, err := txscript.PayToAddrScript(addr) + if err != nil { + return []byte{}, err + } + return script, nil + } + + outputs := []*wire.TxOut{out} + authoredTx, err := spvwallet.NewUnsignedTransaction(outputs, btc.Amount(feePerKB), inputSource, changeSource) + if err != nil { + return nil, err + } + + // BIP 69 sorting + txsort.InPlaceSort(authoredTx.Tx) + + // Sign tx + getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { + addrStr := addr.EncodeAddress() + wif := additionalKeysByAddress[addrStr] + return wif.PrivKey, wif.CompressPubKey, nil + }) + getScript := txscript.ScriptClosure(func( + addr btc.Address) ([]byte, error) { + return []byte{}, nil + }) + for i, txIn := range authoredTx.Tx.TxIn { + prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] + script, err := txscript.SignTxOutput(w.params, + authoredTx.Tx, i, prevOutScript, txscript.SigHashAll, getKey, + getScript, txIn.SignatureScript) + if err != nil { + return nil, errors.New("Failed to sign transaction") + } + txIn.SignatureScript = script + } + return authoredTx.Tx, nil +} + +func (w *BitcoindWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { + <-w.initChan + includeWatchOnly := false + tx, err := w.rpcClient.GetTransaction(&txid, &includeWatchOnly) + if err != nil { + return nil, err + } + if tx.Confirmations > 0 { + return nil, spvwallet.BumpFeeAlreadyConfirmedError + } + unspent, err := w.rpcClient.ListUnspent() + if err != nil { + return nil, err + } + for _, u := range unspent { + if u.TxID == txid.String() { + if u.Confirmations > 0 { + return nil, spvwallet.BumpFeeAlreadyConfirmedError + } + h, err := chainhash.NewHashFromStr(u.TxID) + if err != nil { + continue + } + addr, err := btc.DecodeAddress(u.Address, w.params) + if err != nil { + continue + } + key, err := w.rpcClient.DumpPrivKey(addr) + if err != nil { + continue + } + in := wallet.TransactionInput{ + LinkedAddress: addr, + OutpointIndex: u.Vout, + OutpointHash: h.CloneBytes(), + Value: int64(u.Amount), + } + hdKey := hd.NewExtendedKey(w.params.HDPrivateKeyID[:], key.PrivKey.Serialize(), make([]byte, 32), make([]byte, 4), 0, 0, true) + transactionID, err := w.SweepAddress([]wallet.TransactionInput{in}, nil, hdKey, nil, wallet.FEE_BUMP) + if err != nil { + return nil, err + } + return transactionID, nil + } + } + return nil, spvwallet.BumpFeeNotFoundError +} + +func (w *BitcoindWallet) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 { + <-w.initChan + defautlFee := uint64(50) + var nBlocks json.RawMessage + switch feeLevel { + case wallet.PRIOIRTY: + nBlocks = json.RawMessage([]byte(`1`)) + case wallet.NORMAL: + nBlocks = json.RawMessage([]byte(`3`)) + case wallet.ECONOMIC: + nBlocks = json.RawMessage([]byte(`6`)) + default: + return defautlFee + } + resp, err := w.rpcClient.RawRequest("estimatefee", []json.RawMessage{nBlocks}) + if err != nil { + return defautlFee + } + feePerKb, err := strconv.Atoi(string(resp)) + if err != nil { + return defautlFee + } + if feePerKb <= 0 { + return defautlFee + } + fee := feePerKb / 1000 + return uint64(fee) +} + +func (w *BitcoindWallet) EstimateFee(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, feePerByte uint64) uint64 { + tx := wire.NewMsgTx(wire.TxVersion) + for _, out := range outs { + scriptPubKey, _ := txscript.PayToAddrScript(out.Address) + output := wire.NewTxOut(out.Value, scriptPubKey) + tx.TxOut = append(tx.TxOut, output) + } + estimatedSize := spvwallet.EstimateSerializeSize(len(ins), tx.TxOut, false, spvwallet.P2PKH) + fee := estimatedSize * int(feePerByte) + return uint64(fee) +} + +func (w *BitcoindWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (uint64, error) { + <-w.initChan + // Since this is an estimate we can use a dummy output address. Let's use a long one so we don't under estimate. + addr, err := btc.DecodeAddress("bc1qxtq7ha2l5qg70atpwp3fus84fx3w0v2w4r2my7gt89ll3w0vnlgspu349h", &chaincfg.MainNetParams) + if err != nil { + return 0, err + } + tx, err := w.buildTx(amount, addr, feeLevel) + if err != nil { + return 0, err + } + var outval int64 + for _, output := range tx.TxOut { + outval += output.Value + } + var inval int64 + utxos, err := w.rpcClient.ListUnspent() + if err != nil { + return 0, err + } + for _, input := range tx.TxIn { + for _, utxo := range utxos { + if utxo.TxID == input.PreviousOutPoint.Hash.String() && utxo.Vout == input.PreviousOutPoint.Index { + inval += int64(utxo.Amount * 100000000) + break + } + } + } + if inval < outval { + return 0, errors.New("Error building transaction: inputs less than outputs") + } + return uint64(inval - outval), err +} + +func (w *BitcoindWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wallet.Signature, error) { + var sigs []wallet.Signature + tx := wire.NewMsgTx(1) + for _, in := range ins { + ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) + if err != nil { + return sigs, err + } + outpoint := wire.NewOutPoint(ch, in.OutpointIndex) + input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) + tx.TxIn = append(tx.TxIn, input) + } + for _, out := range outs { + scriptPubKey, err := txscript.PayToAddrScript(out.Address) + if err != nil { + return nil, err + } + output := wire.NewTxOut(out.Value, scriptPubKey) + tx.TxOut = append(tx.TxOut, output) + } + + // Subtract fee + txType := spvwallet.P2SH_2of3_Multisig + _, err := spvwallet.LockTimeFromRedeemScript(redeemScript) + if err == nil { + txType = spvwallet.P2SH_Multisig_Timelock_2Sigs + } + estimatedSize := spvwallet.EstimateSerializeSize(len(ins), tx.TxOut, false, txType) + fee := estimatedSize * int(feePerByte) + if len(tx.TxOut) > 0 { + feePerOutput := fee / len(tx.TxOut) + for _, output := range tx.TxOut { + output.Value -= int64(feePerOutput) + } + } + + // BIP 69 sorting + txsort.InPlaceSort(tx) + + signingKey, err := key.ECPrivKey() + if err != nil { + return sigs, err + } + + hashes := txscript.NewTxSigHashes(tx) + for i := range tx.TxIn { + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, redeemScript, txscript.SigHashAll, signingKey) + if err != nil { + continue + } + bs := wallet.Signature{InputIndex: uint32(i), Signature: sig} + sigs = append(sigs, bs) + } + return sigs, nil +} + +func (w *BitcoindWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, sigs1 []wallet.Signature, sigs2 []wallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { + <-w.initChan + tx := wire.NewMsgTx(1) + for _, in := range ins { + ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) + if err != nil { + return nil, err + } + outpoint := wire.NewOutPoint(ch, in.OutpointIndex) + input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) + tx.TxIn = append(tx.TxIn, input) + } + for _, out := range outs { + scriptPubKey, err := txscript.PayToAddrScript(out.Address) + if err != nil { + return nil, err + } + output := wire.NewTxOut(out.Value, scriptPubKey) + tx.TxOut = append(tx.TxOut, output) + } + + // Subtract fee + txType := spvwallet.P2SH_2of3_Multisig + _, err := spvwallet.LockTimeFromRedeemScript(redeemScript) + if err == nil { + txType = spvwallet.P2SH_Multisig_Timelock_2Sigs + } + estimatedSize := spvwallet.EstimateSerializeSize(len(ins), tx.TxOut, false, txType) + fee := estimatedSize * int(feePerByte) + if len(tx.TxOut) > 0 { + feePerOutput := fee / len(tx.TxOut) + for _, output := range tx.TxOut { + output.Value -= int64(feePerOutput) + } + } + + // BIP 69 sorting + txsort.InPlaceSort(tx) + + // Check if time locked + var timeLocked bool + if redeemScript[0] == txscript.OP_IF { + timeLocked = true + } + + for i, input := range tx.TxIn { + var sig1 []byte + var sig2 []byte + for _, sig := range sigs1 { + if int(sig.InputIndex) == i { + sig1 = sig.Signature + break + } + } + for _, sig := range sigs2 { + if int(sig.InputIndex) == i { + sig2 = sig.Signature + break + } + } + + witness := wire.TxWitness{[]byte{}, sig1, sig2} + + if timeLocked { + witness = append(witness, []byte{0x01}) + } + witness = append(witness, redeemScript) + input.Witness = witness + } + // broadcast + if broadcast { + _, err = w.rpcClient.SendRawTransaction(tx, false) + if err != nil { + return nil, err + } + } + var buf bytes.Buffer + tx.BtcEncode(&buf, wire.ProtocolVersion, wire.WitnessEncoding) + return buf.Bytes(), nil +} + +func (w *BitcoindWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wallet.FeeLevel) (*chainhash.Hash, error) { + <-w.initChan + var internalAddr btc.Address + if address != nil { + internalAddr = *address + } else { + internalAddr = w.CurrentAddress(wallet.INTERNAL) + } + script, err := txscript.PayToAddrScript(internalAddr) + if err != nil { + return nil, err + } + + var val int64 + var inputs []*wire.TxIn + additionalPrevScripts := make(map[wire.OutPoint][]byte) + for _, in := range ins { + val += in.Value + ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) + if err != nil { + return nil, err + } + script, err := txscript.PayToAddrScript(in.LinkedAddress) + if err != nil { + return nil, err + } + outpoint := wire.NewOutPoint(ch, in.OutpointIndex) + input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) + inputs = append(inputs, input) + additionalPrevScripts[*outpoint] = script + } + out := wire.NewTxOut(val, script) + + txType := spvwallet.P2PKH + if redeemScript != nil { + txType = spvwallet.P2SH_1of2_Multisig + _, err := spvwallet.LockTimeFromRedeemScript(*redeemScript) + if err == nil { + txType = spvwallet.P2SH_Multisig_Timelock_1Sig + } + } + estimatedSize := spvwallet.EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) + + // Calculate the fee + feePerByte := int(w.GetFeePerByte(feeLevel)) + fee := estimatedSize * feePerByte + + outVal := val - int64(fee) + if outVal < 0 { + outVal = 0 + } + out.Value = outVal + + tx := &wire.MsgTx{ + Version: wire.TxVersion, + TxIn: inputs, + TxOut: []*wire.TxOut{out}, + LockTime: 0, + } + + // BIP 69 sorting + txsort.InPlaceSort(tx) + + // Sign tx + privKey, err := key.ECPrivKey() + if err != nil { + return nil, err + } + pk := privKey.PubKey().SerializeCompressed() + addressPub, err := btc.NewAddressPubKey(pk, w.params) + + getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { + if addressPub.EncodeAddress() == addr.EncodeAddress() { + wif, err := btc.NewWIF(privKey, w.params, true) + if err != nil { + return nil, false, err + } + return wif.PrivKey, wif.CompressPubKey, nil + } + return nil, false, errors.New("Not found") + }) + getScript := txscript.ScriptClosure(func(addr btc.Address) ([]byte, error) { + if redeemScript == nil { + return []byte{}, nil + } + return *redeemScript, nil + }) + + // Check if time locked + var timeLocked bool + if redeemScript != nil { + rs := *redeemScript + if rs[0] == txscript.OP_IF { + timeLocked = true + tx.Version = 2 + } + for _, txIn := range tx.TxIn { + locktime, err := spvwallet.LockTimeFromRedeemScript(*redeemScript) + if err != nil { + return nil, err + } + txIn.Sequence = locktime + } + } + + hashes := txscript.NewTxSigHashes(tx) + for i, txIn := range tx.TxIn { + if redeemScript == nil { + prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] + script, err := txscript.SignTxOutput(w.params, + tx, i, prevOutScript, txscript.SigHashAll, getKey, + getScript, txIn.SignatureScript) + if err != nil { + return nil, errors.New("Failed to sign transaction") + } + txIn.SignatureScript = script + } else { + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, *redeemScript, txscript.SigHashAll, privKey) + if err != nil { + return nil, err + } + var witness wire.TxWitness + if timeLocked { + witness = wire.TxWitness{sig, []byte{}} + } else { + witness = wire.TxWitness{[]byte{}, sig} + } + witness = append(witness, *redeemScript) + txIn.Witness = witness + } + } + + // broadcast + _, err = w.rpcClient.SendRawTransaction(tx, false) + if err != nil { + return nil, err + } + txid := tx.TxHash() + return &txid, nil +} + +func (w *BitcoindWallet) Params() *chaincfg.Params { + return w.params +} + +func (w *BitcoindWallet) AddTransactionListener(callback func(wallet.TransactionCallback)) { + w.listeners = append(w.listeners, callback) +} + +func (w *BitcoindWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) { + if uint32(timeout.Hours()) > 0 && timeoutKey == nil { + return nil, nil, errors.New("Timeout key must be non nil when using an escrow timeout") + } + + if len(keys) < threshold { + return nil, nil, fmt.Errorf("unable to generate multisig script with "+ + "%d required signatures when there are only %d public "+ + "keys available", threshold, len(keys)) + } + + var ecKeys []*btcec.PublicKey + for _, key := range keys { + ecKey, err := key.ECPubKey() + if err != nil { + return nil, nil, err + } + ecKeys = append(ecKeys, ecKey) + } + + builder := txscript.NewScriptBuilder() + if uint32(timeout.Hours()) == 0 { + + builder.AddInt64(int64(threshold)) + for _, key := range ecKeys { + builder.AddData(key.SerializeCompressed()) + } + builder.AddInt64(int64(len(ecKeys))) + builder.AddOp(txscript.OP_CHECKMULTISIG) + + } else { + ecKey, err := timeoutKey.ECPubKey() + if err != nil { + return nil, nil, err + } + sequenceLock := blockchain.LockTimeToSequence(false, uint32(timeout.Hours()*6)) + builder.AddOp(txscript.OP_IF) + builder.AddInt64(int64(threshold)) + for _, key := range ecKeys { + builder.AddData(key.SerializeCompressed()) + } + builder.AddInt64(int64(len(ecKeys))) + builder.AddOp(txscript.OP_CHECKMULTISIG) + builder.AddOp(txscript.OP_ELSE). + AddInt64(int64(sequenceLock)). + AddOp(txscript.OP_CHECKSEQUENCEVERIFY). + AddOp(txscript.OP_DROP). + AddData(ecKey.SerializeCompressed()). + AddOp(txscript.OP_CHECKSIG). + AddOp(txscript.OP_ENDIF) + } + redeemScript, err = builder.Script() + if err != nil { + return nil, nil, err + } + + witnessProgram := sha256.Sum256(redeemScript) + + addr, err = btc.NewAddressWitnessScriptHash(witnessProgram[:], w.params) + if err != nil { + return nil, nil, err + } + return addr, redeemScript, nil +} + +func (w *BitcoindWallet) addWatchedScript(addr btc.Address) error { + return w.rpcClient.ImportAddressRescan(addr.EncodeAddress(), false) +} + +func (w *BitcoindWallet) ReSyncBlockchain(fromDate time.Time) { + <-w.initChan + w.rpcClient.RawRequest("stop", []json.RawMessage{}) + w.rpcClient.Shutdown() + time.Sleep(5 * time.Second) + args := w.BuildArguments(true) + cmd := exec.Command(w.binary, args...) + cmd.Start() + + client, err := btcrpcclient.New(connCfg, nil) + if err != nil { + log.Error("Could not connect to bitcoind during rescan") + } + w.rpcClient = client +} + +func (w *BitcoindWallet) Close() { + if w.rpcClient != nil { + w.rpcClient.RawRequest("stop", []json.RawMessage{}) + w.rpcClient.Shutdown() + } +} + +func (w *BitcoindWallet) ExchangeRates() wallet.ExchangeRates { + return w.exchangeRates +} + +func DefaultSocksPort(controlPort int) int { + socksPort := 9050 + if controlPort == 9151 || controlPort == 9051 { + controlPort-- + socksPort = controlPort + } + return socksPort +} + +// AssociateTransactionWithOrder used for ORDER_PAYMENT message +func (w *BitcoindWallet) AssociateTransactionWithOrder(txnCB wallet.TransactionCallback) { + for _, l := range w.listeners { + go l(txnCB) + } +} diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/wallet.go b/vendor/github.com/OpenBazaar/go-ethwallet/wallet/wallet.go deleted file mode 100644 index aee34e745f..0000000000 --- a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/wallet.go +++ /dev/null @@ -1,1030 +0,0 @@ -package wallet - -import ( - "bytes" - "context" - "crypto/ecdsa" - "encoding/binary" - "encoding/gob" - "errors" - "fmt" - "io/ioutil" - "math/big" - "path" - "runtime" - "time" - - "github.com/OpenBazaar/multiwallet/config" - wi "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcutil" - hd "github.com/btcsuite/btcutil/hdkeychain" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/sha3" - log "github.com/sirupsen/logrus" - "golang.org/x/net/proxy" - "gopkg.in/yaml.v2" - - "github.com/OpenBazaar/go-ethwallet/util" -) - -const ( - // InfuraAPIKey is the hard coded Infura API key - InfuraAPIKey = "openbazaar" -) - -// EthConfiguration - used for eth specific configuration -type EthConfiguration struct { - RopstenPPAddress string `yaml:"ROPSTEN_PPv2_ADDRESS"` - RegistryAddress string `yaml:"ROPSTEN_REGISTRY"` -} - -// EthRedeemScript - used to represent redeem script for eth wallet -// -// -type EthRedeemScript struct { - TxnID common.Address - Threshold uint8 - Timeout uint32 - Buyer common.Address - Seller common.Address - Moderator common.Address - MultisigAddress common.Address - TokenAddress common.Address -} - -// SerializeEthScript - used to serialize eth redeem script -func SerializeEthScript(scrpt EthRedeemScript) ([]byte, error) { - b := bytes.Buffer{} - e := gob.NewEncoder(&b) - err := e.Encode(scrpt) - return b.Bytes(), err -} - -// DeserializeEthScript - used to deserialize eth redeem script -func DeserializeEthScript(b []byte) (EthRedeemScript, error) { - scrpt := EthRedeemScript{} - buf := bytes.NewBuffer(b) - d := gob.NewDecoder(buf) - err := d.Decode(&scrpt) - return scrpt, err -} - -// PendingTxn used to record a pending eth txn -type PendingTxn struct { - TxnID common.Hash - OrderID string - Amount int64 - Nonce int32 -} - -// SerializePendingTxn - used to serialize eth pending txn -func SerializePendingTxn(pTxn PendingTxn) ([]byte, error) { - b := bytes.Buffer{} - e := gob.NewEncoder(&b) - err := e.Encode(pTxn) - return b.Bytes(), err -} - -// DeserializePendingTxn - used to deserialize eth pending txn -func DeserializePendingTxn(b []byte) (PendingTxn, error) { - pTxn := PendingTxn{} - buf := bytes.NewBuffer(b) - d := gob.NewDecoder(buf) - err := d.Decode(&pTxn) - return pTxn, err -} - -// GenScriptHash - used to generate script hash for eth as per -// escrow smart contract -func GenScriptHash(script EthRedeemScript) ([32]byte, string, error) { - ahash := sha3.NewKeccak256() - a := make([]byte, 4) - binary.BigEndian.PutUint32(a, script.Timeout) - arr := append(script.TxnID.Bytes(), append([]byte{script.Threshold}, - append(a[:], append(script.Buyer.Bytes(), - append(script.Seller.Bytes(), append(script.Moderator.Bytes(), - append(script.MultisigAddress.Bytes())...)...)...)...)...)...) - ahash.Write(arr) - var retHash [32]byte - - copy(retHash[:], ahash.Sum(nil)[:]) - ahashStr := hexutil.Encode(retHash[:]) - - return retHash, ahashStr, nil -} - -// EthereumWallet is the wallet implementation for ethereum -type EthereumWallet struct { - client *EthClient - account *Account - address *EthAddress - service *Service - registry *Registry - ppsct *Escrow - db wi.Datastore - exchangeRates wi.ExchangeRates - listeners []func(wi.TransactionCallback) -} - -// NewEthereumWalletWithKeyfile will return a reference to the Eth Wallet -func NewEthereumWalletWithKeyfile(url, keyFile, passwd string) *EthereumWallet { - client, err := NewEthClient(url) - if err != nil { - log.Fatalf("error initializing wallet: %v", err) - } - var myAccount *Account - myAccount, err = NewAccountFromKeyfile(keyFile, passwd) - if err != nil { - log.Fatalf("key file validation failed: %s", err.Error()) - } - addr := myAccount.Address() - - _, filename, _, _ := runtime.Caller(0) - conf, err := ioutil.ReadFile(path.Join(path.Dir(filename), "../configuration.yaml")) - - if err != nil { - log.Fatalf("ethereum config not found: %s", err.Error()) - } - ethConfig := EthConfiguration{} - err = yaml.Unmarshal(conf, ðConfig) - if err != nil { - log.Fatalf("ethereum config not valid: %s", err.Error()) - } - - reg, err := NewRegistry(common.HexToAddress(ethConfig.RegistryAddress), client) - if err != nil { - log.Fatalf("error initilaizing contract failed: %s", err.Error()) - } - - //reg.GetVersionDetails() - - //smtct, err := NewWallet(common.HexToAddress(ethConfig.RopstenPPAddress), client) - //if err != nil { - // log.Fatalf("error initilaizing contract failed: %s", err.Error()) - //} - - return &EthereumWallet{client, myAccount, &EthAddress{&addr}, &Service{}, reg, nil, nil, nil, []func(wi.TransactionCallback){}} -} - -// NewEthereumWallet will return a reference to the Eth Wallet -func NewEthereumWallet(cfg config.CoinConfig, mnemonic string, proxy proxy.Dialer) (*EthereumWallet, error) { - client, err := NewEthClient(cfg.ClientAPIs[0] + "/" + InfuraAPIKey) - if err != nil { - log.Errorf("error initializing wallet: %v", err) - return nil, err - } - var myAccount *Account - /* - seed := bip39.NewSeed(mnemonic, "") - - privateKeyECDSA, err := crypto.ToECDSA(seed) - if err != nil { - return nil - } - - key := &keystore.Key{ - Address: crypto.PubkeyToAddress(privateKeyECDSA.PublicKey), - PrivateKey: privateKeyECDSA, - } - - myAccount = &Account{key} - */ - myAccount, err = NewAccountFromMnemonic(mnemonic, "") - if err != nil { - log.Errorf("mnemonic based pk generation failed: %s", err.Error()) - return nil, err - } - addr := myAccount.Address() - - ethConfig := EthConfiguration{} - - var regAddr interface{} - var ok bool - if regAddr, ok = cfg.Options["RegistryAddress"]; !ok { - log.Errorf("ethereum registry not found: %s", err.Error()) - return nil, err - } - - ethConfig.RegistryAddress = regAddr.(string) - - /* - _, filename, _, _ := runtime.Caller(0) - conf, err := ioutil.ReadFile(path.Join(path.Dir(filename), "../configuration.yaml")) - - if err != nil { - log.Errorf("ethereum config not found: %s", err.Error()) - return nil, err - } - - err = yaml.Unmarshal(conf, ðConfig) - if err != nil { - log.Errorf("ethereum config not valid: %s", err.Error()) - return nil, err - } - */ - - reg, err := NewRegistry(common.HexToAddress(ethConfig.RegistryAddress), client) - if err != nil { - log.Errorf("error initilaizing contract failed: %s", err.Error()) - return nil, err - } - - //reg.GetVersionDetails() - - //smtct, err := NewWallet(common.HexToAddress(ethConfig.RopstenPPAddress), client) - //if err != nil { - // log.Fatalf("error initilaizing contract failed: %s", err.Error()) - //} - - er := NewEthereumPriceFetcher(proxy) - - return &EthereumWallet{client, myAccount, &EthAddress{&addr}, &Service{}, reg, nil, cfg.DB, er, []func(wi.TransactionCallback){}}, nil -} - -// Params - return nil to comply -func (wallet *EthereumWallet) Params() *chaincfg.Params { - return nil -} - -// GetBalance returns the balance for the wallet -func (wallet *EthereumWallet) GetBalance() (*big.Int, error) { - return wallet.client.GetBalance(wallet.account.Address()) -} - -// GetUnconfirmedBalance returns the unconfirmed balance for the wallet -func (wallet *EthereumWallet) GetUnconfirmedBalance() (*big.Int, error) { - return wallet.client.GetUnconfirmedBalance(wallet.account.Address()) -} - -// Transfer will transfer the amount from this wallet to the spec address -func (wallet *EthereumWallet) Transfer(to string, value *big.Int) (common.Hash, error) { - toAddress := common.HexToAddress(to) - return wallet.client.Transfer(wallet.account, toAddress, value) -} - -// Start will start the wallet daemon -func (wallet *EthereumWallet) Start() { - // start the ticker to check for pending txn rcpts - ticker := time.NewTicker(5 * time.Second) - go func() { - for range ticker.C { - // get the pending txns - txns, err := wallet.db.Txns().GetAll(true) - if err != nil { - continue - } - for _, txn := range txns { - hash := common.HexToHash(txn.Txid) - go wallet.CheckTxnRcpt(&hash, txn.Bytes) - } - } - }() -} - -// CurrencyCode returns ETH -func (wallet *EthereumWallet) CurrencyCode() string { - return "ETH" -} - -// IsDust Check if this amount is considered dust - 10000 wei -func (wallet *EthereumWallet) IsDust(amount int64) bool { - return amount < 10000 -} - -// MasterPrivateKey - Get the master private key -func (wallet *EthereumWallet) MasterPrivateKey() *hd.ExtendedKey { - return hd.NewExtendedKey([]byte{0x00, 0x00, 0x00, 0x00}, wallet.account.privateKey.D.Bytes(), - wallet.account.address.Bytes(), wallet.account.address.Bytes(), 0, 0, true) -} - -// MasterPublicKey - Get the master public key -func (wallet *EthereumWallet) MasterPublicKey() *hd.ExtendedKey { - publicKey := wallet.account.privateKey.Public() - publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) - if !ok { - log.Fatal("error casting public key to ECDSA") - } - - publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA) - return hd.NewExtendedKey([]byte{0x00, 0x00, 0x00, 0x00}, publicKeyBytes, - wallet.account.address.Bytes(), wallet.account.address.Bytes(), 0, 0, false) -} - -// ChildKey Generate a child key using the given chaincode. The key is used in multisig transactions. -// For most implementations this should just be child key 0. -func (wallet *EthereumWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) { - if isPrivateKey { - return wallet.MasterPrivateKey(), nil - } - return wallet.MasterPublicKey(), nil -} - -// CurrentAddress - Get the current address for the given purpose -func (wallet *EthereumWallet) CurrentAddress(purpose wi.KeyPurpose) btcutil.Address { - return *wallet.address -} - -// NewAddress - Returns a fresh address that has never been returned by this function -func (wallet *EthereumWallet) NewAddress(purpose wi.KeyPurpose) btcutil.Address { - return *wallet.address -} - -// DecodeAddress - Parse the address string and return an address interface -func (wallet *EthereumWallet) DecodeAddress(addr string) (btcutil.Address, error) { - ethAddr := common.HexToAddress(addr) - if wallet.HasKey(EthAddress{ðAddr}) { - return *wallet.address, nil - } - return EthAddress{}, errors.New("invalid or unknown address") -} - -// ScriptToAddress - ? -func (wallet *EthereumWallet) ScriptToAddress(script []byte) (btcutil.Address, error) { - return wallet.address, nil -} - -// HasKey - Returns if the wallet has the key for the given address -func (wallet *EthereumWallet) HasKey(addr btcutil.Address) bool { - if !util.IsValidAddress(addr.String()) { - return false - } - return wallet.account.Address().String() == addr.String() -} - -// Balance - Get the confirmed and unconfirmed balances -func (wallet *EthereumWallet) Balance() (confirmed, unconfirmed int64) { - var balance, ucbalance int64 - bal, err := wallet.GetBalance() - if err == nil { - balance = bal.Int64() - } - ucbal, err := wallet.GetUnconfirmedBalance() - if err == nil { - ucbalance = ucbal.Int64() - } - return balance, ucbalance -} - -// Transactions - Returns a list of transactions for this wallet -func (wallet *EthereumWallet) Transactions() ([]wi.Txn, error) { - return txns, nil -} - -// GetTransaction - Get info on a specific transaction -func (wallet *EthereumWallet) GetTransaction(txid chainhash.Hash) (wi.Txn, error) { - tx, _, err := wallet.client.GetTransaction(common.HexToHash(txid.String())) - if err != nil { - return wi.Txn{}, err - } - return wi.Txn{ - Txid: tx.Hash().String(), - Value: tx.Value().Int64(), - Height: 0, - Timestamp: time.Now(), - WatchOnly: false, - Bytes: tx.Data(), - }, nil -} - -// ChainTip - Get the height and best hash of the blockchain -func (wallet *EthereumWallet) ChainTip() (uint32, chainhash.Hash) { - num, hash, err := wallet.client.GetLatestBlock() - h, _ := chainhash.NewHashFromStr("") - if err != nil { - return 0, *h - } - h, _ = chainhash.NewHashFromStr(hash[2:]) - return num, *h -} - -// GetFeePerByte - Get the current fee per byte -func (wallet *EthereumWallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { - return 0 -} - -// Spend - Send ether to an external wallet -func (wallet *EthereumWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { - - var hash common.Hash - var h *chainhash.Hash - var err error - - if referenceID == "" { - // no referenceID means this is a direct transfer - hash, err = wallet.Transfer(addr.String(), big.NewInt(amount)) - } else { - // this is a spend which means it has to be linked to an order - // specified using the refernceID - - //twoMinutes, _ := time.ParseDuration("2m") - - // check if the addr is a multisig addr - scripts, err := wallet.db.WatchedScripts().GetAll() - if err != nil { - return nil, err - } - isScript := false - key := []byte(addr.String()) - redeemScript := []byte{} - - for _, script := range scripts { - if bytes.Equal(key, script[:common.AddressLength]) { - isScript = true - redeemScript = script[common.AddressLength:] - break - } - } - - if isScript { - ethScript, err := DeserializeEthScript(redeemScript) - if err != nil { - return nil, err - } - hash, err = wallet.callAddTransaction(ethScript, big.NewInt(amount)) - } else { - hash, err = wallet.Transfer(addr.String(), big.NewInt(amount)) - } - - if err != nil { - return nil, err - } - start := time.Now() - flag := false - var rcpt *types.Receipt - for !flag { - rcpt, err = wallet.client.TransactionReceipt(context.Background(), hash) - if rcpt != nil { - flag = true - } - if time.Since(start).Seconds() > 120 { - flag = true - } - } - if rcpt != nil { - // good. so the txn has been processed but we have to account for failed - // but valid txn like some contract condition causing revert - if rcpt.Status > 0 { - // all good to update order state - go wallet.callListeners(wallet.createTxnCallback(hash.Hex(), referenceID, amount, time.Now())) - } else { - // there was some error processing this txn - nonce, err := wallet.client.GetTxnNonce(hash.Hex()) - if err == nil { - data, err := SerializePendingTxn(PendingTxn{ - TxnID: hash, - Amount: amount, - OrderID: referenceID, - Nonce: nonce, - }) - if err == nil { - wallet.db.Txns().Put(data, hash.Hex(), 0, 0, time.Now(), true) - } - } - - return nil, errors.New("transaction pending") - } - } - } - - if err == nil { - h, err = chainhash.NewHashFromStr(hash.Hex()[2:]) - } - return h, err -} - -func (wallet *EthereumWallet) createTxnCallback(txID, orderID string, value int64, bTime time.Time) wi.TransactionCallback { - output := wi.TransactionOutput{ - Address: wallet.address, - Value: value, - Index: 1, - OrderID: orderID, - } - - return wi.TransactionCallback{ - Txid: txID, - Outputs: []wi.TransactionOutput{output}, - Inputs: []wi.TransactionInput{}, - Height: 1, - Timestamp: time.Now(), - Value: value, - WatchOnly: false, - BlockTime: bTime, - } -} - -func (wallet *EthereumWallet) callListeners(txnCB wi.TransactionCallback) { - for _, l := range wallet.listeners { - go l(txnCB) - } -} - -// CheckTxnRcpt check the txn rcpt status -func (wallet *EthereumWallet) CheckTxnRcpt(hash *common.Hash, data []byte) (*common.Hash, error) { - - var rcpt *types.Receipt - pTxn, err := DeserializePendingTxn(data) - if err != nil { - return nil, err - } - - rcpt, err = wallet.client.TransactionReceipt(context.Background(), *hash) - - if rcpt != nil { - // good. so the txn has been processed but we have to account for failed - // but valid txn like some contract condition causing revert - if rcpt.Status > 0 { - // all good to update order state - chash, err := chainhash.NewHashFromStr((*hash).Hex()[2:]) - if err != nil { - return nil, err - } - wallet.db.Txns().Delete(chash) - go wallet.callListeners(wallet.createTxnCallback(hash.Hex(), pTxn.OrderID, pTxn.Amount, time.Now())) - } - } - - return hash, nil - -} - -// BumpFee - Bump the fee for the given transaction -func (wallet *EthereumWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { - return chainhash.NewHashFromStr(txid.String()) -} - -// EstimateFee - Calculates the estimated size of the transaction and returns the total fee for the given feePerByte -func (wallet *EthereumWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte uint64) uint64 { - sum := big.NewInt(0) - for _, out := range outs { - gas, err := wallet.client.EstimateTxnGas(wallet.account.Address(), - common.HexToAddress(out.Address.String()), big.NewInt(out.Value)) - if err != nil { - return sum.Uint64() - } - sum.Add(sum, gas) - } - return sum.Uint64() -} - -// EstimateSpendFee - Build a spend transaction for the amount and return the transaction fee -func (wallet *EthereumWallet) EstimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { - gas, err := wallet.client.EstimateGasSpend(wallet.account.Address(), big.NewInt(amount)) - return gas.Uint64(), err -} - -// SweepAddress - Build and broadcast a transaction that sweeps all coins from an address. If it is a p2sh multisig, the redeemScript must be included -func (wallet *EthereumWallet) SweepAddress(utxos []wi.TransactionInput, address *btcutil.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { - return chainhash.NewHashFromStr("") -} - -// ExchangeRates - return the exchangerates -func (wallet *EthereumWallet) ExchangeRates() wi.ExchangeRates { - return wallet.exchangeRates -} - -func (wallet *EthereumWallet) callAddTransaction(script EthRedeemScript, value *big.Int) (common.Hash, error) { - - h := common.BigToHash(big.NewInt(0)) - - // call registry to get the deployed address for the escrow ct - fromAddress := wallet.account.Address() - nonce, err := wallet.client.PendingNonceAt(context.Background(), fromAddress) - if err != nil { - log.Fatal(err) - } - gasPrice, err := wallet.client.SuggestGasPrice(context.Background()) - if err != nil { - log.Fatal(err) - } - auth := bind.NewKeyedTransactor(wallet.account.privateKey) - - auth.Nonce = big.NewInt(int64(nonce)) - auth.Value = value // in wei - auth.GasLimit = 4000000 // in units - auth.GasPrice = gasPrice - - //redeemScript, err := SerializeEthScript(script) - //if err != nil { - // return h, err - //} - - shash, _, err := GenScriptHash(script) - if err != nil { - return h, err - } - - smtct, err := NewEscrow(script.MultisigAddress, wallet.client) - if err != nil { - log.Fatalf("error initilaizing contract failed: %s", err.Error()) - } - - ///smtct.CalculateRedeemScriptHash() - - var tx *types.Transaction - - //if script.Threshold == 1 { - tx, err = smtct.AddTransaction(auth, script.Buyer, script.Seller, - script.Moderator, script.Threshold, - script.Timeout, shash, script.TxnID) - //} else { - // tx, err = smtct.AddTransaction(auth, script.Buyer, script.Seller, - // script.Moderator, script.Threshold, - // script.Timeout, shash, script.TxnID) - //} - - if err == nil { - h = tx.Hash() - } - - return h, err - -} - -// GenerateMultisigScript - Generate a multisig script from public keys. If a timeout is included the returned script should be a timelocked escrow which releases using the timeoutKey. -func (wallet *EthereumWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (btcutil.Address, []byte, error) { - if uint32(timeout.Hours()) > 0 && timeoutKey == nil { - return nil, nil, errors.New("timeout key must be non nil when using an escrow timeout") - } - - if len(keys) < threshold { - return nil, nil, fmt.Errorf("unable to generate multisig script with "+ - "%d required signatures when there are only %d public "+ - "keys available", threshold, len(keys)) - } - - if len(keys) < 2 { - return nil, nil, fmt.Errorf("unable to generate multisig script with "+ - "%d required signatures when there are only %d public "+ - "keys available", threshold, len(keys)) - } - - var ecKeys []common.Address - for _, key := range keys { - ecKey, err := key.ECPubKey() - if err != nil { - return nil, nil, err - } - ecKeys = append(ecKeys, common.BytesToAddress(ecKey.SerializeUncompressed())) - } - - ver, err := wallet.registry.GetRecommendedVersion(nil, "escrow") - if err != nil { - log.Fatal(err) - } - - if util.IsZeroAddress(ver.Implementation) { - return nil, nil, errors.New("no escrow contract available") - } - - builder := EthRedeemScript{} - - builder.TxnID = common.BytesToAddress(util.ExtractChaincode(&keys[0])) - builder.Timeout = uint32(timeout.Hours()) - builder.Threshold = uint8(threshold) - builder.Buyer = ecKeys[0] - builder.Seller = ecKeys[1] - builder.MultisigAddress = ver.Implementation - - if threshold > 1 { - builder.Moderator = ecKeys[2] - } - switch threshold { - case 1: - { - // Seller is offline - } - case 2: - { - // Moderated payment - } - default: - { - // handle this - } - } - - redeemScript, err := SerializeEthScript(builder) - if err != nil { - return nil, nil, err - } - - hash := sha3.NewKeccak256() - hash.Write(redeemScript) - addr := common.HexToAddress(hexutil.Encode(hash.Sum(nil)[:])) - retAddr := EthAddress{&addr} - - scriptKey := append(addr.Bytes(), redeemScript...) - wallet.db.WatchedScripts().Put(scriptKey) - - return retAddr, redeemScript, nil -} - -// CreateMultisigSignature - Create a signature for a multisig transaction -func (wallet *EthereumWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { - - var sigs []wi.Signature - - payables := make(map[string]*big.Int) - for _, out := range outs { - if out.Value <= 0 { - continue - } - val := big.NewInt(out.Value) - if p, ok := payables[out.Address.String()]; ok { - sum := big.NewInt(0) - sum.Add(val, p) - payables[out.Address.String()] = sum - } else { - payables[out.Address.String()] = val - } - } - - //destinations := []common.Address{} - //amounts := []*big.Int{} - - destArr := []byte{} - //destStr := "" - amountArr := []byte{} - //amountStr := "" - - //spew.Dump(payables) - - for k, v := range payables { - addr := common.HexToAddress(k) - sample := [32]byte{} - sampleDest := [32]byte{} - copy(sampleDest[12:], addr.Bytes()) - a := make([]byte, 8) - binary.BigEndian.PutUint64(a, v.Uint64()) - - copy(sample[24:], a) - //destinations = append(destinations, addr) - //amounts = append(amounts, v) - //addrStr := fmt.Sprintf("%064s", addr.String()) - //destStr = destStr + addrStr - destArr = append(destArr, sampleDest[:]...) - amountArr = append(amountArr, sample[:]...) - //amnt := fmt.Sprintf("%064s", fmt.Sprintf("%x", v.Int64())) - //amountStr = amountStr + amnt - } - - //fmt.Println("destarr : ", destArr) - //fmt.Println("amountArr : ", amountArr) - - rScript, err := DeserializeEthScript(redeemScript) - if err != nil { - return nil, err - } - - //spew.Dump(rScript) - - shash, _, err := GenScriptHash(rScript) - if err != nil { - return nil, err - } - - var txHash [32]byte - var payloadHash [32]byte - - /* - // Follows ERC191 signature scheme: https://github.com/ethereum/EIPs/issues/191 - bytes32 txHash = keccak256( - abi.encodePacked( - "\x19Ethereum Signed Message:\n32", - keccak256( - abi.encodePacked( - byte(0x19), - byte(0), - this, - destinations, - amounts, - scriptHash - ) - ) - ) - ); - - */ - - payload := []byte{byte(0x19), byte(0)} - payload = append(payload, rScript.MultisigAddress.Bytes()...) - payload = append(payload, destArr...) - payload = append(payload, amountArr...) - payload = append(payload, shash[:]...) - - //script.MultisigAddress.String()[2:] - - //payloadStr := "0x19" + "00" + rScript.MultisigAddress.String()[2:] + destStr + amountStr + - // hashStr[2:] - //payloadStr = payloadStr + "" - - //pHash := crypto.Keccak256([]byte(payloadStr)) - pHash := crypto.Keccak256(payload) - copy(payloadHash[:], pHash) - - txData := []byte{byte(0x19)} - txData = append(txData, []byte("Ethereum Signed Message:\n32")...) - //txData = append(txData, byte(32)) - txData = append(txData, payloadHash[:]...) - txnHash := crypto.Keccak256(txData) - //fmt.Println("txnHash : ", hexutil.Encode(txnHash)) - //fmt.Println("phash : ", hexutil.Encode(payloadHash[:])) - copy(txHash[:], txnHash) - - sig, err := crypto.Sign(txHash[:], wallet.account.privateKey) - if err != nil { - log.Errorf("error signing in createmultisig : %v", err) - } - sigs = append(sigs, wi.Signature{InputIndex: 1, Signature: sig}) - - return sigs, err -} - -// Multisign - Combine signatures and optionally broadcast -func (wallet *EthereumWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - - //var buf bytes.Buffer - - payables := make(map[string]*big.Int) - for _, out := range outs { - if out.Value <= 0 { - continue - } - val := big.NewInt(out.Value) - if p, ok := payables[out.Address.String()]; ok { - sum := big.NewInt(0) - sum.Add(val, p) - payables[out.Address.String()] = sum - } else { - payables[out.Address.String()] = val - } - } - - rSlice := [][32]byte{} //, 2) - sSlice := [][32]byte{} //, 2) - vSlice := []uint8{} //, 2) - - r := [32]byte{} - s := [32]byte{} - v := uint8(0) - - if len(sigs1[0].Signature) > 0 { - r, s, v = util.SigRSV(sigs1[0].Signature) - rSlice = append(rSlice, r) - sSlice = append(sSlice, s) - vSlice = append(vSlice, v) - } - - r = [32]byte{} - s = [32]byte{} - v = uint8(0) - - if len(sigs2[0].Signature) > 0 { - r, s, v = util.SigRSV(sigs2[0].Signature) - rSlice = append(rSlice, r) - sSlice = append(sSlice, s) - vSlice = append(vSlice, v) - } - - rScript, err := DeserializeEthScript(redeemScript) - if err != nil { - return nil, err - } - - shash, _, err := GenScriptHash(rScript) - if err != nil { - return nil, err - } - - smtct, err := NewEscrow(rScript.MultisigAddress, wallet.client) - if err != nil { - log.Fatalf("error initilaizing contract failed: %s", err.Error()) - } - - destinations := []common.Address{} - amounts := []*big.Int{} - - for k, v := range payables { - destinations = append(destinations, common.HexToAddress(k)) - amounts = append(amounts, v) - } - - fromAddress := wallet.account.Address() - nonce, err := wallet.client.PendingNonceAt(context.Background(), fromAddress) - if err != nil { - log.Fatal(err) - } - gasPrice, err := wallet.client.SuggestGasPrice(context.Background()) - if err != nil { - log.Fatal(err) - } - auth := bind.NewKeyedTransactor(wallet.account.privateKey) - - auth.Nonce = big.NewInt(int64(nonce)) - auth.Value = big.NewInt(0) // in wei - auth.GasLimit = 4000000 // in units - auth.GasPrice = gasPrice - - var tx *types.Transaction - - tx, err = smtct.Execute(auth, vSlice, rSlice, sSlice, shash, destinations, amounts) - - //fmt.Println(tx) - //fmt.Println(err) - - if err != nil { - return nil, err - } - - ret, err := tx.MarshalJSON() - - return ret, err -} - -// AddWatchedAddress - Add a script to the wallet and get notifications back when coins are received or spent from it -func (wallet *EthereumWallet) AddWatchedAddress(address btcutil.Address) error { - // the reason eth wallet cannot use this as of now is because only the address - // is insufficient, the redeemScript is also required - return nil -} - -// AddTransactionListener - add a txn listener -func (wallet *EthereumWallet) AddTransactionListener(callback func(wi.TransactionCallback)) { - // add incoming txn listener using service - wallet.listeners = append(wallet.listeners, callback) -} - -// ReSyncBlockchain - Use this to re-download merkle blocks in case of missed transactions -func (wallet *EthereumWallet) ReSyncBlockchain(fromTime time.Time) { - // use service here -} - -// GetConfirmations - Return the number of confirmations and the height for a transaction -func (wallet *EthereumWallet) GetConfirmations(txid chainhash.Hash) (confirms, atHeight uint32, err error) { - return 0, 0, nil -} - -// Close will stop the wallet daemon -func (wallet *EthereumWallet) Close() { - // stop the wallet daemon -} - -// CreateAddress - used to generate a new address -func (wallet *EthereumWallet) CreateAddress() (common.Address, error) { - fromAddress := wallet.account.Address() - nonce, err := wallet.client.PendingNonceAt(context.Background(), fromAddress) - if err != nil { - fmt.Println(err) - } - addr := crypto.CreateAddress(fromAddress, nonce) - //fmt.Println("Addr : ", addr.String()) - return addr, err -} - -// GenWallet creates a wallet -func GenWallet() { - privateKey, err := crypto.GenerateKey() - if err != nil { - log.Fatal(err) - } - - privateKeyBytes := crypto.FromECDSA(privateKey) - fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) // fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19 - - publicKey := privateKey.Public() - publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) - if !ok { - log.Fatal("error casting public key to ECDSA") - } - - publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA) - fmt.Println(hexutil.Encode(publicKeyBytes)[4:]) // 9a7df67f79246283fdc93af76d4f8cdd62c4886e8cd870944e817dd0b97934fdd7719d0810951e03418205868a5c1b40b192451367f28e0088dd75e15de40c05 - - address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex() - fmt.Println(address) // 0x96216849c49358B10257cb55b28eA603c874b05E - - hash := sha3.NewKeccak256() - hash.Write(publicKeyBytes[1:]) - fmt.Println(hexutil.Encode(hash.Sum(nil)[12:])) // 0x96216849c49358b10257cb55b28ea603c874b05e - - fmt.Println(util.IsValidAddress(address)) - -} - -// GenDefaultKeyStore will generate a default keystore -func GenDefaultKeyStore(passwd string) (*Account, error) { - ks := keystore.NewKeyStore("./", keystore.StandardScryptN, keystore.StandardScryptP) - - account, err := ks.NewAccount(passwd) - if err != nil { - return nil, err - } - return NewAccountFromKeyfile(account.URL.Path, passwd) -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/.travis.yml b/vendor/github.com/OpenBazaar/spvwallet/.travis.yml index 871cbef07c..66005fe0d4 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/.travis.yml +++ b/vendor/github.com/OpenBazaar/spvwallet/.travis.yml @@ -1,16 +1,19 @@ language: go go: - - 1.9 -sudo: required + - 1.11 services: - docker env: - - "PATH=/home/travis/gopath/bin:$PATH" + - DEP_VERSION=0.5.4 PATH=/home/travis/gopath/bin:${PATH} before_install: + - curl -L -s https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64 -o $GOPATH/bin/dep + - chmod +x $GOPATH/bin/dep - go get github.com/tcnksm/ghr - go get github.com/axw/gocov/gocov - go get github.com/mattn/goveralls +install: + - dep ensure script: - - diff -u <(echo -n) <(gofmt -d -s $(find . -type f -name '*.go' -not -path "./cmd/spvwallet/vendor/*" -not -path "./gui/resources.go" )) + - diff -u <(echo -n) <(gofmt -d -s $(find . -type f -name '*.go' -not -path "./cmd/spvwallet/vendor/*" -not -path "./gui/resources.go" -not -path "./vendor/*")) - cd $TRAVIS_BUILD_DIR && chmod a+x test_compile.sh && ./test_compile.sh - - goveralls -coverprofile=coverage.out -service travis-ci \ No newline at end of file + - goveralls -coverprofile=coverage.out -service travis-ci diff --git a/vendor/github.com/OpenBazaar/spvwallet/Dockerfile.dev b/vendor/github.com/OpenBazaar/spvwallet/Dockerfile.dev new file mode 100755 index 0000000000..d41c68e7a8 --- /dev/null +++ b/vendor/github.com/OpenBazaar/spvwallet/Dockerfile.dev @@ -0,0 +1,10 @@ +FROM golang:1.11 +VOLUME /var/lib/openbazaar + +WORKDIR /go/src/github.com/OpenBazaar/spvwallet +RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh && \ + go get -u github.com/derekparker/delve/cmd/dlv + +COPY . . + +ENTRYPOINT ["/bin/bash"] diff --git a/vendor/github.com/OpenBazaar/spvwallet/Gopkg.lock b/vendor/github.com/OpenBazaar/spvwallet/Gopkg.lock new file mode 100644 index 0000000000..be8e727bc1 --- /dev/null +++ b/vendor/github.com/OpenBazaar/spvwallet/Gopkg.lock @@ -0,0 +1,451 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + digest = "1:0d7a2df3f50b10ccaeac6c37b4970245d6ad3b9f19c8fe8e820cb335006c8100" + name = "github.com/OpenBazaar/jsonpb" + packages = ["."] + pruneopts = "UT" + revision = "37d32ddf4eefaab6c19a01c99f4e00df9b1be48f" + +[[projects]] + branch = "ethereum-master" + digest = "1:c411c1051b3ab7c823786bf82887580f2d93898be2504e145a67419afef5ba2d" + name = "github.com/OpenBazaar/wallet-interface" + packages = ["."] + pruneopts = "UT" + revision = "cbbb40466dcfe7d299f685fd0aa9a4fe9ea49147" + +[[projects]] + digest = "1:35a426de67d2340cece030713f231c923045550993f3d8aff5d772b02e7b0417" + name = "github.com/asticode/go-astikit" + packages = ["."] + pruneopts = "UT" + revision = "3833bbfde29cca140757cb1e9ea1df6b0b6ea323" + version = "v0.3.0" + +[[projects]] + digest = "1:bfe69faae1f375f77c7a9816ac852d09a65f04eff65ae26add69d2e53cc73dca" + name = "github.com/asticode/go-astilectron" + packages = ["."] + pruneopts = "UT" + revision = "f88a6474c180acac6676002c7180c2333541e1ce" + version = "v0.11.0" + +[[projects]] + digest = "1:5d37166a9ee252a5f036cebb8969937f9d57588ebcd6886deb998afb7f33c407" + name = "github.com/asticode/go-astilog" + packages = ["."] + pruneopts = "UT" + revision = "d1add92f6cdd4e94919cc878a7d7696cc6f41231" + version = "v1.5.0" + +[[projects]] + digest = "1:b8e07a21225ed189e4ccaba8cd3b7c9d6da38d3acb1a56a9e3d4cb5d84ebc556" + name = "github.com/asticode/go-astitools" + packages = ["template"] + pruneopts = "UT" + revision = "e5e8eaa60d39789dd2189b360d6f83a5ed94b79d" + version = "v1.3.0" + +[[projects]] + digest = "1:323ef1c999160d12fafa4074b5a5706511baf1cd91a935ae62494791c94abaf4" + name = "github.com/atotto/clipboard" + packages = ["."] + pruneopts = "UT" + revision = "579379fa8ff8a6d3fa979cec107f8f6d7f8fde90" + version = "v0.1.2" + +[[projects]] + digest = "1:0f98f59e9a2f4070d66f0c9c39561f68fcd1dc837b22a852d28d0003aebd1b1e" + name = "github.com/boltdb/bolt" + packages = ["."] + pruneopts = "UT" + revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8" + version = "v1.3.1" + +[[projects]] + digest = "1:38e337477887a8935559e3042ce53f14fcc24fd66635b57f423965c8297ccc90" + name = "github.com/btcsuite/btcd" + packages = [ + "addrmgr", + "blockchain", + "btcec", + "chaincfg", + "chaincfg/chainhash", + "connmgr", + "database", + "peer", + "txscript", + "wire", + ] + pruneopts = "UT" + revision = "f3ec13030e4e828869954472cbc51ac36bee5c1d" + version = "v0.20.1-beta" + +[[projects]] + branch = "master" + digest = "1:30d4a548e09bca4a0c77317c58e7407e2a65c15325e944f9c08a7b7992f8a59e" + name = "github.com/btcsuite/btclog" + packages = ["."] + pruneopts = "UT" + revision = "84c8d2346e9fc8c7b947e243b9c24e6df9fd206a" + +[[projects]] + branch = "master" + digest = "1:4a13c7cdb269ba1ceadf68312e363b442df7cca8ba5c9d5d069a18b9e6caa1d5" + name = "github.com/btcsuite/btcutil" + packages = [ + ".", + "base58", + "bech32", + "bloom", + "coinset", + "hdkeychain", + "txsort", + ] + pruneopts = "UT" + revision = "02a4fd9de1d52e877491996349a92d54c653ccbf" + +[[projects]] + digest = "1:7ffc24d91a12c173c18fe9ada86a05fc476f8943f4acffeddc6ec87a4f32bdef" + name = "github.com/btcsuite/btcwallet" + packages = [ + "wallet/txauthor", + "wallet/txrules", + "wallet/txsizes", + ] + pruneopts = "UT" + revision = "b19df70dddb66b27902f48cc48e69741909ef2e9" + version = "v0.11.0" + +[[projects]] + branch = "master" + digest = "1:1e6b2f7aa98b082c30a1303c29a702c369b2ec6d86b74a599bc8bbe2333db299" + name = "github.com/btcsuite/go-socks" + packages = ["socks"] + pruneopts = "UT" + revision = "4720035b7bfd2a9bb130b1c184f8bbe41b6f0d0f" + +[[projects]] + digest = "1:91fc3f4d1842584d1342364193106e80d1d532bbd1668fbd7c61627f01d0111f" + name = "github.com/btcsuite/goleveldb" + packages = [ + "leveldb/errors", + "leveldb/storage", + "leveldb/util", + ] + pruneopts = "UT" + revision = "3fd0373267b6461dbefe91cef614278064d05465" + version = "v1.0.0" + +[[projects]] + branch = "master" + digest = "1:9d61b5ca59d3db0b1f1c1e9f5930b4f7c7fd954f54b70c1d83802b8805db918f" + name = "github.com/cevaris/ordered_map" + packages = ["."] + pruneopts = "UT" + revision = "3adeae072e730f1919a936e13b4923706d3f60fe" + +[[projects]] + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" + name = "github.com/davecgh/go-spew" + packages = ["spew"] + pruneopts = "UT" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" + +[[projects]] + digest = "1:bde2a1ce1de28312f165a88926c12f4acd19dc4d7da96a445dfa5a29eae07a93" + name = "github.com/fatih/color" + packages = ["."] + pruneopts = "UT" + revision = "daf2830f2741ebb735b21709a520c5f37d642d85" + version = "v1.9.0" + +[[projects]] + digest = "1:228f39dbc93e88d95a024f45d5beea0a64cd33e89bdfb841a1669abb74f8b1e9" + name = "github.com/golang/protobuf" + packages = [ + "proto", + "protoc-gen-go/descriptor", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp", + ] + pruneopts = "UT" + revision = "d23c5127dc24889085f8ccea5c9d560a57a879d8" + version = "v1.3.3" + +[[projects]] + digest = "1:a2cff208d4759f6ba1b1cd228587b0a1869f95f22542ec9cd17fff64430113c7" + name = "github.com/jessevdk/go-flags" + packages = ["."] + pruneopts = "UT" + revision = "c6ca198ec95c841fdb89fc0de7496fed11ab854e" + version = "v1.4.0" + +[[projects]] + digest = "1:84a35669b4b31cc20ffc89c3b2ab32f2189fb2366a973efa1c25e009ef6ae1c6" + name = "github.com/julienschmidt/httprouter" + packages = ["."] + pruneopts = "UT" + revision = "4eec211fa4e8df74ed978dc5681612131854144f" + version = "v1.3.0" + +[[projects]] + digest = "1:4a29eeb25603debe8f2098a9902c4d3851034cf70d33be428826e86e8c30a1b0" + name = "github.com/mattn/go-colorable" + packages = ["."] + pruneopts = "UT" + revision = "98ec13f34aabf44cc914c65a1cfb7b9bc815aef1" + version = "v0.1.4" + +[[projects]] + digest = "1:0c58d31abe2a2ccb429c559b6292e7df89dcda675456fecc282fa90aa08273eb" + name = "github.com/mattn/go-isatty" + packages = ["."] + pruneopts = "UT" + revision = "7b513a986450394f7bbf1476909911b3aa3a55ce" + version = "v0.0.12" + +[[projects]] + digest = "1:e2ac6e4ee843b2001b6c3a7801180ea3f7fa6d61fb917ca7dde15e26ef02a082" + name = "github.com/mattn/go-sqlite3" + packages = ["."] + pruneopts = "UT" + revision = "9bdaffc12bf8be15afceb51bb60851edd4afdff5" + version = "v2.0.3" + +[[projects]] + digest = "1:5d231480e1c64a726869bc4142d270184c419749d34f167646baa21008eb0a79" + name = "github.com/mitchellh/go-homedir" + packages = ["."] + pruneopts = "UT" + revision = "af06845cf3004701891bf4fdb884bfe4920b3727" + version = "v1.1.0" + +[[projects]] + digest = "1:c805e517269b0ba4c21ded5836019ed7d16953d4026cb7d00041d039c7906be9" + name = "github.com/natefinch/lumberjack" + packages = ["."] + pruneopts = "UT" + revision = "a96e63847dc3c67d17befa69c303767e2f84e54f" + version = "v2.1" + +[[projects]] + digest = "1:5b3b29ce0e569f62935d9541dff2e16cc09df981ebde48e82259076a73a3d0c7" + name = "github.com/op/go-logging" + packages = ["."] + pruneopts = "UT" + revision = "b2cb9fa56473e98db8caba80237377e83fe44db5" + version = "v1" + +[[projects]] + digest = "1:9e1d37b58d17113ec3cb5608ac0382313c5b59470b94ed97d0976e69c7022314" + name = "github.com/pkg/errors" + packages = ["."] + pruneopts = "UT" + revision = "614d223910a179a466c1767a985424175c39b465" + version = "v0.9.1" + +[[projects]] + branch = "master" + digest = "1:eb960fd3ea2dab0ee0b216c962c54b439006efec889b079a23d6d0b24547bb7a" + name = "github.com/skratchdot/open-golang" + packages = ["open"] + pruneopts = "UT" + revision = "eef8423979666925a58eb77f9db583e54320d5a4" + +[[projects]] + digest = "1:91b40a2adb6b4ccd51b1dfb306edfa76139e1599b01666346085472b386f5447" + name = "github.com/tyler-smith/go-bip39" + packages = [ + ".", + "wordlists", + ] + pruneopts = "UT" + revision = "5e3853c3f4e1a44df487c7efeb064ee8b43755de" + version = "1.0.2" + +[[projects]] + branch = "master" + digest = "1:6d096c04caafd558fd8aaae07bf349235a0c455c652cd524c2e0a4e95e536cdd" + name = "github.com/yawning/bulb" + packages = [ + ".", + "utils", + "utils/pkcs1", + ] + pruneopts = "UT" + revision = "85d80d893c3d4a478b8c0abbc43f0ea13e1ce4f9" + +[[projects]] + branch = "master" + digest = "1:1cdae1db2401d9ea3c98e44c301b94d3a3021228d141a9a8af601b025ff31a4d" + name = "golang.org/x/crypto" + packages = [ + "pbkdf2", + "ripemd160", + ] + pruneopts = "UT" + revision = "86ce3cb696783b739e41e834e2eead3e1b4aa3fb" + +[[projects]] + branch = "master" + digest = "1:5f4febb068e1910d3790fd682d564a85ea0773f1a45072fd723170c78034f2b5" + name = "golang.org/x/net" + packages = [ + "context", + "http/httpguts", + "http2", + "http2/hpack", + "idna", + "internal/socks", + "internal/timeseries", + "proxy", + "trace", + ] + pruneopts = "UT" + revision = "16171245cfb220d5317888b716d69c1fb4e7992b" + +[[projects]] + branch = "master" + digest = "1:72b7c210f8cfe1431d2f300fbf37f25e52aa77324b05ab6b698483054033803e" + name = "golang.org/x/sys" + packages = ["unix"] + pruneopts = "UT" + revision = "d101bd2416d505c0448a6ce8a282482678040a89" + +[[projects]] + digest = "1:8d8faad6b12a3a4c819a3f9618cb6ee1fa1cfc33253abeeea8b55336721e3405" + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/language", + "internal/language/compact", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + ] + pruneopts = "UT" + revision = "342b2e1fbaa52c93f31447ad2c6abc048c63e475" + version = "v0.3.2" + +[[projects]] + branch = "master" + digest = "1:0c679e19d1865dd65e7ec400bf9562d8f161cf59c4f74c0bb50f365fc9fb19eb" + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + pruneopts = "UT" + revision = "2dc5924e38981f069b4982c6eb2b72365efd00a7" + +[[projects]] + digest = "1:6112fd005e06e37449ca883f2f8e5b4060285e62b6877c16e5565c072d43d422" + name = "google.golang.org/grpc" + packages = [ + ".", + "attributes", + "backoff", + "balancer", + "balancer/base", + "balancer/roundrobin", + "binarylog/grpc_binarylog_v1", + "codes", + "connectivity", + "credentials", + "credentials/internal", + "encoding", + "encoding/proto", + "grpclog", + "internal", + "internal/backoff", + "internal/balancerload", + "internal/binarylog", + "internal/buffer", + "internal/channelz", + "internal/envconfig", + "internal/grpcrand", + "internal/grpcsync", + "internal/resolver/dns", + "internal/resolver/passthrough", + "internal/syscall", + "internal/transport", + "keepalive", + "metadata", + "naming", + "peer", + "reflection", + "reflection/grpc_reflection_v1alpha", + "resolver", + "serviceconfig", + "stats", + "status", + "tap", + ] + pruneopts = "UT" + revision = "f495f5b15ae7ccda3b38c53a1bfcde4c1a58a2bc" + version = "v1.27.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/OpenBazaar/jsonpb", + "github.com/OpenBazaar/wallet-interface", + "github.com/asticode/go-astilectron", + "github.com/asticode/go-astilog", + "github.com/asticode/go-astitools/template", + "github.com/atotto/clipboard", + "github.com/boltdb/bolt", + "github.com/btcsuite/btcd/addrmgr", + "github.com/btcsuite/btcd/blockchain", + "github.com/btcsuite/btcd/btcec", + "github.com/btcsuite/btcd/chaincfg", + "github.com/btcsuite/btcd/chaincfg/chainhash", + "github.com/btcsuite/btcd/connmgr", + "github.com/btcsuite/btcd/peer", + "github.com/btcsuite/btcd/txscript", + "github.com/btcsuite/btcd/wire", + "github.com/btcsuite/btcutil", + "github.com/btcsuite/btcutil/bloom", + "github.com/btcsuite/btcutil/coinset", + "github.com/btcsuite/btcutil/hdkeychain", + "github.com/btcsuite/btcutil/txsort", + "github.com/btcsuite/btcwallet/wallet/txauthor", + "github.com/btcsuite/btcwallet/wallet/txrules", + "github.com/btcsuite/goleveldb/leveldb/errors", + "github.com/cevaris/ordered_map", + "github.com/fatih/color", + "github.com/golang/protobuf/proto", + "github.com/golang/protobuf/ptypes", + "github.com/golang/protobuf/ptypes/timestamp", + "github.com/jessevdk/go-flags", + "github.com/julienschmidt/httprouter", + "github.com/mattn/go-sqlite3", + "github.com/mitchellh/go-homedir", + "github.com/natefinch/lumberjack", + "github.com/op/go-logging", + "github.com/pkg/errors", + "github.com/skratchdot/open-golang/open", + "github.com/tyler-smith/go-bip39", + "github.com/yawning/bulb", + "golang.org/x/net/context", + "golang.org/x/net/proxy", + "google.golang.org/grpc", + "google.golang.org/grpc/reflection", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/OpenBazaar/spvwallet/Gopkg.toml b/vendor/github.com/OpenBazaar/spvwallet/Gopkg.toml new file mode 100644 index 0000000000..9d71a5bf82 --- /dev/null +++ b/vendor/github.com/OpenBazaar/spvwallet/Gopkg.toml @@ -0,0 +1,134 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + branch = "master" + name = "github.com/OpenBazaar/jsonpb" + +[[constraint]] + branch = "ethereum-master" + name = "github.com/OpenBazaar/wallet-interface" + +[[constraint]] + name = "github.com/asticode/go-astilectron" + version = "0.11.0" + +[[constraint]] + name = "github.com/asticode/go-astilog" + version = "1.5.0" + +[[constraint]] + name = "github.com/asticode/go-astitools" + version = "1.3.0" + +[[constraint]] + name = "github.com/atotto/clipboard" + version = "0.1.2" + +[[constraint]] + name = "github.com/boltdb/bolt" + version = "1.3.1" + +[[constraint]] + name = "github.com/btcsuite/btcd" + version = "0.20.1-beta" + +[[constraint]] + branch = "master" + name = "github.com/btcsuite/btcutil" + +[[constraint]] + name = "github.com/btcsuite/btcwallet" + version = "0.11.0" + +[[constraint]] + name = "github.com/btcsuite/goleveldb" + version = "1.0.0" + +[[constraint]] + branch = "master" + name = "github.com/cevaris/ordered_map" + +[[constraint]] + name = "github.com/fatih/color" + version = "1.9.0" + +[[constraint]] + name = "github.com/golang/protobuf" + version = "1.3.2" + +[[constraint]] + name = "github.com/jessevdk/go-flags" + version = "1.4.0" + +[[constraint]] + name = "github.com/julienschmidt/httprouter" + version = "1.3.0" + +[[constraint]] + name = "github.com/mattn/go-sqlite3" + version = "2.0.2" + +[[constraint]] + name = "github.com/mitchellh/go-homedir" + version = "1.1.0" + +[[constraint]] + name = "github.com/natefinch/lumberjack" + version = "2.1.0" + +[[constraint]] + name = "github.com/op/go-logging" + version = "1.0.0" + +[[constraint]] + name = "github.com/pkg/errors" + version = "0.9.1" + +[[constraint]] + branch = "master" + name = "github.com/skratchdot/open-golang" + +[[constraint]] + name = "github.com/tyler-smith/go-bip39" + version = "1.0.2" + +[[constraint]] + branch = "master" + name = "github.com/yawning/bulb" + +[[constraint]] + branch = "master" + name = "golang.org/x/net" + +[[constraint]] + name = "google.golang.org/grpc" + version = "1.26.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/OpenBazaar/spvwallet/api/pb/api.pb.go b/vendor/github.com/OpenBazaar/spvwallet/api/pb/api.pb.go deleted file mode 100644 index baa9649409..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/api/pb/api.pb.go +++ /dev/null @@ -1,2022 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: api.proto - -/* -Package pb is a generated protocol buffer package. - -It is generated from these files: - api.proto - -It has these top-level messages: - Empty - KeySelection - Address - Height - Balances - Key - Keys - Addresses - BoolResponse - NetParams - TransactionList - Tx - Txid - FeeLevelSelection - FeePerByte - Fee - SpendInfo - PeerList - Peer - Confirmations - Utxo - SweepInfo - Input - Output - Signature - CreateMultisigInfo - SignatureList - MultisignInfo - RawTx - EstimateFeeData - Header -*/ -package pb - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" -import google_protobuf "github.com/golang/protobuf/ptypes/timestamp" - -import ( - context "golang.org/x/net/context" - grpc "google.golang.org/grpc" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -type KeyPurpose int32 - -const ( - KeyPurpose_INTERNAL KeyPurpose = 0 - KeyPurpose_EXTERNAL KeyPurpose = 1 -) - -var KeyPurpose_name = map[int32]string{ - 0: "INTERNAL", - 1: "EXTERNAL", -} -var KeyPurpose_value = map[string]int32{ - "INTERNAL": 0, - "EXTERNAL": 1, -} - -func (x KeyPurpose) String() string { - return proto.EnumName(KeyPurpose_name, int32(x)) -} -func (KeyPurpose) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -type FeeLevel int32 - -const ( - FeeLevel_ECONOMIC FeeLevel = 0 - FeeLevel_NORMAL FeeLevel = 1 - FeeLevel_PRIORITY FeeLevel = 2 -) - -var FeeLevel_name = map[int32]string{ - 0: "ECONOMIC", - 1: "NORMAL", - 2: "PRIORITY", -} -var FeeLevel_value = map[string]int32{ - "ECONOMIC": 0, - "NORMAL": 1, - "PRIORITY": 2, -} - -func (x FeeLevel) String() string { - return proto.EnumName(FeeLevel_name, int32(x)) -} -func (FeeLevel) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } - -type Empty struct { -} - -func (m *Empty) Reset() { *m = Empty{} } -func (m *Empty) String() string { return proto.CompactTextString(m) } -func (*Empty) ProtoMessage() {} -func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -type KeySelection struct { - Purpose KeyPurpose `protobuf:"varint,1,opt,name=purpose,enum=pb.KeyPurpose" json:"purpose,omitempty"` -} - -func (m *KeySelection) Reset() { *m = KeySelection{} } -func (m *KeySelection) String() string { return proto.CompactTextString(m) } -func (*KeySelection) ProtoMessage() {} -func (*KeySelection) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } - -func (m *KeySelection) GetPurpose() KeyPurpose { - if m != nil { - return m.Purpose - } - return KeyPurpose_INTERNAL -} - -type Address struct { - Addr string `protobuf:"bytes,1,opt,name=addr" json:"addr,omitempty"` -} - -func (m *Address) Reset() { *m = Address{} } -func (m *Address) String() string { return proto.CompactTextString(m) } -func (*Address) ProtoMessage() {} -func (*Address) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } - -func (m *Address) GetAddr() string { - if m != nil { - return m.Addr - } - return "" -} - -type Height struct { - Height uint32 `protobuf:"varint,1,opt,name=height" json:"height,omitempty"` -} - -func (m *Height) Reset() { *m = Height{} } -func (m *Height) String() string { return proto.CompactTextString(m) } -func (*Height) ProtoMessage() {} -func (*Height) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } - -func (m *Height) GetHeight() uint32 { - if m != nil { - return m.Height - } - return 0 -} - -type Balances struct { - Confirmed uint64 `protobuf:"varint,1,opt,name=confirmed" json:"confirmed,omitempty"` - Unconfirmed uint64 `protobuf:"varint,2,opt,name=unconfirmed" json:"unconfirmed,omitempty"` -} - -func (m *Balances) Reset() { *m = Balances{} } -func (m *Balances) String() string { return proto.CompactTextString(m) } -func (*Balances) ProtoMessage() {} -func (*Balances) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } - -func (m *Balances) GetConfirmed() uint64 { - if m != nil { - return m.Confirmed - } - return 0 -} - -func (m *Balances) GetUnconfirmed() uint64 { - if m != nil { - return m.Unconfirmed - } - return 0 -} - -type Key struct { - Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` -} - -func (m *Key) Reset() { *m = Key{} } -func (m *Key) String() string { return proto.CompactTextString(m) } -func (*Key) ProtoMessage() {} -func (*Key) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } - -func (m *Key) GetKey() string { - if m != nil { - return m.Key - } - return "" -} - -type Keys struct { - Keys []*Key `protobuf:"bytes,1,rep,name=keys" json:"keys,omitempty"` -} - -func (m *Keys) Reset() { *m = Keys{} } -func (m *Keys) String() string { return proto.CompactTextString(m) } -func (*Keys) ProtoMessage() {} -func (*Keys) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } - -func (m *Keys) GetKeys() []*Key { - if m != nil { - return m.Keys - } - return nil -} - -type Addresses struct { - Addresses []*Address `protobuf:"bytes,1,rep,name=addresses" json:"addresses,omitempty"` -} - -func (m *Addresses) Reset() { *m = Addresses{} } -func (m *Addresses) String() string { return proto.CompactTextString(m) } -func (*Addresses) ProtoMessage() {} -func (*Addresses) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } - -func (m *Addresses) GetAddresses() []*Address { - if m != nil { - return m.Addresses - } - return nil -} - -type BoolResponse struct { - Bool bool `protobuf:"varint,1,opt,name=bool" json:"bool,omitempty"` -} - -func (m *BoolResponse) Reset() { *m = BoolResponse{} } -func (m *BoolResponse) String() string { return proto.CompactTextString(m) } -func (*BoolResponse) ProtoMessage() {} -func (*BoolResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } - -func (m *BoolResponse) GetBool() bool { - if m != nil { - return m.Bool - } - return false -} - -type NetParams struct { - Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` -} - -func (m *NetParams) Reset() { *m = NetParams{} } -func (m *NetParams) String() string { return proto.CompactTextString(m) } -func (*NetParams) ProtoMessage() {} -func (*NetParams) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } - -func (m *NetParams) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -type TransactionList struct { - Transactions []*Tx `protobuf:"bytes,1,rep,name=transactions" json:"transactions,omitempty"` -} - -func (m *TransactionList) Reset() { *m = TransactionList{} } -func (m *TransactionList) String() string { return proto.CompactTextString(m) } -func (*TransactionList) ProtoMessage() {} -func (*TransactionList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } - -func (m *TransactionList) GetTransactions() []*Tx { - if m != nil { - return m.Transactions - } - return nil -} - -type Tx struct { - Txid string `protobuf:"bytes,1,opt,name=txid" json:"txid,omitempty"` - Value int64 `protobuf:"varint,2,opt,name=value" json:"value,omitempty"` - Height int32 `protobuf:"varint,3,opt,name=height" json:"height,omitempty"` - Timestamp *google_protobuf.Timestamp `protobuf:"bytes,4,opt,name=timestamp" json:"timestamp,omitempty"` - WatchOnly bool `protobuf:"varint,5,opt,name=watchOnly" json:"watchOnly,omitempty"` - Raw []byte `protobuf:"bytes,6,opt,name=raw,proto3" json:"raw,omitempty"` -} - -func (m *Tx) Reset() { *m = Tx{} } -func (m *Tx) String() string { return proto.CompactTextString(m) } -func (*Tx) ProtoMessage() {} -func (*Tx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } - -func (m *Tx) GetTxid() string { - if m != nil { - return m.Txid - } - return "" -} - -func (m *Tx) GetValue() int64 { - if m != nil { - return m.Value - } - return 0 -} - -func (m *Tx) GetHeight() int32 { - if m != nil { - return m.Height - } - return 0 -} - -func (m *Tx) GetTimestamp() *google_protobuf.Timestamp { - if m != nil { - return m.Timestamp - } - return nil -} - -func (m *Tx) GetWatchOnly() bool { - if m != nil { - return m.WatchOnly - } - return false -} - -func (m *Tx) GetRaw() []byte { - if m != nil { - return m.Raw - } - return nil -} - -type Txid struct { - Hash string `protobuf:"bytes,1,opt,name=hash" json:"hash,omitempty"` -} - -func (m *Txid) Reset() { *m = Txid{} } -func (m *Txid) String() string { return proto.CompactTextString(m) } -func (*Txid) ProtoMessage() {} -func (*Txid) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } - -func (m *Txid) GetHash() string { - if m != nil { - return m.Hash - } - return "" -} - -type FeeLevelSelection struct { - FeeLevel FeeLevel `protobuf:"varint,1,opt,name=feeLevel,enum=pb.FeeLevel" json:"feeLevel,omitempty"` -} - -func (m *FeeLevelSelection) Reset() { *m = FeeLevelSelection{} } -func (m *FeeLevelSelection) String() string { return proto.CompactTextString(m) } -func (*FeeLevelSelection) ProtoMessage() {} -func (*FeeLevelSelection) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } - -func (m *FeeLevelSelection) GetFeeLevel() FeeLevel { - if m != nil { - return m.FeeLevel - } - return FeeLevel_ECONOMIC -} - -type FeePerByte struct { - Fee uint64 `protobuf:"varint,1,opt,name=fee" json:"fee,omitempty"` -} - -func (m *FeePerByte) Reset() { *m = FeePerByte{} } -func (m *FeePerByte) String() string { return proto.CompactTextString(m) } -func (*FeePerByte) ProtoMessage() {} -func (*FeePerByte) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } - -func (m *FeePerByte) GetFee() uint64 { - if m != nil { - return m.Fee - } - return 0 -} - -type Fee struct { - Fee uint64 `protobuf:"varint,1,opt,name=fee" json:"fee,omitempty"` -} - -func (m *Fee) Reset() { *m = Fee{} } -func (m *Fee) String() string { return proto.CompactTextString(m) } -func (*Fee) ProtoMessage() {} -func (*Fee) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } - -func (m *Fee) GetFee() uint64 { - if m != nil { - return m.Fee - } - return 0 -} - -type SpendInfo struct { - Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` - Amount uint64 `protobuf:"varint,2,opt,name=amount" json:"amount,omitempty"` - FeeLevel FeeLevel `protobuf:"varint,3,opt,name=feeLevel,enum=pb.FeeLevel" json:"feeLevel,omitempty"` -} - -func (m *SpendInfo) Reset() { *m = SpendInfo{} } -func (m *SpendInfo) String() string { return proto.CompactTextString(m) } -func (*SpendInfo) ProtoMessage() {} -func (*SpendInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } - -func (m *SpendInfo) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func (m *SpendInfo) GetAmount() uint64 { - if m != nil { - return m.Amount - } - return 0 -} - -func (m *SpendInfo) GetFeeLevel() FeeLevel { - if m != nil { - return m.FeeLevel - } - return FeeLevel_ECONOMIC -} - -type PeerList struct { - Peers []*Peer `protobuf:"bytes,1,rep,name=peers" json:"peers,omitempty"` -} - -func (m *PeerList) Reset() { *m = PeerList{} } -func (m *PeerList) String() string { return proto.CompactTextString(m) } -func (*PeerList) ProtoMessage() {} -func (*PeerList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } - -func (m *PeerList) GetPeers() []*Peer { - if m != nil { - return m.Peers - } - return nil -} - -type Peer struct { - Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` - BytesSent uint64 `protobuf:"varint,2,opt,name=bytesSent" json:"bytesSent,omitempty"` - BytesReceived uint64 `protobuf:"varint,3,opt,name=bytesReceived" json:"bytesReceived,omitempty"` - Connected bool `protobuf:"varint,4,opt,name=connected" json:"connected,omitempty"` - ID int32 `protobuf:"varint,5,opt,name=ID" json:"ID,omitempty"` - LastBlock int32 `protobuf:"varint,6,opt,name=lastBlock" json:"lastBlock,omitempty"` - ProtocolVersion uint32 `protobuf:"varint,7,opt,name=protocolVersion" json:"protocolVersion,omitempty"` - Services string `protobuf:"bytes,8,opt,name=services" json:"services,omitempty"` - UserAgent string `protobuf:"bytes,9,opt,name=userAgent" json:"userAgent,omitempty"` - TimeConnected *google_protobuf.Timestamp `protobuf:"bytes,10,opt,name=timeConnected" json:"timeConnected,omitempty"` -} - -func (m *Peer) Reset() { *m = Peer{} } -func (m *Peer) String() string { return proto.CompactTextString(m) } -func (*Peer) ProtoMessage() {} -func (*Peer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } - -func (m *Peer) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func (m *Peer) GetBytesSent() uint64 { - if m != nil { - return m.BytesSent - } - return 0 -} - -func (m *Peer) GetBytesReceived() uint64 { - if m != nil { - return m.BytesReceived - } - return 0 -} - -func (m *Peer) GetConnected() bool { - if m != nil { - return m.Connected - } - return false -} - -func (m *Peer) GetID() int32 { - if m != nil { - return m.ID - } - return 0 -} - -func (m *Peer) GetLastBlock() int32 { - if m != nil { - return m.LastBlock - } - return 0 -} - -func (m *Peer) GetProtocolVersion() uint32 { - if m != nil { - return m.ProtocolVersion - } - return 0 -} - -func (m *Peer) GetServices() string { - if m != nil { - return m.Services - } - return "" -} - -func (m *Peer) GetUserAgent() string { - if m != nil { - return m.UserAgent - } - return "" -} - -func (m *Peer) GetTimeConnected() *google_protobuf.Timestamp { - if m != nil { - return m.TimeConnected - } - return nil -} - -type Confirmations struct { - Confirmations uint32 `protobuf:"varint,1,opt,name=confirmations" json:"confirmations,omitempty"` -} - -func (m *Confirmations) Reset() { *m = Confirmations{} } -func (m *Confirmations) String() string { return proto.CompactTextString(m) } -func (*Confirmations) ProtoMessage() {} -func (*Confirmations) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } - -func (m *Confirmations) GetConfirmations() uint32 { - if m != nil { - return m.Confirmations - } - return 0 -} - -type Utxo struct { - Txid string `protobuf:"bytes,1,opt,name=txid" json:"txid,omitempty"` - Index uint32 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` - Value uint64 `protobuf:"varint,3,opt,name=value" json:"value,omitempty"` -} - -func (m *Utxo) Reset() { *m = Utxo{} } -func (m *Utxo) String() string { return proto.CompactTextString(m) } -func (*Utxo) ProtoMessage() {} -func (*Utxo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } - -func (m *Utxo) GetTxid() string { - if m != nil { - return m.Txid - } - return "" -} - -func (m *Utxo) GetIndex() uint32 { - if m != nil { - return m.Index - } - return 0 -} - -func (m *Utxo) GetValue() uint64 { - if m != nil { - return m.Value - } - return 0 -} - -type SweepInfo struct { - Utxos []*Utxo `protobuf:"bytes,1,rep,name=utxos" json:"utxos,omitempty"` - Address string `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"` - Key string `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` - RedeemScript []byte `protobuf:"bytes,4,opt,name=redeemScript,proto3" json:"redeemScript,omitempty"` - FeeLevel FeeLevel `protobuf:"varint,5,opt,name=feeLevel,enum=pb.FeeLevel" json:"feeLevel,omitempty"` -} - -func (m *SweepInfo) Reset() { *m = SweepInfo{} } -func (m *SweepInfo) String() string { return proto.CompactTextString(m) } -func (*SweepInfo) ProtoMessage() {} -func (*SweepInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } - -func (m *SweepInfo) GetUtxos() []*Utxo { - if m != nil { - return m.Utxos - } - return nil -} - -func (m *SweepInfo) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func (m *SweepInfo) GetKey() string { - if m != nil { - return m.Key - } - return "" -} - -func (m *SweepInfo) GetRedeemScript() []byte { - if m != nil { - return m.RedeemScript - } - return nil -} - -func (m *SweepInfo) GetFeeLevel() FeeLevel { - if m != nil { - return m.FeeLevel - } - return FeeLevel_ECONOMIC -} - -type Input struct { - Txid string `protobuf:"bytes,1,opt,name=txid" json:"txid,omitempty"` - Index uint32 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` -} - -func (m *Input) Reset() { *m = Input{} } -func (m *Input) String() string { return proto.CompactTextString(m) } -func (*Input) ProtoMessage() {} -func (*Input) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } - -func (m *Input) GetTxid() string { - if m != nil { - return m.Txid - } - return "" -} - -func (m *Input) GetIndex() uint32 { - if m != nil { - return m.Index - } - return 0 -} - -type Output struct { - ScriptPubKey []byte `protobuf:"bytes,1,opt,name=scriptPubKey,proto3" json:"scriptPubKey,omitempty"` - Value uint64 `protobuf:"varint,2,opt,name=value" json:"value,omitempty"` -} - -func (m *Output) Reset() { *m = Output{} } -func (m *Output) String() string { return proto.CompactTextString(m) } -func (*Output) ProtoMessage() {} -func (*Output) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } - -func (m *Output) GetScriptPubKey() []byte { - if m != nil { - return m.ScriptPubKey - } - return nil -} - -func (m *Output) GetValue() uint64 { - if m != nil { - return m.Value - } - return 0 -} - -type Signature struct { - Index uint32 `protobuf:"varint,1,opt,name=index" json:"index,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (m *Signature) Reset() { *m = Signature{} } -func (m *Signature) String() string { return proto.CompactTextString(m) } -func (*Signature) ProtoMessage() {} -func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } - -func (m *Signature) GetIndex() uint32 { - if m != nil { - return m.Index - } - return 0 -} - -func (m *Signature) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -type CreateMultisigInfo struct { - Inputs []*Input `protobuf:"bytes,1,rep,name=inputs" json:"inputs,omitempty"` - Outputs []*Output `protobuf:"bytes,2,rep,name=outputs" json:"outputs,omitempty"` - Key string `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` - RedeemScript []byte `protobuf:"bytes,4,opt,name=redeemScript,proto3" json:"redeemScript,omitempty"` - FeePerByte uint64 `protobuf:"varint,5,opt,name=feePerByte" json:"feePerByte,omitempty"` -} - -func (m *CreateMultisigInfo) Reset() { *m = CreateMultisigInfo{} } -func (m *CreateMultisigInfo) String() string { return proto.CompactTextString(m) } -func (*CreateMultisigInfo) ProtoMessage() {} -func (*CreateMultisigInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } - -func (m *CreateMultisigInfo) GetInputs() []*Input { - if m != nil { - return m.Inputs - } - return nil -} - -func (m *CreateMultisigInfo) GetOutputs() []*Output { - if m != nil { - return m.Outputs - } - return nil -} - -func (m *CreateMultisigInfo) GetKey() string { - if m != nil { - return m.Key - } - return "" -} - -func (m *CreateMultisigInfo) GetRedeemScript() []byte { - if m != nil { - return m.RedeemScript - } - return nil -} - -func (m *CreateMultisigInfo) GetFeePerByte() uint64 { - if m != nil { - return m.FeePerByte - } - return 0 -} - -type SignatureList struct { - Sigs []*Signature `protobuf:"bytes,1,rep,name=sigs" json:"sigs,omitempty"` -} - -func (m *SignatureList) Reset() { *m = SignatureList{} } -func (m *SignatureList) String() string { return proto.CompactTextString(m) } -func (*SignatureList) ProtoMessage() {} -func (*SignatureList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } - -func (m *SignatureList) GetSigs() []*Signature { - if m != nil { - return m.Sigs - } - return nil -} - -type MultisignInfo struct { - Inputs []*Input `protobuf:"bytes,1,rep,name=inputs" json:"inputs,omitempty"` - Outputs []*Output `protobuf:"bytes,2,rep,name=outputs" json:"outputs,omitempty"` - Sig1 []*Signature `protobuf:"bytes,3,rep,name=sig1" json:"sig1,omitempty"` - Sig2 []*Signature `protobuf:"bytes,4,rep,name=sig2" json:"sig2,omitempty"` - RedeemScript []byte `protobuf:"bytes,5,opt,name=redeemScript,proto3" json:"redeemScript,omitempty"` - FeePerByte uint64 `protobuf:"varint,6,opt,name=feePerByte" json:"feePerByte,omitempty"` - Broadcast bool `protobuf:"varint,7,opt,name=broadcast" json:"broadcast,omitempty"` -} - -func (m *MultisignInfo) Reset() { *m = MultisignInfo{} } -func (m *MultisignInfo) String() string { return proto.CompactTextString(m) } -func (*MultisignInfo) ProtoMessage() {} -func (*MultisignInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } - -func (m *MultisignInfo) GetInputs() []*Input { - if m != nil { - return m.Inputs - } - return nil -} - -func (m *MultisignInfo) GetOutputs() []*Output { - if m != nil { - return m.Outputs - } - return nil -} - -func (m *MultisignInfo) GetSig1() []*Signature { - if m != nil { - return m.Sig1 - } - return nil -} - -func (m *MultisignInfo) GetSig2() []*Signature { - if m != nil { - return m.Sig2 - } - return nil -} - -func (m *MultisignInfo) GetRedeemScript() []byte { - if m != nil { - return m.RedeemScript - } - return nil -} - -func (m *MultisignInfo) GetFeePerByte() uint64 { - if m != nil { - return m.FeePerByte - } - return 0 -} - -func (m *MultisignInfo) GetBroadcast() bool { - if m != nil { - return m.Broadcast - } - return false -} - -type RawTx struct { - Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` -} - -func (m *RawTx) Reset() { *m = RawTx{} } -func (m *RawTx) String() string { return proto.CompactTextString(m) } -func (*RawTx) ProtoMessage() {} -func (*RawTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } - -func (m *RawTx) GetTx() []byte { - if m != nil { - return m.Tx - } - return nil -} - -type EstimateFeeData struct { - Inputs []*Input `protobuf:"bytes,1,rep,name=inputs" json:"inputs,omitempty"` - Outputs []*Output `protobuf:"bytes,2,rep,name=outputs" json:"outputs,omitempty"` - FeePerByte uint64 `protobuf:"varint,3,opt,name=feePerByte" json:"feePerByte,omitempty"` -} - -func (m *EstimateFeeData) Reset() { *m = EstimateFeeData{} } -func (m *EstimateFeeData) String() string { return proto.CompactTextString(m) } -func (*EstimateFeeData) ProtoMessage() {} -func (*EstimateFeeData) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } - -func (m *EstimateFeeData) GetInputs() []*Input { - if m != nil { - return m.Inputs - } - return nil -} - -func (m *EstimateFeeData) GetOutputs() []*Output { - if m != nil { - return m.Outputs - } - return nil -} - -func (m *EstimateFeeData) GetFeePerByte() uint64 { - if m != nil { - return m.FeePerByte - } - return 0 -} - -type Header struct { - Entry string `protobuf:"bytes,1,opt,name=entry" json:"entry,omitempty"` -} - -func (m *Header) Reset() { *m = Header{} } -func (m *Header) String() string { return proto.CompactTextString(m) } -func (*Header) ProtoMessage() {} -func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } - -func (m *Header) GetEntry() string { - if m != nil { - return m.Entry - } - return "" -} - -func init() { - proto.RegisterType((*Empty)(nil), "pb.Empty") - proto.RegisterType((*KeySelection)(nil), "pb.KeySelection") - proto.RegisterType((*Address)(nil), "pb.Address") - proto.RegisterType((*Height)(nil), "pb.Height") - proto.RegisterType((*Balances)(nil), "pb.Balances") - proto.RegisterType((*Key)(nil), "pb.Key") - proto.RegisterType((*Keys)(nil), "pb.Keys") - proto.RegisterType((*Addresses)(nil), "pb.Addresses") - proto.RegisterType((*BoolResponse)(nil), "pb.BoolResponse") - proto.RegisterType((*NetParams)(nil), "pb.NetParams") - proto.RegisterType((*TransactionList)(nil), "pb.TransactionList") - proto.RegisterType((*Tx)(nil), "pb.Tx") - proto.RegisterType((*Txid)(nil), "pb.Txid") - proto.RegisterType((*FeeLevelSelection)(nil), "pb.FeeLevelSelection") - proto.RegisterType((*FeePerByte)(nil), "pb.FeePerByte") - proto.RegisterType((*Fee)(nil), "pb.Fee") - proto.RegisterType((*SpendInfo)(nil), "pb.SpendInfo") - proto.RegisterType((*PeerList)(nil), "pb.PeerList") - proto.RegisterType((*Peer)(nil), "pb.Peer") - proto.RegisterType((*Confirmations)(nil), "pb.Confirmations") - proto.RegisterType((*Utxo)(nil), "pb.Utxo") - proto.RegisterType((*SweepInfo)(nil), "pb.SweepInfo") - proto.RegisterType((*Input)(nil), "pb.Input") - proto.RegisterType((*Output)(nil), "pb.Output") - proto.RegisterType((*Signature)(nil), "pb.Signature") - proto.RegisterType((*CreateMultisigInfo)(nil), "pb.CreateMultisigInfo") - proto.RegisterType((*SignatureList)(nil), "pb.SignatureList") - proto.RegisterType((*MultisignInfo)(nil), "pb.MultisignInfo") - proto.RegisterType((*RawTx)(nil), "pb.RawTx") - proto.RegisterType((*EstimateFeeData)(nil), "pb.EstimateFeeData") - proto.RegisterType((*Header)(nil), "pb.Header") - proto.RegisterEnum("pb.KeyPurpose", KeyPurpose_name, KeyPurpose_value) - proto.RegisterEnum("pb.FeeLevel", FeeLevel_name, FeeLevel_value) -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// Client API for API service - -type APIClient interface { - Stop(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) - CurrentAddress(ctx context.Context, in *KeySelection, opts ...grpc.CallOption) (*Address, error) - NewAddress(ctx context.Context, in *KeySelection, opts ...grpc.CallOption) (*Address, error) - ChainTip(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Height, error) - Balance(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Balances, error) - MasterPrivateKey(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Key, error) - MasterPublicKey(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Key, error) - HasKey(ctx context.Context, in *Address, opts ...grpc.CallOption) (*BoolResponse, error) - Params(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*NetParams, error) - Transactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TransactionList, error) - GetTransaction(ctx context.Context, in *Txid, opts ...grpc.CallOption) (*Tx, error) - GetFeePerByte(ctx context.Context, in *FeeLevelSelection, opts ...grpc.CallOption) (*FeePerByte, error) - Spend(ctx context.Context, in *SpendInfo, opts ...grpc.CallOption) (*Txid, error) - BumpFee(ctx context.Context, in *Txid, opts ...grpc.CallOption) (*Txid, error) - Peers(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PeerList, error) - AddWatchedAddress(ctx context.Context, in *Address, opts ...grpc.CallOption) (*Empty, error) - GetConfirmations(ctx context.Context, in *Txid, opts ...grpc.CallOption) (*Confirmations, error) - SweepAddress(ctx context.Context, in *SweepInfo, opts ...grpc.CallOption) (*Txid, error) - ReSyncBlockchain(ctx context.Context, in *google_protobuf.Timestamp, opts ...grpc.CallOption) (*Empty, error) - CreateMultisigSignature(ctx context.Context, in *CreateMultisigInfo, opts ...grpc.CallOption) (*SignatureList, error) - Multisign(ctx context.Context, in *MultisignInfo, opts ...grpc.CallOption) (*RawTx, error) - EstimateFee(ctx context.Context, in *EstimateFeeData, opts ...grpc.CallOption) (*Fee, error) - GetKey(ctx context.Context, in *Address, opts ...grpc.CallOption) (*Key, error) - ListKeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Keys, error) - ListAddresses(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Addresses, error) - WalletNotify(ctx context.Context, in *Empty, opts ...grpc.CallOption) (API_WalletNotifyClient, error) - DumpHeaders(ctx context.Context, in *Empty, opts ...grpc.CallOption) (API_DumpHeadersClient, error) -} - -type aPIClient struct { - cc *grpc.ClientConn -} - -func NewAPIClient(cc *grpc.ClientConn) APIClient { - return &aPIClient{cc} -} - -func (c *aPIClient) Stop(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) - err := grpc.Invoke(ctx, "/pb.API/Stop", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) CurrentAddress(ctx context.Context, in *KeySelection, opts ...grpc.CallOption) (*Address, error) { - out := new(Address) - err := grpc.Invoke(ctx, "/pb.API/CurrentAddress", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) NewAddress(ctx context.Context, in *KeySelection, opts ...grpc.CallOption) (*Address, error) { - out := new(Address) - err := grpc.Invoke(ctx, "/pb.API/NewAddress", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) ChainTip(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Height, error) { - out := new(Height) - err := grpc.Invoke(ctx, "/pb.API/ChainTip", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) Balance(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Balances, error) { - out := new(Balances) - err := grpc.Invoke(ctx, "/pb.API/Balance", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) MasterPrivateKey(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Key, error) { - out := new(Key) - err := grpc.Invoke(ctx, "/pb.API/MasterPrivateKey", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) MasterPublicKey(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Key, error) { - out := new(Key) - err := grpc.Invoke(ctx, "/pb.API/MasterPublicKey", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) HasKey(ctx context.Context, in *Address, opts ...grpc.CallOption) (*BoolResponse, error) { - out := new(BoolResponse) - err := grpc.Invoke(ctx, "/pb.API/HasKey", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) Params(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*NetParams, error) { - out := new(NetParams) - err := grpc.Invoke(ctx, "/pb.API/Params", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) Transactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TransactionList, error) { - out := new(TransactionList) - err := grpc.Invoke(ctx, "/pb.API/Transactions", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) GetTransaction(ctx context.Context, in *Txid, opts ...grpc.CallOption) (*Tx, error) { - out := new(Tx) - err := grpc.Invoke(ctx, "/pb.API/GetTransaction", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) GetFeePerByte(ctx context.Context, in *FeeLevelSelection, opts ...grpc.CallOption) (*FeePerByte, error) { - out := new(FeePerByte) - err := grpc.Invoke(ctx, "/pb.API/GetFeePerByte", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) Spend(ctx context.Context, in *SpendInfo, opts ...grpc.CallOption) (*Txid, error) { - out := new(Txid) - err := grpc.Invoke(ctx, "/pb.API/Spend", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) BumpFee(ctx context.Context, in *Txid, opts ...grpc.CallOption) (*Txid, error) { - out := new(Txid) - err := grpc.Invoke(ctx, "/pb.API/BumpFee", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) Peers(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PeerList, error) { - out := new(PeerList) - err := grpc.Invoke(ctx, "/pb.API/Peers", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) AddWatchedAddress(ctx context.Context, in *Address, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) - err := grpc.Invoke(ctx, "/pb.API/AddWatchedAddress", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) GetConfirmations(ctx context.Context, in *Txid, opts ...grpc.CallOption) (*Confirmations, error) { - out := new(Confirmations) - err := grpc.Invoke(ctx, "/pb.API/GetConfirmations", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) SweepAddress(ctx context.Context, in *SweepInfo, opts ...grpc.CallOption) (*Txid, error) { - out := new(Txid) - err := grpc.Invoke(ctx, "/pb.API/SweepAddress", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) ReSyncBlockchain(ctx context.Context, in *google_protobuf.Timestamp, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) - err := grpc.Invoke(ctx, "/pb.API/ReSyncBlockchain", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) CreateMultisigSignature(ctx context.Context, in *CreateMultisigInfo, opts ...grpc.CallOption) (*SignatureList, error) { - out := new(SignatureList) - err := grpc.Invoke(ctx, "/pb.API/CreateMultisigSignature", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) Multisign(ctx context.Context, in *MultisignInfo, opts ...grpc.CallOption) (*RawTx, error) { - out := new(RawTx) - err := grpc.Invoke(ctx, "/pb.API/Multisign", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) EstimateFee(ctx context.Context, in *EstimateFeeData, opts ...grpc.CallOption) (*Fee, error) { - out := new(Fee) - err := grpc.Invoke(ctx, "/pb.API/EstimateFee", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) GetKey(ctx context.Context, in *Address, opts ...grpc.CallOption) (*Key, error) { - out := new(Key) - err := grpc.Invoke(ctx, "/pb.API/GetKey", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) ListKeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Keys, error) { - out := new(Keys) - err := grpc.Invoke(ctx, "/pb.API/ListKeys", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) ListAddresses(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Addresses, error) { - out := new(Addresses) - err := grpc.Invoke(ctx, "/pb.API/ListAddresses", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aPIClient) WalletNotify(ctx context.Context, in *Empty, opts ...grpc.CallOption) (API_WalletNotifyClient, error) { - stream, err := grpc.NewClientStream(ctx, &_API_serviceDesc.Streams[0], c.cc, "/pb.API/WalletNotify", opts...) - if err != nil { - return nil, err - } - x := &aPIWalletNotifyClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type API_WalletNotifyClient interface { - Recv() (*Tx, error) - grpc.ClientStream -} - -type aPIWalletNotifyClient struct { - grpc.ClientStream -} - -func (x *aPIWalletNotifyClient) Recv() (*Tx, error) { - m := new(Tx) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *aPIClient) DumpHeaders(ctx context.Context, in *Empty, opts ...grpc.CallOption) (API_DumpHeadersClient, error) { - stream, err := grpc.NewClientStream(ctx, &_API_serviceDesc.Streams[1], c.cc, "/pb.API/DumpHeaders", opts...) - if err != nil { - return nil, err - } - x := &aPIDumpHeadersClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type API_DumpHeadersClient interface { - Recv() (*Header, error) - grpc.ClientStream -} - -type aPIDumpHeadersClient struct { - grpc.ClientStream -} - -func (x *aPIDumpHeadersClient) Recv() (*Header, error) { - m := new(Header) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// Server API for API service - -type APIServer interface { - Stop(context.Context, *Empty) (*Empty, error) - CurrentAddress(context.Context, *KeySelection) (*Address, error) - NewAddress(context.Context, *KeySelection) (*Address, error) - ChainTip(context.Context, *Empty) (*Height, error) - Balance(context.Context, *Empty) (*Balances, error) - MasterPrivateKey(context.Context, *Empty) (*Key, error) - MasterPublicKey(context.Context, *Empty) (*Key, error) - HasKey(context.Context, *Address) (*BoolResponse, error) - Params(context.Context, *Empty) (*NetParams, error) - Transactions(context.Context, *Empty) (*TransactionList, error) - GetTransaction(context.Context, *Txid) (*Tx, error) - GetFeePerByte(context.Context, *FeeLevelSelection) (*FeePerByte, error) - Spend(context.Context, *SpendInfo) (*Txid, error) - BumpFee(context.Context, *Txid) (*Txid, error) - Peers(context.Context, *Empty) (*PeerList, error) - AddWatchedAddress(context.Context, *Address) (*Empty, error) - GetConfirmations(context.Context, *Txid) (*Confirmations, error) - SweepAddress(context.Context, *SweepInfo) (*Txid, error) - ReSyncBlockchain(context.Context, *google_protobuf.Timestamp) (*Empty, error) - CreateMultisigSignature(context.Context, *CreateMultisigInfo) (*SignatureList, error) - Multisign(context.Context, *MultisignInfo) (*RawTx, error) - EstimateFee(context.Context, *EstimateFeeData) (*Fee, error) - GetKey(context.Context, *Address) (*Key, error) - ListKeys(context.Context, *Empty) (*Keys, error) - ListAddresses(context.Context, *Empty) (*Addresses, error) - WalletNotify(*Empty, API_WalletNotifyServer) error - DumpHeaders(*Empty, API_DumpHeadersServer) error -} - -func RegisterAPIServer(s *grpc.Server, srv APIServer) { - s.RegisterService(&_API_serviceDesc, srv) -} - -func _API_Stop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).Stop(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/Stop", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).Stop(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_CurrentAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(KeySelection) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).CurrentAddress(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/CurrentAddress", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).CurrentAddress(ctx, req.(*KeySelection)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_NewAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(KeySelection) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).NewAddress(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/NewAddress", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).NewAddress(ctx, req.(*KeySelection)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_ChainTip_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).ChainTip(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/ChainTip", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).ChainTip(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_Balance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).Balance(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/Balance", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).Balance(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_MasterPrivateKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).MasterPrivateKey(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/MasterPrivateKey", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).MasterPrivateKey(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_MasterPublicKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).MasterPublicKey(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/MasterPublicKey", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).MasterPublicKey(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_HasKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Address) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).HasKey(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/HasKey", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).HasKey(ctx, req.(*Address)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).Params(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/Params", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).Params(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_Transactions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).Transactions(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/Transactions", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).Transactions(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_GetTransaction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Txid) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).GetTransaction(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/GetTransaction", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).GetTransaction(ctx, req.(*Txid)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_GetFeePerByte_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(FeeLevelSelection) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).GetFeePerByte(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/GetFeePerByte", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).GetFeePerByte(ctx, req.(*FeeLevelSelection)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_Spend_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SpendInfo) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).Spend(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/Spend", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).Spend(ctx, req.(*SpendInfo)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_BumpFee_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Txid) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).BumpFee(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/BumpFee", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).BumpFee(ctx, req.(*Txid)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_Peers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).Peers(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/Peers", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).Peers(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_AddWatchedAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Address) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).AddWatchedAddress(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/AddWatchedAddress", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).AddWatchedAddress(ctx, req.(*Address)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_GetConfirmations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Txid) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).GetConfirmations(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/GetConfirmations", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).GetConfirmations(ctx, req.(*Txid)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_SweepAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SweepInfo) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).SweepAddress(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/SweepAddress", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).SweepAddress(ctx, req.(*SweepInfo)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_ReSyncBlockchain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(google_protobuf.Timestamp) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).ReSyncBlockchain(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/ReSyncBlockchain", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).ReSyncBlockchain(ctx, req.(*google_protobuf.Timestamp)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_CreateMultisigSignature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateMultisigInfo) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).CreateMultisigSignature(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/CreateMultisigSignature", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).CreateMultisigSignature(ctx, req.(*CreateMultisigInfo)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_Multisign_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MultisignInfo) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).Multisign(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/Multisign", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).Multisign(ctx, req.(*MultisignInfo)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_EstimateFee_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(EstimateFeeData) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).EstimateFee(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/EstimateFee", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).EstimateFee(ctx, req.(*EstimateFeeData)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_GetKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Address) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).GetKey(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/GetKey", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).GetKey(ctx, req.(*Address)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_ListKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).ListKeys(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/ListKeys", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).ListKeys(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_ListAddresses_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(APIServer).ListAddresses(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.API/ListAddresses", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(APIServer).ListAddresses(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _API_WalletNotify_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(Empty) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(APIServer).WalletNotify(m, &aPIWalletNotifyServer{stream}) -} - -type API_WalletNotifyServer interface { - Send(*Tx) error - grpc.ServerStream -} - -type aPIWalletNotifyServer struct { - grpc.ServerStream -} - -func (x *aPIWalletNotifyServer) Send(m *Tx) error { - return x.ServerStream.SendMsg(m) -} - -func _API_DumpHeaders_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(Empty) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(APIServer).DumpHeaders(m, &aPIDumpHeadersServer{stream}) -} - -type API_DumpHeadersServer interface { - Send(*Header) error - grpc.ServerStream -} - -type aPIDumpHeadersServer struct { - grpc.ServerStream -} - -func (x *aPIDumpHeadersServer) Send(m *Header) error { - return x.ServerStream.SendMsg(m) -} - -var _API_serviceDesc = grpc.ServiceDesc{ - ServiceName: "pb.API", - HandlerType: (*APIServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Stop", - Handler: _API_Stop_Handler, - }, - { - MethodName: "CurrentAddress", - Handler: _API_CurrentAddress_Handler, - }, - { - MethodName: "NewAddress", - Handler: _API_NewAddress_Handler, - }, - { - MethodName: "ChainTip", - Handler: _API_ChainTip_Handler, - }, - { - MethodName: "Balance", - Handler: _API_Balance_Handler, - }, - { - MethodName: "MasterPrivateKey", - Handler: _API_MasterPrivateKey_Handler, - }, - { - MethodName: "MasterPublicKey", - Handler: _API_MasterPublicKey_Handler, - }, - { - MethodName: "HasKey", - Handler: _API_HasKey_Handler, - }, - { - MethodName: "Params", - Handler: _API_Params_Handler, - }, - { - MethodName: "Transactions", - Handler: _API_Transactions_Handler, - }, - { - MethodName: "GetTransaction", - Handler: _API_GetTransaction_Handler, - }, - { - MethodName: "GetFeePerByte", - Handler: _API_GetFeePerByte_Handler, - }, - { - MethodName: "Spend", - Handler: _API_Spend_Handler, - }, - { - MethodName: "BumpFee", - Handler: _API_BumpFee_Handler, - }, - { - MethodName: "Peers", - Handler: _API_Peers_Handler, - }, - { - MethodName: "AddWatchedAddress", - Handler: _API_AddWatchedAddress_Handler, - }, - { - MethodName: "GetConfirmations", - Handler: _API_GetConfirmations_Handler, - }, - { - MethodName: "SweepAddress", - Handler: _API_SweepAddress_Handler, - }, - { - MethodName: "ReSyncBlockchain", - Handler: _API_ReSyncBlockchain_Handler, - }, - { - MethodName: "CreateMultisigSignature", - Handler: _API_CreateMultisigSignature_Handler, - }, - { - MethodName: "Multisign", - Handler: _API_Multisign_Handler, - }, - { - MethodName: "EstimateFee", - Handler: _API_EstimateFee_Handler, - }, - { - MethodName: "GetKey", - Handler: _API_GetKey_Handler, - }, - { - MethodName: "ListKeys", - Handler: _API_ListKeys_Handler, - }, - { - MethodName: "ListAddresses", - Handler: _API_ListAddresses_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "WalletNotify", - Handler: _API_WalletNotify_Handler, - ServerStreams: true, - }, - { - StreamName: "DumpHeaders", - Handler: _API_DumpHeaders_Handler, - ServerStreams: true, - }, - }, - Metadata: "api.proto", -} - -func init() { proto.RegisterFile("api.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 1504 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0x5d, 0x6f, 0x1b, 0x4d, - 0x15, 0xf6, 0xb7, 0xbd, 0x27, 0x76, 0xe2, 0x0e, 0xf0, 0xd6, 0x32, 0x25, 0x75, 0xa7, 0x45, 0xb8, - 0x41, 0xa4, 0x8d, 0x11, 0xa8, 0x12, 0xaa, 0x20, 0xdf, 0x35, 0x69, 0x12, 0x6b, 0x6c, 0x28, 0x5c, - 0x8e, 0xbd, 0x27, 0xce, 0xaa, 0xf6, 0xee, 0x6a, 0x77, 0x36, 0xb1, 0xb9, 0xe2, 0xb7, 0x20, 0x71, - 0x8f, 0xc4, 0x7f, 0xe1, 0xf7, 0xa0, 0x39, 0xfb, 0x9d, 0x34, 0x69, 0xf5, 0xaa, 0x77, 0x33, 0xe7, - 0x3c, 0xde, 0x39, 0x1f, 0xcf, 0x9c, 0x79, 0x0c, 0x86, 0x74, 0xad, 0x5d, 0xd7, 0x73, 0x94, 0xc3, - 0x4a, 0xee, 0xb4, 0xfb, 0x7c, 0xee, 0x38, 0xf3, 0x05, 0xbe, 0x21, 0xcb, 0x34, 0xb8, 0x7a, 0xa3, - 0xac, 0x25, 0xfa, 0x4a, 0x2e, 0xdd, 0x10, 0xc4, 0xeb, 0x50, 0x3d, 0x5e, 0xba, 0x6a, 0xcd, 0xdf, - 0x41, 0xf3, 0x0c, 0xd7, 0x63, 0x5c, 0xe0, 0x4c, 0x59, 0x8e, 0xcd, 0xfa, 0x50, 0x77, 0x03, 0xcf, - 0x75, 0x7c, 0xec, 0x14, 0x7b, 0xc5, 0xfe, 0xe6, 0x60, 0x73, 0xd7, 0x9d, 0xee, 0x9e, 0xe1, 0x7a, - 0x14, 0x5a, 0x45, 0xec, 0xe6, 0xbf, 0x80, 0xfa, 0xbe, 0x69, 0x7a, 0xe8, 0xfb, 0x8c, 0x41, 0x45, - 0x9a, 0xa6, 0x47, 0xbf, 0x30, 0x04, 0xad, 0x79, 0x0f, 0x6a, 0x1f, 0xd0, 0x9a, 0x5f, 0x2b, 0xf6, - 0x03, 0xd4, 0xae, 0x69, 0x45, 0xfe, 0x96, 0x88, 0x76, 0xfc, 0xcf, 0xd0, 0x38, 0x90, 0x0b, 0x69, - 0xcf, 0xd0, 0x67, 0xcf, 0xc0, 0x98, 0x39, 0xf6, 0x95, 0xe5, 0x2d, 0xd1, 0x24, 0x58, 0x45, 0xa4, - 0x06, 0xd6, 0x83, 0x8d, 0xc0, 0x4e, 0xfd, 0x25, 0xf2, 0x67, 0x4d, 0xfc, 0x29, 0x94, 0xcf, 0x70, - 0xcd, 0xda, 0x50, 0xfe, 0x8c, 0xeb, 0x28, 0x0e, 0xbd, 0xe4, 0x2f, 0xa1, 0x72, 0x86, 0x6b, 0x9f, - 0xfd, 0x1c, 0x2a, 0x9f, 0x71, 0xed, 0x77, 0x8a, 0xbd, 0x72, 0x7f, 0x63, 0x50, 0x8f, 0x92, 0x12, - 0x64, 0xe4, 0xbf, 0x07, 0x23, 0x4a, 0x05, 0x7d, 0xf6, 0x1a, 0x0c, 0x19, 0x6f, 0x22, 0xf8, 0x86, - 0x86, 0x47, 0x08, 0x91, 0x7a, 0x39, 0x87, 0xe6, 0x81, 0xe3, 0x2c, 0x04, 0xfa, 0xae, 0x63, 0xfb, - 0xa8, 0xeb, 0x30, 0x75, 0x9c, 0x05, 0x9d, 0xdf, 0x10, 0xb4, 0xe6, 0xcf, 0xc1, 0xb8, 0x40, 0x35, - 0x92, 0x9e, 0x5c, 0x52, 0xa1, 0x6c, 0xb9, 0xc4, 0xb8, 0x50, 0x7a, 0xcd, 0xdf, 0xc3, 0xd6, 0xc4, - 0x93, 0xb6, 0x2f, 0xa9, 0x01, 0x1f, 0x2d, 0x5f, 0xb1, 0x1d, 0x68, 0xaa, 0xd4, 0x14, 0x47, 0x51, - 0xd3, 0x51, 0x4c, 0x56, 0x22, 0xe7, 0xe3, 0xff, 0x29, 0x42, 0x69, 0xb2, 0xd2, 0x5f, 0x56, 0x2b, - 0xcb, 0x8c, 0xbf, 0xac, 0xd7, 0xec, 0xa7, 0x50, 0xbd, 0x91, 0x8b, 0x00, 0xa9, 0x60, 0x65, 0x11, - 0x6e, 0x32, 0xed, 0x28, 0xf7, 0x8a, 0xfd, 0x6a, 0xdc, 0x0e, 0xf6, 0x0e, 0x8c, 0x84, 0x25, 0x9d, - 0x4a, 0xaf, 0xd8, 0xdf, 0x18, 0x74, 0x77, 0x43, 0x1e, 0xed, 0xc6, 0x3c, 0xda, 0x9d, 0xc4, 0x08, - 0x91, 0x82, 0x75, 0xf3, 0x6e, 0xa5, 0x9a, 0x5d, 0x5f, 0xda, 0x8b, 0x75, 0xa7, 0x4a, 0xb9, 0xa7, - 0x06, 0xdd, 0x13, 0x4f, 0xde, 0x76, 0x6a, 0xbd, 0x62, 0xbf, 0x29, 0xf4, 0x92, 0x77, 0xa1, 0x32, - 0xd1, 0xf1, 0x31, 0xa8, 0x5c, 0x4b, 0xff, 0x3a, 0x8e, 0x59, 0xaf, 0xf9, 0x7b, 0x78, 0x72, 0x82, - 0xf8, 0x11, 0x6f, 0x70, 0x91, 0x25, 0x65, 0xe3, 0x2a, 0x32, 0x46, 0xac, 0x6c, 0xea, 0x5a, 0xc4, - 0x40, 0x91, 0x78, 0xf9, 0x36, 0xc0, 0x09, 0xe2, 0x08, 0xbd, 0x83, 0xb5, 0x42, 0x7d, 0xf4, 0x15, - 0x62, 0xc4, 0x27, 0xbd, 0xd4, 0x3c, 0x39, 0xc1, 0x2f, 0x39, 0xe6, 0x60, 0x8c, 0x5d, 0xb4, 0xcd, - 0xa1, 0x7d, 0xe5, 0xb0, 0x0e, 0xd4, 0xa3, 0x26, 0x47, 0xb1, 0xc5, 0x5b, 0x5d, 0x3c, 0xb9, 0x74, - 0x02, 0x5b, 0x45, 0x24, 0x8c, 0x76, 0xb9, 0x08, 0xcb, 0x8f, 0x46, 0xb8, 0x03, 0x8d, 0x11, 0xa2, - 0x47, 0x7d, 0xde, 0x86, 0xaa, 0x8b, 0xe8, 0xc5, 0x0d, 0x6e, 0xe8, 0x9f, 0x68, 0xa7, 0x08, 0xcd, - 0xfc, 0x7f, 0x25, 0xa8, 0xe8, 0xfd, 0x23, 0x01, 0x3d, 0x03, 0x63, 0xba, 0x56, 0xe8, 0x8f, 0x31, - 0x89, 0x29, 0x35, 0xb0, 0x57, 0xd0, 0xa2, 0x8d, 0xc0, 0x19, 0x5a, 0x37, 0x68, 0x52, 0x6c, 0x15, - 0x91, 0x37, 0x46, 0x97, 0xcf, 0xc6, 0x99, 0x42, 0x93, 0x3a, 0xdf, 0x10, 0xa9, 0x81, 0x6d, 0x42, - 0x69, 0x78, 0x44, 0x6d, 0xad, 0x8a, 0xd2, 0xf0, 0x48, 0xa3, 0x17, 0xd2, 0x57, 0x07, 0x0b, 0x67, - 0xf6, 0x99, 0xba, 0x5a, 0x15, 0xa9, 0x81, 0xf5, 0x61, 0x8b, 0xc8, 0x32, 0x73, 0x16, 0x7f, 0x45, - 0xcf, 0xb7, 0x1c, 0xbb, 0x53, 0xa7, 0x5b, 0x7f, 0xd7, 0xcc, 0xba, 0xd0, 0xf0, 0xd1, 0xbb, 0xb1, - 0x66, 0xe8, 0x77, 0x1a, 0x94, 0x54, 0xb2, 0xd7, 0x67, 0x04, 0x3e, 0x7a, 0xfb, 0x73, 0x9d, 0x95, - 0x41, 0xce, 0xd4, 0xc0, 0xfe, 0x04, 0x2d, 0x4d, 0xbe, 0xc3, 0x24, 0x66, 0xf8, 0x2a, 0x5b, 0xf3, - 0x3f, 0xe0, 0xbf, 0x83, 0xd6, 0x61, 0x38, 0x3b, 0x24, 0xdd, 0x22, 0x5d, 0xa8, 0x59, 0xd6, 0x10, - 0x8d, 0xaa, 0xbc, 0x91, 0x9f, 0x40, 0xe5, 0x2f, 0x6a, 0xe5, 0x3c, 0x74, 0xd9, 0x2c, 0xdb, 0xc4, - 0x15, 0x35, 0xa1, 0x25, 0xc2, 0x4d, 0x7a, 0x05, 0xc3, 0xc2, 0x87, 0x1b, 0xfe, 0xef, 0x22, 0x18, - 0xe3, 0x5b, 0x44, 0x97, 0xd8, 0xb6, 0x0d, 0xd5, 0x40, 0xad, 0x9c, 0x1c, 0x0b, 0xf4, 0x31, 0x22, - 0x34, 0x67, 0x9b, 0x5f, 0xca, 0x37, 0x3f, 0x1a, 0x77, 0xe5, 0x64, 0xdc, 0x31, 0x0e, 0x4d, 0x0f, - 0x4d, 0xc4, 0xe5, 0x78, 0xe6, 0x59, 0xae, 0xa2, 0x6e, 0x36, 0x45, 0xce, 0x96, 0xe3, 0x6a, 0xf5, - 0x51, 0xae, 0xee, 0x41, 0x75, 0x68, 0xbb, 0x81, 0xfa, 0xf6, 0x84, 0xf9, 0x01, 0xd4, 0x2e, 0x03, - 0xa5, 0x7f, 0xc3, 0xa1, 0xe9, 0xd3, 0x81, 0xa3, 0x60, 0x7a, 0x16, 0x0d, 0xe5, 0xa6, 0xc8, 0xd9, - 0xf2, 0x13, 0x2a, 0x29, 0xcf, 0x1f, 0xc1, 0x18, 0x5b, 0x73, 0x5b, 0xaa, 0xc0, 0xc3, 0xf4, 0x98, - 0x62, 0xb6, 0xae, 0xcf, 0xc0, 0xf0, 0x63, 0x08, 0xfd, 0xb8, 0x29, 0x52, 0x03, 0xff, 0x6f, 0x11, - 0xd8, 0xa1, 0x87, 0x52, 0xe1, 0x79, 0xb0, 0x50, 0x96, 0x6f, 0xcd, 0xa9, 0xd0, 0x2f, 0xa0, 0x66, - 0xe9, 0x74, 0xe2, 0x4a, 0x1b, 0x3a, 0x6d, 0x4a, 0x50, 0x44, 0x0e, 0xf6, 0x0a, 0xea, 0x0e, 0x85, - 0xaf, 0x6b, 0xad, 0x31, 0xa0, 0x31, 0x61, 0x46, 0x22, 0x76, 0xfd, 0xc8, 0xba, 0x6f, 0x03, 0x5c, - 0x25, 0xb3, 0x89, 0x2a, 0x5f, 0x11, 0x19, 0x0b, 0x1f, 0x40, 0x2b, 0x49, 0x9b, 0xc6, 0xc3, 0x0b, - 0xa8, 0xf8, 0xd6, 0x3c, 0x8e, 0xb6, 0xa5, 0x23, 0x49, 0x00, 0x82, 0x5c, 0xfc, 0x9f, 0x25, 0x68, - 0xc5, 0x39, 0xda, 0xdf, 0x37, 0xc9, 0xf0, 0xf4, 0xbd, 0x4e, 0xf9, 0xa1, 0xd3, 0xf7, 0x22, 0xc8, - 0xa0, 0x53, 0x79, 0x08, 0x32, 0xb8, 0x57, 0x98, 0xea, 0x57, 0x0b, 0x53, 0xbb, 0x5b, 0x18, 0x9a, - 0x71, 0x9e, 0x23, 0xcd, 0x99, 0xf4, 0x15, 0x4d, 0x93, 0x86, 0x48, 0x0d, 0xfc, 0x29, 0x54, 0x85, - 0xbc, 0x9d, 0xac, 0xf4, 0xa0, 0x52, 0xab, 0x88, 0x66, 0x25, 0xb5, 0xe2, 0xff, 0x80, 0xad, 0x63, - 0x5f, 0x59, 0x4b, 0xa9, 0xf0, 0x04, 0xf1, 0x48, 0x2a, 0xf9, 0xfd, 0x8a, 0x93, 0x0f, 0xb9, 0x7c, - 0xaf, 0x97, 0xdb, 0x5a, 0xfd, 0x48, 0x13, 0x3d, 0xcd, 0x5f, 0xb4, 0x95, 0x17, 0x8b, 0x92, 0x70, - 0xb3, 0xd3, 0x07, 0x48, 0x35, 0x15, 0x6b, 0x42, 0x63, 0x78, 0x31, 0x39, 0x16, 0x17, 0xfb, 0x1f, - 0xdb, 0x05, 0xbd, 0x3b, 0xfe, 0x5b, 0xb4, 0x2b, 0xee, 0x0c, 0xa0, 0x11, 0xdf, 0x4c, 0xf2, 0x1c, - 0x5e, 0x5e, 0x5c, 0x9e, 0x0f, 0x0f, 0xdb, 0x05, 0x06, 0x50, 0xbb, 0xb8, 0x14, 0xe7, 0x1a, 0xa5, - 0x3d, 0x23, 0x31, 0xbc, 0x14, 0xc3, 0xc9, 0xdf, 0xdb, 0xa5, 0xc1, 0xbf, 0x0c, 0x28, 0xef, 0x8f, - 0x86, 0x6c, 0x1b, 0x2a, 0x63, 0xe5, 0xb8, 0x8c, 0xd2, 0x24, 0xbd, 0xd7, 0x4d, 0x97, 0xbc, 0xc0, - 0xf6, 0x60, 0xf3, 0x30, 0xf0, 0x3c, 0xb4, 0x55, 0xac, 0xe4, 0xda, 0x91, 0x30, 0x4a, 0xde, 0xde, - 0x6e, 0x56, 0xfb, 0xf0, 0x02, 0xfb, 0x0d, 0xc0, 0x05, 0xde, 0x7e, 0x33, 0xfc, 0x25, 0x34, 0x0e, - 0xaf, 0xa5, 0x65, 0x4f, 0xac, 0x5c, 0x14, 0x54, 0xd3, 0x50, 0x1e, 0xf2, 0x82, 0x2e, 0x79, 0x24, - 0x04, 0xb3, 0x18, 0x1a, 0x4a, 0xb1, 0x40, 0xe4, 0x05, 0xd6, 0x87, 0xf6, 0xb9, 0xf4, 0x15, 0x7a, - 0x23, 0xcf, 0xba, 0x91, 0x0a, 0xf5, 0xfc, 0xc8, 0xc0, 0x63, 0x49, 0xc7, 0x0b, 0xec, 0x57, 0xb0, - 0x15, 0x21, 0x83, 0xe9, 0xc2, 0x9a, 0x3d, 0x0c, 0x7c, 0x0d, 0xb5, 0x0f, 0xd2, 0xd7, 0xfe, 0x6c, - 0xd8, 0x5d, 0xca, 0x2a, 0x2b, 0xec, 0x28, 0xc6, 0x5a, 0xa4, 0xe1, 0x32, 0x9f, 0x22, 0xc6, 0x27, - 0xea, 0x8e, 0x17, 0xd8, 0x5b, 0x68, 0x66, 0xb4, 0x5c, 0x0e, 0xfb, 0x13, 0x52, 0x6f, 0x79, 0xa1, - 0x47, 0xdf, 0xdd, 0x3c, 0x45, 0x95, 0xb1, 0xb3, 0x46, 0x28, 0xf3, 0x2c, 0xb3, 0x1b, 0x09, 0x3e, - 0x5e, 0x60, 0xef, 0xa0, 0x75, 0x8a, 0x2a, 0xa3, 0x6c, 0x7e, 0x96, 0x9d, 0xd8, 0x69, 0xf5, 0x37, - 0x23, 0x73, 0x4c, 0xc3, 0x02, 0xe3, 0x50, 0x25, 0x5d, 0xc3, 0xc2, 0xdb, 0x19, 0x4b, 0x9c, 0x6e, - 0x72, 0x0a, 0x2f, 0xb0, 0xe7, 0x50, 0x3f, 0x08, 0x96, 0xae, 0x16, 0x46, 0xe9, 0xe1, 0x59, 0x00, - 0x87, 0xaa, 0x96, 0x21, 0xfe, 0xbd, 0xf6, 0xc4, 0x4a, 0x86, 0x88, 0xf1, 0x64, 0xdf, 0x34, 0x3f, - 0x69, 0xd9, 0x87, 0x66, 0xcc, 0x8f, 0x5c, 0x59, 0xef, 0x50, 0xaf, 0x7d, 0x8a, 0x2a, 0xff, 0x08, - 0xa7, 0x87, 0x3f, 0xd1, 0xab, 0x9c, 0x93, 0xba, 0xd5, 0xa4, 0x47, 0x33, 0xfe, 0x78, 0x98, 0x51, - 0xfc, 0x8c, 0xe6, 0x02, 0xfe, 0x03, 0xb4, 0x05, 0x8e, 0xd7, 0xf6, 0x8c, 0x44, 0xc9, 0x4c, 0x33, - 0x90, 0x3d, 0x22, 0x0f, 0xf2, 0xa1, 0x9d, 0xc0, 0xd3, 0xfc, 0xe3, 0x91, 0x3e, 0x46, 0x3f, 0x50, - 0x5c, 0xf7, 0x5e, 0x96, 0x30, 0xde, 0xdc, 0xf0, 0xe6, 0x05, 0xf6, 0x6b, 0x30, 0x92, 0xd1, 0xcc, - 0x08, 0x91, 0x9b, 0xd4, 0xe1, 0xa1, 0x34, 0xba, 0xa8, 0x7c, 0x1b, 0x99, 0x61, 0xc5, 0x88, 0x2d, - 0x77, 0xa6, 0x57, 0xc8, 0xdc, 0x13, 0xd4, 0x6d, 0xed, 0x41, 0xed, 0x14, 0xd5, 0x3d, 0xe6, 0x66, - 0xb8, 0xfd, 0x02, 0x1a, 0x3a, 0x0e, 0xfa, 0xf3, 0x93, 0x69, 0x5b, 0x23, 0x42, 0xf8, 0x14, 0x60, - 0x4b, 0x43, 0xd2, 0xbf, 0x3e, 0x77, 0xa9, 0x9d, 0x78, 0x78, 0x81, 0xfd, 0x12, 0x9a, 0x9f, 0xe4, - 0x62, 0x81, 0xea, 0xc2, 0x51, 0xd6, 0x55, 0xee, 0x46, 0x25, 0x3c, 0x7d, 0x5b, 0x64, 0x7d, 0xd8, - 0x38, 0x0a, 0x96, 0x6e, 0x38, 0xfc, 0xfc, 0x2f, 0xdc, 0x79, 0x6d, 0xd7, 0xc8, 0x69, 0x8d, 0xfa, - 0xf0, 0xdb, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x92, 0x0b, 0x7d, 0xbb, 0x0e, 0x00, 0x00, -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/api/pb/api.proto b/vendor/github.com/OpenBazaar/spvwallet/api/pb/api.proto deleted file mode 100644 index d833bf602f..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/api/pb/api.proto +++ /dev/null @@ -1,206 +0,0 @@ -syntax = "proto3"; - -package pb; - -import "google/protobuf/timestamp.proto"; - -service API { - rpc Stop (Empty) returns (Empty) {} - rpc CurrentAddress (KeySelection) returns (Address) {} - rpc NewAddress (KeySelection) returns (Address) {} - rpc ChainTip (Empty) returns (Height) {} - rpc Balance (Empty) returns (Balances) {} - rpc MasterPrivateKey (Empty) returns (Key) {} - rpc MasterPublicKey (Empty) returns (Key) {} - rpc HasKey (Address) returns (BoolResponse) {} - rpc Params (Empty) returns (NetParams) {} - rpc Transactions (Empty) returns (TransactionList) {} - rpc GetTransaction (Txid) returns (Tx) {} - rpc GetFeePerByte (FeeLevelSelection) returns (FeePerByte) {} - rpc Spend (SpendInfo) returns (Txid) {} - rpc BumpFee (Txid) returns (Txid) {} - rpc Peers (Empty) returns (PeerList) {} - rpc AddWatchedAddress (Address) returns (Empty) {} - rpc GetConfirmations (Txid) returns (Confirmations) {} - rpc SweepAddress (SweepInfo) returns (Txid) {} - rpc ReSyncBlockchain (google.protobuf.Timestamp) returns (Empty) {} - rpc CreateMultisigSignature (CreateMultisigInfo) returns (SignatureList) {} - rpc Multisign (MultisignInfo) returns (RawTx) {} - rpc EstimateFee (EstimateFeeData) returns (Fee) {} - rpc GetKey (Address) returns (Key) {} - rpc ListKeys (Empty) returns (Keys) {} - rpc ListAddresses (Empty) returns (Addresses) {} - rpc WalletNotify (Empty) returns (stream Tx) {} - rpc DumpHeaders (Empty) returns (stream Header) {} -} - -message Empty {} - -enum KeyPurpose { - INTERNAL = 0; - EXTERNAL = 1; -} - -message KeySelection { - KeyPurpose purpose = 1; -} - -message Address { - string addr = 1; -} - -message Height { - uint32 height = 1; -} - -message Balances { - uint64 confirmed = 1; - uint64 unconfirmed = 2; -} - -message Key { - string key = 1; -} - -message Keys { - repeated Key keys = 1; -} - -message Addresses { - repeated Address addresses = 1; -} - -message BoolResponse { - bool bool = 1; -} - -message NetParams { - string name = 1; -} - -message TransactionList { - repeated Tx transactions = 1; -} - -message Tx { - string txid = 1; - int64 value = 2; - int32 height = 3; - google.protobuf.Timestamp timestamp = 4; - bool watchOnly = 5; - bytes raw = 6; -} - -message Txid { - string hash = 1; -} - -enum FeeLevel { - ECONOMIC = 0; - NORMAL = 1; - PRIORITY = 2; -} - -message FeeLevelSelection { - FeeLevel feeLevel = 1; -} - -message FeePerByte { - uint64 fee = 1; -} - -message Fee { - uint64 fee = 1; -} - -message SpendInfo { - string address = 1; - uint64 amount = 2; - FeeLevel feeLevel = 3; -} - -message PeerList { - repeated Peer peers = 1; -} - -message Peer { - string address = 1; - uint64 bytesSent = 2; - uint64 bytesReceived = 3; - bool connected = 4; - int32 ID = 5; - int32 lastBlock = 6; - uint32 protocolVersion = 7; - string services = 8; - string userAgent = 9; - google.protobuf.Timestamp timeConnected = 10; -} - -message Confirmations { - uint32 confirmations = 1; -} - -message Utxo { - string txid = 1; - uint32 index = 2; - uint64 value = 3; -} - -message SweepInfo { - repeated Utxo utxos = 1; - string address = 2; - string key = 3; - bytes redeemScript = 4; - FeeLevel feeLevel = 5; -} - -message Input { - string txid = 1; - uint32 index = 2; -} - -message Output { - bytes scriptPubKey = 1; - uint64 value = 2; -} - -message Signature { - uint32 index = 1; - bytes signature = 2; -} - -message CreateMultisigInfo { - repeated Input inputs = 1; - repeated Output outputs = 2; - string key = 3; - bytes redeemScript = 4; - uint64 feePerByte = 5; -} - -message SignatureList { - repeated Signature sigs = 1; -} - -message MultisignInfo { - repeated Input inputs = 1; - repeated Output outputs = 2; - repeated Signature sig1 = 3; - repeated Signature sig2 = 4; - bytes redeemScript = 5; - uint64 feePerByte = 6; - bool broadcast = 7; -} - -message RawTx { - bytes tx = 1; -} - -message EstimateFeeData { - repeated Input inputs = 1; - repeated Output outputs = 2; - uint64 feePerByte = 3; -} - -message Header { - string entry = 1; -} \ No newline at end of file diff --git a/vendor/github.com/OpenBazaar/spvwallet/api/rpc.go b/vendor/github.com/OpenBazaar/spvwallet/api/rpc.go deleted file mode 100644 index 84dd403215..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/api/rpc.go +++ /dev/null @@ -1,648 +0,0 @@ -package api - -import ( - "encoding/hex" - "errors" - "github.com/OpenBazaar/spvwallet" - "github.com/OpenBazaar/spvwallet/api/pb" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/hdkeychain" - "github.com/golang/protobuf/ptypes" - "github.com/golang/protobuf/ptypes/timestamp" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/reflection" - "net" - "sync" -) - -const Addr = "127.0.0.1:8234" - -type server struct { - w *spvwallet.SPVWallet -} - -func ServeAPI(w *spvwallet.SPVWallet) error { - lis, err := net.Listen("tcp", Addr) - if err != nil { - return err - } - s := grpc.NewServer() - pb.RegisterAPIServer(s, &server{w}) - reflection.Register(s) - if err := s.Serve(lis); err != nil { - return err - } - return nil -} - -func (s *server) Stop(ctx context.Context, in *pb.Empty) (*pb.Empty, error) { - s.w.Close() - return &pb.Empty{}, nil -} - -func (s *server) CurrentAddress(ctx context.Context, in *pb.KeySelection) (*pb.Address, error) { - var purpose wallet.KeyPurpose - if in.Purpose == pb.KeyPurpose_INTERNAL { - purpose = wallet.INTERNAL - } else if in.Purpose == pb.KeyPurpose_EXTERNAL { - purpose = wallet.EXTERNAL - } else { - return nil, errors.New("Unknown key purpose") - } - addr := s.w.CurrentAddress(purpose) - return &pb.Address{addr.String()}, nil -} - -func (s *server) NewAddress(ctx context.Context, in *pb.KeySelection) (*pb.Address, error) { - var purpose wallet.KeyPurpose - if in.Purpose == pb.KeyPurpose_INTERNAL { - purpose = wallet.INTERNAL - } else if in.Purpose == pb.KeyPurpose_EXTERNAL { - purpose = wallet.EXTERNAL - } else { - return nil, errors.New("Unknown key purpose") - } - addr := s.w.NewAddress(purpose) - return &pb.Address{addr.String()}, nil -} - -func (s *server) ChainTip(ctx context.Context, in *pb.Empty) (*pb.Height, error) { - h, _ := s.w.ChainTip() - return &pb.Height{h}, nil -} - -func (s *server) Balance(ctx context.Context, in *pb.Empty) (*pb.Balances, error) { - confirmed, unconfirmed := s.w.Balance() - return &pb.Balances{uint64(confirmed), uint64(unconfirmed)}, nil -} - -func (s *server) MasterPrivateKey(ctx context.Context, in *pb.Empty) (*pb.Key, error) { - return &pb.Key{s.w.MasterPrivateKey().String()}, nil -} - -func (s *server) MasterPublicKey(ctx context.Context, in *pb.Empty) (*pb.Key, error) { - return &pb.Key{s.w.MasterPublicKey().String()}, nil -} - -func (s *server) Params(ctx context.Context, in *pb.Empty) (*pb.NetParams, error) { - return &pb.NetParams{s.w.Params().Name}, nil -} - -func (s *server) HasKey(ctx context.Context, in *pb.Address) (*pb.BoolResponse, error) { - params, err := s.Params(ctx, &pb.Empty{}) - if err != nil { - return nil, err - } - var p chaincfg.Params - switch params.Name { - case chaincfg.TestNet3Params.Name: - p = chaincfg.TestNet3Params - case chaincfg.MainNetParams.Name: - p = chaincfg.MainNetParams - case chaincfg.RegressionNetParams.Name: - p = chaincfg.RegressionNetParams - default: - return nil, errors.New("Unknown network parameters") - } - addr, err := btcutil.DecodeAddress(in.Addr, &p) - if err != nil { - return nil, err - } - return &pb.BoolResponse{s.w.HasKey(addr)}, nil -} - -func (s *server) Transactions(ctx context.Context, in *pb.Empty) (*pb.TransactionList, error) { - txs, err := s.w.Transactions() - if err != nil { - return nil, err - } - var list []*pb.Tx - for _, tx := range txs { - ts, err := ptypes.TimestampProto(tx.Timestamp) - if err != nil { - return nil, err - } - respTx := &pb.Tx{ - Txid: tx.Txid, - Value: tx.Value, - Height: tx.Height, - WatchOnly: tx.WatchOnly, - Timestamp: ts, - Raw: tx.Bytes, - } - list = append(list, respTx) - } - return &pb.TransactionList{list}, nil -} - -func (s *server) GetTransaction(ctx context.Context, in *pb.Txid) (*pb.Tx, error) { - ch, err := chainhash.NewHashFromStr(in.Hash) - if err != nil { - return nil, err - } - tx, err := s.w.GetTransaction(*ch) - if err != nil { - return nil, err - } - ts, err := ptypes.TimestampProto(tx.Timestamp) - if err != nil { - return nil, err - } - respTx := &pb.Tx{ - Txid: tx.Txid, - Value: tx.Value, - Height: tx.Height, - WatchOnly: tx.WatchOnly, - Timestamp: ts, - Raw: tx.Bytes, - } - return respTx, nil -} - -func (s *server) GetFeePerByte(ctx context.Context, in *pb.FeeLevelSelection) (*pb.FeePerByte, error) { - var feeLevel wallet.FeeLevel - switch in.FeeLevel { - case pb.FeeLevel_ECONOMIC: - feeLevel = wallet.ECONOMIC - case pb.FeeLevel_NORMAL: - feeLevel = wallet.NORMAL - case pb.FeeLevel_PRIORITY: - feeLevel = wallet.PRIOIRTY - default: - return nil, errors.New("Unknown fee level") - } - return &pb.FeePerByte{s.w.GetFeePerByte(feeLevel)}, nil -} - -func (s *server) Spend(ctx context.Context, in *pb.SpendInfo) (*pb.Txid, error) { - params, err := s.Params(ctx, &pb.Empty{}) - if err != nil { - return nil, err - } - var p chaincfg.Params - switch params.Name { - case chaincfg.TestNet3Params.Name: - p = chaincfg.TestNet3Params - case chaincfg.MainNetParams.Name: - p = chaincfg.MainNetParams - case chaincfg.RegressionNetParams.Name: - p = chaincfg.RegressionNetParams - default: - return nil, errors.New("Unknown network parameters") - } - var feeLevel wallet.FeeLevel - switch in.FeeLevel { - case pb.FeeLevel_ECONOMIC: - feeLevel = wallet.ECONOMIC - case pb.FeeLevel_NORMAL: - feeLevel = wallet.NORMAL - case pb.FeeLevel_PRIORITY: - feeLevel = wallet.PRIOIRTY - default: - return nil, errors.New("Unknown fee level") - } - addr, err := btcutil.DecodeAddress(in.Address, &p) - if err != nil { - return nil, err - } - txid, err := s.w.Spend(int64(in.Amount), addr, feeLevel, "", false) - if err != nil { - return nil, err - } - return &pb.Txid{txid.String()}, nil -} - -func (s *server) BumpFee(ctx context.Context, in *pb.Txid) (*pb.Txid, error) { - ch, err := chainhash.NewHashFromStr(in.Hash) - if err != nil { - return nil, err - } - txid, err := s.w.BumpFee(*ch) - if err != nil { - return nil, err - } - return &pb.Txid{txid.String()}, nil -} - -func (s *server) Peers(ctx context.Context, in *pb.Empty) (*pb.PeerList, error) { - var peers []*pb.Peer - for _, peer := range s.w.ConnectedPeers() { - ts, err := ptypes.TimestampProto(peer.TimeConnected()) - if err != nil { - return nil, err - } - p := &pb.Peer{ - Address: peer.Addr(), - BytesSent: peer.BytesSent(), - BytesReceived: peer.BytesReceived(), - Connected: peer.Connected(), - ID: peer.ID(), - LastBlock: peer.LastBlock(), - ProtocolVersion: peer.ProtocolVersion(), - Services: peer.Services().String(), - UserAgent: peer.UserAgent(), - TimeConnected: ts, - } - peers = append(peers, p) - } - return &pb.PeerList{peers}, nil -} - -func (s *server) AddWatchedAddress(ctx context.Context, in *pb.Address) (*pb.Empty, error) { - params, err := s.Params(ctx, &pb.Empty{}) - if err != nil { - return nil, err - } - var p chaincfg.Params - switch params.Name { - case chaincfg.TestNet3Params.Name: - p = chaincfg.TestNet3Params - case chaincfg.MainNetParams.Name: - p = chaincfg.MainNetParams - case chaincfg.RegressionNetParams.Name: - p = chaincfg.RegressionNetParams - default: - return nil, errors.New("Unknown network parameters") - } - addr, err := btcutil.DecodeAddress(in.Addr, &p) - if err != nil { - return nil, err - } - return nil, s.w.AddWatchedAddress(addr) -} - -func (s *server) GetConfirmations(ctx context.Context, in *pb.Txid) (*pb.Confirmations, error) { - ch, err := chainhash.NewHashFromStr(in.Hash) - if err != nil { - return nil, err - } - confirms, _, err := s.w.GetConfirmations(*ch) - if err != nil { - return nil, err - } - return &pb.Confirmations{confirms}, nil -} - -func (s *server) SweepAddress(ctx context.Context, in *pb.SweepInfo) (*pb.Txid, error) { - var ins []wallet.TransactionInput - for _, u := range in.Utxos { - h, err := chainhash.NewHashFromStr(u.Txid) - if err != nil { - return nil, err - } - in := wallet.TransactionInput{ - OutpointHash: h.CloneBytes(), - OutpointIndex: u.Index, - Value: int64(u.Value), - } - ins = append(ins, in) - } - params, err := s.Params(ctx, &pb.Empty{}) - if err != nil { - return nil, err - } - var p chaincfg.Params - switch params.Name { - case chaincfg.TestNet3Params.Name: - p = chaincfg.TestNet3Params - case chaincfg.MainNetParams.Name: - p = chaincfg.MainNetParams - case chaincfg.RegressionNetParams.Name: - p = chaincfg.RegressionNetParams - default: - return nil, errors.New("Unknown network parameters") - } - var addr *btcutil.Address - if in.Address != "" { - a, err := btcutil.DecodeAddress(in.Address, &p) - if err != nil { - return nil, err - } - addr = &a - } else { - addr = nil - } - var key *hdkeychain.ExtendedKey - wif, err := btcutil.DecodeWIF(in.Key) - if err == nil { - key = hdkeychain.NewExtendedKey( - p.HDPrivateKeyID[:], - wif.PrivKey.Serialize(), - make([]byte, 32), - make([]byte, 4), - 0, - 0, - true) - } else { - keyBytes, err := hex.DecodeString(in.Key) - if err == nil { - key = hdkeychain.NewExtendedKey( - p.HDPrivateKeyID[:], - keyBytes, - make([]byte, 32), - make([]byte, 4), - 0, - 0, - true) - } else { - key, err = hdkeychain.NewKeyFromString(in.Key) - if err != nil { - return nil, err - } - } - } - var rs *[]byte - if len(in.RedeemScript) > 0 { - rs = &in.RedeemScript - } - var feeLevel wallet.FeeLevel - switch in.FeeLevel { - case pb.FeeLevel_ECONOMIC: - feeLevel = wallet.ECONOMIC - case pb.FeeLevel_NORMAL: - feeLevel = wallet.NORMAL - case pb.FeeLevel_PRIORITY: - feeLevel = wallet.PRIOIRTY - default: - return nil, errors.New("Unknown fee level") - } - newTxid, err := s.w.SweepAddress(ins, addr, key, rs, feeLevel) - if err != nil { - return nil, err - } - return &pb.Txid{newTxid.String()}, nil -} - -func (s *server) ReSyncBlockchain(ctx context.Context, in *timestamp.Timestamp) (*pb.Empty, error) { - t, err := ptypes.Timestamp(in) - if err != nil { - return nil, err - } - s.w.ReSyncBlockchain(t) - return &pb.Empty{}, nil -} - -func (s *server) CreateMultisigSignature(ctx context.Context, in *pb.CreateMultisigInfo) (*pb.SignatureList, error) { - var ins []wallet.TransactionInput - for _, input := range in.Inputs { - h, err := hex.DecodeString(input.Txid) - if err != nil { - return nil, err - } - i := wallet.TransactionInput{ - OutpointHash: h, - OutpointIndex: input.Index, - } - ins = append(ins, i) - } - var outs []wallet.TransactionOutput - for _, output := range in.Outputs { - addr, err := s.w.ScriptToAddress(output.ScriptPubKey) - if err != nil { - return nil, err - } - o := wallet.TransactionOutput{ - Address: addr, - Value: int64(output.Value), - } - outs = append(outs, o) - } - params, err := s.Params(ctx, &pb.Empty{}) - if err != nil { - return nil, err - } - var p chaincfg.Params - switch params.Name { - case chaincfg.TestNet3Params.Name: - p = chaincfg.TestNet3Params - case chaincfg.MainNetParams.Name: - p = chaincfg.MainNetParams - case chaincfg.RegressionNetParams.Name: - p = chaincfg.RegressionNetParams - default: - return nil, errors.New("Unknown network parameters") - } - var key *hdkeychain.ExtendedKey - wif, err := btcutil.DecodeWIF(in.Key) - if err == nil { - key = hdkeychain.NewExtendedKey( - p.HDPrivateKeyID[:], - wif.PrivKey.Serialize(), - make([]byte, 32), - make([]byte, 4), - 0, - 0, - true) - } else { - keyBytes, err := hex.DecodeString(in.Key) - if err == nil { - key = hdkeychain.NewExtendedKey( - p.HDPrivateKeyID[:], - keyBytes, - make([]byte, 32), - make([]byte, 4), - 0, - 0, - true) - } else { - key, err = hdkeychain.NewKeyFromString(in.Key) - if err != nil { - return nil, err - } - } - } - sigs, err := s.w.CreateMultisigSignature(ins, outs, key, in.RedeemScript, in.FeePerByte) - if err != nil { - return nil, err - } - var retSigs []*pb.Signature - for _, s := range sigs { - sig := &pb.Signature{ - Index: s.InputIndex, - Signature: s.Signature, - } - retSigs = append(retSigs, sig) - } - return &pb.SignatureList{retSigs}, nil -} - -func (s *server) Multisign(ctx context.Context, in *pb.MultisignInfo) (*pb.RawTx, error) { - var ins []wallet.TransactionInput - for _, input := range in.Inputs { - h, err := hex.DecodeString(input.Txid) - if err != nil { - return nil, err - } - i := wallet.TransactionInput{ - OutpointHash: h, - OutpointIndex: input.Index, - } - ins = append(ins, i) - } - var outs []wallet.TransactionOutput - for _, output := range in.Outputs { - addr, err := s.w.ScriptToAddress(output.ScriptPubKey) - if err != nil { - return nil, err - } - o := wallet.TransactionOutput{ - Address: addr, - Value: int64(output.Value), - } - outs = append(outs, o) - } - var sig1 []wallet.Signature - for _, s := range in.Sig1 { - sig := wallet.Signature{ - InputIndex: s.Index, - Signature: s.Signature, - } - sig1 = append(sig1, sig) - } - var sig2 []wallet.Signature - for _, s := range in.Sig2 { - sig := wallet.Signature{ - InputIndex: s.Index, - Signature: s.Signature, - } - sig2 = append(sig2, sig) - } - tx, err := s.w.Multisign(ins, outs, sig1, sig2, in.RedeemScript, in.FeePerByte, in.Broadcast) - if err != nil { - return nil, err - } - return &pb.RawTx{tx}, nil -} - -func (s *server) EstimateFee(ctx context.Context, in *pb.EstimateFeeData) (*pb.Fee, error) { - var ins []wallet.TransactionInput - for _, input := range in.Inputs { - h, err := hex.DecodeString(input.Txid) - if err != nil { - return nil, err - } - i := wallet.TransactionInput{ - OutpointHash: h, - OutpointIndex: input.Index, - } - ins = append(ins, i) - } - var outs []wallet.TransactionOutput - for _, output := range in.Outputs { - addr, err := s.w.ScriptToAddress(output.ScriptPubKey) - if err != nil { - return nil, err - } - o := wallet.TransactionOutput{ - Address: addr, - Value: int64(output.Value), - } - outs = append(outs, o) - } - fee := s.w.EstimateFee(ins, outs, in.FeePerByte) - return &pb.Fee{fee}, nil -} - -func (s *server) WalletNotify(in *pb.Empty, stream pb.API_WalletNotifyServer) error { - cb := func(tx wallet.TransactionCallback) { - ts, err := ptypes.TimestampProto(tx.Timestamp) - if err != nil { - return - } - resp := &pb.Tx{ - Txid: tx.Txid, - Value: tx.Value, - Height: tx.Height, - Timestamp: ts, - WatchOnly: tx.WatchOnly, - } - if err := stream.Send(resp); err != nil { - return - } - } - s.w.AddTransactionListener(cb) - // Keep the connection open to continue streaming - var wg sync.WaitGroup - wg.Add(1) - wg.Wait() - return nil -} - -type HeaderWriter struct { - stream pb.API_DumpHeadersServer -} - -func (h *HeaderWriter) Write(p []byte) (n int, err error) { - hdr := &pb.Header{string(p)} - if err := h.stream.Send(hdr); err != nil { - return 0, err - } - return 0, nil -} - -func (s *server) DumpHeaders(in *pb.Empty, stream pb.API_DumpHeadersServer) error { - writer := HeaderWriter{stream} - s.w.DumpHeaders(&writer) - return nil -} - -func (s *server) GetKey(ctx context.Context, in *pb.Address) (*pb.Key, error) { - params, err := s.Params(ctx, &pb.Empty{}) - if err != nil { - return nil, err - } - var p chaincfg.Params - switch params.Name { - case chaincfg.TestNet3Params.Name: - p = chaincfg.TestNet3Params - case chaincfg.MainNetParams.Name: - p = chaincfg.MainNetParams - case chaincfg.RegressionNetParams.Name: - p = chaincfg.RegressionNetParams - default: - return nil, errors.New("Unknown network parameters") - } - addr, err := btcutil.DecodeAddress(in.Addr, &p) - if err != nil { - return nil, err - } - key, err := s.w.GetKey(addr) - if err != nil { - return nil, err - } - wif, err := btcutil.NewWIF(key, &p, true) - if err != nil { - return nil, err - } - return &pb.Key{wif.String()}, nil -} - -func (s *server) ListAddresses(ctx context.Context, in *pb.Empty) (*pb.Addresses, error) { - addrs := s.w.ListAddresses() - var list []*pb.Address - for _, addr := range addrs { - ret := new(pb.Address) - ret.Addr = addr.String() - list = append(list, ret) - } - return &pb.Addresses{list}, nil -} - -func (s *server) ListKeys(ctx context.Context, in *pb.Empty) (*pb.Keys, error) { - keys := s.w.ListKeys() - var list []*pb.Key - for _, key := range keys { - ret := new(pb.Key) - wif, err := btcutil.NewWIF(&key, s.w.Params(), true) - if err != nil { - return nil, err - } - ret.Key = wif.String() - list = append(list, ret) - } - return &pb.Keys{list}, nil -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/blockchain.go b/vendor/github.com/OpenBazaar/spvwallet/blockchain.go index 2ea11866a0..3bdad91b9c 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/blockchain.go +++ b/vendor/github.com/OpenBazaar/spvwallet/blockchain.go @@ -198,7 +198,7 @@ func (b *Blockchain) calcRequiredWork(header wire.BlockHeader, height int32, pre // We are on a difficulty adjustment period so we need to correctly calculate the new difficulty. epoch, err := b.GetEpoch() if err != nil { - log.Error(err) + log.Error(err.Error()) return 0, err } return calcDiffAdjust(*epoch, prevHeader.header, b.params), nil @@ -296,7 +296,7 @@ func (b *Blockchain) GetBlockLocator() blockchain.BlockLocator { return blockchain.BlockLocator(ret) } -// Returns last header before reorg point +// GetCommonAncestor returns last header before reorg point func (b *Blockchain) GetCommonAncestor(bestHeader, prevBestHeader StoredHeader) (*StoredHeader, error) { var err error rollback := func(parent StoredHeader, n int) (StoredHeader, error) { diff --git a/vendor/github.com/OpenBazaar/spvwallet/blockchain_test.go b/vendor/github.com/OpenBazaar/spvwallet/blockchain_test.go deleted file mode 100644 index 10ce5e9325..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/blockchain_test.go +++ /dev/null @@ -1,682 +0,0 @@ -package spvwallet - -import ( - "bytes" - "crypto/rand" - "encoding/hex" - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "math/big" - "os" - "testing" - "time" -) - -// New chain starting from regtest genesis -var chain = []string{ - "0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910fc3ed4523bf94fc1fa184bee85af604c9ebeea6b39b498f62703fd3f03e7475534658d158ffff7f2001000000", - "000000207c3d2d417ff34a46f4f11a972d8e32bc98b300112dd4d9a1dae9ff87468eae136b90f1757adfab2056d693160b417b8f87a65c2c0735a47e63768f26473905506059d158ffff7f2003000000", - "000000200c6ea2eaf928b2d5d080c2f36dac1185865db1289c7339834b98e8034e4274073ed977491ebe6f9c0e01f5796e36ed66bf4e410bbbc2635129d6e0ecfc1897908459d158ffff7f2001000000", - "000000202e1569563ff6463f65bb7669b35fb9dd95ba0b251e30251b9877d9578b8700680337ff38b71d9667190c99e8fae337ba8c9c40cbd2c4678ba71d81cf6d3a1aa2ac59d158ffff7f2001000000", - "000000204525edcccf706e3769a54c8772934f291d6810315a26c177862c66feb9f3896e090c84be811cfdfed6da043cb337fccecff95fc73810ca82adb3d032b5d49140c759d158ffff7f2000000000", - "00000020ada1a9efa81df10d7b430e2fd5f3b085180c91b0e9b0f6e9af2d9b733544015eab404ef503e538909a04a419499133af9bcee47fcfc84baaab5344f77ebd455dec59d158ffff7f2000000000", - "000000204fdcb9ca4cc47ae7485bfc2f8adcbd515b1ee0cb724d343c91f02b6ec5a0ba507dddd2639fc1bd522489a2c2f2b681a60c6c7939490458dc1c008f3217cb47d6035ad158ffff7f2001000000", - "0000002019dbc9a6cec93be207053e4dfbc63af20c3cedba68f890c5a90f27aeb2ecc73386692b64e16ea4b87fc877cb3762394d12b597a0ca8d5efb2ea2c6e163f9e4c8225ad158ffff7f2000000000", - "000000203afc4a1c100fe3e21fa24ef92857613bb00890564e3529623780bc8d4a86d15cfd35aef39950dc53c348b5013f4ee3d94afc16745d6b3c8a9e6acfb8a2641c6f3e5ad158ffff7f2000000000", - "000000200e1b58feab56f9fe5ed7484a8c7bfecdb270da528db7a805d18208891bde3726a5ccb0a073d0cc7402ac89f4bb4b64c39bc365bfee7ccd7ea3a24996ee684c775a5ad158ffff7f2000000000", -} - -// Forks `chain` starting at block 6 -var fork = []string{ - "00000020ada1a9efa81df10d7b430e2fd5f3b085180c91b0e9b0f6e9af2d9b733544015eead915a2f4521c58cb1c42a469aefede5a9d1dddfe8ccc408f8135fc2560f25a096dd158ffff7f20e9aace03", - "0000002097e3603b40c0c7add951e3a7dba5088836d17e1123ef7cffdd60174e3dce0024cffe0c74189d854a778a3e57fee8510103e83d95b221b8bfe1159806b3bde27e236dd158ffff7f20794caff6", - "0000002085a3bf0898ed1cad9e868120c8e044673425a13ecc7ab2daec204ca9190e643ca32434566054789e79214a7cb7c1b6e37084cbfce7564d4aabb10ef6fc1d655c3d6dd158ffff7f20c2e4cb6f", - "000000209aa626e76fbcfc08bc1626a0a9bc7b82d8521de22a477e7b377d8f83be8d446a05aae352ffe9f09af1d79d24992dbee2785b3fe4eb4a0e21e7a3b26a90115dac536dd158ffff7f201d2f76eb", - "000000208d6d636589b4056d1486fbcc0b46adefbb770b7e6a8d668fe65c3f58f5c2c70934008f98664ffec01f583870f843b617c869ec30f1b37723b3d0f0d4a3ba6a88686dd158ffff7f209d12ee06", - "0000002067cf05afedc2b5956c10845006358fe480893e1199a0c0e2b70d5ecf2787af760385ca3d191d1800cd7b6a56d8b44853109f3e5983a94c7e10818541278ec6027b6dd158ffff7f2004e2c75c", - "00000020b2227c6c858a36af167d9667dcf4f58df604ab7962a660d69d233a63e7269f06ecb669fff090b7f2f6952d52c96ca0c8abe1e266d9740f8548eeb10eea9e3536906dd158ffff7f20c0ac3d1e", -} - -func createBlockChain(bc *Blockchain) error { - best, err := bc.db.GetBestHeader() - if err != nil { - return err - } - x := best.height - last := best.header - for i := 0; i < 2015; i++ { - x++ - hdr := wire.BlockHeader{} - hdr.PrevBlock = last.BlockHash() - hdr.Nonce = 0 - hdr.Timestamp = time.Now().Add(time.Minute * time.Duration(i)) - mr := make([]byte, 32) - rand.Read(mr) - ch, err := chainhash.NewHash(mr) - if err != nil { - return err - } - hdr.MerkleRoot = *ch - hdr.Bits = best.header.Bits - hdr.Version = 3 - sh := StoredHeader{ - header: hdr, - height: x, - totalWork: big.NewInt(0), - } - bc.db.(*HeaderDB).put(sh, true) - last = hdr - } - return nil -} - -var MockCreationTime time.Time - -func TestNewBlockchain(t *testing.T) { - bc, err := NewBlockchain("", MockCreationTime, &chaincfg.MainNetParams) - if err != nil { - t.Error(err) - } - best, err := bc.db.GetBestHeader() - if err != nil { - t.Error(err) - } - bestHash := best.header.BlockHash() - checkHash := mainnetCheckpoints[0].Header.BlockHash() - if !bestHash.IsEqual(&checkHash) { - t.Error("Blockchain failed to initialize with correct mainnet checkpoint") - } - if best.height != mainnetCheckpoints[0].Height { - t.Error("Blockchain failed to initialized with correct mainnet checkpoint height") - } - if best.totalWork.Uint64() != 0 { - t.Error("Blockchain failed to initialized with correct mainnet total work") - } - os.RemoveAll("headers.bin") - bc, err = NewBlockchain("", MockCreationTime, &chaincfg.TestNet3Params) - if err != nil { - t.Error(err) - } - best, err = bc.db.GetBestHeader() - if err != nil { - t.Error(err) - } - bestHash = best.header.BlockHash() - checkHash = testnet3Checkpoints[0].Header.BlockHash() - if !bestHash.IsEqual(&checkHash) { - t.Error("Blockchain failed to initialize with correct testnet checkpoint") - } - if best.height != testnet3Checkpoints[0].Height { - t.Error("Blockchain failed to initialized with correct testnet checkpoint height") - } - if best.totalWork.Uint64() != 0 { - t.Error("Blockchain failed to initialized with correct testnet total work") - } - os.RemoveAll("headers.bin") - bc, err = NewBlockchain("", MockCreationTime, &chaincfg.RegressionNetParams) - if err != nil { - t.Error(err) - } - best, err = bc.db.GetBestHeader() - if err != nil { - t.Error(err) - } - bestHash = best.header.BlockHash() - checkHash = regtestCheckpoint.Header.BlockHash() - if !bestHash.IsEqual(&checkHash) { - t.Error("Blockchain failed to initialize with correct regtest checkpoint") - } - if best.height != regtestCheckpoint.Height { - t.Error("Blockchain failed to initialized with correct regtest checkpoint height") - } - if best.totalWork.Uint64() != 0 { - t.Error("Blockchain failed to initialized with correct regtest total work") - } - os.RemoveAll("headers.bin") -} - -func TestBlockchain_CommitHeader(t *testing.T) { - bc, err := NewBlockchain("", MockCreationTime, &chaincfg.RegressionNetParams) - if err != nil { - t.Error(err) - } - var headers = []wire.BlockHeader{regtestCheckpoint.Header} - for i, c := range chain { - b, err := hex.DecodeString(c) - if err != nil { - t.Error(err) - } - var hdr wire.BlockHeader - hdr.Deserialize(bytes.NewReader(b)) - newTip, reorg, height, err := bc.CommitHeader(hdr) - if err != nil { - t.Error() - } - if !newTip { - t.Error("Failed to set new tip when inserting header") - } - if reorg != nil { - t.Error("Incorrectly set reorg when inserting header") - } - if height != uint32(i+1) { - t.Error("Returned incorrect height when inserting header") - } - headers = append(headers, hdr) - } - best, err := bc.db.GetBestHeader() - if err != nil { - t.Error(err) - } - for i := len(headers) - 1; i >= 0; i-- { - putHash := headers[i].BlockHash() - retHash := best.header.BlockHash() - if !putHash.IsEqual(&retHash) { - t.Error("Header put failed") - } - best, err = bc.db.GetPreviousHeader(best.header) - } - os.RemoveAll("headers.bin") -} - -func Test_Reorg(t *testing.T) { - bc, err := NewBlockchain("", MockCreationTime, &chaincfg.RegressionNetParams) - if err != nil { - t.Error(err) - } - var headers = []wire.BlockHeader{regtestCheckpoint.Header} - for i, c := range chain { - b, err := hex.DecodeString(c) - if err != nil { - t.Error(err) - } - var hdr wire.BlockHeader - hdr.Deserialize(bytes.NewReader(b)) - newTip, reorg, height, err := bc.CommitHeader(hdr) - if err != nil { - t.Error() - } - if !newTip { - t.Error("Failed to set new tip when inserting header") - } - if reorg != nil { - t.Error("Incorrectly set reorg when inserting header") - } - if height != uint32(i+1) { - t.Error("Returned incorrect height when inserting header") - } - if i < 5 { - headers = append(headers, hdr) - } - } - for i, c := range fork { - b, err := hex.DecodeString(c) - if err != nil { - t.Error(err) - } - var hdr wire.BlockHeader - hdr.Deserialize(bytes.NewReader(b)) - newTip, reorg, height, err := bc.CommitHeader(hdr) - if err != nil { - t.Error() - } - if newTip && i+6 < 11 { - t.Error("Incorrectly set new tip when inserting header") - } - if !newTip && i+6 >= 11 { - t.Error("Failed to set new tip when inserting header") - } - if reorg != nil && i+6 != 11 { - t.Error("Incorrectly set reorg when inserting header") - } - if reorg == nil && i+6 == 11 { - t.Error("Failed to return reorg when inserting a header that caused a reorg") - } - if height != uint32(i+6) { - t.Error("Returned incorrect height when inserting header") - } - headers = append(headers, hdr) - } - best, err := bc.db.GetBestHeader() - if err != nil { - t.Error(err) - } - for i := len(headers) - 1; i >= 0; i-- { - putHash := headers[i].BlockHash() - retHash := best.header.BlockHash() - if !putHash.IsEqual(&retHash) { - t.Error("Header put failed") - } - best, err = bc.db.GetPreviousHeader(best.header) - } - os.RemoveAll("headers.bin") -} - -func TestBlockchain_GetCommonAncestor(t *testing.T) { - bc, err := NewBlockchain("", MockCreationTime, &chaincfg.RegressionNetParams) - if err != nil { - t.Error(err) - } - var hdr wire.BlockHeader - for _, c := range chain { - b, err := hex.DecodeString(c) - if err != nil { - t.Error(err) - } - hdr.Deserialize(bytes.NewReader(b)) - bc.CommitHeader(hdr) - } - prevBest := StoredHeader{header: hdr, height: 10} - for i := 0; i < len(fork)-1; i++ { - b, err := hex.DecodeString(fork[i]) - if err != nil { - t.Error(err) - } - hdr.Deserialize(bytes.NewReader(b)) - bc.CommitHeader(hdr) - } - currentBest := StoredHeader{header: hdr, height: 11} - - last, err := bc.GetCommonAncestor(currentBest, prevBest) - if err != nil { - t.Error(err) - } - if last.height != 5 { - t.Error("Incorrect reorg height") - } - os.RemoveAll("headers.bin") -} - -func TestBlockchain_CheckHeader(t *testing.T) { - params := &chaincfg.RegressionNetParams - bc, err := NewBlockchain("", MockCreationTime, params) - if err != nil { - t.Error(err) - } - - // Test valid header - header0, err := hex.DecodeString(chain[0]) - if err != nil { - t.Error(err) - } - var buf bytes.Buffer - buf.Write(header0) - hdr0 := wire.BlockHeader{} - hdr0.Deserialize(&buf) - - header1, err := hex.DecodeString(chain[1]) - if err != nil { - t.Error(err) - } - buf.Write(header1) - hdr1 := wire.BlockHeader{} - hdr1.Deserialize(&buf) - sh := StoredHeader{ - header: hdr0, - height: 0, - totalWork: big.NewInt(0), - } - if !bc.CheckHeader(hdr1, sh) { - t.Error("Check header incorrectly returned false") - } - - // Test header doesn't link - header2, err := hex.DecodeString(chain[2]) - if err != nil { - t.Error(err) - } - buf.Write(header2) - hdr2 := wire.BlockHeader{} - hdr2.Deserialize(&buf) - if bc.CheckHeader(hdr2, sh) { - t.Error("Check header missed headers that don't link") - } - // Test invalid difficulty - params.ReduceMinDifficulty = false - invalidDiffHdr := hdr1 - invalidDiffHdr.Bits = 0 - if bc.CheckHeader(invalidDiffHdr, sh) { - t.Error("Check header did not detect invalid PoW") - } - - // Test invalid proof of work - params.ReduceMinDifficulty = true - invalidPoWHdr := hdr1 - invalidPoWHdr.Nonce = 0 - if bc.CheckHeader(invalidPoWHdr, sh) { - t.Error("Check header did not detect invalid PoW") - } - - os.RemoveAll("headers.bin") -} - -func TestBlockchain_GetNPrevBlockHashes(t *testing.T) { - bc, err := NewBlockchain("", MockCreationTime, &chaincfg.RegressionNetParams) - if err != nil { - t.Error(err) - } - var headers = []wire.BlockHeader{regtestCheckpoint.Header} - for i, c := range chain { - b, err := hex.DecodeString(c) - if err != nil { - t.Error(err) - } - var hdr wire.BlockHeader - hdr.Deserialize(bytes.NewReader(b)) - newTip, reorg, height, err := bc.CommitHeader(hdr) - if err != nil { - t.Error() - } - if !newTip { - t.Error("Failed to set new tip when inserting header") - } - if reorg != nil { - t.Error("Incorrectly set reorg when inserting header") - } - if height != uint32(i+1) { - t.Error("Returned incorrect height when inserting header") - } - headers = append(headers, hdr) - } - - nHashes := bc.GetNPrevBlockHashes(5) - for i := 0; i < 5; i++ { - h := headers[(len(headers)-1)-i].BlockHash() - if !nHashes[i].IsEqual(&h) { - t.Error("GetNPrevBlockHashes returned invalid hashes") - } - } - os.RemoveAll("headers.bin") -} - -func TestBlockchain_checkProofOfWork(t *testing.T) { - // Test valid - header0, err := hex.DecodeString(chain[0]) - if err != nil { - t.Error(err) - } - var buf bytes.Buffer - buf.Write(header0) - hdr0 := wire.BlockHeader{} - hdr0.Deserialize(&buf) - if !checkProofOfWork(hdr0, &chaincfg.RegressionNetParams) { - t.Error("checkProofOfWork failed") - } - - // Test negative target - neg := hdr0 - neg.Bits = 1000000000 - if checkProofOfWork(neg, &chaincfg.RegressionNetParams) { - t.Error("checkProofOfWork failed to negative target") - } - - // Test too high diff - params := chaincfg.RegressionNetParams - params.PowLimit = big.NewInt(0) - if checkProofOfWork(hdr0, ¶ms) { - t.Error("checkProofOfWork failed to detect above max PoW") - } - - // Test to low work - badHeader := "1" + chain[0][1:] - header0, err = hex.DecodeString(badHeader) - if err != nil { - t.Error(err) - } - badHdr := wire.BlockHeader{} - buf.Write(header0) - badHdr.Deserialize(&buf) - if checkProofOfWork(badHdr, &chaincfg.RegressionNetParams) { - t.Error("checkProofOfWork failed to detect insuffient work") - } -} - -func TestBlockchain_calcDiffAdjust(t *testing.T) { - - // Test calculation of next difficulty target with no constraints applying - start := wire.BlockHeader{} - end := wire.BlockHeader{} - start.Timestamp = time.Unix(1261130161, 0) // Block #30240 - end.Timestamp = time.Unix(1262152739, 0) // Block #32255 - end.Bits = 0x1d00ffff - if calcDiffAdjust(start, end, &chaincfg.RegressionNetParams) != 0x1d00d86a { - t.Error("callDiffAdjust returned incorrect difficulty") - } - - // Test the constraint on the upper bound for next work - start = wire.BlockHeader{} - end = wire.BlockHeader{} - start.Timestamp = time.Unix(1279008237, 0) // Block #0 - end.Timestamp = time.Unix(1279297671, 0) // Block #2015 - end.Bits = 0x1c05a3f4 - if calcDiffAdjust(start, end, &chaincfg.RegressionNetParams) != 0x1c0168fd { - t.Error("callDiffAdjust returned incorrect difficulty") - } - - // Test the constraint on the lower bound for actual time taken - start = wire.BlockHeader{} - end = wire.BlockHeader{} - start.Timestamp = time.Unix(1279008237, 0) // Block #66528 - end.Timestamp = time.Unix(1279297671, 0) // Block #68543 - end.Bits = 0x1c05a3f4 - if calcDiffAdjust(start, end, &chaincfg.RegressionNetParams) != 0x1c0168fd { - t.Error("callDiffAdjust returned incorrect difficulty") - } - - // Test the constraint on the upper bound for actual time taken - start = wire.BlockHeader{} - end = wire.BlockHeader{} - start.Timestamp = time.Unix(1263163443, 0) // NOTE: Not an actual block time - end.Timestamp = time.Unix(1269211443, 0) // Block #46367 - end.Bits = 0x1c387f6f - if calcDiffAdjust(start, end, &chaincfg.RegressionNetParams) != 0x1d00e1fd { - t.Error("callDiffAdjust returned incorrect difficulty") - } -} - -func TestBlockchain_GetBlockLocator(t *testing.T) { - bc, err := NewBlockchain("", MockCreationTime, &chaincfg.RegressionNetParams) - if err != nil { - t.Error(err) - } - var headers = []wire.BlockHeader{regtestCheckpoint.Header} - for i, c := range chain { - b, err := hex.DecodeString(c) - if err != nil { - t.Error(err) - } - var hdr wire.BlockHeader - hdr.Deserialize(bytes.NewReader(b)) - bc.CommitHeader(hdr) - if i < 5 { - headers = append(headers, hdr) - } - } - - for _, c := range fork { - b, err := hex.DecodeString(c) - if err != nil { - t.Error(err) - } - var hdr wire.BlockHeader - hdr.Deserialize(bytes.NewReader(b)) - bc.CommitHeader(hdr) - headers = append(headers, hdr) - } - - nHashes := bc.GetBlockLocator() - for i := 0; i < 10; i++ { - h := headers[(len(headers)-1)-i].BlockHash() - if !nHashes[i].IsEqual(&h) { - t.Error("GetBlockLocatorHashes returned invalid hashes") - } - } - if nHashes[10].String() != "13ae8e4687ffe9daa1d9d42d1100b398bc328e2d971af1f4464af37f412d3d7c" { - t.Error("Error calculating locator hashes after step increase") - } - os.RemoveAll("headers.bin") -} - -func TestBlockchain_GetEpoch(t *testing.T) { - bc, err := NewBlockchain("", MockCreationTime, &chaincfg.RegressionNetParams) - if err != nil { - t.Error(err) - } - err = createBlockChain(bc) - if err != nil { - t.Error(err) - } - epoch, err := bc.GetEpoch() - if err != nil { - t.Error(err) - } - if epoch.BlockHash().String() != "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206" { - t.Error("Returned incorrect epoch") - } - os.RemoveAll("headers.bin") -} - -func TestBlockchain_calcRequiredWork(t *testing.T) { - params := &chaincfg.TestNet3Params - bc, err := NewBlockchain("", MockCreationTime, params) - if err != nil { - t.Error(err) - } - err = createBlockChain(bc) - if err != nil { - t.Error(err) - } - best, err := bc.db.GetBestHeader() - if err != nil { - t.Error(err) - } - - // Test during difficulty adjust period - newHdr := wire.BlockHeader{} - newHdr.PrevBlock = best.header.BlockHash() - work, err := bc.calcRequiredWork(newHdr, 2016, best) - if err != nil { - t.Error(err) - } - if work <= best.header.Bits { - t.Error("Returned in correct bits") - } - newHdr.Bits = work - sh := StoredHeader{ - header: newHdr, - height: 2016, - totalWork: blockchain.CompactToBig(work), - } - bc.db.Put(sh, true) - - // Test during normal adjustment - params.ReduceMinDifficulty = false - newHdr1 := wire.BlockHeader{} - newHdr1.PrevBlock = newHdr.BlockHash() - work1, err := bc.calcRequiredWork(newHdr1, 2017, sh) - if err != nil { - t.Error(err) - } - if work1 != work { - t.Error("Returned in correct bits") - } - newHdr1.Bits = work1 - sh = StoredHeader{ - header: newHdr1, - height: 2017, - totalWork: blockchain.CompactToBig(work1), - } - bc.db.Put(sh, true) - - // Test with reduced difficult flag - params.ReduceMinDifficulty = true - newHdr2 := wire.BlockHeader{} - newHdr2.PrevBlock = newHdr1.BlockHash() - work2, err := bc.calcRequiredWork(newHdr2, 2018, sh) - if err != nil { - t.Error(err) - } - if work2 != work1 { - t.Error("Returned in correct bits") - } - newHdr2.Bits = work2 - sh = StoredHeader{ - header: newHdr2, - height: 2018, - totalWork: blockchain.CompactToBig(work2), - } - bc.db.Put(sh, true) - - // Test testnet exemption - newHdr3 := wire.BlockHeader{} - newHdr3.PrevBlock = newHdr2.BlockHash() - newHdr3.Timestamp = newHdr2.Timestamp.Add(time.Minute * 21) - work3, err := bc.calcRequiredWork(newHdr3, 2019, sh) - if err != nil { - t.Error(err) - } - if work3 != params.PowLimitBits { - t.Error("Returned in correct bits") - } - newHdr3.Bits = work3 - sh = StoredHeader{ - header: newHdr3, - height: 2019, - totalWork: blockchain.CompactToBig(work3), - } - bc.db.Put(sh, true) - - // Test multiple special difficulty blocks in a row - params.ReduceMinDifficulty = true - newHdr4 := wire.BlockHeader{} - newHdr4.PrevBlock = newHdr3.BlockHash() - work4, err := bc.calcRequiredWork(newHdr4, 2020, sh) - if err != nil { - t.Error(err) - } - if work4 != work2 { - t.Error("Returned in correct bits") - } - os.RemoveAll("headers.bin") -} - -func TestBlockchain_Rollback(t *testing.T) { - bc, err := NewBlockchain("", MockCreationTime, &chaincfg.RegressionNetParams) - if err != nil { - t.Error(err) - return - } - err = createBlockChain(bc) - if err != nil { - t.Error(err) - return - } - sh, err := bc.db.GetBestHeader() - if err != nil { - t.Error(err) - return - } - for i := 0; i < 1000; i++ { - sh, err = bc.db.GetPreviousHeader(sh.header) - if err != nil { - t.Error(err) - return - } - } - - err = bc.Rollback(sh.header.Timestamp) - if err != nil { - t.Error(err) - return - } - h, err := bc.db.Height() - if err != nil { - t.Error(err) - return - } - if h != sh.height-1 { - t.Error("Failed to roll back the blockchain to the correct height") - } - os.RemoveAll("headers.bin") -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/cli/cli.go b/vendor/github.com/OpenBazaar/spvwallet/cli/cli.go deleted file mode 100644 index 2b0bcaffce..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/cli/cli.go +++ /dev/null @@ -1,1041 +0,0 @@ -package cli - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "github.com/OpenBazaar/jsonpb" - "github.com/OpenBazaar/spvwallet" - "github.com/OpenBazaar/spvwallet/api" - "github.com/OpenBazaar/spvwallet/api/pb" - "github.com/btcsuite/btcd/wire" - "github.com/golang/protobuf/ptypes" - "github.com/golang/protobuf/ptypes/timestamp" - "github.com/jessevdk/go-flags" - "golang.org/x/net/context" - "google.golang.org/grpc" - "os" - "strconv" - "strings" - "time" -) - -func SetupCli(parser *flags.Parser) { - // Add commands to parser - parser.AddCommand("stop", - "stop the wallet", - "The stop command disconnects from peers and shuts down the wallet", - &stop) - parser.AddCommand("currentaddress", - "get the current bitcoin address", - "Returns the first unused address in the keychain\n\n"+ - "Args:\n"+ - "1. purpose (string default=external) The purpose for the address. Can be external for receiving from outside parties or internal for example, for change.\n\n"+ - "Examples:\n"+ - "> spvwallet currentaddress\n"+ - "1DxGWC22a46VPEjq8YKoeVXSLzB7BA8sJS\n"+ - "> spvwallet currentaddress internal\n"+ - "18zAxgfKx4NuTUGUEuB8p7FKgCYPM15DfS\n", - ¤tAddress) - parser.AddCommand("newaddress", - "get a new bitcoin address", - "Returns a new unused address in the keychain. Use caution when using this function as generating too many new addresses may cause the keychain to extend further than the wallet's lookahead window, meaning it might fail to recover all transactions when restoring from seed. CurrentAddress is safer as it never extends past the lookahead window.\n\n"+ - "Args:\n"+ - "1. purpose (string default=external) The purpose for the address. Can be external for receiving from outside parties or internal for example, for change.\n\n"+ - "Examples:\n"+ - "> spvwallet newaddress\n"+ - "1DxGWC22a46VPEjq8YKoeVXSLzB7BA8sJS\n"+ - "> spvwallet newaddress internal\n"+ - "18zAxgfKx4NuTUGUEuB8p7FKgCYPM15DfS\n", - &newAddress) - parser.AddCommand("chaintip", - "return the height of the chain", - "Returns the height of the best chain of headers", - &chainTip) - parser.AddCommand("dumpheaders", - "print the header database", - "Prints the header database to stdout."+ - "Args:\n"+ - "1. Path (string) Optional path to the header file\n", - &dumpheaders) - parser.AddCommand("balance", - "get the wallet balance", - "Returns both the confirmed and unconfirmed balances", - &balance) - parser.AddCommand("masterprivatekey", - "get the wallet's master private key", - "Returns the bip32 master private key", - &masterPrivateKey) - parser.AddCommand("masterpublickey", - "get the wallet's master public key", - "Returns the bip32 master public key", - &masterPublicKey) - parser.AddCommand("getkey", - "get a private key", - "Return the private key for the given address", - &getKey) - parser.AddCommand("listaddresses", - "list all addresses", - "Returns all addresses currently watched by the wallet", - &listAddresses) - parser.AddCommand("listkeys", - "list all private keys", - "Returns all private keys currently watched by the wallet", - &listKeys) - parser.AddCommand("haskey", - "does key exist", - "Returns whether a key for the given address exists in the wallet\n\n"+ - "Args:\n"+ - "1. address (string) The address to find a key for.\n\n"+ - "Examples:\n"+ - "> spvwallet haskey 1DxGWC22a46VPEjq8YKoeVXSLzB7BA8sJS\n"+ - "true\n", - &hasKey) - parser.AddCommand("transactions", - "get a list of transactions", - "Returns a json list of the wallet's transactions", - &transactions) - parser.AddCommand("gettransaction", - "get a specific transaction", - "Returns json data of a specific transaction\n\n"+ - "Args:\n"+ - "1. txid (string) A transaction ID to search for.\n\n"+ - "Examples:\n"+ - "> spvwallet gettransaction 190bd83935740b88ebdfe724485f36ca4aa40125a21b93c410e0e191d4e9e0b5\n", - &getTransaction) - parser.AddCommand("getfeeperbyte", - "get the current bitcoin fee", - "Returns the current network fee per byte for the given fee level.\n\n"+ - "Args:\n"+ - "1. feelevel (string default=normal) The fee level: economic, normal, priority\n\n"+ - "Examples:\n"+ - "> spvwallet getfeeperbyte\n"+ - "140\n"+ - "> spvwallet getfeeperbyte priority\n"+ - "160\n", - &getFeePerByte) - parser.AddCommand("spend", - "send bitcoins", - "Send bitcoins to the given address\n\n"+ - "Args:\n"+ - "1. address (string) The recipient's bitcoin address\n"+ - "2. amount (integer) The amount to send in satoshi"+ - "3. feelevel (string default=normal) The fee level: economic, normal, priority\n\n"+ - "Examples:\n"+ - "> spvwallet spend 1DxGWC22a46VPEjq8YKoeVXSLzB7BA8sJS 1000000\n"+ - "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c"+ - "> spvwallet spend 1DxGWC22a46VPEjq8YKoeVXSLzB7BA8sJS 3000000000 priority\n"+ - "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", - &spend) - parser.AddCommand("bumpfee", - "bump the tx fee", - "Bumps the fee on an unconfirmed transaction\n\n"+ - "Args:\n"+ - "1. txid (string) The transaction ID of the transaction to bump.\n\n"+ - "Examples:\n"+ - "> spvwallet bumpfee 190bd83935740b88ebdfe724485f36ca4aa40125a21b93c410e0e191d4e9e0b5\n"+ - "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", - &bumpFee) - parser.AddCommand("peers", - "get info about peers", - "Returns a list of json data on each connected peer", - &peers) - parser.AddCommand("addwatchedscript", - "add a script to watch", - "Add a script of bitcoin address to watch\n\n"+ - "Args:\n"+ - "1. script (string) A hex encoded output script or bitcoin address.\n\n"+ - "Examples:\n"+ - "> spvwallet addwatchedscript 1DxGWC22a46VPEjq8YKoeVXSLzB7BA8sJS\n"+ - "> spvwallet addwatchedscript 76a914f318374559bf8296228e9c7480578a357081d59988ac\n", - &addWatchedAddress) - parser.AddCommand("getconfirmations", - "get the number of confirmations for a tx", - "Returns the number of confirmations for the given transaction\n\n"+ - "Args:\n"+ - "1. txid (string) The transaction ID\n\n"+ - "Examples:\n"+ - "> spvwallet getconfirmations 190bd83935740b88ebdfe724485f36ca4aa40125a21b93c410e0e191d4e9e0b5\n"+ - "6\n", - &getConfirmations) - parser.AddCommand("sweepaddress", - "sweep all coins from an address", - "Completely empty an address into a different one\n\n"+ - "Args:\n"+ - "1. sweepinfo (jsonobject) A json obeject containing the required data\n"+ - "{\n"+ - ` "utxos": [`+"\n"+ - " {\n"+ - ` "txid": "id" (string, required) The transaction id`+"\n"+ - ` "index": n (integer, required) The output index`+"\n"+ - ` "value": n (integer, required) The output amount in satoshi`+"\n"+ - " }\n"+ - " ],\n"+ - ` "address": "addr", (string, optional) The address to send the coins to. If omitted a change address from this wallet will be used.`+"\n"+ - ` "key": "key", (string, required) The private key used to sign. Can be in WIF, Hex, or xPriv format`+"\n"+ - ` "redeemScript": "script", (string, optional) Redeem script if p2sh. Only single key scripts supported a present.`+"\n"+ - ` "feeLevel": "level", (string, optional default=normal ) The fee level: economic, normal, or priority`+"\n"+ - "}\n\n"+ - "Examples:\n"+ - `> spvwallet sweepaddress "{"utxos":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0, "value": 1000000], "address": "1DxGWC22a46VPEjq8YKoeVXSLzB7BA8sJS", "key": "KzSg35HS67h4e7NLEywc3gNydjbRjzsyrPH5D7G8rpgv9qQCnb3S", "redeemScript": "1f6eb0660aab25ffe35978e7cb6e31bf40e1cceaf29c7f4f118cd2d76c2088237cb33c75510b8be669d90c01b0c394477690ff9c8388bcec4d71c3855fa50beb", "feeLevel":"priority"}"`+"\n"+ - "12c56cfcdc0249002c2a4b1f7fd957c7149fc45d0e9920594c7c78c17dcc34bd\n\n"+ - `> spvwallet sweepaddress "{"utxos":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0, "value": 1000000], "address": "1DxGWC22a46VPEjq8YKoeVXSLzB7BA8sJS", "key": "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", "feeLevel":"priority"}"`+"\n"+ - "12c56cfcdc0249002c2a4b1f7fd957c7149fc45d0e9920594c7c78c17dcc34bd\n\n"+ - `> spvwallet sweepaddress "{"utxos":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0, "value": 1000000], "address": "1DxGWC22a46VPEjq8YKoeVXSLzB7BA8sJS", "key": "be93c7096dc03bd495894140ff7fee894fbf6c944980d26f8f1cb12cc54316c7"}"`+"\n"+ - "12c56cfcdc0249002c2a4b1f7fd957c7149fc45d0e9920594c7c78c17dcc34bd\n\n"+ - `> spvwallet sweepaddress "{"utxos":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0, "value": 1000000], "key": "be93c7096dc03bd495894140ff7fee894fbf6c944980d26f8f1cb12cc54316c7"}"`+"\n"+ - "12c56cfcdc0249002c2a4b1f7fd957c7149fc45d0e9920594c7c78c17dcc34bd", - &sweepAddress) - parser.AddCommand("resyncblockchain", - "re-download the chain of headers", - "Will download all headers from the given height. Try this to uncover missing transasctions\n\n"+ - "Args:\n"+ - "1. timestamp (RFC3339 formatted timestamp) The starting time for the resync.\n\n"+ - "Examples:\n"+ - "> spvwallet resyncblockchain 2017-10-06T16:00:17Z\n"+ - "> spvwallet resyncblockchain", - &reSyncBlockchain) - parser.AddCommand("createmultisigsignature", - "create a p2sh multisig signature", - "Create a signature for a p2sh multisig transaction\n\n"+ - "Args:\n"+ - "1. txinfo (jsonobject) A json obeject containing the required data\n"+ - "{\n"+ - ` "inputs": [`+"\n"+ - " {\n"+ - ` "txid": "id" (string, required) The transaction id`+"\n"+ - ` "index": n (integer, required) The output index`+"\n"+ - " }\n"+ - " ],\n"+ - ` "outputs": [`+"\n"+ - " {\n"+ - ` "scriptPubKey": "script" (string, required) The output script in hex`+"\n"+ - ` "value": n (integer, required) The value to send to this output in satoshi`+"\n"+ - " }\n"+ - " ],\n"+ - ` "key": "key", (string, required) The private key used to sign. Can be in WIF, Hex, or xPriv format`+"\n"+ - ` "redeemScript": "script", (string, required) Redeem script if p2sh.`+"\n"+ - ` "feePerByte": n, (integer, required) The fee per byte in satoshis to use.`+"\n"+ - "}\n\n"+ - "Examples:\n"+ - `> spvwallet createmultisigsignature "{"inputs":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0], "outputs":["scriptPubKey": "76a914f318374559bf8296228e9c7480578a357081d59988ac", "value": 1000000], "key": "KzSg35HS67h4e7NLEywc3gNydjbRjzsyrPH5D7G8rpgv9qQCnb3S", "redeemScript": "1f6eb0660aab25ffe35978e7cb6e31bf40e1cceaf29c7f4f118cd2d76c2088237cb33c75510b8be669d90c01b0c394477690ff9c8388bcec4d71c3855fa50beb", "feePerByte": 140}"`+"\n"+ - `[{"inputIndex": 0, "signature": "d76206ff0df8ab2c4121bae90c71d9b3a432e8f9c0cc90f66f61dec782bc82983a08c93cd9c660f412ba082f95b11f561276782dfbf4376ff4ca6b2f4ab7b3b0d8ba8b724b0237933a"}]`+"\n\n"+ - `> spvwallet createmultisigsignature "{"inputs":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0], "outputs":["scriptPubKey": "76a914f318374559bf8296228e9c7480578a357081d59988ac", "value": 1000000], "key": "be93c7096dc03bd495894140ff7fee894fbf6c944980d26f8f1cb12cc54316c7", "redeemScript": "1f6eb0660aab25ffe35978e7cb6e31bf40e1cceaf29c7f4f118cd2d76c2088237cb33c75510b8be669d90c01b0c394477690ff9c8388bcec4d71c3855fa50beb", "feePerByte": 140}"`+"\n"+ - `[{"inputIndex": 0, "signature": "d76206ff0df8ab2c4121bae90c71d9b3a432e8f9c0cc90f66f61dec782bc82983a08c93cd9c660f412ba082f95b11f561276782dfbf4376ff4ca6b2f4ab7b3b0d8ba8b724b0237933a"}]`+"\n\n"+ - `> spvwallet createmultisigsignature "{"inputs":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0], "outputs":["scriptPubKey": "76a914f318374559bf8296228e9c7480578a357081d59988ac", "value": 1000000], "key": "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", "redeemScript": "1f6eb0660aab25ffe35978e7cb6e31bf40e1cceaf29c7f4f118cd2d76c2088237cb33c75510b8be669d90c01b0c394477690ff9c8388bcec4d71c3855fa50beb", "feePerByte": 140}"`+"\n"+ - `[{"inputIndex": 0, "signature": "d76206ff0df8ab2c4121bae90c71d9b3a432e8f9c0cc90f66f61dec782bc82983a08c93cd9c660f412ba082f95b11f561276782dfbf4376ff4ca6b2f4ab7b3b0d8ba8b724b0237933a"}]`+"\n\n", - &createMultisigSignature) - parser.AddCommand("multisign", - "combine multisig signatures", - "Create a signed 2 of 3 p2sh transaction from two signatures and optionally broadcast\n\n"+ - "Args:\n"+ - "1. txinfo (jsonobject) A json obeject containing the required data\n"+ - "{\n"+ - ` "inputs": [`+"\n"+ - " {\n"+ - ` "txid": "id" (string, required) The transaction id`+"\n"+ - ` "index": n (integer, required) The output index`+"\n"+ - " }\n"+ - " ],\n"+ - ` "outputs": [`+"\n"+ - " {\n"+ - ` "scriptPubKey": "script" (string, required) The output script in hex`+"\n"+ - ` "value": n (integer, required) The value to send to this output in satoshi`+"\n"+ - " }\n"+ - " ],\n"+ - ` "sig1": [`+"\n"+ - " {\n"+ - ` "index": n (integer, required) The input index for signature 1`+"\n"+ - ` "signature": "sig" (string, required) The hex encoded signature`+"\n"+ - " },\n"+ - " ],\n"+ - ` "sig2": [`+"\n"+ - " {\n"+ - ` "index": n (integer, required) The input index for signature 2`+"\n"+ - ` "signature": "sig" (string, required) The hex encoded signature`+"\n"+ - " },\n"+ - " ],\n"+ - ` "redeemScript": "script", (string, required) Redeem script if p2sh.`+"\n"+ - ` "feePerByte": n, (integer, required) The fee per byte in satoshis to use.`+"\n"+ - ` "broadcast": b, (bool, optional default=false) Broadcast the resulting tx to the network.`+"\n"+ - "}\n\n"+ - "Examples:\n"+ - `> spvwallet multisign "{"inputs":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0], "outputs":["scriptPubKey": "76a914f318374559bf8296228e9c7480578a357081d59988ac", "value": 1000000], "sig1": [{"inputIndex": 0, "signature": "d76206ff0df8ab2c4121bae90c71d9b3a432e8f9c0cc90f66f61dec782bc82983a08c93cd9c660f412ba082f95b11f561276782dfbf4376ff4ca6b2f4ab7b3b0d8ba8b724b0237933a"}], "sig2": [{"inputIndex": 0, "signature": "766c36dea732e9640868155b79703545b6ef129bb0446f9b86ac7cad775229ef41ac95543bf488ed42c5b82ffc14d7248136e988b1d4c0ea6d56712de139f83815e8974306d267a900"}], redeemScript": "1f6eb0660aab25ffe35978e7cb6e31bf40e1cceaf29c7f4f118cd2d76c2088237cb33c75510b8be669d90c01b0c394477690ff9c8388bcec4d71c3855fa50beb", "feePerByte": 140, "broadcast": true}"`+"\n"+ - `1393c31443b83c47de7def5a9edaf5f88c050e99f166353ed37404937be3099b`+"\n\n"+ - `> spvwallet multisign "{"inputs":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0], "outputs":["scriptPubKey": "76a914f318374559bf8296228e9c7480578a357081d59988ac", "value": 1000000], "sig1": [{"inputIndex": 0, "signature": "d76206ff0df8ab2c4121bae90c71d9b3a432e8f9c0cc90f66f61dec782bc82983a08c93cd9c660f412ba082f95b11f561276782dfbf4376ff4ca6b2f4ab7b3b0d8ba8b724b0237933a"}], "sig2": [{"inputIndex": 0, "signature": "766c36dea732e9640868155b79703545b6ef129bb0446f9b86ac7cad775229ef41ac95543bf488ed42c5b82ffc14d7248136e988b1d4c0ea6d56712de139f83815e8974306d267a900"}], "redeemScript": "1f6eb0660aab25ffe35978e7cb6e31bf40e1cceaf29c7f4f118cd2d76c2088237cb33c75510b8be669d90c01b0c394477690ff9c8388bcec4d71c3855fa50beb", "feePerByte": 140, "broadcast": false}"`+"\n"+ - `010000000100357d084478aa6beba8ca59de331e9bd725d23c3eaf7de0e5167801582a585f040000006b483045022100897aba7833d46a519c1f46694e053be8fdeae32125acd764c54c97ac6856d6f802201ff0e693055e39b16151b4da2a61f8dbb3948c08107b68a4b484dc7359de5b350121026a9dc92c93988750560fb46885fe549251c664e63545889367f5db183637f966ffffffff02a4857902000000001976a9143f2fe0d76898ef6c23b2b2a2892d763e0602bc4288acbd8b7349000000001976a914cc61ffeae5c6673caaaff5c0b06af395c8edc9ad88ac00000000`+"\n\n", - &multisign) - parser.AddCommand("estimatefee", - "estimate the fee for a tx", - "Given a transaction estimate what fee it will cost in satoshis\n\n"+ - "Args:\n"+ - "1. txinfo (jsonobject) A json obeject containing the required data\n"+ - "{\n"+ - ` "inputs": [`+"\n"+ - " {\n"+ - ` "txid": "id" (string, required) The transaction id`+"\n"+ - ` "index": n (integer, required) The output index`+"\n"+ - " }\n"+ - " ],\n"+ - ` "outputs": [`+"\n"+ - " {\n"+ - ` "scriptPubKey": "script" (string, required) The output script in hex`+"\n"+ - ` "value": n (integer, required) The value to send to this output in satoshi`+"\n"+ - " }\n"+ - " ],\n"+ - ` "feePerByte": n, (integer, required) The fee per byte in satoshis to use.`+"\n"+ - "}\n\n"+ - "Examples:\n"+ - `> spvwallet estimatefee "{"inputs":["txid": "82bfd45f3564e0b5166ab9ca072200a237f78499576e9658b20b0ccd10ff325c", "index": 0], "outputs":["scriptPubKey": "76a914f318374559bf8296228e9c7480578a357081d59988ac", "value": 1000000], "feePerByte": 140}"`+"\n"+ - "18500\n", - &estimateFee) -} - -func newGRPCClient() (pb.APIClient, *grpc.ClientConn, error) { - // Set up a connection to the server. - conn, err := grpc.Dial(api.Addr, grpc.WithInsecure()) - if err != nil { - return nil, nil, err - } - client := pb.NewAPIClient(conn) - return client, conn, nil -} - -type Stop struct{} - -var stop Stop - -func (x *Stop) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - client.Stop(context.Background(), &pb.Empty{}) - return nil -} - -type CurrentAddress struct{} - -var currentAddress CurrentAddress - -func (x *CurrentAddress) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - var purpose pb.KeyPurpose - userSelection := "" - if len(args) > 0 { - userSelection = args[0] - } - switch strings.ToLower(userSelection) { - case "internal": - purpose = pb.KeyPurpose_INTERNAL - case "external": - purpose = pb.KeyPurpose_EXTERNAL - default: - purpose = pb.KeyPurpose_EXTERNAL - } - resp, err := client.CurrentAddress(context.Background(), &pb.KeySelection{purpose}) - if err != nil { - return err - } - fmt.Println(resp.Addr) - return nil -} - -type NewAddress struct{} - -var newAddress NewAddress - -func (x *NewAddress) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - var purpose pb.KeyPurpose - userSelection := "" - if len(args) > 0 { - userSelection = args[0] - } - switch strings.ToLower(userSelection) { - case "internal": - purpose = pb.KeyPurpose_INTERNAL - case "external": - purpose = pb.KeyPurpose_EXTERNAL - default: - purpose = pb.KeyPurpose_EXTERNAL - } - resp, err := client.NewAddress(context.Background(), &pb.KeySelection{purpose}) - if err != nil { - return err - } - fmt.Println(resp.Addr) - return nil -} - -type ChainTip struct{} - -var chainTip ChainTip - -func (x *ChainTip) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - resp, err := client.ChainTip(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - fmt.Println(resp.Height) - return nil -} - -type Balance struct{} - -var balance Balance - -func (x *Balance) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - resp, err := client.Balance(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - type ret struct { - Confirmed uint64 `json:"confirmed"` - Unconfirmed uint64 `json:"unconfirmed"` - } - out, err := json.MarshalIndent(&ret{resp.Confirmed, resp.Unconfirmed}, "", " ") - if err != nil { - return err - } - fmt.Println(string(out)) - return nil -} - -type MasterPrivateKey struct{} - -var masterPrivateKey MasterPrivateKey - -func (x *MasterPrivateKey) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - resp, err := client.MasterPrivateKey(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - fmt.Println(resp.Key) - return nil -} - -type MasterPublicKey struct{} - -var masterPublicKey MasterPublicKey - -func (x *MasterPublicKey) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - resp, err := client.MasterPublicKey(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - fmt.Println(resp.Key) - return nil -} - -type HasKey struct{} - -var hasKey HasKey - -func (x *HasKey) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Bitcoin address is required") - } - resp, err := client.HasKey(context.Background(), &pb.Address{args[0]}) - if err != nil { - return err - } - fmt.Println(resp.Bool) - return nil -} - -type Transactions struct{} - -var transactions Transactions - -func (x *Transactions) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - resp, err := client.Transactions(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - chainTip, err := client.ChainTip(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - type Tx struct { - Txid string `json:"txid"` - Value int64 `json:"value"` - Status string `json:"status"` - Timestamp time.Time `json:"timestamp"` - Confirmations int32 `json:"confirmations"` - Height int32 `json:"height"` - WatchOnly bool `json:"watchOnly"` - } - var txns []Tx - for _, tx := range resp.Transactions { - var confirmations int32 - var status string - confs := int32(chainTip.Height) - tx.Height + 1 - if tx.Height <= 0 { - confs = tx.Height - } - ts := time.Unix(int64(tx.Timestamp.Seconds), int64(tx.Timestamp.Nanos)) - switch { - case confs < 0: - status = "DEAD" - case confs == 0 && time.Since(ts) <= time.Hour*6: - status = "UNCONFIRMED" - case confs == 0 && time.Since(ts) > time.Hour*6: - status = "STUCK" - case confs > 0 && confs < 7: - status = "PENDING" - confirmations = confs - case confs > 6: - status = "CONFIRMED" - confirmations = confs - } - t := Tx{ - Txid: tx.Txid, - Value: tx.Value, - Height: tx.Height, - WatchOnly: tx.WatchOnly, - Timestamp: ts, - Status: status, - Confirmations: confirmations, - } - txns = append(txns, t) - } - formatted, err := json.MarshalIndent(txns, "", " ") - if err != nil { - return err - } - fmt.Println(string(formatted)) - return nil -} - -type GetTransaction struct{} - -var getTransaction GetTransaction - -func (x *GetTransaction) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Txid is required") - } - resp, err := client.GetTransaction(context.Background(), &pb.Txid{args[0]}) - if err != nil { - return err - } - chainTip, err := client.ChainTip(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - type Tx struct { - Txid string `json:"txid"` - Value int64 `json:"value"` - Status string `json:"status"` - Timestamp time.Time `json:"timestamp"` - Confirmations int32 `json:"confirmations"` - Height int32 `json:"height"` - WatchOnly bool `json:"watchOnly"` - } - var confirmations int32 - var status string - confs := int32(chainTip.Height) - resp.Height + 1 - if resp.Height <= 0 { - confs = resp.Height - } - ts := time.Unix(int64(resp.Timestamp.Seconds), int64(resp.Timestamp.Nanos)) - switch { - case confs < 0: - status = "DEAD" - case confs == 0 && time.Since(ts) <= time.Hour*6: - status = "UNCONFIRMED" - case confs == 0 && time.Since(ts) > time.Hour*6: - status = "STUCK" - case confs > 0 && confs < 7: - status = "PENDING" - confirmations = confs - case confs > 6: - status = "CONFIRMED" - confirmations = confs - } - t := Tx{ - Txid: resp.Txid, - Value: resp.Value, - Height: resp.Height, - WatchOnly: resp.WatchOnly, - Timestamp: ts, - Status: status, - Confirmations: confirmations, - } - formatted, err := json.MarshalIndent(t, "", " ") - if err != nil { - return err - } - fmt.Println(string(formatted)) - return nil -} - -type GetFeePerByte struct{} - -var getFeePerByte GetFeePerByte - -func (x *GetFeePerByte) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - var feeLevel pb.FeeLevel - userSelection := "" - if len(args) > 0 { - userSelection = args[0] - } - switch strings.ToLower(userSelection) { - case "economic": - feeLevel = pb.FeeLevel_ECONOMIC - case "normal": - feeLevel = pb.FeeLevel_NORMAL - case "priority": - feeLevel = pb.FeeLevel_PRIORITY - default: - feeLevel = pb.FeeLevel_NORMAL - } - resp, err := client.GetFeePerByte(context.Background(), &pb.FeeLevelSelection{feeLevel}) - if err != nil { - return err - } - fmt.Println(resp.Fee) - return nil -} - -type Spend struct{} - -var spend Spend - -func (x *Spend) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - var feeLevel pb.FeeLevel - userSelection := "" - if len(args) > 2 { - userSelection = args[2] - } - if len(args) < 2 { - return errors.New("Address and amount are required") - } - switch strings.ToLower(userSelection) { - case "economic": - feeLevel = pb.FeeLevel_ECONOMIC - case "normal": - feeLevel = pb.FeeLevel_NORMAL - case "priority": - feeLevel = pb.FeeLevel_PRIORITY - default: - feeLevel = pb.FeeLevel_NORMAL - } - amt, err := strconv.Atoi(args[1]) - if err != nil { - return err - } - resp, err := client.Spend(context.Background(), &pb.SpendInfo{args[0], uint64(amt), feeLevel}) - if err != nil { - return err - } - fmt.Println(resp.Hash) - return nil -} - -type BumpFee struct{} - -var bumpFee BumpFee - -func (x *BumpFee) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Txid is required") - } - resp, err := client.BumpFee(context.Background(), &pb.Txid{args[0]}) - if err != nil { - return err - } - fmt.Println(resp.Hash) - return nil -} - -type Peers struct{} - -var peers Peers - -func (x *Peers) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - resp, err := client.Peers(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - type peer struct { - Address string `json:"address"` - BytesSent uint64 `json:"bytesSent"` - BytesReceived uint64 `json:"bytesReceived"` - Connected bool `json:"connected"` - ID int32 `json:"id"` - LastBlock int32 `json:"lastBlock"` - ProtocolVersion uint32 `json:"protocolVersion"` - Services string `json:"services"` - UserAgent string `json:"userAgent"` - TimeConnected time.Time `json:"timeConnected"` - } - var peers []peer - for _, p := range resp.Peers { - pi := peer{ - Address: p.Address, - BytesSent: p.BytesSent, - BytesReceived: p.BytesReceived, - Connected: p.Connected, - ID: p.ID, - LastBlock: p.LastBlock, - ProtocolVersion: p.ProtocolVersion, - Services: p.Services, - UserAgent: p.UserAgent, - TimeConnected: time.Unix(int64(p.TimeConnected.Seconds), int64(p.TimeConnected.Nanos)), - } - peers = append(peers, pi) - } - out, err := json.MarshalIndent(peers, "", " ") - fmt.Println(string(out)) - return nil -} - -type AddWatchedAddress struct{} - -var addWatchedAddress AddWatchedAddress - -func (x *AddWatchedAddress) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Address or script required") - } - _, err = client.AddWatchedAddress(context.Background(), &pb.Address{args[0]}) - return err -} - -type GetConfirmations struct{} - -var getConfirmations GetConfirmations - -func (x *GetConfirmations) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Txid is required") - } - resp, err := client.GetConfirmations(context.Background(), &pb.Txid{args[0]}) - if err != nil { - return err - } - fmt.Println(resp.Confirmations) - return nil -} - -type SweepAddress struct{} - -var sweepAddress SweepAddress - -func (x *SweepAddress) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Sweep data is required") - } - sweepInfo := new(pb.SweepInfo) - if err := jsonpb.UnmarshalString(args[0], sweepInfo); err != nil { - return err - } - resp, err := client.SweepAddress(context.Background(), sweepInfo) - if err != nil { - return err - } - fmt.Println(resp.Hash) - return nil -} - -type ReSyncBlockchain struct{} - -var reSyncBlockchain ReSyncBlockchain - -func (x *ReSyncBlockchain) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - var ts *timestamp.Timestamp - if len(args) <= 0 { - return errors.New("Txid is required") - } else { - t, err := time.Parse(time.RFC3339, args[0]) - if err != nil { - return err - } - ts, err = ptypes.TimestampProto(t) - if err != nil { - return err - } - } - _, err = client.ReSyncBlockchain(context.Background(), ts) - if err != nil { - return err - } - return nil -} - -type CreateMultisigSignature struct{} - -var createMultisigSignature CreateMultisigSignature - -func (x *CreateMultisigSignature) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Multisig data is required") - } - multsigInfo := new(pb.CreateMultisigInfo) - if err := jsonpb.UnmarshalString(args[0], multsigInfo); err != nil { - return err - } - resp, err := client.CreateMultisigSignature(context.Background(), multsigInfo) - if err != nil { - return err - } - type sig struct { - InputIndex uint32 `json:"inputIndex"` - Signature string `json:"signature"` - } - var sigs []sig - for _, s := range resp.Sigs { - retSig := sig{ - InputIndex: s.Index, - Signature: hex.EncodeToString(s.Signature), - } - sigs = append(sigs, retSig) - } - out, err := json.MarshalIndent(sigs, "", " ") - fmt.Println(string(out)) - return nil -} - -type Multisign struct{} - -var multisign Multisign - -func (x *Multisign) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Multisig data is required") - } - multsignInfo := new(pb.MultisignInfo) - if err := jsonpb.UnmarshalString(args[0], multsignInfo); err != nil { - return err - } - resp, err := client.Multisign(context.Background(), multsignInfo) - if err != nil { - return err - } - if multsignInfo.Broadcast { - r := bytes.NewReader(resp.Tx) - msgTx := wire.NewMsgTx(1) - msgTx.BtcDecode(r, 1, wire.WitnessEncoding) - fmt.Println(msgTx.TxHash().String()) - } else { - fmt.Println(hex.EncodeToString(resp.Tx)) - } - return nil -} - -type EstimateFee struct{} - -var estimateFee EstimateFee - -func (x *EstimateFee) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Tx data is required") - } - estimateFeeData := new(pb.EstimateFeeData) - if err := jsonpb.UnmarshalString(args[0], estimateFeeData); err != nil { - return err - } - resp, err := client.EstimateFee(context.Background(), estimateFeeData) - if err != nil { - return err - } - fmt.Println(resp.Fee) - return nil -} - -type DumpHeaders struct{} - -var dumpheaders DumpHeaders - -func (x *DumpHeaders) Execute(args []string) error { - if len(args) <= 0 { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - stream, err := client.DumpHeaders(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - for { - hdr, err := stream.Recv() - if err != nil { - return err - } - fmt.Println(hdr.Entry) - } - } else { - db, err := spvwallet.NewHeaderDB(args[0]) - if err != nil { - fmt.Println(err) - } else { - db.Print(os.Stdout) - } - } - return nil -} - -type GetKey struct{} - -var getKey GetKey - -func (x *GetKey) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - if len(args) <= 0 { - return errors.New("Address is required") - } - resp, err := client.GetKey(context.Background(), &pb.Address{args[0]}) - if err != nil { - return err - } - fmt.Println(resp.Key) - return nil -} - -type ListAddresses struct{} - -var listAddresses ListAddresses - -func (x *ListAddresses) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - resp, err := client.ListAddresses(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - for _, addr := range resp.Addresses { - fmt.Println(addr.Addr) - } - return nil -} - -type ListKeys struct{} - -var listKeys ListKeys - -func (x *ListKeys) Execute(args []string) error { - client, conn, err := newGRPCClient() - if err != nil { - return err - } - defer conn.Close() - resp, err := client.ListKeys(context.Background(), &pb.Empty{}) - if err != nil { - return err - } - for _, key := range resp.Keys { - fmt.Println(key.Key) - } - return nil -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/cmd/spvwallet/main.go b/vendor/github.com/OpenBazaar/spvwallet/cmd/spvwallet/main.go deleted file mode 100644 index ae6c1cfeeb..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/cmd/spvwallet/main.go +++ /dev/null @@ -1,570 +0,0 @@ -package main - -import ( - "encoding/json" - "errors" - "fmt" - - "github.com/OpenBazaar/spvwallet" - "github.com/OpenBazaar/spvwallet/api" - "github.com/OpenBazaar/spvwallet/cli" - "github.com/OpenBazaar/spvwallet/db" - "github.com/OpenBazaar/spvwallet/gui" - "github.com/OpenBazaar/spvwallet/gui/bootstrap" - wi "github.com/OpenBazaar/wallet-interface" - "github.com/asticode/go-astilectron" - "github.com/asticode/go-astilog" - "github.com/atotto/clipboard" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil" - "github.com/fatih/color" - "github.com/jessevdk/go-flags" - "github.com/natefinch/lumberjack" - "github.com/op/go-logging" - "github.com/skratchdot/open-golang/open" - "github.com/yawning/bulb" - "golang.org/x/net/proxy" - "io/ioutil" - "net" - "net/url" - "os" - "os/signal" - "path" - "strings" - "sync" - "time" -) - -var parser = flags.NewParser(nil, flags.Default) - -type Start struct { - DataDir string `short:"d" long:"datadir" description:"specify the data directory to be used"` - Testnet bool `short:"t" long:"testnet" description:"use the test network"` - Regtest bool `short:"r" long:"regtest" description:"run in regression test mode"` - Mnemonic string `short:"m" long:"mnemonic" description:"specify a mnemonic seed to use to derive the keychain"` - WalletCreationDate string `short:"w" long:"walletcreationdate" description:"specify the date the seed was created. if omitted the wallet will sync from the oldest checkpoint."` - TrustedPeer string `short:"i" long:"trustedpeer" description:"specify a single trusted peer to connect to"` - Tor bool `long:"tor" description:"connect via a running Tor daemon"` - FeeAPI string `short:"f" long:"feeapi" description:"fee API to use to fetch current fee rates. set as empty string to disable API lookups." default:"https://bitcoinfees.21.co/api/v1/fees/recommended"` - MaxFee uint64 `short:"x" long:"maxfee" description:"the fee-per-byte ceiling beyond which fees cannot go" default:"2000"` - LowDefaultFee uint64 `short:"e" long:"economicfee" description:"the default low fee-per-byte" default:"140"` - MediumDefaultFee uint64 `short:"n" long:"normalfee" description:"the default medium fee-per-byte" default:"160"` - HighDefaultFee uint64 `short:"p" long:"priorityfee" description:"the default high fee-per-byte" default:"180"` - Gui bool `long:"gui" description:"launch an experimental GUI"` - Verbose bool `short:"v" long:"verbose" description:"print to standard out"` -} -type Version struct{} - -var start Start -var version Version -var wallet *spvwallet.SPVWallet - -func main() { - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - go func() { - for range c { - fmt.Println("SPVWallet shutting down...") - wallet.Close() - os.Exit(1) - } - }() - if len(os.Args) == 1 { - start.Gui = true - start.Execute([]string{"defaultSettings"}) - } else { - parser.AddCommand("start", - "start the wallet", - "The start command starts the wallet daemon", - &start) - parser.AddCommand("version", - "print the version number", - "Print the version number and exit", - &version) - cli.SetupCli(parser) - if _, err := parser.Parse(); err != nil { - os.Exit(1) - } - } -} - -func (x *Version) Execute(args []string) error { - fmt.Println(spvwallet.WALLET_VERSION) - return nil -} - -func (x *Start) Execute(args []string) error { - var err error - // Create a new config - config := spvwallet.NewDefaultConfig() - if x.DataDir != "" { - config.RepoPath = x.DataDir - } - if x.Testnet && x.Regtest { - return errors.New("Invalid combination of testnet and regtest modes") - } - basepath := config.RepoPath - if x.Testnet { - config.Params = &chaincfg.TestNet3Params - config.RepoPath = path.Join(config.RepoPath, "testnet") - } - if x.Regtest { - config.Params = &chaincfg.RegressionNetParams - config.RepoPath = path.Join(config.RepoPath, "regtest") - } - - _, ferr := os.Stat(config.RepoPath) - if os.IsNotExist(ferr) { - os.Mkdir(config.RepoPath, os.ModePerm) - } - if x.Mnemonic != "" { - config.Mnemonic = x.Mnemonic - } - if x.TrustedPeer != "" { - addr, err := net.ResolveTCPAddr("tcp", x.TrustedPeer) - if err != nil { - return err - } - config.TrustedPeer = addr - } - if x.Tor { - var conn *bulb.Conn - conn, err = bulb.Dial("tcp4", "127.0.0.1:9151") - if err != nil { - conn, err = bulb.Dial("tcp4", "127.0.0.1:9151") - if err != nil { - return errors.New("Tor daemon not found") - } - } - dialer, err := conn.Dialer(nil) - if err != nil { - return err - } - config.Proxy = dialer - } - if x.FeeAPI != "" { - u, err := url.Parse(x.FeeAPI) - if err != nil { - return err - } - config.FeeAPI = *u - } - if len(args) == 0 { - config.MaxFee = x.MaxFee - config.LowFee = x.LowDefaultFee - config.MediumFee = x.MediumDefaultFee - config.HighFee = x.HighDefaultFee - } - - // Make the logging a little prettier - var fileLogFormat = logging.MustStringFormatter(`%{time:15:04:05.000} [%{shortfunc}] [%{level}] %{message}`) - var stdoutLogFormat = logging.MustStringFormatter(`%{color:reset}%{color}%{time:15:04:05.000} [%{shortfunc}] [%{level}] %{message}`) - w := &lumberjack.Logger{ - Filename: path.Join(config.RepoPath, "logs", "bitcoin.log"), - MaxSize: 10, // Megabytes - MaxBackups: 3, - MaxAge: 30, // Days - } - bitcoinFile := logging.NewLogBackend(w, "", 0) - bitcoinFileFormatter := logging.NewBackendFormatter(bitcoinFile, fileLogFormat) - config.Logger = logging.MultiLogger(logging.MultiLogger(bitcoinFileFormatter)) - if x.Verbose { - stdoutLog := logging.NewLogBackend(os.Stdout, "", 0) - stdoutFormatter := logging.NewBackendFormatter(stdoutLog, stdoutLogFormat) - config.Logger = logging.MultiLogger(logging.MultiLogger(stdoutFormatter)) - } - - // Select wallet datastore - sqliteDatastore, _ := db.Create(config.RepoPath) - config.DB = sqliteDatastore - - mn, _ := sqliteDatastore.GetMnemonic() - if mn != "" { - config.Mnemonic = mn - } - cd, err := sqliteDatastore.GetCreationDate() - if err == nil { - config.CreationDate = cd - } - - // Write version file - f, err := os.Create(path.Join(basepath, "version")) - if err != nil { - return err - } - f.Write([]byte("1")) - f.Close() - - // Load settings - type Fees struct { - Priority uint64 `json:"priority"` - Normal uint64 `json:"normal"` - Economic uint64 `json:"economic"` - FeeAPI string `json:"feeAPI"` - } - - type Settings struct { - FiatCode string `json:"fiatCode"` - FiatSymbol string `json:"fiatSymbol"` - FeeLevel string `json:"feeLevel"` - SelectBox string `json:"selectBox"` - BitcoinUnit string `json:"bitcoinUnit"` - DecimalPlaces int `json:"decimalPlaces"` - TrustedPeer string `json:"trustedPeer"` - Proxy string `json:"proxy"` - Fees Fees `json:"fees"` - } - - var settings Settings - s, err := ioutil.ReadFile(path.Join(basepath, "settings.json")) - if err != nil { - settings = Settings{ - FiatCode: "USD", - FiatSymbol: "$", - FeeLevel: "priority", - SelectBox: "bitcoin", - BitcoinUnit: "BTC", - DecimalPlaces: 5, - Fees: Fees{ - Priority: config.HighFee, - Normal: config.MediumFee, - Economic: config.LowFee, - FeeAPI: config.FeeAPI.String(), - }, - } - f, err := os.Create(path.Join(basepath, "settings.json")) - if err != nil { - return err - } - s, err := json.MarshalIndent(&settings, "", " ") - if err != nil { - return err - } - f.Write(s) - f.Close() - } else { - err := json.Unmarshal([]byte(s), &settings) - if err != nil { - return err - } - } - if settings.TrustedPeer != "" { - var tp net.Addr - tp, err = net.ResolveTCPAddr("tcp", settings.TrustedPeer) - if err != nil { - return err - } - config.TrustedPeer = tp - } - - if settings.Proxy != "" { - tbProxyURL, err := url.Parse("socks5://" + settings.Proxy) - if err != nil { - return err - } - tbDialer, err := proxy.FromURL(tbProxyURL, proxy.Direct) - if err != nil { - return err - } - config.Proxy = tbDialer - } - feeApi, _ := url.Parse(settings.Fees.FeeAPI) - config.FeeAPI = *feeApi - config.HighFee = settings.Fees.Priority - config.MediumFee = settings.Fees.Normal - config.LowFee = settings.Fees.Economic - - if x.WalletCreationDate != "" { - creationDate, err := time.Parse(time.RFC3339, x.WalletCreationDate) - if err != nil { - return errors.New("Wallet creation date timestamp must be in RFC3339 format") - } - config.CreationDate = creationDate - } - - // Create the wallet - wallet, err = spvwallet.NewSPVWallet(config) - if err != nil { - return err - } - - if err := sqliteDatastore.SetMnemonic(config.Mnemonic); err != nil { - return err - } - if err := sqliteDatastore.SetCreationDate(config.CreationDate); err != nil { - return err - } - - go api.ServeAPI(wallet) - - // Start it! - printSplashScreen() - - if x.Gui { - go wallet.Start() - - type Stats struct { - Confirmed int64 `json:"confirmed"` - Fiat string `json:"fiat"` - Transactions int `json:"transactions"` - Height uint32 `json:"height"` - ExchangeRate string `json:"exchangeRate"` - } - - txc := make(chan uint32) - listener := func(wi.TransactionCallback) { - h, _ := wallet.ChainTip() - txc <- h - } - wallet.AddTransactionListener(listener) - - tc := make(chan struct{}) - rc := make(chan int) - - os.RemoveAll(path.Join(basepath, "resources")) - iconPath := path.Join(basepath, "icon.png") - _, err := os.Stat(iconPath) - if os.IsNotExist(err) { - f, err := os.Create(iconPath) - if err != nil { - return err - } - icon, err := gui.AppIconPngBytes() - if err != nil { - return err - } - f.Write(icon) - defer f.Close() - } - - // Run bootstrap - if err := bootstrap.Run(bootstrap.Options{ - AstilectronOptions: astilectron.Options{ - AppName: "spvwallet", - AppIconDefaultPath: iconPath, - //AppIconDarwinPath: p + "/gopher.icns", - BaseDirectoryPath: basepath, - }, - Homepage: "index.html", - MessageHandler: func(w *astilectron.Window, m bootstrap.MessageIn) { - switch m.Name { - case "getStats": - type P struct { - CurrencyCode string `json:"currencyCode"` - } - var p P - if err := json.Unmarshal(m.Payload, &p); err != nil { - astilog.Errorf("Unmarshaling %s failed", m.Payload) - return - } - confirmed, _ := wallet.Balance() - txs, err := wallet.Transactions() - if err != nil { - astilog.Errorf(err.Error()) - return - } - rate, err := wallet.ExchangeRates().GetExchangeRate(p.CurrencyCode) - if err != nil { - astilog.Errorf("Failed to get exchange rate") - return - } - btcVal := float64(confirmed) / 100000000 - fiatVal := float64(btcVal) * rate - height, _ := wallet.ChainTip() - - st := Stats{ - Confirmed: confirmed, - Fiat: fmt.Sprintf("%.2f", fiatVal), - Transactions: len(txs), - Height: height, - ExchangeRate: fmt.Sprintf("%.2f", rate), - } - w.SendMessage(bootstrap.MessageOut{Name: "statsUpdate", Payload: st}) - case "getAddress": - addr := wallet.CurrentAddress(wi.EXTERNAL) - w.SendMessage(bootstrap.MessageOut{Name: "address", Payload: addr.EncodeAddress()}) - case "send": - type P struct { - Address string `json:"address"` - Amount float64 `json:"amount"` - Note string `json:"note"` - FeeLevel string `json:"feeLevel"` - } - var p P - if err := json.Unmarshal(m.Payload, &p); err != nil { - astilog.Errorf("Unmarshaling %s failed", m.Payload) - return - } - var feeLevel wi.FeeLevel - switch strings.ToLower(p.FeeLevel) { - case "priority": - feeLevel = wi.PRIOIRTY - case "normal": - feeLevel = wi.NORMAL - case "economic": - feeLevel = wi.ECONOMIC - default: - feeLevel = wi.NORMAL - } - addr, err := btcutil.DecodeAddress(p.Address, wallet.Params()) - if err != nil { - w.SendMessage(bootstrap.MessageOut{Name: "spendError", Payload: "Invalid address"}) - return - } - _, err = wallet.Spend(int64(p.Amount), addr, feeLevel, "", false) - if err != nil { - w.SendMessage(bootstrap.MessageOut{Name: "spendError", Payload: err.Error()}) - } - case "clipboard": - type P struct { - Data string `json:"data"` - } - var p P - if err := json.Unmarshal(m.Payload, &p); err != nil { - astilog.Errorf("Unmarshaling %s failed", m.Payload) - return - } - clipboard.WriteAll(p.Data) - case "putSettings": - var setstr string - if err := json.Unmarshal(m.Payload, &setstr); err != nil { - astilog.Errorf("Unmarshaling %s failed", m.Payload) - return - } - var settings Settings - if err := json.Unmarshal([]byte(setstr), &settings); err != nil { - astilog.Errorf("Unmarshaling %s failed", m.Payload) - return - } - - f, err := os.Create(path.Join(basepath, "settings.json")) - if err != nil { - astilog.Error(err.Error()) - return - } - defer f.Close() - b, err := json.MarshalIndent(&settings, "", " ") - if err != nil { - astilog.Error(err.Error()) - return - } - f.Write(b) - case "getSettings": - settings, err := ioutil.ReadFile(path.Join(basepath, "settings.json")) - if err != nil { - astilog.Error(err.Error()) - } - w.SendMessage(bootstrap.MessageOut{Name: "settings", Payload: string(settings)}) - case "openbrowser": - var url string - if err := json.Unmarshal(m.Payload, &url); err != nil { - astilog.Errorf("Unmarshaling %s failed", m.Payload) - return - } - open.Run(url) - case "resync": - wallet.ReSyncBlockchain(time.Time{}) - case "restore": - var mnemonic string - if err := json.Unmarshal(m.Payload, &mnemonic); err != nil { - astilog.Errorf("Unmarshaling %s failed", m.Payload) - return - } - wallet.Close() - os.Remove(path.Join(config.RepoPath, "wallet.db")) - os.Remove(path.Join(config.RepoPath, "headers.bin")) - sqliteDatastore, _ := db.Create(config.RepoPath) - config.DB = sqliteDatastore - config.Mnemonic = mnemonic - config.CreationDate = time.Time{} - wallet, err = spvwallet.NewSPVWallet(config) - if err != nil { - astilog.Errorf("Unmarshaling %s failed", m.Payload) - return - } - sqliteDatastore.SetMnemonic(mnemonic) - sqliteDatastore.SetCreationDate(time.Time{}) - go wallet.Start() - case "minimize": - go func() { - w.Hide() - tc <- struct{}{} - }() - case "showTransactions": - go func() { - rc <- 649 - }() - txs, err := wallet.Transactions() - if err != nil { - w.SendMessage(bootstrap.MessageOut{Name: "txError", Payload: err.Error()}) - } - w.SendMessage(bootstrap.MessageOut{Name: "transactions", Payload: txs}) - case "getTransactions": - txs, err := wallet.Transactions() - if err != nil { - w.SendMessage(bootstrap.MessageOut{Name: "txError", Payload: err.Error()}) - } - w.SendMessage(bootstrap.MessageOut{Name: "transactions", Payload: txs}) - case "hide": - go func() { - rc <- 341 - }() - case "showSettings": - go func() { - rc <- 649 - }() - case "getMnemonic": - w.SendMessage(bootstrap.MessageOut{Name: "mnemonic", Payload: wallet.Mnemonic()}) - } - }, - RestoreAssets: gui.RestoreAssets, - WindowOptions: &astilectron.WindowOptions{ - Center: astilectron.PtrBool(true), - Height: astilectron.PtrInt(340), - Width: astilectron.PtrInt(621), - Maximizable: astilectron.PtrBool(false), - Fullscreenable: astilectron.PtrBool(false), - Resizable: astilectron.PtrBool(false), - }, - TrayOptions: &astilectron.TrayOptions{ - Image: astilectron.PtrStr(iconPath), - }, - TrayChan: tc, - ResizeChan: rc, - TransactionChan: txc, - BaseDirectoryPath: basepath, - Wallet: wallet, - //Debug: true, - }); err != nil { - astilog.Fatal(err) - } - } else { - wallet.Start() - var wg sync.WaitGroup - wg.Add(1) - wg.Wait() - } - return nil -} - -func printSplashScreen() { - blue := color.New(color.FgBlue) - white := color.New(color.FgWhite) - white.Printf(" _______________________ ______") - blue.Println(" __ .__ .__ __") - white.Printf(` / _____/\______ \ \ / /`) - blue.Println(` \ / \_____ | | | | _____/ |_`) - white.Printf(` \_____ \ | ___/\ Y /`) - blue.Println(`\ \/\/ /\__ \ | | | | _/ __ \ __\`) - white.Printf(` / \ | | \ / `) - blue.Println(` \ / / __ \| |_| |_\ ___/| |`) - white.Printf(`/_______ / |____| \___/ `) - blue.Println(` \__/\ / (____ /____/____/\___ >__|`) - white.Printf(` \/ `) - blue.Println(` \/ \/ \/`) - blue.DisableColor() - white.DisableColor() - fmt.Println("") - fmt.Println("SPVWallet v" + spvwallet.WALLET_VERSION + " starting...") - fmt.Println("[Press Ctrl+C to exit]") -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/config.go b/vendor/github.com/OpenBazaar/spvwallet/config.go index e35cb7bc85..2b4cb41321 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/config.go +++ b/vendor/github.com/OpenBazaar/spvwallet/config.go @@ -41,9 +41,10 @@ type Config struct { Proxy proxy.Dialer // The default fee-per-byte for each level - LowFee uint64 - MediumFee uint64 - HighFee uint64 + SuperLowFee uint64 + LowFee uint64 + MediumFee uint64 + HighFee uint64 // The highest allowable fee-per-byte MaxFee uint64 diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/README.md b/vendor/github.com/OpenBazaar/spvwallet/db/README.md deleted file mode 100644 index 5d65059b68..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/README.md +++ /dev/null @@ -1,8 +0,0 @@ -SQLite db implementation -======================== - -The `Datastore` interface allows for a pluggable wallet database. OpenBazaar, for example, uses its own `Datastore` implementation -so that wallet data can be stored in the same database alongside the rest of OpenBazaar data so that users need only make one backup. - -Writing your own implementation is probably the best approach, however, this package does contain a workable `Datastore` implementation -using SQLite. This is the datastore used by `NewDefaultConfig`. \ No newline at end of file diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/database.go b/vendor/github.com/OpenBazaar/spvwallet/db/database.go deleted file mode 100644 index 8f7aded736..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/database.go +++ /dev/null @@ -1,163 +0,0 @@ -package db - -import ( - "database/sql" - "github.com/OpenBazaar/wallet-interface" - _ "github.com/mattn/go-sqlite3" - "path" - "sync" - "time" -) - -// This database is mostly just an example implementation used for testing. -// End users are free to user their own database. -type SQLiteDatastore struct { - keys wallet.Keys - utxos wallet.Utxos - stxos wallet.Stxos - txns wallet.Txns - watchedScripts wallet.WatchedScripts - db *sql.DB - lock *sync.RWMutex -} - -func Create(repoPath string) (*SQLiteDatastore, error) { - dbPath := path.Join(repoPath, "wallet.db") - conn, err := sql.Open("sqlite3", dbPath) - if err != nil { - return nil, err - } - - l := new(sync.RWMutex) - sqliteDB := &SQLiteDatastore{ - keys: &KeysDB{ - db: conn, - lock: l, - }, - utxos: &UtxoDB{ - db: conn, - lock: l, - }, - stxos: &StxoDB{ - db: conn, - lock: l, - }, - txns: &TxnsDB{ - db: conn, - lock: l, - }, - watchedScripts: &WatchedScriptsDB{ - db: conn, - lock: l, - }, - db: conn, - lock: l, - } - initDatabaseTables(conn) - return sqliteDB, nil -} - -func (db *SQLiteDatastore) Keys() wallet.Keys { - return db.keys -} -func (db *SQLiteDatastore) Utxos() wallet.Utxos { - return db.utxos -} -func (db *SQLiteDatastore) Stxos() wallet.Stxos { - return db.stxos -} -func (db *SQLiteDatastore) Txns() wallet.Txns { - return db.txns -} -func (db *SQLiteDatastore) WatchedScripts() wallet.WatchedScripts { - return db.watchedScripts -} - -func initDatabaseTables(db *sql.DB) error { - var sqlStmt string - sqlStmt = sqlStmt + ` - create table if not exists keys (scriptAddress text primary key not null, purpose integer, keyIndex integer, used integer, key text); - create table if not exists utxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer); - create table if not exists stxos (outpoint text primary key not null, value integer, height integer, scriptPubKey text, watchOnly integer, spendHeight integer, spendTxid text); - create table if not exists txns (txid text primary key not null, value integer, height integer, timestamp integer, watchOnly integer, tx blob); - create table if not exists watchedScripts (scriptPubKey text primary key not null); - create table if not exists config(key text primary key not null, value blob); - ` - _, err := db.Exec(sqlStmt) - if err != nil { - return err - } - return nil -} - -func (s *SQLiteDatastore) GetMnemonic() (string, error) { - s.lock.RLock() - defer s.lock.RUnlock() - stmt, err := s.db.Prepare("select value from config where key=?") - defer stmt.Close() - var mnemonic string - err = stmt.QueryRow("mnemonic").Scan(&mnemonic) - if err != nil { - return "", err - } - return mnemonic, nil -} - -func (s *SQLiteDatastore) SetMnemonic(mnemonic string) error { - s.lock.RLock() - defer s.lock.RUnlock() - tx, err := s.db.Begin() - if err != nil { - return err - } - stmt, err := tx.Prepare("insert or replace into config(key, value) values(?,?)") - if err != nil { - return err - } - defer stmt.Close() - _, err = stmt.Exec("mnemonic", mnemonic) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} - -func (s *SQLiteDatastore) GetCreationDate() (time.Time, error) { - s.lock.RLock() - defer s.lock.RUnlock() - var t time.Time - stmt, err := s.db.Prepare("select value from config where key=?") - if err != nil { - return t, err - } - defer stmt.Close() - var creationDate []byte - err = stmt.QueryRow("creationDate").Scan(&creationDate) - if err != nil { - return t, err - } - return time.Parse(time.RFC3339, string(creationDate)) -} - -func (s *SQLiteDatastore) SetCreationDate(creationDate time.Time) error { - s.lock.RLock() - defer s.lock.RUnlock() - tx, err := s.db.Begin() - if err != nil { - return err - } - stmt, err := tx.Prepare("insert or replace into config(key, value) values(?,?)") - if err != nil { - return err - } - defer stmt.Close() - _, err = stmt.Exec("creationDate", creationDate.Format(time.RFC3339)) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/keys.go b/vendor/github.com/OpenBazaar/spvwallet/db/keys.go deleted file mode 100644 index d731c3f70d..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/keys.go +++ /dev/null @@ -1,239 +0,0 @@ -package db - -import ( - "database/sql" - "encoding/hex" - "errors" - "fmt" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/btcec" - "math/rand" - "strconv" - "sync" -) - -type KeysDB struct { - db *sql.DB - lock *sync.RWMutex -} - -func (k *KeysDB) Put(scriptAddress []byte, keyPath wallet.KeyPath) error { - k.lock.Lock() - defer k.lock.Unlock() - tx, err := k.db.Begin() - if err != nil { - return err - } - stmt, _ := tx.Prepare("insert into keys(scriptAddress, purpose, keyIndex, used) values(?,?,?,?)") - defer stmt.Close() - _, err = stmt.Exec(hex.EncodeToString(scriptAddress), int(keyPath.Purpose), keyPath.Index, 0) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} - -func (k *KeysDB) ImportKey(scriptAddress []byte, key *btcec.PrivateKey) error { - k.lock.Lock() - defer k.lock.Unlock() - tx, err := k.db.Begin() - if err != nil { - return err - } - index := rand.Uint32() - stmt, _ := tx.Prepare("insert into keys(scriptAddress, purpose, keyIndex, used, key) values(?,?,?,?,?)") - defer stmt.Close() - _, err = stmt.Exec(hex.EncodeToString(scriptAddress), -1, index, 1, hex.EncodeToString(key.Serialize())) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} - -func (k *KeysDB) MarkKeyAsUsed(scriptAddress []byte) error { - k.lock.Lock() - defer k.lock.Unlock() - tx, err := k.db.Begin() - if err != nil { - return err - } - stmt, err := tx.Prepare("update keys set used=1 where scriptAddress=?") - if err != nil { - tx.Rollback() - return err - } - defer stmt.Close() - _, err = stmt.Exec(hex.EncodeToString(scriptAddress)) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} - -func (k *KeysDB) GetLastKeyIndex(purpose wallet.KeyPurpose) (int, bool, error) { - k.lock.RLock() - defer k.lock.RUnlock() - - stm := "select keyIndex, used from keys where purpose=" + strconv.Itoa(int(purpose)) + " order by rowid desc limit 1" - stmt, err := k.db.Prepare(stm) - defer stmt.Close() - var index int - var usedInt int - err = stmt.QueryRow().Scan(&index, &usedInt) - if err != nil { - return 0, false, err - } - var used bool - if usedInt == 0 { - used = false - } else { - used = true - } - return index, used, nil -} - -func (k *KeysDB) GetPathForKey(scriptAddress []byte) (wallet.KeyPath, error) { - k.lock.RLock() - defer k.lock.RUnlock() - - stmt, err := k.db.Prepare("select purpose, keyIndex from keys where scriptAddress=? and purpose!=-1") - defer stmt.Close() - var purpose int - var index int - err = stmt.QueryRow(hex.EncodeToString(scriptAddress)).Scan(&purpose, &index) - if err != nil { - return wallet.KeyPath{}, errors.New("Key not found") - } - p := wallet.KeyPath{ - Purpose: wallet.KeyPurpose(purpose), - Index: index, - } - return p, nil -} - -func (k *KeysDB) GetKey(scriptAddress []byte) (*btcec.PrivateKey, error) { - k.lock.RLock() - defer k.lock.RUnlock() - - stmt, err := k.db.Prepare("select key from keys where scriptAddress=? and purpose=-1") - defer stmt.Close() - var keyHex string - err = stmt.QueryRow(hex.EncodeToString(scriptAddress)).Scan(&keyHex) - if err != nil { - return nil, errors.New("Key not found") - } - keyBytes, err := hex.DecodeString(keyHex) - if err != nil { - return nil, err - } - key, _ := btcec.PrivKeyFromBytes(btcec.S256(), keyBytes) - return key, nil -} - -func (k *KeysDB) GetImported() ([]*btcec.PrivateKey, error) { - k.lock.RLock() - defer k.lock.RUnlock() - var ret []*btcec.PrivateKey - stm := "select key from keys where purpose=-1" - rows, err := k.db.Query(stm) - if err != nil { - return ret, err - } - defer rows.Close() - for rows.Next() { - var keyHex []byte - err = rows.Scan(&keyHex) - if err != nil { - return ret, err - } - keyBytes, err := hex.DecodeString(string(keyHex)) - if err != nil { - return ret, err - } - priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), keyBytes) - ret = append(ret, priv) - } - return ret, nil -} - -func (k *KeysDB) GetUnused(purpose wallet.KeyPurpose) ([]int, error) { - k.lock.RLock() - defer k.lock.RUnlock() - var ret []int - stm := "select keyIndex from keys where purpose=" + strconv.Itoa(int(purpose)) + " and used=0 order by rowid asc" - rows, err := k.db.Query(stm) - if err != nil { - return ret, err - } - defer rows.Close() - for rows.Next() { - var index int - err = rows.Scan(&index) - if err != nil { - return ret, err - } - ret = append(ret, index) - } - return ret, nil -} - -func (k *KeysDB) GetAll() ([]wallet.KeyPath, error) { - k.lock.RLock() - defer k.lock.RUnlock() - var ret []wallet.KeyPath - stm := "select purpose, keyIndex from keys" - rows, err := k.db.Query(stm) - defer rows.Close() - if err != nil { - fmt.Println(err) - return ret, err - } - for rows.Next() { - var purpose int - var index int - if err := rows.Scan(&purpose, &index); err != nil { - fmt.Println(err) - } - p := wallet.KeyPath{ - Purpose: wallet.KeyPurpose(purpose), - Index: index, - } - ret = append(ret, p) - } - return ret, nil -} - -func (k *KeysDB) GetLookaheadWindows() map[wallet.KeyPurpose]int { - k.lock.RLock() - defer k.lock.RUnlock() - windows := make(map[wallet.KeyPurpose]int) - for i := 0; i < 2; i++ { - stm := "select used from keys where purpose=" + strconv.Itoa(i) + " order by rowid desc" - rows, err := k.db.Query(stm) - if err != nil { - continue - } - var unusedCount int - for rows.Next() { - var used int - if err := rows.Scan(&used); err != nil { - used = 1 - } - if used == 0 { - unusedCount++ - } else { - break - } - } - purpose := wallet.KeyPurpose(i) - windows[purpose] = unusedCount - rows.Close() - } - return windows -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/keys_test.go b/vendor/github.com/OpenBazaar/spvwallet/db/keys_test.go deleted file mode 100644 index ef22551cd4..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/keys_test.go +++ /dev/null @@ -1,283 +0,0 @@ -package db - -import ( - "bytes" - "crypto/rand" - "database/sql" - "encoding/hex" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/btcec" - "sync" - "testing" -) - -var kdb KeysDB - -func init() { - conn, _ := sql.Open("sqlite3", ":memory:") - initDatabaseTables(conn) - kdb = KeysDB{ - db: conn, - lock: new(sync.RWMutex), - } -} - -func TestGetAll(t *testing.T) { - for i := 0; i < 100; i++ { - b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, i}) - if err != nil { - t.Error(err) - } - } - all, err := kdb.GetAll() - if err != nil || len(all) != 100 { - t.Error("Failed to fetch all keys") - } -} - -func TestPutKey(t *testing.T) { - b := make([]byte, 32) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 0}) - if err != nil { - t.Error(err) - } - stmt, _ := kdb.db.Prepare("select scriptAddress, purpose, keyIndex, used from keys where scriptAddress=?") - defer stmt.Close() - - var scriptAddress string - var purpose int - var index int - var used int - err = stmt.QueryRow(hex.EncodeToString(b)).Scan(&scriptAddress, &purpose, &index, &used) - if err != nil { - t.Error(err) - } - if scriptAddress != hex.EncodeToString(b) { - t.Errorf(`Expected %s got %s`, hex.EncodeToString(b), scriptAddress) - } - if purpose != 0 { - t.Errorf(`Expected 0 got %d`, purpose) - } - if index != 0 { - t.Errorf(`Expected 0 got %d`, index) - } - if used != 0 { - t.Errorf(`Expected 0 got %s`, used) - } -} - -func TestKeysDB_GetImported(t *testing.T) { - key, err := btcec.NewPrivateKey(btcec.S256()) - if err != nil { - t.Error(err) - } - err = kdb.ImportKey([]byte("fsdfa"), key) - if err != nil { - t.Error(err) - } - - keys, err := kdb.GetImported() - if err != nil { - t.Error(err) - } - if len(keys) != 1 { - t.Error("Failed to return imported key") - } - if !bytes.Equal(key.Serialize(), keys[0].Serialize()) { - t.Error("Returned incorrect key") - } -} - -func TestImportKey(t *testing.T) { - key, err := btcec.NewPrivateKey(btcec.S256()) - if err != nil { - t.Error(err) - } - var b []byte - for i := 0; i < 32; i++ { - b = append(b, 0xff) - } - err = kdb.ImportKey(b, key) - if err != nil { - t.Error(err) - } - stmt, _ := kdb.db.Prepare("select scriptAddress, purpose, used, key from keys where scriptAddress=?") - defer stmt.Close() - - var scriptAddress string - var purpose int - var used int - var keyHex string - err = stmt.QueryRow(hex.EncodeToString(b)).Scan(&scriptAddress, &purpose, &used, &keyHex) - if err != nil { - t.Error(err) - } - if scriptAddress != hex.EncodeToString(b) { - t.Errorf(`Expected %s got %s`, hex.EncodeToString(b), scriptAddress) - } - if purpose != -1 { - t.Errorf(`Expected -1 got %d`, purpose) - } - if used != 1 { - t.Errorf(`Expected 0 got %d`, used) - } - keyBytes, err := hex.DecodeString(keyHex) - if err != nil { - t.Error(err) - } - if !bytes.Equal(key.Serialize(), keyBytes) { - t.Errorf(`Expected %s got %s`, hex.EncodeToString(b), hex.EncodeToString(keyBytes)) - } -} - -func TestPutDuplicateKey(t *testing.T) { - b := make([]byte, 32) - kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 0}) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 0}) - if err == nil { - t.Error("Expected duplicate key error") - } -} - -func TestMarkKeyAsUsed(t *testing.T) { - b := make([]byte, 33) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 0}) - if err != nil { - t.Error(err) - } - err = kdb.MarkKeyAsUsed(b) - if err != nil { - t.Error(err) - } - stmt, _ := kdb.db.Prepare("select scriptAddress, purpose, keyIndex, used from keys where scriptAddress=?") - defer stmt.Close() - - var scriptAddress string - var purpose int - var index int - var used int - err = stmt.QueryRow(hex.EncodeToString(b)).Scan(&scriptAddress, &purpose, &index, &used) - if err != nil { - t.Error(err) - } - if used != 1 { - t.Errorf(`Expected 1 got %s`, used) - } -} - -func TestGetLastKeyIndex(t *testing.T) { - var last []byte - for i := 0; i < 100; i++ { - b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, i}) - if err != nil { - t.Error(err) - } - last = b - } - idx, used, err := kdb.GetLastKeyIndex(wallet.EXTERNAL) - if err != nil || idx != 99 || used != false { - t.Error("Failed to fetch correct last index") - } - kdb.MarkKeyAsUsed(last) - _, used, err = kdb.GetLastKeyIndex(wallet.EXTERNAL) - if err != nil || used != true { - t.Error("Failed to fetch correct last index") - } -} - -func TestGetPathForKey(t *testing.T) { - b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, 15}) - if err != nil { - t.Error(err) - } - path, err := kdb.GetPathForKey(b) - if err != nil { - t.Error(err) - } - if path.Index != 15 || path.Purpose != wallet.EXTERNAL { - t.Error("Returned incorrect key path") - } -} - -func TestGetKey(t *testing.T) { - key, err := btcec.NewPrivateKey(btcec.S256()) - if err != nil { - t.Error(err) - } - var b []byte - for i := 0; i < 32; i++ { - b = append(b, 0xee) - } - err = kdb.ImportKey(b, key) - if err != nil { - t.Error(err) - } - k, err := kdb.GetKey(b) - if err != nil { - t.Error(err) - } - if !bytes.Equal(key.Serialize(), k.Serialize()) { - t.Error("Failed to return imported key") - } -} - -func TestKeyNotFound(t *testing.T) { - b := make([]byte, 32) - rand.Read(b) - _, err := kdb.GetPathForKey(b) - if err == nil { - t.Error("Return key when it shouldn't have") - } -} - -func TestGetUnsed(t *testing.T) { - for i := 0; i < 100; i++ { - b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.INTERNAL, i}) - if err != nil { - t.Error(err) - } - } - idx, err := kdb.GetUnused(wallet.INTERNAL) - if err != nil { - t.Error("Failed to fetch correct unused") - } - if len(idx) != 100 { - t.Error("Failed to fetch correct unused") - } -} - -func TestGetLookaheadWindows(t *testing.T) { - for i := 0; i < 100; i++ { - b := make([]byte, 32) - rand.Read(b) - err := kdb.Put(b, wallet.KeyPath{wallet.EXTERNAL, i}) - if err != nil { - t.Error(err) - } - if i < 50 { - kdb.MarkKeyAsUsed(b) - } - b = make([]byte, 32) - rand.Read(b) - err = kdb.Put(b, wallet.KeyPath{wallet.INTERNAL, i}) - if err != nil { - t.Error(err) - } - if i < 50 { - kdb.MarkKeyAsUsed(b) - } - } - windows := kdb.GetLookaheadWindows() - if windows[wallet.EXTERNAL] != 50 || windows[wallet.INTERNAL] != 50 { - t.Error("Fetched incorrect lookahead windows") - } - -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/stxo.go b/vendor/github.com/OpenBazaar/spvwallet/db/stxo.go deleted file mode 100644 index 43adc50877..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/stxo.go +++ /dev/null @@ -1,113 +0,0 @@ -package db - -import ( - "database/sql" - "encoding/hex" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "strconv" - "strings" - "sync" -) - -type StxoDB struct { - db *sql.DB - lock *sync.RWMutex -} - -func (s *StxoDB) Put(stxo wallet.Stxo) error { - s.lock.Lock() - defer s.lock.Unlock() - tx, _ := s.db.Begin() - stmt, err := tx.Prepare("insert or replace into stxos(outpoint, value, height, scriptPubKey, watchOnly, spendHeight, spendTxid) values(?,?,?,?,?,?,?)") - defer stmt.Close() - if err != nil { - tx.Rollback() - return err - } - watchOnly := 0 - if stxo.Utxo.WatchOnly { - watchOnly = 1 - } - outpoint := stxo.Utxo.Op.Hash.String() + ":" + strconv.Itoa(int(stxo.Utxo.Op.Index)) - _, err = stmt.Exec(outpoint, int(stxo.Utxo.Value), int(stxo.Utxo.AtHeight), hex.EncodeToString(stxo.Utxo.ScriptPubkey), watchOnly, int(stxo.SpendHeight), stxo.SpendTxid.String()) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} - -func (s *StxoDB) GetAll() ([]wallet.Stxo, error) { - s.lock.RLock() - defer s.lock.RUnlock() - var ret []wallet.Stxo - stm := "select outpoint, value, height, scriptPubKey, watchOnly, spendHeight, spendTxid from stxos" - rows, err := s.db.Query(stm) - defer rows.Close() - if err != nil { - return ret, err - } - for rows.Next() { - var outpoint string - var value int - var height int - var scriptPubKey string - var watchOnlyInt int - var spendHeight int - var spendTxid string - if err := rows.Scan(&outpoint, &value, &height, &scriptPubKey, &watchOnlyInt, &spendHeight, &spendTxid); err != nil { - continue - } - s := strings.Split(outpoint, ":") - if err != nil { - continue - } - shaHash, err := chainhash.NewHashFromStr(s[0]) - if err != nil { - continue - } - index, err := strconv.Atoi(s[1]) - if err != nil { - continue - } - watchOnly := false - if watchOnlyInt > 0 { - watchOnly = true - } - scriptBytes, err := hex.DecodeString(scriptPubKey) - if err != nil { - continue - } - spentHash, err := chainhash.NewHashFromStr(spendTxid) - if err != nil { - continue - } - utxo := wallet.Utxo{ - Op: *wire.NewOutPoint(shaHash, uint32(index)), - AtHeight: int32(height), - Value: int64(value), - ScriptPubkey: scriptBytes, - WatchOnly: watchOnly, - } - ret = append(ret, wallet.Stxo{ - Utxo: utxo, - SpendHeight: int32(spendHeight), - SpendTxid: *spentHash, - }) - } - return ret, nil -} - -func (s *StxoDB) Delete(stxo wallet.Stxo) error { - s.lock.Lock() - defer s.lock.Unlock() - outpoint := stxo.Utxo.Op.Hash.String() + ":" + strconv.Itoa(int(stxo.Utxo.Op.Index)) - _, err := s.db.Exec("delete from stxos where outpoint=?", outpoint) - if err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/stxo_test.go b/vendor/github.com/OpenBazaar/spvwallet/db/stxo_test.go deleted file mode 100644 index 9075cf9361..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/stxo_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package db - -import ( - "bytes" - "database/sql" - "encoding/hex" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "strconv" - "sync" - "testing" -) - -var sxdb StxoDB -var stxo wallet.Stxo - -func init() { - conn, _ := sql.Open("sqlite3", ":memory:") - initDatabaseTables(conn) - sxdb = StxoDB{ - db: conn, - lock: new(sync.RWMutex), - } - sh1, _ := chainhash.NewHashFromStr("e941e1c32b3dd1a68edc3af9f7fe711f35aaca60f758c2dd49561e45ca2c41c0") - sh2, _ := chainhash.NewHashFromStr("82998e18760a5f6e5573cd789269e7853e3ebaba07a8df0929badd69dc644c5f") - outpoint := wire.NewOutPoint(sh1, 0) - utxo := wallet.Utxo{ - Op: *outpoint, - AtHeight: 300000, - Value: 100000000, - ScriptPubkey: []byte("scriptpubkey"), - WatchOnly: false, - } - stxo = wallet.Stxo{ - Utxo: utxo, - SpendHeight: 300100, - SpendTxid: *sh2, - } -} - -func TestStxoPut(t *testing.T) { - err := sxdb.Put(stxo) - if err != nil { - t.Error(err) - } - stmt, _ := sxdb.db.Prepare("select outpoint, value, height, watchOnly, scriptPubKey, spendHeight, spendTxid from stxos where outpoint=?") - defer stmt.Close() - - var outpoint string - var value int - var height int - var scriptPubkey string - var spendHeight int - var spendTxid string - var watchOnly int - o := stxo.Utxo.Op.Hash.String() + ":" + strconv.Itoa(int(stxo.Utxo.Op.Index)) - err = stmt.QueryRow(o).Scan(&outpoint, &value, &height, &watchOnly, &scriptPubkey, &spendHeight, &spendTxid) - if err != nil { - t.Error(err) - } - if outpoint != o { - t.Error("Stxo db returned wrong outpoint") - } - if value != int(stxo.Utxo.Value) { - t.Error("Stxo db returned wrong value") - } - if height != int(stxo.Utxo.AtHeight) { - t.Error("Stxo db returned wrong height") - } - if scriptPubkey != hex.EncodeToString(stxo.Utxo.ScriptPubkey) { - t.Error("Stxo db returned wrong scriptPubKey") - } - if spendHeight != int(stxo.SpendHeight) { - t.Error("Stxo db returned wrong spend height") - } - if spendTxid != stxo.SpendTxid.String() { - t.Error("Stxo db returned wrong spend txid") - } - if watchOnly != 0 { - t.Error("Stxo db returned wrong watch only bool") - } -} - -func TestStxoGetAll(t *testing.T) { - err := sxdb.Put(stxo) - if err != nil { - t.Error(err) - } - stxos, err := sxdb.GetAll() - if err != nil { - t.Error(err) - } - if stxos[0].Utxo.Op.Hash.String() != stxo.Utxo.Op.Hash.String() { - t.Error("Stxo db returned wrong outpoint hash") - } - if stxos[0].Utxo.Op.Index != stxo.Utxo.Op.Index { - t.Error("Stxo db returned wrong outpoint index") - } - if stxos[0].Utxo.Value != stxo.Utxo.Value { - t.Error("Stxo db returned wrong value") - } - if stxos[0].Utxo.AtHeight != stxo.Utxo.AtHeight { - t.Error("Stxo db returned wrong height") - } - if !bytes.Equal(stxos[0].Utxo.ScriptPubkey, stxo.Utxo.ScriptPubkey) { - t.Error("Stxo db returned wrong scriptPubKey") - } - if stxos[0].SpendHeight != stxo.SpendHeight { - t.Error("Stxo db returned wrong spend height") - } - if stxos[0].SpendTxid.String() != stxo.SpendTxid.String() { - t.Error("Stxo db returned wrong spend txid") - } - if stxos[0].Utxo.WatchOnly != stxo.Utxo.WatchOnly { - t.Error("Stxo db returned wrong watch only bool") - } -} - -func TestDeleteStxo(t *testing.T) { - err := sxdb.Put(stxo) - if err != nil { - t.Error(err) - } - err = sxdb.Delete(stxo) - if err != nil { - t.Error(err) - } - stxos, err := sxdb.GetAll() - if err != nil { - t.Error(err) - } - if len(stxos) != 0 { - t.Error("Stxo db delete failed") - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/txns.go b/vendor/github.com/OpenBazaar/spvwallet/db/txns.go deleted file mode 100644 index 6408dcef8b..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/txns.go +++ /dev/null @@ -1,152 +0,0 @@ -package db - -import ( - "bytes" - "database/sql" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "sync" - "time" -) - -type TxnsDB struct { - db *sql.DB - lock *sync.RWMutex -} - -func (t *TxnsDB) Put(txn []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error { - t.lock.Lock() - defer t.lock.Unlock() - tx, err := t.db.Begin() - if err != nil { - return err - } - stmt, err := tx.Prepare("insert or replace into txns(txid, value, height, timestamp, watchOnly, tx) values(?,?,?,?,?,?)") - defer stmt.Close() - if err != nil { - tx.Rollback() - return err - } - watchOnlyInt := 0 - if watchOnly { - watchOnlyInt = 1 - } - _, err = stmt.Exec(txid, value, height, int(timestamp.Unix()), watchOnlyInt, txn) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} - -func (t *TxnsDB) Get(txid chainhash.Hash) (wallet.Txn, error) { - t.lock.RLock() - defer t.lock.RUnlock() - var txn wallet.Txn - stmt, err := t.db.Prepare("select tx, value, height, timestamp, watchOnly from txns where txid=?") - if err != nil { - return txn, err - } - defer stmt.Close() - var ret []byte - var value int - var height int - var timestamp int - var watchOnlyInt int - err = stmt.QueryRow(txid.String()).Scan(&ret, &value, &height, ×tamp, &watchOnlyInt) - if err != nil { - return txn, err - } - r := bytes.NewReader(ret) - msgTx := wire.NewMsgTx(1) - msgTx.BtcDecode(r, 1, wire.WitnessEncoding) - watchOnly := false - if watchOnlyInt > 0 { - watchOnly = true - } - txn = wallet.Txn{ - Txid: msgTx.TxHash().String(), - Value: int64(value), - Height: int32(height), - Timestamp: time.Unix(int64(timestamp), 0), - WatchOnly: watchOnly, - Bytes: ret, - } - return txn, nil -} - -func (t *TxnsDB) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) { - t.lock.RLock() - defer t.lock.RUnlock() - var ret []wallet.Txn - stm := "select tx, value, height, timestamp, watchOnly from txns" - rows, err := t.db.Query(stm) - if err != nil { - return ret, err - } - defer rows.Close() - for rows.Next() { - var tx []byte - var value int - var height int - var timestamp int - var watchOnlyInt int - if err := rows.Scan(&tx, &value, &height, ×tamp, &watchOnlyInt); err != nil { - continue - } - r := bytes.NewReader(tx) - msgTx := wire.NewMsgTx(1) - msgTx.BtcDecode(r, 1, wire.WitnessEncoding) - watchOnly := false - if watchOnlyInt > 0 { - if !includeWatchOnly { - continue - } - watchOnly = true - } - - txn := wallet.Txn{ - Txid: msgTx.TxHash().String(), - Value: int64(value), - Height: int32(height), - Timestamp: time.Unix(int64(timestamp), 0), - WatchOnly: watchOnly, - Bytes: tx, - } - ret = append(ret, txn) - } - return ret, nil -} - -func (t *TxnsDB) Delete(txid *chainhash.Hash) error { - t.lock.Lock() - defer t.lock.Unlock() - _, err := t.db.Exec("delete from txns where txid=?", txid.String()) - if err != nil { - return err - } - return nil -} - -func (t *TxnsDB) UpdateHeight(txid chainhash.Hash, height int, timestamp time.Time) error { - t.lock.Lock() - defer t.lock.Unlock() - tx, err := t.db.Begin() - if err != nil { - return err - } - stmt, err := tx.Prepare("update txns set height=?, timestamp=? where txid=?") - if err != nil { - return err - } - defer stmt.Close() - _, err = stmt.Exec(height, int(timestamp.Unix()), txid.String()) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/txns_test.go b/vendor/github.com/OpenBazaar/spvwallet/db/txns_test.go deleted file mode 100644 index ef37efb6a7..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/txns_test.go +++ /dev/null @@ -1,156 +0,0 @@ -package db - -import ( - "bytes" - "database/sql" - "encoding/hex" - "github.com/btcsuite/btcd/wire" - "sync" - "testing" - "time" -) - -var txdb TxnsDB - -func init() { - conn, _ := sql.Open("sqlite3", ":memory:") - initDatabaseTables(conn) - txdb = TxnsDB{ - db: conn, - lock: new(sync.RWMutex), - } -} - -func TestTxnsPut(t *testing.T) { - tx := wire.NewMsgTx(wire.TxVersion) - txHex := "01000000018b5d47ec7ae47ae2e158345069fd38a1460f436c486fd3376de24b5df8da62a201000000da00483045022100d9dfd2bd3762fbb06d4b7d37ba3544aefd2ea9913a728b90b446abf530eed03d0220066f3fe0e7a652d2383cfa3b06188301e7ff02320d3a9b32675d1b0d62e9de740147304402206271eb865f0a5f92fdb4306711c17f53c959a09d401cd375bf60904191f70e080220231368d0bacde1775505f6978486b2732179f3d3f971aa67690475763c3d96de01475221024760c9ba5fa6241da6ee8601f0266f0e0592f53735703f0feaae23eda6673ae821038cfa8e97caaafbe21455803043618440c28c501ec32d6ece6865003165a0d4d152aeffffffff0224eb1400000000001976a91411a23852c4554182abb97f811509d60015071a5188acc4c59d260000000017a9140be09225644b4cfdbb472028d8ccaf6df736025c8700000000" - raw, _ := hex.DecodeString(txHex) - r := bytes.NewReader(raw) - tx.Deserialize(r) - - err := txdb.Put(raw, tx.TxHash().String(), 5, 1, time.Now(), false) - if err != nil { - t.Error(err) - } - stmt, err := txdb.db.Prepare("select tx, value, height, watchOnly from txns where txid=?") - defer stmt.Close() - var ret []byte - var val int - var height int - var watchOnly int - err = stmt.QueryRow(tx.TxHash().String()).Scan(&ret, &val, &height, &watchOnly) - if err != nil { - t.Error(err) - } - if hex.EncodeToString(ret) != txHex { - t.Error("Txns db put failed") - } - if val != 5 { - t.Error("Txns db failed to put value") - } - if height != 1 { - t.Error("Txns db failed to put height") - } - if watchOnly != 0 { - t.Error("Txns db failed to put watchOnly") - } -} - -func TestTxnsGet(t *testing.T) { - tx := wire.NewMsgTx(wire.TxVersion) - txHex := "0100000001a8c3a68b7bec7ed52ea4a5787e5005e02adbcedb2ac1a38bb3ae499def8994db01000000d900473044022025bd8408492d4c55bc1aba94c0857ff8ce9e0030b4a2e464986411b917d83f4a022070336fb42b2b0e141f428e98e543ba0e5c0c00d7dd3142a3c01f6e4b3c0518600147304402202744e1c27d05d62502d4d2091082bf97ba92f25247e75bcc2856e1f7de472a7002206c64ff5ddf6a039375f296f620b384d9529ff658a449179c094dc588b43497b301475221024760c9ba5fa6241da6ee8601f0266f0e0592f53735703f0feaae23eda6673ae821038cfa8e97caaafbe21455803043618440c28c501ec32d6ece6865003165a0d4d152aeffffffff0249cc4a00000000001976a914429d80ec4980e5e30a9d888f92e087b9bb55f66588ac709246260000000017a9140be09225644b4cfdbb472028d8ccaf6df736025c8700000000" - raw, _ := hex.DecodeString(txHex) - r := bytes.NewReader(raw) - tx.Deserialize(r) - - now := time.Now() - - err := txdb.Put(raw, tx.TxHash().String(), 0, 1, now, false) - if err != nil { - t.Error(err) - } - txn, err := txdb.Get(tx.TxHash()) - if err != nil { - t.Error(err) - } - if tx.TxHash().String() != txn.Txid { - t.Error("Txn db get failed") - } - if txn.Height != 1 { - t.Error("Txn db failed to get height") - } - if now.Equal(txn.Timestamp) { - t.Error("Txn db failed to return correct time") - } - if txn.WatchOnly != false { - t.Error("Txns db failed to put watchOnly") - } -} - -func TestTxnsGetAll(t *testing.T) { - tx := wire.NewMsgTx(wire.TxVersion) - txHex := "0100000001867aee4c46da655cca2fa7a16c39883d34a05b1af416beda611c42bb4769f97601000000d900473044022035c352425d3dfff6df3a7196017df1e758079748b9ef022c0ced3c7e90218710022079016e302accec5d2aaf5e34676c10749767e3a34a64f80a0d0aa489027b7689014730440220612b2be46cb24bcd314827ea1682df8f82ff1fa0106cf8e9cf48b3b46ea6b0cf022052ed5da8dbc6052afd40db80cba6f87129ec6828ceffc48c9f3b6f2b855a246001475221024760c9ba5fa6241da6ee8601f0266f0e0592f53735703f0feaae23eda6673ae821038cfa8e97caaafbe21455803043618440c28c501ec32d6ece6865003165a0d4d152aeffffffff0200360500000000001976a91487dc690fcfe267307762c3d7bdfd96b357d6dde188ac87b069250000000017a9140be09225644b4cfdbb472028d8ccaf6df736025c8700000000" - raw, _ := hex.DecodeString(txHex) - r := bytes.NewReader(raw) - tx.Deserialize(r) - - err := txdb.Put(raw, tx.TxHash().String(), 1, 5, time.Now(), true) - if err != nil { - t.Error(err) - } - txns, err := txdb.GetAll(true) - if err != nil { - t.Error(err) - } - if len(txns) < 1 { - t.Error("Txns db get all failed") - } -} - -func TestDeleteTxns(t *testing.T) { - tx := wire.NewMsgTx(wire.TxVersion) - txHex := "0100000001cbfe4948ebc9113244b802a96e4940fa063c0455a16ca1f39a1e1db03837d9c701000000da004830450221008994e3dba54cb0ea23ca008d0e361b4339ee7b44b5e9101f6837e6a1a89ce044022051be859c68a547feaf60ffacc43f528cf2963c088bde33424d859274505e3f450147304402206cd4ef92cc7f2862c67810479013330fcafe4d468f1370563d4dff6be5bcbedc02207688a09163e615bc82299a29e987e1d718cb99a91d46a1ab13d18c0f6e616a1601475221024760c9ba5fa6241da6ee8601f0266f0e0592f53735703f0feaae23eda6673ae821038cfa8e97caaafbe21455803043618440c28c501ec32d6ece6865003165a0d4d152aeffffffff029ae2c700000000001976a914f72f20a739ec3c3df1a1fd7eff122d13bd5ca39188acb64784240000000017a9140be09225644b4cfdbb472028d8ccaf6df736025c8700000000" - raw, _ := hex.DecodeString(txHex) - r := bytes.NewReader(raw) - tx.Deserialize(r) - - err := txdb.Put(raw, tx.TxHash().String(), 0, 1, time.Now(), false) - if err != nil { - t.Error(err) - } - txid := tx.TxHash() - err = txdb.Delete(&txid) - if err != nil { - t.Error(err) - } - txns, err := txdb.GetAll(true) - if err != nil { - t.Error(err) - } - for _, txn := range txns { - if txn.Txid == txid.String() { - t.Error("Txns db delete failed") - } - } -} - -func TestTxnsDB_UpdateHeight(t *testing.T) { - tx := wire.NewMsgTx(wire.TxVersion) - txHex := "0100000001cbfe4948ebc9113244b802a96e4940fa063c0455a16ca1f39a1e1db03837d9c701000000da004830450221008994e3dba54cb0ea23ca008d0e361b4339ee7b44b5e9101f6837e6a1a89ce044022051be859c68a547feaf60ffacc43f528cf2963c088bde33424d859274505e3f450147304402206cd4ef92cc7f2862c67810479013330fcafe4d468f1370563d4dff6be5bcbedc02207688a09163e615bc82299a29e987e1d718cb99a91d46a1ab13d18c0f6e616a1601475221024760c9ba5fa6241da6ee8601f0266f0e0592f53735703f0feaae23eda6673ae821038cfa8e97caaafbe21455803043618440c28c501ec32d6ece6865003165a0d4d152aeffffffff029ae2c700000000001976a914f72f20a739ec3c3df1a1fd7eff122d13bd5ca39188acb64784240000000017a9140be09225644b4cfdbb472028d8ccaf6df736025c8700000000" - raw, _ := hex.DecodeString(txHex) - r := bytes.NewReader(raw) - tx.Deserialize(r) - - err := txdb.Put(raw, tx.TxHash().String(), 0, 1, time.Now(), false) - if err != nil { - t.Error(err) - } - err = txdb.UpdateHeight(tx.TxHash(), -1, time.Now()) - if err != nil { - t.Error(err) - } - txn, err := txdb.Get(tx.TxHash()) - if txn.Height != -1 { - t.Error("Txn db failed to update height") - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/utxo.go b/vendor/github.com/OpenBazaar/spvwallet/db/utxo.go deleted file mode 100644 index ac1b24a78e..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/utxo.go +++ /dev/null @@ -1,113 +0,0 @@ -package db - -import ( - "database/sql" - "encoding/hex" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "strconv" - "strings" - "sync" -) - -type UtxoDB struct { - db *sql.DB - lock *sync.RWMutex -} - -func (u *UtxoDB) Put(utxo wallet.Utxo) error { - u.lock.Lock() - defer u.lock.Unlock() - tx, _ := u.db.Begin() - stmt, err := tx.Prepare("insert or replace into utxos(outpoint, value, height, scriptPubKey, watchOnly) values(?,?,?,?,?)") - defer stmt.Close() - if err != nil { - tx.Rollback() - return err - } - outpoint := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) - watchOnly := 0 - if utxo.WatchOnly { - watchOnly = 1 - } - _, err = stmt.Exec(outpoint, int(utxo.Value), int(utxo.AtHeight), hex.EncodeToString(utxo.ScriptPubkey), watchOnly) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} - -func (u *UtxoDB) GetAll() ([]wallet.Utxo, error) { - u.lock.RLock() - defer u.lock.RUnlock() - var ret []wallet.Utxo - stm := "select outpoint, value, height, scriptPubKey, watchOnly from utxos" - rows, err := u.db.Query(stm) - defer rows.Close() - if err != nil { - return ret, err - } - for rows.Next() { - var outpoint string - var value int - var height int - var scriptPubKey string - var watchOnlyInt int - if err := rows.Scan(&outpoint, &value, &height, &scriptPubKey, &watchOnlyInt); err != nil { - continue - } - s := strings.Split(outpoint, ":") - if err != nil { - continue - } - shaHash, err := chainhash.NewHashFromStr(s[0]) - if err != nil { - continue - } - index, err := strconv.Atoi(s[1]) - if err != nil { - continue - } - scriptBytes, err := hex.DecodeString(scriptPubKey) - if err != nil { - continue - } - watchOnly := false - if watchOnlyInt == 1 { - watchOnly = true - } - ret = append(ret, wallet.Utxo{ - Op: *wire.NewOutPoint(shaHash, uint32(index)), - AtHeight: int32(height), - Value: int64(value), - ScriptPubkey: scriptBytes, - WatchOnly: watchOnly, - }) - } - return ret, nil -} - -func (u *UtxoDB) SetWatchOnly(utxo wallet.Utxo) error { - u.lock.Lock() - defer u.lock.Unlock() - outpoint := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) - _, err := u.db.Exec("update utxos set watchOnly=? where outpoint=?", 1, outpoint) - if err != nil { - return err - } - return nil -} - -func (u *UtxoDB) Delete(utxo wallet.Utxo) error { - u.lock.Lock() - defer u.lock.Unlock() - outpoint := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) - _, err := u.db.Exec("delete from utxos where outpoint=?", outpoint) - if err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/utxo_test.go b/vendor/github.com/OpenBazaar/spvwallet/db/utxo_test.go deleted file mode 100644 index d784ecff25..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/utxo_test.go +++ /dev/null @@ -1,133 +0,0 @@ -package db - -import ( - "bytes" - "database/sql" - "encoding/hex" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "strconv" - "sync" - "testing" -) - -var uxdb UtxoDB -var utxo wallet.Utxo - -func init() { - conn, _ := sql.Open("sqlite3", ":memory:") - initDatabaseTables(conn) - uxdb = UtxoDB{ - db: conn, - lock: new(sync.RWMutex), - } - sh1, _ := chainhash.NewHashFromStr("e941e1c32b3dd1a68edc3af9f7fe711f35aaca60f758c2dd49561e45ca2c41c0") - outpoint := wire.NewOutPoint(sh1, 0) - utxo = wallet.Utxo{ - Op: *outpoint, - AtHeight: 300000, - Value: 100000000, - ScriptPubkey: []byte("scriptpubkey"), - WatchOnly: false, - } -} - -func TestUtxoPut(t *testing.T) { - err := uxdb.Put(utxo) - if err != nil { - t.Error(err) - } - stmt, _ := uxdb.db.Prepare("select outpoint, value, height, scriptPubKey from utxos where outpoint=?") - defer stmt.Close() - - var outpoint string - var value int - var height int - var scriptPubkey string - o := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) - err = stmt.QueryRow(o).Scan(&outpoint, &value, &height, &scriptPubkey) - if err != nil { - t.Error(err) - } - if outpoint != o { - t.Error("Utxo db returned wrong outpoint") - } - if value != int(utxo.Value) { - t.Error("Utxo db returned wrong value") - } - if height != int(utxo.AtHeight) { - t.Error("Utxo db returned wrong height") - } - if scriptPubkey != hex.EncodeToString(utxo.ScriptPubkey) { - t.Error("Utxo db returned wrong scriptPubKey") - } -} - -func TestUtxoGetAll(t *testing.T) { - err := uxdb.Put(utxo) - if err != nil { - t.Error(err) - } - utxos, err := uxdb.GetAll() - if err != nil { - t.Error(err) - } - if utxos[0].Op.Hash.String() != utxo.Op.Hash.String() { - t.Error("Utxo db returned wrong outpoint hash") - } - if utxos[0].Op.Index != utxo.Op.Index { - t.Error("Utxo db returned wrong outpoint index") - } - if utxos[0].Value != utxo.Value { - t.Error("Utxo db returned wrong value") - } - if utxos[0].AtHeight != utxo.AtHeight { - t.Error("Utxo db returned wrong height") - } - if !bytes.Equal(utxos[0].ScriptPubkey, utxo.ScriptPubkey) { - t.Error("Utxo db returned wrong scriptPubKey") - } -} - -func TestSetWatchOnlyUtxo(t *testing.T) { - err := uxdb.Put(utxo) - if err != nil { - t.Error(err) - } - err = uxdb.SetWatchOnly(utxo) - if err != nil { - t.Error(err) - } - stmt, _ := uxdb.db.Prepare("select watchOnly from utxos where outpoint=?") - defer stmt.Close() - - var watchOnlyInt int - o := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) - err = stmt.QueryRow(o).Scan(&watchOnlyInt) - if err != nil { - t.Error(err) - } - if watchOnlyInt != 1 { - t.Error("Utxo freeze failed") - } - -} - -func TestDeleteUtxo(t *testing.T) { - err := uxdb.Put(utxo) - if err != nil { - t.Error(err) - } - err = uxdb.Delete(utxo) - if err != nil { - t.Error(err) - } - utxos, err := uxdb.GetAll() - if err != nil { - t.Error(err) - } - if len(utxos) != 0 { - t.Error("Utxo db delete failed") - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/watched_scripts.go b/vendor/github.com/OpenBazaar/spvwallet/db/watched_scripts.go deleted file mode 100644 index 10365c63af..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/watched_scripts.go +++ /dev/null @@ -1,65 +0,0 @@ -package db - -import ( - "database/sql" - "encoding/hex" - "sync" -) - -type WatchedScriptsDB struct { - db *sql.DB - lock *sync.RWMutex -} - -func (w *WatchedScriptsDB) Put(scriptPubKey []byte) error { - w.lock.Lock() - defer w.lock.Unlock() - tx, _ := w.db.Begin() - stmt, err := tx.Prepare("insert or replace into watchedScripts(scriptPubKey) values(?)") - defer stmt.Close() - if err != nil { - tx.Rollback() - return err - } - _, err = stmt.Exec(hex.EncodeToString(scriptPubKey)) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - return nil -} - -func (w *WatchedScriptsDB) GetAll() ([][]byte, error) { - w.lock.RLock() - defer w.lock.RUnlock() - var ret [][]byte - stm := "select scriptPubKey from watchedScripts" - rows, err := w.db.Query(stm) - defer rows.Close() - if err != nil { - return ret, err - } - for rows.Next() { - var scriptHex string - if err := rows.Scan(&scriptHex); err != nil { - continue - } - scriptPubKey, err := hex.DecodeString(scriptHex) - if err != nil { - continue - } - ret = append(ret, scriptPubKey) - } - return ret, nil -} - -func (w *WatchedScriptsDB) Delete(scriptPubKey []byte) error { - w.lock.Lock() - defer w.lock.Unlock() - _, err := w.db.Exec("delete from watchedScripts where scriptPubKey=?", hex.EncodeToString(scriptPubKey)) - if err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/db/watched_scripts_test.go b/vendor/github.com/OpenBazaar/spvwallet/db/watched_scripts_test.go deleted file mode 100644 index 6b9247d607..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/db/watched_scripts_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package db - -import ( - "bytes" - "database/sql" - "encoding/hex" - "sync" - "testing" -) - -var wsdb WatchedScriptsDB - -func init() { - conn, _ := sql.Open("sqlite3", ":memory:") - initDatabaseTables(conn) - wsdb = WatchedScriptsDB{ - db: conn, - lock: new(sync.RWMutex), - } -} - -func TestWatchedScriptsDB_Put(t *testing.T) { - err := wsdb.Put([]byte("test")) - if err != nil { - t.Error(err) - } - stmt, _ := wsdb.db.Prepare("select * from watchedscripts") - defer stmt.Close() - - var out string - err = stmt.QueryRow().Scan(&out) - if err != nil { - t.Error(err) - } - if hex.EncodeToString([]byte("test")) != out { - t.Error("Failed to inserted watched script into db") - } -} - -func TestWatchedScriptsDB_GetAll(t *testing.T) { - err := wsdb.Put([]byte("test")) - if err != nil { - t.Error(err) - } - err = wsdb.Put([]byte("test2")) - if err != nil { - t.Error(err) - } - scripts, err := wsdb.GetAll() - if err != nil { - t.Error(err) - } - if len(scripts) != 2 { - t.Error("Returned incorrect number of watched scripts") - } - if !bytes.Equal(scripts[0], []byte("test")) { - t.Error("Returned incorrect watched script") - } - if !bytes.Equal(scripts[1], []byte("test2")) { - t.Error("Returned incorrect watched script") - } -} - -func TestWatchedScriptsDB_Delete(t *testing.T) { - err := wsdb.Put([]byte("test")) - if err != nil { - t.Error(err) - } - err = wsdb.Delete([]byte("test")) - if err != nil { - t.Error(err) - } - scripts, err := wsdb.GetAll() - if err != nil { - t.Error(err) - } - for _, script := range scripts { - if bytes.Equal(script, []byte("test")) { - t.Error("Failed to delete watched script") - } - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/docker-compose.yml b/vendor/github.com/OpenBazaar/spvwallet/docker-compose.yml new file mode 100755 index 0000000000..cf2fccd125 --- /dev/null +++ b/vendor/github.com/OpenBazaar/spvwallet/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3' +services: + dev: + build: + context: . + dockerfile: Dockerfile.dev + volumes: + - .:/go/src/github.com/OpenBazaar/spvwallet + security_opt: + - seccomp:unconfined #req: delve for golang diff --git a/vendor/github.com/OpenBazaar/spvwallet/eight333.go b/vendor/github.com/OpenBazaar/spvwallet/eight333.go index 70ef4231d7..516195a2d4 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/eight333.go +++ b/vendor/github.com/OpenBazaar/spvwallet/eight333.go @@ -121,7 +121,7 @@ func (ws *WireService) Start() { ws.quit = make(chan struct{}) best, err := ws.chain.BestBlock() if err != nil { - log.Error(err) + log.Error(err.Error()) } log.Infof("Starting wire service at height %d", int(best.height)) out: @@ -215,7 +215,7 @@ func (ws *WireService) startSync(syncPeer *peerpkg.Peer) { ws.Rebroadcast() bestBlock, err := ws.chain.BestBlock() if err != nil { - log.Error(err) + log.Error(err.Error()) return } var bestPeer *peerpkg.Peer @@ -463,7 +463,7 @@ func (ws *WireService) handleMerkleBlockMsg(bmsg *merkleBlockMsg) { log.Warningf("Received unrequested block from peer %s", peer) return } else if err != nil { - log.Error(err) + log.Error(err.Error()) return } state.blockScore++ @@ -492,13 +492,13 @@ func (ws *WireService) handleMerkleBlockMsg(bmsg *merkleBlockMsg) { // Rollback the appropriate transactions in our database err := ws.txStore.processReorg(reorg.height) if err != nil { - log.Error(err) + log.Error(err.Error()) } // Set the reorg block as current best block in the header db // This will cause a new chain sync from the reorg point err = ws.chain.db.Put(*reorg, true) if err != nil { - log.Error(err) + log.Error(err.Error()) } // Clear request state for new sync diff --git a/vendor/github.com/OpenBazaar/spvwallet/examples/client.go b/vendor/github.com/OpenBazaar/spvwallet/examples/client.go deleted file mode 100644 index 867ebc06c8..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/examples/client.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/OpenBazaar/spvwallet" - "github.com/OpenBazaar/spvwallet/db" - "github.com/btcsuite/btcd/chaincfg" - "github.com/op/go-logging" -) - -func main() { - // Create a new config - config := spvwallet.NewDefaultConfig() - - // Make the logging a little prettier - backend := logging.NewLogBackend(os.Stdout, "", 0) - formatter := logging.MustStringFormatter(`%{color:reset}%{color}%{time:15:04:05.000} [%{shortfunc}] [%{level}] %{message}`) - stdoutFormatter := logging.NewBackendFormatter(backend, formatter) - config.Logger = logging.MultiLogger(stdoutFormatter) - - // Use testnet - config.Params = &chaincfg.TestNet3Params - - // Select wallet datastore - sqliteDatastore, _ := db.Create(config.RepoPath) - config.DB = sqliteDatastore - - // Create the wallet - wallet, err := spvwallet.NewSPVWallet(config) - if err != nil { - fmt.Println(err) - return - } - - // Start it! - wallet.Start() -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/exchangerates/bitcoinprices.go b/vendor/github.com/OpenBazaar/spvwallet/exchangerates/bitcoinprices.go index cb62fa12f3..f9abdcf599 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/exchangerates/bitcoinprices.go +++ b/vendor/github.com/OpenBazaar/spvwallet/exchangerates/bitcoinprices.go @@ -7,15 +7,15 @@ import ( "net/http" "reflect" "strconv" + "strings" "sync" "time" "github.com/op/go-logging" "golang.org/x/net/proxy" - "strings" ) -const SatoshiPerBTC = 100000000 +const SatoshiPerBTC int64 = 100000000 var log = logging.MustGetLogger("exchangeRates") @@ -103,7 +103,7 @@ func (b *BitcoinPriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, err return copy, nil } -func (b *BitcoinPriceFetcher) UnitsPerCoin() int { +func (b *BitcoinPriceFetcher) UnitsPerCoin() int64 { return SatoshiPerBTC } diff --git a/vendor/github.com/OpenBazaar/spvwallet/exchangerates/exchangerates_test.go b/vendor/github.com/OpenBazaar/spvwallet/exchangerates/exchangerates_test.go deleted file mode 100644 index 3f502188db..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/exchangerates/exchangerates_test.go +++ /dev/null @@ -1,389 +0,0 @@ -package exchangerates - -import ( - "bytes" - "encoding/json" - "io" - gonet "net" - "net/http" - "testing" - "time" -) - -func setupBitcoinPriceFetcher() (b BitcoinPriceFetcher) { - b = BitcoinPriceFetcher{ - cache: make(map[string]float64), - } - client := &http.Client{Transport: &http.Transport{Dial: gonet.Dial}, Timeout: time.Minute} - b.providers = []*ExchangeRateProvider{ - {"https://ticker.openbazaar.org/api", b.cache, client, BitcoinAverageDecoder{}}, - {"https://bitpay.com/api/rates", b.cache, client, BitPayDecoder{}}, - {"https://blockchain.info/ticker", b.cache, client, BlockchainInfoDecoder{}}, - {"https://api.bitcoincharts.com/v1/weighted_prices.json", b.cache, client, BitcoinChartsDecoder{}}, - } - return b -} - -func TestFetchCurrentRates(t *testing.T) { - b := setupBitcoinPriceFetcher() - err := b.fetchCurrentRates() - if err != nil { - t.Error("Failed to fetch bitcoin exchange rates") - } -} - -func TestGetLatestRate(t *testing.T) { - b := setupBitcoinPriceFetcher() - price, err := b.GetLatestRate("USD") - if err != nil || price == 0 { - t.Error("Incorrect return at GetLatestRate (price, err)", price, err) - } - b.cache["USD"] = 650.00 - price, ok := b.cache["USD"] - if !ok || price != 650 { - t.Error("Failed to fetch exchange rates from cache") - } - price, err = b.GetLatestRate("USD") - if err != nil || price == 650.00 { - t.Error("Incorrect return at GetLatestRate (price, err)", price, err) - } -} - -func TestGetAllRates(t *testing.T) { - b := setupBitcoinPriceFetcher() - b.cache["USD"] = 650.00 - b.cache["EUR"] = 600.00 - priceMap, err := b.GetAllRates(true) - if err != nil { - t.Error(err) - } - usd, ok := priceMap["USD"] - if !ok || usd != 650.00 { - t.Error("Failed to fetch exchange rates from cache") - } - eur, ok := priceMap["EUR"] - if !ok || eur != 600.00 { - t.Error("Failed to fetch exchange rates from cache") - } -} - -func TestGetExchangeRate(t *testing.T) { - b := setupBitcoinPriceFetcher() - b.cache["USD"] = 650.00 - r, err := b.GetExchangeRate("USD") - if err != nil { - t.Error("Failed to fetch exchange rate") - } - if r != 650.00 { - t.Error("Returned exchange rate incorrect") - } - r, err = b.GetExchangeRate("EUR") - if r != 0 || err == nil { - t.Error("Return erroneous exchange rate") - } - - // Test that currency symbols are normalized correctly - r, err = b.GetExchangeRate("usd") - if err != nil { - t.Error("Failed to fetch exchange rate") - } - if r != 650.00 { - t.Error("Returned exchange rate incorrect") - } -} - -type req struct { - io.Reader -} - -func (r *req) Close() error { - return nil -} - -func TestDecodeBitcoinAverage(t *testing.T) { - cache := make(map[string]float64) - bitcoinAverageDecoder := BitcoinAverageDecoder{} - var dataMap interface{} - - response := `{ - "AED": { - "ask": 2242.19, - "bid": 2236.61, - "last": 2239.99, - "timestamp": "Tue, 02 Aug 2016 00:20:45 -0000", - "volume_btc": 0.0, - "volume_percent": 0.0 - }, - "AFN": { - "ask": 41849.95, - "bid": 41745.86, - "last": 41808.85, - "timestamp": "Tue, 02 Aug 2016 00:20:45 -0000", - "volume_btc": 0.0, - "volume_percent": 0.0 - }, - "ALL": { - "ask": 74758.44, - "bid": 74572.49, - "last": 74685.02, - "timestamp": "Tue, 02 Aug 2016 00:20:45 -0000", - "volume_btc": 0.0, - "volume_percent": 0.0 - }, - "timestamp": "Tue, 02 Aug 2016 00:20:45 -0000" - }` - // Test valid response - r := &req{bytes.NewReader([]byte(response))} - decoder := json.NewDecoder(r) - err := decoder.Decode(&dataMap) - if err != nil { - t.Error(err) - } - err = bitcoinAverageDecoder.decode(dataMap, cache) - if err != nil { - t.Error(err) - } - // Make sure it saved to cache - if len(cache) == 0 { - t.Error("Failed to response to cache") - } - resp := `{"ZWL": { - "ask": 196806.48, - "bid": 196316.95, - "timestamp": "Tue, 02 Aug 2016 00:20:45 -0000", - "volume_btc": 0.0, - "volume_percent": 0.0 - }}` - - // Test missing JSON element - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - err = decoder.Decode(&dataMap) - if err != nil { - t.Error(err) - } - err = bitcoinAverageDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } - resp = `{ - "ask": 196806.48, - "bid": 196316.95, - "last": 196613.2, - "timestamp": "Tue, 02 Aug 2016 00:20:45 -0000", - "volume_btc": 0.0, - "volume_percent": 0.0 - }` - - // Test invalid JSON - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - err = decoder.Decode(&dataMap) - if err != nil { - t.Error(err) - } - err = bitcoinAverageDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } - - // Test decode error - r = &req{bytes.NewReader([]byte(""))} - decoder = json.NewDecoder(r) - decoder.Decode(&dataMap) - err = bitcoinAverageDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } -} - -func TestDecodeBitPay(t *testing.T) { - cache := make(map[string]float64) - bitpayDecoder := BitPayDecoder{} - var dataMap interface{} - - response := `[{"code":"BTC","name":"Bitcoin","rate":1},{"code":"USD","name":"US Dollar","rate":611.02},{"code":"EUR","name":"Eurozone Euro","rate":546.740696},{"code":"GBP","name":"Pound Sterling","rate":462.982074},{"code":"JPY","name":"Japanese Yen","rate":62479.23908}]` - // Test valid response - r := &req{bytes.NewReader([]byte(response))} - decoder := json.NewDecoder(r) - err := decoder.Decode(&dataMap) - if err != nil { - t.Error(err) - } - err = bitpayDecoder.decode(dataMap, cache) - if err != nil { - t.Error(err) - } - // Make sure it saved to cache - if len(cache) == 0 { - t.Error("Failed to response to cache") - } - - resp := `[{"code":"BTC","name":"Bitcoin"},{"code":"USD","name":"US Dollar","rate":611.02},{"code":"EUR","name":"Eurozone Euro","rate":546.740696},{"code":"GBP","name":"Pound Sterling","rate":462.982074},{"code":"JPY","name":"Japanese Yen","rate":62479.23908}]` - // Test missing JSON element - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - err = decoder.Decode(&dataMap) - if err != nil { - t.Error(err) - } - err = bitpayDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } - - resp = `[{"name":"Bitcoin","rate":611.02},{"code":"USD","name":"US Dollar","rate":611.02},{"code":"EUR","name":"Eurozone Euro","rate":546.740696},{"code":"GBP","name":"Pound Sterling","rate":462.982074},{"code":"JPY","name":"Japanese Yen","rate":62479.23908}]` - // Test missing JSON element - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - err = decoder.Decode(&dataMap) - if err != nil { - t.Error(err) - } - err = bitpayDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } - - // Test decode error - r = &req{bytes.NewReader([]byte(""))} - decoder = json.NewDecoder(r) - decoder.Decode(&dataMap) - err = bitpayDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } -} - -func TestDecodeBlockChainInfo(t *testing.T) { - cache := make(map[string]float64) - blockchainDecoder := BlockchainInfoDecoder{} - var dataMap interface{} - - response := `{"USD" : {"15m" : 612.73, "last" : 612.73, "buy" : 611.1, "sell" : 612.72, "symbol" : "$"}, - "ISK" : {"15m" : 74706.49, "last" : 74706.49, "buy" : 74507.76, "sell" : 74705.27, "symbol" : "kr"}, - "HKD" : {"15m" : 4752.76, "last" : 4752.76, "buy" : 4740.11, "sell" : 4752.68, "symbol" : "$"}}` - // Test valid response - r := &req{bytes.NewReader([]byte(response))} - decoder := json.NewDecoder(r) - err := decoder.Decode(&dataMap) - if err != nil { - t.Error(err) - } - err = blockchainDecoder.decode(dataMap, cache) - if err != nil { - t.Error(err) - } - // Make sure it saved to cache - if len(cache) == 0 { - t.Error("Failed to response to cache") - } - - resp := `{"USD" : [{"15m" : 612.73, "last" : 612.73, "buy" : 611.1, "sell" : 612.72, "symbol" : "$"}], - "ISK" : {"15m" : 74706.49, "last" : 74706.49, "buy" : 74507.76, "sell" : 74705.27, "symbol" : "kr"}, - "HKD" : {"15m" : 4752.76, "last" : 4752.76, "buy" : 4740.11, "sell" : 4752.68, "symbol" : "$"}}` - // Test missing JSON element - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - decoder.Decode(&dataMap) - err = blockchainDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } - - resp = `{"USD" : {"15m" : 612.73, "buy" : 611.1, "sell" : 612.72, "symbol" : "$"}, - "ISK" : {"15m" : 74706.49, "last" : 74706.49, "buy" : 74507.76, "sell" : 74705.27, "symbol" : "kr"}, - "HKD" : {"15m" : 4752.76, "last" : 4752.76, "buy" : 4740.11, "sell" : 4752.68, "symbol" : "$"}}` - // Test missing JSON element - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - decoder.Decode(&dataMap) - err = blockchainDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } - - // Test decode error - r = &req{bytes.NewReader([]byte(""))} - decoder = json.NewDecoder(r) - decoder.Decode(&dataMap) - err = blockchainDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } -} - -func TestDecodeBitcoinCharts(t *testing.T) { - cache := make(map[string]float64) - bitcoinChartsDecoder := BitcoinChartsDecoder{} - var dataMap interface{} - - response := `{"USD": {"7d": "642.47", "30d": "656.26", "24h": "618.68"}, "IDR": {"7d": "8473454.17", "30d": "8611783.41", "24h": "8118676.19"}, "ILS": {"7d": "2486.06", "30d": "2595.67", "24h": "2351.95"}, "GBP": {"7d": "499.01", "30d": "508.06", "24h": "479.65"}}` - // Test valid response - r := &req{bytes.NewReader([]byte(response))} - decoder := json.NewDecoder(r) - err := decoder.Decode(&dataMap) - if err != nil { - t.Error(err) - } - err = bitcoinChartsDecoder.decode(dataMap, cache) - if err != nil { - t.Error(err) - } - // Make sure it saved to cache - if len(cache) == 0 { - t.Error("Failed to response to cache") - } - - resp := `{"USD": {"7d": "642.47", "30d": "656.26"}, "IDR": {"7d": "8473454.17", "30d": "8611783.41", "24h": "8118676.19"}, "ILS": {"7d": "2486.06", "30d": "2595.67", "24h": "2351.95"}, "GBP": {"7d": "499.01", "30d": "508.06", "24h": "479.65"}}` - // Test missing JSON element - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - err = decoder.Decode(&dataMap) - if err != nil { - t.Error(err) - } - err = bitcoinChartsDecoder.decode(dataMap, cache) - if err != nil { - t.Error(err) - } - - resp = `{"USD": {"7d": "642.47", "30d": "656.26", "24h": 618.68}, "IDR": {"7d": "8473454.17", "30d": "8611783.41", "24h": "8118676.19"}, "ILS": {"7d": "2486.06", "30d": "2595.67", "24h": "2351.95"}, "GBP": {"7d": "499.01", "30d": "508.06", "24h": "479.65"}}` - // Test malformatted JSON - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - decoder.Decode(&dataMap) - err = bitcoinChartsDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } - - resp = `{"USD": {"7d": "642.47", "30d": "656.26", "24h": "asdf"}, "IDR": {"7d": "8473454.17", "30d": "8611783.41", "24h": "8118676.19"}, "ILS": {"7d": "2486.06", "30d": "2595.67", "24h": "2351.95"}, "GBP": {"7d": "499.01", "30d": "508.06", "24h": "479.65"}}` - // Test malformatted JSON - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - decoder.Decode(&dataMap) - err = bitcoinChartsDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } - - resp = `{"USD": [{"7d": "642.47", "30d": "656.26", "24h": "615.00"}], "IDR": {"7d": "8473454.17", "30d": "8611783.41", "24h": "8118676.19"}, "ILS": {"7d": "2486.06", "30d": "2595.67", "24h": "2351.95"}, "GBP": {"7d": "499.01", "30d": "508.06", "24h": "479.65"}}` - // Test malformatted JSON - r = &req{bytes.NewReader([]byte(resp))} - decoder = json.NewDecoder(r) - decoder.Decode(&dataMap) - err = bitcoinChartsDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } - - // Test decode error - r = &req{bytes.NewReader([]byte(""))} - decoder = json.NewDecoder(r) - decoder.Decode(&dataMap) - err = bitcoinChartsDecoder.decode(dataMap, cache) - if err == nil { - t.Error(err) - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/fees.go b/vendor/github.com/OpenBazaar/spvwallet/fees.go index 0e832868da..8d116e8c6b 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/fees.go +++ b/vendor/github.com/OpenBazaar/spvwallet/fees.go @@ -19,29 +19,32 @@ type feeCache struct { } type Fees struct { - Priority uint64 `json:"priority"` - Normal uint64 `json:"normal"` - Economic uint64 `json:"economic"` + Priority uint64 `json:"priority"` + Normal uint64 `json:"normal"` + Economic uint64 `json:"economic"` + SuperEconomic uint64 `json:"superEconomic"` } type FeeProvider struct { - maxFee uint64 - priorityFee uint64 - normalFee uint64 - economicFee uint64 - feeAPI string + maxFee uint64 + priorityFee uint64 + normalFee uint64 + economicFee uint64 + superEconomicFee uint64 + feeAPI string httpClient httpClient cache *feeCache } -func NewFeeProvider(maxFee, priorityFee, normalFee, economicFee uint64, feeAPI string, proxy proxy.Dialer) *FeeProvider { +func NewFeeProvider(maxFee, priorityFee, normalFee, economicFee, superEconomicFee uint64, feeAPI string, proxy proxy.Dialer) *FeeProvider { fp := FeeProvider{ maxFee: maxFee, priorityFee: priorityFee, normalFee: normalFee, economicFee: economicFee, + superEconomicFee: superEconomicFee, feeAPI: feeAPI, cache: new(feeCache), } @@ -78,14 +81,16 @@ func (fp *FeeProvider) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 { fees = fp.cache.fees } switch feeLevel { - case wallet.PRIOIRTY: - return fp.selectFee(fees.Priority, wallet.PRIOIRTY) + case wallet.PRIORITY: + return fp.selectFee(fees.Priority, wallet.PRIORITY) case wallet.NORMAL: - return fp.selectFee(fees.Normal, wallet.PRIOIRTY) + return fp.selectFee(fees.Normal, wallet.PRIORITY) case wallet.ECONOMIC: - return fp.selectFee(fees.Economic, wallet.PRIOIRTY) + return fp.selectFee(fees.Economic, wallet.PRIORITY) + case wallet.SUPER_ECONOMIC: + return fp.selectFee(fees.SuperEconomic, wallet.PRIORITY) case wallet.FEE_BUMP: - return fp.selectFee(fees.Priority, wallet.PRIOIRTY) + return fp.selectFee(fees.Priority, wallet.PRIORITY) default: return fp.normalFee } @@ -103,7 +108,7 @@ func (fp *FeeProvider) selectFee(fee uint64, feeLevel wallet.FeeLevel) uint64 { func (fp *FeeProvider) defaultFee(feeLevel wallet.FeeLevel) uint64 { switch feeLevel { - case wallet.PRIOIRTY: + case wallet.PRIORITY: return fp.priorityFee case wallet.NORMAL: return fp.normalFee diff --git a/vendor/github.com/OpenBazaar/spvwallet/fees_test.go b/vendor/github.com/OpenBazaar/spvwallet/fees_test.go deleted file mode 100644 index a9a67b41a2..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/fees_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package spvwallet - -import ( - "bytes" - "github.com/OpenBazaar/wallet-interface" - "net/http" - "testing" -) - -type ClosingBuffer struct { - *bytes.Buffer -} - -func (cb *ClosingBuffer) Close() (err error) { - return -} - -type mockHttpClient struct{} - -func (m *mockHttpClient) Get(url string) (*http.Response, error) { - data := `{"priority":450,"normal":420,"economic":390}` - cb := &ClosingBuffer{bytes.NewBufferString(data)} - resp := &http.Response{ - Body: cb, - } - return resp, nil -} - -func TestFeeProvider_GetFeePerByte(t *testing.T) { - fp := NewFeeProvider(2000, 360, 320, 280, "https://btc.fees.openbazaar.org", nil) - fp.httpClient = new(mockHttpClient) - - // Test fetch from API - if fp.GetFeePerByte(wallet.PRIOIRTY) != 450 { - t.Error("Returned incorrect fee per byte") - } - if fp.GetFeePerByte(wallet.NORMAL) != 420 { - t.Error("Returned incorrect fee per byte") - } - if fp.GetFeePerByte(wallet.ECONOMIC) != 390 { - t.Error("Returned incorrect fee per byte") - } - if fp.GetFeePerByte(wallet.FEE_BUMP) != 450 { - t.Error("Returned incorrect fee per byte") - } - - // Test return over max - fp.maxFee = 100 - if fp.GetFeePerByte(wallet.PRIOIRTY) != 100 { - t.Error("Returned incorrect fee per byte") - } - if fp.GetFeePerByte(wallet.NORMAL) != 100 { - t.Error("Returned incorrect fee per byte") - } - if fp.GetFeePerByte(wallet.ECONOMIC) != 100 { - t.Error("Returned incorrect fee per byte") - } - if fp.GetFeePerByte(wallet.FEE_BUMP) != 100 { - t.Error("Returned incorrect fee per byte") - } - - // Test no API provided - fp.feeAPI = "" - if fp.GetFeePerByte(wallet.PRIOIRTY) != 360 { - t.Error("Returned incorrect fee per byte") - } - if fp.GetFeePerByte(wallet.NORMAL) != 320 { - t.Error("Returned incorrect fee per byte") - } - if fp.GetFeePerByte(wallet.ECONOMIC) != 280 { - t.Error("Returned incorrect fee per byte") - } - if fp.GetFeePerByte(wallet.FEE_BUMP) != 360 { - t.Error("Returned incorrect fee per byte") - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/message.go b/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/message.go deleted file mode 100644 index 046b17fa52..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/message.go +++ /dev/null @@ -1,37 +0,0 @@ -package bootstrap - -import ( - "encoding/json" - - "github.com/asticode/go-astilectron" - "github.com/asticode/go-astilog" -) - -// MessageOut represents a message going out -type MessageOut struct { - Name string `json:"name"` - Payload interface{} `json:"payload"` -} - -// MessageIn represents a message going in -type MessageIn struct { - Name string `json:"name"` - Payload json.RawMessage `json:"payload"` -} - -// handleMessages handles messages -func handleMessages(w *astilectron.Window, messageHandler MessageHandler) astilectron.ListenerMessage { - return func(e *astilectron.EventMessage) (v interface{}) { - // Unmarshal message - var m MessageIn - var err error - if err = e.Unmarshal(&m); err != nil { - astilog.Errorf("Unmarshaling message %+v failed", *e) - return - } - - // Handle message - messageHandler(w, m) - return - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/options.go b/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/options.go deleted file mode 100644 index c581e4b5a5..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/options.go +++ /dev/null @@ -1,52 +0,0 @@ -package bootstrap - -import ( - "net/http" - - "github.com/OpenBazaar/spvwallet" - "github.com/asticode/go-astilectron" - "github.com/julienschmidt/httprouter" -) - -// Options represents options -type Options struct { - AdaptAstilectron AdaptAstilectron - AdaptRouter AdaptRouter - AdaptWindow AdaptWindow - AstilectronOptions astilectron.Options - BaseDirectoryPath string - CustomProvision CustomProvision - Debug bool - Homepage string - MessageHandler MessageHandler - RestoreAssets RestoreAssets - TemplateData TemplateData - WindowOptions *astilectron.WindowOptions - TrayOptions *astilectron.TrayOptions - TrayChan chan struct{} - ResizeChan chan int - TransactionChan chan uint32 - MenuItemOptions []*astilectron.MenuItemOptions - Wallet *spvwallet.SPVWallet -} - -// AdaptAstilectron is a function that adapts astilectron -type AdaptAstilectron func(a *astilectron.Astilectron) - -// AdaptRouter is a function that adapts the router -type AdaptRouter func(r *httprouter.Router) - -// AdaptWindow is a function that adapts the window -type AdaptWindow func(w *astilectron.Window) - -// CustomProvision is a function that executes custom provisioning -type CustomProvision func(baseDirectoryPath string) error - -// MessageHandler is a functions that handles messages -type MessageHandler func(w *astilectron.Window, m MessageIn) - -// RestoreAssets is a function that restores assets namely the go-bindata's RestoreAssets method -type RestoreAssets func(dir, name string) error - -// TemplateData is a function that retrieves a template's data -type TemplateData func(name string, r *http.Request, p httprouter.Params) (d interface{}, err error) diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/provisioner.go b/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/provisioner.go deleted file mode 100644 index 132fd73a30..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/provisioner.go +++ /dev/null @@ -1,38 +0,0 @@ -package bootstrap - -import ( - "os" - "path/filepath" - - "github.com/asticode/go-astilog" - "github.com/pkg/errors" -) - -// provision provisions the resources as well as the custom provision -func provision(baseDirectoryPath string, fnA RestoreAssets, fnP CustomProvision) (err error) { - // Provision resources - // TODO Handle upgrades and therefore removing the resources folder accordingly - var pr = filepath.Join(baseDirectoryPath, "resources") - if _, err = os.Stat(pr); os.IsNotExist(err) { - // Restore assets - astilog.Debugf("Restoring assets in %s", baseDirectoryPath) - if err = fnA(baseDirectoryPath, "resources"); err != nil { - err = errors.Wrapf(err, "restoring assets in %s failed", baseDirectoryPath) - return - } - } else if err != nil { - err = errors.Wrapf(err, "stating %s failed", pr) - return - } else { - astilog.Debugf("%s already exists, skipping restoring assets...", pr) - } - - // Custom provision - if fnP != nil { - if err = fnP(baseDirectoryPath); err != nil { - err = errors.Wrap(err, "custom provisioning failed") - return - } - } - return -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/run.go b/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/run.go deleted file mode 100644 index 4834669cd3..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/run.go +++ /dev/null @@ -1,151 +0,0 @@ -package bootstrap - -import ( - "github.com/asticode/go-astilectron" - "github.com/asticode/go-astilog" - "github.com/pkg/errors" - "os" - "path/filepath" -) - -func Asset(src string) ([]byte, error) { - return []byte{}, nil -} - -// Run runs the bootstrap -func Run(o Options) (err error) { - var a *astilectron.Astilectron - // Create astilectron - if a, err = astilectron.New(o.AstilectronOptions); err != nil { - return errors.Wrap(err, "creating new astilectron failed") - } - //a.SetProvisioner(astilectron.NewDisembedderProvisioner(Asset, "../vendor/astilectron-v"+astilectron.VersionAstilectron+".zip", "../vendor/electron-v"+astilectron.VersionElectron+".zip")) - defer a.Close() - a.HandleSignals() - - // Adapt astilectron - if o.AdaptAstilectron != nil { - o.AdaptAstilectron(a) - } - - // Base directory path default to executable path - if o.BaseDirectoryPath == "" { - if o.BaseDirectoryPath, err = os.Executable(); err != nil { - return errors.Wrap(err, "getting executable path failed") - } - o.BaseDirectoryPath = filepath.Dir(o.BaseDirectoryPath) - } - - // Provision - if err = provision(o.BaseDirectoryPath, o.RestoreAssets, o.CustomProvision); err != nil { - return errors.Wrap(err, "provisioning failed") - } - - // Start - if err = a.Start(); err != nil { - return errors.Wrap(err, "starting astilectron failed") - } - - // Serve or handle messages - var url string - if o.MessageHandler == nil { - var ln = serve(o.BaseDirectoryPath, o.AdaptRouter, o.TemplateData) - defer ln.Close() - url = "http://" + ln.Addr().String() + o.Homepage - } else { - url = filepath.Join(o.BaseDirectoryPath, "resources", "app", o.Homepage) - } - - // Debug - if o.Debug { - o.WindowOptions.Width = astilectron.PtrInt(*o.WindowOptions.Width + 700) - } - - // Init window - var w *astilectron.Window - if w, err = a.NewWindow(url, o.WindowOptions); err != nil { - return errors.Wrap(err, "new window failed") - } - - // Handle messages - if o.MessageHandler != nil { - w.OnMessage(handleMessages(w, o.MessageHandler)) - } - - // Create window - if err = w.Create(); err != nil { - return errors.Wrap(err, "creating window failed") - } - - a.On(astilectron.EventNameAppCmdStop, func(e astilectron.Event) (deleteListener bool) { - close(o.TrayChan) - o.Wallet.Close() - return false - }) - - go func() { - for { - select { - case n := <-o.ResizeChan: - w.Resize(621, n) - case height := <-o.TransactionChan: - w.SendMessage(MessageOut{Name: "newTransaction", Payload: height}) - } - } - }() - - // Add tray icon - if o.TrayOptions != nil { - go func() { - for range o.TrayChan { - t := a.NewTray(o.TrayOptions) - var m = t.NewMenu([]*astilectron.MenuItemOptions{ - { - Label: astilectron.PtrStr("Open"), - OnClick: func(e astilectron.Event) (deleteListener bool) { - go func() { - w.Show() - t.Destroy() - }() - - return false - }, - Enabled: astilectron.PtrBool(true), - }, - { - Label: astilectron.PtrStr("Exit"), - OnClick: func(e astilectron.Event) (deleteListener bool) { - a.Stop() - return false - }, - Enabled: astilectron.PtrBool(true), - }, - }) - - // Create the menu - if err = m.Create(); err != nil { - astilog.Fatal(errors.Wrap(err, "creating tray menu failed")) - } - if err = t.Create(); err != nil { - astilog.Fatal(errors.Wrap(err, "creating tray failed")) - } - } - }() - } - - // Adapt window - if o.AdaptWindow != nil { - o.AdaptWindow(w) - } - - // Debug - if o.Debug { - if err = w.OpenDevTools(); err != nil { - return errors.Wrap(err, "opening dev tools failed") - } - } - - // Blocking pattern - a.Wait() - return -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/server.go b/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/server.go deleted file mode 100644 index 8ebaa6ec77..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/bootstrap/server.go +++ /dev/null @@ -1,81 +0,0 @@ -package bootstrap - -import ( - "net" - "net/http" - "text/template" - - "path/filepath" - - "github.com/asticode/go-astilog" - "github.com/asticode/go-astitools/template" - "github.com/julienschmidt/httprouter" -) - -// Vars -var ( - templates *template.Template -) - -// serve initialize an HTTP server -func serve(baseDirectoryPath string, fnR AdaptRouter, fnT TemplateData) (ln net.Listener) { - // Init router - var r = httprouter.New() - - // Static files - r.ServeFiles("/static/*filepath", http.Dir(filepath.Join(baseDirectoryPath, "resources", "static"))) - - // Dynamic pages - r.GET("/templates/*page", handleTemplates(fnT)) - - // Adapt router - if fnR != nil { - fnR(r) - } - - // Parse templates - var err error - if templates, err = astitemplate.ParseDirectory(filepath.Join(baseDirectoryPath, "resources", "templates"), ".html"); err != nil { - astilog.Fatal(err) - } - - // Listen - if ln, err = net.Listen("tcp", "127.0.0.1:"); err != nil { - astilog.Fatal(err) - } - astilog.Debugf("Listening on %s", ln.Addr()) - - // Serve - go http.Serve(ln, r) - return -} - -// handleTemplate handles templates -func handleTemplates(fn TemplateData) httprouter.Handle { - return func(rw http.ResponseWriter, r *http.Request, p httprouter.Params) { - // Check if template exists - var name = p.ByName("page") + ".html" - if templates.Lookup(name) == nil { - rw.WriteHeader(http.StatusNotFound) - return - } - - // Get data - var d interface{} - var err error - if fn != nil { - if d, err = fn(name, r, p); err != nil { - astilog.Errorf("%s while retrieving data for template %s", err, name) - rw.WriteHeader(http.StatusInternalServerError) - return - } - } - - // Execute template - if err = templates.ExecuteTemplate(rw, name, d); err != nil { - astilog.Errorf("%s while handling template %s", err, name) - rw.WriteHeader(http.StatusInternalServerError) - return - } - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources.go b/vendor/github.com/OpenBazaar/spvwallet/gui/resources.go deleted file mode 100644 index f7b7aa001e..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/resources.go +++ /dev/null @@ -1,546 +0,0 @@ -// Code generated by go-bindata. -// sources: -// resources/app/block.png -// resources/app/caution.png -// resources/app/icon.png -// resources/app/index.html -// resources/app/js/qrcode.min.js -// resources/app/list.png -// resources/app/minimize.jpg -// resources/app/minimize.png -// resources/app/settings.png -// resources/app/static/css/base.css -// resources/app/static/fonts/NotoSans-Bold-webfont.ttf -// resources/app/static/fonts/NotoSans-BoldItalic-webfont.ttf -// resources/app/static/fonts/NotoSans-Italic-webfont.ttf -// resources/app/static/fonts/NotoSans-Regular-webfont.ttf -// DO NOT EDIT! - -package gui - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _resourcesAppBlockPng = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x00\xdb\x05\x24\xfa\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x2c\x00\x00\x00\x2c\x08\x06\x00\x00\x00\x1e\x84\x5a\x01\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xe1\x07\x1c\x07\x1b\x17\x96\x89\x0e\x68\x00\x00\x00\x51\x74\x45\x58\x74\x43\x6f\x6d\x6d\x65\x6e\x74\x00\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\x49\x4e\x43\x4f\x52\x53\x20\x47\x6d\x62\x48\x20\x28\x77\x77\x77\x2e\x69\x63\x6f\x6e\x65\x78\x70\x65\x72\x69\x65\x6e\x63\x65\x2e\x63\x6f\x6d\x29\x20\x2d\x20\x55\x6e\x6c\x69\x63\x65\x6e\x73\x65\x64\x20\x70\x72\x65\x76\x69\x65\x77\x20\x69\x6d\x61\x67\x65\xb6\x9a\x69\xa6\x00\x00\x05\x0b\x49\x44\x41\x54\x58\xc3\xd5\x59\x3b\x4f\x23\x57\x14\xfe\xe6\x11\x01\x0d\x9b\x86\x82\x37\xeb\x20\xaa\x0d\x42\x88\x02\x28\x80\xd2\xc2\x98\x77\x8f\x28\x70\x66\xb0\x8d\x94\xed\x16\xfe\xc3\x46\xf2\x83\x99\x40\xdc\x41\x42\x01\x08\x88\x8d\x28\x10\x02\x0a\xa0\x40\x16\xf2\x02\x05\x42\x60\xcc\xab\x01\x04\x68\x81\x22\x1e\x26\x45\x64\xd6\x9e\x97\xc7\x33\x86\x68\x8f\x64\x79\x3c\x73\xef\x9d\xcf\xdf\xfd\xce\xb9\xf7\x9c\x4b\x88\xa2\x28\x0a\x82\x00\x8a\xa2\x20\xfd\x06\x00\xad\x67\xc9\xcf\x93\x4d\xad\x8f\xd9\x71\x01\x80\x84\x82\x25\x06\x48\xbe\x56\xea\x9c\x68\xa3\xd7\xcc\x8c\x2b\x08\x02\x04\x41\x00\x21\x8a\xa2\x88\xef\xc8\xe8\xef\x05\x68\x82\xf5\xac\x32\x7c\x79\x79\x89\xb1\xb1\x31\x04\x83\x41\x00\x40\x5b\x5b\x1b\x1c\x0e\x07\x0a\x0b\x0b\xb3\x06\x3c\x2b\x80\x2f\x2e\x2e\xc0\xf3\x3c\xa6\xa7\xa7\x11\x8f\xc7\x53\xa7\x90\xa6\xd1\xdb\xdb\x0b\x86\x61\x50\x54\x54\x64\x9a\x65\x22\x39\x4a\x64\x6a\xe7\xe7\xe7\xe0\x79\x1e\x33\x33\x33\x32\xa0\x32\xed\xd1\x34\x7a\x7a\x7a\xc0\x30\x0c\x8a\x8b\x8b\x0d\x81\xa5\x28\xca\x18\xc3\xa7\xa7\xa7\xe0\x79\x1e\xb3\xb3\xb3\x32\x8f\xae\xaf\xaf\x87\xcb\xe5\x02\x00\xf8\x7c\x3e\x6c\x6d\x6d\xc9\x22\x45\x77\x77\x37\x18\x86\x41\x69\x69\xe9\xeb\x4a\x22\x16\x8b\x81\xe3\x38\xcc\xcd\xcd\xc9\x80\x36\x34\x34\xc0\xed\x76\xa3\xae\xae\x2e\xe5\xfe\xf6\xf6\x36\xbc\x5e\x2f\x36\x37\x37\x65\xc0\x3b\x3b\x3b\xc1\xb2\x2c\xca\xca\xca\xf4\x4b\x22\x1e\x8f\x8b\x89\x01\xd4\x2c\x1a\x8d\x82\xe3\x38\xcc\xcf\xcf\xe3\xf9\xf9\x39\xe5\x59\x63\x63\x23\x86\x86\x86\x50\x5b\x5b\xab\xf9\xb2\x70\x38\x0c\x8f\xc7\x83\x8d\x8d\x8d\xd4\x85\x80\x24\xd1\xd1\xd1\x01\x96\x65\x51\x51\x51\x61\x4e\x12\xc7\xc7\x47\xe0\x78\x1e\x0b\xf3\x0b\x32\xa0\x4d\x4d\x4d\x70\xb9\x5c\xa8\xa9\xa9\xc9\x68\x4a\x77\x76\x76\xe0\xf3\xf9\xb0\xbe\xbe\x2e\x03\xde\xde\xd1\x0e\x96\x61\xf0\xfe\xbd\x45\x9b\x61\x29\xbb\xc7\xc7\x47\xf0\xf9\xfc\x08\x85\x42\x32\xa0\xcd\xcd\xcd\x70\xbb\xdd\xa8\xae\xae\x36\xe5\xf1\x91\x48\x04\x5e\xaf\x17\x6b\x6b\x6b\x32\xe0\x36\x9b\x0d\x2e\x97\x53\x11\xb8\x2c\x4a\xac\xaf\xaf\x81\x61\x58\x99\xd7\xb7\xb4\xb4\x60\x68\xc8\x8d\x0f\x1f\x7e\xd6\xc2\xa1\x34\x5b\x84\x56\x87\xdd\xdd\x2f\xf0\x78\xbc\x58\x5d\x5d\x95\x45\x15\x9e\xe7\xd0\xd4\xd4\x9c\xba\x70\x48\x19\xb6\x5a\xad\x38\x3a\x3a\x4a\xe9\xec\xf8\xc5\x81\x8f\xbf\x7e\x04\x49\x92\xe9\xc0\x12\x19\xdc\x7f\xb1\xe7\xe7\x67\x7c\xfe\xed\x33\xc6\x7e\x1f\x4b\xb9\x6f\xb1\x58\xb0\xb4\xb4\xa4\x1d\x25\xaa\xaa\xaa\x14\x07\xad\xac\xac\x84\xd3\xe9\x84\xd5\x6a\x55\x73\xd0\x04\x30\x51\xc2\xae\x2a\x60\x41\x10\xb0\xb4\xb4\x04\xbf\xdf\x8f\xc3\xc3\x43\xc5\xf7\x1e\x1c\x1c\x68\x4b\x22\x19\x70\x7e\x7e\x3e\xee\xef\xef\x65\xff\xda\xe9\x74\xa2\xb5\xb5\x55\x0a\x5c\x54\x01\x28\x03\x2c\x08\x02\x16\x17\x17\xe1\xf7\xfb\x65\xb3\xa9\x06\xf8\x25\x4a\x48\x25\x91\x0c\x38\x1c\x0e\x63\x62\x72\x02\x81\x3f\x02\xb8\xbb\xbb\x4b\x19\xa8\xa2\xa2\x02\x4e\xa7\x13\x6d\x6d\x6d\x09\xe0\x69\x19\x16\x04\x01\xc1\x60\x10\x7e\xbf\x1f\xd1\x68\x54\x97\x73\x26\x03\x4e\x2b\x89\x44\xe3\x87\x87\xaf\x98\x98\x98\x44\x20\x10\xc0\xed\xed\x6d\xca\x80\xe5\xe5\xe5\x18\x1c\x1c\x44\x7b\xbb\x5d\xa4\x28\x5a\x51\xc3\x82\x10\x27\x16\x16\xfe\xc6\xe8\xe8\x28\x4e\x4e\x4e\x32\x8a\x26\x32\x49\x48\x17\x0e\x25\xc0\x09\x7b\x7c\x7c\xc0\xe4\xe4\x9f\x08\x04\x02\xb8\xb9\xb9\x49\x79\x56\x56\x56\x06\x96\x65\xc5\x8e\x8e\x76\xd0\xf4\x0f\x00\x80\x78\xfc\x1f\xcc\xcf\x2f\x10\x1c\xc7\x21\x16\x8b\x19\x0a\x7f\x8a\x1a\x4e\xc7\xb0\xd4\x9e\x9e\x1e\xf1\xd7\xd4\x14\xc6\xc7\xc6\x71\x7d\x7d\x9d\xf2\xac\xa4\xa4\x04\x2c\xcb\x02\x00\x38\x8e\xc3\xd9\xd9\x99\xa9\x78\x6d\x86\x61\x99\x53\x3d\x3d\x3d\x89\x53\x53\x53\xc4\xf8\xf8\xb8\x78\x75\x75\x25\xd5\x2d\x14\xb4\x9c\xae\x4d\x5a\xc0\x24\x45\x51\x46\xb6\x96\x22\x00\xe4\xe5\xe5\xa1\xbf\xbf\x1f\x2b\x2b\x2b\x18\x19\x19\x21\x0a\x0a\x0a\x08\x09\x00\x22\x0d\x28\x42\xa5\x9d\x6a\x4e\x47\x26\x2e\x0c\xd8\x0b\x43\xb9\xb9\xb9\xe8\xeb\xeb\xc3\xca\xca\x0a\x6c\x36\x5b\x26\x8b\x8b\x98\xf4\x49\x9b\xc0\x52\x14\x05\xda\xc8\xc6\x5d\x65\x4a\x91\x93\x93\x03\xcb\x4f\x16\x3d\xfd\x08\x05\xe0\xba\x72\x3a\x33\x49\xa8\x14\xb4\x28\x99\x76\x51\xef\x0c\xe9\x2d\x11\x64\x0a\x98\x50\xd0\x21\xa1\xa1\xcd\x74\xfd\x89\x4c\x00\x9b\x65\x58\x97\x87\x6b\xe8\x96\xc8\xf4\x85\x2f\x0c\x27\x57\x62\x0c\x48\xe2\xcd\x6b\x13\xa4\x41\xa7\x93\x7a\xb9\xd4\xe3\x45\x05\x7d\x6b\xfd\xd6\x9d\x35\x93\x06\xd9\x45\x1a\xed\x12\x3a\xdb\xbd\xaa\xd3\x99\xf1\x72\x31\x6b\x92\xd0\x5a\x38\xf6\xf7\xf7\xb5\x98\x95\xae\x52\x5a\xdf\x44\x36\xa2\x04\x45\x51\xf2\xa5\xd9\x62\xf9\x16\xf8\x3b\x3b\x3b\x31\x38\x38\x88\xbd\xbd\xbd\xff\xa5\x00\x98\x8c\x25\x51\x9e\x25\xa5\xec\x0e\x0f\x7f\x02\x4d\x7f\x53\xca\xf2\xf2\x32\xba\xba\xba\xe0\x70\x38\xb0\xbb\xfb\xe5\xed\xca\xaa\x34\x8d\xe1\xe1\x4f\x32\x1d\x93\xc9\x45\xe6\xff\xea\x0d\xcd\x08\x85\x82\xb0\xdb\xed\x29\x49\xe7\xea\xea\x2a\xba\xbb\x7b\x30\x30\x30\x80\x48\x24\xf2\x6a\x40\x49\x92\x84\xdd\x6e\x47\x28\x14\x7c\xc9\x98\x93\x37\x3f\x8a\x75\x09\x33\x85\x14\xaf\xcf\x0b\xaf\xc7\x6b\x08\x68\xba\x42\x8a\xee\xda\x5a\x26\xa5\xaa\x4c\x01\xeb\x2d\x55\xa9\x66\xcd\x66\x8b\x81\x9b\x5b\x9b\xba\x00\x67\x5a\x0c\x54\xcd\x9a\xcd\x96\x5b\xdf\xfd\xf8\x0e\x77\xb7\x77\x9a\x40\x8d\x94\x5b\xb3\x72\x64\xf0\x96\x05\x6d\xd5\x9c\xce\x88\xbd\xd5\x91\x81\x69\x86\xa5\xf6\x26\x87\x32\x4a\x0c\x4b\xb7\x9c\x4a\x27\x98\x6a\xd7\x6a\x27\x9b\xd9\x1a\x57\x35\x6b\x56\x3b\xa1\x54\x3a\xcd\x34\xb2\xeb\x32\x3a\xee\xbf\x1c\x17\x4a\xfa\x5a\x8f\xed\x8c\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\x01\x00\x00\xff\xff\x3a\x39\xcd\xd3\xdb\x05\x00\x00") - -func resourcesAppBlockPngBytes() ([]byte, error) { - return bindataRead( - _resourcesAppBlockPng, - "resources/app/block.png", - ) -} - -func resourcesAppBlockPng() (*asset, error) { - bytes, err := resourcesAppBlockPngBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/block.png", size: 1499, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppCautionPng = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x00\x6f\x06\x90\xf9\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x3c\x00\x00\x00\x3c\x08\x06\x00\x00\x00\x3a\xfc\xd9\x72\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xe1\x07\x1c\x13\x11\x22\x21\xfa\x29\x6d\x00\x00\x05\xfc\x49\x44\x41\x54\x68\xde\xed\x9b\x4d\x68\x15\x57\x14\xc7\x7f\x6f\x12\x47\x8b\xc6\x16\xc5\x8f\x85\xc8\xa5\xb8\xa9\x10\x28\x7e\xac\xaa\x30\x50\x74\xa5\x91\xa2\x85\x16\x15\xd1\x96\x82\x75\xdb\x2a\xed\xa2\x31\x2e\x5a\x22\xdd\xaa\x50\xac\x22\x51\xea\x46\xac\x1f\x2b\xa5\x70\x41\x77\x46\x29\x04\x42\x17\x56\x06\xa9\xe0\x07\x06\x4a\x14\xf5\x6a\x4c\x17\x73\x9e\xde\x0c\x73\xef\x7c\xbc\x97\xf8\x5e\xec\x1f\x1e\x21\xf3\xee\x9b\x39\xdf\xf7\xdc\x73\xce\xd4\x68\x02\xe2\x28\x44\x69\x63\xff\x1f\x02\xb3\x80\x05\xc0\x1a\x60\x35\xb0\x1c\x50\x72\x6d\xb6\x2c\x7d\x0c\x3c\x00\x62\x60\x18\xb8\x06\x5c\x95\x6b\x4f\x95\x36\xc6\xf5\x8c\xaa\xa8\xd1\x44\xc4\x51\xf8\x3e\xb0\x02\x58\x07\xac\x17\x06\x2b\xdd\x0a\xb8\x04\x5c\x06\x6e\x28\x6d\x6e\x35\x8b\xc6\x5a\x33\xb4\x1a\x47\x61\x37\xb0\x07\x58\x2b\x9a\x6c\x26\x86\x81\x2b\xc0\x21\xa5\xcd\x50\xa3\xda\xae\x55\x61\x14\x40\x69\x43\x1c\x85\x5d\xc0\x11\x60\x33\x30\xb3\xd9\x16\x63\x61\x1c\x78\x06\x9c\x01\x76\x2b\x6d\x46\x6d\x3a\x26\x85\xe1\x14\xa3\x21\xb0\x5d\x98\x9d\xc1\xd4\xe2\x39\xb0\x1b\x18\x50\xda\x98\xb2\x8c\x07\x15\x98\xed\x06\x4e\x03\x47\xdf\x00\xb3\xc8\x33\x8f\x02\xa7\xe3\x28\xec\xb6\xdc\xaa\x39\x1a\x4e\xf9\xea\x4e\xe0\x87\x06\x82\x51\xb3\x11\x03\x07\x94\x36\xc7\x8b\xfa\x76\x19\x93\xee\x05\xf6\x01\xef\x54\x20\xec\x5f\x60\x10\xb8\x09\xdc\x05\x46\xe5\x7a\x17\xb0\x18\x58\x06\xac\x02\xde\xad\x70\xef\x27\x40\xbf\xd2\xa6\xaf\x21\x0d\xd7\xa5\x15\x47\xe1\x0c\xe0\x1b\xe0\xc7\x82\x04\x8c\x01\x8f\x80\xeb\xc0\x29\xe0\xa2\xd2\xe6\x7e\x41\xa1\x2e\x04\x36\x00\x5b\x81\x95\xc0\x1c\xa0\xa3\xe0\x73\xbf\x07\x7e\x56\xda\x3c\xf7\x69\xba\x56\xc0\x8c\xbf\x2b\xc1\xec\x20\x70\x1e\x38\xa1\xb4\xb9\x9d\x15\x03\xf2\x62\x84\x75\x6d\x29\xb0\x03\xe8\x11\xed\x17\x62\x5a\x69\xf3\x93\xcf\xbc\x6b\x39\x01\xaa\x17\xd8\x5f\xe0\x41\xff\x00\x7d\xc0\x05\xa5\xcd\xbd\x46\xb2\xa3\x8c\xac\x6d\x11\xb0\x11\xe8\x05\x96\x14\xb8\xc5\x7e\xa5\x4d\x9f\x4b\xc8\x35\x8f\x29\xef\x04\x0e\x15\xf0\xd9\x73\xc0\x2e\x60\x44\x7e\x57\x69\x7f\xcc\x11\x3c\xc0\x3c\xe0\x18\xb0\xa9\x80\x4f\xef\x51\xda\x1c\xcf\x12\x78\xcd\xc1\x6c\xb7\x98\x66\x5e\x34\xde\xa7\xb4\x39\xd8\xcc\x5c\xb7\x80\x8b\xed\x05\xfa\x0b\x44\xef\x1e\xa5\xcd\x50\x9a\xae\x5a\x86\x54\x43\xd9\x67\x3f\xf1\xdc\x70\x14\xf8\x5a\x69\x73\xb2\x88\x7f\x16\x15\x84\x6f\x6d\x4a\xe3\xdb\x80\xc3\x12\xe5\x5d\x38\x0b\x7c\x06\x98\x4c\x86\x2d\xed\x7e\x21\x1b\xbb\x0f\xdb\x95\x36\x27\x4b\x68\xa8\x06\xcc\x97\x13\x54\x16\x9e\x02\x0f\x95\x36\xe3\x25\xee\xb9\x0d\x18\xc8\x59\xf6\xa5\xd2\xe6\x57\x5b\x90\x69\x0d\x77\x01\x0f\x73\x32\xa8\xd2\x66\x1c\x47\xe1\x4c\xe0\x37\xe0\x63\xe0\x65\x46\xb6\xf7\x07\xf0\xb9\xd2\xe6\x59\x93\xcd\xfb\x39\x30\x5f\x69\x33\xea\x4a\x2d\xf3\x72\xe3\x73\x4a\x9b\x83\x15\x03\xd3\x1c\x60\x2e\xf0\x5e\xea\x33\x57\xbe\x2b\x04\x3b\x95\x14\xc1\x9f\xcf\x49\x43\x8f\x4c\x90\x6e\x9d\x78\x09\x54\x9b\x73\xb6\x9e\x5d\xb4\x1e\x76\x0a\x6d\x2e\x6c\x16\xde\x88\xa3\x90\xc0\xd2\xd2\x1e\x39\xe2\xb9\xd0\x07\x8c\x4c\x66\x34\x2e\x03\x6b\xbb\x1a\x11\xda\x5c\x98\x29\xbc\xa1\xb4\x49\x4c\x5a\x2a\x15\x6b\x3d\xa9\xe6\xa0\x24\x15\x2d\xc1\xac\xcd\xb4\xd0\x73\x41\x68\x74\x65\x93\x6b\x85\xc7\x57\x3e\xbc\xc2\x53\xa9\x18\x03\xce\x2b\x6d\xee\x15\x3d\x82\x4d\xe9\x71\x29\xb1\xb8\x7b\xe2\xcb\x63\x8e\x65\xcb\x85\x47\x02\x39\xcc\xaf\xf3\xdc\xf3\x11\x70\x82\xd6\xc7\x09\xa1\xd5\x85\x75\x71\x14\x86\x81\xec\x8d\xeb\x3d\x0b\xaf\xd7\x0f\x02\xad\x64\xce\xe9\xa8\x2d\x34\x5e\xf7\x2c\x5d\x0f\xcc\x0a\xa4\x6c\xea\x4b\x21\x4f\x95\xa9\x28\xbc\x29\xb3\xb6\x69\x75\xc9\x06\x58\x10\x90\xd4\x8d\x7d\xb8\xd8\xaa\xda\x4d\x6b\xb9\x4e\xab\x07\x6b\x02\x92\x22\xb9\xb3\x52\xa1\xb4\xb9\xdf\xca\xda\x4d\x05\xaf\xfb\x52\x5d\x71\x61\x75\x80\xbf\x8e\x3c\x48\xfb\xc1\x47\xf3\xf2\x20\xc7\x7f\x6f\xb6\xba\x39\x67\x98\xf5\x4d\xdf\xb2\x7a\xd0\x72\xe1\x6e\x1b\x6a\xd8\x47\xf3\x82\x80\xd7\x8d\x2d\xd7\xb9\xb7\xdd\xe0\xa3\x79\x76\xc0\x5b\x86\x80\xa4\x65\xe9\x42\x57\x1b\xf2\xe4\xa3\xf9\x71\x40\xd2\x8b\x75\x61\x71\x1b\x32\xec\xa3\xf9\x41\x20\x05\x2f\x17\x96\xb5\x7a\x96\x95\x91\x6d\x2d\xf3\x2d\x0b\x48\xfa\xaf\x2e\xac\x6a\x43\x0d\xfb\x68\x1e\x0e\x48\xc6\x0c\x5c\x78\x37\x8e\xc2\x85\xed\xb2\x0f\x4b\xab\xc6\xd7\x9f\xba\x16\x90\xcc\x54\xf8\xb0\xa1\x49\x66\x3d\x6e\xfd\xb5\x3f\xf6\x77\x8d\x9a\xf3\x86\x9c\xa5\x57\x3b\x79\x3d\x54\xe2\xca\xb8\xb6\x02\xc7\x1a\xd4\xf2\x18\xf0\x3b\xf0\x57\x06\x73\x35\xb9\x3e\xd6\x84\x2c\x6b\xab\x4f\x2e\xc0\x83\x4e\x92\x9a\xf0\x25\xe0\x2b\xc7\xc2\x95\x71\x14\x2e\x55\xda\xdc\x6e\xa0\x57\xf4\x82\x54\xf5\xd0\xb3\xb6\xca\xfd\xeb\xcd\xb7\x95\x9e\xa5\x97\x80\xa7\x81\x8c\x06\x5d\xf6\x2c\x9c\x43\xd2\xc5\x6b\x54\xfa\x4d\x5d\x9b\x81\x1d\xf8\xcb\xbd\x97\x95\x36\xa6\x53\xfe\xb9\x21\xd1\x3a\xeb\xe4\xd4\x01\xf4\xc4\x51\xf8\x8b\xdd\x19\xac\xe0\x63\x21\xee\x11\x8b\x97\xa4\x5a\x22\x25\x83\xd5\x22\x92\xb6\xaa\xab\x97\x3c\x2c\x3c\xd2\x29\x3f\xba\x15\x47\xe1\x15\xe0\x03\xb2\x2b\x97\xab\x80\x8d\x71\x14\x1e\xad\xa8\x89\x19\xc0\xb7\xc0\x87\x0e\x1f\xfe\x13\x38\x48\xd2\x29\xa8\x12\xac\x36\x7a\xb6\xa3\x71\xe0\x4a\x7d\xd6\x2b\xb0\x7e\x74\x88\x64\x34\xc8\x85\x5e\x60\x9e\xdd\x12\x2d\x81\x0e\x92\x36\xcb\x16\xe0\xd3\xd4\x67\x8b\x7c\xd7\x51\xc5\x77\x49\xda\xa8\xbd\x9e\xa5\xcf\x84\xb7\x89\x85\x78\x19\xfa\x3a\xe3\xf9\xe1\x12\x92\xfe\x6c\xd5\x2d\xe9\x85\xe7\xfb\x17\x0d\x6c\x4d\xc7\xf1\x37\xca\xcf\xd4\x07\xda\x5e\x15\xe2\x2d\xec\xce\x31\xab\x4d\x71\x14\xee\x2d\x3b\x2a\x34\x19\x29\xa4\x58\xda\x5e\xf1\x5d\x17\xea\x33\x5d\x13\x4e\x4b\xb6\x89\x8c\xa6\x17\x64\xa0\x5f\x5a\x95\x6f\xa4\x12\x62\x09\x7b\x1b\xf9\x8d\xf1\x09\x53\x7b\x13\x18\xb6\x7c\x73\x80\xa4\x99\xec\xc3\xe1\x3a\xd3\x71\x14\x4e\x89\xa6\xed\xe7\x58\x0d\x71\x1f\xce\x02\x03\xe9\xbd\x3d\xc8\x90\xa0\x91\x20\x10\xe7\x9c\x39\x07\xea\xe6\x5d\x20\x90\x15\x99\x07\xcb\x1d\xa1\xb2\xcc\x78\x20\xe7\xdc\x1b\x03\xbd\xf6\xf8\x71\x1d\x9d\x19\x7b\x1a\x32\x1b\x71\x80\xfc\xa1\x96\xfe\x38\x0a\x3f\x22\x69\x59\x8e\xa4\x7d\x2c\xb5\xcf\xde\x01\xfe\x76\x6c\x4b\x77\x48\x35\xca\xd3\xf7\x89\xa3\x70\x9e\x04\xa8\x9e\x1c\xc1\x3d\x21\x99\xce\x1b\xca\x1d\x6a\xc9\x08\x0a\x0d\x8f\x2d\x95\xf1\x75\xc7\xbc\xd6\xe4\x8e\x2d\xa5\x73\xda\x69\x3f\x98\x96\x91\x94\x4f\xff\xd1\x43\x07\x31\xd3\x7b\xb8\xd4\x61\xde\x6f\xc7\xf8\x70\xc6\x80\x78\x1f\xfe\xc1\xb5\xa9\xc0\x59\xd9\x7a\x86\xca\x04\xc7\xb7\xee\x15\x80\xff\x5f\xf2\xa8\x70\x3c\x9b\xde\xaf\xf1\xe4\x08\x61\xfa\xbe\xa8\xe5\x2b\xbe\xb5\xf2\xab\x78\xff\x01\x77\x06\x2b\xbb\x4f\xda\x00\x4e\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\x01\x00\x00\xff\xff\xc3\x13\x6c\x93\x6f\x06\x00\x00") - -func resourcesAppCautionPngBytes() ([]byte, error) { - return bindataRead( - _resourcesAppCautionPng, - "resources/app/caution.png", - ) -} - -func resourcesAppCautionPng() (*asset, error) { - bytes, err := resourcesAppCautionPngBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/caution.png", size: 1647, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppIconPng = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x5a\x69\x3c\xd4\xef\xd7\xb6\xc4\x4c\xd9\xa6\x64\x09\x63\xc9\x58\x9b\x48\x4d\xd1\x08\x19\xeb\x90\xa5\xa1\x65\x92\x2d\xc4\x28\x51\xc6\xbe\x0c\x19\x4b\xb2\x8e\xad\x06\x59\x66\x26\x86\x8a\x6c\xd9\x0d\x2d\x42\xd4\x4c\x44\x84\x11\x31\xd9\xb3\xef\x9e\xcf\xf8\xfd\x9f\x17\x5e\xdd\xf7\xf7\xdc\xe7\x5c\xe7\x9c\xeb\x5c\xc7\x67\x9e\x58\x5b\x9a\x08\x1c\x91\x38\xc2\xc1\xc1\x21\x80\x34\x35\x44\x71\x70\x70\xe3\xd9\x7f\x40\x5e\x0e\x0e\x8e\x4d\xcb\x7d\x6d\x0e\x0e\x8e\x43\xbe\x08\xa4\x2d\x10\x08\x04\x86\x02\x5d\xe3\x38\x38\x38\x0e\xfb\x98\xa2\x7d\x39\x38\xae\x3f\x66\xff\x71\x3e\xcb\xe9\xd7\xe0\xe0\xe0\x38\x81\x35\xba\x89\xb5\xf1\xbe\x8b\x0d\x70\x7e\xe4\xc6\x11\x10\x10\xa0\x86\x79\x70\xcf\xd7\xc5\xd9\xc7\x4d\xcd\xfb\x91\x7b\xf6\xfc\x25\x09\x0e\x0e\x59\x0e\xa4\xa1\xbe\x6d\x60\xce\xec\x70\x50\xe3\x6d\xbf\xb0\xfd\x7f\xfd\x5f\x7e\x85\x9c\x3b\x0c\xe1\xe4\xe2\x7c\x74\xac\x4d\xb1\x14\x7a\xd2\x9c\xc3\x88\x53\x6c\xa3\x20\x2e\xff\x4e\xb5\x67\xf5\xad\x2a\xcb\xd7\xc5\xbb\x75\x3b\xb7\xbc\xaa\x07\x3f\x26\x0e\x7e\xbf\x95\x75\xfd\xb5\xd9\x6b\x9e\x2c\x54\x46\x89\xdf\x6b\xbc\xd1\xaf\x01\x91\xe3\xe9\x48\x2e\x67\x47\xab\xf9\x26\xdf\xc9\xf5\xf6\xdb\x10\x3c\xfe\x97\xdb\x5d\x5d\xdf\x9e\xc6\x17\xc9\x26\xd2\xa9\xe6\x67\x97\xd7\x3c\x99\xcd\x0b\x53\xdb\x17\x47\xcd\x1a\x86\x8d\x09\x64\xfd\x14\x4a\x87\x3f\xcd\xd2\x46\xaf\x06\x30\x2d\xb9\xfb\x4c\x2f\x71\xff\x52\x6e\x8b\xe6\x91\x2b\x5c\xc2\x92\xbb\xbf\x12\xf7\x2f\x09\xfe\x12\xf8\x75\xf8\xd7\xdb\x8e\xaf\x01\x5c\x01\xbd\x92\xdd\x21\xf5\x1b\x7f\x09\x10\x4c\x8f\xaa\x28\x02\x89\x52\x77\xc5\xa0\x38\xfd\x99\x63\x8f\xd7\xbf\x25\x53\xb2\x37\x07\x2c\x69\x49\xd8\xce\x5b\xcf\xab\x07\x8a\x65\x2b\x9e\x33\x6a\xa3\xf3\xfa\xfb\x25\xbb\x9f\xc4\xd1\x08\xe4\x47\x95\x20\x33\xc2\x5d\x88\x79\x9a\x44\xb9\xd4\x80\xf0\x00\xf7\xcd\xd6\x49\xf3\x91\x63\xf9\xa2\xc7\x2b\xef\x3f\x72\x02\x2f\xce\x24\x86\xff\xaa\xfa\xe7\xd8\x2f\xd9\xad\xfd\xfb\x37\x92\x10\xdf\x89\x50\x46\x06\xa7\x53\x49\xd9\x21\x4b\x3e\x7f\x87\x7c\x49\x32\xa7\x54\xf6\x21\x65\x71\xf3\xe3\xa9\xd1\x0f\xbf\x2f\x0d\x60\x3b\x95\x91\x83\xe9\xd1\xd6\x84\x18\xeb\x4c\x45\x12\xed\xc1\xa5\x0a\x96\xd7\xed\x9d\x9a\x64\xf3\x22\xe9\x8e\xc8\xea\x4b\x15\x90\x91\x43\xb7\xb9\x6f\x5f\xf3\x86\x79\x0b\x7c\x51\x44\x1e\xb9\x23\x97\x4e\x3e\xd6\xc5\x70\x0d\x61\xa6\x50\x65\x92\x01\x6b\xbf\xc7\x5c\x5e\x48\x4f\xf5\x7e\xfa\xc1\x7d\x83\xf3\xc6\x83\x1d\xdf\x26\x7a\xe3\x39\x58\x06\x84\x5a\x04\xc5\x13\x6c\xb9\xd0\x44\xdb\xc8\x76\xba\x4a\x38\x60\xd9\xe7\xf0\xed\xa3\xcf\xcd\x29\xe5\x31\x16\x66\x27\x73\x0b\x03\x1d\x3d\x54\x91\xa8\x1b\x37\x81\x0a\x54\xa7\x0a\x18\xfa\xcb\x7b\xca\x42\x41\x9e\x8c\x10\x34\xee\x0b\xa5\x80\xf1\xd2\x77\x16\x3b\x5e\x18\xa8\xe0\xe3\xd5\x44\x0f\x3d\x73\xf6\x19\x04\x73\x17\x8a\x27\xc0\xf2\x5f\xbe\xf1\x1a\x78\x6a\x62\xb5\xeb\x2f\x94\xa0\xa0\x93\x29\x55\x1b\x69\x89\xdc\x39\x5c\x2e\x51\x4b\x1e\xf1\x18\x01\x13\xcd\x08\x55\x46\xa2\x08\xa4\x04\x08\x4d\x84\x02\x92\x78\x5e\x1c\xba\x74\x54\x0b\x38\x70\x01\x96\x0e\x0b\xf0\x62\x7a\xc2\xff\x2c\x16\xc8\xf4\xff\x90\xb4\x68\xe1\x48\x25\x73\x3a\xc9\xa5\x93\x39\x6c\xb4\x71\xc9\x53\x63\x5c\x81\xd0\xdc\x19\x29\xb2\xb3\x8f\x98\x8f\x86\x90\xd8\x07\xf3\xdc\x93\x66\x28\x7e\xbe\x02\xc8\xaa\x7e\xa6\xe2\x72\xa4\x7c\x50\xed\x0e\x98\x1b\x2a\x28\xa0\x20\x90\x94\x63\x62\x75\xb4\xcc\x37\x5e\x19\xd9\xe4\x2e\x97\x4e\x96\xfe\xcc\x70\x55\x49\xce\xd9\x03\xc7\x64\xd5\x99\x9f\x7b\xa8\x94\xfc\xe2\xe4\x88\xb0\x24\x92\xd0\xd9\x8e\x50\x46\xda\xa7\x50\x3a\x9a\x2f\xdd\xde\x7b\x61\x38\x75\x04\x88\x1c\x4e\xfb\x1e\x74\xb3\xdb\x93\x69\x47\xd3\x9c\x49\x9c\x9c\x7b\x9b\x0a\xa1\x6e\xb0\x03\xe2\x43\x13\x5f\x71\x58\x12\xb7\x1e\x4a\x95\xbb\xdc\x3f\x89\x61\x4d\xd0\xfe\xd0\x70\x56\xbb\xb5\xb5\x23\x1e\x96\x9f\x8c\x09\xe4\xdf\x6f\x41\x66\x0c\x98\x2b\xe6\xac\x99\xfb\x52\xc0\x52\x6f\x72\x7b\xbb\x22\xa1\xea\x49\x08\xeb\x8a\x60\x8b\xe0\x4e\x40\x13\x7d\xc7\xcd\x47\x1a\xa9\x7a\x88\xaf\x00\xe2\xd5\xda\x7b\x7c\xb1\x80\x2b\xf0\x64\xf9\x99\x0b\xa9\xe4\x13\xb5\x2f\xa8\x8f\x80\xa1\x0d\x23\x1e\x23\x92\x39\x26\x04\x5e\x42\xb4\x35\xe1\xa5\x16\x4f\xba\xd9\xbd\xc7\x3d\xf3\x63\x06\xed\xe6\xb8\x09\xe1\x2b\x0a\xd4\xf7\x08\x65\x4c\xf1\x45\x9e\xf4\x18\x86\x17\x4d\x93\x75\x05\xd4\xe2\xe0\x0d\xeb\x3f\x34\x95\x4a\x3e\x23\x8a\x40\x1a\x28\x98\xa7\x69\x48\x5f\xe4\xb9\xc4\x36\xc8\xe9\xc3\x93\xfb\x68\xc3\x91\xb6\x3e\x9d\x78\x57\x3a\xc7\x84\xb0\xf5\x09\xa1\x4c\x5d\xa9\x80\xa1\x39\x2e\xf1\x05\x72\x2e\x5e\x71\x1a\x1a\x30\x24\xf0\x0e\x9c\xa6\x89\x45\xec\xe7\xdb\x08\xda\xb5\x06\xfd\x97\x7f\x33\x15\xf3\xb4\x4d\xda\x7e\x81\x0d\x57\x1e\x0f\x34\xce\x02\x42\x8d\x78\xf0\x67\xec\xd1\x86\x7d\x57\x01\xf9\x6c\x05\xc8\x4c\x35\x11\x6a\x31\x49\xaf\x13\x5b\xbc\xc2\xfc\xa9\x75\x38\xbd\x57\x67\x26\xa8\x56\x2a\xbc\xfd\x91\x32\x15\x0a\xc5\x13\x8e\x78\x79\x2a\x2d\x9e\xc0\x2a\x46\x7e\xe5\x14\xfd\xa8\x48\x80\x1d\xfa\xc1\xed\x48\xb6\x11\x6c\xf1\xba\x98\x6e\xeb\x2a\x8a\x40\x46\xa7\x51\x3a\x80\x8b\x30\x78\x1a\xed\x7b\xc4\xdc\x1d\x61\xa4\xc4\x9d\x77\xff\x3e\x3f\xd2\x3a\x91\x63\x42\xb8\xfb\x01\xa1\x4c\x05\x55\xc0\xa8\x9c\x4a\xdf\x9e\x1f\x7a\x21\x38\x0b\xca\x36\x25\x48\xff\xf1\x97\x56\x8b\x1d\xad\x90\x32\x53\xe5\xe2\x2b\x20\x47\x66\x50\x90\x22\x81\x47\x72\x91\xcc\xbf\x34\xcb\xb7\x4f\x20\x98\xc1\x79\xe6\xd8\xa3\x0d\x8b\xe4\x0c\x33\x09\x5b\x51\x04\x92\x5b\xc9\x3c\x2d\x2c\x72\x14\xe0\xc0\x35\x7b\x4c\xca\x84\x30\xe9\x79\x7a\x11\xc9\x74\x9c\x4e\x9c\x5c\x6d\x45\x43\xfe\x1e\x85\xe2\x09\xbc\x6d\xbd\xe7\x8f\x7e\xe5\x76\xe0\xb9\x74\x51\x2b\x09\xb2\x8a\x90\xdc\x50\x5b\xfc\x4a\xdb\x5c\x35\x5e\x6e\x65\x5e\x22\xb8\xca\xa5\x1f\x3f\x65\x9e\x66\x10\x79\x83\x4b\xfd\x53\xec\x7b\x53\x09\xe9\x00\xce\x29\x2e\x99\x32\x4d\xa2\x5e\x92\xa0\x3c\x26\x10\x0d\x54\x58\xb5\xcf\x54\x7c\x1a\x31\x5a\x70\x4e\x20\xf4\x8e\x8f\x14\x32\x7e\xcd\x85\x39\x4e\xab\x5b\x35\x5e\x7e\xc3\x3a\x43\x88\x79\x1a\x6d\x8d\x1a\x75\xc5\x3c\xe2\xcf\xc5\x30\x9f\xd3\x1e\x33\xb5\x08\x30\x0f\xe9\x43\x3d\x45\xbe\xe4\x95\x86\x55\xe3\xef\xea\x0c\xc8\x6a\x4e\xb4\x35\xca\xca\x0d\x53\x71\x28\x50\x25\xf7\x64\xe0\x65\x1f\x29\xa4\x6a\xfc\x4c\x24\x8e\x53\x17\xed\x0d\xeb\x37\x8e\x4d\xb5\x75\x10\x45\x20\xed\xb3\x28\x48\x1e\xad\x54\xcb\xc3\xa1\x6a\x67\x44\xb3\x4d\x09\x47\x4a\x79\x42\x33\x7a\x7a\x17\x4f\x8d\x78\x29\x53\x87\xa0\x78\x42\xbd\xa2\x79\x9a\x1b\xad\xeb\xef\xed\x13\x6f\x4d\xd8\x26\xb2\xfd\x68\x45\x11\xb8\x37\x9a\xc4\x96\x38\x41\x79\xaa\x14\x14\x4f\x98\x84\x9a\xa7\x5d\xa3\x49\xfe\xbd\xc2\x7d\xaf\xf5\x21\x04\x23\x1e\xca\x1d\x88\x6b\xa2\xef\x2c\xb0\x64\x09\xf1\xdd\x08\x65\xcc\xf5\x0a\x18\x95\xab\x88\xae\xf2\xb8\xfd\x50\x7b\x2a\xd9\xd9\x4f\x61\x91\x13\x6e\xa5\x3c\x0c\x02\x1b\xa3\xfe\xdd\x04\x2a\x74\x9b\x66\x2a\x0e\x7d\xbb\x28\xba\x15\xec\x54\xc6\xd4\x22\x90\x93\xfc\x68\x7a\x1c\x32\x6f\x34\x89\xef\x4c\x62\x53\x6d\xa5\x44\x11\xc8\xef\x67\xab\x65\x36\x4c\x68\x68\xda\x5a\xeb\x43\x08\x32\x7b\x5d\x76\x11\xc9\xcc\x09\x26\x6d\x2e\x33\xa1\x84\x23\x34\x84\xf2\x5f\x0d\x37\xcc\x23\xe0\x22\x2f\x5c\xac\x23\x99\xb7\x3d\x15\x62\x61\x25\x59\x1b\xd1\xf3\x62\x6c\xbd\xf0\xbd\xa9\xc4\x6d\x51\x04\x32\xf9\xac\x9f\xd7\x07\x24\x76\x8d\xdb\x8a\x3f\x49\x1e\x49\xcc\x96\xe1\x5a\x00\xf4\x2c\x0f\x1e\x41\x66\x57\x80\xcc\xb6\x5e\x43\x2d\x26\x39\x5b\xcc\xdd\x4f\xb2\x14\x96\x08\xb6\x6a\x2d\xbc\xba\x87\x42\x5f\x8d\x78\x8c\x08\x83\x8d\x19\x4e\xe5\x20\xb3\x93\xe6\x69\xe0\xc8\x7e\x0e\x01\x27\x8c\x8f\x14\x12\xe5\x3d\xcc\x1d\x2a\xb5\x61\xdd\x44\x6f\x54\x81\x27\x90\x6f\x8a\x22\x30\x71\x6e\x98\x0a\x75\x9f\x0b\x8b\x28\xa7\x70\xf6\x05\x9c\x05\xd7\xd4\xf7\x9f\xe7\x1a\xa1\xf0\x04\xb2\xb8\x28\x02\x03\xb4\x10\x69\x0d\xe0\x70\xe7\xea\x63\x07\x17\x38\xca\xbd\xd7\x38\xe2\x11\xae\x0d\x8f\x23\xef\x55\x80\xcc\x0c\x20\xe6\x69\x4d\x91\xef\xb8\xd5\xb9\x3c\xd9\xb1\x45\x4d\x69\xd3\x86\x66\x12\x27\xd7\x49\x51\xa6\xd3\x42\x7c\x05\xb0\x43\x15\xb0\x9f\xdc\x1b\xe7\x98\x0a\x34\x53\x1f\x29\x24\x83\xb9\xcd\x9b\x7b\x27\xf0\x21\x16\x84\x6c\x72\x93\x4b\x37\x83\x9a\xa7\x0d\x47\xec\x03\x1a\xa5\x16\x40\xe9\x90\xee\x5f\x37\x22\xd9\x63\x43\xc6\x18\x90\xda\x2b\x29\x8a\xa0\xe2\x2b\x60\xc8\x88\x77\x9c\x65\x87\x3e\x3d\x1e\x37\x25\xc4\x2f\x74\x61\xe3\xc7\xac\xd8\x86\xd5\xf8\x0a\x6c\x4f\xa2\x89\xb3\x5c\x8d\x22\x5a\x7c\xcf\xc4\xa4\x4c\x08\xb6\x6a\x5e\x4c\x3e\x6c\xfc\xd8\x35\xba\x33\xc4\x2f\x36\xda\x5a\x35\x12\x6a\x91\xc9\xe5\xfd\xd2\x37\x2b\xbf\xdf\xc4\x94\x10\xac\x02\xd0\xb5\x9a\xa2\x92\xfb\x8d\x62\x53\x61\x9a\xa2\x08\x2a\xed\xa5\x5a\xfa\xbe\x30\xb3\x9a\x76\x81\xed\xf5\x7b\x0a\x4f\x0e\x5f\x63\xe5\x88\x87\x83\x0c\xd8\x98\x31\x7b\x13\x48\xe1\xea\x64\x8f\x00\x0b\xda\x4c\x84\x57\xd4\xb8\x29\x21\x66\x08\xb2\x58\x46\x6b\x98\x4e\x9c\x4c\x6c\x45\x43\xba\x53\xa2\xad\x55\x53\xa0\x16\xa2\x5c\xde\x87\x7a\x78\x45\x79\xda\x53\x21\x18\x17\x61\x5a\x0b\xc7\x02\xbb\xaa\x9e\x08\xca\x63\x82\xa1\x78\x14\xa7\x2b\x06\xc5\x13\x2e\x13\x28\x56\xee\xeb\x23\x85\x24\x48\x77\xf1\x32\xe5\x69\x8e\xbd\x92\xdd\xda\x85\xef\x4d\x83\xef\x8b\x22\x30\x34\x37\xcc\x23\xae\x45\x7d\x26\x93\x05\x25\x40\xba\x69\x60\x5a\x1e\x37\xbb\x6c\xd2\x5a\xd1\x10\xaf\xc8\x68\x6b\x09\x6b\x34\xf1\x92\x60\xa0\x8c\x8f\x27\x56\x14\x49\x98\x64\x7a\x32\x67\x83\x49\x9b\xab\x2c\x59\x82\x74\x37\x42\x59\xe0\x19\xd4\xa2\x86\x7b\x44\x10\x16\x41\x67\x6a\x11\x20\x7e\x5d\x38\x4e\xef\x57\x9a\x44\xbd\x64\xc1\x93\x7f\x9d\x45\x11\x98\xcb\xae\x98\xb3\x5c\x8d\xc4\x9e\x7f\x44\x85\xb7\x18\x08\x72\xfa\xc9\x61\xe6\xc2\xdf\xdb\xd7\x1e\x06\x60\xc5\x91\xa2\x08\x8c\xac\x2b\xe6\xd1\xd9\xc5\x70\xa7\x7d\xf6\xdb\xab\xad\xc1\xcc\xaf\x11\xc9\xfd\x92\xdd\xd7\xb1\xe2\x98\x67\x68\x20\xe5\x32\x9a\x28\x65\x5a\x04\xd4\x3d\x07\x7f\x0a\x41\x72\x86\xf3\x36\x36\xff\x97\x73\xd8\x2b\x28\x1e\x15\x01\xb5\xf0\x3f\x34\x72\x78\x87\xd3\x9a\x2f\x49\x1e\x89\xaa\x52\xe7\xf2\x2e\xd1\x24\xb6\x24\x08\x9e\x14\x90\xe4\x2b\xe8\x35\x41\x13\x13\x38\x71\x86\x53\xcf\xbe\xfc\x66\x7b\x26\x40\x10\xc0\xbe\x41\x07\x5b\x35\xd1\x1b\x35\xe1\x09\x30\x28\x14\x8f\xca\x73\xc5\x2c\xdd\x66\x7a\x47\x36\x91\x2a\x4d\x09\x30\xda\x0f\x4e\x6f\x6e\x76\x4f\xef\x22\xae\x4d\x6b\xf0\x15\xf4\xba\xa0\x89\xb3\x80\x1d\x79\x9f\x50\x76\xdc\x47\x26\x1e\x31\x93\x67\x12\x27\x85\x0a\xa3\x4c\xdd\xee\xca\xa5\x07\xbb\x4e\x07\xb2\xec\x58\xa1\x59\xbe\x0e\x6c\x58\xe3\xa7\x7d\xb1\x6a\x35\x8e\x62\x60\x43\x55\x79\xbe\x82\x5e\x6e\x34\x51\x8a\x2f\xf4\xb8\x96\x2c\xdb\x6f\x05\x1f\xb1\x45\xa5\x55\xe3\xe5\x71\xba\x3e\xb9\xe2\x2d\xc8\xcc\x3e\x9d\xd2\x71\x87\x59\x16\x59\x19\x61\xc6\xfe\xb4\x73\x52\x9b\x56\xca\x66\x3c\xf6\x71\x39\xc8\xcc\x9e\x40\xe9\xf8\x4b\x1b\xe5\xee\x2a\xac\x34\x25\xd8\xde\x39\xb1\x28\x46\xdb\x9e\x4e\x9c\x74\xc5\x8a\x53\x59\x50\x3c\x43\xca\x0d\x43\xe0\x50\xf1\xb9\xc5\x76\x2a\xe6\xb3\x55\xc4\x8d\x1f\x92\xdd\x5d\xa4\x28\x53\xa3\xbb\x72\xe9\x77\x55\xcc\xd3\x54\x17\x3d\x99\x65\x11\x46\xec\x7a\x92\x30\x3e\xcd\x94\x62\xce\xad\x1a\x2f\x47\xb2\xce\xa0\x8e\xa2\x81\x14\xf4\x67\xc6\xc4\x65\xa6\x0b\x8d\x4e\x47\x43\x90\xc7\x5a\xb8\x7a\x4a\x34\x89\xa3\x71\x82\x27\x45\x12\xa3\xad\x89\x91\xec\xfe\xc5\x1d\x69\x3c\x21\x2e\x90\x24\x8f\x24\x48\xff\xb5\xa1\x49\x4e\x27\x4e\x82\xe9\xfa\xe4\xc2\x72\x90\xd9\xf7\x74\x4a\x87\x0d\xeb\xb6\xc2\x5b\x2b\xf6\xd3\x55\x46\xef\x18\x75\xdf\xf6\x7c\xe9\xfa\xe4\x93\xe5\x20\x33\xbb\x54\x4a\xc7\x1a\x2d\x24\xf2\x06\xf3\xda\x31\x02\x44\xe4\xe3\x8d\x88\xfe\x5e\xc9\xee\x51\x43\x40\x2a\xef\xf3\x68\xeb\x60\x7e\x34\x31\xe7\xf0\x0e\xb8\xdc\x97\xfd\x29\xcc\x65\x9d\xd3\x9b\x7b\xaf\x60\xc4\x63\x92\xee\x4c\xd6\x77\x95\x4b\xbf\x20\x6f\x9e\x06\x8e\xc0\x71\xbd\x90\xc9\x35\x22\x40\xba\x7f\x7a\xc2\xc5\x06\x1d\x45\xc0\x86\x12\x30\x51\x04\x46\x18\x4d\xbc\x04\xde\x80\x38\x9c\x51\x47\xa2\x9e\x27\x70\x2f\x70\xed\x95\x8c\x78\xd4\x14\xbe\x37\x8d\x6a\x43\x28\x5b\x74\x30\xc8\x82\x3b\xe7\x17\xe1\xbf\x44\xd2\x21\xd4\x57\x7b\x62\x1b\xc3\xc1\xa4\x20\x1b\x2c\x08\x03\xba\x09\x54\x90\x35\x4f\x33\x88\xf8\xca\x05\x30\x76\x4f\x85\x20\x75\x02\x34\x73\x01\x3d\x3b\x76\x58\x90\x0a\x31\xda\xda\xe0\x34\x1b\x2a\x63\xa6\x7a\xe4\x5b\x76\x75\x50\x5b\x74\xb9\x1b\x6b\x0e\xc8\xca\x30\xfe\x8e\x5c\xef\xb7\x4e\x86\xab\x26\x5c\x6c\x40\xf7\xbc\x56\x3c\x04\x19\xbf\x7c\x8a\xf9\x71\xd5\xd8\xd7\x0f\x0b\x52\x79\x1c\x6d\x6d\xa0\x62\x9e\x26\xc6\xb9\x0f\x84\x26\xf5\x9c\x44\x12\xda\xaa\x59\x97\x7c\x26\xd5\xc3\x98\x09\x31\x89\xd1\xd6\xec\x89\x3e\x17\x21\xc4\xad\x9e\xc0\x3e\xe3\xed\x31\xc2\xbe\x8c\xd6\x34\x06\xa4\x6e\x51\x24\xc0\x97\xa7\xb3\xa0\x16\x96\x1c\x6f\x68\x67\x95\x91\x84\x0b\x0b\xe2\xcc\x22\x34\xb1\x51\x0b\x1e\xd7\xab\x6e\x09\xbc\x16\x8c\x26\x7e\xe1\x1e\x11\x68\xe4\x2c\x4b\x4b\x81\x20\xbf\xfb\xaa\xe5\x2a\xa5\x6e\xd1\x4e\x64\x10\xa3\xad\x29\x99\x94\x0e\x7d\xec\x0b\x59\x7f\x1f\x36\x7c\xb6\x5a\x9a\x8c\xba\xca\x45\x00\x5d\x9f\xec\xf0\x16\x54\x92\x5e\x01\xa3\x72\xb8\x73\x2f\x70\x4e\xb2\x09\x00\xf9\xb1\xaf\xd0\x97\xc1\xca\xd5\xf5\x31\x76\x73\x95\xb3\xfd\xeb\x8a\xa9\x10\xce\x75\x91\xb6\x7a\xca\xf6\xc6\xcc\xe5\x7c\x2e\x66\x4c\x9d\x14\x65\x3a\x3c\x61\xe0\x66\xab\x8a\x26\xbe\xe2\x0a\xc7\xbb\x59\x13\x20\x7e\xfd\x74\x9a\x55\x05\x2c\x08\x89\x05\x51\xb3\x73\x40\x25\xb0\x0a\x58\xd0\xe9\x45\x4e\x27\x28\xbb\x7e\x55\xab\xad\x38\xcb\xde\x68\x12\xd1\x58\x10\xe6\x0d\x14\xaf\xda\x08\xb5\x10\xe5\x90\xe1\x0c\xd7\x64\x1f\x4a\x48\xe8\x71\x59\x96\x69\x12\x35\x8d\x00\xa9\x93\x6d\x88\x62\x44\x17\xc3\xd5\x9b\xc9\x47\xd3\x67\x57\x18\xe3\x5b\x1d\x38\xd0\xb9\x89\xbe\x73\x17\x0b\xc2\xd4\xfc\x92\xb3\x75\x76\xc3\x2c\x49\x31\x63\x6f\xf2\x2a\x20\x51\x09\x0a\xb4\x68\x34\xb1\xf1\x22\x3c\x0e\x66\x67\x09\xbc\xa6\x85\x26\xf6\x46\x04\x70\x7a\xb7\x3e\x9d\x54\x40\x32\x9c\xb4\x64\x36\x9a\x82\x49\x41\x8e\x58\x10\x46\x11\x8a\x57\x4d\xa7\x9e\x52\xd8\x13\xd0\xd2\x60\x3f\xc9\x50\x7c\xc3\xfb\xc2\xce\x1b\x86\x93\x06\x1b\x12\xd5\x92\x13\x4a\xce\x54\xc0\x2e\xc6\xf7\x70\xbd\x63\x47\x22\x50\xc8\x1d\xd1\xf5\xf2\xc7\x2d\x32\xc2\x07\x51\x8c\xf8\xcc\x98\x38\x4f\xbb\x18\x48\xc1\x43\x90\x12\xa1\x5e\xcc\x61\x9a\x36\x5b\x5b\x81\x8d\x83\xa1\xa2\x08\x81\x2a\xa8\xc5\xe4\xf7\x3a\x54\x9b\xb9\x93\x02\x12\x45\x0f\x15\x08\x7c\xc8\x56\xd5\xf0\xb8\x2a\x05\x51\x84\xc0\x2b\xa8\xc5\x5a\xa1\x2f\xe5\x43\x2b\x3b\x0e\xc2\xdd\xbf\x59\xd8\xb5\x23\x38\x51\xb0\xe1\xa0\x54\x00\xf0\x7c\x4a\x05\x2c\xe8\x82\xcf\xc5\x4c\x7d\x24\xc1\xf6\x7e\x08\x57\x69\x25\x2c\xe8\x2a\x16\x84\xf1\xcd\x01\x79\xe6\xbb\x62\x50\x05\xbe\x94\x0f\x43\x8b\x66\x87\x91\x04\x5b\xb5\x29\x0e\x1c\xca\x1b\xa6\x44\x8a\x32\x15\x7a\x0b\xf2\x74\xba\x32\xc7\x17\x2e\xa1\x25\xcf\x0e\x03\x95\x1c\x2a\x16\xa8\xdf\x44\x6f\x3c\x0f\x8f\x3b\x24\x8a\x10\x88\x83\x5a\xf8\xf3\xee\x09\x6b\x9d\xfd\xef\xf0\xfc\xdf\x59\x11\x07\x51\xb0\xe1\xa3\x58\xeb\xb1\x0a\xd8\x45\x50\xed\xa1\xae\x7c\x08\x52\x42\xf0\xf0\xa2\xfd\xc2\xa9\x5e\xd9\x72\x90\xaa\x6d\xa6\xe2\x57\x0e\x35\xae\xeb\x07\xd5\x3d\x4d\xda\xa4\x89\x55\xc0\x36\x49\x2c\x59\x89\x07\xd2\x27\xae\x3d\x83\x5a\xf4\x70\xa1\x9c\x20\x07\xc6\xf2\x85\x38\xd8\xd4\x18\xee\xfc\xa6\xb9\x12\x54\xb2\xc0\xd6\x11\x38\xee\x46\x95\x03\x30\x23\xb4\x84\x02\x91\x4d\xf4\x2f\x85\x51\x1e\xb5\x37\x81\x7d\x37\xd0\x44\x28\x87\x2e\xf7\x25\xcd\xff\x0e\xeb\x80\x5a\xd5\x23\x1e\x23\xd2\x60\xc3\xf7\xef\x11\xc5\xcd\x1d\x0c\x57\x31\x26\x17\x73\x91\xcd\xd6\x48\xee\x69\x31\x5a\xc7\xaa\xf1\x72\x0c\x4b\x56\x42\x50\xd7\xd6\x38\x2c\x95\xd2\xa1\x4f\xa3\xb0\x93\x4b\x90\xee\x1a\x8f\xe8\x43\x13\x5f\xc5\x0b\x16\x8e\x39\xc9\xd9\x7e\x75\xc3\x3c\x3a\xb6\xc8\xed\x64\xc4\x2e\x60\x32\xd7\xc0\xe1\x8d\xeb\x99\x8a\x6f\x06\x8a\xa7\xa0\xf8\x69\x2a\xd4\xc2\x81\x7b\x47\xac\xfc\xcc\x81\xab\x91\x5f\x00\x3d\x5d\x8c\x09\x3f\xba\xbe\xed\x83\x79\x50\x89\xd2\xcb\x17\x90\x2d\x5d\xe6\xec\xc1\x83\x3c\x01\x82\x8b\x9f\x82\x49\xcf\x4d\x00\x57\x37\x6f\x02\xfb\xfc\xd0\xc4\xfb\xdc\x39\x7c\x39\x12\x6c\xd2\xa0\x42\x9a\x39\x1a\x07\xee\xa9\xf4\x7a\x89\x22\xfc\xfa\x7a\xd3\x0c\x5b\xb8\xa4\x44\x0f\x0e\x5c\xaf\x7f\xaf\xcb\xfc\x5d\xc3\x92\x55\x15\xe2\x2b\x60\xab\xb0\xe1\x48\x6f\xae\x10\x1e\x93\x54\x08\x52\xb5\x74\xe6\xef\x6d\xf3\x87\x61\x58\x50\x46\x94\x50\xc6\xd5\x1b\xae\x98\x0a\xf5\xc5\x30\x68\x14\x01\x82\x6c\xaa\xd2\xcc\xbd\xa7\x92\x94\x24\x58\xf8\xa8\x1c\xe4\xd9\x53\x01\xbb\x78\x7c\x43\xba\xfc\xd2\x01\x2a\xa0\x81\xa3\x1b\x79\x50\x8b\x17\x47\xc1\x86\x1f\xdd\xe5\x7a\x73\xae\x84\x05\x4c\x0f\xd1\x18\x07\x3e\x1a\xb8\xea\x2e\xe6\xa1\x89\x1b\x20\xbd\xee\x27\xd1\xd6\x95\x99\x94\x8e\x27\x34\xcd\x88\x39\x36\x97\x43\x04\x0a\x82\xb0\xf3\xaa\xa1\xfa\x58\x90\x48\x56\xb4\x75\xe5\xd9\xd5\xe1\xe2\x32\x8e\x21\x43\x76\xfa\x24\xee\x90\x68\x75\x68\x62\x23\x0c\x1e\x17\xdf\x81\x28\x3e\xd1\xc5\x98\x30\xa2\x6d\x62\x9b\x4f\x29\x20\x09\xe4\x9b\xe7\x99\x69\x68\x62\x8e\x08\xd8\xf0\xa3\x8b\x5c\x6f\xc2\x95\xdd\xa8\xc9\xef\x34\x53\x36\x94\x90\xdd\xeb\x3c\x1b\x45\x50\x0b\x07\x19\xb0\xe1\xc7\x3b\x72\xbd\x55\x6e\x98\x25\x25\x9a\xde\xd8\xbe\x37\x04\x49\xe0\xed\x03\x54\xc2\x82\xee\x61\x81\x22\xb1\x8e\x03\xf7\x6e\x55\xc0\x82\xc4\x16\xdf\xd1\x2f\x42\x90\x84\xaa\x6b\x0b\xcf\xb7\x06\x2d\x06\x4b\xcc\x1a\x86\x93\x7a\xf2\x39\x33\xd9\xda\x15\x10\x68\x7f\x60\xb2\xfb\xf3\xf6\x4c\xe2\x64\x76\xa1\x81\x47\x39\x1a\x58\x6d\xc4\x6e\xcb\x64\x4e\xf5\x64\x36\x81\x90\xd1\x9b\x67\x16\x07\x83\x49\x7f\xc5\x76\x07\xa1\x7c\x05\x17\x4e\x99\xa7\x5d\x65\x56\xd2\x96\xd9\xf3\x13\x82\xb1\xd4\xe5\x6c\xac\x60\x93\xba\x3e\x2c\x10\x8a\x0f\x4e\x3f\x68\xaf\xeb\xbf\x27\x0e\x70\x99\x8e\xff\xca\xa9\x4e\xd5\x24\xa6\xd1\xf5\x61\x37\xa1\xf8\x60\x3c\xd4\xa2\xa6\xc0\x77\x6c\xc7\xe6\x00\x19\x6a\x69\xf3\xa1\x1c\xb4\x37\xac\x9d\x14\xe5\xe1\x73\x13\xb8\x6a\x87\x26\xf6\x46\x96\x71\xb5\x9b\xb0\xb1\x41\x59\x85\x0a\x68\x35\x8d\x78\xdc\xa5\xeb\xc3\xc4\x1b\xfd\x11\x1c\xae\x98\xb3\xbc\xa1\x9c\xec\x76\x40\x3d\xcf\xe5\x0f\xf5\x9b\xb6\x7d\xe6\x2a\x77\x9c\x2d\x34\x76\xb4\xe7\xf9\xcd\x08\x10\x81\xa8\xf1\xc8\xb2\x2b\x3a\x9a\x08\x83\x1e\x84\xd6\x04\xbb\xdc\xf3\x78\x2d\x0f\x28\x90\xdc\x1c\x74\xc4\x67\xaf\x37\xed\xcf\xf9\x0f\x50\xbc\xc1\xfd\x69\xc6\x66\xf2\xff\xa8\x9a\xdc\xac\x7d\x62\x63\xb6\x77\xf8\xbb\x04\x4a\xb4\x6d\x6c\x4d\x28\xf0\x6f\x23\x04\xc9\x38\x13\xa2\xbb\xf8\x96\xaa\x1f\x19\x93\x12\xed\x63\xea\x86\x59\xd2\x65\x9e\x3f\x40\xf0\xf8\xfc\x1f\xda\x45\xba\xdc\xf1\xf7\x08\x2d\xfc\x01\xb0\x9f\x58\x52\x04\x08\x52\x42\xbc\x2c\x7b\x4b\xe2\xaa\xc1\xa7\x10\x60\xec\x95\x4c\x45\x6f\x9e\x11\xe1\x5c\x03\x76\xab\xfc\xdd\xff\x21\xd9\xbd\x6e\x1c\x6b\xbd\x7f\x13\x18\x6b\x9a\xa9\x58\x06\xd0\x15\xff\xef\x64\xae\x6f\xd5\x78\x59\x9e\x2e\xd7\x2b\x23\xda\x26\x97\x4a\xe9\x40\xd3\xf4\x8c\xa6\x52\x20\x48\x06\xad\x2b\x32\xab\x57\xb2\xdb\x97\x14\x55\xbc\x0e\xc5\x1b\xc8\x9a\xa7\x65\x71\xe5\x1d\x0a\x0d\x4e\x87\x20\x09\x2f\x5d\x8e\x69\x91\x46\x3c\xf6\xdc\xb1\xa0\xd5\xcc\xe8\xf2\x89\x0a\x58\x10\xa7\x8f\x1a\x73\xf7\x2c\x01\x82\x24\x3e\x11\xa0\xa9\xac\x1a\x2f\xe3\x0a\xa3\x8a\x03\xa0\x78\x85\x4c\x4a\x07\x95\x16\x44\xf3\x38\x48\xae\x08\x63\x97\xf6\x7d\x26\x71\x72\x9a\x25\x3b\x2d\xc0\xe7\x8c\x74\xc3\x2c\xf1\x33\xf5\x22\x83\x0e\x58\xce\xd6\x23\x80\xb3\xbd\x5f\xb2\x3b\xcf\x10\x70\x75\x1d\x0d\x34\x57\x66\xef\x23\xef\x22\x36\xff\x3b\x3c\xf2\x8e\xab\xbd\x4f\xb2\x7b\xa6\x30\xaa\xb8\x01\x8a\x57\x48\xa3\x74\x8c\xd0\x3c\x9d\xda\x0f\xb2\xab\x9a\x91\x1d\xa9\xd4\x2f\xd9\x2d\x49\x8a\x2a\x0e\x29\xa1\x73\xf6\xea\xa0\x89\x50\xce\xe6\x78\x36\x23\x23\x87\xdf\x49\x6d\xdc\xcd\x54\x6c\x60\x5b\xbd\x09\x34\x3f\x69\x9e\x06\xcf\xcd\x6d\x6d\x37\x3a\xc8\x2d\x66\x8e\x27\x54\xc1\x3c\xcd\xab\x30\xaa\x58\x1b\x8a\x57\x48\xa1\x20\x79\x36\x60\x3e\x57\x0e\x9c\xcd\x18\x71\x66\x37\xc5\x80\x82\x19\x6d\xff\x68\xd7\x58\x13\x6d\xb9\xd0\x80\x5d\x68\x1e\x39\x47\x1a\xd5\xe1\xf8\xc9\x9e\xd8\xce\xe3\xb7\x33\x15\xcb\x78\x18\xff\x81\x6f\x86\xbb\xe9\x0d\xd3\x93\x02\x23\x2a\xdd\xe5\xa0\xe5\xd4\xa7\x53\x2d\x71\x69\x0e\x48\x02\xe4\xa3\x07\xe7\xd7\x12\x4d\xa2\x98\x31\x80\x3e\x7b\x13\xc8\xa7\x6a\x9e\x26\x1f\xb1\xc0\xc1\xf7\x98\xc4\x36\x56\x3b\xcc\x27\x65\xe7\x0d\x2b\x8b\x13\x2c\x7c\x5e\x09\x12\xb5\xce\x54\x0c\xf9\x56\x77\xcf\x67\xea\x20\xae\x63\x8b\x92\xcc\xcf\xc1\xa4\x3a\x35\x78\xdc\xdd\x4f\xa4\x18\x9e\x34\x4a\xc7\x1a\x76\x5e\xa2\x8a\xdf\x4c\xe2\x56\xc6\xa6\x36\x82\x22\x0a\x36\x20\xac\x94\x8b\xd0\x78\xd0\xc4\xc0\xe0\xd7\x4e\x39\x20\x51\xd3\x4c\xc5\xe5\x88\x32\x6e\x76\x78\x64\x53\x97\xa2\xb0\x17\xd3\x8c\xa8\x8e\xfe\xdb\x66\x23\x8d\x71\x8d\x75\xc4\xd0\xdd\x8c\x6f\x0f\x8c\x4c\xd2\xc8\xce\xeb\x46\xcc\xa0\x55\xe3\x73\xc9\x82\x85\x7f\xdf\x82\x44\x3f\xf4\xda\x47\xe5\xf1\x84\x2b\xc1\x9f\x42\xa2\x4b\x12\x51\xb8\xbe\xea\x33\x28\xdc\x44\x7b\xfb\x42\xb5\xac\x19\xc3\x29\xd0\xb1\x89\xbe\x93\xc6\x02\x11\xa5\xf9\x9c\xf5\x5d\x31\x4b\x37\x68\x76\x85\xbe\xa6\xa8\xaa\xe9\x0a\x92\xb8\xf6\x2e\x9f\xdd\x7e\xf4\xf8\x3a\xa1\xac\xe9\x95\x0d\xc8\xdb\xc1\xa2\x79\xef\x08\x5f\x21\x64\xf5\x6b\xe9\x4c\xe2\xa4\x49\xa1\x81\xc7\x0c\x14\xcf\x93\x42\xe9\x90\xe1\xd8\x8b\x24\x40\x9c\x26\xe2\xfa\xcf\x3d\xea\x85\x36\xff\xbb\xaf\x9f\x4e\x0e\x27\x1e\xb2\xa4\x6a\x12\x1d\x93\x05\x0b\xdb\xef\xca\x49\xf9\xa0\x89\x39\xfc\xb7\x39\x36\x56\x0e\x21\xef\x78\xe2\x7c\x36\xdf\xfa\xe2\x0a\xfe\x6d\x7f\xee\x77\x18\xbc\xe8\x30\xd8\x18\xb7\x73\x9d\xaf\x10\xe2\xf7\x53\x87\xa6\xb1\x6a\xbc\x5c\xc2\x92\x1d\x3c\xcb\x37\xc6\xd1\xc5\x98\xb0\x66\x6e\xd3\x6a\xe8\x68\x08\x46\xf6\x3e\x06\x57\x2e\x79\xe1\x74\xdc\x4c\x19\x3e\xb4\x62\x7b\x41\x1e\xf9\xfe\x8f\x22\xb3\x38\x98\x14\x64\x8e\x05\x79\xbd\x88\xf6\xb9\xcc\xde\xa2\x37\xe4\xca\x43\x7c\x8e\x23\x25\xc4\xbf\x8f\xc8\xcc\xc6\xb0\xed\xdb\xff\x60\xdb\x2f\xf6\xfd\xd0\xfb\x58\x19\x59\xf9\x50\x65\xb1\x37\x98\xb4\xe9\x84\x05\xe9\x10\xa3\x7d\x38\xdc\x30\x28\x1e\xb5\x43\x2f\xa4\x73\x8d\x08\xbc\x1d\xaf\xd6\x01\x0d\xce\xbf\xf7\x7a\x0e\xd1\x0f\x6e\xea\x2e\xee\x04\x93\x30\x9b\xe2\x67\xe4\xe9\x9c\x55\xe8\x85\x4f\x67\x95\x91\xc9\x28\x8b\xa4\x27\x21\xcb\x74\xaf\xe2\x79\xff\x4b\x7d\xc3\x49\x0b\x3b\xab\x1f\x76\x6d\x84\xa8\x41\x1e\x80\x7f\xee\xa2\x86\xc8\xc1\x8a\x73\x11\x01\x9c\x38\x09\xb0\x61\xf2\x04\xde\x87\xe6\x8a\x79\x04\xcf\x5d\xc8\x37\x25\x5c\xf8\xd1\xb5\xdb\xfa\xa0\x5c\xd6\x8c\xf1\xa3\x2a\x72\xaa\x57\xb2\x9b\xaf\x30\x8a\xe5\x2c\xda\xc6\x49\xa0\x74\xec\xd1\x14\x68\x6d\x2c\x28\x01\xe6\x51\xd2\x20\xdd\x31\x70\xc2\x31\x21\x49\x23\x4c\x58\xe8\x3e\x0a\x84\xf3\xd4\x4f\x87\xd4\x4a\x06\xde\x69\xa2\x37\xca\xc1\xe3\xe0\x50\x3c\xf7\x49\xf3\x34\x23\xac\xe8\x83\xf5\xc4\x9e\x93\xc8\x28\x8f\x89\x38\xbd\xbb\x13\xc5\xfb\x92\x60\x97\x35\x68\x1c\x61\x25\x25\x8f\xb3\x34\xf4\xf3\x17\x27\x9f\x58\x1f\x0e\x57\x0c\x8a\x53\x37\xda\xcd\x9a\x50\xa3\x8c\xc5\x95\x4b\x1a\x8b\x59\x0f\xcf\xa9\xd8\x06\x84\x1c\xe1\x78\x3d\xa3\xee\xf4\xbb\xed\x06\x20\x96\x40\x06\x01\xb8\x65\x38\x1d\x24\xc0\x86\xd6\x89\x82\xb2\x1c\x23\xbc\x39\xa2\x60\x04\x81\xf7\xba\x57\xfa\xb4\x5a\xac\x49\x11\xab\x24\x74\xce\x8d\x7e\x14\xa2\xc2\x30\xaf\x80\x05\x59\x60\x81\x68\xe0\xfb\x83\x49\xdb\xc3\x92\x22\xc0\x3e\x97\x98\xe7\x9d\xa9\x15\x4a\x7b\x4e\xd9\x99\x7c\x5a\x28\x6f\x8a\xaa\xf2\xad\x80\x5d\x54\x85\x7f\x28\xaf\x04\xf1\x76\x32\x5c\xad\x98\xb7\x77\x46\xf5\x09\xd2\x36\x7e\x9b\x74\xfa\xd1\xfa\x92\xdc\x61\xe4\xf6\xda\x3d\x92\x8b\x29\xaa\x4a\x83\xd9\x08\xb5\xf0\x8f\x17\x3c\xfb\x05\x7a\x52\xbf\x02\x86\xe6\x08\xe5\x1c\xd0\x85\x3f\x85\x08\xd4\xb7\x2d\x08\x3d\x38\xe9\xe8\xab\x91\x5b\x54\x66\xce\xf8\x66\x27\xb8\x63\x97\xa9\x58\xcd\x92\x7d\xdf\x89\x10\x9f\x22\xd1\xe4\xe8\x72\x10\x0c\x33\xe3\x21\xae\xbc\x0e\x0e\x7f\x0c\x11\x20\x08\xff\xbd\x7d\xab\x8c\x43\xb4\x8d\x03\x4d\xdc\xd1\x58\xfc\xcd\x92\x22\xd8\x1e\x9a\x17\x32\x63\x58\x07\x9a\x67\x2a\x7e\x7d\x22\xa8\x91\x00\xc5\x87\x65\x52\x3a\x1e\xd2\xb6\xd9\x15\x7d\x35\xdd\x1b\xb7\xa8\xb6\x0e\x50\xf8\x4b\x57\xa5\x15\x55\xc0\x7e\x6a\xc3\x3f\x97\xbf\x05\xad\x5d\xcd\x54\x3c\xbc\x18\xd4\xb8\x7f\x95\xf0\xf2\x75\xfd\xab\xdb\xd1\x67\x1c\x2b\x25\xd6\x01\x0a\x98\x4a\x51\x6e\xc7\x67\xc1\x3f\x62\xb6\x3e\x20\x06\x94\xd8\xfb\xde\x14\xa7\xb6\x89\x7b\x2a\xb9\xad\x38\x11\x35\xdc\xb7\xdb\x0a\x12\x69\x31\x4c\x39\xfe\x5b\x16\x9e\xf5\xa3\xd4\x6a\xa7\x28\x6c\x3f\x14\x78\x53\x04\x8c\x20\xc4\x93\xeb\x57\xac\xc5\x9f\xcb\x80\x49\xa5\xf1\x57\x81\xa7\xbe\x84\xfc\xfd\x98\x90\xbb\x26\x93\x20\xf5\xf0\x42\x9f\x5b\x69\xfe\x05\x51\xb0\x19\x63\x71\x63\x18\x6a\xe1\x20\x09\xbe\x73\x33\x10\xfb\x56\xa8\x02\x16\xa4\xeb\x73\x1d\x2b\x88\x54\x25\x7a\xa2\xde\x8c\x17\xce\xcd\xaa\x0d\xbe\xb3\x17\x06\xbb\x94\xaa\x6a\xcf\x1a\xb8\x39\x23\xdc\x9c\x11\x7e\x9b\xbd\x19\x32\xaf\x05\x26\xee\xa9\x2b\x39\x56\x12\xd9\xdd\x3e\xfc\xe7\x9b\x44\xb2\x80\x2a\xf5\x8b\x6e\x0a\xa5\xe3\xcf\xaa\xf1\xf2\x6f\x96\xac\x9b\xbb\xdc\xec\x5b\xa8\xc5\xf5\x6f\x75\x77\x10\x04\x98\xc1\x88\x9e\xb8\x4b\xa5\x51\xe3\x85\xe4\xe9\x25\x17\x69\x34\xa8\x7f\x37\xae\x31\x28\x95\xe7\x2a\x4a\x3d\x81\x73\x3f\x95\xd2\xe1\xbc\x6a\xec\x1b\x86\x7d\x76\xb6\x12\xb4\x66\x9d\xa9\x78\x8d\x79\x8e\xe6\x4f\x47\x43\xa8\x3e\x25\xf2\xf3\x42\xbc\xcf\xaf\x1f\x2d\xeb\x26\x11\xa5\x76\x7d\x82\xee\x27\xa6\x95\x35\x34\xda\x08\x66\x8b\xa5\x96\x6d\x1f\xad\xba\xb0\x72\xa1\x98\x5c\x61\x27\x98\x93\x4d\xe9\x38\x37\x9d\x38\xc9\xc4\x69\xbe\xce\x87\xe2\x9b\x56\x45\x99\xb5\x2c\x10\xc1\xd6\xb0\x2f\x37\xcf\xba\x6d\xb7\xf5\xce\x2f\xbd\x9b\x16\x77\xdf\x2e\x39\x48\x0e\x15\xcb\x36\x8f\xa5\xf2\x3c\xec\xf6\x5c\xaa\xce\xb2\x03\x29\x74\x7f\xfa\x1e\xd1\xcf\x2d\x93\x20\x88\xba\x9e\xe1\x3f\x54\x31\xcc\x87\x26\x4a\x1d\xde\xe1\x30\x7f\x07\xe9\xee\xfc\x3c\x56\xe6\xe2\xda\x97\x4d\x72\xc1\x5a\x68\x37\x3c\x15\x90\xc1\x5d\x8a\x0a\x77\xad\xaa\x78\xdf\xfc\x25\x84\xfe\xae\x7e\xbf\xed\xf5\xc3\x25\xbb\xf0\x95\x45\x76\x97\x62\xb6\x2e\x70\x98\xf4\x4a\x76\x9f\x2a\x8c\x4a\x4f\x75\xa3\x00\x2a\x60\x3f\x45\xb5\xc4\xf4\x5a\x08\xb0\x7b\xf3\x42\x9f\x9e\xf5\x61\x7d\xe0\x9e\x2e\xb6\x59\xaf\xa7\x2f\xbd\x5d\x89\xab\x2c\x3a\xf2\x3b\x59\x13\x7e\x27\xf8\xe2\x95\xbb\x4d\x41\xde\x48\x23\x4d\xa1\x8d\x2b\x99\x8a\x26\x3f\x24\x2d\x5a\xd2\x7a\xdd\x44\x33\x47\x4c\x23\x9b\x0a\x0d\x4c\x51\xce\x75\x7a\xe2\x2f\xbd\x8d\x1a\x2f\x18\xfb\xfd\xbc\x6a\x9b\x05\xe6\x31\x69\x94\xbe\x25\x2c\x69\x01\xba\x91\x56\xb6\x5d\xc0\x73\x95\xf1\x49\x90\x77\x44\xa0\x51\x05\x6e\xfa\x33\xd0\xb5\xaa\xab\x02\x76\x51\x78\xe3\x36\x3b\x79\x15\xd3\x6f\x62\xcf\xf9\x7f\xca\x22\xb9\x60\xfb\x62\xbe\xea\xe4\xae\x79\xdd\x30\x69\x1f\x28\x09\x6a\xd9\xb7\x51\x5d\x0e\x48\x48\xa2\xab\xc4\xbd\xdb\x7b\xb6\x33\x99\xa8\x14\x27\x64\x5c\x44\x38\x5e\x2a\x70\xe9\xf5\x88\xc7\x1a\xf3\xf6\xf6\x62\x05\xc8\xff\x6a\xa6\x62\x03\xa7\xde\xc7\xa2\x78\x33\x46\x4e\xad\x9e\x38\xa9\xe2\xbd\x2e\x3b\x62\x92\xcb\x7d\x87\x7b\x8f\x77\x7e\xe4\xdd\xaf\x8a\xda\x30\xe0\x2b\x84\xe5\x3c\xe0\x15\x2c\xd1\x24\x06\x18\x01\x54\xf8\x92\x13\xfc\x9f\xdc\xb8\x62\x8a\x5a\x4f\x9f\x47\x6c\x55\x67\x9d\x61\xb9\x81\x78\x77\x96\x1d\x24\x29\xf5\x33\x47\x6d\x03\x74\xb8\x04\x71\xe0\x89\x34\xc9\x39\xd9\x37\x8a\x8e\x21\xcf\x79\xae\x4a\x08\x76\x45\x0a\x71\xb7\x08\x83\xc9\x50\x28\x7e\x78\xf9\x02\xb3\x83\x2e\x07\xa1\x2e\x96\xc8\xe7\xaa\x6f\x99\x43\x5a\xea\x94\xb7\xa3\xb8\x6f\x03\x35\xcf\xaf\xee\xa7\x99\x88\x7e\xc8\xc3\xbe\x8c\x15\x9a\x93\xb5\xbc\x04\xca\x45\xa1\xbc\x1b\xcf\x98\xa7\xf1\x4d\x27\x4e\xd6\xd1\xf5\x3b\x69\xf2\x24\xfb\x14\x4a\xc7\x55\xda\xfe\x9d\xd6\x4c\xf2\xc5\x53\xe3\x7b\xcc\x8d\xa9\x17\xfa\xe1\x43\xd7\xe8\x1a\x35\x9e\x4e\x6b\x80\x06\xb9\x3c\xd7\xdf\xdb\x0b\xf9\x7e\x1f\x95\x48\x69\xa6\xd3\x89\x0d\x91\x51\x33\x89\x93\x65\xa4\xa8\xe3\xf6\xe7\xe1\x97\xe9\x6e\x98\x0a\x50\xd9\xb3\x14\xf2\x1b\x95\x21\x3f\xe1\x39\x81\x80\xb4\xd1\x70\x0b\x6c\xc2\xeb\x92\xfb\xfb\xb5\x4b\xe9\xfa\x11\xd3\xc0\xb9\x06\xef\x78\x4b\x39\x6a\x80\x28\x77\x1e\xf1\xd6\x10\x43\x6a\xe3\x70\x4e\xc3\xf1\x81\x73\x70\x3c\x24\xc3\xa8\x20\xe9\xb4\xa5\x41\x48\xf7\xc7\x6f\x3d\x24\x97\xfb\xd7\x7e\xea\x2e\x4c\xa4\x4d\xdc\x53\x4f\xb4\x94\xa3\xbe\x7b\x71\xa4\x51\x03\x6e\x48\x47\x03\xa7\x64\xcd\xd3\xc4\xb8\xd4\x13\x7b\xe4\x90\x94\xab\xe0\x82\x7a\xf3\x8e\x79\x19\x68\xe7\x1e\x73\xe9\x91\xc5\xdd\xe5\xd5\x1b\xb4\x0f\xbb\x74\x0d\xc8\xea\x88\xe3\x5d\xcc\x23\x53\x6c\xdc\xc9\x4a\x50\x0f\x2a\x53\xf1\x54\x24\x2e\xbe\x47\x0e\xe9\x86\x1a\xde\xb4\x16\xb7\x07\x81\x49\xa5\x4b\x93\x46\xf4\xa3\x2f\x29\xf5\xf7\xaf\x61\xf1\x6f\x54\x3b\xa7\xec\x19\x39\x89\x9c\x79\xdd\x0c\xb2\x34\x98\x5c\x0c\xc5\x57\xa6\x50\x90\x89\x3d\x22\xc2\x4f\x49\x95\xa6\xa8\xe7\x07\x39\xdb\x1d\xb1\x15\x9d\x3d\xce\xee\xfc\xb3\xcf\x33\x7a\x45\x00\x5c\x38\x30\xb8\x90\x7d\x75\xf9\x3a\x13\xc9\x06\xfb\x7e\xe7\x05\xca\x23\xdc\x19\x53\x5d\x64\xf3\x7c\x05\xeb\x38\x61\x6b\xc6\x0f\x4d\xbc\xa4\x03\x37\x3c\x8a\x06\xba\x2b\x9b\xa7\x71\x47\xea\x3d\x65\x7b\x3d\xbe\x1b\xe5\xdc\x79\xe1\x79\x77\xbf\xe3\xe1\xf1\x75\xa3\xf6\x94\x5e\x47\x11\xb6\x4e\x9f\x05\x81\xc9\x1e\x50\xfc\xb9\x33\xab\x37\x87\x92\xe9\x17\x4b\xa1\xc8\xe9\xc2\x69\x86\x41\xe7\x3b\xbd\xda\x97\xca\xd1\xe5\xb7\xd3\xd0\xeb\x00\x4a\x41\x35\x7f\xde\x3f\x0d\x17\xd1\xb6\xe7\x41\xa7\xad\x2b\x7c\xcf\x13\x60\xe2\x9d\x17\x28\x9e\xde\xb5\xd9\x3b\x35\xa5\x6c\xd0\xdc\x71\x3e\x18\x6c\xc2\x9b\xce\xec\x8f\xca\xbf\x09\xc1\xbf\x37\xd1\xc4\x9c\x13\xe0\x42\x53\x28\xfe\x7b\x3a\xa5\xe3\x08\x53\x87\x7e\x11\x42\x7d\xd5\x59\xd3\xfe\xc3\xc1\x17\xa9\xbf\x06\xe8\x3a\x0f\x26\x0f\x2f\xed\xe9\x23\x71\x59\x94\x8e\x35\xba\x5c\x7c\x1b\x42\x2b\x4c\x86\xb7\x26\x51\x50\x0e\x49\xb1\xfd\xb4\xdb\xfa\x58\xca\x0e\x3a\xe4\x7a\xa1\x65\xf5\xc8\x3a\x40\x61\x8e\xbf\x51\x13\x6e\x78\xf5\x26\xb0\xc8\x79\x9a\x6b\xcb\x86\xcd\xbc\xe8\x8c\x47\xb8\x72\xd9\x76\xd1\xae\x0b\xcf\x4f\x77\x4e\xd9\xa3\xbe\x36\x9d\x34\x4f\x2b\x32\x8c\x55\xe6\xe2\x1b\xbb\x7e\x45\x87\xca\x5a\x60\xdf\x7a\x9e\xe1\x65\xd6\x37\xe2\x63\xa5\xbf\x06\x58\x57\x1d\xdb\x73\xd2\x50\xac\x24\x04\xbf\xe1\x0a\x85\x99\xa7\x05\xd1\xf5\x79\x73\xa3\x7d\x66\x74\x39\xd2\x67\x46\x33\x09\x30\xa7\xce\x0b\x94\xa5\xbd\x56\xd9\x39\xd1\xcd\x5b\x0b\x32\xe9\x2b\x76\xdb\x1c\x38\x09\xf0\x9d\x6f\x68\xa0\xcc\xfb\xde\x3f\x99\xea\x07\x10\x4e\xee\x39\x3d\xab\xf8\x2f\xdf\x1b\x4d\x74\x0d\x88\x40\xa6\xa6\xd5\xb0\xfc\x9b\xd3\xe5\xa0\x07\xfa\x99\x8a\x7c\x11\xc9\x86\x53\x29\xe4\x8a\x52\x35\x9d\x81\xdd\x56\xd9\x3e\xb7\x3f\x44\xd0\xa4\xa6\xd8\xf8\xb2\x1a\xb5\xcc\x38\x32\xd9\x62\x58\xe9\x4d\xf7\xa2\x70\xa5\xdb\xc2\xa1\xb5\x38\x41\x39\xa4\xdb\x8d\x1a\x95\x6b\xce\x6b\x80\x77\x43\x69\x9d\x17\xfe\x0c\xc6\x29\x77\xba\x5e\x47\x8d\x82\x05\x1a\xe1\xf0\x0f\xf9\x15\xa0\x07\xc6\x99\x8a\x56\x87\x1c\x64\x72\x0d\x08\x31\xfa\x3f\xd7\x06\xe2\x7d\xf7\x9d\xea\xe2\x6b\xb7\xa3\x08\x35\xbf\xcb\x2a\x60\xc8\x42\x03\xfe\x93\x7c\x63\x8a\x15\xb0\x13\x9c\xba\x82\xbd\x85\x95\xa6\xa8\xbf\x6c\x96\xb9\x6f\x74\xc9\x11\x47\xd9\x8e\x22\x48\x77\x9d\x94\x4d\x14\xd4\x88\x83\xe2\x93\xd7\x14\x99\xdf\x58\x20\x02\x8c\x1f\xbe\x1d\x35\x64\xd8\xce\x2a\x69\x9b\x15\xca\x7c\x0d\x12\x9d\x58\x56\x53\xe9\xc5\xa0\x89\x39\xd2\xe0\x3b\xdf\x6e\x02\x35\x09\x6c\x8d\xac\x5d\xe8\x6b\xca\x28\x57\x1e\x7a\xfb\xb1\x67\x8f\xc9\xee\xbe\x92\x4a\xbd\x5a\x5f\x6c\xc2\x1b\x55\xb6\x7f\xb5\x2d\x5f\x19\xae\x0f\xb1\x71\xfa\x77\xe4\x42\xc9\xc9\x9c\xab\x2c\x10\x61\xf2\x4d\xcd\x57\x4c\x82\xee\xa6\x7a\xf1\x5c\xd0\xb1\x8c\x2d\x7f\xfa\xc3\x2a\x1e\xb7\x6c\x94\x88\x3b\xae\xfc\x76\x5e\xc0\xe0\xe9\xa5\xf3\x59\xc6\x45\x29\xb6\xfc\x5d\x11\x2d\x49\x82\x1a\xa6\xc6\x85\xdc\xfc\xf1\x50\x0b\x87\xc3\x97\xce\xc3\x63\xc9\xf3\xc5\x3a\xf3\x17\x6d\xd7\x03\x79\xab\x0d\x1c\x0e\x57\x61\x46\xfd\x05\x82\x96\x4f\x2e\x4d\x7a\x2e\x9d\x17\xfb\xde\x33\x1f\x9f\xa4\xbc\x0e\x78\x9f\xfe\x1a\x34\x39\x53\xf6\x08\x67\xcd\xb8\x92\x93\x41\xe9\x70\x9f\x3e\xf8\xb7\x26\x3f\x17\x9f\x5c\x0a\xa5\x43\x8d\x16\x42\xf2\x35\x9d\x26\x98\x65\x74\x56\x5c\x93\xc4\x45\x74\x26\x01\xac\x87\xfe\x71\xf0\xfd\xe6\x78\x88\x3b\x63\xf9\x33\x69\x5a\xf4\xcf\xb2\x1a\xc6\xc9\x36\x22\xf9\x2e\x66\x09\x1f\x4c\xba\x28\x0d\x56\x24\x46\x97\x8f\x47\x45\xb8\x77\x92\x09\xc5\xf3\x81\x1c\x19\x41\x4f\xa5\xc7\x6f\xdc\x7f\x29\x3b\x12\x7e\x7a\xb3\x5b\x48\xe4\x43\x9f\xe8\x07\x5d\x65\x3b\x15\xe7\x9d\x91\xc7\xb3\x42\xf3\x63\x7b\xf9\x90\x56\x4e\x9a\x1d\xeb\x97\x8e\x6e\x6f\x4c\x33\xe8\x2e\xe6\x11\x74\xb1\x8d\x25\x45\xa8\x77\x9f\x6c\x1f\x53\xb5\xcd\x9c\xb5\xf2\xea\xd8\xeb\x15\xdc\x0c\x93\xb6\x07\xa9\xbf\xcc\x1d\xfe\xf9\xb4\xd8\xe0\x35\xb6\x5d\x34\x5b\x4c\xcc\x15\x57\xee\x6a\xd4\x98\x9b\x56\x56\x07\x81\x47\x93\xef\x04\xdb\x65\x2a\xe6\x95\x69\x12\xfb\x8d\x01\x4f\x60\xbd\xd1\x67\xcc\xd3\x8e\x2c\x06\xd0\x2f\x42\xfc\xfa\x7f\xb5\x30\xab\x65\xd7\x72\xb6\xa3\x9c\x4b\x92\xb5\x2c\xed\x43\x47\xf4\x94\x31\x82\x93\x9c\xfb\xc0\x1c\x10\x18\xc2\xb0\x16\x43\x30\xd7\x23\x94\x8c\x63\x53\x7a\x8d\x32\x54\x33\xdc\x4c\xfc\xb6\x8d\x34\x6d\x40\x65\x21\x81\x80\xb7\x75\x83\x8f\xb5\x0c\xfa\x72\x05\x55\x47\xf7\x98\xc4\xa7\x24\xf9\x2b\xe6\x7e\x41\x75\x8a\xf8\x79\x21\x33\x22\x69\xbc\x12\x16\xf4\xa0\x89\xbe\x73\x07\x9b\xa2\x6c\x60\x07\xac\x84\xa1\x81\x8d\x4a\x6c\xd0\x4b\xd4\x7e\xe6\x75\x36\x3a\x38\xaa\xdb\x16\x54\xb8\xea\x79\x9a\xaf\x91\xfc\x17\x4f\x05\x62\xf5\x1b\x9f\xf9\xfb\x9b\x24\x9f\x3b\x6e\xf7\x37\xe9\x74\xd2\xe8\xd0\x73\x5b\x81\xda\xce\xdf\xc3\xd4\xfb\x95\xe6\xec\xde\xee\xbf\x09\x54\xe8\xfe\x39\x7a\x17\xb3\x94\xe1\x1c\x46\xfb\xf2\x4d\x14\xc1\xf4\xba\x5c\xb7\xf7\x5a\x59\xa5\xd8\xe3\x26\xc8\xbd\xa4\xbe\xd1\x75\x3b\x2a\xba\xee\xbf\x98\x03\xfc\x35\x15\x30\x0f\xd6\x78\xf7\x80\x81\x38\x6c\x0a\xd0\x00\x0d\xac\x84\xfd\x14\xd6\xd2\x66\x3f\x2f\x99\x50\xf8\x96\xf2\xb8\x36\x98\x24\xff\xd2\xe0\x36\xa8\x54\xde\x36\x40\xe7\x2c\xdc\xe8\x86\xc8\x5d\x5c\xf9\x7d\xa1\xa5\xba\xee\x6d\x80\x82\x5f\x77\x9e\x1b\x66\x89\x1a\x4c\x0a\xb2\xc3\xa6\x84\x4b\x76\x22\x80\x8d\xc9\x3d\xc7\xa8\xe4\xb3\x41\xbd\xbb\x51\x51\x77\xc6\x1f\x6f\x3c\x8a\x69\x92\xcd\x64\x93\x40\xc8\x7d\xca\x29\x3c\xcf\x66\xa3\xb9\x2a\xfe\x23\xf6\x4d\xfe\xc6\x7b\x96\xec\xee\x05\x2c\x1b\xdd\xf1\xc8\x29\xe3\xa9\x94\xde\xb0\xdd\x9f\x32\xb3\x31\xf4\x82\xf5\x77\xff\xff\x5b\x80\x76\xe5\xb8\x7b\x2f\x93\x9e\xe9\x06\x86\x60\x3f\xbf\x50\x19\x7e\xfb\xb1\x6d\x56\xe8\x0d\xb9\x62\xee\x0d\x5d\xa3\xbe\x44\x39\x0d\x8d\x8c\xfe\x07\x40\x13\x77\x0c\x9a\xe8\x52\x3b\xe6\x6e\x0d\x1e\xc5\x47\x9c\x33\x15\xcf\x33\x73\x58\x52\x84\x60\x52\xad\x91\xcb\x39\x9e\x7f\x49\x79\x56\x16\x42\xea\xaa\xf6\xfa\x52\x09\x2e\x4d\xc3\xe3\x7b\x4e\x29\xfe\x96\x43\x6c\xc7\x6f\x24\xf6\x48\x8f\x21\xe9\xfa\x5b\x98\xe2\x23\x72\x8b\x66\x4c\x26\x0b\x44\x08\x26\x11\xf8\x7f\x3f\xa4\xff\x2c\xb6\xfe\xe9\xec\xe8\xa9\x3d\x6b\x3e\x97\x3f\x4a\xb2\xe5\x79\x0b\x47\xf8\x89\x2d\xc8\x24\x58\xd7\x8f\x17\xbe\xb3\xb7\x08\x79\xaf\x43\xd7\x80\x64\x7c\x3d\x57\x09\xbb\x58\x37\xe2\x11\x7e\x1a\x6e\xda\xc2\x6f\x21\xf7\x85\xe1\xaa\xb1\xf8\x86\xfd\x34\x05\x55\xcf\xf7\x4e\xa6\x06\xa3\x8f\x5f\x03\xf7\xa7\x6a\xaa\x8f\x14\xcb\x8a\xba\x00\x9a\xeb\xbf\xeb\x9f\xa9\xf1\x3a\xe8\x50\x69\xbb\x9f\x8a\x78\x23\x36\x16\xe4\x75\x77\xcc\x52\x62\x30\xe9\xe2\x09\x30\x59\x26\xe6\x25\x88\xcb\x1b\xe0\x1f\x2f\x28\x47\xd5\x54\xd5\x9e\xb7\xa2\x34\xdb\x63\x13\x9a\x83\x6a\x65\x9b\xf9\x9d\xce\x09\x7f\x68\x85\xc6\xb9\x65\xa3\xfc\xd6\x00\x00\x5c\xdf\x87\x5d\x7d\x24\x31\x75\x37\xf2\x06\x37\x06\x9b\x12\x2e\x1e\x8f\x78\x46\xe9\xd0\xc5\xce\x8b\xa6\xda\xa2\xdc\xb2\xc3\xbf\xd8\xba\xc5\x86\x15\xcf\x95\x7f\xa5\x89\x7d\xa8\x10\x69\x0b\xed\xa6\x7c\x7b\x60\xd4\x3e\x50\xc2\xd8\xdd\xf4\x98\xaa\xea\x0f\xdc\xcf\x27\xbf\xd8\x5a\x86\x5a\xe8\xda\x78\xc3\x16\xe2\x05\x19\xf7\x0c\xae\x02\xff\x42\x63\x93\xd8\xa5\xab\xed\x76\x4a\xc2\xb7\x1a\xa3\xff\x25\xbb\x14\x63\xff\x0f\xb9\x74\x3e\x8b\x11\xce\xfc\xf1\xcc\x7a\x44\x4f\xfc\xe5\x2d\xe2\xee\xa0\xe0\x3a\x40\x61\xb5\xf5\x18\x5c\x89\x7f\x14\x04\x26\xf7\x9b\x39\x02\x2b\x61\x41\xbc\x8b\xaf\xd8\x91\x53\xbf\x6c\x47\x0d\x5f\xb5\x48\xda\xf3\xc2\x3c\x18\x0d\x13\xde\x24\x9a\x7f\xee\x77\x30\x6b\x5e\x43\x0d\x06\x8c\x7c\xcb\xe3\xd7\xd6\x19\xd9\x6d\x95\x75\xcb\x06\xb1\x9b\x9d\xba\x28\x81\x26\x86\xd6\x8e\x78\xec\x9d\x84\x9b\xaa\x67\xd4\x83\xee\x62\xce\x72\x85\x9e\x81\xc7\x92\x47\x24\x6a\x76\x5b\xeb\x4a\xa0\x0e\x48\xaf\x7f\x66\x9e\xdb\x2d\x1c\x11\x6b\x51\xef\x02\xe2\xc7\xd8\xd6\x6e\x1b\x87\x0f\x65\xa4\x04\xe0\x92\x9b\xef\x53\xc8\x67\xd6\x85\xd4\x6e\x21\xdd\x86\xdc\xe8\x1a\xf5\x9d\x08\x65\xaa\x95\x71\xe4\x3a\xe7\xd7\x27\x82\x0c\x73\x8a\x1a\x9e\x76\x2f\x82\xbb\xd0\xc0\x74\xfa\x74\xf2\xd3\x1e\x0b\xb7\xbd\x63\x9e\x21\x2f\xf8\x43\x5e\xfc\xda\xa4\x7d\xe0\x9e\x78\xb7\x13\x17\x6a\xe1\xfe\xf8\x59\x59\x83\x94\xa2\xf4\xb3\xe5\xed\xf4\x39\x5c\x11\x9b\x6c\x67\x47\x4c\xd8\xd1\xfd\xa4\xa2\x89\x39\xd6\xde\xb0\x16\x11\x30\xf9\x86\x19\xbb\x23\x7f\x72\x6e\x2c\xb3\x03\x2c\xbb\x6f\x24\xff\x8b\xc5\x55\xd2\x95\x67\xe8\xb7\x99\x06\xc7\xe5\x5a\x11\x46\xfd\xaf\xb9\xef\xfb\xcc\x51\x72\xf3\xdc\xb7\x52\x88\x66\xdd\xec\x08\xb7\x97\x53\x47\xc3\x05\xe6\x04\x02\x4c\xda\x53\x60\xb7\x75\x9f\x51\x3a\x84\x0f\xfe\x43\x4c\x16\x33\xb3\x03\x46\x06\x70\x68\x1b\xc6\xa6\xf4\xde\x9b\x17\x5a\xbb\xed\x87\x9f\x66\x18\x14\xab\xe9\x1c\x12\x0c\x13\xe1\x98\x6b\x08\xbf\x78\x5e\xbf\x91\x6c\x03\x5a\x68\xfe\xf7\xd6\xf1\x0e\x75\x5d\xc8\x98\xaa\x76\x0a\x2d\x07\x35\x3d\x9a\x65\xab\x0a\xe0\x6e\x11\x0a\x85\xc2\x4d\xd5\xd3\x2b\x40\x77\x31\x15\x5c\x5a\xa7\xd8\x60\x95\x42\x7f\x26\x9b\x85\x6d\xb3\xc4\x0d\x8a\x2a\x86\x5f\xf4\xd6\x0c\xa5\x0d\x72\xaa\x1f\xca\xdf\xa5\xbd\xce\xdd\x7d\x5f\x6d\x63\xf3\x61\xf5\x86\xce\x6f\x2d\xca\x76\x94\x86\xea\x53\x7f\x52\xc5\x99\x27\x49\xf4\x6b\x9b\xdd\xec\xf9\x6f\x36\x65\x8f\x26\x86\xbe\x19\xf1\x18\x91\x04\x93\x87\xcc\xd0\xc0\xc8\x7d\xc0\x97\xa7\x82\x72\xd4\xf5\x92\x2e\xf3\xeb\xb0\x23\x25\x15\x4e\x2a\xd5\x4d\x56\x05\x35\xeb\x2a\xb9\x42\x57\x7e\x59\x35\xcf\x2f\x8d\xea\x76\x57\xd5\xff\xae\x1d\x88\xb0\xbf\xfe\x6c\xb7\x95\x00\x16\x8b\xae\xd9\x8e\x22\x14\xce\xf2\x37\xa6\x1e\x7b\x43\xce\x78\xc3\xf6\x4b\x7b\x31\x9e\x25\x45\xd8\x22\x85\x3a\x2e\x66\x7e\x60\x5d\xb0\xbd\x21\x75\xa3\xfe\xe4\x46\x4a\xe1\x81\x54\xa8\x09\xcb\xde\x8e\x22\x20\x72\x73\x29\x1d\xa3\x7d\x92\xdd\xda\xa4\x28\xac\xcd\x79\xf8\x65\xa1\x1d\x15\x07\x84\xba\xc0\xe1\x75\x80\x88\xbc\xb7\xa8\x8b\xd9\xb5\x1a\xef\x67\xc7\x29\x71\xe6\xaa\xaf\x8d\x68\xd9\x85\x06\x58\x3b\x2a\xbb\xb5\x43\x38\xd9\xf3\x9d\xaa\xa7\x6a\xbe\xe6\x87\xb3\xde\xd5\x0c\x57\xdf\xdc\x3a\x55\x68\x73\xff\x9a\xca\x3a\x80\x6f\x49\x56\x06\x49\x59\xab\x87\x5a\xf8\x27\x08\xd2\x2d\x28\xaa\x78\xda\x90\xca\x98\xc6\x4d\x64\xf6\x8d\x9a\x71\x1f\xd5\x98\xd0\x39\x37\x9e\x9f\x32\xd0\xa1\x95\x46\x8b\xf9\xbd\x7c\x72\xe0\x10\x17\xee\x18\xb8\x30\xdb\xcc\x86\x9d\x5d\x40\xe0\x43\xac\x20\x72\xd7\xe6\xe0\xe6\x81\xa3\x9a\x57\x06\xdf\xd9\x1b\x68\x37\x9c\x82\xc7\x40\x38\x1b\x2f\x98\xa7\x51\xe8\x72\xf5\x14\x58\x74\x4a\x4f\x53\x54\x35\x0b\x44\xd8\xa2\xdc\x91\xb3\x8d\x2b\xbc\x1d\x62\x5d\xa3\x27\x23\x2d\x96\x01\xbb\x5c\xc3\x39\x22\x05\x2e\xb4\x33\xbb\x0a\xac\x84\x5d\xe4\x08\x74\x66\x1b\x1c\xdf\xcb\x47\x1c\xbf\x8b\xf3\xe1\xc9\x88\xee\x22\xb9\x60\x33\xa2\xad\x19\x11\x41\x16\x99\x8a\x0d\x86\xb1\xac\x18\xd4\x71\x04\x7c\x3d\x32\xfd\x4f\xcb\x53\x32\x46\x79\xe8\xa1\x96\x88\xc1\xc3\x03\xc5\x85\xc5\x59\x33\x38\x88\x42\x8d\xe7\xe1\x86\x9a\xc7\x9b\x0d\xdd\x30\x8f\x40\x8b\x8d\x6c\x44\x4b\x43\x85\xbe\x58\x1f\x65\xab\xcd\xb0\xed\xea\xaa\x4a\x94\xfd\xb6\x02\x55\xaa\xa7\x93\x41\x5e\x4c\xf6\x55\x0b\x95\x3b\xb4\xc7\x55\xcc\xae\x2b\xab\x79\x21\x55\x63\xe7\x35\x80\xb9\xbf\x9e\x7b\xb8\xaf\x46\x7c\x2d\xb9\xe0\x9c\x50\xa0\x1d\x36\xae\x4e\x15\x2b\xf7\x85\x31\x71\x98\x86\xa1\x5f\x84\xac\xde\x70\xc7\xf9\xc4\xb2\xc4\x25\x2e\xcc\x49\x4d\x2e\x70\xb8\x0c\x19\x2b\x05\x5d\xc9\x88\xee\xa2\x42\x6f\x1d\x05\x93\x4a\x7f\xc9\xa4\xc3\x68\x0e\xcf\x29\x1d\x0f\xe8\x72\x93\x85\xac\x80\xb5\x8b\xe0\xf4\x98\x94\xef\xfa\xd1\xc5\xb6\x27\x42\xd6\x8a\x0a\x86\x4f\xb6\xcc\x79\x0e\xde\x53\x53\x70\x1c\xda\xa4\x37\xef\xff\x60\x61\x5b\xae\x35\xeb\xc9\xcc\x0b\x99\x49\x78\xb8\xd0\xf6\xb9\x7b\xe2\x05\xcf\xda\x65\xf8\x37\x80\x73\x9d\xaf\x57\xc0\x2e\x72\xd5\xc2\xe0\xb1\xe4\x3d\x49\x9d\x4d\x52\xef\x1a\x5c\x01\x1e\xb3\x62\x37\xd7\xe0\x3d\x9d\xfe\x9e\x4a\x18\x68\x5e\xde\x2a\x87\x92\x94\xc2\x53\x06\xf7\xd4\x81\x21\xfb\x0f\xee\x8d\x86\x9f\x96\xdc\x9b\xfb\xc0\x12\x27\xac\xdc\x54\x8c\x08\x63\xef\x0f\x85\x51\x5f\x8c\x53\x95\xf0\x0b\x09\x82\xb2\x2a\x8f\xb7\xa3\x24\x2e\x65\x7c\x3c\x45\x3d\xed\x80\xf4\x6a\x99\xe2\xfe\xd6\x33\x2f\xeb\xe8\xab\x32\x17\x6b\xf6\x7b\xeb\x94\x6c\xde\xac\x79\x66\xc5\xee\xa6\x72\x67\x54\x28\x44\xa0\xfa\x2a\xf3\x6b\xc4\x0d\x43\xc0\xf3\x44\x84\x25\x3b\x2d\x12\x8b\xa3\x20\x06\xa8\x04\xfa\x33\x39\xa8\x65\x59\x8f\xae\x41\x7e\xfe\x3c\x34\x25\x74\x38\x19\x17\xf2\x01\xe6\x18\x70\x31\x61\xb4\x7f\xf5\x1d\x15\x7a\xe5\xd9\x7a\xc5\x23\xf0\x8b\xe7\x1b\x83\xa5\x1e\xc3\x8b\x7d\x2c\x71\x42\xd5\xf9\x34\xda\xde\xaa\xf1\xb9\xf9\xb8\xcf\x50\x11\x3f\x04\x0b\x6b\x2d\x81\x72\x0b\x09\x2e\x8c\xf9\xf0\x39\xb4\xa4\x2b\xb9\xa0\x3e\x74\x1a\x1e\xe7\xff\x74\xa7\xe6\x9e\x47\x59\x1d\xb9\x34\x24\xce\x2d\x5b\x10\x91\xdd\xf8\x77\x2f\x9f\x8c\x10\xe7\x1c\x11\x6c\x84\xc1\x3f\x5f\x11\x79\xc0\x26\xe9\xb4\xc8\x05\xa3\xa9\x94\xe3\x2e\x2b\xe4\x64\xd4\xd0\xd0\xae\x7e\x86\xd5\xf6\x8b\x6c\x36\xaf\xe9\x5e\x3b\xe6\x5e\x19\xab\x15\xfc\x1b\x50\x3c\x87\xbb\x2b\xc4\xf8\xe8\x83\xb3\x46\xb5\x56\x45\x70\xcf\x24\x4e\xfa\xd1\xf5\xef\x16\xc6\x09\xb7\xe9\x25\x0b\xca\xaa\x98\x7d\xe4\xfb\x7b\xed\x56\x86\xd1\x29\xea\xe9\x5b\x6c\x00\x38\x73\x75\x3e\xac\x0d\x52\x1f\x6b\x75\xeb\x7c\xa8\xb0\x00\x36\x3d\x40\xa0\x5a\x7b\x23\x02\x38\xd4\xe3\x05\xcf\x0a\x47\x13\x41\x96\xc3\xda\x1b\x24\x96\x14\xe1\x8e\xad\xff\x40\x56\x90\xfa\xd6\x75\x2c\xbf\xca\x27\x57\xe3\xf0\xae\xe4\xa2\x17\xae\xc1\x1d\xa4\x35\x50\x57\x9d\xde\x06\xa0\xea\xc1\x86\x19\x96\x1f\x49\x7c\x22\xa5\x95\x6f\x6a\xd3\x56\x68\x01\x1c\x15\x07\x5f\x46\xe5\x54\x58\xe8\x91\x4f\x9c\xa0\xda\x58\x24\x85\x6f\x7c\x6d\x35\x08\x89\xb3\xb1\x3a\xfb\x1a\x7a\x5b\x34\xbb\x6c\x66\xd0\x12\xa8\x20\x72\x55\x44\x4b\x32\xd0\x0f\x9b\xf2\x57\xf5\x0b\xfe\x8c\x79\xda\x1f\x9a\xfa\xdf\x4b\x3f\xae\x31\x40\x8f\x70\xd6\x12\xd2\xf3\x42\x66\xaa\xe5\x80\xc8\xe1\xe9\xc4\x49\x2f\xba\xfe\x4b\x92\x04\xd8\x89\x77\x0f\xd8\x95\x0f\xeb\xfd\x25\x93\x1e\x13\xfb\x5d\x1f\xc9\x73\x41\x26\xd0\x02\x1b\xf7\x57\xd5\x90\x3d\x41\xed\x98\x42\x85\xbe\xa6\xf1\x36\x3f\x9d\x65\x54\x97\xb3\x0c\xdb\x53\x7a\x95\x44\x11\x48\x9e\xfe\xcf\x0c\x57\x07\x6c\xdc\x5f\x65\x43\xb9\x43\x0e\x9c\xf7\xc5\xc0\x08\x94\xd4\x3a\x80\xe2\xcc\x50\x74\x1c\xdf\x8d\x22\x1c\xf1\x52\x59\x6c\xa0\xcb\xbd\x74\x61\xf2\x1d\x08\x80\x55\xfa\x45\xc8\xc7\x12\xc5\x76\x43\x93\x94\x5e\xa5\x39\xed\x70\xcb\xed\xd6\x21\x92\x8b\x29\xe3\x76\x93\x9c\x79\x9a\x19\x36\xee\xf5\x89\x0d\x04\x30\x87\x77\xf6\x28\x18\x81\x82\xae\x03\x28\x63\x63\x0f\xaf\x22\x15\x1e\x72\xf8\xa0\xb0\x71\xaf\x55\x10\x72\x2b\x25\x87\x31\x9f\xfd\xd6\x00\x01\x09\x49\x72\x54\xab\x83\x5d\x10\x42\xb5\xe3\x6d\xee\xe2\x67\x37\x90\xab\x08\xf3\x77\x0a\x6c\xa2\xa4\x2b\x47\xd0\xec\x3d\xc4\xbb\x5e\x4f\x99\x0a\xb3\xfc\xc2\x98\x48\x61\x81\x92\xdd\xbe\xa9\xbf\x94\xd9\x30\x3e\x4d\x5d\xbf\x75\x23\xcf\x7c\xfb\x47\xde\x55\x7b\xff\x43\x19\xf6\xc9\x64\xf6\x5a\xce\xde\x0f\xcd\x51\x42\x55\x0b\xb5\x3d\xbb\xfa\x48\xb7\x65\x5e\xa6\x1b\x5d\xae\xc6\xd5\x49\xfd\xe5\x57\x86\xab\x10\x53\xec\xf2\x69\xf8\x53\x72\xab\x0d\xba\x51\xbb\xcf\x2d\xf7\xd1\xcd\xe1\x55\x53\xd5\xa1\x05\x30\x18\x89\x12\xab\x7a\xb3\x71\x5c\x78\x34\xcc\x0e\xcb\x8f\x9c\x7e\x79\xd8\x69\x3d\x98\x54\xa7\x08\xff\x3c\xc9\xbf\x84\x5f\x4c\x7e\xcb\x6f\x36\xf8\x78\x6d\x58\x93\x51\xbf\x6d\x7c\xab\x3f\x54\x3a\xc2\x2c\x0c\xa0\xda\x20\x4d\x57\x89\xeb\x4a\x22\xd7\x7f\x6f\xb5\x96\x14\xb0\x54\xc1\xbc\xfc\x25\x93\x6e\x8b\x20\xd1\x64\x38\xbd\x13\x05\x2b\x2e\x72\x5f\x3c\xd0\x2b\x3e\xe7\xca\xbd\xb0\xa2\x48\x9e\x6b\xd9\x26\x7e\x53\x06\xd4\xf9\x60\x48\x9f\x9b\x09\xea\xe7\x1f\x1f\xd5\x65\x51\xa3\x22\x42\x95\x88\xe4\xde\x26\x68\x50\x68\x44\x14\x6c\x40\xa8\x9f\xb3\x74\x32\x6a\xa2\x37\xea\xc1\x3f\xbf\xe4\xf5\x43\x6c\x00\x6e\xf2\x2a\x74\x1b\xdd\xe3\x3e\x18\xf2\xb7\xb9\xb2\xb8\x6d\x8b\xa1\x3f\xb3\xa6\x2b\x48\xc5\x8a\x26\x36\xf6\xfe\xc7\x33\x78\xcc\x49\x36\x66\x83\xa6\x53\x7b\xfa\x5d\xf9\x64\xd4\xa0\x74\xe0\xc5\x14\x63\xc0\xcf\x5e\x9a\x05\xb0\x12\x76\x82\x33\x9c\x07\x9a\xdc\x73\x92\xfa\x4b\x75\x68\xc1\xc8\xef\x67\x49\x4f\xf2\x84\x87\xea\xd0\xbc\x04\x18\x29\xe1\xc9\x2e\x9a\x3a\xc9\x88\xb0\x83\x91\xe9\xea\x12\xa5\x25\x17\xca\x99\xa9\x8f\x0c\xfb\xd6\xbc\xcc\x7b\x2b\x60\xe4\xf2\x4c\xc9\x57\x2e\x6b\x74\x95\x64\x9f\xab\x48\x9f\x9b\x89\x8d\xc5\xf5\xab\xe8\x2a\x3b\x1f\x04\xa6\xd6\x56\x74\xc1\xd2\x2f\x4b\x89\x50\xd6\x70\x09\x1e\x0f\x59\x6d\x73\xa0\x61\x68\x62\x85\x51\xf7\xef\x83\x94\xf0\x59\xdc\xb1\x46\x53\x29\xe4\xce\x9a\x06\xd4\xf0\x9c\x4a\xef\x5a\xa0\x62\x9f\x48\x7b\xab\xa9\x0e\x9c\x00\x3b\x3e\x18\xe0\x60\x35\x43\xc4\x15\xf9\xcd\x05\x55\xc9\xd4\x9e\x87\x27\x41\xfc\xbe\x1b\xad\x1a\x2f\x0f\xb0\x40\x92\x92\xc5\xec\xae\xb5\x89\x58\x60\xef\x8c\x26\x27\xa8\x36\xf6\x0f\x6f\x17\x49\xcd\xff\xc3\xb2\xeb\x53\x89\xd0\xa9\x9e\x07\x69\xf9\x3b\x94\xfb\x28\x70\x5c\x53\x36\x2f\xc1\x12\x82\x1c\xf6\xc1\x36\xd1\x1b\xb5\xe0\x1f\x0c\x78\x5f\x83\xf6\x94\x16\x67\x59\x52\x84\x95\x67\xaa\xe7\x4b\x3a\x54\x3d\x43\xf2\xcc\xfc\xca\xd2\x8a\xbf\x8c\x6a\xc0\x53\x6d\x83\xe7\x00\xde\x45\x7e\xc3\x9b\x55\x6f\xf6\xa4\xe6\xb4\xdf\x3c\x4d\x92\x47\xfa\x3e\x74\x68\xa2\x87\x86\x63\xe3\x62\xf9\xaf\xb0\x13\xa4\xb0\x68\x9e\x2f\x91\x6b\x44\x78\xd9\xfd\x48\x79\xd5\x3e\x7c\xc6\xca\xc3\x7e\xf7\xe2\x2d\xbd\xfd\x63\x09\xa3\x92\x60\x13\xc2\xdd\x12\x9e\xd9\x0b\xca\x62\x7d\x42\x28\xb9\x1d\x5f\x26\x98\x7e\x11\x82\xf9\xa1\x7a\xde\x33\x24\xaf\xed\x73\x89\xa6\x0d\xba\x31\x04\x2b\x41\xdd\x51\x3c\x77\x4b\x33\x34\xe3\xc7\xf9\x3c\xf9\x96\xcd\x93\x4e\x67\x9a\x5f\xa6\x92\x31\x1b\xdf\x83\x49\x9b\xf3\x2c\xd0\x19\x59\xb6\xfe\x56\xcd\x2d\x55\x0c\x25\xe7\x91\x7f\x97\x26\x59\x6b\x33\x8d\x12\xa4\x82\x6a\x02\xc0\x66\x61\x8c\xe6\x29\xcd\xaa\x37\xbb\x97\x5e\xdf\xd3\xb5\xda\x1e\xc9\x26\x8d\x9b\x32\x7e\xec\x1c\x19\x28\x1d\xf1\x88\xc9\x7a\xab\xaf\x82\xff\x7a\x48\x2d\xa1\x47\x0e\x69\x7f\xfe\x6c\x5e\xaa\x81\xe3\xc7\xcf\xce\x38\xa0\x0b\x1f\xe9\xbb\xa9\x41\xa1\xc5\x5e\xf6\x3e\xc5\xaf\x7b\xca\x63\x78\xf1\xbc\x87\x57\x9c\x20\x04\x69\xb7\xb4\x12\x4c\xda\xec\x66\x81\xa2\x50\x40\x3d\x21\xfe\x2f\x77\x28\x10\x3f\x1b\x37\xe7\xb6\x01\x95\x3c\x72\xc5\x38\x27\xfd\x2a\xb9\x80\x31\xe2\x23\xb4\xa9\xde\x6c\x38\x33\xfd\x35\x75\x74\xeb\x3b\x4b\x8b\x50\x45\xc5\x95\x69\x12\xd5\x13\x04\x8f\x3a\xb0\x87\xf4\x51\x0f\x2e\x97\x02\x7d\x08\x35\xcb\x58\xec\xcc\xd6\x8a\xd0\xd5\xa1\xe5\x09\x16\x84\x61\xdd\xe9\xbd\xa9\xf1\x5a\x66\xdf\xc6\xdd\x73\xe0\x81\x51\x7b\x2a\x24\xe2\xa1\x13\xba\x89\xde\xa8\x73\xf6\x83\xec\x25\xfa\xb2\xc2\x4d\x5e\x85\x8c\xe1\x0f\xdc\x57\x42\x57\xaf\x5d\xd9\x5b\x34\xa0\x23\xc9\x05\xb6\xc3\x9b\x87\x13\x5e\xac\x1c\x9d\x6c\x9a\x00\x24\x48\x2d\xa9\x8a\x0f\x5d\x80\x13\x20\x89\x9c\xea\x89\x82\x1a\x40\xe1\xb6\x53\x91\xdc\x06\x06\xa6\x28\x99\x3e\xc1\x50\x0d\x52\xfb\xbe\x17\x96\x1f\x53\x9b\x38\xda\x35\x91\x91\x57\xb0\x5a\x89\x7b\x19\x36\x3a\xc8\x82\x11\x62\xfa\xfb\x56\x8d\xcf\x55\xf1\x45\x8b\xb6\x41\x2d\xae\x73\x96\xbe\xe7\x32\x45\xa5\xd0\x95\x5a\xd2\x06\xe5\x5a\x64\xc0\x06\x28\x5d\xe4\xcc\x16\x9f\xc7\xee\x86\xfc\xc4\x4c\x59\x9c\xa5\x3c\x46\x0b\x6c\xe7\x0d\x53\x8f\x0f\x5e\x66\xc9\x93\xc2\xcf\x43\x30\xca\x16\x3b\xcc\xdc\x89\x7b\x6a\x49\x49\x72\x54\x38\xc2\x2b\x6f\xea\xac\xff\x64\x74\x82\xce\xfa\xa5\x92\x53\x56\x71\x96\x10\xcc\x46\xe3\xd9\xa5\xee\xf7\x8a\x78\x34\xf1\x3e\xdf\x2b\x9e\x4b\x1f\xd4\x31\xca\xd7\x44\x67\x3f\x0c\x3c\x17\x43\xfd\xbc\x9b\xc5\x52\x26\x5c\x20\x8c\x2e\x09\x2b\xaa\x07\xa9\x6f\x96\xb5\x08\x83\x8d\x18\x3e\x81\x1c\x03\xd5\x23\x1e\x23\xc2\xff\x26\x53\x85\xdb\xc4\x9c\x4e\xa4\xc3\x3e\x0c\x0a\xbd\x72\xff\x8d\x1b\x39\x0e\x36\x60\x28\x96\x68\xcb\x74\x0e\x50\xf3\xdc\x66\x13\xd4\x6d\xec\xf7\xc8\x2c\x2d\x42\xa7\x37\xe7\xa2\xf6\x55\x6f\x69\x34\xd0\xc0\x84\x44\x80\x01\x97\x1c\x71\xd9\xa1\xc3\x7f\xe8\x1a\x10\x2f\x63\xbf\xfe\xf7\x27\xb4\xe7\x46\x4f\x68\xef\x86\x96\x74\xd0\xe9\x0f\x21\x19\x43\xa5\x85\x23\x5a\x13\x9f\x3d\x32\x15\x01\x1c\x37\x56\x77\x13\x15\x30\x1c\xd7\x6e\x48\xb5\x0f\xf8\xee\x9d\x86\xc7\x90\x5f\x7f\xf6\xde\xd3\x9f\x52\xfe\x3b\xd8\x55\x48\x32\x55\x2d\x52\xea\x95\xec\xce\x5b\xd9\xb6\x20\x29\xe2\x75\xaf\x18\x13\x5e\x4e\xb4\x6c\xbe\x70\x74\x32\xe3\xb1\xb6\x0f\x87\xba\xb8\x87\x3e\x79\x6b\xf3\x95\x52\xbf\xf2\x8d\xed\x84\xd2\xc4\x21\xb7\x51\x25\x3c\x9a\x98\xc0\x65\xe1\x54\xd4\xdc\xfc\x16\x22\x50\x3e\x38\x52\x74\x26\x98\x61\x42\x72\x31\x25\xd6\x5c\x78\x7d\xef\xab\xfb\xa3\xd5\x10\x8f\x51\x9c\x39\x56\x1c\xf9\xc7\x47\xac\xfc\xd5\x88\x87\xee\xc0\x57\xcd\xc4\x67\x20\x5d\x40\x57\x3e\x44\x07\x31\xd3\x3f\x1a\x1d\x7a\x16\x1e\x43\xc6\x94\x5a\x0f\x2d\x04\x7d\xd9\x1e\xde\x77\x9b\x58\xec\xd7\xf7\x72\xc0\xca\x22\x3f\xbe\x03\x2f\x36\x86\xb7\x60\x0c\xe5\x56\x6a\x8b\x21\x5e\x9e\x3b\xba\x0b\x0a\xe9\xf1\x1e\x58\x4e\xf9\xd2\x91\x2f\x8d\x62\xb8\xd8\x41\x87\x22\xc3\xa2\x54\xdb\xd0\x30\x5c\xed\x15\x47\xf6\x00\x39\x15\xe1\xbe\xb2\xac\xa3\x40\x55\x5e\x92\x6c\x39\x01\xd6\x67\x40\xaf\x89\xce\x7d\x62\x75\xc8\xb8\xcd\xd6\x4d\x5d\xfd\xf9\x2f\x82\xa5\x45\x88\x9f\xe9\x40\x13\x67\x87\xbe\x6a\xce\xae\xe3\x17\xff\x70\x2e\xa8\x20\xa3\xbf\x6d\x75\xef\x1b\x9b\xa4\xc0\x4c\xfa\x26\x3c\x26\x73\x37\x47\x13\x74\x57\xbd\x8b\x7b\x03\xe2\x92\xe4\xa9\xcf\xb6\x82\x0b\x2b\xbc\x85\x32\x3a\x18\x64\xae\x9d\x63\x03\x4d\xea\xde\xca\x48\xa3\x73\xf5\x11\x5b\xe8\x96\x38\x4b\x39\xaa\xf9\xa0\xe4\xbc\xf3\x12\x6e\x54\x7f\x86\xf8\xd5\xc4\x24\xd5\x16\x3a\x13\x41\x1e\xf1\x98\xdc\x0d\xac\x0c\xb7\x9c\x49\x7a\x7f\x56\x19\x69\x77\xe1\x1f\xc7\x1c\xc0\x3b\x99\x7d\x59\x75\x59\x54\x23\xf8\x37\x80\xad\xc2\x0e\x36\x7e\x29\xe4\xc7\xb7\x7c\x8b\xe9\xe1\x4d\x68\x3d\xbe\xb1\xe5\xed\x0d\x07\x82\xad\xe9\x5c\x08\x4e\x18\xac\x8f\xca\xba\x76\xe3\xc5\xb7\x20\xd6\x97\x3d\x77\x63\x93\x54\x5b\x29\x75\x56\xbf\xe4\x2a\x05\x74\x17\x83\xe2\xe9\x61\xb5\x87\x20\x51\xa9\xd5\x0b\xf6\xec\x7b\xea\x09\xa7\x5d\x57\x3e\x08\x69\x9d\x4e\x87\xd9\xbb\xbb\x62\x50\x33\xed\x92\xab\xf7\x10\x1b\x10\x38\xc9\x0a\xc9\x70\xf9\xa7\x86\xa0\xf6\x86\x6b\x9f\xbe\xc4\x8c\xa6\x5f\x85\x08\xd4\xe4\x46\x8c\x6f\xff\x33\xde\x55\xc5\x4b\x8b\x65\x40\x90\x8f\x7b\xaa\x16\xf1\xeb\xe7\xfc\xa7\xdd\x8b\xef\x37\xdc\xc3\x4a\x20\xa3\x4a\xd5\xdb\x8d\x43\x1c\x80\x3a\x6a\xaa\x48\xc2\x8a\x47\xdf\x70\x92\xfb\x6c\xf4\x68\x7e\xfd\x90\x0d\x89\x64\x2a\x71\xa5\xc8\x1d\x73\x96\x31\xa3\xf9\xb7\x1d\xbf\x78\x93\xe6\x8d\x43\x32\xb0\xb6\x21\x7b\x5f\xc3\x90\xdc\x64\xd4\xe8\x8b\xb7\xee\x38\x62\xaa\x7c\x0f\xaf\x2a\xfd\x21\x44\x20\x53\x81\xf6\xa4\x29\x3c\x2d\xfc\x38\x22\xf9\xa9\x19\x03\x76\x2d\x4b\xfa\x18\x58\x1f\xd5\x72\xad\x24\x41\x6a\x55\xf1\xd3\x8b\xdd\x32\xdb\xc9\xd3\x49\x96\xf2\x98\xf2\x95\x9d\x01\x0f\x2b\xbe\xb1\x5e\xb7\x15\x69\xb1\x0c\x32\xa6\x18\x3a\x98\xd8\xd9\x06\x81\xc7\x90\x65\xfb\x32\x94\xce\xf8\x4f\x46\xdb\x06\xc0\x95\xe1\xf1\xe4\xd6\x7f\xbf\xa0\x16\xc6\x21\x9b\xbc\x4d\x2f\x40\xd2\x7c\xd0\x99\x7f\x21\xa6\x28\x15\xdb\x34\x12\x49\x9e\x5f\x28\x6f\xb2\x84\xf3\x1a\xba\x4a\xd2\xe5\xeb\x76\x85\x95\x5c\xc6\x4a\xca\x5c\x64\xd1\xfa\x92\x40\xb0\xfd\x41\x1c\xdf\x6d\x2d\x92\x9e\x24\x9d\x81\x29\xaa\x5b\xfd\x5c\x7c\xf2\xfe\x59\xed\x22\xf4\x96\xde\xae\xfb\xd2\xea\x8d\xcb\x0d\x22\x60\xf3\xe9\xe2\x6e\x97\x15\xfc\xfa\xb9\xe0\xb6\xed\xfc\x0b\xea\xf0\x44\x72\xa0\xfb\xda\xd2\xc7\x53\x73\xfe\x0d\x4a\xea\x97\xfc\x6e\xaf\x68\x46\x4c\xe5\x41\x30\x12\x93\x4d\xb3\xa8\xe4\x84\xb5\x8e\x8d\x2c\x87\xcb\xe1\xcb\x42\xd2\x9b\xad\x74\xaf\xe2\xf9\x47\xe2\x7d\xff\xd3\x07\x01\x17\xf9\x8d\xdf\x3d\x39\xac\x6c\xd1\xd1\x6f\xdf\xf3\x81\x47\xbd\xa0\x69\x6c\x9e\xa5\x4c\xf8\xfd\x4b\x00\xfa\x5a\x93\x38\xde\x14\xf8\xcf\x41\xb7\x67\x5e\x1c\x1a\x45\x80\x9d\xce\x30\x3a\x05\x8d\xda\x65\x10\x65\x1d\x03\x36\x49\x7a\xba\x0f\xf5\x36\xbd\x9b\xad\xf6\xb2\x17\x02\xf6\xea\x51\xa4\xfa\xef\x91\xb6\xfe\x3a\x77\x4a\x20\xd2\x48\xb7\x6c\xca\x6e\x77\x49\xc1\x8d\xe1\x3f\x4f\x12\x72\xff\x19\x7d\x6a\xd9\xd1\xae\x5a\x68\x51\x80\x27\x91\xc5\x9f\x46\xba\x73\x89\xad\xfc\xfe\x18\x82\xfe\x2f\xc6\x89\x3d\xa7\xfd\x89\x77\x3b\x40\xc5\xca\xd7\xfb\x6d\xfe\x4f\x77\x7e\xe4\xb5\xbe\xd6\x23\xad\x7e\xc7\xf1\xc2\xb7\xed\x0f\x7c\x9c\x05\x96\x34\x48\xeb\xbb\xc5\x86\x2d\x96\x70\xac\xde\x72\x8b\x0d\x3b\xa1\x3d\xde\x95\x80\xdb\x8c\xae\x5a\x68\xd6\x60\x9b\x74\x67\x90\x10\x03\x69\xf2\x24\x9b\x76\x23\x9c\x00\x74\x61\xeb\xa9\x39\xea\x70\xa2\xee\x9c\x94\xe7\xf6\x66\x58\x55\xf8\xb3\xc6\x59\x29\x45\xf5\x20\xef\x1b\x0e\xa5\x67\xbd\xff\xf5\x1e\xfa\x07\x2c\x61\x4b\x94\x15\xeb\xe2\x44\xbf\x3f\xd5\x14\x8b\x6a\x99\xc6\xc4\x27\xea\x2d\x71\x3b\x35\xa5\x85\x24\xd3\xe9\x96\x90\xbf\x52\x92\xb9\x9f\x02\x60\xee\x2f\x6f\x08\xb7\x91\xde\xf2\x9b\x31\xaa\x2e\xca\xcd\xe6\x35\x06\x5d\xed\x77\x28\x6d\x1a\x7b\x30\xa8\x19\x9e\xb6\xf3\xc9\xdb\x5f\xd7\x5a\x92\x52\xbf\x92\x12\x9b\xfc\x6c\x3e\x58\x2b\x63\x6b\xcd\x3e\x44\x4f\xe0\x5d\xe7\x0e\x98\xcd\x5e\x9f\xf6\x67\xd6\x3f\xf7\xdf\x96\x02\x9b\xa0\x70\xa7\x0f\x59\x72\x35\xf7\xce\x89\xcd\x5f\x93\x5b\x19\xfa\x45\x80\x59\xe4\xee\xea\xb7\xc4\xfe\x10\xb3\x1b\x94\x99\x9d\x9c\x29\xdb\x95\xdb\x1c\x94\xe1\xda\x07\xda\x16\xdf\x6f\x59\x7f\x2f\xfc\xc1\xcd\x04\x85\xae\xaa\x08\x58\x28\x5b\x92\xb4\xfb\x3c\xe0\xdb\xe3\xb6\xd3\x76\x23\x6d\x7f\x7a\x86\x8e\x81\xac\xf6\x3f\x5f\xc9\x07\xf9\xef\x7e\x66\xf5\x3e\xa4\x67\x47\x88\xd8\x87\x39\x23\x55\xa9\x83\xe1\x5f\xdd\x57\x30\x53\x86\xed\xe2\x47\x36\x07\xcd\x4f\xe8\xed\xd7\x15\x9c\x50\x1d\x9a\xd3\xf7\xfa\xf3\xbd\x78\x3e\x9c\xab\xcf\xcd\xc4\xe0\x75\xd1\xba\x40\xe9\xab\x25\xa4\xe2\xde\x54\x62\xd5\x1b\x6d\x75\xf8\x13\xf2\x5e\x9d\xcc\x00\x95\xcd\x68\xdd\x62\x73\x1f\xf1\x3e\x22\x99\xfa\x48\xe2\x85\x05\x99\xd9\xbc\x9d\xc9\x3e\xfa\x51\x8f\xd1\xd5\x53\x8a\x0b\x5b\xe2\x3b\x2b\x2e\x67\xea\x05\xaa\x45\xac\x5e\xd6\x2f\x1d\x2a\x69\xc8\x33\x75\xcb\xb6\x2f\x1c\xa7\x2a\x97\xc8\x27\xe8\xce\x71\x57\xb5\x2f\x28\xec\xf7\xe1\x4c\x8a\x52\x7b\x65\x86\x38\x8a\x38\xec\x77\x2d\xad\xd5\x8f\x14\xb4\x1b\x29\x60\x78\x7f\xc9\xcc\xe6\x3d\x98\x17\xf2\xff\xf8\x61\xb7\x2a\x3c\x48\xee\xb5\xa3\x03\xf0\xb2\x5b\x3b\x77\xf1\xdc\x5e\x95\xa5\xfe\xaf\x3f\x67\x8a\x7b\x1f\x73\x7b\xe6\x5f\xf3\x4c\xd0\x59\x96\x39\xb1\xbf\xf4\xdc\xa6\x3d\x5d\x41\x20\x72\xea\xfb\x1f\xc4\x40\x9f\x3c\x89\xdd\x51\xcf\xa9\xd0\xdb\x3d\x8d\x59\xf6\xc7\xc0\x2e\x5a\x55\x8a\x9f\x75\x6b\x46\x57\xde\xe4\x88\x73\x64\x6c\xf9\xdb\x06\x84\xa8\xf6\x65\x28\xa1\xec\x83\x1a\x85\x8a\xe8\xa2\xd5\x95\x0d\xe2\x7a\xfb\xb0\xc1\x80\xbd\x93\xf0\x78\xf2\x48\x03\x60\xe0\xed\x88\x87\x25\x76\x86\xa7\x41\x47\xee\xd2\x91\xae\x7c\x88\x45\xf6\xf7\xd6\xbd\x0e\xef\xdd\x87\xce\x9d\xb2\xd8\xe6\xcf\xde\xbb\x3b\xe6\x55\xe1\x7b\x0a\xc5\xb6\xd4\xf9\x9d\x43\x25\x42\x16\x42\x01\xc1\xa1\xd8\x4b\x02\x29\x66\x61\xda\x9f\x2c\x77\xa1\xe3\x53\xb9\x66\xdb\x7b\x7e\xf4\x87\x90\xd5\x1f\x27\x99\x37\x99\xda\xc3\xc1\xad\x9e\xef\x1c\x3c\x3a\x2b\xeb\x77\x82\x09\xb6\x9e\xa2\x6d\x7b\x27\xf0\xbb\xad\xe8\x7b\x53\x13\x33\x6a\xee\x4b\xbf\x5b\x9c\x77\x46\xf3\x3a\x62\xac\xa4\x3e\x7d\x08\x18\xb9\xd2\x3c\x79\x2c\x7f\x7b\xfd\x70\x69\xa0\x2a\x9f\x30\xdb\x5a\x46\xd0\x53\x76\x59\x35\xa5\x35\x6c\xde\x19\x56\xc3\x7f\x9d\x5d\x9a\x41\xa2\xa8\x68\xe0\xb6\x3b\x73\x0d\x30\x95\x1f\xb6\x7f\xba\xea\xcd\x0e\xff\xb8\xa3\x56\xae\xc0\x7e\x30\x2c\x4d\x6c\x5f\x60\x4e\xbb\x2c\x39\x89\xe2\x94\xa1\xb0\xad\x11\xdc\xa9\x94\x7f\x41\x14\x6c\x84\xf2\xf6\xab\x06\xf9\x7b\xc5\x9e\x31\x4f\x03\x47\xda\xb1\xc2\x3b\xd2\xc9\xa8\x92\x83\x8d\xd1\x9c\xe4\xc2\x1f\xfb\xe3\xd0\xcf\xf6\xb5\xd8\x8e\x37\xba\xd4\x10\xa6\x6d\x96\x34\xc2\x6b\xf4\x3b\x55\x77\xfe\xe2\x81\xf4\x37\xd1\xbf\xa5\x19\x1a\xfd\xa4\x2c\x37\xfa\xbb\x0b\xb5\xf7\x7a\xaf\x64\x77\x76\xc3\x3f\xc4\x30\xd4\xdb\x6a\xe1\xc0\x93\x8b\xe0\xd9\xbc\x9d\x1f\x79\xe9\xcd\xfc\x5c\x13\xef\xf6\xd2\x9f\x2c\xb4\x44\x09\xe4\x05\x9e\x1c\x17\x6b\xc4\xff\xf8\xda\x02\x7c\x2d\x40\x7f\xdb\xeb\x5e\xdd\x64\xe9\x3c\x51\x7e\xc3\xa4\x3d\xa5\xd7\x4e\xc9\x6f\x26\xba\x1e\xcd\xbc\xa4\xa6\x8a\x3c\xc7\xdc\x8d\xda\x4d\xd3\xe4\x6b\xd4\xd3\x92\x9c\x13\xdd\xb4\x18\xbd\xf3\x7b\x46\xe0\x42\xe8\xef\xc5\x9e\x54\xc6\xf6\x0f\xe3\x22\x94\x4c\xe2\xab\x60\xbe\x3e\x4a\xac\x71\x7b\x4a\xaf\xf6\x7e\x91\x9d\x7a\x6f\x37\x62\x23\x41\xad\x39\x13\x92\xe1\x70\x1e\x2d\x02\x76\xf6\x48\xc7\xe0\x7c\x5e\x0e\xfe\x04\xb3\x55\xd2\xfd\x8d\xfe\x6b\x57\x6e\x6f\x78\x2e\x55\x67\x19\x99\xa0\xf4\x6c\x4d\xc4\xc3\x26\xf5\xda\x06\x6a\xe8\x48\xc8\xea\xa7\x27\x68\x62\x82\xff\x78\x74\x3d\x8a\xbd\x51\x8b\x0f\x54\x4b\x96\x29\x20\xdf\xe7\x57\xcc\x9d\x55\x7d\x7a\xdd\xb8\x5d\x5c\x70\x93\x9c\xe5\xcf\x3d\x91\x56\xf5\xa6\x25\xe2\xdf\xb2\x95\xcb\xce\x68\x1e\x72\x86\xf8\xd5\xe0\xde\x25\x78\x46\x70\x71\x45\xa0\x02\xc9\x2a\xc8\x0a\xcb\x8f\x6c\xfa\xf7\x6d\x55\xd8\xf7\xc7\xeb\xc3\xff\x95\xe9\x25\xb5\x41\xbd\xcd\xd3\x7a\xd2\xf1\xbb\xad\xcf\x3f\xf7\x3b\x76\x7c\xd8\xcf\xe9\x8e\xb1\xb2\x04\x2b\x85\x31\x7f\xb0\x4c\xa7\x53\x07\x9b\xdd\xad\x87\xd6\x83\xe8\x1a\x90\x55\xe3\x1b\x2f\x2e\x78\xca\xa5\x93\x39\x74\xad\x5f\xe2\x62\x1e\xe0\x7c\x78\x07\x85\x46\x74\xfd\x72\x56\xc4\x15\x6f\xec\x8b\xcc\x09\x04\x98\x98\xa0\x84\x12\x74\xff\x0c\xdb\x8a\x2e\x48\x83\x0d\x50\xeb\x02\xc6\x6c\x31\xcd\xb9\x48\x56\x73\x4d\x25\x17\x5c\xb5\x7f\x20\x37\x2b\xc6\x37\x06\xbb\xa2\xfb\x79\xe2\x8f\xca\xf8\x7e\x7d\x7c\x87\x4c\x38\x50\x51\x3a\xce\x92\xfc\x40\x62\xa8\xa6\xd2\xea\x26\xf8\x89\xe5\x49\x6a\x83\x60\x27\xc3\x75\xf3\xb6\x23\x59\x52\xb8\xad\x88\x6b\xb9\x7e\x91\xbd\x2a\xfc\x92\x99\x25\x85\x32\x62\x8b\xbf\x5c\x0e\x79\xaf\x73\xc5\x61\x47\xf3\xfe\xc6\x8a\x46\x55\xf8\x9a\xfa\x37\x62\x5c\x12\x59\x8d\xaa\xa6\x83\x4f\x7d\xbf\xaf\x05\x8f\x21\xcf\x67\x2f\xa7\x97\x4b\x46\x7f\x1b\x2f\x24\xc0\xb8\xa5\xc5\xe6\xf2\x76\x32\xc7\x6a\x71\xe5\x43\x07\xa2\x2c\x04\xf7\x29\xe6\xeb\x25\xea\xf2\xe2\x73\xff\x53\x70\x42\xbd\xd3\x44\xb9\x1e\xb9\xe2\xf5\x57\x8e\x74\xb3\x4f\x08\x65\xa4\x91\x8b\xdc\x6c\x9e\x73\xf3\x83\x42\xc9\xc1\xf5\x91\x5f\x41\x1b\x5f\xea\x94\x82\x57\x6a\xf8\x8d\xa7\x13\x5e\x05\x9b\x63\x8f\x20\x87\x57\xab\xea\x1c\xf4\x34\x8a\xd8\x9b\x89\x99\xd3\x68\x5d\x63\x0c\x44\x40\x32\xef\xcc\xa0\x5e\xe6\xb3\x79\x8f\xd1\x4d\xbe\x4f\x2d\x1b\xa1\x8a\xcd\xcb\x77\xc5\x5b\x34\xe1\x49\x93\xf9\x35\xa3\x27\x0e\x26\x60\x0c\x79\x1e\xfd\x59\xaa\x2c\xef\xd9\x0c\xfe\xdb\xdf\x7c\x48\xf7\x65\xb7\x21\x7b\x2a\xd4\x1f\x57\xae\xbe\x84\x5c\xf2\x1b\xd1\x1b\xd0\xf1\xba\x75\x23\x3c\x46\x60\x4a\xda\x2a\xfc\xfb\xbb\xc2\xf7\x1e\x3f\x54\x13\x2e\xfd\x05\xd3\xe5\x20\x7e\xfd\xfb\xcf\xbb\xbc\x6b\x40\x66\x28\x99\xa0\xdb\x55\xb8\x25\xbb\xf0\xdf\xdf\xcf\x86\xe4\x87\x8d\xde\xfa\xa4\x1e\x78\x58\x78\x34\x10\x3c\x37\xdb\xc3\xd2\x22\x46\x7b\x3e\x82\x55\xeb\x58\xc5\x27\xc9\x51\x43\x26\xab\x4c\xb4\x66\x10\xcf\x28\x48\x01\xad\x87\x6a\xde\x6a\xc8\xf7\x9f\x10\x03\x7a\x9b\x12\xc9\x4f\xd7\x50\x33\xf5\xcb\x27\xf6\x67\x6d\x30\xf6\xfb\x8e\xf4\xab\x30\x3e\xf9\xf6\x1d\x6a\xbf\xb5\xe9\x9f\x7f\x1b\x75\xb7\xf5\x34\xb2\x0e\x8f\xa9\x3a\xfd\x93\x0a\x6f\x81\x08\x80\xd7\x01\xdb\xed\xbb\xad\x23\xf7\xf4\x02\x25\x85\xc5\x5e\x7c\xfc\x70\xc3\x11\x19\xf2\x5e\x87\xfe\x10\xc6\x9d\x31\xb7\x96\xef\xff\xad\xab\xd0\xc5\x74\xfa\x05\xda\xea\xf0\x14\xea\x60\x86\x9d\xb3\xfe\x79\x57\x4c\xf5\x69\x40\x72\x92\x86\x54\x23\xae\xbc\xec\x56\xcb\x8e\xc4\xf8\x94\x4e\xf6\xda\xb0\xa6\x91\x09\x9d\x3f\x41\xea\xe1\x85\x84\x5e\x92\x8b\xe9\x74\x12\x3a\x8f\xfb\x1d\xc8\x0c\x95\x67\x9b\xa5\x0d\x9e\xcd\xda\xf9\x91\x57\xaf\x37\xe0\x3e\xa7\x5d\xe6\xbe\xa3\xf7\xc2\xa8\x79\x8d\xc1\x52\x26\xbe\x34\x0b\x0b\xf1\xdc\xce\x11\x05\x1b\xa0\x02\xa4\x34\x87\x46\xb5\x4a\xd9\x78\x0b\xd2\xc6\x2a\xc3\x6c\x90\x12\xc6\xf3\x42\x6b\xc9\xeb\x42\x9f\x3c\xdc\x03\xce\xec\x51\xc4\xbe\xd5\xcf\xef\xb0\xbf\x19\x1c\x77\x94\x00\xeb\xa3\x02\x66\x9f\x51\x3a\x5e\xbd\xe1\xce\x99\xc3\x2f\xfe\xf5\xdd\x68\x22\xc0\xd2\x4b\xba\xa0\xf8\xdd\xdf\x7b\x4e\xf9\x3f\x0e\xb1\x01\x4b\xcb\x6a\x14\xf3\x30\x29\xa2\x5f\x67\xd3\x84\xdf\xdf\x02\xba\x06\xc4\xaf\x3d\xed\xee\x72\xf6\x5d\xbb\x69\xcb\x67\x7f\x16\xd2\xc8\x05\xb6\x3f\xef\xba\xab\x0e\xcd\x1d\x05\xbb\x68\xd5\xea\x69\x81\x14\xd5\xb5\x63\x9f\xec\xef\x19\x78\x78\xc5\x25\x15\xbe\x2e\x06\x4f\xa4\x5b\xab\x3e\x41\xdb\x5b\xeb\x0d\x21\x58\xef\xea\x14\x30\xbc\xa1\xf5\x1e\xfb\x13\xef\xf6\xbe\xec\xb6\x72\xd2\xb7\x3e\xe2\xce\xee\x7d\x9c\x6a\xdd\x68\xa2\x5f\x5d\x11\xf7\x4c\x0e\x11\xcc\x08\xd2\xd5\x72\x50\x8d\xdc\x3b\xde\x06\xb5\x10\xe5\x04\xf4\x4c\x76\x43\x30\x37\xeb\xf4\x06\xf4\xe6\x85\x04\x33\x43\x87\x93\xc5\x5b\x16\xa1\x9f\x95\x48\x24\x0f\x73\xe3\xe9\xde\x35\x9c\x3e\xf6\x08\xd2\xf7\x9d\x55\xa6\xa2\xb9\xfb\x56\xf6\xdd\x73\x72\x97\x1e\x65\xb6\x58\x11\x62\x32\x85\xdb\xf6\x1e\xe2\x7c\x16\x27\x5a\xf6\xd4\x84\x47\x83\xee\x61\xf9\x75\x62\x06\xc7\x1d\x79\x6d\x0b\x5d\x4c\x89\x0d\x27\x70\xad\x1a\xd9\x77\xa6\x0e\xbc\xf9\x25\x33\x2b\xbf\x0e\x00\x5c\x9f\x99\xf6\x7d\xde\xb8\xb3\x40\x72\xf1\xe0\x63\x0f\x43\xbf\x8f\xaf\x5e\x98\xc8\x61\xca\xbf\x6c\x08\x55\x44\x5b\x13\x82\xbf\x8c\x17\xee\x7e\xff\x29\xd3\xa8\x07\x8f\xa9\x71\x7a\xb4\x3a\xfa\x6d\xeb\x63\x16\xfb\xae\x67\x88\xce\x29\xf8\x63\x72\x5d\xf6\x3f\xe9\xb1\x84\x23\xce\x99\x8a\x22\x4e\x7d\x57\x46\x0d\x09\x31\xcf\xa3\xcb\x71\xbf\x64\xa4\xb0\x5e\x8a\xcd\x9b\xc1\xea\x65\x32\xd6\x7d\xc3\x2f\xa4\xc0\xfa\x8c\x5f\x3a\x1a\xe6\x69\x9b\xe7\x36\x05\xce\xe5\x82\xe6\xf9\xee\xeb\xbd\x1f\x95\x47\x1a\x74\xef\xb6\xee\x3d\xc4\x95\x73\xdc\x1a\xbf\x12\xfa\x47\xa4\x6a\x61\xeb\x1a\xf6\x98\x57\x61\x85\x87\x42\x86\x51\x83\x51\x7b\x0a\x4c\x93\x44\x3b\xca\xfe\xe4\x34\x3e\x3c\xdb\x8e\x70\x37\xbf\xa2\x1b\xa5\x3a\x34\x77\xe2\x00\xf1\x9b\xe2\x73\xb3\x96\x9f\x5a\xb6\x8e\xe4\x5d\x82\x47\x94\x9c\x4a\x7a\x9a\x24\x8b\x99\xbf\x5b\x65\xe2\x21\x97\x4e\x96\x2e\x51\x5b\x96\xc9\xde\x25\x94\xb5\xb4\xed\xb6\x72\x61\x46\xff\xf9\x2a\x96\x6d\x18\x62\xf9\xbd\xda\x10\xca\x19\x6d\x09\x6b\xc0\xd3\x78\x42\xaf\x81\xb4\xd8\x9c\xcc\x3a\xe0\x69\x91\xdf\x5f\x80\x87\x7b\x80\x61\xfb\x37\xe3\x92\xae\xe4\xe8\xf8\x77\x4f\x91\x3c\x01\x5f\x7a\x2b\x1d\x5f\xba\x0d\xe2\x7e\x57\xc2\xd0\xfc\x52\x67\x4a\x4d\x09\x30\x72\x68\xfe\x95\xfd\x09\xcd\x06\xbd\x9b\xb0\x39\x81\xf5\x33\x41\xff\x46\x8d\xdb\xbf\x19\xab\xae\xce\x15\xcf\x63\xad\xb1\xfc\x48\xdf\x4a\xb0\x0f\x13\x8b\xfb\x77\xa5\x99\x67\x22\x7a\x85\x00\xe3\xce\xe0\x31\xa7\xde\x6f\xb9\x81\x4d\x18\x4b\xb1\xda\x9a\xe8\x7c\xec\x69\xef\xa7\x36\x37\x54\xf6\x24\xa9\x20\x31\xf0\xbe\xad\x6a\x34\x66\xe1\x68\x0f\x99\xb9\xe9\xf5\x00\x49\xe4\x2c\x8a\xda\x1d\xdf\x73\x8a\xac\xb6\xbb\x12\xba\x3f\x47\x57\xa9\x4a\x9d\x3e\x52\x96\x97\x62\xe6\x34\x18\x82\x17\x45\x20\xa7\x8f\xf2\x39\xef\xd7\xea\xdd\xbc\xbf\xd9\x2d\x46\xaf\x1f\x2b\xa5\x6b\xc0\x28\xf5\x2b\x4c\x16\x90\x30\xf9\xa6\x41\x18\xa1\x4e\xce\x22\x3f\xaf\x04\xad\x59\x8d\x34\x6a\xc1\x1f\x4f\x7a\x2c\x01\x16\x1e\xff\x30\xc4\xf2\x73\x26\x9c\x26\x9f\xc5\x21\xd9\xa5\x52\x19\x92\xa9\xd8\xf5\x72\x99\xaf\x48\x5b\xee\x57\x72\xcf\xa3\x42\x08\x46\x02\xbe\x1d\x15\x62\xd2\x2e\x2e\x38\x2f\x94\x89\xd8\x7e\xe1\xf8\x7d\xab\xaf\x9f\xe4\xe2\x61\xe6\xf6\xaf\x93\x6d\xf7\xc1\x2d\x9b\xb6\xbf\xa2\x88\x96\xee\xd3\xc8\x73\xd6\x16\x97\x6c\xe9\xea\x9b\x5b\xa7\x9c\x77\x9a\x59\xe2\xd3\x8f\x7f\x54\xe7\x25\x27\xe5\xab\x64\x7c\x0c\x31\x34\x49\x81\x05\x7c\x1f\x94\xaf\x02\x99\xa1\x84\x02\xf7\x9d\xd8\x4e\x4a\x6f\x96\xb5\x18\x6c\xb7\x0e\x15\xba\x00\x95\xf0\x28\xa4\x94\x6e\xae\xa3\x2b\x3b\x27\x3e\x88\x01\xbd\xa0\xef\xdb\x00\x73\xf9\x3c\xb2\xdf\xb0\x18\xc9\x06\x58\x0c\x1d\xd1\x61\x17\x91\xb6\x07\x5c\xac\xd7\xbb\x1a\x14\x2c\xd7\x04\xe9\xbe\xe2\xd6\x6a\x69\x5b\x83\xbb\x8d\x4d\x18\xfb\xf6\xa0\x4e\xef\xe6\xd9\xcd\xc4\xd1\xb8\x24\x59\x28\x1e\x85\x84\x1e\x5a\xfb\x35\xa8\x4e\xec\xc1\x2f\x2a\x3b\x95\x76\xa3\x08\xbd\x57\xed\x27\xb1\xe5\x8e\x4b\x76\x65\x3e\xb8\x72\xd7\x25\x3f\xbd\xc7\xa1\x67\xe1\x9f\xbe\x55\x82\xcc\x28\x6f\xfb\x42\x5c\x5f\xda\xfc\x8f\x75\xec\xe7\xf7\x9c\x5a\x02\x6f\x57\xe1\x15\x65\x20\x2d\x7f\x94\xe8\x2a\x31\x0e\x6e\x7b\xc7\xc4\xed\xc4\xc1\x06\x8c\x5f\xe0\x8a\x6a\xc7\x33\xb9\x88\x40\x0f\xb1\xc7\xa6\x8c\x6f\x8b\x7b\xad\x7b\xff\x22\xcf\xfe\x49\x2f\x7b\xcb\x12\x7a\xdc\x59\x28\x42\x3f\x0a\xe9\xb6\xbf\x71\x64\x2c\xd2\x1e\x78\x12\x69\x50\x70\x16\x67\xb2\x0e\xd8\xfe\xb8\xdb\xca\xf0\xd4\x96\x93\x02\x66\xd0\xbd\x0a\xe5\x4d\x89\x0d\x75\x22\x6d\x50\x8b\x49\xee\x10\xbf\xd3\x49\x90\x8c\x1c\x2b\xb1\xb9\xbc\xd0\xa6\xed\x28\xb7\x8c\xd1\x30\x1b\xec\x21\x4e\x5b\x93\x42\x61\x53\x62\xc3\x70\x25\x0c\xbd\x72\xb3\xc5\xe9\x9e\x70\xdb\xee\xcb\x7f\xf7\x20\x48\x9b\x46\x5c\x39\x6e\x29\x5b\xe7\xfa\xcd\xeb\xff\xad\x84\x1c\x7d\x74\xd6\x21\xc2\xe4\x9b\xb6\xeb\xd2\xd0\xca\xea\x8a\xf5\x8d\x79\xb7\x54\xf2\x92\x2f\x8e\xdd\x52\xd0\xb7\xff\xb6\xd9\x65\x5a\x94\x22\x8c\xa0\x42\xa5\x97\x07\x8a\xa3\xad\x09\xf5\xe4\xb3\x38\x13\x55\xed\x59\x61\xb6\xf6\xb3\x9b\xb8\xa7\xfe\xd4\xb2\x40\xda\x73\x74\x79\x86\x05\xac\x00\x99\xb9\x69\x14\x21\x58\xdc\x6e\x10\x0c\xb1\xa4\xe3\x2a\xfd\x68\x8c\x71\xf3\x9e\x19\x7b\xe8\xc4\x04\x77\xec\x7e\xf3\x11\x49\x4e\x30\x73\x1b\xc3\x5b\x13\xb6\x5a\x77\x5b\xf7\xfe\xed\xb5\xca\xa5\x58\x19\x2a\x59\x57\x8b\xe6\x5e\x46\x05\x5c\xd2\x35\x4f\x3b\xbd\xd6\x7c\x7a\x2f\x11\x6a\x51\xc3\xe3\x3f\x83\x84\x20\x55\xe5\xfe\xe3\x7b\xb9\x6f\xc4\x04\x4b\x59\x25\x3c\x0a\x0d\xe5\x58\x1b\x61\x8c\x86\xbe\x3a\x3c\x16\x89\x7d\x61\x26\x8f\x1c\x8c\xef\xdc\x51\x98\x17\x5a\x33\x6f\x30\x6a\xfe\xb4\x0d\xe8\x7a\x33\x87\x3f\xf3\x42\x1b\x8f\x7a\x7e\xff\xdf\x00\xeb\xc7\x91\x02\x76\xd1\xad\x0b\x6d\xe9\x54\x85\xfb\xe0\x7c\x4c\xab\x96\x59\x87\xd8\x4e\x9e\x2d\x45\xb0\xf6\xf2\x21\x16\x36\x7e\xcf\xdb\x8d\xd8\xd0\x8e\x59\x53\x17\x40\x60\x7d\x61\x21\x43\xa5\x94\x5e\x1d\x4b\xa0\x02\x35\xeb\x97\xcc\xac\xcc\x3a\x20\xd6\xc0\x2d\x9b\x42\x3f\x1a\xe3\xb0\x1d\x69\x57\x28\x6f\x3a\x2d\xad\x84\x27\xf4\x9e\xca\xd8\x12\xb4\xcd\x9c\x95\xfc\x8f\x86\x61\xaa\x43\xb3\x52\x60\x67\x56\xf5\x82\xa3\x0c\x58\x1f\xb5\xfe\xea\x33\xc3\x75\xbb\x7b\x37\xb1\x5b\xb4\x8d\xea\xd8\xf8\xaa\x28\x15\x42\x85\xc0\xbf\xeb\xaf\x03\xb6\xe5\x1c\x71\x19\xdb\x51\xef\x9d\x5c\x75\x13\x4e\x27\x58\xca\x29\xe1\x51\x3f\xef\xfb\x9b\xd5\x52\xfe\x13\x3c\x44\xb6\xe0\x99\x17\x12\x04\x14\x45\x71\xe7\x57\x47\xae\xc5\x84\x14\xda\x98\x4e\xbf\x89\xd2\x5c\x6f\x3d\x2d\xf2\xdf\xc6\x8b\x06\xb2\xd1\x18\xb3\xb6\xaf\xc0\x61\xf1\x05\xfd\xcd\xa3\x7f\xf3\x6d\x11\x00\xaf\xf9\x28\x4b\xa0\x02\x46\x90\xad\x44\xfc\x2d\x9b\x27\x09\xac\xe3\xd3\x51\x9d\x8c\xee\x70\x61\xbb\xb0\xde\xe6\xfd\x1f\x2c\x20\xa1\xde\xbb\xac\x3b\xec\xdb\xe1\x02\x48\x77\xe4\xfa\xc1\x94\x12\x4c\x9e\xfe\xef\xc2\x84\xb0\x31\x05\x35\xe8\xe2\x2b\x83\x45\x28\x23\x7d\x99\x0f\xe9\x6c\x32\x0f\xb4\xf5\x7f\x84\x10\xef\x39\x5c\x60\x6b\x7c\xaa\x02\x76\x62\x78\x25\x2a\x59\x15\x8f\x26\x42\x79\xfc\xa7\xcd\x21\x48\xd5\x5a\xcf\x47\x57\xb0\xf8\x82\xd4\xb2\xb7\x20\xc1\xa8\xce\x36\x7c\xe7\x8e\x02\x5d\x23\xc6\x61\x9b\x93\xaf\xc0\x16\x71\xde\xe9\x9d\x85\x5e\x6d\xdd\xe1\x82\xef\xfa\x48\x62\x8c\x59\x58\xc8\x3a\x60\x9b\x92\x9b\xa6\xa9\x9e\x64\x59\xa0\xeb\x33\xad\x2b\x0e\xc5\xa3\x30\x73\x75\x7f\x01\x17\x6e\x00\xc3\xaa\xb2\x20\x16\x06\x7e\xcf\xb7\xa3\x76\x09\xa3\x93\xbb\x51\xef\x0b\xeb\xb7\xcf\x15\xca\x03\x3d\x46\x57\x4b\x59\x40\x42\xf0\xf8\xd5\x10\x7c\xf6\x29\xfc\xa9\x6d\x90\x21\xe1\xc8\x57\xa4\xf1\xbe\xcb\x83\xc4\xa5\xff\xff\x2d\x40\xad\x9e\x16\xc4\x93\xd4\xeb\xaf\xad\x06\x8f\x8e\x58\x9b\xeb\x37\x34\x49\xe9\x95\xfc\x4e\x04\xdd\x02\x2a\x60\x24\x4a\xba\x86\x65\x66\xc5\x16\x64\xa4\x04\xfb\xdc\x4a\x9d\xee\x3b\x63\x13\x0a\xfa\x9b\xbd\x13\xb3\x18\xe6\x7f\xce\xbf\x46\x6c\x14\x1b\x19\x20\x19\xf2\xd7\xa6\x87\xae\xa2\x2b\x1c\xd9\x6d\xdf\x83\x09\xd9\x67\x5a\x17\xcf\xed\xad\xb0\x80\x5c\x83\xef\x1c\x25\xc1\xfa\xa8\x85\x9b\x40\x05\xaa\x64\x49\x57\xd2\xa7\xdd\xd6\xbd\xcf\xde\x0d\x9d\x98\x8f\x67\x8a\x13\x51\x61\xbf\xa8\x74\x95\x43\x13\xef\xec\xc1\xec\x3b\x97\xfc\xe5\x72\xea\xb3\xee\xf4\x37\x7f\x4c\x25\x3f\x9e\xbe\x6d\x5a\x16\xbe\xf8\xb7\xf0\x7d\x41\x4d\x7f\x65\x31\x74\xf1\x47\xa9\x3e\x13\x6f\xad\x5a\x3d\x57\x09\x43\x37\xfe\x03\x5c\xc8\x05\x29\x66\x6f\x3e\x83\x60\x84\x47\xfe\x9b\xb2\xb1\x83\xad\x65\x71\x49\xf9\x2a\x75\x42\xe9\xa9\x9d\xf3\x47\x6d\xda\x2c\xba\xf2\x84\xd2\x53\xc9\xaf\x8b\x7b\xdf\x91\x2a\x48\x9a\x2b\x2b\x46\xda\xfb\xfb\xb3\xc3\x01\x39\xe0\x80\xa0\xb5\xfd\x7b\x93\x39\xf6\x89\x55\x25\xd7\xfb\xd1\x76\x35\xa9\x89\xbf\x42\x02\x94\x2d\x81\x17\x9a\x9e\xb7\xe3\xa5\x0d\x64\x3b\x20\x91\x87\x4c\x5f\x80\x80\x29\xb1\xdf\xb8\x36\xf5\x2f\x1c\xe6\xe5\x7e\xf9\xd3\xd6\x25\xea\xa1\xc9\x85\xda\xce\xe1\x4c\x57\x74\x4d\x5f\x00\x24\xa8\x6f\x7b\xfe\xc5\xb9\x73\x2d\x7a\x3d\x25\xc1\x14\xaf\xa9\x2f\x3a\x7f\x96\xc3\x9b\x76\x08\x55\xb7\x72\x7d\xd1\x4f\x52\xdf\x34\xb5\xac\x87\x8a\x94\x39\x23\x9e\x05\xcc\x57\xd9\xfc\xe9\xd1\xfa\x0e\xe7\x85\xa8\xbc\x52\x1d\xd9\x69\xf4\x3b\xc2\xd1\xed\x37\x80\xf8\xbc\x27\xcb\xc1\x1f\xb1\x0d\x48\x13\xf6\x0a\x24\xee\xb6\x72\x29\xe7\xae\xe9\xcf\x00\x59\xc2\xaf\x71\x66\xf1\x9e\x3f\x34\x38\x60\x62\xd1\x20\x0e\xe3\xc7\xdb\x80\xb4\xf7\xbb\x51\x9b\x53\x96\x3a\x68\xca\xf8\xa8\x2b\x98\x3b\x4c\xab\x50\xe0\x38\x17\xfb\x4c\xf5\x96\x5f\x56\xe1\x1b\x25\x4a\xb9\x27\x58\xa1\x7f\xa3\x0b\xb3\x97\xa1\xbe\x97\x30\xb1\xb8\xf1\xb8\x8a\x29\x67\x79\x59\x4e\xaa\x72\x5f\xa8\x13\xb0\x0b\x89\x06\x71\x08\xbe\xff\xa7\x48\xc5\x0e\x66\x0c\xfa\xba\xc2\x46\xde\x5e\xf7\x3c\x21\xef\xde\x1b\xf8\x30\xa1\xaa\xb5\x16\x77\x66\xfd\x97\x8b\x43\xf7\x07\x1d\x8b\x42\x62\x61\xb5\x90\x5d\x11\xc7\xb7\xd0\x2b\x40\x4e\xa7\x5a\xc1\x11\x19\xec\xa7\x9e\xf4\x73\x9e\x8f\x95\xa3\x12\xc5\xbc\x6e\xbf\xaa\x75\x2f\xf5\xe3\x87\x99\x63\xd2\x6f\xa9\x6d\xa5\xfb\x1d\x99\x55\xba\xd5\x72\xb9\x64\xbe\x2a\x89\x33\x7f\xf3\x6e\x40\x80\xed\xda\xda\xe5\x23\x72\x1c\xfc\x9c\xdf\x13\x26\x7c\x6e\xc3\x46\x6f\xa9\xed\xdd\xb8\x28\x9c\x7c\x62\x43\x38\x55\xdc\xdf\x3f\xb2\xcd\x23\xa3\xb7\x79\x0a\x10\xc2\xe7\x1c\x60\xf2\x07\x88\x74\x39\x7d\x8c\xf3\xf2\xf5\xda\xb9\x5f\x7a\xcf\xd2\x8b\xd3\x5a\x72\x26\x33\x42\xbe\x94\x5e\x83\xff\x69\xfa\xa1\xe1\x03\x3a\x22\x67\xad\x1c\x92\x9c\x38\xaf\x27\xe7\x0a\x07\x72\xc4\x8e\x05\x0a\xff\xb9\xf2\xe2\x1e\x98\x24\x5e\x8b\x3b\xf3\x2e\xa7\xe6\x84\xe7\xe6\x78\xd9\xad\x76\x5a\x6b\x9b\x83\xd1\xec\x2c\x97\x51\xc5\x7a\x1c\x6f\x34\x88\x83\xb7\x23\xd7\x2f\x72\x40\xe4\x0a\xef\x76\xd4\xc5\xff\xa3\xd9\xcb\xe3\xa1\x7c\xbf\xbf\x2f\x5b\x33\x49\x66\xca\x08\x65\x30\xd9\x49\x11\x9f\x62\x24\xfb\x32\xf6\x9d\xec\x52\x59\x4a\x96\x4c\xb6\x30\x35\x44\xd2\x60\x2c\x45\xf6\x25\x46\xc6\x52\xd6\xec\x22\x4b\x45\xb6\x49\xd9\xc7\x16\x63\x49\xb6\xec\xcf\x6b\xfa\x3e\xbf\x7f\xef\x39\x73\xae\xb3\xbe\xcf\xfb\xdc\x8b\x05\x1f\x39\xf9\x73\xa3\x54\xc7\xeb\x5b\xe9\xcc\x90\x67\x96\x13\x1f\x0f\x05\x8c\x2f\x04\xd7\xf1\xff\x13\x23\xa7\x79\x21\xb3\xa5\x87\xf9\xbf\xa0\xaa\x8b\x29\xdf\xed\xa4\xfc\x3f\xa5\x50\x30\xdf\x62\xbd\x7f\x7c\xa5\x9c\x02\x42\x77\x17\x33\x56\x97\x1c\xa1\xae\xe7\x98\x19\x70\x5f\xbc\x25\x97\x60\x22\x11\x07\x2d\x69\x3e\x76\x95\xf5\x8b\xe7\x7c\x63\x83\x22\xb0\xa7\x37\x44\xd9\x39\xa5\xea\xc6\xd0\x2c\xb8\x5b\x9b\xb6\xd0\x14\x38\x63\x33\x4a\x7e\x5c\x43\xc1\xcc\xb0\x8c\x60\xc2\xbd\xd2\x96\x3b\x1b\x33\x4f\x4b\xac\x9d\x4c\x1e\xfa\xd3\x5d\x5a\xe8\x37\x7a\x8e\x9c\x30\x09\xcf\x71\x6a\xa4\xae\x18\x50\x64\x80\xd0\x5d\x2f\xd4\xe8\xd1\xcd\x20\x56\x14\xe0\x6d\x6d\xd9\x86\xe5\xd4\x76\x73\x85\xd8\xcc\x3e\xbf\x4e\x0e\x08\xce\x12\xab\x71\x34\x99\x0f\x89\x7e\xb2\xc7\xe9\x05\x2b\xce\x75\x16\xb3\xe9\x20\x6d\xf6\x7b\x5d\xe6\xd1\x57\x20\x3c\x67\x8c\xd0\x40\x31\xe3\xb2\x27\x0f\x55\xcf\xf5\xd4\x44\xeb\x3e\xb8\x64\xe5\xbe\x32\x4b\xcc\x0b\x18\xd1\xd5\x4c\xdf\x5e\x95\x7a\xb6\xd6\xc3\x15\xc3\x41\x35\x4e\xf3\xe1\xac\x6c\x5c\x81\x5c\x4b\xb9\xba\x79\x53\xf3\xf3\xfd\x4a\x76\x06\x81\xc0\xe0\x13\xd9\x1c\x1d\xe5\x1f\x14\x25\xa4\x88\x1f\x36\xa9\xcf\x17\x19\x00\x51\xcb\xde\x27\x32\x4d\x5c\xd4\xa6\xa3\x59\x95\x2a\xf5\x79\x97\x95\x1a\x12\xfd\x04\x82\x58\xb5\xf1\x42\x1e\x27\xea\x76\x34\xa8\xce\x2a\xef\xa6\xa5\xc9\x98\x41\x0e\x6f\xbd\x8a\xa6\x7c\xb1\x5a\xdd\xf4\x2a\x27\x30\x08\x04\x66\xe7\x9d\xe9\x85\x51\x95\x38\x5a\x49\x39\x6c\x8c\x2a\x4d\x69\x26\x1c\xc3\xfc\xfa\xe2\xae\xd4\x72\x09\x83\x6b\x96\xf9\x09\x13\xc2\x98\xe8\xab\x4a\x23\x57\x95\x8a\x8d\x4e\x4d\xaf\x7c\xfd\x74\xfc\x79\x7b\x4a\x40\x8c\x8d\xc3\xe1\xaa\x6f\xec\xa3\x14\x2c\x82\xcd\xb4\xe6\x97\x0d\x0d\x0a\xee\x25\x0a\x19\x10\x2b\xdc\x8d\x50\x33\x6a\x02\x40\x9e\x39\xf2\xa0\xe5\x8b\x37\x41\xde\x21\x5f\x90\x60\xb5\x90\xb8\x8d\x89\xe6\xf4\x7a\xa4\x65\x32\x1f\xc2\xaa\xb8\x6a\x55\x3f\xc7\xd0\xae\x34\x52\x2c\x38\x67\xe6\x9e\xd8\xed\xba\x23\x91\x39\xab\x97\x6f\x49\x93\xe3\xce\xab\x71\x7d\xdb\x3a\x1f\xe6\x82\x64\xc2\xa5\x93\x7e\x96\xc2\xf9\x9c\x53\x98\x41\xff\x17\x4f\xd7\x30\xe9\xd7\xbc\x0a\x09\x46\xc6\xee\x7f\x8e\x4b\xa4\x6f\x31\x88\x13\x10\x9e\xd6\x15\xab\x51\x0b\xa9\x91\x79\xe3\xcb\x14\x94\x6c\xaf\xd2\x22\xa7\x47\xe0\xce\xfc\xac\xbe\xfc\x4f\x34\xeb\x53\xb1\xa0\x39\x2e\xd3\xe1\x7f\x6a\xdc\x89\xc9\xd2\x28\x66\x1c\x83\xf7\x91\x93\xa1\x7c\xc9\x28\xa9\xa0\x33\x3d\x28\xda\xef\x53\xe4\xa2\x7f\x29\x56\xaa\xf0\xe5\xc7\x9e\x3d\x4e\x72\x88\x4e\xd1\xca\x3b\xc3\x14\x9e\x9e\xf0\x5c\x8b\xc6\xc9\xa3\x22\xb9\x79\x2c\xc5\x44\x5a\xbf\x52\x53\xb9\x8a\x00\x9a\x29\xe6\xee\x13\x66\x5a\x29\x70\x46\x15\xe5\x34\x13\x8e\x19\xc3\x3b\x61\xd2\x2f\xd3\x88\xa3\x0b\x05\x9f\xd3\x43\x3f\xf8\xcd\x39\xea\x99\x18\xf4\xbd\x11\x8e\xae\x3b\x23\xf6\xb3\xcc\x78\x6d\x97\x25\xfa\xca\x35\x03\xcc\xa8\xe3\x67\xee\x24\x87\x3f\x36\x49\x86\xf5\x39\xab\x12\x67\x6e\x59\x54\x6c\x9d\x6a\x7f\x9d\x6c\xdd\x01\x9c\x68\x38\xb5\xce\x70\x38\xd8\x9d\xfa\x82\x76\xf4\x0d\x98\xb3\x44\xd5\xdc\xae\x35\x33\x24\xbe\x49\xcb\xeb\xcf\x88\x6d\x37\x39\xc0\xbc\xa1\xed\xb1\x52\x77\x23\xa2\xaf\x5e\x30\x1f\x6d\x68\xbf\xec\x4e\x1d\xe5\x71\x25\xf9\x51\x39\x25\xbe\x06\xe2\x07\xd1\x14\x34\xfb\x59\x01\xbb\x0d\x75\x1a\x14\x2c\xc9\xa0\x98\x71\x8f\xcb\x94\xad\xbd\x09\x92\xae\xfd\xbc\x49\x22\x5f\xe3\x09\x61\x03\xe3\xb0\x8e\x11\x45\x4e\xb2\x63\x56\xc0\x41\x6b\xc3\xc4\xdc\xb2\xa1\x86\xeb\x92\x7e\x12\x21\x2c\x41\x57\xd4\x0e\xe5\xda\xcf\x4b\x93\x77\xcb\x0a\x18\xf1\x88\xe8\x1d\x77\x42\x32\xe1\x94\x44\xc2\x81\x34\xdc\xff\x4c\x04\xfc\xd2\x5c\xcc\x5d\x2b\x77\xbb\x3a\xbf\xa5\xdb\xc1\xca\x67\x56\x6d\x9a\xbc\xa2\x6b\x42\xb3\x73\x0c\x7a\x25\xc6\x1b\x6d\x8a\xb0\xe7\x44\x90\x79\xa6\x77\x43\x9a\x7c\x3f\xa5\xf8\xde\x49\x13\xf6\xdf\x4d\xf1\xfd\x64\x51\x6c\x96\x8d\xf1\x88\x3d\x7c\x89\x18\x2a\x76\x01\x65\xda\x28\x66\xdc\x47\x1f\x2d\x83\xb8\xcf\xb7\x37\xb8\x85\x5c\xbf\x98\x2b\xbc\xbf\x14\xaf\xb8\x47\x64\xba\xce\xb7\x6a\x53\x1a\x30\xe2\xd1\x3e\x62\x29\x3e\xde\x18\x34\xb1\x5d\x4d\xb6\xac\x6f\x90\xdd\x69\x7a\x55\x5d\xd1\xc5\xa3\x98\xeb\x00\x0a\xb6\x39\x9b\xc5\x45\x31\xf9\xc9\xb7\x1e\x34\x6b\xd4\x37\x98\x4d\x51\x33\x6d\x3a\x40\x1c\x3b\x2f\x0f\x0b\xee\xa3\xcf\x9d\xf4\x8e\x43\x01\xad\x2f\x3c\xb2\x16\x3d\xaf\x48\xfd\x31\xb2\x8e\xfb\x09\x3e\x79\x01\xdb\x5a\x24\x57\xbd\x90\x4b\xe5\xc1\xef\xa9\x2b\x52\xd1\xc1\x5b\x8f\xc2\xde\x57\xcc\x77\x0c\xa5\xff\x0c\xe6\x7f\x33\xbd\x11\x32\xb1\xb0\xd7\xb8\x15\xd2\x74\xcd\xc6\x70\x44\x4e\xc1\x65\xf1\xc8\xed\x8b\x9c\x82\xa7\xd9\x6c\x4c\x8a\x43\x6f\xdf\x65\x91\x94\x30\x9f\x3c\xd3\xe5\x53\x6f\xf0\x60\xeb\xa6\x1a\x14\x44\x7e\xc4\x72\xb8\xa1\x3b\xc8\x2f\x2b\x64\xcc\xb6\xcd\x95\xb2\xdc\xa9\xcb\x8f\x5b\xdb\x95\xe9\xfd\xa1\xf4\x46\xb7\x3f\xe3\x52\x88\x2c\x8a\x19\x87\xaf\xe1\xdc\x82\x30\xcc\x68\x2f\xc7\x7b\x49\x23\x99\xcb\x9a\x98\x58\x51\x1c\x6a\x60\x38\x56\xd6\xe3\xda\x1e\x1e\xf8\x0a\xfe\x2c\xd3\x99\x1a\xf8\x7e\xa3\x03\xc4\x5d\x94\x1a\x43\x26\x1d\x47\xa8\x81\x5f\x90\x3d\x3c\xf8\x23\x68\xb9\xbc\x7d\x74\xa1\x3d\x1b\x0b\x07\x0b\xb2\x5f\x97\x57\x0a\x63\x5e\x6e\x8d\xb5\x9c\x00\x4e\x61\x70\x95\xd0\xf0\xde\x7d\xb5\xbe\x9f\xda\xc5\x2e\x40\xa7\x80\x54\x32\xcc\xcf\x8c\xe3\x72\x0e\x83\xab\x5c\xdc\xb8\x6f\xb5\x7c\xd8\x6b\x5b\x00\xe2\x1c\x38\xec\x7d\xec\x10\x80\xdd\x78\x82\xff\x5a\x17\xfa\x18\x88\xb1\xc6\x1e\x86\x89\x8d\x57\x8e\xa3\x8f\xe1\x36\xce\x1a\xd0\x2d\x2b\x53\x86\x0a\xc0\x72\xb0\xb1\xe2\x8f\x16\x83\x29\x32\x20\xef\x75\x47\xbc\x09\x90\x87\xee\xe1\xc1\xe5\x52\xff\xba\xa2\xea\xa3\xff\x60\x44\x06\x69\x78\xec\x71\x14\xe0\x0d\x3f\x50\x05\x37\xac\x0e\x0e\x44\x39\xbd\x6c\x6f\x23\x99\x54\x76\x5f\xdc\x51\x83\x82\xbd\xbb\xc8\x8e\x43\x01\x9c\xfe\x89\xcc\x83\xa4\x56\xe1\xa6\x0a\x02\x83\xc0\xb9\x57\x70\xc6\xe6\x43\xbb\x2d\x08\xc3\x2d\xeb\x7a\xcf\xca\x22\xff\x23\x47\x1a\x37\x78\xf7\xf1\x81\xb0\x41\x99\x21\x03\x70\x6f\x39\x14\xc0\x7d\x29\x5a\xb6\xdc\xa4\xc0\x30\x0d\x23\xe4\x04\xd0\xc9\xde\x9b\x34\xe8\x91\xce\x08\xfa\x9f\x1c\xa8\x82\x14\x84\x76\xd1\xf8\x5a\x75\xf4\x87\x8c\x0a\x43\x46\x01\x5b\xad\x3a\x62\x37\x45\x1c\x08\x70\xda\x74\x74\xa5\x77\x1f\x0a\xe0\x96\x48\x63\x47\x81\x11\x7a\x5e\x55\x04\x06\x81\xe0\x6b\x56\xa6\xcf\xb1\xac\x40\x07\xbf\x7b\xe8\x44\xf7\x91\x0d\x53\xf3\x4b\xbb\x48\xe9\xd0\x80\x7e\xe2\x33\x35\x28\x08\xf6\xb6\x43\xa8\x50\x34\xde\xae\x58\x6e\x6e\x67\xd2\xad\xab\x93\xbf\xcc\x0a\x82\x8d\xa1\x0c\xb7\x30\x15\xbb\x7c\x9b\xe3\x8f\xf2\x11\x43\xc5\xb9\xa0\xf3\xa2\x48\x38\x10\x20\x79\x85\xfd\xbe\x45\x43\x00\x69\xb1\xbe\xa2\xba\xa1\xe0\x81\xe0\x7c\x9b\x6a\x2c\x02\xfc\xd0\x42\x31\x03\x8c\xaf\x6b\xfa\x67\xba\xab\x51\x96\x3d\x66\xab\x5e\x13\x97\x22\x94\x28\x26\xe0\x56\x26\x3d\x64\xf0\x6d\x18\x63\xe7\x53\xb7\x1d\xe4\x62\xc3\x4e\x6f\x7e\xd9\x77\x34\x2b\xee\x11\xf7\xd7\x70\x38\x68\x3b\x14\xc0\x6d\x9c\xe0\x3a\x54\x69\xa8\x7e\xa4\xc2\xfa\x96\x62\x02\x66\x22\xad\xce\x44\xc0\x55\xfa\xca\x95\xa1\x02\x5f\x73\x52\x8b\xb6\x1f\xd9\x4c\x3d\x59\xb5\x15\x65\x88\x53\x76\xb8\xc1\xcb\xc3\x62\xec\xbd\xf2\xe5\xc1\x30\x3f\x73\x9c\xae\xcf\xf6\x19\x0b\xaf\x83\xb8\x9c\x9e\x60\x72\x2e\xe8\x2c\xe8\xd3\x87\x32\x20\xf8\xf6\xf0\xa0\x5f\x6c\xfc\x6f\x4c\x90\x57\xa3\xe9\x1a\x85\x93\xae\x90\x4b\x5b\x8b\xa1\xd9\xd3\x35\x0c\xae\x12\xad\xf1\xdf\x10\xdf\xc1\xa5\x21\xbe\x1d\xf4\xde\x13\x90\xfa\x42\x30\x17\xb0\x96\x60\xd3\x46\x49\x05\xd6\x05\x00\x60\x4c\x37\x5a\x39\x8a\x7a\xf6\x20\xed\xe7\x32\xcb\x09\x8c\x59\xdc\xf2\x97\x59\xb3\x86\xe9\x47\xb1\x56\x8e\x15\x29\xfd\x15\x1e\xca\xd8\x27\x20\xb4\x29\xee\x00\xa1\x7d\x22\x02\xae\x92\x5d\xae\x0c\x6d\xb6\xa9\xd8\xe5\xb3\x58\xdd\x0d\xa7\x7a\xbe\x2d\xce\x05\x62\x19\x67\xb5\xb5\x18\x10\x67\xb7\x61\x8c\x65\xa7\xb7\xef\x59\x2c\x8f\xf7\x4a\xd8\xed\x9b\xd1\xc4\x40\xf4\xdb\xee\x70\xb8\x8a\x4f\x25\x21\x49\xf1\xc5\x81\x2a\xe8\x3a\x91\x79\x44\xf6\x08\xfb\x9b\x47\xb5\xa7\x91\x73\x81\x58\xd5\xd9\x08\xb8\x8a\x73\xad\x6c\xef\xed\x30\xb8\xca\x93\x9b\x9a\x9f\x57\x8d\x97\xd7\xde\x22\xc8\x81\xdf\xd0\x6c\x40\x27\x84\x43\x8d\x10\xc3\x28\x26\x44\x78\xce\xa8\xa3\xe1\x59\xdd\xea\x1a\x5a\xf2\x93\x63\xc2\xb4\xfe\x76\x2d\xf6\x2c\x18\xe6\xa7\x1f\xc9\x05\x4b\x64\xf8\xa6\xbf\xd6\x73\x31\xe2\x44\x63\x81\xf7\x14\x0c\xe1\xef\x55\x4e\x60\x02\x07\x53\xd9\x97\x01\x6b\x11\xb6\x78\x94\x24\x4a\xaf\x79\xf5\xb5\x4f\xed\x45\x4a\xa1\x49\xad\xf3\xf7\x27\x6f\x06\x02\xf7\xef\xb6\xc9\xe6\xf4\xda\x62\x06\xc4\x99\x9e\x6b\x56\xbe\x3b\x41\xdc\x38\xad\x67\x9c\xe4\x7a\xbd\x4a\xd1\xc6\x7c\xb7\x4d\x25\x8a\x33\x70\x2a\xf3\xb8\x8d\xa9\xd3\x44\x31\x1b\x4b\xdf\x9f\x7d\x44\x83\x46\x9c\xba\x58\x67\xb1\x96\xba\xe3\x7b\x27\x5d\xd2\x7f\x4e\xc1\x57\xcb\xa8\x9c\xc0\x2c\xa7\xb5\xfa\x30\xe2\xed\x51\x96\x5b\x7b\x7a\xb4\xe5\x78\x3b\x87\x3a\xc3\x2d\x13\xf2\x05\x92\x6d\x3f\x33\x4d\x08\xc4\x09\x6d\x41\x12\x38\x94\xb6\xef\x46\xf4\x8e\x89\x29\xad\x49\x61\x88\xb2\x6b\xd6\xb5\xef\x7b\x92\x14\xdf\x1f\xc6\xca\xae\x71\x4f\x87\x37\x4f\xb6\xdb\x26\x8b\xdb\xad\x29\x6a\x4a\xae\x18\x57\xdc\x69\x44\x0c\x15\x0b\x32\x34\xeb\x98\x6f\x23\xd4\x80\x18\x21\xf9\x4a\xad\x59\x6d\x98\xb4\xb8\xc9\xef\x66\x06\x65\x42\xf5\x05\xb3\x9a\xdb\x29\xad\x05\x61\xe7\x31\xbe\x5a\x46\xf1\x8a\x34\x3b\x05\xd9\xde\x24\x45\x1a\x6f\xad\x99\xe1\x9c\xfc\xa5\x7e\xc1\x62\x09\x9b\xf5\xac\x1c\xce\x26\xb3\x1a\x2a\x7b\xbb\xad\x95\xb5\x28\x23\x4e\xab\xc8\x04\xca\x80\x60\xdf\xc3\x77\x3d\xbb\x7a\xc9\xa2\xfe\x2d\xed\x77\xe6\xfb\x60\x7c\x6b\xfe\x55\x3d\x3d\xaf\x92\xb0\xac\xdb\x31\xa3\x0b\xae\x83\xa2\x51\x74\x93\x0e\xf4\x49\xd8\x7b\x8c\xee\x8f\x99\x34\xed\x8d\x48\xbb\x23\xdb\xe2\xe3\x3b\x4f\xb0\x08\xe0\x96\xbc\x98\x81\x54\x03\x62\x6c\xd5\xe9\x7b\x90\x04\xdf\xdf\x7e\xde\xc6\x45\x75\x08\xec\x78\x41\xe1\x7a\xe3\x6e\x6c\x3a\x71\x54\x5c\x74\x6b\x59\x60\x0b\x29\xeb\xf9\x9a\x32\x9c\xa5\xa2\x3c\xea\x5e\x50\xb4\x19\x3d\x62\xf1\xfa\x88\x9f\x95\xcb\x5e\xb2\x3d\x1b\x2b\x04\xdc\xe4\xe8\x69\xe4\xa3\x07\x83\x65\x3b\x76\x5f\x93\x6a\xdc\xb7\xcb\xd2\xbf\xcb\xc2\x9a\xb9\x4f\x10\xea\xe2\x51\xae\x0b\xad\xaf\xf0\x8a\xfe\xa5\x9f\x2a\xd8\xc5\xb3\x13\xcc\x00\xf1\xd1\x32\x32\xf9\x2c\xd9\x58\xf8\xc7\xdd\xaa\x28\x68\xa2\x49\xdc\x66\x4d\x91\xa6\x03\xbe\xe9\xd0\xdb\x40\x7a\x09\x26\x22\x61\x23\x1b\x73\x7c\x4a\xa0\x6d\xc4\x52\x62\xb4\xca\x74\x4a\xb6\x29\x4e\x48\x61\x5c\x48\x41\x76\x9b\x53\xc3\x7f\x91\x64\x4a\xca\x17\x5f\x7d\x71\xd3\x57\x04\x59\x40\xf9\x7e\xa0\x62\x32\x1f\x52\x34\xb6\x77\x43\xf3\xdc\x99\x1b\xda\x8c\x38\xad\xc9\x4e\x31\xdc\x4d\x1f\xd7\x8c\x8f\x87\x4e\x6a\x54\xa9\xcf\x88\xd5\x6b\xfb\x87\x4e\x1f\xc7\xdf\x06\xbf\xa7\xce\x56\x4b\xda\x84\x06\x1f\x30\xe5\x9b\x6c\x2a\xb5\x29\x59\xd9\x7f\x91\xb7\xed\x29\x5c\x7b\x76\x4b\xb5\xb1\x76\x99\x8b\xb4\x79\x34\x5a\xe4\xdd\x75\xc9\x22\x78\xf2\x79\xb4\x7f\xc9\x7b\x02\x33\x10\x6c\x89\x37\x01\xed\x54\xcb\x61\x7e\x7d\x5d\x75\xc2\x73\x76\xab\x61\xb3\xb0\xcb\x33\xa9\x10\x9a\xf2\x43\x3b\x05\xed\xfa\x0a\x07\xb8\x6b\xba\xe8\x76\xe7\xcb\xae\x35\x91\x1f\xb3\xea\x55\x0a\x25\x74\x4a\xb6\x30\xfc\xd9\x3c\x64\xf2\x04\x2b\xd7\xa1\x4a\xb4\x20\xcd\x1c\x48\xf3\xd2\xbd\xba\xb0\x04\x13\x71\xb5\x86\x25\xba\x27\xcb\x9b\xd6\xfb\x94\xb7\xbe\x78\xce\x79\xf1\x6f\xe3\x4c\xcd\xe6\x71\xea\x92\xde\xe2\x91\xbe\xa2\xe6\x92\xc0\xcd\x4e\x9b\x8e\xa2\xd9\xd9\x4c\xab\x85\x7c\x2f\x13\xec\x78\x07\xa7\x97\xcd\xcd\x74\x28\x78\x1a\x7d\x1c\x85\x63\x74\x77\x4f\x50\x5c\x36\xa7\x21\x22\xe2\x8b\xd4\x02\xca\xe4\x4d\x2b\x56\x4c\x34\x69\x7c\x49\x73\x61\x9a\x3d\xaf\x48\xbe\xae\x4d\xef\x1c\xd8\x63\x1f\x29\x74\xe8\xc9\x08\xad\xc4\xbc\x97\x5b\x3c\x1a\x7d\xf3\xd3\x05\x59\xa4\xf4\xe7\xa4\xf8\x52\x25\x81\x19\xe0\xdb\xd9\x51\x38\xaa\x53\x98\xb4\xc2\x5a\xf2\x6c\xca\x87\x3a\xa9\xf1\x4a\x87\x29\x6a\xa6\xb8\xdd\xbe\x6c\x97\xd4\xe7\x74\x9f\xe4\xd1\x1f\x2f\x0b\xe5\xf6\x4e\x2b\x98\x19\x56\x10\x22\x2f\x88\x55\x16\x3e\xea\xd1\xb6\x48\x5d\x0f\xb2\x98\x0f\xb1\xeb\xfb\x19\x59\xcc\xc1\xd0\xec\xe4\x7d\x0b\xa1\xe2\x53\xa6\xfc\x8a\x77\xe0\xa0\x25\x3e\xda\x83\xce\x0a\x2b\xee\x34\x7a\xc0\x1e\xa9\x1a\x8e\xc4\xec\xce\xfc\xfe\xa5\x67\xee\x71\x24\x48\xc2\x16\x63\xd5\xf2\x5e\xc9\xba\x13\x6c\x26\x82\x1a\x5a\x23\x94\x4d\x37\x1b\x7b\x31\x43\xf6\x94\x78\x30\xe9\x4d\x87\x1e\x79\xb1\xf0\x2e\xcc\xa6\x4f\x1f\x2a\xda\xbf\xc4\xec\xef\x46\x25\x6b\x66\xa3\xa5\x45\xb5\x5d\x98\xf4\xd7\x25\xe5\x12\x23\x58\xac\xfc\x38\x9a\xcf\xb4\xcb\x64\x61\xc6\xff\x33\xd9\xae\x70\x7c\xe4\x7a\x71\xc0\xc7\x01\xca\x63\x30\x69\x1c\x64\xef\x73\x0b\xa1\x72\xaa\x22\x26\x5e\x71\x59\x8e\x1e\x8b\x85\xe3\x53\x53\x1a\xff\x69\xa6\x6f\xbf\x7d\x38\xd1\x44\x9a\xff\x69\x55\x34\xbf\x37\x4f\x0a\xda\x56\x16\xb7\x09\x85\x24\x08\xd4\x47\xc9\x2e\x08\x9f\xc5\xee\x18\x48\xa4\xef\xf3\xd1\xc4\x80\xb7\xd8\xc8\x2b\x38\xa3\x18\xf3\x16\x24\x21\xa1\xf2\xa0\x25\x3e\xaa\xda\x5f\xc2\xee\xaf\x7a\xc4\x89\x30\xb1\x24\x9b\x59\xbe\x9d\xcb\x49\x0e\xbb\x67\x92\x08\x3b\x66\xa4\x6b\x3f\xd1\x7c\xfd\x59\x72\xba\x52\xa5\x7f\x9f\x8c\x0a\x5e\xb2\xf4\x1c\xef\x40\x6c\xdf\x7b\x6f\xc8\x0c\xf6\x46\x34\x50\xcc\xc6\x50\x5e\x2e\x03\xc3\xfb\x05\x78\xa6\xe3\xc1\x9c\xe4\x1a\xb3\xbe\x68\x45\x0b\x4f\x77\xb3\x85\x61\x3d\x0b\xf4\xa1\x81\x6f\xec\x23\x1e\xc7\x18\x9c\xee\xa5\x40\xf2\x28\xa9\xa0\x28\x68\xc4\x51\x22\x68\xca\x87\x26\x0f\xca\x3a\xee\xd0\x1b\x85\x79\x85\x5f\xbf\x67\xfc\xf3\xe4\xf3\xe2\x0f\x66\x53\x44\xc7\xa2\xed\xab\xab\x96\xbd\xdb\x3d\xe6\x9b\xdb\x99\xc5\x8e\x3e\x8f\xd5\x1e\x7c\xe2\x27\x51\xaa\xc7\xb3\xfe\xf0\xf0\x57\x11\x18\x41\xb0\x34\x8a\xd9\x18\xd0\xdb\x62\xf1\xc2\xaf\xf0\xdf\x70\xea\xd8\x39\xce\x8b\x35\x5a\x53\x4f\xee\xce\xc4\x28\xeb\xe6\x4f\x4f\xe4\xf5\xaf\x79\xcd\x3d\x96\xd3\x9c\x4d\xb6\x68\xfc\x65\xe6\x2b\xd2\x6b\x81\x1d\xef\xc8\x2b\xbc\x93\x0e\x55\x29\xf7\x7c\xa8\x89\x62\x8e\x7b\xb0\x12\xf3\x5e\xe1\xdd\xcb\xb8\x00\x1a\x6b\xbb\xe2\xf7\x1b\x1d\x3a\xe4\x80\x11\x89\x21\xbe\x9d\xa7\x41\x25\x21\xf9\x41\x61\xbb\x1e\x11\xcf\x43\x2f\x0c\xc9\x17\x9a\x69\xe4\xd7\xbe\x7c\xbb\xf9\x42\x39\x5e\xd6\x83\x0e\x0e\xed\x5a\x28\xe6\xb8\xb0\x25\x98\x48\x41\xd9\x1e\xfe\x23\x9c\xec\x58\xb8\x68\x9f\x69\xbc\xed\xdf\x6b\xbc\x99\x11\x66\x51\x1f\x48\xc2\x0a\x09\x7d\x21\xdb\x65\x51\xaa\x0f\x6c\x7a\xfe\xe6\xd2\x27\x45\x89\x41\x49\xde\x57\x8a\x38\xc8\x4a\x19\xe6\xd7\x37\xcc\x58\xe1\xd7\xd7\x5f\x7d\x18\x61\xe4\x40\xce\xe0\x6f\xb2\x6b\xb8\xea\x90\xed\xfd\x43\xca\x94\xd7\xa6\x40\x4d\x2d\x0d\xf3\x60\x30\x68\xc7\xc0\xd7\x35\xcd\x1d\xc9\xa2\x22\xe3\xf9\x50\x98\x5c\x6d\xc8\x00\x0c\xcc\xf8\xa4\xfc\x77\x17\x28\xe2\xac\x78\x35\xf9\xd3\xe5\x39\x43\xdb\x85\x41\xeb\x90\xc1\xf5\x83\x75\xf3\xe0\xbf\xb4\x68\xff\x35\x6d\xbf\x53\xf2\xb9\xa2\x6f\x37\xbf\x36\x19\xbb\xf7\xdc\xa5\x4f\x99\x64\xe3\xfe\x2b\xac\x28\x9c\xdd\xf4\x61\xcb\x4c\x9b\xad\x95\xc4\x78\x39\x05\xad\x75\xb1\x4d\x91\x52\x74\xe5\xe8\xf3\x62\xed\xdc\x3d\x0b\xaf\x3d\x49\xcd\xbb\xfc\x55\x84\xf0\x3b\x92\x2f\x4c\x3f\xe7\x5b\x91\xfc\xfa\xeb\x8a\x13\x80\x18\x41\x2a\x83\xbf\xad\x64\x1e\x62\x2b\x64\x41\x1e\x00\x2a\xb2\xf4\xea\xde\x82\xbc\x16\x28\x12\x7f\xb4\xa2\xb5\x79\xf8\xc7\x60\xf1\x60\x68\xe4\x55\xf3\x5c\x46\x6e\xb2\x55\xa8\x49\x3e\xc7\xf8\x7d\x24\xb3\x8a\xcc\x3d\xa2\x50\xf5\x2a\xe4\x1c\x1b\x1e\xa8\x0c\x18\x43\x13\xd4\x6f\xb8\x97\x88\x05\xa8\x34\x34\x05\x9d\x6b\x97\xde\xe6\xad\xb4\xfb\x63\x91\x44\x08\x7b\x8f\x85\x83\x9d\xea\x1b\x3f\xad\xa0\x0a\x57\x58\x05\xc2\xba\x73\x67\x0d\x95\x3f\xa2\x35\x9d\xa5\x51\xfa\xc7\xda\xcb\x00\xaf\x95\x54\xe9\xee\x07\xdd\x07\x0e\xae\xe9\xcc\x2a\x8d\x48\x69\x54\x1e\x9c\xb1\x13\xe9\x2f\xb2\x0d\x13\x11\x1e\xff\x74\xe8\xd4\x2f\xf6\x54\x61\x3e\x71\xf0\x4f\xc1\x91\xd4\xf6\x2b\x2b\x3a\x4f\x70\xd4\x87\x32\xcc\x9c\xfb\x6e\x20\x24\xba\x98\x17\x67\x9d\xcd\x3d\xf7\xca\xd6\x92\x96\x6f\xd5\x95\x1e\xf2\x0c\x7b\x1a\xec\x68\xa0\x98\xe3\xbc\x96\x60\x22\x91\xe7\x6f\x7a\x79\xc9\xec\x7f\xad\xe3\xf4\xb2\x75\x47\x42\x5e\x98\x7a\x98\xd0\x6e\x4f\x24\x2b\x6e\xde\xa2\x09\x81\x3f\xf3\x38\xc1\x5c\xfb\xa7\xaa\x20\x6b\x8d\x6e\xd0\xf4\x61\x4b\x5e\x99\xf2\x2b\xbe\xbe\xee\xc0\xc5\xda\xad\xd3\xf4\x8a\x40\xfc\x81\xaf\xd9\x89\x05\x7b\x04\x7e\xf5\x9f\x8d\xc9\xb8\x47\x37\x4e\x1a\xc5\x1c\xe7\xb8\xf2\xe5\x7d\xbe\xe9\x73\x6c\x8c\x5a\xe1\x2a\xac\xa4\x9c\xf0\xf8\x60\xe8\x83\x45\xf0\x6f\xbd\xc5\x9d\xae\x4c\xe9\x86\xaf\xc7\x5d\xed\x34\xa5\x5e\x3a\xb4\x3b\xc8\xe1\xb4\xa8\xd9\x97\xc1\x9f\xcf\xe9\xed\x3e\x7d\x74\xdd\x0e\x6b\x73\xf3\x43\x7b\x6f\xab\x49\x41\x1d\x13\xe2\xe3\x0d\x7d\x68\x76\xad\x4e\xb2\x5d\x56\xf2\xf3\xeb\x9e\x48\x26\x95\xd0\x7f\xba\xef\x2b\x46\x48\x8b\xf7\x9d\x65\x75\xfe\x19\xa1\x17\x9a\x3d\xce\x7f\x10\xdf\xaa\xa9\x4c\x44\xd8\x76\xb4\x40\x13\x0d\xeb\x4c\xf3\x6b\x5f\xda\x76\x80\x38\x18\xdd\x7f\xf3\x1f\x09\x8a\x2f\xf6\x20\x09\xad\xf1\x6d\xf7\xa2\x82\xab\x8a\x82\xbe\x2b\x17\x6d\x73\x79\x19\xd7\x4f\xb9\xd3\xe4\xb9\x1f\x27\x5b\x85\xa6\x20\xdd\xc1\x8b\xe6\x70\xb8\xca\xf5\x5a\x59\x3a\x72\xd7\x7b\x26\x51\x97\x1f\x63\xd9\xd8\x54\x2b\x56\x64\x36\xf7\x97\x2e\x0f\x65\xec\x57\x61\x11\x6c\x56\x24\x0b\xa9\xd2\x9d\xaa\x41\x74\x0f\xfa\x38\xee\x9e\xa2\x93\x5a\x0d\xc6\xd4\xed\x25\x0b\x38\x1b\xb9\x07\x49\xf8\xe8\x27\x9d\x9b\x93\xea\xb1\xfd\x48\x6b\x68\x24\x84\x54\x35\x82\x3e\xf9\xb4\x85\x47\x51\x4f\x8a\xeb\xf0\x39\x96\x0d\xfc\xe0\xd4\xfb\x29\xb0\xc9\xa9\xd6\x0b\xbb\x89\xb9\xf7\x9a\xa9\x93\x65\x0b\x92\xf0\x11\xcb\xf1\xe3\xcc\xf5\x3d\xc9\xcd\x7d\xea\xc9\xe8\x6a\xf2\x3b\xc2\x13\x67\xb1\xf4\x7d\xc3\x15\x5b\x16\x69\x3b\xda\x35\xe5\x5f\x49\x5b\x06\x50\x61\xc2\x0b\xc6\x4e\xa6\x2d\x08\x07\x27\x0b\xcc\x46\xbb\x19\xda\x7e\x2e\xc3\x72\xb5\xf7\xa2\x59\xc5\xe2\x36\xc5\x44\xfa\x16\xc1\xe6\xe2\x0e\x8c\xb4\x74\x03\xc2\x10\xa7\x14\xdc\x74\x5a\x07\xc5\x1c\x27\xb9\x12\xf3\x7e\x98\x5f\x5f\xa7\xde\xb3\x92\xba\x9c\x4e\x91\xf9\x06\x7c\xb6\xcf\x6c\x1e\xce\xd9\x17\x29\xfd\x74\x46\xb2\xa8\xcf\xe8\xcb\xdb\xcc\xae\x5f\x77\x46\x32\xa9\x6c\x19\x43\x19\x66\x38\xf6\xf0\x5d\xce\x61\xd2\xae\x54\x9d\x4a\x48\x63\xd6\xa2\x54\x18\xca\xc2\xdf\xa6\xa0\x05\x9e\x68\x74\x84\x1b\x5d\xb8\x86\x45\x34\xc7\x15\x8f\xae\x23\xe9\xcd\xe2\x9c\x29\xa2\xb0\x04\x9b\x33\xab\xd9\xa8\x5e\xdc\xd9\xa1\x21\xbc\xec\x9d\x91\x2c\xf8\xd9\xc4\x41\xdf\x2e\x2b\xe1\x6a\x7a\xe2\x1f\x6e\x28\xa2\x96\x2e\x43\x19\xc1\x0b\xb3\xad\x19\x43\xe5\x81\x7f\xc5\xfb\xa5\x34\x60\xe0\xfd\x62\xc3\x21\x39\xba\x9a\x5c\x45\x78\xa2\x4a\x87\x9b\x85\x36\xe5\xf7\x04\x06\x01\xc5\x5d\xa9\xf0\xfd\xd2\xeb\x38\x7d\x97\x30\x69\xba\x6a\xc7\xfa\x07\xe9\x41\x5e\xf5\x6a\x6b\x17\xd9\xe1\xb7\x35\x77\x96\x9a\x92\x74\xc9\x14\x19\x70\x4b\xbd\x29\xc2\xbb\x56\x15\x0e\xdc\xb8\xe9\x8c\x81\x3c\xb5\x90\xa3\x09\xf7\xb2\xcf\x1e\x3f\x37\x91\x5d\xe3\xfa\x16\x8b\x60\x7b\x22\xfb\xf0\x8d\xae\x68\xc3\x00\xfa\x18\xee\xde\xaf\x6a\xf8\x45\x59\x28\x23\x38\x39\x6d\xd9\x53\x4d\x30\xe6\x5e\x82\x9d\xd1\xae\xf7\x29\x2f\x6a\x0a\xac\x36\x1f\xbb\x8d\x64\xc1\x1b\x5f\xa7\x79\xe5\xf5\x8b\xd1\xb8\x41\xbf\x67\xc1\x3c\x24\x78\x35\x6b\xa2\x09\xfe\x50\xb7\x48\x24\x13\x02\xce\x66\xc9\x45\x1f\xb4\x30\x97\x2b\x5b\x5f\xe8\xfb\xa0\x3d\x14\xbc\x9e\x64\xda\xe9\xc8\xd1\xdf\xe3\xfe\xba\xa4\xbf\x6b\x95\xbe\x49\x8c\x59\x2e\x1f\xe1\x1b\x22\xbe\xad\xe3\x8d\xf7\x94\x42\x11\xe0\x5d\x5b\x7a\xe0\x99\x3a\xd9\xe3\xcf\xaa\xfd\xff\x94\xc5\x33\x46\x5b\x1e\xa9\x0e\x8d\x1c\xd9\x44\xab\xd3\xc4\xb8\x55\x76\x8a\x9b\xe6\xde\x05\x81\xc8\x81\x30\xd4\xd2\xc7\x72\x13\x90\xd2\x76\xe8\xe4\xfb\x8a\xfd\x8c\x55\xcd\x46\x75\x51\xcf\x5e\x4d\xde\x30\x9a\x95\xfd\x23\x8f\xac\xc1\xac\xd9\xf8\x5d\x24\x93\x4a\x10\xb2\x0a\xfe\xc7\x89\x07\xa4\xb4\x1d\xe0\xbb\xb2\xe1\x67\x6c\x6b\xfe\x16\x14\x29\xfd\xbd\x4d\xe3\xe6\x56\x59\x48\xdc\xd6\xf3\xa5\x6f\x71\xa2\x22\xe1\xc0\xf7\xe9\x41\x8b\x86\x09\xd4\x24\xb8\x02\x7f\xa4\xac\xa3\xe0\xba\x1f\x7f\xcd\xed\x44\x73\x36\x3d\xa3\xcf\x15\xa7\xf5\xb7\x20\x1c\xa7\xbd\x60\x08\x2f\xdb\xff\x7e\x8b\x9e\x9f\xa0\xea\x0c\x29\x1e\x3e\xa5\x89\x99\x96\xc8\x6d\xfb\xd2\xa0\xa0\x7f\x01\x37\xff\x89\xbe\xd8\xf0\xd1\x93\x2f\x11\xae\x44\x45\xde\xb5\xa8\xa3\x71\x50\x64\xbc\xb9\xf3\x5f\xd6\x5b\x4a\xc4\xd2\x1d\x0d\x79\x05\x67\xec\xe4\xda\xfa\x77\x27\x71\xd8\xf1\xef\xbe\x01\xeb\x4b\x3b\x2f\x24\x53\x64\x3f\xda\x32\xff\x65\xfd\x27\x34\x0b\xce\xef\x99\x79\xd3\x7d\xef\x52\x26\xd6\x6c\x3a\x1e\x7a\x62\x2e\x9f\x02\x31\x3a\xee\x89\xa3\x3c\xae\x37\x0a\xc4\xd8\x44\xc2\xe5\xad\x97\x0f\x7b\xf5\x2a\xc7\x28\x32\xde\x50\xde\x73\x2c\xde\x71\xd8\x0c\x7e\x5e\x6f\xd2\x52\x0b\x87\xda\x33\x71\x14\x8e\xcd\x99\xce\x2e\x08\xff\x2d\xc1\xa8\x9a\xd4\x74\x9a\x79\xf0\x52\x18\xd9\x65\x12\x3e\xba\xf5\x7c\x26\x26\xdd\x9d\x1e\x8d\xfa\x5f\x30\x5f\x56\xd4\xff\xca\x83\x97\xab\x3d\x7b\x90\xef\xc8\xb1\x5d\xd1\xb1\x8c\xf0\xf8\x50\xbe\x44\xb7\xa3\xa1\x05\xcd\x82\xdb\xc8\xfa\x3f\x33\x7d\x4c\x78\x4d\xb1\x2f\x3d\x60\xa1\x5d\x68\x16\xf6\x16\xcf\xa6\x61\x34\x23\x6e\xc3\x3a\xf0\x37\x64\x57\x32\xdc\xce\x10\x26\x70\x4e\x97\xbc\x29\x98\xab\xa3\x31\x88\x41\xb5\x65\x47\xe8\x85\x92\x02\xe6\xd1\x34\xee\x5f\x91\x8a\xeb\x76\x5d\xe2\xf4\xad\x9a\x1d\x2f\x11\xae\x0f\x65\xb8\xf5\x44\x71\xfa\x02\x49\xae\x1b\xad\x85\x1a\xdc\x86\x38\x6e\xb8\x42\xcb\x8c\xcc\xcd\x6a\x7e\x47\x52\xc4\xbf\x65\x52\xca\x7d\x0b\xd2\x6f\xa6\x33\xaa\xa0\xaf\x3d\xf8\x0d\x11\x0b\x07\x97\x9f\x4f\xe7\x74\x4d\xd5\x88\x1d\x13\xb4\xdb\x70\x11\x2f\x66\xdf\x7f\xa6\x93\x66\x5b\xdb\x89\x66\xc4\xf9\x59\x07\xfc\x3b\x5b\x52\x38\xe2\x6b\x2f\x23\x10\xfc\xc8\x74\x9b\xa8\x8e\x6a\x73\x6a\xab\xa3\x48\xda\x05\x25\x60\xd9\x36\x3e\x7a\xce\x9f\x70\x03\x15\x7d\xeb\x78\x2e\x25\x86\x25\xcd\x88\xb2\x55\x87\xe8\x1e\xbc\x32\x3b\x20\xb5\x1e\x3a\xe5\x04\xb4\x8a\x1d\x93\xb4\xfb\x2b\x48\x83\xfe\xcf\x46\x29\xdb\x0e\xe0\x44\xd3\x1c\x50\x25\x1d\x1d\xcf\x6e\xc3\xdf\x06\x79\xbc\x74\x1a\xef\x5f\x6c\x51\x9f\x74\xa0\xca\x66\x58\xb1\xe5\xdc\xae\x64\x4b\x76\x99\x74\x92\xf2\xf4\x2d\x78\xa7\x0d\x45\x8c\xe6\x1c\x5e\x0f\x28\x54\xab\xa9\x78\xa6\x0a\x9c\xda\x46\x6f\xcc\xdb\x6a\x8b\xb1\xbd\xc1\x73\x13\xe5\xcd\x2b\x76\x61\x14\xf1\x6f\x30\xff\x39\x05\xca\x29\x30\x7c\xb6\x3f\xbc\x6c\xc2\xe8\x18\xae\x82\x4e\xf8\x4c\x7e\x67\x61\x99\x6f\xe9\x57\xf8\x66\x60\x99\x37\x3e\xa6\x04\x14\x63\x99\x41\xd5\x53\x73\x68\xa6\xc7\x4d\x38\xe0\x4e\x31\x7d\x3b\x9a\xf2\xff\x13\xcc\x5d\xe4\x36\x3b\x46\xbc\x49\xe3\x96\x8f\x92\x75\xae\xfa\x27\xe6\x77\x6b\xa3\x4b\xe4\x18\x03\xee\x94\x4f\x41\x66\x17\x9d\x51\xa7\xff\x0f\x28\x98\x78\x38\x56\x17\x4d\xeb\x77\x02\x69\xdc\xf2\xd0\x08\xb8\x58\x45\x65\x06\xff\xbd\xc5\x55\xd1\x5d\xa9\xf0\x0c\xfe\x7b\x89\x15\x6f\x48\xf1\xc0\xe9\x55\x0d\xfd\x78\xd1\x01\x55\x36\xa3\x8a\x85\x1b\x34\xa8\x7c\x94\x6c\x55\x6b\x82\xd6\x63\xea\xa2\x3f\x5a\x0c\x19\xa4\x26\x26\x23\xcc\x1c\x67\x4a\x1f\x59\x7b\x10\x19\xbb\x35\x11\x91\x70\xd2\x74\xf2\x6c\xcc\x5b\xeb\x02\xe0\x34\x1d\xd7\x1b\xa5\x60\x87\xba\x15\x0b\x57\xd9\x4d\xd4\x2a\x57\x7e\x25\xb0\x45\x97\x99\x9b\x2f\x16\xcc\xe2\xef\x09\xcf\x25\x0b\x82\xb2\x16\x3a\xc8\x27\x1a\x05\xc2\xf6\xf0\xc7\x9d\xc3\xe0\x82\xaa\x28\x7d\x51\xd7\x6b\xc1\xe1\x2a\xaa\x32\x28\xe6\x38\x26\xb2\x8b\x05\x7a\xcf\x8b\x6c\x86\x38\xd6\xa1\x29\x73\xba\x8f\x92\x44\x39\xf5\x0d\xc6\x77\x81\x09\x41\x29\x13\x09\xd7\x13\xda\x94\xbb\x7e\x02\x77\xc7\x7b\xe4\xd2\x97\x03\xa4\xd9\xec\xc0\x91\x1a\xc1\x3f\x1c\x1b\xd3\x9a\x05\xbf\xa9\xe1\x51\x47\xe6\xc8\xe2\xef\x29\x7c\x46\x39\x05\x84\xbc\x92\xe6\x21\x23\xb0\xcd\x84\xc8\x47\x83\x89\xf3\x90\xca\x15\x42\xf7\x00\xb1\xc7\x4d\xf7\x02\x78\x31\x80\xb6\x24\x97\xee\x64\x0c\xa2\x2d\xd7\x08\x95\xd1\xe8\x55\x8b\x8a\x5d\x07\xcd\xf4\x6d\x31\xfa\x62\xf5\xe1\xa9\x77\xbd\xa0\xf9\xf5\x03\x75\x8a\x0c\x6b\xc4\x81\x6a\x8c\x8e\x79\x02\xd5\xd8\x57\x97\x82\x29\x6b\xba\xac\xbd\xf2\x98\x11\x3d\xe3\x63\xb2\x20\x1d\x51\xd6\x9b\x90\x03\x67\x24\x59\xa1\xa7\x58\x49\xd8\x62\xa1\x2e\x1e\x45\x33\x3a\x03\x93\xdb\xf6\xc5\x98\xd6\xef\xec\x34\x3e\x09\x88\xcd\x99\x0c\x6d\x57\x1a\xb9\x90\xcb\x6e\xbb\x33\x1a\xbb\x72\xe0\xaf\xb1\xde\xae\xe8\x68\x4c\xdf\x91\xd9\x6e\xd9\x93\x6d\x3d\xdc\xdf\x1b\x3e\x3e\x28\xc7\x9f\x44\xf4\xa1\x62\x9f\xeb\x32\x71\xa9\x6d\x41\x1f\x57\x3c\xb0\x4b\x32\x0a\x39\xca\x0e\x0b\xfa\x77\xa3\xcf\x64\x21\x71\x1b\xe3\x93\xe7\x76\x60\x16\x32\xf0\x31\x98\x93\x1c\x52\x73\xc8\x55\x95\x28\x89\x0c\x26\xe9\x46\xee\xf8\x6b\x4c\xfb\xd8\x21\x5e\xc0\xbf\x7f\x98\x35\x86\x9a\xb5\x8b\x07\xff\x73\xba\x8d\x43\x0d\x88\xcf\xf1\x1d\x74\xe0\xc3\x62\x6a\xa6\xbb\xd3\x1f\x7e\x18\x75\x2f\xd0\x73\xdd\x31\x1d\x7e\xeb\xb6\x2c\x18\x8d\x5e\x25\x71\xb5\x71\x65\x14\xf3\xaf\xe9\x9e\x9a\x8f\x9a\x1e\xfa\x23\xea\xf8\x72\xc6\x5a\x5b\x1c\xc1\x8a\x3a\x7b\x7e\xa9\xd2\x10\x87\x97\x41\x31\x47\x47\x1d\x47\xc5\xb9\xce\x0e\x5c\x97\xde\x77\xb4\xf3\x48\x1a\x09\xcd\x1e\xdd\x3a\x21\x7c\x90\x3b\x58\x67\x6f\xf2\x3b\x2b\xa7\x72\x9d\x93\x9c\x52\x5a\x48\x23\xed\xf2\xc5\x9d\x72\xfd\x73\xdc\x23\xe4\x00\xa6\x20\xe1\x81\x3b\x50\x95\x7b\xf2\x31\xac\x6e\x41\x1d\xc5\x1c\x2d\x42\xac\xf8\xeb\x9d\xe9\x3d\xac\xf6\x6b\xa7\xe5\xe9\x0a\xa1\xfb\x2c\xe6\xfd\xd9\x14\x56\x15\x17\x79\xed\x7a\xf3\xfb\x7b\xed\x2f\x82\x5b\x28\x3e\xbe\xb1\x81\x49\xa3\x2e\x0e\x16\x47\x3e\x64\xdb\xbe\x0f\x1d\x08\x72\x48\xa1\x03\xfc\xbb\x92\x84\x85\xff\x95\x95\x03\xf6\x8f\x4a\x8b\x9c\x1e\x0d\x1b\x12\xdd\x59\x8f\x03\x5c\x5f\x52\xa5\x3e\x17\xbb\x08\xd0\x46\xdf\xd1\xc7\x3e\x0b\xfb\x27\xf5\xdb\xb8\x9c\x1b\x2b\x3b\x2d\x25\x1f\x43\x5a\x55\x38\xd4\x48\xd7\x85\xf3\xe0\x8c\xe2\xe6\xd7\x97\xbb\x45\x9a\x1e\x57\x4f\x30\x9b\x98\xf2\x4a\xd8\x34\x19\xf7\xfd\x8c\x44\x94\x06\xea\xf4\xa5\x46\x22\x56\xc7\xbf\x0d\x6f\xdf\x73\x37\xdb\x59\x6a\xb2\xd8\x89\x81\x7d\x3f\x52\x7b\xd6\x26\x83\xd4\x10\x94\xcf\xad\x3d\x2f\xf2\x82\x57\x24\x5c\xa5\x8f\xf7\x61\x98\xf1\x59\x3b\xd4\x23\xd3\xfe\x7c\xc1\x5e\xc6\xac\x78\x5e\xaf\x1c\xdd\x4b\x21\x77\x5b\xbd\x6c\x88\x8a\xcb\x72\xb5\x03\x86\x09\x86\x7b\x59\x42\xe2\xe3\xef\x8a\xaf\x2b\xd9\xc9\x36\x39\xc0\xab\x4f\xae\x5f\xf6\xe8\xb0\xa0\xef\x7d\x3b\x4f\x8c\xba\xdd\x5f\x53\x9a\xbf\x71\x4b\x6c\x41\xfa\xe0\xa3\x3c\xa9\x86\xfa\xd0\xc7\x39\x3c\xbf\x53\xa4\xf1\xe9\x70\x46\x9d\x94\x7e\xcc\x2a\xd1\xf4\x77\x85\xfc\xff\xdd\x71\xe7\x98\x40\x91\x42\xed\x55\x2b\xb6\x50\xed\x34\x3e\xb3\x8a\xdb\x24\xfa\xd2\xeb\x65\x3b\x76\x74\xf1\x26\xcd\x3a\x89\xf0\xa8\x76\x34\xf7\x48\x63\xa5\xef\x65\x27\x8f\x92\xf0\xd4\xc6\x2f\xa3\x8a\xa7\x6a\x51\xf1\x2e\x6a\xaf\x4c\x87\xc6\x28\xc7\x81\xd0\xdd\x66\xe5\x41\x88\x22\x8a\x39\x4e\xe4\xfe\x8d\x7c\xb3\xf1\xbb\xe9\x39\x8e\x86\x23\x7e\x49\x73\xf5\x0e\xa9\xeb\xbb\x21\xfc\x31\x1e\xd1\xd5\x64\xd3\xfa\x60\xb3\x03\x14\x47\xae\x48\xa7\x3b\x52\xb4\xb2\xea\x59\x41\xe4\x1b\xbd\xfa\xf7\x7a\x6b\x73\xf9\x14\x99\x38\xa6\x1e\xeb\x2a\x83\x7e\xb1\x95\xaf\x73\xf6\x15\xe0\xa9\x70\xb2\x5c\x58\x96\xd1\x59\x7d\x94\xdd\x79\x92\xf6\x69\x57\x36\x5c\xa2\x18\x32\xf8\x46\xd5\xe1\xbb\xd9\xe4\x59\xfd\x6b\x96\x3d\x6d\x2e\xe4\x04\x27\xa0\x0f\xe9\x13\x5b\x19\x34\x2b\x16\xcc\x52\x1e\xb3\x25\x73\x00\x9d\x1e\xd9\x0c\xfe\x7b\x7c\xbf\x12\x46\x1f\x5f\x6f\x59\xc7\xa7\xe6\x15\x9c\x3b\x7d\x5c\x45\x3d\x51\xcb\x77\x88\xd9\x9b\xfb\x9a\xf1\xb1\x17\x54\x63\xa8\x99\xf8\x4a\x36\x9c\x91\xe5\x72\x61\xe9\x1f\x76\x6b\xe8\xde\x35\xf4\x13\x01\x70\xb6\x33\xfd\x61\xea\x68\x8a\xab\x6d\x87\x8a\xe1\x9a\x0a\x8f\x5c\xf8\x74\x77\x7a\xd0\x3b\x2c\xeb\x46\x81\xeb\x73\x2c\x23\xe8\x72\x77\x43\xd5\xfb\x33\xab\x02\x39\x63\xd2\x0f\x2b\x83\xac\x32\xaa\xfd\x12\x2c\x47\x26\xed\x59\x87\x8e\x94\x27\x45\xe6\x1b\x4c\x24\x5c\x25\xdb\x18\xfa\xb8\xde\xe7\x93\xbe\x99\x7b\xcf\xb9\x62\x17\x81\x82\x9c\x49\x55\x1a\xb4\xf3\xb8\xff\x22\x89\x72\xca\x1b\x8a\x50\xcb\x92\xae\xd2\xb5\xb9\xf6\xca\x88\xd7\x1c\xb5\xb1\xef\x44\xca\xc3\x0a\x62\x98\x9d\x66\x74\x0b\xea\xb5\x25\x2a\xad\x3b\x54\x0c\xcb\x95\xa3\xb4\x7c\x5c\xd3\xbd\x90\x0c\x91\xad\xf4\x6a\x7a\xb5\xba\xa3\x2a\xf7\xca\x88\x77\x29\xdc\xf8\xa6\x2e\x74\x58\xa2\xb2\xc8\xef\x4f\x1d\xd9\x4c\xa0\x63\x98\x5f\xc3\x45\x9e\x5e\xab\x58\x28\xaf\xda\xa8\x1e\x8a\x99\xf5\xe6\xb7\xb0\x42\x33\xe8\xe3\x18\x31\xe4\xb6\xd6\xc5\xfb\xda\x03\xf4\x49\x32\xbe\x5f\x8f\x65\x9b\xc1\x29\x1e\xc8\x29\x78\x0e\x90\x5d\x26\x8d\x1f\x92\xab\x0d\x81\x00\x0f\x42\x4d\xc0\xab\xc6\x83\xf1\x6b\x9b\x1f\xfc\x05\x95\x6f\xdd\x83\x06\x95\x8f\x89\x82\x68\x33\x68\x4a\x17\x9e\x58\xd8\xe6\xd6\x45\x3d\x52\xeb\x27\xa0\x3a\x18\xa4\x6f\xae\x14\xaf\x07\x84\x2b\xa6\x46\xab\x45\x69\x89\x23\xf5\x50\xfa\x6f\x03\xac\x5e\x0e\xd6\x8d\xa1\x8f\xe1\xe6\x6c\x97\x76\x5a\xb2\x56\x5f\xf1\xf8\xa1\x36\xf6\x05\x12\xdb\x04\x7f\x01\x26\xbb\xff\x1e\xdf\xc9\x85\xe7\x9c\x4a\x7b\xd6\xd1\xad\x40\xcd\xa7\xcf\x76\x3b\x49\x26\xc4\xa7\xb8\x43\x63\xfe\xee\x70\x63\xea\xb0\x58\x9c\xbc\xab\x9d\x66\xbe\xcb\xa5\x4a\xc2\x63\xde\xb7\xab\xb0\xeb\xae\x48\x26\x05\xe3\xeb\xb3\x0d\x94\x53\xde\xdc\x4b\xc7\x99\x22\x54\x51\xcc\x7f\xf2\xfc\xba\xf7\x84\x0b\x6e\x21\x99\x14\xce\x90\xa7\x7e\x43\xce\x66\x61\xd3\x74\x45\xed\x9c\xd3\x19\x23\x4f\x99\x40\x1f\xe7\xb8\x79\xa0\xd2\x2e\x91\xae\xb4\x39\x32\x39\xd5\x74\xe7\x5a\xa0\x17\x7a\x8b\xcd\x04\xe6\x73\x0c\x57\xf8\xdb\x3a\x93\x8c\x6a\xd4\x3c\x90\x77\x91\x4c\x91\x2d\xf1\x26\x59\xf0\x2a\xb7\x38\xae\xfe\x55\x99\x3c\x7a\xc3\xb3\x63\x8c\xd8\x67\xbf\x03\xee\xc6\xfe\xd1\xea\x2e\x9e\xff\x5a\xd0\xc7\x7c\x09\xc7\x51\x5a\x5f\x7c\x2c\xd0\xcb\x07\x14\x71\x69\x5c\xc0\x09\x0e\xb5\x2c\x30\x17\x1c\x0a\x87\xcd\x72\xb1\x61\xd5\xc4\x7c\xee\x21\x74\xf4\x53\x22\xbb\xb2\xba\xa8\x63\xe7\x10\x5e\x41\x14\xf4\xb1\xcb\x25\x1b\xc4\xcf\x33\x31\x99\x9e\x48\xa6\x48\x33\x9a\x65\x3d\x79\x00\xcd\x82\x9b\x3b\xf7\xc7\x8c\x2a\x16\xae\xa2\x5b\xab\xdd\x60\xd7\x93\x37\x5d\xec\x22\x30\x9f\x83\x5b\x10\xd0\x2a\x94\xd3\x9d\x3d\x71\xd4\x8e\x66\x39\x06\xf7\xba\xf1\x66\x77\xe8\x16\xf0\x25\xa8\x41\x67\x34\x53\x9e\xff\x8a\xc7\x89\x39\x85\xc1\x05\xcd\xae\xaf\x97\xce\xc4\x28\x77\xa3\x8f\x1d\x83\x7b\xf2\xf6\xeb\x9e\xc2\xdd\x3b\xdb\x1f\xb1\x11\xcc\x56\x0b\x0f\x0a\x2d\x33\x3c\x6d\xdb\xa5\xc2\xa1\xc0\x11\x1b\xaf\xb8\x97\x44\x91\x31\x06\xa3\xca\x51\xf1\xde\x9f\x2a\xdf\x3e\x4a\xf6\x42\x32\xe1\xe1\xe4\x10\x3a\x8d\x99\x0b\xfe\xb9\x8e\x27\xab\x1f\x68\x7e\x4c\x81\xeb\xea\x1f\x7f\xfc\x46\x22\x33\x28\x5f\xa8\x03\x7d\xcc\xf7\xe2\x78\x43\x3c\x7d\x5a\xec\x50\xc3\x92\xba\x33\xb0\x6c\x6c\x8c\x11\x70\xb1\x70\xe7\x90\xa4\x97\x6a\xd0\x3c\x03\x9a\x7c\x92\x61\x40\x1d\x96\x15\x01\xf6\xf0\xdc\xcf\xfa\x8f\x7b\x59\x2d\x08\x97\x96\x13\x1e\xab\x46\x05\x57\x49\x8c\xd7\xb4\xd1\x73\xfc\xfa\x6a\x9a\xa3\x06\x8a\xd9\xf4\xcd\x23\x2a\xa7\xa9\xde\x6b\x2c\xdb\x3f\xe1\x8b\xfe\xdd\x18\x8f\xc0\x1d\xae\x62\x17\xa7\x38\x6a\x25\xec\x39\xa4\x1b\xd4\x72\xe9\x7d\x78\x20\xdf\xe4\x6d\x4d\x27\xbf\xae\x42\x9e\xdc\x3d\x46\xfa\x0f\xcc\xfe\xef\x5d\x80\x52\x16\x6f\x6e\xc2\xdb\x7e\xd2\xe8\x6c\xc4\xad\x32\xe5\xa8\x29\x6f\xad\x17\x56\x9f\xef\x36\x7e\x35\xe9\x63\x7b\x46\xb9\x76\x0b\xc9\xa0\xb2\xae\x34\xb7\xd3\xb2\x3b\xb5\xdf\x3a\x65\x08\x15\x5e\xc8\x38\xb5\x6f\x03\x0e\xbc\x63\x43\x39\xfd\x03\x51\xa7\x96\x60\x37\x03\x78\x2b\xeb\x17\x9b\xfe\x4e\x90\x62\x9e\x51\x4c\xa1\x8f\x19\x6b\x42\x6a\x9a\xbc\x85\x22\x7e\x53\xfe\x09\x4e\x16\x1d\x17\x12\xb6\x91\x75\xe4\x45\x7d\xfc\x26\xef\x51\x3b\x23\xe9\x1b\x7b\xc8\x41\x13\xe0\x8e\x2e\xd3\x36\xf9\x9e\x40\x11\x07\x72\x13\x9e\x1f\x0f\x22\x66\x4f\xd5\x2f\x48\x09\xfe\xad\x04\xec\x54\xfd\x0c\xc9\xea\x03\x35\x1a\xb7\x58\x54\xbf\xde\xc5\x84\x3d\x82\x22\x67\x49\xa3\x55\xdf\xa2\xf2\xe0\x89\x9b\xd8\x02\xec\x85\xbc\x64\xfa\x86\x8e\xc9\xe7\x98\x70\x46\x32\xab\x23\x1a\x7e\x87\x23\xb6\x6c\x3a\xc0\x37\x3b\x45\xa1\x93\x7b\x2d\xe0\xe3\xc5\xf0\x0c\xfe\xe2\x95\x95\xc2\x0b\x44\xbf\x7e\x6f\x47\xa6\xe6\xeb\xfa\x90\xf8\x0b\xda\x3d\x33\x1c\xe6\x19\x8f\x9e\xf8\xed\x42\xf2\x0b\xdf\xfc\x8a\xe8\xe0\xc4\x8e\xbf\x75\xdb\x6c\x88\x76\x08\x30\x67\x7d\x4b\x41\xc5\xb3\x12\x6c\x1c\xd6\x34\x93\x0c\x83\x0a\xb0\x70\x36\xa6\x0e\xcd\xc7\x6a\x35\x9f\xd7\xf1\xce\x47\xd9\x4a\xc4\xe3\xd9\xe6\xca\x57\x74\x51\xcc\x5a\x9d\x6b\x04\xe3\x85\x7c\xaf\x72\xc2\xe3\xf3\x0f\x3e\xfb\xba\x66\x08\xfa\xcf\x29\xf4\x2b\xf0\x27\x79\xd4\x71\x92\x53\x9a\x4a\x05\xee\x5b\x0b\xb5\xc7\x63\x75\x85\xc8\x83\x39\xc9\x56\x8f\x30\xf9\x1c\x87\xb1\xd8\xd3\x6c\x1c\xb0\x44\x06\x56\xe7\xe1\x0e\xcd\xfc\x78\xae\x56\x5b\xa1\x83\x8f\x50\x47\x26\xb1\xfa\xfe\xae\x55\xa2\x6e\x6e\xb1\x0b\xd8\x4b\xd4\xfe\xac\xb4\xc8\xe9\x1b\x1b\x14\x21\x24\xbe\x32\x5e\x5c\xb8\x1e\x4a\x67\x16\x8b\xf5\x56\x6b\xc9\xb3\x55\x3b\xdf\xfc\x0c\x47\xfc\x2a\xed\x1e\x56\x8e\xf2\xb8\xda\x68\xb7\x78\x47\x28\x45\x53\xbc\x27\xc4\x8c\xc1\xc7\xd0\xac\x18\xb9\x3f\x6a\x01\xb1\x79\xe9\xc4\x1a\xb9\x93\xdc\x17\xab\x8b\xfb\xc5\x57\x2b\x0d\x19\x78\x93\xa7\x0d\x4c\xdd\x7b\xee\x5a\xa4\xae\xdb\x60\x4c\xeb\x1f\xa4\xe7\x4c\x32\x68\xb6\xe0\xa3\x29\xd7\xb2\x02\xd6\x4d\xa7\xc3\xdd\x84\xfc\xe7\x6a\x3d\x6a\x97\x24\x14\x5c\xde\xdc\xd0\x6e\x81\x6a\xbc\x0d\xbd\x64\xe1\x7f\x83\x1e\xc1\xcf\x4a\xca\x01\xf7\x85\x2e\x49\xe7\xa8\xfd\xda\x51\xf5\xf2\xd7\x9e\xf5\x27\x8e\x4b\x13\xbf\x33\x44\x17\x6f\x10\xbf\x77\xbb\xbf\x76\x46\x32\x71\x9f\x2e\xf0\x7c\xaa\xdb\xd1\x74\x23\x7f\x7a\xe2\x02\x26\xda\x9f\x6c\x55\x31\xd7\xd2\xf8\xe4\x6f\x16\xf5\x85\x5e\x9b\x99\xbe\x6c\xa7\xd4\xdb\x47\xbb\x91\xe6\xd7\x8f\x38\x88\x8a\xfd\xa5\x3c\x1f\x6d\x6a\x62\xe6\x8f\x18\x58\xa4\x73\x16\xb2\xe4\xfe\x1c\xcf\x36\x9f\x10\xcc\x83\x33\x7e\x34\xa7\x3a\x5f\xee\x64\x70\xfd\x62\x4e\x1f\x3f\xf9\x0a\xa5\x2f\x85\xda\xc7\x5e\x2f\x2a\x46\xb5\xe0\xa3\xf1\x10\x84\xa7\xdd\x17\xf6\x9b\xdd\xb5\xb2\x3d\xa6\x9f\x25\x9b\x2e\xb8\xfe\xb1\xa3\x89\xb9\x85\xcb\x9b\x57\xec\xb3\xd3\x10\x20\xd5\x4b\x63\x0f\x6f\xea\xc2\x8a\x72\x0c\x65\x7c\xda\x95\x1e\x8a\xde\x53\xe8\x14\xee\x50\x54\xcb\x77\xb9\x64\xb6\x30\xfc\x59\x08\xe3\xd3\x7b\xa5\xfd\xee\x9c\xa4\xcd\x80\xff\x17\xbf\x03\x35\x71\xf6\x17\x66\x6a\xc4\x34\x13\x0e\xf3\xc6\xdf\x99\x7b\x19\xe7\x17\xad\x3b\x54\xf1\x1a\x77\xf9\x4c\x47\x1b\x7e\xd0\x9b\xa8\x08\x93\x7a\xb5\x9f\x8b\xc7\x87\x0e\xf9\x9a\xfe\xda\xb3\x3c\x98\x47\x98\x53\xdc\xe7\xdf\xe0\xc5\x58\x5d\x07\x03\x14\x3a\xea\x75\x57\x64\x4a\x8b\xc2\xb2\xfc\x23\x73\x2a\x61\x9b\x06\xa7\xf8\x0b\x1d\xd3\x90\x43\xf7\xd4\xcf\xd0\x5b\xd4\x68\xef\x41\x92\xe1\x51\x5c\x9a\x09\x47\xf1\x40\x56\x8b\xfc\x45\x56\x44\xeb\xa3\x5e\x58\x15\x61\x43\xf3\x6c\xa5\x80\xf7\x5b\xb1\xf0\xe6\x38\x79\xcf\x81\x2d\xbe\x52\x26\xd6\x02\x6c\xf1\xe8\x8f\x97\x9d\xe9\x21\x98\x83\x0e\xe7\xd2\x9c\x17\xcf\x39\x4b\x1d\xb3\xdc\x0e\x18\xdb\xed\x4f\xd0\x3a\xf4\x3f\xf2\x8d\xa4\x05\x0e\xa2\x0d\x67\x07\xae\x67\xf5\x2f\x84\xa1\x5c\x07\x03\x68\x72\x6e\x44\xb7\x1f\x64\xca\x29\x20\x37\x11\xb5\x0d\xc9\xff\xc4\xd9\x6a\x2b\x14\x92\xa7\x5a\xca\x82\x50\x5b\x98\xd9\x5e\xfb\x76\xcc\x29\xd6\xf4\xed\xa8\x7b\x01\x66\xc0\xd0\xcc\xbd\xb7\x23\x27\x95\xfa\xb5\x57\x7c\x71\x51\xf2\x19\x8d\x6b\x70\x55\x7d\x86\xf4\x4c\x7d\xbe\xc6\xd7\x35\xbd\xa0\xdf\xc7\x2b\x31\x78\xf4\x9c\xf8\x13\x05\x2e\xac\x52\x7e\x40\xb0\x13\x92\x49\x65\xfd\x45\x40\x98\xb1\x87\x1d\x6a\xbf\x21\xcf\x9e\xf8\x49\xee\xd7\x26\xee\x91\x64\x25\x65\x95\x8f\xd9\xdb\xed\xfe\x0d\x7a\xab\xa4\x3e\x7a\xa2\x2b\x5a\xdf\x70\x58\x2e\x6f\x5a\x7f\xfb\x47\xe3\x93\x9a\xd0\xc7\xd4\xcd\x13\x9c\xdb\xf7\xde\x7f\x4d\xd5\x25\x8c\xa6\xcc\x17\xfa\x8d\x9e\x9b\xe9\x09\x94\xb2\xd2\x41\xe8\x54\xa4\x2d\x08\x18\x83\xd7\xc2\x4a\xa3\x51\x5c\x1e\x3a\xa8\x8d\xfd\xac\x82\xba\x5c\xdf\xea\xbc\xef\x72\xd4\x4d\x5c\xbd\x24\xf2\xe8\x8e\x42\xae\xa8\x6d\x07\x78\xd7\xe1\x33\xab\x9f\x9a\xdb\x9f\xa7\x60\x3a\x91\xc4\x45\x44\x78\xd9\x92\x0a\xef\x3a\x3b\x62\x8a\xc3\xce\xad\x8e\x3b\x71\x0f\x12\x14\xa7\xf5\x6b\x3b\x1a\x54\xf3\x15\x4a\xe7\x75\x5f\x3f\x61\x7d\xf9\x0f\x4d\x06\xd6\xf1\x4f\xaf\x35\xd6\xc5\xcf\x0f\xdd\x3f\x15\x01\xe7\x4e\xbc\x0c\x4b\x60\x38\xdb\xcd\xa3\x6c\x9b\xbf\xf6\x3e\x5f\xa1\x74\x6c\xaf\x3c\x60\x1e\xdd\x6e\x7f\x02\xe1\x19\x60\xb3\x46\x99\x8d\xae\x2e\x31\xae\xc7\xe6\x53\xed\xed\x9f\x62\xce\x7d\x8d\x97\x75\xae\x1a\x15\x17\xed\x4a\xf1\x49\xd6\x7d\xe0\x20\xe9\x6a\x57\x87\x15\xe3\x8e\xae\xbe\x60\x55\xef\xfe\x0c\xcb\x06\xbe\x7e\x8f\x3b\x50\x25\xad\x45\xc0\x9b\xc1\x68\x37\x8b\xef\x9b\x34\x37\x24\x53\xa7\x52\x81\xe7\xd3\x34\x97\x3b\x4b\xc1\xef\x16\xf8\x86\xec\x37\x9f\x51\x33\x9e\xd4\x60\x03\x27\xaa\x25\x69\xc1\x56\xee\x0d\xec\xb9\xf9\x06\x2b\x33\xb5\xbe\x6f\xd2\xac\x2f\xe1\xcc\x0c\x13\x15\x03\x4b\x06\xfb\xef\xa4\xb3\x89\x9f\xbe\xee\x8f\xc7\x32\x83\x2e\xb7\xce\xc3\x2c\x21\x05\x1f\xde\xab\x8b\x95\x83\x63\x26\x81\x96\xfd\x3e\x27\x83\x55\x05\x22\x6d\x1c\x1e\x6c\x8e\xd7\xfd\x00\x79\xfa\xe6\x66\xf5\x82\xc6\xf5\x77\x73\x2b\x82\x73\xe9\xb3\x6b\x75\x7c\xfd\xc0\x60\xd3\xa5\xb0\xee\xaa\xc4\xca\x5e\x81\x8c\x91\x2a\x76\x11\x16\xb8\x26\xd2\xcd\xf3\x1f\xe9\x90\xfc\x7d\x7b\xf9\x57\x97\x2f\x41\xbe\xd1\x01\x88\x7e\x39\xb3\xcd\x4c\x2d\xa3\xea\x28\x4d\x28\x1b\xad\x11\xfe\xa3\x60\x80\xdc\x77\xd9\x0c\xfe\xb4\x6f\x85\x5c\x77\x37\x04\xd9\xbd\x38\x23\xe0\xf2\x42\xae\xfb\xf1\x12\xc8\xf5\x02\x8a\x0c\xe0\x8d\xb6\x4d\x96\x0d\xad\x4a\x5b\x7b\x0f\xd9\xde\x69\x50\x44\x6c\xdf\x23\x4d\x64\x0f\x6f\x1b\xf1\x46\x86\x4c\xc0\xf2\x6b\x44\x22\x2a\x77\xab\x83\xaf\xcf\x25\x0b\x79\xd1\xdb\x63\x4f\x77\x92\xb9\xcb\xe7\xf5\xde\x6a\x84\x5a\x94\x65\x4f\x2e\x1b\x63\xfb\xb7\xb2\x85\xac\xc1\xbf\x6a\x01\xcf\xf3\x9a\xdc\x7f\xdf\x65\xac\x35\x41\xcf\x1e\x10\xcd\xce\xfe\xe5\x60\xb8\xa5\x4e\xb3\x56\x20\xbb\xc0\xfe\xc2\x65\xaf\x59\x93\xa4\x76\xe3\xe9\x6e\xff\xf5\x14\x74\x2c\xee\x73\x24\xd6\xdb\x9a\xfa\xe3\x1d\x39\x3a\x23\x93\x65\x24\xd2\xff\xd2\x3b\x16\xc7\x1b\xed\x5f\x6c\x51\x71\x33\x83\x1e\xf0\x6a\x93\x7e\xfb\x17\x8f\x5a\x9e\x9e\x51\xeb\x85\x3d\xd4\xdb\xb5\x17\x74\xe4\xe8\x7c\xde\x3f\xfa\xb9\x96\xed\x2c\xf8\x86\x98\x1a\xf8\xfe\x66\xfb\xb1\x0e\x38\xbb\x60\x95\xc1\x3f\x78\x76\xe7\xc9\x57\x6b\x9b\xbf\x37\x38\x1c\x38\x3a\xe5\xb5\x67\xcd\x4a\x2b\xd8\x19\x40\x67\xae\xbc\xf9\xdf\x0d\x2c\x45\x1c\x08\x4d\xcf\xbf\x08\x6d\xd1\x5a\x85\xeb\xf6\xbf\x20\x06\x09\xbd\xf0\x68\xbd\xcb\x94\x62\xd1\x30\xed\x35\x5b\xe5\x28\x50\xed\x9b\x3d\x9a\x32\xaf\x43\x9e\x2e\x16\x64\x00\xbe\x02\x36\x32\x46\x6b\x84\x4a\x8a\x0c\x90\x9b\xd0\xc2\x9c\x54\x3e\x37\xfe\xed\xae\xe8\xd6\xaf\x95\xc2\x51\xb1\x85\x93\x27\xc3\x9c\x05\x2e\xa5\x11\x47\x49\x05\xc6\x70\x06\x20\x48\x09\x1e\x08\x46\x90\x9d\x5c\x20\x62\xb8\xb7\x4a\xca\x7f\x9d\x72\x1d\x2b\x78\x38\xd4\x48\xa1\xf7\x12\xd5\xa0\xbc\xba\xbc\x12\x8b\x41\x6a\x26\xdf\x39\xfa\x5d\x8e\x46\xac\xe0\x46\xc9\xb6\x0b\x92\x51\xef\x7b\xf2\x05\x18\xc1\x31\x84\x17\x0c\x41\xbe\xf7\x6b\x5d\x18\xe4\x59\x7d\x8c\x7d\xae\xfb\x55\x32\xbc\xc9\xf2\xc0\x3d\xd7\x21\xc1\x81\xbf\xf3\xa5\xbc\xf9\xe0\x66\x5e\x4e\x89\x68\x7e\x47\x13\x46\x95\x19\xb0\xe9\x1e\x38\x5f\x8e\xff\x17\x11\x8c\x81\xfc\x45\x89\xff\x16\x3a\x0b\x85\xb0\xfe\xe6\x25\x2f\x37\xe6\xde\xd4\xcb\x1b\xcb\x19\x62\x56\x06\x13\xb6\x24\xa3\xe6\x4d\xe0\x0c\x59\xbf\xa8\xc6\x4a\xdf\xd3\xde\x06\xcc\xa3\x69\x42\x20\x75\x55\x31\x83\xff\x51\x16\xcf\xa5\xd1\xe2\xe3\xd9\x42\x07\xe6\x08\xb5\x2c\x19\xaa\xb1\xc9\x77\xb3\xe8\x0f\x19\x44\xbe\x26\x5d\xdf\x51\xbc\x48\x14\x42\x03\x88\xa5\xba\xb5\xa7\x27\xaa\x66\xc9\xa7\xfa\xda\x99\x7b\xdc\x47\xd5\x63\xfa\x2f\x62\x5c\x52\xff\xf2\xa9\xc8\xb4\xf7\x3d\x3f\x41\x4d\x0c\xe1\xd0\x70\xa5\x04\x8e\x06\x42\x81\x82\x95\xed\xef\x10\x1a\x14\x10\xcb\x31\x06\xf5\xb4\x06\x77\x6d\x2d\x61\x52\x5d\xee\x1f\x59\xcc\xcb\xab\xcb\x27\xc1\x46\xec\x13\x28\xa8\x3d\x43\x0e\xd1\x68\x68\x7a\x94\x8b\x65\x03\x5d\x7f\x4b\xe6\x21\x06\x75\xdf\x3e\xa4\x70\xa8\x91\x0e\x2b\x4c\x58\x51\x71\x15\xf2\xa6\x15\xa1\x8f\x73\x36\x4f\xe4\x89\x36\x0e\x59\xc1\x8d\x46\x4b\x05\x32\x8c\x54\x99\x71\x6c\x6f\x95\x7e\xb3\xd0\x35\x0f\x54\x4c\xe7\x98\xae\x8b\x86\xe7\x0a\x63\x31\x67\x47\x2a\xae\x32\x48\xfb\x5d\x92\x88\x9a\xff\xc7\xf6\x38\x81\x13\x3c\xc7\xc2\x9f\xb4\xfd\x7d\xf5\x1d\x81\x41\x80\xe7\xb5\xb0\xc1\xf6\x7e\xd6\xcf\xe2\xab\x6e\x1e\xa8\xc4\xbc\x15\x42\x37\x96\x58\xe2\xb6\xf8\x1a\x70\xf3\x74\x24\x29\xee\x84\xef\x32\x79\xfc\xbc\xf4\xeb\xb5\x80\x29\x9c\x41\x20\xe4\xe6\xe6\xe1\x86\xa9\x26\x8d\xcb\x06\xc2\x10\x17\xb3\x1a\x18\xfa\x7b\xfe\xeb\x23\xfc\x1d\x7e\x9e\xa4\x45\xa3\x73\xf9\x70\x46\xf7\x33\xda\xd1\x57\x2e\x98\x56\x38\xc7\x6f\xcc\x54\x8b\x47\x81\x38\xd3\xa9\xf5\xab\x26\xc7\x1e\xdf\x74\x5f\xf4\x31\x11\x4f\x39\x9e\x5d\xb0\x5b\x6e\x92\xf1\x0c\x76\x2b\x69\xba\x3b\xe5\x5a\xb5\x03\x5c\x92\xab\x33\x1d\xdb\xc8\xeb\x95\x83\x95\x00\x62\xc9\x85\x6f\x32\xee\x3a\x92\x02\x3e\x5f\xa6\x09\x01\x62\xdf\xc6\x74\x8e\x29\x63\x84\x31\xf1\x83\xa2\x84\x72\x62\x9b\xb3\xbf\xc0\x55\x5e\x05\x33\xc3\x2c\x01\x46\x95\x27\xad\x05\xa5\x16\xd8\xf1\x0e\xb2\x0b\xd0\x31\x1c\x88\x7d\xae\xdb\xc5\xfb\x7f\x16\xd4\x9e\x92\x1c\xff\x5d\xd1\x7a\xd2\x48\xf2\xd1\x1f\x0f\x8c\x61\xc8\x93\xe1\xc6\x30\xd5\xb4\x5b\xc8\xd3\xe0\x8f\xe0\x92\xc9\x72\x76\xe9\x8d\x02\x10\x57\xfc\x86\x9f\x2b\x89\x28\x19\x5e\x8d\xf9\x79\xfe\xd9\x29\xc6\x38\xbd\x72\xea\x8b\xe7\x9c\xf7\xed\x8a\x7f\x77\xad\x46\x3d\x81\x82\x17\x16\xb6\xbf\x43\xda\x15\x29\x36\x1d\x20\x2e\xed\x2b\x71\x45\x9f\xfa\xe2\xb4\xc2\x65\x09\xcc\x18\x32\xe9\xae\x50\xc3\xd5\xf8\xab\x4c\x71\x97\x37\x9f\x58\x7b\x34\x59\xaf\xc4\x73\x7d\x4e\xc7\x66\x0c\x76\xdb\xc8\x00\x36\xdd\x55\xf6\xcd\xfd\x49\xc6\xf6\xb1\xd7\xc5\x09\x40\xa7\xe7\xbf\x0c\xfe\x7a\xe5\x67\x57\x75\x3d\xd4\xc4\x86\x32\xe9\x94\x86\x95\x74\x5d\xb5\xd8\xd3\x6e\x74\x1b\x31\x40\x1c\x75\x2f\xe8\xf6\x6c\xb2\xbe\xbf\xa7\x49\xa7\x36\x49\x4a\xb4\x38\x10\xa7\x5b\x29\x5a\x92\xc3\xc6\xd8\x9e\xd0\xe9\x63\x22\xfe\xe3\xb8\xf3\xf3\x3c\x2c\x91\xa0\x33\x73\x92\xe1\x96\x36\xc9\x62\x25\xe6\xfd\x16\x67\xdb\x82\xab\xce\x7d\xa2\x63\x29\x23\xce\x2f\xda\xff\x21\x69\xbe\x23\x4c\x68\x73\xa5\x8c\xc0\x28\xa0\x70\x49\xc7\x63\x7b\x3f\x2b\xb9\xed\xb5\xb0\x25\xf4\x5f\x35\x9d\xc4\x84\x25\x0c\x9f\x63\xec\x7c\x93\x2c\xe3\xeb\x9a\x61\x75\x29\x72\x99\xab\x2b\x3d\xe8\xdd\x4c\x0d\x85\x04\x04\x7c\x1a\x9a\x02\xab\x73\x92\xd6\x8b\x5d\x80\x0e\xe5\xa5\x92\xf2\xdf\x8e\xbc\xf1\x0b\x0b\x97\x5a\x1c\xa5\x58\x51\xb8\xc7\xe6\xfe\xe2\x36\xd8\x97\x39\x16\xfe\x18\x3a\x56\x2d\x5a\xd9\x6d\x70\x6a\xcc\x47\x4d\xbf\x60\x62\x54\x59\x8f\x30\x72\xd4\xe6\x61\x8e\x5e\x50\xc4\x34\xde\xc8\xe1\x50\xc3\x2c\xae\x14\x5e\x13\x5a\x48\xd3\x98\x40\xa8\x94\xc8\xbb\xbc\x19\xca\x74\xfa\xe9\xdf\x36\xc8\x13\x96\x88\x15\x02\x6e\x85\x01\xc1\x05\x41\x25\x7b\x2e\x84\x68\xc6\xf6\x07\xb1\xf3\x90\x4b\x7a\x7f\x4e\x4a\x25\xfb\x35\xd2\x4f\x39\x15\xe5\x8f\x15\x7f\xb4\x75\x2c\xa2\x77\x5c\x00\xe3\xfb\x89\xff\x46\x26\x9f\xe5\x45\xe2\x48\x68\x79\x5a\x95\xfb\xa7\xe3\x0c\x4e\x42\x37\x2d\xc2\xb6\xb7\x13\x55\xb3\x5e\x9d\x4e\x67\xd7\xbd\xc2\xd1\xea\x43\xa4\xe8\x7a\xe8\x6d\xbc\x60\x40\x3c\x95\x5d\xa8\x09\xd9\x8b\x4c\x3a\x31\x1b\x60\xf7\x98\x55\x40\xb1\xb5\xa0\xb1\x60\x91\xff\xb0\x1d\x7d\x0c\x37\xe3\x99\x20\x37\xb0\x8e\xb7\xc7\x34\xba\x53\xff\x57\x3a\x56\x7a\x1f\x2e\xaf\x5d\x3d\x66\x7c\x8d\x20\xe9\xdf\xfd\x2c\x84\xa5\x7c\x95\xbd\xed\x4c\x23\x1f\x8b\x40\x3a\x95\x2c\x39\xf8\x60\x2c\x53\xa7\x72\x8c\x62\x02\x84\x56\x25\x7a\x61\xd7\xd3\x36\x5e\xdb\x70\xb6\xae\x0b\x2b\xc5\xfd\x3d\xc7\x84\xb3\xb5\xa4\xd9\x7a\x25\x2a\x1e\xf8\xd1\x84\x80\x77\x96\xbc\xe9\xea\xa6\x97\x65\xc5\xd6\x29\x9a\x10\xb8\x97\x36\xbd\xa3\x4a\x3d\x62\x72\xfa\xc3\xeb\xdf\x0b\xe3\x4b\xac\xf8\x46\x6d\x60\x68\x4e\xdf\x37\xa5\x41\xc1\xef\xf3\x95\x1d\xa5\xf4\x34\x6e\x26\x6a\xf2\x24\xc6\xb0\x3a\x67\xbe\x3d\x39\x71\x4e\x45\xb5\x76\xa0\x37\xae\x3b\x97\xec\x02\x9a\x19\xa8\x06\x7a\xe6\xaf\x8f\x6e\xd3\xb8\xc1\xd2\x2b\xac\xe0\x67\xb5\xbf\xea\x18\xa5\xa7\xab\xb0\x2c\xdc\x68\x37\x0b\xe5\x14\x98\x54\x31\x31\x18\x52\x54\x3e\x1f\xd1\x40\xc1\x80\xe1\x5f\xf1\x1b\x2e\x6f\xaf\x5e\x95\x0c\xcf\xe0\xbf\x47\xf4\x6b\x18\xda\x63\x12\x13\x61\x45\xe1\x2a\x48\xe3\x07\x46\xd1\x1f\x32\xde\x11\x18\x9a\x7b\x36\x43\xc6\x3a\xc3\x67\xff\xad\x95\x38\xa1\xda\xdb\xb5\xb2\x3d\x55\x86\x0c\x20\x78\x88\x6f\xe7\x69\x6b\x41\xe9\x7b\x02\x43\xb3\x25\xd5\x1f\xb6\xd2\xfb\x01\x3e\x2e\xec\x4e\xf2\x39\x06\x58\xa6\x0c\x95\xed\x3d\x78\x5c\x90\x4c\x40\x08\x33\x45\xa4\x59\x04\xff\xd6\xa3\xc8\x80\x61\x9b\x8b\xee\x19\xb7\xc1\x00\x9d\x91\x5e\x98\xd6\x62\xcb\x92\x1f\xbd\xc1\xcb\xc5\x12\xc7\x6e\xf2\x1b\x57\xb4\x7e\x38\x8e\x3e\x06\x82\x27\x96\x69\x1a\x77\x8a\x45\xc3\x89\x7e\x2f\xf2\x52\xb1\x50\xb0\xd3\x71\x28\x80\x93\x8b\xba\xaa\x5c\xb0\xf8\x35\xec\x62\x84\x05\x4d\x0c\xdc\x8b\x28\xf2\x47\x99\xcd\xd1\x17\xa0\x4a\x62\xe8\xdd\x74\x26\x95\x1e\xba\x51\xbd\xe5\x86\x0c\x59\x93\x54\x7b\xfb\xc5\x83\xaf\x75\x74\x76\x43\x60\x6c\x1e\xf7\xcc\xe0\xf7\xb3\x89\x94\xbe\x14\x1e\x12\x50\xc3\x86\x7b\xe3\x5b\x90\xde\x7d\x28\x00\x6c\x87\xec\x8b\xc6\x37\xae\xb7\x8f\x58\xda\x8a\x32\xc4\xb1\x93\xac\xd3\xf5\xf4\x50\xf5\x9a\xa6\x4e\x48\x46\x95\xd0\xda\xa4\x13\x64\x41\x20\xf6\x4e\xde\x7c\xd5\x33\x8c\x54\x48\xc3\xd0\x84\x40\x7f\xb6\x5e\xbf\x57\xb1\xba\x8e\xb8\x78\x78\x06\x7f\x38\xb1\xd1\x35\x9d\x49\x25\xb4\x5c\x19\xda\x6c\xba\x09\xcb\x34\xad\xa0\x1a\xd2\xb8\x41\xff\x34\x24\x83\x3f\xef\x66\xbc\x3c\x67\x44\x59\xaf\xbf\x50\xca\x75\x67\x88\x8a\xe1\xac\x77\x98\x34\xbd\x0c\x9f\x87\x16\x07\xd0\x74\x69\x62\x80\x5d\x94\xdd\xa2\x61\x8f\x9f\xf3\xe2\xdf\x46\xec\x69\xb0\x40\x8c\x9e\xce\x21\x9a\x57\xb1\x97\x45\xce\x43\x24\x3f\x28\x4a\x34\x25\x6d\xa0\x69\x17\xc0\x9f\xf6\xf4\xa0\xe8\xc1\xfe\x3b\xc8\xdc\xec\x56\xd1\x26\xf2\xaf\x08\x51\x21\x4c\x4f\xcd\xc3\xda\x65\xae\xae\x7f\x6d\xdd\xee\xfb\xf3\x0d\x4f\x01\x93\x00\xa6\x68\xb9\x84\x9f\xc3\x3e\x34\x92\xae\xeb\x72\xef\x3a\xde\xb5\x58\x7d\x29\x3e\x55\x6d\x78\xfe\x6d\x0e\x9c\xd1\xad\x6c\x74\x19\xb6\xb5\x62\x3c\x58\xe9\xb4\x0a\x9b\x5e\x4e\x67\xe5\x3a\x32\x9f\xa2\x66\xea\x12\xd3\x30\x1d\x43\x27\xa8\xf1\x5c\x9f\xc9\x76\x62\xae\x83\xcc\x6f\xf3\x54\x9c\xdb\xeb\xae\x16\x05\x0d\x04\x6f\x85\x4e\x1d\x03\x5b\xeb\xff\xd1\xc0\x9e\x9e\x05\x6a\x63\x7f\x72\x65\x85\xd0\xed\x42\xec\xa9\xe8\x61\x14\x50\x1e\xed\xde\xa1\x9c\x3a\x2b\x61\xb3\x17\x87\x88\x8c\xdc\xdf\x09\x58\x7f\xc0\x7a\x55\xb9\xc0\xbb\xe5\x3f\xe2\x74\x77\x7a\xd0\x9f\xc6\xe3\xd4\x2f\x0f\x02\x7f\x4a\x7c\xbb\xb5\x46\xe1\x5c\x3c\xd8\xcc\xf4\xc9\x3b\xa7\x12\x76\x46\xef\xc3\x0f\x74\xdb\xa1\xa9\x05\x74\xef\x91\x45\x7f\x2c\x59\x1d\x74\x1e\x2f\x30\xbf\xa4\xaa\x70\x9a\x05\xc6\x76\x98\x30\xad\xf3\x7f\xc3\x6e\x6f\x62\xf7\xfa\xec\xff\x87\x21\xdd\xfc\xe4\xb9\x08\x16\x56\x91\xa0\x29\x1f\x0b\xaf\xa0\x52\xea\xd8\x39\x72\x2e\xd0\x29\x38\xda\xd8\x17\xb0\xe8\x35\xc0\xb8\xa0\xf6\x53\xf2\x2e\xe9\xa2\xfb\xd1\x50\xdc\xd2\x83\x82\xf4\xf3\x95\x84\x4a\x42\x9f\xb1\x89\xf7\x11\x34\xd4\xc7\xa0\x2f\x75\x27\x9a\xf2\xe5\x25\xdf\x6e\xaa\x39\x9f\x94\x3f\x25\x70\x8f\x95\x3a\x98\x20\x2c\x6a\xd0\x7b\x8e\xe9\x9d\xa0\x4d\x68\x5d\x90\xd7\x9e\x24\xa9\x6a\x04\xcd\x8a\xf3\xb3\xb9\xb4\x10\x49\x41\xb1\x27\x7f\xa0\x97\x24\xf9\x1f\xae\x39\x96\xf7\x30\x0a\xec\xf9\xfa\x8f\x69\xac\xb2\x6b\xd2\xb8\xae\xac\x6c\xd2\x57\xc2\x0f\xb6\x7d\x45\x75\xc2\x98\x9e\xc2\xe3\xbe\x92\x5c\x2b\x63\xaa\x7e\x22\xc8\xef\x35\xdb\x8c\xbe\x17\xec\xfe\xaa\x5b\x84\x1d\x75\x7d\xe4\x9b\x3f\x66\x1c\x70\xb4\xbc\xa3\x5a\x8d\x8d\xc2\xe7\x97\xc0\xb7\x76\xaa\xf2\x8c\xf4\xce\xba\x22\x99\x55\xaa\x66\x97\x1f\x5f\xee\xfb\x10\x99\x5f\x48\xa9\xf8\x1e\x1b\x5c\x25\x61\xf7\xf0\x79\xeb\xed\x6a\x1d\x62\x5a\x95\xfb\x66\x97\x73\x7e\xa9\x00\xe1\xae\xd7\xcf\x60\xa6\x14\xc4\x90\x79\xf0\xe4\x89\x7f\xef\xc3\x09\x81\x7e\xb2\x6d\xff\x91\x75\xe4\x2f\x23\x89\x13\xd9\xf3\x10\xdb\x3a\x45\x89\x89\xf8\x8d\x53\xb4\x0b\xe0\xf2\x17\xf1\xd9\x95\xc3\x96\xc2\x07\xd0\x3d\xfc\x49\xf8\xea\x92\x69\xcd\x4c\x50\x84\x5e\xc9\x4b\x21\x85\x69\xd7\xef\x99\x0e\x3f\x43\xe3\xff\x3d\xbc\xc9\x20\xba\xf1\x09\x18\x50\x5f\x3c\xb7\x68\x98\x5e\x45\x78\x5a\xdf\x42\xb2\xa8\xec\x1e\x7c\x5b\xc7\x6f\x52\x50\xbb\x09\xdd\x6a\xc3\xf3\x34\xe2\xa1\x96\x69\x17\x1a\x8a\xbb\xe7\x5b\x90\x71\xa1\x72\x8e\x96\xd5\x12\xb5\x05\x39\x27\x30\x5e\x65\x3a\x95\x93\xc4\xca\x35\x94\x79\x30\xfb\x6f\x7f\xbf\x99\xf4\xf3\x52\x11\x7f\xef\xd7\x1f\xab\x57\xbf\x95\xca\x9b\x2f\xf7\x1d\x59\x2e\x4f\x95\x62\x9c\x87\xd0\x27\x71\x1b\xcf\x93\xde\xbd\x15\xd9\x9a\x6f\xf3\x29\xe2\xf3\x7d\x80\x5b\x21\x74\x1b\x09\x37\x8c\xa1\x21\xb8\x7b\x12\x99\x6b\xce\x49\x97\x76\x13\xb1\x31\x9f\x48\x2b\xe6\xdb\xd5\x46\xf7\x16\xe3\xfb\x4e\xf9\xe8\xfa\x16\xa4\x9f\xdf\xfe\x7b\x95\xf4\xe8\x27\x84\x3c\x00\x0c\x4e\x79\x85\x1a\x0e\x29\x5e\xcf\x29\x7c\xbe\xc7\xc2\xc0\xf6\xd3\x4b\x49\x59\x67\xd9\x9e\xe6\x1e\x96\x38\x6a\x45\x66\x02\x9d\x25\xa3\xcb\xb0\x92\x10\xb1\x86\xdb\xc6\x44\xaa\x71\xdf\x09\x23\xb1\xf1\x9a\x36\xf4\xf1\x6f\x01\x3e\x79\x3f\xa7\xad\x48\xf3\xa2\xa5\x6f\xd8\x18\xb9\x8b\x06\x0d\x21\xf9\x89\x5c\x6a\xbd\x30\x3e\xa2\x5f\x26\x96\x1d\xf0\xcc\x24\xce\xf4\x74\xff\x38\xc0\x1f\x5f\x85\xb1\x5b\xad\x64\x2c\x45\xb7\x3e\xaf\x2e\x31\x5f\xdd\xf4\xb2\x58\x6e\xec\xc5\x38\xc7\x62\x79\xc1\x8f\x3f\x35\xf3\x90\xf5\x62\x75\x5e\xc3\xa2\x13\xce\xfc\x6f\xc2\xc1\xd3\x2f\xe9\x41\xa6\x2b\x5b\x3f\x8a\xb7\x21\x10\x49\xaf\x84\x1b\x08\x6b\x5e\x71\x3b\xef\x17\x41\x25\x7b\xd3\xbb\xe1\x7c\xe0\xe9\xc5\xa1\x01\x55\xf1\x31\x58\xd2\x8f\x69\x2d\x4c\xaf\x5e\xaa\x0b\x92\x59\xe5\xe1\xcc\x7d\x5d\x8b\x31\x92\xdb\x01\x23\x0d\xc1\xe4\x2b\xf2\x25\x59\xf6\xe1\x1b\x2c\x9b\x53\xf8\xcd\x88\xde\x89\xe2\x9f\xea\x8e\x16\xf5\xcf\x04\xbf\x81\xa7\x52\x71\x1b\x66\x34\x38\x13\xe6\x20\xfc\xdb\x3a\x5e\xa7\xff\x88\x0e\x1f\x55\x33\x9e\xba\x9c\x64\xcf\x95\x03\xfc\x0b\x62\xf5\x84\x3f\xc2\xa8\x66\xc9\x72\xd3\x6e\x5b\xc2\xc2\xeb\xe0\x44\xb7\x00\x2e\x7e\xf7\xe9\x3c\x84\x14\x86\xf0\x39\x23\x12\x4e\xdc\x50\xc2\x64\x26\xf8\x85\x63\xe1\x80\x67\x92\xbe\x07\xba\xa6\xe7\x64\xe7\xe0\x0e\x54\xb3\x52\x72\x38\xfd\x8b\xae\x1c\x29\x5f\x96\x79\x06\x89\x3b\xae\x28\x14\xf2\x19\xdd\xe6\x94\x17\xaa\x26\x86\xc9\xe0\x5f\x22\x6e\x18\xd0\x78\xc1\xbb\x96\xf4\xd6\xc3\x2c\x4e\x91\xf0\xce\x54\xb7\xd9\x6b\x9b\x87\x4b\x95\x8b\x0d\x0b\x0d\x89\xaa\xe0\xc5\x86\x7d\x2f\xac\xca\x3a\x92\x3b\xa6\x58\x1f\x2a\x4c\x52\xef\xef\x10\xaa\xa4\x13\xaf\xfb\xb5\xaf\x4d\x2d\xfc\x25\x16\x83\xba\xd1\xed\xb8\x61\x7e\x8d\x64\x8d\xb7\x47\xc6\x99\xd0\x92\xe0\x41\x34\x2b\x6e\xff\x78\x52\x76\x52\xf5\x17\x84\x5a\x2f\x8c\xf2\xd0\xdf\xbc\x24\x61\xc3\x81\x76\x01\xf4\x4b\x79\x45\x48\x2b\xee\xe1\x77\x76\x43\xb4\x0f\xdb\x14\x1d\x8d\xff\x95\x64\x68\x76\xc0\xb4\x2c\xc5\x07\xcc\x7c\x2f\xbd\xa6\x6c\x7d\x1f\x79\xb3\xec\xb2\xd9\x3f\x10\x08\x16\x52\xa0\xa8\x82\xbc\xc4\xe9\xee\x14\x6c\x23\x36\xfa\xe9\xcd\x30\x38\xf7\xe3\x9f\xf7\x23\xf4\xbc\x2c\xff\x7e\xb9\x84\xc0\x8e\x4b\xb6\xc7\x63\xcf\x83\x9d\x97\xbb\x6f\x45\xb6\x5e\x92\xd4\x7e\xed\xb4\x3c\x59\x21\x74\x9f\x24\x8e\xdf\x4b\x67\x51\x41\xd7\x9a\x19\x26\xca\x7a\xd4\x63\x63\x9e\x76\x1b\xa2\xbe\x7c\x3f\x74\xaa\xbf\xdb\x90\x96\x2c\x63\xaa\xf7\x1a\x8b\x60\xbb\x51\x5c\xb8\x1e\x1a\xd1\xbb\x6f\x37\xd5\xff\x3a\x7f\xd1\x90\xa6\x02\xa2\xa7\x43\x7b\x7b\x3b\xf9\x47\x43\x2e\xd3\x21\x48\xab\xff\x75\x5b\x22\x5c\x45\x79\xf4\x86\x02\xdd\x4d\xf1\xc5\xa0\x7e\x74\x3b\x2e\x6d\xed\xfd\x6c\x4c\xfa\x6d\x64\x6e\xb6\x47\xd3\x91\x6b\x84\x9e\x57\xbc\xec\xa1\x8e\x42\xc2\x7c\x77\xfa\x35\xab\x9e\x19\x8e\x19\xc3\x50\x52\xda\xb3\x4b\xf1\xa3\x17\x0e\x4f\xa5\x7a\xad\xcd\xcd\x73\x5e\x5f\x3f\xf1\xef\xe1\x65\xc7\x59\x9a\x3c\x88\x5e\x78\x4f\x61\x78\x2a\xf1\x20\x2c\x35\x30\xf4\xb7\xb9\xbf\xf6\x2c\x17\xf1\x62\x75\x0f\xa3\x40\xc8\xe8\xd6\x23\xce\xd6\x2f\x4b\xb0\xb9\xa5\x6d\xfb\xe8\x3d\x91\xf7\xe5\x54\xcf\xb7\x08\x2f\xdb\x7c\xb7\x9d\xe5\xbd\xd0\x0f\x83\xe7\x5d\xa9\xbc\xb5\x66\x86\x85\x2f\xdb\x05\xe7\xba\x53\xae\x59\xf5\xd4\x44\xdf\xa0\x9e\x8f\xf6\x2f\x31\x1b\x0c\x6c\xca\x99\x0c\xd5\x4c\xdf\x96\x1c\xaf\xea\x47\x9f\xc6\xdd\xac\xfb\xbe\x8e\x1f\x81\x1c\x56\xf8\x75\xd9\xa1\x96\xd6\x6f\x60\xbc\x2c\xb4\x4a\xbe\x82\x38\xf8\x16\xe4\xeb\x8c\x67\x98\xf4\x78\x8d\x86\xcf\xf6\x9c\x7a\x98\x9a\xb5\xc5\xff\xde\x53\x83\xed\x07\xd0\x6a\x1a\x31\x54\xbb\xda\x84\xb9\xce\x14\xef\x98\xb4\xe3\xda\x9f\x79\xc2\x12\xcd\x3d\xdc\xef\xff\x62\x8c\xf2\x27\x4f\xd8\x1e\xe6\x4c\x86\xb6\xdb\x26\xdf\xd0\x66\xc4\x1d\x84\xfc\x44\x37\x7b\xdf\x7a\x07\x0f\x0a\x2d\x2b\xfc\xb7\x2a\x58\x59\xbb\x32\xc4\xf1\xf5\xcc\xd4\xfa\x6a\x19\x94\x11\xfa\x8c\x47\x95\xdd\x5c\x86\x9b\x56\x1b\x46\x68\x66\x63\x95\x30\xc9\xd1\xa3\x69\x82\xa4\xeb\x52\x71\x90\xc2\xe8\x5e\xef\xbd\x5a\x8e\xd8\x78\xd9\xd0\xaa\xc1\xcb\x6f\x4e\x95\x3f\x10\x1d\xff\x91\xef\xb6\xfc\x31\xfa\xc9\xde\x22\x47\xf3\xd7\x5e\xba\x7a\xf5\xda\x91\x75\x7c\x5d\xb1\x3a\x9b\xb6\xc8\x09\xe7\xcc\x5e\xdd\xa0\xba\x57\xa7\x19\x7f\x25\x54\x9b\xb6\x1e\x66\xa5\x3f\x35\xba\x33\xad\xb3\xb6\x65\xd8\x3e\xa2\x98\xdf\x13\xec\xb8\x31\xd0\xf3\xca\x7d\x93\x28\xbf\xe6\xa6\x30\x1d\x9b\x2c\xdb\x68\x6f\x38\xc2\xa6\xe0\x39\x30\x5b\x61\xf0\xd2\xa6\xe3\xbf\x2b\x46\xa9\xe1\x16\xed\xb6\x2f\x25\x7f\xee\xd7\x53\xa5\xf4\x38\xbd\x42\x1d\xe8\xc9\xf0\x74\x90\xd8\xbc\x5f\x6d\x08\x01\xf8\xa4\xae\x85\xac\xc4\x29\x7a\xc1\xc8\xd2\xd9\xb4\x70\xc3\x67\xf4\x09\x9c\x5f\xe7\x48\x79\xbb\xdb\x98\xe0\x8f\x61\xfe\xe2\x19\xda\xab\x95\xc6\x83\x16\xe6\x09\x1f\xab\x97\x54\x7b\xfb\xfe\x9f\x91\xbb\x47\xe1\xc9\x32\x9b\xfd\x35\x61\x98\xd1\xd5\xbd\xe0\xeb\x19\xdd\x18\x17\xf3\xb7\xfc\x4d\xcb\xe3\xc5\x01\xdb\x5a\xed\xb6\x56\x1b\x9c\x8d\x41\x6b\xcf\xab\xc9\xc9\x54\xef\xc9\xef\x0c\xb8\x8d\x0f\x03\xeb\xf8\xe0\x62\x75\x36\xab\x3b\x74\x67\x30\x41\x91\x79\x44\x2c\x1c\x50\x78\x6b\x97\x60\xa9\x9d\x23\xb7\x1e\x36\x1f\xa8\x9e\x18\xb2\xdf\x3c\x5f\x89\x6d\x9f\x52\x2e\xc5\x16\xa7\x51\x7c\x4c\x3f\x5b\x2b\x90\x3d\x43\x26\x08\x09\x5b\xa1\x61\xc5\x83\xfd\x94\xed\x72\xa5\x09\xfe\xba\x55\x8f\x17\xf2\xc9\x83\xdb\x46\xbc\xab\x75\xef\x57\x71\xb1\xda\xc1\x61\xbc\xdb\x2b\x89\x1f\xae\x0e\x85\x35\x3d\xfc\xde\xf4\xa2\xee\xea\xf2\x81\x75\x7d\x30\x87\xd9\x75\xa0\x19\xf7\x63\x21\x2b\x71\x8d\xee\xd7\x83\x31\x64\x12\xbf\x6e\x50\x26\xf6\x0c\xa8\x4a\xeb\x7a\x30\x1b\xc0\x41\x76\x91\x33\x7f\xb8\x05\x79\x70\x25\xe5\x6b\xe7\x6a\x70\x53\x90\xbf\xd8\xca\x18\x8a\xe4\x30\x01\x80\x81\xbf\x1e\x65\x05\x79\xcd\x9a\x6f\x6b\xf5\xd0\xc0\x74\xb7\xd7\x9c\xc1\x4d\xa2\x5a\xc9\xd1\x4c\x62\xe8\xa1\x64\xd0\xd4\x71\x3a\x64\x7d\xe2\x4f\xaa\x7b\x7b\xe6\xdd\xe5\x14\x16\x90\xd7\xda\x64\x03\xe1\x26\x7d\xa1\xc3\x68\x32\xe6\xc3\x27\x34\x04\xd8\xd6\x2a\x5e\x4c\x4d\xda\x83\x3c\xb8\x82\x2c\x5e\x85\x5d\x77\x43\x32\x82\xb8\x93\x4d\x6b\xfb\x93\xce\x34\xb8\x60\xd2\x8e\xda\xf0\xfc\x11\xa6\xc8\x26\x12\x38\xb5\x77\xd9\xcb\x74\x75\x27\x4a\x64\xee\xe1\x5f\x17\xbb\x00\xd0\x7f\xc9\x92\xfd\x0d\xde\xd4\x90\x35\x7b\x1e\x22\x29\x1c\xf2\x1d\x0d\x01\xe7\x7a\x66\x5e\x76\xaf\x89\xdc\xe8\x70\x2b\x2c\x5e\x2a\x37\x69\x63\x00\x2c\x9b\x92\xbd\x30\xbe\x6a\xf6\x3e\x68\xad\x58\x78\xc8\xf5\x4b\xa4\x0e\x34\x33\x6e\x66\xd6\x53\xb7\xfd\x30\x0b\xc9\x8a\x02\x4e\xf0\x9b\x98\xcc\x72\xf6\x3e\xb1\x5a\x3a\xeb\x2a\x4e\xf6\xab\xc4\xb2\x83\xae\xcf\x23\x4a\x01\x7d\x36\x2b\xfc\x15\xf1\xfb\x07\x78\x80\xd3\xdf\xad\x9d\x87\x9c\x28\x56\x97\xd3\xbd\xcf\xea\x9c\x19\xf6\x72\xd0\x13\xc9\xa8\x42\xfc\x53\xa3\xfc\x2a\x69\x3a\x67\x27\xf5\xcb\x3b\x65\x28\xe0\x0e\xd7\x51\x48\x65\xd7\x55\xa0\x93\xdc\xe2\x78\xbf\x24\xba\x1a\xd2\x2a\x8c\xcf\x19\x99\x9b\xfd\xee\x72\x7e\xb7\xe3\xa9\xde\x4f\xab\x8a\xa0\x79\x10\x9b\xc1\x7f\xa1\x8a\xbd\x4f\xa7\x56\x22\x3c\xa4\x51\xcc\xbd\x1a\x0b\x05\x5d\x9d\x23\x58\x8e\xcd\x83\x96\x8d\xd5\x42\xc5\xe9\xd8\x44\xd9\x92\x31\xb4\x96\xba\x09\x94\x01\x30\x41\x85\x43\x7a\xd0\x1a\xb9\xb3\x25\xff\x9e\x20\xf4\x1f\x59\xcf\x83\xb8\x98\x7a\xa4\xed\x97\x9e\x43\xa7\xc6\x37\xf8\x25\x18\x23\x38\x36\xa5\x9d\xc1\x7f\xed\x2e\x32\xa7\xcf\xd7\x0a\xba\xf7\x48\xb5\xff\x0c\x0d\x0e\x52\x2f\x79\xc1\xae\x38\x87\x7d\x3b\xb6\x87\x07\x38\x86\xc1\xc4\x8f\x0b\x59\x89\x74\x4a\xdc\xa2\x35\xbb\x71\xe4\x04\xb6\x7c\x08\xf2\x0e\x3d\xbf\xba\x28\x32\x67\x25\x58\xf9\x2a\x08\xd2\x62\x81\xaf\xe1\x97\x91\xcc\x80\x6d\x32\x38\x83\xff\xc2\x7b\xf6\x3e\xb6\xda\x0b\xe1\x21\x68\x21\x25\x57\x24\xa3\xca\xfa\x0c\x39\xb1\x90\x42\x2e\x7c\x7e\xa0\x7a\xa2\xef\x2c\x2b\x0a\x4c\xc6\x55\x61\x76\x13\xb1\x51\x77\xba\x3c\x51\x1b\xfb\x59\x12\x0b\x2e\x14\x05\x20\x67\x34\x4e\x90\xd2\xa2\xf1\xc5\xb7\x16\x61\x63\x18\x66\x57\x54\xaf\x47\xcb\xca\xa6\xb0\x80\x57\x7f\xc3\x32\xf8\xeb\x9d\x90\x39\x37\x7c\x6d\xa1\xc2\x5d\xeb\x78\x47\xbd\xdd\x74\x2c\x3b\xf8\xda\x72\x98\xf5\xa2\x9e\x73\x2d\x60\xe0\x7d\xb4\xbf\x57\x05\x81\x01\xe8\x14\xcc\x0b\x87\x8c\xa1\x35\x64\x67\x3f\xc0\xb7\x76\x82\x87\x2e\xc5\x31\xc7\x09\xf6\xe4\x4d\xcf\xc4\x64\xdc\x44\xe6\x66\xe7\xf4\xdc\xe3\xb5\xfd\x32\x62\x62\xbf\x05\x61\x00\x91\x6b\x32\xbd\xb0\x20\xb2\xba\x9c\xd9\x0a\x9d\xba\x18\x61\x3e\xfc\x44\x43\x70\x9f\xba\x6d\xc5\xbb\xbe\x1c\x4e\xd6\x3c\x54\x98\x8e\xad\x20\xf4\x19\xdf\x48\xf9\xc2\x08\x4e\xfb\x17\xcc\x43\xae\xda\x44\xba\x55\x8d\x72\xb5\x5e\xcf\x34\x0d\xe1\x41\xa8\x18\xce\x90\xe1\x77\xee\x84\x49\xbb\x36\xad\xd2\x83\xc8\x8e\x4a\xdc\x30\xa1\xc1\x31\x62\x1a\x74\x87\xf4\xfa\xe7\xc9\x0f\x80\x5b\x5a\x3d\x67\x42\x31\xaf\xed\xad\x30\x38\x30\x86\x5b\x05\x86\x96\x7d\x43\x6b\x9c\x66\x35\x81\xee\x3d\xb2\x37\xbd\xb8\xca\xce\x10\xfd\x29\x45\x4e\xbb\xe7\x15\x89\x1e\x45\xc5\x88\xb8\xf3\xec\xa0\xb3\xe1\x2b\xf1\xba\x27\xf2\xbc\x78\x04\xbd\x9a\x36\x74\x76\xc3\xb1\xec\x40\xf0\x65\x75\xc1\xf3\x22\x0a\xf9\x57\x44\x47\xb1\x19\x5b\xd4\x81\x2a\x50\x51\x7d\xf4\x69\x1d\xdf\xca\xcb\x2f\xae\x8f\x4a\x14\xea\x85\x85\x8a\x2f\xc0\x28\x0a\x20\x46\xff\x7f\x11\xfc\xda\x79\xe8\xd4\x13\x5d\xd3\x76\x28\x00\x26\x9d\x9e\x0b\x1f\xc4\x62\xa3\x84\x38\x8b\xe0\x5b\x3b\x85\x79\xc3\x68\x66\xdc\xd4\x03\xd7\xd9\xe5\xe1\x9b\x57\xde\x98\x07\x4a\x52\xd7\xde\x08\xff\xb3\x7f\xcb\xa4\x17\xe6\x41\x41\x11\xcd\x6b\xe8\x59\x76\x21\x36\x7a\xa5\x33\x35\xff\x96\xe7\x88\x4d\x1a\xb8\xf2\x15\xad\xa5\x7e\xfb\x76\xac\x54\xd8\x1e\x5e\x1f\xc2\x00\x20\x7f\xc9\xf3\x90\xea\x1b\x91\x3a\x36\x53\xf4\x6a\x4e\xae\x18\x40\x33\xe3\xb2\x3f\x8f\x24\x16\x35\x2a\xbf\x8a\xd8\x83\x48\xfa\x7e\xe2\xbf\xfd\xaf\x6a\x53\x58\x80\x50\x8e\xc4\xc2\x2a\x59\xdd\x5a\xec\x16\x6a\x63\xdf\x89\x9c\x77\xc9\x66\x1e\x48\xfb\xd5\xbe\x36\x25\x07\xeb\xb3\x06\x93\x5d\xd8\xc4\xbc\x9a\x56\x4f\x73\xa8\x81\x66\x86\xc3\xcf\xeb\x78\xd7\xff\x89\x2e\xad\x5b\x60\xde\x16\xab\x03\xee\x54\x7a\x08\xf5\x49\x7f\xae\xa4\x90\x27\x94\x6b\x5a\xd0\xc7\x80\x00\x92\xa2\xb7\x9b\x86\x85\x4a\x46\x48\x85\x67\xf0\x2f\x25\x6f\x18\x51\x14\x00\x5b\x86\xec\x1a\xf7\xbf\xa7\x9a\x72\x88\x3d\xfc\x95\x77\x7f\xf6\xd8\x81\x4e\x5b\x53\x40\x68\xd9\x10\x3a\x3c\xa9\xf5\x8c\x1a\xe6\xcf\xfe\x24\x1a\xb3\x4f\x06\x9d\x51\xf5\x06\x24\xc4\xd6\xad\x99\x43\x55\x7a\x19\xd4\x6e\xe6\xe5\xbd\x25\xab\x5b\x4b\xf8\xa1\x96\xd6\x9d\x31\x11\x41\x15\x17\xe2\x2c\xe8\xd6\x85\xc8\x9d\xdb\xc3\x2b\xd4\xcd\xa9\xdf\x0c\x83\x83\xb2\xef\xda\xd7\x94\xa3\x8a\xd5\xad\x25\x1e\xd1\xd7\x0d\x71\x3a\xff\x66\x70\x72\xaa\x95\x0c\xe7\x49\x31\x9d\x5d\xde\x4e\xa7\xe7\x24\xd3\x31\x28\xd4\xbb\x1a\x0b\xbd\x1b\x71\x29\x3c\xe4\xba\xe8\x42\x20\x0d\x0e\xd8\xbf\xa6\x78\x57\xa4\x55\xf1\xd0\x33\x6c\x93\xf0\x42\x3c\x69\x24\xa3\xf4\xdf\x97\x99\x2a\xfd\x57\x30\x61\xae\xc8\xf3\x27\xc5\xc2\x89\xd7\x94\x7f\x25\x6f\xa0\x68\xbc\x80\x5d\xea\xe5\x1e\x9e\xc6\x57\x69\x28\x23\xe0\xba\x74\x41\x61\xda\xd5\x96\x8e\x43\xfa\x77\x18\x80\xc1\xa6\x51\x06\x3f\x33\x05\xd5\x8f\x53\x1b\xee\x58\xc7\x07\x12\x4b\xca\x7b\x18\xb2\xc2\xfe\x7d\x5b\x70\x32\x29\x7d\x0f\xf2\xc0\xb2\xad\x9d\xae\x76\x5b\x77\xf7\x0d\x36\xaa\x22\x0b\xce\xf7\x8b\xdf\xbc\x29\x92\x59\xa5\x7b\x86\xfc\xea\xd6\x6d\xdd\xa4\xba\x83\x96\xaf\xbd\xe5\xca\x50\xd0\x4e\x11\x5c\xc0\x67\xf0\xb7\x51\x54\xfb\x9f\xa8\xd5\xf0\xf7\xc2\xae\x60\x76\xa3\xb0\xec\x00\xf2\x7f\xcc\x30\xe6\x69\x77\x37\xdf\x39\x7a\xdf\xa7\xed\xd4\xcf\x43\x7a\xad\x23\x75\x38\x58\xa7\x54\xaf\x29\xd7\x58\xf6\x93\x29\x0a\x60\x29\xa1\x5a\x9c\x73\x0f\xff\x30\xa7\xe7\xde\x3f\xd3\xca\x8d\xfb\xb9\xc8\xea\x79\x27\x23\xca\xc2\xc2\xc4\xdd\x0b\xb0\x50\x80\x0d\x94\x0c\xff\xf1\x83\xff\xcb\xf7\xd5\xba\xc4\x74\xd1\x3a\x46\x70\xf6\x22\x71\x83\xa1\x17\x56\x44\x51\xed\x7f\xaa\x36\x0c\xeb\x85\x59\xea\xec\x56\x60\xd9\x01\x76\x67\x84\xff\xcb\xa7\xf2\xf6\x7a\xce\xd6\x80\xf5\x07\xd1\xfe\xe5\x22\xec\x80\x65\x68\x6a\xa7\xe5\x11\x0d\xee\xae\x81\xba\x56\x51\xaa\xa7\x7b\x94\x72\x51\x60\x95\xd7\xaa\x12\xd2\x98\xf5\x7b\xe1\x2e\xa7\x97\xbd\x73\xfa\x1b\xd4\xbb\x75\x15\x9e\x68\x79\x20\xc0\x65\x89\xd9\xcd\xc3\x46\x55\xf8\x52\x5f\x41\x96\x78\x75\xfd\xb5\x67\xd9\x30\x30\x3d\x89\x1b\xae\x0c\xc6\xf3\x15\x5f\xe3\x46\x42\xb3\x47\xbb\x59\x7c\x25\xb9\xba\x53\xbc\x2b\xb0\x79\xd9\xc7\x83\x87\x0e\xc8\xb5\xa6\xc3\x2e\xe9\x33\x65\x69\xe5\xb2\xff\x2d\x86\xc4\x5a\x77\xb8\x15\x2e\x92\xf9\x2d\xff\xee\x7b\xd1\x67\x02\x71\xfb\x6c\x2f\xec\x7e\x39\x7b\xbc\xe5\x6d\x1a\x70\x9f\xdb\x69\x99\x1e\x43\x26\x1d\x25\x6e\xc8\xd0\x2e\x80\x45\x6a\x3a\x0d\x71\xb1\xd6\x61\x8a\x48\x13\xbe\x5d\x2a\xa0\x45\xe3\x33\x08\xe1\x49\xfc\x73\x15\x99\x38\xcc\xcf\x8c\x7b\xf2\x21\xf9\x72\x40\x00\xa2\xf5\xf1\xc1\xdb\xbc\x6a\x5d\xf4\x27\x34\x14\xc7\x45\xab\x16\xb0\xbc\x38\x6c\x05\x17\x7d\x43\x53\x1e\xfb\xff\x48\x10\xc7\x74\xae\x3d\xc9\x97\x29\x07\xce\xde\xbc\x8e\xb7\x1f\x43\x26\xc1\xf4\x3e\x7c\x45\x9f\xc0\x3d\x6e\x57\xfc\x2e\xfe\x68\xcb\x8a\x35\xf3\x20\x49\xa8\xcb\xfd\xf5\xc5\x6a\x5f\x67\x0f\xd6\xf3\x7b\xf8\x2b\x39\xb8\x05\x01\x80\xf8\xa6\xad\xa4\x3c\xf9\xf6\x31\x93\x53\xa4\x77\xdc\x07\x45\x09\x65\xe2\x86\x21\x8d\x17\x68\x7d\xaa\x10\x78\xa7\xec\xf6\x26\x68\xc4\x51\xe2\xd1\xca\x77\x8a\x0c\x00\x5d\xb5\x63\xeb\x78\x2b\xdb\xc8\x4e\x46\x91\x70\xfc\xb6\x09\xe6\xa5\x6e\xea\x3d\x24\x73\xf3\xef\x76\x45\x47\xf9\x36\xe6\xb5\xfd\xc6\x27\x01\xf7\x06\xc6\x15\x83\xa6\xca\x07\x5f\xaa\x8a\x87\x75\x68\xe6\x2f\xf1\x0e\xb1\x00\xb9\xb6\x8b\x18\xfe\x2a\xf6\x78\x4e\x44\xab\xea\x9f\x7d\xa7\x10\x7f\xed\x59\x7e\x21\x7b\x97\x74\x16\x95\xe9\x0d\x47\xf8\xf6\x84\xea\x3d\x3b\xd5\x2f\xba\xe2\x5d\xb6\xa8\x98\xab\xca\xbd\x87\x02\x00\xf1\xb9\xe0\x1f\x63\x3e\x2f\x29\x16\xae\x3e\xb9\xd3\xb2\x5d\xa7\x28\xe1\x95\xb4\x11\x44\xbb\x00\x52\x73\x1d\xe0\x5e\xc6\x7f\x97\x4e\x12\x85\x0a\x3c\x7f\xaa\x6a\xeb\x47\x3a\xc2\x7f\xf0\x57\xc4\x27\x9d\x67\x07\x6e\x51\xda\xe6\x4d\x46\xbc\x78\x0d\x14\xef\x07\x98\x8e\x8d\x80\x7b\x2a\x16\x0e\xbe\x72\xad\x2e\x2d\x36\x09\xf4\x14\x19\x9d\x4a\xc7\x5c\xe2\x19\x3d\x11\xd1\x10\x4d\xb9\xfe\xb3\x2d\xef\xc5\x54\xc5\x57\x9d\x83\x21\xa4\x7a\x12\xfd\xbf\xdc\xe5\xa9\x79\xb0\x80\x50\xb8\x0d\xa4\xeb\x34\xeb\x14\x3c\x30\xf4\xdb\xd0\x98\x49\xad\xe9\xe9\xea\x73\x4c\x2c\x83\x5e\xaa\x69\xd8\x96\x71\x71\x6a\x36\xeb\xcd\x3b\x5b\x90\x91\xf5\xff\x90\x89\x01\xad\x62\x00\xd1\xc9\x75\x4d\x39\xa0\x1f\xad\x41\x31\x86\x46\xb6\xac\xe3\x5f\x7f\x50\x94\xb0\xc2\xec\xc6\xd1\xb9\x09\x35\xdd\x9e\x35\xb3\xce\x64\xea\xc1\x55\x5d\x62\x9a\xcc\xc0\x16\xdf\xa5\xb1\x26\x81\x3b\xb3\xc3\x37\xaf\x6f\x43\xea\xe8\xe5\x90\xea\xd5\x98\xd7\x7b\x23\xb2\xf3\x3c\xeb\xd4\xef\x83\x86\x3c\x2b\x5d\xf4\x38\x1a\x8a\xdb\x88\xf2\xdf\x74\x84\xe7\x9e\x34\x3a\x27\x7a\x8e\x97\x8e\x22\x3c\x15\xf6\xfd\x99\x81\xa1\xc6\xef\xd9\x89\x9a\x25\x58\x5c\xf1\x9f\x7d\xa7\x97\x79\xfe\xa4\x50\x4b\x1e\xb0\x5b\x59\x20\xf0\xe9\x75\xe6\x7b\xc2\x65\x81\x7f\x92\xb3\xc1\xa1\x65\x5f\xd0\x1a\x96\x26\x50\xed\xe6\x75\x7c\x64\xbb\xdb\x59\x15\xc3\x99\xe5\x9a\x42\x3a\x58\x23\x9a\x8d\xae\x29\xff\x7d\x8c\x8d\xba\x90\x0b\x27\x8c\x36\xe9\x51\xf5\x4f\xe3\xbe\x7c\xa6\x07\xfc\xd2\xed\x30\x38\xf8\xe3\x99\x5f\x83\x0b\x6d\x13\x0b\x17\x1c\xdc\xb6\x1e\xf1\xd7\xfb\xe9\x9c\xce\x02\xb4\x9e\xd0\xb1\xe7\x69\x38\x71\x7c\x76\xa7\xc5\x92\x26\x70\x43\x1b\x75\x0f\xf4\xc2\x92\x75\x77\x15\x69\xbc\x40\xda\xce\x70\xc4\x4f\x81\x23\xb6\x9c\xd0\x67\xbc\x04\x63\x54\x29\x39\xa8\x9b\x87\x6c\xdb\x44\x76\x32\xb1\x3a\xe3\x03\x42\x7f\xdb\x63\xae\x5a\xcf\x03\xdc\x54\xe7\x88\x9f\xf1\x4d\x35\x28\x50\xd8\xc2\x05\x10\xb4\x3f\x1a\x43\xcf\xd1\xf0\x44\xca\x8d\x48\x80\xcb\xa6\xe3\x5f\xdc\xa9\x11\xe1\x86\x04\x49\x91\xb3\x91\x6a\xc3\x2a\x19\xfc\xf7\xe2\x36\xe6\x29\x0a\xc0\xa9\xf0\xcf\x95\x7f\xdf\x50\xd7\x6e\x5a\x65\xf0\x5f\xa8\x66\x8f\x17\x45\xb4\x1e\x5b\xdf\x9f\x3c\x83\x39\xf2\x4c\x67\x02\xc7\x9e\xd3\x4d\xd3\xb2\xa3\xed\xb4\xc4\x16\xab\xcf\x9c\x8c\x28\x53\xb8\x7e\x71\x81\x87\x06\x99\x2a\xbe\x02\xc0\x19\x3b\x8c\x86\xaa\x39\x1c\x48\x5b\x57\x76\x34\x91\x0a\x69\x18\x71\x76\x72\xae\x9c\x46\xc5\xd3\xe3\x28\x30\xf3\x85\x15\x13\x76\x1b\x79\x3e\x36\x4d\x9e\x40\x96\x9d\x31\xf5\xd7\x9e\xbd\x30\xc4\xe5\x60\x5b\xfc\x1e\x34\x67\x55\x12\x12\x14\x69\x76\xb5\x49\x27\x66\x2d\x2f\xc6\x29\x6e\xde\xea\x12\xbf\x51\x70\x96\x18\xb0\x6e\xba\xb9\xff\xf7\x36\xbd\x01\x5e\x70\xe8\x06\xd5\xce\x43\xb6\x6f\x40\xba\x04\x59\x9d\x39\xb0\xfe\xe6\x87\x37\xfe\x0d\xe4\xe6\x32\xfa\x7f\xd7\xd3\x82\x54\xef\x35\xa9\xac\x0c\x9a\x99\x3a\xc2\x3f\x6a\x2a\x9b\x6e\x96\x84\xd1\xd9\x83\x5b\x5a\x6f\x50\xe8\x6f\x1e\x1a\x3c\xd0\xa2\x8a\x3d\xee\x81\x63\xa2\x1f\x29\x4f\xf9\x1d\x3b\x23\xf8\xd8\x5f\x67\xdf\xd7\x1d\x18\x6d\xd9\xf3\xf6\xa8\x06\x5b\x3c\x9a\x32\x4f\x29\x88\x4c\x3a\x31\x6b\xa8\xe7\xa8\x3a\xf3\xf8\x32\x88\x93\xdc\xd6\xdb\xbd\x4a\x83\x07\x7e\x0a\x2f\xeb\xfa\xa0\x28\x21\x2b\xac\x24\xe2\xfe\x14\x7b\x06\xb8\xd5\xe0\x4f\x50\x07\x13\x84\xbf\x6f\xdd\x7d\xa1\x34\xa1\xa8\xbe\x66\x58\x92\x06\x70\xbc\xc3\x22\x0b\x7e\x19\x12\x3f\xed\x10\xad\xcc\x7e\xfe\xe6\x0e\x22\x0b\xfe\x37\xcf\x9f\x10\x58\xb5\xe9\xe8\x4e\xf7\x31\x3c\x08\x70\x9f\x6d\xdd\x3d\x35\xc0\x7c\xe2\x66\xfd\xed\x94\xa0\xd0\xb6\x6c\x36\xd0\xf9\xcc\x3f\x30\xf4\xb7\x0b\x0d\x1e\xa8\x8d\xd2\xd7\xf9\xd7\x98\x07\x91\x58\x76\xa0\x63\xae\x67\x3b\x41\xef\x68\xc1\x37\x05\x57\x2a\x05\xe8\x2c\xb2\x76\x4d\xa9\x17\x56\x33\xa1\xc8\x80\x68\x65\xc6\xfa\x9b\x87\x5e\x5c\xf0\xa4\x28\x80\x66\x7d\x3d\xdb\x09\x75\x8f\x8b\x6e\xba\xaa\xc5\xe3\x87\xdf\x59\x33\x1b\xb2\x9d\x4b\x21\x40\x7a\xad\x30\xef\xb9\x92\xf2\xaf\x2a\x76\x53\xe6\xff\xc9\x7f\xc2\x04\xe9\xf4\xdb\xd1\x2e\x80\x38\x56\x29\x17\x76\x89\xa8\x82\x17\x85\xff\xd4\xa6\x54\xab\xf6\xdf\xc8\xe0\x2f\x7e\xc7\x6e\x8a\x40\xb4\x86\x63\xfd\xcd\x0d\x8d\x1b\x10\x84\xca\x1e\x46\x40\x7a\x1f\xa6\x9a\x86\x7d\x3c\xba\x50\x00\xfb\xf0\x3f\x59\x2e\xdd\xa0\xca\x79\x48\xd3\x7b\x76\x53\x21\x84\x1a\xd3\x18\x32\xa9\x5a\x6f\x97\x44\x37\xb7\x21\x59\xc6\xd7\x35\xad\xc1\xeb\x49\xc0\xab\x27\xf4\x21\x78\x6b\x5c\xf4\x9a\xf2\xdf\x68\x6c\x54\x4e\x36\xfc\xec\xc2\x4a\xe1\x23\x83\x7e\x6d\xf2\x03\xa0\xf2\x26\x51\xfb\x73\x7a\xe0\xc3\x06\x5e\x7a\x82\x0f\x62\x1a\x58\xe2\x0f\x54\x41\x67\x45\x66\x70\xe8\xef\x87\x34\xb8\x66\xdb\x7f\xd0\x87\xd7\x51\x0b\xf7\x7c\xdc\x95\x00\x9b\x83\x67\x75\xce\xd0\xb6\x98\x4d\x88\xd1\x41\xc7\x1e\x67\x5b\xe1\x7a\xe8\xc8\x3d\x80\x9b\xb2\x11\x7a\x26\x1a\x7d\xd6\x59\xcd\x2d\x4a\x8f\xc6\x00\x80\xb1\xb7\xad\x70\xfa\xf4\x4e\xcb\x03\x8a\x6a\x74\x77\x25\xbb\xf1\xad\x0c\xfe\xe2\xa4\x8d\x87\x98\xff\x68\x17\x00\x00\x2a\xad\x37\x31\xab\x6f\xd8\x7e\xe6\xc0\xcf\xae\xef\x4f\xf2\x0d\xc5\xc6\x32\x02\x00\x34\xff\x78\x65\xf0\xef\x7f\x42\x6b\xf4\x99\x40\xcd\x9a\xd7\xf1\x47\x89\x1b\xb2\x34\x5e\xba\xb8\xda\xfd\xe4\x8d\x1b\x34\x78\x16\xfc\x4d\x57\x12\xf1\x8c\x6d\x24\x00\x00\xa4\xde\x23\xe5\xf9\x07\x85\xc2\x6f\x40\x18\x22\xa4\xff\xbb\xa6\x3c\x8c\x5a\x90\x22\x3e\xb4\x76\x65\xa0\xff\x76\xeb\x65\xde\xd5\xe0\xd0\xb2\x76\x34\x74\x51\x2c\x5c\x9c\xba\xd3\x22\x4b\x8d\xaf\x03\x00\x74\x96\x4a\x2a\x29\x5b\x3b\x21\x19\xf7\x8c\xa1\x66\x9f\xd6\xf1\x99\x7a\xbb\x45\x58\x76\x00\x40\x56\x4b\xe3\xdc\x4e\x8b\x51\xb1\xfa\xa4\x0a\xa2\xd5\x6f\x37\x3c\xef\x75\xb1\x3a\xfd\x94\x93\xbe\xd5\x79\x61\x15\xec\x8f\xb9\xa6\x6f\xee\x26\x2e\xae\x14\xc6\x24\xf9\xc5\xe6\x0d\x90\xdf\xd3\x7f\x13\xfc\x26\xbe\xa0\xdf\x0b\xa3\xd8\x42\x5a\x9e\xcb\xa0\xf4\x49\x8d\x91\x5f\xea\x0d\x4d\x9d\xd2\x59\x00\x00\xdc\x6f\x94\x60\xf1\xd9\x6c\x6f\x10\x11\xd2\xed\xd7\x94\xa1\x42\x0d\x0e\xfd\x86\xff\x5c\x6f\x86\x6b\x12\x0f\xbf\xac\xe3\xb5\x8b\xf1\x93\xdf\xc4\xc2\xc5\xe7\x77\x5a\xa6\x89\x25\xc6\x07\xca\x62\x00\x00\x01\xc9\xc3\x9e\x75\xfc\x39\xb2\xfa\xe4\x6f\xb1\x70\x9e\xc9\x9d\x16\x03\xe2\x75\x8f\x74\x26\xba\xbe\xbc\xd2\xa0\xd0\x6f\xce\x48\x46\xa6\x5c\xf8\x9d\xf0\x79\xc8\x44\x5c\x5b\x98\x39\x00\x40\xa7\x2e\x53\x6f\xb7\x06\x0b\x65\x63\x8f\x90\xb6\xbd\x7e\x7e\xe1\x0e\x0d\x4e\x3f\x04\x35\x2a\xba\xa0\x94\xc1\xef\x9d\xa4\xaa\xe5\xbd\xac\xf1\xc9\xcf\xdf\xfc\x13\x29\x14\xd9\xee\x4e\xb9\x01\x00\xc0\x1d\x5c\x93\x5c\x50\xeb\x85\x5d\xb1\x81\xb4\x4c\x9a\x40\x65\x0b\xeb\x72\xfb\x2f\x2e\xa0\x30\xb2\xff\x73\x8b\x48\xd1\xfb\xd0\xbc\x8e\xcf\xa7\xa8\x4a\xcb\xf1\xf2\x7c\x15\xe8\x85\xa1\x2d\x9a\x72\xe3\x68\x74\x03\x0f\x8f\xb6\x56\xae\xfd\x22\x16\x35\x7e\xfc\x2b\xcb\x16\x23\x2a\x56\xf7\xcc\x5a\xaa\xf0\xb6\x5c\x4e\x16\xa7\x0b\xb3\x8f\xfa\x0f\xcd\x66\x6e\xef\x8f\x27\xcb\x13\x3b\x55\x9f\xe9\xe5\x7c\x82\x46\x65\xc3\x99\xa0\x55\x70\x4e\x4d\x06\x4e\x8d\x1c\xc6\xcb\xdc\x83\x50\xd5\x93\x35\x89\x4f\x4e\x9f\x4a\x04\x7c\xe7\xdf\x29\x52\xe5\xbe\x24\x2b\xef\xb6\xb2\xc9\xb2\xd5\x7f\x6e\x58\x2d\xf5\x9a\x98\x37\xdb\xa4\xe8\x27\x1d\x5d\xbb\x9d\x44\x79\x34\x31\x30\xa6\xdd\x77\x86\x29\x18\x7d\xac\x23\x01\xef\xad\x9f\x6f\x17\xca\xb6\x14\xf9\xdd\x44\x87\x28\x24\xde\xd3\xe0\x7f\xd2\xe1\x2c\x32\x27\xc5\x07\x4e\x28\x6f\x69\xb8\xb8\x1a\xbd\x12\x27\x84\xe9\x6f\x43\x0b\xcd\xfe\x19\xfa\x05\xfd\x9a\x86\xf7\xfe\x92\x6f\x47\x60\x32\xfc\xff\xd7\x15\x2e\xce\xfe\x29\xff\x05\xfd\x4a\xc0\x97\xf1\xb3\x1f\xbb\x18\x45\xf8\x77\x55\xfe\x5c\xa6\x39\x8d\xa5\xe9\xf2\x4f\x0e\x03\x7b\x4f\xa8\x1d\xe3\x3d\x8e\xb1\xf3\x18\x62\x9e\xc3\x1e\x5f\x99\x4b\x77\xfe\x33\xf6\xbe\x25\x05\x68\xf0\x2d\x6f\x64\xbb\x70\xb3\x4b\xae\xad\x10\x86\x38\xa8\x67\x35\xe0\x70\x69\xca\x1e\xaf\x34\x25\x98\xab\x74\xb9\x86\x70\x53\x74\xb2\xba\x4f\x8a\x28\x84\x59\x4c\x7f\xfd\x78\x0c\x89\x3f\xa0\x0a\x2c\xa5\x24\x7e\xfe\xaf\xf9\x62\xb3\xe7\xff\xae\xbf\x68\x6f\x76\x18\xff\x6f\x58\x99\xbd\x95\x4f\xb7\xd6\x8e\x61\x89\x7d\x1f\xf5\x41\x93\x28\x84\x71\x59\xbd\x3f\x99\x2f\xfe\xf2\x88\xc0\xde\xf7\x5b\x01\x1a\x2c\x31\xeb\xcb\x53\x26\x3a\xf9\xb9\x91\x28\x84\x49\x25\x09\x37\x37\xfe\x3f\x92\xbe\x3d\x2e\xc9\xf3\xfd\x1f\x44\x05\x53\x91\xd4\xa5\x29\x28\xea\x63\x41\x07\xec\x80\x85\xe6\x61\xe2\xf1\xb1\x48\x83\x96\x1d\xb0\xec\x63\x2e\xb1\x32\x45\x4d\xcb\x43\xf0\xf1\xb8\x34\xfd\xf1\x44\xd9\x48\x6d\xe8\xa3\x46\xa6\x1d\x66\x25\xb6\xda\xe3\x6c\xf9\xfb\xe8\x34\x45\x2c\xc7\x48\x69\x8e\x74\xac\x8c\xda\x3c\x94\x96\xdf\xd7\xc3\xfe\xe5\xba\xaf\xfb\xbe\xde\x87\xfb\xba\x2f\xfe\x7a\xe8\xd5\x4b\x65\xc4\xa1\x64\x16\x21\x77\x9d\xfe\x3d\x25\xe1\x90\x66\xc9\x63\x3b\x04\x80\xc3\xb7\x6d\x46\x7d\xf4\xc2\xd4\xcc\xb2\x88\x9e\x90\xd1\x0c\x7a\xf5\xdf\xa2\xe7\xd8\x3e\x53\x71\xcc\x2d\x7b\x30\x27\x77\x28\x6b\xbe\x40\xff\x55\x92\x76\x8a\xa4\x7d\x2b\x11\xf1\x10\x05\x02\x40\x17\x57\x7c\x13\x7f\xe7\xf9\xca\xc1\x29\x3f\xc2\xea\xb0\x5e\x3d\x0f\x79\x50\xbf\x0d\x85\x73\xba\x14\xe6\x07\xad\xa4\xc8\x95\x2f\xa9\x35\x54\x7a\x75\xa2\xc8\x2e\x22\x3b\x0a\x02\x14\xdf\x8f\x55\x0b\xfd\x82\xfc\xd9\x19\x47\xc7\xce\x7d\xb1\xb6\xde\x95\xd9\x23\xeb\xfc\x48\x33\xce\x4e\x11\x41\x08\xc8\xea\x5d\x4e\xaf\xb6\x0b\x8b\x4c\x4e\x3d\xcd\x66\x7d\xfb\xd9\x8d\xe5\xed\xcf\x86\x00\xb0\x36\xbd\x22\x31\x6d\xd3\x69\x36\x4b\x2e\xeb\x94\xd9\xe5\x49\x66\xf7\x2f\x03\x21\x80\xd3\xe6\xc0\x63\xe0\xc3\x23\x69\x25\xab\x8b\x1c\xd6\xe8\xef\xd8\x8c\xda\xed\x75\x36\xb1\xbc\xa1\x19\xe3\xe7\xcf\x4e\x0f\xf0\xa8\x49\xe3\xc4\x7f\xb2\x4a\xc3\x1a\x17\xa7\x4c\x5f\xbd\x55\x6c\x4e\xf6\xa9\x9b\x7b\x64\xb0\x7a\x45\x75\x44\x75\xc9\xb3\xce\xf9\x3a\xb3\x1c\x00\xa1\x57\x8f\xe3\xc4\xf9\x3c\xc6\xf6\x86\x50\xc7\xbe\xc8\x88\xf0\x5e\xfd\x1c\x32\x80\x24\x99\x68\x76\x51\x16\x23\x6b\xc9\x85\x66\x78\xb9\x25\x97\x91\x8d\xd9\x86\x5d\xfa\xc2\x74\x88\xe4\x43\x8c\x2e\x89\x5e\x9d\x5b\x1f\xaa\xb6\x25\xb2\x5f\xac\xd6\xdf\x21\x8c\xda\xce\xff\xbb\x5d\xc9\xb4\x67\xc2\x53\xe9\x76\x07\x4a\xfd\x74\x1a\xc9\x50\xc0\x65\x9c\x35\x3f\x68\x56\xe3\x64\xca\x93\xef\x23\xbc\xae\x13\x2a\xd7\xfa\x87\xbd\xf8\x9d\xaa\x76\xe1\x32\xb2\x71\x3e\xb8\x81\xca\x54\x09\x00\xaa\x6e\xd4\x5a\xbc\xae\x15\xee\x23\x53\xea\xa7\xd3\x49\x06\x6c\x23\xff\x12\xe6\x26\x66\x67\x95\x29\x56\x91\x6f\x99\xa3\xd7\x8d\x9f\x52\xb9\x90\x8b\xf6\xb7\x74\xe9\x67\x6e\xe2\x77\xfe\x9b\xd5\x9e\xef\x98\x73\x61\xce\xc6\xd0\x95\x63\x27\x77\xe3\xf2\xe2\xfe\x16\x4d\x88\x0b\xff\xd5\xcd\xbb\xb4\x99\x4f\x2c\xaf\x8c\x9d\xf3\x23\xf8\x26\x71\xe2\x29\x16\x8b\x89\x99\xa5\x00\x08\xb9\xa9\xb7\xf1\x18\x3d\x11\x91\xc9\x01\x2c\x82\xef\x7a\x4e\x3c\x65\x19\x79\xc5\x0b\x0f\x10\x82\x7d\xd7\xe1\xc7\x20\xe1\xbb\x2c\x77\xce\xb7\x85\xb1\xc3\xcf\xd4\x23\x0f\xc4\x0d\x0d\xa8\xa0\x99\x57\xbd\x91\x63\x3c\xc6\xd1\x88\xd2\xe4\x1f\x58\x04\x5f\x2f\x4e\x7c\x92\xce\x3c\xe1\x20\x0a\x57\x55\x74\x4c\x94\xcf\x65\x1c\xaa\x22\x0e\xcd\xa7\x93\x52\x9e\xc8\x3a\xfd\x31\xf3\x40\x41\xeb\x1e\x08\xa0\xf7\x7a\x26\xdc\x94\xf6\x65\xd7\x87\x32\xeb\xc8\x45\xb2\x8b\x4d\x6d\x07\x6d\xf3\x88\x7b\xb7\xa2\x3e\x15\xfc\xa4\xb5\x7c\x7d\x49\xf8\x21\x24\xb3\xec\x49\x75\x61\xec\xf7\xcf\xd4\x23\x7d\xa2\xcd\xa2\x99\x7a\xb4\xf2\x55\x8f\x4f\x8a\x6b\x79\x8c\xe0\x72\xe2\x50\x4e\x06\x29\x85\x26\xeb\xd4\x2c\x67\xb9\x8e\xd2\xd0\x44\xc5\x64\x1b\xee\x54\xb4\x92\xef\x40\xa9\x7f\x37\x49\x55\x0f\x32\xb3\xee\xfa\xa6\x05\xdd\x0a\x47\x6b\xe1\xc6\xc4\x87\x6f\xb3\x3c\xeb\x40\xa9\x2f\x30\x26\x52\x5d\x64\x5d\x5e\xd6\xbf\x61\x83\xbf\x41\x79\x32\xc8\xb7\x8b\x27\xfd\x2c\x7d\x77\x10\xd9\xb6\x5f\xf5\xea\x23\x74\xa7\x11\x0b\x93\xc2\x81\xc2\x2d\xc6\x9f\xa4\x7d\xfd\x43\x1e\x06\x27\xbc\xbc\x84\xa1\x7f\x8f\x4f\x88\xd1\xf1\xfe\x8d\xa5\x31\x6f\x9d\xec\x4d\x4a\xcf\x2c\xfb\xd8\x93\x4d\xf0\xe5\x72\xe2\x1f\xda\xcd\x93\x0e\x26\xf8\x80\x10\x33\x7e\xbb\xf8\x7e\x13\x7f\xd1\xfb\x41\xc4\x93\x90\x6b\x12\x57\xed\x57\x39\xcb\x6e\x51\x4d\xc8\x76\x68\xc1\xdc\x35\x39\x87\x33\xcb\x3e\xf6\x87\x5c\xf3\x1b\x52\x8f\x58\x8b\x6e\x62\xae\x84\xdd\x8f\x82\x80\x2c\x6d\x16\xe2\x46\xaf\xbe\x1a\x59\x7a\x6d\x89\x5c\x24\xdb\xcc\x89\x3f\x11\x9e\xbb\xfe\xe7\x89\xff\xf2\x00\x10\xea\x34\x6c\x42\xe9\xe2\x0c\x79\xc8\x6c\x0a\x76\x47\x64\xac\xd2\xbf\x0f\x6e\x7f\xce\x5d\xdc\x60\x82\x5d\x38\x60\x79\x2a\xcd\x26\x85\xe1\x47\xf0\x6d\xb6\x5c\xc2\xdf\xc7\xa5\x1d\x4c\x3b\x07\x80\xdc\xea\x79\xef\x5d\xc5\x46\xc9\xae\xe2\x64\x43\x4a\x50\x9a\x99\xf1\x19\x6a\x76\xf8\xcb\x02\x70\xb7\x9c\x5c\xb4\x6c\x04\xd5\xd0\x6e\xe2\xae\x23\x04\x08\xde\xa3\x2b\x33\x48\x6b\xf8\xbc\x38\x1f\xfc\x4e\x0b\xb7\x15\xa8\x23\x99\x91\x8b\xd0\x35\xff\xae\x90\x6b\x3b\x93\x0d\x29\xb9\x1a\x27\xc5\x56\x93\xe1\x5c\x36\xfe\x08\x5c\x1f\x30\x36\x6c\x32\x14\x49\xfb\xe6\x44\x47\x31\xe3\xe5\xa6\x9f\x3d\x7e\x04\xae\xef\x4c\x27\x5d\xdf\xcc\x65\x2c\x45\x2e\x58\xa8\x1c\x0a\xd1\xca\x4b\x4e\x58\xa4\x01\x05\xe0\x6e\xca\x84\x57\x83\x01\x6e\x6a\x1b\xc3\xd4\x98\xc3\x3a\x47\x10\x82\x7f\xed\x74\xc8\xc9\xef\xd5\x1f\x1b\xf2\x50\x19\xc8\x45\x86\x1b\x4d\x6d\x9f\xcf\xcd\xde\x3e\xd7\x13\x81\xb2\xd1\x3f\xa8\x47\xc6\x9b\xf8\x6d\xdf\x10\x25\x6e\x65\x55\x15\xd7\xbf\xe7\x32\x82\xcd\xea\xac\xf2\xd6\x9a\x68\xb4\xdc\x89\xbb\x97\x61\x73\xbd\x2f\xc0\x63\xf7\xa4\x2d\xe3\x76\xb0\xfd\x7c\xa9\x09\x1a\xbd\x03\xcf\x02\xf4\x42\x6e\x66\xd9\x3f\xb1\xe4\x22\x17\x57\x4e\xfc\x1b\x5c\x8d\x59\x80\xa7\x29\x69\x7d\x2a\x66\x16\x54\xf2\x57\x50\x3c\x39\xc5\x85\xb1\x89\x8d\x8a\x96\x66\xcc\x21\x6c\x9d\x23\x0a\xb5\x5d\x66\x2d\x8e\x6b\xe6\xa7\x7e\x43\x94\x34\xf5\x66\x13\x7c\xf7\x70\x19\x71\x66\x4f\xcd\x06\x4c\xfe\x70\xd9\x8b\x5d\xb4\xbe\x75\x25\x31\x76\xe2\x89\x03\xfb\x7c\x63\x53\xdb\x2b\xec\x5b\x3c\xb1\xfb\xd0\xf1\x28\x08\x66\x65\x63\x6e\x72\x94\x35\x4e\x14\xcf\xfe\xa2\xc2\xd8\xc4\x56\x45\x8b\x13\xee\x2a\x7e\x8b\xe9\xfe\x39\x4c\xae\x6e\x8f\x8b\x5e\xf4\xf7\x0f\x93\xd1\x63\xf6\x30\x9f\x71\x19\x93\xc3\x07\x39\xe9\xa7\x51\x3b\xca\x68\x57\x2d\xee\x65\xdb\xa4\x68\x4f\xb3\xaf\x1d\x4c\x36\xa4\xe4\xeb\x8e\xe8\xbe\x42\x8d\xa5\x78\x3e\x6d\x39\x76\x49\xf8\xe1\x48\x66\x19\xd3\x86\xc8\x9e\x89\xe6\xc5\xe1\x31\x3d\x38\x3b\x13\xf5\x0f\x33\x28\x6f\x2e\xda\x07\x57\x10\x25\x25\x3f\x87\x5c\x1b\x13\x18\x0c\xdf\x20\x4e\xc9\xee\xde\x17\x01\xd0\xa5\xa4\xb8\xdd\xbd\x4a\xe9\xeb\x1f\xe6\xb2\x6a\xdc\x63\xf7\x5b\x98\xdf\x66\x79\x0f\x5f\x69\x76\x09\x3f\x19\x05\xc1\xef\x9e\x61\x4e\xe2\x66\xd3\x6c\xae\x57\x05\x78\xec\xbe\xe9\x9b\x75\x17\x97\xb6\xe6\x56\x38\x6a\x12\x97\xe0\x60\xec\xac\xab\xb6\x70\xdd\x0c\xb4\xba\xc8\x70\x57\xda\x97\x2d\x6a\xc6\x1d\xb5\x68\x46\x93\x6e\x93\xe7\x09\xb7\x5a\x13\x63\xf3\x27\xad\xe4\xab\x22\x78\x71\x0b\xb8\xd5\x98\xaa\x32\xb4\x90\xda\x2c\x9c\xb1\xb3\xcb\xe7\x62\xe3\x58\x06\x29\xa5\x9e\x99\x35\x33\xd9\xee\xf4\x6b\xb0\x49\x9c\xac\x81\x95\xc8\x78\x23\x7f\xba\x8c\x28\x79\x75\xae\x30\xd6\xa1\x59\xd1\x92\x25\xee\x16\xcf\xe9\x12\x87\x21\xc0\x6a\xda\x9c\x18\xad\xcc\x0b\xf2\x0f\x93\x1d\x23\xb2\x39\x37\x9a\xda\xea\xec\x6a\x2c\x8f\xaf\x44\x35\xf8\x89\xbf\x63\xa1\x6c\x2a\x6b\xc8\x83\x6b\x1e\x13\xc9\xbc\xcd\x65\x38\x0d\x17\xa4\xbd\xda\x8e\x92\x22\x18\x58\x8f\x1d\xb3\xfe\x61\x70\xe3\x35\xf0\x95\x95\xdc\x9c\x99\x35\x73\x46\x97\x88\x58\x9a\x42\x7f\x14\x84\xe4\xd6\x3e\xae\x6a\x08\x85\x93\xeb\x48\xd1\x5f\xf6\xea\x33\x90\x43\x66\xd5\xa8\x89\x60\x89\xff\xf2\x9c\x92\xc4\xd8\x94\xd3\x6c\x5a\xeb\x7f\x8c\x5d\xdf\xda\x0d\x06\xb1\xef\xa4\xa6\x55\x02\xa0\x4b\xdd\x15\xd1\xd6\x26\xfe\x40\x15\x51\xd2\xf9\x38\x84\x16\x28\x6a\x6a\xab\x23\xd6\xd8\x04\x6c\x46\x11\xf4\x6b\x94\x08\x96\x5e\x7d\xa5\x21\x14\x6e\x4b\x27\x45\x1f\x1b\x52\x8f\xe4\xe9\xde\x20\xcb\x91\x8f\x5d\x7e\x10\x20\xf8\x98\x6a\x31\x26\x11\xfa\xf9\xfa\x87\x19\xd6\xe0\xe5\xff\x90\x64\x9d\x67\x02\x8c\x56\x09\x93\xa8\x03\x99\x49\xcd\x43\x95\x5d\x07\xea\x43\x61\x46\x06\x29\x9a\xc7\x9c\xb7\xff\xf3\x36\xd2\x64\xaa\xb3\xb5\xc0\x82\x7c\x59\xf8\xe1\xeb\xcc\x32\x26\x71\xb1\xf7\x1a\x33\xbc\xd0\x47\x92\x6a\x51\xb3\x1c\x85\xfe\xec\x96\x23\x6b\xd9\xe8\x93\x8d\x34\x4e\xed\xea\x22\x95\x0d\x33\x6b\xc6\x5e\xf3\x74\xcf\x49\x53\xac\xc3\x31\x27\xa3\x57\xff\x7e\x8a\x24\xd0\xe6\xb0\x69\xfd\x5f\xf6\xea\x03\x74\x0a\xa4\x07\x7b\xb6\xc5\x13\xe4\x56\x84\x23\x5d\xc8\x6c\x65\x88\xe0\xeb\x00\x0f\xe9\xd7\x0a\x45\xcb\x1b\xc1\xcd\x6b\xa3\x6b\x3a\xc3\x21\xd8\xea\xbd\x2f\xb5\x99\x5f\xe0\x40\xf1\x3c\xbf\x19\x2f\x67\x9a\x73\xe2\xd7\x63\x3e\x5b\xe5\xd8\xdd\xa2\xb2\x22\x21\x38\xe8\xc1\x72\x16\x4b\xff\xfe\xed\x90\x07\xd7\x9d\x45\x68\xf4\x48\x31\x18\x14\xed\xcd\xc5\xbf\x85\xdf\x8f\x82\xd4\x9b\xfb\xc4\x67\x71\x63\x57\x84\x1f\xf2\x33\x2b\xd4\x4e\x44\xb6\xe0\xff\xcb\x3a\xf7\xe3\x59\x04\x96\x7d\x4e\x18\xca\x5e\xbe\x71\xb3\xa6\xea\x49\x5e\xb0\x7f\x98\xc1\x15\x2f\x67\x7a\x72\xe2\x4f\x58\xd5\x60\x5e\x53\x5e\x78\x82\xaa\xcb\x29\x22\x2f\x51\x15\xcc\xbf\x14\xd6\x13\x95\xff\x07\x55\x1a\x71\x43\xd1\x52\x2b\x9a\x10\xb5\xa2\xef\x8e\x8b\x97\x93\x19\xbe\x91\xdf\x56\x49\x94\x7c\xfc\x25\x84\xd6\x2f\x6e\x6a\x7b\x85\x3b\x89\x0d\x22\x1c\x5f\x51\xe3\x05\x72\xab\x3f\xd9\xe7\xc4\xf5\xea\xb5\x53\x24\x81\x3d\x8b\xd0\xe8\xa7\x56\x8f\xac\x42\xe4\xed\x6f\x9d\xdb\x5c\x4d\x61\x6d\xc8\x42\xf9\xb0\xa6\x27\xb4\x51\x39\x41\x95\x9a\x31\xb3\x66\x8e\x68\x7a\xa2\xb2\xd1\xee\x43\x1f\xdd\xa4\xb9\x59\xea\x26\x13\x2a\x7d\xfd\x23\x64\x4c\x22\x9b\x1e\xcb\x8b\xf3\xb1\xac\xb4\xf8\x8c\xde\x7d\x18\x33\x8e\x19\x93\x08\x95\x9b\xfc\xc3\x64\xbb\x89\x6c\xfa\x5e\x5e\xdc\x5f\x43\x41\xec\x33\xb4\x5b\xe9\x28\x9c\x8c\x97\x4e\xc8\x36\x1e\x63\x32\xb2\x34\xea\xc2\x40\x08\x2d\x2b\x8c\x17\x57\x05\xe7\x67\xff\xde\x8f\x2c\xea\xc8\x20\x14\xf1\x72\x8b\x2e\x4d\xf7\x58\xda\xa7\x9a\x72\x06\x89\x6c\x45\x86\xac\x53\x53\x32\xfb\xe9\x27\x8a\x09\x11\xd4\x88\x80\xc8\x61\x7a\xf5\x6f\xf5\x89\x40\xeb\x1f\x54\xa9\xff\x75\x45\x4b\xb5\xd9\xd2\xb2\x00\x74\xe4\x82\xf7\xed\x8d\x5a\xa8\xd3\xf9\xd4\x87\x02\xad\xff\x0b\xa1\x65\xed\xe5\xc5\x59\x8b\x42\x45\x73\x38\x57\xf3\xc9\x28\x88\x49\x89\x53\x3d\x5a\x9d\x13\x92\x59\x06\xdf\xcd\x20\x45\x27\x7e\xa7\x68\x89\xc4\x46\x62\x16\x26\x3e\x15\x43\x70\xea\x83\x8b\xb3\xa1\x82\xab\xc6\xc0\x10\xc5\x02\xb9\x48\xe5\x2c\x30\x18\xac\x90\x60\xdc\xcd\x2e\xbb\xa7\x51\x50\xa7\x9e\xf1\x9d\x65\x50\x8d\x50\x19\xe8\x1f\xa1\x52\xb3\x08\x8d\x1b\xd5\xea\x91\x0b\xc9\x67\x17\x3e\x46\x27\xd4\xea\xc8\xa0\xea\xc8\x01\x9b\x1a\x02\xb9\x56\xf8\x21\x3e\xb3\x02\xfe\x33\x9d\x14\x9d\x78\x03\x6d\x77\xa5\xd8\x05\xcc\xdf\xff\x39\x06\x80\x0e\x4d\xd8\x20\x2c\xf9\xa2\xf0\xc3\x89\xcc\x0a\xf8\xdb\x74\x52\x74\xe0\xa0\x7a\x64\x38\xf9\x6d\xd6\x19\x41\x66\x39\xa0\x98\x9b\xb6\xdc\x69\x59\xb9\x43\xa9\x75\xa6\x78\x09\x4e\x91\x8b\xb8\x55\xcc\xac\x19\x1b\x4d\xdf\x9b\x39\xf4\xf6\xcf\x0c\xd8\xeb\x86\xdb\x43\x8d\x25\x53\xce\x60\xf7\x4b\xaa\xf4\xcc\x35\x45\xcb\x09\x41\xe9\x4b\xc6\xd0\x7a\x08\xbe\x7d\xdf\x71\x7e\x9d\x51\x2e\xed\xcb\xea\x5a\x0f\x95\xfc\x12\x42\x9b\xd9\xcb\x8b\x7b\x2a\xa7\x94\xf8\x9c\x4b\x95\x00\xe7\x6b\x93\x10\x01\xb2\x9c\x5e\x7d\x28\xb2\x27\xca\xc5\x16\x2f\x67\x62\x65\x9d\x1a\xf1\x29\xe7\x20\x1f\x56\x38\xa4\xce\xef\x13\xf9\x60\xdc\x77\xa0\x2f\xb8\x97\xa0\x9d\x5c\xa4\x32\x17\x18\x52\x8e\x6a\x0e\x77\xc4\xa3\x55\x65\x5c\xc2\x1d\x35\x2b\x6d\xe6\xb7\x9d\xab\x94\x30\xb7\xa2\xd1\x14\x43\x4a\xb6\x26\xd7\xe6\xfe\xf9\x54\x09\x50\x7c\x00\x9b\xb7\x92\xb5\x4e\x2f\x4c\xca\xac\x80\x95\x7a\xaa\x74\x15\x7a\xb0\xc5\x98\xd5\xeb\x62\x27\xed\x76\x15\xac\x74\x65\x51\x58\xcf\x3c\x68\x1c\x06\x5e\x0e\xc8\x3a\xcf\x78\xa6\x11\x8c\x96\x09\x9f\x46\x5d\x40\x55\xd9\x0b\xb3\x1a\xf3\xbc\x00\xbd\x90\x97\x59\x01\xef\x25\xb2\xc1\x39\x81\x21\x65\xb3\xee\x4b\x2a\xee\x0a\xda\x3d\x4b\xfe\xaa\x46\xd2\x91\x49\x2e\xa3\xbc\x21\x11\xc8\x2a\x2c\x8c\x55\xb9\xc8\x3a\xf7\x63\x5e\xe3\x7f\xc0\x8d\xfa\xb3\x22\x21\xe6\x36\x27\x6c\x0f\x66\xb2\x91\xbf\x58\x7a\x15\x5e\x48\x27\x45\x9f\x89\xe5\xc4\xbf\x89\x5e\xa8\x7b\x39\x80\x32\x42\x3f\xb0\xac\xc6\x82\x7c\x41\xf8\x61\x57\x66\x05\x3c\x2d\x24\x45\xcb\xa0\xa6\xb6\x7b\x72\x4a\xc9\x4d\xb3\x15\xa8\x0d\xdc\x46\x6b\x91\x66\x91\x03\x97\xb1\x35\xac\x27\xca\x10\x84\x97\xc3\x02\x81\xc1\x30\x84\x74\x21\x07\x44\x9c\xc2\x0c\x00\x6c\xfd\x4b\x34\x21\xbe\xc0\x63\x94\xd7\x27\x02\xe7\xed\xf0\x72\x78\xa5\xc0\x60\x78\x89\x7c\x6e\x3f\xb4\x3a\x9f\x9d\x56\x09\x70\xae\xf7\x25\x8f\xdb\x05\x6c\xd3\xdf\x59\xe7\x1f\xa1\x9a\x4f\x27\x45\xa3\xf3\xd4\x33\xec\x6c\x53\x7e\xcd\x3f\x7e\x5d\x7e\x10\xd3\xea\x12\x6e\x72\xf0\x91\x7b\x0e\x98\x59\x01\xbf\x7b\x45\x95\x32\x99\x9c\xf8\x40\x5b\x16\x26\xc7\x36\x68\xe7\x1a\xb0\xfb\x14\xce\xb8\x52\xb7\x99\x5e\xfd\x57\x43\x22\x30\x83\xe2\x1b\xf4\xcd\x9a\xd9\xa0\x3b\x99\xdc\xf3\xb2\x12\xf9\x61\xd4\x13\x74\x39\xb0\x5d\x94\x21\xbe\x20\x3e\x09\xf3\x2f\xe1\xe7\xa2\x0c\x2b\xf1\x72\x58\x92\x62\x30\xbc\x6b\x7f\xeb\x32\x6d\x17\xb0\x8a\x15\x09\x3d\xf9\xd9\x47\x1c\x33\x7c\xd0\xf3\x2c\xca\xe1\x67\x14\xa5\x43\x61\xb6\x6d\xb6\xc5\x98\xf9\x6b\xab\x1b\x4e\x07\x00\xb0\x76\x18\x73\xa8\xe9\x13\x77\x2a\x7c\x68\x23\xb4\x0a\x3d\xa4\xe6\x98\xc1\xf0\x54\xf4\x7c\x28\x88\xfb\xf1\x0f\x1d\x19\x3c\x37\xcb\xd3\x44\xb2\x63\x62\x94\xda\xe5\x14\x2f\xc1\x1d\x16\xc1\xbb\x38\xc5\x60\xf0\x6b\xef\x36\xea\x91\xee\xc2\x0c\x40\xd0\xb6\xce\xec\x51\x54\xae\xcb\x7c\xe1\x94\x33\x78\xa1\x2f\x84\xa6\x70\x90\x75\x6a\x30\x39\xde\x6f\x58\xda\x2d\xac\x48\x28\x42\xbf\xd0\xde\x2c\x3e\xda\xc4\x9f\x3e\x57\x29\x01\xf0\x72\x78\x40\x60\x48\x39\xa6\x39\x3c\xbf\x3f\xe1\x7b\x1d\x19\x94\xb5\x1e\x10\x0d\x0b\x62\x70\x67\xdd\x28\x5e\x60\x8b\x90\x14\x8d\x0e\x1c\x2b\x30\x0f\x70\x0b\x66\xb9\x58\xd7\xc7\x2b\x40\x95\xf4\x05\x31\xcf\x82\xe5\x30\x7f\xaa\x37\x49\x90\x56\x05\x04\x52\xf1\x72\xf8\xf6\x86\x8e\xdf\xd2\xe2\xf6\x54\x76\xdb\x26\x96\x03\x02\xdb\x6c\xb3\x43\x16\x8f\xcc\xf9\x97\x85\xfb\xec\xb5\x5e\xa0\xdd\xff\x42\x68\x82\xd7\x36\x4f\x5e\x32\x6e\x90\x4b\x5d\x7f\x5e\x01\xca\x12\xca\x45\x19\xc9\x31\x66\x3f\x4a\x84\xca\xd5\x1d\x91\x50\xd3\xcf\x21\x34\xc1\x0d\x5b\xb7\xb5\x0f\xb3\xc9\xd3\xe7\x27\x62\x55\x53\x2f\x2c\x6a\xb6\xe7\xda\x77\x6c\xd0\xab\xcc\xe7\xa2\x54\x15\x7e\x04\xef\x99\x27\x09\xe4\xe9\x5f\x7a\xd3\x3b\xd2\x8f\x4b\x60\xb7\x7d\x36\x79\xb5\xb3\x80\x71\x51\xda\xe7\x5e\x98\x0b\x08\x68\xe4\x22\xe8\x8c\x42\xd1\x32\xd3\xb1\xc4\xd2\x02\xf7\xa2\x54\xce\x29\xa2\xe2\xf6\xd5\xe2\xc9\x33\x9c\x22\x38\x08\x05\xf1\xb0\x8b\xa5\xfd\xe6\xe2\x44\xda\xf0\xa8\x27\x48\xb9\xe7\xdc\xf1\xff\x4e\x99\xd7\x5d\x10\xee\x73\xd4\x7a\x81\x5e\x7a\xaa\x94\xb9\xcb\x72\xc2\x18\x8e\xb8\xb5\x1f\x5a\x9f\xcf\x3d\x2e\x81\x89\x1d\xe7\x66\x01\xa3\x99\xce\x73\xdc\x4a\xca\x04\xc9\x45\xd0\xaa\xfd\xbc\xb8\xaa\x86\x4f\xb4\xfe\x36\xa4\x72\x7e\x97\x8b\xc0\x5e\x6b\x91\x77\xe5\x14\x86\xb1\x43\xc9\x77\xd5\x7a\x81\x87\xc9\x45\x10\x73\x50\x3d\x92\x97\x70\x40\x93\xde\x61\x6d\x7c\x8e\x2c\x0e\xd2\xc0\x6e\xa1\xf7\xda\x18\xac\xcf\xec\x19\x02\x98\xe2\x47\xf0\x16\xac\x97\x75\x6a\x8a\x66\x5f\x74\xe7\xc6\x90\xee\x97\xad\x87\x98\xb6\xe5\xa2\x93\x1b\x9d\xc5\xf4\xea\xbf\x0a\x73\x01\xc5\x05\x74\x8f\x70\x4e\x7c\xe0\xb7\xa7\x9c\xa7\x97\xfd\x80\xd9\x1b\x7c\x2f\x4a\x95\xd2\x96\xa0\xa7\xeb\xbc\xe9\xd5\xde\x5d\x81\x90\xfa\x34\x91\x0d\xca\xc4\x4d\x6d\x6e\x96\x01\xd5\x17\xab\xaa\x83\x6c\x2f\x3b\xb9\x78\x73\xea\xc6\xb1\x4e\xc3\x44\xc4\x9a\xcb\xf0\xee\x88\x84\x9e\x54\x16\xc6\x42\x25\xdf\x29\x5a\xfa\x05\xa5\x2f\xad\xc5\x47\x87\x0b\x1e\xaa\xc5\x34\xdb\xe7\x5f\x21\xde\x48\xb6\x20\x06\x73\x93\x38\x2d\x81\x6f\x4f\x52\xa5\xf0\xf2\x64\x43\x0a\x4f\x63\xa7\x0e\xc8\x35\x7e\xbf\xfe\x56\x48\xb2\x94\x79\x70\x1a\x5b\xf0\x38\x61\x11\x3b\xce\x51\x6a\xed\xaf\x00\xe0\xa7\x09\xaa\x14\xf6\x1b\x54\x8f\xf8\x23\xbc\x7d\x7e\xa4\xc0\x70\xe9\xf4\xdb\x53\xba\x85\xf6\x89\xb7\xf6\x3a\xfc\x18\x9e\x06\x36\xa0\xfb\x50\x0b\x79\x8f\xdf\xec\xf5\x23\x5d\x2d\x6e\x2e\x93\x91\x9f\xdf\xe9\xfd\xd3\xdd\xf8\xb7\xb4\x7c\x89\x26\x81\xfd\x5e\x51\xa5\x70\xa5\xd1\x71\x57\xe0\xbd\xb2\x59\xeb\xef\x82\x8f\xe8\x17\xce\x6e\x7d\xb2\x0a\x84\x90\x10\x1a\x58\x7b\x4f\x43\xff\x7d\x58\x80\x9f\x98\x48\x07\xae\x5f\xd9\x83\x59\xb2\x5e\xcc\xbc\x7b\xf5\x58\xe0\xa7\x0b\x70\xaa\x90\x14\xad\xba\x2c\x40\xe7\x3d\x3a\xf2\xac\x1d\xf7\x6e\x2c\xf8\x7e\xd9\x6b\xd5\x63\xa5\xf5\xfc\xca\x39\xf7\x82\x38\x98\x5f\xe0\xbe\xdf\x1b\x94\xad\xc0\xcb\x81\x99\x30\x5e\x9c\xeb\x6d\x21\xad\xcd\x7f\x85\xfb\x17\xbf\x36\x1e\xec\xa8\xf3\x8d\xf9\x54\x70\x51\xb8\xcf\x0d\x5d\xe1\x8b\xae\xe0\xf3\xe2\xae\xdc\x7e\x25\xf8\xfd\x19\xd2\x24\x89\x37\xd4\x24\xb5\x77\xbf\x7d\x5e\x78\x75\x6d\x72\xe9\xb8\x9e\x5e\xbd\xcd\xb3\x1b\x00\x1b\x50\xa4\x56\x23\xea\x91\x06\x41\xcf\xcb\x3d\xc8\x25\x24\x11\x7f\x36\xd5\xea\x78\xe5\x5b\xfa\xec\xd0\x89\x1b\xe4\xbc\xb9\xcf\xfc\x6d\xf3\x7f\x7f\x94\xf6\xa9\x90\x2d\x20\x17\x83\x97\x03\x02\x5b\x74\x52\x70\xeb\x96\x85\xa6\x8f\x5c\x9d\xe9\x36\xbb\xbb\x65\x6e\xb0\x40\x9d\x34\x22\xcf\x1e\xaf\x7a\x3b\x07\x42\x7b\x26\xa9\x52\xa0\x3f\x8a\x17\x57\x75\xa4\x5f\xd2\x61\xc8\xc9\x73\xac\xdb\x44\xec\xe3\xea\xf6\xe8\xb2\x91\xfe\x96\x4f\xda\x85\xcb\x93\x77\xbf\x7c\xf7\x30\x08\x54\x65\xb2\x08\xde\xa0\xd7\x46\x56\xd2\x22\x2f\xc1\x41\x33\xf7\x85\xfb\xeb\xa7\x5f\x2d\x3d\xda\xb8\x21\x98\x7a\x9a\xf1\x02\xa7\x65\x6f\x9b\x72\x4b\xfe\xa3\xf5\x73\xc6\x83\xe7\x5b\xa2\xa0\x88\xae\x10\x1a\x68\x90\xa2\xc3\xb5\xeb\x7b\x5d\x43\xba\x57\xc2\xc3\xae\xa7\x9d\xa1\x8b\x0b\x9d\xed\x89\xad\x2b\x17\xd7\x1d\xec\x1b\x3f\xfa\xfe\xea\x8b\x81\x04\x5d\x23\x7f\x9a\x3c\x76\x36\x11\x02\xfa\xb5\x4b\xb8\xa1\x02\xf9\xa1\x13\x87\xc9\x77\x31\x18\x0c\x06\x0c\xdf\x19\xd6\xc6\x4e\xf8\xef\xff\x05\x00\x00\xff\xff\xe2\x86\x9c\x07\x0f\x97\x00\x00") - -func resourcesAppIconPngBytes() ([]byte, error) { - return bindataRead( - _resourcesAppIconPng, - "resources/app/icon.png", - ) -} - -func resourcesAppIconPng() (*asset, error) { - bytes, err := resourcesAppIconPngBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/icon.png", size: 38671, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x5b\x6f\x23\x39\x76\xf0\xfb\xfe\x0a\x2e\xbf\x0f\x6b\xb9\xdb\x96\xdd\xd3\x3d\xb3\xb3\x6e\xab\x82\xb6\xdd\x6e\x7b\x7c\x69\x45\x92\xb7\xd7\x3d\xe8\x07\xaa\x8a\xb6\x38\x2e\x15\x35\x45\xca\x96\x77\xe0\x97\x7d\xcf\x53\xb0\x2f\x8b\x05\xb2\x40\x10\x20\x09\xf2\x92\xb7\x24\x40\x10\x60\x91\xfc\x8f\x60\x7f\x41\x7e\x42\x40\xb2\xaa\xc4\x5b\xdd\x6c\xf7\xf6\xcc\x20\x7a\xb0\xa5\x22\xcf\x85\xe7\x1c\x1e\x1e\x1e\x5e\x6a\xfb\xa7\x7b\x6f\x77\x47\xe7\xfd\xd7\x60\xc2\xa7\x71\xf0\x93\x6d\xf1\x0f\xc4\x28\xb9\xec\x41\x9c\x40\xf1\x00\xa3\x28\xf8\x09\x00\x00\x6c\x4f\x31\x47\x20\x9c\xa0\x94\x61\xde\x83\x67\xa3\xfd\xf5\x2f\x61\x56\x14\x93\xe4\x0a\xa4\x38\xee\x41\xc6\x6f\x63\xcc\x26\x18\x73\x08\x26\x29\xbe\x10\x4f\x10\x27\xe1\x46\xc8\xd8\xc6\x18\x31\xdc\x0d\x19\x83\x1b\xc1\x4f\xb6\x37\x14\xea\xed\x31\x8d\x6e\x33\x34\x11\xb9\x06\x61\x8c\x18\xeb\xc1\x8b\x18\x2f\x00\x0a\x39\xa1\xc9\x0e\x4a\x33\x3a\x76\x25\x8e\xc6\x40\x54\xd4\x8a\x65\x15\x32\xbd\xcc\xab\x90\x90\x26\x10\xb0\x34\x54\x5f\xbb\xb3\xe4\xd2\xae\x2d\x10\x92\xa8\x07\xf1\x22\x9c\xa0\xe4\x12\x0f\x10\xc7\x50\x23\x31\xc2\x0b\x0e\x83\xed\x8d\x88\x5c\x6b\x6c\x58\x3f\xef\xcd\xd5\x38\xa6\xe1\x55\x15\x5b\x13\x4c\x2e\x27\xfc\x21\x0c\x85\x34\xe1\x29\x8d\x87\x33\x14\x62\x17\xce\xc3\x39\xc8\x20\x22\x72\x0d\x01\x4d\xc2\x98\x84\x57\x3d\xc8\x26\xf4\x66\x94\xa2\x84\x29\xb5\xb0\xce\x6a\x4d\x0b\x73\x34\x87\xcb\xd6\xc6\x84\x71\xab\xb1\x4d\xf8\x99\x92\x84\x4c\xc9\xaf\xb1\xc5\xcd\x10\x73\x4e\x92\xcb\x76\x9c\x18\x8d\x93\x4c\xb1\x0c\x4d\x0d\x63\x3f\x5d\x5f\x6f\xc6\xa5\x5f\x7c\x79\xe9\x88\x8e\x52\x74\xdb\x59\x7d\xd9\x5e\x7a\x39\x8a\x6a\x46\xd7\xd7\xb3\xee\xb4\x7c\xac\xb3\xfb\x0e\xc5\x31\xe6\x25\x3d\x6a\xc8\x11\x67\x3e\x4b\xcc\xca\xf7\xe7\x49\xc4\x60\x20\xff\x59\x64\x0d\xa3\x1d\xf3\x70\x7d\x8c\x62\x94\x84\xcb\xae\x24\x70\x83\x19\x8a\x1c\x13\xb4\x89\xc4\x68\x8c\x63\x18\xec\x10\x1e\x52\x92\x54\x91\xb9\x20\x88\xdf\x83\x8e\x0d\xba\xae\x28\x5a\xf4\xab\xa0\x13\xbd\x23\xdc\xbb\x85\x3a\x12\x1f\xc4\x78\xce\x39\x4d\x24\x41\x86\x93\x68\x80\x43\x4c\xae\xf1\x8e\x7c\x5a\x10\x1d\xd1\xcb\xcb\xb8\x78\x58\x98\x1b\x97\x8f\x87\x4b\x30\x69\x71\xd9\x77\x70\x42\x13\x7c\xbb\xbd\xa1\x08\x34\xea\x8b\xc7\x24\x29\x71\x1e\x39\x7b\x12\x27\x34\xcd\xec\x95\x6c\x5c\x85\x41\x0d\x73\x40\xb0\x8b\x13\x8e\x53\x18\x88\x27\x39\x7f\xe5\x0a\x20\xc9\x35\x8a\x49\xf4\x2a\x8a\x52\xcc\x96\x1a\x90\xfd\xf0\x80\x44\x11\x4e\x40\x56\x65\xfd\x82\xe0\x38\xb2\x58\xb0\xd9\xf0\xf8\x6b\x5f\xb5\x10\xcd\x55\x7b\xfe\xf4\xbb\x3f\x80\x7e\x8c\x11\xc3\x60\x96\xd2\x6b\x12\x61\x80\x12\x80\x14\x37\x1e\xbe\x3d\xc2\x2d\x7b\x54\x88\x74\x86\x93\xe8\x75\x9a\xd2\xf4\xa3\xb7\x4e\x8e\x7e\x06\xa5\xa2\xa1\x0f\x6f\x8b\xa6\xe8\x7d\xc1\x2b\x60\x49\x74\x82\x52\x7b\xbc\x2b\xad\xdf\x40\x2d\x7b\x98\x85\x29\x99\x09\x8e\x81\x94\x87\xec\x5f\x80\x53\x18\x8c\xa8\x5e\x11\x31\x8e\x53\xc2\xae\x60\xf0\x44\xb1\x5b\xd2\x3c\x49\x80\x24\xb3\x39\x97\xb2\x41\xb9\x95\xf1\xdb\x19\xee\x41\x2e\xc6\x5f\x30\x8b\x51\x88\x27\x34\x8e\x70\xda\x83\xaf\x85\xed\x02\x04\x32\x9f\x05\x6c\xbb\x94\xb8\x7c\x2d\x6e\x67\x13\xb9\xd5\x4f\xe9\x3c\xe1\xdf\x17\xa3\x97\xcc\x00\xc4\x00\x02\xc9\x7c\x3a\xc6\xe9\xe3\xdb\xcc\xc7\xb7\x15\xd5\x0a\x18\x28\xd1\x3e\x86\xcd\x64\x3a\x52\x26\xa3\x04\x63\x19\xcd\x66\x77\x73\xb3\xd6\x42\x24\x5a\x86\x63\x1c\xea\x78\x47\xb7\xb3\xe5\x80\x17\xce\xd3\x14\x27\xe1\xed\x50\xd6\x12\x63\xc0\xae\x0c\x64\x7b\x90\x26\xbb\x59\x99\x7a\xd2\xe1\x13\xc2\xba\x0a\x1b\x8e\x0e\x93\x08\x2f\x9c\x38\xc4\x20\x4c\x95\xa0\xae\x51\x3c\xc7\x6a\xcc\x84\xc1\xd9\x70\x6f\x7b\x43\x15\x34\x86\x1c\xab\x7e\x01\x83\x9d\xd1\x6e\x35\xf0\xf6\x86\x62\xef\x07\x66\x3f\x09\xe5\x18\x06\xa7\x94\xe3\x66\xe6\x21\xeb\x97\xfb\x93\xb7\x49\x7c\x0b\x18\xc6\x09\x18\xdf\x82\x5b\x3a\x7f\x4c\x47\x92\x61\x12\x43\xb6\x1a\x9e\x99\x6f\xba\x62\x57\xdf\x8d\x31\x4a\xb5\xf8\x22\x14\xbf\xa5\xd0\x98\x8c\x2c\x64\x79\x59\xcf\xd7\xf0\xcc\xe8\x6c\x3e\x2b\xb5\xf3\x19\x4a\x8c\x8a\x4a\x34\x42\x60\x21\x4d\x2e\x48\x3a\x45\x82\xe1\x7e\x05\x0e\xa7\x99\xf3\x14\xc3\xe0\x55\x8a\x85\x18\x81\xf8\xf5\x17\x15\x1a\xb2\xa1\x6f\x50\x9a\x10\x11\x6c\xef\xd1\xf9\x38\xc6\x20\x9c\xe0\xf0\x0a\xf0\x09\xe2\x80\x4f\x70\x3e\xe0\x03\x94\x44\xb9\x1f\x24\x0c\x84\x34\x4d\x71\xc8\x5b\x90\x61\x78\x86\x52\xc4\x69\x5a\x3a\xe0\xfa\xa0\xf2\xa9\x5a\x21\x97\x4c\x9d\x15\x92\xb1\x51\x48\xad\x81\x50\x04\xc1\x71\x1f\x45\x86\x7e\x29\xc3\x52\xd0\x4a\xbd\xb2\x4a\x0d\x73\x40\x0b\x5a\xb5\xae\xb5\xc3\xf5\xc0\x54\xd8\x9d\x16\xf8\x8a\xb9\xdb\x39\x66\x6b\x40\xd4\x74\x23\x52\x07\x7d\x45\xef\xda\x10\xe6\x53\x52\x56\xc7\x15\x62\x57\xfb\x34\xdd\xd5\x84\x29\x9b\x5d\xcd\x54\x7d\xa7\x2b\x8b\x97\x53\x15\x87\x97\x87\xcc\xd9\x78\xde\x2a\x72\xb6\x82\xfb\xf2\x30\xe2\xdb\x34\xa4\xd1\x72\xfc\xc8\x7e\x56\x4e\x78\x22\xc2\x66\x31\xba\xb5\xe3\x9a\xec\xf1\x7a\x11\x21\x2d\xed\x87\xce\xf2\xda\x52\x92\x35\xde\x48\xda\x72\x82\xb1\xd7\x55\x6b\x33\x63\x51\x65\xbd\x3e\xa9\x63\xa3\x97\x60\xf9\x20\xb4\x64\x92\xce\x70\xb2\x4b\x49\x32\x46\x4c\xcc\x8f\x52\xcc\xe7\x69\x02\x2e\x50\xcc\xf0\xcb\x3c\x7f\xf5\xff\x60\x70\x8a\x71\x94\x87\x76\x3e\xef\x51\xae\xf4\x92\x39\xb8\x39\x7b\x14\xf2\xe5\xfa\x93\x92\x6c\x88\x56\x65\xbd\x7e\x06\x59\x36\x68\x25\xd4\xa5\x6e\x3d\x0b\xce\xe9\x1c\x4c\xd0\x35\x06\x09\x05\x3a\xd9\x6e\x99\x3d\xf3\xc5\xab\x14\x23\x43\xcb\x8d\x9b\x9e\xa7\x5f\x5a\x34\x3b\x4f\xfc\x54\x34\x39\xc3\xea\xcd\xc4\xb9\xd5\x8e\x15\xde\x7d\x82\x38\xc8\x43\x26\x9f\xa2\xb5\x40\x4c\x04\x43\xbb\x45\xe4\x25\xb1\x40\x0b\xeb\x32\x20\xcb\xed\x2d\x11\x14\xda\xc5\x62\x56\x24\xf5\xea\x6c\x0f\x06\xaf\xce\x2a\x42\x30\x0b\x60\x67\x70\x0c\x83\x9d\xc1\x71\x63\x80\xdd\x57\x7b\x30\xd8\x7d\xd5\x9c\xc2\xee\xc1\x3e\x0c\x76\x0f\xf6\x9b\x03\x1c\xf7\x61\xb0\x7b\xdc\x6f\x0e\x70\x7a\x0e\x83\xdd\xd3\xf3\xe6\x00\xef\x8f\x60\xb0\xfb\xfe\xa8\x31\xc0\xde\xd1\x11\x0c\xf6\x8e\x9a\x03\xbc\x3e\x1b\xc0\xe0\xf5\xd9\xa0\x31\xc0\x9b\x9d\x3e\x0c\xde\xec\x34\x6f\xf4\xc1\xd1\x1e\x0c\x0e\x8e\x9a\xeb\xe1\xe0\x6c\x1f\x06\x07\x67\xcd\xf5\x70\xb8\x37\x80\xc1\xe1\x5e\xf3\x36\x1c\x1e\x0f\x61\x70\x78\x3c\x6c\x0e\x70\x2a\x28\x9c\x36\xa7\xf0\x55\xff\x1c\x06\x5f\xf5\x9b\x6b\xfa\x68\xf0\x0e\x06\x47\x83\x77\x8d\x01\x4e\x7e\x75\x0a\x83\x93\x5f\x9d\x36\x07\x38\x1f\xc0\xe0\xe4\xbc\x79\x1b\x4e\xdf\x1e\xc1\xe0\xf4\x6d\x73\x5b\x3a\x7d\xbf\x07\x83\xd3\xf7\xcd\x35\xdd\x3f\xe8\xc3\xa0\x7f\xd0\xdc\x96\xfa\x47\x03\x18\xf4\x8f\x9a\xb7\xa1\x7f\x7c\x0a\x83\xfe\x71\x73\x29\x0d\xce\x76\x60\x30\x38\xdb\x69\x0c\x30\x7c\x7d\x04\x83\xe1\xeb\xe6\x52\x1a\xbe\xd9\x83\xc1\xf0\x4d\x73\x29\x8d\x0e\x76\x60\x30\x3a\x68\xce\xd2\x68\x70\x0e\x83\xd1\xa0\xb9\xf1\x8d\xde\xed\xc1\x60\xf4\xae\x39\x4b\x67\xc3\xbd\x9a\x09\xb4\x05\xf0\xfe\xd5\x00\x06\xef\x5f\x95\x28\xce\x9d\x2c\x3f\xf6\x88\x98\x45\x3d\x67\x09\xf1\xcd\x67\xf4\xf1\x70\xbc\xac\xd9\x7c\x38\xd4\xd0\x3f\x68\x54\xdc\x19\xed\xd6\xe4\x16\x2c\x80\xa9\x84\x98\xb6\x01\x19\x13\xce\x60\x20\xfe\x36\x06\x61\x88\x53\x36\x21\x30\xc8\xbe\x7c\x2a\x2d\x6a\x41\x17\xd8\xc7\xbe\x14\x85\x11\xd9\x60\xdc\x22\xa0\xc1\xf8\x41\x9a\x9b\xa5\x84\xa6\x84\xdf\xc2\xa0\x9f\x7d\x6b\x2c\xdd\x84\xa6\x53\x14\xc3\xe0\x54\xfe\x6f\x0c\x86\x43\x9a\xd0\x29\x09\x61\xf0\x3a\xfb\xf6\xa9\xd4\xb2\x87\x43\x32\x45\x31\xe8\xc7\x28\xc4\xde\x15\x20\x4d\x2b\x91\xaa\xdc\x5c\x33\x0a\xfb\x83\x94\xb3\x09\x83\xcd\xc6\x72\x7d\x06\x83\x67\x8d\x2b\x7f\x06\x83\xcf\x1a\x57\x7e\x0e\x83\xe7\x8d\x2b\xbf\x80\xc1\x8b\xc6\x95\x3f\x87\xc1\xe7\x8d\x2b\x7f\x01\x83\x2f\x1a\x57\xfe\x39\x0c\x7e\xde\xb8\xf2\x97\x30\xf8\xf2\x21\x46\x28\xec\x63\x9a\xe0\x29\x4d\x48\x68\x5b\x46\x85\x35\xaa\x04\xd2\x04\x87\x57\x27\x28\xbd\x24\x76\xb6\xc1\xae\x2e\x6b\x66\xa6\x3b\x9c\xd0\x1b\x90\x93\x04\x0c\xe3\xa8\x2c\xf7\xa7\x72\x9e\x2a\xd3\x29\x31\x8c\xe9\x02\x1a\x1c\x0f\x6f\x08\x0f\x27\xd2\x76\xb3\xbc\x35\x9b\xd0\x9b\x93\xac\x54\x9a\xee\x2a\xdc\x08\xb6\x55\xa6\xf5\x82\xa6\x0e\x68\xb0\xbd\x21\x0b\x5b\xe7\x62\x5a\x89\xaa\x46\x3c\x29\x66\xb7\x49\x98\xc9\x67\x20\x7f\x80\x9d\x98\x86\x57\xe1\x04\x79\x97\xb1\xfd\x08\x6a\x93\x9b\x7a\x92\x54\x03\x59\xa6\x4a\x9b\xe1\x71\x64\xd0\x3a\x51\x6a\x63\x28\x92\xa5\xbb\xc2\x05\x09\x6f\x78\x8b\x19\xb8\x21\x71\x0c\x52\xbc\x1e\xd1\x9b\x24\xa6\x28\x92\x89\xd3\x71\x21\x17\x99\x3b\x65\x21\x4a\x84\x62\x01\x4a\x6e\xc1\x94\x30\x26\x80\x67\xe8\x76\x8a\x13\xee\x24\x1d\x6a\x1b\xd2\x38\x99\x6a\x43\xde\x33\xa1\x6a\xa3\xa9\x49\xaa\x0e\x96\xea\x69\x97\x5a\x05\x4d\x12\x99\x4a\xf9\x12\xb1\x4c\xab\xee\x51\x20\x42\xb7\xba\xbc\x2a\xa8\xce\xad\x82\x76\xf9\x55\xd5\x44\x5f\x86\x55\x95\x38\x79\xd6\x37\xf4\xb1\xb3\xac\x8f\xd9\xb3\xd9\x84\xa6\xfc\x50\xf8\xb1\xe3\x22\xff\x04\x78\x3a\x67\x1c\x47\x60\x86\x71\xba\x55\xed\xfc\x54\x82\x4f\x56\xef\x63\x9c\x56\xac\xfb\x6c\x93\x59\xb0\xb5\x3d\xa3\x29\x0f\xa0\x41\xbd\x74\xdd\xe7\x23\xf8\x0f\x8d\xd5\xfb\x39\x11\x5b\x3c\xf7\x76\x24\xe7\x74\xae\xfc\x47\x82\x71\x04\x38\x05\x29\x66\x1c\xa5\x5c\xfa\x0a\x31\x2e\x88\x67\x1c\x5d\x61\x80\x2f\x2e\x70\xc8\x7f\x6c\xae\x62\x64\x69\xe2\x23\xf8\x0b\x86\xb9\x46\xe5\x13\xfb\x8d\x21\xe6\x3e\xa7\xa1\x31\xe8\x59\xa1\xa9\xe0\xf2\x7b\xea\x3a\x18\x0d\xaf\xd8\xe7\x60\x96\xd2\xc5\x6d\x03\xd7\x21\xeb\x7d\xdf\x9d\x86\x64\xf2\xfe\xee\x42\x17\xc9\xff\xb9\x8b\x32\x34\x75\xcb\xb5\x85\x0e\x3e\x8e\xa3\x90\xf8\xbf\x9f\x2e\x42\xb2\xf6\xbd\x73\x0e\xd2\x00\x69\x8a\xd7\xa7\xa5\xf3\xab\x65\x37\xcf\xea\x9e\x14\xf3\xb8\xda\xdd\x66\xfc\x06\xc7\xd7\x18\xdc\xd0\x34\x32\xe7\x62\x85\x1b\x98\x26\x0d\x7d\x80\xa0\xdc\xd6\x09\x14\x30\xc6\xd4\xa3\x09\x26\x47\x9a\x0f\x9e\x7b\x64\x84\xdf\x95\x4f\x41\x22\x1c\x63\x2e\x09\xa4\x00\x2f\x08\x93\xe9\x9a\x1b\xb9\xe4\xbe\x06\x48\x12\xc6\xf3\x48\x3c\x11\x33\x90\x90\x92\x84\x01\x92\x00\xc2\xd7\xe4\xfc\x24\xc3\x0e\x2e\x52\x3a\x95\xf3\x17\x21\x64\xc9\xab\x5c\x7a\xc7\xd1\x8f\xcd\x93\x0c\x34\x3d\x7e\x9c\x49\x8a\x40\xbf\x9f\xd2\xe9\x10\xe3\xa8\xd8\x03\xf2\xa9\x26\x2b\x82\x99\x92\xd9\x8a\x28\x72\xfc\x4a\xf6\x1c\x88\x06\x80\xa1\x4c\x7e\x3c\x8a\x97\xc9\xbe\x6e\x6f\xa8\x43\x31\xdb\x6a\xd5\x5e\x39\x82\x15\xd1\xcb\x36\xbe\x41\xd7\x48\x3d\x5d\x51\x1b\x20\xbe\x61\x1b\x6a\xff\x46\x77\x4a\x92\xee\x37\x4c\x18\x94\xaa\x50\xc0\x2b\xdc\xd7\x28\x05\xf9\x52\xfb\xcb\xe2\x89\x7e\xe8\x65\xf9\x54\x9d\x39\x59\xfe\xfe\x36\x5d\x7e\xe7\x0b\x06\x7a\x20\xc1\x37\xe0\xed\xf8\x1b\x1c\xf2\xce\xea\xb2\x2c\xb3\x4b\x1c\x0d\x55\xbe\x5b\x23\xc4\x26\xf4\x86\x24\x97\xfa\xf2\x3f\xe8\x65\x5b\x2d\xec\x4a\xf9\xf2\xbe\x5b\x21\xf7\x72\xea\x49\x44\xc3\xf9\x14\x27\xbc\x7b\x89\xf9\xeb\x18\x8b\xaf\x3b\xb7\x87\x51\xc7\xdc\x4d\xb1\xda\x95\x87\x92\xba\xd9\x5e\x15\xd0\x03\x2b\x09\x4d\xf0\x4a\x0d\x8e\x62\x5b\x42\x39\xbc\x44\x70\x31\x4f\x54\x62\x9d\x71\xc4\xd9\x31\xa5\xb3\xce\x2a\xf8\xae\xd0\x2e\x62\x9c\xc4\x38\xe4\x29\x4d\xba\x0c\x27\x51\xe7\xbb\x04\x4d\xf1\x16\x80\x97\x98\xab\xd3\x16\x6b\x60\x86\x6e\x63\x8a\xa2\x2d\xf0\x5d\xbe\x95\x73\x97\x46\x78\xab\x50\x57\x57\xee\x35\xa0\x11\xbe\xbb\xcb\x84\x2d\x3e\x22\x72\x27\x53\x4c\xe7\xbc\x53\x90\x5e\x03\xcf\x36\x37\x37\x37\xb3\x5a\x77\x16\x87\x7c\x71\x36\x8b\x10\xc7\x0e\x93\xe4\x02\x74\x7e\xea\xd1\x90\x5e\x47\x7c\xd4\x06\x99\x25\x0b\x77\xc5\x37\x11\x61\x75\x94\x79\x90\x48\xb8\x4e\xbe\x70\xa0\x55\x31\xe8\x89\xb2\xaf\x45\xbd\x0f\x2f\x9d\x72\x61\x41\x7b\xe4\x1a\xf4\x4a\x15\xc3\x17\xdd\xd1\x82\x44\x4f\xe1\xba\xee\x05\x19\x5c\x75\x91\x71\x32\xc5\x4d\x91\x89\xba\x3e\x1c\x42\xf4\x4d\x71\xc8\xfd\xb1\x1e\x1c\x24\xa4\x49\x53\x1c\x72\x6f\x93\x07\x47\xd6\x58\xd1\x27\xa6\xe8\xca\x70\x49\x4c\x80\x1f\xc8\x2e\x6b\x01\x66\xd2\xec\x92\x24\xc1\xe9\xc1\xe8\xe4\x18\xf4\x00\xec\x40\xf0\x74\x89\xee\x29\x80\xc6\x70\xc2\x56\xa1\x4b\x9c\x91\xcb\x44\x80\x3e\xb5\xca\x84\xdd\xf0\x45\xf7\x97\x28\x9e\x63\xb0\x0d\x36\x6d\x8d\x4b\x33\xcd\x60\xd7\xa1\x51\x74\x67\xfc\xca\xa4\x6c\x30\x2a\x01\x9f\xca\xd6\xee\x13\xc4\x25\x91\x82\x9a\xd5\xd0\x4c\xd3\x06\xbc\x78\xd6\x47\x8c\x61\x25\x5e\x32\x15\x93\x81\xe9\x6c\x55\x36\x19\x5d\x52\xab\x2d\xb6\x54\x0f\x43\x9a\x74\x72\x31\xad\x01\x1d\xc5\x5a\xae\xd1\x55\x5f\x57\xd0\xfa\xa5\xde\xe1\xd6\xc0\x73\xa7\x67\x16\xe6\x80\xa2\xe8\xf5\x35\x4e\xf8\x31\x61\x1c\x27\x38\xed\xac\x68\x7e\x63\x3d\xc5\x28\xba\x5d\x59\x2b\x3a\x72\xa9\x83\x89\x25\x78\xa7\xa8\x37\xc5\x8c\xa1\x4b\x6c\xab\x85\xc9\xac\x39\xc8\x8b\xbb\xc2\x23\xf9\x54\x17\x22\x86\xc1\xd2\x11\x6e\x79\x47\x53\xb6\x74\xd6\x5f\x0d\xdf\x9e\x76\x67\x28\x65\xb8\x40\x9d\xb9\xb6\x55\x2f\xa8\x1a\x92\x04\xf3\x3b\x74\x51\xd1\x3b\x56\x96\x9b\xde\x57\x2c\xc5\x2f\xb9\xc8\xd0\x74\xd5\x2a\x0a\xfb\x7a\xf3\x43\x57\x8c\x98\xc2\x90\x6c\x37\xda\x14\xc5\x33\x17\x85\xb6\xca\x5d\x87\x45\xae\xed\xe8\xb0\x45\x91\x1f\x32\xf7\x36\x35\xb2\xf0\xec\x3b\x2b\x13\x4a\x86\xcd\xe5\xa4\x5a\x10\x95\xa4\xcd\x33\x73\x2b\xab\xa6\x6f\x51\x9e\x80\x24\x40\xf8\x98\x86\xe4\x44\xbb\xb3\xc5\xcd\x9a\xa6\x9b\x4b\xa0\x65\xad\x5e\xe2\x72\x1b\x9e\x95\xa9\x05\xd7\x72\x76\xe6\x09\xa9\x53\x83\xbb\xdd\xa1\x8c\x9f\x0c\x99\xcb\x4c\xad\x2d\x49\x8b\xc0\xb8\xce\x20\x8a\xe5\xfa\x52\x3b\x90\x38\x3c\x66\x80\xf1\x31\xbe\xc6\x71\x3b\x33\x30\x52\xd9\xab\x2e\x56\xad\xb8\x25\x62\x95\xe8\xf2\xa0\x94\x05\x25\xfd\x6d\x19\x75\xf9\x2b\x8c\x53\x8c\xae\xdc\xa2\xcc\xb7\x09\x68\xe5\xa3\x4b\xdc\x5b\x29\xb3\xfa\x11\x57\xb3\x17\x64\x9b\x3d\x46\x74\x67\xb4\x2b\x94\x6b\x3b\xc3\x6e\x11\x26\x97\x59\x70\x19\x4d\xe3\xbc\xab\x45\x54\xef\x6c\xc3\xdb\xe9\x98\xc6\x62\xf0\xb4\x28\x8b\xc2\x96\x34\xcd\xa3\xae\x26\x51\x1b\xbd\x1e\x77\xb7\x24\x63\x9c\xbe\xbf\x4f\xd3\xdc\x99\x4c\x63\xda\xd9\x11\xfb\xea\xb6\xe9\x73\x22\xfb\xa3\xd3\xf6\x80\xd6\xb3\xa6\x90\xb7\xa4\xea\xcc\xb6\x3c\xf0\x45\x9d\x7b\x74\x8e\x7c\x53\xbf\xbf\x63\x7c\x9b\x76\xe5\x19\xa0\xb2\x7e\xf7\x6d\xda\x55\x21\x55\x84\x3b\xf9\xe6\xb0\x2d\xe8\x2a\xae\x6d\x1f\xb0\x4e\x22\x54\x2a\xed\x3e\x1e\x61\x79\xec\xd6\xdf\x6e\x19\xb4\x14\x95\x2a\x1c\xb3\x8e\xaa\x6d\x23\xd5\x69\x5c\x6b\x70\xfd\xd3\xef\xfe\x00\x3c\x02\x2c\xf1\x8b\x05\x71\x77\xfa\x2a\x57\xdf\x57\xee\x21\x1c\x63\x5e\x5d\x2e\x1e\x75\x1a\xa0\x4a\x34\xd9\x79\x81\x12\xb1\x88\x69\x85\x6d\xc8\x31\x4e\x2e\xf9\x04\x04\xfe\x49\x46\xad\x40\xad\x13\x0e\xd5\x39\x01\xfb\x73\xe7\x1f\x55\xc5\x94\x97\x78\xfa\x5c\xc6\xea\x3a\x78\xf6\x12\x10\x10\xf4\xc0\xe6\x4b\x40\xd6\xd7\xab\xf8\x16\x33\x62\x0b\xcd\xd7\xe4\x83\x9c\x13\x7e\x70\x29\x7c\x4d\x3e\xf8\x19\x05\xfa\x2c\x3b\x4c\x31\xe2\x78\xb4\xb0\x45\xf9\x35\xf9\x50\x22\x77\xc5\x89\xd0\x4c\x17\xcd\x84\xfd\xec\x4e\x48\x2c\x66\x4f\x25\xf5\xfd\x72\xa9\xb4\xa0\x04\xeb\x77\x88\x94\xd8\x50\x99\x37\x2c\xb7\x96\x06\xb9\x0b\x57\x46\x0f\x33\x52\xf1\xb9\x99\x90\x18\x8b\x29\xb0\x94\xd9\x04\x31\x29\xb0\x53\x1a\x61\xd6\x59\xad\x62\x00\x2c\x25\x9d\xe2\x29\xbd\xc6\xb9\xa4\xe5\xa3\x18\x31\x2e\x1f\x54\x90\xf6\xcb\x1e\xd4\x64\x9c\x8c\x4e\x70\xf7\x78\x6a\x2d\x36\x9f\xf9\x15\x5a\x2c\x4e\x78\x54\x5a\x92\x15\xd0\x99\xfb\x36\xcd\x32\x8e\x7f\x39\x90\xc3\x49\xa9\xc6\xb2\x93\x6c\xab\x6b\x96\xe8\xc5\x2c\x6e\x0b\x40\xb8\x66\x3c\x55\x66\xb6\x05\x9e\x7d\xfe\xdc\x2c\xb8\x21\x11\x9f\xc8\xe7\x5e\x76\x2a\x53\x7a\xf9\x64\xb9\x29\x40\x3e\x8e\x35\xad\x5f\x2c\x0f\xe5\x00\xe2\xbf\x99\xe6\x2b\x3a\x3e\x5f\xe8\x36\x28\xd3\xbd\x09\x4f\x6f\x75\x9b\x57\x75\x33\x21\x8a\xc1\xf5\x5a\xb7\x77\x01\x42\xe7\x1c\xa7\x56\xf6\xaa\x1a\x2a\x87\xe8\xca\x04\xfb\x31\x61\x32\xbf\xd1\x59\xb9\x88\xf1\x62\xc5\xc2\x1e\xe3\x0b\x3b\xbd\x56\x8d\x3c\x03\xb0\x71\x47\x98\x23\x12\xb3\x75\xa9\x3a\x9b\x48\x2a\xf4\xdc\x8a\x4a\x0e\x51\xd6\x04\x03\xfd\x35\xc1\x37\x7b\x8a\x7e\x05\x05\xb5\x40\x60\x48\x77\x09\xa7\x06\xfa\x91\x4a\x36\xc0\x5f\x12\x7c\x03\xb2\x12\xe8\xaf\x6f\xf2\x05\x45\x51\x26\x82\x32\x0a\xd9\xd2\x06\xe8\xf9\xd3\x48\x95\x76\x47\x67\x38\x19\xa7\xf4\x86\xe1\x54\x4f\x57\xc3\x09\xe7\x33\xb6\xb5\xb1\xb1\xdc\xce\xd7\x25\xc9\x05\xdd\xe0\x8b\x0d\x11\xa8\x64\x59\x4d\xdd\xb4\xef\x3c\x32\xd6\xc7\x1a\x8d\x63\x5b\xcc\x42\xf3\x23\x3a\x6b\x6d\x2d\x0a\xa6\x89\x31\x7a\x72\xbd\xf5\xfd\x63\xcc\xc3\x5f\xe6\xf3\x55\x7b\xe2\xe7\xc9\x56\x96\xa5\x53\xc5\x28\x26\x53\x67\xfb\x31\x45\x1a\xa4\x2f\xad\x5a\x90\x7c\xd2\x03\xeb\xcf\x4c\x9f\xec\x49\xb7\x6a\x59\xfa\x07\xa4\x59\x0b\xd8\x48\x66\xf0\xa5\x66\xc1\x53\x90\x65\xbd\xdd\x7a\x96\xbc\xc7\x34\x8e\x56\xd6\xc0\x0a\x5f\x64\x8b\xe1\xb6\xf0\xc7\x3c\x6c\x25\x7b\x55\xdf\x93\xda\x2e\xa4\xf3\x14\x40\x33\x0f\xa5\x25\x5c\x44\xa1\x9e\xe9\xce\xb0\x35\x61\xda\xe0\xda\x93\xda\xaf\x66\x3b\x03\x70\xc5\x28\x13\xff\x1a\x76\xcd\x74\xf5\x0e\xe2\x66\x9e\x4b\x2a\x66\x7a\xa8\xaf\xa8\x9a\xde\xa8\xd3\xf0\xc5\xba\x18\x4a\x1d\x29\x08\x88\x1d\xca\x39\x9d\xb6\xee\x9d\x05\x98\xb7\x83\x2a\xd9\x0b\x9a\x9f\xd9\xf6\xe2\x59\xdc\xa9\xa6\xf6\xc0\x35\x82\x02\xdc\x56\x9c\x5c\x39\x72\xeb\xd9\xa2\x23\x53\xec\xb1\x7c\x53\x04\x46\xd4\xad\xf0\xd8\xa2\xf6\x2c\x90\x55\x37\x3b\x5f\x03\x72\x55\xe9\xef\x87\xad\x17\x9a\x1e\xba\xc8\x54\xc0\xdb\x82\x35\xd7\xf7\x9a\xc8\x2c\x43\xa5\xcb\xec\x9e\xcb\x3a\xa6\xa9\x2d\x48\xd4\xce\xd4\x14\x80\x69\x6a\xaa\x65\x5d\x36\x1f\x33\x9e\x92\xe4\xb2\xb3\xb9\x06\x7e\x21\x2d\xad\xdb\xed\x36\x6a\x5e\x86\xd6\x43\xa8\x54\xb9\x6b\x60\x65\x79\x1b\xe1\x8a\x07\xd2\x17\x16\x34\x8c\x0a\xc2\x98\xcc\xc6\x14\xa5\x91\x16\x13\x7c\x17\x21\x8e\xb6\xf2\x81\xdf\x9e\x61\xf8\xe4\x02\x77\xe9\x8c\xe0\xc8\x5a\x8d\xd3\x16\xd1\x8a\xb8\xd6\x89\x57\x1e\x2c\x6a\xf1\xb9\x53\x6b\xe6\x66\x8c\xe2\x84\x9b\xba\x1a\x96\xfe\xd1\x13\x97\xda\x15\x0b\x4d\xfa\x02\x64\xbb\x72\x83\x6a\x79\xd4\xa4\xd5\x93\x41\xbd\x6b\x02\x2b\x4e\x15\x1d\x4f\x8e\x5c\x0f\x7a\xd5\xf5\x17\xb2\xae\x9a\x5a\xd8\x3b\x1c\xec\xf8\x26\x7b\xc0\xec\x69\x46\xfe\xbc\x8f\x53\x73\x75\x43\xad\x3c\x76\x7c\x23\xb2\xad\x5c\x35\xb1\xdc\x19\xed\x7a\xe6\x94\x16\x7e\xd0\x53\xdb\x1e\xc4\xc7\x9d\xa1\x7a\x26\xae\xd9\xa4\xb5\x1d\xf2\x16\x98\xe5\x51\xd1\x86\x98\x5b\xa0\xcd\x8f\x93\xba\x98\x33\xd5\xe5\x04\x3c\xa1\x9f\xb6\xca\x06\x7a\xe0\x04\xf1\x49\x77\x46\x6f\x3a\xcf\x36\xd7\x4a\x56\xc7\xac\x61\xe1\x5a\xc2\xe5\x04\xc0\x46\xb9\x8e\x33\x5e\x24\x89\x8b\x98\xd2\xb4\x23\x60\x9f\xe4\xd4\x57\xc1\x46\xfe\xd5\xbf\x4b\xc5\x8c\x44\xaf\x05\xc4\x77\x65\x11\xb7\xc0\xbc\xe1\x53\x7e\x1e\xce\xe7\x15\x3b\x39\xd0\x13\x3d\x19\xbf\xda\xe5\x74\x9f\x2c\x70\xd4\xf9\xac\x7d\x88\x2e\x39\xf3\x44\xe7\xcb\x08\xdc\xd4\xe1\x92\x1d\x2b\x6c\xbf\xb3\x45\xe7\x5f\xf0\x28\xe0\xcb\xc5\x66\x0f\xd6\xd9\x58\x6d\xc9\xcf\x18\x57\x41\x0f\x6c\x9a\x4d\xcc\xc1\x40\xaf\x97\xa5\x48\x9c\xae\x69\x21\xd0\xdb\x02\x70\xcc\xb0\x89\xc7\x93\xb3\xb5\x31\x74\xb2\x94\xdf\x3a\x58\x32\xfd\x14\x54\xc9\xc8\xc0\xe0\x97\x08\x61\x43\x3e\x0f\xaf\x3a\xdc\xf1\x4f\xf3\x84\x2c\x40\x0f\xec\x21\x8e\xb3\xfd\x0a\xa2\x8e\x32\x24\xd3\x0e\x12\x7a\x93\x77\x17\x65\xcb\x12\x26\xa1\x37\x9d\xbc\xfe\xaa\x29\xbd\x8e\x80\x58\x97\x14\x56\x41\x00\xbe\xfc\xe2\xc5\xa6\xd3\xfa\xac\x09\x3c\x9d\xe3\xf2\x06\xca\x9d\x6f\x25\xed\xda\xc3\x28\xfa\xa4\xcd\xea\xc8\x76\x81\x27\xe0\xe7\x4e\x9a\xf3\x81\x8d\xab\x8b\xd7\xd8\x32\x4a\xb3\x07\x1d\xa1\x6c\xd0\xd3\xd5\xfe\xd2\x72\x7f\x28\x92\xe5\xb9\xf8\xcc\x26\x2e\x03\xdf\x1e\xd8\x04\x3f\xfb\x99\xac\x6f\xb7\xae\x98\xbe\x19\x0b\x33\xbf\xff\xad\xbd\x31\x2a\xab\x66\x0d\xca\x61\x4a\x19\xd3\xc7\x65\xad\xbb\x38\xe4\x65\x7b\x9a\xd1\xff\xdd\x1f\x1a\xd2\x57\x57\x79\xd6\x71\xb0\x0d\xbe\xf0\x85\x5a\x5e\xda\xff\xf3\x37\xbf\xfd\x3d\x74\xd0\xf9\x99\xb6\xb9\x99\xe0\xf0\x6a\x8a\xd2\x2b\x7b\xdf\x42\x89\x90\xff\x1a\xda\xfe\xc0\xd9\xe0\xa8\x4d\xe7\xfe\x5c\xbd\x43\x6d\x62\x0a\x69\x12\x31\x45\x1a\xf4\xc0\xb2\xb3\x98\x26\xa6\xa1\x34\x41\x36\xc0\xf3\x67\x2f\x5e\xfc\xe2\x0b\xe1\x2b\x3c\xee\xd2\x1d\x52\xcb\xc1\x9f\x02\x78\xeb\x2a\xa4\x86\xfa\x17\x9b\x2f\xbe\xbc\x37\xed\x1c\xf8\x29\x80\x37\xad\x29\x67\x0e\xf2\x5e\x84\x33\xd8\xa7\x00\x46\xad\xe9\x3e\x2f\x64\xdd\x5a\xd4\xb9\x98\x27\x75\x76\xdf\x44\x74\x12\xd3\xb4\xde\xb2\xdd\xeb\xbc\x9d\xa8\x28\xa9\x5c\x8c\x76\x2e\x10\x77\x6c\x38\x89\xaa\xb6\x19\x15\x57\x7c\x3b\xd9\xf5\xec\xda\xc1\x0a\x58\xfd\xba\xc3\x15\xcb\xed\x8e\x79\xa2\x67\xbf\x7b\x00\x1a\xf7\x18\xc2\xc6\x49\xea\x92\xc5\x14\x20\xb3\x7b\x89\x99\x61\x5f\x5e\x32\x6e\x39\xce\x8c\xd3\x66\x6b\xe6\x82\x7c\xed\x42\xb2\xd7\x32\x1c\x86\xcc\x36\x37\xe4\xc9\xb3\x64\xed\x67\xc9\x66\xde\x6f\x63\xc6\x95\xae\x1a\xc3\xa5\x36\x85\x8a\x3d\x18\xf9\x8e\x2d\xa8\xb1\x5e\x0e\xa6\xae\x46\x6e\x09\x25\x6f\xcc\xf5\xc3\xc8\x44\xac\x7e\x35\x76\x55\x47\x30\xef\xd0\xd6\x8d\x51\x2f\xa8\x15\xb6\x4e\x33\xbb\x05\xb6\x01\xd1\x5c\x60\x2e\x55\x55\xd2\x88\xec\x43\x76\x9f\x54\x6d\x0b\xd1\x48\x39\x51\x99\xf5\xf2\x8a\x26\x07\x1c\x8a\x97\x76\xdc\x95\x1c\x47\x30\xae\x08\x35\x9d\x59\x95\x27\xaa\xd8\x01\xd4\x60\x09\xb5\x3c\x69\x65\xa6\xab\xee\xb7\xff\xc8\x4d\x66\x35\x4a\x64\xdd\x8f\x98\xb6\x1f\xc2\x4c\x62\xd9\x82\x36\xaf\x39\x6d\xa2\xbb\xba\x05\xbf\x30\xc3\xd6\x0d\xe9\xb4\x54\xbf\xbe\x3b\x75\xad\x41\x4b\x5e\xf2\x5c\xa5\x6b\xf7\xda\x67\x4d\x47\x12\x5a\x8b\x2a\xd5\x20\xd9\x91\xd7\xc7\xc0\x4a\xa6\xbc\x07\xbb\xda\xf2\x66\x1c\x76\x7c\x14\xb6\x4a\x0f\xba\xb7\x65\xcd\xb9\xc2\xe1\xb1\xa4\xe6\x5c\xde\x71\x0f\xa1\x15\xe7\xcd\x1f\x85\x29\xcf\xc9\xdf\xb6\x3c\x69\x67\xd7\x1f\xc8\x92\x7e\x6b\xf6\x27\x37\x75\xcf\x49\xce\x4f\x69\xe2\xee\xe5\x37\x9f\xd0\x76\x4a\xae\xd7\xf8\xd4\xfd\xcc\x39\xc6\xff\xe9\x4c\xd9\xb9\xa7\xdd\x62\x25\xb1\x8e\x72\xb6\xdf\x40\xee\x66\x6b\x77\xd4\xd6\x76\xd0\x03\x5a\x9e\xb5\xf5\x6e\x78\x6d\xdd\xe7\xd9\xaa\xb3\x60\xff\x08\x31\xdb\xe3\xc4\x9b\x0f\x0d\xe5\x5a\x46\x8e\xed\xc2\xdb\x06\x71\xa2\xd1\x10\x54\x2f\x4f\x6b\xb6\xe0\x2c\x2f\xa8\xf5\xdf\x54\x2f\x11\xf3\xc3\x02\xb3\x88\xf9\x9d\x74\x58\x8d\x0c\x7c\xb3\xb6\x9c\xd4\x32\x07\x09\x9c\x95\x12\x54\xab\x56\x73\x12\x63\xb1\x9c\x41\x57\x71\x5c\xa2\x86\x5a\x86\x7d\x29\x71\x79\x7c\x57\xd6\x72\xf2\xec\xfa\x5b\x1c\x3c\xb9\x09\x0d\x99\xd1\xfe\xaa\xd9\xbc\xfe\x0a\x1a\xcb\x9c\x97\x25\xa0\x07\x70\x71\x8e\x0e\x9b\x37\x4f\x7e\xf0\x19\x00\x33\x4e\x8c\x9b\x92\x54\x08\x7b\xa0\x78\x8d\x8c\xff\x40\x63\xa3\x65\x45\x50\xb3\xb4\x08\xb4\x75\x3a\xd0\xcb\x0d\xe1\x49\xd5\x02\x23\xa8\xdd\x1d\x7b\x1f\x52\xf7\xa0\x53\xb2\xec\x58\x41\xe7\x1e\x44\xca\x17\x21\xbd\x74\xac\xc5\xf6\xea\xb4\x88\x06\x9d\x77\xa2\x0d\xe3\x70\xcd\xaa\x5f\x13\x96\xf5\x26\x94\x57\x1a\xb0\x9e\x4a\xb0\xfc\x58\x82\x6f\x76\x78\xb8\x1c\x87\x9c\x25\x6f\xf7\xd0\xcd\x7a\xc1\xb6\x95\xd9\x32\x71\x79\x56\x0a\x6d\x62\x9b\xbe\xce\x9d\x71\xb5\x6f\x0c\x8f\x9d\x6a\x3e\xf4\x35\x51\x21\x32\xff\x01\xa4\x8c\x47\x1d\xb3\x9f\x49\x93\xb6\x5f\xee\xf7\x3a\x3f\x26\x47\xf9\xc3\x84\x77\x12\x73\xe7\xbe\xb1\xf4\x77\x8f\x13\x78\x86\x60\x1b\x60\x6a\x7d\xae\xce\x14\x8a\xb1\x8a\x5c\x3f\xb9\x16\x3f\xf4\xec\x43\x36\xc2\x6d\xe5\x83\xe8\x5a\xd6\x75\xb6\x0a\x85\xae\x81\xfc\xa8\xe6\x96\x7b\x7a\x73\x4d\xda\xfb\x96\xfc\x6b\xa4\x30\xfc\xce\xdf\x7c\x71\x93\x3f\x5f\x60\xbf\x36\x8c\x44\xee\x4e\xf2\x47\x1d\x21\x48\xe4\x8e\x0a\xee\xb9\xe9\xc2\xa9\x08\xf8\x06\xb9\x9e\xd9\x7c\xb9\x1f\x5f\xcb\x62\xc8\x63\xea\x2a\x40\x24\x17\xb7\xc5\xa8\xb1\x6a\xe5\x31\xe4\x52\x79\x7e\xd0\x5a\x2a\x5e\xf8\x25\xb3\x73\xc8\xd7\x71\x6c\x01\xf8\xff\xad\xa3\x05\xf2\xad\x1b\x5b\x00\x0e\x9c\x82\xdd\x57\x7e\x80\xdd\x83\x7d\xf1\x7c\x3f\xed\x3a\x25\xc7\x7d\x3f\xc4\xe9\xb9\x78\xfe\xc7\xbf\x73\x0a\xde\x1f\x89\x82\xa3\xff\xfc\x2b\xbb\x64\xef\x48\x96\x5c\xa5\x76\xc1\xeb\xb3\x81\x28\xf8\xd3\x6f\xfe\xc9\x2e\x79\xb3\x23\xa9\xff\xf1\x6f\xed\x82\x83\x23\x7f\x43\x0e\xce\x54\x43\xb8\x5d\x70\xb8\x27\x69\x0c\x66\x4e\xc1\xf1\x50\x11\xff\x47\xa7\xe4\x34\x63\xeb\x5f\xed\x92\xaf\xfa\x25\x8d\x3f\x1a\xbc\x53\x20\xff\x60\x97\x9c\xfc\xea\xd4\xcb\xf0\xc9\xb9\xe2\xeb\xc4\x2e\x38\x7d\x5b\x22\xad\xd3\xf7\xfe\xa6\xf7\x0f\xfa\x8a\xf6\x3f\x3b\x25\x47\x59\x43\xfe\xde\x29\x39\x96\x5c\xfd\xfa\xbf\x7e\x63\x97\x0c\xce\x76\x14\xcc\xbf\xdb\x25\xc3\xd7\x25\x8c\x0d\xdf\xf8\x19\x1b\x1d\x48\x54\xff\xfd\x2f\xff\xe1\x94\x0c\xce\x15\x91\x7f\x73\x4a\xde\x49\x5c\xa7\x23\x07\xdb\xd9\xd0\x4f\xe5\xfd\x2b\x25\x48\xb5\xf3\xfc\xce\x3e\x96\x62\xbc\xfc\xa6\xad\x47\xf1\xbd\x6d\xc7\xde\xb8\xaa\xdd\x9d\xd3\xdc\xb9\xe4\x77\x13\x80\x9e\x81\xc0\x0a\x4e\x95\xdf\xef\xd9\xfe\xe0\x6b\x1d\xe4\x43\x09\xf6\x61\x0e\xac\xb0\xd8\x13\xa7\x06\xb3\x8c\x5a\x47\x8a\xb8\xe7\xda\x0b\xb3\x39\xb5\x83\xe0\x23\xde\xee\xf0\xd8\x0e\xb9\x12\xe7\x83\xee\x51\x72\x47\x3e\xf7\x8d\x14\x6d\x4d\xd5\xf3\x22\x0c\x4b\x77\x73\xb5\xf9\xaf\xa1\x85\xea\xa7\x16\x7a\x12\xf6\x23\x9b\xd0\xf2\xda\x13\x8b\xd8\x0f\x59\xaf\xc6\xdb\x10\xda\xaa\xd4\x7a\xf7\x82\x25\x47\x79\x37\x23\x6b\xae\x50\x63\x9b\xa5\x88\x82\xb3\xdb\x48\x7e\x14\x72\x5e\xbe\x0f\xa4\xb5\x8b\x5f\xbe\x76\xc4\x3e\x97\x95\x45\xba\x2d\xbc\xfa\x12\x62\x79\xc9\xc9\x8f\x40\xbe\xf6\x6d\xcd\x9a\x7c\x7d\xf7\xaf\x34\x4c\x5d\xbb\x59\xac\x8f\x21\xa1\x92\x94\x7b\x59\x3b\xb3\xcb\x66\x7d\x2d\x94\x49\xee\xda\x2c\xf8\x9f\xb1\x55\x7a\xc6\xde\xdb\x9e\xfc\x56\xfe\x26\x6b\xaf\xaa\x2e\x74\x88\x18\x4b\x27\x65\x54\xcc\x6b\x35\xed\x1d\x92\x18\x57\x2e\xac\xdb\x37\xd0\x36\x17\x60\x06\xa9\x0b\x4f\x10\x6b\xb4\xa0\x5e\x42\xd5\xda\xe3\xa1\x1d\x21\x17\x98\x5d\xd9\x68\xab\x5c\x7e\x93\xd2\xdf\x29\x62\x66\x4a\xcb\x8e\x39\xdb\x9c\x16\xa7\xdc\xad\x44\x0f\x89\xba\x72\x2f\x23\x76\xf2\xaf\x02\xf3\x4d\x8a\x66\x33\xb3\x2f\x56\x9f\x1e\x02\xc5\x65\x97\xad\x0e\x1d\x29\x29\x15\xfb\x26\xb3\x9d\x45\xe6\x8d\x99\x66\x3d\xeb\x10\xb1\xaf\x79\xa0\xd8\x3b\xcb\xc2\x76\xac\x08\x08\x73\x8f\xd3\x93\x9d\xc3\xfe\xf3\x5f\x98\x37\x15\x83\xb9\x7c\xd7\xc7\xce\x61\xff\xc5\x0b\x10\xe1\x94\x5c\xcb\xf5\xcf\x2e\x78\x97\x12\x8e\x01\xe1\x20\xa2\x37\xd9\x4b\x42\xe4\x95\xab\x84\x8b\x00\x14\x01\x86\x2e\xb0\x1a\x39\xbb\xe0\x9c\xce\x41\x88\x12\x30\x67\xb2\x3c\xbb\xf8\x9b\xa6\xd9\x6d\xbf\xea\x3a\xdf\x18\x71\x9c\x76\xa1\xcb\xa3\x23\x85\x3d\xcc\x1c\x19\x64\x4a\x34\x8e\xd0\x4c\xad\x83\x98\x65\xf5\x04\x15\xab\x9a\xf7\x68\x4f\x06\x5b\x56\x55\xad\x15\x14\x77\x63\xc0\x67\x9f\x6f\xce\x16\x75\x5b\x10\x0b\x68\xfd\x9a\x89\xe2\x61\xd9\x45\x13\xa5\x34\x6d\x92\xa5\x3d\x4d\xcf\xe7\xdd\xeb\xaa\xd1\x87\xdc\xcb\xaa\xe3\xa9\xbc\x52\x36\xff\x94\xa7\xea\xac\xa6\x38\x3b\x0b\xfd\xd7\xda\x9a\xab\x58\x95\xcd\xa9\xbb\xaa\xd6\xb7\x20\x64\xde\xe3\x5a\x6d\x00\x8f\x71\x47\x6e\xad\x98\x26\x24\xc2\x8e\x68\x1e\x72\xc9\x4a\xeb\x8b\x55\xda\x5f\xa6\x72\xd7\x40\x8f\xde\x15\x37\x9f\xb9\xe7\xe6\x55\x6a\xea\x79\x85\xc6\x66\x7e\x0f\xf5\x34\x6a\x43\x25\xd1\xaa\xbe\xe5\x33\xc4\xca\x7e\xe3\xbd\x0a\x05\x78\xbb\xa4\xd9\x5f\xda\xd9\x71\x4b\x7f\xf0\x98\x02\xff\x41\x59\x78\xbb\xce\x5b\xeb\x36\xf3\xbe\xa0\xdd\x36\x9e\xdf\x5a\xbe\x31\xe1\xd3\x38\xf8\xdf\x00\x00\x00\xff\xff\x2f\xf3\xb7\x57\x5c\x90\x00\x00") - -func resourcesAppIndexHtmlBytes() ([]byte, error) { - return bindataRead( - _resourcesAppIndexHtml, - "resources/app/index.html", - ) -} - -func resourcesAppIndexHtml() (*asset, error) { - bytes, err := resourcesAppIndexHtmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/index.html", size: 36956, mode: os.FileMode(436), modTime: time.Unix(1501830025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppJsQrcodeMinJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x7c\x7b\x73\xdb\xb8\xee\xe8\x57\x49\x7c\xa6\x5e\xb1\x82\x1d\x92\x7a\x58\xb6\x42\xf7\xa6\x8f\xdd\xf6\x6c\x5f\xdb\x76\x7f\xf7\x9c\xf1\xf1\x76\xf4\xa0\x65\x25\xb2\x95\xb5\x95\xa6\x9d\xc4\xdf\xfd\x0e\x1f\x7a\x5a\x69\x7b\xe6\xce\x2f\x7f\x24\x22\x08\x82\x00\x08\x80\x00\x29\xe5\x4b\xb0\x3b\xf9\xe3\xc3\xb3\x3c\xe6\xfe\xe9\xea\x66\x1b\x15\x69\xbe\x35\xd0\x5d\xf9\x78\x12\x18\x01\xba\x2b\xd6\xe9\x7e\xbc\xc9\x63\xce\xa2\xf1\x9b\x77\xcf\x5f\x7c\xf6\x9e\xbe\xfa\xf4\xf9\xe9\xbf\x3f\xbd\x00\xd9\x15\x07\x45\xc0\x02\xf5\x7c\x1d\xec\xf6\x3c\x7e\x2e\x20\x8b\xa5\xbf\xca\x77\x86\x98\x22\x64\x8b\x25\xc4\x0c\x03\x67\xd5\x88\x71\xc6\xb7\x49\xb1\xf6\xf9\x3c\xf6\x63\xd3\x44\x77\x02\x71\xd5\xe8\x8f\xd6\xc1\x4e\x70\x76\x51\x18\x31\xf2\x57\x73\xd7\x71\x2c\xf7\x89\x11\x2e\xf0\x92\x51\x1b\xdf\x1b\xc4\xb3\x1c\x8c\xbd\xe1\x0a\xcd\xe7\x73\xe2\x41\xb8\x20\x4b\x46\xa8\x77\x6f\x50\xc7\xc3\x76\xd9\x41\x21\x5c\x50\xdd\x61\x63\x8b\x2a\xb0\x0b\xe1\xc2\x52\x50\xd7\x1a\xae\xd0\x6c\x35\xa7\xd8\xf6\x4a\xfa\xd4\xbe\x37\x5c\x62\xdb\xb8\x41\x84\xf4\x12\xa1\x6d\x22\x84\x96\x34\xc8\x94\xde\x1b\x64\xea\xd9\x35\x2e\x69\xe2\x4a\xa4\xd5\x91\xda\x3a\xed\x71\x94\x6f\xa3\xa0\x30\x42\x74\xe8\xf6\x28\x05\x9e\x1e\xa9\x74\x38\x34\xba\xa8\x37\xdb\xfd\x3a\x5d\x15\x06\x99\x12\xd4\x9d\xb1\xee\xf4\x26\x0f\x77\x52\x6b\x8a\xd0\xa1\x32\x8c\xd0\x08\x20\xd4\xa6\x51\x7c\xbb\xe6\x6f\x6f\x36\x21\xdf\x95\x56\xc0\x77\xbb\x7c\xf7\x2c\xdf\xed\x78\x54\xbc\xe6\x5f\x78\xc6\x42\x28\xad\xe8\x26\xe3\x7b\xb6\xbd\xc9\xb2\x26\xe4\x59\x7e\xb3\x2d\x18\xae\xed\xe9\x59\x10\xad\x79\x03\x4d\xc0\x5e\xa7\xfb\x82\x2d\x96\x35\x13\xa9\x62\x22\x5d\x19\x5f\xf2\x34\x3e\xc1\x8c\x95\x2a\x40\xc5\x7a\x97\xdf\x9e\x6c\xf9\xed\xc9\x0b\xc1\x8b\x51\x76\x98\x83\xb3\x81\x19\xa2\xca\x32\x23\x86\xfd\xe8\xbc\xd6\x9c\xa0\xb1\x88\x96\x3e\x8a\x4c\xd3\x97\x33\x6f\x6f\x36\x4c\xd0\xb9\xd8\xed\x82\x6f\x15\x9d\x51\xd4\xa4\x12\x33\xec\xc7\xe7\x75\x9f\x34\xe8\x72\xf4\x22\x5e\xb2\x60\x11\x9b\x51\x83\xf3\xcb\xa6\xfa\xf2\x22\xc8\x94\x02\x82\x86\x02\x24\x20\xac\x87\x5c\x19\x1a\x3f\xbc\x59\xad\xf8\x4e\x78\x94\x6c\xaa\x39\x19\xae\x31\x37\x06\xba\xdb\xf1\xe2\x66\xb7\x1d\xdc\x6c\x63\xbe\x4a\xb7\x3c\x1e\x9c\x32\xb1\x4c\xf9\xea\xe4\x59\xb0\xfd\x12\xec\x3f\xf0\x6d\xcc\x77\xe9\x36\x79\x96\x6f\x0b\xfe\xb5\xa0\xcf\xeb\xf1\x22\x02\x08\xa9\x02\x76\x4a\x20\x64\xdb\xe0\x4b\x9a\x04\x45\xbe\x1b\xdf\xec\xf9\xee\x22\xe1\xdb\xc2\x57\xe4\xcf\x82\x6d\xbc\xcb\xd3\xf8\x2c\x1d\x17\x7c\x2f\x6c\x74\x38\x34\x02\x76\x8a\x21\x78\x13\x14\x2c\x1c\x17\xf9\xc7\x42\x4c\x62\xa0\xf1\x26\x28\xa2\xb5\x51\x8e\x38\x31\x16\x78\x34\x5d\xfe\x67\x2c\xff\xa0\xb3\x14\xc9\x21\xc3\xa1\xf8\xbd\x20\x4b\x49\x47\x5a\xe1\xaf\x59\x1e\x14\x86\x06\x23\x84\x20\xa8\x19\xdd\x29\x2d\xd6\x6b\x49\x80\xb3\xbd\x11\x20\x58\x31\x0c\x09\xcb\xca\x18\x93\xcc\xd9\xca\x5f\x95\x41\x66\xcd\xb0\xbf\xbf\x4d\x05\x3f\x21\xba\x8b\x82\x3d\x3f\x89\xc7\xaf\x67\x6b\x96\x2d\x56\xcb\x05\x5e\xfa\xe1\x8e\x07\x57\xbe\xee\x78\x53\x76\x90\x4e\xc7\x1f\x65\x07\xed\x74\xbc\x2c\x3b\xac\xe5\x21\x5d\x19\xeb\x39\xe3\x48\x23\x98\xa6\x80\x44\xf3\xec\x21\x3b\x1d\x7c\xca\xf3\x93\x2c\xdf\x26\x27\xc2\x08\x06\x48\x6b\xfa\x24\xaa\xa5\x16\x02\xde\xa9\xa8\xca\xb7\x51\x1e\xf3\x3f\x3f\xbc\x32\x02\xd4\x54\xf6\x8e\x5f\x67\x41\xc4\x8d\xb3\xff\x3c\x12\x0a\x0e\x46\xab\x8b\xd1\xaf\xcb\x3b\x7a\x38\x4b\x60\xd0\xa0\x1a\x96\x5e\x61\x84\x55\x34\x09\x9e\x58\x33\x8c\x0e\xc1\xf8\x7a\x97\x17\xb9\x30\x1a\x76\x97\xf0\xe2\xb5\xec\x9e\x35\x36\x09\x4d\xa3\x3f\x2a\x1d\xe0\x76\x97\x16\xbc\xc6\x0f\xea\x75\x0a\x19\x86\xe8\x28\xce\xe9\xa5\x8a\xe6\xa1\x1f\x9a\x26\x0a\xc6\xd7\x37\x45\x37\x8e\x2d\xc2\x25\x78\xe8\x70\x80\xb0\xc9\x5d\x10\xcb\xce\x7a\xae\x50\xe9\x27\x92\x7e\x1b\x18\x21\xf2\x5b\x31\x64\x7c\x7d\xb3\x5f\x1b\x11\xea\x8b\x36\x07\x48\xf7\xcf\x83\xdd\x55\x83\x71\x1d\x62\xf0\x3c\xb8\xbf\xef\x86\xac\x73\x16\xdc\xdf\xe3\x79\xd8\xd7\x13\x1e\x07\x21\x73\x00\x32\xfa\x34\x55\xa7\x43\xe2\x22\x58\x2e\xc2\xe5\x01\x12\x5e\xbc\xa9\xa9\x3c\xa4\xef\xc6\x44\x07\xd8\x04\x57\xbc\x89\xa8\x30\x82\x2b\xfe\x6a\x73\x9d\x19\xa7\x44\xc9\x99\xf0\xe2\x29\xdf\x17\x6f\x82\xfd\xd5\xfb\xa0\x28\xf8\x6e\x6b\x20\xa4\x06\x0b\xbc\xa6\xc0\x51\xbd\xe7\x57\xb1\xd9\x7e\xdc\x89\xf5\x26\x99\x74\x62\x7a\x15\x24\xbb\x83\xbb\x81\xb2\xdb\xaf\xf6\xff\x96\x36\xe2\xe5\x4f\xd1\xe3\x0c\xfb\xfc\x98\x1e\x2f\xc3\x6f\x4d\x6e\xc1\x97\x6a\x81\x25\x7c\xcf\x8b\x9b\xeb\xf7\xf9\x3e\x15\x12\xbf\xdf\xe5\x21\x2f\x75\x82\x01\x6b\xc3\x78\x18\xa7\x3b\xdf\x68\xf2\x13\x83\xf0\xd1\x7e\x37\x9a\xf4\x0d\xba\x88\x2f\x6f\xf6\x45\xb5\x44\x0d\x8c\x4f\xe9\x26\xdd\x26\xbd\x3d\xdf\xae\xf9\xab\xed\x2a\x97\x6b\x07\x9d\x85\x9a\xb3\xc9\x70\xd8\xc6\x55\x1d\x22\x50\x0a\x95\x30\xd6\x76\x84\x32\x7f\xa8\x3d\x23\x1c\x47\x3b\x1e\x14\x5c\xb8\x99\xd1\x21\xff\xc0\x8e\xdf\xde\xb6\x91\xe6\x6a\x13\x5c\xd7\x34\x2a\xfa\x10\xa1\x03\x3c\xa8\xb9\x8e\x2b\xd6\xd1\x7e\x44\xfc\xc9\x9c\x45\x22\xaa\xa2\x74\x65\x9c\x1a\x23\x32\x67\x81\x19\xf5\xba\xa9\x19\x21\x54\x5b\xa1\x1a\xaa\x12\x4f\x31\x2a\x34\xe3\x5e\x17\x16\x60\xa3\xed\xa6\x66\xb4\x5c\x84\x66\xbc\x64\xd1\x9c\xe1\xe1\xd0\x9d\xb3\x68\x38\x34\x30\x63\xf1\xfd\xbd\xcb\x58\x8c\xee\xef\xe3\xb2\x27\x56\x3d\x91\xec\x89\xd0\xfd\x7d\x34\x67\x74\x38\xb4\xe5\x98\xb8\x7c\x8e\x9f\x9c\xe2\xd9\x29\x41\xd2\xf9\x3b\x3e\xda\xf4\xeb\x92\xfd\x80\x61\x50\x31\x14\xfb\xde\x5c\xc9\xdf\x75\x7a\x0c\x11\xf2\x95\xac\x2b\xe1\xfa\xaf\xf3\x7d\xf1\x3e\x4f\xb7\x2a\xa4\x22\x5f\xb3\x15\xcc\x63\xb5\x67\xc7\x10\xb2\x08\x1d\xca\x7d\xe1\x00\x6a\xc1\xdf\xe4\x5f\x52\xfe\x2c\x4b\xaf\x5b\x8b\x20\x02\x84\xa2\x1d\x68\xc3\x78\xb1\xb9\x2e\xbe\x55\xc8\x86\xc0\x00\xce\x88\x5f\x71\x65\xd4\x3e\xbb\x62\xd8\x5f\x35\x7d\xb6\xcc\x61\xe4\x0e\x5d\x62\x25\x6c\xf5\x98\x83\xd8\xaa\xd7\x2d\xdc\xc5\x6a\x59\xa2\xaf\xcb\x0d\x3d\x65\xeb\xc7\x1c\x2e\x59\x07\x6f\xb1\x5e\xfa\x97\xc3\xa1\x11\x8f\x43\x9e\xa4\xdb\x5f\xd3\x2c\x33\x30\x10\x8c\x11\xc4\xe3\x4d\xfe\x85\x7f\xca\x8d\x14\x12\xd1\xca\xd2\xad\x6c\x99\xfc\xb8\x6d\xf2\x26\xa4\x6c\xf3\x6d\x2c\x09\xa2\x4a\x69\xb1\xb6\xe1\x96\x9b\xf6\xaf\x9f\xe7\x07\x47\x41\x6b\xe4\xf9\x81\x69\xa2\x86\x43\x36\x76\x06\x77\x59\x3a\x65\x0b\xc8\x44\xba\xfa\x88\xa2\x46\xa1\xe5\xf9\x61\x1f\xe9\xb0\x9f\xb4\x2b\x36\x9d\x2e\x69\x09\x14\xa4\xc3\x47\xb4\xeb\x98\xad\xe8\xd4\x2f\x9c\xb4\x37\x8d\x51\x0e\xeb\x06\x0d\x24\x0c\xd8\x0f\xab\x94\x59\xf2\xd7\x9f\x93\x2b\xf3\xd6\xe6\x26\x12\x00\xae\x32\xf4\x74\x65\xf4\x08\x24\x03\x7d\xc3\x88\x46\xd4\xa7\x73\x96\xf8\x49\x83\xfe\x5a\x43\x95\x05\xb5\x87\x9b\xc9\x72\xc1\xcd\xf5\x92\x8d\x28\x63\xc9\xfd\xbd\xfa\x2d\x1a\x6b\xd9\x58\xdf\xdf\x63\xc6\x12\x59\x28\xac\x95\xdf\x1e\xca\x75\xaf\xa4\x7b\x20\xeb\x91\x8a\x79\xfa\xec\x65\x23\x02\x1f\xa9\x45\xc8\x4e\x2a\xa7\x56\x52\x9f\x06\xc3\x21\x61\xcc\x20\xc3\x70\x3e\x8f\x74\x32\x53\x72\xfc\x26\x28\xd6\xe3\x55\x96\xe7\x3b\x23\x3a\xb3\xd0\x72\x11\x3d\xb2\xcc\x63\x03\x18\x59\x4b\x16\x1f\x9a\x1a\xfe\xaf\x66\x79\x90\xe8\xd1\xfc\x2c\x6e\xea\x43\x6c\x4a\x0f\xc6\xef\xfe\x8d\xe3\xfc\xdc\xba\x0f\x21\x6e\x69\x4b\xee\x6d\x32\xa4\x60\x9f\x38\x73\x2e\x37\xf8\x3b\xb5\xc2\x35\xdf\xf1\x7c\xce\x91\xef\xce\xf9\x93\x16\xef\x7c\xb9\xf0\x96\x2c\x99\x79\x47\x1d\x26\xd1\x5d\x2d\xf0\x91\x9c\xc4\x31\x35\x8d\x43\x33\xef\xf8\x11\x23\x47\xf3\x79\xcb\x63\xda\x7c\x44\x04\x03\xd3\x1e\x5c\xe2\x88\x5e\x93\x1c\x31\x58\xf5\x09\x8e\xbe\xcf\xba\x27\xf9\x3e\x0d\x44\x9e\x77\xdd\x4e\x92\x8f\x36\x53\x88\xd9\xb1\xe8\xc0\xd9\x04\x12\x86\x61\xdd\xd3\xe9\xaf\xe7\xd8\x5f\x8f\x18\x95\xae\xe5\x32\xb6\x1e\x0e\xd7\xa3\x91\xef\xd7\x84\x53\x86\x7d\x3a\x4f\xfd\x54\xed\xd1\xfd\x1e\xbb\x1e\xa5\x4b\xa5\xc5\x4b\x76\x4a\xfc\xa4\x51\x8f\x1b\x97\x4c\xe9\x34\x58\x24\xcb\xb9\xd0\xab\xda\xd6\xae\x94\x7d\x88\x9d\xd2\x08\x21\x86\xf5\x28\x45\xfe\x95\xc4\x3f\xbd\x44\xd0\x37\x03\xbb\x04\x3e\x1a\xc1\x88\x30\x26\x52\x9c\xc4\x34\x85\x70\x48\x14\x64\xb1\xc9\x22\xc0\xf3\xde\x1c\x20\x46\x77\xf1\x88\x45\x10\xb1\x51\xa4\xea\xbc\xc3\x41\x56\x20\xef\x2f\x9e\x63\x46\x2d\x57\x3d\x12\x46\x26\xd0\xcc\x93\x58\x33\xa1\x86\xb8\x56\x09\x67\x97\x82\xf5\x0f\x1f\x9f\x66\x79\x74\xb5\x57\x39\x5b\x22\xd3\xdd\x2b\xbd\xe1\xc5\x3d\x5b\x5c\x2c\xb6\xb3\x44\x56\x45\xa9\x3c\x8d\x03\x1b\x41\xd9\xae\x0a\x34\x03\xc1\xaa\x6e\xbd\xda\x3e\x4d\x8b\x7d\x89\x1f\x20\x04\xe9\x58\xd6\x65\x46\x82\x2a\x5b\xce\xe4\xea\x8a\x69\x79\x73\xda\xcc\x64\x7c\xb1\x5e\xd6\x87\x11\x22\xe2\x26\x47\xb4\xd1\xdc\x7b\x9c\x1d\x97\xb1\xa2\x2e\x3d\x51\xd4\x4e\xf2\x2f\x7c\xb7\xca\xf2\xdb\xf1\x89\x31\x30\x7b\x28\x98\x83\xf9\xc0\xf4\x1e\x67\xe6\x00\x0d\xd4\x56\xd6\x87\x64\x9f\x33\xef\x71\x36\x1c\x2a\x91\x31\xd8\xc8\xc7\xa7\xac\x07\xf3\x91\xe7\x23\x89\xf4\x34\x2d\x8c\x53\xa2\x28\x0a\x9b\x7c\x80\x7f\x41\x56\xd7\xe7\x12\x43\x90\x57\xab\x0b\x9e\xd0\xf0\x77\x47\x34\xd0\x89\x28\x4d\xab\xc2\x5a\x19\xc2\xd3\x6f\x05\xdf\x1b\x09\x70\x74\x80\x16\x8c\x3d\xe4\x87\x58\x9f\x93\x62\x6d\x12\xaa\x02\x2a\xcb\x73\x04\xeb\x5e\xe8\x25\xc3\xfe\xe5\x79\xd9\xf6\x2f\x4b\xb3\xb9\x62\xe1\xe2\xb2\xb1\x86\x90\x29\x40\x7d\xe6\x34\xba\xf2\x63\x26\x83\xf8\x26\xf8\x6a\xc4\x70\x25\xa2\x6c\xd5\xe6\x90\x21\x48\x16\x97\xcd\x6a\xec\xaa\x4e\x37\x36\x0c\xfb\x9b\x73\xd1\x5f\xce\xbc\x31\x4d\x24\xda\x8b\xcd\x92\x51\xc7\x19\x06\xfa\xb8\x6a\xb1\x31\xa3\xa5\x1f\x99\xec\x4a\xba\xef\x56\xb9\xef\x8b\x46\xf0\x7f\x9f\x67\xdf\xb6\xf9\x26\x0d\x32\x23\x43\x90\xcb\x09\x53\x43\xd0\x82\x6d\xd3\xbe\x47\x04\xc1\x35\xcb\x85\x49\x1b\x5b\xe4\xaf\xdb\xcc\x75\x51\x3b\xac\xae\x3b\xac\x4a\x25\xfd\xcd\x36\xe6\x75\x6b\x5c\x13\x6d\xad\xa5\xf9\x7b\xce\xf0\x13\x89\x66\xfc\x8d\x66\xf8\x50\xf9\xcf\x8e\x61\x50\xd4\xc3\x26\xe9\x9d\xc9\xc2\xc5\xa6\xa9\xea\x8a\x97\x66\xad\xbc\x43\x50\x68\x02\xf1\x7c\x23\x47\x96\x68\x3d\x8b\xda\x52\xf6\x70\x68\xec\x17\x85\x69\x2e\x99\xd6\x78\x5b\x5a\xfe\x33\xe4\xd6\x7d\xe4\xd6\x25\x39\x6d\xcd\xfb\x43\xe3\xbc\xf4\x4e\x5e\x01\xbc\xfd\xf3\xcd\xd3\x17\x1f\x66\x04\x64\xeb\xe2\xf5\xfb\x97\x17\x02\x36\xa3\xd0\xbe\x21\x98\xd9\x0a\xf0\xfb\xc5\xdb\x7f\xbe\x9a\x79\x07\x88\xd9\xdd\x6b\x31\x6c\x86\xe1\x8f\x99\x05\x2f\x67\xf4\x00\x9c\xdd\xbd\xbf\xf8\xf4\xe9\xc5\x87\xb7\x18\xe3\x19\x86\xaa\x41\x66\xa4\x6a\x10\x3c\xa3\x75\x83\xcc\xac\xb2\x41\x30\x9e\xd9\x75\x83\xcc\x9c\xaa\x41\xf0\xcc\xad\x1b\x64\x36\x39\xc0\xaa\x9a\xeb\xf3\xfb\x77\x1f\x5f\x7d\x7a\xf5\xee\xed\xe7\x4f\x17\x4f\x5f\xbf\x98\x2d\x16\x4b\x58\xb8\x40\x3c\xf9\x87\x52\xf5\xc7\x95\x7f\x2c\xac\xfe\xd8\xba\x0f\x2c\x8d\x65\x83\x5d\x22\x82\xad\x70\xa9\x07\x8e\x46\xc7\xe0\xa8\x11\x16\x05\xc7\xd3\x24\xc0\x6d\x8c\x00\xd7\xad\x1a\x1e\x4c\x70\xd9\x70\x30\x4c\xec\x9a\x08\x4c\xbc\xaa\xe1\x82\x47\xab\x86\x07\x9e\x5b\xd3\x85\x29\xae\x59\x80\x09\x85\xa9\xdd\x22\x08\x53\xaf\x45\x13\x08\xa6\xd5\x00\x1b\x3c\x51\x1d\xb9\x35\xc3\xe0\xd9\x40\x08\x6e\x4d\x06\x84\xd8\xad\x09\x81\x94\x1a\xab\x27\x01\x42\xe9\xd1\x44\x40\x68\x25\xab\x43\x15\xd0\x06\x62\xe1\x96\x64\x40\xb0\x07\xc4\xaa\xe7\xc0\x6a\x52\x0a\xc4\xf2\x8e\x38\x01\xa2\xd5\xdf\xe4\x06\x88\xed\xf6\xce\x0e\x44\x2f\x0c\xb5\x25\xab\xae\xee\xf0\x80\xe8\x75\x6a\xea\x01\x88\x45\x81\x94\xcb\xd6\xd0\x07\x10\xcb\x05\x52\xaf\xa2\x18\x41\x75\x87\x07\xc4\x75\x7b\xd9\x04\x32\xc1\xcb\x25\xfc\x46\x9c\x19\xb1\x2c\x07\x7e\x23\xde\x6c\x32\x9d\x58\x02\xf2\xf9\xcd\xc5\xc7\xdf\x67\x94\x38\x94\x42\x3b\xeb\x7d\xa0\x94\x08\xce\xcf\x09\xf6\xcb\x14\xf9\x79\x9a\xa4\x85\x11\xa2\x51\x1b\xb0\x1a\xff\x46\x1c\x34\x67\xd8\x47\xe1\x5f\x4c\xb6\xce\xcf\x7f\x6a\x8c\x76\x7c\x43\x4e\x73\x1f\xa2\xbf\x24\x58\x72\x79\x80\x6e\x11\xf3\x1d\x16\xe9\xcf\xb0\xe8\xb5\x58\xf4\x7e\x8a\x45\xaf\x8a\x4d\x72\x9a\xfb\xb0\x64\x4b\xa2\x3c\x74\xea\x2c\x12\x86\xc0\x47\xa1\x69\x42\x30\x9f\xcf\x19\xf1\xeb\xf3\x8e\xe3\x9a\xb5\x45\x45\x23\xae\xc6\xfd\xc1\x63\x11\x8c\x88\x3e\xbc\x0d\xf6\x57\x47\x87\x25\xfa\xb6\x21\xd0\xb7\x0d\x7c\xdc\x08\x77\x9a\x32\x66\xcc\x08\xcd\x08\x3d\xa2\x7e\x17\x87\x34\x70\xc2\xe3\x7e\xd2\xa4\x11\x3d\xb2\x8e\xfa\xc9\xd1\x1c\x5d\x1c\xd2\xe6\xa3\x51\xd3\x85\x67\x14\x99\x9d\x1a\xef\x98\x47\xd2\xe6\xf1\x71\xf4\x88\x9a\xe2\xf7\xd1\x3c\xa4\x2d\x6f\x8d\xd8\x43\xb3\xc3\xb7\xc0\x32\xb5\x8a\x04\x76\xcc\x57\xc1\x4d\x56\xcc\x8e\x52\xcf\x30\x88\x4f\x36\x8d\x13\xb4\x81\x19\xa0\x83\x5c\x9b\xfe\x74\xe3\x01\x6b\x51\xf9\xc7\x82\x2c\x01\xab\xb2\x3c\xd0\xf5\x72\xc8\xc2\xf1\xe6\x26\x2b\xd2\xeb\xec\x9b\x51\x62\xc9\x3c\xf1\xeb\xb5\x11\x21\x81\x8f\xda\x86\xd5\x4c\x1f\x8f\x2f\x16\xc2\x39\x23\xc3\x21\xc1\xf3\x10\x75\xec\x44\x5f\xb7\xeb\xbd\x56\x93\x24\xd8\x6f\x76\xd6\x5b\xaf\xee\x9f\xb6\xba\xeb\x8d\x58\x77\x7b\xad\x6e\xb5\x2d\x57\x5d\x0f\xea\x54\xd4\x0f\x4a\x91\x3c\xdb\xf3\x93\x74\x65\xd0\xc9\xcf\xf2\x4b\xbf\xcf\x2f\x21\xdf\x67\x98\xb8\x0f\x73\x4c\xf0\xcf\xb2\x7c\x27\x0f\x88\x6d\x32\x0f\xd1\x71\xb1\x52\x7c\xbb\x16\xa8\x21\xf2\x7f\x4a\x20\xfb\x07\x02\x59\xff\x1f\x02\x7d\xc7\xae\x6b\x81\x94\x35\x57\x47\xba\x0f\x05\xe0\x71\xfb\x2e\xc9\x90\x66\x2c\xca\x0b\x3f\xd4\xef\x5c\x34\x8f\x33\xc2\xf2\x34\xa3\x71\x4e\x0b\x09\x0b\xc6\xea\x42\xcc\x88\x81\x8b\xea\x63\x44\x7c\x52\x1e\x9d\x49\x9d\xe2\x79\x6c\xae\xef\xef\x63\x73\x3d\x67\x61\x7d\xc6\x9e\x6a\x4c\x55\xfa\xe3\x39\x37\xd3\xfb\x7b\x6e\xa6\x73\x16\xde\xdf\x1b\xf8\x54\x9e\xa4\x9d\xb2\x14\x0d\x87\x09\x6b\xcc\x62\xae\x81\x9b\x02\xba\x32\x4d\x7f\x35\x77\x86\x43\x23\x32\x99\x65\xae\x46\x4e\x5d\xb2\x4a\x19\x46\xa4\x4f\x8a\x11\x69\x9e\xca\x88\x9c\xb7\x25\xc1\x70\x78\x29\xa2\x7f\x3d\x1d\xe9\x01\x02\x37\x49\x2f\x66\x05\x36\x30\x63\x97\xf7\xf7\x36\x63\x97\x48\x73\xd8\xe1\xae\x97\x37\x57\xf3\xd6\x61\xe9\xf4\x68\xea\x16\x80\x76\x01\x56\x17\x60\x1f\x11\x71\xba\x28\xae\xe6\xd3\xc6\xed\xdb\xb3\x72\xd9\xdb\xaa\x75\x35\xfb\x0f\x33\xaa\x15\xd7\x00\xd0\x2e\xc0\xea\x02\xec\x23\x22\x4e\x17\xc5\x95\x80\x2e\xa3\x57\xaa\x24\xee\x67\xb6\x9f\xd5\x2b\xd3\xf4\xd5\xe9\x86\xdc\xbd\x82\x70\x6f\x10\x8c\x1f\x5f\x9d\x85\x67\xe1\xc8\xc1\xe8\xcc\xa9\xae\xd6\x4d\x46\xf0\xe3\x4c\x38\x15\xbb\x4b\xb2\x3c\x69\xf9\x53\xba\x32\xc8\x3c\x38\x8e\x19\x02\xd1\x18\x98\x81\x3a\xb4\xd0\xa4\x92\xf1\xeb\x77\xbf\x95\x19\x81\xcc\x07\xbe\x5e\x1f\x79\xa7\x8f\xe7\x81\x8f\x02\x53\xd4\xc7\xea\x6c\x22\x98\x33\xea\xb8\x3e\x0a\x46\x12\x56\x11\x7b\xf1\xaf\xf7\x0d\x62\x55\x6b\x56\x57\x8f\xd4\x71\x11\x54\x73\x76\x3a\x0e\xf2\x58\xc7\x9b\x2b\x67\x6d\x92\x5b\x2f\x19\x39\x3f\x5f\xfb\xf5\x89\xb8\xe7\x53\xc7\xed\xc7\x6c\x35\x47\xf6\xf2\xaf\x36\xc0\xe9\x02\xdc\x2e\xc0\x5b\x36\x26\xc2\x3e\x75\x9c\x6a\xa2\x5a\x5d\xed\x49\x97\x6c\xed\xa7\x9d\x37\x10\xfa\xf2\xb1\xea\x1d\x1b\xa5\xed\x1f\xbc\xa5\xb0\xbd\xd9\x54\xaf\x27\x94\x3b\xf8\x77\x76\xff\xc6\xe5\x73\xe3\x70\xc0\x0c\xba\xa7\x11\xea\xbe\xa2\x8b\x27\x73\x85\xee\x0b\x42\xcd\x7e\x61\xb4\xe1\x22\x32\xe3\xe5\x5f\x4c\x67\x0f\xc9\x58\x9a\x55\x49\xca\x88\x10\x32\x35\x4c\x8e\x35\x62\x54\xe7\x16\x2a\xf5\x08\x01\xa3\x03\x6c\xf2\xb8\x6b\xb5\x5d\x7e\x46\xad\xd9\xcf\x31\x6a\x68\xa6\x71\x7f\xd4\x65\x01\x23\x34\x6a\xb1\x80\x91\x90\xf8\x61\xfd\x20\x68\x5c\xf2\x77\xe5\x8d\x16\xf1\x92\x55\xb4\xe3\xe3\x37\xa8\xfa\x06\x74\xd5\x53\xa9\xa2\xf1\x2a\x85\x52\x46\x04\x18\xc9\x83\x21\x99\xf1\x5d\x8e\x3f\x7c\xfc\xfc\xf4\xf5\xbb\x67\xbf\x2b\xbb\x62\x8b\x05\x11\xf5\x1a\x99\x2e\x41\x3f\xb9\xd5\x93\x55\x3e\xa9\x4e\xdb\x56\xc5\xbe\x7c\xa2\x5e\xf5\x44\xcb\x27\x3d\x74\x82\xc1\x71\xca\x27\x5b\x8c\xa0\x60\x39\x40\x26\xd5\x93\x22\x4c\x30\x06\x0f\x4b\xa0\x83\xc1\xa2\xe5\x13\x15\x43\x6c\xa0\x8e\x9e\x97\x58\xb6\xa8\x80\x65\xb7\x3b\x01\xdb\x52\x74\x2c\x20\x0e\x50\x51\xe5\xca\x79\x15\x84\x68\x88\x22\xe6\xb9\xe0\x7a\x92\x98\x6d\x01\x9d\x94\x4f\x52\x58\xf5\xe4\x48\xbc\xa9\xa7\x0e\x13\x6c\xb0\xa7\x60\x11\x45\x8d\x02\xb1\xc1\x56\xf3\xc8\x3e\x6b\x0a\xc4\x02\x02\x36\x06\xa2\xa4\x22\x94\xc0\x54\x89\xe5\x62\xb0\x3c\xa0\xe0\x12\xb0\x34\x79\x0c\x44\x40\x6c\x52\x4d\x28\x06\x6a\x88\x9a\x98\xd8\xa2\x16\x16\xec\x5b\xa2\x32\xb6\x5c\xa0\xe0\x4c\xc1\x52\xac\xca\x92\x5a\xb0\x30\x51\xca\x53\x10\xaa\x21\x56\x2d\x22\x50\xf0\x26\xe0\xaa\x59\xdc\xa9\x94\xac\x52\xbe\xab\x44\x16\xf3\xda\x40\x71\x05\x71\x14\x44\xce\x2e\x14\x4c\xc0\x23\x52\xdf\x1e\x16\xab\x60\x83\x47\xc0\x21\xb2\x53\x2c\x8a\x98\xd6\x21\x40\x2d\xc9\xac\x62\xc4\x6b\x30\x42\x88\x0b\x53\x0a\xe2\x61\x02\x53\x4b\x4e\x73\x2c\x92\xed\x02\xc5\xe0\x82\x3d\x01\x2a\x68\x4f\xc0\xd6\x7a\xb6\x2b\x3d\x13\xa1\x72\x2c\xf0\x3d\x35\x12\x88\x52\xaf\x84\x48\x21\x04\xbe\xa3\x28\x90\x72\xe1\xed\x6a\xe1\x2d\x20\xb6\x03\x84\x38\x40\x1a\x1a\xb6\xc1\x95\x4b\xe0\x80\xeb\x80\x2d\x87\x12\xad\x62\xa7\x52\xb1\x06\x51\x0d\x12\x62\x38\x40\xf0\x54\xe8\x97\xc8\xf3\x0c\xcf\x93\x30\x49\x43\xd0\x72\xd5\x69\x97\x03\x8e\x0d\xd4\x86\x09\x38\x0e\x50\xa7\x41\x4a\x91\xa0\xd2\xca\x08\x10\x6a\xc1\x74\x2a\x25\x9f\x58\x42\x08\x0b\x26\xb6\x3a\x26\x23\xce\xd1\x4a\x49\x0c\x21\x87\x25\x34\xa7\xfd\x8b\x08\x17\xc2\x13\x70\xd4\xa1\x8b\xf4\x0c\x82\x15\x19\xb1\xee\x0e\xd8\x52\x14\xbd\x6c\xc4\xa9\xd6\x8d\x6a\x6d\x93\x49\xa5\x6e\x41\x1e\x03\xa1\x58\xf0\xe6\x08\xfe\x84\x66\xa6\xda\x8a\xec\xca\x8a\xc8\xa4\x24\x77\x4c\x6d\x5a\x51\x13\x9a\x17\x6a\x12\x23\xe5\xf9\x8e\x74\x14\x4b\x51\x11\x8b\x34\x21\x60\x3b\x8a\x9c\x34\x01\xb1\x90\x9e\x0a\x21\xd3\xd2\xc1\xdc\xca\xc3\xac\x5e\x59\x2d\x19\x05\x84\x1e\x84\xe9\x4b\xed\x93\x52\xfd\x4e\xad\x7e\x47\x5b\x39\xc1\x4d\x33\x97\x6c\xb8\x92\x3d\x61\x22\x13\xc5\x4b\x45\xa7\x94\xd2\xad\xa4\x14\xd2\x49\x23\x91\x46\xab\x83\x18\x11\xac\x0a\x71\x80\x08\x5e\x89\x1e\x5b\xae\xe4\x44\x73\x23\x4c\x4b\xb3\x63\xd5\x4e\x6b\x97\x8a\x16\x52\x39\x54\x1f\x0c\xda\x6a\xe1\x84\x42\x27\x2e\xd8\x9e\xb2\x20\x4d\xc7\xae\xc5\x72\x4b\x93\xb0\x2b\x93\x70\x81\x88\x81\x42\xa7\x40\x6c\xaf\x3a\x7d\x54\x06\x26\x08\x96\x16\x46\x7a\x18\xc3\x5a\x3e\x5a\xc9\xe7\xa9\x63\x3e\x2c\xd5\xd4\x70\x46\xcd\xa0\x55\x31\x58\xca\x49\x69\x45\x4e\xc4\x89\x23\x93\xc5\xa5\x31\x88\xf0\x20\x56\x45\x1a\x0b\x99\x6a\x9b\xb5\x2b\x9b\x55\x87\xb4\x2d\xfd\x5b\x9a\x8e\xb0\x94\x9a\x3f\xa5\x36\xc1\x9f\x63\x09\x9f\x52\x33\x77\x3d\xca\x03\xc7\x02\x6a\xe9\x03\x49\xb9\xaf\x90\x92\x3f\xea\x55\xfc\x59\x95\xfe\x24\xa7\xa5\x02\x2d\x4d\x8f\xd6\x04\x6d\x2d\xb0\x45\x9a\x6e\xae\x08\x5a\xa4\x22\x38\x29\xc3\x8e\x34\x90\x89\xb6\x33\x4a\x34\xc1\xda\x50\x88\x66\xd0\x9a\xd4\x0c\x4e\x4b\x06\xdd\x8a\x9e\x53\x07\x34\xdc\x88\x68\x42\x81\x6a\x49\x70\x6d\x33\xa5\x27\xd0\xda\x15\x68\x19\x46\xa8\x53\xaf\x49\x1d\x24\xad\x06\x49\xaa\x97\x84\x4e\xab\x35\xb1\x69\x69\x34\x3d\x04\x6b\x25\x0a\xed\x29\x82\xcd\x70\x24\x74\x57\xc6\x23\x5c\x2a\xaf\xe1\xa4\xa5\xb0\x96\xd3\x43\xa8\x15\xbe\x4b\x33\x16\x41\xa3\x32\x97\x69\xc9\xda\xf4\x78\x3d\x6c\xb7\x4f\x58\xb7\x97\x64\xcd\xa5\x6d\x1f\x05\x72\xa7\x8c\x00\xa4\xb2\x40\x42\x2b\x1f\x9e\x34\x7c\x98\x50\xbd\x20\xd4\xad\x16\xc4\x9a\x1e\x3b\x71\xe5\x24\x36\x69\x3a\xb1\xa6\x28\x42\x6a\x45\xd2\xd5\x14\xad\x3a\x2c\xd8\x6e\x49\x11\xd7\x14\x35\x41\xd7\x6e\xe9\xb1\xcf\x4d\x4a\xaf\x23\xb5\xdb\xd9\xd3\x1e\x8a\xf6\xb1\x1e\x2b\xc6\x44\x66\x53\x93\x24\xda\x41\x44\xce\x54\x91\xf4\x8e\xc5\xb6\x4b\x2e\x2d\x5a\x91\x14\x1b\x4f\x4f\xf0\xb2\xb1\x96\x7b\x52\x8b\x6d\x1d\x47\x1b\x11\xdb\x95\xdc\x93\x5a\xee\x69\x49\x47\x2e\xb6\x08\xd4\x32\x8f\x2c\xe3\x97\x45\xea\xb5\xa9\xfc\xb9\xb1\x36\x15\xc9\x72\x6d\x96\xd0\x7a\x39\xa1\x73\x4d\xad\x6e\x00\x15\xc6\x5e\x62\x7c\x0a\xc2\x8c\xcb\x4e\xbf\xf1\x19\x46\x74\x5c\x2f\x87\x41\x7c\xb2\xdb\x9f\x84\x62\xd0\xc9\xff\x39\xa9\xdf\x79\x9a\xc9\x22\xfa\xec\xe8\x3d\xa0\xd9\xa0\xfd\x85\x45\xa4\x4b\xb7\x33\x0b\x38\x5b\x2c\x61\x25\x6f\x4c\x57\x9d\x97\x06\xa3\x85\xf5\x78\x65\xe2\x25\xac\xf5\x23\x59\x42\xaa\x1f\xe9\x12\xae\x18\xf6\x93\xf9\x95\x7f\x65\x9a\x88\xab\xf7\xc0\x05\x8f\x97\xc6\x1a\xd2\xba\xb2\xe2\x07\x38\x92\xb1\xa3\x89\x9e\xef\x07\xf4\xe0\x6e\xd5\xb1\xb0\x1f\x1b\xc1\x88\x20\x13\x2f\xeb\x4f\x0a\x7e\x84\x4b\x96\xf5\x57\x06\x3f\xc2\xa5\xcb\xfa\xc3\x83\x1f\xe1\x5a\xcb\xea\x7c\x51\xa3\xaa\x25\x3b\x1c\xe0\xea\x7b\xe5\xb6\xaa\x0d\x1b\xf7\x00\xc1\x59\x7d\x05\xa3\x5e\xd0\x69\x7c\x9b\xb2\x08\x97\xf3\xf9\x7c\x32\x0a\x1e\x79\xe8\x00\xd7\x37\xc5\x83\x6f\x1d\x61\x3f\xd4\xa7\xea\xea\x4d\x7f\xf5\xd2\x86\x7e\xe3\x67\x3e\x9f\x87\xa3\x68\x44\x10\xfa\xce\x29\x7a\xbb\xc2\x2f\xab\x7b\x45\xe8\xfb\x22\x34\x06\x08\x61\x1a\xfc\x6b\xe8\x39\x0b\x87\x4d\xb1\x94\xbd\x60\x04\x41\xf9\xc6\x64\x25\xee\x3d\x23\xd4\x9b\xcf\xe7\x0d\x9a\x8f\x3c\xd4\xfc\x40\xc7\x34\x0f\x07\x7d\x20\xb5\x50\x61\x5f\xa6\x88\xc2\x31\xa9\x08\xa1\x54\xa7\x81\x8e\x25\x32\x4d\x01\x13\xad\x89\x07\xae\x8c\x1f\xaa\x18\xc5\x2e\x78\xf2\x4a\x54\xa5\xa9\xb2\x56\x74\x45\x3c\x72\xd4\x76\x68\xcb\x78\x25\xca\x24\xb5\xbb\x52\x15\xc3\xb0\x07\x9e\x2c\xe2\x2c\x51\xa6\x61\x20\x16\x56\x37\xc1\x74\x42\x80\x8a\x0d\x43\x44\x63\x19\x39\x2c\x4a\x80\x8a\xd6\x44\x24\x3f\x92\x3d\x77\x02\xd4\x9b\x00\xc5\x02\x4f\x85\x36\x07\x2c\x8b\x00\xb5\x25\x9e\x80\xc8\xe2\x87\x02\x75\x3c\x20\xf2\xce\xd9\x11\xa1\x85\x50\xa0\xa2\x4c\x92\xe9\xbd\xe3\x89\x6c\x4e\xd4\xbe\x02\x4f\x96\x66\x62\xff\xc1\xa2\xd0\x13\x25\xb6\x80\x4c\x88\x07\x8e\x28\x7f\xa6\x22\xed\x90\x90\x29\x05\x57\x84\x67\xa1\x14\x55\x15\x39\x1e\xb8\xa2\x12\xf1\x28\x58\xf2\x26\x7c\x2a\xc2\xbc\x48\xf7\xf0\x14\x6c\x2c\x83\x34\xc6\x16\x4c\x26\x53\x70\x44\xe9\x22\x6b\x54\x82\xa7\x04\x3c\x67\x02\xae\xd8\x34\x5d\x55\x12\x4d\x08\x4c\x09\x01\xd7\x15\x89\xbe\x2a\xb0\x26\xa2\x64\x99\xc0\x44\xe4\x16\x96\x0c\xbb\x42\x01\x04\x3b\x22\x49\x20\xe0\xc8\x6a\x8f\xd8\xae\xd8\x61\xa9\x03\x1e\x76\xc0\xd5\x39\x38\x15\x81\x78\x8a\xc1\x73\x3d\x70\xd5\x8a\xb8\x02\x46\x5d\x1b\xa6\xd8\x03\x57\xea\x9c\x4c\x44\xbe\x69\x4d\xc4\x12\x88\x0c\x44\xee\xa5\x9e\xac\x02\xe4\x5a\x59\x18\x26\xf2\x1a\x9f\x4c\x45\xdb\xb1\x04\x55\x51\x7f\x4a\x4c\x8a\x5d\x0f\x14\x59\xe2\x7a\xe0\xa9\x65\x24\x9e\x07\x64\x42\xe5\x76\xe5\xc1\x54\xce\x4d\x2d\xb1\x60\x1e\x9e\x02\xa1\x9e\x05\x53\x4f\x6e\x88\xb6\x25\x2a\x74\x22\x0b\x2b\x22\xc4\x92\x07\x00\x8e\x2b\x6a\x31\x4f\x6c\x26\x54\xa4\xc0\x52\x48\xea\x4e\xa7\x40\xf1\x54\x40\xc5\x2f\x22\xf5\x48\x05\x45\xaa\x8c\x66\x22\x68\x4b\xb3\xa1\x53\x99\xdb\x09\xe2\xae\xa0\x45\x27\xd6\x72\x09\x39\x6b\xb8\xa9\x7e\x39\xb8\x15\x08\xa4\x7f\x7c\xe6\x59\xf9\xe1\xdb\xe7\x75\xf1\xee\x5a\x74\xb3\xf0\x50\x5d\xf0\xd6\x71\x69\x1c\xef\x82\x5b\xd6\x3a\xb0\x2b\x3f\x8a\x4a\x9a\x1b\x54\x9c\x47\x37\x1b\xbe\x2d\xca\x97\xd3\x33\x2e\x5a\x6f\x3f\x1a\x83\x75\x51\x5c\xcf\xce\xce\x6e\x6f\x6f\xc7\xb7\xd6\x38\xdf\x25\x67\x14\x63\x7c\xb6\xff\x92\x0c\x20\x68\xec\x36\x27\xe9\xf6\x24\x44\xe1\x78\x1d\xec\xdf\xdd\x6e\xdf\xef\xf2\x6b\xbe\x2b\xbe\x19\x31\x1a\x0e\xa3\xf1\x9e\x17\x17\x45\xb1\x4b\xc3\x9b\x82\x1b\x31\x84\x8b\x78\xd9\xf8\x4e\x4b\xc5\x99\xb6\x38\xe5\xe7\x4e\x9f\x79\x06\x71\xcf\xc5\x8c\xdf\xbc\x71\x1d\xdf\xa6\x71\xb1\x3e\x8b\x11\xb4\xa0\x6b\x9e\x26\xeb\x42\x80\x25\xa9\x28\xe3\xc1\xce\x50\x2f\x43\xae\x59\x62\x0c\xa4\x0c\x77\x5f\x52\x7e\xfb\x34\xff\x3a\x1b\xe0\x13\x7c\x32\x30\xf5\x17\x61\x31\x32\x07\xcd\x16\xc8\x29\x66\x03\x82\xf1\xa3\x01\x28\xca\x65\x6b\x95\x66\xd9\x2c\x1c\x47\x79\x96\xef\x5e\x8b\x8e\x03\xf2\xd7\x2d\x99\xbf\xa3\xc8\xaf\x9b\x6c\xbb\x3f\x1b\xc0\x40\x3e\xcc\xbe\x66\xe9\xf6\x6a\x00\x3d\xd8\x64\x3a\x9d\x9e\xa9\x6e\x04\xd1\x38\xb8\xbe\xe6\xdb\xf8\xd9\x3a\xcd\x62\x63\x8d\x60\xdd\x02\x24\xc6\x40\x64\x05\x03\xb8\x6b\xf2\xf6\x3c\xd8\x5d\x55\x72\x34\x84\x18\x40\x1a\xcf\x06\x05\xdf\x5c\x67\x41\xc1\x07\x07\x54\x2f\x6b\x2a\x53\x06\x75\x23\xd5\x7c\x2b\x2a\x9e\x5f\xca\xd7\xa1\xd2\x95\x51\xdd\x22\xa4\x70\x89\xca\x77\xe8\x12\x63\x70\xb3\xe7\x03\xb8\xfb\x3a\xd3\x2a\x4c\x11\x7c\x2b\x9f\x2f\xd1\x01\xf9\x57\x3f\xa1\xa1\x86\xcc\x30\x58\xef\xf8\x6a\x00\x83\x7f\x54\x8c\x76\xa5\xbe\x42\x87\x03\x34\x8d\x5f\xae\x38\xeb\xbc\x72\xef\x97\x76\x25\x4c\x55\x0e\x7c\x9b\xc7\x7c\x6f\x20\x1f\x55\x3d\x3b\xbe\xc9\xbf\x70\x45\xb5\x02\x66\xc1\xbe\x90\x20\x74\x80\xe0\x60\x20\xb8\x66\xd2\x84\x18\xab\xdd\xa7\x7c\xd0\x0e\x34\x2e\x82\xe4\x6d\xb0\xe1\xe3\x22\x7f\x9d\xdf\xf2\xdd\xb3\x60\xcf\x0d\x04\x7f\xb3\xeb\x27\xf9\x6c\x63\xa0\x27\xfd\x5f\x90\xd7\x6e\xfe\x6a\x13\x24\x7c\xbc\xdf\xd5\xde\xa0\x3e\x46\x1d\x17\xf9\xf3\xa0\x08\xfe\xfc\xf0\xda\x18\xa4\x02\xe7\xec\x7a\x9b\x0c\xb4\xa1\xd7\xe3\x8a\x6f\x19\x1f\xc7\xe9\xfe\x3a\x0b\xbe\xb1\x81\xcc\x24\x07\xd0\xa1\xd4\x41\xda\xe6\x5b\x3e\xa8\x3f\x9d\x8c\x9b\x51\x42\x1e\x7c\xa7\x2b\x23\x1a\x7f\x5e\xfd\x1a\xa4\x19\x0b\x41\x3c\x7e\xbc\x89\x22\xbe\xdf\xb3\x40\x7f\x1b\xc5\xa2\xf1\xe7\xf0\xe3\xcd\xf5\x75\xbe\x2b\x14\x97\xaf\xca\x57\xe6\xfb\xe3\x8c\x90\x41\x70\xcf\x9b\x6b\x75\x4c\x84\x9d\x12\x28\xa7\x1e\x0e\xd5\xdf\x71\x14\x64\x99\x11\xa1\x03\xac\x7e\x34\x18\x37\x99\x15\x51\xa9\x6a\x54\x44\xca\x98\x14\x8f\xf3\x6d\x10\xe6\xbb\x82\x71\x10\xcf\x32\xd5\xd6\xcf\x59\x1e\xc4\x6c\x05\xb1\x5c\x95\x41\x1c\x14\xc1\x4c\xad\x40\x92\xae\xfc\x30\xd8\x73\xd7\x86\xf4\x7f\x9e\xbe\xfb\x70\x8b\x7f\xff\x2d\xc9\x2f\x2e\x2e\x2e\xde\x7e\xfc\x73\xfd\xe2\xcf\x44\x3c\xfe\x29\x7e\xfd\xfa\xec\xe2\xdf\x17\x17\x17\xcf\xde\x86\xdf\xc2\x4c\x00\x5e\xbe\xc8\x5e\xfc\xf1\x3f\x7f\xbc\x22\xf4\xbd\x7d\x76\xe6\x9d\xdd\x5a\xde\x6f\xaf\x2e\xfe\xf5\xfc\xd5\xd3\xdf\x5f\xe0\xe7\x2f\xbf\x26\xd9\xe5\xdb\xa7\x17\x17\xef\xa6\x9f\xfe\xf5\x1a\xff\xdb\x7e\xf7\xf2\x56\x8c\x7a\xfa\xcf\x0f\x7f\x3a\x2f\x76\x57\xff\x4c\x92\x84\xb1\x01\xe8\xc4\xb4\x47\x76\xc6\x4e\x71\x4b\xe2\x27\x3d\xd2\xcf\xfa\x07\x12\x35\x50\x29\xbd\x7c\xaa\x34\x56\x5e\x9b\x7c\xd6\x9f\x29\xeb\xf4\xaf\x6c\x9e\x33\x3a\x26\x65\x26\x49\xce\x6e\xd3\x6d\x9c\xdf\x8e\x63\xfe\x25\x8d\xf8\xfb\xf4\x2b\xcf\x3e\x04\x45\x9a\x43\xc4\x1e\xfa\xc6\xba\xb3\x95\x49\xbb\xf6\xff\x1b\xe4\xe6\xfe\x19\x03\x87\x15\x24\xb0\x06\x11\xab\xee\xd2\x95\x31\xd8\xe6\x31\x17\x1e\x3a\x48\xb7\x27\xc1\x70\x78\x96\x6e\x92\xf2\xdb\xec\x60\x5c\x76\xd6\x77\xf4\x19\x0b\x76\x89\xb4\xe0\x32\x4b\x1d\x11\x3f\x9b\x33\xe2\x67\xa3\x11\xaa\xfa\x16\xd9\x92\x35\x1b\x8f\x43\x9f\x67\x7b\xde\xf8\xb8\x9c\x95\x1f\x97\x5f\x0e\x87\x46\x8d\x4a\x96\x8f\x59\x08\x75\x9b\x76\xda\x56\xa7\x6d\x8b\x36\xf2\xe5\x76\x90\xa9\x9b\xa5\xba\x17\x1d\x0e\xea\xce\xba\x2f\x85\x08\x5f\xed\xdf\x07\xe9\xb6\xe0\x31\x2b\xbf\x77\x2d\x17\x8d\x55\x9f\x4a\x36\xb2\x8b\x4e\xd8\x78\xd0\x93\x23\xd9\xdd\x08\x45\x3a\xcc\xc8\x7d\x87\xe9\xad\xba\xdb\xa9\xb6\x22\x56\x6e\xd9\x10\xb4\xe2\x7a\x1b\xb9\xa6\x5c\xe5\x40\xb9\xb6\x80\x6e\x90\x4c\x78\xa1\x7b\x8c\x01\x8d\x2b\x9e\xfa\x44\xd7\x21\xf3\x07\x01\xea\xbb\xe1\x55\x46\xce\x0a\xa5\x57\x02\x39\xae\x62\xa3\xe3\x6b\xf2\x5b\xdb\xaa\xa0\xfe\x5e\x0e\xd7\x4c\x98\x34\xd1\x2a\x5f\x2a\x75\x51\x7e\x9b\x52\x67\x54\xbc\xef\xfd\x96\x15\x8b\x75\xf6\xc4\x21\x61\x71\x99\x33\x71\x58\xab\xc2\x6f\x97\xdf\x6c\x63\x63\x85\x20\x6d\xb6\x13\xe4\x87\xdf\x11\xbf\xcc\xb4\x9a\x19\x03\xd7\x19\x43\xe3\x05\x05\x9f\xeb\x73\x85\x3b\xed\x5a\x65\x26\x71\x09\x57\x08\x36\xec\xea\xf1\x0a\xb6\xec\xf2\x71\xe2\x47\xe3\x7d\xb1\xcb\xaf\xf8\x47\x31\x25\xcb\x9e\xc4\x75\x42\x33\x8b\x1b\x89\x17\x44\xf2\xab\xc3\xff\x2b\x6d\x4d\x6c\x16\x22\xfd\xf9\x89\x41\x02\xed\x03\x8f\x0a\x63\x03\x5b\x11\x21\x44\x82\xa5\x66\x94\xd0\x46\x56\xb9\x41\xe6\xd8\x69\xa6\x99\x5b\x09\x58\x43\xda\x37\x26\xe2\x69\x66\x6c\xd0\xa8\x1c\x22\xdb\x5b\xd9\x16\x23\x0e\xc7\xf6\x88\x0f\xd0\x5c\x7a\xf5\x79\x6a\x2b\x8c\x1d\x3b\xf0\x70\x18\xab\x78\xac\xdc\x1f\xb5\x49\xa4\x15\xf1\x07\x4e\x00\x1a\x94\xda\x23\x8f\xd2\xa7\xb6\x85\xa9\x7e\x29\x2c\x06\xdc\xeb\xef\xfd\x7e\xde\xeb\x87\xed\xa9\xa5\x99\xb1\x9e\xd7\x17\x82\x27\x0d\xdd\x13\x6e\x3d\x0e\xd0\x19\xe1\xd6\x2c\x38\x00\x3f\x18\x68\xf6\xbf\x5e\x3e\x55\xd7\xfe\xff\x5d\xbd\x52\x7e\x22\x72\x54\xb1\xac\xd8\x03\x35\x4b\xc2\x16\xbf\x9c\x17\x41\x98\xf1\x13\xe9\x69\x6c\x10\xe6\xbb\x98\xef\x66\xd8\x57\x0f\xa3\x28\xcf\xb2\xe0\x7a\xcf\x67\xe5\x83\x3f\x98\xff\xb2\x94\xaf\xb0\xc4\xfa\x7d\x91\xbb\x44\x1d\xc1\x0c\xce\x8b\xdd\x7c\xd0\x9f\xd7\x6b\x94\x5f\xce\x8b\xf8\xe7\x67\xba\x0e\xe2\x38\xdd\x26\x33\xec\x6f\x82\x5d\x92\x6e\x67\xd8\x57\x95\xc5\x2f\x26\x37\x07\xd7\x5f\xfd\xb2\xba\x30\x57\xb2\x19\x06\xd1\x55\x22\x57\x75\x24\x3d\x6f\x36\x30\xeb\xca\x41\xf8\xc2\x93\x46\x91\xd2\x2a\xa6\x90\xf9\x8b\x3f\x98\x9f\x9f\x15\xf1\xfc\x17\xe4\x57\xf2\x9c\x49\x81\x0e\x8d\xb6\x50\xd5\x5c\xd6\x46\xe9\x76\xcb\x77\x2f\x3f\xbd\x79\xcd\x92\xf1\x65\x9e\x6e\x8d\xc1\x40\x95\x7d\x97\x2c\x1a\x47\x55\xca\xbf\xc0\x4b\xb8\x62\xe5\x62\x8c\x2e\xc7\xf9\x6a\xb5\xe7\x85\x8c\x1e\xe8\x8c\x42\xc6\xaa\x05\xa9\x3a\x5f\x2a\x0b\x3e\xa3\xfe\xd5\x1c\x0f\x87\x99\xf8\x65\x5c\xea\x58\xa8\x54\xc1\x32\x21\xf1\xc9\xc0\xbc\x12\x7f\x07\xe8\x07\x35\x49\xb5\x61\xd4\x5c\x0f\x06\xaa\xc2\xf0\xd5\x3f\x9a\x62\x47\x2f\xc0\x76\x6c\xf7\x4e\xa9\x9e\x3a\x6e\x59\xd4\x89\xc7\xc6\x81\xb1\x0d\xb5\x6e\x07\xff\xc0\xf2\x67\x00\xb5\x8e\x67\x83\x7f\xac\xe4\x8f\x00\x36\x0e\x94\xe3\xf1\xcb\x03\x0c\xf6\xb2\x6a\xab\x53\x96\x70\x38\x34\x42\x76\x27\x62\xc0\x2c\x3c\x20\x08\xeb\xef\x90\xd5\x29\x40\x9b\xbd\x45\xb4\x64\xe1\x22\x5a\xfa\x47\x84\x02\xf5\x21\x7d\xb9\xe5\x26\xbc\xac\x9b\x9e\x7e\x7b\x15\x1b\x41\xf9\x2f\x10\x7a\xf2\x92\xe6\xe6\xaf\x95\x54\xff\xe7\xa3\xcf\xf9\xf3\x5d\x70\x9b\x6e\xd5\xe7\x60\x7f\x57\xbb\x6f\xc7\xe5\xbb\x39\xce\x58\x08\xa4\xf3\x57\x11\x77\x05\x55\xa3\x07\x05\x1d\x40\x4d\xd9\x89\xd3\x9d\xa5\xaa\xc2\x65\xc9\x1f\xbf\x3d\x09\x8d\x9d\xd1\x8d\x3c\xe3\xa6\xc6\x8f\x78\xea\xeb\xd4\x14\xc7\xfa\xbf\xb8\x18\x41\xb7\x43\xfd\xfb\x80\x3a\x15\x29\xd2\x22\xe3\xb5\xc2\xb4\x76\x64\x70\x33\x5a\x23\xab\xff\x39\xa1\x77\x1d\xe3\x21\x59\x8f\xf6\xa4\x41\xf9\x5c\xaf\x6e\x67\xb6\x6a\xd8\x70\x68\x9c\xb6\xd6\x55\x7f\x43\x5a\x36\xe7\xcc\x42\x65\x19\x71\x3c\xba\x97\xa5\x87\x76\xaa\x72\xb4\x4e\x48\xaa\x91\xad\x7f\xb4\x15\x0b\x4f\xfb\x7f\x01\x00\x00\xff\xff\x02\xb9\x5d\x4c\xd7\x4d\x00\x00") - -func resourcesAppJsQrcodeMinJsBytes() ([]byte, error) { - return bindataRead( - _resourcesAppJsQrcodeMinJs, - "resources/app/js/qrcode.min.js", - ) -} - -func resourcesAppJsQrcodeMinJs() (*asset, error) { - bytes, err := resourcesAppJsQrcodeMinJsBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/js/qrcode.min.js", size: 19927, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppListPng = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x00\x56\x03\xa9\xfc\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x3c\x00\x00\x00\x3c\x08\x06\x00\x00\x00\x3a\xfc\xd9\x72\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xe1\x07\x1c\x07\x23\x04\x05\xa8\xf3\x4d\x00\x00\x02\xe3\x49\x44\x41\x54\x68\xde\xed\x9a\xbf\x6b\x14\x41\x14\xc7\x3f\xbb\x77\x08\x9e\xe6\xe2\x8f\xa0\x51\x84\xa0\xf8\x03\x6d\x03\x36\x96\xfe\x01\x22\x68\x15\xd1\x5e\xd1\x46\xb0\x12\x11\x04\xff\x05\x0b\x21\x9d\xa5\x60\x6d\x93\x46\x05\xb1\x10\x0b\x45\x83\x36\x11\xa3\x44\x11\x43\xa2\x97\xe4\x6e\x6f\x2d\x76\x0e\xf6\x26\x33\x93\xcc\x16\x99\xc9\xf2\xbe\x30\x1c\xbc\x7b\xb3\xcb\xdb\x7d\xfb\xde\xf7\xbd\x79\x20\x10\xd4\x0a\x89\xe3\xbf\xbd\xc0\x7e\xa0\xaf\xe9\x67\xc0\x9c\x26\x4f\x81\x31\xa0\xad\xc9\x43\xd8\x93\x03\x0b\xc0\xb2\x49\xa1\xe9\xd8\x78\x15\xb8\x0b\x2c\x69\x86\x2d\x02\xe7\xb4\x0b\xb6\x80\x3b\xc0\x14\xd0\x09\x68\x70\xaa\x5e\xc8\x6d\xe0\x99\x8f\xc1\xa8\xb7\x3b\xa6\x56\x19\xff\xd4\x85\xf5\x1b\x1d\x04\xc6\x23\xf1\xdc\x11\xd7\x13\xb1\x21\xb3\xc8\x7b\x9e\xfa\x5b\x8d\x5c\x2d\x6f\x83\x13\xcf\x3d\xe9\x36\x88\x4b\x4e\x97\xee\x6b\xbf\x03\xa3\xba\x1b\xbc\xe1\xd0\x41\x2b\x73\xbd\x61\xd7\xd3\x38\x01\x9c\xd6\x5c\x38\x01\xd6\x80\x19\x4d\xde\x04\xce\x00\x13\x11\xb8\x76\x0e\xbc\x03\xe6\x25\x09\x0b\x04\x82\x5a\x73\xe9\x63\xc0\x49\x43\x94\xee\x02\x2f\x0c\x51\xfa\x14\x70\x24\x70\x94\x1e\x70\xe9\xf7\xc0\x77\xdf\x8d\x0f\x4a\xac\xa5\xbc\x56\x80\x51\x4d\xbf\x0d\x3c\xb1\xe8\x87\x58\xd7\xaa\x30\x2d\x1b\x85\x5c\xb5\x24\xf6\x6e\x44\xd4\x32\xab\x62\x70\x2d\xe1\x32\xb8\xe1\x49\x47\x9b\x11\xc5\xa5\xb4\x0a\x97\xfe\x06\xcc\x02\x7f\xb5\x8b\x2d\x19\x5c\x26\x03\xbe\x00\x1f\x94\xcb\x87\xe6\xd2\xbf\xaa\x44\xe9\x03\xc0\x21\x43\x31\x90\x01\x1f\x0d\x45\xc5\x61\x43\x87\x24\x14\xbe\x02\x7f\x24\x09\x0b\x04\x82\xda\x72\xe9\x04\xb8\x08\x5c\x61\xb8\xed\x9a\x52\xb4\x67\x6f\x69\xf2\x9d\x8a\xce\x9d\x57\x1d\x91\x90\xf6\xf4\x81\x47\xc0\x4b\xdf\x8d\xf7\x14\x4d\xeb\x95\x56\x1f\xf8\xad\xb8\xb3\xce\xa5\xa7\x0d\xfa\x5b\xbd\x32\xf5\xc0\xa7\xaa\x10\x8f\xc4\xc2\xb8\x1a\x1b\xb0\xb6\x46\x04\x5e\x9b\x08\x97\xf6\xe0\xbf\xb9\xa1\xde\xdc\xac\x7e\xa8\x7a\x38\xaf\x62\xf0\x1c\xf0\x56\xe3\xd2\xa9\x83\x4b\xcf\x02\x6f\x02\x73\xe9\xc1\xd9\xd2\x4f\xc9\x40\x02\x81\xa0\xf6\x1f\xf6\x6e\x8a\x83\xe5\xdc\x90\x76\x16\x0c\xe9\xaa\x4d\x31\x09\x90\x47\x60\xd7\x22\x96\x49\x04\xd7\xc8\xc3\x65\xe0\x06\xc5\x89\x7f\x59\xbe\x0c\x5c\xd2\xd2\x55\x4b\xe9\x5e\x20\x8e\x16\xcf\x43\xe0\xb9\x6f\x1e\x3e\x0a\x4c\x1a\xe4\x1d\xc3\xbe\x06\xc5\x71\xe9\xd9\x48\x3c\x77\xba\x0a\xb5\xb4\xf5\x76\xbb\x16\xb7\xed\x45\x62\x6c\x8e\xa3\xaf\x26\x7d\xe9\x4d\x54\x45\x3b\x2c\xc1\x6e\x5b\xf7\xa5\x73\x8a\x39\xa7\x1f\x5a\x41\x9f\xa8\xa0\xd4\x31\x7c\xd7\x8f\x59\x7f\xc8\x16\xaa\x78\x78\x25\x09\x58\x20\x10\xd4\x9e\x4b\x4f\x50\x8c\x3d\x64\x06\x82\xf1\x5a\x93\x37\x80\xe3\x98\x0f\xdf\x42\x10\x8f\x4f\x8a\xef\x7b\x73\xe9\xfb\x0c\x8f\x09\xa7\x14\xa7\x72\x93\x0c\x8f\x15\xb7\x80\xeb\x14\xbd\xe9\x95\x08\xb8\xf4\x4d\xe0\xa9\x2f\x97\x1e\x01\x76\xa9\x85\x66\x5c\x62\xb8\xd1\x3e\x8a\xd9\x8f\xd1\x08\x3c\xb7\x55\x85\x69\xf5\x3d\x39\xb6\x8c\x0f\x07\x74\xeb\xc4\x97\x5a\x96\xab\x9f\x55\x2d\x38\xd9\x46\xfc\xd7\x0c\xfa\x21\x6a\x83\xcc\x45\x6f\x5d\x51\x7a\x8c\x62\xac\xdf\x34\xf2\xf0\x99\xf5\x23\x0f\xe3\xc0\x9e\x48\x3a\x1e\xf3\xaa\xeb\x21\x10\xd4\x1d\xff\x01\x37\x5e\xf3\x33\xdc\xc8\x66\xcd\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\x01\x00\x00\xff\xff\x98\xf3\x78\x67\x56\x03\x00\x00") - -func resourcesAppListPngBytes() ([]byte, error) { - return bindataRead( - _resourcesAppListPng, - "resources/app/list.png", - ) -} - -func resourcesAppListPng() (*asset, error) { - bytes, err := resourcesAppListPngBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/list.png", size: 854, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppMinimizeJpg = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x94\x7b\x50\x93\x57\x1a\xc6\xcf\xf9\x2e\x49\x20\x90\x7e\x09\xe1\x26\x52\xbf\x84\x88\x22\x5a\x03\x1b\x6e\x22\x84\xa0\x42\x82\xac\x72\x17\x11\x14\x14\x0a\x16\x34\x44\x04\x64\x19\xb7\x20\x2d\x68\x91\x8b\x08\xcc\x4a\x81\x60\x41\x14\xa8\x48\xa9\x56\x05\x6b\x05\xb9\xc8\x65\xd4\x55\x30\x41\x81\x66\xc5\x91\x88\xac\xd4\x89\x8b\x60\xb2\x64\x07\xa6\xad\xb3\xfd\x63\x9d\x7d\xe6\xfc\xf9\xcc\x3b\xe7\xf9\xcd\xfb\xbc\x7a\xa5\x5e\x05\x08\x3f\x1f\x89\x0f\x80\x10\x02\x31\x10\x03\xa0\x5f\x00\xee\x9b\x82\xb6\x88\x42\xb6\x07\x6d\x20\xe3\x63\xd7\x7d\x96\x1c\x17\x4f\xa6\x39\x7c\xc2\x27\x57\xa7\xa6\xec\x3f\x18\x4f\x4a\xfc\x7c\x49\xbf\x80\x2d\xbe\x64\x9a\x2b\xdf\x6e\x2d\x29\x4b\x8d\x49\xda\x7f\x38\x83\xf4\x20\xdd\xf8\x86\xfa\x27\x60\x13\x40\x11\x64\xf1\xa1\x28\x8a\xa1\x28\x86\xd3\x70\x1c\xc3\x70\x43\x2a\x95\x42\x33\x32\x34\x32\xa2\x1b\xd2\xe9\xc6\x0c\x16\x61\xcc\x60\x32\xe8\x74\xc2\x8c\x60\x9a\xb0\x4d\x4d\x4d\x8d\x3e\x32\xb7\x30\x63\x5b\xb0\xd8\xa6\xec\xc5\x21\x10\xc5\x30\x1c\xc3\x0d\x70\xdc\x80\x6d\x4c\x37\x66\xff\xdf\xd2\x77\x02\x26\x0d\x78\x03\x6f\x14\x32\x01\xc2\x84\x28\x13\xea\xbb\x80\xd5\x52\x4e\x04\x05\xef\x45\xa3\xe2\x14\x88\x62\xfa\x2e\xc0\x86\x10\xfc\x41\xfa\xc7\xc0\x08\x85\x00\x21\x50\x02\x00\xf8\xc8\x28\x7c\x99\x65\x7b\xce\x71\x3e\x52\xce\x73\xbc\x81\xa9\x12\xa9\xd1\xe4\x53\xb9\x73\xc9\x66\xfb\x16\xdf\xfa\x66\xff\x2d\x9e\x07\xc8\x53\x86\xd3\xcc\x17\xb9\x66\xf0\x87\x15\x62\x9e\x77\x3b\xa6\x8e\xce\x7a\x66\x78\xed\x81\x01\xd1\x7c\x0b\xb0\xec\xa2\x58\x9c\xa8\x2c\xc0\x0b\x6a\x5b\x75\xbb\xb6\xda\x0b\xcc\x96\x5d\x00\x00\x08\xf5\x5d\xc0\x86\x00\x70\x91\xd6\xfb\x0f\x50\x30\x9c\x0a\x50\x02\x31\x33\x77\x81\xa4\x13\x97\xaf\x7f\x0c\x68\x10\x02\x88\x23\xae\x6e\xad\xcb\xe5\x65\x92\x2b\x3b\xd6\x98\xdc\x97\x64\xce\xdb\xd7\x5b\x57\x05\x3b\x92\x2b\xca\x2f\xdd\x38\x1d\x72\xfe\x9d\x67\x57\x73\xe4\xb3\xce\x1a\xbb\x71\xad\x7a\xa0\xa9\x35\x6c\xf3\xca\x2d\x5b\x0b\xa3\x6a\xd5\x0b\xca\xee\xaf\x4a\x33\xa9\x26\xe9\x0a\x4a\x9a\x5f\x9f\xb5\x69\x59\xb3\x6b\x6a\xd1\x84\x76\x9f\x99\x6c\xf5\x2c\xc3\x76\xe6\x92\xac\x2f\xb1\x22\x41\xe7\x60\xd1\x5d\x65\x78\x20\x72\xf8\x84\x6f\x8b\x6c\x4d\xde\x75\xe2\xc2\x84\x77\xc4\x44\x50\x84\xb4\xa0\x5f\xb0\xee\x88\xab\x78\xf0\x5f\x41\x45\xd1\xda\x65\x69\xc3\x7e\x1e\x39\xd3\x89\x4f\x42\x57\x53\x2f\x1e\x69\x57\xdd\xd7\xf4\x16\x4c\xa5\xef\x1a\x7a\x75\xb5\x61\x4c\x1a\xdc\x36\x7e\xfe\xb0\x40\xf0\x6e\xdb\x4e\xdd\x4f\x8b\x44\x99\x7f\x24\x1a\xbd\x14\x04\x85\x50\x08\x6d\xfe\x87\x01\xf9\xcd\xe0\x4c\x00\x88\xa0\x18\x85\x86\x51\x7f\x35\x40\x04\x05\x18\x4e\x30\x59\x1c\x13\xa7\xc0\x98\x94\xbf\xb3\xb9\x0e\xa2\xd3\xa5\xdf\x7d\x4f\xda\x38\xb6\x9a\xf2\x83\x72\xce\xfe\xf2\xfa\x57\x58\x14\x21\x92\x90\xd0\xe6\xff\x44\xa1\x3a\xa8\xcd\xb2\xf2\xdf\x5d\xe1\xee\xf2\xf1\xbd\xe2\x49\xd7\xa1\xc1\x39\x46\xca\x97\x4e\x6e\xdc\xae\xba\xa6\x84\xae\x2b\xea\x72\x03\x25\xfe\x5c\x11\x6f\x3b\x6a\xcc\x57\x0e\xfe\x73\x94\x73\xc6\x86\xfb\x85\xe4\xe6\x0d\xe3\xd2\x9f\xeb\xb6\x69\xc6\xe2\xac\x57\x09\xd4\x15\x03\x6f\x43\x93\x4e\x5e\xf1\x58\x38\xb9\x5c\x22\x4b\x04\xac\x94\x13\x76\x23\x5f\x5f\x7e\x29\xe9\xf1\x6a\xd3\x16\x28\x6e\x9f\x4e\x29\xcc\x3d\xe3\x9b\x31\x33\xca\xa1\x79\x9b\x9f\xed\xce\xdd\x1d\x6a\xa9\x07\xf5\xd8\xe8\x7d\x46\xc8\xe8\xb6\xcc\x65\x56\x54\xf7\xd5\x3a\xdb\xa3\xc3\xbb\xb6\xa9\xe4\xe1\xa5\x95\x95\xc9\x82\xdb\x31\xe9\x55\x3f\xee\x2b\xfe\x82\x43\x0b\xcb\x33\xb3\xcc\x08\x99\xfc\x37\xdf\xf6\x79\x67\x54\xc3\xb7\x69\xb3\xb9\xb9\x1d\x77\x1f\x0b\x0d\xe4\xa9\x61\x0f\xaf\xad\x7a\xc4\x6b\x50\x7e\x35\x12\xdf\x38\x60\xf7\x78\x7b\x73\xb2\xed\xf3\xf1\xb8\xfe\x8a\xde\x29\x73\x81\x33\x43\x76\x28\xca\xbb\xf0\x56\x53\xc2\xd2\xdc\x95\x7f\xda\x1e\x5f\x97\x70\x3f\xa0\x6e\x2f\x28\x98\xef\x69\xda\x71\xbc\x50\xd6\xa8\x78\x6a\x53\xc9\xaf\x93\x34\x86\x8a\xa2\xf3\x06\x1a\xa6\xa4\x77\xba\xaa\x38\x62\xd9\x8b\x91\x3c\x2b\x9f\x9d\x3c\x7c\xcd\xcb\x99\xd6\xa2\xce\xf8\xb1\x1d\xbd\xbe\x4f\xb7\x1e\x9d\x0d\x9c\xf3\xd7\x36\xce\xa9\x75\x3b\xa5\x37\xfb\x22\xce\x39\xad\xec\x6b\x88\xfd\x47\xf0\xbe\x29\xae\xb6\x63\xc5\x20\x9c\xdb\xd4\xfb\xb9\x57\xe4\x67\xe9\x37\x8e\x4d\x04\xff\xf8\xcc\x7c\x59\xd5\x0c\x79\x6d\x68\x26\x03\xef\x39\x9f\x79\xe7\x13\xcb\x8b\x8f\x46\x22\x1b\x2d\x22\x76\x68\x98\xb5\xbc\xf3\x2f\xa0\xbb\x70\xfd\xd2\x42\x43\x80\x40\x14\x7b\xdf\x34\xc8\xe4\x38\x00\x51\x20\x41\xc6\x64\x9f\x3a\xcb\xf7\x92\xfd\xb6\xd0\x42\x0e\x27\xaa\x29\x77\x4f\x7e\xcf\x3b\x9a\xcb\xa1\xf2\xb6\xe0\xeb\x0a\x7f\x5d\x37\x25\x7d\xc1\x3a\x2e\x17\xeb\x57\xba\xec\x76\xb2\x97\x79\xab\x7e\xf0\x25\x99\x03\xd6\xe0\x53\xc9\xa3\x0d\x97\x65\x44\x3f\xdc\x47\x39\x77\x28\x96\x79\xd1\xca\x3f\xa1\x70\xe3\x75\xb3\x8e\xb6\xd7\xb5\x0f\x2c\x83\xa2\x94\x03\x77\xbf\xb5\xf6\x09\x7d\xab\x51\x87\x65\x26\x8d\xe7\x7a\xf9\x37\xde\x4e\x9d\x10\x75\xa6\x1c\xbe\xbc\x36\x6e\x4a\x1b\x7b\xe7\xe6\xc2\x51\xc3\x7b\xa9\x5f\xbf\x72\x96\x25\x96\x15\x3c\x34\x18\x7e\xe3\x3c\x78\xc9\x33\xe3\x8d\x3d\xa7\x72\x76\xeb\x58\xec\x81\xcd\x5a\x41\x39\x92\xba\xa2\x52\xec\xba\xbc\xf7\x6f\x8a\x82\xd0\xb8\xe2\x35\xf2\x4e\xe5\x47\x45\x43\xdf\x7b\x14\x4f\x56\x9f\xf8\xe6\xfa\x50\x84\x74\xc3\xc1\xb5\x9c\xe0\x9f\xa8\x87\xf6\xd7\x57\x7c\x7a\xac\xef\x54\x7e\x38\x11\xaa\x69\x9f\xd3\xff\x7e\x27\xc0\x62\x5e\xe2\x98\x01\xc8\x12\x83\x62\x09\xc9\x32\x20\x59\x22\x12\xd0\x78\x25\x22\xac\x44\xcc\x63\x49\x78\x25\x12\x9e\xfc\x03\xc5\x20\x3e\x54\x8c\x25\x03\x87\x80\x4b\x88\x71\xf8\x5f\x84\x89\xc0\x5f\x48\x51\x8c\xac\xe3\xf7\x83\x21\x24\xce\x90\xd5\x4c\xc0\xae\x01\x17\x44\xdc\xbc\x8e\x1a\xc7\xcb\x0f\xf6\xdc\xcc\x7f\xc9\x4d\x88\x3e\xa0\x6e\x0c\xcc\x7f\x55\x95\xa6\x07\xec\xa3\xb7\xd2\xe0\xd5\xf2\xb8\xe4\x36\x97\x30\x66\x96\xe9\xdb\xe5\x8e\x58\x5e\x40\xce\xf6\xe2\x7b\x08\xa1\xf0\x51\x4f\xef\x35\x2d\xe6\xb6\xac\xcb\x77\xe8\xc6\xc2\x94\xbb\xf8\xd9\x01\x5f\x86\x63\x74\xeb\xf6\x3d\x2d\x8c\x5b\x8e\x1a\x5e\xa9\x1b\x8f\xfe\x9d\x32\x3b\x07\x69\xed\x39\x49\x71\x1c\x9f\xee\x90\x3e\xf3\x2c\x16\xe2\x3f\x0f\x16\x05\xd9\x9a\x75\x28\x29\x0b\x4d\x77\x36\x36\xd7\xb4\x68\x3d\x0e\x87\xef\x1d\xae\x75\xad\x39\x59\x5f\x1e\x7d\x35\x2a\x6f\x88\xaa\x6a\x9f\xff\xab\x0e\x71\x08\xbc\x16\xec\x85\xad\xa7\x3e\x3c\xf1\xa6\x3f\x69\x7a\x9d\x2e\x2f\xa7\xc8\xcf\xfd\xcf\x2a\xe9\x85\x8f\xfd\x05\xa3\xac\x00\x47\x87\x3a\x87\xea\xe6\xbd\xc7\xa5\xc9\x59\x65\xe7\x22\xcd\x2d\x5c\x59\xa9\x93\x02\xfb\x80\x07\x21\xf4\x90\x05\xa0\x93\x4b\x5f\x53\x55\x99\x7f\x81\xcf\x19\xb0\xa0\xdb\xfd\x88\x48\x5c\xb2\x2a\xd8\x64\x2c\x7b\x4f\x96\xa7\xdb\xa4\xb0\x52\x23\xbf\x9b\x71\x6f\x72\xe3\xa4\xa6\x3a\x65\xbe\x47\x0f\xb2\x1f\xe6\x40\x82\x9b\xf4\xcd\xe7\xeb\xf5\x23\xff\x09\x00\x00\xff\xff\xdf\xe0\x80\x38\xf8\x06\x00\x00") - -func resourcesAppMinimizeJpgBytes() ([]byte, error) { - return bindataRead( - _resourcesAppMinimizeJpg, - "resources/app/minimize.jpg", - ) -} - -func resourcesAppMinimizeJpg() (*asset, error) { - bytes, err := resourcesAppMinimizeJpgBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/minimize.jpg", size: 1784, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppMinimizePng = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x94\x7d\x54\x93\xd7\x1d\xc7\xef\x7d\x5e\x92\x90\x40\xfa\x24\x24\x40\x47\xb7\x3c\x01\xa7\xbc\x48\x04\x84\x60\x01\x85\xf0\x12\x21\xc6\x9a\x50\x98\x8a\xb3\x10\x85\x13\xc2\x82\x88\x12\x38\x8a\x83\xa0\xa0\x09\x54\xdb\xa0\x32\x45\xac\x80\x28\x6f\x1a\x75\xb6\x56\x40\x6d\x90\x28\x6f\xea\x32\x54\x62\x50\xd4\x52\x3a\x0f\x2f\x6d\xa1\x8c\x6d\xd2\x1d\xb2\x13\x4f\x75\x5b\xff\x58\xcf\xbe\xe7\x79\xfe\xb9\xe7\x73\xee\xf9\xde\xef\xfd\xfe\xae\xfd\x91\xfd\x39\x20\x24\xe2\x44\x31\x80\x10\x82\x04\x90\x00\x80\x7d\x01\x44\xc4\x26\xc5\x8b\x92\xd7\x25\x85\x93\xca\x8c\x80\xec\xed\x99\x4a\xb2\x20\x48\x10\x48\xfa\x68\x76\xaa\xb6\x29\xc9\x44\xc9\x6a\x52\x22\x8b\x5f\x4d\x16\xac\x08\xf4\x5d\x4a\xe6\x69\x14\x6a\x55\xfe\x2e\x72\x25\xf9\x6e\x20\xdd\xfe\x18\xc4\x02\x14\x41\x1c\x1f\x8a\xa2\x18\x8a\x62\x38\x0d\xc7\x31\x0c\xa7\x53\xa9\x14\x9a\x33\xdd\xd9\x99\x41\x67\x30\x5c\x98\x6c\xc2\x85\xc9\x62\x32\x18\x84\x1b\xc1\x72\xe5\x70\xb9\x5c\xe7\xb7\xdc\x3d\xdc\x38\x1e\x6c\x0e\x97\xe3\xd8\x04\xa2\x18\x86\x63\xb8\x13\x8e\x3b\x71\x5c\x18\x2e\x9c\xff\x5b\xf6\x9b\x80\x45\x03\x91\x20\x12\x85\x2c\x80\xb0\x20\xca\x82\x76\x33\xf0\x04\x00\x41\x1d\x47\xfd\xb7\x68\x14\xaa\x13\x8e\x60\x76\x33\xe0\xfc\xd7\xfa\x2b\xd9\x87\x81\x33\x0a\x01\x42\xa0\x04\x00\xb0\x9c\x1d\x2d\xb8\x79\x2f\x52\x7f\x3c\xc4\xbb\xbb\x80\x52\x50\x43\x2e\x5e\x92\x95\x53\x4e\x6c\x33\xdd\xdb\xdb\x13\x11\xab\x46\x74\x61\xe9\x99\x33\xfc\xb7\x63\x8a\x37\x36\xe8\xc2\xd2\xe5\xab\x43\x9c\xb4\x75\xd5\x96\x11\x2d\x78\x67\x56\x70\x3b\x32\x27\x1a\x30\xe5\x27\x7e\xbd\x20\x78\x0e\xa8\x83\x59\x36\xbb\x19\x78\x11\x00\xa2\x28\xfe\x1f\x7e\x70\x04\xa3\x02\x94\x02\x09\xae\x7b\x28\x87\x74\xb3\x0f\x03\x1a\x84\x00\xe2\xc8\xa5\xac\x73\xcd\x85\x67\x78\x56\x49\xd4\xb9\x55\x96\x3b\x9a\xf3\xbe\xa9\xfc\xe0\x45\x1f\x37\x4c\x9a\x62\xc6\xf4\x3d\xf5\x6f\xad\x49\x1f\xb0\xfe\x70\xcb\x3f\x6e\xb1\xd8\xa0\x09\x6e\x7e\x1a\x36\x2f\x2c\x5b\x19\x50\xd6\x16\xa7\x64\x87\x1c\x6c\x39\x23\x9e\xf9\xe2\xfe\x35\xfe\xb8\x7a\xdd\xe0\xad\x34\xba\xc7\xea\x4e\x7c\x68\xc9\xa9\x8f\x06\x2e\x3c\xe0\x8f\xab\xc5\x3c\xa6\xe8\xbb\x44\xbd\xf1\xb0\x6b\x74\xa0\xd8\x23\x35\xed\xc5\x01\xdd\xd5\xb2\x95\xcb\xfa\x78\xab\xea\x9b\x84\xc7\x3d\xc6\x7e\x61\x25\x87\xda\x29\x9f\xf5\x86\x1a\x45\xe7\xdd\xfc\xfa\x7b\x07\x72\x8c\x4f\x07\x37\xdf\xb6\x55\x14\xbd\xcc\xcd\x5d\x63\x9d\xb9\x96\xa7\x83\x51\x8e\xec\x58\x3f\xcd\x2e\xfd\x95\x79\x14\xc2\x28\x08\xff\x07\x80\xbc\x06\x56\x10\x00\x22\x18\xa4\x30\xa8\xf8\x8f\x00\x02\x51\x80\xe1\x2c\x3e\xc1\x0e\xd9\x59\x75\xc9\x95\xe3\x15\x14\x2c\x92\x2b\xb6\x18\x46\x49\xef\xd0\x98\xd8\xbc\xc1\x1d\xa5\x7b\x1b\xfe\xfc\x63\x44\x94\x28\xa4\xf6\xd3\xef\xdc\xab\x7f\x77\x04\x64\xb7\xd7\x85\x75\x05\x3c\xe6\x71\x95\x19\xa7\x47\xcf\x4d\x1d\x09\x8b\xdb\x56\xbc\x79\x42\xf7\xe4\x13\xd6\x2a\xb9\x5b\xbc\xd7\x26\xfa\x96\xd6\x8b\xf9\x13\x9b\x5a\xd9\xbe\xfb\x3e\x62\xd2\xff\x7e\xd6\x93\x3c\x39\xaa\x3e\xee\x2b\x7c\xdc\xa7\xb9\xdb\xfd\xab\xb1\x8a\xb3\xcd\x85\x5f\x57\xfb\x1b\x0b\x79\xd2\x92\x5a\x5f\x76\x5d\xc5\x96\xd6\xeb\xb2\xfc\x61\x55\x73\xaf\x97\xad\xe7\xfd\xc9\xdd\x85\xdd\x29\xa9\x6d\xc5\x93\x8d\xe6\x4b\x4d\x6b\xcc\x9b\x6d\x7e\x35\xf5\xcf\xaa\x37\xe8\x65\xf1\x4b\x0c\x29\xeb\xe7\xba\xee\xab\x9a\x54\x58\x97\x83\x53\x74\x9c\x4f\xb9\xa0\x19\xdc\xf2\xdb\x1b\xb9\xac\xc2\xcc\xd6\xec\x03\xc5\x1b\xaf\xab\x72\xcb\x6a\x5a\xd7\x74\x0a\x03\x46\x1f\xf3\xd5\x0f\xd3\xb8\x5f\x45\x9f\x58\xf8\x62\x2a\xdc\x7c\x35\xdc\xdc\xbd\xf5\xd4\xb1\x89\xc5\xde\xc3\xd5\x7d\xc9\x0f\x99\xff\xbc\x20\xdd\x3e\x2b\xdd\xde\xd8\x58\x67\x73\x31\x94\xe4\x1f\x14\x16\xde\x29\xf1\xb8\xaf\xdc\xd3\x33\xa3\x6f\xef\x8b\xd5\x8c\x1f\x55\xc9\x5d\xbe\x96\xba\x9e\x6a\xfb\x86\x3e\xfe\xe0\x99\x6a\xd7\xe5\x0d\xa1\xea\x3d\x55\x0e\x2b\xdf\x48\x27\x2a\x0b\x24\x87\xdf\x67\xee\x13\xf8\x67\xe9\x04\x01\x17\x32\x6f\x87\x54\x17\x0c\xfe\xf4\x5f\x7c\xe7\x2f\x36\x96\xb8\xf2\xc5\x7b\xbd\x57\x85\xe2\x93\x7d\x2e\xef\x0d\x38\x09\xc7\x6c\xac\x15\x61\x63\xcf\x3e\x1f\x56\xbb\x1f\xd3\xbb\xd2\xb2\x53\x37\x1a\xd7\x49\xf5\x77\x12\x8e\xee\x1e\x72\xdc\xf0\x22\x02\x3a\xda\x8a\xa1\x6f\xda\x0a\x59\x20\x48\x4e\xf0\xa7\x45\x8a\xd2\x2e\x32\xcf\x50\x7f\xe9\x75\x5d\xa3\xf8\xd7\x5f\x7e\x26\x13\x4f\x77\xb6\xad\x15\x55\x99\x26\x47\xce\x16\x90\x95\xa5\xf5\xa6\xa5\x65\xb0\x46\xe2\xc9\xf7\xa6\x44\x59\x1f\xf2\x42\x47\x8e\x45\xaf\xbd\x6b\x99\x1d\xba\xfa\xce\x5f\x73\xd6\x87\x2f\x0f\x98\x28\x8e\x97\xc0\xea\x33\xf3\xde\xe5\xcf\xbf\xba\x69\x10\x60\xd3\xb4\x12\xea\xa6\xe1\x19\xae\xe9\xc5\xe9\xec\x6c\x3e\x07\x3e\xf8\xb4\x6a\x24\xe3\x37\xcc\x25\x13\x9d\xcc\x3f\x8c\xf2\xba\xac\x46\xeb\x95\x5a\xe6\x6e\xa1\x31\x37\xfc\x10\x0f\x7d\x9a\xf1\x24\x48\xc4\xd9\x28\x16\x7d\xec\x73\xc2\xf7\x87\x26\xf4\x93\xba\xe4\xfe\x86\x60\xb3\xb1\xe5\xf0\xa2\x0f\xa7\x2a\x4c\xb0\x23\xca\x77\x74\x94\x42\x3d\xf0\xb7\x39\xd3\x8b\xef\xbf\xdc\x61\xd9\xbe\xd4\xed\x4a\xdc\x9c\xbf\xa1\xc8\x18\xff\x6d\xbb\x7b\xc7\xd8\x07\x93\x86\xa2\x96\x0d\x92\xf6\x93\xe3\xfa\x36\xf6\x78\x08\x8f\xb6\xf5\x06\xcd\xa6\xfc\xfd\x82\x34\x95\xdc\x36\xd2\xb2\x35\x82\xe5\x95\x14\xc1\x3b\xfa\xfa\x35\x00\x28\x00\x80\x60\x27\x60\x44\x34\x49\x44\x63\x44\x22\xc6\x76\xc2\xd8\x89\x58\x55\x22\x60\x27\x62\x3f\x33\x0d\xc4\xcf\x4d\xc3\x2b\xc0\x8b\x80\x00\x41\x00\x8e\xbf\x01\x20\x8b\x0f\x82\x08\x52\x24\xcf\x53\x94\x1a\xba\xa6\xdf\x64\x4d\x50\xf5\x7e\x49\x6d\xc9\x7f\xbc\x79\x7a\xf7\xf2\xef\xd3\x76\xbd\x5c\x76\xed\x46\xc6\xdd\xfe\xb6\x8b\xf3\xae\xb2\xcf\xf7\xbe\xdb\xab\xd0\x27\x59\xf0\x81\xca\xfe\x7b\xa5\x8a\xa4\x6e\xdb\x88\x65\x6d\xed\x07\x99\x98\x1f\xfd\x97\x17\x47\x9e\x37\x54\x22\x45\xb4\xc6\x2b\xca\xa1\xb4\xda\xc8\x5b\x3e\x49\xc9\x59\x20\x25\x6f\xce\xf7\x1f\x27\x2a\x45\xe3\x8f\x04\xfb\x3c\xf3\xf9\x4f\x9a\xda\xe7\xf1\x7a\x2d\x00\x74\xb4\x89\xeb\x19\xa9\xd0\x7a\x28\xd7\xc6\x83\xd4\x8e\x01\xc9\xfc\x9f\x72\x84\xd8\x6c\x67\xdd\xbd\x87\x7b\x2c\xeb\xbb\xd2\x64\xf5\x5a\x80\xe1\xb0\xf7\xb4\xf2\xc3\x5d\x53\x87\xe6\xf2\x6b\xf4\x96\x98\x98\x6f\x75\x71\x10\x07\xf7\x5d\xe5\xb2\x0a\xed\x7e\xdc\x23\xbb\x4a\xba\xc3\x67\xe7\xb4\xac\x5f\x47\x3f\xe7\xef\xda\x63\x6d\x6e\x71\x0b\x93\x44\x78\x35\x77\xd0\x96\x1e\x4c\x28\x0f\x6e\x0c\xdc\x94\xe3\x57\xae\x3d\xa4\x01\xfb\x83\x4a\xfc\x8e\x0c\x61\x7d\x8a\xa2\xa9\x59\xa1\xda\x76\x39\x23\x72\x7d\x8e\xc9\x2d\x45\xcb\x48\x66\xf4\xf9\xec\xcd\x84\x7a\x17\xdb\xec\xc1\xd4\x18\x42\xfc\xe4\xc8\xa3\x80\xd2\x65\xcb\x1f\x5d\x06\x20\x68\x79\xe1\xfe\x6b\x5f\x72\x42\x60\x3a\x09\xc0\xdb\x76\xdb\xbf\x02\x00\x00\xff\xff\x2d\x4f\xe5\x21\xd9\x06\x00\x00") - -func resourcesAppMinimizePngBytes() ([]byte, error) { - return bindataRead( - _resourcesAppMinimizePng, - "resources/app/minimize.png", - ) -} - -func resourcesAppMinimizePng() (*asset, error) { - bytes, err := resourcesAppMinimizePngBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/minimize.png", size: 1753, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppSettingsPng = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x00\x8b\x04\x74\xfb\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x3c\x00\x00\x00\x3c\x08\x06\x00\x00\x00\x3a\xfc\xd9\x72\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xe1\x07\x1c\x07\x1d\x29\x01\xb2\xb4\x45\x00\x00\x04\x18\x49\x44\x41\x54\x68\xde\xed\x9a\x4b\x68\x55\x57\x14\x86\xbf\x3c\x7d\x24\xc6\x47\xf0\x19\x50\x70\x62\xa2\x49\x45\x2b\x62\x6d\xa8\x08\x22\x0e\x4c\xcc\x40\x10\x6d\x23\xa8\xa0\x03\x51\x4a\x07\xad\xa5\x52\x68\x11\x07\x62\xa9\xd2\x51\x55\xa4\x93\x82\x88\x28\x2a\x28\x54\xd2\xa8\x44\x8d\xa3\xd8\x26\x26\x46\xd4\xa8\xad\x82\x8a\x68\x42\xac\x37\xe6\xd5\x41\xd6\x85\xd3\xf4\x9c\xdc\xfd\x34\x9e\x6b\x7e\x58\xa3\xbb\xf7\x5d\xeb\xdf\x67\x9f\xbd\xd6\xfa\xf7\x81\x11\x8c\xc0\x06\x07\x80\x7e\x4d\xfb\x22\xae\x64\x47\x1b\x90\xed\x07\xae\xfb\x0c\x2a\xd3\xe3\x7f\x97\x1a\xce\x9b\x19\x57\xc2\x73\x0d\xe7\x4d\x03\x72\xe3\x48\x78\xde\x30\x2c\x56\x6c\x09\x97\xbd\x6f\x84\x4b\x87\x9b\x70\x86\xc1\xff\x4e\x7d\xcb\x84\x95\x62\xcc\x56\x18\x33\x11\x58\x0a\xbc\x04\x5a\x81\xe7\x92\x3e\xa2\x30\x16\x28\xb7\xdc\x3d\x65\xe2\xb7\x03\xe8\x4d\xb1\xb0\x85\xc0\x1c\x60\x32\x50\x23\x73\xac\x70\x22\x90\x23\x2f\x02\xdb\x24\xa0\xcc\x90\x15\xfe\x08\xf8\x05\xe8\x31\xcc\xc1\x41\xbb\x0b\xec\x04\x66\x45\xe4\xf8\x0f\x81\x1d\x40\x5d\x60\xce\xcf\xb6\x64\xd7\x47\x04\x73\x0b\xf8\x09\xa8\x04\xf2\x80\x7c\xe0\x1b\xe0\x91\x03\xa2\x83\xad\x1e\xd8\x28\xf1\x14\x01\x9f\x01\x47\x81\xfb\x21\x63\xbb\x64\x37\x1a\x61\x02\x70\x23\x45\x30\x4f\x80\xdf\x81\x0b\x40\xb7\x07\xb2\x49\x7b\x09\x9c\x11\xf2\x1d\x29\xc6\xd6\x9a\x12\xfe\x0e\x78\xe3\x91\x84\x2f\xeb\x04\xb6\xea\x92\xfd\x00\x68\x8a\x21\xd9\xa4\x5d\x05\x66\xe8\x1c\xef\xfb\x63\x4c\x36\x69\x5f\xaa\x12\x2e\x07\x1e\xa7\x01\xe1\xc6\xb0\x7c\x9e\x19\x92\x43\x37\x03\xd3\xd3\xa0\x17\x2f\x05\xd6\x01\x39\x43\x0d\x5a\xf1\x96\x56\xff\x1f\x31\xdf\x7e\xda\x81\x05\x51\xe5\x58\x9e\x14\x16\x8b\x3c\xad\xf8\x15\x49\x2d\xad\x72\x92\x22\xf9\xbb\x18\xa8\x00\x3e\xf6\xe4\xf7\x38\x50\x2d\x19\xe7\x3f\x98\xed\x69\x95\xef\x02\xab\xa5\x04\xcc\x8e\x28\x6f\x0b\x85\xf4\x3d\x0f\xfe\x5f\xcb\xab\xfa\x3f\x8c\x1a\x54\x46\xba\xb0\x0b\xb2\x73\x54\x91\x2f\xf5\xb0\xcb\x18\x76\x00\x59\x43\xe9\x50\xfb\x81\x3e\x47\x64\x4d\xe1\x82\xf4\x0b\x39\xb4\x94\xb0\x05\xf8\xdb\x72\x1b\xe7\x59\x10\x1e\x07\xb4\x59\xa6\xa4\xe5\xba\x4e\x3f\x91\x43\xcc\xc4\xe1\x6a\x07\x87\x4d\xa5\xa1\xef\xb3\x72\x10\x1a\xa1\x08\x38\x08\x24\x34\x1c\xd6\xc9\x21\x64\x8b\x42\xe0\x9a\x66\xaa\xdb\x27\x7d\xb4\xb5\x2a\xd2\xa0\x59\xd2\x65\x3b\x20\x9c\x03\x7c\xad\xe1\xf7\xa1\x2b\x89\xa7\x4f\x73\xd5\x5a\x45\x00\xb0\x45\x37\xd0\xa2\x31\x7e\xaa\x2b\xc2\x44\xa8\x0e\x61\x78\x1d\x28\x2a\x5c\xa0\x53\x9a\x7a\x15\xe4\xba\x24\x9c\x36\x50\x25\xac\xba\x45\xc7\x48\xf1\xe0\x0a\xf9\x52\x10\xa9\xa0\xcd\x25\xe1\x27\x1a\x41\x16\x3b\x3c\xb4\x4a\x34\xc6\xbf\xc0\xc1\x15\xcd\x24\xe0\x07\x79\x37\xdf\xf5\xb4\x94\x00\x0e\xdb\x5c\x00\xcc\x05\xce\x19\x26\xff\x0a\x07\x84\xab\x0c\x7d\xff\x11\x50\x39\x95\xb1\xc2\x52\xd3\xba\x67\xf9\x2e\x17\x44\xc8\xb0\x3a\x42\xde\x61\x60\xbc\x8a\xb3\x0d\x22\x8b\xda\x16\xef\x35\x16\x84\x6b\x1d\x75\x4a\xcd\xc0\xc2\x28\x27\x59\xc0\xe7\x8e\x5b\xb3\x1a\x69\x04\x74\x9e\x6c\x2d\xee\x7b\xe2\x8a\xa8\x3b\x21\x1f\x62\x7a\x9b\x34\x02\x85\x11\xfa\x52\x8e\xfc\x56\x65\xb9\x8d\x87\xb2\xbd\x61\x12\x4f\x2e\xf0\x2b\xb0\xd6\x53\xce\xaf\x17\x89\xa7\x65\x90\xc4\x53\x22\x0b\xb2\xc4\x93\xdf\x04\x30\x1f\xb8\x1d\xf6\xe3\x02\x85\xab\x0c\x17\x96\xd0\xec\xc0\x6c\x6c\x77\xaa\x7a\x74\x4f\x1a\x68\xd2\x49\x6b\x42\xe1\x23\x99\xb2\x98\x5f\xb3\x04\x6d\x93\xea\xbe\xff\x2a\x0d\xc8\x9e\xd7\xb9\x50\x28\x92\x0b\xa9\xb8\x92\xed\x60\xe0\x6e\x5b\x0b\xdb\x80\x57\x31\x25\x7c\xd2\xb4\x81\x49\x25\xe2\xb5\x4b\x81\x7f\xda\x51\x75\x96\xaa\x46\x3e\x25\xe9\x65\xa8\x71\x4f\x81\x65\xa6\x39\xac\x5c\x14\x87\xb0\x62\xe2\x08\xf0\x69\xe0\x3d\xa9\xd6\xec\x6e\x74\xb6\xe7\xa1\x40\xab\xb8\x18\xd8\x05\xfc\x16\x91\xda\x8e\xd8\x26\xee\x43\x81\x3f\xbb\x04\x6c\x97\xfa\x34\xac\x31\x9f\x29\x4a\xff\x1d\x07\x44\x7b\x81\x63\xc0\x4a\xb9\x20\x18\x8c\x19\xc0\x2a\xe0\x47\x79\xaa\xc9\xa7\x3b\xc5\x96\x70\x01\xb0\x86\x81\x8f\x45\x26\x2b\x88\x06\x59\x22\xfa\xfd\x65\x41\xb6\x1b\xf8\x5e\x51\xed\x18\x2b\x9a\x5b\x15\x03\x9f\x2f\x39\x41\x86\xc1\x9c\xf3\x16\x84\xbb\xe4\xe9\x39\x8f\x51\x55\xe2\xe9\x37\x20\xdc\x64\xb1\xc0\xbd\x9a\x12\xad\x72\x8c\x3e\x55\x4b\x1b\xc2\x3d\xc0\x83\xe1\x54\x2d\x4d\xd0\x68\x31\xb7\xcd\x57\x50\x3e\x09\x37\x5b\xcc\xfd\x33\x8e\x84\x13\xc0\x33\xc3\xb9\x37\xe3\x48\x18\x83\x83\x27\x89\x06\x5f\x01\x65\x78\x26\x5c\x06\x7c\x2b\x85\x43\x9f\x42\x2c\x99\xc0\x65\x06\xae\x3d\x47\x30\x02\x03\xfc\x0b\x7e\xbe\x22\xc0\xbf\x5c\x64\x85\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\x01\x00\x00\xff\xff\x3e\xfd\x31\x35\x8b\x04\x00\x00") - -func resourcesAppSettingsPngBytes() ([]byte, error) { - return bindataRead( - _resourcesAppSettingsPng, - "resources/app/settings.png", - ) -} - -func resourcesAppSettingsPng() (*asset, error) { - bytes, err := resourcesAppSettingsPngBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/settings.png", size: 1163, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppStaticCssBaseCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x7b\x6f\xdb\x38\x12\xff\x3f\x9f\x42\x68\x51\x24\xc1\x55\x5a\x3d\x2c\x3f\x14\x1c\xb0\xd7\x5d\x14\x57\x60\x7b\x58\x6c\x0a\xec\x01\x87\xc3\x81\x96\x68\x9b\x08\x4d\xfa\x28\x3a\x89\x5b\xf4\xbb\x1f\x28\x51\xe2\x43\x94\x1c\xa5\xce\xb6\xe9\x6d\x0d\xa4\xb6\x44\x0d\x67\x86\xf3\xf8\xcd\x8c\x7e\x5c\x51\xc2\xfd\x15\xc8\xa1\xf7\xe9\xcc\xf3\x3c\x4f\xfe\xde\x22\x7c\xc8\xbc\x73\x42\x39\xfd\x4f\x09\x48\x79\x7e\x55\xdd\x2d\x59\x9e\x79\x7b\x86\x2f\xce\x83\xe0\x07\xb1\xb4\xfc\xe1\x1f\x94\xd3\x6b\x40\x4a\xff\x37\xb8\xde\x63\xc0\xfc\x3b\xb8\x14\x77\x02\xce\x57\xe7\x97\xde\x8a\xb2\x2d\xe0\x17\xe7\x9c\xed\x21\x3f\xec\xe0\xf9\xe5\x95\xda\xe7\x0e\xa2\xf5\x86\x67\x1e\x11\x8b\xb0\x76\xa3\xe4\x07\x0c\xd5\xf5\xcf\x67\x67\x27\x64\xf4\x0d\xc5\xc5\x63\xb8\x5c\x52\x5c\xfc\x51\x3c\xbe\xe3\x00\xa3\xfc\x94\xba\x44\x15\xc5\xa7\xd0\xe5\xe3\x79\x75\x6b\x54\xe3\x74\xc3\xb7\x58\xf2\x98\x53\x4c\x59\xe6\xbd\x8c\xa7\xe2\x73\xd5\xe5\xfb\x45\xcb\xf7\x0b\x9d\x26\xfa\x08\x33\x2f\x0a\x77\xf7\x8e\xfd\x27\x61\x58\x5f\x15\xcc\xdf\x20\xee\xd7\x8f\x6c\x29\xe5\x1b\x44\xd6\x99\x07\x08\x47\x00\x23\x50\x42\xc9\x27\x86\x9c\x43\xe6\x97\x3b\x90\x57\x0b\xe4\xf3\x18\x11\xe8\x6f\x24\xd5\x28\x88\x2b\xe6\x83\x15\x86\xf7\x92\xfb\x02\x95\x3b\x0c\x0e\x99\xda\x09\x43\xc9\x51\x7b\xab\xbe\x24\x1e\xfc\x1d\x60\x0c\xb9\x7c\xf4\x0e\x15\x7c\x93\x79\xd3\x30\x0e\xe2\x46\x8a\x66\xab\x78\x9e\x36\x97\xb6\x80\xad\x11\xf1\x31\x5c\x09\x16\x9a\xab\x4b\xca\x0a\xc8\x7c\x06\x0a\xb4\x2f\x33\xaf\x25\xb0\x04\xf9\xcd\x9a\xd1\x3d\x29\xfc\x46\xb1\xab\xea\x5f\xf3\xd8\xbd\x5f\x6e\x40\x41\xef\x32\x2f\x14\xd4\xc4\x93\x5e\xe8\xbd\xcc\x57\xe2\xa3\xd3\xce\xbc\x92\x62\x54\x54\x8b\x5e\x16\x71\x91\x14\x8b\xab\x47\x88\x7c\xcd\x01\x2f\x4d\x89\xa3\xe9\x90\xbc\x3b\x50\x14\x88\xac\x7d\x26\x95\x9e\x04\xd5\x2d\x41\xeb\x17\x44\x1a\xcb\x96\x5a\xe1\x74\x97\x79\x93\x49\xd0\x3e\x2d\xb7\xe8\x6e\x90\xa4\xc1\xcc\x52\x5e\xad\x52\x5d\xca\xa5\xf8\xd4\x7b\xbd\xdd\x93\xc2\xe2\x7b\x92\x74\x0f\x2a\x9a\x1b\x06\xf8\x20\x9b\x9d\x38\x6d\x56\xf9\x8c\x65\x74\x51\x72\x65\x3a\x4a\x2a\x3e\xa6\xb2\x2a\x3d\x34\xaa\xd2\x6f\x48\xb3\xd1\x94\x28\x0e\xc4\x15\x1e\x06\x59\x9e\x1f\x63\xd9\x76\x9f\x60\xd2\xc3\x49\xcb\x61\x2b\xce\x12\x14\x71\x62\xd8\xfa\x92\x72\x4e\xb7\x99\xe7\xcf\x1b\xa6\x77\xa0\x90\x3c\x9b\x12\x47\xcd\x02\x0c\x96\xb0\x89\x28\x54\x70\xc1\x0f\x82\x8b\x59\x3a\xf6\x70\x22\xa5\x43\xe3\x1c\xe2\x60\x22\x99\xe4\xf0\x9e\xfb\x00\xa3\x35\xc9\x3c\x21\x94\x29\x4e\x58\xfd\xeb\x17\x5d\x30\xbb\xe4\xb9\xcf\x29\x07\x78\x58\xa6\x0f\x74\xbd\xc6\xf0\xcd\x9e\x73\x4a\x2c\x0f\x4a\xa6\xc1\xdc\x36\xc5\x24\x0a\x92\x93\x87\x87\xd0\x0b\x3d\xb6\x5e\x82\x8b\x38\x5a\xbc\xf6\xd4\x9f\x30\x48\x2f\xfb\xa3\x85\xf4\xa3\xb1\x9a\x9f\x1d\xb1\x32\x97\x07\x98\xe1\x51\xf3\x00\x3d\x42\xa4\xd3\xd6\xea\xf6\xac\x14\x34\x76\x14\x11\x0e\x99\x1e\x96\xff\x96\x73\xd4\x51\x74\x18\xbe\xaa\xd7\xfc\x04\xc5\x7a\x79\x57\x37\x81\x1c\x2a\x42\xd7\x90\x14\xef\x29\x81\x07\xd7\xc1\x26\x53\xe5\x14\xad\x77\x4f\x55\x48\x39\xa1\x37\x1a\x01\xe4\xa8\xee\x5a\x77\x6b\x0d\xf4\xef\xa8\x28\x20\xb1\x53\x1c\xa1\x04\xd6\xf7\x4b\x52\xbc\x07\x6c\xed\x88\xc5\xad\xc7\x0a\x55\xbc\x45\x10\x17\xa3\x13\xa5\xb8\x54\xe9\xd6\xcf\x29\xe1\x90\x70\xa5\xe3\xce\xc9\xd8\xdb\xd7\x78\x40\xec\xff\x33\x2c\x73\x86\x76\xda\x91\x3e\x5c\xbf\x71\x30\xed\x44\x29\xa9\x36\x9b\x74\x00\x4a\x0e\x19\x2a\x6f\xf4\x4d\x06\x2c\x57\x06\xbb\x0a\x45\x08\xed\xe8\x71\xcb\x10\x24\xb1\xec\xb8\x49\x87\xad\xb9\x8c\x4b\xc3\x9c\x9a\x9b\xd4\xfe\x92\x26\x8d\xba\xc0\x96\xee\x09\x77\xad\x89\x5b\x95\x12\xca\xa1\x6b\xc5\x64\x2a\x57\x20\xb2\xdb\xf3\x2c\x6b\x18\xa2\xfb\x3a\x27\x08\x13\xab\x82\xd8\x6b\x7b\x05\x22\xc4\x5c\x21\xc9\x37\xf7\xc1\x6e\x07\x01\x03\x24\x87\x8d\xf5\xa9\xcd\x2b\x8c\x26\xd8\xaa\x68\x9a\x6e\x1b\x2f\xa6\x9d\xe8\x18\x07\x93\xf1\x9e\x36\x60\x09\xdd\x00\x9f\x06\xf3\xd6\x83\x7e\xc2\x10\x30\x93\xa9\xa4\xc3\x53\x34\x0b\x5a\x40\xa7\x25\xad\xd1\x39\x4b\xe3\xb2\x9b\x88\x93\x21\x01\xba\xbe\xd3\x1b\x24\x4b\x48\x8a\x3a\x44\x96\x4e\x7b\xed\x44\x5e\x69\x3e\xd3\xb4\x56\x7c\x13\x14\xde\x70\x2b\xc6\xce\xa3\x60\xd1\xc5\x83\xa3\x72\x19\xda\x82\x35\xcc\xaa\xb8\x07\x98\xbf\x16\x4b\x21\xe1\x17\x9c\x7a\x75\x6c\x7b\xed\xbd\x4c\x27\x45\x3a\x99\xbd\x6e\x5c\xf0\xd2\x95\xf0\x42\x2f\xa9\x52\x5e\x95\xf0\xa2\xc9\xe2\xb5\xa7\xfe\xf4\x25\x3c\x81\x9f\x8d\x1c\xfa\xa8\x63\x3b\x12\x36\x74\xfa\xba\x76\xe7\xca\xa6\xcd\x30\xe1\xc7\xc3\x87\x09\xaa\x83\x7c\xd3\x9a\xa8\x79\x64\x1d\xdf\x99\x2b\xb4\xa1\x85\xdf\x3a\xb0\x80\xa5\xa4\xe1\x3a\x3b\xdd\x44\xfa\x22\x5a\xf8\x95\x6b\x9a\x2a\x86\xe4\x9d\xcc\x3f\x75\x80\x7d\xed\x9a\x2e\xd9\xd4\x5d\xab\xb5\x81\x53\xe4\x31\x46\x71\x81\x6e\x9b\x9a\xd7\x75\x26\x72\xd5\x3b\xc5\x8a\xa1\xa8\x23\xee\xc9\xc1\xf2\x03\xbc\xe7\x0e\xd7\x0c\x9d\xdc\xa5\x5f\x14\x0c\x1f\x02\x3c\x8e\x21\x66\x97\x19\x68\x7a\xb8\xde\xa9\x3e\x46\x13\x41\xd3\x76\xd1\x16\x11\xb4\x45\x1f\xa1\x4b\x53\x5e\x1b\x85\xff\xcb\x72\x5a\x58\x44\xa2\xb9\xad\x10\xa1\xa5\xb9\x4b\x49\xd1\x24\xea\x9a\x40\xdc\x10\x97\x59\xd6\x07\x45\xc1\x60\x59\x0e\x40\xc3\x8e\x6a\x92\xc4\xae\x57\xe7\xb3\x20\x4d\x87\x72\xd6\x73\x44\xf4\x47\xb2\xa7\x61\x8f\xb3\x74\xd0\xbc\x09\x84\x76\x05\x28\xbd\x4c\x35\x13\xcc\x32\x4a\xc1\x16\x08\x0b\x7f\xbc\x83\x5b\x7d\x88\xb8\xae\x4e\x5a\x82\x4b\xc4\x73\x8a\xc6\x63\x4b\x2d\x4f\x8e\xa8\x72\x2a\xab\x2a\x60\x4e\x19\x10\x81\x3b\xdb\x93\x02\x32\x61\x52\x03\x2a\xdb\xd1\xdd\x7e\xd7\xe8\x8c\x96\xa8\x7a\xd0\x63\x10\x03\x8e\x6e\xa1\x85\x14\x11\xa9\x0c\x74\x89\x69\x7e\xd3\x43\x53\x07\x66\xfb\x52\x80\x0c\x88\x61\xce\x75\x64\xe6\x6f\xe9\xc7\xfe\x7b\x65\xdf\x2d\xc7\x65\x25\x40\xfd\x1f\x57\xb1\xed\x16\x95\x68\x89\x70\x05\x96\x36\x55\xa1\xd2\x49\x96\xdd\xb0\xa3\xbb\xa2\x3c\xd9\xcc\x9b\x05\x55\xa6\xb8\xb2\x54\x04\x96\x25\xc5\x7b\x2e\x99\xfb\xe8\x23\x52\xc0\xfb\xb6\x90\x6a\xaa\xa5\x28\x4e\x5f\x35\x98\xab\x0a\xa8\x56\x3d\x52\x5f\xf5\xa3\xba\xec\x37\x9c\x3d\x0c\x83\x8e\xaf\x47\x51\xaa\x60\xd0\x49\x9c\xdd\x8f\x55\x2a\x84\x73\x38\x83\xb3\x07\xa5\x42\x5b\xeb\xd9\x12\xae\x28\x83\x6d\xb7\x56\x96\x64\x2f\x5e\x0c\xab\x4d\x3a\x61\x68\xe8\x68\xea\xd4\x91\x0d\x00\x5a\x88\x61\x5d\x97\x6d\xe4\x8a\x6f\xe3\x46\xa3\x8b\x5a\x0c\x8f\x33\x40\xca\x1d\x60\x90\xf0\xbe\xef\x3d\xa2\x66\x60\xa5\x8a\xfc\xa7\x10\xd5\xee\xdf\x4a\x51\xed\x83\x3f\x2a\x69\x7d\xea\xa3\x25\x2d\x37\xf4\xce\xe1\x45\xd5\x77\x0c\x4d\x17\x07\x04\x6d\xeb\x60\xe3\xad\x40\x01\xdf\x11\x2f\x98\x95\xb2\x3a\x77\xdf\xfa\x7c\x76\xf6\x63\xf3\xf4\x0d\x3c\xac\x18\xd8\xc2\xb2\x59\x21\xe3\x24\xa3\x5b\xef\x93\xaa\x75\xae\x3e\x4b\x0d\x6a\x17\xa3\xab\xcf\x15\xa9\xc7\x93\x88\xbc\x9a\x44\x50\xee\x99\x9d\xfd\xdb\x63\xea\x8b\x0e\xc3\xa1\x5c\x83\x0c\x0b\x23\x8e\x3f\x3a\xbc\x0b\x3e\xef\x00\x23\x88\xac\x4d\x56\x67\xe9\x11\x4e\x4d\xd0\xfe\x40\x40\xa7\x09\x60\x0d\x4f\x6a\x09\x16\x43\x19\xbb\xe2\xe4\x8e\x81\x5d\xa6\x4f\xa3\x64\x08\x53\xe0\xac\x84\x3b\xc0\x00\xa7\x56\x01\xbc\x58\x04\xf3\x57\x66\xd4\x73\x41\x31\xcf\x5f\x0c\xc4\x3b\x7d\x12\x61\x46\xb2\xa0\x13\xca\x72\x4a\x56\x88\xd5\xa6\xda\x5f\xba\xce\x7b\x2a\xd7\xa9\x42\xa4\x80\xe4\x10\xff\xda\xf6\xa0\x2d\xb4\xd9\x29\xc2\xea\xa2\x40\xb5\xdc\x73\xb0\xd7\xfa\x50\x52\x12\x06\x8b\xd1\x78\xca\xb5\x4f\x64\x5d\x6c\xbb\x79\x76\xbd\xa5\x57\x25\x27\x03\xeb\x88\xdc\x02\x8c\x0a\x7f\xa5\xb5\xfa\x8c\xfd\xe6\x36\x1b\x2d\x7f\xaa\xb1\x94\xef\x19\x83\x24\x3f\x5c\x57\x10\xc0\x45\xc5\x9f\xda\x13\x1e\x75\x61\x74\xbb\xff\x48\x16\x1d\x81\x60\x95\xae\x7c\x0c\x4a\x9e\xe9\xbd\xe0\x0f\x22\x06\x03\xc3\xea\xc6\x4d\xfc\xac\xa6\x8c\x3b\x8f\x58\xcd\xd9\x93\x56\x0a\xe3\x47\x83\x0d\x66\x56\x18\xa9\x3d\xa4\x5b\xc8\x56\x98\xde\xf9\x87\xcc\x2b\x73\x46\x31\xee\x6a\x49\xf5\x05\xeb\x15\x4b\xc0\x7c\xce\x40\x7e\x73\xf6\xa9\x4f\x80\xb7\xa9\xf8\x3c\x88\xd4\x99\xd9\x74\x1a\xd0\xca\x08\xa2\x3e\xdf\xec\xb7\xcb\x7e\xfe\x5c\xba\x13\x6a\xad\xf5\xd7\xde\xae\x0a\x78\x6d\x27\xbf\xb7\x2d\x6c\x87\x80\xba\x4e\xed\x16\x32\xe9\x37\x34\x57\x88\xda\x92\x99\xdf\x9b\x9e\x90\x4e\x1d\x9e\x90\xc6\x5f\x0c\x83\x07\xeb\x57\x23\xd5\x38\xf5\xa9\xa9\xd9\xa8\x29\xe3\xbe\xf1\xaa\x26\xa0\xaf\x55\x2a\x8f\x18\x09\xbb\xd0\x81\x24\x1a\x8f\x9f\x63\x0c\x51\x15\xc7\xda\x3f\xb4\x90\xfb\xd6\x5a\x71\x36\xfd\x5b\x91\xd1\x16\x0e\xac\x53\x53\xcf\x7c\x03\xf3\x9b\x2d\x60\x37\xf6\x8b\x1f\xda\x4c\xc4\x99\x29\x0f\x10\x63\x7a\x27\x17\x30\xda\xb6\x5a\xf4\x44\x5a\x35\x64\x20\x07\x08\x97\x35\xa8\xb6\x46\xf7\x93\x36\xd9\xdc\x22\x78\x27\x57\x5a\xf0\x64\xd6\x8d\xc9\xcf\xbb\xfb\xf2\x98\x4e\x43\x4f\xef\x9f\xf3\x0e\x3e\x5d\xcc\x2c\x30\x97\x86\x4f\xe9\xa0\x2e\x97\xeb\xe2\x84\x48\x0d\xab\xfa\x13\x70\xcf\xec\x30\x69\xf9\xef\x9b\xef\x4a\x3d\x18\x38\xa5\xa1\xa9\x3a\xee\x8d\x3e\x16\x8b\x57\x5f\x1d\xa1\x18\xda\x49\x42\x87\x84\x5d\xe4\x22\xa5\xfc\x45\xe4\x20\x73\xac\x16\x76\x64\xd4\xca\x5e\xa3\xc1\x19\x74\x10\x92\x8e\x26\xfb\xde\x09\x39\x4d\xc0\xac\x06\x82\xff\xe2\x87\x1d\xfc\x6b\x15\x73\x96\xf4\xfe\xdf\xe6\x88\x22\x34\xa0\xa4\xfc\xe5\xea\x2b\x7d\x3e\x3b\xd3\x53\xb1\xb3\x27\x56\x89\x88\x48\x51\xf5\x0a\xfc\xc5\x62\xb1\xb0\xa0\x6a\xda\xd1\x9a\x4a\x24\xea\xa4\x33\x6f\xcd\xe0\xc1\x42\x75\x5a\x3f\xce\x0e\x41\x2a\x17\x39\x7a\x7b\x0d\xdf\xee\x86\xc6\xf9\xf9\x03\x1a\x1a\xb1\x1a\x29\x1a\xf3\x82\xd6\x16\x3a\x42\x39\xdc\x5f\x6f\xc7\xd9\x02\x28\x5b\x14\x8e\x2a\x19\x09\x83\xa4\xd4\x66\xc9\xd5\xf9\xc1\xc2\xfb\x8b\xa7\x1f\x83\x41\x5f\x4b\x1f\xce\x67\x0c\x15\xd4\xb2\xe4\x00\xe7\x17\xc2\x72\x3d\x5f\xc8\x75\xa9\xb1\xb1\xa2\x6c\x9b\xd5\x5f\x31\xe0\xf0\x9f\x17\xbe\x58\x77\xa9\x6b\x34\x17\x2a\x36\xa8\x36\xe3\x89\xd0\x48\x75\x9a\xff\x74\xbd\xa5\xc9\x4b\x0a\xf5\xbb\x3d\xc5\x7a\x17\x6c\xfe\x47\xf8\x4f\xcd\xfe\x7b\x47\x4a\xb7\x5e\x4d\x30\x03\x7f\x35\x96\x21\x70\x4b\x09\xca\x1d\x8f\xf9\x7d\xa5\x8c\x1d\xe1\x35\x70\xde\x38\x50\x12\x8e\x96\x30\x76\xe4\xe8\xcc\xcc\x33\xae\xa4\x5e\x0b\xf1\x33\x2c\x5d\x22\x1c\x03\x8b\x5f\xc0\xae\xaa\xa8\x19\x2c\x39\x65\x6e\x48\x55\x71\x31\x1b\xe0\x42\x10\xf8\xad\x26\xd0\x99\xb3\x47\x93\xae\xcb\xf6\x8c\x6a\x7b\x5e\x3e\x1d\xd3\x9f\xfe\x7f\x1a\xc9\x3b\x31\xd3\x96\x38\x5e\x4c\x99\x74\x33\xe8\xc9\x5f\x4c\xd1\x8c\xe8\xf7\xef\xa1\xaf\x38\x4d\x2d\xd7\xf8\xf5\xb9\x0f\xb6\x0c\x39\x8c\x5f\xcf\x77\xcc\x55\xa7\x73\x0b\x2d\x3a\xc6\x5c\x49\xf8\x6d\x8c\xb9\x86\xcf\xe0\x3b\x1e\x7a\x1d\x11\xfc\xbb\x1d\x81\x99\x72\x3f\xf9\x24\x4c\xa4\xe1\x03\xc9\xbb\x6f\xbb\x75\x5c\xa2\x2f\x09\x2f\x9c\x49\x38\x9e\xfd\xf9\x62\xdc\x88\x2c\xcc\xaa\x53\x78\xb6\xa5\xac\xe4\xff\x7b\xc8\x78\xad\x18\xfa\x8f\xe7\x9b\xef\xe6\xcf\xeb\xad\x8e\xa1\x03\x38\x65\xb2\x9b\x45\xdf\x5a\xb2\xeb\x17\xfb\x84\xa9\xce\x2d\xf6\x57\x4c\x75\x4a\xea\xa7\xcf\x74\xe5\x86\x32\xee\x7a\x0b\x7f\xb8\xd8\x71\xd6\xb4\x27\xaa\x80\x6a\x9e\xde\x09\x9e\xba\xb1\x3f\x8a\xbb\x7e\xda\x17\xfb\xe7\x5f\x31\xf6\x5f\x43\xfe\x05\xf0\x21\xb2\x5f\x0c\x90\x5c\x4e\xec\xe2\xbe\x79\x65\x5c\xeb\x7f\xff\x89\x2c\x8e\x20\x8b\xff\x05\x00\x00\xff\xff\x96\x35\xdf\xd4\x5f\x3f\x00\x00") - -func resourcesAppStaticCssBaseCssBytes() ([]byte, error) { - return bindataRead( - _resourcesAppStaticCssBaseCss, - "resources/app/static/css/base.css", - ) -} - -func resourcesAppStaticCssBaseCss() (*asset, error) { - bytes, err := resourcesAppStaticCssBaseCssBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/static/css/base.css", size: 16223, mode: os.FileMode(436), modTime: time.Unix(1501701765, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppStaticFontsNotosansBoldWebfontTtf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7d\x5c\x5b\xe9\x79\x27\x8c\x5f\xe7\x1c\x71\x24\x84\x10\x7a\x7f\x43\x12\x42\x48\x42\x08\x21\x09\x21\x30\x2f\x02\x84\x20\x84\x52\x4a\x1c\x8f\x97\xa5\x94\xf1\x32\x94\x10\x4a\x18\xc2\x50\x96\x12\xe2\x9f\x43\x1c\xe2\x10\xd7\x71\x89\x43\x5c\x4a\xa9\x43\x08\x65\xa9\x4b\xbd\x94\xa5\x2e\x65\x89\xeb\x38\x2c\x1f\x97\x50\x4a\x1d\xea\x12\xea\xb2\xae\x43\x5c\xe2\x52\xca\xba\x2c\xe5\xe7\x32\xcc\xf3\xd1\x7d\x64\xeb\x16\xa0\x19\xc8\xcc\x6c\xf6\x79\x3e\xf3\xc7\x5c\xbe\xe6\xcb\x75\xee\x97\xeb\xbe\xde\xee\xeb\x48\x00\x04\x00\x88\x09\x00\x16\x38\x0a\x0b\xcf\xfe\xd2\xaf\xac\xbd\xde\x0f\x40\xb8\x01\x40\xfd\xf1\x82\x8f\x15\x7e\x22\xea\xe3\xa5\x00\x44\x39\x00\xb1\xf4\xf1\xd3\x9f\x78\xed\x4b\xef\xfc\xd5\x1c\x00\x65\x05\x22\x69\xe5\xe3\xaf\xfd\x07\xef\x97\x7e\x7f\xf4\x9b\x40\x24\x73\x00\x38\x8a\x4f\xbc\x66\x77\xfe\x1b\xfb\xf7\xde\x02\x22\x43\x07\x00\x55\xbf\xfa\xe6\x1b\x4d\xff\x6d\xaa\x20\x13\x88\x8c\x0e\x80\xb0\xfd\x5f\x6d\x6d\xd1\xc9\xbf\x2b\x9b\x07\x22\xb7\x03\x00\xce\xd4\x36\x7d\xfa\xcd\xd7\x26\xec\xff\x05\x88\xdc\x25\x00\xf2\x53\x9f\x7e\xe3\xd7\x9b\x00\x40\x00\x84\xd7\x37\x3f\xe7\xd3\x0d\x9f\xab\x55\xfe\xfd\x37\x36\x81\xf0\x16\x40\x58\x59\x47\xdd\xa7\xde\xa8\xa1\xfe\xe7\x1b\x06\xa0\x7b\x67\x00\x20\xad\xae\xee\x53\x6f\x44\x19\x22\x23\x81\xee\xdd\x03\x00\x43\xdd\x9b\x2d\x6d\x05\xfd\x3f\x79\x0d\xe8\xdf\xd1\x01\x18\x6f\x37\x7c\xf6\x57\xdf\x50\xff\xb0\x79\x08\xe8\x3b\xcb\x00\xc6\xe9\x37\xdf\x68\x6b\xe2\xae\x50\x33\x40\xaf\xf5\x00\x80\xae\xf1\x8d\x37\x3f\xd5\x26\xfb\xce\xbf\x01\xbd\x36\x01\xc0\x9a\x6b\xfa\xec\xaf\xb7\xf0\xff\x9c\xfc\xff\x01\xfd\xd3\x0e\x80\x4f\xa7\x36\x35\x7f\xaa\xe9\xee\x0f\xfe\xc7\x27\x80\x7d\x7a\x12\x80\xf8\xe5\xdf\xf8\x54\x75\xed\xdf\xfc\xa7\x4f\x3e\x05\xf6\x19\x09\x00\xd0\x00\x48\x7b\x30\x9f\x3d\xf8\x57\xbe\x7f\xbf\xd7\xe7\x7a\xee\xfb\x77\x81\xf7\xe5\x15\xf4\x13\x3e\x00\xa1\x23\xcc\x00\x40\x42\x12\x00\x78\x81\x80\x7c\xc8\x07\x0a\x0a\xe0\xd7\x80\x80\x7a\xa8\x07\x0a\x3e\x03\xff\x19\x08\x68\x85\x56\xa0\xe0\x37\xe0\x73\x40\x40\x3b\xb4\x03\x05\x9f\x27\xdb\x81\x20\x3f\x4f\x7e\x09\x28\xb2\x93\xfc\x0a\x10\x64\x17\xf9\x6d\xa0\xc8\x41\xf2\x8f\x80\x20\x6f\x91\x13\x40\x91\x7f\x42\xfe\x09\x10\xe4\x6d\x4a\x00\x14\x25\xa4\x84\x40\x50\x22\xca\x05\x14\x95\x4a\xa5\x03\x41\x65\x50\x99\x40\x51\x59\xac\x14\x20\x58\x2e\xd6\x29\xa0\x58\xe9\x61\xbd\x40\x84\xfd\x4e\xd8\xef\x03\x15\x36\xcc\x2e\x06\x82\xfd\x8b\xec\x4f\x00\xc5\x3e\xcd\xfe\x65\x20\xd8\x15\xec\x4a\xa0\xd8\xaf\xb3\x6b\x81\x60\x7f\x9a\xfd\x6b\x40\xb1\xeb\xd9\xad\x40\xb0\x7f\x83\xfd\x39\xa0\xd8\xed\xec\x2f\x01\xc1\xee\x64\x7f\x19\x28\xf6\x25\x4e\x27\x10\x9c\x2f\x73\x2e\x01\xc9\xf9\x0a\xa7\x0b\x08\xce\x57\x39\x57\x80\xe2\x7c\x8d\xf3\x5b\x40\x70\xba\x39\xdf\x00\x8a\xd3\xc3\xf9\x26\x10\x9c\xeb\x9c\xef\x00\xc5\x19\x0a\x7f\x0d\x88\xf0\xb3\xe1\x0d\x40\x85\xbf\x19\xfe\x26\x10\xc0\x42\x5a\xf1\xfd\xa7\x26\xef\x91\x0f\x81\x24\x97\xc9\xbf\x03\x8a\x7c\x44\x3e\x02\x92\x5c\x25\x9f\x00\x45\xfe\x84\x5c\x07\x8a\xfc\x27\xf2\x7f\x03\x45\xfe\x3b\xb9\x0f\x14\xf9\x0e\x45\x00\x49\xb1\x28\x1a\x48\x8a\x4d\xb1\x81\xa2\x38\x14\x07\x48\x2a\x9c\x8a\x00\x8a\xe2\x51\x7c\x20\xa9\x28\xa4\x0d\x11\x25\x01\x92\x92\x52\x0a\xa0\x28\x25\xa5\x04\x92\x8a\xa6\xd4\x40\x51\x1a\x4a\x03\x24\x65\xa4\x92\x81\x44\x3a\x21\xc3\x7e\x27\xac\x0f\xc8\xb0\xdf\x0d\xfb\x5d\xa0\xc2\xfa\xc3\x06\x81\x0c\xfb\x4e\xd8\x77\x80\x0a\x1b\x0a\x1b\x02\x32\xec\xf7\x7d\xba\x42\xbb\x23\xd0\x99\x72\xa1\x14\xae\x01\xf5\xab\x9f\x6b\x6e\x00\xc9\xa7\x9b\x3f\xf5\x19\x30\x34\xbc\xd1\xd2\x08\x2e\xb4\x23\x78\xe7\x1d\xa0\x90\x5d\x50\x41\xff\x4f\x1e\xf5\xff\x9f\xf9\x54\x73\x23\xa8\xde\x7c\xa3\xf9\x33\xa0\x43\xd4\xf4\xe6\x67\xde\xfc\x0c\xb8\xd1\xf3\x11\x88\xfa\x66\x0c\x47\x1c\x33\x42\x18\xd0\xc0\x06\x0e\x1a\x21\x1c\xb8\xc0\x03\x15\xe8\xc1\x02\x4e\xc8\x04\x2f\x14\xc3\x19\xa8\x80\x6a\xa8\x87\x66\x34\x1b\xf1\xcd\x32\xe6\x5f\xa2\x88\xf9\x97\xbe\xc9\xfc\x4b\xed\x31\xff\xbe\x51\x00\x2c\x02\x80\x48\xaa\x63\xfe\x9f\x6c\x60\xfe\x15\xdb\x98\x7f\x41\x0f\x34\x09\x40\x44\xae\x02\x4d\x01\x10\x5c\x35\x90\xc0\x01\x72\x75\xe7\xc7\x99\x40\xc0\x22\xdc\x02\x02\x96\x81\x07\x12\xb0\x80\x03\xd2\xc0\x0d\x5e\x28\x82\x52\x38\x0b\x15\x50\x05\xb5\xd0\x00\xcd\xd0\x06\x17\xa0\x13\x2e\x43\x37\x5c\x87\x7e\x20\x58\x02\x28\x03\x82\x9a\xf2\x51\xd6\x5b\x3e\x4a\x92\x08\x91\xed\x37\x01\xc1\x1a\xf1\xf1\x44\xdd\x7e\x27\x10\xac\x9d\x77\x36\x80\x20\xfe\xda\x87\xb0\xbd\x48\x1e\xfd\x94\x19\x81\xf5\xd6\xfe\xd2\xcb\x9f\x52\x3a\x44\x4f\x21\x7c\x10\x8d\xf9\x63\x1f\x0d\xfb\x12\xc2\x6f\x42\x19\x90\x10\x06\x1f\x83\x8f\x03\xc0\x2f\xc0\x2f\x02\x05\xbf\x04\x9f\x04\x1a\x5e\x83\x0a\x88\x80\xd7\xe1\x75\x10\xfb\x74\x4c\xfe\x98\x5c\x43\x56\xc9\x65\xe2\x10\x80\xef\x79\x40\x23\x12\x32\x58\x05\x82\xd0\x23\x9d\x1f\x67\xa7\x83\x30\x02\xb7\x60\x02\xa6\xe0\x2e\xcc\xc2\xbc\x6f\x95\x34\x0b\x08\x52\xc4\x1a\x03\x82\xac\x66\x37\x00\x41\xfe\x0f\x76\x0f\x10\xe4\x3d\x84\x57\xfb\x28\xf5\x8b\x0c\xf5\xe1\x94\x1d\xe1\xff\x05\x21\xdf\x42\x3c\x07\xf1\xa3\x88\x9f\x45\xf4\x33\x68\xb4\xd7\x11\xfd\x07\x86\xd2\x67\x81\x20\xdb\x11\xff\x71\x1f\xa5\x6a\x7d\x94\x18\x42\xbc\x16\xe1\xe5\x88\xbe\x45\x2b\x7c\x32\x3e\x79\x50\x11\x9f\x24\xbe\x45\x8d\x53\x7f\x4e\x7d\x8f\x9a\xa5\xfe\x82\x9a\xa3\xfe\x8a\x5a\xa2\x1e\x51\xab\xd4\xff\xa4\x1e\x53\xff\x40\x3d\xa5\x7e\x4a\x3d\xa3\xfe\x85\xda\xa6\xf6\xa8\x7d\xea\x1d\x16\xb0\x48\x56\x94\xcf\x8f\xc9\x7b\xe4\xf7\xc9\x59\x72\x01\x59\x8c\x08\x00\x14\x00\xa0\xf5\xc5\x63\x20\xde\xee\x61\xf5\x03\xf1\x76\xb9\x8f\x02\x04\x28\x51\x4b\x68\x81\x20\x1a\x80\x07\x7a\x28\x84\x12\x38\x03\xe5\x70\x0e\x6a\xa0\x1e\x9a\xa0\x15\xce\xc3\x45\xe8\x82\xab\xd0\x03\x7d\x30\x00\xc3\x30\x0a\xe3\x30\x09\x77\x60\x06\xe6\x60\x11\x1e\xc2\x23\x78\x02\xeb\xb0\x09\xdb\xf0\x82\x00\x82\x26\x78\x40\x90\xa3\xc8\x7e\xff\x0e\xd1\x0e\x64\xe3\x3a\x64\xf9\xdd\x08\x59\xc4\xf0\x22\x44\x5d\x08\xd9\x44\xd4\x81\x68\x29\xc2\x65\x88\xe7\x20\x9a\x87\x68\x35\xe3\x19\xfb\x2e\x20\x08\x0f\xe2\x7b\xd0\xc8\x0c\x3f\x7e\x10\x21\x9e\x61\x23\x14\x04\xd6\xc0\x8c\xcc\x50\xbf\xa4\x27\x20\xe3\x97\xf4\xf8\xbd\xce\x00\x26\x30\x83\x05\xac\x60\x03\x3b\x24\x83\x13\x52\x21\x0d\x4e\x41\x3a\x14\x40\x21\x14\x41\x31\x94\x40\x29\x7c\x02\x3e\x09\x67\xe0\x3f\x40\x19\xfc\x47\x28\x87\x6e\xe8\x87\xdf\x83\xff\x0a\x63\x30\x0d\xdf\x85\x3d\x5f\xf4\x20\x7f\x8a\x6c\x98\x66\xf2\x94\x6f\x9d\x64\x29\x10\x64\x1f\xf0\xa0\x08\xae\x41\x2f\xdc\x80\x21\xb8\x09\x63\x70\x1b\xa6\xe1\x1e\xdc\x87\x05\x58\x82\x15\x78\x0c\x4f\x61\x03\x9e\xc3\x2e\xec\x13\x2c\x82\x4b\x08\x08\x19\xa1\x26\xf4\x84\x99\xb0\x11\x2e\x22\x93\xf0\x10\x85\x44\x09\x71\x86\x28\x27\xce\x11\x35\x44\x3d\xd1\x44\xb4\x12\xe7\x89\x8b\x44\x17\x71\x95\xe8\x21\xfa\x88\x01\x62\x98\x18\x25\xc6\x89\x49\xe2\x0e\x31\x43\xcc\x11\x8b\xc4\x43\xe2\x11\xf1\x84\x58\x27\x36\x89\x6d\xe2\x05\x09\x24\x4d\xf2\x48\x11\xa9\x20\xb5\xa4\x81\xb4\x90\x0e\x32\x8d\x74\xfb\xfc\x37\x6c\x1a\x08\x6a\x3d\xac\x0d\x08\x56\x59\xd8\x45\x20\xa8\xfb\x3e\x9e\x9a\x0f\xbb\xfd\x92\xb2\xc6\x7c\x78\x98\xcb\xc7\x93\xe5\x3e\x4a\x4c\x23\xbc\x24\xc0\xd3\xdf\xf6\xd1\xb0\xdf\x46\x78\x5b\x58\x0d\x10\x54\x2f\x1a\x13\xe3\xa9\x91\xb0\xcf\x01\xc1\xfa\x38\x92\xb4\x22\xc9\x61\x1f\x65\x67\x22\xbe\x1e\xd1\x32\x44\x2d\x68\xf6\x5e\x6a\x1d\x08\x6a\x09\xd1\x4a\x56\x1c\x10\xac\x5c\x5a\x02\x04\xd5\xe4\x43\xc8\x9f\x86\xbd\xf0\x21\xac\x73\x2f\x65\x88\x6f\xf9\x78\x86\x52\xab\x0c\xef\x93\xa7\x1b\xb1\x71\xae\x06\x78\xff\xb3\x02\xd6\xaf\x03\x41\x19\x59\x12\x20\x88\x3f\x08\x2b\x01\x82\xd5\x84\xf0\x3d\x1f\xa5\x8b\x99\xf1\x03\x08\x55\xeb\xa3\xcc\xbe\x70\x1a\x16\x8d\xf6\x85\xa8\x7f\x16\x8c\xb2\x3c\xe8\x29\x44\x19\x19\x3f\xc2\xe8\x87\x91\xc1\x78\x5c\x06\xe3\x49\x88\x00\x03\x64\x03\x40\x01\xbc\x0e\x2a\xe8\x81\x6f\x82\x0b\x7e\x1b\x7e\x1b\xd2\xe0\x77\xa1\x1f\x4e\xc1\x04\xfc\x09\x64\xc0\x9f\xc2\x9f\x42\x16\xfc\x77\x98\x06\x37\x61\x21\x12\x21\x87\xfe\x2c\xdd\x0c\x1e\xfa\x2b\xf4\x65\x28\x40\x56\xfa\xf7\x2f\xad\xf4\x9d\x24\xd6\x16\x10\xd4\x00\xa5\x05\x82\x1a\x06\x1e\x54\xa3\xc8\xf9\x00\x96\x61\x15\xd6\xe0\x19\x6c\xc1\x0e\xec\x11\x24\xc1\x21\xf8\x84\x84\x50\x11\x3a\xc2\x44\x58\x09\x27\x91\x4e\xe4\x10\x05\x44\x31\x71\x9a\x28\x23\x2a\x89\x6a\xa2\x8e\x68\x24\x5a\x88\x76\xa2\x83\xb8\x44\x5c\x21\xae\x11\xbd\xc4\x0d\x62\x88\xb8\x49\x8c\x11\xb7\x89\x69\xe2\x1e\x71\x9f\x58\x20\x96\x88\x15\xe2\x31\xf1\x94\xd8\x20\x9e\x13\xbb\xc4\x3e\xc9\x22\xb9\xa4\x80\x94\x91\x6a\x52\x4f\x9a\x49\x1b\xe9\x22\x33\x49\x0f\x59\x48\x96\x90\x67\xc8\x72\xf2\x1c\x59\x43\xd6\x93\x4d\x64\x2b\x79\x9e\xbc\x48\x76\x91\x57\xc9\x1e\xb2\x8f\x1c\x20\x87\xc9\x51\x72\x9c\x9c\x24\xef\x90\x33\xe4\x1c\xb9\x48\x3e\x24\x1f\x91\x4f\xc8\x75\x72\x93\xdc\x26\x5f\x50\x40\xd1\x14\xcf\x67\x25\x3e\xcb\x66\xb5\xf8\xa2\x2e\xcb\x1d\xf6\x9f\x81\x60\xfd\x08\x45\xe3\x19\x74\x42\x77\x91\x4e\x2f\xfb\xf0\x30\x33\xb2\x6c\x35\xb2\xe6\x31\x84\xdb\x02\x3c\xfd\x4d\x74\xae\xbf\x89\x68\x23\x1a\xad\xcc\x47\x71\x9e\xea\x44\xb6\x9e\x83\x64\x74\x68\x84\x7e\xcc\xb2\xab\x02\xde\x42\xed\x21\xba\x44\xf9\x72\x6d\xba\x8f\x52\x45\xac\x24\x20\x58\x29\xc8\xb2\xf7\x7c\x08\xf9\xf7\x34\xdf\x87\x20\xfb\x40\x32\xc4\x37\x90\x35\x23\x4a\xdd\x65\x78\x64\xd9\x0f\x02\xe3\xb0\x54\x18\x9f\x12\xb0\x6c\x72\xd1\xc7\x93\xff\x8c\x46\xab\x41\xf8\x3a\xb2\x6c\x2b\xe2\x47\x03\x08\xe5\xf6\xfb\x52\xe7\x7b\x51\xba\x0f\xf1\x7b\x47\x53\x7c\xb5\x38\xf5\xaf\xf0\xdd\x69\x4d\x60\x9d\x38\xf5\xaf\x70\x3d\x30\x1a\x5b\x8d\x66\x5c\x47\x4f\x19\x02\xbb\x7e\xa9\xd5\xc0\x4f\xa9\x4e\x56\x09\x8a\x26\xb7\xd1\x4f\x6f\x07\x74\x88\x34\xc3\x09\xac\x8d\xf6\x60\xf3\x0e\xa1\x9f\x2e\x22\xaf\x93\x06\x79\x9d\xaf\xca\x70\xc1\x4d\xf8\x63\xc8\x82\x09\x98\x84\x7c\x98\x82\x3f\x87\x22\xf8\x1e\x7c\x0f\x4a\xe1\x5f\xe1\x5f\xe1\x13\x84\x94\x90\xc2\x69\xe2\x5b\xc4\xb7\xe0\x93\xa4\x88\x94\xc0\x19\x52\x46\xca\xe0\x3f\x90\x2a\x52\x05\x65\xa4\x86\xd4\xc2\x7f\x24\x75\xa4\x0e\x7e\x99\x34\x91\x26\xa8\x20\x2d\xa4\x05\x7e\x85\xb4\x92\x56\xa8\x24\x4f\x91\xe9\xf0\x3a\xf9\x8b\x64\x09\xfc\x27\xb2\x94\x2c\x85\x37\x90\xc7\x0e\xbc\xf4\xd8\xfd\x69\xf2\x27\x40\x10\x93\x44\x2d\x10\xa4\xaf\x1e\x4d\x7c\x7f\x99\x9c\x10\x11\x0a\x42\x4b\x18\x08\x0b\xe1\x20\xd2\x08\x37\xe1\x25\x8a\x88\x52\xc2\x57\xa1\xc0\xdb\xbb\x18\x5d\x7c\x45\x25\x6f\x8f\x23\x7e\x0d\xa3\xb3\x3e\xea\xcb\xd8\x6f\x7f\x81\x91\xdf\x97\x21\x7c\x1a\x7b\x16\x93\xf7\x49\x1e\x18\x7f\xed\x20\xb2\xaf\xc3\x24\x67\x81\x78\x67\xc3\x3f\xef\x62\x60\x64\x46\xc6\x8f\xcf\x62\xe3\x4c\x63\xfc\xc8\x21\x3c\x14\x5d\x0b\x5a\x33\x09\x91\xe8\x8e\x04\xe8\x76\xc4\x42\xb7\xa3\x70\x74\x3b\x8a\x44\xb7\x23\x05\xba\x11\xa9\xd1\x5d\x48\x83\x6e\x41\x3a\x74\xff\xd1\xa3\x9b\x8f\x09\xdd\x70\xcc\xe8\x6e\x93\x80\x6e\x35\x96\x0f\x61\xc4\x44\x00\xb8\x05\x00\x13\x00\x30\x05\x00\x77\x01\x60\xd6\x77\x45\x06\x80\x07\x00\xb0\x0c\x00\xab\x00\xb0\x06\x00\xbe\x3a\x69\x0b\x00\x76\x00\x60\xcf\x57\x9c\x00\x10\x1c\x00\xc2\x77\x6b\x96\x00\x10\x2a\xdf\xed\x19\x80\x30\x01\x10\x56\x00\xc2\x09\x40\xa4\x03\x10\x39\x00\x44\x01\x00\x51\x0c\x40\x9c\x06\x20\xca\x00\x88\x4a\x00\xa2\x1a\x80\xa8\x03\x20\x1a\x01\x88\x16\x00\xa2\x1d\x80\xe8\x00\x20\x2e\x01\x10\x57\x00\x88\x6b\x00\x44\x2f\x00\x71\x03\x80\x18\x02\x20\x6e\xfa\xf4\xfa\x4e\x3f\x46\x67\x5e\x51\xc9\x3b\x0b\x21\x7e\xda\xe2\xb3\xa9\x77\x2e\x20\xbe\x0a\x51\x46\xb2\x0b\xd1\x31\x44\x87\x31\xa4\x1f\xc3\xbb\x0e\xd1\x16\x44\xcb\x10\x5d\xf6\xd9\x94\x8f\xbe\x92\x5f\x38\x24\xcf\xfc\x74\x0a\xd1\x6b\x98\xe4\x0c\x46\xc7\x42\xd0\x99\x43\x23\xf7\x03\x41\xd6\x92\x7c\x20\xc8\x3b\xc0\x03\xcf\x07\xe5\xab\x44\x05\x51\x45\xd4\x12\x0d\x44\x33\xd1\x46\x5c\x20\x3a\x89\xcb\x44\x37\x71\x9d\xe8\x27\x06\x89\x11\xe2\x16\x31\x41\x4c\x11\x77\x89\x59\x62\x9e\x78\x40\x2c\x13\xab\xc4\x1a\xf1\x8c\xd8\x22\x76\x88\x3d\x20\xde\xbe\x40\xd7\xbd\xa4\x00\x7e\x1e\xf9\xbe\xef\xae\x03\xc0\xe6\xbc\xc4\x5f\xd1\xb3\x40\xbc\x7d\xcd\x8f\x6f\x1f\xfa\x29\x3e\x4e\x1d\x36\xc2\x79\x44\x15\x87\xe8\x63\x44\xbb\x91\xa4\x03\xd1\xdd\x97\xb3\xbc\x92\x99\x0f\xc8\xf8\xc7\x9c\x0e\xc8\xd3\x43\x88\x4e\x22\x44\x1d\xe0\x19\x79\x5f\x4d\xf5\x92\x32\xcf\xe2\x88\x1f\xf7\x04\xe8\xe1\x9f\x06\x28\xe9\x46\xf7\xbf\x36\xdf\x38\xe4\x27\x7c\xf3\x32\xf4\xd5\x8c\x93\xd8\x4e\x3d\xc7\xa0\x43\x40\x02\x1f\xf5\x62\x00\x75\x61\xa4\xa8\xdb\x22\x43\xdd\x16\x25\xea\xb3\xa8\x51\x87\x45\x83\x7a\x2b\x3a\xd4\x55\x89\x43\xfd\x14\x03\xea\xa7\x18\x51\x3f\xc5\x89\xfa\x29\x69\xa8\x93\x92\x8e\x7a\x28\xb9\x1f\xda\xb8\x9e\x9f\x4b\xd4\x00\x62\x0c\x80\xb8\x0d\x40\x4c\x03\x10\xf7\x00\x88\xfb\x00\xc4\x02\x00\xb1\x04\x40\xac\x00\x10\x8f\x01\x88\xa7\x00\xc4\x06\x00\xf1\x1c\x80\xd8\x05\x20\xf6\x01\x48\x16\x00\xc9\x05\x20\x05\x00\xa4\x0c\x80\x54\x03\x90\x7a\x00\xd2\x0c\x40\xda\x00\x48\x17\x00\x99\x09\x40\x7a\x00\xc8\x42\x00\xb2\x04\x80\x3c\x03\x40\x96\x03\x90\xe7\x00\xc8\x1a\x00\xb2\x1e\x80\x6c\x02\x20\x5b\x01\xc8\xf3\x40\xbc\xdd\xc6\x9a\xf4\x59\x37\x0b\x9d\xf6\x41\x1e\x20\xec\x41\x80\xc7\x64\xae\x06\xf8\x77\xc6\x82\x7e\xda\xfd\x92\x06\x8f\xc3\x50\x6a\xf0\x20\x65\x21\x8b\x63\xa1\x38\xc6\x42\xf1\x30\x6c\x0b\x7b\x0a\xf9\x0d\x6b\x0c\x43\xaa\x30\xca\x20\x7d\x18\x9d\xc1\x78\x34\x32\xb1\xff\xc1\x51\xd2\xcd\xea\xf2\x79\x8c\x6f\x5e\xf2\x13\x01\x0a\xc0\x5a\xc6\xe8\x30\xb6\xe6\xc3\x14\xef\x64\xf4\x01\xa1\x52\x28\xaf\x03\xa1\xd2\x02\x8f\x4a\xa6\x6b\xe8\x7a\xba\x89\x6e\xa5\xcf\xd3\x17\xe9\x2e\xfa\x2a\xdd\x43\xf7\xd1\x03\xf4\x30\x3d\x4a\x8f\xd3\x93\xf4\x1d\x7a\x86\x9e\xa3\x17\xe9\x87\xf4\x23\xfa\x09\xbd\x4e\x6f\xd2\xdb\xf4\x0b\x36\xb0\x69\x36\x8f\x2d\x62\x2b\xd8\x5a\xb6\x81\x6d\x61\x3b\xd8\x69\x6c\x37\xdb\xcb\x2e\x62\x97\xb2\xcf\xb2\x2b\xd8\x55\xec\x5a\x76\x03\xbb\x99\xdd\xc6\xbe\xc0\xee\x64\x5f\x66\x77\xb3\xaf\xb3\xfb\xd9\x83\xec\x11\xf6\x2d\xf6\x04\x7b\x8a\x7d\x97\x3d\xcb\x9e\x67\x3f\x60\x2f\xb3\x57\xd9\x6b\xec\x67\xec\x2d\xf6\x0e\x7b\x8f\x43\x72\x38\x1c\x3e\x47\xc2\x51\x71\x74\x1c\x13\xc7\xca\x71\x72\xd2\x39\x39\x9c\x02\x4e\x31\xe7\x34\xa7\x8c\x53\xc9\xa9\xe6\xd4\x71\x1a\x39\x2d\x9c\x76\x4e\x07\xe7\x12\xe7\x0a\xe7\x1a\xa7\x97\x73\x83\x33\xc4\xb9\xc9\x19\xe3\xdc\xe6\x4c\x73\xee\x71\xee\x73\x16\x38\x4b\x9c\x15\xce\x63\xce\x53\xce\x06\xe7\x39\x67\x97\xb3\x1f\xce\x0a\xe7\x86\x0b\xc2\x65\xe1\xea\x70\x7d\xb8\x39\xdc\x16\xee\x0a\xcf\x0c\xf7\x84\x17\x86\x97\x84\x9f\x09\x2f\x0f\x3f\x17\x5e\x13\x5e\x1f\xde\x14\xde\x1a\x7e\x3e\xfc\x62\x78\x57\xf8\xd5\xf0\x9e\xf0\xbe\xf0\x81\xf0\xe1\xf0\xd1\xf0\xf1\xf0\xc9\xf0\x3b\xe1\x33\xe1\x73\xe1\x8b\xe1\x0f\xc3\x1f\x85\x3f\x09\x5f\x0f\xdf\x0c\xdf\x0e\x7f\xc1\x05\x2e\xcd\xe5\x71\x45\x5c\x05\x57\xcb\x35\x70\x2d\x5c\x07\x37\x8d\xeb\xe6\x7a\xb9\x45\xdc\x52\xee\x59\x6e\x05\xb7\x8a\x5b\xcb\x6d\xe0\x36\x73\xdb\xb8\x17\xb8\x9d\xdc\xcb\xdc\x6e\xee\x75\x6e\x3f\x77\x90\x3b\xc2\xbd\xc5\x9d\xe0\x4e\x71\xef\x72\x67\xb9\xf3\xdc\x07\xdc\x65\xee\x2a\x77\x8d\xfb\x8c\xbb\xc5\xdd\xe1\xee\x45\x90\x11\x9c\x08\x7e\x84\x24\x42\x15\xa1\x8b\x30\x45\x58\x23\x9c\x11\xe9\x11\x39\x11\x05\x11\xc5\x11\xa7\x23\xca\x22\x2a\x23\xaa\x23\xea\x22\x1a\x23\x5a\x22\xda\x23\x3a\x22\x2e\x45\x5c\x89\xb8\x16\xd1\x1b\x71\x23\x62\x28\xe2\x66\xc4\x58\xc4\xed\x88\xe9\x88\x7b\x11\xf7\x23\x16\x22\x96\x22\x56\x22\x1e\x47\x3c\x8d\xd8\x88\x78\x1e\xb1\x1b\xb1\xcf\x63\xf1\xb8\x3c\x01\x4f\xc6\x53\xf3\xf4\x3c\x33\xcf\xc6\x73\xf1\x32\x79\x1e\x5e\x21\xaf\x84\x77\x86\x57\xce\x3b\xc7\xab\xe1\xd5\xf3\x9a\x78\xad\xbc\xf3\xbc\x8b\xbc\x2e\xde\x55\x5e\x0f\xaf\x8f\x37\xc0\x1b\xe6\x8d\xf2\xc6\x79\x93\xbc\x3b\xbc\x19\xde\x1c\x6f\x91\xf7\x90\xf7\x88\xf7\x84\xb7\xce\xdb\xe4\x6d\xf3\x5e\x44\x42\x24\x1d\xc9\x8b\x14\x45\x2a\x22\xb5\x91\x86\x48\x4b\xa4\x23\x32\x2d\xd2\x1d\xe9\x8d\x2c\x8a\x2c\x8d\x3c\x1b\x59\x11\x59\x15\x59\x1b\xd9\x10\xd9\x1c\xd9\x16\x79\x21\xb2\x33\xf2\x72\x64\x77\xe4\xf5\xc8\xfe\xc8\xc1\xc8\x91\xc8\x5b\x91\x13\x91\x53\x91\x77\x23\x67\x23\xe7\x23\x1f\x44\x2e\x47\xae\x46\xae\x45\x3e\x8b\xdc\x8a\xdc\x89\xdc\xe3\x93\x7c\x0e\x9f\xcf\x97\xf0\x55\x7c\x1d\xdf\xc4\xb7\xf2\x9d\xfc\x74\x7e\x0e\xbf\x80\x5f\xcc\x3f\xcd\x2f\xe3\x57\xf2\xab\xf9\x75\xfc\x46\x7e\x0b\xbf\x9d\xdf\xc1\xbf\xc4\xbf\xc2\xbf\xc6\xef\xe5\xdf\xe0\x0f\xf1\x6f\xf2\xc7\xf8\xb7\xf9\xd3\xfc\x7b\xfc\xfb\xfc\x05\xfe\x12\x7f\x85\xff\x98\xff\x94\xbf\xc1\x7f\xce\xdf\xe5\xef\x47\xb1\xa2\xb8\x51\x82\x28\x59\x94\x3a\x4a\x1f\x65\x8e\xb2\x45\xb9\xa2\x32\xa3\x3c\x51\x85\x51\x25\x51\x67\xa2\xca\xa3\xce\x45\xd5\x44\xd5\x47\x35\x45\xb5\x46\x9d\x8f\xba\x18\xd5\x15\x75\x35\xaa\x27\xaa\x2f\x6a\x20\x6a\x38\x6a\x34\x6a\x3c\x6a\x32\xea\x4e\xd4\x4c\xd4\x5c\xd4\x62\xd4\xc3\xa8\x47\x51\x4f\xa2\xd6\xa3\x36\xa3\xb6\xa3\x5e\x08\x40\x40\x0b\x78\x02\x91\x40\x21\xd0\x0a\x0c\x02\x8b\xc0\x21\x48\x13\xb8\x05\x5e\x41\x91\xa0\x54\x70\x56\x50\x21\xa8\x12\xd4\x0a\x1a\x04\xcd\x82\x36\xc1\x05\x41\xa7\xe0\xb2\xa0\x5b\x70\x5d\xd0\x2f\x18\x14\x8c\x08\x6e\x09\x26\x04\x53\x82\xbb\x82\x59\xc1\xbc\xe0\x81\x60\x59\xb0\x2a\x58\x13\x3c\x13\x6c\x09\x76\x04\x7b\x42\x52\xc8\x11\xf2\x85\x12\xa1\x4a\xa8\x13\x9a\x84\x56\xa1\x53\x98\x2e\xcc\x11\x16\x08\x8b\x85\xa7\x85\x65\xc2\x4a\x61\xb5\xb0\x4e\xd8\x28\x6c\x11\xb6\x0b\x3b\x84\x97\x84\x57\x84\xd7\x84\xbd\xc2\x1b\xc2\x21\xe1\x4d\xe1\x98\xf0\xb6\x70\x5a\x78\x4f\x78\x5f\xb8\x20\x5c\x12\xae\x08\x1f\x0b\x9f\x0a\x37\x84\xcf\x85\xbb\xc2\x7d\x11\x4b\xc4\x15\x09\x44\x32\x91\x5a\xa4\x17\x99\x45\x36\x91\x4b\x94\x29\xf2\x88\x0a\x45\x25\xa2\x33\xa2\x72\xd1\x39\x51\x8d\xa8\x5e\xd4\x24\x6a\x15\x9d\x17\x5d\x14\x75\x89\xae\x8a\x7a\x44\x7d\xa2\x01\xd1\xb0\x68\x54\x34\x2e\x9a\x14\xdd\x11\xcd\x88\xe6\x44\x8b\xa2\x87\xa2\x47\xa2\x27\xa2\x75\xd1\xa6\x68\x5b\xf4\x42\x0c\x62\x5a\xcc\x13\x8b\xc4\x0a\xb1\x56\x6c\x10\x5b\xc4\x0e\x71\x9a\xd8\x2d\xf6\x8a\x8b\xc4\xa5\xe2\xb3\xe2\x0a\x71\x95\xb8\x56\xdc\x20\x6e\x16\xb7\x89\x2f\x88\x3b\xc5\x97\xc5\xdd\xe2\xeb\xe2\x7e\xf1\xa0\x78\x44\x7c\x4b\x3c\x21\x9e\x12\xdf\x15\xcf\x8a\xe7\xc5\x0f\xc4\xcb\xe2\x55\xf1\x9a\xf8\x99\x78\x4b\xbc\x23\xde\x93\x90\x12\x8e\x84\x2f\x91\x48\x54\x12\x9d\xc4\x24\xb1\x4a\x9c\x92\x74\x49\x8e\xa4\x40\x52\x2c\x39\x2d\x29\x93\x54\x4a\xaa\x25\x75\x92\x46\x49\x8b\xa4\x5d\xd2\x21\xb9\x24\xb9\x22\xb9\x26\xe9\x95\xdc\x90\x0c\x49\x6e\x4a\xc6\x24\xb7\x25\xd3\x92\x7b\x92\xfb\x92\x05\xc9\x92\x64\x45\xf2\x58\xf2\x54\xb2\x21\x79\x2e\xd9\x95\xec\x4b\x59\x52\xae\x54\x20\x95\x49\xd5\x52\xbd\xd4\x2c\xb5\x49\x5d\xd2\x4c\xa9\x47\x5a\x28\x2d\x91\x9e\x91\x96\x4b\xcf\x49\x6b\xa4\xf5\xd2\x26\x69\xab\xf4\xbc\xf4\xa2\xb4\x4b\x7a\x55\xda\x23\xed\x93\x0e\x48\x87\xa5\xa3\xd2\x71\xe9\xa4\xf4\x8e\x74\x46\x3a\x27\x5d\x94\x3e\x94\x3e\x92\x3e\x91\xae\x4b\x37\xa5\xdb\xd2\x17\x32\x90\xd1\x32\x9e\x4c\x24\x53\xc8\xb4\x32\x83\xcc\x22\x73\xc8\xd2\x64\x6e\x99\x57\x56\x24\x2b\x95\x9d\x95\x55\xc8\xaa\x64\xb5\xb2\x06\x59\xb3\xac\x4d\x76\x41\xd6\x29\xbb\x2c\xeb\x96\x5d\x97\xf5\xcb\x06\x65\x23\xb2\x5b\xb2\x09\xd9\x94\xec\xae\x6c\x56\x36\x2f\x7b\x20\x5b\x96\xad\xca\xd6\x64\xcf\x64\x5b\xb2\x1d\xd9\x9e\x9c\x94\x73\xe4\x7c\xb9\x44\xae\x92\xeb\xe4\x26\xb9\x55\xee\x94\xa7\xcb\x73\xe4\x05\xf2\x62\xf9\x69\x79\x99\xbc\x52\x5e\x2d\xaf\x93\x37\xca\x5b\xe4\xed\xf2\x0e\xf9\x25\xf9\x15\xf9\x35\x79\xaf\xfc\x86\x7c\x48\x7e\x53\x3e\x26\xbf\x2d\x9f\x96\xdf\x93\xdf\x97\x2f\xc8\x97\xe4\x2b\xf2\xc7\xf2\xa7\xf2\x0d\xf9\x73\xf9\xae\x7c\x5f\xc1\x52\x70\x15\x02\x85\x4c\xa1\x56\xe8\x15\x66\x85\x4d\xe1\x52\x64\x2a\x3c\x8a\x42\x45\x89\xe2\x8c\xa2\x5c\x71\x4e\x51\xa3\xa8\x57\x34\x29\x5a\x15\xe7\x15\x17\x15\x5d\x8a\xab\x8a\x1e\x45\x9f\x62\x40\x31\xac\x18\x55\x8c\x2b\x26\x15\x77\x14\x33\x8a\x39\xc5\xa2\xe2\xa1\xe2\x91\xe2\x89\x62\x5d\xb1\xa9\xd8\x56\xbc\x50\x82\x92\x56\xf2\x94\x22\xa5\x42\xa9\x55\x1a\x94\x16\xa5\x43\x99\xa6\x74\x2b\xbd\xca\x22\x65\xa9\xf2\xac\xb2\x42\x59\xa5\xac\x55\x36\x28\x9b\x95\x6d\xca\x0b\xca\x4e\x20\xc2\xf2\xfd\x5d\xe4\x30\x20\xa8\x76\x7f\x9f\x5b\x02\x04\x85\xfa\xdf\xc4\xf7\x10\xe2\xbb\x75\x11\x61\x39\xa8\xe3\x4b\x20\x9c\xb5\x3f\x0a\x04\x6b\x1b\xfd\x14\x49\xd2\x7f\x84\x64\x98\x8e\x78\x2f\xf6\x2c\xea\x8b\x87\x31\xdd\xe2\x11\x44\x67\x10\xde\x84\x28\x89\x9e\xe5\xfb\x28\x6b\x03\xfd\xf4\x7f\x21\x1e\xbd\x0b\x65\x89\x91\x4c\x25\xd6\x71\x1f\xf7\xad\x8d\xdc\x45\xe3\x33\xc8\xee\x7e\x11\x10\x2c\x34\x2f\xf1\x07\xfe\xb5\xf9\x90\xfe\x00\xc2\x56\xa1\xd1\x98\xb5\xf1\x18\x7c\x5f\x02\x04\xeb\x17\xf6\x25\x2f\x65\xc8\x86\x40\x47\x9f\x85\xf4\x40\x4e\xa3\x95\x57\x20\xa4\x04\x3d\x35\xe4\x1b\x99\xe9\xf7\x33\xab\x7d\x77\x4a\xbf\xcd\xac\x1f\x3d\x35\x1a\xd0\x15\x4e\x19\x7d\x1e\xa6\xcc\x29\xe0\xfa\x7c\x0f\xda\x74\x34\x65\xf4\xc9\x9c\x05\xcb\x1b\xd0\xea\xbb\xd3\xb0\x07\xcc\x79\xf9\x56\xce\x68\xfb\x30\xf5\x6b\xfb\x10\x65\x34\x8c\x6b\xfb\xdd\x29\xa3\xed\xc3\x94\xd1\x36\x73\x52\x0c\xef\xd7\xad\x18\xd3\xb3\x9f\x47\x6f\xfa\xc4\x3e\xca\xd8\x30\x63\x2d\xc7\xe2\x91\x9e\x19\xbb\x0a\xe2\x47\x03\x3b\x0d\xcd\xa3\x19\xfd\x14\xc3\xef\x06\x2c\x33\x14\x1f\x16\x0f\xb9\xaf\xf8\x9c\x80\xc6\x70\xde\xef\x6b\x7f\xf0\xae\x7c\x82\x6f\x76\xe2\xbf\xf9\x28\x8e\xb3\xd2\x7d\x1e\x4a\xb9\x90\x0e\x91\xb7\xfa\xfd\x02\xf9\x2c\xe3\x1d\x0c\xf5\x7b\x3a\x73\x76\x4b\x88\x1f\x39\x84\x87\xe0\x19\xfb\xf4\xaf\x3c\x14\xdf\x88\xa8\x04\xad\x67\x09\xe9\xa1\x17\xb3\x81\x10\x3c\x1b\xbd\xef\xa2\xd3\xe0\x55\xf4\xf0\xcf\xe8\xe7\x7d\xfb\xc5\x71\x7f\x6c\x69\x38\xcc\x23\xcd\x34\x20\x8a\xe3\x97\x91\x6d\x73\x10\x45\x11\x89\xf1\x7d\x9c\x67\x3c\x88\xb1\xc6\x13\xf3\xc8\x2a\x58\xb5\x3e\xca\xc4\x37\x26\x92\xf8\xfd\x11\xd9\x33\x1e\xeb\xfc\x51\x05\xf1\xe4\xda\x41\x9e\x40\xef\x0c\x99\x48\xc8\x12\xa0\x58\xcd\x44\xec\xca\x00\xee\x8f\x93\xd3\x81\x48\x8e\x5b\x38\x4b\x85\xac\x1a\xe9\xd6\x1f\x45\x7b\xe0\xd5\x5b\x4d\x6a\x35\xb0\x06\xc2\x1a\xd0\x0c\x63\xb1\x14\x0f\x59\xe9\x4d\x4c\x7b\xc8\xd2\x70\x5b\xf2\x5b\x5d\x0b\xda\xe9\x69\xdc\x06\x7c\xfe\x1b\x14\xa9\xd0\x1a\x38\xe8\x64\xe9\x3f\xf2\xfd\x94\x89\xb4\x8c\xa7\x87\xc1\x3b\x29\xaf\x4e\xea\x32\xa6\x07\x26\x16\x21\x4a\x89\xb1\x33\x7a\x0d\x21\xb8\xe6\x99\x59\xc8\x83\xda\x66\xa5\x07\xf6\x48\xde\x0a\x78\x2b\xf9\x1d\xec\xf4\x3f\x11\x58\x09\x57\xe3\xe3\xc3\x91\xf5\x72\xae\xa1\x1d\x7d\xd5\x67\xc3\x61\x5f\x45\x33\xfe\x67\x1f\x65\x7f\xd9\x87\xb0\xbf\xec\xe3\xe9\xea\x83\x31\x0a\xf7\xc7\x20\x3b\xc7\x56\xcb\xd8\x1b\xfd\xaf\x68\xfc\xaf\xc3\xbb\x44\x0f\x5c\xdb\xd4\x1c\x8a\x39\x3c\x44\x31\x9e\x39\x53\xb2\xc7\xef\xf5\x45\x47\xed\x02\x1f\x93\x2e\xc5\x34\x8f\xf9\x6c\xa8\x48\x4b\xad\x04\xf4\x86\xf3\xa1\xa2\x53\x28\xef\x3e\xca\xa3\xdf\xcd\x9b\xc8\x45\xcc\x8b\x91\x47\x90\xad\x87\x22\x67\x36\xca\xe9\xcb\x01\x7b\xf0\xe7\xa9\x1b\x88\x5e\x3e\xb8\x17\xf2\x2f\x91\x45\xfd\xe4\x60\x44\x0a\xf2\x50\x34\x4e\x98\x3d\x60\x21\x8c\x56\xc3\xb6\x7c\x1e\x44\xb3\x90\x67\xa1\x31\x83\x3c\x6e\x34\x70\xb2\xe4\x3f\xa3\xf1\x4d\x68\x34\x36\x42\x10\xf5\xfb\x2f\xb3\xc7\xb1\x83\xfa\xc4\x23\x76\xd8\x04\x3a\xfd\x19\xc4\xe3\x11\x0f\x5f\x27\x9a\x97\x95\x7d\x28\x1a\x98\x02\xab\x62\x46\x60\x64\x18\x8f\x0b\xa2\x8b\x01\x8f\x63\xa8\xff\xf3\x0e\x2c\xa6\x06\x08\x50\xff\x27\x1a\xa6\x11\x32\x1d\xf0\x71\x7f\xc6\x5f\x67\xb2\x36\xbc\xfa\x04\x84\xbf\xaa\xb1\x21\xfa\x4b\x88\xaa\xd1\x38\x7b\xc8\x83\x50\x9c\x67\xab\x7c\x23\xd0\x75\x81\x5a\x8e\xb5\xc1\xec\x3a\x70\x2e\x34\xfa\x2c\x03\x6b\x07\x21\xc8\x62\x49\x46\x63\x2b\x8c\x5f\x07\xaa\x05\x32\x11\x5b\x43\x23\x5a\xdb\x85\xc0\x4e\x89\xc7\xe8\xa7\xea\x00\x25\x0b\x7c\x14\xfe\x16\xf1\xc5\xcc\x59\xa3\xd9\xdb\xe1\x60\xad\x82\xea\x40\xfa\x4b\x01\x9e\xfc\x53\x86\xf7\xd7\x78\x92\x97\xde\xe7\xa7\x61\x48\xe6\x8f\x11\x4d\xf2\x5b\xf2\x2b\x7b\x23\xff\x1e\x5e\x7d\x66\x84\x89\x57\xac\xce\x80\xce\x59\x36\x14\x39\x7f\x15\xe1\xa8\x52\xc5\x47\x63\xbf\x89\x56\xf2\x4d\xa4\xc3\xef\xf9\xed\xd0\x27\x3f\x8e\xec\x04\x8d\x4c\xff\x42\x20\xee\xb1\xfe\x12\xf3\x29\x23\xe3\x59\x4c\xbc\x45\xeb\x61\xac\x05\xe5\x05\xa6\xae\xc6\x6b\x66\x7f\x0d\x86\xd5\x78\x78\xb5\xec\xff\xfc\x0b\xd2\x3f\xf5\x45\x72\xe2\xe5\x1e\xd9\xff\x7f\x4c\xbe\x3c\x30\x8e\x3f\xe3\x30\x74\x09\x7d\x2e\xeb\x82\x8f\x12\xdb\x3e\xea\x8f\x75\x55\x08\x99\xf7\x51\x76\x01\x92\x19\x43\x08\xb3\x12\x84\x93\x5b\x08\xb1\x32\x9a\x47\x32\x02\x1f\xa5\x72\x7c\x34\x8c\x46\xb4\x10\xe1\x0b\x68\xcc\x2e\xc4\xf7\xa3\xa7\x86\xd0\x4f\xff\x1e\x8d\x33\x12\x98\x8b\xf0\x20\xbc\x26\x20\x13\x14\xfd\xf0\x9c\x2b\xdb\x9f\xf3\xed\x02\x51\xd9\xfe\x3a\xda\xf5\xfa\xcb\x8a\x8b\xb1\x9f\xa0\x7a\x12\xc9\xfb\x3d\x94\x91\xdf\x44\x74\x0d\xd5\x09\x0c\xce\xc3\xf8\x50\x91\x76\x1c\xc5\x40\x26\x1e\x8e\xef\x0f\x02\x41\xce\x22\xba\x82\x90\x4d\x54\x0d\xa2\x6a\x9f\x39\xc7\xa0\x9a\x33\x44\x9d\x79\x1c\x9e\x24\x7c\xb3\x10\x7f\x80\xe6\xc2\xeb\x4c\xbc\x9e\xc4\x33\x54\x13\xd2\x06\x0f\xed\x71\xd7\x47\x89\x3f\xf0\x69\xe0\x48\x7e\x1d\xc5\x13\xdf\xca\xbb\x51\xbd\xf4\x47\x01\x0b\x0c\xc5\x87\xaa\x36\xa9\xd1\xc0\xbc\xfe\xca\x9c\x44\xf4\x18\x35\x27\xce\xfb\x75\xc8\xd8\x1b\xc6\x1f\x91\xb9\x86\x7c\x7b\xc1\x79\x66\xef\xc4\x3c\xda\x57\x70\x2d\x3a\x87\xb2\xd8\xdc\xbb\xd6\xab\x01\x99\xa0\xba\x14\x21\x1d\x0c\x8e\x46\xee\x40\xf4\x8f\xd0\xb9\x57\xa3\x3d\x36\xed\x57\xbe\xcc\x35\x54\x93\xef\xa4\x28\x13\xa2\x4d\x48\x66\x97\x91\x81\xa3\xeb\x55\x32\x10\x21\x29\x12\xcd\x32\xed\xa3\x78\xed\x7a\x52\xde\xef\x3b\x25\x07\xf9\x50\x55\x19\xab\x3e\x70\x0a\x8c\x6d\x90\xad\x7e\x9f\x5a\x7f\xa9\x07\x66\x64\xff\xb3\x62\xcc\x0e\x43\xde\x0d\x7f\x3e\x7c\x28\xff\xfd\xa0\xf8\xe0\x8a\xcb\x77\x52\x8c\x4f\x51\xbd\xe8\xec\x36\x19\xfe\x64\x36\x1f\xcc\xa3\x71\xd6\x7e\xb6\x71\xfc\xde\xcd\xf8\xc2\xdc\xcf\x7c\x87\x0a\xe2\x03\xe3\x04\xdf\xa1\xd0\xde\xb1\xfb\xd4\x61\x9e\xb1\x6d\xff\x5d\xe6\xf0\x4d\xf6\x7b\x01\x5f\x66\x61\x37\x0b\xbf\x2f\xfc\x26\xfa\x6c\x74\xf0\x67\x64\x2e\x42\x2f\xb8\xa0\x0f\x26\xe1\x17\x61\x8a\x68\x87\x7a\xe2\x02\xf1\x45\x22\x91\xb8\x44\x5c\x27\xec\xc4\xb7\x88\x6f\x11\x1e\x62\x88\xf8\xef\x44\x1e\x71\x8f\xf8\x11\xf1\xcb\xc4\x23\xe2\x9f\x88\xb7\x88\x2d\xe2\x7f\x11\x5f\x24\xb6\xc9\xb7\x88\x2f\x85\x7d\x2c\xec\xd7\x49\x22\x6c\x98\xce\x23\x1d\x74\x3e\xdd\x4f\xce\xb3\x37\xd9\x9b\x94\x89\xf3\x4b\x9c\x5f\xa2\xe2\x39\xe7\x38\x35\x94\x99\xf3\x59\xce\x67\x29\x3b\xa7\x99\xd3\x4c\x39\xd0\x67\x64\x9e\xc1\xcb\xcf\x5e\xfe\x9e\x6f\x65\x29\x03\x29\x5a\x20\x53\x6e\x02\x8f\x4a\xe6\xcd\xf2\xe6\x79\x0f\x78\xcb\xbc\x55\xde\x1a\xef\x19\x6f\x8b\xb7\xc3\xdb\x8b\x24\x23\x39\x91\xfc\x48\x49\xa4\x2a\x52\x17\x69\x8a\xb4\x46\x3a\x23\xd3\x23\x73\x22\x0b\x22\x8b\x23\x4f\x47\x96\x45\x56\x46\x56\x47\xd6\x45\x36\x46\xb6\x44\xb6\x47\x76\x44\x5e\x8a\xbc\x12\x79\x2d\xb2\x37\xf2\x46\xe4\x50\xe4\xcd\xc8\xb1\xc8\xdb\x91\xd3\x91\xf7\x22\xef\x47\x2e\x44\x2e\x45\xae\x44\x3e\x8e\x7c\x1a\xb9\x11\xf9\x3c\x72\x37\x72\x9f\xcf\xe2\x73\xf9\x02\xbe\x8c\xaf\xe6\xeb\xf9\x66\xbe\x8d\xef\xe2\x67\xf2\x3d\xfc\x42\x7e\x09\xff\x0c\xbf\x9c\x7f\x8e\x5f\xc3\xaf\xe7\x37\xf1\x5b\xf9\xe7\xf9\x17\xf9\x5d\xfc\xab\xfc\x1e\x7e\x1f\x7f\x80\x3f\xcc\x1f\xe5\x8f\xf3\x27\xf9\x77\xf8\x33\xfc\x39\xfe\x22\xff\x21\xff\x11\xff\x09\x7f\x9d\xbf\xc9\xdf\xe6\xbf\x88\x82\x28\x3a\x8a\x17\x25\x8a\x52\x44\x69\xa3\x0c\x51\x96\x28\x47\x54\x5a\x94\x3b\xca\x1b\x55\x14\x55\x1a\x75\x36\xaa\x22\xaa\x2a\xaa\x36\xaa\x21\xaa\x39\xaa\x2d\xea\x42\x54\x67\xd4\xe5\xa8\xee\xa8\xeb\x51\xfd\x51\x83\x51\x23\x51\xb7\xa2\x26\xa2\xa6\xa2\xee\x46\xcd\x46\xcd\x47\x3d\x88\x5a\x8e\x5a\x8d\x5a\x8b\x7a\x16\xb5\x15\xb5\x13\xb5\x27\x20\x05\x1c\x01\x5f\x20\x11\xa8\x04\x3a\x81\x49\x60\x15\x38\x05\xe9\x82\x1c\x41\x81\xa0\x58\x70\x5a\x50\x26\xa8\x14\x54\x0b\xea\x04\x8d\x82\x16\x41\xbb\xa0\x43\x70\x49\x70\x45\x70\x4d\xd0\x2b\xb8\x21\x18\x12\xdc\x14\x8c\x09\x6e\x0b\xa6\x05\xf7\x04\xf7\x05\x0b\x82\x25\xc1\x8a\xe0\xb1\xe0\xa9\x60\x43\xf0\x5c\xb0\x2b\xd8\x17\xb2\x84\x5c\xa1\x40\x28\x13\xaa\x85\x7a\xa1\x59\x68\x13\xba\x84\x99\x42\x8f\xb0\x50\x58\x22\x3c\x23\x2c\x17\x9e\x13\xd6\x08\xeb\x85\x4d\xc2\x56\xe1\x79\xe1\x45\x61\x97\xf0\xaa\xb0\x47\xd8\x27\x1c\x10\x0e\x0b\x47\x85\xe3\xc2\x49\xe1\x1d\xe1\x8c\x70\x4e\xb8\x28\x7c\x28\x7c\x24\x7c\x22\x5c\x17\x6e\x0a\xb7\x85\x2f\x44\x20\xa2\x45\x3c\x91\x48\xa4\x10\x69\x45\x06\x91\x45\xe4\x10\xa5\x89\xdc\x22\xaf\xa8\x48\x54\x2a\x3a\x2b\xaa\x10\x55\x89\x6a\x45\x0d\xa2\x66\x51\x9b\xe8\x82\xa8\x53\x74\x59\xd4\x2d\xba\x2e\xea\x17\x0d\x8a\x46\x44\xb7\x44\x13\xa2\x29\xd1\x5d\xd1\xac\x68\x5e\xf4\x40\xb4\x2c\x5a\x15\xad\x89\x9e\x89\xb6\x44\x3b\xa2\x3d\x31\x29\xe6\x88\xf9\x62\x89\x58\x25\xd6\x89\x4d\x62\xab\xd8\x29\x4e\x17\xe7\x88\x0b\xc4\xc5\xe2\xd3\xe2\x32\x71\xa5\xb8\x5a\x5c\x27\x6e\x14\xb7\x88\xdb\xc5\x1d\xe2\x4b\xe2\x2b\xe2\x6b\xe2\x5e\xf1\x0d\xf1\x90\xf8\xa6\x78\x4c\x7c\x5b\x3c\x2d\xbe\x27\xbe\x2f\x5e\x10\x2f\x89\x57\xc4\x8f\xc5\x4f\xc5\x1b\xe2\xe7\xe2\x5d\xf1\xbe\x84\x25\xe1\x4a\x04\x12\x99\x44\x2d\xd1\x4b\xcc\x12\x9b\xc4\x25\xc9\x94\x78\x24\x85\x92\x12\xc9\x19\x49\xb9\xe4\x9c\xa4\x46\x52\x2f\x69\x92\xb4\x4a\xce\x4b\x2e\x4a\xba\x24\x57\x25\x3d\x92\x3e\xc9\x80\x64\x58\x32\x2a\x19\x97\x4c\x4a\xee\x48\x66\x24\x73\x92\x45\xc9\x43\xc9\x23\xc9\x13\xc9\xba\x64\x53\xb2\x2d\x79\x21\x05\x29\x2d\xe5\x49\x45\x52\x85\x54\x2b\x35\x48\x2d\x52\x87\x34\x4d\xea\x96\x7a\xa5\x45\xd2\x52\xe9\x59\x69\x85\xb4\x4a\x5a\x2b\x6d\x90\x36\x4b\xdb\xa4\x17\xa4\x9d\xd2\xcb\xd2\x6e\xe9\x75\x69\xbf\x74\x50\x3a\x22\xbd\x25\x9d\x90\x4e\x49\xef\x4a\x67\xa5\xf3\xd2\x07\xd2\x65\xe9\xaa\x74\x4d\xfa\x4c\xba\x25\xdd\x91\xee\xc9\x48\x19\x47\xc6\x97\x49\x64\x2a\x99\x4e\x66\x92\x59\x65\x4e\x59\xba\x2c\x47\x56\x20\x2b\x96\x9d\x96\x95\xc9\x2a\x65\xd5\xb2\x3a\x59\xa3\xac\x45\xd6\x2e\xeb\x90\x5d\x92\x5d\x91\x5d\x93\xf5\xca\x6e\xc8\x86\x64\x37\x65\x63\xb2\xdb\xb2\x69\xd9\x3d\xd9\x7d\xd9\x82\x6c\x49\xb6\x22\x7b\x2c\x7b\x2a\xdb\x90\x3d\x97\xed\xca\xf6\xe5\x2c\x39\x57\x2e\x90\xcb\xe4\x6a\xb9\x5e\x6e\x96\xdb\xe4\x2e\x79\xa6\xdc\x23\x2f\x94\x97\xc8\xcf\xc8\xcb\xe5\xe7\xe4\x35\xf2\x7a\x79\x93\xbc\x55\x7e\x5e\x7e\x51\xde\x25\xbf\x2a\xef\x91\xf7\xc9\x07\xe4\xc3\xf2\x51\xf9\xb8\x7c\x52\x7e\x47\x3e\x23\x9f\x93\x2f\xca\x1f\xca\x1f\xc9\x9f\xc8\xd7\xe5\x9b\xf2\x6d\xf9\x0b\x05\x28\x68\x05\x4f\x21\x52\x28\x14\x5a\x85\x41\x61\x51\x38\x14\x69\x0a\xb7\xc2\xab\x28\x52\x94\x2a\xce\x2a\x2a\x14\x55\x8a\x5a\x45\x83\xa2\x59\xd1\xa6\xb8\xa0\xe8\x54\x5c\x56\x74\x2b\xae\x2b\xfa\x15\x83\x8a\x11\xc5\x2d\xc5\x84\x62\x4a\x71\x57\x31\xab\x98\x57\x3c\x50\x2c\x2b\x56\x15\x6b\x8a\x67\x8a\x2d\xc5\x8e\x62\x4f\x49\x2a\x39\x4a\xbe\x52\xa2\x54\x29\x75\x4a\x93\xd2\xaa\x74\x2a\xd3\x95\x39\xca\x02\x65\xb1\xf2\xb4\xb2\x4c\x59\xa9\xac\x56\xd6\x29\x1b\x95\x2d\xca\x76\x65\x87\xf2\x92\xf2\x8a\xf2\x9a\xb2\x57\x79\x43\x39\xa4\xbc\xa9\x1c\x53\xde\x56\x4e\x2b\xef\x29\xef\x2b\x17\x94\x4b\xca\x15\xe5\x63\xe5\x53\xe5\x86\xf2\xb9\x72\x57\xb9\xaf\x62\xa9\xb8\x2a\x81\x4a\xa6\x52\xab\xf4\x2a\xb3\xca\xa6\x72\xa9\x32\x55\x1e\x55\xa1\xaa\x44\x75\x46\x55\xae\x3a\xa7\xaa\x51\xd5\xab\x9a\x54\xad\xaa\xf3\xaa\x8b\xaa\x2e\xd5\x55\x55\x8f\xaa\x4f\x35\xa0\x1a\x56\x8d\xaa\xc6\x55\x93\xaa\x3b\xaa\x19\xd5\x9c\x6a\x51\xf5\x50\xf5\x48\xf5\x44\xb5\xae\xda\x54\x6d\xab\x5e\x44\x43\x34\x1d\xcd\x8b\x16\x45\x2b\xa2\xb5\xd1\x86\x68\x4b\xb4\x23\x3a\x2d\xda\x1d\xed\x8d\x2e\x8a\x2e\x8d\x3e\x1b\x5d\x11\x5d\x15\x5d\x1b\xdd\x10\xdd\x1c\xdd\x16\x7d\x21\xba\x33\xfa\x72\x74\x77\xf4\xf5\xe8\xfe\xe8\xc1\xe8\x91\xe8\x5b\xd1\x13\xd1\x53\xd1\x77\xa3\x67\xa3\xe7\xa3\x1f\x44\x2f\x47\xaf\x46\xaf\x45\x3f\x8b\xde\x8a\xde\x89\xde\x53\x93\x6a\x8e\x9a\xaf\x96\xa8\x55\x6a\x9d\xda\xa4\xb6\xaa\x9d\xea\x74\x75\x8e\xba\x40\x5d\xac\x3e\xad\x2e\x53\x57\xaa\xab\xd5\x75\xea\x46\x75\x8b\xba\x5d\xdd\xa1\xbe\xa4\xbe\xa2\xbe\xa6\xee\x55\xdf\x50\x0f\xa9\x6f\xaa\xc7\xd4\xb7\xd5\xd3\xea\x7b\xea\xfb\xea\x05\xf5\x92\x7a\x45\xfd\x58\xfd\x54\xbd\xa1\x7e\xae\xde\x55\xef\x6b\x58\x1a\xae\x46\xa0\x91\x69\xd4\x1a\xbd\xc6\xac\xb1\x69\x5c\x9a\x4c\x8d\x47\x53\xa8\x29\xd1\x9c\xd1\x94\x6b\xce\x69\x6a\x34\xf5\x9a\x26\x4d\xab\xe6\xbc\xe6\xa2\xa6\x4b\x73\x55\xd3\xa3\xe9\xd3\x0c\x68\x86\x35\xa3\x9a\x71\xcd\xa4\xe6\x8e\x66\x46\x33\xa7\x59\xd4\x3c\xd4\x3c\xd2\x3c\xd1\xac\x6b\x36\x35\xdb\x9a\x17\x5a\xd0\xd2\x5a\x9e\x56\xa4\x55\x68\xb5\x5a\x83\xd6\xa2\x75\x68\xd3\xb4\x6e\xad\x57\x5b\xa4\x2d\xd5\x9e\xd5\x56\x68\xab\xb4\xb5\xda\x06\x6d\xb3\xb6\x4d\x7b\x41\xdb\xa9\xbd\xac\xed\xd6\x5e\xd7\xf6\x6b\x07\xb5\x23\xda\x5b\xda\x09\xed\x94\xf6\xae\x76\x56\x3b\xaf\x7d\xa0\x5d\xd6\xae\x6a\xd7\xb4\xcf\xb4\x5b\xda\x1d\xed\x5e\x0c\x19\xc3\x89\xe1\xc7\x48\x62\x54\x31\xba\x18\x53\x8c\x35\xc6\x19\x93\x1e\x93\x13\x53\x10\x53\x1c\x73\x3a\xa6\x2c\xa6\x32\xa6\x3a\xa6\x2e\xa6\x31\xa6\x25\xa6\x3d\xa6\x23\xe6\x52\xcc\x95\x98\x6b\x31\xbd\x31\x37\x62\x86\x62\x6e\xc6\x8c\xc5\xdc\x8e\x99\x8e\xb9\x17\x73\x3f\x66\x21\x66\x29\x66\x25\xe6\x71\xcc\xd3\x98\x8d\x98\xe7\x31\xbb\x31\xfb\x3a\x96\x8e\xab\x13\xe8\x64\x3a\xb5\x4e\xaf\x33\xeb\x6c\x3a\x97\x2e\x53\xe7\xd1\x15\xea\x4a\x74\x67\x74\xe5\xba\x73\xba\x1a\x5d\xbd\xae\x49\xd7\xaa\x3b\xaf\xbb\xa8\xeb\xd2\x5d\xd5\xf5\xe8\xfa\x74\x03\xba\x61\xdd\xa8\x6e\x5c\x37\xa9\xbb\xa3\x9b\xd1\xcd\xe9\x16\x75\x0f\x75\x8f\x74\x4f\x74\xeb\xba\x4d\xdd\xb6\xee\x45\x2c\xc4\xd2\xb1\xbc\x58\x51\xac\x22\x56\x1b\x6b\x88\xb5\xc4\x3a\x62\xd3\x62\xdd\xb1\xde\xd8\xa2\xd8\xd2\xd8\xb3\xb1\x15\xb1\x55\xb1\xb5\xb1\x0d\xb1\xcd\xb1\x6d\xb1\x17\x62\x3b\x63\x2f\xc7\x76\xc7\x5e\x8f\xed\x8f\x1d\x8c\x1d\x89\xbd\x15\x3b\x11\x3b\x15\x7b\x37\x76\x36\x76\x3e\xf6\x41\xec\x72\xec\x6a\xec\x5a\xec\xb3\xd8\xad\xd8\x9d\xd8\x3d\x3d\xa9\xe7\xe8\xf9\x7a\x89\x5e\xa5\xd7\xe9\x4d\x7a\xab\xde\xa9\x4f\xd7\xe7\xe8\x0b\xf4\xc5\xfa\xd3\xfa\x32\x7d\xa5\xbe\x5a\x5f\xa7\x6f\xd4\xb7\xe8\xdb\xf5\x1d\xfa\x4b\xfa\x2b\xfa\x6b\xfa\x5e\xfd\x0d\xfd\x90\xfe\xa6\x7e\x4c\x7f\x5b\x3f\xad\xbf\xa7\xbf\xaf\x5f\xd0\x2f\xe9\x57\xf4\x8f\xf5\x4f\xf5\x1b\xfa\xe7\xfa\x5d\xfd\x7e\x1c\x2b\x8e\x1b\x27\x88\x93\xc5\xa9\xe3\xf4\x71\xe6\x38\x5b\x9c\x2b\x2e\x33\xce\x13\x57\x18\x57\x12\x77\x26\xae\x3c\xee\x5c\x5c\x4d\x5c\x7d\x5c\x53\x5c\x6b\xdc\xf9\xb8\x8b\x71\x5d\x71\x57\xe3\x7a\xe2\xfa\xe2\x06\xe2\x86\xe3\x46\xe3\xc6\xe3\x26\xe3\xee\xc4\xcd\xc4\xcd\xc5\x2d\xc6\x3d\x8c\x7b\x14\xf7\x24\x6e\x3d\x6e\x33\x6e\x3b\xee\x85\x01\x0c\xb4\x81\x67\x10\x19\x14\x06\xad\xc1\x60\xb0\x18\x1c\x86\x34\x83\xdb\xe0\x35\x14\x19\x4a\x0d\x67\x0d\x15\x86\x2a\x43\xad\xa1\xc1\xd0\x6c\x68\x33\x5c\x30\x74\x1a\x2e\x1b\xba\x0d\xd7\x0d\xfd\x86\x41\xc3\x88\xe1\x96\x61\xc2\x30\x65\xb8\x6b\x98\x35\xcc\x1b\x1e\x18\x96\x0d\xab\x86\x35\xc3\x33\xc3\x96\x61\xc7\xb0\x67\x24\x8d\x1c\x23\xdf\x28\x31\xaa\x8c\x3a\xa3\xc9\x68\x35\x3a\x8d\xe9\xc6\x1c\x63\x81\xb1\xd8\x78\xda\x58\x66\xac\x34\x56\x1b\xeb\x8c\x8d\xc6\x16\x63\xbb\xb1\xc3\x78\xc9\x78\xc5\x78\xcd\xd8\x6b\xbc\x61\x1c\x32\xde\x34\x8e\x19\x6f\x1b\xa7\x8d\xf7\x8c\xf7\x8d\x0b\xc6\x25\xe3\x8a\xf1\xb1\xf1\xa9\x71\xc3\xf8\xdc\xb8\x6b\xdc\x37\xb1\x4c\x5c\x93\xc0\x24\x33\xa9\x4d\x7a\x93\xd9\x64\x33\xb9\x4c\x99\x26\x8f\xa9\xd0\x54\x62\x3a\x63\x2a\x37\x9d\x33\xd5\x98\xea\x4d\x4d\xa6\x56\xd3\x79\xd3\x45\x53\x97\xe9\xaa\xa9\xc7\xd4\x67\x1a\x30\x0d\x9b\x46\x4d\xe3\xa6\x49\xd3\x1d\xd3\x8c\x69\xce\xb4\x68\x7a\x68\x7a\x64\x7a\x62\x5a\x37\x6d\x9a\xb6\x4d\x2f\xe2\x21\x9e\x8e\xe7\xc5\x8b\xe2\x15\xf1\xda\x78\x43\xbc\x25\xde\x11\x9f\x16\xef\x8e\xf7\xc6\x17\xc5\x97\xc6\x9f\x8d\xaf\x88\xaf\x8a\xaf\x8d\x6f\x88\x6f\x8e\x6f\x8b\xbf\x10\xdf\x19\x7f\x39\xbe\x3b\xfe\x7a\x7c\x7f\xfc\x60\xfc\x48\xfc\xad\xf8\x89\xf8\xa9\xf8\xbb\xf1\xb3\xf1\xf3\xf1\x0f\xe2\x97\xe3\x57\xe3\xd7\xe2\x9f\xc5\x6f\xc5\xef\xc4\xef\x99\x49\x33\xc7\xcc\x37\x4b\xcc\x2a\xb3\xce\x6c\x32\x5b\xcd\x4e\x73\xba\x39\xc7\x5c\x60\x2e\x36\x9f\x36\x97\x99\x2b\xcd\xd5\xe6\x3a\x73\xa3\xb9\xc5\xdc\x6e\xee\x30\x5f\x32\x5f\x31\x5f\x33\xf7\x9a\x6f\x98\x87\xcc\x37\xcd\x63\xe6\xdb\xe6\x69\xf3\x3d\xf3\x7d\xf3\x82\x79\xc9\xbc\x62\x7e\x6c\x7e\x6a\xde\x30\x3f\x37\xef\x9a\xf7\x13\x58\x09\xdc\x04\x41\x82\x2c\x41\x9d\xa0\x4f\x30\x27\xd8\x12\x5c\x09\x99\x09\x9e\x84\xc2\x84\x92\x84\x33\x09\xe5\x09\xe7\x12\x6a\x12\xea\x13\x9a\x12\x5a\x13\xce\x27\x5c\x4c\xe8\x4a\xb8\x9a\xd0\x93\xd0\x97\x30\x90\x30\x9c\x30\x9a\x30\x9e\x30\x99\x70\x27\x61\x26\x61\x2e\x61\x31\xe1\x61\xc2\xa3\x84\x27\x09\xeb\x09\x9b\x09\xdb\x09\x2f\x2c\x60\xa1\x2d\x3c\x8b\xc8\xa2\xb0\x68\x2d\x06\x8b\xc5\xe2\xb0\xa4\x59\xdc\x16\xaf\xa5\xc8\x52\x6a\x39\x6b\xa9\xb0\x54\x59\x6a\x2d\x0d\x96\x66\x4b\x9b\xe5\x82\xa5\xd3\x72\xd9\xd2\x6d\xb9\x6e\xe9\xb7\x0c\x5a\x46\x2c\xb7\x2c\x13\x96\x29\xcb\x5d\xcb\xac\x65\xde\xf2\xc0\xb2\x6c\x59\xb5\xac\x59\x9e\x59\xb6\x2c\x3b\x96\xbd\x44\x32\x91\x93\xc8\x4f\x94\x24\xaa\x12\x75\x89\xa6\x44\x6b\xa2\x33\x31\x3d\x31\x27\xb1\x20\xb1\x38\xf1\x74\x62\x59\x62\x65\x62\x75\x62\x5d\x62\x63\x62\x4b\x62\x7b\x62\x47\xe2\xa5\xc4\x2b\x89\xd7\x12\x7b\x13\x6f\x24\x0e\x25\xde\x4c\x1c\x4b\xbc\x9d\x38\x9d\x78\x2f\xf1\x7e\xe2\x42\xe2\x52\xe2\x4a\xe2\xe3\xc4\xa7\x89\x1b\x89\xcf\x13\x77\x13\xf7\xad\x2c\x2b\xd7\x2a\xb0\xca\xac\x6a\xab\xde\x6a\xb6\xda\xac\x2e\x6b\xa6\xd5\x63\x2d\xb4\x96\x58\xcf\x58\xcb\xad\xe7\xac\x35\xd6\x7a\x6b\x93\xb5\xd5\x7a\xde\x7a\xd1\xda\x65\xbd\x6a\xed\xb1\xf6\x59\x07\xac\xc3\xd6\x51\xeb\xb8\x75\xd2\x7a\xc7\x3a\x63\x9d\xb3\x2e\x5a\x1f\x5a\x1f\x59\x9f\x58\xd7\xad\x9b\xd6\x6d\xeb\x8b\x24\x48\xa2\x93\x78\x49\xa2\x24\x45\x92\x36\xc9\x90\x64\x49\x72\x24\xa5\x25\xb9\x93\xbc\x49\x45\x49\xa5\x49\x67\x93\x2a\x92\xaa\x92\x6a\x93\x1a\x92\x9a\x93\xda\x92\x2e\x24\x75\x26\x5d\x4e\xea\x4e\xba\x9e\xd4\x9f\x34\x98\x34\x92\x74\x2b\x69\x22\x69\x2a\xe9\x6e\xd2\x6c\xd2\x7c\xd2\x83\xa4\xe5\xa4\xd5\xa4\xb5\xa4\x67\x49\x5b\x49\x3b\x49\x7b\x36\xd2\xc6\xb1\xf1\x6d\x12\x9b\xca\xa6\xb3\x99\x6c\x56\x9b\xd3\x96\x6e\xcb\xb1\x15\xd8\x8a\x6d\xa7\x6d\x65\xb6\x4a\x5b\xb5\xad\xce\xd6\x68\x6b\xb1\xb5\xdb\x3a\x6c\x97\x6c\x57\x6c\xd7\x6c\xbd\xb6\x1b\xb6\x21\xdb\x4d\xdb\x98\xed\xb6\x6d\xda\x76\xcf\x76\xdf\xb6\x60\x5b\xb2\xad\xd8\x1e\xdb\x9e\xda\x36\x6c\xcf\x6d\xbb\xb6\x7d\x3b\xcb\xce\xb5\x0b\xec\x32\xbb\xda\xae\xb7\x9b\xed\x36\xbb\xcb\x9e\x69\xf7\xd8\x0b\xed\x25\xf6\x33\xf6\x72\xfb\x39\x7b\x8d\xbd\xde\xde\x64\x6f\xb5\x9f\xb7\x5f\xb4\x77\xd9\xaf\xda\x7b\xec\x7d\xf6\x01\xfb\xb0\x7d\xd4\x3e\x6e\x9f\xb4\xdf\xb1\xcf\xd8\xe7\xec\x8b\xf6\x87\xf6\x47\xf6\x27\xf6\x75\xfb\xa6\x7d\xdb\xfe\xc2\x01\x0e\xda\xc1\x73\x88\x1c\x0a\x87\xd6\x61\x70\x58\x1c\x0e\x47\x9a\xc3\xed\xf0\x3a\x8a\x1c\xa5\x8e\xb3\x8e\x0a\x47\x95\xa3\xd6\xd1\xe0\x68\x76\xb4\x39\x2e\x38\x3a\x1d\x97\x1d\xdd\x8e\xeb\x8e\x7e\xc7\xa0\x63\xc4\x71\xcb\x31\xe1\x98\x72\xdc\x75\xcc\x3a\xe6\x1d\x0f\x1c\xcb\x8e\x55\xc7\x9a\xe3\x99\x63\xcb\xb1\xe3\xd8\x4b\x26\x93\x39\xc9\xfc\x64\x49\xb2\x2a\x59\x97\x6c\x4a\xb6\x26\x3b\x93\xd3\x93\x73\x92\x0b\x92\x8b\x93\x4f\x27\x97\x25\x57\x26\x57\x27\xd7\x25\x37\x26\xb7\x24\xb7\x27\x77\x24\x5f\x4a\xbe\x92\x7c\x2d\xb9\x37\xf9\x46\xf2\x50\xf2\xcd\xe4\xb1\xe4\xdb\xc9\xd3\xc9\xf7\x92\xef\x27\x2f\x24\x2f\x25\xaf\x24\x3f\x4e\x7e\x9a\xbc\x91\xfc\x3c\x79\x37\x79\xdf\xc9\x72\x72\x9d\x02\xa7\xcc\xa9\x76\xea\x9d\x66\xa7\xcd\xe9\x72\x66\x3a\x3d\xce\x42\x67\x89\xf3\x8c\xb3\xdc\x79\xce\x59\xe3\xac\x77\x36\x39\x5b\x9d\xe7\x9d\x17\x9d\x5d\xce\xab\xce\x1e\x67\x9f\x73\xc0\x39\xec\x1c\x75\x8e\x3b\x27\x9d\x77\x9c\x33\xce\x39\xe7\xa2\xf3\xa1\xf3\x91\xf3\x89\x73\xdd\xb9\xe9\xdc\x76\xbe\x48\x81\x14\x3a\x85\x07\x44\xd8\x97\xfd\x9f\x91\x75\x00\x11\x56\x85\xf1\x4a\x8c\xdf\x08\xf0\xac\xcf\x63\x7c\x0d\x26\xf3\x83\x00\x4f\xc7\x04\x78\x4a\x13\xe0\xc9\x61\x4c\xfe\x34\x36\x0e\xb6\x06\xf6\x6f\x62\xe3\x7c\x11\xe3\xcf\x61\xcf\xd2\x21\xf0\x22\x6c\xcc\x3a\x8c\x1f\xc4\xe4\x79\x98\x7c\x0a\x36\xef\x34\x86\x97\x61\xcf\xee\x1f\x3d\x0e\xeb\x6f\x30\x79\x01\x86\x6b\x42\xe0\x53\x98\x4e\x94\x47\xcb\x84\x79\x31\x5d\xbd\x75\x34\xcf\xda\x39\x1a\x67\xff\xdd\xd1\xe3\xb0\xb6\x43\xcc\x85\xf1\x14\xb6\x2f\xea\x05\xc6\x7f\x2e\xc4\x98\x5f\xc3\xf4\xf9\x23\x0c\x1f\x38\x5a\x86\xfa\x47\x6c\x9c\x2f\x7f\x30\x3c\xfb\xc6\xd1\xb6\x1a\x64\x9f\xc7\xe0\x71\xfb\x3c\x0e\x8f\xfb\x42\x28\xfb\x7c\x5f\x3c\xef\x64\x3c\x6e\x9f\xb8\x5f\x84\x8d\x1d\x6d\xab\xef\x87\x67\x97\x1d\x6d\xe7\xb8\x6d\x1f\x87\x0f\x65\xdb\x21\x6d\x7e\xfb\xbd\x6d\xfb\xfd\xf0\xf8\x98\xc7\xe1\x71\xdb\x0e\xf2\xf1\xaf\x1d\x6d\xab\x41\xb1\xe2\xa4\xb8\xf2\x68\x9d\x7f\x60\xf8\xc6\xd1\x7b\x09\xc2\x93\xd9\x47\xfb\xd1\xd4\xff\x39\x1c\xcf\x2f\x41\xeb\xfc\x80\x70\x3c\x67\xe1\x67\x1d\x0a\x0f\xca\x6b\x6f\xfd\x9f\xc3\xc3\xbe\x7f\xb4\x7e\xf0\xdc\x1a\x24\x8f\xe7\xd9\x9d\x10\xfc\x97\x8f\x7e\xf6\xfd\xe0\xd4\x9b\xef\x2d\x8f\xc7\xcf\x20\x9d\x9f\x14\xcf\x3a\x86\x0c\x16\x63\x71\xdf\x3f\x29\xce\xfe\x0b\x8c\xff\x21\x36\x17\x56\x7b\xe0\xf9\xf4\xa4\x38\x5e\xb7\xe0\xb9\xf8\x03\xc3\xf1\x5c\xff\xb9\x9f\x1d\x0f\xaa\xa3\xbc\x3f\x7f\x1c\xaf\xdf\x82\x6a\x12\xbc\x7e\xfb\x5a\x08\x1c\xdf\xe3\x3f\xfe\xec\x38\x15\xa2\xbe\xa2\x2b\x30\x3c\xfa\x68\x99\xb0\x62\x8c\x17\xb1\x8f\x8c\xdb\xc7\x89\xe1\xf4\x4f\xde\x7b\xae\xa0\x3c\x88\xc5\x5b\xfa\xab\x98\xbc\x1d\x93\xc1\xea\x7c\xd6\x37\xd8\x47\xc7\x52\xbc\x96\xc6\xd6\x40\x65\xb0\x8f\x8c\x69\xa1\xe2\x12\x39\x84\xe1\xd8\xbe\x38\x98\xbf\x1c\xc7\xc7\xe9\x3e\x4c\xe6\xb3\x01\x3e\x1c\xb3\x1f\x36\x86\xd3\x10\xe2\x5c\x42\xdc\x29\x82\x7c\xea\x0e\xb6\xfe\x2d\xf6\xd1\x7e\xf4\x3c\x04\x8e\xd9\x12\x5b\x82\xad\x07\xe7\x8b\x8f\xd6\x73\x90\x0d\x6f\x1c\xc3\x6e\x43\xd5\x66\x78\xdd\xfe\xd6\xd1\x7b\xc4\x75\xc2\xc5\xd6\x1f\x8e\xc5\x40\xce\x2e\xb6\x97\x44\x6c\xfd\x78\xae\xf9\x07\xec\xd9\x78\xec\x59\x4c\x3f\xec\x71\x6c\xde\x10\x75\x51\xa8\xfc\x18\x32\x9e\x87\x88\x1b\xb8\x1e\xf0\x3b\x05\x5e\xeb\x9e\xb8\xc6\x08\x61\xdb\x27\xcd\x35\x41\x67\x14\x22\xbf\x1f\xe7\x2c\x42\xad\x93\x53\x8d\xe1\x98\x6d\x87\xf2\xaf\x93\xd6\xae\x27\xad\xf1\x4e\x5a\x0b\x9d\x54\x9f\x27\xcd\xc5\x27\xcd\x41\xa1\x72\x65\x50\x2c\xc5\xef\x8c\xa1\x6a\x4e\xf9\xd1\xe7\x45\xc7\x62\x38\x27\xc4\xbc\x21\xee\xda\xc7\x39\x97\x90\x76\x18\x22\x87\x52\x78\xee\x48\xc0\xf0\xfe\xa3\xcf\x8b\x3d\x76\x34\x1f\x74\xc7\x0f\x91\xe3\xf0\x1a\x92\x15\xaa\x5f\x81\xe7\x62\x3c\x56\xfc\x14\x1b\xbf\x2a\xc4\x39\xa6\xbc\xb7\x7e\x42\xd5\xd8\x74\xca\xd1\xe7\x15\xb2\xc6\x0b\x55\x93\x84\xe8\x29\x85\xe2\x83\xf4\x53\x7b\x0c\xf9\x10\xf1\x9f\xfe\x3a\xfb\xc8\xf8\x8f\xf3\x61\x5f\x3f\xda\xf6\x82\xee\x1a\xa1\xe6\xfd\x41\x88\xfd\x7e\xed\x68\xfb\x0f\xc5\x07\xc5\x04\x1c\xff\xf1\xd1\x36\x49\x65\x87\x38\x2f\x2c\xb7\xe2\x7d\xb3\x50\x7c\xc8\xb5\xe1\x77\x31\x3c\xfe\x60\x36\x49\x63\xf5\x0c\xfd\xa5\xa3\xed\xe1\xc4\xbc\xfd\x68\x9e\xf5\xb7\x47\xf3\xb8\x8f\x9c\xb4\xf7\x82\xc7\xb1\x50\xfd\x40\x3c\xbe\x85\x55\x1e\x7d\xbe\x41\x35\x79\x08\x1b\x08\xaa\x55\xb0\xfa\x0d\xcf\x7d\x38\x1f\xe4\xe3\x21\x78\xdc\x47\x82\x7a\xc5\x9a\xa3\xed\x19\xb7\xd5\xb0\x92\xa3\x75\x82\xe7\x74\xea\x87\x47\xdb\x7c\xa8\xf5\x70\xb0\x98\xc3\xc1\xea\x6d\x0e\x56\x43\xd2\x5f\x39\x7a\x6d\x6c\x4c\xb7\x41\x35\x12\x66\x87\x61\xf8\xbd\x1b\xab\x1b\x59\x3f\x3a\x86\x3d\x87\xea\x0f\x63\x31\x39\xa4\x5f\x84\xea\x27\xdb\x8f\xb6\xc3\x20\xbb\xfa\xc7\xa3\xc7\x61\xe1\x7d\x27\x4c\x27\x9c\x10\xbd\x44\x2a\xd4\x5e\x0a\x42\xd8\xea\x31\xf6\x4b\x8f\x1f\x7d\xee\xc7\xe9\xbd\x1f\xa7\xc7\xce\xc2\xee\x7a\x41\x7e\x31\x70\xb4\x7e\x8e\x93\x23\x82\xe2\x7c\xa8\x78\xbe\x19\xc2\xb6\x43\xf5\x9d\xbc\x21\xc6\x09\x55\x13\x56\x85\x58\xe7\x49\xf1\xf7\xd3\xb7\xfc\x10\xf0\x9f\x57\xff\x13\xbf\x83\x07\xbd\x3f\xfa\x80\xfa\x99\x1f\x14\x7e\xe2\x7e\x66\x88\xbb\xd2\x49\xf1\x0f\xa3\x87\x19\xe4\xe3\xd8\x7b\xc9\xa0\x3a\xe1\x84\xf8\x07\xd6\xf3\xfc\x90\xfb\x9c\x21\xef\x50\xf4\xd1\xf6\x16\x12\xff\x80\xfa\xa2\x3f\xb7\x7e\xe9\x87\xdc\x47\xfd\xbf\xad\xbf\x1a\x74\x0f\xfa\xda\x7b\xe3\xa1\xfa\xae\x1f\x36\x1e\xf4\x8e\x7e\xe0\xbd\xf1\x90\x77\xae\x0f\xa8\xf7\x1b\x14\x03\x3f\x77\xf4\x9a\x43\xdd\xf5\x82\xfa\xc6\x1f\xd4\x7b\xc3\xff\x8f\xe2\x3f\xb7\xfc\xfb\x01\xe1\x1f\x76\x8f\xeb\xe7\x86\x87\xe8\xb7\x7f\xe8\xf8\x49\xdf\x13\x85\xe8\xb1\x7f\xd8\xf8\xb1\xde\x43\xbd\x0f\x1c\xef\x71\xb1\xbe\x87\xf1\xc7\xa8\x73\x82\x72\x37\xfe\xbe\x03\x8f\x51\x9f\x3b\x7a\x5e\x3a\x10\x6f\x7f\xfe\xdf\xd8\x21\xfd\x7f\xc3\x02\xfc\xbf\xc7\x9e\xf0\xff\x1e\x7b\x02\x0c\xbe\x35\xb2\x8a\x8f\xa2\x1f\x7d\xa7\xe7\xa3\xef\xf4\x7c\xf4\x9d\x9e\x8f\xbe\xd3\xf3\xd1\x77\x7a\x3e\xfa\x4e\xcf\x47\xdf\xe9\xf9\xe8\x3b\x3d\x1f\x7d\xa7\xe7\xa3\xef\xf4\x7c\xf4\x9d\x9e\x8f\xbe\xd3\xf3\xff\xe6\xef\xf4\xd0\x2c\x1f\x45\xbf\x57\xa7\x0a\xf1\xe8\x77\xfb\x84\x29\x11\xaf\x44\xfc\x06\xe2\x37\xd0\xef\xdb\xf9\xbc\x8f\x67\x7d\x1e\xf1\x35\x88\x47\xbf\x8d\x27\xec\x07\x48\xe6\x07\x3e\x9e\x8e\xf1\xf1\x74\x0c\xfa\x6d\x3f\x1a\xf4\x17\xcc\x34\xe8\x37\xf9\x0c\xa3\xdf\x60\x3f\x8c\xe4\x4f\x23\xf9\xd3\x68\x1c\xb4\x06\x16\x5a\x03\xfb\x37\x7d\x3c\xfb\x37\xd1\x38\x5f\x44\xe3\x7c\x11\xf1\xe7\x10\x7f\x8e\xf9\xdd\x41\xe8\x59\xfa\x10\x5e\x84\xf0\x22\x34\x66\x1d\x1a\x93\xf9\xbb\x72\x83\x88\x1f\x44\xf2\x3c\x24\xcf\x43\xf2\x29\x48\x3e\x05\xcd\x3b\x8d\xe6\x9d\x46\x78\x19\xc2\xcb\xd0\xb3\xfb\xe8\xd9\xfd\x83\xe3\xb0\xfe\x06\xf1\x7f\x83\xe4\x05\x48\x1e\xfd\x76\x23\x16\xda\x2f\x4b\x73\x08\x9f\x42\xf8\x14\xd2\x09\xd2\x2d\xa5\x3c\x28\x13\xe6\x45\xbc\x17\xe9\xea\x2d\xa4\xab\xb7\x0e\xf2\xac\x1d\x34\xce\xce\x41\x9c\xfd\x77\x68\xfd\x7f\x77\x70\x1c\xd6\x36\x92\xdf\x3e\x34\x17\xc6\x53\x68\x5f\x14\xda\x17\xf5\x02\xf1\x2f\x10\xff\x39\xc4\x7f\xee\xd0\x98\x5f\x43\x63\x7e\x0d\xe9\xf3\x47\x48\x9f\x3f\x42\xf8\x00\xc2\x07\x0e\xca\x50\xff\x88\xc6\xf9\x47\x34\x0e\xea\x25\xf8\xed\xed\x7d\xf0\xcc\xe7\xef\xd8\x37\x18\x5b\x45\xb8\x92\xb1\x4f\xd4\x75\xf8\xfc\x71\x79\xa6\x97\xc6\xd8\xe7\x71\x78\xe6\x5d\x1f\xe3\x0b\xcc\x7b\x95\x97\xf6\xc9\x74\xbc\xde\x37\xcf\x63\x3a\x52\xc7\xe5\x99\x1e\x0f\x63\x9f\xb8\x5f\x84\x8d\x21\x7e\xec\xa0\xad\xbe\x1f\x9e\x8d\xfc\x82\x5d\x76\xd0\xce\x71\xdb\x3e\x0e\x1f\xca\xb6\x43\xda\x3c\x6e\xc3\x21\x6c\xfb\xfd\xf0\xf8\x98\xc7\xe1\x71\xdb\x0e\xf2\x71\x1c\xc7\x6c\x35\x28\x56\x84\xc4\x03\x71\x38\x08\xc7\x6d\x1b\x8f\x2d\x1f\x14\x8e\xd9\x73\x50\x7c\xc0\x62\x7e\x58\x32\xe2\x93\x0f\xf9\x11\x7e\xbe\x27\xc6\xb1\x3c\x72\x0c\x79\xe6\xdd\x35\x93\x5f\x82\xd6\x79\x62\x3c\x90\xa7\x70\x9c\x79\x47\xcd\xe4\x2c\xa6\x07\xcc\x9c\x35\x9e\xcb\x70\x1b\xc0\x63\x02\x6e\xab\x27\xc7\xb1\xfc\x78\x0c\xf9\xb0\xef\xa3\x35\x7c\xdf\xaf\x1f\xeb\x2b\x9f\x42\x9f\x75\x62\x72\x6b\x90\x3c\x9e\x67\xb1\xdc\x11\xc4\x7f\x99\xe9\xf2\x32\xcf\x32\xdd\xdf\xfd\x03\x79\x39\xc8\x1f\x8f\x81\x53\x6f\xa2\x7d\xbd\xf9\x6e\xf2\x78\xfc\xc4\x75\x8b\xe7\xfd\x60\x3c\x84\x7c\x16\x92\xcf\x7a\xd7\x67\xb1\x18\x8b\xfb\xfe\x49\x71\xf6\x5f\xa0\x18\xf8\x17\x88\xff\x21\xe2\x7f\x88\xe6\x2a\x62\x3a\xe2\xfb\x07\xf2\x29\x5e\x93\x04\xe3\x47\xcb\x33\xef\x90\x99\xba\x05\xcf\xc5\xa1\xf1\x40\x9d\x73\x2c\x79\xac\x86\xc1\xf3\x3b\xf3\xae\xf2\x28\xfc\x68\x79\x3c\x07\x05\xe9\xf9\x43\xc7\x69\xd6\x51\x38\xf3\xee\x97\xa9\xdf\x82\x6a\x12\x2c\x3f\xe2\xf1\x39\x08\xc7\xf7\x8e\xd5\x2a\x27\xc5\x29\x14\x4f\xa8\x43\xf5\x15\x5d\x81\xd6\x53\x81\xf0\x68\x84\x47\x1f\x8a\x4b\xc5\x88\x2f\x46\xbc\x08\xf1\xa2\xfd\x83\x75\x78\xc8\x18\x1e\x88\xd5\xf4\x4f\xd0\x5c\x3f\x79\xb7\xb9\x82\xf2\x20\x16\x87\xe9\xaf\xa2\x67\xbf\x8a\xe4\xd1\xdf\x22\x0e\xb3\xef\x1f\xa8\xf3\x59\xdf\x40\xfc\x37\x0e\xc5\x58\xbc\x96\x46\x6b\x60\xa3\x35\x50\x19\x48\x27\x19\x07\x63\x5d\xa8\xb8\x44\x0e\xa1\xf8\xe0\xff\xdd\x9e\x08\x47\xfb\xe2\x20\x3f\xe2\x14\xbd\xbb\x8f\xd3\xaf\xee\x02\x74\x1f\xe2\xfb\x90\xcc\x67\x91\xcc\x67\x7d\x7c\x38\xb2\x9f\x70\x64\x3f\x6c\x84\xb3\x11\x4e\xa3\xbf\x38\x46\xc3\xa1\x73\x09\x71\xa7\x08\xf2\xa9\x3b\x08\xbf\x83\xd6\xbf\x85\xd6\xbf\x75\xc8\x8f\x9e\x23\x99\xe7\xef\xe6\x5f\x6c\x09\x5a\x8f\x04\xad\x07\xf1\x34\xc3\x23\xdb\xa0\x8b\x0f\xea\x39\xe8\x6e\x82\xe9\x2a\xc8\x67\x71\xbb\x0d\x55\x9b\xe1\x75\x3b\x8a\xcf\xac\xb7\x0e\xee\x11\xd7\x09\xf3\x3d\x12\x2e\x5a\x7f\x38\x8a\x81\xe1\x28\x06\x72\x76\xd1\x19\xed\xa2\xbd\x24\xa2\xbd\x24\xa2\xf5\xa3\xf3\xa5\x99\x5c\xf3\x0f\x68\xfc\x7f\x40\xcf\xc6\xa3\x67\xe3\xd1\xb3\x48\x3f\x1c\xa4\x1f\xf6\x38\x7a\x76\x7c\xff\x5d\xea\xa5\x50\xf9\x31\x64\x3c\x0f\x11\x4f\x70\x3d\xe0\x77\x0a\xbc\xd6\x0d\x55\x33\x84\xac\x31\xd0\xe7\xce\x5e\xda\x36\x8a\x15\x3b\x07\xed\xf3\x38\xb9\x86\xf9\x2c\x80\xff\x8c\xd0\xdd\x99\x75\x28\xbf\x73\x91\x2d\xbd\xfb\x59\x84\x5a\x27\x07\xfd\x05\x72\x4e\x35\xc2\x91\x6d\x87\xd5\xed\xbf\x4b\x9e\x3d\x69\x4d\x7b\xd2\x9a\xf0\xa4\xb5\xd3\x49\x73\x77\xe8\x1c\x7d\x34\x7e\xd2\xdc\x14\x2a\x57\x06\xc5\x52\x14\xbb\x58\xcc\x9d\x31\x54\xcd\x29\x47\x76\x22\x3f\x78\x5e\x74\x2c\xc2\x63\x11\x8e\xfe\x32\x7c\x18\xe7\xdd\xfc\x3d\xf4\xb9\xd0\x47\xd6\xde\x21\xed\x30\x44\x0e\xa5\xd0\x38\x14\x93\x3b\x12\xd0\xda\x12\x10\xde\x8f\xf0\xfe\x83\xe7\xc5\x46\x77\x52\xf6\xd8\x41\x3e\xa8\x07\x85\xe5\xbb\xa0\x3b\x26\x56\x43\x06\xed\x17\xef\x57\xe0\xb9\x18\xed\x97\x62\x62\xc5\x4f\x11\xff\xd3\xfd\x03\x3d\xae\x50\xbd\xa0\x50\xfa\xc1\xfb\x57\x41\x76\x88\x9e\xa5\x53\x0e\xc5\x81\x10\xb5\x5f\x50\xdc\xc6\x6b\x92\x10\x3d\xa5\x50\x7c\x90\x7e\x6a\x11\x5f\xfb\xae\xf2\x21\xe2\x3f\xfd\x75\xb4\xfe\xaf\x1f\x8c\xff\x38\x1f\x86\x64\xc2\xbe\x7e\xd0\xf6\x82\xee\x1a\xa1\xe6\x45\xf1\x93\xf5\x83\x43\xfb\xc5\xef\xcb\x87\xee\xda\xf4\xcd\x83\x78\x50\x4c\x40\x38\xc5\xe0\x3f\x46\xf8\x8f\x0f\xda\x24\x95\x8d\xf8\xec\x43\xe7\x85\xe5\x56\xbc\x6f\x16\x8a\x0f\xd9\x13\xc0\xef\x62\x78\xfc\x41\x36\x49\x23\x9b\xa4\x51\x3d\x43\xa3\x7a\x86\xfe\x12\xe2\xbf\x74\xd0\x1e\x4e\xcc\xa3\x78\x42\xd9\x0f\xf2\xac\xbf\x45\x6b\xf8\xdb\x83\x3c\xee\x23\x27\xed\xbd\xe0\x71\x2c\x54\x3f\x10\x8f\x6f\x61\x95\x88\xaf\x3c\x78\xbe\x41\x35\x79\x08\x1b\x08\xaa\x55\x50\xfd\xc6\x42\xf5\x1b\x9e\xfb\x70\x3e\xc8\xc7\x43\xf0\xb8\x8f\x04\xf5\x8a\x11\x1e\xa6\x39\x14\x4b\x31\x5b\x0d\x2b\x41\x78\xc9\x41\x9d\xe0\xf5\x2a\x85\x72\x2e\xf5\xc3\x83\x36\x1f\x6a\x3d\x1c\x14\x73\x38\x28\xe6\x70\x50\xbd\xcd\x41\xf5\x36\x07\xd5\x90\x1c\x54\x43\xd2\x5f\x41\xeb\xfc\xca\xc1\xb5\xb1\x91\x6e\xd9\x48\xb7\x41\x35\x12\x66\x87\x61\xe8\xde\x1d\xc6\xdc\xbb\x51\xdd\xc8\x42\x75\x23\x0b\xe9\x9f\xf5\xa3\x77\xb5\xe7\x50\xfd\x61\xac\x5f\x1d\xd2\x2f\x42\xf5\x93\x71\x5b\x0d\xd1\x5b\x0e\xca\x59\x78\xdc\x40\x7d\x27\x16\xd3\x77\x42\x3a\x61\x21\x9d\x70\x50\xec\xe2\x1c\xea\x25\xe2\x31\x21\x68\x2f\x05\x88\x2f\x38\x64\xab\xc7\xd8\x2f\x8d\xf4\x4c\x8f\x1f\x3c\xf7\xe3\xf4\xde\x8f\xd3\x63\x67\xa1\xbb\x1e\x4b\x74\xc8\x2f\xb0\x9a\x3c\xc8\x2f\x8e\x91\x23\x82\xe2\x7c\xa8\x78\xbe\x89\xe4\x37\x0f\xd9\x36\xe6\x2f\x41\xb1\x1d\xaf\x73\xf0\x71\x42\xf5\x2d\xd1\x77\x74\xfc\xef\x92\xf0\x75\xe2\xef\x98\x8e\x83\xbf\x9f\xbe\xe5\x87\x80\x07\xd7\xae\x58\x7d\x1e\x12\xa7\x43\xf4\x39\x43\xe1\x21\x6a\x66\xf4\x9d\x1e\xe6\x0e\xce\x7c\xa7\xc7\xff\xfe\x28\x44\x6d\x7f\xd2\x7e\xe6\xc9\xe5\x8f\xc6\x8f\xd7\xcf\x0c\xf4\x18\x43\xdd\x95\x42\xf5\x07\x42\xf6\x33\x43\xf6\x24\x3f\x98\xde\x26\xf3\x1d\x1d\xe6\xbd\x64\x50\x9d\x10\x12\xa7\x59\x47\xe1\x27\xef\x79\x9e\x10\x0f\xaa\xe1\xd1\xde\x8f\xb8\x13\xfd\xec\x38\xf3\xf9\x5f\xff\x3b\x26\xdc\x5f\x42\xe1\x1f\x50\x5f\x34\x64\x2d\xfd\x41\xf5\x45\x4f\x8a\x07\xf5\x4b\x91\x6d\xbf\x6b\xbf\xf4\xa4\x78\xa8\x3e\xe7\xc9\x71\xfc\xae\x8a\xf9\x75\x08\x9c\xf9\xee\x8e\xff\x1e\x84\xd7\xe7\xf8\xfd\x08\xc3\x43\xf5\x5d\x4f\x8e\xd3\xac\x93\xe0\xcc\x77\x77\xfc\xef\xe8\xb1\x5c\x19\x0a\x0f\xd9\x07\x0e\xd9\xe3\xa5\x8f\xee\xa1\x85\xba\x6b\xe3\x31\x10\xb3\x07\xfa\x47\x74\x1d\x56\xf7\xd6\x1d\x75\xd7\x63\xbe\xd3\xe3\xef\x1b\x87\xca\xa7\xc1\x77\xf9\xba\x0f\x17\x47\x3a\x79\x8f\xf7\x95\xc7\x91\xff\xa0\x70\xfa\x3d\x7b\x17\xef\xf3\xbd\x64\xdd\x07\x83\x87\xaa\x07\xe8\x63\xf4\xb8\x8e\xce\x9b\x27\xed\x19\x1e\xc0\xeb\x3e\x18\x3c\x54\x5e\xc0\xe6\x45\xdf\xb9\x39\xdc\x6f\xff\xe0\x70\xfa\xc8\x7e\xfe\xf1\xe2\x5e\x00\x67\xbe\x73\x73\xb8\xc7\xfe\xc1\xe1\xf4\x91\x3d\xfc\xd0\xef\xa1\xe8\xa3\x7b\x41\xc7\x79\x6f\x85\xdf\x9d\xb1\x1e\x17\xeb\x7b\x08\xff\xde\xfe\x31\xeb\x9c\xa0\xcf\x8d\xe0\xef\x3b\xf0\x18\x85\xe7\x2c\xfc\x5e\x8f\xfa\xe4\xb4\x2f\xde\xfe\x5f\xf1\x9d\x1e\x4a\x4b\x19\x00\x80\x0d\x04\x68\x01\xc0\xc7\x5b\x80\x00\x07\x00\xa4\x01\x80\x1b\x08\xf0\x02\x41\xfe\x9a\x8f\x23\x7f\x8d\x55\x0c\x04\x31\xc2\x50\x30\xbf\x44\xfc\x14\xfd\x75\xc4\x8f\xb5\x15\xdc\x02\xea\x63\x77\x80\x47\x3e\x12\x5a\x84\x0e\x61\x9a\xd0\x2d\xf4\x0a\x8b\x84\xa5\xc2\xb3\xc2\x0a\x61\x95\xb0\x56\xd8\x20\x6c\x16\xb6\x09\x2f\x08\x3b\x85\x97\x85\xdd\xc2\xeb\xc2\x7e\xe1\xa0\x70\x44\x78\x4b\x38\x21\x9c\x12\xde\x15\xce\x0a\xe7\x85\x0f\x84\xcb\xc2\x55\xe1\x9a\xf0\x99\x70\x4b\xb8\x23\xdc\x13\x91\x22\x8e\x88\x2f\x92\x88\x54\x22\x9d\xc8\x24\xb2\x8a\x9c\xa2\x74\x51\x8e\xa8\x40\x54\x2c\x3a\x2d\x2a\x13\x55\x8a\xaa\x45\x75\xa2\x46\x51\x8b\xa8\x5d\xd4\x21\xba\x24\xba\x22\xba\x26\xea\x15\xdd\x10\x0d\x89\x6e\x8a\xc6\x44\xb7\x45\xd3\xa2\x7b\xa2\xfb\xa2\x05\xd1\x92\x68\x45\xf4\x58\xf4\x54\xb4\x21\x7a\x2e\xda\x15\xed\x8b\x59\x62\xae\x58\x20\x96\x89\xd5\x62\xbd\xd8\x2c\xb6\x89\x5d\xe2\x4c\xb1\x47\x5c\x28\x2e\x11\x9f\x11\x97\x8b\xcf\x89\x6b\xc4\xf5\xe2\x26\x71\xab\xf8\xbc\xf8\xa2\xb8\x4b\x7c\x55\xdc\x23\xee\x13\x0f\x88\x87\xc5\xa3\xe2\x71\xf1\xa4\xf8\x8e\x78\x46\x3c\x27\x5e\x14\x3f\x14\x3f\x12\x3f\x11\xaf\x8b\x37\xc5\xdb\xe2\x17\x12\x90\xd0\x12\x9e\x44\x24\x51\x48\xb4\x12\x83\xc4\x22\x71\x48\xd2\x24\x6e\x89\x57\x52\x24\x29\x95\x9c\x95\x54\x48\xaa\x24\xb5\x92\x06\x49\xb3\xa4\x4d\x72\x41\xd2\x29\xb9\x2c\xe9\x96\x5c\x97\xf4\x4b\x06\x25\x23\x92\x5b\x92\x09\xc9\x94\xe4\xae\x64\x56\x32\x2f\x79\x20\x59\x96\xac\x4a\xd6\x24\xcf\x24\x5b\x92\x1d\xc9\x9e\x94\x94\x72\xa4\x7c\xa9\x44\xaa\x92\xea\xa4\x26\xa9\x55\xea\x94\xa6\x4b\x73\xa4\x05\xd2\x62\xe9\x69\x69\x99\xb4\x52\x5a\x2d\xad\x93\x36\x4a\x5b\xa4\xed\xd2\x0e\xe9\x25\xe9\x15\xe9\x35\x69\xaf\xf4\x86\x74\x48\x7a\x53\x3a\x26\xbd\x2d\x9d\x96\xde\x93\xde\x97\x2e\x48\x97\xa4\x2b\xd2\xc7\xd2\xa7\xd2\x0d\xe9\x73\xe9\xae\x74\x5f\xc6\x92\x71\x65\x02\x99\x4c\xa6\x96\xe9\x65\x66\x99\x4d\xe6\x92\x65\xca\x3c\xb2\x42\x59\x89\xec\x8c\xac\x5c\x76\x4e\x56\x23\xab\x97\x35\xc9\x5a\x65\xe7\x65\x17\x65\x5d\xb2\xab\xb2\x1e\x59\x9f\x6c\x40\x36\x2c\x1b\x95\x8d\xcb\x26\x65\x77\x64\x33\xb2\x39\xd9\xa2\xec\xa1\xec\x91\xec\x89\x6c\x5d\xb6\x29\xdb\x96\xbd\x90\x83\x9c\x96\xf3\xe4\x22\xb9\x42\xae\x95\x1b\xe4\x16\xb9\x43\x9e\x26\x77\xcb\xbd\xf2\x22\x79\xa9\xfc\xac\xbc\x42\x5e\x25\xaf\x95\x37\xc8\x9b\xe5\x6d\xf2\x0b\xf2\x4e\xf9\x65\x79\xb7\xfc\xba\xbc\x5f\x3e\x28\x1f\x91\xdf\x92\x4f\xc8\xa7\xe4\x77\xe5\xb3\xf2\x79\xf9\x03\xf9\xb2\x7c\x55\xbe\x26\x7f\x26\xdf\x92\xef\xc8\xf7\x14\xa4\x82\xa3\xe0\x2b\x24\x0a\x95\x42\xa7\x30\x29\xac\x0a\xa7\x22\x5d\x91\xa3\x28\x50\x14\x2b\x4e\x2b\xca\x14\x95\x8a\x6a\x45\x9d\xa2\x51\xd1\xa2\x68\x57\x74\x28\x2e\x29\xae\x28\xae\x29\x7a\x15\x37\x14\x43\x8a\x9b\x8a\x31\xc5\x6d\xc5\xb4\xe2\x9e\xe2\xbe\x62\x41\xb1\xa4\x58\x51\x3c\x56\x3c\x55\x6c\x28\x9e\x2b\x76\x15\xfb\x4a\x96\x92\xab\x14\x28\x65\x4a\xb5\x52\xaf\x34\x2b\x6d\x4a\x97\x32\x53\xe9\x51\x16\x2a\x4b\x94\x67\x94\xe5\xca\x73\xca\x1a\x65\xbd\xb2\x49\xd9\xaa\x3c\xaf\xbc\xa8\xec\x52\x5e\x55\xf6\x28\xfb\x94\x03\xca\x61\xe5\xa8\x72\x5c\x39\xa9\xbc\xa3\x9c\x51\xce\x29\x17\x95\x0f\x95\x8f\x94\x4f\x94\xeb\xca\x4d\xe5\xb6\xf2\x85\x0a\x54\xb4\x8a\xa7\x12\xa9\x14\x2a\xad\xca\xa0\xb2\xa8\x1c\xaa\x34\x95\x5b\xe5\x55\x15\xa9\x4a\x55\x67\x55\x15\xaa\x2a\x55\xad\xaa\x41\xd5\xac\x6a\x53\x5d\x50\x75\xaa\x2e\xab\xba\x55\xd7\x55\xfd\xaa\x41\xd5\x88\xea\x96\x6a\x42\x35\xa5\xba\xab\x9a\x55\xcd\xab\x1e\xa8\x96\x55\xab\xaa\x35\xd5\x33\xd5\x96\x6a\x47\xb5\x17\x4d\x46\x73\xa2\xf9\xd1\x92\x68\x55\xb4\x2e\xda\x14\x6d\x8d\x76\x46\xa7\x47\xe7\x44\x17\x44\x17\x47\x9f\x8e\x2e\x8b\xae\x8c\xae\x8e\xae\x8b\x6e\x8c\x6e\x89\x6e\x8f\xee\x88\xbe\x14\x7d\x25\xfa\x5a\x74\x6f\xf4\x8d\xe8\xa1\xe8\x9b\xd1\x63\xd1\xb7\xa3\xa7\xa3\xef\x45\xdf\x8f\x5e\x88\x5e\x8a\x5e\x89\x7e\x1c\xfd\x34\x7a\x23\xfa\x79\xf4\x6e\xf4\xbe\x9a\xa5\xe6\xaa\x05\x6a\x99\x5a\xad\xd6\xab\xcd\x6a\x9b\xda\xa5\xce\x54\x7b\xd4\x85\xea\x12\xf5\x19\x75\xb9\xfa\x9c\xba\x46\x5d\xaf\x6e\x52\xb7\xaa\xcf\xab\x2f\xaa\xbb\xd4\x57\xd5\x3d\xea\x3e\xf5\x80\x7a\x58\x3d\xaa\x1e\x57\x4f\xaa\xef\xa8\x67\xd4\x73\xea\x45\xf5\x43\xf5\x23\xf5\x13\xf5\xba\x7a\x53\xbd\xad\x7e\xa1\x01\x0d\xad\xe1\x69\x44\x1a\x85\x46\xab\x31\x68\x2c\x1a\x87\x26\x4d\xe3\xd6\x78\x35\x45\x9a\x52\xcd\x59\x4d\x85\xa6\x4a\x53\xab\x69\xd0\x34\x6b\xda\x34\x17\x34\x9d\x9a\xcb\x9a\x6e\xcd\x75\x4d\xbf\x66\x50\x33\xa2\xb9\xa5\x99\xd0\x4c\x69\xee\x6a\x66\x35\xf3\x9a\x07\x9a\x65\xcd\xaa\x66\x4d\xf3\x4c\xb3\xa5\xd9\xd1\xec\x69\x49\x2d\x47\xcb\xd7\x4a\xb4\x2a\xad\x4e\x6b\xd2\x5a\xb5\x4e\x6d\xba\x36\x47\x5b\xa0\x2d\xd6\x9e\xd6\x96\x69\x2b\xb5\xd5\xda\x3a\x6d\xa3\xb6\x45\xdb\xae\xed\xd0\x5e\xd2\x5e\xd1\x5e\xd3\xf6\x6a\x6f\x68\x87\xb4\x37\xb5\x63\xda\xdb\xda\x69\xed\x3d\xed\x7d\xed\x82\x76\x49\xbb\xa2\x7d\xac\x7d\xaa\xdd\xd0\x3e\xd7\xee\x6a\xf7\x63\x58\x31\xdc\x18\x41\x8c\x2c\x46\x1d\xa3\x8f\x31\xc7\xd8\x62\x5c\x31\x99\x31\x9e\x98\xc2\x98\x92\x98\x33\x31\xe5\x31\xe7\x62\x6a\x62\xea\x63\x9a\x62\x5a\x63\xce\xc7\x5c\x8c\xe9\x8a\xb9\x1a\xd3\x13\xd3\x17\x33\x10\x33\x1c\x33\x1a\x33\x1e\x33\x19\x73\x27\x66\x26\x66\x2e\x66\x31\xe6\x61\xcc\xa3\x98\x27\x31\xeb\x31\x9b\x31\xdb\x31\x2f\x74\xa0\xa3\x75\x3c\x9d\x48\xa7\xd0\x69\x75\x06\x9d\x45\xe7\xd0\xa5\xe9\xdc\x3a\xaf\xae\x48\x57\xaa\x3b\xab\xab\xd0\x55\xe9\x6a\x75\x0d\xba\x66\x5d\x9b\xee\x82\xae\x53\x77\x59\xd7\xad\xbb\xae\xeb\xd7\x0d\xea\x46\x74\xb7\x74\x13\xba\x29\xdd\x5d\xdd\xac\x6e\x5e\xf7\x40\xb7\xac\x5b\xd5\xad\xe9\x9e\xe9\xb6\x74\x3b\xba\xbd\x58\x32\x96\x13\xcb\x8f\x95\xc4\xaa\x62\x75\xb1\xa6\x58\x6b\xac\x33\x36\x3d\x36\x27\xb6\x20\xb6\x38\xf6\x74\x6c\x59\x6c\x65\x6c\x75\x6c\x5d\x6c\x63\x6c\x4b\x6c\x7b\x6c\x47\xec\xa5\xd8\x2b\xb1\xd7\x62\x7b\x63\x6f\xc4\x0e\xc5\xde\x8c\x1d\x8b\xbd\x1d\x3b\x1d\x7b\x2f\xf6\x7e\xec\x42\xec\x52\xec\x4a\xec\xe3\xd8\xa7\xb1\x1b\xb1\xcf\x63\x77\x63\xf7\xf5\x2c\x3d\x57\x2f\xd0\xcb\xf4\x6a\xbd\x5e\x6f\xd6\xdb\xf4\x2e\x7d\xa6\xde\xa3\x2f\xd4\x97\xe8\xcf\xe8\xcb\xf5\xe7\xf4\x35\xfa\x7a\x7d\x93\xbe\x55\x7f\x5e\x7f\x51\xdf\xa5\xbf\xaa\xef\xd1\xf7\xe9\x07\xf4\xc3\xfa\x51\xfd\xb8\x7e\x52\x7f\x47\x3f\xa3\x9f\xd3\x2f\xea\x1f\xea\x1f\xe9\x9f\xe8\xd7\xf5\x9b\xfa\x6d\xfd\x8b\x38\x88\xa3\xe3\x78\x71\xa2\x38\x45\x9c\x36\xce\x10\x67\x89\x73\xc4\xa5\xc5\xb9\xe3\xbc\x71\x45\x71\xa5\x71\x67\xe3\x2a\xe2\xaa\xe2\x6a\xe3\x1a\xe2\x9a\xe3\xda\xe2\x2e\xc4\x75\xc6\x5d\x8e\xeb\x8e\xbb\x1e\xd7\x1f\x37\x18\x37\x12\x77\x2b\x6e\x22\x6e\x2a\xee\x6e\xdc\x6c\xdc\x7c\xdc\x83\xb8\xe5\xb8\xd5\xb8\xb5\xb8\x67\x71\x5b\x71\x3b\x71\x7b\x06\xd2\xc0\x31\xf0\x0d\x12\x83\xca\xa0\x33\x98\x0c\x56\x83\xd3\x90\x6e\xc8\x31\x14\x18\x8a\x0d\xa7\x0d\x65\x86\x4a\x43\xb5\xa1\xce\xd0\x68\x68\x31\xb4\x1b\x3a\x0c\x97\x0c\x57\x0c\xd7\x0c\xbd\x86\x1b\x86\x21\xc3\x4d\xc3\x98\xe1\xb6\x61\xda\x70\xcf\x70\xdf\xb0\x60\x58\x32\xac\x18\x1e\x1b\x9e\x1a\x36\x0c\xcf\x0d\xbb\x86\x7d\x23\xcb\xc8\x35\x0a\x8c\x32\xa3\xda\xa8\x37\x9a\x8d\x36\xa3\xcb\x98\x69\xf4\x18\x0b\x8d\x25\xc6\x33\xc6\x72\xe3\x39\x63\x8d\xb1\xde\xd8\x64\x6c\x35\x9e\x37\x5e\x34\x76\x19\xaf\x1a\x7b\x8c\x7d\xc6\x01\xe3\xb0\x71\xd4\x38\x6e\x9c\x34\xde\x31\xce\x18\xe7\x8c\x8b\xc6\x87\xc6\x47\xc6\x27\xc6\x75\xe3\xa6\x71\xdb\xf8\xc2\x04\x26\xda\xc4\x33\x89\x4c\x0a\x93\xd6\x64\x30\x59\x4c\x0e\x53\x9a\xc9\x6d\xf2\x9a\x8a\x4c\xa5\xa6\xb3\xa6\x0a\x53\x95\xa9\xd6\xd4\x60\x6a\x36\xb5\x99\x2e\x98\x3a\x4d\x97\x4d\xdd\xa6\xeb\xa6\x7e\xd3\xa0\x69\xc4\x74\xcb\x34\x61\x9a\x32\xdd\x35\xcd\x9a\xe6\x4d\x0f\x4c\xcb\xa6\x55\xd3\x9a\xe9\x99\x69\xcb\xb4\x63\xda\x8b\x27\xe3\x39\xf1\xfc\x78\x49\xbc\x2a\x5e\x17\x6f\x8a\xb7\xc6\x3b\xe3\xd3\xe3\x73\xe2\x0b\xe2\x8b\xe3\x4f\xc7\x97\xc5\x57\xc6\x57\xc7\xd7\xc5\x37\xc6\xb7\xc4\xb7\xc7\x77\xc4\x5f\x8a\xbf\x12\x7f\x2d\xbe\x37\xfe\x46\xfc\x50\xfc\xcd\xf8\xb1\xf8\xdb\xf1\xd3\xf1\xf7\xe2\xef\xc7\x2f\xc4\x2f\xc5\xaf\xc4\x3f\x8e\x7f\x1a\xbf\x11\xff\x3c\x7e\x37\x7e\xdf\xcc\x32\x73\xcd\x02\xb3\xcc\xac\x36\xeb\xcd\x66\xb3\xcd\xec\x32\x67\x9a\x3d\xe6\x42\x73\x89\xf9\x8c\xb9\xdc\x7c\xce\x5c\x63\xae\x37\x37\x99\x5b\xcd\xe7\xcd\x17\xcd\x5d\xe6\xab\xe6\x1e\x73\x9f\x79\xc0\x3c\x6c\x1e\x35\x8f\x9b\x27\xcd\x77\xcc\x33\xe6\x39\xf3\xa2\xf9\xa1\xf9\x91\xf9\x89\x79\xdd\xbc\x69\xde\x36\xbf\x48\x80\x04\x3a\x81\x97\x20\x4a\x50\x24\x68\x13\x0c\x09\x96\x04\x47\x42\x5a\x82\x3b\xc1\x9b\x50\x94\x50\x9a\x70\x36\xa1\x22\xa1\x2a\xa1\x36\xa1\x21\xa1\x39\xa1\x2d\xe1\x42\x42\x67\xc2\xe5\x84\xee\x84\xeb\x09\xfd\x09\x83\x09\x23\x09\xb7\x12\x26\x12\xa6\x12\xee\x26\xcc\x26\xcc\x27\x3c\x48\x58\x4e\x58\x4d\x58\x4b\x78\x96\xb0\x95\xb0\x93\xb0\x67\x21\x2d\x1c\x0b\xdf\x22\xb1\xa8\x2c\x3a\x8b\xc9\x62\xb5\x38\x2d\xe9\x96\x1c\x4b\x81\xa5\xd8\x72\xda\x52\x66\xa9\xb4\x54\x5b\xea\x2c\x8d\x96\x16\x4b\xbb\xa5\xc3\x72\xc9\x72\xc5\x72\xcd\xd2\x6b\xb9\x61\x19\xb2\xdc\xb4\x8c\x59\x6e\x5b\xa6\x2d\xf7\x2c\xf7\x2d\x0b\x96\x25\xcb\x8a\xe5\xb1\xe5\xa9\x65\xc3\xf2\xdc\xb2\x6b\xd9\x4f\x64\x25\x72\x13\x05\x89\xb2\x44\x75\xa2\x3e\xd1\x9c\x68\x4b\x74\x25\x66\x26\x7a\x12\x0b\x13\x4b\x12\xcf\x24\x96\x27\x9e\x4b\xac\x49\xac\x4f\x6c\x4a\x6c\x4d\x3c\x9f\x78\x31\xb1\x2b\xf1\x6a\x62\x4f\x62\x5f\xe2\x40\xe2\x70\xe2\x68\xe2\x78\xe2\x64\xe2\x9d\xc4\x99\xc4\xb9\xc4\xc5\xc4\x87\x89\x8f\x12\x9f\x24\xae\x27\x6e\x26\x6e\x27\xbe\xb0\x82\x95\xb6\xf2\xac\x22\xab\xc2\xaa\xb5\x1a\xac\x16\xab\xc3\x9a\x66\x75\x5b\xbd\xd6\x22\x6b\xa9\xf5\xac\xb5\xc2\x5a\x65\xad\xb5\x36\x58\x9b\xad\x6d\xd6\x0b\xd6\x4e\xeb\x65\x6b\xb7\xf5\xba\xb5\xdf\x3a\x68\x1d\xb1\xde\xb2\x4e\x58\xa7\xac\x77\xad\xb3\xd6\x79\xeb\x03\xeb\xb2\x75\xd5\xba\x66\x7d\x66\xdd\xb2\xee\x58\xf7\x92\xc8\x24\x4e\x12\x3f\x49\x92\xa4\x4a\xd2\x25\x99\x92\xac\x49\xce\xa4\xf4\xa4\x9c\xa4\x82\xa4\xe2\xa4\xd3\x49\x65\x49\x95\x49\xd5\x49\x75\x49\x8d\x49\x2d\x49\xed\x49\x1d\x49\x97\x92\xae\x24\x5d\x4b\xea\x4d\xba\x91\x34\x94\x74\x33\x69\x2c\xe9\x76\xd2\x74\xd2\xbd\xa4\xfb\x49\x0b\x49\x4b\x49\x2b\x49\x8f\x93\x9e\x26\x6d\x24\x3d\x4f\xda\x4d\xda\xb7\xb1\x6c\x5c\x9b\xc0\x26\xb3\xa9\x6d\x7a\x9b\xd9\x66\xb3\xb9\x6c\x99\x36\x8f\xad\xd0\x56\x62\x3b\x63\x2b\xb7\x9d\xb3\xd5\xd8\xea\x6d\x4d\xb6\x56\xdb\x79\xdb\x45\x5b\x97\xed\xaa\xad\xc7\xd6\x67\x1b\xb0\x0d\xdb\x46\x6d\xe3\xb6\x49\xdb\x1d\xdb\x8c\x6d\xce\xb6\x68\x7b\x68\x7b\x64\x7b\x62\x5b\xb7\x6d\xda\xb6\x6d\x2f\xec\x60\xa7\xed\x3c\xbb\xc8\xae\xb0\x6b\xed\x06\xbb\xc5\xee\xb0\xa7\xd9\xdd\x76\xaf\xbd\xc8\x5e\x6a\x3f\x6b\xaf\xb0\x57\xd9\x6b\xed\x0d\xf6\x66\x7b\x9b\xfd\x82\xbd\xd3\x7e\xd9\xde\x6d\xbf\x6e\xef\xb7\x0f\xda\x47\xec\xb7\xec\x13\xf6\x29\xfb\x5d\xfb\xac\x7d\xde\xfe\xc0\xbe\x6c\x5f\xb5\xaf\xd9\x9f\xd9\xb7\xec\x3b\xf6\x3d\x07\xe9\xe0\x38\xf8\x0e\x89\x43\xe5\xd0\x39\x4c\x0e\xab\xc3\xe9\x48\x77\xe4\x38\x0a\x1c\xc5\x8e\xd3\x8e\x32\x47\xa5\xa3\xda\x51\xe7\x68\x74\xb4\x38\xda\x1d\x1d\x8e\x4b\x8e\x2b\x8e\x6b\x8e\x5e\xc7\x0d\xc7\x90\xe3\xa6\x63\xcc\x71\xdb\x31\xed\xb8\xe7\xb8\xef\x58\x70\x2c\x39\x56\x1c\x8f\x1d\x4f\x1d\x1b\x8e\xe7\x8e\x5d\xc7\x7e\x32\x2b\x99\x9b\x2c\x48\x96\x25\xab\x93\xf5\xc9\xe6\x64\x5b\xb2\x2b\x39\x33\xd9\x93\x5c\x98\x5c\x92\x7c\x26\xb9\x3c\xf9\x5c\x72\x4d\x72\x7d\x72\x53\x72\x6b\xf2\xf9\xe4\x8b\xc9\x5d\xc9\x57\x93\x7b\x92\xfb\x92\x07\x92\x87\x93\x47\x93\xc7\x93\x27\x93\xef\x24\xcf\x24\xcf\x25\x2f\x26\x3f\x4c\x7e\x94\xfc\x24\x79\x3d\x79\x33\x79\x3b\xf9\x85\x13\x9c\xb4\x93\xe7\x14\x39\x15\x4e\xad\xd3\xe0\xb4\x38\x1d\xce\x34\xa7\xdb\xe9\x75\x16\x39\x4b\x9d\x67\x9d\x15\xce\x2a\x67\xad\xb3\xc1\xd9\xec\x6c\x73\x5e\x70\x76\x3a\x2f\x3b\xbb\x9d\xd7\x9d\xfd\xce\x41\xe7\x88\xf3\x96\x73\xc2\x39\xe5\xbc\xeb\x9c\x75\xce\x3b\x1f\x38\x97\x9d\xab\xce\x35\xe7\x33\xe7\x96\x73\xc7\xb9\x97\x42\xa6\x70\x52\xf8\x29\x92\x14\x55\x8a\x2e\xc5\x94\x62\x4d\x71\xa6\xa4\xa7\xe4\xa4\x14\xa4\x14\xa7\x9c\x4e\x29\x4b\xa9\x4c\xa9\x4e\xa9\x4b\x69\x4c\x69\x49\x69\x4f\xe9\x48\xb9\x94\x72\x25\xe5\x5a\x4a\x6f\xca\x8d\x94\xa1\x94\x9b\x29\x63\x29\xb7\x53\xa6\x53\xee\xa5\xdc\x4f\x59\x48\x59\x4a\x59\x49\x79\x9c\xf2\x34\x65\x23\xe5\x79\xca\x6e\xca\xbe\x8b\xe5\xe2\xba\x04\x2e\x99\x4b\xed\xd2\xbb\xcc\x2e\x9b\xcb\xe5\xca\x74\x79\x5c\x85\xae\x12\xd7\x19\x57\xb9\xeb\x9c\xab\xc6\x55\xef\x6a\x72\xb5\xba\xce\xbb\x2e\xba\xba\x5c\x57\x5d\x3d\xae\x3e\xd7\x80\x6b\xd8\x35\xea\x1a\x77\x4d\xba\xee\xb8\x66\x5c\x73\xae\x45\xd7\x43\xd7\x23\xd7\x13\xd7\xba\x6b\xd3\xb5\xed\x7a\x91\x0a\xa9\x74\x2a\x2f\x55\x94\xaa\x48\xd5\xa6\x1a\x52\x2d\xa9\x8e\xd4\xb4\x54\x77\xaa\x37\xb5\x28\xb5\x34\xf5\x6c\x6a\x45\x6a\x55\x6a\x6d\x6a\x43\x6a\x73\x6a\x5b\xea\x85\xd4\xce\xd4\xcb\xa9\xdd\xa9\xd7\x53\xfb\x53\x07\x53\x47\x52\x6f\xa5\x4e\xa4\x4e\xa5\xde\x4d\x9d\x4d\x9d\x4f\x7d\x90\xba\x9c\xba\x9a\xba\x96\xfa\x2c\x75\x2b\x75\x27\x75\x2f\x8d\x4c\xe3\xa4\xf1\xd3\x24\x69\xaa\x34\x5d\x9a\x29\xcd\x9a\xe6\x4c\x4b\x4f\xcb\x49\x2b\x48\x2b\x4e\x3b\x9d\x56\x96\x56\x99\x56\x9d\x56\x97\xd6\x98\xd6\x92\xd6\x9e\xd6\x91\x76\x29\xed\x4a\xda\xb5\xb4\xde\xb4\x1b\x69\x43\x69\x37\xd3\xc6\xd2\x6e\xa7\x4d\xa7\xdd\x4b\xbb\x9f\xb6\x90\xb6\x94\xb6\x92\xf6\x38\xed\x69\xda\x46\xda\xf3\xb4\xdd\xb4\xfd\x53\xac\x53\xdc\x53\x82\x53\xb2\x53\xea\x53\xfa\x53\xe6\x53\xb6\x53\xae\x53\x99\xa7\x3c\xa7\x0a\x4f\x95\x9c\x3a\x73\xaa\xfc\xd4\xb9\x53\x35\xa7\xea\x4f\x35\x9d\x6a\x3d\x75\xfe\xd4\xc5\x53\x5d\xa7\xae\x9e\xea\x39\xd5\x77\x6a\xe0\xd4\xf0\xa9\xd1\x53\xe3\xa7\x26\x4f\xdd\x39\x35\x73\x6a\xee\xd4\xe2\xa9\x87\xa7\x1e\x9d\x7a\x72\x6a\xfd\xd4\xe6\xa9\xed\x53\x2f\xd2\x21\x9d\x4e\xe7\xa5\x8b\xd2\x15\xe9\xda\x74\x43\xba\x25\xdd\x91\x9e\x96\xee\x4e\xf7\xa6\x17\xa5\x97\xa6\x9f\x4d\xaf\x48\xaf\x4a\xaf\x4d\x6f\x48\x6f\x4e\x6f\x4b\xbf\x90\xde\x99\x7e\x39\xbd\x3b\xfd\x7a\x7a\x7f\xfa\x60\xfa\x48\xfa\xad\xf4\x89\xf4\xa9\xf4\xbb\xe9\xb3\xe9\xf3\xe9\x0f\xd2\x97\xd3\x57\xd3\xd7\xd2\x9f\xa5\x6f\xa5\xef\xa4\xef\x65\x90\x19\x9c\x0c\x7e\x86\x24\x43\x95\xa1\xcb\x30\x65\x58\x33\x9c\x19\xe9\x19\x39\x19\x05\x19\xc5\x19\xa7\x33\xca\x32\x2a\x33\xaa\x33\xea\x32\x1a\x33\x5a\x32\xda\x33\x3a\x32\x2e\x65\x5c\xc9\xb8\x96\xd1\x9b\x71\x23\x63\x28\xe3\x66\xc6\x58\xc6\xed\x8c\xe9\x8c\x7b\x19\xf7\x33\x16\x32\x96\x32\x56\x32\x1e\x67\x3c\xcd\xd8\xc8\x78\x9e\xb1\x9b\xb1\x9f\xc9\xca\xe4\x66\x0a\x32\x65\x99\xea\x4c\x7d\xa6\x39\xd3\x96\xe9\xca\xcc\xcc\xf4\x64\x16\x66\x96\x64\x9e\xc9\x2c\xcf\x3c\x97\x59\x93\x59\x9f\xd9\x94\xd9\x9a\x79\x3e\xf3\x62\x66\x57\xe6\xd5\xcc\x9e\xcc\xbe\xcc\x81\xcc\xe1\xcc\xd1\xcc\xf1\xcc\xc9\xcc\x3b\x99\x33\x99\x73\x99\x8b\x99\x0f\x33\x1f\x65\x3e\xc9\x5c\xcf\xdc\xcc\xdc\xce\x7c\x91\x05\x59\x74\x16\x2f\x4b\x94\xa5\xc8\xd2\x66\x19\xb2\x2c\x59\x8e\xac\xb4\x2c\x77\x96\x37\xab\x28\xab\x34\xeb\x6c\x56\x45\x56\x55\x56\x6d\x56\x43\x56\x73\x56\x5b\xd6\x85\xac\xce\xac\xcb\x59\xdd\x59\xd7\xb3\xfa\xb3\x06\xb3\x46\xb2\x6e\x65\x4d\x64\x4d\x65\xdd\xcd\x9a\xcd\x9a\xcf\x7a\x90\xb5\x9c\xb5\x9a\xb5\x96\xf5\x2c\x6b\x2b\x6b\x27\x6b\xcf\x4d\xba\x39\x6e\xbe\x5b\xe2\x56\xb9\x75\x6e\x93\xdb\xea\x76\xba\xd3\xdd\x39\xee\x02\x77\xb1\xfb\xb4\xbb\xcc\x5d\xe9\xae\x76\xd7\xb9\x1b\xdd\x2d\xee\x76\x77\x87\xfb\x92\xfb\x8a\xfb\x9a\xbb\xd7\x7d\xc3\x3d\xe4\xbe\xe9\x1e\x73\xdf\x76\x4f\xbb\xef\xb9\xef\xbb\x17\xdc\x4b\xee\x15\xf7\x63\xf7\x53\xf7\x86\xfb\xb9\x7b\xd7\xbd\x9f\xcd\xca\xe6\x66\x0b\xb2\x65\xd9\xea\x6c\x7d\xb6\x39\xdb\x96\xed\xca\xce\xcc\xf6\x64\x17\x66\x97\x64\x9f\xc9\x2e\xcf\x3e\x97\x5d\x93\x5d\x9f\xdd\x94\xdd\x9a\x7d\x3e\xfb\x62\x76\x57\xf6\xd5\xec\x9e\xec\xbe\xec\x81\xec\xe1\xec\xd1\xec\xf1\xec\xc9\xec\x3b\xd9\x33\xd9\x73\xd9\x8b\xd9\x0f\xb3\x1f\x65\x3f\xc9\x5e\xcf\xde\xcc\xde\xce\x7e\x91\x03\x39\x74\x0e\x2f\x47\x94\xa3\xc8\xd1\xe6\x18\x72\x2c\x39\x8e\x9c\xb4\x1c\x77\x8e\x37\xa7\x28\xa7\x34\xe7\x6c\x4e\x45\x4e\x55\x4e\x6d\x4e\x43\x4e\x73\x4e\x5b\xce\x85\x9c\xce\x9c\xcb\x39\xdd\x39\xd7\x73\xfa\x73\x06\x73\x46\x72\x6e\xe5\x4c\xe4\x4c\xe5\xdc\xcd\x99\xcd\x99\xcf\x79\x90\xb3\x9c\xb3\x9a\xb3\x96\xf3\x2c\x67\x2b\x67\x27\x67\x2f\x97\xcc\xe5\xe4\xf2\x73\x25\xb9\xaa\x5c\x5d\xae\x29\xd7\x9a\xeb\xcc\x4d\xcf\xcd\xc9\x2d\xc8\x2d\xce\x3d\x9d\x5b\x96\x5b\x99\x5b\x9d\x5b\x97\xdb\x98\xdb\x92\xdb\x9e\xdb\x91\x7b\x29\xf7\x4a\xee\xb5\xdc\xde\xdc\x1b\xb9\x43\xb9\x37\x73\xc7\x72\x6f\xe7\x4e\xe7\xde\xcb\xbd\x9f\xbb\x90\xbb\x94\xbb\x92\xfb\x38\xf7\x69\xee\x46\xee\xf3\xdc\xdd\xdc\x7d\x0f\xcb\xc3\xf5\x08\x3c\x32\x8f\xda\xa3\xf7\x98\x3d\x36\x8f\xcb\x93\xe9\xf1\x78\x0a\x3d\x25\x9e\x33\x9e\x72\xcf\x39\x4f\x8d\xa7\xde\xd3\xe4\x69\xf5\x9c\xf7\x5c\xf4\x74\x79\xae\x7a\x7a\x3c\x7d\x9e\x01\xcf\xb0\x67\xd4\x33\xee\x99\xf4\xdc\xf1\xcc\x78\xe6\x3c\x8b\x9e\x87\x9e\x47\x9e\x27\x9e\x75\xcf\xa6\x67\xdb\xf3\x22\x0f\xf2\xe8\x3c\x5e\x9e\x28\x4f\x91\xa7\xcd\x33\xe4\x59\xf2\x1c\x79\x69\x79\xee\x3c\x6f\x5e\x51\x5e\x69\xde\xd9\xbc\x8a\xbc\xaa\xbc\xda\xbc\x86\xbc\xe6\xbc\xb6\xbc\x0b\x79\x9d\x79\x97\xf3\xba\xf3\xae\xe7\xf5\xe7\x0d\xe6\x8d\xe4\xdd\xca\x9b\xc8\x9b\xca\xbb\x9b\x37\x9b\x37\x9f\xf7\x20\x6f\x39\x6f\x35\x6f\x2d\xef\x59\xde\x56\xde\x4e\xde\x9e\x97\xf4\x72\xbc\x7c\xaf\xc4\xab\xf2\xea\xbc\x26\xaf\xd5\xeb\xf4\xa6\x7b\x73\xbc\x05\xde\x62\xef\x69\x6f\x99\xb7\xd2\x5b\xed\xad\xf3\x36\x7a\x5b\xbc\xed\xde\x0e\xef\x25\xef\x15\xef\x35\x6f\xaf\xf7\x86\x77\xc8\x7b\xd3\x3b\xe6\xbd\xed\x9d\xf6\xde\xf3\xde\xf7\x2e\x78\x97\xbc\x2b\xde\xc7\xde\xa7\xde\x0d\xef\x73\xef\xae\x77\x3f\x9f\x95\xcf\xcd\x17\xe4\xcb\xf2\xd5\xf9\xfa\x7c\x73\xbe\x2d\xdf\x95\x9f\x99\xef\xc9\x2f\xcc\x2f\xc9\x3f\x93\x5f\x9e\x7f\x2e\xbf\x26\xbf\x3e\xbf\x29\xbf\x35\xff\x7c\xfe\xc5\xfc\xae\xfc\xab\xf9\x3d\xf9\x7d\xf9\x03\xf9\xc3\xf9\xa3\xf9\xe3\xf9\x93\xf9\x77\xf2\x67\xf2\xe7\xf2\x17\xf3\x1f\xe6\x3f\xca\x7f\x92\xbf\x9e\xbf\x99\xbf\x9d\xff\xa2\x00\x0a\xe8\x02\x5e\x81\xa8\x40\x51\xa0\x2d\x30\x14\x58\x0a\x1c\x05\x69\x05\xee\x02\x6f\x41\x51\x41\x69\xc1\xd9\x82\x8a\x82\xaa\x82\xda\x82\x86\x82\xe6\x82\xb6\x82\x0b\x05\x9d\x05\x97\x0b\xba\x0b\xae\x17\xf4\x03\x41\xa2\x4f\x24\x50\xeb\xa8\xdf\x74\x15\xfd\xb5\x66\xf4\x79\x2f\x16\xfa\x44\x85\xff\xef\x37\xff\x3b\x42\x10\xce\xfc\x5d\x6a\x92\x79\x9f\x87\xde\xbc\xfa\xff\xe6\x7a\x35\x36\x4e\xf9\xd1\x08\x75\x16\x75\xac\xd0\xe7\x77\x29\x17\x42\x98\xf7\x4f\xa8\xfb\x46\xfe\x1b\xfa\x1b\xd2\xbf\xc5\xc8\xfb\x28\xf1\x2b\x08\x79\x0d\xf1\xe7\x11\x55\xec\x17\x02\x41\xae\x04\xd6\x43\x8e\xa3\xb9\xf2\xd1\x98\x9d\x08\x29\x40\x23\xcf\xa2\x6e\x17\x7a\x8a\xfa\x36\x42\xf2\xd0\x5c\xe8\xad\x24\xc5\x45\x08\xf3\x09\x03\x37\x42\x74\x68\x9c\x2f\x61\x7b\x6f\x38\x28\x43\x5e\x7e\xa7\xeb\xe5\xe7\x9e\xfd\x32\x3d\xe8\xa9\x22\x6c\xa7\x68\x76\xf2\x93\x98\x4c\x26\x1a\x87\xc6\x76\xfa\xcf\x48\xa6\x0f\xdb\xc5\xa7\x91\xcc\x2a\xea\x48\x66\xa2\xd1\xfe\x0c\xc9\xfc\x21\x92\xa9\xc7\xb4\xfa\x05\x0c\xc1\xe7\x42\x9a\x24\x7f\x01\x21\x9f\x61\x8d\xf9\xb4\xe1\xa3\xa4\x03\x21\x5d\x74\xdd\x2b\xfd\xb4\x22\xe4\xd3\x48\xa6\x12\xc9\xa8\x03\x32\xac\x74\xec\xdc\x5f\xc7\xc6\x61\xe6\xca\x44\xe3\x90\xe8\x2c\xe6\x99\xa7\x7c\x3f\x65\xa5\x23\x99\x8e\x7d\x09\x10\xe4\xb7\x91\xcc\x68\x40\x87\x44\x06\xed\x79\x75\x82\x9c\xc3\x08\x7a\xea\xf3\xe8\xa9\xbb\xe8\x29\x87\x5f\xa6\x3b\xf8\x29\x6a\xd3\x37\x0b\x3d\x84\x56\xf5\x5d\x34\xfb\xb7\xd1\xec\x25\x68\x76\xe6\xaf\xfe\xb7\x23\x44\x85\x21\x5d\x98\x4c\x2b\x9a\xeb\xd0\x9a\x89\x7d\x34\xa6\xce\x47\x89\xc7\x68\xf6\xb7\x11\x52\x84\x90\x87\x08\xf9\x6e\xd8\x7d\x20\xc8\xe9\x80\x4c\xd0\xec\x8c\x56\x3f\x8e\x9e\x5a\x47\x08\xb3\xe6\x37\xd1\x9a\xf9\x08\x37\x22\x99\xd3\x07\x65\x82\x9f\x42\xeb\xd9\x0e\x9c\x0e\xf1\x04\xc9\x7c\x9f\xdd\xf3\xca\xa2\xae\x9e\x00\x69\x38\x06\xe2\x08\x46\x58\xbf\x8d\x7c\xa7\x1b\xd9\xe1\x99\xc3\x11\x00\xe9\xb0\xda\x37\x57\xb0\xbf\x1f\x0b\x69\x08\x46\x88\xdf\xf2\xc9\x04\xf9\x3b\x83\x8c\x1c\x42\xa6\x83\x90\x86\x60\xe4\x70\x44\xa2\xf2\x7c\x32\xc1\xfe\xee\x1b\x07\xf7\xf7\x63\x22\x0d\xef\x8d\x1c\x8c\x24\x14\x8d\xc6\xc1\xfc\xfd\x98\x48\xc3\x81\x28\xf1\x05\x74\xa6\x78\x04\xf0\xc7\x28\xd6\xc6\x2b\x0b\x5f\xf6\x79\x0a\x4b\x15\x36\xf1\x4a\xe6\x33\x3e\xff\xa2\xee\x22\x19\xc7\x09\x10\x05\xb2\xc3\x83\x08\x23\x93\xe9\x47\x86\x7c\xde\x1d\xd6\xf6\x2a\xd2\xfe\x21\xb2\x70\x0f\x63\xb1\x87\x63\x0b\xb2\x96\xd7\xb1\xb9\x98\x48\x72\x3c\x44\x11\x8c\x30\x71\x83\xe4\xf8\x10\x3c\x92\x90\x23\xef\x81\x28\x82\x11\xb2\xdd\x27\xc3\x12\xa0\x91\x2f\x33\xbe\x8c\x10\x46\xab\xad\x98\x8c\x0a\xd3\xf3\xcf\x8a\x28\x0e\x22\x87\x62\xd4\xe1\xd9\x8f\x87\x28\x0e\x20\x1f\x47\x3a\x64\x4e\x90\xcb\xc4\x3a\x14\xd5\xf1\xe8\x77\x58\xe6\xfb\x6c\x0e\x10\x2c\x03\x16\x13\x3e\xe3\x8b\x75\x41\x67\xc1\xc4\x96\x20\x99\x43\xe7\x15\x54\x4b\xec\xbb\xb1\x4c\x84\x64\xf6\x1b\x7d\x91\x04\xd9\x3c\x60\xb5\xc4\xa7\x69\x2b\x10\xd4\x12\x92\x61\x32\x11\x2e\x23\xc3\x64\x46\x31\x3b\xfc\x77\xe4\x29\x80\xe5\xee\x4f\x23\x9e\x91\x29\x7f\xd7\x71\x96\xb0\x35\xef\xa0\x7d\xe1\x95\x0c\xd2\x98\xdf\x07\x3b\x42\x54\x3b\xbf\xc3\x68\x15\x93\xa9\xf6\xe9\x30\x28\xd6\xbd\x8e\xe9\xb0\x34\x44\x3c\x64\x6c\x7e\x29\x48\x26\x10\x21\x1b\xfc\x32\x81\x35\x1f\x51\x59\x21\x3d\xbf\x7e\x48\xcf\x68\x2e\x96\x0a\xc9\x54\x63\xe3\xac\x07\xc6\xa1\xf4\x98\x7e\x8a\xfc\x7b\xb7\xa2\xcc\x88\x64\x7c\xb6\x41\xa5\x61\x32\x95\x7e\x19\xcf\x21\x99\xc0\x59\xd4\x1e\x1a\xa7\x9a\x91\xc1\x6b\x3f\xb4\xe6\x2e\xfa\xec\x2b\x99\x02\x24\x23\xc0\xe2\xe1\xbf\x31\x16\xce\x1e\x01\x82\xda\x43\x1e\xdd\x70\x74\xc5\x78\x44\xbd\x81\xf2\x05\xa5\xc3\xf2\x05\x13\x13\x16\xb1\x98\xf0\x5b\xe8\xed\x7e\x90\x4c\xd8\xd6\x21\x99\x63\x8c\x83\xd7\xab\xbe\x7d\x11\x19\xbe\xbd\xbf\xaa\x6d\xdc\xaf\xb2\x15\x9e\xe3\x32\x50\x66\x3f\x8f\x45\xa4\x27\xc8\xc6\x0c\xfe\x33\x6d\x7c\x75\x5e\x4d\x08\xe1\xa3\xaa\xe0\x35\x94\x07\x17\xfd\x95\x70\xe3\xcb\xb9\xc8\x06\x66\x1c\xe4\xcb\x23\x78\x6d\x8c\xf4\x1c\x54\x59\x31\x08\xb2\x16\x3c\xf2\xe7\xa3\x9d\x62\xf5\x33\x91\xc1\x9e\x46\x19\xb6\xee\xd5\x0a\x83\x6a\x6c\xff\x4e\xeb\x82\x77\x7a\xb8\x0e\x67\x64\xc8\x86\x40\x15\x77\x84\xcc\x9f\xa2\x71\xb6\xdf\x55\x26\x68\x2e\x7f\x7e\xef\x09\xce\xef\xe4\xb7\x91\xd5\x61\x99\x31\xb8\xe6\x47\x2b\x7c\x59\xb3\x21\x19\x1f\x72\xac\x71\x50\x0d\xcc\x1a\x43\xc8\xdb\x47\x8c\xdc\x78\x68\x64\xc9\xcb\xbf\x92\x10\x74\xbf\x68\xf7\xd9\x18\x9e\x0b\x0e\xd7\x1b\x87\x33\xc8\x91\x32\xbe\x15\x56\x61\x32\xcc\xb7\x49\x1f\x33\xb5\x01\x42\x9e\xa1\xbc\xbc\xed\x93\xa1\xee\xa2\xa7\x86\xb0\xfa\x10\xdd\x5c\x88\xbf\x46\x36\xe6\x42\xf6\xc3\xd4\xb4\x41\xb7\x1b\x74\xca\x7f\xed\xaf\x8d\x37\x90\xd5\xb9\x0f\x8c\xc3\x44\x3f\x8a\xb1\x55\x6c\x9c\x22\x2c\xd6\x31\x27\xf8\x36\x92\x41\x31\x8a\xa9\xa8\x43\xca\xf4\x22\x99\x67\x70\xe8\x6e\x85\xbc\xe0\x65\x65\x8e\xc6\x41\x36\x5f\x84\xc5\x3a\x7c\x9c\x41\x24\xb3\x0d\x87\x6e\x64\x68\x9c\x97\xf5\xbc\x4f\x66\x08\x8d\xf3\x49\x6c\x5f\x28\xcb\x10\xdf\xf5\xc5\x28\xff\xde\x1f\x1f\x1e\x07\xe0\xc0\x38\x8f\x8f\xae\xeb\x0e\xe7\x6e\x8a\xf9\x14\x66\x90\x0c\xb2\x8d\x60\x99\x63\x8c\xc3\x21\x91\xcc\x10\x26\x33\xef\x93\x41\x15\x5a\xe8\x71\xac\x07\xc7\xc1\xe2\xea\x3f\x1f\xf2\x94\x56\xe4\x29\xab\xbe\x71\xf0\xfb\x29\xf5\xa6\x6f\x1c\x9a\x8f\x6c\xcc\x78\xa8\x5e\x2d\xf0\xd7\x24\x81\xbc\xc3\xc4\xa8\x2f\xa0\x3b\x48\xd0\x1d\x16\x3d\x85\xdd\x61\x89\x6d\xcc\x5a\x9e\xbc\xab\x4c\xe5\x31\x64\xae\x06\x64\x08\x94\xdf\xc9\x1e\x14\x49\x26\x03\xd9\x0a\xbf\x1d\x33\x7c\x50\xc7\xe3\x2a\x42\x54\x01\x19\xff\x53\xeb\x58\x86\xfd\x7d\x24\xbf\x87\xd5\x09\x5f\x65\x72\x37\xf6\x54\x02\x16\xe7\x39\xfe\x2a\x85\x03\x44\x18\xf3\x6d\xe4\x45\x7f\x95\xe2\x3b\xe5\x65\xac\x22\x3a\x7c\xbb\xe9\x45\xe7\x75\x05\xcb\xdd\xcc\x0a\x05\x98\x57\x32\x59\xd8\x80\x21\x28\x6e\xf8\x57\xc8\x54\x17\x32\xa6\x6a\x42\x88\x08\x8d\xfc\x31\x34\xce\x32\x42\xa6\x91\x4c\x2f\xb6\x2f\x66\x17\x85\x98\x57\xa2\x58\x47\xa2\x6f\xb1\x32\xab\xf2\x57\x05\x67\x7d\xfb\xa2\xeb\xb0\xa8\xc5\x74\x3c\xaa\x02\xbe\x4c\xfd\x2b\x1d\xb8\x69\xa2\x18\x45\xfc\x47\x94\x3d\xd1\x53\xc4\x79\x7f\x86\xb5\x06\x67\x4f\x7f\xff\x67\x86\x0e\xf4\x7f\x7e\x0b\xd3\x33\xd3\x3d\x38\x83\x67\x61\x24\xd3\x1a\x18\x87\xd1\x2a\xa3\x19\x76\x03\x73\xb2\x87\xa3\x3a\xc0\xd1\x51\x9d\x3e\x78\xd7\x63\x90\x3d\x3c\x3e\x63\xf9\x02\xe9\x99\x75\x09\xcd\xd5\xca\xe8\x0d\x3d\x35\xe9\x93\x09\x6b\x43\xbe\xc3\x8c\x83\xaa\x23\xd6\x05\xcc\xea\x98\x13\x64\xa2\x0d\x53\xbd\xe3\xf1\x99\x39\x0b\x17\x42\xd2\xb1\xbd\x33\x11\xf2\x37\xb0\x48\xfb\x9f\x30\xeb\x65\x64\xda\x50\x3e\x45\x9a\x27\xce\x1e\x8a\x87\xdd\x68\xae\x1b\xe8\xa9\x96\x80\x85\x13\xdf\x45\xbe\xc3\xdc\xbb\xbb\x8f\x8e\xab\x4c\x24\xa1\x0d\x78\xb4\x41\x3b\x35\x63\xd1\xc6\x88\x34\xf6\x08\xed\x34\xf6\x90\x6d\x7c\x9a\x89\x24\xb8\xb5\x30\x27\xe8\xbf\x37\x05\x22\xc9\xa1\xde\xd7\xab\xce\x49\x20\x26\xbc\x8e\xd9\xaa\x3a\x80\xf8\xd7\xcc\x78\xae\x13\xc9\x20\xbb\x22\x4d\x08\x89\x46\xe3\xa4\xa2\x71\xe6\x98\xb3\x40\xc8\x9f\x05\xea\x55\x4e\xaa\x2f\xda\x70\xd3\x7c\x67\xc4\x21\x7d\x32\xec\x4d\x9f\xe7\x86\xa3\xbc\xcc\x46\xbe\xc3\x56\xfb\x10\xf6\x0b\x1f\x42\xff\xa5\x0f\x09\x43\xb3\xb0\xff\x05\x69\xa0\x70\xbf\x09\x88\xb0\x3f\xf3\xc9\xd0\x8d\x3e\x99\x30\x37\xd2\xe1\x1f\xa3\x9a\xad\x8c\xb1\x0d\x1f\xc2\x46\xba\x0a\xb7\xa1\x67\xd3\x7d\x4f\xb1\xbf\x87\x46\x2e\x40\x73\xa1\x5b\x36\xfd\x1b\x68\x1c\x40\x73\xb1\xfc\x37\x3b\x5f\x3c\xec\xa2\x0f\xde\xda\xd6\xb1\x3b\x35\xd3\x5d\xf9\x32\x7d\xb0\xca\x2d\x0d\x54\xa7\xfe\x0a\x44\x72\xb0\x4a\xf1\xdf\x4a\x1a\xb0\x2c\x63\x38\x98\xad\xfc\x73\x31\xb6\x8a\xdf\x53\x90\x1d\xb2\x7e\xc5\x17\x25\xfc\x7e\xf1\x1c\x8d\xf3\x87\x3e\x3b\xa4\x23\xd0\xde\x3f\x0f\x81\xbe\x31\xe3\x71\xa9\x81\xb3\x60\xd1\xfe\xdc\x24\x79\x75\x97\x61\x64\x98\x2e\x68\x29\x8a\xa2\x74\xc0\x73\xc9\x15\xa4\x8d\x65\x2c\x6e\xfc\xa9\xaf\xca\xf5\x47\xad\x52\xcc\x97\xfd\x3b\x45\x4f\xb5\x63\x6b\xc6\xeb\xba\x20\x19\x5f\xee\xf6\xdf\x3d\x99\xb9\x7e\x01\xcd\xf5\x1a\x66\x51\xaf\x21\x6d\x6c\x21\xad\xfe\x00\x79\x1c\xa3\x67\xac\x7a\xe7\xa4\xfa\xe4\xb9\xcc\x6f\x64\xd8\x65\x2c\xca\x37\x7b\x78\x06\x66\x51\x26\x1f\xc2\x5e\x43\xa7\xcc\xe4\x8b\xa7\x68\x2e\x26\x02\xbb\x20\x70\x47\xc3\xf4\xc3\x7c\x43\x8f\xbd\x80\x90\x15\x24\x33\x81\xbc\x80\x66\xe2\x3c\xda\x17\x53\x09\x2b\xf1\xe8\x87\xd6\x7c\x0b\xeb\x5d\x30\x16\x45\xa3\x58\x8a\x5b\xd4\x9f\x1d\xea\x15\xd0\x87\xac\xee\x36\x26\x93\x83\x64\x66\x98\x98\x0c\x81\xbb\xf0\x77\xf0\x7b\xae\x5f\x26\x70\x5f\x46\x99\x91\xa9\xeb\x82\xfa\x87\x3d\x28\xda\xe3\xd6\xdb\x73\xf0\x1e\xe7\xcf\xf8\x21\x64\x5e\xd5\xd8\xd6\xe0\x1a\x3b\xc8\xc2\x43\xd4\xea\x2f\x6d\x03\xab\xb1\x17\xd0\xbe\x46\xfc\x35\xb6\x4f\x86\x87\xe6\x9a\x0c\x92\x09\xd4\x09\x14\x26\x83\xd7\x90\x66\x34\x0e\xee\x4d\xcf\x0f\xd5\x87\xe6\x43\x1e\x87\xc9\xf8\x23\xe4\x80\x3f\x3e\xe7\xbc\x8a\xf3\xcc\x5c\xf7\x7c\x88\x3f\xbf\xa3\xef\xac\x92\x7a\xf4\x94\x12\xf5\x8b\x86\x91\xcc\x04\x76\x37\x67\xe6\x7a\x79\x37\x9f\x7e\x15\x57\x91\x37\x51\xe8\x13\xde\xac\x7f\x46\xc8\xbf\xc0\xab\x5e\x8a\x5f\x86\xf1\x53\x21\x96\xa9\xff\x2b\x92\xe9\x44\x32\x6f\x60\x35\x09\xb3\xe6\x2f\x30\x51\xdd\x17\xeb\xfc\x51\xdd\x5f\x0d\xfa\x90\x90\x36\xc6\x9c\x45\x3e\xbc\xea\x93\xf8\xef\xc2\xe5\x4c\x1f\x12\xf3\xe5\x6a\xbf\x2f\xbf\xf7\x99\x7e\x01\xab\xd5\xfd\x35\x2d\xf2\xf7\xa5\x40\x26\x22\xd0\x9b\x11\xc2\x83\x6c\xac\xe1\x9d\xe5\x97\x59\xef\xa5\xfd\xf8\x10\x62\xc1\xa7\x79\x62\x1e\xd1\xf3\x08\x79\xd9\x07\x18\x7b\x19\x01\xa8\x65\xd4\x7d\x7a\x86\xd6\xf3\x63\xa4\xd5\x65\x74\x8f\x43\x51\x9d\xfa\x31\x13\xd5\x91\x0e\xbf\xc6\xec\x1d\xbd\x93\xfa\x77\x1f\x12\xf6\x16\x53\x39\x20\x04\x75\xba\x98\xdc\x4d\x6c\x23\x8d\x1d\xba\x53\x33\x7a\xf6\x47\xec\xcc\x77\xfa\x8f\xba\x5b\x05\xe7\x53\x84\xfc\x13\x1a\x67\x29\x50\x03\x10\xff\x1b\x59\xcb\x0a\x53\x39\xa0\x91\xc7\xb0\x9c\x3b\x7d\xf8\x7e\x81\x65\x7c\x26\x0b\x37\x32\x31\x01\xad\x99\xb1\x9f\x72\xb4\x0b\xd4\x03\xf1\x47\x51\xf5\xff\x43\xde\xbb\xc7\x47\x51\x9d\x7f\xc0\xcf\x99\x73\x76\x76\x37\x09\x24\x9b\x0b\x49\xb8\x24\xbb\xb9\x71\x49\x20\x90\x70\x31\x88\x4a\x11\x01\x45\x11\x10\x31\x28\x20\xf7\x22\x22\x20\xa2\x78\x03\x91\xbb\x68\x2d\x45\x54\x04\xbc\x14\x10\x10\xb5\x9d\x0d\xe1\xe2\x14\x45\x70\xb4\x8a\x76\xac\xa2\x38\x2d\x5e\x47\x21\x8d\x4e\xad\x55\x9c\x5a\x94\x3c\xef\xe7\x9c\x99\xdd\xcc\x6e\x82\xda\xf6\xf7\x79\xdf\x3f\x5e\xf7\xf3\xec\x6c\x0e\x67\x66\x9e\xf3\x3d\xcf\xfd\x9c\x19\x85\x24\x88\xdf\x4e\x55\x84\xe4\x89\x16\x67\x2d\xc9\x41\xde\xc1\x50\xc4\x39\xce\xf3\xc3\xd2\x87\x1e\xdf\xfd\xb5\x27\xa2\xde\xe6\x91\x0d\x57\x4f\xc5\x28\x6a\x3d\xb9\xde\x5d\x1e\x9e\xdd\x79\xf7\xcc\xa9\x13\x81\x5c\xef\x69\xa9\xf5\xf8\xa6\x73\x3c\xb6\x6e\xb5\xbb\xbe\x63\x79\x72\x87\x99\x49\x2d\xe9\xe2\xee\x4e\x65\x69\x9b\x68\xa9\x16\x67\xdd\xee\xe1\xd9\xbb\x42\x37\xd8\xad\xee\x72\x3b\xbf\xd9\xc3\xa1\x23\xe1\xcf\x78\xce\x3a\x4b\x8b\x6f\x9a\xa7\x65\xb6\x27\xc7\x6f\x12\x2d\x1d\x05\x3f\xdf\x79\xac\x96\x68\x61\x8b\x3d\x2d\x07\x3c\x63\x77\xab\x34\xde\xba\x56\x0b\x0e\x3b\x26\xac\xbe\x59\xf1\x96\xfb\xbd\xd5\xcb\x64\x9c\xc9\x29\xa7\x6a\xdd\x8c\xa1\xcb\x61\x62\x7e\xda\xbc\xf2\xe8\xb1\xd8\x89\x2d\xcd\x3e\x37\x71\x2d\x52\xf0\x3c\x46\x5c\x99\x89\x96\xf9\xce\xca\xa9\x68\x19\x2a\x5a\x5e\x10\xda\x2d\xaa\x2b\x64\x99\x68\x39\xd1\xa2\x25\xb1\x1a\xc6\xe5\x30\x45\xcc\x57\x89\xb8\xfb\x4e\xd1\xe2\xac\x60\xbe\x21\x74\x59\xac\x60\x9e\xb5\x65\x7f\x73\x4b\xcb\x1c\xa4\x95\x16\xd3\xd3\xb2\xaa\x39\x07\x71\x65\xcc\xf1\x5f\x8b\xc4\x95\xc5\xec\x38\xb5\x5c\x3a\xba\x45\x0e\x32\x48\xf0\xec\xc4\x48\x27\x05\x62\x8e\x5e\xac\x6f\xd6\x6e\xf2\x96\x27\x83\x5e\xeb\xd1\x9d\xf5\xcd\xb9\x43\x42\xd5\xe8\xe3\xb3\xb4\x6c\x10\x67\xed\x6c\x96\x79\xa7\x85\x88\x9a\x95\x93\x95\xb8\x92\xe9\x89\x18\xdd\x16\x8f\xc6\xb5\x62\xb5\xfe\x20\x38\x74\x72\xc6\xb5\x67\x69\x71\xe6\x7d\x20\x3f\x0b\xde\x77\x65\x83\xf7\x19\xec\xe9\x23\x7c\x25\xf9\x58\x7c\x0f\x84\xe4\x6a\xcf\x9d\x2d\xe6\xc2\xd1\x65\x31\x0a\x36\xcb\x23\x87\xbf\xf3\x64\x2e\xb5\x1e\x09\xef\xdd\x5c\xa1\x72\x56\x8a\xdd\xb9\x70\x6a\x29\x43\x1d\xe9\x95\x59\xd2\x4a\xb1\x53\x1f\x3b\xd1\x32\xdf\x11\xfc\x5c\xe6\x6d\xc1\xb1\x3c\xf2\x14\x2d\xf3\x3c\x7d\x5a\xb4\x90\x2f\xc4\xbd\xc2\x9e\x39\xf5\xb6\x88\xb5\x7e\xb2\xc9\x93\xfd\x8d\x71\xe2\x31\xaf\x8d\x6a\x3d\x3b\x96\x7e\xdd\x62\x06\x97\x37\x73\xe8\xda\x9f\x19\x5c\x2b\x7d\xd9\x1e\xc4\xb6\x7b\xac\xc4\x7d\x70\x96\x3d\x03\x9e\xa8\xe0\x0d\x31\x0a\x51\xf3\xf4\xc6\x51\xae\xfd\xb1\x9a\x6d\xe6\xcf\x19\xa9\xb3\x9a\xe9\xe4\x56\xbe\xfb\x5a\xb6\x88\x6c\x2b\xa1\x85\xe3\x4c\x07\xfb\x6e\x8d\xd9\x55\xfa\x83\x27\xb6\x11\x95\x01\x47\xe6\xe9\xef\x44\x9f\x57\x79\x1f\xa6\x88\x7c\x50\xc4\x5a\xbe\x7a\xd1\x32\x41\xf4\xf9\xaa\xb9\x7a\xe0\xe4\x32\xf4\x51\xd1\xb2\x40\xb4\xf8\xc5\x95\x4b\x9b\xbd\xb0\x14\x14\x2d\x37\x78\x5a\xc6\xb7\xb0\x1b\xab\x5a\xc8\xea\xaa\xe6\xf5\x41\x37\x2a\x98\xdd\xc2\xcb\x08\x79\x26\xbf\x4a\xde\xf5\x11\xdf\x89\x71\x16\x1b\xe5\xf1\x83\x1e\x1b\x95\x68\x01\x9a\xf5\x3d\x56\x83\x6d\xa9\xcb\x2d\x35\xae\xa5\xcc\x7b\x3c\xec\x5b\x1e\x5f\x90\xef\x89\x76\x32\x25\x1e\xff\x0f\x16\x7d\x5e\x69\x96\x55\x36\x41\x3c\xf1\x3b\x5f\x8e\xd7\x64\x5a\xae\xcb\x24\xb4\x9c\x65\x5c\xd2\x16\x8f\x76\x4f\xf1\x58\x80\xc5\x2d\x3c\xbe\x8b\xb3\x88\xc7\x12\x70\x16\x2d\xde\xdd\x35\x03\x9d\x3e\x1e\x2d\x98\xdd\x72\x9f\x8c\x1b\xff\x78\xfd\xce\xbc\xe4\xd9\x69\xda\xd0\xc2\x5f\xcc\x6b\x75\x76\x9a\x12\xec\xf3\xbc\x16\x76\x95\xb7\x7c\x22\x2c\x40\x4f\x71\xaf\x09\x1e\xbf\x1c\x8b\x88\xe6\xc5\xf7\xb7\xb8\xf1\x86\x27\x7a\x1f\xef\x89\xde\x13\xd7\x85\x37\xb4\xe0\x67\x43\x1c\x9f\xef\xe5\xe6\x1a\xa3\x37\x7a\x77\x10\xab\x69\xe6\x50\x1a\x9c\xdc\x42\x3e\x6e\x1a\x96\x74\x56\x2d\xbf\x72\x92\x25\x19\x06\x84\x34\x78\xc6\xbe\x56\xb4\xbc\xe9\x19\xe9\x9d\xe2\x3a\x89\xf1\x46\xf3\xbd\xc6\xbb\xf6\x67\x58\xf2\x0a\xf8\x19\x3b\x79\xa4\xa2\x45\xf1\xac\x32\xdc\xd7\x42\x36\x6e\x69\x8e\x9f\xdd\x3e\x6b\x9a\xd1\x70\xde\xa7\x20\xdd\x22\x5a\x5a\xeb\x33\x26\xa9\x8f\xee\x59\xdd\x3e\xd0\x42\xbb\x5b\xa9\x2d\x7b\x90\x77\xfb\x88\x96\xff\xbc\xcf\xf9\x2d\xfa\x9c\xdf\xa2\x4f\xb2\x16\x08\x69\x49\x5a\xdd\x9e\xd7\x62\x75\xfb\x67\xf7\xf1\xac\x2e\x39\x5a\xd9\x53\xb4\x38\xfa\xf5\x91\xb0\x63\x15\x22\xb3\xf3\xae\x80\x2f\x10\xab\x30\x8e\xc6\x8d\x3e\xcb\xaa\xf4\xd3\xe2\x3a\x9e\x15\xe7\xc4\x55\x69\x47\xe3\xbc\xab\xd2\xbc\x85\x66\x78\xf6\xf6\xc4\xae\x33\x3b\x69\xb7\x61\xe2\x75\x5a\xec\xa6\x73\xf8\xf9\xe9\x7b\x25\xad\x4a\xcf\x6b\x21\xf3\xf3\xe2\xd5\x30\xef\x2e\xca\x3b\x78\x46\xcf\xda\x8b\xda\x88\xe3\xa9\x13\x76\x5a\x8a\x7b\x25\xda\x9f\x0d\x3f\xb3\x4f\xe2\xda\xf1\x86\x16\x56\x6b\x83\x58\xdd\xee\x19\xef\xe3\xea\xa9\xbf\x36\xbe\x13\x2c\xd0\xe2\x3a\xb5\xad\x5f\x27\xa9\x4f\xeb\x16\xf2\x15\x3e\xf6\x84\xdd\xa1\xa2\x72\xeb\x46\xdd\x2f\x88\x96\xd6\xfa\x54\xc4\xe3\x67\x27\x56\x4f\xd8\x65\x2a\x66\xf9\x4b\x4f\x8c\x2d\x6c\xef\x7f\xb1\x4e\xdd\xd2\x62\x6f\xf8\xaf\xfa\xcc\x6b\xd5\xf2\x2f\xf3\xd8\x9f\xd9\x9e\x18\xc9\x9b\x49\xb5\xd6\xa7\x22\xa9\x4f\x8b\xd5\x64\xa9\x8d\x53\x3d\x63\x67\x5b\x4d\xde\x90\xe4\x65\xf2\xc4\x28\x7e\x4e\x9f\xd6\x56\x8a\xf3\x12\xe3\x84\x84\x95\x62\x61\x91\x92\xfc\xd7\x86\xb3\xac\x14\x0f\x8c\x47\xd4\xee\x75\x02\xbd\x45\x9f\x37\x3c\x7d\x4e\xf1\x3e\xbe\xfb\xe2\xab\xc9\xc3\x84\xe6\xb6\xf7\xde\x4b\x8c\xdd\xb9\xd7\xe7\xe2\x5e\xa3\x3c\xda\xed\xae\x14\xfb\x03\xdc\x0e\x8b\x6c\x62\x3f\xb4\x5c\x3d\xd9\x90\x14\xed\xbc\xe1\x5c\xe7\x3f\xee\x33\x2f\xa9\xcf\x7e\x21\xf3\x89\x2b\xbc\xc9\xf2\x23\xfc\x45\x52\x9f\x64\xf9\xb9\xa5\x95\xeb\xb4\xda\x47\xda\xe8\xb1\x2d\xbf\x74\x73\x99\xe6\xb5\x80\x80\xa7\xfe\xe3\xf6\x11\xfc\x78\x72\x7c\x49\xe8\x72\xab\x2b\xce\x03\x13\x57\x9c\x7f\x66\x9f\xd9\x2d\xfa\xe4\xfd\x8c\xeb\xb4\xe8\x23\x7b\x76\x68\x0b\x0e\x63\xfb\x7b\x45\x1f\x31\x8a\xa7\x5b\xec\xd8\x1c\xe9\xd9\x57\xd9\xc9\x63\xf9\x7f\xbc\x4f\x6b\x2b\xe9\x79\x49\x2b\xe9\x8e\x8c\x25\xae\x77\x37\xcb\xb3\xe5\x91\x31\xb7\x8f\x90\x9f\xc4\x78\x6c\xc3\xcf\xec\xd3\xd2\xcb\xdc\xeb\xc8\xb3\x1c\x5f\x49\xa7\x37\xc8\xdb\x38\x1a\xbe\x69\x9e\x1c\x76\x1b\xe7\x99\xb7\xc4\x2a\x66\xf2\xda\xb8\xa7\x2e\x16\x7d\x52\xdc\xbd\x46\xfc\x3a\xba\x68\x49\xdc\x49\xb8\xa1\xd5\x88\xf1\xa5\x40\x9a\xe8\xb3\xcd\x53\x01\xde\xcf\xfb\xf8\x46\xc6\x11\x4b\x8c\x13\x36\xb4\x88\x13\x78\xcb\x14\xcf\x75\x62\x2b\x11\x2d\xae\xe3\xb1\x75\x9e\xd5\x0a\x37\xe6\x77\xd7\xd1\xf8\x75\xa4\x25\xfc\x3a\xf1\x55\x86\xfd\x40\xa4\xde\xfc\x3a\xad\xee\x16\x6b\x19\x8b\x6e\x48\xce\xa0\x05\x87\xb7\x7b\xf2\x0b\xc7\xce\x57\xf2\x7b\xf9\x06\x08\x6c\x63\x55\xeb\xfd\x62\x0f\xf0\xc8\xe6\xf5\xb8\x9f\xa3\xef\xe2\x3a\x89\xbb\x47\xf6\x8b\xdd\x23\x23\xe3\xb1\x68\x6b\x72\x38\x30\x79\x47\x87\xec\x79\x2a\xa1\x15\x5d\x16\x7d\xf8\xbd\xd8\x2c\x71\xaf\xd8\x75\xf6\x0b\xd9\x18\xe9\xd9\x19\xf2\x93\xf7\x72\xab\xcd\x7f\x16\x79\x99\x53\x6d\x9e\xcc\x9a\xf7\xcf\x3b\xb3\xf3\x33\xf6\x8f\xb5\x52\x0f\x6f\xf1\xf4\x47\x92\x6f\x72\xa4\xb7\xd9\x0f\x76\x74\x6a\x44\xcd\xeb\x44\x24\x2f\xb9\x56\xe9\xee\x91\x2e\x17\xc8\x3b\x6b\x64\x7f\x06\x00\x09\x22\x3f\xf9\x06\x96\xbb\x48\x39\xb9\x9b\xdc\x4d\xba\x8b\xf7\xb0\xf4\x10\xef\x61\xb9\x40\xbc\x87\x65\xa0\x78\x0f\x4b\xad\x78\x0f\xcb\x3c\xf1\x1e\x96\x25\xe2\x3d\x2c\x4b\xc5\x7b\x58\xc0\xb7\xdd\xf7\xac\x54\xe9\x53\x7c\xcf\x49\xfd\x7c\x2f\xf8\x0e\x49\xbf\xf0\x69\xbe\xa3\xd2\x45\xbe\x63\xbe\x7f\x4a\x57\xfa\x4e\xcb\xe2\xfd\x32\x72\x27\xe9\x36\xb9\x48\xfe\x85\xf4\x80\x7c\xa1\x3c\x44\xda\x2d\x5f\x23\x4f\x92\xf6\xc9\xd7\xcb\xf3\xa5\xe7\xe5\x55\xf2\x1a\xe9\x65\xf9\x41\x79\xb3\xf4\x9a\xff\x4b\xff\x97\xd2\x5b\x81\xcb\x02\x97\x49\x6f\x07\x26\x06\xa6\x49\x47\x03\x73\x03\x73\xa5\xbf\x06\xe6\x07\xe6\x4b\xc7\x41\x82\x54\xe9\xb0\xf4\x3e\x80\xf4\xa1\x64\x42\x07\xe9\x84\xf4\x37\x08\x4b\x5f\x48\xdf\x42\x89\xf4\x3d\x25\x50\x49\x19\xcd\x80\xbe\x34\x93\xe6\xc3\x85\xb4\x03\xed\x04\xc3\x69\x29\xed\x05\x23\x58\x6f\xd6\x0f\xae\xf1\x3d\xe2\x7b\x12\xae\x85\xd9\x00\xa4\x0e\x80\x5b\x11\xf2\x02\x00\xd1\x00\xc8\x11\x00\xf2\x67\x00\xee\x95\xc9\xfb\x00\x3c\xd3\x27\x7f\x03\x20\x5f\x02\x70\x2f\x4c\x4e\x73\x18\x01\x24\x19\x40\x4a\x03\x90\x32\x01\xa4\x3c\x00\xa9\x00\x40\x2a\x01\x90\xba\x89\x28\x56\x92\xfa\x82\x24\x0d\x00\x49\x1a\x04\x92\x34\x0c\x40\x1a\x01\x92\x34\x06\x24\xe9\x6a\x90\xa4\x49\x20\x49\x33\x40\x92\x66\x83\x24\xcd\x07\x49\xba\x15\x24\x69\x31\x48\xd2\x72\x90\xa4\x35\x20\x49\x6b\x41\x92\x1e\x02\x49\xda\x0c\x92\xb4\x05\x24\x69\x27\x48\xd2\xef\x40\x92\xea\x41\x92\x54\x90\xa4\x17\x41\x92\x5e\x01\x49\x7a\x03\x24\xe9\x6d\x90\x24\x03\x24\xe9\x43\x00\xe9\x33\x00\xe9\x73\x00\xe9\x2b\x00\xc9\x06\x90\x7e\x00\xa0\x12\x48\x34\x00\x40\xdb\x82\x44\xb3\x41\xa2\xed\x41\xe2\xba\x4b\xcb\x00\x68\x05\x00\xad\x02\x89\x9e\x03\x12\x3d\x1f\x80\x0e\x06\xa0\x97\x00\xd0\x91\x20\xd1\xb1\x20\xd1\xf1\x20\xd1\x29\x20\xd1\x99\x00\x74\x0e\x48\x74\x01\x48\xf4\x76\x00\xba\x04\x80\xae\x04\xa0\xf7\x01\xd0\x75\x00\x74\x03\x00\x7d\x0c\x80\x6e\x03\xa0\xbb\x00\xa8\x02\x40\xf7\x02\xd0\x03\x00\xf4\x30\x00\x7d\x15\x80\xea\x00\xf4\x1d\x00\xfa\x57\x00\xfa\x31\x00\x3d\x09\x40\x2d\x00\xfa\x35\x48\xf4\x3b\x00\xda\x04\xc0\x18\x00\x4b\x01\x60\x19\x00\xac\x1d\x00\xeb\x08\xc0\x8a\x40\x62\x5d\x00\x58\x0f\x90\x58\x6f\x20\x67\xee\xe5\x32\xed\x7c\x03\x24\xff\x06\xe0\xf1\x47\xec\x37\xd3\xe3\x7d\xd6\x37\xf7\x41\xc5\xdb\x9f\xad\x8e\x7d\x27\x5e\xc7\xf9\xa6\xcb\x13\xbf\x71\x06\x7d\x84\xff\xe6\xda\xd5\xda\xb7\x38\x2b\xfb\x6c\xff\xca\xbf\xcf\xdc\xfb\x63\xff\xfa\x5f\x7f\x4f\x03\x82\xd6\x59\xb9\x5a\xd0\xfc\xcd\x6d\x4a\x7c\x8c\x97\x36\xff\xf6\xf0\x2f\xae\xd6\xca\xb8\x80\x2d\x4e\xee\xef\xfe\xeb\xe2\x1f\xfb\xd7\x84\x9e\x9b\x5b\x3f\x97\x7c\xfc\x7f\xf7\x2d\xf5\xe7\xd7\x94\x6a\x85\x5d\xbe\xbc\xf9\x1b\x80\x99\xcd\xdf\x09\xe3\xfa\xc9\x6f\x34\xbd\xdc\xf2\xdf\xac\x4c\xfc\x7f\xe1\xdb\x40\x09\x6c\x84\x77\xe0\xaf\x24\x9b\xf4\x27\xc3\xc8\x2d\x64\x3f\xf9\x5a\xea\x2d\xe9\xf4\x56\xe8\x04\xe9\xa8\x41\x08\x35\x28\x82\x6c\x28\x41\x0b\x96\xa2\x05\xcb\xd0\x82\xe5\x68\xc1\x0a\xb4\x60\x25\x5a\xb0\x0a\x2d\x38\x8c\x16\x68\x68\xc1\x2b\x68\x91\x03\x68\xf9\xb6\xa3\x25\x5f\x88\x96\x7c\x11\x5a\xf2\x50\xb4\xe4\x8b\xd1\x92\x87\xa3\x25\x5f\x86\x96\x7c\x39\x5a\xf2\x28\xb4\xe4\x2b\xd0\x92\xaf\x44\x4b\xbe\x0a\x2d\x79\x1c\x5a\xfe\x27\x50\xf3\x6f\x43\x0d\xda\x82\x0f\xba\x40\x0a\x74\x81\x34\x18\x02\x45\x30\x12\x06\xc2\x10\xb8\x08\x0a\x60\x38\x14\xc0\x08\x28\x80\xcb\xa1\x00\x26\xc1\x10\x68\x80\x02\x68\x84\x01\xfe\xc7\xa1\x8b\x7f\x2b\x74\x01\x02\xdd\xa1\xaa\xc5\xf9\x43\x7e\xe2\xfc\x21\xf1\xf3\x83\x90\x8e\x06\x84\xd0\xa0\xe7\xa2\x45\x07\xa3\x45\x87\xa2\x45\x47\xa0\x45\x1d\xfe\x0c\xff\x36\x34\x80\xd2\xe1\x68\xd3\xd1\x68\xd3\x5a\x34\x21\x15\xd2\x71\x31\x84\x70\x31\x3d\x17\x75\x3a\x18\x75\x3a\x14\x75\x7a\x31\xda\x74\x04\xea\xfc\x3c\x7a\x83\x38\x77\xb1\x7f\x1b\x2e\x86\x0c\x48\x47\x1d\x42\xa8\x27\xdc\xe1\x62\x34\xc5\x5d\xae\x44\x9b\x8e\x45\x83\x5e\x85\x26\x1d\x87\x36\x9d\x80\x26\xbd\x01\x6d\xba\x0c\x4d\xff\x13\xa8\xfb\xb7\xa1\x0e\x6d\x21\x03\x75\x3a\x11\x2d\x3a\x15\x2d\x3a\x03\x2d\x7a\x23\x5a\x74\x3e\x5a\x74\x01\x5a\xf4\x66\xb4\xe8\x2d\x68\xd1\x5b\xd1\xa2\x8b\xd1\xf2\x3f\x82\xba\x7f\x23\xea\xfe\x4d\xa8\x8b\x7b\x9b\x90\x81\x16\x84\xd0\x6c\x71\x85\xd8\xd9\xcd\x67\x5a\xfe\x8d\x68\xf9\x37\x09\xee\x4d\xff\x36\x34\xa1\x0c\x7c\x68\x42\x0a\x9a\x74\x37\x9a\xf4\x39\xa8\xa2\x07\xd0\xa4\x47\xd1\xa4\x06\x1a\xf4\x38\x9a\xf4\x1b\xb4\xe8\x77\x68\xd1\xef\xd1\x62\x11\x34\x58\x29\x9a\xac\x33\x9a\x6c\x14\x9a\x6c\x34\x5a\x6c\x02\x9a\x6c\x22\x5a\xec\x5a\xb4\xd8\x64\xb4\xd8\x74\x34\xd9\x0c\xb4\xd8\x2f\xd1\x60\x33\xd1\x62\xd7\xa1\xc1\x66\xa1\xc5\xee\x44\x83\x2d\x42\x8b\x3d\x89\x06\xdb\x8e\x16\xdb\x83\x16\xdb\x8b\x26\xdb\x87\x16\xdb\x8f\x26\x3b\x88\x26\x7b\x11\x2d\xff\xe3\x68\xfa\xb7\xa2\x09\xdd\xc0\x87\x0a\xa4\xa0\x42\x77\xa3\xee\x72\xa6\xd3\xa3\xb8\x9d\x1a\xa8\xd1\xe3\xa8\xd3\x6f\xd0\x70\x39\x33\x58\x04\x35\x56\x8a\x2a\xeb\x8c\x2a\x1b\x85\x3a\x1b\x8d\x06\x9b\x80\xdb\xd9\x44\x34\xd8\xb5\xa8\xb3\xc9\xa8\xb3\xe9\xa8\xb3\x19\x68\xb0\x5f\xa2\xe6\x72\xa6\x09\xce\x6e\x40\x93\xcd\x41\x8b\xcd\x45\x93\xcd\x13\x9c\x6a\x2e\xa7\x9a\xcb\xe9\x76\xb6\x17\x0d\xb6\x0f\xb7\xb3\xfd\x68\xb0\x83\xa8\xb3\x17\xd1\xf0\x3f\x8e\x8a\x7f\x2b\x2a\x50\x1e\xc7\x90\x73\x79\x14\x2d\xfa\x2e\x5a\x02\xbf\x6f\xd0\x74\x39\x34\x59\x26\xda\x2e\x7e\x16\x2b\x43\x9b\x75\x46\x8b\x75\x41\x9b\xf5\x44\x9b\x8d\x46\x93\x4d\x40\x8b\x4d\x44\x53\xe0\x38\x09\x6d\x81\xe5\x14\xb4\xd9\x0c\x34\x5b\x60\xd9\x92\xe3\x1f\xc7\xf6\x45\x34\xe3\xb8\x12\x68\x03\x5d\xe1\x2d\xf8\x8a\x00\xbd\x88\x5e\x4c\xc7\xd0\x5a\x3a\x93\xde\xc6\x2e\x62\x57\x71\x6b\x3c\xa4\x8a\xdb\x10\xd2\x40\x0d\x6a\xf8\x67\xf8\x67\x07\xd7\xf8\x67\x07\x8d\x94\x23\xa9\x9b\x53\x8e\xa4\x55\xa5\x9d\x93\xba\xb9\x6d\x4a\xca\x91\xf4\xc1\x29\x47\xd2\x8f\x64\x9e\xca\x9a\x91\x35\x23\x75\x73\xbb\x01\xf9\x45\xfe\x19\xf9\xfb\xf3\x8f\xb4\xcf\xc8\x3f\xd2\xbe\x28\x7f\x7f\xfb\xde\xf9\xfb\xf9\xdf\xf9\x47\x3a\xc8\xed\x33\x3a\x8e\xef\x38\xbe\x7d\xef\x8e\xe3\xfd\x33\x82\x46\xf3\x27\xad\x2a\x75\x73\x5a\x95\xf3\x49\x39\xe2\xfd\x64\x9e\x72\x3e\xed\x06\xa4\x0f\x16\xd7\x89\x7d\x8e\x24\x7e\x3a\x2e\xcd\x3f\xd2\x71\x3c\xa7\xa0\x91\xbf\x3f\x46\xa9\x9b\x9d\x4f\xca\x91\x8e\xeb\x39\xcf\xf9\x2d\x88\xf7\x69\xdf\xbb\x7d\xef\xb6\x29\xfc\xd3\xe9\x16\xfe\x9d\xbf\xdf\xb9\x77\x5a\x55\x07\x99\x7f\xd2\x8f\xb4\xcf\x70\x28\xc6\x0d\xff\x64\xcd\xe8\x38\xbe\xdd\x00\x4e\xf9\x45\xfc\x53\x50\x5b\xb0\x85\xdf\x93\x8f\x80\xf7\x2e\xb0\x0a\x0b\x0a\xa7\x15\x9e\xee\xb8\xb4\xc0\x0a\xa7\x85\x1f\x2b\xb0\x22\x63\x0a\x0b\x22\x2b\x79\x7b\x64\x73\xf8\xb1\xc2\x69\x45\x23\x22\x2b\x8b\x47\x16\x9e\x2e\x9c\x56\x7c\x7b\xfe\xfe\xe2\x25\xc5\xb7\x17\x6f\x2c\x56\xf2\xf7\x97\xac\x2b\x5e\x52\xb2\xad\xe4\x70\xf1\xc6\x52\x28\x85\xd2\xf6\xa5\x50\x5a\xd1\x71\x69\x29\x94\xf5\x28\x9c\x56\x36\xb0\x73\xfb\xae\x6b\xbb\x49\x65\x03\xf9\xa7\x5b\x5a\xb7\x8d\xe5\xef\x54\xac\xab\x30\x3a\xb7\xef\x2e\x75\x4b\xab\x30\xba\xa5\x75\xcf\xee\x91\xd2\x75\x6d\xe7\xf6\xdd\x36\xf6\x58\xdb\x2d\xad\xbb\xd4\x5d\xf4\xed\x9e\xdd\x3d\x3b\x7f\x7f\xe5\x9c\xca\x05\x1c\xbd\x9e\x29\x95\x73\x7a\xa6\xf4\x5c\xd2\x73\x49\xe5\x82\x9e\xa7\x7b\x2e\xe9\x99\xc2\x5b\x7b\x75\xe9\xd5\x85\xb7\x89\xdf\xaf\x54\x2e\xe0\x7f\xf7\x7a\xa5\x67\x4a\xcf\xd3\xdd\xb3\x7b\x9e\xee\xf5\x71\xaf\x2e\x5d\xd7\x96\xbf\x53\x75\x35\xa7\xea\x9e\xd5\x3d\x2b\x8c\xea\xfe\x3d\x97\x74\xcf\xee\xb9\xa4\xdb\xc6\x9e\xa7\x39\xf1\x0f\xff\xdb\xa5\xd3\x5d\xd7\x76\x97\xf2\xf7\xf3\x33\x7b\xa4\xf4\x5c\xd2\xb9\x7d\xe5\x82\xea\xcd\x7d\xbe\xec\xbb\xe0\x9c\x63\xe7\x7c\x55\xb3\xb2\xc2\xa8\x9c\xc3\x8f\xdd\xd2\x7a\xa6\xc4\x88\xf7\xaf\xde\x5c\xb9\xa0\xe6\x87\x01\x8f\x9d\xc7\x7a\x2e\xe1\x23\xa9\x5c\x70\xde\xf9\x17\x5c\xca\x89\xf7\xe6\x3d\x38\x5d\x70\xfb\xc0\x92\x81\xf3\xf3\xf7\x73\xe2\x67\x0e\x5c\x7f\xe1\x90\xd8\xbf\x71\x2a\x7f\xc7\x21\xfe\x89\xf1\xc4\xfb\xf1\xbb\xf6\x7a\xc5\xc3\x65\xc2\x08\x38\xc5\xf8\x74\x78\xab\x59\x79\xe1\xf8\xc1\x13\x39\xf1\xab\xc6\x7e\x0f\x36\x2e\xea\x7b\xd1\xf2\xc1\x13\x9d\x7b\xf2\x79\xe7\xf2\x10\x23\xaf\x0c\xfe\x1c\x6a\x4d\x32\xbd\x94\x72\x24\x46\xb1\x4f\x41\x6d\xec\x93\x79\xaa\x60\x4b\xec\xe3\xc8\x63\x33\x15\x16\x04\xd7\xf0\x8f\xd0\xe0\xd9\x9c\x0a\x4f\xc3\xa7\x50\x82\x2a\xf4\x83\x6c\xa8\x81\x6c\xe8\x0f\xd9\x30\x00\x52\x60\x30\x1a\x30\x04\x35\x18\x8a\x1a\x0c\x43\x0d\x2e\x41\x13\x46\xa2\x09\xa3\xd0\x84\xd1\xa8\xc1\x15\x68\xc2\x18\xd4\xe0\x4a\x34\x61\x2c\x9a\xc0\xbd\xe3\x52\x54\x61\x19\xaa\xb0\x1c\x55\x58\x81\x2a\xac\x44\x15\x56\xa1\x0a\x8f\x43\x0a\x6c\x41\x0d\xb6\xa2\x01\xdc\xa7\x3e\x89\x06\x6c\x47\x03\x76\xa0\x01\x3b\xd1\x80\xa7\x50\x83\x5d\xa8\xc1\xd3\xa8\xc1\x33\xa8\xc1\xb3\xa8\x41\x3d\x6a\xb0\x07\x35\xd8\x8b\x1a\xec\x43\x0d\xf6\xa3\x06\x2a\x6a\xf0\x07\x34\xe1\x00\x9a\xf0\x3c\x9a\xf0\x02\x9a\x70\x18\x55\x78\x09\x0d\xd0\x50\x85\x97\xd1\x80\x57\x50\x85\x3f\xa2\x01\xaf\xa1\x06\xaf\xa3\x06\x7f\x42\x0d\xde\x44\x0d\xde\x42\x0d\x8e\xa2\x06\xef\xa2\x06\xef\xa1\x06\x7f\x41\x0d\x8e\xa3\x06\x1f\xa0\x06\x1f\xa1\x09\x9f\xa0\x09\x9f\xa2\x09\x27\xd0\x84\xd3\x68\x12\x19\x4d\x12\x40\x93\xb4\x41\x93\xa4\xa3\x46\x42\xa8\x91\x2c\xd4\x48\x0e\x6a\x24\x17\x4d\x92\x8f\x26\xe9\x84\x26\x89\xa0\x49\x4a\x20\x9b\x94\x41\x36\x29\x47\x93\x74\x47\x93\x54\xa2\x49\x7a\xa1\x49\xaa\xd1\x24\x7d\xd0\x24\x7d\x21\x9b\x9c\x03\x29\xa4\x3f\xa4\x90\xa9\xa8\x91\xf9\x68\x92\x03\xa8\x92\xe7\xd1\x20\x07\xd1\x20\x87\x50\x23\xc7\xd1\x24\xef\x43\x36\x3d\x17\x55\x3a\x18\x55\x3a\x14\x55\x3a\x02\x55\x3a\x11\x0d\x7a\x2d\x5a\x74\x92\xf0\xe0\x06\x9d\x81\x26\xfd\x25\x5a\x74\x26\x5a\xf4\x3a\xb4\xe8\x6c\xb4\xe8\x1c\xe1\xd5\x0d\x7a\x13\x9a\x74\x01\x1a\xf4\x66\x34\xe8\xad\x68\xd0\xc5\x68\x50\x15\x35\x7a\x08\x55\xfa\x32\x6a\xf4\x0d\xd4\xe8\x27\x68\xd1\x13\xa8\xd2\x93\xa8\x51\x0b\x55\xfa\x0f\xd4\xe8\xd7\xa8\xd1\x6f\x51\x63\x04\x35\x26\xa1\xc6\x7c\xa8\x31\x19\x4d\x96\x82\x2a\xcb\x45\x95\xe5\xa1\xca\x8a\xd0\x66\x25\xa8\xb1\x6e\xa8\xb1\x0a\xd4\x58\x0f\xd4\x58\x15\x6a\xec\x6a\xd4\xd8\x78\xd4\xd8\x2d\xa8\xb1\x85\xa8\xb2\xbb\x51\x65\x4b\xd1\x62\xcb\x50\x65\xcb\xd1\x62\x2b\x50\x65\x2b\xd1\x62\xab\x51\x63\x6b\xd0\x62\xf7\xa1\xc5\x36\xa0\xc6\x36\xa2\xc6\x36\xa3\xc6\xa2\xa8\xb2\x3a\xd4\xd8\x6e\x54\x59\x3d\x6a\xec\x39\xd4\x98\x8a\x2a\x7b\x01\x35\x76\x18\x35\xf6\x12\x6a\x4c\x43\xd5\xb7\x1d\x55\xdf\x0e\x34\x7c\x27\xd0\x94\xcb\x20\x5b\xee\x02\xd9\x72\x37\xc8\x96\x2f\x44\x55\x1e\x8c\x86\x7c\x11\xaa\xf2\x10\x34\xe4\xa1\xa8\xca\xc3\xd0\x90\x2f\x46\x55\x1e\x8e\xaa\x7c\x29\x1a\xf2\x65\xa8\xca\x23\xd0\x90\x2f\x47\x55\x1e\x89\x86\x3c\x0a\x55\x79\x34\x1a\xf2\x15\xa8\xca\x63\xd0\x90\xaf\x44\x55\x1e\x8b\x86\x7c\x15\xaa\x72\x2d\x1a\xf2\x38\x54\xe5\xab\xd1\x90\xc7\xa3\x26\x4f\x44\x4d\x9e\x84\x9a\x3c\x05\x35\x79\x06\x6a\xf2\x4c\xd4\xe4\x59\xa8\xc9\xf3\x50\x93\xe7\xa3\x26\x2f\x40\x4d\xbe\x15\x35\xf9\x76\xd4\xe4\x3b\x51\x93\x17\xa3\x26\x2f\x41\x4d\x5e\x8a\x9a\xbc\x1c\x35\x79\x25\x6a\xf2\x6a\x34\xe5\x35\x68\xca\xf7\xa1\x29\xdf\x8f\xa6\xbc\x16\x4d\x79\x1d\x9a\xf2\x7a\x34\xe5\x07\x21\x45\x7e\x18\x52\xe4\x47\x20\x45\xde\x04\x29\x22\xaa\xbd\x1a\x56\x41\x19\xea\xd0\x0d\x75\xa8\x42\x1d\x7a\xa3\x0e\xfd\x50\x85\x73\xd0\x82\x1a\xd4\xa0\x3f\x6a\x30\x00\x35\xb8\x07\x75\x58\x8f\x3a\x3c\x88\x3a\x3c\x84\x3a\x3c\x8c\x3a\x6c\x40\x1d\x36\xa2\x0e\x9b\xd0\x82\xcd\x68\xc1\xa3\x68\xc1\x63\x68\xc1\xe3\xa8\xc1\xab\xa8\xc3\x11\xd4\xe1\x0d\xd4\x41\x47\x1d\x3e\x44\x1d\x3e\x46\x1d\x4c\xd4\xe1\x33\xd4\x49\x5b\xd4\x49\x06\xea\x24\x13\x75\x92\x8d\x3a\x29\x41\x95\x94\xa1\x4a\xba\xa1\x45\x2a\xd0\x22\x3d\xd0\x22\x3d\xd1\x22\x55\x68\x91\xde\x68\x91\xbe\xa8\x91\x73\x50\x23\xfd\x51\x23\x53\x50\x27\x37\xa2\x45\x5e\x44\x9d\xbc\x8f\x2a\x1d\x8e\x06\x1d\x8d\x06\x1d\x8b\x2a\xbd\x0a\x35\x5a\x8b\x3a\xbd\x1a\x35\x3a\x01\x35\x3a\x0b\x2d\xba\x0c\x35\xba\x1b\x55\xba\x07\x75\x7a\x00\x55\xfa\x26\xea\xf4\x6d\x11\xc5\xa9\xf4\x5d\x34\xa8\x81\x0a\x3d\x8e\x2a\xfd\x06\x75\xfa\x1d\x6a\xf4\x7b\xd4\x59\x08\x75\x16\x41\x85\x15\xa3\xce\x4a\x51\x63\x9d\x51\x63\x5d\x51\x67\xe5\xa8\xb3\xee\xa8\xb3\x4a\xd4\x59\x2f\xd4\xd9\x28\x54\xd9\x68\xd4\xd9\x38\xd4\xd9\x35\xa8\xb3\x09\xa8\xb2\x89\xa8\xb3\x6b\x51\x63\x93\x51\x63\xd3\x51\x65\x33\x50\x67\xbf\x44\x85\xcd\x44\x8d\x5d\x87\x0a\x9b\x85\x1a\xbb\x01\x35\x36\x17\x35\x76\x27\x2a\x6c\x11\x6a\xec\x61\xd4\xd9\x23\xa8\xb3\x4d\xa8\xb3\x27\x51\x61\xdb\x51\x63\x7b\x50\x63\x7b\x51\x67\xfb\x50\x63\xfb\x51\x67\xcf\xa3\xce\x0e\xa2\xca\x5e\x44\x5d\x2e\x43\x4d\xee\x82\x9a\xdc\x0d\x35\x79\x2e\xea\xf2\x8d\xa8\xcb\x37\xa1\x2e\xdf\x8c\xba\xbc\x10\x75\xf9\x36\xd4\xe5\x3b\x50\x97\x17\xa1\x2e\xdf\x85\xba\x7c\x37\xea\xf2\x32\xd4\xe5\x15\xa8\xcb\xab\xd0\x92\xef\x41\x4b\xbe\x17\x2d\xf9\x57\x68\xc9\xbf\x46\x4b\xfe\x0d\x5a\xf2\x03\x68\xc9\x0f\xa2\x26\x3f\x8c\x9a\xfc\x08\x6a\xf2\x26\xd4\x20\x0b\xfa\xa1\x41\x4a\xd0\x20\x65\x68\x90\xf7\x05\xca\x06\xdd\x8d\x06\x3d\x80\x06\x3d\x2a\xa2\x73\x43\x44\xe7\x3c\x32\x1f\x85\x86\x1b\x8d\x1b\x22\x1a\x9f\x8e\x86\x88\xc2\x0f\xa2\xc1\xa3\x6a\x18\x00\x3e\x54\x21\x05\x55\x28\x43\x0b\xba\xa1\x05\xdd\x61\x29\x54\xa1\x05\xbd\xd1\x12\x72\x57\x83\x06\xf4\x47\xc3\x95\x39\x0b\xd6\xa3\x05\x0f\xa2\x05\x0f\xa1\x05\x0f\xa3\x05\x1b\xd0\x82\x8d\x71\x19\xb3\xe0\x08\x5a\xf0\x06\x5a\xa0\xa3\x05\x1f\xa2\x05\x1f\xa3\x05\x26\x5a\xf0\x19\x5a\xa4\x2d\x5a\x24\x03\x2d\x92\x89\x16\xc9\x46\x2b\x2e\x63\x7d\xd1\xf0\xc8\x12\x97\x23\x8b\xcb\x91\x5c\x86\x86\xdc\x05\x0d\xb9\x1b\x1a\xf2\x5c\xb4\xe4\x1b\xd1\x92\x6f\x42\x4b\xbe\x19\x2d\x79\x21\x5a\xf2\x6d\x68\xc9\x77\xa0\x25\x2f\x42\x4b\xbe\x0b\x2d\xf9\x6e\xb4\xe4\x65\x68\xc9\x2b\x5a\xe2\xe6\x7f\x1c\x55\xff\x56\x54\xa1\x77\x2c\xf3\x13\x59\x6e\x3f\x34\xa1\x06\x6d\xe8\x8f\x36\x9c\xcb\xf1\x40\x1b\xce\x43\xfb\xac\xd9\xef\xe3\x68\x27\x64\xc0\x25\x68\x92\x32\x6e\xe5\xd1\x26\xe7\xa0\x4d\xfa\xa3\x4d\xce\x45\x9b\x9c\x87\x36\xb9\x00\x6d\x9e\x21\x93\xf7\xd1\xa4\x7b\xd1\x16\x99\x72\x19\xda\x72\x17\xb4\xe5\x6e\x68\xff\xa7\x59\xb3\xfc\x20\xda\xf2\xc3\x68\xcb\x8f\xa0\x2d\x6f\x42\x3b\x9e\xa5\x96\xc6\xe7\x2e\x36\x6f\x3f\x36\x4f\xff\xe9\x1c\xb9\xf3\xf1\x9f\xe2\x2f\x6c\xd9\x00\x58\x20\xea\x0a\x5e\x0a\x25\x51\x11\x64\x27\x10\x9f\x15\x2f\x2d\x4d\xa2\x65\x49\xb4\x3c\x89\x56\x24\xd1\xca\x24\x5a\x95\x44\x87\x93\x48\x4b\xa2\x57\x12\x49\xcc\xa8\x87\xf8\xac\x7a\x49\xcc\xaa\x97\x2e\x4a\xa2\xa1\x49\x74\x71\x12\x0d\x4f\xa2\xcb\x92\xe8\xf2\x24\x1a\x95\x44\x57\x24\xd1\x95\x49\x74\x55\x12\x8d\x4b\x24\x51\x9b\xf1\xd2\xb6\x44\x82\x11\xb1\xfc\xbb\x85\xd4\xf5\x43\x0b\xce\x41\x1b\x6a\xd0\x82\xfe\x42\x97\xcc\x1f\x95\xc4\x4d\x68\xc3\x66\xb4\xe1\x51\xb4\xe1\x31\xb4\xe1\x71\x34\xff\x0b\x0b\x62\x91\x32\xb4\x48\x37\xb4\x49\x05\xda\xa4\x07\xda\xa4\x27\xda\xa4\x0a\x6d\xd2\x1b\x6d\xd2\x17\x2d\x72\x0e\x9a\xa4\x3f\x9a\x42\x92\x6f\x44\xdb\xb5\x2e\x5c\x17\x2d\xb9\x0b\x5a\x72\xb7\xff\x5c\xba\xe5\x55\x68\xcb\xf7\xa0\x2d\xdf\x8b\xb6\xfc\x2b\xb4\xe5\x5f\xa3\x2d\xff\x06\x6d\xf9\x01\xb4\xe5\x07\xd1\x94\x1f\x46\x53\x7e\x04\x4d\x79\x93\xc8\xb0\x9d\x7a\x40\x24\x56\x3f\x82\x12\xd4\x85\xb5\x71\x2c\x8d\x0e\xcb\x50\x87\xe5\xa8\xc3\x0a\xd4\x61\x25\xea\xb0\x0a\x75\x38\x8c\x3a\x68\xa8\xc3\x2b\xa8\x27\x59\x14\xdd\xb7\x1d\x75\xf9\x42\xd4\xe5\x8b\x50\x97\x87\xa2\x2e\x5f\x8c\xba\x3c\x1c\x75\xf9\x32\xd4\xe5\xcb\x51\x97\x47\xa1\x2e\x5f\x81\xba\x7c\x25\xea\xf2\x55\xa8\xcb\xe3\x50\x8f\xd7\xa5\x8e\x08\x2d\xcc\x10\x36\x30\x56\xed\x53\x5b\xce\x25\x64\xc3\x60\x54\x60\x08\xaa\x30\x14\x55\x18\x86\x2a\x5c\x82\x2a\x8c\x44\x1d\x46\xa1\x0e\xa3\x51\x85\x2b\x50\x87\x31\xa8\xc2\x95\xa8\xc3\x58\xd4\xa0\x16\x75\x18\x87\x16\x5c\x8d\x16\x5c\x83\x16\x8c\x47\x0b\x26\xa0\x71\xd6\xcc\xe0\xc7\x64\x63\x0b\xaa\xc0\x31\xdb\x86\x0a\x3c\x89\x0a\x6c\x47\x05\x76\xa0\x02\x3b\x51\x81\xa7\x50\x85\x5d\xa8\xc2\xd3\xa8\xc2\x33\xa8\xc2\xb3\xa8\x42\x3d\xaa\xb0\x07\x55\xd8\x8b\x2a\xec\x43\x15\xf6\xa3\x0a\x2a\xaa\xf0\x07\xd4\xe1\x00\xea\xf0\x3c\xea\xf0\x02\xea\x70\x50\x68\x39\xcf\x1a\x14\x37\x6b\x50\xdc\xac\x41\x11\xb2\xf7\x1a\xaa\x42\xfe\x5e\x47\x55\xc8\xe0\x9f\x50\x15\x72\xf8\x26\xaa\xf0\x16\xaa\x70\x14\x55\x78\x17\x55\x78\x0f\x55\xf8\x0b\xaa\x70\x1c\x55\xf8\x00\x55\x21\xa7\x1f\xa1\x2a\x64\xf5\x13\x54\x85\xbc\x7e\x8a\x2a\x97\x59\x38\x81\x2a\x9c\x46\x9d\xc8\xa8\x93\x00\xea\xa4\x8d\x88\xb6\x2c\x92\x8e\xaa\x90\xe5\x10\xaa\x42\x9e\xb3\x50\x15\x32\x9d\x83\x2a\xc9\x45\x9d\xe4\xa3\x4e\x3a\xa1\x46\x22\xa8\x79\xb2\x0c\x9d\x74\x47\x9d\x54\xa2\x4e\x7a\xa1\x4e\xaa\x51\x27\x7d\x50\x27\xfd\xd0\x22\x03\xd0\x20\xe7\xa3\x41\x06\xa2\x21\x64\x7d\x2a\xaa\x64\x3e\xea\x6e\xb6\xa1\x90\x83\xa8\x08\xd9\x3f\x84\x2a\x39\x8e\x1a\xcf\x38\xdc\xc8\x5a\xf1\x9d\x40\x5d\xee\x8c\x96\xdc\x55\x58\x2d\x1e\x55\x2b\x6e\x54\xad\xb8\x51\xb5\xe2\x89\xaa\x15\x37\xaa\x56\xdc\xa8\x5a\x71\xa3\x6a\xc5\x8d\xaa\x15\x37\xaa\x56\xdc\xa8\x5a\x71\xa3\x6a\x45\x1e\x8f\xaa\x3c\x11\x55\x79\x12\xaa\xf2\x14\x54\xe5\x19\xa8\xca\x33\x51\x95\x67\xa1\x2a\x74\x70\x1e\xaa\x42\x0f\xe7\xa3\x2a\x74\x71\x01\xaa\x71\x7d\xbc\x15\x55\xa1\x93\xb7\xa3\x2a\xf4\xf2\x4e\x54\x85\x6e\x2e\x46\x55\xe8\xe7\x12\x54\x85\x8e\x2e\x45\x55\xe8\xe9\x72\x54\x85\xae\xae\x44\x55\x5e\x8d\xba\xbc\x06\x75\xf9\x3e\xd4\xe5\xfb\x51\x97\xd7\xa2\x2e\xaf\x43\x5d\x5e\x8f\xba\xbc\x41\xd4\x40\x0d\xff\x46\x34\xfc\x9b\xd0\x88\x57\xa7\x3b\x42\xba\xa8\xa0\x72\x3f\xc4\xf5\xd4\x86\x65\x68\xc3\x72\xb4\x61\x05\xda\xb0\x12\x6d\x58\x25\xa2\x01\x1b\x34\xb4\xe1\x15\xa1\x9b\xdc\xcb\x73\xcf\x6e\xcb\x17\xa1\x2d\x0f\x45\x5b\xbe\x18\x6d\x79\x38\xda\xf2\x65\x68\xcb\x97\xa3\x2d\x8f\x42\x5b\xbe\x02\x6d\xf9\x4a\xb4\xe5\xab\xd0\x96\xc7\x09\x4f\x6e\xf9\xb7\xa1\x05\x7b\x62\x35\x63\x57\x2f\x0d\x28\x43\x1b\xba\xa1\x0d\x55\x68\x43\x6f\xb4\x61\x30\x5a\x30\x04\x2d\x18\x8a\x16\x0c\x43\x0b\x2e\x41\x1b\x46\xa2\x0d\xa3\xd0\x86\xd1\x68\xc1\x15\x68\xc3\x18\xb4\xe0\x4a\xb4\x61\x2c\xda\x50\x2b\x38\x37\x60\x19\x1a\xb0\x1c\x0d\x58\x81\x06\xac\x44\x03\x56\xa1\x01\xf7\xa0\x0d\xeb\xd1\x86\x07\xd1\x86\x87\xd0\x86\x87\xd1\x86\x0d\x68\xc3\x46\xb4\x61\x0b\x5a\xb0\x15\x2d\xe0\x5c\x3d\x89\x16\x6c\x47\x0b\x76\xa0\x05\x3b\xd1\x82\xa7\xd0\x82\x5d\x68\xc1\xd3\x68\xc1\x33\x68\xc1\xb3\x68\x41\x3d\xe7\x1e\x2d\xd8\x8b\x16\xec\x43\x0b\xf6\xa3\x05\x2a\x5a\xf0\x07\xb4\xe1\x00\xda\xf0\x3c\xda\xf0\x82\x40\xcb\x80\x97\x84\x67\x35\xe0\x65\xe1\x51\x0d\xf8\xa3\x88\x4a\x6c\x78\x4d\xd8\x7e\x1b\x5e\x17\xf6\xdf\x86\x3f\x09\x1f\x60\xc3\x9b\x68\xc1\x5b\x68\xc1\x51\xb4\xe0\x5d\xb4\xe0\x3d\xb4\xe0\x2f\x68\xc1\x71\xb4\xe0\x03\xe1\x23\x6c\xf8\x08\x6d\xf8\x18\x6d\xf8\x04\x6d\x30\xd1\x86\x4f\xd1\x86\xcf\xd0\x86\x13\x68\xc3\x69\xb4\x89\x8c\x36\x09\xa0\x4d\xda\xa0\x4d\xda\xa2\x4d\xd2\x85\x1f\xb1\x49\x48\xf8\x12\x9b\x64\x09\x7f\x62\x93\x1c\xb4\x48\x2e\xda\x24\x1f\x6d\xd2\x09\x6d\x12\x41\x9b\x94\xa3\x4d\xba\xa3\x4d\x2a\xd1\x26\xbd\xd0\x26\xd5\x68\x93\x3e\x68\x93\x29\x68\x93\xa9\x68\x91\xf9\x62\xe6\x0d\xf2\x3c\x5a\xe4\xa0\x88\x96\x6c\x72\x08\x2d\x72\x5c\x48\x83\xe1\xdb\x81\x96\xef\x84\x90\x0a\x43\x1e\x2c\xa2\x00\x43\x1e\x22\xbc\xbf\x21\x0f\x13\x5e\xdf\x90\x87\xa3\x21\x5f\x2a\x3c\xbc\x21\x8f\x10\x9e\xdd\x90\x47\x0a\x8f\x6e\xc8\xa3\x85\x27\x37\xe4\x31\xc2\x83\x1b\xf2\x58\xe1\xb9\x0d\xb9\x56\x78\x6c\x43\xbe\x1a\x2d\x79\x3c\x5a\xf2\x44\xb4\xe4\x49\x68\xc9\x53\xd0\x92\x67\xa0\x25\xcf\x44\x4b\x9e\x25\x7c\x9b\x2d\xcf\x13\xfe\xcd\x96\xe7\x0b\x1f\x67\xcb\x0b\x84\x9f\xb3\xe5\x85\x68\xcb\xb7\x0a\x5f\x67\xcb\xb7\x0b\x7f\x67\xcb\x77\x0a\x9f\x67\xcb\x8b\x85\xdf\xb3\xe5\x25\xc2\xf7\xd9\xf2\x52\xe1\xff\x6c\x79\xb9\xf0\x81\xb6\xbc\x12\x2d\x79\x35\xda\xf2\x1a\xb4\xe5\xfb\xd0\x96\xef\x47\x5b\x5e\x8b\xb6\xbc\x0e\x6d\x79\xbd\x90\x6a\x67\x1d\xe3\xb9\xa4\xb5\x25\xad\x85\xb7\x19\x8c\x3a\x0c\x41\x1d\x86\xa2\x0e\xc3\x50\x87\x4b\xd0\xf2\xd4\x9b\x74\xb7\xde\xa4\xbb\xf5\x26\x43\xd4\x9b\x26\x88\x78\x50\x83\x65\xa8\xc1\x72\xd4\x60\x05\x6a\xb0\x12\x35\x58\xf5\x13\x79\xca\x16\xd4\x61\x2b\xea\xc0\x39\x7b\x12\x75\xd8\x8e\x3a\xec\x40\x1d\x76\xa2\x0e\x4f\xa1\x0e\xbb\x50\x87\xa7\x51\x87\x67\x50\x87\x67\x51\x87\x7a\xd4\x61\x0f\xea\xb0\x17\x75\xd8\x87\x3a\xec\x47\x1d\x54\xd4\x5b\xa9\x45\x69\xf0\x92\xf0\xd9\x1a\xbc\x2c\xfc\xb6\x06\x7f\x44\xdd\xf5\x2a\xba\xeb\x55\x74\xd7\xab\xe8\xae\x57\xd1\xe1\x2d\xd4\xe1\x28\xea\xf0\x2e\xea\xf0\x1e\xea\xf0\x17\xd4\xe1\x38\xea\xf0\x81\xc8\xd1\xb9\x57\xb1\x5c\xaf\x62\xb9\x5e\xc5\x72\xbd\x8a\xd5\xa2\x56\xe5\x78\x15\xdd\xf5\x2a\xba\xeb\x55\x74\xd7\xab\xe8\x9e\xda\x95\x41\x22\x68\x9c\xb5\x66\x35\x00\x2d\x72\x3e\x5a\x64\xa0\x1b\xff\x4f\x45\xdd\xad\x5b\x69\xe4\x79\xd4\xc9\x41\xd4\x5d\x4f\xa2\x93\xe3\x68\xf8\xb6\xa3\xe6\xdb\x81\xba\xa8\xcf\x5c\x88\x9a\x3c\x58\xc4\x26\x9a\x3c\x44\xc4\x27\x9a\x3c\x4c\xc4\x28\x9a\x3c\x1c\x35\xf9\x52\x11\xa7\x68\xf2\x08\x11\xab\x68\xf2\x48\x11\xaf\x68\xf2\x68\x11\xb3\x68\xf2\x18\x11\xb7\x68\xf2\x58\x11\xbb\x68\x72\xad\x88\x5f\x34\xf9\x6a\xd4\xe5\xf1\xa8\xcb\x13\x51\x97\x27\xa1\x2e\x4f\x41\x5d\x9e\x81\xba\x3c\x13\x75\x79\x16\xea\xae\xf7\xd0\x5d\xef\xa1\xbb\xde\x43\xf7\x78\x0f\xdd\xf5\x1e\xba\xeb\x3d\x74\xd7\x7b\xe8\xae\xf7\xd0\x5d\xef\xa1\xbb\xde\x43\x77\xbd\x87\xfe\x63\x35\x9c\xb8\xb7\x28\x6d\x61\xab\x7f\xcc\xbe\x72\x7b\xc7\x6d\x1d\xb7\x73\xdc\xc6\x7d\xe8\xda\x2f\xd3\xb1\x5b\xc2\x46\x71\xfb\xc4\x6d\x53\xb6\x6b\x6b\x5e\x44\x5b\xe8\x32\xd7\x63\xae\xc3\x31\xfd\xe5\xba\xcb\xf5\x96\xeb\x2c\xd7\x57\xae\xab\x5c\x4f\xb9\x97\x62\xe0\x43\x1b\x52\xd0\xf6\x3f\x8e\xb6\x7f\x2b\xda\x10\x8a\xb5\xb4\x12\xab\xd9\x3c\x3e\x72\x63\x09\x9b\x9c\x8f\x36\x19\x88\x76\x3c\x2e\xd8\x20\x56\xe1\x9c\xab\x30\xf0\x41\x36\xa4\x40\xb6\xff\x71\xc8\xf6\x6f\x85\x6c\xd1\x32\x00\x52\xc4\x1a\xed\x00\xff\x56\x18\x00\xbd\x13\x3c\x15\xf7\x4e\x63\x84\xfe\xfd\x67\x1e\xe4\x35\xa1\x37\x96\xf0\x06\x3f\xe1\x09\x84\x55\x0f\x09\x99\xb7\x84\x25\x9f\x2a\x64\xf4\xc7\xad\xe3\x3c\x21\x2f\x96\xb0\x88\xb7\x0a\xf9\xb0\x84\x05\x5c\x2c\x64\xc2\x12\x56\x6f\xb9\x90\x03\x0b\xae\x8c\xaf\x37\xb7\xe6\x87\xbd\x23\xfc\xbf\xf0\x9d\xdc\x4f\x72\x1f\xf9\xc7\xff\x0c\x05\xe1\x0b\x3f\x71\x7d\xe0\x09\xd7\xd7\x25\xa3\x12\xf3\x55\x87\xd0\xe2\xfe\x49\xf8\x25\xee\x93\xb8\x3f\xe2\x7e\x88\xfb\x20\xee\x7f\xb8\xef\xe1\x7e\x87\xfb\x1c\xee\x6f\x7e\xca\xd7\xfc\x07\x68\x7a\xd6\xe2\x63\xa8\xc6\x2a\x33\x45\x42\xae\xba\x88\x0a\xc7\x56\xe8\x22\xaa\x1c\x5c\x92\x2d\x48\x11\x32\x68\xf9\x39\xbe\xe7\x88\xf3\xbc\x94\x92\x44\x69\x30\x24\x81\x8a\x60\x64\x02\x0d\x74\x77\x0c\x0c\xf4\xec\x1c\xf0\xd2\xf0\x24\x1a\x91\x44\x97\x27\xd1\x24\x18\x92\x40\x0d\x50\x90\x40\x8d\x30\xc0\x4b\x62\x8c\x5e\xda\x9a\x48\xff\xd5\x08\x13\xe9\xff\xfd\x11\x0e\xf1\xd2\x4f\x8e\x30\x13\x2e\x86\x2e\x70\x15\x74\x81\x71\x50\x05\x57\x43\x15\x5c\x03\x55\x30\x1e\xaa\xe0\x20\x54\x91\x52\xe8\x42\x3a\x43\x17\xd2\x0f\xaa\xc8\x07\xd0\x45\xee\x0c\x55\x72\x57\xa8\x92\x37\x40\x55\x60\x05\x74\x09\xac\x84\x2e\x81\x55\xd0\x25\xb0\xda\xbd\x52\x15\x5c\x05\x55\x67\xb9\x52\x15\xe9\x0c\x55\xee\x95\xaa\x92\xae\x54\x15\x58\x09\x55\x81\x55\x50\x15\x58\x0d\x55\x90\x16\xab\x89\xd2\xe1\x68\xd1\xd1\x68\x79\xea\xd8\x16\xbd\x1a\x0d\x51\xc7\x5e\xe6\xa9\x29\x86\x5a\xdd\x4d\xe2\xec\x0c\x89\xed\xf5\x30\xe9\x55\x68\x8b\x5d\x22\x57\x8b\xfd\x1e\xb6\xbb\xdf\xc3\x5b\xc7\x73\xe3\x24\x7a\x2e\x6a\x74\x30\x6a\x74\x28\x6a\x82\x87\x11\xa8\x09\x3e\x6a\xd1\xa4\xd7\xa0\x4d\x27\xa2\x4e\xaf\x45\x83\x4e\x42\x93\x4e\x46\x93\x4e\x41\x93\x4e\x45\xdd\x5d\x1f\x32\xe8\x75\x68\xd2\xeb\xd1\xa4\xb3\xd1\xa4\x73\xd0\xa4\x37\xa2\x4e\x6f\x42\x9d\x2e\x40\x9d\xde\x8c\x3a\x5d\x88\x26\xbd\x15\x75\x7a\x3b\x9a\xf4\x0e\x34\xe9\x22\x34\xe9\x62\xd4\xe9\x5d\x68\xd2\x25\xcd\x3e\xcd\xff\x05\xb7\xf4\x74\x2c\x5a\x82\xf7\x09\x0e\xbf\x50\x22\x46\xeb\xa5\x50\x22\x09\x14\xbc\x34\x38\x89\x86\x26\xd1\x88\x24\x1a\x97\x48\x02\x21\x2f\x6d\x4b\x24\xe8\xee\xad\x69\xd0\x73\x51\xa1\x83\x51\xa1\x43\x51\xa1\xc3\xc5\x7e\x1b\x85\x8e\x46\x53\xac\x42\x5c\x23\xf6\xc3\xa8\xf4\x5a\xd4\xe9\x24\xd4\xe9\x64\x34\xe8\x14\xd4\xe9\x54\x54\xe9\x74\xb1\x47\x86\x23\xa8\xd3\xeb\x50\xa7\xd7\xa3\x41\x67\xa3\x4e\xe7\xa0\x4e\xe7\x8a\x55\x36\xd5\x45\x51\xa5\x37\xa3\x4a\x17\xa2\x4e\x6f\x45\x95\xde\x86\x16\xbd\x1d\x75\x7a\x07\xea\x74\x11\xea\x74\x31\xaa\xf4\x2e\xd4\xe9\x12\xd4\xe9\xd2\xd6\x73\x4b\xff\x17\x68\x42\x9a\xd8\x5d\xe4\xa5\xd1\x49\x54\x2b\xb8\x8e\x13\xf8\xe2\x12\xc9\x5b\xe6\xa3\x4d\x6f\x41\x1b\x2a\x44\x5d\xc9\x4b\xa1\x44\x12\xfb\x95\xbc\x34\x38\x89\x86\x26\x11\x97\x5c\x2f\x8d\x40\x3d\x81\x92\xe6\x87\xde\x90\x48\xa2\xd6\xe4\xa5\x6d\x89\x04\x03\x45\x9e\xeb\xa5\x50\x22\xfd\xc7\x12\x74\x31\x9a\x09\x94\x2c\x51\x5c\x07\xbd\x34\xd6\x5d\x37\x89\xd1\x55\x42\x3f\x9b\x69\x9c\xd0\xd5\x66\x9a\x80\x66\x02\xdd\xe0\xea\xef\x0d\x71\x3d\x36\xbd\x24\x72\x1f\x2f\x6d\x4b\x24\x48\xf1\xe8\xba\x41\x07\xa3\x41\x87\xa2\x21\x64\x60\x84\x58\x3b\xb3\xe3\x71\x25\xa1\x37\x40\x36\xc8\xe0\x43\x03\x52\xd0\x88\xcd\xba\xff\x71\xee\x1b\xd1\x00\x5f\xdc\xf6\xdc\xe0\xb1\x25\xe7\x40\x06\xea\x5e\x12\xbb\xc0\xbc\x34\x35\x89\x66\x24\xd1\x8d\x49\x34\x3f\x89\x16\x24\xd1\xcd\x49\x74\x4b\x12\xdd\x9a\x44\x8b\x13\x49\xec\x5f\xf3\xd2\xc6\x24\xda\x94\x48\xc0\x62\xd5\x99\x78\xf5\xc4\x1f\x1f\x57\x2b\xbb\xdc\x20\x1d\x7c\xa8\x41\x0a\x6a\x74\x22\xda\x74\x2a\xda\x42\xdf\x1d\xbd\xb6\xdd\x11\xd9\xf4\x66\x81\x2e\x3f\xcb\xa6\x8b\x05\xca\x9a\x7f\x2b\x6a\x02\x7f\x11\x35\xc7\xce\xf2\x44\xc2\xe9\x3c\xaa\x16\xd8\xdb\xfe\x6d\x68\x0b\xe9\x36\x13\x28\x03\xad\x04\x0a\xa1\xe9\xa5\xff\x79\x6e\x7e\x6a\x2e\x7e\x1a\xfb\x44\xda\x98\x44\x9b\x92\xe8\x09\x21\xe1\xcd\xb4\x2d\x91\x04\x26\x62\x64\xf1\xfd\x84\x7d\xe3\xf2\xbb\x1b\x35\x7a\x00\x35\x7a\x10\x2d\x7a\x14\x75\xfa\x8e\xd8\x13\xa7\xd3\xe3\xa8\x89\x55\xcb\x53\x9e\x7d\x85\xe9\x68\xb1\x2c\xb1\x8b\x4f\x67\xa5\x68\xb0\xce\x68\xb0\xf3\xd0\x60\x17\xa2\xc1\x2e\x47\x83\x8d\x42\xcd\x5d\xdd\xd4\xdd\xbd\x86\x3a\x9b\x24\xf6\x1b\xea\x6c\x8a\x58\xed\xd4\xdc\x3d\x87\xba\xbb\x4f\x4e\x77\xf7\x1c\xea\x62\x5f\xdc\xe3\x68\xb1\x27\xd0\x62\xbf\x45\x8b\x6d\x41\x8b\x6d\x45\x8b\x6d\x13\xfb\xe5\x74\xb1\x5f\xee\x69\x34\xd8\x1e\xd4\xdd\x3d\x73\xba\xbb\x1f\x51\x73\xf7\x23\x3a\xfa\xf7\x68\x82\xef\xd9\x83\x16\x55\x51\x77\x77\x5d\xe8\xf4\x0d\xd4\xe9\x9b\x68\xd1\xb7\xf9\x68\x21\x5b\xac\x6e\x7f\x8a\x3a\xfd\x0c\x75\x7a\x02\x35\x7a\x12\x55\xda\x80\x16\xfd\x1b\x5a\xb4\x11\x75\xfa\x39\xea\xf4\x0b\xd4\xa9\x85\x1a\xfd\x3b\xea\xf4\x4b\xd4\xe9\x3f\x50\xa5\x5f\xa1\x4e\xff\x89\x3a\xfd\x5a\xac\x8a\x1b\xf4\x14\x1a\xf4\x5b\x54\xa9\x8d\x16\xfd\x97\x58\x25\xd7\xe9\xbf\x51\xa7\xa7\x51\xa7\xdf\xa3\x41\x7f\x40\x9d\x9e\x41\x9d\x36\xa1\x45\x11\x75\x06\x68\x32\x82\x2a\x93\x50\x65\x0c\x75\xe6\x43\x95\xc9\xa8\xb1\x14\xd4\x58\x2a\xea\xac\x0d\xea\xac\x2d\xea\x2c\x1d\x0d\x96\x21\x56\xdb\x2d\x96\x89\x16\x6b\x87\xba\xbb\x0b\x44\x63\xed\x51\x67\x1d\x51\x67\x05\xa8\xb3\x22\xd4\x59\x31\x5a\xac\x04\x55\x56\x26\x76\x2c\x5a\xac\x2b\x5a\xac\x1b\xaa\xac\x1c\x2d\x56\x81\x2a\xeb\x8e\x16\xeb\x81\x2a\xab\x44\x8b\xf5\x44\x8b\xf5\x42\x8b\x55\xa1\xca\x06\xa0\xce\x06\xa2\xce\x06\xa1\xce\x86\xa0\xce\x86\xa1\xc5\x2e\x41\x8b\x5d\x8a\x3a\x1b\xe1\xee\xd1\x1c\x83\x3a\x1b\x8b\x3a\xab\x15\x2b\xf9\x16\xbb\x1a\x55\x76\x0d\x5a\x6c\x3c\xaa\x6c\x02\x64\x8b\xfd\x9b\x93\xd0\x60\x53\xd0\x60\xd3\xd0\x12\xfb\x37\x67\x8a\xd9\xd5\xd9\x6c\xd4\xd9\x0d\xa8\xb3\x39\xa8\xb2\xb9\xa8\xb3\x79\xa8\xb2\x9b\xd0\x62\x37\xa3\xce\x6e\x41\x9d\x2d\x44\x8d\xdd\x86\x3a\xbb\x43\x48\x81\xce\xee\x42\x5d\xec\x5c\x59\x86\xaa\xd8\xb1\xb2\x1a\x55\x76\x3f\x5a\x6c\x2d\x5a\x6c\x1d\x9a\x6c\x3d\xea\xec\x21\xd4\xd9\xc3\x62\xf7\x8a\xca\x1e\x41\x8b\x6d\x44\x95\x6d\x42\x8b\x6d\x46\x95\x3d\x26\xa4\xc8\x60\x5b\xd0\x60\xdb\xc4\x4e\x4b\x9d\xed\x44\x9d\xed\x42\x9d\xfd\x0e\x2d\xa6\xa0\xe5\xee\x74\x51\xdd\x9d\x2e\xaa\xd8\x45\xb0\x1f\x75\xf6\x1c\xea\x4c\x45\x8d\x1d\x10\xbb\x09\x2c\xf6\x82\xd8\x4d\x60\xb0\xc3\xa8\xb2\x97\x50\x67\x1a\x6a\xad\xd7\xa6\x85\xa4\xc5\x24\xeb\x5d\x47\x67\xc4\xac\x15\xbb\x33\xc1\x67\x81\xcf\x40\xa5\x8b\x3c\x47\x91\x23\xc8\xf5\xc0\xd9\x2b\x6a\xb1\xb9\x68\x09\x3d\xe0\x23\xe3\xa3\xe2\x23\xda\x2e\xb8\xb5\xd8\x6e\xb1\x57\xd4\x62\xfb\xd1\xe2\x9c\x81\x14\xfb\x0b\x8a\x5b\xdc\xdb\xf0\xdc\x3f\xf2\x33\x78\xf8\xa5\xcb\xc7\x75\x71\x5e\x74\x31\x53\x77\xb6\xc2\xcf\x93\x67\xe7\x89\x1d\x42\x1b\x46\xc4\x3d\xe9\x1e\xb4\x5b\xd1\x3d\x9b\xbe\x8d\x36\x7d\x17\x4d\xfa\x31\xda\xf4\x04\x1a\xf4\x24\x5a\xd4\x42\x83\xfe\x03\x2d\xfa\x35\x5a\xf4\x5b\x97\x7b\x82\x16\x93\xd0\x62\x14\xaa\x98\x0f\x2d\x26\xa3\xcd\x52\xd0\x60\x69\x50\xc5\x42\x68\xbb\x7a\x60\xb0\x62\xb1\x1b\x8a\x8f\xd0\x66\xdd\xc4\x28\x6d\x56\x21\x46\x6a\xb3\x1e\x62\xb4\x36\xeb\x85\x36\xab\x42\x8b\x9d\x0f\x55\x6c\x24\x54\xb1\x71\x68\xb3\xab\xc5\xe8\x6d\x36\x3e\x69\x16\xe6\xa0\x29\x66\x62\x1e\x9a\xae\x7c\x3a\xbb\x76\x13\x65\x92\xa3\x62\xb3\x0d\x02\x19\x9b\x6d\x14\xe8\xd8\x6c\x73\x1c\x1d\x2e\x5f\x96\x2b\x5f\x96\x2b\x57\x06\x7b\x1e\x6d\xf6\x02\x5a\xec\x30\x5a\xae\x3c\x35\xcb\x50\x65\x3c\xcf\xd9\x2d\xf6\xe1\xc4\xf6\xdf\xc4\xec\xb1\x9e\xb0\xc7\x3b\x4b\xcc\xad\xd7\x0e\x5b\xec\x42\xb4\xd8\xe5\x62\x97\x89\xee\xda\x61\xd5\xb5\xc3\xb1\xbd\x36\x7a\xab\xf6\xb7\x79\xbe\x1d\x3b\x7c\x0f\x5a\xec\xde\x04\xbb\x6b\xb1\x3d\x42\x4b\x2c\xb6\x0f\x55\x31\xdf\xce\xee\x6a\xcb\x93\x73\xb9\xf5\x00\x7a\x08\x6d\x2e\x81\x2c\x57\xec\xa4\x76\xa4\xeb\x3a\x8f\x84\xdf\x29\xb0\xb4\xd9\x32\xb4\xd9\x0a\xb4\xb9\x44\xc5\x6b\x08\x29\xb1\xe8\x89\x95\x8a\xbd\xd7\x36\xbb\x56\xec\xb1\xb6\xc5\x5e\xe9\x7d\x9e\x67\x01\x18\x7d\x0e\xe6\xb0\x75\x90\x1d\xd7\x83\xf3\xe2\x91\xd7\x6e\x21\x79\x16\x3d\x80\xb6\xf0\x6b\x87\xd0\xa2\x2f\xa3\x45\xff\x88\x16\x7d\x15\x6d\xfa\x86\xf0\x75\xa6\xf0\x75\xc7\x5c\x7d\x39\x8e\x36\xfd\x50\x48\xa4\x4d\x2d\x21\x69\x5c\xc2\x2c\x96\x87\x36\x2b\x74\x47\x12\xe3\x69\x28\x5a\xec\x62\xb4\xd9\x28\xb4\xc5\xbe\xfa\x18\x8f\x53\x85\x8f\xb3\xe3\x23\x9e\x8f\x16\xbb\x05\x2d\xb6\x10\x6d\x77\xd4\x16\x5b\x26\xf6\xe1\x59\xec\x57\x68\xb1\x5f\xa3\xcd\x1e\x45\x5b\xf8\xbd\xdf\xba\xfe\x8e\xeb\xd7\xb3\x68\xb1\xdf\xbb\xfb\xc3\xf7\x09\xe9\xb1\x98\x8a\x36\x3b\x88\x36\x7b\x09\x2d\xa6\x79\x22\xcb\xf8\x2a\xb6\xbb\xbb\x50\x17\xbb\x0b\xf9\x48\xdf\x40\x4d\x8c\xee\x84\xf0\x5f\x3a\x4b\x11\xbe\x43\x67\x79\xa8\xb3\x0e\xee\x28\xa6\xc6\xb9\xd4\xd8\x42\x61\x77\x75\xb6\x0c\x75\xb6\x02\x75\xc1\x61\x8c\x93\x28\x1a\x6c\x37\x1a\xee\x8e\x40\xdd\xdd\x09\xd8\xbc\x8a\xdd\xcf\x83\xbd\xe5\x62\x6f\xd1\x83\x68\x26\x61\x6f\x79\xb0\x37\x05\x77\xc7\xd1\xa2\x1f\x0a\x2e\x5b\xc3\x3d\x19\x73\x2e\xdb\x96\x8b\xb9\xc9\x26\xa3\xe9\x62\x9e\x88\x75\x4b\x9c\x2d\xf6\xa8\x88\x2f\x4c\xf6\x5b\x34\xd9\x56\x34\x7f\x04\x63\xab\x05\xc6\x84\x01\x64\x8b\x7a\x80\xee\xc6\x8b\x3c\x5a\x30\xe9\x49\xc1\xb3\x49\xff\x81\x36\xfd\x1a\x6d\xfa\x2d\xda\x8c\xa0\xcd\x24\xb4\x99\x4f\x8c\xc5\x64\x79\x68\xb2\x12\x61\x99\xb8\x55\xe2\x16\x89\x5b\x22\x6e\x7d\xb8\xe5\xb1\xd9\x42\x34\xd9\x6a\x61\x49\xb8\x15\xe1\x16\xc4\x66\x75\x68\xb3\x7a\xb4\x99\x8a\x26\x7b\x01\x6d\x76\x18\x6d\xa6\xa1\x99\xf4\x64\x88\x93\xb9\x74\x12\xf6\xf3\x6c\xb6\xd3\x27\x62\x02\x4b\xd8\xc5\x0a\xe1\xff\x2d\x61\x07\xaf\x16\xbe\xbb\xd9\xee\xcd\x11\xf6\xce\xb1\xf6\xab\x85\x5f\xb5\x84\x4d\x8b\xd9\x33\x6e\xcb\xea\x85\x3f\x14\xb6\x0b\x0a\xe2\xf1\x37\x8f\x96\xbe\x41\x9b\x9e\x42\x5b\x44\x3f\xdf\xa1\x4d\xbf\x47\x9b\xa5\xa3\x2d\x22\x89\xd1\x68\xb3\x89\x68\xbb\x51\x81\xcd\x66\xa2\xcd\x66\xa1\x2d\x22\x80\x45\x68\x0b\xcf\xfe\x04\xda\x6c\x0b\xda\x6c\x1b\xda\x6c\x3b\xda\x71\x2f\xbd\x17\x6d\xb6\x1f\x6d\xf6\xa2\xa7\x5e\x9e\x1a\x97\xb4\x13\xc2\x6f\x58\x2c\x45\x48\x0b\x9f\x79\x3e\x83\x7c\xe6\x9a\xad\x44\xe7\x78\x96\xe1\xf0\xa9\xd3\x53\x68\xba\x7c\x1a\x62\x1f\x63\xba\x78\xe6\xc3\x8a\x47\x4d\x3c\x32\x72\xf8\xd6\xc5\x3e\xc5\x49\x68\xb2\x29\x68\xba\xfc\x73\xbb\x69\xb0\x59\x68\xc4\x11\x73\xc6\x61\x88\x71\xac\x13\x63\x31\xd9\x16\x34\xd9\x36\x34\xd9\x76\x34\x3c\x63\x71\x22\x8c\x17\x51\x6f\x99\xc5\xc4\x6c\x58\x7c\x94\x05\x9e\xf8\xdc\xd1\xa5\xa3\x62\x1f\xa6\x21\xf4\xe5\x9b\x56\x9f\xf3\xb1\x12\x76\x16\xc6\xf4\x63\xba\xe0\xdb\x79\xce\xe7\x3a\x34\xc4\x33\x28\x4f\xba\x71\xf4\x3e\xb1\x5f\xd2\x4a\x88\x9f\xfb\xc4\xbd\x90\x57\xae\x62\xc8\x39\xf2\x65\x0a\xe4\xbc\x32\x16\x43\xb1\xc8\xf5\xc5\x31\x34\xbd\x72\xd7\xd3\x95\x3d\x8e\x6c\x4c\xfe\x26\xba\x19\xc2\x94\x38\xba\x26\x9b\xe5\x3e\x35\xe3\xc8\xa3\xd9\x42\x1e\x13\x11\x36\xe3\xb2\xb9\x57\xec\x02\xd5\x84\x8c\xbe\x88\x3a\x97\xd3\xb8\x77\x92\xd8\x1e\xb4\xd9\x3e\xb4\x21\x0f\xd2\xb9\xb7\x42\x95\xaa\xc2\x3a\x19\xf4\x65\x34\xe9\x1b\x68\x26\xc8\x53\x2e\x1a\x42\xa6\x6e\x41\x53\xc8\xd5\xdd\x68\xb0\x65\x68\xb0\x15\x68\x78\x6c\xa1\x29\xe4\xed\x25\x34\x5d\x99\x53\xfd\xdb\x50\x85\xf5\x09\x76\x62\x37\x64\xbb\x59\x88\x41\x0f\x40\x36\x3d\x84\x1a\x7d\x19\x0d\xfa\x06\x1a\x49\x99\x88\x49\x8f\x43\x36\xfd\x14\x4d\xfa\x99\xe0\x46\xa7\x27\xd1\xf0\x64\x23\x26\xfd\x1c\x4d\xfa\x05\x9a\xdc\x9a\xd3\xbf\xa3\x49\xbf\x14\xb6\xc7\xa0\x5f\xa1\x49\xff\x89\x26\xfd\x5a\x64\x21\x86\x9b\x85\x98\x6e\x16\x62\xd2\xd3\x68\xd2\x1f\xd0\xa4\x67\xd0\x74\x33\x10\x9e\x7d\x18\x4c\x42\x83\x51\xc8\x66\x0c\x4d\xe6\x43\xc3\xdd\x67\xae\xb3\x54\x34\x59\x1a\x64\xb3\x36\x68\xb2\xb6\x68\xb2\x0c\x34\x45\x2c\xd9\x0e\x4d\x96\x8b\x9a\xf0\x20\xed\xd1\x64\x1d\xd1\x62\x05\x68\xb2\x22\x34\xdd\xec\xc3\x70\xb3\x0e\xc3\xcd\x3a\x0c\x37\xeb\x30\xe2\x31\x67\x15\x1a\x6c\x00\x9a\xec\x7c\xc8\x66\x03\xd1\x64\x83\xd0\x64\x43\xd0\xf4\x64\x1d\x26\x1b\x81\x26\x1b\x09\xd9\x6c\x14\x64\xb3\x31\x68\xb2\xb1\x68\xb2\x5a\x34\xdd\xcc\xc3\x70\x33\x0f\x43\x64\x1e\x5c\x2f\xa7\x43\xb6\x27\xdb\x30\x5b\x44\x71\x4e\xb6\xc1\xa3\x39\x43\x78\xb9\xdb\xd0\x64\x77\xa0\xe9\x66\x1b\x26\xbb\x1b\x35\xb6\x0c\x35\xb6\x02\x35\xb6\xda\xd5\x65\x9e\x6d\xac\x47\x93\x3d\x84\xa6\x9b\x69\x18\x6e\xa6\x61\xb8\x99\x86\x21\x32\x0d\x27\xbb\x30\xd9\x2e\x34\x3d\xd9\x85\xce\xea\x84\x94\xe8\xac\x1e\x8d\x78\x8c\xfc\x1c\x1a\xc2\x7b\x1e\x40\xd3\xcd\x2e\x0c\x76\x10\xb2\xd9\x61\x34\xd8\x4b\x68\x08\x8f\xda\x9a\x8d\x8f\xc4\xf2\x77\xd7\xeb\x58\xae\xd7\x89\xdb\xfc\x04\x5d\x6c\xf6\x3a\x67\xb7\xfb\x0b\x5b\xd1\xab\x98\x1e\x39\x5e\xc7\x89\x51\x35\x4f\xcd\x60\x83\x78\x7e\xce\x4b\x29\x89\x24\x9e\x4d\xf4\xd2\x73\x50\x95\x40\x07\xd0\x4c\xa0\xa3\x49\x64\xb8\x36\xce\x88\xdb\x3a\x33\x81\xbe\x71\x6d\x5f\x8c\xbe\x4b\xa2\xef\x13\x49\xd8\x47\x2f\x71\x5b\xe9\xa5\xce\x49\x34\x2a\x89\x46\xbb\x36\x75\x74\xdc\xb6\x9a\x09\x34\x51\x58\xb0\x66\xba\x36\x89\x26\x27\xd1\x74\x61\x8f\x9b\x69\x86\x6b\x9b\x67\x78\x6c\xb4\x97\x66\xba\x1e\x7a\x66\x3c\x3f\x33\x12\x68\x96\xeb\xbd\x63\x74\xa7\x6b\xdf\x63\xb4\xc8\xf5\xe8\x31\x7a\xd2\xb5\xfd\x31\xda\xee\x7a\xf7\x18\xed\x49\xa2\xbd\x68\x26\xd0\x3e\x37\x56\x8a\xd1\x7e\x34\x13\xe8\x60\x12\xbd\xe8\xf8\x96\x18\x89\x67\x1b\xbd\xb4\x35\x91\x84\x3f\x14\x92\xe4\xf1\x87\xce\xbf\x94\x0a\x1b\xfa\x1c\xcc\xf1\xe4\xb9\xb1\x67\x5e\x0d\x31\xd7\xdc\x3e\x85\xa1\x40\x78\xa0\xb3\xe5\xbb\xa3\x3d\x39\xef\x44\x17\xf3\x98\x3f\x4f\x7e\x56\x93\xfb\xf4\xc4\x3c\xdc\x48\xc8\x75\x5f\x44\x4b\xc4\x5e\xb6\x37\xfa\xe3\xd1\x4f\x42\x04\xf8\x63\x91\x5f\x2c\x12\xe2\x51\x50\x72\x04\xb8\xdd\x13\x05\xc6\xee\xea\x46\x82\xb0\x53\xec\xf8\xf5\x52\x4a\x22\x89\xfc\xd1\x4b\x2d\xf5\x50\x4f\xa0\xa3\xb8\x3d\x81\x0c\xd4\x12\xe8\xb8\x9b\x7f\x1e\x8f\xe7\xa1\x46\x02\xb5\xd4\x43\xc3\x4b\xe2\xa9\x5f\x2f\x95\xa2\x9a\x40\x9d\x93\x68\x94\x78\x6e\xa4\x99\x46\x8b\xa7\x26\x9a\x69\x02\x6e\x4f\xa0\x89\x22\xe6\x69\xa6\x6b\xc5\xf3\x25\xcd\x34\x39\x89\xa6\x27\xd1\x0c\xf1\x14\x46\x33\xfd\x12\xb5\x04\x6a\xa9\x87\x5a\x02\x25\xeb\xe1\x0d\xc2\x07\x35\xd3\x1c\x37\xc2\x8e\xd1\x5c\xe1\x9b\x9a\x69\x9e\x1b\xed\xc4\xe8\x4e\xf1\xdc\x4b\x33\xb5\xd4\x63\x2d\x81\x5a\xea\xf1\xf6\x04\xda\x2b\x64\xb7\x99\xf6\xe1\xf6\x04\xda\x8f\x46\x02\x1d\x14\x71\x61\x33\xbd\x28\x9e\x4e\x89\x93\xd8\x41\xed\xa5\xad\x89\x04\xf9\xf1\x18\xd2\x79\x62\xc8\x12\xf1\x62\x72\x94\xdd\x1c\x61\x7b\xe3\xbf\x96\xf9\xc8\x76\x61\x89\x54\xb6\xdf\x79\xb2\x27\x1e\xd3\xb5\xf5\xc4\xc6\xdc\x3f\x34\xe7\x8a\xcd\x39\xa2\x93\x97\x4f\xf7\xe4\x79\x07\xd1\x82\x65\x9e\x1a\x95\x13\x99\xb5\x16\x95\x71\x0b\xf3\x89\xa8\x0f\x7b\x23\x32\xfd\x47\x22\x31\xdd\x13\x89\xe9\xf4\x5b\xd4\xdd\x28\xcc\x68\x11\x85\xf1\x08\x0c\x84\xdf\xd6\x99\x84\xba\x27\x0a\xd3\x99\x8c\xc6\x7f\x19\x85\x59\x6e\x14\xa6\xbb\x51\x98\xee\x46\x61\xba\x1b\x85\xe9\x9e\x28\x4c\x6f\x35\x0a\xf3\x46\x5f\x2d\x23\x2f\xdd\x8d\xbc\x9a\xb3\xa0\xd9\x42\xba\x0d\x36\x0f\x8d\xb3\x44\x58\x46\x3c\xc2\x5a\x2a\x62\x68\x8d\x2d\x17\x71\xb4\xc6\x56\xa2\xc1\x56\xa3\xce\xee\x41\x9b\xad\x41\x83\xdd\x8b\x36\xbb\x0f\x8d\xa4\xa8\x4b\x77\xa3\x2e\xdd\x8d\xba\x74\x61\x89\x63\x11\x17\x8f\xc5\xeb\x50\x17\xf1\x78\xbd\x58\x19\x38\x5b\xa4\xa5\xb3\x43\xc2\x7e\xea\xf1\x48\x2b\x56\x77\xf3\x66\x94\xcd\x35\x88\x3c\x91\x9b\xdb\xa2\x26\xe0\xad\x05\x74\xf3\xbc\x89\x21\x26\x7d\x5a\x42\x66\x76\xca\xf1\x03\xee\x8a\x89\x7d\x96\x2c\x4d\x8b\xaf\x90\x38\x16\xc9\xf2\xbc\x8d\xc1\x76\xbd\xbb\xed\x7a\x71\x3b\x21\x43\x76\x3c\xb7\xcd\xf6\xb8\x1e\x69\x9f\xd0\x5a\xcb\x93\xc9\x39\x3e\x33\x0b\x7c\xa8\x43\x8a\x5b\x37\x3c\xe5\x59\xc3\x19\xed\xfa\xbf\x66\xcd\x73\xd6\x5d\xb6\xb8\xeb\x2d\x7b\x5d\x3b\xe0\x5c\x4d\xf7\x6f\x45\x1d\x02\xf4\xa8\x47\xc3\x26\x08\xde\x63\x95\x39\x27\xb3\x7a\xe6\x27\xe3\xc3\x64\x3f\x74\x54\xa0\xd7\x4c\xef\x26\x51\x72\x3c\xf8\x8d\xf0\xf9\xcd\xd4\xd2\xef\x98\x5e\x12\xef\x72\xf0\x52\xcb\x78\xd0\x4a\xa0\x32\xb4\x13\xa8\x33\x5a\x09\xd4\x05\xed\x04\xea\x99\x44\xa3\x45\xcc\xd8\x4c\x13\xc4\x4c\x37\xd3\x44\x11\x33\x36\x53\x72\xbc\x38\x09\xed\x04\x4a\x8e\x1f\xa7\xa0\x9d\x40\x33\x44\x0c\xd9\x4c\xff\x6b\xfc\xf8\xbf\xfb\xad\xff\x6f\xe3\xcf\x17\x13\xe9\x27\xe3\x4d\x9f\xa8\x95\xc5\x7c\x8e\xeb\x6b\x60\x60\x5c\x6f\x62\x4f\x71\x3a\x75\x4c\x93\xfe\x51\xe4\x29\xaa\x5b\xbb\xe4\xf9\x8a\x29\x9e\xee\x74\x6a\x4b\xb1\xba\x92\xf3\x1e\x91\x5c\x34\x59\x07\x91\x83\x34\xe7\x1a\x43\xdd\x3c\xd7\x79\x0a\xd4\x74\xeb\xf3\xde\x5a\xa6\x53\x67\x72\x9e\x0a\xe5\xf3\x69\xba\xf3\x66\x0a\x0e\xe7\xbb\xb9\xec\x9d\xc2\xb2\x5a\xec\x6e\x34\xd9\x32\x34\xd9\x0a\x34\xd9\xaf\xd0\x14\x79\xab\xb7\xc6\xf9\xa4\xa8\x90\x58\xec\x59\x37\x37\xfd\x3d\x9a\x22\x3f\xdd\xe3\xae\xdb\xec\x73\xad\xa5\xf3\xf4\xa9\x19\xd7\xf5\x82\x38\x02\xb1\x91\x71\xeb\xe1\x1d\x5d\x7a\xbc\x4a\xe6\x48\xb2\x53\x1d\x33\xe3\x58\xde\xe4\xe2\x79\x7f\x92\x65\xe1\xdc\xb4\xac\x88\x35\xdf\x39\x37\x6e\x8b\x0f\xa1\x2d\x6a\xc6\x47\x9d\x1a\xbd\x58\x4d\xf0\xd6\x82\xbd\x16\x28\x56\xc5\xf6\xae\x2a\x78\xaa\xd7\x71\xdb\x9d\x15\x5f\xa3\x68\x88\x57\x2c\x63\x95\x4a\x9b\x4d\x13\x55\x49\x9b\xdd\x9f\x64\x6f\x7f\x87\x36\x53\x12\x6a\x74\xce\x5a\x45\xb9\xa7\x46\xe7\xe4\xb3\x87\xdc\x3a\xf7\x51\xb7\xb6\xed\xac\x2b\x98\xf1\x7a\x5d\xae\xbb\x1e\x57\xea\xda\x93\xa1\x42\x16\x5a\x7f\x3f\xcf\xd4\x84\x77\xf4\x34\xaf\x27\xb4\xb6\x8e\xd0\xda\x9a\x41\xf3\x7b\x7a\x9c\xba\x9e\x04\xbf\x01\x1f\xf8\x00\x20\x05\x52\x81\x40\x3a\x84\x80\x42\x09\x74\x05\x19\x7a\x40\x25\xa4\x41\x15\xf4\x86\xb6\xd0\x0f\xce\x87\x10\x0c\x86\x21\x90\x0f\xc3\xe0\x62\xe8\x08\xc3\xdd\x9d\x88\x23\xa0\x10\x46\xc2\x15\x10\x86\x2b\xe1\x4a\x28\x81\xab\xe0\x2a\x28\x85\x71\x30\x1e\xca\x60\x22\x4c\x84\x6e\xb0\x14\x7e\x05\xe5\xb0\x0e\xd6\x41\x3f\x58\x0f\x1b\xe0\x1c\xd8\x08\x4f\xc0\x79\xb0\x05\x76\xc0\x60\xd8\x05\xcf\xc2\x25\x50\x07\x75\x30\x02\xea\x61\x2f\x5c\x0e\xfb\x61\x3f\x8c\x06\x15\x54\xb8\x02\x0e\xc2\xab\x30\x06\x8e\xc0\x11\x98\x08\x6f\xc0\x1b\x70\x2d\xe8\xa0\xc3\x24\xf8\x33\xbc\x0d\x93\xe1\x1d\xf8\x00\xa6\x41\x03\x34\xc0\x1c\xf8\x0e\xbe\x87\xb9\x70\x06\xce\xc0\x4d\x80\x84\xc0\x02\x42\x09\x85\x85\x24\x40\x02\x70\x2b\x69\x4b\xda\xc2\x6d\x24\x83\x64\xc0\xed\x24\x93\x64\xc2\x1d\x24\x9b\x64\xc3\x9d\x24\x97\xe4\xc2\x22\x92\x4f\xf2\x61\x31\xe9\x40\x3a\xc0\x5d\xa4\x84\x74\x81\x25\xa4\x1b\xe9\x06\x2b\x48\x05\xa9\x80\x95\xa4\x07\xe9\x01\xab\x48\x4f\xd2\x13\x56\x93\x2a\x52\x05\xf7\x90\xde\xa4\x37\xac\x21\x7d\xc9\xb9\x70\x2f\x39\x8f\x9c\x07\xbf\x21\x17\x90\x0b\x60\x1d\x99\x4a\xa6\xc2\x03\x64\x3e\x99\x0f\xeb\xc9\x01\xf2\x02\x3c\x48\x5e\x24\x2f\xc2\x06\xf2\x3e\xf9\x00\x1e\xa1\xe7\xd2\x73\x61\x13\x1d\x48\x87\xc2\x66\x7a\x31\xbd\x18\xb6\xd1\xe1\x74\x38\x3c\x49\x2f\xa3\x23\x60\x3b\x1d\x4d\x47\xc3\x4e\x3a\x86\x8e\x81\xa7\xe8\x58\x7a\x0d\xec\xa2\x13\xe8\x44\x50\xe8\x24\x3a\x19\xea\xe8\x54\x3a\x15\xea\xe9\x74\x3a\x1d\xf6\xd0\x99\xf4\x06\xd8\x4b\xe7\xd2\xb9\x70\x80\xde\x48\x6f\x84\xe7\xe9\x4d\xf4\x26\x78\x81\xde\x4c\x6f\x86\x83\xf4\x56\x7a\x1b\xbc\x48\xef\xa4\x77\xc2\x61\xba\x98\x2e\x86\x97\xe8\x52\xba\x0c\x34\xba\x9b\xee\x85\x57\xa8\x4a\x9f\x87\x23\xf4\x20\x3d\x08\x3a\x3d\x44\x5f\x86\x37\xe9\x1f\xe9\xab\xf0\x0e\x7d\x9d\xbe\x0e\xc7\xe8\x9b\xf4\x4d\x78\x8f\xbe\x45\xdf\x03\x83\xfe\x95\x1e\x87\x8f\xe8\x07\xf4\x23\xf8\x84\x7e\x42\x3f\x81\xcf\xe8\xa7\xf4\x6f\x70\x82\x7e\x41\xbf\x80\x2f\xe8\x3f\xe8\x3f\xc0\xa2\xff\xa4\xff\x84\xbf\xd3\x6f\xe8\xbf\xe0\x4b\x7a\x9a\x7e\x0f\xdf\xd0\x33\x14\xe1\x5b\x46\x18\x83\xef\x58\x0a\x6b\x03\x3f\xb0\x74\x96\x4e\x80\x85\x58\x0e\x21\x2c\x97\x75\x20\x32\xeb\xc4\x3a\x91\x54\x56\xc8\x0a\x49\x1a\x8b\xb0\x5e\xa4\x0d\x3b\x97\x5d\x43\x0a\xd8\x04\x36\x93\x5c\xc0\xae\x67\xf3\xc8\x70\x36\x9f\x2d\x24\xa3\xd8\xed\xec\x0e\x72\x15\x5b\xcc\xee\x22\xe3\xd8\xdd\x6c\x39\xb9\x86\xad\x64\x2b\xc9\xb5\x6c\x35\xfb\x0d\x99\xc4\x1e\x66\xdb\xc8\x2c\xb6\x83\xed\x24\xb7\xb2\xa7\x99\x42\x6e\x67\xbb\xd9\x21\xb2\x84\xbd\xc4\x34\xf2\x6b\xdf\x76\xdf\x0e\xf2\x1b\xb9\x4c\x2e\x27\x0f\xc8\x17\xca\xb3\xc8\x23\xf2\x5c\xf9\x26\x72\x48\xbe\x59\xbe\x99\xbc\x22\x2f\x94\x17\x92\x3f\xca\xb7\xc9\xb7\x91\x57\xe5\x3b\xe4\x3b\xc8\x6b\xf2\x62\x79\x31\x39\x22\x2f\x91\x97\x90\xd7\xe5\xa5\xf2\x52\xf2\x86\xbc\x5c\x5e\x4e\xfe\x24\xaf\x94\x57\x11\x5d\xbe\x4f\xbe\x8f\xfc\x59\xbe\x5f\xbe\x9f\xbc\x25\xaf\x95\xd7\x92\xb7\xe5\x75\xf2\x3a\x72\x54\x5e\x2f\x6f\x26\xef\xc8\x9f\xc9\x9f\x91\x0f\xfc\x8f\xf8\x37\x91\x0f\xfd\x8f\xf9\x9f\x20\x9f\xf8\xb7\xf8\xb7\x90\xcf\xfc\xdb\xfc\xdb\xc8\x09\xff\x17\xfe\x2f\xc8\x49\xf7\x0d\x75\x29\x30\x08\xc6\x00\x9d\x7a\xdb\xfc\xd9\x90\xfd\xcb\xf9\xd3\xaf\x87\xf0\xec\xc9\x0b\xe6\x40\x85\x78\xf7\x1b\x20\x8a\x5e\x67\xfb\x4d\xa6\x4e\xbd\x61\x1e\x04\x00\x80\x8a\xeb\x49\xc0\x20\x05\x32\xa1\x3d\x14\x89\x7e\x04\xc2\x20\xf3\xa3\xef\x3e\xe7\x6f\xdf\x77\xce\x79\xfe\xfb\x80\xf8\x66\x81\x0f\x32\x48\x91\xd4\x9b\x0e\x61\xb5\xd0\x11\xfa\xc3\x20\xb8\x04\x46\xc3\xd5\x30\x05\x66\xc1\x7c\xb8\x1d\x96\xc2\x1a\x58\x07\x1b\x61\x0b\xec\x82\x3a\x50\xe1\x30\x1c\x81\xb7\xe1\xaf\x60\xc2\xe7\xf0\x35\x9c\x26\x40\x64\x92\x16\x78\x01\xa8\xf4\xb4\xf4\x74\xe0\x79\x71\xdc\x15\x38\x20\x8e\x4f\x05\xfe\x20\x8e\x3b\x03\xaa\x38\xee\x08\xec\x07\x2a\xed\x92\x9e\x0e\xec\x13\xc7\x5d\x81\xbd\xe2\xf8\x54\x60\x8f\x38\xee\x0c\xd4\x8b\xe3\x8e\x40\x1d\x50\xe9\x29\xe9\xe9\x40\x54\x1c\x77\x05\x14\x71\x7c\x2a\xf0\x7b\x71\xdc\x19\xf8\x9d\x38\xee\x08\x3c\x03\x54\xda\x29\x3d\x1d\x78\x5a\x1c\x77\x05\x76\x89\xe3\x53\x81\xa7\xc4\x71\x67\x60\xa7\x38\xee\x08\xec\x00\x2a\xed\x90\x9e\x0e\x6c\x17\xc7\x5d\x81\x27\xc5\xf1\xa9\xc0\x36\x71\xdc\x19\x78\x0e\x24\x69\x57\xe0\x20\x48\xd2\xd3\x81\x67\x41\x92\x76\x06\x76\x83\x24\x3d\xf5\x3f\x20\xf2\x57\x17\x91\xbf\xb8\x88\x18\x2e\x22\xef\xb9\x88\x1c\x73\x11\x79\xc7\x45\xe4\xa8\x8b\xc8\xdb\x2e\x22\x6f\xb9\x88\xfc\xd9\x45\x44\x77\x11\xf9\x93\x8b\xc8\x1b\x2e\x22\xaf\xbb\x88\x1c\x71\x11\x79\xcd\x45\xe4\x55\x17\x91\x3f\xba\x88\xbc\xe2\x22\xa1\xb9\x48\xbc\xe4\x22\x71\xd8\x45\xe2\x90\x8b\xc4\x8b\xe2\xb8\x23\x70\x5c\x60\xf1\x26\x47\x21\xf0\x32\x48\xd2\x8e\xc0\xbb\x1c\xa3\xff\x01\x11\xdb\x45\xe4\x5b\x17\x91\x53\x2e\x22\xdf\xb8\x88\x7c\xed\x22\xf2\x95\x8b\xc8\x3f\x5c\x44\xbe\x74\x11\xf9\xbb\x8b\x88\xe5\x22\xf2\x85\x8b\xc8\xe7\x2e\x22\x8d\x2e\x12\x7f\x73\x91\x38\xe9\x22\x71\xc2\x45\xe2\x33\x17\x89\x4f\x5d\xd9\x30\x5d\x44\x3e\x76\x11\xf9\xc8\x45\xe4\x43\x17\x91\x0f\x5c\x44\xde\x77\x11\xf9\xa7\x90\x91\x7f\x09\x5c\x3e\x11\x88\x34\x88\xb7\xa6\xfe\xd7\x88\x04\x33\x1d\x44\x82\x21\x07\x91\x60\x86\x83\x48\x30\xdd\x41\x24\xd8\xd6\x41\x24\xd8\xc6\x41\x24\x98\xe6\x20\x11\x4c\x75\x90\x08\xa6\x38\x48\x04\x03\x0e\x12\x41\xbf\x83\x44\x50\x76\x64\x23\xe8\x73\x10\x09\x32\x07\x91\xa0\xe4\x20\x12\x24\x0e\x22\x41\x70\x11\x41\x17\x91\x26\x17\x91\x1f\x5c\x44\xbe\x77\x11\x39\xed\x22\xf2\x6f\x17\x91\xef\x1c\x44\x82\x41\x2e\x1d\xc1\x2c\x81\xc8\x19\x8e\x48\x90\xfe\x8f\x88\x54\xba\x48\xf4\x70\x91\xe8\xee\x22\x51\xe1\x22\xd1\xcd\x45\xa2\xab\x23\x1b\xc1\x2e\x2e\x22\x9d\x5d\x44\xca\x5c\x44\x4a\x5c\x44\x8a\x5d\x44\x8a\x5c\x44\x22\x2e\x22\x61\x17\x91\x02\x17\x91\x4e\x2e\x22\x1d\x1d\x44\x82\x1d\x1c\x44\x82\xed\x1d\x44\x82\x79\x0e\x22\xc1\x5c\x07\x91\x60\x3b\x07\x91\x60\x8e\x83\x48\x30\xdb\x45\xa4\x54\x20\x52\xce\x25\x25\x98\x2f\x10\x29\x74\xde\xac\x0b\x84\x9f\x1f\xb7\xd2\x99\x40\xa0\xa3\xb0\xc3\x14\x08\x50\xb8\x14\x2e\x93\xba\x81\x04\x6d\xa5\xc3\xd2\x31\x00\xe9\x7d\xe9\x7d\xc8\x91\x90\x12\x68\x47\x19\x95\x21\x9f\x06\x68\x00\x3a\xd2\x34\xda\x16\x3a\xd1\x4c\x9a\x0d\x61\x9a\x4f\xf3\xa1\x98\x76\xa2\x9d\xa0\x44\xbc\x75\xb8\x54\xbc\x75\xb8\xca\xf7\x88\x6f\x23\xf4\xf5\x6d\xf6\x6d\x81\x73\x7c\xdb\x7c\xdb\xe0\x02\x20\x64\x1d\x50\x48\x83\x39\x04\x20\x00\x99\xd0\x11\xca\xa0\x27\xf4\x87\xc1\x30\x02\x6a\x83\xfd\x80\x49\xaf\x4a\xc7\xa4\x97\x82\x7d\xdd\x5f\x87\x83\x7d\xc4\xaf\x77\xa5\x97\x82\xbd\xdd\x5f\x87\x83\xd5\xc0\xa4\x57\x44\xbf\x2a\xf7\xd7\xe1\x60\x2f\xf1\x8b\xf7\xeb\xe9\xfe\x3a\x0c\x69\xd0\x1e\x4a\xa0\x07\x9c\x03\x83\xe0\x52\x18\x0b\x93\x60\x16\x2c\x80\xc5\xb0\x3a\x38\x1c\x98\x74\x44\x7a\x55\x7a\x29\x78\x89\xfb\xeb\x70\xf0\x62\xf1\xeb\x15\xe9\xa5\xe0\x30\xf7\xd7\xe1\xe0\x05\x71\x8e\xce\x8f\x73\x74\x5e\x9c\xa3\x01\x71\x8e\xce\x8d\x73\xd4\x3f\xce\x51\x4d\x9c\xa3\x73\x7e\x06\x47\x97\xc7\x39\x1a\x11\xe7\xe8\xb2\x38\x47\x97\xc6\x39\x1a\x1a\xe7\x68\x48\x9c\xa3\x8b\xe2\x1c\x0d\x8e\x73\x74\x61\x9c\xa3\x41\x71\x8e\x7e\x11\xe7\x68\x60\x9c\x23\x02\x94\x4e\xa5\xd7\xd3\x85\x20\x41\x1a\x50\xf8\x86\xfc\xdb\x37\xc6\x23\x09\xd4\x17\x96\x0e\x80\x0f\x98\x6f\xa3\xaf\x1a\x80\x14\x3a\x47\xfa\x16\xcc\x90\x20\x20\x49\xa9\x01\x89\xf9\x98\x24\xb1\x8f\x41\xc2\x81\x70\x2b\x02\x40\x84\x47\x05\x97\x5d\x3e\xe2\x72\x08\x43\x1b\x3c\x23\xcf\x68\x9a\x01\x10\xf8\x95\xb4\x24\x0c\xe4\xf1\x8f\xde\x03\x60\x13\x7d\x7b\x01\x20\x0c\x79\xae\x1c\x72\x72\xa4\x10\xe8\x29\x21\x89\xfc\x6f\x46\x0d\x00\xf8\x1a\x96\x80\x0c\xf3\xc5\xdb\x67\x17\xd3\xb9\xf4\x66\xba\x98\xae\xa1\xf7\xd1\xdf\x52\xdd\xd7\xb9\xd3\x91\x82\x4d\x05\x8f\x15\xfc\xbb\x30\xa7\xb0\x53\xe1\x45\x85\x97\x15\x5e\x55\x38\xae\xf0\x9a\xc2\x09\x85\x8b\x0a\xeb\x0b\xb5\xc2\xa3\x85\xc7\x0b\xff\x51\x78\xaa\xb0\x29\x5c\x14\x2e\x0b\xf7\x0c\xf7\x0e\xf7\x0f\x0f\x08\x9f\x1f\x1e\x1c\xbe\x36\x3c\x2f\x7c\x5b\xf8\xae\xf0\xfa\xf0\x53\xe1\x3d\x61\x35\xfc\x55\xc4\x17\xc9\x8a\xe4\x46\x8a\x22\x65\x91\x1e\x91\x11\x91\x31\x91\x89\x91\xe5\x91\x07\x23\x3b\x8b\xa4\x22\xb9\x28\xbd\x28\xb3\x28\xa7\xa8\x7d\x51\x61\x51\xd7\xa2\xf2\xa2\x61\x45\x93\x8b\xa6\x17\x4b\xc5\x19\xc5\x91\x52\x28\x95\x4a\xd3\x4a\x33\x4a\xb3\x4b\xf3\x4a\x3b\x96\x96\x94\x56\x94\xf6\x2e\x1d\x50\x3a\xbb\x74\x49\xe9\xf2\xd2\xd5\xa5\xf7\x95\x3e\x50\xfa\xdb\xd2\x67\x4a\xeb\x4a\xd5\xd2\x03\xa5\x5a\xe9\x1b\xa5\x6f\x96\xfe\xa5\xf4\x64\xd9\x80\xb2\x81\x65\x83\xca\x26\x95\x4d\x2d\x9b\x51\x76\x7d\xd9\xdc\x8a\x1b\x2a\x16\xf6\xc8\xdd\x11\xd9\x71\xdf\xc7\xf0\x3d\x6b\x2a\x6e\x42\x3c\x83\x28\xde\xbc\xdb\x06\xc2\xf0\x04\x5d\x40\x6f\xa7\xcb\xe9\x7d\xf4\x7e\xba\x95\xfe\xb9\x13\x74\x6a\x2a\x78\xac\xe0\x89\x42\x28\xcc\x2b\x0c\x17\x0e\x2b\x1c\xe9\x8e\xf9\xda\xc2\x25\x85\x7b\x0b\x5f\x29\x3c\x56\xf8\x41\xe1\xd7\x85\x76\x18\xc2\x65\xe1\x6e\xe1\xaa\x70\x8d\x3b\xe6\x89\xe1\x59\xe1\x05\xe1\xbb\xc2\x6b\xc3\x4f\x84\x9f\x0e\x3f\xe7\x8e\xb9\x9d\x3b\xe6\xcb\x22\x57\x44\xae\x89\x2c\x8f\xac\x8d\x8f\x39\x54\x94\x53\x94\x5f\x54\xe0\x8e\x79\x52\xd1\x34\x31\xe6\xf0\x59\xc6\x3c\x32\x3e\xe6\xb5\xa5\x4f\x94\xee\x8a\x8f\xf9\x48\xe9\x9b\xa5\x46\xe9\xc9\xb2\xfe\xf1\x31\x4f\x2f\x9b\x55\x36\xb7\x62\x52\xc5\x8d\x3d\x72\x77\xe4\xee\x58\xfd\x31\x7c\x4f\x9a\xc2\x4d\x88\x3f\xf0\x48\x12\xbf\xc5\x4f\xf1\x30\xbe\x80\x2a\xee\xc1\x7a\xdc\x8d\x75\x18\x6d\xf8\x4b\xc3\xf6\x86\x6d\x0d\x5b\x1b\x1e\x6d\xd8\xd4\xf0\x48\xc3\xc3\x0d\x0f\x36\xac\x6f\x78\xa0\x61\x5d\xc3\x6f\x1a\x7e\xdd\x70\x7f\xc3\xaf\x1a\xee\x6d\x58\xd3\xb0\xba\x61\x55\xc3\xca\x86\x65\x0d\x4b\x1a\xee\x6a\xb8\xa3\xe1\xf6\x86\xdb\x1a\x16\x34\x5c\xd3\x30\xaa\x61\x44\xc3\xc5\x0d\x35\x0d\x3d\x1a\xba\x37\x74\x3b\xf9\xed\xc9\x4f\x4e\xbe\x73\xf2\xed\x93\xaf\x9e\x7c\xf9\xe4\x0b\x27\x9f\x38\xb9\xf9\xe4\x43\x27\x6f\x3c\x39\xe3\xe4\x98\x13\xdf\x9f\xf8\xee\xc4\x57\x27\xfe\x71\xe2\xef\x27\x3e\x3f\xd1\x70\xe2\xc3\x13\x1f\x9c\x38\x74\x62\xd7\x89\x9d\x27\xd2\x3e\xc3\xcf\xbe\xfa\x34\xf3\xd3\xd0\xa7\x81\x4f\x7d\x9f\x4a\x26\x9a\x3f\x98\xdf\x9a\x5f\x9a\x0d\xe6\xc7\xe6\x9f\x4c\xd5\xdc\x67\xd6\x9b\x51\xf3\x77\xe6\x16\x73\xa3\xf9\xa0\x79\xbf\xf9\x2b\x73\xa5\x79\xb7\x79\x97\xb9\xd0\xbc\xde\xcc\x33\x73\xcc\xec\x4f\xfe\xf5\xc9\xb7\x9f\x9c\xfa\xe4\x9f\x9f\x7c\x79\xbc\xe9\xf8\xf7\x7f\x1d\x3f\x79\xc2\xa4\x7f\x75\x59\xde\x66\x79\xca\x75\xc1\xfb\x03\xeb\xdc\xf7\x2b\xff\xff\xeb\x3f\x59\x4a\x01\x27\xe5\x48\x1e\x3d\x11\x2f\x9b\x07\x80\xf8\xf1\x6c\xff\x39\x67\x52\xf1\xcc\xb0\x0c\x7e\x08\x40\x50\x54\x09\xd2\xa0\x0d\xb4\x85\x74\xc8\x80\x10\x64\x42\x16\x64\x43\x0e\xb4\x83\x5c\xc8\x83\x7c\x68\x0f\x1d\xa0\x23\x74\x82\x02\x28\x84\x30\x44\xa0\x08\x8a\xa1\x04\x4a\xa1\x0c\x3a\x43\x17\xe8\x0a\xdd\xa0\x1c\x2a\xa0\xbb\xa8\x2d\xf4\x84\x5e\x50\x05\xd5\xd0\x1b\xfa\x40\x5f\xe8\x07\xe7\x40\x0d\xf4\x87\x73\x61\x00\x9c\x07\xe7\xc3\x05\x30\x10\x7e\x01\x83\xe0\x42\x18\x0c\x17\xc1\x10\x18\x2a\xea\x0e\x97\xc0\x70\x6e\x35\x61\x04\x5c\x0e\x23\x61\x14\x8c\x86\x2b\x60\x0c\x5c\x09\x63\xe1\x2a\xa8\x85\x71\x70\x35\x5c\x03\xe3\x61\x02\x4c\x84\x6b\x61\x12\x4c\x06\x80\x95\xb0\x0a\xee\x81\x7b\xe1\x01\xd8\x00\x8f\xc1\x56\xd8\x02\xdb\x60\x3b\x3c\x09\x3b\xe0\x29\x78\x1a\x76\xc1\x33\xf0\x2c\xfc\x1e\x7e\x07\x0a\x44\x61\x37\xec\x11\x35\x88\xfd\xb0\x0f\x0e\xc0\x1f\xe0\x79\x78\xc1\xbf\x1d\xe6\xc3\x34\x98\x0e\xd7\xf9\x77\xc2\xad\xf0\x5b\x98\x07\xd7\xfb\x3f\x87\x5b\x60\x56\x20\x05\x56\xc3\xc6\x80\x0f\x6e\x0a\xa4\x05\xda\xc0\x2f\x61\xa1\xff\x4c\x00\xfc\x48\xe7\x07\x02\x30\x1b\xee\xa4\xd7\xc0\x4e\x50\xe1\x6e\x98\x0a\x73\x02\x8c\x8c\x09\x04\xfd\x4d\x70\x03\x2c\xf2\x3f\x05\x53\x60\x29\xac\x80\x87\x49\x36\xc9\xf1\x3f\xe2\xdf\xe8\xdf\xe2\xdf\xea\x7f\xcc\xff\x38\x3c\x17\x18\x0e\x87\x48\x7f\xff\x7e\xff\x5f\xfc\xf5\xfe\x3d\x81\x15\x81\x95\xfe\x1d\x70\x9b\xff\x09\xff\x36\xbf\x02\xcb\xe1\x3e\x58\x06\xbf\x82\x35\xf0\x6b\x58\x0b\xbf\x81\xfb\xe1\x41\x78\x08\x00\xd6\xc3\x66\x78\x14\x36\xc1\x37\xd2\x6a\xe9\x31\xb8\x51\xda\x28\x6d\x92\x36\xc3\xed\xd2\xe3\xd2\xa3\xd2\x3d\x7c\x0a\xb9\x2f\x20\x12\x29\x87\xd7\xe1\x2f\x60\x42\x23\x7c\x0d\x36\x9c\x81\x26\xd2\x09\x14\xd2\x8b\x8c\x20\x39\xa4\x13\x29\x27\xbd\x48\x5f\x72\x01\xb9\x88\x04\xe0\x1d\x38\x45\xca\xe0\x35\x78\x01\xfe\x40\xda\xc0\x3e\x78\x14\x36\xc0\x0e\xf8\x0c\x9e\x85\xb7\x48\x88\xe4\x02\x28\x50\xa1\x40\xd6\x70\xe5\xd2\x91\xb5\xca\x25\xb7\x8c\x53\xa0\xf8\x82\x3c\x45\x2e\xaf\x3d\x6f\x9c\x68\x5b\x34\x2e\xfc\x8e\x42\xb2\x7a\xe4\x75\x57\x48\x45\xf8\xaf\x4a\x5a\x79\x77\x45\xaa\x18\x3e\xba\xf6\xa2\xe2\x71\x91\xee\x0a\xad\xb8\x2e\x2f\xac\x0c\x1c\x59\x1b\x51\x06\x8e\xeb\xae\xb0\x0a\x7e\x6a\xa4\x38\x72\x7b\xed\x07\x1d\xfe\x34\xae\xc3\xf0\xd1\xb5\xb5\x67\x3a\xfc\x7d\x5c\x87\xe2\x88\xe2\x2b\xaf\x55\x86\xdc\x32\x4e\xfc\xc3\xb8\x71\x79\xdd\x15\x5f\x45\x9b\xf1\x57\x77\x57\xe4\x8a\x68\x11\x59\x3d\xb2\x56\x09\xaf\x1e\x3f\xbe\x83\x02\xe3\xba\x2b\xfe\x8a\x68\x89\x68\x1a\x18\x6f\x0a\x54\x64\x86\xc2\x35\x95\xdd\x95\x60\x45\x78\x11\xbf\x89\xd6\xe1\x4f\xe3\xc2\x0a\x2d\xbd\xb8\x38\xac\xb0\xb2\x4b\x14\x18\x59\xbb\x66\xfa\x9a\xc9\x61\xfe\xe3\x9c\x0e\x91\xc8\xb8\x0e\x6b\xc4\x5f\xa3\x9d\xbf\xf8\x0d\x53\x1c\xee\x32\x3a\x64\x44\xc6\x75\x57\x52\x2b\xc2\x6f\x8b\xe1\xa4\x55\x84\x2b\x15\x7f\xf9\xf8\xda\x70\x78\x68\xf1\x90\xc9\xb3\xc2\xb5\xe1\x69\x53\x9c\x4b\xf0\x7e\x6d\xf8\x9d\xc3\x35\x95\xe1\x35\xe1\xa1\x6b\x86\x4c\x2e\x5e\x13\x5e\x53\x2c\x6e\x57\xcc\x2f\xae\x0c\x3c\xa7\x43\x64\x5c\x87\x62\xde\xa0\x0c\x9c\xce\xff\x18\xd7\x5d\x69\x2b\xee\x74\xde\xb1\xbc\x48\xa4\x43\xf8\xd8\x9a\xe1\xa3\x6b\xc3\x6b\x8a\x2f\x0e\x2b\x70\xa5\xcb\x5b\x44\x74\x4b\xaf\x28\x0e\x1f\x73\x6f\x5e\x1c\xae\x1d\x7e\x45\x87\x88\x42\xc6\xd5\xae\x51\x58\xd9\xc5\xc5\x6b\x8a\xc3\x6b\x2e\x5e\x53\x3c\x99\x9f\xe0\x9c\xc2\x0f\xdd\x95\x0c\x3e\x0d\x99\xe5\xdd\x95\x10\x1f\x00\xff\x91\x99\x34\x80\x35\xfc\x50\x3c\x79\xd6\x24\xef\x48\xf8\xa9\x59\x15\xe1\x35\xe1\x35\xab\x38\x6c\x97\x4c\x2b\x5e\xe3\x57\xc2\x23\x6b\x07\x74\x78\x71\x5c\x77\x25\xbb\x62\x37\x0c\x24\x03\x07\x0d\x22\xc3\xf7\x67\xc0\x54\x10\xdf\xbc\xf3\x95\xb5\xfc\x7b\x74\x6d\xf1\x94\xb0\x02\xc5\x83\x3a\x4c\x09\x2b\xa4\x78\xd0\xb8\xb0\x32\x70\x74\x6d\x1d\x84\xe1\xc2\xa9\x83\xea\x48\x98\x5c\x38\x75\x90\x12\x9e\xaa\xe4\x4f\xef\x18\xbb\x57\x4e\x85\x42\x2e\x9c\x5a\xac\xc0\x85\x53\x8b\xbb\x3b\x36\x88\x20\x42\x3a\x48\x70\x08\x80\xa5\xf8\xf6\x02\x05\x3f\x40\x75\x28\x12\x2a\x8d\x84\x22\x87\xe8\xc5\x67\x0a\xa5\xdb\xce\xac\xf2\xed\x3d\x7d\xc9\x4c\x76\x12\x24\xb8\x19\x4f\x90\xa3\xbe\xbd\x90\x0a\xe9\x70\x39\xd4\xa5\x49\x50\xae\x04\x2b\xeb\x29\x83\x2c\x56\x4e\x94\x8c\x4a\x05\x8e\x29\x69\x55\x51\x39\xa3\x51\x69\x23\x0e\xbb\xdb\xca\x10\x28\x8f\xa6\xe7\x35\x2a\xe9\x95\xd1\xb6\x79\x8d\xd1\x10\x29\x8f\xb6\x4d\x0f\x65\x46\x83\xb4\xa6\x06\xa2\x69\x34\x94\xa9\xb4\xad\xe9\xd9\xab\x5f\xef\xbe\xd5\x55\xed\x72\xb2\xe5\xe2\xa2\xb2\xac\x08\x2d\xbe\xf9\xea\xb1\x57\x5c\x33\x7e\xf4\x98\xf1\x8c\x5c\x5d\x7d\xea\xd7\x63\xc6\xd6\x8e\xbe\xfc\x9a\x71\xbe\x5b\x7f\xa8\x74\xec\xeb\x0a\xba\x9d\x0e\x72\x79\xbe\x14\xea\x80\xf3\xc2\xaa\x39\x2f\x01\x56\xae\xc8\x55\xa2\xc5\xfd\x93\x28\x81\x4a\x85\x1e\xab\x97\xf2\x20\xc4\xca\x15\x29\x23\xea\x27\xe5\xf5\xb2\xf8\x2b\x1a\x24\xe5\x51\xbf\x14\xca\x8c\x12\x56\x53\x03\x3d\x7b\xf1\x9b\x93\x08\x2d\x5e\x41\x72\xbb\xbe\x4c\x16\xf1\x6f\xdf\xde\x33\x5f\x49\x19\x67\xbe\xe2\xf7\xed\x0e\xc0\x9a\x7c\x7b\xa1\x03\x14\x92\x19\x50\xd7\x1e\xa0\xbc\x2e\xa7\x5d\x7e\x75\x75\x75\x9d\x5f\x82\xf2\xba\x40\x6a\x5a\x75\x75\x75\x3d\x90\xf6\xfe\x36\xe5\xbb\xa5\x50\xc7\x4e\x25\xb9\xd5\x51\xf0\x35\xee\xce\xce\xcd\xeb\x50\x92\x5b\x55\xef\x63\xe2\x9f\x68\x46\x41\x21\xff\x27\x9f\xaf\x71\xb7\x1c\x4c\x69\x53\x92\x5b\x45\x94\x70\xa5\xd2\xfe\x58\x7d\xbe\xc3\x67\x7e\x46\xb4\x1d\x29\xaf\xcf\x11\x7f\xd5\xe5\xb4\x4b\x29\xdf\x3d\x30\x27\x2b\x58\xbe\x3b\x90\xd3\x2e\x50\x5e\xef\x77\x7a\xf9\x2b\xeb\x03\x4e\x0f\x7f\x80\xf7\xf0\xb3\x60\xb9\x92\x93\x11\x4d\x25\xe5\xf5\x69\xce\x10\x23\xa4\x5c\xe9\xdb\x5e\x3d\x5f\xfd\x66\x38\xe4\x94\xa7\xa8\xe7\x7f\x78\x8a\xf2\x1f\x4a\xfb\x8c\xdd\x52\x7b\x7f\x56\xf9\x6e\x2a\xbe\x65\xfe\xad\xe4\x67\xec\x0e\xe6\x07\xb2\xca\x95\x76\x19\xbb\x53\xda\xa5\x66\xf1\xab\xed\x6e\x93\x93\x96\x55\xbe\x3b\x43\x7c\x87\xc4\x77\x36\xff\xe6\x7d\x72\x45\x9f\xfc\x8c\xdd\x79\xe2\xac\xf6\x19\xbb\x3b\xc4\xae\xd3\x31\x76\x9d\x4e\xbc\xcf\xee\x82\x58\xcf\x42\xde\x4e\x07\x66\x48\x94\x8f\x3c\x23\xc4\xa1\xe9\xd8\xa9\xa0\xb0\x47\xd2\x7f\xca\xc0\xf6\x7c\x46\xfa\x44\xfa\x15\xf7\x89\x64\x55\xd3\x6a\x4e\x39\x11\x7f\x24\x27\x42\x8b\xb3\x8a\x69\x71\x56\x69\x75\xbf\xe2\xee\x24\xa7\xf2\x07\x12\xb9\xec\xf8\x65\xaf\x8c\x78\x6f\xc4\x57\x4d\x8d\x95\x44\x6a\x7a\xef\xb2\xf7\x47\x1c\xbe\xf4\xbd\x4b\x08\x68\x95\x1a\x79\x48\xff\xdb\x5b\xe4\x91\xa6\x5f\x72\x7a\xeb\x6f\x7a\xd3\x2c\xf2\x10\x27\xfd\x6f\xc2\x0b\xd7\xe2\x3d\x6c\xb0\x9c\x09\x61\x28\x83\x0a\x58\x07\x4a\xbb\x4a\x25\xab\x3a\xda\x31\xd0\xa8\x74\xae\xaa\x6b\xd7\x91\xc3\xda\x2e\x27\x58\xae\xa4\x56\x2a\xa5\xd5\x51\x39\xa5\x51\xa1\x55\x75\x72\x2a\x6f\x97\x59\xb0\x9c\x28\xdd\x85\xe8\xe7\x55\x45\x23\x59\x8d\x4a\x24\x23\x9a\x43\xca\xeb\x68\xc7\x92\xaa\xaa\xaa\xfa\xec\x3c\x48\x65\xe5\x75\xbe\xd4\xce\x55\x55\x55\x4a\x76\x46\xb4\x2b\x29\x8f\x66\x64\x35\x46\x7b\xf0\x63\x57\xae\x09\x01\xae\x09\x1d\xdb\x85\x32\x95\xbc\x1a\x25\x35\xb4\x07\x82\x19\xf9\x25\x15\x25\xb9\x35\x8a\x9c\xa9\x04\x6a\x7a\xf6\xca\xea\xdd\xb7\x5f\x9f\xea\x9c\x76\xb9\xfe\xb2\xce\xa1\x02\x29\x27\x5b\xf6\xe7\x14\xf7\xe1\xbf\x49\x6e\xa8\x73\x0f\x52\x9a\xdd\x2e\xb7\x8f\x4c\xfa\xf6\xe9\x5d\xd6\xb9\xf6\xd3\xd7\xef\x39\xf1\xdc\xc4\xcd\xdb\x5e\x7a\xf2\xb2\x93\x6f\xde\x73\x6a\xff\x55\xdf\x4e\xba\xf0\x95\x27\x49\xf7\xf3\x06\xdf\x4d\x52\x56\x0f\x1e\xcc\xf2\x7f\xf3\x87\xec\x47\x1e\x4c\x19\xfd\xf9\xc0\xb6\x4d\x7f\x19\x3e\x67\x79\xed\xe3\x87\xb2\xfe\xf4\x9a\x6f\x14\x09\x94\x0f\x92\x49\xdf\xf6\x23\xf6\xad\xaa\xa8\x29\xf8\x22\xeb\x87\x63\xb9\xd7\x76\xeb\x5f\xc8\xf5\xcd\x07\x17\xe0\x97\xb2\xed\x7b\x1d\x52\x20\x1b\xf2\xa0\x18\xba\xc3\x36\xa8\xcb\xe1\xd2\x1f\x01\x28\x8f\x76\xf6\x35\xd6\xb5\xe3\xf2\x2f\x49\x50\x1e\xcd\xf4\x35\xd6\x07\xda\x46\xa4\x36\xe5\xd1\x80\xaf\xb1\xbe\x43\xb9\xf8\xd9\xc1\xd7\x48\x94\x1e\x1c\xa9\x68\x6a\x5e\xa3\x92\x9a\x11\xcd\x20\xe5\x51\x5f\x5e\xa3\xe2\xcb\x88\xe6\x93\xf2\x68\x49\x5e\xa3\x52\xe2\x00\x54\x90\xd7\x18\xad\xe4\x00\xa5\x86\x32\xeb\x02\x52\x4e\x4d\x4d\x8d\xe2\x0b\x29\x79\x35\xd1\x92\xfc\x50\xa6\xd2\xae\x46\xe9\x1a\xaa\xeb\x10\xc9\xad\xe1\xd0\x05\x72\x42\x99\xbb\xf3\x0b\x4a\xba\x96\xe4\xd6\x44\x33\x3b\x84\x32\x77\xfb\x52\x33\xa0\x24\x97\x23\x97\x11\x89\x59\x95\x7e\xd9\xed\xaa\xab\xfa\xf4\x2e\x2e\x92\xb3\x48\x75\x90\xb4\xf6\x0f\x17\x90\x71\x4f\xed\xa9\x7b\xe6\xc9\xfa\x1f\xba\x57\x4d\x9a\x54\xd5\x7d\x24\x2d\xff\xea\x87\x77\x89\x96\xd4\xcc\x24\xf2\xda\xdf\xdf\x3f\xd9\xf0\xf7\x0f\xef\x5a\xf4\xc3\xe9\x3b\xbe\xbf\x9b\x9b\x48\xa2\xf2\xc6\x13\x0d\x7f\xff\x40\x34\x72\xb9\x1a\x8d\x96\x0c\xbe\xd7\xa1\x13\x94\x41\x2f\x58\x04\x75\x79\x1c\xaf\x0e\x1c\xaf\x08\x6d\xac\x0b\x72\xa8\x2a\x03\x8d\x44\xa9\x12\xa0\x14\xb4\x6b\x54\x0a\x32\x94\xce\xe1\x63\xa1\xa8\x9c\xd9\xa8\xc8\x95\xd1\xce\x99\xbc\x29\x5a\x41\xca\xa3\x69\x99\x8d\xd1\x6a\x8e\x8c\x1c\xca\x54\x68\x4d\xb4\xa2\x73\x28\xb3\x3e\xd8\x21\x52\x92\xce\x05\x25\x2d\x54\x97\x91\x5f\x2c\xd0\x88\xe4\x85\x32\x95\xfc\x1a\xa5\x32\xb4\x07\xe4\xb4\x76\x02\x15\x47\x84\x7a\x90\x3e\x31\x2b\xeb\x27\x7d\xfb\x45\x64\xc9\x4f\x22\x9d\xe5\xe2\xa2\x92\x52\x0e\x41\x3f\xd2\x96\x64\x65\xe7\x9e\x4f\xfa\xf4\x2e\x2b\x2e\x92\x47\xdf\xf6\xc0\xf0\xc1\x8d\x2f\xa9\x1f\xad\xd9\x48\x3a\x0e\xed\x4d\xce\x2f\x59\x3c\x92\x74\x6f\x5a\x75\xd3\xc1\x7f\x9e\x6a\x32\xc9\x2f\xee\x9e\xbe\x78\x7a\x53\x7d\xff\x0b\xc7\x5e\x3b\x76\xfc\xb0\x9a\x0b\x2f\x23\xf7\xde\x73\x68\xcc\xd8\x47\x27\x6c\x50\x9f\xfd\xcd\xc2\x97\xc7\x35\x7d\x71\xf3\xfe\x55\x4d\x38\xb5\xe9\xf8\x8d\x2b\x3e\x7e\x7f\xec\x8c\xf3\xc8\x25\x15\x93\xa4\x45\xb5\xb3\x7a\x4e\x38\xbf\xcf\x79\x03\xb9\xff\x59\x41\xb7\x93\xcd\xc2\x86\x17\x41\xa2\xbd\x66\x1e\x7b\x1d\xf5\x91\x72\xd7\x2e\xaf\x88\x59\x63\xc7\x7f\x8d\x6e\x3a\x20\xdd\xe6\xdb\x0b\x6d\x20\x0f\xea\xa8\x04\xe5\x44\x69\x2b\x90\xf4\xe7\x35\x46\xd3\x9d\xb3\x32\x32\xfb\x55\xcb\x52\x4e\x76\x66\x6e\x71\x99\x34\x7a\xd3\xba\xd3\xbf\x5a\xfb\xc0\xea\xef\x1e\xd8\x28\xf5\x22\x41\xa2\xff\xee\x50\x53\xd5\xa9\x6f\x9b\xfa\x3d\xb7\x8b\xbc\xe2\x5c\xf3\xbc\xa6\x03\xd2\xb4\xd8\x35\x21\x76\xcd\xd4\x63\x51\xd6\x7c\xcd\xea\x76\x99\xa1\x0c\xc9\x5f\xdc\x37\xb3\x4f\x6f\xe9\xbc\xd3\x0f\x6c\xdc\xb4\xee\xbb\x55\xeb\xd7\xfa\xf6\xfe\xbe\xa9\x57\xd3\xbf\x9b\xfe\xdd\xd4\x7f\xe7\x7e\xf2\x9a\x7d\x4a\xfc\x8f\xea\x80\xc0\x05\xd2\x58\xd6\x49\xce\x16\x91\xbd\x42\x2b\x09\xf7\x85\x19\xce\xa5\xfa\xf9\x68\x84\x96\xe6\xfa\xb2\xfc\xa9\xa4\x73\xd6\x05\x9d\xc9\x0d\x5d\x89\xdc\x95\xdc\x1c\x69\x7a\xe6\xa3\x4f\x37\xdf\x63\x7d\xc0\x32\x4f\xcf\x24\xf3\x9a\xd6\xce\xfc\x21\xaf\xe9\xbd\xdb\x48\x4d\xd3\x6b\x0b\x49\x57\x20\x50\x0b\x9f\xb2\x1a\xf6\x32\xa4\xc2\x95\xa0\x40\xa5\xe2\xaf\x8e\x12\xb9\x51\xf1\x55\xd5\x01\xe1\x76\x09\x52\x82\xe5\x75\x04\xf8\x4f\x42\xb9\x89\x4a\xab\x54\x52\x8e\x29\x52\x55\x7d\xd0\xf1\x1b\xac\xaa\x2e\x98\xc2\xff\x39\xe8\x0f\x96\xd7\xa5\x04\xf9\xcf\x14\x08\x96\x47\xdb\x38\x9c\xf5\x89\x84\xaa\x43\x91\x9c\x48\xa8\x38\x54\x4b\x96\x1d\x27\xcb\x9a\x16\x1d\x97\xa6\x1d\x27\x2b\x9b\x6e\x3f\xde\x74\x17\xb9\x9b\x8f\xab\xe9\x3b\xf2\x3a\x7c\x09\x32\x94\x72\x1e\xea\x25\x06\x41\x3e\x7b\xfe\x4a\x45\x3a\x16\x65\x59\x8d\xd1\x00\x29\x8f\x32\x29\x94\xa9\xc8\xc2\xb5\x66\xf6\x8b\xe4\xca\xf4\x82\x5f\x94\x90\xbc\xf4\xde\x77\x36\x7d\x47\x52\xac\xdc\x23\x4d\x5f\x08\xdc\xc9\x4e\x69\xac\xb4\x45\xc8\x82\x02\x95\x51\x92\xda\xc8\x89\x8b\x42\x14\x48\x79\x3d\xcd\xe0\x92\x11\x93\x85\x3e\x91\x9c\xf3\xa4\x7c\xb2\xf3\xf4\x69\x7e\xae\x88\x4b\x48\x0d\xa4\x42\x17\x68\x0e\x48\xe2\x71\x49\x9a\x90\x09\x39\xa3\x51\x90\x33\x3c\x6f\xb8\x11\x0f\x35\x62\x51\x06\xbf\x66\x5b\x00\x3a\x58\xc8\x66\x3b\xa8\x03\xae\xb7\x44\x08\x03\xab\x74\x79\xa8\x26\x11\xd2\x56\x8a\x90\x9c\x33\x1f\x71\xf5\xe7\xb1\xc1\x25\x68\xb1\x61\xbe\x3f\x41\x2a\xe4\xc2\x60\xa8\x0b\x72\x45\x4f\x4f\x69\x14\xa2\x19\xcd\xe1\x83\xc9\x13\xac\xa4\xa5\x37\x2a\x69\x19\xd1\x4c\x52\x1e\x95\x73\x1a\x85\xe9\xcb\x4c\x8b\x87\x44\x39\x3c\x3a\x92\xa1\x46\x58\xaf\xcc\x48\x15\x84\x32\xa4\x48\x11\x90\x8c\x76\xd5\x55\x7d\x43\x19\x5c\x35\x2f\x39\x4d\xd8\x19\x42\xbf\x6f\xfa\xfe\x4c\x13\x92\xea\x09\x73\x66\x4f\x9a\x7c\xfd\x0d\x13\xa5\xe3\x64\x19\x99\xdb\xb4\xa4\xe9\xfe\xa6\xbb\x9b\xd6\x92\x3b\xc9\x4d\x4d\xdf\x34\x5a\x24\x85\xb4\xf9\x42\x60\x7c\x1b\x00\x1d\xe1\xdb\x0b\x29\x50\x0a\x75\xac\x79\x4c\xa9\x95\x0a\x3b\x16\xa5\x39\x8d\xd1\x34\x52\x1e\xa5\x2c\x94\xa9\x10\x31\x5f\x84\x07\x83\x17\x10\x39\x9d\xdc\x46\xde\x6b\x6a\x7a\x9d\xfa\x2e\x2b\xd8\xc9\x2e\x20\x0b\x4f\x5f\x42\x47\xdc\xbb\xe1\xb2\xbc\x55\x42\xbe\x47\x00\xb0\x91\xc2\xce\x5d\x01\x75\x21\x3e\xea\xb6\xb4\xb1\x8e\xf1\x51\xb7\xa7\x8d\x44\x29\xa8\x54\x72\x8f\x45\x03\xe9\x8d\x75\x81\x5c\x2e\x66\x81\x8c\x60\x79\x5d\xae\x88\x56\x72\x43\xc1\xf2\x68\x21\x29\x87\x68\xdb\x50\x28\x53\xc9\xac\x51\xda\x87\xea\x02\xb9\x9d\xb8\xbd\x67\x99\x0a\x70\x10\xce\x97\xaa\xab\x0a\x48\x4e\x76\x5b\x92\x4e\x72\x22\xa1\x48\x1f\x72\xbe\xe4\x98\x28\xff\x88\xd9\xf7\xef\x9c\x79\xcf\xdb\x0b\x86\x3e\x78\xe0\x80\xb4\xe8\x07\x89\xcc\xdd\x3a\xad\x62\xf2\xa8\x2b\x9f\xb8\x8a\x9d\x1e\x7f\x69\xd7\x69\xf5\x0b\xa6\x47\xd5\x67\xa2\x6d\x9b\x7e\x78\x8f\xdc\xb4\xe3\xee\x39\xe7\xd6\x8e\x1d\x31\xcc\xe1\x19\x2d\x36\xc8\xf7\x3a\x94\xc1\x2c\xa8\x2b\xe5\x3c\xb3\x94\xc6\xba\x3c\xe1\xbd\x52\x1b\xeb\xd3\x52\x4b\xf3\xda\x94\x47\xd3\x02\x8d\xbb\x73\x4a\xf3\x02\xe5\x44\xe9\x5c\xa9\xf8\x8f\x45\x8b\x72\x1b\x95\x0c\x6e\xa0\x3b\xa4\x37\xd6\x65\x74\xe0\x43\xc8\x48\x0d\x96\x47\xbb\xf0\x21\xa4\x32\x1e\x46\x16\xd5\xd4\x44\x73\x4a\x43\x99\xd1\x8c\x82\x9a\x1a\x25\x33\xa4\x74\xa8\x51\xf2\xb8\xcb\xea\xd9\xab\x5f\xa8\x80\x54\x57\x71\x37\x5d\x4e\xfa\x88\x1f\x7c\x10\x9d\xfb\x46\xaa\x98\xf0\xe9\x7c\x94\x2c\x52\x34\xe2\xca\x37\xa6\x3d\xb2\x6e\xe7\xfe\xb9\x37\xee\x7a\xf4\xcf\xc3\x1e\xbc\xe6\xd7\xaf\x92\x9c\x4f\x89\x7f\xfb\x43\xd1\xbd\x4d\x7a\xd3\x67\x5f\x9e\x4b\xfc\xe5\x7d\x67\xde\xf4\xcb\xb1\x7f\x1f\x37\x7b\x7b\xcf\x73\xdf\x5d\xbb\x7f\xdb\x3d\x2f\x96\xc8\xed\x9e\xfe\xcd\xd1\x2f\xb8\x1c\x16\x03\xb0\x1b\xc5\x3c\x67\xc1\x34\x47\x0e\x85\x5f\xae\x87\xd4\xa0\xd4\x86\xc7\xc9\x51\x08\x36\x2a\x72\x15\x51\xb2\x2b\x95\xa0\x88\xd9\x03\xe9\x22\xa8\x09\x08\x3b\x10\x90\x83\xe5\x75\x41\x31\x41\x41\x6e\x12\x72\x48\x79\x34\x10\x0c\x65\xd6\x49\x19\x21\xe1\x63\x52\x41\xc8\x88\x22\x85\x94\x0c\x3e\x45\x7d\x48\x24\x54\x9d\x53\x2c\x52\x87\x3e\xbd\xfb\xf6\x2b\x96\xfd\xc5\xd2\xdd\xa4\x93\xa2\x34\xbd\xdd\xf4\x04\x99\x94\x42\x03\xa5\xbd\x49\xe5\x7b\x54\xf9\xe1\xba\xaf\x9a\xde\x22\x95\x5f\x7d\x77\xbe\x95\x35\x7a\x84\x63\x1f\xa7\xa1\xc5\xfa\x88\x98\x7a\x8c\x13\x51\x47\x59\x6a\x63\x5d\x1b\x3e\x17\x19\xb4\xb1\x3e\x3b\xd0\xbe\x4d\x9b\xf2\x68\x36\x57\xa0\x8e\x95\x8a\x7c\x2c\x9a\x9b\xd3\x18\xed\x44\xca\xa3\xb9\x72\x28\x33\xda\x36\x9d\x73\xc4\xda\x87\xb8\xb8\x28\x81\x50\x1d\x49\xe5\x61\x81\x92\x9d\x19\x4d\x0b\xd5\xc4\x50\x0f\xf7\xe9\x1d\xe1\x58\x67\x45\x42\x11\xda\xcf\x51\x7e\x88\x14\x4d\xbb\xfc\xed\x89\xa4\x43\xd3\xf1\x3e\x4b\xba\xdc\xd1\x8f\xe6\x9f\xb1\x3b\x14\x9f\x77\xf5\x3b\xdf\x37\xbd\xdd\xd4\x70\xea\x5c\x92\xda\xad\xcf\xdf\x3e\xc8\x49\x1b\x24\x35\x36\x9d\x6e\xfa\xc4\xdf\xf6\xcb\x37\xbf\x6d\xfa\xce\xc9\x3f\x86\xa1\xc5\x46\xfa\xfe\x08\x79\x50\x02\x73\x9d\x48\x28\xda\x31\xa6\xeb\x81\x60\x63\x7d\x7a\x51\x0e\x6d\x53\x1e\x4d\xe7\xfe\xbd\x54\xa8\x7d\x7e\x7a\x23\x8f\xe9\x0b\xb9\xba\x67\x35\x46\xcb\x48\x79\x34\x1f\x42\x99\x75\xa9\x69\x6d\x38\xbf\x85\xa1\x3a\x9a\x2e\x02\x9d\xcc\xcc\xa8\x4f\xc4\x84\x45\x1d\x43\x99\x51\xc8\xac\xa9\x51\xd2\x43\x4a\x5a\x8d\x12\xe0\x86\x94\x9b\x05\x88\x54\xe5\xe6\x94\x15\x17\xb5\x25\xfe\x6a\x77\x2c\xc5\x45\x65\x92\x70\xe3\x7d\x1d\xdd\x18\x46\xe6\x92\x39\x8b\x86\x8e\xbb\xea\xf1\xd7\xa6\x05\xdb\x4c\xfd\xab\xf6\x61\xd3\x77\x9f\x6f\xf9\xe7\x32\x52\xbd\x68\xd2\xd4\x59\x53\xa7\x4d\x5c\x21\xdd\x40\xea\xc8\xce\xf4\x7f\x65\x4f\x3a\xf0\xec\x2e\xfb\x2f\x9f\x37\xfd\xe3\x21\x12\x1e\xbf\x70\xdb\x8a\x3b\xae\xbf\xe3\x76\x3e\x2f\xfd\x84\x5e\xef\x05\x99\xfb\x67\x5f\xcc\x5e\x44\x81\xeb\xb4\xbf\x92\x1b\x77\x88\x12\x10\xe1\x48\xcf\x5e\x59\xa1\x48\x0e\x89\x90\x7e\x2c\xff\xcc\x7b\x4d\x07\xa4\x52\x56\x47\xd8\xe1\xef\xd3\x58\x9d\x53\xe9\x12\x4f\x1b\xf9\x5e\x83\x5c\x28\x82\x1e\xb0\xc0\x45\xac\x83\xdf\x0d\x83\x2a\xfc\x8d\x44\xa9\x14\x30\xe5\xf1\xd0\x87\xab\x58\x71\x66\xa3\x92\x97\x11\x2d\xe0\x78\x65\x36\x2a\x99\x19\x4a\x1a\x6f\xee\x9a\xd9\xa8\x74\xad\x14\xf1\x50\x4f\x52\x1e\x2d\x76\xe2\x21\xa5\x6b\x68\x77\x4e\x87\x48\x50\x04\x43\x99\x4a\x7a\x0d\x44\x2b\x3a\x84\x32\x79\x08\x94\x19\x29\x4b\x08\x81\x4a\xaa\x1d\x75\x13\xda\x16\x0b\x7e\x44\xec\x2c\x67\x65\xb7\x8b\xc7\x3f\xc3\x56\x3c\xb0\x68\x0e\x61\x6f\xbd\x4d\xc8\x9d\x6b\xb6\xfd\xba\xe9\xe4\xc9\xaf\x9a\xbe\x24\x05\xb7\xce\xbc\x69\xfe\x8d\x77\xbd\x5b\x75\xd9\xf4\x29\x23\xa6\x8d\xb8\x7c\x32\xb9\x69\xd1\xe1\x4b\x2e\xaf\xbf\xfe\xd1\xc3\x07\xb7\xcc\xfb\xfd\x45\xb5\x07\xe7\xd7\x1f\x7f\xe3\x4f\x63\x27\x4d\x1d\x75\xe1\xcd\x83\xa6\x48\xfd\x06\x5c\x5b\xd5\x63\xd2\x05\x17\x8d\x1c\xe5\xc8\xcd\x20\x81\xc3\x1f\x21\x1f\x4a\xb9\xdc\xa4\x08\x1f\x11\x74\xe5\xa6\x38\xa5\xb1\x3e\xb7\x53\x0a\x97\x9b\x5c\x2e\x37\x65\x02\x90\xf6\x59\x8d\x4a\xfb\x8c\x68\x98\x27\xaa\xe9\x8d\xd1\xce\xa4\x3c\xda\x9e\xcb\x4d\x4a\x5a\x3a\x97\x96\x70\x28\x4a\x73\x6b\x6a\x14\x7f\x66\x5d\x66\x56\xb6\x50\xcf\xdc\xf4\x50\xa6\xd2\xa6\x46\xe9\x14\x52\xb2\x6a\x94\xe2\xcc\xa8\xdf\x71\x27\xbd\xa1\xba\xaa\x5d\x66\x4e\x06\x44\x8a\x3a\xf7\x69\x57\x5d\x75\x3e\xe9\x57\xdc\x96\x14\x17\x95\x79\x05\x67\x10\x49\x3d\xb9\xe5\x9b\xa5\x4d\xeb\x9b\x7e\xbd\xf4\xc2\x31\xe3\x37\xbd\x3a\x2b\x90\xd6\x7f\xc3\xfc\x83\xef\x93\xf2\x29\xd3\x26\xae\x5c\x34\x79\xd2\x6c\xfa\xfa\x17\x24\xb4\xa1\xe9\xa3\x57\x9b\x46\x36\x8d\x6d\xfb\x5d\xce\x35\x2f\x3d\x3d\xf1\xd2\x6f\x3f\x9c\x75\xe7\x1d\x23\x17\x6e\x5b\x2e\xc6\x29\x7c\x32\xbb\x49\xf8\xc2\x6a\xa8\x4b\x27\x50\xfe\xff\x70\xf7\x26\x60\x52\x15\xe7\xfe\x70\xd5\xd9\x7a\xef\x3e\x75\xba\x4f\xaf\x33\xd3\xdd\xd3\xb3\xd2\xcc\x34\xd3\xcd\xcc\xd8\xb2\xa3\x12\x44\x21\x80\x48\x00\x11\x15\x01\x11\x51\x41\x24\x06\x91\x4b\x90\x28\x31\xc1\x10\xe3\x12\x35\x89\x17\x51\x89\xf1\x12\x53\xa7\xbb\x21\x68\xd4\xb8\x04\x89\x21\x86\x18\x22\xfe\xfd\x13\x93\x78\x8d\x31\x27\xe2\x12\xaf\x31\xb2\xcc\xe1\x7b\xaa\xea\x9c\x5e\x66\xc3\x78\xbf\xe7\xf9\x9e\xe7\x7b\xcc\xf4\xf4\xf4\x90\x39\x55\xef\xfb\xd6\x5b\xbf\x77\x2f\xa9\xf4\x42\xae\x76\x19\x84\xab\x5d\x06\x0a\xfd\x46\xae\xc3\x7e\x17\x34\x1a\xec\xb2\x26\xdf\x2f\x9e\x55\xb9\xb4\xf9\x6f\x92\x37\xb3\xe6\xcf\x63\x74\x26\xd8\x84\x3c\x5f\x02\x0a\x38\x03\x14\x9c\xe4\xf9\xb2\xf9\x54\x3f\x55\xe5\x1e\x59\xc7\x42\x16\x7b\x64\x8d\xf3\xeb\x98\xcb\x68\x01\x98\xd6\x3c\x1c\x52\x0a\x92\x53\xce\xe7\x2b\x80\xc5\x05\xab\x9e\x6f\x81\x97\x9d\xd6\xf3\xcb\x28\x46\x78\xa5\xb2\x00\x82\xcf\x0e\x08\x79\x11\x00\x09\x00\x7f\x37\x54\x1d\x50\x9d\xc7\xbf\xd9\x37\x87\xdb\xc5\x6d\xda\x06\x3f\xfc\xd0\x78\xc1\x78\xe7\x03\xb2\xce\x79\x70\x87\x90\x17\x00\xf5\x63\x44\x19\xf2\x91\x74\x8a\x32\x24\x1d\x62\x7b\x46\x73\x94\x11\x0f\xec\x4e\x92\x3f\x72\x32\xce\xbf\x09\x77\x1c\x39\x02\x6f\x79\xfd\x75\xd0\xff\x59\xbd\xdd\x0e\xd8\x0d\xd5\x79\xdc\xae\xbe\x39\xfc\x9b\x07\x3e\x80\x11\x38\xee\x43\x43\xde\x46\x69\x22\x9d\x7a\x9b\xdf\x2e\x1e\xa0\xb2\xb7\x0a\x30\x53\x2d\xe4\xd4\x71\x2a\x53\xaa\x67\xac\x89\x64\xa8\xd0\x45\x0f\x6b\x09\x59\x2f\x7a\x12\x51\x7b\x5a\x73\x87\x75\x9c\x90\x29\x75\x44\x85\x89\x9f\xdb\x83\x94\x12\x87\x42\xf5\x29\x72\xdc\x12\x48\x73\x28\xf9\xbc\x26\x06\x10\x31\x57\x81\x16\xa9\x47\x4a\x41\x0c\xb8\xf3\xf9\xbc\xc6\x85\x90\x79\x8d\x5b\x96\x87\x17\xd6\x43\x7a\x49\x98\x07\xcd\xe6\xaf\x22\xaf\xf4\xa7\xe3\xbf\xf9\x9f\x25\x5b\x2f\xcd\x19\xff\x9a\x7d\xf5\x95\x67\x5d\x3a\xf7\x9e\x67\x37\x59\x1c\x17\x67\x6c\x78\xf1\x91\x6b\xb6\x2f\xf9\xc2\xb4\xb1\x63\xa7\x5d\xfa\xad\x99\xe7\x2d\x3a\x73\xd2\xd9\x8b\x4f\xd6\x95\x51\x1b\xd9\xe3\xb2\x53\x73\xa4\xfd\xe2\x1e\xd0\x0d\x26\x82\xdb\x00\x03\x21\x2d\x5e\x1d\xe7\x32\x5a\x87\xa8\x13\xd6\xbb\x73\xda\x19\x5e\x1d\xc7\xb3\x78\x7c\x46\x8b\x78\x75\x88\x27\x11\x29\x2c\x8d\x60\xb8\x78\x04\xf3\xba\xf4\xb0\x9f\x7a\x64\xad\x11\xa6\x4d\x0f\x8b\x36\x19\xa6\xb5\xc6\x1e\xa4\x4c\x74\xb8\x05\x7f\xa4\xa5\x63\x54\x6e\x6c\x53\x28\x0f\x34\x7f\x07\x52\xf0\xa8\x3c\x3e\x03\x61\x5f\x1e\x8f\x57\x4a\x76\x10\x6c\x1c\x41\x68\x13\x41\xb8\x8e\x9e\x3c\xa5\x29\x99\x15\x14\x02\x62\x52\x8d\x2d\xad\xec\xd4\x75\xd3\xf3\x18\xe2\x03\xf4\xec\x75\xc2\x54\xa3\xc0\x91\xc3\x99\x6d\xea\x55\xa5\x64\x02\x40\xf2\x8b\x09\x90\x1c\xca\x65\x47\xe0\x77\x20\xf7\x07\xb8\xe0\xa9\x85\x8f\x5e\x3b\x6d\x4d\x58\xee\xda\x3a\x57\xfb\x35\x74\x1c\x99\xf5\xfb\xb3\x42\xe7\x4f\x3c\xff\x96\xff\xf9\xc1\x4b\xc6\xef\x1f\x80\xad\x30\xbc\x0a\x82\x35\xbf\x37\x8e\x19\x5f\x33\xbe\xc4\x5d\xb6\x6b\xfe\x25\x4e\x4f\xe7\x39\x1b\xbe\xc9\x4d\xfd\x17\xbc\xeb\xad\x92\x51\x7a\xfd\xdb\x1f\xde\xfa\x85\x33\xc7\x9e\xf3\xea\xde\x57\xa0\x10\x0f\x1b\xa1\xad\x3f\xfb\xee\x83\xff\xda\xfc\xa8\xf1\xcb\x5f\x1b\xef\x1a\xaf\x67\xd3\xcf\x2d\x80\xdf\x86\x37\x1d\xda\xf8\xed\x37\x9c\xdf\x2f\xc7\x32\xc4\x5b\xc4\xa7\x80\x0d\x78\xc0\x79\x0c\x0d\x63\x3e\x47\x2f\x83\x92\x64\x07\xd0\x93\xd6\x24\x72\x27\x98\xc6\x97\xac\x63\x9b\xac\x09\x04\x4a\xca\xd4\x66\xd2\x04\x1b\x52\x8a\x90\xb3\x3b\x28\xb5\xa0\x1d\x29\xd8\x9d\x1f\xd5\xd5\x05\x93\x30\xc9\x27\x79\x7f\x92\x6b\x69\x95\x38\x01\xae\xe7\x24\xa3\xb0\xa2\xef\xdd\x15\x7b\xe1\x86\x3b\x9b\xed\x49\xf1\xa9\xe3\x67\xc3\x85\xc6\xc3\xdc\xa5\xf0\xf5\x9b\x9a\xbe\x4a\x4e\xc9\x5e\x00\x84\x8f\xc5\x3d\xc0\x07\x42\x20\x01\xae\x00\x05\x1f\x60\x30\x81\x89\x73\xc2\xad\x97\xc2\x21\x1f\xe7\x49\x6b\x61\xa7\x0e\x71\x92\x2e\x49\x56\x75\x1c\xce\x62\x99\x49\xb1\x3b\xa8\xe3\x3a\x72\x93\x88\x41\x9d\x70\x97\x0a\xae\x66\x77\x50\xcd\x29\xd3\xb5\xe1\x30\xa2\x1f\xe0\x84\x82\xc5\xfc\xa8\xae\x1c\x4a\x26\xaa\x20\x5a\x8a\xa7\x1c\x4b\xa6\xba\x2d\x34\xb7\x17\xee\x87\xbd\x30\xb2\x7e\xd9\x37\xd7\x1b\x7f\xfa\xf4\xbd\x5f\x7d\xf5\x46\xe3\xe4\xb3\xa5\xff\x58\xbd\xfe\x96\x87\xc4\x3d\xda\x73\x9b\x1f\x45\xce\xf8\x63\xb7\xff\xf2\xcf\x10\x2c\x5e\xba\xe7\x93\x19\x0b\xe6\x9c\x0b\x20\xb8\xe1\xd4\x51\xe1\x15\xf1\x00\x08\x82\x73\x40\x21\x40\x6f\x02\x0b\x37\x3b\x79\xbd\x68\x0b\x08\x04\x78\x86\xe8\x16\x3c\x41\x5d\x0b\x93\x0b\xd7\x17\x60\x38\xd9\x86\x0a\xc0\x43\xd0\x98\x26\x38\x91\x89\x0b\x46\x2b\x4d\xb9\x6c\xc8\x46\x24\x89\x53\xe5\x64\xb6\x17\x49\xa9\x04\xb8\x61\x27\xec\x7d\xe5\xd5\xd7\x96\xcc\xde\x39\xf3\x27\xcf\xc2\x6b\xef\x3f\x52\xfa\xa3\xf1\x9c\xf1\x38\xf7\xfa\x5f\xe0\x97\x7e\x7a\xc5\xc9\xd6\x33\x8d\x63\xef\x1a\xa1\xe9\xc6\xc9\xf3\xe0\x66\xca\xef\xbd\x00\x88\x6b\xc5\x3d\xc0\x0e\x7c\x44\x77\xda\xc9\xca\x1c\x16\x85\x7d\x6e\xdd\x74\xf5\x6a\x0e\x55\xc7\x0e\x99\x1a\x0d\x84\x94\x88\x2e\xcf\x81\x2a\x24\x03\x48\x06\x49\x3e\x97\x40\x72\x32\xb5\x17\x1e\x80\xcb\xe0\x56\x63\xa9\x71\xd3\xf2\x5b\xe0\xb3\xc6\xa5\x8f\x88\x7b\x8c\x5b\x8d\x1f\x1b\xdf\x35\xbe\x0a\x01\x7c\x13\xbe\x46\x75\x19\xe1\x2f\x47\x7d\xcc\x5f\x60\x92\x46\x9f\x4c\x71\x87\xe0\xd6\x4b\x22\x13\x37\x91\x2c\xc2\x5d\x5e\x04\xb1\x65\xa9\xa9\xeb\x70\x39\xd2\x98\xcb\x32\xa3\xd6\x34\xf5\x98\x15\x4b\xbf\xd0\x5e\x7e\x5a\xdf\x51\xf8\x81\x81\xb8\x80\xb8\xc7\x30\x7e\x6e\x18\x5b\x4e\x01\xeb\xb9\xbc\x21\xee\x01\x0e\x30\xb1\xca\xde\xa3\xcf\xb4\x8b\xf4\x99\x76\x82\x3f\x9d\xec\x99\xbe\xea\x67\xf2\x0e\xd3\x8a\xd6\x5c\xfd\x1e\xb8\x97\x9f\xd2\xf7\x2e\xfc\xd0\x90\xc9\xc3\xb6\xf4\xf5\x3d\xc3\x9e\x75\xc3\xa9\xa3\x62\xab\x78\x00\x44\xc1\x3a\xe6\x13\xa2\xf6\x12\x43\x8e\xbc\x5e\x52\xfc\x61\x82\x00\x14\x72\xa4\x62\xcc\x5d\x16\x2c\xbb\xcb\x54\x1f\x35\xf2\x65\x95\x9a\x1e\x8a\x23\xad\xd5\x59\x6e\x32\xde\x1e\x26\x78\x40\x45\xc4\xda\xd6\xbc\x61\xa4\x60\x35\xaf\xf9\x15\x82\x21\x5d\x79\x02\x8d\xb1\x94\xc7\x3c\x63\x0f\xc3\x90\xb6\x16\x22\x29\xd4\xf9\x83\x08\x7d\xbc\x90\xc8\x0b\xbc\x1b\x5e\xf1\xe6\x2b\x57\x6c\xff\xf1\x4b\x1f\xbd\xf0\xe4\x65\x4b\x8c\x77\xb9\xb3\x6f\x3f\x76\xb3\xb1\xdb\x78\x88\x7b\x03\x2e\x86\x5b\x17\x7c\x3a\xd3\xf8\xe8\x2f\xef\x9f\x08\xc0\x2e\xc8\xf5\x39\x3b\x9b\xe1\x2d\x16\x0d\xc5\x65\x94\x77\x13\x4c\x2d\x61\x63\x5a\x02\x8b\xb9\x12\xef\xa4\x54\xe4\xf9\x32\xe7\x5c\xaa\x8e\xb9\x2c\xd9\x98\x1d\xa6\xb1\x90\xd5\x6c\xaa\x5e\xe1\x59\xf9\xbf\xbd\xb0\x87\x3b\x0b\x76\x1b\x07\xfa\x9e\x16\xf7\xf4\xbd\xc0\x8d\x3b\x3e\x8d\xbb\xa1\xef\x36\x00\xc1\x64\x00\xb8\x23\xf4\x79\x79\x93\x67\x22\xb5\x67\xdd\xd4\xff\xe0\x50\x09\xb6\x2c\x4b\x85\x94\x2d\x70\xd4\xb8\xe1\x80\x83\x3e\xcd\x7c\x52\x77\x2f\x6a\xed\x4e\xaa\x36\x14\x52\x27\x17\x0a\xdc\x7d\x85\x02\x9e\xcd\x17\x66\x63\x3c\xfb\xe4\x8c\xd9\x98\xec\xeb\xd4\x72\x63\x36\x7c\x9f\xfa\x84\x3a\x40\x41\x22\xfb\x71\x65\x34\xce\xd4\x78\xe2\x61\xcd\xae\x32\xd7\x90\xc6\xb9\x18\xee\x92\x10\xbd\xf2\x6c\x14\x54\xa1\x24\x92\xb9\x54\x63\xeb\xbd\x33\x27\x2f\x9b\x07\x7b\xfe\xfe\xf6\x95\x33\xee\x09\x6c\xdc\x22\x2e\x38\xfe\xe8\x29\x60\x7c\x1c\x2c\xcb\x9f\x48\xb0\xb6\x1b\x8c\x32\x69\x67\x2f\xd3\x0e\x62\x0f\xf3\x1b\x50\x82\x69\x5e\x0b\x77\x6b\xbc\x33\xcf\x4e\x1a\xea\x85\x49\x07\x4c\x42\x1b\xa1\xd6\x8d\x70\x2b\x9c\x67\x70\x1c\x67\x6c\x37\x36\x6d\x16\xf7\xf4\x5d\xbe\x0b\xfe\xa3\x6f\xdd\xc9\x57\xb8\xe5\x8b\xfa\x3e\x31\xcf\xd8\x04\x71\x0f\x10\xc1\x48\xf3\x8c\xf1\xe6\x19\x83\x58\xa2\x4f\xe2\x55\xbd\xc0\x53\xe9\xe6\x45\x47\x5a\xb3\x55\x31\x85\xb0\x63\x96\xb8\xe7\xc4\xb4\x53\xd6\xba\xa5\xdf\x8b\x7b\x40\x00\x6c\x31\xff\x96\xcd\x97\x63\x2b\xd7\x38\x31\x97\x83\x58\xa5\x7f\x31\x80\x74\x0d\x85\x75\x1c\xa0\x91\x09\xe6\xdf\x94\x35\x37\xd2\xb1\x3b\x43\x2e\x5c\xdc\x13\x7d\xf2\xf9\x3f\xbc\x17\xa0\x71\x09\x5f\xa7\x17\xcb\xcf\x6a\x7c\xf4\x98\x88\xb9\x67\x79\xa0\xf1\x72\x67\x27\x2c\x72\xbc\x4f\x36\xc3\x02\x9a\x8b\xe8\x6c\xd1\x9b\xcf\x63\x37\xc2\x9e\xbc\x69\x88\xb8\x19\x39\x60\x0e\x92\xa5\x8e\xee\xf1\xa7\x60\x12\xa6\x14\x15\xed\x85\x3b\xe1\x02\x09\x5e\x0b\x7f\x68\xfc\x91\x77\x3b\x8c\x2d\xc6\x5f\x8c\xed\x0e\xbf\xb8\xe7\xc4\x0e\x61\xd1\xf1\x69\x5c\xa9\xeb\xab\x30\x70\x62\x8b\xb0\xde\xd8\xb1\xb6\x6f\x9e\xc9\x8f\x97\xe8\x3d\xb3\xc0\xe4\x87\xc3\xe4\x87\x2d\x67\xe9\x3f\x1f\xd2\xb1\x4f\xd6\x24\x62\x1d\x23\x1d\xdb\x65\x4d\x08\x53\xec\x86\x60\x5a\xf3\x11\x06\xb9\xdc\x79\x22\x0d\x1a\xe7\x64\xfe\x0c\x3e\x6f\x71\xce\x95\xb7\x96\xca\x11\x09\xb1\x56\xb9\x85\x5b\x6f\xf3\xc1\x90\xf1\xe5\xbe\xaf\xd1\xd5\x3d\x01\xeb\xbf\xcc\x95\x8e\x4f\x13\x66\x1b\x47\x36\xf4\xcd\x64\xf7\x31\xd1\x1f\xef\x50\x3f\x93\x5a\xf1\x33\x59\x1a\xc4\x4f\xe4\x32\xc8\xe4\x25\x44\xfd\x4c\x64\x35\x52\x48\xd7\x42\x30\xad\x21\x37\x79\x38\xbd\xea\xfc\x3e\xa2\x18\xa4\xbc\xa9\x0c\x98\xb2\x26\xa0\x23\x48\x15\x76\xa3\x74\x03\xbc\x12\xce\x82\xb3\xe0\x52\xe3\x5e\x03\x1b\xd8\xb8\x17\x9e\xf3\xe4\x13\x70\x8d\xb1\xed\x89\xa7\xb8\x3f\xc1\xab\xe1\x26\xe3\x26\xe3\x2e\xe3\x6e\xe3\x46\x78\x2b\xbc\xea\x9f\x9f\xc2\xf7\xe0\xfb\xc7\xac\xfb\x43\x78\xcc\xf4\x3f\x4c\x36\x4f\x26\xbd\x3b\xfc\x6e\xbd\xe4\x70\x01\x72\x3b\x3b\x88\x06\x0f\xd0\x65\x3a\x55\x1d\xbb\xb2\xd8\x29\x53\xac\x20\xaa\xba\xa6\x12\x09\xf7\xbb\x50\xcd\xe5\x2b\x24\x53\x11\x58\xb9\x6f\x0f\x41\x27\x54\x8d\xd7\x8d\x0f\x6f\x59\xb6\xed\x5b\x37\x6c\xbc\x5d\xdc\xf3\xf6\x5b\x47\x8f\xf7\x7d\xca\x4b\xab\x57\x5e\xbd\x9c\xd1\xc9\x78\x98\xd2\xc9\x07\x22\x60\x11\x28\x78\x00\x23\x4f\xc1\xe3\x27\x92\xed\x71\x39\xd2\x8c\x64\x21\x42\xb2\x28\x43\x0a\x21\x9d\xc0\x04\xd5\x24\x59\x8c\x68\x5c\x19\x29\x45\xde\xe5\xa6\xa6\xa5\x84\xb0\x93\xd0\xce\x83\x14\xec\xc8\xe3\x10\xea\x47\x41\xce\x46\x04\x6e\x50\x2a\xfe\x54\x83\x97\x1a\x6b\x8c\x8f\x43\x43\x92\xd2\x30\x1e\x9a\x65\xdc\x00\xa7\x0e\x42\x4f\x71\x2a\xd5\x3f\x41\x70\x51\x45\x1a\x29\x49\x83\x6e\xbd\xe4\xf6\x52\x92\xba\xc9\x05\x65\xa2\x05\x55\xc7\x5e\x6a\xdb\x28\x26\x49\xc3\xc4\x8a\x26\xab\x76\xe5\xb1\x88\x34\xbb\x93\x88\x80\xd7\x4d\x11\x3b\x0e\xa2\x5a\x94\x43\xf6\x50\x4d\xeb\xc7\xe0\x08\xd8\xf0\xad\x9b\xe1\xe3\xc6\xa3\xc6\x43\x8f\x2c\xb9\x73\xeb\xb6\x7b\x16\x89\x7b\x5e\x7f\x63\xd3\x4b\xf9\xbe\xcd\x5c\x57\xdf\x41\xbe\x63\xf1\x95\xcb\xe7\x11\x7d\xb0\xe8\xd4\x51\x21\x24\x1e\x00\xad\x60\x35\x28\xb4\x50\x5f\x0e\xaf\x17\x14\xb2\xd4\x08\xaf\x17\x83\x2d\x0a\xc1\x34\x6d\x19\xec\x3b\xac\xd5\xf9\x74\x5c\x47\x83\xb1\x5a\xca\xa7\x63\x35\x4b\x43\x3f\x75\x3e\x06\xc1\x6c\x68\xb7\xe0\x52\x22\x09\x62\xbc\x13\x1b\x36\x98\xa4\x7e\x9e\x16\xe6\xe7\x09\xa2\x22\xf4\xd5\xa5\x68\xc4\x27\x42\x6f\xba\x2a\xf7\x5a\x27\x6c\xed\xe4\xa8\xa1\x1f\x64\x68\x48\x52\x03\x0d\x30\x64\x1a\xfc\x8b\xee\x7a\xf9\xc2\x65\x57\x8f\xba\x78\xdb\xad\xb7\xce\x84\xb6\xbf\x5d\x77\x70\xf5\x92\xb5\xf7\x4d\x9b\xb7\xa8\xe5\x82\xef\xbd\x7c\xaf\xf1\x96\xf1\xf7\xb3\x61\x62\x72\xcf\x8c\xe9\xe9\xb3\xc6\x9f\x3d\xe1\xfa\xfb\xaf\x78\xfe\x8f\x3d\x5d\xff\x18\xd5\x32\x7b\x72\xfb\xb8\xfc\xb4\xc5\xfb\xb6\xbd\xf8\x17\x00\x41\x3b\x00\xc2\x3a\x71\x0f\xb0\x81\x33\x41\x41\xaa\xf6\x8d\x60\x3e\x4b\x03\xce\xd2\x61\x42\xf8\x82\x28\x11\x61\x13\x79\x47\xba\x20\x89\x34\x62\x08\x1c\x69\xcb\xaa\x33\xaf\xb8\x76\x61\xa6\xb1\xc6\xf8\x95\x50\x82\x9c\x61\x9c\x38\x5f\x28\xb1\x3b\xe1\xf1\x53\x47\xc5\x45\xe2\x1e\xa0\x80\x5e\x50\x90\x09\x2d\x25\x53\x4f\x63\x67\x8e\x9a\xb1\x4c\x55\x63\x5e\xa6\x61\x6c\xb7\xaa\x53\x80\xeb\xe0\x91\x82\xe5\xbc\xf9\x80\x80\x75\x0b\x05\x24\x21\x95\x00\x8f\xc3\xee\xaf\xff\xe0\xde\xdb\x60\xf7\x1d\xc6\xfb\x3f\x33\xfe\x6a\xfc\x92\xb3\xf3\x8f\x9f\xdc\xf4\xa3\x07\xfe\xf3\x31\x7e\xc3\xc9\x19\x3b\x3e\xbe\x19\x26\x59\x7e\x92\x98\xa3\x77\xeb\x38\x50\x70\x91\xfd\xd1\x10\xbb\x3d\x67\xdd\xde\x50\xd5\x31\xa4\x57\x37\xb9\x69\xc9\x6d\xaa\xd9\x21\x52\x34\xa7\x8b\xb0\x09\x58\x87\x17\x25\x61\x03\x0c\xf5\xf4\x12\xa8\x0f\xf3\xd0\x1f\xea\x92\x5c\x13\xa1\x0a\xf3\x86\xcf\x78\x5c\xdc\x73\xf2\xfe\xe9\x2f\xb7\x2d\xfc\x2b\xbf\xec\xf8\xb4\x72\x5e\x94\xed\x29\x71\x0f\xa8\x87\x41\x50\xa8\x27\x92\xee\xcf\xd1\x47\x6b\x76\x44\x6e\x93\x06\xf6\x70\x1f\x7d\x38\xd1\x6c\x8a\x4f\xd7\xe2\x66\x80\x5b\xfe\xf0\x12\x72\x7f\x78\xb1\x28\x63\xdb\xb3\x5a\xcc\x75\x0c\x47\x9e\x7d\xf2\xd9\xdd\x9f\xdc\xca\x3e\x0e\xcb\x38\xf8\xac\xe6\x12\x8e\x61\xcf\xb3\x4f\x8e\xdf\xfb\x3f\x13\x81\x9a\x76\x61\x51\x2e\x4a\xa2\xcd\x9f\x7e\xf2\xd9\x0f\xfe\x59\x4f\x3f\x71\xc9\x45\xb7\xcb\xe3\x4f\xe3\xb0\x5c\x0c\x85\x83\xfe\xf4\x93\xe3\x1f\xfc\xe8\xf7\xf4\x57\x31\xb9\x18\x8d\x45\xfc\x84\x99\xb6\xc4\x37\x12\xdf\x48\x49\x5e\xa4\xe4\x0b\xd1\x58\x84\x7c\x73\xbb\x3c\x55\x1f\x86\xc2\x41\xa4\xe4\xc1\x44\xb7\xcd\x13\x8e\x89\x92\xcb\x1d\x0c\x45\xa2\xd5\xf1\x6d\x38\xf4\xaf\xf0\xc4\x28\xd4\x10\x21\xa8\xbf\x9e\x12\xb4\x1e\x29\x58\xa0\x04\xf5\x07\x43\xe3\x61\xaf\x3f\xe9\x6f\x80\xec\x0d\x4c\xf2\x2d\x5c\xab\x17\xda\xf8\x24\xec\xfa\x59\x57\x50\x4a\xfb\x5f\x85\xcd\xaf\x7a\x47\xb8\x9c\x23\x95\x27\x61\x97\xb1\xd5\xf8\xcf\x17\x5d\xdd\x82\x34\xca\xb3\xcf\xd8\x2e\xee\x39\xf9\xdf\x6f\xec\xc8\x7f\x30\x99\xcf\x9d\x7c\xb9\xf7\xbf\x67\xcd\xd0\xa7\xf2\x0d\xc7\xa7\xf1\xa0\x1d\xc2\x91\x3d\x1f\xe4\xfa\x38\x93\x0f\xe2\x5c\xca\xff\x96\x0a\x1e\xe1\x2c\x3c\xe2\xce\x50\xf8\xa4\x71\xe4\x2e\x13\x28\x0a\xe9\x72\x50\x08\x42\xff\x07\xdf\x36\xce\x84\x73\xe1\x18\xd8\x0d\x67\x18\xdd\xf0\x7d\xe3\x01\x63\x97\xb1\x8b\xfb\x88\xfb\x45\xdf\x47\x9c\xb7\x2f\xdd\x17\xe7\xda\xfb\x5e\xb3\xf8\x4d\xf3\x29\xec\x04\xf7\xd8\xca\x72\xc6\xe7\x20\x76\x50\x37\x8d\xa4\xea\x9a\x93\xa8\x63\x1b\x52\x30\x47\x28\xc1\xde\x10\x4a\x10\xc8\x83\x92\x08\xce\x84\x19\xd8\x05\x67\x18\x31\xe3\xd7\xe2\x9e\xbe\x9d\xdc\x82\x93\x9b\xfb\xf6\x73\x19\xf2\xf7\xbb\x4c\x5f\xb8\x03\x74\x5a\xf8\xc4\xb2\xb1\x28\x14\x75\x66\x28\x6a\xd7\x6c\xcc\xa3\xad\x09\xbc\x69\x4c\xe5\xba\x09\x86\x50\x61\x12\x75\x71\x4f\xf7\xcd\x15\xa2\x7d\x67\x73\x07\x5f\xe2\xdf\x83\xe0\x97\x27\x15\x86\x7d\xb6\x19\x4f\x71\x6b\xa8\x0e\xe8\x35\xbd\x29\x82\xa4\x63\x5b\xd9\x77\x83\xc1\xe1\x92\x4d\x06\x0e\x81\xd8\x24\x9a\x18\xd6\xad\x9f\xf8\x6c\x45\x01\xa8\x29\x94\x53\xb7\xc1\xbf\xfc\xf9\xcf\xc6\x53\xd2\xf1\x43\xc7\x77\x1d\xa2\x7f\xdb\x0d\x80\x99\xdf\x12\x04\x05\xde\xa2\x4b\x55\xfc\x89\xb0\xdd\x0d\x55\x2e\x69\xbc\xcb\xe2\x4f\x10\xe4\x8c\xa7\xb8\x10\x5d\xcf\x44\xd3\xf3\xc1\xb3\xf5\x00\x73\x3d\xb6\xc3\x98\xcf\x96\x24\xb6\x08\x49\xd6\x60\x58\xc7\x30\x83\x25\xd9\x5a\x98\xcd\xf2\x37\x85\x72\x28\xd5\x9d\x44\xc9\xdc\x9f\xfe\x04\xff\x62\xd4\xad\x16\xe7\x1c\x3a\x26\x91\x67\x64\x38\xbb\xb0\x44\x7c\x06\x48\x00\x01\x13\x32\x9a\xae\x60\x1a\x2f\x82\x29\x07\xcc\xc0\x3d\xdf\x86\x1f\x7c\x60\x3c\x63\xfc\x8d\xb3\xf3\x7b\x4e\x4e\xe3\x36\xf7\x6d\x20\x38\xfa\xa4\xf1\x14\x3f\xe3\xd4\x54\xc0\x83\x7a\x80\xf9\x4c\x09\x78\x81\x5b\x48\x9b\xdf\xaa\xb6\x66\x4b\xaa\x49\x81\x9f\x7d\xf2\xf1\xbd\x5b\x09\x2d\xe0\xf9\xc2\xeb\xfc\xed\x52\x12\xd8\x41\x33\xc0\x52\x46\xe3\x04\x9d\x4a\x07\x38\x5c\x12\x58\x58\xd0\x49\x85\x51\xa2\x2c\x1c\xd5\x05\xbb\x93\xc1\x90\x9a\xea\x84\xf0\x7c\x38\x77\xc2\xae\x5f\x4d\xf8\x58\x72\xab\x4b\x7f\x19\x1b\xb9\x8f\xe1\xa7\xb9\xa7\x8e\x0a\x63\x84\xb5\x20\x0c\x1a\xc9\x2d\x85\x08\x75\x83\x96\x3b\xda\x0d\x89\x8c\xd8\xf4\x12\x9f\x08\xba\x89\xc1\xe2\xd5\x21\x4e\x31\x07\xbe\x4a\x1d\xf8\x0d\xcc\x5a\xf1\xf9\x74\xad\xc9\xf4\xe1\x6b\x0e\x02\xf0\x1a\x50\xc1\xe6\x0e\x12\x1b\xcc\xa7\x60\x7f\x1e\x68\x7c\xd0\xb2\xd5\x09\x58\x70\x2b\xd8\xc9\xdc\xd0\x13\x60\xf7\xe8\x54\xa3\xad\x95\xfa\xbd\x50\xaa\xd5\x72\xc2\xe6\xb2\x3d\xe3\xa0\xcd\x0b\xe7\x1e\x3b\xf1\xfc\xe3\xb7\xee\x5e\xfa\xdc\xbb\x6f\x7e\xf8\xea\x18\xfb\xf4\x87\x36\x3f\xf8\x04\xcc\xdf\xb5\x62\xe3\x97\x6f\xb9\x19\xce\x28\xfc\xc8\x21\x75\x3d\x36\xeb\x37\x4b\x7f\xf1\xcb\xbe\xd0\xbd\x97\x9d\xb7\xf7\xd1\x4d\x37\x2e\x5d\x28\x08\xf3\xc8\xde\xb6\x9f\x3a\x2a\x94\xa4\x00\x50\x40\x1c\x5c\x65\x62\x2f\x2f\xd9\x5b\xd0\xa9\x17\xec\x64\x6f\x75\x0e\xbd\x60\xa7\x39\x2d\x76\xe8\x48\xd3\x9c\x23\x70\x58\xf3\xfb\xa8\x31\xe6\x67\x99\x18\x2e\x55\xd7\x92\x30\xad\xf9\x01\x52\x0a\xa2\x24\x93\x3d\x45\x90\x66\xf7\x12\x55\x14\x04\xf4\x7a\xc1\x75\x88\x80\x09\x7b\x19\xa4\xa1\x00\x0d\x46\x28\xcc\xdc\x49\xd9\xfc\x55\x4e\x65\xdb\x76\xd8\xe5\x76\x5f\xf5\xbb\x17\xff\xfc\xce\xfe\x7d\xab\xd4\xdc\xd4\xab\xae\x5f\x74\xed\xaa\xcb\x56\x2f\xe7\xa4\x80\x71\xcf\x39\xf7\xee\x34\x0e\x18\xff\x63\xbc\x6b\xfc\x76\xdb\x7a\x2e\x57\xfa\xfe\x8f\x1f\x79\xe4\x91\x6f\x6e\x27\xf2\xb6\xf0\xd4\x51\xfe\x0d\x61\x0d\x50\xc9\x3d\x44\x7d\x24\x1e\xa7\x5e\xe0\xc9\x46\x1c\xce\x32\xd2\x25\xeb\x0d\x11\x19\xf0\x04\x90\x82\x51\x1e\x3b\x50\x01\xb0\x65\xd7\xda\xbb\x04\x0c\x20\x39\x97\xed\xe9\xa5\xb6\xee\x42\x58\x07\x1d\xcf\xdf\xbf\x60\xea\x4d\xe3\xdf\x7f\x7f\xde\x3d\xe7\x4d\xfb\xee\x9a\xbe\x4f\xb8\x76\x58\x0f\x3b\xce\x3f\x5a\xdf\x6c\x3c\x6e\xec\xcd\x64\x8d\x13\x99\x26\x2a\x37\x0b\x4f\x1d\x15\x56\x9b\xb4\x9d\x05\x0a\x6e\x42\x5b\x1f\x00\x15\x1a\xaa\x3a\x21\x20\xb9\x12\x9d\x3e\x9d\x00\xda\x88\xa2\xe3\x48\x06\x4b\x39\x4a\x4d\xbb\x1f\x29\x25\xde\x2b\x07\xeb\x99\x6b\x50\x13\x3d\xf9\x3c\x76\x12\xb4\xc3\x52\x15\x72\xd9\x50\xae\x85\x5c\xd5\xa9\xd6\x94\x94\x6a\xe4\x20\xa5\x60\x2f\x23\xe1\xc2\xb7\x5f\x3a\x74\xad\x33\x04\xb3\x7f\x1f\xe3\x59\xfe\xea\xbe\x37\x61\xf7\x75\x2b\xd6\x5e\x2d\x5e\xbb\x61\xd9\x6a\xae\x03\xfa\x61\xee\xe1\x0d\x8b\xe1\xb2\x63\x47\xef\x78\x04\x66\xa1\xeb\x91\x47\xbe\xfe\x50\xb2\xf4\xfd\x1f\x5b\xeb\x5e\x2c\xac\x01\x01\x10\x03\xcb\x40\x41\x21\x54\x74\xd9\x4c\x2a\x46\x24\xbd\xa4\xda\x15\xde\x93\xd6\x54\x91\x45\xd8\x00\x35\x69\xb1\x9a\x25\x26\x4d\x90\x59\x6b\x34\xde\x16\xb4\x23\xa5\xc0\xbb\x94\x3c\xb3\x6a\x58\xe4\xcd\xa5\x20\x05\xfb\xa8\x7b\xc1\x9b\xc7\xaa\xe9\xed\x95\x41\x2e\x0b\xea\x61\x92\x22\xb2\x5e\x95\x3a\x16\x60\x92\x62\xb1\x85\x30\xf2\xe9\x7b\xd0\xde\x97\x11\xbf\x7d\xf3\xd2\xd2\xe2\x99\x7b\x36\x1b\x1f\x19\xbf\x85\x63\xe1\x2e\xee\xba\xcb\x2e\xbb\x86\x6b\x85\x11\x98\x33\x3e\x7a\xff\xae\x9b\xbf\x33\xa2\xf3\x68\x5b\x2b\x1c\x01\xef\x5d\xbd\x7e\x3d\xc3\x07\xed\x00\xf0\x6b\xa5\x38\x50\x89\x5d\x16\xa0\x1c\x20\xbb\x50\x6c\x3a\x06\xd9\x02\x07\x99\x71\x2e\x39\x98\x68\x04\x0e\x13\xcd\x4b\x64\xdb\x9b\x2d\xf8\x03\x44\xe8\xfd\xc8\x91\x2e\x04\xa8\x05\x10\x20\x48\x8c\x8a\x8d\xcb\xc7\xf0\xbc\x84\x58\xbe\x55\x77\x2f\xcd\x94\xa1\xfe\x11\xa9\x1e\x32\xe7\x51\xfb\xa3\x4f\x1d\x7c\x60\xfd\x8c\x85\x33\x26\x9d\x09\xed\xc6\xa7\xc6\x41\x7e\xdd\x9d\xb3\x67\xff\x1c\x67\xfe\x5c\x3f\x7d\xec\x94\xb7\x4f\x6e\xe1\xd7\x31\xfd\xb2\xd0\x08\x08\xab\x85\x35\x20\x0a\x5a\xc0\x2a\x50\xb0\x41\x62\xff\x90\x95\xb9\x33\x1a\xb2\xe9\x34\x96\x0c\x0e\x6b\x31\x55\xc7\x31\x99\x66\xe7\x49\x59\xcd\xa1\x50\x67\x1a\x59\xab\x3f\xa3\xb5\xc1\xb4\x16\x03\x66\x74\x13\xfb\xd1\x1e\xde\x8d\x82\xe1\x86\x66\x22\x38\x49\x45\x13\x55\x42\x79\x62\xcc\x11\x9a\xdb\x50\x09\x88\x3e\xfa\xcb\xb2\x18\xf5\x26\x51\x40\x30\xc3\x3c\xe3\x60\x6f\x95\x38\x8d\x83\x44\x9c\x16\xbe\xfd\xd2\x6f\xbe\x6c\x8f\x40\xce\x78\xc7\xf8\xfb\x3f\x7f\x7c\x40\x7f\xd7\xe1\xb8\xea\x77\x2f\xbd\x01\x7b\xaf\x5a\xbd\x7e\xc5\xb5\xeb\x5f\x33\x65\x6a\xdb\x89\xed\xff\x38\x36\xf9\xe3\xb9\x46\xf0\xb6\x47\x60\x0f\xb4\x3d\xba\xf3\xf6\x07\x9a\x8b\x3f\xa0\xbc\xd8\x0e\x80\xf0\xa8\x14\x00\xaa\xe5\x7f\xc1\x9e\x9c\x75\x22\x55\xa6\x4f\x54\x59\xf3\xc2\xb4\xe6\xf1\x31\xf3\x53\x05\xf4\x76\xc5\x5e\xa4\xd9\x1c\x34\xc4\x42\xf5\x86\x0f\xb2\x28\x26\xb1\xd9\x09\x58\x47\xdb\x61\x97\xcd\x26\x2f\xfb\xe3\xbe\x5f\x1b\x07\x4b\x5f\xbd\x4e\x0a\x18\x2f\x34\xdf\xb6\xe0\xe1\xdf\xbf\xd8\xd7\xca\xdd\xfe\xd1\xe3\x2f\xf4\x7d\x44\xe8\x7c\x27\x00\xf0\x4f\x52\x00\xd8\x81\x1b\x8c\x36\xe3\xdc\x4e\x42\x67\x9b\x79\x47\x78\x68\x74\x1b\x64\x69\xc6\x85\x40\x3d\x27\x9a\xdb\x81\x14\xcd\xc6\xb1\xf8\xce\xe8\x5c\x96\xc6\x1d\x08\x4e\xbe\x73\xe7\xce\x0b\x2e\xd8\xe9\x81\x5d\xe2\xc6\xbb\xef\xfe\xc2\x17\x4f\x84\x84\x45\x27\x76\x10\x7e\x9e\xda\x60\x04\xe8\x73\x88\xfd\x75\x36\x28\x48\xa6\x90\x71\x4e\x1d\xab\x19\x4d\x16\x98\xd9\x25\x1e\xc6\x5e\x16\x47\x57\xb2\xd4\xdc\xb2\x8b\x48\xd1\x64\xca\xa9\xa1\x1c\x43\xe4\xd9\xad\xd0\x5a\xc5\xe6\x29\xe7\x4e\xff\x02\xec\xfa\xcd\xd3\x6b\xe7\xc0\x20\x5d\xcd\x5b\xfe\xb9\x73\x84\xc7\x4e\xb4\x17\x9e\x8b\xd8\x66\x93\x55\x95\xe9\xfe\x09\xcd\x27\xea\x35\xe9\xee\xcc\x51\x29\x83\xd8\x47\x89\xef\xa5\xc4\xa7\xfe\x42\x2f\x45\x68\x22\x59\x84\x8d\xbe\x75\x5b\x2e\x23\x5b\xae\xec\x34\xda\x0e\xbb\x64\xe1\x16\x98\x87\xf3\x8c\xb3\xe1\x6b\xc6\x76\xe3\x99\xcd\x52\xa0\x6f\x9a\xf1\x18\x9c\x63\xc4\xfa\xb6\xc0\x7d\x57\x1a\x0f\xb3\xe7\xc2\x57\xa4\x00\xe0\x41\x1d\x7b\x2e\x4d\xd4\x22\x36\x88\x4f\xa7\x5f\x62\xd9\x4f\xb4\x1d\x76\x49\x81\x63\x47\x81\xb5\x5e\xdb\x64\x61\x0d\x48\x91\xd3\x40\x31\x18\x8a\xe6\x72\x05\x48\xce\x05\x59\x36\xf6\xe4\xb4\xb8\x43\xc7\xc1\x2c\xc4\x4d\xf4\x0f\x12\x73\x30\x25\x53\xf3\x3b\xea\xa3\xd1\x4f\x62\xc7\x22\x9f\xae\x35\x13\x63\x11\x50\x2c\x8c\x63\x08\xdb\xf2\x38\xaa\x68\x4e\x07\xcb\xb4\xa0\x7e\xa0\x38\x31\xd7\x05\x87\x93\x9e\x86\x1c\xca\x85\x72\xe3\x21\x39\x11\xe4\x95\x89\x58\x0b\x95\xb1\xf2\x9b\xed\x7a\x3b\xea\x78\xec\x9a\x13\xf3\x63\x1d\x3f\xb9\xe6\x99\x17\x8c\xdf\xcc\xfa\xd2\xaa\x6b\x8d\x83\xb3\xbe\xb4\x76\x85\xb0\x68\xdb\xf4\x2f\x3d\x3c\x63\xee\x0b\xaf\x11\xc1\x5b\xb7\x6e\xfb\xe3\x7d\x07\xc9\xf7\x5d\xfb\x88\x04\x96\xcf\x00\xd5\xad\xe7\x9b\xbc\x70\x55\xed\x4c\x93\x89\x22\x32\x3d\x60\x3e\xea\xfd\x72\x93\xeb\xd5\xa7\x53\xbd\x1a\x30\x37\xe2\x26\x1b\x01\x1a\x94\x91\xa2\xf1\x42\xbe\x7a\xdd\xc1\x7e\x0b\xcd\x15\xaf\x7b\xe1\x57\xc6\xc1\xb9\x8b\xbe\x7a\x9d\xb0\x68\xdb\xac\x0b\x0e\xed\x67\x2b\xfb\xaf\x17\xd9\x99\x20\xba\xfe\x5e\x61\x0d\xf0\x80\x08\x91\x55\x1a\x5f\x46\xd6\x8d\x19\x72\x96\x1d\x1d\x5e\x55\xc7\x5e\x16\x0f\xb1\xa9\xcc\xd1\x11\xf0\x9a\x2e\x45\xa0\x85\x10\x2a\x07\x8d\xc9\xc5\x69\x06\x8d\x6b\x33\x0c\x16\xc2\x06\xc8\x3f\xf8\xc9\xd7\x8c\x3f\x1b\xa7\x1e\xfc\xe4\x6b\xb0\xf7\xea\xf5\x37\x5e\xb5\x72\xfd\x8d\x2b\xb9\x2e\xa8\xc0\x51\x5b\x8d\xe3\xd8\xf8\xc0\xf8\xf5\xed\xd0\x8e\x77\x3e\xf6\xa3\x1f\xee\xdc\xf9\x08\xc1\x27\x46\x40\x28\x09\x6b\x80\x1f\xc4\xc1\x15\xa6\x4f\x26\xe4\xd4\x19\xc9\x24\x13\x9f\x60\x90\xa9\xc6\x25\x81\x32\x2e\x71\x54\xe3\x12\xc1\x67\xe1\x12\xc9\x43\x17\xed\x41\x8a\x46\x3e\x23\xc8\xc4\x91\xc7\xd0\x22\xa6\x9f\x10\x93\x22\x93\x00\x47\x0e\x5c\x2a\xa8\x46\xa8\x2e\x44\x26\x36\xf9\x34\xed\x25\xd0\xe4\xca\xe7\x37\xef\x5b\x25\xcb\x57\x5d\xff\xf2\xd2\x95\xab\x97\x73\x46\x40\x9a\x76\xc7\x4e\xe3\x37\xc6\x87\x45\xe3\xd3\x6f\x6c\xdb\x1a\x34\xc6\x08\xf1\xd2\xf7\xe1\x6c\x86\x4d\x2a\x7a\x3e\x00\x12\xe4\x36\xb2\x97\xf5\xbc\x2b\x63\x45\x9e\x54\x72\x8f\x32\x41\x36\x15\xbc\xcb\xa7\x13\xe5\xd1\x48\x51\x16\xc1\x03\x3e\x25\x1c\x27\x6a\x3d\x86\x0a\x36\xc9\xcb\x12\x5a\x5d\x48\x29\x02\x89\x7e\x6e\x6a\xf4\x20\x55\xe9\x49\x34\x9a\x45\xec\x6b\xa0\xc1\xc2\xb7\xf7\xaf\x78\x60\xac\x3d\x06\x39\xe3\x37\x1e\x4f\xd7\x8e\x15\x2f\xfe\x99\xa8\xf1\xeb\x57\x8a\x4c\x8f\x2b\x70\xf4\xcc\x39\xdb\x8e\xed\x81\xaf\x8e\xbb\x6a\xd6\x1c\xd8\x05\xdd\x8f\xee\xbc\x65\x67\x73\xe9\xfb\x4c\x7e\xf9\x1b\x84\x35\x40\x06\x67\x58\x71\x8f\xb2\xf0\xba\x3d\x3a\xc4\x88\xf9\xc5\x7c\x3a\x3d\x82\x32\x93\x58\xa0\x41\xf7\x40\x59\x0d\xf1\xa6\x9c\xbe\xd3\xe1\x1b\xad\x2d\x1f\xdf\x1e\x6a\xee\xfe\xce\x43\xc2\xa2\xa7\x16\xad\x71\x18\xff\xed\xbc\x67\x4b\xdf\x7e\x60\x61\xba\x5d\xc2\x1a\xd0\x4c\x10\x2a\xcb\x9c\xb1\xd0\x88\xc3\x66\xa5\x3d\xe0\x70\x96\xd1\xca\xcc\x00\xf1\xb3\xd0\x33\xcd\x3c\x4a\x11\xac\xbd\x9b\x77\x78\xd5\xba\x46\x42\x3a\x45\x29\x48\x3e\x91\x92\xae\x4e\x65\x69\xd4\x0e\x54\x04\x92\x12\x21\xbf\xb5\x10\x20\xbb\xd1\x09\x04\x51\x03\xc1\x10\x4d\xa3\x4e\x35\xb6\xb4\x76\x13\x88\x62\xfa\x8c\x16\xbe\xf3\xfb\x5f\xfd\x7c\xe1\x9c\xef\x9c\xbf\xe5\x4b\x77\x6e\xbe\xf1\xcc\x0f\xde\xbf\x71\xd7\x79\x17\xbe\x3a\x6b\xe7\xc8\x95\x0b\x36\xad\xeb\xe5\xc7\xdc\xfd\xd0\xbc\x3f\x34\x75\x9e\xdb\x3e\x76\x4c\xf7\xc2\xaf\x5c\xb0\xab\x94\x4c\x9c\x6c\xeb\xb9\xb4\xa9\x23\xdf\xd2\xb3\xf0\x06\xba\xb7\xcc\xa9\xa3\x7c\xaf\x78\x3e\x50\x89\xae\xa3\xb9\x70\x6e\x87\x5e\x10\xc9\xde\xec\x0c\xa3\x88\x34\xaf\x4a\x14\x1c\x4c\x58\x4c\x9c\x52\x8e\x29\x05\xac\x9c\x4c\x02\x59\x02\x8e\x6a\x9c\xa2\x39\x02\xa6\x0d\xec\x46\xd5\x98\x4b\x64\x66\x8f\xbf\x7b\x02\xcc\xa9\x04\xab\xd0\x80\x8e\x4a\x76\xd7\x8d\x32\x8f\xce\x7b\x01\xe6\x8d\xfd\xe7\x8e\x9d\xb9\xea\xba\x9d\x3f\xfd\x21\xbf\x6e\xd3\xb2\xa3\xef\xbf\xdd\xf7\xf6\xa4\xf1\xa9\xb7\x72\x4f\x3c\xc1\xc5\xe8\xba\xef\x3f\x75\x54\xd8\x21\x2c\x62\x7a\x8c\x9c\x4a\x06\x13\x25\x07\x3b\x9a\xd4\xe1\xa4\x5a\xca\xde\x72\x38\x59\x7a\x8c\x3a\x9c\x94\x3c\x76\x21\x9a\x78\x23\x79\x4c\xe0\xd2\xcf\x01\x65\x19\x3a\xf7\xc3\x2e\xa2\xbf\x60\xd7\xdf\xdb\xe5\xae\xd2\x9a\x7d\xbf\x84\xb7\x70\xaf\xf7\xad\x21\x4a\x8c\xf3\x9e\xd8\xb1\x6d\xc6\x85\x87\xca\xbe\x81\xdb\x85\x45\xc0\x05\x92\x96\x0f\x0a\x96\x7d\x50\xcc\x01\x41\xfd\x4c\x65\xb7\x48\xae\x87\x7a\x43\xe0\x84\xff\x93\x74\xda\xa5\xd6\xd7\xe0\x04\x63\xae\xb1\x5f\x58\xd4\xb7\x79\xf9\x86\xd5\xd7\x73\x1b\xe8\x7d\x0e\x41\x00\x00\x69\x9f\xb0\x08\xc4\xc0\x13\x80\xa6\x63\x63\x35\x47\xff\x74\x01\x3a\xfd\xb9\x5c\xce\x02\xc1\xa6\x97\xc9\x4f\x74\xa3\x9f\x22\x60\x1a\xa5\x50\x3e\xf8\x03\x8d\x52\x00\x19\xc7\x9e\xf5\x62\x28\x63\xee\xd9\x27\x9f\xfb\xfd\x87\xbf\x21\x9f\x8a\xd8\xd9\xe9\xc5\x9e\x67\xb5\xb0\xed\x18\x0e\x3d\x8b\x9d\x72\xd1\xe5\xf4\xf8\xd3\x45\x37\x79\x2d\xb8\x9c\x55\x0e\x22\x82\xfb\x77\x73\xae\x50\xd8\xed\x31\xfd\x41\x3f\xe5\x9c\xae\x50\x38\x66\xfd\x6c\xba\x81\xfc\x90\x3a\x38\x81\x06\x62\xe4\x06\xf7\x52\xc2\x26\xfd\x41\x7f\xae\x67\x02\x64\x7e\xa0\x9c\xe9\x08\x72\xc1\x14\x9f\x0c\xc0\x51\x9b\x82\xad\x76\x21\x2e\x7f\x03\xce\xdc\xec\x4e\x71\x76\x57\x9b\xf7\x56\x98\x36\x9e\x31\x4a\x73\xaf\x73\xfc\xda\xd8\x2b\x2c\x32\xd0\x3c\x43\x3f\xff\x91\x0b\xb9\x70\xdf\xdf\x7a\x5f\x3d\x73\xfe\x5b\x39\xf8\xc1\x89\x1d\x70\x0b\x7c\xff\xe4\x37\x09\x8d\x9c\x00\x08\xf7\x50\xda\x57\xfb\x7f\xe0\xd0\xfe\x9f\x9c\x03\x26\x63\x14\x50\xb8\xa0\x13\xae\x37\xee\x85\x0b\x5e\x3f\x02\x17\x18\x77\xc1\x0d\xc6\x23\xef\x1e\xe5\xc6\x70\x29\xe3\xfb\x70\x49\xdf\x1b\x7d\xfb\xe0\x46\x63\x13\xe5\xaf\x11\xa0\xfc\x0d\x82\x34\xb0\x58\x8b\x3d\x19\x4d\x71\x52\x44\xc5\xe2\xdd\xd4\x69\xed\xcb\x63\x80\x34\x41\xce\xd7\x72\x9a\x48\x13\x45\xb8\x3d\x13\x20\x9c\x71\x28\xe6\x94\x5c\x89\x83\xf0\x0b\x46\xeb\xa4\x7f\x3c\xf8\xc5\xf3\x7b\x27\xcd\x5a\xd7\xa8\x08\x8b\xfa\xbe\x39\x7b\xd5\x15\x17\x71\x6b\x4f\xf8\x7f\xf2\x38\xfa\xc8\x73\xf9\x92\x5e\x96\xdb\xc6\x3f\x26\x2c\xaa\xf6\x0b\xd9\xf5\x82\x40\xce\x29\x6f\x3f\x9d\x5f\xa8\x3b\xa9\xc2\xa4\xda\xcb\x49\x46\x84\x9f\x6c\xd8\x39\x67\x89\x7b\x4e\x7f\xb1\x6f\x96\xce\x30\x41\xdc\x78\x8a\x7b\x55\xdc\xc3\x2c\x70\x9a\xde\xe6\xb4\xe9\x38\x9c\xd1\x42\x44\x03\x64\x34\x48\x40\x41\x22\x83\xeb\x0e\x13\x50\x1a\x08\xeb\xd8\x93\x2d\x04\xa8\x49\x1e\x08\x39\xd2\xd8\x91\x2d\xd4\x51\x35\x50\x47\x0e\x3e\xb9\xef\x02\x75\xcc\xa3\xab\x81\x10\x52\x34\x7f\x5d\x3e\x8f\x21\xd2\x64\x44\xcd\x47\x1a\x06\x23\xc7\x9f\x9c\xb2\xd1\xe3\x61\x4e\xf5\x42\x15\x05\x6c\x6a\x50\x45\x81\x60\x48\x6d\xec\x84\xdd\x68\x74\x4b\x7c\xc3\xe6\xd9\x3f\xfb\xd1\xe5\xe7\xfd\xfd\xef\xe7\x2f\xde\xf9\xf4\x05\x9b\xe1\x73\x1f\xcc\xba\x0c\x8e\xbf\xf6\xba\xee\x37\xb9\xb3\xa6\x1a\xaf\xfe\x2c\xe5\x4e\x3d\x69\xbc\x7a\xee\x64\xee\xbf\x47\x5f\xb7\x1a\x8e\xb9\x6c\x36\x00\x10\xee\x37\x32\xdc\x0e\xc9\x4b\x7d\x36\x26\xdc\x2b\xf1\x34\x1b\xc6\xfc\x66\x82\x3e\x88\x72\x08\xee\x3f\x62\x64\x6c\x7f\xfa\x34\xc9\x72\xf3\x79\xbb\x45\x03\x2f\xa1\x81\xc7\xa6\xe3\x78\x46\x03\x36\x9d\xf0\x36\x68\xd2\x80\x3f\x8c\x1d\x59\x2d\x16\x26\xa8\xb9\x10\xe3\xc9\xae\x63\x21\x47\xba\xc0\xd3\xdc\x5a\x1e\x38\xd2\xd8\x93\xa5\x34\x88\x31\x0e\x00\x2d\x44\x85\x2e\x96\xcf\xe3\x20\xd2\x6c\x52\x3e\x8f\x3d\x0a\xcd\x40\x1a\xd5\x15\x1a\x4f\xb6\xda\xdb\xdd\x42\x36\xdc\xda\x9d\x6d\x20\x84\x08\xe6\x54\x72\x2b\x05\xbc\x30\x35\xfb\xf2\xf3\x74\x7d\xda\x12\xb2\xfd\x0d\x1b\x36\xcf\x7e\xfa\x87\x8b\xb9\x73\xa6\xc0\xf4\x93\x29\x77\xea\x67\x30\x3d\xe5\x6c\xfe\xcd\xd1\xd7\xad\x32\x9e\xbf\x6c\xd6\x07\xb3\x2f\x33\xf6\xad\xba\xae\x9b\xe5\x57\x71\xad\x42\x9e\xdf\x00\x54\x90\x03\x34\xc9\x25\xa7\xd9\x25\xbd\xe8\xb7\x7b\xed\xcc\xc5\xe6\xca\x12\x2d\xce\x4c\x49\xbf\x97\x86\x2f\x34\xde\x8e\x2c\xb5\x4c\x6c\x9b\x10\xbd\xae\xa9\x4e\x6e\x25\xb7\xe4\xbc\x2b\xee\x3b\x77\xd3\x79\x9b\x16\x77\xff\x47\xcf\xd2\xef\x4d\xfe\xca\x82\xcd\x97\xf6\x6e\xe0\x5a\xdf\xb9\x3a\x91\xe8\x9d\x98\x7f\xe7\xea\x68\xf3\x19\x67\xb1\x3c\x3a\x63\x1b\x3c\x24\x2c\x02\x3c\xf0\x81\x71\xcc\x96\x2c\x79\x2a\x05\x77\x02\x35\x6f\x9c\xb2\x8e\x79\xfa\xad\x08\x9d\x82\x3d\xad\x71\x66\xa5\x1d\x07\x09\x8e\xf3\x50\x63\x27\x06\x73\xfe\xea\x4c\xb6\xb5\xb9\x8f\x73\xc6\xce\x8b\x67\xb1\x54\x3a\x63\x1b\x7f\xf0\x64\x97\xd8\x3c\x6b\xfe\xbc\xd9\x73\xe6\xb2\x1c\xb6\x6d\xa7\x8e\x0a\xb2\x78\x00\xc4\xc0\x06\x50\x88\x10\xfd\x2b\x70\x20\x5d\x72\x0b\xc0\x25\xa4\xb1\x5b\x26\x27\x05\x4b\xd9\x52\x14\x45\x04\x4f\x5a\x8b\x3a\x74\x1c\xca\x5a\xca\xd3\xa7\xd2\xe0\x68\x04\xa6\x31\x9f\x2d\x85\x69\x15\x14\x16\xb3\x85\x70\x84\x30\x36\xac\x3a\xd2\xd4\xa5\x10\x8e\x20\x96\xa7\x0b\x34\x14\xa5\x6a\x0e\xbb\x51\x01\x38\x02\xa6\xef\xc6\xce\x00\x90\x59\xfe\xc4\x62\x39\x32\x23\xa5\x4d\x4d\x75\x37\x6d\x7b\xe5\x50\x61\xe7\x2d\x0b\xa6\xde\x34\x7e\xdd\xf5\xef\xcd\xfe\xda\x92\x8d\xdf\x28\x18\x0b\xb9\xb7\xa1\x08\xeb\xe2\x3b\x1f\x70\x4c\x7a\xb7\xbe\xe9\x87\xff\x65\x3c\x11\xef\x30\xc6\x39\x9e\xfa\xc5\x18\x56\x37\x02\x80\xb0\x82\xe6\xab\x7f\xd9\x3c\xfb\x31\x5e\xa7\xe5\x8c\x04\x2a\x97\x6c\x12\x70\x7b\xd2\x38\x94\xd3\x6c\x92\x8e\xd5\x2c\x0d\x3a\x08\x87\xb1\x3d\xab\x45\xfc\x04\x8d\x16\x22\x02\xd9\x43\xa4\xde\x41\x5e\x89\xb4\x0a\x74\x53\x02\x60\xc9\xec\x5a\x44\x40\x0a\x8e\xe5\x01\x35\xe1\x89\xf6\x40\x36\xa6\xc4\xdc\x88\x16\x3b\xe6\xba\xc7\xc3\x71\x30\xd5\x9d\xeb\xef\x65\x50\x03\xb6\x24\x9a\x7d\xc5\xf4\x42\xe1\xed\x57\x5e\x78\xe1\xe2\x1f\xac\x99\x31\x07\xde\x60\xdc\xf6\x5d\xee\x37\x9f\x8e\xbc\x6e\xc9\x1d\x47\x5e\x78\xe9\xf5\xd9\x7f\x9d\x38\xff\x82\xe7\x8e\x6c\x7b\x6c\x86\x71\x12\x70\x60\x35\x30\x84\xa4\xf0\x18\x88\x81\x56\x70\x13\x60\x0a\xac\x59\xd4\xb1\x92\xd1\xe2\xa2\x4e\x23\x6d\x91\xc3\xa5\x3a\x96\xcd\x56\xc7\xb2\xd9\x5c\xec\xe0\xd2\x60\x5b\x04\x29\xbb\xb9\x80\x0a\x43\x31\x02\x95\x1a\x91\xa6\x08\xf9\x3c\x76\x29\xbb\x25\x9b\xc3\xe3\x93\x69\xc2\x56\x5c\x41\xca\x6e\x8f\x57\x0e\x04\x43\xe4\x1f\x35\x23\x2d\xe2\xa2\xf1\xec\xdd\x80\x93\xec\x8e\x18\x43\xa9\xbd\x21\xb2\x97\xde\x90\x2d\xa8\x06\x6c\x21\x5b\x2b\x41\xda\xb6\xd6\xde\x96\xee\xd1\xbd\xa1\x2a\xab\x61\xf5\x9d\x1b\x2f\x5a\x71\xe5\x45\x1b\xef\xd9\xd4\xdd\xbd\xe1\x3b\x1b\x2f\x59\xba\x66\xce\x86\x3b\x36\xf6\xf4\xdc\x77\xf5\xcc\x59\xd7\xae\xfe\xe2\x8c\x6b\x85\xd0\x9d\x1b\xbb\x7b\x37\x6d\xdb\x34\xff\x9a\xab\x16\x6e\xb8\x63\x43\x2e\xb7\xfe\x8e\x0d\x17\x2f\x5f\x76\xc9\xbe\xe9\xd7\x5e\x33\x63\xe6\x35\xab\x28\x0f\x25\x00\x84\xdb\xc4\x3d\x20\x08\xae\x07\xd4\xc1\x69\xc5\x0d\x4a\x32\xf2\x02\x4f\x1a\x3b\x72\x9a\xec\x25\x47\xb3\x14\x50\xe9\x07\x62\x4e\x0b\x78\x75\x6c\xcb\x52\x6b\xdd\x7b\x98\x98\xe9\x1e\x45\xc7\xf6\x6c\xc1\xe3\xb5\x02\xc2\x58\xca\x16\xbc\x1e\xf2\x93\x57\x76\xa4\x71\x80\x59\xf2\x1e\xaf\x15\x7b\x50\xcd\xd8\x83\x9f\x5a\xce\x39\x35\xa5\x92\xaf\x64\x37\xe1\x65\xaa\x3b\x27\xc1\xb1\x50\x82\x76\x98\x37\x36\xbd\xf0\xc9\x27\x9f\x18\x6f\xfe\xeb\x5f\xff\x7a\x86\x85\x24\xfa\xd4\xc2\x37\x0a\x6f\xbc\x51\xf8\x06\x91\x38\xae\x4a\xaf\xda\x40\x0a\x98\x15\xaa\x58\xc8\x5a\x45\xaa\x92\xf5\xce\x74\xc8\xc3\x1c\x4a\x45\x20\xd5\xb1\x47\x8e\xc0\x45\x27\x5f\x11\x30\x9f\x39\xf9\x0a\xd5\x11\x2b\x4e\x1d\xe5\x37\x4a\x71\x30\x12\xf4\x82\xad\xa0\x90\xa6\x51\x57\xaf\x8e\xa3\x19\x2d\x40\x64\xe0\x8c\x0c\xf6\x1c\xc6\x28\x5b\xea\x60\x7f\xb1\x3e\xac\xe3\x0e\x59\xcb\xc2\x74\x29\xc5\x3e\x09\xb6\x65\xb3\xc4\xe0\x96\xc2\xb4\xec\x2c\x0f\xd3\x5a\x07\x01\x71\x2e\x5f\x3e\xaf\x49\xf5\x48\xf9\xa9\xe0\x0c\x44\x13\xe9\x51\xdd\x4d\xa1\xbc\x96\xca\x22\xa5\x10\x4a\x36\x53\xc0\x2d\xa4\x59\x40\x36\x8a\x76\x43\x14\x6a\xa3\xff\x02\x07\xcc\x7a\x87\x2a\x6c\x0d\xbb\x47\x13\x59\x28\x63\x70\x89\x82\x70\xa8\x06\x68\x1e\xb6\x94\x6a\xf4\x07\x82\x21\x9a\x85\xed\x85\x2b\x66\xbd\x38\xe5\xf9\xe6\x05\x33\x9f\xdc\x72\xcb\x2d\x7f\xda\xf3\xd8\x73\xb3\x57\xac\x3f\x73\xd6\xb4\x85\xeb\x1e\xbd\x7b\xc3\xf8\x09\x1f\xbc\x74\x60\xe1\x86\x75\x33\x56\xfe\x47\xcb\xe8\x31\x07\xdb\xf3\x6b\x5b\x47\xe5\x1a\xcf\xbb\x7f\xcd\xfd\x8b\xe6\xdc\xb9\xe9\x81\x39\x3f\xcf\x36\x76\x64\x3a\xcf\xcd\x9c\xf3\xf0\x95\x85\x99\x6d\x57\x4e\xbb\xeb\x27\xfc\x79\x13\x97\x74\xe5\xbf\x74\xce\xc5\x1d\xbe\xf3\xa8\x7f\x0e\x86\x84\x4f\xf9\x7d\x92\x40\x73\x93\x33\x00\x3b\x32\x58\xcd\x69\x3c\xaf\x63\x5f\x96\x05\x85\x58\x99\x8e\x84\x58\x8e\x0a\xcb\x3f\x37\xf3\x92\xab\x35\x68\x73\xd5\x7b\x18\x3a\x6f\xe2\xe4\xf3\xce\x9f\x34\xf1\x3c\x78\xe7\xac\xb1\x93\xa6\xcf\x98\x38\x76\x96\xb8\x61\xd2\x94\x69\xe3\xc6\x9e\x3b\x65\xc2\x94\x49\x53\x27\x8c\x9b\x3a\x09\xf0\x60\xc9\xa9\xa3\xd2\xd9\xe2\x01\xe0\x03\x71\xd0\x03\xee\x64\x5e\xe4\x52\x80\x86\x40\x98\x7a\xad\x63\x51\x91\xd1\x9d\x6e\xc1\x93\x2e\x8d\x66\x3f\xa5\xda\xe8\x4f\x29\x33\x54\xd2\x4b\xef\x61\x99\x29\x55\x99\xe6\x86\x97\xd2\xec\xa7\xb4\x4c\x44\xb6\x64\xa7\x3f\x69\x67\x10\x15\x9b\x46\xca\x4f\xdd\x01\xa1\x2e\xd5\x3c\x6a\x34\x3d\xd0\x9d\xa3\x91\x82\xbb\xf2\xb8\x0d\xed\xb1\xcb\xe1\x04\x68\x19\xc5\x62\xec\xb8\xb9\x9c\x45\x28\x28\x6a\x80\x13\x52\x8d\x4d\x5c\x6f\x40\x11\x72\xd9\x26\xa5\x7b\x34\xd7\x94\x6a\x14\x38\xb1\xa2\xb3\x58\xe6\x98\x4a\x41\xfd\x92\x5f\xc2\x45\xbf\x22\x5f\xcf\x1b\x3b\x7e\x7b\xd0\xd8\xf1\xc2\xd5\xbb\x60\x7a\xd7\x2e\x38\xe2\xc7\xbb\x8c\x57\x77\xed\x32\x0e\xff\x18\x7a\xff\xf8\xcc\xcd\x37\x8e\x5d\x31\xe7\x86\x2d\x6b\xb7\x5c\xf2\x95\xb1\x8b\x27\x3d\x77\x88\x3b\x42\xff\x6f\xc6\x8e\x5f\xed\x33\x76\xfe\xf6\x20\x5c\xf0\x22\xf9\x97\xd5\xff\xcf\x57\x3e\x1d\xbf\xa1\xe7\xbf\xee\xfb\xc1\xa3\x99\xcd\xb1\xd0\x87\x54\xde\x33\xdc\x87\xdc\x5e\x71\x3f\x08\x81\x24\xf8\x36\xab\x43\x2f\x49\x94\x32\x58\xcd\x94\x62\xec\x5d\x3c\x53\x12\x4c\x6a\x35\x52\x6a\x85\xd9\xc1\x0a\x5b\x01\x9c\x92\x8f\x7d\xe0\x93\x4b\x88\x91\x0e\x65\xb4\x14\xa1\x17\x30\xd3\x41\x71\x03\x2a\x48\x6e\x5a\x92\x41\xed\x1b\xa0\xc5\x54\xa4\x68\xb2\x42\xab\x35\x88\xd0\x0b\x44\x1b\x30\xaf\x31\x76\x2b\xd8\x61\x85\x77\x68\x74\xc7\x74\xdf\xa4\x5a\x29\x7d\x7a\x4d\xe7\xab\x4d\xca\x3c\xf2\xc4\xe5\x1b\x67\x7d\x7d\xf2\xe4\xff\xbc\xfc\xb6\xbb\xb7\xc4\xd3\x37\x4d\x5b\xbb\xe1\xe5\xce\xc4\xf4\xf9\x97\xdf\xc1\x1f\xbc\xfa\x6a\x87\xb0\x76\xdc\x96\x44\xf6\x5b\x9b\x8d\x29\xd7\x9c\x39\x71\xed\xca\x96\xa6\x0b\x26\x35\x49\x4e\xc0\x81\xd9\x60\x91\x70\xbf\x20\x00\x09\x78\x68\x56\x79\xc8\x01\x6d\xe6\xb7\xd9\x70\xcd\x11\x43\x87\xa1\x23\x5b\xe0\x75\x7f\x20\x6f\xfe\xc0\xa5\xa2\x70\xff\x0d\xc6\xc3\xc6\xc3\x37\xc0\x7d\xe5\xb7\x66\xbe\xf8\xa7\x42\x9e\x9f\x00\x44\x82\x67\x58\xc6\xb9\x55\x35\x48\xab\x99\x25\x72\xdd\x99\xf0\xae\x20\xf0\xe5\xab\xcd\x56\xae\x0c\x4c\xa1\x79\xfc\x9b\x47\xb8\x25\x47\xfa\x9e\x80\x2b\xc1\xff\xae\x7e\x4f\xa8\x39\x13\x1d\xa0\x07\x94\x86\x3e\x15\x23\xd9\xa9\x18\xc9\x7e\x33\xb2\x93\xac\x6d\x64\xc2\x91\xc6\xed\xd9\x52\x63\x0f\xfd\x5d\xe3\x30\x67\xa4\x83\xfd\xd4\x99\xb5\xf4\x5f\x33\xfb\xa0\x79\xc0\xa1\xc9\x76\x20\x65\xb7\x3b\x50\x27\xa4\xdb\xd8\x9d\x87\x47\xd0\x32\xae\x76\x72\x7c\x46\x22\xa5\x64\x97\xc3\x80\xfe\xaa\x07\x7d\xa6\x63\x03\x11\x2b\x38\xb6\xf9\x53\x7c\x55\x72\xcd\x67\x38\x36\x2b\xa0\xed\xd1\xef\xcd\x9d\xf6\x3e\x7e\x79\xe3\xb2\x59\xf3\x67\x2f\x58\x72\xda\x43\xd3\x77\x17\xbf\x71\xf3\xad\x17\xac\xab\x37\xd6\xc0\xc5\xc6\x03\xf0\xcd\x99\x93\xce\x9d\x44\x6d\x93\x53\xc7\xa5\x80\x20\x49\x6f\x00\x1e\x84\x18\x9f\x44\x9d\x7c\x55\x45\x5f\xf9\xee\xa4\x2a\x09\x6e\x29\xf0\xd2\x4b\x80\x03\x0b\xf9\x08\x4f\x30\xa0\x17\x44\xc1\x54\x33\xaa\x1c\xf6\xd2\xac\x3d\x45\xb4\x12\x54\x2b\x47\x49\x53\x2b\xd9\xf2\x75\x34\x5d\x95\xc0\x3b\x81\x5c\x14\x61\x85\x1c\x2b\xb3\x10\x85\x9c\x0d\x56\xd3\x57\x3e\x1a\xa6\x53\x71\xe1\xf6\x45\x0b\x1f\xbc\xf8\xe2\xed\x17\xdf\xf1\xd2\xcf\xe7\x4f\x9e\xbc\xe0\xa2\x49\x13\x2f\x12\x56\x93\x4f\x77\x2c\xbc\xf8\xc1\x05\xfb\xef\x98\xb8\x60\xe1\xf8\x09\x8b\x16\x02\x0e\xcc\x03\x40\xc8\x8b\x1c\xc5\xc6\x4b\x4c\x24\xc7\xaa\x27\xb0\x2b\xa7\x89\x92\x4e\x2c\x29\x81\x26\xdd\x08\x5e\x47\xba\x20\x52\xd8\x26\xda\x1c\x0c\x3b\x7b\x0f\x93\x5b\xd6\xc3\x96\x5e\x41\x01\xbc\x23\x8d\x9d\x65\x14\x60\x26\x8b\x22\x33\x59\x94\x56\x61\x54\x0a\x63\xf9\x37\x4f\xc6\xad\xe2\xd8\x23\x47\xb8\x1d\x47\xe0\x2d\xc6\x7a\x56\x1e\x4b\x63\xe5\xd3\xb8\x67\x68\x7e\xf7\x2c\x33\x3f\x20\x20\x52\xca\x39\x44\x16\x32\x40\x87\x35\x31\xac\x17\x44\x44\xd7\xe5\x72\xa4\x0b\x88\xae\x16\xb9\x1d\x69\x66\xfd\x3a\xdc\x2c\x70\x10\x40\x05\x11\xd1\xd0\x32\x57\x5b\x4e\xe1\x23\xb0\xb1\xbb\x5c\x4b\x91\xb9\xf3\xe9\xdb\x1e\x58\xb4\xe9\x4a\x78\x69\xdf\xba\x3f\x2f\xcb\x8f\x6a\x9b\x75\xb9\x38\x6d\xd3\x2d\x6b\x2f\xbc\x67\xed\x25\xbf\x7c\xf4\xc8\x92\xf9\xd9\x96\x36\x9a\xa7\x35\x86\xcb\x73\x7b\xc4\x97\x40\x33\xc1\x4f\xb4\xec\x11\x79\x75\xdc\x94\xd1\x78\xaf\x8e\x1d\x19\xcd\xe9\x65\x8e\x38\xf1\x70\x29\xc9\x28\xe4\x4d\x1c\x46\xa5\x18\x53\x0a\x5e\x6a\x9d\x79\x1d\x8e\x34\x75\xca\xc5\x44\xa4\x68\xf5\x0d\x84\xcb\x7c\x13\x83\x03\x0e\xa4\xc1\x24\x33\x4f\xc9\x2f\x30\x42\x5a\x80\x98\x6c\x61\x96\xaa\xe5\xef\xa6\x35\xf7\xe5\x3a\x48\xea\x87\x35\x35\x66\x80\x65\xd9\x4b\xa9\xc6\x31\x77\xad\xdf\x36\x6f\xc6\xaa\x85\x17\xcc\xca\xe6\x32\x73\xf2\x4b\xc7\x7f\xf7\x8a\x8d\x3b\x1e\x5b\xb4\x1c\x3f\xb9\x8d\xdb\xf8\xcc\x82\xab\xba\xbb\xb7\x8f\xce\xb7\x64\x5b\xda\x6e\xcf\x8c\xff\xea\xf2\x6d\xbd\x9e\xc0\x35\x5f\x5c\xf7\xcd\x81\x39\x03\x20\xa3\xf1\x95\x9c\x01\xb1\x9c\x33\xa0\x89\xa6\x3b\x73\x54\x17\xec\xee\xe9\x4d\xaa\x5e\x68\x83\xe7\xef\x9a\x00\xe7\x8e\x3e\xf1\x05\xe1\xf5\xd8\x2f\x97\xaa\xa3\x5f\xce\x32\x3f\xbf\x11\x10\x1e\x15\x16\x81\x30\x58\x30\x84\x7f\x8c\x3a\xad\x23\xac\x84\x8d\x05\xbf\xc2\x15\x2f\x59\xd4\xbc\x57\x88\x7d\xe3\x40\xd4\x57\xa6\x94\x7d\x65\x05\x2f\xad\xfb\x1b\xc2\x5b\xd6\x1a\x87\x68\x3b\xec\x9a\xb7\xe8\x3f\xae\x83\x5d\xef\xa4\x7d\x23\xbe\x32\x6f\xfc\xf2\x84\x28\x1a\x01\x69\x5a\xdf\x9a\x75\xeb\x7e\xfc\x0b\xce\x7b\x62\xc7\x3d\x17\x5e\xd8\x39\xf2\xc2\x1f\x18\xcf\x02\x08\x56\x1b\x27\x85\x6d\x52\x00\xf8\xc0\xf9\x00\xdb\x33\x1a\x2f\xea\x05\x3b\x55\xe3\x76\x0f\x31\x59\xec\x4e\x07\x31\xc5\xe8\x21\x70\x1e\x2e\x39\x98\x0e\x74\xc8\x25\x20\x03\x9b\x90\xc6\x20\x83\x1d\x34\xad\xb5\x24\x32\x85\x88\xcc\x5a\xfa\x9e\x1c\x91\x7a\xf2\x1f\x81\x3c\xab\xff\xef\xdf\xb8\x85\x0f\xee\xdc\x31\x7e\xce\xff\x39\x20\x28\x50\x30\x3e\xfd\x9b\x34\xf3\x18\xe6\x73\xca\x71\xe6\x07\x59\xcb\xb5\xc3\x43\xfc\x86\x7f\xa7\x2e\xdb\xdf\xbf\xd4\x8b\xd8\xa7\xdc\x21\xab\xb2\x0a\x9e\x3a\x62\x04\xe0\x0e\x00\x80\x02\xa6\xb0\xca\x84\x92\x8d\xdd\xf7\x72\x86\xa5\x6a\xf8\x69\x4a\xb6\x27\xcc\x52\xe1\x3c\xa2\x99\x9c\x01\x34\x5e\xb6\x92\x31\x34\xe0\xc9\xd3\xc4\x05\x67\x7e\x54\x17\xcf\x20\x6a\x6b\x6f\xce\x02\xa2\xad\xcd\xb1\x8b\x22\x53\x77\xce\x78\x2e\x36\x6d\xde\x77\x1f\x98\x71\xb6\xf1\x8a\xcd\x3b\xfe\x82\xc8\xfd\xe3\xc2\x4b\x27\x7e\xf5\x3a\x95\xed\x6d\x21\x37\x8d\x9b\x4a\x73\x5c\x1b\x41\x6d\x19\x75\xb8\x52\x46\xad\x41\x1b\x8b\x33\x36\xe7\x50\x8a\x15\x52\x2f\x84\x1d\x3f\x7f\x9f\x17\x63\xa3\x66\x08\x07\xde\x3d\x79\x17\x7c\x66\xd5\x25\x4d\x23\xc6\xb1\xb8\x71\x9e\xfb\x90\x7b\x53\xdc\x4f\x71\xe9\x54\x60\x96\x8d\xb3\xe3\xe8\xf3\x5a\xb0\xd4\x6c\xea\x62\x16\x90\x5b\x5d\x6c\xca\x35\xe4\x2c\xb7\xb7\xba\x86\xbc\x8a\xa2\xd5\x8a\x36\x5f\x7c\xe8\xde\x27\x7f\xfa\x9f\xf7\x3d\x71\x60\xd2\xd4\xa9\x13\x26\x4c\x9d\x3a\x49\x58\xf8\xa3\xe7\xf7\xed\xfc\xaf\xe7\xf6\xfd\x70\xc9\xd2\xa5\x4b\x96\x5c\x7e\x39\xe8\x8f\x39\x7a\x1d\xb0\x17\xaa\xb0\x99\x7d\x9b\x0d\x83\xc6\xdf\x8f\xc0\x35\xc6\xed\x30\x5e\x7e\xfb\x2a\x5c\x08\x17\xde\x60\xe4\xa3\xc6\x98\x1b\x2a\x6f\xa9\x2b\x17\x74\x02\x20\x7d\x87\xd2\xcc\x0b\x22\x20\x09\xee\x62\x5e\x5d\x1c\x32\x33\xab\xdd\xb9\x92\x2f\xea\x82\x9e\x34\xf6\xe7\xc8\x8e\xb1\x9a\x2d\x44\x7d\x44\x6e\xa3\x8a\x83\xe1\x38\x46\x60\xcc\xd3\xfb\x1a\xc7\xb2\x5a\x88\x79\x8e\x42\x61\x5a\x4d\xae\x3a\xd2\x85\x30\xad\x31\x0f\xfb\x1c\x69\x8a\xe6\x08\x1f\x0a\xd0\xe6\x22\xba\x33\x8c\x0a\x6e\x6f\x94\xbc\x0b\x29\x1a\xa2\x41\xa3\xa8\x8f\x25\xb3\x40\xa4\xf1\x0d\x94\x5e\x15\x5e\xf9\x61\x0e\x36\x77\xc3\x1c\x22\x36\x5e\xaa\xbb\x35\xd7\x3d\xba\xd7\x0b\x6d\x9d\x65\x16\x3e\xc2\xa7\x3f\x38\xf9\x2a\x5c\x07\x37\x1d\xdd\xb0\xe1\xfd\x17\x5f\x94\x1c\xdd\xbe\x6a\xb6\x9e\x28\x89\x7b\x8e\x4f\xbb\xf7\x7e\x6e\x52\xdf\xcb\x8f\x7e\xf7\xbb\x8f\x3e\x3c\x77\x71\x74\x65\x88\xd6\xc3\x12\x5a\x94\x4c\x5a\x34\x83\x6f\x99\x7e\x68\x57\x4e\x0b\x8b\x7a\x99\x1a\x28\x45\xa8\xa1\x21\x91\xe9\xe2\xca\xe6\x13\x30\xad\x05\xc2\x7a\x21\x90\xa0\x4e\xc3\xa8\x23\x5d\x48\x50\x8f\x61\x22\x66\xaa\xe4\xea\x6d\x27\xd0\x6e\xb7\xc7\xeb\x43\x61\x0a\xfe\xc3\x31\xa4\xe0\xba\x3c\x4e\xa1\x92\x10\xe0\x13\x34\xa5\x80\x79\x27\x20\xd2\x6c\xce\x81\x34\x70\xc0\xc1\xef\x9a\x01\x74\xf8\x64\xe0\xe5\x33\x90\x1a\x3c\x1c\x78\x1d\x01\x01\x2c\x00\x40\xc2\xf4\x3e\x6a\x07\xa3\xc1\x58\xf0\x17\x96\x3d\x8c\xb3\xb9\x42\x2b\x07\xd2\xe5\x2b\xaa\x34\xa2\xbb\x25\xec\x49\xe3\xce\x9c\x36\xc2\xab\xe3\x51\xd9\x42\xf7\x08\xb2\xf1\xee\x0e\x47\xba\xd4\xc4\x93\xdf\x69\x4d\x5e\xbd\xe4\x74\xd0\xb7\xf4\x1a\x1b\x77\xfa\x6b\x0c\x27\x65\x2d\x07\xd3\xb8\x27\xab\x65\x89\x75\x9c\x2d\x64\x73\xe4\x77\xd9\x51\x8e\x74\x21\x97\x25\x6f\x73\x23\x1c\x69\x6d\xbc\x79\xdb\x15\xea\x1b\xda\xf3\xf9\xbc\x96\x4b\x22\x45\x6b\xed\xce\xe7\x71\x16\x69\x23\xdb\x88\x44\x75\x8f\x40\x0a\x4e\xe7\xe9\x4d\xa8\x01\x42\xff\x21\xee\xc2\xcf\x7a\x0b\x0e\x21\x86\x0b\x86\xbe\x1c\xff\x8b\xf1\x63\x66\xb5\x5c\x0e\x73\x61\xf6\xed\x1f\x42\x4c\x01\x07\xc6\x19\xeb\xf8\xd7\x68\xac\xa4\x15\x5c\x07\x0a\x71\x08\xd2\xa5\x66\xab\x58\x94\x79\xea\xdb\x98\xbf\x4f\xa1\xfe\x3e\x02\xfa\x1a\x65\xbd\xe8\x68\xac\xb3\xa7\x2d\x7f\x82\x23\xac\x53\x6f\x93\x8f\x15\x8b\x6b\x52\x1d\x52\x34\xc1\x43\x49\x53\x72\x2b\x91\x78\x33\x95\x4c\xc5\x6c\xed\xd3\x8c\x0a\xc0\xc6\x6e\xc4\x10\xad\x13\x1d\x07\x93\xac\x72\x54\x65\x51\xcf\x10\xbd\x18\xab\x4d\xf1\x71\x97\x6d\xbb\xa4\x1b\xda\xe7\xaf\xbc\x3a\xff\xa5\xf9\x5f\x2c\x5d\xba\x6c\xf1\xbf\x56\xfc\xe1\x04\x9c\x61\xb9\x37\xeb\x57\x3e\x70\xe5\x94\x69\xe3\xc6\x4c\x5b\xfc\xad\xe9\x33\xe6\x4d\xc8\x4f\x3b\x73\xc4\x1b\x67\x9c\xf3\x9c\x70\x63\xc5\xdf\xc9\xb3\x3a\x47\xdb\x1a\x60\x03\x32\x08\x82\xe9\xfd\x2b\x1d\x51\xa5\xd2\x31\x34\x58\xa5\x63\xd8\xac\x74\xdc\x0d\x39\xbb\x1b\x29\xac\xd6\x11\x99\xb9\xe9\xe5\x5a\x47\x2b\x37\x71\x60\xd1\xa3\x60\x26\x2b\xae\xaa\x2d\x7e\xb4\x2d\x62\xb9\x8b\x27\xce\x66\x45\x90\xd5\xeb\xf4\x80\x20\x98\x3b\x4c\x45\xe6\xb0\xeb\xdc\x03\x39\xbb\xc3\x8b\x82\x34\x46\x8a\x34\xc5\x9f\x1f\xba\x38\x93\xb7\xe0\xd1\x20\x55\x9a\xb7\x98\x80\xa9\x5f\xb5\x26\xfc\x5d\x05\x3f\x55\xaf\x59\x05\x31\x70\x49\xff\x35\x07\x2b\x6b\xae\x1b\x6c\xcd\xf5\x30\xcd\xf2\x57\xa8\x5d\x2e\xa0\x9f\x42\xce\xe5\x46\x2a\x73\x48\xf2\x2c\xec\x0f\x34\x18\x44\x0a\x8e\x56\x16\xef\xa2\xa8\xae\x01\x86\xd4\x54\x4b\xab\x64\x1b\x48\xf2\xf1\x4f\x9f\x05\x97\xc6\xef\x9b\x7a\xe0\x07\xd3\x67\x7c\x37\x5d\x4b\x77\x29\x1d\x7b\x7a\xd5\xe8\xe2\x94\xd8\xc5\x17\xcc\xba\xe4\x64\xb7\x59\x81\x5a\xd9\xcb\xa5\xc0\x06\xe2\xa0\x19\x72\xfd\xf7\x92\xb0\xf6\x82\x43\x19\xcd\x1e\xce\xe5\x34\x59\xd4\xb1\x2f\x5b\xac\x93\x43\xf6\x34\x8e\xe5\x34\x97\xa8\x6b\x6e\x7f\x36\x6b\x55\xf8\xf7\xdb\x6c\x2b\x0b\x34\x1e\x1d\xff\x42\x82\x06\x1a\x63\x9d\xd8\xd7\x89\x63\xb2\xe6\xae\x3b\x46\xce\x58\xb8\xee\xd8\x93\x6f\xef\xd8\xf7\x13\x9a\x90\xee\x96\x8b\x1e\xb7\xcf\x9f\x2e\x7a\xc9\x2b\x8e\xc9\xc5\x48\x2c\xec\x4f\x17\xa3\xe4\xb5\xe0\x71\xfb\xaa\xe2\x8d\xde\x7c\x21\x1a\x0b\x93\x77\x91\x3c\x28\x7a\xbc\x2c\xe5\x1c\xfe\x94\xdc\x0e\xe1\x48\x34\x56\x13\x75\xec\x4f\x6e\x7f\x28\x9e\x48\x9a\xe4\x0e\xd0\xac\x26\x98\x40\x0a\x6e\xaa\x26\x37\x35\xeb\x38\x72\x44\x73\xe4\x88\x76\x72\x44\xa1\x0d\x24\x7b\xbb\x6b\xdb\x97\xdb\xbf\x38\x7d\x5a\x53\x3c\xef\xb9\xdb\x75\xc7\xf5\xd6\xfb\xf3\xfb\x71\xa0\xfd\x8e\x87\x93\xad\x89\xd1\x3d\xe4\x5b\xb2\xbb\xe7\x64\xaf\xc5\x04\xc1\xe4\xc1\x5c\x60\x03\x7e\x5a\xcf\xbe\xa1\x3f\x17\x02\x65\x2e\xa0\x0c\x4e\xe5\x34\x17\xaf\xe3\xfa\xfe\x14\xb7\xc3\xb4\xe6\x45\x34\x13\x86\x20\xf4\x84\x42\x4b\xdd\xab\xf8\xa0\x79\xed\x48\x29\x48\x90\x86\x23\xa2\x08\x87\xf3\x38\xa1\x14\x44\xda\x90\x0c\x68\x30\x40\x93\x0d\xaa\x0e\x4b\x4d\x17\x43\xb2\xed\xea\x4f\xaa\x49\x10\xb7\xdc\x85\xf7\xb1\x3d\x2f\x2a\x3b\x0d\xad\xcd\x1f\x34\x9d\x87\x27\x7e\x4b\x77\xcd\x7d\xd9\x72\x22\x56\xc9\xa0\x93\x6a\xaa\x24\xf8\xba\xb9\x7b\x77\x0e\xfb\x32\x1a\xe2\x75\x1c\xcf\x98\x2e\x31\xd3\xfd\xa5\xc9\x32\xad\x6c\xe2\x61\xba\x14\x62\x80\x3f\x44\xb5\x75\x05\xfe\xd3\x1a\x0e\xb7\xac\x33\xd8\x24\x33\x4c\x10\x42\x1a\x44\xf9\x3c\xae\x53\x34\x55\x62\x77\x99\x4b\xa1\x21\x37\xec\xcd\x03\x2d\x8e\x90\xb2\x9b\x77\xb8\xa0\x1a\xa1\x51\x80\x2e\xd8\x62\xf5\x18\xb3\x55\xab\x8f\x40\xc8\xba\xdf\xe0\xc7\xe9\x2d\xab\xaf\xfe\x76\x06\x7e\x52\xa3\x44\x26\x5f\x36\xa2\xa7\x67\xc4\x88\x5e\xf1\x9b\x67\xce\x5b\xb9\x69\xd3\x8a\xf9\x63\x8e\xaf\xad\x56\x26\xbf\xb8\x58\x18\xdd\xd1\x91\xcb\x99\xf5\xe8\xb6\x66\x5a\x9b\xe7\x07\x17\x31\x5f\x11\x06\xb9\x4a\x89\xb2\xe0\x26\x98\xb0\xe4\x95\xdd\x9c\x87\xd6\xd6\x96\x44\x3b\x7d\x2b\x9a\x45\x67\xd4\x1b\x5e\xae\x1c\xa6\x86\xbe\x83\xa3\x66\xbf\x59\xc8\xab\x52\x63\xa4\x0b\x56\x2a\x87\x93\x28\xc9\xc3\x24\x4a\x71\xdb\x84\x7b\xfa\x5e\xe6\xbc\x7d\x1f\x71\xb9\x93\xdf\x35\xd4\x7b\xa0\x0d\xde\xb8\xb1\x52\x4c\xcc\xd6\xcc\xcd\x60\xf5\x67\x01\xb3\xbe\xbb\x1d\xac\x63\xd9\xaa\xa5\x78\xc5\xa7\xa5\x39\x79\x1d\xb7\x66\xb4\xa8\xb7\x5c\xeb\x3d\xc2\xaa\xf5\xc6\x1e\x76\x95\x36\x85\x75\x2d\x0d\xd3\x5a\x9d\x07\x29\xc5\x50\x43\xbc\x95\x1c\xc0\x26\xb4\xdb\xe9\x0b\x08\xf4\x34\x02\x2d\x10\xa5\xbf\x4a\x36\x35\x85\xf2\x9a\xad\x95\x80\x0e\xcf\x67\xa8\x0a\x87\x03\xed\x9e\x21\x0a\xc5\xe1\xa6\x5a\x7b\x68\xd0\xc2\xf1\xbe\xc5\xfd\x8d\x24\x56\x07\xc8\xd9\xd6\x00\x17\x08\x80\x59\xa7\xab\xe6\x56\x4f\x57\xcd\x4d\x13\x4d\x88\x4e\x72\x7b\xac\xcc\xd1\x32\x77\xca\x19\xff\x55\x05\xde\x7d\xd0\xbc\x4f\x2b\xcc\xb1\xae\xd2\x7e\x6b\x9b\xf3\xbf\x5d\x1b\x96\xb3\xa7\x59\x9e\x79\x7b\x56\x2f\x6f\xa7\x75\x6d\x96\x97\x27\xa5\xad\x1b\x93\x03\x3f\x01\x40\x08\xd8\x58\x1e\xdf\x2c\x16\xe1\xd2\x42\xbc\x5e\xf0\xd1\x0e\x55\x6e\xbd\xe4\x0f\x7a\x7d\x1e\x5a\x52\x49\x53\xfa\xbc\xb4\x2b\x12\x35\x85\xa8\x1b\x2b\x14\xa1\xcb\x62\x36\x11\xcd\x3f\x0b\xd1\xf4\x3e\xb6\x38\x7f\xcd\xbd\xc8\x57\x2d\xf5\x27\xd5\x37\xe2\xf3\x95\xe5\xd6\xdc\x86\xc7\x5e\xad\xaa\x9e\xe7\x4d\x5a\xce\xa5\x76\x6b\x0a\xdc\x34\x3c\x35\x09\x31\x93\x39\xcd\xc7\xeb\x38\x56\xce\xf7\x1c\x86\xb4\x0e\x19\x2b\x89\xc3\xc8\x2a\x15\x56\x10\xcd\xa2\x23\x18\xa6\x41\x61\xe9\xa0\x0e\x62\xf7\xfa\xd4\x81\x54\x1f\x22\x54\x53\xcd\x04\xef\x20\x51\x9b\x0a\x3f\x0e\xf6\x8f\xdf\x70\x60\x04\x00\xdc\x11\xdb\x1a\x60\x07\x01\x70\x96\x99\x73\xec\xa5\xe6\xbf\x4a\xdb\x04\x2a\xaa\x5e\x50\x68\x67\x50\x25\xe0\x48\x63\x5f\xb6\xe0\x52\xc8\x4f\x2e\x07\xcb\x64\x20\x62\xa2\xb8\x88\x75\x6e\xa6\x20\x5b\x92\xcb\x57\x15\xa2\x8f\x30\x25\x77\x24\x2b\x48\xb7\xc4\xf6\xd3\xbf\xf4\x2b\x4d\x07\x1c\x98\x0c\x00\xdf\x69\xca\xf1\x94\x9a\x2a\x78\x35\x83\x39\xda\x5b\xe7\x74\x85\xf0\x54\x72\x39\x42\xc3\x00\xa3\x61\xd5\x4a\xca\x92\x6b\xd6\xc6\x1b\x8a\x29\xb5\xd5\x2b\xa9\x92\xdb\x53\x7f\x00\x80\x9f\x64\xca\xed\x24\x33\x32\xeb\xa7\xeb\x89\x66\xb0\x4c\x85\xb4\x10\x92\xcb\x12\x1a\xc8\x16\x64\x6a\xaf\xcb\x5e\x47\x1a\x2b\x59\x26\xa9\x32\xad\x53\xa5\xbe\xe8\x1a\x39\xad\x5a\x58\x53\xb5\x9c\x2e\x65\x8b\xeb\x27\xa3\xfd\x88\xc5\x83\x3c\x00\xdc\x3b\x65\x39\xbd\xcc\xac\xe0\x40\xac\x8d\x31\x11\x4a\xbe\x22\x94\x5e\x9a\xbb\x59\x94\x54\xaf\x3d\xad\x01\x44\xf3\x76\x24\xa4\x17\xc3\xf4\x03\x4b\xf4\xbc\x00\x29\x25\xde\xe1\x96\x11\x51\xbe\x0d\x2a\x52\x4a\x4a\x30\x14\xa3\x8a\xb9\xd6\xf5\xe2\xaf\x26\x6a\xd5\xe7\x79\x4b\x00\x1d\x26\x81\xff\x61\xc9\x61\x59\xfa\x8e\xad\xaa\x21\xf6\xc1\x2a\x1c\xc0\x81\x8c\xd9\xab\xc3\x0d\xc2\xe0\x0a\x33\xdf\xd7\x63\x55\xb8\x05\xdc\x7a\x09\x40\xa7\xe0\x49\x63\x35\xa7\x01\x37\xcb\xcf\x88\x10\x41\xc5\x5c\x96\x56\x09\x07\xb2\x05\x0f\x15\x57\x4f\xc8\x91\x2e\xb8\xe8\x5d\xe8\xa2\x59\x37\xac\xdf\x84\x2d\x48\x9d\x97\x66\xd9\xba\x4d\x66\x66\xab\xd5\xdc\xa3\x1d\x22\x98\x4b\x20\x62\xc1\x12\xeb\x34\x73\x5b\xa5\xc9\x87\xb1\x18\xf6\x6c\x86\xcf\xff\xf6\x77\x0f\xbd\xf7\x1e\x37\xc7\xe0\x96\x58\xcd\x3e\xb8\x39\xc6\x2e\xf8\xe6\xdf\x3e\x30\xee\x37\xcc\xda\xe6\x97\x6c\x97\x02\x1f\x68\x85\x9e\x01\x95\xf6\x38\x9e\xd1\xe4\x44\x8e\x7a\x45\x70\x28\x5b\x6c\x0a\xc7\xed\x69\x82\xe6\xfc\xa2\xae\x05\x62\x04\x41\xb7\x0d\x5f\x8a\xdf\xde\x0f\x4b\xa7\x3a\x71\xa8\x13\xa7\x64\x2d\x50\x77\x8c\x20\xa0\x44\x35\x96\x0e\xc8\x45\x35\x10\xf2\xa7\x8b\x41\xf2\x8a\x53\x72\x31\x99\x4a\xf8\xd3\xc5\x46\xf2\x5a\x50\x03\xa1\x2a\x2c\x1d\xcc\x17\x1a\x53\x09\xf2\x2e\x99\x07\x45\x35\x98\x6c\x64\x58\x3a\xa0\x06\x43\x89\x64\x63\xaa\x06\x4b\x13\xc3\xb7\xe8\x62\x62\x82\x25\xb4\x9b\x73\xfa\x63\xec\x2e\xa7\x4d\x01\xb0\x1d\x69\x75\xb4\xcc\x73\x98\xe6\x00\xfc\xa0\xe0\xba\x5f\xcb\x80\xf4\x10\xc8\x7a\x60\x2b\x81\xfe\xe0\x1a\xf0\xac\xaf\x00\xd5\x25\x2a\x68\x00\x5f\x18\xb4\xb3\x40\x7c\xb0\xce\x02\x09\xb3\xb3\x40\x91\x77\x04\xa3\xac\x23\xd2\xe9\x9a\x0b\x94\xf5\xde\x30\x5d\x06\x44\x53\x0d\x0e\xd9\x6d\x80\xdf\x6a\xde\xe7\xfd\xd7\x3e\xf3\xdf\x5f\x7b\x89\x77\x04\x23\x0d\x8c\x3f\x5a\x34\xf6\x99\x3a\x24\xf8\x2d\xed\x38\xcc\x26\x0e\x9b\x0a\x73\xc8\x4d\x70\xf3\xab\xed\xe4\xca\x3e\x22\x20\x05\xe6\x9b\xfb\xa8\xb7\xf6\x91\x24\xfb\x60\x77\x66\x34\x44\x0b\x23\xe2\xe6\x3e\x9a\xcd\xb6\x70\x14\x7f\xe0\x38\xda\xcd\xfb\x64\x35\xc2\x9a\x16\x28\x9a\x3f\x40\x5b\x03\xd7\x0f\xbe\xa1\x5a\x2d\x3b\x4c\x03\x08\xa9\x5a\xeb\x6e\x1d\xaa\x1b\x84\xf0\x44\xb5\xe5\x5c\xa8\xb4\x32\x28\xef\xef\x52\xe0\xa2\x3d\xa4\x4f\x9a\xfb\x6b\xb5\xf6\x97\x26\x1a\x38\xa3\xb9\xeb\x72\x39\x1a\x2c\xf3\x67\x8b\x89\x40\xcc\x9e\xc6\xf1\x9c\xe6\x13\x75\x4d\x0e\x91\x33\xcf\x9a\x48\x37\x85\xca\xed\xa2\x09\x01\x32\xfd\x4e\x7a\xbc\x13\xfb\x3b\x71\x5c\xd6\xe4\xba\x63\xd8\x2f\x6b\x75\xd5\x27\x5d\x96\x8b\x48\xf6\xfb\xd3\x45\x85\xbc\xe2\xb8\x5c\xac\x8f\xd7\xf9\xd3\xc5\x06\xf2\x5a\x40\xb2\xbf\xea\xa4\x2b\xf9\x42\x43\xbc\x8e\xbc\xab\xcf\x83\x22\x52\xea\x1b\xd8\x49\x97\x91\xe2\xaf\xee\x5a\x4e\x4f\x7a\x53\x99\x05\xed\x84\x05\x8e\x50\x2c\x65\xb2\x20\x1c\x21\x2c\x48\xb7\x0e\xce\x82\x41\x0f\xf7\x70\xac\x88\x0d\x71\xd2\xaf\x1a\x92\x2b\x3f\xed\x67\x4d\x97\x2a\x8c\x11\x4c\xbe\xcc\xa5\xe7\x27\x09\x3a\xc0\x8a\x41\x4e\x10\x39\x40\xe9\x9c\x16\xe1\x75\xdc\x5c\xe6\x82\x79\x9c\x08\x88\xa8\x43\xba\x99\x62\xa6\xb5\x29\x3a\x6e\xab\x1c\xb2\x0c\x4c\xd3\x66\x96\x45\xde\xe7\x77\x7c\x46\x05\x31\x04\x7a\x1b\xe6\xa8\x35\x0c\x04\x73\x43\x9f\xba\xbe\xfe\xd8\x0e\x82\x4d\xd0\x2d\xc8\xc2\xfd\xc0\x05\x80\xbf\xd7\x41\xf3\x2a\x1c\xb0\x15\x6e\xba\x17\x76\xc0\xae\xfb\x8c\x83\xb0\xe3\x6e\xe3\xa0\x71\xe8\x1e\xd8\x2e\x80\xfb\x8d\x57\x61\xfa\x1e\xe3\xa0\xf1\xca\xbd\xb0\xc3\x78\xf5\x5e\xd8\x61\xc9\xf7\x4e\xf1\x1d\x49\x00\x7e\x10\x03\x8d\x60\xa5\x59\xe1\xd2\x60\x51\x31\xc2\x97\xab\x89\x03\x21\x5a\x0f\x44\xf4\x8f\x33\xc4\x4a\x89\x03\x66\x65\x6d\x02\xed\x16\x79\x9f\x27\x54\x47\x44\xc7\xc9\xb2\x5e\x1b\x3c\x48\x29\xf8\x90\xc2\x4a\x5e\x8a\xc0\x19\x6c\x64\xce\x98\x82\x68\xb3\xe7\xcb\x95\x3a\x34\x01\x0f\xd1\x0e\x8f\xb6\xd6\xde\x16\x18\x08\xd1\xfe\x71\x7e\x42\xd6\xd1\xad\x94\x78\x2f\x7e\x67\xce\xf6\x79\xcf\x13\xf2\xed\xfb\xe6\x82\x1d\x0b\x5e\x84\xe7\x9c\x01\x8f\xcf\xb9\xf2\x89\xa7\x7e\x7e\xfe\x72\xb8\x26\xc7\x48\x36\x65\xc3\xf2\xcd\xcf\x1b\xb7\x12\xaa\x4d\xda\xb2\xf2\xeb\xcf\xc3\x4d\x3f\xbf\x9e\xfb\xb8\xe3\x58\xdf\x39\xad\xf0\xbd\xd2\x5a\x8a\x3d\x68\x7f\x0a\xdb\x1a\xa0\x80\x18\x38\x7b\xb0\x0e\x15\x75\x83\x75\xa8\xa8\x87\x69\x8d\x27\xa7\x84\xe8\x24\xec\x40\x45\x59\x0d\x45\x4c\xc0\x34\xb0\x5d\x45\xf9\x9e\x18\xd0\xb7\xe2\x25\xeb\x76\x18\xd8\xbf\x42\x9a\x55\xb6\xf3\x3e\xff\x1a\x1d\x3c\x52\x8a\xb2\x3f\x18\x63\xfd\xd5\xb5\x50\x38\x3f\xc4\x1a\xcb\x20\x79\xc0\x1a\xe1\x2e\x4b\xfb\x0f\x5c\xa4\xd8\x50\xd1\xfb\xd5\xeb\x4c\x80\xe9\x83\xad\x33\x39\xd8\x3a\x1b\xfb\xd1\xb2\x24\x07\x43\x75\x09\xd6\x03\x95\x5d\x62\x43\x10\xb5\x5a\xe1\x0f\x58\xf5\xce\x6a\x2d\x3f\xf8\xca\x2b\xfa\x1d\xf0\xe6\xda\xe7\x02\x05\x34\x80\x11\x04\x57\xf7\x5f\x3d\x21\x72\x5b\x4e\x0b\xf2\x3a\x6e\xcc\x42\x9c\xb6\xb6\x52\xf4\xf3\xc0\x9e\xd6\x22\xa8\x7a\x53\xc5\x66\xb7\xc3\x9e\xd6\xe2\x0a\x4d\x17\x6f\x56\x74\xda\xfe\x3e\x1e\x41\x8a\x26\x4b\x43\xb2\x60\x08\x6d\x31\x90\x23\xfc\x20\x4a\x62\x90\x2d\x3e\xdf\x5f\x3d\x30\xbf\x93\x60\x50\xdb\x0f\x81\xd1\xfd\xbb\x55\x28\xe5\x6e\x15\x7e\xb3\x5b\x45\x81\x73\xb3\x6e\xc9\x03\x3b\x56\x94\xdd\xe9\xd5\xad\x2b\xc2\x65\x87\x40\xa5\x85\x05\x7f\xb2\x2c\x24\x95\xbe\x4a\x6e\xa0\x5a\x7d\x18\x99\xb3\xd3\xe5\xa1\xd6\xb5\xcb\xa5\x97\x78\x95\xb5\x59\x73\x55\xba\x40\xa9\xba\xc6\x79\xb2\x59\x0b\xf4\xd8\xac\x5a\x79\xd5\x83\x14\x6c\x63\x48\x53\xa5\x3d\x71\xfb\xb5\x58\xea\x29\x18\xd0\x6d\xbc\x65\x1c\xbf\x6f\xc9\x1d\xdf\xda\xf8\xf5\x9b\xc4\x3d\x6f\xbf\xff\xe6\xdb\x9f\x1a\x47\xb8\xf8\x95\x37\x5e\xb5\x9c\xe5\x45\x9c\x3a\x2a\x2e\x97\xe2\xa0\x1b\xdc\x60\xae\x88\x36\xb4\x8b\x4b\x3a\xee\xca\x68\x82\x43\x87\xb8\x87\x2e\xa3\xdb\xa7\xe3\x6e\x99\x16\x36\x7b\x7d\xd4\xe3\x9a\x84\x69\x5a\x1f\xd7\x49\xcc\x7b\xb2\xaa\x5e\x72\x71\x74\x23\x45\xab\x8b\xe5\xf3\xd8\x8b\x4a\x42\x38\xde\xdc\x45\xdd\x5a\x9d\x66\x02\x5e\x1c\xd0\xcc\x6a\xdc\x85\x0a\x36\xb5\x2e\xcf\x70\xf2\xe8\x26\xda\x40\xdb\x2b\x0c\x55\xd7\x05\xab\xda\x8d\xd2\xea\xe2\x66\xc8\x7d\x0c\x5b\x46\x4c\x9c\x36\x71\x44\xf7\xe4\xef\x5c\x99\xd3\xdf\xba\xfc\xdb\x63\xbb\x1f\x99\xf8\x68\x62\xf6\xb4\xff\x58\x3c\x65\xca\xf4\xf1\x1b\x97\x5c\x7f\xb3\xb0\xe6\xa5\xb7\xb4\xbb\x27\x5e\x76\xfe\x99\xa3\x46\x04\x63\xa3\xdb\x2e\x5a\x7c\xe3\x8c\x5d\x8f\xd7\x37\x7e\xd4\x94\x5d\xdf\x9e\x1b\x3b\x62\xea\x0d\xb3\x26\xae\xe8\xea\x9d\xd9\x39\x76\xd6\x95\x97\x9e\xb8\x97\xea\x7f\xda\x5b\x42\x4a\x82\x30\x48\x82\x34\xb8\xb1\xba\xbb\x44\x53\x4d\x77\x89\xf6\x4a\x77\x89\x91\x94\x40\x8d\xaa\x8e\x1b\x65\xea\xfc\x37\xbb\x4b\x74\x90\x5b\x93\x58\x0e\x0e\x67\x84\xc0\x6a\xdc\x8a\x4a\x36\x77\x30\x46\xcb\x05\x7d\x4a\xc1\x5f\xdf\x40\xe5\xeb\xdf\x6b\x33\x51\x89\x40\x0d\xdb\x6f\xe2\x3e\x53\xbd\x2e\x1c\xb2\xed\x84\xb8\xdc\x0c\x4c\xdd\x5c\xee\x3f\x51\xbd\xff\x46\x90\x06\x5f\xf9\x4c\xdd\x35\x46\x0e\xd1\x5d\xa3\xa3\x5f\x77\x8d\xdd\x36\x77\x30\xd5\x92\xb6\x76\xdf\xda\xf6\x39\x76\x5f\x69\xb2\x51\x06\xef\xc3\x75\xdb\x18\x61\x9e\xc9\x61\xba\x6e\xf0\xb9\x6a\xfc\xce\xf6\x9f\x00\x61\x3a\x1b\xf4\xa6\xea\xfd\xb7\xd7\xec\xbf\xb3\xb2\xff\x2e\xba\xff\x56\x55\xc7\xad\x74\xd6\x87\xb5\xff\x2c\x4c\x6b\xad\x00\x29\x25\xc2\x7f\xda\x06\x6b\x24\x15\x80\xba\x26\x46\x82\xa2\xbf\x3e\xd1\x48\xd1\xd4\xbf\x2b\x01\x35\x51\xb1\x61\xc5\xe0\xa2\xea\xbb\xc0\x3f\xa4\x2c\x08\xa3\xab\x21\xff\xf5\x96\x40\x58\xf4\xf0\x82\x30\x18\x05\xce\x84\x23\xaa\xe9\x91\xab\xa1\xc7\x19\x16\x3d\x70\x5b\x46\x8b\xb4\xe7\x72\x5a\x52\xd4\x71\x22\x5b\xec\x48\xb6\xd9\xd3\x78\x64\x4e\xab\x13\x75\xad\xbe\x89\xe0\xff\x31\x94\x60\x5d\xaa\x8e\xbb\x64\xad\xa7\x42\xb0\xb1\xfd\x4c\x80\x91\x9d\x38\xd1\x89\x47\xca\x5a\x7d\xdd\x31\x9c\x90\xb5\xf6\x6a\x13\xa0\x5e\x2e\x36\xd4\x13\xeb\x3e\x4e\x5e\xf1\x48\xb9\x38\x62\x64\xbb\x3f\x5d\x4c\x93\xd7\x42\x43\x7d\xa2\xca\x04\x88\xe7\x0b\xe9\x91\xed\xe4\xdd\x88\x3c\x28\x36\xc4\x47\xa4\x99\x09\x50\xdf\x10\x4f\xb4\x8f\x48\x8f\xac\x31\x01\xba\x2c\x96\x8d\x62\xe9\xa1\x44\x6c\xeb\xda\x3a\x2c\x9e\x25\x9b\x5b\x28\xcf\xce\x40\x48\x29\x00\xc5\x4f\x0b\x5d\x10\xe6\xf2\xd8\x46\x7b\x50\xb8\xd1\x69\xb8\x37\x78\x90\x6d\x58\x2e\x6e\x1e\xc2\x58\x48\x0e\xcd\xd0\x5c\x3f\x6b\x61\xad\xc5\x53\xc1\xe4\xa9\x40\x7b\xdf\x77\x82\x33\xc1\x0f\xaa\xb9\xda\x5a\xc3\xd5\x91\x65\xae\x36\x66\xf0\x19\x39\xad\x8e\xd7\x71\x85\x83\xcd\xaa\x5e\x8c\x34\x13\x08\x10\x47\x3a\x6e\x96\xb5\x11\x65\x5e\xe2\x0c\xb9\x15\xba\x15\xca\x54\x7a\xfb\x17\x1c\xc1\x56\x42\xab\x0c\xd2\x6c\xee\x7c\x1e\x77\x2b\x1a\xa2\x21\xeb\x91\x9f\x97\x90\xd5\xee\xb9\x32\xf9\xaa\x91\xc4\x60\xa4\xdc\x6f\xe1\x87\xeb\x4c\xda\x25\x2d\x18\x31\x18\x15\x5f\x37\x61\xc4\x49\xaf\xa5\x2d\x5e\xb3\x00\x85\x45\xc7\x42\x99\x8e\xa5\xcf\x46\xc7\x52\x96\x65\xbc\x9d\x91\x31\xb3\xa2\x07\x90\xb3\x94\x29\xa7\x35\x57\x51\xb4\x3b\x71\x18\x95\xe2\x2c\xa3\x8f\x10\x35\x63\xa6\x5b\x74\x13\xa5\xd2\xd8\x4a\x8d\x8d\xf8\x67\x22\xaa\x76\x46\x16\x29\x5a\x3c\x92\x1f\x8e\xbc\x70\x50\xf2\x56\x37\x05\x1a\x54\xf1\xb6\x6e\x59\x7d\xcd\xb7\xbf\xb5\x6a\xd5\xd7\x15\x46\xdf\x5b\x47\x8d\xa2\x91\xc1\x9e\xc1\x6e\xa0\xe4\xca\x4d\x5f\xbb\x62\xe5\xd7\xbe\x7a\xe2\x9f\x26\x79\x85\x78\xc7\x68\x33\x4e\x48\x75\x8f\x64\x08\x6b\x41\x1b\xc8\xd2\xea\xf6\x42\x02\x80\x34\x6e\xc9\x69\x51\x9b\x8e\xd3\xd9\x82\x07\x82\x34\x56\x72\xb4\x30\xbb\x37\x5b\xca\x85\x12\x1e\x4f\x5a\xcb\x89\x3a\xe6\xb3\x38\x27\x6b\xa3\x88\x72\xce\x53\xd2\xb6\xab\x3a\x6e\x97\xb5\x4e\x46\xcd\x90\x4f\xc7\xb9\x2c\x0e\xc9\xda\x68\x82\x61\x14\x5d\x3b\x13\xa6\xb5\x76\x60\xb6\xbf\xc3\x9d\xa8\x60\xf7\xb4\x98\x79\x66\xbe\x54\x3e\x8f\x47\xa3\x82\x12\x4d\xd0\xf6\xbc\x8a\xe9\xea\x0b\x45\x09\x85\xeb\x68\x1a\xd1\xa8\x04\xab\x6a\xb7\x13\xea\x62\x0f\x2b\xbc\x29\xd3\xb6\xc5\x24\x6e\x88\x9c\x7c\xab\xa9\x8e\x59\x76\xd1\xda\xef\x56\x63\x3d\x76\xe6\x7e\xf4\x8f\x9f\xcf\x9f\xbe\xf5\x91\xcb\x9f\xd6\xdf\x5a\x33\xf9\xc7\x5f\x79\x03\x82\xbe\x0e\xf1\xdb\x37\xff\x62\xef\x17\xf7\xde\x7a\xdb\x9b\x53\x17\xef\x7b\xe0\xc1\x17\x60\x7e\xeb\xd2\xaf\xac\xbe\xe9\x26\x6e\x07\x7c\x9c\x5b\x31\xef\x75\x46\xe0\x39\xe7\x4c\x9e\xfe\xab\xa5\x9b\x27\x4e\x32\xde\xd3\xef\xba\xf9\x3b\xf3\x8e\xb6\xb6\x2d\xbd\x72\xed\xfc\xa7\x1f\x62\x14\xfe\x12\xb4\xad\xba\x89\xf5\x3e\x30\xfb\x32\xb5\x81\x9b\xcd\xd8\x66\x03\x8b\x6d\x5a\xcd\x99\x70\x8b\xd9\x5f\xbd\xbd\xdc\xee\xd7\xc5\x5a\x21\xa4\xc2\x3a\x11\x4c\x5a\xcc\x5f\x08\xd6\x93\x7b\x1c\xc7\x50\x21\xd2\x40\x69\x96\x52\x76\x3b\x3c\x01\x3e\x9e\xa0\x6a\x32\xd2\x82\x14\xdc\x96\xc7\x01\x54\x0c\xd6\x27\x68\xc3\x47\x47\x03\xa1\x9c\x84\x4c\xd9\x1c\xba\xbd\xd3\x20\x31\xce\x41\x3b\x3e\x41\xae\x5f\x84\x73\x90\x0e\x50\xc6\xdb\xfd\x02\x9c\x3c\xeb\xab\x24\x25\x41\x00\xd4\x83\x26\xb0\xba\x7f\x67\xa5\x46\x49\x2f\x35\xb0\xce\x4a\x0d\x62\x79\x0a\x88\x5d\xd5\x71\x03\xed\xac\x14\x37\x3b\x2b\xb5\xc0\xb4\x66\x27\xb2\xa3\x06\x4d\xcf\x9d\x4b\x09\x45\x62\xa6\xdb\x68\xb0\x26\x4b\x0d\xc3\x34\x59\xaa\x4a\x30\x1a\xa6\xdb\x92\x85\xee\x2e\x19\xba\xe9\x92\xf0\x09\x83\x77\x27\xff\xc2\x9a\x2f\x55\xef\x37\x06\x9a\xc0\xca\xd3\x75\x92\x6a\x1e\xa2\x93\x54\x8b\xd9\x49\x8a\xec\xb3\x2e\xde\xc4\x5c\xae\x45\xaf\xcf\x8c\x67\xff\xdb\xfd\xa4\xca\x40\xee\x34\x8d\xa5\xe2\x96\x2d\x3e\x44\x83\x29\xf8\x64\x19\xc8\x55\xef\xb5\x11\xb4\x83\x2f\xf7\xdf\x6b\xab\xa4\x97\x52\x6c\xaf\x29\xb2\xd7\x11\xe5\xbd\xa6\xe8\x5e\x9b\xcc\xbd\xa6\x4d\xde\x16\xd4\x60\x23\x11\xd7\x26\xca\xdd\x70\x24\xc1\xb8\x5b\xf4\xfa\xea\x1a\x06\xd9\x75\x6a\x58\x06\xd7\xe6\x34\x0d\xc3\xe5\x65\xd5\xe0\xcd\x35\x34\xab\xf9\x17\xaa\xd0\x5b\xdf\xab\x8c\xdf\x82\x49\x03\x81\xf6\x37\x69\x05\x39\xb0\xb1\x3f\x15\x9a\x25\xbd\x94\x64\x54\x20\x60\xad\x21\x83\xbb\x72\x5a\x98\x27\xca\x15\xe2\xd1\x65\x92\x24\xb3\x45\xd5\x4e\x6e\xf9\x18\x0b\xcd\x10\x1b\xb0\x53\xd1\x71\xa3\x39\xe9\x4e\xeb\x86\x69\x5a\x5a\x85\x5b\xf3\xb8\x0d\x15\x5d\x0a\xcf\x12\x02\xed\x2e\xd6\xe0\x2a\x89\x86\x21\x47\x4d\xca\x0d\x25\x46\xf5\xcd\x33\x38\x61\x5e\xb6\x2e\xf1\x6b\x4d\xa2\xc0\xba\xb2\x33\x60\x90\x93\x70\x85\x79\x8b\xf7\xad\x5a\xbd\x7e\x3d\xb7\xa8\x12\x80\xe3\x4e\x7d\x0f\x00\xf8\x07\x5a\x67\xe0\x06\xad\x55\x3d\xa8\xcc\xe6\x53\x9a\xdb\xa7\x57\xda\x4e\x71\xcc\x7f\xc1\x97\x8f\x28\x4a\xa2\xa5\xe6\x49\x7c\x0e\x76\x59\x5d\x0a\x8f\xf7\x98\xad\xa7\x00\x07\xee\x00\x80\xfb\xdd\x67\xfd\xfb\xbc\xbd\x12\xdd\x27\x07\x82\x47\x49\x74\x87\x29\xf5\x4f\xc1\xae\x72\x45\xc3\x89\xd6\x72\x6f\xab\x5b\x01\xe0\xde\x95\x92\xc0\x03\x10\x68\x36\xe3\xb5\x3e\xfa\xf7\x15\x1a\x04\x45\x3e\xe6\xd0\x40\xde\xc1\x63\xb2\x64\x0b\x37\x56\x8b\xd9\x17\xe9\x73\x2a\xe2\x54\x7e\x16\x7f\xea\x2d\x00\xb8\x3b\x68\xdd\xa5\x0f\xc4\xc0\x7c\x33\xfe\x4a\x6f\x61\x47\x06\x47\x58\xfc\xd5\xcf\x2a\xc8\xdd\x87\x09\x66\x29\x4a\x3e\x77\x6d\xfc\x55\xa6\x1f\x04\xcd\x86\x74\x6e\x60\xa6\xbc\x6b\x41\x1f\x52\x34\x7f\x84\xd1\xb7\x5a\x24\x50\x12\x55\xff\x5c\x6f\x71\xfe\x69\xd8\x75\xd1\x80\x42\xcd\xe3\xcf\x93\xc5\x8a\x1b\x2a\xf1\x7e\xda\x4f\x49\x8a\xd3\xfc\xd7\xc5\xac\x0a\x5e\x8b\xdb\x74\xdc\x9c\xd1\x78\x5b\x39\xf9\xb5\x4e\x2d\x7b\xbe\x83\x2a\xcb\x75\xad\xa3\x68\xc0\x93\xcf\xe3\x46\xb4\x87\x77\x48\x5e\x39\xe2\x22\x87\x3e\xa8\x14\x90\x5f\xa1\x96\x6b\x73\x1c\x29\x5a\x10\xd0\x5b\x4c\x13\xa5\xf2\x88\x9e\x50\x6f\x0b\x75\xde\xb6\xf6\x06\xa9\x3b\x57\x51\x65\x90\x6a\x04\xb5\xbd\x97\x84\x37\x5e\x9e\x62\x9f\xf8\xd5\xbf\x2e\xc1\xf3\x27\x2c\xbd\xeb\x9a\x37\x97\x3c\xf6\xfd\xbb\x8c\x3f\x9e\xfa\xa7\xf1\x7f\x61\xef\x57\x56\xad\x5f\x71\xe3\x55\xeb\xae\x85\xba\x0e\xd1\x62\xe1\x7b\x37\x7e\xeb\xfb\x2b\xc6\x34\xe2\xb3\xce\xdb\x7a\xff\xf2\x6d\xc6\xfd\xba\xf1\x37\x63\x3f\x54\xf4\xad\xdf\x7a\xf8\xa1\x95\x37\xdf\x46\xe5\x8c\xf5\x72\xf3\x82\x00\x18\x59\xce\x68\xec\xdf\xc9\x0a\x37\x65\x34\xb5\x39\x97\xd3\xea\x45\x1d\xd7\x65\x8b\xed\xf5\x4d\xf6\x34\x6e\xa3\xd1\x59\x2d\x92\x20\xb8\xbe\x63\xb0\x56\x57\x9d\xfd\xcc\xb2\xb6\x4e\x5c\xd7\x89\xdb\x64\x2d\x52\x77\x8c\x90\xad\xb9\xda\x2c\x8b\xc8\xc5\x68\xa4\xce\x9f\x2e\xc6\xc8\x2b\x6e\x93\x8b\x2d\x6d\xcd\xfe\x74\xb1\x95\xbc\x16\xa2\x91\xba\x2a\xb3\x2c\x96\x2f\xb4\xb6\x35\x93\x77\x2d\x79\x50\x8c\xc6\x5a\x5a\x99\x59\x16\x89\xc6\xea\x9a\x5b\x5a\xdb\x6a\xcc\xb2\x00\x40\x4a\x51\x50\x83\x23\x99\x3f\xb7\x64\x0b\xd7\xd3\xd9\x98\xd8\xa5\x14\x12\xc9\x46\xca\x11\x9b\x6c\x4e\xb3\x1a\xb4\xff\xd6\xe0\x11\xd8\x7e\x5d\xb9\x0e\x0e\x61\x6a\x0d\xe8\xd6\x25\xbc\xd6\x2f\x00\x5b\xbe\x63\xef\xa5\xe7\x31\x08\x1a\xc1\x4c\x33\xa2\x1f\xb5\x3a\x78\x25\x9c\xe5\xf8\x41\x48\xd5\x09\x02\xad\x37\x5d\x7a\xe4\xc6\x09\x95\x3b\x06\xd6\xa3\x12\x2f\x3b\x03\x2c\x09\x39\x11\x1d\xa2\x9b\x57\x95\x2b\x68\xc8\xb6\x5e\x77\x98\xfa\x69\xf1\x90\xdd\xbd\x84\x6f\x9a\x40\xe1\x0a\xab\xcd\x57\xcd\x3e\x22\x55\xfb\xa8\xed\x44\x96\x1a\xac\x13\x59\x93\xd9\x89\xac\xc4\x3b\xa3\xf5\x34\xc4\x61\x43\x5a\x43\xfc\x33\x77\x25\xab\x42\x03\x43\xb4\x27\x9b\x68\xe1\x80\xa1\xda\x94\x71\xd0\x02\x02\xd5\xfb\x20\x1a\x60\xbe\xb9\x8f\xb8\xb5\x8f\x66\xe7\x60\x3a\xc0\x56\xa5\x03\x0a\x5e\x5f\x2c\x4f\xb5\xc0\x6e\x1e\x29\xa1\x88\x93\x6e\x89\xf5\xf3\xa1\x0a\x60\x70\xc6\xd4\x7a\x68\x86\xe4\xce\x8a\x1a\x57\xfd\x90\x2c\xe2\xe7\x55\x5f\xf0\xf3\x06\xf0\xc9\x0b\x3c\xa0\x19\x74\x41\x60\xee\xaf\xdd\xda\x5f\xc6\xa9\xe3\xfa\x8c\xe6\x6d\xc8\xe5\xb4\xa0\x48\x90\x5c\xb1\x31\x58\x6f\x4f\xe3\x64\x4e\x43\xa2\xae\x29\x11\x72\xea\xd9\xfc\xda\x16\x55\xc7\x2d\x6c\x58\x2d\x21\x40\xae\xdf\xa9\x4f\x76\x62\xb5\x13\x27\x65\x4d\xa9\x3b\x86\x55\x59\x6b\xa8\x3e\xf5\x8a\x5c\xf4\x2b\xaa\x3f\x5d\x0c\x90\x57\x9c\x94\x8b\xf1\x64\x83\x3f\x5d\x4c\x90\xd7\x82\x5f\x51\xab\x4e\x7d\x20\x5f\x48\x24\x1b\x98\x5b\x06\x14\xfd\x81\x78\x82\x9d\x7a\xc5\x1f\x50\x1b\xe2\x89\x64\xcd\xa9\x6f\x61\x2c\x68\x26\x2c\x18\x49\x58\xe0\x0c\x9a\x52\xa5\x14\x22\xd1\x18\x3d\xf5\x99\xf6\xa1\xd8\x30\x84\xab\x65\x48\x76\x6c\x1c\xe2\xf0\xa7\x86\xe6\xcc\xdc\x5a\x2d\xd0\xb7\xc0\x62\x8e\x60\xf2\x46\xa0\x67\xa8\x19\x74\x95\xe7\xc5\xd5\x5b\xdc\x49\x39\x75\x1c\xca\xe0\x4c\x8e\xa6\xfc\xb6\x97\x39\x11\x55\xf5\xa2\x37\x4a\x10\x57\x00\x55\x66\xc7\xa9\x7a\x71\xa4\x2d\x61\x4f\x6b\x2d\x0a\xb5\xcd\x46\x9a\x13\x85\x5b\x02\x48\x29\xf2\x4e\x3a\xcc\x0b\x68\xa9\xfa\xa1\x88\x51\x63\xcf\x57\x48\x50\x8b\xb6\x6a\xc8\x51\xf6\x95\xac\xb2\xf6\x0f\x53\x65\x9c\x35\x80\x12\x27\x2d\x5f\xc9\xff\x58\xe7\xf0\x91\x4a\xdf\x84\x79\xe0\x0d\x21\x2f\xec\xa7\xb5\xbe\x31\xd0\x09\xb0\x27\xa3\xd9\x04\xdd\x1a\x98\x16\xc9\x68\x7e\x81\x15\x0f\x08\x87\xb1\x9c\xd5\x9c\x48\xc7\xc1\x2c\xd1\x8e\x66\xbd\xb9\x38\xc4\x40\xb9\x79\xfc\x9b\x7d\x9b\xa7\x4d\x9e\x7c\xee\xb4\x49\x93\xce\x9b\x36\xf9\xac\xa9\xe4\x3b\xb7\xe4\xc8\x91\x0f\xce\x3f\x6f\xc6\xb9\x53\x66\xcf\xe0\x85\xf3\xa6\xcf\xfa\xc2\x94\x59\x33\x4c\xfd\x5c\x12\xee\x15\xee\xa0\xf1\xdd\x14\x58\x61\xc5\x77\x2d\x8e\x44\x9c\xe5\xfc\x8c\x80\x4a\x2f\xc1\x24\x4c\x6b\x4e\x95\xe5\x67\xd0\xf8\xae\x8f\xe0\xd9\x22\x5f\x89\xee\x8a\x03\xa3\xbb\x4e\x10\x4c\xfd\x7b\xd1\x5d\xc2\x8d\x56\x4a\xfe\xaf\x5d\xdf\x7b\xef\x99\xdf\x22\x1c\xf8\x8f\x95\x67\xdd\x7f\xf6\xbd\xb0\xd7\x0f\xc7\xa5\x27\xdc\xb8\x72\x6b\x4b\xcf\x8d\x57\xb9\x19\xdd\x47\xcf\x5e\x39\xe7\x7b\xc6\x09\x42\xfa\x8e\xa5\x57\x2e\xf9\x3e\x0c\x2c\x9a\x0a\x8f\x84\x1e\x31\xc2\xbe\x1f\xfd\x70\xd6\x58\x86\x3d\x69\x4f\x38\xd3\xbe\x9d\x3f\x64\x57\xb8\x86\xc1\xba\xc2\xc5\xad\xc0\x24\xb5\x69\x1d\xa8\x68\x59\xb4\x55\x65\xaf\xc3\xb5\x88\x2b\xdf\x4c\x03\x7a\xc5\x5d\x64\xde\x47\x03\x7b\xc6\x89\xd3\xcb\x4d\xbe\x6b\xd7\x7e\xe1\xbf\xbf\x76\x1a\xfc\x55\xd4\x30\xed\xd4\xec\x42\x05\x5f\x24\x4a\x55\xc5\xe9\xd6\x5d\x0e\x05\x0f\xec\x71\x37\xcf\x0a\x25\x0c\x58\xb8\x10\xad\xe4\xfd\x56\xd6\xdd\x08\x2e\x19\x72\xdd\xa9\xc1\xd6\xdd\x64\xd2\xdc\xb2\x35\x09\xd5\x4d\x4b\xd3\xa5\x14\x7c\x75\x0d\x9f\x69\x07\xb5\x57\xcf\x80\x6d\xcc\xaa\xbe\x70\x06\xdd\x4a\x55\x68\x18\xf0\xe6\x7e\x98\x0d\x39\x12\xdc\x34\x54\xed\x74\x43\x06\x8f\x60\xa6\x63\x53\x19\x45\xf2\x3e\xbd\xa8\xf2\x96\xdd\x58\xd9\x68\xb1\xd5\xe5\xb0\xa7\xb5\xa4\xa2\xe3\x24\x1d\x91\x4e\x47\xe9\x53\xfb\x51\xa1\xb6\xa2\x94\xc7\xad\x8a\xe6\xf1\x7d\xa6\xed\x0e\x11\x38\x1e\xb0\xf1\x5d\x03\xe3\xc6\x83\x6c\xff\x99\x01\x61\x63\xc0\xb1\x3e\x77\x52\x12\x04\x41\x7c\xb0\x4e\x77\x89\x0c\x51\x12\x9f\xbd\xd3\x5d\x25\x78\x3c\x44\xcb\xbb\x9c\x55\xc1\x3e\x48\xeb\x3b\xe1\x95\x8a\xac\xd1\x5e\xac\xb4\x7f\x73\x12\x2c\x33\x27\xe9\x45\x9c\x7a\xc1\x41\x34\x59\x03\x6d\xc3\x8a\x61\xc6\x2a\x20\x51\x7d\xba\xc6\x05\xb3\x59\xab\x9f\xa9\x5b\x65\x95\x22\x2a\xc1\xd5\xa2\x44\x0b\xde\x70\x0c\x69\x0e\x4a\xf7\x08\xb1\xc7\x88\x3e\xc3\x0d\x74\x74\xad\xc3\x6c\xc2\x89\x92\xc8\x07\x29\xb2\xb6\xfa\xc4\xc7\x61\x6d\x33\x56\xd8\x65\xb3\x79\xb3\x3b\xae\x7c\xf1\xcf\x7f\xda\xff\xea\x72\xaf\xcd\x56\xe9\xc7\x6a\x07\xc6\xba\xaf\x4c\x9d\x75\x21\x6d\x16\xff\x81\xf1\xeb\xdb\xc6\x2f\xaa\xed\xc9\xca\x9b\xb4\x16\x28\x7a\xee\x24\x16\x5b\x2d\xb5\x71\x22\x83\x47\xe6\xb4\x28\xaf\xe3\x96\x2c\x9d\x38\x1b\x3a\xac\xd5\x23\x1d\xd7\xcb\x74\x33\xed\xe6\x54\xd9\xfa\x10\x52\x34\x48\x74\x57\x0a\x69\xa2\x90\xcf\xe3\x76\x36\xdb\xf2\x33\x33\x69\xa8\x3e\x41\x43\xf0\xec\xa5\x81\xe2\x35\x18\xfb\xc4\xb5\x03\x04\xcc\xac\x05\x92\x0c\x60\x03\x2e\x80\xac\x6a\x86\x4a\x25\x94\xbb\x5c\x09\x65\xcf\x68\x0e\x49\xa7\xa6\xfd\xc0\xaa\x33\x7f\x55\xf9\xa2\xd3\xed\x61\xe5\x8b\x6e\x9a\x90\x54\x53\xbe\xa8\xc2\x01\xf5\x5c\xcd\xdc\xce\xbe\xf7\xfa\x57\xcf\x1d\x3a\x54\x29\x9a\x33\xe3\x80\xe2\x2e\x10\x06\x75\xa0\x05\xdc\x56\x1d\xe9\x88\xd7\x44\x3a\x9a\xca\x91\x8e\x48\x46\x8b\x4a\xe5\x6e\xe9\xf5\x2a\x65\x52\x63\x25\xda\xd7\x46\xf8\x54\x1d\x1e\x6f\xac\x9a\xbf\x50\xf0\xc7\xea\xa8\xbe\x6b\xfa\xbc\xd1\x21\xb2\xd3\x61\x83\x6a\x07\xb9\x9d\x7d\xbf\x18\x3a\x80\xd6\x7d\xe8\xd0\xc9\x35\xe5\xc8\x78\xa5\x66\x6b\x83\x59\x03\xf9\x9d\x21\x6b\x20\xb1\x3f\xa3\x79\xa4\xf2\x9c\x2a\xd9\x91\xc6\x76\xe6\x15\xb1\x5b\xdd\x1a\x8a\x36\x87\xdd\x9e\xd6\x80\x4c\x11\x10\xe1\xa4\x83\x8e\xcf\x32\xfb\xdd\x14\x05\xd9\x67\xaf\x54\x4e\x3a\xec\x48\xd1\x24\x95\xce\x91\x2e\x71\xd0\xcf\xca\x26\x65\x45\x13\xd1\xe0\x65\x93\x39\x02\x7a\x19\xe6\x6d\x19\x58\xbe\xa7\x3e\x26\x64\x2e\xbc\xf0\x37\xf2\xe3\xee\x3f\xec\x7c\xfc\xe0\xbe\x7e\xe5\xaa\x1b\x32\x3d\xe1\x0d\xf7\xef\xdd\x73\x62\xa3\x55\xaf\xca\xe2\x5c\x69\x33\x26\x5e\xf8\x0c\x31\x71\xdc\x94\xd1\x1a\x24\xbd\xd0\xd0\x44\x28\xd0\x90\x74\xa4\x71\x24\x5b\x1d\x28\x8f\x66\x71\xab\x5c\x8a\xb0\x30\x57\x24\x53\x1b\x38\x2f\x26\x7d\x23\xed\xe9\x52\x82\xfd\x36\x91\x29\x25\x59\xd0\x2b\x0b\xd3\x5a\x82\x08\x8c\xd3\xad\x50\xb7\x73\x12\x69\xa8\x91\x50\xa0\xf3\xf3\x0a\x49\x0d\xa1\x86\xcf\xa7\xa8\x21\xda\xbd\x43\x67\x55\x6c\xb1\xe8\xf7\x74\x45\x78\xa8\x5e\x2b\xcf\x60\x8d\x83\xdb\x4d\x1a\x56\x0b\x10\xb1\xd3\xc2\x5e\xbd\x24\xd9\x51\xb9\x96\x36\x51\x7d\xd0\xbd\x30\x8d\x1d\xd9\x92\x4a\x6b\xdf\x8b\x02\x2d\x64\x20\x12\x42\x10\xaa\xd7\x86\x94\x22\x27\x41\x3b\xcd\x49\x47\x58\xa4\x9e\x77\x44\xa8\x51\x50\xa2\xf5\xf4\x24\x85\xeb\x59\xee\x0d\x42\x9a\x37\x9a\xcf\x0f\x55\x2a\xec\x1f\x4d\xad\x25\xb5\xd2\x84\x78\x90\x9a\xe1\xb7\xce\x5f\x5e\x9c\x32\xa3\x23\xd5\x3b\x76\xf6\xb4\xd5\xb7\xf5\xab\x1c\x3e\xfe\xe0\x59\x5f\x9e\x3e\xf9\xea\xd1\x23\xda\x94\x42\x68\x23\x3b\x3b\x73\x8d\x80\x70\xbe\x39\xb3\x65\x34\x78\x8c\x75\x07\x18\x22\xb9\x04\x67\x33\x5a\x87\xb7\x36\xc7\xa4\x7b\xf0\x1c\x13\x9c\x4a\x1c\x46\xe6\xe8\x5f\xad\xa7\x26\xdf\x24\x85\x8a\xee\xa0\x8d\x80\x56\x6d\x44\x03\x52\x0a\xc8\x4f\xa3\x53\x3e\x54\x68\xed\xc8\x52\x82\xb4\x74\x20\x45\x4b\x65\xf2\x79\x2d\x66\xe6\x5f\x24\x68\x57\x30\x9e\x76\x05\xa3\xb9\x18\x9f\x29\x13\x05\x0e\xa0\xd8\xb0\x03\x60\x5a\x6b\x68\x37\x4c\x66\x4a\xdf\x9c\xfe\x74\xe4\xd8\xcc\x59\xdb\x1a\x8a\x45\x86\x9b\x3a\x9b\x28\x4f\x9d\x4d\x7e\xbe\xa9\xb3\x65\x24\x3c\x54\x55\xe1\x9f\x2c\x37\xcc\x60\xe5\x84\xc2\x53\x55\x79\x6f\x0b\x4f\x1d\xe5\xdf\x92\x92\x34\xb3\x7f\xf0\x29\x30\xf1\xf2\x14\x98\xc4\xe7\x98\x02\x03\x2b\x2e\xa3\xc1\x82\x83\x53\xac\x85\x0e\x12\x15\x14\xde\xab\x5a\x67\x85\xb6\x4d\xe0\x8b\xc3\xd0\xb6\xb9\x4c\xdb\x16\x98\xd6\x3c\x44\xe2\x68\x72\xe9\xe7\xa0\x72\x2d\x5a\x1f\x82\xd4\xef\xd5\x38\x89\x86\x20\x77\x35\x6c\x37\xfd\xde\x5e\x4a\xf3\x14\x38\x77\x50\x9a\x37\x95\x69\xde\x5c\x0e\xe5\x86\x52\xf4\x60\xfc\x9b\xf4\xaf\xdd\xc4\xa0\x4c\x98\x5e\xb3\x85\xc1\x19\x51\xb5\x03\x8b\x17\xcb\xa8\x9c\xcf\x1d\x92\x17\xb8\x21\xa3\x45\x04\xbd\x4a\xdc\xb1\x47\xa6\xad\xd6\x63\xa6\x62\x8c\x85\xc8\x7d\xe1\x13\x02\x14\x0f\xd9\x7c\xe4\x9e\xa0\xac\x19\x5a\xf0\xad\x71\x1e\x43\x09\xfe\x3f\xe9\x68\x8f\x41\xf9\x20\x2e\x66\x43\x3e\x98\xcc\xbf\x41\xb1\x79\x03\x58\x38\x08\xfd\xa9\xb6\x17\xaa\x45\x1f\xbb\x58\x88\x35\x2a\xb3\xa2\x96\x68\x90\x40\x23\x4f\x80\xa7\x2b\xff\x77\x8f\x84\xb5\x89\xc1\x8f\xc4\x75\x6c\x0b\x83\xf0\x41\xbc\xd3\x1c\x53\x52\x73\x1e\x9a\x87\x3d\x0f\x2d\xe5\xf3\xd0\xfa\xbf\x3f\x0f\xb9\x60\xa8\xa7\x37\x47\x4e\x73\xb2\x13\x0e\xc1\x82\x0f\x0e\xdc\x39\x7b\xce\x3d\x07\xe6\xdc\x1e\x37\xbe\x57\xbf\x72\x70\x4e\xe8\xb1\x8b\x2f\xf8\xd2\xfc\xd8\x9c\x1f\x66\x33\x9b\xcd\xf3\x10\xa7\xe7\xa1\x09\x7c\x61\xd0\xf3\xd0\x5c\x3e\x0f\x2d\xe6\x79\xd0\x82\xe1\xcf\x75\x1a\x6a\xb6\x30\x28\x03\x16\xd5\x6e\x60\x10\x3e\x48\xd1\xea\xf5\xf3\x6c\xa6\x37\xcd\x5d\x0e\x81\x06\x70\xa1\x39\xd5\x3b\x6c\x95\xcc\x37\xb8\xcb\xa2\x14\x56\x75\x1c\x66\x26\x9e\x18\x64\xa2\x44\x3b\x62\x3a\x5c\x34\x4b\xa3\xe8\x0b\xa8\xc4\x38\xc0\xa2\x42\x1b\x90\x03\xad\x21\xdc\x7f\xe4\x37\xac\xdd\x82\x7f\xc0\x04\x70\xe3\xd7\x35\x1b\xb8\xb0\xff\x40\x70\xdb\xbc\xaa\xd5\x1f\x4f\xd1\xe9\xe0\xd4\x57\x2d\x35\x9b\xf3\xb7\xda\x88\xc5\x5a\x9e\xc0\x85\x1d\x19\xdc\x94\xb3\x32\x4d\x86\x9b\xc3\x35\xe2\x34\x73\xb8\x68\x35\xf1\x6e\xe0\xf1\x06\xeb\x13\xd5\xf3\x94\x86\x1c\xcb\x05\xbb\xc7\xc3\xde\xa4\x2a\xd9\x86\x99\xcf\xc5\x8f\xf5\xb5\xda\x61\x74\xe6\xdc\x61\x06\x75\xc1\x53\xd1\xae\xa7\x26\x06\xf0\xe6\xff\x7f\xd4\x75\x2e\x3c\x75\x54\x74\x4b\x01\x10\x05\xad\xe0\x9b\xe6\xa4\xae\x10\x1d\x55\x94\xc1\x88\x76\x40\xc1\xbe\x2c\xf6\x64\xac\xe8\x89\x39\x0c\xcb\x0e\xd3\xd8\x9d\xd5\x14\x36\xb1\xcb\x4e\x4b\xa7\x69\xbb\x3a\x45\x36\x1d\x3e\x58\xca\x15\x94\x24\x2d\xb0\x46\x0e\xd6\xc4\xda\x1e\x23\xfc\x2c\x8f\xc7\x42\x74\x3c\x16\x56\x14\x1c\xc8\x03\xcd\x19\x40\x4a\x09\xa8\xc1\xda\xf1\x58\x2d\xe3\x60\xb2\x3b\xd9\x9d\x54\x73\x6a\xca\x62\x6b\x73\xcd\xb4\xb5\xbf\xfe\xf2\xf0\x4a\x67\xc8\xd8\x07\xc7\xc0\xec\xf7\xbe\x47\x79\xfa\xe2\x9f\x29\x4f\xaf\x11\x56\xaf\x5f\xb6\x9a\xf3\x42\x09\x26\x1f\xde\xbc\x34\xb7\xff\xc1\x07\xf7\x9f\x98\x73\xc7\x23\xb0\xe9\xf8\xdd\xf7\x6c\xb8\xab\xee\xe1\xdb\x7f\x00\x2a\xfd\x0f\x24\x83\xc6\xbb\xe7\x9d\xa6\x2a\xde\x4d\x4d\xbe\xea\xc9\xfa\x43\xb4\x41\x40\xc3\xb7\x41\x50\xab\xab\xdb\x65\x6e\x67\x75\x77\x81\x43\x87\x2a\x31\xc6\xc5\xe2\x2e\x10\x00\x61\x10\x07\xd7\xf5\xcf\xea\xa8\x97\xf4\x52\x84\x65\x75\x44\x44\x3a\xe2\x2a\x28\x95\xaf\x48\x3b\x41\xd0\x34\xc5\x25\x6a\xa6\xb8\x24\x6b\xd2\x97\xa2\xa8\x3c\x20\x4e\x29\x7a\x7d\xa1\x70\x4d\x22\x47\x64\xb8\x44\x0e\xea\x5a\x18\x26\x9b\xe5\x49\x6e\x67\xdf\x1f\x86\x4b\x62\x39\x74\xc8\xca\x5d\xb1\xfa\x3b\x6c\xa0\x75\x94\x5b\x4f\x43\xfb\x50\x46\x43\x92\x5e\x40\xb4\x10\x1d\x05\x1c\x44\x04\xad\x39\x49\x83\x72\xc2\xed\x00\xf6\x74\xc9\x53\x6e\x9c\xe2\x87\xe9\x52\x80\xfd\x24\xb1\x12\x76\x8f\x1b\x29\x38\x92\xd7\xfc\x0e\xa4\x68\x28\x94\xcf\xe3\x00\xc2\xea\x00\x7e\x55\x9b\x8f\x55\x8c\x3b\x79\xa0\xc6\x58\xac\x6a\x60\x61\x19\xd7\x55\xf9\x58\x69\x33\x47\xe9\xfb\xc3\xe7\x28\xe1\x04\x75\xa7\x14\xa2\xb4\x65\x5c\xb4\xde\x91\xa6\xad\xed\xcb\x89\x4b\x5a\x30\x95\x25\x7c\x25\xf6\xa1\x8b\x76\x52\x36\xf3\x98\x70\x5d\x96\xf0\xb9\x54\xcf\x8c\x68\x9a\xd1\xa4\x22\x05\x37\xe6\x71\x13\x2a\xf1\x2e\x25\x4a\x5d\xcc\xf5\x0a\x6e\xa8\x9a\x0a\x68\x71\x3c\x35\x1c\xc7\x6b\xdd\x0c\xc3\xb0\x7e\x4b\x0d\x3d\x7e\x3c\xb4\x10\x88\xaa\x49\xa0\xbe\x38\x91\x04\x4b\x0e\xce\xa5\xfd\x11\x16\x9f\x46\x0e\xfc\x19\xcd\x2b\x7c\x86\x76\x1f\x8c\xff\x9a\x2c\xb3\xe9\x37\x32\xe1\xb1\xd7\x3f\x48\xff\x09\x13\x43\x55\x1f\xc9\x67\x29\x72\xaa\x3a\x95\x25\x0b\x2f\x59\xfc\x0c\x98\xf9\x75\xeb\x87\xcf\xaf\xc3\xa9\x8c\xd6\x20\x0c\x92\x66\x57\x07\xd3\x5a\x42\xa6\x8d\x8c\xaa\x33\xee\xea\xec\xcc\x7a\x4f\xd0\xfc\xaa\x08\x31\x6b\xa5\x20\x52\xfa\xb1\x4b\x1d\x86\x5d\x56\xba\x5d\x05\x1a\x0e\x9b\x6e\x97\x65\x18\x71\x88\x64\x3b\xee\xd2\x0a\x4e\xdc\x6b\x04\x04\x8e\xce\x1a\xa6\x13\x19\x7c\x96\x67\xa3\x86\x51\x38\x96\xd1\x82\x5e\xc2\x2f\x5f\xb9\x2f\x4b\xc3\xe9\x9a\x87\x84\xb3\xe4\x78\xba\x61\xba\xe4\x67\x26\x7e\x1c\xa6\x35\xbf\x1b\xb1\x20\x94\x8f\xec\xdf\x1d\x36\x8b\xed\xab\xfb\x86\xf4\x33\xc7\xab\x18\x68\x8c\xab\xf5\x5c\x94\x19\x69\x1c\xef\x67\x6c\xf3\x60\xa1\xd1\x56\x9e\xbb\xd9\x01\x76\x56\xf1\x53\xa9\x6a\x05\x64\xf1\x16\xa7\x33\x5a\x8b\xb7\x36\x85\xb2\x73\x20\x6f\xcd\x96\xfd\x38\x55\x61\x6f\xa6\x8a\xbd\x29\x54\xe2\x95\x88\x2b\xce\x52\x8d\x70\x9a\xb6\x1b\xf0\xfa\x12\x2d\x6d\xed\xac\xc7\x5e\x0b\x52\x0a\x75\xa9\x36\x02\xa6\x5d\xf1\x7f\x37\xd3\x72\x00\x65\x4e\x23\x03\x3f\xaa\x21\xd6\x50\xb2\x70\xe2\x83\x81\x7e\x0a\xab\xff\x8d\x17\x44\xc1\x2c\x33\x36\x41\xd0\xaa\x4c\x6b\x91\xdd\x7a\x29\x10\xf2\xc9\x1e\x0a\x85\x68\x13\x6a\x1f\x03\xae\xfe\x6c\x21\x4c\x3b\x86\x86\xa3\x8e\x34\x46\xd9\xe2\xc4\x70\xd0\xc1\x5a\x51\x87\x69\x2b\x6a\xab\xeb\x4a\x0d\x40\xad\x69\x80\x53\x83\x4c\xaf\xa9\x70\xbe\x06\x93\x1e\x4b\x55\x75\xc0\xa9\xcd\x17\x4d\x81\x11\x60\x6d\xff\xb3\xdb\x26\xe9\xa5\x26\xc6\xd8\x26\xc2\xd8\x74\x99\xb1\x4d\x94\xb1\xcd\x26\x2b\x47\x96\x2f\x53\x72\x67\x34\xd3\x6c\xd1\x08\x6b\xbb\x26\x29\x25\xaf\x2f\x56\x57\x3f\x48\xba\x68\xd3\xb0\xe9\xa2\xb5\x58\x7c\x38\x35\x7b\x69\xcd\xde\x97\x0e\x93\x1b\xfc\x61\x15\x2d\xfa\x52\xf4\xd2\xa5\xf6\x9e\xd8\x6a\x5b\x03\xa2\xa0\x0d\xdc\x06\x58\x21\xa0\xd7\xaa\x7c\xb6\xf3\x7a\x49\xf1\x87\x09\x05\x14\xbe\x92\x14\x1e\xa4\x76\xab\x4c\x5b\x85\xeb\x58\xcc\x16\x64\x95\xb6\x83\x51\x1c\xe9\x72\x8a\xb8\x16\xab\xcb\xe7\xb1\x8c\xf6\xf0\xf6\x70\x43\xbc\x85\x76\x5d\x57\x95\x82\xd4\xd8\x44\xbd\x0d\xde\x30\xed\xb1\xa8\xf9\x15\xa4\x68\x80\x58\x29\x76\x1a\x03\xac\xb5\xb2\x5a\x88\x9d\x48\x05\x97\x76\xf3\x1a\x24\x95\xf6\x06\x78\x37\xbc\xe2\xcd\x57\xae\xd8\xfe\xe3\x97\x3e\x7a\xe1\xc9\xcb\x96\x18\xef\x72\x67\xdf\x7e\xec\x66\x63\xb7\xf1\xd0\x89\x1a\xf7\xc3\x1b\x70\x31\xdc\xba\xe0\xd3\x99\xc6\x47\x7f\x79\xff\x44\x00\x76\x41\xae\xcf\xd9\xd9\x0c\x6f\x11\x9e\xac\xad\x8b\xa5\xf3\x01\xa5\x24\xa5\xc7\x68\xf0\xd5\xc1\x26\xc1\x76\x57\x57\x17\x64\x06\x9b\x04\xdb\x63\x56\x16\x50\xe6\xd3\xad\xfb\xd1\x44\x27\x1b\x07\x1b\x6f\x19\x99\x23\x9f\x64\xd8\x44\x58\xec\x40\x1a\xa1\x49\xff\xc9\xb0\xf4\x1f\x0d\x3b\x19\x76\xb0\x7c\xa3\xe1\xe7\xc4\x2e\xae\xa6\x88\x73\xb8\x99\xb1\xfc\x4f\xab\x73\x8f\x66\x96\x07\xc8\x5a\xf2\xb2\x81\xd2\xe7\xd1\xe1\xe5\x05\xb7\x64\xb4\x84\xa4\x17\x12\x2d\xb4\xcb\x6d\xca\x91\xa6\x8d\x7a\xca\x42\x54\x8c\xb9\x08\x24\xab\x63\xd8\x85\x49\x14\x6e\xcc\x0e\x14\x2a\x2c\xcb\x44\x83\x12\x24\x33\xc2\x9c\x67\x58\xe2\xed\xe1\x04\x2d\xaf\x4b\x21\xdc\x44\x15\xa1\x94\x07\x9f\x43\x9c\x6a\xe0\xdc\x30\xd2\x04\x47\xd4\xc0\x99\x21\xe5\x49\x72\x5b\x68\xcf\x92\xa5\xb4\x29\x4b\xf7\x0d\x94\xa5\x21\x28\x54\x11\xb0\xba\x2c\x6e\x97\x4b\x31\x46\xa1\x58\xc6\x14\x38\x4d\x6a\xcc\xf6\x13\x39\x9c\x29\x93\x88\x08\x5f\x06\x20\x65\x8f\xe8\xf6\xaa\xa6\xb0\xa5\x90\x66\xfb\x7c\x42\x56\x1b\x2c\x39\xbd\x8c\xdd\x51\x43\xa6\x07\x86\x13\x32\xd1\x61\x92\xea\xe4\xfd\x96\x80\x59\xf2\xb5\x0c\x44\x41\x0a\xdc\x7a\x1a\xf9\x6a\xcc\x68\xf5\x42\xc5\xab\x19\x2c\xd7\xaa\xc4\x65\x9d\x36\x11\x19\x54\x43\x11\xb5\x1d\x8f\x21\xa5\xc8\xdb\xbd\xc4\xd2\xd1\x54\x19\x7d\x6e\xe9\x29\xfb\x0d\x87\x96\x1c\x2e\xcc\x40\xd5\x50\x12\x23\x9a\xa8\xca\x92\x97\x00\x9d\x41\x9d\x01\xeb\x06\x91\x97\xce\x8c\xd6\x4e\x76\x3c\xaa\xda\xfe\x6e\x85\x69\x2d\x2d\xeb\x38\x3d\xc4\x5c\xea\x2e\x73\xf8\xea\x6e\xde\xed\x0d\xd6\xd8\xdb\xff\xbb\x71\xd4\x15\x50\x79\xba\xb9\xd4\x33\x19\x05\x86\x9d\x4e\xcd\x09\x26\xb8\xe4\xc0\x0d\xc6\x18\xb1\x55\x3c\x40\x65\x60\xfd\xe9\xee\xa4\xa6\xd3\xdf\x49\x84\xe3\xb2\x8b\x29\x0d\x56\x88\xad\x22\xca\xf0\xcf\x7f\x0b\x41\xd3\x81\x94\x1a\x4e\x65\x18\xd4\x83\x74\xde\x45\x85\x21\x79\x7f\xf2\xed\xae\xa7\x26\x06\x1e\xdd\x6a\xe2\x91\xf2\xdd\x43\xf8\xbf\x66\xb0\xbb\x67\xd4\x69\xa7\x90\x77\xf5\x9b\x42\x3e\xd1\x61\x8e\x21\x6f\x4d\xff\xbf\x36\x88\x9c\x5c\x3d\x14\x9c\x9c\x96\xf3\xe3\x67\xcc\x2b\xf8\x5a\xed\xc3\xb3\x1e\x2e\x52\x1f\xbb\x2d\xd6\xf5\xd4\x44\xb3\xb7\xd8\x32\xb3\x97\xd2\x42\x33\xda\x6e\x33\x83\xa5\x62\xae\xc4\x3b\x59\xab\x04\xbe\x3c\x14\xd9\xa5\xd2\xb9\x0d\x2e\xe6\x87\x12\xb2\xe5\xd1\xc8\xae\x72\x57\x1f\x3b\x2a\xfa\x64\xda\xec\x14\xdb\xcc\xb6\x4a\x6c\xe2\xb5\xf5\x5f\x6d\x79\xc4\x5e\xd8\xc3\x9d\x05\xbb\x8d\x03\x7d\x4f\xdf\x55\x7d\x63\x8a\x7b\xfa\x5e\xe0\xc6\x1d\x9f\xc6\xdd\xd0\x77\x5b\x4d\xdb\xba\x72\x2e\xbe\xed\x31\x1a\x7b\xb9\xb0\x3c\x59\x9d\xa6\xe2\x34\x0d\x31\x5c\xbd\xd9\x4a\xc4\x91\x82\x21\x9a\x39\xe8\x45\x25\x9b\x23\x12\xa5\xc8\xd1\xa3\x68\xf5\x71\xab\xbb\x18\x46\xf9\xa1\xa6\xae\xd7\x2e\xbd\xdf\x0c\xf6\xff\xae\x5e\xfe\x20\x03\xd9\xa5\xc5\xb5\x21\x24\xd6\x2f\x43\x8a\x8b\x7b\x80\x1f\x84\xc0\xf5\x0c\x11\x63\x4f\x8e\x1e\x3d\x6c\xcb\x95\x02\x32\xc5\xc3\x01\x5e\x2f\x41\x40\xdf\xba\x82\xb9\x1c\x9d\x48\x23\x3a\xb2\x59\x3a\xef\x40\xa1\x0e\x4d\xa4\xea\x9a\x10\xc8\x66\x0b\x0a\x9d\x94\xa2\x00\x82\xed\xd9\xe6\x25\x35\xcb\x1c\x9e\x35\x63\xdc\xcc\x61\x5d\xa8\x3b\xd7\x9d\x54\x2d\x37\x1f\xe3\x8f\x98\xec\x4e\x9a\x5c\x79\xe2\x09\xc2\x17\xe3\x57\xe4\xa7\xbe\xa7\x85\x8e\xfd\xcf\x3f\xff\xfc\xf3\xfb\x4f\x1c\x22\x4c\x11\x3a\x4a\x25\x00\x20\x10\xcc\x19\xf7\x75\x60\xa5\xd9\xa3\x5f\xc9\x61\x90\xc1\x36\xba\x50\x2c\x66\x31\x9f\x81\xb8\x3e\x83\x63\x74\xa5\x51\x9f\xae\x09\xf6\x6c\xb6\x10\xa5\xad\xe5\xa3\x36\x47\xba\x10\x8b\xd2\xa9\x96\x64\xd1\x51\x36\x4d\x56\xf1\xe9\x74\xa8\x71\x34\x46\x8b\x6a\xb0\x1f\x69\x6e\x6f\xde\x1c\xf0\x4a\x27\xa7\xf9\xd9\xca\xe9\x44\xc0\x7e\x5c\x4a\x22\xe1\xfb\xb0\x0b\x8e\x31\xf6\x79\x95\x65\x7f\xdc\xf7\x2b\xe3\x60\x69\xe3\x1a\xe3\xa0\xb0\x6b\xff\x83\x0f\xee\x57\x2e\xd8\xf3\xf0\xef\xf6\xf7\x2d\xe1\x66\x7e\xf4\x93\xe7\x8d\x8c\xb0\x0b\x00\xee\xd4\x3f\x68\x8f\xc8\x4b\x69\xd7\xc3\xbf\x32\x1d\x58\xa8\x27\x4c\xf0\x65\x34\x20\xe7\x72\x9a\x5d\xd4\xb1\x2d\x5b\x0c\xd8\x7d\x76\x3a\x7b\x81\x17\x75\x4d\x70\x65\x59\x27\xc4\xe8\x61\x2d\xa9\xea\x85\x24\xdd\x45\x92\xe0\x8a\x86\x6c\x21\x4a\x3d\xb0\xd1\xb0\x83\xba\x87\x9a\xfb\xa5\x7a\xfb\x3b\xb1\xad\x13\xfb\x65\x4d\xa8\x3b\x86\x6d\xb4\x03\x57\x25\xd5\x5b\x90\x8b\xa2\x60\xf3\xa7\x8b\x12\x79\xc5\x7e\xb9\x88\xfc\xb2\x3f\x5d\x54\xc8\x6b\x41\x14\x6c\x55\xa9\xde\x52\xbe\xa0\xf8\x65\xf2\x0e\xe5\x01\x4d\x32\x63\xa9\xde\x82\x28\xd9\x64\xa4\xf8\x6b\x52\xbd\x93\x51\xa4\x68\xbc\x8f\x95\x00\x0d\xde\x4f\xab\xaa\x09\xa3\x6f\x88\x54\xed\xb3\xcd\x5e\x92\xfd\xda\xe3\x1d\x7b\x6d\x40\xef\xcd\x53\xdf\x03\x80\xfb\x3f\x92\x17\x84\x40\x0c\xfc\xca\xa4\x6b\x04\x7e\x26\xba\xd6\x65\x70\xf8\xb0\x16\xf3\x95\xa7\x0a\xff\x7f\x4c\xbb\x58\xf8\x74\xb4\xa3\xb5\x6a\x43\xd0\x6c\x15\xec\xea\x5f\xcd\x72\xa2\xbd\x52\xc3\x36\x01\x00\xee\x6d\xc9\xa0\xb9\xdb\x63\x40\x41\x20\x74\x72\x10\xf9\x63\xc9\xdb\xd4\xe9\x2d\x1d\x26\xa7\xb8\x68\x93\x04\x6f\x5a\x03\xf6\x5c\xae\xe4\xa3\xc3\x68\x34\xce\x99\xb5\xc6\x2f\x51\x0f\x71\x15\x0b\x27\x70\x3b\xfb\x2e\xb6\x5a\x7f\x1e\x3a\xd4\xaf\xe3\x27\x77\x4a\x07\x80\xdb\x26\xee\xa2\x33\x16\x9b\xcc\xe7\x8a\xb0\xea\xb9\x76\x3a\x53\xc3\xe6\xd3\xcd\x21\x8b\x3c\x79\x00\x4a\xa2\x10\xb7\xd3\x40\xb0\x4b\x78\xfd\xd0\xa1\x72\xf9\x1a\xe0\x80\x0d\x00\x3e\x6a\xdb\x40\xf3\xf1\xbf\x56\xd5\xdb\x14\xbb\x32\x9a\x28\xe9\x05\x91\x06\x5c\x44\xbb\x23\x8d\x81\xe5\x40\x2e\x41\x06\xb8\x21\x03\x14\xa7\x69\x7f\x8a\x43\xb2\x66\xab\x0c\x22\x23\x57\x0f\xd5\xd9\x9e\x3c\x6d\x8a\xaa\xb9\xc4\x7c\x5e\xb3\xdb\x90\x82\x1d\xd4\x8d\x51\x83\xa8\xab\x28\x63\xab\x41\xce\x39\xb3\x8d\xac\xe5\x3c\x3e\x16\x1f\x28\xcb\x3f\x01\x80\x7b\x5e\x4a\xd3\x3a\xc0\xe5\x55\x75\x80\x43\xec\x4d\xe9\xb7\x37\xa2\x8a\x91\x4f\x27\x5a\xb9\x6a\xfd\xfe\xaa\xf5\x23\xef\xc0\xf5\xf3\x35\xeb\x47\x49\x34\xab\x66\xdd\x3a\xec\x92\xd2\xe6\x9a\x8f\xaf\xae\xf0\x61\xb2\x11\xe0\x8e\x98\xfe\xc2\x1b\xaa\xfc\x85\xb4\xf1\xad\xe9\x27\xa4\xce\x41\x8e\x39\x07\xe5\xec\x70\xfd\x6f\x31\x27\x63\x77\xe2\x30\xaa\x71\x11\x72\xcc\xbd\xe2\x40\x5a\x90\xb6\x82\x0c\xc6\xa8\x3f\x1f\xfb\x90\xe5\x30\xac\xed\xe7\xda\xcf\x2d\x66\x76\xcb\xed\x7b\xaf\xc6\xff\x55\x4d\xf5\x01\xee\x42\xc0\x83\x45\x46\x00\x7e\x2c\x05\x00\x02\x51\xd0\x00\x96\x81\x02\x4f\x36\x45\x2e\x9d\x42\x9d\xa9\x56\x9c\x2c\x2f\x32\x60\x46\xfe\x63\x74\x8a\x69\x83\x4f\xc7\xc1\x2c\x06\x64\x13\x36\xb6\x09\x5a\xf0\x11\xa3\xc5\x6c\xb8\x01\x95\x04\xa7\x2f\x40\x7b\xac\x69\x4e\x1f\x1b\x28\xc6\x23\x0d\xb8\xcd\x1e\x03\xfd\x16\x5f\xc6\xe2\x84\x23\x8b\x6a\x76\xd0\x4d\xc1\xb7\x07\x76\xd5\x2e\x5f\x3a\x4a\xf0\xf6\x89\x10\x65\x11\xed\x49\xcc\x1d\xb1\x2d\xa3\x3e\xf7\x99\x55\x3d\x89\xab\x1d\xec\xe5\xd6\xc4\xa7\xe1\x4e\xa5\x3b\xb1\xe5\x61\xaf\x21\xbc\xb9\x52\xab\x3b\xb1\x9b\xae\xaf\xa6\x5d\xee\x2b\x96\x9f\x19\x12\x5c\x05\x5f\xa1\xb3\x94\x93\x56\xf7\x2c\x5a\xe9\x2a\x58\xe9\xe6\xf4\x8b\x4d\xc1\x23\x08\x69\x3b\xec\xb2\xea\x64\xc1\x64\x63\xb6\xe8\xa2\x32\x17\x21\x9c\xa9\xec\x49\xc9\xe1\x50\x86\x98\x14\xf4\xc0\x33\x89\x1b\x56\xdc\x1c\xac\x0d\x57\xc0\x84\x96\xc8\x41\xa0\x65\x88\x3a\xb2\x42\x4c\xc8\x00\xa2\x69\x75\xd5\x3b\xb5\x59\x79\xeb\x34\x67\xda\xdc\xee\xdc\x99\x93\x97\xcd\x83\x3d\x7f\x7f\xfb\xca\x19\xd5\x5b\xbe\x27\xb0\x71\x8b\xb8\xe0\xf8\xa3\xa7\x80\xf1\x71\x10\x00\x01\xdc\x69\x04\x84\x76\x29\x40\x6b\x88\x89\x1d\xf4\xe5\xaa\x3a\x62\xec\xcf\xe1\x70\x46\xf3\x39\x75\x6c\xcb\xe0\xc6\x9c\xc6\x09\x6c\x4e\x42\x53\x06\x3b\xe8\x70\x69\xb7\x4f\x27\xcb\x66\xf3\xa6\x70\x8c\xf9\x54\xe2\xf4\xd2\xa7\x55\xc7\x45\x1b\xe7\xa1\xe9\xb7\x0a\xd2\x7c\x61\xd6\xe1\xa2\x9e\x66\x55\xfa\xc2\x34\xaf\x14\x3b\x10\xf6\x50\x49\xab\x92\x2b\x5b\xa5\x7f\x5b\xaa\xb1\xb5\xcc\xc8\x3b\x2d\x01\x73\x4e\x39\x77\xfa\x17\x60\xd7\x6f\x9e\x5e\x3b\x07\x06\x59\xcc\x64\x63\x45\xc8\xde\xf2\xcf\x9d\x23\x3c\x76\xa2\xbd\xf0\x5c\xc4\x36\xdb\xb2\xf5\x4e\x2d\x37\x66\xf3\x0e\xda\x7b\x3a\x06\xba\x41\x41\x32\x55\x33\x67\x4e\x15\x11\x59\x9c\xab\x1e\xa6\x35\xbb\x48\x29\x0d\x34\xce\xc5\x8e\x83\xc4\xe2\x1e\xb5\x64\xae\xf5\x8a\xdd\x5b\xa1\xf6\xd8\x6a\x2c\x5c\x43\x6e\xdb\x0b\xb5\x58\xfe\xd4\x06\x23\xc0\xbd\x63\xd6\x0f\x92\x35\x99\x2a\x95\x73\x56\xd6\xe4\xfb\x8c\x6b\xa2\x94\xaa\x5d\xd3\xe6\x0a\x95\xc4\xea\x35\x55\xd1\x47\xda\x35\x00\x97\xef\x35\xc6\x88\x33\xcd\x3e\x72\xa3\x2a\xd3\xfd\x4d\xbb\xa8\xaa\x6f\x1c\x41\xb4\xa1\x72\x92\x00\xef\x34\x23\x25\xa8\x97\xce\xf9\x87\x36\xe4\xb7\x4c\xd7\xbd\xb0\xe7\x46\xb8\x15\xce\x33\x38\x8e\x33\xb6\x1b\x9b\x36\xbb\x2d\x7b\x55\xdc\xd3\x77\xf9\x2e\xf8\x8f\xbe\x75\x27\x5f\xe1\x96\x2f\xea\xfb\xc4\x98\x6b\x9a\xa9\x1c\xd8\x6e\x8c\x11\x3e\x91\x02\x80\x20\xa8\x33\xcd\x75\x38\x73\xd4\x52\xa5\xc6\x0e\x1b\xc3\xeb\xa5\xc6\x0e\x9d\x70\xe6\xa5\x93\xdf\x45\x5a\xa9\x4b\xdf\xba\xad\x15\xd9\x72\x03\xd7\xb4\x1d\x76\xc9\xc2\x2d\x30\x0f\xe7\x19\x67\xc3\xd7\x8c\xed\xc6\x33\x9b\x39\x6b\x55\x52\xa0\x6f\x9a\xf1\x18\x9c\xf3\xff\x70\xf7\xe6\x71\x52\x54\xe7\xde\xf8\x39\x55\xd5\x55\xbd\x77\x57\x75\x57\x2f\xd3\xb3\xf5\xf4\xec\xcd\x4c\xcf\x74\x33\x33\xb4\x6c\x6a\x5c\x10\x51\x11\x15\xd1\x20\x1a\xdc\xd8\x54\x10\x0d\x2a\x1a\x17\x5c\xe2\x4a\x62\xd4\xb8\x87\x20\xa2\x31\x68\xaa\x7a\x9a\x11\x8d\x89\x28\x8a\x12\x62\xd4\x10\xc9\xf5\x1a\xb3\xa8\xc4\x94\xe2\x7a\x8d\x41\x98\x2e\x7e\x9f\x7a\xce\xa9\xea\x65\x7a\x06\x92\x7b\xff\xf8\x7d\xde\xf7\xfd\x04\xdb\x91\x3b\x7d\xce\x73\x9e\xf3\x9c\x67\xfd\x7e\xf5\x58\xe1\x26\xfc\xf2\x42\x7d\x9d\xb5\x2c\x62\x27\xb8\xaf\xb9\x79\xc8\x07\xa8\x31\x25\x93\xd0\x8a\x3d\x63\x56\xe8\x7d\x64\x55\xa2\xc9\x6a\xc4\x9b\xe0\xcd\x36\x8f\xb9\x26\x1f\x2e\x2e\x6a\x0d\xee\x65\x59\xee\x76\x7c\x08\x3e\x52\x9f\x86\x77\xe8\xeb\xf4\xad\xab\xb9\x79\xfa\x3b\x3f\x9d\xf5\x04\xbe\x50\x47\x85\xb5\xf8\x89\xd3\x75\x85\xd6\x2b\xa7\x0a\xcb\x91\x0d\x79\xcd\x6f\x37\x22\x54\x4a\x31\xe7\x33\x91\x13\x73\x2c\x54\xbb\x58\x9b\x23\x09\x7e\x05\xcc\xfd\xf0\x82\x37\x5b\x12\x8f\x16\x59\x07\x70\x3f\x73\xe2\xf0\x6f\x2d\x78\xc1\x7d\xd3\xcb\xb9\x06\xd6\x20\xc4\x7c\x25\x18\x7e\x12\x60\x0c\xc0\x8e\x0d\xf9\x7b\x2c\xbb\xe8\x35\xbf\x82\x13\xdc\xc5\xaf\xb0\xbe\x60\x0d\xee\xd5\xdf\xa3\xbf\x9e\x0f\x7e\xb3\x9b\x3f\xa7\x08\x89\x46\xf4\x8d\x9b\x6a\x1b\xfa\xcf\xf6\xe4\x28\xdf\x53\x89\xc2\x31\x27\x16\x16\x16\xb5\xcc\xd8\x54\x89\x6e\x9d\xad\x4f\xc4\x6f\x52\x9b\x47\x71\x13\x14\x67\xaa\x1a\x6a\x42\x8e\x15\x38\xf2\x15\x96\xe6\x18\x06\xea\x6c\xf3\x57\x4f\xc6\xbd\xe6\xef\xc5\x2f\x1b\xbb\xb3\xfa\x0b\xa6\xda\x9e\x86\x3d\x4d\xad\xd8\x93\xe2\xcc\x0c\xf2\xc8\x69\x1f\x63\x73\x48\xc5\xbc\x28\x01\x90\x55\xf1\xb8\xe8\xd7\xc3\xd6\xf4\xbb\x68\xcb\x10\xd9\x19\xb7\xd4\xea\x0e\x82\xf3\x62\x6f\xe0\x83\x70\x5e\xad\xd6\x79\x81\x72\x96\x1d\x19\x0d\xf8\x39\xfa\x15\x01\xf3\x0b\xd6\xe0\xde\xb9\xf4\xb7\x1b\xfb\xe1\x5e\x2b\xf9\xdd\x64\x5f\xe4\xac\x0e\xaf\xd8\x57\xde\x4e\x70\x26\xed\xc6\x1b\x5e\x6d\x67\x0a\x4b\x20\xd8\x9d\x7e\x0d\x36\x69\x6d\xcd\xaa\x84\xc3\xd6\x56\xd1\x1a\xb8\xb1\x31\xe6\xb3\x62\x1d\xd8\xd8\xd7\x8f\xe9\xbe\xba\xcc\x9b\x97\x52\x79\x4e\x2b\x57\x47\xe3\x6b\x38\xc3\x62\xfa\xc9\x36\xe9\xf6\xcc\x2f\x59\x83\x7b\xaf\x80\x6f\x30\x36\xc7\x3c\x5d\x7c\xff\x19\xba\x37\x0f\x9a\x44\x98\x07\x55\x3b\xed\x7f\xc3\x8a\x37\xa5\xb8\x77\x2a\x38\x0d\x35\x39\x36\x9d\xb3\xbb\xcd\xd6\x23\xd5\x67\x48\x92\xb1\xd3\x0c\x50\x4f\x6f\x60\xc0\x30\x81\x61\x1b\x6c\x4d\x60\x86\x70\xff\xea\x4b\xf5\x61\xe6\xc4\xe1\xcb\x8f\x64\x6e\xba\x88\xd9\x5c\x18\x9e\xf3\xd2\xc3\xfa\x9c\xfd\x08\xef\xee\x00\xce\xdd\x0f\x11\x62\x6e\xe5\x83\xc8\x65\xf8\x1d\xa0\x89\x4c\x0a\xe8\x2f\x1d\xe4\x1b\x8d\x1d\xa5\x29\x01\x26\x4b\x7e\xb9\x60\xfc\xea\xe8\x33\xb8\xf7\xa8\x4b\x9e\xd5\x5f\x9f\xc6\xac\x58\xca\x76\x15\xee\x48\xbe\xbc\xb4\xb0\x00\xbf\x9b\xb4\x70\xf3\x97\x23\x1f\x8a\x98\xfe\x48\x09\x6e\xbe\x49\x44\x3a\x2a\x2c\x7e\x0d\xb5\x5b\xaa\xcb\x9d\x35\x5e\x9a\x3c\xe3\xf4\x07\x22\x65\x80\xf4\x94\xe3\x69\x74\x40\xfa\x40\xd1\xbe\x94\x61\xd0\x6f\x29\x1a\x9a\x4a\xcc\xf9\x64\x99\x5d\x20\x98\x13\xd6\x7c\x69\x55\xcc\x09\xb3\xc8\x5f\x01\x29\xd1\x60\x4e\xd3\x72\x59\xc5\x2d\x0e\x0a\xe6\xa4\xa6\xa4\x46\x6b\x60\xd9\x46\xb4\xc4\x72\xd9\xd1\xa0\x1c\xac\xb5\x57\xa0\x37\xb4\x58\xa3\x73\x95\x68\x0d\x6f\x17\xed\xa5\xf1\x7e\x6e\x03\xfe\xa1\x08\x3a\xe3\x7f\x2f\xfb\x41\xc6\xe9\x0f\x5a\xa2\x1f\x5b\xe4\x45\xf3\x57\x26\xf2\x9b\x4b\xec\x60\x85\xcc\x2b\xde\xdb\xc7\xa1\x1f\xa1\xce\xf4\xcb\xff\x33\x79\xe7\x04\x39\x9a\x3d\x28\x31\x5b\x6f\x71\xb9\x98\xad\x77\x78\x84\x9c\x8b\xef\x70\xa9\x8e\xd7\xa3\x45\x55\xe4\xdc\x30\xb6\x9c\x1b\xa9\x9c\xcb\x89\x17\xa4\x50\xac\xb6\x4c\xcf\x49\xab\xf1\x58\xc4\x0b\xe5\x15\xf4\x0a\xd1\xb7\x94\xd5\xcc\x47\xca\xbf\xac\x6d\xa0\x52\xef\x13\xe8\xac\x51\xcf\xa1\xb9\xda\x39\x98\x53\xe4\x39\x4e\x86\x41\x37\xb7\x98\x17\xc2\xb4\x41\xc0\x25\xe5\x62\xb5\x75\x07\x75\x2e\x15\x5b\xaa\x38\x9d\x6d\x65\x5b\x1a\x71\x44\x3c\x5f\xb6\x23\x06\xf1\x08\xd9\xd6\xda\x86\x10\x8f\x62\xe8\x22\x82\x8b\xac\x48\x19\x30\xac\x39\xbb\xb1\x29\x2f\x40\x7e\x38\x88\xcb\xcb\xec\x54\xb9\x80\xa6\x70\x90\x29\x50\x63\x3e\x28\x3f\x98\x59\x51\xc3\x11\xe6\x18\xf0\xa7\xd4\x98\x60\x66\x47\x81\x6a\xcc\x1e\x16\x25\xe3\x59\x75\x35\x87\xb3\x2a\xe3\xa5\x0f\x5b\x40\x1a\x88\x87\x79\x36\x50\x6d\x97\xfc\x91\x0d\x38\xea\x4d\x7f\xef\x99\xf2\xed\xb1\x2f\xe0\xf6\xd7\x42\x2f\xeb\x7f\x1f\x9e\x3a\x62\x6f\xf0\x4e\x6c\xd2\x67\xc1\xfd\x8e\xa2\xf3\x47\x32\x92\xb8\x53\xaa\xe8\xb0\x2a\x06\x51\x11\x06\x8a\x82\xa4\x5c\xe0\x10\x49\x4c\x17\xb5\xda\x21\x83\xe2\x46\x96\x67\xdc\x82\x17\x82\x6f\xb3\x4e\x82\x44\xa0\x5b\x95\x72\x6c\x50\xce\x96\xab\x1c\x38\xf9\x30\x43\x3a\x00\xca\x67\x69\xdb\x17\x7f\xbd\xf8\xa4\x33\x8e\xb9\x78\x91\xad\xe0\x70\x04\x6c\x43\xc3\x2b\x71\xdd\x0a\xfc\xc5\xde\xe9\xaf\xff\x25\xf4\x65\xf0\xb4\x73\xb9\xe3\x41\xdb\x4a\xb8\xaa\x97\xa3\x5a\xb3\xe3\xad\x44\xb5\x22\x0e\x4d\xf1\xa6\xd4\x80\x11\x7f\xd4\x11\xdc\x12\x1f\xe0\x96\xc8\x54\xc3\xea\x29\x6e\x89\x71\xd3\x65\x31\xe7\x15\xfc\xa0\x51\x01\x2f\x81\xa6\x47\xa2\x22\x66\x55\x1c\xa9\xaa\x5f\xd6\xe2\xfb\x68\xae\x7a\x8d\xd6\x11\x48\x2b\x97\x6c\xf9\xcd\x73\xbf\x58\x7c\xdc\xc4\x49\x2b\xf3\xd7\x5c\xcc\xcd\x5b\x7d\xc2\x29\x3b\x5e\x19\x7e\x6a\x70\x73\xf4\xf3\xc0\x13\xcc\xe7\xef\x50\xb9\x53\x6e\x08\xe8\x97\x95\x51\x14\x1d\x5f\x8d\x81\x20\x94\x52\xc3\xbc\x25\xfd\x0a\x2a\x8f\x58\x09\x0d\x49\xe4\xa0\x69\x48\xe4\x31\x18\x05\x9a\x98\xf5\x63\xf0\x76\x94\xf6\xd3\xde\x6b\xdb\x00\xb9\xb3\x3a\xf4\x6d\xda\xad\x2d\x9b\xd3\x01\x31\x27\x88\xdc\xc7\x5b\xc6\x55\x92\x35\x45\x22\x24\x56\x82\x4c\x8c\xab\x64\x95\xd9\x22\x22\x44\x5a\x8a\x60\xf6\xd7\xc7\xe4\xd1\xe1\x7b\x64\x3c\x3a\x18\xc9\x76\x66\x7d\x61\xeb\x18\x90\x30\x3b\x76\x94\x20\xc1\x14\xb9\x39\xae\xa2\xdc\x23\xb7\x57\xe1\x1e\x19\xa5\x55\xd6\x22\x24\x19\x74\xd7\x94\x74\xc6\x16\xd9\x49\x06\x83\x7c\x83\x1d\x9a\xf0\x8c\x9f\x07\x52\xb4\x5b\x16\xcc\x19\x6d\x95\x55\x02\x62\x9e\x75\x84\xeb\xc0\x94\x05\x09\x3e\xce\x68\x7c\x25\x95\x8d\x04\xa3\x71\x64\xa4\xca\xd2\x89\xde\xd1\x98\x31\x78\x97\x39\x72\x39\x5c\xc6\x55\x42\xf0\x57\x92\x14\xfb\x67\x55\x15\xec\x1f\xc0\x1d\xe1\xb5\x5c\x20\x6a\xc8\x23\x10\x72\x24\x15\x6f\xba\x14\x10\xc8\x97\x56\x6a\xfd\x79\x2f\xd9\xb7\x37\x45\x01\x82\x14\x19\x4a\x8b\xf9\x10\x91\x02\x40\x05\x79\x49\xff\x5e\x93\x98\x67\x9d\x84\x10\x57\x09\x49\x4a\x78\x4c\x94\xa0\x91\x0d\x15\x55\x15\xe1\x47\x65\x62\x78\x70\x74\x20\xa7\x27\xcc\x26\x8a\xb5\x25\x7a\xc1\x95\x71\xeb\x34\xa0\x76\x34\xab\x2a\xbb\x4e\x47\xb5\x2b\xd9\x49\xaf\xe4\x10\xeb\x08\xc5\x1a\x13\xed\x94\x5f\xa7\xb9\xe5\x20\xf9\x75\xc0\x7f\xf0\x62\x21\x73\x10\x4c\x3b\x4d\x53\x2e\x92\x71\x57\xe3\x07\xd3\x77\xdf\x3a\x01\x77\x45\xb7\x2d\x19\x8b\x72\xe7\x94\x5f\x74\xc8\x7d\xaf\xf6\xc7\x36\x5f\x20\x27\x9f\x3e\x11\x59\x78\x87\x04\xeb\x29\x8c\x12\x68\x1c\x9a\x4b\x4f\x3c\x66\x9e\x78\xdc\xb0\x9a\x5d\xa5\x53\x32\xf5\xe4\x0a\x2b\xed\x69\x00\xa1\x88\x58\xb7\xb8\x5e\x7c\x9a\x95\x9c\xe1\x40\x73\xcb\x38\x0a\xf8\xd4\x66\x28\x74\x6c\xd4\xab\x6c\xee\x94\x2d\x85\xd6\x19\x05\xcb\xea\x97\xe6\x4e\x5b\x2c\x5c\x1d\xd1\xdc\x73\x15\xe8\x27\xba\x57\xeb\xb6\x33\xd8\xdc\x36\xf4\xc8\x08\x33\x6d\xaf\xa1\x10\x4a\xa0\xab\xc8\x54\x31\xf4\x47\xc0\x80\x53\x0d\xab\x41\x16\x4d\x75\xb8\x8b\x36\x20\xef\xf4\x04\x59\x4f\x52\x75\xba\x2d\x27\x25\x1c\xb2\xa0\xc8\xbc\xb2\xa6\x38\xd2\x39\x6f\x1d\x30\x6b\xbb\x69\xc7\x44\x5d\x58\x94\x72\x22\x1b\x24\xd3\x81\x86\xaa\xd7\x65\x15\xa7\xa8\xa2\x70\x16\xa0\x21\xea\x2d\x81\x84\x4b\x28\x37\x49\x77\x04\x99\xca\x10\xa1\x6d\x71\x05\x3e\x09\x4f\x99\x7c\x7d\x82\x3d\xa7\xc8\xc1\xd9\x7a\x47\x97\xfe\x82\xae\xe0\xa9\x1b\xd6\x1d\x76\x45\x6b\xe2\x86\x81\xf5\x1b\x98\xbf\xe0\xc5\x78\x95\xd7\x61\x76\x68\x3a\x5c\xf8\x16\x7c\xfe\x57\xdf\xc8\x12\x7b\x6b\x20\xb4\x8f\xde\x6d\x61\x25\xb7\x1c\x10\x39\xd2\xe8\x27\xa4\x7a\xa7\xd4\x66\x54\x51\xd0\x48\x97\x48\x82\x9e\xba\x62\xcf\x14\xf1\xb0\x7a\x78\x2d\x3f\xce\x03\x1d\x23\xe3\x6c\x1a\x56\x32\xb0\xff\x46\x19\xda\xad\x5b\x8b\xdc\x06\x5d\xc6\x6b\x2a\x69\x80\x0f\xdc\xda\x28\x4a\x6a\x2d\x0b\x94\x06\x2a\x5f\x93\xcd\x2a\x5d\xd2\xa0\x5d\x8c\x8c\x23\xd8\x32\x34\xd0\xf2\x24\x44\x49\x09\x66\x95\x71\x62\x0e\x35\xb6\x66\xb3\x59\x95\x35\x1e\x59\xe3\xef\x5b\xb2\xe9\x27\xed\x9d\x72\x49\x7f\x67\x1b\x0c\x58\x97\x02\xa0\xd9\xcc\x0e\xcf\x18\x66\x96\xbe\x7a\xf4\x0f\x3e\xfb\x0a\xfb\x0b\x21\xe1\xee\x1b\x16\x3f\x7b\xce\x89\xbf\xba\x49\xff\xe2\xee\xdb\xf7\xae\xdd\x73\x43\x11\x0f\x8d\x15\xf0\x8b\xcc\xa5\x0b\xe6\x5d\xc9\xf4\x62\x19\x77\x9d\x70\xdc\x83\xfa\x97\x9f\xde\x65\xbf\xfa\xf6\xce\xee\xdd\x6d\xed\x0f\x3c\x70\x1b\xb6\xab\x54\x73\x3a\x2f\xba\x6a\x39\xb1\x8d\x86\x6f\x3e\x0d\x72\xad\x21\xd4\x50\xea\x9d\xc3\x38\x59\x83\x5b\xcb\xbb\xc3\x88\xf1\x24\x55\xb7\xab\x38\x5e\x29\x6b\x4a\x38\xad\x78\xe8\x70\x99\x4c\x66\x47\x3c\xd6\x9d\x89\x89\x39\x97\x08\x6e\xad\x4d\x1a\xb4\x3b\xa5\x00\xbc\xe1\x61\xe3\x7d\xb0\x67\x95\x06\xd1\x1a\x32\xe3\xe4\x20\x2f\xe0\x38\x4e\x14\x89\x34\xd8\x22\x6d\xc5\x13\xb8\x13\xd7\xdf\x71\x1d\x7e\x4a\x7f\x5c\x7f\xe4\x51\x91\x46\x74\xcf\x9e\xf3\xa3\xdb\x56\xdf\x33\xcf\x36\xf4\xf6\xbb\xd7\x6e\xcb\x16\x56\x31\xbd\x85\xd7\xad\x78\xb4\xc0\xcc\x5f\xb8\x60\x8e\x99\x83\xf8\x11\x1f\x47\x7e\x14\x45\x93\x46\x78\x4f\x6e\x8f\xe5\x7b\xf8\x7d\xc4\xe1\xf0\x83\x37\x2e\x12\x44\x47\xec\x1e\xe9\x17\x85\xd9\xd6\x62\x77\x05\x84\x9c\x1f\x76\xf9\xc6\xab\x0b\xa6\x74\x84\x5b\xfa\xee\x7c\xe4\x6a\x2b\xe2\x7c\x6e\xde\x72\x87\xfe\x9e\xf3\x9e\x9b\x0a\xaf\x14\xa3\x4d\x90\xb5\x3e\xd1\x36\x0d\xf2\x16\x86\xac\xcf\xac\x90\x75\xc8\x90\xb5\xb7\x9a\xac\xbd\x20\x6b\xa9\x44\xd6\x92\x47\x94\x72\xae\x30\x00\xd2\xd9\x44\xd5\xee\x84\xb2\x03\x15\x70\xa8\x8a\x80\x8b\x74\x20\x25\xa1\x67\xb9\x80\x89\x5c\x9b\x8b\x11\x68\x89\x80\xd9\x2e\x43\xae\xdf\x3c\x5c\x8c\xe9\xce\xd6\x27\xb2\x2b\xb8\xe5\xc8\x8e\xa2\x68\x72\x49\x1d\x22\xe7\x37\xe4\x2b\x53\xf9\x3a\x76\xaa\x51\x2a\xdf\xa8\xc3\x70\xe8\x04\x8e\x00\x92\x38\xe5\x62\x1a\xa6\x98\xad\xab\x90\x74\x31\x75\x57\x26\xe9\x62\x16\xaf\x4c\xd6\x95\xfa\x5c\x8b\x5a\xd0\x05\x15\x32\x6e\x31\x64\x5c\x57\x94\x71\xab\x25\xe3\x3a\x90\x71\x9c\xca\xd8\x9c\x5f\xcd\x79\xfd\x35\x86\x8c\xe3\x62\xce\x25\x45\x89\x46\xe7\xed\xce\xa0\x1c\x82\x5d\xd4\x51\x89\xb7\x54\x53\xe9\x11\xc3\x93\xa3\x28\xb6\xbe\xbf\x2c\x4c\xbb\xa5\x8a\x7e\x97\xc5\x9e\xc3\x33\x4d\x1d\x3f\x09\x21\x76\x13\x1f\x47\x5e\xd4\x60\xe8\x38\xd4\x4f\x0d\xf1\xe7\x42\xe0\xae\x7a\x88\x12\xf9\x76\xaa\x0d\x3e\xa2\x36\x0d\x3e\x51\xca\xb9\x99\x00\xe8\xb8\xdf\x78\xc3\xa4\x00\x1d\x18\x2c\x6f\xa3\xaf\x38\x88\x93\xca\x56\xd8\x59\x76\x1a\x65\x51\xe4\xde\x4b\xcb\x8f\x84\x41\xf3\xf6\xef\xe6\xc2\xc2\x72\xd4\x86\x7a\xd0\x15\x04\xed\x41\xe5\x58\x2d\x27\x51\x16\xad\xc1\x50\xab\x64\x4f\x02\x24\x88\xcf\x8a\x61\x8c\x80\x32\xe1\xd3\x0c\xf7\x2a\x6d\xf8\x54\xb0\xec\xf6\x0e\x43\xfe\x82\xf8\x34\xe7\x92\xa2\x8d\xad\x49\x60\x65\x48\x48\x83\xa1\xf8\xb8\x2e\x38\x0d\xae\x55\x94\x14\x64\xe8\xff\x20\xf6\xd5\x02\xc2\xb8\x14\xa5\xb4\xfd\x03\x62\x3d\xb9\x01\xdd\xb8\xad\x9b\xe9\x1b\xdf\x9c\x49\x87\xc8\xc4\x2e\x2f\x07\xeb\x71\xb8\x1e\xcb\x41\x8e\x34\xb1\xc1\xdd\x9e\x77\xd7\x6b\xa7\x9c\x77\x41\xcf\x19\xab\x6f\xbc\x71\x26\x16\xfe\x71\xf1\xeb\xcb\xce\xb9\xf4\xbe\xe9\x73\xe6\xb5\x9e\xf4\xc0\x6b\xf7\xea\xef\xeb\x1f\x7d\x9f\x5e\xf7\x23\x70\xe3\xe1\xfd\xc7\x1f\x97\xfc\xd6\x94\x23\xa6\x5e\x72\xff\xf9\x2f\xfe\xb9\xbf\xf7\x8b\x9e\xd6\x59\x87\x77\x4c\xce\x4e\x9f\xff\xf2\xea\xad\x1f\xf0\x53\xcb\x72\x65\x73\xf7\xef\x66\x37\xf0\x71\xd4\x82\xba\xd1\x72\x94\x93\x0d\x79\xd4\x9a\xd3\x05\x0e\x41\x03\x2c\x23\xb4\x53\x89\xa4\x8d\x28\x4e\x71\x11\xd7\x44\x0a\x10\x38\x23\x98\xce\x4f\xb4\x02\x7f\x82\xe1\x99\x38\xbc\x72\x6d\x53\x47\x37\x54\xed\xa4\x3c\xef\xb3\x75\x26\x41\x14\xb5\x32\x10\x9a\x2b\x0e\x71\x10\xf1\x52\x94\x40\xd0\x91\xfe\xc5\xf1\xfd\xe6\xb8\xf5\x68\x2c\x3b\x4c\x11\x7a\xf3\xc3\x3f\xfc\xe6\xf9\xb9\x27\xdf\x39\xe3\xa6\x53\x7f\xb4\xea\x8a\x43\x3e\xfb\xf4\x8a\x0d\xc7\x9e\xf2\xd6\x89\xeb\xc7\x2d\x39\xfd\xda\xcb\x07\xf6\x52\x11\xb0\x13\xef\x7e\x64\xce\x9f\x9a\xbb\x8f\xe9\x98\x34\xb1\x6f\xee\x65\x27\x6d\xc8\xc7\x1b\x87\xdb\xfb\xcf\x6a\xee\xca\xb6\xf6\xcf\x5d\x81\xff\x59\xca\x8f\x55\xd4\x87\x3e\x74\xe5\x18\xfa\xd0\x3f\x8a\x3e\x0c\x50\x7d\x18\x74\xb7\x77\xf4\x11\x54\x51\x53\x21\x48\x57\xb3\x94\x0f\xc5\xc7\xa5\x7a\xff\xaf\x34\xa2\xbc\x97\xee\x80\x6a\x71\x61\x69\xf5\xee\x60\x74\xa3\xb2\xa6\x67\xe8\xc7\x8b\xa0\x1f\x19\x74\x49\x55\xfd\x20\x78\xdc\x91\xd6\xf4\x08\x0d\xe9\xb3\x34\xa4\x23\x43\x34\x64\x88\x68\x48\x6f\x89\x82\xa4\xfe\xaf\x14\xa4\x08\xf4\x30\xa6\x96\xe0\x52\x89\x1c\x58\x55\x2a\xe5\x31\x4f\x0f\x72\x61\xdb\x76\xd4\x86\x0e\x41\x8f\x10\x7d\xc9\xf7\x90\x81\x2b\x53\x65\x94\x09\x29\x35\xe9\xb5\x34\x67\x62\x75\xcd\x19\xec\x4b\x08\xf6\xa4\xda\x15\xd1\x94\xae\x94\xda\x17\x21\x84\x24\x54\x95\x52\x87\x18\x12\xe8\x12\x37\x72\xae\xd6\x64\xcf\x04\xe2\xe9\xe7\xa5\x68\x63\x6f\xda\x50\x9a\x44\x9f\x28\xa9\xa1\x38\x60\xc5\x24\x45\x69\xb0\x3d\x95\x36\x74\x4f\x0d\x4d\x10\x25\xd5\x57\x9b\xfd\x0f\x0c\xcd\x48\x46\x83\x03\xea\x56\xb2\x9c\xdc\xe0\x80\xda\x35\x82\xe9\x00\x51\xbe\x87\x0d\xdc\x72\xd4\x82\x26\xa0\xf5\x44\xbf\xf2\xdd\xa5\x7c\x0f\x82\xa6\xf4\xa7\xd4\x0e\x8b\x32\x63\xa4\x25\x1a\xcc\x48\xf5\xf6\xa4\x9a\x8c\xc0\xa8\x5b\x26\x42\x58\x33\x0c\xc5\xcb\x27\x5a\xbb\xba\x41\x7a\x49\x31\x6f\x58\xa6\x7e\xe3\x73\xbd\x94\x77\x78\xd9\x54\x0f\x5c\xbf\x8c\x28\xe5\x78\x9f\x0d\x5e\xa0\x8e\x7e\x51\x52\x26\x64\x15\x59\x1c\x6c\xed\xea\xc9\x00\x25\x44\xb7\x28\x19\x1a\x09\x25\x0c\x93\x13\xe2\x60\x34\xb2\x0a\x43\xc4\x98\x6a\xb9\xa1\x5c\x98\x07\x50\xcc\x7d\x9f\x94\x8b\xb2\xd4\x8e\xf5\xa3\x95\x63\xd8\xb1\x81\x51\xec\xd8\x84\xe2\xbb\xd6\x59\xf6\xae\x8d\x1b\x6f\x99\xb1\xee\x54\xe6\xff\xce\x8c\x95\xbd\xf0\x07\xb6\x63\x65\x2f\xfe\x01\x55\x4d\x58\x52\x9e\x1c\x27\x76\xec\xb7\x60\xc7\xc6\x8f\xf2\xce\xf5\x8d\xf2\xce\xf5\x53\x65\x1a\x4c\xb4\xb6\xa7\x41\x7f\x4c\x33\xd6\x59\x34\x63\xe3\x7a\xff\x4f\xcc\x58\x39\x42\xc7\x98\x0a\xe3\x2a\x93\xc8\x01\xf4\x85\x6d\xaa\x94\x47\x87\x1e\xe4\x2e\xb7\x0d\x21\x01\xd5\x18\xf1\xb9\xdf\xf0\xd5\x78\x93\xf8\x4f\x45\x2c\x70\xd5\x44\x52\xaa\xcb\x4b\xe6\x20\xf9\x9d\x86\x23\x9a\xb3\xf1\xd0\xae\xc7\x3a\x92\x39\xde\x66\x7c\xe4\x91\x23\xa9\xd8\xfc\x8a\xdc\xb8\x53\x54\x3d\x11\x4d\xf1\xa4\x54\x39\xa2\xc1\x64\xa4\x87\x37\xa2\x02\x7f\x84\x46\x05\x46\x2c\x83\x54\x17\x6d\xde\xf1\x8b\xaa\x5d\x36\xe1\x33\xa1\xc1\x7d\xe4\x95\xe9\xe0\x66\xea\xcb\xf5\xdf\x4c\x2d\xbf\x1b\x5c\x1e\x33\xba\xbe\x6f\x06\x97\xdf\x5b\x57\x61\x51\x18\x94\xd2\x83\xec\x80\x6d\x06\xf0\xc7\xdc\x47\xf2\x0e\x26\x7f\x8c\xcd\x38\x6a\xbb\xa0\x29\x28\x4d\x06\x16\x4a\x78\x64\x82\x3b\x55\x87\x8f\x8c\xfb\x06\xa1\xc5\x4a\x80\x94\x5b\x2e\x08\x2d\x56\x41\x63\x93\x0e\xbf\x1a\x73\x15\x39\x66\x1c\x41\x51\xda\xc8\x84\xa2\x75\xf5\x74\xc4\x6b\xd0\x2d\x56\x50\xcb\x88\x45\x6a\x19\x7b\x3d\x69\xfc\xb3\x89\x0a\x06\x07\x77\x2a\xce\xc8\x71\x99\x00\x87\x92\xf6\xb8\x3e\xb1\x8a\xd1\x48\x3d\x3e\x67\x0b\xce\xea\xaf\x1c\x33\x69\xe6\xd2\x8b\xd7\x3f\xfd\xd8\xdc\x0a\x33\x71\xf9\xb5\xe7\xed\xfe\x74\x57\x61\xd7\x61\x53\x12\xef\x67\x9e\x79\x86\x89\xed\x9b\x53\x69\x64\x19\xd4\x81\x10\x77\xb9\xb0\x1c\x09\x28\x84\x0e\x47\x23\x8e\x19\x2b\xe1\xb1\xcf\x17\x12\xca\x36\x1e\x50\xd9\x50\xf1\xc0\x2a\x02\x0a\x7a\x58\xfa\x47\xe5\x55\x1e\xeb\xb0\x98\x75\x95\x3a\x98\xda\xbf\x9b\x7d\x89\x6f\x07\x2c\xa2\xa5\x34\x47\xe4\x76\x68\x65\x07\x65\xb3\xc3\x82\x38\x07\x19\x32\x81\xe2\xdc\x81\x0f\x0b\x6a\x74\xc6\x09\x29\x4c\x16\xa9\x6e\xb1\x74\xa8\xd5\x26\x8d\x71\x04\x56\xb3\x44\xa5\xe0\xf1\xcf\x69\x67\xc3\x48\x91\xe3\x05\x56\x9f\x03\x26\xb2\x86\x1a\xee\x19\x24\xcb\x57\x2a\xe9\xbc\xdb\xe3\xc4\x9e\xa4\x62\xcb\xa8\x6e\xb7\xa6\x08\x69\xe8\xfa\x71\xee\x54\xbc\x69\x6b\xda\xdc\x09\x3b\x62\x1d\x74\x5f\x39\x27\x6c\xca\x89\x8c\x1f\x38\xdd\x04\xa8\xc3\x3a\x04\x32\x7e\x90\xe8\xcb\x88\x20\xfd\x7f\xfd\x4b\xff\xcd\x9e\x3d\x44\xe4\xfa\xc3\x7a\x61\x03\x73\xb2\x8e\xe7\x43\xed\xc6\x90\xb5\x71\x2f\xea\xd1\x5d\x88\x20\xdb\xf9\xc7\x96\x74\x3e\x56\x1b\xe2\x3c\x46\xa8\xaa\xc6\x6c\x9a\xe2\x4a\x83\xe8\xa3\x3b\x95\xba\x34\x4c\x86\xc0\x34\x82\x07\xf2\xd3\x1e\x01\x9a\x8c\xc9\x88\x44\x2e\x0a\x98\x30\x51\x58\x70\x34\x46\xcf\xc2\x13\xa5\x67\xe1\x0f\x89\x92\x12\xc8\x2a\x31\x51\x91\xb2\xaa\xcd\x2e\x56\x9c\x06\x99\x4d\x08\x59\x3c\x54\x93\x71\xa2\x2f\xd3\x67\x9e\x06\x0e\xe9\x1f\x19\x27\x32\xfe\xee\x63\x9e\x7d\xe2\xea\xab\xe9\x59\xbc\xb0\xf5\x2e\xe3\x30\xa2\x35\x43\xcf\xdd\xb5\xf5\x05\x54\xc2\x7b\x7b\x16\x92\x50\x27\xfa\xbc\x0a\x73\x6c\x53\x4a\x0d\x24\x32\x64\x6f\x35\xe9\xc1\xb6\x58\x93\x1d\x28\xbc\x42\x36\x4d\x0d\xd7\xa7\x4b\xd9\x64\x4b\x89\x71\xc7\x55\x74\xd5\xb7\x76\x2b\x35\xdd\x4a\xab\x5f\x0d\xd7\x7e\xa3\xd4\xf8\xd5\x44\x69\x57\x7d\xd8\x3f\x18\x09\xd7\x04\x92\x83\x51\xe3\x4f\xa5\xd5\x3f\xd8\xdc\x9a\x08\x24\x07\x5b\x8c\x3f\x73\x91\x70\x4d\x49\x57\x7d\x34\x9b\x6b\x69\x4d\x18\x9f\x9a\xb3\x68\x30\x12\x6d\x6e\x21\x5d\xf5\xe1\x48\xb4\x26\xd1\xdc\xd2\x5a\xd6\x55\x5f\x41\xcd\x5b\x4f\x5e\x22\xb7\xa4\x36\x34\x8e\x4a\xcd\x5b\xb5\xf9\x7e\x04\x8d\xed\xaf\x46\xe9\xc4\xaf\x46\x65\x5b\x3b\x92\x67\xc2\xc4\x99\x26\x7c\x1f\xdc\x68\xa8\xcc\x07\xcb\xf7\x51\x01\x44\xfd\xff\x0f\xbe\x0f\x0a\x85\x3d\x8e\x40\x61\xe7\xa5\x22\xdd\xc7\xa0\xaf\x31\x4e\x78\x33\xf1\x81\xd0\xa1\xab\x9e\xc6\x08\x6c\xe8\xf3\x46\x39\x8d\x2a\x00\xd1\x91\x11\x87\x41\xef\x00\xaf\x23\x09\x85\xd0\xf1\x55\xee\x40\x20\xa5\x06\x79\x0d\xcc\xff\x48\x4d\x8f\x54\x50\x40\x2b\x7e\xd0\x30\x39\x34\x3a\x5b\x75\x5c\x1e\x49\x8b\x2c\x30\xeb\xab\x32\x3d\x93\x1a\x27\xd5\x17\x8a\x19\x34\x1a\x2e\xb9\x05\x15\x14\xad\xa6\x15\x35\x15\x90\xf0\x8a\x44\x70\xc9\xc3\x91\x83\xc4\x25\x8f\xcb\x23\x04\xaf\x30\xeb\xab\x61\x90\xc3\xa2\x4d\xdb\x72\x15\x70\x6a\x5f\x5b\x45\xae\xf5\x29\x35\xc2\x6b\xb9\x48\x3d\x00\x46\xc4\x1c\x49\x20\x1f\x2a\x25\xda\x56\x82\x74\x30\xa0\xac\x6c\x59\x22\x7e\xa5\xc6\xf8\x0b\x64\xa8\x1a\xa8\x3f\x82\x01\x51\x52\x1a\x01\x07\xc9\xcf\xd7\x03\xb1\x9d\xa4\xd4\x8e\x76\xd9\x4b\x0b\x78\x23\xce\xe4\xf5\xf2\x29\xf1\x2a\x34\xe7\x4b\xcd\xf9\x70\xf3\x3e\x13\x2c\xa0\x9b\x47\x3b\x9f\xea\x10\x40\x45\x30\xf9\x50\x5a\x61\x4b\x01\x80\xc8\x3e\x95\x5a\xf0\xb5\x4d\x00\x20\x80\x99\xa7\x00\x40\x0e\x8b\xd6\xb0\x4e\xca\x79\x7c\x07\x89\x30\x5f\xba\xeb\x11\x47\x7a\x45\xd9\xae\xab\xa0\xfc\x2f\x29\x42\x20\x99\xdc\xe3\x76\x8e\x72\x8f\x7f\xb7\x2a\xf7\x78\xbe\x89\x10\x66\xb6\xa7\xf2\x21\x4a\x98\x59\xf6\x68\x04\x70\x92\xf2\x62\x2a\x0d\x00\xc5\x61\x01\x0b\x97\x3d\x28\x50\x88\x1d\xf4\xf3\xb5\x24\x89\xdb\xde\x24\x4a\x6a\x34\x30\x62\x9b\x23\x09\xc9\x07\x4a\xaa\x33\x23\x6f\xde\x3c\x93\xf0\xf2\x5e\x93\xe9\xb2\xda\x51\x3b\x29\xd3\xe5\x85\x25\xfc\x96\xe4\xcc\x73\x14\x5b\xff\xfe\xd1\xb1\xf5\xf3\xcd\x44\x00\x9d\xa9\x7c\x84\x0a\xa0\x02\x62\x9f\x42\x24\x97\xa2\xec\xc7\x5c\x0e\x7b\x32\xdf\x46\x7e\xde\x96\x32\x95\xbc\x1b\x27\xd5\x38\xc5\xda\x6f\x13\x73\x7c\x7d\x84\x28\x39\x05\x12\xb2\x2c\xaa\xda\xd9\x2c\x4a\x6a\x4c\x1e\x9d\x2a\x61\x14\x09\x8d\x64\x4e\xb0\x8f\x90\x50\x15\xb5\xe0\x2b\x05\xc4\x96\x70\xea\xd7\x12\x04\xca\x91\xac\xfa\xad\xd5\x4c\x6a\x5b\x85\x49\x1d\xf2\x87\x23\xb5\x75\x8d\x2d\xf4\xf1\x8e\x37\x8d\x6e\x5a\x47\xd4\xab\x47\x9e\xb7\x6b\x44\x99\xba\x2a\xc3\xfe\x88\x02\x35\x39\xef\xb7\xa0\x6f\xac\x1e\xb5\x8d\xc1\x0e\xd1\x5e\xcd\xfc\x76\x54\x98\xdf\x8d\x52\xb4\xa6\xbe\xc1\x62\x87\x68\x6a\x3b\x48\x2b\x3c\x62\x87\x23\xce\xeb\xd7\x95\x1b\xac\x4a\x13\x31\x62\x7f\x0c\x7a\x4a\x0f\xda\xe6\xd9\x86\x90\x84\x9a\xd1\x0a\x72\x5a\xf4\xc2\x96\xba\x83\x75\x5e\x0b\xf4\xaa\xe4\xfe\xd6\x10\x54\xa4\x9a\xe2\x29\xb6\xe2\xa4\x5a\x13\x10\xa5\x1c\xef\x0f\x11\x1f\x20\x17\x6e\x20\x34\x5f\x75\x4d\xc4\x48\xfb\xc5\x5c\xa0\xa6\x21\x9b\xcd\x12\x08\x74\x7e\xd4\xab\x5c\x31\x21\x35\xf2\x50\xd7\x95\x03\x1d\x8d\x3c\xd1\xc2\x27\x23\x31\x8e\xee\xd7\x83\xdc\x5a\x6e\x1e\x0a\xa2\x56\xf4\x23\x3a\x3f\x3a\xaa\x23\xd6\xe0\xb5\xa0\xf0\xcb\x4f\x76\xb0\x16\x2e\x2a\x81\xf5\x56\xe4\x54\xbe\x96\x8c\x80\xb5\xe3\xa4\x2a\xb3\xa2\xa4\xf2\x52\x36\xab\xd6\x3a\x44\xc3\x42\xc3\x65\x75\x89\xb9\x68\x9c\x60\xe7\x34\x34\x13\x43\x2e\x89\x39\xb9\x36\x6e\x48\x82\x8f\x1c\x80\xe1\x64\x84\x34\x46\x28\x00\xb3\xa0\x1c\xa1\x7a\xc4\xf1\xeb\x13\x2b\x84\x01\xb3\xe2\xc2\x73\xc2\x72\x54\x87\x92\x38\x8a\x72\x75\x08\x46\x93\x72\x08\x60\x1a\xc4\x4c\xc6\x64\x89\xc7\x3e\x4d\xc1\xa4\xbf\x44\x22\x14\xf1\x86\xab\x39\xc5\xff\xf9\x99\x86\xab\xe9\x55\x6c\x7e\x45\xd8\xac\xc6\x5c\xdf\x28\xd1\xcd\xcf\x6e\xde\xf8\xf5\x8d\xe4\xc7\x11\xbf\x12\xda\xac\xba\xb8\x6f\x14\xcf\xe6\x67\xa7\x6c\xfa\x9f\x43\xc1\xf7\xb4\xf9\x07\x79\x9b\x10\x48\x3e\xbb\xf9\xb3\x7f\xd6\xc1\x4f\x5c\xfe\x41\xb7\xcb\x13\x48\x2a\x11\xff\x60\x38\x12\x0a\x24\x9f\x9d\xf2\xd3\x2f\xff\x00\xff\x29\xe6\x1f\xac\x89\x45\x03\x46\xc0\x5d\x32\x66\x9b\xab\x89\x45\x8d\x7f\xb8\x5d\x9e\x92\x1f\x86\x23\x21\x51\xca\xa2\x43\xdd\x82\x27\x12\xb3\xf1\x2e\x77\x28\x1c\xad\xe9\x2e\xf9\x7f\x78\xf4\xff\x04\xce\xab\x88\x45\x69\x30\x50\x57\x4f\x78\x30\x51\x1d\xed\x76\x04\xb2\x89\x29\x78\x20\x10\x0f\xd4\x63\xf2\x01\xc7\xd9\x56\xa6\xcd\x8b\x05\x36\x5e\x9e\x5e\xc7\xbd\xbf\xec\x0d\xf1\xc9\xc0\x5b\xb8\xe5\x2d\x6f\xa7\xcb\x39\x4e\x7a\x16\xf7\xea\xb7\xe9\x3f\xd9\xea\xea\xe3\xf8\x1e\xcf\xcb\xfa\x9a\xa1\x72\x48\x82\xe1\xf7\xde\x5d\x9b\xfd\xec\x70\x36\x33\xfc\xda\xc0\x7b\x27\x1e\xaf\x4d\x63\xeb\xf7\x4e\x67\x51\x07\xc6\xe3\xfa\x3f\xcb\x14\x98\x72\xa0\x02\x06\x05\x11\xe2\x5f\xe6\xe3\x28\x86\x3a\xd0\xaf\xe8\x74\xbc\x9c\x01\xc6\x8d\x1c\x76\x06\x32\xc6\xa9\x75\x96\x9e\x5a\x00\x1c\x24\x60\x45\x35\x4e\xed\x45\xe9\xb3\x3f\x41\x80\x80\xfc\x4a\x6c\xb3\x57\xc1\x7e\x85\xd9\xfc\xec\x0b\x7f\xf8\xfc\x77\xc6\x4f\x6d\x8a\xb3\xdb\xab\x78\x36\xab\x11\xe1\x1b\x25\xbc\x59\x71\xfa\x07\x5d\x4e\x4f\x20\x39\xe8\x36\xfe\xcc\xb9\x9c\x25\x02\x57\xdc\x59\xb4\x91\x71\x85\x23\x6e\x0f\x95\xef\xd3\x8c\xd3\x15\x8e\xc4\xcc\x7f\xa7\x62\x0d\x60\x23\x26\xa8\x25\x28\xd5\x28\x26\x4a\x2a\xe7\x05\x4d\x8f\x07\x42\x81\x4c\xff\x54\x4c\x04\x9b\xa1\x92\x75\xe1\x44\xa5\x54\x83\xb8\xe7\xda\x50\x9b\x9d\x6b\xf0\xdf\x82\x67\xae\x72\x27\x18\xbb\xab\xdd\x7b\x23\x4e\xea\xbf\xd6\xf3\xb3\x2f\x76\xfc\x56\xdf\xb4\xa0\x54\xa8\xdc\x3c\x5d\x9c\xa3\x6b\x33\x1e\x3d\x85\x89\x14\xfe\x31\xf0\xd6\x21\xa7\xbd\x9f\xc1\x9f\xed\x5b\x8b\x6f\xc2\x9f\x0e\xdf\x5a\x46\x94\x69\x61\x26\x70\x3a\xe0\xf4\x86\x50\x9a\xf4\xd2\xc2\x25\x50\xd8\x0c\x04\x00\xc2\x4e\x95\xa7\x5e\x3f\x2f\x88\x92\xca\x04\x61\x2b\x02\x84\xed\x86\x82\x38\x70\x1c\x9b\xb3\x39\x45\x5d\x98\x89\x53\xb8\x17\x1f\xaf\xc7\xf4\xdf\xea\x5a\x05\x10\xc5\x7a\xe6\xf4\xe1\x55\x85\x57\x98\x14\x3b\x5c\x7e\xbe\x45\xde\x9a\xe6\x6a\xbc\x35\x2d\x29\xc3\xc6\x1e\x3c\x25\x4a\xc5\x92\x46\x21\x42\xd1\xff\xbb\x5c\x7e\x55\x29\x6c\xca\x39\x86\x88\xcc\x66\x23\x3b\x78\x42\x4b\xcb\xa5\xa6\x48\x29\xa5\x3e\xa3\xba\x59\x4d\x89\x10\xef\x9e\x88\x70\xd0\xc7\x0b\xf6\xa4\xea\x10\x35\xc5\x91\x52\x7d\xa2\x36\x28\xc3\x0f\x62\x92\x46\x38\xfc\x0c\x83\x89\xdd\x92\x61\x13\x65\x1f\x88\x57\x8d\xf1\xa2\x94\x63\x23\xc4\xcd\x1d\x29\xf3\x51\x39\x5f\x4a\xa4\xff\xdc\x48\x9e\x97\xd2\x23\xe0\xd6\x8c\xe0\x77\x61\x50\x2f\x42\xdc\x32\x61\x39\x72\x20\x09\x75\xd3\x99\x1c\xc1\xc4\x02\x06\xf8\x12\x23\x42\x34\x8e\x42\x40\x90\xa7\x51\x39\x96\x3e\x67\x99\x3e\x1c\x17\xe3\x32\x2e\x19\xd6\xea\x65\x7e\x55\x98\xcd\xd5\x14\x8e\x60\x5e\x2f\x74\xd0\x52\xec\x36\xf6\x13\x8c\x5e\x1d\x96\xca\xe7\xc2\x06\x10\x62\x9f\xe0\xe3\xe5\xdf\x6b\xd7\x72\x1c\x36\xbe\xd7\x7e\xa0\xef\x05\x3c\x57\xd9\xfa\xde\x01\x86\xd7\xa3\xec\xe1\xba\x9d\x71\x16\x86\xe8\xf7\xe6\x99\x17\xb4\xad\x85\x13\xb5\xd2\x7e\x17\x73\xbf\xe7\xc1\xf7\x1e\x51\x65\xbf\x8a\x98\x52\xdd\x1c\x7c\xbd\xe2\xdc\xa9\x7a\xfd\x1a\xb0\x47\x7a\x9d\x34\x77\x35\x96\x14\xcc\x21\xa1\x52\x29\x64\x61\x5a\xa8\x44\x06\x6f\x16\x67\x92\x88\x0c\x82\xb0\x96\xa3\xaa\xc8\x60\x8c\xb5\xa8\x02\x93\x1d\x6d\x35\x54\x36\xe6\x6a\x4a\x65\xf3\x13\x58\x8d\x29\x19\x32\xf5\x8a\x50\xb9\x1e\x44\x46\xd1\x83\x68\x8a\x80\x3a\x8f\xa9\x07\x65\xd9\xe0\x12\x39\x0c\x1f\x52\x96\x11\x2e\xca\xa3\x7c\x84\x81\xc8\x64\x13\xe8\x45\x64\x14\xbd\x18\x73\x1d\xa6\x5e\x94\xad\xa3\x44\x02\xc3\x3f\x2b\x5b\x87\x29\x89\x8a\xb1\x03\x32\xa7\xc9\x4e\xe5\x1b\x4a\xa6\xc5\x1c\x29\x95\x73\x68\xe6\xa8\x98\xdb\x1c\x83\x73\x18\xcb\x10\x80\xd8\x04\x16\x21\x92\x22\x4f\x6b\xa2\x49\x16\xd7\x3c\xf7\xda\xc3\x97\x1d\x3d\x77\xc6\xd5\x9c\xf2\xbc\x92\xfa\x6b\xdd\xcd\xfb\xe6\x1a\xb2\xe6\xf6\xef\x06\x6e\xac\x1a\xd4\x82\x6e\x22\xbc\xbf\xa4\x27\xb2\xde\xa9\x91\x79\x86\x04\x21\xc8\x2a\x07\x82\x69\x85\xd4\x2b\x93\x06\x68\x0f\x48\xbd\xc6\x20\xf5\x1a\x13\x1c\xc9\x5c\x34\x66\x66\x5c\x29\xe2\x12\x00\xdb\x18\xd1\x86\xe1\x43\xe4\x5c\x84\xbb\x28\x2e\xaa\x5e\x30\xea\x89\xa8\x28\xa9\x62\x08\xfa\x06\x15\x57\x15\x50\x18\x93\x41\x4b\x48\x88\xb4\x0d\xdc\x9f\x68\x62\x4d\x74\x18\xb7\x7b\xf1\xef\xdf\xd8\xf9\xe1\x2b\x2f\x2f\x95\x33\x1a\xee\x5d\x7c\xc9\xbc\x8b\xde\x7c\x8b\x27\x30\x31\xa1\xc3\x1f\x5c\xaf\xef\xd2\x3f\xd5\x3f\xd6\xdf\x58\xbd\x92\xdb\x50\xb8\x29\xff\xe0\x93\x8f\xe2\x3e\xfd\x2d\xc3\x9e\x3a\x11\xb2\x7d\x6a\x1b\x02\x86\xc3\x71\xe8\x5a\x9a\xf1\xaf\x35\xbb\x7d\x83\x6e\x4d\x49\xa6\xf3\xcd\x09\x11\xe0\x2c\x8b\x3d\xb1\xe1\x08\xb4\x81\x4a\x38\x09\xbd\xcf\xcd\x69\xa5\x96\x50\x4f\x7a\x43\x9a\xd2\xde\xb8\x53\x04\xd4\x71\x23\x80\x94\xc8\xa4\xbb\x2a\xb4\x8b\x92\xea\x74\xc1\x6e\x6b\xc9\x6c\x44\xb3\x08\x3f\x50\x82\x52\x0e\x09\x51\x4a\xb4\xd0\x9f\xa1\x1d\x52\x32\xa9\x4b\xc6\x45\xa8\x53\x86\x13\xad\xa4\x88\x19\x4f\xf4\x99\x6d\x52\xce\x2d\x9b\xf0\x57\x78\x00\x47\x57\x9e\x7f\xdb\x4a\xfd\x2f\x7b\x0a\xef\xf6\x1d\x36\x29\xf8\x45\x94\x79\x77\xfb\x35\x57\xe8\xc3\x2f\x6c\xfc\xde\xb2\x2b\xaf\x5f\xc7\x9d\xfe\xd8\x46\xf5\x85\xeb\x7e\x26\x3a\xeb\x7f\x7e\xfb\xab\x7f\xe5\x36\x7d\x2b\xd5\xdd\xd7\x37\xfc\x8f\xf9\xe7\x0e\x7d\x7d\xfc\xe9\x27\x1f\x63\xcd\x78\xfe\x1a\x66\xfe\x83\xe8\x44\x3a\x31\xe8\x76\x9b\x90\xb4\xac\x96\xb7\x05\x5d\x16\x16\xad\x6c\x0d\x4d\x73\xe9\x9c\x1b\x46\x22\xdd\xac\x23\xa9\xb8\x09\xf0\x87\x43\x06\xb0\x60\xa4\x06\xdd\x80\x7e\x61\x8e\x46\x66\x1a\x39\xd9\x1f\x6f\xb3\x9a\xbc\xd8\x07\x0b\xf7\x5f\x81\xeb\xf1\x84\xc2\xba\x4b\x16\x3c\x74\xe7\x5d\xf9\x13\x6c\x43\xfb\x91\xfe\xfa\x3f\xfe\xa0\x0f\xe8\xe7\x9e\x77\xee\x69\x88\x41\x6b\xa8\x6e\x06\x51\x03\x5a\x40\x7b\x14\x21\xb4\x8d\x38\x35\x68\xa6\x53\xeb\x1c\x30\x01\x85\x05\xab\x1f\x50\x26\x85\x18\x19\x16\x26\x1b\x0b\xa3\x34\x6e\x1e\xda\x1a\x28\x23\x51\xca\x09\x76\x80\xee\x8e\x89\xaa\xd3\x6f\x1c\x8a\xd3\x6f\x98\x31\xc9\x42\xc8\xad\x54\xbc\x40\x51\xed\xd6\xb0\xeb\x0b\xb7\x96\xea\xdc\x34\xaa\x71\x7c\x70\xd7\x7d\x65\xea\xc6\x64\x2c\x65\x83\x1c\x1d\xf7\x29\xc8\x58\x46\xd3\x69\xbf\xb5\xd7\x45\xe7\x4d\x59\xd9\x09\x08\x5d\x86\x7c\x4b\x87\xd2\xcd\x0e\x73\x41\xd6\x80\xac\x03\xe6\x6a\x9c\x59\xa4\xca\x5e\xb8\xe8\x24\x74\x31\x44\x1b\xe4\xe2\x8d\xc0\xe2\x05\xd2\x7d\x0a\xf7\x6d\x34\x64\xab\xef\xd2\xf7\x14\xde\xc7\x7d\x7f\xfd\xee\xca\x1f\x3c\x7d\x0b\x7e\x8a\xb3\x17\x5e\xdf\xfd\xce\x5f\xbf\xc4\xbf\x7f\xeb\x82\x05\x8b\xe7\x99\xf9\xce\x21\xc0\xe2\xa8\x47\x27\x53\xfc\x59\xd9\xe4\xc6\x8b\x39\xc8\x44\x2a\x19\x40\x93\x08\x1a\x17\x1d\xe8\x70\x13\x12\x1a\x18\xe8\x50\x78\x18\xe7\x20\x8c\x78\x40\x50\xe8\x86\xcc\xa7\xc9\x84\x17\x14\x4c\x26\x3c\x64\x75\x3a\x93\x24\x88\x7c\x3f\xee\xf5\x78\xfa\x1e\x5b\xb8\xf5\xaf\xfa\xc7\xff\xb3\x1f\xe9\xbb\x71\xef\x05\x4b\x97\x2c\x5e\xfa\x9d\xcb\x16\x33\x09\xf6\x0b\xfd\x9e\x09\x8f\xce\x3a\x59\xff\xad\xfe\xb9\xfe\x99\xfe\x3b\xdc\x8a\x3d\xeb\xee\x7f\xe4\xe7\x3f\x7b\xec\xbe\x3b\x11\x46\xd3\x20\x57\xbb\x1d\x45\xd0\x91\x94\xe7\xc1\x67\xf2\x3c\xc8\xac\x36\x18\xb1\x33\xf6\x24\x24\x69\xa5\x9d\x40\xf1\x00\xa6\xda\x67\x27\xd3\x56\x11\x31\x67\x23\x5e\x0f\x23\x8b\x14\x57\xb6\x3f\x43\x7a\xf3\x9b\x5a\xdb\xa0\x6d\x40\xea\x1b\x0f\x89\xf0\x69\xbf\xd9\x83\xb3\xf8\x4c\xfd\x61\xfd\xd9\x8b\x36\x9d\x75\xfd\x7d\xc7\xfd\xfa\x95\x57\x72\xa7\x3e\x74\x8c\xed\x9c\xf3\xf5\x4b\xf4\x75\xfa\x7d\xfa\xd2\x44\x3b\xe6\xba\x1b\x30\xbb\xfb\x23\xcc\x1c\xd2\x46\xe6\x70\x57\xec\xdf\x6d\x5b\x2f\xd8\x51\x93\x21\xd9\x46\xe8\xb0\x37\x5f\xb1\x10\xab\x0d\x06\x1a\x39\x3b\x80\x9d\x38\x1c\x16\x49\x74\x34\x04\xfc\x96\x48\x0d\xc4\x44\x29\x87\xa2\x75\x40\x06\xd2\x48\xa3\x5b\xc5\x27\x2a\x1e\x68\x24\x77\x17\xa9\x41\x60\x26\x29\x2c\xb7\x26\x9a\xea\x70\x25\x4d\x08\xf0\x82\x9c\x79\x2a\xf3\xd3\xfb\xba\x8f\x0f\x64\x27\x9c\x53\x49\x10\x42\x28\x41\xc2\x8f\xfe\x42\x76\x6a\xc1\x8b\x67\xfd\xa3\x8c\x1a\x04\xf6\x30\x77\xff\x6e\x2e\xc7\x37\xa0\x38\xba\x98\xee\x21\x6a\xf6\x88\xcb\x64\xde\x07\x56\xdf\x54\x4a\xd5\x6d\x33\x54\x35\x42\x58\x13\x6d\x61\x51\x1a\x64\x65\x42\xcf\x29\x8a\x39\x89\x4e\xee\x45\x1b\x49\x73\xbc\x2c\xe6\x90\x54\x4b\xc9\x42\x44\x78\x02\x08\x8b\xa2\xcb\x02\x13\xec\x83\x57\xac\x64\x83\x25\x24\x22\xc0\x1a\x32\x31\xf9\xd3\x87\x4e\x98\x92\x1d\x38\xb7\x9c\x3c\x84\xd0\x85\x38\x4e\xde\xb0\xb1\x41\x0b\x2e\x7f\xe0\xbd\x52\xda\x90\xff\x27\xb8\x27\x9c\x08\xf1\x17\xd9\x86\x00\x77\x7b\x8e\x39\x8d\x65\xbe\x5e\x1e\xb7\xa6\xd4\x10\x04\x2e\xb4\x53\xf5\x47\x34\xc5\xef\x57\x5d\x86\x01\x94\x35\xc3\x26\x46\xe8\x02\xeb\x68\x6f\xb7\x12\xc8\x2a\x2e\x51\x91\xb2\x48\xf5\xc8\x86\xee\x19\xe6\xd0\x7a\x94\xe8\x82\x8b\xaf\x11\x30\x9d\x18\x6f\xd0\x9e\xe2\xa2\xcd\x07\xe8\x46\xbc\x59\x3f\x6b\xbd\xf1\xf4\x98\xeb\xb6\xde\x1d\x60\x38\x81\xfe\x17\x84\xb8\xf9\x14\x9b\xe3\x44\xba\x76\xbf\x5b\xcb\x09\x0c\x49\x5d\xe6\xd9\x80\x53\x28\xb7\x89\x86\xc8\x3d\x60\x10\x61\x06\x51\xd6\x72\x22\xd4\xa2\x45\xde\x91\x24\xf0\x1d\x01\xbf\x79\x93\xc7\x37\xc7\x29\x58\x61\x63\x73\x4b\x30\x34\x11\x96\x3e\x17\x4f\xc6\x89\x65\x85\xfb\xd9\x07\xf4\x29\xfa\x9f\xf5\x3f\xe3\x43\xee\x7c\x68\xc1\xcc\x8d\x77\xe2\x17\x76\x7e\x8a\x7b\x31\xda\x3b\xfd\xdd\x8f\xce\x3b\x1b\xdf\x3c\x97\xf2\xe0\x2c\x83\xb7\x27\x8e\x96\x51\x9c\x28\x91\x80\x2b\xa8\x2e\xc1\xd2\x78\x2a\xcc\x18\x41\x95\xf4\x48\xb0\x42\xbb\x4f\x53\xec\xa9\x9c\xdd\x63\x8d\xd6\x27\x28\x99\x40\x9e\xf5\x4b\x91\x06\x4a\x20\x6a\xf3\x65\xb3\x8a\x47\x82\xa1\x4f\xa7\x57\x94\xf2\xc8\xe7\x87\xff\x58\xc1\xde\x51\x95\x8e\x65\xee\x47\x2f\xed\x5c\xe2\x0c\x17\x6e\x63\xd7\x97\xf3\xb0\x00\x67\x47\x17\x76\xe0\xf6\x75\xd7\x9c\x75\xf7\xae\x32\xfa\x95\x9f\xdd\xb9\xd6\xe4\xbc\xba\x97\x6f\x40\x75\xa8\x1d\x2d\x22\x7b\x53\x65\x82\xac\xcb\x3a\xad\x09\xa7\x7a\x59\x53\xea\x09\x5b\x28\x2f\x6b\x4a\xc4\xf0\x6b\x5c\x01\xd2\x6c\x52\x6f\x3c\xa2\x22\xb9\xb7\x11\x71\x23\x2b\x7b\x63\x14\x59\x18\x10\xaf\xc8\xfb\x24\x66\x95\x56\x31\xcf\x23\x97\x64\x32\xcc\xa0\x78\x1a\xbc\x1b\x1a\x2f\xb6\x0d\xd0\xde\xac\xd6\xb6\x6e\xdc\x12\x0c\x4f\xc1\xe6\x58\x57\x0d\x76\x7c\x85\x5b\x36\xff\xe6\xd3\x2f\x76\x5e\xf0\xc6\x0f\x2e\x3f\x63\xc3\x9c\xe9\xc7\xdc\x72\xcb\x33\x1b\xf0\xc0\xb6\x15\xb7\x5e\x71\xfe\xd2\x2b\x38\x27\x66\xb1\xb4\x67\xc7\xd0\x67\x87\xdc\xfb\xeb\x1f\x3c\xd2\x75\xd8\x1f\xbb\x06\xfa\xbb\xfb\x17\x1e\x7d\xc6\xd7\x1b\x5f\x5c\xdc\x30\x74\xed\x79\x2b\xbf\x0f\xf6\xeb\x72\x84\xd8\x2d\xf0\xee\x1e\x4d\x3d\x78\xcc\x6a\x80\xca\xa6\xda\xdd\x5a\xde\xc6\x21\x87\xe9\xd9\xb8\x01\xad\x89\x4f\xab\x2e\x59\xcb\x31\x2e\x0b\xcb\xc8\x9e\x1e\x3c\x94\xe1\x1c\x49\x8a\x5c\x00\x7a\xd5\x47\xfe\x77\x39\x13\xd4\x45\xfc\x59\x61\x37\x3b\x1d\x23\x7c\xb9\x8e\x0f\xd3\xf7\x4e\x07\xfd\x5e\xb7\x7f\x37\x2f\xd9\x5e\x83\xbb\x39\x8b\xa2\xa4\x47\x58\x2d\xe7\x36\xbe\xd9\xc6\x6a\x79\x19\x4b\x6e\x0f\xdc\x57\xb8\xa3\x04\x56\xd1\x17\xd6\x72\x31\x9f\x09\xa3\x08\xac\xde\x2a\x96\xad\x56\x1d\x7b\x56\x71\x13\xa7\x2a\xd0\x07\xd3\x2f\x9c\x20\xf6\x37\x67\xcc\x81\x32\x4a\xec\xb2\x8e\x4b\x7a\x76\x3c\x77\x97\xfe\xc2\xd2\x5b\x71\xf8\x11\x7c\x3a\x5e\xa5\xdf\xa5\xe7\xf5\xc7\xf5\xb5\xf8\xb0\xfc\x0b\x8f\x6c\x71\x31\x7b\xa7\x6d\xde\xf6\xed\xa3\xb1\xfb\xa4\x23\xf5\x0b\xf5\x87\xf5\x87\xf5\x4b\xf1\x4d\xbf\xfd\xc5\xda\xa1\x07\xc8\xbb\x35\x67\xff\x6e\xee\x4d\xdb\x76\xd4\x82\x2e\x41\xb9\x04\x22\x7e\x16\x91\x99\xcf\xa9\xe5\xe5\x48\xc2\x90\x99\xec\xb0\x06\x04\xc8\x70\xb3\x22\x19\x2a\xc2\x07\x34\x85\x4f\xa9\x52\x40\xcb\x49\xd0\xbc\x23\x85\x1c\x49\xc3\xf9\x47\x6a\x5d\x42\x94\x94\x38\xb8\x0a\xa8\x91\x00\x28\x71\x2c\xbc\x6a\x2a\xef\xc9\x96\xbc\x6b\xfd\x03\x7d\xcd\xe2\xf8\xe6\x4c\x9a\x83\xe0\x85\x97\x8d\x1b\x2c\xc3\x87\x78\xba\x79\x40\xe4\xe3\x8d\xcd\x73\xfe\xfb\x25\x7d\x35\x1e\xf7\xcf\xfb\x31\x7f\xeb\x4d\x9b\x7f\x77\xc3\x0d\x3b\x3e\xba\xe2\xe6\xbf\x7f\x86\x97\x2d\x42\xfb\xcf\xda\xa2\x0f\xe9\xef\xea\x5b\xf0\xc3\xf7\x0c\x49\xfc\x00\x0e\xfc\xe2\x8d\xa3\x4f\x7b\x7d\xc5\x69\xc7\x9e\xfd\xed\x2f\xcf\x5a\xf8\xc7\x74\xb7\x3e\x7c\xc2\xdf\x61\xaf\xfb\xdf\xd1\x83\xac\x0e\xd8\x9d\x33\x90\x35\x03\x66\x04\xbb\x8c\x03\x7a\xc7\x9c\x2e\x0d\x2b\x41\x00\x30\xf2\xfa\xc8\xc8\x17\xf4\x21\x79\xed\x0e\x73\xf0\x4b\x06\xdc\x0c\x91\x98\x50\x4f\x39\x98\x11\x1d\xf2\x82\xde\xa9\x96\xcc\x94\x9e\x49\xec\x51\x85\x8f\xf1\xe7\xba\x7f\x53\x6e\xce\x8c\xf7\xe5\xc9\x53\xf8\x8c\xae\xdf\x54\x28\x4c\x1c\x1c\x6a\x00\xd9\xbf\xac\x07\xb9\x94\x6d\x3b\xaa\x43\x0b\x11\x51\x16\xd1\x01\x9c\x10\x0c\xe1\xc0\xb7\x65\xd4\xa0\x40\x06\x6c\xb9\x9d\x8a\x3d\xad\x46\x7c\x84\x0d\x80\x83\xe2\x6e\xc8\x91\xcc\x71\x11\xe3\x23\x67\x58\xc5\x06\x58\x5a\x8c\x3c\xb5\x61\x20\x6d\x0c\xc2\x44\x86\x08\x93\xd9\x6e\xc3\xf8\xf4\xf4\x86\x61\x92\x39\xd1\x37\xd0\x67\xc5\x8b\x75\x38\x23\x27\xc8\xb2\x5f\x9e\x38\xf1\xaa\xc7\x1f\xff\xc5\x8b\xf7\x2c\x9d\x36\x6b\xea\x05\x1f\x7c\xf0\x9c\xb2\xf8\xb8\xf7\x03\x4f\xb0\xcb\x7e\x34\x6b\xd6\xaf\x72\x46\x24\x79\xd4\xae\xe1\xf9\xea\x8b\x51\xcb\xe7\x19\x16\xec\xa8\x15\x5d\x87\x72\xcd\xe6\x70\x1d\x89\xa7\x58\x2d\x5f\xdf\xd0\x6c\x04\x53\xf5\x2c\xb8\x0e\x76\x87\x95\xeb\xa7\xa3\x75\xb5\x38\xa9\xc6\x7d\x00\x96\x56\x0b\xd0\x9b\xb5\xf5\x0e\x92\xe2\xaf\x0d\x8b\x52\x8e\x0d\x36\xd3\x71\x13\xde\x46\x26\x91\x1a\xea\x45\x89\x8c\xd7\x05\xa1\xd2\x5e\xe2\x45\x98\xfe\x43\x99\x83\x54\x0d\x98\x18\xf0\x88\xcf\x3f\x95\x59\x77\x0f\xf1\x92\x16\x56\x43\xa4\x06\x38\xe2\xc0\xba\x0d\xe0\x29\x1d\xb1\x6b\x04\x2c\x31\xc9\x23\xda\x32\xb6\x21\x14\x42\x8d\xe8\x3b\x88\x24\xe6\x1c\x19\xc5\x4f\xdb\xfa\xe2\x29\x25\xb0\x33\x1f\x86\xaa\x45\x2e\x00\x93\xc5\x01\xc3\xbe\x84\xe1\xfd\xc8\x7b\x48\x39\xa3\x09\x27\xd5\x70\x00\xe0\x51\x8d\x47\xc2\x6f\x23\x8f\x84\x2b\x8b\x54\x14\x15\xa5\x41\x9b\x27\x50\x0f\xe6\x54\x34\x73\xe3\x38\x8e\x25\x62\x50\xfb\xc6\xf7\x0f\x04\x82\x99\xb4\x61\x51\xbd\x18\x4f\xdd\x13\xec\x77\x07\x26\x49\x98\xc7\x53\x0b\x5f\xde\xfe\x93\x1b\x6f\xbc\xff\xd8\x49\xb3\x8f\x3c\xaa\x25\xde\xd2\x68\x1b\x2a\xac\xea\x79\xba\xef\xd8\xc7\xda\x99\xab\xf7\x1d\xa5\xff\xfd\x67\x37\xac\x79\xf0\xd6\xf3\xde\xb9\x5e\x9f\x7c\xf1\x85\xdd\xb7\x4f\x3d\xf2\x7a\x84\x8d\xf8\x4b\x98\xc1\x07\x51\x93\x39\x27\x44\x06\x06\xfd\x4e\x2d\x17\xc4\x14\xf3\x00\xe2\x03\xe2\xbb\x36\x91\xf8\xa0\x89\xc6\x5b\x3e\x78\x0b\x03\x38\xa9\x86\x28\x69\x7b\x13\x0d\x15\x62\xa2\x2a\x38\xb2\x59\x35\xe0\x81\xee\x54\xa4\x06\xfd\xa2\x94\x17\xdc\x7c\x8c\xec\xac\x14\xb5\xb7\x0e\x5b\x95\x19\x7f\xbc\xb1\x75\x32\xa6\x03\xf7\x00\xda\xbb\xf8\xf7\xbf\x7c\xf5\xcc\x73\xce\x3d\x0b\xf7\xea\x4e\xfd\x5f\x1f\x6f\x58\x71\xa1\x09\xd8\xfb\x5f\xbf\xfd\xc7\xf7\xbf\xf7\xfd\x07\x98\xd3\x0b\xb7\xea\xec\x9f\x3f\xdf\xf1\xa5\xf2\x42\xe1\x4b\x43\x3f\x9f\xda\xbf\x9b\x6d\x01\xbf\x23\x45\x23\x5d\xde\x42\x68\xa2\xc0\x3b\x61\x9a\x4d\xe1\x5d\x10\xc1\x2a\xd8\x30\xbc\xc5\x2a\xd1\x80\xcc\x27\x1a\x9f\xc2\x47\x1c\x33\xe9\xb8\xef\x5c\xf0\x80\xfe\x43\xbc\x88\x9b\xb1\xef\xf5\x69\xc7\x35\xfd\x4f\x06\x61\x34\x80\x10\xb3\x0b\xec\xc9\xb1\xb4\x8b\xd5\x66\x44\x78\x08\xfb\x6d\xa4\x79\xcd\xf0\x24\x5d\x69\xb0\x29\x92\xe5\x49\xda\xd3\x83\x82\xe4\xf7\x26\x55\xc4\x15\x11\x41\x79\x67\x3a\x0d\xc6\x85\x78\x8d\x04\x22\xcf\xb8\x96\x61\x39\xde\x37\x20\x0e\xfc\x2a\xc7\xdc\x97\x7b\xee\xb9\x5c\xe1\xfc\x1c\x33\x57\xc7\xa7\xcf\x52\x94\x59\xfa\x7a\x5d\x5f\x6f\x7c\xc0\xa7\x13\x5b\xbe\x09\x21\x1b\x99\x7b\x9d\x42\x73\x47\x12\xc1\x78\x20\xf6\x1c\xf0\xfc\x48\xbf\x4d\x88\xe0\xa0\x45\x8c\xad\x7b\x8d\xf7\x9d\x75\x07\x8d\xcb\x86\x49\x52\xc6\x38\x94\xa9\x78\x0a\x43\x5d\x71\x81\x05\xbc\xaf\x4d\xb8\x7f\xd5\xfa\x79\xcb\x56\x1c\x39\xe7\xb0\xee\xf1\xa7\x1c\xfe\x35\xc3\x01\x2a\x9a\x6d\xa8\x30\xef\x97\xef\x7e\x6f\xf1\x84\x86\xaf\x02\x73\xf4\x67\x29\x24\x9a\x85\x39\xc6\x27\x50\xd8\x88\x82\x11\xad\x7e\xf9\x71\x49\x4e\x8b\xa0\xa1\x85\x7d\x86\x98\x00\x0d\x2d\x6c\x78\xcf\x1e\xc0\x0d\xf6\xc3\x47\x42\x01\x01\x89\x2e\xa9\x34\xd1\x25\x43\xa2\xab\x04\x22\x6d\x4d\x3e\x77\xf2\x8c\xec\x84\x73\x2a\xe1\xd1\xb8\x2d\x1b\xf2\x46\x4c\xa0\xaf\x2d\xc3\x46\x33\xd6\x17\x44\x88\x59\x0d\x18\x46\x47\x10\xaf\xd4\xcc\x7d\x09\x56\xee\xcb\x0d\x2d\x92\x4c\xda\x6a\xfa\x74\x3a\x47\x36\x47\x52\x67\x01\xdc\x7d\xda\x16\x19\x5c\x87\x7b\xd7\xaf\xd7\x5f\x67\x56\xec\x62\x36\x15\xa6\xed\x2a\xdc\xcc\xac\x80\x33\xb2\xef\xdf\xcd\xfd\x8d\x8f\xa3\x36\xf4\x02\xbd\x67\x75\x86\x62\x86\x59\x4d\x61\x53\x8a\x98\x1a\x74\x8b\x1e\x2f\x80\x38\x41\xcd\x9b\xdb\x09\xa9\xa7\x0e\x28\x2e\x29\xad\x35\x58\x65\xb9\xee\x6d\x48\xe5\xd8\xee\x6d\x58\x15\x25\xe3\xb3\x24\x76\x6f\x53\xfa\x6b\x9e\x95\xd6\xbc\xf8\x32\x54\xf5\x58\xff\x20\xc3\x4a\x81\x24\x81\xd6\x15\x03\xc9\x41\xbf\xf1\xa7\xf1\xf3\x80\xf1\xf3\x9c\x8d\x13\x4b\xea\x4c\xfe\x6c\x8e\x61\x25\xe3\x53\x20\x8b\x06\x19\x9b\x1f\x60\x74\xb1\xf5\x49\x39\xb4\x06\x23\xd5\x5e\x27\x4a\xaa\x33\x91\xcd\xaa\x1e\x51\x24\x21\x5b\x06\xb7\x09\x6d\x03\x86\x6f\x22\xf4\x19\xf7\x37\x3c\x10\x16\xb0\xe1\xe6\xd1\xfe\xc9\x36\xa6\xb5\x2d\xc1\x0b\xac\x1d\xbf\x1d\x7a\x2d\xf3\x44\xc3\xb4\x54\x7a\xfc\x09\xa7\xde\x98\x9f\xfa\xeb\xcc\x13\x58\x6e\x99\x31\x10\x6f\x0e\x5f\xdc\x76\xe1\x6d\x1d\x17\x27\x3d\x7c\x77\xfd\xef\xb8\x78\x76\xf2\xe3\x99\xa8\xdf\x33\x2c\xce\xbf\x60\xe2\x13\x99\x02\xbf\x60\xbe\x73\xb7\x5b\x5a\xb2\x02\x7f\xeb\x86\xf1\xf7\xcf\xd0\x63\x44\xcf\x9f\xda\xbf\x5b\x58\x6d\x1b\x22\x75\x11\x60\xe1\xab\x37\x0e\x2f\x9a\x31\x9c\x2d\xc5\x93\x26\xc9\x2c\x07\x54\x58\x4b\x3b\x9f\x80\x3d\x91\xb2\x8a\x1a\x31\x5b\x40\x26\x65\x11\x3b\x2b\x02\xd1\x97\x4b\xa4\xac\x2c\x14\xbb\x41\x09\x65\x91\x6a\x0b\x8a\xd2\xa0\x4c\x00\x76\xa8\x61\x30\x2b\xe9\xe5\x55\x64\x70\xdc\x5b\x9f\xc2\x7d\x83\x57\x2e\xc3\x7d\xb9\x95\xcb\xf1\x80\x96\x0c\xa4\xf3\x17\xef\x5e\xe4\x5d\xf6\xc9\xf6\xb7\xf0\xed\x5c\xc7\x70\xea\x9f\x8f\x6f\x60\x2f\x1e\x4e\xfd\xf3\xe7\xdb\xd9\x99\x7b\xa7\x3f\x78\xca\xb7\x37\x6d\xfa\x03\xf5\x4d\x28\x3e\xcb\x12\x3a\xbd\x08\x50\x8f\x6e\x40\xe2\x64\x28\x38\x8b\x6d\xa7\x1a\x14\x01\x3b\xc7\x08\xee\x3c\x22\x58\x5d\x47\x04\xaa\x3d\x86\x1d\x0e\xda\x44\x02\xb0\x61\x6c\x45\xf0\x11\x37\xcb\x9e\x45\x2a\x13\x36\xa1\x5e\x0d\xb7\x80\x97\x72\x76\x3f\xe1\x7b\x35\x7d\x97\x32\x70\xa0\xa2\x07\x53\x0e\x0b\x94\x7f\x7c\x3a\xf5\x63\xca\x01\x81\x86\x5f\xfb\xc5\xb3\x0d\x25\x18\x2d\x41\xc3\xbf\xaa\x98\x32\xf6\x3b\x34\xc5\x9d\x32\x53\x8a\x15\x08\x40\xa1\x32\x24\x26\x45\x38\x08\xb4\x9f\x0a\x78\x1f\x0a\x7a\xb3\x6f\x22\x77\xb9\x09\x7a\x43\xb1\x3f\x6c\xaf\x21\x17\x92\x50\x04\x9d\x52\x89\xf0\x10\x66\xb5\x7c\xc0\xed\x30\x7c\x94\x00\x6b\x75\xf8\xb9\xc3\x86\x8f\x65\x42\x83\x06\xd3\x00\xf9\x50\x83\x93\xaa\x04\x73\xd0\x0e\x00\x79\x30\x3e\xf2\xa8\x12\xe4\xa1\x85\xcc\xb0\x03\xb1\x54\xe3\x48\x50\x87\x6f\x05\x9f\x7e\xe2\x91\x5f\x05\x0a\xb5\xcc\x5f\xa3\x4f\x3f\xa4\xbf\x54\x09\xe5\xb0\x2f\xbf\x6d\xf3\xaf\x30\xf3\xb3\x41\xca\x23\xc3\xff\x91\x0f\xa2\x00\xaa\x43\x67\xd2\x6c\x75\xd8\x5c\x79\x8c\xd5\x14\x21\x65\xc1\x5a\x85\x41\x98\x00\x26\x19\x26\xc8\x2b\xd1\xa0\xb1\x56\x11\xd2\xec\x39\x1b\xc1\x37\x04\xda\xdf\x9c\x1b\x79\x29\x21\xbc\x8d\x12\xc2\xd3\x3d\x84\xfb\xfb\xe2\x61\x2f\x16\x42\x72\x05\x60\xc5\x0a\xbc\x08\xcf\xc2\xa7\xe7\xce\xc0\x5d\xde\xe6\x3b\x56\x4e\x1e\x09\x52\x41\xa0\x09\xb6\x4f\x7e\x2b\xa4\x6e\x4b\xff\x64\x67\x05\x30\x85\x35\xcb\x67\x7b\xcd\xc6\xa3\x10\x6a\x42\xb3\x51\x2e\x00\xde\xa2\x99\x5d\x6a\x74\x5a\x49\x31\x9a\x56\x82\x4c\x85\x4c\x5c\x89\xba\xb0\xb1\x99\x00\xd0\x25\xe5\x78\x3b\x60\x27\xaa\x8d\x35\x30\x91\x8c\xe8\x66\xf8\x12\x40\x01\x63\x1f\x0c\xd9\x47\x05\x8c\x00\x40\x4e\x2c\x7d\xf5\xe8\xbb\x71\x97\x2f\x76\xea\x1d\x0b\xc7\x53\xec\x89\x22\x6e\x00\x81\x9a\x38\xf2\xc8\xae\xcf\x43\x37\x3e\xb4\xb8\xe6\xaa\xfb\x29\xe2\x84\x52\x04\x0f\x81\xb3\xb1\xcf\xb3\xbd\x06\xb8\xb3\x4b\x29\x63\x2b\x78\x4b\xf5\xf4\x80\x8c\x47\xa4\x89\x35\x3c\x5b\x13\x4d\x22\x16\x06\x48\xa8\x46\x9c\x54\xe5\x30\xa4\x11\xdc\xc4\x16\x01\x94\x44\x63\xcc\xd8\x21\xe0\xcc\x8a\xaa\xcd\xd8\xa9\x9b\xe4\x90\x90\xda\x04\x3e\xaf\x9c\x2d\x4e\x80\x91\xc3\x2a\xbd\x0d\x95\x67\xd6\xb8\x02\x9f\x81\x8f\xc1\x13\x9f\x7a\xac\xf0\xe6\xfb\xfa\xf6\x25\xe7\x1f\x73\x41\xd7\xb1\xfa\xa3\xfa\x26\xfd\x69\xfd\x51\x7c\x64\xee\x49\x3c\x4f\x5f\xa7\xff\x84\x1c\xdb\x33\xcf\x7c\xf3\x8f\xe1\x20\xbb\xe3\x8a\xef\x75\xf6\x3c\xbe\x5b\xff\x91\x7e\x25\xbe\x1e\x5f\xf0\xaf\xaf\x8d\xb3\x23\x33\x72\xfc\x5b\xdc\x72\x14\x45\x2d\xc6\x5e\xc3\x10\x21\x9a\x28\x12\x42\x46\x4d\x38\x8d\x6d\xc2\xd5\x26\xf1\x61\x8d\xac\x29\x35\x64\xa7\x41\xb9\xec\x96\xb7\x19\x3b\xad\x11\x25\x35\xcc\x82\x0b\xaf\x1a\x6e\x7d\x71\xa7\x89\x3a\x51\xca\x49\x41\x94\x2d\xdb\x6b\x26\x5d\xb6\x57\xd8\x6a\xa2\x09\x95\x43\x04\xc9\xff\xfa\xe2\xb6\x6b\xde\x27\xb6\xe0\xe2\x49\x5d\xfa\x47\xff\xfa\x5c\xff\x08\x0f\x9c\x73\xd1\x85\x67\x9f\x73\xd1\x05\xe7\x30\xbd\x38\x80\x53\x6b\xd6\x98\xf6\x61\xda\x77\x7f\xa0\x7f\xa2\xff\x0e\xf7\x61\xff\x63\x3f\xb3\x30\x61\x20\xc7\x66\x5b\x07\x3e\x7d\x03\x9a\x4f\x3b\xd1\xe0\xbe\xf9\xdc\x9a\x52\x9f\xce\xbb\xc2\x1e\x60\x74\x70\x5b\x15\x08\x29\x02\xa0\x47\x1e\xda\x38\x1b\x06\xbb\x11\xa3\x59\xfc\xb8\x99\x31\x97\x21\x54\x0c\x66\x91\xea\x0b\x43\xb6\x2d\x58\x5e\x02\xe2\xe2\x30\x49\x51\x56\xfd\x21\x55\x1f\x06\x61\x27\x96\xf5\xb7\xf5\xcf\x6f\xd4\xb7\x9b\x29\xb7\xf3\x6f\x5f\xfd\xdd\xab\xef\xe0\x4e\x7f\x6c\xe3\xae\xf7\x77\xef\x2d\xec\xa1\x09\x37\xfd\xd3\xa5\x17\x5c\xb0\x00\xf0\x1e\xf4\x20\x97\xe7\x1b\x00\x07\xe4\x32\x52\xe7\x03\xe4\x8f\x00\xb0\xb6\x91\x12\x9f\xe9\x81\x91\x0e\xa4\x06\x9f\x96\x73\xd7\x36\xa6\xd3\x69\xda\x2d\x6a\x78\x88\x00\xf8\xd1\x60\x78\x87\x3e\x3f\xa0\x2b\xb4\x88\x83\x1c\x1f\x20\x98\xdb\x50\xc8\x33\x5e\x4b\xa0\xce\xa1\xb8\xe2\x82\x11\xd9\x73\x66\xd3\x99\xe5\xa7\xf1\x82\x5c\xac\x0a\x40\x91\xa5\x01\x47\xe1\x04\xa9\xfe\xae\x19\x1c\x34\x7c\xb7\x9e\x5e\xd6\xed\x4e\xaf\x5d\xb8\xf5\xaf\x7f\x79\xe5\xad\x05\x5e\x41\x58\x7c\xc9\x6b\xe7\x2e\x59\xb6\x80\xd1\x83\xfc\x13\x3f\x1f\x6a\xd0\x82\x7d\x53\xbc\xdf\xbe\xee\xc4\x53\xf4\xed\xfa\xff\x18\x17\xf3\xe6\x29\xf3\xf4\x89\x5c\x43\xfe\x41\x3c\xeb\xd1\x47\x6f\x5d\x03\xf5\xad\xfd\x19\xc0\x95\xf0\xa1\x08\xc4\x65\xe6\x14\x4c\xde\xeb\x07\x9c\x4f\xaf\x4b\xcb\xb3\x11\x42\x92\xe2\xb2\x8c\xbe\x4f\xd6\x54\xc6\x9f\x4e\x2b\x3e\xc0\x3d\x83\xe3\x33\x6c\x7e\x90\x22\x8b\x0b\xa2\xea\x74\x83\x53\xea\x85\xaa\x8c\x12\x11\xa1\x24\x93\x11\xe3\x72\xa6\x1a\xb2\xc4\x26\xdc\x7f\x09\xee\xc4\xf5\x37\xdf\x54\x86\x28\x61\x1b\x7a\xed\xed\x77\xbf\xf7\xca\x94\xc2\x2a\xa6\x57\x7f\x90\x39\x6b\xfe\xc2\x05\xa7\x11\x9f\x66\xf6\xfe\xdd\x9c\xdf\xb6\x1d\x35\x1b\xb7\xac\xc9\xc4\xa8\xf2\x9b\xac\xe2\x9e\x26\x7f\x91\x65\xbf\xc6\x07\x57\x4c\x30\x5c\x18\x1f\x6d\x0a\x34\xfd\x66\x45\x10\x37\xb2\x4e\x7f\xa8\xae\x09\x68\xd5\xe8\x58\x86\xd5\x1d\xe8\x11\x07\x91\x10\x68\x68\x0e\x67\x55\xbf\x53\x24\x29\x81\xc0\xf8\xfe\x81\x29\x0c\xb9\x4b\x42\x1b\x6d\xf1\x10\xbc\x66\xe8\xcc\xc7\x9b\x9a\x67\xaf\xff\xf5\x2d\x17\xa6\xce\xfc\xf6\x49\xeb\xcf\x9d\xfb\xfe\x67\xff\xfd\xaf\x47\xb6\x5f\xb5\xa8\x7f\xf1\xa2\xdf\xbe\xf7\x9c\x3e\xfc\xb9\xae\xe3\x5b\x7f\xbc\x73\x56\xf6\x5b\x47\xf7\x7c\xeb\x98\xae\x8e\x2f\xce\xdf\xf1\xc2\x7d\x6f\x9c\x94\x39\x62\x7a\xea\xd8\x93\xe7\xe9\xfa\xdc\x1d\xc6\xfe\x8e\xdf\xbf\x9b\x35\x7c\x83\x26\xb4\xc0\xac\x8f\x08\x1a\xa0\xf1\x93\x09\x48\x5a\x12\x09\x00\xf4\x1c\x4f\x3b\xe1\x9a\x4d\xdc\x39\xa0\xa9\xe1\xc5\x8d\xac\xc3\x27\xc7\x1a\xc9\xe8\xa3\x5a\x57\x0f\xaf\x5a\x23\x71\xde\x1c\xe2\x20\x72\x4b\x80\x98\xe9\x93\x28\x36\x77\xff\x80\x99\x66\x2c\xdf\x97\xd9\xe5\x77\xfc\x1d\x3f\x7f\x70\xf6\x71\x47\x1e\x7b\xe7\xac\x59\x2f\xfc\xe5\xa5\x3f\xdf\x94\xfb\xce\xf9\xe3\xf2\xbf\xfc\xd9\xda\xff\xfe\x60\x17\x1e\xb8\xfa\xe7\x87\x4d\x3c\xa4\xb5\x23\xd9\xdd\xfc\xa7\x39\x6b\x7e\x78\xcd\xc3\x47\xb6\xf6\x77\x37\x9f\x37\xe7\x1f\x27\xfc\x0c\xf6\x63\xcd\x5a\xf5\xd3\x4a\x9a\x87\xd5\x20\xfe\x53\x05\x37\xd0\x3f\xc0\xb0\x94\xea\xf1\x41\xb7\x80\xa1\x41\x8c\x13\x30\x33\xc0\x87\xe8\xe9\xcd\xf4\x39\x70\x5f\x5c\x8e\x37\xb5\x39\x70\x7f\x26\x2e\x1e\x8f\xff\xa8\xf7\xb1\xef\xeb\xd3\x33\x0a\xde\xaa\x27\x3e\xef\xc2\xaf\x7f\xc5\x38\xf1\xf6\x4f\x74\x97\x3e\xb9\xf0\x95\x7b\x3f\xe1\x34\xb8\x49\x0f\xb2\x73\xf8\x0e\x24\xa3\x46\x74\x16\xa2\x35\x19\x25\x90\xca\x47\x49\x3b\x74\x7d\x4a\x65\x69\x02\x02\xed\xa4\x60\x5c\x4a\x88\x64\xd2\x6b\xd2\x2a\xef\x23\x2e\xaf\x18\x12\x09\x30\xa7\xc3\x4b\x2a\x78\x01\x51\xe5\x5d\xd9\xac\x12\x95\x0c\xc7\xa0\x9e\x64\xb6\xd8\xf1\xfd\x99\x46\x72\x53\xcd\x21\x35\xd2\xd8\x3c\x91\x8a\xf5\xf2\x47\xbf\x8f\xe7\x4d\x9f\x34\x73\xe9\x05\xf7\xfd\x2a\x3f\x70\xdb\x8f\x37\x65\x27\xf4\xf6\xb4\x37\xb5\xdb\xb2\x17\xac\xd2\x7f\xb8\xf7\xb5\xc3\xa6\x24\xde\x1f\xff\xcc\xb3\xdc\xd0\xaa\x15\xad\xfd\x87\x8e\x4f\x27\xc9\x3c\x18\x9d\x93\x6c\x44\xab\xd0\x58\x63\x60\x8a\x94\x52\xc3\x02\xd9\x4c\x83\x35\x77\xd7\x00\x71\x57\x03\x1d\x8b\x04\xe0\xd1\x08\xd9\x94\xa3\x41\x94\x72\x4c\x30\x9c\x05\xce\x66\x45\x32\x34\x21\x27\xb8\x79\x70\x18\xc2\x12\xc1\x22\xb2\x8b\x39\xb7\x57\x26\xf0\x25\xd5\x86\xf1\x4a\xd0\x0a\x27\x63\xd8\x72\xe9\x38\xde\x5d\xab\x67\x1f\x97\xca\x4c\xe8\xae\x79\xfa\xb1\xd2\x61\x3c\xfd\x3c\x65\x5d\xec\x2d\x29\x3b\xf9\xfa\x67\x9e\x61\x62\xc6\x1e\x9d\x08\x71\x86\x3f\x2f\xa2\x59\xa4\x5e\x49\x5e\x12\x27\x6b\x84\x96\x94\x6b\x82\xcc\xac\x92\xb0\x44\x90\xb5\x9c\x00\xdb\x17\x6c\x0e\xc2\x32\xe1\x41\x04\x9e\xd0\x2e\x02\xb3\xab\xd3\x6e\x78\x02\x3e\xeb\xe5\x80\x9c\x96\xf9\x68\x38\xb7\x6c\x62\x8f\xd0\x2f\xd6\xb7\xdf\x0c\x8f\x04\xd4\x63\x60\xf2\xf1\x5b\xa9\xce\xbe\x3e\x73\x06\x0f\xde\x84\x0b\x49\x57\xa3\x1a\x72\xd0\xfb\x27\x81\xf0\x01\x95\xd8\x41\x5e\xb6\x7a\x08\x79\x03\x84\xb0\x3c\x00\xa3\x24\x01\x11\xa8\x67\x73\xf5\x01\xe3\xdf\xea\x8d\xa8\x37\x6e\xe8\xb7\x49\x22\x21\x89\x4a\x04\x6e\x1e\x03\xa5\x25\x87\x11\x65\x90\x54\x8a\x99\x6a\x84\x97\xa0\x0e\x57\x4e\x3d\xa6\xee\xdc\xbc\xe5\xdc\x53\x8f\x3d\x61\x4a\x7f\xe9\xc8\x23\x7b\xf9\xb5\x73\x96\x6c\xd8\x18\xff\x28\x7c\x48\xf6\xf4\xd2\x81\x47\x98\x73\xa4\xf3\xc3\x22\x9a\x8e\xca\x66\x86\xcd\x34\xa3\x94\x52\xfc\x74\xa6\xd4\x6f\xcd\x94\xfa\x21\x97\xeb\x47\x44\xba\x48\xb5\x7b\x49\x71\x18\x89\x8a\xd3\x1a\x05\xb6\xa6\xff\x1a\xa3\x64\xa8\x74\x52\xcf\x94\x4c\xf4\xcc\xf1\xfa\x7d\x64\xb2\x71\xef\xeb\x53\x27\xc9\x1f\xb9\x82\x78\xa1\x6d\xc0\x8a\x45\x3b\x80\x4b\xe9\x38\x94\xab\xa9\x9c\xd3\xf0\xa5\x4c\x44\xca\x92\x76\xfc\x90\x0c\xe9\x8e\x7a\x43\x63\x59\x18\x48\xa6\xc8\xd9\x6e\x99\x94\x7d\xc5\x8a\x3e\x65\x79\x0a\x26\x3e\x2d\x6d\xde\x7e\x0a\xf7\xdd\x7e\xef\xbd\x37\xe3\xbe\xe9\x47\xe1\x2e\x6f\xe3\xe2\xa1\x5b\xcc\x9e\x6d\x68\xd2\x5e\xf8\xe0\x8f\xee\xbb\x97\xbd\xfb\xb9\x9a\x7b\x16\x85\xee\x7f\xec\xfc\x60\xe1\x45\xe8\xd6\x26\xef\xcc\xfd\xfb\x77\xf3\xcb\x6d\x3c\xaa\x47\xa7\x12\x6f\x2e\x57\x3b\xa2\xd7\xbe\xa1\xb2\x23\x5b\x26\x09\x9a\x46\x73\xc5\xb5\xc0\x10\x17\xcd\x22\x95\x37\x7c\xf3\x48\x14\x52\x47\xb0\xfe\xd1\x56\x6e\xb6\x5a\x5b\x8d\xd5\x47\x1f\x8f\xbb\x7c\x8d\x4b\x9e\xbe\xe3\xa3\x0e\xa9\x67\x70\xf9\xcb\xaf\x96\xb6\x54\x5f\x1a\xfa\xd1\x25\xa1\x07\x1f\x3f\x4f\x1e\x7e\x7d\xf5\x71\xb3\x77\x20\x8c\x06\xa0\xc6\x32\x84\xe2\xe8\x6a\x2a\x67\x93\x48\x59\xf1\x67\xe0\xfc\xa5\x34\x14\xea\xea\x77\xaa\x7c\x48\xcb\xf1\xa0\xb5\xbc\x71\xf0\xf5\xbc\xa9\xb2\x0a\x4f\xbc\xd1\x50\x48\xcb\x85\x00\x0c\x3b\x24\x39\x92\x39\x77\x08\x3a\x5b\x7c\xb4\x78\xe7\x36\xce\xa2\x26\x9e\x05\xf4\xa8\x40\x16\xa9\x08\xe0\x9a\x7c\xa1\x7a\x2b\x05\xc0\x93\xc7\x11\xca\x59\x86\xde\x84\x24\x39\xc8\x70\x89\xa6\x66\xa6\x6f\xbc\x34\x30\xc0\xac\xfa\xfe\x8d\x5b\x86\xf2\x2f\x5f\x7b\x0b\x73\xb5\x7e\xc7\x3d\x8f\x3d\xa1\x6f\x79\x73\x87\xfe\xf2\x13\xeb\x1f\xe0\x72\x98\xd3\x3f\x3a\x5a\x2f\x6c\xdb\xfa\xf6\x7f\x6d\xdb\x36\x3c\x03\x87\xf4\xe1\xb9\xfa\xaf\xb7\x3e\xad\x7f\x74\xf7\xdd\x38\xbc\x69\x2b\x9e\x32\xcf\x38\x27\x84\x10\xb7\xc7\xb6\x1d\xc5\xd0\x04\x72\x5f\x21\xc5\x9c\x0b\x32\x24\x82\x85\x3a\x92\x7b\xa7\x1a\x0e\x68\xa4\x72\xe4\x8b\x89\x52\xce\x26\x82\xed\x43\x86\xed\xeb\xe9\x15\xe3\x98\x36\x54\xd3\x57\x90\x64\x69\xe4\xa0\xe1\xab\x64\x71\x9b\x77\xc0\xc1\x4f\x15\x57\x27\xe5\xfe\xd6\xfe\xa6\x69\xf3\xef\x7c\x68\x86\xfe\xa0\xfe\xa2\x6d\x68\xf8\xfe\xb6\xbf\x1d\x32\xfe\xcf\xad\x78\xce\xb9\x33\xea\x7b\xba\x03\x9f\x27\x1e\xba\x65\xc5\xb6\xe1\x07\x91\xb9\x2e\xdd\xb6\x1d\x05\xd0\xa1\x34\xf2\xb1\x33\xa6\x71\x03\xbe\xc1\x20\xac\xcb\x88\x6c\x00\x7d\xd5\x0d\xcd\x2b\x08\xa2\xe7\x1c\x72\x0a\x59\x42\x22\x68\x18\x5e\x91\x24\x8d\x02\xb4\xd1\xb4\x9b\x49\x34\xcd\x38\xf9\xfc\xdb\x0e\x55\x70\x17\xe9\x2b\xfd\x5b\xc7\xf8\xde\xce\x76\x6e\xd3\xe7\x89\xc5\x37\xeb\x37\x33\xb3\xa1\x9d\xb4\x0b\xbf\x7d\xca\xf1\x4d\xb0\x96\xa0\x1e\xe4\xfe\xc6\x2d\x47\x8d\x80\x6a\x86\x51\x32\xe7\x32\xec\x99\x48\x30\x3d\xeb\x9c\xf0\x72\x18\x2f\x03\x82\x18\xd2\x30\x53\xa2\xb8\xd1\xc6\xf9\x64\x42\xef\x8e\xa8\xff\x63\xb6\xf6\x16\x8b\x07\xbc\x80\x99\x78\x13\x01\x48\x98\x8a\x83\x78\x86\xd2\x1d\xe4\x9b\x9b\x2e\xec\xbd\x67\xd1\xb8\x79\x35\xad\x0d\xfd\xc7\xb6\xe9\x6f\x5f\xaf\x3f\x7a\xe4\x09\xee\x69\xf1\x27\xbe\x25\x73\xf3\x0a\x7b\xae\xbd\xfa\xee\x33\x71\xea\x86\x4b\x03\xee\xdd\xae\x33\x2e\x1c\xde\xa1\xdf\x27\x7e\xc9\x3a\xb7\x4c\x24\xf7\x0e\xfa\x1c\xc1\x66\x99\xc8\xfa\x3e\x56\x03\xd9\xa9\x02\xab\xe5\x59\x0e\xd9\x3d\x49\xc5\x95\x51\x59\xb7\xa6\x78\xe0\x85\x20\x66\xca\x47\xdb\x0d\x81\x61\xc8\x49\xda\x0d\x13\x7d\xf1\x00\xb4\x3e\x66\xe4\x38\x1b\x17\x7b\xb1\xfc\x0a\x5e\xb1\xa7\x30\x9b\xab\xd1\xff\xf6\xbc\xbe\xfa\x63\xe6\xf5\x6d\xf8\x56\x1d\x9f\x83\xd1\xab\xfa\x39\xba\xbe\x61\x3f\x59\x03\xf4\x7d\x72\xf3\x4a\xd7\x60\xd7\x20\xb3\xaf\x0a\x76\x2d\xcf\xb1\xb0\x06\x4f\x46\xe5\xe8\xd0\xf5\x18\x6b\x08\x24\xfa\xe2\x03\xf1\xbe\xb8\x2c\x64\xe4\xb8\x10\x97\x07\xfe\xf8\x53\x9c\x79\x48\x8f\xb2\x87\x3f\xf3\xa0\xbe\xe3\x29\xc6\x99\xc7\x89\x57\xfe\xa8\x6d\xdd\xfb\xca\xa7\x9a\xf1\xdd\xd9\xfd\xbb\xb9\x45\x90\xdf\x3a\x9a\x32\x56\x72\x4e\x2d\xe7\xb3\xf2\xd2\x35\xd0\xc3\x2c\x53\x02\x19\x59\x10\x4d\xa4\x58\x2e\x42\x00\x3f\xbc\x62\x0e\x4b\xf0\x6e\xfb\x08\xdf\x9f\x85\xf6\xd1\x9a\xc4\xb4\x13\x34\x44\x9a\xa3\xb2\x67\x7c\xbc\xe0\xb1\x47\xdf\x78\x7d\x25\x5e\x50\xf8\x90\x7d\x5e\x9f\xf9\x05\x46\xfa\x2f\xf5\x3f\xea\x85\x89\x58\x18\xd7\xb7\xf0\xe2\xf3\xce\x7c\x1b\xcf\xc5\x68\xab\x7e\x8e\xf3\x4f\x2f\xbd\xf1\xa9\xb1\xbe\x99\xfb\x77\x73\xd7\xc2\xfa\x66\xd1\x28\x57\x74\x52\x7f\xce\x5e\x24\x53\xf4\xca\x5a\xce\x0b\xed\x66\x5e\xa7\x83\x70\x59\x95\xf0\x77\x88\x61\x12\xec\xd9\xc5\x1c\x02\x5c\x48\xc3\xc5\xe0\xa8\x27\x8a\xfb\xe2\x62\x9c\x16\x36\x09\xfa\x23\x1f\x6f\x6c\x9e\x39\xfc\xb5\x7e\x02\xfb\x7c\x61\x17\x5e\xbc\xf2\x8d\x37\x1e\x7d\x6c\x89\xf6\xed\xcd\xfa\xff\xe8\x7f\xd5\x9f\xc3\x6b\x5e\xfe\x53\x00\x3f\xb8\x75\x3f\xd2\xd7\xbd\xfd\x9d\x05\x17\x2c\xea\x4f\xea\xdf\x9c\xf0\x01\xac\x55\x0f\x72\x73\xb8\x79\x28\x8a\x66\x9a\xfe\x93\x9d\xc0\xd8\x3a\xff\xb7\x2b\xcd\x8c\x97\x06\xc0\x2d\xad\x5c\x29\x9a\xf9\xcd\xa7\xfa\x4c\xf6\x95\x42\x0e\xdf\xba\xe2\x95\x57\xd7\xfe\xf8\x9c\x77\xbe\xfd\xf2\x7e\xa4\x7f\xaa\xbf\xbe\x13\x33\x4d\xf8\xe1\xad\x9a\x7e\xed\xdb\xd7\xdd\x7c\xf5\xcd\x99\x2e\x5d\x3f\x19\xdb\x10\x46\xf3\xf5\x20\xd7\xc5\xcd\x43\x09\xb4\x1c\xe5\x3c\x80\x35\x68\xd7\x8c\x2b\x19\x13\x2c\x98\xcd\x68\x04\x3c\x7e\x1b\x49\xc7\xe6\x6c\xe0\x5e\xd8\x1c\x14\x63\xb3\xe8\xfc\xdb\xc4\x8d\x8c\xcb\x1f\x8a\xc5\x49\x58\x33\xe8\xf5\xd5\xd5\x43\x20\x1a\x8b\x13\xff\xdf\x2d\xe6\x90\xbf\x2e\x4b\x2a\x68\xbe\x6c\x4f\x6f\xd8\xdf\x02\x76\x0f\xb4\xa3\x2f\x2e\x63\x68\xb3\xb4\x79\x31\xf1\xff\xe1\x35\x9a\x8f\x6f\xbb\x6f\xd9\x75\x4f\xde\x86\xc7\xeb\x3c\x7b\xab\x7e\xcf\xab\xaf\xe9\xff\xd4\x3f\x9a\x73\xfc\x6b\xcf\x7d\x70\xda\xa7\xd7\xbc\xf4\xf7\x0d\xb8\xbb\xde\x35\xe1\xf0\xa9\xe3\x7f\x8b\x45\xed\x25\xfd\x6d\xff\x2f\xee\xce\xe7\x64\xa1\x3d\x31\x77\xe6\x7b\xcd\xe3\xd6\x93\x3b\xc5\xf5\x81\x5f\xb5\x8c\xde\xa9\x3a\x3b\xa4\xf2\x6b\xc8\x35\x8a\x80\x63\x15\xa0\x8e\x95\x7d\xa7\x1a\xf2\x69\xb9\x10\x38\x7a\xa1\x06\x47\x52\x89\xa6\x73\x76\x78\x7e\xec\x00\x5a\x60\x67\x89\x63\xa5\x86\x0c\x6f\x2f\x02\x3c\x5d\x75\xf4\xf6\xb9\x38\x51\x52\xbd\x21\x60\x2d\x85\x1d\x92\xc6\xe3\x62\x88\x33\x85\xc9\xa4\x39\x23\xd4\x36\x8e\x2f\x2e\x0f\xe0\xdb\xf4\x1f\x33\xde\xbe\xf6\x45\xa7\x1e\x77\xcb\x9c\x7b\xe6\xdd\xb0\xe6\xec\xdf\x63\x3c\xf3\x76\xfd\x03\xfd\x06\xe6\xc7\xef\x63\xe5\x95\xc3\x6e\x98\x7e\xea\xa2\xc3\x67\xff\x72\xf6\xb1\x3d\x1f\x3d\xfb\xd0\xf5\xaf\xe8\xe7\xfa\x34\x7a\x57\x67\xda\x86\x50\x8d\xb1\x27\x72\x57\x5d\x5a\xce\x63\xdc\x05\x37\xab\x29\xbe\x74\x5e\x74\x44\x3c\x1e\xb0\xb4\x00\xd0\xe2\xdc\xa9\x8a\x3e\x2d\x27\x42\x71\x44\xf4\x39\x92\x39\x27\x90\x5a\x3a\xdd\x40\xad\x46\x19\xd4\xe0\x76\xd7\x1a\xc1\x87\xd3\x50\xc4\x48\xe9\xed\x76\x88\x2a\x06\xef\xc1\xba\xd5\x1d\x58\x24\xf4\x96\xb0\x27\x2e\xde\xd4\x9a\x9d\xf1\xc1\x39\x8f\x3e\xa6\xef\xd0\xf7\xfd\x94\xfd\x4b\xe1\xab\x01\x0d\x87\xf5\x4d\xfa\xeb\xdf\xfd\xf3\x44\xec\x6a\x1f\xb8\x78\xc9\x5f\x18\x3f\x80\x4f\x7c\xb9\xe7\xad\x2f\x86\xdb\x49\xcc\xc9\x25\xe0\x9e\x2c\xa3\x77\x9a\xb3\x6b\x39\x37\x26\x24\xf6\x8a\x37\x9d\xf7\xdb\xc3\x6e\x4f\x52\xf5\x53\xf8\x6d\xe7\x4e\xd5\x2f\x69\x39\xbf\xd3\xa4\xaf\xcb\x39\xc1\x7f\x74\xba\xc8\x3e\xfc\x24\x34\x0d\x06\x28\x4c\x26\xec\x03\x68\xae\xb8\x30\xd9\x87\x5d\x54\x71\x10\xf6\x61\xbc\x1d\x8d\x7d\xe3\xe3\x09\x31\x01\x0d\xce\xf0\xf2\x1a\xdb\x38\xfe\xe8\xf7\x4e\xc7\x1d\xfa\xeb\x5b\x36\xb0\x6b\xf5\x8e\x86\x4f\xbe\xd4\x77\xea\x1f\x7c\xf7\xbf\x7a\x87\x9b\xd3\x37\x5c\x8b\x1f\xdc\xb5\xeb\x95\x27\x1f\x1d\xfa\x75\x2b\xc2\x68\xfa\xfe\xdd\xec\x06\xdb\x0c\xd4\x6c\xf8\x3c\x90\x13\xe0\x04\x52\x8e\x35\xc2\x22\xc3\x37\x17\x01\x96\xa4\x25\xa5\x78\x76\xaa\x11\x89\x34\x07\x78\xac\xe6\x00\x0f\x34\x07\x78\x7c\x64\xf1\x11\x72\x08\x0d\x01\x92\x31\x88\x78\x44\x69\xd0\xc9\x89\x4d\xcd\xe1\xac\xda\x20\x00\x52\x33\x52\xb9\x26\xb2\x8f\xb0\xa8\xe2\x06\xe8\x58\x56\xfc\xe6\x6e\xcc\xee\x9d\xc9\x38\x61\x21\x66\x04\x43\x0d\x98\xe2\xc5\xb4\x4e\x9f\xb1\xfd\xa4\x0b\xbf\x33\x2e\xf3\xe4\xe2\x17\xb7\xce\xd9\x82\x63\xfa\xae\xd6\xfe\x0b\xce\x3c\xed\xeb\x0f\x2f\xde\xd1\x3b\xdc\x91\x1d\x18\x68\xca\xc4\x4e\x7b\xe4\xba\x59\x10\x36\x4d\x9b\x30\xa1\x61\x6a\xff\xad\x67\xad\xcb\xb5\x22\x2b\x67\xc5\x2d\x47\x5e\x14\x31\x3c\x53\x28\x1c\xf0\xd0\x79\x48\xf2\x55\x9e\x14\x71\x7b\xa2\x16\x7f\x92\x2f\xad\x78\x49\x63\xb6\x93\x66\x6b\xbc\xb4\x84\x20\x11\xf6\x62\x98\x70\x71\x82\x67\x4a\x0a\x09\x00\xaa\xd9\x9f\x49\xd7\x63\xd9\x8f\x6c\x51\x6c\xde\x1c\x79\xcd\x9e\xa4\x77\xf1\xef\x57\xbe\xb8\x50\xbf\x4a\x5f\xb3\x45\xbb\x68\xfe\x65\x67\xeb\x41\x7e\xfa\x0f\xd7\x5f\xf3\xf1\x7d\xfa\xc7\xfa\xfa\x36\x7d\x22\xb3\x2d\xf2\xa7\xb5\x57\xfe\xe0\xfe\x1f\x23\x8c\xd7\xea\x41\xe6\x2a\xe0\x74\x49\x20\x63\x6d\x38\x45\xf9\xd6\xf2\x2c\xd4\xf5\xe9\x3f\x28\xeb\x1a\x16\x33\x22\x5e\xfb\x8e\x1e\xb4\xa3\x3d\x24\xcf\xf8\x80\x1e\x64\x6f\x82\xff\x7b\x01\xf5\xc0\x6f\xe0\x32\x0a\x4e\x01\x4f\x95\xbd\xe4\xf7\x50\x4e\x18\x93\xff\xce\x41\xc1\x57\xa0\xca\x28\x3e\xf0\x0e\xee\xa7\xbf\x94\xfc\x62\x8c\xce\xd3\x83\xec\xb3\x50\x33\x98\x8b\x20\xc2\x4c\x29\x3e\xd2\xc9\xef\x49\x1b\x0b\x74\x65\x54\x9b\x4d\x53\x1c\x69\x28\x1e\x40\x51\x5a\x65\xf8\x74\x3a\x2f\x92\x2f\xb0\xbb\xd3\xe9\x9c\x28\x99\x97\x58\x71\x96\x91\xd3\x72\x66\x81\x7a\xa0\x2f\x6e\xfc\x7f\x91\x74\x4f\x1b\xf1\x5c\x42\x3c\x0f\x4f\xd2\x5f\xc2\x93\xde\xc1\x93\xf5\x2d\xc6\xff\xde\xd9\xb3\xf5\xef\x5b\x99\x27\x0a\xb3\xb7\xfe\x7d\x6b\xa1\x96\xf9\x00\xf6\x7d\xe9\xfe\x5d\x78\x07\xf4\x67\xf9\xd0\x09\xa4\xe3\x45\x71\xa4\x0c\xdf\x27\xc0\x25\x29\x09\x95\xe2\x4e\xab\xbc\xdf\x58\xb1\xf1\x8f\x41\x2f\x8f\xec\x10\xe0\x2b\xbe\x94\xea\x8d\x68\xd0\x22\xed\xf5\x89\x92\xea\x60\x8d\x7b\xe7\x66\x69\x12\x6b\xa0\x64\x36\x29\x10\x67\x13\x97\x9e\x3e\xfb\xa4\x6f\xcf\x9d\x75\xf2\x5c\x0e\x9f\x9e\xf9\x6a\xf5\xc9\xb3\xe7\xcc\x3a\xe1\xdb\xa7\xd9\x2e\x1b\x4e\x11\x5c\xec\x4d\x08\x39\xa7\xc1\x4c\x9a\x0f\x45\x09\xfe\xb7\x11\xa5\x1b\xc1\x84\xc3\xf0\x1f\xd3\xe0\x6a\x2b\x38\x03\x10\xfd\x5e\x8b\x97\xdf\x21\x03\x99\xb4\x11\x45\xd8\x42\xd0\x20\x87\x54\x87\x9d\x74\xc0\x05\x44\xd5\xe6\x26\x97\x26\x44\x21\x50\xa1\x32\xc4\x92\x0e\x4a\x3c\xda\xbc\xca\xa6\x62\x37\xe8\x82\x1b\xf0\x66\xfd\xac\x47\xb9\x9a\x92\x11\x96\x6c\x05\x1b\x87\xd9\x68\x89\x11\xfe\x1b\xfe\xe3\xbe\x69\xa3\x0d\xb5\x98\xfb\x74\xac\xe5\xe3\xd6\x3e\xbf\x4d\x3a\x15\x14\x94\x51\xc3\x76\x8d\xb4\xd8\x3b\xcc\x4e\x6a\x9f\x9b\x9a\x97\x80\x5d\x1b\x6b\xc3\x41\xbf\x28\xc1\x56\x55\xc6\x27\x4a\xb9\xfa\x96\x56\x93\xf1\x61\xc4\x86\xab\x0e\xc6\x54\xd9\x70\x5f\xc9\xac\xcc\x63\x07\xd8\x70\xf5\xe9\x19\xc0\x3a\xb7\xbf\xc2\xc7\x91\x84\x1a\x50\x07\x9a\x80\xee\x21\x99\x46\x43\xef\xdb\xec\x1a\xa9\xaa\x36\xc3\x98\x8b\x5d\x53\xea\x28\x10\x97\x23\x45\xc1\xfd\x0c\xff\x43\x09\x90\x6c\x8c\xd3\xa7\x29\x4e\xbf\x1a\x95\x34\xc3\xe0\xf0\x19\x40\xf5\xb3\x07\x44\x29\xcf\x7a\xfd\x21\x48\x32\x46\x45\xa0\x45\x53\x9c\x80\x4c\xa5\xb6\x35\x8a\xd2\xa0\xc7\x1b\x8a\x13\x40\x2e\x35\x80\xb2\x59\xa5\x59\xca\xf1\xb6\x56\x32\xa8\x3d\xd8\xd9\x0d\x40\x89\xc5\x86\x4f\x5a\x3b\x1e\xd1\xee\x39\xaa\xd8\xe6\xee\xda\xb6\xe3\x22\x67\x18\xa7\xcb\xbb\x40\x2f\xba\xea\xbc\x65\xec\x50\x89\xfc\x1e\x2f\x93\x1f\xe5\x16\xbf\x6a\x3e\x3e\xaf\xac\x41\x34\xff\xe0\x93\x85\xf4\x28\x83\x48\x0c\xda\xa4\xcf\xe2\x97\x03\x67\x56\xc0\xe4\x31\x2a\x72\x81\xb9\x33\x8a\x98\x22\x7e\x71\x70\x14\xca\x2c\x17\xc1\x4d\x27\x41\x20\x4c\x6c\x83\x37\x6f\xa7\xad\x73\xc8\x9c\x5a\x8a\x97\xf2\x26\x42\x71\x00\xf8\xb4\x66\x15\x89\x09\x09\xa7\x56\x39\x01\x24\x8b\x36\xe9\x41\xfe\x1c\x3e\x08\xeb\xab\x35\x7b\x96\xac\x15\x0e\xba\x71\xc8\x9b\x54\x63\x1c\x79\xee\x61\xb5\x45\x76\x90\xaa\xab\x55\x82\x69\x78\x56\x22\x24\x33\x63\xad\x59\xf1\x9a\x7c\xa9\xc8\x6e\x0e\x7c\x95\xaf\xba\x9c\xed\x11\x96\x3f\x79\x24\xd3\x23\xec\xa2\x1a\xc7\x23\x0b\x6f\xdf\x4c\x78\x0f\x44\x54\x63\x62\x61\x13\x26\x4b\x5f\x4a\xe5\x9d\x26\x3d\xaa\x82\xd3\xe0\x6e\x95\x25\x67\x14\x89\xd0\x59\x86\xd2\xe0\x5b\x39\x8c\x75\x73\x3e\xa0\xd1\x51\x83\x51\xc0\x3f\xf0\x11\xf3\x84\x44\x8b\x36\x2d\x5c\x7d\xed\x6b\x70\x6f\xdd\x88\x95\xf3\xc1\x6f\x76\x57\xe5\xa6\x34\x74\xc4\x7e\x11\xe4\xc0\xeb\xd0\x95\xe5\xac\x32\xaa\x10\xca\x64\x94\x58\x8a\xe4\x04\xea\xc7\x24\x35\x32\x3e\x19\x6a\x12\xa1\xb4\x21\xc6\x7a\x21\x59\xae\x72\x88\x24\xa7\x65\x51\xf5\xc3\x11\x48\xb4\xbd\x11\x01\x24\x10\x1e\x8d\xdd\xc8\x56\xa1\x50\x65\x5d\x0c\x5c\x6d\x99\x6e\x55\x50\x1b\x55\xd1\x33\xfb\x59\x7c\x10\xf6\xd8\x8a\x1e\x1a\xc1\x9d\x33\xe8\xc6\x8d\xde\xa4\xda\xc2\x69\x80\x34\x0d\x5b\x76\x5a\x9d\x8e\x07\xd8\xb2\x52\x4f\x7a\x3a\x9b\xd2\xd0\xf6\x38\xea\xc6\x95\x88\xa4\x36\x02\xbd\x04\x92\x20\x27\xac\xb6\xc4\x44\x29\xc7\x72\x2e\xd2\xb4\xa5\xd6\x37\x8d\x29\x86\x4a\x0d\x2d\x97\x47\x6f\x35\x65\xad\x10\x4b\x15\x05\x00\xbd\x15\xe2\xd0\x37\xdf\x84\x92\xe8\xc6\x0a\x5e\xc9\x58\xa6\xd8\xf9\xd1\x98\x52\xc3\x4e\x4d\xe9\x4c\x19\x82\x32\x8b\x8e\xe5\x4d\x20\x8a\x0b\x92\xf9\x4a\x22\xad\xd6\xf9\x34\xa5\x2d\x0d\xe5\xc7\xb2\xae\x10\xb5\xc6\x25\x4a\xaa\xdc\x98\xcd\x2a\x75\xa2\xda\xd2\x09\x02\x21\x91\xac\x2a\xf8\xa1\xa0\x31\x4a\xb7\xc8\x28\x92\xa8\x64\xf0\xfa\x74\x84\x24\x46\x90\x29\x8d\x14\x04\xcc\x6a\xdb\x6e\x10\xee\x00\x8c\xc3\x5a\x0b\xcb\x9e\x25\x3a\x92\xe7\xc3\x50\x6d\xe4\x59\xcb\xfe\x08\x7e\x4d\x11\x08\xdd\x1f\xeb\x27\xec\x44\x40\xfd\x69\x77\x64\xb3\x0a\x27\x3e\x8d\x19\xa7\x37\x10\x0c\x13\xdc\x57\x49\xf5\x41\x79\x1c\x87\xc1\x45\xef\xe9\xed\xc5\x71\x1c\x67\xe3\xae\x4a\x4c\xf5\x38\xd3\xda\xc6\x33\x1c\x5e\xc9\xf0\x7a\x6e\x51\xe1\xe3\x45\x53\xca\x9e\x81\xab\xf1\x55\x3f\x6a\xb1\xc7\x6d\xcf\xed\x3d\x02\xcf\xd5\xd7\x09\xcb\x4b\x0c\xfe\xbe\x05\xf8\xed\x2b\x9b\xaf\x31\xce\x74\xf6\xfe\xdd\xdc\x44\x3e\x8e\x22\xa8\x0d\xf5\xa2\x95\xa4\xf3\x84\x80\xf6\x75\x0a\x34\x78\x12\x04\x2d\xcf\xa6\x42\x46\xe4\x04\xb5\xa6\x34\xec\xaa\x5d\xd6\x94\x76\x60\x89\x30\x5c\x45\x9f\x4f\x53\x33\x38\xa9\xb6\x23\x51\x1a\x74\x38\xa3\x31\x02\x2a\x9c\x17\xdc\xa1\xba\x16\x52\xa4\x1b\x0c\x34\x34\x36\x43\x0c\xcf\x86\x08\xf6\x8e\x00\x85\x03\x37\xc9\x31\x05\xc6\xf7\x4f\xc5\x7d\xe3\x13\x4d\xb4\x76\x57\x82\xd7\x52\xbe\xf1\x20\x94\x6a\x04\x2f\x9e\xfd\xcd\xbe\x17\x9f\xba\x71\xe3\xb9\x2f\x7c\xfc\xb7\xcf\xdf\x9a\x68\x3f\xee\x91\x55\x3f\x7d\xa6\x1c\xbc\xf5\xe4\xbb\x16\x5d\xfd\xdd\x1b\xae\xc3\xc7\xe7\x7e\xe6\xe0\x7b\x9f\x38\xf1\x77\xe7\xbe\xf4\x6a\x21\x7c\xef\x77\x8e\xdd\x64\x9b\x5f\x2a\x8f\x17\xae\xbd\xe2\xdc\xb9\x1c\x37\x87\xd4\xdc\xfe\x84\x10\x7b\x98\x70\x07\xf2\xa2\x1a\x74\x18\xed\xce\x0a\x42\x17\x69\x2c\xa5\x88\xc0\x9b\x92\x8b\x80\xa3\x1c\xa9\x01\xfc\xa9\x9c\x18\xb1\x9c\xe8\x00\xb1\xcb\x11\x11\x14\x19\x08\xd9\xcb\x01\xe6\x4b\x18\x91\x9b\xcb\x16\x2b\x52\x8a\xf3\xd2\x93\xfa\xc6\x5e\xc1\x07\x7f\x23\x42\xcc\xc7\x80\x7b\x2f\xa1\x96\x12\xdc\x7b\x18\xde\xf6\xc1\x20\x1f\x54\xb4\x25\xdf\x28\xdf\x1f\x10\xe3\xe2\x15\x65\xdf\xfb\x08\xee\x1d\x01\x64\xbf\x6f\xad\xc5\xa5\x74\x07\x72\xa1\x1a\xd4\x6c\x78\x05\x8e\xd2\xa6\x17\xb5\x89\xb5\x40\x6c\x4a\xda\x5d\xf8\x30\x89\x37\x63\x56\x2a\xa7\x51\xdc\xc8\x7a\xa5\x70\xc4\x01\xc4\x39\x04\x91\xc8\x6c\x74\x19\x49\x9c\x53\x21\xad\x31\x98\x91\xf8\xb2\x5d\x4c\x18\x95\x19\x09\x97\x9e\xf4\x2e\xab\x4b\x89\x2d\xe1\xca\xa9\x45\xed\xc6\xfe\x60\x52\xa9\xd1\xec\x52\x6a\x2d\xce\xcb\xd4\xc9\x9a\x52\x47\xe6\x65\x04\x99\x8c\xc9\xd4\x01\xe5\x87\x3f\x6b\x78\x7f\x1b\x59\x29\x18\xad\x71\x12\xe8\x6c\x02\x5b\x47\x18\x53\xaa\xd3\xe4\x54\xa8\xf3\xa8\x9c\x47\x8b\xca\x36\x38\x7b\x74\xce\xa3\x1b\x4a\x29\x12\xd6\x97\xf0\x1e\x99\xf8\x71\x77\x20\x09\xc5\xd1\x71\xd5\xd0\xa3\x9a\xaa\xa1\x47\x25\x2a\xd0\xa3\xf2\x7e\x39\x5a\xdf\x40\xb1\xa3\x6a\x62\xa3\x02\x3f\x96\x6f\x6d\x04\xc4\xd0\xfa\x72\x47\xb5\x0a\x44\xd8\x79\x95\xb8\xad\x04\x1f\x8c\xf0\x0c\xce\x1b\x15\x2d\xaa\xb9\x1a\x5a\x54\x8b\x85\x16\x15\x26\x1e\xb9\x64\x91\x0c\x0e\xfa\x62\xb5\x75\x60\x8a\x0e\x0c\x16\x55\xb6\xa5\x11\x38\x41\xe5\xf4\x10\x55\x30\xbd\x8e\x2e\x8f\x59\x08\xd6\x5b\x07\xe0\x24\x36\xa1\x6e\xb4\xb8\x0a\xda\x5b\x63\x4a\x19\x97\x51\x6b\x9c\x9a\xd2\x9a\x06\x78\x0a\x9b\x49\x8d\x60\x9c\xd3\x60\x98\x45\xf6\xa4\x12\xc8\xa8\x75\x91\xd2\x43\x1b\xec\x70\x3b\xec\x80\x19\xac\x24\x52\x6a\x47\x84\xb0\x26\x24\xea\x44\x49\xf5\xf3\x63\x01\x29\xda\x46\x81\xfc\x18\x89\x10\xc5\x33\xeb\x0b\x67\x1d\x35\x31\x3b\x7d\x7a\x76\xe2\x51\xf8\x2e\xf3\x53\xb5\x83\x9c\xf7\xeb\x5f\xef\x98\x3a\x65\xca\xd4\x49\x53\xa7\x4e\xa2\xff\x84\xf8\x94\x9c\xe7\x1f\x01\x83\xb1\x19\xf5\xa0\xef\x57\x9e\x69\xad\x21\x84\xf6\x8c\xda\xe4\xd4\x94\xee\x74\x19\x2c\xa3\x21\x86\x5e\x0b\xf3\x2d\x0a\x62\x90\x33\x6a\x43\xa4\x0c\x4a\x2a\xe9\x32\xc4\xd0\x12\xd1\x94\x96\x94\x9a\x8c\x68\x40\xa3\xd1\x10\x25\x2f\x4e\x8b\x11\x87\x28\x49\x49\xf5\x94\x23\xbd\x8d\x01\xd8\x38\x9a\x78\x46\xa8\x42\xbe\xba\x74\xaa\xe8\xc4\xe9\xd5\x84\x63\xea\xc6\x3c\xc0\x01\x6c\x43\x19\xb4\xa4\x2a\x12\xa0\xd2\x9b\x51\x43\x4e\x4d\x49\xa6\x4d\x3e\x04\x43\x29\x02\x86\x34\x20\xbb\x5e\xa2\x11\xdd\xa0\x11\xed\x11\x4d\x69\x4f\xa9\xdd\x11\xc2\x92\x10\x0d\x88\xa4\x4b\x48\x69\x17\x07\xfd\x7c\x53\x9b\x71\x0f\x0e\x8c\xff\x67\x42\xa0\xc8\x63\x6a\x88\xdb\xdc\xf5\x2b\x8b\x66\xe1\x19\xe9\x97\x8e\x1c\x43\x47\x6c\xb7\xd2\xbd\xbf\x1d\xbb\xec\x9e\x60\xf6\xc9\xd4\x43\x25\xb2\x00\x3d\x11\xdc\x80\x86\xd3\x81\xfa\x0c\x6f\xb3\x5c\x4f\x22\x86\x40\xba\x32\x6a\xbd\x53\x53\x32\xe9\xa2\x29\xe8\x2f\x07\x05\x54\x63\xe5\xda\xd1\x03\xda\xd1\x19\x01\xe7\xb4\x27\xa2\x01\xa9\x46\x4c\x16\xa5\x9c\x14\x6f\x32\xbc\xeb\x4e\x31\xc7\x37\x03\xdd\x4a\x8f\xa9\x25\x07\xb4\x11\x07\x92\xd3\x08\x55\xd9\x34\x9a\x98\xaa\xc0\xcc\xdd\x34\xaa\x94\x8a\x3a\x73\x16\xd8\xf7\x2e\x94\x45\xcb\xab\xe8\x4c\x32\xa5\x0c\x64\x80\xea\xaf\x37\x8d\x95\x43\x2c\x9d\x69\x02\x01\xb5\x97\xeb\xcc\x78\xd0\x99\xee\x88\xa6\x74\xa7\xd4\xf1\x11\x4d\x9d\x68\x78\x75\x4d\x86\x19\x6d\xc8\x66\x95\x6e\x31\xe7\xe7\xa1\xea\x3c\x5e\x52\xa3\xf5\x07\xf9\x12\x8c\x86\x2a\x34\x42\x81\xde\xbf\xe3\xce\x53\x8e\xbf\xef\x8e\x6b\x4e\x8c\xe9\x9f\xf6\x5c\x13\x38\x28\x5b\x23\x64\x6b\xa6\x1f\x77\xe4\xac\x9a\x6b\xce\x68\x3b\xf2\x7a\xfd\xf6\xca\x8b\x65\xea\x92\x17\xde\x90\x14\x9a\x88\x6e\xaa\xd4\xa5\x36\x43\x50\x99\x8c\xda\xe5\xd4\x94\x6c\x89\x2e\x4d\xb2\x74\xa9\x19\x44\xd5\x59\xae\x4b\xfd\xa0\x4b\x3d\x11\x4d\xe9\x49\xa9\xfd\x11\x4d\x9d\x8c\x93\x00\x19\x99\x93\xc2\x71\xd0\x20\x51\xe5\xa3\xd9\xac\xd2\x2f\x0d\x7a\x7c\xb1\xc6\xff\xe4\xc1\x19\x4d\x72\x23\x54\xea\x87\x07\x92\xdc\x48\xd5\xe2\xfb\xc6\x14\x1c\x2a\xb7\x49\x31\xb0\x49\xcb\xaa\xe8\x57\x0b\xd8\xa4\x86\x11\x36\xa9\x16\x84\xd6\x74\x10\x36\xa9\xa9\x96\x94\xeb\xdb\xc5\x9c\x5f\xe6\x0d\xd1\x75\x4b\x84\xd4\x78\x14\xed\x8a\x87\xc2\x72\xa2\x1b\x07\x0e\x56\xaf\xde\xc2\x33\x66\x2d\x7a\xed\xa8\x17\xb9\x83\xd3\xa8\xc9\xc1\x7b\x2e\x8b\xa5\x7e\xae\xdf\x5c\x55\x26\x45\xdb\x54\x07\xb6\xe9\x86\x4a\x7d\x8a\x53\xdb\xd4\x36\xaa\x6d\xaa\x07\xd1\x34\x1f\x84\x6d\x6a\x36\xfc\x64\x29\x06\x96\x49\x0d\xf3\x60\x97\x06\x3d\xbe\x68\xcd\x41\x6a\xd3\x01\x24\x35\x42\x8f\xae\x1d\x5d\x52\x55\x34\x28\x3b\xba\xa0\x18\x98\x35\x9e\x07\xf3\x21\x31\x74\x9e\x39\x27\xcd\xd3\xa0\xd2\x26\x14\xe7\xa4\x6d\x9a\x89\x65\x20\x4b\xd6\xcc\x3d\x93\x56\x7d\x14\xc3\x40\xb6\xa2\xe5\x98\x89\xec\x31\xf6\xec\x34\x2f\xf4\x4d\xc1\x64\x76\x3a\xd1\x64\xce\x69\xcc\x61\xde\xb4\xfd\xe0\xba\x33\x73\x0b\x4f\x79\xfe\x52\xec\xc7\x5d\xfa\x47\x7b\x77\xeb\x5f\xe3\x06\xe6\xa2\x73\x4e\xbb\xd4\x81\x3f\xbc\xeb\xba\x3b\x5b\xd3\xbb\xc7\x35\xeb\x3b\xf4\x2f\xf4\x7f\xe8\xaf\x61\xd7\x33\x4b\x57\x2e\xbb\x02\xc2\x7d\x12\xf3\xdb\x3b\x90\x80\x5c\x28\x0c\xe7\xbe\xba\x32\xee\x8f\x98\x71\xbf\x22\xa7\x94\xb6\x8c\xea\x73\x6a\x4a\x3c\xad\xd8\x53\xaa\xc3\xd8\x60\x67\x69\x2e\xc0\x8d\x93\x8a\x3d\x6d\xf6\x93\xd7\x63\xa2\x0b\xcd\xc5\x24\x41\x92\x4e\xa0\xe4\x78\x1c\x21\x7c\x46\x4a\x2d\x24\x98\x6d\x0c\x70\xb1\x71\x22\xc5\x1c\xc2\x11\x68\xd0\xb2\xf2\x04\x6c\xa5\xcf\x42\x12\x05\xa5\xe7\x5f\x9a\x34\x48\x94\x3a\x2d\xab\x49\xce\x60\xa1\xf9\xef\x56\xf2\x60\x71\xd1\x61\x19\xe6\x20\x77\xc0\x4c\x35\x4f\xda\x46\x73\x08\x7f\x44\x11\x88\xa3\xd2\x68\x0a\x7a\xac\x34\x8f\x90\x14\xb4\x5c\xa3\x71\x23\xfa\x33\x46\x4c\xa5\x4c\x4a\x97\xa4\x15\x7a\xcc\xb4\x02\xe0\x6d\x19\x72\x9a\x0a\x72\xea\x90\xb5\xc1\xba\x0e\xc3\xc3\x8b\x66\xc0\xa7\xed\xf0\x03\x26\x3b\x49\x35\x28\x99\xc6\x9d\xa2\x9a\x8d\x68\xea\xa1\xa6\x8f\x1b\x4a\x66\xb3\x4a\x46\x54\x05\x77\x36\xab\x64\x25\x55\x0c\x18\xd2\xe9\x11\x45\x29\x87\xa4\x00\x1d\x32\x60\xe8\x0c\x8c\xe2\x16\x0f\x94\x73\xa8\x10\xa2\x95\x74\x28\x75\x8a\xaa\x25\x20\x5e\x2f\x15\xe8\x39\x34\xff\xd0\x63\x5d\xa1\x2a\x99\x88\x4b\x4b\x84\x7b\x38\x4d\x44\xb0\x6b\x4a\x7c\xa1\x52\xdd\x13\x51\x1d\x5a\x51\xa9\x79\x6e\x4b\xf3\x62\x29\x80\x6e\x31\x75\xae\xbe\x54\xe7\x24\x9c\x54\x23\x11\xa0\x7c\x35\xb5\x0c\x58\x9b\x05\x51\xca\x63\xde\xee\x70\x1b\xb1\x51\x04\x32\xad\x9c\x94\x67\x6c\x4e\x17\xe1\x2b\xc4\x6e\x91\x54\x85\x4b\x35\x0c\x83\x56\xb1\x63\x68\xd5\x67\x44\x99\xce\x1a\xa1\x4c\x8b\x9e\x7f\x7e\xef\xd7\xa6\x12\x4d\x9e\x5c\xb4\xab\xa5\x7a\xd4\x8a\xd2\xe8\xd1\x52\x2d\x6a\x10\xb4\x5c\x27\x83\x92\x6a\x8f\xb3\x34\x2d\xd5\x3c\x42\x7f\x32\xa5\x11\x7b\x1b\xa6\xb4\x57\x84\xb3\x98\x26\xaa\xc6\xd3\xf8\x7d\xd0\xe1\x04\x3b\xaa\xb4\x89\x4a\x28\xab\x74\x49\x39\xa1\xc1\x9d\xcd\x66\x55\x5f\x93\x28\xe5\x02\xb1\x5a\x30\x34\xcd\xff\x0b\x1d\xc2\x96\xde\x04\x0e\x42\x6f\x5e\x22\xea\x72\xfe\x01\xb4\x65\x5f\x66\xa4\x96\x50\x0c\x49\xa1\x85\xd7\x91\x0f\x05\x50\x18\xcd\x27\xfd\x7a\x0a\xca\x14\x0b\x7e\x9c\x5b\x53\xa4\x74\xde\xeb\x77\x33\x1e\x68\xc4\xca\xdb\xec\xf0\xd1\xe6\xd6\x94\x60\x4a\x95\x79\x32\xa4\xeb\xd9\xa9\x88\x45\x9a\x10\xe8\x30\x70\x30\x50\x21\x26\xc3\xb0\x6a\x14\x2a\xc3\xbd\xb8\x84\xe9\x56\x8c\xb3\x38\x2e\x26\xd8\xbe\xb8\xcc\xac\xe6\xee\x29\x92\xdb\xea\xf2\x3d\x58\xc0\x57\x5c\x3d\x99\x59\x6f\x1b\x32\xe9\x6c\x0d\x4d\x60\xce\x62\x8e\xc7\x57\xed\xd8\x41\xcf\x9e\xd7\x6d\x1b\xc0\x7e\xf4\xa3\x49\xe8\x69\x5a\xcb\x6b\xcd\xa8\x35\x82\xe1\x58\x40\x43\x91\x22\x65\xa0\x77\x7c\x62\x3a\x3f\x10\x6e\xf4\x78\x92\xea\x80\x0d\x3a\x81\x07\xfc\x6a\x8f\x57\x53\x32\x29\x75\xbc\xb1\x85\xc9\xa6\x0d\x29\x31\x1b\x61\x9f\xa6\x0c\xa4\x95\xb0\x1f\xf8\xa7\x64\x49\x53\xa7\xe0\xa4\xda\x81\x28\x7a\x9b\xd2\x2d\xe6\xed\x9e\xd6\x0c\x50\x50\x85\x25\xd5\x97\xc8\x66\x95\x09\x62\x5e\xaa\x69\xec\x03\x2a\x2f\x59\x52\x6b\xeb\xa0\xb3\xbc\xc6\xd0\x87\x5a\x23\x46\x50\xed\x3d\xa4\xe7\xc0\x23\xaa\x2e\xb3\x55\x7b\x2a\xed\xbe\x34\xd4\x01\x00\x0a\x50\x1d\x8e\x97\x8e\xc9\xc2\x9f\x2d\x45\xcd\xe8\x8b\xcb\x2c\x3c\x5b\xb3\xbf\xfc\xe2\xf9\xd3\x8e\xbb\xed\xd1\xb3\x7f\xa5\xbd\xbf\xfc\xf0\x27\x2f\x7b\x17\xa3\x42\x97\xed\x07\xd7\xbd\xb4\xe9\x84\x4d\x37\xde\xfc\xb7\x69\xf3\x5f\x7e\xf8\xa7\x5b\x70\xf6\xb6\x73\x2f\x5b\x76\xe5\x95\xdb\x98\xf5\xaf\xe1\xa7\x98\x45\x73\xde\x26\x6a\x72\xf2\x91\x87\x1f\xf7\x9b\x73\x57\x1d\x7a\x98\xfe\x89\x76\xd7\x75\x77\xce\xd9\xdd\xd6\x7e\xee\xc2\x4b\x4f\xfb\xd5\x23\x44\x59\x4e\x65\xd3\x3b\x76\x14\xde\x5a\x7a\x65\x11\xbf\x6a\x83\x6d\x3b\x8a\xa3\x3b\x51\xae\x01\xe6\x19\xec\x34\xaf\x67\x67\xb5\xbc\x28\x35\xb0\x9e\xa4\x12\xc9\xa8\x22\x90\x96\xe4\x43\xb2\xf1\x03\x35\x64\xb7\xe0\x71\x5c\x21\xc8\xe1\xfb\x30\xe4\x3c\x63\x3e\x4d\xb5\x85\xd3\x69\x13\xe2\xa4\xc6\x91\xcc\xf9\x00\x2b\xd0\x27\x3a\x8c\x3f\x65\xda\x6d\xeb\x73\x89\x52\x8e\xb5\x37\x10\x8c\x36\x68\xdc\x08\xc9\xa2\xa4\xba\x10\xe9\x14\xb5\x26\xfb\xc2\x04\xcf\xc1\x1f\x4f\xd3\x06\x84\x3e\x32\x6c\x5d\x84\x75\xf8\xdb\x9b\xe7\xaf\x79\x72\xdb\x97\xf8\xa6\xb3\xe7\xec\x47\x18\xe9\x1f\x33\x47\xdc\x70\x43\x19\xa6\xc3\xe9\x7b\x66\xea\x5f\x7e\xa0\x33\xf2\xe9\x5b\xcf\xfe\x44\x57\xb6\xea\xff\x02\x38\x07\x32\xe7\xc6\xed\x86\x5e\xd2\x2e\xb4\x0e\x41\xe5\x82\xd4\x87\xbd\xc0\x86\xae\x84\x53\x8a\x2b\x43\x91\xe6\x15\x47\x1a\x2b\xdd\xb0\xe9\xb8\xac\x29\x71\x30\x2b\x0a\x9f\x56\xed\x92\x96\xb3\xb7\x41\x37\x97\xcb\x91\x54\xec\x7e\x35\xea\x33\x0c\x51\x2e\x0a\x0d\x5f\xd1\xb0\x23\xa9\xa6\x70\x52\x8d\x23\x73\x4e\x37\x2a\x3e\xcd\x7a\x03\xa1\xda\xfa\xe6\x24\xd8\x1d\x49\xb5\xc5\xc8\xbe\xdd\x59\xa4\x06\xbc\x64\x02\x20\x2c\x2a\x62\x56\x15\x22\xa2\x34\x88\x6c\xf0\x37\xad\x2a\xf2\x00\x08\x01\x9a\x55\xa1\x84\x6c\xc8\x65\x00\x6a\xca\x64\xf0\x71\x32\x26\x99\xc4\xf7\xb7\xff\xee\xbb\xf6\x28\x66\x56\xde\x75\xba\x7e\xc4\x3f\x9f\x7c\x7d\xd7\xb4\x0b\x82\xfa\x5b\xf8\x38\x87\x63\xc9\x9b\xdb\xdf\xc1\x03\x8b\x97\x5d\xb5\xe0\xc2\x2b\x17\x2f\x61\xa6\x63\x0e\xb7\xac\x5b\xbd\xef\x86\x87\xf4\xdf\x1d\xae\xcd\xee\xea\x79\x68\xd9\xcd\xeb\x71\xa8\xf0\xe0\x0f\xaf\x5a\x1d\x7d\xf4\xae\xbb\xc8\xfc\xa3\xad\x4d\x58\x8e\x6a\x50\x07\xba\x85\x76\x88\x79\xd9\x12\x6d\x91\x02\xc0\x26\x0d\xb5\xbf\xce\x52\xe5\xf0\xd3\x66\x72\x5b\x3a\xe7\x97\xa1\xc9\x4a\x72\x24\xc1\xb7\x71\x21\x3a\x4f\xa6\xf8\xc5\x21\xd6\x1e\xa9\x6b\x68\x6d\x23\xb7\x6c\x90\x8f\x37\x25\xe0\xe1\xf1\x46\x48\xad\x27\x20\x89\x92\x8a\x5c\xa6\x7e\x58\x34\x67\x25\x5a\x52\x81\xfa\x51\x11\x44\x95\x6a\x4b\x05\xf6\xc7\xc7\xe5\x29\xc9\x12\xad\x29\x43\x00\xb1\x7d\x58\x96\x98\x64\x41\x7f\x96\xf1\x71\x90\x49\x1f\xba\xa6\x54\x83\xdc\x29\x55\x14\x34\xd3\xdb\xef\x94\x35\xa5\xd3\xaf\xf6\x10\x8d\x71\x48\xd0\x5d\x11\xf0\x69\x4a\x20\x05\xfe\x7d\xa7\xf1\x0e\x79\x7d\x31\x68\x32\x08\x88\x87\xba\x58\xb7\x18\x8a\x34\xc4\x5b\xdb\xba\xc0\x14\xf5\x48\xaa\x8d\x80\x22\xa8\x4d\x09\xe8\xe5\x74\x13\x90\x49\x41\xcc\x23\x9b\x0f\xfe\x52\xa9\x76\x04\x39\xaa\x1b\x93\x31\xd1\x8b\xaa\xf9\x66\xa2\x26\x73\x77\x6d\x23\x5a\xa2\x7f\xa8\x7f\xf4\xcf\x27\xb7\x6b\x1f\x3b\x1c\x8b\x7f\xbf\xed\xdd\x49\x65\x42\xb9\x7e\xf1\xb2\x95\x8b\x2e\x5a\xf9\x47\xda\x58\xb0\x7a\xdf\x9a\x2f\xbe\x39\xfc\xab\xd9\x7a\xe8\xe6\x47\x71\x3f\xf7\x41\x69\xee\xf9\xe1\xc7\xd7\xdf\xfe\x70\xcb\xe0\x43\xc8\xc4\x9e\xb4\xcd\x14\x96\x23\x37\x8a\xa1\x43\xa8\xcf\x62\xa7\x95\x54\x5b\xc6\x74\xf9\x09\x1c\x22\xf8\xf9\x6e\x98\x6a\x23\x99\x39\xe3\x23\xeb\xa4\x65\x4e\xd1\x82\x7d\x60\x2b\x3b\x4b\xfa\xaf\xc0\xb7\xe1\x39\x3a\xc3\x30\x80\x4e\xf1\x5f\x15\xbd\x24\x85\xb3\x37\xe0\x2f\x0a\x97\x53\x94\x8a\xca\x86\x19\x86\x60\x56\x08\x0f\x22\x2f\xaa\x43\x93\xe9\x1a\x9d\xa4\x92\x09\x7d\x5e\xf5\x56\xff\x19\x93\x06\x77\xc9\x6b\x9c\x17\x67\xf3\x89\xa0\xa2\x50\xc7\xe3\xdc\xe6\x32\x4b\xf0\x29\x2a\x16\xba\x06\xf7\x56\x22\x55\xbc\x59\xb6\x54\x3e\x58\x98\x5e\x86\x58\x21\x5c\x5b\xbe\x56\x16\xad\xd0\x83\x74\xbe\x5d\x46\x6d\xe8\x7b\xa4\x1e\x43\x07\xc1\xc8\x65\x0c\xb0\x90\xf5\x6c\xf4\x6a\x26\x83\x82\x3b\xac\x29\x6e\xbf\x1a\xc2\xc9\x7c\x1d\x69\x32\xab\x23\xb8\x93\x7c\x98\xf0\x29\xd4\x85\x44\x29\xcf\xfa\x02\x8e\x28\x45\xf1\xab\x69\x6a\x21\x13\xd7\x2d\xa2\xa4\x24\x80\x73\x20\x54\xd7\x64\x3c\x76\x81\xa8\xf1\xf0\xf1\xbe\xec\x88\xa2\x8d\x55\xa5\x09\x8c\x40\xd6\x1f\x59\xb7\xb1\xe6\xc8\x9f\x2a\x27\x1c\xa8\xa8\xdb\x58\x03\xe5\xfb\xda\xcb\x90\xf6\xc9\xdd\xbb\x97\x5b\x8e\x3c\x28\x8a\x92\xe8\x4a\x52\xb7\xc9\xd7\x95\x30\x79\x86\x9d\x9a\xd2\x91\x52\x9b\xbd\x56\xf1\xd9\x2b\x03\xa7\x7d\x0d\x06\x9a\x10\x43\x0e\xf1\xe2\xe8\x67\x97\x61\xa3\x6b\x48\xab\x41\x50\x1c\x72\x8a\x6c\xb8\xbe\xb5\x03\x0e\xb8\xb9\x43\x94\x94\xb6\xac\xe2\x14\x73\x35\x71\xa0\xb4\x0f\xd7\x89\x52\x4e\x40\x62\x76\x64\x69\xa7\x74\xf6\x7c\xa4\x24\x2a\xaa\x3b\xc5\x21\x74\x4f\xb9\x1c\x2a\xcb\x3b\xe6\x2c\xfa\x70\x53\x99\x1c\x38\xa2\x0f\x42\x14\xf4\xc1\x90\xc4\xcd\x54\x23\xea\x2a\x34\x82\x48\x42\x09\xa5\xd4\x30\x6f\x09\x84\x2a\x46\xb9\x40\x4c\xc5\x30\x04\x52\xe3\x36\xa2\xaa\x30\x40\x32\x81\x82\x80\x85\x12\xa5\x7c\x24\x6a\x0a\xc7\xd1\x2c\x4a\xa6\x58\x02\x75\x07\x56\x0e\xc3\x21\xfe\x77\x14\xa4\x89\x59\x5f\xf8\xfb\xc1\x29\x09\x73\xc9\x8e\x1d\x7b\xf2\x95\xfc\x14\x1c\xd1\x15\xdb\x06\xe4\x81\xc8\x29\x65\x44\xed\xa0\x2d\xf1\x12\x6d\x89\x39\x81\x17\xb7\xdd\x0b\xc0\x55\x3e\x43\x46\x3d\x64\xdc\x5b\x36\xc3\xf3\x7c\x0b\x91\x51\x0b\x05\x57\x94\x35\xb5\x97\x8e\x7b\x13\xa6\x98\x96\x7a\x13\xff\x6c\xc8\x29\xb3\xb1\xa6\xce\x2e\x5a\x0d\x24\x53\x0d\xce\x76\xe8\x9b\xeb\x34\x24\x15\x8b\x83\x02\xc9\x55\x14\x88\x84\x0c\xff\x86\x12\x6d\x67\xd6\x17\xb6\x1e\xa4\x1e\xb1\x73\x76\xec\x28\xcc\xa9\xae\x4c\x60\x0b\x61\x66\x43\x58\x06\x7d\x83\xd3\xab\x4e\x6d\x74\x58\x53\x1b\x9d\x74\x6a\x63\xd0\x2f\x52\x1e\xb2\xff\x60\x70\xa3\xc2\x46\x8e\x3e\xc7\xb1\xb8\xcc\x54\x56\x9f\xea\x10\x16\x55\xda\xf6\xac\x1e\xe4\x66\xd3\x37\xfa\x64\x44\x10\xaf\x3d\x76\x4d\x89\x50\x2c\xc4\x4e\xa0\xa2\x0c\xca\x5a\x8e\x07\x6e\x47\xde\x45\x9d\x93\x20\x2f\x4a\x79\x9f\xdf\xf4\x43\x58\x4a\x23\xea\x11\x73\x48\x84\xe9\x09\x2f\x09\x88\xc3\x65\x1b\x33\x67\x0e\x78\x2e\xd1\xd4\x56\xf1\xea\x66\xe7\xbe\x7f\xee\xc3\xeb\x7f\xb3\xf5\xbb\xf8\xee\x42\x8e\x7d\x45\x3f\xea\x93\xbd\xab\xf5\x4f\x5f\xd8\xb7\xf9\x84\xb2\x9d\xdd\xd3\x95\xb9\xe9\xea\x5b\x56\xbd\x8d\xaf\xd6\xb6\xea\xf3\x6b\xf4\xbf\xfe\xf8\x2f\x97\xcd\x14\xd6\x96\xf7\xea\xed\xbf\x4a\x0f\x32\x9f\xd0\xba\x75\x1f\x82\xb6\x69\xc5\x05\x28\x72\xd0\x71\x62\xdb\xa9\xda\x7d\xa4\xcd\xc4\x6e\x83\xb2\x17\x52\x19\x17\x19\x6c\xe7\xcb\x21\xec\x48\x7f\x4c\xc5\x5a\x57\x15\xbb\x62\xca\x89\x5f\x4b\x7b\x61\xde\xae\xf0\x87\xa0\xbf\xd6\x36\x44\xfb\x4e\x0f\xdc\x5d\x5b\x53\xad\xd9\x34\xf6\x1f\x75\xd7\x8e\xdd\x4e\x3b\x56\xff\x2c\x59\xb7\xe3\x1e\x6b\xdd\x27\x1c\x7c\xb7\xec\xe8\x1b\xb0\xba\x65\xc7\xea\x90\x1d\xbb\x25\x76\xf4\x1e\x58\xda\xb7\x60\x7f\x96\x0f\xd2\xbe\xd7\x5b\x0f\xb6\xeb\xb5\xf3\x80\x5d\xaf\xc9\xff\x5d\xd7\xeb\xbf\xd3\xea\x7a\x90\xbd\xad\x07\xd5\xcc\x8a\xca\x62\x94\x84\xe1\x8d\x8f\x1d\xa3\x34\x1f\x38\x46\x69\xc1\x49\xd5\xef\x12\xa5\x8d\xac\x3d\x12\xab\x4f\x40\x68\x22\xe6\xf8\x86\x46\xf0\x8d\xfe\xf3\xc8\xc4\xa2\x92\x18\x23\x26\x61\xec\x94\x5a\x62\xd4\x70\x84\x7b\xb6\xc8\x35\x51\x1a\x8b\x24\x50\xca\xf0\x0b\x47\xc6\x22\xe4\x3d\x6b\x96\x21\xc7\xdc\x59\x2d\x16\x31\x9e\xb3\x66\x1a\x8b\xd4\xd2\x58\xc4\x01\xb1\x48\x7d\xa2\xad\xdb\xf8\x41\x67\x31\x12\x21\x20\x13\xe5\x91\x08\xfc\xa5\x31\x23\x11\x6b\xef\xec\x41\xc4\x20\x38\x49\x85\xf0\xfc\x58\xe1\x07\xfb\x34\x15\x44\x61\xa6\x19\x7a\x60\xb4\x69\xff\x6e\x21\x6f\x1b\x42\x11\x74\x06\xed\xad\x85\xd2\x83\xd3\xa9\x99\xb1\x07\xbc\x05\x79\x36\x2c\x79\x3d\x16\xeb\x84\x21\xa0\x08\x81\x66\x8f\x90\x6e\x4d\x2e\x6d\x3c\xf4\x8a\x40\x00\x5f\xfc\x74\xea\xc4\x23\x10\x9b\x6a\xf6\x05\x97\x54\x5d\x08\x8a\xa1\x61\x91\xfa\xf1\xdf\x70\xdf\xa9\xe7\x9d\x37\x07\xf7\xe9\x1e\x5d\xff\x5c\x6f\xb0\x0d\x15\xb6\x30\x93\x87\x3b\xae\xff\xee\x55\x77\x31\x0b\x0a\x77\x15\xf6\xbe\xf7\xcf\x7c\xe1\x66\xd2\x57\x1b\xb4\x31\xb6\xd7\x4c\xcb\x09\x08\x7e\x02\x45\x12\x57\x50\xca\xb4\x35\x3e\x19\xa0\x77\x7c\x04\x78\xd1\x49\x47\x27\x7d\xb4\x63\x32\x40\x70\xb4\x42\x90\xcf\xf2\x67\x2b\xc7\x60\x00\x8d\x45\x0e\x32\x48\x88\xe2\x7e\x44\xe7\x60\x36\xed\xee\xb5\x1f\xfe\xbb\x0b\xb6\xec\x7a\x46\x7f\x68\xcf\x5b\x98\x5f\xf0\x9d\x6b\xee\xd4\x83\xc2\xda\xe7\xce\x5e\xaa\xbf\x57\xf8\xbd\x7e\x9b\xae\x1d\xa7\xbb\x59\xf9\x14\x7c\xfe\xf6\x9b\xef\x7c\xef\x55\x1a\xd3\x6d\x13\x96\x97\xe2\xad\x94\x74\xc7\x5a\xf8\x2a\xa3\xf4\xc1\x12\xf8\x06\x43\xcb\x5c\x6e\xbf\x08\xfd\x60\x62\x9e\x71\x4a\xc1\x90\xf1\x99\x23\x10\x15\x24\xf4\xab\xda\xe8\xcb\x9a\xe5\xac\xca\x9e\x56\x3c\x7b\xea\x86\xdf\x4c\xfd\x6a\x64\x23\xab\x30\x4f\x3e\xf7\xd5\xd8\xb8\x97\xcd\x58\xef\x71\xe8\x25\xaa\x43\xa7\x94\x77\xaf\x5a\xad\xab\x16\xc8\x56\x39\x62\x59\x03\xed\x4d\xcd\x71\x32\x10\x5c\xb8\xc5\x41\x21\x0c\x4d\x8e\x07\x86\x2e\xb3\x16\x5d\xd1\x7e\xfa\x18\x5d\xf4\x88\x9e\x53\xde\x6d\xae\x99\xe6\xfe\x85\x27\x90\x1f\x85\xa1\xc2\x7f\x35\x5d\xb7\x3b\xa3\xf8\x52\x30\xfa\x9c\x4c\xe5\x79\x92\xa6\x8a\xa7\xd4\x5a\x9b\x66\xa6\xaa\xfc\x7e\x80\x05\x67\x71\x32\xdf\x44\x60\x41\x9a\xfc\x6a\x3b\x4e\xe6\x1d\x84\x04\x31\x05\x35\x00\x52\x43\x6b\x12\x07\xb1\x18\x81\x08\xb0\x5d\x1a\x94\x6b\xe3\xbc\xf1\xd1\x21\xaa\x2e\xe0\x51\xe7\xa1\x8b\xaa\x39\x0b\x35\x80\xd6\xbe\xf1\xd6\x58\x39\x1b\x67\x03\x71\xb6\xb5\x8d\x17\x58\x8b\x54\x8f\x0d\x1a\x22\xa0\xf6\xfe\xab\xe4\xf7\x97\x5e\xf0\x83\x14\xfe\x5a\xcf\x2f\x2a\x68\x4b\x14\xfc\xc3\xf3\x66\x7b\x03\x47\x34\x77\x2f\x0a\xe1\xd9\xe1\xa7\x97\xe4\x66\x07\x5a\xd3\xfd\x9d\x9d\x03\xb6\xc4\x21\xa7\x5e\x78\xcd\xb5\x8b\x4f\x99\xb2\xf7\x5d\x3c\x5d\x1f\x62\x8e\xc7\xf1\xbf\x1f\x79\xf4\x4b\xec\x74\x7f\xe7\x65\x0d\xee\x9a\x4b\x06\xf4\x77\xe6\x72\x4c\x26\x09\xbc\x91\xb4\xe6\x24\x3c\x01\x5d\x44\xdd\x68\x02\x3a\x02\xbd\x50\x5a\x2d\x68\x2b\xeb\x5d\x1d\x67\x15\x09\x9a\x52\xf9\x49\x44\x58\x87\xa7\xf2\xb5\xe4\xd3\x84\x94\x9a\x31\xc4\x76\x24\x88\xad\x45\xd6\x06\xa3\x2d\xc8\x9e\xcc\x67\x89\xd4\x5a\x88\xc1\xa4\x85\xa7\xa9\x8d\x3b\x45\x4a\xb4\xa9\x1e\x85\x93\x6a\xd6\x88\x89\x43\xa9\x1e\x43\x29\xa6\x8a\x43\x82\xbb\xa9\x2d\x33\x01\xec\x67\x83\x59\x83\x1a\x37\x56\xfd\x40\x3d\x7c\x92\x28\xa9\x0d\xd1\xec\x58\x95\x04\x5c\xb5\x12\x15\x28\x11\x79\x31\x64\xa8\x56\x5b\xc0\x2d\x26\xfb\x64\x90\x54\x18\xa6\x81\xfc\xe5\x75\xd7\xfc\xa0\x97\xb0\x51\x0e\x54\x29\x35\x70\x7b\x28\x1d\xe5\x70\x3d\xad\x37\xd8\x32\x70\x18\x91\x85\x47\xe8\x5b\x4a\x38\x3c\xa1\xee\x00\x36\x21\x80\x6a\xd1\xf9\xff\x66\xdd\x01\x7c\xd6\x03\x16\x1c\x00\x3d\xc3\x23\x4a\xb9\x60\x18\xaa\x32\xd5\x8b\x0f\x01\xf3\x85\xa9\x5e\x81\xf8\x05\x7d\x52\xaa\x95\x21\xac\x07\x95\xd6\x22\xf8\x38\xd4\x22\x26\xa2\xc3\xd0\xa6\x31\x6b\x11\x87\xa6\xf3\x93\x48\x2d\x62\x12\xa9\x45\x4c\x82\x5a\x04\x56\x0e\x1f\xa5\x08\x31\x09\x8a\x10\x93\x69\x11\xe2\x5b\x15\x45\x88\x9c\xdd\x03\x13\x44\x61\x29\xef\x4b\x64\xfa\x27\x1a\xaa\x34\x19\xca\x10\x03\x13\x46\x2d\x43\xf4\x34\x92\x5c\x8d\x5d\x84\x62\x84\xf4\x9f\x17\x23\xac\x37\x3a\xf0\xef\x57\x24\xf0\x1d\x54\xbe\xc7\xfc\x7b\x75\x09\xf3\x09\x27\xc5\x09\x0e\xad\xd8\xbf\xde\xf6\xa1\xb0\x1c\x05\x50\x0c\x26\x0d\x2e\x21\xfd\x15\xc5\xce\xe3\x28\x5b\x1c\x2a\x20\x60\x88\x8d\xc6\x8b\x48\x13\x17\x41\x8a\xa3\xd3\x28\x1e\xea\xb0\xb1\x3e\x4f\xb8\x36\xd1\x0a\xd9\x76\xa7\x94\xe3\xdb\xda\xc1\x81\xab\x37\x54\xc9\x27\x02\x53\x4c\x54\x1c\x44\xce\x50\x13\xe9\xbe\xcf\xd9\x04\x7b\x31\x30\x0f\x0f\x84\x85\x10\xb0\x86\xb4\x09\x6d\x03\xad\x38\x18\xc6\x10\x96\x87\x32\x8d\xe2\xf8\xb6\x12\x5f\x6e\x21\x3e\x71\xeb\x9d\x27\xaf\x99\xf3\xa2\x7e\xaf\xae\xbc\x7c\xeb\xe9\x6b\x4f\xdf\x8a\x8f\x9c\x80\xf7\x9e\xbc\xf0\x99\xe7\x9e\x9f\xb1\x00\x2f\xcf\xe8\x5e\xd3\xa9\x83\x14\xc6\x51\x57\x2d\x58\xf5\xa2\x7e\xa3\x7e\xb7\x7e\xc5\x61\x37\x2d\xf9\xfe\x8b\xf8\xda\xe7\x2f\x61\xbe\xea\xfa\xa6\x70\x64\x1b\xfe\x24\x7f\x29\xd3\x52\xa2\x8f\x73\xf7\xe7\xa1\x4f\xd9\x90\x47\x33\x1a\x87\x96\x51\x79\xb4\x99\x9d\xca\xd1\x22\x7f\x11\xc5\xe0\xeb\xa4\x1e\x42\xb7\x29\x0f\x5f\x56\xe9\x14\x87\x58\x4f\xb8\xb6\xa1\xb9\x85\x0a\xc3\xd6\x18\x07\x61\xb4\x95\x0b\xc3\x89\x42\xe3\xfe\x1d\x61\x58\x5e\x1d\x31\x42\x6d\x90\xa2\xb8\xfe\x92\x81\x7b\x0f\xb9\x43\xff\xab\xbe\xff\x7b\x4b\xbe\x75\xff\x11\xf7\xe2\x81\x00\x9e\x9c\x9c\x7a\xc5\x92\xf1\x54\x0c\xcb\x5b\xfb\xaf\x58\xec\x26\x49\x8a\xf1\xb3\x96\x9c\xfc\x80\xbe\x4f\xff\x4c\xff\x6d\xd7\xb9\x0b\xcf\x79\x10\x07\xe7\x4d\xc3\xef\x84\x1f\x65\x30\x95\xc2\x70\xd8\xf7\xb3\xc7\x4e\x9c\x64\xbd\x87\xcb\x91\x80\x44\x78\x11\x4f\xab\xac\x85\x4b\xc5\xe9\x8b\xa6\x6a\xd3\x17\x89\x8a\xe9\x8b\x43\x1d\x98\x71\x7a\x7c\x52\x20\x42\x1a\x82\xb1\x24\x92\x80\xb3\x38\x77\x41\x08\xff\xba\x31\xad\x79\x5b\xff\x5e\x5a\xf1\xde\x84\xbb\xe2\xe7\x74\xac\x3d\xe6\x4d\x7c\x22\xa9\x7b\x5f\x0d\x3f\xf8\xe9\x94\xff\xb6\xea\xde\xf3\xe4\x69\x4f\x4e\x88\x65\x5f\xdd\x37\x1e\x8a\xdf\xac\x0d\xfe\xbd\x77\x7b\x49\xed\x3b\x8e\x22\xa8\x09\x8d\x43\xfd\x46\x0c\x53\x7c\xcd\x5a\xca\x5e\xb3\xce\xe2\x24\xc6\x00\x8c\xd0\x46\xd3\x6a\x42\xd6\x94\x58\x5a\x49\xc0\x0b\x6f\x96\xb9\x27\xe0\xa4\x9a\x30\xb6\xea\x70\x42\xb7\xe7\x90\xe0\x0e\xd5\x37\x76\x75\x9b\xe3\x18\xa9\xf4\xf8\xff\x68\x1c\xc3\x92\x47\x69\x09\x93\xfe\xac\xda\xf3\xc3\x59\xb2\x09\x91\xe7\x67\x8e\x29\x9b\x6a\x05\xee\x05\xa6\x98\x2e\xa6\xaf\x0e\x77\x9e\x25\x28\x73\xf6\xe6\x2a\x24\x20\x19\xc5\xd0\x9d\x95\xa7\x1f\xb2\x3a\x21\x02\x29\xd5\xc5\x6b\xb9\x00\x70\x3d\x04\xec\x8e\x24\xa4\x1d\x6a\x53\x8a\x7d\x27\x65\x07\x1f\x14\x64\xbb\x3d\xa9\x22\xbf\xe1\x64\x83\x9a\xc8\x50\xce\xcc\x7b\xc9\x7f\xe6\xbc\x3e\x3b\xd1\x19\xe8\x41\xb2\x8b\x92\xca\x3b\x00\xb1\x29\x8f\x19\x57\x28\x6c\x88\xd1\x2b\x41\x7c\x8c\x08\xf9\x6e\x4d\xa9\xda\x10\x74\x99\x44\x37\x93\x68\x12\x46\x0e\xeb\x04\x9d\xef\x3c\xbe\xe1\x0d\xc7\x13\x5c\xf7\x49\x73\xde\xf0\xd4\x97\x0f\xeb\xf0\xc9\x1f\xff\x72\xf0\x27\xa9\xfe\xc8\x55\xc3\x7d\x74\x52\xa7\x38\xab\x93\x44\x11\xd4\x8a\x7a\x50\xae\x54\x43\x3a\xca\x34\xa4\xdb\xf2\x77\x9a\x53\x6a\x2d\xaf\xe5\x9a\x6b\x0d\x29\x34\x47\x1d\x49\xa5\x21\x6d\x36\x51\xb7\xc9\xd0\x60\xde\xe6\xb7\xa8\xc2\x53\x4a\x9b\x5f\x1d\x67\x29\xd0\x60\x83\x6f\x9c\x3d\x99\x6f\x24\xff\xb5\x31\x65\xfa\x3d\x69\x9c\x54\x1b\x0d\x27\xde\xe9\x96\x88\xab\x23\xaa\xf5\x90\xe6\xec\xfe\x4f\x5b\x25\x4a\x85\xc5\x8e\x39\xe0\x73\x67\x99\xe0\x84\x51\x07\x7c\xb8\x3e\x4b\x86\xcb\xad\xe9\x1e\x16\xcd\x44\x88\x63\x80\x7f\x50\x46\x0d\xe8\x64\x3a\xf3\x11\x60\xb5\x9c\x0b\xb2\x9c\x6e\x2d\xef\x93\x9c\x2e\x0f\xa4\x7b\x00\xc3\xc3\x49\x72\x26\xde\x74\x2e\x00\x38\x11\x01\xd9\x91\x54\xdc\x69\x02\x91\x06\xd8\x1d\x01\xa7\x28\x0d\x0a\x0c\x68\x04\xe0\x82\x9b\x97\x21\x20\x16\x5d\x94\xa2\x19\x99\x69\x5e\x87\x63\xd8\xe9\x85\xdd\xf8\x33\x5d\x64\x82\x85\x77\xcc\x2b\x61\x99\x89\x3d\x7f\x28\xba\x29\xf4\x87\xd4\x56\xcc\xdd\xbf\x9b\x9b\x4f\x39\xb4\x5b\x50\x0a\x5d\x4e\x7b\xeb\x5c\x02\x7d\x0f\x12\xbc\x96\x6f\xb0\x4b\xac\x27\xa9\x36\xd8\x48\xf4\x1f\xda\xa9\xa0\x34\xc0\x47\xd9\x1b\xd2\xe0\x80\xc0\xb0\x8e\x44\xf2\xd8\xe1\x10\xc1\x87\x69\x14\x9f\x76\x49\x6c\x4d\x6d\x6b\x7b\x17\x19\xd6\x19\xf4\xfa\x92\xe3\xc0\x48\xb8\x24\xf2\x8a\xd8\x45\x23\xe4\x6f\xa0\x5c\x3c\x7e\x54\xf4\x28\xfa\x09\x90\x1a\x2a\x31\x10\xa4\x19\xaf\xf8\x83\xb9\x38\xba\xe7\x13\x6c\x2f\xa4\x6c\x3f\xb8\xee\xdc\xfc\xfc\x99\x43\xab\xf4\x2f\xf5\x37\xdc\x96\x7d\x10\xf1\x06\xe6\xe2\xef\x7c\xe7\xc2\x53\x4c\x69\x30\x6d\x38\x8a\x33\xfa\x97\x9f\xde\x75\xdd\x9d\x9d\xdd\xbb\xdb\xdb\x70\x27\xf7\x35\x15\xd0\xf0\x1f\x96\xad\x5c\xc9\x7c\x62\x4a\x86\x70\xdd\x31\xc2\x55\xc8\x85\xa2\x66\x77\x9e\x85\x1a\x66\xb8\xa0\x79\x9b\x1d\x51\xae\x3b\x25\x0c\x89\xfe\x5c\x18\xba\x15\xc2\x6e\x47\x12\xf0\xc4\x8a\x49\x3d\xc3\x0d\x85\x91\x61\x87\xcb\x91\x54\x18\xea\x86\x0e\xba\x1d\x46\x64\x40\xef\x8b\x83\xd0\x76\x4b\xe4\x56\x18\xc1\x78\xd4\x0d\x69\x56\x35\xe0\x10\x25\xd5\x17\xce\x02\x36\x85\x48\x73\x05\x45\x55\x28\xd5\xf6\x4d\x45\x25\x18\x7e\xb3\x4c\xb7\x8b\xc7\x5f\xb4\x07\xc8\x9c\x5b\x9a\xcf\x27\x61\x0e\xb3\x03\x3d\x58\x79\xfa\x6d\xbc\x96\x4f\x90\xd3\x4f\xd8\x60\x16\x33\xc2\x6b\xb9\x46\x18\x51\x6b\x34\x94\x37\x96\x36\x93\x81\x76\x59\x53\x9b\x12\xe9\xb4\x62\xf7\x53\xa3\xa8\xc8\x30\xac\xda\x8c\x93\x4a\x6d\xda\xd0\x0f\x93\x33\x3f\x49\x69\x8e\x94\x50\x56\x69\x16\xf3\xac\x4b\x8a\x00\xa8\x56\x0c\x52\xe3\xbc\x48\xb9\xf3\xed\x2e\x92\x13\x4a\x88\x63\x28\x48\xb9\x69\x04\x1d\xa9\xae\x19\xdf\x2f\x13\x08\x4f\xb5\xa3\x8a\x52\xb0\x5b\x4c\x09\x15\xde\x5a\xb6\x72\x25\xd8\xcb\xfd\xcb\x11\x62\xde\xb1\xee\xfa\x71\xe4\xae\x43\x35\x03\x2e\xb6\x7b\xa7\x12\x4e\xc3\xdd\x8e\xa4\x73\x01\xb7\x79\xb7\x55\x7f\x2c\x9d\xce\xb9\x01\x98\xc8\xed\x84\x77\x83\xdc\x72\xe8\xc6\xb4\x85\x48\xf4\x51\xf4\x02\x02\x25\x03\x7d\xc5\x4b\x7e\xbb\xa9\xd3\x0a\x99\xea\xd3\x5b\xaa\x5c\xf0\xd2\xd9\xbe\xd2\x2b\x8e\xd8\xfd\x6e\x84\x98\x4b\x80\x9f\x34\x80\xc2\xa8\x8b\xe2\xde\xcb\x30\xe9\x17\x49\x29\xc1\x9d\x8a\x93\x44\x13\x6e\x4a\xa4\x10\x34\x9e\x27\x5b\xc5\xda\x5a\xac\x4f\xac\x18\x17\xbf\xb2\xee\xd9\x85\xe6\x62\x62\xb8\x97\x77\xd3\xf5\xa4\xe9\x02\xf6\x26\x61\xfe\x8f\x31\xbc\x2d\x36\x24\x5c\x05\x75\xd6\xeb\x29\x4f\x56\x80\x21\xc5\x06\x96\xd7\x72\x2e\xd6\x62\x45\xe3\xcd\xcb\x93\xf7\x10\x35\xa2\x34\x69\x61\x59\xcb\x85\x01\x53\x27\x6c\x3c\x3e\xc1\x74\xce\x1f\x36\xc1\x76\x14\x09\xec\x90\x80\xa1\x77\xd6\xbc\x42\x1e\x8a\x7e\x14\xf6\xd3\x2c\x10\x70\x44\x2b\x36\xb0\xac\x65\xcf\x44\x89\xdc\xb9\x32\x3d\x59\x4a\x44\x5e\xbc\x35\xdf\xbc\x55\x36\x45\x89\x10\xb3\xff\x29\x84\x98\xcd\x7c\x12\xea\x82\x0b\xe8\xde\x7c\x78\xd4\xbd\x49\x15\x7b\xf3\xe2\xa4\x2a\xfa\x34\x8a\x74\x64\xae\x3f\x50\xb2\x7e\xd1\x3b\x72\xfd\x6c\x99\xe2\x8b\x71\x71\x56\xd9\xba\x8f\xc0\xbd\xdc\xdb\xe6\x9a\xf7\xb5\xc1\x29\x90\x78\x68\x37\xc4\x43\x2e\xd0\xe3\x0e\x34\x8b\x4e\x62\x46\xcd\x78\xa8\xae\xd8\x78\x13\x0a\x6b\x4a\x88\x60\x52\xf3\x61\xd2\x46\x1c\xb2\xb0\x82\x63\xe2\x10\xeb\x73\x04\xa5\x46\x42\xc9\x5e\x17\xad\x3a\x82\x29\xb5\x51\xad\x69\x65\x4b\x4b\xb7\x54\x91\x46\x94\x6b\x37\x35\x50\xb5\x3a\xc2\x2c\xdb\xfe\xcd\xb2\xde\x15\xd5\x5a\xdb\xb3\x44\xc7\xb2\xc3\x97\xd3\xb2\x2d\x7b\x9b\xa5\xf5\x5c\xc9\x3c\x66\x18\x25\x50\x17\x9a\x47\x5f\xe7\x98\x19\xe7\xc4\x9d\x66\x76\x4b\xf1\xa5\x21\x59\xeb\x87\x64\x6d\x3d\x2d\xc9\xa6\x70\x52\x8d\x20\x62\x80\xea\xc5\x21\xd6\x19\x90\x9b\x49\xe8\x27\x48\x6a\x07\xcc\x8f\xc7\x63\xa3\x8e\x65\x16\xdd\xda\x92\x02\x6c\xc9\xd3\x55\x56\x78\x2d\xbe\x59\x6e\xb3\xfc\x3a\xdf\xda\xf6\x88\x01\xcd\x5b\xcd\x27\xeb\x54\x5a\x7e\x65\xc7\x97\xf8\xb4\xe4\x7c\xc9\xbb\x95\x40\xb7\xd3\xd3\xad\x33\x4f\x37\xce\x8e\xf6\x5c\x91\x3a\x46\x4d\x58\x1b\x74\xd7\x94\xbc\x4b\x35\x7e\x82\xab\x10\xd6\x06\x25\xbe\xc1\x9e\xcc\x07\xc8\xcf\x03\x29\xf3\xad\x6a\x29\xbe\x55\x4a\x40\xcc\x3b\x7c\x6c\x5d\x9c\xa0\x2c\x1b\xaf\x95\x1a\xaf\xab\x3e\x9b\x5b\xee\xa5\x8d\x3e\x99\x9b\x2a\x53\xeb\x7b\x47\x9b\xcc\xe5\x9e\xb1\x5c\xb4\x5c\x91\x3c\xc0\x9c\xcb\x35\xee\x66\x0c\xb5\xa1\x55\x54\x0b\x1a\x4c\x2d\x68\x21\x00\x19\x22\xaf\xe5\xa2\x30\x85\x1d\xf5\x82\x69\x31\x5b\x5e\x6a\x49\x2c\x54\xeb\xa7\x8e\xbc\xe2\x4d\x29\xb5\xa4\xff\x57\x86\x8c\x7e\x3e\x48\xa4\xd0\x81\x93\x6a\xad\xd7\xcc\x80\xe6\x59\xd1\xd9\x00\xa1\x71\x50\x02\x18\xd0\x96\x86\xd1\x54\xa5\x52\x0e\xa3\xcc\xef\xde\x55\x26\x06\xd7\xa8\xf3\xbb\xec\x1c\xeb\xf1\x9a\x53\x1c\xde\xe5\xd0\x32\x84\x6c\xd3\xe0\xfd\x0a\xa3\x46\xd4\x89\x2e\xa0\xac\x35\x81\x0c\x61\x0f\x6b\x74\x6b\xf9\x50\xc4\x69\xf8\xfa\x21\x97\x86\x95\x24\x38\xab\x61\x78\xd0\x4c\xc2\x2d\x9f\xac\x19\x1e\xbd\x1a\x36\xc9\xbc\x95\x5a\x71\x23\x2f\xdb\xe2\x89\x76\x1a\x06\x4a\x41\xe8\xbc\x43\x6a\x84\x86\x81\x8d\x04\x6d\xae\xcc\x8d\xad\x86\x79\x5e\xfc\x0b\xcb\xcc\xcb\xd0\x8e\x9f\xc0\x9d\xb8\xfe\x8e\xeb\xca\x50\xd0\xfd\x55\x7d\xdb\xb7\xdf\xbd\x76\x5b\xb6\xb0\x8a\xe9\x2d\xbc\xce\x76\xcd\x5f\xb8\x60\x0e\xb3\xbe\x78\x27\xf6\xeb\x08\xb1\x2b\xe0\xfd\xab\x41\xcd\x68\x0a\x7d\xbb\x5d\x18\x25\x01\x04\x4d\x0d\x79\xc8\xf0\xb9\x13\xe0\xd1\x09\x26\xba\x53\x94\xf2\x8c\xe0\x85\xf2\x15\x52\x5d\x21\x6a\xf6\xca\x1e\x6b\x33\x41\x1f\x66\xad\xe4\xbc\x19\xcd\x9b\x9b\x58\xf5\x61\x97\x6f\xbc\xba\x60\x4a\x47\xb8\xa5\xef\xce\x47\x8e\x32\x17\x6f\xbd\x93\x7b\x5b\xb9\x79\xcf\xcd\x5b\xee\xd0\xdf\x73\xde\x73\x53\xe1\x15\xfa\x73\x78\xb8\xa1\x9e\x6c\x9b\x06\x6f\x66\x0c\x35\xa3\x1f\x17\x2b\x24\x90\x07\x6d\x76\x6b\x79\x77\x2d\xfa\xff\xc8\xfb\xf3\xf8\x28\xaa\xbc\x7f\x14\x3f\xa7\xaa\xba\xba\xab\xf7\xaa\xee\xea\x25\x4b\x27\x9d\x4e\xd2\x84\x26\xe9\xa4\x9b\x24\xb6\xac\x22\xa2\x22\x22\x22\x22\x22\x66\x04\x01\x15\x64\x57\x11\x91\x41\x45\xc4\x8d\x41\xc5\x05\xd1\x41\x06\x91\x41\x64\xb0\xaa\xd3\x44\x64\x5c\x50\x07\x70\x54\xe4\xeb\x30\xc2\xf8\x73\xdc\xc6\x71\x9c\x72\x18\x41\x67\x79\x44\x92\xca\xef\x75\x3e\xa7\xaa\xbb\x93\x00\xcf\xdc\xe7\x3e\xf7\x9f\x7b\xc7\x21\x40\x12\x52\x75\x4e\x9d\x3a\xe7\xb3\xbc\x17\xc6\x95\x50\x9d\x8e\xd3\xad\xe2\x9a\xbc\x23\x66\x59\xaa\xbd\xd4\x45\x5e\xec\xfc\x42\x36\xa2\x31\x72\x04\x55\xd2\xf5\x6c\x29\xac\xe7\x5a\xf3\xf8\xf1\x90\x87\x98\x75\x88\xc0\x14\xf1\x4b\x59\xbb\xcf\x06\x85\x9e\x32\xf2\xca\xdb\x8c\xbe\x74\xfe\x89\x8a\x3d\x8f\xa5\x82\xa4\x7d\xcf\x67\xf9\x97\x1e\xab\xf9\x2c\x53\xe0\xbe\xe8\x31\x16\x0e\xdc\x2e\x86\x3c\x50\x84\x18\xb4\x02\x21\xf6\x31\x78\x97\x23\xf9\x18\x82\x9c\xb3\x10\xca\xa8\x25\x2e\xed\x34\x07\x6e\x45\x52\x71\x1f\x56\x23\x1e\x4d\x41\x95\x87\x45\xf3\xe4\x8d\xf4\x38\x6e\x2b\x4d\x0d\x38\x9c\x81\x82\x9e\xea\x95\x40\x10\x1f\x8e\x5d\x92\xbc\x58\xe4\x20\xa5\x49\x79\x4a\x44\x49\x15\xc1\x03\xba\xe7\xcb\xdb\x7b\x39\xac\xe8\x31\xc8\x87\x7b\xac\x84\x9e\x67\x73\xd1\x0a\x20\xcf\x9d\xf2\xec\x17\x21\x09\xb8\x0b\x97\x9c\x8a\x69\x1f\x3f\x15\xd3\xbe\x5f\x2f\xa6\x7d\x87\x57\x0e\x95\x94\x57\x54\x1b\x5c\x7b\x80\x7c\x9e\x8e\x03\xd7\x27\xc8\xeb\x43\x7b\x9b\xd8\x37\xe2\x3b\x15\x59\xfb\xd2\x5e\x11\x20\x62\xd1\x2a\x83\x77\x2f\xa0\x08\xea\x87\x7e\x52\xac\x1d\xed\x15\x34\x78\x11\x15\x7f\x1a\x10\x41\xf6\xc3\xc5\x86\x70\xb2\x87\x82\x83\x5c\xf9\x0d\xc7\x27\xee\xe4\x2d\x65\x15\xd1\x5a\x5a\xbe\xce\x86\xab\x29\xc0\xd0\x6b\x6a\x49\x17\xef\x35\xec\xa9\x58\x6c\x85\xb0\x7a\x95\x39\x20\x67\x6f\xde\x1a\xbe\xad\xcf\x8b\x7a\xf2\x85\x3e\xcc\xeb\x8b\x0b\xef\xaa\xa9\x8d\xb0\x0c\x49\xa8\x12\xdd\x79\x0a\x5e\x63\x24\xa9\x06\x78\x2d\x1b\x01\xbd\xce\x88\x0f\xd4\x3b\x7b\x3a\x4c\x29\x95\x64\x71\x16\x8e\x57\xa3\x54\x52\x78\xbe\x4a\x09\xf9\x06\x7a\x2e\x83\x66\x7d\xa5\x8f\xca\xd2\x97\x88\x59\x6f\x00\x98\x8e\x61\xf0\xc9\x3b\xf5\x33\x2e\x5e\xab\x7d\x1e\xee\xc1\x1e\x6b\xf5\x54\x04\xeb\x48\x51\xda\x98\xd7\x52\xa0\x79\xe3\x7d\xa7\xd1\x52\x38\x4d\xba\x18\xcb\x0b\x2c\x54\xa5\x14\xb6\x38\x59\x34\x54\xa9\xca\x52\xaa\xc3\x93\x4f\x16\xab\xc9\xaa\x36\x92\x45\x41\xcc\x4a\xa1\x4a\x80\xfb\x4b\x59\x97\xa7\x24\xf3\x1f\x51\xaa\x8b\x47\xde\x87\xa3\xb8\xac\xc7\xc8\x4f\xc1\x99\x2e\x29\x1a\x38\x83\xda\xf4\x41\x5c\xd0\xf2\x2e\x8a\xa3\x46\x74\x2b\xca\xd6\x22\x6a\x7d\x9f\x95\x8c\x5e\x42\x7b\xa0\x56\xb2\x25\xa0\x2c\xe6\x39\xac\x96\x79\x34\x12\x2e\x58\x71\x42\x8d\x79\x34\xb2\xc5\xa6\x48\x9c\xe0\x11\xa5\x76\x67\xbf\x44\x23\x44\x93\xe2\x4b\x9c\x43\x0a\x57\xd6\x0e\x48\x52\x63\x5c\x35\x10\x05\x55\xd0\x5a\x0a\x81\x0b\x88\xed\xd8\x53\x16\xab\x0e\x66\x54\x29\x0c\x95\x95\x22\x14\x5c\x03\x8e\x37\x30\xcd\x03\xab\xc9\xf8\xc0\xf2\x9a\x97\xfd\x11\x1c\x04\xb5\xda\x58\x95\x0f\x7a\x7a\xbc\x35\xd6\xf6\xe8\x81\xcb\x67\xce\x69\xbc\x7a\xcd\x3d\xf7\x8c\xc3\xd6\xbf\x2e\x3c\xb8\x60\xfa\xcd\x4f\x8e\x9e\xd4\x56\x7b\xd9\x53\x07\xd6\xe9\x5f\xea\xdf\x9c\xef\x89\xdb\x70\xc9\x45\x57\x65\x47\xe2\xca\x11\x2d\x63\x2f\x4e\x9c\x3b\x74\xe4\xb0\x9b\xd6\x5f\xf7\xe6\xa7\x2d\x4d\xdf\x35\xd6\x8e\x1f\x51\x37\x24\x33\x7a\xda\xde\x35\xfb\xfe\xac\xcf\x6a\x7a\x65\xb8\x7f\xeb\x83\x94\xf7\x30\x88\xdd\xce\x2d\x42\x35\xa8\x01\x2d\x44\x59\x99\xcc\x45\x99\x59\x39\x00\x67\x0e\x10\x9a\x50\x42\x29\x53\xa4\x89\x04\xd7\x92\x8f\xaa\x49\x38\x90\x28\xb5\xc7\x6a\xeb\xa0\x84\x1c\x11\x5f\x62\x05\xb7\x5c\x66\x60\x1d\x25\x29\xcb\x7b\x2c\xf4\x9c\x91\xc1\xfc\x11\x3c\x3a\x78\x29\x4c\x9b\x09\x14\x19\x43\x5d\x48\xc9\xb0\x65\x7f\x20\x18\x61\x0c\xb7\x60\xd0\x1b\x35\xe6\x26\x3f\x05\x53\xbe\xfe\xfd\x3b\xaf\x4f\x99\xf0\xc8\x98\x55\x57\xac\x5d\x71\xdb\xd9\xc7\xbe\xbd\x6d\xfb\x45\x97\x7f\x78\xe9\x96\x01\x37\x4e\xbe\x73\x49\xeb\x3b\xe6\xf8\xd9\x41\x8f\x3d\x3b\xe9\x8f\xd5\x0d\x17\xd6\x0d\x1e\xd4\x3c\xe5\xd6\xcb\xb6\xe7\xa2\x95\x9d\xfd\x5a\xae\xa9\xae\xcf\xd4\xb6\x4c\x59\x7c\x72\xa1\x39\x7a\x32\xfe\x3a\x7d\x10\x78\x09\x58\x91\x17\x8d\x42\x59\xde\xf4\x8b\x31\x2c\x05\xb0\x22\x02\x28\x10\xbc\x04\xf8\xbc\x97\x00\x0f\x5e\x02\x3c\x12\x12\xc0\xa2\xb3\xf0\xa2\x94\x75\x38\x3d\x99\xfc\xe6\x4c\xfe\x63\xcd\xfb\x06\x23\x01\xfd\x9d\xa4\x79\x83\xd4\x4a\xe0\xe4\x18\x2e\x77\x62\x53\xf1\xbd\x24\xf5\x41\xe0\x8b\x21\xa3\x08\xba\xd9\xf0\xfc\x72\x0a\xda\x99\x2c\x32\xe0\x60\xf4\xe7\xbd\x31\x04\xbf\x69\x4f\xa8\xb8\x53\x59\x3f\x38\x65\xf8\xc9\x5d\x82\x74\xbf\x5f\x94\xda\x99\x40\x98\xf6\x35\x9c\x62\x71\xfd\xee\xd4\x5e\x18\x86\x45\x43\xfe\x01\x14\x3b\x61\x2c\xdc\xf2\xd2\x2f\x67\xe7\xa7\xbc\xc8\x0b\x83\xfa\x34\xfc\xf8\x89\x39\x32\x8c\xda\xba\x8f\x72\x47\x2c\xef\xa2\x5a\x34\xcb\xd8\x55\x03\x82\x91\xcb\x54\xdb\xb5\x5c\x79\x99\x97\x75\x81\xef\x30\x9c\x89\x21\x7a\x7c\x44\x0d\x83\xe1\x6c\x14\xa6\x3d\x5a\x46\xbd\x61\x91\x1a\xf0\xd2\xb0\xb4\x4c\x54\x5d\xbe\x4c\x46\x29\x37\xfa\x19\xd5\xa2\xca\xd7\x52\x6f\x79\x6a\xf0\x5f\x9d\xa6\x0e\xd4\x32\xbc\x4a\xd1\x4a\xf0\xf9\xaf\xa4\xe8\x4c\x33\x44\xb7\xb6\x2d\xc3\xa1\x17\x8e\xe1\xf2\xb7\x5f\xf8\xed\x11\xfd\x65\xfd\x33\xfd\xb5\xb7\xda\xba\xe6\xe2\x05\x7f\xff\xeb\x7d\x4b\xff\xfa\xfb\x95\x2b\xdf\xdf\x63\x49\x5c\x76\xf1\xdb\xcf\xae\xde\x15\xe6\xfd\x1d\x8f\xbc\xf3\xcd\x25\x98\xab\x4f\x1f\x99\x7a\xfd\xf7\x93\x66\x5e\x74\xe5\xe2\xbc\x0e\x7d\x13\xb7\x08\xc5\xd1\x34\x94\x0d\x62\xaa\x1d\xae\xd4\x00\xaa\x14\x3c\xc4\x6d\x14\x7e\xcf\x43\x9a\x1a\x95\x35\xb5\x44\xd4\xb2\x7c\x09\xac\x21\xbb\x00\x89\x07\x52\xd9\x1a\x13\x59\xae\xa2\x68\x26\xa3\x38\xa8\xc3\x8d\x22\x8a\xaa\xbf\x04\x1a\xc0\xb0\x6f\x14\x63\x4c\xe1\x0f\xd4\xdd\x26\x4a\xdd\x6d\xe4\x3c\xe0\xd4\x7f\xe5\x9f\x6e\xd8\xb0\xe5\xad\x3d\xeb\x1e\x7d\xfb\xa5\x1f\x46\xef\xbe\x60\xf2\x1f\xb0\x70\xe4\xdf\x3f\x7b\xec\xd9\x5f\x3d\xac\x7f\xfb\xfa\xc9\x3d\x8f\x27\x9a\x57\x2d\xbf\x6f\xe9\x5f\xa6\xdf\xd0\x11\x8f\x7e\x32\xf5\xff\xbc\x74\xff\x73\x35\xae\xd0\x6f\x37\x3d\xf1\xe7\x25\xe3\x0c\x5c\xcf\x4c\xa8\x31\x94\xa0\x29\x46\xd4\x6a\xcd\x73\x35\x72\xac\x9d\x5a\x28\x19\x02\xd0\x08\x14\xff\x15\x26\x45\x36\x08\x5b\x1e\x2a\x05\x19\x87\x23\x2f\xfc\x64\x13\xdb\xdd\x12\x95\x35\xb3\x1a\xb2\x4f\x05\xd0\x14\xbc\x31\x7d\xc8\x1c\xcc\xb9\xb8\x59\x7f\xb7\xeb\xd5\x47\x7a\xd3\x38\xde\x62\x86\xfc\x38\x9a\x59\xdc\x75\x5f\x1f\xcd\x53\x03\xd7\x63\x7d\x1a\xc9\xa8\x1a\x4d\x34\xee\xdd\x95\x06\xfa\x06\x8d\xa5\x65\xea\x5e\x2b\xd3\xba\x8d\xcb\xc8\x17\x64\x24\x4a\x59\x3e\x00\xf4\x6a\xb7\x98\xb3\x0a\x25\x80\x64\x56\x5c\x52\xb6\x8c\x3c\x09\x03\x8a\x04\x18\xe6\x62\xdb\x5a\x80\xf6\x18\xc9\x43\x6f\x8e\x87\xd5\xea\x9d\xf9\xe9\xde\xf7\xf4\x83\xb9\x3b\x16\x7e\xda\x8b\xdf\x41\xdd\x6b\x7f\xbf\xaf\x2b\xce\xac\xfe\x7e\xc7\x5b\x5d\xdf\xf7\x64\x78\x60\xc0\x81\x5d\x0f\xbe\xe2\x63\x8a\x9c\xac\x28\x14\xcc\xcb\xf6\xf0\x53\x2c\x72\x5a\x93\xff\x47\x7e\x8a\xbb\x8e\x36\xd9\x46\xfe\xf9\xc1\x3f\xff\x43\x7f\x77\xd9\xca\xad\x4f\x59\x3a\x5e\x99\x39\xa7\xeb\x6f\x3f\x26\x2d\xf7\xac\x7b\xf2\xf7\xdf\x75\xfe\x68\x70\xe4\x2c\x63\x79\x3f\x8a\xa0\x04\x9a\x86\x14\x5f\x52\x75\x0b\x1a\x40\x49\x0d\x17\x31\x59\x53\x2a\x28\x54\xce\x96\x3f\x2e\x6a\x24\xf2\x2a\x28\x7c\x1a\x7a\xf1\x72\x85\x28\xe5\xd8\x92\xb2\xaa\x3a\x32\xb3\x35\xa2\x6a\x01\x89\x4a\xb7\x8f\x62\x7c\x05\x31\xe7\x0d\xd1\x2f\xf6\x04\x8f\xe6\xcd\x78\xc5\xe6\x81\x2d\xad\xa7\xb0\xc8\x37\xe1\xa3\x99\xf4\xc0\x21\x43\x97\xe9\xdb\xed\x6c\x6f\x18\x69\x31\x74\x74\x5e\x66\x84\xfc\x4d\x05\xbe\x61\x4c\xeb\xcc\x44\x0f\x10\x29\xac\x9f\x39\xdd\x47\x2d\x39\xd0\x3f\xaf\xca\x63\x47\xcb\x59\x0d\x26\x5e\x71\xa7\x73\x8e\x68\xc8\xea\x4a\xa8\x0e\x36\xef\x5b\x45\xf5\xce\x14\x01\xf6\x2c\x19\x4c\xd1\x05\x19\x24\xd0\x0c\xa4\xa0\x52\x41\xbe\x24\x07\xa9\xa7\x95\xc0\x83\x58\xa1\xe2\x12\xb3\xa1\x72\x50\x06\xf1\xd2\x12\x03\x2d\xb4\xc8\xd4\xc0\x93\xf5\x19\x98\x8d\xd6\x06\x3c\x04\x47\x65\x6f\xb4\x52\x6c\x8e\x92\xb7\x9c\x13\xfd\x50\x7f\x21\x9f\xf1\x46\x2b\xe7\x3c\xf8\xd0\xc2\xeb\x70\x33\xae\xc7\x75\xb8\xe5\xba\x9b\x70\x44\xdf\xac\xef\xd2\x77\xe9\xcf\xe1\xf3\x70\x1b\xfe\x89\xfe\xac\xbe\x11\x77\xae\xfe\x78\x70\xe6\xe5\xa7\xee\x5b\xa5\x7f\x85\x4b\x57\xad\x5a\xfb\xc6\xa0\x5b\xf4\xdf\xeb\xfa\x51\x2c\x62\x56\x3f\x8e\xbd\xd8\x9b\xf7\x69\xe4\xb6\xf3\x7e\x54\x8e\xe2\xe8\x36\xc3\x69\x25\x6a\xd7\x94\xda\xa4\xea\xb0\x93\x81\x29\x9e\x34\x6c\x66\x14\x55\xae\xd8\xbc\x4a\x84\x0c\x0d\xc9\xd0\x35\x8d\xc8\x80\xee\x33\xcb\xa1\x31\xf2\xa5\xa0\x4c\x99\x45\x00\x3e\x67\x80\x10\x40\x39\x22\x0a\x84\xbe\x48\xad\x8d\x9a\xbe\xde\x0e\x51\x65\xfc\xb4\xc0\x52\x43\x07\x6d\x20\x43\x61\xd8\x64\x6f\x43\xd1\xaa\x06\x5c\x93\xf7\x8e\x9b\x82\x7d\xf3\x66\xe2\xa6\x89\xd3\xae\xbd\x02\xa7\x6e\x5c\xb8\xea\x51\xfd\x0f\x7a\xd7\xa6\x1f\xef\xc3\xad\xb7\xdc\x7e\xfc\x96\xdb\x8f\xe3\x4e\x7c\xf6\xc2\xf4\x6f\x5e\x78\xe7\x9d\x67\xee\xbf\xe7\x17\xef\xbd\xf7\xec\x6f\x07\xb6\xfc\x7e\xc3\x09\xfd\xab\x3b\x8e\x6f\x59\xfb\x33\x1c\x5b\xfb\x28\x62\x50\x93\xee\x07\x6f\x0e\x01\x05\xd0\xb5\x46\x9f\xc8\x0a\x42\xf7\x59\x8e\xa1\xaa\xb2\x8a\x3f\xa9\x3a\xed\xd4\x3f\xd9\x7d\x58\x15\x7d\x9a\x62\x4b\x65\xdd\x90\xa8\xbb\xc9\x01\x1b\x22\x23\x76\x9b\x35\x77\xd5\xe9\xa7\xc1\x2e\x98\x0b\x29\x56\x48\x49\x39\xd6\xd4\x8f\xcd\x43\xd5\x2d\xe0\xc6\x6e\xc0\xee\x9b\x0a\x20\xf5\xae\xaf\x07\x0d\x5e\x8a\xe3\x2f\x3d\x3f\xfd\xf2\x02\x3a\xfd\x4b\xdf\x36\x3c\x46\x5f\xa5\xbe\x19\x46\x18\xb5\xea\x75\xe0\xe5\x21\xa3\xab\x8d\xa8\xcd\x6a\xd3\xb2\x1c\x39\x7c\x58\x9b\x06\x38\x5f\x5e\xc3\x4a\x80\x46\x07\x21\xad\x38\x18\x08\x1a\xc1\x80\x71\xaf\x26\x6c\x57\x06\x9f\xf8\x53\xdc\x2b\x20\xb4\x7b\xf8\x62\xb5\x16\x10\xd9\x8f\xae\xb9\xfa\xfc\x81\xc9\x74\xda\x00\x5f\xeb\x8f\xaa\xcf\x96\x7e\xe8\x4b\x8f\x5c\x91\xe7\xa0\x5b\x56\x5a\x67\x22\x2b\x72\xa1\x00\xba\xb1\x77\x7f\xde\x56\xa4\x91\xa1\x7a\xb9\xbc\x41\xb5\x01\xd2\x20\xeb\x48\xf2\x02\xe9\xc6\xc4\x6b\x90\x89\x76\x5b\x45\x29\x8b\x79\x5b\x86\x36\xd4\x9c\x19\x85\x93\xb2\x8c\x45\xa0\x7b\xb4\x0d\xb4\x53\x8b\xe4\x09\x0c\x69\x02\x43\xf4\xb3\x27\x4a\x03\xfa\xec\xf7\x50\xd5\x53\xa3\xdb\xce\x5c\x43\xc5\x08\x6e\x35\x75\x4e\x69\x9f\xdd\x0f\x58\x8c\x04\x7a\xb2\xb8\xcf\x5e\xda\xa3\xcf\x5e\x99\xef\xb3\xf7\x54\x3a\x0d\xcb\x60\x72\x11\x29\x74\xd2\xe3\x9e\x88\x2d\xa1\xc6\xbc\xa0\xcd\x16\xf7\x52\xa0\x52\x38\x8f\xcd\x88\x81\xfe\x40\x5c\xca\x5a\x9d\xe0\xbc\xe8\xa1\x46\x44\x95\xff\xc3\x76\x7a\x11\xb7\xdc\x9c\x85\x53\xc2\x02\x33\xb4\x7b\xde\x0c\xd3\x71\x8a\x1e\xfa\x56\x53\x67\xe0\xa3\x22\x0d\x60\x3f\xc7\x80\xa6\x7b\x04\xdd\x63\x74\xa5\xfa\x34\x5a\x95\xb2\xa4\xea\x71\x6b\x39\x8b\xcd\x8f\x4d\x90\x5f\xc5\x7f\xd3\x5a\x55\x04\x4a\x3f\x0b\x87\x34\x1a\xbd\x92\xd3\xd9\xe9\x8b\xc0\xbe\x21\x66\x3d\xfe\x32\x9a\x2c\x1b\xf2\x8a\x7e\x0f\x89\x32\xc2\x06\x48\xb8\xd0\x5a\xa5\x79\x44\xbc\x35\x6d\x35\x6c\x0a\xe2\x45\x0d\xd6\xae\x79\xa5\x57\x85\x2f\xd8\x32\xf6\x8d\xd2\xd1\x93\x9e\xd8\x30\x76\x64\xa1\xc3\xaa\x7f\x60\x75\x0f\xbd\x2c\xbc\x7e\x48\x68\xc6\xf0\x3b\x16\xca\x28\x8f\xab\x9f\x06\xfa\x35\x71\xd4\x80\x7e\x41\xfb\xac\x3d\x78\x86\x03\x78\x88\xfb\x42\x6e\x2d\xd7\x8f\x76\x5c\xfb\x15\xb4\xfa\x6c\xb2\xa6\xf4\x4b\x91\xed\xb1\x8e\xb6\xda\xdb\xab\xf8\x3a\x5b\x42\x2d\x09\x69\x4a\x49\x52\xad\x32\x14\xfa\x6c\x00\xae\x8d\x83\x87\x5d\x2e\x54\x56\x5e\x03\xc9\x55\x9d\xb4\x93\x95\x1c\x91\x8a\x01\x24\x89\xe4\xab\x8c\x6c\x19\xa9\x52\x48\x94\xda\xe5\xb2\x0a\xb0\x71\xb0\x95\xd3\x98\xbe\xdf\x19\x9a\xad\xa7\x98\x91\x33\xb6\x5c\x71\xb2\xe7\x1c\xb9\x4e\xdf\x74\xed\xfa\x75\x8f\x49\xe3\x56\x42\xe7\xd5\x42\xfb\x19\xb6\x3a\x83\x97\x58\x83\x9a\x4c\xae\x6a\xc1\x8b\xd9\xc7\x92\x37\x41\x49\xa6\xd5\x72\xbb\xa6\xd4\xa5\x80\x9c\x68\xc9\x6b\xcb\x16\xc8\x89\x4a\x20\xa5\x56\x86\x34\xa5\xd2\x0b\x31\xdb\x80\x90\xa6\x0c\x28\xf0\x14\xd3\x38\x01\x42\x9b\xed\xac\xc7\x27\x90\x19\x11\x07\x18\x35\x25\xa4\xfa\x3c\xa7\x6e\x62\xf4\xa0\x23\x9e\x4e\xdc\xef\x0c\xa4\xc4\xe8\x69\x44\x10\x4f\xc7\x4c\x64\x9f\x3c\xa5\x14\x22\xb2\x18\x7d\x8e\x23\x06\x37\xb1\x0e\x35\xa3\xa5\x46\xaf\x23\x6a\xd7\xb2\xb2\x21\x22\x55\x4a\x45\xa4\x68\x6b\xdf\x4e\x29\x8a\x96\x3c\xbd\x3c\x22\x6b\xed\x52\x04\xd9\x48\xa0\x02\xea\x2e\x11\x68\xde\x93\x68\xbc\xbd\xd1\x5a\xdd\x57\x4f\xaa\x3f\x59\x40\xac\x3d\x4a\x6b\xfe\xf1\xe8\xe9\xdb\x61\xbd\x04\x70\x0a\x6d\x8e\x62\x38\xf2\x29\xf8\x88\xf9\xc9\x99\x69\x76\x3c\x70\x43\x7e\x96\xfa\xb4\xc6\xd6\x15\x66\xa7\x2b\x6e\x74\x3f\x98\xb9\x3d\xf4\xb6\x8a\xd7\x53\x3d\x6a\x42\x4f\x9d\x6a\x35\xf5\xcf\x5b\x62\x46\x53\xed\x91\x70\x7f\x5b\x22\x57\x43\xff\x1e\x48\x29\x0d\x49\x35\xd9\x67\x75\x05\x70\x22\x57\x4f\xeb\x58\xf5\x5e\x35\xda\x03\x27\x5f\xbc\xc0\xea\x03\xa2\x94\x0d\x36\x24\x33\x40\x85\xdd\x29\x78\x7c\x61\x16\xfa\x44\x55\x92\xda\xd8\xf4\x9f\x2d\x35\x12\x7e\x47\x18\xf2\x56\xa6\xc9\x0e\xdd\xc0\x90\x2c\x8e\x6d\x8e\xca\x67\x58\x68\xa2\x30\xef\xea\xc6\x4b\x46\x0e\x2e\xaf\xab\x15\x96\x39\xe6\x5d\x9d\xb8\xf8\xbc\x21\x65\xfd\x6b\x9d\x73\x98\x2d\xa7\xa7\xc1\x5e\x39\xfb\xce\xb2\x68\xe9\x80\x01\x0b\x6f\x2b\x8d\x96\xd5\x25\xf1\xf0\xd7\x5e\x43\x85\xde\x2a\x59\x6b\x35\xb0\xd2\x9e\x34\x56\x5a\xbd\x5d\xcb\x8a\x0c\xb8\xe9\xe7\xaa\x60\xbe\xda\x03\x62\x95\xcd\xdc\xe6\x14\xb7\xb1\xf2\xd2\x34\x26\x8c\x5b\x7a\x08\x1b\xd4\xa4\x94\xfe\xc5\x6d\x36\x43\xe8\x20\x4c\xdb\x6c\x25\xb4\x18\x08\xab\xce\x2d\x4a\x59\x4f\x6d\x9c\xaa\xe2\xb5\xb3\xa2\x1d\xe8\x65\x25\x92\xda\xaf\x8e\xcc\x60\xba\xfe\x4c\xbd\xb6\x53\xce\x1c\x3e\x7d\xe3\xed\xd7\xa7\x9f\xb9\x02\x5b\xf6\x14\x6d\xb8\xbe\x73\xd7\x19\xca\x37\xe4\xcc\x3e\xed\x4c\x58\x87\x91\xbc\x1e\x72\x8f\x55\x58\x9e\x54\x43\x5c\xfe\xb4\x2b\x2c\x34\xb5\xc4\x0b\x1e\xbe\xe6\xba\x22\x27\x5c\x49\xa0\xb0\x71\xfd\x27\x6b\xc8\x3c\xca\xcf\xb0\x64\x0e\xc0\x49\x7e\xfa\xd5\xd1\x9d\xf7\x20\xa0\xeb\xc1\x0f\xd8\x8e\xaa\xbc\xf6\xb1\x68\xf6\x58\x83\x76\x30\xee\x2a\xe3\xf2\x29\x4f\x81\x40\xaf\x46\xbc\xb0\xcd\x98\xec\x79\xb2\xdd\x44\x4a\xc8\x58\xc4\xa0\x1d\xc6\x12\x14\x4f\xf3\x34\x7b\x12\xe4\x8d\xf1\x9c\x96\x17\x3f\x8c\x8e\xe6\x74\x7c\x78\xe6\x97\x30\x1a\xae\xcf\x79\x33\xff\xd4\xa7\x0d\x1c\x35\xe6\x39\x53\xdb\xeb\x9c\x31\x0f\x19\xf3\x01\xc5\x7b\x30\xe0\x2b\xc5\x76\xc1\xe3\x63\x29\x01\xfe\x7f\x7a\xbe\x9c\xf9\x4c\xd1\x13\xff\xfd\x49\xb2\xee\xf5\xd7\x7f\x97\x57\xcc\xe2\xfa\x9c\x1f\xb7\x18\x4f\x51\xb6\x53\x09\xc2\x02\x40\xbc\xb4\xe8\xdc\xe8\xdf\x8b\xda\x6e\x2a\xcf\x99\xbc\xf6\x44\x0f\x5e\x7b\x75\x44\x94\xda\xed\x6c\xa9\x4c\x4e\x57\x6b\x28\x6f\xd3\x57\x2a\x9f\xe1\xe0\xe8\x45\x61\x3f\xd3\x61\x91\x7f\x1d\x67\x9c\xf1\x88\xc8\xbf\x87\x85\xa3\x81\xa1\xde\x94\xbc\x8e\x6c\xc8\x89\x5a\x51\xd6\x6a\xba\x66\x2a\x6c\x5a\x11\x92\xaa\x9d\x24\x44\x2e\x60\xac\xf3\xb2\x06\xb9\x05\x40\x71\x98\x0c\x52\x11\xfd\x43\x63\x93\x08\x72\x1d\x50\x8b\x8a\xca\x78\x1c\x4e\xe2\x26\x6a\x46\xb9\x8b\xd9\x62\xe9\xe8\xda\xc2\x4c\x06\x17\xca\x24\xdb\x79\xe8\x10\x89\x7f\x91\xee\xe7\x56\x5b\xb6\xa3\x00\x2a\x41\x29\xea\x42\xa9\xd8\xd2\x8a\x0b\x6c\x20\x94\x20\x34\x4f\xb0\x52\x9a\x54\xcb\x70\x02\xa9\x92\x8b\x06\x68\x48\x54\x39\x6f\x06\x2e\x67\x78\x4f\x46\x31\xd9\xcd\x68\x7e\x35\x0c\xc3\xc5\xc7\x1e\x2a\xb5\xf3\x8e\xca\x83\xf8\x7c\x3d\x7e\xce\x77\xbf\xb8\x64\x4c\xeb\x39\x97\x2e\xa9\x92\xf6\x33\x5b\xb8\xb6\xae\x07\xc6\xcf\xbf\xee\x2a\xe6\xe6\x93\xbe\x17\x77\x88\xdf\xbb\xae\x9d\xde\xca\x7d\x70\xe8\x10\x62\xd0\xd8\xee\x1c\xbb\x94\xf7\xc3\x8e\x34\xd3\xa8\x21\x87\xdc\x1a\x4d\xbb\xca\x93\xaa\xc3\x4d\x92\x78\xd8\x90\x8c\x0c\x3e\x00\x21\x69\x29\xc5\x39\x8b\x46\x1b\x95\xe4\xea\x59\xc6\x27\x53\x55\x26\xd5\x01\xcf\x38\x64\x98\xb7\x94\x8b\x2a\xe3\x86\x0a\x25\x34\x8f\x83\x2d\xad\x0d\x98\x64\xb1\xb4\xa6\x04\x21\x25\x6f\xf5\x05\x8c\xea\xe4\xd8\xe1\xfd\x45\x2b\x6e\x2a\x9b\x30\xe0\xae\x07\x77\xac\x7f\xf5\xb2\x60\xf2\x9f\xae\x85\xf5\x4d\xd7\x8c\x64\x96\x0c\x89\x2d\x1c\xc1\xdd\x77\xf2\x55\x29\x7c\xcf\x1d\x77\xdc\x7f\x6e\x6c\x12\xbe\x66\x61\x7d\xcd\x78\xa8\xe1\x75\xe7\xf8\x3a\x6e\x11\xaa\x45\x49\xf4\x8c\x51\xfd\xf2\x03\xb2\xd9\xad\x81\xa3\x7d\x11\x4d\xaf\x4a\xd0\x72\x0d\x6e\xbf\xd5\x95\x50\x1b\xdc\x79\x72\x6b\xad\x47\x53\x6a\xe9\x8a\x76\x80\xa1\x84\xe2\x00\x30\xb3\xe9\x76\xd5\x44\x62\x45\xa3\x48\x16\x11\x55\x6b\x18\x46\x94\x0d\x84\x20\xe3\x1a\x20\xaa\x6e\xd0\xa5\x6f\x20\x79\x87\x18\x28\xa5\x55\x41\xd5\x11\xc9\x90\x83\x5e\xa9\xc8\xa8\x56\xff\x29\x2c\x27\x7a\xcc\x41\x9c\xce\x8c\x51\x62\xc3\xe6\x8c\x6c\xd4\xea\xc4\xfa\x6d\x73\x5f\x7e\xad\x68\x4e\xd6\x90\x59\xba\xf8\xf2\x9b\xae\x63\x76\xd0\xd9\xe1\xda\xd6\x8c\x9d\xf8\xbb\xb7\xf5\x1f\xf2\x93\x33\x1a\xe6\x0b\x33\x94\x14\x88\xfd\x74\xaa\x10\x83\x92\xdd\x39\xf6\x69\xcb\x18\x70\x28\xd9\x6c\xa0\x3f\x2b\xdd\x1a\x6d\xd1\x9e\xa1\x79\x90\xab\x71\x4a\x9c\x2b\xa1\xd6\xb8\x69\xe5\xbd\x0c\xfa\x08\x2a\x17\x49\xa5\xb2\x42\x99\xd9\x49\xc8\x96\x41\xe5\xa0\xcc\x30\xdc\x8e\xe1\x44\xce\x43\x67\xb0\x1f\x49\xcb\xca\x44\xa9\x9d\xf1\x07\xc2\x06\x03\xdc\x09\x04\xc1\x4a\xc3\x6c\xbb\x46\x54\xc3\xe0\x45\x43\xd2\x54\xd5\x62\x13\x7b\xb7\x19\x4e\x35\x5d\xf9\x79\x32\xdb\x0d\x65\x13\x12\x77\xad\x2e\x9a\x26\xdc\x44\xa7\xc8\xe8\x3a\xe8\x93\x7a\x4f\xd1\xb7\x5d\x4f\xd1\xc9\xc1\xdd\xcb\x74\x3f\xfe\x80\x6b\x43\x2e\x54\xdf\x4b\x19\xc1\x9d\x57\x46\xf0\x90\x57\xf3\x8c\x8a\x08\x45\x12\x08\x45\xa2\x07\xc6\xb9\x69\x9d\x00\xfe\xcf\x75\xa8\x85\x64\xc0\x25\xe4\x45\x0b\xa4\xd5\x4a\xbb\xa6\xd4\xd3\x60\x49\xf1\xa6\xd5\xb8\x40\xa2\x76\x28\x96\xb6\xf6\xb2\x10\x50\xf8\x94\xda\xdf\xa3\x29\xf6\x94\x11\x2f\xa9\x3e\xd9\x20\x6b\x94\x8b\x52\xd6\xc2\x96\x50\x1d\x6a\xd5\x1d\xa2\x2a\xd4\x5e\xc8\x78\x2b\x4b\x68\x53\x2d\x6e\xd0\xee\x59\x29\x6b\xe1\x5d\x7d\x68\xf7\x7e\x6b\xba\x25\x9d\x92\x44\x2f\x8a\x55\xc6\xf9\x68\x15\xc2\xc5\xba\x60\x96\xa2\x9d\x59\x9e\xf2\xf9\xbe\xdf\xcd\x76\xb9\x70\xca\xe5\x9a\xfd\xbb\x7d\x9f\xeb\x7f\xfb\x47\x37\x5a\xbc\x44\xd7\x8f\xe9\xdf\xe1\xd6\xd9\x37\xce\x9f\x71\xe3\xbc\xa9\xf3\x99\x4f\xaf\x9b\x7b\xe3\xec\xf9\x53\xe7\xce\x61\x92\xd8\x83\x9b\xb7\xdc\x3e\x15\xcf\xd2\x1f\x3f\xeb\xb9\x2d\xfa\x7b\xfa\x71\xfd\x98\xfe\xfe\x2b\xaf\xe0\x24\xf6\x6f\xdb\xbc\x7e\x73\xf3\x33\x0f\xfe\xf2\xe5\xad\x8f\x3f\xfb\xc2\xf3\xbf\x7c\xf0\x99\x7c\x0e\x6d\x9d\xc0\x2d\xea\x35\x5f\xae\xb4\x5a\x29\x14\xe6\xcb\x6a\x4a\xe5\x2a\xfe\xde\xf3\xe5\xa7\x16\x31\x3e\x8f\xa6\xf4\x4f\x29\x3e\x3a\x5f\x76\x63\xbe\xfc\x64\xbe\xd8\x10\xcc\x97\x4f\x54\x3d\x16\x43\xb5\xdb\x6a\xce\x57\xd6\xe3\x05\xad\xea\xb8\xa8\xda\xe9\x9c\x99\xfc\xfc\x74\x65\xb0\x25\x9a\x42\xd4\x31\x28\x46\x2b\xe3\xc5\x75\xe6\x53\xce\x17\xf6\xff\x13\x75\xdf\xfa\x53\x6c\xfd\x3b\xb6\x7e\xb1\xf7\xc3\xeb\x5d\x2e\xfd\x7d\x17\xad\x3b\xb7\xce\x9f\x3a\xef\xc6\x19\xf3\xe7\xde\xc0\x7c\x4a\x66\xed\x86\xb9\xf3\x66\x32\x49\x2c\xe2\xf4\xab\xaf\xea\x87\x74\x8d\xcc\xd3\x73\xcf\x0f\xd4\xaf\xc1\x1b\xdb\x96\x3f\x87\x53\x58\x7c\xfe\x97\x3f\xfb\x79\xf3\xe6\xf5\x9b\x0f\xfe\xfc\x67\xbf\x7c\x7e\xdb\xe6\xc7\xb7\x1a\xf5\xb3\xee\x99\x96\x95\xbc\x1f\xb9\x91\x1f\x05\x4d\x9f\x2b\x85\x27\x07\x9a\xe2\x4c\xab\x32\x2d\x53\x0a\x20\x54\x20\xd8\x85\x84\xc2\x26\x01\x10\x4c\x22\x34\x2f\x44\x68\x56\x72\xce\x79\x35\x40\x05\x03\x3a\xc6\x91\x51\xac\xe2\x70\x01\xb3\x16\xbb\xd3\x23\xca\x01\x8a\xec\x57\xb8\x0c\x82\x1e\x7d\x3b\xb6\xf8\x82\x50\x80\x6f\xc2\xd1\xd6\x34\x0b\x35\xb4\x98\x2f\xc6\xfa\xd2\xbe\xda\x38\xef\x4b\xc7\x19\x0e\xcf\x8b\xec\x5f\x8a\xb7\xea\xd9\x59\xfa\xd7\x3b\xf6\xbf\xd8\x32\x6b\xd7\x88\x2d\x72\x20\x7a\xe3\xcd\xad\x96\x57\x26\xe9\x1b\x4e\x8e\xc5\x53\x74\x3b\xfe\x37\xd4\xd2\x3e\x39\xf7\xca\x3b\x74\xab\x02\x9a\x0c\x33\xb9\x0f\xa0\xb6\x5c\x43\x22\x4c\x28\xa0\x89\xac\x46\x8b\xac\x31\x56\x6b\x77\x06\x38\x5b\x02\xcc\x09\x69\x38\x16\x09\xd0\xc0\x2b\x82\x0c\x9b\x74\x31\x20\x4a\xaa\xbf\x94\x12\xae\x91\x2f\x52\x49\xdb\xed\x8a\x1b\x04\x70\x05\x07\x2d\x98\x4b\xd5\xe9\x54\xb0\x35\x6d\x0d\x04\xad\xb5\x71\x0c\x7a\x0b\xe4\x25\xb6\xc6\x5a\x6b\x99\x1a\x2f\xb0\xd4\x98\xc5\x5b\x70\xeb\x07\xe7\x8c\xac\xd8\x57\xdf\x70\xce\xf4\x89\x1e\xfd\xf5\xaa\xc1\xeb\x3f\xce\x7d\x7a\xd9\xa8\xd4\xbe\xf3\x9e\xd9\x82\x87\xcd\xc6\x69\x6f\xc5\x8b\x7b\x98\x8f\xfe\x8c\xaf\x78\xc9\x7e\xd9\x0a\x4f\xa4\xb3\xd6\xd2\x79\xad\xed\x62\xbd\xf3\x22\xe7\x23\xef\x8e\xc7\x57\x9e\xd4\xff\x71\x0b\xbb\x80\xd3\x4f\xd0\xba\xb9\x3e\x91\x6b\x82\x7d\xa0\x0a\x8d\x35\xc6\xe6\x36\xc3\xad\x4a\x3b\x3d\x74\x63\xe6\x4a\x86\x18\x19\x7c\x5d\xc3\x19\xa4\xba\xc9\xa8\x7c\xa5\x10\x57\xe6\x90\xd3\x21\x55\x18\xce\x3f\x36\x7b\x81\x6c\xe7\x4b\xb3\x81\xa0\x35\xce\x06\xc1\x91\x17\x82\x05\x36\xe6\xab\xc5\xfe\xa0\xcf\x8d\xa7\xe0\x32\x2c\x0c\xe8\xb7\xee\x37\x9b\xd3\xe5\x93\xc7\x7c\xe6\x97\x27\x3d\x7e\xd1\xe8\x27\x16\x35\x37\x3d\xbc\x7f\xcb\xf7\xb8\x35\xf6\xdb\x25\x8b\x98\x3a\x5c\x8e\xeb\x39\xfc\x9c\x3e\xd0\xe7\x3e\x5a\xde\xb5\x9a\x49\xa6\xf4\x93\xc9\x6a\x5e\x9f\x8e\x3f\xb8\x0d\xdf\xff\xc8\xc5\x4c\x13\xb3\x15\xfa\x99\x49\x84\xb8\x61\x96\x0e\xe4\x42\x13\x28\x77\x17\x8a\x79\x24\x72\xce\x21\xec\x64\x5d\x09\xc5\x92\x56\x91\x53\x53\xac\x29\xd8\x46\x9d\x87\x15\xa6\x40\xd6\x75\x9a\x07\x07\x2d\xe8\x65\x9d\x70\x7c\x38\x91\x90\x80\x8d\x96\xec\xfe\xe0\x60\x29\x53\x7b\xd7\xe4\x7d\xb8\xe5\xef\x7f\x67\x2e\xed\x5c\xc2\x4c\xd0\x99\xe9\x5d\x4f\x83\x5f\x35\x33\x01\x31\xa8\xae\x7b\x26\xf4\x22\x3c\x48\x42\x63\x0c\xc4\x9f\xd9\x9b\x57\x79\x31\x95\x82\xc5\xee\x4b\x2a\xf6\xc3\x8a\x9b\xde\x80\x37\x95\xb5\xc3\xf5\xec\xe4\x7a\x7e\xb2\xb1\x23\xbb\x28\x65\x1d\x6e\x2f\xb5\xca\xa2\xef\xbb\x18\x6d\x4d\x5b\xe5\x18\x16\xa3\xcd\x6c\x0c\x8b\x96\xd6\x58\x1d\xbb\xa3\x69\x73\x7a\xa5\xfe\x83\xfe\xce\x03\x9b\x71\x12\xb7\x4c\x9f\xce\xe5\x30\xd3\x36\x4d\xd7\x6d\x5d\x23\xe7\xe9\xff\xc5\x8c\x60\x9d\x90\x3b\x63\xb2\x87\x01\x66\xa2\x19\xcd\x43\x79\xa0\x84\x52\x99\x54\x4b\xec\x66\x36\xac\xf4\xcb\x37\xc0\x1a\x0c\xbc\x44\xab\xd9\x0b\xad\x4e\x03\xb1\xb7\x83\x15\xdc\x72\x68\x40\x8a\x62\x25\x76\xf2\x1e\x4b\x49\x19\x95\x84\x2f\xa9\xa4\xd2\x63\x00\x97\x28\xab\xfe\x6f\xe0\x12\xd6\x40\xb0\xc0\xdf\x6d\xc0\xf1\x06\x9c\xc4\xc5\xf0\x89\x5e\xa8\x89\xf7\xdf\x2f\xf3\x55\x4f\x38\x7f\x54\x6b\x74\x56\x72\xda\x3d\x53\x33\xf1\xf3\x87\xa7\x0b\x20\x8a\xde\xd8\x89\x67\xda\x9d\xb5\x03\x2e\x3d\xc7\xf7\xad\xd3\x73\xf6\x4d\xf7\x4f\x1d\x57\x16\xfa\xa1\x80\xa4\x00\x4f\x71\xdd\xcf\x7e\x0d\x1e\xbb\x03\x51\xa1\xfd\xe0\x4b\xaa\x2e\xea\x45\x4d\x25\x70\x5c\x3e\x4a\xc1\x65\xc5\xac\xd5\x03\x82\x09\x5c\xcf\xf6\x02\x00\x5e\x0a\x24\xe4\x06\x1c\x33\x5a\x0c\x5d\xdf\x4d\xbc\xab\xb1\x71\xf2\xf9\x17\x0e\x8e\xcd\x6d\x7a\xf2\xf5\xc1\xd5\x33\x26\xd3\x4e\x43\xab\xff\x96\x85\x0b\x26\x91\x1b\xbb\x7f\xc7\x75\x17\xc3\x73\xe1\x11\x62\x37\x5b\x0e\x20\x1f\x79\x03\x61\xb5\x00\xc8\x52\xb4\x6b\xed\x3e\x3b\x63\x4b\x80\x5b\xa1\x9d\x82\x25\x04\xda\x5c\xb0\x78\xa8\x45\xa1\x60\x17\x25\x95\x81\x28\xd7\x47\xfe\x68\x71\x67\x32\x2a\x23\x8a\x26\x96\xc0\x80\x12\x40\x90\x4b\x81\x03\xfc\x67\x9f\xfe\x01\x0b\xb9\x37\xf4\x83\xb9\xd7\x17\x4d\x5a\xbd\xc5\x32\x6e\xd9\xd1\x3d\xcf\x77\x4e\xed\xfa\x8a\x79\x7a\xc8\xeb\xb7\x5f\x3e\x77\x5a\xfe\x9e\x36\x42\xcd\x78\x14\xca\x3a\xc8\x3d\xc1\x82\x01\x8f\x38\x39\xa9\x38\x0e\x9b\xaa\x3b\x1e\x30\x80\xa3\xbd\x5b\xbb\x43\x94\x54\x16\x22\x29\x89\xfc\x91\xf7\xd3\x82\x3f\x32\xf1\x8a\x14\xd7\x50\x74\x33\xd3\x3f\xba\xe3\x30\xb6\xbe\xf4\x8a\x7e\xb0\xfd\xb5\x45\x93\xee\xdb\xc2\xfe\xbb\x75\x94\xf6\xd6\xaf\x4e\xb4\xbd\x85\x47\x0e\x79\x65\x19\xb9\x1b\x16\xf9\x11\xe2\xfe\x69\xe9\x40\x3e\x54\x81\xfa\xa1\x27\x8c\xec\xc0\x6f\xee\xc0\xfd\x9c\x5a\x0e\x61\x91\x73\x25\x94\xb2\xb4\x8a\x2c\x9a\x12\x49\xe5\x2a\x4b\xc9\x27\xc8\x0e\x06\xd8\x3e\x1f\xbc\xea\x7e\x59\x53\x4b\x2b\x53\xa9\xac\x1f\x58\x31\xfe\x88\x90\xc8\xfa\x00\x7a\xe2\x23\x51\xa2\x9f\x26\x8f\xee\x80\xa6\x54\x57\x1e\x16\x55\x2b\xf5\x0d\xa5\xe9\xa2\xa1\x52\x0e\x09\x65\x28\x93\x51\x2b\x4b\x4d\xae\x7b\x3f\x51\xb1\x66\x8c\xed\xa1\xb2\x08\xb9\x11\x8b\x8a\x16\x38\x74\xa3\x31\x99\xec\x1a\x26\xfc\xc1\xbf\x19\xef\xc7\xad\x38\xbc\x74\xe6\x03\x4b\xf5\xcf\x7e\xe8\xfa\x04\xb7\xbc\x73\xc7\x6d\x7a\xe7\x1e\x4d\xcb\xfd\x74\xc1\xd2\x95\xcf\xe2\x29\xfb\xd9\xb5\xea\x1b\x2b\xb6\x8a\xf6\x8a\x6d\xab\xdf\xfe\x1c\x4f\x99\x32\x6d\x46\xc7\xe4\xfd\x4c\x70\xec\xe4\x09\x17\xd2\x7e\x27\xea\x3e\xca\x3b\x2d\x1d\x90\x2f\xcd\x35\x66\xc4\xe4\x51\x28\xd6\x74\x0e\x23\x91\x75\x25\x54\x47\x79\x3a\xad\x62\xa7\xa6\x5a\x84\x54\xca\x00\xdd\x90\x99\x08\xd0\x4d\xcf\x1f\x30\x9b\x6b\x4a\x00\x70\xd6\x24\xa6\x73\xc9\xd0\x24\x74\x41\x24\xed\x72\x18\x28\x9c\xb2\x00\xb4\xba\x51\x63\x93\xd8\x6c\x62\x1f\xd2\x72\x4c\xa6\x08\xbf\x21\xd8\x62\x76\x3c\x77\xe0\x66\x66\x14\x6e\xde\xb1\x23\x6f\xa6\x02\x78\xbf\xae\xdd\xcc\x16\x9d\x91\xba\xbe\x25\xbf\xf4\x4d\x00\xec\x3b\xb9\x61\xde\xf3\x1b\x9e\xd9\x36\x07\x61\x28\x24\xa7\x2d\x1d\xc8\x99\x57\xaf\x34\x7a\x6d\x90\xfa\x1a\xf2\x9a\x4e\xa3\x9d\x66\x64\xc1\x9c\x53\x94\x54\xcc\xe4\x01\x0e\x36\xb3\x79\x86\x1b\x70\xdc\x8d\xad\x18\x1f\xc7\xe3\xf1\x77\xfa\x7e\xfd\x98\x7d\xb0\xe0\x4c\xbb\xf4\xbf\x59\x3a\x7e\x1c\xcd\xce\x2b\x3f\xde\x32\xf4\xd3\xba\xce\xb5\x88\x45\xbb\xba\x67\x72\x0c\x78\x0f\x93\x4c\x58\x33\x74\xb3\x7c\x69\xd5\x65\x68\x3e\x90\x33\xa3\xc4\xa9\xa9\xb6\x70\x2a\x95\x0b\x06\xbc\x80\x79\x96\xd3\x69\x35\xe8\xd4\x54\x21\x64\x6c\xe6\xa5\x79\x38\x43\x30\x95\xf5\x43\x57\xc8\xef\x01\x08\x70\xfb\x70\x3f\x99\x42\x32\xb7\x2d\x25\xbb\x87\xfc\xff\x8e\xad\x46\x72\xc2\xae\xb0\x0d\x6e\x45\xda\x63\x51\x2d\xe5\x27\xdc\x8a\xb8\xc7\xa2\x88\xde\x76\x9b\x68\xf1\x25\xda\x05\xf8\xe8\x84\x8f\x2e\xf8\xe8\x25\x1f\x15\xc9\xdb\xee\x93\x58\x5f\x82\x6b\xf7\x93\xdf\x2c\xed\x32\xf9\xad\x3d\x04\x1f\xc3\xe4\x23\x8b\xb2\xa2\xe4\x6f\x68\x68\xc0\xc3\x5d\xac\xc5\x26\x38\x5d\x5e\x51\xf2\xc9\xa1\x70\x43\xf1\xff\x94\xe1\x25\x14\xbe\xd2\x9a\xb6\xa6\xe5\x18\x4b\x7e\x45\xc5\xa8\x35\xd6\xea\x6b\x8d\x35\xa7\x7d\xb1\x5d\xcc\x05\xe1\xdf\x84\x86\x2c\x1f\xbf\xfd\x6f\x53\xf1\x02\x7d\x6c\x7c\x6f\xfc\xda\x61\xc3\xee\x1c\x7f\xc8\xd2\xd1\xd6\x66\x36\x9a\xd6\xaf\xc7\x77\xfe\xa0\xe3\x73\xa8\x36\xe1\x44\x6e\x1a\xe0\x2b\xaa\x50\x3f\x34\x00\xad\x32\x5c\xcb\xbd\x26\x1e\xaf\x96\xd7\x72\xb1\x8a\x20\x39\x81\x9d\x69\x20\xf3\xd5\xa5\x20\xb0\xa8\xcf\xe3\x2f\x62\x29\xa5\x82\xd2\xfd\x1d\x12\xa5\xfb\x57\xd0\xe0\x49\xe9\x2f\x0e\xb7\x5b\x5c\xac\x37\x18\x76\x57\xd5\xd4\x51\xdf\xab\x2c\xef\xf3\x43\xd3\xb4\xc2\x4b\x42\x90\x68\x26\xa3\xd6\x06\x41\x46\x62\x80\xd1\x63\xb4\x99\x7d\x24\x12\x80\x44\x70\x39\x8e\x02\xad\x9f\x6e\xd4\x24\x02\x69\xc0\x35\xfe\x60\x6b\x3c\xdd\x4a\xa2\xe3\x74\x6d\x7c\x0a\x0e\xff\xd0\x7f\xc0\xc3\xfb\xb7\x2c\x5c\xaa\x8f\x9c\x52\x35\x98\x76\x92\xae\x3a\xe7\xe1\xfd\x5b\x17\xdc\x89\x9b\x4b\x9b\x2f\x5c\x33\xde\x3e\x75\x2e\x1e\x3b\xd1\x52\x42\x7b\x48\x3c\xfe\xa5\x5e\x73\xf6\x9f\x37\x3f\xaa\xff\xd3\x06\x9d\x24\xb7\x3e\x05\x7f\x35\xe2\x9f\x0b\x27\x0f\x79\xe2\xdd\xa3\x4b\x17\x2c\x48\x22\xdc\x7d\xbd\x3e\x9e\xd9\x02\xef\xe9\x44\x94\xb5\x93\xf5\xe4\x4b\xaa\x0c\xab\x29\xd6\xa4\xe2\x4e\xab\x36\xa7\xa6\x38\x53\xd0\xef\xb6\x1c\x56\x84\x14\x60\x2e\x1c\xa9\xac\xd7\x92\xb7\x72\xb7\x00\xed\xcc\x62\xa5\x0d\x70\xa4\x32\x3e\xca\x71\xb5\xf6\x48\xf8\x62\xf9\xe0\x04\x32\x81\x75\xe3\x46\xcc\x9c\xb4\x6b\x17\x6e\xd9\xb5\xeb\x9b\xaf\x6e\x18\xfb\xb8\x7f\xf9\x2a\x06\xe9\xcc\x94\xae\xcd\xba\xce\x50\x8f\x50\xaa\xbf\xb7\xc0\xa8\xb9\xcc\x40\xd4\xb8\xd5\x07\x59\xa6\x79\x77\x16\x72\x77\xc5\xc5\x60\xcb\x61\x55\x08\xa4\x52\xaa\xd7\xa3\xa9\x8e\x92\xd4\xe9\x6e\x94\x6c\x18\x5e\x8b\x28\xa9\x21\x90\xf8\xb0\x32\xc6\x81\xd4\xe7\x66\x7b\xfa\x5a\x42\xba\xba\x71\x23\x6e\xda\xb8\xb1\xc8\xcb\x92\x64\xae\x4c\x6c\x3f\xde\xa3\x0f\xdf\xdf\xa5\x14\x5b\xb9\x92\xd8\x5c\xf7\xf3\x93\x2c\x07\x00\xdb\x33\x0b\x65\x4b\x11\x35\xf4\xcb\xda\x18\x94\xa0\xc7\x43\x1d\x25\xd1\xbb\x84\x7c\x5b\xbb\x22\x98\xc7\xfb\xd4\xa4\x20\x09\x33\x21\x3e\xed\x56\x2e\x04\x8e\x8f\x76\xb2\x82\x90\x5a\x4a\xeb\x5e\x6a\x9d\xcf\x44\x7a\x98\xca\xde\x24\x58\xaf\xa4\xf2\x60\x01\xe3\xfc\xaf\x14\x9b\x5b\x69\xdf\xba\x87\x86\x35\xb3\xf8\x3e\xd4\xfd\x3c\xb6\x3e\x28\x44\x70\x78\x70\xe3\xd0\x74\xb8\xad\x59\x5f\xcf\x78\x2e\xda\xbb\x72\x6b\xd7\xbd\xf8\xbc\x6d\x4f\x3f\xf7\xcc\xe6\x2d\x8f\x6f\x63\x3e\xfe\x1a\x5f\xde\x91\x7d\xea\xc4\x81\x61\x83\xe5\x6f\x1c\x7e\x7c\xc3\xaf\x6f\xbd\xee\xea\x9d\x78\xc2\x9f\x8e\x9e\xfc\xc7\xbf\x87\x7f\x72\x48\x3f\x61\x62\x99\xb8\x45\x50\x27\xbd\x0e\x65\x6d\x79\x85\x34\xc9\x18\x62\x7f\xb3\x9d\x66\x76\xd0\x0c\x79\x34\x10\x82\x4a\x52\x59\xc8\x88\x28\xe5\xd8\x50\x69\x14\xa8\x33\xd5\x62\xd6\x0a\x4e\x48\x48\x75\x51\x97\x56\xc5\x26\x76\x20\xde\x13\xa4\xdf\x60\xa4\xe5\x81\xa2\xc1\x52\x3c\x13\x1d\x6c\x0f\x3c\xd3\x94\xaf\xf6\xcf\xda\x30\xd8\x56\x8a\x19\x13\xcf\xe4\x72\x35\x6d\x9a\xb5\xef\x73\xdc\x3a\x7b\xc1\x4d\x37\x5a\xa8\xfc\x99\x84\x07\x8e\x9b\xb0\xe6\x64\x8d\x09\x66\x9a\x3c\xf7\xd2\x09\xb8\x09\x3b\xb7\x6e\x59\xb9\xa5\x26\xf7\x34\x3c\x57\x3f\x42\x96\x0b\x2c\x1d\xe0\x2c\x3c\xdd\xd8\x95\x1d\x69\xfa\x44\x4b\xe0\xc0\xf7\x92\x03\x5f\x4a\xab\xc8\xa1\x29\x2e\x6a\x30\xec\x85\xb3\xcd\x23\x6b\x8a\x04\xfa\x62\x01\xa3\x14\x5c\x86\x13\x6a\xc0\x43\xeb\x24\x56\x51\xb5\x3b\xf3\x47\x86\x3d\xa3\x94\xf4\x39\xbe\x81\x4c\x12\x15\x6b\x8a\x0e\xec\x9e\x14\x12\xfd\x1d\xdc\x42\x79\x23\x4c\x53\x27\x73\x5f\x11\x75\x84\x69\xea\xa4\x8c\x11\x44\xcf\x34\x76\x31\xb7\x88\x7a\x18\x04\xcc\x18\x2a\x2b\x90\x2d\xd1\xed\x22\x63\x08\x08\xae\x84\x22\xd2\xa0\xc5\x97\x82\x04\x38\x00\x63\x90\x3d\x5a\x56\x86\xc3\x59\xf6\x09\x89\x6c\x00\xf2\xe4\x00\xa2\x8e\x05\xaa\x1c\x00\x94\x0b\x52\x59\x37\x89\xf9\xa0\x76\x4f\x4e\xe5\x1e\x24\x10\x2b\xcd\x54\x36\x16\x71\x3f\x96\x3c\x1d\xfa\xf0\x13\xfd\x20\xde\xbf\x0f\x7f\x60\xf0\x3e\xae\x9f\xba\x4f\xcf\xe0\xfd\x34\xa6\x40\x88\xd3\x61\xce\xfd\xe8\x1a\xc3\x93\x93\x33\xe2\x09\x91\x83\x1e\x98\x43\x4a\xa5\x14\xd1\xab\x62\x8b\x19\x52\xc8\x00\x36\x77\xcb\x5a\xd6\x0d\xa4\x3e\x37\xc9\x9d\x3c\x6e\x50\xcc\x27\xf7\x1b\x30\x8d\xef\x25\x28\x4b\x8a\x1e\xa8\xc5\xc2\xfd\xc6\xa3\xc1\x68\x6b\x94\xdc\x27\x16\xa3\x22\x8e\x06\x5b\xaf\xbf\x1e\x8f\x9b\x86\x9f\x9e\x86\xc7\xce\x9e\x7d\x44\xff\x5e\x7f\x4f\xff\x16\x9f\x33\x7b\x16\x57\xbf\xff\xcd\x37\xdf\x7c\x73\xbf\xee\xec\xda\xcf\x24\xb1\xfe\xc1\x07\x28\x5f\xc3\xe6\xda\x00\xef\x36\xd8\xa8\x61\x73\xf9\x1a\x76\x28\xa9\xda\x4a\xd3\x69\x35\x6c\xd1\x54\x86\x4f\x01\xf8\x9f\xbc\x10\x85\x6a\x76\x48\x54\xbd\x11\xa3\x9a\x1d\xf5\x45\xc9\x49\xd8\xb3\x9a\x1d\x6b\x4e\x5b\x82\x81\x60\xba\x65\x18\xc6\x63\xe7\xe2\xf2\x39\xf8\xfc\x65\x37\x64\xf5\xbf\x17\x55\xb5\xb5\xd7\xe7\xe1\xa5\x31\x28\x78\x47\xb9\x36\xbd\x03\x8f\xd6\x3b\xf6\x75\xc5\xcc\xea\x36\x33\x6a\xdf\xbe\x19\xe3\xe7\x5f\x77\xd5\x0c\x83\xb7\xb0\x9c\x5b\x04\x78\x9c\x9b\xcd\x3a\x82\x55\x2b\xaa\x08\x57\x58\xb5\x9c\xab\x24\x60\x75\x25\x54\x97\x3b\xdf\xb2\xf2\x78\x34\x25\x0c\x0b\xba\xdc\x28\x1a\x55\x17\x09\xe6\x95\x8b\x59\xab\x08\xb9\x89\xdd\xf4\x24\x75\xd1\x82\xb7\x5a\x11\xa0\x4b\xbc\xaf\x84\x5e\x40\xf6\xf3\x1e\x2c\xfb\xd3\xa9\xd6\x20\x1f\xab\xaa\xc5\xad\x43\x01\x81\xc3\xcb\xeb\x3f\x1c\x64\x1b\xf7\xec\x1d\xbf\x78\xf9\xc7\x1f\xdf\xdc\x71\xf7\x4b\x33\x5e\xff\xf6\xf3\xe3\x38\x79\xcb\xca\xbb\x1e\x9d\xb5\x1c\x2f\x66\xbe\x7e\xe2\xda\x0b\x77\x3d\x4f\x11\x36\xe3\x0f\x4e\x7f\x0b\xbf\xc0\x71\x93\x26\x2f\xbf\x6d\x86\x81\xc1\x5b\xc0\x2d\x42\x5e\x54\x66\x2a\x52\x50\x72\x46\x5e\xc7\xd1\x74\x12\x16\x65\xa0\x1c\x07\xe8\xf6\x04\xb5\xee\x80\x28\x4a\xed\xbc\xc3\xcd\x52\xc5\x36\xc5\x4e\xce\x0d\xbb\x28\xed\x44\x16\x87\xd3\x57\xd2\x4b\x93\xd1\x14\xe5\xf4\x16\x59\x05\x7c\xf5\xdb\x43\xf3\xc8\xd6\x93\x57\xe2\xfc\xe3\xb2\x59\x45\x00\xca\x35\x27\x37\x51\xe1\x4d\x3d\xfb\xc4\xba\x68\xee\xe9\xad\x14\x73\xdb\x7d\x94\xcb\xc1\x3d\x97\xa2\xd9\x46\xbd\xde\x91\x2f\xd3\x43\x11\x9a\xc5\xde\xca\x3d\xc9\xbc\x3e\x79\x18\x0c\xd8\x79\x21\x61\x0a\xbf\x8b\x12\x0c\x06\xd0\x69\x32\x15\x59\x11\x49\x9a\xc0\x78\x32\x19\x25\x28\x66\x59\xde\x09\xbb\x6b\x18\x89\x52\x56\x70\xfb\x33\x79\x30\x2b\x2d\x70\x42\xe5\xce\x6a\x00\x13\xbc\xb1\x2a\x71\xe3\x0f\x09\xf7\xec\xdf\xed\xfb\xfc\xeb\xfd\x87\x67\x0b\x25\x25\xb7\xdc\x7e\xed\xdc\x8f\xbe\xe1\xda\x1e\xde\xa2\xbf\xab\xff\x43\xff\x9b\xfe\x7f\x9e\x5d\xc3\xd4\xbc\xf0\xc4\xb6\xad\x78\xac\xfe\x85\x39\x06\xbe\x02\x6a\x93\x73\x8d\x31\x84\x4c\x0b\x58\x09\x02\x30\xc0\xbb\xaa\x5c\xe1\x80\x28\xf7\xd0\xa3\x9d\x9a\xc1\xca\x46\xbf\xac\x1c\x41\xad\x11\x0a\x91\x31\xb1\x9d\xe3\xa5\x10\x64\xf6\x12\xc9\x80\x3c\x25\x54\x34\xd3\xea\x2a\xca\x83\x45\xc8\xec\x65\xd8\x70\xe4\x7c\xcd\xb6\xc7\x90\xe0\xe9\x58\x37\xb6\xb7\x4f\x18\x93\x39\xab\xb1\x89\x75\x3a\xe9\xe0\xf6\xce\x97\xd3\x17\xcc\xbe\xa9\x6d\xde\xfc\xa9\x0b\xae\x67\xb8\xd7\x5e\xe8\xa8\xd0\xfc\xcd\x43\xdd\x57\xdd\x95\x1f\xe8\x9a\xa5\x4c\x3a\xf7\xf4\xaf\x9e\x7b\xee\xb9\x07\x36\xd2\x3d\x75\x58\xf7\x51\xf6\x0d\xd8\x53\x87\x50\x6d\x5e\xd5\x63\xd7\x60\x6d\xa9\xb2\x9d\x9a\xbe\x48\x40\x7b\x00\x6b\x17\xd5\x63\xa3\x85\x43\x59\xcc\x5a\x9c\x50\x42\x65\xf2\xa9\x31\xed\x74\x56\xd5\xc6\xf3\xba\xce\xb1\x2a\xeb\xb0\xc7\x0f\x61\x16\x07\xf4\x6f\xf4\x93\x73\x9f\xb8\x70\xd4\x23\x3f\x59\x78\xef\x83\xb7\x4e\x7f\x80\x8b\x8f\xd1\xff\xa8\xff\x49\xd7\xf4\xdf\xd5\x34\x60\x4b\x32\xb5\x75\xcb\xf3\xcf\x8e\x80\x35\xbf\x96\x8b\x71\x8b\x80\x5d\xb6\xd2\x78\xa7\xa3\x79\x1e\x8a\x5d\xcb\xc5\xbd\x01\x92\x88\xc5\xdd\xa6\x09\xaf\x52\x9a\x32\x93\x99\x6a\x0c\x9c\x66\x91\x4b\x40\xe4\x0b\xb6\x01\x24\x62\x52\xaa\xc5\x9c\xc0\x7a\x03\x50\x4f\xf3\x99\x78\xc7\x68\xc0\xfc\x72\x5c\x54\x7c\x19\xc5\x2b\x65\x9d\xc8\x9d\x81\x87\xd2\x57\xb4\xd5\x60\xe4\x04\x5b\x7a\x36\x2a\x6a\x2d\xf9\x67\x32\x05\xc7\x70\x69\xc7\xa6\xc9\xa3\x6e\x19\x71\xef\x72\xe1\xae\x57\x9f\x7c\xf1\x0f\xbf\x39\x78\x4b\xa2\x62\x5d\x74\xe4\x0d\x78\xf9\x39\xf7\x9e\x7f\xd5\xf0\x61\x77\x33\x75\x38\x82\x07\x8c\x39\x5a\x56\xfb\xdc\xaf\x6a\x07\x2e\x79\xf2\xee\x75\xcf\x5f\x72\xd9\xe5\x23\xaf\xba\xfd\x89\xca\xc9\x99\xa6\x01\xa9\xff\x2f\xe1\xab\xa7\x74\x1f\xb5\x8c\xe5\x63\xf0\x9e\x2d\x30\x4e\xf4\x30\x09\x4c\xc4\xa4\xea\x2c\x7a\xb5\x7a\x74\x48\x0c\x27\x38\xc0\x1c\xd3\xf0\xcb\x56\x0e\xe1\x57\x49\x65\xdc\xe8\x3d\x59\x48\x60\x29\x4b\x4a\xc0\xa8\x14\x0f\x17\x90\x85\xf7\xb0\xc1\x10\xfd\x0e\xa7\xa8\xb8\x8b\x86\x3d\x04\x17\x5e\x39\xf9\x94\xea\xc4\xc6\xa0\xdb\x95\x6b\xc6\x64\x5a\x9a\x86\xf4\x55\x26\xce\x0f\xd9\xfb\xeb\x6d\x15\x9a\x7f\xc8\xd0\x93\x63\x1e\xee\x3d\xdc\xbe\xbe\x77\x76\xf3\xbc\x82\x72\x59\x98\xd7\x72\x32\xb2\x73\x45\xbe\x77\x38\xef\x7b\xe7\xa7\x80\x37\xab\xb1\x1d\xca\xd8\x54\x6e\xf0\x8b\x59\xbb\xc8\xc1\x76\x28\xda\x69\x40\x86\x80\xc8\x23\x4b\x46\x14\x36\x10\xa5\x53\xe6\x8b\xd9\x4c\x01\x80\x35\x14\xe7\x37\x09\xdb\xbe\x3d\x81\x83\xfa\x21\xfd\xf8\x3d\x2f\x8f\xbe\x66\xe7\x8c\xbb\x1e\xb2\xe8\x63\xf1\x76\xfb\x9c\x6b\xae\x9d\x8f\xbf\x7c\xf4\x5b\xec\xd6\x0f\xe8\x5f\xeb\xdf\xe9\xbf\xaf\xab\x3d\xda\xd0\xff\x91\xbb\xde\xbd\x79\xf1\xed\xff\xaf\xf2\xef\x83\x35\xc8\x3f\xcc\x2d\x42\x51\xd4\x8f\xe4\xd9\xe0\x78\x54\xc3\x53\x22\xab\xca\x59\xb5\x5c\xc8\x57\xe1\x70\x25\x68\xfb\xbe\x2e\xa9\xf4\x3b\xac\xe0\x94\x5a\x46\xc9\xac\x4a\x4b\xc9\x6e\xef\xe3\x6f\x36\x22\x39\x61\xe7\x14\xdc\xe0\x56\xd0\x1e\x4e\xed\x17\x39\xe1\x56\xaa\xf6\xa0\x76\x84\xab\xfa\x35\x34\x34\x34\x60\x15\x55\x41\x9d\x00\xab\x65\xfd\x00\x63\x8d\x54\x5f\x88\x02\xc3\x39\x71\xa7\xd5\xed\x91\xa9\xb4\xb2\xd1\x48\xf7\xd5\x14\xc6\x9a\xe2\x82\xad\xb4\x24\x0a\x71\x45\xdc\x4a\x9e\xa4\x31\xf2\xe6\x29\xcc\x97\xa5\x0f\xde\x7c\xed\xcb\xb3\x27\xbd\xb6\xf4\x23\x5c\xd3\xf4\x6e\x79\x79\xba\x7e\xc4\x45\xe7\xce\xf9\xe9\x8c\x07\xfb\x05\xf4\xaf\xba\xd1\x77\xfa\x77\xb8\xc6\xb3\xe0\x8a\x79\xcb\xf0\xd7\xef\xde\x74\x03\xcc\xc3\x9e\xf6\xe6\x59\xb3\x46\x34\xe7\x26\xcc\xbb\x83\xd3\x35\xfd\x3d\xec\xb8\x7d\xfc\x94\xa7\x1f\xa0\xe7\xc1\xd8\xee\xa3\x5c\x0d\xf4\xdb\x6f\x47\xd9\x6a\x50\x57\xb4\x69\x34\xc4\xf6\x5a\xb5\x5c\x20\x5c\x2d\xb8\x12\x6a\x80\xd7\x4c\xde\x72\x99\x4f\x53\xca\xbc\x8a\x0f\x28\x0f\x22\x50\x1e\x7c\xa2\x96\xf5\x01\x5b\xcb\x17\xa4\x6c\x2d\xb5\x8c\x32\x1d\x90\x1a\xa9\x16\x25\xa5\x0a\x04\xc4\x81\xdd\x14\x90\x54\x8e\x05\xb7\x1f\x95\x27\xe7\xa0\x40\x31\xdb\xbe\x81\x2d\xad\xcd\x86\xa2\x6c\x7e\xef\x0d\x0c\xc2\x32\xfc\x21\x9a\x6a\x69\x95\xf9\x68\x65\xf5\xd8\x3b\x1e\xfa\x50\xff\x66\x91\x36\xa9\x6d\xf1\xfd\x17\x2f\x98\xbb\x72\xcd\xfa\xad\x8f\xac\xc5\xce\xeb\xfe\x78\xe5\x76\xfd\x47\xfd\xdf\xfa\xd7\xb8\x79\xf6\x3d\x65\xf6\xa6\x0f\x56\xaf\x6b\xa8\xfd\xa4\xb1\x22\xd5\x32\xa2\xf5\xd0\x39\x17\x2c\xab\xaf\xfb\xe7\xc5\xcf\xe5\xc7\x4b\xce\x9b\x7e\x68\x21\xca\xc6\x81\x01\x6a\xd3\xb2\x25\x20\xe7\x6e\xd5\x72\x4e\x47\xbc\xc4\x95\x50\x9d\xbc\x69\x72\xa0\x78\x53\x6a\xcc\xa7\xa9\xe5\xa2\x96\xb5\x96\x93\x31\x5a\x9d\x02\x3d\x6e\xca\xad\x86\x81\x32\x52\xb9\x38\x25\x7c\x3a\x44\x15\xc7\xa0\xef\x4d\x9d\x95\x7d\xa2\x1a\x20\x07\x4e\x89\xa4\x90\x9d\xb7\xb5\xb9\x37\x89\x0b\x8e\xf6\xb8\x11\x51\xd2\xba\x27\xc9\x84\xc7\x4e\x3c\x70\xcd\x63\x8f\x3e\xbd\xe9\x96\xf9\xbf\x7a\x78\xd6\x6d\x17\xbf\x35\x6e\xf2\xe2\xcf\xef\xff\xa0\xf3\xb3\xfb\x6e\xbe\xfb\xc7\xe7\xf5\xbf\x36\x75\xf6\x6b\x38\x77\xe8\xc8\x73\x0e\x9d\x35\xa4\xa5\xa5\x36\xfa\x61\x7d\x7c\xe3\x7d\xaf\x66\xec\x55\xcb\x66\xcc\xdc\x30\x31\xff\x5c\x2d\x64\x9d\xa7\x49\x44\x93\x32\xc7\x19\xc2\x74\x0b\xca\x39\xec\xa9\x90\x2b\xa1\x3a\x78\x4d\xa9\x25\x4f\xb2\x92\x0c\x78\xa0\x49\x55\x6b\xf0\x51\x3b\xd6\x06\x5e\x94\xb2\xa5\xfd\xfa\xc3\x7b\x6a\xe7\x44\x49\xc5\x0d\xc0\xd6\xc8\x56\xf7\x4f\x64\x32\x19\xb5\xb2\x56\x94\x94\x7e\x06\x30\x3b\x06\x81\x19\x8c\xb1\xb2\x37\x4f\x8d\xd2\x78\xe9\xca\x6e\x81\xa5\x1d\xe7\x8b\x86\x7b\xd9\x1b\x93\x70\xf0\xc1\xb5\x37\xce\x5c\xbf\xf2\xd0\xf9\x3b\xc7\x4c\x5e\x78\xe8\xde\xfb\x0f\x0d\x5c\x44\x96\x77\xe2\xdc\x8a\x73\xe7\xfc\xf4\xa5\x8b\xce\x9e\x7b\xdf\xcd\x3f\xfd\xf6\x39\xfd\x5f\x4d\x9d\xfd\x07\xdc\x39\xf2\x9c\x43\xad\x67\xcf\x87\xa1\x4f\x18\x53\x31\x7b\xd6\x88\x4a\x39\x37\xa1\x63\x6c\x59\xd1\x1c\xd0\x78\x7a\x37\xb7\x08\xf9\x50\x3f\x34\xdf\xa8\xf1\x06\x4d\xb6\x44\xad\x55\xcb\x55\x44\xa0\xc8\x5d\xc1\xe7\x0d\xfe\x0d\x42\x55\x09\xed\x36\xbb\x7d\x9a\x6a\x15\x69\x11\xbb\xc4\x2f\x4a\xed\x9c\x18\x8c\x50\xe2\xaf\x51\xcf\x8e\x04\x29\x87\xa2\x42\x6c\xb7\x23\xbf\x83\x7c\xad\xd6\xd8\x89\xa1\x1d\x19\x28\x2a\x67\x57\xa2\x3c\x1e\xaa\xf8\xf1\x4f\x59\x87\x65\x55\x3b\x31\x67\xd1\xca\x25\xfa\x27\xff\xd0\xbf\xd1\xdf\xc7\xad\xf7\xae\x99\xbb\x64\xd1\x53\xf1\xe8\xa3\xb7\x2d\x9e\xb6\xe2\x69\xa6\x69\x07\xb6\x3d\xf8\xcc\x13\x57\xdf\x1a\x71\x84\x6f\xbe\x7a\xcb\x9b\x38\x85\x7d\xca\xb6\x0b\x86\x0d\x6f\x3e\xd4\x3c\xaa\x69\xd8\xab\x14\xef\xc0\x2c\x00\x5e\xc8\xc4\xd3\x57\xa2\x8a\xeb\x64\x9e\xff\xbb\x75\xb2\x02\x40\x62\xd3\x26\xb3\xe2\xd4\xa7\xd4\x84\x0a\xf1\x4d\x0c\xbc\x1c\x97\x20\x92\x58\x96\x5b\xb5\xfc\xa1\x9f\xce\x8b\x10\xc6\xbd\x24\x96\x29\x3a\xf4\x2b\x3c\x9a\x52\x91\x54\x6c\x69\x70\x6a\x8c\x93\xd3\xa3\xa4\x34\x43\x66\xbb\x83\x0d\x95\x57\x55\xf7\x6f\x22\x13\x5e\x2f\xa9\x96\x01\xe4\x61\x94\x1b\xfe\x1c\xa2\xf8\x12\x39\xff\xe5\x52\xfa\x75\xa7\x74\x86\xf3\xbf\xaf\x38\x7d\x8f\x72\xcc\x6f\xdf\xbf\xc5\x96\x0f\x04\xf2\xca\xf4\x16\x0b\x28\xd3\xb7\xce\x5e\x70\xeb\x75\x7c\x41\x92\xbe\x28\x1e\x18\x4d\xb5\xe9\xa5\xd5\xcf\xe1\x16\x6c\xdd\xba\xe5\x81\x8d\xe0\x86\x45\xfd\xe6\x48\x8e\x57\x82\x6a\xc9\x9a\xec\xab\xd0\x4f\x77\xd9\x52\xca\x22\x8b\x9e\x4a\xa1\x9f\xec\xaf\xa5\x26\x30\x4f\xf1\x89\x1d\x54\x9d\x1f\xa0\xc8\x51\xaa\xcd\xdf\x5b\x93\x1f\xbe\x78\x66\x4d\xfe\xff\x44\x8a\xbf\xf5\x4c\x12\xfc\x64\x98\xa6\xe9\x17\x86\x77\x6f\x1c\xb7\x08\x95\xa2\x5b\x11\x04\x79\xaa\xd7\x6e\xbc\x79\x0e\xbb\x96\xf3\xcb\x61\xf2\xe6\xf9\x0b\x11\x83\x81\x2b\x95\x70\x42\x0d\xfa\xb4\xac\x04\xf2\x60\x92\x5f\x48\x40\xe4\x20\xb9\x45\x29\xeb\xe0\x40\xc8\x24\x28\xaa\x36\x40\x76\x78\xc3\x22\xd9\x57\x55\xd9\x4f\x26\x03\xc1\xce\x44\x62\x08\xae\xc7\x1b\x68\x1e\x27\x60\x20\x18\x6b\x8e\x8a\x7c\xb4\x12\x4d\x79\x18\x7b\x5f\x9d\xbd\xf3\xda\xc9\x43\x57\x5d\xb6\xe6\x79\x2c\x0f\x1b\xf9\x21\xfe\xf1\x0d\xfd\x47\xfd\x3b\xfd\x4f\x4c\xd3\x8b\xd8\xfa\x60\xbf\x86\xa3\x95\x03\xb2\xeb\x75\x45\x7c\xe5\xdd\xae\x77\x27\xe1\x3a\xd4\xa3\x66\x12\x40\x95\xe8\x3a\xa3\x66\x22\xa4\x15\x6f\x52\x0d\x93\x0c\x25\x9a\x54\x7c\x87\x73\x41\xc8\x49\xb2\xbe\x60\xbe\x35\x16\xa4\x48\x3b\x17\x4d\x56\xaa\x60\x90\x64\x3b\x0d\xd0\x58\x88\xb7\x40\x9b\xda\x25\x01\x96\x01\xa9\x28\x2c\x4a\xed\x16\x97\x2f\x02\x8f\x4d\x8c\xfa\x22\xd8\x40\x0b\x1a\x08\x4a\x12\xad\xfb\xfc\xe9\x54\xf3\xc0\xda\xb8\x1b\xe3\x61\xfb\xbd\xd5\x36\xde\xd9\xbc\x17\x0f\xd3\x27\x2c\x7f\xe6\x9e\x7b\xd6\x37\x5e\x3a\xe5\xbc\x51\x55\xd5\x35\x95\x5c\x9b\x1e\xaf\xbe\xe3\x9c\x6b\xef\xc6\x47\x3a\xe7\xfc\xb0\x7e\xe5\xc6\xa7\x1f\xb8\x64\xfb\xaf\xf4\xc9\x0b\xe7\x0e\xb8\xf3\xbc\x91\x77\xd0\x5e\xd8\x57\xdc\x6a\x6e\x11\xaa\x47\xad\xe8\x7a\xda\xcd\x55\xc4\xb4\x3a\x40\xd0\x14\x39\xa5\x54\x25\xd5\x26\x32\xb4\xb3\x92\x4a\xcd\xe1\x5c\x03\xf5\x3f\x6a\xf0\x92\x57\x32\x57\x41\xc7\x93\x21\x67\x45\x0d\x3d\x0a\x06\x8a\x59\x47\x95\x9d\x8c\xa6\x42\x52\xca\x32\x48\x1d\xd0\x24\x4a\x39\xbb\xa3\xa2\x06\xdc\x33\x39\x51\xc5\x7e\x5a\x6f\xa3\x67\x02\x8c\x6c\x98\x21\x29\x45\x5e\x4a\x37\xc3\x1a\x04\x15\x18\x65\x9c\x3c\x3d\x73\xe3\x8c\xf3\x91\x2b\xcb\xae\xb8\xa3\xe5\xb6\x5a\x9b\x2d\x59\x7f\xc1\xd0\x25\x17\x95\x5f\x5d\x5e\x5d\x5a\xd2\xaf\xb6\x76\xdf\x79\x0d\x1b\x57\xde\xf3\x54\xbf\xa1\x4f\xa6\xc7\x26\xaa\xf0\xa7\xd5\x55\xb1\xaa\xf3\x46\xb1\x37\x7f\xe1\xf6\x8c\x1b\xfd\xc2\x20\xf7\x84\xc1\xd3\xae\x38\xcf\xe3\xfe\xc2\xee\x08\xd7\xe9\x5d\xb3\xef\x1e\x7e\xfb\x33\x4f\xdd\x75\xfe\x5d\xd3\x0e\x8c\x3c\xa7\x6b\x71\x4d\x73\x3a\x36\xb6\xed\x2a\x84\xd1\x7a\xdd\xcf\x6d\x82\xe7\x7b\x31\x65\x35\xf5\x10\xc5\x70\x25\x4d\xa2\x1a\xeb\x01\xf9\x16\x17\x4e\x90\xdd\xd4\xe9\xa1\x04\x35\x17\x2b\x4a\xaa\xe8\x07\x9c\x8a\xe2\xcd\x20\x95\xf7\x1b\x9e\xb9\x3d\xd4\x2d\x00\x63\x04\x95\xee\xbc\xa4\x85\x7e\xd0\xe9\x6c\xf9\xf9\xe2\xbd\x6f\x17\xab\x58\x9c\xe8\xc0\x1f\x56\xdf\x7d\xf9\xb8\x43\xf4\x4c\xa7\xbe\x05\x15\x28\x82\x2e\x33\x7a\x7c\x81\x74\xbe\x2c\x41\x91\xe6\x11\xd8\xd6\x95\x08\x2d\xa7\x04\x3c\x14\x61\x1e\x31\xc4\x80\x82\x62\x3b\xc7\x7b\x25\xea\xd9\x45\x76\x10\x6b\x09\x68\x1f\xf7\x2e\x45\x94\xe3\xbe\x1c\x67\xa3\xfe\x30\xbd\x98\xd9\x6c\xd4\x1c\x16\x49\xb1\x39\xe7\x17\x13\x9a\xc9\xbd\xea\x7e\xb8\xd7\x38\x59\x51\x70\xaf\xe1\xa4\x1a\xb1\x17\xca\x28\x54\xa3\x2b\x4e\xef\x37\x4e\x65\x48\xc9\xfd\xd6\x19\x3b\x3d\x15\x2f\xda\x49\xee\xd7\xf0\x57\x88\x90\xd7\xbd\x14\x12\x9e\x32\x12\x38\xb6\x5b\x3d\x52\x8c\xae\xa9\x33\x0d\x20\xcf\x5f\x6c\xee\x3b\x92\xeb\x3f\x7f\xeb\x9d\x57\x5e\x9c\x7d\xf1\xa0\xc1\x4b\x7b\x0f\xe7\xd0\xfe\xce\x1d\xed\x7b\xc2\xc7\x7d\xdb\x98\xe3\x1f\xbf\xb0\xaf\xeb\x7b\x64\xd6\x78\xa1\xe7\xe3\x40\x7e\xf4\x13\xa3\x46\xc7\x62\x94\xc8\x61\x64\x67\x5d\x00\x61\xc3\x16\x4d\xb1\xa4\x20\x8d\xe7\x68\xb7\xdf\x7e\x58\x65\x9c\xa9\x14\x45\x59\x7a\x53\xa9\xac\x60\xcf\xa3\x2c\x8b\x60\x2b\x01\x13\x90\xe0\xf6\x65\x0a\x8d\x62\x5a\x86\xce\xd3\x18\xa1\xbb\xa3\x1f\x74\x51\xae\xde\x11\x7a\xd6\xea\x75\xf8\x08\xbb\x95\x76\x75\x30\xda\xd8\x7d\x94\x0d\x02\xf6\x31\x49\xb1\x07\xf9\x35\x0c\xb0\x1d\xba\x7a\x29\xfa\x91\x77\x88\xc0\x24\xc4\x46\xc7\x4f\x2c\x56\x80\xd8\x88\x9b\x2e\x1c\x7c\xe9\xfc\x39\xeb\x5f\xcb\xe2\x36\x16\x75\x21\xaa\xf2\x00\x6b\xb1\x0e\x21\x66\x37\xd7\x86\x1c\x28\x63\x54\xcc\x2c\xf0\xf3\x9d\x49\x85\x01\xa4\x45\x56\x60\xf2\xdc\x3e\x3e\x95\x65\x60\x98\x0c\xd9\x0b\xb9\x14\x79\x6d\x50\x63\x53\xba\x48\xb9\xb1\x4e\x51\x98\x87\x15\x65\xed\x44\xe6\xc1\x89\x6b\xd7\x4e\xec\xba\x69\xe2\xda\x7c\x0f\x60\x29\x70\x30\x27\xa0\xac\x0f\xd6\x7c\x52\x65\x21\x9a\x69\x17\xd8\x80\x2d\xa1\x7a\x2d\x9a\x82\x52\x8a\x25\x69\x98\x8e\xe4\x42\x94\x86\x12\x02\x1d\x22\x72\x35\xc9\xa3\x29\x7c\x4a\x91\x80\x28\x6f\x48\x48\x91\x10\x8f\x4c\xf1\x50\x9c\x0e\x8a\x51\x31\x60\x12\x4b\xe2\x62\x54\xac\x8d\x55\x59\xb9\xfb\x6f\x8a\xe1\xa6\xf2\x40\x4d\xc2\xf9\x38\x77\xff\xdc\x3a\xfd\x60\x79\x60\xb4\xc4\x4c\x7b\x70\x2b\xcb\xdc\xd9\x15\xb5\x0d\xcc\x3c\xfc\x1c\xd7\xb5\x8e\xd9\xcf\xcf\x06\x1d\xc9\xa3\x08\xb1\x43\x78\x3f\xf4\x5b\x6e\xa4\x9a\x3a\x8a\x27\xa9\xd8\xd3\x39\x3f\x25\xd0\xd8\x52\x4a\x28\x99\x63\xe9\x5f\x78\xb3\xe5\x6d\x08\xf1\x91\x7b\x73\xe1\x84\x6a\x91\x53\xb0\x99\x28\xd6\x54\xd6\x09\xee\x07\x4e\x81\x36\xbf\x69\x6f\x89\x64\x54\x21\x3f\xcd\x35\x58\x8a\x69\x02\xeb\xed\x60\x7e\x9d\xc4\xaa\x6a\x5b\xfd\x83\x68\x2d\xda\xff\xd3\x1b\x86\xa5\x70\xd3\xdb\x6f\xeb\x07\x2f\x58\xb1\x7a\xd7\xb4\xa1\x93\x62\x35\x6c\x7a\xd6\x6d\x35\x4c\x55\xe7\xe7\x1b\xba\xb6\x31\x13\x17\xcc\x3f\xb7\xec\x86\x18\xa2\xef\x2b\xb3\x03\x78\x20\x09\xa4\x38\x92\x64\xc5\x80\x70\xc2\x99\xd7\x4b\xb0\xf7\x7a\x81\x32\xd1\xed\xcf\xbf\xb0\x82\x7f\xc2\x28\x06\x29\xc6\xde\xa5\xfb\x2d\x7b\xa1\xc6\xb5\xa2\xa0\x85\x06\x45\xbe\x72\x9b\xa6\xb8\x92\xaa\xcf\x4e\x2f\x58\xd8\xc7\x98\x54\x36\x02\x48\x80\x88\x45\x00\xc9\xaf\x00\xad\x10\x67\x03\xb0\x96\x02\xa5\x46\xa3\x94\xec\x6e\xaa\xc7\x9b\x01\xbd\x1d\xde\xe5\xa3\xb2\x6f\xbe\x3c\xe4\x5e\xf1\x82\x58\x08\x1f\xc8\xe4\x27\x0d\x00\x18\x45\x2e\x6d\xbd\x9c\xe9\x36\xe2\x26\x76\xbf\x7e\xde\xb7\x3f\x3e\xa4\xff\x7d\xcf\x8f\x7b\xa6\x7c\x39\x63\xc3\x73\xef\xec\x5d\x8c\x1f\xef\xca\xf2\x7e\x7d\xf4\x3e\x7d\x5a\x49\xf7\x67\x4f\x7c\xbe\x78\x1c\xe6\xeb\xd3\xf7\xdc\x01\x46\x6d\x9d\x0f\xc0\x38\xd7\x77\x1f\xb5\x0e\xe2\xda\x50\x8c\x44\x77\x50\xe1\x8a\x92\xc1\x96\xa6\x61\x46\x3d\x29\x78\x0d\x55\xbb\x2f\x9d\x36\x65\x1b\x8d\x93\x04\x84\xa2\x3c\x50\xd6\x24\x31\x90\xdf\xa3\x81\x3a\xa3\xc0\x52\x3f\x41\xa7\x48\x55\x41\x24\xd8\x02\xfd\xa2\x12\x22\xa7\x4b\x40\x94\xda\x83\xa1\x72\x1a\x26\xf4\x14\x8e\xea\xa5\xa4\x14\xcf\x9f\x37\x97\x5e\x31\x7f\x1e\xf9\x78\xf3\x2c\xdc\xa4\xd5\x79\x1b\xb7\xcf\xea\x9c\x54\x3a\x40\xbd\xf1\xf5\x37\xcd\xa3\x67\xe3\x0e\xa6\x89\xfc\xbe\x7d\x2f\x08\x29\x5d\x32\xe1\xd9\x31\x57\xbc\x49\xcf\x46\x18\x5b\x35\x19\x5b\x15\x19\x56\x59\xdf\x61\x29\x81\xbc\xdc\x46\xdf\x91\x05\x70\x42\x91\xa0\x3b\x07\x2c\x4e\x18\x5c\x15\x0c\x2e\x52\x41\x8b\x03\x25\x65\x19\x60\xa4\x87\xc9\xf0\xaa\x44\x49\x0d\x47\xfa\x88\x43\xf5\x3c\x47\xf9\xd3\x0d\x4e\x3f\xe8\x72\x5d\x7f\xf0\x4c\x83\x23\xe7\xeb\x90\xd9\xcf\xc1\xf0\xe8\x1a\xb5\x8e\x80\x38\x68\x95\xb1\x46\xab\x8b\x5c\x81\x14\x57\x5a\xad\x13\x34\xa5\x32\xa5\xf8\x93\xd4\x6a\x81\x1a\xec\xd4\x7b\xc0\x57\x9e\x3c\xad\x6a\x0f\x50\x68\xca\xa8\x0c\x02\xe8\x90\xd6\x1b\x6d\xa6\x1a\x51\xb1\x66\x94\x6a\x49\xb5\x0b\x20\xbe\x98\xf5\xbb\x02\xb4\xad\x51\x90\x0c\x08\x66\x54\x5c\x27\x4a\xed\x2c\x27\xd8\xe1\x91\x16\x5a\x92\x26\xcf\xa0\xc0\xc6\xcf\xf3\x0b\xf2\x5a\x1e\x06\xbf\xe0\xe4\x95\xa5\xf5\x2f\xce\x7d\xed\x2d\x7a\xb0\x0d\x3f\x9b\xcc\x89\x7e\x90\xcc\x09\xd7\xb6\xe6\xe2\x2b\x36\x8f\x9d\xf8\xd6\x91\xce\x1d\xea\x9b\xe1\xe3\x24\x5b\xfb\x88\x4c\x49\xd7\x41\x66\x35\x99\x12\x72\xca\xe1\xee\xb7\xc8\xd9\x0d\x35\xf9\xe9\x06\xe7\x9d\x27\x93\x00\xe5\x3e\x59\x00\x56\x37\x23\xe4\xf1\x0c\x60\x75\x4d\x09\x53\x5e\x23\xde\x08\x5b\xe8\x2e\x21\x52\x3b\x6b\xa6\x4c\x94\x94\x08\x28\xda\xa0\x30\x2d\xd5\x86\x40\x2a\xda\x26\x64\x0a\x99\xe5\x29\xc4\x49\x60\xb0\x43\x86\xa4\xd3\x67\xf7\x74\x4c\x52\x7f\xb5\x70\xe8\x97\xf2\x88\x0c\xf7\x71\x4f\xc7\xa4\x25\x3b\x5f\xab\x30\xf6\x9a\x95\x70\xff\xd7\x9b\xfa\x29\xf9\x0e\x61\x89\xa0\x19\x05\xf6\xe2\xad\xc6\xd8\x5c\x1c\xc5\xf1\x12\x47\xf6\x13\xd0\x50\x31\xab\xe8\x48\xcc\x3a\xbc\xd0\x29\x2c\x91\x54\x7b\xb0\xd8\x5b\xab\x98\x0a\x52\x2c\xa1\x54\xf4\x64\xe0\xfe\xcd\xfd\x91\x8c\xc2\xf0\x7b\xea\xdc\x46\xf7\xc9\x97\x59\x2f\x65\x78\x98\xb1\x9e\x25\xc6\xb5\x21\x37\x1a\x57\xe4\xae\x85\x0d\x77\x2d\x0f\x4d\x99\x7c\x90\x32\x81\xbb\x96\x4f\x03\x9d\x65\x13\xe8\xcd\x8b\x2a\x63\xcf\x64\x14\x1b\x2d\xb7\xf5\x31\xd3\x6a\xc0\xe0\x45\x87\x03\xb2\xb8\x11\xcf\x65\x38\xab\xc8\xe0\xb8\xbe\x46\x47\x32\xd7\xd6\x79\xfc\xfc\x7f\x87\xf1\xee\x93\x9b\x58\xf7\x97\x73\xf4\x11\xa8\xc0\x13\x04\xaf\x5d\x1f\x0a\xa3\x74\x6f\x9e\x60\x88\xe4\x74\x6e\x12\x01\xa9\x7e\xbe\x08\x00\xea\x77\x9f\x8e\x01\x08\x35\x4e\x5a\x99\xee\x4d\xfc\x1b\xec\x99\x3b\xf3\xad\x32\x7d\x28\x7e\xd3\x3d\x67\xe6\x5b\x7d\x78\x60\x17\xdc\x74\xd3\x5f\x0f\xcd\x5f\x50\xa8\xe7\x2e\x87\x7e\x56\x0c\xad\x31\x6a\x3c\x6e\x9b\x46\x43\xf7\x52\xbb\x06\x4b\x57\x15\xac\x05\xe5\xe0\x9c\xdd\xe5\x27\xf7\x69\xb7\xe6\x1d\x00\x43\xb2\x66\xca\x07\x5b\xc4\x54\x0a\x6c\x9e\x85\x54\xd6\x1d\x81\x86\xbc\x57\x48\x28\xd6\x54\xfb\x70\xb7\xd3\xf0\x03\x8c\x84\xc8\x5c\x42\xa7\xd8\x2d\x82\x28\x95\x6a\x77\x89\x52\x16\x85\x22\x99\x4c\x46\xe5\x05\xb1\xb8\x93\xd4\x1c\x95\xf3\xff\x35\xf3\xb1\x5e\xec\xc7\x29\xb8\x14\x33\x2b\xa7\xb1\x15\xba\x84\x0f\xea\x4d\xf8\xdb\xce\x2f\xda\x1e\xde\xf0\x8f\x22\xf6\x23\xd3\x84\x65\x5c\x7f\x56\xec\xab\xbd\x5f\xfd\x45\x8b\x0f\x5a\x8d\xad\x6a\x9e\x8b\xca\xa0\xb6\xee\xa3\xfc\x48\xa8\x71\xc5\x4d\xed\x30\xc5\x91\x56\x03\x36\x4d\xa9\x48\x65\x03\x20\x54\x12\x28\x11\x12\x34\xf5\xae\xb1\xe7\x23\x6f\xbf\x08\x95\xae\x30\x4e\xa8\x65\xa2\x66\x08\xe3\xaa\x36\x91\x46\xe0\xb0\x29\x89\x64\x9f\x6a\x77\x7b\x38\x83\xe5\xac\x38\x32\x08\xfa\xcc\x8a\x1b\x7a\x4c\x36\x54\xc0\xdd\x73\x92\xec\x67\x62\x55\xb5\xb4\x9d\x52\xe3\x35\xd5\x5b\x0a\x23\x6d\x7b\x09\x5f\xf9\xd7\xaf\xf1\xe5\xd9\x3f\xbd\x77\xdb\xd3\xfd\xed\xe3\xbf\x7d\xef\x4f\x38\xbc\x63\xc2\x18\x1c\x1a\x33\x61\xd2\xc4\x1f\xbe\xfc\xfc\x04\xfe\x62\x1f\x4e\xfc\xe2\x19\xfd\xf0\x6f\xff\xa6\xff\xfb\xfa\x59\xbf\xc3\x8e\x6f\xf4\x1f\x16\xad\xda\xbb\x77\xd5\xa2\x7b\x6f\xdf\xfb\xf1\x11\x83\x47\xc2\xc7\x21\xce\x0a\xa1\x0a\x34\x8f\xa2\x2c\x80\x11\x61\xd3\x94\xb0\xc1\x23\xe1\xd3\x6a\xc0\x4a\x26\x80\x84\x2f\x5c\x12\x54\xde\x0b\x5c\x47\x37\x40\x20\x53\x29\xd5\x25\x69\xaa\x25\x9c\x4a\x29\x2e\xba\x65\x0b\xb2\xa6\x46\xc9\xaa\x95\x3d\xf4\x2d\x0a\x88\xaa\x40\xe9\x22\x2a\x63\xa5\x63\x45\x35\x62\x54\xe4\x90\xec\x47\x16\x31\x2a\x56\xa3\x1a\x7f\x20\x28\xba\x31\x06\x44\x6e\x7c\x0a\x1e\x88\x6b\x71\x29\x0e\xe1\xa1\xfa\x3e\xfd\xcf\xfa\x57\xfa\x57\xfa\x1b\xf8\xec\xf5\xf7\xdc\xf9\x0c\x33\x68\xe5\xba\xc7\x57\x31\xc9\x2e\x5c\xe3\xc3\x8a\x3e\x2e\xa8\xff\xfe\xfb\xff\xd2\x8f\x04\xf5\x32\xfc\xe7\x12\x9c\xfc\x76\xb5\x2a\x31\x1b\xc5\x5d\x7a\x9d\x94\x7d\xf0\xee\x9d\x3e\xb2\x07\x24\xba\x8f\xb2\x0c\xd7\x86\xbc\xe8\x2c\x53\xb3\x9e\xac\x6a\xd6\xa5\xc1\x5e\x66\x6a\xd4\x91\xac\x42\x32\xd5\x85\xc8\x7e\xcb\x92\x1c\xc2\x01\xc6\xa3\x41\x5f\xaf\x38\x20\x11\x8c\xb5\x3e\xf4\x1c\x6e\xfa\xba\xde\x33\xb0\xfd\xba\xb4\x13\x47\xec\x8f\xde\xc7\x64\x4e\x6e\x7a\xe5\xea\x45\xf9\x6b\xf2\x7e\xe4\x45\x2d\xbd\xae\x09\xfc\x8c\xff\xad\x2b\xb2\xc7\x4e\x1c\x85\x2b\xc2\x35\x75\x3f\x7b\x84\x6b\x43\x65\xe8\x42\x03\x81\x66\x0e\x31\x5f\x24\x2c\x07\xe0\x2d\x4f\x53\xa8\x88\xa9\x63\x13\x0c\x65\x8a\x14\xed\x4a\xa1\x11\xc6\xd2\x52\x7b\xe1\x36\x0a\xdb\xf1\x10\x6c\xa4\xdd\xe6\x2d\x35\xc1\x6e\xbc\x65\x8b\xd3\x3e\xf8\xb9\xa9\x85\xb9\xa0\xc0\x2a\x75\xd7\xa0\xfb\xaf\x6f\xbb\x86\x9e\x27\x80\x43\x82\x39\x29\x1c\x25\x4e\x17\x75\x65\x14\xa9\xcd\x9e\x31\x27\x5e\x7a\x76\x20\x15\x3b\xf3\xca\x5b\x7d\xd4\x86\x37\xf6\x10\x94\xd5\xfd\xfc\xe8\xbc\x8c\xec\xc9\x8f\xcd\x78\x19\xae\x59\x82\x46\xf5\xbe\x66\x28\xa9\xfa\x84\xbc\xfe\x1a\xb9\x6e\x59\xf1\x75\xcd\x4e\x93\x53\x54\xe4\x8c\x82\xcd\x7b\x08\xf6\xbe\x87\xa2\xb8\xbd\xc7\xdd\xe4\x43\x78\xee\x8b\x82\xb6\xed\xe8\xe2\x58\x7e\x3d\x42\x2c\xc7\x2d\x46\x0e\x54\x6f\xba\xf9\x27\xa9\x24\x9c\x93\x4a\xc2\x79\x34\xc8\xf0\x40\xd2\x04\x3a\xeb\x66\xd4\xed\x35\xec\x50\x65\x71\x3d\x5e\x76\xcb\xe2\xd8\xc8\x21\x8f\x31\x9f\xe1\x75\xd1\x1f\xe4\xcd\x5d\x4d\xe6\x5a\x60\x1e\x87\x9f\x9d\x40\x0a\x9f\x54\x04\x40\x7b\xc2\x4f\xe6\x0f\x03\x6c\x1f\x7e\x32\xac\x3c\x47\x46\x61\xc4\x3c\x1a\x21\x8c\xa1\x54\x61\x4d\x2c\x5e\x8c\x97\xe9\xef\x3f\x36\x64\x24\x37\x31\xaa\x5f\x7f\xb2\x99\xfb\xf5\x66\x19\xce\x8a\xed\x08\x71\x64\x9d\x39\x91\x8c\xae\x32\xef\x3c\x6d\x80\x1f\x78\x2d\xe7\x70\x81\x22\xb3\xc3\x42\x05\x94\xd0\x61\x08\x5b\x5d\x29\x12\xb9\x92\xf0\xc6\xe2\xd3\xa0\xac\x02\xb5\x55\x7b\x46\xb1\x88\xaa\x55\x00\xbc\x10\xc9\x8a\xac\x10\xb7\x1a\xd9\x85\xe1\x8b\x58\x2c\x93\xbd\x9d\x91\x0e\xfd\xf5\x28\x1e\xad\x67\xf5\xef\x37\x28\x93\x6e\xb8\xe2\xe2\x03\x5c\x9b\xb2\xe9\x4f\x97\xe9\x75\x78\xa3\x7e\x0d\x33\x67\xec\xf9\x83\x46\x9f\xea\x3e\x81\x89\xe3\xe2\x8d\x2a\x94\x25\x9d\x63\x65\x27\x88\xf0\x15\xee\xd3\x45\x85\xed\x5c\xf4\x3e\x05\xf3\x3e\x5d\x34\x8c\x11\x44\xd5\x02\x05\x53\xd9\x45\xe3\x32\x96\x42\xf6\xa0\xba\x80\x8d\x9a\x62\x3c\x7f\x9f\xb8\x69\x03\x76\xe3\xb1\x7a\xc7\xd1\xbf\x1e\xfa\xe2\xc0\xc5\x57\xdc\x30\x49\xe1\xda\xf4\x6b\xf0\x46\xbd\xee\xb2\x3f\xfd\x42\x3d\x32\x7a\x10\x80\x47\x0b\x7c\x98\x24\xba\xd7\xd0\xa2\xaa\x2d\x52\x10\x55\x2a\x93\x6a\xa9\xe1\x39\x5b\x05\xae\x33\xa1\x90\x06\xe8\x85\x10\xb8\x53\x01\x39\xa6\x09\x27\xd4\x50\x95\x28\x29\xf5\x50\xbc\xad\xcc\x28\xfd\xa4\xe1\x02\x2b\xb8\xe5\xd2\xf2\x48\x2d\xd8\x8f\x49\x62\x5e\x4f\xb4\xb4\x92\x06\x92\xb2\xa8\x94\x67\x54\xa1\x56\x94\xda\x11\x4f\x6b\x40\xc6\x12\x3b\xb5\xae\x68\x3c\x6f\x9c\x5e\x19\xc6\xa7\xa7\xc8\xfc\xfd\x2f\xe7\x9e\xdd\xd0\xda\x38\xf0\x82\x36\xfd\xb3\xd3\x53\x63\xb6\xe7\xdc\x8f\x9e\x7d\xb6\xf4\x61\x29\x1e\x8f\xdf\x2a\x22\xc5\x40\xdc\xcc\xec\xe0\x63\x28\x88\xce\x46\x8a\x0c\x41\xb2\xe2\x4e\xaa\x82\x40\x71\x35\x96\xc3\xaa\xe4\x31\x70\x35\x8c\x0c\xa5\x6b\xc5\x2d\xb6\x23\xde\x29\x01\x66\x8b\x2c\xe8\x7c\x34\xdc\xa3\x47\x91\x0f\x83\xdb\x5f\xa4\x9d\x08\x33\x00\xb6\x0c\x32\x1a\x0e\x3f\x1e\x22\xa1\x6f\xd1\x3d\x54\xa0\x99\x48\x29\xa7\xf7\x60\x4d\x2a\x21\xea\x51\x18\x48\xe5\x71\xae\x95\x66\x27\xa8\x04\xc4\x6d\xb3\x25\xd0\x09\x2a\x09\x09\x89\xac\xa5\x24\xdf\x09\x82\xe3\x90\x29\x17\x25\xa5\xc2\xe8\x04\xa9\x92\x8d\x82\x5c\x5d\x54\x1e\xbe\xa8\x2f\x54\x7c\xcf\xf9\x0e\x11\xdc\xf7\xc6\x8d\xe6\x9d\x6f\xdc\x68\xde\x3b\xb3\xe4\x2b\xfc\x89\x71\xfb\x7a\xfd\x57\x5d\x0f\xc0\x08\xf2\x63\x80\x98\x6e\xb0\xc1\xb3\x0a\x90\x24\x33\xa9\xda\x85\x3c\x42\xc9\x6a\xce\xa4\xdd\xc0\xa5\x92\xdc\x1f\xd1\x99\x64\x29\xdb\x98\x6d\x6e\x39\x65\x3c\x3e\xe4\x82\xe9\x2f\xb6\xc3\x2e\xb7\xf0\x57\xea\x90\xd4\x20\x76\xd6\x37\x15\xdb\x7e\xdd\x79\x33\x6c\x71\x1d\xed\xec\xaa\xa1\x43\x20\xb6\xec\x1e\x65\xcc\x65\x18\x55\xa3\x5b\x50\x96\x05\xa8\x8a\x29\x8f\xa2\xf8\x52\x4a\x30\xa9\x96\xbb\xa1\x7a\x61\x13\x34\x23\xeb\x35\xd4\x4e\x94\x12\xe0\x5a\x28\x95\x29\x10\xc4\xf3\xa7\xb2\x22\x47\x66\x55\xf4\x09\x54\xa0\x9d\x2b\xa1\x2b\x40\x24\xdb\x34\x52\xab\xca\xa1\xaa\x03\x15\x64\xb2\xb1\xd9\xa8\xb4\x97\x75\x60\xcb\x20\xdc\x7b\x62\x21\xd9\x6d\x35\x1a\x36\xb1\x2a\x7e\xf7\x13\x0f\x9c\x65\xce\xef\x03\xab\x5d\xb9\x5f\xac\xdc\xb4\xab\x5f\x55\xbf\xc6\xa6\xb3\x32\x9d\x4b\x56\x70\xaf\xe5\x41\x2a\x1b\x9e\x79\xf1\xee\xb9\x15\x89\x54\xf3\xb0\x16\xf2\xfe\x8e\x40\x88\x1d\x6d\xb9\x06\xc9\x68\x0e\xdd\x65\xa8\xad\x39\x2b\x68\x39\xb7\xc7\x69\x54\x33\xdd\x56\xba\xcb\x78\x0f\x2b\xce\x14\x99\xf6\xac\x15\x1a\x85\x56\x41\x48\x64\xbd\xd6\xbc\x89\x0b\x4a\xc1\x9e\x63\xf5\xc2\xde\x88\x54\xb7\xb1\x49\x7a\xc0\x4c\xce\x6f\x96\xac\x28\x0d\x9c\x3e\x98\xb4\xec\xc1\xb1\xe6\x68\x33\xcd\xf7\x46\x2c\xdc\xb2\xf3\xf9\x47\xb6\x4e\x7a\x4b\xdf\x8f\x33\x17\x0e\x1e\xc7\x8d\xfe\x32\xbd\x6b\x77\xd7\x57\xc0\xf5\x66\x4a\xcf\x19\x4a\x39\x8a\xba\xdf\xd0\xca\x9d\x8b\xce\xc4\x71\xcf\x47\x0e\x81\xff\x48\x27\xd7\x94\xc6\x03\x51\x88\xff\x0b\x12\xb9\xc5\xca\xb8\x37\x6d\xee\xd8\x6a\x50\xd3\x3b\xdd\xe7\x0c\x8d\x7d\x39\x70\xf7\xcb\xec\xf7\x94\x6b\x64\x19\xc1\xb5\xa1\x20\xaa\x40\x2b\x4c\xff\x1c\xc8\x4f\x04\xcd\x24\x3e\xe7\x30\xf2\x01\xe1\x28\x92\x4e\x17\xa1\x83\x2b\x4d\x40\x73\x88\x0e\x20\x10\x32\x81\xcc\x64\x17\xe5\x71\x42\x89\x40\x4c\xa4\x38\x53\x59\x81\x37\x0b\xae\xe0\x53\xc4\x87\xa8\x6a\x83\x40\x3b\x11\xa5\x6e\xa3\x4a\xd6\x8b\x80\x94\x17\x8b\x33\x29\x48\xad\xd1\xf5\xb8\x09\x6f\xc1\x4d\x1b\x37\xe6\x35\xd5\x9b\x26\xb6\xcd\x5e\xe2\xd6\x27\x63\x6d\x3f\xde\xa1\x8f\x27\xbf\xf6\xeb\xc1\x35\x63\x2f\x3f\xb4\x6f\x7a\x68\xc9\x92\x65\xab\xe1\xd9\xa4\xbb\x8f\x72\x9d\x5c\x1b\x8a\xa0\xd5\x46\xcf\x4f\xb0\x19\xa7\x96\x37\xad\x22\xab\x06\x66\x25\x15\x20\x38\xc0\x8b\x5a\x96\x07\x86\x14\xcf\x0a\x89\x6c\x19\x9f\xd7\x1a\xe0\xa9\xf9\x9e\xe4\x45\x36\x2e\xd1\x1e\x90\x3c\xb6\x84\xea\x14\x41\xda\x30\x20\xd2\xfc\x9c\x37\x0a\x0a\x1e\x51\x15\xc2\x99\x8c\x1a\x70\x8a\x54\x47\x13\x09\xa2\xd4\xce\x3b\x03\x80\xae\x21\xc9\xb9\xc7\x50\x95\x97\xdd\x38\x9f\x8b\xc4\x9b\xa3\x72\x8c\x6a\x4a\x56\xa2\x66\x6f\x6b\x9a\x29\x9d\x7f\xc3\xba\x07\xee\x5f\x37\x6b\x0e\x13\x3e\x7e\xed\x74\xfd\x3d\xfd\x84\xfe\x5f\xfa\x81\x03\xec\x92\xaf\xbe\x38\xe7\xe5\xe5\x0f\xaf\x5f\xff\xf0\x9d\x1d\x23\xbe\xf8\x6a\xd4\xef\xef\xf8\xab\xfe\x2f\x2c\x7c\x8e\x3d\x8f\x19\xb5\x3e\x6e\x3f\xf4\x38\x2f\x31\xc6\xcb\xdb\x0d\x34\x32\xa0\x46\x61\x9f\x2d\xeb\x5d\x0a\x0b\x78\x28\x18\x4a\x60\x45\x29\xeb\x91\xc2\x94\x39\xc0\xd3\x25\x87\xc5\xde\xdd\x22\x40\x55\x1a\x2f\x0c\x08\xcb\xac\xc7\x4d\xf3\xee\x98\x33\xef\xac\xe6\xd4\x90\x09\xf3\x36\x6d\xd5\x8f\xeb\xff\xa5\xff\x5b\xff\x37\xd6\x99\x6b\xba\x1e\x5f\x73\xf7\x9d\x8f\x60\xf7\x20\xb2\x93\xed\x52\xf5\x7f\xea\xff\xd6\x7f\xc0\x66\x1d\x1d\xfa\x96\x0e\x14\x2d\xe2\x87\x19\x25\x7b\x1a\x53\x01\xa0\xdf\x9a\x17\x50\x24\xa9\x9c\x95\xc5\xdb\x70\x06\x6f\xd3\xdf\x38\x12\xe7\x79\x5b\xcd\x1f\xb8\xb6\x93\x9b\x98\x65\x2b\xa6\xdd\x70\x7b\xd7\x0a\xaa\x81\x8c\x10\xbf\x17\x30\xe4\x7f\xa0\x3f\xb7\xdd\x26\x88\x25\xd5\xc1\xa2\x62\x05\x8d\x53\x4b\x7c\x20\x7c\x44\x66\xc0\x46\x43\x56\xe0\x73\xfd\xf6\xd8\x25\xc0\xe7\x42\x5e\x05\xef\x71\x2b\x25\x5e\x25\xbc\x67\xf7\x1b\x3f\xfd\x7e\x38\xf9\xac\x45\x11\x1b\xdc\x8a\x7f\x8f\xca\xf1\x27\x14\x76\xcf\xee\x37\x83\xc7\xf6\xc1\x77\x0b\x5e\xc5\xbe\xc7\xa2\xd8\xbc\x8a\x75\xcf\xee\x37\x7e\xf6\xdd\x8f\x48\x4e\x38\x14\xbf\xb7\x5d\xf2\x8b\xbe\x44\xbb\x8f\x7c\xcc\xfa\xfc\x62\xe5\xfd\x95\xf7\xc7\x78\xb7\x28\x65\x14\x29\x83\x3a\x58\xce\x2e\x85\x7d\x7e\x83\xc8\x85\x87\xdb\x31\xcb\x59\xed\x62\xd1\xe7\x28\xbf\x0b\x1b\xf5\x12\xa7\x0c\xf5\x12\x1c\x2d\xc5\x69\x5f\x61\x4e\xa2\x6c\x03\x26\x2f\x8d\x95\xf5\xe3\x11\x78\xcc\xc4\x9b\xf9\xf7\xf0\x05\x78\xa8\xfe\xc1\x5d\x15\x95\xbc\xa5\xe1\x7e\x5d\xbd\xdb\x56\xc7\xf0\x42\x7f\xf7\x3d\x5c\x9b\xbe\x44\x97\xd8\x9b\x4f\x6e\xc2\xc7\x57\x7d\xfd\x93\xbf\x74\x7d\xcd\x84\x63\xdf\x9c\x75\xbe\x36\x54\xf7\x16\x9e\x0b\x5f\x81\x02\x28\x61\x3c\x17\x37\xed\xe9\x51\xd1\x51\x35\x04\xd1\x2e\xf4\xea\xa4\x42\xaf\xae\x09\xfa\xa5\xf4\x48\xf0\xe0\xc2\xc3\xfa\xe8\x9c\xef\x7e\x31\x69\x64\xf3\xc8\x4b\x97\x54\x49\xf8\x15\x3d\xfb\xbb\x12\x07\xef\x8a\x1c\xe4\xde\xda\xb1\x43\xfc\xce\x79\xed\xf4\xd6\x93\x1f\x32\xa3\x2f\x5a\x7c\xdd\x55\x5d\x1d\x45\x6b\xc2\x86\x1a\x4d\xd5\x1c\x0c\x0b\x03\x2b\x02\x95\xcb\xf1\x68\xaa\xfd\x34\x72\x39\xa5\x54\x2e\x07\x4f\xfa\xfe\x6f\x78\x92\x3e\x5e\x3f\xc8\xb5\xe9\x93\xf0\xd6\xae\x91\x7a\x1b\xde\x44\xf3\x84\x56\xdd\xcf\x2d\x3a\xbd\x56\x29\xd9\xa1\xad\xff\xa1\x56\xa9\xb9\x25\xcb\xb0\x25\x9f\x5e\xab\xb4\x28\xd7\x2b\xd2\x2a\x4d\xa7\x53\x4d\x63\xa6\xdd\xbf\xc6\xd4\x2a\x5d\x3e\x62\xa0\xf4\x61\xe9\xb3\x3f\xdf\x4e\x6b\x48\xad\xdd\x63\xb9\xf5\xb0\x3f\x57\x92\x37\x39\x48\xcf\x79\x72\xb3\x4a\x28\x95\xbf\xdf\x5c\xc4\x11\xe4\x5c\x09\x35\x62\xf4\xf9\x4b\x0f\x9b\xc2\x39\x55\xe4\x19\x59\x83\x20\x72\xa2\x44\xc8\x1d\xf6\xbd\xb7\x3c\x6b\x20\x81\x01\x47\x5c\x03\xbd\xfb\x58\x15\x4f\x6f\x73\x74\x57\xe7\xd2\xab\x73\xb7\x2f\x58\xb9\xf7\xe0\x86\x81\xbe\x4d\x72\x04\xd7\x0f\xff\x79\xb4\xb2\x71\x14\xb9\xe5\x5d\x5d\xe7\xee\x7c\xf8\x81\x79\x3f\x5f\xb7\xac\x39\x73\xd6\x39\xda\xb8\xf2\xd8\x45\x30\xbf\x19\xdd\xcf\x4d\x84\x77\x6f\x1c\xca\xba\x61\xc7\xb1\x41\x7a\xc8\xda\x69\x7a\xc8\x03\xa0\x29\xcb\xc3\xa9\xc7\x1b\x34\x4a\xd5\xcf\x1b\x27\x01\x52\x59\x03\x31\xe3\x12\xb3\x48\xf4\x83\xd4\x0d\x6d\x57\x07\x7b\x34\x44\x9a\x8b\x7b\x25\x99\x29\x5f\xce\xd8\xb0\xe5\x9d\x7d\xb7\xe0\xc7\xba\xb2\xec\x7e\x7d\xd4\xdf\x7f\x5c\xa3\x7f\xfb\xc6\xc9\x3d\x8f\xd7\xa7\x57\x2d\x87\x5e\x88\xb6\x4f\x9f\x56\xa2\x7f\xfe\xc4\x67\xb7\x8e\x33\x31\x13\x13\xa1\x27\x92\x44\x3f\x43\x59\x2f\xb9\x53\x8f\x4d\x23\x93\x58\x96\x56\xe3\x56\x4d\xa9\x4f\x52\x1f\x5b\x50\xf0\xc9\x55\x53\x8c\x41\x35\x48\x8a\x83\x75\x9c\x0d\x90\x14\x36\x97\x40\xe5\x7b\xaa\xf3\x1d\x1f\x9b\x98\x63\xdd\xbe\x68\x7f\xb2\xdf\x07\xa5\xac\x28\x51\xbd\x6e\x90\x33\x2c\x89\x64\x32\x4a\xbd\x08\xda\x5c\xa0\xaa\x10\x04\x45\x55\xd5\xe1\xa3\xc2\xcb\x52\xa6\xb1\x49\xa6\x88\xc3\x9e\x23\x05\x76\x7d\xd0\x6a\x78\x62\xd3\x40\xab\x15\x40\x24\xbf\xfe\xc5\xad\x1f\xcc\x16\x3f\x79\x6b\xa6\x39\xf6\x75\x1f\xdf\x34\x64\xe0\x98\x07\x1a\xab\x2e\xdf\x75\xdb\x1f\xbf\xfb\xe4\x86\x49\xc3\xef\xab\x1e\xbb\x66\xfc\xe0\x73\x37\xff\xf4\xc9\xab\x67\x26\x46\xac\x5e\xff\x0e\xbe\x4e\xdb\xa7\x2f\x17\x57\xfd\xe1\x9e\xe9\xbf\x6c\xbd\xf0\xae\x4c\x55\x63\x62\xfb\x86\xd4\x59\xe5\x81\xf3\xc7\x26\x51\x81\xbf\xce\x57\x20\x1f\x1a\x69\x38\x3b\x89\x86\x56\xcd\x7f\xc2\x5b\x17\x81\xb7\x4e\xc6\x54\x48\x86\x4f\xc3\x5a\x7f\x69\x8f\x7e\xb0\x83\xb2\xd6\x37\x2d\x3b\xba\xe7\x85\x1f\xa6\x76\x3d\xcc\x1c\x1f\xfa\xea\xd2\xcb\xe7\x4e\x43\x18\x35\x21\xc4\x1e\xe4\x2b\x90\x9f\xdc\x07\x54\x12\xcd\x8d\x48\xce\x67\xc3\xce\x42\xa5\x3f\x40\x7e\x17\x45\x49\xe5\x20\x09\x16\xc8\x1f\x91\xb5\xb0\x49\xf9\x06\xc2\x26\x65\xad\xa5\x60\xce\xa0\x18\x15\x1b\x70\xd3\x92\x8f\x57\x7f\xfa\xd9\x9c\x2d\xab\xaf\xb8\xe9\xf5\x0e\xfd\xe0\xee\x57\xb9\xeb\x7f\xfa\xce\xbc\x65\x1f\x4f\x9b\x33\x71\xe9\xab\x43\xbb\xbc\xcc\xbc\xcb\xff\x05\x73\xd2\x7d\x94\xdd\x0c\xdc\xca\x91\xb4\xef\x6b\x88\xea\xc3\x76\x21\xe4\xef\x85\xc7\x09\xb0\x38\x26\xdb\x85\x53\x10\x25\x10\xcf\x46\x2a\xeb\xa3\x3d\x52\xbb\xa8\x62\x08\x01\x86\x61\xf3\xf0\x17\xa3\xa2\x01\x3b\xac\xaa\xe5\xe7\x6c\x7d\xe0\x8a\x9b\xde\x6c\xc7\x4d\xbb\x5f\xbd\xfd\x2f\x8f\xce\x7d\xfb\xfa\x3f\x5e\x3b\x67\xe2\xed\xaf\x0d\x61\x4e\x74\xdd\x3b\xf1\x5f\x2f\x2e\x7b\x7b\x41\xc6\xc8\x73\x3f\xe1\x16\x21\x19\x0d\x42\x79\x62\x42\x5e\xeb\x20\x60\xca\xe0\x53\xd8\x9c\x2b\x0f\xb9\xcf\x22\x1e\x50\x3d\x7d\x78\x05\x95\xa2\x37\x9a\x6a\x69\x15\xf9\x58\x25\x9a\x82\xcb\xb1\xed\xcd\xf5\x93\x27\xb6\xd5\xeb\xdf\x61\xcf\x05\x2b\x2e\x5e\x79\x40\xff\x2f\xbd\x0b\xb7\xe2\xb5\xf8\xf9\x31\x47\xfb\x95\x74\xbd\xd6\xf5\x41\x43\x5a\x3f\x39\x01\xaf\x36\xb5\x07\x2d\x07\x40\xe3\x2e\x8a\xae\x3d\x85\xc2\x5d\xae\x22\x2c\xb0\xae\x44\xae\x82\x43\x3e\x2e\x61\xba\x5f\x17\x49\x10\x96\x79\xa1\xdc\x6b\x2a\xdc\xc5\x0c\x72\xba\xa9\x6c\x87\xd4\x70\x05\x49\xac\x9d\x22\x6f\x80\xc6\x4e\x25\x6a\x17\xfc\xcf\x04\xed\xf6\x4e\x9e\x78\xd9\x55\x57\x5f\x3a\x61\xca\x69\xc5\xec\xba\x27\x4c\x9c\x34\xfe\xd2\x2b\x27\x21\x16\xf0\x2d\xef\x72\x6d\xc8\x83\x42\x14\x5d\x05\xa5\x47\x2f\x6f\xf0\x53\x2a\x79\x2d\x17\x0e\x79\x18\x57\x42\x0d\x5b\x34\xd3\x80\xc7\x4b\xc9\x5d\x5e\xaa\x43\xe8\x0c\x68\x4a\x79\xe5\x61\x11\x18\x2c\x55\xe4\x85\xf1\x1b\x90\x73\xa4\x86\xbc\x50\xad\x54\xc2\xb4\xf1\xa4\x54\x4a\xc5\xd5\x9a\x3c\x4c\xb3\xa6\x97\xcd\x42\x74\x23\x33\xe4\x2f\x5f\x2d\x98\xbb\xf8\x81\x6e\xf4\xad\xfe\xcf\x1f\xa6\xce\x98\x39\xf3\xfb\x4f\xa6\x4e\xdf\xd4\x8d\xb8\xb6\xc7\x1e\x9a\xbc\x5c\xb2\xb9\x57\x5d\xfb\xec\x0b\x87\x2e\x1c\x31\x62\xd0\xc1\xb3\x86\xcd\x84\x33\x65\x6c\xf7\x51\x6e\x3b\xb7\x08\x89\xa8\x1a\xdd\x6e\x8c\x44\x36\x91\xd5\x61\xab\x96\xab\xa8\xf2\x08\x26\xf6\x94\xb6\x4b\x25\x9f\xa6\x94\x01\x4c\x81\xe2\xaa\xb3\x12\x04\xc5\x52\xa5\x00\xf8\x80\xa0\xe1\x14\x45\x92\x47\xc9\x10\x92\x0f\x8a\xaa\x07\xc6\x56\x25\xd3\x05\x5f\x21\xb6\x73\xce\x20\x70\xc0\xc2\x92\xf1\x16\x52\x64\x75\xb5\xc9\xd7\xa9\xae\xc9\x3f\xc4\x3c\xc4\x7a\xec\xca\x9b\x3f\xc6\xcc\x67\x38\x86\x07\xe9\x3b\xf5\xaf\xfe\xa1\x9f\xc4\x75\xf3\xe6\xe2\xa8\xfe\xd1\x35\x0b\x56\xde\x17\xad\x59\xbd\x02\x8f\x9c\xba\xca\x27\x0c\xf8\xf5\x93\x2f\xe8\xbf\xd7\xbf\xd1\xbf\xd1\x3f\xc8\xed\x1e\x36\x12\x4f\xc6\xd7\x0c\xca\x8c\x4c\x1f\x6a\x31\x30\x7f\x16\x89\xaf\x40\xb5\x64\x97\xaf\x36\x1b\x30\x70\x7e\x06\xec\x5a\xae\xa2\xb2\x9a\xa3\x4e\xc4\xf9\x5c\x3e\x5e\x2c\x93\x4d\x82\xe2\x2a\x9f\x96\x2d\xaf\x22\xc3\x2e\xaf\x10\x12\xed\x62\x55\xb9\x8d\x64\x32\x00\x33\x17\x43\xd4\x26\xab\x3c\x2c\x4a\xd9\x00\x57\x9d\xc9\x64\x54\x91\x37\x22\xff\xca\x0a\x51\x52\xc3\x08\x40\x00\x24\xeb\xe1\xc0\x2b\xc4\x23\x2a\xae\x82\x34\x50\x73\x11\x3e\xe8\xb4\xa0\xc0\xf3\x2e\xfc\xc5\xd3\x97\x0c\xcd\xb4\xce\x38\x3d\x34\xd0\x33\x79\xfb\xce\x0a\xcd\xbf\x48\x39\xd2\x1b\x21\x48\x31\x5a\xdb\x21\xce\x1e\x56\xe4\x9e\x81\x7b\xba\x67\x58\x8b\x4b\xa5\xbd\xdc\x33\x8c\x0a\x67\x4f\x83\x8c\x8d\xb8\x09\x6f\xc3\x4d\xfa\x41\x7d\x22\xd7\x46\xf2\xaf\x93\x9b\xf0\x01\x3d\x8d\x58\xa8\x51\x4c\x01\xad\x9c\x12\x14\x23\x2b\x8d\xa5\xd7\xcc\x85\x68\x95\x42\x48\x41\x96\x0c\x08\x0b\xb7\xa6\x54\x25\xd5\x72\xce\xec\x7b\xe5\xbc\xb4\x54\xe1\xa5\xb2\x10\x81\xd2\x14\x5c\x5f\xb1\xa7\xb2\x56\xce\xcc\xf1\x15\xce\xab\x56\x78\x29\x18\x81\xf3\x8a\x12\x35\x5f\xb1\x8a\x59\x47\x79\x15\x9c\xb5\x21\x9f\x49\x4e\x87\x5a\x45\xf4\x54\x15\x8a\xbc\xc6\xe7\xee\x27\x1e\x38\x0b\x37\xf5\x2a\x52\x3c\x06\x58\xa6\xce\x25\x2b\x48\x76\x51\x54\xa3\xe0\x2f\x33\x79\xea\x38\x1f\x43\xb8\xd1\xd9\x86\x63\x95\x49\x57\xb5\x26\xa1\x1f\x6a\x3d\xac\xb0\x29\x88\x58\xbd\x46\xc4\x0a\x92\xea\x48\x45\x2e\x72\x54\x0a\x94\xa7\x4a\xdb\x9e\x62\x6b\xcc\x8a\xa3\x18\x5f\x83\x47\xac\x20\xb3\xea\xe5\x56\xea\xfb\xf5\xad\xf8\x15\xae\x4d\x1f\x7c\x3d\x9e\x72\xa2\x83\x39\xaa\x6f\xd3\xb7\xe3\xaf\xcc\x5e\x2c\xbb\x99\x6b\x43\x16\x34\xc0\x70\x09\x60\x6d\x26\x9e\x8a\x37\xd3\xbb\x2c\x0b\x58\x15\xd6\x22\x24\x54\x6b\xe1\x01\xca\xe4\xd1\x1d\xe2\xda\x3a\x1f\xd0\x7a\x60\xa1\x2b\xd1\x00\x34\x15\x29\xc1\x64\xbe\x20\x47\xb5\x1c\xa2\xb2\xa6\x44\xe1\x65\x57\x84\x14\xc9\x15\x95\x80\x57\x8d\x4b\x1a\x79\x55\xac\x69\x10\x76\x08\x46\x45\x29\xc7\x96\x46\xaa\xc1\xd1\x34\x2e\x02\x93\x59\x0a\x8a\xd2\x4e\xde\xea\x65\xe9\x67\x8d\xe2\x9c\xc9\x3c\xef\x05\x7a\xce\xe3\x0f\x4f\x45\x3e\x97\xf3\x70\xe7\xf7\x4f\x4b\x3e\x5f\x38\xc7\x44\x3a\x9f\xb8\x06\x7f\x38\x64\x76\x6f\xfe\x79\x21\xa6\x29\x45\x73\x68\xc5\x43\xf1\x26\x15\x47\x5a\x15\x2d\x9a\x22\xa4\x94\xb0\x11\xe0\x94\x25\x15\xf7\x61\x45\x4a\x41\x05\xdb\x96\xca\xba\xdc\xa6\x68\x4a\xd6\xed\xca\x77\x5f\x5d\xf4\xe0\xb2\x18\x99\xb3\xcb\x4d\x9e\x28\x10\xdc\xc2\x24\xe8\xb0\x94\x9e\x22\xf8\x91\x0d\x3c\x54\x73\xba\x4f\x10\xf4\xc9\x27\xfa\xc1\x5d\xbb\x7a\x06\x42\xf7\xef\xd3\xbf\xc0\x15\xfb\xb0\xc3\x88\x86\x50\x51\x3c\x54\x46\xc6\x40\xf2\x17\x78\x5c\x69\x35\x64\x01\xc3\x59\x33\x38\x2a\x2f\x0e\x8e\x64\x2a\x7b\xec\xf7\x00\x2a\xc6\x0f\xbc\x73\xbf\x24\x24\xb2\x32\x04\xe1\x72\x50\x48\x40\xff\xca\x2f\x17\x02\xa7\xd0\x7f\x17\x38\xe5\x87\xd2\xdc\x2b\x80\xda\xb5\x4b\x3f\xf8\xc9\x27\xbd\x82\x28\xfd\x5f\x74\x2c\xf7\x93\x48\xca\xd4\x2a\x3c\xc8\xfb\x51\x10\x55\xa3\x38\x7a\xdc\xf0\x62\x32\xbb\xe4\x94\xfa\x14\xb7\x69\x4a\x55\x8a\x96\xce\x84\xa4\xd9\x24\x2e\x34\xc6\x15\x3e\x05\x94\x43\x7b\x4a\xa9\x31\xd9\x78\xd9\x1a\xa8\xb9\xd5\x38\xa9\x95\x91\x6a\x0b\x91\x85\xe9\x93\x4b\xab\xa8\x2d\x98\x6a\x21\x29\x6b\x0d\xf5\x92\x75\x7b\x45\xa9\x5d\xf2\x95\xd6\xd0\x45\xab\xa2\x10\xd5\xdd\xe4\x2d\x7d\xb5\x0b\x49\x2e\x27\x47\x4f\xc1\xcc\x13\x70\x34\xcf\x48\x64\x2f\xd2\x05\xc6\x7e\x72\x57\x5f\x76\xde\xe7\xf8\x3b\xdd\x53\x44\x4b\xd4\x47\xef\xeb\xba\x54\xeb\xc9\xd0\xd3\x31\xb3\xc5\x78\x1f\x6d\x19\xde\x8f\xea\xd1\xd9\xe8\x0d\xca\x08\x52\xc4\x74\xb6\x7f\x7e\x62\x6a\x6c\x9a\x72\x96\x31\x31\x72\x12\x14\x74\xc9\xfc\x0c\x82\xf9\x69\x90\x35\x03\x0a\xfd\xdf\xcc\x0f\xf9\x24\x79\xec\xa2\xac\x65\x23\xd0\x94\x8f\xc4\x84\x84\x3a\x98\xcc\x5a\x03\x99\xb5\xba\x44\xd3\x59\xd5\xc1\x8c\x3a\x90\xa4\x36\x96\x7e\x19\x32\x7f\x39\xb7\x1c\xac\xa6\xfa\xec\xa5\x46\xbf\x20\x2e\x2a\x21\x32\xa5\x1d\xc8\x1d\xe9\x57\xd7\x00\xfc\x06\x87\x78\xba\x49\x3c\x1d\xbe\xed\x0c\xa4\x47\x9c\x62\x9f\x22\x29\xdd\x43\xfa\xb1\x37\x8a\x90\x6f\x8f\x75\x7d\x7a\x06\x1a\x24\x4c\x31\x4d\xf9\x7a\x83\xe2\xfa\xf2\x22\x39\x34\xa5\x7b\xac\xed\x35\xde\x8f\x6a\x50\x0a\x35\xa3\xa1\x68\x0f\xca\x46\xc8\xbc\x87\xd2\x64\x51\x2a\x2d\x29\x00\x97\xd1\xe9\x6f\xb6\x69\x4a\x23\x9d\xfe\xdc\x60\x29\xe2\x70\x25\xd4\xc1\x6e\xfa\x08\x86\x51\xb9\x57\x19\xe4\x5e\x07\xd0\x47\x90\xa6\x8f\x20\x9d\x7f\x04\x69\x78\x04\x69\xf2\x08\xd2\x5e\x35\x83\x13\x39\x99\x26\xed\xc3\xc9\xd4\xd7\x92\xa9\x8f\xc6\xea\x1a\xc9\xd4\x0f\x80\xa9\xaf\xcc\x64\x94\x8c\xb8\xd3\x2d\x85\x2b\x06\xb6\xc0\xdc\x0f\x76\x03\x11\x46\x6d\x8e\x88\xd2\x4e\x54\x19\xad\xad\x4b\x9f\x79\xda\x7b\xe7\xfa\xa7\x59\xc9\xd8\x2c\x01\x14\xa6\x7e\x42\x57\xe7\x6d\x53\xdb\x6f\x9b\x77\xcf\x6f\x8c\x32\x40\x97\x72\xba\xe5\xbd\x96\xd6\x07\x7a\x3c\x83\x5d\x5d\xe7\xbe\xbc\xfa\xbe\x05\x1b\x9e\x80\x42\x41\xdf\x05\xdf\x75\x93\x51\x3b\x60\x50\x12\x21\x3e\x63\x19\x83\x2a\x51\x23\xda\x84\xa8\xa1\x67\xcc\xaa\x81\x20\x8a\xea\xb6\x1a\xe6\x73\x8d\xb4\xb6\x6e\x83\x5d\xd9\x56\x30\x9f\x6b\x4a\x2a\x15\x87\xd5\x28\xad\x49\x57\x44\xc9\x57\x2b\x90\x90\x20\x27\x57\x3d\xcd\x0e\x49\x50\x41\x22\xd5\x90\x4f\x03\xdf\xc4\x68\x05\x54\x8e\x54\x6f\xbd\x28\xa9\x89\x64\x26\xa3\xd4\x8a\xed\x36\xb7\x1f\x32\xf7\x90\x94\x75\xc8\x76\x88\x26\x1a\x63\xa2\x94\x75\x78\x43\x24\xb8\xb3\x90\x7d\x1e\x53\x2d\x44\x5a\x7d\x2f\x6a\xee\x45\xb0\xd1\xdd\x8b\x56\xd5\x36\x8b\xd8\x9f\x8e\x1a\x5d\x3d\xdc\x3c\xb0\x35\x9a\xdc\x3a\xe9\x2d\x86\xb9\xfa\xb2\x77\x5e\x9f\x72\xd9\xda\x8b\x56\xd5\x5c\x7d\xdd\xdd\xb7\x65\xba\xfe\xd9\x75\x24\xb7\x0d\x37\xad\xc4\xc7\xb6\x54\x4f\x9b\xdd\xbe\x5c\xe8\x46\xb4\x60\x2f\x43\x83\xaf\xb4\x26\x19\x4f\x5f\x75\xeb\xf8\xad\xd9\x97\x5e\x61\xf8\xae\xef\x56\xfe\xa4\xaa\xb6\x31\x31\x6a\xed\x52\x7f\x7f\xc3\xa7\xcf\x6f\x19\xc5\x57\xa0\x1a\x54\x4f\x76\xd1\x28\xc8\x12\x9b\x3e\x7d\xf5\x46\x1b\xa2\xbe\x67\x1b\x22\x90\x54\x4b\x8b\x9a\x57\x0d\x49\xa5\x9a\x4a\x14\x73\xa9\x6c\x75\x2d\xf9\xde\x6a\x32\x71\x86\x60\x31\x9f\x48\x81\xc6\x29\x20\x07\x6b\xab\xa9\x6f\x52\x44\xcc\x06\x42\xd1\x4c\xde\xb5\xdc\x17\xce\x64\x94\x3a\x51\xa9\xc8\xa8\x96\x7a\x5a\x74\xf2\x88\xaa\x4b\x2a\x9a\xa7\xe6\x3e\xed\x43\xc3\xc0\x87\x76\x2d\x60\x25\xb6\x8a\x30\x4b\xf8\x3c\xe3\xbc\x1f\xaa\xfe\x6a\xe1\xd0\x21\x03\xd3\x99\x85\x5b\x5e\xfa\x25\x6e\xba\x70\xf0\xb8\xf9\xfa\xaf\xe9\xf4\x4c\x31\xbb\x8c\x47\x76\xbe\x56\xf1\x8d\x3c\x22\xf3\x34\x78\xfd\x81\xed\x1f\xb3\xd8\xd0\x22\x3e\x6a\x0d\x5b\xc6\xa0\x46\x34\x08\x7d\x6c\xec\xa3\x03\xd2\xea\x40\xab\x46\x59\x96\x0e\x41\xcb\xfa\x00\x80\x67\xef\x69\x6c\xe8\x83\x66\xa3\x2f\xaf\x4d\x9c\x89\xc6\x49\x96\x90\x71\x6b\x58\x19\x9c\x54\x92\x85\xde\x4d\x32\x8f\x99\x4f\x42\x9d\x30\x69\x28\x13\x93\x78\xcf\xe0\x8c\xb7\xe2\x84\x51\x3d\x52\x87\xe0\x84\x2a\x24\xe9\x0c\x7a\x45\xd5\x31\x80\x5a\x06\xba\xeb\x32\x19\xa5\x55\xcc\x95\xf8\xa2\x71\xd8\x3d\xab\x25\x35\x08\xba\xba\x19\x87\x28\xb5\xbb\xab\x9b\x5a\x81\x47\x25\x66\xcb\xbd\x15\x19\x40\xd0\x91\x7d\xd7\x22\x02\x57\xa7\x47\x1b\x88\xbc\xcc\xb5\xcd\x80\x6a\xeb\x2b\x17\x50\x49\x8b\x47\xcd\xd4\x89\x86\xd2\x20\x61\xba\x6b\xf4\x8f\xd7\xb4\xdc\x97\x89\xe3\x18\x2e\xb9\x6a\xf3\x95\x93\xcf\x5b\x3c\xe2\xde\x9f\xda\xb6\x3e\xfa\x64\xfb\x1f\x7e\xa3\x1f\x7b\x62\xfa\x57\x73\x72\xdb\x38\x7f\xd9\xb5\xa3\x46\x5d\x75\x5b\xf3\x1d\xa6\xc1\xe2\xdf\x56\xd6\xc7\xa7\xac\xc7\x11\x3c\xa0\xaa\xff\xd1\xb2\xda\xcd\x3b\xe2\xb1\x1b\x9e\xbc\x7b\xdd\xf3\xbf\xb8\x74\x5c\xc7\x2b\x4c\x69\x57\xae\xdf\xd9\x99\xa6\xb6\x16\x1a\x2b\xd7\xe9\x7e\x6b\x98\xaf\x40\x4d\x68\x03\xca\x36\x92\x27\x91\x48\x83\xd9\xb2\xda\x40\xe7\x1c\x3c\x97\xe3\x02\xcd\xab\x95\xb2\x24\x38\x7d\x51\xd0\x37\x78\x63\x34\x42\xcb\x29\xe9\xd1\x14\x77\x4a\x49\xc2\xe6\xaa\x26\x3c\x9a\x92\xa0\x8a\x48\x61\x0f\x35\xc4\x18\x90\x14\x25\x95\x77\x64\x32\x4a\x42\x6c\x17\xbc\x92\x8d\xce\x67\xb6\x4c\xa6\x55\xb8\xc6\x28\xf4\x8d\x55\x4f\x83\xe1\xba\xac\xca\x71\xba\x5e\x1d\xa2\xc1\xf2\x6e\xa5\x2b\x15\x42\x9d\x72\x1c\x3d\x35\xcc\xd5\x88\x59\xc9\x7f\x75\x5b\x5f\x39\xb8\x61\xe9\xd8\x29\x63\xcf\x39\x1b\xff\x50\x27\x35\xb5\x2f\xfc\xcd\x3b\x26\xce\x35\x77\xc7\x02\xfd\x7d\xfd\x7b\xfd\x20\xbb\x64\xed\xf8\xf1\xaf\x2b\xc9\xcf\xcb\x2f\x1e\x3c\x6a\xcd\x25\x97\xff\xee\xed\x02\xdc\x95\x72\x39\xd8\x25\x9d\xab\xd8\x25\x06\x57\xc2\x72\x33\x9c\x45\xcb\x0c\xac\x28\x39\x7b\x54\x8b\x55\xa3\xfe\xe2\x41\x2b\x85\xa5\x53\x61\xda\x1a\x9a\xae\xd5\xd0\x62\x9c\x81\x7c\xb5\xe2\x84\x5a\xe1\xa3\x8a\xb5\x61\xb7\x28\x65\x2d\x0e\x92\x19\x29\x56\x51\x15\x83\xc0\x83\xca\xfa\xc0\xb5\x08\xa9\x16\x24\x4a\x4a\x35\x10\x71\x58\xb7\xbf\x82\xfa\x08\x80\x9c\x4f\x9a\x92\x10\xf2\x5b\x58\x4f\x18\x03\x39\xc7\xa3\x55\x71\x92\x4c\xbc\xff\xc7\x03\xf1\xab\xda\x36\xdc\xfe\xe9\x6f\x7e\x93\x9b\x72\xd1\xaa\x91\x4b\x2e\xbf\x6b\xf3\xb2\x7f\xe9\x27\xff\xb5\x93\xf7\x9f\x8c\xcf\x6f\xab\xa9\x1f\xd8\xef\xdc\x8d\x77\x52\xcc\xc2\xc5\xfd\x47\xb4\x9c\xbb\x7e\x5e\x47\xee\xb2\x61\xd4\x1f\xd1\x92\xe4\xfd\xc8\x86\x1c\x68\x8c\xa1\xfe\xc1\xdb\x0c\xc4\x86\xc3\x46\x07\x4a\xf3\x52\x81\xe2\xef\x0d\x7f\x26\x1b\x88\xba\x92\xcc\x06\x1a\x45\xbc\x0d\x60\x24\x2a\xeb\x10\xa5\x62\x38\x7d\x54\xae\xc1\xd1\x8d\xb8\x89\x1d\xa3\xdb\x18\x7b\xe7\x26\xfc\xbd\xee\x06\xbc\x7c\xd7\xa5\xda\x41\x12\x6e\x19\x1a\x49\xa3\x41\xa7\x30\x8c\x6f\x32\xba\xce\x36\xc1\x91\x4e\xa7\xb3\x2e\x06\x25\x72\x6e\xaf\xe8\xf3\x57\x07\xd3\x58\x29\x01\xb1\x0f\x57\x2a\x87\x69\x39\xd8\x9d\x52\x30\x6d\x79\xfa\x52\x39\x2b\xfd\x9c\x3f\x05\x12\x03\x2d\x25\xbb\xdf\x6c\x3c\x76\x1d\x92\x13\x76\xb7\xe2\xf2\x2a\xe1\x3d\x8a\xdb\xab\x78\xf6\xec\x7e\x33\x74\x6c\x2f\x6d\x24\x39\x1b\x38\x05\xed\x71\xab\x4c\xe4\x04\xa7\xe0\x3d\xbb\x87\xbc\x7e\xac\x8e\x7e\xc5\xd1\xe0\x56\xec\x7b\x54\xcc\xd8\x54\x26\x7a\xc2\xad\xb0\xc5\x5f\xf4\x36\xa8\x6e\x8f\x4d\xf1\xec\x71\xab\xc1\xe8\x09\x25\xb4\x67\xf7\x1b\x7f\x3b\xbe\x90\x7e\x4d\x68\x50\x1d\x76\x9b\x62\xdf\xe3\x56\x2d\x55\x27\x14\xae\xf8\x6b\x22\xc8\x13\xaa\xa1\xa0\x4d\x0d\x56\x9d\x70\x2b\x81\x3d\xbb\x87\x64\xbf\xed\xa4\xc2\x01\x7c\x83\xca\x59\x6c\x8a\x65\x0f\xa7\x5a\x63\x27\x2c\x8a\xad\xf0\x45\x55\x94\x6c\x8a\xcf\xab\x48\x7b\xdc\x8a\xdf\xab\xc8\x7b\xd0\x70\x2f\xc2\x0c\xcb\x59\x78\xab\xdd\x23\xc9\x81\x60\x2f\x35\x42\xe8\x63\x49\xe4\x1b\x6c\x82\xdd\xe1\xf4\x78\xc5\x53\x7f\x93\xd1\xd7\x6a\x6c\x12\xd3\xa5\x98\xfc\x9f\x8d\x39\x70\x8c\x2d\xfe\xcb\x1b\xb7\xdf\xf9\xc1\xe2\x15\x6f\x7c\xf0\xf1\xd2\x65\x1f\x1d\x78\x6d\x79\xe1\x2f\x8c\xa2\xc7\xf1\x47\x7a\x0d\xfe\xb8\x6b\x1c\x79\xa6\x96\x8e\xa2\xbf\x7f\xab\x4b\xa6\xf7\x66\x06\xfc\x74\x3d\x68\x52\xbe\xc3\x98\xc3\x1c\xb2\x71\x09\x78\x70\x56\x2d\x2b\x90\x27\x6c\xa3\x9f\x72\xa4\xe0\xaf\x14\x5f\xe0\x85\x67\x6d\x4b\xa9\xd6\x10\xec\x39\x56\x0a\x9e\x70\xa6\x54\x36\x44\x02\x3a\x55\xcc\x67\xd4\x40\x86\x32\x7e\xdf\xc8\x3e\xf9\x9d\x7e\xe1\x77\xf0\x91\xe1\xbb\x7e\xc4\x51\xfd\x33\x56\x31\xff\x04\x58\x92\x23\xc0\xe7\x5b\x84\x2a\xd0\xb5\x86\xa3\xa3\x5d\xd0\xa0\x59\x42\x97\x7d\x44\xd0\x14\x91\x22\x44\x4b\x01\x55\x42\xae\x2d\xe2\x84\xe2\xa2\x22\x7d\x51\x12\xb4\x5b\x45\x49\x95\x43\xa0\x5a\x00\xc6\x85\xf6\x10\x95\xb9\x8f\x88\x59\x1e\x95\x1a\x6d\x93\xde\x90\x93\x5e\x4c\x3f\xd8\xc7\xea\xc6\x5c\xb3\x63\x7d\x2f\xc2\xdf\xa4\xb3\xd8\x59\xdf\x54\x6c\x7d\x55\x7f\xab\x17\xe9\x6f\x1f\x5e\xbe\xd4\x1c\x83\x65\x31\x68\x16\xdc\x60\x44\x1d\x3d\xc7\x10\x17\x0a\xa0\xc0\x3a\x08\x30\x8c\x71\x94\x14\xc6\x01\x14\x76\x32\x8e\x48\x94\x8e\xa3\x9c\x84\x13\x94\xe2\xad\xc6\x43\xa2\x94\xe5\x51\x39\xf5\x3a\x38\xf5\x48\xfa\x2a\xd7\xf5\x19\x52\x13\xd5\x88\xd9\x79\x9a\x81\xe5\x05\xeb\x62\xab\xa7\x17\x86\x87\x30\xda\x80\x57\xb1\xfb\x79\x3f\xf2\xa3\x4b\x91\xe2\x4d\xaa\x36\xb7\x96\xf5\x42\xdc\xee\x25\x47\xbc\x33\x05\x1b\x93\xe1\x78\x1a\x82\x1d\xd8\x4f\xf9\x52\xce\x50\x91\xe9\xa9\x25\xa3\xb8\x44\x95\xb7\x91\x8d\xd6\xe6\x35\x31\xd8\x62\xda\x90\x55\x0a\xc8\x62\xcc\x38\x4b\x36\x1c\x73\xba\x2f\x79\xf1\xa9\x67\x8e\xaf\x9e\x79\x05\x5e\xc5\xad\xfe\xfb\xb0\x7b\x97\x6e\x58\xdb\xf5\x09\xfe\x26\x77\xcf\x1a\x7d\x71\xe1\x9e\xca\xc1\x4d\x43\x29\x49\xaa\xa2\x5b\xcb\x96\x40\xe2\x56\x12\x00\xb4\x0b\xa4\xff\xee\x02\x8b\x20\x64\x12\x2f\xc9\xfd\xc8\xa1\x22\x22\x81\x1b\xc0\x49\x1c\xef\x11\x21\x9d\x10\x4b\xe8\xe7\x04\x51\xb5\x3a\x0b\x4a\x50\xbe\x1e\xec\xc5\xa2\x3b\xa6\x41\xdc\x86\x35\xf7\x0d\x3d\xa7\xbe\x7e\xac\xd3\x7d\xe9\xaf\x9e\x7a\xe6\xf8\xb9\xa3\xc9\x9d\xb3\xab\xef\xbc\x37\xa8\x78\x27\xba\x07\x4f\x5f\xf2\xf4\x63\xe4\xfe\xaf\xbc\x0a\x06\xc0\x74\xef\x46\x41\xbc\x8e\xf7\x23\x27\xf2\xa3\xd1\xc0\xe8\x62\xdd\x5a\x96\x75\x98\xe2\x5b\x8a\x2f\xa9\x7a\xac\xb4\xb5\x63\x21\xdb\xac\x6a\x0b\x69\x8a\x98\x82\xdb\xb7\x59\x44\x49\xf5\xd0\x4e\x8a\x83\x16\x96\x7d\x74\x59\x18\x44\xca\x34\x1c\xd0\xb4\xaa\x17\xab\x1a\x95\x1e\xba\xe8\xd8\xa6\xb5\x57\xaf\xbb\xfb\xce\x3b\xef\xae\xcb\xb9\x97\xb3\xcb\x3b\xaf\xb9\xe7\x21\xcb\x9a\xb9\x73\x17\x18\x73\xc9\x1c\xe1\x3e\x46\x5e\x34\x00\x29\xce\xa4\x6a\xe5\xb5\x3c\x6a\x36\xd4\x0b\x35\x6b\x05\x4d\x5a\xb6\x27\x6a\xd6\x6a\xcc\x41\x47\xcc\x3e\xe0\xde\xf1\x03\xcb\xbc\x25\x0d\x0b\xef\xc0\xab\xd8\x51\x3f\xbb\xf0\x32\xfe\x43\x7e\xfe\x0c\x7d\x22\xd4\x6b\xf0\x12\x66\x0e\x77\x80\x5e\xc7\x93\x54\x59\xe3\x3a\x3c\x74\x97\x7b\x21\x96\x3d\xa2\x64\x0a\xc7\xb7\x1a\x04\x14\x13\x0a\xd3\xe4\x0b\x25\x17\xde\x71\xfc\xa5\x98\x73\xc0\x7d\x97\xa4\xf0\x72\x72\x05\xbc\xad\x73\xf7\xea\xd1\x97\xc2\x7a\xad\x47\x41\xd6\xcd\x1d\x40\x25\xe8\x62\x58\xaf\x0e\xb7\xa6\x84\xe1\x72\xa6\xba\x99\x4d\x48\x40\x03\x56\xa2\x98\xe5\x10\x85\xe8\x0a\x92\x68\xda\x16\x3a\xbc\x74\x11\x84\x45\xc5\x05\x1d\x22\xb9\xc7\x8d\xf8\x7b\xbf\x6b\xf5\x12\x19\xf2\xb1\xb1\xfd\x1b\x1a\xa7\xea\x9d\x76\x5b\xfd\x8a\x31\x85\x1b\x9b\x32\xc5\xab\x04\xb0\xbb\xfe\xf2\x9f\x9c\x77\x01\xd9\x8b\xc9\xda\xfd\x82\x3b\x00\xf8\xd1\xa9\x30\xe3\x2e\xb7\xa6\xc8\x26\xfb\x30\xcb\xca\x66\xa5\x52\xc1\xa9\x3c\x84\x34\x54\x04\x21\xcd\x09\x34\x88\xfe\x4f\x50\xa4\x3e\x31\x2d\xa6\x7d\xbd\x51\xa4\x1b\x8e\x2d\xfd\x10\x73\xba\xfe\xf2\xae\x67\x95\x8d\xe7\x0c\x1f\x7f\xde\xfd\xe4\x79\xe9\xbf\xc5\xad\xfa\xc6\x73\x7e\x79\xdb\xdd\x9b\xce\xee\xd7\x32\x08\x61\x14\xc7\xab\x2c\xd3\xb9\x03\xa8\x1c\x7d\x8e\xb0\x12\x81\xb2\xb4\x71\xe0\x63\x20\x70\xe6\xfc\xf4\x56\x2a\x8c\x73\x7e\xd8\x31\x43\x7e\x07\x35\xb8\x95\xf2\x3d\x9c\x8a\xab\x4f\xb8\x15\x66\xcf\xee\xa1\x17\x7e\x77\x11\x8d\x00\x78\xaf\x22\xec\x51\xcb\x6a\x4e\x28\xe1\x3d\xbb\x87\x3c\xf6\xed\x23\xf4\x1f\xf8\xe0\x4c\xe6\x54\x7f\xed\x09\xb7\x22\xef\x51\x78\x6f\xbb\x95\x17\x7c\x89\x76\x1b\xf9\xa8\x94\x79\xdb\x4b\xca\xc2\xbe\x44\xd6\xca\x0b\x45\xb8\x11\x5b\x26\x5b\x52\x16\x16\xa5\x0c\x1a\xee\x41\x98\xb1\x09\x92\xcf\x2f\x87\x4b\xca\xca\x79\x6b\x9f\x73\xd8\x41\xbe\xdc\xf7\x8b\xc6\xc9\xeb\x4b\xfb\x02\x64\x41\xb7\xfa\xa2\xbe\x08\x96\xe1\x4f\x69\x36\xca\xb0\x31\x2b\xcf\x46\xe3\x7f\x9f\x51\xe1\xe7\x98\x88\x30\x1b\xdb\x66\xda\xcb\x79\x2e\xea\xbe\x41\xeb\xd4\x3b\x27\x9d\xc7\xd7\x36\x8e\xd6\x75\xee\x80\xbe\x7a\xc5\x9a\x86\xcd\x51\xfc\x88\x3e\x37\xbe\xb5\x3a\xf6\x4a\x1a\x2f\xea\xdc\x8d\x97\xe3\xf0\xc6\x37\xf5\x77\x28\x16\x27\xc8\x6e\xe1\x0e\x20\x19\xf9\x10\xa8\x38\xba\xa1\x3d\x09\x7d\xc9\xc6\x26\xdf\x29\x2c\x87\x86\x61\x3f\xb6\x6e\xf1\x3a\x39\x21\xb4\x19\x23\x7d\x75\xfa\x95\xe5\xe7\xa7\xaa\x06\xaf\x68\xf6\x70\x07\xf4\xba\xf4\x4f\xce\xbf\x08\x1f\xe9\x1c\xb7\x62\x85\xb3\xc3\xfe\x58\x1d\xac\xfd\x30\xfb\x06\xde\x6c\xe9\x40\x3c\x8a\x23\xd0\x77\xce\x21\x0e\x09\x5c\x02\x2b\x56\x60\xfe\x72\x3e\x0d\xba\xf6\x1c\x43\x25\x36\x1b\x9b\x7c\x52\x6b\x34\xc8\xb3\xe1\xf3\x2a\x70\xd8\x9d\xfa\x29\xfb\x06\xee\x77\x20\xb0\x57\xff\x0b\xc5\x5e\x84\xd9\x37\xd8\xc5\xf0\xf3\x5c\x68\x24\xfd\x89\x8a\x90\x36\x7e\xa8\x69\x34\x40\x7f\xae\xc2\x51\xf8\x90\xc3\x07\x64\x54\xf3\x12\x8a\x00\xcc\x3a\x87\xa4\xb8\x8a\x2e\x97\xee\x79\xd5\x1f\xce\xab\xc0\x21\x4f\xd1\xd5\x0b\x37\x51\x18\x93\x95\x8c\x09\xec\x0e\xac\xc6\x98\x6c\xf0\x6a\xf0\x3e\x0d\x2e\xcc\x23\x4a\xc1\x6d\x6c\xf2\xb5\x48\xad\x69\xc6\x1a\x0d\x07\x66\x34\x7f\x3c\x22\xa6\xff\x95\x3d\x72\x15\xf6\x2d\xd0\xff\xf5\xcd\xff\xfe\x1c\xf5\xba\x3f\xf8\x79\x96\x1e\xf7\xc7\x18\xf7\xc7\xd0\x53\x90\xfc\xbc\xd6\x68\xc0\x17\xab\x65\xc2\x6e\x1c\xaa\x19\xfe\xf1\xa0\xa9\x96\x8d\x81\x7f\x75\xa3\xe5\xd8\x41\xe2\x89\x3b\xb9\xf5\x68\x39\x7f\x33\x72\xa1\xc1\x48\x41\xc9\x1c\xa6\xad\x22\x6b\x32\x67\x83\x3f\xc1\x9c\x73\x87\x73\x0e\x68\x0f\x65\x39\x38\x34\x38\x2b\x1c\x7b\x48\xb5\x62\x91\x22\x95\xd9\x66\x4a\xed\x69\x86\x8c\x77\x79\xff\x96\x96\xfe\x73\x1f\x7a\x88\x5b\xbf\x3a\x5d\x5f\x9f\xfe\xd9\xdd\xd7\xcf\xb9\xab\xf7\xb5\x1c\xc9\x9c\x9d\x5e\x8b\x33\x37\x23\x83\x61\x4c\x02\x7a\x72\x2d\x2b\x24\x1c\x56\x4e\x48\x28\xf6\x14\x52\x39\xbb\xd1\x5b\x62\x07\xb6\xa4\x65\xa8\x86\xa7\xe5\xaa\xda\xe5\x0f\xcd\xa5\x57\xb3\xdc\x77\xc3\x8a\x9f\x91\xcb\xad\xbe\x0b\x61\xe4\x65\x37\x31\xd7\xf0\x51\x24\xa2\x4b\xa9\x06\x8e\x2a\xd0\x5e\x23\x43\x5e\x04\x29\xa9\x08\x87\x73\x36\xba\xb7\xd8\xbc\xaa\xd3\x91\x50\x2d\x21\x8d\xec\x31\xaa\x4d\x30\xf4\x26\x91\x6a\x17\x28\x96\xdf\x23\xaa\x16\xb1\x87\xde\x21\x95\x68\x8a\x35\x1b\x4a\x87\xde\x05\xeb\xd7\xfd\xea\x1f\x07\x3e\x18\xd4\x72\xf9\x15\x96\x2f\x86\x3f\xb0\xfc\x9d\x73\xaf\xff\x20\x31\xbf\x71\x50\x2b\x79\x66\x51\x76\x13\xb3\x00\xee\xe5\x6c\x04\xf4\x08\xe3\x16\xd0\x61\xd5\x11\x02\x01\x3f\x8f\x23\xef\xbc\x45\x6e\xc1\x0d\xda\xff\x10\xbc\xb0\x36\xb1\x87\xed\x03\xed\x03\x04\xe5\x58\x73\x6d\xf4\x85\xf5\xeb\x17\x8c\xbc\xe2\xf2\x96\x41\x1f\x1c\xf8\x87\xc5\x7d\xc7\xda\xe1\xcf\xb4\x0e\x6a\x9c\x9f\xf8\xe0\xfa\x41\x74\xad\x4c\x42\x7e\x2e\xc3\x5d\x88\x78\x84\x7c\xcd\x58\x16\xb0\x3c\x89\xfd\xa2\x6b\x02\xb3\x1d\xbf\xb3\x06\x1f\x3f\xae\xbf\xa5\x7f\x7d\xac\xd7\xf7\xb5\x36\x0b\xb8\x19\xcb\x93\x98\xed\x5d\x13\xd8\x2f\xfc\xc7\x70\x18\x0f\x39\xae\x7b\xd7\x18\x67\xdd\x20\x6e\x1a\x57\x0e\xdf\x87\xd3\x38\x26\xe0\x7a\x7c\x7c\x0d\xee\x38\xa6\x7f\xad\xbf\x35\x88\xfd\x53\x67\x84\xfc\x33\xd4\xfb\x7b\x7d\x69\x81\x7c\x77\xfd\x71\x3c\x04\x87\x8f\xe9\xa3\xd7\x70\xe5\xe4\x26\x3a\x23\xe4\xfb\x76\x73\x1f\x71\x15\x7c\x14\xb9\x50\x84\xac\x3f\xc5\x96\x56\x59\x0e\x9c\x99\x28\xc9\x9c\x45\xc6\x0a\xf3\x35\xb7\xb4\x46\x23\x38\x28\xc7\x6a\xe3\xbc\x75\xf7\xab\xe7\xe2\x19\x15\x4f\x5e\xf0\xee\xcf\x2f\x1e\xfb\x04\xf7\x51\xe9\xab\xf3\x07\xb6\x8f\x2a\xbd\xfa\xb2\x4b\x7f\x52\xf4\x33\xdd\xa8\x12\x4e\x3c\x86\xd3\x14\x3e\x85\xc9\xd3\xf7\x02\x86\x1d\xe2\x0a\xca\xc6\xe9\xe9\xd6\xbf\xbb\xa7\x3d\x3f\xdf\xc3\x8b\xbf\x7b\x3d\xb7\x17\xcd\xe4\xeb\x10\x8b\xfa\xd3\x77\x85\x43\x12\x97\x30\x7e\xc3\x0a\x07\x8b\x97\x85\xc7\x68\xfc\x86\x1a\x9b\x58\x31\x2d\xce\x7c\x8f\xdb\x8b\xa7\xeb\x4f\x23\x8c\x4b\xb9\x8f\xd8\x37\x2c\xdb\x11\x8b\xaa\xc8\xcf\x50\x31\xaf\x91\x5f\xe4\x5f\xab\x08\x27\x72\xac\x17\x59\xb9\x84\x6a\x81\x6d\x1a\x37\x47\x65\x5c\xca\x6c\xe1\x3e\x3a\x74\x08\xe1\xee\x7b\xb8\x8f\xf0\x7e\x3e\x8a\x6c\x28\x0a\xff\x16\x26\x4a\x80\xab\x5a\x00\x21\x4b\x6b\x0a\x1c\x79\xeb\x59\x32\x5d\x64\x54\xb7\x6d\x1f\x86\x27\x0e\x3c\x79\x3e\xf7\x51\xe9\xdb\x33\xe4\x81\x07\x52\xf0\x7c\xf4\x41\xdc\x47\xe8\x76\xf3\x67\xf1\x30\x47\xe6\xcf\xe2\xe0\x67\x21\x95\xe1\x0d\xab\x2e\xdc\x1c\x0d\x04\xe5\x58\x03\xd6\x07\xe1\x89\xc3\xb6\xbf\x33\xec\x9f\xbc\x53\x9e\xf1\x76\xe9\x80\xbd\x14\xa3\xbf\x5e\xbf\x08\xcd\xec\x7e\x91\xce\x0b\x9b\x24\x3b\x1c\x99\x17\x54\x98\x17\xf6\x70\x8e\xa1\xf3\xc2\x98\xf3\x62\x4d\x8b\xb1\x99\xef\xbd\x77\xa9\x0e\x3d\x42\xfd\x45\xfd\x11\x7c\x79\xf7\x0c\xc4\x92\x75\xc0\x26\x55\xc4\x6b\xe4\x17\xcc\x0b\x8b\x13\x39\x06\xe6\x05\x35\x36\x59\xa2\x72\x54\x7f\x91\xd9\xd2\x35\xf9\xa9\x43\x08\xeb\x9f\xeb\x3f\xc1\xd1\xee\x5f\xd2\x71\x58\x92\x2a\x36\xc6\x61\x3b\x4c\xa6\x12\xc6\x81\x2d\xc6\xc6\x61\x31\x86\x11\xd7\x3f\x37\xc6\x31\xf2\x4a\x18\xc6\x08\x3a\x27\x3d\x7e\x96\xad\x30\x27\x36\x73\x4e\x54\xce\x66\xee\xfa\xd8\x98\xde\x98\xfe\xb9\x31\xc1\xef\xea\xb7\xe5\x27\x98\xe9\x1e\x8d\x10\xea\xe0\x46\x23\x06\x59\x50\x09\xcd\x81\x8d\x06\xb1\xc2\xa6\x54\xc6\xab\x29\x5c\x0a\x35\x36\xc5\x4a\x31\x8e\xb2\x1d\x1d\x1d\xfa\xa3\xf8\xc6\x0e\x5c\xae\x7f\xc9\x8d\xd6\xbf\x44\xb8\x7b\x34\x5b\x6f\xfc\xfb\x00\x52\x98\xa4\x8a\x5c\x1a\x56\x58\xd8\x33\xb0\x57\x23\x0f\x38\xca\x76\xe0\x1b\x3b\xe0\xdb\xc9\xde\x8a\xbf\x40\xcb\xd9\x57\xfe\x9f\xd9\xc7\xf1\x17\x3d\xf7\xf1\xe2\x6b\xfd\xaf\xef\xe3\xcc\xff\x29\xda\xc7\xbb\xeb\xf4\x89\xe8\x48\xf7\x06\x64\x45\xc3\x11\x19\x0d\x32\xae\x95\xca\x22\xe0\x1b\x20\x46\xa0\x67\x1f\x3e\x9c\xe3\x8c\xb1\x61\x18\x1b\x2f\x24\xb2\x18\xa0\x0b\xd8\x2a\xc0\x9b\x98\x6e\x4e\xcb\x69\x39\x7a\x64\xed\xbd\x6b\xf5\xf1\xfa\x07\x07\x0e\xd0\x9c\xb3\xf7\x35\x14\x26\x6d\x5c\xc6\xbc\x75\x8b\x71\x0d\x4b\xe1\x1a\xc0\x90\xe1\x18\x21\x91\xb5\x70\x26\x43\x86\xac\xea\xa8\x1c\x93\x63\xcd\xb1\x23\x78\xc7\xda\x7b\xd7\x4e\x5b\x7a\xe0\x00\xfc\xfc\x7a\x74\xa4\x7b\x3f\x72\xa0\x09\x64\xbe\x14\x3e\x5d\x34\x0c\x07\x5c\xc2\x21\x08\x89\x2c\x72\x14\x46\xe4\x24\x27\x94\x82\x53\xe4\x90\x72\x70\x09\x85\x4d\x65\x6d\x50\xe9\xb6\x91\x71\x09\x36\x13\xde\x0f\x6f\x12\x8c\x8b\x5e\x77\xed\xbd\x6b\xd7\xde\xbb\xf6\xb7\x0f\x3d\xb4\x74\xcd\x1a\x3a\xb6\x57\xd0\x91\xee\x56\xc4\xa2\x6a\xfa\x6e\xc2\x85\x8d\xdf\x8a\xdf\x2e\x3b\x67\xdc\x7f\xf4\x08\xde\xa1\x8f\xff\xad\x91\x8f\x7f\xc9\x7d\xc4\xfe\x9b\x4f\x20\x17\xc9\x6f\x1c\x49\xd5\xc2\x6b\x59\x0b\xdc\xa7\xc5\x06\x8b\xc7\x7c\xd8\x98\xde\x27\x86\x1a\xa8\x71\xd7\x10\x9a\x01\x94\x1c\xc4\xe2\x81\xcb\x42\xd2\x05\x08\x80\x23\x4c\x3a\x45\xfd\x7b\x6b\xbf\xdc\xc6\x25\x2f\xbf\xfc\x7d\xef\x0e\xe7\x1f\xb7\xec\x38\xc8\x27\x92\x2d\xa1\x65\xeb\x77\x75\x90\xeb\xaf\xe5\x34\xfc\x19\xd4\x29\xab\xc8\xb3\x21\xef\x64\xd1\x5e\xa5\x72\x5e\x0d\x7e\xd9\x69\x58\x6b\x42\x4b\xd6\x52\x33\xff\xe5\x79\x6f\x83\xff\x3f\x7b\x6f\x02\x1f\x55\x75\xf7\x0f\x9f\x73\xb7\xd9\x97\x7b\x67\xcd\x9e\xc9\x64\x21\x0c\x61\x60\x26\x93\x61\xd8\x02\x91\x1d\x04\x8c\x18\x10\x63\x04\x41\xf6\x3d\x22\x20\x02\x22\x62\x44\x45\x14\x2c\x22\xa2\xa2\x22\x52\x44\xbc\x77\x32\x46\x54\x6a\xa1\xd4\x15\x2d\xa5\x54\x28\x2e\x55\xab\x48\xa7\x22\x52\x1f\x4b\x15\x92\x93\xf7\x73\xce\xb9\x77\x32\x09\x41\xed\xf3\xb4\xef\xe7\xf9\xff\xdf\xf7\xe9\x23\x99\x4c\x92\x3b\x67\xfd\xfd\xbe\xbf\xef\x6f\x83\xe3\xb8\x13\xec\x08\x21\x0e\x4c\xc0\x03\x46\x01\xd9\x10\x4c\xd8\xe8\x16\xb8\xda\x4e\x2d\x69\x99\x96\x30\xd3\x89\xd0\xda\x1b\x09\x81\x4e\x24\x03\x06\x14\x09\xab\x0d\x03\xc9\xa0\x77\x61\x8b\x51\x20\x29\xcf\xe9\x8d\xaf\xa3\xe9\x0d\xb1\xc7\x35\x2c\x9c\xf7\xc0\xfd\x0b\x16\xdc\xbd\xa5\x47\x0f\x7c\xb2\xbb\x56\xf0\xaf\xcf\x59\x7d\xe7\xf4\x39\x77\xde\x3e\xaf\xac\xbc\xbc\xac\x2c\x1c\x06\x10\x18\x91\x13\x6e\x07\x80\x60\x03\x1a\xaf\x63\x0b\x2a\xc6\x14\x40\x50\xc9\x4d\x82\x0a\x74\x2a\xe4\x4c\xa5\x39\xb1\xa2\x02\xcc\x31\x35\xae\x2b\xac\x66\x35\xd0\x90\x67\xe3\xa8\x19\x8d\x43\x46\x97\xf9\xa3\x7d\xab\x47\x2c\x5c\x87\x2e\x5c\x71\xcb\x95\x55\x73\xcb\xbb\x76\x91\xe2\x9e\x55\x64\x5f\x8f\x70\x27\x38\xb3\x60\x05\x1e\xf0\x02\xb1\x8f\x81\x3d\x4c\x2b\x03\xea\x42\x8d\x4e\xbd\x4d\x4f\xfa\xb6\xb0\x7c\x52\xe1\x4c\x21\x52\x4c\x1f\x2f\x01\x36\xba\xce\xf4\x3f\x94\x4f\xe2\xee\x1d\xdd\x65\x5d\x77\xd9\x61\x57\xb8\xec\x1f\x64\x9d\x5d\xb1\x67\xff\xf0\xca\xa9\xa7\x5e\x7f\x81\x84\xdf\x73\xf6\x46\x9e\xd3\x39\x02\x8d\x02\xfe\x57\x76\xd8\x1b\x45\x87\xdd\x11\x68\x94\xf0\xbf\x71\x9e\xd3\xa5\x59\x55\x42\x2c\x2e\x39\xec\xf8\x95\x18\x03\x8d\xbc\x20\x4a\xc4\x82\x7a\x89\xe3\x05\x9d\x5d\x94\x1c\x1d\x4d\xa7\x4e\xbb\x3f\x1f\x31\x6d\xb8\xa5\x74\xcc\x95\x23\x0a\xf3\x62\x96\x5f\x98\x1e\xbc\x59\x7b\xcd\x9d\x78\x70\x87\xaf\x24\xbf\xbc\x02\x7f\xf1\x45\x2a\xb0\x9d\xb1\x8d\x3b\xc9\x65\x08\x3e\x60\x00\x12\xc8\x20\xa8\xc3\x18\x56\x38\x8e\xb6\x3e\x70\x04\x49\xcb\x30\x0c\x0d\xfa\x43\x2a\xe3\xc3\x9a\x2e\xdd\xd6\x7f\xbe\x0b\x96\xe5\x7f\x31\xe2\xcc\xbd\xbd\x60\x59\xc6\xdb\x73\xb8\x93\x59\xd7\xbc\x50\xea\x8a\xbc\x55\x91\x75\x60\xae\x2b\xf0\x12\xe1\x04\xd0\x7e\x38\x0a\x0e\x61\xc3\xc0\x8a\xf5\x88\x91\xdc\x19\xb5\x4c\x43\x42\x4f\xd5\x98\xc2\x1b\xd5\x1e\x3b\xb0\xa8\x5d\x85\x57\xb4\x1f\xe6\xe5\xe4\x94\x77\xab\x1a\x39\x68\xee\xaa\x69\xf7\x74\xa9\x66\x4e\x8d\x9e\x31\x7d\x30\x29\xd8\xea\xc6\xf7\x39\xc8\x3d\x08\x8e\x0a\x61\x60\xa2\xb2\x17\xdb\x47\x2c\x87\x2f\xaf\xcc\x87\x54\xc2\x5e\x66\x42\xf8\x73\xf0\x7b\x42\x88\xe4\xdd\x2a\x50\xa7\xf1\x37\x0a\x47\x7c\xa8\x6c\xb4\x24\xea\x89\x7a\x74\x1e\x5d\x89\xee\xe8\xb2\x65\x35\xcb\x97\x4d\x58\xbe\x7c\xc2\xb2\xe5\xdc\x69\xed\x55\xcd\xb2\x65\xb4\x77\x04\xb5\x23\xdd\x20\x0f\x5c\x03\x64\xbb\x56\xbb\x9d\xb0\xa4\xb4\xbc\x9d\xe9\x72\xe5\xed\xf0\xc5\xf1\xfd\x44\x79\x3b\x62\x0a\xab\x15\xed\xc2\x97\x56\xb4\x2b\xb1\x42\xe7\x85\x6d\x96\x6c\x81\x33\x75\xdd\x7a\x01\xc9\x53\x57\x4e\x9f\xb3\xa4\x57\xf7\x61\xd1\x48\x24\x27\x93\x7b\x0f\x3d\x96\x59\x57\x3e\x7c\x1a\x9c\xd4\x52\xfd\xf2\xcd\x53\x96\x2e\x9b\x3a\x72\x73\x2d\x7a\xbd\xa6\xba\x7a\x6a\x78\x52\x8a\x4f\x84\xeb\x05\x27\x60\x41\x26\x20\xd4\x21\x47\x83\xb4\xbc\x49\xf2\x1f\xc5\x59\x0e\x31\x2c\x3e\xfe\x0d\x6c\xe0\xd6\x5f\xac\x07\x10\xcc\x82\xcb\x58\x8e\xfb\x10\x14\x82\x59\x24\x77\x33\x9b\x04\x19\x50\xd8\x4e\xc2\x33\x65\x6f\x48\x43\xee\xb9\x30\x90\x90\xe8\x1d\x2d\x56\x9b\xbb\xc9\xfe\x98\x9c\x2b\xbe\xc8\x1a\xac\xae\xec\x02\xda\xd9\x2d\x95\xb5\x9a\xed\xa2\x0d\x3b\x49\x5b\x37\x29\xe3\x27\xda\xba\xf9\xb5\xba\xcd\xaa\x2b\x68\x56\xd3\xb3\xdb\x37\x0d\x1b\x78\x73\xef\xd9\x23\xe6\xcd\xac\x2b\xdb\xff\xea\xc4\x3b\x06\x55\x3d\x3d\x68\x8d\xaf\x7a\xd4\xfd\x37\xb2\xdf\xcd\xbd\x75\xe0\x8e\x4c\x7f\x34\xaf\x7b\xd7\xd2\xc1\x13\xfb\xdf\x7e\x97\x33\xeb\xb5\xdc\xd2\xa1\x99\x05\x81\xbc\xe8\x02\x92\x4f\x0d\x1b\xd8\x57\xb8\xf7\x80\x09\x00\x87\x01\xfa\xb2\xa0\xcf\x00\x7d\x26\x18\x80\xa5\xe8\x14\xb4\xed\xd9\x0d\xed\xe8\x33\x18\x40\xdf\xee\x7b\x15\x36\xc0\x3d\x70\x2b\x3a\x0f\x8d\x68\x1a\x1a\x07\xf3\xd0\x67\xf8\xef\x07\xc1\x06\x16\xdf\x1b\x07\x88\xb6\xd9\x31\xce\x74\x3b\xc6\x0e\x03\x8a\xcd\x4b\xc3\xd2\x6d\xf6\x9f\x30\x62\xdc\x1e\xd1\x2f\x76\x87\x83\x8e\x3e\x2b\x3f\x3f\x6e\xcd\xfc\xc1\xd7\x3d\x7c\xff\xb9\x8d\x1b\xb9\x93\x9b\x5e\xac\xdd\x39\x7c\xec\xc0\xeb\x36\x04\x5b\xde\x86\x27\x06\xbe\xa4\xc5\xdd\x31\xfb\xf8\xd5\x80\x07\x3d\x40\x9c\xc3\x72\x32\x05\x72\x08\xae\xe2\x08\xf2\x26\xaa\x99\x25\xaa\x19\xa4\x62\xef\x1c\x11\x9f\xe8\x17\xb7\x33\xde\x06\xee\x42\xc3\x85\x55\xdc\x85\xf4\xe7\xe9\x40\x7f\x10\x17\xda\x3d\x2f\x0e\x89\x4a\x86\xac\xaa\xf5\x05\x72\xa3\x78\xfa\x74\x81\x28\x7e\x01\x3f\xdd\x90\x7a\x7a\x18\x3f\x1f\x3e\xd8\xd0\xc0\xee\x6a\x80\xd5\x17\x56\xb1\xbb\xc0\x7f\xee\x33\x98\x6d\x0d\x4c\xdd\x85\x55\xcc\xb6\xff\xe0\x67\xc0\x9a\x06\x76\xc7\x85\x55\xb0\xa6\xc3\xda\xf7\xa2\x48\xb6\xb3\x0f\x10\x82\x32\x73\x5c\x7b\x3a\xc3\x6b\x15\xde\xb4\xf8\x47\xf2\x74\xf2\x6c\xee\xc2\x85\x55\xe0\x32\xcf\xd5\x48\x49\x1a\x3e\x09\x0d\x1a\x66\xd6\xf6\xb6\x93\xb8\xca\xb0\xe8\x73\x6d\x6f\x80\x0f\xf2\xab\x2f\x0a\x0d\xe0\xd2\x35\xa1\xbd\x52\xdb\xf8\x4e\xa1\xed\xd1\xfa\x34\x94\x2a\x33\xa1\x34\xb4\xa7\xae\x09\x7d\xba\x4f\xc4\xcf\x47\xf3\xf9\xd5\x2d\x4f\x35\xb4\x4c\xa5\xb6\xc2\x68\x34\x13\x36\xb6\x2a\xc0\x0a\xb2\x09\x2e\x82\x5c\x92\x48\x60\x5b\x10\x28\x10\xcb\x59\x40\x78\x6b\xbe\x9d\x79\x59\x82\x46\xb7\x33\x30\x97\x8c\x69\xb3\x2f\x09\xde\x62\x50\x0d\xf7\x2e\xdc\x2d\x5c\x0f\x58\xa0\xc3\x4f\x6e\x43\xf2\x5c\x30\xc1\xab\xc7\x5d\x1f\xd4\x6c\xc3\x88\xcf\x85\x6a\xd8\x71\xcd\x7b\xd8\x71\xdc\xbb\x6b\xd6\x40\xeb\x9a\x35\xff\x3b\x78\x34\xb4\x1b\x39\x61\x4d\xeb\x87\x40\x00\x79\xd8\xbe\xc4\x46\xb2\x81\xc0\x58\x28\xeb\xf0\x12\x09\x78\x89\x18\xba\x44\x59\x30\x0c\xfd\x68\xf7\x53\x89\xa6\xed\xe8\xe3\xa9\x45\xe8\x2c\x94\x50\x2c\xf5\x8c\x13\x40\x00\x39\x44\x4b\x53\x1f\xa2\x91\x92\x67\x6a\x8e\x22\x96\x2a\x84\x5e\x30\x41\xb4\x1b\xfa\xa7\xc2\xa2\xa7\x12\x4d\xc8\x09\x0f\xa1\x7e\xd0\x86\xfe\x4e\xf0\x3d\x40\x4e\xc8\x80\x20\x10\x40\x29\xb6\x11\x55\x47\x24\x61\xe0\x04\xcd\xb4\x93\x99\x90\xc2\x09\xaa\xbf\x01\x9b\x99\x45\x2e\x0b\x74\x15\xb5\x02\x86\x41\x71\x38\xba\x05\xed\xf9\x70\xfd\xaa\xd5\xf7\x7f\xd4\xfe\x79\x25\x9a\xbd\xab\x3d\x8f\x3d\x2e\x83\x10\x86\xd3\xd8\x5a\x64\x58\x8d\x83\x2b\xe2\x5d\x7c\xa4\x0c\xe2\xa7\xb5\x20\x38\x1a\xc5\x83\x1f\x4e\xfd\xe8\xfe\x55\xab\xd5\xde\x00\x2d\xbb\x98\xd1\xad\x6b\xfe\xfd\xd8\xd4\x71\x19\x6c\x3a\xe1\x12\x68\x8a\x36\x77\x84\xa6\xd8\x1e\x66\x06\x41\x1f\x7b\xdf\xbf\xc8\x11\x68\xb6\x35\xbb\xa4\x8d\x23\x60\xd0\x15\xcc\x00\x78\x80\xbd\x9b\x60\x2e\xd7\xa5\x98\x8b\x1c\xe8\x4b\xf0\x16\xba\xa2\x23\xe0\x62\x06\x5c\x02\xb8\x18\x54\xc5\x54\xc2\xd7\xd8\x06\xa0\x07\x12\x3e\x29\x42\x50\xb6\x85\x09\xe9\x63\xa4\xcf\xee\x64\x94\x45\x11\xca\x25\x75\x87\xa8\x0a\x96\xf5\x69\x78\xea\xda\x3f\xc1\x85\xb0\xcc\x35\xaf\xf2\xc9\xab\xfe\xcc\xd6\x3b\x17\xbd\x9a\x35\xe0\x8d\xee\xce\xd2\xe7\xc7\x67\xf5\x79\x13\xaf\xc5\x14\x74\x2d\xdc\xde\xfa\x00\xf0\x80\xe7\x7e\x1e\x5e\xfe\x5f\x81\x95\x61\xa7\x58\x19\x4d\xb9\x0c\x58\x46\xd7\x76\x00\xcb\x4c\xeb\xd5\xb0\x01\x28\x82\x8b\x9c\xcd\x32\x72\x36\x59\x92\x4b\x84\xcf\xa6\x4d\xcd\x2a\x22\x67\x53\x36\x87\x14\xc1\x9e\x94\x25\xf2\x05\xa8\xc5\x28\xd5\xc3\x27\xa6\xbd\x7e\x7e\x62\xcd\xd5\xd7\xd5\x56\x8f\xab\x4d\xa5\x03\xf5\x1c\x57\x33\xa1\x7a\xcc\x75\xd7\xb2\xf7\x6a\xf9\x3f\xb0\xb5\x86\xcb\x03\xbb\xf9\x7a\xc0\x83\x10\xc0\xb2\x4f\xd5\x38\xaa\x6d\x0f\xda\x34\x83\xaa\x71\x78\x22\xbb\x79\x96\x5a\xfa\x22\x36\xc3\x77\xc3\x71\xa7\xb9\x3c\x38\x6e\xee\xe9\x8e\xcf\x6b\x53\x91\x80\x3c\x0f\x70\x86\xcb\xa3\x08\x42\xa6\xf9\x44\x7f\x64\x37\x1c\x37\x97\x17\xe6\xa2\x3d\xe4\x79\xf0\x34\xd8\xcd\xf6\x49\x3d\xef\xe7\x6b\x2e\xca\x09\xba\xc2\xae\xdd\x73\x4f\xc3\xd3\x70\xdc\xe9\xb9\xa0\x93\xe7\xfd\x7c\x0d\x4b\xc6\x17\x8e\x84\xc5\xdd\xa7\xe7\xc2\xd3\x73\x4f\xa3\x3d\xf8\xbc\x46\x51\x0d\x7c\xbb\x75\x17\xd1\x81\x84\x37\xa1\xbb\xc6\x87\x12\x0c\x65\x00\x38\xfa\x06\x0c\x11\x3d\xa8\x23\x04\x1d\xd1\x83\x76\xc2\x08\x50\xd9\x82\x05\x61\xd8\xe5\x8b\x84\x45\x1f\x8a\xd6\x33\xbb\x17\x37\xcf\x9b\x70\xf8\x30\xda\x4b\x75\xa0\xf6\x19\x64\xcc\x7c\x50\x7d\x72\xda\xd0\xc8\x98\x79\xed\xd1\xda\x0f\x38\x83\xf6\x5c\x17\x7e\x2a\x9b\x87\x1f\xda\x00\x20\x0a\x22\x27\x3c\x0a\xb6\x02\x03\xd6\x19\x18\xb0\xb4\x89\x3f\x63\x10\x28\x2c\xd1\x19\x24\x79\x83\x87\x2e\xde\xe7\xf2\xf1\x2e\x88\x82\x0c\x83\xbe\x65\xf6\xb6\x54\x43\x6b\x0b\x5a\x02\xc5\x65\xf7\x2e\xbf\x7f\x19\x14\x01\x80\xcd\x6e\xee\x24\x1a\xff\xaf\x72\x9c\xcd\xee\xce\x38\xce\xe6\xdf\x73\x27\x5b\xc5\x9f\xc9\xbd\x42\x4d\x7e\x35\xff\xbe\x13\xf2\x15\xa2\xd1\xdc\x49\xd8\x48\x38\xef\xcc\x0e\x9c\x77\x1a\xdf\x0d\xdb\xf1\xdd\x68\xf4\xe5\x09\x6f\xfc\xcc\x8b\x9f\x72\x27\x5a\x73\x88\x3d\xff\x7f\xbe\x7c\xba\xf8\xe9\xcf\x35\xe6\x21\x7a\x81\x3b\x09\xaf\x21\x7c\x7a\xee\x8f\xf0\xe9\x2a\x5e\x42\x2f\x68\x5c\x3a\xaa\xe1\x93\x70\x8f\xb0\x1f\xb0\xc0\xd1\xf1\xef\xb4\x5f\xae\x61\x6b\xf8\xe4\x31\x5a\x6f\x1b\x2d\xe1\x4e\xc2\x7b\x08\x0f\x36\xfc\xbf\xc1\x83\x75\xce\x81\xc1\x74\x0e\x0c\x2d\xb9\x0c\x09\x06\x5b\xaf\xe3\x92\xe0\x59\xc2\x81\xe5\xfe\x08\x07\x46\x44\xae\xca\x7f\x3d\xd3\x91\xff\x42\xcf\x71\xdf\xc3\x6b\x05\x8e\xc8\xf1\x00\x96\xe3\xb2\x2b\xac\xb0\x6c\x52\xb6\x85\x68\xb9\x2e\x2f\x75\x6f\x8a\x49\x59\x20\xb5\x91\x15\x49\xc2\x8f\x4c\xa7\xb7\x8a\xd2\x5e\xa3\xe7\x46\x0e\xa8\x1a\x39\x6a\xe0\x80\x91\x70\xd3\x55\x7d\x07\x5e\x39\x7a\x40\xdf\xab\xf8\x15\x03\x87\x8c\xe8\xd7\x77\xf8\x90\xca\x21\x03\x87\x55\xf6\x1b\x36\x10\xc0\xe6\x93\xdc\x21\xb4\x5d\xd8\x01\x1c\x60\x3c\xe1\x8a\xcd\x14\xd9\x48\x6a\xc0\x8c\x93\x74\x3c\xd4\x79\x93\x8d\x46\x9d\x4d\x1f\x50\xe9\x69\x42\x2a\xab\x0c\x22\xe1\x2c\x48\x1b\x6c\xb3\x5a\x6f\x58\x12\x49\x15\x49\x99\xd3\x6e\xae\x1a\x62\x6f\x83\xfe\x12\x35\xbd\xa7\xf9\x64\xee\xcc\xd2\xfb\xee\x7d\xca\xb8\xd7\x33\xb2\xa2\x6b\xc1\x40\xfe\xd4\x2e\xa3\x65\xfe\xb4\x6d\xa5\x43\x37\x99\xc3\x45\xf9\x05\xb4\xa6\x8f\x8e\x3b\x01\x5a\x54\x4e\x70\xd8\xbf\x8e\xbb\x3a\xc7\x5c\xec\x65\x30\xd7\x0f\x3f\x83\x0e\xc4\x38\x89\x3b\x09\x0f\xa8\xdc\xd4\xff\x00\x27\x75\x42\x4c\xb5\xc9\x1d\x62\xb3\xb4\xf3\x8b\xb5\xf3\x89\xc1\xf6\x3e\xb1\x0e\x36\x4b\x7b\xa7\x18\xf5\xff\xfc\x8f\xfd\x62\x0c\x3a\xc3\xbd\x0e\x9d\xe4\x19\x3a\x10\x25\xf3\xe6\xc2\xea\x13\xb0\xd2\xd2\x9e\xa5\x4f\x7b\x96\xcc\x92\xc8\x40\x95\x22\xc5\x2b\x23\x86\xc9\xff\xd0\x99\x77\x1f\x50\x9f\x4c\x9e\x0e\x00\x73\x71\x15\x77\x12\x9d\x26\xeb\xea\xc0\x18\x51\x17\x94\xed\x14\x23\x9a\x42\xf8\x14\x02\x85\xd1\xb5\x69\x02\x15\x1a\xb6\x81\xc4\x8b\xab\x60\x99\x6f\x6a\xe9\x53\xc3\x8f\xc2\x79\xe4\xd5\x93\xfd\x3f\x10\xcc\xae\x61\xcf\xf7\xca\x8a\xbd\x15\x22\x5f\x7b\x1e\x26\xf7\x6c\x33\x77\x12\xce\x12\x8e\x01\x0b\xc8\x00\x93\x89\xa4\xe0\xac\x49\xcd\xdd\x42\x25\x85\xec\x09\x2a\x22\xed\x8c\xdf\x5e\x60\x58\x61\x80\xc4\xb4\x39\x3b\x93\x1d\xb4\x7c\xaa\x89\x8b\xc5\x14\xbd\x4e\x6c\x93\x20\x30\x25\x3c\x8b\xa3\xe9\xf7\x73\xf3\x2f\xf4\xf5\x13\x26\x2c\x34\x3e\x62\x3a\xb4\x7d\xe7\xbe\x8f\x87\xf4\x89\x8d\x18\x11\xeb\x33\x44\x08\x8c\xbf\xba\x76\xf4\xe3\x89\x3d\x47\x2b\xfb\xf7\xaf\xec\x5b\x59\xa9\xca\xb6\x75\x69\xb2\x8d\x15\x92\x71\x13\xc1\x3f\x26\x52\x84\x27\x25\xdb\x28\xa7\x27\x5b\xe8\xf8\xd4\x6b\x60\x01\x34\x8e\x5b\x27\xca\x6c\x4c\x16\x54\x8b\x47\x6d\xe2\xe0\xc7\x12\x5d\x87\x96\x18\x3f\xdc\xb5\xe7\xf7\x86\xdd\x5c\xf7\xab\x27\xfc\xde\xc2\x9d\x7c\xf8\xd5\xc6\x27\xb0\x7c\xa3\xe7\xa7\x1f\x7b\x10\xbc\x45\x62\x1a\xfc\x97\x8d\xb9\x68\x8b\xb7\x60\xd5\x78\x8b\x43\x9d\xc5\x5b\xa4\x9e\x25\xe0\x67\x5d\x26\xde\xa2\x2d\xd6\x82\xa5\x16\xed\xa1\x4e\x63\x2d\xda\x8f\xeb\x32\xb1\x16\x6d\x71\x16\xac\x1a\x67\x71\xa8\xd3\x38\x8b\x7f\xe3\xb8\xfe\x97\xfa\x3c\x61\xeb\x28\x54\x05\x12\xad\x6f\x76\xf0\xd5\xa5\xd1\x2a\x1d\x7d\x76\x3c\xf1\x70\xa9\x2e\xb5\xf6\x7e\x34\x0c\x68\xfd\x11\x7f\xe2\xb3\x86\x86\xcf\x5e\x5b\x8b\x96\xaf\xed\xf8\xfc\x36\xbc\xc9\x33\xda\x1f\xb6\x83\x9e\x14\xd5\x0a\xea\xed\x0a\xc5\x05\xf2\xd9\x02\xa7\x3e\x9f\x7a\xcc\x12\x0d\x9f\x7d\xd6\x10\x5b\xbb\x7c\x2d\x5e\x8b\x4d\xdc\x51\x38\x57\x98\xf5\xdf\xb3\x11\x20\x61\x19\xd1\x26\xe6\x83\xbb\xf9\x73\xb7\xa2\xe9\x30\x8f\xac\xc9\x10\x6e\x2c\x0c\x13\xdd\x4d\xd9\x1c\x4e\x25\x30\x28\x74\x14\xec\xf8\x0c\x10\x04\xdf\x1f\x46\x7c\x1e\x2b\x7c\x65\xea\x68\x58\x66\xf5\x27\xb9\xb1\xfb\xdc\x4b\x56\xb9\x7f\xf7\x3a\x80\xad\x6b\x90\x13\x2c\x6f\xfd\xfc\x5f\xf4\xb7\x9a\x0c\x01\x99\xbd\xbc\xbf\x75\xc5\x5d\x8b\xba\x56\xf4\xe8\xb1\xb0\x01\x35\xcf\x5c\xb9\xbe\x47\xd7\xae\x3d\xee\x5f\xf9\xff\xfb\x5b\xff\xa7\xfe\x56\xf4\x02\x7a\x12\x5e\xd3\x7a\xf3\xbf\x12\xc7\x70\x1f\xc6\xa3\x31\xe4\x04\x00\xcc\x02\x16\x50\x4a\x64\x30\xa3\x4b\xc6\x19\x32\x3e\x86\xb4\xc7\xb5\x92\x9a\x91\x7a\x6f\x12\x28\x8c\x89\x28\x84\x1e\x3d\xf9\x54\x88\xa8\xe0\x2f\x28\x41\xb1\x9e\xa1\x48\x4f\xf4\xd0\x86\x09\xa3\x9a\xa5\x68\x25\x64\x10\x92\x77\x64\xa9\xf9\xf2\xf0\x4d\xed\xd9\xc6\x20\x49\x68\xe1\x49\xd7\x11\x1e\xaa\xcf\xb6\x1c\x57\x18\xfc\xec\x94\x5f\x2a\x12\x4e\xaf\x6d\x87\xb4\xaa\x49\xb3\x10\x52\xeb\x25\x61\x6c\x87\xaa\x51\x51\xeb\x8a\x9f\xc6\xa5\xa9\xa6\xf4\xcd\x27\x77\xee\x1c\x57\xbd\x13\x9d\xde\xbc\x79\xe8\x68\x8a\x4b\xd1\x22\x78\x6d\xeb\xca\xff\x28\x2e\x45\xff\xec\x88\x4b\x99\x56\x01\x39\x41\x73\xeb\x27\xc0\x04\xdc\x2a\xf6\xb3\xd2\x23\xe2\x6c\xbb\x55\x9e\x0e\xd8\x4f\x6c\x53\x7a\x62\x1b\xf6\x23\x7a\xb9\x33\xec\x97\x82\x7e\x17\x1a\x16\xce\xdf\xf0\xe0\xdc\xf9\xeb\xb6\x4c\x0a\x44\x22\x81\x40\x04\x5d\x98\xbe\x72\xf5\x8d\x33\x6e\x5f\x39\x63\x22\xbe\x78\x3d\x00\x6c\xbd\x06\xf5\x01\xcf\xb7\xae\xa1\x6b\xa9\x6f\xb3\x2f\xf5\xc7\x15\xde\x9e\x54\x78\x7d\x2a\xb0\x87\xa0\x3f\x41\xe7\x7f\xce\x56\xa2\x87\x99\x23\xaf\x8b\xa3\x9a\x9e\xfb\x07\x38\x77\xdd\x47\xee\x56\x2e\x72\x82\x53\x00\x00\x09\x54\xd1\xac\x9e\x84\x8e\xce\xcb\xae\xfa\x6b\x1c\xe4\x20\x59\xbc\x49\xc5\xc2\xa7\xea\x22\xb0\x76\x52\xba\x5c\xd6\x89\x0a\xb0\xd0\x44\x37\x23\x9e\x0f\xf5\x3d\x95\x44\xc3\x3a\xb5\x0d\x53\xc9\x5f\xb2\xae\xcb\x18\xb6\x73\xf4\xc1\xac\x11\x13\x1e\x7e\x7c\xf4\x20\x74\x54\x67\xed\x7f\x75\xc6\xd6\x7e\xde\x9b\x06\xdc\xbe\xc8\x45\xef\x77\x05\x72\x82\x77\x89\x4f\xbb\xe2\xc7\x7c\xda\x97\xf7\x67\xb3\x97\xf8\xb3\xdf\xf9\x09\x7f\xf6\xbf\x25\x06\x69\x13\xaa\x82\x73\x89\x5c\xea\x9f\x92\x4b\x14\x81\x02\xbb\x4a\xbe\x63\x64\xa2\x01\xd1\x36\xed\x22\x50\xce\x84\x49\x71\x26\x3e\xd1\x1f\xf1\xb9\xfc\x44\x1b\xa0\x8a\xbb\x6f\x44\x3b\x3e\xfb\x8c\xea\xdb\x15\x68\x33\x5c\xdb\xba\x06\xb8\xc1\x2c\x80\xad\x1f\x7b\x58\xeb\x03\x63\x08\xc5\x59\x52\x17\x80\x05\x86\x80\x22\x98\xb1\x99\xee\xe9\x80\x10\x05\x0a\x77\xf1\x77\xba\x76\x1d\x6c\x04\x48\xb3\x50\x74\x22\xde\x46\xb3\x44\xca\x3c\xb2\x4e\x91\x56\xb6\xe2\xc3\xe4\x30\x6a\xff\x92\x8e\x8b\xf8\xae\xac\x98\xbf\x20\x3c\xe0\xc6\xfa\xf0\x80\x79\x4b\x66\xcd\x8f\x44\xe6\xcf\x58\xb2\xa2\xa1\x6a\x70\x43\xd5\xe0\x85\xb7\x0d\x1d\x7a\xeb\x7f\xd0\xcf\x81\x9f\x3b\x1d\x36\xb6\xbe\x40\x39\x10\x0b\xa9\x67\xc1\x68\x1c\x08\x63\x11\xe9\xf9\x83\xe9\x14\x88\xbf\x3d\x07\x72\x18\xdd\xd1\x81\x03\x41\x4b\xd0\x50\x78\x4f\xeb\x23\xff\x56\x1b\x9d\xff\x11\x1b\x7d\x7a\x5b\x9c\x0a\xf9\xec\x75\x69\x9f\xfd\x9f\xc6\xd0\x68\x68\x3b\x0c\xfd\xff\x51\x7e\xfa\xbf\x1f\x37\xe8\x43\xfb\xe1\x27\xad\xc3\x00\x0b\x32\x3a\x8f\x8b\xd2\xfe\xc4\xc7\xbe\xd6\x5c\xb5\xef\x3e\xac\xab\xae\x45\x3d\xe1\x73\xad\xc7\x34\xdf\x9c\x2e\x98\xe0\xe8\xd5\x4d\xfd\xbd\xea\x9b\xe3\xd5\x16\x0f\xe8\x5a\xb6\xba\x79\x2f\xfe\xaf\xec\xde\xfb\x48\x4f\x20\x34\x19\x3e\x0b\x1f\x67\xfe\xfc\x7f\xc7\x3e\x4d\xbe\xcc\x3e\xc1\x67\x2f\xd9\xa7\x1a\x78\x04\xee\x61\x9e\xfa\x09\xbe\x0d\x1e\x51\xf9\xb6\x16\x23\x3c\xc2\x9c\xff\xd1\xdf\x6f\x31\xf2\x67\x52\xbf\x8f\xb6\xc2\x00\x9c\xc1\x8e\x05\x2c\x90\xc8\x7e\x6a\x3e\x3e\xf2\xeb\x06\xe8\x81\x68\x2b\x33\x75\x56\xcb\xe3\xf0\x33\x38\x3f\x81\x48\x3c\x33\xaa\x69\x5d\x07\xf7\x90\xd8\x10\x93\x16\x1b\x82\x37\x0f\x86\x21\xaa\x61\x1e\x7c\xbd\x65\xfe\x12\xe1\xde\x1f\x16\x53\x9d\xb6\x16\x39\xc1\x0a\x0d\x83\x0b\x41\x4d\xab\x5a\xda\x76\xde\x1a\x94\x8d\x29\xd3\xc0\x48\xae\xbe\x51\x50\xe3\x2b\x2d\x3a\xa2\xea\x7a\xf4\xd4\x51\x78\xa0\x46\x59\x2e\x5f\xd8\xd0\xb0\xb0\x47\x8f\x8a\xae\x39\x2b\x67\xce\x5a\x79\x3f\xc6\x02\x9d\xe8\x21\x4d\x09\xb5\x71\xf7\xea\x1b\xdc\xcf\xe6\xee\x37\xdd\x0d\xdf\xb9\xbb\xa5\xf8\xc6\xbf\xfc\x05\xed\xa0\xdc\x57\x04\x95\x81\x23\xad\x6f\x92\xb3\x5c\x4e\x56\x8c\x4f\x59\x15\x6d\x67\x19\x2b\x4d\xea\x70\x90\x79\xaa\x7d\x52\x3a\x4e\xe7\x13\x7d\x0e\x57\x38\x72\x18\x6e\x45\xd3\xea\x13\x31\x34\x0d\x96\x1d\x38\x70\xa9\x8e\x73\x04\x65\x4b\x4a\xc7\xe9\x42\x71\x07\xab\x45\x0a\x29\x46\x7b\x9b\x8e\x73\xd3\x4f\x71\x53\x94\xd5\x56\x8c\xca\x04\x03\x1a\x15\x28\xba\x69\xa1\x33\xbb\x28\xf3\xc4\x37\xad\xd3\xaa\xfb\xf1\x5a\x1c\x1e\x4d\xb9\xf7\x93\xcc\x3e\xfa\x2f\x5a\x81\x55\x5b\xc5\xbc\x19\x4b\xe6\x2d\x24\xba\xae\x12\x6d\x5e\x78\xdb\xb0\x61\xb7\xd6\x53\x4d\xf7\xff\x7e\x4c\x15\x6c\x5d\xc1\x6d\x03\x6b\x84\xb3\xc0\x03\xae\x4c\xf7\xf0\x5b\x34\x76\x94\x5c\x7b\xee\x78\xc2\xa5\x22\xcf\x50\xa3\xdd\xc5\xe9\x49\x22\x16\xfe\x1e\xa3\xeb\xb0\xba\x44\x40\xb1\x40\x8c\xe2\x48\x71\x5a\x1a\xbc\xdb\x9d\x89\x68\x86\x1e\x09\x22\x5a\xd3\xb7\x4f\x51\xa0\x68\xe3\x22\xf2\xe5\x01\x6e\xdb\x8c\x6e\xd9\x19\xbd\xfa\x0f\x2e\x1e\x79\xfd\xf4\xee\xd9\xae\x48\xff\xa1\x5d\x46\xd5\xa9\xb1\x07\x42\x0e\xdc\xad\xdb\xfb\xaf\xc7\x1e\x08\x39\x6a\xec\xc1\xbf\x37\xae\xfc\xdf\x19\xef\x3e\x85\x3b\x01\xb7\xff\x5f\xe2\x1f\xb9\xac\x7e\xbc\xd4\x3f\xd2\x7a\x0d\xb7\x00\x3c\xcf\xbf\x04\xf4\x20\x1f\xc4\x39\x06\x04\x14\xd0\x66\xa1\x09\x76\x95\x58\xa3\x04\x56\x44\x35\x2d\xa8\x65\x31\xb6\x86\x5b\x90\x89\x2d\x0b\x79\x0d\x60\xd1\x5c\x6e\x3f\xdc\x2c\x2c\x25\xbd\x2e\xf3\xc0\x70\xca\xd3\xc9\x9e\xb0\x62\x60\x93\x72\x4e\x48\x6b\xab\x43\xca\xf3\x91\xca\x57\x4a\xa6\x37\xa9\xb8\x04\x51\x8a\x9b\xed\xa4\x9a\x6c\xa6\xa8\x48\xa4\x48\x29\x6b\xc0\x6f\x5a\x9c\xb1\x8e\xe1\xb3\x45\xda\x00\xa2\xe5\x6d\xf6\xdc\xdc\xa1\xbd\x63\x23\x46\xc4\x7a\x0f\x85\x65\x78\x58\x42\xef\xdb\xe7\xac\xc1\x6f\xf4\x1d\xca\x0f\x1c\x3a\x60\xc0\xd0\x41\x03\x07\x96\x93\x61\xde\xde\x68\x6f\x20\xdf\x92\xb3\xf3\x10\x72\x42\xd8\xba\x19\x98\xb1\x74\xc3\x36\xaf\x35\x65\xf3\x12\x76\xc8\x12\x94\xcd\x9a\x41\x40\xc8\x6f\x52\xa8\x3e\x65\xfe\xea\xc2\x6d\xc6\x47\x64\xce\x31\x7f\xa0\x6b\x41\xbf\x1b\x8e\xce\x9a\x1e\xee\x69\xde\x95\xf5\x67\x00\x51\x15\xb7\x1f\xbe\x26\x64\x50\x19\x9d\x8a\x4d\x91\x08\xaa\x4c\x08\xe9\x62\xba\x43\x9c\x11\x4d\x67\x57\xf5\x04\x21\xad\xa9\xb1\x80\xaa\xd8\xdb\x1a\x5a\x36\x72\xfb\xe1\xf5\xe8\xe9\xbf\xfc\xe5\xdf\x83\x37\x18\x74\x06\x8d\x84\x4e\x62\x17\x11\x5e\x9d\xa5\x6c\x88\xa6\x3f\xd2\x87\x98\xb2\x8f\xb0\x1a\x51\xb1\xa9\xa8\xaa\x11\xd1\x0f\xc3\xa2\x1f\x9d\x79\xf7\x5d\x58\x4b\xec\x25\x95\x57\x87\xad\x55\xc8\x09\x5e\x6b\x5d\x9b\xf2\x01\xab\x44\x4e\x9b\x3b\x9e\x70\x66\x6c\xca\x07\xcc\x32\x69\x7e\x70\x1d\x9e\xba\xff\x35\x78\x5b\xc3\x3f\x96\xa3\x0d\xe7\xf1\x3d\x6d\xe0\xd6\xc1\x25\x42\x19\xc8\x02\x93\x01\xc9\x0b\x0e\xab\x74\x57\xa3\xd7\x28\xea\xb5\x08\x31\xe2\x0d\x21\xd5\xd4\x13\x59\x74\x59\xb3\x48\x12\x78\xc2\x4a\x55\x45\x96\x8a\xa7\x2d\xa2\xc2\x92\x33\xe7\x15\x45\x49\x71\xb8\x63\x31\xda\x9e\x88\xd7\x93\xb3\x47\x12\x8a\xa3\x1e\x5d\xaa\xe3\x67\x41\x89\xae\x24\x4a\xfa\xf0\xa3\x06\xc3\xe2\x29\x43\xaf\x18\x7c\xd3\x90\x82\x82\x40\x57\xd3\x0a\x6b\x7d\x5d\xe5\x95\xc3\x6f\x1a\x51\x98\xdd\xad\xab\x95\x3b\x79\xcb\x03\x45\xf5\x7d\x16\x4a\x7d\xa2\xab\xd7\x96\x2e\xef\x7b\x8b\x18\xed\x0b\x58\xd4\xc0\x2d\x87\x4b\x74\x0d\xa4\xff\x58\x10\xdc\x06\x64\x1f\xad\x11\x96\xa2\x14\x64\x53\xa8\x51\xcf\x3a\xf5\x01\xcd\xd1\x04\x42\x72\x59\x50\x29\x31\xa6\xca\x1d\xd3\x70\x5a\xd9\x63\x57\xbc\x30\x20\x17\x86\x48\x2e\x79\x57\x92\x4b\x8e\x35\x21\xe5\x22\x14\x8f\x3a\x3d\xaf\xa8\x38\xd9\x58\x4c\xce\x95\x14\x41\x22\x2d\xaf\x15\xbd\x2d\x16\xbb\xac\xe0\xf0\x5c\x26\x24\x03\x35\x18\x96\x4e\x0a\x5f\x33\x7c\x60\xbe\x3a\xd5\xee\xe3\x46\x0d\xca\xed\xd6\xd5\xba\x5c\x73\x1b\x68\x5f\xf9\x15\x4b\xef\xf7\x07\xfc\x7d\x7a\xad\x5e\xeb\x0f\xf8\xa3\x7d\x1b\x54\x2f\x02\x33\x56\x73\x27\x00\x06\x3d\xce\x9d\x80\x53\x85\xcf\x80\x07\x04\xc1\x38\x55\x52\x98\xb4\xe6\xa7\x97\x2c\x40\xb7\x60\x22\x8b\x7e\xe3\x0f\x35\xe6\x67\x75\xd3\x07\x12\x25\xf4\x7b\x6f\x88\x2c\x8b\xe9\xb8\xec\x0f\x69\x34\x4c\x61\xe8\xb2\xb3\x63\x3b\x17\x96\x8f\x1b\xe6\x5f\xdf\x63\xcc\xa0\xbe\x39\xa5\xc5\x86\x15\xa6\xf9\xd7\x07\xae\x1c\xdc\x2f\xbb\x6b\xb1\x79\x85\x61\x41\x6d\x67\xef\x73\x27\x66\xaf\xce\xf6\x65\x97\x75\x5b\x74\x6b\x96\x2f\xbb\x6b\x77\x98\x37\x67\x55\xb6\x2f\xab\x2c\xb0\x90\x7e\xaf\xe2\x4d\x54\x09\xa7\xb5\xee\x03\x06\x7c\x33\xf5\x1a\x17\x4d\x03\x15\x18\x3d\xb6\x8b\x79\x72\xc4\x8a\x5c\xe1\x88\x05\x46\xfc\x2e\xb4\x15\x82\x77\x21\x68\x05\xef\xa2\xe6\xfd\xab\x56\xed\xff\xd5\xaa\x55\x84\x1f\x26\xf7\xe7\x3d\x20\x80\x42\x2d\x36\x4d\x0d\x70\x6b\x63\x3f\x15\x8e\x27\xfb\x8d\x6f\x4c\xd4\xe3\x77\xf9\x23\xaf\xec\xdf\xbf\xf4\xee\xf3\x87\x0e\x9d\x3f\x0f\x80\xb7\xa5\x08\x00\xe6\x43\xbe\x09\xf0\xc0\x00\x6c\x20\x03\xf8\x49\xf7\xee\x81\x60\x24\xb8\x1a\x8c\x07\xd7\x81\x29\x60\x36\x58\x0c\x56\x80\x06\xf0\x20\x78\x04\x3c\x05\x76\x03\x19\x34\x81\x57\x98\x79\x6a\x05\xcb\x71\xcf\x85\x35\x84\xa6\x5c\xb3\x27\x14\xa2\xef\x62\x4b\x7f\x6f\x48\x86\x76\xb9\x2e\xff\xb8\x98\xb8\x91\x5e\x6c\x13\x56\x21\xd7\xc6\xc3\x61\x95\x2f\x53\x26\x28\xa1\x10\x7d\xd7\xc8\x25\xe5\x44\x48\x36\xda\xe5\xea\xfc\xe3\xa2\x7c\x5b\x38\x31\x9a\xee\xe3\xd2\x50\x7c\x16\x04\x81\xc4\x34\x2a\x16\x87\x0f\x02\xd3\x2c\x01\x79\x5e\x38\x31\x9c\xfe\xbc\x3e\x94\x88\xf4\x20\xef\xdd\x1e\x4e\x44\xe8\x7b\x6b\x43\x09\x5f\x0e\x79\xef\xa1\x70\xc2\x47\xdf\xdb\x12\x4a\xe8\x04\xf2\xde\x4b\x61\x45\xc7\x25\xe5\x7d\xa1\x46\xaf\x4e\xd0\x07\xe4\x5f\x86\x13\x12\xfd\x9d\x67\x42\x89\x92\x00\xf9\x9d\x27\xc3\xda\x39\x7a\x2c\xa4\xf4\x9e\x66\xcf\x3f\x10\x94\xef\x09\x27\x2a\xe9\x7b\x1b\x42\x50\x7e\x95\xaa\x2c\x63\x28\xa4\x8a\x63\x45\x6f\x0d\x85\x14\xde\x9d\x94\xcd\x21\x99\xb7\xcb\x2e\x3c\x71\x0d\x8b\x06\x55\x3c\xd6\x98\xc9\x03\x7d\x40\x2e\x0c\x27\xf2\xe8\x4f\x4a\x43\x32\x6b\x57\xba\xc3\x80\xdc\x2b\x94\x08\xd1\xf7\xfa\x86\xe4\x90\x5d\x19\x07\x03\xf2\x84\x90\x32\xde\x93\x94\x27\x86\x1a\x87\x8c\x1f\xa7\x0f\x24\xaa\xe8\x2f\x54\x05\xe5\x51\xe1\xc4\x10\xfa\xcd\xd8\x50\xe3\x24\xf2\xc3\x5a\xfa\x7d\x6d\x50\x9e\x1a\x4e\x4c\xa2\xdf\xcc\x08\x35\xce\xc1\x3f\x94\x6f\x09\x27\x16\xd0\xb7\x6e\x0d\xc9\xe3\xed\xca\x46\x18\x90\xb7\x86\x12\x9b\xe9\x7b\x4f\x84\x1a\xef\xd8\xbc\x51\x1f\x48\xac\xa4\xdf\xaf\x0c\xca\x77\x87\x13\x77\xd0\x6f\xee\x0b\xc9\x1b\xed\xf2\xd3\x78\x3a\xcf\xd2\x77\x36\xdb\x95\xe7\x61\x40\x79\xf1\xa5\x50\x28\x21\xd3\xc9\x37\xbe\x8c\x27\xcf\x8a\x92\x22\x79\x63\x31\xc5\x65\x17\xa5\xc6\x1c\x5f\x49\xa0\xd0\x13\x53\x36\x6f\x14\xa5\x17\x9f\xf9\xe5\x73\x7b\x94\x38\xfe\xf6\xd9\xa7\x45\xa9\xf1\xa1\x2d\x8f\x3d\x49\xaa\x58\x40\x56\x94\x5e\xac\x1a\x52\x3b\x69\xce\x02\xfc\xc3\xd1\xd5\xa2\xa4\x4c\x9d\x11\x8b\x29\xd3\x66\x89\x52\xe3\xa8\xb1\xb7\xdc\x4a\x8a\x47\xfb\x48\xd4\x13\x14\xc3\x22\x8d\xcf\x72\xa4\xb4\x3c\x91\x4b\x2e\xa7\x26\x95\xc8\xab\x54\x2e\x4f\xb1\x98\x7a\xd5\xf1\x3d\x7f\x81\x43\x45\xa2\xac\xfa\x7d\xea\xfd\x4b\x7f\xf3\xb2\xcf\xc3\x7f\xa5\x7e\xaa\x27\xf5\xd8\x70\x24\x2c\x12\x97\x4e\x24\x03\x86\xc5\x96\xa2\x79\x47\xd1\xc1\x79\xf3\x60\xe5\xd1\x25\xbd\xb2\xb2\xb3\xb3\x7a\x15\x65\x67\xf5\xa2\xaf\x7a\x65\x65\x4f\x88\xf6\xca\xcb\xf0\xe6\xd1\x7f\x37\x46\xa3\xb9\x19\x19\xb9\xd1\x68\x34\x3a\x18\x0e\x42\xfb\xe1\xa0\x93\x51\xf5\xff\xe4\xb6\x1f\x3d\xd8\x2b\x9a\xe7\xcd\xc8\xa3\xff\x4e\xea\x15\x8d\xf6\xca\xce\x8e\x46\x7b\x95\xe0\x57\xa6\x63\x73\xd0\x41\x58\x39\x67\x0e\xac\x3a\x36\x9f\xe9\x03\xab\xd0\x6b\x4c\x5f\x58\x39\xef\x28\x9a\x4a\xfe\x7e\x19\x7e\x44\x2e\x5c\x86\xff\x3c\x17\x75\x8d\x46\xb3\xb3\xb3\x99\x47\xc9\x97\x96\xfe\x64\x54\xec\xf8\x68\x34\x7a\xf1\xb5\xf9\xf3\xf9\x61\xf3\xe6\x5d\x7c\x3f\x1a\xed\xc5\xbe\x18\x8d\xf6\x6a\xfe\xb0\xed\xa7\x2d\x13\xd3\xff\x0e\x75\x8b\x46\xa3\xf0\x61\xfc\xc4\x65\xf8\x87\xb5\xf3\x8f\xa1\xd7\xf8\x61\xf3\xd0\xc1\xa3\xcd\xff\x85\x07\x80\x65\xd5\x38\x6e\x1f\xd8\x21\x54\x03\x33\x96\x55\x20\x98\x10\x54\x59\x65\x21\x16\x12\x1f\x52\x8c\xf6\xa4\x62\x6c\x73\xd4\x46\x2a\xa2\xc5\x25\x91\xb0\xdb\xe3\x12\x74\x7b\x4a\x37\xcd\xbc\xda\xfd\xe9\xc4\x5b\x0f\x70\xfb\x66\x66\x0f\x0b\x97\x4f\x5b\x90\x71\x5f\xee\x74\x82\x21\x58\x6e\x2f\x80\xc2\xba\x7f\x6f\x3e\x61\x4b\x2a\x2f\xfc\xb1\xb6\x7c\xc2\x4b\xfc\xf3\xd4\x15\x8f\x01\x22\x6b\x4d\x6a\x56\xbb\x46\xd8\x65\x76\x20\xec\x3a\xf8\xe7\xdb\x73\x77\xd4\x0f\xc0\x1a\x63\x31\xda\x22\xa3\x3d\x83\x07\x3b\xaa\x5f\xb4\xd9\x74\x68\xfb\xce\x97\x0c\xbf\xd0\xd7\x4f\xb8\x76\x91\x7e\xac\xa6\x64\xf9\xd5\x8f\x27\x9e\x7b\x76\xfc\xd5\x75\xa3\x02\x7d\x2b\x2b\xfb\x56\xf6\xef\xaf\xfa\xa2\x51\x14\x1c\x6a\xdd\x0f\x4c\x2a\x37\x4d\x6d\x54\x93\x1a\xc1\x47\x6d\x54\x63\x08\xdb\x58\x76\x6a\xa3\x72\x40\x94\xe2\xbc\xce\x44\xd2\x4e\x58\x9d\x28\x29\x0c\x01\x3d\xba\x94\x8d\x5a\x12\x3d\x54\x33\x73\xea\xe4\x9b\xa6\x93\x7f\xb7\xd6\x4c\x9b\x3a\x69\xea\xcc\x9a\xe9\x37\x4d\x9e\x8a\xf7\x1a\x39\xc1\x8e\xd6\xbd\xc0\x0c\x8a\x31\x7e\x4e\x30\x6d\x7b\x6d\x3e\xae\xe8\x49\xfe\xaa\xa2\x27\x6d\x0d\x05\x82\x38\x74\x15\xd1\xb0\x4b\xd0\xb9\x09\x5b\xbb\x67\xe9\x41\x4f\xb7\x07\x17\x0f\xf3\x7c\x70\xc3\x89\xdc\xe9\x33\x72\x87\xf6\xee\x36\x7d\x6e\x0e\x48\x7b\xae\x05\x9f\x21\x3d\xe1\x36\x8c\xea\x0e\xeb\x49\x63\x38\xe2\x35\xd2\x93\x20\x38\xc2\xd0\xbb\x3d\xc4\xe5\x4c\xce\xd2\x1e\xf7\xb1\xe9\xe5\x72\x8d\x1b\x9f\xa5\xea\x59\x79\xf7\x5a\x46\x76\x27\x67\x09\x30\xa8\x01\x39\xe1\x06\xf2\xdc\x1c\xd5\x93\xed\xce\x0e\x87\x53\x8f\xcf\x0d\x02\x05\x60\xb5\x2c\x66\x68\x74\x75\xdb\x63\x61\x7f\x18\x0d\xab\x3c\xb3\x4e\xd0\xf9\x51\x83\xe7\xfd\xa9\xc1\xe7\x6e\xf0\x94\x6c\x9e\x37\x06\xce\xcd\xb9\xd6\x75\xaf\xab\x3a\x77\x46\xb7\xde\xde\x6e\xbe\x19\xf8\x73\xcd\xc3\x42\x33\x33\x47\x54\xf4\x44\x5f\xc5\xbe\xb8\x62\xdc\x07\x21\x6f\xbf\x5d\x7d\xeb\x2b\x68\x6d\x6a\x6e\x2f\x40\xda\x59\xfe\xef\xe7\xe1\x8a\xed\xf2\x70\xb5\x72\x0a\x7b\xd3\xd2\x70\x01\x04\x6f\x71\x49\xc6\xf9\x73\xe2\xc2\x52\xb2\xef\xad\x0e\x71\x61\xb0\xb5\x04\x39\xc1\xc9\xd6\x38\xb0\x82\x12\x80\x8f\x91\x51\xe3\x3e\xb4\x8c\x35\x1d\x4d\x0d\x55\x58\xb3\x96\x22\x1c\xf5\x94\x84\x75\xa9\x33\x74\xb2\x6c\x55\xd6\x03\x59\xab\xca\x36\xcc\xa8\xaf\xac\xac\x9f\x81\x3e\x6b\x18\xbc\x61\xc3\xe0\x06\xe7\x94\x9a\x3b\xef\xac\x99\x02\x00\x60\xd1\x12\xe4\x84\x0d\xad\xaf\x03\x07\xc8\x03\x01\xb0\x92\xe0\x7a\x4b\x38\xe1\xd1\x50\x9f\x9c\x13\x94\x4b\xd3\x38\x22\x28\x77\x23\x1f\xed\xa4\x37\xcf\x49\x8a\x57\x25\xf2\xe9\x77\xf9\xa4\x96\xa8\xc6\x09\x65\x3a\xf1\x9e\x62\x0c\x9c\x2f\x2a\x36\x3e\x16\x93\x8b\x25\xc5\x42\x98\x19\x8f\xda\x26\x26\x47\x54\x8c\xa0\xad\xf5\x42\x1a\x4f\x94\x72\x84\xa4\xc7\x69\xf1\x69\xaf\xd1\x92\xa5\xd3\xeb\xa3\x91\xfa\xe9\x4b\x97\x4e\xaf\x8f\xc4\x16\x4e\x5f\x3a\xa7\x4f\xaf\xf0\x80\x81\xa1\xd0\x40\x58\x3d\x20\xdc\xab\x4f\x55\xcf\xd0\x40\x74\xf6\xc6\xc5\x63\xc7\x2e\xbe\xf1\xa6\xc5\xd5\xd5\x8b\x6f\xaa\xe8\xd7\xaf\xa2\xa2\x6f\xdf\x0a\xf5\x2b\xbd\xbb\xdc\xeb\xe0\x90\x30\x08\xe8\x40\xb5\x16\xdf\xa2\xba\xbb\xd9\x54\x64\x04\xab\x6b\x97\x97\x02\xd3\x39\x3d\x01\x06\x54\x16\x4e\x61\x20\x91\xae\x0a\x2f\x90\xca\x14\x24\xec\x24\xac\x0b\xeb\xfc\xd1\x43\x43\x66\x16\x35\x0f\x99\x59\xc4\x8f\x3e\x7f\xcf\x3f\xd6\x91\xcf\xad\x44\x4e\x7e\x53\xeb\x6e\x60\x06\x36\x62\x03\x73\x7c\x12\x5f\x60\x7a\xad\xb8\x70\x7e\x34\x2c\x70\xbe\xfc\xc2\x83\xef\x8d\x83\xbd\xdf\x87\xcf\x34\xbe\x7b\x03\x9a\x86\xde\x47\xbf\x42\x37\xd5\x4c\x9e\x75\xf8\xad\xdf\x1d\xc1\xcf\xe0\xe2\xfc\x26\x61\x58\x27\xcf\x60\x7f\xe2\x19\xc2\x30\xf5\x21\xd4\x4e\xe4\x4e\x70\x56\x7e\x06\xe5\xdb\x53\xf7\x22\x95\xc1\x45\x98\x57\x36\xe2\x73\xbd\xc6\xbd\xcb\x9d\x78\xf0\x41\xd5\xb6\xfc\x13\x67\x6d\x9d\xf9\xa3\x1c\xbd\xce\xe7\xf2\xbd\xc6\xbd\x7b\xb1\xfc\x61\xfa\x37\x95\xdc\x87\xfc\x26\xd2\x2b\x24\x8f\xf8\x95\x40\x58\xd1\xf1\xc9\x46\x49\x67\xd1\x93\x2e\x99\xb2\x81\x54\x39\xa2\x8e\xd4\x70\x88\xe7\x34\xe7\x0e\xb5\x16\x0e\x8a\x07\x1f\x3e\x08\x9d\xd0\xf1\xcc\x63\xdd\x7e\x61\x3b\xf0\xe8\xed\x5f\x7e\x74\x72\xd1\xc8\x19\x4e\xee\xc3\xcd\x4f\x57\x54\xcc\x79\x70\x67\x41\x69\x41\xac\xa2\x93\x75\x61\xdb\xd6\xa5\xa2\xd0\x97\xcf\x79\xfc\xc5\x85\xfe\x7c\xdd\xc1\xc9\xf0\x11\x18\x80\x57\xc0\x47\xaf\x7a\x77\x1c\x7a\xe3\x7d\x74\x5d\x23\x17\x7f\xfb\xbd\x23\x6f\x4e\x9e\x75\x58\xdd\xa3\x00\x7f\x2f\xc1\xff\x99\x84\x57\xd6\x26\xa7\xc3\x02\x4b\xd0\x58\x63\x1f\xb6\x21\x7c\x07\xf9\x10\xcc\x44\x5f\x5e\xf8\xdd\x6b\xf7\x1e\x3d\x7a\x2f\xe5\xec\xf6\x33\xa5\x70\x08\x0f\x80\x1b\xe4\x83\xfb\x00\xe9\x70\xad\xc5\x58\x3a\x83\x89\x4c\xfa\x2a\x57\x63\x0e\xd4\x46\x19\xd8\xcc\x14\xa9\x99\x99\x43\x5a\x0d\x24\x6c\xf4\x0d\x9b\x3d\x21\xd2\x63\x27\x06\x89\x95\x49\xbb\x63\xe4\x88\x71\xc1\x4c\x48\x1c\xe2\x50\x04\xf4\xda\xd9\x25\x52\x99\x5a\x06\x24\x14\x93\x89\xc9\x82\x28\xeb\x89\xf3\xd1\x40\xef\x59\x25\x2c\xf7\x17\xe8\x4a\xd4\x32\x9e\xfe\xb4\xab\xd6\x0f\xea\x04\xb4\xff\x99\x57\x6e\x5c\x55\xb3\xa6\xaa\xea\x89\x29\xf7\x6d\xba\x3b\xb7\x76\xf3\xe2\x15\xef\x75\xcf\xbf\xf2\xda\x1b\x37\xb2\xfa\xb9\xf3\x0c\xdc\xcd\xfd\x1a\xf2\x43\xeb\xd7\xa0\xc1\xf3\x97\x2f\x9e\x53\xec\xaf\x1e\x58\x24\x18\xc9\x9c\xf7\x32\xa5\xb0\x9a\x07\xc0\x01\x32\xc1\x4c\x2c\x4d\x12\x26\x3a\x4f\x7d\x50\x35\x32\x65\x6f\x1b\x76\xc8\xa2\x89\xb7\x5a\x91\x48\x59\x4f\xe8\x29\x95\xdd\x50\x5c\x7a\x51\x8a\xb3\x26\x11\x4f\x4e\x10\x15\x8b\x95\x54\xe4\x52\xfb\x5a\xeb\x49\x45\x2e\x27\x85\x17\x94\xa9\xca\x81\x3e\x92\xaf\xeb\x22\x0e\x41\x07\xe9\x59\x2e\xa0\xbd\x4d\x3b\xb6\xed\x45\x25\x6c\xdd\x35\x2b\x6f\xeb\xbd\x70\xbc\xf2\xd6\x11\x98\xc1\x0c\x1f\xd8\x67\x14\xbb\x41\x3e\xb8\xfb\x17\xd7\x5f\x75\x7d\xaf\x87\xb2\xdc\xaf\x82\xd6\x21\x63\x87\x51\xfe\x7d\x13\x13\x01\xf3\x05\x01\xe8\x80\x09\x94\x52\xa6\xd4\x4a\x3b\x41\x10\x35\x88\xf5\x83\x48\x28\x1a\xc5\x84\xd5\x96\xc0\x10\x25\xab\xc1\x5c\x87\x18\x16\xe7\xce\x9f\x3b\x77\xbe\xe1\x2d\x7e\x57\x5d\x5d\x6d\x73\x92\xf9\x75\xcb\x40\xbc\x36\x7b\x98\x52\x38\x8e\x07\x24\x9e\xa2\x0a\xc8\x86\xa0\x62\x23\xf5\xbe\xa8\xf3\x3f\x15\xcd\x2a\xb6\x8b\x66\x15\xb5\x68\x56\xd6\xf0\x33\xb3\xdb\xd1\x9e\xc4\x53\x5b\x5e\x79\xe9\x89\x47\x5e\x3e\x3c\x70\xd8\xd0\x01\x03\x86\x0e\x1b\xc8\x6e\xde\xf5\x9b\xd7\x9f\xd9\x73\xf0\xf5\x5d\x37\x4d\x9d\x7a\xd3\xd4\x1b\x49\xdd\x7c\xb2\x57\xe3\xb8\xef\x80\x03\x5c\x4f\x76\x8a\x57\xf9\x21\x52\x3e\x8f\x67\x0c\x01\x72\x21\x9d\x1d\xc2\x3a\xf5\x54\xc2\xe3\xef\x8c\xf6\x54\x04\x46\x50\xd1\xb3\xb4\xa1\x8e\x59\x94\xad\x31\xa0\xf0\xa2\x28\x29\x26\x0b\x19\x28\xad\x94\x96\x5e\xba\xad\x18\xed\x7d\x7b\xc9\x55\xa3\xde\xde\x9a\x69\xcc\x5f\x32\x72\xf5\x5a\xb6\x14\x1e\x46\x53\x1f\x9e\xb9\x12\x8e\x6a\x19\x38\xb1\x47\xc5\x9d\x78\x7c\x27\x99\x52\x58\x44\xce\xd2\x00\x40\x0a\x5e\x6b\x6a\x48\x6a\x63\xe3\xe9\xe8\xe8\x78\x80\x62\x96\xb4\x8e\x90\x71\x20\x58\x63\x1d\x35\x0b\x69\x69\xec\x54\x4f\x48\x3e\x3a\xf9\xca\x0b\x8b\xe7\xf5\x9d\x32\xe8\xf1\xc7\xe7\xd5\x05\x67\x0d\x41\xbb\xd9\x07\x13\xaf\x06\x1f\x2a\x7d\xff\xdd\x3e\x3b\x72\xdc\xf4\x0e\xef\x66\x4a\xe1\x04\x41\x00\x12\xc8\x05\x37\x83\x78\x36\x4c\xcb\x84\x24\x6d\x11\x59\x83\x81\x1a\xa0\xea\x80\x48\x99\xc1\x84\x83\x2e\x90\x83\xf6\x0b\xf1\x86\xd4\x11\x2a\x7a\x87\x28\x25\x58\xab\xdd\x45\x3a\x1f\x1a\xc5\x38\x2f\x78\x08\x0a\xc4\x16\x1d\x59\x2e\x39\x9b\xdc\x5a\x56\x52\x78\x21\xb5\xcb\xa4\x33\x44\x58\xad\x07\x4f\xc3\x57\xd4\xfa\xe4\x68\xf7\xc3\x77\xae\x1b\x21\xd8\xde\xde\x5a\x6c\x18\x7c\xdf\xea\x4d\x87\x37\x8c\x1a\xce\x0e\xab\x1e\x34\x9c\xdd\xf4\xfc\x81\x69\x13\x7b\x7e\xd6\x1c\xac\x9d\x71\x60\xd7\xef\xaf\x99\xee\x5c\x34\x79\x36\x50\xf7\x3d\x02\xc7\x09\x02\x70\x82\x49\xb4\xcb\x97\x8a\x7f\xda\x17\x73\x8c\xeb\x49\xff\x50\x3d\x51\x7b\x2e\x4d\xe9\x13\x0e\x52\xab\xeb\xa8\x9e\xd6\x1f\x29\xeb\x08\x3b\x2b\xeb\x88\xf6\xbe\xad\x37\x56\x6d\x5a\xd5\xf0\xf6\xcd\xd7\x8c\x64\x22\xec\xd1\x37\x23\x0b\xa6\xdd\xb1\x12\x45\xe0\xd6\x87\xe7\x2f\x45\x4d\x00\xc0\x96\xa3\x4c\x84\x29\xe3\x01\xf0\x81\x99\x20\x9e\x43\x8a\xfa\x87\x53\x8e\xbd\x90\xda\x2d\x29\xe1\x4b\x05\x8d\xe0\x43\xe8\xa3\x60\x24\x83\x8e\x32\x83\x5e\x21\x91\x0e\xd1\xc7\x10\x6f\x84\x92\x01\x68\xbb\x53\x09\x8b\x0f\xa0\xe8\x72\x44\x29\x0e\xf1\xd5\xa2\x83\x55\x0b\x19\x6a\xe5\x8d\xb5\x11\x6b\x5f\x5b\x8e\x3e\x92\x65\xce\xae\x1f\xf2\x74\x3f\x29\xfb\xe6\xa1\xab\x56\xbd\x3d\x6f\x6c\xd5\x5b\xf3\xaf\x1c\xc2\x44\x98\x5f\x4f\xec\x51\x31\x2d\x18\xbd\xf5\x2e\x32\x8d\xd9\x37\xa1\x27\xe0\xd6\x87\x67\xae\xc4\xb3\xc1\xba\xc4\xce\x44\xc0\x59\x1e\x00\x3b\x08\xd1\xda\x8a\x56\xad\xb6\x62\xc2\x9e\x3e\x09\xc5\xce\x5c\x5a\x61\x91\xed\x58\x61\xf1\xdc\x96\x3c\x63\xd1\x2d\x03\xba\xb9\x6d\x52\x69\xdd\x5c\xfc\xe9\x4b\xfa\x0f\xe6\x12\xc2\xf5\xd7\xa0\x47\xc0\xff\x11\x77\x7b\x35\x13\x81\xab\xb8\xef\x80\x09\x00\x18\x56\x0b\xde\x85\xa1\x1f\xad\x3e\xba\x3e\x8b\xe3\xd8\xcc\xf5\xc7\xd0\xe9\x77\xb9\xef\xd0\x82\x91\x43\xfa\xd4\xc0\x07\x5a\x06\xaa\x7f\xb3\x42\xfd\x1b\x07\x1b\xf6\x44\xc3\xac\xc3\x5f\xa2\x43\xab\x2f\x9c\xfd\x62\xc3\x86\x2f\xce\x5d\xf8\x7c\xeb\x36\x26\x02\xa7\xc3\x09\x9f\x7e\x8a\x76\xa1\x47\xce\x9d\x53\xeb\x6c\x73\xf3\xe1\xc7\x7c\x13\x30\x80\x92\x74\x3f\x8b\x51\x0b\xf3\x34\x72\x01\xc5\xa4\xd5\x8d\xa3\x75\xd9\x52\x71\xfc\xa5\xf9\x63\x5d\x30\x18\xd8\x38\x98\x9b\x9f\x19\x49\x0c\x72\x0e\x79\xa1\xbf\x5a\xbb\xbb\x1f\xfc\xb8\x75\x2d\x30\x80\x22\x22\xc9\x59\xf5\x89\x06\xe2\xff\xd2\x9e\xc8\x1b\x34\x1f\x98\x03\xdb\x31\x24\x04\xa7\x34\xb0\x71\x70\xbc\x60\xac\x03\x1d\x45\xd5\x43\x5e\xe8\x9f\x15\x6b\x1c\x08\x20\xb8\x07\x39\xe1\x3f\x89\x4f\xa4\xd7\x4f\xfb\x44\xb0\xb1\x7b\xa9\x5f\xc4\x93\xee\x17\xb9\xe7\x52\xbf\x08\xa8\x6c\x3d\xc3\x1e\x24\xfd\x9a\xfb\xa9\x55\xa5\x6d\x46\xb5\x67\x97\xcb\x98\xea\xd8\xcc\xbb\xd4\x8e\xcd\x36\x6a\xe9\xc9\x2e\x31\xce\x9b\xb1\x94\x4a\xab\xb1\xa6\xf6\xa8\x2a\x6e\xeb\x58\xe1\x2f\xd0\x55\x6e\x3e\x06\x59\xe8\x46\x7f\x43\x17\xe7\x3d\x3c\x7c\xc8\xc6\x1b\x16\xdd\x7d\xdf\xd2\xa9\xf7\x72\x25\xa3\xd0\x47\xe8\x2f\x28\x89\xfe\x50\xd4\x1d\xf2\xc1\xd0\xae\x9d\xbf\x7c\xba\x0a\x30\xa0\xb6\xf5\x8c\xda\xaf\x2d\x17\xcc\x06\xa4\xc9\x89\x62\x31\x26\x53\xad\xdb\x12\x39\x5e\x27\x6b\x09\xd0\x4e\x48\x79\x5a\xfb\x36\xd9\x44\x6b\xb7\x66\xda\x69\xed\xd6\x4c\xb7\x28\x25\x04\x83\xc5\x49\x9b\xa2\x59\x9c\xf4\xa8\xe6\x88\xb2\x3d\x26\x7b\x25\x05\x98\x62\x24\x67\x5a\xe8\xa4\xc3\x5b\x81\x68\xc7\xa2\x54\xc4\xea\x20\x15\x08\x59\x0b\xb3\xa1\xe1\x37\x5b\x27\x0e\xbb\xad\xff\xd9\xb3\x13\x36\x8f\x1c\xf1\x70\x7d\xcb\x79\x78\x8a\x98\x67\x4c\x29\xcc\x81\x65\xa3\xce\xe4\x14\xa1\xbd\x68\x5f\x30\x84\x2e\x06\x0b\x99\x41\xc4\x64\x63\xd2\xd6\x37\x1f\xcf\xe7\x92\x15\x4e\xe4\x65\xea\x19\x4b\x40\xc9\xe3\x68\x57\x34\xef\x71\xad\xc7\x9b\x84\xcf\x8a\xda\x09\x2d\xdb\x2b\x4a\x09\x46\x6f\xf3\xb8\xc8\x7c\xb4\x5d\xc8\x13\x65\x73\x4c\xce\x94\x14\x09\x5b\x52\x2e\x51\xf6\xfc\xe4\x7e\xa4\x52\x8e\x2e\xb3\x31\x02\x99\x52\xe7\xdb\x83\xfe\x91\xca\x4f\x02\x95\xe8\x7b\x78\x8c\xab\x07\x58\x0b\xf6\xa2\x15\xfb\x12\x76\x35\xbf\xd4\x41\x1a\x90\x5a\x08\xe7\x20\x5b\xec\x0a\xe3\x48\xca\x0c\x29\xd3\xa2\x58\x18\x51\x8a\x0b\x46\x7b\x2c\xd6\x96\xa7\x6e\x4a\x07\x2d\x95\x03\x0b\xa1\xd7\x56\x7e\xdb\x4e\x2d\xdb\x14\x7d\x0f\x8d\x67\x3c\xef\xa0\xaf\xb8\xa3\x5a\xb6\x29\x00\x10\x9e\xe0\x4e\xb2\x83\x84\x3a\xa0\xc7\x77\x8d\xc6\x69\x9b\x52\x71\xda\xc4\x51\x6a\x6c\x77\x7b\xa1\xe6\xab\x84\x27\xa4\x88\x09\x66\x8d\x9e\xcb\x9d\xcc\xab\xf8\x68\x9c\xf7\x95\x46\xd2\x67\xe7\x15\xee\x7b\xf6\x73\x21\xa1\xfa\x4b\x47\x92\xc8\xd6\x1c\x1a\xd9\xea\xb9\x9c\xb7\xd4\x07\x03\x3f\xc3\x63\xea\xf8\x09\x8f\xe9\x2b\x97\x77\x98\xae\xb8\x9c\xc3\x94\x6d\x7d\x0b\x00\x7e\x2d\xff\x0f\xa0\x07\x76\xe0\x06\xd7\xd3\x5e\x82\xb2\x39\x1c\x37\x62\x7b\xd5\x26\x1a\x8c\x16\xd2\x5a\xb0\x11\x18\x8c\x7a\x1a\x1b\x6b\x38\xae\xd8\xed\xa4\xb9\x07\x29\xbf\x6c\x4f\x2a\x5e\x18\x50\xec\x78\xac\x9c\x9e\x27\x45\x5e\xc4\x46\xa3\x49\x94\xc8\x19\x33\x92\x98\x09\x35\x4e\x41\x1d\x35\x4b\x9a\x0b\xfb\x58\x87\x8f\x29\x2e\x11\x7a\xa9\x0b\x79\x2b\xc3\xc1\xe5\x8c\x80\xe2\xb3\x5a\xbe\x9a\xb5\x0f\xae\xd8\x54\xa4\xf7\x71\x0b\xd4\xc5\xbd\xf8\x00\xbf\xff\xc2\x20\x58\x8b\x76\x30\x93\xe0\xc9\xdb\x0a\x6f\x07\x10\x2c\x66\x4a\xe0\x31\x76\x39\x30\x81\x2e\x69\x19\xca\xea\x17\xad\x8a\x3d\xf1\x75\xdb\xb5\x86\x6a\xe9\x8b\xb8\x58\x4b\x48\x66\x8e\xaa\x89\xc8\x80\x69\x7d\x0c\x00\xee\x41\xb2\x1e\x4e\x70\x8d\xda\x59\x51\x62\x93\x64\x39\x14\x8b\x39\x99\xb0\xd2\x25\xb1\x9a\x53\x4b\xe2\x22\x4b\x22\xb9\x92\xb2\x25\x14\x97\x48\xf0\xb8\xe4\x34\x10\xa7\xdf\x00\xc9\x6e\x08\x60\x89\x02\x34\xba\x30\x6d\x15\x1c\xa4\xc6\x04\xf9\x4f\x9c\xa2\xae\xc1\xf7\xec\x88\x96\x33\xf0\x1b\x24\x32\xce\xf4\xa9\x37\x21\xf4\x6b\x84\x1a\x5a\xa9\x0d\xf1\x18\x00\xfc\x3f\xd4\x31\x5e\xa9\xee\x98\x9d\xee\x98\x6c\x0d\x27\xcc\x0e\x32\x42\x33\xdb\x61\x84\x4e\x17\x29\x4f\xed\x6c\xab\x6d\xee\x4a\xd2\xb1\x19\x3b\x1b\x5b\xea\x7f\xa9\xb1\xc1\x0a\xe6\x0a\x18\x41\x87\x5b\x7e\xd5\x6e\x6c\x2d\x87\x98\x7e\x17\x46\x30\x4b\x5a\xd6\xd1\xb1\xb1\x27\xd4\xb1\x5d\x4d\xc7\x16\xb7\x32\x20\xd0\x08\x0c\x56\x75\x28\x26\xb2\x58\x71\xc9\x94\x5a\x29\x5b\x28\x6e\x92\xb4\xf0\x7c\x3c\x32\x32\x2a\x60\xc0\x48\x40\x22\xf5\xc8\xe3\xd0\x2c\xc6\xda\x9d\x21\x47\x24\x2a\x96\x44\x7c\x2e\x9d\xe8\x71\x69\x23\xfc\x26\x1e\x67\x1e\x89\xc7\xd3\x46\x27\x57\xb3\xf1\x6a\x59\xae\x6e\x1e\x5d\x2d\xe3\xfb\xd9\xfa\x46\xeb\x19\x21\xa6\x8e\x2f\x17\x5c\x07\xe2\x12\xde\x61\x2f\x9b\x8c\x9b\xf1\x0e\x67\xe3\x45\x93\xcc\x7a\x0a\xb6\x0d\xc7\x15\x97\x27\x29\xbb\x08\xf6\x53\x6c\x1e\xaa\x14\x5c\x06\xb5\x25\x31\xbe\xa8\x66\x92\xa2\x08\xbc\xa4\x77\xa6\x2b\x13\x23\xef\x6c\xb1\xc3\x5a\x76\xda\x3c\xb3\xb7\x3a\xe6\xab\x2e\xdf\x38\x33\x35\x0f\x34\xff\x32\x8d\x33\xe9\x79\xb8\x1b\x00\x21\x87\xcc\x49\xc4\xd6\x8c\x1d\xaf\xb9\x81\x21\xd7\xb8\x11\xd8\x0d\x78\x32\x52\x50\xb6\x1f\x57\x6c\x2e\x5a\xea\xd4\x66\xa7\x3c\xab\x02\xec\xa2\x14\x37\x59\x89\x15\x6c\xe8\x38\x6c\x9f\x81\xb6\x77\x5e\xaa\x8e\xf4\x14\x1c\x0b\x83\xb0\x27\x1c\x8d\xb2\xd0\xbb\xa9\xb1\xc1\x21\x2d\x3b\x99\x89\xcd\x6b\x5a\xde\x64\x82\x80\x69\x7d\x03\x00\x61\x0e\x19\x4b\x29\x78\x50\x3d\x9b\x99\x61\xc5\xc8\x92\x3e\xca\x12\x5e\xe3\x02\x72\x30\x25\x3c\xac\xae\x41\xd9\x7a\x5c\x29\x72\x27\xe3\x45\xa4\xbd\x50\x51\xa9\x21\x10\xb7\x16\x91\xa6\x6f\x06\xda\x31\x2b\x0f\xaf\xb8\x3b\x19\x77\xe5\x91\xde\x69\x99\x86\x40\x3c\x8f\xd4\xae\xce\xcb\x32\x04\x94\x00\x0c\x28\x45\x56\xac\x0b\x78\x13\x9e\x44\x9e\x48\x9c\x58\x40\x01\x46\x51\x7a\xd1\xea\xca\xce\x2b\xea\x82\xf7\xa4\xa0\xe3\xe4\x44\x5f\x31\x13\x29\x97\x48\x47\x4c\x27\xa3\xc3\xe7\xbc\x42\xa2\x66\x0f\xa9\x50\xa4\x6d\x4f\x06\xac\xdf\xf2\xcc\x73\xb0\xef\x51\x58\x09\x97\xed\x7c\x14\xde\xd2\xb2\xe2\xde\x3b\x5f\x4f\xbc\xf8\xdb\x3b\xef\x4a\x3b\x66\x90\xbb\x1e\x0e\x7c\x63\x1f\xf4\x6c\x46\x71\x74\xfa\x0d\xf4\xdb\x49\xa8\x19\x7a\x86\x41\xe6\xad\x37\x3f\xfc\xe8\xad\xc3\x2d\xc3\x50\x12\x70\xad\x6f\xb7\x9e\x61\x3d\x44\x37\x64\x80\x02\x50\x06\x1a\x68\x9f\x69\x45\x32\x24\xe3\x16\xda\x74\x4d\x0e\x50\x5d\x51\x14\x22\x7d\x82\xcc\xc7\x15\x9b\x2d\xd9\x28\xd8\xcc\xfa\x80\x02\xbc\x49\x19\x04\x89\xf2\xb0\xd9\x49\xcb\xd6\x2e\x5e\xda\x25\xc8\x0c\x54\x1b\x5e\xb1\x61\x35\x92\x99\x5b\x10\x8b\xc5\x94\x2e\x7e\x51\x6a\xf4\x48\xf9\x79\x44\x0e\x4b\x1e\x52\xe7\x5f\xb6\x88\xb2\x33\x46\x35\x4b\x66\x56\x41\xac\x63\xfa\x82\x43\x4c\xef\xa0\xed\xe8\x44\xcf\x44\x35\x3d\x73\x02\xf6\x1c\xde\xf7\xaa\x05\x73\xb7\xbe\x16\xaf\xb9\x9c\xc6\x69\x2e\x62\x41\x0b\x18\xd8\xdf\xff\x79\xf8\x65\xee\xad\x4b\xe2\x75\x48\x2f\x10\x7e\x2d\xbf\x1f\xe8\x80\x05\x8c\x4c\xeb\x4a\x8f\xb5\x8f\xa0\x27\xad\x32\x05\x36\xa9\x7a\x82\x14\x9d\x3d\xa9\x06\xd2\x28\xac\x5d\xad\x5c\xa3\x13\xa5\x46\xc8\xe8\x0d\xd4\x25\xa9\x27\xb5\xdd\xb5\xfe\xf5\x9a\x8a\xe9\x44\xb3\x74\x54\x27\x80\x05\xfb\x00\xe0\xbe\xe3\x9b\x80\x8d\xa0\xac\x54\xef\x59\x36\x49\x12\xf7\x94\x7c\x73\x32\xe1\xf5\x90\xde\xb3\x5e\x63\x5b\xef\x59\x17\x3e\xd9\xe9\xbd\x67\xb3\x49\xef\x59\xf7\x25\xbd\x67\x3d\x6a\xef\x59\xef\x25\xbd\x67\xf3\xb9\xb4\xde\xb3\x2c\xc1\x58\x3e\x7f\x44\x2b\xa3\xbe\x0f\xbe\x09\xa3\x30\x63\xf9\xb4\x7b\x97\xa3\x4f\xbe\xff\xfa\x9d\xdb\x6f\x45\xcd\x07\x12\x2b\x17\x2e\x5f\xfb\x34\xdf\xa4\x1c\x5c\xb3\x4b\x34\xe6\xed\x5e\xff\xd6\xa7\x10\xdc\x78\x53\xd3\xf9\xd1\x13\xc7\x0d\x07\x90\xcc\x65\x1c\x89\x0d\x50\xfb\x55\x92\x25\x55\x38\xbc\x96\xb4\x5f\x25\xef\x4a\xa6\x85\xeb\xa4\xf7\xab\x14\xf7\xb1\xdb\x5a\xb6\xf2\x4d\xad\xe0\xe2\x08\xbc\x47\x31\x00\x78\x23\xbf\x1f\xf0\xc0\x8a\x11\x02\x89\x12\x10\xd8\xa4\xac\x0b\xd1\x1a\x43\x6c\x58\xab\xb1\x2b\x57\x64\xbe\x72\xa8\xe7\x19\x33\x09\x9e\xd3\x75\xb7\xca\xfa\x03\x0a\x57\xf2\x03\x2f\xb3\x07\x58\xa0\x70\xfa\xee\xdd\x61\x23\xcb\xe9\xf4\x6a\xa8\x1b\xa0\xc0\x0a\x92\xce\x8d\x26\xb5\x53\x3a\x74\x41\x1f\x5b\x52\x5c\x62\x65\x62\xf0\x55\x58\x07\xf7\x35\xcf\x66\x26\x36\x9b\x0a\x19\xc6\xd5\x25\xce\x1b\x2f\x7c\x27\x43\x86\x05\x25\xab\x9d\xb6\xf1\xf7\x50\x1b\x0c\xcf\x95\xe1\x9b\x80\x09\x0c\x55\x47\x67\x60\x93\xea\x7c\xcd\xc9\x04\x4f\x8f\x11\x6f\x4e\x75\x5c\x35\xb8\x68\x37\x29\xa0\x65\x77\xc9\x4c\x88\xb6\x95\x6a\xeb\xbb\x9a\x52\xcd\xfb\xda\x54\x72\x3b\x3d\x4c\x7a\x43\x72\x0b\x89\xed\xd7\x5d\xfd\x5c\x1d\x9b\xa4\x46\x20\x49\x61\x32\x06\xb1\xa1\x06\x68\xc2\x4b\xc7\x66\xf5\xa4\x59\x8e\xd8\x93\xf9\x55\x4b\x0d\x97\xd9\x32\x88\x39\xf2\x36\xfb\x35\x04\x6f\x35\x4b\xad\xda\x9c\xf8\x69\x64\x4e\xe9\x3d\x64\x99\xf6\x3d\x64\xd9\xb6\x1e\xb2\xae\x8e\x3d\x64\x5d\x9d\xf5\x90\xdd\xd7\xa6\xc2\xdb\xe9\xed\xf4\x9e\xd2\x1e\x90\x95\x42\x3e\xa9\x9e\xd2\x2e\x36\x99\xc8\xf0\x1a\xb0\xc5\x94\x61\x4e\xaa\x31\x58\xe4\xb4\x53\x36\x51\x11\xdc\xb4\x2f\xa7\x64\x16\xa5\x46\xd6\xe0\xcd\xa4\x5d\xa4\xb1\x5e\x14\xcc\x12\xe8\xb4\x8b\xb4\x46\x2a\x3a\x22\x3e\xd7\xa5\xfd\xa3\x2b\x7f\xfd\xca\xaf\xf6\xef\x7f\xf5\xd5\x03\x8b\x19\xfd\xa5\x9d\xa3\xbf\xbd\x78\xf1\xdb\x6f\x9b\x2f\xa2\x2d\x08\x91\xf5\xaa\x52\x63\x61\x4c\x20\xa6\x9e\x77\x9e\x01\x14\x04\x32\x64\xc3\xe3\x06\x26\xb5\xdb\x42\x28\xce\x18\xb4\x8c\x51\xbc\x5a\xea\x4a\xa5\x41\x8a\x2a\x0a\x25\x3a\xe0\x07\xba\x2f\x63\x49\xef\xa2\x1e\xea\xbe\xe8\x53\xfb\xa2\x7a\xc4\x15\x33\xd9\x0c\x6c\x49\xd3\x62\x55\xc4\x3b\x4c\x37\x22\x4a\x6a\xef\x41\x1d\xde\x89\x5b\xe1\x7d\x70\x02\x62\x18\x06\x6d\x47\xab\xd7\xf0\x4d\x2d\x53\xf6\xc0\xbf\xb7\x2c\x6b\x3e\xca\xcc\xa8\x6b\x39\x0f\x20\x91\x8d\x61\xf2\x59\xfd\xda\x4b\xc6\xf4\x0f\x32\xab\xe2\xd0\x95\x24\xa6\x3b\x47\x98\x1d\x06\xcb\x1b\x92\xd8\xa2\xd7\x64\x21\xec\x0e\x4b\xac\x50\x07\xe1\x39\x58\x0d\xff\x8e\xde\x44\xdf\x18\xfb\x1a\xcc\x61\x0b\xfa\x8a\x6f\xba\x30\x82\x9d\x9f\x73\xae\xa2\xff\x9f\x4b\x9b\x37\xd1\x39\x0a\xc7\xf8\x26\xe0\xc4\x1a\x8a\x9e\x6b\x5b\x98\x7e\xb2\xc2\xf0\xe1\x70\xaa\x0f\x8b\x98\x54\x44\xea\x17\x27\x14\x87\x44\x73\xf5\xc4\xa4\x6c\x0e\x62\x08\x47\x7a\x35\x7c\xf4\xb5\x93\x48\x03\x5b\x77\xab\x6c\x3f\xa0\xb0\x99\x3f\xf0\x32\x83\xa5\x01\x6b\xc7\xd2\x80\x61\x6d\x76\x55\x1a\x28\x26\x2c\x2b\x79\x6b\x8c\x70\x41\x16\x6d\x06\x66\xba\x74\x30\x0c\x49\x2b\x9d\x0a\x87\x1f\xfa\xa0\x5f\x72\x89\xfb\xe0\x4e\x38\x51\x80\xf3\xe1\x4e\xf4\x09\x6b\x36\xa0\x06\xf4\x05\xda\x6e\x70\xf0\x4d\x17\x9f\xe2\xea\x2e\x8c\x60\x12\x3d\x6f\x87\xce\x8b\x0d\xdc\x72\xf4\xd4\xe2\x96\x09\xea\xde\xbd\x4d\xe4\xfb\x44\x75\x3d\x0d\xea\xde\xe9\xc2\x6a\xff\x21\xc5\x26\x12\xed\x2a\xc0\x80\xa2\x17\x93\xb2\xde\xae\x70\xde\xa4\xcc\x05\x49\xab\x74\x1b\xde\x4c\x93\x99\xba\x0c\x18\x23\xad\x45\xc1\xc6\xb4\x5d\x36\xc5\xb4\xa1\x32\xa4\xef\x8f\x3a\xca\x06\x66\xb9\xce\x06\x3d\xe8\x96\x96\x3b\xc9\xe8\x5e\x86\x39\xb7\x30\x89\x0b\x23\xb8\x6a\xf4\xe1\x8a\x96\xb1\xb4\x3f\x6b\x35\x00\x5c\x25\xdf\x44\xe2\x35\x4d\xa0\x54\x5d\x77\xc8\x26\xc9\x39\x26\x72\xcc\xa0\x07\xbc\x25\xa0\x18\xa8\x1c\x4b\xbb\xdd\x5a\x58\x76\x35\xfb\x75\x73\x5f\x76\x5b\x73\x13\xf3\x3d\x04\xad\x80\xdb\x87\x50\xcb\x41\x72\x3f\x98\x76\x3d\xe3\x07\x75\xd2\x31\x5e\x6b\x01\xa2\xf6\x88\xd7\x1a\xc3\x93\xe6\x1f\x6d\x1e\x02\x87\x4d\x94\x14\x20\xc4\x2e\xdb\x12\xfe\x47\xda\xc0\x5f\xb6\xfb\x7b\xea\x5e\xf5\x23\x39\xf7\xc1\xf6\x67\x9d\xaa\x7f\x9a\x78\xaf\x73\xb5\xa9\x7f\x57\x32\x55\xac\x4f\x95\x6d\xdc\x5a\x74\xb8\xe5\x4b\x7c\x9a\xb9\xc4\xc5\x51\x80\x21\x7a\x61\x37\xdf\x04\x8c\xc0\x01\xaa\x54\xa9\x40\x34\xb9\x03\xaf\xa6\x09\x30\xda\x6a\xd2\x5a\x96\x46\x6a\x1f\x19\xed\x04\x57\xf0\x2e\x52\xce\x12\x28\x8e\xb4\x0e\x67\x58\x51\x73\x3e\x7f\x06\x6c\xd3\xcd\xc7\xa0\x11\xba\xd0\x49\x74\x6e\xed\xb4\x0d\xf7\x2f\x59\xb5\x9e\x6f\x3a\xf5\xf9\x99\x0b\x2d\xdf\xb3\xc2\xc2\x39\x73\x67\x90\xb9\x8d\x06\x80\x5b\x46\xce\x5d\x85\x8a\x29\x2c\xda\xbe\xea\xcc\xa4\xf3\x15\xe9\x6d\xa5\x58\x6c\x5a\x36\x18\x3d\x5c\x3c\x5d\x76\x2c\x98\x0c\x78\x7f\x7d\x05\x25\x06\x58\x11\xf6\x89\xa3\xe1\x09\x14\x61\x3f\x47\x23\xc2\x32\x7c\x03\xf9\xcf\x95\xc1\x23\xdf\x31\x46\x78\xf8\x6b\x64\x42\xfd\x5a\xbe\x33\xab\xfa\xa9\x54\xfd\x5c\x1d\xe8\x4d\x6b\x44\xd2\x05\x05\x6c\x92\xd4\xe3\x23\xa5\x21\x29\x0c\x10\x34\x18\xd0\x49\x7d\x48\xad\xeb\x1e\x37\x16\xd5\xa3\x77\xb8\x04\x64\x10\xba\x38\x8a\x4b\xa8\x3d\xb9\x01\xe0\x10\xdf\x04\xf4\x58\x1e\xea\x48\x4f\x6e\x0d\x12\x18\x08\x7d\x23\xb8\x54\x0a\x45\x47\xfa\x30\x02\x05\xd0\x17\x3d\x7a\x8a\x9a\x81\x91\x6e\x57\xf0\x4d\x69\xe6\x04\xed\x5b\x2c\xac\xe5\x0f\x13\xc4\x1c\x00\x33\x29\x93\x17\x17\x30\x3c\x74\xe7\x38\x05\x4b\x40\xf6\x87\x15\xb7\x21\x29\x8b\xa1\x04\x97\x4f\xde\xe8\x1a\x56\x38\x43\x52\xd6\x6b\xf1\x04\x4a\xa6\x94\x94\x33\x29\x3e\xe3\x73\x43\x21\xc5\x21\x26\x15\x9d\x3f\x14\x92\x1d\x76\xd2\xb0\xcf\x22\x25\x95\x32\xbc\x01\xf9\x39\xa2\xa4\x58\xb4\x12\x7a\x85\x7d\xf0\xa2\x87\x43\x9c\xdb\xe5\x64\xb8\x00\x74\xf9\x22\xfe\x82\x42\xa6\xc8\xe9\xee\x03\x45\x7f\x81\x90\x3a\x04\xb5\x1b\xa0\xf5\xa5\x08\xf4\x44\x9a\xa0\xf5\x81\x27\xd1\x5f\x5f\x71\xa3\xa4\xfb\x15\xf4\xd7\x27\xa1\x3f\xb1\xc3\x5a\xba\x69\x37\xb3\xc2\xfa\xe4\x4b\xbb\x37\x95\x32\xe7\x1f\xfd\x61\x7d\x22\xb1\xfe\x87\x47\xb7\xa3\x0b\x6b\x3e\xfb\x6c\x0d\x14\x9e\x7a\x60\x0f\x33\x73\x07\xea\xf3\xcb\x4d\x77\x3f\xa3\xae\x27\x5f\x43\xf4\x58\x71\x9b\x7e\x61\x34\xfd\xa2\x5e\x7b\x52\x7d\x42\xcd\x3e\xe9\x69\x20\x2a\x85\xfc\x3f\x3c\x85\x7a\xc3\x1a\xd8\x07\x46\xe0\x68\x14\x81\x67\xd1\xe3\x68\x0f\xda\xc3\x7c\xcb\xfc\xb6\xe5\x5b\xc6\xda\x12\x68\xc9\x63\x4a\x5b\x4e\x90\x7d\x9b\x0b\x80\xb0\x99\x6f\x02\x59\x60\x0c\xb5\x42\xe8\xd9\xd0\xdb\xc2\xe1\x44\x86\xe0\x81\x96\x80\x6c\x0c\x2b\x19\xa6\xa4\xec\xd4\x42\xae\x15\x56\x4a\xca\x2c\xed\x4b\xae\x0b\x29\x6e\x91\x74\xf1\x76\xd3\xf8\x28\x51\x22\xfa\x5f\x3d\x30\x64\x89\x7c\xa2\xda\x36\xcc\x0e\x7c\xa4\x77\x75\x3e\x98\x0b\x0b\x36\xc7\xf3\xa0\x3b\x6f\xef\x56\xe8\x47\xc7\xd1\xb1\x30\xfa\x5b\x18\x1d\x41\x1f\xb2\xc7\xe0\xe7\xc8\xf7\xd8\x7d\xac\xbe\xf9\xfb\x07\x1f\xc2\xaf\xd1\x69\x74\x1e\x8d\x82\x09\x68\x20\xe3\x8d\x02\x20\x48\xfc\x7b\x20\x1f\xac\x52\xd7\x45\x0c\x63\xf1\x28\xdb\xd4\x1e\x72\x19\x2c\x85\xe4\xfc\x71\x25\xdb\x9d\x8c\x67\x93\x73\x9c\x9d\x6f\x08\xc4\xf9\x6c\x8d\xea\x96\xb3\x29\xbd\x6b\x76\x27\xe3\x66\x37\x7e\xd7\x2c\x1a\x02\x71\xb7\x19\xbf\x74\x4b\x86\x00\x25\x49\x79\xda\x31\xd4\x2d\x2a\x06\xd2\x0e\x24\x03\x8a\x52\x23\x6f\x76\xe4\x11\x14\x13\xfe\x29\xd3\x31\x7a\x79\x93\xf1\xe7\xd8\x89\x2c\xc6\xdb\xcc\x69\x5d\x0d\xc1\x62\x7e\x30\x59\xed\x90\x28\x32\xd4\x42\xf4\x51\x0b\x31\x2b\x44\x3a\xf8\x5b\x8f\x2b\x2e\x57\xb2\x51\x70\x59\xb1\x85\x28\x52\x0b\x51\x4c\x36\x7a\xc9\x1b\xb9\x12\x6d\xda\x6f\x05\xa2\x94\x60\x0d\x66\xbb\x58\xe8\x89\x29\xb9\x2e\x51\x4a\x48\x6e\x4f\x96\x0f\x83\xb4\xf6\xa4\x58\x3a\xad\x92\xce\xa7\xc6\xb4\xf4\x7a\x03\x05\x46\xe8\xef\x5a\x96\xbd\x70\x44\xcd\xb2\xff\x61\x41\x3a\x5a\x12\x8e\x68\x49\xf7\x44\xbf\x11\x39\xa1\xab\x21\xbc\x4b\x3e\x58\xd0\x5e\x56\xc8\x52\x50\xce\x0d\x2b\x66\x42\x12\x90\x5d\xa4\x82\xa3\xd1\x26\xe8\xf4\x01\xc5\x20\x92\x3a\xcc\x36\x31\xd9\xe8\x22\x6f\x64\x49\xd4\xb8\xd2\x61\x2b\x16\x9a\x25\x6c\xed\xba\x6c\xb4\xb9\x70\x16\xb6\x80\x59\x2f\xed\x3e\x7a\xa9\xac\x61\x2f\x53\x3f\x20\x5d\x06\xbd\xd2\x49\x89\xab\x34\xb1\xc4\x6d\xef\x58\x56\x80\xca\x29\x1e\x08\x75\x20\x17\x74\x05\x61\x30\x8f\x76\x53\x96\xdd\x61\xa5\xc0\x90\x94\xed\xa1\xb8\x21\xd5\xa9\xaf\xd4\x90\x84\x72\x39\xb9\x50\x79\xae\xa4\x9c\x67\xa7\x3b\x24\x25\x95\x08\x0c\x28\x45\x79\xa2\x94\xc8\x66\x03\x41\xd2\x5f\xda\x2a\xbe\x28\x18\x32\x32\x7b\xf4\x24\x68\xba\x20\xbb\xad\xf3\xaf\x02\xa4\x58\x4c\x36\xa8\x7d\xe3\xd4\x16\xff\x34\x7b\x5e\x74\xa6\xe2\x14\x2e\x6d\x3a\x9d\xb2\xe8\x6b\xff\xeb\x83\x5b\x1e\x09\xd9\xbc\x81\xe6\xfc\x92\x71\xf9\x59\xf6\xeb\x72\x17\xdc\x52\xe0\x9a\xf7\xc1\x7b\x49\x18\x9d\xbd\xf0\x96\xd9\xdc\xfc\xe5\x27\x16\xab\x24\x08\x13\x80\x6e\xd8\x63\xdc\xb8\xba\xe8\xe4\x8b\x33\xd0\x5b\xb7\x18\xcf\x19\xed\x57\x4e\x7c\x16\xf6\x80\x96\x67\x9e\xd9\xd0\x68\x4e\x6c\x83\xb5\x29\x12\x9c\x01\xa3\x5b\xcf\x70\x45\x42\x1d\x28\x26\xd9\x10\xf1\x42\xac\xf1\x72\xf5\x49\xb2\x06\x8a\x5d\x97\x4c\xb8\x33\x0a\x0d\x96\x80\xe2\x16\xb4\xfc\x07\x25\xdb\x91\x94\xb3\xed\xb2\x03\x9b\xce\xa4\xe6\x43\x10\x4b\xe9\xb8\x83\x28\x26\x87\xc7\x10\x50\x7a\xe2\x9b\x29\xa8\x95\x03\x72\x0b\x45\x49\x2e\x88\xc9\x19\xa2\x02\x7c\xb1\x98\xec\x96\x14\x8e\x25\x3d\x0d\x15\xc1\x42\xd7\xc5\xac\xd6\xc7\x8f\x14\x93\x46\xaa\x6d\xed\x79\xdd\x7d\xa0\x8b\xbc\xf0\x85\x2a\xa2\x2e\xc1\x97\x5f\x98\xe2\xf4\x47\xdf\xfe\xc0\xfb\xe8\x6f\xf5\xc9\x09\x75\x4b\xee\xb9\x72\xe1\xbc\xb5\x1b\xb6\xee\xda\xb8\x09\x9a\xa7\x7f\x74\xed\x1e\x74\x01\x9d\x47\xa7\xe1\x5e\x75\x45\x60\x64\xf6\x5d\xd9\xc6\x9e\x47\xd7\x6f\xe9\x5e\xfc\x71\x8f\xbc\x50\x45\x55\xf4\xd8\xc0\x61\x2b\xca\x4a\xbf\xbb\xf2\x19\x6e\x58\xda\x5a\x6c\x47\x4e\x6e\x97\x50\x07\x9c\x20\x07\x5c\xab\x59\xe2\xf8\x2c\xe8\xc8\x62\x18\x30\x56\x56\x7b\x9e\x29\x4e\x1b\xc1\xd2\x66\x18\x50\x4c\xb6\x24\x61\xbe\x9c\x34\xd1\x4d\x36\x8b\x8d\x3a\x57\x46\x0e\xe9\x39\x2e\x29\x99\x59\x04\xdf\x93\x42\xdb\x1c\x05\x9d\xe1\x94\x5f\xd9\xa7\xb5\x0b\x4c\x6d\xf5\xf6\x64\xa9\x18\x6e\x5c\x74\xe8\x1d\x74\xa4\xa6\xee\xf6\x45\x2b\x34\xc7\x45\xdd\x86\xab\xae\x3e\xf6\xe6\xc5\x3e\xdc\xb2\x65\xcb\x9e\x7b\xa3\xe5\xdb\x36\x4f\x06\x03\xb6\x13\xae\xaa\x0e\x58\x80\x1b\xf4\x01\x71\x13\xb1\xf9\x0d\x49\x32\x76\x35\x77\x53\x61\x6d\x94\xfa\x67\x81\x28\xc5\xad\x92\x9b\x5c\x39\x41\xad\xd6\x06\x45\x62\x7b\x5c\x86\x4f\xda\xde\xc6\x1d\x0d\xd2\x96\xb4\x2e\x8d\x2a\x2a\x6f\xf3\xa9\x70\x60\x43\xeb\x59\x6e\xbf\x90\x00\x2e\xe0\x03\x5d\x41\x04\x3c\x01\xe2\x8e\xf4\xf1\xc8\xe6\xb0\x9c\x17\x94\xc3\x61\xac\x04\xe4\xb2\x10\x94\x2b\xb4\xf1\xc9\xac\x9d\xf2\x31\x6e\x6f\x52\x76\x07\x95\x6c\x2f\x51\x61\x06\xb5\x41\x79\x00\xff\xa8\x87\x37\x29\xdb\xed\xb2\x05\xbf\x36\xdb\x88\xf1\x62\xb1\x25\x95\x28\x0c\x28\x81\x6c\x51\x4a\x08\x8e\x82\x62\xd2\xa2\xbc\x87\xa8\x94\x74\x89\xc5\x14\x0b\x06\xc4\x65\x61\xb2\x07\xf8\x44\xda\x63\x4a\x46\x9e\x28\xc5\x0b\xfc\x5d\xa9\xa7\x46\x9d\x33\x46\x07\x25\xbe\x5c\xe8\xc2\x20\x99\xf9\x29\xff\xcd\x06\x18\x9a\xb9\x68\xc5\xa2\xec\x00\x0c\x77\xc9\x41\xdf\xa0\x2f\x51\x4b\xeb\xfc\xcb\xfa\x74\x20\x62\x26\xb5\x6c\xde\xb8\xfa\x95\xc3\xb3\x8f\xbf\xf4\xd8\xd7\xb7\xa0\x37\xd0\x3b\x90\xe5\xee\xbb\x6c\x6a\x1c\xf5\x89\xf2\x80\x5b\x48\x64\xd4\x8c\x9f\x92\x50\x81\xce\x24\x54\x37\x55\x42\x29\xd9\x2c\xa1\xe5\x1b\xb1\x74\xfa\xb7\xc9\xa6\x9f\x23\x92\x7e\x5a\x14\xd1\xb9\x6e\x47\x4e\x1e\x08\x79\xc0\x09\x4a\xc1\x72\x10\x17\x09\xcb\x6f\xc0\xea\x51\xce\x0b\x2a\xf9\x86\xa4\x5c\x12\xc4\x30\x91\x70\xd0\xea\xdd\x73\x11\xe7\x48\x16\x9e\xab\x3b\x29\x17\xe2\xf3\xa0\xb3\x25\xe3\x85\x24\x44\xb3\x30\x4f\xa5\x9b\x0b\x9d\xa2\x14\x17\x39\x6f\x8c\xf4\x35\x50\x4c\x46\x2d\xcf\x4c\x76\xc4\x94\x7c\x0c\xcc\x8c\xae\x58\x4c\x2e\xd1\x3a\x23\x96\x17\x86\x43\xe9\xfc\x5e\x41\x49\x86\xd6\x0f\xbc\x38\x00\x23\x1a\x0b\x22\x6e\x87\x5e\xf4\x15\xb4\x6d\x59\xbf\xff\x65\x74\xf1\x8b\xb7\x56\xf6\xb8\xaf\xef\xed\xb7\xad\x5d\x35\x2c\x32\x65\xde\xbc\x29\x1f\x23\xa7\x50\xfe\xe9\x3f\x7f\xff\xf2\x2f\x9e\xf7\x08\xde\x83\x7b\xff\xf0\x6d\x65\x4b\x92\x15\xf3\x4a\x6e\x5b\x30\xaf\xfe\xdb\xb9\xd3\x6a\xa7\xa2\x0b\x04\x27\x31\xc8\xc9\xdd\xcb\xd5\x01\x07\xe1\x0c\xf0\xe5\x30\x86\x65\x7b\x90\xd8\x38\xf6\xe3\x8a\xcd\x43\xcc\x5b\x0c\xc8\x4d\xee\xb6\x7a\xfd\x71\x81\x77\x50\x85\x99\xea\x99\xea\x23\xdd\x19\x48\xa7\x42\x28\x30\x2e\x5f\xb9\x14\x65\x60\xbf\x1d\xae\x2a\xab\xc0\xc5\xf2\x76\xc0\x7e\x68\x4a\x59\x05\xfa\x55\xaf\x6e\x5c\x1d\x72\xf4\xff\x76\x78\xb7\x53\xd7\xc2\xe6\x8b\x89\x9b\xd1\xe9\x85\x35\x30\xf7\x4e\xf5\xbc\x71\x5b\x84\x3c\x90\x03\x4a\xc1\xcd\x20\x9e\x85\xf7\xc0\x67\x24\xdd\xd8\xf4\xba\xd4\xca\xe7\xba\x92\x72\xae\x5d\x96\x08\x6b\xea\x48\xca\x7c\x50\x91\x1c\xf8\x2d\xd2\x67\xdc\xeb\x4a\x92\x55\x97\x72\x69\x12\x78\xa1\xf8\xa2\x4d\xef\xca\xf2\x95\xe0\x0b\xe9\x95\xe2\x66\x37\x8d\x74\xb7\xf9\x44\x29\x01\x78\xb3\x97\xfc\x40\x4f\xe9\x44\x2c\xff\x2f\x11\xff\x1e\x7a\x21\x0b\x0a\x8b\x52\x77\xd4\x0a\x6b\x0f\xbe\xf5\xf5\xdf\xdf\x9f\x7f\x74\xfd\xb2\xda\x3d\x13\x86\x8f\xb8\xe7\x9e\x7d\xcf\xa3\x2f\xd1\x3f\xbf\x43\x1f\xc2\xde\x4b\x67\xce\xbf\xf5\x86\x99\xcb\x1b\x60\x53\xd3\xb9\xde\x0f\xff\xfa\x81\xa7\xcb\xaa\x4e\x94\x45\x2b\xba\x57\xcc\x1c\x52\x77\x7e\x3b\x6a\x41\xdf\x7c\xff\xc9\x4d\x2b\xee\x5e\x73\xfd\xe6\xde\xfe\x17\x89\xbd\x87\xf5\x1f\x57\x0f\x8a\x7f\x5a\xfb\x95\xfc\x4c\xed\xd7\xe5\x3f\xa7\xfd\x7e\x5a\xe9\xfd\x88\xae\x23\x67\xae\x16\xad\x65\xbf\x15\x30\xae\x1b\x43\xe2\xd1\xc9\xe6\x52\x76\xdc\xea\x4a\xca\x56\x3b\xe9\x7c\xea\x76\x60\x7b\x81\xe0\x36\x0c\x47\x15\x9d\x9e\x04\xa4\x35\xb2\x8e\x0c\xd2\x04\xdd\x2d\x29\x4e\xe2\xba\xd1\xeb\x52\x94\x99\xa3\x1c\x14\x59\xa1\xdf\x17\xf1\xb9\x04\xc0\xb8\x9c\xb9\x0c\xe9\x83\xae\xf3\x91\x7a\x9f\x25\x85\xb5\x50\x80\xe5\xd9\x1b\xc2\xe8\xcf\x6c\xcd\xdb\xe8\xfb\xb5\x25\xc3\xa7\x0f\xdc\xf9\xf8\x3d\xe8\xbd\xc1\x63\xc6\x4c\x43\xc3\xe0\xb1\xa3\x70\x67\xb3\xce\xf8\x49\xd3\xb3\xe8\x38\x3a\xbd\x69\xc4\xc4\x48\xb6\xc5\xb7\x62\xda\x2f\x0e\x5e\xff\x68\x30\xbf\xd4\x71\xa5\xda\x37\x00\xeb\x68\xae\x1e\x38\xc1\xa8\xcb\x6a\x68\x57\x67\x1a\xda\xdd\x4e\x43\x93\xba\x04\x3f\xa5\x94\x3b\xe8\xe2\x4b\x74\xb0\x8a\x25\xb9\xcd\x42\x1e\x30\x91\x3e\x35\x63\x34\xb6\x46\x20\xaa\xc9\xa1\x4b\xca\x1e\xb5\xaf\x6d\x66\x8a\x05\x74\x84\x54\x22\x56\x76\x86\x88\xc9\x9d\xd5\xbe\x38\xbc\xc3\xdc\x56\x1c\x3e\x9d\xb8\xa1\x65\x24\x8b\x68\x38\x6b\x2d\x34\x41\x3b\xd4\x43\x0f\xfa\x2f\x74\x16\xfd\x13\x9d\x85\x51\x6e\xe6\x92\xc5\xb3\x79\xd4\x1b\xbe\xa1\x9f\xb9\x68\xce\x3c\x56\x80\x9b\xe0\x5d\x68\x0e\x5a\x8e\xe6\xa1\xa5\xf0\x61\xe8\xf9\x6b\xf2\xcb\xaf\x3e\xff\xfc\x2f\x7f\x50\xfb\xe8\xb3\x1e\x0e\x63\x86\xe0\x25\x88\xc1\x9a\x42\x0c\xa4\xbd\xdf\x8f\xa2\x84\x34\x70\x90\x0e\x0a\xb4\x1e\x0f\xdc\x79\xae\x0e\xd8\xb4\xde\x11\xb2\x29\x4c\x41\x80\xbe\x8d\xc3\x23\x8d\xeb\x53\x8c\x9d\x2c\x68\x0c\x1d\x6f\xd1\x78\x58\x1b\x0c\xa7\xa8\xd8\xed\xb0\x27\xcb\x72\xeb\x61\x6f\x38\x18\x1f\x19\xb4\x03\xbd\xb1\x81\xab\x43\x1f\x3e\x59\xbd\x1b\xce\x43\xa0\xe5\x29\xb8\x7b\x22\x92\x01\x04\xfa\xd6\x33\xdc\x67\x82\x0f\x14\x60\x44\x44\xce\x89\x57\x0d\x0f\xc0\x42\xcb\x88\x0d\x50\x7f\x10\x4b\x2d\xa0\x48\x80\x7a\xdb\x78\x31\x01\x75\xd6\x5c\x72\xc0\x8d\x94\x8d\x0d\xc3\x12\xbc\xda\xba\x48\x45\x38\x94\x0b\x3d\x30\x2d\xac\xb8\x84\xc1\x5a\x51\xc7\xea\xe1\x49\x7f\x61\xed\x0d\xa1\xf2\x31\xe3\xeb\x9f\xae\x0f\xc3\x8c\xa2\x51\x51\x5f\xa1\x67\x51\xc9\xbc\xfb\x4a\x17\x05\x2c\x42\xf7\xdc\xdf\x71\xbe\xda\x89\x23\x2c\xcd\xe2\x90\x4d\xf7\x37\x37\xcf\xb8\xd1\x78\xc6\x2c\xcd\x59\x02\xaf\x58\x5b\xbe\x75\x14\xca\x4a\x9d\xe9\x3a\xe0\x05\x13\x41\xdc\x82\xc7\x2a\xb5\x83\x4c\xc6\xb0\x0c\x82\x50\xce\x20\x0b\xe6\x25\x0b\x26\x7b\xd5\x9e\x10\xb6\x24\xf1\x77\x7b\xd5\x39\x18\x48\x6d\x29\x93\x24\xdb\x30\xbc\xb3\x60\xac\x67\x73\x75\x00\x3a\xd8\xbc\x57\x23\xf4\x4a\xf2\x20\x5e\xd2\x09\x75\x2b\x17\xc1\x9e\xa7\x03\xb6\xae\x4b\x27\xf4\x9f\x91\xcf\xf3\xc8\x29\x8c\x68\xa9\x5f\xb6\xec\xf9\xdf\x32\xd6\x8b\x4f\x6d\xbe\xe6\x9a\xee\xdd\xae\x79\x0c\x1d\x00\x10\x08\x00\x70\xf5\xe4\xdc\x74\x51\xc7\x4a\x14\x97\x2e\x4c\x8e\x8d\xee\xb8\xa2\x77\xa9\xc7\x06\x58\xd4\xc8\x78\x87\xcf\xe1\x09\x57\x48\xa2\xcf\x6e\x84\x3a\x9f\x00\x63\x1f\x0c\xd6\xd7\x4f\x83\xe5\x13\x7e\xbd\x1d\x9d\xe5\xea\x5a\x1e\xfa\xe2\x11\x78\x1f\x0c\xb4\x02\xb4\x1e\xbd\xb8\x3d\x4d\x46\x75\x07\xf7\x00\x39\x23\xa8\xb8\xf9\xa4\x6c\x0f\x2a\x06\x53\x38\xac\x58\xf9\x24\x94\x83\x54\x12\xbb\xd2\x24\xb1\x0d\x4b\x62\xd9\x1c\x56\x1c\xb6\x94\x30\xb6\x19\x54\x91\x2c\x67\xdb\x95\x52\x18\x50\xfc\x8e\xa4\xd2\x43\x95\xce\x0a\x5b\x16\x23\x6d\xb2\x0d\x31\xb9\x54\x8a\xe7\x17\x77\xc3\x20\xc1\x2f\x2a\xbe\x22\x7c\x09\xdd\x19\x62\x4a\x52\x53\x6c\xa4\x49\xe8\xa8\x10\x80\x11\x9f\xab\xbd\x84\xce\x85\xed\x84\x5d\x77\x58\xbb\x71\xdd\x87\x0d\x8f\xbc\x77\x85\x9b\x2d\x1c\xf9\xf2\x57\xab\x37\xed\xdc\xf5\xfc\xd6\xe0\xe4\xbb\x53\x02\xef\xe4\x27\xb0\x69\xe5\xaf\x2b\x8c\xe5\xef\xcc\x5e\x5d\x64\xf9\xe4\x0f\xeb\x16\xdf\x50\xfd\x87\xe5\xcb\x87\x5e\x13\xc9\x4a\x13\x7a\xc5\x1f\x60\xdd\x3c\xa4\xf5\x0c\x77\x07\x57\x4f\xf2\xe1\x06\x81\xb8\x11\x1f\x0e\x51\x8b\x8f\xf3\xa4\xaa\xd4\x6a\x02\xdc\x89\xad\x6d\x55\xac\xa4\x12\xde\x68\xae\x0d\x29\xca\xac\x06\xbe\xb9\x25\xa2\x5a\x8b\x99\xa2\x34\xf7\xce\x10\x98\x0b\xd9\x27\xcf\xdf\x89\x3e\x45\xad\x4f\x9e\xbf\x13\x46\xe7\x2e\xbf\x75\xf6\x9c\xe5\xb7\xce\x61\x7a\x42\x09\xf6\xb8\x0f\x5d\x90\xd1\x37\xe8\xdd\xf5\x50\x2f\xef\xdc\xfd\xcb\x67\x77\xee\x7c\x06\x40\x90\xd1\x7a\x86\x7f\x8a\xab\x03\x1e\x30\x19\xc4\xdd\xf8\x4c\x10\xe2\xd4\x60\x50\x43\xde\x3c\xfa\xa4\xc2\x39\xd4\x92\x1d\xee\xe3\x8a\xcb\x96\x8c\xbb\x49\x5c\x80\x1b\x18\x02\xb2\x4b\xf5\x4a\xd9\x92\x71\x41\xd2\xea\x7f\xca\xa6\x10\x8d\x3e\x34\xb8\xa9\x27\xd6\xa3\xc2\x84\x48\xd4\xe7\xf2\xab\x02\x48\xed\x6a\xef\x13\x7d\x62\x46\x9c\x3b\x71\xa6\xa2\xcb\x15\x95\xa5\xab\x2a\x36\x3f\x86\xf6\xa2\x23\xec\xe2\x35\xd3\x92\x2d\xef\x84\x7b\xfa\x3f\xcc\xc8\xdd\xf1\x34\x53\xd5\x7c\x2f\xbb\x98\xe0\xcd\x65\xc8\xc9\x6d\xe6\xea\x81\x08\x72\xc1\x04\x55\xfa\xb9\x8c\xc9\x38\x87\x07\x9b\x65\x4c\x92\xdb\x46\xe3\x0c\x45\x5b\x52\x96\x42\xb2\x48\x72\xfd\xc9\xd9\xce\x87\x01\x45\x54\xdb\xc4\x7b\xc5\xb8\xc9\xc2\xd1\xb8\x6d\x93\x28\x91\xcc\x04\x39\x4b\x13\x93\xda\x22\x33\xfe\x82\x12\xbf\xdb\xd5\x86\x24\xf1\x89\x59\x06\x5d\xa0\xf5\xd1\x33\x77\xfc\xe3\x83\xad\xab\x24\x7b\xe0\xe6\xbe\x8b\xa6\x4c\xbe\x79\xe1\x2c\xe4\xe4\x72\xa0\x03\x06\xd7\xa3\xef\x5f\x40\xdf\xa0\xdf\x5d\xb9\x67\x12\x3a\xcd\xfa\x03\x81\xc7\x14\xf9\xf1\x47\x9e\x01\x6d\x3a\x9c\xab\x07\xd9\x60\x2c\xa0\x87\x40\x8f\x0f\x41\x4e\x7a\x64\xa4\x07\xeb\x14\x8c\xd0\x42\x4a\xae\xd6\xf3\x2a\x0b\xaf\x62\x82\xd5\xab\xb1\x2f\x92\x14\x17\x48\x10\x5b\x7a\xf3\x27\x1a\x12\x59\xdc\xfe\x50\x57\xa8\x67\x1a\x5a\x60\xc1\xbe\xe7\x27\x3c\x3f\x63\xe5\xa2\xd0\xd4\xb5\xcf\x3e\x76\x0f\x7a\xef\xa1\xea\x29\x27\x3f\x81\x67\xe1\x30\xd8\x6f\xec\x5f\xab\x7e\x7b\x68\x44\x5d\x2c\xc7\x7f\xc7\xac\x2d\xef\x1e\x9f\x5c\x18\x70\x76\x4d\x6a\xb6\x8c\x9d\x9b\x44\xea\xc8\xd5\xa8\xeb\x2d\x6a\xf1\x90\x5e\x5d\x92\x14\x49\xca\xea\xe4\x08\xc7\x75\x4e\x2d\x8d\x94\xc0\x12\x7c\x9a\x65\x13\x29\xc1\xc6\x6b\x05\x23\x80\x8e\x9e\xe8\x52\xe8\xf2\xb9\x5d\x4e\x2b\xf4\xa7\x39\x2c\x4b\xb0\xa6\x64\x96\x30\xfd\xd0\x17\x89\x86\x8b\xcf\xa2\x66\xf4\x19\xec\xbd\xe4\x96\x9b\x97\xf6\x19\x14\x7a\xea\x2e\xc6\xc7\x54\x7e\xf2\xda\x5f\x37\x7e\x7e\x2b\x2c\x83\xfa\x6d\x3b\x1e\x79\x60\xfe\x8b\x57\xef\x50\xf9\xf8\xd6\x33\x1c\xe0\xea\x80\x84\x71\x86\xb5\xdd\x71\x96\xd4\x11\x3b\x82\xb2\x78\x9c\x1e\x5b\x51\x3b\xb6\x71\x91\x88\x1e\x11\x18\x02\xa4\x45\x9d\x62\xb0\xd2\xe3\x2b\xa5\x1d\xdf\x74\xfd\x19\x11\x4b\x65\xb6\x04\xd5\x0f\xef\x3b\x76\xc1\xec\x47\x5f\x8b\xb3\xcb\x56\x4d\x3b\xd5\x72\x8a\x6a\xd1\x97\x19\x52\x1b\x94\xd8\xd4\x5c\x1d\x70\x81\x71\x97\x5a\xd3\x9a\x33\x88\x1a\xd0\x29\x6b\xb9\x13\x23\x19\x1f\x09\x33\x8b\xb1\x85\x23\xcd\x1c\xbe\x9c\x09\xdc\x99\x89\xdb\xb9\x21\x4b\xed\x55\xe4\xe4\x2f\x70\x8b\x49\x65\x83\xc5\x94\xa5\x96\x9d\x61\xc5\xa0\x4f\xca\x99\x21\x1a\x31\xc3\x86\x95\x7c\x1d\xb6\xec\x09\x19\x0a\x8e\x2b\x3a\x89\xb8\x88\xdc\x30\x80\xc1\xa6\x4b\xc2\xbf\x8a\xa5\x41\x0e\x9e\x83\x83\xb2\xa1\x6a\x01\x4a\xd9\x2d\xca\x5c\x4c\xc9\x71\x91\xfa\x7f\x40\xc9\x37\x88\x52\x5c\x07\x68\x9b\x3a\xfc\x23\x2c\xa0\xa5\xa8\xc7\x0a\x5d\x76\x9e\xa4\x8a\x03\x97\x93\xe1\x74\xa2\x4f\x2c\x04\xbc\x5a\x71\x5e\x70\xd5\xce\x5b\xfa\xf1\xc4\x11\xd0\x7a\xfc\x95\xcf\x20\xf8\x05\xfa\x7b\x1c\x9d\x42\x67\xd1\x29\x76\xd8\xba\x5d\x75\x13\x63\x03\x98\xd2\x47\x61\xde\xc6\x07\x6e\x3d\xb2\x0c\x9d\x29\x67\xb8\x97\x4f\xa0\x8f\x2e\x3e\x87\x2e\x3e\x2a\xa2\x7c\xf8\x69\x2e\xcc\x1f\x6f\x7e\xf7\xd1\x6d\xcf\x8e\x99\x0c\x60\xeb\x11\xe4\xe4\xde\xe6\xe6\x82\x7c\x50\x49\x73\x27\x68\x03\x6b\x9e\x4d\x92\x93\x1c\x56\xdc\x94\xe3\xc6\x18\x1a\x28\xee\x2c\x51\x92\x33\x30\xc4\x78\x11\xea\x6c\x92\x97\x60\x0c\x3b\xc5\x18\x2c\x64\xd3\x30\x46\x1e\x84\x3e\xe8\xa0\x38\x83\xf4\x96\x63\x61\x4f\x78\xfe\xae\x8c\x21\xbd\x7a\xf5\x59\x34\x7c\xe2\xa2\xb1\xa5\x23\xa0\x07\x86\x51\xec\x50\xf6\x90\x7e\x3d\xcb\xaf\x99\xb7\xe2\x89\xf2\x19\xe8\x0d\xe4\x64\x17\xc3\x49\x43\xfa\x3b\xbe\xcb\x0b\x2f\x5c\xfe\x31\xfc\xba\x45\x40\x45\x03\x22\x96\xb3\x79\x0d\x8f\xc3\x21\x2d\xbf\x20\x67\x7a\x03\x72\x0a\x43\x04\x8c\x53\x67\xb5\xed\x90\xa0\xc7\x50\x3f\x2e\x90\xe6\x80\x82\xce\x40\x01\xb5\x6c\x0d\x93\x8d\xca\x4c\x77\x26\xe0\x8d\x12\xe8\x46\xe9\xc9\x46\x61\x6c\x2d\x8a\x54\xd3\x98\x5d\x54\x26\x8a\x22\xc1\x1e\xe4\x74\x89\xa9\xd3\xe5\x11\x7d\x22\xde\x05\xd6\x27\x89\x76\xc0\x93\x6d\xd9\x00\xfd\xb7\x3f\x0d\xb3\xe4\xf5\x63\x61\xd6\x68\x74\x0c\x9d\x40\xa7\xd0\x9f\xd1\x47\x4c\x80\x09\xb7\xbc\xfe\xfc\x26\x33\xdf\xe7\xc2\x9b\xe2\x33\x8d\x9f\xc2\xbe\xe8\x34\xba\x80\xce\xa2\x3f\x88\xa8\x18\x7e\x60\x80\x3e\x00\xc1\xdc\xd6\x33\xc2\x72\xae\x0e\x94\x80\xa5\x20\x5e\x84\xe7\x92\x4b\x4f\x9b\x14\x22\x22\x51\xf6\x84\xa1\xdc\xa5\x63\x5d\x5a\xd5\x63\x8c\x4d\xe9\x2c\x31\x49\x30\x81\x5a\xb4\x5c\x36\x8b\x0a\x57\x14\x8b\xc9\x36\x49\xf1\x15\x90\xc8\x6a\xc5\x93\x8b\xc5\xb9\x24\x7b\x63\x40\x31\x14\x89\x92\xec\x8b\xc9\xac\x18\x07\x96\x2c\x35\xc8\x57\x8a\xfa\x98\x36\x50\x45\x5f\xd8\x59\x9f\x2a\xf4\x8b\x29\xc8\x62\xe6\xf6\x18\x00\x8b\x56\x4c\x99\x74\xf5\x28\x98\x31\x6a\x5c\xdd\xd4\x15\xb0\x68\x40\xcf\xb3\xef\xdf\xba\xad\xd4\xd8\xfd\xd1\x25\xc7\xcf\x30\x79\x5b\x21\xf7\x24\xba\x80\x8e\xee\xd8\x73\xf3\x5d\xb0\x04\x9d\x6c\xa8\xff\xe5\xd3\x30\x0c\x85\xa7\x10\x7a\x14\xfd\x80\xfe\x38\x73\xe6\xbc\xa9\xb0\x3b\xe1\xe6\xcd\x84\xeb\xe3\x48\x5c\x5a\x11\x98\xd7\x49\x54\x9a\x9f\xfa\x1c\x72\x42\x50\x2e\xee\x18\x95\xd6\xe6\x73\xc8\x24\x6f\xe4\x4b\x49\xe2\x55\x6b\x0b\x4a\xcb\xb7\x89\x52\xa3\xe4\xc9\xf1\x5f\x1a\x88\xd6\xc1\xf9\xd0\xce\x0c\x48\x77\x3f\x98\x35\x4a\xfe\xa1\x36\xdb\x00\xb4\x5e\xd2\x80\xa2\x39\x3f\x8d\x43\xfc\x53\x9b\x03\x82\x55\x39\x44\x8e\x70\x88\x65\x60\x65\xe7\x0c\x62\x80\x32\x88\x6a\xf0\x1d\x15\x80\x8d\x6e\x16\xe8\x03\x4a\xb6\xf8\x13\xa2\x50\x2e\xc0\xdf\x77\x91\x68\x44\x1e\xa1\xc3\xb0\x4c\xa4\x64\x61\x51\xe0\x67\x48\x47\xc7\x65\x5c\x13\x9d\x49\xcd\x17\x2e\x75\x51\x5c\x8e\x11\xec\xe8\xac\x60\x29\xf6\x23\xdc\x6e\x06\x28\xc0\xfa\xbe\x13\xf4\xe7\xef\x0c\xfd\x15\xaa\xfa\x32\xc1\x1a\x33\x73\x49\x8b\x4b\x9d\xa8\xe4\xe5\xff\x6c\x24\x98\xa2\x7f\x2f\x0b\x09\xb7\x69\x1e\x87\xcb\x41\x43\x06\xb6\x71\xd4\x74\x4f\xeb\x48\x8e\xc7\x8d\x9d\x69\xb1\xbc\x9f\xa9\xc5\xf2\x55\x2d\x96\x10\x1c\xee\xcc\xdc\x42\x4f\x4c\xb1\x18\x44\x49\xc9\xca\xfe\x19\xbb\x96\x72\x1e\x74\xaa\xdc\x36\x6b\xe4\x76\xa7\x9b\xc3\xfe\xb5\x8d\xe6\x06\x0c\x95\x3f\x02\x96\x3f\x3d\xc0\xaa\xcb\x4b\xa0\x9e\x3f\x21\x81\x42\x9d\x4a\xa0\x84\xaf\xa0\x4b\xb7\x1e\x78\xcf\x5c\x62\xa3\x27\xb7\xac\x3b\x7e\xf9\x3f\x17\x44\xa9\xe9\xff\xa4\x44\x7a\x42\xdb\xda\x9f\x29\x9a\xd8\x5f\xa7\xe7\x55\x4c\x6c\x3d\xc3\x3d\x2e\xe4\x11\x2c\x10\x04\xb7\xaa\x32\x2a\xc7\x98\x94\x0b\x82\x8a\x5d\x47\x1c\x84\x25\xd6\xa4\x5c\xa6\x66\xbc\x52\xb7\x52\x26\x09\xca\x97\x33\x69\x18\xb1\xc3\x95\x94\xbb\xe6\x1f\x17\xb5\xd4\xd7\x9e\x30\xa0\x74\xcd\x14\xa5\x97\x58\x93\xdd\xe0\xc9\x29\x28\xa4\x4c\x76\x0e\x46\x80\x0e\x6a\xa5\x59\x62\x4a\x89\x81\x02\xc4\x32\xd5\x66\x23\xa7\x5b\xad\x21\xe0\x52\x5b\xd0\x10\x84\x58\x84\x35\x2c\xe1\x79\x1c\x69\xa8\x7c\x22\x1c\x0d\x8b\x9e\x7d\xe9\xad\xed\x0f\x2f\x0a\xf6\x7b\x75\xda\x5b\x5f\xaf\xfd\xe7\x13\xe8\xef\xe8\x4b\x18\xd3\xaf\xbc\xf9\xe4\x8c\x09\xbb\xb8\x82\x19\x91\xa1\x43\x06\xf6\xef\xbd\x88\x39\x06\xd7\xc1\x43\x0f\x2c\x5d\xf9\x8b\xfe\xab\x5f\x1e\x5d\xfb\xd5\x9b\x4f\xfc\xfd\x4e\xb8\xf2\x8b\xe7\x0e\x40\xd3\x8c\x15\x4c\x4e\x46\x4e\xa8\xb8\xb4\x4c\xe5\xf2\x4b\x5b\xcf\xf0\x78\x3d\x02\x20\x0c\x1e\x05\x71\x1f\x5e\x0d\x93\x3e\x29\x67\x93\x06\x27\x19\xba\xa4\x1c\x0c\x35\x32\x19\xd9\x7a\x42\xe7\xcb\xa1\x20\xb6\x98\x88\xdf\xb1\xf8\xb8\xc2\x8b\xc9\x78\x31\x71\x90\x17\x63\x63\xa9\xd8\xae\xe8\xbd\x49\xd9\x89\x6f\x45\x37\x8c\xef\x89\x4b\x5f\x0e\x86\x94\x5c\x57\x52\xc9\x70\x50\xcf\x64\x37\x27\x75\x8b\x5b\xc5\xb8\xc9\x47\x52\xb6\x32\x68\xb9\xe9\x52\x93\x28\xc5\xf5\xfe\x00\xc9\xe2\x12\x49\x01\x2c\x25\x94\x41\xea\x52\x93\xfc\x21\xb2\x5a\x2e\x35\xff\xbb\xa4\xb8\x90\x50\x92\xf9\x8e\xb0\xcb\xef\x21\x57\x48\x2c\x57\x73\x8a\xa0\xd3\xed\xc1\xb0\xa5\xf4\x17\x5b\x26\x4e\xb7\x4d\xae\x7d\x70\x13\xf3\x09\x7a\xe3\xc9\x4f\xdf\x80\x7f\x19\xbf\x71\x35\x83\x0e\xa1\xdf\xa1\x11\xe6\xac\xec\xae\x3d\xe0\xe7\x47\x9b\xdc\xeb\xa7\xac\x66\x3e\xa9\xa9\x9b\x50\x79\xd7\xd0\x91\x63\xbe\xfc\x67\x9e\x8f\xb9\xf9\xbd\x7b\x9e\xf8\x55\xcb\x81\x53\x81\x32\xb4\x17\x6d\x83\x23\x23\x33\x03\x5d\xb3\x73\x98\x1d\x0b\x6e\x63\x76\xb6\xc5\xab\xf0\x02\x7f\x08\xb8\x40\x7f\x35\x96\x44\xc7\x80\x00\x06\x57\x66\x03\x0d\x82\x72\x1e\xc7\x07\x85\x20\x5b\x87\x53\x8d\x59\x31\x3b\x45\x29\x6e\x64\x5c\x78\x8a\x3a\x91\xe4\xb9\x8b\x3e\xd8\x9f\x0d\x87\x3c\x2e\x52\x36\x4e\x60\x74\x34\x90\xa5\xac\xff\xd2\x19\x8b\x6f\xb8\xa6\xaa\x5b\x46\x97\x48\xe6\x15\x4d\x15\x24\xa2\xe5\xf1\xbb\xff\x21\x57\x65\x9d\x32\x07\x4a\x26\xa1\x6d\xf7\xb7\xbc\xcf\x04\x53\x71\xfb\x45\x24\x56\x3e\x17\x5b\x04\x39\x78\x34\x76\xda\xb4\x53\x71\x19\x92\x8d\x20\xc7\xae\x26\x22\xe4\x10\x66\x82\xc8\xa9\xec\x1c\x2d\x76\x3f\x47\x94\xe2\xa6\xac\xdc\x18\x05\x16\x90\x9c\x58\x5a\xf7\x3b\x2d\x86\xff\xd2\x41\xa6\x87\xf3\x5f\x3a\xda\xf4\xb8\xfe\x4e\x87\x4d\x7d\xf9\xbc\xa0\xab\x51\x75\xe9\x6d\x97\xae\xe3\xa5\xba\x94\x2e\x6a\x63\xb6\xc3\xa9\x0f\x90\xc8\x11\x77\x10\xab\xd4\xc6\x02\xf2\x86\xa6\x35\x9d\x6e\x51\x8a\xc3\x8c\xbc\x58\x2c\x46\x34\xa8\xcc\xc4\x94\x2e\x8e\x94\xfe\xfc\x99\xbb\xf0\x23\x2e\xfe\x4b\xe7\xfb\x52\xa7\xbe\xfe\x4b\x67\x7e\xa9\xd3\x9f\xc5\xf6\x89\x50\x22\x38\x81\x08\xbc\x20\x0f\xcc\xa7\xb1\x5d\xb2\x39\xac\xb8\xf4\x49\x39\x43\x95\xd8\x42\x58\x71\xeb\x92\x72\x5e\x88\x14\x80\x09\x6a\x29\x60\x92\x2b\x29\x4b\x34\x74\x86\x75\x85\x42\x24\x06\x89\xcf\x08\x91\x3c\x37\x6c\x96\x1a\x5c\x24\x2f\x8c\x26\xe5\x63\xf1\xe3\x16\x15\x03\x2d\x67\xa2\x30\x3a\x8d\x1b\x17\x7d\x22\x07\x5c\x4e\x15\xfc\x16\x61\x4c\x6c\x85\x90\xf2\x45\xb5\xb0\x1c\x16\xc3\x2c\xe8\x85\xfd\xd1\x1b\xe8\x0b\x74\x0a\x9d\x42\x07\x61\xef\xad\x77\xad\x7e\x82\xe9\xb3\x76\xcb\xe6\x06\x26\xd8\x02\x8b\x1c\x50\x46\x63\x3d\xe8\x8f\xdf\xfe\x13\x9d\xf0\xa0\x6c\xf8\x45\x26\x0c\x9e\x5d\xaf\x48\xcc\x76\x71\x1f\x2a\x95\xe2\xf7\xdd\xf9\xa2\x03\xcb\x9b\x70\xeb\x19\xdd\x61\xae\x0e\x38\x41\x17\xf0\x98\x3a\x53\x63\x58\xf1\xea\x93\xb2\x2f\x14\xf7\xda\xb0\x30\xf1\x66\x1b\x02\xd4\x9c\x75\xea\x92\x0a\x57\x1c\x0a\x41\xb9\x94\xe4\x7d\xba\xc4\x64\x5c\x22\xec\x8c\xa4\xb2\x33\x18\xde\xe7\x8a\x29\x37\x8f\x4e\x4c\xc6\x75\x85\x29\xc3\xbc\x2b\x0c\x28\x2e\x89\x96\xb6\xcf\x12\x15\x5b\x09\x2d\x76\x68\x31\xc7\x62\x72\xa1\xa8\x18\x8b\xf1\x09\x90\xa8\xc1\x6e\xa3\xc6\xb0\x53\x54\x74\x52\x2c\x65\x0e\xbb\x5d\x4e\xc2\x91\x08\xfe\x02\x26\x52\x1e\x75\xa8\xe2\xc7\xe7\x52\x35\x78\x89\x4f\x08\xef\x15\xfe\x86\x50\xe5\xa9\x8f\xbf\xbe\xda\x58\x7d\xf6\xe3\x53\x95\x27\x6b\xa7\x8f\x1b\x05\xbd\xa3\xc6\x4d\xaf\x1d\xd0\xbc\xbd\x3f\x31\x9b\x8f\xc6\x9b\xd1\xb7\x7f\xf8\x03\xb4\x36\xc7\x8f\xa2\x86\xcd\x0f\xd6\x37\xac\x5b\xd7\x50\xff\xc0\xa6\x5f\xfe\xf1\x6d\x92\x7b\x7d\x06\x39\xf9\x3c\xae\x0e\x94\x82\xb5\x20\x5e\x80\xef\x41\x36\x09\x33\xa4\x8c\xb4\x52\x22\x24\x65\x47\x50\xf1\xaa\xee\xae\xa2\xe3\x0a\xef\x25\x02\x96\x10\x28\xde\x64\x63\x96\x29\x57\x1f\x50\x44\x2f\xf5\x72\xf1\x45\x18\x45\xf9\x62\x31\xc5\x94\x2b\x4a\x8d\x7a\x87\x2b\x1f\xab\x69\x11\x1f\x76\xa0\x78\x1d\x14\x39\x17\x88\xb2\x3b\x26\x97\x48\x2f\xf1\x26\xab\x3d\x37\x5f\x57\x8a\x7f\x87\x11\x69\x31\x2c\x7a\xde\x75\x50\x55\xde\x51\xd1\xee\x2b\x28\x89\xd0\xd9\x17\x8a\xe5\x51\xe8\xab\x90\x22\xe5\xfe\x02\x9d\x73\xd0\xac\x17\x5f\xb0\xc3\x6f\xa0\xf9\x8d\x61\x13\x83\x01\xf4\xf1\xf8\x2b\x43\x3d\xa2\x3d\x50\x73\x26\x2a\x45\xdf\x8d\xae\xb9\x37\x50\xc4\x55\x65\xff\xfe\x8f\x13\x27\x30\x35\xe8\x6e\xf4\xc7\x55\x0b\xec\x68\x3d\xda\x93\xf5\xbe\x14\xad\x7c\x20\x0a\x6b\x6e\xbe\xba\x25\xf1\x10\xac\x7d\xe2\x5b\x3b\x89\x2f\x05\x80\xc4\x97\x5a\x41\x26\xb8\x8e\xf2\x31\x34\xb6\xd4\xcb\x26\x13\x66\xc9\xc4\x5a\x02\x8a\xd9\x44\xcb\xb0\x50\x5a\x46\x75\x45\x9a\x60\x80\x44\x5e\x1a\x29\x80\x11\x3c\x49\x72\xfe\x8d\x58\xa9\xb0\x92\x97\x50\x49\x5e\xa9\x63\xd8\x69\xda\x91\x4f\x69\xda\x25\x70\x2e\xbc\x12\x8e\x81\xd3\xd1\x29\xd4\x8a\x0e\xa3\x1f\xd0\x5f\xe1\xe0\x5f\x35\xed\x7b\xf5\xd5\xa6\x97\xf7\xb3\x73\xa1\x1f\xf6\x43\x87\xd0\x07\x3f\xa0\x43\x85\xe8\x1c\xb4\x16\xc2\xde\x68\x77\xd3\x8b\xcf\xed\x79\x71\x1f\xe5\x1a\xb8\x2d\x5c\x3d\xb0\x81\x2c\x30\x51\x65\xc0\x32\x8c\x49\xd9\x14\x4c\x38\x38\xa0\xe3\x02\x5a\x10\x9c\xdd\x45\x52\x1f\x55\x17\x90\x96\x30\x8c\xd1\x71\x0e\x7e\xcb\x8c\x87\xed\xc8\x20\xc3\x76\x98\x44\x49\x31\x5a\x62\xc4\x53\xd7\x1e\x1b\x3b\x89\xa4\x6a\x8f\x8e\x6b\x55\x50\xfc\xce\x7e\x74\x64\xdf\x7b\x9d\xd1\xa4\x5f\xa0\x8f\x02\xc8\x0d\xff\xd6\x0d\x76\xf9\x44\xa3\x4a\x01\xc4\x6b\xcf\x1d\xe5\x0f\x03\x17\x18\x4d\xf3\xd9\xe8\xca\x1b\xd8\x64\xa3\x20\xb1\x58\x85\xb8\x3b\x86\xeb\x8b\xaa\x86\x13\xa5\x94\x8b\x48\x20\x8b\x6c\x8e\xd1\xe4\xa0\x8e\xc9\xcc\x94\x98\xc6\x63\x06\x4b\xe0\x1c\x58\xf5\xfe\x89\xa9\xd5\xcf\x5c\x95\x78\xf5\xb7\x07\xa7\xa3\xc3\xdf\xa2\x66\x76\x16\xcc\x86\x83\xa7\x37\x97\xf4\x8e\xbf\xb0\x57\x6e\x39\x0f\x3d\xa5\xb0\x1b\xe1\x15\x27\x72\x25\x5c\x3d\x28\x02\x33\x00\x25\x43\x0d\x46\xe2\xc0\xca\xc1\x57\xa2\x38\x3d\x8c\x1d\x6b\x37\xa7\xa3\xcd\x78\x8c\x67\x66\x15\xc6\x48\x85\xa7\x17\x0d\x9c\x48\xcd\x47\xd9\x29\x29\x12\x29\xf3\x94\x83\xcd\xc8\x4c\xda\x51\x5f\xe7\xcc\xc2\x3f\xe3\xd4\x88\x83\x72\xa9\xb0\xad\xdb\xbc\xea\x32\xa4\x3d\xf5\x35\xf4\xde\x1d\xd6\xde\x0b\x99\x17\x8e\xbf\x3c\xf1\x91\x07\xee\xbd\xcb\x3f\x64\xf6\xd0\xf8\xc6\x73\x1f\x56\xae\xcd\xb8\x61\xca\x75\x37\x8e\x9e\xfe\xc9\x49\x78\xf6\x6d\x58\xb8\x65\xec\x5f\xab\x0e\xfd\x76\xf0\xd5\xa1\x7c\x29\xf8\xf0\x1d\xcf\x34\x3a\xf4\xa7\x7c\xe1\xfe\x65\xe5\xce\x6e\x5f\xa6\xf2\x4e\x04\x12\xab\x39\xb6\x5d\x8e\x8d\x39\x99\x30\xf2\x24\x43\xc3\x68\x4a\xc6\x8d\x04\x68\x19\xf5\x86\x54\x4a\x2a\x3e\x37\x9c\x96\xac\xa1\xe8\xbc\xc9\xb8\x8e\x14\xc7\xd0\xb1\x1d\x13\x50\x44\x5f\xc4\x2f\xee\x63\x47\xb7\x7c\x0e\xbf\x47\xe8\x3c\xdf\x84\x50\x03\x72\x9c\x6b\x79\x4d\xf3\x5b\xb2\x9f\x70\x75\xc0\x04\x46\x00\x62\xf4\x28\x9c\x8e\x44\x38\x18\x83\x0a\xaf\xff\x6f\x7e\xb2\x9a\x95\x2a\xfa\x23\x7e\x71\x3b\x5b\xd9\xf2\x2d\xfc\xec\xfc\x57\xc8\x29\x8c\x38\x85\x9e\x42\xc1\xaf\x9a\x3f\xa1\x35\x27\xce\xb7\x9e\x61\x4f\xf2\x87\x81\x1f\xeb\x3d\xa7\xea\x9f\xa4\xd1\xd5\x3e\x21\x99\xd0\x67\x3a\x19\x4b\x40\xd1\xb3\x49\x42\xcc\xe5\x1e\x57\x78\x89\xc8\x3d\x42\x18\xaa\x51\x89\x7c\x2e\x49\x50\x50\xcc\x74\x2b\x81\x62\xa3\x8d\x4b\xe4\x4c\x31\x6e\x16\x31\xc4\x54\x7c\x7a\x51\x8a\xf3\xb9\x7e\x8a\x2d\xd3\x25\x9c\x0d\xfa\x58\x21\xad\x53\x4c\xa4\xbc\x12\xfa\x1c\x2a\x92\x34\x8e\x59\xbc\x69\x5b\x6e\x19\xd3\xe7\xe1\xac\x80\xbf\x67\x78\xe4\xe4\xbb\x1f\xf3\x55\xb6\xbc\xbe\x36\xab\x47\x7e\xb7\x2e\xfc\x2e\xff\xda\x65\x57\xcf\x7a\x18\x09\x35\x25\x99\x79\xd2\x09\xef\xaa\x05\x75\x73\x8f\xc2\x57\x6a\x82\xd9\xd9\x1e\xca\x85\x3b\x39\xb3\xe0\x07\xc5\xe0\x6a\x20\xe7\x07\x95\x2c\x5d\x52\xd6\x05\x15\x8b\xea\xb0\xf7\x1f\x57\xbc\x8e\xa4\xcc\x61\xb8\x6c\x17\x93\xc4\x37\xef\xe7\x68\xfc\x87\xd7\x2e\x4a\x72\x71\x0c\x28\x59\xf9\xa2\x24\xe7\x62\x9c\xd2\x68\xb4\xd3\xa3\x6b\x91\x54\xba\x56\x1d\xa5\xa0\x2b\x51\x85\x35\x5b\xe4\xe9\x30\x97\xa8\xa3\xf6\xb3\xac\x60\x8e\x58\xee\x08\x8f\x59\x7a\xcf\x96\x82\x1d\xcc\x8d\xc2\x3f\xb2\x22\xb1\x50\x78\xf4\xfc\xad\x4f\xfb\xde\x83\xcb\x0e\x30\x63\xab\x2a\xf3\x72\xcc\xa6\xa3\xfe\xbb\x56\x5e\x33\x15\x0d\x5a\xb1\xab\xe5\xc6\xa1\xbd\xfa\x96\x4b\x27\x32\xd6\xdd\x3d\xe6\x7a\xa6\x94\xea\x27\x00\xb8\x21\xfc\x7b\xc0\x0b\x62\x6a\x36\x2e\xd9\x23\xc2\x24\x66\x90\x5c\x5c\xde\x45\xdd\x7d\xbc\x89\xec\x06\x50\xdc\xd8\xf6\xe5\xbd\xe9\x2b\xee\x53\x43\x5d\x25\x31\xc2\x97\x14\x15\x97\xe0\x7f\xb0\x0a\xd9\x0d\x8d\x70\x0c\x1c\x3f\xac\x0f\x7a\x67\x35\x3a\x39\x11\x2e\x14\xbb\xa0\x69\xb5\x70\x75\xf5\xe2\x4d\xeb\xf8\x1b\x67\xa3\x31\x68\xfc\x16\xb4\x73\x35\x8c\xc1\xb2\xa2\x3d\x5b\x4f\x4c\xbf\xfa\x9b\x47\x3f\x8d\x8c\xc5\xe3\x9a\x86\x9c\xec\x1e\x21\x0f\xb8\xc1\x93\xa4\xe7\xaf\x25\x28\x4b\x41\x12\x58\xe6\x38\x4e\x50\x91\x11\x06\x14\xce\x45\x02\xcc\xe4\x8a\x4c\xb9\x38\x13\x2a\x92\xa3\xfb\xdb\x40\x71\x48\xdd\xdf\x96\x2b\x32\x5f\x71\x7c\x7c\xa8\x14\xb8\x02\x46\xab\xec\xb0\xcb\xce\x03\xb2\x64\x97\xc5\x03\xe4\xf7\x2c\x56\xfc\x7b\x56\x8b\xfa\x7b\x1f\x1c\xea\x42\x7f\xcf\x6a\x97\x6d\x07\x64\x8b\x5d\x36\x1f\x00\x8d\x66\x9b\xe8\x24\x35\xd8\x53\xaf\xe4\x01\x99\x90\x56\x95\xd4\xc5\x80\x62\xd1\xb7\x15\xf8\xe7\xf4\x50\x9d\x7e\x79\x49\x6a\xfe\x45\x5b\xe1\x55\xf0\x1b\x28\xd4\x8c\x42\x6f\xee\xd4\xa3\x86\x5e\xf0\x01\x5f\x04\x2d\xef\x0d\xc7\xed\x42\x5f\x0a\x79\x7d\xd1\xb6\x96\xa3\xe8\xa9\xb7\xd1\xca\x4d\xf0\x3a\xb8\xee\xc6\xaa\xe5\xbb\x57\xaf\x9c\xb2\x6a\xef\xfc\x77\xa6\xe0\x33\xb6\x17\x39\x75\x9f\xf0\x4d\xa0\x14\xd4\xab\x68\x4a\x1f\x56\x3c\x2c\x06\x8a\x71\x07\xde\xa1\x2c\x7f\x38\x2c\x97\x06\x15\xc0\x52\xe8\x20\x91\x2a\x89\x2e\x57\x2a\x1d\x39\xc7\x95\x94\x73\xec\x4a\x01\x0c\xc8\x7c\x48\x29\x52\xe3\x64\x32\x5d\xa9\xea\x77\x66\x53\x2c\x26\x17\x48\x71\x56\xd0\x13\x75\xe4\xb1\xe1\x7d\x25\x49\x2a\x1e\x5f\xa8\x3f\x8c\x92\x82\x3f\xaa\xd7\x96\xc4\x69\x6b\xf1\xda\xda\x57\xae\x14\xee\xe5\xce\xad\x5e\x63\x15\xcc\xf5\x9f\xdf\xbd\x2f\x62\x8e\xbc\xbf\xec\x4f\xef\xc0\xc8\xa1\x86\x55\x30\x72\x68\xdd\x0a\x18\x41\x9f\xa2\x93\x17\xdd\x67\x6e\x38\x52\x97\xa8\x9b\x75\xdd\xdc\x13\x9f\x73\xf6\xe6\x2a\xf4\xbd\xfc\x0a\x5b\x8b\xbf\xee\x7f\x9f\x8d\x5c\xa8\x43\xff\xf8\x07\x91\x57\x5b\x91\x53\xd7\x87\x60\xa5\x5b\x40\xbc\x04\xcf\xd9\x17\x56\x04\x03\x89\xe1\x26\xe2\xcb\xe8\x08\x87\xe5\x8c\xa0\x92\xa9\x4f\x45\x07\xa5\x91\x37\x84\xb0\xa1\x95\xcb\xa4\x90\xe2\xb2\xd1\x09\xb3\x40\x94\x94\x8c\x4c\x9a\xc0\x5c\x12\x93\xcd\x92\xe2\x2f\x24\xb5\xcb\x94\x3c\x1f\xd1\x6b\x25\xa2\xa4\x60\x09\xd2\xc1\x5f\x9d\x7a\x81\xa7\x19\xf1\xe5\x57\x42\xbc\x1e\xea\x72\x6c\x85\x3d\xaf\x1a\xbf\x60\x3e\xfe\x77\xf1\x2c\xd8\x13\x9d\x42\x1f\x5c\xdc\xc3\xd5\x82\x56\x83\xc5\x32\xe3\x48\xf3\x84\xac\x6e\xca\x9c\x5f\xff\x06\xae\x65\x4e\xb6\xd4\x2f\x5b\xb6\x7d\x2f\xd3\x13\x7f\xdd\xf3\x3a\x63\xbd\xd8\x84\xce\x9d\xfb\xf2\xeb\xdd\xcf\x3c\x3d\x6a\xfc\x6f\x54\xdf\x1a\x00\xdc\x19\xfe\x30\xad\x37\xe4\xc5\x77\xd0\xc5\x68\x4a\xda\xc8\x26\x13\x79\x76\x2f\x86\x47\x79\x78\xa7\x49\xed\x21\xc5\xe2\x4a\x62\x43\xc0\x4b\xe3\x39\x3c\xae\x24\x49\xf7\xf5\x5a\x44\x29\xc1\x0a\xf6\x6c\x42\xf5\x7b\x44\x39\x2b\x06\x14\x7b\x1e\xf5\xc2\x19\x45\xe2\xb6\x92\x5d\x9a\x12\x04\xed\xc2\x7e\xc2\xa1\xfe\x90\x7a\x35\xcb\xa3\x94\xb9\xa9\x85\xd2\xb9\x41\xb3\xfb\x8c\xf3\xf7\x0f\x4c\x5e\xb8\xec\xe6\xf9\x0d\x95\xb0\x1c\xbd\x63\x32\xf5\x7f\xfd\xf6\x2f\xff\xce\x1e\x3a\x07\xbd\x19\xde\xef\x2d\xd2\xda\xe5\x0f\xde\x79\xc3\x6f\x9a\x60\xf8\xc2\x08\xf8\x61\x70\x52\xed\x2c\x98\xa9\xc9\xc8\x85\xc4\x5f\x38\x19\xc4\x33\x49\x4e\x8b\x21\x19\x17\x21\x49\x54\x48\x39\x10\x65\x67\xb0\x83\x0f\xd1\x09\x03\xb2\x3d\xa4\x38\x6c\x49\x02\x81\x9d\x26\x51\x6a\x64\x79\x92\x2e\x28\x3b\x44\x99\x54\x59\xc9\x14\x25\x99\x04\x71\xa5\x30\x9f\x94\xd2\xe7\xda\xd9\x24\xf3\xc0\xe0\xbe\xf6\xdc\xa9\xaa\xea\xaa\x82\x8c\xea\x29\x27\xe6\x4f\x83\x21\xf4\x3b\x8b\x65\xf6\xef\xde\xfe\x8c\x29\x85\x79\x30\xe0\xf9\xda\xbc\x63\x0f\x92\x77\xbd\xc7\x58\x7f\x68\x82\xef\xf7\x9b\xfd\x0c\x0c\xa8\x39\xa3\x08\xf0\x59\x24\xff\x61\x6e\x9a\xee\x96\xcd\x41\x45\xb4\x24\x13\xbc\x97\xa6\x8c\x5a\x52\xa9\x8e\x59\x34\xc1\x32\x8b\x92\xa1\x7a\x1b\x85\x7b\x59\xf8\xf0\x59\x6d\x31\x6c\x7e\xc4\x79\x52\xa2\x00\x90\x7c\x29\xd9\x1a\x93\x81\x88\x2f\xa2\x57\x52\xf4\xce\x58\x4c\xe6\x45\x12\xb8\x10\x16\x7d\x62\x05\xcd\x1c\xe0\xfc\x05\x25\xa2\x3b\x1c\x92\x22\xe5\xc4\x59\x23\xee\x83\x15\xb3\x56\x40\x27\x0c\x6d\x42\xdf\x29\x3b\xd6\xae\x5e\xfb\xf0\xf3\x43\x1f\x59\x3f\xa6\x8a\x6f\x6a\xf9\xae\x0c\xad\x41\x8f\x9f\x45\xbb\xe2\x41\x68\x0f\x42\xfe\xf3\x6d\xef\xde\xe4\x6b\xa9\xd5\xe2\x97\x8c\xdc\x44\xae\x2e\x7d\x2e\x90\xce\x45\x62\xdb\xe6\xc2\xb6\xcd\xc5\xa6\xcd\x05\x23\x6e\xbd\xa3\xe3\x5c\x48\x51\x1e\x89\xcc\x45\xba\x64\x2e\xae\x8e\x73\x09\x49\xa2\x93\xc1\x37\x27\xbd\x3c\x8c\xb8\x1d\xf6\x1c\x3d\xe9\x8b\x7f\xae\x3a\xf5\xd0\xfd\x8b\xca\x96\xf5\x5c\xdc\x70\xdb\x5d\xa1\x1e\x5c\x1d\xaa\xf5\xa3\xdf\xa0\x3f\x1d\x40\x5f\x6e\x0a\x43\x9d\x37\xf7\xd0\xee\xc6\xe7\xbc\xa8\x92\xce\xa3\xa6\xf5\x0c\x97\xc1\x1f\x06\xa5\x78\x1e\x58\x3e\x28\x05\x6c\x92\xdc\x15\x8c\x65\x55\x29\x48\xc4\x00\xc0\xba\x37\x8f\xca\x03\x01\xdf\x0c\x55\x18\xe4\xd1\x1a\x6d\x8a\x60\x16\xa5\x26\xd6\xea\xca\xca\x2e\xa0\x81\x82\xa2\x52\x48\x42\x30\x0a\x4a\x44\x49\x2e\xc2\xb2\x22\x01\x6c\x92\xb7\x90\xe6\xa5\x96\x57\x44\x53\xee\x3c\xa7\x87\xef\x0e\x23\xe5\x85\x94\x36\xd0\x59\x19\xaa\x97\x45\xc1\x57\x50\x58\xf3\xcc\xaf\x0f\xcc\xbf\x6a\xdc\x98\xf1\x12\xba\x90\xe9\x83\xf0\x4f\xc7\x2f\xee\x3a\xb2\x7a\x66\x78\xf6\xac\x77\xff\xb2\x1f\x35\x9f\x43\x08\xde\xbb\xf1\xbd\xe1\xc3\x6e\xac\xa9\x1a\x77\xcd\xd5\x5d\x8b\x67\x96\x2c\xec\xb9\xff\xcf\x1f\x1e\x7a\xf6\xc4\xd0\x40\xef\x61\x3d\x46\x8e\xab\x43\xa8\xf6\x18\xcd\x1d\x46\x4e\xf6\x7d\xae\x1e\x74\xc3\x73\x75\xe3\xeb\x62\xd2\x25\xe5\xae\x41\xc5\x8f\x71\x71\x19\x55\x83\x5e\x6c\x5c\xcb\x56\xbb\x02\x1c\x04\xd7\x59\x29\x6e\xcb\xb0\x25\x95\xee\x30\xa0\x58\x1d\xb4\x1c\x91\x5e\x6c\xe2\x4c\x76\x77\x8e\x9f\x44\x29\x67\x48\x4a\x71\x09\x9e\xab\xbf\xab\x28\x61\x89\x68\x12\x13\x40\x74\x64\x14\x93\xb9\x7a\xca\xfb\xc3\x68\x7f\x26\x35\x59\x9d\x1a\x20\xe8\x72\x5a\x21\x99\x6c\x38\x54\x41\x83\x20\x0a\x7b\x5e\x79\xd7\x96\x25\x37\xf6\xbc\x6e\xe4\xb0\xda\xc0\xe9\x11\xdf\x1e\x3b\xf2\xd5\xa8\x8d\xeb\x57\x5c\x1f\x3a\x33\x49\x99\x76\xd3\xab\xb7\x9e\x45\xdf\x97\x2d\xdc\xbd\xea\xca\xde\x63\x6f\x1a\x7c\x55\x75\xf5\x95\x57\x8d\xa9\xad\x5f\xd3\xf8\xc7\xdf\x35\xde\xf6\xf2\x7d\x83\xfb\x8d\xac\xed\x73\xb2\x5b\xf9\xdf\x7a\x14\x27\x29\x5f\x49\x73\xc8\x0f\x83\x2c\x90\x0b\x06\xa9\xd9\x8d\xd9\x6a\x5d\x15\xd9\x1e\x56\x78\x63\x52\x76\x85\x20\x09\xce\x85\x01\xa0\x64\x93\xb2\x31\x99\xe4\xb0\x25\x18\x9d\x23\x23\x97\x86\x50\xc5\xf5\x16\x29\x46\x73\xe2\x60\x09\x3e\x69\x04\x43\x79\xda\x0a\x98\xd9\x20\x74\x41\x1f\x8c\xc1\xbf\xda\xfa\x5f\xdb\xad\xa2\x6a\xfc\xf5\x75\x6b\xfa\x56\xdc\x39\x61\xfc\xa4\x41\x65\x65\xa1\x81\x99\x36\x78\xac\x79\x36\x33\x11\x7d\x18\x67\x57\xe4\x35\x48\x9f\x94\x8e\x99\x5c\x57\x5d\x7a\xc6\x31\xb8\x22\xa7\x79\x95\x0c\x19\x66\x08\x19\x6f\x1e\x00\x5c\x4f\xae\x0e\x64\x82\x1c\x50\xad\x8e\x37\x4b\x97\x24\x1e\x59\x32\x5e\x81\xc4\x0b\xf3\x76\x59\x97\x7f\x5c\x94\x1d\xb4\xa9\x8c\x14\x82\x72\x6e\x50\xc9\xc3\x33\x20\xf7\x09\x66\x10\xae\x2a\xce\x78\x73\x30\x9c\xd5\xf3\x6a\x0b\xcf\x70\x04\x92\x3b\xdf\x61\xf4\x78\xf0\x45\x3e\x36\x0f\x3e\x58\xd2\xbb\xb8\x47\xa8\xd7\xd0\xeb\xea\x6e\x0e\x45\xea\x27\x5c\x37\x34\x1a\xea\x79\x45\xc4\x06\x97\xb7\x64\xc0\xa6\x23\x7b\x99\x49\x55\x3d\x9d\x7f\xc8\xeb\x33\x68\x70\xef\xbc\x3f\x38\x6b\x3c\x2d\x5b\xf6\x9c\x82\x37\x68\x79\x9e\xaf\xf3\x87\x49\xe6\xd0\x7c\x10\x77\x91\x71\x6b\x79\x9e\x7a\x36\x99\xb0\xf9\x5c\x58\xd9\xd8\x4c\x49\xcd\x65\xee\xf5\x90\xbc\x47\x2f\x25\x25\x24\x37\x05\xe7\xb9\x5e\x51\x6a\xd4\xb3\x36\x17\x09\xeb\x10\x49\xc1\x13\xa0\xf8\xb2\xb0\x91\x28\xc5\x62\xb2\x4d\x6b\x97\x27\xc4\x64\x56\x4c\x99\x8b\xf9\x74\x17\x74\xe1\xfe\x30\x9c\x0f\x08\xbf\x7b\x89\x91\x3e\x09\x0e\x7f\x7d\xe6\x6b\x1f\x37\xfe\x36\x43\x37\xe2\xf4\x3a\x98\x09\xbb\xa1\x2d\xe8\x45\xf4\x32\xda\x03\x07\xef\x7f\x62\xf7\x1b\xbb\xe2\x7b\x5e\x67\x76\xc3\x75\x70\xcb\xcc\xaf\xc6\x35\xc6\xab\x6b\x51\xf3\x0f\xe8\x9f\xe8\xcf\x70\xda\x81\x3b\xb6\x6f\xbe\x6b\xed\x5d\xeb\x54\xbd\xda\x7a\x86\xdb\xca\xd5\x83\x02\xb0\x10\xc4\xf3\xf1\x4c\xad\x06\xd5\x87\x65\x34\x24\x13\x99\xce\x7c\x3c\xd3\x4c\x43\xca\x9d\xa5\x1a\x9a\x22\x45\x4f\x84\x78\xc2\xc2\x3a\x61\x64\x3d\x99\x84\x68\xc9\x11\x15\x9d\x90\x6a\xee\xe9\xc9\x89\x51\x5b\x04\x90\x60\x6f\x23\x06\x86\x78\xae\xaa\x1b\x40\xd3\xaf\xf9\xa2\xdd\xa7\x4d\x8f\x78\xdc\xdd\x2e\x27\xe7\xcf\x07\xb5\xb0\x6b\xcb\x1d\x27\x6e\x9e\x30\x3c\x7e\x15\x3a\x0d\xc1\xa4\x85\x13\xc7\x85\x17\x07\x17\x3d\xf7\xeb\x4f\xd0\x99\x1f\xd0\x45\xf4\x47\xc6\x0f\x45\x58\x59\xd8\xed\xfb\x92\x32\xb4\x05\xbd\x31\x6e\x44\xd5\xc8\xd2\xdc\xaf\x46\x1d\xdc\xf5\xfa\x9f\x61\x00\x40\x7c\x06\x79\x3f\xdf\x04\x7c\x78\x7e\x1e\x2d\xa7\x9d\xd2\x8a\x3a\x4a\xaf\x3a\xb5\x72\x85\x24\xb3\x21\x9b\x26\xe7\x71\x21\xc5\xed\x4a\xca\x42\x48\x6d\xab\xa5\x98\xbc\x14\x40\xe0\x4b\x25\xe7\x11\xe8\x90\x1b\xa3\x7d\xb5\x6c\x58\x3e\x90\xc2\x7b\x19\x1e\x51\x6a\x34\x01\x6b\xae\x26\x13\xd5\x14\x3e\x22\x06\xfd\x34\x5a\x1d\xdb\x85\x44\x6c\xf8\xbb\xc3\xbc\x97\x9f\x5f\x0d\x23\xab\xf7\xbe\xec\x10\xfe\xee\xec\x3b\x70\x31\x3a\xbc\x78\x60\x5f\xd7\xb7\x7a\x3b\x1b\xd8\xf8\x24\x9c\x80\x76\x6d\xdf\x54\x32\xc1\x1c\xea\xd6\xa3\x7b\xf3\x0e\xb6\xb6\x7b\x8f\xd2\x88\xa8\xea\x2b\x23\x00\xdc\x04\x52\xab\xf7\x3a\x35\xb7\x4d\x9b\x92\x55\x47\x72\x0a\xf9\xa0\x4a\x59\xa8\xf5\x0b\x55\xc2\x85\x54\x45\xb5\xe1\x89\xc5\x4d\x66\xad\x5c\x10\xb1\x28\xed\x80\x98\x5f\x40\xb1\x9a\xd5\xf3\xd9\x36\x03\xd5\x9c\x2d\xa0\xa3\x36\xee\xd9\x36\x0b\x86\xe0\x2c\xb4\x19\xfd\x6e\xd2\x3c\xeb\x87\x7a\x1b\x3b\xec\x8e\x87\x60\x13\x1a\x71\xaa\xb9\x81\x5d\x36\xb1\xa8\xc4\x36\x90\xd8\x4d\xad\x67\x08\xaf\xe7\x03\x73\x28\xbe\xf9\x7f\xd8\x7b\x13\x38\xa9\xaa\x6b\x5f\x78\xef\x33\xd6\x5c\x75\xce\xa9\xa1\xab\xe7\xea\xa9\x68\x0a\xba\xe8\x2a\xba\x9b\x62\x16\x51\x90\xa1\x45\xc4\x16\x10\x5b\x64\x74\x60\x90\xa0\x22\x22\x21\x48\x94\x10\xa2\x06\xa7\xa0\x51\x2f\x22\x12\x43\x50\xcf\xa9\x2e\x5b\xa2\xc6\x31\x8e\x5c\x24\x5c\x23\x3c\xae\x21\xc6\x28\xc6\x52\x34\x6a\x8c\x41\xe8\xda\x7c\xbf\xb3\xf6\x39\xa7\xaa\x27\x34\x79\xdf\x77\xdf\x7d\xef\x7b\xbf\xfc\x3a\x56\x57\x37\x5d\x7b\xaf\xbd\xcf\xde\x6b\xfd\xd7\x5a\xff\xbf\x2a\x25\x69\x86\x51\x1f\x63\xb1\x4f\xf3\x09\x59\x0b\xe5\xab\x10\xa8\xe7\x56\x66\xc1\x7b\xc1\x02\xab\xf3\x65\x92\xac\x89\xe1\x54\x4a\x73\x06\x25\x59\xb3\x41\x91\x73\x85\x4f\x92\x3b\x79\xa7\x18\x2c\x2a\x8b\x9c\x0e\xbe\x33\xe3\xc1\xfe\x60\xbb\x51\xe7\xef\x79\xaa\x7f\xc0\xee\x50\xd1\xfe\x37\xba\xe3\x74\xed\x06\xce\x55\x8d\x86\xa0\xc7\x8c\xcc\x6f\xd4\xcc\xfc\x0e\x76\x64\xd5\xe2\xb8\x99\x61\xac\x51\xb2\x6a\x8d\x0f\xb0\x58\x31\x60\xd0\x9a\x84\x14\xc8\x2f\xea\x71\xd5\x89\x0b\x9e\x1f\x4b\xe3\xaa\x88\x4f\xad\x78\x5e\x93\x1d\xdf\xa8\xca\xf3\x6a\xc4\xd7\x51\x19\xa9\x50\x62\xe9\xca\x48\x45\x5e\x00\x0b\x75\xc8\x4a\x45\x25\x8d\xb7\xcc\x57\x10\x6f\x95\xd6\x48\xf2\x13\x0e\xd6\x53\x1c\x1d\x5c\x13\x4a\x69\xa1\x81\x50\xd4\x82\xb4\xa8\xc3\xac\x7d\x1b\x2c\x59\xf5\x58\xf9\xe2\xb7\xba\x68\x75\x39\x53\x81\xcb\x19\xb3\x94\x2c\x8e\x1b\x30\x53\x9b\xf7\x40\x18\xa9\x1d\x7b\x71\x15\x54\xc3\xcd\xbe\x67\x88\xcf\xd3\x78\xf1\x79\xb3\xd7\xae\x88\x85\xc9\x07\xae\xca\xa6\x59\x8f\x3d\x3d\x13\xc7\x06\x6e\x1d\xfd\xbd\xf9\xf3\xaf\xfa\xd1\xf5\x78\x22\x7e\x10\xff\xd8\xac\x8f\x1b\x5c\x75\xc9\x39\xf5\x36\x9b\x73\x44\x5b\xd3\x99\x89\xa2\x60\xc0\xc3\x8b\x9e\xad\x38\x79\x7c\x60\xcb\xfd\x5a\xfa\x3e\xf2\x15\xf9\x0b\x3d\x7b\x0c\x7e\xc1\x51\x7d\xb0\x0b\x9a\x88\x9b\x93\xc2\x6c\x79\xe6\x40\xbb\x94\x46\x82\xaf\x80\x3c\xb6\x6f\xbe\xc0\x3e\x69\x02\xfb\xe2\x07\x84\x3c\xd2\x5a\xe2\xc7\xef\x0a\x7e\xe8\xd5\x1a\x4f\xb9\xa0\x41\x4a\xda\x01\x04\xc0\x3e\x2e\x0b\x71\x35\x7f\x50\xf5\x24\x74\xcf\x55\x8f\x9e\xa0\xf2\x90\x97\x64\xcd\x17\xd0\x77\xa3\x21\x2d\xad\x0a\x74\x17\x8a\x56\x8c\xa4\xfb\x75\x16\x79\xe1\x86\xb3\xcf\x99\x3a\x01\x37\xbe\xf9\x9b\x6b\x66\xe0\x20\xf0\xfb\xbd\xaf\xb4\xcd\xe0\x76\x9d\xac\x4f\xbf\x10\x16\xa7\x1b\xa4\x7e\x85\x5c\x22\x32\x2a\xea\xcd\x25\x12\x62\xb3\x19\xc5\x05\x5c\x22\x8a\x01\x43\x18\xc4\x03\xdd\xab\xd8\x43\x14\x97\x28\x20\x28\xee\xa7\x8a\x9d\x2e\x7b\x0b\x8e\xe8\x87\x71\x6f\x06\x82\x33\xfd\x4f\xee\x7a\xe8\x37\x4a\xae\x94\xf9\x53\xf8\xc9\xfb\xc9\x6f\x7b\x12\x11\x9c\xcc\xbc\xfe\xfc\x6f\x30\xf3\xcb\x0e\xe3\x4e\x61\x3f\xe7\x56\xa2\x30\x9a\x67\xe4\x98\x25\xd1\x58\x57\x9b\x98\xcd\x38\x3d\x21\x7d\xdc\x4e\x3e\x6b\xc9\x44\x80\xd0\x28\xe4\x33\xdc\x48\x92\x9f\x60\x6d\x4e\x8f\x14\x82\x4c\xb2\x64\x54\xba\x78\x24\xd5\x0f\x05\xd4\x08\x3a\x53\x7a\x91\x45\xc2\xc5\x11\x09\x44\xe8\x34\x02\x02\xdc\x1d\x1e\x1c\xd9\xf3\xe8\xcc\x5d\x57\x5e\xbe\xd2\x8b\x1f\x26\x17\x79\x96\x2d\x3e\xf7\xdf\x16\xdd\x9a\x21\x1f\x93\xa3\x4c\x3d\x1e\x88\x2b\x27\x1d\x3e\xe3\xfa\xb5\x7b\x37\xac\xad\x19\xf4\xf1\x39\xb8\x5a\x1f\xfb\xa4\x53\xc7\xd8\x67\x80\x23\xb2\x9d\xd6\xcc\x6a\xac\x98\x85\x42\x32\xcd\x21\x66\x33\xa2\x10\xf4\xb9\x63\x9a\xc8\x53\x3a\x4e\xfe\xa0\x6a\x4b\x68\x4a\x30\x9b\xe6\x15\x68\x90\x16\xec\x31\x5a\x1e\xcb\x06\x41\x59\x43\xdf\x0d\x18\xf2\x2c\x8a\x1e\x5e\xaa\x2e\xc8\x2f\xea\xde\x4b\x4b\x53\x30\x99\x50\x22\x4d\x91\x3a\x83\xe7\xdb\xa0\x88\x9c\xf4\xd8\x3d\x47\x14\x32\x1b\xef\xf4\xbe\xb6\xea\x96\xb6\xc9\xbf\x69\xc7\x02\x46\xe4\x0b\xf2\xf7\xff\x68\xfc\x6c\x1a\x46\x7b\xff\x31\xe6\x40\xf5\x60\xf2\x01\xf9\x80\xfc\x81\xbc\x4d\xfd\x42\x93\xa3\xc1\x85\x02\x26\xff\x13\x25\x7f\x72\xba\x21\x6c\x71\x3a\xb3\x19\x36\x40\xe9\x6e\x9c\x79\x96\x8a\x40\x56\x63\xdc\x89\x84\x79\x9b\x8b\xe6\x73\x16\x70\x03\x7c\x43\x01\x54\xe8\xbb\xea\x41\xd7\xd0\x9c\x26\xd8\x45\xde\x27\x27\xee\x59\xb0\xe5\xd6\x75\x3f\xba\x81\xef\x3c\xfa\xd9\x7b\x47\x8f\x93\x77\x98\x8a\xcb\xaf\xbf\xf2\x32\xb3\x77\x8c\xcb\xc0\xfd\x14\x41\x8b\x0c\xc6\x86\xb0\xc3\xe8\xe0\x29\xa7\x4d\x64\x38\x6e\x5e\xbc\x01\x6f\x56\x63\x82\x89\x84\x99\xd5\x72\x19\xd1\x7a\x00\x49\x32\x28\xfd\x41\xa1\x85\xd5\x4b\xee\x95\x64\x4d\x32\x18\xd4\x5d\xd0\xab\xc3\x1b\xc8\x84\x17\x43\xb7\x88\x2c\xd1\xea\xde\x0a\x1c\x86\x9a\x53\xda\x39\x22\x6e\xc3\x8d\xa2\xe8\x49\x6c\xbf\xfc\x95\x3f\xbd\xfb\xea\xdb\x97\x79\x44\xf1\xca\xab\xf7\x2d\x5c\xb2\xe2\x32\x86\xf8\x6d\x88\xac\xbe\x6e\xe2\x79\x17\x90\xbd\xe4\x6f\xe4\xaf\xe4\xdf\x37\x8d\x6e\x27\x23\xb8\x8a\xcc\x7d\x78\xfa\xc3\x0f\x6f\xde\x06\x39\x82\x53\xc7\x20\x47\x10\x44\x67\x99\x78\xad\xc9\x55\xe4\x60\xb3\x1d\xa2\x9f\xb3\x59\x7d\x9d\xee\x20\xc0\x6e\x79\x3c\x56\x94\xd2\xc8\xad\x07\xb7\x14\x1e\x2b\x04\xd9\xf5\x83\x8b\x09\xf8\x22\x7a\x84\x54\x5d\x89\x56\xed\xc4\x2d\x07\xde\x3e\xb4\x60\xfa\xce\x69\x8f\x3f\x8f\x97\xdf\xfb\x4e\xe6\x8f\xe4\x05\xf2\x18\x73\xf8\x03\x7c\xe1\x93\x8b\xbb\xa2\xc3\xc9\x37\x9f\x90\xd0\x54\xd2\x35\x19\x6f\x30\x31\x74\xe0\x9a\x51\xd0\x25\xbd\x78\x8e\x4c\x62\x0e\x45\xca\x6a\xbe\xa2\xac\xc1\x78\x6d\x96\x78\x3a\xa5\xac\x7e\xca\xe9\x21\xac\xe2\x33\xa9\xb9\x3b\x18\xde\xed\xa1\x5d\xb2\xaa\xcb\x22\x66\xf1\xa6\xba\x73\xc8\x14\x50\xc8\xac\xc7\x6b\x05\x7c\x3b\xbe\x89\xbc\xeb\xb5\x93\x35\xa4\x8b\xdc\x69\x57\xf8\xce\xdc\x78\xe6\x99\x13\x93\x98\xcc\x4a\xbc\x24\x37\x8b\xd9\x45\x7e\x74\x6d\x6e\xa6\xd5\x2b\xc4\x7f\xc5\xb5\x23\x97\x6e\x47\xd1\x8a\xb5\x39\xda\x4e\x61\xd0\xf2\xc8\xe0\x66\x8a\x94\x13\x07\xd0\x4c\x20\x5c\x66\x38\xa8\x27\x12\x25\xb9\x83\xb5\xd9\x9d\xd4\xcf\x82\xce\x74\x29\x22\xe1\x6a\x2c\x6d\xc3\x3b\xb0\x0d\xdb\xf0\x36\xf2\x3e\x39\xf2\x36\x39\x42\xfc\xc2\x24\x32\x05\x67\x4e\x6e\x67\x97\x92\x22\xfc\xd1\x89\x5f\x50\xce\x34\xa3\xd6\x3c\x84\x6a\xd0\xf7\xa9\x07\xa5\x95\x38\xb2\x69\x1e\x1b\x0d\x76\x81\xb8\xbe\x92\x72\x52\x43\x7c\x56\xf5\x25\xb0\x5a\x1b\x57\x03\x07\x55\x9c\xd0\xfc\x5e\xdd\x94\x89\x44\xda\x0f\xd9\x58\xbf\x6c\x8f\xa5\x03\x50\x10\x1d\x08\xd9\x41\x72\xa3\xdc\x48\x3e\xd7\xe1\x98\xe6\x37\xc0\xc4\x72\x29\xed\xf2\xf0\x00\x08\x94\x18\x25\x99\x11\x9a\x7f\x0f\x24\xbb\x97\xa4\x87\x40\x8f\xb0\xa9\xfa\x34\x75\xe9\x78\x0e\xd9\x41\xf6\xad\xc6\xbb\xad\x02\x75\x95\x79\xaf\x5b\x7d\x7a\xf6\xd5\x6b\xae\x61\x1e\xeb\x5e\x9f\x3e\xf1\xd4\x31\x6e\x3b\xbf\x17\x15\xe9\x76\xb7\x99\xfb\x97\x31\xb8\xa9\x3a\x8a\x6c\x8c\xbe\x7f\xc3\x94\x65\x38\x08\x37\x47\x9e\xdf\xb6\xc8\x04\x34\x34\x26\x20\xf5\xc3\x6b\x2b\x37\x0d\x05\x25\x88\x89\x6f\x1c\xc7\x29\x7c\x09\x79\x80\x3c\xb5\x7c\xcf\xdc\x1f\xde\x33\xf5\xd9\x57\x5f\x4d\x5f\x78\xff\x39\xfc\x82\xc5\xe4\x6a\xb2\x83\xdc\x43\xae\xaa\x1e\x80\xb9\x86\x0a\xcc\x1e\xfb\x18\x33\xc3\xa3\xc8\xe4\xd7\x31\x9e\xaf\x2a\x8b\x6f\xb8\xf0\x09\xcb\x54\x16\xfb\x39\x77\x2c\x53\x09\xe4\xa4\xe6\xf3\x56\x6d\x3e\x6f\xaa\x9b\xa6\x46\xca\x7c\x34\x2c\x29\xd3\x9d\x71\x87\xd7\xcf\xc1\x45\x52\xe9\x05\xef\x41\x13\xfd\xba\x77\xeb\xfe\x0e\xcf\x61\x61\xed\x64\x7f\xcf\x64\xa3\x49\x8d\xdb\xe7\xd3\x89\x17\xe4\x69\x72\x11\x53\x60\xff\x9a\x3c\xff\x70\xc1\x0a\x64\xaa\x4a\x6d\x8c\x3b\x96\xa9\xa2\xf3\x33\xd6\xa3\x36\xae\x86\x0f\x6a\x15\x3e\x68\x22\x06\x22\xe2\x20\xdd\x59\x15\x61\x49\xee\x60\x6c\x01\x2f\x2d\xb9\xa2\x39\x7c\xad\xc8\x26\xc9\x1a\x2f\x7f\xa7\x75\x2a\xac\x96\xec\x6f\xcd\x16\x9b\x33\xec\x77\xf1\xc8\x95\xd6\x2c\xe9\x5d\xc4\x88\x2b\x81\xbb\xf7\xbc\x6f\x63\x92\x0b\x7c\x1b\x93\x9c\x1e\x02\xd8\xf5\xe3\xc7\xe5\x06\x92\xe2\x42\x4e\x39\x4b\x01\xb7\x80\x5c\xae\xeb\xb7\x86\x18\x6e\x9e\x65\x4e\x6c\x37\x64\x71\x59\x63\x6c\x26\x27\xc8\x0d\xa7\x1f\x9d\x3e\xb8\x48\x52\x5f\x1f\x93\x26\xe4\xb4\x43\x55\xed\x46\xfb\xad\x41\xdd\x25\x4b\x59\xd5\x4e\xbb\x53\x4c\x02\x11\xbb\x7e\x7e\x79\x03\xbd\x27\xd2\x4f\xad\x4d\xc1\xbc\x72\x42\x5f\x25\x36\xe6\x14\x2d\xf6\x10\xab\xae\x06\xa3\xfa\x53\x9f\x09\x1c\xdf\x89\xca\xd1\x32\xa3\x2a\xca\x0d\x05\xc9\xce\x6c\x21\x81\x51\x86\x2f\x71\x5b\xc0\xa6\x55\x23\xa5\x4f\xb1\xb4\x0c\xb8\x5f\x58\x7b\x2c\x5d\x06\xdc\x2f\x65\x05\xdc\x2f\x0e\xa3\x8e\x2a\x58\xaa\x07\x18\x70\x27\xf3\xee\x82\x0a\xcf\x88\x14\x49\x04\xcb\x30\x78\xbe\x12\xc0\xe6\xa3\xf0\xd0\xba\x6a\x4a\x81\x34\x9b\x4c\xc2\x73\x3e\xf8\xc7\xbe\x37\xae\xbe\x70\xfe\x39\xcd\x89\xf0\xf9\x97\x10\x95\xec\xa5\x9c\x48\xe4\xf3\x37\x7f\xb3\xfe\xc0\xe1\x3a\x8c\x62\x15\xe3\x5b\xd6\xcd\x9a\x90\x6b\x07\x92\x24\xba\xaf\x66\x88\x2b\x81\x3f\xb1\xb9\x17\x1b\xa3\xb7\x2f\x36\x46\x1f\xa6\x22\xc7\x9a\x20\x9a\x36\x97\x22\x92\x25\x76\x0c\x04\x8d\x65\x86\xe2\x31\x25\x6a\x14\x62\x85\xba\xc7\xe0\x83\x57\xf3\x7b\x51\x29\x9a\x63\xe0\xf3\x7e\xf3\x34\x72\xb2\xd9\x8c\x47\x2a\xe6\x0c\x16\x63\x5b\x31\x1c\x45\x14\xa5\x97\x42\x59\xd5\x93\x48\x4b\x30\x12\xc9\x67\x8f\xe9\xf7\x01\xd2\x24\xdd\x11\x08\xa6\x34\x5b\x31\x3c\x96\x1a\xe7\x34\xdc\x2c\x7a\xfc\x04\x43\x62\xb4\xd0\x89\xa5\x41\x0c\x5a\x95\xc6\x53\xff\x7c\xe3\x91\x25\xcb\x2f\xbc\xf5\xa6\x5d\x07\x5d\xcc\xea\xdc\x4d\xee\xd7\x9f\xf9\xd5\xdf\xae\xd8\x77\x3d\x79\x84\xdc\xc9\x1c\x7e\x1f\x5f\xb8\xa7\x65\x48\x57\xed\xc8\xe7\x76\x91\xf4\x8b\x53\x49\xd7\x80\x6a\x70\x0b\x10\x46\xed\xa7\x8e\x71\x21\x7e\x2f\x8a\xa2\x15\x28\x5d\x87\xa8\xb1\x28\x7f\x6c\x98\xcd\x76\x04\xeb\x80\x3f\x76\x40\x5c\xf5\x1e\xd4\x4a\xbd\x00\x7d\xe8\xf7\x6d\x35\xb4\xf1\x43\x11\x7e\xa9\x51\x18\x24\x4a\x4f\x70\x4e\x39\x5c\x59\xa7\xbb\x05\xd5\xb2\x16\x84\xac\x10\x57\x47\x7d\xdc\xa0\xd4\x81\xbd\xa5\xd5\x7a\xec\x29\x87\xc1\x5d\x1f\xd2\xd8\x62\x22\xd9\x0d\x38\xda\xc0\x50\x2c\xd8\xca\xa4\x18\x0d\x4c\x5c\x75\x55\xfb\x9d\xfb\x2e\x58\xb4\x74\xc8\xc5\xb7\xdd\x7c\xf3\x34\x2c\x7e\xf4\xbd\xfd\x2b\x16\x5c\x73\xcf\xa4\x99\xed\x75\xe7\xff\x7c\xdf\x56\xf2\x3e\xf9\x78\x3c\xae\x1c\xd7\xdc\x3a\x35\x76\xe6\xe8\xf1\x63\xae\xbe\x77\xf1\x8b\x7f\x6c\x6e\xfc\x62\x48\xdd\xf4\x71\xf5\xa3\x52\x93\xe6\xbd\x7c\xdb\x2b\x1f\xfc\x97\xf1\x16\xfe\x9f\xc8\x29\x84\x4f\x5d\x46\xa6\xe3\xcf\xf8\x4e\xe4\x46\x83\x11\x50\x82\x41\xd4\x6b\xb0\xc5\xf2\x05\x6d\xa3\xfd\x85\xb7\xe0\xb3\x6c\x9d\x36\x6e\xd1\x4c\xdc\xfc\xf1\xd1\xcb\x5b\xef\xf6\xaf\xdb\xc8\xcf\x3e\xf1\xc8\x29\x44\xbe\xa2\x1a\x2d\xc8\x77\xea\x98\xb8\x9d\xef\x44\xc5\xa8\x1a\xa9\x94\x47\x42\x45\x49\xad\xc4\x95\x55\x71\x22\x1d\x46\x94\xeb\x33\x6d\x63\xe8\x13\x96\x71\x54\x87\x6d\xee\x98\xe6\x70\x51\x78\x55\xa6\x99\x23\x3b\x64\x5b\x2a\x74\xab\x05\xc0\x7a\x6a\x73\xf1\x53\x63\x7e\x72\xfc\x72\xa0\x46\xb4\x35\x78\x54\xe1\x79\x5e\xf3\xbb\xbf\xf1\xa8\xc1\xe7\x55\xc1\xd7\x21\x0a\x36\x25\xa6\x06\x7d\x1d\x81\xa0\x5f\x89\xa5\x45\xc1\x96\xc7\x52\xd2\x81\xa0\x5f\x92\x53\x28\x1d\x10\xc4\x86\x86\x06\x9c\xb1\xf9\xe9\x2b\x43\x3e\x5c\xab\x2e\x01\x1f\xcd\x88\xd3\x9a\x8b\xb1\x12\x91\x92\x40\x5d\x57\x8f\xa5\x88\xe8\xc0\x42\x75\x95\x15\x12\xf9\x86\x27\x9b\x46\xb7\x5c\x54\xc9\xce\x5c\x89\x3d\x38\x4a\xfe\x93\xfc\x89\x5c\x4e\x8e\xf8\x46\x5f\x92\xfe\xb7\x19\xdc\xae\xf6\x5b\x36\x6c\x78\x68\x22\x43\xfc\x97\x62\x91\xb9\x10\x3b\x73\xfb\x3f\xfa\xfd\x07\x47\xb9\xcc\xcd\x04\x93\x85\x8f\x60\x79\xe1\xa2\xf9\x17\x19\x67\x9c\xf8\x08\xdf\x89\x64\x54\x82\x16\xd2\xee\x36\xdd\x4e\x8a\x2b\x9b\x67\x2d\x95\x3c\x06\x6b\xa9\x2a\x82\x74\x6a\x49\x9e\x49\x54\xa6\xe9\x35\x19\xb8\xf7\xf4\x9d\xad\x50\x00\x53\xa1\x6e\x91\x93\x96\x57\x21\x4d\x52\x24\x59\x73\x86\xcc\x36\x6e\xfd\x7f\xf9\x99\x49\xb5\x05\x71\x1e\x3e\x82\x9b\x0a\x67\x54\xcd\xca\xed\xb7\xfc\x70\xe3\xb6\x89\x94\xf8\x94\xce\x83\x59\x95\xdb\x44\x16\x2e\x5a\x38\xcb\xe4\xcb\x83\x7b\x47\x41\x6d\xb4\x8e\x4a\x75\x24\xbb\xdf\x38\x3e\xd9\xba\x71\xfc\xb0\xb8\x12\xbd\x71\x24\xe8\x31\x95\xf4\x1b\x47\x96\xac\x32\x47\xc9\xaa\x6e\x03\x26\xc1\x82\xfb\xc5\x20\x04\xc8\x5f\x2a\xeb\x7f\xf7\x21\xd9\x7b\xf6\x34\x72\x67\xfe\x36\x39\xf0\x54\xee\x2f\x0c\x63\x5d\x23\xd4\xc6\xfc\x5c\x71\x25\xf0\x19\x0e\xe9\x11\x2d\x71\xc9\x42\x1a\x43\x26\x41\xb9\x0b\xb1\xd9\x83\x63\x10\x45\x52\x16\x2c\xc5\xba\x46\x70\x33\xe3\xc2\x93\x72\x9f\x30\x8d\x64\x5b\xee\xb3\x36\xeb\x42\xc9\x8d\x64\x7e\x9b\x1b\x97\xb3\x31\x47\x73\x25\x85\x17\x0b\x1d\xc3\x11\x71\x25\xf2\xa2\x22\x34\xb3\x0f\x16\xcd\x70\x5c\xc5\x07\x35\x96\x76\xcb\x38\x30\x90\x77\x01\x8c\xc3\x62\x49\x4e\x0b\x3e\xa0\x1a\x77\x48\x19\xd1\x2b\xfb\x83\xfa\x89\x6c\x97\x0d\xf1\xad\xde\x1d\xfa\x56\xb0\xc6\x5a\xee\x12\x0e\x71\x0e\x81\x79\x08\xaf\x24\xc7\x64\x5b\x6e\xf6\x2d\x96\xcb\x94\x1b\xfd\x9b\x43\x5c\xdb\x89\x49\xcc\xb3\xb7\xe0\xc0\xc9\x6d\x96\xe7\xa4\x8f\xd9\x7f\xea\x18\xdf\x2a\x6e\x41\x7e\x54\xa5\xaf\x2c\xc4\x4b\x12\x9b\xa5\xec\x63\x42\x52\xad\x8c\x6b\x61\x4f\x36\x1d\xae\xd4\x57\x2e\x5c\x6a\x8f\x41\x26\xaa\x5a\x8f\x99\xb4\xa0\x44\x1d\xf2\x60\x40\x92\x3b\x5c\x52\x15\xa6\xc8\x8e\x95\x16\xd5\x18\x08\x2e\x95\x08\x4e\x36\xb7\x28\x11\xec\x61\x0c\xbf\xa1\xb9\x05\x1b\x80\x4e\x04\x2a\x0a\xfc\x78\x22\xbe\xdc\xe1\x6d\x3a\x89\xc7\x92\x11\x17\xdc\xb9\xf7\x8e\xef\x2f\x99\xbd\xfe\xbc\x45\x35\x64\x1f\x96\xc4\x59\x2b\x17\xce\x77\x62\xbf\xf2\xd5\x87\x9f\xbe\xcf\x77\x76\x1d\x18\xb6\x86\xb9\xe1\xe4\xd7\x2f\xfe\xea\xfc\x72\xec\xa8\x99\x34\x8f\xff\xfb\xe2\xf3\x2f\xba\xe4\xe9\x5f\xed\x30\x73\xd7\x6d\xc0\x95\xe9\x44\x13\x69\xa5\xa5\x2a\xc2\xf9\x9d\x76\x82\xae\xa0\xd3\x61\x8f\xe5\x43\x68\x5a\xf8\xc5\x06\xf2\x0b\xa2\x80\x77\xc7\x19\xb0\x49\xdf\x24\xc1\xc5\xb8\x89\xcc\x20\x6f\xf3\x9d\x27\xa7\x70\x99\x13\x93\x48\x1b\xde\x85\xfe\x9b\xf1\x75\x53\xbf\xea\x59\xb0\x03\xf8\xeb\xd0\x03\xec\x72\x65\x2d\xdf\x2a\xc3\xfb\x9d\x3d\xfc\x75\x17\x7d\x5e\x5d\xe0\xdf\xb8\x58\x3b\xa8\xa1\xf9\x8c\x90\x17\x54\x07\xfc\x2e\x89\x0a\xd9\x25\xad\xd3\xc5\x17\x89\x5a\x07\x8b\xee\x78\x5d\x8f\xcb\xf1\xb0\xdc\x8e\xab\x2f\xbb\xff\xf6\x3b\x33\xe7\xea\xee\x17\xd9\xff\xd1\xef\x49\x0b\x3d\x49\xfe\x2f\x8f\x78\x7f\x3c\xe2\x0e\xd2\xc6\x7f\x05\xf7\xb5\x82\x2e\x36\xd6\xcb\xc3\x66\x35\x24\x24\x12\x69\x27\x08\x00\x38\xdd\xf6\x98\x6a\x4b\x50\x47\x55\x32\xce\x59\xf7\x41\xcd\xa5\x00\xa4\xa2\x6f\x20\x21\x90\xed\xb0\x0b\x5e\x1b\xad\x5c\x08\xe8\xc6\x72\x53\xde\x54\xaf\xa4\x71\x1e\x2a\x08\x93\xa4\x97\x1e\xdd\xd1\xfa\x39\x22\x30\x8e\x15\x5b\x1e\xa9\x67\x67\xbc\x44\xde\xee\x5a\x42\xde\xc6\x4f\x32\x23\xc8\xa1\xca\xbb\x30\x83\xab\x98\x33\xf1\xb9\x27\xa7\xe4\x66\xe0\x5d\xa4\x8d\xd9\xcd\xa6\x8f\x92\xff\xb5\xbc\xe2\x08\x21\x71\x33\xdf\x89\x24\x34\xdc\xf8\x5c\xa7\x27\x49\x59\x40\x35\xde\x96\x4c\x82\x9c\x83\xf7\xa0\x7e\x4d\x7a\x64\xfd\x9a\xd4\x14\x93\x14\xb4\x83\x13\xdd\x3e\x00\x96\x1a\x4d\x72\x55\x8b\x65\x95\xb1\x91\x00\x1e\x83\x0f\xe3\x08\x3e\x8c\xc7\x12\x3f\x63\x23\x19\x12\x22\xef\x92\x10\x73\x9c\x79\x16\x8e\xfc\x82\x63\x5f\xff\x32\xfc\xf0\x43\xfc\x5e\x54\x87\xae\xa0\xca\x12\x5a\xd0\x6e\xe0\xf8\x35\x8e\x6c\xa6\xac\xd4\x07\x2a\x4a\x76\x5a\x1a\x59\x74\x10\x5a\x21\x23\x40\x9f\xa1\x64\xd3\x11\xe8\x5c\x8f\x94\x52\x06\x23\xa4\x05\x7d\x14\x50\x2c\x95\x34\xb7\x92\x4a\xa9\x65\xb2\x66\x77\xd0\x9a\x7e\xa1\x8e\x26\x45\x68\xd0\xdf\x9d\x33\x2b\x52\x09\xb1\x7f\x65\x77\xc6\x2c\xb1\x7d\x2d\x2e\xfa\xd5\x5f\x71\xd9\x6b\xbf\x7a\xfd\x10\xf9\x35\x79\x97\x3c\xfb\x52\x7b\x6e\x19\x5e\xf1\xe9\x47\x9b\xd6\x7c\xf4\xfb\x9b\x6e\x7a\xf3\x79\x3e\x76\xfe\xd4\xd7\x1e\xba\x65\x4f\x58\xf0\x77\xde\xfe\xc6\xc7\xe7\x62\x6e\x70\xf2\xd0\xa5\x97\x7d\x39\x73\xd1\xe4\x59\xab\x2c\xde\xe1\x23\xf0\xac\x4e\xeb\x9b\x13\xba\xf7\x6d\x26\x19\xb7\x99\x2a\x40\xd5\x95\xe8\x4d\x7d\xb7\x5b\xac\xe7\xe5\xd5\xeb\xd2\xca\xdf\xaf\x5b\x90\x17\x95\xa1\x35\xbd\x46\xa4\x96\xc4\x35\xbf\x27\x9b\xf6\x97\x00\x7a\x17\xb2\xc7\x00\xde\x2b\x37\x87\xd9\xe1\x63\xb1\x0d\xfa\xa7\x0b\x07\x5c\x01\xc7\xaf\x1e\x4c\x96\xa5\x8c\x66\x6a\xd5\x21\xa7\xc5\x50\x09\xd5\xfd\x48\xbb\x3d\xb4\xce\xfe\x74\x57\x70\xb7\xcb\xac\xe7\x54\x5e\xef\x75\x87\xf5\xbc\x8f\xb7\x58\x37\x18\xb5\xf9\x5c\xe0\x65\xee\xcb\x8b\x71\x16\x7a\x31\xae\xfe\xbd\x98\x1e\xce\x4b\x77\xa7\x05\xd6\xd6\x77\xea\x18\xdc\x93\x0a\xfa\xa9\x71\x4f\xa2\x24\xa5\xc1\xb1\x5c\x76\xb7\x71\xc4\x38\x0f\x9a\x6e\x5a\x9f\x9e\xb9\x5b\xf7\xcc\xbd\x05\x9e\xb9\xd7\xd7\xe1\xf1\xba\x7b\x79\xe6\x1e\xaf\x1b\x3c\x73\x8f\xe9\x99\xbb\x3d\xdd\x3c\x73\x37\x6b\x08\xed\x14\x78\xe6\x11\xd3\x25\xb7\x3c\xf1\x9f\x93\xbd\xe4\x5e\xdf\xe8\x4b\x3a\x1e\x98\x91\x77\xbc\x4f\x4c\x32\x9d\xee\x6e\xb8\xf9\xff\x89\x1c\xed\xff\x75\xba\x07\xff\x97\x17\xfd\x7f\x25\x2f\xfa\x7f\xd7\x9c\xd4\x7f\x05\x6f\x3a\xc4\x24\xf0\xfc\x0e\xee\x1d\x91\xe8\x0f\x2f\xf5\x46\xbf\x53\xa0\xd1\x5f\x68\xd1\x47\x24\x81\xfe\x2f\xa7\xfa\xff\x77\x9c\xea\x7b\x48\x9b\x10\x82\xcf\x69\x35\xce\x64\xfd\x9e\x41\x10\x94\xa1\xfe\x83\x32\x23\x12\xeb\x70\x88\x9c\x0d\xc2\x33\x3a\x1e\xd6\x24\x49\x2c\x80\x3a\xf2\xd1\xd9\x7f\x9a\xc1\xd9\xc9\xb1\xb9\xb9\x10\x9c\x01\xa7\x3b\xd4\x34\x2b\x68\x92\xc1\xa3\x06\x1f\xe8\x48\x66\x24\x01\xa0\x72\x89\xcd\xaa\x76\xdd\x37\xf3\xd8\xad\xa7\xdb\x18\x84\x9b\x12\xe6\xb8\xe8\xd3\x4d\x2f\x2a\x29\x85\x0a\x6a\xe6\x5b\x60\x08\x70\xfd\x2f\xc5\x4d\xf3\xae\x99\xfe\xd0\x2a\xdc\x4c\xde\xb8\x77\xdf\xc5\x07\xde\x67\x67\x33\x73\x72\x5d\x57\x5c\x19\xa9\x67\x6e\x3b\x31\x89\x69\x1a\x5a\xf7\x3a\x3d\xbb\xc4\xbf\x14\x9e\xe5\x06\xf6\x43\x1f\x27\xde\x9e\xec\xc7\x12\xfa\x59\x66\x33\x50\x9f\x3e\xcf\x72\xfc\x0a\x1e\x86\x5f\xc1\x4d\x86\x05\x20\x44\xa5\xf6\xb7\xbd\x00\xbe\x5c\x7b\xf7\xcf\x33\x96\xc0\x63\x2c\x81\xf1\xd1\xbe\xd3\x7f\x74\x87\xc7\x69\xb3\xc5\x34\xb7\x92\xa5\xea\x0c\xac\x29\xfe\xd1\x7d\x38\xc9\xee\x43\xca\xaf\x4b\xe1\xda\xd0\xb8\xf9\x1a\xa3\xce\xe1\x3c\xa3\xee\xca\xed\xca\x27\x34\x32\x6c\xc0\x01\x77\x9b\x8b\x5e\x39\x4e\xda\x04\xc0\x24\xd2\x4e\x37\x04\x46\xc8\x1e\x53\xdd\xfd\x55\x3b\x84\x71\x01\x0e\x66\x3d\x43\xcc\x8e\x35\x7a\xa4\x4a\xf6\x93\xb7\x49\x1b\x6e\xd2\xc3\xd5\x8e\x69\xfa\x41\x64\x82\x78\x5d\x93\x0c\xec\x0b\x62\x56\x61\xa3\x71\x27\x84\xd0\xf9\x74\x84\xaa\x3f\xa9\x39\x4d\x04\x2f\x90\xcc\xb0\x4a\x7e\x8c\x45\x3d\xee\x5f\x6f\xde\x80\xfa\xa1\x10\x32\x95\x5e\x15\x67\xbe\x22\xc3\x18\x63\x3e\x9c\xc6\xd4\x78\x0b\x70\x18\x37\x91\x03\xe4\xd0\xec\xf3\xee\xb9\x75\xd3\xee\x33\xd9\x05\xfa\xda\xe6\xf6\x67\xdf\xfa\xe0\x28\x59\xb8\x68\xd1\xcc\xdc\x6a\xfd\xfa\x2a\x8c\xf9\xed\x48\xd6\xef\x2e\xb8\xaf\x1d\xc6\x10\x33\xac\x6c\xb7\xc6\xa7\x14\xb8\x91\xfa\xdd\xe5\x31\x0c\x07\x0c\x5a\xb2\xa3\xc7\xa0\x0a\x43\x7c\xdc\xdc\x33\xc0\xcf\x15\x84\xf7\x46\x2e\xfa\x10\xe4\x42\xe7\x18\x99\x50\x77\x61\x26\x54\xf2\x81\x12\xab\xe4\x2a\x4c\x4b\x7b\x0f\xaa\x72\x42\xe3\x43\xd9\xb4\x17\x6e\x0a\xaf\xcf\x1e\xa3\x49\x6a\x9f\x1b\x92\xd4\x90\xfc\x54\xf9\x6e\xa9\x4f\xc3\x91\x80\x73\xbe\x52\x89\x34\x51\x9a\x4e\x71\xe2\x47\xe8\x14\x3e\x0b\xcf\x27\x77\x90\x47\x3e\x7d\xe9\x6f\xbf\xc2\xeb\xe4\xdc\xcd\xcc\x75\xc2\xf3\xdb\xe6\x3f\x77\x31\xbf\x60\x31\x59\x41\xee\x27\x77\x93\xb5\x93\x31\x37\x15\x5f\x4d\x76\x3d\x37\x2c\x4a\xb1\xbb\x53\xc7\x6c\x61\x7e\x1f\x92\x51\x19\xfa\x9e\x71\xef\x43\x66\x2d\x68\x84\xb5\xd0\xc3\xaf\x95\xe8\xbb\x51\x72\x8b\xa6\xa7\x55\xde\x03\xa1\xf5\x19\x08\x6d\x10\x2a\x32\x8a\x70\x4c\x73\x04\x69\x90\x61\xd6\x61\x14\x49\x9a\x1b\x9a\x34\x59\x49\x92\xd3\x0e\xa5\x28\x65\x3d\x35\x72\xde\x3b\x62\x23\x12\x75\x90\xa0\x4a\x40\x7f\x86\xca\xab\xf0\x39\xb8\x08\x8f\xc4\xad\xe4\x71\xf2\x32\x79\x97\x64\x8a\xc9\x47\x4c\xdb\x23\x0f\xe2\x29\x0f\x3f\xb4\xe3\x97\xba\xeb\x86\x23\x38\x49\xae\x23\x5b\xc9\x56\xb2\x0a\x4f\xc5\xa3\x73\x9b\x98\x23\x5f\x7d\x83\x3f\xfd\xea\xc4\x09\xa8\x85\xfb\x1a\x21\xee\x5e\xc0\x18\x82\xe8\xa2\x7c\xfc\x04\x13\xf3\xbb\xb2\x19\x97\x84\x44\xda\x8a\x0c\x9e\x05\x67\x71\xdc\x38\x68\x5b\x91\x9d\xb6\x9c\x69\x1e\x4e\x92\x35\xec\x4e\x19\x95\x4f\xc6\x4d\x8c\x53\xaa\x9f\x32\x83\x55\x63\xe8\x12\x00\xd8\xb9\x1a\x2b\xe6\xfd\xe5\xc0\xdb\x6e\xf8\x21\x2e\xc3\x4e\xfc\x07\xf2\xc6\xf3\x64\xd7\xfa\x1f\xfc\x70\xcb\x3d\xd7\xfd\x90\xd9\x90\x38\x70\xeb\xeb\x87\x4f\x4c\x62\x1a\x73\xfb\x59\x72\xe9\x55\x78\x73\x1b\xc5\xd3\xda\x4e\x1d\xe3\x46\x70\xd7\xa0\x22\x5a\xc5\x2c\xe9\x6b\x12\x34\x8b\xcd\x5d\x58\xf7\xeb\xc5\x6c\x86\xad\x0c\xba\xf4\xe5\xf0\x58\xa5\xcc\xe1\x40\x56\x0d\x43\xb5\x86\xbe\x16\x5e\x2f\x45\x29\xc3\xfa\x19\x05\x11\x75\xb9\x94\x16\x5d\xc1\x14\x50\xbf\x40\x65\x2c\x14\x75\xc9\x06\x71\x82\xea\x92\x55\x07\xbd\x91\xc7\x60\x28\x2b\x8d\x1a\x32\xea\x46\xff\x53\xad\x1f\x1a\xc6\x45\x0f\x6e\xfb\xe6\xe4\x8b\x8f\xdd\xfc\xc4\xc2\x17\x3e\x79\xef\xf3\xb7\x47\xd8\xa6\x3e\xb4\xe1\xc1\x5f\xe3\xd4\x9d\x57\xac\xbb\xf6\xa6\x1b\x71\x6b\xfa\x97\x76\xa1\x71\xd7\x79\x6f\x2e\xfc\xed\x6b\xb9\xd0\xd6\x4b\x27\xef\x79\x64\xfd\xf5\x0b\xe7\x70\xdc\x4c\x93\xff\x99\x72\xb6\xd4\xa0\xa7\x0b\x18\x5b\x22\x71\x4d\x12\xb3\xaa\x10\x87\x02\x81\x5e\x34\x2d\x7e\xfd\x14\x49\x68\x75\xf9\xc6\x3f\x41\x6c\x78\x1d\x69\xa2\x40\x1b\xfa\xc4\xa5\xcf\x2f\xa7\x85\xa7\x82\x4f\xe5\x9e\x57\x45\x9f\x6a\x7f\x5e\xe5\x7c\x1d\x3c\x27\x28\x31\xd5\xee\xeb\xb0\xd9\x45\x25\x96\xe6\x39\xa1\x20\x34\xb3\xd9\x45\xa8\x43\xe5\x78\x9b\x9d\xd6\xa1\x9a\xaf\xa0\x0e\xb5\xa2\x58\x92\x35\x29\x04\x35\xee\x40\x00\xe3\xa7\xa1\xb2\x9b\xba\xf4\xb5\xa3\x71\x8b\x22\x70\x1e\x46\x34\x18\x7d\xf3\x22\x66\x92\xaf\xba\xca\x83\xe7\xe0\x5a\xdc\xb2\xf4\xc8\xea\x6a\x42\xfe\xfe\xfd\xf3\x06\x89\xde\xa6\xc7\x16\xec\xff\x90\x1c\x39\x85\x4e\x21\xf2\x1e\x6e\xb9\xf1\xba\xc3\xbf\x6d\xbe\x72\x16\xf3\x00\x5e\x8f\x6f\x6b\x52\xc2\x3e\xf2\xf7\xb2\x9a\xd8\xb4\x0d\x4b\xa7\xcf\xcc\x1d\x23\x9f\x93\xb7\xf0\x72\x3c\x70\xef\x21\x1c\xc3\xd5\x89\xf3\x10\x0b\x3c\xb7\x7b\x81\xe7\xb6\xa8\x10\x43\x34\x8a\x8e\xb5\x4a\x21\x9b\x09\x17\x01\x86\x18\xe6\xf3\x18\xa2\x37\xab\x86\xbb\x61\x88\x65\x80\x21\x06\x7a\x61\x88\x45\x06\x86\x18\xee\x85\x21\xd2\x7a\x6f\x03\x43\xac\xed\x4e\x53\x5e\x1d\xd9\xc6\x8c\xfa\xf0\xe8\x8a\x65\xab\x36\x9f\x42\x9f\x91\xaf\x8e\x5f\xba\x70\xd1\xa2\x2f\x8f\x5c\xba\x60\xfb\x29\xc4\xb5\xdf\xf5\xd3\xd9\xeb\x64\x9b\x67\xe3\xfc\x87\x7e\xf5\xd6\x39\xe3\xc6\x8d\xd8\x3f\x6c\xcc\x22\x93\xb3\x97\xdd\xc1\xb5\x17\x62\x88\x46\xb3\xb2\x85\x21\x7a\xfb\xc6\x10\x03\x11\x69\x1b\xcb\x91\xc1\x5c\xfb\xd1\xae\x8d\xf0\xbc\x94\x91\xe5\x7c\x23\x70\xc5\x16\x60\x88\x62\xdf\x18\x22\xa6\xd5\x9b\x16\x86\x28\xe5\x31\x44\xaf\x85\x21\x4a\xfd\x61\x88\x2d\xc9\x66\xb9\x1b\x86\x58\x2d\x30\x65\xed\x73\x6f\x2c\x66\x83\x3b\xc8\x67\x39\x1f\xf9\x0c\xdf\x8f\xb7\x1f\x0d\x5f\xf8\xee\x5d\xf8\x15\x5c\xd3\xb5\x3e\xf7\x53\xbc\x85\x2c\x67\xae\x62\xee\x7d\x8a\xa4\xcd\xfd\x3f\x0f\x78\xa5\x4b\xd0\x22\x43\x69\xd6\x69\x56\x93\x86\x85\x6c\x26\x60\x93\x59\x77\x4c\x0b\xf0\x56\x1e\xcc\x16\x80\xb6\x12\x1b\xad\x55\x10\xa8\xa8\x8e\x16\xb4\x49\x72\x9a\x75\xca\x29\xaa\x3c\xe6\x81\xaa\x05\xa7\x6c\x16\xbd\xe9\x01\x42\xc0\xb8\x33\x7c\x28\x99\x40\x65\x66\xea\x21\x40\xa9\x2b\x4d\x7a\xe7\xf0\xf1\x4f\xb1\x2d\x17\xe7\x7f\x7a\xe3\xc2\xcc\xbc\x69\x9d\x1b\xc8\x97\xe4\x77\x78\x24\xde\xcd\x7c\xef\xd2\x4b\x97\x31\x51\x1c\xc6\x49\xf2\xe5\x67\x77\xde\x78\xfb\xc0\x86\x63\x03\xa2\x78\x20\xde\xba\x62\xcd\x1a\x0b\x93\x14\xba\xb8\xf6\x5e\x98\x24\xfe\x9f\xc3\x24\xf1\x4b\x64\x01\x1e\x81\x6f\xc5\xa5\xf8\x56\x3c\x82\x2c\xc0\x2f\x91\xa7\x48\x1b\xf9\x80\xb4\x31\x67\x33\x45\xb9\xf7\x98\x0a\xf8\xfa\x28\xf7\x14\xd3\x92\x7b\x5d\xff\x32\xf8\xd5\xab\xb9\x95\x68\x80\x7e\x8b\x41\x9f\x18\x67\xcb\xa6\x8b\xf5\xa1\x28\x62\x36\xe3\x72\x46\x8b\xf5\x23\x5e\xc8\x02\xfd\x88\x78\x50\xf5\x25\x80\xa6\xb7\x4c\xca\xa6\x45\xa8\x0d\x11\x5d\x06\xc9\x48\x99\x28\xc9\x06\x83\x19\x17\xa5\x15\x01\x4e\x49\xc3\xd5\x29\x68\x24\xd5\x7f\xa0\x2a\x92\x16\x84\x46\x10\x59\x0d\x01\x72\xd3\x07\x79\xbf\x00\x55\xb0\x50\xb9\x0f\x4f\x8e\x6e\xf6\xd6\xb6\x7d\x73\xef\xba\xf3\xbe\xed\xd7\x5e\xf5\xe8\x96\x2b\xae\x9f\xfa\xd2\xb4\xd9\xab\xfe\xf4\xe3\x03\x5d\xef\x6e\xba\xe6\x87\x27\x7e\x49\x3e\x6a\xec\x1a\xd0\x70\xe6\xe8\xf1\x67\xbc\x35\x6c\x54\x73\x73\x5d\xe4\xed\xc1\xd1\x6d\x9b\x7e\x93\x72\x54\xad\x5d\xb8\xe8\x81\x36\x64\x3e\x37\x7c\x35\xec\xf5\xd6\x02\xad\x41\x6c\x84\x88\x1e\x0a\xfa\x29\x56\x7f\xac\x4d\xa1\x19\x16\xc0\x26\xf9\x94\x6a\x37\xe8\xe0\x6d\x05\xa5\x90\xbc\xe5\xbf\xfa\x59\x8a\xd5\xb4\xe0\x6d\x38\x1a\x62\x38\xbc\x9c\x1c\xf6\xe7\x08\xd7\x4e\xce\x3e\x9b\x7c\xce\xfa\x4e\x6e\xc7\xcf\xae\x3a\xdc\xf5\x25\x62\xe8\x38\x84\x31\xc8\x8d\x4a\xd0\x8d\xbd\x46\xa2\x86\xe3\x9a\xec\xc9\xa6\xe5\x30\x24\x3e\x03\xf6\x98\xea\xa1\x92\x51\xd6\xf0\x54\x2f\x04\x1d\x52\x56\xf5\x80\x8c\x4f\xe1\x88\xf5\xfd\xcd\x7a\xf4\xa1\x95\xd0\xae\x22\x77\x4a\xb5\xcb\x69\x21\x10\xd6\x77\xbb\x4d\xd2\xf4\x5b\xac\xff\xd1\xdb\xbb\x67\xd9\xba\xcd\x85\x7c\xde\x03\x96\xec\x35\x39\x61\x4c\x3e\xb1\x46\xb9\xc5\xbf\xe2\xda\x7b\xe0\x92\xb8\x3b\x2e\xe9\xfd\x36\x5c\x72\x1b\x6e\xc4\xbb\xf1\x34\x72\x16\xfe\x33\xd9\x49\x5a\xb8\xf6\xc2\x1d\x4c\x9f\xa5\x53\xc7\xb8\x4d\xf0\x2c\x0d\xa3\x7e\x36\x05\xd6\xf5\x60\x11\x38\xe7\x5d\xfa\x99\x25\xc7\x55\xc7\x41\xcd\xee\xcd\xd2\x07\x89\x75\xd0\xdd\xe9\xa2\x42\xc6\xa3\xb0\x1e\x92\xc9\x14\x3e\x04\xf4\xb0\xb1\x31\x35\x75\x54\x90\x6d\x25\xfb\xc9\x5f\x2a\xe7\xdc\x73\xc3\x15\xae\xaf\xfc\x3b\xf0\x3a\x7c\xee\xc9\xed\xec\x6a\xb2\x89\xdc\xf6\xb0\x39\x47\x21\x02\xbc\xe0\x0f\x1a\xcf\xb1\x4b\x4e\x26\x4d\x4e\x70\x8b\x10\x5c\xce\xaa\x45\x34\x28\xf4\x24\x80\xaf\xa1\x98\x42\x85\xa3\xaf\xf8\xe2\xb0\x7e\xf7\x72\xaa\x87\x62\x85\xb6\x01\xdf\xa8\x42\x01\x30\xea\xf3\x75\x78\x7d\x9e\x5e\xc0\xa8\xd7\x07\x5d\x20\x19\xc1\xe3\xa5\xea\xaf\x0d\xb8\x43\xf0\x5a\x42\xb0\x58\x73\x17\x49\x32\xa8\xde\x19\x88\xa2\xa1\xb4\xa5\x94\xe3\xd0\x68\x06\xa6\x29\x0a\x22\x5b\xcd\xd6\xc5\xa1\x4c\xf6\xf9\xf2\xa4\x3d\x52\x3b\x48\xc3\xdb\xc8\xfb\xbe\xe6\xd8\x2b\x87\x5f\x8f\x35\x2a\x5c\x3b\xa9\x9e\xfa\xda\x84\xbb\x37\x2c\xc3\xe9\x93\xdb\xd9\x15\xa3\xdf\x5a\x42\x5c\xf8\xf8\xb2\x57\xc7\x77\xdd\x66\xae\xef\x6e\xe0\xcb\x18\xd3\x63\x7d\x0b\xb0\x45\x31\x5b\x48\x96\xd1\x1d\x5b\xf4\xf6\x15\x8f\xea\xeb\xbd\x0b\x37\x92\xfd\xa4\x8d\x6b\x27\xd3\xf1\x63\x27\xb7\xe3\x7d\x24\x69\xea\x5f\xfc\xd7\x70\x6c\xcf\xf9\x57\x38\xb6\x75\x7b\x6c\xe5\xda\x7b\x60\x8b\xfa\xe0\x04\x31\x8f\x2d\x7a\xf3\xd8\xa2\xb7\x27\xb6\xb8\x8d\x3d\x4e\xde\x24\x57\x72\xed\xfa\x26\xeb\xda\x68\xd6\xce\x73\x2b\x91\x82\x2a\x74\xaf\x05\xc2\x8b\x90\x83\x72\x32\x42\x67\x8a\x56\x6a\xa7\x64\xd8\x94\x07\x4b\xf1\x66\x55\x3f\xa0\x46\xe1\x3c\xeb\x95\xa6\x20\x49\x4e\x73\x5e\x68\x94\x09\xd3\x63\x0c\x69\x21\xb7\x24\x6b\xfa\x7b\x6a\x29\xf8\xb0\xd8\x14\x5a\x50\xa4\x64\x28\x59\xd0\x88\x0c\xc4\xd8\x85\xa5\xf3\xc7\x63\x9e\x2b\xff\xe3\x95\x3f\x5d\xfe\xe2\x86\x97\xaf\xf2\xf9\xf2\x75\xf3\xc2\xa4\x2d\x3b\xc9\x9b\xe4\xf3\x0e\x72\xfc\xc7\xb7\xfd\x24\xd8\xb3\x66\xfe\xbf\x4f\x8f\x0f\x46\x71\x84\xb8\x51\xb0\x56\x16\x26\xa9\x8f\x03\x89\xdd\x30\x49\xef\xb7\x60\x92\x4d\x34\xf5\x18\xe7\x3c\xe4\x76\xb2\x9f\x5d\x7d\x14\x9a\xde\xe0\x4c\x22\x7e\xee\x16\xae\x1d\x05\x51\xcc\xd0\x8d\xb1\x25\x55\x77\x5c\x93\x1d\x10\x28\x51\xec\x55\x76\x53\x97\x03\x49\x1a\xe7\x4b\x01\xfd\x9a\x02\xd2\x3e\x4a\x04\xeb\xc7\x2f\x25\xd8\x19\x83\x71\xeb\x5b\x25\x0e\xc1\x59\xb9\x1f\x4f\x20\xd1\x33\xbe\x78\xf0\xdc\x29\x2d\x67\x9c\xb7\xba\x4a\xe6\xda\x73\x9b\xa7\x5f\xb5\xf8\x22\xe6\x9a\x93\xca\xe3\x8f\x49\x5f\xba\xe7\x2f\x68\xf9\xff\x15\x8f\x1a\xed\x7d\xbc\x1b\xce\xa0\x42\x2c\x12\xf7\x8f\x45\x26\xed\x38\x52\x02\x57\x8b\x13\x3b\xf0\x1a\xb2\x15\xcf\x3e\xfc\x0e\x9e\x4d\xee\xc4\x6b\xc9\xc3\x9f\x1c\x63\x46\x30\xd5\xe4\x3e\xbc\x20\x77\x24\xf7\x32\x5e\x47\xd6\xd3\x1e\x85\xe5\xfc\x02\xf8\x0c\x33\x6f\xcd\x8a\x85\x38\x98\xc3\x24\x64\x2e\x80\x22\xbd\x79\x14\xcc\x6b\x41\x91\x52\xcf\xf3\x2e\x69\x9c\x77\xcf\xe2\xc4\x43\xe4\x33\xae\x5d\xdf\x3d\xd4\xf1\xd5\x3f\x77\x0d\x42\xdc\x36\xe0\x37\x3f\xc7\xa8\x2f\x84\x4f\xb1\x27\x33\x3e\xde\xa5\x1f\xae\x3e\xc1\x02\x66\x8c\x0f\x74\x61\xdd\x55\x07\xc9\x09\xbf\x41\xc2\x0a\x9c\x92\xbc\xcf\x68\x94\x06\xf8\xb1\x3b\xfa\xb8\x06\x37\x6e\x9c\xf9\xb3\xa9\xfa\x91\x7b\x45\xe7\x05\x4f\xbe\xc6\x3c\x8b\xb7\x91\xc5\xb7\x0f\xa8\xc4\xef\x9f\xdc\x8e\x9f\x19\xd6\xf0\x34\x3d\xdb\xc4\x48\xe1\x59\x6f\xda\x00\x1e\x9b\x6e\xd8\x63\xb7\xa9\x5b\x00\x60\xbf\x67\xfd\x2a\xfa\x65\x4c\x7e\x23\xbb\xfa\xe4\x76\x6a\x73\xf1\x65\x88\xd7\xda\xf2\x9f\xa7\x89\xce\x44\x77\xf4\x11\xf7\x44\x1f\xfb\xfb\x70\x13\x7d\xa4\xf9\x66\xd4\x1b\x73\x2c\x18\xca\x0e\xf2\x69\x7e\x34\xe6\x72\x18\x98\xe3\x22\xb0\x81\x82\xce\x33\xb0\x32\x97\x90\xb5\x4e\x8e\x0c\xab\x50\xbc\x4c\xa0\x31\x92\x83\x92\x2b\x30\x89\xb4\x03\xda\x6b\x1d\x88\xd6\xc7\x78\xe9\xe8\x8c\xb4\x8f\xcb\x80\xce\xa4\xa6\x88\x94\xac\x0c\x06\x7c\x14\x72\xa4\x88\xe3\xdd\x87\x30\xf3\x0f\xa2\xe4\x3e\xc1\x89\xdf\xef\x5d\x7c\xd9\xef\xd8\xd5\x47\xc9\xb4\x1d\x3b\xc9\x7d\xec\xea\xdc\xec\x5b\xce\x18\x0e\x58\xa3\xee\x83\x0c\x06\x3f\x4b\x46\x41\x0b\x6b\x54\x92\x9a\xd3\x18\x9c\xea\x4f\x66\x58\xd9\x61\x8d\x2d\xd4\xe3\x3e\xf6\xe4\xcd\xa5\xe8\xe1\x91\xd7\xc8\x0d\xc9\xdd\xb1\x46\x28\x33\x8d\x1a\x43\xc3\xd4\x66\x77\x60\xf4\xf5\xd7\x7f\x7f\xe0\x96\xbd\x97\x2d\xde\xc4\xc6\xf4\x65\xd4\xc7\xa7\x75\xbc\x75\xcb\x19\xc3\x49\xad\x7e\x91\x19\xfa\x61\x08\x71\xdb\xb9\x76\x64\x47\x52\x1e\x67\x34\x86\x97\x61\xa5\xbc\xdd\xe4\x02\xb7\x50\x75\x80\xcf\x04\xc6\x02\xaf\x4d\x72\xf4\x18\x10\xe0\x8c\x30\x9e\x6d\xb8\xf1\x10\x66\x8e\x13\xf9\xfd\xb7\xf7\x5e\xb6\xf8\x00\x1d\x07\xb9\xef\x2d\x30\xd2\xff\x9e\xbd\x7c\xdb\x4e\x1d\x13\x1e\xe1\x56\x22\x19\x95\xa3\x25\xdd\xf0\x45\xd3\x01\x00\xf7\xb6\xd4\x91\xc7\x17\xc5\xac\xc9\xd2\x2c\x7b\x7b\xe2\x8b\xde\xac\xe9\x16\x98\x35\xfb\x61\x45\x92\xbb\x23\x8b\x61\x0b\x59\x4c\x36\xd7\x24\x13\xfa\xd0\xab\xab\x6a\xa2\xd5\x52\xa1\xbe\xfc\x36\xdc\xb8\xaf\x0c\x4b\x07\x3f\xc5\x61\xf2\xf1\xd7\x47\xc8\x3f\x4a\x5f\xc7\x5d\xf3\x56\x2c\x9f\x37\xff\xaa\xe5\xf3\x74\x9f\xed\xe0\xa7\xe4\x75\xf2\x77\xf2\x29\x79\xf3\x78\x96\x24\x99\xc6\x5f\xfc\xf2\x97\xbf\xf8\xc5\xc3\x3b\x8d\x67\x88\xab\xe0\xda\x7b\xe1\x89\xc0\x72\x29\xe4\xf1\x44\x3e\x8f\x27\x2a\xdd\xf0\x44\xef\x77\xc3\x13\x1b\x01\x4f\x6c\x4e\x42\xaf\x3a\x6b\xe1\x89\x78\xf0\x92\xe5\x7f\xfb\x0f\xc6\x46\xf6\x3f\xd2\x95\x5c\x36\x6b\xd7\x81\xc9\x17\xe0\xa7\x06\xef\x5a\xb9\x7d\xcf\xc9\xed\x78\x1b\x99\xcb\x32\x67\x9f\x8b\x8b\xcf\x41\x66\x5e\x8f\x9b\x27\x44\x40\x6b\xb2\x06\xad\xe8\x89\x38\x54\x09\xd9\x4c\x39\x45\x1c\xca\xf5\xe1\xd6\x5a\x88\x43\x39\x20\x0e\x15\x06\xe2\x50\xa7\x47\x66\xfa\x05\x14\x08\xa6\x52\x6a\x85\xf4\x04\xeb\x94\x43\x61\x60\xd8\x13\xe4\x3e\xc1\x87\xf2\xd3\x80\x0f\x8a\x59\xbb\xa9\x9c\x0e\x85\xb8\xc7\x28\xe4\xbc\xa4\x7f\x30\x82\xfb\x9a\x96\x74\x76\x7d\x40\x41\x09\xce\x98\x2f\x07\x8a\xb2\x51\x94\x44\x3f\xe8\x39\xe3\x5a\x21\x9b\x89\xd0\x19\x47\xf8\xac\x5a\x1e\x57\x1b\x93\x5a\x11\x9b\x55\x63\x09\x53\x82\x55\x9f\x7e\x24\xd1\x11\xb0\x21\x1b\xb0\x67\xeb\x86\x18\x80\x63\x5a\x83\x9c\xed\xa8\x6a\x18\x60\xa3\x26\x69\xc2\x31\xda\xf9\x16\x4d\xa9\x03\xa4\x0e\xa7\xcc\xd6\x42\xf9\xa2\xcd\x69\x75\xc3\xf5\x6f\x80\xc2\x4a\x78\x6a\x83\xc2\x22\xf8\xbe\xed\xf1\x1b\xb3\x34\x7e\x9d\x61\x10\xec\x32\x6b\xe3\xfb\x32\xcd\x62\xa3\x5c\x3e\x77\xd5\x8a\x35\x6b\x98\x76\xab\x4a\x1e\x23\x0e\xf4\x47\xfd\xa8\x0e\x6d\x30\x18\xc5\x03\x71\xad\x18\xf4\x68\x54\x31\xa9\x61\x3e\xab\xf2\x09\x95\x8d\x43\xf9\x56\xed\x41\x3d\xb6\xad\xf1\x66\x35\xce\x96\x48\xa4\x6b\x6a\x41\xf8\x50\xb4\xc7\xd2\xb5\xc0\xcd\x5a\xab\x5f\x08\x35\xd4\xb1\x92\xbd\x94\xf9\xae\xa6\x96\xfa\x55\xa5\x52\x87\xcb\x13\xa0\x8d\xcf\x40\x42\x16\x4a\xa9\xb5\x92\x5a\x94\x52\x91\x9c\x76\x7a\x2a\x29\xab\x78\x53\xb2\x09\x3a\x04\x03\x7e\x31\x49\x11\x67\x68\xb4\xd1\xcf\xa0\x26\x53\x22\x2d\x22\x71\xf7\xe1\x46\x3c\x82\xbc\xec\x91\x17\xfd\xf1\xe5\x37\x9e\x79\xfc\xca\xa9\x23\x46\xae\x69\x6f\x5b\xb7\x92\xec\xe7\x76\xbf\xfa\xe0\x83\xaf\xca\xe7\x77\xee\xf8\x8f\x57\xbb\x3e\xe9\x78\x3e\xfc\xb9\xb2\x8b\x49\x2f\x5b\xf6\xf8\x8b\x24\xce\xed\xb6\xce\x6e\x76\x97\x10\x81\x7e\x9b\x54\x2f\xc4\xd1\xdb\x07\xe2\xa8\x3a\x12\x7d\xb5\xdc\x04\x0a\x5a\x6e\x00\x87\xbc\xcc\xa8\x90\x06\x3c\x92\x3b\x6c\x15\x46\xff\xef\xdd\x37\xae\x8f\x7d\x37\x70\x74\x5e\x69\x30\xc6\x94\x9a\x63\xb7\x5b\x2c\x9d\x6a\x51\xc2\x24\x3c\x2d\xa7\x3a\x40\x90\xe7\x07\x11\xa0\xea\x94\x5a\x2e\x3d\xc1\xda\x3d\x81\xd2\x2a\x53\x05\xc8\x4b\xfb\x45\x4b\xf5\xad\x50\x44\x69\x3a\x05\x39\xac\xff\xd4\x9c\x84\xfe\x10\xd0\xa8\x08\x54\x19\x19\x93\xa4\xb3\x1c\xbc\x09\xe8\xbd\x99\xf3\x97\xdf\xbf\xf1\xdc\x9c\x19\xb7\x4f\xd9\x78\xe1\x1d\x1b\xae\x1f\xfe\xd7\xcf\xae\xdf\x3d\xf9\x82\xb7\xcf\xdb\x39\x68\xc9\xec\xf5\xab\x5b\xd8\x11\x77\x3d\x34\xf3\x0f\x35\x0d\xe7\xd4\x8f\x1c\xd1\x34\xe7\xba\xf3\x77\x67\x22\x95\x5d\x03\x9a\xe7\xd6\x0c\x4e\xd5\x35\xcf\x59\x05\x7b\xe1\x0e\x84\x80\x1b\xc1\x86\x5c\x68\xa8\xc1\x80\x08\x1c\x3e\x62\x5c\x63\xb8\x2c\xb4\xec\xda\x81\x5a\xcf\x05\xdc\x98\xe0\x5b\xb8\xec\x7a\xc8\xcd\xd0\x52\x52\x93\xfd\x40\xf7\x44\xef\x00\xd6\x03\x37\x6e\xe4\xd7\xdd\x75\xd7\x84\x73\x4f\x86\x0c\x87\x81\x3d\x75\x14\x21\xe6\x0e\xd0\xd0\xf0\xa2\x12\x34\xcb\xf0\x7f\x4d\xfd\x8c\x30\xed\xaf\x51\x28\x2e\xd6\x9f\x7e\x86\x0f\xde\x08\x1a\xa0\x6f\x5e\x3f\x23\xe8\x35\xb4\x55\xd1\x90\x46\xb6\x87\x5c\x46\xe1\xf7\x25\xe6\xa1\xf1\x34\x6e\x9c\xd5\x4b\x1b\xe3\xc4\x8b\xfa\x60\xf9\xb5\xe6\xe1\xf0\xdf\x8d\x37\x82\x41\xe8\xd4\x31\xe1\x2d\xd0\xfc\xaa\x40\x17\x1a\x19\x8f\x22\x21\x6b\xb8\x3f\x26\x3a\x26\x8b\xd9\x8c\xbd\x22\xa8\xdf\xba\x76\xdd\x01\xab\x04\x61\xd3\x22\x2f\x08\xc8\x14\xd1\x1e\x7c\xb7\xd7\x88\xfa\x80\x1d\x1a\xe9\xb7\x18\x5c\xbe\x85\xc0\x19\x64\x71\xea\xb1\x54\x0d\xf0\x59\xad\xe1\x96\x19\x30\x5a\xf5\xad\xc7\xff\x4a\x2a\xc8\x88\xcf\x00\x4a\xe3\x8a\x6f\x7a\x6e\xde\xa5\xeb\x4d\x44\xcd\xf4\x68\x01\x55\xfb\x8b\xee\xb0\xc1\x99\x03\x63\x97\x50\x18\x5d\x4a\x71\x0f\x15\x25\x35\xd9\xf4\x68\xf9\x64\x86\xf5\xb9\xb1\x3b\xa6\x16\x25\x8d\x50\xc4\x84\x7f\x24\xea\xf9\x48\x94\x75\x9f\x4b\x80\x2b\x24\x80\x2b\x14\x30\x22\x91\x12\x48\x14\xcb\x92\xac\x39\x03\xdd\x0a\x42\x8c\x39\x40\xeb\x8b\xe9\x56\xe2\x39\xb8\xd1\x18\x3e\xd9\xc1\xdc\x02\x43\xa7\xc8\x14\x1d\x38\xde\x47\x92\xd4\xcd\xd4\xef\x07\x84\xe0\x7e\x28\xd5\x3d\xb6\x12\x7d\xd4\x72\xb2\xf7\xdd\x50\x16\x57\x4b\xe0\x6e\x28\x36\xef\x86\x62\xa8\x40\x2d\xd6\xef\x86\x92\x62\xfd\x65\x89\x7e\x37\x14\x53\x87\x5c\x36\xd8\xfd\x8a\x4b\xe8\xdd\xa0\x48\x9a\x0b\xaa\x63\x51\x09\xf4\x11\xf6\x79\x11\x44\xa4\xa1\x7d\x1e\xff\x64\x7f\xa6\xe7\xc1\x9f\x5b\xc0\x4c\xfb\xd2\x3c\xf1\xa9\xaf\xfe\x95\x10\xe9\xd5\x17\x83\xbb\xf7\xc5\x78\xbf\x73\x5f\x4c\x0f\x08\xb7\xde\x3a\xf5\x0b\xa1\xdc\x82\xe3\xdf\xc2\xc8\x23\xf0\x2c\xb5\xf5\x81\xd6\x87\xfa\x42\xeb\x8b\xcc\xbe\x18\x5e\xf7\xaa\x80\x95\x4e\x70\xfb\x64\x3f\x48\xd8\x7e\x0b\x6a\x6f\xf5\xc4\x74\x83\xbc\x3b\x0d\x3f\xaa\x37\xd2\xed\x32\x1b\x62\x28\x7f\xc0\x2d\xc2\x18\x14\x44\x35\x68\x46\x4f\xb4\x47\xad\x8a\x6b\x25\x9e\x6c\xba\xa4\x0a\x56\xb5\xdc\x1e\x53\x43\x94\x41\x20\x74\x50\x2b\x92\xa8\x7b\x58\x14\x92\xe4\x0e\x2c\xd7\xb8\xa9\xa2\xcf\x77\x85\x85\xba\x41\xf5\xfd\x81\x44\xe4\x17\xbd\x50\xfb\xde\xa8\x91\xd0\x52\x50\x4f\xbc\x8d\x2c\xe7\x5e\x80\x38\xb7\xb0\x1f\x46\xec\xde\x0f\xd3\x27\xde\x61\x54\x48\x5b\xfd\x30\xfd\x06\xfd\xcf\xe2\x04\xb9\xce\x44\x3c\x4e\x6e\x27\xcb\x21\xc4\xa6\x35\x8c\xb6\x51\xfc\xeb\x28\x81\x6e\x41\xe9\x21\xfa\x67\x0f\x4c\x6a\x3e\x36\xab\x86\x12\x69\xdf\x10\xfd\xe3\x7d\x8a\x9d\x72\x7d\xaa\x35\x49\xcd\xe1\xa0\x2a\x4a\x49\x5a\xd4\xe8\x85\xc6\x7f\x19\xc7\x0a\x89\x5d\xa3\xde\xac\x36\x54\x7f\x8a\xdc\x92\x9c\x16\xd9\x21\x54\xe0\x21\x2d\x44\x06\xa7\x20\x0d\x95\xae\xac\x19\x08\x77\xab\x6f\x88\x24\xab\x83\xf5\x88\xa2\x03\x89\x95\x51\x7a\xb7\x6a\x42\x24\x0f\x15\x5b\x5d\xab\x72\x32\xd1\x22\x45\x0c\xb6\x49\x2b\x61\x65\x75\xd6\xd3\x76\x5d\x5c\x8f\x5d\x93\x1e\x1f\xb7\x64\xfc\x45\x75\x3f\xb8\xf5\x29\xf5\xfc\x0b\x70\xf3\xc4\x25\xea\x9e\xdb\xd6\x45\x67\x8f\x5f\x32\x56\x9d\x8c\x5d\xb8\x9e\xec\x21\x07\xaf\x4e\x4f\x9d\xfa\xd8\xd5\xe4\x10\x79\x92\x45\x78\x3a\x5e\x35\x3c\x79\x68\x70\xe4\x6f\x7f\x3e\x49\xfe\x71\x16\xfe\x09\xb9\xfa\x2c\x6c\x3f\xf9\xde\x57\x91\xc1\x87\x1a\x47\x92\x1f\x93\x47\xc9\x26\x32\x7f\xe2\xe4\xc9\x13\xf1\x7d\x88\x6a\x7d\x0a\x2f\x73\xed\x28\x8c\xe6\x23\x68\x9f\x54\x03\x49\xd8\x81\x9a\x5d\x4a\x26\xcd\x23\x11\xfb\xb2\x2a\xa6\xcf\x89\xc3\x07\xdc\xf0\x92\x6e\x10\x03\x1c\xb7\x63\xfd\x99\x08\x43\x2c\x95\xb6\x85\x80\x9c\xcd\x08\x57\x90\x86\xc2\x92\x9c\xe6\xdc\x21\xea\x6f\x9a\x1b\x91\xa5\x2f\x64\x29\xe2\x63\xc4\x88\x13\x47\x04\x3c\xe3\xa5\x6a\x87\xcd\x3d\x66\xc9\xd5\xf8\xbc\x5d\x55\xb2\x6d\xf1\xc5\x78\xe8\x6b\xbf\x23\x1f\xdf\xdd\x49\x5e\xe1\xda\x73\xeb\xae\x5b\x3a\xe5\x1e\x1c\xc0\x4b\x72\x77\x5e\x7f\xc5\xcf\xf1\x1d\xb8\x8a\xfc\x34\xf7\xc7\x7f\xc7\x5b\xc9\x65\x16\xb6\x22\x40\x8f\x46\x31\x5a\x66\xdc\x55\xb2\x8b\xd6\x0d\x67\xec\xc5\x5e\x96\xd6\xd0\x66\x30\xd2\x5f\xc2\x71\x6a\xd3\x8f\x53\x60\xbf\xf7\xc1\x59\xaa\x4f\x07\xce\x52\xd9\x07\x99\x33\xfd\x2c\xf5\x41\x23\xa1\x4f\x3f\x4b\x65\x9a\x03\x76\x07\x80\x10\x1f\x69\xc5\xb2\x01\x89\x49\x4d\x11\xe3\xec\x84\xca\xa5\xc2\x8a\x2f\x8c\x70\x13\x5e\x4d\x36\xae\xa1\x05\x4c\xa4\x0d\x37\x5d\x7e\xff\xed\x77\x66\xa6\x71\xbe\x0f\x9f\x7f\xfe\xc3\xcd\x1f\xfd\x9e\xb4\x70\xbe\xae\xcf\x8c\xb2\x2f\x63\x1e\x1c\x1f\x85\x7b\xeb\x7b\xe6\x3c\xf2\x97\x16\x00\xcc\x62\x22\x8d\xc1\x55\xc6\xac\x3d\x96\x09\xdb\x61\x72\x61\x43\x80\xd8\x98\x8b\xf7\xdb\xe6\x12\x30\xae\x65\xb8\xca\xc2\x7d\xcd\xa5\x3b\x94\x84\x19\xdc\x88\x17\x93\x7b\x00\x24\x51\x72\x9f\xe0\x46\xc0\x49\xd8\xd5\x47\x5f\x7f\xfd\xe8\xde\xee\x90\x12\xc2\x68\xcf\xa9\x63\xe2\x74\x7e\x2f\xaa\x42\xab\x0c\x8f\xbf\xac\x77\x65\x93\x9b\xcd\x66\xd8\x48\x99\xe8\xd6\x6f\x39\xf0\xc8\x7c\x89\x0e\x47\x99\x98\xa7\xe2\xa8\xa2\x55\x4e\x55\xc0\x46\x0f\x28\x44\x08\xc4\xf1\x15\xe8\x0d\x54\x64\x7b\x0c\xea\x6c\x94\x4a\x20\xd2\x43\x5a\xc4\x64\x1f\x36\x40\x08\x39\x4f\x98\x2f\x46\x24\xe3\xbc\xa3\xdd\xf0\x6c\xb5\xb4\x07\x37\x1f\x1a\x84\x6f\xc0\x35\x1f\xbe\xb3\x60\x76\xe6\xc2\x87\x7e\xe7\x67\x16\xe4\xee\x75\xff\x6e\xd7\xa5\x2f\x7c\xef\xb2\xd7\x57\x91\x97\xc9\xfd\xe1\x37\xa1\xca\xa9\x08\x0f\x5f\xdc\x15\x1d\xfe\xd8\x76\x42\x9e\xf8\xfd\x80\x5a\xe8\x8c\x6f\xc5\xa3\x72\x9b\x0c\x9d\x65\xa1\x8c\x5b\x89\xca\xad\x2a\x2e\xe8\x43\xf6\x8b\x06\xca\x62\xc3\xb4\x82\x9a\xe6\x5b\x5c\x62\x36\xc3\x96\x85\x05\x37\xf0\x56\xea\xae\x87\x27\x61\x82\x2e\xe5\xd4\xf5\x28\x87\x90\x4e\x9f\xae\x14\xa0\xfd\xff\xa5\x56\xff\x3f\xb0\x71\x96\xe9\xd3\x0c\x86\xf2\xd3\x84\xb3\xa5\xae\xba\xca\xea\xf8\x0f\x08\x14\x77\xd9\x86\x1b\x8f\x34\xe2\x03\x17\x3d\x37\xb5\xed\x96\xeb\x5e\xf5\xe1\x9d\x64\xb6\xfd\xea\x95\x5b\xd5\x1f\xfd\xee\x73\xf2\x65\xf8\x08\xf8\x21\x2f\x0d\xaa\x39\x30\xe6\xbd\xf7\x7f\xf0\xfd\x69\x9f\x9d\xf5\xe5\x5f\x49\xd2\xdc\x87\x87\xf8\x67\x90\x13\xf9\xd0\x24\x0b\x41\x35\x3a\x1a\xb0\x2a\x59\x08\xa0\xc9\x5d\x2f\x65\xe1\xdc\xd4\x23\x70\x0d\xbb\xa8\x22\x8c\xd7\xb8\x30\x3b\x78\xbb\xcb\x4b\x2b\x0e\xa0\xad\xb0\x1a\x40\x15\x1c\x61\xa2\x02\x33\x18\xaf\x61\xe2\xe4\xad\x03\x0b\xc8\x5f\x17\xed\xc7\x65\x38\x75\xb3\xe2\xe4\x9f\x39\x31\x9e\x59\x95\xdb\xa4\x7f\xb1\x0b\xf0\xac\xb3\x86\x5a\xcf\x46\x05\xdc\x2b\x12\x6a\xe9\x36\x26\x90\xb4\x96\xe3\xaa\xed\xa0\x26\x16\x01\xd6\xa7\x89\x36\x03\xba\x36\x07\xe0\xeb\x35\x00\x25\x12\xad\x8b\x0a\xf8\x10\x5e\x8e\x0f\x93\x77\xb6\xb6\x92\xe3\xd3\x7e\x76\x14\xbb\xab\x27\x96\x15\xeb\xae\xb9\x6e\x2b\xfd\x8b\xb9\x66\xda\x7d\x17\x5e\x4c\x6b\x1d\x6d\x0e\xfe\x19\xa4\xa0\x30\xba\xce\x58\x69\xd1\xe9\x4d\x26\x0b\x3a\x22\x64\xc4\xeb\x27\x8d\x3b\x99\xa4\xc5\x7a\xf4\xfc\x54\xe8\x36\x56\x68\x6f\xa3\xd7\x0b\x4a\x1b\x20\x59\x61\x28\x2b\x7a\x7d\x34\x57\xe5\x92\xd2\x1c\xef\xd7\x0f\x50\x27\x95\x02\x63\x75\x27\xd3\x1f\x48\x81\x34\x77\x91\xe9\x6a\x2a\xf9\x49\x44\x14\xdd\x5f\xd2\x27\xb2\x07\x37\xe3\x9f\xbd\x63\x99\xf3\xf3\xc5\xfb\xc9\x81\xcf\xc9\x5e\x66\x0b\x4e\x25\xe7\x38\x9c\xd0\x68\x71\x66\xde\xb0\xd4\xb8\x9b\x3e\x8b\x0e\x35\xfc\x25\xb1\x85\x6b\x47\x0a\x2a\x42\x0b\x7b\xcc\x0d\x5b\x73\xc3\xd6\xdc\x44\x8b\x28\x4e\x29\x32\xe7\xe6\x32\x48\x16\xf5\x4b\xd3\xa5\xd0\xa2\x07\xa7\x04\xa3\xef\x31\x91\x50\x7f\x13\x49\xd6\x45\x85\x6d\xd8\x86\xb7\x3c\x89\x97\xe9\x8b\xf2\xd0\x38\x72\x7c\xdc\x4e\xf2\x87\x17\xc9\x3e\xe6\x96\x8f\xe7\x86\x02\x56\x4a\x77\x2f\x69\x82\xaf\x7d\x24\xc9\xdc\xfb\x9f\xe3\xcf\x41\x0c\xf4\x8b\x9f\xcd\x77\xa2\x30\x2a\x45\xd7\x1b\xfb\xc3\xad\x24\x93\x50\x4a\xaf\x15\xb3\x96\x7e\xae\x51\xac\xe7\xd7\x4f\x0e\x8a\x6a\x7a\x8c\x93\xbd\xdc\x2c\xda\xe3\x05\x20\x91\xd6\xb8\xe2\x54\x4a\x55\x80\xd1\xdb\x23\x69\xf6\xd2\x54\x4a\x75\xcb\x9a\x0d\x30\xcf\x62\x24\xc9\x19\xce\x2e\x07\x28\x16\x27\x69\x3c\xad\x0e\x57\x46\xe3\x16\xdc\x14\x09\xe0\x72\x1c\x52\x22\x6c\x03\x8e\x42\xaa\x44\x64\x4b\x98\xfa\xad\xc3\x1f\xf9\x21\xd9\xc4\x07\xc8\xfa\x8d\x8f\xa4\xb6\x92\xd7\xd6\xd4\xcf\x38\x93\xec\x9b\xd0\x36\x60\xcd\x3b\x5d\x04\xbf\xdc\xf1\x54\x0d\x7e\x7b\xf3\x66\x12\xab\x7d\xee\x51\x32\x02\xaf\xbf\x61\x81\x2f\x77\x1b\xb3\xc2\xb7\x70\x0d\x59\xc7\x65\xc8\xab\x38\x85\x18\xe4\x47\x88\xfb\x0b\xdc\xd9\xa5\x68\x6d\xb7\x79\xea\xe7\x4b\x31\x9f\x9f\x67\x51\x7e\x9e\x45\xd9\xb4\x02\xc4\x52\x8a\xcd\x1e\xb3\xa6\x5c\xf4\x9d\xa6\xfc\x2f\x4c\x55\x09\xb5\xf8\xaf\x19\xb0\xf6\x22\xf2\x2e\x37\x94\xbc\x33\x6b\xf5\xc0\xab\x09\x69\x2f\x1e\x16\x27\xc7\x9b\x47\x86\xda\x3b\xd3\x19\x3c\x7b\xed\x4f\x2b\xf1\xd2\x2b\xae\x20\x5b\x2a\x7f\xba\x86\xec\xc4\xd1\xa9\xe3\x9c\x64\x0c\x7e\xc9\x31\xbe\x95\x1c\x66\x6f\x7b\xef\x3d\xb3\xbf\xdd\xb6\x94\xef\x44\x15\xa8\x0a\xdd\x6d\x62\xd8\x4a\x38\x69\xac\xaa\x8a\x93\x5a\xa5\x7e\x8b\x94\x23\xc1\xad\x7b\x24\xf4\xb9\x53\x23\x09\xf3\x06\xa9\xa0\x8f\x5e\x05\xf5\xe5\xfa\x5f\x79\x28\xd7\x2c\x96\xe4\xb4\xc0\x97\xa5\x0c\x43\x54\x52\x43\x44\xa8\x21\xaa\x60\x1b\x97\x43\x3b\xb2\x26\x54\xea\x16\xcb\x77\x03\xf4\x69\x84\x88\xd2\xdc\x12\x91\x70\x09\x86\x7e\x27\xb2\xb3\xaf\x65\x27\xaf\xff\x6c\x50\x92\x3c\xc2\x5c\xdd\x45\xe0\xa6\x49\xf7\xb3\xfa\xf8\xe5\x75\xc9\xdc\x26\x6b\x0f\xe8\xf1\xed\xd7\x5c\x3b\xd8\x65\x47\x0f\xbb\x60\xc3\x2e\xbc\x65\x17\xfd\x96\x29\x30\x49\x51\x37\x93\x7c\x97\x4d\xf2\x1d\xad\x53\xae\xef\x23\x59\x7f\xc8\x59\xe9\x9f\xb5\x52\xa8\x45\x7f\xf0\xf7\x9f\x42\x5c\x92\xbc\x33\xeb\xfa\xfa\x6b\x08\x69\x0f\x8d\x34\x36\x0c\x21\xd7\x94\x55\x92\xb7\x98\x64\xfa\x09\x38\x01\xc6\x17\xec\x9b\x89\x13\x1d\xd6\xbe\xc1\xb3\x2f\x28\x27\x49\xd8\x3d\x18\xd5\x93\x38\xd7\x29\x7c\x8e\xce\x41\x8f\xa3\x74\x33\xdc\x16\xf6\xac\x3a\x21\xae\x8d\x14\xb3\xaa\x23\xae\x39\xed\x59\x35\x1a\xcf\x54\x79\x90\x8b\x8b\x61\x75\x12\x18\x67\xb8\x92\x4d\x0f\x07\xef\x6a\xf8\x38\x7b\x4c\x1d\x4e\x09\xcd\x93\xfa\x91\x6d\xe8\xf1\xa5\xbd\x83\xa0\x62\xdc\x61\x8f\x69\x93\x71\x4c\x1b\xae\x5f\x30\xfe\x40\x31\x3c\x1a\x5e\x69\xac\x9b\x63\xe5\xa2\xd2\xf2\xfa\xf8\x90\xe6\x31\x67\x4d\xa8\x09\xa5\xb4\x41\x82\x24\xa7\xab\x6a\xa2\x10\x25\x34\x8f\xa4\x9c\x3d\x0e\x56\x92\xd5\x24\x9c\x90\xf1\x21\xa9\x94\x1a\x95\x3b\x8a\xca\x6b\x07\x19\xac\xe0\xcd\xb5\x90\xed\x2e\x6c\xaf\x8d\x8e\xc6\x2d\x75\xd1\xa6\x64\x30\x34\x9a\x31\x24\xd6\x44\x90\xd2\x31\xbb\x72\xab\x3c\x38\xe0\x4f\x26\xc6\xe0\x44\x28\xd0\x80\xab\xbd\xb8\xaa\xae\xfe\x18\x3a\xf5\xd2\x6e\xb3\x01\x77\xff\xb3\x3f\x3a\xff\xc9\x55\x73\x37\x1c\x68\xfe\x79\xeb\x85\x0b\x47\x4e\x1a\x52\x3c\xfa\xe2\x4b\x1e\xd9\xf3\xe4\xbf\xed\xd9\x4b\x1e\x27\xff\x63\xce\xbc\xfa\x2d\xb3\x2e\xbb\xf7\x27\xe5\xbe\xd9\xcd\x4f\xfc\x35\xbd\x6f\xc5\xa3\xf7\x89\xdc\xc2\x65\x66\x7f\xee\xfe\xe6\x29\xd2\xaa\x0d\x25\x03\x7e\xbe\xa0\xb5\x41\xfa\x99\xeb\xde\xaa\x3d\x3f\xf8\xc9\xaf\xc3\x82\xff\xc9\x2d\xaf\x7f\x22\x45\xeb\x67\xf2\x7c\xfd\x51\x5f\x98\xe3\x76\xeb\x3e\x51\x05\x89\x73\xd5\xfc\x02\x34\x11\x3d\x86\xd2\x43\xc1\xf6\x36\xdd\xf6\xea\xf8\xa4\x36\x5c\xcc\xaa\xa3\x13\xaa\x3d\xae\x39\x84\xac\x5a\x17\xcf\x44\x8c\x15\x38\x07\x56\xa0\xa5\x28\x9b\x6e\x81\x15\x68\x39\xc3\x1e\x53\x5b\x7c\x1a\x4f\xeb\x9e\x1a\x95\xac\x16\x93\xb2\x69\x3e\x06\x38\xb1\x6e\xff\x49\x38\xa6\xb5\x50\xfb\x87\x41\xb3\x80\x97\xc6\xda\x59\x29\x54\x52\x36\x74\xf4\x78\xdd\xf6\x6a\x4c\xee\x88\x0c\x00\x75\x4d\xa4\x0d\x1d\x4e\x4d\x6f\xd7\x4d\xdf\x08\xdd\xc2\x83\x1b\x52\x29\xb5\x4e\xee\x08\x95\xd5\xc4\x4c\xd3\xf7\x6c\x6c\x16\xc4\x68\x73\x4b\x1c\xf7\xb6\xbc\x65\x78\x43\x2c\xa6\x39\x49\x2d\x5f\x25\x54\x57\x56\x7c\xf8\x29\xb6\x15\x56\x1b\x6e\x58\x73\xf1\x85\xbf\x4d\x6d\x9d\xde\x36\x7f\xc4\xc4\x64\x55\xf3\x8c\x49\xdf\xbf\xf9\xc0\xfa\xe5\xe4\x0f\xe4\x8b\x25\x97\x4e\x9e\x75\xc1\xb9\xad\x43\x7e\x54\x2e\xb5\x0d\x1d\xdf\x71\x03\x79\x60\xed\xe3\x0f\xaf\xcf\x97\x22\x0e\x51\x96\x5c\x52\x52\x7f\xef\xa2\x29\x83\x7d\x5b\xdd\xcb\xab\x6e\xb9\x94\xd6\x25\x3e\x92\x8e\x0e\x1d\x3a\x50\xb7\xba\x54\x64\x33\xfa\x8d\x84\xbb\x41\x43\xe1\x5c\x83\x9f\x1a\xba\x59\x6c\xde\x64\x32\x13\x16\x42\xd8\x0d\x12\x71\x61\x27\xa5\xa9\x2e\x2d\x94\x7d\x0e\xe1\x98\x2a\x26\x40\x09\xd0\x0e\x34\xd5\x1e\x10\xa3\xa2\x2c\x2f\x66\xd3\x91\x41\x40\x4d\xa9\x7a\x50\x04\xae\xed\x4a\xb4\x14\x57\xdd\x9d\xae\xc0\xc1\x8a\xc7\xee\xc5\xd5\xe4\x20\x79\x2b\x49\x3e\x4e\x92\xfd\xe4\x1d\xf6\x2d\xfc\x3e\x89\xdc\xff\x13\xd6\xd6\x75\x7c\xcb\x9d\xfa\x6b\xf2\x17\xf2\x35\x99\x82\x33\xd8\xfe\x7f\x98\x56\xf5\xff\xce\x1c\xbb\x6c\x41\x5d\x9c\xee\xd9\x26\x7b\x56\xc6\x15\x39\xb2\x19\xbf\xc7\xa1\x8f\xdd\x4f\x83\x4c\x1a\x34\x42\x4d\x5c\x9f\x85\x70\x10\x81\xd4\x42\x6e\xad\x67\x21\xdc\x48\xef\xb2\x45\x2f\x95\x92\xd1\xf8\x45\xcf\xd2\x45\x2f\xf5\xaa\x86\x9b\x78\xf5\xd5\x1f\xbd\x75\xd5\x8a\xbc\x36\xe8\x4e\xd0\x06\x5d\x4c\xf3\x20\xaa\x3f\x99\x76\x1a\xb2\x96\xbe\x7c\x2f\x30\xa6\x15\x5f\x6a\x73\xf1\x53\x23\xdf\x3e\x56\x06\xad\xd3\xfe\x06\x8f\xaa\x3c\xaf\x09\x45\xdf\xa8\xe2\xf3\x28\x2d\x88\x0a\xad\x71\x14\x15\x7f\xbe\xfd\xdb\x17\x90\x64\xcd\xc3\xa5\x80\x73\xdd\x4d\xe5\x2b\x83\xa1\xe6\x16\xc5\x7a\xcc\x05\x11\xb4\x0b\x22\xb1\x80\xd4\xbc\xab\x65\xce\x75\x6d\x57\x9f\x9d\x6c\x6c\x18\x3b\x90\x6c\x25\x8f\xf1\x9d\x5d\x2b\xb7\x6d\xfe\xc1\xaf\x18\xdb\xaf\xee\x9b\x1c\xfd\x32\x34\xe1\xda\x93\x5d\xe6\xb8\xb9\x03\xdc\x22\x14\x44\xcd\xb4\x56\x00\x1a\x47\xf4\x41\x4b\x0e\xab\x7a\x02\x9b\x0d\xb4\x52\x50\x92\xd3\x3c\x07\x80\xa3\x4b\x02\x9e\x28\x0b\xaf\xeb\x3e\x8e\x31\xfb\x12\x36\xce\x3d\x68\x4d\x72\xca\x95\x17\x4c\x99\x18\x8b\x56\x26\x03\xe4\xdf\xc9\xeb\x5c\x7b\xee\xd6\x87\xce\x5d\x7e\x03\x9e\x79\xeb\x15\x8d\xa5\xc7\x94\x41\x2d\x5d\x5f\x5a\xba\xa0\x3b\xc5\x95\x28\x80\x2a\x50\x3d\x5a\xd1\x8f\x0d\x07\x5a\x36\x8c\xfd\xf3\x36\xa4\x78\x68\x10\xfa\x34\xbe\xa3\x35\x9b\x22\xe5\x18\x80\xd2\x5a\xeb\x55\x7f\x16\x26\x9d\x78\x70\x64\x41\xfd\xf6\x73\x0e\xe0\x65\xf0\xea\xc1\xd1\xff\xd9\x97\xd5\xc5\xf6\xc0\xc4\x47\x87\x95\xa4\x5e\x4b\xc0\x7f\x1b\xf7\x5a\xba\xa8\xdc\x01\x21\x82\x82\xa8\x12\x0d\x44\x63\xfb\x5a\x8b\x98\xb5\x16\x83\x70\x8c\x4e\x26\x04\x7c\xf0\xdf\x7d\x55\xfa\x9a\x4f\x3f\x2b\x45\x1e\xe8\x3d\x9f\xbe\x56\x4f\x70\xf5\x39\x9f\x55\xc4\xef\xb8\x05\xce\x98\x10\x6a\x40\x97\xf4\x3c\x63\x02\x6c\x36\x5d\xa4\x4f\xae\x32\xa9\xd6\xc6\xb5\x81\xfa\xfc\xe2\x3d\x85\x06\x85\x60\x56\x1b\xd2\xfd\x84\xb1\x0f\x94\x64\x75\x40\x4a\x2b\xaa\x95\xe4\x0c\x12\x5c\x72\x29\x65\xc2\x2d\x6c\x9c\xf7\x05\x93\x89\x66\xc9\xa7\xcf\xb9\xb6\x6f\x30\x79\x15\x9e\x82\xcf\xc2\x67\xe2\xc9\xa4\x93\x3c\x45\x9e\x21\x4f\xe0\x31\x3b\x76\x3f\xfa\xd0\x83\x8f\x3e\xfe\x10\x37\xa9\x27\xb6\xdc\x3a\x95\x62\xcb\xcc\xbb\xf8\x3a\x7c\x2d\xd9\x48\x36\x91\x5b\xc8\x8d\x78\x0d\xbe\x96\x9c\x3a\x76\x14\xdb\x30\x9f\xfd\x6c\x7d\x7f\xb5\x89\xf6\x7a\xa3\x86\x77\x88\x6e\x03\xeb\xac\x2a\xd6\xa7\x5e\x95\xb4\xaa\x79\xd5\x68\x5c\x1b\xa4\xdb\xa0\xb1\xaf\xa2\xde\x44\xf7\xa2\x5e\xc7\x20\x49\x56\x07\xa6\xb4\x50\x54\x92\x33\x22\x2a\xaf\x18\x62\xd9\xa0\xef\x02\x5f\xdc\xb7\x15\xfa\xad\xfb\x65\xed\xfd\xe1\xeb\xfd\x56\x04\xe3\x9b\xfb\xb0\x00\xe5\xb6\xdd\x20\xa4\x84\x46\x14\x40\x03\xd0\x02\x94\xae\xc5\x28\x96\x11\x38\xe4\xe0\x62\xaa\x14\xcf\x94\xc2\x2b\x68\xb5\x40\x07\xb5\x60\x30\xab\x5f\xe7\x11\xda\x7f\x04\x3d\x16\x91\xa0\x24\x77\xb0\x76\xaf\x02\x3e\x51\xa9\x24\xc9\x1d\x5e\x25\x0c\x1a\x56\xb5\x52\x07\x0a\xba\x22\xb4\xb4\xa4\x83\xb5\x57\x47\x4d\x33\xd4\x42\x3f\x45\x88\xd3\x37\x04\x2f\x54\x57\x45\x6b\x10\xf6\x53\xa5\x94\x60\xa8\x46\xf2\xd5\xea\xef\x71\xab\x70\x03\xae\xf1\x8d\x1f\xd5\x34\x51\xc6\x15\xb8\x91\xbc\x45\xfe\x5c\xbd\xe2\xda\x32\xf2\x1e\xd9\x8f\xc7\xdc\xba\x39\x78\xd6\x90\xc1\x67\x85\x70\x88\x7c\x1a\x5d\xb4\xa8\x9e\x7c\xc2\xbc\x8b\xcf\xc4\x6b\xea\x46\x26\x06\x8d\xab\x23\x3f\x24\xcf\x90\xe7\xc8\x8d\x03\x56\xae\xac\xc1\xeb\xf0\xf8\x57\xbe\xac\x1d\x58\x5e\x3e\x70\x12\xbe\x03\xdf\x3a\x75\xf2\xe4\xa9\x50\xbf\xbd\x85\x97\xb9\x0c\x0a\xa0\x18\x9a\x87\x54\x5f\x3c\x53\x42\x67\x1d\x8d\x67\x78\x63\xd6\xb4\x1b\x3e\x18\xb0\x66\xed\x08\x40\xe3\xbb\x31\x6b\xd1\x4d\x67\x5d\xe2\x93\xe4\x0e\xb7\x52\x04\x2a\x36\x51\xa9\xc3\x11\x44\x30\x6b\x5e\xff\x9d\x9a\x81\x86\xe4\x86\x0c\x1e\x1d\x95\x07\x85\x1c\x49\xb4\x8e\xa9\xf5\x19\x93\xa6\xd5\xa8\xf4\x6d\x61\xce\xdf\x3e\x54\x96\x5d\x11\xf8\x53\xee\xaf\x1f\xda\x27\x36\xa7\x26\xd8\xdf\xfd\x12\xb7\x3c\xa0\xa4\x52\xb1\xd1\xc5\xe7\x9f\x3b\xed\x1c\x69\xf4\xa8\xe6\xf1\xca\xdd\x4c\xe3\xa7\xb8\x3a\x32\x7d\x7a\x15\x79\xe7\xe3\x4f\xc8\x9f\xea\x9a\x86\x8f\x68\x8e\xe2\xda\xf7\xc9\x97\xa3\xa3\xb1\x48\xb2\x42\xfb\xfe\x8d\x0f\x97\xc5\x87\x35\x36\x9f\x61\xf0\xf6\xdb\x46\xd9\x6e\x41\x8d\x68\x02\x9a\x85\xfe\x07\x4a\xc7\xf5\xf3\xbb\x9e\xe6\x33\x82\x09\x9a\xc4\xa8\xa6\x49\x8c\xd2\x84\x3a\x26\xae\x26\x92\xda\x48\x3e\xdb\x31\x7e\xe4\x18\x5b\x4c\x6b\xe1\xb3\x58\x9d\x5d\x98\xd8\x48\xe0\x58\x66\x42\x11\x72\x72\x31\x75\x82\x4f\xbb\x00\xc7\x32\xad\xa0\xe7\x91\xbe\xa0\xd5\x11\xeb\x40\x17\x9c\x67\x8f\xa9\x13\x13\x6a\x2b\xad\xf2\xaa\xf3\x66\xb5\x8b\x70\x4c\x4b\xb8\x25\x39\xed\x60\xe3\xfa\x51\x38\x41\xd2\x7c\x62\x2a\xa5\x5e\x20\xa7\x5b\xc6\x0b\xfa\x3b\xad\x52\x46\x19\x74\xc6\xb8\x4a\x2a\x75\xd4\x19\xac\xa8\xae\x1f\x3e\x6a\x34\x18\xd9\xe1\xd3\x0f\x14\x51\xa9\x00\xaa\x4f\x56\xd2\x04\x3d\x64\x1c\x23\xa7\x27\xb6\x9e\xa7\xff\xd3\x91\x92\x3a\xb9\xcf\xd4\x48\x73\x8b\xc1\x2c\xdc\x4f\x66\x04\x37\x0d\xd5\xd7\xa0\x9c\x19\x81\x03\xd5\x55\x51\x0a\xef\x86\xcc\xcc\xbb\xd8\xa4\x2f\x4d\x03\x03\xf9\x93\xf3\xee\x1d\x39\x13\xf2\x27\x8f\x6d\x9b\xfb\xd4\xa4\xc9\x4f\x5d\xb2\x7d\x37\xe4\x4f\x66\x8e\xfc\xf9\x34\x33\x7f\x72\x65\x7a\xc6\x54\x15\xf2\x27\xcc\xda\x31\xcb\x2e\x1f\x7e\xd5\xaa\x9b\x5a\x3d\xbe\xcc\x8f\x16\x27\xc2\x0d\x31\x67\x49\xeb\x84\xd6\x19\x1d\x37\x0e\x1d\x5b\x3b\xa8\x96\xe6\x57\x46\xc7\x21\xbf\x72\x9c\x7c\x7e\xd5\xfc\x85\xcb\xb0\xfc\x35\x64\x57\xe2\xa3\xcd\xec\xca\x84\xe9\x93\x5b\xf1\x7d\xfc\x6b\x8d\xf3\xae\x6e\xae\x1b\x5c\xf7\x62\x73\xbd\x3b\x39\x62\x7a\xd3\xf0\xd9\x53\x2e\xfe\x89\xd8\xe6\x19\x5e\xae\xc8\xbe\x62\x83\xf7\xe1\x25\x71\x3a\xaa\x47\x63\xd1\x74\x74\xc4\xd0\xe0\xab\xa6\xb2\x2b\xb2\x51\x67\x5d\x96\xd4\xec\x62\x56\x0d\x25\xd4\x49\xf1\xcc\x64\x08\x94\xd4\x61\x71\x75\x60\x52\x6b\xe2\xb3\x1d\xa3\x9a\x86\xd9\x62\xda\x10\x7d\xa5\xcf\xa7\x90\x6c\x10\x20\xd9\x81\x38\x96\x19\x4b\x57\x7a\xac\x4f\x6b\xa5\xeb\xae\xaf\x74\xeb\x04\x7d\xa5\x5b\x27\xd9\x63\xea\x19\x09\x7d\x17\x04\x70\x4c\xab\x0c\x66\xb5\x19\x38\xa6\x8d\x1d\x08\x27\x43\x14\x18\xdb\x5b\xa5\x0e\x61\xc8\x28\x5e\x7f\x39\x41\x7e\xa2\xd8\x57\x3b\x7c\x04\x44\xb8\x01\xa9\x53\x0e\x95\x55\x27\x9b\x5b\x60\x91\xed\x1e\xb8\x35\x7c\x54\xb0\x87\x95\xa0\x6f\x48\x1b\x36\x59\x92\xb5\x33\x26\xa4\x52\x6a\x93\xa4\x8e\xcf\x6b\xc6\x41\xcd\x3d\xc4\x4a\x70\x94\xfa\x4c\xd5\x4d\x99\xf6\x55\x0b\xc6\xe2\x32\xdf\xba\xb8\x73\x8e\xfd\xfd\xae\x1b\xda\xc6\x8c\xab\x7d\x6a\xd5\x92\xdb\x6f\xbc\xf1\x8e\xa5\xd7\x3e\x15\x3d\x63\x74\xdb\x0d\x77\x7e\x7d\x8c\x9c\x20\x27\x1f\xbd\xe1\xfa\xc7\x09\x21\xc7\xf1\xab\x55\xc3\x17\xcd\xe8\x6b\x45\x3b\xd7\x25\xc6\xd5\x0e\xaa\x65\x46\xe0\x62\x5c\x3e\xf2\x40\xb9\x9b\xec\x4a\x3f\xb5\x71\xe3\xd3\x1a\x6e\xf3\x94\x1d\x18\x49\xfe\x4c\x3e\x24\x47\xc8\xef\xaf\xba\x0a\xd7\x73\xa7\x12\x67\x2d\x1c\x5d\x63\x2c\xe5\xd0\x11\xe7\x0d\x1d\x3e\x6b\x6a\xfb\x66\xa1\xcd\x35\xa2\x02\x96\x92\xf2\xd6\xd8\x46\x89\xe3\x50\x02\x8d\x45\x8f\x7f\xf7\xcc\xa3\x3a\x3a\xae\xa6\x92\x99\xa1\x74\x5d\x87\xfa\xb4\xb1\x6c\x56\x6b\x19\x91\x48\x60\xf5\x8c\x6f\x49\x49\x8e\x33\x52\x92\x4f\x88\xec\x90\xe4\xd0\xd1\x74\x69\x32\x42\x64\xf0\xf0\x51\xfa\xeb\x62\x39\x53\x59\x33\xb0\x29\x65\x3d\x89\xf9\x9c\xa4\x04\x39\x49\x6d\x28\x4d\x57\xfe\x4b\xb9\x49\xdc\x14\x09\x88\xd5\xd1\x6a\xfa\xf5\x2f\x64\x2a\x99\x33\xd8\xb1\xd3\x87\x35\xde\x93\x68\x69\xbc\xb7\xb1\xe5\x9f\xcb\x5b\xf2\xf3\x66\xce\xdc\xbd\x68\xd1\xa2\x45\x88\xa1\xf9\x4b\x7e\x07\x0a\xa3\x28\xba\xad\x8f\x0c\xa6\x5a\x1b\x57\x2b\x93\x99\x12\x6a\xe0\x12\x9f\x16\x65\xb3\x5a\x79\x95\x6e\xe0\x01\xdf\x92\xda\xac\x37\x52\x9b\x19\x3e\x5c\x5c\x52\x0b\x72\x67\x52\xc6\x16\x2a\x8a\xd4\x80\x06\xb8\xdc\x11\x08\x96\x56\x82\x79\x0b\x72\x9c\x5a\x49\xad\x24\x6b\xc5\x65\xa7\xcf\x76\x2a\xdd\xcc\x77\xda\xdc\xe7\xc8\x42\x3b\x9d\x3e\x11\xca\x4f\x31\xed\x82\x75\x5f\x11\xf8\xa6\x43\x7a\x6c\x1d\x30\xfd\xc4\x00\xe8\xc2\x07\xf4\x7d\xe8\x05\xc1\x01\xaf\x6c\x8f\x15\x30\xfc\x04\x80\xe1\xa7\xa8\x90\x05\x1f\x70\x41\x4a\x1e\xa1\xf9\xf5\x9b\x80\x73\x78\x01\xc7\x12\xbd\xdf\x4e\x7e\x0f\x6d\x02\x06\xf1\xf4\x7b\x1f\x2f\xbc\xe8\xd7\xb3\x5f\x3a\x84\x1f\x18\xde\xd1\x4a\xf6\x92\x7b\xc8\x0f\x29\xe3\x34\x50\xfe\x9c\x38\x46\x42\x8a\x94\x63\xf0\xff\xc0\x1b\x0c\x3d\x4b\xa8\xdf\x0b\xa0\x76\x94\x97\xaf\x94\xe3\x19\x0f\xa8\x7f\xa7\x3d\x90\xcc\xf4\xf8\xec\xb1\x82\xbe\x1f\xfd\xe4\x03\x35\x6d\x6f\x5e\x4d\x3b\x6d\xf3\xb0\x30\x5e\x8f\xa1\x5f\x6f\xc8\x58\xf6\x51\xbb\x67\x28\x0b\x46\xa4\x3a\xab\x6e\xef\xd1\xcb\xbe\xff\xbd\xf5\xab\xd6\x6e\x20\xfb\xbb\x08\xa1\xf5\x7a\xd3\x3e\x1a\xf7\xcb\x5f\xde\xb7\xbb\x36\xe7\xc2\x7f\x50\x70\x05\xc2\xe8\xb2\x53\x27\xb8\xd5\xbc\x03\x29\xa8\xd2\x60\x0c\xe0\x21\x21\xe5\x8f\xd3\xea\x16\x5e\xd2\x43\x78\xa8\x6e\x51\x5a\x78\xa5\xb6\x85\x57\x42\x2c\x2f\xd6\xc2\x57\x54\xb9\xec\x6c\x5c\xf1\x0a\xf9\x60\x02\x2e\xeb\x5c\xd7\x89\x2b\x26\x91\xa3\xaf\xe1\xd2\x09\xe4\xfd\xcc\xfa\x0c\x53\xbd\x66\x07\x9e\xbd\x63\xed\x0e\x9c\x3a\x87\xfc\x76\xc7\x9a\x1d\x64\xe7\xce\x35\x3b\xc8\xab\x93\xf0\x08\x84\x51\x86\x5b\xc3\xbe\xcc\xef\x43\x3e\x34\x08\xa9\xce\x78\x86\x81\x4d\x9e\x76\x02\x41\xb5\xd3\x63\x8f\xa5\x19\xa7\x7e\xda\x33\xbc\x1d\x52\x76\xba\x6d\x68\x05\x5d\xa4\x99\x96\x82\xd1\xca\x8f\xcc\x52\xbc\xd7\x31\x6f\x69\x73\x8a\x34\x09\xcd\x43\x86\x25\xb9\x13\xd7\xb4\xaf\x4c\x4d\x8c\x25\x27\xd0\x38\xfc\x2b\xee\x10\xe7\x02\xfd\x95\xdd\x48\x45\x71\xd5\x45\x6b\x91\xd8\x44\x87\x0f\x23\x5b\x4c\x95\x92\x9a\xc8\x67\x55\x21\x01\x4b\xe1\x3e\x98\x71\xc1\xcd\x63\xc6\xe4\xf2\xd9\x2f\xee\x82\x78\x92\x6d\x50\xa5\x06\x8f\xca\xfa\x34\xa5\xf4\x1b\x5e\x95\x7c\x9a\x50\xfa\xcd\x53\x7e\xc7\x4b\xc3\x50\x20\xe6\x54\x59\x5f\x07\xc7\x0a\x4a\xac\x83\xd7\xff\x5f\x55\x7c\x1d\xb2\x22\x29\xb1\x34\xc7\x16\xf0\x06\xa8\x7c\x2a\x2d\x2b\x12\x50\x07\x28\x1c\x2f\x43\xeb\x62\xa7\xc2\x72\xbc\x20\xc1\x37\x66\x70\x0f\x35\x4d\x09\xb8\x49\x70\x19\xae\xa6\xd7\x88\x50\xfd\x95\xa7\xf5\xa6\x55\x57\x0d\xbf\x7c\xd9\x98\x4e\x67\xac\xa1\xfc\x9c\x49\x37\x3f\xc9\x1d\x7e\xa9\x76\x70\x5d\xf3\x35\x97\x36\x8e\x18\x5a\x54\xde\x02\x73\xc6\xfb\xb8\x97\x58\x4e\x98\x89\x24\xd4\x80\x54\x6f\x3c\xe3\x31\x20\x4a\x68\x2f\xc8\x38\xe9\x65\xea\x44\xba\x79\x9d\x5e\xa0\x02\x87\x0e\x83\x21\x8d\x66\x2d\x31\x08\x55\x86\x02\x0d\x18\xef\x9b\xd1\x3a\xa1\xb5\x76\x70\xed\xf8\xc6\x1f\x3c\xc1\x77\x9e\x33\x6b\x78\x53\x49\xb1\x24\x29\x95\xc3\x5d\x6d\xc2\x66\xfd\xb3\xf6\x72\x2f\xb1\x8c\xf9\x59\xf6\x78\xc6\x91\xff\x2c\xf7\xc1\x8c\x40\x3f\xcb\x2d\xe8\x9f\xe5\xb6\xdb\x63\x2a\xea\xf9\x59\xd6\xad\x88\xf7\xea\x57\xdb\x13\x3f\x18\x72\x56\xed\xe0\x5a\x3e\xdb\x34\x7c\xd6\x39\xf3\x36\x0b\x6d\xce\x11\x95\x8a\x24\x15\x23\x84\xc9\x35\x82\x1f\xdf\x22\x4e\x47\x01\x54\x87\x40\x1e\x25\xa9\x39\xf8\x6c\x87\xec\x70\xdb\x62\x1a\xcf\x9b\x98\x4a\x26\x00\x4b\xa8\x7f\x46\x5f\xbe\x16\xb9\xa6\xb7\x9f\x24\xf8\x13\x79\x7f\x67\xe8\x08\x64\x43\xf5\xe4\x05\xf1\x05\x7e\x0b\xf4\x29\xd7\xa3\x16\x34\x1e\x4d\x47\x73\xd1\x52\xfc\x23\x94\xae\xd0\x5d\x9b\xb6\x64\xa6\x8e\x9e\xcb\x17\x27\xd2\x75\x15\xfa\xae\xad\x2b\xb5\xc7\xd2\x55\xe7\xcf\x4a\x24\x12\xea\xd0\x78\x66\x30\xdd\xd1\x43\x07\xeb\x3f\x1b\x3a\xd0\x1e\x53\x87\x24\xf4\xe3\xe9\xdc\x64\x46\xa2\xff\x72\x62\x22\x5d\x04\x0c\xcf\x45\xfa\x7e\xf7\x9f\x35\x59\xff\x97\x8e\xb8\x7a\x45\x32\xc3\xd2\xdf\x98\x9f\x48\x3b\x58\xb3\x7d\x26\x2d\x5c\xba\x48\xff\x8d\x33\xe2\x99\xe1\xf4\x6f\x9f\x31\x5c\xff\xd9\x19\xc3\xec\x31\x75\x54\x02\xab\xcb\x68\x31\x30\x75\x9d\xdc\xb4\x04\xb0\x34\x91\x29\xa1\x6f\xd4\x03\x6f\xb8\x88\x63\xfa\xaa\xe8\x6f\x08\xe0\x40\xa9\xd5\x89\x8c\x9f\xbe\x51\x95\x50\xfd\xe0\x7e\xa9\xc3\x12\x99\x16\xfa\xde\xf8\x84\xda\xe2\xd3\x1a\x71\x4c\x1d\x9d\xc8\x0c\xa1\xef\x8d\x4a\xa8\x43\x7c\xda\x59\x38\xa6\x9e\x9f\xc8\x4c\xa7\xef\xcd\x4d\xa8\xd3\x7d\xda\xa5\x38\x96\x59\x4a\xdf\x58\xea\xd3\xa6\xe0\x98\x3a\x3b\x91\x99\x4c\xdf\x98\x95\x50\x27\xfb\xb4\xc5\x38\x96\x59\x44\x1f\xb1\xe5\x38\xa6\x95\xe8\x61\xac\x83\x4d\xa5\x34\x41\x94\xe4\x0e\xa9\x08\xfc\x6d\xad\xb1\x45\x92\xb5\xc1\xc3\x53\x29\x6d\xe9\xa5\x92\xdc\x71\x6e\xdb\xc5\x13\xf5\xb7\x27\x4f\x91\x64\x6d\xfe\x15\xb4\x96\x96\x46\x32\xc6\xc3\xd1\xfd\x3b\xb6\xdb\x77\xb8\xfb\xcf\x9a\xfb\xff\x51\xf7\x3f\x59\xf8\x8b\xf5\xfc\xc2\xc5\x73\x56\x0a\xd3\xf8\x91\xe3\x5b\x13\xfc\xa2\x6e\xdf\x4d\xe9\xf6\x1d\xfe\x92\x5f\xa0\x7f\x7b\x2e\x3f\xf2\xac\xd6\x04\x3f\xd9\xf9\xf2\xc5\x2b\x44\xe3\x1b\x7c\xfc\x34\xff\x70\xa5\xf3\x15\xf3\x9b\x24\x8f\xf7\xce\xbe\x6c\xd1\x9c\xc1\xb1\x68\x23\x71\xcd\xbe\x7c\xd1\xc5\xfa\x2b\xf6\x1d\xf3\xd5\x49\xef\xac\xcb\x17\xcd\x19\x34\xa8\x3e\x2e\x78\x5e\x5c\x78\xb1\xfe\xe2\xa4\xad\xf7\xaf\x91\xf0\x8b\x97\xcd\x1e\x34\x68\xc0\x10\xd8\xcf\xeb\xc4\xb5\xfc\x5b\x48\x44\x1e\x14\x44\xe5\xa8\x0e\x0d\x46\x4d\x68\x14\x5a\x87\xd4\xe6\x78\x66\x18\xdd\x6e\x38\xa1\xf2\x95\x07\x25\x75\xa4\xb5\x01\xeb\xe2\x58\x77\xf3\x2a\x0e\xaa\xa1\x44\xa6\x96\x2e\x64\xb8\xf2\xa0\x64\x6e\xaa\xea\x84\x36\x06\xc7\xb4\x70\x05\x48\xd5\xab\xb5\x92\x56\x5e\x95\x4a\xa9\x25\x54\x83\xbf\x99\x97\x64\x95\x03\xaf\x0d\x8d\x48\xa5\xd4\x61\xb2\xda\x92\x52\xeb\xa4\x8c\xac\x44\x63\x83\x69\xa0\xda\x14\x0c\x05\xc4\x06\xac\x34\xb7\x84\xfc\x82\xa8\xb4\x04\x43\x62\x55\x03\xc6\xcd\x2d\xc9\x90\x07\xeb\x4b\xd2\x92\x14\xc4\x6a\x7e\x68\x73\x4b\x48\x10\xd9\x96\x50\x39\x0e\x89\x75\x4a\x53\x4b\x39\x0e\x05\xea\xea\x8f\xac\xf7\x8c\x7b\xee\xea\xdf\x5c\x39\xff\xe9\xcd\xca\x99\x6b\xa6\xcc\x93\x86\x4d\x63\x94\x26\x69\xb3\x53\x3a\xbb\xe6\x52\xe5\x9c\x8a\x4b\x87\xca\x9b\xf1\x33\x8f\x6d\x3d\xeb\xe3\x31\xa9\xb9\x4a\xdd\xec\xd0\x99\x3f\xbd\xdd\x33\xe1\xb5\x33\x8e\x30\x4d\x97\xd2\x5f\xcb\xed\xb9\xe6\xdc\xb9\xa1\xf6\x24\x3f\xf8\xec\x57\xe6\xcf\xbb\xf0\xf9\x6f\x4e\xc2\xdf\x3c\x57\xe0\x26\xbc\x76\xc6\x1f\x6e\x5c\x1b\xba\x68\xd8\xf8\xad\x0d\x5d\xcf\xce\xe3\xc6\xbd\x38\xea\xec\x3f\xe2\xbf\x6f\x76\xea\x7f\xb7\x09\x31\x68\x0f\x69\x13\x63\xe2\x16\xa4\xa0\x08\xfa\x81\x51\xa7\xe9\xce\xf3\xab\x56\xc4\xb5\x22\x4f\x36\x5d\x04\x87\x43\x51\x89\x3d\x66\x2a\x6c\x1a\xfc\xaa\x7e\xe0\x57\x0d\x50\x0a\x03\x8f\xc1\xaf\x5a\x8d\x63\x1a\xeb\x97\x68\xe9\x9d\x1a\x90\x54\x25\xa5\x7a\xe4\xb4\x58\x52\x61\x14\x75\xba\xdc\x12\x80\x5c\x56\x71\x88\x43\xaa\x09\x75\x27\x59\x85\x72\x84\xd3\x11\xad\xe2\xd6\x34\x79\xe4\x99\x42\xba\xd5\xf9\x0b\x7b\xd2\xad\x9e\x9c\x91\x9b\x82\x77\xf5\xa6\x5c\x85\xbe\xec\xe5\x42\xab\x30\x06\x49\xa8\x12\xfd\xc8\x98\xb7\x2b\xcf\xe1\x50\x16\xd7\x82\x9e\x6c\x3a\x08\xec\x18\xc1\xb0\x3d\x06\x52\xb6\x91\x42\x0e\x07\xa5\xf2\xa0\x04\xd2\x30\x72\x5c\x53\xf2\x06\xb0\x29\x94\x5c\x06\xea\x2d\x78\x4a\x98\xa1\x4a\x60\x00\x21\x5c\x46\x39\x1c\x3a\x9c\x2e\x5f\x71\xc1\xfc\x6d\x76\x9f\x35\x7f\x5a\xd1\x4a\xa7\xdf\x83\xcd\x21\x5f\xdb\x8a\x63\xb7\x93\x3f\x6e\x32\x49\x1d\x7c\xf6\x59\x2b\x16\x2f\xb0\xe1\x40\xe0\x6f\x1f\x3e\xb8\x77\xb1\x55\xeb\x4a\x5b\x1f\x4d\x66\x87\x25\xad\x97\x5c\xf4\x9b\x5f\x4e\xba\x9b\xd6\xb9\xc5\x0d\xde\xb0\x7f\xa2\x5e\xcf\xf5\xff\x52\xbd\x5e\xbe\xd6\xb9\x57\xbd\x5e\x7c\x13\x6e\xc6\x31\xf2\xf6\xf5\x56\xbd\x5e\x33\xe5\x1c\xe3\x22\xe4\x67\x3f\x23\xf7\x41\xbd\x5e\xa4\xeb\x48\xbe\x5e\x8f\x43\x88\xdb\x0e\xbd\xd2\x90\xc5\xb2\xea\xf5\x90\xa1\xa0\x4a\x8b\xb6\x33\x61\xbb\x17\xd3\x22\x3d\xa8\xdf\xfe\x9f\xae\xd3\xb3\xe6\xd0\xab\xe5\x13\x8a\xb5\x57\x93\x8d\xb4\x99\x31\x77\xcc\xa8\xd3\xe3\x96\xbf\xf2\xee\xbb\xaf\x90\x31\x3b\x76\x92\xfb\xb8\xe5\x5d\x0b\x68\xa1\x5e\x9e\x7b\xd4\x8b\x4a\xd0\xdc\x42\xee\xd1\x12\x57\x36\xe3\xf1\x01\xf7\xa8\x27\xaf\x0b\xe1\x0d\x64\x55\x5f\x42\xf5\x52\x19\x08\x9e\xca\x40\x68\x21\xa3\x97\x9b\x97\x54\x87\xee\x69\x5b\xac\x57\x3e\x49\xb3\x39\xe9\x59\xd6\x8d\x12\x3d\x24\x46\x85\x18\x0e\xe3\x64\x4b\xb4\x25\xd4\x8d\xa1\xf4\x92\x8b\x67\x6e\x5d\xd9\xf6\xbd\x9b\xb6\x84\xa6\xdc\xb3\xb0\xde\xe0\x29\x5d\xff\xfa\xe8\xb5\x57\xed\x08\xe4\x8e\xb3\x02\xb3\x74\xd9\x6d\x4d\xb3\x97\x5e\x86\x0a\xb8\x0d\x42\x94\x79\x46\x32\x75\xd7\x2c\x6e\x03\xe0\x35\xa0\x38\x68\xc8\x0b\x74\xee\x21\x1f\x3c\x1c\x8e\x00\x85\x42\x43\x48\x92\xd3\xac\x02\x05\x57\x55\x52\x9a\xf3\x8a\x86\xb0\xb0\x27\x85\x34\x09\x99\x92\xa7\x25\x52\xda\x45\x7f\x09\xcb\x1d\x2c\xe7\xa8\x35\xa4\xe2\x92\x21\x53\x21\x10\x66\x94\xa7\x3a\x18\x81\xcd\x89\x19\x7c\x07\xbe\xe6\xed\xf3\x5f\xf9\xd3\x96\xf6\x07\x96\x0c\x1d\x45\x39\x0f\x24\x79\xdd\x23\x57\x84\xf2\xc4\x07\xe7\x9f\x4f\xde\x24\x9f\x93\x03\xdb\xd6\x5c\xbb\xd9\x67\x91\x1f\x30\x0f\xac\xd9\xd0\xba\x04\x08\x10\x28\xff\xf9\x5a\xe1\x18\x12\xcd\xea\x37\x8b\x78\x36\x8d\x05\xb3\x1e\xb4\x07\x07\x2d\xa3\x2f\x53\x51\x2f\x0e\x5a\xe6\xd7\xd8\x95\x5b\xc1\x77\xe2\xe6\xdc\x1b\x27\x27\x19\x9c\x50\xfb\xf9\xdb\x0a\xfe\x36\x63\x10\x4f\xa4\x19\xf8\xdb\x4c\xe1\xdf\xf6\xe6\xff\xb6\xd4\x8b\x83\x82\x29\xc5\x0a\x61\xb8\x76\xdc\x98\xfb\xb8\x6b\xa3\xc1\x95\x30\x0d\x38\xe0\x66\x98\xfa\xc2\x30\x6e\x57\x36\x83\xb0\xcb\x78\xbc\x91\x2b\xab\xda\x13\x40\xa3\xe3\x82\x47\xc3\x19\xe8\xa1\x2c\xdc\x31\xd6\xc9\xdb\x63\x69\x97\x13\xb4\x02\x90\x3d\x06\x62\x32\xf0\x2c\x14\xd0\xb8\xc7\x37\xb1\x5b\x73\x0f\xe0\x2d\x64\x39\x79\x83\x99\x41\x98\x05\x84\xdc\x4b\x72\xbb\x99\x19\xc8\xec\xaf\x60\x9f\x85\xfe\xd1\x19\x05\x5a\xc7\x9a\xe0\xe8\x36\x16\x5b\xcf\xb1\xf4\x54\x39\xfe\x96\xb1\x04\xe8\x58\xb8\x4d\x6c\x23\x41\x78\x0a\xc9\x90\xfd\x78\xfb\x27\xf8\xc0\xf1\xc3\x9f\x90\x76\xbc\x1d\xb8\x31\x11\xbf\x1a\x34\xb5\xe6\x76\xe3\xf1\x77\x65\x55\x6f\x5c\x0b\xb8\xb3\x99\x12\x11\xca\xed\x4a\xdc\x56\x4b\x6e\x39\xa5\xb3\x2f\x87\xda\x88\x72\xd6\x1e\x53\xcb\x29\xdf\x9f\xd3\x4b\xfb\x71\x8b\xca\x25\x39\x2d\x7a\x65\x88\x77\x51\x00\x34\x98\xcd\xc6\xb9\xe6\x64\x82\x93\x03\x40\xc8\x51\x47\x79\x6a\x69\x55\x89\xb4\x47\xb7\xd7\x95\x77\xbd\x80\x1b\xef\xd9\x7c\xf2\x9e\x65\x9b\x27\xad\xbf\x69\xf3\xf6\x0f\xff\xd1\x34\x89\xef\x24\x64\xb9\x6b\x17\x39\xb0\xef\x25\x72\xe8\xc1\x60\x18\xfb\xe2\xfb\xd4\xdf\xbe\xe6\xce\x7d\x05\x35\xfe\x0e\xe0\xcc\x29\x43\x97\x75\xeb\xe8\x73\xd0\xf1\xb3\xd9\x4c\x31\x1d\x7f\x71\x9e\xb2\xb0\x0c\x3a\xba\xd2\x65\x30\xfe\x32\x7d\xfc\x65\xc6\xf8\x15\xca\x57\x08\x65\xad\x20\xc6\x59\x24\xa5\x45\x6f\x20\x3f\x0f\xd9\x9c\x47\x40\xf7\x28\x8d\x79\x44\x0d\x5d\x28\x5f\xa4\x4a\x94\xb6\xe9\xa6\x9e\x34\xf9\x81\x93\x3f\xbe\xfe\x4f\x77\xdc\xfa\xbd\xc1\xab\x1b\xaf\x5e\x4b\x5e\x1e\xd8\xc0\xb5\x1f\xff\xc2\xf5\x13\xd2\xf5\x68\x07\x21\x37\x25\xb1\x58\x54\xfe\xd0\xcf\x70\xa3\x40\x6e\x31\x72\xcc\xa4\xcd\x26\xf3\x9d\x28\x80\x66\x19\x95\x74\x5e\xb9\x3b\xb7\x7f\x30\xae\x2a\xc0\xa3\x25\xcb\x66\x1b\x10\x54\x45\x29\x14\x63\xf0\x00\xc6\xe0\x70\xea\xa7\x83\x5b\x52\xed\x29\xca\x16\xf1\x04\x27\x3a\x5d\x92\xbf\x37\xcd\x16\xf0\x13\xf6\x45\xff\x8f\xa7\xe3\x51\xe4\xed\x47\xfa\x52\x00\x20\x32\xf8\x11\xa6\x0a\x00\x1d\xf7\x72\x71\x26\xd7\xde\x6b\xdc\xf8\x5b\xc7\x2d\xe5\xc7\xad\xd9\x1c\x30\x6a\xcd\x09\x89\xc0\xef\x36\xee\x5e\x14\x61\x01\xec\x20\x9f\xfd\xb4\x2f\x96\x30\x72\x8f\xee\x00\x58\x4c\x61\xa6\xde\x35\xd5\x2f\x48\xa1\xdb\xa9\x82\x41\x66\x08\x8d\xc4\x4c\x11\x03\xb5\x25\xae\xd5\x7b\xba\x6b\x19\x0c\x8f\xab\x83\x0e\x66\x86\x52\xf5\x71\x7b\x22\x3d\x68\xa8\xbe\x87\x06\x95\xda\x01\x34\x2d\xa2\x77\xa4\xa5\x73\xa0\x8d\xc0\x31\x6d\xe8\x20\x49\xee\x60\x7d\x35\x43\xc0\xd1\xf1\xd5\x4b\x72\x3a\x3a\x68\x68\x2a\x95\xd2\x4a\x87\x48\xb2\x26\xbb\x53\xa0\x2f\x4f\xf5\x0e\x64\xd0\x3b\xf8\xce\x4a\x07\x8a\xf1\xfc\x44\x93\x46\x9b\x64\xf4\xdb\xb5\x0f\x5e\x1a\xd9\x52\x3d\xb8\xf5\xec\x8e\x73\xc7\x55\xff\xf8\xaa\x49\xd3\x4f\x2b\x85\x70\x62\xbd\x3c\x60\xe0\xd0\xa5\xe3\x46\x4e\x9e\x16\x5f\xbc\x2e\x84\x18\xd4\x4a\xfc\x06\xc7\xda\x08\x74\x0f\xcd\x14\x64\x12\xd4\x6e\x26\xd1\x9a\x9a\x8a\x6b\x31\x4f\x77\xbe\xb5\x91\x71\xb5\xe1\x60\xa6\x99\xda\xad\x19\x42\xd7\xbe\xd9\xd7\xd4\xfa\x84\x36\x0a\xc7\xb4\xe6\x06\x49\x4e\x2b\xc5\x09\xdd\x4e\x05\x64\x6c\xd1\x98\x24\xa7\xeb\x1b\x9a\xf5\xb7\x9d\x09\x49\xd6\x10\x50\xb2\x49\x06\x25\x9b\x0c\x94\x6c\xff\x04\x19\x5b\x6f\x03\x7e\x0b\x3d\xdb\x85\xdd\xad\x77\x5a\xb6\x36\xf2\x45\x77\xeb\x99\x1a\x3d\xef\xf3\x9d\xc8\x63\xe9\x4a\x38\x0b\x34\x0e\xbc\x56\x8a\x98\x49\x18\x64\x01\x40\xfc\xec\xd3\x7d\x05\x8f\x24\xa7\x39\x41\xa4\xb1\x83\xca\x9b\x5e\x33\x2b\xda\xdc\x96\xd7\x5c\xf0\x88\x58\x3a\x08\x78\x29\x9e\x40\xde\xde\x93\x97\x42\xc8\x3f\xc6\xa6\x76\xed\x72\xbe\x89\x6b\xef\x31\x26\xdc\x7d\x4c\xde\x6e\x63\x92\xf2\x63\xd2\x38\x01\x46\xa4\x89\x7c\xaa\xdf\x31\x25\xe9\x98\xf2\x0d\x74\xf5\x27\xc8\x67\x9b\xf2\x2c\x68\xf9\x27\xd4\xe0\xb6\x9f\x06\x7c\xd5\xe3\x0b\x22\x12\x90\xa4\xcb\x6b\xff\x16\x56\xb2\xeb\x9e\xad\x97\x06\xb1\x62\xb7\x4e\x3e\xc9\xac\xf8\x1c\x83\xa5\x64\x80\xb6\xf3\x05\xaa\x25\x51\x37\xce\xf5\xcc\xcd\x98\xc3\x33\x09\xc3\x30\x64\xdb\x29\x74\xf3\x0d\x7c\x67\x6e\xfe\x6e\x06\xcf\x7b\x0a\x4f\xc8\xad\xee\x3a\x80\xef\xfb\x23\xde\x39\x3b\xf7\xb5\xc5\xb9\x07\xbc\x9b\xb2\x35\x26\xd3\x46\xb6\xa4\xc9\x5d\xa3\x1f\x70\x85\x62\x65\x19\x8f\x01\xce\x24\x28\xbb\x70\x8f\x31\xb5\x48\xc9\x40\x8b\x3e\x24\x36\x50\x2d\x45\xa5\x6d\xb8\x74\xfe\x96\x3d\x78\x24\x74\x17\x3e\x75\x68\xcb\xa5\xba\x6d\xd6\xe0\x91\xeb\xb3\xb9\x8f\x72\x4f\x61\x87\x8a\x17\xac\xd6\x0f\x2f\xf0\x1d\xf8\x5a\xe0\x88\x6f\x47\x69\x05\x41\x55\x1a\xcd\xe7\x38\x93\x19\x8c\x94\x1e\x81\x4a\x00\x0e\xe0\x6e\x81\x8a\x62\x39\xf9\x0a\x38\xf9\x0a\xa2\xc2\xa4\x48\x43\x8a\x24\xa7\xed\x6e\x5f\x41\x5b\x7e\x32\x50\x2d\xb5\x50\xdb\x89\xe0\x4c\xe0\xe6\x4d\x9b\xae\xc7\x3f\x31\x6d\x47\xd6\x6f\x20\x6f\x70\x8d\x64\xe3\x46\x42\x3e\xda\x8d\xbf\xd0\x8d\xc7\x5c\xd6\x9e\xfb\x9a\x6b\xb4\x7c\x1d\xee\x6b\xc1\x8f\x82\x68\x9e\x51\xfb\xe3\x4b\xd2\x16\xe8\x5e\x0d\xa5\x21\x10\x24\x66\xa8\x20\x31\x8c\xd5\x10\x24\x16\xf3\x82\xc4\xfa\x58\x8b\x0c\x15\x62\x4d\xbf\xf0\x90\xe6\x86\x97\x72\x37\x2a\x01\x49\x4c\x16\x8e\xda\xe8\x1d\xf5\x71\x37\xe1\x14\x9e\x49\xc6\xe3\x43\x64\x1b\x79\x76\x83\xd9\x40\x4a\xd2\x64\x17\x9e\x41\x4a\x72\x1b\xf1\xcb\x97\x93\x1d\xdc\x6e\xa3\xee\xeb\x08\x3c\xab\x67\x18\x9d\xbb\x36\xab\xc3\x42\x43\x86\x46\xa7\x9b\x8a\x47\x31\x89\xb4\x1b\xbc\x32\x37\xa2\x32\x9d\x48\x43\x6e\xdd\xa9\x17\x1d\x60\xca\x30\x8e\x14\x1a\x91\x59\xb3\x06\x6f\x2e\x34\x20\xc8\xbb\xe5\xe6\x77\x33\x5f\xc6\x18\xc3\x6d\xa0\x2b\x7d\x86\xd5\xc3\x68\x3e\x9b\x1a\x12\x69\xa3\xba\xf3\xa0\xe6\x90\x29\x29\xb8\xc3\x24\x05\xd7\x2f\x59\xa4\x21\xa7\x3e\x06\xc1\x0e\x63\x90\x9a\x0a\x28\x36\x99\xf5\x78\x37\x1e\x41\xce\xc6\xef\x91\xa7\x49\x0b\x79\x9f\x5d\x7d\xb4\xb0\x8b\x95\x5d\x6d\x69\x8a\x09\x5b\x20\x2e\x9b\xd1\xe3\xbc\xe2\x01\x58\xb2\x74\x37\x7c\x56\x5c\xc6\x24\x8c\xae\x12\x43\x77\x43\x77\xd1\x1d\x4e\x7a\x90\x01\x63\xba\xa7\x37\x83\x7d\x0f\x41\x0e\x3d\xf6\xcd\x8b\x72\x18\xf0\xc5\xaa\xdc\xa6\xfc\x79\xf5\x02\x70\x2a\xcd\xe8\xf1\x2c\x16\x8c\x49\xcc\x8f\xc9\xdb\x73\x4c\xde\xfc\x98\xa4\x6f\x1f\x93\x41\xe4\x87\x03\xe4\x53\xb2\xcf\x24\xf3\x33\x30\x85\x7d\x24\x69\x69\x42\x09\xbb\x21\xb6\x68\xcd\xb3\xc1\xf0\x46\x67\x80\x8d\xcd\x66\x58\x17\x74\xe4\xb0\x79\x11\x34\xca\xe3\xae\xba\x41\x81\x45\x1f\x97\x2d\x90\x4d\xdb\xc0\x93\xb7\x89\x96\x27\x9f\xec\x6d\x1f\x66\x0d\x79\x2a\x6f\x1d\x42\x4e\x4e\x29\xb0\x0d\x42\x82\xaf\x1b\x37\xa8\x3e\x0e\xa3\x12\xdf\x26\xe6\xc7\x21\xe6\xc7\xe1\x35\xc7\xe1\xa0\xe3\xb0\x7b\xb3\x69\x3b\x6c\x24\x7b\xaf\x71\x04\x0a\x6c\xc2\xdc\x45\xee\xcb\xd3\x1b\x1e\xed\xda\x08\xe6\x80\x98\xc2\x76\x2f\xdf\x89\x2a\xd1\x95\xc6\x18\x4a\x0d\x6d\x92\x0a\x36\xab\xba\xe3\x9a\xe2\xce\x66\xc2\x3c\xac\x53\xd8\x6d\xb1\x14\x57\x06\xb2\x6a\xa5\x0f\x02\xf9\x52\x6a\x1a\x43\x9a\xd7\xee\xa5\x50\x52\xb0\x54\x92\xd3\x3c\x9c\x4d\xf4\xa0\x52\xa5\x14\x15\xe9\x65\x8d\x65\xeb\x37\xb8\xa0\x82\x27\x73\x56\xee\xfc\x35\xae\xba\x7d\xf3\xc9\x7b\x96\x6e\x9c\xb6\xfe\xa6\x0d\xbb\xde\x3e\x3a\x7c\x1e\xd9\x4b\xbc\x7c\x67\x6e\xa9\xef\x57\xe4\xad\x37\xf5\x08\xc3\x5f\x82\x7d\xf1\xb7\x1f\xf9\xed\x6b\x81\x5c\x17\x28\xa3\xd0\x3d\xe7\x10\xde\xe6\xda\x51\x39\x5a\x61\xcc\xa9\xd8\xe0\x44\x2c\x13\xa9\x38\x32\x9b\xcd\x84\x59\x3a\x27\x36\x5b\xd8\x48\x57\x4e\xb9\x07\x8a\xa9\x99\x8b\x29\x94\x62\x53\x68\xa8\x54\x5c\x22\x51\xee\x1c\x35\x20\x69\x2e\x19\x66\x46\x39\x74\x34\xd6\x25\xc9\xaa\xcd\xbc\x2c\x7a\x45\x1b\xba\x6f\x63\x90\x2d\x1e\x9e\xf6\xb3\x2f\x7e\xb8\xfa\x4f\x77\x41\xb8\xb1\x72\xdd\xcf\xef\x16\xc8\x7e\xb2\x89\x6b\x27\x15\xdc\x2d\x24\xf7\x68\xc7\x29\xb4\xd1\x88\x38\xee\xba\x8f\x00\x1f\x98\x51\xbf\xb5\x9b\x3f\xc1\xef\x43\xf5\x68\x28\xfa\xa9\xc1\x98\xeb\x61\xb3\x6a\xb5\xee\xbe\x96\x9b\x72\x5e\x76\x57\x36\x1d\xd4\x27\x9a\xb0\x65\xb1\xda\x54\x98\xe3\x54\x70\x4c\x1b\x28\x65\xd5\x81\x3e\xa8\xe5\x0b\x4b\x59\xad\x59\x7f\x4b\x91\xe4\x27\x44\x3b\xeb\xf1\x41\x9e\x7f\x88\x94\x0e\xd6\x42\x8d\x4e\x58\x4e\x97\x96\x57\xd3\x2c\x68\x54\x92\xd3\xa5\x95\xb5\xfa\xdb\x09\x29\xe3\x44\x4a\x78\x70\x4d\x28\xa5\xd9\x83\xa6\x82\xb0\x51\x0c\x50\x57\x5d\x49\x0b\x35\x28\x0f\x12\x4d\x33\x05\x8d\xce\x42\x5a\xa8\xe1\xa7\x45\x50\xd5\x55\xc2\x2a\x7c\x16\x1e\x3d\xec\xf6\x86\xd6\x39\xad\xa4\xf3\x35\x2d\x2c\x8c\x99\xfa\xea\x73\x4f\xff\x6e\xde\x8a\x86\x71\x53\xc6\x8f\xbe\xfa\xd1\x2d\x97\xdd\x4e\xde\x20\xf7\xb3\x73\x86\xd5\x8d\x9a\x74\x55\xcb\x68\xe6\x75\xbc\x16\x6f\x0c\xcb\x9f\x97\x11\xee\xc3\x93\xdc\x94\xbf\xad\xfd\xcf\xf7\xbf\x3c\x74\xdb\x3f\xae\xf2\x05\xbf\x08\xcf\xab\xc2\x37\xe3\x21\xd7\x3f\xde\x38\xec\xd7\x0b\xb3\x6b\xa0\xee\x6b\x0f\x77\x82\x5b\x89\x06\xa2\xa4\x1e\x33\x0c\x80\x68\xc7\x91\x55\x6b\x74\x7b\x55\x08\x26\x35\x8a\x3d\x9b\x09\x25\x06\xe8\x21\x43\x48\x77\x7d\x29\x9f\x90\xcb\x0b\xa5\x8f\x7e\x1c\xd3\x62\x45\x10\x07\xc5\x7c\x5a\x5c\xdf\x00\x45\x94\x46\x28\xe6\x07\xd9\x5c\xaf\x34\x40\xb7\x59\x5c\xd2\x42\x75\xb4\xab\xbb\xac\xa2\x06\x2c\xe6\x1d\x20\xc9\xe9\xb2\x48\x9d\x61\x31\xe4\xf2\x17\x53\x8b\x85\xf2\x16\x4b\x1a\xed\x97\x46\x0a\xb9\x1f\x93\x55\xa1\x5a\xbf\x01\x0a\xcd\xc1\xd2\x37\x03\x57\x0f\x39\x73\xe6\xb0\xe5\x97\x2d\x5f\x12\x76\x0d\x2c\xdb\xf9\xf0\xd6\x74\x5b\x6b\xe9\xc0\x11\x63\x27\xce\xb8\x63\xdd\xbc\x9b\x3f\x25\x47\x99\x23\x53\x16\x0f\x1a\x3c\x9b\x89\x61\x3f\x1e\x1a\x54\x3e\x08\xef\xdc\xb3\xf5\x11\xee\xdc\xf5\x53\x7f\xa1\xfd\xfa\xe1\x6b\x9f\x1a\x2a\x4a\x6f\x85\xda\xaa\x70\xcb\xa1\xef\x5f\x38\xf6\x67\xa9\x89\x74\x6f\x11\xbf\xa1\xe1\x53\x8f\x56\x53\x96\xcc\x4c\x25\x8d\x13\xcc\x34\xbf\x1a\x05\x7d\x4d\x53\xcf\x67\x60\x61\xb6\xbf\x14\xc7\x32\x35\x10\x2d\x68\x31\xfd\x3c\xd0\xaf\xd2\x50\x45\x34\x05\x9a\x70\x19\x87\xd7\xcf\xd1\x8a\x07\x7f\x58\xff\x41\xa9\x6e\x21\x4d\x8c\x7e\x67\x15\xfc\x5e\x5e\x7f\x3f\x5a\x40\xf8\xdf\xbb\xbb\xfb\x7d\x6a\x03\xe5\x96\xf5\x74\xf3\xf5\xbd\x42\xfc\x06\x47\xe8\x00\x6b\xfe\x15\x46\x7c\x69\x10\x85\xaa\x75\x90\x54\x30\x91\x41\xe3\x99\x2a\xc1\xb1\x4c\x35\x9d\xf9\x40\x1c\xd3\x4a\x9c\x92\xdc\xe1\x0f\x96\x53\x95\x6a\xa9\xc3\xee\x66\x2b\x60\xe6\x45\x75\x50\x2d\xab\xfa\xa5\x74\xb0\x44\x7f\xa6\x34\x7b\x85\x24\xa7\x91\x00\x4a\xaa\xac\x74\x1a\x86\xd1\xde\xd3\xef\x93\x73\x14\xb7\xf6\x98\x7c\x1f\x1c\xa4\xbd\x43\x1c\xe8\x77\x6a\x03\x9d\x24\x27\x1a\x8b\xba\x4b\x24\xb9\x80\x4c\x90\x0f\x64\xd3\x0e\xde\x62\x12\xe4\x7d\x9a\xcd\x19\xd3\x44\x25\x9b\x16\x6d\x10\x07\xb2\x96\x30\xa2\x52\x70\xf7\x81\x62\x12\x78\x06\x86\x6a\x52\x57\x9b\xee\x17\x70\x19\xe0\x41\x25\xcb\x81\x07\x95\x7e\x66\x21\x05\xaa\xf1\x99\xde\x3e\x3f\x53\xea\xeb\x33\x9b\xcc\x5b\xce\x60\x44\xc5\x32\xf9\x8c\xb2\xa2\xe6\x16\xe9\xb7\xbe\xe9\x1b\x21\x84\x38\xc2\x77\x22\x1b\x1a\x82\xd2\x22\x42\x31\xaa\xd3\xc4\x26\xb1\x6a\x8f\xab\xe2\x41\x4d\x08\x64\x21\x5c\x12\x44\x49\x56\x19\xfd\x68\xa7\x2f\x86\x34\x4a\x16\xd3\xf9\x34\x1c\xc7\x8d\xb8\x95\x94\x90\x7f\xe7\x3b\x73\x3b\x99\xd9\x5d\x1b\x72\xaf\x32\x71\x93\x7b\x75\x2b\xc4\x65\x43\x0c\x36\x0e\x7b\x52\x75\xc7\x2d\xb7\xd3\x4b\x83\x30\x97\x5b\x92\x35\x01\x82\x2f\xdd\xe5\x84\x85\x97\x22\x4a\xb0\xc2\x50\x84\x82\x4f\x51\x8b\x2b\xdc\xae\x9a\xaa\x34\x6e\x25\x53\xc9\x3e\xae\x9d\xd8\xce\xb9\x6d\x64\x66\x2e\x3e\x7e\x72\x3b\xf1\xe3\x63\xdd\xe6\xe3\x33\x19\xf4\xcd\xf9\x64\xdc\x1e\x27\x72\x03\xd7\xaa\x9b\xa5\x6a\x4f\x92\xee\x75\xaa\xde\x04\x28\xa9\xf0\x89\xb4\x03\xfc\x16\x87\xcd\x1e\x33\x7d\x50\xb7\x3d\x06\x45\x30\x0e\xa7\x39\x79\x4f\xb7\xc9\x5b\x36\x8e\x34\xe5\x8d\x80\xc7\x90\x17\xc8\xbf\x93\x17\xf0\x18\xd3\x18\xf5\x84\x90\x2f\xb1\x07\x33\x15\xa8\xd0\x26\x7e\x74\x91\x11\xfb\x38\x93\x9a\x2c\x66\x55\x77\xc2\x32\x91\x2f\x0e\x41\x8f\xef\xa0\xea\x07\x09\x0c\xd5\x99\x48\x7b\x21\xaf\xe1\x75\xdb\x63\x69\x1f\x14\x1f\xf9\x64\x1a\xf2\x40\xcb\xb3\x69\x3e\xa5\x0f\xf3\x19\x9b\xa1\x29\xd2\xdd\x88\xb8\x9a\x1c\x21\xfb\xc8\x11\x5c\xdd\xcd\x98\x47\xc9\x37\x58\x3c\x6a\x61\x7a\xfc\xeb\xe0\x3b\x0f\xcf\xc7\xb1\x96\xbe\x94\x8f\xfa\xed\xd4\x29\x06\x2b\x69\x36\xc1\x84\xbf\x3a\x38\x9b\xdd\x63\x81\x5f\x76\x2b\xac\xef\xa5\x3b\x35\x12\xd7\x92\xb7\x77\x75\x97\x9e\x22\xf5\xe0\x2f\x53\xf9\x29\x84\x91\x83\x2c\xe7\x19\xf0\x97\x0b\xc7\x81\xbb\x8f\x43\xfa\x96\x71\x18\x7c\xb3\x54\x99\xb0\xba\x07\xe7\xec\x5f\x30\x43\x3e\x7b\xa2\x90\x75\x96\xec\x00\xff\x18\x98\x67\x8d\x33\x41\x9c\x08\xb6\x58\x42\x55\xc0\x35\x9e\xcd\xa6\x3d\xf0\x44\x7a\x5c\xa6\x06\x96\x98\xb4\x8e\x0a\x1f\xe8\xcd\x83\x9a\x9a\xc7\x62\x2e\x36\x7e\xdf\x78\x82\x05\xca\xe3\xab\xda\x7d\x9a\xcb\x49\xd1\x5b\xf0\xe5\x11\x6f\xe4\x7d\xba\x9f\x1f\xf4\x0c\x19\x41\x2e\x67\x8a\x69\x76\xed\xe4\x1a\xe3\x1c\x69\xe5\x32\x34\xc6\xb0\xce\x12\xa1\x05\xec\x35\xdb\x1c\xab\x08\xcd\x60\xd8\x48\xa6\x99\x47\x8b\x31\x46\xef\xb7\x8d\xd1\x9b\x1f\xa3\xc5\xdb\x5a\x78\xca\xc0\x49\xc3\xb6\x91\xc3\xf8\x6e\xdc\xa8\x9f\x36\x5d\x36\x38\x6d\x96\x98\xb4\xad\x94\x8b\x79\x29\x69\x83\xbe\xf2\x10\x3a\x17\x99\x12\x5e\x6a\x20\xae\x09\x6c\x56\x15\x7c\x54\xc1\x4b\xb6\x5b\x1a\x4c\x86\x82\x95\x64\x29\x78\x01\x67\xab\x33\xa6\x79\x14\x5a\x46\x27\xb1\xc0\x27\xd7\x5b\xcc\xab\x0f\x41\x2f\x7a\xee\xf6\x12\xf5\x32\x42\x33\x10\xf6\x82\x75\x5e\x43\x96\xf3\x69\xe0\x8b\x9e\x8c\x4c\x9a\x5f\xd5\x1f\xd7\xf8\x3c\x5f\xab\xc1\xb1\x23\x59\x14\xbf\x40\xdd\xea\xa4\x90\x70\x91\x39\x2e\x7f\x0a\x81\x30\x49\xbe\x59\xae\xf7\xf0\x2c\xc6\x5f\x7a\x42\xf7\x64\xfd\x35\x62\x34\x60\xfe\x2d\xd4\x41\x0b\xa3\x35\x34\x43\x4a\x8d\xe8\x4a\x66\x42\x02\xa4\x45\x43\x6c\x36\x1d\x82\x2c\x53\xc8\x6f\x8f\x15\xf4\xfe\x59\x0d\x7f\xd4\xa4\x7e\x68\xf8\xcb\x28\x14\xde\xb1\x01\x0c\xe5\xc5\x31\xd5\x99\x00\x1d\x7f\x20\x6a\x67\x81\xd1\x0a\x69\x42\x48\x92\x35\x9f\x4c\xf9\x06\xec\x05\x8d\x7f\x49\xc9\x98\x8e\x20\x4a\xd5\x92\x68\x58\x7b\xe9\x4d\xb3\xee\xc6\xcd\xe4\x8d\xf5\xcb\x6e\x1a\x30\xc0\xb4\xf5\xb2\x85\x0c\x9e\x48\x5e\x74\x27\xa9\x8a\xda\xe0\x22\xf2\x0c\x6e\x64\x5e\x2f\xe4\x56\x0e\xa3\x75\xe6\x9c\xb0\x31\x27\x9e\xce\x49\xc8\xa6\x43\xbc\x35\x27\x1e\xe6\xc4\x8b\xb0\x3b\x8d\x2d\x63\x91\x0f\x9a\x4b\x73\xba\xf9\x79\x0b\xe6\xa7\xfb\x21\xbc\x0c\xfc\x16\xc6\xbc\x46\x60\x29\x19\xb0\xe6\x15\xa8\x6e\x12\x8c\x65\x52\xd6\xb6\xb6\xe3\x46\xb2\xff\xf2\x33\xd7\x86\x93\xd6\x2a\x61\xf4\x85\xaf\x9e\xd2\x33\x37\x2b\x5f\x1e\xe6\x9e\xb6\xb4\x2d\x17\x99\x7a\x75\xa8\x40\x6f\x3f\x23\x78\x4d\x25\x71\x55\xd6\x87\xce\xe6\xf5\xea\xf2\x80\x60\x81\xb6\xbe\xe6\x54\xc0\x13\x34\xe2\x57\x0a\xff\x52\x8d\xfd\x2a\x01\x50\xc0\x3b\x0e\x5e\xf4\xe6\x87\x64\xef\xbc\x6b\xce\xfd\xc5\xb5\x7c\x67\x6e\x6f\x32\xfa\xea\x9e\xdc\x0e\x86\xbb\xe2\xca\xca\x81\xb9\x15\x79\xec\xef\x65\xe0\x70\x3b\xa7\x60\x3c\xd0\xed\x42\xc1\x06\x21\x4f\xf8\x9b\x27\x6d\x83\x61\x50\xc2\x5f\xcd\x29\xd1\x61\x68\x82\xa7\x20\x5a\xcd\x0f\x47\x0f\x51\xb7\xe1\xc6\x2b\x32\x17\x3e\xf9\x1a\x79\x73\xe3\x4f\x7f\xc5\xb5\x93\xf1\xc3\x1a\x9e\x7e\x94\xcc\xc5\x3b\x36\x4e\x24\x65\x16\x0f\xde\x97\xfc\x3e\x14\x41\x03\xd0\x75\x94\x95\x4d\xf3\xb3\xd9\xb4\x4b\x77\xb1\xea\xd8\x6c\xc6\x56\x51\xe2\xa2\x74\x2e\x36\x36\xab\x56\x25\x4c\xd7\x52\x28\x02\x75\xd7\x72\x7a\x12\x48\x41\xfd\x67\x69\xa9\x1c\xb8\x5c\xbc\x86\xe2\x89\x80\xe0\x76\x56\xcb\x25\x95\xd5\x1d\xeb\x12\xca\xcf\x58\x21\xa9\xa1\x94\x56\x67\xd3\x5d\x6b\x06\x40\xa4\xa1\x2d\x49\x0f\x0e\xf8\x47\x60\x2a\xd9\x45\x79\x5e\x6a\x5a\x24\x81\x03\x32\x9b\xaa\xba\xda\x08\x98\xb7\xe9\x63\x9b\x32\xb7\xbe\x16\x2f\xc0\xb5\x78\x0e\xbe\xe8\xe4\xdb\xee\xff\x78\xe6\xc7\x78\xca\xb2\xb5\xe4\xfd\xdd\xe4\x45\x72\x63\xd9\x98\x87\x1e\x66\xf6\x32\x47\x3b\x9f\xfb\xb7\x97\xd9\x35\x57\xcf\x92\x26\x96\xcf\xc4\xa5\x78\x18\xb9\x86\xdc\x30\xe1\x85\xd7\x2e\x1e\x4f\x3e\x9e\x3c\x0e\x5f\x80\x9b\x7f\x7c\x9d\xba\xbd\xc3\x98\x3f\x3f\x17\xf8\x6d\x6a\xd1\x1d\x28\x5d\x8c\x68\xbe\x21\xed\xd4\xdd\xbd\x6a\x21\x9b\x11\xcb\x8a\x9d\xee\x98\xea\xa5\x75\xa0\x15\x09\x83\xa2\x32\xc3\xd3\xbc\x03\x0f\xe0\x82\x7e\xe8\xf8\xbc\xc0\x18\xef\x03\x3a\x1f\xcd\x23\x53\xce\x4a\xde\x30\x41\x99\x6e\x02\xd5\x27\xab\xa5\x29\xb5\x52\x4a\x3b\x95\x62\xdd\xa5\xf6\x98\xfd\x85\x4a\x31\x65\x31\x2d\x93\xd4\x60\x4a\xab\x16\xbb\x99\x46\xd0\x2d\x03\x94\xc3\x3d\xe8\x5e\xa3\x95\xb4\x11\x55\xa8\xdf\x17\x9e\x2b\x45\x70\xf0\x9d\x2f\xb1\x27\x17\xe6\xef\xda\x78\xc5\xd3\xf3\x5a\x9f\xbd\x99\xe4\xc8\x7e\x85\xec\x61\xd6\xe1\x97\x98\x55\x8b\xdb\x6f\x60\x5e\x9a\x7b\x56\x4b\x53\xeb\x3b\x1f\x93\xbf\xfd\xf5\xce\x1b\x6f\x8f\x0d\x3e\x16\x1d\x80\xf9\x2f\xf7\x5e\x75\xc3\x4a\xca\xd5\xd6\x06\x7b\xa1\x06\xc5\xd0\xc3\x06\x43\x5f\x79\x52\xf3\x3b\xb3\xe9\x12\x80\x49\x4b\xca\xec\x31\xba\x33\xea\xf5\x9d\x51\x55\x56\xb0\x33\x6a\x2d\xb9\x4e\x63\x67\x44\xf2\x3b\xa3\x36\x91\x96\x22\xe6\xce\xd0\xf7\x31\xe0\x31\x0a\x6d\x5e\x32\x37\x49\x44\xb7\x90\x56\x26\x49\xb2\x26\xc7\x40\x78\x21\xed\xf2\xd7\x43\x98\x6a\x6e\x9c\x2a\xd8\x38\xf5\xdf\x61\xe3\x78\x00\x11\xad\xfb\x2e\x7b\x67\xe9\xc1\xef\x93\x43\x5f\x93\x77\x8a\xbf\x7d\xef\x8c\x1d\x6d\x27\x0b\xf0\xf6\x01\xf8\x1c\xec\x31\x76\x10\xb5\xdb\x72\xd8\x43\x95\x28\x8a\xee\x42\x74\xeb\xd4\x0a\x59\xb5\x38\x9e\x51\xa0\xa2\x5b\xad\x88\x9b\x1b\x28\x62\x16\xe7\x17\x6c\xa0\x8a\xfc\x06\x8a\xc0\x06\x02\x68\x47\x02\xd1\xd3\x2a\x63\x2f\xd5\xe3\x98\x56\xc1\xc3\x83\xae\xfa\x24\xb5\x1c\xea\x4e\xa2\x29\xb5\x58\x4a\x2b\xce\xda\x94\xb9\x87\xb4\x50\x29\xf0\x28\xeb\xbb\xa8\xf6\xdb\x77\x91\xa0\x5b\xa9\x01\x9f\x76\x1f\xad\x4b\x93\x4f\x9f\x38\xe0\x3d\xed\x36\x1a\xe3\x22\xeb\xf0\x6d\x03\x8e\xbf\x4c\xb7\x12\xc2\x68\x1c\x42\xcc\x3b\x10\xaf\x99\xac\xb8\x3c\x90\x2b\xb9\xe2\x2a\x03\xe2\xf5\x69\x3b\x63\x29\xd7\x0b\x89\x34\x63\x87\x42\x0c\xdd\xc3\xe1\x12\x26\x31\x5e\x53\x8b\x14\x6d\x8a\x04\x44\x29\x14\x18\x97\x4e\x33\xf7\xa4\xd3\xea\x74\x36\x3d\x5d\x55\xa7\x77\xb5\x4e\x57\x4d\xde\x24\x71\xb3\xb8\x05\x49\xa8\x02\x2d\xeb\x53\xc1\xbe\x9f\x7a\xb3\xca\xb8\x2a\x1f\x84\xe2\x32\xc5\xcc\xad\x98\x6a\x52\xa0\x0a\x22\x4b\xb2\x56\x81\x53\x29\xcd\xe3\x95\x68\x0a\xf0\xdb\x15\xa6\x94\x6e\xf5\x74\xfd\x6b\xe0\x6f\xe9\xc1\x3a\xd8\x9f\x26\x7e\x61\x59\x1d\x9d\xab\xd0\x05\x75\x75\x3d\xe7\x8a\xff\x57\xcf\xb5\x7f\x6d\xad\xf3\x7a\xce\xb5\x1f\xad\xad\x42\x79\x24\xa3\x86\xe4\x31\xe0\xc6\x59\x5e\x50\x43\xa2\xf2\x7a\x24\xa6\x05\xdd\xd9\x4c\x29\x2d\xc1\x28\xb5\x65\x4d\x79\x8e\x3c\x1b\x8e\xee\x88\xba\x28\x2d\x2b\x94\x9e\x76\xf0\xa2\x4f\xa9\x09\x41\xb7\xb3\x7e\x63\x06\x7d\x50\x3e\xa2\x22\x20\x3d\x2e\x95\x35\x57\x98\x92\x7a\x99\xb7\x68\x0b\x8e\xe0\x7e\x6b\x4a\x70\xf3\x16\xbc\x09\xcf\xcc\x3d\xc7\xbd\x86\xe3\x77\x9a\x75\x25\xb7\xfe\xdb\x9f\xff\x3e\x79\x39\xdf\x99\x1b\xbb\x1f\x7f\x91\x9b\x76\x1f\xf9\xe0\x85\x82\xd2\x92\x97\x5e\x0f\x13\x13\xf3\xe5\x8e\x43\x6d\xc9\xa5\x05\xb5\x25\x2a\x07\x94\x98\x4a\xf7\x7a\x12\x26\xa1\x96\x19\x68\xb5\x51\x44\x12\x2c\xd3\x17\x45\x70\x7b\xf5\xc9\x18\x09\x5b\xc5\x62\xc4\x54\x7d\xb4\x88\xcb\x1e\x0c\x17\x24\x4a\x71\x02\x49\x3d\x40\x5e\x70\x54\xb6\xe1\x46\x9c\xc6\x33\x49\xf4\x28\x96\x4c\x9c\xf7\xea\xef\x3f\x70\x4f\xe2\xfa\x0a\xae\x9d\x28\xf8\x53\xe2\x22\xef\x90\x53\x16\xd0\xfb\xf0\x5d\x77\xde\x1f\x70\x91\x47\xe8\xfa\xf8\x48\x9b\xb0\x19\xe2\x86\x07\x51\x9e\x34\x17\x9c\x45\x10\xbb\x97\x58\x1a\x33\x78\xa9\xd8\x7d\xb8\x1f\xb1\x7b\xc9\xfd\x8d\x47\x55\x0a\x34\x9d\xac\xce\x88\xee\x9a\x4e\x46\x5b\x44\x5a\x36\xc5\xee\x25\xb9\x40\xec\x5e\x73\x78\x8d\x72\xb6\xbc\x08\x81\x24\xa5\x31\x54\xae\x74\x17\xc0\x87\xe2\x4f\x10\xc1\x8f\x16\x88\xe0\x1b\x05\xaf\x54\x0a\xbf\xf3\xe7\x05\x52\xf8\x66\x0c\x77\x33\xc1\x64\xfe\x23\x8c\x59\x9f\xc2\x67\xa0\x3e\xe5\x6c\x43\xab\x47\x9f\x3b\x88\x20\x03\x6b\xb0\x4f\xa4\xad\x06\x1e\xaa\xa9\x15\xd2\x17\xd0\x23\xc9\x9a\x0b\xa4\x85\x58\xbf\x24\xa7\x91\x1e\x4a\xc2\x49\xde\x43\x61\x8b\x8e\xaf\x9b\xca\x16\x8e\x6d\x21\x47\x36\xf5\xd2\xda\x32\xa3\xb8\xbc\xde\x96\xfe\xcc\x2c\x82\x35\xb9\xa8\xc7\x33\xe3\x8c\x6b\x92\x3b\x9b\x61\x83\xf9\xdc\x1a\x8d\xe7\x42\xf4\x99\x09\x51\xff\xdc\xd0\xb4\x87\x76\x28\x3d\xc4\x70\xc2\x80\x25\x83\x78\x19\x51\xaa\x00\x33\x79\xd4\x6d\x4f\xe5\xd3\x6c\x37\xff\xe3\xc1\xe7\x6e\x9a\xfc\xc3\xe9\xdf\xbf\xd5\xd2\xbf\xdf\xa1\x91\x63\x77\xc5\xb1\xaf\x38\xf0\xc2\x6e\x7c\xc2\xe0\x15\x24\x0e\xd0\xc7\x0a\xa2\xf9\x85\xcf\x01\x9f\x54\x1d\x71\xcd\x07\x1a\xc5\xf9\x9c\x1b\x8d\xf1\x82\xf4\x91\x08\x42\x8e\xc0\xd4\xc8\xd2\x63\xbb\xa0\x55\xcc\xa8\x48\x9a\xc3\x07\x7c\x0d\x8e\xbe\xc7\x8c\xac\xa7\xb9\xa5\x40\x4e\xeb\xf8\x47\x53\xae\x1d\x7b\xd5\xf7\x96\x2c\xe7\x2c\x5d\xad\x5f\xff\x83\x7c\x5c\x54\x89\x85\xe1\x77\xde\x82\x1f\x80\x84\x1c\xcd\x5b\x66\x00\x6f\x38\xff\x5f\xcd\x5b\x52\x4d\x65\x97\x95\x64\xee\x2b\x45\x48\xb7\x80\x95\xb6\x34\xb6\x66\x9f\x89\x4b\x9a\xb7\x3c\x04\xb8\xc2\xf9\xff\x6a\xde\xf2\x9f\x18\x93\x99\xb6\x34\x77\x64\x5f\x89\x4b\xc0\x14\x20\x26\x0e\xa1\x79\xa7\xc3\x14\xd2\x32\xdc\xf9\xb2\xc7\x1e\xeb\x17\x5e\xe8\xf0\xb8\x24\x5b\x4c\xf3\x2a\x50\x7a\x67\x82\x0c\x5e\x56\x92\x35\x21\x90\xea\x13\x66\x48\xf6\xd2\x0d\x27\xe4\xed\x7f\xf4\x21\x1d\x4e\xda\x98\x0c\x8e\x01\xca\x00\x18\x03\xc4\xbc\xa0\x11\x73\x5a\x8c\xc1\x67\x61\x0c\x1d\x6e\xa7\xcf\x16\x33\xb5\x06\x4d\xa4\xc1\xa3\x0f\x8e\xf7\xa7\x4e\x87\x35\x24\x9b\x7a\xa8\x0b\x75\x91\x4f\x3f\xec\x2d\x30\x44\x96\x33\x57\x1d\xa1\x1a\x43\x7b\x48\x9b\x2d\xc2\x77\xa2\x22\x3d\x4a\xa1\x37\xbf\x62\x70\x33\x6a\x0c\x9f\xcc\xab\xe9\x49\x59\x2d\x50\x04\x8a\x7a\x2e\x7d\x59\x65\x48\x4b\xfb\xa4\xac\x7e\x6f\x1a\xc2\x7a\x2f\xfe\xe1\x53\x3f\x9c\xc2\x4a\x83\x47\xf5\x3f\xaf\xb1\xc5\xdf\xf0\x2a\xf3\x3c\xab\x9f\x4d\x0d\x0d\xb8\x83\x61\x2d\x12\x14\xcd\x55\xa4\xcf\x46\xa6\x67\x95\x94\x52\x45\x73\x97\x60\x24\xc9\x69\xd1\xe6\x33\x45\x51\x0a\x5b\x0b\x9a\x95\x6a\x1c\xc1\xd5\x72\x40\xda\x83\x77\xe2\xd9\x02\x5e\x8e\x77\x1a\xfb\xf8\x5d\xd6\x65\x27\x1b\xc9\x07\x64\x9b\x5d\xe1\x3b\x4f\x6e\xe7\xda\x8d\x0d\x9d\x69\xfc\x01\xf6\x9f\xdc\xc8\xad\x21\xdb\xaf\xc9\xcd\x34\xf7\xb6\x38\x85\x6b\x47\xa5\xe8\x51\x63\xce\xbe\x60\xa1\x7e\x20\x25\x02\x2c\x95\xb3\x6a\x29\xdd\x33\x32\xd5\x0f\x2c\xef\xa9\x1f\x28\xd3\x79\xf6\xd4\x0f\xf4\xfb\x3a\x14\xbf\xdc\xeb\xae\x51\xfc\x32\xd5\x0f\x94\x95\xbc\x7e\xa0\x52\xa0\x1f\x28\x95\x1a\xfa\x81\xaa\x4b\x02\x91\x38\xc3\x1a\x2e\x77\x89\x69\x8d\xbc\x96\x20\x58\xa4\x1f\x3d\x41\xa3\xd5\xa0\x6f\x55\x41\xe3\x7c\xef\xa1\x2c\xf8\x5f\xe7\x5b\x53\x8e\x9d\x9b\xc4\x2d\x48\x44\x01\x54\x82\x6e\x2e\xd0\xed\x03\xdc\x24\x68\xe1\x26\x4a\x5c\x73\x79\xb2\x69\x17\x94\x00\xb9\xbc\x20\x89\x0b\x55\xf5\xb6\x83\x9a\x5d\xca\x76\x88\x76\x9b\x2d\xa6\x21\x1f\xa8\x0f\x88\x3e\x8b\x03\x9b\xf5\xd1\x1a\x7b\xe0\x33\x0d\x80\x47\x23\xa4\x54\x4e\xee\xc4\x0c\xef\x55\x82\x21\xda\xd1\x4d\x99\x4e\xf5\x6b\xbd\xd8\x22\x39\x8d\x38\x7b\x10\x7c\x47\x98\xba\xa8\xc0\x70\x78\x0d\x23\x90\xf4\x15\xb9\x4f\xae\x58\xd1\xc3\xef\xc4\x25\x78\xed\x1d\xb5\xb6\x08\xff\xcc\x89\xf1\x78\x0e\xd9\x61\xf9\xd6\x27\xb7\xe0\xc3\x37\xd4\xfc\x00\xb1\xa0\x8f\x3d\x47\x18\x83\x8a\x50\x1d\x1a\x82\x76\x17\x2a\x64\xd7\x77\x53\xc8\x6e\x30\x15\xb2\xd5\x9a\xb8\x56\xe6\xc9\xa6\xcb\x40\xb2\xa4\xac\xd2\x1e\x53\xc3\x09\x93\x95\x25\x1a\xc8\xaa\x51\x9f\x5a\xac\x1f\x77\x61\x29\xab\x86\xe3\x10\xd4\x45\x7d\xda\xa0\xbc\x92\x76\x02\xc7\xb4\x68\x58\x92\xd3\xf6\x3a\xdd\x23\xd0\x06\x15\x4b\xf2\x13\xa2\x2b\x58\x56\x53\x4f\x29\xf7\x34\x05\x8a\x14\x1b\x24\xdd\x6b\x90\x15\x23\x11\xc7\x80\xbe\x92\x1d\x3c\xda\xd3\x8a\x6b\x77\x77\xd3\x95\xd3\x4a\x6d\x8f\xe8\x61\xb2\xcf\xfb\x55\xde\xe6\x7f\x6e\x1a\x6f\xbf\xa5\xc1\xcd\x19\xfb\xa5\x0d\x89\xc0\xb5\x55\x6b\xf2\x77\xe6\x77\x8c\xdf\xda\x31\x52\x5c\xad\x4e\x6a\x4e\x96\x32\x94\xd7\xd1\xca\x7b\x9f\x25\x4a\x06\x47\x2a\xa5\x03\xa8\x94\xa1\x82\xc3\xdc\x2e\x51\xfd\xa7\x36\x49\x4e\x0b\x18\x9a\x16\x8a\x41\xf6\xa5\x52\x4e\xf3\x0c\x2d\xa9\xc6\x7e\xc0\x0a\xac\x8d\xc2\x76\xd7\xc4\xd1\xb7\x49\xe1\x3b\x85\x5b\xa6\xc2\xd4\xb4\xb8\x87\x6e\x95\x76\x4b\xd7\xc2\xd8\x33\xc2\x7e\x43\xdf\xe2\xe4\xef\x60\xcf\x30\xd7\x5a\xea\x37\xfa\xfc\x41\x5f\x5d\xe0\x50\x11\xaa\x41\x0d\x68\x38\xba\xbf\x70\x07\x45\xbb\xed\xa0\x41\xd6\x0e\xaa\x8a\xab\xc3\x92\x5a\x29\x9b\x55\x13\x09\xac\x8e\x00\x4b\xd4\x06\xb2\x1d\xe1\x5a\x64\x8b\x69\x15\x52\x56\xad\xa5\x3d\x97\x74\xc3\xa8\x71\x7d\x3b\x35\xc9\x59\x6d\x24\x8e\x69\x15\xb0\x73\x82\x90\xc3\x8e\x4b\x9a\xe8\x4a\xa5\xd4\x26\x59\x93\x14\xdd\x12\x83\xfe\xd5\x2d\x53\x68\x30\x6b\xc3\x14\xea\x08\xf5\xb5\x79\x9e\x31\x8d\xb7\xd6\xd8\x35\x41\xd3\x7a\x7d\xec\x1f\xee\xb0\x61\xc8\x2e\x8f\xb1\x7f\xd8\x43\x96\x56\x08\xc4\xf4\xb5\xe0\x67\x29\xba\x27\xeb\x32\xf4\x2d\xec\x6c\x96\x46\xf5\x9c\x2b\xab\xca\x89\x8c\xc7\xe7\x82\x0e\x1e\x36\x9b\xe1\x6d\xf0\x92\x77\x99\x02\xdc\xaa\x04\xf2\xfa\x2a\x97\x48\xdb\xdd\x70\x16\x32\xa0\xbc\x63\x94\x1f\x05\xe0\x0c\x6c\xc4\xf9\xd6\x0a\xfd\xa4\xc6\x11\xa9\x9a\xb9\x8d\xbb\x3b\xb7\x8f\xf1\xe4\xbe\x64\x92\x5d\x3f\x23\x81\xbb\xb1\x88\xaf\x5f\xc7\x77\x12\xf2\x1c\x21\x1b\x4f\x21\x7d\x1b\x30\x73\x99\x56\x44\xcf\x0b\x81\x70\xd7\xa0\x01\x28\x81\x86\xa1\x34\x4a\x57\xea\x23\xad\x4b\x6a\xc5\x62\x56\x8d\x25\x68\x39\xe2\xff\xc3\xde\x9f\x47\x45\x79\x64\xff\xe3\x78\xdd\x67\x6b\x64\xed\x85\xa6\x41\x44\x68\x1a\x68\x11\x01\xa1\x69\x5a\x44\xdc\x82\x8a\x80\xa8\xa8\x88\x06\x51\x11\x11\x57\x40\x54\x24\xc4\xa8\x21\xb8\x44\x89\x71\x37\xc6\x18\x83\xd8\x31\x86\x98\x6e\x24\x68\xd4\xb8\xc4\x3d\xc6\x18\xe2\xa8\xe3\x24\x26\x31\x6a\x4c\x2b\x31\xc6\x49\x1c\xa3\x50\xfc\xce\x53\xcf\xd3\x0b\x8b\x4e\xe6\x7c\xde\xe7\xfc\xfe\xf9\x9e\x39\x73\x44\xc3\x53\x55\xf7\xd6\xad\x5b\xb7\xee\xf2\xba\x72\x92\x22\x65\x32\x44\xd7\xe9\x54\x01\x6e\x6e\x61\x66\x1d\x29\x2f\x37\xe9\xa4\xe6\x9e\xee\x16\x30\xc5\x91\x1d\x0f\x55\x5a\x4c\xa1\x52\x73\x84\xb0\xcf\x2a\x0f\x8b\x49\x47\xac\xf2\x18\x08\x33\x2b\xe5\x16\x73\x6f\x08\x33\x87\x22\xd1\x44\x33\x45\xc8\x6a\x9d\xdc\x48\xd2\x86\x4a\x6e\xf6\xd0\xc4\xc5\x99\x62\x64\xb5\xf2\xce\x01\x04\xbd\x5f\x6e\xee\x42\x1e\xf0\xaa\xce\xfc\xf6\x77\x09\xe5\xb5\x4a\xcf\x00\xa1\x73\x8e\x13\xbf\xf5\x26\x37\xb9\xd9\xc5\x23\xce\x2e\x02\x21\xa2\x0c\x10\xf0\x1f\xab\x77\x88\xb8\x18\x03\x45\x10\x20\x7b\x8b\x7e\xa1\xbf\x77\xc6\xc3\xdf\x8f\x8e\x1b\xb6\x7a\xd7\x94\xcf\x2c\x37\x8b\x07\x7e\xb4\xf0\x3a\xa0\xe6\x70\xf6\xcd\x57\x4f\x1e\x18\x7e\x60\xd9\xca\x1b\x49\x39\xa7\xb6\xbf\x77\x02\xe2\x56\x4f\x5d\x58\xf4\xf2\xcb\x54\x15\xec\xa5\x66\x64\x5e\x13\xe4\x60\xf4\xa0\x81\xc3\xbe\x98\x5a\xde\x7f\x00\xfe\xd5\xb2\xe1\xd5\x75\x99\x8d\xda\x6e\x53\xa7\xcf\x1f\xf7\xd9\x4e\x41\x10\xc6\x82\xa4\xf0\x65\x44\xa1\x05\x08\x31\x03\x24\x6b\x09\x16\x56\xa1\x18\x31\x53\xf1\x2f\x4c\x4a\x28\xa6\xab\x53\x78\xb9\x7b\xb8\x85\x99\x15\xae\x16\xfe\x75\xc3\xb8\x5b\x6a\x19\x12\x2e\x66\x24\xa4\x8a\x9c\x44\x1f\xdc\x85\x07\x8e\x3c\xba\x56\x45\x62\x69\x2a\x9f\x4e\x61\x26\x69\xf4\xbe\xfe\x2a\xd2\x39\x5a\x6a\x42\xfc\x61\x02\x11\x55\x91\xb7\x7b\x4d\x6e\xc4\xa6\x6c\xad\x34\x1d\x2a\x70\x16\xb4\x51\x91\x31\x74\x72\x73\x23\xfc\x86\x65\x94\xa7\xed\x42\xf9\x2b\xca\x2e\x2e\x0e\xbd\xd2\xfa\x21\x4f\x14\x88\x42\xd1\xaa\xb6\x9d\xc3\xb4\x9c\xa5\x4e\x23\x74\x0e\xd3\xb0\x16\x53\x00\xc9\x60\xa9\xf5\x21\x28\xf0\x3e\x5d\x3a\x85\x99\x94\xd1\xd6\x4c\x16\x27\xa5\xc5\xec\xa5\x89\x26\x2d\xd4\x94\x32\x8b\x49\x19\xc9\xff\x14\x24\x36\x53\x0b\x83\x30\xb3\x93\x52\x26\x37\x05\x92\x8c\x16\xda\x45\x4e\x30\x3c\x4c\x9c\xbc\xd6\xdd\xc3\x8f\x68\x47\x6b\x13\x31\xcd\xf3\x9a\x88\xb5\xb9\x59\x9f\xd3\x4a\x2d\xb4\xed\x25\xcb\x3e\xbb\xa7\x1a\x1b\x2a\xf2\xa7\x39\x8a\x34\x55\xa3\x50\x75\x4b\x23\x27\x67\x2f\x90\x9e\xf5\xe9\x22\x57\xbc\xad\xb1\x07\x96\xb6\xd4\x29\x41\xce\xab\x49\x25\x2d\xd4\xe8\x09\x6d\x61\x3c\x54\x96\x5a\x5f\x0f\x6b\x1b\x18\x02\xe2\x69\x06\xa5\xe0\x03\x61\x65\x26\xa7\x38\x93\xab\x5c\x08\x8a\xe9\xc9\xd2\x19\x89\x2c\x36\x48\x67\xc3\x96\x14\xde\x0a\xd5\x4c\x98\xdb\xa5\xc3\x1b\xf0\xf1\xc2\x55\xa0\xda\x09\xe3\xa1\x1c\x6f\xc0\x75\x78\x37\xae\x82\x01\x75\xc7\x77\x9e\x70\xa1\x9e\x24\x1d\x3b\xf7\xe2\x10\x70\x1d\x35\x08\xcf\xc1\xdb\xf1\x76\x3c\x1f\x96\x7f\xf9\x71\x55\xfd\xdb\x82\x2f\x2e\xb3\xa5\x91\xc9\x6e\xd3\x6f\xdf\x9b\x13\x55\x3c\x2b\xb1\xaf\xdd\xde\x6f\x5f\x29\x27\x18\x37\xbe\x10\x46\xc8\xf0\x12\x6c\x1f\x25\x7f\xaa\x9d\x3a\x09\x95\x78\xac\xab\x50\xdf\xf4\x3c\x7a\x08\x20\x82\x40\x8f\x26\xd0\x8a\x95\x99\x49\x35\xb0\x6f\xbe\x3a\xb1\x76\xfa\x98\xa3\xf3\x41\x0a\xe1\xf8\xee\x93\x46\xfc\x08\xfc\xa9\x82\xdc\x71\xf3\x3b\xc1\x9d\x0d\xaf\xae\x0b\x89\x6e\xec\x11\x84\x2f\xe1\xdf\xf1\x2f\xf8\x02\xb8\x7c\x5a\x58\x56\xf4\x92\x70\x6f\x91\x7d\x90\x64\x10\x5a\xb4\x48\x87\x56\x3f\x7f\x2f\x4c\xc1\xa4\xb7\x9d\xbf\xbd\xb7\x5d\x97\x2b\xe6\x40\x99\xc5\x14\x68\x6b\x67\x67\x8a\xb0\xd3\xd9\x7a\xbb\xf4\x10\x66\xee\x16\x28\x93\xef\x63\x5d\xbd\xe5\x41\xaa\x38\xb3\x6f\x84\x4c\x6e\xa6\x3b\xff\x37\xaa\x3b\xdc\x45\xc7\x3b\x29\xd8\xe1\xe7\xff\xba\xbb\xcd\xbd\xad\xb7\x15\xac\xb7\xf5\xba\x7b\xe6\x8e\x33\x6f\x8a\xb7\x55\x3f\xeb\x1d\xc5\x08\xfb\xef\xd0\x0f\x70\xad\xc8\xb3\x20\x47\x19\x50\x0b\x3c\xeb\xb0\x1f\xa0\xf2\x8a\xd9\x57\x66\xd9\xa7\xf6\x55\xf2\xa6\xb1\x9c\x98\xc6\x6a\xb9\x85\xc0\xf8\xd8\x24\xc4\xd4\x8d\x57\x50\x11\x0e\x5d\x01\xcd\xae\x6c\x5c\x9c\xa9\x9b\xcc\x2c\x0f\xe2\x2f\x02\xb9\x29\x84\x67\x9c\xfa\xef\x8a\x4b\xab\xbb\x5d\x10\x1d\xc7\xae\x5e\x1d\x8b\xd1\x11\x2b\xb3\x26\x0b\xe2\xf4\x92\xed\x66\xef\x40\xae\x98\x65\xd6\xab\x7d\x2e\x2f\x61\xf4\x05\x2b\xcf\x68\xd1\x57\x9f\x81\x64\xc8\x0f\x85\xa2\x05\x1d\x7b\xeb\x7d\x23\x4d\x5a\x1d\x11\x33\xb5\xa0\xf6\x3c\xae\xd8\xdd\xd5\xfb\xbc\xdd\x3d\x9c\xc2\xac\x95\xe1\xde\x32\xcb\xbe\xae\xe4\x1f\x82\x44\xed\xe7\x21\x97\xc9\xcd\x4a\xdf\xb8\x38\x73\x90\xbb\x4c\x6e\x56\x6b\xff\x86\x27\xbb\xd3\xb3\xa4\xe8\xd9\xfe\x7b\xd0\x74\x20\x3e\xcf\xf0\xe1\xdb\x6c\xc6\x7e\x0e\xb6\x22\x2d\xfa\xf2\x99\x0e\x79\x01\xff\x7f\xe3\x05\x28\x9e\xc1\x8b\x67\xfb\xf7\x6f\x74\xc0\x8a\x67\xb8\xf8\x6d\xed\xe1\xfa\xd9\x65\x22\xbb\xa5\x91\xb9\x2a\xc9\x40\x21\x28\x1a\xf5\x45\xdb\x84\xaa\x39\xb3\x97\x35\x51\x38\xc8\xd9\xb1\x56\xce\xd4\x33\xd2\xd4\x47\x67\xee\x4e\x5b\x4c\xb1\xd1\x60\xea\x17\x69\xd2\x5e\x31\x75\x89\x36\x87\xcb\x2c\xa6\x70\x5b\xa9\xdc\xbe\x38\x37\x6f\xa7\x30\xb3\x4e\x6e\x31\xe9\x22\xcd\x71\x72\x8b\xc9\x5b\x6a\x2f\x9f\xeb\x0f\x61\x66\x5d\xb8\x4c\x5e\x2b\x0d\xa2\x79\x7b\x29\x4e\x66\x76\x26\x15\x82\x5d\xbc\x64\x72\xb3\x9b\xa2\x7d\xe5\x1c\x6f\x3c\xa3\xff\xa1\x7e\xee\x19\x2c\xfc\xef\x55\x74\x13\xdb\xb3\xf2\xb9\x95\x74\x54\x71\x7b\x7e\xa6\xb5\x34\x32\x1a\x8e\x41\xdd\x50\x0c\xea\x8f\xaa\xc4\x0c\x6c\xc6\xc9\x62\x2b\xa5\x73\xa8\xa1\x33\x45\x47\x9a\xfa\xea\xcc\x3d\x68\x8b\xa9\x97\x80\xca\x16\x7a\xc5\x1c\x29\xb3\x98\x22\xa5\x44\xe1\xc4\xcb\x2d\x26\x49\xc0\x15\x99\x49\xaa\xeb\xa0\xac\x8e\xa0\xb4\xe9\x23\x65\x72\xb3\xa2\x73\x5c\x9c\x59\x12\x2a\x93\x9b\x19\x2d\xe1\xdf\x3e\xff\x80\x5e\x02\x4e\xa2\x0b\xe9\x45\xdb\x41\x41\x1d\xff\x72\x53\xfd\x4f\x65\x75\xcf\xe0\xeb\x7f\x29\xae\x83\xf6\x4c\x7d\x6e\x81\x1d\xbb\xb6\x83\xf3\x0a\x28\xae\xa5\x91\x99\x41\xf2\x7c\x86\xa0\x5a\x6f\x24\x94\x03\x0b\xd6\xa8\xbb\xd8\x0b\x45\x72\xc5\xac\x14\x33\x75\x94\x12\x99\xdc\x2c\x95\xf1\x62\xc5\x78\x0b\xf1\x08\x77\x59\x2d\xc8\xf9\x27\xaa\xc9\x43\xf0\x09\x1a\x1c\x72\xee\xf5\xc0\x1b\x98\xe0\xc5\x10\xb1\x8a\x9b\x70\x2f\xff\xfd\x5d\x5f\x5f\x2c\x83\xfc\xe6\x3b\xf4\x51\x3c\xe2\x77\x40\xf8\x10\xbe\x8a\x9b\xe3\x41\xd2\x43\x3f\x7d\x6e\xde\xc4\x6b\x90\x05\xe8\x34\xce\x75\xfe\xee\xe4\xd7\xf7\xc9\xfa\xb0\x27\x93\xc1\x64\xa3\xce\x68\x04\xaa\x75\xe7\xb7\xda\xcd\xc9\x62\xf2\x8e\x34\xd3\xce\x16\x82\x2b\xc1\x5d\x31\x7b\x2a\x2d\xb5\x1c\x09\xe4\x73\x2e\x9d\xc2\x48\x67\x55\x4f\x4e\x26\x17\x5d\x58\xb4\x37\xf1\xb0\x98\xdc\x64\xb5\x48\xe6\x29\x64\x27\x90\x24\x1c\x55\xab\x75\x0a\x5d\x0e\x94\x9e\x1c\xa3\x09\xd4\xc6\x65\xdd\x9c\xba\xdd\xf8\xc5\xe9\x05\xb0\xb1\xb9\x96\x3e\x83\x07\xff\xfa\x64\x0d\xbe\x7f\xfc\xe9\xb1\x4d\xe1\xba\xe5\x8b\x5f\x2f\xbf\x06\x8b\x2d\xa7\x71\x4e\x67\xfc\xe3\xe6\x1f\x16\x8e\x10\x31\x19\xd8\xeb\x1c\x26\x6f\xbb\xf1\xf6\x6a\x12\x2b\x26\x8a\x34\xd2\x2c\x13\x3b\x84\x0b\x28\x28\x0e\x9d\xd3\x48\xf2\x0d\x0d\x24\xeb\xc5\xe4\x2c\xdb\x27\xf1\x90\xca\x49\x1c\xcc\x1a\xfa\x11\xfa\xd7\xb9\xc5\xb5\x46\x3b\x11\x90\x4e\xf4\x6a\xa5\x1d\xdf\x44\x40\x36\x31\x50\x46\x2b\x98\xc9\x93\x64\x11\xc8\x84\x0b\xbb\x74\xc9\xde\x63\x8f\xad\x41\x6e\x48\x86\x26\xb4\xeb\xb1\x67\x72\x8f\x34\x7b\x88\x09\x3a\xed\x5b\xed\x29\xda\xb5\xda\x33\x73\x6e\x71\x71\x26\x27\x79\xad\x2b\x2f\x14\xff\xa5\xd5\x9e\xb2\x55\x97\xbd\x57\x28\x63\xbb\x06\x7b\xcc\xb5\x4b\x97\x10\x2d\xf0\x52\x92\x41\xf0\x2d\xb4\xb6\xba\x18\x07\x6e\xfa\x44\x9a\x82\x75\x66\x05\x2d\xe4\xad\x74\x73\xe4\xa9\x14\xc2\x08\x22\xbe\x97\xd0\x61\x37\x50\x4e\xcc\x37\x2b\xa7\x43\xf9\xff\x2a\x15\x4a\x46\x02\xbb\x90\x5a\x80\xe7\xb3\xf7\x19\x67\xb3\x2d\xcb\xe3\x3a\xd0\x70\xed\xb6\xa0\x83\x0b\x93\x16\x7b\x1e\x32\xe4\x3d\x18\x8c\xe6\xb5\xdf\x11\x15\xf1\x28\xc9\xec\x1e\x25\x61\x5f\xf6\xb9\x13\x14\x1d\x4f\x99\xe3\x0e\xed\x0b\x70\xea\xe4\x14\x66\xee\x2c\xb7\x98\x3a\x47\x9a\x03\xc4\x54\x1d\x02\x99\xcc\xd3\x67\x0e\xe8\x2c\x93\x9b\x39\xd7\xe7\x6f\xd4\x33\x48\x6e\xb5\x79\xaf\xb6\xa7\xb7\xdd\x66\xb6\xbf\x15\x79\x9b\x9c\x60\xee\x4b\x32\x90\x0b\x52\x22\x35\x0a\x47\x33\xda\x22\x62\x93\x5d\x8d\x34\x85\xe9\xcc\x3e\x62\xf6\x4d\x84\x0d\x77\xdf\x55\x88\x1a\x77\x91\x11\xcf\x78\x20\x6f\x72\xcb\x2d\xa6\x6e\x02\xfc\x23\xa7\xb2\x90\x22\x11\x7e\x5f\xf7\xd1\x1e\x8a\x4e\x44\x4f\x2b\x08\xe2\x21\xd7\x16\x8a\x1f\x3c\xbd\x74\x01\x32\xa9\x3a\x90\x7b\x96\xfa\x6d\x8f\xcf\x3f\xe8\xe0\xa7\x50\x8c\xd7\x7c\x7a\xb8\x6b\x07\xa6\x41\x1b\xac\x7e\x98\xf9\xe7\x63\xf8\x15\xee\xff\x45\x35\xb7\xb7\xb1\x09\x76\xbf\x6d\xcf\xa3\x50\x81\x88\x88\xed\x67\x45\xef\xd7\x38\x5b\xf8\x7d\x8f\x14\xf6\x3d\x34\x1a\xf8\x0b\x0d\x5d\x31\x77\x56\x5a\xf6\xb9\x77\x46\xe2\xbe\x77\x16\x32\xb2\x24\x4a\xcb\xbe\x1e\x92\x00\xa7\x30\x73\x88\x9c\xd4\x49\xf4\x90\x5b\xcc\x3a\x08\x33\x87\x78\xf2\x8c\x70\xf6\xd3\x10\x46\x68\xfc\x9e\x81\xfc\xdf\xda\x2d\xe6\x80\x96\xdd\xaa\xc1\x76\x2b\x88\xec\x33\x56\x06\x14\x5a\xa1\xb2\x41\x63\xe3\x44\x5b\x68\x6c\xba\xc9\x6a\x38\xff\x5b\x04\xc9\xa6\x76\xd9\xef\xf5\xff\xaf\x07\xc3\xff\x75\x0f\x06\xd6\xe1\x8c\xc9\x89\xcf\xb6\x27\x2a\x7b\x3e\x5f\x4d\x81\x91\xa6\x08\xc1\x59\xdb\xcd\xe6\xe6\xb7\x33\xd9\x07\x04\x87\xad\xbf\xd4\x1c\x0c\x61\xe6\x30\xb9\xc5\x14\xd6\x8a\xf5\xd1\x10\x66\x0e\xf6\x97\xc9\xf7\x75\xf2\x50\xd1\xc2\xb1\xfb\x1b\xdc\x7f\x96\xa6\xf9\xef\xbb\xe2\xf3\xdf\x0f\xa0\x6d\xa3\x28\xa6\x03\xbb\x87\x6d\x75\x06\xfd\x3b\x3e\x85\xbc\x8d\x1e\xd0\x99\xec\x5f\x00\xd7\xc1\x81\x74\xbf\x42\x8e\xa1\xa7\x94\xb4\x73\xb5\x9e\x3a\xb2\xbb\x9d\x79\x83\x30\x44\xc6\x9f\x3e\x02\x3c\xdb\x43\x6e\x56\xfb\xf3\x52\x49\x34\xf0\x7f\x3d\x85\x0e\x72\xf0\x77\x4e\xe1\xfc\x56\xb2\x01\xe8\x6f\x1c\xc5\x55\x82\xbc\x50\xc8\xf1\x2e\x4a\x12\xdf\x2c\x82\xcc\x6c\x43\xb5\x4e\x48\x68\xf8\x28\x3c\x63\x95\xb4\xa5\x4e\x26\x75\xa2\xdc\xc2\xcc\x32\x57\xcb\x3e\x6f\x27\xca\x29\xac\xbd\xe4\xf8\x5c\xb1\xca\x8a\x87\x10\xb9\x64\x55\x96\x5a\x0f\x92\x54\xed\x21\xed\x14\xb6\x2f\x8c\xe5\x1f\x73\xc1\x72\x8b\x29\x38\x92\x17\x25\x22\x3c\xfe\x3e\x32\xf9\x3e\xca\x49\xe9\x16\xa4\x8a\x33\x7b\x04\xcb\xe4\xb5\x8a\x6e\x11\x42\x7f\x56\x37\x01\xa6\x4a\x26\x33\xb1\x71\x66\x4a\x49\x8c\x4e\xfe\xcd\x22\xca\x54\xa0\x56\xe6\xa5\x0b\x50\xa8\xad\x4e\x81\x67\xa9\xf3\xa4\x5f\x50\x0b\x0c\x82\x29\x78\x3d\xde\xfd\xeb\x89\x7f\x7f\x08\x8b\xe5\xcd\xcb\xa8\x85\xdc\xb1\x1d\x53\x8e\x4e\x78\xb3\x83\xeb\x3b\x77\x1a\x2e\xc2\xef\xe0\x4d\x78\x51\x0a\x30\xc3\x60\x1e\xde\x73\xb4\x97\x96\x9a\xda\xd1\x1d\x9e\xdc\xd2\x48\x1f\xe6\x18\xa4\x42\x1a\x14\x89\xd6\x5b\xf3\x86\x24\x96\x5a\x29\xe9\x22\x29\xb1\xd4\x49\x38\x2f\xa9\x5b\x98\x90\x29\x19\x69\x0a\xd7\x99\x7d\x69\x8b\x49\x1b\x0d\xfc\xcb\xcf\xfb\x8a\xb9\xab\x8c\x94\xbe\xb2\x42\x08\x5e\xe1\x65\xa9\x65\x49\xcc\x91\xe5\x84\xdc\x73\x52\x35\xd9\x5d\x6e\x31\x47\x41\x98\xb9\xab\x37\xd1\xeb\x52\x2f\x9e\x59\xdd\x59\x99\xdc\xac\x0d\xe7\x59\xc5\xd1\x32\xb9\x09\x48\xbe\x97\x82\x00\x62\xb9\x92\xe0\xb6\x9b\x35\x53\x88\x67\x92\xd8\x93\xca\x8a\x0c\xfd\xac\x23\x98\xbc\xf7\xad\xeb\x0a\x3c\x1e\x8c\x1e\x67\x4b\x2a\x33\x52\x3e\xcb\x06\x0e\x10\xfe\x1d\xff\xf9\x4d\x60\x07\xcf\x8e\xfb\x23\x00\x9d\xff\x4f\xbf\x06\x4d\x38\xbe\x85\x6f\xe1\xef\xf0\xe5\x8e\x1e\x1b\x14\xf2\x6c\x69\x64\xd3\x38\x8c\x3c\x91\x37\x8a\x11\xe2\x1f\xfc\x79\x12\x2a\xa7\x38\x92\x4a\xe1\xc5\x11\x25\xcf\x2b\x73\x64\x96\xb9\x0a\x4e\x5d\x24\x33\x53\x82\x5f\x5f\x2d\xd6\x19\xb9\x53\x9a\x40\x31\xdd\x85\x37\x2c\x3d\x21\x09\xa6\x3b\x7b\xe8\x9f\x42\x7f\x1c\x3f\x66\xc3\xf9\xf5\xaf\xcc\x1a\xbf\x74\x64\x5e\xd0\x47\xbc\x25\xdc\xd4\xd0\xab\x8c\x7a\xf9\xe9\xa3\xcf\x3f\x1c\xd5\x15\x9c\x83\x92\x73\x98\x35\xa2\x2d\x4c\x7a\x38\xb3\x35\xc8\x0b\x75\x46\xd1\xed\x7a\x38\xab\x22\xcd\xde\x1c\x79\x63\x08\x58\x74\x7f\xb7\x43\x33\xbf\xa0\x67\xf5\x8d\x38\xc5\x1b\xbd\xed\x3b\x44\x30\x0d\xc4\xee\x25\xfc\x21\xfe\xca\x00\xd4\x03\x65\x75\xc0\xa1\xae\x04\x44\xde\x9b\xb6\x98\x82\xa2\xc1\x14\x6e\xf5\xb6\x99\x7c\x85\xbe\x09\x5a\xb9\xc5\x1c\x21\x3a\xd4\x4c\x9e\x71\x26\xb5\xcc\x4c\x53\x24\xd5\xe9\x6f\x71\xf2\x19\xc2\xf0\x2c\xee\x9a\x3b\x32\x7a\xdb\x71\x9b\xd5\x75\xec\x27\x22\xfd\xb3\x19\xe4\x85\x02\x51\x04\xca\x69\xc7\xfd\x80\x48\x53\x0f\x9d\xb9\x33\x6d\x31\x85\x44\x93\x96\x28\xaa\x2b\xfc\x33\xdd\xe4\x27\x25\x50\x91\xa1\x72\xa1\x25\x8a\x9f\x8a\x7f\x86\x7b\xc5\xc5\x99\x34\x32\x33\xcb\xc4\xc5\x99\x42\xe5\x26\xa7\xff\xa1\x9f\xf6\xb3\x88\x7e\xd6\x0e\x9e\xeb\xc8\xf2\x6d\xbf\xa3\xec\xfc\x76\x54\x5b\xf7\xb7\x18\x79\xa2\xae\x48\x8b\xc2\xdb\xef\x2f\xff\x96\xe1\xdf\x28\x7f\x5b\xf4\xfb\x82\xd0\x6c\x5d\x67\xed\xba\xfe\xac\xbd\xda\xd5\xb7\x40\x09\xe1\x01\xb7\x92\x1b\x57\xf5\x82\x70\x9f\x73\xb3\x3a\x3c\x17\xbe\x63\x3e\x0e\x55\xea\xcf\xc6\xfa\x1e\x9b\xad\x0c\xdb\x3f\xd2\xbe\x4f\x42\x3f\x9e\x50\x14\xd6\x76\x9f\xc0\xd4\x3d\xd2\x1c\xf6\xbf\x1d\x8f\x76\x8b\x7e\x16\xaf\xbf\x6a\xbb\xe8\x8e\xcf\x4e\xbb\x55\xf3\xeb\x26\xf5\x4b\x92\x0c\xa4\x40\xfe\x28\x8c\x7f\x57\xb9\xd9\xf2\x06\x9d\x75\x75\x32\xce\x0d\xdc\x08\xeb\x85\xac\x2d\xf7\x4e\x16\x93\x5f\xa4\x29\x54\xc7\x1b\x46\x26\x8d\x2d\xe5\x9f\x56\x5a\xf6\x79\xd2\xbc\xc1\xdd\x59\x78\x68\xb9\xd9\x33\xb8\x42\x5c\xdd\x9c\xc4\x30\x7e\x24\x6f\x7a\x93\xa4\xff\xce\x04\xc2\x54\xd6\x51\x06\x97\x10\x75\x7a\x86\xb8\x39\x64\x75\x09\x85\x63\x80\xda\x0b\x5a\xeb\x34\x2f\x52\x48\xc6\x84\x75\x20\x67\xa4\xce\x89\x63\x90\x1c\x75\x45\xdd\x51\xb1\x88\x99\x27\x26\x7f\xd5\x49\x59\x57\x9e\x76\x29\x67\x31\x75\x89\x34\x75\xd3\x99\xbd\xc4\xfa\x97\x30\x6b\x36\xd8\x3e\x05\x21\xd9\x47\x20\xd9\xd5\x9e\x17\x16\xec\xe2\xea\x14\x66\xf6\x97\xf3\x2f\x34\xfe\x0a\x27\x0d\x98\x7c\x14\xfc\x4b\x92\xb8\x5a\x58\xa9\x15\xea\xb2\x55\x5e\x58\xbb\xe8\xbb\x23\xe5\xf6\x5c\x31\xa1\x26\xed\x68\x07\xb6\x9d\x63\xee\x18\x29\x51\xa3\x67\xb5\x57\x2a\x24\x97\x8c\x19\xcd\xd6\xa3\x4e\xbc\x36\x17\xa0\xf9\xf8\x37\x83\x33\xa1\x8b\x55\x5a\x9e\x51\x3d\xed\xd2\x06\x3b\xe4\x00\xbd\xad\x79\x2b\x84\xe1\xcb\x6c\x7d\x0b\x6a\x22\x59\x5c\x36\x2c\x15\xba\x9a\xc9\x16\xc7\x27\xd0\x79\x12\xfb\xf8\x1e\x96\x67\x54\x4a\xdb\xc6\xb7\xe2\x81\xd0\x0c\x0e\x07\x39\xbe\xcf\x64\x8b\x45\xd2\x88\x25\x98\x28\xcb\x25\x19\xc8\x59\x94\xd8\x48\xb4\x42\xb0\x47\x79\x35\xe8\xe2\x2a\x74\xe0\x36\x85\xeb\xea\x68\x85\x33\xc9\x7d\x74\x6d\x2b\xb1\x3d\x6d\x95\xf1\x54\xb4\xc9\x45\x80\x4f\x10\x8b\x2d\x3c\x5c\xc2\x44\x70\x19\x53\x08\x2f\xee\x76\xa1\x35\x49\x48\xd6\x8e\x39\x52\x29\xd8\x16\x12\xde\x3e\xd5\x84\x92\x07\x94\x8b\x88\x95\x40\xba\x55\x07\x10\x17\x9e\xd6\xea\x30\x7b\xa6\x3f\x5d\x48\xf0\xcc\x05\x1f\xd0\xe3\x06\x7c\x75\xfc\xc8\xb7\xde\x58\x59\xf3\x42\x76\xfb\x4d\x85\x62\xd0\xb3\xf5\xcd\x17\x2d\x97\x6e\xdd\xc6\x53\xf3\xf2\x32\x99\xa4\x36\x7b\xfa\xd7\x7c\xb6\xfe\x49\x32\x62\x09\x4e\x4b\x38\xc7\x20\x67\x51\xa2\x23\x6c\xbc\x09\xd3\x99\x5d\xac\x8d\xd6\x7b\xe8\xea\x68\xb9\xc0\x9b\x76\xa2\x1d\x69\x6b\x7d\x2d\xf0\x46\x21\x20\x70\x98\x7c\x48\x91\x8a\x60\x8d\x4a\x89\x4b\x98\x80\x77\xb9\x47\x12\xdc\x9b\x60\x29\x09\x38\x44\x78\x08\x77\x8d\xc4\x47\x26\x37\x07\x76\xe3\x79\x23\x6f\xcd\x1b\x42\xbc\x56\x04\x73\x7d\x1e\x6b\x76\x40\xd4\x7a\x40\x8f\x1e\xfd\xb9\xbd\xf2\x7c\xfe\xb4\x95\xfd\x3b\x60\x4b\x26\x44\x31\xd9\x78\x44\xb5\xd1\xbc\xef\x52\xe5\x80\xde\x74\x55\x1b\xae\x3c\x39\xc3\x64\x3f\xad\x12\xf0\x78\xb1\xa7\x88\xd1\xd9\x19\x95\xb7\x41\xe9\x34\x79\x47\x9a\xa5\xce\x96\x5a\xa9\xb7\xb5\x8b\x49\x07\xb8\x9d\xbe\x7f\x1f\xb7\x93\xb4\x69\x70\x09\x33\x2b\x15\x04\x9a\xd7\xec\xc2\x3f\xf0\xdc\x49\xdb\x35\x57\x29\xb9\xab\xda\x82\x7a\x2a\xbc\x74\xd1\x7a\x5e\x0f\x70\x9a\x40\xad\x23\xc2\x67\x62\x7c\x9f\x32\xd0\xee\xff\x20\x77\x4c\x2b\xac\xcf\xa6\x73\x8a\x3d\x90\x8a\x97\x9b\x3f\xf7\x41\x80\x18\x1c\x4a\x30\x3f\x7d\x51\x29\xb2\xc1\x7d\x9a\xa4\x91\x66\x25\x67\x31\xa1\x48\x53\x27\x9d\x19\x9c\x2c\x26\x49\xb4\x43\x04\x5d\x44\xfc\xf4\x75\xb1\x46\x65\xf9\x45\x7b\xbb\x90\x6e\xb8\xb5\x6e\x84\x11\x6e\x84\x36\x37\x56\x08\xb0\x9b\x5d\x7c\xc5\x82\x53\x64\x56\x4a\x09\x64\xa5\x09\xc9\x6a\x5d\x5c\x15\x56\x48\x2f\x2b\x30\xa8\x52\x27\xd0\x41\x2e\xb1\x04\x68\x05\x13\xba\xe1\x8d\x09\x43\xa2\x7b\xea\x74\x76\xbc\xd0\x13\x78\xbb\x79\xa7\xef\x65\x85\x2e\xb1\x1c\xaa\xac\xf5\xed\x9e\x6c\x2d\xc9\x73\x1d\x26\xfa\xf8\x94\xb6\xfa\x76\xdb\x5d\xea\x13\x69\xf2\x14\xca\xdc\x3b\x43\x98\xd9\xd9\xd3\x56\x5e\x2e\x6f\x55\x0b\x41\x91\x52\x73\x55\xdb\x92\x77\xdb\x02\x13\xa0\x7d\xed\xfb\x40\x70\xda\xff\xc1\xcc\x61\xf1\xf1\x65\x9b\xdb\x14\xc0\xfb\x13\x96\x3f\x50\xec\x49\x15\xaa\xe0\x01\x39\xe3\x50\xe6\x26\xa9\x93\xb5\xae\xd5\xcb\x56\x03\x4f\xd6\x2a\x78\x33\x78\xe3\xd3\xd9\x5b\x08\x0c\x38\x2b\x9f\xbb\x56\xef\xd6\x65\xf1\xad\x99\xd9\xae\x40\xfe\xa6\x95\xa3\x7b\x5a\x57\xc9\x3b\x70\xd5\x56\x2b\xcf\x3f\xe6\x33\x08\x26\x75\x82\xb8\x56\x77\x11\x4b\xca\x49\x57\x47\x53\x88\x75\x0b\x33\xb9\xea\x88\xba\x74\x8e\x06\x82\xbb\xcd\x5b\x2b\x14\x22\x95\xb8\x66\x96\x16\x0f\x72\x14\xa8\xf5\x6a\x21\x5e\xa8\x56\x92\x1f\xa0\x12\xdf\x82\x50\x5c\x61\x63\xe2\x2a\xd0\xe2\x4b\xb0\x1d\x6f\x27\x0c\x9c\x81\xa9\x34\xc2\xc1\x5a\xdc\xbc\xc9\x01\x3f\x00\x21\x66\x13\xa9\x7f\x75\x5c\x0f\xb4\x5b\x8f\xe4\xbf\xac\x47\x07\x1a\xbd\x4e\x60\x97\x4e\xa9\x01\x35\xcf\xa3\xb0\x8b\x57\xf1\x8f\x22\x97\xbe\xbd\xd6\x00\x11\x78\xd7\xbd\x46\x38\x71\x1b\xea\x79\x0e\xe1\xe4\xdb\x38\x41\x64\x0c\x85\xb2\x10\x62\x72\xc8\x5d\x28\x47\x03\xad\x2f\x79\x57\x0b\x61\x4d\x1d\x2d\x75\x62\x85\x3b\xc4\x0a\xc7\xe7\xac\x24\x6d\x74\xdc\xed\x09\xfd\x04\x85\x8f\xbc\xbe\xc9\x7b\x3b\x26\x48\x4d\x6e\xc8\x00\x82\x94\x2c\x23\x99\x33\xbd\xa0\x6b\x19\xe8\x71\x46\x73\x35\xf4\x5e\xf7\x4e\xfe\x88\xba\xf5\x70\xee\x1f\xbf\x50\x51\x4f\x92\xe1\x5c\xde\x54\x58\x39\x8e\xe0\x00\x35\x32\x45\x9c\x27\x92\x23\x7f\xde\xca\x27\x3a\xca\x83\xb8\xf3\x23\xad\xf5\x4d\x0a\x25\xa9\xdf\x72\x12\x6a\x80\xf9\x65\xf8\xc8\x2d\xfc\x59\xe0\x74\xe4\x55\xe3\xa4\x90\xc9\xeb\x68\x77\xa9\x97\x1f\xe9\x57\x26\x23\xbe\x6c\xe1\x7d\x8b\xcc\x9d\x5c\x65\xf2\x3a\xe4\xe6\x4e\xfe\xa3\xb5\x65\x95\x2e\x84\x57\x3c\x1a\xad\x86\xd3\x04\x52\x20\xd8\x60\x82\x53\x33\xeb\xf6\xb9\x4b\x05\xce\x2a\x88\xbe\x1b\xef\x96\x7f\xf9\xd4\x0d\xd0\xcf\x9d\x31\x7f\x36\x5b\xb0\x28\xaf\x88\x0a\x07\x05\xe8\xaa\x17\xe5\x40\xde\x5f\x8d\x6b\x77\x41\x34\xb8\xec\xda\xb5\x62\xa7\xba\x6e\xdb\x47\x02\x1d\xdc\x41\xd2\xa7\x37\x04\x2d\x14\x7b\x16\x29\x74\x66\x7f\x22\x57\xb5\xfe\x3e\xbc\x72\xf1\x77\xef\x14\x26\x32\x38\xc8\xc7\xc6\x60\xad\x90\xcd\xad\xb4\xfa\xac\x1d\x90\xde\xdc\x20\xcc\x2c\xf5\xb0\x90\xec\x12\x12\x8e\xf0\x21\xaf\x77\xaf\x38\x93\x9b\xdc\xa4\x88\x43\xc4\x2f\xc2\xff\x35\x48\xd6\x6a\x17\x6c\xb5\x29\xe4\x62\xb1\xa6\xb2\x11\xd7\xad\xb0\x33\xdd\xc1\xa5\x18\xf4\xf4\xf0\x8c\xf1\x69\x10\xf5\xe0\xd7\x59\xc7\xb5\x61\x7b\x17\xfd\xf2\x1b\xf4\x9e\xf0\xe2\xe8\x9c\xa4\x77\x56\x42\xfd\x3f\xff\x43\x45\x3d\xfd\x74\xe0\x80\xbc\x22\xa8\xc4\xe1\x27\xbe\x4a\x4b\xe8\x97\x7c\xef\xda\xa4\xbc\x01\xf1\xe0\x3f\x5d\xa4\xf7\x1c\x27\xbc\x44\x97\xa0\xda\xae\x3c\xbd\xde\x3a\x73\x50\x27\x8b\xc9\x23\xba\x36\x88\xd4\x43\x07\x29\x3a\x85\x99\x9c\x23\xc9\x43\x14\x5d\x31\xab\x95\x16\x93\x5a\xc8\xf2\xe0\x48\xc2\xba\xc9\x55\x2a\xe0\x39\x44\x5a\x3b\x59\xf2\xb7\x07\xff\x40\xed\xa4\x96\xc9\xf7\xd1\x5d\x49\xfb\x66\xb3\x16\x11\x24\x11\x93\x5c\x66\xf6\xf6\xe5\x35\x48\x50\x57\x19\xe9\x64\xef\x2c\x33\xa3\xb0\x38\xfb\xae\x46\x80\xde\x6a\x52\x27\x80\x23\xf1\xc8\x71\x8f\xb3\xae\x9d\x38\x3f\xc3\x59\xe2\x01\x51\x23\x32\xc7\xa6\x40\xf8\xbd\x5f\x16\x6e\xe9\x1b\x71\x32\xf3\x3f\xf8\x4f\xd0\xe7\x4c\x2f\xc8\x63\x66\x14\x9d\xa3\xc2\x41\x0a\xb1\xd5\x21\x6b\xba\x43\xde\xd3\xe9\x29\x83\xf3\x8a\xfe\xc2\xc7\x4f\x5e\x48\x48\x35\xa4\x43\x37\x50\xee\xda\xb5\xb2\x4a\x5d\xbf\x15\x01\xf2\x69\x69\xe4\x76\xb0\xe7\x51\x37\x84\x14\xb1\x6a\x87\x30\xb9\x97\xe3\x16\x88\x51\xde\x00\x21\x52\xee\x73\x16\xfc\x7f\x06\x77\xe3\x26\x73\xfd\xa8\x31\xe3\x86\x43\xd4\x03\xcb\xdd\x3f\x4e\x7c\xba\x67\x0f\x64\xce\x2c\xda\xf6\x16\x1b\xff\xe6\xa1\xf7\x56\x1e\x0b\xe2\xbc\x3e\x5c\x3b\x75\x9c\xb0\x01\xa7\xbe\xbc\xf5\xaf\x19\xb3\xaf\x35\xa4\x65\xe6\xda\xe2\xb2\x5c\x16\xc1\x8e\x45\x0a\x5b\xc8\xd8\x4b\xe9\xe9\x48\x7b\xdb\xd8\x72\xdc\xc2\xab\xaf\x9d\x7f\xd8\xf0\xeb\x6e\x42\xf6\xad\xeb\x4d\xeb\x56\x6c\x5d\xbf\x7d\xf9\xd4\xb9\xc3\x6a\x87\x33\xfe\x11\x21\x24\x1a\xac\xfd\xec\x25\x42\xec\xa9\x2f\xdf\xaa\x9c\x9a\x47\x42\xc5\xc1\x81\xc2\x9c\x3e\x38\x83\x2d\x66\xcf\x23\xff\xd6\xb4\xfa\x81\x60\xb7\xda\x68\xe4\x49\x6c\x80\xee\xbf\x83\x37\x4f\xa2\x80\x76\xd1\x70\xb6\xbe\x1e\xe6\xdf\x7f\x7f\x97\x23\x75\x3b\x78\xdb\x19\xf6\xf0\x84\x19\x45\xba\xd2\x70\x01\x1b\xce\x14\xa3\x40\x47\xba\xda\xce\x61\xa3\x28\x8d\x84\xbc\x1b\x96\x16\x10\xd0\x8a\xab\x6f\xbd\x57\xbd\x7d\xcf\x9b\x24\x18\xce\xf8\xdb\xa3\xdb\xd3\x48\x95\xce\xe0\xb4\xa1\x62\xe0\x9b\xd4\xf1\xb5\x34\x4a\x36\xb1\xf5\x48\x8d\x90\x43\x99\x5c\xeb\x83\xa3\x17\x0a\xe6\x34\xf6\x82\xb9\xb9\xd4\xf0\xb1\xe3\xd3\x20\xfa\xc1\xdd\x7b\x0f\xf1\x09\x69\xdf\x89\xfb\xb6\x3b\xd6\xcc\x1d\x4f\x7a\xc1\xba\x5d\x67\x4f\xd0\x09\xcb\x30\xe0\xa9\x62\xdd\x20\x6a\x69\xe4\x6e\x90\xde\xfe\xc8\x5e\xf5\xd6\x5a\x54\xf5\x32\x8d\x63\xfd\x5b\xa4\x28\x9e\xb7\xee\xdd\x7f\xd2\xaa\x00\xae\xd9\x37\xf9\x05\x71\x8b\xce\x9e\xa2\x90\x43\x1d\x5c\x4b\xa3\x64\x0f\x89\xd5\x23\x5b\xe1\x57\x2b\x31\xd4\x8a\xe5\x55\x9d\x41\x3f\x74\xcc\x98\xa1\x10\x75\xef\xd6\xcf\xf7\xa8\xe6\x9f\xc5\x0a\xab\x33\xbc\x9c\xf3\xcb\x3f\x79\xe1\xec\x71\xa0\x9a\x57\xf2\x6f\x9a\x96\x46\x09\x43\xee\x7a\xdb\x98\x84\x49\xf6\x03\xa6\x17\xca\xa3\x36\x42\x34\x95\x36\x72\xcc\x50\x08\xb7\xfc\x74\xe7\x2e\x85\x67\x0a\x25\x52\xcd\x3e\x49\xc2\x62\x4f\x9f\x3f\xf7\x79\x06\xd6\xf1\xeb\x2c\x69\x69\x64\x1f\xb0\xe7\x91\x1f\x42\x04\x54\x2c\xc0\x0a\x2a\x66\xe3\x87\x5a\x49\xc2\x01\x25\x1f\xc3\xb0\x9b\xe0\x79\x6b\xe6\xdc\xa3\xf9\x9f\x5d\xbd\x76\x69\xeb\x5e\xbc\x8a\x3a\x84\x3f\xc6\x87\xf0\x36\xbc\x94\xba\x7e\x1b\x46\x7f\x32\xf3\x49\x5c\x77\xfc\xf8\xee\x3d\xfc\xfe\x66\x09\x50\x65\x78\x2b\xde\x02\xaf\x0b\x3c\xe7\xef\x96\x87\x4c\x31\xbf\x76\x07\xf0\x2e\x8e\x34\x31\xd3\xab\xf5\x6a\xa5\x54\x1d\x80\xb2\x60\x10\xf4\xf8\xe9\x64\x56\xca\x27\x49\x3b\xdf\x06\xe5\xd2\xf5\xf8\x3b\x2a\xab\xf9\x30\xfe\x19\x9f\xa5\xb4\xd0\x05\x7a\x66\xdc\xd5\x68\xdf\xdf\x87\x0f\xce\x9b\x72\x6b\x42\xb3\x19\xba\x8b\x18\x3c\x2d\x8d\x6c\x0e\xc1\x18\x47\x8a\x0e\x38\xad\x17\x10\xb6\x52\x32\x32\x53\x21\xea\xd7\x9f\xef\xdd\x17\xd1\x71\xce\x59\x59\x7c\xea\xcb\xf3\x47\xe8\x7e\xc2\x58\x91\x2d\x8d\xec\x60\x52\x57\x89\x04\x24\x9b\x36\x2a\x4c\x40\xce\x1a\x91\x99\x91\xca\x8b\x83\xe5\x3e\x45\x97\xde\xbe\x8d\x19\x51\x2b\x9d\xfa\xf2\xcc\x49\x8a\xe2\xc7\xc9\x6c\x69\x24\x38\x71\xbc\x4e\x88\x89\x35\xe8\x23\xc4\x3e\x4f\x8c\x0d\xc7\x8e\xf4\x7b\x12\x00\xed\x82\x0c\x32\x4e\x1d\x10\x94\xf9\xe5\xfe\x77\xf7\xbf\xfe\xe4\x5d\x13\xd0\x0b\x96\x1f\xfb\xaa\xa2\xe2\xf2\x2f\x2f\xad\xbc\x7b\xcf\xb8\x67\x09\x74\x9a\x7c\x1c\x1f\xc5\x3f\xe0\x7a\xd8\xb1\x6e\xbf\x82\xf3\xf9\x74\xf5\xf4\xf7\x5f\x7c\x61\xf8\xed\x92\x91\x29\x79\x99\x0f\xf3\x27\x4f\x9b\x1c\x15\x89\x7f\x1d\x7e\x57\x38\xb7\x2d\x8d\x4c\x30\x53\x8c\x42\xc4\xb9\x43\x04\xb4\x3c\x5b\x03\x42\xdb\xd4\x6a\x52\x7f\xaf\x0e\x08\x4a\x5b\xf2\xe6\x65\x7c\xb7\xd8\x92\x99\x5d\xf2\xfa\xb0\xa2\x39\x15\x6b\xb6\xee\x5e\xb7\x1e\x5c\xa7\x7d\x37\xae\x06\x3f\xc1\x8f\xf0\x1d\xd0\xcf\x5c\xd6\xc5\x39\xaa\xa1\x72\x4b\x44\xc8\xf5\x9e\xfe\xd1\xb1\x03\x0d\x97\x06\x24\x2d\x0a\x0f\xfd\x63\xd8\x2e\xb1\x16\xd7\x93\xcb\x69\x77\x86\xd5\x6d\x2c\xf1\xf6\x45\xaf\xc1\xc4\xd2\xed\xd3\xbf\x37\xbe\xd0\x41\xe1\x6b\xb2\x68\xef\x66\x8c\x4e\x75\x2c\x7f\x25\x36\x7a\x28\x5b\xd1\xf6\x0c\xb7\x35\xfc\x5b\xd7\xb0\x36\x6d\x58\xf3\xe2\xd0\x98\x48\x9d\x0e\x37\xb4\x2b\x63\xb5\x9b\xab\xb6\x62\x56\xa2\x97\x9c\x34\xc4\x8e\x70\xa0\xc9\x66\xc3\x77\x02\x4d\x6b\x8d\x44\xed\xb0\x59\xf0\xf7\x05\xc3\x13\xd7\xc1\x6d\xfc\xc3\x6f\x6d\x75\x93\x60\xcc\x37\xfb\xf3\x96\x28\xf5\x10\x3e\x6f\xa3\x9b\x24\x94\x70\xc6\x6d\x74\xf9\x92\xf9\x5c\x40\x0d\xb4\xa3\x56\xa2\x76\x5f\xfb\x0e\xc6\xe3\xf5\xb0\x08\x1b\x1b\xef\x61\x23\x94\x35\xfc\xd4\x8a\x2c\xc1\x16\x6f\x3e\xc5\x1b\x9a\x54\x3c\xf4\x15\x08\x23\xf9\x2f\xdc\x03\x82\xff\xab\x22\x9a\x24\x40\x98\x00\x38\xb5\xc6\xc7\x96\x66\x73\x00\x2e\xc1\xcf\xba\x6f\x45\x72\xde\xc1\x4b\x57\xe3\xdf\x2b\xf2\xd6\xbc\x41\x5a\x86\xe0\xd5\x30\x8f\x50\xb0\xb8\xa4\xf9\x31\xcd\x15\xcd\x9a\x9d\x2f\xf4\x0b\xe1\xae\x31\xc5\x24\x26\x85\x48\xf7\x0e\x22\x76\x84\x67\x34\xf1\x2b\x8a\xed\x3b\x74\xd1\x32\x5b\xe7\x0e\xf7\x99\xdf\x6c\xb9\x18\xda\x60\x25\xe4\x87\xe0\xab\xdb\x85\x06\x1e\x17\xec\xbd\x3b\x8c\x87\x3f\x82\xd1\x84\x92\xfc\xba\xb3\xb6\xde\x1d\x90\x4e\xfa\x76\x50\x2d\x8f\x10\xe2\xaa\xc9\xf9\xef\x8a\x90\x06\xf8\xa3\x16\x14\x0a\x0e\x65\x15\x1a\x50\x58\x2d\x61\x67\xd8\xf1\xf2\x6b\xe0\x07\x2e\xf4\xcf\xcd\xf7\xe0\x01\x96\x52\xca\xa6\x63\xc7\xf0\x9e\xa5\x4b\x5e\x5b\xfb\xd6\xc2\xd7\xa8\xf2\xe8\x86\x37\xce\x5d\xb3\xa6\xce\x53\x51\xcd\x17\x69\x3c\xb9\x10\x56\x65\x20\x9a\xdc\x1b\xb7\x09\xc6\x46\x28\xea\x89\x50\x14\x08\x38\x94\x6a\x25\x69\x52\xd2\x2a\x83\x3d\x30\x48\xab\xa1\x6d\x93\xb2\x42\xc0\x0b\xc2\x67\x15\xfc\xfb\x1b\xb8\xd7\x73\xf3\x88\x86\xa7\x0e\x59\xec\x8d\xf8\x7b\xf5\xee\x26\xdd\x9c\x71\x7b\x1a\x52\xc6\x50\xdb\xc5\xf4\x75\x38\x18\xbe\xa7\xb8\xea\x40\x7a\xb4\x1e\xff\x76\xcf\x9a\xc2\x7e\xeb\x6b\x3c\x89\xa6\x06\x0f\x87\xce\x43\xdf\x24\x19\xec\x02\x26\x65\x35\x89\xcb\x7b\x58\xb5\x6b\x00\x92\x49\x29\x09\xa8\x41\xe3\x98\x3d\x61\x8b\xd5\xee\x37\xc3\x24\x5c\x8c\xff\x50\xb5\x4e\x95\x70\x08\xcb\x62\xbc\x73\x24\x2e\x81\x24\x87\xe4\x08\x01\xfb\x91\x29\x22\xf9\xe6\x01\xfc\x3c\x72\x7e\x73\x75\x06\x21\x17\x85\x94\xed\xb4\xb2\xdf\xb3\x6e\x9f\x99\xb1\xbd\x8f\x93\x2f\x50\xf8\x2b\x37\xb7\xa8\xaa\x19\xa7\x7f\x04\xc3\xcc\xa2\x79\xb3\xd8\x82\xb2\xab\x54\x38\xc8\x21\x66\xc4\xe8\x35\x7f\xd5\xc3\xe5\x84\x99\x23\x47\x43\x14\xb8\xee\x36\x56\x18\x83\xeb\xb6\x59\xdf\x8a\x92\xc3\x6c\x3d\x7f\x2f\x11\xe7\x74\x5f\x30\x28\x84\x8a\x46\x20\xe0\x75\x74\x08\xa5\x75\x07\x09\xad\x86\xa8\x43\x51\x5e\x5c\x98\xe2\x32\x04\x5f\x76\xef\xee\xe2\xdc\x43\x7e\x10\xa2\xf0\x6a\xfc\xee\x69\x17\x3d\xc3\xf5\x74\x3b\x85\x77\xb0\xf5\x4d\x3f\x5d\xaf\x8a\xfb\x6d\x20\xad\x6b\xba\x60\xf8\x69\x64\x9a\x25\x89\xee\xfa\x24\x99\x46\xa1\x00\x3d\x62\x7f\xd3\x35\x8b\x3a\xc5\x13\x21\xee\x14\xf1\x63\x20\x85\x5a\xe1\xa5\xd0\xc5\xf6\x03\x61\x52\x9d\x38\xab\x0b\x68\x68\xb5\x27\xf4\x5c\xea\xa5\x75\x62\xfc\xa5\xaf\xc3\x88\x72\x57\x0d\xe5\xe4\xd2\xcd\x7d\x19\x84\xe1\x23\xb8\x2e\x63\x6e\xa7\x2f\xf1\x01\x26\x1b\xcb\x32\xb1\x25\x75\xd7\x18\xca\xbb\xf9\x17\xc3\xe5\xde\xe3\x6e\xea\xe0\xb7\xa7\x55\xb0\x1c\xee\x37\xad\xb2\x61\x41\x4d\x62\xcf\x23\xb9\x70\x97\x83\xd6\xa0\x32\xa8\x41\x25\xd1\xf2\xdb\xc6\x1b\x06\x10\x70\x72\xfd\x9e\x62\x48\xc6\x7f\x35\x6e\xfa\x7a\x03\x15\x85\x77\x08\x40\xf7\xb0\xf4\xe2\x4a\xd3\xdb\xd8\xf8\x68\xe5\xb5\x23\x42\x86\xaf\x0d\xcb\xe9\x0f\xa6\xd8\x3a\x9e\x82\x8c\x47\x5b\xc7\xdb\x01\x51\x0f\xca\x56\xe5\x0d\x86\x11\xb7\xcc\xab\xdf\x99\x08\x3f\x61\xa3\x80\x51\x0f\x3d\x97\x96\xcf\xce\xc4\xf7\x3f\x2d\x37\x16\x0a\x49\xb2\x44\x97\x23\xa7\x0a\xb6\x1e\xf5\x68\xa5\xcb\x9f\x87\x41\xdc\x46\xad\x67\xce\xdc\x78\x02\x7a\x6e\xb1\xc2\x52\xac\x7e\xef\xe7\xff\xe8\x93\xf1\x79\x7c\xbd\xad\x82\x6f\x2e\x72\xad\xc1\x0d\xe7\x6d\x20\x15\x5f\x7d\x4c\xfa\x9f\xb4\xd3\xf5\xce\xdc\x41\x26\x9b\xbf\x4b\xed\xba\xfe\x99\xc0\xc1\xad\x0c\x37\xcd\x88\xcd\xbf\xbf\x66\x6b\x58\xf2\xca\xdb\x1b\x9d\xf0\xc5\xfb\xad\x95\xa4\x88\x25\x6c\xed\x5e\xb2\x6b\xa3\x80\x25\x6c\x35\xe5\x44\xdc\xe7\x4b\x6c\x3d\xaf\xd5\xac\x76\xd7\xf3\x01\x99\x21\x96\x0a\x82\xd8\x19\x9b\x1c\x99\x20\xf4\x7c\xc1\x5f\x34\x7f\x27\x58\x78\x6d\x49\x17\x5b\xbf\x08\x45\xf5\x04\x9b\x40\xe2\xc4\x64\xf3\xb6\xb7\x75\xce\xe7\x41\x25\x0b\x35\xf1\xad\x88\x5d\xb4\x6d\xbd\x93\xbd\x3c\xbe\x2d\x99\x3b\x37\x6f\xde\x8a\x97\x3b\xe0\x7c\xe3\x0c\x2e\x9f\xd4\xf3\x22\x47\x64\xee\x03\x4c\x85\x88\x59\xfe\x33\x5b\x6f\xc5\xa1\x20\xd0\xd1\x62\xdd\xff\x1e\x82\x4d\xda\xea\x9b\x1d\xf4\x63\xf2\x04\xf8\x8a\xb7\x3b\xad\x08\x11\x04\x9a\xd9\x01\x77\x5d\xb8\x79\xec\x50\x61\xea\xf6\xe8\x65\xc2\xc4\xad\x10\xcc\xf0\x5e\x52\xa7\x6d\x43\x31\x13\xd6\x70\x90\xf3\xb4\xda\xc4\x9e\x1e\xa0\x8b\x75\x1c\x92\xb7\x73\x78\xf6\x48\x24\xd2\xbc\xef\x4f\x7d\x29\x00\xea\xd5\x2d\x99\xcb\x79\xe2\x13\xc1\x2b\xc7\x57\xff\xe3\x34\xe6\x48\x8b\x86\xca\x87\x7b\x4f\x34\x3f\x14\x62\xdf\x08\x31\x79\x4c\x36\x92\x20\x57\x84\x74\xd6\x12\x4e\x35\xad\xe5\x3c\x61\x03\x84\xc2\x46\xfc\x64\x34\x9e\x3c\x7a\x2d\x84\x4e\xd6\x2b\x98\xec\xa7\x55\xe0\x8a\xff\x80\x8b\xa0\x37\xa5\x92\xef\xa5\x08\xb1\x46\x82\x87\xa0\x20\xdf\x5b\xfb\x15\xf1\xff\xa7\x15\x6a\x99\x46\x4a\x21\x7a\x13\x4e\x82\xb7\xf1\x54\x38\xd0\x9c\x81\x97\x96\x5c\x04\x6d\x0e\x93\x7d\x04\x1f\xc5\xdf\x1f\x07\x77\xfc\x10\x1a\xe0\x0c\x89\x8d\x65\xb6\x34\x4a\x10\xa9\xef\x8b\x40\xbd\x88\x4d\xca\x5f\x25\xa4\x9e\x82\xf4\xc8\x17\x5c\xd6\x1e\xc2\x23\xd7\xa0\xe2\x85\x83\xbc\xb2\xc5\xfc\x24\x83\x08\x20\xad\xcc\xa4\x2e\xb1\x6b\xca\x4f\x1e\x18\xf7\x59\xc9\xca\x1b\x49\xb9\x27\xb6\xbf\x77\x82\xd4\xcf\xbd\xfe\xfe\x94\x43\xf7\x48\xfd\xdc\x77\xb8\x05\xfc\xa9\xe9\xe3\xae\xc9\x20\xae\xe8\xe5\x97\x57\x4f\x79\x09\x84\xe2\xb8\x1e\x41\x79\xd3\x17\x8e\x3d\xb2\x4b\xac\x9c\x4b\x3b\x9f\x5b\x3e\xa0\x3f\xc8\xf6\x15\xbc\x7c\x6f\x37\xc3\x8c\x7d\xf1\xd5\x97\xf2\x84\x38\x9e\x1c\x21\x26\x89\x60\x98\xfa\x11\xdb\x53\xaf\x93\xa9\x05\x90\x66\x9d\x52\x43\x3c\xeb\x6a\x99\xa2\x4d\x9e\x75\x18\xc8\xb7\x40\xee\x1f\xdf\xfa\x75\xa9\xae\x30\xfc\x78\x12\x8f\x7e\xf8\xee\xd4\xec\xa9\x79\x9b\x2b\x27\x65\x4d\x9e\xb6\x14\x1a\x0f\xc0\xc1\x15\x1b\x22\xc7\x74\x3e\x10\x3f\xf3\xad\x8f\xa0\x11\x5f\x4e\x1d\x9e\x3c\xf8\x40\xfc\xe0\x81\x71\x82\x3c\x95\xb6\x3c\xa0\x6f\x10\x3c\x62\x44\x0a\xc9\x44\xf3\x5a\x2a\x98\xb6\x9a\x40\x54\x0a\x5d\x9f\x54\xed\x1d\xb1\x2d\x77\xe5\x46\xe8\x9a\xf4\xfa\xa8\x37\x3f\xfc\x0b\xff\x87\x8a\x04\x57\xe8\x95\xf6\x59\xd2\x85\x3a\x5c\x1e\xd0\xe5\x54\x1c\x84\x21\x0a\x99\x10\x62\x72\x99\x6c\xe4\x84\x3c\x04\xbb\x88\x24\x5e\x68\xc9\xf5\xa9\x31\xc1\x74\xf0\x04\x03\x3e\x8a\x1b\xd2\xf3\x61\x12\x3e\x54\xce\x64\xe3\x1f\xf1\x53\xdc\x88\xbf\x3d\x0e\x73\x61\xb6\x70\x17\x0f\x16\xc7\x70\xe5\x25\x9c\x70\x80\x8c\x12\x0a\x32\x85\x30\x8e\x4c\xa7\xd4\x0c\x9e\x61\x1f\x0c\x1f\x7e\xc8\x0f\xf7\xe9\xd2\x83\x07\xe1\xc2\x11\xb8\x64\x1d\x13\x2e\xe0\x3f\xf8\x61\xf1\xbd\x23\x3c\x9d\x26\x84\xe8\x44\xdb\x59\xb3\x49\x94\x89\xda\x80\xb3\xa1\x02\x97\x41\x15\x93\x7d\xe4\xc9\x51\xfc\xaf\xe3\x02\x5f\x32\x5a\x1e\xd0\x97\x99\x02\xa4\xb5\xbf\xdd\x45\x67\x08\xb1\x90\x3b\xc8\x77\x97\x64\x4c\xbf\xf2\xda\xa7\x3f\xbe\xbd\x62\xfb\xee\xe6\x5b\x4f\xb6\x0e\x3d\x37\x6a\xcb\x8a\x83\x75\xb3\x27\x7d\xb2\x3b\x7f\xfa\xee\x4a\xfa\x51\xff\xb8\x2d\x8b\xf3\xdf\xf4\x64\xa4\xaf\x17\x6d\xf9\x24\xe1\x44\x60\x48\x46\x7a\xf2\xf0\xfd\x89\x23\xe3\x13\xc7\x23\x0a\xad\xc5\xc9\x70\x9d\xf0\xce\x15\x09\x15\x3e\x4a\x4f\x4d\x20\xff\x1c\x5b\x3b\x6a\x94\xd1\x68\xf4\x80\x28\xfc\xc3\x90\xe1\x9b\x36\x42\xbd\x18\x13\x81\x96\x3d\xf8\x30\xbf\x6c\xe4\x86\x90\x44\x78\xb1\x89\x06\x7c\x46\x42\x6c\xda\xa0\x87\xfb\x6b\x47\xf6\x2d\x72\x9f\x90\xcf\x78\x3f\xbd\x7b\xf2\xac\x42\xa0\xcb\x24\xca\x18\x7f\x32\x65\x3a\x7b\xeb\x09\xd3\xc3\x49\xa0\x07\x0f\x5c\x08\xeb\xf0\xaf\xf8\x72\x3e\x93\x8d\x9d\x97\xc2\x7c\xd2\xf8\xe2\xe6\x20\x9c\xc3\x7f\x1b\x86\x10\x5d\x26\xcc\xa7\x30\xf0\x1f\xab\x24\xe4\x50\x4a\xc2\x2a\x1f\x16\x65\x5d\x80\x86\xe6\x04\x3d\xdc\x1e\x4d\x05\xe3\xe9\x03\xd6\x97\xe0\x13\xc7\xa1\xc8\x5f\x9c\x93\x2d\x61\xb2\xc9\x69\x16\x41\x26\x34\xbc\xc9\x03\x1a\xd0\xf8\x83\xcc\x04\xc9\x20\x65\xc0\x1f\x92\x6f\x38\x73\xf8\xda\x75\x7c\x8f\x73\x66\x98\xec\xa6\x6a\x3a\xeb\x69\x15\xe5\x37\xe7\xe7\xa6\x35\x74\xf1\xd1\xaa\xe6\xfb\xd6\xf5\x0b\xba\x41\x18\x2b\x84\x27\x5a\x2d\x8e\xa3\x83\x07\x9c\xeb\x35\x7c\x01\xbb\x73\x12\x09\x93\xdd\x54\xf7\x4b\x12\xd5\xe5\x69\x15\x3d\x7a\xde\x99\xe6\x3b\x82\x7c\x95\xb6\x3c\x60\x0e\x32\x05\xc8\x85\x5f\x4d\xab\x2c\x59\xa9\x9a\x97\xaf\x80\x52\xf0\x01\x67\x60\xc1\x07\xdf\xc6\x4f\xf1\x5f\xf8\x67\x40\xa0\x86\x40\xfc\x23\xbe\x4e\xe9\x40\x09\x5a\xfc\x4f\x7c\x17\x5b\xf0\x15\xe8\x01\x4a\x5c\x0e\x8b\x60\x11\xbf\xae\xa4\x96\x07\xb4\x89\x29\x20\x52\x1b\xab\x8b\x16\x4a\xb5\xec\x72\xc2\x2b\xe6\xa4\x5d\x87\xfe\x04\x05\xfe\xa5\xe9\x83\x95\xe9\xaf\x0d\xda\xbc\xf5\xed\xd5\x83\x4a\xe3\x18\x75\x1a\x6e\xc0\x7f\xe2\x7b\xf8\xeb\xb8\x53\x5d\x02\xce\xd5\xd7\x9e\x0b\xf3\x23\x3e\x6d\x27\xe6\x26\x93\x48\x72\xf6\x78\x79\x20\x75\x73\x9e\x04\x4b\xd1\xe0\x90\xb8\x9a\xb5\x1a\x38\x13\xc8\x20\xa6\x12\x3f\x36\xe1\xdf\xf0\xc5\x47\xbb\xde\x17\x32\x4f\xa9\x50\x87\x8c\xca\x80\xe6\x97\x66\x91\xf4\x55\xc1\x97\x80\x16\x33\x37\x19\x84\x94\x28\xbc\xbf\x52\xee\xe1\x81\x58\x17\x17\x27\x44\x7b\xa9\x14\x0a\x4a\x42\xb9\x2d\x1f\x47\xa1\xc8\x30\xe4\x1d\x29\x8f\x8b\x94\xc9\x41\x15\x27\xe3\x25\x45\x17\xd5\x53\x21\xe5\xb9\xe5\x29\xd1\xf2\x4a\x51\x1d\xa0\xf4\xf4\x52\xa9\x23\x20\x8b\xea\x0b\x5d\x21\x2c\x45\xc4\xff\x8e\x8e\xc0\x4d\x91\xc1\xf0\x88\x72\xc6\xb7\xf0\x7f\x4e\x6e\x11\xb0\xc3\x27\x6e\x18\x9c\xf2\x36\xaf\xe3\x82\x11\xc3\x52\x4c\x3f\xa4\x40\xbe\x48\xc3\xcb\x91\x2a\x56\x18\x54\x25\xd1\x72\xfc\x4f\x31\x06\x15\x51\xc5\xc0\x19\x40\x20\x32\x38\x7f\xea\x3b\xa0\x00\x39\x44\xea\xd2\x67\x8d\xde\x86\x9b\xf0\xaf\xf8\x42\xf8\xb9\x0f\xde\x4f\x8f\xc7\x51\xee\x7b\xe0\x5b\xd5\xae\xf7\xa7\xd0\xe9\x5b\x13\x37\xe3\x1b\xb8\x65\xd9\x5c\xfd\x16\x43\x25\xa8\x01\xbd\x54\xf0\xeb\x4b\xb3\xdc\x40\x1f\xf2\x2e\xfe\x3c\x22\xe1\xa5\x99\xb6\xfb\xa0\x84\x29\x46\xfe\xa4\x5a\x89\xbf\x0f\xf4\x0e\x15\x76\x2a\xa1\x7b\x1b\x49\x53\x14\x00\xf1\x85\x27\x49\xb0\x03\xcb\x33\xa9\xbb\x92\x8d\x15\xb9\x07\x66\x8f\xff\xec\x15\x70\xdf\xf4\xc6\x5f\x55\x8f\x2b\xf0\x2d\xdc\x52\x78\x76\xc8\x9a\x07\xff\xc6\xbf\x81\x3f\x35\x6f\xfa\x94\x05\xce\xd0\x7b\x96\x90\x30\x3c\x13\xee\x6c\x70\x5a\x5c\x49\x6a\xec\xb6\x6d\x5b\x8d\xff\xda\x87\x1b\xf1\xa5\xb4\x61\x6f\x83\xeb\x81\x39\x8b\x16\xcc\x5f\x64\x34\x92\x4d\x23\xf2\x39\xbf\xe5\x21\xa3\x27\x35\x20\x81\x82\xf7\x21\x02\x12\x40\xa7\xf4\xd4\x45\x93\x3f\x38\x89\x18\x61\x35\x78\xea\xa2\xf9\x9b\x69\xfe\xa4\xdc\xd4\xa1\x0f\x8f\x1d\x79\xf8\xc2\xe8\xd3\x8f\x2d\x77\x1e\xe3\x1b\x37\x6f\xdc\x84\x45\xd3\xdf\x0b\xef\xb6\x7c\xde\xf2\x8a\x8b\x17\x2b\x2a\xa6\xae\x8b\x18\xfb\xfd\xb1\x0b\xe7\x3f\xbf\x70\xe1\xbc\xb0\xff\x94\x96\xe4\xf2\xca\x79\xfa\x85\xcc\x4c\x3f\x50\x0b\xd4\xf9\x81\x2d\xf3\xf2\xec\xac\xb2\x97\x66\x51\x5a\x67\x6b\x62\xa5\xb3\x33\xbf\x50\x67\xbb\x3f\x6a\x0b\xa5\x25\xba\xc0\x5a\x6b\x4c\x21\x4d\x20\xca\x02\x03\x55\xb8\x60\xe1\x4c\x0a\x7a\x31\xf8\xa7\x96\xc7\xf8\x07\x4a\xbb\x7b\xfb\xae\xf7\xf0\x43\x7c\x09\x0c\x84\x46\x5e\x17\x9f\x61\xb2\x49\xfc\x1f\x59\xef\x38\xd2\x6e\x53\xd4\xa9\x26\x28\xf8\xe6\xca\x9d\x2b\xf9\xe9\xb3\x8a\xb2\xa6\xce\x61\xb2\x3f\xfe\xb0\xee\x28\x2e\xa0\x46\x8c\x1d\x33\x6a\x24\xa2\xf8\x37\x8d\xd8\x23\xd1\x8b\xb7\x0f\xc4\x57\xa4\x4c\xe3\xf8\x4e\xf5\x83\x41\x93\xf2\xbf\xff\x06\xe6\xfd\xbe\x05\xff\x91\x97\x3b\xad\xb8\x34\x7b\x1a\x3c\x08\xda\x5e\xb0\xd9\xf8\xb4\x0a\x6a\x71\x1a\x2d\x4d\xc9\x80\xa8\x81\xa8\xd5\x78\xfc\x2d\xa8\x06\x5e\xdc\xd5\x81\x21\xfa\x98\x58\x83\xc2\xd3\x3a\x9c\x3b\x38\x6f\xf9\x1d\xaf\xfe\xea\xa7\xbc\x9c\xf0\x53\xa5\xc5\xd3\x72\x45\x90\xa9\x2a\xe3\x5b\xb3\x77\x68\xf1\xf5\x75\x10\x3b\x56\xd4\x91\xab\x88\xed\x23\xfa\xbf\x34\xb2\x30\x7a\x12\x3e\xf7\x90\xde\xf6\xf9\xe7\x4d\xb9\xf4\x36\x04\x68\x6b\x4b\x23\xb3\x9d\xc4\xcd\x90\xc2\xd1\xdb\x26\x45\x9a\x00\xb4\x15\xa2\xa6\xcf\xcd\x99\x0a\x51\xf8\x69\x4b\x0b\x6a\x41\x80\xa9\x49\xcd\x9b\xd6\x2d\x5d\xba\x8e\x9a\xd1\xbc\x03\x3f\xc2\x8f\x01\x10\xa0\x34\x14\xc6\x1c\x67\x74\xc8\x13\xf5\xe9\xdf\xd5\x55\xe6\xe6\xee\xce\x76\x42\x32\x16\xb1\x4a\x2f\x04\xcb\xc7\x21\xb7\x4e\xce\xce\x9d\x96\x8f\x43\xce\xe0\x8c\x22\x27\x84\xc9\xe4\x28\xce\x3b\x32\x4c\x26\x87\x38\xf1\x38\x0b\x47\xda\x20\x53\x0b\x72\xcd\x5f\x86\xd6\xfb\x2d\x8d\xaa\x2c\x2d\xfd\xf0\x74\xf3\x43\x26\x7b\xcd\xc8\x51\x97\xce\x84\x41\x54\x46\xf6\x92\xb9\x10\x65\x09\x95\xe9\xf6\xcd\x3d\xf1\x05\xa2\x51\x22\x0a\xe3\x72\x19\x1d\x72\x41\x2a\xfe\x9d\xd3\x2a\xa5\xd7\xe1\x67\xb6\xa3\xf1\x13\x53\x07\xf4\x19\x39\x34\x71\x60\x0a\x95\x3a\x60\x40\xf2\xd0\x81\x03\x53\xa0\xc6\x61\xca\xe1\xa3\x2f\x9d\xa6\x1e\xf7\x19\x3a\x20\xb1\x5f\x52\x32\xfe\xa0\xcf\xd0\x21\x7d\xfb\x25\x25\x37\x39\x2c\x22\x7a\x5f\xf1\x89\x2f\xac\x3e\xf6\xeb\xcc\x71\x76\x31\x7f\x5a\x0c\xea\x68\x71\xa6\xb6\x53\x5a\x27\x56\xa7\x51\x95\x0f\xdf\xfb\xa8\xf9\x22\x3f\x5b\xcd\x29\x32\xdb\xb0\xb1\xd5\x69\x19\x27\xae\x36\x6b\xdd\x77\xcf\x9d\x03\x51\x23\xc7\xce\x9f\x41\xe6\x08\xdf\x33\xe7\xe9\x38\xdf\xc8\x8f\xe6\x1c\xfd\x5c\x7c\xdb\x32\x5a\xe1\xde\x54\xe8\xac\xef\x68\x1d\xa8\x3d\x1f\x5d\x75\xe9\xc1\x76\x0a\x93\x5c\x7b\x84\xcb\xf0\x23\x26\xbb\x39\x3b\x70\xb7\xd6\x50\xed\x45\x55\x3d\xad\x42\x80\x42\x11\x22\x98\xe1\xbe\xd6\xef\x62\x0d\x0a\x1d\x79\x8f\xf3\x5f\xd3\x11\xa0\x75\xa7\x68\x75\xe8\x83\xb5\xce\x5a\xce\xbb\xeb\xfb\x3f\x1b\xd5\x9e\x2e\xda\xcd\xbf\xe1\xeb\xb8\x71\x9b\x7b\x30\xc5\x04\x29\x36\xe0\xfb\x4c\x76\xf3\x86\xa0\xd3\x7a\xe3\x0c\xaa\xac\xb9\xe2\xb5\xd5\xa9\xc7\xa9\x57\x9e\x56\x51\x19\x71\x26\x55\x77\x63\x72\xf3\x49\x62\xaf\x20\x44\xef\x21\xf9\x3a\x48\x27\x56\x78\xa9\x95\x19\x54\x70\xb3\x85\xee\xd5\xfc\x2d\xa5\xdb\x42\x73\xc7\x36\x36\x3d\x3e\xce\xff\x6e\x62\x4b\x23\xbd\x46\xf0\x91\xb5\xaa\xdc\xb3\x17\x86\x31\x9a\xc0\xc4\x94\x4f\x46\x97\x2f\xdd\xb9\x73\x12\x74\xc6\xe3\xa9\x87\xb8\xe6\xe4\x09\x8c\xef\x7c\x11\x7a\x2a\x30\x64\xd4\xb8\xe1\x29\x3b\xc1\xe3\xd8\x46\xfc\x79\xa7\x3d\x1b\x76\x7e\xc2\x8f\x99\xdb\xd2\x48\xa7\x33\x05\x28\x18\xf5\xe9\xef\xef\x8e\xd4\x0a\x5f\xa4\x90\x20\x49\x88\x56\xa2\x40\xbe\x8c\x46\x2a\x75\x9e\x36\x4e\x2a\xd5\x74\x9d\x36\x4e\xe3\x85\xfa\x85\x21\xef\x7e\xbc\x4c\xaa\xe2\x5a\x49\x64\x54\x4f\x5e\xe3\xf5\xa5\xac\xf5\x83\x82\x1c\xb9\x83\xc4\x5d\xf0\xa7\x13\x8b\x34\x24\xb7\x7c\xd3\xb2\x81\xfe\x29\x49\x03\x96\x8e\x1c\xf2\xf1\xd1\xbd\x47\x13\x0a\xe7\x4e\x1f\xd1\x6d\xf4\xe8\xad\x07\x36\x9e\x3f\x75\x02\xc2\xe7\xee\x1c\xd0\x3b\x5c\x17\x1c\x15\xa7\x56\xef\x4f\xab\x5e\x97\x5e\x3a\x2e\xa2\x87\x2e\x2e\x28\x7e\xe0\xe0\x13\x83\xf6\xf0\x6b\xf5\x6f\x69\x64\x10\x53\x60\xf7\xb5\xb6\x6a\x88\x22\x00\x67\xd8\xe2\x6d\xfe\xfa\xc4\xd8\x9c\x17\x4a\xa6\x5f\xaa\xf9\xf0\x9b\x99\x0b\x12\x73\xc2\x47\x46\x44\xe5\xe4\xad\x98\x9d\xbd\x3d\x27\xc7\x75\xbf\x72\xd8\x98\x57\xae\xcc\x79\xeb\xe4\xc9\xb7\x66\xfc\xf3\x95\xcc\x54\xe5\xfe\x80\x8c\x8a\x85\x53\x44\x7b\xb3\x9c\xc9\x46\xac\x68\x6f\xca\x4c\xd4\x25\xec\xcf\x64\x1f\x6b\xca\xb1\xfa\x4a\x98\x60\xd1\x0e\x03\x35\x68\x88\x24\x80\x84\xf6\x84\xd7\xc0\x09\x2a\xfe\xb8\xec\x16\x26\x61\xc3\x5c\xaf\xf2\xc6\x1e\xb5\xbb\x7b\x75\x48\xd7\xfa\xc0\xe6\xf1\x76\x1b\x2e\x4e\xd0\x31\xa4\x7f\x9e\x4c\x2d\x33\xd1\x2b\x7f\xc7\xe3\xf9\x5f\xa6\xb7\x37\xe5\xfc\x3f\xeb\x58\x01\x13\xbd\x9f\x28\xb7\xbc\x59\xc9\xab\x55\x9d\xcc\x66\x64\x86\x01\xaf\x6e\x03\x43\x66\xdf\x5c\xb0\xda\xeb\x3b\xaf\x95\xa5\x37\x7f\xfe\x2d\xe4\xbb\x90\xfb\x77\xa8\x1f\x60\x31\x2e\x2f\xc9\xa3\xc6\x37\x1b\x67\x15\xf0\x3f\x5f\xfc\x02\x1f\x80\xa4\xd3\x08\x90\x5f\xcb\x03\x26\x92\xf4\xca\x13\xf8\xde\x17\xe4\x0a\xb2\x7c\xe2\x71\xf0\x0b\x0f\x0d\x8d\x08\x1d\x14\x40\x5d\x7d\x88\x7f\x1e\x94\x5c\xb9\x60\x00\x75\x54\x96\xf8\x01\x1c\x07\xc4\x53\xd5\xfc\x4f\x7c\x7f\x9e\x60\xc3\xc9\xa9\x3a\xc6\x87\x33\x09\xef\x4b\x05\xcf\x3d\xad\x5a\xa2\x50\x53\x5a\x4e\x0e\xa5\xa0\x84\xd2\x3f\xd2\xf0\xa2\xb4\x0a\x50\x2d\x72\xf7\xa3\xea\xe8\xa6\x26\xe6\xe1\x43\x30\xc2\x2b\xbd\x73\x85\xef\xdd\xa9\x3a\x36\x91\xab\x11\xde\x97\x0a\xc7\xf7\xa5\x9e\x1f\x47\xa6\x71\x87\xef\xe9\x4c\x9c\x07\x8b\xf1\x52\xd8\xda\x5c\x8e\xdf\x9a\x75\x0c\x14\x13\xa8\x3a\xfa\xb1\xe9\x07\x13\xfe\xab\x96\x0c\xb7\x8d\xd8\x13\xd5\x54\x1d\x7d\x80\x8c\xa5\x22\x5e\x3d\xeb\x8b\x4d\xd4\x38\x42\x12\x99\xc3\x6b\xad\x1a\x92\x7f\xfa\x2a\x23\x2d\x77\xfc\xc5\x03\x35\x1b\x26\x8c\x3b\xba\xaa\xfc\xc5\x51\xe3\x26\x97\xf0\x63\x97\xae\x1c\xbb\xc0\x9d\xf3\x2c\x99\xb2\xe2\xdd\xda\xc4\xc1\x8b\x6b\x62\xfb\xc6\x47\x0b\xef\x42\xaa\x8e\x71\xe5\x6a\x88\xcd\x14\xe4\xf0\x2e\x6c\xf7\x2c\x74\x7c\x15\xae\xe3\x27\xea\xbd\x7b\x95\xe1\xe2\x01\x5c\x7c\xc3\x61\x2a\xa6\xa0\x06\xd6\x96\xae\x1c\x17\x5b\x63\x98\xb0\xe2\x5d\x38\x84\xff\x63\x9f\x8c\xe2\xe9\x61\x54\x5c\x8d\xf0\x86\x53\xf0\xaf\x2f\xa5\xa7\xed\x0d\x57\x0d\x69\xc0\x42\x00\xfe\x07\xfe\x39\x75\x12\x24\xe1\x86\x52\x7e\xdd\xf8\xf1\xdd\xa7\xf8\xcf\x5a\x48\x83\x24\x41\x3e\x79\x9e\x38\x71\x35\xfc\x5b\x4b\xe1\xf0\xd6\xaa\xa6\x72\xf1\x22\x98\x8e\x37\x43\xb9\x9d\x95\x04\x6b\x90\xaa\xa3\x2e\x89\xbf\xaf\x27\x2d\x35\xf8\xff\xc9\x66\x43\x05\xde\x08\x33\x71\x19\x95\x47\xd5\xd5\x82\xc4\xf4\x83\xa9\xc9\x89\xff\xfd\x22\xca\x48\x7f\xcb\x1d\x14\x2c\x63\x12\x0b\xb3\xb7\x36\xd2\x6b\xf4\x6a\x19\x6f\xb9\x15\x81\x16\xb8\x0f\x36\xa4\xce\x7f\x65\xfd\xc7\x6f\x2e\x4f\x49\x3c\x0f\xc6\x8f\xbf\xbc\x8f\x5b\x98\xda\x47\x20\x4f\xa8\x31\x1c\xde\xfe\xfe\x47\xee\x97\x3e\x69\xfe\x3d\x1e\x5c\x84\x35\x13\x1e\xbb\x08\xf2\xae\x96\xe9\xc8\xb9\xaa\xbe\x01\xc6\x1b\x37\xf0\x78\x42\x67\x31\x54\x36\x39\x41\x3d\x4e\x46\x80\x46\x53\x75\x54\x9c\x75\xcd\x76\x18\xb6\xd1\xe5\xe5\x70\x7b\xe9\x52\xaa\xae\x2c\x8e\x5a\x67\x28\x2b\x33\x34\xcf\x89\x2b\xe3\xdf\x6a\x7b\x61\x25\x54\x70\x35\xbc\xbd\x44\xeb\x1d\x1f\x6b\xe9\x83\x42\x52\xfa\xdf\xf8\xf0\xfd\x61\xb0\xb5\xd6\xe3\xc5\x2c\xfa\x40\x53\x72\xdd\xa7\x76\x3e\x36\x71\x35\x44\xca\xc9\x5b\x4d\x27\xbc\xd5\xaa\x6f\x64\x82\xba\x09\xaf\x82\x92\x16\x84\xef\x64\x93\xb5\x45\x96\xc0\x78\xdc\xbf\xf9\x2c\xd4\x0c\xc0\x1b\xc5\x6f\xf5\x5c\x0d\x62\x51\xe7\xfe\x2e\x34\x42\x2c\x27\x81\xa1\x34\x4a\x43\xfd\xa2\xfb\x89\x3a\x37\xaa\x27\xa1\x54\x59\x7d\x03\x4c\xfc\x18\x4d\x07\x6b\x6d\xf3\xb2\x2a\x22\x6f\xfc\xfe\x29\xda\xbe\xd7\xaa\x41\xd7\xc4\x80\x2b\xc4\x5c\x72\xe6\xf0\xaf\x17\x31\xe6\xdc\x28\xf2\xfd\x63\xda\xa9\xc9\x09\x7e\x9a\xfe\x4d\xd3\x4d\xda\xef\xf6\x44\xac\x15\xf9\x3a\x90\xab\x41\x52\x32\x96\xfd\xbd\xa6\xf2\x52\xca\xaa\xc1\x1b\x0e\x39\xb9\x5e\xc4\x77\xf0\x00\x27\x89\x13\x3f\x46\xb3\xf2\x1f\x03\xe1\x72\x93\x13\xf5\xc7\xcc\x85\xfd\x71\xa4\x6d\x3d\x4c\x0e\x39\x63\x84\x0f\x1e\x0e\x2f\xc8\xea\xf3\x1c\xcb\x40\x23\xb8\x9f\x75\xe7\xb0\x94\x70\x42\xf9\x71\x3e\x4d\x35\x39\xc1\x2f\x53\x3f\x6b\x7a\x44\xce\x7b\x11\x65\x64\xc6\x73\x07\x91\x0b\xaf\x75\x15\x31\x48\x17\xcd\x0b\xb5\x26\x10\x19\x84\x37\x5f\x20\x57\x04\xf0\xc7\x1f\x80\x70\xd3\xc3\x87\xb8\xc5\x02\xce\xe0\x82\xff\x53\xb1\x9c\xa9\x7d\x0a\x6e\xf8\xf7\xa7\x4d\xf8\x21\x48\x9f\xe0\x3d\x90\x01\x99\x1f\x23\x0a\xcd\xa6\x8c\xf4\x23\xae\xc6\x6a\xa3\xb7\x33\xd1\x45\x2f\x81\xcd\x46\x9f\x7d\x30\xf5\x85\x1f\x0e\x1e\xf8\xb1\xff\x88\x49\x13\xee\xfd\xeb\x5b\x8b\xe5\xdb\x6f\xbf\xfd\x96\xf1\xfc\x72\x94\x76\x49\xfe\x8c\x19\xc7\x8f\xcf\x98\x91\xb5\xbc\x7b\xd8\xea\x69\xe6\x63\x9f\xd5\x1d\x3f\x7e\x10\x89\xe7\x90\x2e\xe7\x6a\x50\x27\xd1\x4a\x0c\x90\x59\xd5\xb7\xa8\x46\x46\xc3\xaa\xab\x67\x26\x25\x5f\xcc\xc8\x9a\x46\xc8\x3e\x51\x5d\x83\x37\x52\xbe\x6f\xa5\x0c\xb5\x7d\xff\x88\xc8\x8e\xd2\xa6\x95\x24\xa0\xa6\x1d\x22\x54\xd5\xa0\xff\xd7\xd7\x9f\x83\x1e\x3f\x69\x2a\x48\x2a\x9c\x9c\x57\x90\xc8\x0f\xb4\x71\xeb\xfe\x31\xf8\x05\xa8\xc0\x65\x94\x7e\xe8\xa0\xa4\x04\x04\x48\x4b\xd5\xd1\xa9\x5c\x8d\xa3\x4d\xab\xa5\x83\xf1\xf5\x1b\xec\x93\xda\xda\xa6\x83\xf4\x60\xde\xa6\xa5\x8c\x0c\xc3\xd5\x08\xab\xd5\x59\x6d\x5a\x41\xc4\x43\xb6\xde\x98\x39\xa3\x20\xf7\xc6\xdd\xaf\xcf\xdf\x66\xfc\xa9\xca\xe6\xf5\x8b\xf2\x0b\x16\x50\xb3\x9b\x0b\xf6\x9c\x3f\x83\x00\x05\x53\x75\x6c\x2d\x57\x23\xda\x48\x5e\xaa\xbe\x94\x60\x23\xf1\xa6\x92\x70\x33\x72\x12\x5a\x13\xfc\x6d\x85\xd6\x95\x96\x74\xed\xb4\xb5\x61\xab\x5a\xea\x1c\x5a\xf1\x2d\xfe\xa3\x69\x8d\x44\xc3\x7a\x77\xae\x6c\xe2\x6a\x9a\x2f\xef\x9c\x26\x0b\xdd\xe5\x47\xc5\x35\x9f\xd9\x94\x37\xde\x44\x85\x35\x39\x51\xaa\xce\x7b\x42\x37\x8e\x6f\xbe\x27\xe8\xfd\xf1\x94\x91\x8e\x62\x2f\x20\x6f\xf1\x6d\xd5\x31\x74\x9a\xc1\x86\x93\x35\xbe\x6e\xff\x9a\xc5\x53\x5e\x4d\x7e\xe3\x83\x6a\xd3\xdb\x3d\xb8\x5e\x2f\x8f\x5f\xb0\xec\xe6\xec\x61\x13\x32\x27\x67\xd3\xdb\x16\xcd\xe3\xd8\xc0\x92\xb8\x35\x83\x57\xac\x6a\x7e\x32\x7d\x50\xf4\xd2\xf9\xe3\x33\x06\xf5\x67\x98\x78\x61\xae\x4a\xca\x48\xe7\xb2\xe7\x91\x8a\xb7\x32\x6c\x9d\xf8\xad\xbe\x46\xc1\xd5\x18\xa0\xb0\xb9\x17\x2b\xb7\x86\x73\xf1\x0b\xc7\x2d\x58\x51\x77\xe0\x8d\xc5\xb9\xaf\x26\xbf\xb9\x07\xef\xbd\x3e\x76\xe2\xc4\x99\x69\x59\xf4\x01\x8a\xc9\x1f\xd2\x73\xc9\xbc\x45\xf3\x39\x46\xb3\x20\x6e\xcd\x60\x30\x31\x54\x42\xff\xcc\x31\x83\x11\x85\xf2\x29\x23\x9d\xc3\x9e\x47\x52\xd4\x45\xb4\xc2\x55\x3a\x83\x4e\xcc\x07\xb3\xd2\x42\xcc\xa9\xfc\xea\x4d\x6f\x8d\xe0\x94\x87\x6b\xc2\x9c\x86\x6d\x7d\xb3\xfa\xa7\x77\xb3\x52\x47\x64\x25\x8f\x64\x0c\x87\xff\x59\x94\xd3\xf4\x78\x6a\xf1\x3f\x0e\x59\xf2\x67\x7a\xbd\x32\x6b\x1e\x7f\xe7\xe4\x50\x46\x36\x81\xbd\x40\x6a\x37\x9e\xef\x37\x75\x74\x9b\x86\x18\x78\xeb\xa9\x1f\xd5\x57\x40\x24\xe3\x94\x39\x94\x8c\xcd\xcf\x5e\xb3\x62\xf0\x8a\x51\xb9\xbb\xf4\x49\x6b\xe6\x2e\x78\xe3\x63\xf3\xaa\xd2\xdc\xb2\xa4\x37\x8c\xc6\x51\xd1\x8b\x32\xb7\x1f\x69\xa0\x52\x07\x6e\x73\xbf\x9d\xfe\xe2\xb8\xd8\x88\x94\xb1\x8c\xd3\xb4\x17\xa7\x26\x54\x07\xa8\x86\x0c\x1d\x95\xb0\x74\x3e\x4f\x73\x7c\xb6\xa1\x72\x70\x56\x44\x8f\xcf\x5e\x4e\xcd\xac\x9e\xcf\x93\x1e\x1d\x32\x26\x11\x51\x68\x2d\x65\xa4\x57\x71\x16\xa4\x10\x6e\x5e\x9d\xd2\xea\xbc\x16\x52\x0d\x34\x12\xc7\x12\x5f\xc9\xda\x1f\x39\xd6\x65\xd8\xd6\x37\x77\xee\xda\x30\xb8\xa0\x87\x2c\x38\x36\x25\x63\xf0\x88\x11\x49\x63\x87\x00\x55\xc7\xe8\xff\xca\x8d\x2d\xbe\x7c\xe8\xb3\x2b\x91\xfa\x0c\xa8\x78\x69\x76\xc9\xdc\xe2\xa2\x69\xf9\x56\xfe\x72\xf7\x49\x36\xb6\x95\xbf\x21\x09\xd0\x9a\xc3\x62\xc2\x1d\xe1\xb0\x93\xf4\x07\x1b\x87\x33\xd3\x28\x1b\x8b\x0b\x7b\x3c\x7e\x7a\x9a\x67\xf2\xed\x49\x05\x5e\xaf\xcc\x2a\x11\xc7\xce\x60\xcf\x23\x05\xea\x6c\x7d\x41\x39\xc0\xfa\x13\xa8\x43\x61\xdc\x2f\xf6\x7f\x7c\xa4\xf9\x0f\x7a\x7a\xf6\xf0\xa5\x83\xe6\x98\x4f\x7e\xff\x33\x18\x46\x0c\x7d\x61\x0c\xa3\x3b\x7e\xf5\xf0\xae\xbc\xf1\x79\x5d\xfd\xab\x0d\x5f\x81\xdf\xb0\xb1\xc3\x89\xec\xe5\x50\x46\x5a\x88\x8d\xf9\x38\xec\x9c\x9d\x33\x06\x61\x8a\x1c\xca\x8f\x9e\x3d\x79\xcb\xf2\x05\x1f\x7f\xf9\xe3\xc5\x83\x1f\x9f\x6e\xa0\x32\x92\x07\xbd\xc8\x31\x1c\xbf\x03\x3b\x7b\x7d\x7d\xf8\xc4\x95\x43\x4b\xd2\x32\x86\x8f\x21\xf9\x18\x94\x91\x0e\x66\xcf\x13\xfb\xc3\x9e\x13\xd1\x3e\x25\xc2\x6a\x3b\x67\x4e\x9a\xb6\xed\xc0\x1e\xf3\x9a\xc1\xfa\xe2\x94\xf4\x11\x13\xa7\x17\x95\x15\xe7\x9c\x78\xf7\x8d\xd2\x53\x27\xcf\xd1\xab\x86\x65\xc9\xb9\xa0\x37\x27\xcf\xe8\xfd\x96\x32\x30\x30\x24\x22\x64\x7d\xcf\x9e\x19\xf1\x7b\xf4\xf3\x10\xa0\x24\xca\x48\xcb\xd9\xf3\xe4\x84\xf2\xf7\xa4\x83\x51\x63\x3b\xaa\xb6\xf7\x5c\x60\xd2\xca\x35\xd7\xee\x64\xa4\x17\x2c\x4c\x1d\xbf\x64\xc9\x80\x6d\x9f\x6f\xad\xaf\xce\xcd\xb8\x72\xe8\x22\x75\x75\x6f\xfc\xf8\xac\xf5\x81\x11\xc1\xda\xa8\xf5\xbd\x0b\x27\x54\x68\x39\xd5\xd8\xc1\x05\xe5\xc2\xd9\xcc\x83\x6c\xc2\x9f\xce\x62\x86\x87\x78\x66\x1c\x72\x8a\x0d\xe2\xde\xda\xa3\xb1\x79\xc6\x0d\x9b\xc6\x70\x8a\xc3\x17\xbe\x30\x2f\x79\xab\xba\x86\xa2\x46\x6c\x5e\xff\xde\xad\xd4\x51\x63\x53\xe9\x91\xe3\xde\x66\x0c\x9f\x5d\x2d\xca\x69\x7a\xf4\xfe\x47\xe1\x7b\xe2\x4d\xae\x53\x8a\xaf\x7c\x3a\x7f\xde\xe4\x42\xef\x57\x66\xf1\xf3\xad\x84\x72\x28\x63\x0f\xa3\x4e\xc4\x5b\x62\xf5\xed\x86\x18\x64\x3a\xd9\xca\xfe\x71\xa5\xa5\x7d\x12\x9c\xbf\x87\xc6\xe8\xd8\xfc\xe9\x86\x27\xb4\x53\xd3\x63\x9e\xdf\x6b\xa9\x3a\xfa\x20\x77\x1f\xb9\x0b\xfa\x54\xa2\xeb\x47\x6e\x7f\x5a\xa2\x5c\xfb\xbd\x0b\x35\xf9\x76\x13\x3e\x08\x99\x2d\xe8\xde\x24\xaa\x8e\xe9\x8d\xbb\xd6\x96\xdc\xc3\x66\x3c\x04\xfa\x24\x3f\x14\xee\xcc\xb5\x54\x1d\x9b\xc7\x9e\x6f\xa5\x7d\xac\x3a\x88\xbf\x3b\x49\x5c\xc7\xfa\xe7\xda\x3d\xfe\xce\x21\x4b\x87\xec\x1f\xe0\x19\xb0\x78\xe4\xaa\xca\xeb\x65\xe3\x52\xae\x97\x8d\x1e\xce\x9b\x71\x39\x7d\xf4\x45\xfa\x3e\xcb\x36\x63\x0e\xce\xec\x2e\x2d\xc2\x65\x70\x66\xf7\x82\xd7\xf1\x5a\x32\x07\x64\xd3\x4b\xc5\xdc\x27\xbb\x86\x73\xc8\x21\xd1\xdb\xc7\x77\x0d\x5d\x96\xb2\x7a\xe3\xf2\xa5\xa9\x71\xda\xc8\x88\x1e\xe5\x13\xc6\x88\x83\xaf\x79\xa3\xb9\xb6\x6c\xb9\xc2\xe8\x16\xd7\x87\x72\xde\x5a\xb2\x92\x1f\x19\x91\xb3\xb1\x9b\x5e\x44\x6a\xe5\x55\xad\xbd\x0b\x8e\xde\xcf\xfc\xaf\x8f\xec\xfb\xc7\x37\x9f\xd6\x5d\xb9\x95\x36\x7e\xdc\xf0\xe1\x2f\x66\xa6\x31\xf1\x47\xfe\xf1\xcf\x83\x47\x2e\xff\xf3\x50\xf1\x82\x05\xc5\xf3\xe6\xcd\xe3\xd7\x39\x98\xda\x4d\x5d\x62\x2f\x58\x7d\xb3\x56\xfd\xe0\xe0\x9c\x95\x0c\x9e\xb1\xed\xc8\xb9\x0b\x87\x47\xcd\xd2\xc7\xcc\x18\x34\x7a\x4a\xde\xd8\x94\xa9\xec\x56\xdd\x97\xa7\x4f\x7d\xd5\x59\xfd\x49\x40\xd0\xbc\xe2\x92\xa2\x70\xc2\xd7\x7c\x46\x4f\xd6\xc5\xdf\x73\x7a\xf1\xc8\x6a\xac\xae\x33\xb2\x9e\x1b\x64\x1d\x7a\x8e\x5f\x08\xc7\xcd\x9b\x37\x6f\x1e\xc7\x7f\xc7\xd3\xc3\xe8\x89\x04\xe8\x04\xb9\xd2\x11\x8d\x99\x7f\x2b\x6d\x7c\x66\x1a\x75\x83\x6a\x38\x60\xbe\xca\xe8\x0b\x8b\x8b\x0b\x0f\x7d\x73\x99\xf0\x80\xe7\xef\x2a\x72\x8e\xbb\x3a\xe4\x83\x58\xb5\x9b\x4a\xc8\x04\xb1\x6a\xb7\x4f\xba\xba\x8c\xdc\xb4\x6e\xe7\x07\x6f\x0e\x9a\x15\xed\xe2\x32\x2c\x63\xd3\xd0\x91\x23\x53\x29\xc8\x66\xb2\x73\x8b\xaf\x1c\x3e\x7c\x35\xdc\x50\x88\x4f\x52\xd7\x17\xcd\xba\x57\x5c\x3c\x65\x0e\xa1\x25\x8a\x32\x52\x79\x5c\x0e\xb1\x8a\xf4\xfd\x40\x47\x3a\x7a\xdb\x4e\xb0\x5e\x16\x55\xd6\xbf\xf2\xf6\xed\x9c\x7e\xa9\x63\xe7\xbf\xf6\x12\xeb\x9f\x39\xa4\xda\xf8\x0e\x5e\x99\xe9\xfd\xae\x66\xc9\xab\x50\x22\xc8\xd9\x4a\xca\x48\x97\xb2\x87\x05\x5b\x51\x47\x0a\xa1\xf8\x6b\xdf\x7a\x99\xae\xbc\x5e\x3e\x31\xfd\x87\x3d\xfe\xce\xdd\x96\x0f\xab\xdc\x40\x9f\x80\xbf\x70\x9f\xdd\x0b\x57\xc0\xac\xa6\xc7\x53\xfb\x18\xd6\x09\x63\x4c\xa2\x2e\xd1\xdb\xd9\x1d\x48\x81\x22\xfa\x7b\xba\x48\x5d\xdd\xdc\x18\x27\x24\x65\x10\xe3\xa9\x04\xe4\xea\xe4\xd4\x09\x45\xea\xe4\x71\x91\xba\x76\xde\x2b\x85\x5e\x74\xf9\xe8\xed\xce\xa5\x49\xf0\xad\xb9\x6c\x1d\x5e\x4a\x47\xe6\xf7\xeb\xb5\x65\x3d\x75\xe9\xd2\xa2\x71\xc3\x2f\x57\xf9\xb9\x06\x2f\x49\xa9\xa8\x24\xf3\xad\xa2\x8c\xec\x24\xf6\xb0\x78\x36\x6c\x6b\x6e\xb3\x76\x91\x82\x55\xc2\x69\x18\x33\xec\x87\x3d\x5d\xdd\x82\x17\x0f\x39\x94\xa0\xf4\x5f\x3c\x72\x75\xa5\x48\x4b\x49\x21\x54\xf0\x7f\xac\x14\x49\x2a\x8e\xe9\xb7\x82\x9f\x43\x4e\xd5\xd1\xb9\xec\x61\xf2\x3e\xd0\x89\xc5\x81\x3a\xd0\xc8\xef\x6e\xeb\xc2\x30\x4e\xbe\xdb\x2c\xf8\xdc\x4d\xf6\x30\x1e\x9c\x99\x94\x32\x06\x0e\x0a\x67\xde\x9d\xda\x4d\xfd\x40\xfa\x38\x09\xba\xef\xb9\x7e\x09\xf7\xf0\xe8\xb0\x9e\x21\xa3\x12\xb6\x2e\x5e\xfa\x56\xef\x31\x9a\xd8\xc0\x3e\x21\xdd\x53\x46\x4e\x8b\xeb\x3d\x27\xfd\x05\xea\x48\x8d\x54\x15\x96\xb9\x64\xe4\x82\x75\x6b\x4b\x86\x2e\x9d\xa8\xf5\x95\xd6\x78\xc5\x27\x26\x8a\xb6\x09\x2f\x57\x27\xb8\x47\x48\x41\xa2\x5b\x32\xdb\x0c\x4a\x46\x88\x6e\xf9\x40\x57\xab\x9d\x69\x53\xbd\xca\xb5\x17\x3e\xfd\xe8\x44\x41\x1e\xc8\x8e\xbd\xbf\x26\x3b\x28\xbf\x7b\xfd\xc4\x09\xb1\xda\xe1\x29\xa3\x07\xbf\x07\xd9\xcc\x88\xed\x7b\xd6\x2d\xcd\x5b\x28\x63\xba\xfe\xbe\xee\x83\x70\xbc\x8a\x52\x2b\x3b\x57\xa7\x8c\xd8\x9d\x3e\x30\x71\x40\xbd\x90\x6f\x0b\xd9\x74\x9e\x28\x27\x3a\x21\x25\x84\x52\xe8\xc0\x1d\x94\x9a\x98\x58\x83\xcf\x9d\x12\x77\x5d\x27\x06\xbc\x54\xab\xef\xe0\x4b\x5d\x43\x1b\xb5\x6a\xf6\x30\xde\x13\xf2\x49\x98\x62\xfc\x70\xd8\xd1\xcc\x26\x9d\x1d\xd5\xeb\xcc\x44\x5e\x77\x53\x46\xba\x8c\x7b\x44\x72\xd3\x91\x42\x1a\x6c\xcb\xcd\x13\x9f\x80\x2a\xbb\xf1\x2d\xe8\x09\xad\x3b\xe4\x81\xff\x5e\xd3\xb6\x17\x77\x8c\xc9\xdc\x9a\xd7\x27\x6a\x6a\xde\xb2\x97\xbf\x3c\x5e\x7b\xe5\x56\x56\xf2\x88\xf1\x1b\xc6\x4e\xa5\x6f\x03\xa4\xe4\x2f\x9b\x3a\x57\xab\xdd\x34\xb8\x7b\x97\xe0\xa1\x51\x03\xf6\x14\xd4\x1d\xad\xd9\x36\x74\xcc\xc4\x17\x2b\x52\x55\x8b\x04\x7d\x04\xd9\xcc\x52\xf6\x22\xf2\x21\x51\x8b\x98\x58\x83\xca\x1d\xf8\xe9\xec\xdc\x93\x69\x64\x11\xc0\xda\x2c\x9f\xfc\x91\x63\xaa\xfa\xf5\xca\x9d\xbc\xbd\xa2\xfa\xb0\xe5\xfc\xc5\x93\xdf\x50\x53\x27\xbf\x3c\xb8\x5f\xf7\x08\x46\x3f\xe7\x6c\xee\xd4\x91\xeb\xc7\x4c\x9e\x27\x85\xfc\x25\x1b\xcf\xef\xfd\xf8\x27\x05\xae\x85\x34\xcf\x73\x09\x4e\x6f\xcc\x2a\x2a\x34\x24\x22\x40\x08\xb2\xe9\x1d\xec\x19\xe4\x8f\x90\x0c\xb4\xf6\x1b\xdc\x1f\x14\x3a\x50\xd8\x65\x21\x12\x68\x98\x3d\xd9\xb3\x57\x60\xcf\xa0\x91\xb1\x93\xa6\x76\x8b\xbd\xf0\x03\xae\xab\xf4\x8a\x0d\x55\x87\x0e\x18\x96\x53\xa8\x49\xbd\x0d\xd9\xd4\xb4\x3f\x63\x83\x5c\xf7\x28\xd3\xe7\x6f\x85\x8c\xe6\x07\xb8\x3e\x52\xd3\xa9\x5a\x95\x3f\xf5\x06\x4e\x27\xb4\x2d\x6f\x99\x04\x65\xf4\x56\x24\x21\xd2\x1a\x63\x0d\x3d\xea\x64\xcb\xcb\x4a\x4b\xcb\x9c\xbf\xa7\xa3\xa6\x4f\xcf\x6b\xda\x28\x5c\x4d\xbc\xde\x6f\x99\x44\x55\x53\x25\xfc\x9b\x4e\x65\xbb\x5b\x84\x0d\x90\xad\xdd\xad\x76\x8e\x5c\x3c\xb8\x67\x17\x59\x80\x7a\x46\xe9\x0e\xda\x69\xe9\x90\xa1\xcc\x39\xa7\xbc\x49\x78\x9e\xa0\x2f\x5a\x46\xd1\xa5\xd4\x74\x5e\x0e\x0c\xff\x55\x5f\x14\xb6\x55\x17\x80\xe4\x2d\x93\xe9\x5c\x6a\xfa\x73\xcf\x15\x35\xdd\xf1\x5c\x51\x68\x2d\x76\xa1\x4f\xd0\x3b\xff\xaf\xe4\x1d\xbb\xfc\x1d\x79\xc7\x0a\x3a\x8f\x2a\xfa\xfb\xf2\x4e\x15\x75\x28\xef\xab\xb0\x27\x9d\x4d\x78\xdd\x05\x21\x83\xfd\x1e\xd4\x6a\xf8\x8b\x47\x61\xbf\x0b\x95\xab\x8e\xee\xad\x3a\xb9\x7b\xe3\xcc\x4c\x57\xd7\x4b\x97\x0c\x13\xd3\x06\x0d\x4a\x4b\x4d\xb6\x1c\xfe\xe6\x9f\x07\x0e\xfd\x53\x3f\x2f\xf1\x33\x2a\x38\x7e\x4e\x59\xd9\xcc\xbc\x62\x41\x9e\xb1\x92\x59\x4a\x2d\x13\xe4\xd9\xf0\xff\x22\xcf\x8d\xff\x5d\x9c\x49\x0e\x92\x92\xde\x41\xbd\xf2\x7f\x20\xcf\x58\xf9\xdf\xe4\x79\x6b\x4b\xa3\x24\x9f\x29\x26\x3d\xd0\x5a\x45\x58\x94\x8e\xe0\xc8\x22\x54\xae\xd0\x2a\x5c\x48\x30\xb4\xc5\x5e\xc2\x96\x0e\xb9\x02\xd0\xdc\x93\xda\xb8\xd8\x0a\x94\xfb\xc6\xb2\x5b\x2d\xa8\x05\x31\x0c\x49\x2f\x9c\x58\xe4\x18\x97\x49\x08\xe9\x81\x7f\xb5\x6c\x58\xb2\x81\xe4\x18\x1e\x3e\x0c\x00\xc7\x8b\xca\x16\x21\x44\xb5\x94\xb7\x34\x32\x75\x9c\x27\xd2\xa2\x68\x84\xe8\xbe\xa0\x53\xe9\xd5\x4a\x2f\x5d\xb4\x70\xfb\x6b\x95\x9e\x12\xfe\x52\x97\xcb\xa4\x14\xbf\xa7\x12\x8d\x8c\xb7\x46\x84\x34\x40\xbd\x54\x13\x48\x2f\xa2\x96\x17\x69\x20\x4a\x11\x90\x2c\xdf\xc4\x2c\x2f\xf2\x91\xba\xba\xce\xfc\xe6\xeb\x2b\x77\xce\x9c\x2a\x54\xea\x2c\x5d\x14\x29\x6e\x70\x60\xe6\xbc\xec\x82\x86\xcb\x1c\xb3\x63\x4d\x35\x33\xe8\x7d\x49\xc1\x9a\x6a\x4e\x3e\x70\x9b\x11\xdf\xc6\xf7\xf1\x3d\xfc\xf5\x9a\x32\xd6\x89\x9b\xd3\xbc\xbe\x6e\xdb\x47\xbb\x40\x8f\x05\xdb\x22\xab\xa5\x91\xad\x24\xeb\x8a\x11\x73\x11\xc9\xbb\x86\x9f\x5d\x43\xce\xb3\xc3\x32\xb5\x1d\x97\x17\xdd\x3d\x79\x65\x96\xb3\x4a\xd9\x35\x59\xbe\x91\x5a\x59\xe4\x25\x87\x68\x1f\xaf\x14\xb7\x8d\xcc\xb2\xc2\xc0\xd6\x15\x47\x45\x65\xa4\xe2\xa8\x13\x74\xab\x5e\x32\x69\x0e\x37\xe7\x8d\x5d\xdc\x90\xf7\x25\x05\xeb\xde\x63\x9e\x8e\x77\x28\x3e\xfa\x60\x9d\x50\x3f\xd8\x52\x87\x10\x3d\x9f\xf3\x27\xb1\x34\xc2\x31\x8d\xde\x20\x3e\x37\x04\x3b\x4b\xad\x54\xcb\xec\x3c\x94\xa9\x65\xc4\x04\x4a\xe5\x59\xb5\x7b\xf7\xe1\x8b\xdb\xcb\xd2\xb2\xd2\x06\xf4\x06\x27\xfc\xb8\xb3\x8f\x95\x6f\xf8\x62\x17\x45\x70\x38\x07\xa5\x6b\xaa\x99\x86\xf5\xe9\xe9\x47\x4d\x91\x3f\xfa\x0d\xeb\x33\xf8\x36\xbe\x40\x38\x86\x17\xc3\x0d\xae\x77\x0c\x42\x74\xcb\x61\x84\x9c\x74\x62\x3f\xf7\x04\x84\xe8\x98\x58\x43\x1b\x13\xda\x0f\x88\xf9\x46\xfa\xd3\x69\x49\xfb\x35\x09\x69\x6c\x09\x5e\xac\xc0\x1c\xd6\x4b\x25\x9e\x9b\xc4\xd2\x99\xb6\x68\x52\xf8\xc7\x73\x8e\x9c\x48\x96\x6f\x64\xe6\x2f\xc4\x5f\x9d\x3c\x81\x2f\xbe\x7f\x9d\xc6\x17\x5f\x70\x81\xe5\x45\xe0\x3e\x72\x6c\xee\x14\x6a\xc7\x2f\xef\x8e\x1c\x5b\x9a\x07\x45\x2f\x57\x2b\xe0\xa0\x35\x38\x75\x3e\x28\x7f\xf9\x76\x5f\x6c\x84\x54\x77\x3f\xbc\x12\x76\x77\x09\xa1\xb1\x0f\x3c\xe8\x3c\x15\x42\x5d\x23\xc2\x4b\x4b\xe7\x7f\xab\x71\x5e\x55\x5a\xfa\xfe\x7b\xe4\x7e\xe7\xd7\xcf\x6e\x25\xfd\x10\xb5\xad\x57\xef\xb8\xee\x48\x68\xbd\xe2\xc4\x97\xf3\xad\xe1\xbd\x91\x2e\x9b\xd8\xf9\x0b\xf1\xc5\xeb\xe7\xf0\xc5\x44\x67\xa8\x18\x0c\xe3\x33\xb2\xa7\x15\x43\xd1\x2b\x46\x05\xd4\x93\x90\xe0\xe1\xce\x53\x5e\xdf\xa8\xc0\x5b\x60\x51\x54\x28\x0e\x85\x07\x5d\x27\x43\x80\x7b\x5a\x66\x69\xe9\x1c\x5e\xe6\xb1\x27\x53\x47\xea\x79\x62\xc4\x1d\x14\x6d\x57\xb9\xd8\x70\x88\xd7\x5d\x0e\x67\x40\xad\xb7\x09\xbd\x98\xc3\x46\xa4\x9e\xe4\x36\x9f\xfe\x71\xfa\xe7\xe5\xa7\x0a\xa5\x52\xfb\x09\xe0\x77\x32\xd5\x95\x17\x7b\x31\xc5\xb9\x78\x4d\x35\xc3\x1c\x5e\x6b\xc4\x5f\xe1\x07\xfb\xf0\xe3\xd7\xd7\xac\xf6\xda\x2c\x99\xbd\xa6\x9a\x9b\x76\x8a\x9b\x45\x1f\xb3\x65\x3a\xf3\xb2\x55\x8e\x10\x5d\xc2\x14\xa3\x60\x87\x95\x91\x8d\xa5\x05\xd1\x6a\x2b\x56\xc2\x52\xee\x84\x7b\xc4\x98\xf3\xfb\x86\xaa\x82\xf5\xeb\x76\x7a\xf9\x09\x2b\xf1\x75\x17\x57\x12\xff\x86\x91\x85\x3f\x0e\x67\x17\x77\xc2\x3f\x39\x6f\x5a\x1e\xc9\xcd\x7e\xc3\x28\xc1\x87\xa1\x8a\x9b\x4d\xe6\x5c\x84\x10\xcd\x30\x25\xbc\x5d\x47\x0b\x67\x4b\x2a\x3a\xad\x3b\x98\xaf\x9c\xaa\x28\x96\xc9\x61\xd1\x82\x12\x4d\x62\xc2\xc6\x56\x73\x79\x26\xbb\x43\x7c\xe5\xfb\xec\x7c\xd8\xa2\x7e\xac\xac\x3e\xd5\x76\x9e\xc7\x2d\x8d\x8c\x33\x53\x8c\xa2\xf8\x5d\x37\x38\xbe\xd0\x95\x9e\x5d\x41\xe5\xa5\x8a\x35\xe8\x6c\x09\x04\xb6\xe7\x4f\x04\xad\x09\x94\x38\x2d\xf6\xbd\xf3\x8f\x2f\x8e\x66\x8d\xde\x90\x5a\xd1\x39\x71\x75\x49\x42\x7f\xd7\x8d\x92\xd9\x5e\xbf\xdd\x7f\xa9\x26\x65\xcc\xe5\x91\xe3\x53\x03\x12\x73\x96\xf6\x99\xec\x0e\xc6\x83\xc9\xbd\xc6\x6d\xdc\x99\xf9\x5d\x50\x44\x8a\x4f\x60\x48\xbc\x4e\xa7\x1a\x75\x30\xb1\x57\x8f\x9a\x3a\x75\x40\x53\xb7\xd8\x9e\x3d\xfd\x0d\xfa\xc8\x70\x92\x67\xd2\x52\xdd\xd2\x48\x1b\xd8\x54\xd4\xdd\x7e\x8e\xf9\x57\x46\xeb\xd3\xeb\x10\xd8\x13\xd4\x4f\x16\x55\x51\xac\x59\xb7\x3b\xf3\x04\xc4\xe1\x33\xbc\x76\xd9\xc4\xac\x2c\xf0\x75\x1f\xda\x67\x44\xe1\x5c\xe3\xfe\xf7\x09\x17\x2a\x2b\xdf\x67\x3f\x5b\x9a\xd7\x78\xff\x36\xbe\xc9\xcd\x5e\xb3\x4b\xd2\x6b\x40\x5f\xcd\x4d\xdd\xa7\x9f\x6e\x22\xac\x40\x80\x18\x84\xe8\xcb\x4c\x36\xf1\x0c\x11\x9e\x1b\xf8\x47\x02\x6d\x9f\x57\xa2\x56\xaa\xf5\x0a\x22\x6d\x0c\xb5\xbc\x68\xdc\xd8\x35\xd8\x87\x1e\xf8\xa8\xab\x7a\x98\x6c\x13\xb3\xaa\x24\x35\x6b\x39\xe5\xdc\x54\xd9\xe4\xdb\x39\x38\x8e\x03\xe3\x9a\x6a\xed\x09\xcb\x69\x6c\xe2\x66\xad\xad\xd2\x7e\x6a\xa9\x83\x4c\xce\xa0\x47\x42\xce\x3e\x91\x75\xc1\x97\x20\x8b\x09\x52\x47\xab\x94\x64\x67\x5b\x2b\x76\x85\x63\xd6\x3e\xf8\x80\xd7\x9f\x1f\x5d\xf8\xe5\x1e\xc3\xcc\x6a\x38\x75\xe3\xd6\x17\x5f\xcd\xef\xe4\xdd\xb9\xa0\xec\xea\xcc\xc2\x85\xd3\x59\x1c\xca\x4c\xfa\xfd\xaf\x81\x7f\x64\x34\x2b\x2a\x8d\xf8\x6b\x7c\x1f\xff\x86\xcf\x57\xaf\xa1\x74\xb5\xdb\x21\x7d\xb7\x91\x17\x64\x40\x9b\xa8\x3a\x7a\x9b\x90\x6f\xea\x18\xaf\xd8\x74\x03\x5e\xf8\xe9\x27\xfc\x19\x55\x47\x53\xf8\x2e\x78\x35\x61\xd0\xe1\x0b\x88\x42\x52\xec\xc9\xa4\x92\xba\x1c\x35\x42\xaa\x98\x58\x83\x56\x1f\x4c\xc2\xbd\xaa\xae\x94\xe0\x0c\x77\xcc\x71\x91\xde\xf9\x67\x2d\x0c\x6d\x7e\x40\xd7\xe1\xcc\xf2\x37\xd7\x24\xe1\xeb\xf8\x3f\xf8\x3b\xe8\x55\x52\x58\xb0\xa0\x70\xfe\xcc\x97\x9d\x0f\xff\x3b\xa8\x70\xea\x55\xcb\x05\xfc\x73\xfa\xf8\xb7\x0e\x2e\xbc\x8d\xff\x42\x2d\x77\x16\x2f\x5f\xf1\xca\x82\x65\xcb\xc4\x3a\xa0\x3c\x27\x35\xe7\x49\x6e\x17\xdb\xae\x83\x4c\xad\x34\xe8\x80\x93\xd8\x72\x4c\x05\x1d\x29\x53\xcb\xc0\x2a\x05\x5a\x89\xc6\x10\xa2\x97\x45\x8a\x02\x40\x69\x21\x6a\xc8\x77\xf8\x3a\xd7\x49\x96\x77\xfd\xf4\x97\xf8\x62\xe6\x84\x25\x45\xf8\x22\x36\xb8\xfa\xf2\xf2\x30\x32\x76\xfe\xb7\xc7\x86\xd0\xa5\x82\x2c\x70\xd4\x01\xb8\x9e\x95\x85\xd7\x15\x4e\xab\xbe\x74\xa6\x59\x4b\x55\x96\x96\xee\x3d\xd1\xfc\x90\xd6\x34\x1f\x63\x34\x37\x75\xd2\x4d\x0f\x33\xf7\x52\xbe\x62\x7e\x3c\x55\x24\xe4\x03\xca\xf4\x84\x7f\x4a\x8d\x90\x08\xbc\x63\x07\xbe\x08\x57\xcf\xc0\x31\xdc\xff\x0c\x0e\x85\xab\xb6\xba\x12\x5a\x25\xd4\x35\xd9\x7e\xbf\x95\xe8\xee\x80\xa8\x73\xe7\x86\xf6\x19\x59\x38\x7b\xeb\x91\x5a\xeb\xf7\xa5\xa2\x58\x96\x5a\x71\x80\x58\x29\xa9\xe1\xf2\xe7\xa5\x85\x1f\xc7\x5a\xe3\xa1\x53\x6a\x38\x4a\x28\xf0\x90\xa9\x65\x6a\x07\x50\x34\x4e\xa8\xf1\x30\xff\x4b\x99\x33\x49\xf1\xc3\x01\x5e\x15\xe2\x8b\xa0\x77\x99\x3e\xed\xa3\x2e\x38\x0b\xaa\xa4\x93\xc7\xe7\x4f\x21\xf3\xad\x35\x3e\xbe\x7e\xe6\x17\xdc\x4c\x0a\x3c\xe8\x13\x8b\xe7\xff\x71\xa6\xb0\xa8\x50\xec\x8f\x9b\x48\xe2\xae\xde\xd6\xd5\xab\x05\x0a\x38\x46\x13\x18\xa4\x55\x13\x3f\xc2\x0e\x88\x82\x2a\x9e\x7c\x16\x3f\xfe\xcf\x13\xdc\x4c\x43\xd4\xcc\xc2\x33\x22\x25\x84\x9a\xdf\x9f\xfc\xfb\xf1\xcb\x2f\x3d\xb2\xf6\x1c\x66\x23\x49\x0f\xc4\x20\x32\x66\xac\x41\xa3\x57\x2b\x39\x89\x3a\x44\xab\x57\x2b\x35\x02\x45\x48\x1d\x80\x12\xac\xd6\xd6\xe2\xe8\x85\x8f\x28\xdf\xb5\xd1\x94\xaa\xc7\x7a\xca\xe7\xc1\xbc\x98\xb2\x2c\x06\x5f\xc0\x4d\xf8\x3f\xf8\x02\xf8\xba\x6e\x2d\x5b\xb4\xd9\x15\xae\x9e\x79\x6d\xec\xed\x1b\x63\x5e\x7f\xed\xc5\x1b\xb7\x47\xbe\x7e\xe6\x0e\x6e\x82\x4e\x3f\x52\x4b\x5e\x29\x2f\x23\x67\x2d\x94\xd8\x52\x01\x28\x5c\xcc\x56\xb6\x9e\x31\x89\xd2\xb1\x70\x49\x62\x3f\x71\x56\xe7\xef\x0e\x88\xe2\x0d\xa7\xd3\x3f\x2e\xda\xb0\x26\x8b\xd4\xdb\xfb\x74\xe6\x2d\xa8\x24\xde\x76\x2a\x9c\x5c\x94\x4f\x71\x9e\x78\xd3\xa0\x2d\x46\x7c\x1e\xff\x1b\xdf\x7c\xe7\x89\x58\xce\x54\x44\xad\x29\xa3\x74\xbc\xe5\x24\xd4\xca\xa0\x2c\x1c\xca\x5c\xb5\xae\xc1\xb1\x02\xbb\x4d\x9d\xff\xf3\xea\xb1\xf3\x36\xac\x99\x30\x24\x26\x52\xa7\x4b\x7f\x5e\x61\xf6\x93\xf3\xf6\xa2\xaa\x36\x25\xda\xa4\x6f\x7e\x28\xb1\x91\x34\x24\xfe\xd8\xce\x3a\x6a\xb3\x1a\x59\x68\x6b\xb3\x28\xcf\x8a\x3a\xf0\x16\x5d\xea\x68\x0b\x35\xe7\x39\x16\x72\x21\xa1\x66\x85\x5b\x49\x6c\xa1\x58\x1b\xbd\x86\x76\x85\x69\x4a\x4f\x46\xdd\xca\x77\xda\xa6\x92\xe5\xdc\x57\x0b\x9c\x7c\x80\xa2\xbc\xad\xdc\xc7\x3f\xe3\x3b\xf8\xee\x9f\x1f\x9d\xb7\xdc\x63\xd9\x99\xdf\x9c\xbb\x0e\x86\x99\x45\x0b\xa7\x71\x42\x69\x0b\xcf\x82\x35\x4d\xdb\xf1\x52\x71\x2d\x7b\xc3\x89\x3e\xc4\xf2\xca\x5d\x10\x0b\x12\x5e\x07\x06\xef\x7b\x47\xcc\xa1\x0f\x65\xbe\xe5\x3c\x91\xaf\x20\x11\x12\x1d\xc9\x68\xd5\xc9\xa4\x6a\x3b\xf5\x40\x1a\x65\x4a\x99\x0a\x88\x83\x4c\x9c\x08\x51\x8b\xf0\xf5\x09\x43\x62\x22\x74\x31\x71\xf8\x48\x39\xe7\xd9\x9c\x8c\xf7\xc0\x68\xec\x8b\xf3\xf0\x76\x5c\x23\xa2\x2e\x9c\x9a\x8e\xab\x11\xa0\x22\x1c\x4a\x19\x38\x4f\x24\x43\x48\x65\x65\xa6\x8d\xbd\x45\x84\x85\x10\x95\xc7\x93\x75\x87\xff\x8c\xf3\x14\xb7\x4d\x5c\x9b\x64\xb7\x70\x1f\xeb\xda\xf9\x60\xdb\xee\x90\x4d\x13\x8a\x3f\xec\x68\x6d\x35\xda\x64\x66\xeb\xc8\xb1\x85\x05\xf8\xe2\xc8\xb1\xf3\x67\xd8\xb3\x97\x30\x67\xdf\x37\x5e\xe9\xed\xd8\x6b\xcf\x71\xb2\xd6\x1a\x84\xb2\xee\x42\x2d\xb2\xce\xc1\x57\xfb\x8c\x55\xec\xb0\x9a\x82\x76\x41\xc9\xc8\x5e\x32\x57\xcc\x07\x6b\x3b\xdb\x87\xa7\xf9\x59\xec\x77\x61\x00\xc9\x08\xb3\xd9\x7c\x6d\x4e\x27\xf7\xcc\x3a\x36\x87\xd3\xe9\xed\xdb\xbe\x88\x8d\x37\xef\xf0\x9d\x77\xb0\x38\x75\x31\xd3\xb6\x92\x0d\x09\xfb\x45\xec\xbb\xae\x0e\xfb\xd5\xca\xc4\x53\xb6\xde\xbc\x56\x96\x9d\x7d\x1f\x99\x6c\x9b\x39\x87\x8d\xc2\x86\x02\x7f\xf6\xe9\x1a\xa6\x18\xe9\xac\x51\x03\xd1\xb6\xf2\x22\x77\x68\x3b\x2a\x45\x13\x4b\x1f\x13\x01\xda\x08\x2a\x4b\xb0\xaf\xd6\xa5\x2e\x1f\xbb\xbe\xfc\xa5\xde\xa3\xad\xfb\xd9\x3f\x45\x30\xb1\x8c\x3d\x66\x8d\x5f\x5a\x6a\xa0\xe3\x05\xe3\x6a\x68\x68\x9f\x78\x7d\xd6\xc2\x51\x6f\x64\x5a\x44\x7a\x4b\x9d\x89\x85\x35\x29\x28\x3c\x2e\x24\x36\xab\x04\x41\xcb\x09\xec\x49\x5b\x38\x0d\x6f\xe5\x8b\xf9\xdf\x64\x55\x4a\xab\x24\xb5\x39\xa2\xfc\xdf\x12\x12\x74\xba\xde\xfb\x3e\x9e\x94\x1a\x17\x1b\x95\x40\x79\x8b\xbb\x1b\x83\x6f\x9b\x3f\x9a\xdb\xf7\xa6\x72\x60\x1c\x1b\x7f\x68\x8f\xbf\xc5\x33\xa1\x6f\x53\x92\xfd\xf8\x55\x7f\x72\xc4\x5f\xa8\x19\x65\x2a\x99\x6c\xe4\x8d\x12\xfa\xfb\x77\xea\x8c\xa4\xce\xac\xab\x97\x17\xcb\xd0\x3e\x9d\x19\xe4\xed\xae\x98\x38\xce\xdd\x09\x79\x78\x3b\x4f\x1c\xe7\xad\x14\x72\xbc\x74\x91\x24\xf3\xd0\x96\x45\xac\x8b\x96\xe9\xa2\x7a\x3a\xa0\xa5\xb5\x3a\xa8\x6a\xe8\xf7\xcf\xa0\x4e\x1c\xdb\xed\x2a\xf4\xc3\x7b\x7e\xb1\x1e\x52\xbc\x92\xc9\x6e\x2e\x2f\x9d\x35\xa9\x82\x5a\xd4\xb4\xd4\x7e\x44\x91\x15\xbf\xa5\x82\xac\x09\x39\x40\xae\x38\x9e\xfe\xb6\x88\x2b\x25\xd6\x71\xfb\xb6\x45\x5c\xb1\x9d\x7d\x02\x2c\x02\xc8\x80\x43\x49\x4e\x9d\xd2\x21\xa7\xae\x15\x53\x0d\x14\xc7\x1b\x8d\xd8\x89\x72\xb6\x6e\x67\x1d\x75\xdc\x72\xba\x79\x24\xde\x60\x3d\x20\x88\x42\x19\x38\x94\x9d\xc1\xcc\x27\x1d\xe9\xda\xc7\x9d\x85\x60\xb9\xd5\x8c\xb0\x3a\xc2\x82\x3b\xec\xf2\x36\x4d\xa7\xeb\x19\x3d\x64\xda\xaa\xca\xbe\x62\xc7\x2e\x88\xeb\xa8\xbf\xdb\x23\xbc\x7d\xa0\x5e\x71\xd9\x77\xe7\xb6\x2d\x5b\x26\xa7\x1c\xd8\x6d\xeb\xef\x46\xee\x2f\x76\x07\x39\x1f\xdd\x1d\xf5\x79\xbb\x45\x10\x1d\x2e\xb5\x47\x8f\xc9\xe5\xe5\xe4\x0b\x54\x9e\x4e\x17\x19\x33\x64\xda\xea\x4a\xdb\xe5\xf5\xdd\xa2\x19\x0e\x57\xd7\x1a\x7e\x8b\xc8\xec\xd5\x6f\x6f\x11\xee\x2d\x5c\xbb\x79\x8b\xba\x6e\xdb\x6e\xf1\x3e\x61\xd3\x38\x0d\xea\x86\xf4\x8e\x7e\x07\x47\xc1\xb5\xae\x24\x40\xa6\x8f\x89\x6d\x7f\x9b\x58\xef\xd1\x7d\x26\x41\x8a\xe3\x74\x31\x09\x7d\x17\xe1\x1a\x67\xfa\x99\x97\xa9\x54\x94\xe9\x27\x17\xe3\x06\x2a\xef\xfa\xc3\xf4\x54\x43\x5e\x58\x9b\x2b\x55\xbc\xdb\x1b\xc5\xdc\x70\xd4\xa6\xad\x52\x2b\xfe\x38\xb8\x8c\xda\xf4\x54\xe2\x99\x33\x34\x6f\x55\xe5\x98\x58\xfc\x10\x7f\x0d\x7d\x3a\x6c\xa5\x84\x33\xc4\xdd\x59\xed\x04\xdd\x61\x8b\x58\x87\x0a\x28\x4d\x9c\x3f\xfa\xef\xd4\x9d\xb7\x5d\xd0\x73\x6a\xd0\xad\x8b\x1a\x3d\xe9\xb9\xa5\xe8\x78\x84\xb8\xac\x37\x9c\x77\xd9\xd6\xa3\x61\x8a\x79\x1b\x5e\x25\xfb\x7b\x1d\x1e\x5a\xbd\xe7\x9e\xdb\xd5\xa1\xb0\xbf\x55\x96\xb7\xc0\xa9\xe7\xf4\x72\x70\x2a\x11\x56\x85\x28\x94\x89\x43\x39\x3f\x72\x87\x85\xda\xe2\xda\x42\xe2\x7e\x34\x52\x39\x4a\xb0\x5e\xc6\x1b\xb6\x1d\xf5\x55\x6a\x82\xee\x8a\x27\x56\x09\xee\x82\x1f\x7e\xdf\x71\x87\xa5\xbf\x7e\x6f\xa6\x44\x19\xa6\xd2\xaf\xfd\x69\xeb\xb4\x44\xa1\xf5\x38\x94\x46\x9c\x27\x72\x12\x62\xf6\xba\x68\xa2\x57\x15\xb2\xb6\x47\x68\xbd\xd1\x38\x6a\x94\xd1\x0d\xa2\xf2\x62\x74\x11\x64\x36\x76\xf1\xc6\x8d\x43\x86\x3f\x55\x31\xd9\x8e\x27\x84\xe7\x73\x3f\x1c\x4a\x1f\x17\x71\x42\x62\xad\x70\xb5\x8e\x8c\xd4\x3b\x74\xfd\x96\xf4\xdb\x74\x09\x68\xf0\xc2\x77\xf1\xd3\xee\x21\x56\x52\x06\xaf\x9b\x38\x77\xc5\xea\x85\xb9\xab\x18\x6d\x2a\xfe\x0e\xff\x84\x2d\xf8\x1b\xa6\x58\x9c\x04\xbe\x8b\x8c\xde\x6d\xfc\x60\xe7\x40\x72\x67\x84\x52\x7b\x39\x0d\xff\x0a\x94\xc8\xda\x5f\x1a\x9e\x9c\xc4\xf1\x55\xe3\x78\x5b\xac\xaa\xb0\x6f\xd8\x6a\xe5\xc0\x38\x3a\xd7\x7a\x53\xec\x79\xf7\x90\x7c\xbe\xb8\x4b\x3c\x3d\x5b\x71\x28\xdb\x20\xd4\x5e\xb6\xca\x6f\xef\x58\xd3\x6d\xb5\x26\x76\xdb\x38\x95\x1e\x2a\x8d\xaa\x2b\x3e\x75\x16\x2a\xa8\x6b\xcd\xc5\xbc\x7d\x41\xb9\x3b\xf2\x6c\x4d\xda\x98\x4b\x76\xf9\xcc\xe6\x4f\x6b\x2b\xf9\x24\x0f\x5b\xf6\xd9\x12\xb9\xee\xbd\x1a\xe8\x87\x9d\xe8\xed\x78\xef\x89\xda\xf2\x27\x7b\xda\x89\xe2\x0b\xbd\xf6\x3c\xb6\x9c\x7e\xdc\xe5\xbd\xf5\x33\x77\xda\x05\xd0\x96\xd7\x93\xc5\x9e\x42\x32\x92\x6f\xe3\x98\xd7\xd3\xea\xd1\xa1\x09\x54\x56\xee\xf1\x73\x56\x17\xa4\xbc\xfe\xd6\xbb\xaf\xaf\x4b\xe1\x14\x8a\xf4\x8c\xc4\x94\x8d\x55\xfc\xc3\x3c\x37\xa6\xdf\xd5\xfd\x47\x2e\x15\x4d\x81\xb2\x92\xfc\x05\xc5\x3f\x9f\x42\x80\xb2\x29\x23\x75\x86\x3d\x45\xe2\x05\x36\x63\x5e\x48\xa7\x70\x07\x4d\x40\xf6\x89\xfa\x57\xe6\xf6\x9d\x93\x58\x55\x35\x77\x5a\xcf\xfc\x51\xf8\x2d\x26\xea\xd4\xc5\x98\x9d\xe1\xbf\xdc\x7c\xa1\xae\xab\x2f\xa2\x50\x36\x95\x4f\x3d\x66\x4f\xa1\xae\x22\x62\x86\x43\x6e\x86\xca\x1e\x34\xe0\x24\xda\x58\x43\x08\x6b\x7b\x18\x65\x9f\xfb\xfc\xe5\xc2\x84\x9e\xe9\xe1\xd9\x19\xcc\x8b\xe5\x79\x65\x9b\x96\xaf\x1e\xa5\x08\x98\xee\x17\x9a\x04\x4e\xa1\x93\xa3\x12\xba\xf7\xc8\x62\xa2\xce\x7e\x19\xb3\xd3\xd3\xa7\xa0\x54\xeb\x3d\x7a\x7a\xd6\xf4\x79\x86\xc0\x51\x3d\x87\xa6\xce\xf6\xed\xdf\x2d\xd0\x2f\x98\xf0\x24\x9d\x32\xd2\xf1\xdc\x13\xd2\xc1\x42\x9c\xdb\x10\xa2\x95\x68\x0d\x21\x5a\x83\x97\xca\xa0\x92\xb4\x8d\xc9\xf1\xb2\x96\xfe\xc9\xe6\x55\x51\x9c\x2e\x7d\xfb\xa0\xd2\xee\xfd\x06\xe7\x8c\xd8\xf6\xc2\xfc\x69\x33\xce\xee\xdd\x73\xee\xea\xf0\xe1\xa3\x87\x8e\x4a\x1e\x33\x94\x71\xaa\x3a\xf2\x02\x35\x7f\xc4\x94\xd9\x43\xfd\x34\x65\x91\xba\x49\x33\x87\x4c\x7c\xf2\xc1\xa9\x6b\xc7\xdf\x9b\x38\xb5\x68\x6e\x72\x16\xa9\x49\x4b\xa2\x8c\x54\x23\x7b\x4a\x78\x07\xb5\xcf\x17\x69\xa5\x9f\x38\x4d\x60\xd2\xd2\x95\x17\xbe\x4d\x1f\x36\xbd\x38\x69\x74\x59\x69\xc2\xc4\xed\xc3\xdf\xfc\x70\x6b\xf6\xa8\x2f\x3f\x3e\x45\x5d\xad\x89\x1f\x9f\xb5\x56\x1d\x19\x1c\x1c\xb5\x3e\xd0\xbb\x20\xbb\x5c\xcb\xa9\xc6\x0c\x9e\xf3\x2a\x02\x34\x90\xaa\xa3\x2a\xb8\x87\x42\x9c\xdc\xe1\xad\xe5\x07\x3a\xa5\x46\xa6\x91\x0d\x9c\xbb\x64\x6d\x7e\xa6\x7e\x78\x48\x46\x7d\x7d\x03\xeb\x93\x67\xe8\xbb\xe4\x15\xf5\x56\x45\x76\xec\x3b\xcd\x6f\x53\x53\x05\x9f\xf6\x6e\xc8\x01\x13\x5b\xcf\x8f\x41\xf2\x3f\xf5\x32\x8d\x9e\x44\xb1\x95\x1a\x62\x52\x64\x46\xea\xa6\x15\x15\x35\xcc\x99\x53\xf9\xda\x68\x28\x36\x7a\x94\x40\xc9\x4a\xd0\xe3\xf3\x2b\x71\x7e\x19\x6f\x43\x64\x43\x0e\x1d\xce\x9e\xfa\x9f\x72\x56\xb2\xdf\x79\xfd\x8d\x91\x9c\xac\xf6\xf8\xb1\x8f\xe6\xae\xac\xaa\x62\x98\xa1\x6f\xae\x78\xfb\x6a\x52\xda\xa8\x21\x74\xca\xe8\x0d\x8c\xee\xd8\x37\x45\x39\x4d\x4d\xbb\x3e\x0c\xdf\x1d\xbf\xd7\x75\x4a\xf1\x37\x9f\x16\xcf\x9d\x3c\xab\x73\xd9\x6c\x9e\xaf\x95\x90\x4f\xa7\x5b\x31\x61\x1c\xe2\x74\x56\xa8\x82\x90\xca\x86\x45\x63\x87\x37\x34\x38\x39\x05\xcf\x1e\xb9\x6c\x15\x7d\x1c\xfe\xc4\x7d\x8d\x0b\x56\xc0\x8c\xa7\xb5\xd0\xc7\x27\x2b\xbe\xd7\x5a\xc1\x4f\x40\xd5\xc1\x5e\xee\xb6\x50\x6f\x27\xb3\x91\xac\x91\xd1\x62\x9c\xb1\xe0\xeb\x82\x82\xaf\x3b\x15\x15\x17\x17\xd1\x8f\x45\x8a\x0f\x43\x22\x55\x91\x9f\x9f\x47\xd6\x41\x19\xa9\x7e\x6c\xbd\x35\x07\xd6\x96\x9d\x50\xd9\x90\x15\x9f\x3c\x22\xb7\xbc\x8c\x36\x52\xd2\xe6\x07\x99\xde\xef\x68\x96\x0a\xb9\x1e\x75\x94\xb3\xe8\x17\x73\xc8\xcb\x1d\xbc\x70\x21\x9c\x2c\x2b\xa3\xea\xa6\xc5\xc3\xf1\xf8\xdc\xdc\x78\xdc\x2f\x7e\x9a\xe3\xef\x2b\x84\xbd\xd5\xe8\x75\x7a\xf2\x8d\x52\xa7\xd4\x28\xf9\xef\xe6\xcc\xe1\xbf\x2c\x28\x20\xdf\x56\xad\xdc\xc4\x7f\xbc\x69\x65\x15\xff\x35\x42\x74\x4b\x35\xe4\xc0\x29\xee\x36\xc1\x8e\x50\x13\x6f\xbb\x90\x28\xaf\xb4\x26\x13\x0a\x18\x85\x81\x9c\x35\xae\x9a\x95\x37\x25\xa4\x61\xf2\x94\x4e\x65\x05\x2f\x16\x2e\xee\xa2\x4a\x08\xd4\x6a\xf3\x79\xea\x29\x6e\xd4\x8b\x34\xd5\x84\x67\x15\x94\x8c\x4f\x55\x76\x4d\x0a\x0b\x61\x5e\xb4\xf2\x00\x72\x28\xc4\x59\x6c\x3c\xb0\xaa\xb3\xca\x86\xee\xdd\x35\x61\xa1\x99\x0f\xa9\x2c\xa6\xf2\x69\x49\xb7\x08\x8f\x1d\x2a\x5e\xd6\xfe\x80\x1c\xc8\xe3\x2c\xed\x73\x8d\x5d\xc3\x34\xdd\xbb\x7f\xbd\xb0\x34\x13\x4a\x77\x78\x44\x74\x63\x56\x3e\x2d\x5e\x5a\x6a\xcb\x17\xa2\xaa\xd9\xfa\x56\xf9\xc2\x29\x1d\xe7\x0b\xaf\x6d\x80\x81\xbc\x1a\x6b\xde\x21\xe2\x3d\xae\x85\x1c\x56\xcd\x9e\x22\x16\x65\xbb\x77\xae\x4d\x42\xf5\x6d\x93\x8e\x76\xf8\x39\x07\x2e\x18\xfa\x51\x82\x5c\x3d\x3f\xed\xd5\x65\xaf\x2e\x4c\x8b\x0a\x0d\xcd\x98\x3f\x6a\x70\xc3\xfc\x91\x43\xf9\xf1\x73\xe2\x7a\x15\x19\x7a\x2f\xdb\xd8\x5c\xbf\x70\x99\x8c\x3f\x11\x8f\x8c\x0b\x0a\xf1\x22\x38\x61\x5c\xb0\x82\xe4\x38\xaf\x82\x1c\xd2\xa3\x3e\xf0\x19\x79\x1c\xbc\xac\x72\xf6\x44\x8e\x06\x7e\xec\xe2\x51\x43\x2e\x5d\x72\x76\x1e\xf2\xc6\xc7\xf1\xf2\xc0\x85\xc9\xe5\x15\x56\xc9\x2d\x80\x72\xdc\xd7\x58\x5a\x01\x33\x9e\xd6\xc0\xc0\x6e\xc3\x8a\xf9\xb9\x85\xb3\xfb\x18\x72\xe8\x0c\xa2\x5b\xed\xfc\x74\xcc\xa5\xb2\x5e\x9d\x9a\x40\xa7\xe0\x50\x4d\xb7\x1d\x7e\xce\xc1\x4b\x86\x56\xac\x6a\xe8\x33\x60\xec\xf0\xb2\x79\x19\x50\x52\xe5\xd1\xa3\x1b\x9d\x99\xd3\x47\xbf\x66\x35\x76\x86\x13\xa3\x46\x2d\x58\x81\x07\xbc\xb2\x44\xe4\x1d\xfd\x80\x3d\xd5\x2e\x87\xca\xba\xc7\x7a\xeb\xf0\x6b\xad\xc3\x86\x6a\x42\x83\x83\xb3\xee\xf2\x83\x13\x2e\xf1\xa3\x36\xd7\x75\xeb\xe1\x51\xa5\x7c\x4c\xf9\x91\xb1\x37\xda\xf6\x94\xae\x21\x98\xa9\xfc\xd8\x40\x52\xaf\x35\xe0\x0f\xb2\xb5\x4d\x30\xc5\xe3\x3c\xc6\x3b\x24\x12\xb2\x91\xb7\x0e\xe8\x20\xaa\x09\x53\xbe\x99\x6f\xe2\x0b\x42\x2d\x7a\x36\x65\xa4\x93\xd8\x53\xc8\x05\x49\x89\x0e\x70\xcc\xc0\xf2\x22\xce\x49\x5e\xc1\x9c\xaa\xfd\xe0\x8b\xb3\x1f\x7f\xf0\xc5\x35\xaf\x65\xcb\x3c\xf1\x17\x10\xeb\xb9\x6c\x19\x63\x38\x74\xe9\xea\xfe\xa3\xdf\x5c\x2d\xde\xb1\x63\xed\x56\x32\x16\x94\x30\x83\xb9\xc7\x48\x86\xbc\x09\xde\x1a\x89\x48\xc9\x88\x46\x16\xa2\xcc\x06\x4f\x2f\x95\xcc\x1d\x80\x04\x9b\xb5\xd9\x5f\x9f\x3e\x76\xe4\x1f\x5f\x7f\x7e\xec\xb3\x6b\x97\xf2\x26\x8c\x9f\x0e\xe5\x13\x72\xa6\x65\x32\xfd\x6a\xbf\x70\x87\x48\xdc\x20\x6f\x78\xff\xc3\x8b\x32\x7c\x02\x12\xe4\xdf\xbc\x3f\xf1\x15\x57\xb8\xe4\xba\x04\x7f\xea\xfa\xca\xc4\xec\x57\x5c\x05\xba\xb3\x21\x87\x32\xb2\xa7\x6c\x75\x69\x0e\xef\x74\xb1\x7e\x5b\xe9\xc0\x5f\x31\xf6\xaf\x8d\x80\xec\x77\xd7\xad\x5c\xd6\x3f\x6e\xaa\x3e\xab\x4f\xee\x92\xb1\xd5\xdb\x63\x02\xd5\xc1\x81\x81\xdd\x87\x9c\xe9\xb7\x21\xaa\xb8\xef\x8c\x97\xc6\x32\xf7\xf3\x8a\xfa\x6e\xf4\xf6\xd7\xf9\x86\x86\xc6\x4c\x4f\x2f\x59\xe4\x9c\xd7\xad\x9b\xeb\x5a\xc5\x2f\x60\xe8\x1a\x94\xe8\xdf\x23\x22\x3a\x5f\x90\x97\x7c\x78\xc2\x3d\x44\x2a\xbb\xbc\xb4\xb6\xb1\x44\x41\x79\xe9\xa5\xc4\xa8\xa0\x6e\x81\xdd\xcb\xe6\x8d\x82\x45\x44\x46\xb6\x2e\x2d\x56\xee\x70\x0b\x0d\x6b\x2a\xe4\xa5\x83\xe4\x68\x41\x0e\x95\xc4\xcd\x26\x71\x0c\x7b\x8e\x16\xbf\xfa\xd6\x9e\x1b\x92\xaf\x55\x9c\x50\x71\xf5\xaa\xae\x7b\x7c\x72\xde\x94\x41\x3d\x02\x03\x35\x1a\x45\xd9\x3c\xd6\x27\x73\xc8\x27\xfb\xdf\xc1\x95\xe1\x61\xde\xf8\xe7\x97\x0a\x15\x6b\x5d\x35\x91\xe3\x17\x2f\x05\x21\x0f\x40\x43\x19\xe9\xe3\x04\x4f\xc2\x4f\xa8\x2c\x11\x62\x09\x44\x47\x8b\x07\x27\x01\x54\xbc\xda\x55\x6b\x66\x34\x80\xa6\xa1\xa0\x60\x47\x17\x97\xe0\x25\x49\xcb\x56\x35\x2c\xda\x20\xc7\xd7\x19\x6e\x25\x68\xf1\x35\xfe\xff\x2b\xf1\xde\x29\xf1\xb1\x6b\x5f\x1f\x24\x37\x1e\x20\x3e\x4a\xca\x48\xcf\x67\xeb\x89\xa5\xa4\x57\x2b\x39\xa5\xf5\xfa\x17\x5c\xc4\x4a\x11\xd8\xcf\x10\x0a\xc5\x9b\xe6\xbc\xf8\xe2\x9c\x94\x14\x28\x36\xae\xfc\x66\x7f\xdd\xe5\x4a\xd6\xe7\x9d\xb7\xc7\x7d\x30\x3d\x2f\x6f\xfa\xb8\x97\xc3\xdf\x7e\x27\xe7\xd3\x77\x0e\xd5\x6f\x3b\x2c\xdc\xa5\x68\x15\x65\xa4\xd3\x08\x0e\x6a\x07\xb9\xe6\xab\x1a\x86\x0e\x4f\x7c\xe1\x52\xdd\xde\x8f\x6b\x19\x4f\xa8\xc2\x19\xb9\x99\x99\xb9\xb0\x07\x67\xef\xdf\x6f\x16\xbf\x9d\xc1\x9e\xb2\xd7\x35\xd9\x9e\xb8\x42\x3e\x82\x1f\x88\xa3\x0c\x1f\x9b\x9c\xaa\xd5\xa8\xc3\xa2\x47\x15\x16\x1f\xae\xaf\xdf\x6f\x1f\xec\x50\xb7\x08\x8f\x2a\xe5\x2b\x2f\x7d\x5a\x7f\xc0\x4c\xf4\xc3\x1f\x54\x1d\xed\x29\xdc\x39\x34\xe8\x40\x43\x87\x68\x35\x9c\x84\x76\x85\xe0\xab\x10\xf4\xed\x7a\x5f\x86\x61\x3b\x6f\xe4\x0f\x5a\x13\x86\xfa\x09\x03\xfa\x4e\xc2\xc9\x84\x8e\x74\xaa\x8e\x32\x11\xdc\x52\xa4\xb0\xd5\xec\xa5\x43\x2e\x36\x51\x7d\xb1\x11\xf2\xa8\xba\x45\xf0\xf3\xbb\x2b\x71\xa8\xa8\x67\xd3\x21\x87\x8e\x17\xef\x64\xbb\x3f\xc2\xc1\xa4\x76\xf8\x36\x58\xe3\x1f\x14\x91\x9c\x39\xdd\x36\x06\x7e\x14\xa9\x71\x5d\xab\x98\x36\xaf\x44\xb4\xd9\xe2\xe8\x0c\xb2\xef\xfe\xf6\xd1\x6c\xb6\x6c\x18\xf0\x96\x62\x3f\x10\xea\x17\x38\x61\xdc\x44\xbc\x2d\xa3\x7f\xe9\xd8\x61\x13\x56\xac\x99\xd5\xad\x53\x81\x54\x71\x31\xb2\x34\x2a\x24\x46\x98\x61\x31\xf6\x7f\x79\xca\x84\xe1\x73\xa6\x4d\xf2\xd5\x46\x84\x54\x25\xc4\x24\x08\x6b\x0e\x87\x7c\x9a\x22\x58\xc0\x48\xd1\xbe\xd6\x90\x21\x7b\x16\x9e\xb8\x6d\xc0\xcc\x79\xcb\x57\xa5\x83\x17\x9e\x49\xbd\x85\x2f\xc2\x88\xef\xce\xd6\xc0\x8e\xba\xc0\xc0\x17\xb3\xc6\x67\x6e\x84\x4e\xef\xae\xc4\x37\xbb\xe1\x7f\x6c\xaf\xb7\xe9\xa6\xc1\xdc\x13\xd2\xf3\xc7\x47\xf4\x22\x08\x81\x36\x4a\x4c\x6d\x16\x43\x27\xd9\xf5\x9f\xed\x3f\x72\xe8\x60\xdd\xd1\xcb\xf4\xd0\xf4\x11\xc9\x0c\x3e\x0d\xbd\x25\x43\xd3\x86\x0f\x61\x1a\xc0\x1b\x64\xf8\x67\xfc\x3b\xbe\x85\x7f\x07\x9f\xd3\x55\xd5\x55\xd5\xdb\xdf\xdd\xbe\x9d\x1f\x1f\x67\x33\x8f\xa1\x8a\x5b\x4f\x30\xb8\xfd\x10\x82\x18\x7b\x69\xab\x5e\xed\xa5\x52\x6a\x42\x82\xed\xff\x84\xb3\x97\xc6\x25\x27\xc7\xc5\x0f\x6e\x04\x4e\x1a\xbe\x72\x09\x78\x97\xf7\x1d\x94\xd2\xab\xcf\x10\x76\xd1\xf2\xfe\x43\x12\x07\x0c\x00\x85\xe7\x6b\x1f\x74\xde\xd7\x7f\xf9\x90\xfe\x89\x03\x06\xf0\xe3\xeb\x99\xc7\x70\x81\x8c\xaf\xe0\xef\x14\x87\xf1\x59\xa1\x61\x00\x27\x31\x38\x4c\xa0\x17\x27\x80\x50\x0f\xad\x13\x70\xbd\xca\x7f\x2c\xe7\xff\xc1\x3e\x43\x40\xe7\xa8\xc3\xfd\x3d\x5f\xde\xff\x6f\xe1\xaf\x44\x26\x2b\x70\x1a\xca\x6b\xd9\x83\xc2\x10\x92\x90\x84\x63\x77\x4a\xe9\xd9\x95\x12\xfe\x54\x29\x03\xf5\x31\x7d\x29\x7d\x4c\x04\x25\xfc\xa9\x09\x94\x94\xbd\x10\x9b\x1f\x10\x12\xe0\x17\xe4\xe7\x17\xe4\x37\xbe\x56\xdd\x4d\xad\xee\xa6\xd6\x84\x69\xa2\x7b\x44\x14\xf9\x26\xf8\xf8\x29\xdc\x3a\x71\x12\x17\x85\x5c\xa6\x70\xed\x24\x71\x67\xa2\xfa\x49\x95\xee\x2e\x9c\x53\x27\x67\xa9\xd4\x43\x25\x97\x3a\xc9\x94\xfc\xbc\x78\x3e\x73\x18\x2a\xd9\x27\xbc\x8c\x82\x5e\x27\xec\x46\x2c\xf1\x5b\xb8\x53\x9a\xc0\x08\xc0\xf3\xeb\x5d\xc2\x22\xba\x0e\x4d\xa9\xd8\x2f\x75\x4f\xab\x28\x29\xec\x3d\x7d\x7e\x2f\xf6\x5c\x54\x7c\x8c\xb7\x7f\xec\x89\x90\xf0\x90\xf8\x12\x32\x4e\x03\x73\x0a\xfa\x71\x0c\x62\xf9\x71\xd4\x06\x15\x8b\x1b\x40\xf3\x67\x06\xfe\x9e\x39\x75\xb0\xa2\x8a\xf8\xfe\xf1\x71\xe6\x14\x44\x8a\xbf\x63\x50\xa9\x95\x6a\x7c\x3c\xe3\x4f\xd0\xe0\x3a\x36\xa7\xaa\xe2\x20\x12\xc7\xa9\x83\x7e\xec\x1f\xe2\x38\xac\x44\x8b\x1b\x20\x15\x02\x33\xfe\x64\xe3\x0e\x6d\xaf\xaa\x10\xc7\xa9\x83\x48\xf1\x77\x82\xd5\x4a\xb5\x04\x1f\x87\x40\x48\xc5\xd7\xff\x64\x33\xb6\x1f\x12\x7e\x27\x8e\xa9\x81\x33\xec\x63\x24\x21\x73\x05\xb3\x12\x2d\x8b\xe3\x32\xee\x82\x1f\x44\x65\xdc\xc5\x37\xd9\xb4\xaa\x45\x15\x55\x55\x8b\x2a\xda\xfe\x6e\x30\x6b\x50\xb1\xc1\x12\x1c\x07\x51\xe0\x77\x37\x03\x5f\xc4\x37\xef\xb2\x19\x55\x15\x8b\xaa\xaa\x2a\x16\x21\x68\x49\xc6\x9e\xa8\xae\xe5\x08\xf2\x40\x48\xa2\x53\xd9\x33\xe9\xfc\x40\x53\xbf\xd6\x49\xd5\x3b\x46\x1b\xec\xe9\x17\xdc\x37\xa6\x2a\x75\x90\xa6\x87\xd3\x66\xd7\xd4\xd1\x84\x3f\x2d\xa3\x99\x03\xa8\x9a\x4b\xe7\x6d\x42\x5a\x1f\x6b\xd0\x29\x39\x09\x91\xcc\x9a\x85\xc7\x55\xe1\x6f\xce\x4f\x52\xfd\x8b\x1d\xb8\xaa\xeb\xb4\xe9\x7e\x43\x7a\xf7\x98\x26\x60\xab\xe0\xe5\xd8\x13\xd6\xb4\xec\x45\x6e\xbc\x54\xb3\x3a\x2f\x95\xd2\x1d\x24\x1a\x7d\xac\x21\x44\x1b\xac\xf3\x52\x19\xf8\x61\xf8\x7f\x89\x00\x2d\x5e\xae\xba\x9c\x1b\xf9\xe1\x44\x95\x76\xd3\x9c\xe1\x30\x3b\xbf\x7b\x82\xaa\xbb\x26\x3f\x20\xcd\x6f\x95\x32\xbd\x6b\xfa\x0c\xff\x55\xae\x49\xd1\xd3\x3b\x27\xc7\x46\xa5\xf4\xfe\xb0\x4f\x51\x2f\xef\x84\xb3\x2f\x8e\xfe\x57\x34\x62\x10\x6a\xde\xcd\x56\xb0\x87\x91\x84\xf4\x09\x0b\x46\x28\xca\x8a\xff\xe3\x58\x21\xae\xa6\x42\xb4\x1c\xed\xf0\x1a\xa4\x18\x28\xa3\x38\x5c\x3b\xa3\xf9\xde\x8c\x45\xcb\x8b\xe6\xbc\xf9\x46\x61\xe1\x8a\x78\x58\xb4\x3e\xd8\x49\xdd\xaf\x67\xcf\xee\xb1\xb1\xdd\xbb\xc7\xb2\x87\x9f\x24\x42\x16\xae\xc6\x9b\x66\x2d\x7d\x6d\xda\xac\xd7\x96\x30\xbd\xe0\xda\xcb\x41\x4b\x9e\x24\x84\xc7\xc4\x84\x87\xeb\x74\x88\x41\x19\xcd\xbb\x99\x78\x66\x3e\xc1\xd0\x8b\x40\xbd\x9f\x53\xe7\x03\xad\x7a\xc1\x59\xbd\xad\x8e\x51\x43\x47\xcf\xeb\x65\xab\xc3\x95\xb2\xae\xce\x20\x78\x5e\x27\x5b\x57\xd7\xda\x05\xab\xda\x32\x39\xe5\x40\xf3\x43\x71\xa1\x74\x90\xe8\x82\x6d\x7a\x60\x5d\x2a\x62\xd0\x01\x84\x98\x3f\x24\x79\x62\xed\x68\xa8\x80\x99\xe3\xd0\x9c\x56\x43\x93\xa5\xa8\x35\x7a\x7b\x2b\x02\xd1\xe1\x74\x00\xce\x80\x01\x7c\xca\xf2\x56\x95\xe1\x1f\x1e\xff\xfa\xc5\x92\x97\x70\xd3\xb1\xba\x57\x8a\xca\x2a\x76\xb2\xc4\xf3\xc4\xd6\x9b\x8f\x97\xef\x96\x39\xfb\xef\xa9\x3c\xfb\x23\xa0\x9c\xa9\xf5\x8f\xd2\xc6\x8f\x1e\x4a\xf9\x6c\xdc\x38\x64\x38\xa2\xd1\x0e\x31\x2f\x4d\x8e\xfc\x51\xb7\x36\xd1\x54\xaa\x7d\xfc\xd4\x36\xb1\x2d\x90\x2a\x64\xa0\xd9\xe3\xa7\x9b\xc9\xb4\x8e\x51\x54\x92\x7a\x66\x0f\x9e\xd2\x61\x64\x6a\x9e\x6e\x9c\xce\xfc\xc1\xd6\xff\x1f\xd3\xcd\x19\x8d\xa3\xd3\x9f\x45\xf7\x93\xc8\x4d\x9b\x86\xa4\xf1\x74\xe3\xf4\xff\x5b\xba\x23\xc9\xb4\xcf\xa1\xbb\x69\x3d\x99\x9a\xd0\xfd\x9e\x48\xb7\x58\xc9\xdb\x96\x6e\x56\xad\x54\x2b\xda\xd2\xde\x9a\x64\x5c\x4a\x19\x9b\xc7\x6f\x6d\xb5\xe1\x8e\x24\xaf\xbe\x44\x4d\xb4\x12\x4d\x7a\x6e\xe2\xf7\x44\x7a\xbd\x90\xa6\x23\x7a\x3d\x80\x9f\xb4\xc3\x58\xb9\x40\xea\x28\x7e\xc2\xb7\x3b\x8c\x93\x13\x4a\x57\x5f\xa2\xd7\xd9\x02\xe4\xe4\x7e\x2e\xc1\x9e\x4c\x83\xa4\x18\x79\xa1\x50\xc1\x97\x2d\x0f\xb2\x1a\xe1\x94\x52\xaa\x8e\x36\xc8\x88\x03\x5d\x30\xbc\xb5\x06\x9d\xd5\x3f\xa4\x55\x58\xbb\xe4\x94\x18\xc1\xd0\x70\xf9\x6a\x6e\xba\x71\xc4\xc7\xc7\xa0\x60\xeb\xb7\x75\xdf\xe3\xe3\x78\x2f\x2c\xf5\x7d\xd1\x27\xc9\x98\x76\xdc\x37\x39\x73\xf3\xf6\xb4\xc4\xec\x9a\x7e\x90\x11\xf3\x74\x08\x75\xed\x16\x8c\xdd\x3f\xad\x49\xdb\x1b\xff\x75\x0f\xab\x86\xe1\xa6\x14\x28\x6f\xce\x91\xb8\xf7\x1d\xe5\xb3\x35\xc1\x7b\x6a\xff\x25\x73\x95\x4e\x94\xef\xd9\xa9\xca\x98\x0b\xd1\xc2\x1a\xb3\xb0\x27\x7d\x93\x53\x23\x25\xea\x86\xa2\x5a\x61\xea\xca\xa4\xc4\xdf\xef\x0e\x9a\x80\xe7\x2d\x31\x0b\xba\x40\xa7\xcf\xb7\x0a\xf0\x36\x99\x9b\x52\x92\x37\x17\x37\x3f\x02\xaa\xf5\x02\x13\xad\x0b\x0c\x05\x3f\x08\x4f\x15\x21\x72\x22\xa3\xf1\xd3\xc8\x20\x7c\xbb\xd5\xfa\x38\x53\xab\xf5\x1d\x40\x88\x9d\x2f\xc9\x23\x75\xd8\xde\x0e\x68\x5a\xb4\x50\x89\xed\x70\x20\xce\x43\x1e\xac\xc6\x53\xf1\xcb\xf9\x15\x70\x0c\x4f\xda\x15\x2d\x9e\x7f\xbc\x0c\x7f\x84\x37\xe3\x25\x80\xe0\x06\x5c\x15\x0f\x3e\xb2\xf6\x72\x14\x70\xea\x7d\x89\xb7\xb0\x03\x1c\x79\x9b\x63\xfb\xb9\x80\xf2\x88\x4c\xf5\x1c\x58\x79\x66\x32\x3f\x6b\x73\x7f\x87\x30\x0b\x4f\x1b\x4e\x67\xf9\x77\xc1\xff\x4e\x9b\x4e\x3c\xe3\xad\x69\x13\x0f\xb7\xb8\xaf\xe9\x36\x0c\xfe\x67\xd0\xe6\x48\x92\x6d\xae\xe7\x80\xe5\x8f\x26\x93\x3e\x07\x32\xbf\xc9\xc7\x3e\xff\x01\xfc\x9e\x48\x9b\xab\x88\xbc\x20\xd0\x26\x1c\x6d\x42\x9f\x03\x59\xf8\x11\x7f\xb8\xaa\x04\xe2\xec\x64\xf1\x87\x98\x27\x8c\xd0\xf3\x9e\x48\x0f\x39\xbf\x1d\xd0\xa3\xb0\x9d\xdf\x67\x6c\xd3\x77\xfc\x1c\xe3\x9e\xbd\x49\x38\xe3\x12\xbd\xc2\xbe\x43\x3c\x0d\xf1\xcf\xdd\x1f\xd1\x46\xd5\xb4\xdf\x1f\x77\xde\x42\xed\x9c\xf2\x62\x6d\xdb\x2d\xfa\x6b\x3b\x6f\xa2\xee\x5e\x2d\xee\x51\xfc\xff\xb4\x47\xd6\xf9\x9e\xb3\x47\x6a\xeb\xc4\xcf\xd9\xa6\xa7\x2b\x1c\xd6\x70\x00\x4f\x13\x69\xf4\xe2\xad\x21\x1b\x8d\x10\x6b\x50\x77\x05\xde\x92\xd2\x72\x12\x4d\x07\x3b\x56\xfb\xd9\x0b\x30\xd5\xff\xad\xa4\xf3\xef\x0c\x4b\xdb\x7c\xfe\xe7\xb6\x5b\x87\x5f\xfd\xac\x30\x66\xdf\x60\xdf\x09\xa3\x46\x4e\xa4\xde\x22\x9b\x28\xd2\x3c\x4d\xa4\xb9\x5d\xe6\x90\x75\x1f\x5b\xcf\xfc\xbc\x1d\x2d\x6f\xb5\x86\xda\x67\x6f\x6d\x73\xae\x7d\x35\xf4\xe7\xad\xf6\x18\x21\x86\xfa\xff\xf1\xf6\x25\xf0\x51\x56\x57\xdf\xf7\x3e\xdb\x64\x23\x30\x99\x99\x0c\x10\x48\x78\x18\x92\x21\x84\x10\x92\x61\x32\x84\x2d\x0b\xfb\x16\x20\x86\x18\x10\x22\x22\xb2\x29\x6b\x88\x88\x98\xa6\x88\x48\x15\x10\x83\x6c\xa2\xa5\x88\x98\x17\x11\x29\x46\x44\x44\xc4\x05\x01\x29\x22\xa5\x29\xa5\x14\xa9\xe5\xa5\x88\x68\x54\x44\x4b\x31\x99\xb9\xf3\xfd\x9e\xfb\xec\xdb\xcc\x24\xfa\x7e\x3f\x9b\xb2\xcd\xdc\xfb\x3f\xff\x7b\xee\x39\x77\x39\xe7\xdc\xa8\x0a\x10\xcb\x57\xbd\x55\x3e\x66\x03\xb9\x9d\x99\x97\xc7\xd2\x0b\x1e\x22\x47\x05\x1a\xe1\xf7\xc8\x4a\xd8\x03\xf1\x9c\x26\xc1\x31\xc9\xd5\x39\xa7\x47\xfe\x8d\x3e\x28\x56\xf9\x65\x32\xde\x7f\x9f\x48\xb1\xe7\xd4\xe5\x26\xe5\xbc\x29\xbc\xf9\x3b\xdd\x12\x87\xdf\x3e\xe4\xef\xea\xd4\x77\xa9\xf8\x46\x03\x1f\x09\xc8\xdd\xd8\x0c\xaf\x53\x71\xe4\x3d\xfa\xf3\x21\x65\xbf\x13\x0d\xef\x54\x1b\xbb\xbb\x61\x0f\xf2\x98\x02\x48\xf3\x97\xfc\xc5\x6a\x04\xb2\x8a\xaf\xb4\x69\x65\xbd\x3e\xa8\xb2\x13\x1c\x93\x7d\xaa\x54\x2d\x2b\x8c\x49\x1a\xf6\x7c\x96\x3d\xfb\x55\x9c\x4f\xa5\x96\x37\x25\xb4\xbc\xbc\x94\x36\xa9\x47\x73\x79\xff\x29\x96\x31\x16\x31\x98\xc8\x1b\x38\xbf\x68\xf9\x72\xe2\x63\x19\x11\x01\x5e\x47\xb3\xa8\x04\x7c\xee\xc7\xed\x8e\xd5\x6a\xa5\x90\xfd\x75\x95\x16\xc5\xca\xb2\x2b\x75\x18\x3e\x2f\xcb\x2e\xea\xf1\x74\x5c\xc3\x38\xc4\xc8\xaa\xbb\x0c\x35\xb2\x0f\xa9\x30\xfc\xd9\x7c\x68\x03\x0f\xc9\x98\xa8\xe1\xdc\xc8\x12\xe0\x10\x9a\x44\x11\xf8\xdc\xc5\xa5\x19\x55\x6e\x1f\x95\x4c\x48\x49\x96\xbd\x08\x6e\x5d\xa3\x18\x5d\xff\xdb\xb1\xeb\x1f\x4e\x1f\x37\x76\x54\xb7\x94\xbc\x36\x9b\x62\x6b\x97\x88\xbf\x97\x85\x45\x93\x6a\x77\xb1\xee\x2e\x7d\x72\xb9\x5f\x58\x6f\x2e\x96\x7d\x92\x20\x7b\x4f\x1c\x03\x64\x28\xbb\x61\xd7\x21\x39\x98\x66\x82\x65\x78\x08\x36\x06\xab\xc1\x51\x13\x25\x5d\x47\x76\x8a\xb0\x54\x83\x58\xd0\x01\xf4\xd4\xb0\xe2\xe1\x70\x09\x69\xa7\x36\xfd\xd2\x46\xc9\xcf\xe9\x3d\x54\xd6\xc4\x89\x9f\xb5\xdb\x17\xf7\x79\xdd\xbe\xb3\x2f\xaa\x57\x35\x32\x49\x96\xea\xac\xdc\xf6\xd5\xdb\x0e\x1d\xfc\xef\x4d\xd5\x62\x46\x98\x17\xc8\x4e\x4d\x67\x32\xb0\xae\x78\xc1\x00\x33\xc6\xc2\xc0\x0a\xc9\xdd\x6a\x15\xce\x1d\x6a\x9c\x6d\xcc\x09\xa4\x1d\x02\xf0\x9f\x8b\x54\xc0\xa9\x55\x98\x48\x5c\xe3\x9d\x44\x96\x99\xf8\x4d\x21\x05\x8b\xa4\xb4\x36\x21\x87\xf1\xf5\xcf\xb3\xc4\xe5\x16\x5a\x1d\x08\x1c\x65\xce\xe1\x65\x16\xc1\xcd\x0d\xb2\xca\xb2\x9e\xaf\xa9\x6e\x14\xa1\xc9\x5a\xa5\xb5\x87\x26\x38\x13\x9d\x3d\x82\xdb\x54\x87\x66\xfa\x57\x93\xcb\xc8\x15\xc2\x22\x8e\xc0\xef\x4e\xb8\x19\x04\x3a\xe2\xf6\xdb\x89\x55\x70\x84\x3a\x59\xe2\x53\x84\x5d\x00\x67\xe0\x96\xc2\x4d\x70\xd6\x95\x73\xb3\x76\xbc\x7e\xea\xd6\xb1\xc3\xf7\xcd\x40\xdf\x10\x43\xd6\xfd\xfc\x38\x7a\x0b\xbd\x0c\x4b\x88\x3a\xe2\x32\x9c\x0e\xd7\x4e\xbe\x33\x1e\xdd\xfa\xf7\x77\xcd\x76\x98\x0d\x89\x40\x4c\xaf\x54\xb8\x8a\x3a\xdc\xd0\x20\xac\x95\xa9\x45\xf4\x5e\xdc\x97\x2a\x6a\x48\x17\xf5\x89\x6d\x9c\xe2\x4c\x55\x8a\xfc\x94\xa2\x3d\xa3\xa3\x1f\xfc\xcb\xa9\xcb\x87\x89\xba\xc0\x85\x07\x17\x2d\x9f\xab\x88\xf7\x6c\xde\xc1\x07\x79\x26\x3e\xf5\x0a\xcc\x25\xdf\x6e\x68\x08\x8c\xdf\x5d\xb7\x6e\x3b\x0e\xf4\xc4\xe3\x41\xcf\xb4\xcc\xe4\x6b\xb8\x28\xab\x25\x2b\x56\x8b\xb9\xc4\x60\xe8\x45\xa7\x03\xef\x3d\x2a\x8c\x49\xe0\x18\x31\xb0\x69\x14\xb1\x34\xf0\x94\x34\x2e\x3b\x00\xa0\x76\x5b\x66\xf2\xe3\xa2\xad\x78\xcc\x5f\x4c\x29\xf7\x7c\x42\xd9\x63\x5c\xf2\x38\x5f\xdc\xe1\x0a\x85\x8f\x03\x6e\xa1\xe8\xb1\xd0\x38\x1e\x17\x6e\x6d\x3b\x13\xdb\xa4\xc8\x70\xe2\xe5\xac\x8c\x13\x5d\xc7\x4b\x49\x02\xef\x53\x77\x33\xf6\xd6\xe0\xcc\x14\x77\xa4\x5a\x9c\x42\xe3\xd2\xfe\x62\x26\x7e\x37\xdd\x29\xee\x0b\xc5\xff\xcc\x9e\x89\x55\x00\xf7\x1a\x3d\x87\xab\x60\xfb\xac\xe1\x3b\xb8\x3c\xf7\xe5\x38\x07\x21\xd3\x4c\x2a\xb3\xde\x35\x42\xce\xd6\x23\x30\x1c\x19\xa3\xb7\x99\xd7\x21\x3b\x1e\x23\x3e\xaf\xde\xc0\xe2\x28\xc8\x58\xa7\x36\x29\x19\x32\x07\xe8\x9c\xca\x72\xc0\x0b\x4a\x06\xf8\xba\x43\xc8\x8e\xc7\x30\x01\xaf\x72\x8d\xfb\xd1\x13\xb0\x48\xdd\x63\x96\x5a\x6e\x5d\xaf\x06\x52\xf3\x7a\x38\x5c\xd0\xc3\x0e\xea\xd1\xb5\x28\xcd\xad\x62\x48\xe7\xa8\x2c\xa9\x52\x96\x59\x82\xa9\x04\x7c\x8c\xef\x70\x41\x2f\x5d\x66\x23\xa8\xea\x41\x33\x6c\x6f\xab\x7a\x31\xc0\x2e\x77\x46\x04\xff\x83\x26\x91\x39\xf8\x8e\xc2\x25\x64\x4e\xe9\x1c\x2b\xa9\xb8\xe3\x8f\x35\xf1\xa3\x23\xea\xeb\x89\xe7\xeb\xeb\xb5\x0e\x1d\xfe\xcf\xfe\x12\xb2\xbe\x64\xff\xfe\x12\x7f\x71\xc9\x7e\x00\xc8\xe0\x1f\xd0\x24\xe2\x73\xc6\x8e\x4f\xa5\xba\x99\xf5\xa8\x8a\xf9\xba\xcf\xa4\xcb\x7b\xc5\xe8\x2f\x6d\xa7\x96\x34\x31\x08\x0c\xd7\x70\xa6\x40\x3e\x00\x64\x3c\x5e\x9b\x3a\x85\xb8\x69\xe5\xb1\xa4\x42\x3a\x28\x1e\x3c\x38\x14\x1f\xc8\x1f\xd6\x9f\xbf\x1b\x20\x05\x19\x33\xe6\x96\xc0\x31\x39\x1f\x0f\x15\xff\x9e\xd9\x9a\x3f\x68\x50\xfe\x80\xfc\xfc\x9f\x77\x29\xa5\xb5\x78\x93\x1e\xd9\x6c\xcf\x7b\x3d\xeb\xf7\xc2\x3f\x73\x58\x82\xdf\x00\x40\x1c\xb6\xc4\xe1\x75\x32\x7e\x83\x44\x39\x17\x6d\x78\xb5\x6c\x80\xc1\x21\xf6\xf5\x16\xcc\x46\x57\x34\xfd\xd3\xc3\x84\x0e\x9a\x6e\x73\x22\xd3\x57\xf5\xfd\xf2\xb6\x7d\xbc\xa5\x92\xaf\x55\xc5\xe9\x94\x54\x95\x5a\x3a\x6d\x39\x04\x73\x1f\x85\x6b\x61\x39\x22\x08\x02\xed\x40\x2b\x56\xe6\x09\x27\x2b\xf4\xc1\xc0\xfd\x7b\xe1\x0f\x81\x65\xfe\x73\xc4\xec\x8a\xc0\x6d\x26\x43\x3c\x46\xe1\x6d\xfd\x6d\xcb\x8b\xd2\x3b\x2d\x62\x76\x80\xaa\x65\x55\x66\xc0\x05\xb4\x03\x1d\x5d\xc9\x0a\x6d\xcb\x99\x01\x81\xd5\x38\x1f\x80\x29\x55\x9c\xd1\xf0\xb6\x7e\x3c\x8e\x4d\xd1\xe1\x56\x18\x7b\x35\xee\x89\xa2\xc9\x57\xa1\x16\x2d\x33\x6f\xf7\x6f\x33\x76\x63\xcc\x0a\x83\xaf\xc5\x9c\x2e\x18\x7d\x0d\x62\xc9\x9f\x1c\x42\x2f\x09\x58\xdb\x69\xb0\x5a\x58\x07\xab\x83\x59\xca\xed\xb8\xb4\x28\xd7\x36\x00\xc1\x06\xbc\x24\x60\x4c\xd0\x61\xe4\x5a\x33\x80\xb7\x90\x6b\x4f\x87\x6e\x6d\x83\xc8\x23\x95\x8f\x63\x4f\xe2\x45\x5b\x05\x95\xde\x72\x42\x60\x83\xc0\x5a\xf3\xa8\x20\x90\xb9\xaa\x45\x25\xf0\x32\x8e\xc5\x8c\xd3\xc4\x62\xd6\xe2\xcf\xb7\x85\xd9\xfc\x87\xe1\x3e\xc6\xfe\x73\x23\xf6\x41\x51\x5c\x5f\x96\x0e\x80\xe4\x57\x76\x78\xc1\xa2\xee\x31\x8a\xa8\x43\x31\x8a\x5e\x99\x61\x0d\x0d\x3f\x1f\x56\xf7\x4d\x06\xaf\xa3\x12\x62\x9d\x65\x3c\x20\x79\x46\xf1\x43\xf8\x4a\x04\x1d\x88\x3a\x44\x89\x28\x98\xea\x86\x86\x3b\x73\x15\x48\xf0\x78\x08\x32\x47\x8b\x32\xd3\xfc\x40\x10\x13\xfc\xff\xe2\xd9\xe7\x7a\x14\x38\x0f\x5e\x47\x2f\x11\xeb\x18\x3b\x20\x81\x05\x00\x8e\x64\xa1\x93\xc0\xe4\x77\x60\xf6\xda\x06\x78\xaf\xd4\xee\x2c\xa1\x5d\x9b\xc4\xa5\x6a\x3b\xc6\xf7\xb0\x42\xb5\xef\x12\x84\x53\x6c\xfb\x70\x9f\x4f\xa2\x59\xc4\x37\x8c\x1d\xb4\x01\x56\x00\x48\x55\x2b\x1c\x67\x8f\xaa\xda\x80\x1d\x61\xb6\x7a\xe3\x28\x70\xce\xbf\x97\xd4\x60\xa9\xc2\xef\x1a\x48\x15\xe0\x59\x6b\x9f\x5c\x9b\x0b\xb2\xd0\x95\xe0\x90\x0d\xcb\x21\x58\x07\x27\x33\x70\x01\xac\x43\x5f\x90\x71\xd1\x68\x35\xfa\x37\xda\x11\x6d\x83\x45\xd2\x74\x6f\xde\x49\x55\x34\x8d\x22\x0e\x64\xff\x16\xda\x9b\x57\x53\xcb\xd1\xce\xaa\x40\x39\x93\x29\x4f\x4c\x3c\xef\x2d\x45\x0c\x0b\x5c\xfc\x0e\x48\x1b\x91\xc4\xea\x72\x6d\xa4\xee\x35\x49\x37\xe8\x33\x39\xd9\x06\xce\x11\x20\x28\x6b\x06\x6b\x73\x6d\xa8\x8b\x4a\x1c\xbc\xdc\x33\x43\xc9\x2d\xab\xb9\xb1\xdc\x13\x84\x95\xac\xb1\xd4\x8a\x75\x27\x2f\xb3\xbd\x05\x32\x4b\xc6\x24\x84\xcc\xfc\x42\x3a\x94\xc4\x7c\x54\xb3\x64\x0f\x99\x06\x1c\xe3\xd8\x6a\x79\x0b\xc5\x89\x6e\x24\xaf\xbc\x7e\xc5\x76\xd2\x52\x44\x55\xfe\xca\xf2\x2e\xc3\xdd\x87\x92\x57\x89\x81\xf3\x5b\xa7\xf0\xfd\x5d\x7b\x41\x5e\xc2\xcb\xcd\x38\x2c\xaa\xc2\x05\xac\x26\x96\x5b\xda\x42\x27\x7a\x38\xf0\x44\xb4\xed\x53\x71\x44\xdf\x81\x9d\x1f\x26\x0e\x34\x8d\xa2\x4a\xd0\xa5\xea\xc0\x78\x69\x30\x85\x3d\x0a\x63\x17\x79\xf4\xe8\xa5\xb2\x29\x85\xc1\x89\x5a\xe8\x6c\x59\xc5\x6f\x17\xf7\x14\xc7\x6b\xc2\x5d\x62\xfe\xeb\x6b\x27\x14\x83\xc4\xfb\xac\x53\xf8\x0e\xaa\x05\x98\xcf\x88\xa3\xa2\xc1\x2c\x91\x21\xec\x57\xf0\xd9\x48\x4b\x31\x67\x8a\x9c\xab\x31\x2b\xda\xe6\x7c\xd7\x29\xe1\xde\x4c\x87\xd9\x89\xad\xa6\x0a\x2e\x2b\x98\x4f\x0d\xda\xb5\x0d\x82\xef\xe2\x71\xb6\x37\xc1\x89\x3d\x98\x1a\x62\x0d\xd7\xa0\x0e\x21\x6e\xef\x10\x9a\x25\x60\xeb\xac\xc7\x46\x6a\x2c\xaf\x0a\x65\x81\xd6\x04\x6b\xc9\x55\x9b\x63\x8c\x7d\x96\x80\xbd\xab\x09\x76\x75\x87\x1a\x29\xfe\xa5\xea\x50\x4f\xb8\xa6\x3f\x0a\x9f\x31\x5c\xc7\x6b\x53\x07\xc8\xe4\xf3\x3f\x15\xef\x65\x48\xef\xa2\x99\x1c\x79\x49\x77\x79\xe2\xb3\x69\x68\x2b\xda\xaf\x7e\x31\xcd\x1a\xbd\x60\x6a\xef\x71\x43\x06\x74\x4e\x4f\x8b\xae\x8e\x5d\x30\x35\x63\xec\xd0\x81\x9d\x7a\xa4\xc5\x79\x67\x96\xc1\x31\x85\xf5\x23\x14\x2f\xaa\x6d\x42\x8f\x2a\x1e\x53\x23\xee\x7e\x70\x45\x27\xb6\x53\x66\xcf\xc5\x8f\x26\xb1\x9d\x7a\xf4\x82\x29\x1d\x17\x3f\x6d\x2f\x7c\x36\x5b\x3a\x8f\xdd\x6a\x89\x03\x6d\x40\x2a\xc8\xc6\x31\x00\xfc\x23\x07\xfc\xbb\x0e\x84\x31\x5e\x65\x34\x82\xe2\x92\x4f\x78\x0b\x81\x7f\x47\xe3\x5d\x13\xbc\x70\x1e\xff\xd2\xc3\x43\xb9\x22\xf0\x6c\xf1\xd1\x04\xf4\x3d\xfa\x74\x1d\x8c\x22\xcb\xd4\x80\x03\x93\xf9\x57\x3a\x5e\x21\x93\x45\xe4\xb4\xc0\xb7\x4f\xe0\x3b\x0f\x0c\x6d\x19\xe3\x66\x3b\xe7\x56\x0c\xc0\x2c\x71\xfd\x0e\x37\x8a\xbf\x8b\x7c\x2c\x6a\xf1\xda\x7e\xd0\xa0\x01\xc2\xaf\x00\x00\x9a\x1f\x13\xe6\x9a\x30\x26\x03\xc1\xc8\x08\x47\x45\x15\xa4\x21\x8f\x90\x32\x78\x23\xc2\x41\x92\x64\x9a\x29\x8e\x16\xec\x25\x09\x17\x6e\xbc\x24\xa1\xfc\xb4\x38\x70\xcf\xca\xe2\x69\xe6\x0a\x5f\x23\xcc\x78\xe4\x54\x97\x1e\x21\x46\x86\x55\x5e\x79\x98\x73\x3f\x49\x79\xf3\xa2\xd6\x7d\xab\x90\x8f\xa1\x66\x59\x7d\xe9\xa2\x7c\x49\x46\xcd\xe2\x69\x65\xff\x03\x45\xc6\xf4\x3c\x95\x2b\x6f\x5c\xe6\x08\xdc\xb4\x94\x0f\xf1\x36\x24\x0c\x1f\xd2\x75\x4c\x48\x3e\x94\xb7\x33\x6a\x3e\x3a\x9b\xf0\xa1\x9a\xf9\xf2\xcd\x8c\x8e\x8f\x13\x22\x0d\xac\x04\xc4\x88\x8f\x40\xb9\xa8\x22\xb1\xca\x7b\x22\xfe\x1e\x6a\x8f\xa5\x12\xc7\xfd\x75\x92\xa2\x3f\x28\xd6\x65\x25\x45\x83\x43\x2a\x9f\x0f\x8d\x81\x0e\x74\x11\xdd\x5c\xe5\x16\x56\x9e\xbb\xc4\xe7\x43\xaf\x5d\x6d\x6c\x0a\xdc\x91\xb6\xba\xfe\x4b\xf8\x01\x51\xfe\x8c\x0d\xd9\xa9\x03\x0c\x0b\x6c\xc2\xdd\xaa\xae\xf2\x8e\x3a\xf1\x5a\xde\x06\xab\xab\xed\x88\x99\xd7\x49\x42\xd7\x72\x06\xb6\x50\x60\x47\x99\x78\x4d\xac\x12\x57\xbd\xa2\x8c\x33\x8d\x64\x94\xb6\x47\x46\x32\xb6\xe1\x4f\x4c\x34\x12\xe2\x35\x91\xff\x34\x16\x4f\x94\xcd\x1e\xb1\x6c\xd2\x82\xc3\x58\x36\x3b\xee\x32\xa4\x64\x62\xcc\x12\x7f\x5e\x3a\xc2\x32\x13\xbf\x39\x93\xa2\x88\xdc\xe1\x16\xb6\x72\x49\x6d\xc5\x02\x6a\x0f\xec\x01\x93\x9f\x79\x1c\xee\x43\xbb\xd1\xcb\xaf\xcc\x78\x6e\xed\xfa\xcd\x15\x62\x68\xd6\xc5\xcb\x2b\x4e\xe5\x05\x56\xe2\xd7\x51\x33\xa7\xcf\x99\x5d\x2e\x46\x67\xe0\xb5\x1f\xb9\x94\xb1\x83\x76\xfc\xb9\x9d\x26\x75\x5d\xe2\x70\x87\x2a\x6f\x7d\x9e\xb0\xec\x93\x72\xd6\x03\x27\xe5\x75\x39\x1f\x6f\x31\x02\xdf\x07\xfe\x02\xec\xa3\x85\x35\xa0\x0e\xbb\x18\x7d\x81\xf7\xe3\x38\xf7\x3e\x8a\xaf\xcc\x2f\xed\x86\x35\x42\x08\x9b\x73\x95\x04\xe2\x3e\x5d\x25\x83\x10\x2b\x46\x8f\x60\x10\x9e\xbf\x1d\x85\x33\x47\x19\xbd\x15\xef\xbb\xc3\x4a\xb0\x97\xa8\x43\x8c\xa9\x18\x4c\x46\x43\x43\x80\x50\x8a\x02\x48\x5e\x16\x7a\x2f\x96\xa5\x73\x28\x69\xa0\x97\x75\x18\x4a\xf4\x57\xa2\xce\x50\x2a\xea\x62\x43\x83\x1c\x2b\xc2\x8f\x0b\x27\x9b\x46\x32\x8b\x14\x0b\x86\x67\x8a\x5a\xa0\x0a\xce\x3a\x57\x08\x4a\xa5\x94\x65\x6d\x03\xb5\x96\x93\x04\xef\xdf\xbf\x41\x2f\xe1\xf1\x20\x81\x5d\x3c\x33\xd0\x80\x77\x70\xed\xbc\xa5\xc2\xbd\xb6\x01\xde\xab\x19\x05\x6e\x6c\x2b\x82\x8d\x94\xd3\x32\x13\xb8\x41\x6f\x00\x7c\x62\xb6\x25\xae\x6c\xe0\xed\xd3\x4d\x99\xa5\x9c\x0c\x9d\xc2\x13\x32\x12\x69\x15\x1b\xcf\x4c\x9c\x39\xaf\xf7\xd4\xf5\x4f\x3e\x39\x1e\x5a\xbe\x5a\x7c\x76\xd1\x8c\xaa\xe7\x47\x95\x57\xa4\xdd\xf5\xc2\x99\xad\xe8\x2a\xfa\x7a\x25\x56\xe0\x21\xb0\x4b\x51\x6e\xf1\xd8\x8c\xc1\x83\x86\xe4\x2f\xd9\x36\xeb\xa3\x7f\xe6\x66\xff\xd0\x3b\xad\xa4\x28\x7d\x60\xde\xa8\xe9\xc7\xd7\x9f\xf8\x37\x73\x4d\xda\xc7\x4c\x09\x36\x92\x7b\x19\x3b\x48\x05\xbd\x0c\xab\x31\xe8\xea\x2f\xc8\x91\x3e\xea\x42\x0c\x62\x89\x2b\xa1\xfe\x42\x13\x7f\xf5\xa6\xa9\xc2\x20\x54\xb7\x12\x6b\x2f\x10\x2f\x48\x38\x2a\x50\x09\xe5\xa4\x4f\xff\x1f\xf1\x32\x07\x2b\x56\x58\x5e\x50\xb3\xb4\x57\x9a\x82\x4a\x70\x8d\x8a\x5f\x9b\x97\xaf\x31\x92\x30\xbc\xf8\x49\x69\xfe\x70\xfa\x92\x6a\xa9\x04\x6e\xbe\x86\x5e\x84\xcc\x28\x97\x7b\xb4\xe4\x8a\xc3\xd2\xd4\x4e\x5a\xae\xb6\xed\x34\xf4\x41\x38\xa2\xa0\x61\x68\x78\x5d\xba\x28\x1c\x41\x57\x24\x75\x99\xfe\x9a\x63\xe4\xbb\x59\x62\x6c\x1c\x79\x84\x61\xf1\x2a\xb5\x7f\xa4\x0c\x1a\x81\x0e\x4d\xe7\x40\x3d\xe2\x70\x3a\xb7\xde\x10\x2f\x9e\x97\x51\x3e\xe0\x06\x5e\x50\x18\x39\xcf\x5e\x0f\xae\x06\xe7\x60\x2c\x6c\x2f\xa8\x28\x2b\x9a\x16\x96\xeb\xe2\x8d\xcb\x66\x4e\x5b\xbe\x71\x5b\x09\x6a\x72\x4d\x7d\x5c\x14\x23\x2c\xdd\x96\x87\x92\xc6\xcf\x79\xa0\x34\x69\xcf\xca\xdc\x47\xae\x48\x2b\x67\x52\x98\xc7\xd7\x40\x2a\xf0\x80\xfc\x08\xf9\x36\x05\x1f\x9a\xf3\x14\x43\xe4\x61\x68\x27\xbb\x1a\xe3\xc6\xf3\x5e\xb0\x87\x79\x2d\x9f\xf9\x2d\x35\x01\x1d\x23\x33\x90\xbc\x21\x88\x52\xf8\x7e\x6c\x0f\x04\x3b\xe9\x6b\xa1\x45\x68\x91\x69\x68\x17\x89\xe1\xe4\x0d\x84\x25\x53\x3e\x33\x4c\x07\x80\x5a\x66\x99\x09\x2c\xc2\x0b\x31\xc2\x0d\xb4\x18\x19\x41\x8d\x47\x95\xe8\x4f\x71\xfc\xfa\xe6\x00\x24\x10\x6a\x1e\x43\x1d\x20\x3a\x4b\xf6\x37\x2b\xd8\x48\xfa\x2c\x31\x62\x9c\x85\x58\x69\x4e\x59\x3b\x41\x12\x43\xac\x29\x27\x96\x12\xec\x23\x84\x59\xe0\xe2\x71\x81\x6b\x42\xad\x36\x22\x89\xf0\x2b\xf0\xa1\x12\x6a\x19\x7d\x30\x2c\xbe\xd2\x12\x05\xbe\x26\x8f\x64\x8f\xb3\x50\x09\xae\x81\xd8\x1a\x7c\x9b\x78\x9b\xab\xc3\xd7\x3c\x5f\x3e\x83\x4c\x47\x2f\x09\xf8\x62\x15\xf8\x58\x07\x2b\x40\x7b\x1b\x1f\x5d\xc9\xc8\x3e\x10\xee\x70\xb2\xd0\x4b\xe4\x50\x8c\xab\x83\x19\x2e\xae\x15\x2d\xa4\xae\x5c\x73\x06\x88\x9a\x1b\x30\x96\x59\x02\x16\x87\x8c\x45\x7d\xfb\x20\xa0\x42\x9a\xb3\x28\x09\xdf\xcf\x9f\xa9\xef\x20\x40\x16\x9a\x45\x3e\x8f\x71\xba\x4c\x71\xaa\x7a\xd0\x22\x5e\xa7\xea\xc9\x00\x7a\xb4\xa2\x47\x12\xec\x43\x8b\xe9\x0a\x21\x36\xa0\x87\xa6\x7e\x05\xff\xfc\x2a\x34\x39\x66\xd9\x07\xbd\xbf\xfb\xfd\xd6\xa7\xa0\xb7\x16\x7d\xf7\x2e\xfa\x12\x7d\x02\x49\x7d\x8c\x02\x11\x45\xee\xf3\xaf\x78\x75\xfb\x1f\xf6\x90\xd5\xfe\xe2\x9d\x3f\x3d\x0e\xd9\xc0\xd7\xfa\x18\x05\x12\x6c\x43\x8b\xa9\x9d\xf8\x2d\x68\xa1\x9a\x96\x02\x87\x98\xc1\x62\x33\x41\x22\x55\xd4\xf8\x5a\x28\xa4\xb1\x4f\x0f\x44\x59\x5b\xa3\x79\xe7\xfa\xe2\x89\x0d\xa8\xaf\x51\xac\xc4\x3e\x34\x49\xe0\xc3\x98\x0d\xe3\x63\x1b\x1d\x17\xef\x99\x5c\x94\x1b\xf1\x31\x46\x13\x78\xc7\xd7\x74\x46\x93\x04\x3e\x4c\xd9\x30\x44\xa2\xe3\x62\x86\x09\x12\x3d\x21\x81\x6d\x3a\x20\x1c\x1f\xb3\x04\x3e\xba\x18\xf3\xa1\x52\x46\x1d\x0f\x75\x2a\x6d\x34\x92\xbe\x4a\x39\x01\x38\xb9\x67\x09\x72\x6b\xab\xa9\x48\x72\xab\x7a\xd4\xc9\x3b\x41\x7d\x4b\xa7\x97\xf2\x98\x5a\xff\x83\x8d\x74\x45\x54\x05\x1e\x6f\x4f\x0b\x46\x5c\x3a\x48\xd0\x89\x7c\x3b\xdc\x21\xaf\x9e\x04\xba\x93\xf9\xf1\x2e\x37\x37\x82\x8d\xd4\x4e\x1c\x6f\xdb\x13\x57\x91\x8a\x5c\x1b\x24\x94\x3a\x9a\x76\x85\x41\xa9\x27\x8e\x6a\x1f\xea\x0c\x9a\xe7\xd1\x87\xe3\xf6\xbb\xe2\xb5\xb8\x81\x25\xc1\x97\xc6\x91\x5a\x13\x86\xa8\x0b\x4c\x33\x38\x97\x35\xa0\x2f\xf9\xfd\xf7\xe1\x7a\xed\x29\x2c\xc5\xf3\xc6\x5c\xc3\x77\x1f\xdd\x70\x2d\x32\x43\xe6\x42\xa0\xd2\xd1\xb6\xdf\x18\x94\x01\x5b\x1d\x8d\x30\x11\xdc\x80\xd2\x1e\xcb\x34\x3e\x86\xd7\xca\x42\xfc\x42\x2a\x4e\x19\x34\x1c\x40\x98\x07\x6d\xce\x6c\x26\xb6\x00\x3a\x60\x1e\x6a\x8b\xf6\xdd\x32\x0d\xe4\xf5\x6f\x1b\x7b\xa6\xfb\x94\x2f\xc9\x99\x4d\xa3\x98\x74\xcd\x4c\xc6\xfd\x52\xeb\x98\x78\xb1\x5f\xa9\x20\x9d\x59\xbf\xf9\x7f\x67\x63\xa2\x18\xf7\x05\x98\x8f\xca\xd0\xc9\x80\x49\xaf\x54\x45\x60\xe5\xec\xea\x45\x4b\x88\xea\xe6\x9d\xd4\x05\x23\x3b\x06\x50\x09\xed\x11\xe3\x03\x95\xf2\x4a\xab\x00\x9d\x88\x94\x70\x64\xa1\x10\x48\x8e\x81\x00\xa8\x04\xd7\xe4\x13\xda\x53\xc8\x21\xb5\xa7\x86\x1e\x25\x5c\xb7\xc9\x40\xa5\x18\x11\x00\x80\xe5\x88\xa5\x12\x74\xc6\xd5\x69\x59\xfc\x4a\xad\xcf\xc6\x8a\xaf\xdd\x72\x8d\xa6\x11\xf8\x95\x52\x56\x48\x84\xee\x05\x61\xf6\xbb\xd9\x89\x4c\x86\xed\x3c\x4c\x3d\x1f\xdf\x23\x36\xa6\x67\xc2\x61\x98\x8d\xd6\xa2\x3f\x9c\x88\xf5\x52\x4c\xef\x36\xc7\xd1\x8e\x06\x58\x96\xbf\xf7\x4f\xf9\x3f\xd1\x07\xfd\xff\x7b\x79\x67\xde\xf7\x45\xa4\xc7\x7f\xc6\xf7\xbf\x13\x8a\x6f\x8c\x20\x93\x9b\x46\x91\x20\x1d\xc2\x9e\xb9\xdf\x7b\x02\x84\xa5\xc2\xf1\xc0\x27\x49\x3d\x8f\x03\x82\x93\x86\x39\xce\xb0\xc2\x8b\x97\xac\x2d\xd1\xe6\xc9\xcd\x87\x3c\x18\x8f\x80\x26\x16\xba\x14\x48\xec\xb0\xf7\x8a\x44\x77\x14\x95\xd2\xee\x69\x38\x7e\x65\x9c\x8b\x88\x8a\xed\x1e\xff\x24\xcc\x40\x47\xd1\x81\xb2\xc5\xd1\x9f\xa2\x43\x2b\x04\x20\x54\x05\xb2\x96\xa3\x1b\x63\x5e\x99\x48\xb4\x0f\x7c\xe5\x3b\xdf\x6f\xd2\x55\x0f\xfc\xbe\x79\x27\x5c\x0d\xbf\xf3\xaf\x61\xe2\x04\x10\xfc\x78\x45\xce\x89\x14\x45\x10\x01\x27\xb0\x56\x0a\x68\x08\x47\x8a\x1c\xd1\x04\x5a\xc2\x8b\x84\x26\x3c\x2f\xb0\x42\x0a\x6d\x08\x45\x8c\x22\xb8\x81\x14\x78\x29\x03\x9d\x41\x3a\x67\x83\xc3\x30\x63\x62\x4e\x22\x21\xca\x6a\x14\x6a\x1a\x96\x33\x83\x00\x54\x52\xe0\x8e\xc2\xf7\x22\x9e\x30\x5a\x65\x82\x38\x3c\x99\xc7\xf4\x78\x43\xd3\x4a\x57\x1b\xad\xbb\x78\x7e\x67\x46\xa4\x77\xd2\x4c\x8f\x80\xce\x8f\x84\x23\xe8\xb0\x0c\x2a\x62\x4b\x78\xde\xec\x11\xe8\x9c\x88\x24\x02\x9d\x5b\x2c\x9c\x59\x87\xa4\x46\x8e\x5b\x00\xa8\xc4\x72\x84\x3e\xf8\x7f\xc1\x07\x6f\x5c\xc3\xf0\xa1\x8c\xfb\xb0\xa3\x12\xe6\x38\x7e\x1b\xf9\x57\xe4\xa3\x52\xb0\xcb\xa1\xf8\x50\xc4\x44\x70\x7e\xb3\x4c\x8c\x87\xcf\x8e\xc6\xe1\x77\xf8\x7f\xb2\x1f\xb9\x86\xfa\xc1\x32\xd8\x1f\x7a\x61\x31\xf2\xc2\xef\xd0\x76\xb4\x17\xed\x3d\x84\x69\x27\x6e\x11\x1f\x07\x6e\x11\xf1\x81\x8c\x40\x0a\x91\x1e\xb8\x20\x8e\x36\x01\x62\x00\xa0\x36\x33\x76\x21\x7e\x9d\xaf\xa8\x1a\xcd\x89\x23\xb5\xab\xaa\xa6\x0a\xab\xd1\x2b\xdf\x34\x0e\xe3\x1b\x95\x8a\xa9\x06\x8e\xc3\x1a\xb4\x42\x18\x3d\x52\xc0\x2a\xc5\x9a\xab\xd1\x9a\x58\x06\x43\xf0\x51\x06\x1b\x2a\xad\x24\xba\x99\x4f\x0a\x32\x51\x52\xac\xbb\x2c\x15\x61\xd2\xbd\x81\x8c\x73\x0c\xfa\xd6\x0a\xac\x9b\xc9\xfc\x3a\x03\xe1\x3c\x5e\x2b\xa7\xb7\xd1\x90\x85\xca\x03\x04\x38\x1e\x66\xc1\x6c\x58\x8c\x92\xd0\xa7\x71\x62\xd6\x42\x1d\x31\xd9\xbf\x32\x70\x92\xc8\xa2\x76\x2a\xf4\xdf\x4e\xad\x63\xec\xfc\x0d\x8e\xc2\xcf\xe3\x0a\x87\xb8\x08\x50\x3e\x94\x5b\x2d\x6e\x48\x8a\x61\x62\xbb\x9c\x85\xc3\x91\xbb\xf0\x87\x97\xc6\x8d\xf1\x15\x4e\x58\xd6\x35\x21\x49\x98\x73\x81\x35\x25\x0b\x67\xdd\x43\x54\x35\xdb\xfe\xb8\xcf\x7a\xab\xcd\xfd\x33\x7c\xf4\x52\x21\x3f\x22\x1b\x00\x6a\x91\xa5\x12\x44\xe3\xf8\x53\x2f\x64\xad\xb8\xca\x0c\xf6\x26\xd2\x2e\x23\x9b\x78\x2f\x50\x46\x75\x0c\x0c\x21\xce\xfa\x33\x95\xfb\x8b\x53\xe4\xb7\x10\x7c\xe2\x4f\x08\x02\x26\x23\x49\xb1\xaf\x20\x80\x0f\x00\xf2\x0d\x86\x95\xdb\xe5\xab\xdd\xa8\xdb\x55\xd4\xd3\xf5\xef\x54\xb6\x2b\x54\xd5\xbd\x41\x5d\x4c\xd2\x9c\x0f\x64\xa3\x12\x6a\x11\xae\xa1\x93\xa0\xc2\x2b\x52\xa1\x80\x1a\xc8\xc3\x53\x4c\xc6\xa8\x9c\xd3\x3e\x54\x22\xbc\x9f\x9f\xa0\xc2\x27\xb6\xa3\x80\x16\xd8\x85\xdb\x11\x31\xc9\x6b\xb1\x6c\xf4\x92\x80\xa5\x8d\x12\x0b\xcd\x3a\x58\x25\x63\xcf\x10\x75\x81\xc9\x32\x8a\xb5\x0d\x7c\xff\x2f\x09\xfd\xb7\x51\xf6\xcf\x7d\x57\xc9\xca\x8f\xdc\x77\xc5\x9e\x95\xf1\xb8\x7c\x4c\x7e\x07\xd3\x98\x7c\x3e\x2c\x57\x19\x8a\x5f\xc3\x87\xe4\xea\x22\xf0\xd7\xe2\x9c\x1f\x7c\xae\xc6\x34\x89\xb9\x1a\x26\x27\x2f\x26\xd3\x47\x7b\x06\xf3\xa4\x7e\xee\x18\x9c\xba\x35\x99\xfb\xec\xfa\x48\x7c\x36\x34\x79\x25\x32\x02\xe3\xcb\x8a\x45\x3d\xb6\x8a\xd5\x3c\xc2\x38\xa6\xe3\x42\x61\x8f\xf9\x52\x39\x0f\xfe\x7d\x07\x6a\x1d\x53\x2f\xee\xf8\x4c\x67\xa9\x31\x4c\xb3\x49\xbb\xc0\x00\x9b\xc1\x04\x7e\x4f\x8b\x88\x04\x65\xc1\x46\xaa\x3f\x53\x85\xb3\x70\x8d\x2a\x4f\xeb\x6b\x4d\xdb\xbc\x3c\x1a\x2f\x06\x68\x58\xff\x44\x28\x38\xfd\x2c\x07\x65\xfe\xb3\xcf\x1a\x54\x3d\x11\xcb\x4d\x13\x3f\xad\xf3\x64\x66\x7a\x9e\x79\x62\xf6\xbc\xc7\xc5\xb8\x46\x32\xdf\xb2\x5e\x8c\x97\x97\xcb\x9c\x2a\xee\xb5\x8f\x9c\xd9\xfe\xc8\xf0\x29\x63\x6a\xaa\x78\x53\xb5\x1f\xe7\xbf\x3d\xd5\x3c\x85\x69\x12\xd7\x23\x10\xef\xad\x2f\xd3\xa7\x81\x0b\x94\x14\x64\xb4\x73\xb9\x40\x54\x47\x4b\xa7\x58\xa7\xb3\x53\x47\x40\x75\x4b\x8d\xb2\x50\x49\x51\x51\x1d\x1e\x9a\x14\x15\x45\x81\x04\x2a\x65\xce\x24\x8a\x8a\xb7\x3f\x38\x29\xde\xc6\xd7\x24\xe7\x7e\x12\xf2\xb2\x32\xac\xc0\x93\x90\x27\x97\x26\x17\xdf\x94\xf4\x58\xdb\x01\x36\x87\xe2\x8b\x96\x52\x6c\x57\xb7\x78\xb2\xcf\xba\xbc\x3e\xfe\x40\xdf\xba\x0f\xe6\xc3\xa4\x1f\x60\x76\xf7\xab\x07\x0e\xa3\x1b\x28\x70\xf9\xc5\xf1\xfb\x8b\x57\xad\x41\x67\xcb\xaf\x77\xfd\xed\xb4\xad\x4f\x91\xdb\x61\x14\x4c\xfd\xeb\xc7\x5f\x74\x3d\xff\xea\xdf\x6f\x8e\x86\x4c\xef\x9e\xf3\xe6\x9e\xba\xf0\xdd\xd0\x01\x3b\xf6\xf8\x57\x0a\xba\x52\x22\xd4\xc9\x69\x03\x12\x15\x55\x72\xf8\xca\x38\x22\x1d\xca\xb2\x38\x87\xf8\x6a\x38\xab\xf8\x05\x8b\x50\x0a\x87\x98\xc6\x57\xc0\x79\x46\x88\x4b\x07\x65\xa8\x44\xa8\x7f\xd3\x15\xbf\x7e\x16\xc1\x98\x8b\x9d\x85\x1a\x6e\x2b\xee\x35\xc4\x60\x07\x0a\xe5\xdc\x32\xce\xdf\xaf\xb2\xdc\x06\x16\x90\x04\x58\x85\x6c\x5e\xa1\xbc\x58\x5b\xe8\x72\x0b\xef\xca\x91\x58\x5e\xa5\x98\xfb\x92\xe7\xa4\xaf\x5d\xb3\x33\x66\x9f\x73\x74\x6e\x8f\xae\x85\x05\xbc\xd4\xa2\xbc\x16\xdf\xee\x98\x36\x0b\x66\xbe\x98\x3e\xfc\xb9\x38\x4f\x6a\x97\xae\xcd\x09\x58\x7e\xbe\x5f\x5e\xdf\x77\x61\xd9\x73\x23\xd4\x77\x3d\xa4\x50\x34\x38\xd4\xe0\x42\xf0\x41\xe5\xab\x81\x02\x40\x09\xbc\x9c\xc3\xe7\xe3\x49\x78\x25\x24\x30\x63\x55\x79\x41\x5e\x07\xa0\x50\xd5\x49\xc9\xcd\xc2\x59\xb0\xbf\x77\x75\xa7\x9d\x0b\xef\x5f\x7c\x5f\x22\x4f\x0c\x1c\x38\xd1\xfb\xc3\xe0\x1d\x22\x3f\x4c\x46\xd2\xe3\x9b\x8b\x5f\x4b\x49\x1a\x7d\xcf\x03\x85\x7e\x2f\x26\x87\xd8\xd4\xf1\x9e\xf9\x8e\x49\x55\xf8\x5c\x8a\xe3\x08\x31\x35\xa0\x3d\xae\x46\xdf\x37\x04\x4b\x36\x15\x28\x52\xe2\x4c\x04\x66\xc4\xd3\x8b\x4a\x84\xb4\x50\x9a\xfe\x27\x8c\xd0\x80\x2b\xca\xab\x04\x5b\x29\x30\x47\xde\x96\xe0\xaa\x38\x6b\x0b\x3a\x2b\x39\x83\x5e\x0f\x2e\x78\x65\x33\xe0\x4e\xc9\x19\xba\x7c\x2b\xf7\xae\x2d\xbb\xae\x2e\x9c\x05\x07\x64\xff\xa6\xfb\xce\xfb\x16\xcf\x9d\x93\xa8\x51\xaa\x23\x8e\x85\x93\x3a\x2e\x45\x27\x92\x1e\xdf\x3c\x62\x57\xcf\xa4\xc2\x07\xa6\x0d\x13\xb8\xc3\x79\x51\x0d\x58\xaf\x6a\x80\x05\x74\x01\xbd\x38\xce\x48\xb1\xef\x96\x72\x97\x89\xb1\x0c\x36\x60\x6e\x87\x12\x5f\x34\xcf\x1c\x33\x17\xe3\x6a\xee\x6f\xcc\x9c\x04\xb5\x52\xaa\xef\x2f\xf0\x15\x35\x4a\xd0\xb1\x5e\x61\x75\x4c\xab\xfd\xe1\xd4\xcd\x93\x38\xac\x62\x51\x35\x53\x13\xe3\x2b\x4a\xcd\x70\x85\x52\x3b\xf2\xa1\x1a\x66\xc4\xf8\xc5\x1d\x06\x2e\x21\x52\x3a\x3b\x92\x05\xdd\xdb\xcd\xdc\x11\x74\x6f\x70\xeb\x74\x2f\x92\xe9\xba\x43\x89\x5c\x20\x13\x7e\xa7\x42\x1e\xb1\x3a\x52\x67\xd4\x62\x48\x1c\x2f\xc0\x1c\x67\x72\xab\x12\x63\x8e\x4d\xf2\x07\x75\x1a\xba\xa7\x08\x26\xf4\xfe\xed\x80\x67\xd6\x4d\xbe\x6b\xd3\xca\xd8\xca\x69\xd9\x13\x86\x0f\x4c\xee\x91\x1e\x53\x1d\xbf\x78\x5a\xcf\xf1\xc3\xf3\x3b\xf5\xec\xde\x26\x5b\xad\xb1\x4c\x46\xd2\xae\x69\x43\x9f\xe8\x9f\x34\x7c\xc2\xa8\x62\x58\x3e\xff\x37\x9d\xd8\xa4\x9e\x3d\x2b\x97\x25\xb1\x9d\xd2\xb3\x9a\x2e\x4b\x36\x91\xe7\xbc\xbf\xa5\x33\xe6\x7c\x10\x18\x11\x39\xe7\xc6\xe0\x0d\x5f\xa5\x90\x68\x8f\x44\x92\x04\xa3\x07\x2b\x44\xfe\xcd\x85\x6a\x4e\x12\x95\x9c\xe2\x7d\xa7\xa5\x52\xd0\xf1\x6e\x12\xff\xb1\xd0\x40\xc7\x0d\x7d\xe9\x00\xe5\xe6\x22\xdd\xc8\xb1\xaa\xf6\x2f\x82\x46\x8b\x5e\x16\xf3\xca\xf9\x59\xa6\x8b\xa0\xcb\x79\x11\xf3\x6a\x8b\xcc\xef\xde\xab\x04\xd8\x96\xa7\xac\xb3\x99\x0f\xa6\xfa\x28\xb1\x2e\xd1\x78\x64\x51\x5f\x6d\x7a\xbf\x63\x13\x0a\x34\x0a\xb5\x17\x78\xbe\x0c\xfc\x4e\xdc\xe6\xa8\xca\xf2\xf2\xc5\xd1\xcf\xc7\x1e\xdb\xf1\xca\xe1\x5d\x3c\x5f\x45\xc3\xb2\x2e\x4f\xa9\x94\x6c\x68\xf5\xdd\x77\x55\x8c\xd9\x7e\x60\x6f\xf3\x53\xbc\xd3\xf9\x5b\xd2\x9c\x69\x8e\xf9\xf7\x49\x3a\xc8\x7c\x18\x89\xcf\x51\x03\x52\xf8\x69\x73\x9f\xb3\x5b\x05\xee\x29\x9e\xab\x2a\x0c\xce\x80\x2b\x7a\xb5\x88\xf3\xa4\x38\xc1\x7d\x22\x52\x2d\x57\x9d\x43\x70\x25\x78\x00\xfd\xfa\x25\x46\x05\xa7\xea\x72\xd6\xb0\x95\x73\xfb\x68\xfc\x8d\xc8\x15\x74\x3b\xa6\xcd\x49\x9a\xd8\xf4\xb9\xe4\x6b\x54\x5c\xf5\x6a\x09\x57\x22\xa0\x90\x33\xb4\xce\x00\xdc\x38\xd3\x09\x29\x71\x25\xe0\x6c\xee\xa8\x98\x83\x98\xa7\x72\xbd\x9f\x31\xd1\x29\x7e\xcb\x23\xda\x6d\xf5\x6c\x54\x53\x56\xc7\x93\x35\x2d\x71\x58\xd9\x8c\x9c\x5c\xe6\xc1\x18\x8f\xbb\xbf\xd7\x4c\xcd\xc8\xda\xd9\xcc\xe0\x21\x7d\x0a\x13\xd2\xe7\x47\xb7\xef\x90\xae\xb4\x79\x4c\x24\x7e\xc6\x5c\xdf\xb4\x80\x23\x56\xbd\x49\x2a\xe0\x91\xa9\xe0\x2d\x8d\x14\x4a\x1f\x63\x07\x3d\x41\x8e\x96\x5f\x01\xb1\x3b\x42\x17\x13\xb3\xcd\x32\x77\xfa\xf1\xf8\x4d\xd1\x87\x5e\x79\xf9\x43\x52\x61\x99\x1f\x8b\x5d\x3c\x3d\x73\x1c\x6f\x99\xd3\x35\x5a\x5a\xda\x7f\xd8\x8a\x0d\x5b\xfe\xf0\x8e\x60\x88\x17\x3e\xa6\xf6\x2e\x4a\xdf\x92\x0a\x06\x82\xe1\x61\x79\x0e\x0d\x3a\xa4\xe2\xee\x8e\x44\x80\x38\x73\x4d\xae\x30\x94\x45\x76\x2a\xfc\xdc\xc7\x7e\xa5\xda\xc0\xaf\xa8\x4a\xd4\x98\xbb\x15\x87\xaa\xba\xc1\x71\x23\xbf\x22\x55\xcc\x69\xae\x31\xf1\x29\x19\x91\xf8\x14\x15\xa0\xc8\x5c\xca\xef\x54\xe0\x5e\xe5\xb9\xb2\x99\xf9\x14\x7a\xb5\x88\xf3\x3d\x8d\x3f\xe1\xf3\xb5\x09\x45\x8d\x13\xb9\xc2\x90\x5c\x1d\x47\x2e\xa4\x55\x2f\xd6\xec\x13\x0b\x2b\x89\x39\xd4\xb8\x56\x1f\x5f\x4f\x89\x3f\x49\x37\xaa\x0e\x24\x56\xcc\x92\x42\xd1\x0c\xcb\x00\x49\x0f\x2d\x25\xf2\xb5\xfa\xf4\x05\x7f\xf0\x33\x4b\xcd\x9f\xc8\x39\x85\x00\x50\x84\xe5\x36\x88\x15\x22\xe2\x25\x19\x80\x45\xbf\x27\x54\x8a\xf3\xe5\x28\xd5\x1e\x50\x51\x0b\xa9\xd8\xa9\xdd\xf2\x09\xb5\x16\xa7\x33\xbb\xb0\x8c\x59\x61\x64\x34\xd8\x8c\x86\x11\xd7\xae\xde\x8f\x9a\xc9\x4d\x9c\xd0\x20\x13\xe5\x9f\xd6\x9a\xda\x59\x47\xc2\xd6\xce\xd2\xdd\xb7\x8b\x3c\xc4\xff\xda\xb5\xb3\xe6\x9b\x60\xc9\x0b\x51\x24\xee\x43\x35\xb8\xc0\x05\x65\x9d\xb8\xff\x58\xce\xe1\x9a\x29\xac\xb6\x4e\x9c\x72\x11\x97\x2a\x2c\x47\x94\xac\x5c\x57\xee\x39\xe0\xf7\xfc\xae\x5c\x51\x36\x4e\xb1\xb7\x38\xa6\xd8\x8f\x4f\x09\x36\xd2\x14\x53\x23\xd4\x53\xcb\x36\xad\x1d\xa7\x5a\x9b\xf3\x8c\x88\x1b\x71\x63\x66\x54\x5b\x71\x42\x2c\x26\x77\x03\xe3\x32\x2c\x25\xa7\x00\xc8\xd7\x94\xab\x96\xf7\xe1\x64\xf0\x0c\xd6\x97\x73\xb8\xae\x33\xab\xd8\x01\x9b\x72\xe4\xc1\x5b\xdd\xd7\x14\x0c\x7d\xa7\xdc\xe2\x0a\x7b\xee\x3b\x2f\x68\x38\x12\x37\xb5\xdc\xbe\xfb\x0b\xac\x33\xdc\xbe\xbb\x13\xe8\x81\x5f\xb5\x16\x7b\x8d\x98\x23\x16\xa3\x18\x68\xc8\x50\x9d\x12\x4f\x9c\xc0\x90\xb0\xe7\xf6\xdb\x8d\x19\x12\xe1\x61\x86\x44\x9d\x79\x21\x6a\x94\x61\xbd\x35\x15\x20\x83\xad\xab\xb9\xfa\x5c\x53\xef\xb2\x8d\xd5\x08\x6e\xd3\xec\x4c\xc5\x7c\xb7\x3d\xcc\x1d\x41\x9f\x4c\x6b\xae\xa9\xa0\x25\x58\x30\x59\x06\x08\x23\x50\x2d\x26\x8a\x67\x0e\x2e\x52\x61\x0e\xa7\x62\x68\xd8\xa2\x45\xcb\x89\x8b\x1a\x09\xc4\x5a\x8d\x0b\x30\x9f\xd9\xa1\xf8\x34\xde\xa0\x2a\x29\xfd\x26\x92\xed\xa8\x8a\x5b\xf3\xed\xa7\xa2\xce\x63\x67\xcc\x6d\x3f\x50\x18\xd9\x5c\x6d\xb9\x4d\x8b\x68\x1b\xed\x08\x55\x05\x33\x84\x20\xfe\x6a\x4e\x71\x49\xf0\x1a\x2a\xa1\xda\x59\x2a\x71\x8d\xc8\xae\x40\x0b\xda\xc8\xa7\xbf\xa6\xdc\x92\x1e\xd5\x39\x78\xd5\x86\xf9\xe7\xf3\x7a\x7f\x4f\x81\x29\xa8\x94\x9a\xce\xb0\x82\x6e\xe6\x44\xc4\x9f\x2d\x22\xff\xaf\x0a\x72\xec\x12\x6e\x2d\x40\x1e\x53\x40\xc5\x33\xb9\xf9\x4f\xe2\xda\xa6\x08\x00\xe2\x92\xb4\x2e\x50\xd4\x5f\x32\x5a\x17\x14\x09\x55\x97\x72\xd5\x6b\x02\x55\xa5\x25\xdd\xaa\x80\x00\x55\x00\x10\x03\x98\x5d\xc0\x06\x9c\x1c\xf3\x06\xa7\xe2\x56\xd6\x5a\xa5\x76\xed\x29\x30\x9b\xbe\xa6\x6e\xa9\x89\xc2\x55\xa4\x08\x50\x84\x4a\x88\x4b\xd2\x7a\x4c\x59\x33\x4a\x64\x4d\x04\xca\x07\xaa\x2b\xf1\x29\x6b\xc2\xd5\xa2\x12\xf8\x05\xae\xa7\x63\xe5\xdf\xfc\xd1\xe6\x01\xc8\xa5\x75\x08\xa9\xc0\xd5\x75\x39\xa2\x5f\x2a\x6b\x85\x6b\x80\x97\xd0\xd7\xe9\x33\x38\xff\x37\xd9\x34\xfb\x57\x6c\x38\x44\xe2\x2f\x5f\x7b\xc2\x34\xe3\xb7\xd9\xa1\xae\xfd\xbc\x95\x92\x75\x5a\x95\xe9\xab\x7c\xde\x5e\xa1\x4d\xaa\x24\x5f\xe8\x13\x33\x7c\x0b\xf8\x5e\xb5\xe9\xbd\xfb\x85\xcc\x5e\x7f\x5b\x71\x0d\x8b\xf3\x9c\xb1\xbe\x38\x84\x7a\xa8\x86\x59\xce\xfa\x31\x0e\x21\xb2\xe6\x0a\xc4\x54\x76\xf2\x01\xed\x82\x93\x14\xf2\xec\x77\x61\x0e\x32\x43\x72\x60\xb8\xda\x34\xa1\x83\xd5\x20\x32\xe3\x85\x6c\xa3\x5b\x02\x8b\xb9\xe0\xc2\xba\xca\x85\x6f\xa5\x94\x2c\x69\x8e\x7a\x45\xce\xc4\xd5\x8d\x9e\xa7\xfe\x4a\xf7\xb3\x55\x24\x8d\x58\xcd\x2f\x6d\x34\x64\x51\xef\x28\x0f\x75\xeb\x45\xe6\x3a\x29\xef\x18\xb8\x35\x58\x0c\x53\x03\xda\xe0\x5b\xe6\x2c\x7d\x8e\xb8\x16\xa1\x74\x65\x2b\xad\xc0\x54\xbc\xed\x54\x02\x6c\x23\x55\x1b\xf0\xf3\x00\xf5\x29\xe3\xca\x95\x97\x98\x3b\x4e\x7c\x2c\x22\x54\xf2\xc7\xad\xbd\x34\xfc\xd9\x0c\xef\x41\x64\x1e\x75\xfc\x75\xd2\xdf\x87\xbc\x28\x91\xa8\x61\x8f\x19\x65\x70\x33\x22\x92\x08\xc4\x35\xda\x56\xbc\x46\x73\x00\x17\xc7\x9d\x62\x8d\x16\x11\x87\xe2\x0a\x4d\xc5\xa0\x6a\x69\x66\x15\x19\x14\xd7\x66\xc9\x46\x0c\x4a\x2b\x33\x91\x41\x65\x5d\x86\x51\x82\xee\x69\x6b\x98\x98\xeb\x5e\xf8\xe9\x6a\xa2\x86\xd5\xea\x65\x50\x64\xea\xf8\xa3\xee\x8e\x81\x9b\xc7\xfb\x99\x3b\x82\x4e\xea\x6b\x98\x84\xd2\xc9\x30\xd3\xda\x44\x3d\x6f\xa9\x81\x47\xa6\xa6\xe4\x0b\x06\x6b\x50\x9e\xf3\x05\x02\xe7\xfd\x23\xe3\xdc\x78\xf3\xa7\xa7\xbd\x50\xb9\x3a\x7a\x4a\xa4\x9d\x31\x59\x26\x19\xf0\x2f\xaf\x8d\x64\xfe\xdf\xd0\xac\xf6\xc4\xba\x11\x9d\x31\xff\x7c\x66\x62\x28\xfe\x4d\x4e\xb4\x4c\xab\x6b\xec\x89\x64\x89\xc7\x84\xa8\xba\x11\x6a\x85\x07\xe4\x09\x40\xf1\x7e\xd8\x52\x29\x8c\x45\xcf\x08\xc7\xc2\xdc\x2f\x53\xca\x95\xd6\xd3\xa1\x9d\x34\xf5\x8e\xf2\x5e\xa2\x5e\xe3\xb1\x29\xde\x5f\x33\xac\xa0\xe3\xbd\x43\x73\x6c\x8b\xc0\x7f\xcf\x55\x82\x23\xc2\xf8\x72\xb2\x5c\xb9\x0a\x2c\xd7\x78\x76\xc1\xb7\x33\x17\x2c\x95\xc0\xc6\x47\x9d\x62\xe6\x9c\xb9\x5e\xd6\x19\x0f\x2d\x89\x0e\x9d\x8f\x97\xea\x1d\xcd\x85\x25\x70\x72\xfd\x54\x98\x19\xdf\xed\x99\xe5\x03\xf5\xfe\xfd\x55\xf1\x55\x90\x2f\xe0\x83\x70\xe5\xe9\x81\xe7\x13\xdf\x38\x95\xf3\x87\xbf\xe9\x6a\x99\xc8\x71\xdf\xd8\xaf\xd3\x67\x18\x16\xc7\x16\x65\x88\x4c\xf1\x60\x08\x1e\x8c\xce\xbf\x2b\x6b\x18\x2d\xfc\x64\xf8\x26\x98\xd9\x36\xe9\xee\x67\xe6\xf4\xd1\x79\xf7\x5c\x11\x0f\xa6\x68\xe8\xd0\xcc\x9b\x89\x4f\xfe\xfe\xc1\x8e\xd5\xdb\x34\xde\x9d\x80\x72\x9d\x0f\x99\x9b\x4e\xa6\xdc\x88\x91\xf9\x4a\x67\x64\xc2\x4d\x9e\x10\x9a\xdf\x57\xe1\x89\xf4\xdc\xd0\x8d\x7c\x68\x7e\xf3\x87\xb2\x0b\x52\x71\x93\x62\xce\x8d\x94\x27\xa0\x9b\x96\x06\xdc\x6c\x12\xe0\x54\xa8\xa7\xa0\x9e\x1a\x6a\x0d\x8f\xc8\x3f\x4b\x9a\x74\x22\x37\xb7\xb1\xde\x64\x87\xd7\x1b\xa3\xb5\x61\x38\x15\x3a\xa6\x5b\x22\x86\xd0\x24\x93\x75\x22\x7d\x86\xd9\x85\xf5\x29\x37\x32\x7d\x32\x59\x2f\x86\x54\xad\x4c\xa3\x85\xa3\xb9\x86\x19\xad\x1f\x45\x3e\xa7\x01\x1b\xc8\xc0\xf9\x5e\x46\x7c\x9a\xd6\xf4\x0a\xa3\x78\x2e\x93\x03\xc4\xca\x90\x8a\x48\xbd\xad\x3e\x43\xf4\x1f\x90\x15\x52\xe4\x36\x1e\x24\x0a\x2f\x90\x19\xeb\x63\x64\x3e\xc3\x80\xdd\xd5\x26\x90\x93\xc2\x29\x2b\x59\xa6\x39\xf9\x14\x8b\x90\xf1\xfb\x35\xe6\x02\xae\xad\x13\x89\xad\x93\xfd\x43\x38\x45\x3d\x2b\x7a\x86\x10\xfa\xa9\xd9\xc3\xd1\x67\x68\xa6\x05\x76\x4e\xe5\x0b\x42\x2a\xe3\x10\x85\x23\x30\xd7\x41\xd1\x03\x10\x60\x1f\x2a\x11\x72\x3d\x93\x4c\x32\x81\x85\xae\xf5\xc9\x7a\xfc\x99\x88\x51\x7e\xe7\x3f\xe4\x98\xe3\x6d\xa8\x44\xc8\xed\xec\x6c\x92\x8b\x27\xf5\xa0\x4b\xbc\x83\x15\xfc\xcd\x8d\x3e\x8d\xb7\xbb\x74\xc7\x81\x73\x10\x2d\xb7\x41\x02\x1e\x51\xa3\xfc\x43\xfd\x94\xd6\x8b\xf2\x94\x66\x0a\xeb\x65\x62\x7a\x68\x67\x2d\x21\xe4\x1a\xee\x02\x76\xbe\x52\x93\x91\x6c\x06\xbd\xeb\xc5\xf4\x69\x22\xee\x74\xf2\xd2\x69\xba\xf3\x95\x7d\xc1\x46\x4b\xba\xa5\x12\x74\x02\xa9\xea\xbe\x1d\x83\x20\xaf\x48\x12\x01\x72\xd2\xea\xba\xad\x9c\xd4\xa3\x86\xc1\xcc\xf8\x2e\x0f\x1e\x7c\x5a\x12\xff\x2d\xd1\x39\x72\x72\xcf\x79\xf1\xb9\xe7\xb7\x92\x9b\x8e\x74\xdc\x3c\x37\x71\xdb\xff\xcc\xb2\x07\x3e\x12\x12\x2e\x55\x75\xa1\xb7\x05\x1b\x99\x4a\x86\x05\xc9\xb8\xde\x98\x61\xff\x32\x09\xda\x84\xd4\xe1\xc5\x30\xb3\x6d\x97\x87\xde\x7e\xe6\xeb\xf4\x84\xde\x6f\x72\x14\x4c\x11\x10\x28\x65\xaf\x4a\x7c\x6e\x49\xe2\x8b\xbb\x67\x3a\xfc\x67\xd7\x8f\x2d\x6b\xa0\x3a\x2a\x73\xc4\x22\x96\x5f\xf2\x89\xe6\xf2\xd7\x0b\x9e\x30\x94\xf8\xcc\x04\x31\x63\xae\x45\xb2\x4b\xbd\x9b\xcb\x3e\x51\xe8\x3d\x84\xe8\xf4\x58\x29\x67\x90\x97\xfb\x36\xe8\xa4\xcd\x6d\xd5\x8f\xbb\xa1\xe2\x9b\xa9\xc0\x7a\x83\x19\x60\x46\x85\x6e\x2a\x48\x9c\xec\x02\xc9\xf8\xcc\x33\x8c\x3e\x84\x98\x14\x7a\xd5\x18\x68\x3e\x3b\xb4\x34\x69\xa7\x89\xc4\xd7\x34\xd0\x09\xf4\x09\xa3\x27\x66\x49\xfe\x26\x8c\xbd\x1b\x2a\xdb\xdf\x6c\x0e\x75\xd2\xe5\xe8\xf2\xbc\xc5\x83\x64\xbc\x42\x09\xad\x4b\xa1\x93\xff\x75\xcc\xcd\x8e\xa0\x0a\x80\x76\x8e\xb5\x37\xca\xe7\xdd\x87\x4a\x2c\xe9\x8c\x3d\x02\x5b\xa3\x70\x16\x66\x8a\xb6\x5b\xf6\x1a\x26\x2c\x09\xee\x03\xfb\x0e\xa6\x92\x66\x22\xb2\x31\x3a\x27\xa2\x57\xa4\x32\x9d\x37\xd1\x48\x2f\xb9\x15\x29\xa7\xa9\x52\x93\xd3\x24\x2d\xf7\x95\x39\x4d\xe8\xaa\x94\xfc\x2b\xa7\x35\xd1\x59\xb2\xbd\xe0\x73\x26\xd8\x90\x79\x4d\x72\xcb\x26\x29\x12\xe8\x86\x94\xd9\xab\xcf\x8c\x60\x28\x55\x3e\x2f\x2a\xa1\x10\x7e\xf7\x2d\x6c\x3e\x56\xbc\x58\xaa\x5f\x02\xee\x3f\x24\xe7\xdf\x71\xb8\xa9\x8a\xd0\xb8\xc3\xe5\x63\x49\x49\x7f\x7a\xd4\xe8\x0b\x2d\xdf\xb7\x41\x14\xe8\xa4\xc4\x6c\x60\x2a\x94\xf0\x3d\x6a\xdb\xa0\x1a\x80\x28\x9d\xcf\xe4\xc7\x81\xdb\x0f\xf4\x30\xcf\x5c\x31\xea\xd1\x44\xb4\x42\x75\xef\x86\x29\x2b\x97\x0d\x6c\x25\x2f\xeb\x34\x10\x05\xba\x28\x75\xcb\x38\x29\x5f\xa9\x68\x7e\xd3\xa8\x04\x59\x6e\xb2\x49\x5f\x07\x00\xcb\xcd\xaf\xd5\x4d\xc7\xd1\xb8\x77\x33\x65\xfc\xd1\xbc\x38\x80\x8e\x03\xea\xac\xce\xa8\xf0\xfb\x07\xc0\x94\xe3\x0a\x34\xfd\x84\xf7\x96\x30\x2e\x4f\x3c\x74\x58\xed\x9e\x1c\x7c\x53\xd6\x35\x4d\xff\x56\x22\xb7\x49\xf3\xf6\x82\x5e\x31\xc5\x68\xca\x8f\xff\x78\xf8\xf9\x9c\xb6\xed\x33\xfc\x5d\xdc\xa5\x5d\x92\xda\xdd\x93\xbc\xf0\xe1\xae\x8e\xf9\xff\x38\x73\x03\xfa\x1e\x5c\xf4\xf0\x83\xd4\x82\xe5\x17\x16\x15\x0d\xf3\x0e\x29\xcc\x2e\x1c\xbb\x86\xc8\x80\x89\xb0\x77\x69\x69\x85\xef\xbe\xe6\xd9\xe8\x93\x87\x63\x6e\xc6\xb4\x1b\x3b\xf9\x7f\x60\x6f\xd8\xe6\x95\x57\xd6\xbf\x19\x77\xe0\x45\x38\xac\x8c\xcc\xee\x42\x0e\x1c\xe0\xed\x77\xf7\xc8\x45\x8f\xff\x32\xac\x22\x48\x8b\x3d\xd1\xe9\xe8\x05\x23\xc1\x3a\x6a\x4c\x61\x4e\xe1\xd0\x3e\x43\x8b\x9e\x78\x3a\x3c\x58\xa2\xff\xf0\x49\xfd\xbc\x03\x06\x92\x5d\xb2\xc9\x32\x62\x85\x7c\xd6\x0f\x18\x2f\x48\xc6\x15\x96\x8b\xc2\x22\xc6\x8c\xa6\x49\x84\x92\x2a\xb2\x05\xb3\x64\x8e\xfc\x6a\x5e\xc1\xdc\x82\x3e\x85\xc3\x37\xb3\xa2\x04\xa7\x61\x4c\x67\x5f\xed\x80\x25\xa6\xf0\xc9\x57\xcb\xe8\x8c\x6e\xd4\xb4\xde\x39\x13\x06\xdd\x57\x13\xb8\x5f\x14\x66\xbd\xe3\xe9\x57\x3a\x0c\xdf\xdf\x2a\x19\x04\xf4\x02\xd1\xb6\x16\xca\x30\xbc\xb0\x4f\xc1\xdc\x82\xbc\x87\x37\x95\x46\x2c\x04\xf5\xf4\xa0\x09\x39\xbd\xa7\x51\xdd\x32\xe8\x32\xa2\xc6\x7f\x55\x2b\x44\xcb\x65\x80\xa1\xc6\x41\x3c\xe9\x32\xd7\x20\xbb\x38\x10\x25\xa2\x0c\xc8\xd7\x19\xc6\x74\xa9\xc9\x69\xe9\x40\xc0\x29\x1d\x5e\x79\xda\x51\xf4\x4e\xdf\xd6\xe9\x13\x34\x1f\x0b\x18\x81\x1c\x40\x1a\x0c\x69\x4e\x80\x20\x27\x49\xe7\xaa\xfe\x2d\x1d\x0d\x5e\x92\xfe\x6f\x0e\x95\xe5\xb8\x82\xd7\x5a\x45\x60\x42\x78\x9d\x0a\x71\x7c\x21\x0d\x4b\x64\xa6\xe8\x9d\xe8\xaa\x7b\xb3\x27\x0c\x1f\x94\xdc\x23\x3d\xba\x3a\x7e\xf1\xbd\x99\xe3\x86\x17\x74\xca\x48\x8f\x83\x92\x85\x5a\x94\x93\xd7\xcf\x33\x28\xbf\xc6\x5c\xc2\x7f\x3c\x54\xd3\x89\x4d\xca\xcc\x58\xb2\x14\xd7\xe2\xf1\x7b\x44\x19\x33\xc6\x33\x5e\xa2\x77\x5a\x7a\xf6\x08\xcf\xe4\x07\xfe\x6f\xe4\x94\xed\x58\x68\x33\xf6\x86\x89\x9c\xd1\xa2\x9c\x73\xf2\x07\x79\xfa\xe5\xe5\x2c\x5a\xd4\x1a\x41\xbf\xf5\x8c\xc8\x4e\x4f\xeb\x4d\x78\x99\xf1\xe4\x03\x8a\x3c\x3c\xfa\x53\x60\x01\x4e\xd0\x59\x8e\x20\x26\x2c\x6a\x2f\xa1\x0f\x17\x3e\xf5\x84\xe8\x13\x6e\xab\x63\x82\xa9\x3c\x42\xe9\x00\x02\xaf\x08\xb1\xc0\xa6\x7d\x41\x8d\x91\x87\xfa\xfc\xac\x37\x15\x36\x9d\x56\x77\x47\xf7\x54\x59\xf0\x40\x9d\x1c\x27\x0f\x01\x60\x0e\xd1\x9f\xe2\x77\x92\x52\xf0\xda\x5b\x6d\x20\x24\xc3\x46\xaa\x32\x2b\xa1\x68\x07\xf6\x08\x26\x2c\xc6\x20\xc5\x92\x9a\xa2\x9c\xf9\x70\x18\x6f\xb4\x9a\x9e\xd7\x24\x5d\x9a\xe0\x50\x4f\xf0\x54\x13\x1c\xd2\x3c\x86\x29\x21\x90\xd0\x03\x95\x33\xf7\x84\x29\x90\xf0\x7c\xf8\xa4\x0a\xe3\xc6\x7c\xec\x15\xcc\xe1\x63\x61\xf9\xb0\x09\xf6\xaf\xf9\xd9\xd0\x7c\x24\x1a\xf2\x11\x2d\xa5\xef\x89\xc5\x72\xb4\x7c\xe4\xa8\xb4\xe3\xa0\x60\xdc\xe0\x22\x23\x46\x9a\xa5\x0c\x34\x6a\xa1\x60\xcc\x02\x37\x45\x4e\x82\x57\x01\x60\x96\x33\x8f\x01\x27\xce\xa5\xe8\x63\xfa\xa2\x9b\xda\x50\xa9\x09\xea\x6c\x32\x69\x17\x8b\x36\x69\xac\xd1\xb0\xd5\xaa\x67\x29\xaa\x57\x5a\xa1\xe6\xc3\xfa\xf1\x8b\x14\xab\x53\x6d\x6c\x6c\x91\x61\x95\xec\x4a\xb7\x08\xc0\xae\x55\x1a\x92\xe6\x89\x3a\xac\x04\x28\x0e\x36\x52\xa9\x4c\x39\x48\x13\xb2\x6c\x7d\xa2\x9e\x49\x15\x4f\x13\xfb\x43\x07\xfe\x0d\x9b\x93\xeb\x73\x30\x6c\x97\x6e\x50\xb3\x32\x2d\xfe\xed\xb3\xe7\xd1\xd7\x95\x37\xca\x2b\x96\x3e\x3d\x76\xd1\xfc\x55\xeb\xb7\xed\xde\xf0\x1c\x8c\x9b\xf5\xf9\xa4\xbd\xa8\x09\xdd\x46\xd7\x61\xad\xb4\x2e\x85\xde\x07\x9f\xec\x14\x93\x7d\x6e\xdd\xd6\x5e\x69\x97\x7b\xa7\xe4\xe4\x16\xf9\x1a\x0a\x47\x54\x67\xa6\xff\x34\xf6\x15\x2a\x47\xbd\x22\x6d\x35\x3e\x8d\xa1\x0a\x8f\x6f\xa5\x6c\xb7\x42\x01\xa4\xdd\x9a\x55\x28\x29\xe0\xf3\x82\x34\xe0\x05\x83\x22\x46\x68\x66\xe0\xc2\x22\xfd\x54\x6b\xf3\x42\xf2\xd9\xc7\xc8\xf6\xf1\xfe\xa4\x95\xb8\x4d\x0c\x62\x58\xdc\xef\xe8\x6d\x64\x48\xa2\x1d\x06\xb6\xf2\x97\xe0\x36\x31\xa0\x61\x71\xff\xa8\xb5\xa9\x91\xf3\x6d\x53\xac\x2d\x7f\x25\xbe\xe9\x88\x71\x7f\x21\xf3\x9d\x2b\x5a\xdd\x88\xf9\x9e\x27\xad\x25\x09\xce\x07\x50\xe7\xe9\x4f\x41\x5b\x7c\x6f\xa2\x99\xf8\x50\x19\x5b\x2a\x4f\x71\x46\x0e\x28\xa5\x7c\xaa\x29\xdd\x7c\x52\xf9\x02\xb9\xbe\x7d\xed\x0a\x43\xd9\xbe\x62\x8a\x3e\x2d\x77\xa0\x59\x56\x34\x0f\x53\x75\x40\x62\x1f\x96\x21\xf8\x52\x97\xf9\xca\x42\xd5\x93\x6e\x8e\xed\x52\x08\x64\xb6\x9e\x50\xc9\xa5\xef\xd7\x64\xe2\xa8\xfa\x35\x98\x23\x8a\x9e\xcd\xd6\x0f\x7a\x79\x09\x53\x79\x25\xc5\x37\x94\x57\xd2\xf1\x68\x33\x79\x15\xeb\x05\xb5\xbc\xc1\x46\x75\xbf\xa4\x89\xe2\x2a\xfb\xb5\x1b\xe8\x28\x6d\x26\xaf\xa8\x93\xea\x9e\x09\xfc\x8e\xc8\x6e\xa6\x1c\xd8\x41\x37\xb3\xb7\xca\x34\x4a\xab\x79\x49\x6b\x89\xa4\xb7\xc2\x2b\x5a\xcd\xfd\xa9\x65\xfc\x2b\x5a\xd4\x31\xbd\x3f\x8a\xa0\x3f\x8d\x12\x6b\xfa\xf3\xc9\x7a\xac\xeb\x90\x3e\xa4\xf3\x2f\x7c\x7f\x5e\xa0\x7d\x0d\x50\xf5\x52\x98\x89\x52\x6b\x5f\x3e\xd3\xea\xb5\x5e\xe0\xe3\x26\x0e\x23\x42\x1c\x26\x4a\xae\xc5\xa1\xd7\x73\x3d\x13\x75\x86\x0e\xa0\x55\x7c\xf8\x94\x2f\x42\x2a\x70\x14\x6b\xf5\x3e\x0c\x1f\x0a\x83\xde\x2a\x3e\x68\x13\x1c\xf7\xeb\xe7\x41\x18\x3e\x24\x03\x2d\xe2\xb8\x82\x73\xb1\xfa\x9b\xe1\x88\x64\xa9\xac\x01\xf5\x7c\xb8\xb5\xb2\x1e\xe2\xed\x50\x0b\x65\xf0\x8b\xb0\x6a\x96\xca\x1a\xac\xfb\xc2\xae\x95\xc3\x82\x5d\xab\xde\x71\x63\xbf\xc4\xe4\x85\xf0\x7b\xd2\x7f\x4a\xbf\x27\xbf\xc0\x6d\xe0\xf7\x94\x0f\x8a\x6b\xdb\xd7\xfb\x3d\xb9\x7d\xa5\xdf\x93\x3b\x30\xf0\x7b\x8a\x0e\xb0\x1f\xb0\xac\x8f\xc8\xef\xc9\x3d\xe9\xfd\x9e\x42\x20\x53\xbf\xa7\x94\x4b\xdf\xaf\xb9\xdf\x93\xfb\x35\xf2\x7b\x0a\x49\xcd\xfc\x9e\x4e\xde\x99\x11\xf9\x3d\xbd\xbc\xb2\xdf\x33\x93\x57\xe9\xf7\x54\xf2\x72\x7e\x4f\xd9\x6f\x08\xbf\x27\xfd\x67\xe8\xf7\xcc\xe4\x55\xfa\x3d\xd5\x93\xf4\x80\x0c\x7e\x06\x80\xa5\x42\xd8\x67\xe6\x44\xb8\x23\x56\x02\xc9\x09\x37\xc7\xe1\xe3\x0a\x58\xe1\xf6\xc1\xaa\xf1\x88\x0c\x9b\x66\x5a\x47\x84\x4d\x9a\xd3\xf0\x47\x73\x70\xda\x7d\xaf\x12\x1b\x01\x76\x04\x1b\x49\x27\x53\x0e\xda\x28\x63\x75\xf8\x3a\x78\xba\xc5\x02\xcc\x1e\x39\x60\xc2\xc2\x79\xdb\x8e\xd6\x77\x93\x27\x7a\x05\x09\x02\x80\x2f\x76\x47\x25\xeb\xd7\x08\xdb\x85\xf6\xdb\xf2\xaf\x4d\xa9\xe7\xb6\xba\xbf\xed\x8a\x03\x33\xb9\x2b\xcd\x3a\xc0\xdf\x5e\xee\x8f\x1b\xf7\x00\x6e\xdf\x0b\xe2\xf9\x9b\x6a\xad\xfb\xd7\x08\x24\x9e\x59\x89\xda\xde\x4b\xee\xe7\x31\xd1\xfd\xaa\xfc\x9c\x7f\xab\xdc\x1d\x3d\x4b\x5e\x03\x04\x6f\x6a\xfa\xd5\x1c\x7f\x1b\xf7\xdb\x4e\xd2\xf6\xfd\x72\xc7\x0b\x84\x8e\xd5\x6e\x4d\x29\xa7\xdc\x31\x09\x7a\xaa\xfb\xd5\x5e\xe3\x68\xfa\x15\x66\x5c\x4f\x51\x5e\x28\x77\xfb\xba\xe8\xe8\x4d\xe5\xa5\xfa\x48\x4e\x9e\xe4\x66\xb7\xaa\xdf\xd0\xf2\x8a\x67\x72\x92\xbc\xbf\x97\x3b\x7e\x5e\x98\xe7\xe6\xf2\xf2\x1d\x63\x9f\x1e\xfc\x1b\xee\xf7\x0a\x70\x82\xd4\x10\x27\x5d\xda\xee\x95\x6a\xdb\xc3\x64\xf6\x8c\x95\x21\xa5\x8a\x93\x5c\xeb\x0a\x9b\x67\x2b\x50\x91\x1a\x1f\x1e\xfc\xac\x15\xd8\xd4\xb3\xdc\x6c\x66\x4f\x94\xb1\x75\x96\x26\x79\x48\x70\xc7\x55\x4e\x9b\xdf\x4b\x46\x99\xf9\x6c\x9b\x32\x97\x4e\x9a\xca\x5f\xf3\xc9\x74\x3a\x77\xad\x4c\xab\x13\xf7\xa9\xa4\xdf\xd4\x5f\x2b\xdb\x56\xf8\xeb\xe9\x7c\xeb\x3a\x5f\xad\x6a\x1d\xfb\x2e\x3a\x2f\x02\x5f\xad\xec\x45\xe7\xab\xef\x17\x24\x31\xf1\xd3\x6a\x81\xf4\x7d\x9a\xf9\x69\x65\x9f\x06\x7e\x5a\xe8\xd5\xc4\x47\x1b\xc8\x59\x1c\x81\x8f\x36\x92\x53\xf2\xd1\x8c\x91\x9c\xb2\x7f\x36\x92\x73\xba\xa9\x9c\xb4\x61\x9f\x06\xfe\x19\x1a\xc9\x29\xfb\x66\x8d\xba\xf0\xfe\x8f\x4e\x6f\xa9\x6f\x56\x80\x08\xef\x9b\x45\xe5\x0a\xe3\x97\xd5\x63\x10\x19\x2e\xad\x5f\x8e\x04\x97\xec\x97\x1b\x8c\x81\x69\x7c\xb2\x46\x37\xf8\x5c\xc7\x72\x9c\xeb\x98\x1e\x2e\xd7\x51\x75\x17\x69\x96\xe7\x58\x29\xc7\x42\x98\xa5\x38\xc2\x6f\x34\xce\xbb\x25\x38\xb4\x21\x0f\x66\x38\x94\x71\x0e\x66\x40\x88\x7f\xa9\x37\xfe\x42\xce\x12\xe3\x05\x6d\x40\x27\xd0\x5d\xcc\x3c\x50\xe6\xd3\x18\x5c\xa1\x8b\x04\x89\x61\x00\x6a\x44\x5f\x88\x53\xa9\xb3\x88\xec\xa4\x78\xf5\xaf\x4b\xa7\x19\xa2\xba\x2e\x7f\x50\x8c\xe8\xef\xa3\x8a\x5b\x08\x89\xcf\xe8\x6a\x3c\x0c\x3e\x69\xda\x95\x87\x05\x48\xa5\xaa\xfc\xe8\x37\x5a\x80\x61\xf1\x19\x86\x20\x84\x7e\x30\x1c\x32\x22\x81\x43\x44\x7c\x37\xc5\xb8\x83\x08\x09\x24\xa0\x36\xde\xa0\xd5\x1c\x1a\x63\xfc\x41\xe2\x70\x98\x0a\x63\xe7\xaa\xfe\x91\x72\xc8\x63\xc4\xa7\xbf\xd8\x7e\x06\x1b\x99\x87\xe9\x33\xd8\xef\xa5\x1a\x78\x55\xc3\x1c\x69\xd9\xbf\xae\x30\xcf\x8c\xd6\xf8\x5c\x54\x67\x92\x19\x2d\xe3\x78\x4a\x81\x43\xeb\x81\x8d\x71\x28\x7c\x71\x7b\x73\x24\x1a\xff\x8c\x52\x4d\x91\x50\x1c\x0e\xcb\xb7\xf4\x19\xc1\x9f\x64\x86\xf0\xd6\xc6\x88\x74\x7e\xbb\x20\x04\x43\x86\xbe\x3c\xf0\x88\x39\x51\x46\xf8\xcc\x3c\xbb\x31\x3e\x03\x1f\x1f\x02\xa1\xa1\xdf\x0f\x01\x90\xc7\x57\x1b\x82\x3f\x69\x15\x60\xa2\x59\xda\xf5\xc0\xe2\x48\xe9\x13\x97\x08\x68\x41\x08\x3d\xe3\xf1\xbd\x12\x82\x3f\x3a\x0c\x3e\xfd\xda\x61\x5e\xa4\xf4\x89\xcb\x89\x10\x08\x09\xb0\x3e\xf8\x1d\x75\x84\x29\x07\x0e\x75\x8c\x72\x9f\x34\x37\x9b\x0c\x71\x6e\x0f\xa1\xbd\x9e\x5d\x0f\x73\xe6\x2c\xae\x5e\xdc\x29\x03\x7a\xba\x77\x46\xdf\xa3\x2f\x51\x20\xa8\xbc\x91\x45\xc4\xb4\xc0\xe6\x0d\x2b\x0e\x9f\x7e\xf0\x6f\x6f\xff\xfe\xdb\x87\xd1\x09\xf4\x27\x48\x92\x7f\xd1\xef\x6b\x23\xe9\x5b\x33\x2f\x0d\xfb\xbe\x57\x31\x2d\x0d\x3b\xa7\x4e\xea\xce\xc1\xf9\xbe\xbd\xc0\x01\xba\xe1\x51\x31\xec\xdd\x6c\x2e\x1a\xa1\x38\xae\x9b\x89\xc6\x3c\xfc\xd5\xfc\x0e\x35\x32\x4c\x26\xf3\xcf\x10\x93\xc1\xec\x33\x26\xe8\x2d\xb3\xfb\xd1\xd6\xf0\x24\xcd\x39\x23\x4c\xb7\x75\x2b\xf0\x08\x78\x52\xdf\x7d\xb6\x86\x27\x3a\x14\xa6\x2b\x06\x2b\xf4\x08\x78\x92\xef\x35\x45\x4c\x57\x70\xd5\xdf\x01\xa6\x98\x22\x59\xb5\x1b\x01\x7c\x2d\xec\xea\xdd\x10\x2e\x4d\x87\x3e\x42\xff\x65\xb8\x35\xab\x7a\x23\xdc\x9b\xc3\xaf\xee\x23\x02\xae\x39\x4e\x17\xce\xbb\xc7\xe0\xfd\x73\x7b\xbd\xf7\x4e\x95\x62\xc3\x15\x96\x61\xac\x32\x24\x5c\xe3\xa2\xfd\x72\x1c\xb8\x70\xf6\xbb\x4e\xd8\xe3\x75\x31\xf7\x78\x72\x2f\x06\xd3\xac\x44\xd5\x9b\x91\x5b\x1b\xa7\xeb\x73\xa7\x69\x9f\xb2\x97\x30\xe8\x53\x54\xd9\xcf\xcd\xbb\x14\x35\x15\x0e\x53\x74\x8a\xf7\x95\x57\xb9\x7e\x85\xfd\x5b\x56\xa4\xfb\x37\x11\x44\xf8\xa0\x22\xf8\x17\x15\xa8\x50\x5b\x38\x18\xab\xc6\x46\x80\x79\xc1\x46\x66\x39\x53\x0e\xdc\xfc\xeb\xc4\x09\x3e\x96\x50\xa4\x29\xe2\xdf\xb4\x23\x59\x6e\x7d\x4b\xe0\x98\x4c\x0e\xb0\xce\x5b\xcd\xeb\x5d\x00\x53\xab\xef\x9f\x76\xd7\x18\xd8\x61\x4c\x69\xc5\x8c\x6a\x98\x5a\x90\xfd\xdd\xf9\x47\x5f\x4c\x8f\xe9\xf5\xc2\xd2\xbf\x35\x12\xcf\xc9\xfb\xba\x94\x6d\x90\x7a\x09\x35\xa1\x73\xbb\xf6\x2e\x79\x12\xba\xd1\xc5\xd5\x95\xaf\xbe\x0c\x3d\x90\xd9\x89\xd0\x0b\xe8\x67\xf4\xd7\x39\x73\xe6\xcf\x80\xbd\xc8\x57\xf5\xbe\xac\x75\x58\x35\x7a\x1b\x16\xeb\x5c\xc5\xde\x2f\x42\xb0\xd4\x76\x9d\xef\xe3\xb1\x7a\x81\x1b\xe4\xf2\xef\x6a\xb7\x80\x59\x03\x6f\x18\x0e\x35\xfc\x44\xeb\x1a\x23\x26\xfa\x35\xd3\xfb\xe3\xd6\xca\x60\x32\x97\xc3\xca\xf0\xa6\x7e\x8e\x47\x3c\x02\x6b\x4d\xee\x9e\x7f\x9d\x71\x90\xbc\x6d\x58\xed\x21\xb5\xae\xb7\x75\xe3\xa0\xba\xb7\xfe\x75\xc6\x81\x8e\x54\x06\xf8\xbd\xde\xee\xb5\x6e\x1c\x14\x77\xde\xbc\x0c\x57\x80\x1b\xe4\x83\xe2\x16\xc8\x10\x89\x37\x0f\x2b\x90\xe9\x65\xb3\x14\xd8\x1e\xa9\x78\x9f\x87\xbb\x2f\xff\x55\xe5\xd4\xf8\x84\xb0\x72\xae\x0a\xeb\x2b\x5a\x2b\xa8\xe1\x5d\xfb\x47\x78\x6f\xdf\xdb\xe0\x84\xc1\xca\xa6\x11\xde\x3e\x09\xdd\x3c\x5d\x80\xd5\x4e\x58\x58\x2b\x6b\xcd\x4d\xe0\x8f\x41\x1c\xf6\x44\xa7\xe2\x02\x7e\x3a\xac\xdc\xfa\xca\x6b\x70\xc0\x39\x98\x0f\x97\xd5\xbd\x00\x1f\x0e\x54\xaf\x79\xe2\xf8\x81\xb7\x3e\x7e\xe2\x49\xdd\x01\x3f\xa4\xa6\xc2\xc2\x13\x87\xa0\x73\x33\xaa\x47\xd7\x4f\xa0\x8f\xa7\x21\x3f\x74\x8e\x80\xc4\x27\x27\x2f\x7d\xfe\xc9\xe9\xc0\x08\x74\x43\x5a\xb7\x5c\x90\xb0\xe9\xef\xf2\xc2\x60\x93\xed\x7f\xb3\x39\x38\xdd\xfd\x40\x44\xe0\xf0\x1a\x24\x2a\x4f\xd8\xab\xf6\x0d\x79\xc7\x1f\x06\xa5\x6e\x2b\xc4\x86\x60\xd2\xe4\x82\xa1\x95\x98\xcd\xe3\x03\xc2\x60\x36\x58\xc3\x85\x40\x6d\x72\x41\x11\x09\x68\x7e\xad\x77\xd9\x94\x67\xf9\xc4\x22\x62\x9e\x45\x7b\x7e\x57\xa4\x34\xcb\xf7\x1b\x91\xe9\x2d\x8f\xf9\x07\x53\x9e\xe9\xc8\x31\xeb\xed\x77\x71\xa4\x34\xcb\xf7\x23\x11\xf1\x8c\x63\x06\x56\x09\x6b\xdb\xe1\x11\xde\x99\x84\x15\x20\xec\x45\xca\x63\x21\xc4\x09\x73\xb7\x12\x99\xce\x47\x26\x97\x36\x1b\xa0\xd5\x72\x49\xf6\xf9\xdb\xc8\x05\xd3\xdc\xcd\x44\x38\x97\xf9\xfc\x2b\x16\xe7\x8b\x7a\x5a\x98\xdb\x1a\x36\x55\x51\x4e\x14\x25\x61\x8c\x23\x7f\x5d\xf6\x8a\x08\xb2\x44\xd7\x3b\x16\xbf\xd7\x21\xf7\xc8\x2f\xc4\x16\x3e\x75\x4f\xc2\xb6\x21\x5c\xe6\xa1\x9c\x6e\xab\xcc\x35\x14\xf3\x1a\x58\x7e\x17\x17\x71\xde\x45\xa4\xe1\xf6\xb0\x8b\xc0\x59\xc8\xa0\xef\xe5\x02\x5b\xad\xc7\x13\x69\x38\x3a\xdc\x17\x49\xf8\xfc\x08\x89\x21\x31\xce\x96\xe5\xeb\xe9\x98\x44\x79\x1a\x87\x97\x66\x0a\xa2\xeb\x62\xfe\x98\x38\x85\xbc\xe1\xdb\xb7\x99\x84\x6b\x4e\x37\x8d\x16\xbd\xa8\xc0\xdf\x1f\xc7\x49\xb0\x20\x0a\x24\x02\xb9\x36\x8b\x3a\x30\xa2\xbf\x80\x74\x98\x1c\xf9\x20\x62\x6c\x7e\x4e\x19\xf2\x23\xc5\x2c\xb1\xfc\x0b\x83\x26\xa1\x27\x8a\x60\xa5\x9e\x22\xdf\x15\x26\xb1\x2d\xfc\xdd\x13\xdf\x9e\xae\xbe\xae\xaa\xda\x9b\x49\xd9\x43\xd8\x59\x40\x4f\x9b\x96\x36\xa4\xd6\xf0\xc2\xf8\x67\xca\xb5\xa9\xe4\x7e\xc3\xd5\xf5\x35\xbb\x86\x93\x2e\x56\xab\xcc\x6e\xdf\xf6\xeb\xae\xdb\xc4\xb3\x6b\x56\xa8\x60\x6c\x72\x6e\x1e\xe2\x68\x16\xb6\x11\x67\x94\xf1\x01\x58\x92\x42\xb7\x22\xea\x2b\xc4\xf1\x26\x7c\x31\xf4\x51\xeb\x57\x0a\x3d\xe3\xf7\x08\xac\x50\x73\x31\xe2\x1d\x69\x84\xdb\x68\x82\x11\x6d\x6f\xa4\x6b\xfd\x5b\x0a\x1e\x5a\x89\x2d\xd2\xed\xf1\xa6\x96\xee\x8a\xdf\x97\x78\xa3\xc0\x14\x64\x97\x6a\x1d\xf8\xf0\x7b\x37\x2d\xf0\x10\x1e\x87\x34\xfb\xbc\xad\x29\xd3\x50\xda\xe0\xca\xe8\xd1\x75\xe0\xbd\xe7\x3a\xb7\xa0\x5e\x83\xbf\xc3\x2c\x4f\x76\xdc\xee\xa4\x7f\xd2\xe7\xb4\xc7\x59\x1a\x79\xfa\xb5\x54\x1e\xed\xb6\x46\x29\x5f\x0b\x4b\x39\xc4\x88\xa2\xb5\xb8\xa6\x43\xd3\x78\x41\x3e\x00\x00\x2d\xc8\x23\xe6\xe2\x0f\x03\xe3\x7e\x51\x75\x07\xf5\x80\xb5\xa2\xd4\x83\x34\x62\x4b\x5b\x59\xf3\x41\x1a\x3d\x4b\x47\xe1\x40\xa9\x55\x32\x86\xa8\xfe\xd0\x52\x19\xf5\xa5\x20\x22\x17\xd2\xa4\x0a\x81\x5e\xc8\x56\x8e\x65\xa8\x0a\x11\x6a\x39\x5b\x53\x2e\x42\x92\x73\x4f\x2b\xeb\x46\xc8\x53\xf1\xba\xbc\xa8\x6b\x95\x9c\x11\x8f\x67\xab\xca\x49\x48\x82\xbe\xd6\xca\xb2\x12\x1a\x41\xf1\xdd\x99\x28\xa7\x58\x77\x61\x1c\xa8\xf8\x35\x2a\x2f\x68\xc4\xfd\x95\xca\x4d\xc8\x96\xb6\xf5\x75\x27\x64\x12\x0e\x6a\xae\xe3\xfe\xbf\x70\xf1\xab\x95\xa4\x90\xb8\x70\xfc\x82\xda\x14\x12\x19\xcc\x23\x9a\x3b\x3e\x0a\x80\x60\x63\xd4\x8b\x52\xdd\x88\x0c\xe5\xfb\xbe\x9a\xfc\x19\xbe\x4e\x80\x6a\x15\xab\xae\x23\x21\x47\x27\xac\xe0\x33\xdb\xc9\x95\x8a\xf0\x78\xb1\x4e\x80\x26\x82\xc8\x8d\xb3\xda\x03\xb4\x6a\xe9\x1c\x12\x97\x61\x45\x8b\x50\xb8\xf4\xf5\x2d\x8c\x80\x19\xd7\xba\xd0\x00\xa3\x01\x0c\x36\x46\x9f\x55\xd4\x79\xf0\x44\x5c\xf9\x42\x85\x30\xa2\x3a\x18\x4a\x98\x11\xd6\xc4\x88\x08\x6f\x64\x15\x32\xd4\x78\x23\xab\x97\xa1\x22\x36\xa2\xda\x19\x6a\xc0\x91\xf0\x6b\x56\x49\xc3\x98\xdf\x50\x75\x35\xcc\xf9\x35\xad\xb1\x11\x82\xdf\x44\x13\x7e\xcd\x2a\x6e\x98\xf1\x1b\xba\xfe\x86\x39\xc3\xe6\xb5\x38\x34\x1c\x07\xaf\x06\x1b\xa3\x37\x28\x6a\x5d\x14\xb5\xaa\x32\x87\x5a\x80\x56\xd5\xe9\x50\x09\xd3\xb2\x9a\x1d\xad\x96\x29\x64\x05\x8f\x08\x65\x0a\x59\xcf\x23\x94\x50\xa1\x6b\x7b\xa8\x65\x22\x15\x79\xcb\x2c\xff\x16\x97\xc1\x89\x07\xad\xf4\x3b\x5a\x9b\xad\x39\x05\x41\x9f\x8b\xde\x04\x6e\x35\xcf\xa0\x9e\x6b\xb2\x65\x69\x0d\x9e\xd0\x69\xd5\x0a\x3c\xf7\x84\xc8\xb0\x16\x01\x31\x27\x0c\xea\xc9\xc9\x39\xbd\x2c\xff\x66\x67\x78\x54\x66\xf6\xda\x14\xdd\x2b\x61\x93\xb0\x25\xce\x1a\x8c\x2f\xd3\x5b\x87\x33\xb2\xd4\x6c\x05\xce\x08\x92\xb4\x25\x32\x0f\x18\x5d\x98\xff\x1a\x7c\x9a\xa5\x6e\xcb\x38\xff\x16\x36\x89\xdb\x98\x4f\x9b\xe2\x2c\xe0\x97\xf3\x69\x96\xda\x2d\xe3\xfc\x30\x82\x24\x6f\x63\x3e\xe7\x29\xe2\xb1\x29\x45\x0e\x35\x0b\xf2\xc0\x88\x88\xb0\xb6\x22\xfd\x5b\x06\xbe\xa6\xc5\x89\xe0\xa2\x18\x16\x2a\xe4\x05\xf7\xaf\x28\x4b\xe8\xf4\x70\x59\x96\x87\x5b\x9e\x28\x6e\x26\x8c\xfa\x12\x1b\xc7\xa7\xc7\x44\x0b\xf9\x61\xe9\x61\x32\xc6\xd5\xde\xda\x38\x7f\xfc\x9c\x62\x39\x11\x2a\x97\x5c\x79\xc0\x0b\x0c\x70\x84\xca\x2c\x57\xe3\x30\xce\x33\x57\x02\x09\x99\x73\xae\x02\x82\xe3\xa8\x63\xef\x95\xf2\xae\xb2\x23\xcc\x40\x0f\xbd\xae\x55\xe5\xa3\x9f\x8b\x60\x3d\x6b\xca\x93\x11\xbe\x48\x32\xd5\xc3\xad\x63\xcd\x10\x46\x90\xc3\x6e\xc0\x5f\x6e\x08\xfe\x8c\x33\xda\x43\xaf\x5b\x55\xf9\xed\xa6\xfc\x19\xe7\xba\x6b\xf8\x0b\x36\x6a\xf1\x45\x92\xf9\xae\xc6\x17\x26\x0f\xde\x9c\x3f\xe3\x9c\x78\x35\x42\x0e\xe3\x67\xc1\xc6\xd8\x5e\x52\xae\x5b\x41\x2b\x32\xe4\xd5\x80\x5b\x94\x2f\xaf\x82\xdf\x82\xdc\x79\xb5\x1e\x44\x2a\x43\x88\x4c\xfa\x08\x65\x30\xcc\xab\x0f\x25\x44\x88\x1c\x7b\x95\x0c\x24\x98\x87\xec\x52\xac\xe5\x90\xd6\x47\x86\x92\x4a\x47\xd0\x82\x30\xd1\xc7\xa5\x23\xe9\xd6\xc5\x8b\x36\x9d\x93\x0e\xa6\x5b\x2f\x4b\xa8\x23\xf6\x96\x84\x91\x66\xb4\x54\x18\x4d\x3c\xa9\x7c\xca\x4e\x09\xb2\xf0\xb1\x80\x83\xc1\x98\xd6\x47\x96\x1a\x1e\x3d\x47\x1e\x66\x5a\x2e\xca\x54\xf2\x8b\xe2\x4d\x9b\xfe\xac\x3b\x7d\xfe\x25\x32\x6a\x8e\x66\x5b\x27\xa3\x1c\x86\xfa\xbf\xa2\x90\x03\x7f\x51\x38\xaa\x34\x7e\x92\x90\xff\x67\xe3\xd8\xe2\x30\xd5\xce\xa2\x88\xeb\x7f\x51\xbc\xaa\x34\x8e\xf2\xe9\xfa\xff\xd9\x38\xb6\x3c\x8c\xb5\x4e\x14\xf2\xd9\x5f\x14\xce\x2a\x8d\xa3\xe2\x64\x5d\xd6\x57\x3e\xe6\x73\x0c\xb8\xe7\x17\x47\xb7\x86\x38\x56\x6f\x75\xa8\xeb\x5c\x91\x82\xa8\x5f\x1a\xf3\xfa\xf3\x0e\xe3\xa3\x75\x35\x0f\xc5\xbf\x9c\x07\xed\x49\x4d\x4b\xcc\x6f\x04\xa1\xb0\x6c\x8b\xad\x72\xa8\x98\xd8\xa6\x27\x45\x1b\xcd\xaf\xe7\xad\x42\xfc\xe9\xa0\xd6\x44\xc7\x9a\x6c\x36\x42\xc5\xca\xf6\x09\xb1\xf7\x88\x20\x34\x4c\xb3\x10\xe3\x65\x48\x55\xc8\xd0\xe2\x28\x5a\xb3\x8d\x4a\x88\x98\x5a\xca\x13\x62\xdf\xd2\x62\x21\xf8\xf5\xf8\xef\xa4\x78\xca\x61\xbf\x24\xda\x36\xcc\x26\x27\x54\xec\x6d\x9f\xf0\x9b\x9e\x5f\x45\xb6\x56\x47\xe5\x86\xdd\x20\x45\x28\x5d\xeb\xe3\x75\x0d\xf6\x51\x19\x21\xc6\xad\x05\xd1\xbb\xa1\x37\x57\xa1\x62\x79\x3d\xe1\xf7\x5a\x2d\x9f\x57\xbc\x6c\x05\x21\xc6\xad\x05\x51\xbe\x66\xe3\x16\x41\xcc\xaf\xf9\xb0\xb5\x28\xfe\x57\xbf\xef\x89\x69\x90\x62\x66\x27\xfe\x5a\xd1\xc0\x2d\xdc\xd0\x85\x88\x0d\x56\x19\x98\x5f\x1e\x27\xac\xdd\x5f\x47\x28\x7f\x4b\xa3\x86\x5b\xba\x19\x0c\x11\x43\x1c\x8a\x80\x96\xc7\x13\x6b\xcf\xb1\xf8\xf8\xdd\x0c\x90\x0c\x7a\xe2\xf8\xf5\x30\x77\xea\x1e\x8e\x19\x9e\x98\x34\xe5\x55\xba\xf9\x75\xf9\xfe\x3d\x54\xd6\xc4\x89\x9f\xb5\xdb\x17\xf7\x79\xdd\xbe\xb3\x35\xe2\x25\xb9\xe9\x8d\x38\xdd\x36\x2b\xb7\x7d\xf5\xb6\x43\x07\xfd\xdb\x84\xab\x70\xf9\x7d\x1f\x7a\x2f\x48\x06\x5d\x41\xaf\x08\x62\x94\x58\x07\x8c\x08\xde\x57\x44\x5d\xe0\xd5\xb0\xa0\xc8\xf7\x1a\x1a\x02\xe3\x65\x3c\x62\x1c\x98\x18\xf7\x5c\xd0\xba\xa8\xec\x16\x07\x80\x89\x21\xda\x39\x2d\x88\xfe\x12\x62\xb5\x7f\x3e\x2d\x87\x7d\xe1\x37\x43\xed\x34\xa0\x16\x09\x71\x79\xad\x8e\xca\x6b\x51\x14\x5e\x0b\x62\xef\x74\x1c\xfb\x5a\xca\x71\x4b\xc3\x7a\xf4\x70\x07\x45\x1c\x73\x6e\x18\xa7\x24\xce\xad\x78\x21\x66\xe5\x97\xc7\xab\x98\xa3\x5f\x61\xf2\x7c\x16\x1b\x5e\xb3\xdf\xd5\xbc\x6f\x5b\x22\x6a\xb9\xc8\x7f\xbc\x14\x73\xf3\x2b\x47\xdc\xfc\x02\x71\xc2\xab\x94\xa9\x5c\x4a\x15\x13\xdf\x60\xb1\x54\x03\x0b\x70\x80\x24\x29\x62\x25\x16\xaa\x0c\x9d\xee\x01\x16\x87\xca\xa8\x1d\x57\xbf\xc0\x62\xa9\x16\x2c\x58\x73\x8d\xf8\xc6\x87\xd0\x0f\x83\x80\x05\xc4\x02\xab\x1c\x19\x83\x0d\x95\xae\xf9\x54\xa2\x2e\xf0\xad\xba\x51\x26\xa3\xa1\xc1\xef\x95\xda\x0b\x7e\x8b\xdf\x8e\x39\x02\xa2\x40\x3b\x90\x08\x00\x69\x1c\x10\x62\x13\xec\x45\x9c\xd1\x1b\x16\x2f\xf3\x86\xa1\x69\xbb\xfe\x4d\x12\x32\xf8\xbd\xb6\x7d\xc3\x00\x0e\x6b\xa8\x17\x50\x16\x9a\x3f\x7a\x42\x0a\xb1\x42\x47\x80\x05\xbf\x64\x2f\xf3\x11\x26\x32\xc8\xe8\xbe\x3e\xc4\x85\x3c\x04\xb5\xd4\x31\xb8\x03\xd7\x08\xd5\xed\xe9\xe4\xd2\x2c\xba\x02\xe4\x10\xee\x43\x76\x32\x29\xb8\x19\xc4\x01\xa0\xbe\x1e\xdf\x27\xaa\xde\x5c\x85\x1e\x71\xfd\xdc\x0d\x77\xd0\x8d\x61\xfa\xb9\x5b\xdb\x0f\x38\x4b\x5d\xa0\xe2\x18\x6e\x65\x69\xf2\x62\xe8\x59\xb3\x97\xf1\x2e\x68\x5e\xc1\x23\xc1\x35\xea\x34\xf9\x21\x73\x03\xdf\x14\x64\x99\xb4\xd7\x56\x3a\x21\x75\x75\x4d\x4b\x55\xfc\xfe\x5a\x6c\x55\x45\xf6\x84\xe1\x03\x93\x7b\xa4\xc7\x54\xc7\x2f\x9e\x96\x39\x6e\x78\x7e\xa7\x9e\xdd\xdb\x4c\x19\xd6\x3f\x6f\xd4\xa8\xbc\xfe\xc3\xe0\x46\xf1\x77\x34\x5a\xf0\x98\x72\x15\x72\x28\x7f\xd0\xa0\xfc\x01\xf9\xf9\x03\x84\x5f\xe5\x38\x08\x16\xdf\x39\xf6\x88\xec\x46\x3a\xdc\x55\xf9\x7f\xcd\x12\x4e\xe6\xca\x47\x75\x42\x50\xbc\x90\x77\x42\x55\xe2\xfe\x23\xe8\xdd\xb4\x53\xd3\xce\x5a\x23\x23\x0c\x7b\x7d\x0d\x9f\x0c\x7b\xbd\x7e\x5d\x95\xdf\xc4\x63\x88\xc7\xb5\xbe\x5b\x52\xe9\x5b\x83\xc0\x54\xcb\x74\xc9\x37\x5a\xb5\x93\x78\x88\x17\xee\x97\x5b\x7d\xbb\x6c\x4a\xca\xc4\x48\xc1\x49\x1c\x5d\xd3\xbe\x59\x19\xfc\x0c\x00\xea\x22\x7d\x08\x44\x01\xbb\xc2\x5a\x2a\x9f\x49\xc8\x11\x13\x4f\x76\x2a\xde\x46\x90\x6d\xa4\xfa\x3d\x0d\xdc\xde\x19\xb9\x3d\x83\x67\x17\x72\xc4\xdb\xc0\xee\x8a\x57\x1e\x16\x1a\x3f\xec\x80\xdb\x63\x06\x1a\xe1\x93\x2b\x35\x4b\xf8\x14\xf5\x98\x15\xf8\x54\x75\xcf\x71\x7b\xd9\x46\xf8\xe4\xf6\x24\x7c\x8a\x7b\xa8\x85\xc6\x05\xb8\x09\x70\x28\xd8\x18\x9d\x4b\x1f\x04\xb1\xa0\x03\x37\xc2\x66\xd7\x5e\x87\x4c\xee\xb4\x42\xdc\x1f\x12\xb0\x1d\x75\x9c\x5c\x87\xeb\xff\x3a\x01\x30\xab\xa6\x01\xdb\xe9\x22\x7a\x8c\x5f\x51\xe0\xdb\x5b\x6f\xd2\x9e\x7c\x9f\xdb\x4e\x17\xd1\x62\xfc\x0a\x01\x01\x6e\x51\xbb\xc9\x33\xb8\x16\x6f\x9a\x99\x95\xd6\xec\x8f\x6f\x85\xdb\xf0\x86\x29\xe2\x4f\x04\xff\x88\xf3\xd0\x32\x78\xef\x48\xaa\x56\x23\x2a\xc2\x27\xa8\x56\x22\x37\x14\x19\x6e\x19\xe2\x2a\xe4\xac\x86\xef\xe0\x0d\xae\x6d\x7a\x2f\x20\xb9\x95\x08\xc9\xad\x40\x54\x4d\x3a\x89\x3a\x64\x55\x9c\xa4\x5c\x6c\x68\xf0\xaf\xd2\xde\xf9\xbe\x88\xf1\xe5\x81\x18\x60\x03\x2c\x67\x7b\xc8\x3e\x92\x2b\xb1\x79\x3d\xc2\x62\x44\x7d\xdc\x21\x7f\x62\xc6\x0a\xce\x93\xf4\x1b\xde\x78\xdb\x91\xbf\x32\xa7\x2a\x4a\xee\x0d\x16\xaf\xe4\xfe\x69\xc0\x70\x7a\xf6\xef\x0a\x87\x0f\x29\x2c\x84\xd0\xbe\xf8\xbd\xf6\x85\x6f\x34\x3f\xaa\xc8\xb0\x3b\xc6\xff\x9b\x0a\x47\x7b\x1d\x0e\xa8\x4b\xdf\xf3\x70\x23\xef\xd3\xe3\x80\x94\x8c\x20\xc5\xd7\xf9\x76\x72\x65\xee\x5e\x0d\x0e\x7f\x3f\x45\xff\x63\xdb\xbf\xf2\xb4\x3d\xff\x8f\x43\x1f\x16\x70\x10\xc1\xd7\x30\x8e\x78\x5c\xaf\x39\xa2\x6a\xcd\x66\x46\x6d\x9a\x82\x79\x8d\xad\xf5\xaf\x56\x9f\x5d\xfc\x05\xf7\x79\x43\x88\x0c\x18\x68\xd2\xaf\xca\xe3\x9b\x54\x8c\x76\x75\x4d\xeb\x15\xce\xff\xbf\x2e\x03\xbb\x1e\x6e\x25\xe0\x2f\x55\x90\xf5\x92\xb4\x2c\x00\x04\xb0\x00\x40\x76\xb4\x54\xe3\xbc\x44\xa0\x3e\x4e\x50\x54\xbf\xb5\xa8\xb4\xda\xc3\x17\xba\x95\xd6\xd5\x3f\xa7\x68\xeb\x00\x13\x20\x1f\x00\xe2\x1a\x83\x00\xc9\xaf\xc0\x58\x87\xb2\x98\x6e\x3e\x51\x17\x98\xca\x37\xc2\xad\xa3\x7f\x3e\xaf\xfb\x3e\x67\x2f\xc9\xeb\x7a\xfb\xab\xac\xc8\x2b\xda\xdf\xfb\x84\xba\xbb\x92\xed\x55\xb7\xc6\xb7\xd5\xa4\xb7\xbd\xca\xb6\xb4\x55\x96\x17\x1a\x17\x56\xd6\xda\x46\xd3\x1a\x93\xfa\x13\x60\x93\x97\x5d\x44\x7b\xbb\xcb\xa4\x4d\x39\x9e\xa4\x9d\xfe\x74\xd2\xe4\x75\x14\x10\x99\x8d\xd4\x9c\xa1\x99\xda\x48\xd3\xa2\xe4\x6b\x35\x75\xc8\xf9\xfc\xcf\x0c\xe0\xc0\x15\xa7\x8d\x2b\xb4\x29\x35\xcc\x28\x07\x74\xb9\x4a\xd3\x4c\x92\x4e\xfb\x09\x8a\x27\xf6\x49\xef\x05\x0e\xac\xbf\x26\x55\xff\x58\x87\x51\x57\x6f\x12\x75\x66\x89\xa6\x0d\x0d\x00\x50\x82\x3c\x79\xc0\x01\xba\x80\x74\xd0\xc7\xbc\x82\x9f\xde\xd2\xd2\xf2\xdf\x19\x75\x5d\xa6\xb6\xb7\x70\x98\x60\xdc\x4c\xaa\xf9\x2d\x55\x9b\xde\xc7\x04\x2b\xd7\x3a\x8c\xb4\x81\xdd\x0d\x85\x11\xba\xd4\x06\x38\x34\xc6\x1c\x8d\x25\xe6\xd6\xa3\xcb\x90\x9d\xda\xcc\x94\x03\x2b\x48\xc6\x67\x85\x56\x31\xf9\x99\x70\x75\x75\xbb\x12\x1d\x1d\x60\x32\x94\xf2\x9f\x1d\xda\xed\xda\x32\xe8\x00\xc1\x17\x1a\x1f\xff\xcf\x3f\xb6\xd5\x24\xb4\xcb\x58\x32\x60\xf1\xfd\xf7\x2d\x59\x34\x77\x9a\xb4\x8b\x43\x76\xaa\x33\xb4\xc1\xac\x75\xe8\xce\x1f\xd1\xf7\xe8\xb3\xb1\x7b\xa7\xa1\xeb\xa4\x2b\x23\xe3\xf7\x6f\xec\xdf\xfe\xfc\x2b\xc4\x13\xda\x18\xec\x16\xe2\xd1\x5c\xdb\x99\xe0\xe9\x27\x5f\xcf\x85\x01\x44\x2e\xd3\xc5\x60\x8b\x73\x27\x1e\xd7\x37\x6c\x51\x75\x43\xa3\xa1\xab\x32\xf1\x65\x26\xea\xfe\xa5\xee\xfd\x76\x51\xaf\x6e\x60\x3c\x79\x60\x68\x8b\x30\x99\xee\x69\x8d\xb0\x6e\x8a\x7c\x9f\x6b\x62\x0d\xda\x84\xdb\xfd\xca\x6f\xf2\x57\xf3\x75\x09\xa4\x37\xf9\x55\x0b\x39\x65\x05\xc0\x9b\x2a\x33\xa4\x7c\x7f\x9f\x2e\x16\x8d\x8f\xdc\x2e\x83\x40\x14\x88\x53\xb6\xcb\x39\x3c\x45\x73\x87\x88\x3a\xd5\x1b\xfe\xfe\x86\x06\x61\x4f\xd0\x1f\xfb\x25\xab\xc2\xc7\x49\xe5\x1a\x25\x07\x37\x5e\x55\x9b\x50\x70\x73\xa5\xca\x2a\x84\xba\xb6\xb4\x65\x18\x45\x07\xf7\xbf\xca\xa6\x24\x2f\xa7\x2a\xb7\xc8\xbf\x1d\x50\x8d\x63\x69\x3b\x2a\xdf\x0e\x50\xc4\xd2\x76\xa1\x1c\x76\x8a\x75\x75\x10\xa6\x49\x06\x54\x47\xd1\x36\xc0\x18\xe8\x40\x17\xd1\xcd\x55\x33\xd7\x3f\xb3\xb4\x66\x9d\x41\x00\xed\xb5\xab\x8d\x4d\x81\x3b\x24\xb3\xe8\xa1\x79\xb3\x39\x1b\x71\x98\xba\x4a\x25\x08\xeb\xd7\x64\xae\xcf\x90\x36\xf5\xb0\x89\xfd\xd4\x2e\x52\x45\x4b\x19\xaa\x7d\x23\x7b\x78\xd8\xc4\xf6\x89\xed\x6b\xad\x1c\x84\x55\xd4\x45\xa2\x01\xd7\xbd\x00\x52\x95\x01\x58\x25\x8c\xa0\x54\x81\x43\x8c\xa3\xe3\x6b\x03\x0c\x6c\x45\xe5\x82\x96\x05\xd0\x89\x65\x0c\x16\xb6\x38\x4e\xe3\x96\xee\x96\x82\xe0\xb1\x53\x15\xc0\x8d\xfd\x4c\xa4\xc8\x5b\x04\x78\x53\x4b\x81\xa2\xc7\xe4\xf3\x1f\x99\xdb\x3e\x2d\xe2\x56\x89\xd0\x1a\x79\x19\x06\x11\x6a\x0b\x83\xbe\x24\xc4\x8a\x93\x23\xb1\x66\x44\x3c\x8e\xfb\xf9\x85\x31\x3f\x61\xe3\x7a\x16\x9a\xb8\x87\x88\xc3\xd6\xde\xd3\x9f\x39\xf1\xdc\xc7\x0b\xf1\x5b\xbf\x66\xf4\x56\xab\xc5\x79\xb6\xc5\xf1\xaf\x1a\xb9\x9a\xde\x97\x74\x2b\xf8\x59\xb0\x91\x79\x81\x3e\x83\xf7\x10\xc9\xca\x1d\x89\x61\x39\x74\xc9\x74\x0f\x0a\x51\x04\x5d\x30\xe4\x81\x6a\xf3\xc2\xec\x64\xf0\xd3\x60\x23\xd3\x5f\xd9\x6f\xc8\x32\xec\x7d\x22\xa8\x0e\xbf\x30\x82\x82\xf0\xbc\x3f\xb9\x8e\xfb\x4d\x57\x9f\x7f\x85\xa9\xce\x25\x0a\x9e\x12\xa2\x08\x97\xb4\x51\x8b\xa8\xde\x16\x8f\xe5\x29\x19\x4b\xa4\xc1\x1d\x39\x11\x44\xa8\x2c\x6c\x59\x81\x39\x02\xf8\x82\x8d\xd1\xf7\xd1\x67\x40\x17\x6e\xe5\xe8\x69\x59\xd8\x81\x2f\xb2\x60\x92\x96\x87\xc4\x00\x08\x4f\x53\x17\xc9\x74\xd1\xff\x88\x5b\xc6\xd3\xe2\x49\xda\x45\xc5\x19\x35\x04\xdb\xa9\x63\x70\xaf\x70\x07\xa3\xf1\xed\x8a\x77\xd9\xb4\x8f\xb2\xc2\xe0\x79\x74\x13\x64\xd0\x0c\x20\x01\x20\xad\x1e\x6b\x46\x19\xba\xc9\x24\xfe\xfc\x35\xd7\x66\x90\x45\x37\xc1\x17\xf4\x2a\x10\x0f\x00\xe9\x73\xfb\x9c\x3e\xa7\xc5\x69\x71\x5b\x5d\x56\xcb\x17\xbb\x77\x7b\xf7\xec\xf1\xee\xde\xed\xad\x29\xab\xa1\xc0\xee\x3a\xdf\x9e\x3d\xbe\xba\xdd\xbe\x9a\xa6\xdd\x74\x79\x0d\xf7\xdd\x0b\xe8\x26\xac\xa7\x57\x81\x18\xae\x5d\xd6\xed\x73\x5a\xdc\x3e\x97\x35\x1d\x8e\x5a\xe9\xbb\x7c\xd9\xb7\xf2\x0e\xba\x49\x5f\xa9\xf6\x5d\xba\xe4\xad\x6e\x5a\x00\x00\x44\x63\xd0\x4d\x90\xce\x7f\x1e\xfa\x9c\x16\xd6\xea\xb2\xba\x9c\x16\x34\xe6\x0b\xdf\x2a\x38\xa6\xf4\xce\x2a\x1f\xb5\xe7\x92\xaf\xba\x29\x85\xae\xad\xf6\x72\xf2\x0e\x84\xbb\x89\x32\x62\x27\x87\x9b\xdb\x0b\x0e\x24\x3a\xc0\xdd\x4d\x4d\x3c\x17\xa1\xfe\xad\x84\x28\xa3\x8a\xc8\xfe\xe2\xbf\x95\x90\x37\x89\xb2\x6b\xd7\x84\x7f\x83\x07\xc8\x7d\xc4\x36\x40\x82\xf6\x05\xb1\x80\xa4\x68\x30\x0e\xd6\x40\x02\x82\xac\xa9\x1e\x6b\x02\xcc\xcb\xcb\xee\xcd\x7f\x67\x0a\x3c\xf0\xe5\x97\xd2\x77\x2c\x91\x7c\xc7\x62\xf8\x1d\xeb\x5b\xf8\x2b\x10\x64\x19\x7f\x98\x00\x47\x51\x16\xb9\x97\x89\x07\x24\xb0\x70\xeb\x75\x8f\x95\xb5\x7a\xac\x47\x2f\xc1\xbe\x97\x50\x96\xe5\x8b\x3b\x2c\xf7\xc3\xcd\x27\x3f\xca\x26\x8b\x83\x0d\xfc\xe7\x2c\xac\x03\xff\x47\x91\x25\xfe\x7d\xdc\x4f\xe6\x9a\xb5\x6b\xf8\xbe\x3b\x90\x1f\xc2\x5d\xf4\x41\xdc\x5a\x6e\x82\xcf\x43\x58\xd8\x0e\x89\x0f\x78\x2f\x15\xb9\xd0\x57\xe4\x85\x7b\xa0\x6d\x11\xfa\xcf\xd7\x8a\xcf\x31\x00\xd8\x12\x7c\xac\x93\x21\x3b\x0c\x4d\x81\x1d\xe2\x73\x7e\x43\x7e\x08\xbb\x9f\x49\x3c\x8e\xbe\xc4\xed\xe5\xa3\x3b\xf0\x34\xf8\x4e\xf1\xb9\xfc\xc2\x6e\xb0\x7d\xdb\x3e\x8f\xa1\x3b\x30\xa6\xd1\xf9\x27\xf4\x8d\xae\x5f\x1f\x9b\x68\x73\xa5\x11\x1d\xe2\x61\xfb\xd4\x82\x4b\xfd\xef\xa3\x77\x24\xfe\x27\x08\x6a\x60\x2c\x20\xb8\xcf\x91\x4b\xf1\xe7\xda\x82\xae\x05\x09\x14\x88\x8b\xa2\xda\x59\x2d\x1f\xb4\xfd\x73\x5b\xa2\xed\x07\x64\x2c\x09\xf2\x3d\x1d\xcf\x4c\xcd\xb1\x26\x40\x27\x47\x97\x20\x43\xaa\x56\x16\x78\x5c\x27\x55\xa2\x28\x1d\x50\xf4\xc3\x80\x36\x12\x72\x8f\x5a\xd0\x3b\x43\x53\x60\xfb\xb6\x0a\x81\x65\xb9\x09\x4e\x6e\x72\x3b\x96\x5b\xf7\x7d\x91\x80\xff\x6a\x89\x90\xf9\x50\xcb\x29\x31\x92\xaa\x65\x06\xbe\xaf\xe3\x68\xa2\xc8\x15\x04\xcb\x01\x20\xeb\x18\x3b\x88\xe5\x74\x99\x26\x59\x32\xd5\x91\x6a\x63\x6d\xcb\xa1\xcf\x07\x13\x7d\x70\x0c\x3a\xe0\x43\x5f\xfb\xc8\x1d\x3f\x24\xc3\x97\xd0\xbd\xc9\x3f\x24\xfb\x8b\xc8\xa3\x00\x82\x45\x00\x90\xfb\x19\x3b\x70\xe0\xef\xb9\x7d\xb4\xf8\x65\xa7\x85\x6f\x61\x11\x1c\x9d\x95\x85\xde\x82\xa3\x7d\xd0\xd9\x97\x6b\x27\x2b\x8b\xfb\xff\xbe\xe8\x86\x0f\x4e\xbe\x95\x72\xed\x7c\xf2\x0f\xc9\xf0\x11\xf4\xbb\xe4\x1f\x92\xcf\x5f\x4b\xb9\x95\x82\x56\xc3\x65\x00\x82\xe9\x70\x1f\xb1\x83\x4a\x07\xb1\x20\xb1\x20\x1a\x30\x71\x6d\xc8\x9a\x68\x18\x0d\xb2\xa6\x9e\x11\x95\x5b\xb1\x6f\x9c\xbe\x71\xcd\x53\x9b\xb7\xfc\xee\xe9\x4d\x44\xe3\xb6\x97\x77\x3d\xbf\xb5\xae\x0e\x9f\x2b\x54\x05\xaf\x31\xd3\x61\x1e\x88\xc5\x27\xae\x69\x05\xf6\xe4\xf6\x09\x71\x0c\x60\xba\xa5\x26\xb5\x25\xa3\xc9\xea\x49\xac\x23\xda\x06\xf2\x3d\x9e\x0c\x2b\xf0\x78\x04\x2d\xf0\x99\xec\x4d\x95\xbf\xaf\x9a\x5c\x76\xd7\x3d\x53\x4a\x4a\xa7\x10\xc3\x27\xdf\xcd\xfd\x6e\xe2\x14\x62\x84\xf8\x77\xeb\x4b\xcb\xca\x4b\xc6\xdd\x33\x69\x82\xe6\x57\x3c\x67\x78\x5b\x46\x9d\x03\x34\xb6\x65\x0e\xd6\x9a\x0e\x2f\xa1\x65\x9c\x05\x1b\xdf\xb4\x00\x40\x54\xcc\xd9\x2e\xfc\xef\x31\xf5\x14\x9e\xcc\x59\xd9\xbd\xa1\x97\xb3\x61\xa8\x18\x5e\x2a\xa5\x56\x8c\xe7\x0c\x17\x6e\x2b\x01\xdd\x04\xdf\xd1\x2b\xf1\x19\xad\x15\x5b\x39\xeb\x77\xf0\xf3\x63\x65\xe4\x39\x58\x8f\x8a\x9b\x53\xa8\x2b\x40\xf5\xb9\x58\xb1\x4f\xd6\x21\x7c\x16\x2d\x81\x6b\xf9\xcf\x8f\x47\x8d\xc2\x37\xd4\x9f\xf7\xb2\x56\xd6\x2b\xb6\xbd\x16\x2d\xe1\xdb\x2f\x86\xf6\xf1\x62\x0f\x16\x90\x1f\xfc\x2e\x06\xd0\xa7\x41\x0c\xb0\x83\xf6\xf8\x75\x98\xbe\x7c\xfc\x0c\x2b\x12\xe6\xe3\x9c\x9c\xb7\x8f\xab\x2b\x63\x83\x9e\x68\x68\xf4\x0f\xb4\xd1\x5f\xe6\xc3\x49\xaf\xbe\x55\xbf\xf7\x95\x03\xfe\xcc\x9c\x69\xd3\x72\x32\xc7\x93\x19\x37\xfd\xe7\xe1\xc7\x9a\xbf\x26\xda\xc2\xf2\x57\xdf\xda\xbf\x6f\xd7\x01\x7f\x4f\xee\x2f\x7a\x52\x04\x3c\xf5\xed\xe7\x5f\x5e\xff\xf6\x9f\x35\xd5\xfe\xa6\xe5\xcd\x2b\xe8\x83\x4d\xa3\xe0\x61\xee\x2f\xaf\x5d\xff\xf6\x32\xfe\xcb\x6a\xee\x4f\xff\xfe\x4a\xf8\x13\x67\x57\x56\x91\x75\xf0\x45\xfa\x20\xb6\xe7\x2c\xe9\x5a\x05\x9d\xe9\xc7\xe9\x83\x81\x9b\xdc\x1c\x5b\x45\xd6\x91\x45\xf8\xdf\x2c\xfc\xbf\x42\xf1\x13\xb0\x5a\xfc\x1c\xd1\x8e\xfb\x2c\xc9\x7d\x96\xfa\x4a\xf8\x6c\xac\xfc\x69\xcd\x37\xd4\xdf\xe3\xbf\x0b\x41\x09\xa8\x20\x76\x50\x14\xb6\x81\x5e\xe8\x8c\x86\x96\x12\x58\x79\x09\xdd\x80\xce\x4b\x84\xab\x23\x3c\xb9\x14\xed\x42\xbb\x96\x0a\xb6\x5f\xfe\xac\x2f\x1a\xfa\xa0\x03\x96\xc0\x44\xf4\xf5\x25\x58\x89\xd6\x9d\x87\x53\xe0\x94\xa5\x28\xaf\x23\xea\x8f\xcf\x6b\xaa\x82\xd7\xa8\x24\x7c\x1f\xd8\x16\x24\x81\x14\x00\x94\x7a\x8e\x11\x6a\xfe\x2c\xe9\x38\x05\x27\x7b\x7e\x22\xac\xaa\x3f\x8a\x3a\x4e\x3f\xe2\xcf\x42\x7b\x14\x7f\xc0\xfa\xd6\xc4\xd8\x29\x86\xb9\x8c\xd7\x01\x5e\xd6\xc1\x50\x71\x8c\xfd\xd4\x29\x8c\x19\x2d\x05\x80\xa8\xe5\x39\x66\xa1\x07\xa2\xa5\x64\xc6\xf7\xfe\xf3\xdc\xf0\x00\x01\xe7\x59\xd8\x40\x5f\x01\x31\xf8\xc4\x32\x03\x0c\x2b\x48\x8b\x4d\x64\x49\xd0\x2e\x29\x8d\xa4\x01\xdd\x33\xb3\x7d\x72\xcd\x24\x5b\x9b\x9a\x49\xb6\xf6\xb6\xf6\x51\xae\x28\xa2\x66\x52\x94\x2b\xbd\x66\x92\x0b\x64\x65\x80\xf6\x59\x19\xd6\x04\x90\x97\xd7\x3e\x2b\x2b\x23\x03\xdb\x09\xab\xd3\x63\x75\x7a\xb8\x59\x2d\x09\x67\x0d\xf7\xdb\xaa\x7d\xe3\xa7\x4d\x1b\x5f\x32\x65\xdf\xc4\x7b\xf0\x2f\xc2\x9f\xf8\x5f\x16\xfc\x61\xcc\x5d\x13\xc6\x8d\x83\x8d\x3b\x4a\x8a\xc7\x8f\x1f\x0f\x1b\x77\x8c\xc5\x7f\xfe\x96\xff\x7b\xd5\x7c\x6b\xcb\xc9\xef\xb1\xba\xbc\xdc\x7c\xf3\xf0\x73\xee\xd8\x31\xf8\xf9\xb1\x63\xe2\x1c\x92\x67\x1d\xe7\x77\xe5\xf9\x1c\x0b\x92\x0a\xe2\x41\x14\xa0\xda\x51\x5d\x28\x92\xa2\x63\x48\x9a\xb3\x04\xed\xce\x4c\xcd\xc9\xc9\xee\x2d\x4e\x76\x37\x6b\x65\xf1\x84\xaf\x84\x03\xd0\xc7\xf2\xac\x2f\x86\x76\x8c\xa3\x1d\xba\x09\x6e\xd2\x2b\xb1\xad\x61\x49\xab\xcb\x7a\x13\xfe\xeb\x78\x19\xbd\x12\xd5\x36\x7d\x4e\x77\x03\x8a\xcf\x3c\xc5\xe9\x10\x99\x04\xb9\x56\x6f\xde\xbc\x79\x9c\x33\x09\x87\xd0\x08\x0c\x8d\x10\x3e\xb3\x0a\x30\x78\x05\xe6\x73\x5a\xb8\xbe\x9d\x3e\x37\xfe\x64\x69\x4d\x4d\x0d\xb5\xe7\xd2\xa5\x83\x4d\x7e\x9a\x3a\xb8\x68\xd1\x22\xb5\xcd\x69\x23\x71\xa0\x60\xa0\x83\x44\x00\x7a\x51\x96\x1f\xa4\x13\x5e\xe2\x0b\xfa\x34\x88\xc6\xde\x04\xdb\x83\x76\xac\x60\x0e\x84\xd3\xd6\x74\x6e\xa2\xa3\x9d\xbb\x0e\xf8\x33\xb3\x73\x7a\xf5\xca\xc9\xce\xe4\xa7\x3a\xf2\x70\x53\xfd\xb1\xdf\xd6\x2c\x5f\xce\xb7\x15\x47\x8c\x22\x6e\xd3\x47\x40\x0c\x48\xc0\x33\xc9\xc3\x75\xef\x70\x79\xdd\x1e\x6f\x1f\x5f\x3c\xb4\xc4\xc1\x15\x8d\xd5\xd5\xdf\x9d\x38\xc1\x44\x7b\xdb\x12\x57\xb6\x11\x85\x81\x33\xbb\xb7\x6c\xd9\xbd\xab\x6c\x7a\xc7\x87\x9c\xfc\xfc\x2a\x25\xf2\x88\xd3\xf4\x41\xd0\x91\x6b\x21\x19\x72\x36\x29\xcd\xd5\xd5\xe2\xb6\xb1\x0e\xd6\x22\xcd\x96\xd2\x9c\x55\xbe\xbd\x77\x4f\xc8\xef\x3b\x2f\x95\x88\x42\x2f\xb6\xeb\xdb\x6f\xfd\x1f\x8f\xbe\xbd\x9d\x98\xf7\x41\x97\x1e\x2b\xf3\x0b\x12\x32\xe0\xa1\x43\xab\xa3\x36\xfd\xb6\x76\x07\x87\xcb\x43\xe4\x11\x97\xe9\x53\x42\x75\xd1\x3e\x09\x9e\x1c\xa7\x83\x13\xcc\xe2\x91\xa7\x9f\x52\x60\xcf\x4f\x37\x06\x0f\xe8\x95\xbb\x76\x4d\x54\xd4\xf0\xdf\x3c\xfa\xf4\xc1\x8d\xbb\x8e\x5c\x2a\xf2\x79\x8b\xfa\xf6\xef\x3b\x94\x3c\xdb\x0c\x82\x6d\x8f\x24\x2e\x5c\x39\x7d\xe3\xe3\x4f\xef\x39\x5f\x59\x58\x3a\xac\xd0\x57\x54\xc0\x61\xef\x4f\x8c\x22\x2e\x08\x6b\x2e\x2f\xeb\x80\x2e\xd8\x9f\x78\x11\xbd\xef\x87\xa5\x14\x3a\xb4\x29\x90\x4e\x1c\xe0\xe3\xe9\x32\x09\x2f\x71\x89\x3e\x0d\x9c\x80\x15\x5e\xf5\xf2\xc9\x97\xef\x96\x64\x42\x8d\xc8\xcd\xd8\xec\x89\xce\x41\x90\xc7\x96\x39\xfc\xee\x9a\x7d\x6b\xd6\xed\x1e\x3c\x66\x74\x91\xeb\xfd\x2d\x2f\xbd\x7d\xa5\x5f\x5e\xff\x01\xab\x1e\xe8\xdc\x27\x2d\x2d\xa7\x47\xef\x8c\x4c\x32\xaf\x70\x6e\xaf\x49\xbf\x99\xfd\xe8\xb2\x39\xf9\x33\x32\x7a\x0c\x1c\xd9\xb3\x6a\xd3\xda\x47\x32\xf3\xf2\x32\x27\xf4\xec\x09\xef\x4e\xcf\x71\xd8\x72\x32\x3a\x67\x65\x01\x02\x64\x10\x79\xc4\x79\x99\x17\x89\x0c\xb7\x17\x47\x23\xba\xb4\xbc\x64\x70\x4c\xdc\xbe\x3e\x32\x37\xdb\x23\x72\xf3\x45\xdf\xfe\xbe\x61\x43\xbc\xde\x22\x6a\xf3\x53\x7b\xce\x7f\x88\xfc\x02\x35\x8f\xf9\x0a\xf3\x33\x06\xdf\x35\x1c\x8f\xe9\x4c\xc2\x4f\xc6\xd0\x27\xb1\x56\x58\x3d\x4e\x4f\xae\xa7\x8b\xc3\xea\x12\xa3\x5e\x66\xee\x4c\x8a\x1f\xf9\x0c\x24\x4e\x0c\xc8\x9b\x3c\x82\xf0\x13\x87\x4b\x1f\x68\x42\x59\xb0\x76\x4c\xc1\xb4\x45\xe8\x00\x37\x7e\x93\x83\x77\x91\xd9\xc4\xa3\xa0\x3d\x87\xd3\xd7\x27\x37\x1f\x72\x8e\xca\xe2\xc6\x80\xad\x2e\xfe\xd8\x22\xcd\x67\xf7\xe4\xe4\x0e\x84\x96\x78\x38\xf9\xc0\xdb\xeb\x6b\xee\x7f\x7c\xd4\x33\xaf\xee\xda\xff\x42\x4f\xa6\xef\x63\x93\x1f\x7e\xf2\xea\xbc\xb1\x53\xcb\xef\xab\x18\x59\xbd\x84\xa1\xbb\x2e\xcd\x5b\x3f\xec\x77\x6b\x02\x4d\x73\x86\xe6\xac\xa8\x9a\x5c\x36\xb4\x80\xa2\xfa\x03\x02\xcc\x0e\xde\x45\x96\x11\x8f\x00\x1b\xa7\x7d\xbc\xad\xee\x0c\x59\x7c\xef\x20\xdc\x05\xb3\x18\xf3\xec\x3f\xbd\xfd\xc7\xa3\x81\x9f\xc8\x39\x15\xe3\x56\x0c\x9d\xff\xc6\xc7\xff\xfc\x12\xfa\xc6\x8f\x1c\x3c\xf1\x5f\x1f\x5e\x38\xf2\xca\xcc\xc9\x33\x93\x53\x76\xf9\x3e\x83\x9d\xc7\xde\x3d\x8e\x9f\x17\xb3\x83\x13\xc9\x6a\xe2\x51\xbc\x26\x52\xf9\x00\x25\xb9\xb3\xff\x7c\xf4\xcd\xbf\xfe\xe5\x9d\x03\x7f\xfb\x77\xf1\xe4\x49\xe3\xc6\xdd\x53\x5e\xfc\xd5\xd1\xbf\xfe\xfd\xf0\xd1\xf3\x7f\x7f\xb7\xf2\xe1\x87\x2b\x97\x2c\x59\x82\xb9\x74\x07\xa7\x91\x4b\x89\xb9\x9c\x8f\x73\x46\x43\x8f\xd3\xe7\x89\x86\xae\x58\xe8\x86\x09\xa8\xc9\xbf\x63\x47\x33\xba\x0d\x9d\x68\xcf\xde\x1d\xf0\x19\xf8\xd8\x7f\xff\x8b\x9e\x40\x8b\x61\x0c\xba\xcd\xe3\x98\x1e\xbc\x8b\x9c\x46\x3c\x02\x12\x40\x07\x00\x7c\x5e\xb6\x17\x74\x75\xb5\x78\x15\x70\x78\x51\xa7\x13\x9d\xc9\x79\xf7\x6d\x5d\xfd\xf0\x1f\x3f\xfd\xd7\xd9\xc3\x7f\x3c\x71\x8e\x28\x1b\x35\xf4\x1e\xe6\xcd\x59\xf7\x3c\x30\xf0\xe5\xbe\x7f\x3e\x72\xec\x6f\xef\xfe\xb6\xb8\x6c\xdc\x44\x8c\x27\x03\x00\x6a\x06\x7d\x1a\xbf\x2e\xde\x8e\x9b\x59\x96\x34\x57\x57\x2b\xb7\xcf\x16\xf6\x30\xdc\x7f\x56\x57\x57\x22\xe3\xa7\xab\xf5\x1b\x26\x3f\x3c\xa9\x61\xd6\x54\xa2\x0c\xbd\x07\xd3\xd1\x05\x38\x38\xb0\x27\xee\xc6\x77\xe4\x7e\x48\xc2\xf6\x43\xbe\xc9\x43\x5f\x3c\xfb\x32\x01\x97\x7f\xb9\xe9\xda\x1b\x37\xe0\x36\xc8\x6d\x5b\xc1\xa8\xe0\x53\xd4\x6e\x26\x01\x24\x83\x6e\x5c\x5f\xb6\x76\x20\xd5\xe7\xb1\x24\x3a\x7d\x1e\x6e\x2f\x4b\x72\x03\xd3\x16\xba\x7c\x69\x6e\x8b\xcb\x97\x46\xa4\xda\x9d\xb6\x78\x68\x4b\x74\xda\xd2\x32\xe0\x28\x98\x09\xe3\xd8\x4d\xc9\xa3\x87\xb1\x9b\xd2\x17\x4c\x2f\xda\xf9\xc8\xf3\xdb\xf6\xb0\x9b\xd8\xe2\xa2\xd4\x4d\x59\xdb\xb7\x40\xcf\x90\x35\x33\x1e\xfc\xc8\x77\xf7\xde\x41\x03\x9d\xc4\x45\x68\x87\xb3\x5c\x2f\x3c\x47\xc5\xbd\xfc\xa7\xcc\xdb\x29\xfe\x6b\x6d\xf3\xfc\x85\xd1\x3b\x77\x92\xf6\x77\xbe\x9e\x00\x07\x5c\x78\x6f\x26\xb1\xaf\xf7\x27\x81\x7f\x76\xb2\x90\xe3\xdb\x01\x08\x46\x05\x1b\xa9\xd9\xf4\x19\xfe\xfd\xc7\x84\x6e\x9c\xe0\x1c\x9d\x84\xa3\x9d\x53\x0c\xed\xc2\x54\x74\x86\x58\x77\xba\x80\x51\xdb\x60\xb7\x93\x27\xff\x32\xe3\xa1\x75\x7d\x5f\x7e\xf3\xdc\x11\x57\x9c\x6b\xd6\x84\x5e\x9d\x52\xda\xb3\x75\xcb\xa6\xef\xbd\x8c\x1a\xd0\x71\xa2\xe1\x3a\x9c\xfc\xce\x9c\x1f\x72\x7b\xa0\x1f\xbf\x47\xd5\x65\x44\xcd\xe6\x51\x93\x63\x9a\x62\xbe\xf8\xa0\xa3\xdb\x3f\x1a\x3e\x8a\xf9\x76\x01\x40\xb9\xe9\x83\xc0\xca\xd9\x18\x8f\x18\x4a\xe5\xe0\xc3\xa9\x5c\x9b\xc8\x05\x81\x8f\x88\x0e\x81\xeb\x9c\x73\x42\x67\x21\x53\x4f\x22\x84\xf6\xa3\xfa\x7a\xd4\x04\x19\x7e\xfd\x02\xa8\xb9\xf4\x69\x0e\xb7\xc7\x3b\x08\xfa\x5c\x5e\x8f\x97\xfb\xe1\xb4\x52\x28\xaf\xdd\x19\x0a\x2d\xc6\x43\x0b\x6b\x2d\x99\x31\x9a\xae\xaf\xaf\xaf\xff\xf7\x85\xa3\xc7\xa6\x16\xaf\x1c\x3a\x7e\x0c\x9c\x85\x9e\x87\xb3\xd0\x16\x7a\xd8\x28\xe2\xb3\x3b\x3d\xe6\x4e\xac\xaf\xdc\x5f\xf9\xd9\x5f\x4b\xbe\xec\xec\x2a\x2b\x5b\xb4\xbf\xb2\x7e\xd4\x43\x6e\xe4\x07\x10\xec\x08\xa6\x58\x8a\xe8\x52\xd0\x5d\x11\xef\xe6\xb4\x79\x78\x33\x2e\x87\xbd\xb1\x5e\xd2\x25\x58\x37\x87\x75\xc7\x8d\x74\x6b\xe6\x9e\xf9\x9f\xdd\xb7\xfd\x4c\xe5\xf0\xd1\x47\x8f\xa1\xcf\x26\xdc\xbd\x70\x01\x3a\xbb\xed\x53\x38\x73\xc2\xdd\x55\x73\xa9\x8a\xf5\x63\xef\x5e\x04\x4b\xee\x38\x8f\x5d\x08\xb8\x89\x75\xcb\x96\xed\xd8\x17\x38\x3b\x1b\xbd\x4d\x12\x0f\x2d\x5b\xb6\xf7\x78\xe0\x16\x5f\x0b\xd1\x0e\x00\x55\x43\x1f\x04\x49\x38\x1b\x22\x0d\xf4\xc0\x7c\x71\xa2\x5a\x59\x9b\xc7\xca\xbb\x26\xce\x3b\xb2\x24\xe7\x21\x6d\x4e\x0f\xe9\x71\xbb\x58\xa7\xc7\x4b\x3a\xd3\xdc\xf6\xa5\x4b\x97\xc2\xa2\x5d\x07\xaf\x56\x55\x55\x55\xa1\xf7\x76\x1d\xf8\xf7\xb9\xb8\xf4\xae\x2b\xb3\x4a\xa1\x27\xbb\xd4\xe5\x25\xa3\x61\xd3\x96\x8d\x5b\x60\x13\x62\xb8\x9f\x2d\x1b\xb7\xf0\xbf\x81\x4d\xc4\x43\x7b\xd0\xf9\x8d\x1b\x37\xa2\xf3\x3b\x3b\xfe\x8e\xd3\xdf\x43\xc1\x46\xe6\x06\x7d\x10\xdf\x71\xa4\xe3\xd3\x29\xfd\x3d\x8d\x37\x1f\x7a\xf0\x08\xca\xc7\x52\x5e\xeb\x21\x58\x05\xdb\xc1\x24\x74\x16\x5d\xf7\x16\xad\x59\xf7\x9b\xdf\x95\x12\x93\x77\x97\x6f\x83\xed\xd0\xcd\x11\x9e\xe2\xbb\xee\x7b\xfa\xe5\xcd\xf2\x8d\xcd\xec\xaa\x79\xb3\x03\xc7\x1f\x9a\xf5\xcd\xb7\xe7\xd0\x99\x01\x83\x5d\x67\x3d\x75\xaf\xc3\x41\x5c\xff\xdb\x82\x8d\x96\x04\xfa\x20\x8e\x63\xe8\x8f\xfb\xe7\x3c\xbc\x25\x31\xc1\xc3\x92\x4a\x0c\xf2\xf8\x3b\xec\x89\x4e\xd1\x07\xb9\x45\x17\xec\xee\x05\xb7\xc1\x9a\x1f\xfe\xb7\xe1\xde\x53\x10\x7d\xf0\xdd\xe4\x11\x73\xa7\xde\x3f\x7b\x08\xb1\xe1\xe3\x7d\xaf\xfd\x61\x54\x51\xd5\x80\x79\x03\x7f\x33\x7f\x6a\xaf\x53\x27\x66\xad\x2b\x1c\xfa\x6a\xfe\xea\x61\x8f\x3e\x3b\x93\x3e\x78\xf6\x32\xfa\xcf\xfc\xf3\x68\x08\x91\x1d\x38\x4b\x66\xce\x9a\x31\xbb\x1c\x2d\xdb\xba\xa7\xfc\xf3\x6e\xbd\xc6\xa6\xfb\x0a\xfa\x96\x2f\x29\xdd\x7b\xa0\x0b\xeb\xef\x9e\x3b\xad\xd7\xe0\xc1\xa3\x36\x02\x6e\x5f\x63\x07\x80\x3e\x47\x1f\x04\x29\xc0\x05\xdc\x20\x03\xf4\x02\x39\xc0\x8b\xc7\xce\xed\xf2\x7a\x48\x8f\xcd\x63\x63\x6d\x1e\x9b\x87\xf4\x38\x5c\x16\x8f\xc3\x45\xb2\x24\xf7\x63\x73\x7a\x7c\xa4\x33\x37\x1f\x7a\xdc\x2e\x9f\xc7\xcd\xff\xd1\x67\xdf\xda\xa1\x66\x56\xe9\xf5\xe2\xf7\xca\x21\x55\x76\x74\xcc\xf5\xd2\x39\x2b\x3a\x6c\xab\x2f\x45\x57\xa6\xbc\x37\x19\xfd\xab\x74\x5f\xe2\x94\x0e\xd3\x12\x69\xfb\xd5\x95\x1d\x8b\x13\xd2\xed\x3f\x26\x55\x38\xa6\x74\x74\xaa\x86\x56\x33\xbc\x30\x83\x1b\xda\x33\x23\x9f\xd8\xb2\x71\xcb\x7b\x68\x2f\xfe\xc3\x19\x21\x57\xe4\x08\x1d\xc7\xd8\x41\x47\x90\xcc\xdb\x29\xce\x16\x7a\xd2\x06\x42\xd6\xcb\x7a\x59\xac\x69\x2e\x21\x03\x80\x75\xb0\xca\x78\x7f\x66\xca\x97\x9f\xfc\xed\xa1\x18\x27\x3a\x0e\xfb\xc3\x9c\x17\x5e\xf8\xba\x7f\x9b\xd9\xe7\x4f\xfc\x6b\x19\x59\xe2\xdf\x77\x64\xf1\xdc\xaa\xf9\xd4\xa2\xe5\x33\x17\x11\xf1\x90\x81\xec\xae\x95\x0f\x78\x4e\xbe\xf4\xd2\xc9\xe6\xd2\xda\x57\x60\x37\xd4\x77\x2d\x59\xbc\x69\x73\xf5\xc6\x4e\xbb\xd6\xfd\x1e\x40\x50\x14\x6c\xa4\x56\xd2\x1f\x02\x37\xe6\x2b\xcd\xcb\x4d\xee\x5c\x20\xcd\x6b\x0b\xb7\x84\x72\x38\x59\x07\x9b\xc8\xe6\xf8\xac\x8c\xab\x2b\x70\x17\x3d\x4c\x11\x4b\x56\xa5\xc2\x21\x3f\x1e\xd9\x35\x7d\xe8\x23\x85\x8f\x6e\x77\xc2\xe7\x50\x05\x41\xc0\xfb\xd1\x3e\x0f\x8c\x5f\xff\xc4\x92\x37\xfe\x83\x3e\x4e\x87\x57\xea\x9d\x6e\xef\xfe\x5b\xb0\x43\xc9\x57\x29\xae\x75\x4f\xee\x77\x65\xb1\xf5\x3f\xe6\x05\x41\x7f\x18\xf3\x0d\x67\x57\xda\x01\x40\x3d\x47\x1f\xe4\xc6\x0f\xdb\x25\xab\xc7\x07\x59\xc8\x3a\x5c\x90\x85\x16\x2b\x6b\x6d\xb7\x12\xe6\x24\x8c\x82\xd9\x30\x1f\xdd\x0f\x07\xdf\x81\xa5\xe8\x2d\xf4\xf1\x70\xf4\x19\x31\xef\x04\xb1\x32\x50\xbd\x15\x7e\x13\xa8\x3e\x11\x78\x8e\xa8\xf0\x04\xce\x13\xf3\xf8\xb5\x60\x3a\xb6\x55\x07\x71\xdc\xb7\x95\xb3\x73\x3e\x27\xcd\xfd\x58\x59\xaf\xc5\x9d\xca\xfd\x58\xd3\xa9\x42\xb4\xf4\xdd\x32\xf4\xfd\x3b\x65\xe8\x07\x74\x76\x5f\x29\x24\xf6\x96\x41\x82\x3a\x00\x09\x84\x4e\xac\xa8\x7e\xf7\x60\x4d\xf5\x21\xe4\x6d\x5a\x5a\xbd\xff\xe0\xc3\xd5\xfb\xe1\x16\x6e\xac\xd2\x91\xdd\x72\x81\x3e\x0d\x3a\x08\xf9\x5c\x83\x20\x7f\x56\x4c\xb9\x58\x1b\x4b\x7a\x72\xc4\xe3\x62\x0b\xb4\xf1\x21\xba\x76\x21\x81\x23\x1e\x92\x36\xd9\x63\x5b\xd2\x47\xfb\x1f\x83\x25\xf0\xb7\x9f\xa2\xb5\xdf\xa2\x1d\xdf\x41\xf7\x3b\x6d\x37\x5f\x7b\xf4\xe6\x07\xa5\xef\x8c\x23\x37\xfc\x4f\xcf\x73\x87\x5f\x7b\x7b\xca\xfe\x65\x43\xe7\x76\x8c\x62\x1c\xe3\x9e\x4f\x9b\x35\xfa\xbe\x82\x7e\xc3\xee\x4e\xa4\x17\xb9\x3d\x68\x2f\xba\x10\x40\xbf\x39\x4b\x55\xf8\xb7\x6d\x81\xb6\xfd\x7b\xcf\x77\xeb\xf6\xf3\x53\x64\xea\x67\x6f\xbd\xb6\x7d\xf1\xfe\x07\xd2\x3b\xf5\x99\x8f\x56\x11\xff\x2c\xae\x9c\x3c\xb4\xf8\xfe\xf9\x80\x00\x00\xd9\xa9\x45\xf4\x19\xd0\x15\xf4\x04\x20\x1b\xda\x7c\x72\x34\x06\x61\x49\xb0\xca\xcb\x36\x6e\xb2\xc6\x42\x0b\x14\xd6\x8c\xae\xae\x70\xe0\xae\xea\x67\xee\xfa\xf4\xed\x7d\x87\xee\x7b\xe4\xdf\x1f\xbf\x3d\x62\x44\xef\xfc\x9c\x81\xb9\xa3\x3f\xdf\x3d\x17\x9e\xeb\xdb\xb3\x7b\xaf\x8a\x29\xc4\x18\xd4\xf0\x09\xfa\x76\xd6\x47\x7f\xf9\xf8\xad\xe5\xe8\xbf\xaf\xa3\x79\xe8\xc6\x1b\x07\x6c\xdf\xd8\x0b\x07\x8c\x7b\x7f\x3b\xda\x01\xa3\xce\x52\xc3\x86\xfc\x71\xe4\xf0\x03\xa3\x9f\xe3\xf6\x8b\xb2\x6d\x65\x81\x9b\xc3\x23\x59\xd6\x2e\x36\x8f\xc3\xe5\x74\xd8\xb9\x99\xc9\x50\x19\xd0\xca\x5a\x69\x4e\xd1\x59\x2f\xeb\xf3\xba\x59\x2f\x9b\x96\x01\xed\x55\x55\x55\x70\x2f\xac\x1d\x33\x6f\x32\x41\x4d\x59\x96\x8b\xbe\xfd\xdc\x8d\xce\xc2\x6c\x76\x62\x55\x57\xf4\x23\xec\x47\x10\xe8\x04\xec\xd0\xfb\xb1\x79\xc4\x85\x75\xcb\xd6\xc1\x31\xe8\xc0\x3a\x67\x62\xcf\x2e\xeb\x5e\x7e\x0d\x2d\x25\x2e\x94\x77\xef\xbd\xae\xcb\xa0\xa4\x75\x77\x03\x12\x2c\x0d\x4e\xa1\xfb\xe3\x73\xb0\x4e\x80\xe5\xd7\x06\x5e\x8f\x23\xd1\x69\x49\x73\x5b\x59\x2b\x63\x71\xb8\xbc\xdd\x00\x47\x84\x35\x1e\xc2\x5c\x9f\xd5\xb5\x14\x7a\x61\x4a\xfd\xb7\x67\x67\x6e\x3f\x04\x8f\x7e\x80\xea\xd1\x3f\xd1\x67\x30\x7f\xcd\xd3\x2b\x37\xc0\x93\x33\xd3\xd7\x13\x97\x61\x0e\x5c\xd1\xab\x6c\x24\x55\x76\x67\x0c\x85\x1e\x0a\x10\x85\x51\x1b\x36\x26\xc2\xdf\xc2\x09\x27\x7f\xea\x4a\xd6\xe7\xdc\x0a\xcc\xa4\xa2\x60\x9e\x98\xab\xe2\xc1\xba\xc9\xb1\x00\xb2\x6d\x2e\xaf\xc7\xe7\xf2\xb2\x36\xd6\xc6\x3a\x5c\x4e\x8f\xc3\x65\xe3\x73\x35\x38\x7b\x94\xe6\x8e\x87\xdb\x9f\x7e\x2f\xfb\x3b\xc8\xbe\x0b\x4b\x0e\x43\xd7\xcd\xec\xf7\xd7\xee\x40\xa7\x6b\xd1\x94\x8d\xc7\xe0\xd0\xcc\x1b\x59\x6b\xfa\xc7\xc5\xf5\x82\xe7\xb6\x6c\xdc\x42\xb8\x02\x97\x39\x8b\x93\x05\xcf\xa1\x2c\x62\xf6\xc6\x2d\x7f\x1d\x9d\x7f\x94\x9f\x0f\xf6\x60\x23\x55\x4d\x9f\xc6\x79\x0b\x5e\x0f\x66\x55\x54\x45\xb7\x10\xa0\xe6\x71\xb8\x38\xaf\xed\x60\x19\xfe\xb6\xce\xca\xb0\x5d\xbb\x79\xfb\xf8\xec\x6f\x0e\x7b\x02\xad\x24\x5e\xf7\x4e\xbb\x67\xf4\xef\x1f\x9e\x72\xf5\xe6\x3f\xfe\x6b\x9d\xf3\x7e\xaf\x65\x45\x70\x77\x60\x88\x7b\xee\x83\xa7\xae\x1d\x41\xcd\x37\x11\x6a\x0b\x9b\xb6\xdc\x55\xb8\xc5\x53\x3c\x78\x64\x5a\xef\x1f\x66\x35\x7c\x58\x94\xb7\xc5\x33\xa4\xf3\x96\xcc\xa2\xd1\xa5\x15\x08\x4d\x69\xf8\xb4\x9f\x17\xaf\x25\x97\x06\xa7\x50\xe7\x18\x3b\x48\x04\x9d\x34\xcc\xe7\xfa\x24\xea\xdb\xd1\xd6\x78\xb8\x14\x0e\x82\x89\xf5\x6f\xbc\x3c\x63\xe3\x94\x05\xfb\x36\xac\xa9\x47\x5f\xa0\x33\x30\x1f\x3a\x9e\xa8\x25\x2e\xc2\x42\x58\xdb\x69\xec\x58\xfb\x38\xff\x50\xab\xbf\x4f\x9b\x01\xc8\xdf\x2f\x76\xf3\x06\x1b\xac\x81\x77\xa3\x49\xfd\xc8\x4f\x52\x02\xf8\x8c\x08\x00\x8a\xa5\x0f\xe2\x68\x32\xaf\xa0\x4e\xbd\x60\x06\xf4\x72\xa6\x8c\xa3\x9a\xa0\x21\xbb\x6a\xf9\xbc\x0d\x0e\xb4\x08\xae\xb3\x3f\x3a\x75\x27\xf9\x22\x3a\x3a\x22\xe1\xab\x7f\xa7\xa1\xc3\xb0\x16\x6d\x24\x56\x6e\xbd\xf7\xee\x2d\x65\xf7\x6d\xd9\x52\x3c\x67\x0b\xba\x52\x18\x58\x8f\xf9\x8c\x09\x36\x52\xd3\xb1\x1e\x03\x9b\xd7\xe7\xb5\x78\x7d\x56\xd6\x91\xea\xa0\xb9\x1f\xeb\x20\xe8\x65\xdb\x01\xb6\xab\xdb\x1a\x73\xf2\xe4\x49\x98\x01\xf3\xd1\x87\xdc\xcf\xde\x9d\xb0\x3d\x7a\x06\xbd\x30\x7f\x0c\x91\x55\x3f\xa4\x66\x48\xfd\x10\x38\xad\x69\x41\xfd\x82\x9a\x05\xfb\x17\xa0\x98\x4e\xd7\xaf\xa1\x5d\x68\xb9\x9d\xa8\x04\x10\x59\xc9\xfe\xf0\x7b\xe6\x67\x10\x0f\x00\xf4\xe1\x23\x5a\x27\x6d\xb3\xc4\x42\xb7\x0d\x59\xdd\x70\x5e\x3a\x64\xd2\x61\x15\x8b\xf6\x7e\x71\xf5\xc5\xa7\x1a\x2f\x53\xff\x6d\x9a\x0d\x17\xa2\x67\x67\xfb\xdb\xa3\x0b\xcb\x60\x1e\x3a\xb5\x14\xa6\xe3\xf3\x99\xfc\x60\x23\xd3\x99\xfe\x10\x9f\xf4\x75\x93\xde\xfe\xc2\xcb\x4b\xc6\x61\x97\x02\x55\xa1\x27\x1a\x9a\x6c\x2e\xf2\x0f\xbe\x5e\x35\xc3\x37\xb3\x60\xe4\xc8\xb5\x4b\x26\x8f\xab\xfc\x9f\xa3\xc7\xf9\x43\xbd\x35\xf5\x3b\x36\x1f\x7c\xeb\xf7\x9b\xde\x3e\x3d\x68\xf8\x90\x81\x03\x87\x0c\x1f\x44\x95\xd5\xbf\x93\xf3\x42\xfa\xcc\x7b\x8f\x66\xec\xca\x3c\xe4\x2f\xc5\x87\x78\xe5\x7b\x3e\x3c\xb9\x6b\xef\x07\x1f\xef\x9e\xf1\xc0\x03\x33\x66\xdc\x7f\x3f\x20\x40\x7a\xf0\x3b\xf2\x0b\xfa\x14\x48\x02\xdd\x38\xf6\x72\x7d\x56\xc9\x1a\x71\x90\x84\xab\xe3\xb4\x81\x10\xf2\x56\x88\x71\xa4\x4f\x2f\x3d\x72\xfc\xe5\xa3\xa7\x6f\x55\x0f\x18\xcb\x9c\x8d\x3d\x74\xf8\xed\x4f\x61\x6a\x79\xc5\x64\xaf\x1b\x9e\xfd\xb8\x63\x27\xf8\xc2\xa1\xd7\xf7\x6d\x3e\x80\x82\x0b\x6f\xbc\x73\xff\xcc\xcf\xdf\x3b\xfb\x71\x0d\xf4\xb9\x77\x2f\x5b\x33\x26\x9f\xe3\x60\x35\x00\x96\xef\xe8\x83\xc2\x49\x5a\x06\x5e\xc9\x40\x4f\x9a\x97\xf3\x0b\xd0\x95\xe0\xb0\xaa\xce\xd2\xa4\xd4\x56\x5e\xfc\xd5\x70\x14\x6c\x4a\x68\x0f\x63\xd0\x21\x44\xc4\xb7\x27\xdf\x3c\xb0\x73\xdb\xa1\x43\xdb\xb7\x1d\xb2\x13\x35\xc8\x57\x38\x72\x78\x41\xc1\xf0\x91\x85\xf4\xc1\xe6\x9b\x37\xf6\x10\xd5\x4d\xa3\x28\x27\x0a\xbe\x14\x58\x43\xd4\xec\xfe\xe8\xe4\xcb\xaf\x7d\x74\x02\x75\x3f\x72\x84\xa8\x11\x85\xc7\x63\x32\x23\xd8\xc8\x0c\xa1\x4f\x83\xb6\x20\x05\xf4\x00\x39\xe2\x2e\x80\x4a\x70\x70\x7e\xa4\x6b\x37\xc2\x67\x4f\xa0\x3c\x39\xdd\x12\xbc\x7d\x88\x6e\xae\xae\x14\x01\xad\xfc\x59\x6b\x06\xec\xc0\x2f\xa9\x32\xe0\x8c\x4f\x60\xc5\x9f\xb8\x9f\x8f\xd0\xce\x3f\x9f\x45\x3b\x8f\xcd\xdb\x0b\x33\xf6\xee\x85\x3d\x5e\xdf\x8b\xce\xef\xdd\x8b\xfe\xf6\x3a\x5c\x06\xb3\x76\xbf\xf0\xea\x93\xbb\x9f\xdd\x73\xd7\xa4\x67\x88\x4b\xf8\x0b\x68\xe7\x9f\x8e\xa3\xba\x3f\x9f\x85\x93\x4f\x70\x9f\x51\x7c\x27\xb0\x91\xac\x59\xb7\xf6\xf1\x97\xd1\xfb\xf0\x83\x9d\x13\x46\x72\xf3\xd4\x45\x5c\xa3\x57\xe3\x7b\x8a\xf6\xfc\xa9\x04\xb7\xda\x85\x56\x4f\x12\xf4\x58\x5d\x56\x9f\x8b\x74\x91\x2e\xa7\xd5\x45\xb0\xe7\x56\xc0\xe7\x3e\xfc\xe0\xe4\xe1\x95\x4c\xd4\xd9\x87\x8e\x47\x31\xf4\x88\xf9\xf3\x03\xbf\x27\xee\x0f\xfc\x9e\x38\x17\x38\x4f\x64\x04\xb2\xe0\xce\xa7\xb8\xdf\xd4\xa0\x52\x00\x81\x0f\x00\x26\x01\xdf\xb9\x86\xbf\x71\x0d\x71\xc7\x1a\xd9\x13\x62\x80\x00\x33\x83\x97\xa9\x35\xd4\x08\x5c\x3d\x99\xe3\x9a\x1b\xec\x04\x07\x6b\xe5\xb7\xac\x4e\xac\x6c\x84\x8f\xb5\xe2\x3d\xed\xcc\xa7\x7f\xda\xb4\xf5\xc7\xd5\xfe\xe3\xd9\x75\x25\x2b\xdf\x9e\x30\x62\xfa\xc5\xad\xbf\xff\x61\xd5\xd7\x44\x69\xce\xcb\xe5\xaf\x3f\x4a\x24\xbc\x06\x82\x6b\x9f\x41\x81\x57\xd0\x8b\xde\x61\x73\x56\xa4\xbf\xf0\xd8\x73\x90\xfe\x11\x3a\xbc\x45\x55\x78\x6c\x63\x82\x77\x18\x06\x73\xd6\x06\x58\xb9\xd5\x67\x12\xf4\xd8\x5c\x6e\x97\xc5\xe6\xc9\x82\xf1\x90\x84\x1e\x98\xea\x15\xc3\x11\xdd\xbd\x08\xaf\x72\x3a\x26\x3a\x93\x21\xd6\xc2\x98\xa6\x2f\xd0\x9f\x72\xae\x66\x4f\x5b\xed\x8b\x27\x2d\x16\x7e\xc2\xbd\x38\x70\x76\xdf\xdc\x41\x85\x9e\x7b\xc6\x66\x3e\xf3\xbb\x25\x4f\x7a\x6a\x8a\x53\xdd\x85\x43\xaa\xc6\xbf\xb0\x61\x25\x71\x9b\xf8\x20\x50\xb0\x65\x0b\xf4\xec\x19\xd8\x36\xb9\xb9\x33\x37\xf3\xd2\x77\x3a\x93\x9d\x9d\x3a\x76\x49\x4c\xcd\x1b\xe3\x9d\xb6\x28\x7b\x6b\x46\x92\xbd\x13\xdb\xa1\x67\xc5\xc8\x39\x8b\x85\xbb\x52\x00\xc8\x51\x54\x05\x88\xe6\xf6\x73\xfc\xbd\x01\x6b\x1d\x08\x3f\x47\x63\xe1\x9b\x30\xfb\x1a\x6c\x73\x0d\xae\x6e\xde\xc9\x9f\x3b\xf5\x0b\xde\x64\xf6\xe1\xbd\x48\x3c\x8e\x16\x4a\xe5\x54\x20\x1f\x32\x6d\xa1\x0d\x8b\x94\x28\xe8\xa5\x57\x5e\xe2\xb8\x85\x05\x90\xc5\x21\x48\xd5\x0f\x66\xbe\xff\x1d\x49\x27\xf5\x2e\x7e\x0e\x9f\x22\x13\x31\x1b\x97\xaf\x2f\x2f\x5e\x38\xe5\xae\x09\x39\x9e\xac\xd2\xbc\x07\x06\x6d\x99\x55\xb3\x73\x4f\xc5\xec\xfd\x87\xd7\x53\xa7\xbf\xf1\x6f\x84\x47\x17\xde\xdb\xad\xc7\xc0\xe6\x03\x9c\x3c\xb9\x47\x27\x3f\xe8\xf5\xee\xe8\x93\x97\x96\x93\xd6\x7d\x5d\xd6\xa0\xdf\xce\x5e\xef\x6b\x63\x9f\x3f\x6e\xd9\x1a\x0e\x5f\x72\xf0\x26\x73\x87\x3e\x0d\x12\x41\x47\x9c\xc9\x2c\x4c\xe8\xb6\xdc\x7e\xd4\xeb\x13\x4e\xc0\x2c\xd1\x11\x63\x4d\x7e\xee\xbd\xa7\xb6\x57\xac\x98\x03\xa7\x05\x96\xfd\x6b\x66\x5e\xef\xee\x13\xee\x07\x41\x8c\x1a\xde\x36\x47\x4d\x8f\x5a\xb1\xaa\x6a\xe2\xe6\xaa\x7b\x3f\xd9\x7d\x69\xc6\xa4\x9c\xb4\xee\xe5\xcd\xc5\xe1\xb0\xd3\xa0\x5f\xf0\x2b\x89\xdb\x34\xd0\x1b\xbf\x87\xad\xe1\xb7\x25\xc7\x7c\x32\xcd\x8f\xf3\x80\xbf\x0a\x77\xee\xa7\x27\xbb\x31\xc2\x83\x40\xbc\x5f\xee\x1f\xfc\x8a\x39\x47\x9f\x02\xa9\x20\x1d\x14\x82\xd1\xe0\x6e\xce\x5a\x44\x42\x72\x8b\x45\xeb\x6f\x4e\x7d\x3d\x2f\xeb\xf1\x70\xb2\x12\x35\xa6\x63\x11\x38\xd9\x12\xd1\x69\x30\x19\xcb\x7d\x10\xef\xdb\x72\x41\x01\x8e\x93\x32\x3f\x77\x6e\xb1\xb0\x93\x8d\x0f\xaa\xdf\x88\x54\x50\xfd\x81\x76\xcb\x04\xc4\x63\x3b\x38\xf8\x15\xf3\x3c\x3e\x97\x8e\xc1\xfb\x87\xbe\xd2\xf9\x34\xd9\x52\x79\x06\x0b\x07\xda\x57\x78\x01\xae\x87\xd5\x4a\xe1\xe0\xbb\x99\x68\x11\x6a\xc8\xad\x79\xc8\x0f\xa9\x4a\xbc\xf7\xcb\xf5\xf0\x51\x55\x5d\xd3\xdc\x56\x39\x0a\xdc\x92\xbf\xb9\x01\x92\x30\x11\x7d\x8d\x9a\xe7\x6f\x19\x39\x6c\xc3\xbd\x8b\x7f\xb7\xf6\x91\x19\x6b\x28\xf7\x18\xf4\x39\xfa\x5f\x74\x03\xfd\x25\xb5\x17\xa4\xb3\x72\x76\xd7\xbd\xfa\x72\x11\x00\x10\xee\x04\x33\x98\x0a\x62\x08\x68\xc3\xc7\xe3\x78\xf0\x8e\x38\xd1\xe9\x4a\x83\x3b\xd7\xd7\x8c\x18\x94\x47\x5e\xf6\xbb\xf2\x06\x8d\xa8\x81\x45\xdd\x46\x6c\x5e\x31\xa4\x6c\xc8\x8a\xcd\x38\x8e\xa7\x5d\xf0\x18\x71\x93\xaa\x91\xbe\x97\xe8\x74\xa4\xb9\xad\x2e\x2b\x03\xdb\x6d\x1e\x21\x7c\x94\x4c\x1f\x51\xb3\x7e\x7d\xcd\x88\x81\xfd\xfc\x2e\xf2\x72\x3f\xa0\xeb\x8f\x4d\x73\x73\x5f\x64\x2c\xae\x5c\x1f\xdc\x49\x5e\xe6\x3a\x5a\x8f\xbb\x85\xe9\x5c\x4f\x7c\x43\xda\xfe\x52\xbd\x89\x4e\xab\xc7\x9a\xeb\xe3\xbe\x98\x06\xdb\xf1\xa8\x46\x74\x1b\x71\x4e\x81\x77\xfd\x7a\xa0\xea\xcf\x29\xcb\xa7\xe8\x54\x29\x29\x81\xe4\xee\x03\x84\x42\x66\x09\x88\x56\x76\xa7\x80\x85\xb1\xc8\x0c\x28\x50\x29\xbf\x27\xa0\x23\x50\xbf\x81\x22\x27\x7c\x1f\x3c\x4e\x02\xb6\x0b\x8e\xc0\x6d\x92\xdc\xca\x9b\x66\x1d\xac\xd5\xb4\x65\xf8\x2f\xd4\x45\xd7\xfa\xec\xf1\xf0\x29\xf3\x0e\xf0\x7b\x77\xd4\x74\x7c\xbf\xe2\x12\xd7\x0a\x4e\x6c\xbc\xac\xb9\x9e\x9c\x04\x6b\x3b\x6e\x81\x96\x96\x6a\xf7\xe4\x24\xf8\xb8\xe5\x42\x3c\xec\xbf\xe9\xe7\x3f\xcc\x29\x75\xd6\xe7\x3e\x5f\xb6\xa7\xee\xeb\x1f\x5e\x47\x9f\x1f\x39\xd9\x00\x8b\x66\xcc\xda\xdd\x25\xbe\xd8\x3b\xac\x72\x24\x5c\xbf\x0f\xe6\xbe\x90\xde\x98\x9b\x07\xdb\x4e\x46\xff\x44\xdf\x23\x3f\x2a\xf8\xea\xaf\x6f\x6f\x85\xf6\x3f\xf7\xe9\xf3\xd0\xdf\xf9\x35\x4a\x1e\x00\x74\x0c\x7d\x04\xd0\xdc\x8a\xdf\xe3\x85\x2c\x74\x40\x96\x74\xa7\xb9\xe3\x89\x3c\xf8\x2e\xac\x80\x87\xfc\x0f\x12\x93\xfd\xb1\xdd\x08\xc2\xd1\xbd\x9e\x8e\x69\xfa\x69\x3f\x24\x48\xe0\x5e\x61\x6f\x7b\xf7\xd3\x00\x82\x3a\xe4\xa3\x47\x08\x31\x36\x42\xe6\x68\x1d\xb5\x13\x7d\x14\xb8\x88\x7c\x96\x9a\x3b\x2b\x98\xea\x9f\x57\xe2\x73\x11\xe4\xa3\x09\x7c\xaf\x0c\x6c\xd1\x78\x17\x14\xcd\xb9\xc8\x74\x22\x3f\x70\x8e\x7a\x26\x10\x07\xbf\x0b\xfc\x4c\x8e\x68\x76\xa3\x2b\x64\x11\xf1\x6d\x9d\x3f\xb0\x20\x10\x87\x00\x04\xe5\xc4\x0c\x2a\x8f\xcc\x07\x24\xe8\x53\xd0\x15\x07\x2e\x1d\x82\xf0\x01\x08\x47\xc1\x7f\x40\x22\x0f\xc2\xb6\x70\x3d\x24\xb2\xe0\x02\xf8\x07\xf8\x3d\xa4\x20\xc8\x9a\xba\x68\xea\xd4\xa9\xaa\x38\xa8\x72\xf2\x0a\x31\xe3\xd2\xa5\x48\xee\x95\x21\xa8\x22\xd2\x61\x03\x59\x8d\x71\x6a\x23\x39\xa6\x4e\x28\x9d\x42\x34\x94\x96\x95\x97\x4c\x98\x54\x0e\x20\x48\x0d\xde\xa2\xfc\xcc\x65\x10\x85\x6d\x13\x67\x67\x5d\x30\x15\x0e\x3d\x03\xbf\xbe\x14\x78\xf1\x6d\xf4\x13\xd1\x70\x3e\x70\x8a\x7e\xe8\x67\x07\x71\x05\xaf\x65\x16\xc1\xe5\xb4\x8f\x72\x01\x3b\x48\x91\x6a\x4b\x3b\xe5\x1b\x2c\xe1\x46\x88\xdb\x02\xe3\xb3\x2f\x5a\xda\x0c\x2c\x7a\x6b\xed\xfe\xca\xea\xdd\x6b\xdf\x38\xb8\x7a\xff\xf2\xfe\xcf\x8d\x5b\x77\xe0\xd3\xa1\xfd\xca\x8b\xd3\xc6\xe7\xf4\x1d\x4a\x58\xc6\x4f\xee\x3b\x64\x58\xdf\xbb\x89\x86\x67\x3f\xd8\xb7\xe7\x9d\xe7\x9f\xf9\x78\xff\xd8\xa9\x87\xb6\x0e\x18\xb9\x7a\xc8\xe0\xb1\x83\x9e\x1a\x9f\xd7\x6f\x34\x80\x70\x2b\x00\xcc\x34\xea\x24\xa0\x01\x60\xad\x1e\x2b\xeb\x80\x5b\x2b\xa8\xb9\xd4\xc9\xe6\x2d\x15\x78\xce\x38\x83\x88\xda\x43\x45\x01\x1b\x48\x2e\x88\xb3\x81\x98\x58\x10\x6b\x77\xc4\x82\xb6\xf8\x3e\x39\x87\xbf\x23\xf7\x58\x3d\xd9\xbd\x69\x6b\x1f\x1c\x6b\x0b\x15\xd7\x61\xd0\xb9\xf8\xdc\xca\x95\x0d\x4b\x67\x1e\xdf\xb1\xf3\x03\x82\x00\x9b\x6e\xae\x5a\x75\xeb\x39\x04\x08\xe2\xe8\xbf\xaf\x1c\x43\x1c\xaf\x00\xd9\xc9\x31\x78\xef\x0d\x1c\x9c\x8b\xc6\x5b\x2f\xfe\x4a\xd3\xc1\x9f\x04\xdd\x33\x78\xfe\x47\xef\xce\x2b\x9b\x34\xd4\x33\xe0\xe3\x43\xf3\xca\x8e\xbb\x9f\xa1\xee\xbc\xf3\x61\x77\x94\x36\xa2\xb0\x99\x7a\xf7\x83\x74\x5e\x5f\xcb\xe1\x54\x2a\x8f\x2a\x02\x0e\x7c\x62\x89\x2f\x82\x9c\x89\xd2\x65\x97\x9b\x6b\x8f\x34\xfc\xdb\xf2\x59\xcf\x8f\x5c\x31\x7a\xc5\x74\xef\x6f\x72\x1f\x78\xa1\xe8\x91\xc9\x2b\xa7\xf9\xaa\x73\x0d\xfe\x0e\x4e\xbd\x3e\xaf\x4b\x17\x5f\x41\xde\xf5\x79\x1d\x53\xfb\x0e\x86\x93\x54\x7f\xc4\x3a\x52\x0e\xd6\x53\x79\x74\x07\x60\xc3\xe3\xce\xed\xec\x6d\x4e\x8b\xc7\xc1\x72\xa6\x99\x74\xfb\xca\xe1\xf8\xf1\x68\x1a\x41\xad\x3c\x35\xe5\x5b\xb4\x6f\x1c\x7c\x29\x70\xa7\xe6\xd4\x24\xb8\xf3\xd2\x9e\x8b\xb0\x43\xd9\xb1\x8b\x7b\x2e\xa1\x6f\x4b\xdf\x07\x24\x98\x01\x7e\xa2\x46\x50\xe3\x85\xf8\x8f\x82\x82\xb4\x28\x40\xc5\x92\x16\xca\x12\xd7\x86\x1a\x4f\x43\x1a\xdc\x0b\x21\x8c\xa2\x21\xd9\x36\x3a\x2b\x3a\x3f\x7a\x41\xf4\x17\xd1\xdf\x47\x33\xd1\x20\x6b\xaa\xd3\x93\x35\xd5\x23\x46\xfb\x59\x3d\x1e\xab\xc7\x93\xdd\xdb\x87\xb3\x23\xf9\x9f\x19\xe4\xbf\xfd\x9d\xf8\x9f\x9f\x9e\x7b\x0e\xce\xd8\xb8\x91\xfb\x01\x04\x28\x03\x80\xca\xa3\x07\x02\x12\xc4\xe0\xd5\xb7\x03\x7a\xa1\x23\x1a\x3a\xca\xc8\x2b\x7e\x96\xbc\x12\x28\x25\xf6\x5e\xba\x44\x1c\x7d\x16\x7e\xff\x3d\xfa\x08\x7d\x85\x63\x5a\xca\xf5\xdf\x89\xe6\xbe\x56\x4e\x5e\xf1\xa7\x10\x7b\x03\xa5\xe4\x95\x4b\x97\x60\xd4\x4d\xd8\x1e\x0e\xfa\x1e\x59\x9f\xe5\xbe\xb3\x1d\x00\xca\x47\xad\x00\x14\x88\xe6\x34\x8a\x06\x14\x03\x98\x98\x58\x1a\x44\x11\x5a\x8d\xf2\x58\xa3\xa1\x35\x95\xb5\x46\xc3\xed\xf0\x53\x78\xc6\xff\x36\xf1\x33\x5a\x89\x9e\x20\x96\x13\x4c\xa0\x29\xb0\xaa\x84\x60\xe0\x1e\x54\x86\x79\xbf\x83\x6d\x01\x0d\x80\x0f\xdf\x22\x71\x00\x9a\xee\x10\xc3\x2f\xa1\x8d\x00\x40\xc2\x85\xec\x64\x03\xb3\x07\x38\x00\x80\x56\xc5\xd5\x30\x56\x00\x0b\xe3\xb0\x12\xae\xdd\xd5\xf9\x63\x3c\xa9\x29\x71\xd6\x34\xd6\xda\x35\x96\x41\x76\xe6\xf3\x8f\x6f\x17\x64\xa5\x7b\x62\xa2\xd3\xdd\x6e\xd7\x9c\x3b\xab\x00\x84\x14\xb2\x13\x07\x98\x3d\xc0\x2e\x64\x51\x3a\x79\x65\xf2\x5a\x3d\x56\x3e\xff\x98\xf2\xb8\x5c\x1d\x62\x92\x53\xac\x9d\x3a\xd4\xee\x5c\x95\x37\x1e\xad\x70\x7b\xdb\x51\xe9\xa9\x9e\x1a\x4b\xf5\xcf\xae\x63\xb7\x07\xf1\xb1\x0d\xb7\x89\x3a\xfa\x00\xe9\xc3\x31\x97\x24\x0d\xf8\x30\x2d\x2b\xc4\x42\x93\x5e\xd6\x11\x43\x1f\x25\xea\x6a\x71\x8c\x16\xbc\x80\xec\xc4\x6c\xcb\x29\xce\x2e\x41\xab\xc7\x0a\x2f\xd4\x22\x7b\xf4\x5b\xb7\x47\x73\x72\xad\x43\x76\xdc\x0e\xcd\xfd\x1b\x27\x37\xb1\x8e\x74\x07\x1e\x44\x76\xda\x55\xdb\x3c\x5f\xe8\x0b\xd9\xc9\x14\xfc\x99\xf6\x05\xd1\x80\xa4\x28\xc6\x22\x84\x85\x71\x4c\x5b\x3d\x39\xb8\x4b\xab\xcb\x1a\x43\xa6\x6f\x20\xea\x6a\x9b\x2e\x53\x1b\x70\xdb\x1c\x46\xcb\x29\xbe\x6d\xce\x2e\x10\xeb\x36\x10\x9b\x88\x3a\xda\xd5\x3c\xbf\x96\x97\x81\x4c\xc1\xff\xce\xb5\x4b\x13\x04\x63\x01\x90\x04\x59\x7c\xf0\xa8\xd4\xae\xc7\x1a\x43\x6c\xe1\xda\xa5\x36\x34\x5d\x96\x30\x5b\x4e\x71\x7e\x81\x6f\x97\x43\xbd\x81\xd8\xc4\xc1\x8e\x7e\xab\x79\x3e\x0f\x5c\xc0\x8d\x3f\xd7\xa9\x20\x16\xd0\x04\xc3\x44\x45\x03\xc8\x70\x3d\x88\x5d\xc8\x7d\xb8\x70\x2f\x7c\x37\xb7\x47\x53\x1b\xf8\xef\x63\x6e\x2c\x9c\x96\x91\xd1\x80\xe6\x1a\x60\x78\xd1\x73\x44\xd9\x45\xc2\xb1\xfc\xf4\xd1\xc0\x83\x5c\x13\xb5\xcd\xf3\x39\x0a\xc4\x71\xc2\x18\x92\x0b\xe2\x2c\x58\xca\xa8\x68\x40\xf3\x62\x7a\xd4\x6d\x60\x59\xb0\xac\x9b\x30\x0c\x8e\x25\x20\xe2\xb0\x9c\x02\xb1\xa0\x7b\x81\xd5\xd2\x06\xd0\xd1\xd1\x44\x4c\x4c\x5c\x9b\x28\x40\xc3\x18\x5e\x1a\x4f\x8e\x20\x8f\xa6\x35\x56\x90\x8b\x23\x67\x83\xd8\x28\x0f\x8e\x08\xde\x86\xb7\xe8\x03\x64\x23\xb6\x11\xb9\x05\x9d\x49\x8b\x25\x1a\x50\x54\x14\x75\x2f\x0d\x49\x7a\x37\x80\x9f\x00\xc8\x80\xfd\x9c\x1f\x84\x9c\xf3\x9b\xea\xb9\x77\xea\xa2\xac\x7b\xa7\xf2\x6a\x66\x95\x54\x0d\xf2\xea\xd6\x54\x44\x1f\x85\xb7\x6a\x6b\xe1\xec\x0d\x1b\xf8\x75\xcd\x45\x6e\xce\x60\xbd\x13\x46\x8a\xfb\x0f\x5e\xac\xfd\xbb\xa0\x7f\x6a\x1d\x6c\xe4\xf6\xec\x50\xba\xbd\xe5\xf5\x90\x1f\x54\xfa\xef\x1b\x2e\xd4\xfa\xbb\x72\xba\x7c\x51\x18\x13\xf1\xb3\x38\x08\x09\x5e\x24\x2f\xa1\x94\xda\xbf\x0b\x5a\xcb\x09\x29\xf4\x8f\xdb\xa5\x39\x8f\xcb\x7f\x9a\xe7\x84\xfb\xbc\xff\xe0\xdf\x89\xc5\x28\x05\x37\xde\x74\x98\x5a\xc0\xb7\x2f\xe8\x3a\x87\xa5\x5f\x41\x0a\x05\x80\x85\x88\x8a\x8a\x89\xe5\xac\x25\x09\xa3\x76\x53\xf0\x13\x0a\x32\xd4\x7e\x1a\xb6\xe5\x6c\xa8\xc8\x09\x26\x45\xd0\x27\x81\x15\x2f\x1f\xb1\x18\x43\x6c\x09\xcc\x21\xd3\x37\xc0\x5b\xb5\x17\x36\x34\x75\x27\xff\x29\xf6\xd1\x80\x65\xe8\x5a\x10\x0f\x2c\x51\x24\x15\x45\xc5\xc4\x52\x51\x8c\xa0\x59\x1e\xc9\x80\x49\x33\xcb\x85\x67\xd7\xe5\xda\xbf\xd7\x0a\xf3\x4b\x1a\x43\xdc\x96\x20\x23\xff\x59\x28\xf4\xbc\xa4\x16\x75\x26\x2f\xd7\xc2\x5b\xb5\xcd\xb5\xe4\x3f\xe1\xec\x0d\x4d\xdd\xe9\x61\x98\x6f\x6e\xdc\x2d\xa7\x78\x0e\x3d\x02\xe3\xc2\x0c\x22\x36\xc1\x5b\xf4\x05\xbf\x6b\xc3\x05\xde\x76\x5c\x14\xf4\x37\x5a\x1e\x41\xd6\x81\xc7\x10\x5e\xe1\x67\xb2\xa8\xa7\x04\xbc\x28\xb4\x2b\xf0\x8d\x3f\x29\x7e\x9e\x1c\x15\x78\xa6\x16\x5e\xe1\x1a\x6f\x3a\x5c\x0b\x67\x53\x0b\xfc\x2e\x3c\xc7\xe0\x2d\x3c\x47\xa3\x41\xdf\x82\x64\x0a\x80\x68\x86\x20\x62\x62\xb5\x44\x73\xce\xca\x02\xb2\xb0\x63\xc2\x94\x1b\xb1\xed\xe1\xd9\x26\xb6\xf0\x6c\x93\x97\x9b\xd2\x25\x5b\x89\xf5\x30\x9a\x67\x88\x97\x22\x06\x5e\xe5\xd9\xe4\xb9\xe4\x2c\x8b\x30\x27\xf0\x67\x25\x3e\x3d\x98\x4f\x8f\x35\x86\x1c\x53\xeb\x77\xc1\xab\x1c\x9f\xf4\xb0\xa6\x74\x38\x7b\x03\x79\xb9\xb9\x56\x69\x8f\x62\x95\x7c\x4a\x36\x49\xb4\x4b\x98\x53\x7f\x57\x51\x2f\xf1\xbc\x88\x55\xb2\xca\x5a\x05\x5e\x39\xad\xe4\xe7\x87\x68\xcb\x48\xc5\x77\xa2\x41\x5b\xf1\x5b\xdc\x77\xc8\xff\xc7\xde\xdb\xc0\x47\x55\x5d\x7d\xa3\xff\x75\xce\x3e\x67\x26\x21\x40\x42\x26\x86\x18\x42\x18\x42\x88\x31\xc4\x10\x86\xc9\x98\xc6\x10\x8c\x18\x43\x8c\x29\xc6\x74\x8c\x34\xc6\x18\x30\x46\x14\x21\x20\xc6\x34\x4d\xc7\x14\xe9\x08\x48\x31\x46\x11\x11\xd3\x29\x8d\x94\xa6\x14\x29\x52\x3a\x22\x45\x29\x2a\xa5\x08\x96\x47\x29\x52\x6a\xa9\xa5\x54\xa9\x94\x52\x4a\x79\xed\x30\x73\xe6\xfe\xf6\x3e\x67\x26\x93\x2f\xd0\x3e\xef\x73\xef\x7d\xef\xef\x46\x17\x7b\x66\xce\xfe\x58\x7b\xed\xb5\xff\x6b\xed\x7d\xf6\x47\xb8\x45\xb8\x3a\x77\xf0\xe4\x22\xb1\xd0\x68\xa5\x24\x2c\x67\x03\x0b\x87\x61\xda\x74\xab\x2e\x67\x0e\x21\xba\x62\xf7\x13\x77\x34\x17\x75\x64\x7f\xd7\x85\xdd\x5f\xda\x69\x61\x79\x87\x04\x7e\xf1\x56\xf9\x0f\x21\x9d\x14\x98\x17\x96\xa1\x98\x63\x15\x32\xef\xa0\x07\x3a\xc2\x20\x7b\xe9\x61\x1d\x03\xe4\x70\x1a\x45\xac\x0e\x8d\xd0\x64\x5b\x5c\xbc\x68\x59\xae\xcd\xa2\xc9\x7a\xf5\x99\xcb\xdf\xb7\x53\xcf\xc1\xe8\x0b\xa2\xbf\xf3\x72\x8b\xa7\xa7\x0d\x93\xe5\xe1\x66\x70\xd4\x8e\x19\xce\xf4\x8a\xaa\x9b\xcc\xf4\x2b\x33\xa9\xe6\xad\x51\x34\x52\x5f\xcb\xdd\xdb\x83\xa7\x84\xd1\xb8\x17\xdb\x0c\x2e\x12\x74\x64\x0f\x3c\xa0\x43\x9c\x7f\xbc\x28\x3f\xd2\x46\x08\x6c\x96\x87\x23\x2a\x5a\x51\xa3\xd5\x98\xe1\x6a\x34\x33\xeb\xdd\xb9\x4f\x7f\x8e\xcc\x37\x4d\xb7\x18\x1c\xb8\x3a\x42\x36\xc3\xb0\x1b\x72\xb8\x2e\x8a\xde\xde\x61\x79\x24\xe8\x38\xa6\xcb\x43\xd9\x1d\xf8\x2e\x6f\xf5\x5e\x91\xf4\x42\x59\x08\xdf\x0d\x3d\x9b\x3e\x7d\xbc\x69\xd8\xb0\xe1\x30\x9b\x15\x49\x8a\x19\x1e\x42\x77\xc5\x80\x77\xf3\x3d\x51\x14\x25\x87\x7b\x58\x6f\x17\x9b\xd2\x0f\xe9\x75\x1b\xc5\xd1\x5e\x58\x15\x03\xf0\xf9\xc8\xbb\xaf\xbd\x13\xf2\x18\x36\x1c\x8a\x14\xa5\x4a\x6a\xcc\xf0\x28\x05\x64\x92\xb9\xcf\x60\xb3\x0d\x94\x47\xb8\x0f\xe8\xbd\x92\x43\x8b\xd1\x2f\x75\x6c\x91\x23\xea\x12\x92\x87\xc1\x8d\xad\x97\x23\x23\x6d\x98\xa7\x4b\x1d\xba\xf6\x47\xda\xd0\x78\x38\xa7\x67\x0f\x1b\x39\x32\x81\xf7\x81\xe1\x71\x71\xaa\x34\x6a\x94\x25\x21\x16\xc3\x85\x7e\xc4\xb0\x50\x57\x88\x32\xfa\xc2\xa8\x50\x5f\x10\x22\xb1\x71\x3d\x09\xdb\x5a\x9b\x8e\x40\x61\xf9\x18\xfd\x22\xbc\xc8\x2b\xdc\x3f\x42\x30\x10\xea\x27\x06\x14\xc8\x7f\x40\x3f\xde\x10\x29\x8b\xb0\x8e\x18\xf5\x0a\x29\x4a\x58\x30\xbd\x0a\xc3\xc2\x79\x28\xe2\xac\xc0\xc4\xfe\x3d\xa8\x17\x29\x7a\x7b\x52\x08\x2f\xfa\x77\xa8\x3e\xc8\x21\xc6\x57\xd2\x59\xa5\x47\xf7\x1f\x93\xc8\x1a\xa7\xf4\x48\x67\xd9\xf1\x4b\xe9\x30\xc6\x5e\xfc\x7b\xef\x33\xcd\xc2\x7e\x77\x69\x62\xef\xb3\xc8\x74\x21\xb7\x53\x7f\x26\x1d\xe9\x7d\x26\x1d\xe9\x7d\xc6\x3f\x87\xd2\x51\x1c\x7f\x16\x7e\x7a\x2d\x1a\xb4\x66\xa5\xc7\x94\x6e\x8c\x6b\x46\x22\x5e\xbc\x71\x0e\xad\x8e\xc9\x81\x0d\x0e\x14\xa0\x08\x37\xe1\x16\xdc\x8a\xaf\xe2\x0e\xdc\x89\xaf\xe3\x1e\xcc\xc1\xfd\x78\x10\x0b\xb0\x18\xcd\x68\x85\x0b\x4b\xe1\xc6\x4a\xac\x46\x27\x9e\xc7\x8b\xf8\x1e\x7e\x80\x1f\x02\x89\xb6\x84\xb4\x38\xbb\x2d\x41\xee\x47\xf1\x3c\x1c\xe4\x59\xfc\xff\x43\xf1\x1b\x1e\xe8\xfd\x1b\xea\x73\x63\xc4\xdf\x03\x0d\xbd\x7f\x43\x7d\x6e\x9c\x43\x4b\xe7\xcc\xa1\x65\xf7\xde\x4b\x4f\xd4\xd5\x51\x7b\x7d\x3d\x2d\xad\xab\xfb\xb7\xbd\xa6\x46\xfb\xa8\x4e\x66\xb5\xb5\xb4\xd4\x20\x57\x7d\xfd\xbf\xd7\xfe\xdf\x1e\x1b\x55\xc0\xff\x60\xdb\xff\x18\xaf\xe0\x55\xfc\x1c\xaf\xe3\x0d\xec\xc5\x3e\x1c\xc0\x7b\x78\x1f\x47\x71\x1c\x27\x70\x12\x9f\xe0\x33\xfc\x1d\xff\xc4\xff\xc2\x25\x04\x49\x26\x13\x0d\xa3\x91\x14\x4f\x89\x94\x4c\xa9\x94\x46\x19\x94\x45\x39\x64\x23\x07\x15\x50\x11\xdd\x44\xb7\xd0\xad\xf4\x55\x20\x61\x88\x76\x8d\x1b\xa2\x5d\xe3\xfe\xff\xf8\x97\x8d\x1f\xa9\xba\x11\x5a\xff\x25\x7e\x6d\x1c\xf4\xef\x3f\xcc\x2c\xe2\x57\xf5\xff\x2d\xdd\xe4\xff\xd4\xd8\xc0\x4d\xc2\x5e\x1c\x31\xa5\x63\x26\x6e\xc3\xed\xf8\x1a\xee\xc2\xdd\xb8\x17\xf7\xe1\x01\xcc\x47\x13\x96\xa0\x05\x6d\x68\xc7\x32\x2c\xc7\x2a\x74\xe0\x39\xbc\x80\x97\xf0\x7d\xbc\x8c\x1f\xe1\x27\xf8\x29\x7e\x86\xd7\xf0\x0b\xec\xc1\xdb\xd8\x8f\x83\x38\x8c\x23\x38\x86\x8f\xf0\x31\x4e\xe1\x34\xfe\x86\x7f\xe0\x5f\xf8\x37\x02\x44\xa4\x50\x14\x0d\xa7\x38\x4a\xa0\x24\x4a\x21\x2b\xa5\x53\x26\x65\x53\x2e\xd9\x29\x9f\x0a\xe9\x46\xba\x99\x66\xd2\x6d\x74\x3b\x90\x10\x67\xb3\xa7\xf5\x23\x5b\xc2\x50\x94\x96\x60\x8b\x1b\x84\xf8\x98\xb3\x90\x78\xe2\x04\x9b\x5d\xee\x97\x61\xfc\x60\xbf\xfd\x7f\x38\xee\xbc\xd0\xdf\x83\xe2\xbf\xf9\xfc\x9f\x79\x0f\x46\xfe\xf9\xb2\xfa\x7e\x9f\xd7\xfb\xf7\x65\x7f\x9f\x1f\xf9\x37\x78\x94\x3e\x89\xe7\x0d\xfe\xd7\x48\xe3\xe6\xd0\xf8\x7b\xf9\xbf\xd6\x7a\xb2\xd6\x45\xfe\xed\xad\xd7\x4e\xd4\x6a\xc7\xf5\xff\xb9\xb2\xcf\x21\xeb\x9c\xfa\x1a\xad\xbd\xae\x4e\xea\xae\xa5\x74\xf1\xbf\xb5\xfe\xdf\x79\x73\xe6\x44\xe6\xe2\x73\xfe\x1f\x15\x45\xf8\x6b\xad\xb8\xc8\x66\xb3\x23\xdc\x27\x73\xc4\x59\xe3\x5a\xe5\x13\x17\xe5\x13\x7e\xab\x98\x37\x57\x01\xf6\x1e\x33\xe6\x79\x6c\x71\xd6\xb8\x74\x6b\x9c\x55\x65\xfb\x2f\x2d\x65\xb9\x97\xde\x63\xfb\x2f\x39\xca\x59\x2e\x08\xf3\xc9\x25\x35\xca\xad\x62\x6f\x63\x9c\x35\x6e\x3e\x5d\x22\x17\xf9\x35\x26\xce\x16\x09\x3f\x33\xde\xf6\xf0\x3c\xe6\xd3\x25\x6d\x16\xdd\xa7\xbd\xa8\xc7\x2b\x27\x9d\x17\xa0\xdd\x0c\xe9\x34\xcf\xc7\x1e\x67\x8d\x33\xa3\x5d\x6a\x0c\xac\xd5\xdf\xf9\x75\x01\x6a\x39\xdb\x02\x09\x71\x3f\x83\x24\x8b\xc9\xba\x1c\xe3\x85\x8d\x35\x8a\xa8\x4b\xaa\x96\x9c\x6c\xcb\xa5\x4a\x10\x75\x04\x4f\xa9\xb3\xd9\x66\x48\x80\x12\x47\xd4\xc1\xf6\x27\xb3\x7d\x81\x2e\x3d\x9f\xe0\x29\xb5\x9c\x75\xf2\x67\x64\x25\xea\x62\x5b\x02\x3d\xac\xf3\x52\x25\xfa\xa6\x8b\xa2\x38\x9e\x4e\x2a\x93\xea\x2f\xe5\x87\xe6\xb3\x67\x29\x7b\xc4\xb8\x0d\x62\x09\x5a\x9a\x9c\x4c\x72\x35\xed\x5d\x44\x7b\xb5\xc2\x45\xaf\x5f\xb8\x70\x41\x3a\x21\xfd\x29\x30\x36\x60\x95\x4e\x68\xf7\xd3\x0b\xb4\x8e\xa7\xdb\x84\x0d\x2c\x9b\x65\x8a\xf5\x53\x63\xa7\xc7\xc4\xc2\x3c\x1a\xa3\xc7\x59\x2d\x31\x63\x98\x18\x34\x45\xcc\x69\xc7\x87\x5e\x92\x88\x65\xb8\xd7\x91\xc3\x32\x96\x6c\x53\xa6\x91\x7d\xaa\xfe\xf6\x6e\x53\xf3\xe1\xc7\x5a\x0f\xb7\xb4\x1c\x6e\x7d\xec\x70\xb3\xb3\x6e\x53\xfd\x9c\x9e\xfa\xba\xcd\x73\xea\x7a\xea\xa4\xb9\x2d\xef\xb7\xb4\xbc\xdf\xf2\xd8\xe1\x96\x96\x43\xad\xf5\x3d\x75\x75\x3d\xfc\x61\xfd\x26\x2e\xbb\x58\xd4\xc3\xc9\x6a\x59\xa5\xd8\xc3\x9d\x88\x54\x64\x20\x07\x0e\x14\xe1\x16\x7c\x15\x77\xe2\x1e\xdc\x8f\x05\x68\x86\x4b\x3f\x99\x28\xc1\x92\x36\x3e\xd1\x08\xe3\x8c\x30\xfe\x7f\xf8\x7b\xa8\xbc\xfa\xeb\xed\xf6\xeb\xd3\x1c\x79\x79\x0e\x47\xde\xd4\xfc\xb9\x3c\xe0\xf4\xac\xdd\xe1\xb0\x73\xda\x62\xcf\xcb\xb3\x73\xda\x9c\x3f\x75\x6a\x3e\xa7\x35\x0e\x9b\xcd\xc1\xa9\x9e\x3f\xe7\xff\xa5\xf3\x6f\x52\x95\xdd\x6e\x6f\x71\x38\xec\xd4\x61\xb7\x3b\xb4\x9b\xaf\xbf\xde\x2e\x79\xbf\xe2\xc8\x0b\x54\x38\x6c\x0e\xb9\xcd\xe1\xb0\xfb\x7f\x9d\x97\xe7\x90\xf7\xd9\xed\xd7\xfb\xf7\x3b\x1c\x36\xf1\x5b\xe0\x36\x1e\xef\x75\x87\x23\x4f\x2b\x09\xa5\x6d\xb6\xdb\xc5\x39\x0e\xdb\xb0\x9c\xa5\xc9\x3e\xb1\x8b\x3e\xdc\x4e\x48\x1b\x8f\x6d\x0b\x8e\x2e\x9a\x7f\x6c\xb1\xa6\xfd\x7c\x87\xa6\x49\xc5\x0f\x1d\x69\x5e\x72\x6c\xde\xcf\x35\x8d\x24\x7d\xdf\x21\xc0\x36\xb3\xa5\x90\xf5\xb7\x64\x0c\x72\x0c\x62\x2c\x09\x66\xc4\x12\x72\x0e\xe6\x1c\xec\xf3\x4e\xc3\x1a\x47\xfd\xda\x3c\x93\x2d\xf5\xb3\xe6\x03\x8f\x2e\x39\xd8\xdc\x7c\xa0\xf9\xd1\x83\x4b\xd8\xd2\x4b\x6d\x52\x71\xf3\x81\xe6\xe6\x83\x4b\x1e\x39\xd8\xdc\x7c\x10\x72\x9f\x32\xd2\x90\x31\x7d\x94\x05\xf2\x98\x31\x31\x0c\x6c\x42\xba\x79\x5c\xec\x68\x8c\x13\x65\x7d\x74\x28\xf6\x90\xd8\x88\x3e\x74\x71\x89\xfd\x54\x70\x40\xf1\x15\x75\x3d\xf5\xf7\xf6\xd4\xd7\xf7\xdc\x5b\xdf\x53\x37\x80\x97\x47\xea\xf8\xa3\xba\x39\x5c\x01\x21\x61\x31\x2d\x93\xea\xe5\x25\x88\x11\x6b\xf2\xf4\xb7\x22\x03\xd7\x6c\x2e\xee\x9c\xfb\x40\xc9\xcc\xe7\xe6\x34\x74\xdc\x3a\x67\x66\xc5\x3d\xf7\x97\xdc\x7c\xbf\xd4\xd6\xf0\x4c\x59\x69\xc3\x83\xab\x9e\x6e\x2c\x9d\xdb\x38\xa3\xa4\xa1\x01\x80\x42\x5b\x83\xa7\xd4\x16\xb6\x19\xc3\xc4\xfa\xd0\xeb\xf0\x15\x80\xa6\xc2\x3a\x0e\x7a\x4b\x38\x2c\xb0\x4d\x81\x7d\x2a\xd2\xc6\x9b\xd4\xc4\xc8\x65\x92\x8e\xab\x6c\x53\x1c\x89\x6a\xda\xf8\xc8\xc5\x93\xb4\x95\xea\x49\x22\x99\xea\xb5\xe7\xfd\x97\xb4\x17\xaa\xc9\x76\xf4\x77\x94\xab\xbd\xf7\xbb\x63\xcf\xaf\x7b\x3f\xdb\x6a\xcd\xe6\x94\x52\x50\xde\xf9\x4c\x79\x61\xdd\xeb\x5e\xaa\xca\xb1\x5a\xb3\xb2\xac\xd6\x1c\xa9\xd4\x47\xf3\xb4\x35\x3e\x4d\x7b\x91\xee\xf7\x1f\xd5\xde\xa5\xa9\x47\x8f\x91\x6d\xdd\x0b\xb3\xc7\x65\x67\x8f\x4b\xcd\xc9\xd1\x8e\xa7\x2d\x5f\x9e\xb6\x93\x34\xe3\x3b\x18\x1d\x0e\x9e\x52\xd7\x09\xde\x8d\xdd\x90\x91\x9c\x47\xae\xe1\x8c\xe7\xbc\x66\xa8\x69\xe3\x33\x22\x7f\xa5\xc3\x82\x59\x89\xe6\x68\xcf\xfb\x35\x6d\x3d\x65\x65\x5b\xc7\x4e\x9e\x3c\xd6\x9a\x9d\x52\xef\x7d\xad\x7e\xda\xad\xcf\x74\x96\x53\x6b\x8e\x75\xec\x75\xd7\x8d\xed\xc7\x20\xb5\xa6\xe6\xe4\xa4\x8e\xcb\xce\xd6\xd6\xef\xdc\x99\xb6\x7c\x39\x59\x8d\xef\x62\x6e\xb7\x24\xb8\x58\x1d\xc1\x0a\x90\x09\xae\xe6\x76\x5b\x9e\x23\xc3\x91\x98\xe7\xb0\xdb\x12\xc6\x52\xa2\x23\xd1\x24\xd6\x1d\xab\xa6\x44\x53\xc6\x08\x32\x25\xa4\xd9\x27\x66\x98\x32\x1c\x13\x33\xf4\x06\xcc\xd0\x79\x2b\x39\x1a\x33\x6b\x7b\xe6\xae\x05\x0b\x8b\x6f\xbc\xaf\x60\x67\xb6\xd7\xa9\x1e\x3d\x1a\x5b\xee\xcd\xdd\x31\xe5\xce\xea\xe2\x96\xb9\xbb\xb2\x76\x54\xc4\x16\xed\x5d\xbe\xf2\x1d\xf9\xed\xe5\x2b\xf7\x90\x77\x5a\x7b\xad\x37\x77\x47\x45\xcc\xb1\x63\x6a\x46\xf6\x8e\x6c\x6f\xd3\x23\xd3\xda\xea\x76\x65\xed\x48\xbf\x76\xf8\xb1\x63\xb1\x65\xdb\xb3\xbd\x73\xdb\x52\xdd\x6f\xff\xea\x09\xf7\xbe\x7d\x62\xfe\x19\xb3\x58\x06\x6b\x47\x22\x26\x88\x15\x26\xa1\x13\x1a\x85\x36\x99\x8c\x39\x19\x59\xbc\x04\x0f\x89\xeb\x18\x49\x4d\xcb\xb7\x34\x35\x57\x39\x9f\x69\x24\x04\x51\xde\xd3\x5a\xe5\x2c\x98\xd6\x5c\x5d\xdd\x4c\xce\x92\x8d\xa3\x36\x34\xb6\x6d\x74\x56\xb5\x3c\xb4\x61\xc4\xc6\x12\xcd\x47\xaa\x14\xed\x6c\x99\x56\x58\xe5\x6c\x7e\x0c\x12\x55\xc2\xc7\xb6\xb0\x76\x7d\x05\x91\xfe\x36\xcf\x31\x31\x63\xa2\x7d\xaa\x23\xcf\x96\x28\x4a\xb1\x4d\x49\x30\xa9\x09\x96\x54\xb2\x8c\xa4\xf1\xd7\x51\x86\x69\x10\xbd\xa6\xca\x4d\xad\x37\x57\x9d\xef\xcc\x8a\x52\x4d\x66\xeb\x4d\x37\x54\x67\x8e\x1f\x39\x82\xc5\xc6\x30\x36\x22\x21\x3d\x6d\xc4\x67\x55\x3f\x5d\xb4\x64\x73\x45\x5b\x75\x75\x6b\x9b\x73\x76\xab\x94\xf8\x58\x4f\xd6\xf9\xac\x2c\x36\x22\xca\xcc\x58\xdc\xf0\x98\x11\xc9\x05\x73\x6e\x9b\x3a\x2e\x4a\x55\x8b\x67\xe7\x9e\xad\x7c\xa8\x6d\x4b\x77\xdb\x3d\x8f\xf2\xe8\x2d\x62\x0f\x2e\xc0\x18\x7b\x4f\xec\x07\x98\x9a\xe7\x98\x46\x8e\xb1\x94\x38\x96\x12\xc5\xcb\xcb\xb1\x52\x2a\x59\x1d\x53\xa6\x51\x21\x71\xae\x0a\xaa\xef\x5b\xbe\x2c\x79\xf4\xbd\xcf\xad\x2a\x91\xda\xab\xd7\xcf\x65\xb3\x36\x2c\x53\xfd\x7f\x55\x5b\x37\x57\xcf\xee\xf9\x7a\x3b\x9d\x9d\xed\xae\x6c\xde\xd9\x56\xb7\xe9\x29\xd7\xd2\x5b\xee\x75\xbd\xe1\xd9\x58\x6b\x4e\x4f\xaf\xdb\xfc\xcc\x88\x37\x5c\x46\x59\x0a\x63\xfb\x60\xd3\xcb\x9a\x92\x28\x84\x61\xac\xc4\xcf\x73\xf4\xf6\xeb\xeb\x28\x63\xac\xcc\x8b\x9e\x26\xdb\xf5\xa5\x09\x05\xcf\xd6\x14\xde\x97\x3e\x6a\xd8\x86\xa6\x47\x3c\x37\x57\xc5\x5e\x95\xf1\xc0\x4d\x65\xeb\x1f\xb9\xfe\xd1\x7b\x0a\x59\xee\x02\xd7\xc2\x28\xff\x0e\xb3\xbb\xb9\x36\x4f\xce\xdf\x3a\x7b\xf1\x06\x29\x7d\xf1\x4b\x92\xad\x38\x63\x42\x46\xcb\x1a\xcf\x83\xce\xfa\x0c\x66\xae\xb8\x75\xc9\x92\xee\x29\xb7\x3f\xd0\xb6\xee\xb1\x3c\x4b\x5a\xda\xd5\xd7\x37\x3f\x57\x9e\xd3\xb2\xe4\x25\x7d\xbf\x6d\xf0\x34\x9b\xcd\x5a\xc2\xe8\x72\x55\xa2\xb1\x68\x4f\x35\x8d\x20\xd3\x75\x94\x43\xd7\x51\xc3\x53\x73\x9d\xab\x33\xac\xab\xab\xef\x5d\x5d\xbd\x60\x55\x7b\xda\x55\xb3\xb7\x7e\xfd\xd6\x3c\x79\xe9\x83\xcb\x17\x37\x37\x2f\x71\xcf\x71\xee\x5e\xfe\xea\x91\x76\xe7\xcf\x3f\x6b\xbd\xaf\x1d\x62\x6f\xd1\x27\xf2\xfb\x6c\x9f\x58\xcb\x91\x07\xc7\x55\x48\x54\x61\x9a\x88\xe2\x47\x48\xaa\x28\x23\x73\x6b\x89\xf6\x5e\x55\x96\xe6\x93\xaa\x97\x53\xf5\x77\xdb\xb4\xe7\x97\x97\x68\x0f\x3c\x5b\x49\xf3\x79\xda\xb7\x91\x22\x17\xb0\x76\xb1\xeb\x54\x68\x4d\x9c\x2d\x81\x4b\xc6\x94\x26\x16\xd0\xea\x2f\x82\xdf\x6e\xbb\x2d\x2b\xa7\x7c\xdd\x43\xb5\x39\xf9\x8b\xa6\x77\x3e\x98\x9f\xdf\x5e\xb1\x38\x5e\xae\x9c\xbb\xa7\xb3\x67\x4d\x8b\xab\xa5\xd9\x13\xad\xa9\xad\xcf\x3b\xf4\xf5\x43\x47\xd8\x39\xe6\x16\x6b\xf6\x90\xae\xe7\x98\x2e\x72\xd1\xd5\x3f\x4e\x31\xde\x2d\xa7\xdb\x15\x8a\x6d\x2e\xcb\xbb\x4e\x7a\xfd\xc5\x7b\x16\xb7\x56\xe4\x64\x05\x8e\x2d\x5f\x9c\xff\x15\x5a\x20\x65\x04\x8e\x39\xca\x97\xc4\x4b\xe7\xb6\xf9\x7f\xe1\x7a\xf6\xbe\xdb\x17\x8c\xa2\x37\x9f\xd3\x1e\x7d\x64\xbd\x5d\xfa\xf3\x73\x4b\xd6\x1a\x6b\x8e\x1d\x4c\x52\x0e\x1a\x67\x37\xd8\x1d\x71\x26\xbb\x23\xce\x16\x97\x1e\x67\x8b\x73\x24\x98\x04\xa5\xc5\x29\x71\x69\x71\x8e\xf4\x38\xa5\x61\xff\xfe\xfd\x75\x54\x56\xb7\x9f\x87\xda\x8e\xba\x3a\x2a\xd3\x76\x24\x7e\xaf\x96\x2e\xd6\x79\xea\xa8\x44\xfb\xd8\x43\x35\xda\x81\xda\xae\x3a\x2d\x7a\xb6\xa7\x5a\x5b\x4f\x85\xdf\xd3\x5e\xa0\xe9\x6f\x79\xe8\xa2\x47\xf8\x78\x60\x45\xca\x0e\x24\x00\x71\xa1\xdd\x34\xbd\x5b\x68\xe3\xac\x71\x5e\xaf\x97\xf2\xa8\x50\xdb\xcb\x49\xba\xdd\xdf\x42\xfb\xb6\x3e\xbf\x99\xbb\x89\x9b\x9f\xdf\xba\x2f\x08\xda\x67\xf8\x8a\x90\x9a\x54\x0b\xe2\x23\xf3\x09\xef\x75\x8c\xf3\x78\x3c\x94\xeb\xf1\x78\x3c\xda\x7b\x74\x6e\xf3\x8b\x9b\xa5\xdc\xc0\x7b\x9b\x5f\xdc\xac\xc5\xd2\x39\x7d\x6e\xf6\x6d\x83\x8f\xab\xf5\x93\xb2\x13\xe3\xac\x71\x57\x85\x4e\xe3\xcc\x10\x4b\x92\x26\xa6\x8d\x37\x15\x48\xcb\x16\xa5\x51\x5e\xc2\xd8\xb2\x51\xcf\xb1\xe5\x0b\x46\xc7\x4a\xd7\xf8\x37\x8c\x89\x2f\x8f\x91\x1c\xdf\x7d\x99\x49\xb3\x02\xb3\xd4\xf9\xcf\x6c\x50\xb5\x3d\x41\x48\x5d\xea\x7c\x48\x62\xcf\x50\x8f\xd8\x87\x98\x6c\xec\x10\x33\xf6\x41\x1a\x5b\x84\xc4\x3a\x53\xce\xa4\xa5\x3b\xe2\xa8\x4a\xed\xd7\x94\xa7\x1f\x57\x79\xfa\xb4\xdc\xbe\x8f\x1e\x36\x36\x3c\xb6\xb7\x36\x3d\x34\xbf\x71\xe1\x3e\x7d\x1d\x8b\x57\xb3\x88\x75\x53\x89\x18\x07\x24\xea\x39\xab\x26\xb2\x52\x9a\xb1\xa3\x72\x04\xa5\x8d\x0b\x6f\x75\xf4\x52\x0f\x5d\x4b\x63\xbf\xfb\x6d\xda\xa2\x6d\xd2\x7e\xf0\xf2\x0d\x93\xa7\xd9\x92\xee\x99\xaa\xbd\x40\x79\x73\x3b\x9f\x5a\xbd\xa6\x76\xa9\x9a\x7f\xec\xa3\xf6\xfd\xf9\x81\xa5\x52\x6e\xa0\xb2\xe8\x86\x84\xbf\x0e\xb3\x28\x49\xf5\x0f\x34\x56\x83\xc1\xa9\x39\x59\x81\x6a\x41\x32\xc6\x61\xa2\x58\x37\x33\x35\xaf\x88\x54\x53\x46\x5e\x01\xc5\xdb\x64\x96\x44\x62\x3f\xba\x49\x4e\x8b\xbf\x8e\xd2\x2d\x89\xf1\x6a\x22\x87\x1b\x53\x11\xd9\xa7\x66\x38\x4f\x7d\x9a\xfb\x9d\x1f\xdf\xb7\xe7\xb3\x94\x9a\xae\x3a\xba\xfa\x48\x81\xf9\x86\xc5\x5f\xad\xe9\x9a\xdd\xb9\x9e\xf2\xb3\xbf\x72\xff\xdb\xce\xfa\x45\x19\xb7\xa6\x53\x45\xcf\x8f\x46\x9e\x94\x2b\x0e\xdd\x47\xdf\xd3\xca\x4b\xb4\xf7\x02\x89\x6b\x6f\x9d\x39\x42\xab\xa3\xb5\xc3\x5f\x5b\x7b\xf3\x78\xc2\xb5\x67\x46\x2e\xb9\xb3\x86\x6d\x97\x72\x67\x5e\x07\x09\x39\x9a\x53\x6e\x13\x7b\x0f\x53\xb8\x6c\x8b\xc8\x96\x60\xec\x90\x94\x13\xf5\xdd\x21\x72\x5a\xfc\xc4\x24\xa2\xf8\xb4\x9c\x4d\xd5\x7b\x57\xd6\x77\xd5\xc7\xce\xe8\x8c\x1b\x35\x6b\xe1\xa2\x8d\xb3\xbb\x6a\xdf\xa2\xdc\xea\x6a\xb9\xa5\xbd\xe1\xcc\x59\xda\xa1\x95\x9d\x0a\x34\x4a\x69\x27\x6d\xda\x3c\xea\xb9\x91\x52\xa4\x64\xed\x21\x7a\x56\x5f\xcf\xe5\xd5\x9c\x6a\x87\xd8\x83\xd1\xe7\x76\x03\xa1\x9d\xfa\x9d\x06\x94\xa5\x1d\x11\x77\x2e\x88\xbb\x0c\x2e\x55\x05\xca\xa9\x47\xbf\x6d\x81\xa7\xf7\x68\x0b\x94\x0a\xd5\x12\xba\x1d\xc1\x32\x92\xf4\x03\x18\xc4\xa9\x58\x69\x71\x53\xf5\x0d\xc0\x94\x6b\x32\xc5\x36\xfc\xe1\xed\x77\x37\x6a\x7f\x7b\x6b\xfb\xe3\x8b\x54\x8b\xb6\x37\x7d\xf9\xec\xee\x0f\xde\xd1\xd4\xc0\xd3\xd4\x21\xad\x3a\xbf\x65\x6f\xe0\xbc\xce\x8f\x32\x57\xd9\x81\x58\x3d\x3f\x07\x59\xa3\x48\x64\x45\x26\xce\xd0\x37\xe8\x29\xaa\xd6\x24\x9a\xbd\x4b\x3b\x32\x53\x6b\x5f\xaa\xec\x08\xd4\xbe\x42\xff\x0c\xb4\x04\x8e\x0b\xbe\x1a\x6b\x03\x17\x43\x7c\xb1\x8b\xaa\x05\xa3\xf4\x7c\x4c\xb6\x3e\x39\x79\x28\x37\xd6\xdc\x4e\xf9\x54\xad\xcd\xa0\xdc\x8d\xda\xdf\x6e\xd3\x76\x2f\x55\x2d\x81\x32\xad\x87\xaa\xb4\x64\xad\x81\x33\x45\x6f\x3f\xa0\x75\xf3\xbc\x72\x35\x27\x6b\xd2\xd7\xe6\xd9\xec\xc4\xbb\x30\xff\x27\x2e\x57\xfa\x45\xc0\xc9\xae\x0e\xcc\x90\xde\xd3\x8e\xec\x97\xff\x46\xf8\x95\x7f\x54\xc0\x49\x3d\x3c\x8d\x43\x5b\x20\xf7\xb0\xda\x50\x1a\xbb\x91\xc6\x21\xa9\x5a\x92\x5c\xac\x99\xa5\x68\xed\xec\x76\x69\xcf\xe9\x77\x02\xb7\x07\xbe\x43\x1d\xc6\xfe\xab\x33\x4a\xab\x72\x10\xa3\x8c\xfd\x10\x13\x6c\xe3\x12\x6d\x0e\x6b\x9c\x35\x23\x4d\xb5\x8e\x9f\x28\xa5\x0b\x8b\x5b\x48\xdc\xe4\x4a\xcd\xcb\x11\xfc\x11\x99\x9e\x8a\x1a\x4b\x49\x41\x4c\x8f\x7d\x5c\xfb\xf7\xa6\xc0\x93\x74\x73\xcf\xfa\x97\xbf\xd7\xbd\x71\x4d\x8f\x74\xfc\x13\xfa\xda\x8e\x6d\x2f\xfa\xca\x3c\xdb\x7f\x46\x55\x7f\x3a\x73\xe9\x9f\x17\xa7\x7f\xf4\xbe\xf6\x6f\x84\x30\x85\x1d\x60\x8b\xf5\x53\x7a\xe3\xc5\xdd\x56\xfa\xc6\x48\xe3\x18\x0d\xd9\x4a\x45\x1f\x5a\xa3\xcd\x6a\x66\x7b\xe6\x33\x0b\x27\xcd\x49\xcc\x48\xcd\x2f\xcb\x38\xaf\xed\x61\xb5\x81\xa5\x8d\x6d\xf3\x5a\x69\xed\x13\x8f\x5a\x86\x9d\x19\x76\xf7\x43\x01\xa7\x9e\x9f\x79\x84\x72\x00\x19\x46\x7e\xd3\xc8\x11\x6f\x8d\xbf\x2a\x3e\x6f\x94\x9e\xaf\xc8\x96\xf7\x21\xab\x3c\x51\xca\x10\x1f\x28\xf7\xf5\xdc\xab\xd4\xac\xf8\x23\x94\x7e\x24\x69\x82\x79\x52\xcc\xd2\x09\x6b\x5b\xca\x66\x4e\xb0\x5e\x9b\x7d\x4d\xdc\x3f\xb4\xef\xbd\x33\xcc\xce\xd4\xc9\xc3\xdf\xd6\x3c\xca\x0e\xff\x9f\x3e\xda\x90\xff\xf7\x62\xd9\xe6\x3f\x78\xaf\xf6\xbf\x6e\x25\x36\x59\xba\xea\x99\x95\xa9\x17\xe2\x33\x6a\xca\xfc\x92\x8c\x4c\xa2\x49\x79\x7f\xb7\x05\x24\xb1\xa7\x0e\x30\x25\xb2\xc5\x62\x17\x13\xe7\xc1\x96\x57\x44\xf1\xd6\xf8\xb1\x94\x68\xcb\xeb\x65\x86\xd7\x71\x18\xa5\x0d\x23\xab\x85\x26\xb7\x5f\x95\x61\x66\xa9\xb1\x2b\x68\xd6\xd2\x51\xa9\x92\x79\xe4\xc3\xe9\xdf\xfd\xe6\xd7\x6e\x4c\x4b\x2e\x9a\x91\xb4\x53\xdb\xee\x7c\x24\xea\x26\xb7\xe6\x65\xb5\x5a\x5c\xb5\x76\xba\xfc\xe5\xaf\x49\xa3\x03\x9f\xde\xf6\xf6\xd4\x6f\xd2\xbb\xeb\x3a\x52\xcf\x0c\xbb\xb3\x2e\x30\x83\xdc\x74\x56\xfb\x6d\xe0\x67\x06\x2e\xae\x62\x8b\x71\xb5\xbe\x8f\x6a\x4a\xc4\xbe\x4e\x53\xa2\x2e\x6a\x2b\x59\x65\x35\xde\x92\x68\xf8\x4f\x96\xea\xbc\x54\xcb\xba\x6f\xb4\x3c\xbf\x23\xeb\xda\x58\xb3\x9a\x71\x94\x8a\x34\xa7\xb6\x6f\xbf\x73\xdb\x8c\x92\x8c\xd4\xb1\x13\xe9\x48\x8f\xf9\x8e\x7b\xb2\x5b\x9f\x59\xb5\xf8\xdd\x47\x1a\xe6\xce\x5f\xb4\x58\x6a\xbb\xb4\x81\x4e\xc5\x52\xe7\x57\xee\xb2\xcd\x9e\x74\x9d\x58\x5f\xed\x05\x58\xae\xbe\xd6\xd4\x16\xd9\x87\xf5\xbe\xab\x69\xe1\x3e\x0b\xc8\xad\xac\x36\x1c\x2f\xc1\xca\x3b\x04\xf5\x68\x4e\x56\xab\x55\x9e\xd4\x6c\x90\xc4\x1d\x6e\x3e\xb6\x04\x09\x86\x2e\x3a\x12\x47\x50\x42\xac\x22\x96\x8d\x41\x9c\x49\x0d\x25\xb4\x80\x3c\xa1\x66\x41\xf3\x47\xb3\xcb\x68\xc4\x6f\x77\x7e\x4c\xd0\x16\x6a\x3d\xda\x2b\xda\x0b\x72\xa9\xbb\xa7\x76\x76\xfe\x74\x29\x6b\x1d\xa5\x76\x3c\xfd\x8d\xf7\x9a\xb5\x33\x53\x25\xe9\xb5\xa3\xda\xef\x2f\x69\x1f\x6b\xaf\xd3\xb5\xf9\x31\xfb\xba\xd6\xff\xf0\xab\xf7\x72\xdd\xb7\x62\xad\xd4\x69\xac\xe3\x41\x3c\x25\x92\x4c\x89\x64\x95\x32\x67\x06\x8e\xce\x14\xff\x12\xa3\xd6\xf9\xda\x77\xe8\x18\x0f\x96\x89\x77\xc3\x2e\x25\x89\x3a\x4c\xbb\x8d\xb7\xed\x91\xc3\x9d\x38\x5b\x5c\x7b\x59\x7e\x41\x49\x49\x41\x7e\x19\x55\xed\x56\xe7\x89\x73\xaa\x0b\x0b\xb5\xb3\xd2\xcb\x81\xaf\x8b\xb4\xac\x41\x1a\xa1\x9e\x1a\x98\x96\x97\x1d\x4e\x9b\x49\x27\xdc\x9a\xb5\x37\xf9\x5e\xfe\x7d\x1c\x20\x69\x5b\xd8\x31\xaa\x52\x4f\xe9\xf7\x2e\x88\x77\xda\x11\x79\x68\x5b\xa4\x8d\x5a\x56\x28\x13\x76\xec\x8d\x37\xa8\xc3\xc8\x02\x20\xed\x1c\xdb\x4b\xb1\x6a\x22\x14\xc4\x4f\x8f\x96\x69\x24\xee\xc1\x2b\x90\x81\x1c\x71\x2a\x11\x77\xfa\x6d\x71\xda\x39\xda\xfe\x10\xdb\xfb\xd0\xa7\xda\x66\xd1\x66\xab\xd9\x66\xb9\xca\x54\x20\xce\xa1\x89\x22\x0e\xad\xab\x69\x0e\xd5\x6b\x9f\xbd\xa8\xec\xa0\x65\x5a\xab\x76\x91\xa2\xf5\x78\xab\xe5\x2a\x53\xaa\x88\x27\x5e\xe4\xd2\x6a\x4a\x78\x91\x12\xb4\x2e\xd5\x42\xc3\xb4\x7f\x69\xc6\xb9\x3e\xed\x92\x87\x36\xa9\x17\x8c\x7b\x23\xac\x72\x5a\xa4\x0c\xda\x29\xc3\xf1\x9a\x6d\xe6\x8c\x19\x65\xe5\xc5\xd3\x6f\x53\x2f\x04\x8a\xb4\x8b\xc5\x33\x67\x16\x17\xdf\x52\xa2\xa7\xdd\x4e\x9b\x4c\x66\x3d\x6d\x32\xd9\xe2\x23\xeb\xde\xee\x78\xcd\xa1\x7d\xcc\xd3\x95\xdd\x34\xa3\x4c\xda\x2e\xed\x09\x14\xc9\x07\x8a\x6f\x29\xb9\xe9\xa6\xd2\x52\xa3\x6c\xba\x8b\x36\x29\x3f\xf9\x22\xe9\xe9\xae\x01\xe9\x7b\xe5\x67\xac\x9f\x4a\x4b\x48\xb3\xa7\x25\x68\xe7\xa4\x71\xbb\xe7\x2f\x67\x7b\xa9\x6a\xfe\x27\x9f\x7c\x22\xe2\x01\x14\x4b\x55\x88\xc2\xa8\x1d\xb2\x59\x21\x33\x01\x39\x53\xa6\xc4\xd9\x72\x6c\xb9\x93\xad\x76\x63\xd6\x3b\x4e\x3b\xb7\x7b\xfe\xf2\x87\x78\x22\x43\xd6\x5d\xda\x1d\x4c\x0e\xbe\x28\xe6\x3f\xf2\x1c\xd6\xb1\x94\x98\x90\x36\x31\x43\x35\xa5\x75\xfd\xe2\x26\xba\x2f\xf5\x85\xd2\x03\x2f\xdd\x56\xf1\xfc\x01\xed\xe1\x5f\x2c\x9c\xfa\x6a\x49\xf2\xdd\x77\xdc\x7e\x8f\x7e\x16\x0b\xda\x68\x0f\x5b\x2c\xc6\xbd\xd9\xd3\x47\xc7\x60\x94\x0a\x75\x74\xd2\xc8\x84\xb6\xbb\x46\xc6\x46\xc9\x6d\x77\x21\x2a\x36\x4a\x8a\x42\xce\xdd\x59\x18\x5d\x94\xd5\x67\x3a\x2c\x2f\xe2\x04\xad\x88\x03\xf9\x66\x3b\xef\xa8\xb9\xbb\xb2\xaa\x26\x14\x52\x46\x95\xf3\xce\x3b\x6e\xbf\xab\x5a\xba\x60\x7c\xe0\x3e\x2d\xd5\xc8\x0d\xf2\x4e\xd1\x77\xa6\x4c\x1f\x03\x26\x9b\x98\xc9\x1c\x55\xa2\x38\x15\x49\x19\xc7\xea\x98\xc4\x4a\x51\x0d\x49\x5f\xf5\x67\xbb\x3b\xe7\x6e\xdb\xdd\x91\x85\x1b\xeb\xdf\x1a\x64\x04\x20\x83\x6a\x8e\x1f\xa7\x65\xc7\x8e\xe9\x58\xd1\x42\xa7\xe8\xfd\xde\xb3\xdc\x5a\x68\xb6\xed\x82\xb2\xc3\x2f\xf0\xa6\x5d\xba\x48\x9b\x7a\x9f\x09\xad\x51\x76\x04\xa6\x87\xec\x4b\x1d\xab\xe3\xcf\x72\xe3\xac\x71\xfc\xf3\x25\x8f\x31\x7f\xf3\xb9\x9a\x8a\x04\x71\x86\x87\xd8\xa3\xdb\xbb\xd3\x4e\x9c\x52\x12\x67\x8d\x23\x31\x47\xa6\xa6\x8d\x8f\x8f\xb3\xc6\x65\x6e\xda\xf5\x5e\x57\x6b\x45\x4d\xc5\x8d\x5f\x21\xb3\xf6\xb9\xf6\x9e\x74\x7c\xe3\xc6\x3b\xee\xd8\x38\x9c\x72\xe5\x96\xce\xca\xca\x37\xb6\xe6\xfc\x31\xe5\xb6\x1b\x4a\x4e\xf9\xdd\x72\x8b\xa4\x3e\xf7\xdc\x2d\x5f\xbd\x94\xc8\x6a\xc5\x06\x39\x7d\x4e\xea\xaf\xa2\xbc\xa4\x21\x4b\x1b\xb4\x90\x4f\x07\xcb\xde\xef\x56\x2d\xff\x3e\x03\x30\x9e\xaf\x79\x84\xc8\x37\x0b\x53\xf5\xdd\x37\x83\xe5\x6d\xfd\x4f\xea\xd7\x34\xe0\x97\x0f\x87\xae\xf1\x65\x25\x20\xe4\x6d\x86\xc1\x67\xce\x97\xe4\xf2\x0b\x32\x77\xea\x8b\xb0\x15\x92\x1c\x40\xfe\xe3\x6c\x1b\xa2\xd5\x52\x71\x86\x6e\xde\x04\xab\x2d\x21\x6d\x9c\xc9\x7f\xfc\x1e\x5a\x47\x93\xa2\xa3\xb5\xaf\xbf\xca\xb6\xfd\xea\xd0\x81\x03\xc6\xba\x12\xb6\x4d\xce\x51\x4b\xf5\x75\x6f\xb6\x71\x2c\x31\x6d\xe2\x84\xb4\xe8\x68\xba\x89\x5e\xbc\xfd\x60\x95\xf6\xce\x07\x4a\xdb\x81\xf7\xf6\xdd\x3b\x8f\xe7\x7b\x94\x1d\x07\x54\x8b\xd8\x9b\x63\xf8\x32\xfa\x21\x19\xfe\xa3\x71\x7b\xd6\xb8\x8e\xdf\xbf\xe4\x8f\x8f\x95\x35\x5a\xd8\xf1\x35\x3f\x48\xb5\x1c\x4e\x4c\xcb\xcf\x33\x7c\x21\xf6\x91\x9c\xa5\x9f\xd9\x19\x27\xf6\x89\xe9\x43\xa3\xf7\x7e\x78\xe7\x4b\x93\x9e\x8b\x7b\xf3\x85\x9f\x29\xb1\x87\x33\x46\x3d\xf4\xec\x0f\x70\x15\xaa\xb4\x76\xd3\x1e\xe5\xac\x58\xc3\x33\x5c\xac\x52\x49\x8b\x78\x6f\x7f\x2b\xee\x40\x0d\xea\x30\x17\x4d\x68\x0e\xbf\xe9\x03\x1f\x61\x9a\x6c\x09\xb6\x04\x6b\x12\xd9\xc4\x1a\x16\x59\xe0\x56\x7c\x9f\xad\xdd\xfa\x59\x8d\xf1\x62\xef\x8c\x35\x21\x14\xca\x71\xc6\x30\xdf\xd8\x9c\x97\x21\xc6\x3c\xe1\xfd\x7b\x59\x14\x8e\x28\xb6\xf6\x19\x6b\xb0\xe3\x6d\x62\x90\x68\xb7\xc6\xa5\xd9\x7b\xcb\xb4\xc5\x55\x2d\x58\xb0\xe0\x4d\xed\xf0\x82\x05\x0b\x16\x50\xce\x9b\x1d\x6e\xd7\xb7\x9e\x74\xbb\x5c\x6e\x97\xdb\xed\x76\x67\xd2\x08\xed\x3c\x8d\x68\xa1\x58\xed\x1c\xc5\x9e\xd8\x3c\x7f\xe1\x75\x93\x0a\x26\xcf\xaf\xad\x2a\xcb\x4d\x9f\x5d\x52\x7c\xdd\x84\x6b\x73\x0a\x8e\x53\x9c\xf6\x77\x8a\x5b\x9b\x95\xe4\x6c\x7b\xa0\x76\xea\xf9\xbd\xf3\xb5\xdf\xd0\x64\xfd\xfd\x54\x06\x4f\xdf\xfc\xcb\xf9\x72\xb6\xc8\x61\x39\x8d\xd4\xfe\x41\x6e\x9a\xbc\x60\x4f\xe0\xe7\xcf\xbc\xb8\xae\xb3\x63\xfd\xfa\x8e\xb7\xdf\x7e\xeb\xd2\xcf\xe6\xab\xda\x82\x05\xff\x5e\x20\x82\x4b\x87\xa5\xb2\x9b\xee\xc8\x9d\x61\x66\xc3\x67\x5c\x7f\xfb\x5d\x0d\x59\xe9\x65\xf5\xe3\xc7\x8d\x4f\xb9\xf4\xba\xfe\xf8\x48\x83\xd9\x49\xcf\x68\x8b\xee\x99\x13\xe8\xfe\xa5\x76\x58\xd5\x16\x68\xbf\xd9\xe3\xdb\x24\x58\x75\xf7\x96\x23\xf6\x8f\x54\x69\x7b\x4c\x3d\xaa\x05\xb2\xb8\x39\x17\xf1\x51\x72\x68\xf7\x88\x69\x04\xa5\x90\xcd\x2e\x26\x8f\x8c\xa9\xc7\x88\xd9\xab\x2a\xb9\x47\xde\xec\xaf\xd2\xb6\x54\x7a\x66\x17\x4d\xcb\x2d\xad\x2a\xf8\xaf\x49\x37\xde\x3f\xf3\xf5\x97\xbf\xba\xf3\x9e\x5b\x4a\x8a\x67\x96\xde\x54\x7a\xb3\x34\x4f\xee\xf1\x3b\xfd\x77\x2a\x8d\xdb\x66\x7d\x25\xc7\x7e\x6b\xde\x8c\x85\x65\x05\x39\x53\x6e\xcc\xad\xfc\x56\xb5\x7b\xdd\xf5\xfe\xa8\xa2\xd2\x99\xd3\xa6\xcf\x2c\xe5\xfa\xd4\xc8\x8e\x31\x9b\x5a\x24\xec\x87\x71\xd4\x98\x55\xcc\x10\x35\x52\x9c\xe9\xae\xc5\xf7\xcd\x19\x46\x96\xf8\x0b\x7f\xf9\xdb\x49\xb5\xe8\xfe\x3b\xbe\x7e\xcf\xeb\x3f\xee\xd6\xdf\xfb\xd4\xb2\x83\xd2\x0e\xd5\xa2\x9f\x2d\x3d\x8d\x1c\xd6\x04\xd5\x44\xb5\x23\x33\xcc\x74\xf5\x2c\x27\x3b\x78\x75\xee\xae\xe9\x96\xad\x4b\x8d\xb8\x5a\x81\xb4\x23\xb8\x14\x66\xc4\xef\x30\x2b\x51\xd1\xe6\xc7\x65\xe4\x5c\xfd\xae\xf1\x96\x88\x8c\xd4\x69\x46\xf2\x5b\xbf\xbe\x4d\x73\xf2\xe4\x9b\x9e\x02\x51\x05\x3b\x26\x6d\xec\x3d\xc3\x5a\x5c\xca\x40\x15\x15\xd5\xdb\x46\x66\x98\xd9\xb1\x84\x9e\xe5\xc9\xb9\xbb\xa6\xeb\xf7\xbf\x9b\x5e\x56\x0e\x22\x0e\x57\x8b\xfd\xaf\x62\x46\x2c\x61\x04\x25\x58\x42\x1b\x0a\x15\xbb\x23\x4f\x14\x34\xf8\x31\xe9\xb4\x76\xd5\xcc\x9b\xd3\xb3\xd3\x8b\x8a\x6f\x2a\xa3\xd9\xf1\xd7\x26\x90\x7a\xed\xcb\xb7\x5f\xe6\xcc\xf4\xf3\x95\x0b\xe3\xcb\xae\x4a\x4f\x19\x35\x2a\xee\xea\x31\xe9\xd9\x65\x37\x5e\x7d\x53\xe7\x9d\x96\xda\x23\xda\xc3\x97\x39\x43\x1d\x2d\xac\x51\xce\x52\xf6\x09\x3e\x2f\xc3\x63\xcb\x60\xdc\x0c\x59\x24\xc8\x7f\x8c\xed\xd5\x3c\x6a\x37\xe2\xf5\xf6\x10\xaa\x34\x92\xd2\x32\x0c\x1d\xf2\x1f\x1b\xfb\x40\xe6\x53\x2b\x37\x44\x6f\x49\xbc\x35\xef\xda\xf1\x37\x2a\xa7\x36\x45\x0f\x5f\xd0\xb0\x3e\xf3\x96\xce\x18\x5b\xfa\x38\xb1\x7e\xd1\x9f\xcd\x8e\x21\x5f\x75\x61\xb8\xd8\x75\x61\x8f\x74\x27\xd2\x85\xec\x55\x93\x3f\x7b\xe1\xfd\x54\x60\x77\x8f\xd9\xb0\x70\xce\xa2\x7b\xe9\xef\x5f\xb3\xff\xe3\x26\x0f\x3b\x96\xfc\xed\x35\x15\x3f\x4e\x4d\xbe\xf5\xeb\xf7\xdd\xb8\xf7\xea\xaf\x3f\x9c\x70\xd7\x12\x40\xba\x14\xc3\x8e\x05\x93\x54\x97\xb8\xb7\x17\xa4\x5f\xd9\x21\xae\x78\xeb\xcd\xf7\x52\xcc\xf9\xbc\x3b\x9e\xef\x3e\xb9\xf0\x7e\xba\x21\xf7\x5b\xd7\x6c\xb8\x77\xd1\xbc\x07\xd4\x79\x09\x0b\xef\xba\xba\x59\x7b\x27\xf9\xdb\x6b\x4a\xbb\x27\x25\xdf\x78\x5f\x5d\x49\x88\xbf\xe0\x09\xf5\x73\x0c\xc7\xb8\xfe\xfc\x91\x71\x8c\x5c\x64\x95\xfb\xb2\x7a\xea\xaa\x92\xda\xa6\x36\xd5\x15\xed\x28\x4e\xcf\x4a\xeb\xc3\x32\xad\x73\xa9\xa5\xb3\x16\x25\x15\x3e\x22\xa5\xa6\x24\x8c\x15\x65\xe5\xb2\x63\xc1\x64\x53\x0a\x86\x23\xbd\x7f\x59\x83\xdf\x1c\xe7\xcf\xed\x29\xa6\x51\x93\x1f\xbf\xe1\xbb\xab\x66\xdf\xf1\xdc\xd2\x61\x8b\xeb\x22\x6f\xb0\x99\x34\x4b\xbf\xc1\x86\x1d\x4b\xee\xae\xbb\xf9\x89\x82\xe4\x5b\x6e\x2f\xab\xa0\xea\x87\xbf\x35\xc6\x9a\x3c\x69\xd2\xe2\x96\x64\xeb\x98\xcc\x9c\x50\xb9\xaa\xba\xc7\x68\x03\x9b\xde\x23\xf5\xb3\x2c\x1c\xa1\x36\xc8\x5d\x63\x5e\x5c\x5d\xbd\x28\xea\x85\x61\x7b\x3d\x2f\xef\xd4\x4a\x72\x3e\xaa\x59\xac\x66\xdd\x79\x47\x6d\x79\xd7\xf6\xcd\xd5\xc9\x0f\xd4\x25\x3c\x7c\xef\x15\xf2\x32\x2e\x50\x99\xd8\x2f\xaf\x25\x1f\xe5\x94\x2c\x9d\x17\xce\x8b\x32\x12\xea\x1e\x48\xfe\x5a\x38\x2f\x93\x6a\xc8\xbe\x5f\x5e\xe1\x8d\xf2\xba\xf0\xd3\xc6\xf7\xcb\xf6\x4f\x57\x95\x38\xe7\x4e\xc9\x53\x1f\x8c\xb6\x65\x14\xd8\x7b\xb3\x8f\x6f\x54\x6f\x9a\x31\xf5\xc6\x51\x99\x0f\x47\x8d\x4e\xca\x0c\xcb\xdd\x62\x4a\x41\x8c\x78\xa7\x60\xeb\xb5\x70\x13\x33\x86\x10\xfb\x3a\xd3\xbc\xfa\xb7\x47\x3c\x17\xe5\x7d\xf9\x07\x7b\xe4\x08\xb1\x7f\x73\xd8\xa2\xfa\xd0\xc5\x41\xaa\x54\x50\xd2\xfe\xcc\xf3\xdf\x7b\xcd\x10\xf8\xc2\x6f\xea\x02\x27\x44\x6b\x16\xf2\x00\xe2\x6c\xc8\xd0\xf1\x45\x36\xa3\x3b\x66\x44\xdf\xe0\x48\xcb\xae\x28\x79\xf5\xab\xc5\x69\x2b\x16\x96\x55\x6a\x1f\x8d\xba\xe6\xda\xa9\xf3\x8b\x6f\xb8\x75\x56\xce\xfd\xae\x44\x61\x8f\x63\x35\x8b\x94\x49\x40\x0c\x90\x28\x6c\x9a\x55\xdf\x01\x17\x5b\x70\x43\x2b\x65\xfc\xfc\x47\x73\xbf\x76\x32\xbe\x87\xca\x35\xf7\x4f\x7f\x99\x04\xc8\xda\x76\x76\x80\x96\x9a\x62\x30\x0c\x16\x8c\x43\xf6\xf4\x31\xf2\xe3\x8f\x73\xb3\x3e\x0e\x93\xe1\x01\x03\x46\xc7\xc4\x8c\x1d\x39\xea\x9e\x51\xaf\x8c\x92\x47\x21\xe7\x6e\xb1\xe8\x35\xe7\xee\xa6\xab\xdf\xcd\x9d\xdc\xe7\x74\x95\xd0\x81\xfe\x09\x91\x63\xb9\xed\xa1\x6b\x91\xf6\xcd\xab\xa4\xf2\x29\x6f\xdd\x1c\xbe\x04\xb0\xc4\xb8\xf9\xe8\x58\xf2\x63\x6b\x2c\xf9\x3f\xc9\x79\xa9\xf7\x1e\x60\xad\x8d\x1d\xa0\x72\x53\x8c\xb8\x4f\x62\x5c\xc4\x5d\x35\xf1\x43\x1c\x85\xad\xb5\x51\x79\xe5\xbc\x83\x25\xbf\x64\x03\xef\x63\x52\x3f\xb7\xac\x79\x2c\x39\xe7\xc7\xda\xf2\xfe\x57\x2e\x5d\xf6\x8c\x60\x31\xce\xdf\xa1\xb4\x8b\xb7\xf8\x76\x2b\xe9\x4b\xd8\x3d\x34\x97\xb2\xdc\x6e\xad\x9b\xf9\xdc\xda\x11\xca\xf2\xb9\xe4\x2e\xaa\xb9\x72\xfc\xd5\x3c\x7e\x09\xed\xf4\xb9\xa4\x23\x52\xfa\xe5\xe2\x3f\x4c\x56\xb7\x5b\x5b\xc6\x7c\xee\xc0\x6c\x69\xa3\xcf\x45\x1e\x79\x76\x9f\xf8\xe6\xde\xf8\xe1\xe8\x2e\xe6\x73\xfb\x67\xc8\xbb\x7c\x2e\xe6\xe3\x71\x2b\x22\xe2\x3a\xa2\xc4\xc1\x26\x54\x51\x43\x85\x54\xea\x76\x6b\x5e\x25\xa9\x4e\x3b\x42\x36\x9f\x8b\xed\xd3\xde\x35\xce\x70\xee\xe5\xc5\x41\xfa\x72\x7d\x6b\x65\x3d\x95\x92\xcd\xed\xd6\x9e\x55\x12\xeb\x34\x2f\x55\xfa\x5c\xf2\x26\x5d\x36\xa1\xfc\xc5\xd9\xf7\x3a\xeb\x15\xb5\xd2\x52\xb7\x5b\x49\xac\x0d\xbc\x20\x2d\xf6\xb9\xa4\xb2\xc8\x78\x7a\xbe\xf1\x3c\xa2\x9d\x2a\x2a\x69\xfb\x71\xc1\x47\xe2\x3c\xad\x51\x9b\x2c\x37\xfa\x5c\x67\xa4\x97\x79\xfc\x92\x48\xbe\xf5\xf8\x54\x32\x9b\xb6\x7c\xec\x76\x6b\x1b\x95\xe4\x06\xed\xc1\xc0\x8b\xb2\xcf\xe7\x92\x37\xe8\x7c\xf0\x01\x75\x53\x5f\x3e\x4a\x66\xd3\x2d\x2b\x56\x28\x29\x73\xb5\xa3\x94\xc9\x9b\x87\xc7\xb3\x0f\x22\x0f\xfb\x83\x74\x8b\x90\xc7\x76\xc5\x56\x11\x38\x21\x59\x7d\x2e\xd6\x12\x38\x8a\xc8\xf8\x51\x7a\xfc\xb8\x50\x82\x3a\xca\x11\x09\xec\xe5\x81\x6d\x94\x4d\x56\xce\x89\xb6\x55\xe7\x65\xd6\x60\x32\x9c\xb5\x98\xe6\x92\xd9\xed\xd6\x36\x29\xf9\xa5\x81\x0d\x52\xad\xcf\x25\xad\xd7\xe3\x67\xf7\x89\x9f\xa8\x97\x91\xdd\x4c\x9d\x9f\xbb\xdd\x5a\x97\x52\x50\x12\x28\xf9\x5c\xde\xe6\x73\xd1\x08\x9a\xc3\xe3\x97\x1a\xf1\xd5\x70\x5d\x4b\x1f\x95\x9a\xdc\x6e\xa5\x70\xc6\xa5\x75\xac\xc1\xe7\xd2\xf3\xec\x2f\x8f\xec\xc5\x42\x1e\xf9\xa5\x7a\x15\x25\x27\xcf\x2b\x7d\x10\x79\xa4\xb7\x1a\xf2\xf0\x2a\xb3\x72\xfd\x1f\xc9\x69\x3e\x17\x4b\xf2\x7f\x84\xc8\xf8\x86\x3c\xec\x7a\x02\x17\x55\x0b\xfd\xd8\xab\x94\xdb\xfd\x9f\x48\xf7\x6f\xf3\xb9\x64\x4f\x60\xd9\xc0\xf8\x71\xa1\x02\x16\x51\x8a\xdb\xad\x6d\xe3\x05\xb4\xd1\x28\xa9\x89\xf3\x13\x92\x5f\xc6\x60\xf2\xcb\x68\xa1\xa5\x14\xe3\x76\x6b\x6b\x78\x9a\x6a\x79\x93\xcf\x45\x95\x7a\xfc\x9c\x3e\xba\x22\xe4\x47\x39\x2e\xda\x7c\x44\x54\xa1\xcc\xe1\x4f\xf8\x90\xed\xf5\xb9\xa8\x54\xe7\xa7\x9f\x5c\xec\xbc\xba\x2b\x56\x84\xab\x7a\x41\xe4\x99\x32\x88\x5c\x52\xda\xe8\x36\x43\x2e\x95\x39\xfe\x4c\xf9\xa8\xcf\x25\x1f\xf5\x67\x8a\xf8\x89\x83\xc9\x25\x91\xcb\xe5\x46\x5d\x90\x39\xfe\x44\x79\x5e\xbb\xcf\x25\x2f\xf1\xaf\x1c\x52\xaf\x5c\x54\x41\xd9\x22\x7e\x55\xd6\xa5\x93\xd2\x02\xda\xea\x73\x49\xab\x03\xfa\x19\xd6\x7d\xd3\x50\x7a\x38\xcd\x12\x52\x43\x69\xda\x7c\xf2\x4a\x9f\x8b\x1c\xda\xfe\x08\xb9\xe8\x75\x15\x1b\x09\x72\xda\xe9\xd9\xcf\xdc\x5a\x96\x52\x95\x7d\x49\x65\x3e\x9f\xcb\x38\x4b\x50\xc8\xa4\x57\x9f\x32\xdb\xa9\x70\xc5\x0a\xa5\x2a\x5b\xaf\x65\x84\x4e\x8b\x59\x45\x2b\x6f\x10\x9a\x45\x8b\xe9\x9f\x6e\xed\xa0\xb6\x9d\x8d\xa2\x05\x1c\x70\xb4\x1d\x82\xcf\xf2\x08\x3e\x8d\xaa\x45\x51\x39\xbd\x28\x64\xb7\x43\xdb\xcb\xcc\xd4\xa2\x1d\xe4\xb0\x23\x77\x50\x9e\x76\xfc\x8a\x69\xd6\x6a\xc7\x79\x9a\xc0\x1e\xa9\xc8\xe7\x92\x32\xa5\x76\xed\xe2\xe0\x69\xec\xa4\x84\xd2\x2c\xd5\xce\xf2\x34\xfe\xf7\xe5\x6c\x9f\xeb\xb4\xfc\x93\x8b\xba\x0c\x6b\x23\xda\x55\x4f\x43\x4a\x2d\xad\x27\xbb\xdb\xad\xad\xd2\xce\x8b\x24\x85\xf2\x5e\x9f\x8b\x2d\xff\xc4\x28\x23\x2c\x1b\x5d\x0b\xca\xe9\xc5\x15\x2b\xf4\x4a\xf8\x5c\x6c\xaf\xf6\xd1\x60\x98\xcc\x63\x2a\x1e\xaa\xa2\x02\xb7\x3b\x08\xf9\xa4\x9b\x12\x7d\x2e\xf6\xf6\x9f\x2e\x87\xf7\x3a\xa4\xac\x97\x4f\xba\xb5\xbd\x52\x95\xcf\x25\x35\x52\xeb\xe5\xe2\xbb\x28\x96\xe3\x83\x7c\xd2\x1d\x38\x2f\xa7\xfb\x5c\x64\x97\xb6\x0c\xc2\x4b\xbc\x61\x1f\x5e\x3a\xef\x76\x6b\x9b\x79\xec\xe9\x42\x73\x4f\xf6\xc1\xaa\x48\x3d\x9f\x55\x47\xa9\x54\xc7\x55\x4a\x3e\x5b\xaf\x1d\x97\x9c\x02\x0f\x8f\x0c\x68\xdb\xb0\xde\x96\xd7\x51\x81\xde\x31\x18\xab\xd3\xf6\x51\x09\xc5\xfa\x5c\xf2\x56\xcd\x1b\xc6\xe6\x81\xfd\xb9\xa4\x9e\xb2\xa8\xc6\xed\xd6\xee\x67\xb1\x77\x6b\x3b\x22\xf1\xb0\x7c\xa0\x4d\x29\xaf\x95\x96\xb9\xdd\x2c\xfa\xbe\xc0\x37\xe4\xb5\x3e\x17\x65\x44\xc6\x8b\xb4\x11\xe5\x35\xb4\xe5\x98\xe0\x24\xe6\x3e\xad\x52\x9b\xcb\x66\xfb\x5c\xd2\xe2\x70\xbe\xfd\x31\xb1\xbc\x96\x2b\x3a\xc3\x5c\x6d\xaf\xc4\x63\xce\x1d\x80\x27\x86\x4c\x72\x96\x90\x83\xaa\x44\xc6\xf5\xa5\x81\xb5\x72\x91\xcf\xc5\x52\xfc\xa7\x44\xbe\xf9\x83\xf5\xfd\xfc\x25\x94\x6f\xc8\xc4\x59\x12\xf8\xbe\xf4\xf4\x76\x6e\x82\x02\x0b\x41\x28\x1a\x4c\x86\x45\xcd\x54\x23\x30\x71\x2f\x5b\x50\x18\xa8\xa2\x7c\xa9\x94\x73\xae\xe9\x63\xda\xbe\x69\x42\x32\x2c\x6a\xa6\x05\x14\x2d\x9c\x90\x05\x85\x81\x5c\xb9\xdb\xe7\x22\x67\xdf\xf8\x91\x98\x58\xd4\x4c\xeb\x4e\x70\xab\xc5\x16\x14\xfa\x3f\x3a\x20\x30\xd1\xae\xc7\xed\x2f\x97\xa2\x66\xca\x5d\xb1\x82\xe7\xda\x23\x67\xf9\x5c\x94\x3d\xa4\xed\x6c\x23\xbb\x81\x89\xe6\x5c\x7f\x53\x1f\x4c\xb4\x0f\x26\x17\x7b\x1b\xdd\x60\x60\xa2\x39\xd7\x7f\xf7\x97\xc1\xc4\xe8\x6c\x7f\xd6\x97\xc5\xc4\xe8\xec\x4b\x6f\x47\x62\xa2\x7d\x20\x26\xda\x5d\xb4\xfe\x84\x5b\xcb\xe5\x71\x67\x85\x30\xd1\x3e\x00\x13\xed\x2e\xb2\xad\x58\xc1\x99\x68\x91\x0f\x0b\x4c\x2c\x1f\x88\x89\xe5\xd4\xcc\x31\xf1\x63\xad\x47\x56\xa5\x56\x8e\x89\x81\x5f\x5e\x19\x13\x0f\x6b\x3b\x79\xf4\x30\x26\xa6\x6a\x31\x57\x4c\xb3\x55\x3b\xce\xd3\x84\x31\xb1\x4a\x2b\x1a\x02\x13\x7b\xd3\xac\xd7\xfe\xce\xd3\x84\x30\x71\x89\x56\x8b\xfe\xfd\x48\x4f\xc3\x93\x6c\x11\x98\xd8\xa5\xfd\x4d\x24\xd1\x31\xb1\x52\x9b\x07\x42\xe3\x00\x4c\x6c\x24\xd7\x8a\x15\xda\x39\xa3\xce\x2e\x71\xc7\x47\x6f\xbe\x11\xd8\x29\x9d\x74\xbb\x03\x0f\x1a\xf1\xde\x0b\x1c\x1e\x80\x0f\x21\xd5\xa6\x12\x9a\x47\x2e\xb7\x5b\x7b\x43\xdb\x29\x1d\xa5\x4e\x8e\x9f\xf2\x49\x6d\xed\x17\xb1\x2f\xd2\xe7\xd4\xa2\xfd\x5a\x2a\xf1\xb9\xa4\x76\xb2\x7f\x31\xfb\xc2\xd3\x04\xde\x94\x67\xf9\x5c\x94\x24\xb5\x6b\xff\x1a\x5c\x2e\x24\x97\xd3\x22\x6a\x72\xbb\xb5\x07\xfe\x22\x7d\x4e\x6f\xfa\xbb\x59\xba\xcf\x25\xef\xd0\xfe\xd2\x1f\x5f\x0c\x6d\x37\x8c\x85\x74\x8e\x5e\xbc\xe8\x73\xc9\xfb\xb5\x37\x07\xb7\x15\xb2\x87\x9c\x94\xef\x76\x7f\x22\xad\x77\x73\x28\x64\xb3\xb5\xe2\x21\xb1\xdf\xe4\xa1\x06\xca\x74\xbb\xcf\x4b\xeb\xdd\x94\x4f\x9c\x83\x75\xda\xd0\x76\xa2\x5e\x74\x9f\x2e\x69\xbd\x5b\x7b\x4b\x5e\xe7\x73\x51\x3a\x35\x5f\x66\x1c\xb1\x5c\xf4\x9c\x4d\x3c\x3a\x13\xe8\xb9\x9e\xc7\x75\x46\xf6\x7d\x45\x6f\x4d\x67\x2d\x45\x0b\x61\xec\x91\xf6\xd4\x6a\x72\x9d\xcf\xc5\xd2\x03\xb1\x7a\xbf\x74\x0e\xd6\xf7\x9d\xb5\x14\x4f\x8d\xbc\x5f\xf2\x04\x9f\x4b\x8f\x9d\xf7\xb9\x64\x57\x60\xb7\x38\x73\x63\x90\xbe\x5f\x5d\x43\x36\x1d\x5c\xa4\x9d\xf7\x6b\x47\x28\x57\x60\xf4\x7c\xed\xd7\x83\x94\x11\x52\x1c\x67\x3d\x95\x8b\x81\xd6\x5a\x69\x6f\x8d\xb6\x3b\x12\x13\x9d\x03\xfc\x66\x67\xad\xd4\xea\x76\x4b\x7b\x6a\x03\x2f\xb1\xb7\x45\x9f\xae\x19\x88\x85\x35\x35\x94\xb3\x62\x85\xb4\xfb\x7e\xed\xb0\x00\x12\x1b\xf4\x33\x1e\x07\x60\xa1\xa3\xc9\x30\x69\x07\xa4\x63\xe5\xda\x68\x36\xc3\xe7\x92\xf7\xfa\x0b\x11\x19\xbf\x8f\x3c\x1c\x0b\x28\x8b\x6a\x45\xfd\x8e\x95\x6b\xd1\xf2\x03\xa7\x7d\x2e\x39\xdb\xff\xfe\xc0\xf8\x71\xa1\xf8\x45\x54\x66\xc4\x0f\x7c\x22\x95\x4b\x99\x3e\x97\x54\x14\xd8\xa3\xd7\xcf\x11\xd4\x06\x49\xd3\x44\xd5\xc2\xb1\x10\x69\xbc\x54\x2c\xd7\xfb\x5c\x54\xad\x6d\x44\x1f\xbe\x22\xf0\xd0\xd1\x44\x2b\xfd\x6e\x2d\x97\xc7\xaf\x0f\xe1\xa1\x63\x00\x1e\x3a\x9a\xa8\x68\xc5\x0a\x1e\xe9\x63\xd6\x2a\x64\x57\xda\x1f\x0f\xd3\xa8\x94\x5e\xa0\x23\xee\xbf\x69\x2e\x72\xf3\xd1\x1a\xf3\xf9\x6b\x06\xfa\x04\xe1\xfe\x58\x42\x2f\x52\x85\xdb\xad\x9d\xd4\x5e\xe1\xf1\xb5\xad\x34\xcb\xe7\x92\x5b\x28\xd6\x7f\xf0\x32\x69\xbe\x2f\x54\xe4\x3d\x6d\x2f\x4f\x13\xf8\x44\x4a\xf2\xb9\xa4\x7a\x3a\xaf\xaf\x61\xd0\xd3\x2c\xed\x8b\x87\xa1\x34\xdb\xb5\x3f\x90\x5b\xf6\xfb\x37\xc8\x35\x3e\x57\x97\xfc\x48\x60\x06\xfa\x8f\x3d\x43\x78\x18\x4a\xb2\x59\xfb\x0b\x2f\xc6\xf0\xfe\xb5\x40\x75\xc4\xd8\xb3\x17\xe7\x4a\xe8\xfb\x2b\x56\x68\xbf\x33\x2a\x9d\x12\xc8\x17\xf9\xb6\xf7\xc9\x57\xf4\x64\x6a\xa7\x7a\x2a\x77\xbb\x4f\x68\x9b\xa8\x53\x7a\x8d\xec\xdc\xa5\x3c\x10\xa8\xed\x13\x3f\x02\x17\xd3\xa8\x9d\x16\x73\xa7\xf2\xb4\xb6\x8d\x3a\xa5\xa3\x3a\x2c\x06\x16\x0f\xf0\x43\xc2\xf2\xc9\xa7\x2d\x86\x8d\xd9\x42\x5d\xf2\xcd\x5a\x95\x54\xe6\x73\x49\xd5\xb4\x8a\x5b\xd0\xc1\xd2\xd8\x7b\xd3\x6c\xd5\xde\xa3\x2e\xf9\x96\x40\xaa\xdc\xe6\x73\x6d\x97\xce\x05\xb6\xf5\x29\x27\x52\x3e\xa1\x24\x9b\xb4\xa3\x3c\x89\x7f\x0d\x53\x7d\x2e\xb9\x33\xb0\x57\x8f\xdf\x1f\x17\xf3\x69\xcb\x8a\x15\xda\x7e\x5a\x23\xdf\xea\xf1\xb9\x64\x6f\xc0\x03\x42\xc7\x00\xf9\xc8\xd4\x41\x4e\x9e\xef\x31\x6d\x0d\x79\xc9\x29\x2d\x16\xd0\x38\x57\xb7\x03\x1d\x91\xfa\xa6\xe7\xdb\x21\x75\xb9\xdd\x81\x5f\x90\x57\xfa\xf3\x29\x9f\x4b\x3e\x1e\x68\x8d\x88\xd7\xc7\xbe\x74\x50\x29\x39\xdd\x6e\xed\x84\xf6\x07\xf2\xd2\x83\xba\xff\xa9\xed\x44\xbf\xf8\x61\x39\x1a\x8c\x68\xbf\x08\x82\xbc\x7c\xfc\x22\x2f\xf5\xb9\xa8\x98\x72\xb5\x93\x18\xc0\xbb\x80\x52\x53\x28\x49\xd7\x47\x3c\x45\xe0\x7d\xd6\xe6\x73\x49\xe5\x9f\x0f\xf0\x45\x43\x5e\xb4\x6e\x2b\x68\x27\xad\x97\xb2\x7c\x2e\xa9\x53\xdb\x8b\xa1\xc6\x16\xb2\x87\x2a\xa9\xd0\xed\x3e\x4e\x4e\x37\x87\x38\xf9\x68\xc0\x35\xa4\xbd\x90\x3d\x54\xc1\x5d\xae\x73\xe4\x74\x4b\x0b\xb8\x8e\xc9\xe9\x5a\xee\x65\xe7\xb6\xc6\x0a\x5c\x3f\x42\x4e\x37\xb9\xa5\x94\x30\x33\x43\xd9\x0c\x63\x6a\x8b\x9c\x6e\xed\x0c\xf3\xea\x88\xdb\xcf\x3f\x37\x6c\x46\x79\x0d\x81\xdc\x1c\x8e\xa8\xa5\xe1\x33\xb6\xca\xe7\x92\xdf\xf7\x67\x63\xe0\xd8\x42\x09\x59\xd0\x1a\x8a\xa6\x36\x23\xc1\xe7\xf2\xef\xde\xf4\xb9\x64\xa7\xbf\x67\xe8\xb1\x48\x0d\xa5\xd0\x3c\x23\xbe\xe6\x93\x5c\x7d\x31\x72\xa8\x34\x85\x3a\xae\xf2\x34\xc7\x29\x4f\xee\xe0\x38\xaf\x1d\xec\x3b\x9f\x63\x0a\xdb\x19\xeb\xac\x1a\x6a\xa1\x68\xb7\x96\x4b\xcd\x8d\xda\x26\x01\x92\x22\x5e\x3f\x8c\x9c\x55\x43\x05\x2b\x56\xf0\x38\x27\xb8\xb7\xdd\x77\x4c\xee\x30\x30\x32\x87\xb6\xd1\x11\xf7\x67\xda\x43\xd9\x4a\x15\x87\xc8\x4b\x6a\x5f\xbf\x36\xc4\x66\x3a\xd9\x69\x9b\x50\x28\x9f\xb6\x32\x5b\xa9\xd2\xf6\x93\xc3\xe7\x92\x57\xfa\x2e\xb5\x0e\xf0\x85\x1d\x61\xbd\x0d\xa5\x39\xae\xf5\x64\x2b\x55\x81\x23\x42\xb5\xca\xe8\x6f\x97\xf6\xf7\x9f\xb7\x70\x84\xfb\x7f\x22\xfd\x46\xa4\xd9\xab\x75\xe7\x2a\xb3\xfc\xc7\xf9\xe8\xf2\xb4\x1c\xe7\x37\xa3\xff\xdc\x88\x23\xd4\xff\x53\xe8\xd7\xba\xa5\xd6\x5e\xcd\x51\x2a\x23\x27\x47\xfa\xcc\x2f\x38\x74\x2d\xc8\xa4\xdd\x5c\xd5\x45\x85\x8d\xe1\x42\xdf\x71\x97\x23\x84\x8f\x39\xe4\xe5\xf9\x1e\xd1\xaa\x1c\x4c\xa2\x52\x0e\x8f\x47\xfd\x96\x01\xf3\x44\x8e\x30\x3e\x66\xd0\x76\x3e\x4e\xbb\xa0\xdd\x97\xcb\xf2\x75\x78\xf4\xa7\xa0\xff\xdc\x55\xaf\x7c\xd2\x69\x97\x61\x73\xbe\x9b\xcb\xca\xb4\xad\x7c\xb4\x2b\x35\xd1\x28\x7f\xdb\x10\x69\xec\x3c\xcd\x51\x31\xdd\x75\x54\xeb\xb2\xb3\xe9\x81\x76\xee\x16\xec\x93\x1a\xfd\x87\xfb\x96\x13\x29\x9f\x74\xfa\xa5\x21\x9f\xd7\x72\xd9\x6c\xff\x47\x2c\xc9\xe7\x92\xd3\xfc\x1f\xa1\xef\x9c\x94\x23\x34\xa3\x46\xbf\x5c\xb1\x82\x47\xdd\xb3\x9a\x5b\x40\xbf\xbb\xdf\xbc\x9f\x21\xc7\x52\xe9\x13\xb7\x3b\xb0\x7a\x86\x52\xe8\x73\xb1\x86\x4b\xeb\x06\xcc\x27\x86\xea\x69\xa2\x6c\xee\x09\xba\xdd\x9f\x6b\xf3\x4b\xa4\x5f\xd3\x1c\x1a\xe1\x73\xc9\xdb\x3e\x0f\x94\xf4\x9d\xaf\x0c\xbb\x51\x34\x8b\xdc\x54\xed\x76\x6b\x9f\x6b\xeb\x4b\xa5\xe3\x3a\x3c\x06\xe6\x5e\x4e\xcf\xb6\x70\x43\xa6\x1d\xd6\x3c\xe5\xd2\x49\x6d\xab\xbc\xc1\xe7\x22\x2b\x65\x1b\x36\xc3\x3e\x88\x4c\x42\x49\xbc\xda\x6b\x15\xd2\xc9\xc0\x51\xd6\xe2\x73\x49\xd6\xc0\x09\xf4\x9d\xbf\x34\xdc\x30\xca\xa6\x9d\x5c\x26\xa5\xd2\x49\xd1\x46\x3c\x62\x1f\x5b\xed\x08\xd9\x8c\x12\x5a\x4d\xb3\xdd\xee\x8f\xb5\xca\x06\x6a\xe1\x7c\xc8\xbe\xc0\x7a\x6d\x1e\xfa\xcd\x43\x87\xdc\x30\x99\x2a\xe8\x05\xde\x38\xc7\xb5\xf2\x79\xf4\x1d\x69\xe3\x67\x3e\x97\xdc\xa8\x4d\xd6\x1a\xfb\xce\x6f\x87\xf8\xa8\x90\x3e\x76\xbb\x03\x6d\xf3\xa4\x83\xc2\x94\x2e\x0e\xbc\xd0\x77\xde\xbc\x57\x86\x95\xd4\x44\x0f\xb9\xdd\xda\x41\xcd\x3b\x8f\x16\xeb\xae\xa8\xb6\x1d\xfd\xe6\xe5\xc3\xf2\x30\xd8\xd0\xbc\xda\xde\x46\xfa\x8e\xf6\x2e\xdb\x27\x50\xe8\x48\xbf\xf9\xed\x10\x1f\xba\x93\xf1\xda\x5c\x72\xc9\x5d\x3e\x17\x65\x6a\x47\xfb\xe2\xb3\xcd\xb0\x15\xe4\xa1\x11\xd4\xce\x4d\x9d\x9b\x03\x95\xbc\xcb\x3f\x63\x00\xf6\xf3\xb8\x76\x23\x72\xac\x18\x77\x9d\x70\xb3\xcc\xc3\x3e\x97\x9c\xe1\x3f\x36\x48\xdc\x90\x9d\x18\x43\x8b\xdd\x6e\xed\x63\xb7\x74\x41\x52\x7d\x2e\x69\x46\x60\xd7\xd0\x71\x6d\xc2\x37\x3e\xe2\xa6\x1a\xc1\x6f\x96\x76\x04\x8a\x58\x1f\x09\x93\x24\x56\x31\xe5\xa2\x90\xd7\x53\xdc\x0f\x23\x96\x77\xda\x46\x50\x42\x9c\xc5\x58\xa5\x3e\x7e\xa2\x71\x47\x8c\xdd\x9a\x90\x6e\x9f\x46\xf6\xde\x83\x79\xe5\x88\x2b\x63\xe2\x43\x6f\x88\x6a\xfe\xf9\xbb\x47\x5f\x98\x32\x72\x74\x96\x7f\x5c\x46\xd5\xb8\xe4\xd8\xaf\x8f\x5d\xf8\xe8\xf8\x84\x87\x7f\x77\xf0\xf4\xa7\xd2\xc6\xc0\xc3\xf9\xd3\x1f\xbc\x71\xea\x8d\x25\xcf\x14\x3e\xd8\xf4\xe8\x83\x6c\x41\xeb\xd1\x3f\x53\xf4\xd8\xbc\x8e\x1b\x1e\x91\xb2\xe8\x2a\x9a\x5c\x55\x55\xeb\xb8\xf7\x52\xa3\xf6\xab\x47\xa3\xcf\x45\xc7\xde\x36\xfb\x87\x34\x59\xfe\xee\xee\xdd\x9f\x38\x95\x49\x69\xec\xde\xc9\x53\x6e\x9f\x76\xcf\xe3\xfe\xe7\x5e\x7e\x79\xf5\xab\x31\xdb\xd7\xcb\x35\x09\xab\x7e\x30\xfa\x96\xad\xff\x13\xf5\x09\xdf\x8e\x7d\xf9\xfa\x7c\x3f\x7f\xfa\xbc\xe9\x53\x6f\xbc\xe5\x99\xa6\x50\x7d\x28\x29\x6f\xac\x7e\xd1\xff\x17\xad\x90\xcb\xff\xac\x51\x21\x29\x73\xf4\x0f\x56\x19\x17\x70\xff\xa7\x75\x0a\xbd\x11\x34\x6e\xea\x8e\xff\x0f\xda\xa8\xe4\x46\xfb\xf4\x79\x45\xf9\xdf\x78\xba\xe0\x4b\x35\x12\xed\x9f\x76\xfb\x94\xc9\xf7\xb2\xb4\x49\x8a\x93\x3d\xee\xb7\xf4\x6f\xa5\xff\x91\x3a\x7d\xc1\x76\x5a\xc9\xeb\xf4\xe0\xf4\xfc\x6f\x3c\x3d\x36\xdc\x50\x89\xbc\xa1\x52\x96\x14\xfc\x27\x95\xd2\x5b\xaa\xe0\xd5\x9b\xc3\x75\x2a\x12\xb7\x2c\x7d\x05\x25\xf8\xea\x95\xeb\x14\xf1\xb2\x7c\x5c\xdc\x7f\xab\x53\x1d\xef\x8a\xaf\xae\xbe\x6b\xf6\xc8\x75\x23\xb7\xbd\xa0\xbd\x69\xf4\xae\xce\x69\xa1\x4a\xfe\x85\xa2\x53\x1c\x1d\xf6\x96\x21\xeb\xc8\x9e\xcd\xb5\xe5\xda\x1e\x7f\x8a\xb2\x84\x46\xd6\x71\x8d\xac\x73\xf9\xab\x43\x8d\xb7\xce\xb2\xe2\xe5\xa4\xa2\x9f\xa1\x4f\x3d\x27\xa1\x00\xb7\x70\xfb\xf5\x25\xea\x39\x7e\xa2\xe3\xbf\xd5\xdb\x7e\xff\x92\xa8\x68\xec\x0b\x23\xb7\x3f\xef\x79\xf5\xe6\xfc\xe9\x0f\x4e\xb7\xdf\x58\xd2\xb9\xb0\xb7\xdf\x39\x52\x68\x58\x6a\x7b\xee\x65\xab\x3a\x65\xca\xb7\x57\x3c\xf9\x83\x41\xab\x2a\x35\x24\xbd\xbc\xc2\x72\xe3\x6e\xfb\x60\x75\xbd\xfd\x4b\xd6\x35\xfe\xb2\xbd\x50\xac\x1b\xb9\x5c\xab\xf6\xad\xac\xa5\xe4\xc6\xa9\xd3\xe7\x4d\xcf\x6f\xee\xbc\xbe\xb7\x5d\x87\x99\x72\x93\xaf\xd4\xb0\xa2\xb6\xf4\x04\xd7\xe0\x3a\xa1\xc1\xd2\xe3\x97\x3e\xec\x6d\xd9\x6b\x7e\x56\x29\x9a\xf6\x7f\x43\xdb\x5e\xa6\xbe\x5f\xba\x6d\xaf\x33\xf0\xa7\xb9\x33\xa2\xaf\xf2\xc6\x1d\xf7\xa8\xe3\x3f\xae\xae\xde\xba\x37\xbd\x52\x2c\x96\xf6\x06\x4f\x07\xcf\xc8\x89\x26\x09\x32\x46\x61\x1c\xf7\x94\xe5\x81\xe6\x20\x3e\x2e\xf2\xfa\xbb\x70\x5f\x4c\x8c\x34\x63\x59\x94\x3b\xf3\x86\xdb\x17\xce\x5f\xb7\x7b\xdb\x37\x0d\x8c\x64\x3d\xfd\xec\xd5\xa5\x5f\xcb\x08\xe0\xc6\x69\x69\x27\x6d\xaf\xa9\x53\x43\x60\xf8\xc5\x78\x90\xfb\xf1\x60\x88\x32\x31\xd2\xf4\x44\xf5\xf2\xf0\x53\xc3\xf6\xf4\xe7\xc1\x75\x69\x7f\x2f\x0f\x0a\x85\xac\xcc\x10\x3c\xf4\x87\xdb\xcb\xc8\x21\x6c\x2a\x7e\x30\xb8\x20\xfa\xc2\xe7\xa5\x99\x83\x49\x62\x48\x59\x5c\x81\x8f\x08\x59\xf4\xc2\xfb\x77\x7a\xf9\x78\xc5\xc0\xf7\xcb\xf3\xa1\x4b\x83\x23\x39\xe7\xe3\x0f\x82\x8f\x22\xc4\x20\x19\x99\x98\x02\xc8\x97\x81\xea\x21\x04\x33\x7e\x50\x48\xbe\xa6\x97\xb1\xc7\x0d\x50\x56\xb6\x0e\x86\xbd\x97\x56\x45\x08\x69\x51\x08\x7e\x23\x78\x1b\x8e\x31\xb8\x16\xb6\xbe\xbc\x0d\x84\xd7\xc1\xa5\x35\x7e\x70\x18\x8d\xd0\xa1\x6d\x06\x8e\x72\xee\x06\xc2\x65\x24\x77\xca\xb4\x30\x62\x0e\xe4\x6f\x6a\x7f\xfe\xfa\x43\x44\x7f\xe1\x19\xa0\x38\x7e\x08\xe8\xfb\x5e\x2f\x87\xae\x10\xf8\x85\x59\xec\xd7\xe9\x87\xf7\x91\x60\x18\xe6\xae\x2c\xc3\x2b\xf0\x38\xa8\x0c\x7b\xe1\x6a\x59\x2f\x8b\x5b\x0d\xbc\xfa\x02\x1c\xea\x52\x14\xc8\xc4\xb0\x3a\x78\x96\xed\x32\x49\x62\xbd\xff\x35\xc8\xd5\xcf\x61\x09\xad\xf5\xcd\xb0\x8e\x25\xb1\x77\x69\x30\xe7\x35\xac\x7e\xab\x69\xca\x03\x8b\xda\x16\x8d\xc9\x22\xdb\x35\x29\xda\xdf\xb5\xbf\x68\x81\xe0\xab\x91\x98\xf5\x43\xa3\x7f\x92\x26\xd5\x05\xd6\x3c\xd3\xbe\xf3\xc0\x83\xbf\xfd\xf9\x4b\x7f\x7b\x54\x7b\x47\xfb\x35\xc9\xf2\x6b\xfd\xe0\x8b\x6e\x0e\x77\xd4\xff\x0e\x7f\xe1\xd5\x69\x43\xf1\x17\xc6\xb3\x4d\x06\x88\x7d\x31\xfe\x5c\x71\xbd\x3e\xf3\x97\xe2\xaf\x1f\xba\xa4\x5f\x51\x7e\x61\xac\xa3\xd4\x2b\x4a\xb0\x2f\xde\xbc\x65\x48\xf0\xbf\xc3\x9f\x72\x25\xf9\xf5\x62\x20\xd9\x0d\xe4\xfb\xa2\xfc\x2d\xe8\x85\xc0\x30\x8f\x45\x48\x10\x3e\xfa\x57\x86\xe4\xf1\x72\xc8\x78\x39\x61\x7a\x07\xc5\xc7\x4d\x06\x28\x0e\xce\x33\x7b\x63\x30\xa8\xa4\x92\x30\x3c\xf6\xe1\x3b\x0d\x53\x50\xf0\x45\xf8\x1e\x80\x9a\x97\xd5\xd2\xd7\x06\xc7\xce\x1f\x19\x80\x39\x34\xe7\x03\x61\x74\x54\x18\x39\xfb\xf3\x7d\xc3\x17\xe3\x3b\x7e\x80\xf6\x1a\xf8\x79\x65\xc6\x7b\x31\x95\xc6\x86\x90\xf4\x0a\xbc\xf7\x45\xaf\x77\x42\x90\xfa\x1f\xca\x3c\xfe\x4b\x68\xf6\x6b\x43\x60\x2d\xd9\x0d\x84\xfd\x52\x9c\x3f\xdc\xeb\x04\x2a\xc1\x4f\x85\x2d\xd8\x2f\xf6\xf1\x8d\xc6\x44\x61\xed\xed\xd6\x04\xa5\xcf\xad\x7d\x36\x63\xdd\x6b\x5f\x4b\x10\x11\x65\xb4\xb4\x31\x50\x17\x5a\xea\x3a\xfb\xa3\x9c\x92\xa5\x8e\x6f\x7c\xa5\xd7\x10\xfc\x29\xbc\xdc\xf6\xec\xee\xdd\xbf\x30\x16\xbe\x4a\x6f\x24\xd4\x3d\x90\x7c\x5d\xdb\xbf\x0f\xf5\x9a\x01\xf6\x54\x78\xf9\x6d\x3f\xde\x52\x86\xe0\x6d\x80\x71\x12\x3b\x21\x86\xe4\x6d\x5b\x2f\x53\x37\xdc\x9c\xf3\x87\x94\x56\x47\xda\x60\xbc\xf9\x1f\x88\x30\x9e\xd3\x93\xef\x9b\x9b\x90\xf6\xad\xeb\xb4\xf2\x30\x73\x4a\xf0\xb7\x82\xb7\xdd\x18\x8e\x24\x58\x91\xc3\x5b\x7d\x70\x2b\xca\x59\x18\x95\xa1\x8b\x50\x1e\x52\x80\xd7\x8a\x75\xe1\x4d\xd1\x2f\x0c\xdb\xeb\xf9\xe1\xcf\xaf\x0a\xf1\xb4\xb3\xe6\x0f\xd7\x96\x2d\xfd\x76\x2f\xd3\xa7\x43\x4f\x4c\x99\x77\xde\x51\x53\xd1\xb5\xfd\x27\xda\x4f\x42\xf2\xbc\xe5\x61\x4b\xf5\xc2\x64\xdf\xd2\xc1\xc5\xd9\x8f\xe7\x8c\x2b\xf1\x3c\x98\x64\x55\xd3\x17\xe0\xf9\xc7\xbd\xdc\x16\x56\x8e\xff\x43\xcd\xe2\xcc\xa1\x79\xee\x23\xe7\xbc\x64\xd7\x4c\xcb\xc3\xf7\x6a\xce\x08\x1d\x30\xfa\xd6\x7e\x61\x2b\xd2\xf5\x33\x94\x86\xb6\x16\x83\x6a\x6d\xe4\xea\xf0\xa1\xcc\x46\x7f\xdd\xa5\x31\xe1\x15\xdc\x83\xf7\xac\xc0\x40\x3d\x0e\x7c\xff\x7f\x13\xdf\x83\xe8\xf0\x15\xf9\x3e\xdb\x4f\x99\xaf\xcc\x36\x9d\x1b\xa8\xd6\x61\xbe\x77\x0b\x2c\xcb\x81\x03\x37\x7d\x39\x34\x8b\x90\xfc\xc4\x2b\x55\x60\xdd\xe0\xfa\x53\xcb\x55\x7e\xf1\xef\x2e\x5f\x13\xf5\xfa\x01\xea\xff\x33\xae\xfd\xf7\x06\xfe\x15\xaa\xcd\xff\xa6\xba\x0c\xd4\xfb\x2f\x51\x97\x4f\xfb\x76\x80\x2f\x5a\x17\xfa\xcb\xc0\xae\x20\xce\xd5\xa8\x54\x1a\x95\x83\x18\x1b\x71\x6f\xff\x55\x09\x71\xb1\x52\xda\xf8\x8c\x38\xfd\xf6\x16\xe3\xb2\x22\xef\x99\x5c\xf3\x8c\x3f\x3f\xf5\xe7\x7f\x9e\x3e\xf5\x40\xc5\xac\xe2\x86\xea\xb6\x65\x9b\x5e\x54\x76\xec\x6a\x98\x1f\xf8\xcc\xdf\xa2\x69\xda\xc5\xab\x48\xb2\xb8\xdc\xf2\xb4\xb5\x2f\x7c\xf0\x0f\xbf\xaf\x37\xff\xfd\xfa\x7d\xbe\xe2\x16\x57\x29\xbc\x6b\x43\xdc\x60\xed\x10\xf7\xb9\x7a\xc9\x2d\xb5\x9a\x46\x52\xe2\x3f\xfe\xb8\xe8\x8e\xbb\x67\x2e\x9a\xa7\x04\xa2\xa2\xe2\x95\x1d\xfe\x56\x4a\x69\xa6\x7f\xf8\xca\xde\x3b\x71\xd5\x79\xcb\x5d\xf7\xb1\x0a\xed\x78\x5b\x60\x16\xcf\x77\x4b\xf0\x8c\x52\xab\x1c\x14\xb7\x7e\xd9\xad\x09\x96\x08\x56\x53\xc8\x1a\x51\x13\x8b\xca\xd2\xc6\x61\x0b\xd9\x57\xad\x5d\xbb\xbc\x6d\xd9\xa6\xf5\xda\x81\x50\x45\x3a\xb4\xb3\xaf\x6b\x7f\xd1\x7e\x25\x99\x33\x47\x7c\xef\xd9\xef\xf5\xd0\xbd\x9c\xf3\x7c\xe9\xb4\xa8\x93\x96\xba\xe1\xc2\xb7\xc9\x0a\x09\xeb\x82\x67\xd8\x47\x6a\x2a\xe2\x31\x91\xb7\xf6\xd4\x09\xb6\x29\x2c\xbc\xf3\x92\x59\xc7\x4d\xa0\xd8\xfe\x97\x27\xc6\xad\xa3\x11\xbe\xd3\x34\xfc\xf9\xef\xff\xe2\x4d\xed\x4f\xda\x25\xcd\xaf\xfd\x99\x72\xff\xf1\xd7\x8e\x15\xce\x19\x8b\xbf\xb1\x70\xf6\x61\xf2\x48\x9b\x3e\xbe\x78\xe8\xb5\xe7\x7e\x9c\x64\xb6\x1c\xde\x76\xf8\xe4\x29\x52\x35\xed\x6c\xf3\xe3\x7f\x5d\x78\xdf\x3d\x77\x6b\x7f\x02\x64\x94\xb0\x1e\xe9\x8c\x31\x76\x4f\xd6\xeb\x39\xd4\xd8\xa4\x64\xb0\x71\xc8\x80\x09\x93\xf0\x88\x43\xe4\x2d\xc7\x5c\x36\xef\xb0\xc7\x56\x32\xd8\x18\x62\xc0\x44\x48\x78\xb4\x30\x28\xdf\x43\x8d\x09\x4a\x06\xf7\xff\x07\xce\x2c\xbc\x15\x1e\x2b\xe9\xbc\x47\x5f\x36\x7f\x25\x92\xf7\x41\xfc\xf7\x81\xf9\xf7\x7a\xea\x92\xb6\x9d\x1d\xa3\xa3\xaa\x15\xc3\x90\x80\x84\xe9\xd1\x72\x54\xec\xe3\x23\x63\xee\x89\x91\x62\x90\x73\xf7\xd5\x07\xdf\x99\xd2\x77\x77\x90\xa2\x6f\xc9\x1c\x41\xa6\xde\x2d\x41\x34\x72\xcc\xcd\x0f\x52\xe9\xf4\xf7\x6f\x56\x16\x1b\xdd\xad\x36\x79\x5c\xfd\x8f\x13\x66\xbe\x2e\xee\x69\x94\xb4\x55\xec\x18\x2d\x50\x4f\x09\xbb\xa9\xef\xd7\xd3\x41\xc1\x7a\x1d\x39\x22\xb7\xff\xac\x7a\xb6\xa5\xa1\xae\xf5\xd9\x75\x95\x9a\x2f\xed\xee\x6f\x87\x77\xfe\xa8\xc9\xb3\x1e\xb8\xaf\x2a\xb9\x67\x69\xde\x63\x1f\x8b\x02\xa6\x89\xbb\x93\xe4\x3e\xe7\x4f\x24\x0f\x3c\x81\x22\xbd\xdf\x69\x14\xbd\x68\xdf\xbb\xad\x48\x9c\x4b\xb1\xda\xc8\xf5\x86\x70\xee\xb2\xd6\xc5\x8e\xd2\x5c\xf5\x94\xd8\xdb\x9c\x63\xec\xa5\x1e\xb0\x49\x4c\x1e\xaa\xb4\xae\xa8\x05\x77\x4f\xfe\xea\x8c\x1b\x52\x32\x27\x46\xb5\x0d\x5b\x70\x77\xd6\x6d\x37\x17\x8e\xb9\x76\x62\xcc\xfd\x83\x70\x70\xf4\xc1\xf6\x31\xd6\x31\xd9\x93\x16\x7d\x23\xd9\x3a\xe6\xda\xeb\xa8\x63\x00\x37\x5c\x86\x82\x1f\x53\x8c\x7e\x16\xd4\x10\xdc\x84\x14\x6d\xc8\xe2\x17\x53\xb9\xb3\xe1\xe0\xcc\x9f\xf6\x2f\x53\xb2\x5a\x56\x2c\xba\x7a\xca\xea\x2f\x56\x4e\x78\x0a\x63\xc8\x72\xec\x0d\x4e\x2a\xbf\x71\x5b\xe9\x80\xba\xa5\x5e\xbd\x68\x85\xe5\xc6\xa7\x73\xf5\x3a\x89\xf6\x33\xc5\x40\x36\x6e\x92\x4c\xa0\xf0\x00\x44\xb4\xd7\x6c\x2a\x1f\xdb\x36\xe5\xc0\xcc\xdf\xf2\x56\x92\x52\x2d\x53\x36\xe6\x25\x4f\x79\x75\xc8\xb4\x61\xd5\xe4\x69\x3f\x99\xb6\x78\x0c\x95\xe7\xee\xaf\x12\x2d\x1c\x9d\x5c\xf2\x42\x8e\x25\xf7\x47\x05\x42\x6f\x56\xb2\x03\xb4\xc4\x34\x02\x23\xc4\x9e\xde\x5e\x8d\x1c\x41\x5c\x25\x87\x6c\xd4\x95\xdf\x7d\xe6\x6b\x15\x2f\x7c\xf7\xf1\xdb\x93\xb5\xb3\x93\x1f\x8f\x1f\x64\x8f\xda\x85\xab\xcb\x6e\xbb\xb9\xf2\xea\xc7\xef\xce\xb8\xf9\x09\x6d\x55\xff\x8d\x6a\x86\xce\x1e\xa0\x2a\xf5\x68\xa4\xce\x2a\x5f\x52\x67\xd5\xa4\xdd\xbb\xdf\x1f\x98\x39\x6f\xbb\x63\x34\x57\x3d\x2a\x4e\xd3\x1f\x5a\x47\x12\x86\x6c\xb6\xf9\xd2\x46\x76\x8c\xb7\x58\xf2\x24\xbd\xc5\x32\x73\x68\xfa\xee\xdd\x86\xbc\x7b\xf9\x1e\xc0\xb5\x7e\xd6\xcb\x60\xfc\xe9\x69\xd5\x14\xaa\x32\x67\x7e\x91\xb4\xa6\x79\x6f\xbc\xf1\x5f\x45\x85\x85\x46\x5a\x86\x42\xb6\x43\x1e\x15\x1e\x27\x64\x03\x5f\xce\xd7\x28\xfc\x42\x7e\xc5\x40\xc7\x7a\x10\x0f\xe2\x4b\xf1\x12\x1a\xb1\x7c\x01\x5e\xf4\x31\xca\xfd\x57\x1c\x98\x44\x3a\x33\x0c\x4e\xb6\x43\xf2\x87\xc7\x9d\x13\x74\xcb\x70\x45\x3f\xd8\x79\x39\x9f\x37\x72\x00\x37\x88\x77\xfb\x85\xca\x1c\x64\xcc\xe0\xbc\xec\xf8\x60\xb0\x11\x6d\xef\x48\x40\x46\x19\xeb\x96\x93\x8d\xb9\xd6\xf4\xa1\x24\xde\xdf\x12\x96\x5d\x69\xbc\x3f\xc4\x8c\x6a\x78\x64\xaf\x97\xab\x1a\xe5\x4e\xbc\x42\xb9\xbd\xf3\x26\x65\x57\x9c\x23\x19\xa2\xe4\x77\x7a\x27\x98\xf5\xb2\x53\x86\xaa\xf3\x50\x73\x4d\x65\x97\x9f\x57\x1a\x7c\x22\x7e\x54\xc4\xdc\xbb\x8c\x7c\xd6\x2d\x5d\x34\xde\x5b\x4c\xe8\x5b\xee\x90\x73\x73\xf9\x97\x9d\x87\x1b\xfc\xe5\x44\xef\x8c\x1b\x61\x0b\xf3\xc8\x67\x95\x6e\x71\x4e\x84\xdd\x9a\x60\x4a\xcb\x48\xd3\x69\x8b\x3c\xbd\xf2\xfa\xdc\x17\xa6\x38\x72\xd7\xe5\x3a\x94\xf2\xea\xea\xcd\x0d\x0d\xe2\x5c\x60\xe2\x14\x5d\xb8\x88\xb6\x7e\xfd\x9e\x91\x37\xfc\x4b\x4a\x15\x2b\xdb\x70\x28\x66\xd9\xef\x42\xe1\xa5\x98\xc0\xa6\x61\x4f\x9a\x57\x81\x60\x0e\x9d\xf4\xc6\xff\x35\xaf\x0a\x3c\x0e\x0c\xdb\x76\x29\xc6\x37\x7f\xd8\x93\xc6\xef\xe1\xbf\xa8\xf9\xec\x20\xc4\x52\x43\x66\x01\x24\x4e\x65\x58\x22\xef\xc3\x32\x25\x0b\xd9\xac\x13\xd5\x26\x3b\x8a\x54\xa0\x52\xb2\x62\x99\xb4\x03\x95\xd2\x0e\x14\xb2\x1a\x14\xf1\x67\x52\x29\x8a\xa4\x4e\x14\x4a\xa5\x58\x22\x57\x60\x04\xeb\x44\x19\xeb\x44\x0b\xeb\x44\x85\x41\x69\xac\x13\x73\x59\x27\x4a\x59\x27\x1c\x46\x58\xcc\xe3\xf3\xb4\x3c\x8f\x10\xc9\x87\xa1\x9a\xb2\xd1\xa0\x2c\x03\x94\x3a\x78\x95\x24\x34\x2b\x67\xe0\x65\xad\xf0\xb2\xb9\xf0\x2a\x07\xd0\xac\xa6\xc2\x2b\xa7\xa0\x58\xda\x18\x6c\x54\x66\xc1\xcb\x96\xc1\x6b\x5a\x09\xaf\xda\x0e\xaf\x5a\x8b\x66\x45\x35\xc2\x52\x78\x59\x23\x6a\xd9\x06\x64\xaa\x31\xd8\xa2\xd8\x00\xd3\x2e\x40\x71\x02\x4c\x03\xd8\x06\xe4\x4a\x1b\xb1\x5a\xae\x40\x8c\xb4\x11\x36\xd6\x89\x1c\xb9\x2c\xe8\x67\xc7\xa9\x9c\x1d\x81\x53\x89\x85\x87\xa5\xa0\x46\x89\x45\x0d\xdb\x89\x1a\x39\x09\x99\xfc\xb3\x52\x0c\x8f\xd4\x84\x4e\xa9\x29\xd8\xc6\x2e\x8a\xcf\x1e\xd3\x71\x78\xf8\xef\xec\x82\x88\xef\xe1\xf1\xe4\x0d\xf0\xc8\x3e\xd4\xc8\x2d\xc8\x51\x8a\xb1\x8e\xad\x02\xd4\x63\xb0\x30\x0f\xa2\xf9\x67\xf9\x13\x38\xe4\x0c\xa4\xb2\x46\xda\x27\x67\xa0\x52\xc8\xd2\x90\x3d\xeb\xc4\x6a\xd6\x29\x7e\x6b\x62\x9d\x50\x45\x9c\x93\x98\xc7\x8e\x53\xa2\xba\x09\x73\xe5\x58\xe4\xb0\x33\x46\x9a\x4e\x14\xf2\xdf\x18\x82\x3e\x79\x3e\x6a\x84\x1c\xcd\xc8\x91\xcd\x28\xe0\x75\x51\x4a\xe1\x51\x0a\xd1\xc4\xe5\x4d\xdd\xc1\xe3\xb2\x19\x35\x72\x32\xf2\x79\x7a\x53\x0c\xae\x33\x68\xb6\x7c\x18\x85\x42\xee\x83\x90\xa9\x0b\xe0\x6d\x21\xda\x41\xa7\x57\x78\x28\xa7\xe0\x5a\xde\x16\x72\x4a\xf0\xf7\x72\x0a\xf2\x95\x33\xc8\x09\xb5\x43\x7f\x62\x9d\x68\x17\x9f\x63\xb0\x25\x92\x78\x5b\xf0\x36\x53\xb6\xc2\xc3\xe5\x3e\x18\x99\x9c\x70\xf2\xb6\xe0\xed\x10\x49\x52\x53\xf0\x45\xa9\x09\x1d\x52\x53\xf0\x3b\x52\x53\xf0\xa4\x90\xbf\xd1\x0e\x03\x88\xeb\x98\xfe\x7c\x5d\x24\xf1\xb6\x10\x6d\xbd\x4a\xaf\xab\x68\xfb\xfe\x21\xaf\x3b\xd7\x85\xa1\xc2\x33\xf0\x0a\xdd\x38\x83\x1c\x25\x17\x35\x42\x46\x3b\x2f\x1b\xbe\xc2\x43\xae\xcf\x22\xdd\x10\x21\xd7\x75\x5e\x1f\x35\x15\x50\x8a\xc1\xe4\x94\xe0\x3f\x78\x9d\xe5\x14\x14\x49\x4d\xc1\xd3\x72\x0a\x4c\x52\x53\xf0\x15\xd1\x1f\x9a\x50\x6b\x84\x1e\x65\x2f\x8a\xd9\x4e\x74\xf2\x3e\xc2\xf5\x54\xf4\x93\x8b\xf0\x08\x5a\x06\x2f\x8f\x63\x84\x73\x22\xbf\xcb\xf3\x45\x28\x49\x4d\xc1\x4f\x78\x3b\x8a\xb2\xfb\x87\x05\x50\xc3\x9f\x79\xbb\x5e\x40\x4d\xff\xd0\xb4\x1f\xcd\xa6\xf7\x51\xc3\xfb\x20\xef\x07\x46\x38\xc7\x08\xef\xe0\xfd\x92\xf7\x8d\x21\xc3\x0d\xc8\xe4\xfd\xa6\x7f\x28\xfa\x71\x31\xd6\x7d\xd1\x90\xf7\x77\xd1\xe7\x78\x7f\x5f\xd5\xdb\xef\x79\xdf\xeb\x1f\xca\x7a\xbf\x65\xea\x6c\x44\x2b\xc9\xa2\x3d\x3d\x4a\x19\xb6\x28\xa3\xb0\x4e\x49\x42\x69\x44\x5b\xe7\xa8\xa7\x44\x1c\x1d\x1b\x2e\x88\xf6\x6c\x51\x97\xa3\x5b\xc9\x41\x35\x9b\x1b\x3c\xce\x3a\xf1\xb6\x68\x43\x8e\x39\xa7\xe0\x91\xf3\xb1\x45\x4e\x81\x23\xd4\x0e\x52\x37\x2c\xec\x0c\xcc\xe6\x52\x6c\x51\xdb\x83\xc7\x43\xb2\x54\xd7\xa1\x59\x59\x80\x9a\xa8\x18\x34\x9b\x16\xa0\x46\x05\xa2\x05\x1f\x3a\x96\x39\x65\x1f\x2a\xd8\x6e\x54\x48\xe7\x82\x6e\x21\x97\xf3\x88\x0e\xc9\xc7\x64\xc1\x16\xd5\x82\x75\x6a\x19\x1c\xbc\x5c\x51\xd7\x33\xb0\x84\xeb\xb9\x13\xf9\x6c\x27\x66\xb1\x8d\x82\xea\xd9\x6a\x38\x98\x07\xf9\xac\x09\x15\xb2\x0f\x65\xa2\x0f\x58\x69\x03\xb3\xe2\x45\x66\x45\x03\xc7\xa1\xe8\x16\x78\xa3\xde\x87\xd7\xfc\x39\x6a\x4c\x59\xf0\xaa\x17\xe1\x65\x1f\xc3\x13\x95\x01\xaf\xf9\x3c\xbc\xa6\x6d\xf0\x84\xfa\x08\xc7\x00\xde\x0f\xc3\xba\xf0\x05\xdb\x88\xed\x44\x75\xff\xfe\xc6\xf1\x86\xf7\xf9\x01\xfd\xc2\x90\x5f\x7f\x7d\x13\x75\xdb\x88\x7c\xae\xeb\x91\x3c\x87\xd2\x99\xeb\xe1\x55\x1a\x75\x1b\xc1\x65\xdd\xbf\x9c\x50\x3e\xfd\xf9\x60\xad\x98\x15\xd9\x6f\xe5\x94\xe0\x62\xa9\x29\x18\x23\xa7\x80\x49\x4d\xc1\x2d\xfd\xf9\x50\x4a\xd1\x24\x6f\x08\x6a\x86\x9e\x2f\x35\xea\xe8\x0e\xd7\xb5\x9f\x7e\x2b\x39\xa8\x65\xed\xb0\x84\xfb\x79\xa2\x8e\x23\xaa\x15\xf3\x15\xb3\x88\x27\xda\x2e\x82\x1f\xc1\xc7\x50\xfd\x2e\x2c\x0f\x43\xdf\xe5\x56\x54\xa8\x99\xf0\xc8\xeb\x91\xc3\x65\x63\xda\x8a\x1a\x4e\x02\xd7\x0d\x7d\x66\xcb\x8c\xfe\xc5\x6d\x15\xef\x07\x47\xa0\xca\xa7\xa1\x2a\x75\xb0\xa8\x31\x80\xd0\x25\xa3\xdc\x10\x9e\xa8\x36\xa3\x3d\x4a\x61\x91\x37\x18\xba\xb6\x4a\xf0\xb8\x4e\xfc\xae\xf7\x25\x6e\x3f\x8b\x58\x83\xde\x4f\x0c\x3b\x5a\xcd\x49\xed\x40\x0d\xd7\x3b\x4e\x4a\x07\x2a\x78\x5d\x05\x4e\x85\xe2\x1d\x40\x8d\xc8\x6f\x95\xc0\xbd\x75\xa2\xcd\x74\xbb\x0b\x99\x87\x27\x91\x29\xb7\x02\x72\x61\xf0\x0c\xc7\x2e\xd5\x22\x6c\xf0\x3a\x83\x3c\x4a\x71\x70\xaf\x48\xb3\x57\xb7\x05\xaa\x0f\x35\x6a\x37\x6a\xd5\xa5\xc2\x2e\x67\x45\x90\x47\x50\x0e\xd6\xc9\x39\xc8\x62\x47\xb1\x99\x13\x97\x85\xd4\x14\xdc\x1b\x41\x25\x72\x0b\x8a\x0d\x5b\x0e\x25\x07\x36\xa5\x26\xc2\xa6\x1b\xbc\x8a\x7e\xb6\x0e\x0e\xae\x8b\x6c\x23\x20\x64\x79\x04\xb9\x3c\xe4\xb2\x16\x7e\x49\x0a\x3c\x8a\x19\x15\xbc\x8e\x4a\x39\xaf\x53\xb0\x84\x5d\x04\xe4\xf7\x0d\xbf\xc1\x48\x63\x8e\x41\x8d\x79\x39\x6a\xcc\xbb\x51\xa3\xba\x91\xa3\x98\x91\x63\xaa\x41\x8e\x69\x1b\x32\x79\xbd\x14\x8e\xd5\x65\x00\x3b\x26\xea\x7b\x94\x13\xab\x43\x17\x27\x29\x23\xb8\x53\x36\xa3\x4b\x8e\x46\xae\x2c\x21\x9b\xa9\xe8\x52\x56\x21\x43\xde\x05\x0b\xed\x42\x92\xbc\x1a\x49\x3c\x14\xb4\x13\x49\x40\xb0\x9d\x93\xb4\x1c\xb1\xd2\x72\x58\x23\x7c\xb2\x6c\x41\xc7\xb1\x93\x13\x10\x5c\xc7\x8e\x53\x32\x10\xfc\x0e\xa0\x15\xf0\xef\x80\xf6\x0a\xa0\xfd\x51\xa7\x60\x99\x41\xed\x06\x65\x46\x12\x3b\x8e\x93\xdc\x77\x62\x5d\x54\x45\x1b\x11\xcd\x8e\xe3\x3d\xb6\x1d\xeb\x01\x6d\x17\x10\xcc\x91\x77\xc2\x22\x65\xa3\x4b\x9e\x8b\x79\xf2\x29\x64\xc9\x33\x30\x43\xae\x86\x67\x28\x02\xb4\x0a\x40\x73\xf2\xfa\x00\x5a\x8f\x4e\x41\x70\x92\x7a\x50\x6d\xf0\x75\x13\xa0\x15\x03\xda\x1c\x20\x78\x07\x10\x74\xf6\x25\xcd\x61\x50\x0e\xe0\xbf\x0a\xf0\xff\x46\xcf\xf7\xd2\x1f\x8d\xba\xf1\x38\xcd\x40\xf0\xeb\x80\xf6\x63\xc0\x7f\x0c\x08\x9a\x8c\x7c\x2b\x0c\x19\x9c\x01\x2e\xb9\x00\x6d\x8d\x11\xb7\xb0\x2f\x85\xe5\x53\xae\x93\xd6\x09\x04\x4b\x80\xe0\xd2\xbe\x32\x12\xe5\xe5\xeb\x7e\x39\x2f\x87\x97\x17\x54\x81\xe0\xd7\x80\xe0\x58\x20\x98\x67\x94\xd7\x09\x68\x6d\x46\xfd\x2b\xf4\x32\x05\xcd\x31\xf2\xb0\x02\xda\x5d\x80\x76\xaf\xce\x7f\x20\x1a\xd0\xd6\xe9\x9f\x83\xcb\x8c\xf2\xed\x7a\x1e\xc1\x1c\x20\xd8\x66\xd4\xb3\xc0\x68\xdb\x39\x7a\x99\xda\x7c\x20\xf8\xac\x21\xbf\xbb\xf4\x7a\x06\xf9\x67\xb7\x41\x5d\x7a\xbe\xbc\x2e\x81\x74\x20\x58\x05\x04\x65\x5d\x0e\xa2\xee\x55\x3a\xf1\xb8\xe2\xef\x57\x40\x30\x23\x42\x46\x45\x06\x15\x1b\x54\xd4\x4b\x5c\x27\xb4\x2d\x40\x90\xd7\x75\xb3\xfe\x59\x3b\x66\xb4\xf3\x16\x20\x70\x18\x08\xc6\x1a\xbf\xb7\x73\x92\x54\x64\x1a\xb4\x42\x60\x0f\xc7\x37\xee\x2b\x55\xa2\x88\x75\xd1\x51\xd6\x85\x9d\xca\xb2\xe0\xaf\xb8\x2f\xac\x44\x07\x5f\x52\xb7\x04\x5f\x62\x49\xc1\x97\xd4\xad\xc1\x77\xd4\x94\xe0\x93\x6a\x77\xf0\x1d\xb9\x38\xb8\x3f\x34\xfe\x60\x6d\xf0\x2a\x33\x90\x2f\xf0\x6f\x03\x72\x39\x4e\xf3\x3e\xcc\xfd\x2c\x6e\x8b\x84\x7d\x37\xc6\x1e\xac\x03\x95\xa2\x7f\x5f\x84\x97\xfb\xb3\xdc\x4e\x73\x5c\xe5\xd8\xa8\x7e\x8c\x1a\x3e\xee\x30\x49\x98\xcf\xed\x33\xf7\x95\x85\xdf\x9b\xad\xe3\x20\xc7\x2a\x8e\x6b\x4a\x26\x56\xf3\xdf\xb8\xcf\xce\x56\x42\x12\x58\xce\xed\xb3\xdf\xf0\x6b\xcf\xa3\x86\xc7\x13\x7e\xdc\x19\x98\x45\xbc\xbd\x50\xf9\x73\x76\x01\x25\xca\x69\x24\xb1\xf3\x68\x11\xf1\xf3\x51\xc3\x2a\x90\xc9\xf3\x54\x9d\xa8\x61\xbb\x82\xef\xa9\xdb\xb0\x5a\xfd\x04\xf3\xe5\x62\xc4\xf0\xdf\x45\x9a\x4c\xfd\x37\xe6\xc3\x6c\xe5\x38\x32\x95\x18\x40\xcd\x0a\x3e\x29\xc2\xa5\xa8\x31\x69\xb0\x29\x99\xc1\x33\x61\x1b\x97\x84\x66\x51\xde\x7c\x78\x59\x06\x3c\x4c\x0a\x5e\x64\x8d\xa8\x61\x7b\x82\x67\x98\x39\xd8\x60\x5e\x8b\x2d\x1c\x87\x95\x6e\x03\xf7\x9b\xe1\x65\x6b\xe0\x61\x2e\x38\x59\x06\x72\x85\x3c\x67\x21\x55\xcd\x37\xf2\x2b\x46\x2a\x9b\x8f\x68\x5e\x06\xbb\x80\x5a\xde\x66\xc2\xc6\xf0\xf2\xb8\x2f\x9d\x84\x32\x31\x3e\xe0\x36\x25\x09\xcd\x42\xde\x9d\x42\x16\x08\xf9\x65\x3c\x0c\x8d\x4d\xd4\x26\x64\x8a\x76\x9b\x87\x66\x61\x6f\xc5\xf8\x04\xf9\xdc\x76\x99\x34\xc4\x9a\x99\x1e\x87\xb7\xaf\xba\x06\x5e\xa5\x02\x16\xd1\x66\xbc\xcd\xb9\xdf\x67\xb4\xbb\x9a\x82\x68\x9e\x9f\x69\xa5\xc0\xfb\x5a\x1e\x57\xc4\xe7\xe3\xd2\x8b\x88\x15\x7c\x18\xfa\x10\x6a\x73\x61\x53\x37\x20\x93\xe7\x19\x6a\x73\xb5\x08\x5e\xe5\x7d\xcc\x37\x7b\xe0\x35\x9f\x86\x57\x39\x0c\x98\xf8\x6f\xc9\xa2\xec\x52\xf3\x6a\x78\x95\xca\xe0\x45\x61\xdf\x7d\xa8\xe1\xf6\x41\xd8\x82\x59\x48\x11\xb6\xde\x0f\x08\x1d\xd9\x1b\xb6\x67\x5c\x4f\xa0\xee\x81\x87\xdb\x0f\x21\x43\x47\xd8\xde\xf2\x76\xc9\x11\x76\x69\x29\x6a\xf8\x58\x53\x69\x87\x47\x29\x42\xab\x69\x0f\x3c\xa6\x8f\xe1\x51\xb6\x00\xea\x41\x78\xd8\x69\x78\xb8\x6c\x4d\x0c\x1e\xb6\x1b\x08\x8d\xa9\xc4\x38\xe3\x7d\x78\xb8\xec\x75\x3b\x28\xc6\xba\xa7\x84\xff\x90\x0c\x98\x92\x85\x2d\x66\x82\x8f\xbd\xc6\xb8\xa9\x0e\x1e\xf3\x76\x34\x9b\x2c\x50\x95\x7a\x40\x29\x07\x4c\xeb\xe0\x55\x1b\xe0\x51\x8e\x02\x4a\x2a\x60\x8e\x86\xd7\xe4\x80\x47\x5d\x80\x4c\xe6\x87\xc5\xbc\x06\x5e\x53\x34\x3c\xca\x08\x64\xb2\x26\xa4\x8a\xbe\xc1\xf5\x33\xa4\x67\xbb\x00\xc6\xd3\x1a\x61\xf4\x2a\x34\x47\x65\xa2\x46\xdd\xaa\xfb\xc8\xa2\xbc\x54\x23\xe4\xe5\xce\x33\xf4\xe5\x04\x1a\xd9\x12\x6c\x67\x5d\xb8\xc0\xba\xe8\x20\xeb\xa2\x03\x80\xb6\xc4\x74\x1a\x99\xa6\x8d\xc8\x34\x55\xc1\xab\xce\x83\x87\x9d\x45\x0e\x3b\x0d\x16\xd2\x2d\xb6\x11\x5e\x96\x04\x0f\x6b\x41\x8e\x7c\x16\x4c\x39\x01\x2f\x3b\x0c\x8f\xb9\x00\x30\x2d\xd7\x75\x80\xb7\x83\x1a\xc3\xdb\x4b\xb4\x8f\x97\x1d\x80\x47\x49\x07\x63\x17\xc1\x94\x8f\x00\x65\x35\xa0\xee\x84\x57\x39\x0f\x8f\xba\x19\x5e\x35\x16\x9e\x28\xc0\x6b\x4a\x81\x47\x75\xa0\x59\x29\xea\x1d\x33\x0a\x6c\x68\x40\x8e\xf0\x9d\xd6\x1a\x3e\xd4\x5a\x40\x39\x2f\xe4\x15\x6d\x6a\x42\xa6\x5a\x85\x1c\x75\x01\xe6\x2b\xef\xa1\x95\xeb\x10\x6f\x47\xe5\x7d\x78\x95\x2a\x78\x4c\x6b\x00\xc5\x0b\x84\x42\xae\xe7\x5c\x57\xb9\xbe\xa8\x16\x78\x95\x32\x78\xd4\xed\x88\xe5\xfa\x26\xfc\xcb\x72\x78\xd4\x8f\xe0\x55\x78\xbb\x19\x79\x99\xcb\xe0\x35\x35\xc2\x23\xf0\x6c\x08\x1f\x9c\xb5\xe2\x51\xa1\x87\xcb\xd1\x2d\x7c\x37\x23\x0c\x95\x15\x92\x4b\xc8\x07\x17\x7d\x64\x2f\x3c\xe1\x70\x08\x1f\x95\xeb\xbe\xe8\xdb\x15\xba\xff\x34\x20\x34\x78\xe4\x7d\x91\xeb\x23\xef\x33\x42\x6f\x43\xed\x73\x1c\x50\x32\x11\x2d\xe6\x73\x3c\xbd\xe3\x31\x53\x23\x6a\x4c\xf5\xa8\x31\x55\x20\x49\xbd\x88\x7c\x65\x3d\x92\x94\x32\x54\x98\x67\x20\xd6\xd4\x0a\x98\xab\xe1\x35\x75\xc1\xa3\x36\xa0\x59\xa9\x40\x8d\x1a\x8b\x4c\xe5\x84\xf0\xc5\xab\x45\xfb\xae\x44\xac\x72\x00\x30\xa7\x21\xd6\xc4\x31\xf0\x1c\xbc\xea\x49\x78\x4c\x29\xc1\x8b\xa6\x42\x40\xf4\x77\x5e\x8e\x31\xb6\x14\x78\x71\x01\x1e\xf3\x19\xc4\x9a\x24\x20\x2a\x1f\x5e\xd3\x2c\x78\xd4\x0e\x78\x95\x7d\xf0\x08\x7d\x38\x0a\x0f\x6b\x83\x45\x4d\x41\xac\xc9\x89\x6a\x36\x1b\xa3\x58\x06\x5a\xd8\x09\x6c\x65\x27\x50\x22\xef\xc4\x56\x36\x03\x4e\x31\x97\x51\x16\xec\x61\x55\xd8\x2a\xef\x42\x96\x9a\x81\xad\x8a\x13\x5b\x15\x1b\x5a\x58\x26\x4a\x85\xfe\xe8\x94\x6e\x7a\x1f\xd5\xac\x07\x4b\xc2\xf3\x1b\xb9\xd8\xca\x16\x20\x85\x93\xec\x45\x96\xe2\xc0\x3a\x85\xa1\x42\xdd\x84\x19\x3c\x64\x05\xb0\xa8\xf5\xc8\x64\x12\x9c\xf2\x19\xcc\x90\x77\x62\x2e\x4b\x45\xaa\xbc\x17\x5b\x59\xbe\x18\x8f\x6e\xe5\x79\x28\x9b\x31\x9f\x9d\x40\x0a\xcb\xc6\x28\x65\x3b\x46\xb0\x54\x74\xb3\x54\x8c\x62\x6e\x74\xcb\x4b\xd0\x2d\x37\x63\x3e\xab\x41\x13\xdb\x86\x6e\x69\x25\xaa\xa4\x8c\xe0\x16\x66\x46\xb7\xbc\x18\xdd\xca\x2e\x74\xb3\x53\xe8\x56\x54\x74\xb3\xfd\x68\x62\xf5\x98\x2f\x9f\x42\x37\x4b\x14\x69\x33\x58\x17\xd6\x29\xc7\x90\x2e\xef\xc6\x6c\x79\x37\x56\xc9\x17\xd0\xa8\xac\x43\xbd\x7c\x1e\x1d\xfc\xb3\xec\x45\xa3\xbc\x1f\xf5\x72\x23\xaa\xe5\x05\x28\x95\x2f\xa0\x41\x62\x58\x2e\x1f\x41\x87\x72\x01\x1d\x6c\x04\x3a\xe4\x93\x68\x94\xf3\x51\x22\x42\x4e\xe7\xd1\x21\x79\x90\xcb\xa2\xb1\x5c\xf6\xa1\x4e\x39\x8f\x95\x72\x33\x46\x49\x67\x31\x82\xa5\xa0\x43\x5e\x8a\x24\xf9\x63\x34\xb0\xd3\x68\x94\x77\x03\x12\xe0\x96\x0e\xa3\x43\xc4\x6f\xc6\xa8\x70\x9c\x7d\x58\x19\x8a\x63\xda\xc3\xc7\x31\xc1\xa5\xc2\x1f\x4f\x0a\x6e\x37\x1d\x0f\xee\x52\x8a\x83\xbb\xf8\x6f\xf2\x86\xe0\x52\x39\x27\xd8\x26\xfb\x82\x9f\xcb\x2d\xc1\x6e\xf9\x13\x30\x81\x1f\xb9\x58\xc3\xdc\x88\x35\xef\xe4\x63\x2d\x31\x4e\x81\x12\x0b\x28\x33\x44\x1f\x41\x78\x5e\x30\x09\x99\xea\x36\xd4\x18\x73\x87\x4d\xa1\xb9\x43\xfe\x5c\xde\x80\x26\x31\x3e\x1c\x15\xdc\x2b\xc6\x14\x1e\x44\x8b\x31\x85\x3e\x1f\x19\x9e\x8b\x0c\x8f\x9d\xce\xa2\x5a\xf8\xd3\xfa\x7c\xd0\x5e\x31\xc6\xe4\xfe\xc2\x4e\xac\x92\xed\xa8\x95\x67\xa3\x56\xee\x42\xa5\x5c\x8a\x52\xa9\x09\xc5\xb4\x35\xb8\x49\x3e\x8a\x5a\xf9\x14\x56\xd1\x16\x40\x5a\x82\x55\x52\x39\x4a\x38\xd1\xc5\x60\x37\x5d\xc0\x2a\xba\x10\xbc\x20\x9d\x43\x87\xb2\x05\x1d\xca\x66\xac\x94\x4f\x05\x3f\x97\x4f\xa1\x83\x15\xa2\x43\xee\x16\xf3\xa9\xb5\xb2\x84\x5a\xba\x18\xfc\x5c\x6a\x47\xae\x7c\x0a\x69\x72\x17\x32\xe5\xe3\x58\x29\x5f\xc0\x4a\xd9\x1c\xbc\x20\x5b\x50\x29\xc8\x85\x4a\xb9\x1c\xd9\xf2\x06\xd4\x02\x1a\x27\xbb\xe1\x7f\x2e\x01\xb4\xc3\x80\xb6\x27\x22\xcc\xd7\x49\x8c\x1f\x84\xcf\x18\xc6\xa4\x3a\xc3\xfe\xf7\x0f\x07\xce\xbf\x5d\x36\x1c\x64\x1e\xee\x27\x83\xce\xcf\xcd\x85\x57\xcc\xf7\x0e\x9c\x87\xeb\x1f\xae\x52\x8a\xd1\x14\xfa\x2e\xa7\x04\xff\x25\x35\x05\xbf\x67\xcc\xcf\x7d\x16\x9a\xaf\xe8\x1f\x1a\x73\x6e\x1d\x6c\x19\xcc\x52\x53\xf0\x13\xfd\x7b\x38\xfc\x0e\xf7\x2d\xb8\x5e\xf4\x0f\x87\x9c\x93\xbb\xc2\x7c\x5c\x18\x73\x43\x7e\x54\x28\xec\x3b\x3f\xd7\xd1\x37\x0c\x7e\x76\xc5\x79\xba\x2b\xcc\xd7\x7d\xd9\x79\x3b\x31\xd7\xb0\xca\x98\x73\x58\xa5\xcf\xd7\x73\x8c\xbd\x52\x18\xb6\x01\x46\x18\x9e\x8f\x18\x62\xae\x4f\xb4\x15\xe7\x2b\x34\x76\x3f\x02\xa7\x1c\x0b\x8f\x9a\x8c\x2d\x43\xce\x01\x8b\x30\xf8\xfe\xe5\x9f\x5f\x39\xbc\xf2\xdc\x70\xf0\x20\xdb\x19\x3c\x31\xc8\xf3\x1f\xeb\x73\x50\x62\x8e\x77\x89\x11\x76\x5c\xbe\xcd\x83\x27\x86\x7c\x6e\xcc\x35\x5e\x31\xec\x3f\xa7\x6a\xcc\x33\x5e\x29\xec\x33\xe7\x3a\x48\x28\xc6\x39\x97\x23\xe3\xdd\x83\xea\x05\xf5\xa1\xd6\xe0\x49\x4e\x21\x0c\xec\x4f\x4a\x05\x88\x93\xda\x6d\x50\xab\x48\x73\x26\x34\x87\x34\x14\xa9\xe7\x41\x9c\xcc\xa5\x06\xa5\x72\x0a\x9e\x31\x27\x06\x0f\x71\x92\xf5\x31\x5a\x97\x5c\x1c\x0c\xc8\xc5\xc1\x73\x72\x31\x26\xc9\xc5\x90\xe5\xe2\xe0\x6f\xe5\xe2\xe0\x21\x56\x06\x62\x85\x20\xa5\xd5\xa0\xd5\x20\xa5\x1b\xa4\xcc\x0b\x1e\xe2\x34\xe8\x3b\x09\xde\x0e\x67\x41\x26\x80\xcc\x73\x0d\x32\x83\xcc\x29\x20\x31\x16\xbc\x0c\xa9\xe5\x20\xd3\x2a\x90\x69\x03\xa7\xe0\x49\x3e\x86\xbb\x2c\xf9\x40\xa6\x11\x20\x73\x93\x41\x16\x90\x39\x13\x64\xda\x15\x3c\xc4\x29\x24\xf7\xb0\x1c\x0d\xb9\xc8\xc5\x28\x90\x23\xde\xa9\x84\xcb\x37\xf2\xbd\x52\x3b\x9a\xf7\x01\x9c\xa2\x7c\xa0\x3e\xb4\x2b\x78\x92\xd3\x95\xda\x25\xda\x06\xe2\x34\x6c\xb9\x41\x75\x9c\x82\x67\x86\x55\x07\x0f\x71\xba\x52\xbd\xa3\x0b\x40\xd1\xb3\x40\xc3\xb6\x19\xe4\x04\x0d\x9b\x07\x8a\xd6\x82\x87\x38\x7d\x11\x1d\x54\x96\x05\xff\xa6\x2c\x0b\xfe\x9d\xd7\x43\x2a\x44\x07\xeb\xa2\x2d\x22\x3c\x8e\xf7\x58\x37\x4e\x0d\xca\x7b\x65\xf0\x90\x52\x12\x3c\xa4\x5e\x0c\x1e\x52\x4f\x07\x0f\x45\x71\x3f\xb1\x8b\x62\x05\xed\xc6\x79\xb9\x38\xf8\x8a\x5c\x1c\x3c\x2d\x17\x07\xd7\x1b\xf4\x63\xb9\x38\xf8\x5f\x72\x0a\x4c\xdc\x7e\xb0\xcc\xe0\x21\x56\x10\x3c\x14\x99\xa6\xbf\x0e\xf0\xb1\x3e\xa7\xf0\x77\x4d\xef\x5f\x6a\x41\xf0\x10\x27\xe5\x18\x88\x75\x61\xa7\x4e\xb4\x64\x30\xf9\x98\x46\x05\x0f\xa9\xdb\x82\xef\x9a\x52\x83\x87\xd4\x3d\xc1\x43\x51\x2b\xe1\xe0\x63\x26\xa9\x10\x5d\x0c\x10\x2f\x92\x43\xa1\xd4\x23\xfc\x27\x10\xc7\xd9\x16\x40\x2a\x05\x68\x1d\x80\x83\xa1\x77\xc9\xc1\x23\x40\xd0\x0a\x04\x8f\x02\x5a\xb9\x78\x2f\xdc\x89\x42\xf1\x2e\x13\xa8\x34\x1b\xc4\x1a\xb1\x5b\x2e\x0b\xfa\x43\x73\x90\x52\x29\x8a\x42\xf3\x92\x9c\x58\x32\x8a\x44\x68\x45\x2b\xb3\xa2\x49\x96\x50\xaf\x1e\xc5\x12\x23\xdf\x0a\x20\x38\x2a\x44\xbc\xfc\xe8\x22\x14\x49\x56\x2c\x13\xef\xac\xe7\x63\x99\x74\x1e\x95\x9c\xd8\x6a\x2c\x61\x08\xfa\x28\x5a\x6b\x16\xef\x9b\xd3\x04\x8f\xa1\xb4\xb1\x11\x34\x4a\x36\x23\x53\x36\x23\x46\x36\xa3\x4a\x36\xc3\x26\x9b\x51\x20\x9b\x91\x2d\x9b\x91\x25\xd7\xa3\x41\xf8\xac\x5e\xc3\xe7\xf4\x20\x83\xfb\xa9\xac\x13\x59\xc6\xfb\xee\x32\xe3\x3d\x77\x25\xb7\xd3\xac\x13\x16\x53\x1a\xbc\xa6\x2a\xac\x53\x4e\xc1\x22\xde\x09\x76\xa2\x98\x75\x22\x96\x75\x22\xd3\x6c\x41\x26\xfb\x18\xe0\xf1\x94\x13\xfa\x7b\x22\xf1\x39\x49\xbc\x27\x5d\xc6\x3a\x11\x0d\x68\x71\x6a\x0d\xd7\x03\x64\x9a\xf3\xe1\x56\x37\x61\xae\x9a\x83\x34\xb5\x0c\x0e\x76\x01\x0d\x6a\x11\xa2\xe5\xd3\x28\x34\xc5\xe0\x2b\xa6\x18\x8c\x35\xc2\x02\x53\x0c\x66\x9b\x62\x70\x13\xf7\x09\xcd\xa0\x0d\x0c\x14\xdb\x3f\x14\xb4\x11\x05\xca\x0c\xe4\x2b\x67\xb1\x51\x89\x41\x26\xeb\x44\x75\x48\x4e\x6c\x2e\xd2\x95\x4d\x68\x32\x1d\xa1\xb5\xca\x1e\x4a\x94\xcb\x05\x7f\xfa\x9c\x70\x8f\x78\x97\xef\x14\x9f\x8f\xa0\x8b\x75\xf0\x50\x4a\x63\x47\x88\x29\x3d\xc1\x8b\x0a\xe8\xa8\xd2\x23\xad\x12\x9f\x07\x84\xfd\x89\x8e\xe9\xcf\x78\xc8\x29\xf2\xd9\x97\xfd\xfd\x8b\x10\xd0\x97\xa4\x23\x4a\x0f\x1a\xc4\xe7\x23\xc2\x3e\xb7\xb2\x23\x50\xa5\x23\x98\xcf\x89\xeb\xbc\xe9\x0c\x75\x99\xce\x50\x47\x28\x64\x3d\xa2\xde\x9b\xd8\x1e\xd4\xb3\x23\xd8\xc6\x8e\x20\x93\x93\x74\x04\x8b\xcd\x59\xb4\xd5\x3c\x8f\x0e\x9b\x9c\x54\xa2\x82\x8e\xa9\xa0\x4a\x56\x84\x02\xa5\x08\x05\x6c\x0f\x1a\x98\x05\xc5\x0c\x78\x5b\xe5\xf2\x6f\x44\x03\x5b\x06\xf0\xb1\x02\x5b\x16\x7c\x5b\x51\x61\x11\xef\xf9\xb8\x2f\xc2\x7d\x13\x3e\x6e\x9c\x0d\x8f\xb2\x0a\x5e\x45\x82\x27\xe4\xbb\xa8\x36\x34\xb3\x1d\xe2\xbd\x22\x4c\x92\xf0\x5f\x2c\xac\x07\x5e\x79\x3f\x3c\xaa\x13\x35\xd2\x76\xf0\xfe\xe7\xd2\x49\xcc\x8d\x9e\x93\x4f\x62\x35\x27\x29\x13\xed\x21\xe2\xbf\xeb\x84\x2e\xa9\x14\xf5\xf2\x41\xf1\xce\xaf\x85\x3f\x63\x75\x80\xb2\x1c\x99\x9c\xcc\x1e\x9d\x00\xff\x71\x20\x78\x11\xf0\x1f\x0d\xf5\x76\x33\x50\xc5\x89\x75\xa1\x91\x81\x6a\x0d\xaa\xe0\xf6\x4b\x02\x5a\xf4\x39\x6c\x7f\x36\x70\x29\x46\x0f\xfd\xb9\xfd\x89\x36\x22\x5a\x72\x22\x16\xd0\xb6\x03\x5a\x1b\xef\xaf\xcc\x09\x4f\x3f\xaa\x60\x4e\x54\x1a\x21\xa7\x12\x39\x16\x25\xcc\x09\xbb\x41\xb3\x98\x13\xd9\xcc\x89\x52\x39\x56\x84\xe9\x11\x94\xc1\x9c\xc8\x91\x63\xc5\xe7\x14\xe6\x44\x62\x44\x3a\xfe\x7b\xa6\x91\xbe\x3c\x82\x6a\xe5\x58\x11\xf6\xe7\x23\x14\xaf\x24\x14\xd7\x88\x97\xc3\x9c\xc8\x67\x4e\x14\x85\x48\x8e\x15\xa1\xbd\x3f\xc9\xb1\x22\x2c\xef\x4f\x72\x2c\x1a\xfb\xe7\x1d\x91\x7f\x7f\x3e\x9c\x06\x55\x87\x3e\xcb\x7c\x7c\xe3\x84\xa3\x3f\xc9\xb1\x22\x2c\x35\xf2\x0d\x93\x21\xbf\x76\x83\xf2\x43\x24\xc7\x8a\xb0\xa3\x3f\x0d\xc1\x47\xff\x7a\xcc\x92\x63\x85\x8c\x72\x22\xea\xcc\xe5\x9d\x62\xc8\x39\xc7\x68\x8f\x70\xfb\x18\xed\x52\x6a\xb4\xdf\xac\x08\x39\x65\x1b\xbc\x56\x44\xb6\xbf\xc1\x77\x1f\x3e\xae\xe4\x83\x18\x76\x36\x92\xfe\x10\x49\x57\xf2\xb5\xe4\xe2\xe0\xa7\x06\x71\x5f\xef\xb7\x03\x7c\xb1\x44\x63\xfd\x11\xf7\x91\xf3\xb1\x4e\xb6\xa1\x24\x92\x0c\xdd\x5e\x65\xf4\xc7\xae\x08\xda\x62\xd0\xca\x88\x67\xe2\x37\xb9\x12\x85\x06\x39\x0d\x2a\x0b\x11\xeb\x42\x3e\xb6\x84\x17\x70\x5d\xd3\x8f\xb6\x03\x34\x09\x90\xb9\xe5\x9e\x00\x28\xd5\x80\xfa\x98\xf0\xa4\x61\x8a\x01\x4c\x75\x80\x69\x3b\x60\xbe\x1e\x30\x3f\x01\x98\xdf\x04\xa2\x2c\x40\x54\x29\x10\xf5\x29\x10\x3d\x1d\x88\xbe\x00\x0c\xfb\x0d\x10\xf3\x38\x30\x7c\x2a\x30\x62\x34\x30\x62\x2e\x30\xf2\x21\x20\xb6\x0a\x88\xfd\x00\x88\xab\x02\xe2\xbe\x09\xc4\xbd\x09\xc4\x7d\x0a\x8c\x7a\x17\xb0\x8c\x03\x2c\x9b\x81\x84\xc7\x80\xab\x62\x81\xab\x9e\x02\x12\x19\x90\xb8\x10\x18\x5d\x0a\x8c\xf6\x02\x49\xe3\x80\xa4\x27\x80\xa4\x73\xc0\xd5\x37\x00\xc9\x16\x20\x79\x2b\x30\x66\x16\x30\xe6\x43\x20\xc5\x03\x8c\x2d\x07\x52\xa7\x02\xa9\x6b\x81\x71\x16\x60\xdc\x53\xc0\x78\x0b\x30\xfe\x9b\xc0\xf8\xdf\x03\x69\xd7\x03\x69\xcf\x02\x69\xbf\x02\x26\x4c\x02\x26\x34\x02\x13\x3c\xc0\x84\x73\x40\xfa\xbb\xc0\xc4\xf5\x40\xc6\x35\x40\xc6\x1f\x81\x6b\x36\x03\x99\xb3\x80\x6b\xaf\x07\xae\xf5\x02\x59\xe3\x80\xac\xad\xc0\xa4\x6b\x80\x49\x75\x40\xf6\x0d\x40\xf6\xbb\xc0\x75\x0f\x01\x39\xd7\x03\x39\x7e\x60\xf2\x42\x20\xb7\x1c\x98\xc2\x80\x29\x6b\x81\x29\xe7\x80\xa9\x16\x60\xea\x63\xc0\xd4\x0b\x80\x7d\x16\x90\x37\x06\xc8\xab\x02\x1c\xe3\x00\xc7\x7a\x9d\xae\x1f\x0d\x5c\x7f\x0e\xc8\xdf\x05\x7c\x65\x3b\x50\xf0\x08\x50\xf0\x26\x70\xc3\x39\xa0\xf0\x21\x60\xda\x56\xa0\x68\x13\x50\x74\x0e\x98\x3e\x03\x98\xfe\x38\x70\xe3\x19\xa0\x78\x0c\x50\xec\x05\x6e\xaa\x06\x6e\xba\x00\xcc\xf8\x00\xb8\x79\x02\x70\xf3\x6f\x80\x92\x6a\xa0\x64\x33\x70\xcb\x54\xe0\x96\x27\x81\xd2\x31\x40\x69\x23\x30\xf3\x11\xa0\xec\x09\xa0\x7c\x0c\x70\x9b\x19\xb8\x6d\x2b\x50\x31\x17\xf8\xea\x64\x60\xd6\x76\xe0\xf6\xed\x40\xe5\x56\xe0\x8e\x6a\xa0\x8a\xd3\x05\xe0\x6b\xcf\x02\xce\xe9\xc0\x9d\x93\x80\x3b\x77\x01\xd5\xe5\x40\xf5\xa7\xc0\x5d\xbb\x80\xd9\xdf\x04\x6a\xcc\x40\xcd\x5b\xc0\xdd\x4f\x01\xb5\x0f\x01\x75\x0c\xb8\xd7\x0c\xdc\x5b\x0e\xd4\x5f\x0f\xd4\xff\x1e\x98\xf3\x04\x30\x77\x3a\x70\xdf\x35\xc0\x7d\x9b\x80\x86\x1b\x80\xfb\xcb\x81\xc6\x72\xe0\x81\x72\x60\x5e\x0d\xf0\xd0\x64\x60\xfe\x63\xc0\xc3\x1f\x02\x0b\xa7\x02\x4d\xd7\x03\x8b\xae\x01\x16\x5b\x80\x47\x46\x03\x4b\x6e\x00\x96\xac\x07\x96\xf8\x81\x47\x1b\x81\xe6\x31\xc0\x63\x0c\x68\x79\x0a\xf8\x46\x15\xd0\x3a\x06\x68\xf5\x03\x6d\x6b\x81\x6f\x75\x03\xae\x49\xc0\xe3\xa3\x81\xc7\x3f\x00\xda\x9f\x02\xbe\x5d\x03\x2c\xad\x03\x96\x7e\x0e\x3c\xf1\x2e\xb0\xec\x4d\xe0\x3b\x73\x01\x77\x23\xf0\x64\x1d\xb0\xbc\x1b\x58\xd1\x0d\xac\x3c\x03\x3c\xe5\x01\x56\x95\x02\xdf\xb5\x00\xdf\xfd\x00\x58\xfd\x2c\xf0\x74\x35\xd0\x31\x01\xe8\xf8\x33\xf0\xcc\x26\xa0\xf3\x59\xe0\xd9\x2a\xe0\xb9\x6a\xe0\xb9\x73\xc0\x9a\x0f\x80\xe7\xbd\xc0\xda\xdf\x03\x2f\x3c\x09\xac\x7b\x1c\x78\xb1\x1a\x58\xff\x2c\xf0\xd2\x0c\xa0\xab\x14\xf8\x5e\x35\xe0\x79\x0c\xf8\x7e\x37\xb0\xe1\x43\xe0\x07\x1f\x00\xdd\xbf\x07\x5e\xfe\x00\xd8\xf8\x21\xf0\xc3\xa7\x81\x4d\xd5\xc0\x8f\xc6\x00\x3f\xfa\x23\xf0\xe3\xeb\x81\xcd\x75\xc0\xe6\x0f\x81\x9f\x5c\x03\x6c\x61\xc0\x96\xad\xc0\x2b\x4f\x02\x5b\x67\x01\x5b\x3f\x05\x7e\x3a\x01\xf8\xe9\x1f\x81\x6d\xbf\x02\x5e\xad\x01\x5e\x3d\x07\x6c\x7f\x0c\xf8\x59\x2c\xf0\xb3\xa7\x80\x1d\x00\x76\xd4\x01\x3b\x3e\x00\x7e\x3e\x15\xf8\xf9\x56\xc0\x1b\x03\x78\x9f\x04\xbc\x9f\x02\xaf\xd5\x01\xaf\x6d\x07\x76\x3e\x06\xbc\x3e\x19\x78\xfd\x53\x60\xd7\x5a\xe0\x17\x0b\x81\xdd\xd3\x81\x37\x62\x81\x37\x7e\x03\xbc\xf9\x24\xb0\x67\x3a\xf0\x4b\x33\xb0\x77\x34\xf0\xd6\x38\xe0\x6d\x33\xf0\xb6\x1f\x78\xe7\x02\xf0\xab\xa9\xc0\xfe\x18\x60\xbf\x07\xf8\xf5\x43\xc0\x01\x06\x1c\x38\x07\xbc\xfb\x2c\x70\xb0\x1b\x38\xd4\x0d\xbc\xf7\x16\xf0\x9b\x0f\x80\xff\x9a\x00\xbc\xff\x10\xf0\xc1\x53\xc0\x91\xf5\xc0\x6f\x1f\x01\x8e\x3e\x09\x7c\x38\x0e\xf8\xf0\x02\x70\xec\x29\xe0\x77\xdf\x04\x8e\x5f\x00\x3e\x7a\x1c\xf8\xc3\x04\xe0\x0f\x1f\x02\x27\xde\x02\xfe\xb8\x0b\xf8\xd8\x0b\xfc\xe9\x43\xe0\xe4\x26\xe0\xcf\x4f\x02\xa7\x1e\x03\xfe\xf2\x04\xf0\xe9\xf5\xc0\xe9\xa7\x80\xbf\x8e\x06\xfe\xfa\x26\xf0\x99\x07\x38\x33\x1a\x38\xf3\x34\xf0\xb7\x31\xc0\xdf\x36\x01\x67\x27\x03\x67\xbd\xc0\xdf\x2d\xc0\xb9\x58\xe0\x1f\xa3\x81\x7f\x6c\x05\xce\x7f\x13\xf8\xa7\x05\xf8\xe7\x6f\x80\x0b\x0b\x81\x7f\x4d\x05\x2e\xc6\x02\x17\x7f\x03\xfc\xaf\xa7\x80\xcf\x27\x01\xff\x36\x03\xff\xbe\x00\xf8\x1e\x02\x2e\x5d\x03\xf8\x2d\x80\xbf\x1b\x08\xcc\x05\xb4\x3a\x20\x38\x19\x04\x06\xc2\x5c\x10\x2e\x80\xe8\x09\x90\x34\x01\x24\xad\x05\xc9\xbf\x07\xb1\xad\x20\xe5\x11\x90\xca\x40\xea\x9b\x20\xd3\xd3\x20\x73\x0d\x28\xaa\x14\x14\x3d\x15\x14\xed\x07\x0d\xfb\x1c\x14\xb3\x15\x34\xfc\x69\xd0\x88\x3a\xd0\x88\x0f\x41\x23\xd7\x83\x62\x1f\x07\xc5\xc5\x82\xe2\x7e\x0f\x1a\xd5\x08\x8a\x1f\x0d\x8a\xff\x0d\xc8\xf2\x26\x28\xa1\x1a\x94\xf0\x67\xd0\x55\x4f\x83\x12\x2d\xa0\xc4\xa7\x41\xa3\x27\x83\x46\xff\x1e\x94\xf4\x04\xe8\xea\x46\x50\xf2\x0d\xa0\x31\x0c\x34\xe6\x2d\x50\xca\x56\xd0\xd8\x1a\xd0\xd8\xf5\xa0\xb1\x17\x40\xa9\xcf\x82\xc6\x8d\x03\x59\xcd\x20\xeb\x05\x50\xda\x74\x50\xda\x1f\x41\x13\x36\x83\xd2\xe7\x82\x26\x96\x82\x32\xe6\x82\xae\x79\xe8\xff\xe2\xe4\x7d\xe0\xf2\x1c\xdf\xff\xff\xd7\x79\x1e\xc7\x79\x5d\xd7\xbd\x35\x1b\x42\x68\x64\x42\x9b\xb6\x75\xdf\xd7\x75\xf7\x87\xb0\xfe\xdc\xd3\x68\x5b\xb6\x46\x08\xb5\x95\x95\xb5\xca\xd6\x08\x21\x0c\x21\x0c\x61\x08\x21\x84\x10\xc2\x10\x42\x08\x21\x84\x21\x84\x30\x84\x10\x32\xc3\xef\xb1\x3a\x76\xdb\xfb\xf3\x79\x3f\x3e\x8f\xdf\xe3\xfb\x7e\x3f\xea\x38\xaf\xfb\xbe\xaf\xf3\x79\x9e\xe7\x75\xdd\xd7\xf3\x38\xce\xc7\x02\x35\x3d\x19\x6a\x46\x36\xd4\x8c\x4d\x50\x07\xe6\x42\xc5\x7b\x50\x33\xa3\xa0\x66\x6e\x84\x9a\xd5\x02\x35\xbb\x05\x2a\xa1\x0b\xca\xdf\x0b\x15\x18\x85\xf2\xa2\xa1\x82\x79\x50\x89\x65\x50\x49\x0d\x50\xc9\x05\x50\x29\x35\x50\x07\xf5\x43\x1d\xdc\x05\x75\x08\x43\x1d\xd2\x09\x75\x58\x02\xd4\x9c\x04\xa8\xb4\x7c\xa8\xf4\x4a\xa8\x8c\x06\xa8\xcc\x64\xa8\xcc\x41\xa8\xd0\x10\xd4\xdc\x11\xa8\xac\x28\xa8\x79\x99\x50\x47\x44\x42\x1d\x31\x04\x75\x64\x2d\x54\x76\x32\x54\xf6\x10\xd4\x02\x40\x2d\xd8\x02\x95\x13\x01\x95\xd3\x01\x75\x54\x09\xd4\xa2\x58\xa8\x45\x1b\xa1\x16\x0f\x43\x2d\xa9\x81\x3a\x3a\x1b\xea\x98\x1e\xa8\xbc\x7e\xa8\x63\x37\x41\x1d\xd7\x09\x75\xfc\x26\xa8\xfc\x41\xa8\x13\xe3\xa0\x4e\x1c\x82\x2a\x60\xa8\x82\x21\xa8\xa5\x91\x50\x4b\x7b\xa1\x96\xe5\x42\x15\x25\x40\x15\xf5\x43\x15\x77\x41\x9d\xdc\x01\xb5\xbc\x07\xaa\xa4\x0f\xaa\xb4\x17\xea\x94\x3a\xa8\x15\xeb\xa1\xca\x6a\xa1\x56\xe6\x40\x95\x7b\x50\x15\xb1\x50\x95\xd1\x50\xa7\xc6\x41\xad\xda\xfa\xd3\x0e\xb5\xba\x1e\xaa\xaa\x0c\x6a\xcd\x1c\xa8\x35\x5b\xa0\x4e\xeb\x82\x3a\x3d\x17\xaa\x3a\x15\xea\x8c\x64\xa8\x33\xe3\xa1\xce\x1c\x80\x3a\xab\x0e\xaa\x26\x1b\xea\xec\x12\xa8\x73\x72\xa1\xce\xad\x87\xaa\x6d\x87\x3a\xaf\x1f\xea\x82\x18\xa8\xb5\x45\x50\x17\x26\x40\x5d\xb8\x05\xea\xa2\x11\xa8\x8b\x47\xa0\xea\x4a\xa0\xea\x46\xa1\x2e\xe9\x84\xba\x74\x08\xaa\xde\x81\xaa\x2f\x81\xba\x7c\x3d\xd4\x15\xdd\x50\x57\x36\x40\xad\xab\x84\xba\x2a\x15\xea\xaa\x2e\xa8\xab\xf3\xa1\xae\x29\x81\xba\x66\x04\xaa\xa1\x0e\xea\xda\x48\xa8\xeb\xe2\xa0\xae\x1b\x85\xba\xbe\x12\x6a\x7d\x3b\xd4\x0d\xbd\x50\x37\x96\x41\xdd\x94\x00\xd5\x18\x03\x75\xb3\x03\x75\x73\x0f\xd4\x2d\x35\x50\xb7\xc6\x43\xdd\xda\x0f\xd5\xd4\x01\x75\x5b\x25\xd4\xed\x1e\xd4\x1d\x31\x50\x77\xb4\x41\x35\xb7\x43\xdd\xd9\x08\x75\x57\x3d\xd4\xdd\xb9\x50\x2d\x31\x50\xf7\x24\x40\xdd\x1b\x03\x75\x9f\x03\xd5\x1a\x01\xd5\x3a\x0a\x75\x7f\x03\xd4\x03\x4d\x50\x0f\xd6\x41\xb5\x15\x40\x3d\xe4\x41\x3d\x3c\x07\xea\xe1\x7e\xa8\x47\xea\xa0\xda\x0b\xa0\x1e\x65\xa8\x47\x4b\xa0\x1e\xed\x85\x7a\xac\x1a\xea\xf1\x64\xa8\xc7\xd7\x43\x6d\xa8\x85\x7a\x22\x1f\xea\xc9\x54\xa8\xa7\x32\xa1\x3a\x18\xaa\xa3\x1b\xea\xe9\x3c\xa8\xa7\x87\xa1\x9e\x19\x86\x7a\x76\x00\xaa\xb3\x07\xea\xb9\x39\x50\xcf\xb5\x43\x3d\x9f\x0b\xf5\x7c\x37\xd4\x0b\x45\x50\x2f\x74\x42\x75\x45\x43\x75\x75\x41\xbd\x58\x06\xf5\x52\x0d\xd4\xcb\x80\x7a\xb9\x0b\xaa\x3b\x1b\xea\x95\x78\xa8\x57\x06\xa0\x5e\x6d\x80\x7a\xad\x06\xaa\xa7\x0c\xea\xf5\x28\xa8\xd7\x2b\xa1\xde\x68\x83\x7a\x33\x1e\xea\xcd\x7a\xa8\x5e\x0f\xaa\x77\x08\xea\xad\x06\xa8\xb7\xdb\xa1\xde\x49\x85\x7a\xa7\x1b\xaa\x2f\x17\xaa\x6f\x00\xea\xdd\x0e\xa8\xf7\xea\xa0\xde\xaf\x81\xda\x58\x0b\xb5\x71\x18\xea\x83\x8d\x50\x1f\xe6\x42\x7d\xd8\x04\xf5\x51\x1d\x54\x7f\x36\xd4\xc7\x91\x50\x9f\x24\x40\x7d\xda\x0c\xf5\x59\x1c\xd4\xe7\xf9\x50\x5f\x54\x43\x7d\xc9\x50\x5f\x25\x40\x7d\x1d\x0d\xf5\x75\x13\xd4\x37\xd5\x50\xdf\x4e\x81\xfa\xb6\x0f\xea\xbb\x76\xa8\xa1\x2c\xa8\xef\x1d\xa8\xef\x1b\xa0\xbe\xdf\x02\xf5\x43\x11\xd4\x8f\x0c\xf5\x63\x1b\xd4\xf0\x16\xa8\x9f\x0a\xa0\x7e\x6a\x83\xfa\xd9\x83\xfa\x79\x2d\xd4\xcf\x7d\x50\xbf\xc4\x42\xfd\xb2\x0e\xea\x97\x2d\x50\x23\x75\x50\xbf\x02\xea\xd7\x38\xa8\x5f\x73\xa0\x7e\xad\x81\xfa\xb5\x19\xea\xd7\x51\xa8\xdf\x72\xa0\x7e\x6b\x80\xfa\xad\x17\xea\xf7\x68\xa8\xdf\x4b\xa0\x7e\x6f\x85\xfa\x7d\x10\x6a\x34\x01\x6a\xb4\x06\x6a\xb4\x03\x6a\x74\x08\xea\x8f\x3c\xa8\x3f\xba\xa0\x36\xc7\x41\x6d\xae\x83\xfa\x93\xa1\xfe\xcc\x84\xfa\xb3\x0b\x6a\x4b\x04\xd4\x96\x66\xa8\xbf\xa2\xa1\xfe\x8e\x82\xfa\xbb\x1a\xea\xef\x3e\xa8\x7f\x32\xa1\xc1\xd0\x48\x86\x56\x53\xa0\x55\x0e\xb4\xea\x81\xd6\xd1\xd0\xba\x16\x5a\x0f\x42\x53\x16\x34\x35\x41\xd3\x28\x34\xe7\x43\x73\x3b\x34\x8f\x42\x9b\x1a\x68\xd3\x09\x6d\x39\xd0\x56\x1e\xb4\xd5\x02\x6d\xcf\x81\xb6\xeb\xa1\xed\x4d\xd0\x4e\x36\xb4\x2f\x13\xda\xd7\x01\x3d\x21\x02\x7a\x42\x3e\xf4\x84\x56\xe8\x09\x5b\xa0\x27\x16\x40\x4f\x6c\x83\x8e\x00\x74\x44\x36\x74\xc4\x7a\xe8\x88\x21\xe8\x49\x83\xd0\x3b\x44\x43\xef\x90\x0d\xbd\x43\x37\xf4\xe4\x08\xe8\xc9\x6b\xa1\xa7\xc4\x40\x4f\x69\x87\xde\x71\x0a\xf4\x8e\x25\xd0\x3b\xb6\x42\xef\x14\x01\xbd\x53\x15\xf4\xce\x71\xd0\x3b\xb7\x40\xef\x3c\x02\x1d\x39\x07\x3a\xb2\x1e\x3a\x72\x23\xf4\x2e\xb1\xd0\xbb\x54\x42\xef\xd2\x0b\xbd\x6b\x02\xf4\xae\x6b\xa1\x77\xed\x86\xde\xcd\x83\xde\x6d\x3d\xf4\x6e\xa3\xd0\x51\x55\xd0\x51\xad\xd0\xbb\x3b\xd0\xbb\x17\x40\xef\xde\x0c\xbd\x47\x34\xf4\x1e\xad\xd0\x7b\x8c\x40\xef\x59\x0d\xbd\xe7\x10\x74\x74\x02\x74\x74\x03\xf4\xd4\x4c\xe8\xa9\x8d\xd0\x53\x87\xa1\xf7\x2a\x83\xde\x6b\x08\x7a\xef\x41\xe8\x98\x68\xe8\x98\x1c\xe8\x98\x06\xe8\x7d\xea\xa1\xf7\xe9\x80\xde\x67\x08\x7a\x5a\x0c\xf4\xb4\x6c\xe8\x69\x1b\xa0\xf7\x8d\x86\xde\xb7\x1a\x3a\x36\x0e\x3a\x76\x3d\xf4\x7e\x09\xd0\xfb\x55\x41\xef\xd7\x09\xbd\x7f\x04\xf4\x01\x0c\x7d\x40\x36\xf4\x01\x5b\xa0\xe3\xf2\xa1\xe3\x3a\xa1\xa7\x33\xf4\xf4\x22\xe8\xe9\xed\xd0\x33\x2a\xa1\x0f\xac\x86\x8e\xcf\x87\x8e\x6f\x86\x8e\xdf\x04\xed\xcf\x81\xf6\xb7\x40\x07\x22\xa1\x03\x3d\xd0\x6e\x2a\xb4\xdb\x00\xed\x0e\x41\x7b\x55\xd0\xde\x00\x74\x30\x16\x3a\x58\x07\x9d\x58\x07\x9d\x04\xe8\xa4\x4c\xe8\xa4\x7a\xe8\xa4\x4e\xe8\xa4\x11\xe8\xe4\x7c\xe8\xe4\x66\xe8\xe4\x41\xe8\x94\x8d\xd0\x07\x35\x42\x1f\x34\x02\x7d\xf0\x5a\xe8\xd4\x58\xe8\xd4\x16\xe8\x43\x6a\xa0\x0f\x8d\x81\x3e\x74\x18\xfa\xb0\x02\xe8\x39\x80\x9e\xe3\x41\xcf\x29\x83\x9e\xd3\x09\x9d\x36\x05\x3a\xad\x0a\x3a\x9d\xa1\xd3\xfb\xa0\x33\x5a\xa1\x33\xe3\xa1\x33\x6b\xa0\x43\xf1\xd0\xa1\x4d\xd0\x73\x53\xa1\xe7\x0e\x40\x1f\x5e\x03\x9d\x15\x0d\x9d\x35\x0c\x3d\xaf\x06\xfa\x88\xf5\xd0\x47\xb6\x42\x67\x27\x43\xcf\x67\xe8\xf9\x39\xd0\xf3\x87\xa1\x17\x94\x40\x2f\xe8\x82\x5e\xe8\x41\x2f\x1c\x81\xce\xc9\x87\xce\xe9\x86\x3e\x6a\x0e\xf4\xa2\x28\xe8\x45\xed\xd0\x8b\x23\xa1\x17\xb7\x43\xe7\x3a\xd0\xb9\xeb\xa0\x97\x38\xd0\x4b\xca\xa0\x97\xf4\x40\x1f\xdd\x01\x7d\x4c\x2c\xf4\x31\x7d\xd0\x79\x9d\xd0\xc7\x36\x40\x1f\x57\x05\x7d\x7c\x2d\x74\x7e\x3d\xf4\x09\x99\xd0\x27\xf4\x42\x9f\x14\x05\x5d\xc0\xd0\x05\x5b\xa0\x0b\xeb\xa0\x97\xd6\x42\x2f\xab\x84\x2e\x4a\x80\x2e\xea\x84\x2e\xae\x86\x2e\xee\x87\x3e\x39\x0f\x7a\x39\x43\x2f\x6f\x83\x2e\x89\x84\x2e\x8d\x85\x2e\xed\x82\x3e\xa5\x0a\x7a\x85\x07\xbd\x62\x10\xba\x6c\x3d\xf4\xca\x58\xe8\x95\xdd\xd0\xe5\x1b\xa0\x2b\xca\xa0\x2b\x93\xa1\x4f\x4d\x80\x5e\x15\x09\xbd\x3a\x06\x7a\xf5\x26\xe8\xaa\x0d\xd0\x6b\xfa\xa0\x4f\x1b\x84\xae\x8e\x86\xae\x6e\x81\x3e\xa3\x00\xfa\xcc\x12\xe8\xb3\x72\xa1\x6b\xca\xa0\xcf\xae\x82\x3e\xc7\x83\x3e\x67\x18\xfa\xdc\x7a\xe8\xda\x12\xe8\xda\x4d\xd0\xe7\x15\x41\x9f\x3f\x07\xfa\x82\x08\xe8\x0b\x9a\xa1\xd7\x36\x43\x5f\xb8\x1e\xfa\xa2\x75\xd0\x17\x17\x41\xd7\xc5\x42\xd7\x0d\x43\x5f\xb2\x01\xfa\xd2\x66\xe8\xcb\x1a\xa0\xeb\x33\xa1\xeb\xb7\x40\x5f\xbe\x09\xfa\x8a\x6e\xe8\x2b\x9b\xa0\xd7\x65\x42\x5f\x15\x0d\x7d\x75\x11\xf4\xd5\xc3\xd0\xd7\xd4\x42\x37\xa4\x42\x37\x8c\x42\x5f\xdb\x0a\x7d\xdd\x1c\xe8\xeb\x23\xa1\xaf\x6f\x85\x5e\x9f\x0f\xbd\x7e\x00\xfa\x86\x3e\xe8\x1b\xab\xa0\x6f\xca\x85\x6e\x4c\x86\x6e\xec\x83\xbe\xb9\x13\xfa\x96\x75\xd0\xb7\x32\xf4\xad\x5d\xd0\x4d\xad\xd0\xb7\x45\x42\xdf\xb6\x09\xfa\xf6\x6c\xe8\x3b\xaa\xa0\x9b\x93\xa1\x9b\x37\x42\xdf\x99\x0f\x7d\xd7\x14\xe8\xbb\x06\xa0\xef\xce\x87\xbe\x7b\x13\x74\x4b\x2d\xf4\x3d\xd9\xd0\xf7\xac\x87\xbe\x37\x0b\xfa\xde\x4e\xe8\xfb\xb2\xa1\x5b\xe3\xa1\x5b\x3b\xa0\xef\x6f\x82\x7e\xc0\x81\x7e\x60\x10\xfa\xc1\x0e\xe8\xb6\x78\xe8\xb6\x1e\xe8\x87\x62\xa0\x1f\x6a\x81\x7e\x78\x0e\xf4\xc3\xcd\xd0\x8f\xc4\x40\xb7\x4f\x81\x6e\xaf\x86\x6e\x1f\x85\x7e\xb4\x0e\xfa\xd1\x51\xe8\xc7\x1a\xa0\x1f\xf7\xa0\x1f\xef\x87\xde\x50\x00\xfd\x44\x14\xf4\x13\x5b\xa0\x9f\x6c\x85\x7e\xaa\x0e\xba\xa3\x0b\xfa\xe9\x75\xd0\x4f\xf7\x43\x3f\x53\x07\xfd\x6c\x2e\xf4\xb3\x03\xd0\x9d\xdd\xd0\xcf\xe5\x40\x3f\x9f\x0c\xfd\x7c\x13\xf4\x0b\xd1\xd0\x5d\x51\xd0\x5d\x75\xd0\x2f\xc6\x41\xbf\x58\x03\xfd\x52\x16\xf4\x4b\x7d\xd0\x2f\x7b\xd0\x2f\xb7\x41\x77\x37\x42\xbf\x02\xe8\x57\xaa\xa1\x5f\x65\xe8\x57\xab\xa0\x5f\x73\xa0\x5f\x6b\x82\xee\xc9\x84\xee\xe9\x82\x7e\xbd\x1a\xfa\x8d\x6c\xe8\x37\x46\xa1\xdf\xdc\x04\xfd\x56\x04\xf4\xdb\x80\x7e\xbb\x0a\xfa\x9d\x04\xe8\xbe\x08\xe8\xbe\x2a\xe8\x77\xe3\xa0\xdf\xdd\x00\xfd\x5e\x15\xf4\xfb\xf1\xd0\xef\x0f\x43\x6f\xac\x82\xfe\x20\x06\xfa\x83\x61\xe8\x0f\xcb\xa0\x3f\x6a\x84\xee\x2f\x82\xfe\x38\x1e\xfa\xe3\x11\xe8\x4f\x06\xa0\x3f\x6d\x87\x1e\xc8\x82\x1e\xe8\x86\xfe\xac\x19\xfa\xf3\x12\xe8\x2f\x72\xa0\x07\x53\xa1\xbf\xcc\x85\xfe\xaa\x1a\xfa\xeb\x11\xe8\x6f\x4a\xa0\xbf\x8d\x82\xfe\x76\x10\xfa\xbb\x26\xe8\xa1\x64\xe8\xa1\x61\xe8\xef\xab\xa1\x7f\xa8\x86\xfe\x31\x0b\x7a\x38\x1b\xfa\xa7\x1c\xe8\x9f\xb3\xa0\x7f\x49\x86\xfe\x35\x0a\xfa\xb7\x41\xe8\xd1\x7c\xe8\x3f\xaa\xa0\x37\x7b\xd0\x9b\x07\xa0\xff\xcc\x83\xfe\xb3\x13\x7a\x4b\x3b\xf4\x5f\x31\xd0\x7f\xd5\x43\xff\x35\x0a\x42\x37\x48\x47\x83\x28\x12\xc4\x5b\x7f\xfa\x41\xa6\x11\x64\xe5\x81\xec\x2c\x90\xdd\x0c\x72\x00\x72\xea\x41\xbe\x48\x90\xaf\x0f\x34\xa1\x11\x34\x31\x17\x14\x11\x01\x9a\x94\x09\xda\x61\x2d\x68\x72\x14\x68\x72\x0b\x68\x4a\x2a\x68\x4a\x37\x68\xc7\x6a\xd0\x4e\x09\xa0\x9d\xda\x41\x3b\x7b\xa0\x9d\xbb\x41\x91\xf9\xa0\xc8\x41\xd0\x2e\x25\xa0\x5d\x53\x41\xbb\x4d\x01\x45\xcd\x01\xed\x5e\x06\xda\xa3\x0c\xb4\x67\x09\x68\xcf\x7e\x50\x74\x0e\x28\xba\x0d\x34\x35\x06\x34\xb5\x0b\xb4\x57\x25\x68\xaf\x51\xd0\xde\x35\xa0\x98\x38\x50\x4c\x27\x68\x9f\x22\xd0\x34\x80\xa6\xf5\x81\xf6\x6d\x01\xc5\x26\x83\x62\x3b\x41\xfb\x75\x82\xf6\xef\x01\xc5\x31\x68\x7a\x14\x68\x7a\x2d\x68\x46\x19\xe8\xc0\x3c\x50\x7c\x02\x28\x7e\x14\x34\x73\x04\x34\xab\x1e\x34\x3b\x19\x34\x7b\x08\x94\x50\x0b\xf2\x47\x82\xfc\xdd\xa0\x40\x09\xc8\xcd\x07\x79\x55\x20\xaf\x1f\x14\xec\x01\x25\x45\x80\x92\x23\x40\x29\xb9\xa0\x94\x2d\xa0\x83\xf3\x40\xa9\xb1\xa0\x43\x52\x41\x87\x8c\x82\x0e\xed\x02\x1d\x36\x0a\x4a\x8b\x07\xa5\x27\x83\x32\xe6\x80\x32\xd7\x81\x42\x9b\x40\x73\xeb\x40\x87\x27\x80\x0e\xdf\x08\xca\xaa\x01\xcd\x2b\x01\x1d\x91\x07\x3a\x32\x1f\x94\x5d\x02\x9a\x1f\x0b\x9a\xdf\x01\x5a\x30\x00\x5a\x38\x02\x3a\x2a\x1e\xb4\x28\x17\xb4\x68\x10\xb4\xb8\x0a\x94\x5b\x00\x5a\x92\x0b\x3a\xda\x01\x1d\xdd\x09\x3a\xa6\x03\x94\xd7\x0e\x3a\x36\x12\x74\x6c\x25\xe8\xb8\x7a\xd0\xf1\xcd\xa0\xfc\x5a\xd0\x09\x39\xa0\x13\xb6\x80\x4e\x6c\x01\x9d\x94\x0c\x3a\xa9\x13\x54\x90\x05\x2a\x9c\x02\x5a\x0a\xd0\x32\x07\xb4\xac\x16\xb4\x6c\x04\x54\x94\x07\x2a\xea\x04\x15\x27\x80\x8a\x1b\x40\xc5\x9b\x40\x27\xa7\x82\x4e\x6e\x06\x2d\x07\x68\x79\x36\x68\x79\x03\xa8\x64\x0a\xa8\x64\x2d\xa8\x64\x04\x54\x9a\x07\x2a\xed\x01\x9d\x92\x00\x3a\xa5\x0e\xb4\x02\xa0\x15\x25\xa0\x32\x80\xca\xb6\xc6\x3e\xd0\xca\x2c\xd0\xca\x76\x50\x39\x83\xca\x73\x40\xe5\x03\xa0\x8a\x02\x50\x45\x1f\xa8\x32\x13\x54\x59\x0d\xaa\x6c\x05\x55\x6e\x01\x9d\x9a\x03\x3a\x75\x1d\xe8\xd4\x7e\xd0\xaa\x3a\xd0\xaa\x2d\xa0\xd5\x59\xa0\xd5\xf5\xa0\xd5\x83\xa0\xaa\x48\x50\xd5\x5a\x50\xd5\x06\x50\xd5\x10\x68\x4d\x1c\x68\x4d\x01\x68\x4d\x2b\x68\xcd\x10\xe8\xb4\x4c\xd0\x69\x0d\xa0\xd3\x86\x41\xa7\x97\x81\x4e\x1f\x02\x55\xd7\x83\xaa\x87\x41\x67\x78\xa0\x33\x2a\x41\x67\xb4\x81\xce\x04\xe8\xcc\x6c\xd0\x99\x95\xa0\x33\xdb\x41\x67\x79\xa0\xb3\x3a\x40\x35\xb1\xa0\x9a\x7c\x50\x4d\x17\xa8\x66\x18\x74\x76\x26\xe8\xec\x61\xd0\x39\xb9\xa0\x73\xaa\x40\xe7\xb4\x81\xce\xe9\x03\x9d\x1b\x09\x3a\xb7\x04\x74\x6e\x1b\xe8\xdc\x61\x50\x6d\x2a\xa8\xb6\x09\x74\x5e\x04\xe8\xbc\x1c\xd0\x79\xb5\xa0\xf3\xda\x40\xe7\x33\xe8\x7c\x0f\x74\x7e\x11\xe8\xfc\xf5\xa0\xf3\xfb\x40\x17\x4c\x01\x5d\x90\x0f\xba\xa0\x09\x74\xc1\x00\x68\x6d\x02\x68\x6d\x03\x68\x6d\x1f\xe8\xc2\x18\xd0\x85\x99\xa0\x0b\x6b\x41\x17\x6e\x02\x5d\x94\x0b\xba\xa8\x03\x74\x71\x24\xe8\xe2\x0d\xa0\xba\x68\x50\x5d\x35\xa8\xae\x17\x74\x49\x2c\xe8\x92\x7a\xd0\x25\xc3\xa0\x4b\x0b\x40\x97\x36\x80\x2e\xed\x03\x5d\x96\x0c\xba\xac\x01\x74\xd9\x00\xa8\x3e\x1e\x54\x5f\x04\xaa\x5f\x0f\xaa\x1f\x05\x5d\x9e\x0a\xba\xbc\x16\x74\xf9\x30\xe8\x8a\x5c\xd0\x15\x75\xa0\x2b\x86\x41\x57\x16\x81\xae\x6c\x05\xad\x8b\x05\xad\x6b\x00\x5d\x05\xd0\x55\x09\xa0\xab\xca\x40\x57\xb5\x82\xae\x1a\x00\x5d\x9d\x0b\xba\xba\x11\x74\xf5\x08\xe8\x9a\x22\xd0\x35\xbd\xa0\x86\x7c\x50\xc3\x08\xe8\xda\x75\xa0\xeb\xa6\x80\xae\xeb\x05\x5d\x9f\x03\xba\x7e\x08\xb4\xbe\x00\xb4\xbe\x1b\x74\x43\x1e\xe8\x86\x3e\xd0\x8d\xa9\xa0\x1b\xdb\x41\x37\x0e\x82\x6e\xca\x05\xdd\x34\x02\x6a\x8c\x05\x35\x96\x80\x1a\x07\x40\x37\x7b\xa0\x9b\x5b\x40\xb7\xc4\x83\x6e\x69\x07\xdd\x1a\x0d\xba\xb5\x03\xd4\x14\x0d\x6a\xca\x03\x35\x0d\x82\x6e\xcb\x02\xdd\xd6\x03\xba\x3d\x0e\x74\xfb\x06\xd0\x1d\x71\xa0\x3b\x3a\x40\xcd\x51\xa0\xe6\x02\x50\xf3\x10\xe8\xce\x32\xd0\x5d\x0e\xe8\xae\x3a\xd0\xdd\x51\xa0\xbb\x5b\x40\x2d\xf1\xa0\x96\x5a\x50\xcb\x10\xe8\x9e\x1c\xd0\x3d\x1b\x40\xf7\xc6\x83\xee\x5d\x0b\xba\xb7\x0b\x74\xdf\x1c\xd0\x7d\x1d\xa0\xd6\x18\x50\x6b\x11\xa8\xb5\x19\x74\x7f\x24\xe8\xfe\x7c\xd0\xfd\x8d\xa0\xfb\x7b\x40\xf7\x6f\x01\x3d\x90\x0a\x7a\xa0\x09\xf4\x40\x2f\xe8\x41\x06\x3d\x38\x07\xf4\xe0\x06\x50\x5b\x0c\xa8\xad\x06\xd4\xb6\x11\xf4\x50\x24\xe8\xa1\x02\xd0\x43\xbd\xa0\x87\x73\x40\x0f\x37\x82\x1e\xde\x02\x7a\x24\x0f\xf4\x48\x1b\xe8\x91\x21\x50\xfb\x1c\x50\x7b\x35\xa8\xbd\x05\xd4\x3e\x02\x7a\x34\x1f\xf4\x68\x1b\xe8\xb1\x29\xa0\xc7\x2a\x41\x8f\xf5\x81\x1e\xcf\x06\x3d\xde\x00\x7a\x7c\x03\xe8\xf1\x7e\xd0\x06\x80\x36\xc4\x82\x36\xe4\x80\x36\xd4\x80\x36\xb4\x83\x36\x6c\x02\x3d\x91\x0d\x7a\xa2\x07\xf4\x64\x35\xe8\xc9\x11\xd0\x53\x95\xa0\xa7\x86\x40\x1d\x25\xa0\x8e\x7e\xd0\xd3\x39\xa0\xa7\x47\x40\xcf\x34\x80\x9e\x19\x06\x3d\x5b\x09\x7a\xb6\x07\xd4\x99\x0d\xea\x6c\x04\x3d\x37\x05\xf4\x5c\x25\xe8\xb9\x11\xd0\xf3\x45\xa0\xe7\x47\x40\x2f\xe4\x80\x5e\x18\x00\x75\xcd\x01\x75\xf5\x82\x5e\x8c\x07\xbd\xb8\x01\xf4\x52\x1c\xe8\xa5\x1e\xd0\xcb\x79\xa0\xee\x48\x50\x77\x2e\xa8\xbb\x1d\xf4\x4a\x0c\xe8\x95\x66\xd0\x2b\x43\xa0\x57\xb3\x41\xaf\x36\x80\x5e\x1d\x01\xbd\x56\x02\x7a\x6d\x18\xd4\x93\x07\xea\xe9\x03\xbd\x1e\x0f\x7a\x7d\x3d\xe8\x0d\x07\xf4\x46\x0d\xe8\x4d\x07\xf4\x66\x2d\xe8\xcd\x8d\xa0\xde\x64\x50\x6f\x3d\xa8\x77\x10\xf4\x56\x02\xe8\xad\x5a\xd0\x5b\x1b\x40\x6f\x0d\x81\xde\xf6\x40\x6f\x57\x81\xde\x6e\x06\xbd\xdd\x03\x7a\x27\x0a\xf4\x4e\x01\xe8\x9d\x5e\x50\x5f\x1e\xa8\xaf\x0b\xf4\x6e\x16\xe8\xdd\x76\xd0\x7b\xc9\xa0\xf7\xd6\x81\xde\x1b\x02\xbd\x9f\x09\x7a\xbf\x09\xf4\xfe\x10\x68\x63\x2a\x68\x63\x0b\xe8\x83\x28\xd0\x07\xbd\xa0\x0f\xeb\x40\x1f\x15\x81\xfa\x33\x41\xfd\x3d\xa0\x8f\x73\x41\x1f\xf7\x83\x3e\x29\x01\x7d\xd2\x03\xfa\x34\x1b\xf4\x69\x0b\x68\x20\x16\x34\x50\x0f\x1a\x18\x00\x7d\x96\x05\xfa\xac\x11\xf4\x79\x24\xe8\xf3\x6a\xd0\xe7\x1b\x41\x5f\xc4\x82\xbe\x68\x07\x0d\xa6\x82\x06\x7b\x40\x5f\xe6\x82\xbe\x8a\x00\x7d\xd5\x01\xfa\xba\x06\xb4\xc9\x03\x6d\xea\x07\x7d\x53\x03\xfa\xa6\x03\xf4\x6d\x34\xe8\xdb\x7c\xd0\xb7\x5b\xdb\x23\xa0\xef\xb2\x40\xdf\x35\x82\x86\x22\x40\x43\x0d\xa0\xef\xa3\x41\xdf\x37\x83\x7e\x88\x07\xfd\xd0\x08\xfa\x31\x02\xf4\x63\x1b\x68\x38\x17\x34\xbc\x09\xf4\x53\x0d\xe8\xa7\x11\xd0\xcf\x65\xa0\x9f\x3b\x40\xbf\x38\xa0\x5f\x1a\x40\x23\xd1\xa0\x91\x56\xd0\xaf\x1e\xe8\xd7\x4d\xa0\xdf\x1a\x40\xbf\xc7\x80\x7e\x6f\x06\x8d\x26\x80\x46\xdb\x41\x7f\x44\x80\xfe\x28\x00\xfd\x31\x00\xda\x9c\x0f\xda\xdc\x0c\xfa\x33\x02\xf4\x67\x11\xe8\xcf\x0e\xd0\x16\x06\x6d\xc9\x02\x6d\x59\x0b\xda\xd2\x09\xfa\x2b\x12\xf4\x57\x23\xe8\xef\x2c\xd0\xdf\x1b\x41\xff\x94\x80\xfe\x69\x03\xa3\x0a\x8c\x1e\xb0\xca\x01\xab\x6e\xb0\x2e\x01\xeb\x21\x30\x35\x82\x39\x06\xcc\x3d\x60\x53\x02\xb6\x12\xc0\x56\x3f\xd8\x6e\x03\x3b\x1e\xd8\x19\x00\xfb\x0a\xc0\x13\x22\xc0\x13\xea\xc1\x13\x3d\xf0\xc4\x5e\x70\x44\x03\x78\x52\x32\x78\x07\x07\xbc\x43\x1d\x78\x72\x02\x78\x72\x35\x78\xf2\x08\x78\x4a\x3e\x78\xca\x08\x78\xc7\x22\xf0\x4e\x0e\x78\xa7\x1a\xf0\xce\xb1\xe0\x9d\xd7\x83\x23\x53\xc1\x91\x3d\xe0\x5d\xea\xc1\xbb\xc6\x81\x77\x1d\x01\xef\x56\x02\x8e\x8a\x00\x47\x55\x82\xa3\x3a\xc1\xbb\x3b\xe0\xdd\x73\xc1\xbb\x77\x83\xf7\x48\x05\xef\xd1\x03\xde\xb3\x00\x1c\x0d\x70\x74\x13\x78\x6a\x2a\x78\x6a\x3f\x78\xaf\x06\xf0\xde\x39\xe0\x98\x48\x70\x4c\x3f\x78\x9f\x6a\xf0\xb4\x28\xf0\xb4\x66\xf0\xbe\x1e\x78\xdf\x4e\x70\x6c\x0e\x38\x76\x04\xbc\x5f\x13\x78\xff\x1c\xf0\x01\x0c\x3e\xa0\x1e\x1c\x17\x05\x8e\xab\x06\xc7\x6d\x04\x4f\xcf\x05\x4f\xef\x05\xcf\xc8\x01\xcf\xe8\x05\x1f\x98\x0d\x3e\xb0\x1b\x1c\x5f\x00\x8e\x1f\x05\xcf\x5c\x0f\x9e\x95\x0a\x9e\xd5\x0e\x9e\x9d\x00\x9e\x5d\x03\x9e\x3d\x04\x4e\xf0\xc0\x09\x4d\x60\x3f\x83\xfd\xf5\x60\xff\x16\x70\x60\x1d\xd8\x4d\x05\xbb\x43\x60\xaf\x0d\x1c\xac\x02\x27\xa6\x82\x93\x18\x9c\x34\x04\x4e\xde\x08\x4e\xc9\x04\xa7\xb4\x83\x0f\x4a\x05\x1f\xd4\x05\x3e\x38\x1b\x7c\xf0\x46\x70\xea\x5a\xf0\x21\x09\xe0\x43\x7a\xc1\x87\x56\x82\x0f\x8b\x03\x1f\x36\x00\x9e\xb3\x1e\x9c\x96\x03\x4e\x6b\x03\xa7\x4f\x01\xa7\xd7\x81\x33\x00\xce\xa8\x06\x67\x0c\x83\x33\x0b\xc0\x99\xbd\xe0\x50\x1e\x38\x34\x00\x9e\x5b\x02\x9e\x3b\x0c\x3e\xbc\x11\x9c\x95\x05\xce\x6a\x01\xcf\x73\xc0\xf3\x6a\xc1\xf3\x46\xc1\x47\x54\x82\x8f\x18\x02\x1f\x59\x07\xce\x8e\x05\x67\xaf\x05\x67\x0f\x82\xe7\xe7\x83\xe7\xf7\x81\x17\x64\x83\x17\x74\x81\x17\x16\x80\x17\x6e\x01\xe7\xe4\x81\x73\xda\xc1\x47\xc5\x81\x8f\x6a\x04\x2f\x9a\x02\x5e\x54\x07\x5e\x1c\x03\x5e\xbc\x01\x9c\x3b\x07\x9c\xdb\x0d\x5e\x52\x02\x3e\xda\x01\x1f\xdd\x0a\x3e\x26\x07\x7c\xcc\x46\x70\x5e\x01\xf8\x58\x80\x8f\x6d\x02\x1f\x37\x07\x7c\xdc\x00\xf8\xf8\x7c\xf0\xf1\x1b\xc1\xf9\x65\xe0\x13\x00\x3e\xa1\x01\x7c\x62\x1c\xf8\xc4\x01\xf0\x49\xeb\xc1\x27\x8d\x80\x0b\x4a\xc0\x05\x03\xe0\xc2\x1a\xf0\xd2\x38\xf0\xd2\x3e\xf0\xb2\xf5\xe0\xa2\x7c\x70\x71\x0c\xb8\x78\x10\x7c\x72\x0f\x78\x79\x3b\xb8\x24\x07\x5c\x32\x04\x2e\x6d\x02\x9f\x92\x0b\x5e\xe1\x80\x57\x74\x80\xcb\x1a\xc0\x2b\xcb\xc0\xe5\x0e\xb8\xbc\x05\x5c\x91\x0c\xae\xe8\x06\x57\xc6\x81\x2b\xeb\xc0\x95\x1b\xc1\xa7\xc6\x81\x4f\x6d\x02\xaf\x8a\x02\xaf\x5a\x0b\x5e\x35\x0c\x5e\x5d\x0f\xae\x8a\x03\x57\x8d\x82\xd7\x74\x83\x4f\x6b\x05\x9f\xde\x00\xae\xae\x01\x9f\x51\x04\x3e\xb3\x12\x7c\x56\x0d\xb8\x26\x12\x5c\xd3\x0a\x3e\x3b\x1f\x7c\x4e\x04\xf8\x9c\x0e\xf0\xb9\x95\xe0\xda\x4c\xf0\x79\x51\xe0\xf3\x5a\xc0\xe7\xa7\x82\xcf\x1f\x04\x5f\x50\x0f\x5e\xeb\x81\xd7\x0e\x80\x2f\x6c\x05\x5f\x54\x0d\xbe\x18\xe0\x8b\xeb\xc0\x75\x71\xe0\xba\x6e\xf0\x25\x25\xe0\x4b\x23\xc0\x97\xf6\x82\x2f\x6b\x00\xd7\x17\x80\x2f\x8f\x07\x5f\x31\x05\x7c\xc5\x08\xf8\xca\x8d\xe0\x75\x9d\xe0\xab\xba\xc1\x57\xf7\x82\xaf\x69\x00\x37\xe4\x81\xaf\xf5\xc0\xd7\x4d\x01\x5f\x37\x04\xbe\xbe\x1b\xbc\xbe\x1b\x7c\x43\x37\xf8\xc6\x4a\xf0\x4d\x00\xdf\xd4\x09\x6e\x2c\x02\xdf\x1c\x0b\xbe\x79\x10\x7c\x4b\x37\xf8\xd6\x04\xf0\xad\xb5\xe0\x5b\x07\xc0\x4d\x73\xc0\x4d\x2d\xe0\xa6\x01\xf0\x6d\x53\xc0\xb7\x65\x81\x6f\x6b\x00\xdf\x1e\x03\xbe\xbd\x09\x7c\x07\x83\xef\xa8\x03\x37\x47\x80\x9b\xdb\xc0\x77\x02\x7c\x67\x0e\xf8\xce\x26\xf0\x9d\xc3\xe0\xbb\xb2\xc1\x77\x35\x82\xef\x1a\x02\xdf\x5d\x00\xbe\xbb\x03\xdc\x02\x70\x4b\x1d\xf8\x9e\x29\xe0\x7b\xd6\x82\xef\x4d\x06\xdf\xbb\x0e\x7c\x6f\x2f\xf8\xbe\x68\xf0\x7d\x25\xe0\xfb\x3a\xc0\xad\x53\xc0\xad\x6b\xc1\xad\xa3\xe0\xfb\x73\xc1\xf7\x8f\x82\x1f\x68\x04\x3f\x18\x0f\x7e\xb0\x13\xdc\x96\x03\x7e\x28\x06\xfc\x50\x35\xf8\xa1\x76\xf0\xc3\x00\x3f\x9c\x0d\x7e\xb8\x13\xfc\x48\x0c\xf8\x91\x5a\xf0\x23\x2d\xe0\xf6\x22\xf0\xa3\x0c\x7e\xb4\x13\xfc\x58\x2d\xf8\xf1\x02\xf0\xe3\x1b\xc1\x1b\x72\xc0\x1b\xfa\xc1\x4f\x94\x80\x9f\x04\xf8\xc9\x78\xf0\x93\x45\xff\x0f\x3f\xb5\xe0\x27\x3b\xc0\x4f\x0e\x81\x9f\x8a\x06\x3f\x95\x0c\x7e\x2a\x17\xfc\x54\x25\xf8\xa9\x66\xf0\x53\x1b\xc1\x1d\x0c\xee\x88\x07\x77\xe4\x82\x3b\x6a\xc0\x1d\xcd\xe0\x8e\x1e\x70\xc7\x08\xf8\xe9\x7c\xf0\xd3\x8d\xe0\xa7\xfb\xc1\xcf\xc4\x80\x9f\xc9\x03\x3f\xd3\x06\x7e\x66\x04\xfc\x6c\x1d\xf8\xd9\x16\xf0\xb3\x7d\xe0\x67\xb7\x80\x3b\xe3\xc1\x9d\xf9\xe3\x3f\xcf\xc5\x82\x9f\x9b\x03\x7e\xae\x0c\xfc\x5c\x0b\xf8\xb9\x3e\xf0\xf3\x00\x3f\x5f\x06\x7e\xbe\x0e\xfc\x7c\x0b\xf8\x85\x32\xf9\x69\x06\xbf\x30\x02\xee\x8a\x02\x77\xa5\x82\xbb\x2a\xc1\x5d\xcd\xe0\xae\x61\xf0\x8b\x1e\xf8\xc5\x3a\xf0\x8b\xc3\xe0\x97\xa2\xc0\x2f\x35\x81\x5f\x76\xc0\x2f\x67\x81\x5f\x6e\x03\x77\x3b\xe0\xee\x5c\x70\xf7\x3a\x70\xf7\x20\xf8\x95\x4c\xf0\x2b\xfd\xe0\x57\x73\xc1\xaf\x36\x80\x5f\x03\xf8\xb5\x1a\x70\x0f\x83\x7b\xd6\x82\x5f\xf7\xc0\xaf\x0f\x81\xdf\xa8\x04\xbf\x31\x04\x7e\x73\x0e\xf8\xcd\xf5\xe0\xde\x6c\x70\xef\x46\xf0\x5b\x05\xe0\xb7\xfa\xc1\x6f\xe7\x80\xdf\xee\x07\xbf\x93\x05\x7e\xa7\x09\xdc\x07\x70\x5f\x16\xb8\xaf\x1f\xfc\x6e\x36\xf8\xdd\x7e\xf0\x7b\x6b\xc1\xef\xf5\x83\xdf\xcf\x06\xbf\xbf\x01\xbc\xb1\x08\xbc\x71\x1d\xf8\x83\x04\xf0\x07\x43\xe0\x0f\x5b\xc1\x1f\x35\x83\xfb\xeb\xc0\x1f\xa7\x82\x3f\x5e\x07\xfe\xb8\x1b\xfc\x09\xc0\x9f\x24\x83\x3f\xa9\x04\x7f\xd2\x05\xfe\x34\x0a\xfc\x69\x35\xf8\xd3\x61\xf0\x40\x02\x78\x20\x0f\x3c\xb0\x0e\x3c\x30\x80\xb1\x7f\x50\xf6\x59\x3c\xf8\xb3\x7c\xf0\x67\x1b\xc1\x9f\x8d\x82\x3f\xcf\x03\x7f\xde\x04\xfe\x22\x16\xfc\x45\x19\xf8\x8b\x01\xf0\x60\x24\x78\x30\x0b\x3c\xd8\x08\x1e\xec\x00\x7f\xc9\xe0\x2f\xb3\xc1\x5f\x56\x83\xbf\x6c\x00\x7f\xb9\x01\xfc\xe5\x30\xf8\xab\x29\xe0\xaf\xb2\xc0\x5f\x55\x82\xbf\x6a\x03\x7f\x35\x02\xfe\x3a\x19\xfc\xf5\x3a\xf0\xd7\xc3\xe0\x4d\x51\xe0\x4d\x99\xe0\x4d\x95\xe0\x4d\xcd\xe0\x6f\x1c\xf0\x37\xb9\xe0\x6f\xea\xc0\xdf\xb4\x83\xbf\x19\x00\x7f\x1b\x09\xfe\xb6\x1a\xfc\x6d\x33\xf8\xdb\x8d\xe0\xef\x1c\xf0\x77\xa9\xe0\xef\x6a\xc0\xdf\x6d\x02\x0f\x45\x83\x87\x0a\xc0\x43\x7d\xe0\xef\xe3\xc1\xdf\x57\x82\xbf\x1f\x04\xff\x90\x0a\xfe\xa1\x06\xfc\x63\x14\xf8\xc7\x7c\xf0\x8f\x1b\xc0\x3f\xf6\x81\x7f\x1c\x06\x0f\x47\x80\x87\xe3\xc0\xc3\x99\xe0\x9f\xe7\x80\x7f\x8b\x01\xff\xd1\x01\xfe\x63\x23\x78\x33\xc0\x9b\xa3\xc1\x9b\xb3\xc0\x9b\x8b\xc0\x9b\xd7\x81\x37\xb7\x82\x37\x77\x83\x37\x0f\x82\xff\x8c\x06\xff\xd9\x04\xde\x32\x08\xfe\x2b\x1a\xfc\x57\x2d\xf8\xef\x28\xf0\xdf\x25\xe0\x7f\x62\xc1\xff\x74\xc0\xa0\x00\x06\xbd\x30\xaa\x0a\x46\x0d\xc0\xe8\x6a\x18\xdd\x03\x43\x0e\x0c\xe5\xc1\x50\x27\x0c\xc7\xc3\x70\x15\x0c\xb7\xc3\x98\x08\x18\x53\x02\x63\xfa\x60\xac\x12\x18\xab\x17\xc6\x9e\x02\x63\x17\xc0\xd8\x2d\x30\xf6\x08\x8c\x13\x07\xe3\xe4\xc3\x38\xdd\x30\xbe\x28\x18\x5f\x33\xcc\x84\x58\x98\x09\x8d\x30\x13\xba\x60\x26\x6c\x82\x99\x98\x07\x33\xb1\x1e\x66\x62\x37\x4c\x84\x03\x13\x91\x09\x13\x51\x0d\x13\xd1\x04\x13\xd1\x0d\x33\x89\x61\x26\x65\xc2\x4c\x5a\x0b\x33\xa9\x15\x66\xd2\x20\xcc\x0e\xd1\x30\x3b\x34\xc0\xec\x30\x0c\x33\x39\x02\x66\x72\x1c\xcc\xe4\x39\x30\x93\xdb\x60\xa6\x38\x30\x53\xda\x60\x76\xcc\x84\xd9\xb1\x12\x66\xc7\x46\x98\x1d\xfb\x60\x76\xc2\xf8\xcf\xce\x8d\x30\x91\xb1\x30\x91\xf9\x30\x91\x75\x30\x91\x5d\x30\x91\x43\x30\xbb\x34\xc0\xec\x32\x04\xb3\x6b\x02\xcc\xae\xb5\x30\xbb\xf6\xc2\xec\x96\x0a\xb3\x5b\x3b\x4c\x14\x60\xa2\xb2\x61\xa2\xda\x61\x76\x8f\x85\xd9\xbd\x08\x66\xf7\x06\x98\x3d\xe2\x60\xf6\x58\x07\xb3\x47\x2b\xcc\x1e\xfd\x30\x7b\x46\xc0\xec\x99\x0a\xb3\x67\x09\xcc\x9e\xeb\x61\xf6\xec\x86\xd9\x73\x18\x26\x3a\x06\x26\x3a\x07\x26\xba\x1a\x26\xba\x05\x26\xba\x1f\x66\x6a\x04\xcc\xd4\x54\x98\xa9\x05\x30\x53\xeb\x60\xa6\x6e\x80\x99\xba\x09\x66\xaf\x68\x98\xbd\xb2\x61\xf6\xaa\x86\xd9\xab\x09\x66\xaf\xde\xb1\x3f\x24\x34\x7b\x7b\x30\x7b\x17\xc1\xec\x5d\x0f\xb3\x77\x1b\xcc\xde\xfd\x30\x31\x53\x60\x62\x32\x61\x62\xaa\x61\x62\x5a\x60\x62\x7a\x61\x62\xb6\xc0\xec\x13\x0f\xb3\x4f\x3e\xcc\x3e\x75\x30\xfb\x6c\x80\xd9\x67\x08\x66\x5a\x34\xcc\xb4\x4c\x98\x69\x55\x30\xd3\x1a\x61\xa6\xf5\xc0\x4c\xdb\x02\xb3\x6f\x02\xcc\xbe\x05\x30\xfb\xd6\xc3\xec\xdb\x0e\xb3\xef\x20\x4c\x6c\x24\x4c\x6c\x16\x4c\x6c\x35\x4c\x6c\x13\x4c\x6c\x17\x4c\xec\x30\xcc\x7e\xb1\x30\xfb\xe5\xc1\xec\x57\x0f\xb3\x5f\x07\xcc\x7e\x83\x30\xfb\x47\xc0\xec\x9f\x0a\xb3\x7f\x25\xcc\xfe\xcd\x30\xfb\xf7\xc1\xec\xbf\x05\xe6\x80\x38\x98\x03\x72\x61\x0e\x58\x0b\x73\x40\x1b\xcc\x01\x03\x30\x71\x53\x60\xe2\x32\x61\xe2\xaa\x60\xe2\xd6\xc3\xc4\x75\xc2\xc4\x0d\xc3\x4c\x8f\x81\x99\x9e\x0b\x33\xbd\x0e\x66\x7a\x1b\xcc\xf4\x3e\x98\x19\x80\x99\xe1\xc1\xcc\x28\x81\x99\xd1\x08\x33\xa3\x07\x66\xc6\x08\xcc\x81\xb1\x30\x07\xe6\xc2\x1c\x58\x07\x73\x60\x07\xcc\x81\x43\x30\xf1\x91\x30\xf1\x99\x30\xf1\x65\x30\xf1\x8d\x30\xf1\xbd\x30\x33\x01\x33\x33\x1e\x66\x66\x1e\xcc\xcc\x3a\x98\x99\x1b\x60\x66\x0e\xc2\xcc\x8a\x84\x99\x95\x09\x33\xab\x1a\x66\x56\x2b\xcc\xac\x3e\x98\x59\xa3\x30\xb3\x63\x60\x66\xe7\xc2\xcc\xae\x83\x99\xdd\x01\x33\x7b\x08\x26\x21\x12\x26\x21\x13\x26\xa1\x0a\x26\xa1\x05\x26\xa1\x1f\xc6\x1f\x01\xe3\xf7\x60\xfc\xf9\x30\xfe\x7a\x18\x7f\x07\x8c\x7f\x18\x26\x10\x03\x13\xc8\x82\x09\x54\xc3\x04\x5a\x60\x02\xbd\x63\x7f\xd0\x61\xdc\x04\x18\x37\x0f\xc6\x5d\x0b\xe3\xb6\xc1\xb8\xfd\x30\x9e\x03\xe3\x6d\x84\x09\xb6\xc2\x24\xd6\xc2\x24\xe5\xc2\x24\xa7\xc2\xa4\xc4\xc1\x1c\x14\x05\x73\xb0\x03\x73\x70\x3d\x4c\xea\x14\x98\xd4\xf5\x30\x87\xc4\xc0\x1c\xd2\x01\x73\x68\x3e\xcc\x61\x80\x39\xac\x09\x66\xce\x1c\x98\x39\x03\x30\x69\xb5\x30\xe9\xb1\x30\xe9\xfd\x30\x19\x0d\x30\x99\x39\x30\xa1\x08\x98\x50\x0b\xcc\xdc\x4c\x98\xb9\xa3\x30\x87\xb7\xc2\x64\x15\xc1\xcc\x8b\x86\x99\xb7\x09\xe6\x88\x0d\x30\x47\x46\xc1\x1c\x59\x09\x73\x64\x3f\x4c\x76\x2e\x4c\x76\x1b\xcc\xfc\x08\x98\xf9\x65\x30\xf3\x7b\x60\x16\x24\xc0\x2c\xa8\x83\x59\x30\x08\xb3\xb0\x0a\x66\x61\x3f\x4c\x4e\x16\x4c\xce\x5a\x98\x9c\x4e\x98\xa3\x52\x61\x8e\x5a\x0f\x73\xd4\x08\xcc\xa2\x04\x98\x45\x65\x30\x8b\x46\x61\x16\xaf\x85\x59\x3c\x0a\x93\x5b\x06\x93\x3b\x08\xb3\xa4\x00\x66\xc9\x46\x98\xa3\xb3\x61\x8e\xae\x85\x02\x7c\xe5\x6a\x11\x72\xc7\xfe\x0d\x97\x86\x82\xc6\xae\xd8\x1a\xca\xe5\xdf\x75\xed\x88\xb7\x41\x50\xec\x03\x70\xe2\xd8\x7f\xa9\x6c\x6b\x5b\x61\x27\x9c\x28\x6d\x0d\x07\x95\xd2\x26\xa4\xa3\x5a\xda\x8c\x68\x3c\x29\x6d\x83\x28\xbc\x27\x6d\x0b\x7b\xe0\x07\x69\xdb\x68\x56\x8e\xb4\x1d\xcc\x50\xad\xd2\xf6\x21\x4e\x6d\xfb\xfc\x04\xcc\x51\x7f\x4b\x7b\x22\x52\xf5\xa1\xd2\x8e\x40\x9d\x3e\x53\xda\x93\x90\x4f\x5a\xda\x3b\x20\x97\xb6\x8d\xad\x1b\xbb\xd2\xc3\xd2\x7e\x05\x09\xd4\x8d\x0c\x54\xa0\x12\x67\x60\x15\x4a\xb1\x1c\x25\xa8\x42\x0c\x02\x48\x80\x1f\x01\xc4\xe0\x70\x54\xa0\x02\xcb\x51\x86\x62\xc4\x60\x1e\xca\xb1\x0c\xb3\x10\x83\x34\x94\xa1\x0c\x31\x58\x14\x3e\x6b\xf5\xd8\x51\x31\x56\xa3\x18\xab\x70\x1a\x8a\x51\x84\x59\x58\x80\x0a\x54\xa1\x02\x31\x58\x8c\x42\x94\x63\x35\xd2\x51\x81\x32\x14\x61\x3e\x2a\x50\x3e\xf6\xee\x19\xa8\x94\xde\x57\xa2\x10\xcb\x51\x8a\x72\x2c\x47\x0c\x66\x22\xe6\xbf\x9c\x1f\x13\xee\xe1\xff\x7a\xef\xe8\xb1\x51\xac\x46\xe9\x18\x25\x06\x7e\xcc\x42\x02\xbc\xf0\x39\xdb\xce\x98\xf9\x5f\x7a\x2b\x1d\xeb\xa9\x10\x31\xa8\xc2\x2a\x14\xa2\x08\xc5\x63\x23\x5b\x85\x15\x88\x41\x05\x4e\xfe\x3f\xd6\x65\x6b\xaf\x45\x88\x19\xfb\xfc\x19\x88\xc1\xd2\xb1\xf7\x57\xa1\x78\x6c\x5e\xab\x51\x35\x36\xae\xe2\xb1\xcf\x94\x8e\x8d\x6c\xd9\xd8\x2b\x55\x28\x94\xe3\x53\xb0\x66\xec\x5a\xac\x46\x11\x4a\xb1\x0c\x55\x32\x87\xd5\x98\xf5\xff\x63\xcd\xb6\x8d\xe4\x7f\x7f\x32\x73\xec\xda\x6c\xbd\x5a\xe5\x63\x33\x2b\x46\x21\x56\xfe\xc7\xab\xe3\xa3\x5a\x3a\x36\xee\xff\x7d\x7e\xd1\x7f\x3d\x7f\xeb\x95\xaf\x42\x25\x0e\xc2\x6c\xcc\xc6\x32\x54\x8c\x7d\x6e\x16\x96\x6f\xb7\x3e\xb3\xc6\x5e\x5f\x89\xd9\xa8\xc4\x6c\xe9\xb5\x02\xb3\xff\xc7\xb9\xa7\x8f\xfd\x7f\x16\x56\xfe\x0f\x72\xe9\x7f\xcc\xf0\xdf\xbe\x72\xb0\x6a\x8c\xb6\x66\x6c\x8d\x56\x63\xb1\xdc\x77\xa5\x63\x2b\xba\x1a\xb3\x91\x2b\x3d\xfc\xe7\x1c\x57\x61\x31\x4a\x50\x81\xd3\xb1\x0c\x85\x63\x77\x6b\xb6\x9c\x53\x3e\x76\xb4\x75\x0d\xd6\x8c\x5d\xc5\xad\x9f\xdd\x3a\xd3\x92\xb1\xf9\xa7\xa1\x12\x85\x58\x26\x47\xff\x79\x4e\x3c\x62\xfe\xd7\x1d\x17\x18\xbb\xe3\xfe\xfb\x1c\x0b\xb7\xeb\x6b\x16\x2a\xb0\x0a\xcb\x31\x1b\x65\xff\xd1\xe7\xd6\x19\x64\x63\x1e\x32\x10\xc2\x02\x2c\x46\x08\x33\xa5\xcf\x63\x50\x8c\xa5\x38\x79\x8c\x53\x15\xbe\xb7\x8f\x91\xb1\x1f\x81\x35\x63\xdf\x4c\x3f\x92\xc6\x7e\xbb\x38\x08\xee\xd8\x6f\x3f\x92\xc3\xdf\x6d\x17\xe3\x7f\x34\x02\xe0\x9f\x93\x71\x32\xfe\xcb\xff\x7c\xe5\x80\xd2\x8a\x40\x60\x18\x58\xb0\xe1\x60\xeb\xd3\x67\x22\x22\x30\x09\x3b\x60\x32\xa6\x60\x47\xec\x84\x9d\x11\x89\x5d\xb0\x2b\x76\x43\x14\x76\xc7\x1e\xd8\x13\xd1\x98\x8a\xbd\xb0\x37\x62\xb0\x0f\xa6\x61\x5f\xc4\x62\x3f\xec\x8f\x03\x10\x87\xe9\x98\x81\x03\x11\x8f\x99\x98\x85\xd9\xf2\x94\x71\xe1\x21\x88\x44\x24\x21\x19\x29\x38\x08\x07\x23\x15\x87\xe0\x50\x1c\x86\x39\x48\x43\x3a\x32\x90\x89\x10\xe6\xe2\x70\x64\x61\x1e\x8e\xc0\x91\xc8\xc6\x7c\x2c\xc0\x42\xe4\xe0\x28\x2c\xc2\x62\xe4\x62\x09\x8e\xc6\x31\xc8\xc3\xb1\x38\x0e\xc7\x23\x1f\x27\xe0\x44\x9c\x84\x02\x14\x2a\xc6\x1d\x58\x8b\x0b\xf1\x34\xae\xc3\x26\x5c\x84\x2b\x70\x19\x6e\xc6\x3d\x68\x56\x06\x97\xe2\x43\x5c\x80\x6b\x94\xa5\x6c\x5c\xae\x1c\xd4\xe1\x05\x7c\xa2\x7c\xb8\x05\xf7\xe2\x57\x8c\xe0\x37\xdc\x8e\xfb\xf1\x0a\x5e\xc6\x03\x58\x8a\x65\x58\x87\x22\xbc\x86\x62\x74\xe3\x55\xbc\x89\x1e\xbc\x8e\x37\xf0\x0d\x4e\xc6\x3b\xe8\xc5\x5b\x78\x10\xcb\x31\x8c\xab\xf0\x1e\xfa\xf0\x2e\x4a\xf0\x1d\xbe\xc7\x25\x38\x05\xa5\x58\x81\x95\x28\x43\x39\x9a\x50\x81\x53\x51\x39\x76\x9f\xac\x41\x15\x4e\xc3\xe9\xf8\x16\xd5\x38\x13\x67\xe0\x2c\x9c\x8d\x1a\x6c\xc0\x6d\x38\x17\xe7\xa0\x16\xe7\x61\x08\x3f\xe0\x49\x35\x41\x4d\x54\x11\x6a\x92\xda\x41\x4d\xc6\x5f\xf8\x5b\x4d\x51\x3b\xaa\x9d\xd4\xce\xf8\x47\x41\x45\xaa\x5d\xd4\xae\x4a\xa9\xdd\x54\x94\xda\x5d\xed\xa1\xf6\x54\xd1\x6a\xaa\xda\x4b\xed\xad\x62\xd4\x3e\x6a\x1a\x46\xf1\x87\xda\x57\xc5\xaa\xfd\xd4\xfe\xea\x00\x15\xa7\xa6\xab\x19\xea\x40\x15\xaf\x66\xaa\x59\x6a\xb6\x4a\x50\x7e\x15\xc0\x66\xbc\xaf\x5c\xe5\xa9\xa0\x4a\x54\x49\x2a\x59\xa5\xa8\x83\xd4\xc1\x2a\x55\x1d\xa2\x0e\x55\x87\xa9\x39\x2a\x0d\x9f\xe3\x0b\x95\xae\x32\x54\xa6\x0a\xa9\xb9\xea\x70\x95\xa5\xe6\xa9\x23\xd4\x91\x2a\x5b\xcd\x57\x0b\xd4\x42\x95\x83\x36\x3c\xa4\x8e\x52\x8b\xd4\x62\x95\xab\x96\xa8\xa3\xd5\x31\x2a\x4f\x1d\xab\x8e\xc3\x9f\xd8\x82\x41\x7c\xa9\x8e\x57\xf9\xea\x04\x75\xa2\x3a\x49\x15\xa8\x42\xb5\x54\x2d\x53\x45\xaa\x58\x9d\xac\x96\xab\x12\x55\xaa\x4e\x51\x2b\x54\x99\x5a\xa9\xca\x55\x85\xaa\xc4\x53\xea\x54\xb5\x4a\xad\x56\x55\xf8\x0a\x5f\xab\x35\xea\x34\x75\xba\xaa\x56\x67\xa8\x33\xd5\x59\xaa\x46\x9d\xad\xce\x51\xe7\xaa\x5a\x75\x9e\x3a\x5f\x5d\xa0\xd6\xaa\x0b\xd5\x45\xea\x62\xdc\xa5\xea\xd4\x25\xea\x52\x75\x99\xaa\x57\x97\xab\x2b\xd4\x95\x6a\x9d\xba\x4a\x5d\xad\xae\x51\x0d\xea\x5a\x75\x9d\xba\x5e\xad\x57\x37\xa8\x1b\xd5\x4d\xaa\x51\xdd\xac\x6e\x51\xb7\xaa\x26\x75\x9b\xba\x5d\xdd\xa1\x9a\xd5\x9d\xea\x2e\x75\xb7\x6a\x51\xf7\xa8\x7b\xd5\x7d\xaa\x55\xdd\xaf\x1e\x50\x0f\xaa\x36\xf5\x90\x7a\x58\x3d\xa2\xda\xd5\xa3\xea\x31\xf5\xb8\xda\xa0\x9e\x50\x4f\xaa\xa7\x54\x87\x7a\x5a\x3d\xa3\x9e\x55\x9d\xea\x39\xf5\xbc\x7a\x41\x75\xa9\x17\xd5\x4b\xea\x65\xd5\xad\x5e\x51\xaf\xaa\xd7\x54\x8f\x7a\x5d\xbd\xa1\xde\x54\xbd\xea\x2d\xf5\xb6\x7a\x47\xf5\xa9\x77\xd5\x7b\xea\x7d\xb5\x51\x7d\xa0\x3e\x54\x1f\xa9\x7e\xf5\xb1\xfa\x44\x7d\xaa\x06\xd4\x67\xea\x73\xf5\x85\x1a\x54\x5f\xaa\xaf\xd4\xd7\x6a\x93\xfa\x46\x7d\xab\xbe\x53\x43\xea\x7b\xf5\x83\xfa\x51\x0d\xab\x9f\xd4\xcf\xea\x17\x35\xa2\x7e\x55\xbf\xa9\xdf\xd5\xa8\xfa\x43\x6d\x56\x7f\xaa\x2d\xea\x2f\xf5\xb7\xfa\x47\x43\x2b\xad\x35\x69\xd6\x46\x5b\xda\xd6\x8e\xf6\xe9\x09\x7a\xa2\x8e\xd0\x93\xf4\x0e\x7a\xb2\x9e\xa2\x77\xd4\x3b\xe9\x9d\x75\xa4\xde\x45\xef\xaa\x77\xd3\x51\x7a\x77\xbd\x87\xde\x53\x47\xeb\xa9\x7a\x2f\xbd\xb7\x8e\xd1\xfb\xe8\x69\x7a\x5f\x1d\xab\xf7\xd3\xfb\xeb\x03\x74\x9c\x9e\xae\x67\xe8\x03\x75\xbc\x9e\xa9\x67\xe9\xd9\x3a\x41\xfb\x75\x40\xbb\xda\xd3\x41\x9d\xa8\x93\x74\xb2\x4e\xd1\x07\xe9\x83\x75\xaa\x3e\x44\x1f\xaa\x0f\xd3\x73\x74\x9a\x4e\xd7\x19\x3a\x53\x87\xf4\x5c\x7d\xb8\xce\xd2\xf3\xf4\x11\xfa\x48\x9d\xad\xe7\xeb\x05\x7a\xa1\xce\xd1\x47\xe9\x45\x7a\xb1\xce\xd5\x4b\xf4\xd1\xfa\x18\x9d\xa7\x8f\xd5\xc7\xe9\xe3\x75\xbe\x3e\x41\x9f\xa8\x4f\xd2\x05\xba\x50\x2f\xd5\xcb\x74\x91\x2e\xd6\x27\xeb\xe5\xba\x44\x97\xea\x53\xf4\x0a\x5d\xa6\x57\xea\x72\x5d\xa1\x2b\xf5\xa9\x7a\x95\x5e\xad\xab\xf4\x1a\x7d\x9a\x3e\x5d\x57\xeb\x33\xf4\x99\xfa\x2c\x5d\xa3\xcf\xd6\xe7\xe8\x73\x75\xad\x3e\x4f\x9f\xaf\x2f\xd0\x6b\xf5\x85\xfa\x22\x7d\xb1\xae\xd3\x97\xe8\x4b\xf5\x65\xba\x5e\x5f\xae\xaf\xd0\x57\xea\x75\xfa\x2a\x7d\xb5\xbe\x46\x37\xe8\x6b\xf5\x75\xfa\x7a\xbd\x5e\xdf\xa0\x6f\xd4\x37\xe9\x46\x7d\xb3\xbe\x45\xdf\xaa\x9b\xf4\x6d\xfa\x76\x7d\x87\x6e\xd6\x77\xea\xbb\xf4\xdd\xba\x45\xdf\xa3\xef\xd5\xf7\xe9\x56\x7d\xbf\x7e\x40\x3f\xa8\xdb\xf4\x43\xfa\x61\xfd\x88\x6e\xd7\x8f\xea\xc7\xf4\xe3\x7a\x83\x7e\x42\x3f\x89\x8d\xf8\x4c\x3f\xa5\x3b\xf4\xd3\xfa\x19\xfd\xac\xee\xd4\xcf\xe9\xe7\xf5\x0b\xba\x4b\xbf\xa8\x5f\xd2\x2f\xeb\x6e\xfd\x8a\x7e\x15\x1f\xa1\x1f\x1f\x63\x00\x1f\xe0\x53\xfd\x9a\xee\xd1\xaf\xeb\x37\xf4\x9b\xba\x57\xbf\xa5\xdf\xd6\xef\xe8\x3e\xfd\xae\x7e\x4f\xbf\xaf\x37\xea\x0f\xf4\x87\xfa\x23\xdd\xaf\x3f\xd6\x9f\xe8\x4f\xf5\x80\xfe\x4c\x7f\xae\xbf\xd0\x83\xfa\x4b\xfd\x95\xfe\x5a\x6f\xd2\xdf\xe8\x6f\xf5\x77\x7a\x48\x7f\xaf\x7f\xd0\x3f\xea\x61\xfd\x93\xfe\x59\xff\xa2\x47\xf4\xaf\xfa\x37\xfd\xbb\x1e\xd5\x7f\xe8\xcd\xfa\x4f\xbd\x45\xff\xa5\xff\xd6\xff\x10\x48\x91\x26\x22\x26\x43\x16\xd9\xe4\x90\x8f\x26\xd0\x44\x8a\xa0\x49\xb4\x03\x4d\xa6\x29\xb4\x23\xed\x44\x3b\x53\x24\xed\x42\xbb\xd2\x6e\x14\x45\xbb\xd3\x1e\xb4\x27\x45\xd3\x54\xda\x8b\xf6\xa6\x18\xda\x87\xa6\xd1\xbe\x14\x4b\xfb\xd1\xfe\x74\x00\xc5\xd1\x74\x9a\x41\x07\x52\x3c\xcd\xa4\x59\x34\x9b\x12\xc8\x4f\x01\x72\xc9\xa3\x20\x25\x52\x12\x25\x53\x0a\x1d\x44\x07\x53\x2a\x1d\x42\x87\xd2\x61\x34\x87\xd2\x28\x9d\x32\x28\x93\x42\x34\x97\x0e\xa7\x2c\x9a\x47\x47\xd0\x91\x94\x4d\xf3\x69\x01\x2d\xa4\x1c\x3a\x8a\x16\xd1\x62\xca\xa5\x25\x74\x34\x1d\x43\x79\x74\x2c\x1d\x47\xc7\x53\x3e\x9d\x40\x27\xd2\x49\x54\x40\x85\xb4\x94\x96\x51\x11\x15\xd3\xc9\xb4\x9c\x4a\xa8\x94\x4e\xa1\x15\x54\x46\x2b\xa9\x9c\x2a\xa8\x92\x4e\x45\x0b\xad\xa2\xd5\x54\x45\x6b\xe8\x34\x3a\x9d\xaa\xe9\x0c\x3a\x93\xce\xa2\x1a\x3a\x9b\xce\xa1\x73\xa9\x96\xce\xa3\xf3\xe9\x02\x5a\x8b\x5b\xe9\x42\xba\x88\x2e\xa6\x3a\xba\x84\x2e\xa5\xcb\xa8\x9e\x2e\xa7\x2b\xe8\x4a\x5a\x47\x57\xd1\xd5\x74\x0d\x35\xd0\xb5\x74\x1d\xae\xa7\xeb\x69\x3d\xdd\x80\x9b\xe8\x46\xba\x89\x1a\xe9\x66\xba\x85\x6e\xa5\x26\xba\x8d\x6e\xa7\x3b\xa8\x99\xee\xa4\xbb\xe8\x6e\x6a\xa1\x7b\xe8\x5e\xba\x8f\x5a\xe9\x7e\x7a\x80\x1e\xa4\x36\x7a\x88\x1e\xa6\x47\xa8\x9d\x1e\xa5\xc7\xe8\x71\xda\x40\x4f\xd0\x93\xf4\x14\x75\xd0\xd3\xf4\x0c\x3d\x4b\x9d\xf4\x1c\x3d\x4f\x2f\x50\x17\xbd\x48\x2f\xd1\xcb\xd4\x4d\xaf\xd0\xab\xf4\x1a\xf5\xd0\xeb\xf4\x06\xbd\x49\xbd\xf4\x16\xbd\x4d\xef\x50\x1f\xbd\x4b\xef\xd1\xfb\xb4\x91\x3e\xa0\x0f\xe9\x23\xea\xa7\x8f\xe9\x13\xfa\x94\x06\xe8\x33\xfa\x9c\xbe\xa0\x41\xfa\x92\xbe\xa2\xaf\x69\x13\x7d\x43\xdf\xd2\x77\x34\x44\xdf\xd3\x0f\xf4\x23\x0d\xd3\x4f\xf4\x33\xfd\x42\x23\xf4\x2b\xfd\x46\xbf\xd3\x28\xfd\x41\x9b\xe9\x4f\xda\x42\x7f\xd1\xdf\xf4\x0f\x83\x15\x6b\x26\x66\x36\x6c\xb1\xcd\x0e\xfb\x78\x02\x4f\xe4\x08\x9e\xc4\x3b\xf0\x64\x9e\xc2\x3b\xf2\x4e\xbc\x33\x47\xf2\x2e\xbc\x2b\xef\xc6\x51\xbc\x3b\xef\xc1\x7b\x72\x34\x4f\xe5\xbd\x78\x6f\x8e\xe1\x7d\x78\x1a\xef\xcb\xb1\xbc\x1f\xef\xcf\x07\x70\x1c\x4f\xe7\x19\x7c\x20\xc7\xf3\x4c\x9e\xc5\xb3\x39\x81\xfd\x1c\x60\x97\x3d\x0e\x72\x22\x27\x71\x32\xa7\xf0\x41\x7c\x30\xa7\xf2\x21\x7c\x28\x1f\xc6\x73\x38\x8d\xd3\x39\x83\x33\x39\xc4\x73\xf9\x70\xce\xe2\x79\x7c\x04\x1f\xc9\xd9\x3c\x9f\x17\xf0\x42\xce\xe1\xa3\x78\x11\x2f\xe6\x5c\x5e\xc2\x47\xf3\x31\x9c\xc7\xc7\xf2\x71\x7c\x3c\xe7\xf3\x09\x7c\x22\x9f\xc4\x05\x5c\xc8\x4b\x79\x19\x17\x71\x31\x9f\xcc\xcb\xb9\x84\x4b\xf9\x14\x5e\xc1\x65\xbc\x92\xcb\xb9\x82\x2b\xf9\x54\x5e\xc5\xab\xb9\x8a\xd7\xf0\x69\x7c\x3a\x57\xf3\x19\x7c\x26\x9f\xc5\x35\x7c\x36\x9f\xc3\xe7\x72\x2d\x9f\xc7\xe7\xf3\x05\xbc\x96\x2f\xe4\x8b\xf8\x62\xae\xe3\x4b\xf8\x52\xbe\x8c\xeb\xf9\x72\xbe\x82\xaf\xe4\x75\x7c\x15\x5f\xcd\xd7\x70\x03\x5f\xcb\xd7\xf1\xf5\xbc\x9e\x6f\xe0\x1b\xf9\x26\x6e\xe4\x9b\xf9\x16\xbe\x95\x9b\xf8\x36\xbe\x9d\xef\xe0\x66\xbe\x93\xef\xe2\xbb\xb9\x85\xef\xe1\x7b\xf9\x3e\x6e\xe5\xfb\xf9\x01\x7e\x90\xdb\xf8\x21\x7e\x98\x1f\xe1\x76\x7e\x94\x1f\xe3\xc7\x79\x03\x3f\xc1\x4f\xf2\x53\xdc\xc1\x4f\xf3\x33\xfc\x2c\x77\xf2\x73\xfc\x3c\xbf\xc0\x5d\xfc\x22\xbf\xc4\x2f\x73\x37\xbf\xc2\xaf\xf2\x6b\xdc\xc3\xaf\xf3\x1b\xfc\x26\xf7\xf2\x5b\xfc\x36\xbf\xc3\x7d\xfc\x2e\xbf\xc7\xef\xf3\x46\xfe\x80\x3f\xe4\x8f\xb8\x9f\x3f\xe6\x4f\xf8\x53\x1e\xe0\xcf\xf8\x73\xfe\x82\x07\xf9\x4b\xfe\x8a\xbf\xe6\x4d\xfc\x0d\x7f\xcb\xdf\xf1\x10\x7f\xcf\x3f\xf0\x8f\x3c\xcc\x3f\xf1\xcf\xfc\x0b\x8f\xf0\xaf\xfc\x1b\xff\xce\xa3\xfc\x07\x6f\xe6\x3f\x79\x0b\xff\xc5\x7f\xf3\x3f\x06\x46\x19\x6d\xc8\xb0\x31\xc6\x32\xb6\x71\x8c\xcf\x4c\x30\x13\x4d\x84\x99\x64\x76\x30\x93\xcd\x14\xb3\xa3\xd9\xc9\xec\x6c\x22\xcd\x2e\x66\x57\xb3\x9b\x89\x32\xbb\x9b\x3d\xcc\x9e\x26\xda\x4c\x35\x7b\x99\xbd\x4d\x8c\xd9\xc7\x4c\x33\xfb\x9a\x58\xb3\x9f\xd9\xdf\x1c\x60\xe2\xcc\x74\x33\xc3\x1c\x68\xe2\xcd\x4c\x33\xcb\xcc\x36\x09\xc6\x6f\x02\xc6\x35\x9e\x09\x9a\x44\x93\x64\x92\x4d\x8a\x39\xc8\x1c\x6c\x52\xcd\x21\xe6\x50\x73\x98\x99\x63\xd2\x4c\xba\xc9\x30\x99\x26\x64\xe6\x9a\xc3\x4d\x96\x99\x67\x8e\x30\x47\x9a\x6c\x33\xdf\x2c\x30\x0b\x4d\x8e\x39\xca\x2c\x32\x8b\x4d\xae\x59\x62\x8e\x36\xc7\x98\x3c\x73\xac\x39\xce\x1c\x6f\xf2\xcd\x09\xe6\x44\x73\x92\x29\x30\x85\x66\xa9\x59\x66\x8a\x4c\xb1\x39\xd9\x2c\x37\x25\xa6\xd4\x9c\x62\x56\x98\x32\xb3\xd2\x94\x9b\x0a\x53\x69\x4e\x35\xab\xcc\x6a\x53\x65\xd6\x98\xd3\xcc\xe9\xa6\xda\x9c\x61\xce\x34\x67\x99\x1a\x73\xb6\x39\xc7\x9c\x6b\x6a\xcd\x79\xe6\x7c\x73\x81\x59\x6b\x2e\x34\x17\x99\x8b\x4d\x9d\xb9\xc4\x5c\x6a\x2e\x33\xf5\xe6\x72\x73\x85\xb9\xd2\xac\x33\x57\x99\xab\xcd\x35\xa6\xc1\x5c\x6b\xae\x33\xd7\x9b\xf5\xe6\x06\x73\xa3\xb9\xc9\x34\x9a\x9b\xcd\x2d\xe6\x56\xd3\x64\x6e\x33\xb7\x9b\x3b\x4c\xb3\xb9\xd3\xdc\x65\xee\x36\x2d\xe6\x1e\x73\xaf\xb9\xcf\xb4\x9a\xfb\xcd\x03\xe6\x41\xd3\x66\x1e\x32\x0f\x9b\x47\x4c\xbb\x79\xd4\x3c\x66\x1e\x37\x1b\xcc\x13\xe6\x49\xf3\x94\xe9\x30\x4f\x9b\x67\xcc\xb3\xa6\xd3\x3c\x67\x9e\x37\x2f\x98\x2e\xf3\xa2\x79\xc9\xbc\x6c\xba\xcd\x2b\xe6\x55\xf3\x9a\xe9\x31\xaf\x9b\x37\xcc\x9b\xa6\xd7\xbc\x65\xde\x36\xef\x98\x3e\xf3\xae\x79\xcf\xbc\x6f\x36\x9a\x0f\xcc\x87\xe6\x23\xd3\x6f\x3e\x36\x9f\x98\x4f\xcd\x80\xf9\xcc\x7c\x6e\xbe\x30\x83\xe6\x4b\xf3\x95\xf9\xda\x6c\x32\xdf\x98\x6f\xcd\x77\x66\xc8\x7c\x6f\x7e\x30\x3f\x9a\x61\xf3\x93\xf9\xd9\xfc\x62\x46\xcc\xaf\xe6\x37\xf3\xbb\x19\x35\x7f\x98\xcd\xe6\x4f\xb3\xc5\xfc\x65\xfe\x36\xff\x58\xb0\x94\xa5\x2d\xb2\xd8\x32\x96\x65\xd9\x96\x63\xf9\xac\x09\xd6\x44\x2b\xc2\x9a\x64\xed\x60\x4d\xb6\xa6\x58\x3b\x5a\x3b\x59\x3b\x5b\x91\xd6\x2e\xd6\xae\xd6\x6e\x56\x94\xb5\xbb\xb5\x87\xb5\xa7\x15\x6d\x4d\xb5\xf6\xb2\xf6\xb6\x62\xac\x7d\xac\x69\xd6\xbe\x56\xac\xb5\x9f\xb5\xbf\x75\x80\x15\x67\x4d\xb7\x66\x58\x07\x5a\xf1\xd6\x4c\x6b\x96\x35\xdb\x4a\xb0\xfc\x56\xc0\x72\x2d\xcf\x0a\x5a\x89\x56\x92\x95\x6c\xa5\x58\x07\x59\x07\x5b\xa9\xd6\x21\xd6\xa1\xd6\x61\xd6\x1c\x2b\xcd\x4a\xb7\x32\xac\x4c\x2b\x64\xcd\xb5\x0e\xb7\xb2\xac\x79\xd6\x11\xd6\x91\x56\xb6\x35\xdf\x5a\x60\x2d\xb4\x72\xac\xa3\xac\x45\xd6\x62\x2b\xd7\x5a\x62\x1d\x6d\x1d\x63\xe5\x59\xc7\x5a\xc7\x59\xc7\x5b\xf9\xd6\x09\xd6\x89\xd6\x49\x56\x81\x55\x68\x2d\xb5\x96\x59\x45\x56\xb1\x75\xb2\xb5\xdc\x2a\xb1\x4a\xad\x53\xac\x15\x56\x99\xb5\xd2\x2a\xb7\x2a\xac\x4a\xeb\x54\x6b\x95\xb5\xda\xaa\xb2\xd6\x58\xa7\x59\xa7\x5b\xd5\xd6\x19\xd6\x99\xd6\x59\x56\x8d\x75\xb6\x75\x8e\x75\xae\x55\x6b\x9d\x67\x9d\x6f\x5d\x60\xad\xb5\x2e\xb4\x2e\xb2\x2e\xb6\xea\xac\x4b\xac\x4b\xad\xcb\xac\x7a\xeb\x72\xeb\x0a\xeb\x4a\x6b\x9d\x75\x95\x75\xb5\x75\x8d\xd5\x60\x5d\x6b\x5d\x67\x5d\x6f\xad\xb7\x6e\xb0\x6e\xb4\x6e\xb2\x1a\xad\x9b\xad\x5b\xac\x5b\xad\x26\xeb\x36\xeb\x76\xeb\x0e\xab\xd9\xba\xd3\xba\xcb\xba\xdb\x6a\xb1\xee\xb1\xee\xb5\xee\xb3\x5a\xad\xfb\xad\x07\xac\x07\xad\x36\xeb\x21\xeb\x61\xeb\x11\xab\xdd\x7a\xd4\x7a\xcc\x7a\xdc\xda\x60\x3d\x61\x3d\x69\x3d\x65\x75\x58\x4f\x5b\xcf\x58\xcf\x5a\x9d\xd6\x73\xd6\xf3\xd6\x0b\x56\x97\xf5\xa2\xf5\x92\xf5\xb2\xd5\x6d\xbd\x62\xbd\x6a\xbd\x66\xf5\x58\xaf\x5b\x6f\x58\x6f\x5a\xbd\xd6\x5b\xd6\xdb\xd6\x3b\x56\x9f\xf5\xae\xf5\x9e\xf5\xbe\xb5\xd1\xfa\xc0\xfa\xd0\xfa\xc8\xea\xb7\x3e\xb6\x3e\xb1\x3e\xb5\x06\xac\xcf\xac\xcf\xad\x2f\xac\x41\xeb\x4b\xeb\x2b\xeb\x6b\x6b\x93\xf5\x8d\xf5\xad\xf5\x9d\x35\x64\x7d\x6f\xfd\x60\xfd\x68\x0d\x5b\x3f\x59\x3f\x5b\xbf\x58\x23\xd6\xaf\xd6\x6f\xd6\xef\xd6\xa8\xf5\x87\xb5\xd9\xfa\xd3\xda\x62\xfd\x65\xfd\x6d\xfd\x63\xc3\x56\xb6\xb6\xc9\x66\xdb\xd8\x96\x6d\xdb\x8e\xed\xb3\x27\xd8\x13\xed\x08\x7b\x92\xbd\x83\x3d\xd9\x9e\x62\xef\x68\xef\x64\xef\x6c\x47\xda\xbb\xd8\xbb\xda\xbb\xd9\x51\xf6\xee\xf6\x1e\xf6\x9e\x76\xb4\x3d\xd5\xde\xcb\xde\xdb\x8e\xb1\xf7\xb1\xa7\xd9\xfb\xda\xb1\xf6\x7e\xf6\xfe\xf6\x01\x76\x9c\x3d\xdd\x9e\x61\x1f\x68\xc7\xdb\x33\xed\x59\xf6\x6c\x3b\xc1\xf6\xdb\x01\xdb\xb5\x3d\x3b\x68\x27\xda\x49\x76\xb2\x9d\x62\x1f\x64\x1f\x6c\xa7\xda\x87\xd8\x87\xda\x87\xd9\x73\xec\x34\x3b\xdd\xce\xb0\x33\xed\x90\x3d\xd7\x3e\xdc\xce\xb2\xe7\xd9\x47\xd8\x47\xda\xd9\xf6\x7c\x7b\x81\xbd\xd0\xce\xb1\x8f\xb2\x17\xd9\x8b\xed\x5c\x7b\x89\x7d\xb4\x7d\x8c\x9d\x67\x1f\x6b\x1f\x67\x1f\x6f\xe7\xdb\x27\xd8\x27\xda\x27\xd9\x05\x76\xa1\xbd\xd4\x5e\x66\x17\xd9\xc5\xf6\xc9\xf6\x72\xbb\xc4\x2e\xb5\x4f\xb1\x57\xd8\x65\xf6\x4a\xbb\xdc\xae\xb0\x2b\xed\x53\xed\x55\xf6\x6a\xbb\xca\x5e\x63\x9f\x66\x9f\x6e\x57\xdb\x67\xd8\x67\xda\x67\xd9\x35\xf6\xd9\xf6\x39\xf6\xb9\x76\xad\x7d\x9e\x7d\xbe\x7d\x81\xbd\xd6\xbe\xd0\xbe\xc8\xbe\xd8\xae\xb3\x2f\xb1\x2f\xb5\x2f\xb3\xeb\xed\xcb\xed\x2b\xec\x2b\xed\x75\xf6\x55\xf6\xd5\xf6\x35\x76\x83\x7d\xad\x7d\x9d\x7d\xbd\xbd\xde\xbe\xc1\xbe\xd1\xbe\xc9\x6e\xb4\x6f\xb6\x6f\xb1\x6f\xb5\x9b\xec\xdb\xec\xdb\xed\x3b\xec\x66\xfb\x4e\xfb\x2e\xfb\x6e\xbb\xc5\xbe\xc7\xbe\xd7\xbe\xcf\x6e\xb5\xef\xb7\x1f\xb0\x1f\xb4\xdb\xec\x87\xec\x87\xed\x47\xec\x76\xfb\x51\xfb\x31\xfb\x71\x7b\x83\xfd\x84\xfd\xa4\xfd\x94\xdd\x61\x3f\x6d\x3f\x63\x3f\x8b\x87\xf1\x88\xdd\x69\x3f\x67\x3f\x8f\xc7\xf0\x38\xba\xec\x17\xd0\x8e\x47\xf1\xa2\xdd\x85\xf3\xf1\x3c\x2e\xc6\x7d\xf6\x8b\xf6\x4b\xf6\xcb\x76\xb7\xfd\x8a\xfd\x2a\x5e\xb2\x5f\xb3\x7b\xec\xd7\xf1\x0c\x9e\xb5\xdf\xb0\xdf\x44\x87\xdd\x6b\xbf\x65\xbf\x6d\xbf\x63\xf7\xd9\xef\xda\xef\xd9\xef\xdb\x1b\xed\x0f\xec\x0f\xed\x8f\xec\x7e\xfb\x63\xfb\x13\xfb\x53\x7b\xc0\xfe\xcc\xfe\xdc\xfe\xc2\x1e\xb4\xbf\xb4\xbf\xb2\xbf\xc6\xef\xf6\x26\xfb\x1b\xfb\x5b\xfb\x3b\x7b\xc8\xfe\xde\xfe\xc1\xfe\xd1\x1e\xb6\x7f\xb2\x7f\xb6\x7f\xb1\x47\xec\x5f\xed\xdf\xec\xdf\xed\x51\xfb\x0f\x7b\xb3\xfd\xa7\xbd\xc5\xfe\xcb\xfe\xdb\xfe\x07\xf5\x0e\x1c\xe5\x68\x87\x1c\x76\x8c\x63\x39\xb6\xe3\x38\x3e\x67\x82\x33\xd1\x89\x70\x26\x39\x3b\x38\x93\x9d\x29\xce\x8e\x58\xef\xec\x84\x1b\x71\x03\x7e\x74\x76\x76\x22\x71\x27\xae\x76\x76\x71\x76\x45\x23\xee\xc6\x95\xce\x6e\x68\xc0\xb5\x4e\x94\xb3\xbb\xb3\x87\xb3\xa7\x13\xed\x4c\x75\xf6\x72\xf6\x76\x62\x9c\x7d\x9c\x69\xce\xbe\x4e\xac\xb3\x9f\xb3\xbf\x73\x80\x13\xe7\x4c\x77\x66\x38\x07\x3a\xf1\xce\x4c\x67\x96\x33\xdb\x49\x70\xfc\x4e\xc0\x71\x1d\xcf\x09\x3a\x89\x4e\x92\x93\xec\xa4\x38\x07\x39\x07\x3b\xa9\xce\x21\xce\xa1\xce\x61\xce\x1c\x27\xcd\x49\x77\x32\x9c\x4c\x27\xe4\xcc\x75\x0e\x77\xb2\x9c\x79\xce\x11\xce\x91\x4e\xb6\x33\xdf\x59\xe0\x2c\x74\x72\x9c\xa3\x9c\x45\xce\x62\x27\x17\x4f\x38\x4b\x9c\xa3\x9d\x63\x9c\x3c\xe7\x58\xe7\x38\xe7\x78\x27\xdf\x39\xc1\x39\xd1\x39\xc9\x29\x70\x0a\x9d\xa5\xce\x32\xa7\xc8\x29\x76\x4e\x76\x96\x3b\x25\x4e\xa9\x73\x8a\xb3\xc2\x29\x73\x56\x3a\xe5\x4e\x85\x53\xe9\x9c\xea\xac\x72\x56\x3b\x55\xce\x1a\xe7\x34\xe7\x74\xa7\xda\x39\xc3\x39\xd3\x39\xcb\xa9\x71\xce\x76\xce\x71\xce\x75\x6a\x9d\xf3\x9c\xf3\x9d\x0b\x9c\xb5\xce\x85\xce\x45\xce\xc5\x4e\x9d\x73\x89\x73\xa9\x73\x99\x53\xef\x5c\xee\x5c\xe1\x5c\xe9\xac\x73\xae\x72\xae\x76\xae\x71\x1a\x9c\x6b\x9d\xeb\x9c\xeb\x9d\xf5\xce\x0d\xce\x8d\xce\x4d\x4e\xa3\x73\xb3\x73\x8b\x73\xab\xd3\xe4\xdc\xe6\xdc\xee\xdc\xe1\x34\x3b\x77\x3a\x77\x39\x77\x3b\x2d\xce\x3d\xce\xbd\xce\x7d\x4e\xab\x73\xbf\xf3\x80\xf3\xa0\xd3\xe6\x3c\xe4\x3c\xec\x3c\xe2\xb4\x3b\x8f\x3a\x8f\x39\x8f\x3b\x1b\x9c\x27\x9c\x27\x9d\xa7\x9c\x0e\xe7\x69\xe7\x19\xe7\x59\xa7\xd3\x79\xce\x79\xde\x79\xc1\xe9\x72\x5e\x74\x5e\x72\x5e\x76\xba\x9d\x57\x9c\x57\x9d\xd7\x9c\x1e\xe7\x75\xe7\x0d\xe7\x4d\xa7\xd7\x79\xcb\x79\xdb\x79\xc7\xe9\x73\xde\x75\xde\x73\xde\x77\x36\x3a\x1f\x38\x1f\x3a\x1f\x39\xfd\xce\xc7\xce\x27\xce\xa7\xce\x80\xf3\x99\xf3\xb9\xf3\x85\x33\xe8\x7c\xe9\x7c\xe5\x7c\xed\x6c\x72\xbe\x71\xbe\x75\xbe\x73\x86\x9c\xef\x9d\x1f\x9c\x1f\x9d\x61\xe7\x27\xe7\x67\xe7\x17\x67\xc4\xf9\xd5\xf9\xcd\xf9\xdd\x19\x75\xfe\x70\x36\x3b\x7f\x3a\x5b\x9c\xbf\x9c\xbf\x9d\x7f\x7c\xf0\x29\x9f\xf6\x91\x8f\x7d\xc6\x67\xf9\x6c\x9f\xe3\xf3\xf9\x26\xf8\x26\xfa\x22\x7c\x93\x7c\x3b\xf8\x26\xfb\xa6\xf8\x76\xf4\xed\xe4\xdb\xd9\x17\xe9\xdb\xc5\xb7\xab\x6f\x37\x5f\x94\x6f\x77\xdf\x1e\xbe\x3d\x7d\xd1\xbe\xa9\xbe\xbd\x7c\x7b\xfb\x62\x7c\xfb\xf8\xa6\xf9\xf6\xf5\xc5\xfa\xf6\xf3\xed\xef\x3b\xc0\x17\xe7\x9b\xee\x9b\xe1\x3b\xd0\x17\xef\x9b\xe9\x9b\xe5\x9b\xed\x4b\xf0\xf9\x7d\x01\x9f\xeb\xf3\x7c\x41\x5f\xa2\x2f\xc9\x97\xec\x4b\xf1\x1d\xe4\x3b\xd8\x97\xea\x3b\xc4\x77\xa8\xef\x30\xdf\x1c\x5f\x9a\x2f\xdd\x97\xe1\xcb\xf4\x85\x7c\x73\x7d\x87\xfb\xb2\x7c\xf3\x7c\x47\xf8\x8e\xf4\x65\xfb\xe6\xfb\x16\xf8\x16\xfa\x72\x7c\x47\xf9\x16\xf9\x16\xfb\x72\x7d\x4b\x7c\x47\xfb\x8e\xf1\xe5\xf9\x8e\xf5\x1d\xe7\x3b\xde\x97\xef\x3b\xc1\x77\xa2\xef\x24\x5f\x81\xaf\xd0\xb7\xd4\xb7\xcc\x57\xe4\x2b\xf6\x9d\xec\x5b\xee\x2b\xf1\x95\xfa\x4e\xf1\xad\xf0\x95\xf9\x56\xfa\xca\x7d\x15\xbe\x4a\xdf\xa9\xbe\x55\xbe\xd5\xbe\x2a\xdf\x1a\xdf\x69\xd6\xf2\xb2\x33\x2a\x4b\xfc\xf6\x9a\xf2\xd2\x84\x84\x84\xcc\xf1\x98\x96\x20\x51\x8e\xd3\x03\x12\x5d\x89\x41\x89\x29\x76\xda\xca\xc2\x65\xab\x2a\xca\xed\xc2\xf1\x68\xa5\x2d\x5d\x55\x7c\x5a\xb1\x55\x38\x16\xec\xb4\x8a\xe5\x15\xe5\xc5\x2b\xec\xc2\xf1\x38\x31\x63\x59\xe9\xaa\x65\x6b\x56\x9e\x5c\x56\x5c\x3d\x71\xd9\xbf\xed\x09\x19\x45\x15\x55\x85\xcb\x96\x15\x97\x57\x4d\x58\x16\x6e\x5a\x99\xcb\x0a\xb7\x76\x59\x34\x1e\x32\x97\xad\xaa\x28\xac\xb2\x43\x02\x2c\x16\x60\x68\x1c\x58\x3c\x16\x26\x84\xfe\xed\xa8\x38\xdc\xb4\x43\x32\x8c\xe2\xf1\x68\x85\xc6\x7b\x2c\x1e\x0b\x13\x0f\xdf\x6e\x50\xcb\xb7\x1b\xd4\xe1\xff\xf6\xb5\x3c\xdc\x8c\x38\x7c\x59\xc5\xca\x95\x85\x72\xb0\x7c\xbb\x83\x89\x59\xdb\xf5\x53\xf2\x6f\x9b\xb3\x96\x16\xae\xe2\x92\xa5\x85\xab\xac\x79\x55\xa5\x65\x45\xc5\x56\xe9\x58\xb0\xe7\xc9\x4c\x4a\x65\x26\xf3\xc6\x67\x52\x3a\xbe\x74\xf3\x64\xcc\xa5\xe3\x51\xcf\x3b\x42\x97\x9e\x32\xf1\x88\xed\x18\xa7\xfc\xdb\x8e\x38\x72\xfb\x51\xad\xf8\x8f\x83\xe5\xab\x8a\x8b\xcb\xcb\x0a\xcb\x8b\x4a\x97\x59\xd9\x85\xcb\xd6\x54\x15\x5b\x65\x63\x21\x22\x7b\xfb\xcf\x95\x6d\x77\x60\x65\x8f\x2f\x50\xd9\x58\xe0\xec\xa2\x8a\x2a\x2e\x2b\xaa\xa8\xb2\x16\x8c\x9f\x5f\x3e\x7e\xfe\x82\xed\xcf\x2f\xdf\xfe\xfc\x05\xe3\xe7\x97\x8f\x2f\x70\x79\x61\x65\xc5\xea\xaa\x55\x15\x95\x25\xc5\x14\x2a\x5f\x4e\xc5\xe5\xcb\xed\x85\x32\xf9\x0a\x99\xfc\xc2\xf1\xc9\x57\x8c\x85\x49\x0b\x4b\xd6\x94\x2f\x2f\x5c\xb5\x66\x65\x59\xe1\x9a\xaa\x49\x15\xdb\x1f\x59\x8b\xc6\xc7\xb0\x6a\x7c\x0c\x8b\xb6\x1f\xc3\xaa\xed\xc7\xb0\x68\x7c\x0c\xab\xc6\xc3\xe2\xf1\xb3\x56\x8f\x85\x89\x8b\xb7\x5b\xc6\xd5\xdb\x2d\x63\xee\xf6\xbd\x55\x6d\xdf\x5b\xee\x78\x37\x55\xe3\x2b\x92\xbb\xf5\x92\x56\x6d\xbd\xa4\x4b\xc6\x2f\xe9\x9a\xf1\x4b\xba\x44\x66\xb5\x46\x66\xb5\x64\x7c\x56\x6b\xc6\x82\x59\xb2\xaa\xb4\x7c\xb9\x59\xb3\xf5\xf7\xa4\x25\xff\x31\xc3\x35\xdb\x1f\xd9\x4b\xe4\xd2\xaf\x91\x6f\xcd\x31\xdb\x8d\xf6\xf4\xed\xda\xc7\x6e\xd7\x3e\xe3\xdf\xb6\x75\xdc\xf8\x5c\xcf\x1c\x0b\x13\x8e\xfb\xf7\x36\x3e\x33\xdc\x34\x65\x15\xe5\xcb\x57\x8f\x7d\x8b\xfd\xc9\x09\x12\xfd\x12\x03\x12\x5d\x89\x9e\xc4\xa0\xc4\x44\x89\x49\x12\x93\x25\xa6\x48\x4c\x93\x98\x2e\x31\x43\x62\xa6\xc4\x90\xc4\xb9\xe3\x31\x45\xf8\x29\xc2\x4f\x11\x6e\x8a\x70\x53\x84\x9b\x22\xdc\x14\xe1\xa6\x08\x37\x45\xb8\x29\xc2\x4d\x11\x6e\x8a\x70\x53\x84\x9b\x22\xdc\x94\xb9\x66\x61\x49\xc5\xaa\x72\x53\xb1\xf5\xf7\xf8\x6b\x69\x32\xe7\x34\x61\xa7\x09\x3b\x4d\xd8\x69\xc2\x4e\x13\x76\x9a\xb0\xd3\x84\x9d\x26\xec\x34\x61\xa7\x09\x5b\x9e\xa0\xfe\xb4\x90\x59\x32\xc6\x5c\xf3\x2f\x33\x5d\xe6\x2b\x4f\x57\xbf\x3c\x5d\xfd\xe9\xc2\x96\xa7\xac\x3f\x5d\xd8\xe9\xc2\x4e\x17\x76\xba\xb0\xd3\x85\x9d\x2e\xec\x74\x61\xa7\x0b\x3b\x5d\xe6\x9d\x2e\xeb\x9d\x21\xeb\x9d\x21\xfc\x0c\xe1\x67\x08\x3f\x43\xf8\x19\xc2\xcf\x10\x7e\x86\xf0\x33\x84\x9f\x21\xfc\x0c\xe1\x67\x08\x3f\x43\xf8\x19\xc2\xcf\x10\x7e\x86\xf0\x33\x85\x9f\x29\xfc\x4c\xe1\x67\x0a\x3f\x53\xf8\x99\xc2\xcf\x14\x7e\xa6\xf0\x33\x85\x9f\x29\xfc\x4c\xe1\x67\x0a\x3f\x53\xf8\x99\xc2\xcf\x14\x7e\xa6\xf0\x43\xc2\x0f\x09\x3f\x24\xfc\x90\xf0\x43\xc2\x0f\x05\xad\xc3\xc7\xbf\xf5\xcb\xc7\x82\xbc\x2a\xf4\x90\xd0\x43\x42\x0f\x09\x3d\x24\xf4\x90\xd0\x43\x42\x0f\x09\x7d\xae\xd0\xe7\x0a\x7d\xae\xd0\xe7\x0a\x7d\xae\xd0\xe7\xca\xec\xe7\xca\xec\xe7\xca\xec\xe7\x0a\x7f\x6e\xca\x84\xb4\xad\x4f\x92\xf1\x2f\x79\x61\xb8\x69\xa7\x85\xc6\x63\x61\xf1\xf8\xb3\x6e\xe1\xea\xb2\xc2\xd5\x25\xe3\xed\x8a\x7f\xdb\x63\xbd\x04\x12\x12\x24\xfa\x25\x06\x24\xba\x12\x3d\x89\x41\x89\x89\x12\x93\x24\x26\x4b\x4c\x91\x98\x26\x31\x5d\x62\x86\xc4\x4c\x89\x21\x89\xe3\xab\x11\xf0\x0b\xdf\x2f\x7c\xbf\xf0\xfd\xc2\xf7\x0b\xdf\x2f\x7c\xbf\xf0\xfd\x49\x11\x8b\xb7\x7f\x56\xaf\xde\xee\x40\x3e\x21\x23\xf1\xcb\x48\xfc\x32\x12\xbf\x8c\xc4\x2f\x23\xf1\xcb\x48\x02\x32\x92\x80\x8c\x24\x20\x23\x09\xc8\x48\x02\x32\x92\x80\x8c\x24\x20\x23\x09\xc8\x4a\x04\x64\x25\x02\xb2\x12\x01\xe1\x07\x84\x1f\x10\x7e\x40\xf8\x01\xe1\x07\x84\xef\x0a\xdf\x15\xbe\x2b\x7c\x57\xf8\xae\xf0\x5d\xe1\xbb\xc2\x77\x85\xef\x0a\xdf\x15\xbe\x2b\x7c\x57\xf8\xae\xf0\x5d\xe1\xbb\xc2\x77\x85\xef\x09\xdf\x13\xbe\x27\x7c\x4f\xf8\x9e\xf0\x3d\xe1\x7b\xc2\xf7\x84\xef\x09\xdf\x13\xbe\x27\x7c\x4f\xf8\x9e\xf0\x3d\xe1\x7b\xc2\xf7\x84\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\x9f\x28\xfc\x44\xe1\x27\x0a\x3f\x51\xf8\x89\xc2\x4f\x14\x7e\xa2\xf0\x13\x85\x9f\x28\xfc\x44\xe1\x27\x0a\x3f\x51\xf8\x89\xc2\x4f\x14\x7e\xa2\xf0\x13\x85\x9f\x24\xfc\x24\xe1\x27\x09\x3f\x49\xf8\x49\xc2\x4f\x12\x7e\x92\xf0\x93\x84\x9f\x24\xfc\x24\xe1\x27\x09\x3f\x49\xf8\x49\xc2\x4f\x12\x7e\x92\xf0\x93\x84\x2f\x59\x40\x40\xb2\x80\x80\x64\x01\x01\xc9\x02\x02\x92\x05\x04\x24\x0b\x08\x48\x16\x10\x90\x2c\x20\x20\x59\x40\x40\xb2\x80\x80\x64\x01\x01\xc9\x02\x02\x92\x05\x04\x24\x0b\x08\x48\x16\x10\x90\x2c\x20\x20\x59\x40\x40\xb2\x80\x40\x8a\xf0\x25\x1b\x08\x48\x36\x10\x90\x6c\x20\x20\xd9\x40\x40\xb2\x81\x80\x64\x03\x01\xc9\x06\x02\x92\x0d\x04\x24\x1b\x08\x48\x36\x10\x90\x6c\x20\x20\xd9\x40\x20\x45\xf8\x52\xf3\x04\xd2\x84\x2f\x19\x41\x40\x32\x82\x80\x64\x04\x01\xc9\x08\x02\x92\x11\x04\x24\x23\x08\x48\x46\x10\x90\x8c\x20\x20\x19\x41\x40\x32\x82\x80\x64\x04\x01\xc9\x08\x02\x69\xc2\x4f\x13\x7e\xba\xf0\x25\x2b\x08\x48\x56\x10\x90\xac\x20\x20\x59\x41\x40\xb2\x82\x80\x64\x05\x01\xc9\x0a\x02\x92\x15\x04\x24\x2b\x08\x48\x56\x10\x48\x4f\xf7\x15\x9e\x5c\x5a\x1a\x4c\x4a\x09\xa4\x8c\xb5\x12\xbd\x94\x6d\xcf\x0c\xc9\x0c\x02\x92\x19\x04\x24\x33\x08\x48\x66\x10\x90\xcc\x20\x20\x99\x41\x40\x32\x83\x80\x64\x06\x01\xc9\x04\x02\x92\x09\x04\x24\x13\x08\x48\x26\x10\x90\x4c\x20\x20\x99\x40\x40\x32\x81\x80\x64\x02\x01\xc9\x04\x02\x92\x09\x04\x24\x13\x08\x48\x26\x10\x90\x4c\x20\x20\x99\x40\x40\x32\x81\x80\x64\x02\x01\x31\x7b\x40\xcc\x1e\x10\xb3\x07\xc4\xec\x01\x31\x7b\x40\xcc\x1e\x10\xb3\x07\x42\xd2\x5f\x48\xfa\x0b\x49\x7f\xe2\xf6\x80\xb8\x3d\x20\x6e\x0f\x88\xdb\x03\xe2\xf6\x80\xb8\x3d\x20\x6e\x0f\x88\xdb\x03\xe2\xf6\x80\xb8\x3d\x20\x6e\x0f\x88\xdb\x03\xe2\xf6\x80\xb8\x3d\x20\x6e\x0f\x88\xdb\x03\xe2\xf6\xc0\x5c\xe1\xcf\x15\xfe\x5c\xe1\xcf\x15\xfe\x5c\xe1\xcf\x15\xfe\xdc\xb9\xbe\xe5\xab\x0a\x4f\x2b\x5e\x56\xb1\x72\xa9\x6f\xcc\xee\x5b\x5b\x63\xef\xb9\x09\x01\xdf\x58\x6d\xb2\xdd\x2b\x9e\xc4\xa0\xc4\x44\x89\x49\x12\x93\x27\x95\x54\x54\xac\x28\x5c\x5a\x71\xda\xf6\x67\xa5\x49\x4c\x97\x98\x21\x31\x53\x62\x48\xe2\xf8\x5a\xb8\x62\x76\x57\xcc\xee\x8a\xd9\x5d\x31\xbb\x2b\x66\x77\xc5\xec\xae\x98\xdd\xf5\xcb\x28\xfc\xc9\x12\x53\x24\x0a\x5f\x7c\xee\x8a\xcf\x5d\xf1\xb9\x2b\x3e\x77\xc5\xe7\xae\xf8\xdc\x15\x9f\xbb\x81\x40\x44\x51\x45\xd5\xd2\xe2\xb2\x8a\xd3\xff\x9d\x94\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xbe\xa0\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdb\x15\x69\xbb\x22\x65\x57\xa4\xec\x8a\x94\x5d\x91\xb2\x9b\x14\x32\x55\x15\xe5\x15\xab\x27\x15\x95\x16\xaf\x2a\x5e\x5d\xba\x7a\xec\x68\x42\x5a\x59\x65\x49\xe1\x58\xd3\x57\x58\x5e\x51\x55\x5c\x56\x5c\x5a\x18\x11\xaa\x5c\x5d\x5a\x56\x51\x3e\xf6\xb2\x13\xaa\x92\xf7\xe7\x55\x48\x2b\x62\xe1\xca\xd2\x65\xab\xe4\xfd\x88\x25\xdb\x7d\x78\xc2\xc2\x95\xc5\xcb\xc7\x3f\xb4\x63\x69\x45\x55\xe1\x7f\xb0\xcc\x18\x8b\xd3\x8b\xab\x0a\xcd\xe1\x85\x2b\x57\x16\xda\xc2\xe1\xe3\x8a\xab\x0a\x29\x54\x55\x68\x72\x4b\x8a\xab\x0a\x79\x2b\xc8\x1c\x59\x58\x59\x59\x68\x65\x17\xae\x5c\x5a\x54\xa8\xe7\xaf\xd1\x0b\xd6\xe8\xbc\x52\x5b\xc8\x3a\xa7\x94\x16\x95\x54\x98\xc5\xa5\xcb\x57\x16\x52\x6e\xe1\x1a\x5b\x46\x41\x39\x25\xa5\x94\x51\x52\x4a\x39\xab\x4b\x23\xe6\x6d\x37\x82\xc9\xf2\x81\x6d\xc7\x13\x0a\xc3\x13\x8f\x28\xde\x7e\xba\xc5\xdb\xa6\x5b\xba\x6d\xba\x91\x6b\xfe\xf3\xd4\xf1\xc9\x8c\x9d\xcf\x4b\xb7\x4e\x66\xf9\xd6\xc9\x98\xa2\xe2\xb2\xaa\x42\x5b\xfa\xe2\x33\xb7\x4e\x69\xeb\x9b\x55\x63\x53\xda\xda\x99\x59\x31\x36\xa5\xb2\xf1\x29\x95\xaf\xd1\xd5\xa5\x76\xc5\xf8\x7c\x68\x55\x49\x85\xb5\x7a\xeb\x64\xfc\x66\x2c\x50\x55\xe1\x1a\x5b\xb8\x54\x59\x52\x4a\xcb\x4a\x4a\xa9\x72\x75\xa9\xa9\xd8\xba\xc0\x11\xdb\xaf\xed\xe4\xff\x31\xbc\x88\x8a\xed\xaf\xce\x9a\xed\xaf\x4e\x45\xf8\xea\x8c\xdf\x13\x99\x09\xd6\xd8\xf0\xfc\x8e\xac\x8e\xdc\xcb\x22\x49\x37\xd3\xe3\xca\x92\x52\xbf\x35\x76\xde\xb6\xf7\xe4\xfe\x95\x52\xd9\x95\x52\xd9\x95\x52\xd9\x95\x52\xd9\x95\x52\xd9\x95\x52\xd9\x15\xa1\xba\x22\x54\x57\x84\xea\x8a\x50\x5d\x11\xaa\x2b\x42\x75\x45\xa8\xae\x08\xd5\x15\xa1\xba\x22\x54\x57\x84\xea\x8a\x50\x5d\x11\xaa\x2b\x42\x75\x45\xa8\xae\x08\xd5\x15\xa1\xba\x22\x54\x57\x84\xea\x8a\x50\x5d\x11\xaa\x2b\x42\x75\x45\xa8\xae\x08\xd5\x15\xa1\xba\x22\x54\x57\x84\xea\x8a\x50\x5d\x11\xaa\x2b\x42\x75\x45\xa8\xae\x08\xd5\x15\xa1\xba\x73\xc7\xf9\x5e\x42\xc2\x58\xca\xe4\x4f\x48\x08\xb8\xdb\x5a\x41\x7f\xb8\x15\x08\xb7\xfe\x7d\xd7\x0b\xb7\x82\xe1\x56\x62\xb8\x95\x14\x6e\x25\x87\x5b\x29\xdb\x5a\x89\x61\x9a\x3c\xaf\xbc\x84\xcc\xf0\x2b\xdb\x58\x7e\x2f\xdc\xaf\x3f\xdc\x9b\x3f\xdc\x9b\x3f\xdc\x5b\xe0\xdf\xb1\x87\x47\x1c\x08\x8f\x38\x10\x1e\x67\x20\xdc\x5f\x20\x3c\xce\x40\xb8\xe7\x40\xb8\xe7\x40\xb8\x67\x37\xdc\xb3\x1b\xee\xd9\x0d\xf7\xec\x86\xd7\xc2\x0d\x33\xdc\x30\xc3\x0d\x33\xdc\x30\xc3\x0d\x33\xdc\x30\xc3\x0b\x33\xbc\x30\xc3\x0b\x33\xbc\x30\xc3\x0b\x33\xfe\x5d\x17\x2f\xcc\xf0\xc2\x0c\x2f\xcc\xf0\xfe\x5d\xef\xf0\x19\x89\xe1\x33\x12\xc3\x67\x24\x86\xcf\x48\x0c\x9f\x91\x14\x1e\x55\x52\x78\x2c\x49\xe1\xb1\x24\x85\xc7\x92\x14\xee\x39\x29\xdc\x73\x52\xb8\xe7\xa4\x70\xcf\x49\xe1\x9e\x93\xc3\x3d\x27\x87\xe7\x9b\x1c\x66\x24\x87\x19\xc9\x61\x46\x72\x98\x91\x1c\x66\x24\x87\x19\xc9\x61\x46\x72\x98\x91\x12\x66\xa4\x84\x19\x29\x61\x46\x4a\x98\x91\x12\x66\xa4\x84\x19\x29\x61\x86\x14\x5c\x5e\xf0\xdf\xb5\xf8\xb7\xb7\x6d\x2c\x7f\xf8\x9b\xe3\x4f\xf0\x87\x5b\xe1\x7b\x38\xc1\x0d\xb7\xbc\x70\x2b\x18\x6e\x25\x86\x5b\x49\xe1\x56\x72\xb8\x95\x22\xfc\x6d\xdf\x0d\xbf\x3f\xcc\x92\x62\xd1\x13\xef\x7b\x89\x61\x76\xf8\x9e\xd8\xb6\xad\xec\x25\x6e\x8b\x41\x89\x89\x12\x65\x7e\xe2\x7e\x4f\xdc\xef\x89\xfb\x3d\x71\xbf\x27\xee\xf7\xc4\xfd\x9e\xb8\xdf\x13\xf7\x7b\x52\xd0\x7b\x49\xff\x8e\x21\x3c\x9b\xf0\xba\xfa\xc3\xf7\xe5\xb6\xed\x6d\x2f\x69\x5b\x94\x71\x48\x61\xef\x49\x61\xef\x49\x0e\xe1\x49\x0e\xe1\x49\x0e\xe1\x49\x0e\xe1\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x49\x61\xef\x25\xcf\x0d\x3f\xe1\xfe\xbd\xef\xa4\x2f\x29\xee\xbd\x6d\xd7\x6b\xdb\x35\x91\xe2\xde\xdb\xb6\x16\xdb\xee\xb5\xf0\x79\x32\x06\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\x29\xee\x3d\xd9\xf2\xf7\x64\xcb\xdf\x93\x2d\x7f\x4f\x0a\x7b\x4f\x0a\x7b\x4f\x0a\x7b\x4f\x0a\x7b\x4f\x0a\x7b\x4f\x0a\x7b\x4f\x0a\x7b\x4f\x0a\x7b\x4f\xb6\xfc\x3d\xd9\xf2\xf7\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\x24\x87\xf1\xa4\xd0\xf7\xa4\xd0\xf7\xa4\xd0\xf7\x24\x8f\xf1\x32\xb7\x7d\x4b\x92\xbd\x6d\xef\xc8\x08\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\x09\xca\x46\x7f\x50\x36\xfa\x83\xb2\xd1\x1f\x94\x8d\xfe\xa0\x6c\x0a\x04\x65\x53\x20\x28\x9b\x02\x41\xd9\x14\x08\xca\x46\x7f\x50\x9e\xbe\x41\xd9\x0e\x08\xca\x76\x40\x50\xb6\x03\x82\xb2\x1d\x10\x94\xed\x80\xa0\x6c\x07\x04\x65\x3b\x20\x28\xdb\x01\x41\xd9\x0e\x08\xca\x76\x40\x50\xb6\x03\x82\xb2\x1d\x10\x94\xed\x80\xa0\x6c\x07\x04\x65\x3b\x20\x28\xdb\x01\x41\xd9\x0e\x08\xca\x76\x40\x50\xb6\x03\x82\xb2\x1d\x10\x94\xed\x80\xa0\x6c\x07\x04\x65\x3b\x20\x28\xdb\x01\x41\xd9\xde\x0f\xca\xf6\x7e\x50\x76\x02\x82\xb2\x13\x10\x94\x9d\x80\xe0\xf8\x4e\x80\x3f\x73\x7c\xfd\xfc\x99\xe3\xeb\xe7\xcf\x1c\x5f\x3f\x7f\xe6\xf8\xfa\xf9\x33\xc7\xd7\xcf\x9f\x39\xbe\x7e\xfe\xcc\xf1\xf5\xf3\x67\x26\x6c\x3b\x3f\x59\x62\x8a\xc4\x34\x89\xe9\x12\x33\x24\x66\x4a\x0c\x49\x9c\x3b\x1e\xfd\xc2\xf7\x0b\xdf\x2f\x7c\xbf\xf0\xfd\xc2\xf7\x0b\xdf\x2f\x7c\xbf\xf0\xfd\xc2\xf7\x0b\xdf\x2f\x7c\xbf\xf0\xfd\xc2\xf7\x0b\xdf\x2f\x7c\xbf\xf0\x03\xc2\x0f\x08\x3f\x20\xfc\x80\xf0\x03\xc2\x0f\x08\x3f\x20\xfc\x6d\xeb\x17\x10\x7e\x40\xf8\x01\xe1\x07\x84\x1f\x10\x7e\x40\xf8\x01\xe1\x07\x84\xef\x0a\xdf\x15\xbe\x2b\x7c\x57\xf8\xae\xf0\x5d\xe1\xbb\xc2\x77\x85\xef\x0a\xdf\x15\xbe\x2b\x7c\x57\xf8\xae\xf0\x5d\xe1\xbb\xc2\x77\x85\xef\x09\xdf\x13\xbe\x27\x7c\x4f\xf8\x9e\xf0\x3d\xe1\x7b\xc2\xf7\x84\xef\x09\xdf\x13\xbe\x27\x7c\x4f\xf8\x9e\xf0\x3d\xe1\x7b\xc2\xf7\x84\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\x9f\x28\xfc\x44\xe1\x27\x0a\x3f\x51\xf8\x89\xc2\x4f\x14\x7e\xa2\xf0\x13\x85\x9f\x28\xfc\x44\xe1\x27\x0a\x3f\x51\xf8\x89\xc2\x4f\x14\x7e\xa2\xf0\x13\x85\x9f\x24\xfc\x24\xe1\x27\x09\x3f\x49\xf8\x49\xc2\x4f\x12\x7e\x92\xf0\x93\x84\x9f\x24\xfc\x24\xe1\x27\x09\x3f\x49\xf8\x49\xc2\x4f\x12\x7e\x92\xf0\x93\x84\x9f\x2c\xfc\x64\xe1\x27\x0b\x3f\x59\xf8\xc9\xc2\x4f\x16\x7e\xb2\xf0\x93\x85\x9f\x2c\xfc\x64\xe1\x27\x0b\x3f\x59\xf8\xc9\xc2\x4f\x16\x7e\xb2\xf0\x93\x85\x9f\x22\xfc\x14\xe1\xa7\x08\x3f\x45\xf8\x29\xc2\x4f\x11\x7e\x8a\xf0\x53\x84\x9f\x22\xfc\x14\xe1\xa7\x08\x3f\x45\xf8\x29\xc2\x4f\x11\x7e\x8a\xf0\x53\x84\x9f\x26\xfc\x34\xe1\xa7\x09\x3f\x4d\xf8\x69\xc2\x4f\x13\x7e\x9a\xf0\xd3\x84\x9f\x26\xfc\x34\xe1\xa7\x09\x3f\x4d\xf8\x69\xc2\x4f\x13\x7e\x9a\xf0\xd3\x84\x9f\x2e\xfc\x74\xe1\xa7\x0b\x3f\x5d\xf8\xe9\xc2\x4f\x17\x7e\xba\xf0\xd3\x85\x9f\x2e\xfc\x74\xe1\xa7\x0b\x3f\x5d\xf8\xe9\xc2\x4f\x17\x7e\xba\xf0\xd3\x85\x9f\x21\xfc\x0c\xe1\x67\x08\x3f\x43\xf8\x19\xc2\xcf\x10\x7e\x86\xf0\x33\x84\x9f\x21\xfc\x0c\xe1\x67\x08\x7f\xae\x70\xc6\x3d\xed\x0f\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\x26\x24\x9e\x09\x89\x67\x42\xe2\x99\x90\x78\xe6\xff\x63\xdc\xdc\x76\x1b\xb7\xae\x3e\xee\xc9\x78\xec\xf1\x1c\x72\x9c\x24\xdf\x07\x7c\x1f\xaa\x34\x6d\x7a\x70\x51\x50\x94\x44\x52\x97\xb6\xb4\xfe\x08\x90\x9b\x1e\x50\x64\x06\x28\x1a\xc8\x12\x6d\x0b\x91\x25\x47\x07\x4f\x72\xd7\x9b\x5e\xb6\x0f\xd1\x27\x70\x74\x55\xf4\x3d\xfa\x0a\x7d\x8d\x16\xd6\xfe\x6d\xb6\x26\xb6\xf6\x68\x2e\x66\xaf\xcd\xb5\xb9\xfe\x6b\x6f\x72\xf1\x47\xd2\xa2\xc1\x19\x83\x33\x06\x67\x0c\xce\x58\xae\x83\x2f\x37\x7f\xc3\x3b\x78\xed\x9a\x2f\xdd\x8f\xf8\x5e\x6f\x9a\xa3\x2f\xfd\x8b\xe3\xa3\xd7\xde\x72\xfb\xc1\x19\x83\x33\x06\x67\x0c\xce\x18\x9c\x31\x38\x63\x70\xc6\xe0\x8c\xc1\x19\x83\x33\x06\x67\x0c\xce\x18\x9c\x31\x38\x63\x70\xc6\xe0\x8c\xc1\x19\x83\x33\x06\x67\x0c\xce\x18\x9c\x31\x38\x63\x70\xc5\xe0\x89\xc1\x13\x83\x27\x06\x4f\x0c\x9e\x18\x3c\x31\x78\x62\xf0\xc4\xe0\x89\xc1\x13\x83\x27\x06\x4f\x0c\x9e\x18\x3c\xb1\x13\xaf\xcb\x3c\xe1\x89\xc1\x13\x83\x27\x06\x4f\x0c\x9e\x18\x3c\x31\x78\x62\xf0\xc4\xe0\x89\xc1\x13\x83\x27\x06\x4f\x0c\x9e\x18\x3c\x31\x78\x62\xf0\xc4\xe0\x89\xc1\x13\x83\x27\x06\x4f\x0c\x9e\x18\x3c\x31\x78\x62\xf0\xc4\xe0\x89\xc1\x13\x83\x27\xd6\x43\xbf\x87\x7e\x0f\xfd\x1e\xfa\x3d\xf4\xfb\xe8\xf7\xd1\xef\xa3\xdf\x47\xbf\x8f\x7e\x1f\xfd\x3e\xfa\x7d\xf4\xfb\xe8\xf7\xd1\xef\xa3\xdf\x47\xbf\x8f\x7e\x1f\xfd\x3e\xfa\x7d\xf4\x0d\x7d\x43\xdf\xd0\x37\xf4\x0d\x7d\x43\xdf\xd0\x37\xf4\x0d\x7d\x43\xdf\xd0\x37\xf4\x0d\x7d\x43\xdf\xd0\x37\xf4\x85\xbe\x9a\x07\xaf\x5c\xc1\x7d\xb7\x69\xd8\x8a\xba\x50\x17\xea\x42\x5d\xa8\xbb\xa7\xf1\xa6\xa0\xb6\xa0\xb6\xa0\xb6\xa0\xb6\xa0\xb6\xa0\xb6\xa0\xb6\xa0\xb6\xa0\xb6\x12\x1f\xef\x84\xf6\x94\xb6\x47\xdb\xa7\x35\x5a\x37\x1b\x41\x6d\x41\x6d\x41\x6d\x41\x6d\x41\x6d\x41\x6d\x41\x69\x41\x69\x41\x69\x41\x69\x41\x69\x41\x69\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\xa5\x5e\x8f\xf9\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x65\x41\x61\x41\x61\x41\x61\x41\x61\x41\x61\x41\x61\x41\x5d\x41\x5d\x41\x5d\x41\x5d\x41\x5d\x41\x5d\x41\x5d\x41\x5d\x41\x5b\x41\x59\x75\x7c\x5c\xf2\x87\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\x82\xaa\xe2\x69\x4d\x3c\xad\x89\xa7\x35\xf1\xb4\x26\x9e\xd6\xc4\xd3\x9a\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\x0a\xaf\xc7\x7c\xa1\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\xa0\xa8\x78\x5a\x13\x4f\x6b\x82\xaa\xe2\x69\x4d\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\xd0\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\x50\x55\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x54\xd0\x53\xd0\x53\xd0\x53\xd0\x53\xd0\x53\xd0\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x50\x53\x42\x4f\xe8\xc1\x49\xc1\x47\xc1\x47\xc1\x47\x79\x3e\x0a\x1d\xa1\x23\x74\x84\x8e\x7b\x0a\x4e\x13\xc7\xd1\x34\x71\x1c\x4d\x13\xc7\xd1\x34\x71\x1c\x4d\x13\xc7\xd1\x34\x71\x1c\x4d\x13\xc7\xd1\x34\x71\x1c\x4d\x13\xc7\xd1\x34\x71\x1c\x4d\x13\xc7\xd1\x34\x49\xdc\x8f\x20\xb3\x66\x96\xb5\x0f\xef\xac\x56\xd2\xdc\xb4\x69\xb7\x4b\x1f\xe5\xa6\x6f\x9b\x4f\xce\xc7\x17\xab\x79\x39\x1a\x2c\x2e\x37\x3b\x27\xfe\xd7\xee\x69\xd2\xcc\x9e\xaf\xa6\xa3\x72\xbe\x18\xce\xe6\xe5\xe8\x6c\xf2\xfc\x9b\xd5\x6c\x59\xce\xcb\x9b\x72\xbe\x28\x47\x8c\x91\x6b\x53\x52\x48\x7d\x0a\x1d\xfe\x60\x7c\x67\xb5\x2b\x8b\x09\xa5\x3a\xb8\x1a\x4f\x37\x5f\x2a\x95\xc3\xd9\x94\x58\xad\xf6\x51\xf9\xed\x70\x32\xb8\x1a\x9d\x4d\xd8\xc2\x82\x75\x7c\x8b\x5a\x86\x9a\xbb\x30\xa7\x89\xbb\x30\xa7\x89\xbb\x30\xa7\x49\xc6\xf8\x8c\xf1\x39\xd3\xcd\x59\x58\x9f\x47\xce\xc2\xe6\x2c\x6c\xce\xcc\x73\x16\x36\x67\xff\x2e\xfb\x77\x39\x60\x5d\x0e\x58\x97\x03\xd6\x25\xee\x49\xf2\x7c\x38\x9b\xcc\xa6\x57\xb3\x69\xb9\x1c\xcc\xbf\x63\x6b\xba\x3f\x19\xcf\x07\x74\x90\x3e\xc9\x0e\xae\xcb\x45\xb9\xf4\x9b\x51\x3e\xe9\xee\x8f\x66\xd3\x8b\x7d\x5b\xcd\x67\x6c\x61\x4e\x27\xcc\xe9\x84\x9c\x4e\xc9\xe9\x94\x9c\x4e\xc9\xe9\x94\x9c\x4e\xc9\xe9\x14\xc1\x53\xe6\x74\xca\xda\x29\xe1\xa8\xa4\xfc\x71\x36\x6b\xa6\xfc\x11\x3d\x6b\xf2\x13\xb6\xb4\xe9\x5e\x78\xa4\xcd\x34\x3b\x2a\x17\xcb\xf1\xd5\x60\xc9\x91\x6f\x3a\xa8\xa7\xcd\xb6\x3d\xbe\x9b\xed\xe5\x78\x3e\x3a\x5a\xbe\x9e\x6d\x8c\xc5\xd1\x6c\x5a\x96\xe3\x8b\xcb\xe5\xe5\xb3\xe5\xe5\xbc\xc4\x5e\x3c\x3d\x1f\xdf\x78\xfb\xd9\xa2\xbc\x29\xa7\x74\x5c\xa8\xa2\x7d\x34\x98\xcf\x67\xaf\x27\xe5\xf9\xf2\x70\x63\xad\xae\x9f\x6c\xda\xf9\xdd\x30\xe7\x1c\xcd\x5e\x4f\x9d\x75\x36\x5b\x5e\x1e\x31\x6c\x34\x7d\x56\x59\x67\x8b\xcd\xfd\x6d\xca\x67\x1c\x29\x9f\x55\xa4\x69\xb3\xfb\x64\x36\x5f\x5e\xce\x2e\x66\xd3\xc1\xe4\xd9\x78\xba\xbc\x3b\x91\x87\xcb\xf1\x6c\xfa\xb4\xfc\x66\x35\xbe\x19\x4c\xca\xe9\xb0\x7c\x74\x39\x5b\x2d\xca\xe7\xf3\xf2\x66\x32\xbb\x18\x0f\x07\x93\xe9\x6c\xf9\xe4\x6e\xf0\xc5\x7c\x30\x59\x5e\x57\xe6\xd9\xf2\xf1\x6f\xd5\x4c\xee\xfe\xdd\x19\x4d\x8c\xa4\x32\x5a\xde\x48\xbd\xd1\xf6\x46\xe1\x8d\xae\x37\x32\x6f\xe4\xde\xe8\x60\xb4\x7d\x9c\xd4\xef\xde\xf1\x12\x1d\x1f\xb9\xe5\xe3\xa4\x7e\x4b\xea\xc7\xa4\x3e\x4e\xc7\xa7\xda\xf6\x83\x5b\x3e\x8d\xb4\x32\xbc\x7a\xea\xf3\x69\x55\x86\x77\xb5\xbd\x44\xb3\x12\xf5\x91\x53\x9f\x6a\xbb\x1a\xec\x23\xb7\x7d\x3e\xed\x6a\x5e\x3e\x72\xdb\xef\xde\xa9\x26\x58\xc5\xd9\x6c\x39\x5c\x5d\x9f\x4d\x66\xc3\xaf\x0f\x47\xd3\x4d\xfb\xc8\xf5\x26\xe7\xae\x9d\x2f\xe9\x2f\x17\x97\x83\x51\xf9\x68\xf3\xff\xe1\xe8\xeb\x4d\x7b\x74\x3e\x9e\x4c\xca\xd1\xd9\xec\xdb\x83\xcf\xd3\x34\xc9\x5b\x07\x9f\x37\x8b\x4e\xdb\x35\x9d\xbb\xcb\xdf\x9d\x7b\x5e\x0e\x97\x87\xcb\xf9\x78\x70\xb1\xba\x76\xed\x9c\xfe\x68\xea\xda\xc9\xf9\xc1\x70\x3c\x1f\x4e\xdc\xa9\xd5\xe9\xf5\x36\x01\x5a\xad\xa3\xf1\xf4\xe6\x6c\x35\x99\x94\xcb\x3b\xcb\x0d\x79\x32\xbb\x2e\xa7\x6c\x5c\x5c\x8d\x27\xe5\xf9\x60\x58\x3e\x1b\x4f\x6f\xaa\xce\xc3\xc5\x6a\x7a\x70\x5e\x5e\x0d\x26\xe5\xfe\xdd\x7f\x8f\x16\xd7\x83\x51\xb9\x3f\x9c\xac\xce\x1e\x5d\x96\x83\xf9\xf2\x70\x34\x1e\x5c\xcd\xa6\xa3\xa7\x57\xab\x05\xe7\x60\xf9\xf6\x7f\xd9\xfe\x12\x99\x71\x89\xeb\xb9\x7b\xdf\xb4\xe7\xee\x7d\xd3\x9e\xbb\xf7\x4d\x7b\xee\xde\x37\xed\xb9\x7b\xdf\xb4\xe7\xee\x7d\xd3\x9e\xbb\xf7\x4d\x7b\xee\xde\x37\xed\xb9\x7b\xdf\xb4\xe7\xee\x7d\xd3\x1e\x97\xd8\x1e\x97\xd8\x1e\x97\xd8\x1e\x97\xd8\x5e\x8e\x4e\x8e\x4e\x8e\x0e\x97\xd8\x1e\x97\xd8\x1e\x97\xd8\x1e\x97\x58\xde\xa0\x9e\xe4\x55\x5b\xd0\x76\x69\x4f\x68\x4f\x69\x7b\xb4\x7d\x5a\xa3\x95\x6b\xdd\x33\xdb\x49\xee\x9e\xd9\x4e\xf2\x82\x78\x05\xf1\x0a\xe2\x15\xc4\x73\xf7\xb4\x06\x83\x75\xea\x18\xac\x53\xc7\x60\x9d\x3a\x06\xeb\xd4\x31\x58\xbc\xa9\x15\x6f\x6a\xc5\x9b\x5a\xf1\xa6\x56\xe6\xde\x68\x0b\xd6\x4b\xea\x3f\xde\x7c\x6b\xde\xc9\x32\x6f\x14\xde\xe8\x62\xe4\x09\x46\x97\x2d\x59\xd2\xc4\x68\x62\x14\x45\xdb\x1b\x1d\x6f\x64\xde\xc8\xbd\x51\x78\x83\x38\x45\x37\xf1\x86\x8f\xd3\x4d\xbd\xd1\x3a\xda\x18\x9b\xcb\xac\xb7\x3a\x95\x95\xfd\xdf\xca\x7d\x33\xf0\xd5\xfd\x36\xfb\xe5\x70\x78\x75\xbd\xc5\x99\xc7\x9c\x45\xcc\xd9\x0d\x39\x33\x3f\x28\xe6\x0c\x26\x94\xc5\x12\xca\x62\x09\x65\xf7\x12\x7a\xb1\xc3\xe4\xf3\x58\x96\xf9\x2e\x7b\x06\xb3\xcc\x63\x59\xe6\xb1\x2c\x83\xe1\x8a\x58\x96\x45\x2c\xcb\x62\x97\xb0\xc1\x2c\x8b\x58\x96\xc1\x3d\xba\xb1\x2c\xbb\xb1\x2c\xbb\xb1\x2c\xbb\xbb\x68\x06\xb3\xbc\x77\x5e\x66\xb5\x93\xb6\x13\x73\x66\x31\x67\x1e\x73\x16\x31\xe7\xbd\x2c\x83\x05\x92\xc5\xaa\xa7\xee\x0c\x26\x12\x2c\x90\xba\x33\xb8\x32\xc1\x5a\xa8\x3b\x83\x2b\x13\xac\x85\xba\x33\x98\x50\xb0\x16\xa2\xf3\x0b\xd6\x42\xdd\x19\xcc\x32\x58\x0b\x75\x67\x30\xcb\x60\x2d\x44\x17\x3a\x58\x0b\x75\x67\x30\xcb\x60\x2d\xd4\x9d\x51\xcd\x60\x96\xf7\x8e\x78\x1e\xab\x85\xba\x33\x8b\x39\xf3\x98\xb3\x88\x39\xef\x65\x19\x3c\xf5\xf2\x58\x2d\xd4\x9d\xc1\x2c\x83\x27\x52\xdd\x19\xcc\x32\x48\x92\x60\x0d\xe4\xb1\xea\xa9\x3b\xa3\x7b\x06\x13\xc9\x63\xc7\x2f\x58\x0b\x75\x67\x50\x33\x58\x0b\x75\x67\x30\xa1\x60\x2d\x44\xa7\x10\xac\x85\xba\x33\x98\x65\xb0\x16\xea\xce\xa8\x66\x30\xcb\x7b\x6b\x59\xc4\x6a\xa1\xee\xcc\x62\xce\x3c\xe6\x2c\x62\xce\x7b\x59\x06\x0f\x6a\x11\xab\x85\xba\x33\x98\x65\xb0\x16\xea\xce\x60\x96\xc1\x5a\x08\x9e\x5d\x45\xac\x16\xea\xce\xe8\x9e\xc1\x2c\x83\x67\x59\xdd\x19\xcc\x32\x18\x2e\xba\xd0\xd1\xf9\xed\x14\x36\x78\x96\x05\x6b\xa1\xee\x0c\x6a\x06\x6b\xa1\xee\x0c\xae\x4c\xb0\x16\x82\x59\x76\x63\xb5\x50\x77\x66\x31\x67\x1e\x73\x16\x31\xe7\xbd\x2c\x83\xcb\xd5\x8d\xd5\x42\xdd\x19\xcc\x32\x58\x0b\x75\x67\x30\xcb\x60\x2d\x04\x8f\x5b\x37\x56\x0b\x75\x67\x74\xcf\x60\x96\xc1\x5a\xa8\x3b\x83\x59\x06\xc3\x05\x6b\xa1\xee\x0c\x66\x19\xac\x85\xba\x33\x98\x65\x90\x24\xc1\x33\xb9\x1b\xab\x9e\xba\x33\x98\x65\x74\xf2\xf7\x35\x7f\xb4\xf9\x02\x73\xb3\xa9\x95\xb4\x5d\xdb\x6c\x7d\x55\x7d\xad\x1e\x1b\x54\x7d\xc8\xbe\x7d\x50\x7b\x97\x48\xed\x58\xa4\x6c\x97\x9c\xb2\x5d\x72\xca\x76\xc9\x29\xdb\x92\xd3\xa7\xe3\xd9\xf2\x4d\xcb\x14\x1e\xf3\xe6\x38\xf5\x84\xc2\x63\xb6\xc7\xd9\xb6\x44\xe1\x31\x6f\x8e\x13\xcb\x67\xdb\xfa\x7c\xc6\x27\xb2\x6f\x58\xa2\xad\xc3\x76\x8a\x56\x4f\x6c\xeb\xb0\x68\xb4\x6d\xcb\xb5\x75\xd8\x4e\xd1\xde\x90\xdb\x2e\xe7\x55\x51\xcd\x63\xfb\xfa\xff\x67\xcc\x9b\xe3\x64\x3b\xc4\xc9\xe2\xb3\xdb\x96\xd2\xd6\x61\x3b\x45\xab\x27\xb6\x75\xd8\xfd\x68\xbc\xf1\x6b\x65\xad\xca\x6a\x57\x56\xa7\xb2\xb2\xca\xca\x2b\xab\xa8\xac\xae\xb7\xf2\xa4\xb2\x9a\x95\x95\x56\x56\xa5\x91\x57\x1a\x79\xa5\x91\x57\x1a\x79\xa5\x91\x57\x1a\x79\xa5\x51\x54\x1a\x45\xa5\x51\x54\x1a\x45\xa5\x51\xbd\xd7\x6c\x55\xef\x35\x5b\x45\xa5\x51\x54\x1a\x45\xa5\x51\x54\x1a\xdd\x4a\xa3\xeb\x35\xda\x49\xb1\xb7\xb7\xf7\xb7\x07\xff\xfa\xd3\xed\x83\x3f\xef\x7d\x71\xfb\xf8\x57\x2f\xbf\x7f\xf0\xe0\x2f\xaf\xbe\xd7\xc1\xf1\xcb\x4f\x6e\xdf\x7d\xf5\xc5\xed\x8b\xdf\xbc\xfc\xe4\xf6\x8f\xaf\xfe\xff\xf6\xe0\xf8\xf7\x2f\xf7\x6e\x1f\x36\xec\xf6\xe1\x71\xff\x76\xbf\x61\xeb\x87\x9f\xbe\x75\xbc\xe9\x3c\x6a\xd8\x7a\xff\x05\x9d\x83\x86\xad\x1f\xfd\x8e\xce\x61\xc3\xd6\x07\x39\x9d\xc7\x0d\x5b\x1f\xfe\x82\xce\x51\xc3\xd6\x8f\x7f\x48\xe7\x49\xc3\xd6\x47\xff\x4b\xe7\x69\xc3\xd6\x4f\xfe\x4a\xe7\x59\xc3\xfe\xbe\xf7\x74\xff\xf1\x1e\xfd\xe7\x0d\x5b\x3f\xfb\x88\xce\xdb\x0d\x5b\x3f\xa7\xf3\xe0\xf6\x1d\x52\x7b\xb7\x61\xeb\x77\x8e\xdf\x3a\xfe\xfe\xa1\x6e\x8e\xfb\xb7\xef\x35\x6c\xfd\xee\x8f\xab\xee\xfb\x0d\x5b\xbf\xf7\x79\xd5\xfd\xa0\x61\xeb\xf7\x7f\x5e\x75\x5f\x34\x6c\xfd\xc1\xcf\xaa\xee\x87\x0d\x5b\xbf\xf8\x69\xd5\xfd\xa8\x61\xeb\x0f\x7f\x52\x75\x3f\x6e\xd8\xfa\xa3\xcf\xaa\xee\xff\x34\x6c\xfd\xf1\x0f\x7c\xf7\xd5\xed\x8b\xe3\xbd\xbd\xbd\xbd\x07\xbf\xfe\xe7\x3f\xfe\xb0\xb7\xf7\xef\x00\x00\x00\xff\xff\x10\x11\xee\x26\x1c\x52\x07\x00") - -func resourcesAppStaticFontsNotosansBoldWebfontTtfBytes() ([]byte, error) { - return bindataRead( - _resourcesAppStaticFontsNotosansBoldWebfontTtf, - "resources/app/static/fonts/NotoSans-Bold-webfont.ttf", - ) -} - -func resourcesAppStaticFontsNotosansBoldWebfontTtf() (*asset, error) { - bytes, err := resourcesAppStaticFontsNotosansBoldWebfontTtfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/static/fonts/NotoSans-Bold-webfont.ttf", size: 479772, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppStaticFontsNotosansBolditalicWebfontTtf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7b\x5c\x5c\xfb\x75\x1f\xba\xf6\xde\xf3\x02\x86\x61\xde\x2f\x66\x86\x61\x98\x19\x86\x61\x5e\x0c\xc3\xfb\x29\x84\x31\x21\x84\x43\xb0\x22\x53\x19\x53\x0e\xc6\x84\x72\x38\x32\x26\x18\x63\x45\xd1\x95\x65\x2c\x73\x65\x55\x21\x0a\x56\x29\xa6\x0a\x55\x08\x55\x28\x25\x54\xc1\x2a\xa5\x58\x95\x65\xa2\xc8\x32\xa1\x44\xc5\x0a\x51\x89\xac\x50\xac\x10\x85\x4b\xa8\x42\x28\x57\x97\x83\xee\x67\xd6\x1e\x69\x7e\x03\xcc\x39\xc2\x96\xeb\xde\xfb\x39\x7f\x9c\xa5\x75\xbe\xac\xfd\x7b\xac\xdf\x7a\xfd\xd6\xcc\x06\xa0\x00\x40\x46\x01\x70\xc0\x53\x52\x72\xec\x57\x3e\xb3\xf2\xd9\x09\x00\x2a\x17\x00\x74\x9f\x2c\xfe\x44\xc9\x3b\x31\x9f\xac\x00\xa0\xaa\x01\xa8\x85\x4f\x56\xbe\xf3\xa9\x2f\xef\xfe\xf3\xdf\x01\x60\x1c\x40\xfd\xd2\xf1\x4f\x7e\xea\xd7\x8a\xbe\xf6\x07\xa3\xdf\x02\xaa\xbc\x0b\x40\xa0\x7e\xe7\x53\x6e\xef\xff\xe4\xff\x2b\x37\x50\xc7\x06\x00\xa0\xee\x73\xef\xbf\xdb\xfa\xc7\x53\xc5\xd9\x40\x1d\xdb\x01\xe0\xee\x7e\xae\xa3\xdd\x68\xa8\xd6\xb7\x00\x75\x62\x07\x00\xda\x1a\x5b\x7f\xfd\xfd\x4f\x4d\xb8\xff\x0d\x50\x9f\x69\x05\xa0\x3f\xff\xeb\xef\xfe\x46\x2b\x00\x88\x81\xfa\xec\x22\x00\x08\x7e\xbd\xe5\x2b\x8d\xbd\x9f\xfe\x6f\x9f\x04\xea\xb3\x4f\x80\xfb\x01\x34\x7d\xfe\xdd\x06\xe6\xc2\xbb\xc7\x80\x7f\xe2\x09\x00\xa4\x37\x35\x7d\xfe\x5d\xd1\x72\xd4\x13\xe0\x7f\x46\x0d\x00\xe6\xa6\xf7\xdb\x3b\xff\xe1\x87\xa9\xf7\x81\xff\x99\x5c\x00\xcb\x64\xcb\x17\x3e\xf7\xae\x71\xe6\x7f\x34\x00\xff\xec\x26\x80\x65\xfa\xfd\x77\x3b\x5b\x23\x1f\x31\x33\xc0\x1f\x1e\x07\x00\xe3\xc9\x77\xdf\xff\xfc\x57\xc7\x86\x57\x80\x3f\x3c\x0f\xc0\x85\xd6\x2f\xfc\x46\xbb\xe8\x8f\xe9\xdf\x02\xfe\xbf\x9d\x07\xf8\xf5\xb4\xd6\xb6\xcf\xb7\x36\xfd\xe5\xdc\x06\x08\x64\x02\x00\x58\xfd\xf2\xe7\xeb\x1b\x7f\xf4\xe5\x5f\x7d\x0a\x02\xd9\x06\x00\xf0\x00\x50\x7b\x30\x9b\x77\xed\xbf\xf8\xff\xfd\x5e\xbf\xef\xb9\xff\xdf\x39\xe1\xd7\x9f\xe3\x4f\x44\x00\x94\x91\xb2\x01\x00\x0d\x4e\x00\x28\x02\x0a\x8e\xc2\x51\x60\xa0\x18\xfe\x19\x50\xd0\x0c\xcd\xc0\xc0\x7b\xf0\x25\xa0\xa0\x03\x3a\x80\x81\x2f\xc3\x57\x80\x82\x53\x70\x0a\x18\xf8\x4d\xfa\x14\x50\xf4\x6f\xd2\x5f\x03\x86\xee\xa2\xbf\x01\x14\xdd\x4d\xff\x6b\x60\xe8\x6b\xf4\xbf\x03\x8a\x1e\xa3\x27\x80\xa1\xbf\x43\x7f\x07\x28\xfa\x26\x23\x06\x86\x91\x30\x12\xa0\x18\x29\xe3\x03\x86\x49\x63\x32\x81\x62\xb2\x98\x6c\x60\x98\x1c\x4e\x2a\x50\x1c\x1f\x27\x03\x18\x4e\x26\xb7\x0f\x28\xee\xbf\xe4\xfe\x01\x30\xdc\x61\x7e\x19\x50\xfc\x5f\xe6\xbf\x03\x0c\xbf\x92\xff\x4f\x80\xe2\x9f\xe0\xd7\x00\xc3\xff\x2c\xbf\x11\x28\xfe\xaf\xf3\xff\x19\x30\xfc\x66\x7e\x07\x50\xfc\x2f\xf3\xbf\x02\x0c\xff\x14\xff\x6b\x40\xf1\xbb\xf8\x5f\x07\x86\x7f\x5e\xd0\x05\x94\xe0\xeb\x82\xf3\x40\x0b\xbe\x21\xe8\x06\x4a\xf0\x7f\x0a\x2e\x02\x23\xf8\xe7\x82\xdf\x06\x4a\xd0\x23\xf8\x5d\x60\x04\xbd\x82\x6f\x01\x25\xb8\x22\xf8\x7d\x60\x04\x43\x11\x9f\x02\x2a\xe2\x58\x44\x0b\x30\x11\xef\x47\xbc\x0f\x14\x70\x50\x2b\xfe\xff\x74\xf4\x1d\xfa\x21\xd0\xf4\x22\xfd\xdf\x80\xa1\x97\xe8\x25\xa0\xe9\xc7\xf4\x32\x30\xf4\x4f\xe8\x55\x60\xe8\xbf\xa3\xff\x11\x18\xfa\xff\xa1\x77\x81\xa1\x5f\x32\x14\xd0\x0c\x87\xe1\x01\xcd\xf0\x19\x3e\x30\x8c\x80\x11\x00\xcd\x44\x30\x51\xc0\x30\x42\x46\x04\x34\x13\x83\xda\x90\x32\x72\xa0\x19\x05\xa3\x06\x86\xd1\x30\x1a\xa0\x99\x58\x46\x07\x0c\xa3\x67\xf4\x40\x33\x16\x26\x05\x68\xd4\x09\xcd\xfd\x97\xdc\x7e\xa0\xb9\xdf\xe6\x7e\x1b\x18\xee\x00\xf7\x1a\xd0\xdc\xdf\xe7\xfe\x3e\x30\xdc\x21\xee\x10\xd0\xdc\x3f\xf0\xeb\x0a\x77\x47\xe1\x99\x46\x42\x05\x5c\x06\xe6\x73\x5f\x69\x6b\x01\xf9\xaf\xb7\x7d\xfe\x3d\x30\xb7\xbc\xdb\x7e\x12\x7c\xb8\x23\x78\xf9\x12\x18\xb4\x0b\x26\xe4\xff\xe9\x83\xfe\xff\xbd\xcf\xb7\x9d\x04\xed\xfb\xef\xb6\xbd\x07\x46\xa4\xd6\xf7\xdf\x7b\xff\x3d\xc8\xc5\xe7\xa3\x90\xfa\x67\x8c\x40\x8e\x1d\x81\x0b\x3c\xe0\x83\x00\x47\x88\x80\x48\x10\x82\x16\x4c\x60\x07\x2f\x64\x43\x11\x94\x41\x15\x9c\x80\x7a\x68\x86\x36\x9c\x8d\xfa\xd6\x71\xf6\x5f\xaa\x94\xfd\x97\x37\xc2\xfe\xcb\xec\xb0\xff\xbe\x5b\x0c\x1c\x0a\x80\x72\x36\xb1\xff\x4f\xb7\xb0\xff\xca\x5c\xec\xbf\x60\x02\x1e\x0d\x40\x45\x3f\x06\x1e\x03\x40\x45\xea\x80\x06\x01\xd0\x8f\xb7\xfe\x36\x13\x28\x98\x87\x31\xa0\x60\x11\x84\x20\x07\x3b\x78\x20\x1d\x72\xa1\x08\x4a\xa1\x02\x8e\xc1\x09\xa8\x83\x46\x68\x81\x36\xe8\x84\x33\xd0\x05\x17\xa0\x07\xae\xc0\x00\x50\x4c\x2b\x34\x03\xc5\x94\x21\xfd\x53\x3f\xa5\xe8\xdd\x05\xa0\x98\x9a\x97\x62\xa0\x98\xbf\xf1\x23\xb0\xe4\x47\x38\xb1\xb8\xf6\x26\x3f\xc2\x7b\x07\xe5\xf1\xa7\x81\x11\xbe\xe8\x97\x61\x7f\x4a\x4f\x23\x1d\x42\xfc\x11\xf2\x7e\x2d\x50\x9c\x39\x44\x18\x68\x06\x1a\xb8\xf0\x09\xf8\x24\x00\xfc\x12\xfc\x32\x30\xf0\x2b\xf0\xab\xc0\x83\x4f\xc1\x09\x88\x82\xcf\xc2\x67\x41\xe6\xd7\x31\xfd\xdf\xe9\x15\xb4\xca\x48\x36\x0e\xbd\xfc\x21\xae\xa6\x01\x57\xa9\x84\xc7\x40\x51\x26\xd4\xf9\x9b\xec\xf4\x1a\x5c\x87\x31\x98\x80\x29\xb8\x0d\x77\x61\x16\x28\x7a\x9d\xc7\x01\x8a\x2e\xe6\x8c\x03\xc5\xd0\xfc\x16\xa0\x18\x05\xbf\x17\x28\x7a\x17\xf1\x79\x3f\x65\x7e\x0b\xe9\x1f\xf9\x71\xc6\x8d\xf8\x7f\x47\xe4\xef\x91\x6f\xf1\x53\x8e\x38\x28\x4f\xbf\xe7\x1f\x8d\xfe\x22\xd2\x3f\x40\xfa\x8f\xbc\x63\x40\xd1\xa7\x90\xff\x24\xce\xd5\xe8\xa7\xd4\x13\xe4\x2b\x11\x9f\x46\xfa\x2f\x79\x6a\xa0\xe8\x2f\xf8\xe5\x41\x4b\xfd\x2a\xf5\x7b\xcc\x0d\xe6\x3f\x33\xdf\x63\xee\x32\x3f\x60\xee\x33\xff\x85\x59\x60\x96\x98\xc7\xcc\x8f\x99\x27\xcc\x5f\x33\x4f\x99\xbf\x65\x9e\x31\x7f\xcf\x6c\x32\x3b\xcc\x2e\xf3\x92\x03\x1c\x9a\x13\xe3\xf7\x63\xfa\x0e\xfd\x7d\xfa\x2e\x3d\x87\x16\x23\x05\x00\x7f\x2c\x36\xf8\xe3\x31\x50\xbb\x34\x67\xe0\x15\x85\x5c\x3f\x7d\x79\xd9\x4f\xa9\x46\xca\x00\x14\xd5\x02\x42\x30\x41\x09\x94\x43\x15\x54\x43\x2d\xea\xb9\x15\x3a\xe0\x34\x9c\x83\x6e\xb8\x04\xbd\xd0\x0f\x83\x30\x0c\xa3\x70\x03\x26\xe1\x16\xcc\xc0\x7d\x98\x87\x87\xb0\x04\xcb\xb0\x0a\xeb\xb0\x09\x2f\x28\xa0\x78\x94\x10\x28\xfa\x6b\x68\xbf\xff\x0d\xe9\xa7\xd0\xc6\x8d\x68\x3d\xed\x88\x0c\x20\x4d\x41\xfa\x63\xa4\x2b\x48\x7b\x91\x0a\x08\x8a\x08\xb5\x89\xfc\x11\xa4\xf5\x88\x3c\xd9\xf5\x01\x45\xa9\x11\xa9\x46\x84\xe0\xe9\xe2\x20\x42\xdd\x41\x3a\xcb\x3e\x45\xac\xa1\x97\x18\x5f\x4d\xd0\x27\x04\x55\x07\xbc\xce\x0c\x56\xb0\x81\x1d\x1c\xe0\x02\x37\xa4\x80\x17\xd2\x20\x1d\x32\x20\x13\x8a\xa1\x04\x4a\xa1\x0c\xca\xa1\x02\xde\x81\x5f\x85\x2a\xf8\x35\x38\x0e\x9f\x86\x6a\xe8\x81\x01\xf8\x57\xf0\x47\x30\x0e\xd3\xf0\x5d\xd8\xf1\x47\x0f\xfa\x6f\x31\x82\xf0\x80\x82\xc7\xec\xec\x74\x05\x50\x74\x3f\x08\xa1\x14\x2e\x43\x1f\x5c\x85\x21\x18\x81\x71\xb8\x09\xd3\x70\x07\xee\xc1\x1c\x2c\xc0\x23\x78\x02\x4f\x61\x0d\x9e\xc3\x36\xec\x52\x1c\x2a\x92\x12\x53\x4a\x4a\x47\x99\x28\x1b\xe5\xa2\x7c\x54\x36\x55\x48\x95\x50\xe5\x54\x15\x55\x4d\xd5\x52\x0d\x54\x33\xd5\x4a\x75\x50\xa7\xa9\x73\x54\x37\x75\x89\xea\xa5\xfa\xa9\x41\x6a\x98\x1a\xa5\x6e\x50\x93\xd4\x2d\x6a\x86\xba\x4f\xcd\x53\x0f\xa9\x25\x6a\x99\x5a\xa5\xd6\xa9\x4d\xea\x05\x0d\x34\x8f\x16\xd2\x52\x5a\x4d\x1b\x68\x33\x6d\xa7\x3d\x74\x3a\x9d\x0b\x14\xf3\x6d\xee\x34\x50\xcc\x2a\xb7\x13\x28\xce\x71\xee\x39\xa0\x98\x7b\x7e\x9e\x99\xe5\xde\x7c\x45\x39\xe3\x7e\x9c\xeb\xf3\xf3\xf4\x3c\x52\x7b\x00\xf7\xf3\x46\x3f\xe5\xfd\x6b\x3f\xe5\x7e\x07\xf1\x4e\x6e\x03\x50\xcc\x6d\x1c\x93\xe5\xfb\x70\xcc\xeb\xdc\xaf\x00\xc5\xf9\x24\x4a\x3a\x50\x72\xc6\x4f\xf9\x15\xc8\x0f\x23\x6d\x47\x5a\x8a\xb4\x9e\x53\x0b\x14\xb3\xc0\xac\xfa\x23\x15\x27\x01\x28\xce\x2d\x9e\xfc\x35\xf2\x2b\xdc\x17\xaf\x65\x56\xfd\x08\xcd\xf8\x79\x96\x32\xab\xc8\xd7\xf9\xe5\x79\x27\x51\x1e\x65\x98\x4b\x48\x71\x84\xc0\xb3\x99\x9c\xdf\x00\x8a\xb1\x70\x6c\x40\x51\x7f\xcd\x2d\x07\x8a\xd3\x81\xf8\x8e\x9f\xf2\xca\xd8\x35\x04\x11\xa6\xd1\x4f\xd9\x7d\x91\x94\x1b\x8b\xfb\x42\x1a\x98\x85\xa0\x9c\x42\x7c\x0a\x29\x2b\x13\x40\x58\xfd\xb0\x32\x04\x4f\xca\x10\x3c\x0d\x51\x60\x86\x3c\x00\x28\x86\xcf\x82\x16\x7a\xe1\x5b\xe0\x83\x7f\x01\xff\x02\xd2\xe1\xdb\x30\x00\x19\x30\x01\xdf\x81\x2c\xf8\x0f\xf0\x1f\x20\x07\xfe\x13\x4c\x43\x2e\x65\xa7\x92\x21\x9f\xf7\x05\x5e\x1b\x14\xf2\xbe\xc1\xbb\x00\xc5\x68\xa5\x7f\xf5\xca\x4a\x5f\xfe\x98\xcb\x03\x8a\x19\x64\x0c\x40\x31\xc3\x20\x84\x7a\x8c\x9c\x0f\x60\x11\x1e\xc3\x0a\x3c\x83\x0d\xd8\x82\x1d\x8a\xa6\x04\x94\x88\x92\x53\x5a\xca\x48\x59\x29\x07\xe5\xa5\x32\xa9\x7c\xaa\x98\x2a\xa3\x2a\xa9\xe3\x54\x0d\x55\x4f\x35\x51\x27\xa9\x76\xea\x14\x75\x96\x3a\x4f\x5d\xa4\x2e\x53\x7d\xd4\x55\x6a\x88\x1a\xa1\xc6\xa9\x9b\xd4\x34\x75\x87\xba\x47\xcd\x51\x0b\xd4\x23\xea\x09\xf5\x94\x5a\xa3\x9e\x53\xdb\xfe\x20\x45\x47\xd2\x62\x5a\x49\xeb\x68\x13\x6d\xa3\x5d\xb4\x8f\xce\xa6\x0b\xe9\x12\xba\x9c\xae\xa2\xab\xe9\x5a\xba\x81\x6e\xa6\x5b\xe9\x0e\xfa\x34\x7d\x8e\xee\xa6\x2f\xd1\xbd\x74\x3f\x3d\x48\x0f\xd3\xa3\xf4\x0d\x7a\x92\xbe\x45\xcf\xd0\xf7\xe9\x79\xfa\x21\xbd\x44\x2f\xd3\xab\xf4\x3a\xbd\x49\xbf\x60\x80\xe1\x31\x42\xa0\x98\x75\xbf\x65\x73\xc6\x39\xcb\x40\x71\x26\xb8\x5f\x02\x8a\xf3\xdf\xfd\x11\x98\x53\x4e\x58\xd8\xba\x1f\xe7\x1e\x43\x3b\x5e\x41\xda\x82\xf8\x22\xf2\x28\xc9\x43\x1b\xe5\xb2\xf4\x04\x8e\x30\xee\xa7\x01\xbe\x1d\x23\xfc\x02\xda\xfa\x57\x51\xa6\x0c\x47\xf8\x7b\xb4\xec\xfa\xa0\x9f\x70\xba\x91\xb2\xb3\x57\xe0\xd9\x67\x32\x5d\x40\x31\xa7\x38\x4e\xa0\x38\x23\x7e\x4b\xe5\x88\x11\xf9\xa7\x3c\x51\xa8\x0c\xf5\xf7\x7e\x9e\xa5\x1c\x31\x5a\xb6\x0d\x2d\x7b\xc4\xff\x53\x56\x86\xa3\x25\x78\x7c\x96\x29\x47\xcb\xf6\x21\x1f\x87\xcf\xd6\x07\x7d\x83\x67\x42\x7e\x34\x88\x30\x95\x28\x53\xf1\xd1\x94\xd7\x8f\xb3\x88\x0f\xa6\xe4\x6a\x43\x56\xae\x25\xd6\x19\x8e\xd6\x07\xd7\x49\xd2\xc0\x0a\x57\x83\xa3\xb1\x6b\x60\x16\xf0\xa9\xa2\xe0\xae\x03\x5a\x2d\x45\x3a\xca\x52\x4e\x39\x50\xcc\x4d\x06\xf5\xcf\xd2\xe0\x38\x74\x7d\x70\x6d\xac\xb7\x07\xe6\xdd\xc6\x19\x69\xf4\x3a\x45\x88\xd7\xf9\xab\x0c\x1f\x8c\xc0\xbf\x87\x1c\x98\x80\x49\x38\x0a\x53\xf0\x9f\xa1\x14\xbe\x07\xdf\x83\x0a\xf8\x07\xf8\x07\x78\x87\x52\x50\x0a\xa8\xa4\x7e\x8f\xfa\x3d\xf8\x55\x5a\x4a\xcb\xa1\x8a\x56\xd2\x4a\xf8\x35\x5a\x4b\x6b\xe1\x38\xad\xa7\x0d\xf0\x69\xda\x48\x1b\xe1\x9f\xd0\x56\xda\x0a\x27\x68\x3b\x6d\x87\xcf\xd0\x0e\xda\x01\x35\x74\x06\x9d\x09\x9f\xa5\x7f\x99\x2e\x87\x7f\x4a\x57\xd0\x15\xf0\x2e\x7a\xec\xe0\x2b\x8f\xdd\xfd\x4b\xfa\x27\x40\x51\x93\x54\x23\x50\xb4\xbf\x1e\x4d\xfe\xd9\x32\x39\x25\xa5\xd4\x94\x81\x32\x53\x76\xca\x43\xa5\x53\xb9\x54\x11\x55\x4a\x55\x50\xfe\x0a\x05\x3e\xd8\x06\xea\x65\x1d\xd2\xe1\x0f\xe6\x5f\x51\xf0\x7e\x70\x03\xf9\x15\x82\xde\xf5\x53\x7f\xc6\xfe\xe0\x5d\x56\x7e\x57\x89\xf8\x34\x8e\x30\xbf\x57\xde\x2f\xf9\x72\x38\x30\xf2\xf6\x6b\x7c\x8a\x44\x76\x8d\x40\xbd\x1c\x47\xc9\x29\x1c\xbf\x3b\x30\xef\xfc\xeb\x91\xe7\x50\x66\x2e\x80\xdf\xc5\xb5\xad\xbc\xfe\xe9\xab\x19\xaf\xe3\x08\x2b\x28\xe9\xc7\x97\xfd\x14\x20\x20\x33\xbd\x4f\x7e\x3a\x30\x0b\x0d\xd1\x78\x47\x02\xbc\x1d\x71\xf0\x76\x14\x81\xb7\xa3\x68\xbc\x1d\xa9\xf1\x46\xa4\xc3\xbb\x90\x1e\x6f\x41\x46\xbc\xff\x98\xf0\xe6\x63\xc5\x1b\x8e\x0d\xef\x36\x49\x78\xab\xb1\xff\x1c\x46\x4c\x06\x80\x31\x00\x98\x00\x80\x29\x00\xb8\x0d\x00\x77\xfd\x57\x64\x00\x78\x00\x00\xfe\x7b\xbd\xbf\x12\xf1\x57\x5f\xcf\x00\xc0\x7f\x8f\xde\x02\x80\x1d\x7f\x71\x02\x40\x09\x00\x28\xff\xad\x59\x0e\x40\x69\xfd\xb7\x67\x00\xca\x0a\x40\x39\x00\x28\x2f\x00\x95\x09\x40\xe5\x03\x50\xc5\x00\x54\x19\x00\x55\x09\x40\x1d\x07\xa0\x6a\x00\xa8\x7a\x00\xaa\x09\x80\x3a\x09\xe0\xaf\xb8\xa8\x53\x00\xd4\x59\x00\xea\x3c\x00\x75\x11\x80\xba\x0c\x40\xf5\x01\x50\x57\x01\xa8\x21\x00\x6a\xc4\xaf\xf5\x97\x03\x04\x9d\x79\x4d\x07\x5f\xce\x1d\xf4\xd3\x97\x8b\x2f\xdb\x81\xfa\xe0\xdf\xbc\x3c\x83\x7c\x1d\xe2\x73\xfe\x33\x7c\xd9\x8d\xfc\x38\x50\x2f\xd7\x5e\x0e\x23\xdf\xfd\xea\xd9\x97\x6b\x01\xbc\x7b\x1f\x6d\x47\x7a\x1c\x28\x88\x7c\xb9\x88\xfc\xe2\xab\x71\xd8\x91\x5f\x8f\xc3\xd2\x45\x5c\xdb\x14\xf2\x97\x09\xc9\x19\x82\x8e\x87\xa1\x33\xfb\x46\x1e\x00\x8a\x6e\xa4\x45\x40\xd1\xb7\x40\x08\x85\x6f\xcb\x57\xa9\x13\x54\x1d\xd5\x48\xb5\x50\x6d\x54\x27\x75\x86\xea\xa2\x2e\x50\x3d\xd4\x15\x6a\x80\xba\x46\x5d\xa7\xc6\xa8\x09\x6a\x8a\xba\x4d\xdd\xa5\x66\xa9\x07\xd4\x22\xf5\x98\x5a\xa1\x9e\x51\x1b\xd4\x16\xb5\x03\xd4\xae\x97\xd7\xf4\x8a\x02\xf8\xe9\x07\xcb\x78\x3b\x39\xe1\xbf\xeb\x40\x27\x5f\x00\x14\x54\xfa\xf1\x97\x73\x48\x67\xfc\x3f\xdd\xb5\x21\x7e\x92\xb7\xe9\x97\x09\xe0\xfe\x11\xce\x05\x25\x77\x23\x91\x9f\x42\xc9\x06\xde\x69\x94\x57\xef\xa1\x17\x79\x4f\x70\x84\x1e\x9c\xcb\x03\x14\x6c\xf0\xb7\x71\xc6\x63\x48\xd5\xf8\xd3\xd9\xd7\x32\xb8\x12\x18\xe4\x4f\xbf\x96\x6f\xe0\x0d\xe1\x4f\x27\x11\xd1\x21\x32\xf9\x5a\xbe\xc4\x5f\x53\x05\x28\xae\x13\x4e\x10\x08\x4b\x2b\x79\x85\xb8\x5f\x3f\xf5\xee\xfb\x29\x41\xe9\x4a\xbc\xff\xe1\x38\xf4\xb7\xfc\xf3\xb2\x14\x4a\x70\xc6\x57\xf4\x34\xae\xa1\x10\x67\x2c\x7c\xcd\x1f\x44\x87\x80\x06\x11\xf6\x62\x00\xbb\x30\x0a\xec\xb6\x28\xb1\xdb\xa2\xc1\x3e\x8b\x0e\x3b\x2c\x7a\xec\xad\x18\xb1\xab\x92\x80\xfd\x14\x33\xf6\x53\x2c\xd8\x4f\xf1\x62\x3f\x25\x1d\x3b\x29\x99\xd8\x43\x29\xf8\xb9\x8d\x5b\xf8\x0b\x89\x1a\x40\x8d\x03\x50\x37\x01\xa8\x69\x00\xff\x6d\x8f\xba\x07\x40\xcd\x01\x50\x0b\x00\xd4\x23\x00\xff\x5d\x8e\x7a\x0a\x40\xad\x01\x50\xcf\x01\xa8\x6d\x00\x6a\x17\x80\xe6\x00\xd0\x91\x00\xb4\x18\x80\x56\x02\xd0\x3a\x00\xda\x04\x40\xdb\x00\x68\x17\x00\xed\x03\xa0\xb3\x01\xe8\x42\x00\xba\x04\x80\x2e\x07\xa0\xab\x00\xfc\x77\x4c\xba\x16\x80\x6e\x00\xa0\x9b\x01\xe8\x56\x00\xba\x03\x80\x3e\x0d\xd4\x07\x13\x9c\x49\xa0\x3e\x98\xf2\xd3\x97\xdd\xc8\x9f\xf1\x53\x00\xa4\x25\xdc\x07\xaf\x78\xf6\xa7\x2f\xdb\x51\x66\x01\x7f\x6a\x43\x64\x1c\x69\x5d\x00\xe9\x41\xbe\x07\xa8\x0f\x86\x83\xf2\x01\xc9\x35\xe6\x9a\x5f\xde\x4f\xa1\x04\xa9\x97\x33\x84\x3f\x6d\xc7\x59\xfc\xf1\xb0\x93\xbb\xf1\x7a\xc6\x35\x0e\xe6\x6d\xce\xf8\xeb\xf5\xb0\x32\x2c\x95\x07\x90\x7e\xec\x0d\xf4\x23\x3f\xf3\x1a\x01\xff\xc8\x2f\x87\xa9\xdd\xb7\x47\x69\x1b\xa7\x1b\xe9\xa4\xbf\xb6\x46\xfa\x4e\x60\x0d\x8b\x04\x1d\x26\xd6\xbc\x9f\x0e\xbc\xa6\x5e\xff\x3a\xb5\x6a\xcd\x15\xa0\xb4\x06\x10\x32\x29\xbc\x06\x5e\x33\xaf\x95\xd7\xc1\x3b\xcd\x3b\xc7\xeb\xe6\x5d\xe2\xf5\xf2\xfa\x79\x83\xbc\x61\xde\x28\xef\x06\x6f\x92\x77\x8b\x37\xc3\xbb\xcf\x9b\xe7\x3d\xe4\x2d\xf1\x96\x79\xab\xbc\x75\xde\x26\xef\x05\x1f\xf8\x3c\xbe\x90\x2f\xe5\xab\xf9\x06\xbe\x99\x6f\xe7\x7b\xf8\xe9\xfc\x5c\x7e\x11\xbf\x94\x5f\xc1\x3f\xc6\x3f\xc1\xaf\xe3\x37\xf2\x5b\xf8\x6d\xfc\x4e\xfe\x19\x7e\x17\xff\x02\xbf\x87\x7f\x85\x3f\xc0\xbf\xc6\xbf\xce\x1f\xe3\x4f\xf0\xa7\xf8\xb7\xf9\x77\xf9\xb3\xfc\x07\xfc\x45\xfe\x63\xfe\x0a\xff\x19\x7f\x83\xbf\xc5\xdf\x11\xd0\x02\x81\x40\x24\x90\x0b\xb4\x02\xa3\xc0\x2a\x70\x08\xbc\x82\x4c\x41\xbe\xa0\x58\x50\x26\xa8\x14\x1c\x17\xd4\x08\xea\x05\x4d\x82\x93\x82\x76\xc1\x29\xc1\x59\xc1\x79\xc1\x45\xc1\x65\x41\x9f\xe0\xaa\x60\x48\x30\x22\x18\x17\xdc\x14\x4c\x0b\xee\x08\xee\x09\xe6\x04\x0b\x82\x47\x82\x27\x82\xa7\x82\x35\xc1\x73\xc1\xb6\x60\x37\x82\x13\x11\x19\x21\x8e\x50\x46\xe8\x22\x4c\x11\xb6\x08\x57\x84\x2f\x22\x3b\xa2\x30\xa2\x24\xa2\x3c\xa2\x2a\xa2\x3a\xa2\x36\xa2\x21\xa2\x39\xa2\x35\xa2\x23\xe2\x74\xc4\xb9\x88\xee\x88\x4b\x11\xbd\x11\xfd\x11\x83\x11\xc3\x11\xa3\x11\x37\x22\x26\x23\x6e\x45\xcc\x44\xdc\x8f\x98\x8f\x78\x18\xb1\x14\xb1\x1c\xb1\x1a\xb1\x1e\xb1\x19\xf1\x22\x12\x22\x79\x91\xc2\x48\x69\xa4\x3a\xd2\x10\x69\x8e\xb4\x47\x7a\x22\xd3\x23\x73\x23\x8b\x22\x4b\x23\x2b\x22\x8f\x45\x9e\x88\xac\x8b\x6c\x8c\x6c\x89\x6c\x8b\xec\x8c\x3c\x13\xd9\x15\x79\x21\xb2\x27\xf2\x4a\xe4\x40\xe4\xb5\xc8\xeb\x91\x63\x91\x13\x91\x53\x91\xb7\x23\xef\x46\xce\x46\x3e\x88\x5c\x8c\x7c\x1c\xb9\x12\xf9\x2c\x72\x23\x72\x2b\x72\x27\x8a\x8e\x12\x44\x89\xa2\xe4\x51\xda\x28\x63\x94\x35\xca\x11\xe5\x8d\xca\x8c\xca\x8f\x2a\x8e\x2a\x8b\xaa\x8c\x3a\x1e\x55\x13\x55\x1f\xd5\x14\x75\x32\xaa\x3d\xea\x54\xd4\xd9\xa8\xf3\x51\x17\xa3\x2e\x47\xf5\x45\x5d\x8d\x1a\x8a\x1a\x89\x1a\x8f\xba\x19\x35\x1d\x75\x27\xea\x5e\xd4\x5c\xd4\x42\xd4\xa3\xa8\x27\x51\x4f\xa3\xd6\xa2\x9e\x47\x6d\x47\xed\x0a\x39\xc2\x48\xa1\x58\xa8\x14\xea\x84\x26\xa1\x4d\xe8\x12\xfa\x84\xd9\xc2\x42\x61\x89\xb0\x5c\x58\x25\xac\x16\xd6\x0a\x1b\x84\xcd\xc2\x56\x61\x87\xf0\xb4\xf0\x9c\xb0\x5b\x78\x49\xd8\x2b\xec\x17\x0e\x0a\x87\x85\xa3\xc2\x1b\xc2\x49\xe1\x2d\xe1\x8c\xf0\xbe\x70\x5e\xf8\x50\xb8\x24\x5c\x16\xae\x0a\xd7\x85\x9b\xc2\x17\xd1\x10\xcd\x8b\x16\x46\x4b\xa3\xd5\xd1\x86\x68\x73\xb4\x3d\xda\x13\x9d\x1e\x9d\x1b\x5d\x14\x5d\x1a\x5d\x11\x7d\x2c\xfa\x44\x74\x5d\x74\x63\x74\x4b\x74\x5b\x74\x67\xf4\x99\xe8\xae\xe8\x0b\xd1\x3d\xd1\x57\xa2\x07\xa2\xaf\x45\x5f\x8f\x1e\x8b\x9e\x88\x9e\x8a\xbe\x1d\x7d\x37\x7a\x36\xfa\x41\xf4\x62\xf4\xe3\xe8\x95\xe8\x67\xd1\x1b\xd1\x5b\xd1\x3b\x22\x5a\x24\x10\x89\x44\x72\x91\x56\x64\x14\x59\x45\x0e\x91\x57\x94\x29\xca\x17\x15\x8b\xca\x44\x95\xa2\xe3\xa2\x1a\x51\xbd\xa8\x49\x74\x52\xd4\x2e\x3a\x25\x3a\x2b\x3a\x2f\xba\x28\xba\x2c\xea\x13\x5d\x15\x0d\x89\x46\x44\xe3\xa2\x9b\xa2\x69\xd1\x1d\xd1\x3d\xd1\x9c\x68\x41\xf4\x48\xf4\x44\xf4\x54\xb4\x26\x7a\x2e\xda\x16\xed\xc6\x70\x62\x22\x63\xc4\x31\xca\x18\x5d\x8c\x29\xc6\x16\xe3\x8a\xf1\xc5\x64\xc7\x14\xc6\x94\xc4\x94\xc7\x54\xc5\x54\xc7\xd4\xc6\x34\xc4\x34\xc7\xb4\xc6\x74\xc4\x9c\x8e\x39\x17\xd3\x1d\x73\x29\xa6\x37\xa6\x3f\x66\x30\x66\x38\x66\x34\xe6\x46\xcc\x64\xcc\xad\x98\x99\x98\xfb\x31\xf3\x31\x0f\x63\x96\x62\x96\x63\x56\x63\xd6\x63\x36\x63\x5e\x88\x41\xcc\x13\x0b\xc5\x52\xb1\x5a\x6c\x10\x9b\xc5\x76\xb1\x47\x9c\x2e\xce\x15\x17\x89\x4b\xc5\x15\xe2\x63\xe2\x13\xe2\x3a\x71\xa3\xb8\x45\xdc\x26\xee\x14\x9f\x11\x77\x89\x2f\x88\x7b\xc4\x57\xc4\x03\xe2\x6b\xe2\xeb\xe2\x31\xf1\x84\x78\x4a\x7c\x5b\x7c\x57\x3c\x2b\x7e\x20\x5e\x14\x3f\x16\xaf\x88\x9f\x89\x37\xc4\x5b\xe2\x1d\x09\x2d\x11\x48\x44\x12\xb9\x44\x2b\x31\x4a\xac\x12\x87\xc4\x2b\xc9\x94\xe4\x4b\x8a\x25\x65\x92\x4a\xc9\x71\x49\x8d\xa4\x5e\xd2\x24\x39\x29\x69\x97\x9c\x92\x9c\x95\x9c\x97\x5c\x94\x5c\x96\xf4\x49\xae\x4a\x86\x24\x23\x92\x71\xc9\x4d\xc9\xb4\xe4\x8e\xe4\x9e\x64\x4e\xb2\x20\x79\x24\x79\x22\x79\x2a\x59\x93\x3c\x97\x6c\x4b\x76\xa5\x1c\x69\xa4\x54\x2c\x55\x4a\x75\x52\x93\xd4\x26\x75\x49\x7d\xd2\x6c\x69\xa1\xb4\x44\x5a\x2e\xad\x92\x56\x4b\x6b\xa5\x0d\xd2\x66\x69\xab\xb4\x43\x7a\x5a\x7a\x4e\xda\x2d\xbd\x24\xed\x95\xf6\x4b\x07\xa5\xc3\xd2\x51\xe9\x0d\xe9\xa4\xf4\x96\x74\x46\x7a\x5f\x3a\x2f\x7d\x28\x5d\x92\x2e\x4b\x57\xa5\xeb\xd2\x4d\xe9\x0b\x19\xc8\x78\x32\xa1\x4c\x2a\x53\xcb\x0c\x32\xb3\xcc\x2e\xf3\xc8\xd2\x65\xb9\xb2\x22\x59\xa9\xac\x42\x76\x4c\x76\x42\x56\x27\x6b\x94\xb5\xc8\xda\x64\x9d\xb2\x33\xb2\x2e\xd9\x05\x59\x8f\xec\x8a\x6c\x40\x76\x4d\x76\x5d\x36\x26\x9b\x90\x4d\xc9\x6e\xcb\xee\xca\x66\x65\x0f\x64\x8b\xb2\xc7\xb2\x15\xd9\x33\xd9\x86\x6c\x4b\xb6\x23\xa7\xe5\x02\xb9\x48\x2e\x97\x6b\xe5\x46\xb9\x55\xee\x90\x7b\xe5\x99\xf2\x7c\x79\xb1\xbc\x4c\x5e\x29\x3f\x2e\xaf\x91\xd7\xcb\x9b\xe4\x27\xe5\xed\xf2\x53\xf2\xb3\xf2\xf3\xf2\x8b\xf2\xcb\xf2\x3e\xf9\x55\xf9\x90\x7c\x44\x3e\x2e\xbf\x29\x9f\x96\xdf\x91\xdf\x93\xcf\xc9\x17\xe4\x8f\xe4\x4f\xe4\x4f\xe5\x6b\xf2\xe7\xf2\x6d\xf9\xae\x82\xa3\x88\x54\x88\x15\x4a\x85\x4e\x61\x52\xd8\x14\x2e\x85\x4f\x91\xad\x28\x54\x94\x28\xca\x15\x55\x8a\x6a\x45\xad\xa2\x41\xd1\xac\x68\x55\x74\x28\x4e\x2b\xce\x29\xba\x15\x97\x14\xbd\x8a\x7e\xc5\xa0\x62\x58\x31\xaa\xb8\xa1\x98\x54\xdc\x52\xcc\x28\xee\x2b\xe6\x15\x0f\x15\x4b\x8a\x65\xc5\xaa\x62\x5d\xb1\xa9\x78\xa1\x04\x25\x4f\x29\x54\x4a\x95\x6a\xa5\x41\x69\x56\xda\x95\x1e\x65\xba\x32\x57\x59\xa4\x2c\x55\x56\x28\x8f\x29\x4f\x28\xeb\x94\x8d\xca\x16\x65\x9b\xb2\x53\x79\x46\xd9\xa5\xbc\xa0\xec\x51\x5e\x51\x0e\x28\xaf\x29\xaf\x2b\xc7\x94\x13\xca\x29\xe5\x6d\xe5\x5d\xe5\xac\xf2\x81\x72\x51\xf9\x58\xb9\xa2\x7c\xa6\xdc\x50\x6e\x29\x77\x54\xb4\x4a\xa0\x12\xa9\xe4\x2a\xad\xca\xa8\xb2\xaa\x1c\x2a\xaf\x2a\x53\x95\xaf\x2a\x56\x95\xa9\x2a\x55\xc7\x55\x35\xaa\x7a\x55\x93\xea\xa4\xaa\x5d\x75\x4a\x75\x56\x75\x5e\x75\x51\x75\x59\xd5\xa7\xba\xaa\x1a\x52\x8d\xa8\xc6\x55\x37\x55\xd3\xaa\x3b\xaa\x7b\xaa\x39\xd5\x82\xea\x91\xea\x89\xea\xa9\x6a\x4d\xf5\x5c\xb5\xad\xda\x55\x73\xd4\x91\x6a\xb1\x5a\xa9\xd6\xa9\x4d\x6a\x9b\xda\xa5\xf6\xa9\xb3\xd5\x85\xea\x12\x75\xb9\xba\x4a\x5d\xad\xae\x55\x37\xa8\x9b\xd5\xad\xea\x0e\xf5\x69\xf5\x39\x75\xb7\xfa\x92\xba\x57\xdd\xaf\x1e\x54\x0f\xab\x47\xd5\x37\xd4\x93\xea\x5b\xea\x19\xf5\x7d\xf5\xbc\xfa\xa1\x7a\x49\xbd\xac\x5e\x55\xaf\xab\x37\xd5\x2f\x34\xa0\xe1\x69\x84\x1a\xa9\x46\xad\x31\x68\xcc\x1a\xbb\xc6\xa3\x49\xd7\xe4\x6a\x8a\x34\xa5\x9a\x0a\xcd\x31\xcd\x09\x4d\x9d\xa6\x51\xd3\xa2\x69\xd3\x74\x6a\xce\x68\xba\x80\xe2\xf2\xb1\xb7\xad\x04\x2e\x50\xcc\xa9\x40\x9f\x5b\x0e\x14\x33\x8a\xfd\xe3\x1f\x21\xe2\xbf\x75\x51\x9c\x47\xd8\xf1\xa5\x10\xe7\xec\x8e\x02\xc5\xc1\xae\x36\x2b\xc9\xc3\x1e\x39\x17\xbb\xd7\x4c\x1f\xf1\xac\x0f\x9f\x9d\xc1\x67\xaf\x23\xbd\x81\x78\x2b\x52\x1a\x9f\x5a\x42\x99\x39\xfc\xe9\x7f\x45\x7c\x15\x91\x4f\x20\x5f\x83\x54\x18\x78\x56\x0e\x14\xbd\x8d\xe3\xeb\x76\x4b\x81\xa2\x7b\xfd\x94\x95\xa4\xbe\x1b\x58\x9b\x1f\xe9\x0e\x22\xbc\x9b\xc4\x68\x38\x0e\xf5\xb9\x5d\xff\x1e\xff\xd4\x4f\x59\x19\xba\x05\xe9\xd9\xa0\x24\x3d\x8d\x6b\x93\x23\x52\x8e\x4f\xf5\xf8\x47\x66\x4a\x11\xe7\x7f\x34\xe5\x7d\x1d\x67\x2c\xc5\xa7\x46\x83\xba\x22\x29\xab\xcf\xfd\x94\x3d\x05\x52\x9f\x1f\x41\x5b\x0f\xa6\xac\x3e\xd9\xb3\xe0\x98\x83\xbb\xfb\x70\xca\x7d\xc0\x76\xf7\x51\xc3\xa8\xed\xfd\x34\xa0\xed\x7d\x94\xd5\x30\xa9\xed\x0f\xa7\xe1\xd6\xc0\x6a\x9b\x7a\x07\xcf\x08\x79\x56\xab\x81\x15\x12\x3c\xa7\x7b\xb7\x15\x28\xe6\xef\x90\x9e\x22\xc6\x7f\x13\x1e\xf5\xcc\xda\x55\x08\x3f\x1a\xdc\x69\x58\xbe\x14\x67\x14\x22\x25\xf1\xdb\x41\xed\x85\xe3\xb9\x89\x50\xf0\xda\x7a\x1f\x11\x7b\x21\xf8\x80\xaf\x7d\xf7\xc3\x78\xea\x7f\xfa\x67\xa7\xfe\xd8\x4f\x49\x9c\x59\xf5\x7b\x28\x63\x44\x1d\xa2\xb7\x06\xfc\x02\x7d\x96\x33\x10\xa4\x01\x4f\x67\x9f\x5a\x20\xf8\xd1\x0f\xe5\xff\x1c\x5e\xfb\x7b\xe0\x44\xea\x09\x9e\xc4\xe5\x81\x33\xf2\xaf\xa7\x15\xf5\xd0\x47\xe8\x3f\x0c\xcf\xeb\x81\x60\x64\x98\x09\xce\x1e\xe0\xbf\xea\xdf\x2f\x89\x07\x62\x4b\xcb\x7e\x1e\x35\xd3\x82\x94\xc4\xab\xd1\xb6\x3d\x48\x31\x22\xb1\xbe\x4f\xf2\xac\x07\x05\x2c\xf9\xb0\x3c\xda\x06\x87\xf6\x53\x76\x17\xac\x1e\x02\xfe\x88\xf6\x4c\xc6\x3a\x36\xaa\x84\xe3\x29\x5c\x27\x1b\x09\x39\x62\x8c\xd5\x6c\xc4\x66\x63\x23\x41\xe9\xe9\x60\x24\xa7\xe7\x83\x16\xce\xd1\xa2\x55\xb7\x42\x30\x8a\xe2\x27\x87\x4c\x15\xbc\x8e\xd2\x81\xb9\x1c\x68\x33\x9b\x84\xc5\xae\xa3\xc5\x8e\x10\xda\x43\x4b\x23\x6d\x29\x70\x3a\xf8\xc9\x24\xb7\x32\x68\x03\xcc\x13\x8c\xb4\x7d\x7b\xcf\x97\x7f\x0f\x4f\x39\xde\xff\x53\x36\xd2\xb2\x31\x99\x33\xf5\x32\xf5\xd5\xca\xe9\x0b\x38\x26\x2f\x70\x8e\x7e\x8d\x75\xe0\xaa\x64\xc4\x19\xa5\x21\x42\x6a\x9e\x9d\xc5\x8e\x54\x83\x23\xd7\xa2\x0c\xa1\x4f\x7a\x8c\xd0\xd8\xef\x13\xa7\xff\x7e\x70\x25\x11\xbf\xe6\xe7\x05\xc3\xb8\xda\x1d\xdc\xd1\x7b\x7e\x1b\xe6\x5a\x70\xb4\x5f\xf1\x53\xfe\x2f\xf9\x11\x7e\x34\xea\x67\x76\x6f\x8c\x0a\xf1\x47\xd2\xce\x89\xd5\xd2\x68\xc3\x6c\xa6\xe0\xfe\x01\x7c\x48\xf4\x20\xb5\xcd\x74\xa1\x3d\xcf\x63\xe4\x61\xf9\x47\x48\x59\xeb\xed\x08\x78\x7d\x29\x50\x11\x47\xf6\xee\x82\x1c\x93\x57\x11\xdc\x6f\x88\xcf\x86\x89\xb4\x0c\x5b\x03\x6c\xef\xe5\xc3\x45\xa7\x70\xde\x7d\x80\x47\x7f\xf7\xc3\xbc\x89\xee\xc5\xdd\x55\x23\x5d\x09\xee\x31\x24\x72\xfe\x09\xda\xcf\x4c\x50\x6f\xac\x55\x53\x57\x91\x5e\xd8\xbb\x17\xfa\x0f\xd0\xa2\xbe\xbb\x37\x22\x85\x78\x28\xae\x81\xeb\x0e\x5a\x08\xab\x55\xee\x86\xdf\x83\x78\x1c\xcc\xd1\x6c\x05\x45\x7a\xdc\x28\x04\x23\xc9\xff\x85\xe3\x5b\x71\xb4\x2c\x44\xf0\x5b\x28\x01\xff\x65\xf7\x38\xb7\x57\x9f\x64\xc4\xe6\x4e\xe0\x4e\x67\x58\x4a\xe8\xf9\x06\xb1\xce\x79\xd8\x5b\x2f\xb1\xb6\x6d\x0d\xae\x8a\x73\x26\x58\x29\xb1\x1e\x17\x42\x09\x8f\x63\x69\xe0\xfb\x0e\x9c\x60\x95\x15\xb0\x49\x25\x04\xe3\x27\x9e\x05\xf3\x10\x35\xff\x89\x80\x65\x96\xbe\x5e\x61\x45\xd0\x1e\xe8\x4c\xa4\xef\x22\x15\xb0\xfe\x88\x16\x38\x89\xf6\x5f\x85\x16\xb8\x14\x5c\x21\x67\x2d\xb8\xdf\x40\x46\x10\x21\xbe\x85\xc8\x27\x30\x6e\xb0\x1a\x7b\x04\xaf\xab\x2c\xd6\x92\xe9\x64\xe4\xff\x18\xd7\xbf\x8c\x6b\x3b\x13\xdc\x29\x35\x86\x3f\x15\x04\x29\x5d\xec\xa7\xf0\x67\xc8\x97\x05\x77\x17\xd8\x51\x7e\x30\x6e\xb0\x15\x14\xef\x93\xc8\xb3\x3b\xfa\x0f\x00\xaf\xf6\xc2\x2c\xb0\x71\x95\xd0\x18\x17\x65\xfe\x3d\x52\x27\xab\x67\xc2\xde\x62\x10\x59\x0f\xda\x2a\xa7\x2a\xa8\x73\xa6\x0f\x23\xe7\xe7\xf0\xa7\xdf\xc5\x7d\x65\xa0\xfc\x7f\x41\x5f\xc6\x6f\x71\xf1\x3e\x81\x51\xe8\xdf\x61\x84\x5f\xc3\x08\x7f\x01\x6d\xe6\xaf\xd0\x6e\x7f\x82\xbb\xc0\x75\x72\xfe\x23\xe1\x53\x16\xe4\xff\x02\x35\x33\x1e\xcc\x2c\x6c\x5e\x60\xeb\x6a\xb2\x66\x66\xb5\x4a\xd6\x78\x64\xb5\x1c\xc8\x56\x3e\x9c\x4b\x45\x4f\xbc\xda\x23\xff\x5b\x84\x7c\x75\x70\x1c\xd6\xae\x02\x74\x74\xb7\xcb\x5f\x5d\xfb\x29\x59\xcf\x33\x3b\x88\xcc\xfa\x29\x6f\x8c\x90\x61\x57\x82\x38\xfd\x20\xf8\x14\xd3\xba\x8b\x9f\x97\x22\xa5\xfd\x94\xcb\x0b\x52\xce\x65\x5c\x5b\x39\x31\xce\x10\xfe\x74\x10\xc7\xb9\x1e\x9c\x8b\x2a\x44\x3c\x97\x90\x21\xa3\x1f\x99\x73\x95\xbb\xf7\xb1\xbe\xba\x8f\xfc\x2a\xee\x7a\xf5\x95\x1e\xe8\xb3\xb8\x2a\xb2\x9e\x44\xf9\x57\xe3\xa0\xfc\x3a\xd2\x15\xac\x13\x02\xd5\x32\xc1\x87\xa9\x39\xe9\x1b\xc1\xc8\x4f\xdf\xd8\xbd\x06\x14\x7d\x17\x29\x1b\xff\xd7\xb1\x1a\xc4\x6a\x3f\xa0\x19\x32\x83\x84\xa9\x33\xdf\x84\xa7\x29\xff\x2c\xd4\x1f\xe2\x5c\x44\x84\x0f\xa9\x27\xc9\x0c\xd5\x8a\xda\x10\xe2\x1e\xb7\xfd\x94\xfa\x43\xbf\x06\x0e\xe4\xfd\x32\xd3\xb8\xf2\x1e\x3f\x65\xef\x92\xac\x05\x86\xe3\x43\xb2\x15\xc1\x33\xa3\xc1\x79\x99\x51\xcc\x8f\x58\x83\xbd\x49\xcd\x49\xf2\x01\x1d\xb2\xf6\x46\xf0\x07\x64\xae\x21\x3c\x59\x82\x67\xf7\x4e\xcd\xe2\xbe\x42\x6b\xd1\xfb\x58\x8b\xde\xff\xd0\x7a\x35\x28\x43\xd6\xa5\x57\x11\x39\x8b\xf4\x2a\x8e\x7c\x16\x29\x9b\x19\xeb\x71\x8f\xbe\xdd\x1a\xdc\xbb\xff\xdc\xab\xfc\x27\xc5\x18\x90\x62\x2d\x4a\x6f\xa3\x4c\xb8\x7a\x95\x0e\x46\x48\x86\xc6\x59\xa6\xfd\x94\xac\x5d\x0f\xcb\xb3\x79\x8d\xbd\x3b\x93\x3c\x99\x61\xc3\x55\xbc\xf4\x34\xee\xae\x23\xe0\x53\xab\xaf\xf4\xc0\x8e\xcc\x3e\x1b\x88\x4e\xba\x0f\xbb\x1b\xfe\xa2\xf8\x37\xba\x3f\xfe\x0c\x7c\x68\xc5\xe5\x3f\x29\xea\xbb\x68\x7b\x7d\x78\x76\xeb\x2c\x7f\x38\x9b\x0f\xe5\x71\x9c\x95\x9f\x6e\x9c\x80\x77\xb3\xbe\x70\xff\xa7\xbe\x43\x85\xf0\xc1\x71\x42\xef\x50\xb8\x77\xe2\x3e\xb5\x9f\x67\x6d\x3b\x50\x13\xee\xbf\xc9\xfe\x28\xe8\xcb\x81\xf1\x59\x8f\x63\x6b\xb9\x6f\xe2\x77\xa3\x43\xbf\x23\x73\x0e\xfa\xc0\x07\xfd\x30\x09\xbf\x0c\x53\xd4\x29\x68\xa6\xce\x50\x5f\xa5\x92\xa9\xf3\xd4\x15\xca\x4d\xfd\x1e\xf5\x7b\x54\x21\x35\x44\xfd\x27\xea\x08\x75\x87\xfa\x4b\xea\x9f\x50\x4b\xd4\xdf\x51\x5f\xa4\x36\xa8\xff\x41\x7d\x95\xda\xa4\xbf\x48\x7d\x8d\xfb\x09\xee\x6f\xd0\x14\x77\x98\x77\x84\xf6\xf0\x8e\xf2\x06\xe8\x59\xfe\x3a\x7f\x9d\xb1\x0a\x7e\x45\xf0\x2b\x4c\xa2\xa0\x56\xd0\xc0\xd8\x04\x5f\x10\x7c\x81\x71\x0b\xda\x04\x6d\x8c\x07\xbf\x23\xf3\xec\xf5\x77\x2f\xb1\x9e\x48\x1d\x4c\x35\x00\x9d\x3a\x02\x42\x26\x45\x78\x57\x38\x2b\x7c\x20\x5c\x14\x3e\x16\xae\x08\x9f\x09\x37\x84\x5b\xc2\x9d\x68\x3a\x5a\x10\x2d\x8a\x96\x47\x6b\xa3\x8d\xd1\xd6\x68\x47\xb4\x37\x3a\x33\x3a\x3f\xba\x38\xba\x2c\xba\x32\xfa\x78\x74\x4d\x74\x7d\x74\x53\xf4\xc9\xe8\xf6\xe8\x53\xd1\x67\xa3\xcf\x47\x5f\x8c\xbe\x1c\xdd\x17\x7d\x35\x7a\x28\x7a\x24\x7a\x3c\xfa\x66\xf4\x74\xf4\x9d\xe8\x7b\xd1\x73\xd1\x0b\xd1\x8f\xa2\x9f\x44\x3f\x8d\x5e\x8b\x7e\x1e\xbd\x1d\xbd\x2b\xe2\x88\x22\x45\x62\x91\x52\xa4\x13\x99\x44\x36\x91\x4b\xe4\x13\x65\x8b\x0a\x45\x25\xa2\x72\x51\x95\xa8\x5a\x54\x2b\x6a\x10\x35\x8b\x5a\x45\x1d\xa2\xd3\xa2\x73\xa2\x6e\xd1\x25\x51\xaf\xa8\x5f\x34\x28\x1a\x16\x8d\x8a\x6e\x88\x26\x45\xb7\x44\x33\xa2\xfb\xa2\x79\xd1\x43\xd1\x92\x68\x59\xb4\x2a\x5a\x17\x6d\x8a\x5e\xc4\x40\x0c\x2f\x46\x18\x23\x8d\x51\xc7\x18\x62\xcc\x31\xf6\x18\x4f\x4c\x7a\x4c\x6e\x4c\x51\x4c\x69\x4c\x45\xcc\xb1\x98\x13\x31\x75\x31\x8d\x31\x2d\x31\x6d\x31\x9d\x31\x67\x62\xba\x62\x2e\xc4\xf4\xc4\x5c\x89\x19\x88\xb9\x16\x73\x3d\x66\x2c\x66\x22\x66\x2a\xe6\x76\xcc\xdd\x98\xd9\x98\x07\x31\x8b\x31\x8f\x63\x56\x62\x9e\xc5\x6c\xc4\x6c\xc5\xec\x88\x69\xb1\x40\x2c\x12\xcb\xc5\x5a\xb1\x51\x6c\x15\x3b\xc4\x5e\x71\xa6\x38\x5f\x5c\x2c\x2e\x13\x57\x8a\x8f\x8b\x6b\xc4\xf5\xe2\x26\xf1\x49\x71\xbb\xf8\x94\xf8\xac\xf8\xbc\xf8\xa2\xf8\xb2\xb8\x4f\x7c\x55\x3c\x24\x1e\x11\x8f\x8b\x6f\x8a\xa7\xc5\x77\xc4\xf7\xc4\x73\xe2\x05\xf1\x23\xf1\x13\xf1\x53\xf1\x9a\xf8\xb9\x78\x5b\xbc\x2b\xe1\x48\x22\x25\x62\x89\x52\xa2\x93\x98\x24\x36\x89\x4b\xe2\x93\x64\x4b\x0a\x25\x25\x92\x72\x49\x95\xa4\x5a\x52\x2b\x69\x90\x34\x4b\x5a\x25\x1d\x92\xd3\x92\x73\x92\x6e\xc9\x25\x49\xaf\xa4\x5f\x32\x28\x19\x96\x8c\x4a\x6e\x48\x26\x25\xb7\x24\x33\x92\xfb\x92\x79\xc9\x43\xc9\x92\x64\x59\xb2\x2a\x59\x97\x6c\x4a\x5e\x48\x41\xca\x93\x0a\xa5\x52\xa9\x5a\x6a\x90\x9a\xa5\x76\xa9\x47\x9a\x2e\xcd\x95\x16\x49\x4b\xa5\x15\xd2\x63\xd2\x13\xd2\x3a\x69\xa3\xb4\x45\xda\x26\xed\x94\x9e\x91\x76\x49\x2f\x48\x7b\xa4\x57\xa4\x03\xd2\x6b\xd2\xeb\xd2\x31\xe9\x84\x74\x4a\x7a\x5b\x7a\x57\x3a\x2b\x7d\x20\x5d\x94\x3e\x96\xae\x48\x9f\x49\x37\xa4\x5b\xd2\x1d\x19\x2d\x13\xc8\x44\x32\xb9\x4c\x2b\x33\xca\xac\x32\x87\xcc\x2b\xcb\x94\xe5\xcb\x8a\x65\x65\xb2\x4a\xd9\x71\x59\x8d\xac\x5e\xd6\x24\x3b\x29\x6b\x97\x9d\x92\x9d\x95\x9d\x97\x5d\x94\x5d\x96\xf5\xc9\xae\xca\x86\x64\x23\xb2\x71\xd9\x4d\xd9\xb4\xec\x8e\xec\x9e\x6c\x4e\xb6\x20\x7b\x24\x7b\x22\x7b\x2a\x5b\x93\x3d\x97\x6d\xcb\x76\xe5\x1c\x79\xa4\x5c\x2c\x57\xca\x75\x72\x93\xdc\x26\x77\xc9\x7d\xf2\x6c\x79\xa1\xbc\x44\x5e\x2e\xaf\x92\x57\xcb\x6b\xe5\x0d\xf2\x66\x79\xab\xbc\x43\x7e\x5a\x7e\x4e\xde\x2d\xbf\x24\xef\x95\xf7\xcb\x07\xe5\xc3\xf2\x51\xf9\x0d\xf9\xa4\xfc\x96\x7c\x46\x7e\x5f\x3e\x2f\x7f\x28\x5f\x92\x2f\xcb\x57\xe5\xeb\xf2\x4d\xf9\x0b\x05\x28\x78\x0a\xa1\x42\xaa\x50\x2b\x0c\x0a\xb3\xc2\xae\xf0\x28\xd2\x15\xb9\x8a\x22\x45\xa9\xa2\x42\x71\x4c\x71\x42\x51\xa7\x68\x54\xb4\x28\xda\x14\x9d\x8a\x33\x8a\x2e\xc5\x05\x45\x8f\xe2\x8a\x62\x40\x71\x4d\x71\x5d\x31\xa6\x98\x50\x4c\x29\x6e\x2b\xee\x2a\x66\x15\x0f\x14\x8b\x8a\xc7\x8a\x15\xc5\x33\xc5\x86\x62\x4b\xb1\xa3\xa4\x95\x02\xa5\x48\x29\x57\x6a\x95\x46\xa5\x55\xe9\x50\x7a\x95\x99\xca\x7c\x65\xb1\xb2\x4c\x59\xa9\x3c\xae\xac\x51\xd6\x2b\x9b\x94\x27\x95\xed\xca\x53\xca\xb3\xca\xf3\xca\x8b\xca\xcb\xca\x3e\xe5\x55\xe5\x90\x72\x44\x39\xae\xbc\xa9\x9c\x56\xde\x51\xde\x53\xce\x29\x17\x94\x8f\x94\x4f\x94\x4f\x95\x6b\xca\xe7\xca\x6d\xe5\xae\x8a\xa3\x8a\x54\x89\x55\x4a\x95\x4e\x65\x52\xd9\x54\x2e\x95\x4f\x95\xad\x2a\x54\x95\xa8\xca\x55\x55\xaa\x6a\x55\xad\xaa\x41\xd5\xac\x6a\x55\x75\xa8\x4e\xab\xce\xa9\xba\x55\x97\x54\xbd\xaa\x7e\xd5\xa0\x6a\x58\x35\xaa\xba\xa1\x9a\x54\xdd\x52\xcd\xa8\xee\xab\xe6\x55\x0f\x55\x4b\xaa\x65\xd5\xaa\x6a\x5d\xb5\xa9\x7a\xa1\x06\x35\x4f\x2d\x54\x4b\xd5\x6a\xb5\x41\x6d\x56\xdb\xd5\x1e\x75\xba\x3a\x57\x5d\xa4\x2e\x55\x57\xa8\x8f\xa9\x4f\xa8\xeb\xd4\x8d\xea\x16\x75\x9b\xba\x53\x7d\x46\xdd\xa5\xbe\xa0\xee\x51\x5f\x51\x0f\xa8\xaf\xa9\xaf\xab\xc7\xd4\x13\xea\x29\xf5\x6d\xf5\x5d\xf5\xac\xfa\x81\x7a\x51\xfd\x58\xbd\xa2\x7e\xa6\xde\x50\x6f\xa9\x77\x34\xb4\x46\xa0\x11\x69\xe4\x1a\xad\xc6\xa8\xb1\x6a\x1c\x1a\xaf\x26\x53\x93\xaf\x29\xd6\x94\x69\x2a\x35\xc7\x35\x35\x9a\x7a\x4d\x93\xe6\xa4\xa6\x5d\x73\x4a\x73\x56\x73\x5e\x73\x51\x73\x59\xd3\xa7\xb9\xaa\x19\xd2\x8c\x68\xc6\x35\x37\x35\xd3\x9a\x3b\x9a\x7b\x9a\x39\xcd\x82\xe6\x91\xe6\x89\xe6\xa9\x66\x4d\xf3\x5c\xb3\xad\xd9\xd5\x72\xb4\x91\x5a\xb1\x56\xa9\xd5\x69\x4d\x5a\x9b\xd6\xa5\xf5\x69\xb3\xb5\x85\xda\x12\x6d\xb9\xb6\x4a\x5b\xad\xad\xd5\x36\x68\x9b\xb5\xad\xda\x0e\xed\x69\xed\x39\x6d\xb7\xf6\x92\xb6\x57\xdb\xaf\x1d\xd4\x0e\x6b\x47\xb5\x37\xb4\x93\xda\x5b\xda\x19\xed\x7d\xed\xbc\xf6\xa1\x76\x49\xbb\xac\x5d\xd5\xae\x6b\x37\xb5\x2f\x62\x21\x96\x17\x2b\x8c\x95\xc6\xaa\x63\x0d\xb1\xe6\x58\x7b\xac\x27\x36\x3d\x36\x37\xb6\x28\xb6\x34\xb6\x22\xf6\x58\xec\x89\xd8\xba\xd8\xc6\xd8\x96\xd8\xb6\xd8\xce\xd8\x33\xb1\x5d\xb1\x17\x62\x7b\x62\xaf\xc4\x0e\xc4\x5e\x8b\xbd\x1e\x3b\x16\x3b\x11\x3b\x15\x7b\x3b\xf6\x6e\xec\x6c\xec\x83\xd8\xc5\xd8\xc7\xb1\x2b\xb1\xcf\x62\x37\x62\xb7\x62\x77\x74\xb4\x4e\xa0\x13\xe9\xe4\x3a\xad\xce\xa8\xb3\xea\x1c\x3a\xaf\x2e\x53\x97\xaf\x2b\xd6\x95\xe9\x2a\x75\xc7\x75\x35\xba\x7a\x5d\x93\xee\xa4\xae\x5d\x77\x4a\x77\x56\x77\x5e\x77\x51\x77\x59\xd7\xa7\xbb\xaa\x1b\xd2\x8d\xe8\xc6\x75\x37\x75\xd3\xba\x3b\xba\x7b\xba\x39\xdd\x82\xee\x91\xee\x89\xee\xa9\x6e\x4d\xf7\x5c\xb7\xad\xdb\xd5\x73\xf4\x91\x7a\xb1\x5e\xa9\xd7\xe9\x4d\x7a\x9b\xde\xa5\xf7\xe9\xb3\xf5\x85\xfa\x12\x7d\xb9\xbe\x4a\x5f\xad\xaf\xd5\x37\xe8\x9b\xf5\xad\xfa\x0e\xfd\x69\xfd\x39\x7d\xb7\xfe\x92\xbe\x57\xdf\xaf\x1f\xd4\x0f\xeb\x47\xf5\x37\xf4\x93\xfa\x5b\xfa\x19\xfd\x7d\xfd\xbc\xfe\xa1\x7e\x49\xbf\xac\x5f\xd5\xaf\xeb\x37\xf5\x2f\x0c\x60\xe0\x19\x84\x06\xa9\x41\x6d\x30\x18\xcc\x06\xbb\xc1\x63\x48\x37\xe4\x1a\x8a\x0c\xa5\x86\x0a\xc3\x31\xc3\x09\x43\x9d\xa1\xd1\xd0\x62\x68\x33\x74\x1a\xce\x18\xba\x0c\x17\x0c\x3d\x86\x2b\x86\x01\xc3\x35\xc3\x75\xc3\x98\x61\xc2\x30\x65\xb8\x6d\xb8\x6b\x98\x35\x3c\x30\x2c\x1a\x1e\x1b\x56\x0c\xcf\x0c\x1b\x86\x2d\xc3\x4e\x1c\x1d\x27\x88\x13\xc5\xc9\xe3\xb4\x71\xc6\x38\x6b\x9c\x23\xce\x1b\x97\x19\x97\x1f\x57\x1c\x57\x16\x57\x19\x77\x3c\xae\x26\xae\x3e\xae\x29\xee\x64\x5c\x7b\xdc\xa9\xb8\xb3\x71\xe7\xe3\x2e\xc6\x5d\x8e\xeb\x8b\xbb\x1a\x37\x14\x37\x12\x37\x1e\x77\x33\x6e\x3a\xee\x4e\xdc\xbd\xb8\xb9\xb8\x85\xb8\x47\x71\x4f\xe2\x9e\xc6\xad\xc5\x3d\x8f\xdb\x8e\xdb\x35\x72\x8c\x91\x46\xb1\x51\x69\xd4\x19\x4d\x46\x9b\xd1\x65\xf4\x19\xb3\x8d\x85\xc6\x12\x63\xb9\xb1\xca\x58\x6d\xac\x35\x36\x18\x9b\x8d\xad\xc6\x0e\xe3\x69\xe3\x39\x63\xb7\xf1\x92\xb1\xd7\xd8\x6f\x1c\x34\x0e\x1b\x47\x8d\x37\x8c\x93\xc6\x5b\xc6\x19\xe3\x7d\xe3\xbc\xf1\xa1\x71\xc9\xb8\x6c\x5c\x35\xae\x1b\x37\x8d\x2f\xe2\x21\x9e\x17\x2f\x8c\x97\xc6\xab\xe3\x0d\xf1\xe6\x78\x7b\xbc\x27\x3e\x3d\x3e\x37\xbe\x28\xbe\x34\xbe\x22\xfe\x58\xfc\x89\xf8\xba\xf8\xc6\xf8\x96\xf8\xb6\xf8\xce\xf8\x33\xf1\x5d\xf1\x17\xe2\x7b\xe2\xaf\xc4\x0f\xc4\x5f\x8b\xbf\x1e\x3f\x16\x3f\x11\x3f\x15\x7f\x3b\xfe\x6e\xfc\x6c\xfc\x83\xf8\xc5\xf8\xc7\xf1\x2b\xf1\xcf\xe2\x37\xe2\xb7\xe2\x77\x4c\xb4\x49\x60\x12\x99\xe4\x26\xad\xc9\x68\xb2\x9a\x1c\x26\xaf\x29\xd3\x94\x6f\x2a\x36\x95\x99\x2a\x4d\xc7\x4d\x35\xa6\x7a\x53\x93\xe9\xa4\xa9\xdd\x74\xca\x74\xd6\x74\xde\x74\xd1\x74\xd9\xd4\x67\xba\x6a\x1a\x32\x8d\x98\xc6\x4d\x37\x4d\xd3\xa6\x3b\xa6\x7b\xa6\x39\xd3\x82\xe9\x91\xe9\x89\xe9\xa9\x69\xcd\xf4\xdc\xb4\x6d\xda\x4d\xe0\x24\x44\x26\x88\x13\x94\x09\xba\x04\x53\x82\x2d\xc1\x95\xe0\x4b\xc8\x4e\x28\x4c\x28\x49\x28\x4f\xa8\x4a\xa8\x4e\xa8\x4d\x68\x48\x68\x4e\x68\x4d\xe8\x48\x38\x9d\x70\x2e\xa1\x3b\xe1\x52\x42\x6f\x42\x7f\xc2\x60\xc2\x70\xc2\x68\xc2\x8d\x84\xc9\x84\x5b\x09\x33\x09\xf7\x13\xe6\x13\x1e\x26\x2c\x25\x2c\x27\xac\x26\xac\x27\x6c\x26\xbc\x30\x83\x99\x67\x16\x9a\xa5\x66\xb5\xd9\x60\x36\x9b\xed\x66\x8f\x39\xdd\x9c\x6b\x2e\x32\x97\x9a\x2b\xcc\xc7\xcc\x27\xcc\x75\xe6\x46\x73\x8b\xb9\xcd\xdc\x69\x3e\x63\xee\x32\x5f\x30\xf7\x98\xaf\x98\x07\xcc\xd7\xcc\xd7\xcd\x63\xe6\x09\xf3\x94\xf9\xb6\xf9\xae\x79\xd6\xfc\xc0\xbc\x68\x7e\x6c\x5e\x31\x3f\x33\x6f\x98\xb7\xcc\x3b\x16\xda\x22\xb0\x88\x2c\x72\x8b\xd6\x62\xb4\x58\x2d\x0e\x8b\xd7\x92\x69\xc9\xb7\x14\x5b\xca\x2c\x95\x96\xe3\x96\x1a\x4b\xbd\xa5\xc9\x72\xd2\xd2\x6e\x39\x65\x39\x6b\x39\x6f\xb9\x68\xb9\x6c\xe9\xb3\x5c\xb5\x0c\x59\x46\x2c\xe3\x96\x9b\x96\x69\xcb\x1d\xcb\x3d\xcb\x9c\x65\xc1\xf2\xc8\xf2\xc4\xf2\xd4\xb2\x66\x79\x6e\xd9\xb6\xec\x5a\x39\xd6\x48\xab\xd8\xaa\xb4\xea\xac\x26\xab\xcd\xea\xb2\xfa\xac\xd9\xd6\x42\x6b\x89\xb5\xdc\x5a\x65\xad\xb6\xd6\x5a\x1b\xac\xcd\xd6\x56\x6b\x87\xf5\xb4\xf5\x9c\xb5\xdb\x7a\xc9\xda\x6b\xed\xb7\x0e\x5a\x87\xad\xa3\xd6\x1b\xd6\x49\xeb\x2d\xeb\x8c\xf5\xbe\x75\xde\xfa\xd0\xba\x64\x5d\xb6\xae\x5a\xd7\xad\x9b\xd6\x17\x89\x90\xc8\x4b\x14\x26\x4a\x13\xd5\x89\x86\x44\x73\xa2\x3d\xd1\x93\x98\x9e\x98\x9b\x58\x94\x58\x9a\x58\x91\x78\x2c\xf1\x44\x62\x5d\x62\x63\x62\x4b\x62\x5b\x62\x67\xe2\x99\xc4\xae\xc4\x0b\x89\x3d\x89\x57\x12\x07\x12\xaf\x25\x5e\x4f\x1c\x4b\x9c\x48\x9c\x4a\xbc\x9d\x78\x37\x71\x36\xf1\x41\xe2\x62\xe2\xe3\xc4\x95\xc4\x67\x89\x1b\x89\x5b\x89\x3b\x36\xda\x26\xb0\x89\x6c\x72\x9b\xd6\x66\xb4\x59\x6d\x0e\x9b\xd7\x96\x69\xcb\xb7\x15\xdb\xca\x6c\x95\xb6\xe3\xb6\x1a\x5b\xbd\xad\xc9\x76\xd2\xd6\x6e\x3b\x65\x3b\x6b\x3b\x6f\xbb\x68\xbb\x6c\xeb\xb3\x5d\xb5\x0d\xd9\x46\x6c\xe3\xb6\x9b\xb6\x69\xdb\x1d\xdb\x3d\xdb\x9c\x6d\xc1\xf6\xc8\xf6\xc4\xf6\xd4\xb6\x66\x7b\x6e\xdb\xb6\xed\x26\x71\x92\x22\x93\xc4\x49\xca\x24\x5d\x92\x29\xc9\x96\xe4\x4a\xf2\x25\x65\x27\x15\x26\x95\x24\x95\x27\x55\x25\x55\x27\xd5\x26\x35\x24\x35\x27\xb5\x26\x75\x24\x9d\x4e\x3a\x97\xd4\x9d\x74\x29\xa9\x37\xa9\x3f\x69\x30\x69\x38\x69\x34\xe9\x46\xd2\x64\xd2\xad\xa4\x99\xa4\xfb\x49\xf3\x49\x0f\x93\x96\x92\x96\x93\x56\x93\xd6\x93\x36\x93\x5e\xd8\xc1\xce\xb3\x0b\xed\x52\xbb\xda\x6e\xb0\x9b\xed\x76\xbb\xc7\x9e\x6e\xcf\xb5\x17\xd9\x4b\xed\x15\xf6\x63\xf6\x13\xf6\x3a\x7b\xa3\xbd\xc5\xde\x66\xef\xb4\x9f\xb1\x77\xd9\x2f\xd8\x7b\xec\x57\xec\x03\xf6\x6b\xf6\xeb\xf6\x31\xfb\x84\x7d\xca\x7e\xdb\x7e\xd7\x3e\x6b\x7f\x60\x5f\xb4\x3f\xb6\xaf\xd8\x9f\xd9\x37\xec\x5b\xf6\x9d\x64\x3a\x59\x90\x2c\x4a\x96\x27\x6b\x93\x8d\xc9\xd6\x64\x47\xb2\x37\x39\x33\x39\x3f\xb9\x38\xb9\x2c\xb9\x32\xf9\x78\x72\x4d\x72\x7d\x72\x53\xf2\xc9\xe4\xf6\xe4\x53\xc9\x67\x93\xcf\x27\x5f\x4c\xbe\x9c\xdc\x97\x7c\x35\x79\x28\x79\x24\x79\x3c\xf9\x66\xf2\x74\xf2\x9d\xe4\x7b\xc9\x73\xc9\x0b\xc9\x8f\x92\x9f\x24\x3f\x4d\x5e\x4b\x7e\x9e\xbc\x9d\xbc\xeb\xe0\x38\x22\x1d\x62\x87\xd2\xa1\x73\x98\x1c\x36\x87\xcb\xe1\x73\x64\x3b\x0a\x1d\x25\x8e\x72\x47\x95\xa3\xda\x51\xeb\x68\x70\x34\x3b\x5a\x1d\x1d\x8e\xd3\x8e\x73\x8e\x6e\xc7\x25\x47\xaf\xa3\xdf\x31\xe8\x18\x76\x8c\x3a\x6e\x38\x26\x1d\xb7\x1c\x33\x8e\xfb\x8e\x79\xc7\x43\xc7\x92\x63\xd9\xb1\xea\x58\x77\x6c\x3a\x5e\x38\xc1\xc9\x73\x0a\x9d\x52\xa7\xda\x69\x70\x9a\x9d\x76\xa7\xc7\x99\xee\xcc\x75\x16\x39\x4b\x9d\x15\xce\x63\xce\x13\xce\x3a\x67\xa3\xb3\xc5\xd9\xe6\xec\x74\x9e\x71\x76\x39\x2f\x38\x7b\x9c\x57\x9c\x03\xce\x6b\xce\xeb\xce\x31\xe7\x84\x73\xca\x79\xdb\x79\xd7\x39\xeb\x7c\xe0\x5c\x74\x3e\x76\xae\x38\x9f\x39\x37\x9c\x5b\xce\x1d\x17\xed\x12\xb8\x44\x2e\xb9\x4b\xeb\x32\xba\xac\x2e\x87\xcb\xeb\xca\x74\xe5\xbb\x8a\x5d\x65\xae\x4a\xd7\x71\x57\x8d\xab\xde\xd5\xe4\x3a\xe9\x6a\x77\x9d\x72\x9d\x75\x9d\x77\x5d\x74\x5d\x76\xf5\xb9\xae\xba\x86\x5c\x23\xae\x71\xd7\x4d\xd7\xb4\xeb\x8e\xeb\x9e\x6b\xce\xb5\xe0\x7a\xe4\x7a\xe2\x7a\xea\x5a\x73\x3d\x77\x6d\xbb\x76\xdd\x1c\x77\xa4\x5b\xec\x56\xba\x75\x6e\x93\xdb\xe6\x76\xb9\x7d\xee\x6c\x77\xa1\xbb\xc4\x5d\xee\xae\x72\x57\xbb\x6b\xdd\x0d\xee\x66\x77\xab\xbb\xc3\x7d\xda\x7d\xce\xdd\xed\xbe\xe4\xee\x75\xf7\xbb\x07\xdd\xc3\xee\x51\xf7\x0d\xf7\xa4\xfb\x96\x7b\xc6\x7d\xdf\x3d\xef\x7e\xe8\x5e\x72\x2f\xbb\x57\xdd\xeb\xee\x4d\xf7\x0b\x0f\x78\x78\x1e\xa1\x47\xea\x51\x7b\x0c\x1e\xb3\xc7\xee\xf1\x78\xd2\x3d\xb9\x9e\x22\x4f\xa9\xa7\xc2\x73\xcc\x73\xc2\x53\xe7\x69\xf4\xb4\x78\xda\x3c\x9d\x9e\x33\x9e\x2e\xcf\x05\x4f\x8f\xe7\x8a\x67\xc0\x73\xcd\x73\xdd\x33\xe6\x99\xf0\x4c\x79\x6e\x7b\xee\x7a\x66\x3d\x0f\x3c\x8b\x9e\xc7\x9e\x15\xcf\x33\xcf\x86\x67\xcb\xb3\x93\x42\xa7\x08\x52\x44\x29\xf2\x14\x6d\x8a\x31\xc5\x9a\xe2\x48\xf1\xa6\x64\xa6\xe4\xa7\x14\xa7\x94\xa5\x54\xa6\x1c\x4f\xa9\x49\xa9\x4f\x69\x4a\x39\x99\xd2\x9e\x72\x2a\xe5\x6c\xca\xf9\x94\x8b\x29\x97\x53\xfa\x52\xae\xa6\x0c\xa5\x8c\xa4\x8c\xa7\xdc\x4c\x99\x4e\xb9\x93\x72\x2f\x65\x2e\x65\x21\xe5\x51\xca\x93\x94\xa7\x29\x6b\x29\xcf\x53\xb6\x53\x76\xbd\x1c\x6f\xa4\x57\xec\x55\x7a\x75\x5e\x93\xd7\xe6\x75\x79\x7d\xde\x6c\x6f\xa1\xb7\xc4\x5b\xee\xad\xf2\x56\x7b\x6b\xbd\x0d\xde\x66\x6f\xab\xb7\xc3\x7b\xda\x7b\xce\xdb\xed\xbd\xe4\xed\xf5\xf6\x7b\x07\xbd\xc3\xde\x51\xef\x0d\xef\xa4\xf7\x96\x77\xc6\x7b\xdf\x3b\xef\x7d\xe8\x5d\xf2\x2e\x7b\x57\xbd\xeb\xde\x4d\xef\x8b\x54\x48\xe5\xa5\x0a\x81\xe2\xf2\xf0\x3b\xaf\xe0\xa7\x9c\x2d\x82\xff\x49\x90\xe7\x36\x13\xf8\x71\x82\x2f\x20\x64\xbe\x4e\xf0\xfd\x41\x9e\x11\x07\x79\x7a\x98\x78\xf6\x6f\x08\xde\x12\xe4\xf9\x91\x41\x9e\x47\xf0\xdc\xbf\x20\xe4\xff\x3a\x0c\xfe\x63\x82\xcf\x0b\xb3\xce\x6f\x10\xf8\x24\x31\x6f\x22\x81\xff\x25\xc1\x7f\x8d\xe0\xcb\x08\xfe\x7b\x04\xff\x7d\x62\xbf\x7f\x15\x46\xe6\x4b\x84\x1e\x76\xc2\xc8\xfc\x88\x90\xa9\x3b\x98\xe7\x7c\xf3\x60\x9c\x9f\x77\xf0\x38\x9c\xb1\x83\xd7\x49\xce\xcb\xd4\x12\xfc\x0f\x08\xbe\x34\xcc\x98\x1a\xe2\x8c\x2a\x0e\xd6\x33\x87\xd0\x27\x33\x44\xe8\x9f\xf7\x76\x78\x7e\xd2\xc1\xb6\x1a\x62\x9f\x6f\xc0\x93\xf6\xf9\x26\x3c\xe9\x0b\xe1\xec\xf3\x67\xe2\xbf\x71\x38\x3e\xc4\x3e\x09\xbb\xe5\x96\x84\xb1\xb1\x9f\x81\xe7\xbd\x08\x63\xe7\x5f\x3a\x1c\x1f\xce\xb6\xc3\xda\xfc\xd5\x37\xb0\xed\x9f\x85\xff\xd1\x21\x79\x32\x56\x7c\xff\x60\x3c\x24\xae\x7e\xef\xa7\xc7\x49\xdb\x0e\xd1\xf9\x5b\xc2\x43\x62\xfb\xf7\x3e\x1a\x0f\xf1\xa3\x2f\xfd\xaf\xc3\xc9\xfc\x12\xb2\xce\xb7\x85\xf7\x1f\x7c\xd6\xe1\xf0\x90\xbc\x56\xf7\xbf\x0e\xe7\xde\x3c\x78\xfd\x64\x6e\x0d\xf1\x1d\x32\xcf\x7e\x33\x0c\x6f\x09\xf3\xec\xcf\x80\x33\x5f\x09\x23\x4f\xf8\x32\x19\x3f\x49\xdd\x1e\x16\xe7\x0e\xbf\x81\x0c\x59\x27\x8c\xfd\xf4\x38\x3f\x8d\xe0\x45\x84\x0c\x51\x7b\x90\xf9\xf4\xd0\x38\x91\xc7\xc9\x5c\xfc\xd6\x70\x22\x47\x87\xe4\xf7\x43\xe2\x21\x39\xe8\x47\xbf\x78\x9c\xac\xdf\x42\x6a\x12\x32\x3f\x26\x86\xc1\x89\xba\x8e\xac\x55\x0e\x8b\xd3\x64\xbc\xfd\x7e\x18\x5b\x9a\x0e\x23\x13\x4f\xe0\x44\x5d\x1a\x52\xdb\xbc\x41\x0c\xe7\x95\x87\x99\x2b\x5c\x7e\x27\xe2\x2d\x97\x3c\xf7\x3f\x39\xd8\x06\x38\x4d\xfc\x83\x63\x29\x59\x4b\x57\xf1\x0f\x8c\x63\x24\x1f\x2e\x2e\x85\xc4\x93\xdf\x25\xc6\xdc\xe4\x1f\xca\xc7\x79\x4e\x02\x27\xe2\x8f\x60\x9c\x18\x33\x81\x90\xf9\xfe\xc1\xe7\x12\xee\x4e\x11\xe2\x53\xd5\xc4\xfa\x89\xf8\x1c\xe2\x47\x03\x61\x70\x42\xb7\xbc\x54\x62\x3d\xc4\x3a\xb9\x3f\x24\xe4\xc9\x3b\x1a\xb9\x86\x2f\xbf\x81\xdd\x7e\x31\x0c\x4f\x3e\x4b\xac\x8d\xf9\xd3\x83\x75\x12\x31\x41\xf0\x44\x0c\x14\x34\x10\x7b\x21\xd6\xcc\x0b\x93\x73\xc9\xb3\x10\x10\x36\x4c\xc6\xd8\x70\x75\x51\xd8\xfc\x18\x2e\x9e\x87\x89\x1b\x64\x8d\x41\xde\x29\xc8\x5a\xf7\xb0\xb5\x44\x38\xdb\x3e\x6c\xae\x09\x39\xa3\x30\xb5\x71\xc4\xe0\x47\x9f\x45\xb8\x75\x0a\xc8\x7b\x0d\xb9\xf7\x70\xfe\x75\xd8\xda\xf5\x90\x35\xde\xa1\x6b\xa1\xc3\xea\xf3\x90\xb9\xf8\xb0\x39\x28\x6c\x0e\x25\x63\xe9\xfb\xc4\x38\xe1\x6a\xce\x1f\x87\xd1\xf3\x36\xc1\x0b\xf8\x1f\xe9\xef\x87\x3d\x97\xb0\x7a\x0b\x93\x43\x19\x22\xce\x73\xff\x9c\xc0\x1b\x0f\x3e\x2f\x32\xde\x86\xc4\x5e\x72\x9d\xe1\xee\x2f\x96\x30\x7a\xfe\xc1\xc1\x7b\x67\x7e\x74\x30\x4f\xc6\xcf\x90\x73\xfc\xb3\x8f\xd6\x4f\xb8\x1a\x9b\xbb\x15\x46\xcf\xe1\xec\x2d\x5c\x4d\x32\x12\x66\x9c\x30\xb9\x29\x44\x3f\x10\xe6\x59\x92\x2f\x0f\x73\xee\x64\x3f\x2a\x96\xe0\x53\x08\x99\x22\x02\xff\xe1\xc1\x7a\x08\x3b\x2f\x79\x67\x21\x7a\x47\x9c\xda\x83\xed\x3f\x1c\x1f\xd2\x1f\xd8\x20\xf8\x1f\x1c\x6c\x93\x4c\x52\x98\xf3\x22\xf2\x1a\xd9\x37\x0b\xc7\x87\x5b\x0f\xb7\x86\x7f\xa0\xbf\xf0\xc8\x3b\x0e\xe1\x0b\xbc\xd8\x83\xed\xe1\xd0\x3c\xe1\x2f\xf4\x4f\x0e\x5e\x03\xc9\x93\x3e\x12\xb6\xdf\xf2\xc5\x83\x71\x32\x8e\x85\xeb\x07\x72\x89\x7d\x71\x53\x0f\x3e\xeb\x90\x9a\x9c\xb4\xf9\x70\xb5\x0a\x59\x93\xd4\x1d\xcc\x87\xf3\xf1\x10\x7f\xd7\xf3\x0f\x8e\x6f\x57\x0e\xb6\xe7\x10\x5b\x5d\x0f\x63\xe7\x44\x4e\x67\x46\x0f\xb6\xf9\x70\xeb\xe1\x13\x7e\x27\x20\xeb\x52\xc2\x37\x79\x6e\x62\x4c\x22\xae\xf2\x88\xb5\x85\xd4\x48\xc3\x07\x9f\x05\x87\xbc\x53\x10\xb5\x56\x48\x4d\x4b\xf2\x61\xfa\xc3\x64\xbf\x3a\xac\x5f\x7c\xff\xa3\x6d\x35\x5c\x6f\x39\xe4\xdc\xc9\xb8\x41\xe6\x38\x62\x4c\x81\x3e\x8c\x0d\x6f\x1c\xbc\x1e\x2e\x27\x8c\x7e\xc2\xec\x37\xc4\x6e\x4b\x0f\x3e\xf7\x37\xea\xbd\x87\xd3\x09\xa9\x87\xbf\x3d\x78\xde\x90\x1c\x17\x4e\x3f\xe1\x78\xb2\xd6\x0a\x17\xcf\x7f\xfb\xe0\xbd\x90\x39\x25\xc4\xe6\xc9\x7d\x91\x7d\x80\x70\x35\xc6\x56\x18\x3d\x1f\x16\x7f\x4b\x7d\xcb\xb7\x85\xff\xa2\xfa\x9f\xa4\x3d\x90\xfe\xf8\xb6\xfa\x99\x6f\x0b\x3f\x6c\x0d\x1f\xb6\x3f\x79\x58\xfc\xe7\xd0\xc3\x0c\xf1\x71\xe2\x4e\x14\x52\x27\x1c\x12\x7f\x5b\x3d\xcf\x9f\x77\x9f\x33\xec\x5d\x80\xf8\xec\x35\xc4\x4f\xc3\xe1\x6f\xab\x2f\xfa\x8b\xea\x97\xfe\x9c\xfb\xa8\xff\xbb\xf5\x57\x43\x7a\x8f\x9a\x8f\xc6\xc3\xf5\x5d\x7f\xde\x78\xc8\x67\xf4\x05\x6f\x80\x87\xbb\x73\xbd\xa5\xde\x6f\x48\x0c\x2c\x0d\xb3\x66\x72\x5e\xb2\xbe\x22\xf3\xda\x5b\xfa\xdc\xf0\xff\xaf\xf8\x2f\x2c\xff\xbe\x25\xfc\xe7\xdd\xe3\xfa\x45\xe1\xe1\xfa\xed\x3f\x6f\xfc\xb0\xf1\x2d\x5c\x8f\xfd\xe7\x8d\xbf\xd1\xe7\x50\x3f\x03\xce\x84\xbb\x0b\xbc\x41\x9d\x13\x92\xbb\xc3\xf4\x1e\x43\x72\x56\x25\xb1\xdf\xe0\x5d\xec\x17\xff\xc6\x0e\x1d\xf8\x1b\x16\x10\xf8\x3d\xf6\x54\xe0\xf7\xd8\x53\x60\x06\xea\xe5\x00\xa7\xec\x20\xfa\xf1\x3b\x3d\x1f\xbf\xd3\xf3\xf1\x3b\x3d\x1f\xbf\xd3\xf3\xf1\x3b\x3d\x1f\xbf\xd3\xf3\xf1\x3b\x3d\x1f\xbf\xd3\xf3\xf1\x3b\x3d\x1f\xbf\xd3\xf3\xf1\x3b\x3d\x1f\xbf\xd3\xf3\xff\xe5\x77\x7a\x78\x9c\xd7\xbf\x87\x67\x0b\xff\xda\xd8\x16\xf2\x3f\x41\xfe\x27\xf8\x3b\x76\x9a\x51\xa6\x19\xf1\xe3\x88\x1f\x47\xbe\x00\xf9\x02\x94\xf9\x3a\xca\x7c\x1d\xf9\x7e\xe4\xfb\xf1\xb7\xfd\xe0\xdf\x2e\x63\xc4\xf8\x9b\x7c\x86\xf1\x37\xd8\x0f\xe3\xb3\x7f\x83\xcf\xfe\x0d\xf2\x16\xe4\x2d\x7e\x9e\x1f\xe9\xe7\xf9\x91\xf8\x9b\x85\x90\xe7\x21\xcf\xfd\x0b\x1c\xf3\x2f\x50\xfe\xaf\x51\xfe\xaf\xf7\xe1\x3f\x46\xfc\xc7\xc8\xe7\x21\x9f\xb7\x6f\x9d\xdf\x40\xf9\x6f\x20\x3e\x89\xf8\x24\xce\x9b\x88\xf3\x26\x22\xfe\x97\x88\xff\x25\xf2\x5f\x43\xfe\x6b\xc8\x97\x21\x5f\x86\xfc\xf7\x90\xff\x1e\xf2\xdf\x47\xfe\xfb\xb8\xdf\xbf\xc2\xfd\xfe\xd5\x3e\x99\x2f\x21\xff\x25\xd4\xc3\x0e\xea\x61\x67\x9f\xcc\x8f\x90\xff\x11\xca\xd4\xa1\x4c\xdd\x5e\x9e\xf3\x4d\x94\xf9\xe6\x5e\x9c\x8f\xfb\xe5\xe7\xed\x1d\x87\x33\x86\xfc\xd8\xde\x75\x92\xf3\x32\xb5\xb8\xe6\x5a\xe4\x7f\x80\xfc\x0f\x90\x2f\x45\xbe\x74\xdf\x98\x1a\xe4\x35\x78\x46\x15\x78\x46\x15\x7b\xf5\xcc\x41\x7d\x72\x50\x9f\xcc\x10\x8e\xc3\xfe\xbe\x26\xec\xd5\xbd\xfa\xed\x4f\x3f\x3d\xcf\x7e\xff\x8e\x9f\xc4\xda\x2a\x76\x1a\x7e\xc2\xda\x27\xf2\xc7\xdf\x94\x67\x7b\x69\xac\x7d\xbe\x09\xcf\x7e\xd6\xc7\xfa\x02\xfb\xb9\xca\x2b\xfb\x64\x3b\x5e\x3f\x33\xff\x0d\xb6\x23\xf5\xa6\x3c\xdb\xe3\x09\xd8\x27\x61\xb7\xdc\x12\xb4\xf3\x92\x7d\x36\xf6\x33\xf0\xbc\x17\x78\xd6\x2f\xf6\xd9\x39\x61\xdb\x6f\xc2\x87\xb3\xed\xb0\x36\x7f\x15\x9f\xbd\xfa\xa1\xb6\xfd\xb3\xf0\xe4\x98\x6f\xc2\x13\xb6\x1d\xe2\x53\x04\x4e\xda\x2a\xa9\xc3\xf0\x38\x11\x87\x49\xfd\x13\xb6\x1d\xa2\xf3\xb7\x84\x93\xf6\x1c\xb2\x1e\x32\xe6\x93\xeb\x21\xfd\x88\x3c\xdf\x43\xe3\x44\x1e\x79\x03\x79\xf6\xb3\x6b\x36\xbf\x84\xac\xf3\xd0\x78\x30\x4f\x85\xe0\xf8\x19\x35\x9b\xb3\xd8\x1e\x30\x7b\xd6\x64\x2e\x23\x6d\x80\x8c\x09\xa4\xad\x1e\x1e\x27\xf2\xe3\x1b\xc8\x73\x6f\xe2\x7a\x6e\x06\xd6\xef\x78\xb5\x7e\xf6\xfb\x86\x6c\x6e\x0d\xf1\x1d\x32\xcf\x12\xb9\x23\x84\xb7\xb0\x5d\x5e\xf6\x59\xb6\xfb\xbb\xbb\x27\x2f\x87\x8c\xf9\x06\x38\xf3\x15\xdc\xd7\x57\xf6\xc9\xa3\x2f\xd3\x57\xf7\xc6\x4f\x52\xb7\x64\xde\x0f\xc5\x0f\x96\xe7\x62\x5d\xc1\x1d\xfe\xb0\x67\xc9\x18\x4b\xfa\xfe\x61\x71\x7e\x1a\xe6\xd9\x34\xe4\x45\xc8\x8b\x50\xe6\xc7\x6c\x47\x7c\x77\x4f\x3e\x25\x6b\x92\x50\x3c\x8c\x3c\x7e\x86\xcc\xd6\x2d\x64\x2e\x0e\x8f\x07\xeb\x9c\x37\x92\x27\x72\x74\x48\x7e\xc7\xcf\x3f\x0f\xc2\x0f\x96\x0f\xc9\x41\xa4\x9e\x7f\xee\x38\x8f\x73\x10\xce\x7e\xf6\xcb\xd6\x6f\x21\x35\x09\x99\x1f\xc9\xb8\x4d\xe2\xf8\x39\x2d\x5b\xd7\x91\xb5\xca\x61\x71\x1a\xe3\x2a\xcd\xc6\x5b\x22\x2f\x84\xd4\xa8\xd3\x88\x4f\xef\x93\x89\x47\x99\xf8\xdd\x3d\x75\x29\x59\x87\x87\x8f\xe1\xc1\x58\xcd\x2b\xc7\xbd\x97\xef\x9b\x2b\x5c\x7e\x27\xe2\x30\x17\xcf\x97\xcb\x9e\xfb\x9f\x20\xfe\x27\x7b\x6d\x80\xd3\x84\x7c\xd3\xbe\x18\x4b\xd6\xd2\x55\xe8\x17\x55\x7b\xe3\x1b\xc9\x87\x8b\x4b\x21\xf1\xe4\x77\x11\xff\x5d\x1c\x73\x13\xc7\xdc\xfc\x70\x1f\x0f\xea\x99\xe7\x44\x19\x27\xe2\x18\x7f\xb8\x18\x7f\x04\xe3\x7e\x5e\x30\x8e\x63\x26\xe0\x98\x09\x28\x83\x67\xc1\xfd\xfe\xde\x73\x09\x77\xa7\x08\xf1\xa9\x6a\xc4\xab\x71\xfd\x18\x9f\xe9\x9b\xfb\xfc\x68\x00\x65\x06\x3e\xcc\xbf\x78\xa9\xb8\xe6\x54\x5c\x0f\xae\x93\x8b\xeb\xe4\xfe\x10\xf9\x1f\xa2\x3c\x79\x47\xc3\x35\x70\xd8\x35\x7c\x19\xf9\x2f\xb3\xf6\xc9\xe3\x1c\x68\xb7\x5f\x44\xfc\x8b\xfb\x78\xf2\x59\x5c\x1b\x07\xd7\xc6\xfc\x29\x3e\xfb\xa7\x7b\x75\xc2\xbe\xd3\x13\x31\x81\x3c\xc6\xc0\x08\x8c\x81\x82\x06\xd4\x6d\x03\xee\x05\xd7\xcc\xc3\x35\xf3\x30\xe7\xf2\xf6\xe5\x5c\xf2\x2c\x04\x68\xc3\x82\xe6\xbd\x31\x36\x5c\xbd\x14\x36\x3f\x86\x8b\xe7\x61\xe2\x09\x59\x63\x90\x77\x0a\xb2\xd6\x0d\x5b\x33\x84\xa9\x31\xd8\xef\x9d\xbd\xb2\x6d\xe4\xbf\xb9\x2f\x0e\xbc\x41\xae\x61\xdf\xe9\x09\x9c\x11\xee\x91\xb3\xaf\x36\x8e\x18\x44\xfd\x0f\x7e\xd8\x59\x84\x5b\xa7\x00\xfd\x51\xc0\xde\x6b\x92\x70\x6d\xec\xde\xc3\xe5\xd9\x43\xd6\xb4\x87\xad\x09\x0f\x5b\x3b\x1d\x36\x77\x87\xcf\xd1\x07\xe3\x87\xcd\x4d\x61\x73\x2b\x19\x4b\xdf\x47\xfe\xfd\xdd\x0f\xab\x39\x31\xe6\x70\x7f\xbc\x4f\xcf\xdb\x88\x6f\x23\x2f\x40\x5e\xf0\x61\xfe\x1e\xfe\x5c\x78\x07\xd6\xde\x61\xf5\x16\x26\x87\x32\x18\xe7\x19\x8c\xf3\xdc\x3f\xc7\xf5\xfc\x39\xe2\x8d\x88\x37\xee\x3d\x2f\x32\xde\x86\xc4\x5e\xf2\xee\x43\xe4\xbb\x90\xfb\x0b\x51\x43\x86\xe8\x99\xec\x57\x10\x7b\x67\xf0\x5c\x98\x1f\xed\xe5\xc9\xf8\x19\x52\x4b\xfc\x19\xe2\x7f\xf6\x61\xfa\x21\xfb\x57\x21\x76\x88\x63\x72\xb7\xf6\xe9\x39\x5c\xed\x47\xf6\x94\xc8\x9a\x64\x04\xf9\x91\x7d\xe3\x90\xf9\x28\x5c\xaf\x09\x10\x87\x7d\xcf\x92\x3c\xd6\x06\x81\xdf\xb3\x4d\x9e\x3b\xf6\xa3\xb8\x6c\x3f\x2a\x16\xf1\x58\xe4\x53\x90\x4f\x41\x99\x22\x94\x29\x42\x1c\x63\x3b\xe7\x87\x7b\xf5\x10\x76\x5e\xcc\x89\x1c\xf6\xce\x42\xf4\x8e\x38\xa8\x13\x4e\xed\x3e\x3f\x0a\xc3\x87\xf4\x07\x36\x90\xdf\x40\x1e\x6d\x80\xfe\xc1\x5e\x9b\x64\x30\xa6\x31\x49\xfb\xce\x0b\xf3\x1a\x17\xf3\x1a\xd9\x37\x0b\xc7\x87\x5b\x0f\xb7\x06\xc7\xa9\xd9\xeb\x2f\x3c\xbc\xe3\xf0\xd8\x3b\x0e\xfa\x02\x0f\x7d\x81\x87\xba\xe5\xc5\xee\xb5\x87\x43\xf3\xe8\x2f\x0c\xfa\x0b\x8d\xfe\x42\xff\x64\x9f\xcf\x12\x3c\xe9\x23\x61\xfb\x2d\x58\x0f\xd0\x5f\xdc\x17\x7b\x89\x38\x16\xae\x1f\xc8\xc5\x7d\x71\x71\x5f\x5c\xac\x61\xb8\xa9\x7b\xcf\x3a\xa4\x26\x27\x6d\x3e\x5c\xad\x42\xd6\x24\x44\xee\x23\xf9\x70\x3e\x1e\xe2\xef\x7a\x94\xd7\xef\xee\xcd\xbf\x57\x10\xbf\xb2\xd7\x9e\x43\x6c\x75\x1d\xf9\xf5\x7d\x76\x4e\xd4\xab\xcc\x28\xce\x35\xba\xd7\xe6\xc3\xad\x87\x8f\x7e\xc7\x47\xbf\x13\x60\x4c\x13\xb0\x75\x29\xfa\xa6\x00\x7d\x93\xe7\x46\x5d\xb9\x71\x4c\x8c\xab\x1c\x8c\xab\x3c\x5c\x1b\x0f\xd7\x16\x52\x23\x11\xf7\x5f\xf2\x2c\x38\x78\xa7\xe0\xb0\x77\x0a\xac\xb5\x38\xe3\x7b\xe3\x52\x08\x1f\xa6\x3f\x4c\xf6\xab\xc3\xfa\x05\x19\x97\xc2\xd8\x6a\xb8\xde\x72\xc8\xb9\x93\x71\x03\x73\x1c\x47\xb0\x37\x56\x08\xf0\x4c\x05\xfa\x0f\x8b\x09\x21\x77\x2b\x0e\xea\x84\xb3\x4f\x3f\x61\xf6\x1b\x62\xb7\xb8\x4e\x5e\xe9\xde\x73\x7f\xa3\xde\x7b\x38\x9d\x90\x7a\xf8\x5b\xe4\xff\x76\x5f\x6c\x24\x73\x5c\x38\xfd\x84\xe3\xc9\x5a\x2b\x5c\x3c\xff\x6d\xd4\xc3\x6f\xef\xf3\x77\x22\xa7\x84\xd8\x3c\xb9\x2f\xe2\x8e\x10\xb6\x6f\x89\xef\xe8\x04\xee\x29\xa4\x9e\xc9\xfb\xcb\x9b\xe0\x6f\xa9\x6f\xf9\xb6\xf0\xd0\xda\x15\xf9\x03\x6a\x5a\x12\xe7\x1d\x58\x4b\x1c\xb6\xff\x49\xf6\x67\xd8\x77\x7a\x58\x7f\x0c\xdb\xe7\x3c\x64\x3f\xf3\xf0\xf2\x07\xe3\x6f\xd6\xcf\x24\x7a\x8c\x61\xee\x4a\x61\xfb\x96\xe1\xf0\xb0\x3d\xc9\xb7\xd3\xdb\x64\xdf\xd1\x61\x3f\x97\x0c\xa9\x13\xc2\xe2\x3c\xce\x41\xf8\xe1\x7b\x9e\x87\xc3\x43\x6b\x78\xdc\xfb\x01\x77\xa2\x9f\x1e\x67\xbf\xff\xcb\x7e\xf6\x1a\xe2\xa7\xe1\xf0\xb7\xd5\x17\x0d\x27\xff\xb6\xfa\xa2\x87\xc5\x43\xfa\xa5\x68\xdb\x1f\xda\x2f\x3d\x2c\x1e\xae\xcf\x79\x78\x9c\xbc\xab\x12\x7e\x1d\x06\x67\xdf\xdd\x09\xf4\x1e\xc9\x7c\x44\xf6\x24\x09\x3c\x5c\xdf\xf5\xf0\x38\x8f\x73\x18\x9c\x7d\x77\x27\xf0\x19\x3d\xd9\x9f\x0c\x87\x87\xeb\x03\x87\xed\xf1\xf2\x0e\xae\x4b\xc3\xe1\x64\x0c\x24\xec\x81\x57\xc1\x6b\x22\xea\xde\xa6\xd7\xf3\x92\xf5\x15\xbe\xd3\xc3\xf6\x8d\xc3\xe5\xd3\x3d\x77\xf9\xa6\x9f\x2f\x8e\x3a\xf9\x88\xcf\x2b\xdf\x44\xfe\x6d\xe1\x64\xfe\x3d\x64\xde\x7c\x33\xbc\xe9\xed\xe0\xe1\xea\x81\xe0\xbc\x87\xfd\x1c\xf0\xb0\x3d\xc3\x3d\x78\xd3\xdb\xc1\xc3\xe5\x85\xe0\xbc\xec\x3b\x37\xfb\xfb\xed\x6f\x0f\xe7\x1d\xd8\xcf\x7f\xb3\xb8\x47\xe4\x4d\x7c\xe7\x66\x7f\x8f\xfd\xed\xe1\xbc\x03\x7b\xf8\xe1\x3f\x87\x42\xfe\xc3\x3f\x9f\x7a\x03\x9c\x41\x1f\x61\xf6\xdf\x05\xde\xa0\xce\x21\xbf\x4f\x15\x72\x1f\x24\xef\xb3\x64\xce\xaa\x44\xbc\x12\xf7\x8b\x77\x31\x9e\xff\x2e\xf6\xbf\xc5\x3b\x3d\x8c\x81\x31\x03\x00\x1f\x28\x30\x00\x80\x9f\xb7\x03\x05\x1e\x00\x48\x07\x80\x5c\xa0\xa0\x08\x28\xfa\x77\xfc\x1c\xb5\xcd\x29\x03\x8a\x72\x22\x9d\x04\xdb\x6b\x04\x29\xfb\xd7\x11\x3f\xd1\x59\x3c\x06\xcc\x27\x6e\x81\x90\x5e\x92\xd8\x25\x1e\x49\xba\x24\x57\x52\x24\x29\x95\x54\x48\x8e\x49\x4e\x48\xea\x24\x8d\x92\x16\x49\x9b\xa4\x53\x72\x46\xd2\x25\xb9\x20\xe9\x91\x5c\x91\x0c\x48\xae\x49\xae\x4b\xc6\x24\x13\x92\x29\xc9\x6d\xc9\x5d\xc9\xac\xe4\x81\x64\x51\xf2\x58\xb2\x22\x79\x26\xd9\x90\x6c\x49\x76\xa4\xb4\x54\x20\x15\x49\xe5\x52\xad\xd4\x28\xb5\x4a\x1d\x52\xaf\x34\x53\x9a\x2f\x2d\x96\x96\x49\x2b\xa5\xc7\xa5\x35\xd2\x7a\x69\x93\xf4\xa4\xb4\x5d\x7a\x4a\x7a\x56\x7a\x5e\x7a\x51\x7a\x59\xda\x27\xbd\x2a\x1d\x92\x8e\x48\xc7\xa5\x37\xa5\xd3\xd2\x3b\xd2\x7b\xd2\x39\xe9\x82\xf4\x91\xf4\x89\xf4\xa9\x74\x4d\xfa\x5c\xba\x2d\xdd\x95\x71\x64\x91\x32\xb1\x4c\x29\xd3\xc9\x4c\x32\x9b\xcc\x25\xf3\xc9\xb2\x65\x85\xb2\x12\x59\xb9\xac\x4a\x56\x2d\xab\x95\x35\xc8\x9a\x65\xad\xb2\x0e\xd9\x69\xd9\x39\x59\xb7\xec\x92\xac\x57\xd6\x2f\x1b\x94\x0d\xcb\x46\x65\x37\x64\x93\xb2\x5b\xb2\x19\xd9\x7d\xd9\xbc\xec\xa1\x6c\x49\xb6\x2c\x5b\x95\xad\xcb\x36\x65\x2f\xe4\x20\xe7\xc9\x85\x72\xa9\x5c\x2d\x37\xc8\xcd\x72\xbb\xdc\x23\x4f\x97\xe7\xca\x8b\xe4\xa5\xf2\x0a\xf9\x31\xf9\x09\x79\x9d\xbc\x51\xde\x22\x6f\x93\x77\xca\xcf\xc8\xbb\xe4\x17\xe4\x3d\xf2\x2b\xf2\x01\xf9\x35\xf9\x75\xf9\x98\x7c\x42\x3e\x25\xbf\x2d\xbf\x2b\x9f\x95\x3f\x90\x2f\xca\x1f\xcb\x57\xe4\xcf\xe4\x1b\xf2\x2d\xf9\x8e\x82\x56\x08\x14\x22\x85\x5c\xa1\x55\x18\x15\x56\x85\x43\xe1\x55\x64\x2a\xf2\x15\xc5\x8a\x32\x45\xa5\xe2\xb8\xa2\x46\x51\xaf\x68\x52\x9c\x54\xb4\x2b\x4e\x29\xce\x2a\xce\x2b\x2e\x2a\x2e\x2b\xfa\x14\x57\x15\x43\x8a\x11\xc5\xb8\xe2\xa6\x62\x5a\x71\x47\x71\x4f\x31\xa7\x58\x50\x3c\x52\x3c\x51\x3c\x55\xac\x29\x9e\x2b\xb6\x15\xbb\x4a\x8e\x32\x52\x29\x56\x2a\x95\x3a\xa5\x49\x69\x53\xba\x94\x3e\x65\xb6\xb2\x50\x59\xa2\x2c\x57\x56\x29\xab\x95\xb5\xca\x06\x65\xb3\xb2\x55\xd9\xa1\x3c\xad\x3c\xa7\xec\x56\x5e\x52\xf6\x2a\xfb\x95\x83\xca\x61\xe5\xa8\xf2\x86\x72\x52\x79\x4b\x39\xa3\xbc\xaf\x9c\x57\x3e\x54\x2e\x29\x97\x95\xab\xca\x75\xe5\xa6\xf2\x85\x0a\x54\x3c\x95\x50\x25\x55\xa9\x55\x06\x95\x59\x65\x57\x79\x54\xe9\xaa\x5c\x55\x91\xaa\x54\x55\xa1\x3a\xa6\x3a\xa1\xaa\x53\x35\xaa\x5a\x54\x6d\xaa\x4e\xd5\x19\x55\x97\xea\x82\xaa\x47\x75\x45\x35\xa0\xba\xa6\xba\xae\x1a\x53\x4d\xa8\xa6\x54\xb7\x55\x77\x55\xb3\xaa\x07\xaa\x45\xd5\x63\xd5\x8a\xea\x99\x6a\x43\xb5\xa5\xda\x51\xd3\x6a\x81\x5a\xa4\x96\xab\xb5\x6a\xa3\xda\xaa\x76\xa8\xbd\xea\x4c\x75\xbe\xba\x58\x5d\xa6\xae\x54\x1f\x57\xd7\xa8\xeb\xd5\x4d\xea\x93\xea\x76\xf5\x29\xf5\x59\xf5\x79\xf5\x45\xf5\x65\x75\x9f\xfa\xaa\x7a\x48\x3d\xa2\x1e\x57\xdf\x54\x4f\xab\xef\xa8\xef\xa9\xe7\xd4\x0b\xea\x47\xea\x27\xea\xa7\xea\x35\xf5\x73\xf5\xb6\x7a\x57\xc3\xd1\x44\x6a\xc4\x1a\xa5\x46\xa7\x31\x69\x6c\x1a\x97\xc6\xa7\xc9\xd6\x14\x6a\x4a\x34\xe5\x9a\x2a\x4d\xb5\xa6\x56\xd3\xa0\x69\xd6\xb4\x6a\x3a\x34\xa7\x35\xe7\x34\xdd\x9a\x4b\x9a\x5e\x4d\xbf\x66\x50\x33\xac\x19\xd5\xdc\xd0\x4c\x6a\x6e\x69\x66\x34\xf7\x35\xf3\x9a\x87\x9a\x25\xcd\xb2\x66\x55\xb3\xae\xd9\xd4\xbc\xd0\x82\x96\xa7\x15\x6a\xa5\x5a\xb5\xd6\xa0\x35\x6b\xed\x5a\x8f\x36\x5d\x9b\xab\x2d\xd2\x96\x6a\x2b\xb4\xc7\xb4\x27\xb4\x75\xda\x46\x6d\x8b\xb6\x4d\xdb\xa9\x3d\xa3\xed\xd2\x5e\xd0\xf6\x68\xaf\x68\x07\xb4\xd7\xb4\xd7\xb5\x63\xda\x09\xed\x94\xf6\xb6\xf6\xae\x76\x56\xfb\x40\xbb\xa8\x7d\xac\x5d\xd1\x3e\xd3\x6e\x68\xb7\xb4\x3b\xb1\x74\xac\x20\x56\x14\x2b\x8f\xd5\xc6\x1a\x63\xad\xb1\x8e\x58\x6f\x6c\x66\x6c\x7e\x6c\x71\x6c\x59\x6c\x65\xec\xf1\xd8\x9a\xd8\xfa\xd8\xa6\xd8\x93\xb1\xed\xb1\xa7\x62\xcf\xc6\x9e\x8f\xbd\x18\x7b\x39\xb6\x2f\xf6\x6a\xec\x50\xec\x48\xec\x78\xec\xcd\xd8\xe9\xd8\x3b\xb1\xf7\x62\xe7\x62\x17\x62\x1f\xc5\x3e\x89\x7d\x1a\xbb\x16\xfb\x3c\x76\x3b\x76\x57\xc7\xd1\x45\xea\xc4\x3a\xa5\x4e\xa7\x33\xe9\x6c\x3a\x97\xce\xa7\xcb\xd6\x15\xea\x4a\x74\xe5\xba\x2a\x5d\xb5\xae\x56\xd7\xa0\x6b\xd6\xb5\xea\x3a\x74\xa7\x75\xe7\x74\xdd\xba\x4b\xba\x5e\x5d\xbf\x6e\x50\x37\xac\x1b\xd5\xdd\xd0\x4d\xea\x6e\xe9\x66\x74\xf7\x75\xf3\xba\x87\xba\x25\xdd\xb2\x6e\x55\xb7\xae\xdb\xd4\xbd\xd0\x83\x9e\xa7\x17\xea\xa5\x7a\xb5\xde\xa0\x37\xeb\xed\x7a\x8f\x3e\x5d\x9f\xab\x2f\xd2\x97\xea\x2b\xf4\xc7\xf4\x27\xf4\x75\xfa\x46\x7d\x8b\xbe\x4d\xdf\xa9\x3f\xa3\xef\xd2\x5f\xd0\xf7\xe8\xaf\xe8\x07\xf4\xd7\xf4\xd7\xf5\x63\xfa\x09\xfd\x94\xfe\xb6\xfe\xae\x7e\x56\xff\x40\xbf\xa8\x7f\xac\x5f\xd1\x3f\xd3\x6f\xe8\xb7\xf4\x3b\x06\xda\x20\x30\x88\x0c\x72\x83\xd6\x60\x34\x58\x0d\x0e\x83\xd7\x90\x69\xc8\x37\x14\x1b\xca\x0c\x95\x86\xe3\x86\x1a\x43\xbd\xa1\xc9\x70\xd2\xd0\x6e\x38\x65\x38\x6b\x38\x6f\xb8\x68\xb8\x6c\xe8\x33\x5c\x35\x0c\x19\x46\x0c\xe3\x86\x9b\x86\x69\xc3\x1d\xc3\x3d\xc3\x9c\x61\xc1\xf0\xc8\xf0\xc4\xf0\xd4\xb0\x66\x78\x6e\xd8\x36\xec\xc6\x71\xe2\x22\xe3\xc4\x71\xca\x38\x5d\x9c\x29\xce\x16\xe7\x8a\xf3\xc5\x65\xc7\x15\xc6\x95\xc4\x95\xc7\x55\xc5\x55\xc7\xd5\xc6\x35\xc4\x35\xc7\xb5\xc6\x75\xc4\x9d\x8e\x3b\x17\xd7\x1d\x77\x29\xae\x37\xae\x3f\x6e\x30\x6e\x38\x6e\x34\xee\x46\xdc\x64\xdc\xad\xb8\x99\xb8\xfb\x71\xf3\x71\x0f\xe3\x96\xe2\x96\xe3\x56\xe3\xd6\xe3\x36\xe3\x5e\x18\xc1\xc8\x33\x0a\x8d\x52\xa3\xda\x68\x30\x9a\x8d\x76\xa3\xc7\x98\x6e\xcc\x35\x16\x19\x4b\x8d\x15\xc6\x63\xc6\x13\xc6\x3a\x63\xa3\xb1\xc5\xd8\x66\xec\x34\x9e\x31\x76\x19\x2f\x18\x7b\x8c\x57\x8c\x03\xc6\x6b\xc6\xeb\xc6\x31\xe3\x84\x71\xca\x78\xdb\x78\xd7\x38\x6b\x7c\x60\x5c\x34\x3e\x36\xae\x18\x9f\x19\x37\x8c\x5b\xc6\x9d\x78\x3a\x5e\x10\x2f\x8a\x97\xc7\x6b\xe3\x8d\xf1\xd6\x78\x47\xbc\x37\x3e\x33\x3e\x3f\xbe\x38\xbe\x2c\xbe\x32\xfe\x78\x7c\x4d\x7c\x7d\x7c\x53\xfc\xc9\xf8\xf6\xf8\x53\xf1\x67\xe3\xcf\xc7\x5f\x8c\xbf\x1c\xdf\x17\x7f\x35\x7e\x28\x7e\x24\x7e\x3c\xfe\x66\xfc\x74\xfc\x9d\xf8\x7b\xf1\x73\xf1\x0b\xf1\x8f\xe2\x9f\xc4\x3f\x8d\x5f\x8b\x7f\x1e\xbf\x1d\xbf\x6b\xe2\x98\x22\x4d\x62\x93\xd2\xa4\x33\x99\x4c\x36\x93\xcb\xe4\x33\x65\x9b\x0a\x4d\x25\xa6\x72\x53\x95\xa9\xda\x54\x6b\x6a\x30\x35\x9b\x5a\x4d\x1d\xa6\xd3\xa6\x73\xa6\x6e\xd3\x25\x53\xaf\xa9\xdf\x34\x68\x1a\x36\x8d\x9a\x6e\x98\x26\x4d\xb7\x4c\x33\xa6\xfb\xa6\x79\xd3\x43\xd3\x92\x69\xd9\xb4\x6a\x5a\x37\x6d\x9a\x5e\x24\x40\x02\x2f\x41\x98\x20\x4d\x50\x27\x18\x12\xcc\x09\xf6\x04\x4f\x42\x7a\x42\x6e\x42\x51\x42\x69\x42\x45\xc2\xb1\x84\x13\x09\x75\x09\x8d\x09\x2d\x09\x6d\x09\x9d\x09\x67\x12\xba\x12\x2e\x24\xf4\x24\x5c\x49\x18\x48\xb8\x96\x70\x3d\x61\x2c\x61\x22\x61\x2a\xe1\x76\xc2\xdd\x84\xd9\x84\x07\x09\x8b\x09\x8f\x13\x56\x12\x9e\x25\x6c\x24\x6c\x25\xec\x98\x69\xb3\xc0\x2c\x32\xcb\xcd\x5a\xb3\xd1\x6c\x35\x3b\xcc\x5e\x73\xa6\x39\xdf\x5c\x6c\x2e\x33\x57\x9a\x8f\x9b\x6b\xcc\xf5\xe6\x26\xf3\x49\x73\xbb\xf9\x94\xf9\xac\xf9\xbc\xf9\xa2\xf9\xb2\xb9\xcf\x7c\xd5\x3c\x64\x1e\x31\x8f\x9b\x6f\x9a\xa7\xcd\x77\xcc\xf7\xcc\x73\xe6\x05\xf3\x23\xf3\x13\xf3\x53\xf3\x9a\xf9\xb9\x79\xdb\xbc\x6b\xe1\x58\x22\x2d\x62\x8b\xd2\xa2\xb3\x98\x2c\x36\x8b\xcb\xe2\xb3\x64\x5b\x0a\x2d\x25\x96\x72\x4b\x95\xa5\xda\x52\x6b\x69\xb0\x34\x5b\x5a\x2d\x1d\x96\xd3\x96\x73\x96\x6e\xcb\x25\x4b\xaf\xa5\xdf\x32\x68\x19\xb6\x8c\x5a\x6e\x58\x26\x2d\xb7\x2c\x33\x96\xfb\x96\x79\xcb\x43\xcb\x92\x65\xd9\xb2\x6a\x59\xb7\x6c\x5a\x5e\x58\xc1\xca\xb3\x0a\xad\x52\xab\xda\x6a\xb0\x9a\xad\x76\xab\xc7\x9a\x6e\xcd\xb5\x16\x59\x4b\xad\x15\xd6\x63\xd6\x13\xd6\x3a\x6b\xa3\xb5\xc5\xda\x66\xed\xb4\x9e\xb1\x76\x59\x2f\x58\x7b\xac\x57\xac\x03\xd6\x6b\xd6\xeb\xd6\x31\xeb\x84\x75\xca\x7a\xdb\x7a\xd7\x3a\x6b\x7d\x60\x5d\xb4\x3e\xb6\xae\x58\x9f\x59\x37\xac\x5b\xd6\x9d\x44\x3a\x51\x90\x28\x4a\x94\x27\x6a\x13\x8d\x89\xd6\x44\x47\xa2\x37\x31\x33\x31\x3f\xb1\x38\xb1\x2c\xb1\x32\xf1\x78\x62\x4d\x62\x7d\x62\x53\xe2\xc9\xc4\xf6\xc4\x53\x89\x67\x13\xcf\x27\x5e\x4c\xbc\x9c\xd8\x97\x78\x35\x71\x28\x71\x24\x71\x3c\xf1\x66\xe2\x74\xe2\x9d\xc4\x7b\x89\x73\x89\x0b\x89\x8f\x12\x9f\x24\x3e\x4d\x5c\x4b\x7c\x9e\xb8\x9d\xb8\x6b\xe3\xd8\x22\x6d\x62\x9b\xd2\xa6\xb3\x99\x6c\x36\x9b\xcb\xe6\xb3\x65\xdb\x0a\x6d\x25\xb6\x72\x5b\x95\xad\xda\x56\x6b\x6b\xb0\x35\xdb\x5a\x6d\x1d\xb6\xd3\xb6\x73\xb6\x6e\xdb\x25\x5b\xaf\xad\xdf\x36\x68\x1b\xb6\x8d\xda\x6e\xd8\x26\x6d\xb7\x6c\x33\xb6\xfb\xb6\x79\xdb\x43\xdb\x92\x6d\xd9\xb6\x6a\x5b\xb7\x6d\xda\x5e\x24\x41\x12\x2f\x49\x98\x24\x4d\x52\x27\x19\x92\xcc\x49\xf6\x24\x4f\x52\x7a\x52\x6e\x52\x51\x52\x69\x52\x45\xd2\xb1\xa4\x13\x49\x75\x49\x8d\x49\x2d\x49\x6d\x49\x9d\x49\x67\x92\xba\x92\x2e\x24\xf5\x24\x5d\x49\x1a\x48\xba\x96\x74\x3d\x69\x2c\x69\x22\x69\x2a\xe9\x76\xd2\xdd\xa4\xd9\xa4\x07\x49\x8b\x49\x8f\x93\x56\x92\x9e\x25\x6d\x24\x6d\x25\xed\xd8\x69\xbb\xc0\x2e\xb2\xcb\xed\x5a\xbb\xd1\x6e\xb5\x3b\xec\x5e\x7b\xa6\x3d\xdf\x5e\x6c\x2f\xb3\x57\xda\x8f\xdb\x6b\xec\xf5\xf6\x26\xfb\x49\x7b\xbb\xfd\x94\xfd\xac\xfd\xbc\xfd\xa2\xfd\xb2\xbd\xcf\x7e\xd5\x3e\x64\x1f\xb1\x8f\xdb\x6f\xda\xa7\xed\x77\xec\xf7\xec\x73\xf6\x05\xfb\x23\xfb\x13\xfb\x53\xfb\x9a\xfd\xb9\x7d\xdb\xbe\x9b\xcc\x49\x8e\x4c\x16\x27\x2b\x93\x75\xc9\xa6\x64\x5b\xb2\x2b\xd9\x97\x9c\x9d\x5c\x98\x5c\x92\x5c\x9e\x5c\x95\x5c\x9d\x5c\x9b\xdc\x90\xdc\x9c\xdc\x9a\xdc\x91\x7c\x3a\xf9\x5c\x72\x77\xf2\xa5\xe4\xde\xe4\xfe\xe4\xc1\xe4\xe1\xe4\xd1\xe4\x1b\xc9\x93\xc9\xb7\x92\x67\x92\xef\x27\xcf\x27\x3f\x4c\x5e\x4a\x5e\x4e\x5e\x4d\x5e\x4f\xde\x4c\x7e\xe1\x00\x07\xcf\x21\x74\x48\x1d\x6a\x87\xc1\x61\x76\xd8\x1d\x1e\x47\xba\x23\xd7\x51\xe4\x28\x75\x54\x38\x8e\x39\x4e\x38\xea\x1c\x8d\x8e\x16\x47\x9b\xa3\xd3\x71\xc6\xd1\xe5\xb8\xe0\xe8\x71\x5c\x71\x0c\x38\xae\x39\xae\x3b\xc6\x1c\x13\x8e\x29\xc7\x6d\xc7\x5d\xc7\xac\xe3\x81\x63\xd1\xf1\xd8\xb1\xe2\x78\xe6\xd8\x70\x6c\x39\x76\x9c\xb4\x53\xe0\x14\x39\xe5\x4e\xad\xd3\xe8\xb4\x3a\x1d\x4e\xaf\x33\xd3\x99\xef\x2c\x76\x96\x39\x2b\x9d\xc7\x9d\x35\xce\x7a\x67\x93\xf3\xa4\xb3\xdd\x79\xca\x79\xd6\x79\xde\x79\xd1\x79\xd9\xd9\xe7\xbc\xea\x1c\x72\x8e\x38\xc7\x9d\x37\x9d\xd3\xce\x3b\xce\x7b\xce\x39\xe7\x82\xf3\x91\xf3\x89\xf3\xa9\x73\xcd\xf9\xdc\xb9\xed\xdc\x75\x71\x5c\x91\x2e\xb1\x4b\xe9\xd2\xb9\x4c\x2e\x9b\xcb\xe5\xf2\xb9\xb2\x5d\x85\xae\x12\x57\xb9\xab\xca\x55\xed\xaa\x75\x35\xb8\x9a\x5d\xad\xae\x0e\xd7\x69\xd7\x39\x57\xb7\xeb\x92\xab\xd7\xd5\xef\x1a\x74\x0d\xbb\x46\x5d\x37\x5c\x93\xae\x5b\xae\x19\xd7\x7d\xd7\xbc\xeb\xa1\x6b\xc9\xb5\xec\x5a\x75\xad\xbb\x36\x5d\x2f\xdc\xe0\xe6\xb9\x85\x6e\xa9\x5b\xed\x36\xb8\xcd\x6e\xbb\xdb\xe3\x4e\x77\xe7\xba\x8b\xdc\xa5\xee\x0a\xf7\x31\xf7\x09\x77\x9d\xbb\xd1\xdd\xe2\x6e\x73\x77\xba\xcf\xb8\xbb\xdc\x17\xdc\x3d\xee\x2b\xee\x01\xf7\x35\xf7\x75\xf7\x98\x7b\xc2\x3d\xe5\xbe\xed\xbe\xeb\x9e\x75\x3f\x70\x2f\xba\x1f\xbb\x57\xdc\xcf\xdc\x1b\xee\x2d\xf7\x8e\x87\xf6\x08\x3c\x22\x8f\xdc\xa3\xf5\x18\x3d\x56\x8f\xc3\xe3\xf5\x64\x7a\xf2\x3d\xc5\x9e\x32\x4f\xa5\xe7\xb8\xa7\xc6\x53\xef\x69\xf2\x9c\xf4\xb4\x7b\x4e\x79\xce\x7a\xce\x7b\x2e\x7a\x2e\x7b\xfa\x3c\x57\x3d\x43\x9e\x11\xcf\xb8\xe7\xa6\x67\xda\x73\xc7\x73\xcf\x33\xe7\x59\xf0\x3c\xf2\x3c\xf1\x3c\xf5\xac\x79\x9e\x7b\xb6\x3d\xbb\x29\x9c\x94\xc8\x14\x71\x8a\x32\x45\x97\x62\x4a\xb1\xa5\xb8\x52\x7c\x29\xd9\x29\x85\x29\x25\x29\xe5\x29\x55\x29\xd5\x29\xb5\x29\x0d\x29\xcd\x29\xad\x29\x1d\x29\xa7\x53\xce\xa5\x74\xa7\x5c\x4a\xe9\x4d\xe9\x4f\x19\x4c\x19\x4e\x19\x4d\xb9\x91\x32\x99\x72\x2b\x65\x26\xe5\x7e\xca\x7c\xca\xc3\x94\xa5\x94\xe5\x94\xd5\x94\xf5\x94\xcd\x94\x17\x5e\xf0\xf2\xbc\x42\xaf\xd4\xab\xf6\x1a\xbc\x66\xaf\xdd\xeb\xf1\xa6\x7b\x73\xbd\x45\xde\x52\x6f\x85\xf7\x98\xf7\x84\xb7\xce\xdb\xe8\x6d\xf1\xb6\x79\x3b\xbd\x67\xbc\x5d\xde\x0b\xde\x1e\xef\x15\xef\x80\xf7\x9a\xf7\xba\x77\xcc\x3b\xe1\x9d\xf2\xde\xf6\xde\xf5\xce\x7a\x1f\x78\x17\xbd\x8f\xbd\x2b\xde\x67\xde\x0d\xef\x96\x77\x27\x95\x4e\x15\xa4\x8a\x52\xe5\xa9\xda\x54\x63\xaa\x35\xd5\x91\xea\x4d\xcd\x4c\xcd\x4f\x2d\x4e\x2d\x4b\xad\x4c\x3d\x9e\x5a\x93\x5a\x9f\xda\x94\x7a\x32\xb5\x3d\xf5\x54\xea\xd9\xd4\xf3\xa9\x17\x53\x2f\xa7\xf6\xa5\x5e\x4d\x1d\x4a\x1d\x49\x1d\x4f\xbd\x99\x3a\x9d\x7a\x27\xf5\x5e\xea\x5c\xea\x42\xea\xa3\xd4\x27\xa9\x4f\x53\xd7\x52\x9f\xa7\x6e\xa7\xee\xfa\x38\xbe\x48\x9f\xd8\xa7\xf4\xe9\x7c\x26\x9f\xcd\xe7\xf2\xf9\x7c\xd9\xbe\x42\x5f\x89\xaf\xdc\x57\xe5\xab\xf6\xd5\xfa\x1a\x7c\xcd\xbe\x56\x5f\x87\xef\xb4\xef\x9c\xaf\xdb\x77\xc9\xd7\xeb\xeb\xf7\x0d\xfa\x86\x7d\xa3\xbe\x1b\xbe\x49\xdf\x2d\xdf\x8c\xef\xbe\x6f\xde\xf7\xd0\xb7\xe4\x5b\xf6\xad\xfa\xd6\x7d\x9b\xbe\x17\x69\x90\xc6\x4b\x13\xa6\x49\xd3\xd4\x69\x86\x34\x73\x9a\x3d\xcd\x93\x96\x9e\x96\x9b\x56\x94\x56\x9a\x56\x91\x76\x2c\xed\x44\x5a\x5d\x5a\x63\x5a\x4b\x5a\x5b\x5a\x67\xda\x99\xb4\xae\xb4\x0b\x69\x3d\x69\x57\xd2\x06\xd2\xae\xa5\x5d\x4f\x1b\x4b\x9b\x48\x9b\x4a\xbb\x9d\x76\x37\x6d\x36\xed\x41\xda\x62\xda\xe3\xb4\x95\xb4\x67\x69\x1b\x69\x5b\x69\x3b\xe9\x74\xba\x20\x5d\x94\x2e\x4f\xd7\xa6\x1b\xd3\xad\xe9\x8e\x74\x6f\x7a\x66\x7a\x7e\x7a\x71\x7a\x59\x7a\x65\xfa\xf1\xf4\x9a\xf4\xfa\xf4\xa6\xf4\x93\xe9\xed\xe9\xa7\xd2\xcf\xa6\x9f\x4f\xbf\x98\x7e\x39\xbd\x2f\xfd\x6a\xfa\x50\xfa\x48\xfa\x78\xfa\xcd\xf4\xe9\xf4\x3b\xe9\xf7\xd2\xe7\xd2\x17\xd2\x1f\xa5\x3f\x49\x7f\x9a\xbe\x96\xfe\x3c\x7d\x3b\x7d\x37\x83\x93\x11\x99\x21\xce\x50\x66\xe8\x32\x4c\x19\xb6\x0c\x57\x86\x2f\x23\x3b\xa3\x30\xa3\x24\xa3\x3c\xa3\x2a\xa3\x3a\xa3\x36\xa3\x21\xa3\x39\xa3\x35\xa3\x23\xe3\x74\xc6\xb9\x8c\xee\x8c\x4b\x19\xbd\x19\xfd\x19\x83\x19\xc3\x19\xa3\x19\x37\x32\x26\x33\x6e\x65\xcc\x64\xdc\xcf\x98\xcf\x78\x98\xb1\x94\xb1\x9c\xb1\x9a\xb1\x9e\xb1\x99\xf1\x22\x13\x32\x79\x99\xc2\x4c\x69\xa6\x3a\xd3\x90\x69\xce\xb4\x67\x7a\x32\xd3\x33\x73\x33\x8b\x32\x4b\x33\x2b\x32\x8f\x65\x9e\xc8\xac\xcb\x6c\xcc\x6c\xc9\x6c\xcb\xec\xcc\x3c\x93\xd9\x95\x79\x21\xb3\x27\xf3\x4a\xe6\x40\xe6\xb5\xcc\xeb\x99\x63\x99\x13\x99\x53\x99\xb7\x33\xef\x66\xce\x66\x3e\xc8\x5c\xcc\x7c\x9c\xb9\x92\xf9\x2c\x73\x23\x73\x2b\x73\x27\x8b\xce\x12\x64\x89\xb2\xe4\x59\xda\x2c\x63\x96\x35\xcb\x91\xe5\xcd\xca\xcc\xca\xcf\x2a\xce\x2a\xcb\xaa\xcc\x3a\x9e\x55\x93\x55\x9f\xd5\x94\x75\x32\xab\x3d\xeb\x54\xd6\xd9\xac\xf3\x59\x17\xb3\x2e\x67\xf5\x65\x5d\xcd\x1a\xca\x1a\xc9\x1a\xcf\xba\x99\x35\x9d\x75\x27\xeb\x5e\xd6\x5c\xd6\x42\xd6\xa3\xac\x27\x59\x4f\xb3\xd6\xb2\x9e\x67\x6d\x67\xed\x66\x73\xb2\x23\xb3\xc5\xd9\xca\x6c\x5d\xb6\x29\xdb\x96\xed\xca\xf6\x65\x67\x67\x17\x66\x97\x64\x97\x67\x57\x65\x57\x67\xd7\x66\x37\x64\x37\x67\xb7\x66\x77\x64\x9f\xce\x3e\x97\xdd\x9d\x7d\x29\xbb\x37\xbb\x3f\x7b\x30\x7b\x38\x7b\x34\xfb\x46\xf6\x64\xf6\xad\xec\x99\xec\xfb\xd9\xf3\xd9\x0f\xb3\x97\xb2\x97\xb3\x57\xb3\xd7\xb3\x37\xb3\x5f\xe4\x40\x0e\x2f\x47\x98\x23\xcd\x51\xe7\x18\x72\xcc\x39\xf6\x1c\x4f\x4e\x7a\x4e\x6e\x4e\x51\x4e\x69\x4e\x45\xce\xb1\x9c\x13\x39\x75\x39\x8d\x39\x2d\x39\x6d\x39\x9d\x39\x67\x72\xba\x72\x2e\xe4\xf4\xe4\x5c\xc9\x19\xc8\xb9\x96\x73\x3d\x67\x2c\x67\x22\x67\x2a\xe7\x76\xce\xdd\x9c\xd9\x9c\x07\x39\x8b\x39\x8f\x73\x56\x72\x9e\xe5\x6c\xe4\x6c\xe5\xec\xe4\xd2\xb9\x82\x5c\x51\xae\x3c\x57\x9b\x6b\xcc\xb5\xe6\x3a\x72\xbd\xb9\x99\xb9\xf9\xb9\xc5\xb9\x65\xb9\x95\xb9\xc7\x73\x6b\x72\xeb\x73\x9b\x72\x4f\xe6\xb6\xe7\x9e\xca\x3d\x9b\x7b\x3e\xf7\x62\xee\xe5\xdc\xbe\xdc\xab\xb9\x43\xb9\x23\xb9\xe3\xb9\x37\x73\xa7\x73\xef\xe4\xde\xcb\x9d\xcb\x5d\xc8\x7d\x94\xfb\x24\xf7\x69\xee\x5a\xee\xf3\xdc\xed\xdc\xdd\x3c\x4e\x5e\x64\x9e\x38\x4f\x99\xa7\xcb\x33\xe5\xd9\xf2\x5c\x79\xbe\xbc\xec\xbc\xc2\xbc\x92\xbc\xf2\xbc\xaa\xbc\xea\xbc\xda\xbc\x86\xbc\xe6\xbc\xd6\xbc\x8e\xbc\xd3\x79\xe7\xf2\xba\xf3\x2e\xe5\xf5\xe6\xf5\xe7\x0d\xe6\x0d\xe7\x8d\xe6\xdd\xc8\x9b\xcc\xbb\x95\x37\x93\x77\x3f\x6f\x3e\xef\x61\xde\x52\xde\x72\xde\x6a\xde\x7a\xde\x66\xde\x8b\x7c\xc8\xe7\xe5\x0b\xf3\xa5\xf9\xea\x7c\x43\xbe\x39\xdf\x9e\xef\xc9\x4f\xcf\xcf\xcd\x2f\xca\x2f\xcd\xaf\xc8\x3f\x96\x7f\x22\xbf\x2e\xbf\x31\xbf\x25\xbf\x2d\xbf\x33\xff\x4c\x7e\x57\xfe\x85\xfc\x9e\xfc\x2b\xf9\x03\xf9\xd7\xf2\xaf\xe7\x8f\xe5\x4f\xe4\x4f\xe5\xdf\xce\xbf\x9b\x3f\x9b\xff\x20\x7f\x31\xff\x71\xfe\x4a\xfe\xb3\xfc\x8d\xfc\xad\xfc\x9d\x02\xba\x40\x50\x20\x2a\x90\x17\x68\x0b\x8c\x05\xd6\x02\x47\x81\xb7\x20\xb3\x20\xbf\xa0\xb8\xa0\xac\xa0\xb2\xe0\x78\x41\x4d\x41\x7d\x41\x53\xc1\xc9\x82\xf6\x82\x53\x05\x67\x0b\xce\x17\x5c\x2c\xb8\x5c\xd0\x57\x70\xb5\x60\xa8\x60\xa4\x60\xbc\xe0\x66\xc1\x74\xc1\x9d\x82\x7b\x05\x73\x05\x0b\x05\x8f\x0a\x9e\x14\x3c\x2d\x58\x2b\x78\x5e\xb0\x5d\xb0\x5b\xc8\x29\x8c\x2c\x14\x17\x2a\x0b\x75\x85\xa6\x42\x5b\xa1\xab\xd0\x57\x98\x5d\x58\x58\x58\x52\x58\x5e\x58\x55\x58\x5d\x58\x5b\xd8\x50\xd8\x5c\xd8\x5a\xd8\x51\x78\xba\xf0\x5c\x61\x77\xe1\xa5\xc2\xde\xc2\xfe\xc2\xc1\xc2\xe1\xc2\xd1\xc2\x1b\x85\x93\x85\xb7\x0a\x67\x0a\xef\x17\xce\x17\x3e\x2c\x5c\x2a\x5c\x2e\x5c\x2d\x5c\x2f\xdc\x2c\x7c\x71\x04\x8e\xf0\x8e\x08\x8f\x48\x8f\xa8\x8f\x18\x8e\x98\x8f\xd8\x8f\x78\x8e\xa4\x1f\xc9\x3d\x52\x74\xa4\xf4\x48\xc5\x91\x63\x47\x4e\x1c\xa9\x3b\xd2\x78\xa4\xe5\x48\xdb\x91\xce\x23\x67\x8e\x74\x1d\xb9\x70\xa4\xe7\xc8\x95\x23\x03\x47\xae\x1d\xb9\x7e\x64\xec\xc8\xc4\x91\xa9\x23\xb7\x8f\xdc\x3d\x32\x7b\xe4\xc1\x91\xc5\x23\x8f\x8f\xac\x1c\x79\x76\x64\xe3\xc8\xd6\x91\x9d\x22\xba\x48\x50\x24\x2a\x92\x17\x69\x8b\x8c\x45\xd6\x22\x47\x91\xb7\x28\xb3\x28\xbf\xa8\xb8\xa8\xac\xa8\xb2\xe8\x78\x51\x4d\x51\x7d\x51\x53\xd1\xc9\xa2\xf6\xa2\x53\x45\x67\x8b\xce\x17\x5d\x2c\xba\x5c\xd4\x57\x74\xb5\x68\xa8\x68\xa4\x68\xbc\xe8\x66\xd1\x74\xd1\x9d\xa2\x7b\x45\x73\x45\x0b\x45\x8f\x8a\x9e\x14\x3d\x2d\x5a\x2b\x7a\x5e\xb4\x5d\xb4\x7b\x94\x73\x34\xf2\xa8\xf8\xa8\xf2\xa8\xee\xa8\xe9\xa8\xed\xa8\xeb\xa8\xef\x68\xf6\xd1\xc2\xa3\x25\x47\xcb\x8f\x56\x1d\xad\x3e\x5a\x7b\xb4\xe1\x68\xf3\xd1\xd6\xa3\x1d\x47\x4f\x1f\x3d\x77\xb4\xfb\xe8\xa5\xa3\xbd\x47\xfb\x8f\x0e\x1e\x1d\x3e\x3a\x7a\xf4\xc6\xd1\xc9\xa3\xb7\x8e\xce\x1c\xbd\x7f\x74\xfe\xe8\xc3\xa3\x4b\x47\x97\x8f\xae\x1e\x5d\x3f\xba\x79\xf4\x45\x31\x14\xf3\x8a\x85\xc5\xd2\x62\x75\xb1\xa1\xd8\x5c\x6c\x2f\xf6\x14\xa7\x17\xe7\x16\x17\x15\x97\x16\x57\x14\x1f\x2b\x3e\x51\x5c\x57\xdc\x58\xdc\x52\xdc\x56\xdc\x59\x7c\xa6\xb8\xab\xf8\x42\x71\x4f\xf1\x95\xe2\x01\xa0\x68\xec\x6a\x31\xab\xd8\x6f\xfa\x1a\xfe\xb5\xe6\xdf\xc4\x9e\x11\x7e\xcb\x81\xfe\x4d\x44\xb0\xb3\xc9\x7e\x2f\x81\xfe\x47\x44\xbe\x83\xc8\x1a\x22\xdf\x41\xe4\x53\x88\x9c\x41\x24\x79\x1f\x62\x44\xe4\x25\x76\xd9\xf0\xfb\x4f\xf4\xf7\x11\xc1\xef\x72\xb1\x9f\x50\xd2\x7f\x86\x7f\x43\xba\x9b\xed\xae\xfa\x29\xd5\x8d\x08\x8e\x43\x5f\xf7\x53\xf8\xe6\x6e\x09\x50\x34\xdb\xad\x93\x23\xde\x8e\xe3\xc8\x88\x5d\xc8\xf0\xaf\x4d\xb3\xdf\x64\x7d\x82\xf8\xd7\x11\xe1\x22\x82\xdf\xbc\x64\xb8\xf8\x14\xae\x9f\x9b\x8b\x4f\xad\x21\xf2\x45\x62\xef\x5f\xdc\x27\x33\xfc\xb2\x1b\x28\xba\x95\x90\xc1\xbf\xab\x4d\xc7\x11\xb3\xc7\x21\x62\x24\x34\xc6\xee\x7d\x06\xc7\xb9\x88\x08\xfe\x85\x6c\x9a\xfd\x4e\x12\xbe\xfd\x45\xd7\xe0\x0a\x7b\xf1\x13\x94\x79\x1c\xad\x17\x65\xf0\x3b\x88\x5c\x2f\xca\xbc\x8f\x48\x11\xb1\xf7\x22\x44\xd8\xfe\x60\x3b\x22\x16\x16\xe1\x8c\xfb\x57\xe8\xa7\xf4\xbb\x88\xd4\xf3\x9a\x80\x62\xba\x50\xa6\x1e\xb5\xfa\xf7\xfe\x9f\x32\x35\x28\xf3\x29\x94\x79\x17\x7b\xca\xf8\xed\x67\xf6\x29\xea\x25\xca\x74\xa1\xcc\x57\x51\x26\x12\xc7\xa1\xf1\x2c\x6e\xee\xca\x43\xe7\xa2\x3e\x40\xe4\x3d\x94\xc1\x6f\xdb\xd0\xef\xe1\x38\x1e\x5e\x21\x50\x74\x0b\x9e\xa9\x67\x2f\x02\x3d\xf8\x54\x27\xce\x6e\xc6\xa7\x4a\x02\x32\x3d\xa1\x4f\x31\x5f\xf5\xcf\xc2\x1b\xc2\x55\xfd\x1e\xae\xc7\x4d\xec\x14\xe7\xa2\x63\x11\xd1\x22\xf2\x69\x44\xac\xc4\x0a\x67\xf7\xad\xf9\x1f\xfc\x08\xf5\x47\x38\xa6\x11\x91\x3f\xc2\xd9\xff\x10\x91\x52\x44\x7e\x82\xc8\x10\xf7\x1e\x50\xf4\x34\x22\x43\x38\x72\x16\x8e\xd3\x1d\x9c\x9d\xfa\x73\x62\x3d\xd1\x28\xf3\x77\xb8\xe6\x36\x1c\x2d\x11\x65\x56\x08\x19\xb4\x0d\x6a\x91\x58\x4f\x39\xae\xe7\x0a\xca\xf7\x21\xf2\x00\xc7\xf9\xb7\xfc\xde\xd7\x56\xf7\xb5\x43\x20\x2d\x6f\x80\x78\x42\x11\x06\xbf\xa9\xc6\xcf\x46\x3b\xfc\xd6\xbe\x08\xf0\x1b\xa8\xc3\x2f\xe2\x5c\xa4\xbf\xbf\x19\xd2\x12\x8a\x50\x53\x7e\x19\x7a\x9a\xf0\x77\x44\x58\x5b\xfd\x10\xa4\x25\x14\xd9\x1f\x91\x18\xa7\x5f\x86\x5b\x19\xf4\x77\x46\xee\x1f\x87\xf4\xf7\x37\x44\x5a\x3e\x0a\x39\x20\x92\xac\xe1\x38\xa4\xbf\xbf\x19\xd2\xb2\x07\x69\x46\x19\xd2\xdf\xd9\xef\x25\x97\x73\xd6\x5e\xc7\x84\xdf\xf7\x7b\x0a\x67\x99\x3b\x01\x14\xf3\x5e\xc0\x97\x0b\x5f\xcb\xbc\x7b\x08\x44\xfd\x06\xc8\x90\x3f\xda\x70\x3b\x5f\x21\xcc\x11\xb4\xf0\x42\xb4\xd8\xdf\xda\x1b\x5b\xa8\xbf\x47\x6b\xc9\xf1\xcf\xc5\xdc\xc6\x71\xd8\x48\xc2\x22\xab\x1f\x81\xa8\x43\x91\x57\x71\xc3\x8f\x90\x91\x84\x11\xee\x45\xe8\xed\x10\x44\x1d\x2a\x43\xbf\x83\x7b\x6f\xc7\x91\xdf\x41\xe4\x3d\x44\xc6\x11\x61\x75\xf8\x69\x44\xb4\x88\x7c\xfa\x90\x48\x79\x08\xa2\xde\x23\xb3\x3f\x46\xbd\x47\x3c\xf5\xde\x21\x10\xf5\x1e\x44\x1e\xd4\x21\x1b\x49\xd8\xc8\x1f\x12\xfd\xf6\xcb\xfc\x5b\xbe\xc0\x1f\xc7\x88\x98\xf0\xae\x3f\xd6\x71\xcc\xc4\xb9\xb3\xb1\x65\x98\xe7\x08\xca\xe0\x7a\x8a\x08\x19\xb2\x96\x88\xdb\xcd\x7d\x15\x69\x99\x2e\x9c\xeb\x83\xdd\x93\xfe\x1a\x00\xed\x99\xad\x01\xfe\x81\xb5\x16\xff\x98\xcc\x0e\x8e\xc3\x66\xa2\x30\x32\x1c\x71\x88\x4c\xcb\x3e\x19\xfc\x7e\x27\x21\xf3\x77\x6f\x30\xce\x77\x70\x5f\x64\x25\x83\x79\x30\xe0\x71\xef\x86\xa9\x76\xd8\x5c\x59\x4e\xc8\xfc\x26\xea\xb0\x9c\x88\x75\x39\x7e\x1d\x06\xf6\xf5\xd5\x80\x0c\x1b\x0f\x1d\x41\x19\xd4\x61\x66\x88\x4c\xcb\x6b\x1d\xbe\x92\xf1\xeb\x67\x81\x90\xf9\x54\x50\xcf\xd4\xff\xed\xd7\xf3\xeb\x4c\xed\x97\xc9\xd9\xf5\x12\x73\xed\x19\x27\x60\x2d\x38\x0e\x13\x41\xe8\xe7\xfb\x81\x7d\xbd\x96\x09\x64\xf3\x7f\x0c\xc8\x38\x08\x99\xd7\x6b\x7e\x2d\xd3\x72\xe0\x38\xa4\x4c\x48\xed\x87\xb6\xf1\x2e\xef\xd8\x5e\x19\x9c\x8b\xa8\x06\xe9\xdf\xe5\x5f\x07\x8a\x33\x83\x1e\xfd\xde\xc1\x15\xe3\x01\xf5\x06\x9b\x2f\x6e\x13\xf9\x82\x8d\x12\x3e\x22\x26\x4c\xe1\xa7\xfb\x64\x4e\xf1\x70\x37\xf6\x44\x12\x76\x9c\x3e\xff\x5e\x42\xc6\x31\x12\x32\xac\xd7\xb0\xf9\xcb\xec\xd7\x3c\xe5\x41\x5d\xb1\xb5\xcd\x2c\x22\x6c\xb6\x12\x06\xe7\x82\x4d\xf4\xfd\x6a\x22\x22\xfd\x31\xee\x6b\x02\x4f\xf6\x97\xd0\x53\x58\x1d\x2e\xe2\xf8\xff\x09\xab\x82\xdf\x0e\xac\x87\xad\x84\x4f\xbe\x9a\x8b\x5d\x4f\xa0\x8e\x22\x6b\xe3\x72\xd4\xf3\xb9\x60\x65\x45\x6d\x21\x52\x82\xd6\xc2\x46\x63\xac\xb5\x68\x19\x8e\x4c\xd4\xcf\xd4\x05\xfe\x34\xea\xa7\xe9\xf5\x0a\x89\x1a\x9b\xfa\x0b\xb4\x3a\x8f\xff\xa7\xaf\x77\x9a\x7b\x50\x1d\xce\xca\x30\xad\xc1\x2a\x2e\x9c\x4c\xa0\xd2\x7b\x27\x8c\xcc\x3b\x7b\x65\x18\xa7\x7f\xcd\x21\xf5\xfc\x7b\x84\x85\xa3\x25\x90\x35\x3f\xfd\xaf\x71\x85\xaf\x2a\x46\xbf\x0c\xdf\x8f\x30\x19\x61\xc6\x69\x27\xe2\xea\x7f\xf5\x3f\xc5\x95\xfb\x11\x26\xe3\x80\x91\x4f\xee\x1b\x59\x8e\x75\x82\x67\x4f\x55\xe0\xf6\xdb\x18\x99\x0b\x5e\xd7\x1b\x8e\xa0\xcc\xde\x9c\x12\x90\x19\x0c\x91\xf1\xaf\x70\x86\x90\xf9\x36\xd6\x6c\xc5\xb8\x8b\x6f\x23\xf2\xcb\x98\x97\x37\x71\xcd\xdf\xc0\xa7\xfa\x30\x26\x8c\x07\x6f\x2e\xd4\xdf\x05\x63\x2f\x5b\xf7\x86\xdc\x6e\x84\x78\xca\xaf\x6a\x63\xbf\x8d\xfd\x0d\xea\xb0\x8f\x88\x2d\xec\x38\x7f\x16\x8c\x51\x81\x71\x3e\x89\x32\x45\xc1\x3b\x11\xf5\x5d\x94\x79\x8c\x32\x3f\xf9\x50\x99\x3e\x42\x86\xb8\x5b\x51\xac\x17\xbc\xaa\xcc\xfd\x32\x5f\x45\x9b\x67\xc7\xa9\xdb\x37\xce\x02\x31\x0e\x71\x23\xa3\xa6\x71\x9c\x57\xf5\xbc\x5f\x66\x08\xc7\x29\x25\xf6\xc5\x56\xe6\x43\x18\xa3\xd8\x78\x38\x44\x8c\x53\x4e\xca\x90\xe3\xa0\xe6\x81\xa8\xd9\x66\x0e\xae\x2e\x18\xf6\x77\xc9\x86\xc8\xa0\x6d\x94\x87\xc8\xb0\xe3\x38\xf6\x8c\x13\x22\x23\xa0\x51\x66\x88\x90\x99\xf5\xcb\x60\x85\x46\x8e\x33\x12\xb2\x1e\xc7\x2b\x7b\x0e\x58\xf8\x0c\x11\x37\xea\xf0\x94\xb3\xf6\x79\xca\xbc\x7f\x9c\xc0\xbd\x00\xef\xa7\x4c\xa2\x7f\x1c\x9e\x08\x6d\x0c\x6f\x37\xf4\x19\xd4\x61\x33\x51\xaf\xe2\xfa\x43\xea\x8d\x66\xbc\x05\x90\x32\xef\xe2\x53\xc4\x1d\x96\x7a\x40\x3c\xf5\x80\x90\x11\x13\x32\xb7\x50\xa6\x66\x9f\xcc\xfe\x71\x9e\x13\x32\x31\x18\x91\xf0\xf6\x0d\xff\x26\x50\x23\x39\x42\x6f\xc7\x6c\x3d\xcf\x5a\x0b\x53\x89\x08\xfb\x56\x83\x16\x65\x6a\x01\x5e\x3f\xb5\x4a\x3c\xf5\x3b\x28\xcf\xbe\x83\xf1\x3b\xc0\xde\xf1\xd1\x0e\x79\xaf\xef\xf8\x74\x06\x8e\xc3\xde\x73\x63\x10\xf9\xb6\xbf\x72\xe0\xa5\x87\x54\x29\xfe\x53\x5e\x24\xab\x94\x7d\xb7\x1b\x2b\xef\x75\x3f\x81\xb9\x40\xac\x50\x4c\xac\x90\xcd\x20\x66\xa2\x4a\x79\x97\xf5\x77\x02\x49\x66\xab\x26\xa2\x4e\xc0\xef\x4a\x06\xf2\x0e\x6b\xf3\x9f\x23\xf6\xf5\xa7\x88\xf8\x82\x5e\x19\xc8\x3b\xf8\xc6\x0b\x9b\x9b\xa8\x16\x44\xbe\x8f\xfb\x6a\x22\xaa\x02\xd4\x79\xc0\x4f\x85\x18\x21\xff\x10\xa3\x68\x0f\x3e\xfb\x87\x81\x7c\xea\xb7\xf6\x6c\x22\x2f\xb3\xc8\x8d\x20\xc2\xe6\x38\x0e\x5a\x6c\xa0\xff\xd3\x89\x3b\x65\x7b\x17\xaf\xba\x07\xfe\xa7\x8a\x89\xbc\x53\x86\x08\x66\x6a\xba\x0c\x75\x88\x6f\x0e\x07\xfa\x2d\x2f\x82\x51\x9d\xbb\x84\xc8\x3f\x03\x38\x28\xaa\x1f\x74\xd7\x43\x04\xf5\xc3\xa8\x20\x58\xe1\xb3\xfe\xfe\xbb\x7e\x84\x7d\xf3\x5c\x90\x8f\x2b\xaf\xc6\xb9\xea\x02\x9d\x01\xbf\xef\xb8\xf0\xa9\x65\x5e\xb0\x23\xb4\x1c\xb4\x31\x36\xda\x04\xaa\xf7\x90\xf8\x1c\x8c\x90\x9c\x4c\x22\xfa\xb1\x11\xf2\xcb\x44\xf4\x73\x10\xd6\xeb\x40\x99\xcf\x60\x66\xc7\x77\xf5\xa9\xcf\x84\x89\x87\xf8\x2d\xde\x80\x37\x9d\x0d\xc4\x43\xbf\xef\x60\x0c\x0c\x89\x87\x81\x4e\x17\x3e\xb5\xbf\xd3\xf5\xaa\x4f\x12\x8c\x36\x4f\x83\x7a\xa6\x9f\xb2\x75\x2f\x71\xa6\x6c\xd7\xf1\xf3\x28\x63\xe3\xbd\xbe\x95\x04\xfa\x24\x5a\x22\x92\x58\x08\x9b\x67\xfd\xfd\x4a\xe0\xee\x19\xf4\xf7\x2c\xa2\x96\xc8\x0a\x22\x01\x1d\xfe\x7b\x44\xf0\x34\x99\x47\x88\xe4\xe2\x38\xab\x38\xce\xa7\x70\xcd\x66\x94\xc1\x3e\x12\xf3\x1f\x71\xe4\x7e\xff\xec\xfc\x5b\xfe\x68\x13\xf1\xd4\x7f\x46\xfc\x41\xbf\x0c\xff\xa8\xdf\x73\x23\xea\xfc\x32\x7c\xcc\xcb\xbc\x0b\x7e\x44\x70\xc7\x8f\xf0\xee\xfa\x11\x56\x33\x3c\xf6\x9b\xf7\x97\x77\x5b\x81\xe2\xfe\x96\x5f\x86\xf7\xc0\x2f\xc3\xf9\x02\xfa\xc5\x77\xb0\x66\x7b\x8a\xb3\xff\x1f\x38\x57\x27\xda\x0f\xfa\x17\xaf\xdc\xff\x14\xff\xd7\x70\x64\xcc\x95\xbc\x3c\xbf\x0c\x2f\xd6\x8f\xf0\x9b\xfc\x08\x37\x19\xf5\xf3\x9f\x03\xb7\x9b\xbd\xb7\xb6\x33\xc1\x5b\x1b\x35\x83\xb5\xdf\xc2\xbe\x2a\xb7\x34\x58\x9d\x32\x36\xcc\x20\x36\xa2\x02\xf9\x34\x31\xce\xa7\x89\x2c\x63\xde\x97\xad\xce\x04\xcf\x3d\xf4\x9e\x82\x7e\xf1\x4b\xfe\x28\xc1\x97\xf2\x5e\xf7\x9a\x98\xdf\xf2\xdb\x21\x2f\x0a\xfd\x02\xfb\x09\x81\xbb\x43\x2e\x11\x49\xd8\x0e\x1e\xef\xff\x65\xef\xdd\xe3\xa4\x28\xae\xfe\xe1\x53\x5d\x35\x3d\xb3\xcb\x02\x7b\xe3\xb6\x5c\x76\x76\x97\x5d\x70\x77\xb9\xb8\xa0\xb8\x80\x48\x10\xb9\x88\x22\x22\xe2\x82\x8a\x5c\x14\x11\x51\x11\x41\xbc\x81\xca\x4d\x24\x68\x8c\xf1\x82\x48\xd4\x00\x2e\x88\xca\x33\xcb\x02\x62\x07\xe5\x62\x7b\x89\xd1\x36\x4a\xd4\x4e\xd0\x44\x5b\x60\x45\x3b\x6a\x8c\xb6\x44\x85\xf3\x7e\xea\x74\xcd\x4c\x4f\x2f\xc4\xe4\xf7\x3c\xbf\xf7\xfd\xe3\x7d\x98\xcf\x77\x66\xb6\xa8\xee\xae\x3a\x75\xaa\xce\xb5\x6a\x9a\xd9\x0e\x19\x75\xd2\xb2\x52\xd5\x71\x03\xf6\x8e\xbf\x6e\x6c\x92\x5a\xae\x58\x43\x6d\x1e\x16\x98\xcb\xbe\x1c\x34\xe8\xaa\x8e\x81\x36\x97\x07\xf4\xba\x60\x1d\x5f\xaf\xcb\x4d\xd7\xd1\x6a\x89\xf2\xbe\xef\x3a\x8f\xfa\xfe\x0d\xb5\xa7\x94\xda\xb3\x83\x66\x9c\x4f\xe7\xb1\x69\xed\x3d\x7a\xad\xac\x9f\x45\xbb\x5e\x7d\x8e\xd2\xff\x2a\x9f\x1e\x7b\x97\x38\xea\x4c\x2a\xa9\xa3\x12\x1a\x1d\x7d\x27\x51\xac\x33\xf5\xeb\x92\x40\xdf\x7d\x1d\x72\x66\xba\xef\xfe\x0e\xbd\xa8\x45\x3c\x16\xa3\x3a\x0f\x12\x07\x1a\x74\xd5\xc9\xd4\xaf\xc8\x71\x34\x61\x79\x9f\xfc\xc0\xcc\xdd\xa5\xe4\x7b\x98\xa3\x82\x3e\x22\xbf\xce\x9a\x66\x75\x26\x07\xea\x5c\x49\x75\xcc\xb0\x2d\xcc\x0f\xa7\x79\x43\xd5\x69\x6e\x2f\xf7\x4c\xd7\x51\xdc\x7b\x49\x98\x7b\xb5\x3f\x04\x6c\x34\x53\xd9\x83\x61\x0e\xcf\x69\xc6\xe1\x03\x33\x38\x3c\x6d\x77\x5f\x74\xc2\x3a\x61\xff\xcf\x33\xd4\x66\x8b\xea\x24\x75\x6c\xf9\xac\xd9\x01\xdd\xf8\x19\xa5\x87\x87\xeb\x04\xf4\x67\x35\x9b\x56\x36\x9b\x4d\xcb\x9b\xe9\x87\xff\xb2\x4e\x86\xde\xfb\xe7\x63\x83\x92\xeb\x3c\xf7\xed\xee\x19\xb2\x44\xf3\xb3\x93\x7d\x4b\xf6\x2c\x6a\xcf\x2e\xe2\x79\x5a\x91\xd8\xc3\x01\x3f\x80\xbf\xaa\xfb\x76\xf7\xdd\x72\xee\x28\xed\xd4\x7f\x16\xed\xea\x8c\x90\xae\xa2\x8d\x81\xb4\x9f\xc4\x7f\xba\x3f\x07\x7f\x24\xcd\xf3\x35\xaa\xf3\x23\x4a\x2b\x98\x6c\xcc\x08\xed\x54\xd1\x96\xa8\x99\x2b\xdb\x73\xbb\xba\xaa\x6f\x6a\x55\xf7\xfd\x48\x0f\xc9\x12\xe5\x8f\xea\xaa\x8b\x7f\xc1\x87\x81\x08\x14\x3b\x48\x33\x2e\xb0\xfe\xb0\x6f\x89\xe7\x6b\xc2\xfe\x5e\x7f\x4c\xd5\x7c\xf7\xc7\x74\x7c\x60\xbe\x93\xbe\xca\xbc\xb4\xae\xae\x3c\xf6\x67\x91\x7d\xea\xeb\x1b\x4f\xa1\x9d\xd2\x1c\x7c\xdf\xce\x61\x59\xc2\x1a\x49\xc2\x3e\x20\xdf\x59\xa3\x2c\x51\x7e\x80\x4e\xf2\xdd\x5f\x01\xf8\xfd\xb4\x0b\x85\xb4\x1d\x7e\x3f\x8d\x72\x4f\xd2\x13\xc0\xd7\x13\x88\x86\x8b\x89\x33\xff\xee\xf7\x9d\x62\x52\xef\x13\x55\xdb\x51\xc9\x0d\x54\x72\x81\x6f\xc3\x52\x7b\xbe\x94\xf2\x42\xd9\xd4\xbe\x96\x5b\x90\xe6\x8d\x88\x4f\xc3\x38\xae\x09\xd9\x56\x07\x03\x91\x08\x25\x4f\xa9\xe4\x73\xba\x0f\xe9\xb4\xec\x79\xa2\xc6\x2f\xa9\xce\x20\xaa\xf3\x64\x40\x9a\x07\x63\x88\xcd\xb5\x82\x2b\x03\x75\xae\x54\xe3\x55\x9d\xf6\x59\x51\x2f\x06\x04\x74\xec\x01\xb2\x17\x19\xd1\xc0\xfb\xa8\xa4\x79\x2c\xe9\x07\x7a\xd6\x77\x54\xf3\x9e\xc0\x58\xf8\xe3\xb5\x47\xf6\x54\xe9\x51\x41\x5b\x38\x60\xe7\xaa\x79\xda\x2c\xd6\x96\x8a\xd4\xa4\x35\x90\x0b\xe9\x2a\x7f\x95\xb8\xd0\xe7\xc3\xc0\xb8\xab\xe8\x1b\xd5\xf1\xfd\xd8\x53\x95\x5e\x37\x23\xb3\xc4\xf7\x99\xab\x55\xeb\x4b\xaa\x03\x74\xd5\x2d\x54\xe7\xf2\xc0\x6c\xf2\x35\xbd\x29\xf4\x74\x9f\xe7\x03\x31\x3b\xa5\xa5\xf8\x5e\xd0\x0a\x7f\xcd\x0c\x94\xf8\xeb\xea\xb1\x66\x25\xad\x02\x32\x6e\x0e\x95\x74\x48\x8f\xbb\x36\x8a\x4a\x7e\x13\x28\x19\x4a\x25\xd3\x03\x7d\x7f\x06\xd2\x7e\xad\xfe\x01\x7f\x54\xa0\x85\x6a\x05\x28\x4f\xd3\x47\x95\x5c\x1c\xa0\xcf\xd3\x44\x8d\x17\xd2\x77\x66\x4f\x11\xd7\x1d\x0e\xd4\x39\xb7\x99\x56\x99\x97\x8e\x3c\x66\xf8\x6d\x82\x25\xd1\xb4\xcc\x0d\x46\x15\xc1\x53\x73\x50\x3e\xeb\x26\x7a\xfa\x49\x54\xd2\x9b\x4a\xae\xf0\x35\x6a\x9a\xdd\xbe\x97\xcf\xb7\x53\x0e\x52\xc9\x9f\xfd\xb5\x85\x4a\xea\x02\xde\xb0\xcf\x68\x2e\xe7\xd0\xd3\x5d\x7a\xfa\x01\x2a\xf1\x23\x98\x6f\xd0\x5c\xa6\x08\xe6\x09\x4b\x76\xd0\x55\xef\x9f\xc0\x06\x69\x5e\x32\x29\x60\x71\x6c\x4e\xdb\x20\x8a\x62\xbe\xfc\x2a\xa0\x3b\xdf\x46\xcf\xf2\xfd\x6c\xdf\x91\x5f\xeb\x26\x2a\xe9\x43\x75\x5a\xd1\x6a\xec\xaf\x87\x9b\x88\x62\x1f\x13\x35\x1e\x08\xcc\x8b\x01\xd4\x53\x3a\xe3\x46\x45\x4b\x33\xea\x64\x44\x54\x7d\xaf\x51\xa8\x84\x8d\xa2\x92\xc5\x74\xd5\x46\x2a\x19\x4e\xf7\xb9\x81\xe2\x14\xe4\xb3\x62\x7e\x9c\xf1\xa2\x00\x67\xaa\x78\x4a\x80\xeb\x2e\x02\x38\x9e\x47\x88\xad\x48\x8f\x97\xcf\x87\xcd\x4b\xe0\xa8\x1f\xc9\xa5\xab\x6a\x03\x75\x36\x06\xae\xf2\x6d\xa2\x8d\xb4\x62\xaf\x87\xb4\xb7\xe7\x0f\x01\x2b\xa9\xb9\x75\x33\x96\x4a\x48\xfb\xd2\xee\xa5\x12\x7f\x74\x7c\x4d\x78\x35\xa4\x22\xc5\xbe\x47\x3a\x18\x29\x56\x63\xe1\x47\x8a\xed\xc0\x7c\x2f\xa4\x12\x9a\x05\x4a\x8f\x0a\xda\x3b\xbe\xc7\xec\xda\x8c\xd8\xb1\xac\x33\x10\xc7\x03\x63\x1f\x05\x66\x13\xb5\xf9\x38\x25\x9f\xa7\x33\x04\xd8\x9b\x4a\x27\x49\xe7\x0c\x4c\xa0\x92\xe7\x89\x3e\x74\xd6\x06\xfb\x9c\xda\xdc\x3a\xb0\x46\xb5\x3e\x81\x75\x3c\x2a\x30\x82\x8f\xfa\x72\x27\xb0\x92\x4c\xa7\x92\x8b\xe5\xac\xf4\xfb\xae\xed\x4a\xaf\x5a\x8a\x62\xf3\xe1\xb8\x39\x03\xcc\x09\xac\xc6\x0e\x95\xbc\x47\x77\xf6\x75\xad\xf7\x02\x5a\x01\xb5\x4a\xc5\xfa\x3f\x0f\xd8\xb0\xc1\x9e\x52\x89\x1f\x0d\x8c\x2c\x90\xf7\x89\x0e\x25\x4b\x8a\x38\x3c\xb2\x2e\x50\xb2\x4e\xde\x27\x72\x7b\xa0\xe4\x16\x49\x67\xde\x3e\x72\x13\xb0\xc8\xe5\x34\x82\xe3\xe8\xe9\x57\xd1\x08\xfa\x56\xed\x55\xb4\x02\x5c\x4c\x75\x5e\xa3\x3a\x17\x93\x05\x34\x8d\x66\xe5\xa9\xa4\x99\xcf\xa7\x3a\x77\x05\xe6\xf2\x3e\x9a\x95\x5d\xa9\x64\x6e\x80\xa3\xf2\xd2\x52\xd8\xb7\x2f\xb4\xba\x40\x09\x79\x18\xb4\x9c\xc0\x2a\x31\x9b\x46\xa7\x79\x89\x92\x44\x7a\xda\x8b\xd5\x2c\x0f\x44\x65\x7d\xd0\xf9\x38\x7e\xd6\x47\x2a\x13\xc3\x6d\x96\x89\x91\x9e\x05\x15\x81\xd1\x79\xa3\xd9\x0a\xe0\xaf\x1b\xfe\x0a\xe0\xfb\x1c\x16\x37\x9b\xcb\x99\x79\x17\x29\xff\xea\x71\x6c\x7c\x3f\xce\xf8\x76\x40\xa6\x88\x80\xb6\x73\x9f\xf6\x80\x1c\x7d\xaa\xf3\x0a\xd5\xf9\x3d\xd9\x44\x37\x90\xae\x35\x87\x34\x01\xf2\xc5\x01\x49\x46\x2d\x16\xb0\x1d\x20\x50\x72\xd3\xf1\xfb\xe5\xc7\x53\x14\xaf\x2e\x0a\xac\x00\x0b\x03\xe3\x15\xa4\x73\x05\x69\xb0\x01\x3a\xb3\x7f\x50\x49\xcb\x34\x9d\xb5\x96\x54\x52\x9e\x7e\x16\xef\xda\x3c\x4f\xe6\x58\x65\x28\x7a\x12\x93\x25\x19\xa3\x73\x0d\xe9\x7e\xc1\xd1\xe9\x45\x77\x0e\xf4\x42\xab\x08\x8c\xce\x2d\x6a\x7d\x6e\xdb\x4c\x1b\x94\x7a\xf8\xb7\x81\x95\x9f\xf4\xe7\x54\xc6\x8b\x9b\x6c\x73\x2a\xbf\xc5\x25\x8f\x50\xdf\xd0\x1a\xf5\x4e\xb8\x5f\xda\x94\x63\xab\x8e\x5b\xe2\xd3\xe7\x87\xb4\xb6\x13\x8a\x72\x4a\xdd\xef\x50\xba\x85\x5a\x2b\x2a\xd9\x15\x28\xe9\x70\x6c\x44\x72\x95\x50\x57\xbd\x26\xef\xec\xaf\x24\xec\x36\x5f\x07\xa0\x3a\x67\x05\x38\xf3\x41\x6a\xf3\x46\xea\x69\x6f\xdd\x8f\x6d\xf5\x0d\xf9\xc3\xaf\xa6\x67\x7d\x1a\x58\xc7\xba\xca\xfb\x64\x44\xc0\x87\x1f\x4d\xa4\xb4\x41\xff\xaa\x72\x2a\xb9\x35\x90\xa5\x73\x6b\x33\xde\x98\xda\x4c\x7f\xbe\x94\x9e\xee\xd7\x59\x4b\x25\x43\xa9\x24\xb3\xce\x2a\xaa\x33\x2e\x55\xa7\x82\x4a\x4e\x10\xdd\xce\x98\xdd\x41\xdf\xf2\x15\x61\xce\xd4\xce\xa4\x92\x60\x9d\xeb\x02\xa3\xa3\xee\xe3\x3f\x2b\x50\xe7\x62\xb2\x2b\x83\x75\x6a\xa9\x24\xf3\x3e\xb3\x9b\xdd\x67\x76\xd2\x23\xad\xac\x80\x76\x54\x32\x20\x3c\xee\xff\x56\x9d\x78\xb3\x68\x0e\xc5\x26\xf8\x74\x69\x53\xa8\xec\x35\xfa\x4d\xdb\xcc\xc8\x35\x59\x76\x41\xed\xf4\xcd\x40\x34\x47\x45\x9c\x03\x91\x88\x60\x54\xda\xaf\xf3\x4b\xa2\x58\x30\x2a\x5d\x4e\x25\x6f\x52\x94\x3c\xf3\x3e\xe9\x6c\xa8\xe6\xf7\x19\x15\xce\xa6\xf3\xe5\x57\x46\x9d\x05\xcd\x9e\x45\xe3\x95\x91\x45\x79\x4e\x33\x2b\xe9\x33\xa2\xcf\xdc\x40\xbf\x7c\x6f\xd8\x30\xe5\x0d\x1b\x9c\xf2\x86\xcd\x0d\x58\x49\x0b\xe9\x59\xc3\xe8\x59\xbb\xd5\xfa\xd3\x37\x54\x67\x2e\x71\x42\x66\x9d\x55\x99\xb6\x27\xfb\x96\x5a\xd8\x3b\x43\x5b\xee\x4b\x31\xe8\xde\x69\xfb\xd4\xaf\x13\xad\x4b\x45\x6a\x3e\xf2\xeb\x04\x6d\x58\x35\x97\x83\xab\xdf\xaa\x66\x75\x66\x87\x9e\x75\x4c\x96\xf0\xa5\xe4\xe9\x0a\x66\x87\x3e\x4e\x3e\xd8\x1d\x01\x3d\xfc\x78\x75\xaa\x53\xfa\xb3\xaa\xa3\xa7\xb3\x4c\x4f\x91\x2d\xe4\x8f\x07\x75\x6c\x2a\x39\x9e\x57\xed\x5f\xc5\xa9\x77\x51\x4f\x9b\xad\xd8\xa1\x3a\xab\x42\x75\x6a\x65\x49\x46\x9d\x7d\xcd\x56\xfe\x5a\x2a\x79\x24\x10\x05\xbe\x5e\xad\x3f\x83\x43\x12\xed\x78\x75\xaa\x43\x75\x56\x05\xd6\x31\x65\x41\x93\xb5\x3e\x42\x1c\x3f\x9a\x3c\x9b\xc6\xf4\xbf\xd2\xeb\x33\x34\x51\x4f\x83\x75\xee\xa5\x31\x0d\xd4\x61\x11\xea\xe9\xf0\x40\x7e\x42\x32\xc2\xdb\x3e\x53\x4f\xc8\x88\x14\x7f\x47\xcf\x0a\xca\xaf\x46\x7a\xd6\xf0\x40\xbf\x8a\x95\x1d\x37\x38\x15\x01\x57\x51\xe9\x58\x5f\x6a\xcf\x1b\x81\x67\x7d\x23\xef\x1c\x59\x19\x88\x5c\xcf\x4a\xc6\x53\xd4\xb3\x5e\x08\xf4\xfd\x05\x7a\xd6\x08\xaa\x13\xc8\x01\x66\xeb\xa3\x31\x29\x65\xd2\xd6\x44\x86\x77\xee\x0f\x74\x1f\xdf\x3b\x17\x57\x9a\x79\xdf\x50\x9d\x03\x44\x9f\xcc\x3a\xab\x9a\xd5\x99\xdd\xac\xce\xec\x90\x07\x66\x0d\x5d\x15\xb4\x5c\xce\xa5\x92\x60\x9d\xe5\x74\x55\xb0\x4e\xaf\xe3\xdc\x27\x5c\xe7\x4c\x2a\x59\x42\x6b\x4b\x20\xb7\xd9\xa7\x73\x52\x4f\x00\x08\xe5\x3f\xe7\x50\xdf\x03\xba\x04\xdb\x4f\x3c\xff\x00\x45\x9c\x03\x19\xd1\xbc\x1b\xcd\xd3\x39\x69\x2b\xe9\xdf\xac\x33\xab\x59\x9d\xf6\xa1\x3a\x7f\x08\xdf\x47\xc3\x66\x75\x82\x19\xda\x53\x69\x74\x92\xf9\xbd\xb2\x5f\x1f\x53\xc9\x53\xd4\xf7\x40\xce\x36\x3b\x12\xc8\xd3\xf3\xb3\xc1\x1f\x24\x59\xf0\xaf\xeb\x34\xcb\xfc\x64\x76\xba\x8e\xf2\x3e\x4d\x21\x1e\xcb\x8c\x77\x0f\x4e\xeb\x5a\x00\x99\xf9\xe1\xec\x70\x33\x7d\xcc\xf7\xa6\x06\xeb\xfc\x83\x78\x2c\xb3\xce\xaa\x94\x2f\x25\x57\x49\xf3\x55\x29\x7e\xf6\x57\xf5\xf5\x8a\xaa\xeb\x25\x35\x22\x97\xa7\xf2\x01\x28\x33\x41\x9c\x23\x4b\x92\x6d\xa6\x6c\xd5\x73\x22\x63\x52\x1a\x48\x6b\xca\x35\x1a\x1b\x90\xcb\x19\x7a\x94\xaf\x93\x34\xd3\x60\x17\xc7\x72\x68\x9e\xae\x0f\x78\x80\x77\x84\xee\x1c\xd4\x13\x38\x5d\x15\xd4\x13\x3a\x53\x49\x15\xdd\x67\x21\xdd\x27\x19\x65\xd8\x41\xf3\x7d\x4c\xca\x3f\x56\x75\x9c\x6c\xba\x74\x6c\xcb\x8f\x44\x2c\x97\xf7\xe1\x23\xe4\x7d\x52\x51\x86\x1d\xc0\xb4\x1f\xe5\x7d\x82\xd9\x62\x4a\x2e\xf7\x54\x72\x30\x2d\x97\x7d\x19\x17\xb4\xa0\x4d\x2a\x21\x8f\x87\x8a\x32\xf8\xba\x84\x2b\x9f\x15\x19\x48\x6d\x4e\x7a\xad\x65\xdf\x8b\xa8\xcd\xbe\x9f\x24\x73\x9e\x92\x9e\x10\x98\xa7\xb5\x54\x62\xd2\x7d\x56\x66\x64\x8f\xc8\xfb\x2c\xa7\xfb\xf8\x3a\xc9\x90\x66\x19\xc8\x85\x01\x79\xe1\x8f\x69\xc0\x53\xca\x7e\xa4\x3b\x17\x36\xf3\x94\x0e\xa1\x67\xf9\x99\x2a\xc9\xfb\xa4\xc6\x2b\x59\xe7\xa7\x9f\xc5\x9e\x54\x36\x7e\x02\x18\xfb\x38\x60\xfd\x91\x36\xae\xc6\xbd\x99\xaf\x3b\x43\x4f\xe8\x7d\xfc\x3a\xc7\xd9\xfd\x11\x94\x4d\x95\x8a\x7b\xab\x93\xb6\xb9\xaf\x1f\xb2\xf5\x81\x5c\x23\xdf\x97\xe2\x06\x78\xb5\x3b\xdd\xc7\xcf\x1f\xeb\x4c\x2b\x89\xb4\x34\x35\x28\xf9\xc9\x13\x58\x6e\x67\x55\xec\x4e\x76\x27\xeb\x41\xe7\xb0\xf4\xa4\x73\x58\xce\xa0\x73\x58\x06\xd3\x39\x2c\x75\x74\x0e\xcb\x6c\x3a\x87\xe5\x0e\x3a\x87\x65\x11\x9d\xc3\x02\x91\xfa\xc8\xb3\x5a\xaf\x48\x22\xf2\xbc\xd6\x2f\xf2\x62\x64\x8f\xf6\xb3\x88\x19\xd9\xa7\x9d\x15\x79\x2f\xf2\x77\xed\xc2\xc8\xf7\x3a\xf5\x54\xef\xac\xdd\xac\x97\xea\x3f\xd3\x7e\xa5\x9f\xa9\x0f\xd3\x1a\xf5\x8b\xf5\xc9\xda\x73\xfa\xd5\xfa\x1c\xed\x05\xfd\x2e\x7d\x85\xf6\xb2\xfe\xa0\xbe\x46\xfb\x5d\xf4\x8b\xe8\x17\xda\xdb\xb1\x73\x63\xe7\x6a\xef\xc4\x26\xc5\x2e\xd7\xf6\xc5\xae\x8b\x5d\xa7\xfd\x39\x36\x27\x36\x47\xdb\x0f\x1a\xb4\xd0\xf6\x6a\x1f\x00\x68\x7f\xd1\x1c\xe8\xa8\x1d\xd4\x3e\x85\xb8\xf6\xb9\xf6\x2d\x74\xd5\x7e\xe0\x0c\x7a\x71\xc1\x73\xe1\x54\x9e\xcf\x3b\xc0\x99\xbc\x23\xef\x0c\xa3\x78\x39\x3f\x19\x46\x8b\xbe\xa2\x1f\x5c\x1c\x79\x24\xf2\x24\x5c\x06\xb3\x00\xd8\x16\x00\xb6\x03\x80\xbd\x08\xc0\x4c\x00\xf6\x3a\x00\xfb\x03\x00\x7b\x0f\x80\x7d\x00\xc0\x1c\x00\xf6\x29\x00\xfb\x02\x80\x7d\x03\xc0\xbe\x97\x64\x04\xd0\x74\x00\x2d\x07\x40\xcb\x07\xd0\xda\x03\x68\x5d\x00\xb4\xae\x00\x5a\xa5\xb4\xdf\x40\xd3\x4e\x05\x4d\x1b\x08\x9a\x36\x04\x34\x6d\x04\x80\x36\x1a\x34\x6d\x1c\x68\xda\x44\xd0\xb4\xc9\xa0\x69\xd3\x41\xd3\x66\x81\xa6\xcd\x01\x4d\xbb\x09\x34\x6d\x21\x68\xda\x12\xd0\xb4\x15\xa0\x69\xf7\x81\xa6\x3d\x04\x9a\xb6\x06\x34\x6d\x2d\x68\xda\x46\xd0\xb4\xcd\xa0\x69\x5b\x41\xd3\x0c\xd0\xb4\xdd\xa0\x69\xaf\x80\xa6\xbd\x01\x9a\xf6\x0e\x68\x9a\x0d\x9a\xf6\x17\x00\xed\x00\x80\xf6\x19\x80\xf6\x15\x80\xe6\x01\x68\x3f\x02\x70\x0d\x34\x1e\x03\xe0\xad\x40\xe3\x85\xa0\xf1\x22\xd0\x78\x1c\x80\x57\x00\xf0\x6a\x00\x5e\x03\x1a\x3f\x0d\x34\x3e\x08\x80\x0f\x05\xe0\x67\x03\xf0\x31\xa0\xf1\xf1\xa0\xf1\x4b\x40\xe3\x53\x41\xe3\x33\x00\xf8\xb5\xa0\xf1\xb9\xa0\xf1\x5b\x00\xf8\x1d\x00\x7c\x19\x00\x5f\x09\xc0\xef\x07\xe0\xab\x00\xf8\x63\x00\x7c\x3d\x00\xdf\x04\xc0\x13\x00\x7c\x3b\x00\xdf\x09\xc0\xf7\x02\xf0\xd7\x00\xb8\x05\xc0\xff\x08\xc0\xff\x0c\xc0\x3f\x02\xe0\x87\x00\xb8\x0b\xc0\xbf\x06\x8d\x1f\x01\xe0\xc7\x00\x84\x00\x10\xd9\x00\x22\x17\x40\xb4\x05\x10\x9d\x00\x44\x29\x68\xa2\x3b\x80\xe8\x09\x9a\xe8\x0b\xec\xe8\x04\xc9\xd3\x47\xaf\x91\xef\x48\x1a\xc0\x51\xb2\xa2\xd1\xa0\x77\x4f\xea\x1f\xea\x7b\xd7\xf4\xfb\xd1\x1b\x03\x75\x86\xd0\x7b\x94\xde\x6d\xb1\x1c\x18\x16\xc9\x77\xff\xce\xa8\xab\x72\xf9\xbe\x90\x2f\x01\x86\xe3\xe9\xdd\xa3\xf7\xc9\xfc\x12\x60\x50\x43\x5e\x9b\xe0\x7b\x17\xf9\x8e\x34\x03\x61\x13\x95\x14\x1e\xff\xfd\xe8\x96\x66\xe5\x70\x82\xfa\xd0\xec\xbd\x7b\xb3\xfa\xd9\xaa\xfc\x72\xf9\xf4\x40\x49\xe0\x3e\x68\x89\xb9\xc0\xd0\x94\xef\x50\x18\xf9\x20\x45\x87\x7a\x71\x0e\x7d\x5f\x93\xbc\x0a\x4d\xfa\x5e\x23\xef\x06\x5b\xd3\x4f\x44\x83\xee\x60\x88\x85\xc9\x6b\xd5\xfd\xbb\xa8\xfb\xcb\x72\x27\xf0\xbf\x5d\x02\xad\xed\x9e\x71\x9f\x35\x99\x3d\x52\xd7\x9e\xc3\x3e\xfa\x9f\x7b\x67\x1f\x89\x99\xe4\xcd\x97\xeb\x72\x56\xfa\x1d\xcd\xf4\xbb\xa2\x8c\x49\x4f\x37\xc5\xfd\x3f\xf5\xae\x5a\x1b\xf8\x9e\x9d\x4f\xbf\x0b\xdf\x16\x4e\x85\x67\xe0\x10\xb8\xac\x82\x9d\xc3\x26\xb2\xe5\xec\x75\x4d\x68\xc3\x84\x19\x19\x1f\x79\x2d\xf2\x9a\x3e\x5e\x3f\xa2\x1f\x89\xbc\x16\xfb\x3e\x6b\x56\xe4\x35\xe8\x0c\xad\xd1\x84\x3c\x34\xa1\x14\x0a\xa1\x2b\xba\xb0\x08\x5d\x58\x8c\x2e\x2c\x41\x17\x96\xa2\x0b\xcb\xd0\x85\xbb\xd0\x85\xbd\xe8\x82\x89\x2e\xbc\x82\x2e\xdb\x89\x6e\xa4\x1e\x5d\xfd\x4c\x74\xf5\xb3\xd0\xd5\x87\xa3\xab\x8f\x44\x57\x1f\x85\xae\x7e\x2e\xba\xfa\x79\xe8\xea\xe7\xa3\xab\x5f\x80\xae\x7e\x21\xba\xfa\x45\xe8\xea\x13\xd0\x8d\x3e\x81\x66\x74\x3d\x9a\xd0\x0a\x22\xd0\x1d\xb2\xa1\x3b\xe4\xc0\x30\x28\x85\x31\x30\x18\x86\xc1\x59\xd0\x05\x46\x41\x17\x18\x0d\x5d\xe0\x3c\xe8\x02\x93\x61\x18\x34\x41\x17\x38\x0c\x03\xa3\x8f\x43\xf7\xe8\x3a\xe8\x0e\x0c\x7a\x40\x4d\xb3\xeb\x87\xfd\xc4\xf5\xc3\x52\xd7\x67\x41\x6b\xb4\x21\x0f\x6d\x3e\x00\x5d\x3e\x14\x5d\x3e\x1c\x5d\x3e\x1a\x5d\xee\xb7\xcf\x8e\xae\x47\x1b\x38\x1f\x85\x1e\x1f\x8b\x1e\xaf\x43\x07\x5a\x40\x6b\x5c\x08\x79\xb8\x90\x0f\x40\x8b\x0f\x45\x8b\x0f\x47\x8b\x8f\x44\x8f\x8f\x46\x4b\x5e\xc7\xaf\xa1\x6b\x17\x46\xd7\xe3\x42\xc8\x85\xd6\x68\x41\x1e\x5a\x19\x4f\x18\x89\x0e\x3d\xe5\x42\xf4\xf8\x78\xb4\xf9\x45\xe8\xf0\x09\xe8\xf1\x4b\xd1\xe1\xd7\xa0\xc7\x17\xa3\x13\x7d\x02\xad\xe8\x7a\xb4\xa0\x15\xe4\xa2\xc5\x27\xa1\xcb\xa7\xa1\xcb\xa7\xa3\xcb\xaf\x47\x97\xcf\x41\x97\xcf\x45\x97\xcf\x43\x97\xdf\x88\x2e\xbf\x09\x5d\xbe\x10\xdd\xe8\x23\x68\x45\x57\xa3\x15\x7d\x14\x2d\x7a\xb6\x03\xb9\xe8\x42\x1e\x3a\xcd\xee\x90\xbc\x3a\x7d\xa5\x1b\x5d\x8d\x6e\xf4\x51\x6a\xbd\x13\x5d\x8f\x0e\x3c\x4e\xfc\x90\x4b\x34\x32\xf9\x36\x74\xb9\x81\x16\xdf\x83\x06\x7f\x19\x2d\xfe\x06\x5a\xfc\x2d\x74\xf9\x3b\xe8\xf2\x7d\x50\xc8\xdf\x45\x9b\x7f\x82\x06\x3f\x80\x2e\x3f\x84\x06\x6f\x42\x97\x7f\x8a\x2e\x3f\x8c\x16\xff\x0c\x2d\xfe\x39\x5a\xdc\x45\x93\xff\x0d\x2d\xfe\x05\x5a\xfc\x4b\x34\xf8\x57\x68\xf1\xbf\xa3\xc5\xbf\x46\x83\xff\x03\x2d\xfe\x0d\xda\xfc\x5b\x34\xb8\x87\x2e\xff\x0e\x2d\x7e\x04\x2d\xfe\x4f\xb4\xf8\xf7\x68\xf1\x1f\xd0\xe6\x3f\xa2\xc5\x8f\xa2\xc5\x8f\xa1\xcb\x11\x2d\x01\xe8\x08\x39\x6f\x35\x34\x84\x40\x57\x44\xd0\x10\x3a\x9a\x22\x1b\x4d\xd1\x02\x2d\xd1\x12\x2d\xd1\x0a\x2d\xd1\x1a\x6d\x91\x8b\x96\xc8\x43\x57\xe4\xa3\x2b\xda\xa2\x25\xda\xa1\x21\xda\xa3\x29\x8a\xd0\x12\x9d\xd0\x12\x5d\xd0\x12\x71\x74\x45\x29\x5a\xa2\x0c\x5d\xd1\x15\x0d\x51\x81\xae\xe8\x8e\xae\x38\x09\x5d\x51\x89\x86\xa8\x42\x57\x54\xa3\x21\x7a\xa0\x2b\x7a\xa2\x21\x7a\xa1\x2b\x7a\xa3\x2b\x4e\x46\x57\xd4\xa0\x21\x06\xa2\x25\x06\xa3\x25\x86\xa0\x25\x86\xa1\x25\x46\xa0\x2b\xce\x46\x57\x9c\x83\x96\x18\x8d\x96\x18\x8b\xb6\x18\x87\x96\x18\x8f\x96\xa8\x43\x4b\x4c\x40\x57\x4c\x44\x43\x5c\x8c\xae\xb8\x04\x0d\x71\x29\x14\x8a\x49\x68\x89\xc9\x68\x8b\xa9\x68\x8b\xcb\xd1\x15\xd3\xd1\x16\x33\xd0\x12\x33\xd1\x12\xb3\xd0\x12\xd7\xa0\x25\xae\x45\x43\x5c\x87\x96\x98\x8d\x86\xb8\x01\x5d\x31\x0f\x2d\x71\x23\x5a\x62\x3e\x9a\xe2\x66\xb4\xc4\xad\x68\x89\x05\x68\x89\xdb\xd1\x12\x77\xa2\x21\x16\xa3\x21\x96\xa2\x21\x96\xa3\x21\x56\xa0\x2b\x56\xa2\x2b\xee\x45\x57\xdc\x87\xae\xb8\x1f\x1d\xf1\x00\x5a\xe2\x21\xb4\xc4\xc3\xe8\x8a\x55\x68\x88\x47\xd0\x15\xab\xd1\x10\x8f\xa2\x2b\xd6\xa0\x21\x1e\x43\x57\x3c\x81\xb6\x58\x8b\xb6\x58\x8f\xb6\xa8\x47\x4b\x6c\x44\x4b\x6c\x42\x4b\x6c\x96\x72\x05\x5d\xd1\x80\x86\xd8\x82\x86\x68\x44\x43\x6c\x45\x43\x6c\x47\x4b\xec\x40\x4b\x3c\x8f\x96\x30\xd0\x14\x3b\xd1\x12\x2f\xa0\x2b\x5e\x44\x43\xec\x46\x5b\xec\x45\x43\xbc\x84\x96\x30\xd1\x8c\x3e\x82\x76\x74\x35\xda\xd1\x47\xd1\x4e\xad\x0b\x5d\x21\x82\x0e\x64\xa3\xc3\x1b\xd1\xe1\xcf\xc3\xe5\x7c\x27\x3a\x7c\x1f\x3a\xdc\x46\x93\xef\x47\x87\xb8\xe3\x07\x74\x45\x09\x9a\xa2\x1c\x1d\xd1\x0d\x1d\x71\x3e\x3a\x62\x2c\xba\xe2\x52\x74\xc4\x65\xe8\x8a\x29\xe8\x8a\x2b\xd0\x11\xd3\xd1\x15\x57\xa2\x49\x94\xbc\x0a\x4d\xa2\xe6\x6d\x68\x12\x95\x9e\x44\x93\x7a\xb4\x0d\x5d\x6a\xf5\x73\xe8\x52\xcb\x77\xa1\x23\x76\xa3\x1b\x7d\x1c\x9d\xe8\x3a\x74\xa0\x53\xaa\x45\xdf\xa0\xcb\x8f\x60\x82\xff\x40\xbc\xe5\xf3\x54\x92\x57\x24\x3f\x8c\xa5\x31\x74\xc5\x54\x1a\x3f\x4b\xcc\xc0\x84\x98\x89\x09\x71\x2d\xba\x62\x36\xba\x62\x01\x26\xc4\x13\xe8\x8a\xb5\xe8\x8a\xf5\xe8\x8a\x7a\x4c\x88\xed\xf4\x54\x57\xec\x46\x2b\xf5\xc4\x32\x9a\x75\xcf\xc3\x07\xa9\x99\xf6\x2e\xf5\xdb\xa6\x7e\x4b\x6e\x8e\x43\x17\x51\x8a\x1e\x71\xac\xe4\x52\xc9\xa1\x92\x3b\x7b\x29\xae\x94\xb4\x90\x5c\x76\x31\xb5\xc4\x15\x33\xd0\x16\x33\xd1\x16\xd7\xa0\x43\xad\xb9\x0e\x1d\xd5\x22\x9b\x46\x5f\x8e\xfc\xa3\xd4\x22\x3b\xd5\xa2\x17\xa8\x55\x2e\x74\x87\x08\x26\x20\x1b\x13\xbc\x11\x13\x6a\x44\x12\x7c\x1f\xd6\x73\x1b\xeb\xf9\x7e\x4c\xf0\x23\xe8\xca\x79\x2a\x4a\xb0\x5e\x94\xa3\x21\xba\xa1\x21\xce\xc7\x04\xf1\xfd\xa5\x58\x2f\x2e\xc3\x84\x98\x82\x09\x71\x05\x26\x88\xaf\xaf\xc4\x7a\x31\x03\x5d\x71\x15\xd6\x8b\x99\xe8\x36\x6b\xd5\x6d\x58\x2f\x16\xa0\x2b\x9e\xc4\x7a\x51\x8f\xae\xd8\x86\x73\xc5\x76\xb4\xc5\x73\x38\x57\xec\x40\x5b\xec\xc2\x84\xe4\xa5\xe8\xe3\x98\x88\xae\xc3\x04\xdc\x91\x94\x60\x6a\xb5\xb2\xf9\x1e\x34\xf9\xcb\x68\xf3\x37\xd0\xce\xa0\xe1\xc7\xb4\x5a\x59\xfc\x10\x5a\xfc\x30\x3a\xfc\x33\x74\xf8\xe7\xe8\x70\x17\x2d\xfe\x37\x74\xf8\x17\xe8\xf0\x2f\xd1\xe2\x5f\xa1\xc3\xff\x8e\x0e\xff\x1a\x2d\xfe\x0f\x74\xf8\xb7\x68\xf1\xef\xd4\x18\xfc\x13\x1d\xfe\x3d\x3a\xfc\x47\x74\xf8\x51\x74\x38\xa2\x23\x00\x5d\x21\xf5\x06\x0d\x2d\xc1\xa1\x50\x44\xd0\x12\x3a\xda\x22\x1b\x2d\xd1\x02\x1d\x91\x03\x85\xa2\x25\x3a\xa2\x15\x3a\x22\x17\x1d\x1a\xc3\xb6\xe8\x88\x76\x68\x8a\xf6\x68\x89\x22\x74\x44\x27\x74\x45\x17\x74\x44\x29\xba\x6a\x25\xb2\xd4\x0a\x64\xa9\x15\xc8\x52\x2b\x90\x95\x1a\xe7\x1a\xb4\xc4\x40\x74\xc4\x20\x28\x14\x83\xd1\x11\x43\xd0\x11\xc3\xd0\x11\xe7\xa0\x23\x46\xa3\x23\xc6\x40\xa1\x18\x87\x8e\x18\x8f\x8e\xa8\x43\x47\xad\x3c\x96\x5a\x79\x2c\x31\x09\x9d\x14\x6f\xcc\xa2\x51\xb0\xc5\x6c\xb4\xc5\x3c\x74\xc4\x8d\x68\x8b\xf9\x68\x89\x9b\xd1\x11\xb7\xa2\x43\xbc\x72\x3b\x3a\xe2\x4e\x34\xc5\x22\xb4\xc5\x62\x34\xc5\x12\xb4\xc5\x52\x34\xc5\x32\xa9\xb3\xa2\x25\xee\x46\x4f\xfc\x1c\x3d\xf1\x00\x3a\xe2\x21\x74\xd4\xca\x62\xa9\x95\xc5\x52\x2b\x8b\x45\x7c\xb6\x11\x1d\xb1\x09\x1d\xd1\x80\xb6\xd8\x82\x96\x68\x44\x5b\x6c\x45\x2b\xc5\x7f\xcf\xa3\x2d\x0c\xb4\xc4\x4e\x74\xd4\x0a\x62\x89\x3d\xe8\x89\xbd\x68\x89\x97\xd0\x16\x26\x5a\xa9\x55\x43\xce\x51\x0b\xb2\x49\x96\xfc\xdf\x98\xa3\x36\xf1\x9d\x3f\x47\xad\xe8\x3a\xb4\xe0\xa4\xd4\xaa\x20\x67\xc4\x3e\xe2\x2f\x97\xdb\x68\xab\xd9\xe0\x88\x7c\xf4\x44\x09\xda\xa2\x9c\x5a\xe0\x89\x6e\xd4\x0a\x4f\xf4\x46\x4f\x8c\x45\x47\x5c\x8a\x2e\xad\x55\x93\xd1\xa3\xf5\x6a\x2a\x7a\x62\x3a\x3a\xe2\x4a\x5a\xf9\xe5\xec\xb0\x4f\x30\x3b\x6c\x35\x3b\x6c\x35\x3b\xe4\xfa\xe5\xa8\xf5\x4b\xae\x5d\x4e\x6a\x25\x61\xd0\x16\x4e\x82\xb7\xe1\x2b\x06\xfc\x2c\x3e\x92\x8f\xe3\x75\x7c\x06\xbf\x99\xef\x13\x67\x89\x61\x62\xb8\x18\x25\x2e\x12\x97\x89\x29\x62\x9a\x98\x25\xe6\x8a\x67\x81\x5d\xfc\x98\xd4\x20\xd9\x01\xfe\x0e\x7f\x27\x26\x62\xd9\xd9\xf1\x58\x76\xf6\xf4\x16\x75\x39\x95\x2d\xea\x72\x76\xe7\xbc\x92\x53\xd9\x6a\x55\x8b\xba\xd6\xef\xb4\xa8\xcb\xad\x2b\x58\x56\x70\xa4\xe0\x48\x4e\x65\xdb\xf7\x3a\x98\x31\x51\x34\xb1\x68\x56\xd1\xe6\xa2\x59\x45\xbb\x8b\x26\x16\xbd\x53\x34\x91\xfe\x9e\xd5\x71\x63\xd1\xe6\xce\x7a\x67\xbd\xe8\x9d\xce\x7a\x4c\x64\x4f\x4f\xbf\x72\x76\xe7\x54\xe6\xec\xf6\x5f\x2d\xea\x82\xaf\x82\x65\xfe\xab\xed\x7b\xad\xfd\xfb\x24\x5f\xb3\x32\x5f\x9d\xab\x8b\x66\x75\xd6\x25\xb2\xa7\x17\x4d\x4c\x22\xa7\xd2\x7f\xb5\xa8\xeb\x3c\x48\xb6\xb9\x68\x56\x18\xb2\x4e\xd1\x3b\x45\xef\xb4\x5a\x25\x5f\x5d\xe2\xf2\xbd\x68\xa2\xff\xec\x9c\xdd\x1d\x37\xca\x57\x6e\x5d\xd1\x66\x1f\xc9\xd6\xd0\xeb\x48\x67\xbd\xed\x7b\x12\x1d\x4c\xf9\x2a\xd6\x8a\x47\xd0\x33\x77\x4b\x7a\x14\x6d\x2e\xbe\xb7\x78\x77\x5c\x8f\xaf\xe9\x5c\x5d\x7c\x6f\x7c\x73\xc9\xe0\xe2\x7b\x4b\xbc\xe2\xdd\xa5\xdd\x65\x79\xe9\xa0\x92\xc1\x71\xbd\xf4\xab\xd2\xee\x65\x5f\xc7\xd7\xc4\xf5\xae\x9d\x8a\x26\x76\x2d\xed\xda\xa9\xeb\xc0\xae\x63\x8b\x26\x96\xf7\xed\x5a\x5a\x3e\xac\xfc\xf2\xae\x03\xcb\xd7\x96\xaf\x2d\xdf\x59\xbe\xb6\xdc\xea\x5c\x5d\xbe\xb6\xe2\x0f\x71\xbd\xc2\xe9\xb6\xb5\xb2\xa6\x72\x7d\x85\x23\x5f\x95\x9b\xab\x06\x56\xdf\xd8\xa3\xba\xc7\x9c\x6e\x5b\x7b\xac\xa9\xdc\xdc\x63\x4e\xe5\xe6\x1e\x9b\x7b\x3e\x51\x59\xd3\xab\xb4\x6a\x60\x6d\xf7\xca\xcd\x3d\xd6\xf4\x58\x23\x6b\xf6\xd8\xdc\x63\x73\xd1\xc4\xfe\x9a\xa4\x5d\x7f\xad\x7f\xac\xff\xa2\xfe\x07\x08\xc7\xfa\x2f\xea\x1f\x93\xa5\x03\xba\x0f\xe8\xde\x7f\x51\xff\x45\x54\xe3\x80\xfa\xfb\x40\xff\x58\xff\x63\x3d\x36\xf7\x3f\x36\x60\xf3\x80\xee\x95\x35\xd5\x37\x0e\x8c\x4b\x9c\xbe\xe9\xf4\x4d\x3d\xe6\xf4\xd7\x4e\xdf\xda\x63\x73\xff\x45\x55\x03\xfb\x1f\x93\x90\x2f\xf9\xb7\xc2\xb1\xca\x9a\x1e\x6b\x8a\x26\xca\x2b\x7b\x3e\xd1\x7f\x51\xb7\xad\x83\xf2\x07\x6d\xfc\x59\xf6\xcf\x9e\x38\xd3\x39\x6b\xe7\xf0\x2f\xe4\xf5\xf2\xb3\x72\x73\xff\x58\x12\xb2\xfe\xa0\x8d\x83\xf2\x47\xcc\x3a\xfb\x8b\x51\x93\xfb\x2f\xaa\xac\xe9\xb6\xb5\x68\xe2\xa8\xd5\x17\x3c\x21\x41\x57\xad\x29\x9a\x28\x71\xc1\xeb\xe3\x66\x8d\x1f\x56\x34\x51\xa2\x72\xf3\xf8\x19\xfe\xb5\x49\x54\xdf\xe8\x43\xbe\x92\x2d\x92\xd4\xe9\xaf\xf5\x3f\x10\x68\xe1\xa2\x60\xeb\x25\x92\x6d\xf4\xdb\x35\xfc\x8b\xba\xef\x27\x1c\x90\x90\xf7\x4c\x7e\x9f\x38\x6c\xe2\xfa\x89\xce\x84\x03\x17\x2f\x97\xa5\x72\xc4\x25\x27\x24\x11\xe4\xbe\x7f\x07\xc7\xe3\xc9\x20\x5a\xd4\x25\x91\x7c\x15\x6b\xc9\x57\xc1\xb2\xe2\x11\xc9\x97\xcf\x89\x69\x14\xef\xce\x8e\xcb\x17\xcd\xdd\x6c\x89\xf8\x1a\x96\x03\x5d\xd1\x80\x7e\x50\x08\xb5\x50\x08\xfd\xa1\x10\x06\x42\x36\x0c\x45\x1b\x86\xa1\x09\xc3\xd1\x84\x11\x68\xc2\xd9\xe8\xc0\x18\x74\xe0\x7c\x74\x60\x2c\x9a\x70\x01\x3a\x30\x0e\x4d\xb8\x10\x1d\x18\x8f\x0e\x48\x1b\x68\x11\x1a\xb0\x18\x0d\x58\x82\x06\x2c\x45\x03\x96\xa1\x01\x77\xa1\x01\x8f\x43\x36\xac\x45\x13\xd6\xa1\x0d\xd2\x72\x7a\x12\x6d\xa8\x47\x1b\x36\xa0\x0d\x1b\xd1\x86\xa7\xd0\x84\x4d\x68\xc2\xd3\x68\xc2\x33\x68\xc2\xb3\x68\xc2\x56\x34\x61\x1b\x9a\xb0\x1d\x4d\x78\x0e\x4d\xd8\x81\x26\x18\x68\xc2\x6f\xd1\x81\x9d\xe8\xc0\x0b\xe8\xc0\x8b\xe8\xc0\x5e\x34\xe0\x25\xb4\xc1\x44\x03\x5e\x46\x1b\x5e\x41\x03\x5e\x45\x1b\x7e\x87\x26\xfc\x1e\x4d\x78\x13\x4d\x78\x0b\x4d\x78\x1b\x4d\xd8\x87\x26\xbc\x8b\x26\xbc\x8f\x26\xfc\x09\x4d\xd8\x8f\x26\x7c\x88\x26\xfc\x15\x1d\xf8\x18\x1d\xf8\x04\x1d\x38\x88\x0e\x7c\x8f\x0e\xd3\xd1\x61\x31\x74\x58\x4b\x74\x58\x6b\x34\x59\x1e\x9a\xac\x00\x4d\xd6\x06\x4d\xd6\x0e\x1d\xd6\x01\x1d\xd6\x19\x1d\x56\x82\x0e\xeb\x0a\x85\xac\x02\x0a\x59\x15\x3a\xac\x07\x3a\xac\x17\x3a\xec\x64\x74\x58\x1f\x74\xd8\x29\xe8\xb0\x53\xa1\x90\x9d\x06\xd9\xac\x3f\x64\xb3\x69\x68\xb2\x39\xe8\xb0\x9d\x68\xb0\x17\xd0\x66\xbb\xd0\x66\x7b\xd0\x64\xfb\xd1\x61\x1f\x40\x21\x1f\x80\x06\x1f\x8a\x06\x1f\x8e\x06\x1f\x8d\x06\x9f\x84\x36\xbf\x0c\x5d\x3e\x99\xec\x34\x9b\x4f\x47\x87\x5f\x89\x2e\x9f\x81\x2e\xbf\x0a\x5d\x3e\x0b\x5d\x7e\x2d\xd9\x6e\x36\xbf\x01\x1d\x3e\x17\x6d\x3e\x0f\x6d\x7e\x13\xda\x7c\x21\xda\xdc\x40\x53\x59\x66\x26\x7f\x03\x4d\xfe\x31\xba\xfc\x13\x34\xf9\x21\x34\xf9\x61\xf4\xf8\x67\xe8\xf1\xcf\xd1\xe3\x2e\x1a\xfc\x6f\xe8\xf1\x2f\xd0\xe3\x5f\xa2\xc9\xbf\x42\x8f\xff\x1d\x3d\xfe\x35\x9a\xfc\x1f\xe8\xf1\x6f\xd1\xe4\xdf\xa1\xc7\xff\x89\x1e\xff\x1e\x3d\xfe\x23\x7a\xfc\x28\x7a\x1c\xd1\x13\x0c\x4d\xa1\xa1\x29\x22\x68\x0a\x1d\x1d\x91\x8d\x86\x68\x81\x9e\x68\x89\x9e\x68\x85\x9e\xc8\x45\x4f\xb4\x45\x4f\x59\x56\x86\x28\x42\x4f\x74\x41\x8f\xf4\xd3\xae\x68\x8a\x4a\x34\x45\x35\x9a\xa2\x27\x9a\xa2\x06\x4d\x31\x10\x3d\x31\x18\x3d\x31\x04\x3d\x31\x0c\x3d\x71\x0e\x7a\x62\x34\x7a\x62\x1c\x7a\x62\x3c\x7a\xa2\x0e\x3d\x31\x11\x4d\x71\x09\x9a\x62\x12\x7a\x62\x16\x7a\x62\x1e\x7a\xe2\x46\x34\xc5\x7c\x34\xc4\xcd\xe8\x89\x5b\xd1\x13\xb7\xa3\x47\x56\xce\x22\x74\xc9\xd2\x59\x82\x2e\x59\x3b\xcb\xd0\x15\xcb\xd1\x14\x0f\xa0\x27\x1e\x42\x4f\xac\x42\x53\xac\x46\x53\xac\x41\x53\x6c\x44\x4f\x6c\x42\x4f\x59\x2d\xa6\xb2\x5a\x4c\xf1\x3c\x9a\xc2\x40\x43\xec\x44\x4f\xbc\x88\xa6\xd8\x8b\xa6\x78\x09\x4d\x61\xa2\x11\xa9\x47\x23\xb2\x01\xed\xc8\x41\x74\xf4\x0a\x28\xd4\xbb\x43\xa1\x5e\x09\x85\xfa\x99\x68\xe8\x43\xd1\xd6\xcf\x42\x43\x1f\x86\xb6\x3e\x1c\x0d\x7d\x04\xda\xfa\x48\x34\xf4\xb3\xd1\xd6\x47\xa1\xa1\x9f\x83\xb6\x7e\x2e\x1a\xfa\x68\xb4\xf5\xf3\xd0\xd0\xc7\xa0\xad\x9f\x8f\x86\x3e\x16\x6d\xfd\x02\x34\xf4\x71\x68\xeb\x17\xa2\xa1\x8f\x47\x5b\xbf\x08\x0d\xbd\x0e\x6d\x7d\x02\x1a\xfa\x44\xb4\xf5\x4b\xd0\xd4\x27\xa1\xa9\x4f\x46\x53\x9f\x8a\xa6\x7e\x39\x9a\xfa\x74\x34\xf5\x19\x68\xea\x33\xd1\xd4\x67\xa3\xa9\xcf\x41\x53\x9f\x8b\xa6\x7e\x13\x9a\xfa\x2d\x68\xea\xb7\xa1\xa9\x2f\x44\x53\xbf\x03\x4d\x7d\x11\x9a\xfa\x12\x34\xf5\x65\x68\xea\xcb\xd1\xd1\x57\xa0\xa3\xaf\x44\x47\xbf\x17\x1d\xfd\x3e\x74\xf4\xfb\xd1\xd1\x1f\x40\x47\x7f\x10\xb2\xf5\x87\x21\x5b\x7f\x04\xb2\xf5\x47\x21\x9b\xfc\x2b\x13\x61\x29\x54\xa0\x05\x95\x68\x41\x0d\x5a\xd0\x17\x2d\xe8\x87\x06\x9c\x86\x2e\xd4\xa2\x09\xfd\xd1\x84\x81\x68\xc2\xdd\x68\xc1\x03\x68\xc1\x83\x68\xc1\x43\x68\xc1\xc3\x68\xc1\x2a\xb4\x60\x35\x5a\xf0\x28\xba\xb0\x06\x5d\xf8\x35\xba\xf0\x18\xba\xf0\x38\x9a\xf0\x1a\x5a\xf0\x3a\x5a\xf0\x06\x5a\x60\xa1\x05\x7f\x41\x0b\x3e\x42\x0b\x1c\xb4\xe0\x00\x5a\xac\x15\x5a\x2c\x17\x2d\x96\x8f\x16\x2b\x44\x8b\x75\x45\x83\x55\xa0\xc1\x2a\xd1\x65\xd5\xe8\xb2\x9e\xe8\xb2\xde\xe8\xb2\x1a\x74\x59\x5f\x74\xd9\xa9\x68\xb2\xd3\xd0\x64\xfd\xd1\x64\x53\xd1\x62\xd7\xa3\xcb\x76\xa3\xc5\x3e\x40\x83\x8f\x42\x9b\x8f\x45\x9b\x8f\x47\x83\x5f\x84\x26\xaf\x43\x8b\x4f\x44\x93\x5f\x8a\x26\x9f\x89\x2e\x5f\x8c\x26\x6f\x44\x83\x6f\x43\x8b\xef\x44\x83\xbf\x85\x16\x7f\x07\x2d\xbe\x0f\x0d\xf2\x6a\xd8\x98\xe0\xfb\xd1\xe0\x47\xd0\x24\x6d\x32\x0f\x2d\x51\x82\x09\x51\x86\x96\x28\x47\x53\x74\x43\x53\x9c\x44\xba\xb9\xd4\xcb\xa5\x4e\x6e\x89\x93\xd1\x12\xe7\xa3\x41\x5a\xe6\x04\xd2\xb3\x2d\x71\x29\x1a\xe2\x32\x34\xc5\x14\x34\xc5\x15\x68\x90\xd6\x79\x25\x26\xc4\x0c\x34\xc5\x55\xa4\x7d\x9a\xe2\x1a\x34\xc5\x75\x68\x8a\xdb\x30\x21\x16\xa0\x29\x1e\x26\x9d\x59\xea\xcb\xd2\x4e\x4d\x88\x7a\x34\xc5\x36\x34\x95\x9d\x6a\x92\x9d\xfa\x02\xd9\xaa\xd2\xaa\xb6\xf4\x0a\x34\xf5\xee\x68\xea\x95\x68\xea\xd7\xa1\xa5\x5f\x8f\x96\x7e\x03\x5a\xfa\x3c\xb4\xf4\xf9\x68\xe9\x37\xa3\xa5\xdf\x8a\x96\xbe\x00\x2d\xfd\x76\xb4\xf4\x3b\xd1\xd2\x17\xa3\xa5\x2f\x45\x4b\xbf\x0b\x5d\xfd\x6e\x74\xf5\x9f\xa3\xab\xdf\x83\xae\xfe\x0b\x74\xf5\x5f\xa2\xab\xff\x0a\x5d\xfd\x41\x34\xf5\x87\xd1\xd4\x1f\x41\x53\x7f\x54\xda\x58\xd0\x0f\x6d\xd6\x15\x6d\x56\x81\x36\xfb\x80\xa8\x6b\xf3\x46\xb4\xf9\x4e\xb4\xf9\x3e\xb4\xf9\x7e\x65\xa5\x9e\x8f\xb6\xb2\xc8\x6d\x71\x05\xda\x64\x85\xee\x22\x1d\xda\x85\x81\x10\x41\x03\xb2\xd1\x80\x0a\x74\xa1\x12\x5d\xe8\x01\x8b\xa0\x06\x5d\xe8\x8b\x2e\xf1\x59\x2d\xda\xd0\x1f\x6d\xc5\x63\x2e\x3c\x80\x2e\x3c\x88\x2e\x3c\x84\x2e\x3c\x8c\x2e\xac\x42\x17\x56\xa7\x78\xca\x85\xd7\xd1\x85\x37\xd0\x05\x0b\x5d\xf8\x0b\xba\xf0\x11\xba\xe0\xa0\x0b\x07\xd0\x65\xad\xd0\x65\xb9\xe8\xb2\x7c\x74\x59\x21\xba\x29\x9e\x3a\x15\xed\x00\xef\x48\xbe\x71\x25\xdf\xe8\x15\x68\xeb\xdd\xd1\xd6\x2b\xd1\xd6\xaf\x43\x57\xbf\x1e\x5d\xfd\x06\x74\xf5\x79\xe8\xea\xf3\xd1\xd5\x6f\x46\x57\xbf\x15\x5d\x7d\x01\xba\xfa\xed\xe8\xea\x77\xa2\xab\x2f\x46\x57\x5f\xda\x9c\x5e\xd1\xc7\xd1\x88\xae\x43\x03\xfa\x26\x7d\x8e\xe4\x5f\xed\x87\x0e\xd4\xa2\x07\xfd\xd1\x83\x01\x92\x1e\xe8\xc1\xe9\xe8\x9d\xd0\xef\xfa\x38\x7a\x19\xbe\xd7\xae\xe8\xb0\x0a\x29\x79\xd0\x63\xa7\xa1\xc7\xfa\xa3\xc7\x06\xa0\xc7\x4e\x47\x8f\x9d\x81\x1e\xdb\x49\x3d\x71\xf8\x76\xf4\xc8\x47\x5b\x81\x9e\xde\x1d\x3d\xbd\x12\xbd\xff\xd4\x5f\xab\x3f\x88\x9e\xfe\x30\x7a\xfa\x23\xe8\xe9\x8f\xa2\x97\xf2\x8f\x96\xa7\xc6\x2e\x39\x6e\xff\x6a\x9c\xfe\xd3\x31\x52\xe3\xf1\x9f\xd2\x9f\xd6\xae\x81\x30\x97\xfc\x01\x41\xe4\x85\x50\x0a\x85\x19\x90\xa3\x12\xc4\xa2\x10\x16\x87\xb0\x24\x84\xa5\x21\x2c\x0b\xe1\xae\x10\xf6\x86\x60\x86\xf0\x4a\x26\x68\x44\x03\x90\xa3\x1a\x04\x8d\x6a\x10\x67\x85\x30\x3c\x84\x91\x21\x8c\x0a\xe1\xdc\x10\xce\x0b\xe1\xfc\x10\x2e\x08\xe1\xc2\x10\x2e\x0a\x61\x42\x26\xc8\x8e\x0f\x62\x7d\x26\x60\x74\xd2\x07\xd5\x8c\xeb\xfa\xa1\x0b\xa7\xa1\x07\xb5\xe8\x42\x7f\x9a\x4b\xce\xbf\xe4\xc4\x47\xd1\x83\x35\xe8\xc1\xaf\xd1\x83\xc7\xd0\x83\xc7\xd1\xf9\x3f\x58\x41\x5c\x56\x81\x2e\xab\x44\x8f\x55\xa3\xc7\x7a\xa2\xc7\x7a\xa3\xc7\x6a\xd0\x63\x7d\xd1\x63\xa7\xa2\xcb\x4e\x43\x87\xf5\x47\x87\x38\xf9\x7a\xf4\xd4\xea\x22\xe7\xa2\xab\x77\x47\x57\xaf\xfc\xcf\xb9\x5b\xbf\x0b\x3d\xfd\x6e\xf4\xf4\x9f\xa3\xa7\xdf\x83\x9e\xfe\x0b\xf4\xf4\x5f\xa2\xa7\xff\x0a\x3d\xfd\x41\x74\xf4\x87\xd1\xd1\x1f\x41\x47\x7f\x94\x3c\x00\xbe\x6f\xac\x24\x19\xb9\x80\xae\x68\xd1\x6a\xe3\xaf\x34\x16\x2c\x46\x0b\x96\xa0\x05\x4b\xd1\x82\x65\x68\xc1\x5d\x68\xc1\x5e\xb4\xc0\x44\x0b\x5e\x41\x2b\xb4\xa2\x58\x91\x7a\xb4\xf4\x33\xd1\xd2\xcf\x42\x4b\x1f\x8e\x96\x3e\x12\x2d\x7d\x14\x5a\xfa\xb9\x68\xe9\xe7\xa1\xa5\x9f\x8f\x96\x7e\x01\x5a\xfa\x85\x68\xe9\x17\xa1\xa5\x4f\x20\xff\x8c\x1f\x11\xf9\x7d\x30\xa6\xa0\x66\x9c\xd1\x7c\x2c\xa1\x10\x86\x62\x02\x86\xa1\x01\xc3\xd1\x80\x11\x68\xc0\xd9\x68\xc0\x18\xb4\xe0\x7c\xb4\x60\x2c\x1a\x70\x01\x5a\x30\x0e\x0d\xb8\x10\x2d\x18\x8f\x26\xd4\xa1\x05\x13\xd0\x85\x89\xe8\xc2\x25\xe8\xc2\xa5\x68\x9f\xd0\x52\xf9\x57\x7c\xb1\x16\x0d\x90\xf4\x5a\x8f\x09\x78\x12\x13\x50\x8f\x09\xd8\x80\x09\xd8\x88\x09\x78\x0a\x0d\xd8\x84\x06\x3c\x8d\x06\x3c\x83\x06\x3c\x8b\x06\x6c\x45\x03\xb6\xa1\x01\xdb\xd1\x80\xe7\xd0\x80\x1d\x68\x80\x81\x06\xfc\x16\x2d\xd8\x89\x16\xbc\x80\x16\xbc\x88\x16\xec\xa2\x19\x2e\xad\x98\x84\xb2\x62\x12\xca\x8a\x49\x10\xdf\xfd\x0e\x0d\xe2\xbd\xdf\xa3\x41\xfc\xf7\x26\x1a\xc4\x83\x6f\xa1\x01\x6f\xa3\x01\xfb\xd0\x80\x77\xd1\x80\xf7\xd1\x80\x3f\xa1\x01\xfb\xd1\x80\x0f\xd1\x20\x1e\xfd\x2b\x1a\xc4\xa7\x1f\xa3\x41\xbc\xfa\x09\x1a\x92\x5f\xe1\x20\x1a\xf0\x3d\x5a\x4c\x47\x8b\xc5\xd0\x62\x2d\x49\xb3\x72\x59\x6b\x34\x88\x8f\xf3\xd0\x20\x5e\x2e\x40\x83\xf8\xb9\x0d\x1a\xac\x1d\x5a\xac\x03\x5a\xac\x33\x9a\xac\x04\xcd\x80\xd5\x63\xb1\x1e\x68\xb1\x5e\x68\xb1\x93\xd1\x62\x7d\xd0\x62\xa7\xa0\xc5\xfa\xa1\xcb\x06\xa2\xcd\x06\xa1\xcd\x06\xa3\x4d\x7c\x3e\x0d\x0d\x36\x07\x2d\x65\xfd\x24\xd8\x2e\x4c\x10\xdf\xef\x41\x83\xed\x47\x53\x5a\x40\x4a\x9b\x4e\x44\x0e\xa2\xa5\x77\x43\x57\x3f\x89\x56\x2c\xa9\x49\x27\x94\x26\x9d\x50\x9a\x74\x42\x69\xd2\x09\xa5\x49\x27\x94\x26\x9d\x50\x9a\x74\x42\x69\xd2\x09\xa5\x49\x27\x94\x26\x9d\x50\x9a\x74\x42\x69\xd2\x09\xfd\x12\x34\xf4\x49\x68\xe8\x93\xd1\xd0\xa7\xa2\xa1\x5f\x8e\x86\x3e\x1d\x0d\x7d\x06\x1a\xfa\x4c\x34\x68\x1e\xce\x46\x83\xe6\xe2\x1c\x34\x68\x3e\xce\x45\x23\x35\x27\x6f\x42\x83\xe6\xe5\x2d\x68\xd0\xdc\xbc\x0d\x0d\x9a\x9f\x0b\xd1\xa0\x39\x7a\x07\x1a\x34\x4f\x17\xa1\x41\x73\x75\x09\x1a\x34\x5f\x97\xa1\xa1\x2f\x47\x4b\x5f\x81\x96\xbe\x12\x2d\xfd\x5e\xb4\xf4\xfb\xd0\xd2\xef\x47\x4b\x7f\x00\x2d\x7d\x15\x45\xe0\x9a\xc7\x40\x3a\x41\x6b\x8a\xdf\x49\x59\x24\xe7\xaa\x07\x8b\xd1\x83\x25\xe8\xc1\x52\xf4\x60\x19\x7a\x70\x17\x69\x04\x1e\x98\xe8\xc1\x2b\x34\x3f\xa5\xa4\x97\xd2\xdd\xd3\xcf\x42\x4f\x1f\x8e\x9e\x3e\x12\x3d\x7d\x14\x7a\xfa\xb9\xe8\xe9\xe7\xa1\xa7\x9f\x8f\x9e\x7e\x01\x7a\xfa\x85\xe8\xe9\x17\xa1\xa7\x4f\x20\x69\xee\x46\xd7\xa3\x0b\xcf\x25\x23\x96\x6a\x6e\xda\x50\x81\x1e\x54\xa2\x07\x35\xe8\x41\x5f\xf4\x60\x28\xba\x30\x0c\x5d\x18\x8e\x2e\x8c\x40\x17\xce\x46\x0f\xc6\xa0\x07\xe7\xa3\x07\x63\xd1\x85\x0b\xd0\x83\x71\xe8\xc2\x85\xe8\xc1\x78\xf4\xa0\x8e\x5a\x6e\xc3\x62\xb4\x61\x09\xda\xb0\x14\x6d\x58\x86\x36\xdc\x85\x36\xdc\x8d\x1e\x3c\x80\x1e\x3c\x88\x1e\x3c\x84\x1e\x3c\x8c\x1e\xac\x42\x0f\x56\xa3\x07\x6b\xd1\x85\x75\xe8\x82\x6c\xd5\x93\xe8\x42\x3d\xba\xb0\x01\x5d\xd8\x88\x2e\x3c\x85\x2e\x6c\x42\x17\x9e\x46\x17\x9e\x41\x17\x9e\x45\x17\xb6\xa2\x0b\xdb\xd0\x85\xed\xb2\x17\xe8\xc2\x0e\x74\xc1\x40\x17\x7e\x8b\x1e\xec\x44\x0f\x5e\x40\x0f\x5e\x24\x6a\xd9\xf0\x12\x49\x57\x1b\x5e\x26\xa9\x6a\xc3\xab\xa4\x99\x78\xf0\x3b\x5a\xff\x3d\xf8\x3d\xc9\x00\x0f\xde\x24\x39\xe0\xc1\x5b\xe8\xc2\xdb\xe8\xc2\x3e\x74\xe1\x5d\x74\xe1\x7d\x74\xe1\x4f\xe8\xc2\x7e\x74\xe1\x43\x92\x13\x1e\xfc\x15\x3d\xf8\x08\x3d\xf8\x18\x3d\x70\xd0\x83\x4f\xd0\x83\x03\xe8\xc1\x41\xf4\xe0\x7b\xf4\x98\x8e\x1e\x8b\xa1\xc7\x5a\xa2\xc7\x5a\xa1\xc7\x5a\x93\x2c\xf1\x58\x1e\xc9\x13\x8f\x15\x90\x4c\xf1\x58\x1b\x74\x59\x3b\xf4\x58\x07\xf4\x58\x67\xf4\x58\x09\x7a\xac\x0a\x3d\xd6\x03\x3d\xd6\x0b\x3d\x76\x32\x7a\xac\x0f\x7a\xec\x14\xf4\xd8\x54\xf4\xd8\x34\x74\xd9\x1c\x1a\x79\x9b\xbd\x80\x2e\xdb\x45\x1a\x93\xc7\xf6\xa0\xcb\xf6\x13\x37\xd8\x91\x0d\xe8\x46\x0e\x12\x57\xd8\xfa\x50\xd2\x04\x6c\x7d\x18\x69\x00\xb6\x3e\x82\x24\xbf\xad\x9f\x4d\x12\xdf\xd6\xcf\x21\x49\x6f\xeb\xa3\x49\xc2\xdb\xfa\x18\x92\xec\xb6\x3e\x96\x24\xba\xad\x8f\x23\x49\x6e\xeb\xe3\x49\x82\xdb\x7a\x1d\x49\x6e\x5b\x9f\x88\xae\x7e\x09\xba\xfa\x24\x74\xf5\xc9\xe8\xea\x53\xd1\xd5\x2f\x47\x57\x9f\x8e\xae\x3e\x03\x5d\x7d\x26\xc9\x39\x4f\x9f\x4d\xb2\xce\xd3\xe7\x90\xbc\xf3\xf4\xb9\x24\xf3\x3c\x7d\x3e\x7a\xfa\x4d\x24\xf7\x3c\xfd\x16\x92\x7d\x9e\x7e\x1b\xc9\x3f\x4f\x5f\x48\x32\xd0\xd3\xef\x20\x39\xe8\xe9\x8b\x48\x16\x7a\xfa\x12\x92\x87\x9e\xbe\x0c\x5d\x7d\x39\x7a\xfa\x0a\xf4\xf4\x95\xe8\xe9\xf7\xa2\xa7\xdf\x87\x9e\x7e\x3f\x7a\xfa\x03\xc4\xdd\x7e\x34\xfd\xb7\xa1\x0c\x07\xb3\x99\xe4\x19\x8a\x16\x0c\x43\x0b\x86\xa3\x05\x23\xd0\x82\xb3\xd1\x0d\xf8\xc3\x2c\xe5\x0f\xb3\x94\x3f\xcc\x26\x7f\xd8\xa5\xa4\x1b\x9a\xb0\x18\x4d\x58\x82\x26\x2c\x45\x13\x96\xa1\x09\x77\xfd\x84\xcd\xb2\x16\x2d\x58\x87\x16\xc8\x96\x3d\x89\x16\xd4\xa3\x05\x1b\xd0\x82\x8d\x68\xc1\x53\x68\xc1\x26\xb4\xe0\x69\xb4\xe0\x19\xb4\xe0\x59\xb4\x60\x2b\x5a\xb0\x0d\x2d\xd8\x8e\x16\x3c\x87\x16\xec\x40\x0b\x0c\xd9\xab\x66\xbe\x32\x13\x5e\x22\xf9\x6d\xc2\xcb\x24\xc3\x4d\x78\x15\x2d\x25\x65\x2c\x25\x65\x2c\x25\x65\x2c\x25\x65\x2c\x78\x1b\x2d\xd8\x87\x16\xbc\x8b\x16\xbc\x8f\x16\xfc\x09\x2d\xd8\x8f\x16\x7c\x48\xf6\xb9\x94\x32\xae\x92\x32\xae\x92\x32\xae\x92\x32\x6e\x33\x5f\x9a\x2f\x65\x2c\x25\x65\x2c\x25\x65\x2c\x25\x65\xac\x80\x6f\xcd\x66\x25\x68\x9f\xd0\xa7\x36\x10\x5d\x36\x08\x5d\x36\x58\xd9\x02\xd3\xd0\x52\x7e\x35\x93\xbd\x80\x16\xdb\x85\x96\x92\x2c\x16\xdb\x8f\x76\xa4\x1e\xcd\xc8\x06\xb4\xc8\x47\x73\x26\x9a\xfa\x50\xd2\x53\x4c\x7d\x18\xe9\x2a\xa6\x3e\x82\xf4\x15\x53\x3f\x9b\x74\x16\x53\x3f\x87\xf4\x16\x53\x1f\x4d\xba\x8b\xa9\x8f\x21\xfd\xc5\xd4\xc7\x92\x0e\x63\xea\xe3\x48\x8f\x31\xf5\xf1\xa4\xcb\x98\x7a\x1d\xe9\x33\xa6\x3e\x11\x2d\xfd\x12\xb4\xf4\x49\x68\xe9\x93\xd1\xd2\xa7\xa2\xa5\x5f\x8e\x96\x3e\x1d\x2d\x7d\x06\x5a\xfa\x4c\xb4\x94\x34\xb1\x94\x34\xb1\x94\x34\xb1\x02\xd2\xc4\x52\xd2\xc4\x52\xd2\xc4\x52\xd2\xc4\x52\xd2\xc4\x52\xd2\xc4\x52\xd2\xc4\x52\xd2\xc4\xfa\x57\x7e\x9c\x94\xf4\x28\x6f\xb6\x76\xff\xab\xf5\x56\xae\x7f\x72\xed\x93\xeb\x9e\x5c\xf3\xfe\xa2\xd6\x33\xc7\x5f\xc7\x68\xcd\x92\xeb\x95\x5c\xab\x0a\xd5\xda\xb3\x1b\x3d\x9a\xd3\x72\x3e\xcb\xb9\x9c\x9c\xc7\x72\x0e\xcb\xf9\x2b\xe7\xae\x9c\xb7\x72\xce\xca\xf9\x2a\xa5\x96\x80\x08\x7a\x90\x8d\x5e\xf4\x71\xf4\xa2\xeb\xd0\x83\xdc\x64\x49\x48\x7f\xf3\xa4\xce\xa4\xf4\x0b\x8f\x0d\x42\x8f\x0d\x46\x2f\xa5\x2b\xac\xa2\xc8\xbc\x7f\x07\x01\x11\x28\x84\x6c\x28\x8c\x3e\x0e\x85\xd1\x75\x50\x48\x25\x03\x21\x9b\xb2\x85\x06\x46\xd7\xc1\x40\x38\x25\x43\x6a\x49\x49\x35\x8e\xe6\xe0\x7f\x26\x4d\x7e\x47\x73\xc7\x25\xc9\xf0\x13\x52\x81\x56\xf8\x3c\xe2\x7b\x97\x56\xf5\x69\xc4\xa7\x3f\xbd\x4a\xce\x26\x7e\x71\x69\x65\xbc\x89\xf8\xc3\xa5\x95\x70\x21\xf1\x84\x4b\xab\xdf\x12\xe2\x03\x17\x2e\x4a\x65\x3f\x1d\x4f\x2e\x07\x7b\xf9\x3f\x21\x4b\xa5\xdc\x94\x32\xf3\xd5\xff\x8c\x12\x24\x1b\x3f\x56\x32\xf1\xa0\x92\x7d\x61\xca\x24\x65\xd7\x1e\x74\xa5\xbc\x22\x39\x25\x65\x94\x94\x4f\x52\x36\x49\xb9\x24\x65\x92\x94\x47\x52\x16\x49\x39\x24\x65\x90\x94\x3f\xff\x8e\xec\xf9\x0f\xa8\x1a\xc8\x10\x4b\x52\x37\xe9\xb5\x29\x25\x1e\xeb\x4e\xde\x8f\x75\xd0\x9d\x3c\x20\x92\xa3\x5d\xc8\x26\x7e\x74\xa3\x92\xce\xa7\xd1\x75\x41\x64\x87\x90\x03\xc3\x32\x50\x0a\x63\x32\x30\x58\xe5\xb1\x0d\x0e\xe4\xb3\x05\x31\x2a\x84\xd1\x21\x9c\x17\xc2\x64\x18\x96\x81\x26\xe8\x92\x81\xc3\x30\x30\x08\xea\x63\x10\xeb\x32\xf1\x7f\xd4\xc3\x4c\xfc\xbf\xdf\xc3\x61\x41\xfc\x64\x0f\xf3\x60\x24\x74\x87\x8b\xa0\x3b\x4c\x80\x1a\x98\x08\x35\x70\x09\xd4\xc0\x2e\xa8\x61\xe5\xd0\x9d\x75\x83\xee\xac\x1f\xd4\xb0\x0f\xa1\xbb\xde\x0d\x6a\xf4\x93\xa0\x46\x5f\x05\x35\xb1\xa5\xd0\x3d\xb6\x0c\xba\xc7\xee\x82\xee\xb1\xe5\xea\x2e\x35\x70\x11\xd4\x1c\xe7\x2e\x35\xac\x1b\xd4\xa8\xbb\xd4\x84\xee\x52\x13\x5b\x06\x35\xb1\xbb\xa0\x26\xb6\x1c\x6a\x20\x27\xe9\x27\xe5\xa3\xd0\xe5\x63\xd1\x0d\xf8\xb2\x5d\x3e\x11\x6d\xf2\x65\x2f\x0e\xf8\x19\xf3\x8e\x9b\xdb\xe8\xe7\x29\x26\x33\x0f\x1d\x7e\x11\x7a\x94\xb3\x38\x91\xb2\x0f\x3d\x95\x7d\x18\xf4\xed\x25\xf3\x69\x06\xa0\xc9\x87\xa2\xc9\x87\xa3\x49\x6d\x18\x8d\x26\xb5\xa3\x0e\x1d\x7e\x31\x7a\x7c\x12\x5a\xfc\x32\xb4\xf9\x64\x74\xf8\x14\x74\xf8\x54\x74\xf8\x34\xb4\x54\x1c\xcb\xe6\x57\xa1\xc3\xaf\x46\x87\xcf\x42\x87\x5f\x8b\x0e\xbf\x1e\x2d\x7e\x03\x5a\x7c\x2e\x5a\x7c\x1e\x5a\x7c\x3e\x3a\xfc\x26\xb4\xf8\x2d\xe8\xf0\x5b\xd1\xe1\x0b\xd0\xe1\x0b\xd1\xe2\xb7\xa3\xc3\xef\x48\xcb\xb4\xe8\xe7\x72\xb5\xe7\xe3\xd1\xa5\xb6\x5f\xea\xb7\x17\xba\x52\x6f\x83\xc8\xcb\x04\x51\x21\x88\xa1\x21\x0c\x0f\x61\x74\x08\x13\x32\x41\x14\x0a\x62\x7d\x26\xa0\x47\x46\xee\xe4\x00\x4c\xf0\xa1\x98\xe0\xc3\x31\xc1\x47\x51\xf6\x67\x82\x8f\x45\x87\x22\x11\x17\x53\x76\xa6\xc1\x2f\x43\x8b\x4f\x46\x8b\x4f\x41\x9b\x4f\x45\x8b\x4f\x43\x83\x5f\x41\x19\x9b\x92\x82\x16\xbf\x0a\x2d\x7e\x35\xda\x7c\x16\x5a\xfc\x5a\xb4\xf8\x75\x14\x0d\x34\x14\x15\x0d\x3e\x0f\x0d\x3e\x1f\x2d\x7e\x13\x1a\xfc\x66\x74\xf9\x2d\x68\xf1\x5b\xd1\xe2\x0b\xd0\xe2\x0b\xd1\xe0\xb7\xa3\xc5\xef\x40\x8b\x2f\x3a\xbe\xad\x19\xfd\x1c\x1d\xc8\xa1\x5c\xd7\x20\xc6\x86\x50\x47\xad\x4e\x01\x22\x29\x8e\x94\x25\x73\xd0\xe3\x37\xa2\x07\xd5\xe4\x6b\x0a\x22\x2f\x13\x94\x3d\x1b\xc4\xd0\x10\x86\x87\x20\x39\x37\x88\xd1\x68\x65\x20\x34\x3e\xfc\x9a\x4c\x90\xff\x29\x88\xf5\x99\x80\xc1\x64\xf7\x06\x91\x97\x89\xff\x98\x83\x46\xa2\x93\x81\x30\x47\xc9\x39\x18\xc4\x78\x15\x43\x49\xe2\x22\x9a\x9f\x69\x4c\xa0\xb9\x9a\xc6\xa5\xe8\x64\xe0\x1a\x35\x7f\xaf\x49\xcd\x63\x27\x08\xb2\x81\x82\x58\x9f\x09\xc8\x0e\xcc\x75\x9b\x0f\x45\x9b\x0f\x47\x9b\x78\x60\x34\xc5\xcf\xbc\x94\x5e\xc9\xf8\x35\x50\x08\x3a\x44\xd0\x86\x6c\xb4\x93\xa3\x1e\x7d\x5c\xca\x44\xb4\x21\x92\x5a\x7b\xae\x09\xac\x25\xa7\x41\x2e\x5a\x41\x50\x4e\x72\x10\xd3\x42\x98\x1e\xc2\xf5\x21\xcc\x09\x61\x6e\x08\xf3\x42\xb8\x31\x84\x9b\x42\x58\x98\x09\xca\xa6\x0e\x62\x75\x08\x8f\x66\x02\x44\xd2\x5b\x93\xf2\xa6\x44\x53\xfd\x3a\x4e\xce\x35\xb4\x86\x08\x9a\x90\x8d\x26\x9f\x84\x1e\x9f\x86\x1e\xcd\x77\x7f\x5e\x7b\xaa\x47\x1e\x9f\x47\xd4\x95\x57\x79\x7c\x21\x51\xd9\x8c\xae\x43\x93\xe8\x4f\x5a\x73\xf2\xaa\x80\x36\xdc\x1a\x3d\xc8\x23\xda\x7b\xd1\xf5\xe8\x11\x77\x3b\x19\xc8\x45\x37\x03\x79\xe8\x04\xf1\xdf\x1e\x9b\x9f\x1a\x8b\x9f\xa6\x7d\x26\x56\x87\xf0\x68\x08\x4f\x10\x87\xa7\xb1\x3e\x13\x44\x13\xea\x59\x2a\xbb\xbd\x6f\x8a\x7f\x1b\xd1\xe4\x3b\xd1\xe4\xbb\xd0\xe5\xfb\xd0\xe2\x7f\xa4\xfc\xbd\x35\x7c\x3f\x9a\x2a\x8b\xd0\xa5\x48\x66\x6b\x74\x45\x01\x65\xb7\xae\x11\xe5\x68\x8b\x6e\x68\x8b\xd3\xd1\x16\x67\xa2\x2d\xce\x43\x5b\x9c\x8f\xa6\x8a\x74\x5a\xe2\x32\x95\x5d\x38\x05\x2d\xca\x30\xbc\x02\x4d\x95\x83\xbc\x46\xe5\xf4\xad\xa1\x9c\xbe\xdb\x70\x0d\xe5\xf0\x3d\x4e\x19\xd6\xae\xf8\x8d\xca\x38\x5c\xa7\xb2\x0e\x9f\xc4\x35\x94\xdb\xf7\x34\xda\x62\x1b\xae\x51\xf9\x7d\x6b\x28\xbf\x6f\x17\x9a\x2a\x3f\xd9\x9f\x77\xff\x9b\xaf\xff\xbf\xf9\xfa\xff\xdf\xe5\xeb\x77\x22\x8e\x4b\xe7\x58\xd3\xbc\xa1\x11\x3c\x51\x6e\x7a\x32\x2f\x5d\xce\x07\x3f\xbf\xd5\x15\xd7\x51\xe6\xad\x1b\xca\x45\x97\xad\x75\x45\x23\xe5\xb7\xa6\x72\xd2\x41\x4b\xfe\xa5\xf2\xe4\x83\xcf\xb6\x03\xcf\x2f\xf9\x37\xda\x70\xa5\x6a\xc7\x55\xa9\xb6\x58\x34\x62\xb7\x1d\xa7\x3d\x4f\x9e\xb8\x4d\x62\x0f\x7a\x30\x3a\x90\x85\xee\x1d\x67\x0e\x7a\xfc\x1d\xf4\x28\x0b\xfd\x23\xf4\xf8\x27\x34\xff\x5c\xee\xa2\xcd\xbf\x44\x97\x7f\x8d\x2e\xff\x56\xb5\x9e\xa1\x2b\x34\x74\x05\x87\x1a\x11\x41\x57\xe8\xe8\x89\x6c\xb4\x45\x0e\xd4\x88\xbc\x54\xa6\x95\x2d\xca\x28\xc3\x4a\xf6\xd0\x13\x95\xd4\x4b\x4f\x54\x53\x4f\x3d\xd1\x93\x7a\xeb\x89\x93\xd1\x13\x35\xe8\x8a\x41\x50\x23\xc6\x40\x8d\x98\x40\xd9\x55\xb2\xf7\x9e\xb8\x24\x34\x0a\xd7\xa2\x43\x23\x31\x9b\xb2\xbf\x25\x9f\xfa\x99\xc6\x99\xbc\x29\xa9\xe2\x89\x55\x44\x19\x4f\xac\x26\xea\x78\x62\x4d\x8a\x3a\x92\xbf\x5c\xc5\x5f\xae\xe2\x2b\x5b\xbc\x40\x99\x55\xae\xd8\x8b\xae\xe2\xa7\x34\x0f\xf5\x48\xd9\x39\x8d\x94\x8b\x93\xcc\xc1\x71\xd5\x9e\x0f\x2b\xb5\x16\x17\xa4\xf6\x7d\x24\xd7\x61\x57\x9c\x89\xae\x38\x8f\x32\x4e\x2c\xb5\x0e\x07\xf3\x6d\xac\xc0\x1e\x10\x57\xed\x01\x09\x8e\xb3\x49\x3d\xbc\x1b\x5d\xf1\x73\x1a\x63\x53\xad\xbb\xae\xd8\x46\xb3\xc3\x15\xcf\xa1\x41\xe3\xbc\x0b\x2d\xb5\xee\x26\x6d\x2d\x65\xff\xf3\x3d\xe8\x49\xce\x13\xed\x28\xe3\xdb\xe7\xaa\xab\x02\x9c\x7d\x1b\xd1\xd0\x13\x8b\xd1\x13\x4b\xd1\x93\x9c\x94\xf2\x19\x64\x27\xb5\x26\x51\x4e\x39\xe2\x9e\xb8\x8c\xf2\xc1\x3d\xca\xeb\x7e\x2e\xb0\x23\x4d\xf0\xe7\xe1\x03\x71\x3f\x14\xa6\xf8\x7f\x60\x4a\xe3\x6a\x24\x8e\x73\xf9\x4e\xf4\x48\x9e\xed\x41\x97\xbf\x8c\x2e\x7f\x15\x5d\xfe\x1a\x7a\xfc\x0d\x92\x71\x0e\xc9\xb8\xf7\xd4\x3c\xd9\x8f\x1e\xff\x0b\xe5\x06\x4a\xee\x92\x5c\xe5\x8a\xf6\xe8\x89\x62\xd5\x8b\x64\x7b\x86\xa3\x2b\x46\xa2\x27\xce\x47\x4f\xed\xaf\xf1\xdb\x37\x8d\xe4\x9b\x97\xea\xed\x1c\x74\xc5\x8d\xe8\x8a\xf9\xe8\xa9\x1e\xbb\x62\x31\xe5\xe4\xb9\xe2\x1e\x74\xc5\x2f\xd0\x13\xbf\x46\x8f\x64\xde\x6f\x94\xac\x93\x73\xea\x59\x74\xc5\x7f\xa9\x3c\xf6\xe7\x88\x63\x5c\x61\xa0\x27\x76\xa1\x27\x5e\x42\x57\x98\x01\x6d\x32\x9e\xda\x87\xe7\x67\x3e\x5a\x94\xf9\x28\x7b\xf9\x06\x9a\xd4\x33\x17\x2d\xda\x75\xd1\x0e\x2d\xda\x59\xd1\x51\xf5\x60\x5a\xaa\x85\x26\xed\x6a\xb8\x13\x2d\xb1\x18\x2d\xb1\x14\x2d\x6a\x5d\xb2\x15\x0d\x68\xd3\x4e\x04\x3f\x23\xd0\x52\x59\x80\xa9\x48\xb6\x76\x67\xb3\xdc\x12\x29\x79\x83\x08\xe5\x9a\xd0\x1a\x15\x84\x5c\x19\x82\x90\xab\x44\x18\x2f\x53\xcf\xd2\x78\x23\x84\xb7\xd4\xba\xf7\x56\x60\xfd\x0b\x42\x4a\xfa\x20\xa4\xd4\x0f\x42\x6a\x00\x41\x48\x6d\x20\x08\xa9\x19\x04\x21\xb5\x84\x20\x3e\x0d\xe1\x30\xed\xa7\x49\xe3\xb3\x10\x3e\x0f\x41\x6a\x18\x41\xfc\x8d\xf6\xdf\xa4\xf1\x45\x08\x52\x0b\x09\xe2\x2b\xda\xa3\x93\xc6\xdf\x43\x90\x9a\x4a\x10\xff\xa0\x7d\x3c\x69\x48\x0d\x26\x08\xa9\xcd\x04\x21\x35\x9b\x20\xbe\xa3\xfd\x3f\x69\x1c\x09\xe1\x9f\x21\x7c\x1f\xc2\x0f\x94\x15\x97\x86\xd4\x90\x82\x38\x1a\x82\xd4\x9c\x82\x40\xb4\x82\x20\x8d\x2a\x08\xa9\x5d\x05\xa1\x85\x20\xb5\xae\x20\xa4\x06\x16\x84\x4e\xb9\xbd\x69\x64\x87\xd0\x82\xf6\x31\xa5\xd1\x32\x84\x56\x21\x48\x4d\x2e\x08\xa9\xd5\x05\x91\xa7\x64\x74\x12\xf9\x21\x48\xcd\x2f\x08\x29\xf1\xc2\x68\x4f\x7b\xa7\xd2\x28\xa2\x7d\x54\x69\x74\x0a\xa1\x4b\x08\x52\x8b\x0c\x42\x6a\x94\x41\x94\x29\xfd\xa1\x2c\xb5\x1f\xcb\xc8\x40\x85\xda\x59\x54\x11\xd8\x61\x14\xc4\x49\x21\x48\xcd\x34\x88\x2a\xa5\x97\x24\x21\x35\xd6\x20\x7a\x28\x9d\x25\x09\xa9\xc9\x06\xd1\x4b\xe9\x33\x49\xf4\x0e\xe1\xe4\x10\xa4\xe6\x1b\xc4\x40\xda\x3b\x96\xc6\xe0\x10\x86\x84\x30\x2c\x04\xa9\x35\x07\x71\x76\x08\x52\x9b\x0e\x62\x74\x08\x63\x29\x43\x34\x0d\xa9\x71\x07\x31\x3e\x84\xba\x10\x26\x28\x3d\x2e\x09\xa9\xa1\x07\x71\xb1\xd2\xf1\x92\x90\x9a\x7b\x10\x52\x8b\x0f\x62\x12\xed\x87\x4b\x43\x6a\xf7\x41\x4c\x0d\x41\x6a\xfd\x41\x4c\xa7\x2c\xd7\x34\x66\xd0\xee\xb2\x34\x66\x86\x30\x2b\x84\x6b\x42\x90\xd6\x43\x10\xd7\x29\x9d\x25\x09\x69\x55\x04\x21\x2d\x8c\x20\xa4\xb5\x11\xc4\x8d\x21\xcc\x27\x49\x98\xc6\xcd\xb4\xd7\x2f\x8d\x5b\x43\x58\x10\xc2\xed\x21\x48\x2d\x31\x8c\xc5\xc7\xc1\xd2\xe3\x60\x79\x08\xd2\xfa\x09\x62\x65\x08\xf7\x86\x70\x5f\x08\xd2\x5a\x0a\x42\x5a\x4e\x41\x3c\x14\xc2\xc3\x4a\xd7\x4f\x42\x5a\x57\x41\x3c\xa2\xec\x80\x24\xa4\xd5\x15\xc4\xa3\xca\x46\x48\x42\x5a\x63\x41\x48\xcb\x2c\x08\x69\xa5\x05\xb1\x36\x84\xf5\x21\xd4\xd3\x9e\xc9\x34\x36\x86\xb0\x29\x04\x69\xed\x05\x91\x08\x41\x6a\xe9\x41\x6c\x09\xa1\x31\x84\xad\x21\x6c\xa7\x7d\x9a\x69\xec\x08\xe1\xf9\x10\x0c\xd2\xa6\xd2\xd8\x49\xfb\x3a\xd3\x78\x41\xd9\x51\x49\x48\xeb\x33\x88\xdd\x94\x39\x9e\x86\xb4\x4a\x83\x78\x89\x34\xb5\x34\x4c\xd2\xda\x52\x20\xcb\x35\x88\xd5\x21\x3c\x1a\xc2\x4f\xe5\xa3\x9e\x1a\xd0\xbc\x5d\xa5\x79\xbb\x7c\x17\x3a\x21\xcd\xdb\x0d\x68\xde\x0e\xe9\xa7\xfb\xd1\xe5\x7f\x21\x3d\x35\xac\x75\x87\x35\x6e\x69\xd1\x24\x77\xb4\x3b\x62\x0a\x3a\x4a\xe3\xce\xd4\xb4\x9b\x6b\xd9\xae\xf8\x35\x79\x96\x1c\xf1\x1b\x74\xc4\x3a\x74\xfe\x85\x86\xed\x36\xd3\xb0\x99\x00\x28\x84\x2e\x29\xfb\xf4\x44\xb6\x69\x84\x24\xa2\x4b\x76\x67\x35\x49\x27\x97\xec\xcc\x89\xb4\xd2\xa6\xed\xca\xf4\xbe\x5a\x97\x6c\xc7\x55\x34\x7b\xdc\x94\xbd\x28\x6d\xc5\xad\x34\xe2\x64\x1b\x42\xfb\x94\x7f\xf3\x1b\xf4\x48\xf7\x3a\x82\x1e\xff\x01\x3d\xd1\x9a\xf6\xcd\x7a\x6a\xad\xf5\xc4\x0c\xf4\xc4\x4c\xf4\xc4\x02\xf4\xc4\x13\xe8\x89\xb5\xe8\x89\xf5\xe8\x89\x7a\xf4\x52\x3c\xbf\x1d\x3d\xb1\x03\x3d\xb1\x3b\x90\x77\x90\xf2\xa0\x26\xed\xa8\xd4\xff\xa4\x6c\x31\xee\xa2\x2b\xb2\x69\x64\x24\x95\x25\xb5\x24\x95\xd2\xb6\x58\x49\xca\x87\xfb\x0d\x3a\xaa\x95\x86\xda\x73\xec\x9c\x60\xcf\xb1\x23\xa6\xa2\xa3\x5a\x2f\x25\x82\x21\x66\xd2\xca\x9e\xa4\x8f\x21\xee\xa7\x95\xc1\x11\x6b\xd1\x11\xeb\xd1\x11\xf5\x68\x04\x7a\xb2\x46\xec\xc0\x35\x6a\x0f\xb2\xef\x0b\xee\x14\xf0\x65\x26\xed\x66\x3b\x65\x33\x37\x3f\x23\xc1\x4a\xed\xc8\x48\x72\x54\xd0\x3e\xbe\x8a\xf6\x9f\x98\x64\x03\x6f\xa3\x7d\x26\x56\xc0\xe6\xf5\x7d\x8d\x53\x53\x96\xba\xbf\xd3\xcc\xe7\x91\xe0\x4e\xb3\xf4\x2e\x33\x37\xb0\xcb\xcc\xa5\x5d\x66\xdf\xd0\x4e\x7a\x97\x76\x9a\x1d\x41\x27\xb5\xdb\xec\x07\xd2\x82\xd3\x3b\xce\x00\xba\x64\xf0\x59\x70\xb7\x59\x6b\xda\x41\xef\x29\x2d\xd1\x0b\xed\x36\x4b\xd3\x3d\xc8\x97\xbd\x15\x6f\x9e\x68\xe7\xd9\x58\xd2\x38\x82\xbb\xcf\x7c\x1e\x9e\x84\x5e\x68\xaf\xb8\x23\x66\xa2\x43\x3b\xd2\x92\xe3\x36\x0f\xbd\xd4\x8e\xb4\x05\xe8\xd0\xae\xb4\x45\xe8\xd2\x6e\xb4\x65\x8a\xe7\xd3\x3b\xd1\xd2\xbc\x9f\x39\xce\x4e\x6a\x67\x5a\x72\x3e\x6c\xc7\x7a\xb1\x03\xeb\xd5\x8e\x34\x3a\x1f\x42\xce\x8f\x94\xf7\x41\x13\xdb\xd0\x13\xcf\xa1\x07\xed\xa0\x35\x1a\x90\x87\x06\x37\x68\xfd\xb1\xf9\xcb\xe8\xf0\x37\xe8\x54\x03\x9f\x8b\xdb\xa1\x4d\x9c\x7c\x23\x3a\xc4\xcd\x77\xd2\xee\x7d\x5b\x2c\x45\x3b\x60\xef\x3a\xc4\xe5\x2f\xa1\xa3\x38\xdd\x88\xae\x47\x83\x62\xc1\x96\x8a\x15\x58\xfc\x13\xf4\xf8\x21\xf2\x19\x38\xfc\x4b\x1a\x59\x8f\x7f\x4b\x7b\x04\x3d\xa1\xa1\x27\x22\xb4\xaa\x39\xa2\x3d\x3a\xa2\x2b\x79\xa5\x3c\x51\x4d\xde\x28\x4f\xd4\x10\x65\x3d\x71\x09\x7a\x62\x3e\x3a\x62\x39\x51\xc4\x13\xab\xc9\x7b\x24\x7b\xee\x89\xad\xe8\x09\x03\x1d\xf1\x22\xed\xf3\xf7\x84\x89\x4e\xe8\x8c\x1a\x3f\x6a\xb5\x2a\xa3\x55\x8d\x50\x98\x3a\xf9\x61\x27\x14\x1e\xf7\xf4\x07\xdf\x0a\x76\xf8\x7e\x28\xe4\x9f\xa0\xad\xac\x5c\x3b\xe0\xff\x3e\xd1\x69\x10\x76\xe0\x34\x08\x5b\x9d\x06\x61\x2b\xab\xd0\x51\xd6\x5f\xe6\x89\x10\xbe\xc5\x26\xad\x32\x5b\x68\x68\xd3\x89\x10\xbe\xd5\x65\xab\x1d\x94\xff\xf9\xa9\x10\xbe\x85\xe2\x28\x4b\xc4\x56\x16\x85\xad\x2c\x07\x5b\x59\x08\x76\xe0\x64\x08\xfb\xb8\x27\x43\xa4\x7d\xdd\xe9\x13\x22\xce\x3f\xee\x29\x11\xb6\xd2\x9a\x6d\xa5\x1d\xfb\x6b\xd7\x15\x50\x18\xf0\x73\x3b\xcd\xfc\x86\xbe\xe6\x79\xbc\xd3\x23\xac\xd4\xe9\x11\x8b\xd1\xa4\x53\x23\x96\xa3\xdd\xcc\xcf\x9d\x79\x72\x84\xad\xb4\x2d\x5b\x69\x55\x36\x69\x4f\xbe\x06\xe4\x9f\x1e\x91\xf6\x6b\x5b\x62\x0b\xf1\xb2\x25\xb6\x06\x4e\x31\x69\x7e\x8a\x84\x2d\x76\x41\xa1\xd8\x8b\x76\xea\x14\x89\xe3\x71\x58\x79\x32\x72\x14\xf0\xd4\x3a\x41\x69\x98\xb1\x42\x49\x9e\xcf\x87\x1a\xc5\xf7\xae\xa8\x80\x1a\xd1\x1d\x6a\x32\x57\x21\xa8\xc9\x90\x90\xfe\x1c\xc8\x94\x88\xc9\xd9\xef\xcf\x01\xdf\x5b\x6a\x06\xa2\x57\xf7\xd1\xa9\x13\x41\x64\x67\x82\x4e\xcd\x09\xe2\x79\xb8\x3c\x03\x3b\xd1\xc9\xc0\xbe\x10\xa4\xf4\x08\x62\xbf\x9c\x33\x01\x84\x3d\x1f\x3f\xf8\x9e\xd9\x24\x48\xe2\x04\x21\xa5\x4f\x10\xdd\x42\x38\x3f\x84\xb1\xea\xf4\x9a\x24\x2e\xa5\x93\x32\xd2\xb8\x4c\x9d\x9a\x91\xc4\x94\x10\xae\x20\xa9\x96\xc6\x74\x75\x02\x4e\x12\x52\xd2\x05\x11\xb6\xd2\xae\x52\x92\x30\x89\xb0\xd5\x76\x9b\x92\x92\x49\x84\xad\xa2\x27\x95\x04\x4d\x22\xac\xb9\x6f\x53\x7a\xd8\xb6\xd4\xc9\x1d\x99\x9a\xf4\x73\x4a\x47\x4b\x22\xac\x59\xef\xa2\x08\x60\x1a\xbb\xfd\x53\x7a\x92\xa0\x93\x3f\x82\x58\x97\x09\xb8\x51\x71\x8e\x71\x02\x2e\x32\x52\x9c\xf4\x0d\xba\x19\x38\x42\x27\xfd\xa4\xf1\x03\x8d\x7e\x0a\x14\x27\x0d\x22\xec\xd3\xf9\x29\x7f\x49\xd8\x7f\x31\x96\xf4\x95\x34\x26\xd3\x59\x29\x69\x4c\x0d\x61\x3a\xe9\x32\x69\xcc\xa0\x3d\xb6\x69\xcc\x0c\xe1\x5a\xa5\x9d\x5e\x1b\xd0\x52\x83\x58\x40\x7b\x71\xd3\x78\x42\xc5\x6a\x93\x58\x1b\xc2\xfa\x10\xea\x69\xdf\x6e\x1a\xdb\x55\xcc\x28\x0d\x3f\xae\xe0\x23\xfd\x7d\x37\xe9\x5c\x29\x90\xc4\x3f\xf1\xa8\x1a\xa9\x91\x5d\xd9\xcc\xd3\xfc\x3c\x7c\x90\x81\x9f\xf2\x1a\x4b\xf9\x18\xc4\x11\x3a\xcd\x26\x8d\xf0\x5c\x0f\x7b\xf1\xe2\xd0\x25\x03\xa5\x4a\x2f\x4b\x22\xec\x51\x0b\x7b\xc8\xc2\x1e\xb1\xb0\x07\x2c\xec\xf1\x0a\x7b\xb8\xc2\x6b\x47\xd8\x43\x14\xf6\x08\x85\xd7\x86\x19\xe4\xb5\x49\x63\x66\x08\xd7\x90\xbc\x4b\x23\xcc\x41\xd7\x91\x1c\x4c\xa3\x39\x47\xd9\x19\x08\x7b\x1d\xc2\x5e\x86\xb0\x57\xa1\x9e\x3c\x01\x69\x84\x39\x6a\x47\x08\x61\xab\x3a\xb4\x56\x40\x71\x4a\x9f\x0b\xe8\x72\xd2\xde\xca\xd0\xe7\x3a\x41\xcd\xbf\xd4\xe5\x82\x76\x58\x58\xa7\xab\x0f\xe8\x75\xc9\x16\x2a\xdd\x0e\x9e\xa0\x3d\x9d\x41\x64\x67\x82\xce\x1b\x0b\xa2\xb9\x2c\x4b\x64\x60\x1f\xd6\x67\xc0\x0e\x61\x3f\xed\xe8\x4f\xe3\x88\xca\xf2\x38\x92\xca\xf6\xc8\xf0\xd2\xd3\x79\x66\x41\x94\xa3\x91\x81\x6e\x21\x9c\x8f\x89\x0c\x84\x3d\x9c\x97\x62\x7d\x06\x2e\xc3\x44\x06\xa6\x84\x70\x45\x08\x61\x0f\xe3\x95\x58\x9f\x81\x19\xca\xee\x9e\x91\x8a\x6a\xd7\x67\x60\xa6\xb2\xc9\x67\xa6\x62\xbe\xff\x3d\x7e\xbe\x0d\xeb\x33\xb0\x40\xd9\xf9\x49\x3c\x89\xf5\x19\xa8\x57\x36\x7f\x12\xdb\x70\x6e\x06\xb6\x13\x4f\xa7\xf1\x1c\xce\xcd\xc0\x0e\x75\x0e\x57\x12\xbb\x30\x91\x81\x90\x97\x88\xf6\xc0\x06\xb1\x2e\x13\x64\x3f\xfb\xd6\xec\xff\x9d\x53\xc3\x0c\x5a\xd7\x93\x6b\xb8\xb4\xda\x5a\x91\xbf\x68\xa7\xf2\x09\xed\x0f\xf8\x7c\xd2\xbe\x1e\x3f\xba\x7a\x45\xc0\x5f\xb3\x0b\x5d\x8d\xfd\xd4\x9e\xf6\xe3\xc4\x19\xed\x0c\xec\xa1\x88\x69\x1a\x2f\x93\xa5\x98\xc6\x1b\x21\xfc\xa7\xd2\xe2\x63\xb4\x33\xf0\x09\xd9\x8b\x69\x1c\x0a\x41\x5a\x5c\x41\x7c\x16\xc2\xe7\x21\xb8\x14\x37\x4c\x43\x5a\x68\x41\x7c\x11\xc2\x97\x14\x37\x4c\x43\x5a\x71\x41\xfc\x3d\x84\xaf\x29\x6e\x98\x86\xb4\xf4\x82\xf8\x16\xad\x0c\x48\xeb\x2f\x88\xb0\xb4\xfc\x27\x79\x38\xd2\xf8\x3e\x84\x1f\x43\x38\x1a\x02\x66\x82\xce\x18\x0c\x82\xa1\x95\x01\x2d\x04\x69\x75\x06\x11\x41\x2b\x03\x3a\x59\xa3\x69\x64\xab\xc8\x79\x12\xd2\x42\x0d\x42\x5a\xab\x41\x48\xcb\x35\x88\x56\x21\xe4\x86\x10\xd6\x16\xa4\xa5\x1b\x84\xb4\x7a\x83\x68\xaf\x22\xf8\x49\x48\x6b\x38\x08\x69\x19\x07\x21\xad\xe4\x20\x4a\xd5\x59\x8a\x41\x34\x8f\xe9\x59\x19\x68\x1e\xb3\xb3\x32\xd0\x3c\x66\x67\x65\xa0\x79\xcc\xce\xca\xc0\x4f\x69\x30\x35\x68\x65\x40\x5a\xf0\x41\x48\x6b\x3e\x08\x69\xd9\x07\x31\x24\x84\x61\x21\x9c\x13\xc2\xe8\x10\xc6\x40\x61\x06\xc6\xa1\x93\x81\xf1\x21\xd4\x85\xd0\x3c\x26\x67\x65\xa0\x79\x4c\xce\xca\xc0\x24\x74\x32\xf0\x53\x1a\xd9\x2c\xf2\xc6\xa5\x71\x2d\xda\x19\x98\x1d\xc2\x3c\x74\x32\x70\x23\xda\x19\x98\x4f\x71\xb1\x34\x6e\x46\x27\x03\xb7\x86\x10\xd6\xe8\x6e\x27\x0f\x60\x1a\x77\xa2\x99\x81\x45\x68\x67\x60\xb1\xf2\x86\x24\xb1\x04\xed\x0c\x2c\x55\x9e\x92\x24\x96\xa1\x9d\x81\xe5\x68\x65\xe0\x6e\xf4\x32\xf0\xf3\x10\x1e\xa0\x58\x58\x1a\x0f\x85\xd0\x3c\x0e\x66\x65\xa0\x79\x1c\xcc\xca\x40\xf3\x38\x98\x95\x81\xb0\x06\xbb\x91\x3c\x9f\x69\x6c\x0a\xa1\x41\x79\x28\x93\xd8\x42\x5e\x9e\x34\x1a\x95\xf7\x32\x89\xad\xe4\xfd\x49\xe3\xa7\x34\xe4\xe7\xc9\xf3\x99\x86\x41\xb1\xaa\x34\x76\xa2\x93\x81\xe6\x71\x2a\x2b\x03\x7b\xd0\xcb\xc0\x5e\xf2\xda\xa6\xf1\x92\xf2\x3a\xbd\x94\xf6\x3e\x05\xf1\x93\x71\xa7\x60\x84\xc2\x8f\x1f\xb5\x27\x6f\xaa\x47\xf1\x9c\x60\x1c\xa7\x7b\xe0\x1c\xe5\x64\x6c\xc0\xe4\x36\x1a\x14\x1b\xf8\xc6\xd7\xf3\x55\x7e\xb3\x27\x4a\x48\xa3\x0d\xc7\x09\x4c\xca\x67\x9e\x82\x56\x20\x4e\x60\x90\xbe\x7f\x15\x45\x2f\x3c\x71\x1b\x1a\xcd\xe2\x2f\x4f\xa2\x41\x7a\xff\x89\xf3\xe7\xd2\x9e\x08\x4b\x79\x22\xac\x14\xb2\x53\x30\x92\xdf\xff\xd7\x13\xf1\x3f\xee\x89\xb0\x43\x30\x02\x7a\x75\xfa\xfb\xf1\x3d\x11\x56\x06\xd6\xa5\x60\x24\xbf\x43\x8c\xef\x0b\x68\xb6\xfe\x39\xb7\xc9\x9c\x46\x3f\x66\xb1\xfe\x27\xfd\x98\x61\x5b\x6f\x1f\xe9\xcc\x69\xbc\x1b\x82\x4d\x91\xaf\x34\x9a\xdb\x76\x4e\x10\x74\x3a\x6f\x10\x25\x64\xef\xa5\x51\x4e\x3d\x48\xa3\x02\xbd\x0c\x74\x43\x37\x03\xdd\xd1\xcb\x40\xef\x10\xc6\x92\x6f\x33\x8d\x4b\x69\x86\xa5\x11\xf6\x6b\x4e\xa6\xd8\x53\x1a\x61\x3f\xe7\x54\xf4\x32\x30\x9d\x7c\x9d\x69\x5c\x49\xf6\x61\x1a\xcd\x6d\x43\x3b\x03\xff\xf3\xb6\xa1\x9d\x81\xe6\xb6\xa1\x9d\x81\xe6\xb6\x61\xd8\x4f\xea\x64\xa0\xb9\x9f\xd4\xc9\xc0\xee\x4c\xfc\xa4\x5f\xb4\x7f\xea\x04\xe9\xe4\x69\x76\x7e\x34\xdf\xe1\xaf\x92\x67\xdc\x50\x11\x7c\x87\xdb\x64\xb9\xd9\x2a\xea\xeb\x9f\xf5\xdc\x0e\x1d\xd1\x91\xbc\xdf\x69\x2f\xf7\x70\x5a\x4b\x6d\x35\xda\x46\x20\x8a\xaf\x22\x29\x64\xc5\xcb\x91\x72\xd4\x88\x38\x44\xf9\x39\xe8\x88\xdb\x48\xb7\x70\xc5\x9d\xe8\x88\xc5\xe8\x88\xa5\xe8\x88\x7b\xd0\xc9\x88\xea\x3f\x49\x91\x43\x57\x3c\xab\xa2\x20\xff\x85\x0e\x45\x42\xb6\x29\x59\xf7\x9c\x92\x71\xfe\xa9\x7b\x4e\xea\xe4\xea\xf6\x19\x67\x65\x07\x7b\xd1\x9a\xd6\xba\x64\x8c\xda\x49\xc5\xf0\x17\x04\xd6\x99\xf5\x6a\x7c\xd2\x71\x69\xdf\x2f\x1d\x7c\x42\xbb\x94\x94\xda\x83\x1e\x65\x42\xec\xf3\xf3\x8e\x29\x43\x3a\x98\xe5\x10\x5c\x1b\x92\x19\xba\xc1\x4c\xe9\x40\x66\x6e\x4a\xb2\xb5\x4e\xe5\x5d\xfb\x19\x02\x7e\x66\xc0\xe5\x21\x29\xb4\x19\x3d\x91\xc8\x88\xf1\xfb\xf9\xd6\x27\x05\x62\xe6\x7e\x04\x64\x8f\xca\xd6\xd8\xa7\x32\x34\xfc\xdc\x68\x87\x64\x63\x3b\xb5\x8f\xa0\x5c\xcd\xf2\xe1\x94\x95\xd1\xfc\xb7\x06\xa6\x65\xfc\xde\x40\x3a\x1f\xfa\x78\x79\xd0\xc7\xcb\x79\x4e\xff\xe6\x80\xda\x4b\x47\xb9\x16\x41\xfa\xd7\xa3\x0b\x1a\x3c\x00\x11\x88\x00\x40\x36\xb4\x00\x06\xad\x21\x0f\x38\x74\x85\x93\x40\x87\x9e\xd0\x0b\x72\xa0\x06\xfa\x42\x2b\xe8\x07\x83\x20\x0f\x86\xc2\x30\xe8\x00\x23\x60\x24\x74\x82\x51\x6a\x2f\xf5\x68\x28\x86\x31\x70\x01\xc4\xe1\x42\xb8\x10\xba\xc2\x45\x70\x11\x94\xc3\x04\xb8\x04\x2a\x60\x12\x4c\x82\x4a\x58\x04\xf7\x40\x15\xdc\x0f\xf7\x43\x3f\x78\x00\x56\xc1\x69\xb0\x1a\x9e\x80\xd3\x61\x2d\x6c\x80\xa1\xb0\x09\x9e\x85\xb3\x61\x0b\x6c\x81\xd1\xb0\x15\xb6\xc3\x79\xb0\x03\x76\xc0\x58\x30\xc0\x80\x0b\x60\x17\xbc\x06\xe3\xe0\x75\x78\x1d\x26\xc1\x1b\xf0\x06\x5c\x06\x16\x58\x30\x19\xfe\x00\xef\xc0\x14\xf8\x23\x7c\x08\x97\x43\x13\x34\xc1\xb5\x70\x04\x7e\x80\xeb\xe0\x28\x1c\x85\x1b\x00\x19\x83\xb9\x8c\x33\x0e\xf3\x59\x8c\xc5\xe0\x26\xd6\x8a\xb5\x82\x9b\x59\x2e\xcb\x85\x5b\x58\x3e\xcb\x87\x5b\x59\x21\x2b\x84\xdb\x58\x3b\xd6\x0e\x16\xb0\x0e\xac\x03\x2c\x64\x1d\x59\x47\xb8\x9d\x75\x65\xdd\xe1\x0e\x56\xc9\x2a\x61\x29\xab\x66\xd5\xb0\x8c\xf5\x64\x3d\xe1\x2e\xd6\x9b\xf5\x86\xe5\xac\x86\xd5\xc0\xdd\xac\x2f\xeb\x0b\x2b\xd8\xa9\x6c\x00\xfc\x9c\x9d\xce\x4e\x87\x5f\xb2\x33\xd8\x19\x70\x3f\x9b\xc6\xa6\xc1\xaf\xd8\x1c\x36\x07\x1e\x60\x3b\xd9\x8b\xf0\x20\xdb\xcd\x76\xc3\x2a\xf6\x01\xfb\x10\x1e\xe1\x03\xf8\x00\x78\x94\x0f\xe6\xc3\x61\x0d\x1f\xc9\x47\xc2\x7a\x3e\x8a\x8f\x82\x27\xf9\xb9\x7c\x34\xd4\xf3\xb1\x7c\x2c\x6c\xe4\xe3\xf8\x38\x78\x8a\x8f\xe7\x17\xc3\x26\x7e\x29\x9f\x04\x09\x3e\x99\x4f\x81\x2d\x7c\x1a\x9f\x06\x5b\xf9\x15\xfc\x0a\xd8\xc6\x67\xf0\x6b\x60\x3b\xbf\x8e\x5f\x07\x3b\xf9\xf5\xfc\x7a\x78\x81\xdf\xc0\x6f\x80\x17\xf9\x3c\x3e\x0f\x76\xf1\x9b\xf8\xcd\xb0\x9b\xdf\xc6\x6f\x83\xbd\x7c\x21\x5f\x08\x2f\xf1\x45\x7c\x31\x98\xbc\x91\x6f\x87\x57\xb8\xc1\x5f\x80\xd7\xf9\x2e\xbe\x0b\x2c\xbe\x87\xbf\x0c\x6f\xf1\x57\xf9\x6b\xf0\x47\xfe\x7b\xfe\x7b\x78\x8f\xbf\xc5\xdf\x82\xf7\xf9\xdb\xfc\x7d\xb0\xf9\x9f\xf9\x7e\xf8\x2b\xff\x90\xff\x15\x3e\xe6\x1f\xf3\x8f\xe1\x00\xff\x84\x1f\x80\x83\xfc\x10\x3f\x04\x4d\xfc\x53\xfe\x29\x7c\xca\x3f\xe7\x9f\xc3\x61\xfe\x25\xff\x3b\x7c\xc6\xff\xc1\xbf\x83\xbf\xf1\xef\xf9\x0f\xf0\x35\x3f\xca\x11\xbe\x11\x4c\x08\xf8\x4e\x64\x8b\x96\xf0\x83\x68\x2d\x5a\x03\x8a\x3c\xd1\x86\x81\x68\x27\x3a\xb2\x88\xe8\x2c\x3a\xb3\x6c\x51\x2c\x4a\x58\x0b\x51\x26\x4e\x66\xad\xc4\x00\x71\x31\xeb\x2c\x2e\x15\x33\xd8\x20\x71\xb5\x98\xcd\xce\x16\x73\xc4\x1c\x36\x46\xcc\x15\xf3\xd9\xf9\xe2\x16\x71\x2b\xbb\x50\x2c\x14\xb7\xb3\x8b\xc4\x9d\x62\x09\x9b\x20\x96\x89\x65\xec\x52\xb1\x5c\xdc\xc3\x26\x89\x5f\x88\x5f\xb2\xcb\xc5\xc3\x62\x3d\xbb\x52\x6c\x10\x1b\xd9\x3c\xf1\xb4\x48\xb0\xf9\xa2\x51\xec\x61\x0b\xc4\x4b\xc2\x64\x2b\x23\xf5\x91\x0d\xec\x5e\xbd\x42\xaf\x62\xf7\xe9\x67\xea\x33\xd9\x43\xfa\x75\xfa\x0d\xec\x45\x7d\x9e\x3e\x8f\xbd\xa4\xcf\xd7\xe7\x33\x53\xbf\x59\xbf\x99\xbd\xac\xdf\xaa\xdf\xca\x5e\xd1\x17\xea\x0b\xd9\xab\xfa\x1d\xfa\x1d\xec\x35\x7d\x91\xbe\x88\xfd\x4e\x5f\xa2\x2f\x61\xaf\xeb\xcb\xf4\xbb\xd8\xef\xf5\x95\xfa\x4a\xf6\xa6\x7e\xaf\x7e\x2f\xb3\xf4\xfb\xf4\xfb\xd8\x5b\xfa\xfd\xfa\xfd\xec\x0f\xfa\x03\xfa\x1a\xf6\xb6\x7e\x40\x3f\xc0\xfe\x1c\x7d\x24\xfa\x28\xdb\x1f\x7d\x2c\xfa\x04\xfb\x4b\x74\x6d\x74\x2d\xfb\x38\xba\x3e\xba\x9e\x39\xd1\xcf\xa3\x9f\xb3\x4f\xd4\xaf\x43\x65\xc3\x10\x18\x07\x7c\xda\xcd\x73\x66\x41\xe1\x95\x73\xae\xb8\x1a\xe2\xb3\xa6\xcc\xbd\x16\xaa\xe9\x77\x97\x00\x91\x6a\x9d\xe8\x3b\x9b\x36\xed\x9a\xd9\x10\x03\x00\x4e\xf7\xd3\x40\x40\x36\xe4\x43\x11\x94\x52\x3d\x06\x71\xd0\xe5\x67\x64\xa5\xff\x77\xe4\x88\x7f\x5d\x74\x25\xb0\xc8\x4c\x88\x40\x2e\x2b\xd5\xfa\xf2\x61\xa2\x0e\x3a\x41\x7f\x18\x02\x67\xc3\x58\x98\x08\x53\x61\x26\xcc\x81\x5b\x60\x11\xac\x80\xfb\x61\x35\xac\x85\x4d\xb0\x05\x0c\xd8\x0b\xaf\xc3\x3b\xf0\x67\x70\xe0\x33\xf8\x1a\xbe\x67\xc0\x74\x96\x13\x7b\x11\xb8\xf6\xb4\xf6\x74\xec\x05\xfa\xdc\x14\xdb\x49\x9f\x4f\xc5\x7e\x4b\x9f\x1b\x63\x06\x7d\x6e\x88\xed\x00\xae\x6d\xd2\x9e\x8e\x3d\x47\x9f\x9b\x62\xdb\xe9\xf3\xa9\xd8\x36\xfa\xdc\x18\xdb\x4a\x9f\x1b\x62\x5b\x80\x6b\x4f\x69\x4f\xc7\x1a\xe8\x73\x53\x2c\x41\x9f\x4f\xc5\xfe\x8b\x3e\x37\xc6\x36\xd3\xe7\x86\xd8\x33\xc0\xb5\x8d\xda\xd3\xb1\xa7\xe9\x73\x53\x6c\x13\x7d\x3e\x15\x7b\x8a\x3e\x37\xc6\x36\xd2\xe7\x86\xd8\x06\xe0\xda\x06\xed\xe9\x58\x3d\x7d\x6e\x8a\x3d\x49\x9f\x4f\xc5\xd6\xd3\xe7\xc6\xd8\xf3\xa0\x69\x9b\x62\xbb\x40\xd3\x9e\x8e\x3d\x0b\x9a\xb6\x31\xd6\x08\x9a\xf6\xd4\x7f\x83\x22\x7f\x56\x14\xf9\x93\xa2\x88\xad\x28\xf2\xbe\xa2\xc8\x7b\x8a\x22\x7f\x54\x14\xd9\xa7\x28\xf2\x8e\xa2\xc8\xdb\x8a\x22\x7f\x50\x14\xb1\x14\x45\xde\x54\x14\x79\x43\x51\xe4\xf7\x8a\x22\xaf\x2b\x8a\xfc\x4e\x51\xe4\x35\x45\x91\x57\x15\x45\x5e\x51\x94\x30\x15\x25\x5e\x52\x94\xd8\xab\x28\xb1\x47\x51\x62\x37\x7d\x6e\x88\xed\x27\x5a\xbc\x25\xa9\x10\x7b\x19\x34\x6d\x43\xec\x5d\x49\xa3\xff\x06\x45\x3c\x45\x91\x6f\x15\x45\xbe\x51\x14\xf9\x87\xa2\xc8\xd7\x8a\x22\x5f\x29\x8a\x7c\xa9\x28\xf2\x85\xa2\xc8\xdf\x14\x45\x5c\x45\x91\xcf\x15\x45\x3e\x53\x14\x39\xac\x28\xf1\xa9\xa2\xc4\x21\x45\x89\x83\x8a\x12\x07\x14\x25\x3e\x51\xbc\xe1\x28\x8a\x7c\xa4\x28\xf2\x57\x45\x91\xbf\x28\x8a\x7c\xa8\x28\xf2\x81\xa2\xc8\xdf\x89\x47\xbe\x23\xba\x7c\x4c\x14\x69\xa2\x5f\x2c\xfc\x3f\xa6\x48\x56\xbe\x4f\x91\xac\x3c\x9f\x22\x59\xb9\x3e\x45\xb2\x5a\xfb\x14\xc9\x6a\xe5\x53\x24\xab\xa5\x4f\x91\xac\x1c\x9f\x12\x59\x2d\x7c\x4a\x64\x65\xfb\x94\xc8\x8a\xf9\x94\xc8\x8a\xfa\x94\xc8\xd2\x7d\xde\xc8\x8a\xf8\x14\xc9\x12\x3e\x45\xb2\x34\x9f\x22\x59\xcc\xa7\x48\x16\x28\x8a\xa0\xa2\xc8\x31\x45\x91\x1f\x15\x45\x7e\x50\x14\xf9\x5e\x51\xe4\x9f\x8a\x22\x47\x7c\x8a\x64\x65\x49\xee\xc8\x2a\x20\x8a\x1c\x95\x14\xc9\xe2\xff\x4d\x8a\xf4\x52\x94\xe8\xa9\x28\xd1\x43\x51\xa2\x5a\x51\xa2\x52\x51\xe2\x24\x9f\x37\xb2\xba\x2b\x8a\x74\x53\x14\xa9\x50\x14\xe9\xaa\x28\x52\xa6\x28\x52\xaa\x28\x52\xa2\x28\x12\x57\x14\xe9\xa2\x28\xd2\x59\x51\xa4\x93\x4f\x91\xac\x8e\x3e\x45\xb2\x8a\x7c\x8a\x64\xb5\xf7\x29\x92\xd5\xce\xa7\x48\x56\x5b\x9f\x22\x59\x6d\x7c\x8a\x64\x15\x2a\x8a\x94\x13\x45\xaa\x24\xa7\x64\x75\x20\x8a\x14\xfb\xbf\x6a\x09\x4c\x5e\x9f\x5a\xa5\xf3\x81\x41\x27\x5a\x87\x39\x30\xe0\x70\x0e\x9c\xab\x55\x82\x06\xad\xb4\xbd\xda\x7b\x00\xda\x07\xda\x07\xd0\x46\x43\xce\xa0\x2d\x17\x5c\x87\x0e\x3c\xc6\x63\xd0\x89\xe7\xf0\x56\xd0\x99\xe7\xf3\x42\x88\xf3\x0e\xbc\x03\x94\xf1\xce\xbc\x33\x74\xa5\x5f\xfc\x2c\xa7\x5f\xfc\xac\x89\x3c\x12\x59\x0d\xa7\x46\xd6\x44\xd6\xc2\x69\x91\xf5\x91\xf5\x70\x06\x30\x76\x3f\x70\xc8\x81\x6b\x19\x40\x0c\xf2\xa1\x13\x54\x40\x6f\xe8\x0f\x43\x61\x34\xd4\x65\xf5\x03\xa1\xbd\xa6\xbd\xa7\xbd\x94\x75\xaa\xfa\xb6\x37\xeb\x14\xfa\xf6\xae\xf6\x52\x56\x5f\xf5\x6d\x6f\x56\x1f\x10\xda\x2b\x54\xaf\x46\x7d\xdb\x9b\x75\x32\x7d\x93\xf5\x7a\xab\x6f\x7b\x21\x07\x8a\xa0\x2b\xf4\x84\xd3\x60\x08\x9c\x03\xe3\x61\x32\xcc\x84\xb9\xb0\x10\x96\x67\x8d\x02\xa1\xbd\xae\xbd\xa6\xbd\x94\x75\xb6\xfa\xb6\x37\x6b\x24\x7d\x7b\x45\x7b\x29\x6b\x84\xfa\xb6\x37\xeb\x8c\x54\x8b\x06\xa5\x5a\x74\x7a\xaa\x45\x03\x53\x2d\x1a\x90\x6a\x51\xff\x54\x8b\x6a\x53\x2d\x3a\xed\xdf\x68\xd1\x79\xa9\x16\x8d\x4e\xb5\xe8\xdc\x54\x8b\xce\x49\xb5\x68\x78\xaa\x45\xc3\x52\x2d\x3a\x2b\xd5\xa2\xa1\xa9\x16\x9d\x99\x6a\xd1\x90\x54\x8b\x7e\x96\x6a\xd1\xe0\x54\x8b\x18\x70\x3e\x8d\x5f\xcd\xe7\x83\x06\x39\xc0\xe1\x1f\xec\x9f\x91\x71\x01\x4e\xe0\xe2\x3d\x6d\x27\x44\x40\x44\x56\x47\xfa\x00\xb0\x62\xff\x93\xbf\x0d\xd3\x35\x88\x69\x5a\x8b\x98\x26\x22\x22\x4b\x13\x1f\x81\x86\x83\xe1\x26\x04\x80\x12\xa9\x15\x9c\x7b\xde\xe8\xf3\xa0\x04\x5a\xe2\x51\x7d\xfa\xb1\xe9\x00\xb1\x7b\xb4\x3b\xe2\xc0\x1e\xff\xeb\xfb\x00\x62\x52\x64\x3b\x00\xc4\xa1\xbd\xe2\x43\x09\x9f\x0b\x81\x7f\x43\x9c\x28\xff\x16\xdc\x06\x80\xaf\xe1\x0e\xd0\x61\x0e\x00\xb4\x84\x85\xfc\x3a\x3e\x8f\x2f\xe4\x2b\xf8\x4a\xfe\x1b\x6e\x45\xba\x75\x7e\xbd\xcb\xa3\x5d\x1e\xeb\xf2\xcf\xe2\x36\xc5\x9d\x8b\xcf\x2a\x3e\xb7\xf8\xa2\xe2\x09\xc5\x17\x17\x5f\x5a\xbc\xa0\x78\x6b\xb1\x59\xbc\xaf\x78\x7f\xf1\x97\xc5\xdf\x14\x1f\x8b\x97\xc6\x2b\xe2\xbd\xe3\x7d\xe3\xfd\xe3\x03\xe3\x83\xe2\x43\xe3\x97\xc5\x67\xc7\x6f\x8e\xdf\x1e\x7f\x20\xfe\x54\x7c\x5b\xdc\x88\x7f\x55\x12\x29\x29\x28\x69\x57\x52\x5a\x52\x51\xd2\xb3\x64\x74\xc9\xb8\x92\x49\x25\x4b\x4a\x1e\x2c\xd9\x58\xaa\x95\xea\xa5\xad\x4b\xf3\x4b\xdb\x94\x16\x95\x16\x97\x9e\x54\x5a\x55\x3a\xa2\x74\x4a\xe9\x15\x65\x5a\x59\x6e\x59\x49\x39\x94\x6b\xe5\x39\xe5\xb9\xe5\x85\xe5\xed\xcb\x3b\x95\x77\x2d\xaf\x2e\xef\x5b\x3e\xb0\x7c\x56\xf9\x1d\xe5\x4b\xca\x97\x97\xaf\x2c\xff\x55\xf9\x6f\xca\x9f\x29\xdf\x52\x6e\x94\xef\x2c\x37\xcb\xdf\x28\x7f\xab\xfc\x4f\xe5\x87\x2a\x06\x56\x0c\xae\x18\x52\x31\xb9\x62\x5a\xc5\xf4\x8a\xab\x2b\xae\xab\xbe\xa6\x7a\x7e\xcf\x76\x1b\x4a\x36\xac\xfc\x08\x7e\x10\xc7\xca\x8e\x21\x1e\x45\xa4\x5f\xbd\x6c\x09\x71\x78\x82\xcf\xe5\xb7\xf0\x25\x7c\x25\xbf\x97\xaf\xe3\x7f\xe8\x0c\x9d\x8f\x75\x79\xac\xcb\x13\xc5\x50\xdc\xbe\x38\x5e\x3c\xa2\x78\x8c\xea\xf3\x65\xc5\x77\x14\x6f\x2f\x7e\xa5\xf8\xbd\xe2\x0f\x8b\xbf\x2e\xf6\xe2\x10\xaf\x88\x57\xc6\x6b\xe2\xb5\xaa\xcf\x93\xe2\x33\xe3\x73\xe3\xb7\xc7\xef\x8b\x3f\x11\x7f\x3a\xfe\xbc\xea\x73\x5b\xd5\xe7\x73\x4b\x2e\x28\xb9\xb8\x64\x49\xc9\x7d\xa9\x3e\xe7\x95\xb6\x29\xed\x50\xda\x45\xf5\x79\x72\xe9\xe5\xd4\xe7\xf8\x09\xfa\x3c\x26\xd5\xe7\xfb\xca\x9f\x28\xdf\x94\xea\xf3\xeb\xe5\x6f\x95\xdb\xe5\x87\x2a\xfa\xa7\xfa\x7c\x45\xc5\xcc\x8a\xeb\xaa\x27\x57\x5f\xdf\xb3\xdd\x86\x76\x1b\x96\x7f\x04\x3f\xb0\x63\xf1\x63\x88\x3f\x4a\x4d\x12\xbf\xc5\x4f\x70\x2f\xbe\x88\x06\x6e\xc3\xad\xd8\x88\x5b\xb0\xa1\xe9\x4f\x4d\xf5\x4d\xeb\x9b\xd6\x35\xfd\xba\xe9\xd1\xa6\x47\x9a\x1e\x6e\x7a\xb0\xe9\x81\xa6\x5f\x35\xdd\xdf\xf4\xcb\xa6\x5f\x34\xdd\xdb\x74\x4f\xd3\xcf\x9b\x56\x34\x2d\x6f\xba\xab\x69\x59\xd3\xe2\xa6\x3b\x9a\x6e\x6f\xba\xb5\xe9\x96\xa6\x9b\x9b\xe6\x36\x5d\xdc\x74\x7e\xd3\xe8\xa6\x91\x4d\xb5\x4d\x3d\x9b\x7a\x34\x55\x1e\xfa\xf6\xd0\xc7\x87\xfe\x78\xe8\x9d\x43\xaf\x1d\x7a\xf9\xd0\x8b\x87\x9e\x38\xb4\xe6\xd0\x43\x87\xae\x3f\x34\xfd\xd0\xb8\x83\x3f\x1c\x3c\x72\xf0\xab\x83\x5f\x1e\xfc\xdb\xc1\xcf\x0e\x36\x1d\xfc\xcb\xc1\x0f\x0f\xee\x39\xb8\xe9\xe0\xc6\x83\x39\x07\xf0\xc0\x57\x9f\xe4\x7f\x92\xf7\x49\xec\x93\xc8\x27\x9a\x83\xce\x8f\xce\xb7\xce\x17\x4e\x93\xf3\x91\xf3\xa6\x63\x38\xcf\x39\x5b\x9d\x06\x67\xb3\xb3\xd6\x59\xed\x3c\xe8\xdc\xeb\xdc\xe3\x2c\x73\xee\x74\x6e\x77\xe6\x3b\x57\x3b\xed\x9d\x36\x4e\xe1\xc7\xdf\x7d\xfc\xed\xc7\xdf\x7c\xfc\xf7\x8f\xbf\xd8\x7f\x6c\xff\x0f\x7f\xbe\x64\xca\xa5\x93\xbf\xeb\xbe\xa4\xe5\x92\xec\xab\xb2\xee\x8d\x25\x7f\xdb\xf4\xff\x5f\xff\x74\x2d\x1b\x7c\x93\x23\xdc\x7b\x46\x3f\xf4\x0c\x00\xa9\xcf\x13\xfd\xf3\xaf\xe4\x74\x26\xa2\x0e\x51\x88\x41\x16\xf9\x0d\x72\xa0\x25\xb4\x82\xd6\x90\x0b\x79\x90\x0f\x05\x50\x08\x6d\xa0\x2d\xb4\x83\xf6\xd0\x01\x8a\xa0\x23\x74\x82\xce\xd0\x05\x8a\x21\x0e\x25\x50\x0a\x65\xd0\x15\xca\xa1\x02\xba\x41\x77\x38\x09\x2a\xa1\x0a\xaa\xa1\x07\x79\x1b\x7a\xc3\xc9\x50\x03\x7d\xa0\x2f\x9c\x02\xa7\x42\x3f\x38\x0d\x6a\xa1\x3f\x0c\x80\x81\x70\x3a\x0c\x82\x33\x60\x30\xfc\x0c\x86\xc0\x99\x30\x14\xce\x82\x61\x30\x9c\x3c\x11\x67\xc3\x28\xb9\x6a\xc2\x68\x38\x0f\xc6\xc0\xf9\x30\x16\x2e\x80\x71\x70\x21\x8c\x87\x8b\xa0\x0e\x26\xc0\x44\xb8\x18\x2e\x81\x4b\x61\x12\x5c\x06\x93\x61\x0a\x00\x2c\x83\xbb\xe0\x6e\xf8\x39\xfc\x0a\x56\xc1\x63\xb0\x0e\xd6\xc2\x7a\xa8\x87\x27\x61\x03\x3c\x05\x4f\xc3\x26\x78\x06\x9e\x85\xff\x82\xcd\x90\x80\x06\x68\x84\x6d\xe4\x95\xd8\x01\xcf\xc1\x4e\xf8\x2d\xbc\x00\x2f\x46\xeb\x61\x0e\x5c\x0e\x57\xc0\x55\xd1\x8d\x70\x13\xfc\x06\x66\xc3\xd5\xd1\xcf\xe0\x46\x98\x19\xcb\x86\xe5\xb0\x3a\x16\x81\x1b\x62\x39\xb1\x96\x70\x25\xcc\x8f\x1e\x8d\x41\x14\xf9\x9c\x58\x0c\x66\xc1\x6d\xfc\x62\xd8\x08\x06\xdc\x09\xd3\xe0\xda\x98\x60\xe3\x62\x59\xd1\x63\x70\x0d\x2c\x88\x3e\x05\x53\x61\x11\x2c\x85\x87\x59\x21\x6b\x13\x7d\x24\xba\x3a\xba\x36\xba\x2e\xfa\x58\xf4\x71\x78\x3e\x36\x0a\xf6\xb0\xfe\xd1\x1d\xd1\x3f\x45\xb7\x46\xb7\xc5\x96\xc6\x96\x45\x37\xc0\xcd\xd1\x27\xa2\xeb\xa3\x09\x58\x02\x2b\x61\x31\xdc\x03\x2b\xe0\x17\x70\x1f\xfc\x12\xee\x85\x07\xe1\x21\x00\x78\x00\xd6\xc0\xaf\xe1\x51\xf8\x87\xb6\x5c\x7b\x0c\xae\xd7\x56\x6b\x8f\x6a\x6b\xe0\x16\xed\x71\xed\xd7\xda\xdd\x72\x08\xa5\x2c\x60\xc0\xaa\xe0\x4f\xf0\x57\x38\x08\x87\xe1\x6b\xf0\x98\x80\xdf\xb3\x1e\xac\x07\x3b\x99\xf5\x83\xb7\x60\x09\xdc\xcd\xba\xb0\x93\x58\x3e\x6b\xc9\x74\xf8\x11\xde\x67\x15\xac\x2b\x1c\x83\xed\xac\x94\xb5\x67\x71\x78\x90\x15\xc1\x33\xf0\x21\xbc\x06\x2f\xc3\x22\xb8\x0e\xde\x06\x03\x76\xc0\x4e\x56\xc8\xda\x42\x3d\xeb\xc3\x5a\xb0\x18\x7c\x09\x2b\x59\x2e\xdc\xcb\x7a\x01\x24\xa0\x3a\x01\x05\xa3\x12\xe7\x8c\xa9\x4b\x9c\x7d\xe3\x84\x04\x94\x9d\xd1\x3e\xa1\x57\xd5\x9d\x3e\x81\xca\x16\x4c\x88\xff\x31\xc1\x0a\x7a\xb6\xef\x91\x60\xd5\xf1\x3f\x27\x72\xaa\x7a\x24\xb4\xea\x51\x63\xeb\xce\x2a\x9b\x50\xd2\x23\xc1\xab\xaf\x6a\x1f\x4f\x0c\x1e\x53\x57\x92\x18\x3c\xa1\x47\x42\x54\xcb\x4b\x4b\xca\x4a\x6e\xa9\xfb\xb0\xe3\x9b\x13\x3a\x8e\x1a\x5b\x57\x77\xb4\xe3\xdf\x26\x74\x2c\x2b\x49\x44\xaa\xea\x12\xc3\x6e\x9c\x40\xff\x31\x61\x42\xfb\x1e\x89\x48\x75\xcb\x4b\x26\xf6\x48\xe8\xd5\x0d\xa5\x6c\xf9\x98\xba\x44\x7c\xf9\x25\x97\x74\x4c\xc0\x84\x1e\x89\x68\x75\x43\x57\x2a\x1a\x9c\x2a\x8a\x55\xe7\xe7\xc5\x6b\x7b\xf5\x48\x64\x55\xc7\x17\xc8\x87\x98\x1d\xdf\x9c\x10\x4f\xf0\xf2\x91\x65\xf1\x84\xa8\x38\x3b\x01\x63\xea\x56\x5c\xb1\x62\x4a\x5c\x7e\x39\xad\x63\x49\xc9\x84\x8e\x2b\xe8\xaf\xb1\xfe\x5f\xf2\x81\xd9\x7e\xeb\x72\x3b\xe6\x96\x4c\xe8\x91\x68\x51\x1d\x7f\x87\xba\x93\x53\x1d\xef\x95\x88\x56\x5d\x52\x17\x8f\x0f\x2f\x1b\x36\x65\x66\xbc\x2e\x7e\xf9\x54\xff\x16\xb2\x5e\x4b\xf9\xe4\x78\x6d\xaf\xf8\x8a\xf8\xf0\x15\xc3\xa6\x94\xad\x88\xaf\x28\xa3\xc7\x95\xc9\x9b\x27\x06\x9f\xd6\xb1\x64\x42\xc7\x32\x59\x90\x18\x7c\x85\xfc\x63\x42\x8f\x44\x2b\x7a\xd2\xe9\xef\xb5\x2f\x29\xe9\x18\x7f\x6f\xc5\xa8\xb1\x75\xf1\x15\x65\x23\xe3\x09\xb8\x50\xb5\xad\x84\xaa\xb5\xae\x2e\x8b\xbf\xa7\x1e\x5e\x16\xaf\x1b\x75\x41\xc7\x92\x04\x9b\x50\xb7\x22\x21\x2a\x46\x96\xad\x28\x8b\xaf\x18\xb9\xa2\x6c\x8a\xbc\xc0\xbf\x44\x7e\xf4\x48\xe4\xca\x61\xc8\xaf\xea\x91\xc8\x93\x1d\x90\x5f\xf2\x43\x1d\x58\x21\x3f\xca\xa6\xcc\x9c\x1c\xec\x89\xbc\xb4\xa0\x3a\xbe\x22\xbe\xe2\x2e\x49\xb6\xb3\x2f\x2f\x5b\x11\x4d\xc4\xc7\xd4\x0d\xec\xb8\x7b\x42\x8f\x44\x61\x75\x23\x0c\x66\x83\x87\x0c\x61\xa3\x76\xe4\xc2\x34\xa0\x77\x59\xf9\xc2\x3a\xf9\x3e\xb6\xae\x6c\x6a\x3c\x01\x65\x43\x3a\x4e\x8d\x27\x58\xd9\x90\x09\xf1\xc4\xe0\xb1\x75\x5b\x20\x0e\x67\x4e\x1b\xb2\x85\xc5\xd9\x99\xd3\x86\x24\xe2\xd3\x12\x1d\xae\xe8\x94\x7c\x56\x9b\xea\x04\x3b\x73\x5a\x59\x02\xce\x9c\x56\xd6\xc3\x5f\xa3\x18\x22\xb4\x06\x0d\xf6\x00\x88\xec\xc8\x76\xe0\x10\x05\xe8\x93\x57\x92\x57\x5e\x92\x57\xb2\x87\x8f\x3c\x5a\xac\xdd\x7c\xf4\xae\xc8\xf6\xef\xcf\x9e\x21\x0e\x81\x06\x1d\xf0\xa0\x76\x57\x64\x3b\xb4\x80\xd6\xd0\x0f\xb6\xb4\xd4\xa0\x2a\x91\xd5\x6b\x2b\x17\x50\x20\xaa\x58\x22\xb7\x57\x02\xde\xdb\xaa\xe7\x42\x67\x51\xd5\x90\xc7\xaa\x1a\x74\xc8\xcb\x6f\xc8\x69\x59\x5b\x0b\x0d\x2d\x79\x5e\x7e\x22\xa7\xb6\xf7\xc9\xfd\xfa\x9e\xda\xa7\xa6\x6d\x9b\x42\xbd\xac\xb4\xa2\x23\x2b\x61\x1d\xae\x9e\x32\x74\xec\xb5\x13\x46\x8e\x5d\xf0\x6b\x36\x0e\xe1\x86\x89\xb3\xce\x39\xeb\xa2\x59\xa3\xd8\x36\xfe\xf6\x8f\xbd\x40\x83\xdf\xf1\x7a\x6e\xa8\xb6\x75\x81\x2d\x9a\x7c\x66\xa4\xcf\x56\x21\x20\x26\xaa\x12\x50\xc3\x12\xb1\x5e\x0d\x59\xac\x0a\x7a\x9f\xdc\x91\x95\xf0\x3e\x05\x25\xfc\x77\xc3\x59\x9b\x55\x6f\x9d\xcd\x0a\x1f\xe6\xf5\x5a\xee\xd1\xaf\x24\x68\xcd\x3e\x09\x20\x72\x4a\x64\x3b\x74\x84\x62\x76\x1e\x6c\x29\x02\xa8\xda\xd2\xa6\x6d\x87\x3e\x7d\xfa\x6c\x89\x6a\x50\xb5\x25\xd6\x22\xa7\x4f\x9f\x3e\x5b\x81\x15\x45\x5b\x56\x35\x6a\x79\x9d\x3a\x77\x6d\xd7\xa7\x01\x72\x0e\x37\x16\xb6\x6b\xdf\xb1\x6b\xbb\x9a\xad\x11\x41\xff\xc5\x73\xbb\x14\xcb\xff\x8a\xe4\x1c\x6e\xd4\xb3\xb2\x5b\x76\x6d\x57\xc3\x12\xf1\x5e\x89\xa2\xf7\xb6\x76\x68\x09\x79\xa2\x2a\xd1\x21\xb7\xa1\x2d\xab\x4a\x44\x6b\xb6\xb6\xf1\x0b\x62\x35\x89\x36\xb9\x0d\x2d\x58\xd5\xd6\x1c\x2a\x68\x28\x61\x55\x89\x53\x8b\x8c\xd3\x87\xfd\x6d\x31\xb4\xa9\xca\x36\x4e\xbf\xe7\x8b\x79\xf2\x4b\xa2\x28\xb7\x51\x2b\x8a\x16\x54\x35\x72\x7a\xd7\xe5\x7b\xa2\x43\x6e\x63\x56\x87\x58\x41\x55\xa2\x6d\x6e\x63\x76\xdb\x16\x05\x55\x89\x36\xb9\x8d\x2d\xdb\xe4\x14\x54\x35\xe6\xd2\x7b\x1e\xbd\x17\xca\x77\x59\xa7\x1d\xd5\xe9\x90\xdb\xd8\x9e\xae\x2a\xca\x6d\xec\x98\xbc\x4f\xa7\xe4\x7d\x3a\xcb\x3a\x8d\x5d\x92\x35\x8b\x65\x39\x1f\x9c\xab\x71\xd9\xa5\xdc\x3c\xd9\xe7\x4e\x9d\xbb\x14\xf7\x0c\xfd\x4b\x0c\x2e\x6a\xe8\x50\x94\x97\x9f\x88\xd4\x36\xe4\xb4\xc8\xcb\x4f\x14\xd4\x42\xef\x93\x0b\xfa\x95\xf4\x2b\xeb\x57\x52\xd0\x87\xf7\x91\x88\x96\xc8\x17\x2f\x2b\x28\xe3\x65\x05\xe5\x7d\xfa\x95\x9d\x94\xcf\xda\x0c\xfb\x31\x9f\x95\xcc\xff\xd3\xbc\x57\xe7\xbe\x3f\xf7\xcb\xfc\x63\x87\xcf\x62\x5a\xc1\xb1\xf7\xe7\x7e\x30\x6f\xef\x0d\xef\x5f\xcf\xf2\x5f\x3e\xcb\x64\xab\xac\x4f\xdf\x66\x0f\x1f\xbb\x4a\xe2\xed\x4f\xad\x63\x33\xd8\x2a\x09\xeb\x53\x00\x01\x7d\xf0\x6e\x31\x59\x2f\x24\x09\x59\x0e\xd5\x6c\x00\x24\x3a\xf7\x4a\x14\xf5\x69\xe0\xb1\xc3\x89\x8a\x9a\x2d\x9d\x79\x76\x55\xe3\xe0\xce\x1d\xb3\xaa\x12\x9d\x6a\x12\x65\xbd\x12\xf9\x7d\x1a\xb2\xb3\x0f\x27\x5a\xd6\x24\x5a\xf4\x4a\xe4\xf4\x61\x89\x1e\xbd\x12\xd1\xf7\x1a\xe2\x2d\x0f\x27\x3a\xd6\x24\xe2\xb9\x5b\x3b\xb5\x84\x16\xa2\x2a\xd1\xa9\xd7\x96\x4e\x71\x79\x6d\x27\xc8\xaa\x4a\xc4\x73\x1b\x4e\x62\x55\x0d\xed\x5a\x1e\x4e\xb4\x88\xbf\x97\x27\x07\xac\x85\xa8\x6a\xe8\xe9\x0f\xd8\x20\xeb\x1f\x0d\x72\x9c\x5a\x25\x3a\xe5\x26\xc4\xee\x44\xc7\xdc\x44\xf5\x6e\x63\xd0\x84\xbf\xaf\xa4\xd1\x6b\x91\x9b\x28\xdd\x9d\xc8\xc9\x4d\x14\xec\x8e\x24\x3a\xe5\x36\xf2\x4e\xa2\xa0\x2a\x51\x9a\xdb\x98\x5d\x2a\xe9\x5c\x90\xdb\xd8\xb2\x40\x8e\x54\xbe\x7c\x4f\x74\xcc\x6d\x2c\xea\x58\x5d\x50\x25\x6b\x76\x4e\xd6\x2c\xa3\x9a\x1d\x73\x1b\x2b\xe4\x7f\x71\x68\x14\x05\xa5\xd5\x92\xf2\x6c\x70\x0e\x17\xd9\x2d\xf3\x0b\x8a\x3a\x97\x96\x55\x54\x87\x07\xa5\x5d\x4e\x5e\x7e\x22\xb7\x16\x1a\x78\xe7\xbc\xfc\x06\xe8\x50\x5b\x9b\x28\xcb\x6b\x64\xd1\xdc\x76\x5d\xdb\xd5\x26\xb2\xf3\x1b\xb2\x5a\xd7\xd6\x26\x5a\xe4\x25\x8a\xe5\x3c\xcc\x6b\xdb\xae\xa0\x27\x3b\xa5\xef\xa9\x67\xb0\x3e\xd1\xb6\xed\xa2\x15\xdd\x78\x17\xad\x4d\xa1\xde\x9a\x95\xf5\xab\xe8\xc8\x0a\xdb\xf5\x6b\xc5\x0a\x06\xb1\x53\xfa\x56\x74\xeb\xf3\x8a\x35\x7c\xdd\x9a\x63\x7f\x2d\xfb\x79\x49\xfd\x9d\x33\x97\x5c\x7b\xc6\xe2\x3b\x86\xfc\xf0\x75\xb7\x95\xd5\x6f\x3f\xb2\x6a\x4c\x9f\x41\x67\x5d\x72\xc6\xe8\x93\xcb\x36\xb2\xec\xab\xb3\xd9\x90\xd3\xb7\xde\xf6\xec\xbb\xad\x1f\x7e\xb8\xed\xd0\x4f\x7f\x96\x75\xec\xdd\x3e\x53\xee\xbc\x70\xc7\xfb\x79\xaf\xfe\x2e\x27\x52\x77\x6c\xc4\x79\x71\x2f\x3a\xf4\x68\x2c\x6b\xc4\xa0\x9e\x03\x5a\xc9\x35\x28\x02\x37\xe0\x17\xfa\x2f\x22\xbf\x87\x96\x90\x07\x1d\xe1\x24\x38\x05\x36\xc3\x96\x56\x72\x66\x76\x03\xa8\x6a\xa8\xce\x39\xbc\xa5\xb5\x9c\x9b\x42\x83\xaa\x86\x0e\x39\x87\xb7\xb6\x28\xec\x26\x5a\x56\x35\xb4\xc8\x39\xbc\x35\x5e\x43\x5f\xe3\x39\x87\x59\xe2\x54\x5a\x7c\xf2\x5b\x42\x7b\x51\x95\xc8\xcf\x6d\x68\xc7\xaa\xb6\x46\xfd\xbf\xa2\xb9\x0d\x9d\x58\xd5\xd6\x4a\xff\xaf\xca\xdc\x86\xde\xac\x6a\x6b\x19\xfd\xd5\xd0\x4f\x0e\x74\x7e\x5e\xfe\x96\x16\x22\xaf\xb6\xb6\xb6\xa1\x77\x65\x5e\xfe\x96\x78\xb7\xd6\xb5\x72\xd1\x6a\xd1\x2a\x2f\xbf\xa1\x53\x65\x6d\x6d\xa2\x30\xaf\xa1\xac\x77\x6d\x6d\x43\xbc\x46\x52\x36\xbf\xb6\x36\xd1\x21\xaf\xa1\x5d\xb4\xb6\xb6\xf7\xc9\x05\x7d\xf3\xfd\x15\x4d\x93\x4b\x5a\x01\xeb\xc3\x78\x61\x9f\x9a\xfc\x53\xfa\x96\x95\x6a\x2c\xe3\xff\xfa\x15\xf6\xa9\x91\x04\x2d\x2b\x6d\xc5\x6e\xb8\xce\xb8\xf5\xee\x07\x67\xbf\x78\xcb\xcf\x7f\x31\x57\x0c\xfe\xfc\x87\x97\xaf\x3b\xed\x67\x93\x6a\xcf\xb8\x4c\xbb\x62\xe6\x0b\x0b\xee\x7e\x70\xd6\xce\x9b\xef\xfb\xa5\xd7\xef\xa4\x11\xbd\xfa\x77\x1b\xd1\x93\xcf\x7b\x8a\x75\xbe\xef\x89\xc7\xea\x8f\x7d\x74\xff\x86\xa3\x5d\xe5\x82\xcc\x2f\x9f\xcc\xf4\xfb\x26\x1f\xc3\xa3\xa5\x0d\xac\xf4\xc1\x5f\xaf\xda\x70\x6c\xff\x03\xbf\xbe\x7f\xca\xb5\xaf\x4e\x99\x3c\xfb\x35\xe0\x30\x14\xdd\xc8\x43\x91\x37\xa1\x23\x74\x85\xde\xb0\x10\xb6\xb4\x95\x34\xed\x20\x69\x5a\xcc\x0f\x6f\x89\x49\x72\xf6\x8c\x1d\x66\x89\x93\x7b\x25\x22\xef\x35\x94\xb7\x3c\xdc\xd8\xa9\x3c\x12\xab\x6a\x80\xdc\xc3\x09\xe8\xd5\xd0\x29\xf7\x70\xa2\x3c\xb7\xa1\x8a\x55\x35\xb4\x68\x79\xb8\xa1\x86\x55\x35\x94\x77\xca\xcb\x6f\xec\xc0\x8b\x4b\x25\x3b\x55\xe5\x6d\x89\xb5\x2c\xa9\x95\x0c\x95\xbf\xb5\x55\x5e\x61\x5b\xc9\x64\xd0\x50\xdc\x36\x2f\x3f\xd1\xae\x36\xd1\x33\x6f\x1b\x44\x5a\x14\x96\x76\xef\xda\x8e\x68\x74\x6a\xbf\x8a\x53\xfc\x95\x3f\x37\x52\x30\x88\xf5\x2b\xd1\xa2\x05\x25\xdd\x24\x55\xca\x0b\xdb\xf6\xa9\xe9\xc7\x5b\xb1\x82\xc2\xb6\xed\x88\xdf\xca\x4a\xf5\xa1\xbf\x7e\xe9\x9c\xcf\x5f\x7d\x6a\xef\xb1\x5f\xbd\x54\x3d\xb2\x92\x55\x2f\x6d\x78\xf3\xd8\xda\x11\xff\x75\xe0\xed\xbf\xb2\x01\x17\x0f\xbf\x61\xe6\xc7\xff\x0f\x7b\x7f\x1e\x1f\x55\x75\xff\x0f\xc0\xe7\xdc\x6d\xf6\x99\x7b\xef\xcc\x64\x32\xd9\x27\x93\x95\x4b\x32\x49\x2e\xc9\x30\x22\x20\x08\x08\x61\x11\x11\x11\x59\x22\x28\x22\x8a\x88\x34\x22\x2a\x22\x22\x45\x04\x45\x8a\x28\xe2\x6e\x71\x2d\x45\xbf\xe7\xce\x0c\xc1\x85\xd2\xb8\x57\xd1\x52\x6b\x8d\xfa\xa5\x56\xad\x75\xb9\x16\x6d\x8b\xd6\xb2\x24\x37\xcf\xeb\x9c\x73\x67\x32\x13\x26\xb8\xf4\xfb\xfc\x5e\xcf\x1f\xcf\xcb\x97\x93\x49\x02\xcc\xf9\xec\xeb\x79\xdf\x99\xe3\xbe\xce\x97\x96\x9d\x73\x6a\xcd\xe8\x09\x70\xe1\x96\x03\xf3\x6f\xbc\xe1\xc5\x8f\x1f\xbd\xcd\xf8\xe2\x76\xe3\x68\x6c\xcd\x12\xe3\xd5\xa7\x8d\x8f\x2f\xb8\xea\xc5\x3f\x8d\x9a\x31\x0c\x8e\x57\x17\x33\x97\xd5\xcf\x29\x1c\xb6\xe8\xd4\x98\x3a\x17\xc7\xbd\xd7\xd8\xc7\x98\x4a\x12\x53\xca\x41\x1c\x32\x40\x49\x02\x12\x4e\x20\xe2\x88\x16\x31\x22\x28\xe1\x14\x8d\x4f\x47\x15\x12\x51\x68\x30\xc1\x7f\xbf\xd5\xd8\xcb\x8e\x27\x71\x30\x0c\xe2\x2c\x03\x14\x88\x9c\xe4\x2f\x5a\x5c\xa0\x8a\x53\x34\x17\x54\x34\x0b\x90\x64\x64\x27\x9e\x51\x94\x61\xc8\x0e\x25\xd1\x1b\x66\x5a\xff\x0d\x59\x28\xf4\xfe\x7b\xf9\x97\x77\xc2\x20\x3c\x9b\x19\x09\x1d\xc6\x97\x3d\x9a\xf1\x1b\xe3\x0d\xe3\xaf\xd0\x0e\x60\xef\x12\x63\x2f\x73\x29\xdf\x01\xec\xf8\xdf\xe6\xc8\xbf\xed\x88\x20\x26\xfd\x6f\x3b\xf1\xbf\xcd\x10\xef\x0b\x1a\x1a\x59\x20\x89\xac\x2a\x4b\x22\xc3\x6e\x85\xdf\x5c\xa9\xdf\x79\xa4\xd7\xd8\xcb\x84\x98\xf5\x50\x85\xa5\xc6\x11\x63\x97\xb1\xb3\xe7\xb7\xc6\x51\x00\xc1\x2e\x66\x34\xb7\x5e\xa8\x04\x6e\x00\xbc\x51\xde\xcb\xb3\x95\x96\x4a\xaf\xc5\x01\xab\x2b\x77\xcd\x80\xd3\x42\x10\x2c\x83\x6b\x65\xe3\xa9\x87\xbe\x9b\xf5\xf2\x01\xe8\xe5\x96\x7f\xf5\x14\x5c\xa6\x1a\x0f\x16\x1b\x8a\x81\x26\xc0\xb3\x8c\x2f\x1f\x39\x42\x72\x86\x25\xe0\x08\x57\xc9\x21\xe0\x00\xe7\x00\x04\x22\xc8\xa2\x6a\x90\xd7\x11\xdf\x14\x07\x10\x7b\x50\x60\xb7\x29\x71\x08\xf0\x5b\xc8\xda\x28\x67\xec\x5d\x88\x69\x4a\xda\x68\x20\xe4\x9a\xe2\x36\x3b\xfe\xb5\xcd\x62\x53\xe2\x76\x1b\x7e\x6b\x07\x36\xc2\x35\xcc\xad\xe6\x90\xa4\x4a\x21\x7f\x48\x0a\x4b\x4b\xe0\xe5\x07\xe1\x52\x63\xcb\x41\x66\xc1\x41\xb8\xcc\xd8\x7c\xd0\xb8\x03\x5e\x06\x60\xef\x3d\xc6\x11\xb8\x06\x7c\x0d\x04\x50\x86\xcf\x90\x64\x38\x60\xc3\xd2\xb3\x10\x21\x70\x22\xfe\x4e\xb3\x92\x7f\x8e\x6d\xf1\x86\x02\x82\x65\x61\xeb\xd5\xb0\xd8\x7a\xd5\x2f\x8c\x23\x8f\xc3\x33\x03\xbd\x1f\xd1\xfc\xa7\x16\x3e\xc1\x5c\xca\xec\x00\x2c\x08\xe1\x7f\x47\x83\x76\x1d\xff\x9f\xa1\x06\xd6\xb4\x1a\x78\xa3\x21\x4b\x6d\x33\xe3\x6c\x86\x4f\x1c\x3b\x06\x20\xce\x85\xe0\x4a\x18\x03\x0e\x50\x0f\xfa\x92\xa0\x74\x2e\xe4\xcc\xc8\x85\x52\x29\x11\x25\x30\x33\x01\x4a\x27\x3f\xa9\xb4\x87\x9c\xab\xf7\x31\x00\xd8\xef\x88\x7e\xe6\x81\x38\xc0\x76\x0b\x89\x22\x70\x11\xf3\x30\x61\x18\x82\xb3\xd8\x5a\x58\xdd\xfd\x2e\x76\x06\x38\xb7\x19\xdd\x7b\x88\x9b\xc1\xbf\x49\x7a\x78\x63\x40\xdc\x8e\x0d\x5d\xb4\xeb\xd4\x6f\x06\x30\x51\x85\xf8\x48\x9a\xcb\xa5\x23\x97\xa8\xf9\x70\x7a\xe6\xd2\xb1\x63\xd4\x7c\x2e\x49\xd6\x38\x3b\xf6\x78\x01\x51\x92\x35\x01\x10\xbf\x26\xca\x40\x2d\x93\x44\x86\x4b\x19\x69\x8b\x4c\x8d\x93\x19\xfd\x28\x0c\xff\x06\x6e\x7e\xd8\xf8\x68\xdf\x2b\x6f\xc2\x48\x74\xdc\xb4\x5b\xe6\x0c\x1f\x31\xf5\x96\x79\xf0\x6d\x18\x86\xef\x81\x5e\xa3\xda\x78\xc3\x28\xfd\xe6\xdb\xaf\xda\x97\xbf\x03\x6f\xda\xb7\x74\xe1\x1f\x8c\x2b\x01\x04\x1d\x00\xb0\x9f\x12\xdd\x9e\x0d\xe2\x1c\x00\x0a\x62\x55\x42\x1a\x62\x54\xa2\xe6\x5c\x97\xc6\x7a\x74\xac\xe3\x24\xd2\x3e\x70\xf8\x25\x1a\x69\x39\x11\xf1\x9d\x3c\x62\x45\xc4\x74\xb2\x00\xf1\xf5\x50\x63\x78\x1a\xf4\x58\x4e\x92\x91\x25\x06\x34\xc8\x11\x83\x6b\x68\xc4\x2e\x38\xe4\x6d\x89\xba\xa1\xa5\x83\x69\x39\x6a\xec\x37\x0e\x24\xc3\xb5\xb6\x4b\xfe\xc8\xcd\x82\x73\x8e\xb5\xb2\xc3\xb7\xaf\xb7\x4e\x59\x8b\xf9\x7c\x00\x00\xae\x95\xdf\x0f\x0a\xc0\x19\x94\xcf\x5a\xbe\x83\x86\x1b\xcd\xca\x52\x8e\xf1\x5d\x9a\x2c\x52\x36\xc9\xbc\x24\x6b\xc1\x02\xcc\xa6\x7c\x6c\xdc\x30\x86\xac\x52\x9c\x77\xc8\xd8\x09\x7a\x68\x76\x1b\x8e\xc2\x94\x0b\xb3\x54\x8f\x80\x44\xd0\x6e\x68\xe1\xfd\x21\xb6\x51\x81\x1f\x24\x37\x4c\x1b\x3b\xfa\x96\x85\xb7\xff\xfc\x9f\x37\xee\xfb\xcb\xb4\x87\x9f\x31\xbe\x61\x86\xb6\xbc\x03\x9f\x78\xf0\xb7\xd3\x27\x9e\x79\xfa\x39\xfb\xaf\x38\xff\xa5\x5f\x2e\xde\xbb\xf7\xae\xbf\xd8\x8d\x6e\x00\x81\xbb\xf7\x10\x37\x95\xdf\x0f\xaa\xc1\x25\x20\x5e\x85\xcf\xc7\xd9\xf5\x78\x3e\x3e\x9f\x6c\xd7\x93\x0e\x7b\x55\x3e\x8e\x84\x82\x9e\xf0\x55\xe5\x5b\x15\x88\x6a\x48\x7a\x53\xee\xd2\x91\xa7\xac\x4b\xd2\x0a\x3d\x3a\xc9\x64\x3c\x16\x49\xd6\x4a\x4a\xf1\xc9\xed\x9c\x24\x6b\xb0\x3c\x16\xd3\x7c\x55\x92\xac\x79\x4a\x62\x31\x24\x4b\xa8\x30\x86\xf2\x65\xe4\x27\x79\x41\x09\x54\x9b\x5a\x9a\x87\x84\xc2\x51\xf2\xb5\x2a\x5c\x9e\x26\x45\xb0\xf8\x4b\xa0\xdf\x27\x70\xe1\x72\xf7\xf4\x97\xe6\x3e\xb0\xd3\x30\x36\xd6\x4f\x78\xbc\x73\xc6\x94\x9b\xee\x5e\x7d\xdd\xfb\x1b\xf7\xbd\xb7\xf7\x89\xb5\xeb\xef\x30\x0e\xfd\xe6\x1f\xc3\xa0\xa3\x49\x5d\xbd\x6c\xd7\x07\xd7\x5d\x7e\x7a\xeb\x82\x37\xce\x1a\xb5\xfb\xee\x7b\xfe\x58\x6c\x2d\xf8\xe5\x35\xeb\xfe\xb8\x1c\x30\xbd\x9f\x03\xc0\x4d\x25\xba\xe0\x05\xfb\x40\xdc\x86\xb5\xc1\xaa\x92\xfc\x3e\x69\x77\xd8\x18\x97\xa2\x71\x4e\x55\xd5\xec\x36\x1d\x59\x9a\x20\xf2\x45\x90\xad\x4b\xb3\xba\x74\xcd\x6f\x6a\xc7\xbd\x87\xf7\x50\xed\xb0\x89\xc8\xd3\xc9\x23\x2b\x4e\xc7\x12\x16\x2b\xce\xa2\x6c\x62\xc2\x6e\xf3\x78\x95\x84\x13\xbf\x3e\x3b\xe2\xb2\x7f\x7d\x0c\xfc\x8a\x23\xe1\x22\x3f\x74\xe3\xd7\xb8\xcb\xe6\xc1\xa5\x54\x58\x70\x4b\x72\x0c\xb9\x63\x20\xee\x72\x7b\x70\x96\xd5\xc1\x59\xec\x4e\xfa\xde\x4c\xad\xa0\x66\xb5\x49\x72\x9c\x11\x25\x9a\x17\xd8\xa9\xf8\x19\x09\x89\xb1\x86\x46\x36\x8a\x0b\x0f\x4b\x98\x0d\x79\x2b\x43\xd1\x11\x30\x1a\x16\x2c\xc1\x06\x96\x81\xd1\x17\x77\xaa\x3b\x47\x1a\x07\x47\x1a\xdd\x30\x7a\x8a\x73\xa8\xdb\x51\x7f\x16\x8c\x7c\xc9\xde\xdf\x7d\xc9\x3f\x8d\xb7\x60\xe4\x9f\x47\x4e\xf9\x53\x78\xda\x85\xc4\x17\x15\xf6\x1e\xe2\x16\xf1\x1d\xa0\x08\x9c\x4d\x2b\x13\x8d\x65\x75\x52\x62\x69\xa2\x43\x4f\x7a\x6d\x05\x2e\x97\xa2\x79\x6d\x7a\xdc\xe6\x25\xde\xd3\x81\x9d\x6b\x71\x04\x09\x5d\x5a\x9e\xa8\x6b\x25\x50\x01\x1a\x8b\xd3\x72\x10\x43\x36\x49\x83\x79\xb1\x18\xf2\xca\x9a\x53\x8a\xd1\x6c\xaf\x4f\x98\xde\x10\x1b\x62\x4d\x27\x84\x8d\xbb\xf0\xa9\xf8\x3d\x4f\xb5\x2f\x59\xb8\x74\xd1\x01\xe6\x9b\xa8\x11\x98\x39\x3e\xba\xe7\x4f\x9b\x8d\xaf\x9f\x5f\xbe\x7f\x38\x74\x5d\x78\xdb\xca\xb6\xb6\xd0\x14\xe6\x03\xe3\x98\x71\xd0\xf3\xfb\xa7\x1f\x3f\xb6\xbe\x1e\x30\x60\x66\xef\x21\x6e\x0d\xff\x26\x08\x82\x2a\x70\x2e\x88\x07\xf0\x89\x8b\xed\x7a\x9c\xc7\x27\xb6\x63\x7f\x53\x4d\xfc\x4d\x81\x4b\x47\x05\xa2\x56\x06\x15\xcd\xeb\xd2\xb5\x1a\xa8\x68\x65\x05\x92\x1c\x17\x03\x2e\x6c\x37\x5e\x49\xe3\x89\xe7\xb1\x17\x4b\x72\x02\x58\xbd\x61\x9c\x5c\xf0\x12\xb2\x90\xb4\xa1\x00\x56\xa8\x4d\x01\x0b\xb1\x27\x35\x23\x95\xa2\xfe\x88\xd0\xe3\x86\x33\xaf\x7d\x07\x0e\x3e\xb0\xea\x02\x75\xfa\xe2\x57\xbe\x19\x61\x6d\x7f\xe9\xfe\x5f\xdf\xf6\x8f\x07\xfe\xf4\x1e\xac\x9e\x7a\xfa\x85\xab\x4e\x1f\x7b\xea\x92\xd1\xf0\x9d\xd7\xe1\x5a\x58\xf8\x8b\xc2\xef\x82\x7f\xf9\xfc\xb1\x17\xd0\xaf\x8c\x0f\x6f\x33\xf6\xce\x5e\xb4\xf7\xb6\x33\xce\x39\xe3\x6a\xcc\xff\x29\x00\x70\xcf\xf3\x1d\x40\xc0\x39\x01\xf1\xb9\x38\xb0\x6b\x8c\x43\xc7\x71\x85\x44\x13\x8d\xa5\x71\xb7\xa1\x11\x3b\x98\x90\x05\x4e\x61\x3e\xee\xb9\x65\x28\x7b\xa0\xb6\x47\xe4\xe2\x90\x7b\xe1\xb8\x93\x76\xfd\xa2\xbd\x87\xb8\x85\xfc\x9b\x20\x00\xc2\xa0\x0e\x5c\x0d\xe2\x7e\xcc\x9d\x42\x8b\x99\x76\x29\x82\x0e\x51\x3d\xe1\x4e\xbe\x4b\x4f\x70\xf9\xc0\xaa\x68\x15\x2e\x1d\xe5\x8b\x58\x8c\x9a\xe4\xd2\x91\x24\x22\x27\x36\xe1\x1a\x97\x8e\x6a\x22\x9a\xd3\xa5\x6b\x11\xa8\x68\x15\xd8\x7c\x19\x7f\x2c\x86\x4a\xa4\x64\xa1\x35\x54\xa5\x60\x76\x49\x32\xf2\xc4\x80\xa6\x14\x4a\xf2\x6e\xc0\x39\xa5\x50\x15\xcd\xba\xc4\xca\xaa\xe6\x21\xd8\x74\x89\xd1\x5a\x88\x2f\xca\x64\x5e\x35\x4e\xba\x02\x94\x8d\x42\x14\xce\x79\xf4\xca\x3f\x6f\x5d\xf9\xcc\xfc\x5f\x6e\x7b\x7f\xf5\xdf\xef\xeb\xfa\x37\xac\x5d\x70\xce\xdc\x25\x13\xa6\x5f\xf9\x33\xb4\xf2\x99\x33\x47\x4e\x9a\x05\xdb\xe0\xa0\x1b\x7e\xfe\xf8\x8a\xe7\x16\x4d\xdf\x7e\xc1\x4d\xaf\x0e\xd9\xf4\xd1\xb5\xcf\x5f\xfa\xbb\xfd\x67\x9d\xbf\xf8\x9c\x09\xcb\x5b\xea\xae\x63\x2e\xfb\xf9\xd8\xf1\x77\x8e\x99\x32\x17\x30\x60\x46\xef\x21\x6e\x0c\xff\x26\xc8\xcf\xd0\x0f\xd6\xae\xc7\x45\xcc\x81\xb0\xa9\x1f\xce\x2e\x2d\xe8\xd2\x71\xb1\x9c\xa9\x1f\x41\xa7\x24\x6b\x6c\x20\x16\x43\x65\x52\xdc\x26\x0a\xc4\xe6\xd8\x00\x55\x6d\x5c\xd1\x38\xbd\x45\x84\x40\xaa\xd5\xd1\x30\xd6\x88\x66\x33\xd5\x26\xf1\xca\x8b\x29\x34\x1d\xb1\x1b\xce\x58\x7a\xe5\x53\x07\x47\x58\x97\x3e\xfd\x70\xe2\xf6\xef\x1e\xde\xff\xf6\x2b\x46\xc7\xd7\x37\xfc\x75\xe2\x98\x53\x2f\x1e\x7e\xc6\xc4\x51\x17\x45\x9d\x10\xd4\xbe\xf1\xaf\x07\x0e\x74\x3c\x06\x03\x1b\xbe\xfb\xda\xf8\xc2\x10\xfe\xce\x26\xcf\x3d\x6f\xc2\xea\xf3\xa7\x5f\x3a\xfd\x17\xb4\xdf\x1b\xec\xfd\x94\x69\xe4\xda\x81\x03\x04\xc0\x99\x20\xee\x81\x40\x49\xfa\x49\xb0\xcf\x6c\x81\xe4\x67\x84\xfd\x84\x53\x00\x56\x25\x29\xd3\xe0\x1f\x84\x8a\xe6\xc4\x61\xc3\x16\x43\x82\xa4\xb1\x58\x86\x32\x91\x5b\x76\x4a\xe0\xcd\x95\x1e\x74\x2c\x6d\x1b\x73\xd6\x92\x59\xe3\xcf\x4e\xe5\x09\xec\x75\x73\x16\x4f\x1e\x3b\xe3\xb2\x09\xf8\x6c\x38\x1f\x22\x67\x13\x80\x0c\x06\x83\xb8\x1d\x9f\x4d\x34\x4f\xe4\xc5\x21\x21\xe9\xa2\x87\xc0\x51\xdf\x85\x83\x01\xcb\xc5\x62\x7d\xd9\x51\xe6\x67\xa6\x32\xa5\xe9\xa9\x8f\x4c\xa5\x4c\x5c\xb2\xef\x23\x49\x1e\xb8\x9f\xab\xe4\x01\x10\x00\xf0\x36\x43\xbf\x0d\xfa\x97\xb0\x4f\xf7\xac\x62\xd6\x32\x6b\x36\xc3\x7f\xfe\xd3\x78\xd1\xf8\xfc\x1f\x98\x6f\x4b\xe0\x0e\xae\x92\x03\xa4\x7f\x53\x40\xb3\x2c\x5e\x27\x99\x0c\xaf\x67\xf4\x6e\xbc\xcd\x21\x3f\x6c\x0e\xe1\x7f\xa4\x7b\x3c\xfb\x34\xdc\x71\xf0\x20\x5c\xf7\xfe\xfb\x27\x7c\x56\xb4\xd9\x06\x9b\xa1\x7f\x09\xb3\xb6\x67\x15\xfb\xf4\xfe\x7f\xc0\x20\x1c\xfe\x4f\x43\xdc\x4c\x64\xf4\x58\xef\xa7\xec\xd7\xfc\x7e\xe0\x00\x15\x60\x15\x88\xbb\xb1\xaa\x85\xec\x7a\x9f\x80\x50\x45\x04\xa2\xca\x0c\x19\xa1\xfc\x26\x24\x88\xc9\xa0\x0b\x94\x72\x0a\x0a\x46\x90\x20\x6a\xa5\xd4\x04\xb5\x2a\xac\x8a\x80\xb4\xad\x90\x20\x25\x58\x5b\x51\x05\x36\xb6\x52\x39\xe1\xf6\xe7\x85\x48\xb5\x53\xc1\x4a\x72\xdc\x9f\x5f\x8a\x3d\x59\x48\x42\x52\x0c\xb9\x4f\xec\x72\x79\x5b\x52\x69\x80\x1b\x5a\x42\x23\x60\x94\xd6\x80\x82\xe5\xb1\xcb\xcf\x1f\x73\xd6\xe5\x33\x5b\xa7\x39\x3f\x7b\x57\xfb\x7d\xec\xb2\x9b\xdb\xc6\xfb\x0d\xa3\xf0\xca\xe5\xd7\x9d\xbe\xae\x69\xd9\x96\xf6\xd9\x8b\xb1\xac\x27\xf1\xc5\xab\xfe\xe7\xfe\xb3\xd7\x2d\x9b\x3d\x72\xfe\x8c\xdb\x9f\x39\x73\xfa\x8c\xe6\x15\x65\x63\x08\xbd\x73\x7a\xc7\x09\x2f\xf3\x1d\x60\x28\x18\x03\xbe\xa6\xd5\x82\x56\xe3\xd4\x51\x73\x44\x8b\x38\x75\x24\x47\x90\x43\x4d\x9e\xea\x04\x43\x39\x05\x85\x9a\xd0\xa8\x48\x32\x48\xbe\x81\x68\x2c\xe1\xc1\x60\x9a\x91\x0f\x16\x71\x4c\x4d\xc6\xe8\x77\x31\x51\xab\xa4\xb5\xb3\xc4\x29\xda\x38\x33\xd8\xba\xff\x79\x2e\x0d\xb6\xc3\x45\x34\xb2\x53\x2b\xe1\x8f\xa2\xc2\xce\x44\x51\x49\xa1\x57\x49\x14\xe3\x57\x34\x5c\x4c\x8c\x18\x3e\xd2\xab\xc4\x47\x0c\x1f\xd9\x17\x57\xe3\xc5\x25\x85\x38\xbc\x16\xc5\xc0\xee\xc2\xa2\x11\x23\x8b\x4b\x68\x50\x85\x59\xdf\x91\x10\x5b\x19\x93\xe4\x3d\x0e\x39\xc8\xd5\x44\x9a\x9a\x09\x7b\xe5\x88\x24\xa3\xa6\x18\x3a\x55\x42\xee\x18\x1a\x25\x27\x2d\xc0\x5f\x39\xd8\xf4\x6d\x72\x45\xa8\x0c\x48\x34\x1c\x54\x87\x89\x63\xa3\x3e\x20\xc0\xba\xa1\xdf\x97\xb6\x7f\x8e\xf1\xfb\x00\x76\x13\x7e\x21\x5c\x5e\xc1\x10\xe7\xe7\x8d\x12\xc7\x30\xe7\x5f\xf0\x37\xd0\x0b\x47\xc0\x4b\x6f\xf8\x64\xd3\xcc\x65\xa2\x7d\xc8\x75\x53\x57\xdf\xb6\xfe\x9f\x77\x3c\x73\xdb\xa5\x0e\xf1\x94\xd1\x57\x8e\xfd\xcf\xa1\xfd\xc6\x33\x7b\xa0\xf3\xf0\xf2\x37\x57\x7c\xf6\xf7\xf7\x8d\x7d\x3b\x99\x25\x8d\x75\x9b\xc6\xc7\x2a\xea\xa7\xad\x9e\x00\xbf\x85\x01\x98\xfc\x8f\xf1\x8c\xf1\xfe\x93\xc6\x7b\x8f\x4d\x1e\x37\xf5\xf4\x07\xb7\x6d\x85\xec\x5d\x51\x63\xce\xe0\x51\x65\x63\x6e\xe8\x5a\xfc\xce\xc7\x7b\x8d\x27\xfe\xfc\x8d\xf1\x55\x4d\xfd\xb3\xb3\x7e\x0d\x87\x7e\x3a\xaa\x15\xba\xff\x62\xbf\xf8\xd7\xd8\x6e\xd7\x01\xc0\xdd\xc2\xef\x05\x16\xe0\x01\xc3\x68\xd4\x49\x65\xc4\x49\xc1\x0a\xa0\x4b\xd1\x04\x1c\x7f\x44\x9a\x19\xbb\x74\xd2\x55\x25\x19\x2f\x83\x33\x5e\xab\xd9\x53\x0d\xe3\x70\xc4\x86\x58\x18\x62\x23\x30\x2c\x58\x56\x32\x06\x5c\xbe\xd5\x78\x37\xdf\xa8\xde\x05\x6b\xe1\xe4\x02\x9e\xe5\x5b\x86\xf0\x7b\x8f\x8d\x81\x73\x8c\x47\x98\x79\xb0\x6d\xdd\x7d\x5b\x17\xd3\x58\xd5\x0c\x00\xf7\x09\xdf\x01\x3c\x20\x00\x4a\xc1\x83\x20\xee\xc1\xa7\x00\xaa\x26\xb2\x3a\xed\xb6\x42\x55\x2b\x65\xf5\x64\x7e\xc0\x83\x93\xb2\x7c\xec\xba\xcb\x22\xc8\xd7\xa5\x39\x45\x1d\x15\xe1\x20\xc5\x8b\x7a\xaa\x9d\x39\x62\xcb\xe1\x0d\xa4\x0f\x06\xea\x51\x69\x3d\x02\xa2\x26\xfa\x8f\xa2\x52\x51\x83\xfe\xa3\x48\x14\x13\x01\xb1\xd4\xab\x24\xf2\xf1\x2b\xbb\x1b\x40\x31\x90\x5f\xda\xd7\xc0\x2a\xf2\x49\xb2\x66\xb3\xa6\x0a\x11\x6c\x78\xf9\x12\xf9\x01\x2a\x4d\x07\xde\x8c\x3c\x94\x0b\xb1\x24\x90\x29\x30\x6a\x7e\x6d\x86\xcd\x70\xe7\xa7\x5f\x3e\x76\xf7\x82\x15\xc6\xef\x8d\xc3\x0f\x27\x97\xaf\xdb\xf3\xa8\x7a\xe7\x35\xd7\xec\xdc\xce\x77\x3c\xbc\x63\xdb\xf3\x65\xd6\x82\x4d\x97\x7f\x7a\x04\x82\x2b\x2f\xde\xf1\xdd\xfc\xd9\x1b\x88\x7f\x59\xd9\x7b\x88\x8f\x92\x5c\x66\xac\x19\xa9\x64\x87\x59\x39\x39\x58\x3d\x61\x0d\x70\x38\xb9\x2e\x20\x11\xdb\x23\xea\x5a\x21\x4e\x06\x64\x1c\x90\xfc\xa4\x06\x00\x1e\x5f\x2c\x16\xd3\x38\x07\x29\x45\xa8\x72\xaa\x4d\x79\x01\x4b\x3d\xc4\xe5\x92\x9f\x74\x38\x24\x21\x5c\x0e\x56\xfe\x01\xce\xf9\xeb\xaa\x17\x96\x5e\x75\xe9\xc6\x31\x3f\x7f\xfb\x86\x0d\xdb\x6e\xef\x7c\xf5\x35\xc3\xf8\x8c\xa9\x85\x02\x7c\xe6\xd3\xba\x53\x8f\x0d\xab\xda\x61\xbc\x94\x7c\x7c\xc7\x64\xa3\x7b\x32\x54\x68\xec\x69\x06\x80\x57\xf8\x0e\x60\x03\x5e\x30\xcf\xcc\x95\x81\xaa\xd9\x33\x24\xe4\xc5\xf5\x8a\x2f\x82\x3c\x5d\x44\x1a\xfd\x72\x64\x2c\x0d\x2f\x91\x86\x9d\x3b\x8a\xbc\xa2\x06\xb9\xa3\x6c\x02\x40\xbb\xd7\x64\x3d\xd0\xbc\xf6\xbe\xdc\xa6\x0c\x90\xb2\x8f\x35\x4b\x3e\xca\xd6\x5b\xa1\x1b\x56\xbf\x64\x6c\xea\x9e\x73\xe9\x1d\x7f\xbe\x6e\xcb\xcd\xed\x7c\x87\xf1\x57\xe3\xdf\xc6\x17\xc6\x85\xef\x41\xb0\x1d\x56\xef\xbb\xe7\x97\x00\x12\x7d\xba\x8f\xf4\x46\x2e\x31\x6b\x2a\x1b\xab\x13\x95\xd6\x38\x56\x4f\xf2\x54\xad\x79\x7c\x5c\x67\x04\x97\xc4\xe4\x9c\x8f\x1d\x3e\x94\x3a\x27\x47\xce\x69\xe3\x8e\x22\x8e\x9c\x13\xe7\xf2\xbc\x8d\xf3\x2a\x09\x2b\x7e\xc5\x5a\xc3\xf1\x56\x5b\x5a\x6b\x00\x39\xb2\x25\xc4\x92\xff\xd9\x66\xd8\xcc\x36\xb5\x18\xe0\x74\xf8\x41\xd4\x08\x4f\x65\x40\x0b\xdf\x61\x18\xbf\x35\x8c\xf5\xbd\x44\xd6\xf8\x7c\xdb\x09\x2f\xe7\x99\x16\x67\x53\xfb\x8e\x67\xe5\xc9\xf1\x48\xf5\x67\x27\xf2\xb6\x79\x74\xcd\x61\x9e\xf2\x91\xc3\x9f\xd0\x53\x8a\x08\x76\xe2\xb2\x83\xeb\xcc\x3a\x5a\x02\x9f\x2c\xd7\xb1\xf0\xa1\xea\x5b\x0c\xee\x4c\xf8\xfe\x50\xa3\xfa\x1a\x7c\xa2\xf5\x3d\x3d\xfb\x52\xba\xb7\x84\x7f\x13\x14\x83\x29\x20\x5e\x88\xf9\x25\xa5\x74\xcf\xee\xd0\x93\xfe\xbc\x42\xce\xa5\x68\x7e\x56\x4f\x58\x0a\x89\x1a\x96\x90\x63\xb9\x45\x1d\x07\x2a\xa0\xf9\x25\x92\x17\x69\x96\x42\x49\x46\xee\x98\xc6\x61\x39\x0a\x29\x0f\xd9\x94\xad\x83\x5e\xec\x27\xdc\x30\x5c\x06\x56\xbe\x0d\x6f\x84\xec\xff\x76\xb6\xb7\xde\x71\xee\xdd\xff\xda\xb0\x65\xdb\xa4\xb6\xd1\xc6\xbf\x87\x32\xea\x8e\x9b\x3e\xbd\xc1\xe8\x31\x3e\x63\x2a\xa1\x1d\xa2\xaf\x2f\x3c\x5e\xd3\xf0\x98\xf1\xa6\xb6\xeb\x97\xf9\x50\x81\x4c\x8f\x50\x1f\x82\x55\x26\x1f\xf9\x47\x88\x9c\x1f\x32\xf3\x65\x8b\xd5\xa1\xaa\x94\x97\x71\x86\x17\x54\x55\x4d\xb2\x76\xcc\x4e\x64\x53\x71\x31\x83\xb8\x26\xb3\x2f\xa2\x39\x3c\x3a\x72\x88\x1a\x74\x28\x1a\xe3\xd1\x11\x23\xe2\xfc\x5a\xb3\x78\x74\x64\x11\x35\xde\xa1\x68\x82\x47\x4f\xeb\x86\xd9\x05\xc0\x6f\x5e\x35\x5b\xec\x09\xd6\xc1\x78\x15\x64\x15\x13\x9c\x95\xf7\x2a\x09\x1b\x7e\xc5\x3f\xb7\xe3\x9f\xb3\x09\x96\xb3\xd9\xb3\xe4\xc0\x86\xbc\x21\xe2\x24\xb1\x26\x37\x5d\x03\xdf\xbd\x06\x36\x1a\xfb\x8d\xdf\xdf\x64\xd4\xde\xc4\x77\xf4\xbc\xc8\x0c\x3f\xd6\xca\xac\xe8\xd9\x40\xfb\x2f\x2f\x03\xc0\xae\x21\xb4\x8d\x37\x69\xe3\xcd\x26\x5f\xfa\x50\xf7\x1c\x4e\xd0\x78\xc8\x88\x88\xed\x24\xea\x6a\xed\x04\x09\x86\xa5\x9a\x09\xd3\xef\x70\x68\x03\x0d\x8d\xe1\x91\xd0\x5b\x1d\x0d\x79\x20\x1b\xb0\x0c\xab\x78\xee\xb5\xed\x95\xcc\xfa\xca\x7d\xaf\xdd\x57\x89\xa6\xb1\xf1\x69\x08\x4d\xeb\x9e\x32\x0d\x01\x00\x8d\x7d\xc6\x34\x26\xce\x77\x00\x17\x38\x0f\xc4\x05\x6c\xdd\x16\x15\x39\x22\xb4\x10\x71\x93\x72\xcf\xe2\xd1\x35\x4f\xda\xc0\x77\xd3\x73\x08\x22\xe2\x3b\x91\x45\xc4\xc7\xd0\xb0\x16\x42\xf2\x4a\x3e\x5e\x63\xb0\x67\x72\xe1\x34\x06\x81\x58\x43\x23\x4f\xd2\x66\x18\x82\x38\x6a\x56\x1b\xfb\x66\x4e\xba\x70\x65\x11\xac\x84\x8d\xc6\x5b\x43\xfe\xf3\x61\xdb\xdc\x6d\xbe\x6b\xd6\xf2\x0b\x8e\x2d\xfb\xf7\x47\x85\x20\x53\xd6\x4e\xb0\xde\xb4\x69\xab\xd3\x94\xb4\xc6\xf0\xaa\x0a\x91\x8b\x88\xd5\xe9\xd1\x91\x33\x2d\x56\xcd\x9d\x36\xee\xbf\x53\x01\xde\x77\xf8\x59\x5c\x85\x23\xa7\x98\x60\x9d\x8c\x57\x49\x38\xf0\x6b\xdc\xe1\x64\x32\x0a\x71\x16\x27\xfb\x0e\x7c\x7e\xfc\x4a\x32\x03\xc6\x49\x7b\xa9\x1a\x04\x66\x8f\x07\x8b\x34\x0a\x43\x36\x18\x62\x2d\x54\xa6\xf7\xdc\x07\xef\x87\x97\xf4\x3c\x05\xc3\xc6\x53\x6f\xaf\x5a\xc2\x77\xf4\x8c\x78\x0b\xfe\xab\x67\x4c\x8f\xc0\x4c\x1d\xd7\xf3\x5d\x8a\x0e\x16\xfb\x26\x1e\xfb\x79\x90\xaa\xb1\xd3\x0d\x28\x21\x82\x60\x17\x39\xb9\x25\x5b\xf5\x10\x14\x11\xe8\xa4\xa2\x66\x35\xc0\x66\x28\x16\x34\x55\xaa\x17\x10\x4f\x73\xbc\xb5\xd7\xdc\xff\x68\x06\xc0\xe2\xe3\x3b\x80\x17\x3c\x9d\xb6\x0f\xb7\x9a\xe6\x9a\x80\xb9\xe6\x23\x5c\xf3\xba\x74\xec\x92\x89\x05\xf4\xb5\x37\x3a\x8b\xbb\x55\xf2\xd9\xee\x7a\x37\xf2\x74\x6a\xac\xf5\x28\x8f\x98\x4e\xec\x84\x3e\xa2\x12\xb7\x8a\xc8\xd1\xc9\x63\x91\x0b\x9d\xcf\x8e\x68\x3f\x0c\x08\x6f\xad\x62\xc2\x66\x75\x78\x95\xb8\xcd\xea\xe8\xe3\x2a\x48\xb0\x36\x07\x69\x68\xc0\x0e\x86\x15\x6c\x8e\x7e\xdd\x0d\xaf\x24\xc7\x21\x47\x2a\x72\x8b\xa4\xf1\x4e\x52\x1d\xe0\x2a\x97\x90\xe8\x6d\xf1\x86\x61\x88\x0d\x0b\x0e\x12\x09\xee\x18\x65\x63\x2a\xe1\xe3\xc6\x7e\xe3\x8b\x2d\x15\x13\x6c\x3d\xaf\x1a\x9f\x0f\xb7\xe6\x0d\xdd\xcc\x77\x1c\x7f\x8e\x1b\x7b\xac\x95\x49\xfe\x0a\x8a\xc7\xb7\x72\x4b\x3a\x8c\x7f\xf5\xcc\xa4\xbc\x10\x30\x2f\x44\x70\x93\xc9\x77\xbb\x98\xe6\x84\x05\x73\x42\x22\x9c\x10\x5d\x3a\x12\x45\xcc\x7d\xd2\xe8\x91\x4d\x29\x3c\x74\xf8\xcd\x3e\xb7\xeb\x46\xa2\x88\x3c\x9d\xcf\xbe\x70\xe4\xd0\x5e\xfc\x53\x1e\xd9\xeb\xdd\xc8\xd1\xa9\xb1\xf9\x84\x41\x2c\x88\xb3\x84\x52\xb8\x1b\x32\xac\xdd\xe1\xe9\x4b\x2f\x2c\x22\x29\xbf\x4c\xc1\xa9\x2d\x51\xec\x13\x60\xd8\x22\x50\x15\xba\x08\x4e\xb7\x86\x43\x5b\xa1\x6c\xec\x37\x76\x1a\xf7\xd9\xad\x85\xa5\x5b\xf8\x8e\xe3\xfb\x3f\xdc\xc1\x24\x8f\xb5\x72\xd3\x86\x75\x6d\xe9\x99\x4a\xe2\x31\xf6\xd9\xdb\xf9\x37\x81\x0b\x14\x82\x31\x20\xee\xc8\xf2\xda\xf9\x38\x76\x14\xa5\x9c\x34\x72\x93\xe4\x5a\xb3\x88\xba\x56\x0c\x15\xcd\xef\x96\x64\x8d\x73\x90\x26\xa2\x24\xc9\x9a\x25\xd5\x6b\xad\x50\xcd\xa8\x5b\x06\x60\x56\xb3\x75\xe5\x2b\x70\xce\xdf\x40\x2f\xcc\x7f\xc5\x78\xe2\xa3\x5e\x60\x7c\x0c\xa3\xeb\xae\xb9\xe6\xd5\x2b\x6e\xbc\xea\x9a\xd7\xdb\x99\x20\xb4\xc1\xdf\x7c\x6d\x7c\x64\xf4\x18\x9f\x1a\xa3\xfe\x06\xab\xa1\xb0\x75\xdb\x53\x70\xc4\x2b\xb7\xdd\xbb\xc7\xe8\xa4\xb9\x03\x77\xc8\xec\xb3\x5d\x65\x46\x3c\xbb\x9a\x99\x37\x24\x6d\x0e\x80\x33\x3b\x9b\x99\x42\x80\x2e\xcd\xee\xd1\x91\x5d\xc4\x4e\x46\xe3\x3d\x7d\xd9\xc4\xc3\x87\x3f\xcc\x88\x7f\x76\x11\x79\x3b\x13\x36\xbb\x17\x1b\x32\x7e\x65\x13\xd0\xe6\xc8\xc8\x28\x1c\x52\x56\xd2\x06\x42\x61\xd6\x4b\x1b\x0f\x34\xa3\xd8\x7e\xf8\x88\xf1\xa4\xd1\x75\xdf\x92\x47\x56\xdd\xf6\xf0\xfc\xf9\xbf\xe0\x3b\xba\xfe\xf4\x2f\xe3\xab\x9e\x23\xac\xb0\xf1\xca\xb9\xe7\xd2\xdc\x67\xa5\xf1\x08\xe1\xb5\x08\x4a\x40\x1b\x9d\x0c\x6a\x3e\x87\x1e\x77\xfb\xec\x4a\xe2\x34\xb7\xd3\x66\x8e\x06\x0b\xf1\xe9\x4b\xc9\xe9\x25\x51\x47\x92\xa8\xe5\x9b\x6c\x2f\x83\x0a\xe1\x75\x82\x73\xba\xec\xb8\x82\xb3\x48\xc8\x11\x03\x9a\xcf\x4d\x9c\x09\x2a\x94\x4e\x90\x82\xc5\x1b\x62\x07\x16\xc4\xbf\xff\x64\x18\x77\xc7\x0b\x4e\x26\x8b\x97\x8c\xd0\x05\xc6\x0a\x38\x3e\xb7\x3c\x76\x11\xff\x9e\x97\x8a\x9c\x9a\xcd\xa5\xf6\x49\x24\x0f\x13\x12\xa0\xbd\x7a\x0f\xe9\xd5\xcb\x58\x0c\xa2\x8e\x09\xca\xf2\x4a\x54\x0c\x2e\x11\xe5\x75\x62\xdf\xfa\x1c\xe9\x70\x3a\x5d\x79\x5e\x25\xe1\xc6\xaf\x71\xa7\x2b\x2f\xbb\xc3\xa9\x39\xdd\x38\x36\x41\xa7\x3b\x2f\x6d\xfb\xb2\x4b\x92\x35\xab\x3d\x46\xba\x6e\xb6\x18\xd0\xf2\x80\x24\x6b\xbc\x23\x96\x99\x6e\x63\xeb\xcf\x16\xde\xc5\x5f\x7d\xfd\xd8\x7d\x90\x37\x92\x07\x56\xac\xd8\x35\x65\xed\xed\xe7\x2f\x6c\xe5\x3b\xde\x78\xf9\x81\x4f\xa2\x3d\x5b\x99\xc6\x9e\x03\x6c\xdd\xcf\x96\x4f\x9b\x66\xce\x59\xc8\x6c\x62\x3f\x08\x83\xf9\x20\x5e\x9e\xf2\xbb\x12\x16\x1b\xa1\xb6\x22\x82\x5c\x5d\x5a\x50\x24\x9d\x20\x01\x2a\x5a\xa9\xa8\xe3\x22\x54\x0b\xba\x24\x39\x6e\x67\xcb\x71\x76\x5d\x2a\x48\x72\x5c\xca\x2b\xa2\xdd\xa0\x72\xda\x0d\xca\x93\x12\xd0\xe5\x2b\x35\x9b\x60\xde\x8c\x4e\x67\x3d\xac\xae\x87\xb4\xfb\x45\xfb\x87\x7e\x5f\x5e\x80\x14\x0d\xe1\xf2\xda\xe7\x1f\xbd\xe2\xfa\xc2\xa6\x0b\x37\x5e\x71\xdd\xa7\x77\xbe\x9f\x5c\x72\xdf\xcf\xcf\xbe\x74\x74\xfb\x35\x57\x1b\xef\xf5\x7c\x30\x0e\xca\x97\x9d\xd3\xaa\x8c\x1a\xda\x7a\xe1\x0b\x57\xac\xd9\xbf\xec\x42\xbd\x75\x56\xeb\xf0\xd9\x13\xa7\x3e\xbf\xe6\xad\x6f\x00\x04\x4f\x00\xc0\xbd\xc5\x77\x00\x0b\x68\x05\x71\x01\x90\x6d\x14\xea\xc9\x00\xab\x6b\x9c\xa5\x89\x6c\xa4\xe0\x30\x8d\x2d\xc7\x66\x8a\xec\xc1\xc3\xaf\x13\x91\x09\x22\xb2\x74\x22\x1e\x67\x8e\xac\xc6\x59\x52\x81\xa4\x10\x67\x28\x6c\xc8\xfb\x44\x94\x3d\x1c\x35\x1e\x34\x8c\x03\x06\x97\x84\x8c\x61\x1c\x9f\xc4\x25\x29\x0f\x37\xf5\x1e\xe2\xef\xe1\x3b\x80\x0f\x5b\xb1\x4c\xb4\xc6\xa1\xd3\x1e\xa5\xcb\x8d\x5d\xa8\x9f\xa8\x8c\xc5\xa3\x27\x58\x0b\xb0\x2a\x1a\x47\xb3\x29\x17\x54\x34\xb7\x47\x27\xdb\x28\xf8\x24\xf7\x1f\x7e\x9e\x86\x0f\x97\x88\x9c\x9d\xc8\x8d\x9d\x29\xd0\x9c\x1e\x1c\x70\xf1\x2b\xd1\x09\xce\x82\x0b\x31\x99\x70\xda\x46\x38\xdd\xd0\xe8\x1d\x12\xf5\x86\x58\x01\x57\xd6\xd8\x73\xb2\x0c\x08\x95\x57\x6d\xf2\xbc\x04\x1b\x5f\x90\x7e\xb3\xf2\x17\x65\x2f\xc0\xa6\xd7\x62\xc6\x3e\xc3\xf8\xd3\x37\x70\xcb\xf8\xd1\xec\xbd\xdd\x97\xb4\xaa\xf1\xbb\xb7\xb3\x77\x76\x4f\x31\xbe\x33\x0e\x7f\x42\xe9\x78\x1a\x00\x7e\x19\xdf\x01\xdc\xa0\xc1\x9c\xf3\x03\xac\xf8\x0e\x15\x22\x0f\xa1\x00\xba\x74\x4d\x84\x0a\x8d\xf5\x58\x67\x81\x3b\x95\xd1\x86\xbc\x01\xbf\xcf\xa2\x46\x49\xee\x12\x7a\x1a\x56\xab\x0c\x67\x2b\x54\x4b\x20\x82\xa7\xf6\xf8\x8c\x38\xdf\xd1\xfd\x8b\xe6\xd3\xda\xd5\x29\x77\xc4\xd8\x2b\x8e\xb5\xa6\x3e\xcf\xf2\x39\xdf\x01\x4a\xc0\x65\x20\x5e\x82\xe5\xe5\x53\xc9\x47\x6a\x76\x19\xb3\xad\x34\xf5\xa1\x08\x8a\xc9\x12\xba\x22\x50\x12\x41\x90\xec\xef\x24\x9d\x74\x4b\x00\xbb\x10\x58\x22\xc9\x71\x8e\x17\x70\x8c\xcc\x93\xe2\xf6\x82\x62\xfc\xce\x29\xc7\x1d\x1e\x3f\xd1\x49\x80\xff\x00\xef\x0e\xc6\x62\xf4\xac\x3e\xc1\xa2\x8e\x80\x51\x18\xf2\xfa\x2c\x2a\x3d\x32\x5b\x3d\x24\x1a\xc6\xd6\xf4\x34\x2c\x15\xac\x82\x35\x74\x96\x03\x2e\x83\x6e\xbf\xcd\xda\x3c\x09\xb6\xc2\xe6\x9e\x6b\x8c\xc7\xf2\x18\xc1\x3a\x64\xb8\xb1\xd7\x78\x8a\xef\xe8\xfe\xeb\x90\xc3\xcd\x73\xff\x18\x60\xd5\xee\xbb\x6e\xbf\xfe\xc1\x7d\x6c\xd1\xb1\x56\xe6\xad\x65\x6d\xb3\x1e\xbe\xb9\xa7\x91\xe6\xaa\xb7\x00\xc0\x5f\x43\x72\xd5\x69\xa6\x77\x37\xa7\x28\x88\x57\x49\xba\xcd\x74\x69\xac\xa8\x23\x56\xc4\xca\xa8\x59\x45\x92\x58\x93\x56\xb6\x06\x1d\x31\x32\x2b\xe0\xb0\xf5\x5b\x65\x8d\xb7\x60\x3a\x18\x60\x8e\x03\x1b\x1a\xc3\x90\x0d\x79\x69\x9a\x05\x97\x33\xa7\x7d\x0d\x4f\xbb\x1b\x2e\x86\x33\x7b\x3e\x84\x4e\x63\xf7\x2e\xe3\x4a\xa6\x9b\x79\xb6\xe7\x18\x23\xf4\x28\x3d\xa5\x4c\x69\xcf\xc7\x00\x82\x67\x01\xe0\x47\xf2\x1d\xc0\x0a\x2e\x06\x71\x0b\x3e\x8f\x40\xf9\x8d\x58\x15\x22\x1b\x19\x50\x09\x2e\x1d\x5b\x02\x2c\xeb\x92\x52\xeb\x06\x50\xd4\x35\xbb\xa9\xa2\x77\x1f\x7e\x92\xaa\x28\xc9\x66\x69\x66\x7b\x62\x4e\x0b\x2c\xa4\x0d\x42\x58\x0d\x43\xf8\xa0\xcf\xc2\xa1\x6b\xe0\x55\x70\x46\xcf\xb6\x15\xc6\x5b\x2b\xf8\x8e\x1e\xc4\x4c\xed\xbe\xa6\xe7\x2d\x26\x02\x60\xef\x8b\x00\x70\x88\xd4\x7d\xf5\xa6\xd7\xb5\xb0\x66\xc4\x66\x69\xb5\x87\xcb\x3c\x40\xe7\xf6\x30\xa6\x71\xac\xa9\x75\xe1\x28\x6d\xf6\x87\xd8\xe1\x55\xac\xad\xe7\xe3\x66\xf6\x89\xda\xee\xc3\xcc\xf4\xe6\xd7\xd8\xaf\x20\x78\xbd\xdb\x47\xea\xca\xde\x83\xc6\x5e\xb6\x91\xf8\x85\x49\xc0\xac\x27\x79\x9d\x4c\xa4\xd5\xcc\x56\x27\x21\xf0\xae\xc3\x8f\x65\x57\xbb\x7c\x90\x56\xbb\x41\x52\x95\x73\x7c\x5f\xed\xc2\xc2\x90\x25\x0c\x55\x4b\x25\x5c\x05\xdf\xaf\x7b\xd7\xf8\xe0\xdd\x3a\x63\xaf\x70\xec\xed\x63\xbb\xde\xa6\xf6\xf4\x01\x00\xcc\xf3\x64\x56\x3c\x05\xc4\x59\x40\x52\x59\xca\x6f\xa8\x92\x41\x36\xdb\x95\x64\xc8\xea\x40\x02\x32\xac\x55\x49\x02\xda\xeb\x04\x91\x24\x24\xef\x34\xde\x4c\x38\xe3\xdf\xdd\x8b\x4f\xc5\x42\xfa\xc9\xb8\x56\xfc\x00\x72\x1f\x19\xff\xa6\x23\x66\x00\x7b\x57\x18\x7b\x99\xfd\x84\xc6\x73\x00\x29\x89\x90\xa0\x12\x32\xd9\xa6\x8c\x55\x00\xa6\x29\x27\xb1\x4c\x3d\x12\xea\x71\xa9\x67\x09\x1e\x45\x82\xa8\xb1\x98\x58\x86\x15\x2c\x19\xc4\x46\x55\x18\x8e\x86\xe0\x86\xba\x77\x60\xf8\xdd\x3a\xf8\xbe\xb1\xd6\xd8\xfb\x36\x3f\xfd\xed\xa3\xe4\x66\x26\x08\x33\x56\xae\x99\xdf\x07\x84\x14\x8f\x49\xda\x6e\x89\x20\xae\x2b\xc9\xd2\x7e\xa5\x95\x7e\xea\x0b\xad\xff\xb0\x99\x9f\xca\x21\xb6\xd3\xad\xf1\x05\x47\x39\xc4\x75\x32\x71\x96\x70\x37\x3d\x3f\xc6\xb5\x99\x17\xaa\x30\xcc\xc2\x30\x73\xe9\x1d\xd0\xf7\xe1\x53\xc6\x52\xc6\xca\x76\x74\xb7\x32\xd7\xf4\xac\xa7\x36\x36\xce\xd8\xcb\xdc\xd3\x3b\x1e\xb0\xa0\x98\xec\x1b\x40\x27\x70\x72\x8a\xf9\x25\x63\x2c\xcf\x46\x43\x96\x67\x4b\xd8\x96\x52\x63\xef\xad\xb7\x02\x08\xbb\xb9\xf7\xd9\xc7\x84\x10\xb0\xe2\xbf\x27\x44\x34\x86\xd3\x89\x09\xd0\x25\x05\x3b\xa7\x60\x95\x07\x0d\x8d\xb0\x39\x94\x17\xf0\x87\xeb\x21\xec\x86\xd1\x8a\x33\x9f\x3e\x63\xbd\xe0\xf4\xdf\x71\x6f\x70\xec\xaf\x68\x0e\x34\xab\xf7\x10\xf7\x00\xd7\x0e\x64\x50\x06\x46\x80\xb8\x13\x7b\x4d\x0f\x7e\xb1\x41\xa0\xc4\x39\x08\x14\xad\xd8\xa6\x43\x14\xa2\xf5\x84\x47\xd7\xca\xb1\x2a\x17\x3b\x25\x39\x01\x5c\xee\x3c\x1c\x1e\x6d\xa9\x91\x1a\x19\x93\x04\xd4\xa8\xca\x86\xe9\xe4\xa4\x32\x6b\x58\x32\xeb\x17\x5f\xde\x3a\x7f\x53\xb5\x35\xf6\xc5\xd7\x1f\xbb\xad\x37\x3d\xb3\xf5\x57\xb0\xf1\xf4\x11\x63\x6f\x98\x32\x79\xe4\x98\x95\x13\xe0\x9a\x57\xe0\xc5\x2f\x4f\x9f\xba\xf9\xf8\x8e\x2d\x8f\xbe\xf3\xfb\x99\x33\x6f\xfa\x74\xcb\x19\x73\x7f\x71\x88\x9e\xb3\xb2\xf7\x10\xb7\x48\xf0\x01\x1f\x08\x81\x65\x66\xd5\x23\x92\xb1\x3a\x3e\x5d\x79\x04\x15\x91\x1a\x51\x0b\x9b\xaa\x71\xdf\xe1\x67\x4c\x3b\x70\x23\xd8\xa9\x95\x15\x1e\x45\x4c\x67\x82\x2d\xc3\x45\x21\x5b\xc6\x64\x96\x2f\x90\x61\xcb\x48\xf9\x92\x04\xa9\xb7\xa6\x1f\x20\xb3\x78\xd9\xac\x09\x89\xcb\x4d\x8f\x09\xab\xc3\x96\xf4\x24\x08\xd3\x56\x09\x5b\x61\xdd\x88\x5a\xc5\x3a\x65\xcd\xa4\xdb\x7f\x75\xf3\xd7\xbf\x78\x61\x9a\xf5\x94\xed\xad\xa3\x4e\xbf\x76\xe2\xda\xd6\xab\xa7\x08\x3e\xe3\xa3\x8e\xe5\x17\x8c\x7f\x6f\xdf\x3e\xe3\xfe\x3f\x3c\xbc\x19\x6e\x9e\x3a\x6f\xe3\xbf\x96\xa3\x1b\x8f\x02\x88\x65\xc0\x1e\xe6\xda\x41\x10\x0c\x37\x7b\x84\x92\x4d\xa7\xbc\xb7\x63\xea\x68\x77\x10\x47\x5a\xd2\x1d\x94\xcc\xee\xa0\x5d\x8a\x03\x8b\x0f\x47\x0a\xce\x0c\x62\x43\x64\x32\xd2\xac\x87\xf8\x44\xa4\x2d\x43\x5b\xd3\x55\xb3\xee\x84\xee\x27\x3b\x6e\x9f\xd3\xb2\x68\xf4\x39\x1b\x26\xcf\x3e\x6b\xd2\x8d\x63\xb7\x3f\xfd\xda\xbb\x70\xfd\x9f\xe0\xec\xdf\x8c\xff\x34\x50\x7e\xc3\x87\x37\xcc\x9b\x1f\x09\x7f\x77\xe6\xbb\xa6\x4e\x1c\x13\x7c\x20\x0f\x84\xc1\xd9\xb4\x6b\x1b\xf7\x82\x94\x3a\x94\xd9\x68\x5a\x05\xba\xb4\x80\x47\x47\x01\x91\xec\x0d\xb9\x5c\x34\xad\x72\x06\x70\x36\xec\xf6\x15\x93\x2e\x7b\x99\x07\xab\x89\x28\x05\xb1\x9a\x70\x92\x66\xb1\xc6\xb2\x14\x85\xd4\x49\xe1\x68\xd8\x9c\x1d\x66\xea\xca\xe6\x2f\x37\x4d\x5b\xd1\x6c\x65\x04\xef\x24\x58\x67\x74\x7c\x2a\x5b\xcf\xb8\x77\x2e\xd6\x98\x0d\xe3\xae\x3a\x73\xe2\x28\xac\x30\x6b\x5f\x82\x17\xbd\xda\x3a\xab\xe8\xf2\x73\xe0\xc2\xa3\x87\xb6\x9c\x3b\xa5\xeb\x4d\xb4\xba\x7b\xf9\xd4\x79\x44\x69\x28\x1d\xa3\xb9\x76\x90\x0f\x42\xe0\x12\xba\xa5\xa6\x89\x16\x93\xb3\xa5\xbc\x9e\xb4\x07\xf3\x38\x97\xa2\xd9\x9d\x54\x85\xfa\x56\x58\x8a\xcd\x82\x39\x0c\x15\xad\xd8\x25\xc9\x49\x07\x27\xe6\x05\x69\x82\xaf\x79\x7d\x38\x94\x89\x79\x92\x8c\x7c\x58\x0a\x1a\xf0\xe2\x1c\x32\x98\xea\xd0\x12\x29\xe4\xf9\x7d\x5c\x28\x6c\xc9\x14\x02\xdd\x7d\x08\x97\x0b\xb3\x1e\x85\x05\x71\xed\x15\x23\x6e\xbc\xae\x32\x17\xcf\x3b\xf7\xb6\x8b\x76\xfd\xef\x1f\xbf\x80\xd3\xea\xee\x7d\xf2\x92\x99\xf7\xc1\xfb\x0e\xc0\x73\x12\x0f\xdf\xf6\xdc\x7e\xbf\x6f\xf6\x25\x55\x0d\x9f\xcc\xf8\x2b\x7c\x66\xfe\xd9\xe7\x3f\x44\xfc\x45\xa5\xe1\x63\x0f\x0a\xa5\xa0\x04\x67\xf8\x79\x98\x90\xa0\x45\x47\x42\x13\xb1\x57\x54\x14\xd1\x18\xbb\x8e\xe4\x88\xe6\xb2\x91\x9a\x05\xa7\x17\x66\x62\xff\x22\x0d\x7c\xbc\x88\xec\x9d\x5a\x41\xe1\x51\xe4\xef\xe4\x11\x2f\x26\x04\xde\xee\x55\x12\x36\xfc\x8a\x0a\xc4\x44\x5e\x81\xdf\xab\x24\x82\xf8\x95\x05\x09\xde\xee\x2f\x20\xb6\xb1\x87\x17\x6c\x76\x7f\x5e\xb0\x20\x63\x2b\x14\x68\x4c\x91\x24\xa3\x92\x18\x0a\x4a\x08\xc4\x34\x39\x8f\x2c\x89\x22\x97\x84\x3c\xb1\x86\x46\x0b\x21\xdd\x1b\x1e\xc9\xf4\x65\xca\x1e\xa8\x5a\xc2\x2c\x13\x2a\xaf\x3e\x38\xbc\x65\xf8\x1c\xef\x1b\x0f\x97\xec\x91\x6b\x5f\x44\x6b\x17\x4d\x1d\x7b\x5a\x6c\x9c\xd3\x79\xb0\xf1\xcf\xef\x4e\x36\x9e\x5d\x34\xee\x63\xff\xd4\x59\xec\xcb\x5b\xa6\x4f\xdf\xf7\x3f\x8d\x1f\x95\x4e\x1d\x35\xe2\xd3\x6e\xb7\xb1\x29\x88\xe5\x5a\x68\xf8\x88\xcf\x2a\x01\x83\xb1\xb7\xc6\x5c\x88\x4b\x98\x15\xb5\x36\x1d\x15\x12\x16\x90\x75\x5c\x57\x97\x56\xea\xd1\xb5\x7a\x9c\xf5\x93\x6c\x9f\x29\x24\xd9\x14\x53\x48\x4f\x5d\x2b\xc5\x81\xab\x9c\x24\x5d\x58\x94\x0d\x8d\x01\x62\xd0\xd1\xcc\x89\x0f\x75\x67\x64\x97\xa1\x1a\x66\x79\xb3\xc2\x87\xf6\x2e\x5a\x3b\xb4\xc4\x3a\xfe\xb6\xb3\x6f\xd9\xb1\xe9\xcb\x0d\xb3\xd6\x9c\x66\x8d\x7d\xf1\xed\x10\xe3\xf8\x97\x8b\x7e\x35\x1b\x5e\x31\x69\xf4\x98\x2b\xa7\xb4\x8e\x3c\x63\xd5\x19\x0f\xcc\x38\xff\xf5\xf9\x6d\x93\xba\x7e\xfb\x12\xbc\xe0\x8d\xb1\xe7\x6f\x3e\xbe\xfe\xeb\x4f\x4a\x6b\x59\x75\xe6\xcc\x1b\xbe\x59\x35\x75\xde\x96\xcf\x00\x04\x95\x00\x70\x4b\x04\x1f\x08\x82\x37\x4c\xef\xe6\x11\x83\x2a\xce\x22\xa9\xf5\x9b\xb3\x6c\x2f\x36\x31\x8f\x9e\xf0\x38\xbd\x56\x85\x36\x35\x22\x9a\xc7\x45\x3c\x83\x99\x83\xff\x96\xca\x99\x56\x70\x41\x91\x34\x76\x8e\x7f\x7b\x3f\xf1\x86\xa2\x88\xa4\x4e\xe4\x11\x91\x1b\xff\x2a\xc1\x06\x19\xaf\x92\xe0\xc8\x6b\x3e\x7e\x8d\xe7\x07\xb3\xfb\x65\x88\x8b\x81\x0e\xc8\xb8\xa5\x7c\x96\x33\x05\x0f\xfb\x7d\x4f\xb2\x7a\x31\x88\x0b\x3b\x81\x6c\x5d\x60\xdf\xe4\xe9\xeb\x86\xb8\x61\xda\x71\x5a\xd8\x90\x97\x9a\x80\x85\x25\x0e\xb3\x7a\xd0\x28\xeb\x88\xed\x0b\x36\xde\x15\x58\x67\xbc\xbd\x41\xbc\x6c\xce\x36\xe5\x02\xc1\xb7\xfb\x85\x3f\x4d\x9e\xfb\xf8\xbd\x13\x16\xf7\xac\x65\x36\x8d\x51\x57\xfe\xed\x0d\xa3\x91\xc4\x00\x00\x98\x4d\x82\x0f\xb0\xc0\x0d\x2e\xc8\x98\x69\x41\x12\xad\x91\x2b\xa2\x59\x70\x14\xf4\xd0\x5e\x9b\x4b\x4f\xb0\x0c\xb4\x2a\x1a\x70\x91\x34\x90\x25\x79\x38\xe2\x70\x66\x68\x17\x49\x21\x60\x46\x8a\x67\xd3\xb9\x89\xc6\xb0\x92\xac\x59\x5c\xb4\x47\xe5\x0d\x39\x60\xdf\xb0\xb5\xf2\x2b\x58\xf7\x95\x78\xfe\xb9\x13\x26\xcd\x9c\x73\x17\xd7\x76\x7c\x07\xbf\xe0\xdc\xf3\x46\x9c\x32\xf5\x42\xec\x6b\x8c\x23\x86\x8f\xd9\x2c\xf8\x80\x03\xe4\x81\x76\x10\xe7\x21\xc9\x60\x90\x8d\x1a\xa4\x3f\xa2\x79\x38\x5a\x7b\xf3\x34\x47\x25\x1b\x18\x72\x46\xe5\x7d\xff\xe1\x7d\x69\x03\xe5\x3a\x69\x35\x07\x48\x1d\x07\x53\xd5\x1c\xd4\x04\xa7\x24\x6b\xb8\x26\x00\x1a\x83\x8b\x27\x07\xa9\xac\x53\x7d\x57\xec\x4c\xb1\x69\x65\x1c\xda\x38\x32\xbc\x79\x43\x45\x0f\xac\x37\xfe\x43\xac\x8a\x99\x64\x12\xf0\xb1\x7f\x27\xb7\xf3\x78\xad\xb1\x29\x68\x89\xa6\xc9\x30\xf5\xf0\x9f\x82\x0f\x78\xc0\x36\x33\x97\x75\x78\x54\x35\x6e\x85\x20\x75\x0b\x03\xab\x1b\xf2\x88\x1a\x84\x0a\x66\xb2\x26\x65\x47\x5c\xce\xd4\x3c\x0f\xd5\x3c\xfa\x53\x47\x82\xf5\x60\x25\x73\xe3\xd7\xb8\xdb\xd3\xaf\x29\x8b\x43\xb0\x9b\xe8\x96\x86\xbf\xd2\xc6\x2c\x94\xe4\xb8\x80\x45\x11\x03\x9a\x15\xd7\x0d\x82\x2b\x96\x0a\xc5\x1e\xa8\xa6\x3a\xb4\x44\x8f\xee\x70\x54\xba\xac\xf0\x65\x38\xd3\x70\xc3\x62\x03\xed\xb9\xba\x55\xf0\xf5\xb4\xc6\xae\x1a\x0c\x0f\x1a\xd6\x9e\x7b\xe0\x23\xe3\x8d\x47\xd2\xf4\x31\xf7\x11\x1d\x9a\x90\xd6\x20\x73\x29\x93\x68\x08\xdb\x47\x18\x9f\x9b\x30\xb2\x29\xc8\x68\x90\x49\x27\x79\x2a\x0c\xd1\xf8\x6f\x74\x08\xbe\xa3\x87\x52\x9f\x23\xbc\xc3\xb5\x83\x2a\xf0\x07\xfa\x39\x09\xd9\x4b\xee\x7c\x10\x75\x25\xfa\x11\x77\x10\xa6\xd2\x5d\xa6\x2a\x97\x8e\xaa\x68\xe0\x29\x72\xe9\xa8\x88\xd4\x88\x98\xd5\x09\xd9\x93\x67\x55\x68\x27\x37\xa2\xc9\x74\x8f\x85\x9c\xeb\xa9\x6f\x3c\x54\x63\x8a\x45\x54\xd2\x89\x8a\x44\x54\xd8\xf9\xec\x88\xc3\xdf\x5e\x46\x4c\xdd\x2b\x22\x5f\x27\x92\xb1\xc1\x83\x84\xe4\x2b\x2c\xa1\xb3\x83\xd4\x3b\xc2\xe3\xe2\x2a\x49\x8e\xb3\x1c\x83\x5d\x60\x91\xa4\x09\xe5\x74\xaf\xcb\x6a\x23\x9b\x7b\x9a\x33\x3f\x66\x36\xc6\x3b\x58\xce\x6a\xf3\xe4\x97\x93\xf9\xb8\xea\x55\xc9\xc2\x54\x20\x97\x59\x67\x18\xf8\x57\x9f\xf9\x6d\xb7\xff\xfe\xa0\x62\x1d\xd7\xb1\xe8\xe6\xcd\xd8\xc2\x37\x8a\x17\xb4\xdd\x55\x33\x0f\x9b\xfa\x05\xd8\xd4\xb9\xb6\x03\x7f\xfb\xdb\x15\x57\xee\xdc\x3e\x69\x91\x69\xea\x9f\xfd\xce\x88\x64\xd8\xbc\xe9\x17\xb9\x76\x90\x07\xee\x32\xf5\xd1\xe9\x52\x33\x98\x98\xea\x67\xe5\xb9\x74\x94\x27\x92\xea\xde\xe6\xd1\x13\x4e\x9b\x68\x55\x68\x34\xa7\x1b\x4e\x29\x33\x33\x3d\x21\xe9\x51\xb8\xc9\x65\x0a\x47\x27\xd0\x1c\x6e\xac\x7b\x8e\x94\xee\xe5\x99\x3b\x98\x2e\x29\xc5\x1d\x11\xe7\x81\xc8\x29\x21\xc1\xe4\x48\x82\xe5\x6c\x72\x16\x3b\xfa\xfb\x37\x4a\x7e\x96\x6b\xc3\xf4\xe6\xf0\x6b\x38\x4f\x99\xce\xb5\x03\x17\x08\xa6\x7b\xbe\x64\xbf\x16\xc7\xb4\x3c\x7b\x5f\x06\xe8\x22\x3d\x5f\x9f\x99\x9c\x14\x42\x85\x34\x1a\xcd\x9e\x6f\x9e\x28\xc9\x1a\x48\xdd\x1b\xa0\x29\x88\xb9\x60\xdb\x97\xa6\xce\xda\x0c\xdd\xbb\x5f\xfa\xdb\x26\xe3\xbb\x3d\x2f\xea\x30\xb2\x6d\xe2\xd5\xa7\x6f\x9e\xb8\x62\x22\xbc\xe7\x1d\x38\x79\xcf\xa1\x03\x6f\x1b\xcf\x26\xfe\xfe\xe2\x33\x2b\x0f\xae\x79\xf9\x5a\x92\x43\xf5\xee\x35\x7c\xdc\x22\xae\x9d\xe4\xdd\x3b\x40\xdc\x65\xa6\xdc\x7d\x02\xc0\xd5\x99\x4f\x4d\xe5\x4f\x3e\x97\x8e\x7c\xe4\x4e\x04\x99\x6e\x86\xb3\x9d\x5b\xaa\xcd\xee\x13\x51\x59\x67\xc2\xeb\x2b\xf3\x2a\x89\x10\x7e\x8d\x7b\x7d\x65\x19\x2e\x21\x14\x03\x71\x6f\x59\x88\x28\x2c\xa4\x6f\xa8\x60\x8a\x7c\xd8\x29\xb8\x68\x53\x24\xdf\x45\xd3\x0d\x28\x61\x61\x94\x10\x61\xb0\x50\xcd\x5a\xe6\xab\x0e\x0b\x16\x36\x2b\x51\x1f\x03\x67\x7c\x26\xd9\x36\x26\x6e\xff\xd5\x86\xaf\x37\x9f\x7d\xb5\x6a\x75\x96\x8e\x7f\xce\xcc\xd3\xaf\x99\x6c\xf8\x84\xd6\x9d\xbf\x7d\xf7\xf9\xdf\x1a\x0f\x1e\x68\x3d\xef\xc1\x9b\x8d\x5d\xec\x4a\x33\x53\xff\x0f\xcd\x29\xcd\xdc\x23\x0f\x54\x80\xa7\x01\xcd\xba\xec\x2a\x15\x55\xc8\xa6\x23\x67\x84\xf4\x9b\x2a\xfb\xe7\xc7\x0e\xba\xf5\x63\x0e\xf8\x92\x54\x07\x9d\x22\x2a\xea\xe4\x91\x03\xa7\x64\xcf\x8e\xb8\xe5\xf0\x65\xa9\x11\x96\xcb\x59\x84\xbd\x25\x7e\x8d\xbb\x9c\x45\x27\xec\x92\x16\x11\xd6\xd8\xe9\x1b\xca\x9a\x00\x20\x5d\x4a\xac\xa3\x05\xe4\xe2\x04\xe7\x11\x4b\xe8\x2a\x51\x08\x47\x0d\x50\x10\xcb\x55\xa9\xc1\x50\x2a\xe1\xa9\x87\x27\x56\x6b\x33\xd6\x9d\x62\x8d\x7d\x61\xec\x34\xde\x8e\x0c\x39\x05\x67\x3a\x33\x6f\x9e\x0c\x1b\x27\x9c\x3e\x6e\xf9\x64\x9a\x82\x93\x9a\x6d\xe2\x79\x9b\x8f\x76\xfc\xef\x3f\x9e\x69\x9b\x74\x7e\xc7\x6d\x33\x67\xde\x70\x74\x85\x99\x82\x53\xfb\x65\x77\x72\xed\xf4\x56\x1f\xdd\x37\xef\x33\xdd\x74\x3c\x21\xcb\x27\x1e\x6a\x75\x7d\xf6\xe5\xc8\x76\x37\x6c\x55\xda\xb0\x1c\x5b\xf6\x0f\xab\x1c\x5d\x17\xbd\xf2\x7f\x2a\x2f\xc5\x46\xe5\x30\xfe\x22\xee\xf9\xb5\xe1\xa4\x9f\x19\xe8\x3d\xc4\x3e\xc4\xb5\x83\x72\x9c\x25\x94\x91\x9e\xb0\xa0\x93\xb5\x3a\xcd\x27\xe8\x10\x85\xc9\x76\xa0\x29\x1c\x01\xa7\xf8\x1e\x5d\xab\x80\x0a\xb9\xe5\x14\xb7\xb1\x65\xb1\x58\x4c\x2b\x16\x24\x39\xe1\x91\x7d\x05\x84\x85\x6c\x19\x6d\x0a\xfb\xa4\x04\x74\xca\xb8\xb8\xc1\x29\x8e\x14\x6b\x68\x8c\x36\xa7\x36\x1e\xc9\x8d\xa7\xfe\x2d\x61\xac\x84\x81\xfb\x77\x4c\x5d\xd8\xda\x76\xcd\xbc\x0f\xde\x7c\x6d\xc7\x85\xb7\x5e\x15\x1b\x77\xda\xcc\x95\x97\x1f\xfd\xcb\xe2\x07\xeb\x8e\xcc\x1a\x35\x54\x19\x33\x64\xcc\xfa\x39\x3b\x9f\x3b\xff\xdd\xe9\xaa\x52\x3d\xac\x6e\xe4\x1d\xf3\xf6\xbe\x56\x02\x20\x68\xeb\x3d\xc4\x2e\xe5\x27\x81\x7c\xb0\xc9\xec\xcb\xba\x6c\x3a\x61\x9d\x66\xb5\xe8\x28\xbf\x29\xce\x5b\xed\x4a\xe2\x34\x9e\xb5\x29\x71\x86\x70\x34\x18\x41\xfe\x2e\x14\x68\x22\x63\x70\x5b\x93\x56\x90\xee\x94\x3c\x4a\x63\x58\xa0\x9e\x47\xf9\x9d\x9c\x66\x2b\x3c\xca\x23\x6b\x27\x0b\x34\x5b\x00\xfb\x3e\x6b\x3e\x1d\x64\x39\xfc\x92\x1c\x87\x8c\x4c\x2c\xcc\x25\x53\x0b\xb3\x4a\x24\xe9\x40\x3c\x96\x4f\x43\xa3\x77\x24\x43\x2e\xe1\xd1\x8e\x2d\x2d\x6e\x9a\x87\x44\xbd\x6d\xc5\x2f\xfd\xfc\x85\x46\x58\xd8\x64\x7c\xd6\x2e\xcc\x1c\x35\x7f\xe9\xbd\xdb\x36\x39\xdb\xd9\x6b\xb6\x4e\x3f\xf4\xf5\xa7\x3d\x9f\x96\x04\x5a\xc3\x1f\x37\x5f\xff\xf3\xa6\x11\x0c\x9d\xfd\x2e\xed\x3d\xc4\xc5\xb9\x36\x90\x07\x2e\x02\xa4\x98\xa7\x55\x26\x8b\x6d\xca\xa5\xa6\x3c\xbb\xc5\x95\x6e\x3b\xbb\xfa\xda\xce\xd4\xa5\x6b\x16\x96\x56\x61\x9c\x84\x6c\x31\xe4\x92\xe3\xa2\x44\x76\xe6\xdd\x12\x59\x5b\x65\x45\x5c\x7f\xda\x24\xd9\xbc\x2a\x94\xdd\x66\x36\x9b\x14\x4b\xf3\x57\xc3\x3a\xd3\x43\xc3\x3a\xa2\x5d\x6f\x6e\xbc\x1d\xd6\xcd\xbd\x9a\x99\xd3\xd3\x4e\xfc\x34\x3c\x70\x7c\xc7\x81\x4f\x1e\x05\x10\x2c\x04\x80\xdb\xcc\xb5\x01\x07\x68\xa0\x9e\x3a\x0e\x20\x69\x8c\xa6\xf6\x0f\xa0\x8b\x76\x41\x49\x8f\xd9\x11\x03\x1a\x70\x48\x32\xe2\x68\x33\x31\xcf\x6f\x76\x6b\x17\xc2\xea\x3a\x8b\xfd\xb4\x7c\x58\x0b\x4f\xef\x79\xc4\xf8\x0d\xd7\xd6\xd3\xb1\xee\x02\xad\x9e\x99\x76\x7c\x07\xe1\xcd\x2a\x00\x84\x0e\xae\x0d\x14\x81\xb9\x20\x5e\x84\xf3\x14\xaf\x4a\x3e\x4a\xb3\x49\xb8\x2a\x28\x26\x1f\xc6\xb8\xc8\x86\x83\x1f\x2a\x49\x07\x6d\x52\x95\xe0\xe4\x05\x90\x76\x72\x11\x66\x84\x5f\x8a\xdb\xf2\x0b\xe9\x5d\x2a\xcd\xe5\x26\xcd\xe4\x22\xfc\x6b\x57\x20\xdd\x4c\x26\xbd\x64\x6f\x48\x22\xbd\x64\x6f\x08\x86\x58\xd2\x4a\x66\x43\xab\x60\x90\x73\xd8\x9c\x63\x0a\x3e\x87\xe3\xed\xf6\xb3\xaa\x0e\x42\xb5\xe7\x6b\xa3\x43\xb0\x3b\x67\x15\xea\xc6\x5e\xae\xcd\x90\xde\x5a\x33\xb8\x73\x38\x93\xdf\xf3\xc5\xf3\x8b\x8e\xcd\x84\xff\x38\xbe\x83\xb1\xde\xfb\x4c\xef\x69\x3d\x9f\x00\xd8\x7b\x1f\x00\xdc\x23\x84\x57\x55\x19\xfd\x63\x98\xee\x1f\x93\x5b\x2b\xfd\x7b\xc2\x85\x30\x04\xbd\x21\x16\x2e\x80\x1f\x7e\x0c\x47\xb5\x7f\x0b\x2f\x30\xea\xbe\x35\x9e\x5d\x65\x1c\x61\x86\x33\x21\x23\x0e\xa7\xf4\x1c\xe8\x79\x1b\xce\x30\x76\x92\x7a\xb8\xdd\xf0\x71\x5b\x88\x0e\x9d\x02\xe2\x16\xfc\x6f\x8b\x2a\xf2\x99\x35\x60\x80\xb4\x84\xad\xa6\xae\x58\x2d\xa4\xed\x0a\x34\xc6\x27\xc9\x28\x8f\xd4\xf2\x80\xcc\xa2\x48\xa5\x3a\x12\xb2\x44\x40\xa4\xaf\x4e\xf2\xe8\x4d\x63\x1a\xa6\xaf\x6e\x29\x78\x04\x56\x0f\x75\x5a\x7d\x0d\xb5\x90\x83\x67\xf4\xcc\xd4\x8c\xdf\xcf\x8a\xe9\xae\x79\x17\x35\x72\x6d\x3d\xc7\x2e\xd9\xab\x6e\x38\x87\x29\x38\xce\x18\x49\x2f\x3e\xcf\x5b\x00\xb0\xaf\x72\x6d\xb4\x17\x6c\x23\xbd\x60\xab\x19\xc9\x59\x6b\x66\x2f\xd8\x96\xa3\x17\x1c\x0d\x59\x60\xc8\x12\x09\x33\x23\x8d\x76\x95\xf9\x5a\xe9\x79\x1d\xee\x69\x4c\x32\xcf\xeb\xbf\xeb\x39\x5b\xa7\xfd\xc2\x23\xc6\x5e\x76\x01\xdf\x01\xaa\x81\x0e\xe8\xca\xb7\x5d\xd0\x51\x49\x44\x2b\x12\x68\xb3\xdb\xa2\x93\xbb\x1a\x55\x5d\x49\x1f\xe9\xc1\xc6\x7d\x55\xd8\x47\xf8\x8a\x6d\x0a\x8e\xbb\xc1\xb2\x2e\x29\x19\x22\x4d\x5b\x14\x8a\x24\x83\xf4\xe6\x57\xad\xe9\x26\xee\x3c\x7c\x2f\x8d\x4c\x61\x11\xf1\x9d\x5a\xa0\xf8\x28\x72\x75\xa2\xb0\x98\xe0\xc2\xbc\x57\x41\x01\x31\xe1\x0e\xb8\xbc\x4a\x22\x0f\xbf\xe2\x9f\x57\xe0\x9f\xc7\x2b\xc2\x7c\x46\x88\xe2\x62\xf1\xbc\x80\xcb\x0c\x56\x7b\x38\xde\xe5\xce\x0b\x84\x2b\x52\x7d\x03\x78\xc2\x4f\x48\xf8\x0a\x56\x49\xb2\x26\x4a\x29\xfd\xd4\x7c\xa1\x18\x8e\xec\xc4\xc5\xb2\x51\x6c\xaf\x23\xe0\x30\xb2\xe6\xca\x9a\x1b\x7a\x1e\x88\x9d\xac\xea\x27\xce\x67\x24\x6c\x69\x1e\x62\xad\xbb\x76\x53\xde\xf0\xaa\x67\xb5\xe9\x8d\xb3\xce\xf2\x8c\xae\xfb\xfc\x9c\xb3\x3d\x15\x96\xd3\x4f\x69\x7e\xfc\x49\x77\xb5\x07\xee\xff\xf4\xec\xf9\xb0\x78\xe7\x2d\x1f\x33\xa3\x5a\x8d\x77\x0f\x14\x5b\x0b\x96\x4d\x19\x3c\x36\x5e\x14\x68\xa9\xf9\xeb\xea\x6b\x62\x63\x9e\x1e\x2b\xdd\x8a\x79\x0c\x5f\x35\x22\xcc\x0e\xc1\x4d\x7a\xb2\xa9\x0b\x5b\xb4\x07\x9c\x6a\x05\xd3\x9e\x2c\x94\x54\x09\xbe\x7a\xd0\x88\x58\x3e\x3c\x12\xc2\xfa\x6e\xec\x65\x3e\xe6\x3b\x40\x15\x78\x13\xc4\xbd\x0c\x50\x50\x55\x44\x03\x54\x3c\xc5\x16\xba\x96\x6e\xef\x4a\x16\xd2\x2e\xb9\xa7\xac\x4b\x42\x2e\x35\x99\x47\x85\x91\xdf\x94\x4e\xec\xaf\x3d\x5c\x42\x9d\xb5\xab\xde\x8d\xd8\x4e\x4e\xcb\x67\x8f\xba\x51\x39\x2e\x3d\x12\x1c\x8b\xf9\xef\xc4\xaf\xa8\x5c\x4c\x04\xcb\xf3\x71\x0e\x85\x5f\xe3\x1c\xeb\xca\x90\x82\x33\x16\x0f\x95\xe7\xe3\x77\xc1\x18\xd8\xc3\x72\x4e\x57\x7e\x30\x54\x9e\x96\xc2\x6e\x96\x73\xa6\xbf\x27\x12\x28\xf4\x48\xb2\x66\x25\x63\x9a\xe2\x12\x49\x46\x56\x52\xcb\xdb\xb1\x79\x60\xf7\x30\x02\x46\x9b\x53\x8c\xae\x0a\x47\xd5\x32\x53\x02\xaa\x05\x07\x65\x37\x54\xe0\x82\xb9\x33\x3d\xa3\x83\xb7\x2e\x7d\xc2\x53\x29\x4c\x98\x50\x1b\x82\xd3\xdd\xd5\x9e\xb7\xea\xae\xdd\xe4\x1f\x51\xf9\x9c\x56\x77\x01\x3b\x6a\x02\xac\x5d\x7a\xb9\xdb\xa6\x3e\xa6\x8c\x4d\x94\xf8\x5b\x6a\x3e\x3e\x32\x74\xcc\x33\x63\xa5\x5b\x3e\x9d\x3e\xdf\xf8\xdb\xce\x5b\xc9\x3e\x36\x53\xcd\x55\xb2\xab\x40\x00\xa8\x80\x4c\xed\x54\xcd\xc6\xeb\x09\xbf\xcd\x63\x55\x34\x96\xd7\x91\xb3\x09\xa2\xfc\x88\x16\x24\x0b\x6a\x1e\xb2\x7b\x44\x07\x89\x24\x32\x35\x93\xbc\x86\x5c\x33\xa2\x71\xa9\x9a\xec\xa8\x2d\xb9\xe8\xde\xd3\x2e\x9d\x71\x5a\x5b\x83\x7a\xed\xf0\x8b\xef\x1e\xb6\x60\xfe\x79\x93\x06\xb5\xac\x62\xaa\x3f\x5f\x52\x54\x51\x58\x34\xfc\xd4\xcf\x97\x04\x6a\xaa\xe4\xd1\x80\xe9\xed\x30\x36\x31\x95\x5c\x1b\x60\x81\x07\x0c\xa6\x1e\x25\xe9\xea\x03\x21\xe0\xba\x92\xf6\x3e\x10\x02\x72\xe3\x89\x65\xe8\xbe\x3b\x54\x33\xbb\x05\x55\xad\x10\x1c\x7e\xe0\x8c\xcb\x66\x4d\x38\x7b\x69\xdb\x98\xb3\x8c\x4d\xec\x5b\xdd\x11\xde\x73\xce\x92\xd6\xd3\xe7\x2c\x9e\x44\xf3\x94\x47\x7a\x0f\x71\xc3\xf8\xfd\xa0\x14\x7c\x62\xfa\xf8\x42\x35\x35\xfb\xc0\x1f\xea\xe0\x94\x64\x81\xaf\x88\x77\x29\x5a\x81\x8d\xae\xc6\x82\x2e\x4d\xf2\xe8\x89\x22\x09\x58\x15\xac\x48\x12\xa7\xc4\x0b\x8b\xb0\x81\x17\xe6\xdb\xd2\x17\xff\x47\x3c\x76\xf8\x4b\x92\x6f\x17\x91\xcd\xad\x42\xba\xc6\x43\xc7\xb3\x0e\x54\x24\x26\xb8\x22\x9e\x5e\x03\xb7\x14\x0a\x5e\x85\x4f\x14\xe0\x2f\x59\x7f\xa2\x18\xff\x89\x78\x71\x51\x3f\xc3\xb6\x14\x0a\x92\x1c\x03\x71\xce\x52\x4c\xb4\x88\xe3\x05\x4b\x41\x71\x7d\x46\xcf\xdc\x57\x20\xc9\x28\x9f\xd4\x4e\xc0\x8e\x63\x0c\xce\x1a\x6c\x66\xd2\x69\xde\x07\xef\xd7\xa0\xf6\xc0\x70\xb4\x1e\x3e\xb2\xea\xf3\xed\xa1\xbd\xe1\xab\x16\xcf\x69\x5e\x34\xfa\xec\x75\x67\xcf\x9a\x36\xf1\xc6\xb1\x37\x3f\x5c\xbb\xb7\xf1\xa6\x8d\xcc\xf8\xe7\xe1\x98\xd7\x02\x0f\x3c\xe0\x56\x3f\x0b\x94\xaf\xf8\x64\xdd\xbc\x79\x91\xf0\x77\x67\xd8\x3a\xff\x58\xf1\x3b\xea\x17\xbf\x05\x80\x7b\x9f\x7f\x13\x14\x81\xfb\xcd\x3a\xb1\xc0\xa1\x23\xd8\x14\x77\x30\xb4\x9a\x4a\xf2\x02\x70\xb8\x14\xcd\xe2\x53\xc9\xd4\x4c\xe3\x02\x4d\x4d\x38\x8e\xe2\x90\x99\x69\x76\x6e\x5c\xe1\x5b\x3b\xb5\x7c\xff\x51\x72\xd1\x9e\x18\x9d\xd5\xab\x24\x2c\xf8\x15\xe5\x8b\x09\x5f\xbe\xd7\xab\x24\x02\xf8\x95\x05\x09\xd6\xea\xcd\xa7\x8e\x8d\xe5\x2c\x56\xaf\x2f\x90\x9f\xd5\x22\x15\x05\x32\x6b\x46\x0e\x09\xb9\x88\x9b\x6f\x19\x09\xc3\x51\x35\x9a\xd9\x13\x0d\x59\x42\x16\xc1\x12\x62\x9d\x8d\x2f\x35\xe4\x75\xd6\x75\x36\xd6\x1e\xee\x7c\xf1\xa9\x65\x9b\xe6\x4d\x9c\xe7\x8b\x40\xa5\xce\x78\x47\x1e\xf4\x38\xb3\x39\xfa\x5d\xc3\x7b\x8b\xfe\xfc\x9f\x97\x0f\xcc\xf8\x62\xcc\x99\x73\x3f\xfd\xf3\xf4\x17\x27\x1a\xdd\x80\x01\xed\xc0\xe0\xc2\xdc\x4e\x50\x08\xaa\xc1\x75\x80\x06\x9b\x4a\xb2\xa4\xaf\x95\x3a\x69\x38\x08\x76\x25\x8b\xe8\x0e\x7e\x91\xa8\x95\xf7\xa5\x0b\xb5\x50\xd1\x8a\x82\x92\xbc\x9b\xf1\xf9\x61\xa0\x10\xe7\xb5\xe5\x92\x26\x73\x24\x5f\xd8\x2d\x58\x6c\x2e\x8f\x48\x2f\x5f\xcb\x92\xbc\xdb\xe5\x16\xe9\x65\x6c\x54\x29\x69\x41\x07\x99\x3c\xec\x06\x8c\x60\xb5\x15\xd2\x04\x2b\x1a\xc0\x09\x70\x34\x60\xc1\xc5\x70\xc0\x52\x2d\x84\xcb\xab\x2d\xd5\x51\x9c\x1d\x06\xfa\xae\x55\x09\xed\x5b\x57\xcf\xbe\xf4\x92\xd9\xab\xb7\xad\x69\x6e\x5e\x75\xfb\xea\xf3\x2f\x6a\x9f\xbe\x6a\xcb\xea\x96\x96\xbb\x97\x4c\x3d\x6b\xe9\xb2\x33\xa7\x2c\xe5\x02\x5b\x57\x37\x47\xd7\x6c\x5e\x73\xde\xe5\x8b\xe7\xac\xda\xb2\x4a\x55\x57\x6e\x59\x35\x77\xd1\xc2\xf3\x5f\x9e\xbc\xf4\xf2\x29\x53\x2f\xbf\x82\xd8\xcf\x4c\x00\x78\x3b\xdf\x01\xf2\xc0\x04\x7a\x0f\x8a\x40\x6d\x20\xbb\x9a\x04\xd0\x6f\x71\xe1\x54\x20\x09\x9c\xa0\x9e\x53\x90\xdc\x94\xe4\x78\xf2\x33\xa7\x9a\xe4\xe8\xcf\xdc\x4d\x38\x43\xc0\xa9\x01\xd0\x2c\xbc\x44\xb5\x74\x24\x54\xa3\xe1\xa8\x4a\x66\xd3\x50\xb5\x84\x2d\xf8\xff\x50\x74\x66\x65\x77\x71\x77\xf5\x4b\x9d\xb0\xf6\x67\xb0\x1d\x46\x0d\x61\x7f\x75\x77\x51\x77\x65\x77\xc4\xf8\x20\xf2\x41\x7c\x63\x9c\xf9\x7b\x4f\x9c\x99\xd2\xe3\x8f\x6f\x8c\x7f\xf0\x01\x00\x4c\x46\x0c\xb1\x80\x30\x20\x7b\x1b\x6c\x17\xe2\x9a\x92\x0c\x15\x83\x90\x7a\x67\x5e\x52\x81\xaa\x14\x0e\x42\x12\x4f\x0e\x1e\x84\x6d\xdd\x6f\x71\x88\x8d\x74\xbf\x45\x6a\x4e\x5f\xef\x21\x8e\x13\x4a\xc1\x60\x10\x05\xb7\x82\xb8\x42\x2a\x1a\xa7\x8e\x0a\x22\x9a\x1f\xcb\x77\x28\xae\x67\x92\x75\x26\x3e\x01\x0e\xf0\xc5\x34\xa6\xd4\x89\x9a\x9a\xc6\x23\xc0\x31\xbd\xa6\xac\x4b\xa2\x23\xf2\x88\x56\xe3\xd2\xb5\x18\x2e\x7e\xb0\x64\x59\xbb\xcd\xa3\x34\x57\x04\x62\x5a\x8d\x20\xc9\xbb\xfd\x05\x65\xa1\xca\x06\x5a\xf9\x28\xb4\xf2\x29\x90\x76\x43\x39\xbf\xa6\x01\xff\x21\xe4\x97\x51\xe0\xc4\xda\x27\x9a\xb3\x02\xb2\x98\x65\x50\xea\x0e\x7e\xb5\x1b\xfa\x76\x3d\x79\xe1\xec\xd1\x6d\xcb\x6f\x98\x73\xf9\xa0\xa1\xfa\xcb\xbb\x76\x4d\xdb\xba\x7e\xe4\x59\x67\x9d\x7b\xed\xd5\xcf\x57\x0d\xe9\x3e\xf8\xc6\xbf\xce\x59\xd8\xd8\x8c\xd4\x11\xd1\x8f\x2e\x19\x17\xab\x3e\xbd\x3e\x76\xfb\x82\x73\xb6\x8e\x2d\xbf\x28\xb6\xf5\xd7\x33\x9f\x9f\xde\x34\x74\xd0\xe8\xaa\x96\xdb\x2f\x7c\xba\x3d\x7c\xd1\x29\xbf\x7c\x86\xad\x53\xcf\xa9\x2b\x9d\x13\xb9\x74\x5c\xfe\x79\x64\x56\x08\x1f\xe2\x8e\x70\xaa\xc0\x91\x9d\xf6\x08\xc0\xac\x97\x55\x8d\x75\xe8\xc8\xd5\x84\xbf\xa4\x36\xd1\x78\x97\x8e\x78\x51\xb3\xd3\x3e\x1b\x4e\xa2\xb1\x1c\x30\x01\xb4\xdf\x9b\x7e\x07\x1f\x3a\x73\xfc\xaa\xf1\x93\x57\xc3\xd5\xf4\x2b\xbf\x70\xca\xd4\xcb\x26\x9c\x7b\x39\x79\x05\x2c\xd8\xd0\x7b\x48\x58\xc4\xef\x07\x1e\x50\x0a\x9a\xc1\x56\x3a\x45\x4d\xfa\xc8\x08\x97\xac\x01\x24\x8b\xe8\x54\x57\xad\x73\x72\x2e\x25\xa9\xd2\xef\xc2\x35\xe4\xbb\xb0\x39\xea\xa5\x28\x13\x22\x45\x0d\x11\xc9\xb5\xb5\xa4\x42\xbf\x53\xc8\xc6\x59\xd2\x4a\xc1\x42\xa2\x50\xd1\xf2\x15\x49\xde\xe3\xf4\x71\x45\xe1\xca\x88\x4a\xe4\x54\xa7\x4a\x32\x6a\x88\xa1\x1a\xa9\xc3\x2a\xe6\x97\x81\xaa\x08\x16\x54\x58\x46\x95\xe9\x86\x10\x27\xd3\x8e\x50\x05\x13\xf5\xc9\x9c\xda\x54\x21\x37\x0f\x61\x2a\xc2\xe5\x1c\xc3\x67\x88\x4d\xc4\x25\x1d\x99\x80\x6c\xf8\x1d\x6c\x7b\xfd\x65\x38\xeb\x0f\xaf\x19\x8f\xbf\x79\xc0\xd8\xf1\xe2\x92\x5d\x50\xd9\xf5\x24\xac\xfd\x9f\xff\x31\xde\x7d\x72\x97\xd1\xf5\x24\x74\xff\xf9\x85\xeb\xaf\x1f\x71\xd9\xf4\x6b\x7f\x6e\xcc\xbd\x7a\xd4\x05\xa7\xec\xeb\x62\x0e\xe2\xbf\xf5\x82\xb1\xe3\x0f\x6f\x18\x8f\xbf\x7e\x00\xce\x7a\x05\xff\xc1\x5f\xe3\xbf\x04\x6b\x76\xed\x32\xde\xd9\xf5\xd6\x91\x11\xab\x5a\x7e\x75\xaf\xf1\x5c\xdd\x9a\xa2\xbc\x7f\x01\x06\x6c\x67\x0e\xb1\x4b\xf8\x17\x81\x0c\x8a\xc1\x74\x7a\xd7\x08\xd9\xd4\x64\xa1\xc9\x18\xb2\x95\x9e\xf4\x52\xbb\xf1\x92\x76\x0a\x76\x5f\x98\x15\xa5\x50\xd1\x9c\x5e\x49\x4e\x72\x6e\xd1\x4f\xbc\x97\x43\x4a\x58\x2d\xae\x20\x61\x09\x57\x98\x1e\xc9\x91\x4e\x65\xe6\x64\xba\x0f\x30\x43\xd8\x3e\xe7\x9e\x05\xa3\xa6\x17\x5b\xab\xef\x79\xe0\x0e\x9b\x6d\xea\xb5\x17\xff\xec\x8d\x19\x75\x53\x9a\x67\x4e\xb8\x88\x3d\xb2\xfc\x2f\x57\x37\x37\xcd\xea\x19\x3d\x67\xd1\xad\xd7\x2e\x3d\xeb\xa1\xd6\xc5\x9d\x80\x01\xe3\xc1\x2c\x6e\x35\x67\x05\x02\x70\x91\x1b\x6a\x01\xe8\xb5\x40\xfa\x65\x3c\xdc\xf2\x5b\x43\x5f\xff\x1d\x2c\x86\xb7\xef\x33\xf4\x9b\xbf\x63\xaa\x65\x78\xe0\x5e\x23\x6e\xec\xb8\x18\xbe\x99\x7e\x0b\xfa\xf0\x0e\xd8\x91\x80\xc7\xb9\x0e\xbd\xbd\x96\x42\x3a\xe0\x6c\x0a\x59\x1a\x4e\x6f\x1f\xc4\x39\x02\x40\xc3\x01\x9b\xa2\x59\xd2\x68\x06\x61\x69\x09\xfb\xf4\x41\x66\xc1\xc1\x9e\x67\xe0\x65\xff\x25\xee\x00\x97\xa5\xc7\x75\xa0\x19\x24\x07\xd6\xe4\xc1\xf5\x44\x77\x07\xd3\xdf\x0c\xae\xc7\x67\x1b\x5c\x66\x53\x50\x6d\x53\xb2\xbc\x99\xfc\xae\xfc\x24\x7a\x5d\x47\xbf\xab\x6f\xc2\x2e\xaa\x11\x2a\xc9\x4a\xfa\x83\xca\x13\x14\xbd\xb1\x4e\x92\x77\x3b\x7d\x45\x9c\x52\x43\xe3\x0e\x1a\x44\xee\x93\xd7\xc6\x80\x56\x3f\x58\x92\x93\x56\x31\x1f\x90\x5f\x35\x4b\x3f\x48\xd5\xa1\x64\x5e\x37\xf7\x86\x59\xec\x71\x9b\xc8\xda\xe1\x0f\x50\xf5\x0d\x7f\x7f\xf4\xc1\xb6\x19\x1f\x3f\xf4\xbb\x25\x33\x9f\x9f\x37\x7f\xe6\xf7\xea\x79\xcf\x7d\xec\x15\x37\xdc\x38\x79\x75\xd8\x58\x03\xe7\x18\x8f\xc0\x77\xb7\x4e\x3c\x95\xca\x3d\x2e\xf8\xb8\x43\xc2\x07\x80\x05\x01\x2a\x23\xa7\x8e\xff\xcf\xd8\xf6\xc0\x92\x89\xd7\x71\xae\x7a\xc1\xf7\xda\x6b\x24\x06\x3c\xc2\x06\xd9\x99\x44\x36\x85\x60\x3c\x48\x43\xd6\xe0\x2a\xda\xeb\x4c\x6d\x05\x63\x2e\x4b\x94\xcb\x79\x94\x8d\x38\xc0\x14\x43\x85\x36\x87\x9d\x1c\x4e\xee\x83\x5e\x9c\xe7\xd3\xad\xd4\xf4\x0d\x5e\xda\x00\x8c\x66\xc4\xe8\x47\xe6\xee\x98\x3d\xf7\x97\x73\xe6\x3c\xd4\x36\xf7\xa1\xb9\xfb\x66\x8f\x1a\x3d\x6b\xf6\xa8\x51\xb3\xb9\x65\x73\x7f\x39\xa7\xed\xa1\x39\x73\x1f\x9a\x3d\xeb\xa1\xb6\x91\xb3\xe7\x8c\x18\xd9\x76\x3e\xb9\x8b\x09\x00\x57\xc9\x7d\x4d\xf2\xe6\x05\x66\x06\x46\x6f\x63\x22\x07\xc9\xb7\x90\xad\x29\xce\xf1\x44\x87\xdd\x36\x25\xce\x73\xa4\x73\x65\xb1\xd1\xbc\xda\xdd\x85\x23\xa2\x2b\x85\x67\x15\x77\xb9\xf1\xaf\x5d\xac\x4d\x41\xf6\xa6\xb8\xdb\x45\x16\x72\x81\x4d\x41\x5c\x13\xce\xbc\x41\x43\xa3\x4a\x6f\x75\xf6\x01\x7a\xb0\x4f\x77\x8f\x4f\x81\x7a\x1c\x3c\xc8\xec\x30\x61\x3d\xb6\xc2\x25\x98\xe7\xc3\x98\x56\x56\xe1\xf7\x93\x27\x27\x50\x18\x06\x9b\x53\x47\xc1\x88\x16\x70\xd2\xfe\xba\x90\x42\xf8\x21\x7d\x75\x59\x90\x64\x2d\x3f\x48\xae\x8b\x05\xe9\x30\xc0\x26\xc5\x85\x2c\x40\x06\x6f\xb4\x72\x04\x93\x0d\x62\xe0\x86\x38\x99\x1b\x16\x86\xd2\xd2\x53\x8b\xd5\xf0\x8c\x85\x0b\x5a\x1f\xb9\x7c\xe5\xd6\xc1\xf3\x36\xad\x81\xb3\x6b\x99\xd6\xc7\x0e\xce\x1e\x31\xb4\x68\x50\xcd\xb4\x07\x62\xa7\x5e\x3f\x7f\xdc\xa5\x17\x2d\x3c\x9f\xe6\xaf\x60\x0e\x13\x63\xeb\xf8\xd7\x40\x25\x58\x0b\xe2\x01\x6c\x69\x32\xcd\x52\xc2\x91\x24\x4b\xdf\xd9\x23\x49\x87\x69\x53\x55\xe4\xbc\x65\x94\x5d\x65\x22\x2a\xc0\x41\xdf\x43\xbf\xf5\x44\x92\x05\x54\xf0\xd5\x38\xb2\x09\x14\x34\xa7\x4c\x42\xc5\x38\x9a\x87\x69\x34\xb7\x4b\x1a\x2c\xa3\x4d\xa1\x62\x8a\xd3\xa0\xf9\x0a\x62\x31\x14\xa0\x48\x0d\xde\x54\x60\x4f\x5d\x7f\x23\x44\xb6\xa4\x80\x1a\xcc\x12\x67\xce\xaa\x35\x93\x2e\x18\x32\x62\x75\xf9\xac\xe9\xf3\x87\xd4\xcd\x58\x38\xed\xb6\x5f\xdf\x78\xf7\xc2\xf6\x7b\xba\xe2\x13\x37\x31\xcb\x3a\xc7\x0f\x3f\xa5\x52\x7d\x68\x68\xac\xa6\x66\xf4\xb6\x39\x4b\x17\xcc\x68\x2f\xb5\x86\x36\xad\xbd\xaf\x94\xd4\xd8\x9f\x70\xef\x73\x22\xd9\x5f\xaa\x24\x36\xc0\xf6\xed\x2f\xf1\xd4\x47\xe1\xb8\xcc\x03\xd2\x3b\x23\x7b\x4c\x2d\xd1\x90\xdf\x0d\x2d\xf0\x93\x33\x37\xc3\x33\xeb\xdf\x9b\xc1\xbd\x1f\x9c\xf9\xae\x34\xf4\xf9\x11\x24\xff\xdf\x6b\xf8\xb8\x7d\x5c\x1b\x28\x00\x9d\x19\x1b\x2b\x9a\xd5\x1c\x55\x68\x8c\x53\x55\x11\x88\xa0\x02\x35\x85\x56\x52\xe0\x21\xe8\x01\xe6\xb4\x0f\x31\x7d\x7b\x2c\x45\x66\x41\xf0\xc4\xe1\x6f\xe9\xe5\x92\x87\x0e\xff\x81\xd4\x45\x05\x62\x82\x2d\x20\xc3\x72\xf2\x1a\x2c\x20\x23\xf3\x82\xcc\x69\x66\x90\x0c\x34\xe3\x6c\x7e\x10\x97\x04\xe6\xd7\xf4\x40\x53\xb3\x7a\x63\x31\xe4\x94\xe2\x1e\x02\xf7\x80\x5c\x74\x0d\xd5\xea\x91\xe4\x84\x28\x91\xd4\x9a\xec\xe5\xb1\x82\x59\x1c\xf5\x75\x29\xab\xc3\x6e\xc8\x8e\x81\x33\x60\xdd\x7a\x71\x64\xc3\xac\x2d\x75\x17\xc0\xba\xaf\x3e\x96\xed\xcb\xef\x54\x27\xfb\xec\x2e\xf7\x04\xc3\x27\xb4\xf6\xac\x1c\x17\x3d\x75\xd4\x3b\xef\xc0\x77\x8e\xef\x40\x2f\x55\x17\x5d\x32\x23\x35\xf7\xdc\x6a\x74\x73\x71\x32\xd7\x9d\x84\x33\x22\x9c\x3f\xc6\xad\x24\xa4\x58\x5d\x36\xfc\x2a\xd8\x14\x64\x6b\x22\xc6\x68\xef\x4a\xda\xa8\x3f\xb6\x89\x49\x20\x02\x0b\xd9\xe9\x43\x36\xd2\x2c\x4f\xf2\xd4\x39\x53\x2b\xf4\x8a\xb2\x8a\xad\x0f\xff\x87\x4f\xb9\xf5\xdd\x43\xcc\x9c\x1d\x8f\xfd\x72\xc4\xf4\xf7\xde\xe0\x64\x08\x20\x73\xe4\x0b\x61\xea\x51\xc4\xaa\xf2\x31\x72\x8e\xb5\x4c\x2d\xfc\x94\x5d\xf5\xe3\xb1\x6d\x32\x2f\x92\xaf\x4d\x5d\x5e\x67\xf6\xf4\x81\xdb\xc0\xde\x46\xc3\x07\x05\x00\x80\x04\x46\x82\xb8\x15\xd7\xd3\x9e\x48\x92\x31\x4d\x46\x26\xc1\xd4\x5c\xba\x25\x6b\x14\xb8\x78\xb7\x11\x80\x08\xc6\x23\xc9\x48\x22\x7d\x6e\xe0\xc4\x8e\x91\xcd\x23\x71\xa1\x3a\xaa\x5a\xe8\x47\x56\x1f\x18\x39\x62\xe1\x88\x33\xe7\x3d\x53\xbd\xe9\xb1\xbb\x66\x8c\x36\xde\x0e\x4c\x2b\xaf\xb3\xdd\x33\xbe\x71\xcd\x95\xd7\x07\x30\x5d\x6b\x98\x56\xe6\x43\x72\x17\xa2\x12\x98\x90\x3a\x8e\x54\xf8\xce\x37\xb1\x95\x58\x02\x90\x62\x21\xed\x02\x6f\xa5\xca\x86\xbd\x2d\x51\xc1\x03\xd7\xc0\xcd\x07\x9e\xfd\x6e\x7a\x7e\xa9\x78\xda\x5a\x6e\xdf\x91\xee\x3b\xe0\xa6\x25\x17\x78\xea\xce\x22\x4f\x99\xd8\xc1\x1c\x62\x6b\xf9\x17\x81\xd3\xc4\x72\x3d\x8f\xa2\x42\xa5\x62\x72\x3e\x29\x78\x22\x49\x8f\x49\x65\x90\xf0\xcf\xf4\xa3\x74\xbf\x3f\x29\x50\x6f\x50\x80\xdd\x9a\x4b\x92\x35\x96\xd0\xec\xb1\x53\xc7\xe0\x93\x52\xa0\x3c\x43\x52\x97\xc9\xcd\xf4\x88\x4e\x32\xa1\x77\xc7\x1f\x9e\x5c\xb3\x61\xfe\x13\x57\xdc\x74\xf3\x5b\x53\x47\x4e\x9f\x74\xda\xb9\xb0\x76\x39\x67\x7f\xf9\xdb\xad\x1b\x6f\x78\xeb\x92\x6d\xd7\x2d\xfd\xf5\xb5\x8b\x13\xc6\xad\xcc\x3e\x13\xbb\x76\x16\x17\x4d\xe5\x46\xcd\x90\x8d\x7a\xfd\xb0\x92\x7e\x81\x81\x9b\xbf\xdb\x6f\x5c\x0e\x6b\x61\x60\xfd\x77\xaf\x1b\x4b\xff\x0d\xa7\xc0\xb6\x8b\x0d\x55\x36\x1a\xef\xed\x7b\x0b\x38\x30\x1f\x00\xa1\x95\xf0\xd2\x0d\x82\xa0\x14\xcc\xa5\x9d\x76\x14\x30\x11\x7d\x9c\x6a\x32\x58\xe0\x80\x2e\x05\x79\xd5\x64\x90\x50\x8e\xfc\x4d\xf1\x82\x20\x56\xe7\x02\x09\x87\x94\xb2\x4c\xde\x87\x4c\xde\xc7\xa1\xc5\x4d\xe6\x1a\xb0\x40\x92\xe3\xac\x58\x4c\x3b\xe0\x7d\x92\x60\xa1\x0a\x2b\x4d\xc4\x15\x4b\x38\x5a\xad\x8e\x84\x6e\x38\x3f\x43\x3c\x79\xdc\xc8\x43\xc7\x5f\x82\xbb\x4a\xe1\x41\xc8\x5d\xb3\x22\xbc\xa2\xec\xeb\xd0\x2d\x4f\x9d\x92\xe7\x3a\x35\x53\x70\xc7\x3f\xe7\x3b\x8e\xb5\x6e\x7f\x8a\xa9\xeb\x79\xf3\x89\xbb\xee\x7a\xe2\xf3\x56\xdf\x24\x00\x58\x42\xd7\x7d\x26\x5d\x35\xe0\x66\x10\xaf\x01\x64\x3d\x5d\xab\x72\xea\x69\xca\x4a\xf2\x31\x65\x5a\x09\x0e\x4b\xb5\x19\x54\x20\x96\xf6\xf9\x43\x94\xa6\x41\xd9\x34\x21\xbf\xb4\x9b\x71\x7a\x0a\x4b\xaa\x70\x2a\x14\x92\xe3\xae\xea\x1a\x42\x6a\x55\x0d\x1d\xe1\xe4\x4b\x49\xce\xcf\x16\x84\xf0\xaf\x4b\x64\x54\x18\x43\x50\xd2\x2c\xf6\x9c\x0c\x18\x20\xac\x9d\xc8\x08\xc6\x39\x40\xa4\x3b\x91\x1b\x30\x67\xe8\xe3\xc0\x3a\x00\x84\xf5\x24\xee\xd5\x82\x21\xe0\x14\xf0\x0c\x45\x23\x42\x4d\x6a\xbc\x9a\x01\x4a\x66\x28\x4c\x0e\x69\xae\x0a\xb8\x14\x54\xaf\x26\x87\x50\xa1\x37\x34\xc5\x9b\x87\x60\xa1\x37\x0f\xb6\x29\xc9\x30\x8b\x7f\x8d\xeb\x29\xfc\x87\x1d\x76\xf2\x5d\x2a\x62\x0e\xfb\x41\x11\xf3\xd4\x13\x23\x66\xb8\x59\x92\x91\x12\x43\xac\xa4\x81\xa1\x31\x82\x75\x48\x23\xa7\x64\x46\x4e\x99\x44\xce\x1f\x1a\x33\xbd\xb9\x54\x6c\xdd\x49\x02\xe9\x2a\xaa\x72\x0b\x4f\x54\xb9\x93\x84\xd8\x9e\x27\x72\x69\x20\x9d\xe7\x5f\xc3\x72\x5c\x1b\xc8\x07\x15\xe0\x72\x10\x2f\x82\x40\x49\x96\x53\x00\x8b\xbc\x88\x26\xe2\x4a\xa1\x32\x73\xd9\x20\x48\x91\x46\x4b\xa9\x47\xb6\xd2\xb5\x6e\x02\x5f\xe1\x96\xe4\x24\xef\xe0\x44\xb2\x02\x6c\x95\xe2\xde\x22\xb2\x4a\x57\x2a\x23\x5f\xc6\x7a\x64\xb9\x14\x07\x16\x2f\x31\x34\xcb\x10\x02\x50\x11\x0d\x11\xb8\x0a\x3a\x85\x0b\x90\xc5\xc8\x0c\xd7\x3e\x26\x76\xf9\x4d\x6d\xe3\xfd\x90\x29\xb8\xec\xfa\x6b\xc7\xae\x6b\x5a\xb6\x65\xce\x07\x1f\x69\xbf\x87\x9f\x2d\x39\x8f\x76\x52\x87\x4d\x5b\xd7\x7e\xde\xc8\xf9\x33\xb6\x24\xce\x39\x7b\x46\xf4\xaa\xb2\x31\x1f\xac\xfa\x1f\xee\xca\x19\x97\xa5\xfb\xaa\x2c\xc5\x3e\xb0\xb4\x13\xec\x83\x7c\x1c\x0b\x06\x44\x3f\x08\xa6\xd1\x0f\x0a\x52\xf6\xc4\xf8\xe8\x76\xc1\x80\x08\x08\x6c\x6a\xa3\x3a\x37\x14\xc2\x66\x73\xcd\xba\x3f\x24\x02\xbb\xca\x5c\xbb\x26\xe7\xe3\x9d\x3f\xf9\x7c\xde\xfc\x93\x9f\xcf\x9b\xca\x94\x72\x9f\xaf\xd9\x4c\x9f\xfa\x9f\x8f\x69\xed\x4b\xa7\x4c\x1e\xbe\x4d\xce\x98\x07\x4a\xc0\x69\xfd\xcf\x18\xe8\x3b\x63\x69\xfa\x8c\x65\xe6\x19\x13\x8c\x4b\xf6\x91\x0a\x1c\x06\x24\xec\x6b\xfa\x0e\xe9\x6d\xc6\x0a\x50\x02\x03\xfe\x70\x55\xb5\x60\x61\x73\xa0\x4a\x7c\x3a\x32\x39\x04\x4e\xcb\x5b\xd4\xf4\xca\xc8\x0b\x2f\x59\x7d\x67\x7f\x88\x09\x41\x09\xc6\x92\xa3\x5b\xb4\xf1\xc1\xe6\xf6\x99\x53\xbb\x9b\xd3\x80\x13\x94\xaf\x82\x65\x1e\xb0\x80\x62\x50\x09\x7e\xde\xff\xcc\x25\xa9\x33\x23\x7f\x04\x59\x55\xcd\xe3\xd4\x13\x05\x1e\xbf\x95\x2c\x00\x23\xb9\x89\xa4\xd5\xd6\xae\x64\x31\xcd\x7d\x8a\x45\x8d\xc3\x04\xb9\xf4\x84\xcc\x72\x56\x25\xe9\xa5\x89\x0f\xce\xaa\x8b\xad\x74\x83\x94\x93\x76\x43\xde\x9e\x5f\x4a\x90\xa5\x64\x39\xce\x98\xab\x29\xb0\x44\x92\x51\x79\x26\xdd\xb2\xda\x54\xc2\x60\x8d\x57\x99\x70\x79\x3d\x43\x77\xa5\x4e\x24\xfe\xf8\xb0\xbf\x34\x4e\x1e\x7d\x4a\x69\x79\x43\xde\xae\xd1\x1f\x34\x4e\x3c\x6d\x58\xa8\xb4\xd1\xbd\xf6\x04\x26\xd4\xc2\xe6\x50\x75\x99\x1a\x35\xf6\x87\xaa\x43\x43\xd5\xee\x68\x1f\xee\x06\x47\x64\xb7\xd3\x32\x83\xe8\x57\x10\x84\xc1\xf5\x03\x6a\x18\xca\x8f\xa0\x72\x55\xf3\x3a\x74\x54\xdc\x44\xb6\xba\xc5\x2e\xcd\xef\xd2\x91\x5f\x24\x1a\x57\xea\xd2\x51\xa9\x88\xd8\xb2\x2e\x89\x4c\xdf\x39\xb2\x46\x49\x16\xbd\xfd\xa2\x24\xc7\xed\x90\xdc\xeb\xe5\x24\x8d\xb7\xc5\x62\x04\x23\x2c\xce\x14\x97\x7f\x8f\x01\xe5\x68\xb1\xe5\xd6\xd5\xad\xfd\xfa\x6e\xfd\x55\xf6\xdd\xac\x3e\x9c\x69\xf7\x6e\x20\x12\xef\xd6\x6e\x52\xed\x54\x91\x27\xa2\x49\x0e\x1d\x95\x47\x92\x82\x19\x0e\x2a\xc9\xe5\x95\x20\x95\x74\x90\x00\xf3\x98\x39\x6f\xc2\x51\xea\x72\x2b\x64\x67\x8c\xb8\x39\x36\xb5\x0a\xb6\x5b\x70\xcb\x79\x45\xe5\x15\x81\x98\x66\x2b\x35\x67\xfb\xe5\x92\x24\xef\x66\x6d\xd0\xe1\xa7\xa8\x51\x61\x98\x82\x22\xf5\x59\xb2\x8d\x32\xa3\xb2\x5e\xc9\x7c\x59\xb9\x7e\xd9\x92\x5f\x8c\xda\xd4\x9f\xde\x68\x63\xc3\xa0\x96\x96\x41\x83\xa2\xfc\xf6\xe6\xe9\x97\xad\x59\x73\xe9\xc5\xa3\x8e\xad\x4b\x51\xbc\xfe\x9e\xad\x8b\x99\xd3\xea\x54\xb5\xae\x4e\x55\x81\x89\xf1\x62\x59\x4a\xf0\x55\xbc\xe0\x14\xda\xab\x21\xf3\xb2\x14\x28\x86\x97\xd5\x11\xdb\x94\x74\x8b\x4e\x2c\x6e\xb7\x43\x4f\xf2\x56\x67\x1a\x22\xc3\x17\x31\x5b\x9e\xe1\x0c\x88\x0b\x2c\x29\x18\xf2\x86\x57\xb2\xf7\x70\x53\x53\x50\x17\xe5\x67\x32\xa0\xa5\xfb\x40\xab\x31\xe3\x20\x5c\x0d\x87\xaf\x9e\xda\x07\x7b\x41\x0f\xc7\xcc\x34\xef\xd3\xfa\x4c\xac\x13\x05\xac\xa3\x37\x19\xcc\x2e\x50\x1a\xf0\x04\xd5\x46\xcc\x16\x52\x0a\xfa\x64\x70\x0a\xfa\x04\x79\x08\x44\x59\xb2\x8a\x26\x38\x75\xe6\x46\x90\x56\xa0\x10\x48\xb2\x44\x51\xa8\xbc\x16\x9b\x59\x95\x9c\x08\xc8\xe1\x0a\xe2\x5f\x02\x45\x92\x9c\x28\x08\x55\xe0\xac\x47\xb3\xd6\x4a\xb2\x06\x3c\x3f\x0c\x2d\xc5\x7b\x42\x86\x3f\x10\x7e\x8a\x9e\x95\xf9\x0f\x84\xa6\xd2\xb3\x37\xbb\x22\x30\xb1\x55\xb8\xfb\x2c\xed\xc0\x01\x7c\xdf\x8f\x58\xe2\x8f\xa4\xef\x51\xfe\xdf\x21\x96\xa4\x6f\xff\x9c\x08\x5d\x62\x5c\x9b\x0a\x54\x69\x61\x5a\xda\x52\x37\x83\xfe\x7f\xe3\xec\x66\x1c\xcb\x71\xf6\x63\xa9\x20\x96\x3e\xbb\xa0\xa4\xc2\x57\xe6\xd9\x0b\xbe\xff\xec\x85\x91\x74\xbd\xff\x7f\x79\xf6\xac\x30\x97\x83\x02\x7b\x56\x94\xcb\xa2\x23\x23\xbc\xf5\xe1\x28\xdd\x67\x99\x01\x1c\xc0\x0f\x4a\xc1\x9d\x27\xa7\x08\xf9\x22\xa8\x44\xd5\x3c\x0e\x1d\x05\x29\x72\xbc\xb3\xcb\x84\xfd\x23\x2b\xc5\x85\x2e\x3d\x63\x4c\xfc\x93\x09\xd6\x0a\xf3\x24\x39\x61\xb1\x3b\x04\x6c\x88\xfd\xa8\xcf\xe1\xe0\x73\xb0\xe0\xc2\x7e\xde\xbd\x8f\x07\x4f\x67\xfa\x75\x86\x62\xa6\x98\xba\x98\x8d\x9a\x92\xa1\x78\xff\x0d\x6a\x4a\xda\x4c\xb2\xe0\x53\x8c\xdf\x9b\x16\x92\x89\xa3\x92\x61\x23\xe4\x5c\xdf\xfe\x7f\xf3\x5c\x6c\xca\x04\xb2\xce\xb5\xce\x54\xfe\xcc\x63\xf5\xa9\xbf\x79\xae\x3f\x9a\xfa\x9f\x7d\xae\x0c\x65\xff\xef\xf8\x95\xa5\xde\xd9\x5c\x9b\x9b\xa5\xd9\xfd\x0e\xd9\x5f\xb7\xc9\x59\x9f\x4c\xeb\xf6\x8a\x8c\xd3\xfe\x18\x45\xfe\x51\xc4\x68\x79\x92\x24\x6b\x0e\x7b\x2c\x86\x0a\xc9\x42\x77\x3f\xe2\x72\x68\x6f\x3f\xbd\xc8\x56\xdc\x2c\x12\xb3\x54\x97\xde\x59\x21\xf8\x5a\x2e\x50\x08\xee\x37\xfb\x18\x4e\x55\x73\x9b\x17\x84\x11\xab\x6a\x01\x56\x4f\x02\xe8\xe0\x5c\x8a\xc6\xe4\xab\x2a\xb9\xec\xef\x2a\x6c\x6a\x22\x4d\x7d\x6f\x57\x0a\xdf\x23\x73\x41\x0b\x39\xeb\x51\xa0\x1e\x39\x45\xcd\xed\x3a\x8a\x02\xa2\xc6\xba\x8e\x22\xa7\x98\x60\x9c\xac\x57\x49\xb8\xf0\x2b\x72\x8b\x89\x7c\x77\xc0\xab\x24\x0a\xf1\x2b\xbb\x87\x61\x9d\x2e\x77\x20\xbf\x30\x6b\x3b\x21\x00\x25\x59\xc3\xf5\x59\x43\xa3\x37\xaa\x7a\x53\xf0\x5c\xa1\x42\x98\x06\xe8\xc2\x95\x6a\x65\xf4\x96\xb5\x7d\x28\x5d\xc6\xf0\x55\x5f\x9a\x40\x5d\x13\xbf\x8a\x7e\xcd\x4c\x37\x98\x05\x69\xbc\x2e\x66\xba\xb1\x8b\x22\x76\x19\xf7\x18\xe9\x38\x28\xf8\x2c\xf3\x80\x08\xaa\xc0\xf3\x39\x51\x5a\x50\x49\x04\x49\xaa\x96\xef\xd4\x13\xe1\xfc\x12\xab\xa2\x79\x9d\x3a\x2a\x6c\x4a\x5d\x8e\x30\xc1\x5b\x24\x9a\x1d\xe0\x94\xad\x2a\x0d\xe5\x82\x0a\x71\x25\x4f\x1f\xb6\x90\xde\xa0\xfa\xbf\x82\x75\x29\xac\x92\xe4\x38\xe7\x2d\xa1\x17\x24\x06\x00\x78\xc9\x95\xdb\x0f\x04\xfa\xf2\xf7\x9c\xf9\xfd\x09\x50\x30\xfd\xf3\x7b\x1a\x07\x08\x36\x8c\xa5\x9d\xe8\x52\x05\x38\x23\x27\x3a\x4c\x65\x2e\x74\x98\x2a\x13\x1d\x26\xc1\x39\x8a\xca\x48\xe2\xf4\x03\x01\x62\xbc\xe9\x5a\xf7\x64\x48\x31\xcf\x9b\x7e\xf2\x7b\x10\x63\xb8\x8d\xe9\x8b\xc7\xfd\x69\x99\xfa\xe3\x69\x49\x72\x8e\xa2\xd2\x0a\xf3\x4a\x66\x59\xe8\x47\xa0\xde\xa4\x13\x8b\x93\x12\x05\x47\x9a\x6e\xf6\x7b\xa8\x62\xcf\xcd\xac\x9b\xb3\xe8\x1a\x04\xa6\xe5\xa4\x4b\xc9\x45\xd7\xe0\x0c\xba\xca\xaa\x28\x5d\xf1\x50\x45\x65\xec\x47\x50\xd6\xaf\xba\x3e\x29\x7d\xa3\xb2\xdc\xf4\xf7\x13\x99\xe5\xb9\x53\x74\xce\x23\x74\x36\x82\x1b\x73\xd0\x89\x6a\x23\xa8\x48\xd5\xc2\x4e\x3d\x51\x1f\xae\xb5\x92\x96\x26\xaa\x6a\x82\xa8\x29\x93\xfc\x22\xa8\x24\x1b\xa9\x4d\x37\xa6\x99\x91\xa8\xb2\xf8\xad\x4a\xb2\x9a\x1a\xb5\x0a\x15\xad\xb1\x48\x92\x35\xc9\x41\x1a\x9d\x49\x2e\xbf\x24\x5c\xfb\xa3\xd4\x38\x87\x85\x9e\x94\x39\x33\x72\x9a\xe9\xf7\x31\xe9\x9c\x13\x8c\x96\x33\xf9\x34\x83\xf0\xa9\x12\x44\xc0\x92\x5c\x9c\xaa\x88\xa0\x7a\x55\x2b\x75\xe8\xa8\xb6\x09\xa2\x86\x7e\xfc\xd1\x42\x2e\x1d\x85\xd2\xcc\x41\x55\xb8\x1a\x57\x5c\xba\xd6\x88\x7f\x57\x24\xc9\x71\x47\x3e\x99\x26\x55\x49\x88\xfb\x11\x4c\xc9\x55\x86\x9f\x8c\x29\x3b\xb3\xc3\xde\xf7\x71\xe3\x6f\x59\x91\x90\xcc\x48\xa0\x93\x13\xb9\x7b\x80\x03\x00\x6f\xd4\x06\x03\x36\x68\xb1\xc1\x6a\xb8\x66\x3b\xac\x83\x8d\x77\x1b\x07\x60\xdd\x9d\xc6\x01\xe3\xed\x6d\xb0\x96\x03\xf7\x18\xef\x40\x65\x9b\x71\xc0\x78\x6b\x3b\xac\x33\xde\xd9\x0e\xeb\xa8\x7d\x2d\xe8\xdd\xc9\xc7\x05\x0e\xf8\x41\x09\xa8\x02\x3f\x33\xef\x45\x84\x58\x9d\xec\x7e\x51\xa8\xa6\x6a\x5c\xdc\xa7\x6e\x84\x55\x9a\xb7\x05\x6a\xa0\xa2\xe5\xb1\x92\x1c\x87\xa4\xc1\x87\x2a\xa5\x84\x45\x0e\x12\x78\x1f\xb7\x1c\xb7\xd9\x9d\xc4\xd0\x42\xb2\x24\xc7\x01\x24\xb7\xea\x0b\xa5\x84\x9b\xcd\xa7\xa6\x28\xc7\x6d\x0e\x27\xe9\x62\x8e\x84\x55\xcd\xa4\xaa\xa4\x6b\x6e\x04\x13\xba\xda\xe2\xf5\x05\x20\xe5\x2a\x65\x71\xf5\x82\x6b\x2e\xc0\xbc\xec\x58\x79\xc9\x5d\xcb\x67\x63\x6e\x26\xaf\xbb\x6c\xa7\x95\x99\x3e\xf6\xbc\xeb\x7f\xff\xb3\xf6\x61\x6d\xd7\xbd\xb1\x8c\x2f\xbe\x6b\xe3\x41\xc2\xc3\x49\x6b\x97\x6f\xb9\xe9\xf7\x84\x8b\x67\x6c\x60\x96\x96\x8d\x65\x0e\x2b\x7b\x8c\x7d\x46\x4b\x65\x1c\x0e\x7f\x7d\x2a\x8e\xa1\x04\xa3\xc7\xd2\x0e\x7c\xa0\x18\xac\xcd\x8d\xd2\x53\x72\x72\x94\x9e\xd2\x1f\x8b\xd2\x93\xb0\xc9\x7e\xd2\xdc\x75\x49\xf1\x40\x90\x5e\x9d\x3e\x39\x64\x4f\x3a\x8f\x1e\x00\xbb\x27\x61\x06\x8a\xdc\x20\x3e\xc2\xe6\x74\x7c\xc8\xa6\xf7\xe6\xff\x37\xf4\x12\x54\x22\x4c\xac\x3f\x9f\xe0\xef\xb8\x53\x8f\x64\xf8\x3e\xa2\xcd\x70\x92\x9b\x68\x66\x91\x19\x47\x72\x13\xcd\xcf\xe9\xab\x5b\xfb\x68\x0e\x83\x5b\x73\xd3\x5c\x71\x72\x9a\x2b\xff\x0b\x19\x27\x82\x05\xb4\x8f\xe9\xa6\x3b\x01\xdf\x4f\x77\x56\xb0\x19\x40\xe4\x53\xb2\xc2\xcc\x80\x3c\x38\xa1\xe6\xa5\xbc\x98\x01\x7c\xa0\x04\xd4\x80\x07\x73\x71\x03\x15\x47\x50\xb5\xaa\xe5\x3b\x74\x54\xde\x44\x86\x65\xb9\x58\x83\xbd\xa6\xf9\xa0\x00\x93\x4b\x89\x0a\xb7\xcb\x6a\xf6\x36\x23\x5a\x85\x4b\xd7\x06\xfd\x28\xb6\xb1\x3f\x10\xc0\x2a\x57\x21\x31\x00\x97\x9e\xcb\x76\xad\x03\xb0\x49\xef\x57\x5b\x10\x3c\x24\x4b\x3b\xb0\x02\x09\x2c\xcb\x81\x88\x24\x9f\x0c\x11\xc9\xfb\x23\x10\x91\x34\x01\xa6\x67\xe5\x27\x60\x23\x15\xa6\x0d\x20\x1b\x24\xe9\xe9\x74\x8f\xa6\x0f\x2c\x89\xed\xee\x4b\x96\x68\x9f\xe6\x09\x82\xfd\xe9\x03\x5b\xd2\xdd\xda\x14\xfa\x4e\xd2\xe1\x22\x3d\x0d\x07\xab\x27\x59\x1f\x79\xcb\xd2\x66\x13\x92\x28\x50\x69\x5e\x7f\xd0\xba\x7a\xc4\x90\x36\x86\x93\x3b\x8a\x18\xda\xc6\xc8\xc6\x03\x4d\xb8\xc8\xab\x0f\xbf\xb2\x7b\x00\x64\x58\x87\xd3\xe5\xcb\xaa\x88\x7c\x2e\xb3\x77\xa8\xc2\x90\x45\xcd\x06\x17\xa4\xf0\x74\x4d\x4d\xd3\x0f\x1f\x31\x7e\x6d\xbc\xb7\x7e\xc4\xf2\x4b\x6e\x7d\xf4\xc5\x95\x7c\xc7\xa7\xef\xbc\xf3\x8d\xf1\x2f\xe3\x20\x13\x5e\xbf\x3c\x89\x63\x9d\xd1\x6d\xf8\x78\x9f\x50\x0a\x4e\x01\x4f\x98\xcf\xdc\x28\x15\x74\x34\x94\xc2\x01\x34\x46\x34\xab\x4d\x27\x43\xc9\x9a\x34\xa6\x60\x3d\x54\x34\x87\xa8\xa3\x72\x2c\xa8\x80\x47\xd7\x4e\x35\xc9\xfb\xd5\xe1\x63\x19\x8f\xaa\xd1\x9a\x5d\x47\xd1\x90\x4e\x90\xe0\xf8\x21\xcd\xb4\xb8\x4d\xbd\x23\xa2\x2a\xaf\x91\xe4\xa4\xb5\xb4\x60\x70\x63\x45\x20\xa6\x05\xea\x25\x39\xee\xf1\xd1\xb1\x37\x33\x54\x92\xd1\x29\x31\x54\x20\x21\x40\x06\x75\x45\x31\xd4\x28\xc5\x1d\x01\x3a\x08\xa7\x10\x02\x2d\x15\xe6\xc4\x92\x2c\xe8\xa7\xee\x30\x56\xf7\xdb\xf4\x4d\x3f\x89\x86\xa5\x38\xaf\xdd\xc3\x5b\xd6\x55\x1a\x11\xe8\x3e\xf6\x87\xef\x2e\x58\x33\xa1\x7e\x70\x6c\xf1\xc4\xff\x74\x3d\x77\xf9\x0d\x37\x5e\xd4\xd6\x3c\xad\x6d\xdc\xac\xe5\xa3\x27\x9f\x79\xce\xbc\xab\x83\x86\xf2\x87\x27\x67\x8d\xfb\xd8\x1f\xe7\xf6\x7c\xf4\x46\x72\xdb\xcf\xee\x6b\x1d\xd4\x5c\x14\x68\x56\xce\x5e\x7f\xf6\xce\xdf\x0d\xff\xe7\x94\xd1\xcd\x35\xe3\x46\x8c\xbf\x72\xcc\xf4\x6b\x47\x57\x4e\x89\x8d\x98\x70\xf1\xd5\xc7\x87\xbf\xb2\x3b\x48\x7c\x02\xc1\x2a\x12\x42\x04\xab\xa8\xf6\xa4\x68\x45\x83\xd2\x68\x45\xca\x4f\x46\x2b\x4a\xd7\x3e\x27\x87\x2d\x6a\x48\xc5\xb4\x01\xe0\x8b\x38\x5b\x6a\xee\xf7\xff\xfc\xfc\xa6\x59\x9e\xfc\xfc\xfb\x53\xe1\x69\x80\xf3\x33\x5d\x59\xf5\x4d\x1f\x0d\x21\x10\x01\xe3\x73\xd3\x30\x18\xd3\x40\xd3\xd8\x72\x0f\xcd\x53\xcb\x81\x24\x9b\xc8\x39\x83\x4d\x6a\x2a\x4f\x4e\x4d\xff\x51\xe1\xf7\x40\x49\x7d\x90\x15\x68\xd6\x0d\x84\x2b\xc5\xe5\x67\x8d\x0f\x3b\xfa\x60\xa6\x52\xb4\xb9\x81\x0c\x6a\x40\x0b\xb8\x21\x37\x6d\xaa\x4d\x47\x65\x11\xe4\x55\xb5\x02\xa7\x9e\xa8\x2c\x28\xb3\x2a\x9a\xdf\x49\xe7\x67\x51\x42\x72\xad\x47\x4f\x78\x6b\x81\x55\x49\xd6\xd0\xc2\xa6\x96\xe0\x3a\x24\x4b\x68\x39\x33\x14\x2a\x5a\x4d\x2d\xdd\xca\x28\x96\x4e\x73\x70\x36\x87\xd3\xed\x77\x95\x0d\x6e\xa0\x8b\xdc\x9c\xda\x07\x24\x74\x02\x4f\x72\x8d\x11\xbf\x87\x31\xdf\xe4\xac\x65\xda\x07\x64\x50\x5e\xbf\xd1\xe2\xd3\x19\x48\x5c\x9c\xc9\x23\x8e\xe8\xf0\x20\x30\x04\x6c\x1c\x50\x8b\x71\x40\x56\x55\xad\xc2\xa1\xa3\xfa\x26\x88\x9a\x53\x2a\x8d\xbc\x22\xd9\xc8\x31\x11\x2f\x14\xa8\xa0\x82\x26\xad\xc1\xa5\x6b\x2d\xb8\x9e\xf1\x52\xce\x54\x49\x71\xae\x38\x0f\xa7\x61\x8a\x1c\x77\xba\xc9\x98\xb1\x41\x8a\x5b\x6c\x0e\xe2\xca\x7e\x9a\x45\xe4\x08\xc8\x27\x37\x0e\x7f\xbf\xb8\x3c\x80\x8d\xb0\x17\xf6\xab\x75\x52\x7c\x8a\x13\x3e\x0d\x06\x43\xc1\xb6\x81\xf9\x34\x28\x92\x6c\xa0\xfb\x2c\x2d\x91\x64\x85\x39\xa0\x8c\xf5\x63\x57\x6a\x65\xda\xbc\xd2\x61\x96\xc6\xa7\x64\x70\xac\x4e\x8a\xe7\x15\x73\x98\x4f\xaa\xbc\xdb\xe9\x76\x55\x0c\x2a\xc0\xcc\xa9\xee\x63\x1a\x57\x4c\x34\x4b\x6b\x69\x90\x64\xad\x3a\x14\xfb\xc1\x3c\x33\x77\x33\x32\xd7\x83\x4f\xce\xb7\xeb\x37\x2c\xbd\xfc\x17\xb7\xfe\xec\xf2\x8d\xdb\x1b\x1a\x06\x45\xa3\x83\x06\xb5\x0c\xc8\xba\x17\x96\xdc\x70\xe3\x25\x8b\xd7\xad\x5e\x5a\x37\x64\x08\x99\x6c\x12\x3b\x14\x5e\xe5\xda\xc1\x60\x70\x0a\x38\x1d\x3c\x0d\xe2\x95\x98\x69\x65\x38\x3d\x18\xa4\x6a\x05\x16\x9d\x32\xd0\x0d\x81\x82\x38\x55\x1b\xc5\xeb\xe4\xbd\x16\xb5\xe9\x49\xdf\xb0\x32\xb7\x4b\xd1\x7c\x4e\x1d\xa2\x31\x84\x87\x75\x1e\x1d\x73\xad\x12\x2a\xc9\x0a\xba\xef\x53\x21\x6a\x23\xcd\x07\xb1\x8c\x85\x8a\x56\x59\x27\xc9\x09\x6e\x50\x43\x14\xb3\xab\x42\x4a\x5a\x2d\x55\xd5\x43\xf0\xfb\x91\x72\x87\xcd\xed\xcf\x2b\x28\x1b\x46\x40\x60\x25\x33\x2d\xf6\x55\x4a\xf2\x1e\x50\x5c\x12\xae\xaa\xae\x6b\xc0\x41\x36\x3a\x4c\x92\xe3\xd2\x90\x91\xb1\x58\x4c\x73\x8f\xc2\xc5\xb7\xa3\x1f\x6f\x2d\xe6\x22\x55\x7f\x48\xb0\x6a\x4b\x1f\xf8\x59\x26\xd7\x2b\xd3\x50\x61\x1b\xf4\xdb\xe6\x5e\xaf\x3a\x62\x7b\xe5\xc1\x77\xcf\xb9\x3f\x61\xc4\x8d\xfd\x43\x98\xa5\x8b\x46\xef\x9a\x94\xe8\x58\xb2\x29\x22\xee\x75\xdb\x5b\xef\x98\x79\xfb\xc3\xb0\x71\xd4\x29\xe3\x57\x4d\x18\x3d\x76\xcc\xd5\xe3\x98\xc7\x4c\x24\xb1\x35\xbf\x83\xe7\xef\x9f\x78\xde\xe6\x59\x8d\x23\x1e\xdf\xf8\xdc\x7e\xaf\x77\xde\xc5\xf5\x35\x9f\xcc\x68\x39\xb5\x6d\xcb\x9c\x09\xff\xfb\xda\xf4\x39\xb7\x7c\xb9\x72\xea\xbc\x8d\xfa\x4a\x13\x5e\x8c\xe2\x5b\x98\x58\x74\x0a\xf6\x80\x59\x33\x5c\x13\x90\xae\x6f\x86\x9b\x9a\xde\xba\x3d\xa4\x57\xd1\x6f\x7a\xeb\x06\x92\x9c\x2c\x30\xc7\xb6\x5a\x55\x89\x24\x27\xa4\x80\x39\xb8\x2d\xaa\xa5\x5b\x55\x01\x29\x3d\xbe\xb5\x97\xe3\xd2\xdb\xe2\xa7\x0b\x05\xdf\x03\x68\x77\xe2\xf8\x76\x00\x88\xbb\xb6\xac\xe9\x6d\x2e\xc0\x3b\x43\xcc\x9e\xdc\xd2\x38\x30\x5a\x08\x11\xdc\xb8\x41\x60\x69\x7f\xe4\xb8\x1a\x5e\x4f\xda\xcb\xfb\x90\xe3\x94\x4c\xe4\xb8\x2a\x13\x9c\x65\x30\xf1\x70\x92\xbc\x87\x20\xc7\x15\xd2\x07\x9b\x5a\xa4\x84\xd7\x57\x5c\x42\x38\xd0\x1f\x3f\xae\xa6\xfc\x7b\xf1\xe3\x52\x09\x09\xfb\x3d\x40\x72\x93\xcd\x94\xa4\x74\x40\x40\x39\x7e\x04\x4d\x4a\xba\x3b\xa9\xe4\xbf\x97\xe6\xfe\x68\x79\x4a\x0e\xb4\x3c\x54\xd5\x44\xc8\x2e\x4e\x93\x5d\x5e\x39\xe8\xff\x0a\x33\xaf\x2f\x9b\x39\x29\x78\xde\xa4\x54\x36\x33\x10\x88\x1e\xfc\x30\x95\xce\x50\x9a\x27\x13\x9a\xab\x41\x03\x58\xd1\x9f\xe6\x7a\x4c\x73\x4d\x1f\xcd\x8d\x99\x34\x0f\x36\xe5\xdc\x04\x15\xcd\x05\xcc\xa7\x37\xa2\xc1\x12\x21\xbc\xb8\xb2\xba\x86\xb6\x8d\x12\x5e\x5f\x49\x38\xa7\xbc\xeb\x6b\xbe\x8f\xf6\xfe\x09\xd0\xc9\xa5\xfe\x7a\x56\xfe\x73\xd6\x80\xa2\xe7\x1c\x99\x09\x50\xcf\x53\x44\x01\x38\x53\xfe\x1c\xc8\x07\xe5\x40\x01\xcd\xb8\x1e\xcb\xe6\x46\x2d\xe6\x46\x38\xc5\x0d\x14\x8a\xa0\x21\xaa\x56\xe4\xd0\x51\xa4\x89\xdc\xf1\x09\x76\x69\x25\x2e\x3d\xe1\x2a\x09\xf6\x41\xae\x61\x5e\x95\x88\x64\x63\x0a\xeb\xc7\x60\x5c\xd9\x34\xba\x74\x72\xb1\xa7\x24\x28\xc9\x09\x87\x98\x47\x5a\x0e\x83\x25\x8d\xab\x8d\xc5\x50\xa3\xac\xf9\xbc\xe4\x91\x7d\x04\xcc\x08\xf3\xa9\x36\xfc\xbd\x3a\x92\x0e\xe6\xde\xf4\xd2\x72\x5f\x7c\xcf\xad\x2e\x55\x34\xa0\x0f\x36\xd9\x34\xcc\x8c\xef\x39\xd8\xb5\x9d\x04\xf5\x9e\xcd\x98\x4f\xcc\x65\x99\x73\x3d\xe6\x74\x21\x04\x58\xe0\x04\x73\x4e\xc0\xa2\x23\x4f\xad\xa0\x20\x74\xc8\xda\x74\x02\x0e\x5d\xfa\xf1\x15\x59\xd8\x73\x90\x00\x61\xf0\xb1\x18\x45\xa1\x13\xec\x7d\x28\x74\x29\xcb\x27\x18\x74\xcf\x98\xe6\xcd\xb5\x1d\xdf\x91\x01\xe6\x4a\xce\xc4\x4e\x35\xcf\x74\xee\xc9\xce\xf4\x03\x0f\xc4\x42\xf3\x40\x88\x91\x34\x8b\x33\xe3\x38\xa6\x2d\x92\xe3\x44\x52\xf7\x31\xda\x8e\xef\xc8\xbc\x93\xc1\x80\x0a\x00\x58\x6c\x5f\x38\xa3\x9e\x63\x3e\xfd\x49\x56\xe3\x22\x3e\x8f\xa4\x92\xe7\xc7\x89\x64\xa4\x9b\x90\x25\xd1\xaa\x50\x60\x39\x72\xe5\x5f\x76\xe9\x9a\x2f\xd7\x91\x44\x0f\xbd\x4d\x2d\x4b\x88\x23\xb8\xec\x4e\xb2\x4c\xdf\xcf\x52\xbc\x21\xb6\x22\xcb\x1c\xde\xc3\x07\xe5\xde\xcf\xd4\xfc\xe3\xd5\xf8\xc0\xa4\xa6\xc1\x7c\xab\x10\x38\xc0\x02\x17\x08\x60\xdf\xd7\x1f\x59\xd0\x19\x41\x79\xaa\x66\x71\xe8\x48\x22\xe8\x03\x29\xd1\x12\x2c\x41\x9b\x4b\x47\x36\x73\x47\xae\x8f\xa3\x09\x37\x61\xb1\xd7\xa5\x93\x15\xda\x13\x81\x06\x21\x7d\xb6\x6c\x06\xcc\x60\xbf\xcc\x94\x30\xf7\xf9\xec\x04\x94\xc0\x0e\x2e\xcc\x4e\x36\x19\x30\xbe\xf7\x10\xb7\x4e\x28\x05\xc5\x40\x01\xb3\xcd\x27\xfd\x84\x04\xf2\x70\x47\x4e\xd0\x53\x41\xba\x84\x1a\x63\x25\x54\xb4\x80\xa8\x93\x08\x5d\x59\x22\xc9\xbb\x6d\x9c\xc3\x53\xe8\xc4\x56\x18\x90\x92\x82\x24\x5b\xe8\xea\x66\x4d\x88\xde\x14\xe2\xa4\xb8\x60\x31\xb1\x62\xe8\x33\xd0\xd4\x2a\x72\xa7\xbb\x3a\x9a\x17\x88\x06\xc8\xed\xde\xbe\xe7\xf8\xa6\x33\x98\xf1\x6b\xbe\xb8\x73\xd7\x2c\xbb\x6f\xfe\xe7\x33\x7f\x57\x35\xe3\xaa\x8d\x6d\x5f\x4d\xea\x3c\xeb\xb4\x5b\x8c\x6f\x7f\xf3\xde\x5f\x61\x64\xca\xc4\xd1\xcb\x46\x4d\x1e\x37\xe1\x67\x23\xe1\xb6\x47\xa1\xb8\x7d\xd5\x81\xb6\xb5\x77\x5c\x51\x35\xe8\xb9\x91\x93\x7f\xbe\x7d\xf1\xa5\x47\xb7\x1d\x35\xb6\xbc\xfa\x67\xed\xac\xd9\x4b\x9f\x5d\x30\x79\xf6\xa5\x49\x90\xd2\x6f\xee\x29\xc1\x0d\xf2\xc0\x60\xf0\x5e\x4e\x34\x38\x54\x11\x41\x01\x55\x2b\x71\xea\x89\xda\x92\x0a\x2b\xbd\x22\x17\x6a\x22\x68\xa0\x7d\x20\x71\x01\xa8\x24\x07\xd3\x74\x7a\xf0\xc0\x90\x71\x58\xa8\xe5\x26\x5a\x8a\x83\xa2\xa5\x94\x67\x3f\xad\xff\x07\x61\xc9\x0d\x0e\x48\x72\x9c\xe1\x58\x72\xdd\x47\xd2\x82\xb5\x04\xd9\x7d\xb7\x20\x17\x95\x54\x54\xd3\x25\xd9\x1f\x02\x27\x97\xab\xf2\xcb\x05\x31\x97\x97\xb3\xda\xcb\x01\x3c\xc7\xbd\xdb\x6f\x5a\x45\xe3\xe1\x74\x21\x44\x70\xe8\xca\xfb\x66\xb2\x29\x24\x3a\xf2\xa4\xe7\x70\x26\x04\xa4\xdf\x0c\x82\x15\x50\x21\x58\x1c\x49\xce\x51\x40\x06\xcc\x38\xe4\xd3\x87\x02\x07\xa4\x01\x50\xe9\x80\xbf\xef\x06\x6e\x7a\xa5\x3a\x37\x3c\x5d\x63\xaa\xc5\x92\x89\x52\x07\x4f\x5b\x45\x71\xea\x58\x5b\x1f\x9e\x35\xa5\x61\x51\x9a\x86\xf1\x3f\x8d\x86\xe2\x72\xba\x5d\xf8\x43\xce\xde\x97\x98\xe4\x3c\xfb\xc5\xa9\x84\x24\xe7\xd9\x61\x46\x73\x85\x9e\xfd\x1c\x72\xf6\x22\x50\x83\x2d\x99\x9c\xbd\x34\x75\xf6\x4a\xbb\x9e\xea\x72\x17\xbb\x74\x54\x2c\x12\x78\x62\x1c\x58\xf3\x9a\xc8\x7d\x90\x62\x1c\x40\xdc\x9e\x58\x0c\x85\x25\x22\x0a\x99\x26\x21\x9a\x97\x00\x39\x56\x96\x0e\x40\xce\x09\x9d\x96\x01\xf0\x02\xff\x98\xe5\x53\xaf\xcb\x09\x1e\xc8\x31\x59\xfd\x95\xe7\xfb\xb0\x04\x29\x7d\x37\x08\x6e\xe0\x02\x61\x10\x01\x9b\x4d\xfa\xaa\x52\xf4\x0d\xb6\xeb\xa8\x30\x82\xdc\xaa\xe6\x77\xea\x89\x32\x7f\xa1\x55\xd1\x44\xa7\x8e\xf2\xd3\x33\xd1\x0a\xec\x57\x2b\x80\x95\x40\x1a\x38\x68\x25\x37\xc8\xe4\x81\xc5\xc4\x36\xca\xa7\xbf\xc9\x8f\x98\xdb\xbd\xa4\xfb\x34\x28\x2c\xc9\x1d\x0e\xd1\x5b\xc2\x55\x0d\x36\xd5\xd3\x5f\x48\x7a\x51\x55\x03\xf1\x24\x67\xa7\x65\x00\xc6\x7c\x94\xd3\xe8\x2e\xc8\xcd\x20\xd0\xaf\xbf\x92\x01\xb7\x68\xe6\x61\xd3\x05\x8e\xe8\x6f\x18\xd4\xa5\xe7\xc5\x99\x78\x90\xa8\x3c\x82\x06\xab\x5a\xb1\x43\x47\xd5\x4d\xa9\xc7\xfd\x9a\xf7\x35\xfa\xb6\xb6\x53\x38\x91\xa8\x02\x47\xa6\x5a\xf3\x29\xbf\xa5\x05\x92\x1c\x77\xe4\x89\xd8\x1d\x55\xd0\x79\xf1\x0f\x02\x8e\xcc\xd9\x3b\xc9\x0d\x26\xe9\xec\xd7\x34\xc9\x85\x2d\xc9\x9e\x99\x15\xc4\x58\xb0\x04\x7c\xc0\x55\x72\xaf\x92\xfb\xc3\x85\xa0\x1e\x98\x68\xbe\xa9\x87\xba\x06\x23\x9a\x97\xa3\xd7\x9c\xb9\x2e\x24\x36\x69\x76\xaa\xf6\xc5\xe9\x27\xbc\xf2\x19\x8d\x0a\x29\xe3\xfd\x12\xf6\xe9\x9e\xbb\x5a\x47\x8f\x9e\xd0\x3a\x6a\xd4\xc4\xd6\xd1\xa7\x8f\xc7\x5f\x99\x05\x07\x0f\xfe\x63\xd2\xc4\x29\x13\xc6\x4d\x9b\xc2\x72\x13\x27\x9f\x75\xc6\xb8\xb3\xa6\x10\x1d\x55\x7a\xef\xe1\x16\x72\x5b\x81\x1f\x14\x81\x8a\xf4\x7c\xb9\xcc\xaa\x13\x28\x20\x2d\x68\xd5\xcd\xe5\xf1\x54\x30\xa9\x30\xe7\xcb\x55\xfd\xe6\xcb\x15\x52\xc2\x22\x07\x8a\xfb\xcd\x97\xcb\x32\xe6\xcb\x41\x29\xc1\xba\xf3\x2a\x72\xcc\x97\x87\xf4\xcd\x97\x7d\xe6\x7c\x19\xd2\x6e\x4c\x09\x24\x08\xd5\xca\x8a\xf1\x98\xf7\x6b\xe7\x8d\xdb\x32\x7d\x34\xe6\xff\xca\x85\x4b\x5e\x83\x4b\xc2\xcd\xd3\x56\x8e\x1f\xef\x68\x2c\x98\xb0\x62\x32\x2b\xdc\xb1\xf8\x4e\xcc\xf9\xa1\x33\x2f\xbf\x64\xf1\xdd\x98\xfb\xcd\xeb\x19\x11\xbe\x9c\xff\xb3\xcf\x8d\x4e\xab\xe7\xf2\x8f\xd6\xe1\x98\x4a\x30\xf8\x84\x10\xc8\x03\xa5\xe0\xb2\x9c\x28\x7c\x65\x27\x47\xe1\x0b\x65\xa1\xf0\xc5\x6d\x81\x7c\x7a\xb1\x75\xb7\x28\xc9\xc1\x42\x4a\xff\x8f\x00\xe3\x4b\xa7\xba\x03\xa0\xf2\x0d\x49\xc5\x82\x1c\xf0\x7c\xfc\xca\xbe\xfd\xe5\xff\x63\xba\x28\xba\x20\xa6\x29\x50\x40\x77\x06\xa4\xb8\xa7\xd0\x7c\x60\xd0\x0f\xa3\xcb\x0c\x13\x03\xd0\xf5\x4d\x2a\x4e\xe4\xa0\x8b\x1b\xdf\x37\x23\xee\xa3\xab\x12\x6b\x67\x0e\xba\xaa\x4e\x4e\x57\xb5\x49\x57\xdc\x47\x25\xc5\x49\x9a\xad\x92\x48\x2c\x29\x4a\x72\x21\x9d\x00\x4b\x09\x4f\x51\x29\x05\x0f\xfd\x41\xd4\xf5\x8b\x20\xb9\x69\xfc\x30\x7b\x14\x9c\x9b\xd0\xec\x41\x30\x6b\xd2\xcb\x81\x3c\xd2\x6f\xbe\x29\x07\xc5\xa8\x34\x82\x6a\x55\x02\xf7\x54\xd1\x94\xea\x4c\x9c\x40\x7e\xa0\x0f\x58\xd9\xe4\x04\x0a\x61\xbf\x58\x65\xf6\x6a\x38\xcc\x12\x9b\xaf\x34\x16\x8b\xd1\x9d\x1a\x51\x4e\xed\xd4\xfc\x70\xdd\xcd\xe1\x23\x07\x10\xf7\xc8\x7e\x3e\x32\x17\x33\xde\xe9\x97\xe7\x53\xac\x43\x53\xa7\x73\xa0\x1d\x96\xa5\xd1\x0e\x43\x3f\x05\xed\xb0\x6f\x8f\x61\x60\xd8\x43\xe6\x7a\x53\x4d\x73\xe2\x1f\x0a\xf1\xb4\x9e\x52\xdc\x60\xc1\x07\xfc\x20\x0c\xf6\xd1\xda\x4f\x0b\xda\xb0\x3f\x47\x7e\x15\xc1\x08\x29\x48\xe9\x36\x83\x79\xdf\x28\xe3\x22\x7e\x31\x54\x34\x47\xd6\x3a\xc3\x3e\x7a\x11\x9f\x22\xe7\x3a\x90\x5f\x4c\xb0\x7e\x32\xc9\x25\xaf\xe5\xf8\x35\xee\xf3\x67\x5e\xc4\x2f\x37\x2f\xe2\xfb\xca\xe9\x45\x7c\xf2\x95\x64\xe4\xd0\x4f\x6f\x7b\x33\x52\x92\x17\x3c\xf4\xb1\x0e\xc5\xb2\x66\x2d\x23\xe8\x18\xe6\x55\x70\x28\xc5\xad\x8e\x32\xe2\x91\x59\xfa\xf0\x8f\x96\x8c\x67\x7f\x64\x82\x0a\x57\x51\x54\xe1\x04\xac\x1b\x5d\xac\x5a\xd7\x6e\xdf\xf6\xe8\xc6\xbf\x6e\x88\xcf\x25\xb8\xc2\xa7\x8f\x3f\x63\xe5\xb8\x89\xa3\xcf\xb8\x6a\x82\xe1\xb3\x02\xe3\xcd\xb5\x77\xee\x7c\xe7\xc5\x57\x8d\x3b\xf6\x3e\x9c\x82\x16\xbe\x45\xbf\x6e\xe6\xcc\x1b\xff\x41\x76\xa1\xa9\x7c\x53\xba\xbe\xa2\xbf\x84\x4f\x54\xf4\x40\x17\xd6\xe9\x84\xb5\x28\x60\x35\x93\xa0\x08\x59\x89\x2d\x4a\x4f\x58\x88\x6e\x07\xa8\x2a\x68\x45\x56\x49\x8e\xbb\x0b\x88\x8e\x57\x85\xc8\xd4\xe0\x47\xa8\x47\xae\x6d\x86\x81\x35\x05\x76\x65\x6b\x78\x4e\x85\xb1\x8c\xec\x37\x37\xa1\x77\xb8\x76\x09\x06\xb9\xbb\xe6\x05\x63\x06\xbe\xb9\x26\x46\x34\x89\xa7\x58\x4e\xe6\xf5\x43\x7f\xea\x8a\x3d\xe3\x3d\xf9\xfd\xb3\x68\x68\x80\xbb\x91\xdb\xea\x98\xc5\x75\x27\x5e\x8c\x7c\xfb\xed\x8c\xd9\x27\xbf\x8b\xcc\x74\x2a\xc0\xd8\x81\x27\x3a\xa1\x88\x56\xce\xa7\x17\x58\xbd\x1e\x92\x1d\xfc\xd4\xa1\x55\x34\xf4\x3d\x13\xdc\x20\x3e\xf5\xc0\xe3\x5b\x7c\x7a\xca\xd7\x77\x2d\xab\x08\x5f\x4b\xc0\x86\x81\xf9\x5a\x14\xd1\xf2\x78\x3d\x9e\x47\x40\x05\xf3\x82\x36\x85\xdc\x8c\x2c\x8d\x20\xb1\xcb\xbc\x01\x89\xbc\xe9\x9b\x91\x88\x35\x6f\x52\x07\xe9\x64\x25\x98\xbe\x49\x5d\x06\x15\xcd\x2b\xd2\xbb\x73\x9c\x94\xe4\x6d\xae\xbc\x22\x4c\x76\xf0\x7b\x9e\x2f\xce\x0e\x89\xaa\xb4\xb7\xa7\x32\xa1\xf2\xaa\xdc\x72\x7a\x48\x78\x6a\xc2\x59\x53\x2e\x94\x7e\x13\x35\x9e\xba\xfb\xd7\x27\xdc\xb4\x9d\x55\x55\x34\xea\xd4\x96\x33\x8c\xa7\x6e\xcf\x9c\x59\x2b\x44\x6e\x11\x70\xc7\xc0\x72\xab\x8b\x68\xd5\xbc\x1e\xaf\xae\xc3\xb4\x57\x0f\xb2\x29\x28\x9c\xae\x3d\x32\x46\x71\x15\x99\xc5\x47\x52\xa1\x04\x37\x66\x8c\xe2\x2a\x24\x6c\x51\x83\xe4\x3d\x9c\xd5\xe9\x76\x15\x17\xd4\x61\xca\x15\x49\x73\xd8\xfe\x8b\xd9\x65\x16\x5f\x4e\xae\x11\x72\x16\x7f\x06\x1c\xbd\x7d\x96\xcd\xa7\xde\x75\x86\x2f\xfd\xcc\xf8\x10\x58\x99\x7a\x8e\xad\x57\x55\xa9\xb6\x70\xe6\x6e\x4e\x69\x44\x2b\x70\xea\x59\x17\x95\xcb\x89\x7e\x04\x08\x2b\x12\x5c\x40\xb4\x12\xf5\x20\x05\x2a\x87\x43\x27\x6f\x73\x79\x2b\x02\x31\x8d\x0d\x48\x72\x82\xf1\x15\xd1\xc7\x03\x15\x94\x4a\x32\x2a\x8e\x21\x20\x69\x62\x51\x2c\x76\xd2\x2b\xa3\x51\xd5\x9c\x00\xd1\xa6\x6f\x6e\xc5\x28\x3d\xff\xea\x57\x57\x8c\x2f\x2b\x1a\x7c\xca\xf4\xa9\x0b\x57\xf4\x57\x8c\x63\xdf\x4d\xdb\x38\x79\xde\xa2\xa6\xa2\x52\x19\x05\xcd\x67\xd4\xa7\xf0\xdc\xb1\x6e\x34\x81\xeb\x41\xbc\xc2\xdc\x42\x1a\x48\x47\x1a\x22\x9a\xe2\xd4\x21\x52\xfb\x6b\x45\x0d\xd5\x83\x21\x19\x7a\x50\x23\xed\xe6\xf2\x8a\x9d\x15\x14\x49\x4f\x69\x90\x64\x54\x8f\xb5\x43\x0b\xd5\xc5\x70\xcc\xf9\x29\x13\xec\x7e\x7c\x38\xb9\x22\x5c\x92\xc5\x8f\x81\x14\xa1\xfb\x4f\xfd\xf9\x42\x9f\x43\x1b\xb5\xb4\x93\x2e\xca\xc9\x9e\x5c\x1f\x4e\x3f\xb9\xbe\xe2\x27\x3f\xb9\xbe\x6f\x21\x7f\xa0\x47\xd8\x2f\x48\xed\xe2\x0f\x70\xfb\x92\xf7\x65\xf6\x9d\xb1\xbd\x2b\x42\x88\x9c\x3d\xf7\x13\xb5\xc2\xe9\x27\x6a\x55\xfc\xc4\x27\x6a\xa5\xcf\x3c\xd0\xa3\xb5\x1e\x49\x25\xf4\x39\x46\x8e\x5c\x5e\xc6\x4e\x4d\x26\xaf\x6b\x4e\xca\xeb\xda\x34\xaf\x07\xfd\x17\xbc\xce\xbe\x22\x30\x00\xc7\xe1\xa2\xec\xeb\x01\x03\xf3\x3d\x2b\x61\xa7\xbc\xaf\x22\xbc\xaf\x01\x67\xe4\xe4\x7d\x6d\x9a\xf7\x83\xcc\x21\xb1\x56\x40\x7a\x31\x3f\x41\x0a\xfd\xea\x8e\x01\x64\xf1\x70\x76\xe1\x91\x5b\x20\xfd\xe8\xa0\x32\x59\x08\x82\xa0\x02\xb4\x0d\x28\x13\x14\x8e\x68\xc5\x5c\x3a\xd2\x9b\xb7\x98\x0b\xa0\xa2\x95\x99\x57\x55\x0a\x3c\x92\xac\xc9\x81\x58\x0c\x95\x49\x09\x07\xe7\xa7\xcd\x75\x2b\x69\x03\x10\xa1\x9d\x54\x58\x7d\x7d\x8c\x01\x4d\xe3\x56\xf3\x81\x3e\x03\x8a\xe8\x41\xf3\xf1\x3e\x0c\x7d\xce\x1c\x79\xc6\x54\x05\xb8\x30\x87\x6c\xfa\x51\x63\x4e\xf5\xb3\xa8\x71\xa7\xb0\x51\x92\x9c\x64\x37\x89\xf9\x29\xd6\xd3\x47\xd8\x40\xf6\xf3\x8c\x49\x57\x4e\x71\xfd\x32\x4d\x53\x9f\xed\x54\x9f\xd4\x76\x6a\xd2\xb6\x53\xfb\x5f\xd8\x8e\x9a\x17\x68\x89\xaa\x7e\xc1\x12\xaa\x87\x03\x9a\xce\xfa\x57\x46\x5e\xd8\xbe\xfc\xfd\x3f\x9d\x6d\x3c\x95\xb7\x68\x20\xb1\x08\xa7\x07\x9b\xdb\xdb\x5a\x83\xaf\x5c\xd2\xa2\xa5\xec\x66\x2e\xb1\x9b\xea\x01\xec\xa6\x26\x6d\x37\xb5\xff\x07\x76\x93\x49\xc9\x00\x22\xf8\xdf\x4c\x3a\x72\x89\x81\x1f\x9b\x49\x03\xb9\xa7\xcc\x2b\x96\x76\x82\xbb\x1a\x02\x97\x51\xfc\x7b\x04\x54\xcd\xce\xea\x99\x4f\x05\x27\xe9\x82\xa7\x8b\x3c\x78\x3a\xf5\x84\x98\x7b\x0f\xef\x49\xed\xf0\x7a\xc9\x0e\xaf\x9d\x3b\x8a\x23\x2b\xe4\xc8\x73\x4b\xed\xa9\x67\x7f\x6b\xbc\x47\x92\xe3\x05\x66\xeb\xc5\x6b\xef\x7b\x0e\xb8\x79\xcd\x85\xed\xbb\xb8\x98\x45\x64\x33\x6c\xee\xbb\xc1\x38\xc7\xbc\xbe\xb8\x25\x93\x44\xbe\x23\x7d\x89\x11\x02\x7a\x85\x91\xd9\x91\x49\xa1\x99\x4b\x0a\xbb\xcc\x67\x23\x0e\x06\xe7\xe7\x7a\x3a\x22\x72\x46\x50\xb5\x9a\x9a\x39\xf5\x7b\x46\x62\xfd\x0f\x7a\x46\x22\x72\xca\xa8\xe2\x07\x3e\x29\xb1\x2f\x12\x7d\xff\x23\x13\xd9\x8d\x67\xd7\xc2\xc2\x92\x75\xa7\x9d\xec\xd9\x89\xcc\xeb\x05\xf1\x95\xbe\xd8\xee\xb1\xff\xff\xfb\xab\xe9\x67\xa4\xf2\xcb\x04\x1f\x99\xaf\x4e\xa0\x7b\x11\x64\xa5\x9b\x0c\x58\xa9\xbc\xbd\xaa\xe6\x72\xea\x48\x6a\x42\x9e\x48\x7a\xe0\xea\x21\x53\x56\xa0\xd5\xe4\x61\x09\x07\xf2\x43\xb9\x9f\x82\x39\xa4\x25\x1a\xc2\xff\x59\x54\x4b\x98\xcd\xbd\x0f\x36\xeb\xd6\xbf\xde\x3a\x73\x55\x9d\xd5\x91\x6f\xbc\x5f\x0b\xab\xc3\xb0\x2e\x7c\x4f\xed\x7d\xdd\x1f\xbb\xad\x93\xb7\x9e\xb3\xfd\xff\x43\xde\x9f\xc7\x49\x51\x9d\xfb\xe3\xf8\x39\xb5\xf4\xbe\x54\x55\xef\xd3\xdd\x33\xdd\xd3\xb3\xd2\xcc\x34\xd3\xcd\x30\x74\x10\x70\x01\x44\x40\x44\x24\x88\x44\x89\x5b\x88\xbb\x46\x62\x94\x10\x12\x95\xa8\x41\x45\xe3\x1e\x15\x15\x8d\x1a\x2f\xd7\x98\x53\xdd\xcd\xb8\xc6\x8c\x2b\xa2\x41\x2f\x31\x42\xbc\xfe\x72\x13\x63\x34\x69\x43\x34\x21\x37\x2a\xc8\xd4\xfc\x5e\xe7\x39\x55\xd5\xd5\x33\x3d\x80\xb9\xf9\xfc\xf5\xbd\xbe\x52\xf4\x34\x5c\xa8\xf3\x3c\xcf\x39\xe7\x59\xdf\xef\xc7\x70\xdf\x82\x23\x67\x7d\x73\xc1\x11\xc7\x1c\xfd\xed\xa3\xf1\xba\x2d\x78\xe1\xcf\x66\x2f\x8a\x9f\x77\xd5\xd6\xfb\xef\xdf\xfa\xf9\x92\x9b\x96\xcf\xff\xf5\x1b\xcb\x96\x5d\xfa\xfb\xf3\xe6\x2e\xfb\xf6\xab\x26\xb6\x83\x4d\x43\x6e\xe4\x47\x17\x1d\x04\x4d\xc0\x93\x53\xbd\x34\x94\xa5\xe1\xf6\xbf\x1f\x26\x61\x20\xdd\x08\x1b\xe1\x1b\x10\x86\x5b\x20\x11\x20\x00\xd7\x7b\x94\xc4\x47\x51\x14\x25\x50\xfb\xd8\x1e\xa5\x8c\x58\xad\xb8\x92\x66\x87\x4a\x2c\xa7\x36\xd1\x37\xef\xb0\xb6\xed\xa4\xf5\x6a\x5f\x27\x8c\xd5\xc9\xca\x20\xf4\x29\x35\x25\xcd\xee\xac\x78\x02\x36\x65\xad\xff\x24\x93\x3c\x68\xff\xc9\x40\xda\x7e\x30\x6e\xcf\x3e\xba\xa4\xe1\xc1\x03\x74\xe5\xbc\xf9\xa6\xde\x8b\x63\xe0\x57\xac\x85\xf9\xfd\xc7\x0e\xa2\x9f\x68\x4e\x55\xc4\x6a\x49\x89\xd2\x90\x55\x09\x39\x19\xac\x79\x1c\x10\xc1\xfd\x2c\x4e\x65\x45\xce\x4a\x98\x85\xe8\x5c\xfe\xdf\x81\x77\x01\xa5\xd2\xb2\xdd\xed\x8a\x52\xc9\x85\x65\x95\xb7\x15\xc7\xc2\x40\xd4\x85\xac\x0d\x14\xfd\xf5\xfa\x38\xbe\x06\x44\x32\xcd\x12\x99\x32\xbd\x9f\x61\xcb\xea\x7d\x5a\x3f\x3d\x70\x9f\x16\x69\xcf\xa9\x2d\x62\xb5\xd4\xd2\x4e\x25\xd2\xd2\xea\xcc\xc2\x20\x79\x5d\xf3\x56\x0c\x67\xf5\x89\x71\x92\x30\x5b\xb9\x88\x5d\x22\x99\xd4\x4e\xb9\xd2\xca\x04\xd5\x9a\xab\x64\x58\x48\x97\xc7\x59\x35\xe6\x65\x74\x8b\x09\x59\x0d\x77\x15\x8b\x64\xa2\x52\x91\x84\x96\xf6\xde\xba\xfe\xb6\x9a\xd5\x1c\xbc\xbb\x6b\x94\x74\x02\x07\x31\xa0\xc3\xea\x44\x15\x1e\xbf\xb3\x2f\x6e\x8a\x6e\x38\x51\x67\x4f\xc7\x00\x37\xe5\x15\x07\xb1\x27\x0b\x53\xa5\x67\x67\x1d\x41\xe5\xff\xc5\x5a\x14\x8f\x8e\xb8\x50\x6f\x22\x56\xc2\x8c\xb1\xe6\xf1\xa9\xee\x01\x5a\x4e\x82\x3b\x75\xbf\xcf\xe8\x57\x0c\x42\xbf\xe2\x44\x74\xf9\x81\xfb\x15\x49\x36\xa7\xb6\x0b\x55\xe3\x4a\xd6\xad\xa0\x15\x67\xd5\x2e\xa9\x5a\x4e\x76\xb5\xb2\xf4\x29\x5c\xce\xad\x5e\x28\x90\xc6\xa8\x1f\x95\x94\x41\xc9\xd9\xb6\x48\x51\xb5\x77\x99\x03\x0c\x35\x35\x7f\x91\x06\x46\x8b\xcb\x7b\xc0\x16\xc6\xcb\x0c\xc7\x77\xbc\x16\x46\xee\x9c\x1a\xef\x28\xea\xd7\x82\xc2\x46\xe0\xe8\x4f\x1a\x8c\x9d\xc4\x5f\x18\xab\x63\x12\xcf\xa9\x61\x4f\x3d\xf4\x4d\x33\x9c\x12\x0c\x58\xdd\x1c\x97\xfc\xbf\xa8\x39\x00\xf4\xa4\xe0\x94\xa2\xb0\xac\x00\x81\xe4\x18\x68\x98\x51\x09\x8c\x06\xc7\x02\xaa\xcf\xe2\x98\xea\xd7\x76\x35\xca\xdf\x74\xe9\x1c\xcf\x13\x50\x01\xdd\xc7\xec\x40\x6f\x4f\x66\xa6\xd0\x27\x42\x27\x54\xc6\x53\xad\xb8\xb2\xb5\x6e\xce\xc9\x16\x53\x20\xa9\xfa\x1c\x66\xca\xc4\x4f\xcd\xe9\xf7\x45\x3f\x0d\x82\xbc\xb2\x52\x76\x27\xba\xa8\x39\x90\x9c\x3c\x28\x84\xa5\x64\x7b\x47\x9f\xd1\x63\x01\xa6\x11\xce\xc8\x4a\x29\x96\x6a\xa7\x11\x85\x2b\x41\xcd\x24\x58\x2c\xaa\x7d\xd9\x83\xf6\x7a\x8e\x91\xcb\x41\x0e\x84\xa7\xeb\x64\x74\xc7\xb8\xe7\x81\x96\xb4\xca\x8c\xff\x5f\xd6\xef\xcb\xce\x84\x37\x00\x23\x26\x76\x70\x8c\xa4\xa6\x9c\xc9\x2f\xfc\xef\xbb\xfc\x51\xa7\xc5\x3f\x6f\x64\x06\x17\xe7\x2d\xde\xb9\xe5\x72\x50\xe6\x9a\x4e\x79\x2d\xbf\x7b\x1b\xf4\xf1\x76\xa0\xdc\xd8\x3e\xde\x1e\x7a\x16\x74\xd6\x34\x3f\xc9\x7a\x08\x64\x75\x05\xf7\xd5\xf5\xf1\x66\x59\x1f\x6f\x3c\x09\x2d\x5a\xac\x8f\xb7\xa5\x71\x1f\x6f\x4f\xe7\xc1\xfb\xb6\xad\x71\xc8\xc1\x0e\x7a\xc5\x1a\x92\xf8\xc6\x3f\xe7\xbf\x54\x8b\x4c\xf6\x6f\xad\xf5\xef\xd3\x78\xf8\x7c\xfb\x2a\x94\x44\x13\xd1\x42\xbd\x17\xd0\xc4\x1a\x70\xb9\xab\x95\x50\x38\x4e\x25\x11\xe2\xab\x65\x7b\x1c\x42\xe3\x1e\x03\x6f\x80\x9e\x7f\x48\x0d\xc9\xd0\xf8\xa7\xda\xe3\xd0\x6a\xa9\x0a\x2e\x9d\xa1\x8c\x06\xc6\xe9\x7c\x7d\x5c\x1c\x48\x07\xd2\xbc\x0f\x67\x52\x63\x12\x4b\x6f\xe2\x2b\x31\xff\xdf\x43\xab\xe6\xdd\x7a\xe2\x9d\x7f\x5f\x7f\xd3\xed\x0b\x56\x1c\xa9\xfd\x73\x2a\x57\x78\xe0\xea\xf7\x2f\xd7\x86\xb5\x0f\xf0\x65\xf5\x19\xa6\x76\xec\xc2\xe4\xa3\x33\x3e\xef\x9a\xf4\xb0\xb6\x5d\x7d\xf4\xfe\x28\xce\x62\x6e\xd8\xd6\x9b\xc6\x1d\x62\x6c\xec\x7c\x70\x5c\x0b\x0a\x0f\xdb\xd2\xa8\x19\xf5\xa0\x69\x74\xa5\x35\x16\xf0\xa9\x16\x16\xf0\xc3\x80\x05\xbc\xd7\x5f\x55\xa7\xe3\xac\xda\xeb\x95\x95\x8a\x8b\x8b\xb7\x30\x10\x14\x83\x07\x7c\xaa\x5c\x42\xde\xbe\x2f\xc0\x03\x7e\xa0\xc9\xb4\x83\xd0\x82\x9f\x5e\xb7\xea\xd7\x0e\x46\x12\x6e\x5b\x3b\x7a\x5c\xcd\xa0\x0c\x37\x75\xbd\x16\x74\x7d\xef\xa1\xe8\x9a\x4c\xc8\xa9\x6d\x62\xb5\xd4\x36\x81\xfa\x46\x6d\x9d\xce\x2c\x49\xe5\x2d\x06\x60\x0c\x71\x18\x1d\x8f\xd0\xba\x6d\x24\xb6\xe9\xe5\x98\x86\x21\x8e\x70\x3c\xc4\x26\x8b\x2a\x42\xc0\x15\x84\x16\xff\x2e\x45\xb5\x43\x93\x99\x6e\x3d\x24\x2c\x7f\x11\xdb\x19\x55\xf4\x39\xa8\xed\xbc\x51\xe7\x0d\x1d\xc8\x76\x6c\xdd\xd6\x22\x07\xb3\x9b\x7b\x6d\x59\xe0\x8e\x9f\x86\x6e\x6e\xcc\x1e\x4f\x8a\x39\xb5\x20\x56\x4b\x85\x22\x95\x53\x61\x8a\x33\x0b\x5d\xee\x87\x19\x94\xf2\xa4\x45\xa2\x91\x5d\x65\x12\x93\xd3\x24\x49\x9d\x82\xb3\x95\x01\x26\xa7\xe9\xf5\x74\xf3\xea\xa4\x1e\x59\x51\xe5\xd6\x62\x91\x4c\x91\x1f\x17\xed\xc1\xb0\xad\xbb\xa3\x08\xf6\xd7\xcd\xc9\x8a\xce\x40\xaf\x86\xe3\xf2\xbf\xc0\x41\x3f\xaa\x2a\x74\xe8\x94\xf4\xed\x75\x02\x3c\x28\x41\x3d\xff\x6e\x4d\x8a\x86\xdd\xad\x44\x49\xd4\x85\xbe\x75\x48\x76\xd7\x99\x53\xd3\x42\x2d\xf7\x6b\x5a\x9a\xda\xc6\x92\xd9\x6a\xb3\x8f\x1a\x56\x28\x1c\x67\x33\x58\x65\x6a\x58\x20\xa3\x7f\xd1\x9e\x6a\x79\xd3\x83\xd9\x12\x77\x83\x91\x40\x3d\xd0\x09\xf4\x60\x8d\x23\xdd\xb0\xa1\x20\xd8\xd0\x00\x8d\xa0\x1b\xda\xd0\x94\x9c\x3a\x49\x60\xec\x4c\x75\x56\xa3\x16\x24\x46\xbc\x64\x31\x12\xd2\x23\x33\x13\x29\x28\x83\xa2\x3d\x18\xb2\x75\x77\xfc\xdb\x2c\xc4\x14\xc5\xa1\x5b\xc7\x7f\xeb\x22\x39\xb8\x5d\x9c\x5c\x93\x0b\x87\xd6\x68\xd3\xc4\xf3\xc5\xed\x28\x89\x3a\xd1\xb2\x43\xbb\x7b\xba\xcc\xbb\xc7\x4c\x6a\x36\x77\x5a\xce\x91\x2f\x7c\x0b\xd1\x93\x39\xe4\xc3\xf6\xcc\xc1\x0f\x91\x58\xec\xf8\x00\x6e\x4a\xaf\x9d\x5d\x39\x90\xea\x87\x67\x15\x9e\x2b\x06\x67\xfc\xc7\xb1\x56\xdd\xa7\x41\xf7\x53\xd0\x82\xc6\xba\x87\x49\x60\xa6\x74\x18\xf7\xb5\x68\xba\x76\xeb\x74\xcb\xba\x66\x0f\xf5\xd6\x19\x35\xdd\x3d\x03\x0f\x14\xe8\x4a\x0f\x5d\xad\xcf\xb5\x5c\x71\xd4\x96\xe0\x89\xca\x41\xd5\xca\xed\x08\x4d\x7b\x6c\x5e\xbc\xeb\xd5\x69\x06\x4e\x83\xf8\xa0\x8e\x27\xf8\xa2\x8e\xd0\x67\x77\xb8\x0b\x3a\x82\x5b\x89\x13\x6d\x85\x42\xa1\xc2\xbb\xa8\xc7\x48\x9c\x05\x95\xe7\xab\x44\xc8\x1b\x44\x1b\x6e\x7f\x95\xb8\x25\x15\xbb\xb3\x2a\xe7\x87\xfe\x1e\x07\x75\xba\x18\x3c\x87\xe8\xce\xaa\x36\x7f\x8d\x73\x43\xc7\x72\xa0\x1f\xb6\x82\xa3\xe9\x96\xca\xbc\x9b\x0b\x64\x89\x43\x2a\x0b\x0e\x31\x90\x2d\x3b\xe9\x93\x7e\xef\xa2\xdf\xf3\x65\x5e\x70\xba\x8c\x08\x84\x73\xd3\xb0\xc3\x5b\x04\x2e\x07\x89\xba\x72\x76\xa5\x24\x87\xa1\xd3\xcd\x26\xab\xc1\x90\x11\x82\xf2\xe9\x40\x1a\x8a\xcc\x81\x31\x50\x9d\x38\xbf\x1a\xef\x5a\x8d\xfb\xb4\xd7\xb4\xd7\xaf\xd6\xba\xaf\x5e\x3f\x0a\xaa\x73\xf8\x05\x6e\xfa\xbe\x79\xdc\xa5\xc3\xeb\xc7\x00\x1a\xea\x33\x0a\xf6\xcd\x50\xff\xfa\x40\x97\x95\x5f\x8a\x15\x0a\x66\xd3\x13\x3b\x03\x63\xde\x2a\x89\x49\x8c\x88\xc2\x5f\x2d\xfb\x3d\x01\x47\x96\xe1\xdc\xe5\x80\x8d\xac\x06\x49\xf2\x8b\x1a\x92\x1d\x89\x49\x84\x1b\xb2\x0c\x1e\x48\x12\x91\x87\x88\x1f\xc6\x0f\x62\x52\x99\x8f\x71\x81\x6c\x59\x80\x67\x34\x06\xe4\x24\x31\x6b\x4f\x14\x5f\x24\x42\x11\x55\x7c\x72\x94\x17\x18\x0d\xe8\x20\xe6\x6a\x3f\xe9\xfd\x51\x52\x4c\x56\x2a\xa2\xad\x29\x0e\x33\x6c\x01\x59\x0d\x35\x03\xe9\x8d\xea\xec\x00\xf2\x12\xb5\xa5\xad\xa8\x8f\x2d\x00\x59\x4c\x01\xa7\x7d\xd8\x5e\xd0\x47\x5c\xeb\x86\x16\xea\x65\xdb\x8e\xe7\xe1\x9e\xce\x09\x47\x38\x66\xfc\xe8\xcc\xba\xa1\x85\x42\x9d\x84\x6d\xc1\x2d\xcf\xff\xfa\xd8\x53\x46\xcd\x2b\xd8\x4e\x1f\x23\xeb\x7e\x84\x6c\x3d\xe2\x20\x0a\xa0\x08\x4e\x9a\xb2\x0e\x50\xbb\x14\xa9\x5d\xda\x9c\x2e\x6a\x97\x41\x05\x89\xde\x2c\x91\x0b\x6a\x90\xaf\x92\x50\xbe\xc2\x73\xf4\x8b\x32\xf6\x85\x23\x6d\x91\x82\xca\x7b\xaa\x65\xc1\xee\x70\xb7\x45\xd8\x70\x4f\xad\xac\x2f\xe1\xac\xea\xf7\xd7\x26\x78\xee\xdd\xf3\x82\xa1\x0c\x71\x88\x04\x18\xad\xa6\x81\x3e\x22\x49\xc4\x09\xba\x70\x0d\x11\x24\x95\x31\xa2\xb6\x2a\xd0\x27\x09\x48\x65\x7b\xc0\x16\xc8\x12\x49\x2a\x3b\x24\x67\x20\x4b\xfc\x52\xd9\xed\x77\x05\xb2\x65\x1f\x7d\xd2\xef\x65\xf8\x3e\x20\x95\x15\xfa\x27\xcb\x41\xe3\xcf\x87\xe8\xf7\xe5\xb0\xf1\xbb\x11\xfa\x3d\x7f\xb8\x84\x05\xd1\x66\x77\x38\x5d\x6e\x9f\xac\x04\x43\xe1\x48\xef\xa8\xff\x83\x70\x1c\x01\x54\x0b\xcc\x18\x65\x06\x0a\x03\x69\xbb\x91\x65\x06\xc3\x4f\x0f\xa4\xfb\xff\xa0\x76\x97\xbb\x70\xbe\x1b\xef\xea\xc6\x7d\xdd\xa5\xee\xca\xbb\xcc\xe6\x7f\x8e\x77\xb5\x6b\xdd\x42\xcf\xd6\xe7\x9f\x7f\xfe\xf9\xad\x9f\xbf\x49\xad\x9d\x5f\x6d\x99\xc3\x39\xd5\x16\x44\x29\x94\xc6\x58\x97\x7b\x38\x92\xa2\x36\xce\xe5\x54\xec\x2a\x80\x4c\x55\xc1\x9e\xcf\x13\x31\x47\x6c\x05\x28\xf8\xa0\x9d\x6a\xca\x5b\x25\x29\x56\x51\x0c\x78\xab\x24\x92\xda\x29\xab\x61\xaf\xb5\x08\x54\xb1\xc8\x37\x05\xf2\x9d\xc9\xff\xef\x1b\xcc\xd8\x23\x12\x89\x0e\x91\xb0\x44\x42\x43\xe2\x68\x09\xa7\xa4\xb2\x3d\x45\xe5\xe6\x4a\x01\x93\xe9\xc6\x3d\x4f\xa2\x50\xd6\x5d\x6e\xa1\x3f\x96\x5a\x52\xb6\xda\x2e\x40\xa5\x50\xb4\x85\xda\xfe\xe1\x4e\x10\xa2\x8b\xfd\x68\xd9\x00\x29\x26\x37\x12\x91\xd9\x51\xd2\x04\x48\x29\x61\xb9\xe4\x94\x1c\xec\x08\x47\xb2\x52\x92\x12\x69\x28\xdf\x9a\xb2\xb5\xa7\x6d\x0d\x77\x01\x6e\xd7\x1e\xc8\x6e\xca\xe0\x9e\x34\xce\x66\xb5\xb7\x3a\x26\x38\x66\xdc\x76\xe6\xf5\xb7\x85\x57\x6b\x6f\xae\x95\xce\x39\xe5\x8e\xec\x52\x6e\xb7\xf0\xe8\xd6\xfb\xef\xdf\xfa\xe0\xda\x85\x27\x3f\x72\xe7\x71\x2b\x87\x9f\xe3\x16\xcd\x2a\xac\xf9\xd3\xab\xda\x85\xc2\x0a\xc6\xdb\xf0\x12\x42\x82\x6c\x3f\x15\xb9\x51\x1a\xdd\x62\x45\x49\x8d\xe5\x88\xa7\xa0\x06\x3c\xd5\x72\x73\x20\xe6\xc8\xaa\x3e\x4f\x95\x84\xf3\x20\x71\xcf\x4e\x8b\x27\x1f\xc6\xd9\x4a\x84\x4d\x44\x64\xfe\x25\xd4\xd4\xb4\xc7\x98\x06\x0c\xcb\x15\xbb\xcb\xed\x83\x82\x55\x44\x69\x80\xa0\xda\x60\x76\xa2\x1e\x41\xf5\x7b\x0d\x07\x26\xea\x80\x54\xc7\x20\x60\xb2\xf9\xc6\xef\x00\xa7\x66\x0c\x5d\x3d\x76\x4a\x4f\xce\x11\xa1\xa0\xba\x3d\xd5\x72\xd8\x2d\x3b\xb2\xaa\xcd\x53\x85\x64\x78\x13\xb0\xa8\xc4\x74\x74\x77\x01\xf9\x58\xeb\x5a\xac\xae\xe5\xd4\x87\xb3\x7a\xbe\xdc\x4c\x75\x8c\x99\xd7\x2b\xdb\x9c\xc1\x30\xeb\x8f\x56\xdd\xb2\x31\x0e\xc9\x37\x5a\x2e\x0c\xef\x69\x7f\x1c\x67\x18\xeb\xf3\x07\xc6\x4c\x5f\x19\xb8\xbd\x25\xbd\x2e\x73\x9c\x55\xc7\x0d\x8a\x30\xff\x27\xf8\xde\x81\xf4\x28\x7d\xbc\xde\xc3\x9d\xdb\x53\x0f\xd5\x0b\x35\x17\x26\xf3\xa8\xf8\x28\xf0\x98\x2e\x1d\x2b\x73\x21\xa7\x8a\xf4\xcd\x1c\xe3\x8f\x96\x3a\x0f\x38\xeb\x6a\x0c\x40\x0e\xa4\x99\xcc\x7e\x45\xdf\x84\x8d\x92\xbe\xf9\xa6\x2e\x93\xdf\xe8\xb5\x90\xf5\x56\x99\x7c\xd1\xc2\xc7\xbf\x06\x7c\x0c\x75\x8e\x92\xcb\x0d\x0e\x44\x58\x56\xed\xac\xcc\x51\x8f\x17\x5c\x17\x83\xd5\x0b\xf6\x17\x75\x71\x56\x1d\x90\xb4\xb5\xc6\xc1\xe4\x7c\x82\x2d\x8b\x78\xa4\xa0\xeb\x1b\xd9\xb6\xea\x16\xab\x25\xb7\x4c\x57\xeb\xf6\x39\xb3\xc4\x9e\x87\x01\x5a\x5d\xea\x0e\x2a\x75\x9d\x9a\x8b\x88\x39\x9d\x41\x91\xfa\x4c\x6e\x07\xef\xb3\xea\xc3\x62\xec\x54\x2a\x0d\xa7\x6c\x81\xaa\xcc\x62\xe1\x5c\x7f\xdd\x1a\x41\x51\xbf\xb4\xae\x0c\xe6\x52\xcf\xfd\xae\xb1\x22\xaa\x37\x2d\xc8\x5f\xa1\xe7\xa5\xd7\xd6\xe7\xa5\x99\xfe\x58\x3e\x7a\x9c\x24\xf4\x17\xd3\x51\xc0\x23\x2b\x25\xc1\xcf\xdc\x6b\x08\x93\x62\xd0\x53\xc8\xd2\xcf\xa3\xb0\x9d\x47\xa5\x59\xeb\xd4\x35\x4c\xea\xb2\xaa\x56\x75\x35\xc8\x3d\x8f\x10\x2d\xc8\x6d\xb0\x05\x91\x8c\x42\x28\x85\x36\xb1\x59\x21\xaa\x35\xf8\x35\x54\x28\x05\xa8\xf6\x82\xc0\x3f\xe1\xf2\x00\xda\x5c\x8c\x46\x84\x69\x20\xe9\xb2\xb3\x24\xb3\x9d\x39\x81\x41\x6f\xb5\x1c\x0a\x52\x27\x50\xf1\x02\x73\x73\xc8\x4b\x7d\x68\xea\x64\x84\xe9\x35\x99\x90\xaa\x6a\x6b\x23\x5d\x85\x14\x59\x29\xf1\x1e\x3f\x0d\x11\x83\x01\x59\x29\x79\x63\x2d\x20\x08\x17\x23\x47\x27\x8a\x49\x6a\x36\x66\xf1\x71\x5c\x57\x82\x59\x54\xb7\xfa\x4b\xa8\x96\x25\x3d\x12\xac\x5f\x3e\xbe\x02\x14\x7e\x66\xad\x0e\xa1\x63\xb4\xaf\x84\x1a\xd3\xa9\xd6\x7d\x3a\x7e\x41\xe9\x8b\x29\x19\x4a\x48\x2e\xf7\x98\xed\xc7\xd7\xde\xbf\x4e\x97\x77\xe8\x6f\x5e\x77\xaa\x0d\xea\x6f\x8c\x61\x7e\x7f\x26\xf0\xbc\xcf\x6e\x30\x29\x2f\x8c\x7f\x9c\x89\x0d\x94\xa0\x6f\x13\xd8\x17\x30\x55\x4e\xed\x7f\xb1\xf8\x3c\xd8\xbf\x79\x57\x81\x3c\x54\x25\x50\x28\x90\x48\x4e\xf5\xb9\x19\xef\xa4\xc2\x1a\xc4\xe3\x07\x12\x0a\xf5\x8c\xb6\x80\x67\xa4\x80\xc3\x1f\x90\x48\x70\x08\x6d\xa1\xf2\x91\x83\x06\xa1\xbf\xf5\x27\x46\xc5\xee\x8b\x18\x5b\x81\x35\xd5\xd6\xa4\xe6\xc7\xb0\x99\x71\x1a\x03\x7c\x5b\x9d\xe0\xbe\xbb\x6c\xc1\x19\x6b\x12\xb8\x1d\xf7\x69\x3b\x26\x7f\xfa\xbb\x15\xa7\x58\x25\x78\x7b\x70\xf5\x3a\xf1\xcc\x7d\xdf\xf8\xe7\xef\xe3\x6c\x5e\xb1\x5d\x0b\x0a\x1f\xdb\x82\x88\x47\x3e\xd4\x84\xda\x8d\xf8\xd0\x90\x66\x89\x0b\x86\xa8\x5f\x18\xcd\xa9\xb2\xab\x4a\xbc\x39\xd2\x56\x80\xb9\xbe\x66\x46\xb7\x33\x8e\x94\x09\x96\xd8\x70\xbd\x4b\x82\x03\x2b\x88\xb3\xb0\x21\xe2\xf4\xbb\xb4\x04\xf5\x7b\xab\x16\xcc\x11\x11\x1f\x09\x4a\x24\x30\x44\x42\x12\x09\x0f\x21\x35\x10\xee\xed\xc5\xf0\x34\x29\x18\x2b\x76\xaf\x5f\x8e\xb6\x45\x8a\x6a\x28\x28\x2b\x6a\x33\xc4\x32\x72\x54\x56\x48\x13\x48\xca\x5f\xb4\x8c\xe4\x33\xbb\x0a\xb0\x1c\x43\x6d\x0c\x22\x5c\x1b\xd0\x37\x36\x48\x78\x7a\xff\xfa\xb6\x61\xdc\xab\x7d\x7a\xac\xf6\xd4\x59\x73\xb8\x05\xfa\xf7\xd6\x8d\xb2\x6f\x4a\x68\xb3\xb0\xf9\xf3\x6e\x6d\x43\xcc\x3e\x50\xdb\x3b\xda\xb3\xda\x62\x7e\x0b\x60\x46\x27\xd0\x19\xa8\x64\xa3\xdb\xc6\x5e\x20\xee\x9c\xca\x51\x23\x49\xe6\x88\x8d\x01\x1e\x36\x9b\x7e\xf2\x16\xb6\x58\x40\x6b\x64\xc8\x8d\x63\x30\x1b\xed\x36\x59\x51\x15\x00\x30\xa5\x51\x31\x3d\x0a\x6c\x32\xa0\x55\x8a\x75\xca\x1f\x95\xcd\xd6\x9e\x1d\xad\x7f\xfc\x7a\x5d\x78\x66\x31\x01\xfb\xb3\xa3\x63\x32\x6d\x9f\x16\xe4\x67\xd9\xd2\xc8\x83\xe2\xb0\x16\xcc\xd6\xe2\xd2\xf3\x22\x09\xb6\x16\x6f\xad\x23\xe8\xce\x3d\x3f\x3b\xc4\xb5\xc8\x40\xc7\xca\xb9\xa0\x47\xbc\x7e\x2d\x86\x72\x46\x2d\x65\xdf\xf4\x29\xd3\x4f\x0e\x68\xb8\x47\xd7\x0a\x4e\xd7\xad\xe4\xdd\xd0\xa2\xe5\xba\x3e\x6c\x8f\xd6\xad\x84\x43\xfd\xda\x34\xf1\x41\xc0\xa6\x0c\x1b\xfe\xb6\xea\xf0\x98\x98\xf5\x62\xa1\x00\x47\x1a\xda\x49\xc3\x77\xe2\x31\xd3\x1b\x96\x72\xf9\x5f\x98\x65\x32\x13\x75\x8f\x42\xa2\x2c\xb9\x3d\xf5\x91\x39\x52\x79\x37\x5d\x33\x7d\xc2\x9a\x3d\xd4\x45\xf2\x86\x01\x7d\xa3\xe4\x92\x74\x62\x29\x1a\x9a\xb8\x58\xd0\xcd\x0f\xe0\xb4\x13\xa7\x79\xbb\xbb\x96\xf5\x82\xf4\xc5\x5d\x1b\xf1\x3d\xf8\xec\xe1\xc7\x70\x46\x7b\xec\xcd\xb5\xe7\x0f\x98\x79\x2e\x71\x70\x78\xc6\x0e\xfc\xf7\xe1\x59\xc3\x36\x6e\xd1\x9c\xe1\x4f\xb4\xa5\x96\xdc\x16\x87\xda\xb5\x69\xc2\xdf\x80\x23\x34\x86\xee\xd6\xd7\xec\xf6\x17\x0a\x25\x07\xd5\xa2\x9e\xbe\x68\xb2\x0e\xcf\xeb\x0e\xb4\xc5\x65\x7e\xd2\x58\x34\xc4\x5f\x34\xce\xe5\xfd\x1c\xc4\xb9\x74\xd1\x3e\xff\x98\x45\x03\x5a\x02\x6f\xa0\x25\x00\xe3\x8f\x14\x2b\x16\x61\xaf\x6e\xb1\xd9\xbd\x81\x60\x94\xb5\xcc\xd2\xdf\xb1\x79\xf5\x82\x32\x6f\xf3\xe3\xc2\xd8\xe5\x43\x86\xe1\x56\x77\xbb\xd7\x81\x5f\xc2\xcb\x34\x1f\x4e\x6a\xe4\xf1\xcb\xe6\x9d\x6c\x4a\xc0\x16\x1c\x9e\x57\xfc\xd6\x44\xfc\x8e\xe6\x18\xbe\x0b\x3f\x38\x57\x7b\xb0\x4e\x06\x70\x2f\x08\x7f\x13\x56\x20\x1f\xfa\xa1\xc1\x54\xe0\xd3\x11\x26\x80\xa9\x00\x03\x42\x09\x8c\x5b\xab\x52\xfd\x21\xa4\xe7\x68\x7c\x2c\x47\xa3\xab\xbd\xcc\xfb\x20\x27\x03\x4f\x2f\x7d\x96\xbc\xbe\xb1\x39\x99\x92\x17\x72\x30\xb8\x82\x39\xaf\x9e\x8d\x61\x67\x38\x38\xca\xa2\x87\x05\x9a\x90\x67\xd1\x57\x0d\xb7\x4d\xa6\x7b\xa2\x03\x6f\xb3\xac\x54\x58\x71\xf7\x93\x1b\xf0\xbb\xe6\xea\x8c\x3c\x09\xff\x53\xfb\x2a\x24\x22\x1f\x3a\xde\x98\xea\xd0\x6b\xbd\xa0\x53\x3f\x3b\x88\xfd\xb5\x25\x19\x49\x0d\x2c\x11\x34\xc4\xee\x22\x5e\x45\xbc\x9e\x64\xc3\xb2\x52\xb2\x39\x01\x54\x94\xf1\x21\xd4\xb3\xf5\xe0\xfc\x08\xe2\xd0\x14\xad\xc9\x44\x80\xfd\x7c\x9e\x95\xa1\xc7\xf0\x77\x7f\x6a\x7f\x14\xb0\x6a\x8e\x31\xef\x0c\xc3\xc8\xbc\x20\x63\x36\x60\x64\x1a\x99\xaf\xde\xc8\x6a\xae\x6a\x49\xb0\x7b\x6a\xef\x62\x02\x32\x80\x31\x68\x83\xbd\xfa\x5b\xd8\x82\x7b\x77\xdb\xce\xac\xc3\x9f\xd5\xa6\xf1\x1b\xc5\x41\x24\xd6\xe2\xad\x7a\xb9\x48\xa6\x5c\xe4\x43\x95\x8b\xea\xf2\x59\xa5\x52\xbf\x31\x41\x2c\xc3\x27\x5a\xf6\x23\x15\x8c\xc5\x02\xb9\x91\x7b\xb4\x69\xdc\x46\x5b\x10\x39\x91\x17\x1d\x8d\x4a\x2e\xc4\x66\x5c\xdd\x34\xca\xc7\xc4\x97\x23\x2e\xb3\x74\xed\xc6\x8c\xa6\xcc\xdf\x48\x2e\x5e\x97\xac\xa8\x0e\x01\xde\x85\x37\xdf\x22\x80\xd3\xf8\x0c\xf3\x9f\xff\x01\x13\x90\xf9\xef\xe3\x97\xa8\x8c\x6a\xdc\x55\x0f\x8b\x8f\x83\xcd\x9c\x38\x4a\x36\x2a\xe7\x2c\x14\xca\x36\x84\x1d\xd9\x2f\x6a\x3b\x48\xc5\x36\x13\x20\x0f\x64\xe4\x6e\x60\x39\x27\xea\x5d\xaa\x4c\x3e\xc2\x45\xf5\xfd\xa8\xc2\x42\xf0\x37\x3c\x54\x3e\x35\xbb\xd1\x77\xe7\x21\x5b\x8e\x7e\x96\x0a\xec\x3d\x9c\x78\x94\xd5\xe0\xaf\xe9\xef\x40\x45\x22\x6c\x37\xdf\xc0\x90\x0d\x07\x76\x23\xa1\xaf\x8d\xb5\x9b\x8a\xd3\x0f\xad\x13\x4e\xea\xf6\xca\x86\x78\xa8\x1b\x63\xa3\x1a\x93\xaa\xaa\x72\x28\xd6\xe4\xa1\x82\x12\x85\x9a\x35\x8d\xea\x96\xd2\x65\xf5\x33\xb3\x4b\x8a\xca\x8a\xfb\xb5\xa5\x37\x88\xee\xb1\xc7\x74\xdf\x6c\x59\x4d\x56\x3a\xb2\x82\xbe\xd5\xfc\x0d\x04\x56\x16\xc0\x1f\x73\x49\xd6\x33\xce\x62\x5c\x2e\x8e\xea\xd0\x6b\xbc\x9a\xd3\xea\x14\xe9\xe2\x93\xf5\xd7\xa2\xe2\xe3\x36\x1a\x2f\x85\x47\x34\x84\x60\xcf\x79\xe9\x0d\x03\xc8\x16\x0e\xa3\x39\x9c\x67\x06\xce\xb1\x69\x4e\xbf\x29\xa3\xe7\x4d\x87\xd8\x33\x24\x12\x5e\x02\x87\xf8\xbe\x3d\xdb\x8c\x5b\x15\x7b\xcc\xf2\x00\x1f\xc8\x96\xed\xf4\x59\xc2\xd6\xeb\xb5\x64\x77\xf0\xf4\xac\x15\x8a\xa8\x8c\x05\xbb\xa7\x97\x1d\xb5\x82\xdd\xe1\xb1\x1c\xb5\x9c\x83\x0a\x1c\x6e\x18\x7e\x20\x90\xe6\x07\x22\x22\x30\xe2\xd9\xb9\xdf\xde\x8c\x73\xe7\x6e\x38\x57\xdb\xb6\x94\x43\x53\xf6\xef\xf8\xfa\x97\xb8\x0d\x97\x72\x25\xcd\xb6\xf0\xb5\x9f\x68\x67\x8d\x20\xfc\x6e\x33\xdc\x1d\x54\xe8\x6f\xdb\x82\xc8\x8d\x7e\xa6\xf7\xbe\x3b\x0a\x84\xcb\xc1\xc2\x3c\x39\xe2\x84\xe1\x6c\xe2\x90\x54\x8e\x4d\x4f\xaa\x5e\x73\x8d\x2f\xd5\x5f\x9b\x4e\xa9\x8c\x9d\x63\x57\x45\xbf\x77\xd1\xef\x4b\x2e\xa7\xf5\x0e\xc1\xa3\x57\xe8\x62\x01\x94\xf1\x09\xae\x56\x87\x13\x3a\x18\x55\x9e\x83\x9e\x79\xa4\x72\x4e\xba\x5e\xd8\x89\x32\x5b\xaf\x9d\xae\xf6\x77\x9b\x71\xf7\xba\xc3\xcf\xf9\xd3\xb5\xda\xae\x33\x0e\xe3\xd6\xae\xe6\x9b\x87\x6f\x6d\x7f\x6d\xed\xf0\x1a\xfc\x66\xda\xca\xe7\xb3\x0a\x49\x28\x66\xfa\x46\xf5\x7c\x3e\x86\x9b\xa0\x13\xf7\xe8\x54\x3d\xa6\x9b\xf0\xef\xa2\xe7\xb1\x4b\xb2\x52\x76\xca\xc1\x18\xa3\xa0\x55\x43\xe1\x62\x43\x86\x9e\xba\x23\xa6\x11\x2d\x0f\x27\xd5\xae\xaa\x51\x4c\x3c\x16\x5e\x39\x7a\xf6\x7c\x4f\x9f\xbf\xbf\xa7\x21\xfe\x94\x81\x2a\xa1\x63\x83\x8c\x07\x2d\x65\xf2\x56\x1d\x12\x82\x54\x18\x19\x14\x94\x15\x5e\xe0\x22\xd0\x71\x2b\x29\x25\x05\x06\xb9\x89\x07\x28\xac\x0e\x0d\x44\xca\x02\xdc\x36\x16\x39\x0a\x23\x13\xc8\x6d\x2c\x58\xd4\xdb\xa3\xee\x4d\x5b\x50\x1c\x44\x12\x6a\x42\xd7\x8e\xa3\xff\x78\x23\xfd\x27\xfe\x1f\xe8\xbf\xe4\x94\x43\xc5\xc6\x6a\x0f\xd4\xdd\xbe\x8d\xf4\xde\x6f\xbd\x8a\xeb\x15\xdf\xc0\x37\x3e\x5f\x58\x05\xb3\xf9\xf7\x8e\xa3\xfb\xf4\x21\xe9\xbe\xf5\x8b\xea\xbe\x84\x23\x29\x86\x1e\xb6\x85\x17\xb8\xa6\x78\x0b\x33\x00\xa2\x7c\x21\xe5\x5b\xbd\xe4\x06\xda\x5f\x69\x4a\xa2\x81\xfa\x47\xc9\xa2\xb6\xff\x9b\xc7\xdd\xff\x2d\x8d\xf4\x9f\xfa\x7f\xb3\xff\x23\x71\x7d\xff\x47\x63\xe3\xed\xff\xd1\x93\x40\x8d\x8c\x01\xb7\xd7\x4f\x03\x8d\x32\x08\xfb\xf2\xfa\x59\x20\x76\x1e\x3c\x02\xe7\x41\x1b\xda\x34\x8e\x4d\xb4\x1f\x92\x4d\x74\xfc\x6b\xe7\x01\xb5\x87\x48\xac\x95\xd9\x83\xaa\xc4\xe1\x38\x28\xd9\x92\x69\x33\x56\x3c\x38\xae\x5c\x9d\x68\x1a\x59\x46\x8f\x55\x2a\x0d\x8c\xc3\xe6\x18\x2d\x97\xc9\x08\x89\x33\xc4\x41\x64\x43\x49\xf4\x9f\x8c\x97\x42\x0d\x04\x0b\x05\xb8\xe6\x21\x98\x2c\x79\x40\x38\xcd\x80\x58\x92\x64\x99\xce\x24\x03\x69\x91\xfc\xd5\x72\x40\x8a\x38\x20\x25\x4a\x82\x39\x80\x50\x6c\x19\x2d\x9f\xa0\x44\x42\x90\x07\x53\x86\x90\xaa\x84\xa8\x7c\xe8\x13\xe4\x93\xb4\xcb\x4a\x89\xb3\x39\xe8\x9e\x09\xca\x25\x97\xdb\x49\x3f\x45\x20\x15\x16\x90\x89\x97\x06\x93\x76\x1a\x5c\x22\x97\x5b\x82\xab\x83\x93\xc1\x0f\x0c\x4c\x09\xa4\x23\x54\x26\x0d\x25\x35\xf9\xa4\x73\x70\xd2\xf1\xf5\xfb\x52\x0d\x64\xc4\x3f\xf7\x3a\xee\x0c\xbf\xb7\x7f\xff\xcc\x06\x02\x02\xdf\xa0\x5f\x5b\x0c\x67\x66\x1c\x5d\xae\x67\x03\x5d\xa1\xb8\xd1\x41\x41\xfd\x04\x6f\x4e\x55\x9c\x2c\x43\x82\x76\xaa\x71\x6f\x95\xc4\x59\xa3\x84\xd3\x92\x2c\x19\xb5\x71\xe2\x12\x69\x1a\x42\xa4\xa9\x17\xab\xb8\xc9\xb8\xe6\xe3\xb2\xa2\x7a\x43\xd4\x00\x14\xaf\xac\x10\x3f\x64\xb5\xa4\x22\xc1\x8a\xca\x87\x0d\xb7\x5b\x1f\x28\xb3\x09\x06\xb5\xc3\x00\xdb\x29\x74\x6f\xcc\xc3\x6b\x5d\x9e\x64\x7c\x1d\xdd\x1c\xbd\xda\xa7\x3b\x2e\x9b\xb3\xfc\xe8\x0b\xbf\x9b\xd2\x56\x38\x1c\xa9\xc4\x4d\xe2\xe0\xfe\xce\x45\xaf\x5c\xc2\x2d\xd8\x37\x6f\xd7\xae\xe8\x9e\xf0\xd2\x33\x85\xc5\xd3\x7e\x7f\xcd\xf0\x22\x3d\x7e\xd6\x82\x70\x4e\xa6\xd0\x9d\xfa\x3a\x6b\xe0\x8c\xfe\x9c\x1a\x74\x19\xf9\x6f\x6b\x31\xd8\xe9\x6f\x70\x2c\x42\xb9\x57\xf5\xc4\xf7\xd2\x3d\x50\x76\x7b\x22\x51\xe6\xd4\x18\x9f\x6a\xa5\x5a\x5c\x24\x4d\xf4\x6e\xf4\xcb\x1c\x0c\xd3\x33\xdc\x9b\xa0\x8e\xe4\x82\x64\x7a\x52\x62\xd8\x0a\x89\xb1\x5b\x01\x72\x60\x4c\x04\xa6\xaa\xdb\xff\xfa\xc7\x90\xe3\xe6\x1d\xd7\xde\x11\xb9\xb7\x7b\xdb\x8f\xcf\x9a\x33\xbd\x7f\xfa\x29\xca\x5d\x4c\xd5\xa6\x82\x7d\x43\x8f\xc7\xf6\x84\x8e\x3f\x89\x7b\xbb\xa6\x67\x9d\x17\xcd\xa6\xc1\xbc\x5c\x0b\x5a\xda\x88\xed\x2b\x91\x53\x93\x62\xd5\x70\x15\x46\xd1\xc0\xa5\x2d\x54\x7d\xc9\x3a\x24\xc5\x43\xa5\xf5\x1a\x48\x1f\x98\xdb\xec\xe7\x3d\xdc\xb9\x3d\x07\xe5\x7b\xb3\x62\x9e\x2c\x11\x1f\x05\x3c\xba\xa4\xb9\x9e\x3a\x34\xba\xa6\x9c\x1a\x17\xab\x06\x1f\x93\x8e\x43\xa7\x83\xcf\xd1\x9d\xab\x06\xd9\x7a\x9a\xe2\xfa\x7a\x12\xc9\xe2\x21\xc3\xce\x0d\xa4\xc7\x01\x56\x9c\x6f\x03\xd8\x93\x46\xe0\x72\xdc\xf3\x80\x79\xa2\x73\xaf\xad\xd5\xb9\xf8\xbe\xd9\x48\x17\x5d\x80\xd4\x52\x6a\xed\x72\x65\xcb\x87\xb7\xb6\x3b\xb3\x90\x98\xce\x8e\x66\xa8\x6b\x61\xe5\xb4\x16\xd0\x13\x69\xcf\x53\x55\x55\x3a\x58\xcd\x0a\x88\xfb\x10\xac\xb0\xb5\xeb\x0b\xb1\xd2\x8d\xea\x7a\x3d\x90\xd2\x1e\xad\x6f\x78\x3d\x08\xd1\xe2\xd7\xeb\x7b\x5e\xa9\x0e\x4f\xb4\x65\x41\x87\x5d\x26\x57\x5f\x9d\x0e\x3b\x72\x6a\x4a\xac\x96\x52\x1d\x54\x0e\xa9\x8c\x33\x4b\x12\x26\xa5\x92\x81\x2c\xe8\xce\x5a\xa8\xf1\x4d\x70\xc1\x3c\xb1\x4b\xfa\xa0\x14\xc9\xe4\x18\x0e\xa5\x4f\x56\x54\xb7\x04\xc7\x6f\x59\x08\xa7\x58\x2f\xe3\x21\xc2\x0c\xd6\xc3\x9c\x34\x56\x3d\xae\xc7\x37\x69\x08\x30\xf8\x2b\xab\x0c\x18\x0f\x9f\x66\xf2\x4d\xf6\xa0\x2f\x37\x64\x66\xec\x6d\xb4\x25\x73\xfa\x96\x1c\x04\xc6\xc9\x76\x9d\x9b\xb1\x9c\x4a\x77\xf5\x7c\x31\x2e\x4d\xdd\xf9\x2e\x1c\x12\xff\xe4\x4f\x2e\xbe\x04\xf7\x65\xdf\x39\xf5\x1d\xfd\xd7\x83\x33\x34\x5e\xfe\x33\xb9\xff\xe7\xb3\xf5\x5f\x74\x2c\x49\x31\x01\x78\xa2\x61\x40\xf5\x3e\x59\x5f\x73\x93\xa1\xf9\x94\xcb\x44\x07\x8e\x7a\xab\x24\xca\x7a\x72\xe9\xb6\xed\xc1\x59\x35\x6a\xc2\x89\x36\xcb\x5b\x04\x77\x58\xce\xe8\x58\x85\x65\x25\xd0\x91\x65\xb3\xcb\x4d\xe3\xe8\xd4\x8c\x34\x38\x0b\x54\x2a\x6e\x0c\x95\x9a\xd4\x57\xb8\x49\x57\x2f\x9e\xa4\x7f\x31\x1a\x58\x94\xad\x6c\x78\x46\x0d\x3c\xd5\x58\x2b\xf4\x24\xdb\xd7\x88\xdb\x51\x08\xa5\xd1\x6d\x08\x06\xb2\xd5\x98\xbb\x5a\x92\xe9\x07\x1f\x5f\x85\xaa\x0a\x4c\xb8\x80\xb6\x9b\xf9\x6a\xc5\xe5\x0d\xc0\x4c\x88\x3e\x90\x4e\xdd\x34\xcb\x40\xfa\xc6\x3d\x3f\x87\xab\xd6\xd7\xeb\x23\x09\x89\xda\x43\x5c\xd8\x2b\x92\x04\x9b\x78\xf1\x49\x65\x97\xcf\x09\x29\x5d\x67\x20\xcb\x23\x35\x9e\xa0\x0e\xaa\xd3\xe5\xf5\xd1\x4f\xe6\x7c\xb2\x97\x6e\x05\x14\xae\xc1\x3c\x44\x2c\x5c\xfb\x36\xc3\x46\x06\x02\x60\x21\x60\x0f\xd7\xcf\xe6\xbb\xfb\x35\x34\xcb\x98\x83\xe9\x1f\x76\x9c\x72\xa2\x61\x1c\xcb\xe6\x3c\x3f\xe3\x9c\xd5\xaf\xae\xd2\x8d\x21\x62\xcc\xc4\x04\x99\x35\xa4\xf8\x5b\x3b\x1f\xd7\x86\x8c\x39\xf5\x77\x84\x55\x28\x83\x26\xa1\x22\xfa\x21\xeb\xc6\x25\xe9\x82\x1a\xb4\x57\x59\x67\x6e\xa7\xab\xca\x12\xfb\x42\x41\x1d\x10\xd9\x67\xb5\xc7\x55\xad\xf8\xfa\xe2\x0e\x2f\x34\x12\x61\xf2\x25\x03\x77\x95\xb4\x49\x30\x04\xe5\xf6\x56\xd5\x69\x38\xab\xf6\xb7\xc9\xca\xe1\x4e\xc1\xe1\x97\x82\xf1\xf4\x04\x18\x82\x72\xcb\x6a\x04\x66\x00\x7c\x9d\xb2\x52\x42\x91\xb6\x62\xb1\xa8\xf6\xf4\xc9\x4a\x69\x82\xbb\x9f\x7e\x06\xd7\xc4\xd6\x5c\xb3\x96\xc8\x94\x31\x03\x33\xd0\xfc\xda\x59\x1b\x81\x56\xc6\x30\x62\x5c\x8b\x6d\xa5\x1d\x67\xdd\xf5\x4f\x18\x9d\x79\xad\xc0\xad\x3c\xf5\xc4\x1b\xbe\x76\xca\x93\x17\x7e\xf3\x89\xde\x99\x8f\xac\x79\xfa\xb7\x38\x77\xcc\x31\xe7\x5f\x3f\x6f\xf6\xd1\x17\xcd\xe6\x7e\xde\x73\xf7\xa3\x67\x2d\xbb\x1b\xdf\xfb\x1b\x7c\x4c\x65\xd3\x26\xcb\x04\x4d\x6f\xd7\xb1\xb3\x66\x1d\xfb\xe1\x2b\x5f\x39\x1d\x7b\x5f\x3d\xf5\x6b\xab\xff\x7c\xee\x69\x27\x7c\xf5\x9e\x1a\xdf\x7a\x09\xce\x0a\x1a\xe9\xff\xc4\x98\x8e\xf2\xea\x1e\x2c\xc1\x05\x35\xcc\x9b\x17\xb8\xd7\x0f\xd9\x58\x05\x67\x55\x51\xaa\x92\x78\xde\x8c\xee\x4d\x5e\x32\xa8\x0b\x78\x25\x12\x86\xba\xc0\xd3\x50\x17\xf0\x78\xc3\x81\x6c\xd9\x47\x9f\x25\x8f\x37\x6c\xc9\xe6\xf8\x8a\x48\xf5\xf8\x20\x7f\xe3\xf1\x85\x6b\x05\x70\xaf\xac\x54\x1c\x2e\x1d\x7f\x52\x04\x36\x62\x88\x05\xf4\x1c\x4e\x01\xa7\x19\x71\x17\x4e\xf3\x06\x61\x59\x47\xb6\x96\x0e\xa7\xae\xdd\xd7\xff\xfa\xd1\xc3\x1b\xb1\xa8\x55\xde\xb8\xf4\xd2\x47\x17\xae\xbb\xf9\xab\x2b\xe7\xb5\x98\x99\x8f\x5f\xbe\x74\xef\x7b\x03\xc3\xb7\x70\x7d\xc3\x6f\xf0\x3d\x17\x5f\xb2\x78\x31\x5e\x55\x97\xfb\xe0\x3f\xb3\xa5\x91\x1f\x45\xd1\xc0\x68\xcf\x0e\x93\x98\x51\x15\x02\x7f\xce\xcf\xbc\xb2\x5a\x08\xe2\xae\xf3\xbb\x22\x7c\x87\x1e\x7b\x58\xd2\x11\xee\x9b\x5e\x9b\xd6\x7e\x64\xcf\xc0\x37\x7f\xd6\x7e\xce\x6a\x4b\x26\xc2\xad\xfd\x8f\xf4\xf8\x7f\x6a\x1e\x6b\x0a\x82\xea\x48\x9b\x26\x3c\x0a\x79\xc4\x08\x4a\xa1\x47\x1b\xe9\x28\xc5\x9b\xbe\xa6\xae\xa3\x04\xd3\x91\xe9\x6b\x8e\x51\x50\xaa\x4e\x41\xa9\x40\xb6\x1c\xa5\xcf\x92\xc7\x9b\xb2\x28\x28\x4a\x15\x14\x65\x0a\x8a\xa6\x4c\x05\xc1\xf8\x98\x2f\x02\x54\xd1\x15\x87\x4b\x56\xa0\x57\x4c\x54\x40\x51\xa9\x71\x14\x65\x09\xcb\x4d\x95\x8d\xd6\xd4\x34\x33\x36\xff\x13\xd3\x59\x9d\xae\xcc\xe0\x5c\xd8\x43\x95\x86\xb8\x91\xfb\xb5\x69\xfc\x66\x61\x15\x72\xa2\x18\x9a\xc6\x6a\x08\x25\x37\xd5\x95\x1f\x74\xd5\x04\x45\x84\x18\xcb\xc7\xa9\x31\x97\xac\x94\x1c\x02\x63\x08\x72\xbb\x64\xa5\xec\xf5\x05\x42\xa0\xaf\x5a\xdd\x20\x8e\xeb\x35\xf7\x55\xf3\x8d\xbe\x3f\x4a\x75\x96\x62\x82\x55\x7b\xe6\xbe\xfa\xa3\x79\x07\x3f\xd2\x48\x67\x6d\x35\xde\x67\x5d\x67\x29\x5d\x67\x1d\xe3\xe9\xac\xad\x4e\x67\x6d\x81\x6c\x39\x41\x9f\x25\x8f\xb7\xcd\xa2\xb3\x04\xd5\x59\x82\xe9\x2c\xd1\x56\x8b\x1f\xd8\xa6\xf2\x29\x31\xb6\xa9\x4a\xce\x60\x14\x24\xd1\x36\xee\xc6\x6a\x30\xcd\xd7\x40\x67\x5f\xb6\x46\xcd\xed\x0d\xd4\x66\x4d\x27\xec\x8f\x83\xe6\x8c\x9c\xc2\x44\xd8\x67\x49\xaa\xbb\xd1\xfb\xac\xd9\xdc\x67\x2d\xfa\x3e\x2b\x61\x49\xae\x0b\xf7\x1b\xee\x35\x37\x1e\x13\xe7\x5b\xb5\x76\xdc\xe8\x18\xdf\xd0\xdb\xa8\xe0\x9e\x43\xdd\x23\xbb\x85\xcb\xec\xab\x00\xfd\xe4\x6c\x54\x6a\x35\x6a\x1f\x32\xbd\x55\xe1\x54\xec\x81\xd1\x87\x98\x04\x1d\x96\x36\x9c\x55\x5b\xd8\x64\x21\x8c\xd0\x97\x5c\x7c\xab\xde\x8b\xdf\xd6\x5e\x2c\x92\x16\xa5\x22\x87\x13\x9d\x13\x19\xd4\x6c\xab\x31\xeb\x53\xc6\xde\x20\x1c\x73\xb2\x42\x02\xc5\x49\x7d\x03\x32\x63\x9e\xea\xc5\xc0\x3f\x38\x03\x17\xf2\x11\x3b\x5d\x98\x41\x51\x28\x64\x5a\x4d\xef\xa2\xfb\xb9\x87\x2e\xfa\x6e\x3c\x7f\xc6\xb5\x17\x7d\xe7\xfd\xdb\xde\xae\x9c\xbf\xf1\xfb\x27\x9c\x73\xe4\xaa\xd5\x97\x69\xbf\x19\xfe\x2d\xbe\x5b\x3f\x5a\xe6\x60\xe5\xbc\x2f\xcf\xcb\x1e\x31\x75\xde\x19\xcf\x5f\x74\xc5\x6b\xdf\x38\xa3\x3a\x6f\xf9\xbc\xe9\x5f\x99\xbf\xe8\xb9\x2b\x76\xfc\xc3\x36\xb3\x0e\x9f\x2b\x32\xb2\x9b\xff\xb3\x2d\x0d\x3e\xd4\x4a\x04\x44\x54\x2a\x6f\xab\xc2\x76\x52\x83\x3a\xc3\x82\xc7\x84\x7a\xa1\x6b\x4e\x32\xec\x0f\x35\xe2\x91\x95\x8a\x93\x4f\x81\xeb\xa4\x26\x6d\xb2\xb2\xc5\xaf\x04\x9b\x74\xf7\x89\x4f\xb1\x05\x07\xe5\x32\xf6\x28\x10\xee\xf9\x69\xcc\x3a\xa9\x6f\xa0\x9e\x6f\x71\xf4\x72\xeb\x10\xc8\x22\xf7\x3c\xb0\x68\xe5\xbc\x15\xab\x4f\xfd\xed\xf6\x6d\x0f\x9c\x71\xfd\xb7\x8a\x73\x0e\x5f\xb6\xe6\x82\xbd\xff\x73\xee\x7d\xf8\xab\xfa\x6a\x7b\x3e\x5b\x7e\xc4\xd4\xec\xac\xc9\xb3\xae\x39\x79\xf3\xd3\x5f\xdd\xb5\xa4\x90\xed\x9c\xd6\x33\xf3\xd6\x53\x9f\xd9\xd6\x2c\xbc\x51\xb7\x56\xaa\xdf\x33\x41\xbf\x79\x74\x6e\x43\xfd\x16\x1a\xe9\x77\xb2\xae\xdf\x8a\x8b\x6f\x6d\x03\x62\x3f\x9b\xac\x76\xe5\x4d\x0d\xf7\x4e\xfa\x37\x68\x78\xd4\x38\xc1\x81\xf4\x7c\x5d\x5d\xa3\xc7\xc1\x94\x3d\x0a\xfb\x8b\xea\xfb\xd7\xa0\xef\x3e\x74\x5e\x43\x7d\xe7\x1b\xe9\xbb\xa0\xeb\x7b\x0b\xe8\xbb\x8f\x09\x81\x74\x16\x49\x52\x19\xa4\x4a\xef\xea\xc9\xfd\xdf\xb5\x3e\x4a\x06\xe3\xeb\xfe\xb8\x3a\x09\x1c\xd8\x00\x46\xad\xbf\x5b\x0b\x0a\x4b\xc5\xd7\x50\x06\xf5\xa3\x07\x98\x0d\x54\x26\xb2\x89\x7a\xc3\x0c\x48\x21\x57\xe9\xd0\x39\xc0\xa6\x58\x0c\x82\x4c\x4a\xed\x94\x2b\x5d\x40\x02\x46\xba\x72\x95\x49\xec\x93\xc5\x52\x06\x70\x56\xed\xa2\x96\xe2\xee\xc8\x4e\x2c\x00\x24\xa8\x5c\xe1\x5d\xad\x3d\xbd\x74\x87\xb4\xd8\x64\xa5\x24\x87\x19\xba\x53\x47\x41\x56\x48\x7f\x91\xb4\xca\xe5\xb6\x2c\x58\x90\x1a\x9e\x08\xd8\x99\xba\xe9\xc8\x87\x6c\x3a\xfc\x18\xbe\xb0\x03\x59\x4f\xbc\x8e\x34\xec\x80\xd6\xa3\xfd\xa9\x9e\x3d\x0c\xec\x47\x0b\xf2\x9b\x84\x55\xa8\x15\x4d\x46\xff\xc9\xec\xa7\x92\x65\xf2\x33\x4c\x88\xe4\x73\x95\x76\x5d\x7e\xfd\x16\x63\x22\x39\x2a\xbf\x4e\x26\xb5\xce\x5c\x25\xc7\x3e\x59\xac\x6c\x0a\xce\xaa\x9d\xf4\x54\x71\xb5\x4f\xc8\xe6\x19\x6d\x4b\x99\x77\xa6\x00\x63\xd4\xa6\x90\x89\x45\x92\x93\x89\x9f\x5a\x5d\x49\x09\x36\x81\x20\xdb\xf3\xb2\x42\x26\x03\x04\x5d\x66\x02\x58\xa1\x1a\xcc\x52\x41\x1a\xe6\x27\x1f\xb2\xf9\x8d\x91\xe3\xf8\x16\x28\xd4\x49\xf1\x00\x16\xa8\x6d\x1b\x2b\x43\x7a\x0e\xdd\x02\xe7\x50\xdf\x38\xe7\x50\xbe\xd1\x39\x54\x68\x74\x0e\x75\xe4\xcc\x73\xa8\xab\xf7\xdf\x72\x0e\x59\xef\xd2\x03\x19\xd2\x53\xd6\x7b\xf5\x80\x76\x64\xbf\xa0\x1e\x0f\x2e\x32\xb2\x5b\x68\x85\x33\x68\x12\x5d\x7f\x83\x33\xa8\xaf\xd1\x19\x94\xaf\x3b\x83\x7a\xf5\x33\xa8\x9d\x5a\x03\x5c\x3c\x9d\x3d\xff\x8e\x23\xc8\xba\xfc\xf1\xf5\x7f\x8f\x75\xf1\x07\x50\xbf\xa8\x8d\xf2\x31\x36\x68\x41\x61\x87\x38\x88\x64\x14\x43\x77\xa2\x52\x94\x55\xd2\xd9\xaf\x91\x42\x29\x00\x6d\xb4\x7c\x55\x0d\xc7\xf2\x79\xe2\xcf\x55\x38\x7d\x23\x35\xe5\x48\xd4\xdc\x48\x1e\xba\x91\x04\xb6\x7d\x84\x5c\xc5\xc3\x78\x09\x8d\x0a\xf4\x7d\x7b\x5e\x05\x2f\x32\x2a\x91\xd8\x10\xfd\xe3\xe1\x21\x5e\x0d\xc7\x58\x59\x49\x88\xca\x4a\x89\x73\xf8\xa1\x6c\x20\xeb\xbc\xd7\x9c\x9e\x4e\x8e\x1a\xed\xd4\x63\xb7\x42\x1c\x43\x58\x1f\xd8\x50\x67\xf8\xf1\x01\x7e\xcf\x80\x76\x9f\xa6\xbd\xa1\x69\x6f\x5a\x0d\xdd\xb6\x1e\x73\x9a\xf6\xf9\x02\xa1\x82\x38\xb4\x54\x0b\xf2\x17\x8a\x0b\x90\x8c\x26\xa0\x57\x19\x0a\x6d\xc5\xc1\xce\x8c\x08\x55\x79\x93\xbd\x4a\x26\xe4\x4b\x91\x26\x57\xb6\x7c\x78\x24\xe4\xcc\x96\x82\x2c\xa5\x6e\xae\x3e\x9b\x23\x9d\x3b\x49\x77\x9e\xda\x01\x89\xe7\xcb\x42\xb2\xd3\x91\x35\xd6\x3d\x51\x5f\xf7\x1d\x7b\x1e\xa2\xeb\x16\x48\x77\xaf\x48\x26\x0c\x09\x6a\x3c\xbe\x57\x24\x4d\x43\x3c\x52\xe3\xdd\xbd\xbd\x58\x6d\x9a\xa0\xcb\xa0\x53\x56\x2a\x9c\xdd\xe1\x0f\x00\x3c\xba\x5c\x72\x05\xdb\xa0\xdc\xac\x94\x9c\x21\xd6\x60\x6e\x48\xa4\x4d\x2e\x23\xbb\xcb\x43\x4f\x95\x26\x87\xac\xa8\xad\x9d\x20\x37\xd8\x4e\x63\x85\x14\x98\xc9\x15\xec\x69\xbb\x0e\x9f\xaf\x63\xc0\x4c\x1e\x08\x2c\xad\x13\x9a\x23\xf9\xe2\xf7\x9f\xef\xc3\xf1\xbc\xf6\xc1\x2a\xdb\xb2\x23\x4e\xbb\xf0\xee\xdb\x37\x78\x56\xd5\xcb\x4f\x5c\x78\xcb\x92\xdd\x1f\xbd\x3f\xfc\x7e\x73\x64\x5e\xe6\xdd\xfe\xef\x7e\x3f\x3f\x83\x8b\x53\xfb\x79\x04\x21\x61\x87\x7d\x15\xb2\xa3\x10\x5a\x82\x4a\x36\x6a\x37\xa2\x5e\x9d\x44\x3c\x1b\x4c\xc3\x24\x0c\xad\xa8\xa2\xbf\xaa\x46\x46\x19\x85\x4d\x22\xf6\x21\x22\x4a\x44\x18\xe2\x55\xc1\xae\xe3\x0e\xda\x64\x45\x75\x38\xa1\xc0\x68\x28\xba\x1e\x61\xf0\x91\x9a\xa2\xd7\xd4\xf9\xd3\x15\x43\xcf\xdc\xc3\x16\x4b\xe7\xd0\x8a\x91\xdd\xc2\x35\xb6\x2e\xc0\x30\xda\xa0\x33\x8d\x78\x9d\x55\x70\xf5\x55\x87\xbd\x4a\xa2\xf9\x92\xe8\xa0\x0a\x17\x79\x67\xb6\xc4\x41\x04\xd0\x9a\x23\xa1\x9d\x24\x92\x87\xb1\x5a\x67\xde\xcc\x57\x99\x9a\x8d\xf4\x8a\x24\x3a\x24\xa8\x4e\xaa\x59\x07\xd5\xac\x33\x42\x35\xeb\x88\xb2\x85\xb8\x43\x34\x68\xe0\x14\xd0\xa1\x57\x61\x48\xc5\x0e\x59\xf5\x87\x8a\x10\xad\x62\xaa\xb6\x71\x94\x64\xfa\x9c\x2b\x1a\xea\x07\xef\xd3\x9b\xa6\xf8\xd5\x0d\x54\x83\xcf\x32\xbb\xa8\x30\x7a\x98\xea\x48\x1c\x44\x7e\xf4\x03\x54\xf2\xb1\x2e\x37\xd6\x20\x2f\xf0\x55\x95\x77\xe4\xf3\x15\x84\x7d\xa2\x97\x35\x9b\x81\xda\x3c\x7e\xaa\x36\x29\x47\x7c\x10\x1c\x9a\x3d\x79\xb7\xec\xb9\x89\x65\xea\x24\xc2\x43\x44\xe8\x18\x22\x3e\xa9\xcc\xf9\xf8\x40\x96\x78\xa5\xb2\xd3\xeb\x08\x64\xcb\x1e\xfa\xa4\xdf\xfb\xe9\xf7\x3c\xb4\xcb\x7b\xfc\x56\x70\x1a\x00\x10\x04\xd8\x69\x36\x22\xf9\xf0\xc0\xef\x16\x68\x9b\x98\x52\xe7\xff\x65\xe0\xc3\xb5\xda\x1b\x6b\xb9\x25\x1a\x3e\x9d\xaa\x53\xbb\x57\x1b\x7e\x94\x5b\x02\x35\xaf\x96\x91\xdd\xb0\x77\x53\xe8\x22\x9d\xeb\x3d\xe4\x64\x1c\xb5\xaa\xc7\x5e\x25\x7c\xbe\xe4\xf4\x50\x2d\x3a\xed\xce\x2c\x74\x44\x57\x10\x6e\xb2\x7b\xe9\x92\x55\xe4\xa9\x12\x7f\x1e\xf2\x14\x49\x36\x09\xd0\x8a\xb3\x6a\x20\x29\x2b\x5b\x38\xd1\xc6\x37\x31\xa4\x92\x50\x93\xac\x90\x28\x0c\xb5\x44\x92\xc5\xa2\xea\xf4\xe8\xb8\x97\x81\x81\xc2\x40\x46\x57\x96\xbd\x60\xcf\xd8\xeb\x14\x36\x13\xb7\x74\x5f\xd5\xfd\xa3\x9a\xae\xba\xab\xdd\x7f\x69\x31\xf5\x95\xc6\x7b\x5e\x7e\x0e\x14\xf5\xdc\xcb\xb7\x1a\x9a\x3a\xb2\xf7\x56\x38\x83\x47\x76\x8b\x77\xd9\x4f\x45\x41\x34\x01\x55\x74\xdb\x74\xba\xab\x25\x9e\xaa\xc8\xeb\x2b\x14\xc0\x10\x0b\x6a\xc2\x53\x2d\x77\x26\x5a\x1d\xf4\xda\xa9\x92\x96\x1a\x01\x87\xdf\x24\xe0\x60\x83\xde\x21\x9c\xad\x4c\x60\xe5\x83\x09\x3a\x07\x87\xbf\x5a\x6e\xf1\x79\x1d\xd9\x4a\x8a\x0d\xde\x4d\x34\x67\x9e\x9f\x33\xab\xe0\x1e\x68\xa8\xf5\x0f\x21\x95\x2a\x0b\xc3\x13\x22\x77\x81\x97\x15\xd5\xa9\x14\x8b\xaa\x77\x82\xac\x94\x22\x89\x56\x46\xc6\xe2\x84\x9b\x6d\x2c\x47\x07\x87\xd2\xad\x1d\x8d\x46\xf5\x36\xf8\x5f\xc4\x7d\xcf\xcb\x3f\x5f\xf3\xc3\xd4\xf3\x38\xbf\xad\xa8\x3d\xab\x69\xbf\xfe\x07\x5e\xd3\x70\x76\x0f\xdf\x34\xf7\x48\xfe\xee\xfd\x67\xcf\x2b\x94\xee\xfc\x11\x7f\xdb\xfe\x85\xda\x27\xda\x9e\xf7\xc4\xe5\xa3\xa6\xf9\x0c\x9e\x16\xc6\x55\x77\x6b\x23\xd6\x92\x03\x33\xd5\xd5\xf1\x97\x94\x23\xf4\x93\x41\x59\x57\xe3\x72\x21\xad\x79\xe2\x93\x6a\xfc\x74\x10\x65\x33\xb9\x04\xa9\x5c\x26\xca\x8c\x85\x27\xd1\xf9\x05\x98\x5c\x1a\x48\xa8\x31\x87\xc9\x70\x63\x01\x35\x62\x32\x99\x33\x76\x96\x13\xec\xcb\xa6\xa1\x20\x8a\xa2\x6b\x1b\xda\x57\x08\x88\x08\x8c\xd4\xe2\x18\x7b\xd2\x2d\x48\x6d\xfa\x42\x46\x63\x97\x95\xb2\x53\x09\x85\xe9\x65\xe5\xf3\xca\x8a\x9e\xb1\x3e\x88\xd5\x0c\xa4\xc7\xb3\x92\xed\x50\x84\x6c\x6c\x14\x27\xb3\x1a\xaa\x6e\x0b\xe2\xa3\x28\x8c\x9a\xd0\x37\x1b\xd9\x42\x24\xa7\x46\xe9\x52\xe3\x07\xa6\xee\x49\x8c\x43\xb5\x54\x92\x64\x7a\x9a\x03\x27\x51\xac\xe9\x0b\x70\x12\x0d\xa4\xc7\xa3\x23\x9a\x0f\xeb\x6a\x48\xd1\x43\x57\x65\x9c\x0f\x6b\x51\x10\x65\x68\x8c\xd3\x40\x7f\x69\x28\x0b\x97\xe2\x69\x7a\xf4\xc5\x9b\x9d\x59\x12\xc9\x1b\x94\x2f\x0d\x4f\x07\x83\xb9\x0d\x16\x4c\x9a\xf3\x54\xbd\x95\x16\x56\x64\x6d\xff\x17\x8f\x86\xa8\xac\x90\xf4\xc1\x15\x5c\x5f\x75\x1c\x47\xd7\x2f\xd4\x57\x1d\x1b\x2a\xdd\x76\x5e\x1d\xa7\x82\x71\x0e\x64\x81\xaf\xe9\xfe\x46\xba\xcf\x40\x37\x40\x29\x99\xa1\x62\x4a\xa6\x9c\x59\x12\xcb\x8f\x4b\xe2\x14\xc1\xd9\x4a\x13\x13\x53\x93\x69\x17\xe5\xb4\x71\x88\xca\x42\x96\xa4\x72\xf4\x40\xa0\x32\xeb\xac\x3f\x0d\x9a\x64\x60\x78\x4a\x66\xa8\xed\x43\xdf\xc4\x17\x20\x36\xaa\x93\xcf\x38\x36\x73\x6c\xbd\x7c\x1a\x11\x74\x2d\xab\xc3\xf5\x04\x1b\x72\x08\x28\x08\x1c\xf9\x2f\x34\xb4\xa2\x66\x83\x12\x9f\x4c\xc8\x55\xa2\xba\xab\xdb\x33\xbe\x11\xd5\x06\xde\x8d\x2b\x26\x0e\xd2\x61\x84\xf9\x34\xa4\x8e\xd7\x93\x78\x7e\x41\x8b\xea\x4c\xcb\x8a\xda\x6c\x3d\x34\xd4\x09\x6d\xb2\xa2\xc6\x43\xc5\xf1\xad\xab\x31\x85\x7e\x63\x33\xe3\x3a\xc7\x72\xe7\x37\x36\xb5\xb9\xa3\x99\xf3\x6b\x7c\x59\x25\xa8\xf8\xf6\xa2\x7b\x1a\x59\x5c\xca\x48\xdd\x90\x89\xb9\x4a\x93\x2e\xd2\xdc\xf8\x06\xa7\x73\x2d\x66\x6a\xf7\x4e\x37\x8d\xad\x58\x2f\x80\x3a\xa9\xce\xca\xba\x33\xd4\xca\x94\xa6\x94\xcc\xc2\x86\x31\x36\xc6\x18\x17\x93\x91\x46\xd2\xb2\xd2\x68\x35\x90\xd7\x38\x66\xf7\xd0\x58\x79\x35\x32\xbd\xc9\xa3\xa5\xc5\xec\xef\x73\xfb\x2a\x14\x44\x49\xd4\x81\x6e\x6c\x64\x7f\x98\x74\x1e\xf8\xfa\xe9\xfa\x57\xaf\x1f\xe2\x95\xcb\xd1\x64\x33\x23\x93\x53\xca\xb1\xa6\x34\x6b\x93\x38\xc8\x49\x35\xa6\x89\x60\x9c\xc3\x6a\xdb\xa8\xf6\x81\xf1\xee\xa8\xd1\x5d\x03\xba\x0d\x89\x8b\xf5\x3e\xe7\x2e\xb4\xaa\x21\xcb\x5c\xf7\x81\xaf\xaa\x09\xe3\x5c\x55\x83\x92\xac\x34\xb5\xa4\xd2\x0c\x45\xa1\xe2\x8f\x27\x32\x5d\x87\xee\x9c\x8c\x5d\xfd\x38\x36\x31\x63\xf4\xea\x1b\x93\xcd\x8d\x59\x3b\xe4\x1e\xc4\xbb\xc4\x41\x14\x44\x1d\x68\x33\xb3\x08\xfd\xd8\xb1\x1c\x4a\x6d\x39\xb5\xc5\x53\x1d\x63\x1b\xd4\x1f\x16\xfc\xd5\x4a\xc2\x9c\xec\xfe\x97\xac\x24\x81\x64\x45\x8d\xb6\x41\xc7\x6f\xc5\xa9\xc4\xd2\x8c\x8d\xb6\xa5\x4d\x56\x48\x6b\x91\x28\x72\x29\x04\xd0\x23\x2a\x1f\x95\x15\x15\x39\xc7\x3d\x78\xc6\x82\x8a\x36\x36\x96\xff\xa9\x67\x89\x69\x68\x29\x9a\x63\x2c\x47\xcc\x85\x5a\x50\x28\x09\x2b\x50\x18\x75\xa1\x9b\x99\x95\x90\xa6\x42\x83\x13\xa7\x23\xa7\xa6\x3d\xd5\x71\x8d\x86\x1e\x32\xcd\x4c\x66\xcd\xf5\x26\x54\x3b\x58\x9a\x23\xb2\x52\x92\x9a\x3a\x58\x23\x74\x49\x56\x58\x8f\x6b\xba\x43\x56\x48\x5b\x91\x48\xb2\x1a\xc9\x14\x8b\x84\x3f\x24\x96\xbe\x51\x52\x19\xc7\x88\xee\xac\x17\x4b\x03\x13\xd2\xe6\x8c\x12\x0a\x87\x9e\x40\xc8\xfe\x27\xfb\x2a\xc0\xa5\xbc\x08\x95\x9a\x11\x20\x00\x94\x10\x40\xa0\x29\xf4\x40\x61\x3d\x46\x18\x86\x9c\xe9\xb2\xa3\x74\xd9\x39\x82\x19\x44\x8b\x9e\xaf\xc9\xe1\xac\x8a\x9b\x65\xa5\x24\x88\x36\x06\x3d\xb1\xc5\xd5\x94\x6c\xc9\x40\x96\xd7\xa3\x94\xdd\xfe\x10\x2b\x21\x21\xfa\x87\x44\x5f\x8c\x31\x89\xa4\x03\x41\xc0\xa0\x19\xc0\xe9\x40\xd0\x5e\x80\x21\xdf\x34\xdf\x39\x79\x20\x63\xb3\xe3\xf4\xa8\xf1\xd8\x27\x70\x8b\xcd\x61\x73\xa4\x8f\x77\xe3\x6f\x60\x5f\xc8\xe9\xe8\x5f\x80\xe7\xe1\xfe\xe1\xd5\xda\xc3\x61\xce\xe6\x98\x3c\x5d\x7b\x46\x7b\x0c\xbf\x3b\x0a\xfd\x6a\xff\x1f\x26\xef\xe9\x3f\xe5\x57\x11\xbe\xb0\xff\x8e\x9b\xbf\x7b\xdf\xb3\x7c\x62\xdf\x3c\x6e\xc7\x37\x56\x2c\xff\xf1\x0f\x86\xfb\x46\x03\x62\x71\x68\x2d\x42\xb6\x41\x5b\x1a\x25\x50\x16\x9d\x8e\x4a\x09\x2a\x8f\x40\xa1\x84\x68\x70\xec\x94\xa9\x3c\x58\xff\x91\x0e\xc3\x42\xaf\x70\x37\x73\x5f\x7a\x70\x96\x01\xed\x08\x62\x82\x8a\x20\x24\x6f\x71\x46\xe3\xc9\x34\xc0\xef\xba\x95\x92\xd7\xd7\x0d\x26\x80\x12\xf4\xcf\x78\x23\xa6\x04\x40\x00\x81\xb4\x0c\x02\x08\x50\x01\xc0\xfa\xf9\xd1\xeb\x5f\x8b\x63\x82\xdb\xe9\x99\xd5\xf4\x27\x3c\xd7\xe5\x3a\xbe\xe3\x1d\x5c\x18\xfe\x48\x1b\xb4\xb9\x3c\xcb\xe3\x55\xed\x19\xbc\xa8\x6e\xe5\xc2\x0a\x4d\xde\x71\xc5\xc4\xa1\xe9\x5c\x74\xf8\xcf\xcf\x9d\xb5\x6f\x19\xfe\xf8\xf3\x07\x38\xc7\xdd\x4f\x8e\x1c\x3e\xfc\x5e\x3d\xb5\x3c\x5d\xf7\x53\x08\x89\x33\xed\xab\x90\x03\x45\x80\xc9\x8f\xae\xdb\xc6\xec\x00\xe6\x81\xa2\xd0\xfa\x6c\xf3\x56\x89\x4d\x22\x18\xb8\xe3\x25\xc6\x76\x2b\xd5\xf0\xa6\xee\xdc\xf3\x53\x76\x5c\xc0\x54\x34\x9b\x90\x1e\x33\x1b\x8d\xed\x74\x8f\xb8\xa0\xa8\x4a\xc0\x24\xec\x00\x5f\x04\xc2\xc0\x69\x0c\x79\xaa\xba\x85\x3f\x85\xa7\x5e\x81\xbf\x85\x97\x0e\xdf\x7e\xa9\xb6\xe3\xd2\x45\xa3\xe1\xcd\x08\xb7\x68\xff\xea\xe1\x1d\x5c\x8e\xdf\x3f\x1a\x77\xd5\xca\x41\xd9\x8e\x66\x8c\xe5\xa0\xec\x30\x39\x28\x3b\x75\x0e\xca\x92\x2d\xc2\x2a\xea\x87\xce\x43\x59\xf7\xb2\x07\xe2\x18\x3c\xbf\xee\xd5\xc7\xe3\xa4\x1c\x83\x1d\xcb\x74\xb3\x14\x39\x90\x82\x12\xe8\xc1\x31\xda\x21\x72\x8e\xc4\x0b\xaa\xc7\xcd\x90\x94\x92\x07\x50\x15\xfd\xca\x47\xbf\x72\x7a\xab\xc4\x99\x03\xef\xc8\xc6\x10\x3d\xa2\xde\xda\xc0\xfe\x21\x29\xd2\x46\x15\xe9\x91\x8b\x45\xd5\xe7\x64\xc0\x5d\x63\x55\x19\x6f\x44\xc3\x58\xaf\xcf\x64\x3d\xf1\xa2\x55\xa1\xc2\xfa\x51\x7c\x8b\xdc\xc8\x0b\x08\x09\x04\x38\x5b\x14\xd4\xab\x77\x64\xd8\x8d\x2e\x39\x9e\xaf\x62\x12\xc8\xa9\x41\x9c\x45\xaa\x9d\x35\xf5\xc0\x99\x0c\x48\x8c\x19\x7a\xca\xa4\xed\xd6\xe1\xdf\xe9\x1d\xbc\x73\xf8\xdd\x7e\xfe\x91\xee\xfd\x7b\xb8\x25\xfd\xda\x16\xbd\xfe\xbc\x8d\xff\x2b\x46\xaf\xee\x0f\x5a\xa7\x80\xb9\x91\x1d\x08\x09\x4e\x5b\xda\xf8\xb7\x9d\xf0\x6f\x3b\xf4\xde\x44\xde\x61\xfd\xb7\x9d\x0d\xfe\xed\x01\xfa\x6f\xdb\xcd\x7f\x3b\x97\xe1\x66\x6a\xab\x0a\xdc\x47\xd9\xe1\x57\xf1\xe3\x7d\xda\xdf\xf4\x7f\xbb\xc2\x3d\x57\x7d\x65\xf8\x84\x6a\xdd\x0c\x93\xbe\xee\x95\xc8\x89\x82\x68\x4e\x83\x75\xd3\x7f\xda\x2b\x54\x31\x09\x41\xb7\x8c\x24\x55\xe9\xf1\xac\x4a\x2e\xba\xd9\x38\x6a\xcf\x07\x92\x47\xcd\x83\x1d\x2d\x91\xa7\xf4\xb9\x48\x8b\x44\x06\x2d\x18\x9a\x54\x26\xfc\x56\x98\xff\x85\xf7\x1a\x23\x93\x43\x78\xaf\x03\xc8\xaa\xf6\x5e\xa3\xa5\xf5\x8e\xfe\x5e\x86\xb4\x6a\xe0\x2e\x56\x1b\x89\x8c\x63\x23\xd1\x1c\x3d\xb3\x0e\x62\x23\xd6\x5c\xf9\x28\xb1\x0c\xff\xc5\x9a\x30\xaf\xc9\x66\xcc\xcc\x0d\xd8\x4c\x1e\x6c\x26\x32\x8e\xcd\x98\xef\x72\x20\x9b\xb1\xbe\xcb\x68\x51\x24\xad\xef\x62\xc8\xa3\xbe\x11\x06\x8f\xb8\xb4\x20\xff\x9c\xad\x05\x85\xd0\xe9\x88\xea\x84\x03\x74\x13\xd5\xe1\xac\x62\x12\xce\x99\x25\x05\x13\x96\x44\xa0\x5b\x5e\x95\xe3\x7b\x89\x34\x84\xca\x82\x28\xc9\x6c\x9a\xc1\xf8\xa4\x8f\xa0\x06\x18\x95\x93\x97\x9d\x91\xc4\xc1\xc0\x1e\xe8\x49\x39\x80\x6b\xb5\x48\x3b\x1c\x94\x9f\x4c\x9f\xf2\x83\x36\x2c\x4d\x78\xe1\x67\x57\x9c\xbb\x68\xf6\xe1\xc5\xd9\x3e\x6d\xf7\xb1\xda\x93\x67\xcd\x79\x37\xb4\x59\xd0\x86\x7e\xda\xf7\xfb\x96\x45\x47\xec\xfb\x8b\xb6\x21\x86\x38\xd4\x3e\xb2\x1b\xf8\x78\xe3\xa8\x1b\xfd\x97\xde\x57\x04\x24\x53\x2d\xce\xea\xb8\xa8\x7d\x13\x72\x24\xc3\x92\xd2\xd9\xd1\x08\x7d\xbd\xc4\xd6\xeb\x23\x48\x52\xbb\x13\x7b\x45\x7a\xe4\x89\x89\xbd\xa3\x41\xf9\xba\xa5\xb2\xbd\x1b\x40\xf9\xba\x01\x94\xef\x88\xbf\x77\x41\x97\x56\x17\xfd\xb1\xd4\xd5\x6d\x05\xe5\x53\xbb\xba\x01\x92\x0f\x31\x4c\x3e\xfa\x93\x15\x92\x2f\x90\xa1\xf6\xed\xa0\xf6\xdd\x82\x18\xaa\x0d\x27\x97\xa4\x40\xc7\xf8\x10\x7c\x8c\xa9\xd7\x5e\xcf\xd3\xdb\xae\xfd\xb0\xfb\x87\x19\xdc\x93\xc1\x99\x6e\xed\x9d\x8e\x66\xc7\xd1\xeb\xe7\xdf\xb4\xf9\x07\x1f\xfd\xf0\xf9\xc5\x8e\x2f\xfd\x68\xde\x11\x47\x7d\x7b\xfe\x11\x47\xce\xbb\x6c\x21\xc3\xe3\xbb\x71\xc9\xf1\xb3\x5e\x2f\x3f\xab\xdd\xf3\x5f\x3f\xbe\x11\xdf\xb8\xe8\xd4\x6b\xff\x7e\xc9\xa2\xf9\xdf\xde\x4d\xef\x90\x95\x08\x89\x2f\xc1\x3c\x4f\x06\x65\x51\x19\x41\xa3\x31\x51\x0a\x6a\x82\xd7\xc3\xc7\x20\x5f\x55\x03\xd9\x7c\xbe\xd2\x96\x91\x79\x6f\x56\x6d\x33\x9b\xad\x75\x9e\x4c\x12\x61\xdd\x6d\x3e\xa9\x4a\xba\xe8\x1d\x62\x97\xa0\x69\x48\x6f\x3f\x7e\x9a\x01\xfe\xf4\x92\x6c\x2f\x51\x24\x35\x21\xec\x25\x59\x49\x0d\x08\x7b\x49\x42\x2a\x67\x12\xd9\x40\xb6\xdc\x46\x9f\xfc\x16\x25\x90\xc8\xb4\x65\x6b\x63\x71\x5d\x29\x83\x6d\x43\xcd\x24\x00\x3e\x97\xb4\xc9\xf0\x05\x09\x2a\x25\x3b\xd2\x9d\xc5\xc9\x53\x0a\x7a\x63\x5b\x08\x0a\xdb\xdd\x18\x43\xa5\x37\x92\xd1\x59\x2b\xb2\x78\x40\xff\x75\xe5\x7b\xaf\xe1\x3f\xfc\xe9\xcf\x3f\xb9\xf3\xcc\x4b\xb5\xd7\xb5\x7f\x0c\x7f\x82\xd1\xe4\x59\x27\xd8\xde\x73\x72\x91\xca\x25\x57\x0d\x3e\x5c\xb8\x7d\xf5\x65\x9b\xef\x10\xfa\x06\xdf\x78\x68\xd3\xed\xcf\xa5\x1c\x4d\x1b\x2e\x78\xff\x33\xe1\x89\xaf\xcc\x49\x44\x93\xc3\xe8\x9b\x5f\x7f\xe0\x93\xd3\x97\xaf\x37\x67\xe7\x37\x01\xae\x4a\x10\xad\x61\x4c\xac\x04\x15\x54\x6f\x1d\xf5\x40\xd0\x63\x52\x0f\x84\x72\x44\xde\xa9\x3a\xd9\x31\x67\xdd\x52\x35\x06\x02\x6f\x9c\x31\x10\xc4\xf7\x12\xaf\x54\x16\xbd\x42\x20\x5b\x0e\x7a\x4d\x06\x02\x6f\xd0\xd2\x8f\x1d\xf4\xca\x0a\x71\x9a\xa4\x14\x7a\xfb\x71\xa7\xbe\xcc\x7e\xdc\xcf\x4f\x99\x32\xfc\xd9\x11\x47\x7d\xb4\x5f\x7b\x51\x7b\xeb\xb8\x33\xaf\xbb\xf9\xb9\xf3\xc4\x41\x4d\xdb\xbe\xe3\x95\xbf\x8e\x68\x97\x9c\xb3\x19\xe9\x7b\x69\xab\xce\x6d\x3d\x55\xdf\x4b\xb2\x41\x70\x2d\xe4\x54\x6c\xaf\x42\xa2\x33\xc9\xea\x54\xed\xf4\x34\x8a\x21\x68\x30\x20\x82\xac\x7a\x53\x26\x2b\xc6\xc1\xac\x15\xcf\xe3\x97\xf5\x0d\xff\x7a\xe2\x64\xc7\xdc\xab\x16\x36\xb2\x53\x5b\xf0\xfd\xdf\xdc\x70\xc2\x91\xa3\x8c\xf4\xf8\x79\xdf\xde\x4d\x7d\xef\x91\xdd\x02\x11\x07\x91\x0f\xc5\xd1\xbd\x4c\xd6\xaa\xa2\x9b\x27\x11\x0a\x15\x31\xe6\xe1\x0d\x39\x27\x72\x84\xdf\x49\xa3\xd7\xb2\x5f\xe0\x1d\x59\xdd\xc5\x21\x5c\x01\x48\x0d\x9b\xf2\x54\xc2\x21\x9c\x05\x4d\x18\xd3\x68\xf7\xef\xf9\x35\x2b\x39\xf2\x12\xe1\x86\xe8\x11\xd7\x34\x24\x92\x26\xa9\x2c\x36\x51\x1d\xc4\xe8\x93\x47\x2a\xd7\x04\x6e\x8e\x51\x5c\xf7\x53\x2f\x47\x01\xae\x6d\x65\x54\xfc\x5a\xc8\x0b\xa1\x20\x8d\x5c\xdb\x8d\xb4\x4f\x16\xdb\x6d\x6b\x3d\xbb\x70\xdf\xb7\xee\xfe\x04\x0b\xda\x2f\xb4\xf7\x76\x8e\xe0\xfe\x15\xa7\x5c\x7e\xc3\xc5\x57\x3e\x90\x75\xe0\xe5\x7d\x53\xf9\x7f\x0c\xbf\xb1\xfd\xc5\x4f\xb4\x8f\x5e\x78\x65\xfe\x51\x57\x5c\x72\xd2\x71\xdb\x52\xfa\xda\x57\x80\x8e\xd2\x68\x8b\x3e\x0f\x10\x75\x56\x09\x9f\x23\x82\x89\x47\x1a\xf6\x56\x49\x3a\x5f\xe6\xc3\x46\x30\x1a\x66\x3d\xc2\x7e\x7f\x75\x2c\x48\x26\x2c\x52\xa0\xab\x4c\x0f\x3d\x35\x63\xce\xdf\xa7\xc3\xa4\x7e\x5a\x2a\x8b\x69\xba\xda\x14\x7d\x96\x52\x69\xc1\xd2\x74\x2a\x16\x51\x99\x13\x53\x69\x38\xea\x4b\x9c\x98\x32\x8e\x33\x21\x2c\x2b\x65\xbb\x23\x00\xb3\xdc\x09\x59\xf5\x34\x43\x42\x31\x0a\x3d\x39\xfe\x66\x6b\xf8\x6a\x2f\xcc\xe0\x1a\xcf\xca\xac\x0d\xbe\x89\x7b\x8e\x8d\x77\x7b\x0e\x3b\xf6\xa4\xe2\x4d\x0f\xdf\x3e\x82\x7e\xb2\xed\x1d\x9c\x5c\x3f\xfb\x92\x45\x57\x2d\xf8\xd6\x02\x7c\xd5\x89\x27\xf2\xef\x6a\x77\x5d\xb0\xea\x98\xc3\xd2\xef\xfc\x62\x87\x76\xd7\xe0\xae\xff\xaa\x7c\x6f\xdf\xaa\xca\xf7\xf7\xc2\xac\xde\x48\x75\x64\xb7\xf0\xb0\xb8\x1d\xc5\x4c\x96\x54\x81\xaf\x96\x24\x60\x4e\xd4\xd1\xc9\x1c\x3b\xd5\x80\x04\x8d\xc2\x48\x15\x22\xac\x69\xc4\x2d\x97\xb0\x37\x40\x43\x32\x89\x9e\x2d\x93\xfa\x3a\x07\x9a\xb1\x39\xe8\x62\x97\xa7\x18\x13\x30\xad\x1d\x91\x4b\xe7\xdc\x7e\xf2\x35\xbf\xfa\xee\xfa\xdb\x6f\x7c\x61\xdb\xcb\x18\xe1\xd8\x76\x6d\xd3\xbb\xdf\x7b\x79\xc9\xbe\xae\xa9\x0f\xe2\x69\xa5\x9f\xfc\x78\x21\x16\x16\x6a\x6f\x6a\x1f\x6b\x23\xda\xac\x0f\x72\x6c\x86\x70\xcd\xc8\x6e\x5b\xc6\xee\x40\xad\x68\x81\xde\xf9\x12\x37\xa6\x74\x82\x7c\xb5\xac\xa4\x04\x47\x96\xf8\x72\xaa\xb3\x46\xe5\x1a\x35\x09\x68\xe3\xb2\x52\x42\xd1\x64\x91\xba\xd1\x02\x83\x8a\x72\xca\xc4\x5d\x1b\xc0\x80\x6b\x34\xc4\xfa\x98\x3b\x46\x31\x3c\x02\xa7\xe3\xb9\x2b\xba\xee\x5e\x77\xf4\xac\xc9\xfd\x3d\xd3\x02\xf3\x87\xfe\xb3\x8e\x6d\x93\xb1\x39\x86\x7e\xfa\xe3\xc4\x87\xca\x8c\xf9\xda\xdb\x5f\xb7\x72\x3a\xd2\x77\x5f\x3e\xb2\x5b\xf8\xc8\xd6\x82\x32\xf4\xdd\xd3\xf0\xee\x06\x8b\x63\xd0\x59\x05\x24\x40\x67\xd5\x28\x83\x44\x8d\xd3\x21\x9e\x96\x15\xd2\x02\xe3\xaa\x48\x69\xa6\xef\xee\x17\x18\x64\x97\x8b\x61\xb7\xe9\xf3\x12\x03\xe6\xcb\xc3\xbb\xd7\x93\x3a\x02\x8d\x63\xd7\xe4\xc0\x84\x7b\xae\x9e\x3f\x7d\xd2\xc0\x69\x4d\x4b\x6e\xbd\xa0\x8e\x52\x13\x28\x1c\x9d\x4b\x9e\x79\x28\x59\x55\x56\x69\x6b\xe7\xd5\x98\x1c\xcd\x79\xe6\xff\xcf\x73\xfd\xad\x44\xc8\xe6\x11\x07\x51\x08\xb5\x18\x13\x83\x54\x06\x61\xe3\x56\xf7\xd1\x05\xb7\xd0\x05\xc3\xf4\x47\x45\x66\x57\xb9\x2c\x41\x33\xbd\x3e\xc1\x59\x77\x83\x7b\x7a\x49\x0b\x2c\x3f\x2c\xec\x25\x2d\x92\xea\x15\xf6\xf2\x65\x8f\x37\xdc\x62\x2e\xcc\x17\xa6\x36\x4b\x57\x66\x5c\xcb\xc6\xd2\xea\x2e\x64\xb6\x44\x7a\x15\xbf\x60\xae\x6e\x46\xed\x22\x66\xab\xbc\x98\x5e\xc2\xe6\x02\xcd\x2b\x98\xad\x12\x71\x68\x26\x42\xc2\x56\xb8\x7f\x43\xe8\x56\x1d\x5f\xc8\x59\x50\x25\xbe\x4a\xe4\x7c\xc9\xce\x86\x91\x55\x1b\x5f\x25\x62\xbe\xc2\x07\x5c\x76\x2f\x78\x35\x06\xa2\x7b\xd8\x68\xcd\x37\x3d\xdc\x9f\xfe\xc3\x07\xcb\x94\x7b\x89\xa3\x97\xca\x01\x20\x0b\x25\x55\x14\xf6\x12\x59\x2a\x0b\x32\xf5\x07\x15\xfa\xe4\xb7\x08\xa2\xc3\x29\x2b\x35\x47\x05\x26\x26\x6c\x76\x60\xf2\x94\xcc\xb4\x37\x4a\x43\x1f\x06\x66\xf7\xc0\x34\x1c\xc8\xb4\xda\x66\xe2\xa5\xb8\xf3\x6b\x33\x87\xdf\xea\xe7\x4f\xd1\x5e\xd5\x36\xfd\x73\x18\x4f\x3e\xfb\xb4\x93\x4e\x98\x7d\xed\x4f\xf0\xa6\xf7\x31\xc2\x7d\x18\xed\x9b\xf7\xd6\x5b\x5f\x3e\x11\xaf\xbf\xd4\xe0\x53\xdd\x67\x0b\xa2\x08\x6a\x43\x83\x7a\x6e\xd2\x5f\x28\x05\x4d\xa2\xce\x34\x23\x6e\x74\x17\x54\xaf\x9d\xe1\x04\xb7\x9b\x7b\xd2\x98\x35\x28\xff\xa3\x9b\x61\xd0\xf7\x12\x7f\x2f\x71\x4b\xaa\x2f\xb4\xd7\x47\xfc\x92\x9a\x08\xed\x2d\x3b\x13\x6e\xea\xda\xc2\x33\x49\x9f\xa5\x64\xc2\x6d\x39\xfc\x9d\x45\xe2\x2a\xa2\xb2\xd3\x95\x48\x32\xa8\x75\xb7\xcf\x6f\xfc\x60\xdc\x03\x51\x04\x27\x14\x52\xd3\x90\xfe\x96\x95\x26\x46\x11\x69\xd0\xb7\x4e\x29\xe4\x23\x85\xc9\x33\xf0\x40\x7a\x60\x1c\xf6\xcf\xe5\x57\x7f\x78\xf3\xe6\x65\x0e\x9b\x37\x33\xfc\x4e\x1f\xbf\x78\x34\xeb\xe7\xdc\x39\xb3\x57\xcf\xc5\xeb\x5e\xc4\x27\xbc\x78\xa3\x77\xde\x19\x0f\xbf\x6f\xe1\xfa\x9c\x7b\xc2\x95\xbf\x03\x9b\x0f\x8e\xec\x16\x1e\xb5\xb5\xa0\x04\xea\x44\x2b\x75\xde\x06\xde\x06\x4c\x7a\x7e\x17\x63\x9e\xf5\xec\x54\x93\x52\x95\x24\x59\xa7\xa1\x3e\x2c\x08\x9d\x2a\x3a\x75\x43\xd2\x23\x2b\x25\xde\x05\x8c\x27\x51\x9b\xac\x94\xfd\xe1\x96\x76\x96\xd9\x8f\xb3\x6b\xa3\x5d\xae\x60\x4f\x20\xda\x02\x97\xdb\x4c\x6c\xb6\x59\x76\xf4\x4b\x28\x9d\xa7\x1e\x28\xa7\xf7\x88\xe1\x60\x44\x5f\x9f\x2d\x78\xe9\x7d\x97\x1f\xb5\x28\xdc\x77\x46\x15\x1f\x86\xa5\xf5\x2f\x9d\xf5\xd9\x7b\x77\xfc\xfd\xb5\xdf\xe1\xa6\xaf\x5f\xb1\x69\xe1\xc2\xaf\x5f\x75\xf2\xae\x95\x87\x17\x9b\xfb\xfa\x8f\x7f\xf2\x73\x1c\xc0\xd3\x4f\x2f\x5d\xf2\x4b\xed\xb7\x5f\xba\xfc\x9e\x9f\xfc\x9c\xff\xcb\xad\xc7\x4d\x7c\xeb\xca\x2f\x9f\xf2\x3c\xdc\x75\xfb\x10\x12\x4e\x05\x3c\x4e\x9d\xd7\x9e\x6a\x1e\xf3\x55\xc2\xe5\x4b\x4e\x6a\xf5\xae\x82\xea\xe0\xab\xc4\x9e\xaf\x88\x02\x72\x7a\xe1\xb4\x13\xf9\x2a\xb1\xe5\x31\xe0\x2f\x8f\xe2\xa9\xe5\x7a\x89\xab\x97\x70\x92\xea\x4e\xec\x25\x2e\x49\xb5\x27\xf6\x12\x4e\x2a\xf3\x9c\x3d\x90\x2d\xdb\xe8\x93\xdf\xc2\xf1\x36\xbb\xcb\x6d\x6d\x31\xca\x50\xc3\x1e\x80\xff\x61\x5b\x3f\xe7\x58\xa4\x25\xfb\xf1\xfb\xb3\x86\x3f\xeb\xe7\xfb\xb4\xd7\x30\xc2\xab\x35\x7c\x84\xb6\x6f\x1e\x3b\x8b\x66\x8d\xec\x16\x1d\xe2\x76\x14\x45\xad\xe8\x6c\x9d\xd5\x8a\x86\x17\x7e\x8e\x95\xa9\x2a\x2d\x7c\xd8\xef\xcd\xaa\x2d\x2e\xf3\x1e\x8c\xf9\xcd\x76\x58\x85\x5d\x89\xe0\x79\x32\x1c\x73\x9b\x5c\x11\x9c\xfe\x70\x0b\x2b\x27\x24\x58\xf5\xd2\xc9\xeb\xfe\x18\xf1\xcb\xc4\x0b\x66\xd7\x96\x2e\xe8\x25\xb7\xba\xcb\x9c\x39\x65\x03\x99\x56\xdb\x2c\x7c\x3b\xbe\xf6\x5c\xe1\x86\x1b\xcf\xaf\x9c\x50\xfe\x00\xbb\x71\xeb\x6b\xda\x03\xbf\xfb\xf5\x9f\x71\x61\xe1\xf4\xeb\xde\x3c\xfc\xae\xe7\x5e\xc7\x67\x7e\xfa\x8f\x68\xf7\xad\x0f\x4f\x4c\x61\x6e\xa1\xf6\x1b\xed\x43\x6d\x44\x9b\xf3\xe7\x17\x7f\x71\xd8\xec\x4a\xe9\x52\x7a\x4f\x76\x8f\xec\x16\x23\xe2\x6b\xa8\x13\x9d\x83\x4a\xed\x7a\x20\x5a\x72\xd3\x95\xc9\xae\x6a\x25\x1c\x6b\x77\x7b\xb3\x6a\xb8\x46\x7c\x9c\x90\xaa\x65\x7b\x82\x3a\x6a\x86\xc9\x05\x12\xb2\xa2\x0a\x3c\xc4\x84\xed\xac\x36\x12\x93\x55\x94\x06\x46\x0d\x95\x13\x8a\x45\x22\xcb\xaa\xdd\x5f\x2c\x12\x37\x73\x54\x02\x93\xa7\x0c\xf4\x43\x5f\x2b\x63\x78\xee\xc8\xa4\x42\xf4\x84\xb1\xb3\x0e\xd7\x42\x1e\xe6\x0f\x53\x6d\xdd\x9f\xfe\x79\xfd\x8f\xbe\x8f\xc5\xff\xbc\xef\x9f\x67\xfd\xe0\xce\xd7\xb4\x3d\x95\xd2\x25\x85\x75\x9f\xfe\xe5\x9e\xeb\x7f\xf5\x5f\x67\xfe\xe9\xae\x11\xa4\xbd\x87\x57\x95\xb7\x07\x1c\xe1\x3b\x2e\x5e\xfb\xe4\x59\xc7\x1e\xbf\xe3\xd2\xc1\x93\x4e\xd8\xf3\xcd\x4b\x56\x9c\xb4\xe2\xf3\xde\xae\xed\x08\x8f\x14\xb4\xa0\xf0\x23\xe0\x26\xb8\x04\x99\xb3\xa7\x44\xce\xa9\x9c\x13\x12\x05\x30\x75\x1a\xcc\xc1\x3c\x39\xeb\x3d\x7c\x85\xf5\x1e\xf6\xfa\x88\x38\x24\xaa\x4e\x7a\xd2\xf8\x86\xc4\xb1\x93\xa6\xa2\xaf\xb7\x17\x6f\x11\x6d\x4e\x97\xd7\x67\xb9\x1d\x39\x99\x05\x18\x5e\x86\x8b\x69\xd7\x31\x3e\xf5\x69\x53\x40\x39\xd8\xde\x37\x65\xd2\x2c\x2f\x3e\x8e\xef\x9d\xa2\x09\xc7\xe1\xb7\xa7\x6a\x9d\xb7\x65\x1f\x7c\xf8\xe4\x39\xef\x07\xa6\xcf\xb0\x15\x34\xed\x9a\xe1\xe1\x69\x2f\x3d\x98\xa4\xfb\xe5\x5d\x2d\x28\x5c\x25\xbe\x86\x92\xd4\x7b\xf6\x70\x8c\x8d\xda\xa0\xb6\x89\xe6\x88\x58\x50\x43\x76\x18\xfa\x37\xc1\x39\xac\xb9\x0e\xe7\x90\x1a\x8b\xef\x25\xc1\x21\x91\x08\x52\x59\x14\x9c\x34\xfe\x67\x50\x9f\xee\xb2\x83\xfe\x28\x92\x98\x54\x0e\xc5\x82\x40\x55\x11\x0c\x64\x4b\x0e\xc1\x69\xc9\x07\x54\x04\x87\x33\x18\x63\xd0\xb6\x8f\xd3\x7b\x23\x18\x8a\xc6\xac\x29\x01\x9d\x48\x25\x59\x24\x51\xba\x62\x55\x0e\x31\xb0\x0b\x8f\x0c\xaa\x86\x94\x49\x20\x33\x93\xab\x65\x4d\xfc\xb8\x60\xcf\xf0\x5c\xba\xb5\xb3\x65\xfa\x94\x1f\xb4\x3d\xf5\x48\xf2\xe7\x4a\xf7\x0b\x64\xdd\x59\x8b\x66\x1f\x5e\x9c\xe3\xf1\xbc\xd3\xf7\xff\x7b\xd1\xc8\x9f\xf0\xdf\xb8\x6d\xd1\x92\x67\x7f\x06\x29\x94\x19\xef\xef\x3f\x5d\xdb\x10\xab\xf9\xa6\x4b\xed\x0e\xd4\x85\x4e\x40\xa5\x0e\xd8\x91\x86\x6f\x1a\x72\x57\x2b\xa9\x74\x07\xf5\x8d\x52\xd4\x4d\xed\xb0\xba\xa9\x3a\xeb\x87\xc1\xdd\x9f\x62\xbb\x8f\xa4\x65\x12\x33\x1d\x55\x93\xdc\xc6\xea\xa2\x36\xe6\xb9\x61\xec\x36\xcb\x97\x31\x4f\x75\x72\xcf\x61\xca\x82\x53\x37\x2f\x6b\x4c\x70\xc4\xc8\x6d\x6a\x3e\x6b\x6e\xf2\x18\x92\x1b\x76\xde\x3c\xa6\x05\xc5\x35\xba\xef\x73\x06\x62\x3e\x9f\xa7\x40\x02\x39\x35\xea\x31\xc6\x5d\x89\x90\x37\x00\xd5\x45\x16\x30\xc5\x71\xb6\x22\xb1\x6f\xd2\x38\xab\x8a\xd4\x99\xe1\x03\x50\xef\x8d\xcb\x54\x3f\x92\x52\x72\x30\xb0\x48\xe8\xac\x2e\x23\xa7\x94\x84\x4b\x20\x32\x79\xca\x00\x9f\x0e\x34\xe3\x08\x14\xaa\xcc\x92\x3f\xdc\x0c\x9d\x3e\xfc\xd8\x57\x6e\xfc\x10\x77\xaf\xf4\x04\xf1\x51\x47\xe2\x65\xf8\xf0\xe1\xa3\xf2\x3f\xb9\xef\x1b\xd7\xbd\x3b\xb9\xa7\x2f\xd4\x3f\xf7\xb3\x93\x7e\xb5\x5d\x18\x1c\xbe\x6b\xde\xf3\xd9\x27\x2e\xe5\x2e\xf8\xfc\xf0\xc1\x47\x7e\xbe\xf5\x9a\x55\x47\x9d\x7d\xe2\xd2\xc5\x73\x36\x03\x16\xc9\xc8\x6e\x7b\xbf\x2d\x88\xba\x51\x55\x3f\xf3\xbb\x0b\xec\x76\x53\x5c\x55\x20\xee\x21\x91\x02\x2b\x61\xe8\x60\x78\x13\x40\x4b\xdd\xde\x2a\xe9\xae\x63\x07\x68\x66\xc0\x34\xc0\x0f\x0b\x8d\xb7\x12\x54\xeb\xd4\x88\xb7\x96\x1a\x33\xb1\x4f\x1f\xd9\xb3\x87\xed\x03\xa0\xaa\xd0\x69\x2b\xba\xa5\x32\xdf\xcd\x05\xb2\xe5\x2e\xfa\x2c\x75\x75\x8f\x02\x42\x2d\xf3\xa1\x68\x17\x4b\x09\x1a\x9f\x4c\xc8\x62\x55\xb4\xc1\x10\x3e\x69\x87\x90\xcb\x51\x54\xc3\x6e\x99\xe1\xfd\x20\x35\xac\xc8\x4a\xc5\xe6\x16\x9b\xdb\xd9\xdc\x1f\x86\x98\x91\xe5\x79\xfd\xd8\x52\x11\x36\x5a\x42\x4d\x90\x13\x3c\x0f\xf7\xcc\x4a\xf7\x38\xbe\xfd\xec\x55\x9b\xbc\x3d\xd2\x75\x4b\xcf\xcc\xac\xc5\xd9\x75\x53\xf7\xbe\xfb\xfa\xff\x04\xdb\xa5\x73\x4e\xbe\xad\xeb\x2c\x5b\x50\x7b\xe1\xda\xef\x6f\x7e\xe4\xe6\xbe\xa3\xfe\x38\xa7\xf7\xfa\x75\x0f\x70\xcb\x86\xaf\xd1\xfe\xf7\xaf\x8f\x3d\x72\xd8\x57\xc9\x9c\xc2\xea\xff\x79\x42\x8b\xc0\xbe\x58\x39\xb2\x9b\xbb\x05\x7a\xf6\xbf\xc7\x38\xd1\xa9\xd9\x1b\x99\x06\x4c\x14\x23\xbd\x40\x3c\xf9\xb2\xdd\x92\x61\x00\x97\x39\xa0\x8b\xf0\x37\xff\x78\xdf\x12\x6b\xb3\x9c\x29\x52\x39\xb1\xb7\x17\xc3\x93\x61\x01\xf3\x6c\xa3\x0b\x6c\x02\xda\xa9\xc3\x9c\xf3\x46\x5f\xfe\x80\xb5\xec\x0b\x81\xd1\xca\xc8\x7b\xb8\xef\x7d\xcf\xb2\x96\xe9\x33\x2f\xbc\xfb\xd6\x1b\x3f\x9a\x7c\xb6\x90\xfd\xfc\x85\x69\x91\xb9\xde\xf0\xbb\xfd\x6b\x59\x2c\x0c\xf8\xe5\x70\x5e\x7f\x5f\xcf\xe8\x50\xaf\xa0\x22\x88\xd4\x17\x50\x6d\xde\x42\x81\x35\x26\x4b\xd4\xf5\xb7\x9c\xdb\xb7\xef\xb9\xc7\x84\x27\xb4\x0f\xa9\xb2\xb0\x17\x50\x0a\xeb\x5d\x01\xea\x08\x7b\x65\x4f\x20\x5b\x96\xe8\x93\x47\x65\xce\xee\x61\x09\xe0\xc7\xa9\x93\xe0\xf1\xb2\x24\xb0\xc5\x51\x98\x89\x03\x99\x81\x82\x8e\xd7\x4d\xcf\xad\x88\x7d\x5a\xdb\xd3\xf3\xca\x53\xc9\x3c\x86\xd4\x3d\xef\x89\x81\xc1\x79\x1b\xdb\xc9\x62\xbc\x5c\xc3\xcb\x17\x13\xb2\x58\x7b\x58\xd3\x1e\x5e\x4c\xd8\x39\xd5\x8f\x90\xb8\x4e\xdc\x8e\xc2\x06\x2b\xac\xaa\x84\x0d\xb4\x21\xae\x00\x8b\xa3\xb1\x8c\x01\x62\x1c\xf6\xc3\x5e\x3e\x28\x88\x71\x58\x2a\xf3\x61\x6a\xc6\x21\xfa\x2c\x85\xc2\x63\xf0\x7c\x01\x8b\x89\x37\xb0\x98\x38\xc6\x96\x89\x18\xb5\x97\x27\x58\x2c\x12\xcc\xa2\x71\x6a\xa8\x33\xf1\x0c\xce\x88\x67\x19\xa8\x2d\xc3\x2f\xde\x34\x74\xce\x37\xbf\x35\xf7\xa8\x23\x73\x7d\xf3\xe7\x6b\x2f\xe9\x30\xc6\xe2\xe0\xf0\x8c\x37\xff\xba\xee\x6b\x7d\xc9\x4f\x02\xcb\xb5\x6b\x74\x08\x63\x13\xb3\xd7\x96\x41\x31\xb4\x41\x5f\x6b\x28\x56\x28\x94\x14\xba\xb1\x9d\x40\xd1\x6e\xe0\x11\xc6\x2c\x20\x84\x3a\xb3\x92\xaf\x46\xad\xe4\x19\x2a\x7b\x63\x1e\xb8\x90\x3c\xc0\x9d\xe4\xb1\x2c\xce\x5b\x44\x65\xec\xf1\xea\x20\x44\xc6\x27\x76\x13\x29\x80\x5a\x1c\x29\x42\xaa\xc1\x5e\x24\x02\x2b\x38\x14\xb0\xf5\x20\xb7\x20\x16\xf3\xed\x98\x6b\xab\xdc\xfd\x95\x19\xf9\xc9\x3d\x47\x7a\xe6\x8d\xc1\x2b\x16\x5e\x20\xa4\xa5\x1a\xfc\xd2\x34\xed\xc1\x7a\xb0\x62\xa6\x5b\x1f\x42\xdc\x23\x80\x33\x79\x8d\x19\xc1\xd1\xad\xe4\x70\x17\x0a\x2a\xb6\x57\x55\x4e\xcc\xe7\x8d\x4c\x97\x07\xea\x44\x50\x9e\x94\x54\x1e\x43\x9e\xcb\xf4\x66\xef\xda\x43\xc0\xeb\x70\x49\x65\xce\xa5\x03\x4c\x5a\x28\x5c\xe9\xf7\x6e\xfa\x3d\x5f\xe6\x44\x87\xdb\x08\xdb\x9c\x2e\x4b\x65\xc5\x5e\x34\x5a\xe7\xf5\xb6\x79\x5f\xdf\xc6\x5b\x71\xcf\xad\x9b\xfa\x36\x5d\xa5\xbd\x79\x15\x77\xe9\xfb\xdc\x13\xc3\x73\xdf\x1f\x5e\xcf\x51\xbf\x6f\xe4\xc1\x91\xdd\xc2\x80\xad\x05\xb5\xe3\xa0\xbe\xcf\xe0\x40\x0e\xf3\x90\x9a\x93\x72\x65\x8f\xe4\xf1\x41\x79\x09\x8a\xc9\xc2\x4e\x55\xc6\x59\x1d\xee\x9d\x74\x34\x61\x95\x17\x7a\xb7\x21\x55\xe0\x7b\xb7\x61\x55\x92\xe9\x67\x59\xea\xdd\x46\x57\x33\x74\xd6\x67\xdb\xcd\xbd\xd8\x3c\xa4\x2a\xe9\xbd\x24\x30\x44\xb7\x22\xe6\x9a\x03\x59\x95\x6b\x76\x10\x5e\x2a\x73\xbc\x1c\xc8\x3e\xa5\xbc\xf2\xfc\x0e\xb0\x68\x70\x4f\xa4\x40\xb6\xec\xa7\x4f\x55\x09\xc0\x1f\x52\xe0\x0f\x0d\xdd\xf5\xe9\x4c\xf8\x43\x9c\x54\x6e\xa1\x7f\x47\x49\x14\x24\x8b\x4d\xf8\x8b\x25\xcc\x35\x5b\xbe\x68\x29\xa2\xc7\x31\x27\xfa\x95\x40\xb3\xc9\x29\x84\xc7\x7c\xc3\x8c\xc6\x1e\x97\x95\x92\x33\x0a\x9d\x3c\x1e\x49\x87\xf5\xce\xe0\x4e\x7b\xe7\x00\xdd\x0f\x9d\x40\xff\x36\x10\xb1\x07\x9a\xb1\xd1\xa8\x92\xc3\x1d\x9d\x3e\x6c\xe7\x4f\xe6\xce\xb4\x3d\x93\x1b\x6a\x99\x39\xb1\xd8\x76\xe2\xd9\x97\xdf\xdd\x7d\x77\xcf\xfd\x2b\xfd\x85\xbe\x54\xe6\x98\x4b\x56\xad\x0e\x26\xdd\xf6\x48\x3e\xf5\x4f\xa1\xbd\xbf\xb8\xa9\xd8\xee\xfd\x24\x72\xf6\x99\x7d\x0f\xf4\x0d\xdb\x56\x9d\xe8\xfa\x30\xf5\xfd\xeb\xb7\x1d\xf3\xf0\xa4\xb5\x87\x69\xfd\x60\x4b\xab\x47\x76\xdb\x35\x71\x10\xb5\xa3\x8f\x51\x29\x46\x6d\x29\x5a\x28\x25\xa9\x5e\x5a\xa1\x83\x07\x0e\x41\x8f\x17\x98\xb2\x40\x23\x7a\x96\xd8\x3e\x2a\x4b\x6c\x97\xaa\x44\x84\x2c\xb1\x07\x67\x8d\xd9\x7d\xe3\x8a\xec\x34\xe1\xcb\x7e\x39\x2a\x61\x2c\x0e\x3d\x35\xe3\x7b\x7b\x06\x98\xda\x00\xee\x8e\x41\xdf\xd1\x40\x6b\x10\x4c\x53\xe7\x7b\x82\x5b\x94\x47\x15\x4e\x74\xfb\x42\xbd\x3a\x12\x98\x2f\x64\x6c\x42\xbd\x53\x28\xc3\x08\xca\x52\x69\x68\x36\x53\x95\x66\x68\x9d\x21\x71\x7a\x30\xc5\x64\x65\x10\x39\x95\xa6\x38\x74\x9f\xd5\xb5\x07\xc5\xb1\xa5\x4f\x08\x67\xfa\x21\xce\xee\x84\x6e\xa1\xd5\xbe\xb7\x71\xdf\xeb\xde\xf5\xbf\x9a\xff\x34\xee\x7b\xc3\x73\xe3\xca\x0d\x13\x2b\x38\xa7\xbd\xf6\x47\x69\xf6\x53\x67\xef\x58\xe8\xb9\xf3\x0f\x77\x6e\xc1\xd3\x0f\x9f\xc6\x6b\xfb\x73\x53\x27\x6d\xc0\x4b\xf8\x8b\xf7\xe7\xa6\xf4\xde\xf4\xd3\x6d\xfc\xa2\x7d\xf3\x36\x2e\x5b\xf6\xc4\x13\x8f\x23\x16\x0f\x00\xfe\x5b\x13\xba\x9e\xdd\x8f\x2c\x28\xb0\x7b\x18\x39\x02\xe7\xac\xea\xe4\x35\xaa\xd7\x02\x94\x59\x1f\x15\xa8\xc1\xc8\x5e\x12\xb2\x22\x25\xfa\x7b\x7d\x44\x1a\x52\x1d\xd1\xbd\x22\xb1\x53\xf1\x88\x0e\x29\xa8\x8b\xe7\x71\xd1\x66\x77\xf8\x8d\x1f\xcd\x30\x41\x67\x3a\xf0\xd7\x87\x09\xf5\x78\x89\x75\xd1\x42\x23\xac\xc4\x47\xbb\x36\xde\xba\x74\x01\x0b\x1b\xea\x60\x12\xf7\x6f\xff\xc5\xe6\xa4\x15\x07\x2e\x8c\xce\x1f\x83\x03\xe7\xcd\x99\xd7\xce\x41\x70\x11\xa3\x38\x6b\x81\x3b\x2c\x71\x34\xda\x6b\x80\x7d\x59\xe1\x05\xa7\x74\x40\x98\xc3\x1a\xa2\xdb\x47\xda\x9b\x7b\xea\x91\xdc\x3e\xbf\x43\x58\x5d\x83\x70\x33\x70\xc3\xc4\xed\x80\xff\xd2\x8c\x4e\x1a\x8d\x14\x95\xe0\xab\x95\x48\x08\x72\xa0\x11\x7a\x4c\xb5\x58\x41\xa3\xa2\x7a\x16\x30\x85\xb3\x6a\xd4\x27\x2b\x15\xc1\x1d\x8c\x24\xac\x54\xa6\x6a\x22\x62\x30\x46\x37\x40\x8b\x1a\x48\xdb\x02\xe9\x01\x08\xbe\xc7\xc2\x43\xf5\x5f\xb3\xfa\x8a\x5f\x4f\x1e\x5e\x23\x0c\x70\xab\xb9\x2b\x2f\xbb\xec\x97\x8d\x41\xa1\xb6\x55\x12\xb8\xb9\x70\xdd\xbd\x8f\xeb\xb8\x48\x36\xbd\x56\x75\x8a\x05\x17\x09\x56\x92\xe2\xab\xc4\x91\x33\xb2\xd1\x61\x09\x94\x91\xc4\x59\xd5\x2f\x41\x62\x5a\x4d\x86\x69\x88\x1d\x80\xe4\x00\x80\xef\x23\x35\x15\x93\x95\x92\xd7\x8f\xa8\x22\x20\x51\x65\x14\xa9\xd9\x6a\x22\x53\x06\xd2\x11\x1f\xb6\x87\x43\x8d\x30\xb0\x60\x49\x38\x7f\xed\x45\x29\x9c\x73\xe5\x9e\xbe\x23\xd0\x08\xf9\x4a\x5f\xd4\x1b\xf3\x7e\x19\xbd\x6f\xc7\x97\x96\x2c\x69\x04\x77\x85\xf4\x1c\x9f\xf8\xb6\x68\x83\x5e\xe7\x25\x08\x72\x7b\x6a\xcc\xc0\xb6\xb2\x24\x45\x22\x5e\x98\x91\xa5\x0b\x93\xbc\x2c\x29\x92\x8c\xd0\x85\x51\x77\x44\x92\x55\x9b\x0f\x72\x08\x74\x61\x3e\x24\x99\x0b\x33\xb3\xee\x33\xb0\xb1\xa6\xb1\x45\x18\x80\xb2\x7a\x67\xd5\xac\x25\x61\xdc\xe9\x9a\xf4\xe4\x66\xdf\x18\xac\x32\x00\xb1\xba\x39\x7e\xed\xe5\xd1\xca\x4b\x87\x15\x16\xd6\xa1\x94\xb1\xb8\xeb\x9c\x91\xdd\x8e\x82\xb8\x1d\x66\x7d\xaf\x66\x95\x64\x56\xf6\xe8\xd0\x15\x45\x5c\x05\xb5\x87\xaf\xc2\x00\x45\x1f\x2c\x29\x23\x55\x49\x46\x82\x1e\xc9\x84\x54\x25\x09\x06\xc8\xe6\xf5\x56\xcb\x92\x37\xe8\xc8\xaa\xb2\x17\x92\x0d\x74\xb9\x79\x9c\x55\x27\x64\xe8\x72\x53\x00\x4d\xa3\xda\x9b\x8a\x45\x55\x92\x65\x45\x75\x45\xe8\xc2\x7b\x3a\x64\xa5\xec\x0d\xa2\x84\x9e\x7b\x34\x4d\x33\x1f\x8e\xd4\xd3\xd9\x81\x23\xd3\x58\xb3\xe7\x6c\xc5\xa7\xbc\x77\xf3\xce\x23\x2f\xfa\xc5\x05\x3f\xf9\xb5\xf2\x86\xb6\x6b\x87\x6b\xf9\xe2\x23\xbf\x93\x8d\x3e\xa7\x3d\xf2\x3e\x68\x78\xea\x55\xab\x57\xbf\x72\xa1\xa1\x61\x17\x7e\x76\xf7\xe9\x27\x9e\x75\xfc\x6b\x0f\x17\x4e\xde\x5f\xe0\xdf\x9c\xd8\xb1\x68\x69\x71\xc2\x49\x5f\xd3\xfe\xac\xcd\xfa\x90\x29\x5b\xc5\xd3\x0c\x65\x73\x68\xb9\x16\xb4\x3d\x25\xac\x42\x2d\x28\x8b\xae\x42\x70\x43\xa9\xad\xba\xae\x89\xb3\xa0\x76\xb9\xaa\x24\x94\x27\x52\xce\x68\x28\xd4\xe1\x25\x3b\x60\x20\xfc\xc0\x5c\x9b\x3d\x38\xab\x76\xa4\xa8\x84\x92\x45\xc8\x21\xd9\x22\xc5\xa2\xea\x97\xe8\x8d\x02\x40\x9a\x5d\xad\xb2\x52\xf1\x04\x22\x28\x56\x9f\x9e\x35\xca\x49\xd6\xc3\x66\x7c\x2b\x79\x77\xd5\x71\x9b\xce\x7d\xe0\xd9\xe0\xdf\xb4\x37\xf7\xf8\x6e\x3c\x75\xc9\x38\xa6\x72\xd7\x71\xf3\x07\xef\x9a\xb5\xec\xf3\x0d\xc2\xea\x59\xe9\x0d\x73\xfb\x46\x5b\x0c\xd4\x28\xc4\xed\xe2\x20\x9c\x4e\xb7\xa0\x92\x97\xd5\x28\x58\x7d\xc2\xcf\x57\x55\x5f\x73\x3e\x5f\x71\x47\xbc\xbc\x37\xab\xba\xf5\x13\xca\x0b\x44\x25\x65\xc5\xe3\x75\x64\x2b\x88\x15\x2d\x50\xae\xa2\xb0\x4f\x1e\xbd\x7c\xe1\xaf\x61\xf4\x6e\xde\xb3\x1f\xae\x1e\x13\x89\xb6\x79\xa8\xec\xf6\x34\x07\xb2\xe5\x08\x7d\xf2\x65\xb7\x2f\xd2\x6c\x5e\x2b\xfe\x08\x94\x30\x82\xf5\x9d\x05\x28\x9d\xe1\x6b\x35\x0c\xd1\xd2\x4c\xf0\xc6\x9e\xcf\xb4\x9f\x6a\x3b\x37\x9e\xa7\xbd\x61\x56\x30\xae\xfe\xce\x86\x87\x5e\xb8\x51\xe8\x1b\x7c\xe3\xad\xb7\xfe\xae\xfd\x75\xd8\x68\x20\xd8\xb7\xfe\x92\x0a\xf4\xfe\x3c\xa3\x05\x85\xb3\x6c\x19\x94\x44\x59\xf4\x1f\x7a\xc5\x32\xed\x04\x0f\x24\x59\x30\x3d\x7d\xa6\xfe\xa4\x17\xb2\xd5\xf4\x10\x0b\xf8\x6b\x6d\x15\x66\x8e\x8a\x39\xfd\x49\xea\x71\x94\x13\x49\x77\x20\x5b\x9e\x40\x9f\xa5\x44\xd2\x9a\xc3\x9f\x40\x9d\x7e\x77\x62\x82\xee\xf4\xeb\x9f\x20\xb2\x69\x4f\xd2\xb8\xdb\x2b\x45\x9a\xe1\x70\x4f\xeb\x5c\x4b\x4e\xb9\x6c\x97\x02\xc0\x9c\xaa\x47\x01\x7c\x2d\x0a\xb0\x9b\x91\x39\x2b\xf7\xdb\xec\x7c\x7d\xc1\x7f\x16\x3e\x57\x8f\x0b\xbe\xda\x34\xb1\xd9\xb1\xee\x47\xb7\x3f\x74\xed\x1f\xd6\x97\x4e\x71\x78\x5a\xe6\x3e\x7d\xd4\xdc\xa3\xd7\xcc\x99\x7f\xe4\xd1\xdf\x3a\x46\x0b\xda\x7e\x06\x11\xc2\xca\x47\x97\x6c\x7e\xeb\x85\xad\xda\xad\xcf\xfc\xf8\xbe\x1f\x68\x8f\xf2\x6b\x16\x9d\x7a\x5d\xf5\x3b\xcb\x96\x5d\xf9\x31\xf4\x5a\x8c\x14\x84\x2b\x60\xc6\x36\x82\x9e\xae\x71\xb0\x19\x34\x05\x7c\x18\xf8\x7a\x23\x05\xa3\x87\x0b\xa0\x85\xfc\x40\xec\x12\xd4\xaf\xb1\x58\x43\xd4\x25\x3f\x75\xdf\x18\xb1\x4b\x8d\xe8\x04\x18\x5e\xca\x12\x7d\x8a\xe5\x48\x03\xba\x17\x89\x86\x81\x92\x8e\xe3\xec\x93\x22\x96\x3a\x48\xd0\x4f\x4f\x23\x4f\xb1\x48\xec\x34\x3a\x64\xb8\x66\x25\xbb\xcb\x5b\x34\x5a\x25\x0a\x63\xb0\xcd\x18\xe6\x52\x3e\xdb\xbf\xfb\x63\x03\x75\x69\xc1\x15\x0b\xaf\xbc\xe5\xa5\x79\xe2\xe0\xf6\x57\xb7\x6e\xfc\x60\xca\xf0\x2d\x5c\x9f\xb6\x91\x3b\x75\xd5\x25\x0f\x22\x3d\xe7\x2c\xcc\x15\x5f\x43\x13\xd0\x59\xa8\xd4\x05\x27\x08\x5f\x65\x70\x02\x1e\x2a\x01\x36\xb9\xda\xe2\x05\xa6\x6e\x27\x75\x3d\xbc\x55\x80\xf7\x6c\xa1\xf1\x9d\x5f\x82\xf8\x6e\x8b\xe0\x09\x34\x01\xd0\x27\x09\x2b\x6a\x7b\x07\x3d\x1f\x5a\xbb\x64\x85\x74\x50\x97\xa4\x8c\xfc\x61\x80\x9d\x08\x28\x44\x82\xad\x30\x03\x0f\xcc\xe0\xf5\xa3\xb3\x53\x3f\x2c\x7c\xd8\xee\xe3\xf5\xd2\xad\x4c\xbd\xcc\xee\xaf\x6c\xbe\xff\xe8\xef\x7c\x65\xf2\x09\xf3\xa7\xad\xbb\x64\xe9\x77\xb7\x9d\xfb\xc4\x1f\x4f\x24\xcf\x1f\x79\xe1\x71\x3d\x2b\x96\x1d\x7f\xcf\x6d\xcf\x7e\xf0\xfa\xdf\xf0\xca\xd5\x83\xdf\x9f\xd6\x94\x9b\x3a\xb7\x50\x3c\xbc\x35\xff\x71\xb1\xf7\x97\x0f\x5d\xba\xf9\x7b\xc7\x34\xf5\x0e\xcc\x9e\x34\x7b\x41\xeb\x61\x9a\x76\xf2\xab\x2c\x3e\x4c\x8e\xec\xe6\x1f\x15\x56\xa1\x36\xba\x4e\x40\xce\x48\x18\xc8\x11\x4e\x9b\x89\xaf\xd5\xe4\xad\x92\x26\x86\xcd\xad\x30\x08\x6a\xb5\xc9\x2c\x15\xd8\xe5\x2d\xbc\xd3\x1f\x4e\x00\xb6\xb4\xa2\xe8\x10\xb4\x89\x56\x56\xa6\x76\xca\x65\xe4\x51\x9a\x75\xd8\x08\xaf\x9e\x59\x9f\xc1\xd1\xc3\xce\x8f\x3b\xa7\x98\x8b\xe4\xd8\x34\x32\x94\xad\x92\x9b\x9f\x3f\xf7\xeb\x13\xd7\x9e\x7c\xf9\xec\xf9\x5b\x5f\x7c\xe2\xb5\xd9\xd7\x6f\x3c\xff\x6b\xd9\xdb\xee\x56\x57\x3e\x78\xc6\x0b\x3b\x71\xcf\xf7\x4b\x33\x33\xb9\x49\x6d\xc7\x14\x12\xbb\x96\xdf\xb5\xfe\xb4\x1f\x9c\xd6\xdf\x91\xeb\x69\x3b\x75\xe9\x07\xbd\xe9\x47\x10\x1e\x79\x0b\x21\xe1\x5e\xa8\xdf\xe4\x0d\xdc\x30\xa3\x03\x11\x62\x45\x56\xa2\x41\xaa\x53\xf7\x16\xed\x32\xe1\x60\x0b\xf2\xd0\xf9\xe7\xc4\x03\x69\x3b\x04\xdf\xd9\x3e\xae\x45\x7b\xb6\x8f\xbf\x76\xca\xf0\x0e\x3c\x43\xf3\x70\x4b\xfa\xf7\xe0\x7d\xf8\xdd\xaa\xa6\xb5\x68\xdd\x23\x74\xdf\x64\xb5\x20\x77\x95\xad\x05\xc5\x51\x27\x7a\x12\x11\x25\xa7\x7a\x9d\x55\x12\xcb\x91\x68\xa1\xd2\xc2\x26\xa7\x52\x79\xd2\x9e\xab\xf0\xfa\xf0\x54\x17\xcc\xe4\xa3\xbc\xea\xf6\xc2\xf4\x87\x5b\xc8\x12\x37\xab\x8f\xd9\xbc\x50\xac\xb0\x52\x5d\x91\x54\xaf\x8f\x44\x86\x54\x47\x70\x2f\x71\x42\x68\x53\x8e\x46\x52\x81\x2c\x8f\x4a\x0e\x67\x04\xa8\x29\x1c\xce\x08\x03\x96\x63\x13\xfb\x09\x59\x21\xed\x45\xd2\x2a\xab\xbc\x52\x2c\x12\x1b\x75\xc0\xa4\xba\xf9\xfd\x18\x9b\xdf\x57\xdb\x5b\x64\x45\x45\x36\xe3\x14\x86\x9b\x09\x8f\x1a\xe2\x67\x63\x55\xd3\xb0\x7e\xa1\x67\x1f\xb9\xee\xba\x8d\x3e\xed\x4f\xc2\xf9\x0b\xce\xfc\xd6\x9d\xb7\x3c\xec\xd9\xef\xbb\x64\xfd\x83\x85\xbe\x4e\xa9\xa3\xa5\x75\xb2\x18\xf9\xce\xf5\xeb\x2e\x2d\x1e\xb6\x6f\x57\x20\xbc\x34\xf3\xde\xe4\x1b\xaf\x9c\x3a\x45\xd8\xb4\x7a\x55\x7b\xf7\x12\x5f\xaa\xad\x07\xec\x6d\x85\x8e\x5d\xd1\x8a\x6e\x40\x35\xf0\x82\xd6\x31\xe0\x05\x90\x49\xb6\x31\xb7\xac\x65\x27\x49\x9b\x18\x06\x6d\xa3\x31\x0c\xd2\xbd\x22\x69\xad\xc7\x30\x48\x03\x86\x41\xab\x2e\x91\x16\x59\x29\x63\x2e\x10\x67\x00\xac\x7a\xd7\xa4\x43\x2e\x79\xfd\xe1\xe2\xb8\x30\x06\x35\xac\xe7\x99\x58\x97\x45\x3d\x8e\xc1\xa2\x75\x4b\x3b\x36\x5d\x7d\xfc\x9c\x9e\x69\x17\xc4\xe2\x9e\xdb\x37\x78\x56\xd5\x01\x19\x68\x2b\xb7\xdc\x17\x7f\x4b\xb9\xec\x4a\x03\x6a\x02\x61\xb8\x8b\x7b\x20\xef\x79\x3a\x2a\x39\x10\xb0\x9d\xb1\x9b\xd8\xc5\x57\x55\x9b\x33\x9f\x87\xe4\x27\xda\x59\xf1\xb2\xab\xd6\x6b\xd2\x9f\x9b\x69\x4f\x03\x77\xc2\x01\x0c\xd2\x76\x89\xd8\x86\x78\xd5\xe6\xd4\xaf\x56\x97\x83\xaa\xd4\x6f\x5e\xac\x80\x3c\x61\xdc\xa9\x2b\xdf\x7b\x8d\x8f\x0d\x68\x9b\x34\xed\x75\xed\x8a\xa3\x17\xd9\xde\x73\x42\xfd\x1f\xd0\x26\xbe\x3c\x37\x11\x85\x58\x6c\xc5\xc8\x6e\x7e\xad\xad\x05\xb5\xa2\x57\xd8\x04\x86\x1a\x71\xea\xe7\x81\x02\x8a\x22\xee\x9c\x6a\x73\x5a\x15\x13\xf2\x57\x49\xa0\xa6\x98\x23\xff\xde\x63\x28\xc6\x47\xf8\x21\x41\x0d\x04\xa1\x3c\x45\xd2\x52\x99\x4b\xf3\x81\xac\x48\x02\x52\xd9\x1f\xf0\x05\xb2\x65\x85\x3e\xe9\x6f\xb4\xd2\xdf\x28\x71\x69\xde\x5a\xd6\xe1\x78\x5f\x20\x6d\x32\x16\xfa\xfc\x4a\xab\xe5\x1a\x08\x51\xeb\xc5\x09\x6a\xd8\x91\x04\x8b\x53\x15\x59\x8d\xb5\x14\x8b\xaa\xdb\x0f\x8d\x7b\xc4\x26\x13\x07\xd3\x6c\x2d\xb7\xe6\xc7\x0d\xa0\x2a\x56\x24\x49\xac\xfb\xf1\xfb\xcf\x59\x38\x7b\xee\xb4\x23\xbd\xca\x68\xa8\x0a\x7e\xf5\x2d\x0b\xce\x7e\xfc\x27\xe9\x0f\x63\xd3\x0e\x5b\x36\x06\x43\x04\xa3\x47\x74\x0c\x9a\x10\xba\x08\x59\x90\x43\x42\x80\x38\xc3\x4a\x3a\x61\x20\x6f\xa4\xb7\x64\x64\x14\x3c\x7b\xa8\xd7\x47\x82\x43\xa2\x2a\x08\x7b\x7d\xac\xd3\x3f\xc8\x7a\x7d\x59\x30\xce\xd2\xd8\x8a\x3e\x81\x0b\x09\x6c\x0f\x60\x3b\xb8\x15\xaa\x65\x40\x17\x31\x36\xad\x4f\xb7\x54\x13\x5d\xe4\x43\xdb\x92\x69\x85\xf4\x79\xfd\x77\xde\xef\xc5\x51\x06\x2d\xb2\xef\xed\x44\x64\x71\xe8\x43\xaf\x72\xdd\x77\xf3\x53\xc4\x1c\xd8\xe5\x86\x91\xdd\xf6\x53\x6d\x41\x94\x44\x0f\xe9\x15\xfd\xfa\xb9\x5a\x25\x67\x80\x09\xd6\x8d\x36\x5a\x8a\x79\xcf\x31\xf7\xaf\xd7\x47\x3c\x43\xa2\xea\xa3\x4b\x89\x0e\x91\xa8\x54\xf6\x47\xa9\x9a\x23\xf4\x59\x8a\x44\x7d\x75\xf9\x30\x54\xf6\xf8\x75\xa0\xf6\x2d\x1e\xaf\x4f\xff\x6c\x19\x7f\x54\x9d\x71\x63\x76\x16\x70\x71\x89\x22\x93\xe0\xd8\x61\x2d\x3b\xc4\x5c\x36\xc1\xce\x26\xd9\xea\xe7\xd6\x3a\x17\x2c\x09\xe2\x9c\xeb\x30\xed\xa3\x57\x56\x1b\xf3\x8e\xf5\x43\x6b\x4f\x44\xd7\x5e\x11\xfd\xe5\xbb\xde\xe1\xe7\x61\x78\x0d\x61\x1a\x63\xd9\xd6\x8b\x02\x4a\xa1\x27\x19\x46\x07\x4b\x72\xf1\x18\x65\x4b\x02\x95\x48\xc1\xc0\x0a\xb5\xc8\xa3\xc6\xd6\x31\x53\xfc\xdf\xdf\x8c\x29\x4d\x98\x39\x64\xb1\x26\xa6\x78\xbd\x98\x4a\x7e\xab\x80\x50\x85\x13\x3d\x7e\x26\x12\x3c\xc8\x89\x54\x42\x51\x6b\x3f\x08\xd4\x36\x9a\xcd\xda\x06\xdf\x24\x2b\x15\xe4\x8c\xc4\x13\x8d\x06\xda\xec\x33\x38\x5d\x46\xfa\x64\xdb\x39\x49\xeb\x1c\x5b\xb4\x30\x2b\x4b\xc5\xf4\x25\xed\x6f\xbf\x7c\xec\x8f\x21\xc7\x4d\xbf\x5a\xff\x23\xdc\x33\xeb\x26\xcb\x10\xdb\x45\xde\x19\xa7\x9d\x13\xdd\xf6\x07\x69\xff\x1b\x6f\xbc\xf7\x10\xd8\xcd\x85\x23\x55\x5b\x51\x1c\x44\x29\x74\x0a\x62\x04\xae\xc1\x82\x2a\xc0\x24\x0c\x69\xce\xa9\x1e\xb7\x89\xa9\xea\x94\x20\xa5\x2c\x51\xbf\x41\x87\x2d\x71\x1a\xac\xce\x44\x92\x2b\xbc\x2d\x10\x04\x17\xa1\x49\x81\xb1\x24\xc1\x23\x2b\x65\x64\x0f\x34\xe9\x6b\x51\x06\xd2\x81\x34\x2f\xc8\xa6\x03\xdc\x19\x48\xf3\x69\xe8\x03\xa1\xe1\xe5\x85\x6f\xbf\xa2\xdd\x3a\xc0\xad\x9f\xa6\xad\xbd\xf2\xf2\x6f\x54\xce\x99\x77\xfc\x34\xee\xf4\x7e\xed\xba\xb3\x56\x3d\xa5\x3d\xb1\x4b\x1b\xd1\x7e\x87\xf7\x7c\x82\xcf\x3a\x1d\x0b\xda\xee\x3f\x68\x27\xde\x70\xcf\xba\x7d\xd7\xdc\xfe\xfa\x42\x1c\xd4\xf6\x1f\xf5\xf1\x9d\xbf\xd3\xee\x7e\x0a\x47\x10\x46\x4f\x20\x24\xce\x12\x5f\x43\x09\xf4\x15\x76\xf6\xc1\x90\x4f\x29\xa8\xc7\x4a\x30\xdd\x63\x8e\xe3\x41\xee\x32\xc2\xe6\x76\x18\x3d\x58\x02\x18\x35\x64\x25\xae\x53\x48\x04\x8b\x48\xf5\x27\x64\xa5\x24\xca\x11\xfa\x15\x90\x0b\xc0\x78\x4e\x38\x42\x6d\x36\xa0\xbb\xf2\xf6\xfe\x29\xa6\xc7\xfa\x04\xce\x9c\xe9\xe4\x38\xf9\xfc\xd8\x1b\xfd\x53\xbb\x5b\xa6\x74\x2c\x3a\xf3\xbb\x77\x17\x8f\xd7\x90\xf6\x92\x38\xb8\xff\xae\xf9\x0f\x1f\x3f\xf0\xdb\x0e\xbc\xf4\xc4\x8b\x5b\x5b\x53\x81\xbf\x65\xae\x59\x7d\xfc\x43\x57\xed\x27\x08\xa3\x07\x11\x12\xaf\x12\xb7\xa3\x20\xbd\x5b\x8c\x28\xcf\x49\x5f\x1f\xfc\x9e\x80\xde\x1f\x4d\x43\x3b\x6f\xad\x3f\xda\x9c\x35\x3a\x00\x87\x08\x52\x03\x5e\xba\x01\x1d\xac\x64\x01\x77\x65\x3f\x38\xa7\x11\x63\x64\xac\x97\xcb\xb4\x3e\x18\x3f\xb3\x67\xd5\xe5\xc9\x65\xf8\x52\x63\xb8\xe8\x92\x40\xa6\xbb\xa3\x43\x78\xea\x6f\xee\xe8\xb7\xbf\xa3\xdd\xa8\x0f\x16\xf5\xe0\xb7\x17\x7e\xb9\x0d\xea\x68\xab\xb4\xa0\xf0\x5b\x61\x15\x4a\xa3\xf9\x88\xc1\x4b\x87\x0b\x6a\xcc\x51\x05\xb8\x2a\x35\xc6\x03\x0b\x32\x8c\x8a\xb5\x9a\xa3\x62\x19\x7d\x54\x0c\xf2\x79\x5c\x0b\x40\x36\x90\x98\x5c\x41\x36\xb7\x87\x55\x8a\xeb\x46\xc5\x66\xe2\x29\x54\xce\xf5\xc3\x10\x75\x63\x62\x42\xa0\x3b\x7b\xf7\xdc\x07\x2f\x3a\xee\x84\x6c\x26\x35\xf5\xc4\xa9\xda\x74\x55\xfb\xd5\xf2\xa2\x65\x40\xcc\xf5\xa5\x35\x4b\x70\xf7\x75\xab\xe3\x7f\x73\x9f\x7c\xf6\xfe\x92\x56\x09\x20\xcc\xe6\x5c\xe0\x2e\x9f\xa9\xfb\x98\x7e\xbe\x5a\x72\xe8\x3e\x66\x85\x17\x90\xc3\x0b\x7d\x43\x3c\x5f\x25\x5e\xb8\xd8\xe9\x1d\x8e\x0c\xbc\x63\xb6\x08\x17\x1b\x35\xc9\x0c\xa4\xd9\xe8\x4b\xc1\x9e\xc6\x69\x7e\x7a\x07\xce\xff\x7c\x2a\x3e\x06\x07\xd8\xd8\x8b\xf6\xdc\xcb\x03\xda\x66\xed\x33\x6e\x49\xff\x36\x7c\x9d\x86\xcf\xc4\xe8\x55\x6d\xa5\xa6\x3d\x3a\xc2\xea\x91\x30\x07\x24\xac\x60\xef\x02\xcd\xe5\x7e\x87\x8e\xd1\x6d\x77\x54\x2b\x02\x2f\x3b\x18\x80\x90\xe0\xa9\x12\xb7\xf5\x5d\xe4\x31\xef\x12\xc8\x0c\xa4\xe9\x7f\x7e\xcc\x70\x82\x72\x99\xbf\xde\x91\xc5\x3e\xc2\x86\x5e\xb6\xdf\x99\xd5\x3e\x7a\x09\x3f\xde\x57\xc1\x99\xad\xbb\xaa\xaf\x7c\xb6\xf5\xa3\x2a\x7b\x87\xfd\x23\xbb\x85\xf5\xe2\x20\x8a\xa1\xd9\x0c\x85\x8d\x06\xd8\xac\xfb\x08\x4a\x87\x4d\xa0\xc1\x10\xeb\x0f\x56\x43\x76\x28\xc4\xb2\x22\x3f\x41\x00\x47\x82\x95\x10\xdd\x25\x3a\xb6\x5c\xa7\xdc\x8c\x8d\xb6\x6e\x7d\x2e\x88\x6e\x77\x94\x6e\x15\xe6\xef\x9a\xb7\xa9\x74\xf9\x95\x77\xf6\xe0\x35\x5a\xdf\x00\xbf\x3c\xab\x65\xff\xf3\x59\x6d\x8b\xf6\xdf\x7b\xa6\x61\xfb\x84\xe2\xe5\xdf\x3c\xed\xa4\xed\xf8\x64\x8c\x5e\xd4\x96\x07\x9e\x79\xf0\x43\x6d\x98\xfa\xe9\xd3\x47\x76\x0b\x6f\xc3\xfb\x35\xa1\x15\x7a\x3e\x40\x76\x55\x19\x8c\x94\x83\x6a\xcc\x1d\x11\xbd\x59\x95\xaf\x61\xab\xf8\x24\x06\xa3\xe2\x33\xf9\xe7\x55\x39\xc2\xbc\x47\xb7\xac\xa2\x20\x8c\x10\xab\x5c\x53\x91\x7a\x93\xd4\xdf\x10\x19\x45\x60\x60\x72\x5b\x3b\x1e\xa0\xf7\xb2\xd9\x2b\xc4\x42\xb7\x36\x3c\x1d\xb7\xe1\xb0\xf6\x40\x37\x7f\x47\xff\xf0\x3b\xb8\x90\x3b\x6f\xd7\x6b\xd7\x7c\xef\xf4\xc1\x73\x9f\xfc\xf4\x53\xed\x03\xce\x85\xd7\xed\xfc\xd8\x83\x37\xbe\x3c\x82\xb4\x07\xdf\xfe\xc6\xc5\x27\x9d\xd9\xdb\x3b\x82\x8e\xff\x2d\x77\x39\x93\xf1\x5b\x5a\x50\x58\x27\xac\x40\x4d\xe8\x28\xc3\x77\x76\x54\x49\x04\xe8\x92\x1b\xbd\x34\x11\x8c\x57\x0e\x82\xc3\x8b\xf8\x80\xee\xf0\xd2\xd7\xb4\x4f\x46\xed\x10\xe9\x8c\x6a\x69\x6a\xed\xc5\x59\x7c\x38\x6e\xd2\x9e\xca\xf2\x17\x16\x86\xab\x78\xca\xa4\x73\xde\xd9\x7d\xdd\xaa\x8d\xdb\x2f\xae\x5c\x74\xf7\xc7\x97\x67\xde\xc5\x99\x18\xde\xf4\x62\x55\xbb\xe2\xed\xfb\x6f\xf9\xfa\x65\xcb\xf6\xe7\x32\x17\xff\x8a\xbe\xdf\x63\x5a\x50\xc8\x0a\x2b\x50\x1b\x9c\x41\x00\x69\xe5\xa8\x92\xd6\x1c\x0d\x29\xf5\x48\xb2\xd2\xc4\x86\x98\x9b\x24\x55\xc4\x59\xe0\xeb\xa1\xc1\xa4\xd8\x24\x2b\x5b\x38\x8f\x37\xc2\x82\xc8\x80\x5c\x92\x9a\x19\x70\x9c\x11\x46\x7a\xe4\x12\x92\x9a\x19\x30\x00\xf0\x2e\xdb\xa5\x76\x38\x3f\xc1\x3c\x06\x74\xf3\xb0\x09\x76\x1f\xb6\x38\x43\x8b\xf1\x4b\x3f\xbe\xf4\xaa\x75\x57\x65\xf1\x4c\x6d\xd1\x64\x7e\x7a\x56\xbb\xf1\xb6\x1f\x7d\x47\xdb\xfb\xd6\xd9\xc7\x97\x06\x3f\x3c\xe9\x93\xcb\x2a\x6f\x6e\xc5\x33\xbb\xa4\x59\xb3\xa7\x74\xff\x12\xcb\xd5\x17\xb5\xb7\x63\xf7\xad\xbe\xfe\xfe\x15\x21\xd7\xc4\x8e\x45\x8b\xfe\x90\xe9\xf9\x11\xdb\x5f\xc2\x85\xb6\x16\xc6\x69\x82\xf4\x1e\x73\x12\x85\x5a\x56\xd8\x03\x84\x44\xce\x9c\x2a\xf1\x55\x83\xa5\x28\x20\x31\xcc\xe5\x80\x5d\x56\x2a\xe1\x48\x14\xd8\x59\x90\x1a\xd7\xb7\xbe\x33\x4c\x43\xe7\x00\x5c\x7d\x10\x11\xb3\x69\x33\xbd\xfe\x60\x04\xfe\x36\x3b\x3d\x0d\x42\x69\x3e\x97\xc5\xdb\x34\x92\xc5\x7f\x79\xec\x8e\x23\xaf\x5b\x79\xf3\xf7\xfe\x79\xe5\xcf\x7f\x77\xc2\xec\xeb\xb2\xda\x47\xda\x25\xdc\x51\xfd\x6f\xe1\x67\xb7\x3e\x70\xcd\x5d\x47\x7d\xf9\xb5\x0b\x4e\x7b\xe5\x67\x2b\x7e\x76\xc4\x56\x6d\x8d\x4b\xdb\x8f\x30\x42\x23\xbb\x85\x0a\xcc\x1d\x4d\x65\xf5\x3a\xe8\xd9\xf7\x81\x5f\xc7\x57\x89\xc4\x3a\xb1\xed\x8c\xcb\x20\x09\x6d\xfb\x31\xb6\x1d\xbd\xb2\x8a\x81\x88\xa0\xdf\xb2\x0d\x03\x19\x06\x78\x96\x0f\x87\x24\xea\x68\xcd\xde\xfe\xd5\x47\x9f\xbf\xfc\x07\xef\x7f\xeb\xfe\x01\x7e\x70\x40\x53\x8e\x08\xbf\x5a\xd5\x7e\xaa\x3d\xfd\xed\x6d\x33\xb1\xbd\x7b\xca\x86\x2b\xbf\x72\x02\x27\x01\xfe\xd9\x9e\xdf\x3e\xad\xfd\xaf\xf6\x61\x8f\xfe\x4e\x33\xc1\x86\xa7\x1a\xe7\x84\xa3\xaa\x1b\x8b\x9d\xc1\x9b\xc5\x01\x6c\x2f\xe4\x07\x43\xae\x1d\x11\x1e\x59\xc5\x00\x9c\x32\x1d\x37\xe3\x42\x4a\x7f\x25\x98\xe4\xd2\x47\x73\x5a\x3b\x66\x6f\x5b\x82\xa7\x5e\x79\xcd\x53\xcb\x1f\xe9\xe3\xaf\xea\xd3\xa6\xf4\x34\x3f\xf7\x96\xf6\x8e\xf6\xce\x59\xbf\x19\xf8\xa4\xbd\xef\xae\x2f\xe5\xf1\xc6\xf7\xdf\xdf\x7a\xf7\xf5\xbf\x7c\xb3\x8b\xbd\x0b\xbf\x4e\x5c\x80\xda\xd1\xc5\xa8\x94\x81\x77\xb1\x55\x4b\x21\xfa\x2e\x51\x78\x97\x52\x28\x4a\x83\xd2\x50\xd0\x99\x85\x0e\x01\x28\x6a\x7a\x20\x1d\x52\xb6\x35\x79\x1c\x59\x35\xa5\x4f\x2f\xdb\x3c\xb2\x52\x11\xfc\x4a\x80\x21\xe6\x34\xc9\x4a\x29\x14\x0d\xb2\x3e\xa6\x0c\x7b\xff\xa8\xac\xe2\x54\xb1\x48\x42\xec\x80\x83\x55\xe4\x4d\xf0\x4c\x13\x99\x8d\xc6\x6a\xcd\x1c\x6b\x6f\x3a\xe6\xa7\xc7\xfc\x7e\x42\xd7\x05\xf3\x6d\xa1\x67\x12\x2f\xad\x7b\x21\x8f\xe3\x7d\xda\x5f\xc3\xb3\x4e\x9f\x3f\xe1\xb3\x0f\xcf\xfb\x45\xdf\x9e\xee\xdc\xba\xa6\x7c\x72\xc1\xda\xe3\x03\x93\x4f\x83\xd8\xf3\x8c\xe8\xe1\x7d\x73\x8e\x3f\x65\x5a\x69\xa8\xc3\xc8\x81\x0a\xab\x90\x0f\x45\xd1\x95\xc8\x52\x54\x43\x39\xe2\x03\x16\x29\xbf\xdb\x04\xcd\xd2\x99\x5b\x14\x9d\x62\xa9\xc9\xac\xfa\x57\xac\x2c\x52\x3e\x89\x44\x87\xc4\xb2\xd7\x17\x0d\x64\xcb\x7e\xfa\xe4\x11\x89\xf6\xe2\x32\xf6\xfa\xcd\xfa\xaa\xe2\xd3\xef\x67\xec\x67\x30\xe3\x3a\x44\x3c\x36\xcb\x6d\x9c\x60\xe7\x03\x46\x3d\xc0\x3e\x0b\x2f\xfd\x40\x76\xae\x7f\x62\xc3\xe6\x27\xb4\x3b\x86\x4f\xfb\xd1\xcb\x7f\x3b\xf2\xa8\x25\xab\xbb\xb5\xa0\x6d\xde\xe6\x5f\xec\x7a\x7a\x97\x36\xf8\x7a\x4c\x9b\xc6\x6d\x4b\xe0\xc0\x0b\x27\x2f\x79\x7e\x2b\x42\x18\x3f\xa0\x05\xb9\xb5\xc0\x57\x9a\x41\x74\x3d\x38\x07\x4c\xfc\x68\x67\x85\x87\xd8\x59\xff\x85\x9e\x32\x68\x52\x1f\x96\x0b\x32\x7e\xe0\x1d\x2d\xe8\x40\x9f\xb1\x3a\xca\xdd\x5a\x90\xbf\x06\xfe\xff\xed\x68\x12\xfc\x0d\x02\x30\x0a\x8b\x05\x4c\x1c\x96\xbf\x87\xf0\x92\x2a\xe0\x6c\xc5\xce\xfe\x3a\x27\xfc\x75\x01\xb9\x20\xa7\xe5\x82\x7c\xf7\x3b\x78\x8a\xfe\x97\xb2\xbf\x18\xa3\x95\x5a\x90\x7f\xca\x16\x44\x01\x74\x32\x82\x60\x3e\x47\xfc\x05\x15\x7b\xa8\x13\x40\x5f\xd0\x5d\x50\x45\x4f\x95\x38\xf3\xc4\x9e\xc3\x24\x08\x61\x21\x67\xcb\xe7\xf5\xe1\x00\xd5\xe1\xc9\xe7\x4b\xb2\x42\xcd\x4e\xf6\x3b\xb3\xc4\x95\x2f\x29\x32\xfd\x49\x41\xce\x2c\x11\xf2\x6a\x08\xde\x60\xa0\x3f\x4d\xff\xa3\xef\x11\x82\xff\xe4\x8c\xbc\x12\x1f\xa6\xbd\x88\x0f\x7b\x07\x4f\xd7\x5e\xa0\xff\x7b\xe7\xb3\x97\x3f\x78\x99\xdb\x3c\xbc\xf4\xe5\x0f\x5e\x1e\x4e\x70\x7f\x84\x75\xc7\x46\xde\xe7\xae\x81\xdc\x98\x1f\x0d\xa0\x92\x97\x83\xbe\x17\xea\xaf\x04\x84\x2c\x20\x26\xa2\x9d\x15\x9b\x84\x92\x42\x16\xba\x29\x6c\x46\x9a\x0f\xa9\x5e\x5e\xef\x3c\x1c\xb0\x80\xee\xc4\x71\x1a\xc7\xce\x3d\x6d\xd6\xe2\x0b\x4e\x3a\x66\xf1\xda\x7b\xf0\x92\x11\xb4\x6a\xf9\x79\x0b\x66\x9f\x78\xde\x7c\xbc\x85\xdf\xb1\x3f\x87\x04\xd4\x8f\x90\xab\x09\x66\x82\x03\x90\x8f\xff\x96\x3e\x8b\x8b\x82\x85\x82\xea\xe2\xab\x24\x9e\x2f\x45\x75\x50\xff\x08\x5f\x25\x81\x3c\x64\xe6\xfd\x3b\x01\xcc\xbf\x67\x54\x37\x35\xea\x25\x01\x98\xe5\x73\x09\x7b\x49\x40\x52\xb1\xb0\x97\x2f\x23\xec\x0a\x98\x05\x06\x97\x93\xdd\xd2\x11\x59\x15\xfd\xc5\x22\x89\x2a\xa4\x89\xa5\x86\xf5\x02\x2a\x6f\x4e\x48\xe0\x71\x66\x8e\xfb\x71\x7f\x6d\x2e\xe4\x64\x7d\x28\x84\xdb\x3a\x6a\x12\x79\x77\x3d\x09\xa0\x39\x4a\x81\xf5\x19\x8a\xcf\xe7\x8e\x33\x9e\x0c\x32\x71\x6e\x84\xd9\x64\x26\x93\xcb\x59\x9d\x8a\xa0\x82\x1a\x77\x54\x59\xcd\xca\x65\xb0\xdd\xe2\x02\x75\xe0\x4b\x51\x7a\x32\x45\x1c\xd5\xff\x9b\x74\xa2\x49\x59\x01\xb9\xc0\x04\x71\xa9\xb5\xab\xdb\x48\x9c\x37\x94\x4e\xa3\x29\xe8\xc6\xd2\x79\xeb\x40\xb3\xd1\x0d\xa5\xd3\x70\x60\x1a\xb8\x88\x1c\x7b\x00\x37\x22\x83\x7a\xd0\x34\x74\x35\x2a\xf5\x50\xd9\xf8\x0a\x6a\xd6\x51\x65\x70\x31\x5d\x54\x16\x9d\xc6\x30\x77\x0a\x06\x34\x30\x39\x8c\xd5\x70\x19\xce\xb1\x87\x55\x39\xd5\xe9\x38\xab\x7a\x22\xb2\x52\x16\x7c\xc1\x24\x43\x53\x02\x42\x01\xa4\x76\x66\x65\xa5\x84\x92\x34\x3a\x53\x53\x3d\xb2\x52\x92\xe4\x18\x2b\xe9\x96\xec\x8e\x09\x0c\xc2\xb6\xdc\x9b\x9f\x32\xd5\x08\x43\xa1\xcf\x46\xe7\xc3\x6b\x38\x62\x31\x9e\xc4\x96\xdf\xf8\xe1\x86\xc5\x97\xf6\x3b\x38\x5b\x60\x01\xee\x19\x3d\x79\x31\xff\x88\x59\x6b\x8e\xe1\xed\xa3\xe4\x97\xb0\xca\x0f\xaf\x7b\x11\x7f\x6d\xeb\xbc\xe5\x89\x0b\xbe\x8c\x57\x5a\x06\x33\x16\x9d\xfa\xc3\xdd\xc3\xc3\x8d\x27\xcf\x19\xff\xea\x62\xdb\x2e\xe0\x9f\x0e\x98\xdd\x7d\x06\xff\x74\x89\xf3\x78\x0b\x85\x02\x91\x73\xaa\xc3\x0d\x2d\xe6\x16\xfe\x69\xbd\x35\xc7\x6c\x5e\x6c\xc0\x3f\x4d\xad\x6e\xcb\x98\x76\x1c\x3d\x7e\x2c\x23\xde\xed\x33\x93\x15\x1e\xce\xc4\xa7\x41\xaa\x43\x6f\x3f\x47\xb2\xde\xfa\x46\x83\x1e\xb3\xbb\x84\x25\x5e\x4d\xce\xea\x75\xcb\x16\x9c\xb1\x26\x81\xdb\x71\x9f\xb6\x63\xf2\xa7\xbf\x5b\x71\x0a\x23\xaf\xbe\x3d\xb8\x7a\x9d\x78\xe6\xbe\x6f\xfc\xf3\xf7\x71\x9d\xe3\x25\x68\xab\xd8\x82\x48\x44\x32\x4a\xa0\xc1\xb1\x4c\xdb\x65\x0f\x0e\xf9\xb2\x6a\x5c\x60\x55\x1c\x20\x39\x21\x9e\x02\xf1\xe7\x54\x87\x8b\xc5\xf6\xb5\xc5\xeb\x74\xe9\x44\x49\xed\x94\x61\x5e\xb0\xf9\x40\x52\x30\x0b\x85\x6e\x89\xb8\x20\x8a\xf6\x0e\x21\xd5\xe5\x65\x52\xa0\xbf\xea\x52\x70\xd7\xa4\xa0\x7a\x14\x59\x51\x43\x90\xe0\x42\x0e\x59\x19\x25\x09\x6a\x60\x00\x70\xd2\x88\xc6\xfb\x98\xe9\xfd\xeb\xdb\x86\x71\xaf\xf6\xe9\xb1\xda\x53\x67\xcd\xe1\x16\xd4\xd1\x7a\xbf\x1b\xda\x2c\x6c\xfe\xbc\x5b\xdb\x10\xb3\x0f\x18\xb8\x0c\x3c\xf4\xd8\x7c\x0c\xf7\x9d\x1f\x35\x21\xd5\x64\xf8\x06\xe8\x59\xe2\x02\x6f\xc0\xe6\xaa\x92\x58\x4e\x0d\x08\x55\x15\x73\xf9\xbc\x11\x52\xd4\xf3\x7d\x53\xf1\x38\x71\x56\x75\x79\xab\x44\xa2\xe2\x09\x4b\xb5\x1e\x24\xb3\xaf\xd9\x14\x89\x13\x40\x4c\x5c\x2c\xb1\xe0\x70\x43\x62\xde\x6d\xa0\xd1\xf0\x34\xb0\xa2\x27\x34\xc7\x3a\x46\xe0\xe4\x56\x03\x31\x2a\x14\x5b\x8d\x90\x52\xe7\x5d\xc7\x91\xc6\x82\xd1\x69\xc4\x6d\xe3\x48\xc5\x16\xdc\xbb\xbb\x91\x4c\x60\x6f\x38\x9e\x01\x6e\xe2\x66\xf4\xe6\x68\x6e\xda\x32\x67\x8f\x44\xdb\x22\x05\x92\xc8\xa9\x01\x77\xb5\x31\x4b\x2d\x71\x30\x22\xd2\xa8\xff\x5f\x24\xac\xb5\x6c\x21\x00\x16\x67\x20\xe3\xa8\xc2\xbb\xfd\xe1\x98\xd9\x12\xc8\xbb\xcc\x1f\xcd\xec\x1f\xa3\x33\x86\x88\xc8\x21\xab\x01\x48\x84\x07\x12\x2c\x25\x88\x18\x46\xff\x18\x6e\x5b\x71\xcc\x1e\x6b\xc4\x6d\xcb\x5f\xde\x60\xcb\xd5\xf3\xdb\x5a\x77\x1f\xec\x3d\xc7\x9d\xb6\x20\x92\x50\x02\x75\x62\xdc\x90\xe5\xb7\xec\xc1\x29\x5f\x56\xed\x10\xaa\xa5\x66\xba\xfd\xf4\x8e\x7a\xd2\x94\x53\x03\x2e\x73\x70\xa7\x26\x5d\x22\xe7\x0d\x01\xeb\x9d\x81\x24\x49\xad\x2d\x23\xd5\x6a\x64\x5f\x50\xd2\xa6\x4d\x5a\x7a\xed\x41\xd2\xa1\x68\x9d\xa4\x43\xd1\x31\x92\xa6\xd1\xbd\x43\x26\x4d\x45\x35\x42\x63\xb7\x14\x54\x72\x51\x00\x30\xcd\xd5\x8e\x26\x08\xb5\x09\x96\xd5\x64\xa6\x38\x9e\xdc\xc7\xd9\xd1\x0d\x15\xf0\xd4\xf8\x1b\xbc\x5e\x0f\xe3\xee\x75\xfb\x99\xb6\x20\xf4\x3a\xf5\xa0\x4f\x46\xb3\x0d\xab\x89\x64\xa1\xc0\x02\x81\x54\x4e\x8d\xb9\xaa\x64\x62\x8e\x2a\xc6\x80\x1b\x3b\x48\xa3\x1d\x71\xb2\xc1\xf7\xa4\x57\x9f\x71\xe8\x66\xbc\x87\xe3\x92\x12\xd7\x60\x18\x12\x12\x89\x43\x23\x45\xf3\x10\x2a\xbb\x7d\xf1\x66\xa3\x37\x33\xde\x5c\x63\xc6\x82\x99\x10\x81\x63\x7c\xe5\x65\x9b\x12\x69\xa5\x21\x95\x53\x62\x3d\x13\x09\x99\xa4\x8a\x24\xa9\xa8\x1d\x13\x01\x16\x20\xc5\x86\xb9\x90\x4c\x22\x06\x71\xeb\x01\x9b\xfb\xc6\x51\x45\x23\x32\x63\x6e\xcd\x38\x6a\x68\xc0\xdb\xdb\x40\x11\xfc\xc8\x55\x08\x89\x2d\xf6\x1b\x90\x1d\x18\x9a\x66\xd6\xce\x5c\xba\x2b\x2a\x36\x07\xc2\xde\xac\x6a\x73\xb3\xb4\x81\x00\x07\x2d\xa4\x0d\x78\x41\x56\x4a\x5c\x98\xa1\xf3\x62\x87\xee\x75\x67\x30\x03\x1c\xc7\x69\x3e\x87\x33\x36\x7b\x3d\xa0\xfc\x1a\x4e\xc3\x97\xdc\xa2\xed\x8a\x6a\x9d\x8f\xe2\x6e\x7c\x6c\x93\xc8\x8b\x53\x26\x57\xea\x5c\xb0\x67\xf6\xcd\xc2\x27\x6b\x0f\x72\xa7\xe2\x15\x57\x6d\xbc\xe5\x5c\xfe\xd6\x3a\x67\x81\x71\x7f\x12\x5b\x1a\x29\x28\x85\x7a\xd1\x5c\x86\x02\xc1\x1a\x50\x9d\xd8\x98\x85\xcd\x3a\xab\x06\x02\x68\xda\x5f\x05\x48\xcf\x34\x8d\x11\x02\x41\xfa\xb6\x59\x48\xdc\x7b\x7d\xc0\xfe\xe8\xd4\xfb\xc3\x4c\xbf\xa9\x50\x03\x67\xb4\xbe\x3b\x5f\xd7\xd7\xb2\xfc\x87\x1f\x5e\x7f\xda\x86\x4e\x47\xf1\xcf\x1f\xbd\xeb\x73\x5c\xfd\xe4\x2d\xff\x81\xeb\x68\xa5\x7b\x8f\x9a\x31\xfb\xf2\x85\xc7\xce\x9c\xb5\xe6\x18\x7c\xc5\xcb\xf8\xeb\x2f\x2d\x59\x74\xe3\xe7\x0f\xdc\xf4\xd0\x5b\xe2\xd1\xb5\xf5\x7c\xfe\xc6\xb2\x65\x57\xbf\x7f\xd3\xd1\xa7\xfc\x90\xf5\xcd\x8d\xbc\x84\x90\xd0\x64\xbf\x01\xb9\x51\x8c\xae\x0c\xba\x4c\x45\x8e\x51\x9c\x99\x6d\xfe\x26\x7e\x03\x5c\xec\x6c\x3a\x79\x08\x95\x39\xde\xe1\x64\x96\x6a\x7c\x82\xbc\x38\x9b\xbc\x60\x53\x17\x11\x3b\xea\xb4\xac\xa9\x63\x5a\xdb\xd3\xdb\xd8\xec\xc5\xb6\x8d\xed\xda\xae\xbc\x65\x01\x64\x31\x5f\x5a\x4c\xc8\xe2\xfd\x0b\x17\x13\x7b\xcf\x5c\xf3\x9d\xcd\xb9\x7a\xfe\x7a\x5b\x1a\xf1\x48\x46\xa7\x58\x2c\x06\x83\x13\x03\xf5\x61\x0c\x08\x78\x65\x9e\xc3\x8e\xac\x8a\xbc\x30\x19\x43\x4d\x27\x60\x5e\xc2\x4f\xd1\x55\xf0\x98\xc6\xe2\xd8\x2c\xb3\xf0\xb2\x6a\x83\xbb\x56\x21\x0e\x60\x3e\x0f\xa4\xc7\x30\x7d\xe1\x9e\xbf\x7e\x5c\x4f\xef\xf5\xf9\x03\xa3\x7d\x4a\x83\x2b\xf7\x06\x98\xfd\xef\x46\x8b\x1b\xb2\xa3\x4e\x68\xc4\x8e\x9a\xd5\xd9\x51\x2b\x82\x3b\x91\xd2\xb9\x51\x4b\xad\x99\xb6\xe2\x17\xe1\x2c\xae\x37\xfb\x03\xd1\xa2\xde\x6c\x5d\xca\xc1\x78\x70\xef\xb7\xae\x92\xed\x85\xfb\x81\x0f\x35\x8e\x3a\xd1\x32\x7d\x8d\xcd\x46\xc7\x68\x5b\xed\xce\x4a\x78\xa1\xa7\xb2\x55\x67\x43\xed\xc6\x59\x86\xca\x09\x6c\xa8\xad\x72\x45\x70\x2b\x31\x89\x91\xa1\xaa\x41\x00\x03\x6e\x6b\x1e\x97\x09\xb5\x7e\x5b\x8c\x6a\x0a\x34\x59\x50\x9b\xad\x0b\x4b\xd7\xb7\x04\xea\x14\xa8\x62\x9f\x65\x33\xfc\xb7\xd1\x10\x68\x60\x71\xdf\x80\x82\xac\x03\xa3\x11\x8a\x6d\xe6\xc0\x28\xb6\x6d\xff\x17\x14\xdb\x48\xac\x25\xc5\x50\x6c\x4b\xf1\x44\xf2\x50\x50\xf8\xeb\x44\x32\x0e\x80\xed\xa6\xba\x48\xa9\x31\x02\xf2\xc3\xf5\x9c\x39\x0c\xfb\x98\xf1\xf1\x37\x46\xad\x6d\x3f\x20\x6a\x2d\x69\xce\x43\xe6\xda\xce\xcb\x4a\x29\xc8\x20\x6b\xa1\x12\x4b\xbc\x0c\x48\x3f\xde\xca\x70\x6b\x4b\x7e\x9d\x62\xff\x10\x51\x6b\xad\xcb\x1d\x07\x6c\xb4\xa9\x6e\xb9\x8d\x00\x8c\x2f\xad\x8b\xa7\x19\x76\x76\x37\x0a\xa2\x16\x94\x41\xbd\x88\x8c\x83\x9e\x4d\x7a\x0a\x6a\xd4\x55\x25\x9d\x79\xea\x18\x00\x0a\x6b\x6e\x5c\xf4\x6c\x83\x76\xde\x80\xce\x9e\xe0\xf3\x3a\xb2\x8c\xfd\x35\xa7\x4e\xf0\xc2\xcd\xf0\xc5\x40\xb3\x4b\x4e\x25\x45\x23\xa3\x78\xe8\x10\x81\xd8\xcd\xdb\x3b\x30\x90\xb6\x8b\xb5\x1f\xc7\xb1\x92\xa1\xe3\x8e\x9e\x3e\x63\xee\x82\xb5\x9d\x9d\xdc\xf5\x9d\xda\x2b\xfa\x4f\xe3\x80\x1d\x97\xe6\x2e\xe8\x9f\x34\xeb\x38\xbc\xf0\xd9\x67\x3f\x64\x1f\x11\x70\x43\x33\xbb\xd9\x85\xc2\x28\x8d\xda\xd1\x24\x74\x93\xd5\x76\x9a\x38\x98\x1b\x55\x53\xae\x2a\xc9\xe5\x4d\x48\xdb\xd6\x9c\x9a\xf1\x54\x8d\x76\xec\x46\x90\xb6\x46\x0b\xaa\x61\x5c\x1d\xd4\xaf\x9a\xa8\x37\x64\x53\xd9\x54\x9c\xc1\x54\x2b\xe4\x96\x3b\x92\xb2\x52\x92\x14\x99\x1a\xdc\xc4\xb1\x98\xd9\x87\x82\x94\x3d\x4a\x5c\xe3\x58\xd9\xd1\x8d\xc5\xd5\x08\x1d\xf9\xde\x46\xc2\x32\xec\x6e\x05\x0a\xa2\x66\xd4\x89\xf2\xe8\xd9\x86\x76\x97\xcc\x91\x3e\x66\x77\xd9\x3c\x30\x06\x8e\x07\xd7\x5e\x2b\x1d\x19\x36\xd7\x0b\x70\xed\x35\x06\xb9\x5e\x06\x88\x3b\xf9\x5f\x83\x6b\x6f\x0a\xc9\x8a\xda\x92\x2a\x16\x49\x17\x50\xf1\xf5\x52\xcf\xf2\x90\xac\x90\x49\xd5\xe4\x58\x3c\xb8\x25\xce\x9b\x75\xf1\xac\xa3\x2f\xd9\xb6\xe4\x1b\x78\x76\xee\x89\xd3\xb9\x63\x66\x7d\xa9\x38\x6b\xee\x37\xc7\x37\xc5\xaf\xcd\x3a\x0e\x47\x23\x2b\x2a\xca\xe4\x7b\xe6\x54\xe6\x2e\x98\x92\x9b\x75\x9c\x61\x8b\x76\x0f\x0a\xa3\x14\xea\x46\x93\xd1\x9d\x63\x6c\xb1\xa7\xa0\xb6\xb8\xaa\xa4\x90\xaf\x1d\x6b\xfd\xe3\xe3\x2a\x27\x98\x20\x13\x35\x3b\x9c\x90\xda\x29\xeb\xbc\x7c\x40\x26\xc7\xb6\x69\xb0\x85\x6e\xd3\x44\x44\x56\xd4\x74\x6b\xb1\x48\x26\xc8\x65\x49\x91\xbb\xe9\x79\x37\x49\x51\xfd\x6d\x87\x7e\xda\x1d\x50\x78\xe3\xd8\xe5\x31\xe3\x08\x6f\x1c\xc3\x6c\x24\x3a\xd3\x36\x4f\x85\x33\x71\x22\x1a\x40\x4f\x8d\x77\x26\x4e\x61\xb6\x39\x29\x8f\xc9\xd4\x43\x3e\x0c\x0b\x70\x18\xf6\x78\xab\xa4\x27\xa7\x16\xbc\x55\xb5\xf8\x45\x4d\xb2\xec\x54\x60\xf6\x0c\x4e\x43\xb5\x35\x5b\x2c\x92\x1e\x99\xb4\x15\x49\x41\x51\x3b\x26\x1c\xc2\xbd\x69\xd9\xee\x56\xc7\x34\x70\x50\xe3\x7c\x6e\x21\xdd\xe9\xf3\xd7\x76\x3e\x30\xfb\xd4\xbb\x8f\x1f\xfc\xfd\x31\xda\xff\x2e\xfa\x9b\xfe\xdd\x81\x0f\x4b\x2e\x17\xcc\x7f\xed\xec\xde\xe0\x33\x0b\x6f\xd0\x54\xcb\x39\x40\xed\xf4\x15\xbb\x0f\xce\xcc\x5e\x54\x44\xb7\x8f\xb1\xd3\xfc\xff\x9f\xbd\x37\x01\x8f\xaa\xbc\xf7\xc7\xdf\xf7\x6c\xb3\xcf\x9c\x73\x66\xcb\x6c\x49\x26\x93\xc9\x24\x99\x24\x43\x32\x49\x86\x11\x65\x09\x5b\x64\x13\x29\x22\x02\x46\x14\x17\xc0\xe2\x86\x88\x88\x88\x14\x11\x41\x11\xc1\x1d\xd0\x5a\xac\x54\xa9\xb5\xe7\xcc\x0c\xb1\xb5\x56\xe3\x4a\x5d\xd0\x72\xad\x50\x6b\xdb\x9f\xd6\xa5\x9d\x5e\xec\xed\xc5\xd6\x8a\xca\xc9\xff\x79\x97\x33\x4b\x16\x90\xde\xfb\x7b\x9e\xff\xf3\x7f\xfe\xbd\x8f\x63\x32\xe2\xf5\xbc\xdf\xf7\x3d\xdf\xf7\xbb\x7c\xbe\x9f\x0f\xf1\x99\x23\x4b\xce\xe9\x69\xdf\xda\x59\x26\x90\xb3\xec\xa0\x5a\xe3\xc4\x76\x2e\xe2\x2b\xf1\xe4\x4e\x6d\x73\x3a\xad\x24\xf0\x11\xc5\x21\x67\x87\x9c\x71\xd4\x37\x9d\xc2\x95\x7c\x72\x4b\x0e\x77\x52\x4f\x64\xc9\x13\xf8\xd1\xe1\xec\x38\xd0\x9f\xfe\xf2\xff\xad\xfe\x34\x6b\x92\x71\x98\xa7\xd6\xfb\x91\x8f\x88\xa6\xd3\x4a\x8b\xa4\x46\x6a\xbf\xe5\xb1\xa5\xb6\x0e\x7b\xbc\xee\x48\x0b\x84\xdf\xd6\x9d\x76\xc1\x70\xf5\x79\xea\x25\x97\xc1\xe6\x6f\xe3\x4f\x99\x66\xd7\xb2\x47\x7d\x17\xdd\xa0\x5d\x35\xac\x3f\x1d\x7c\x4e\xff\x6f\xf8\xd3\x9c\xc9\x55\x85\x69\xfb\xd5\xc6\x20\x16\xc4\x90\x22\x31\xec\x4a\xa5\x8c\x23\x5a\x77\x8a\xe7\x74\x58\xd3\x9d\xd8\x99\x0e\x36\xdd\xf0\xde\x74\x90\xe1\x70\xde\x9a\xec\x3f\xc2\x05\xb8\xe5\x58\x9f\x6e\x31\xe5\x1f\x0a\xf0\x14\x39\x6c\x34\xe4\x73\x6c\x15\xe6\x1f\x62\xad\x79\x9d\x51\x91\x8e\x5a\x71\x30\xae\xca\x84\x44\x91\xf0\x0f\x59\xac\x38\x96\xce\x1a\x1d\x1e\x32\x2f\x53\x45\x58\xa1\x54\x23\xba\xaa\x2d\x94\x7e\xc8\xaa\xd3\x0f\x91\x01\x48\x43\x87\x4e\x8e\xa9\xcf\x53\x61\xf6\xa1\x24\x9c\x0e\x3b\x93\xec\x65\x0b\xcf\xbd\xf3\x92\xcb\xf6\x2d\xf9\x8f\xfc\x0f\xb4\x4f\xf6\xa9\xaf\xc2\xf0\xe2\xb9\xbb\x7c\xcd\x3b\x7f\x02\x43\xcf\xbc\xd1\x30\x7f\x49\xdd\x88\x8f\x5b\xa3\x1f\x1d\x78\x53\x7b\xf2\xe9\x47\xef\xe9\x79\x68\xc5\x85\x00\x00\xbe\x7f\x03\x00\xdc\x5f\x8d\x0d\xb8\x7e\xe3\x07\x95\xa0\x01\x6c\x1c\xb6\x86\xa3\xf8\x12\x4a\x7d\x52\x75\x9a\x31\x46\x3a\x90\x50\x83\x56\x92\x05\x8b\x85\x82\x5a\x15\x8c\xab\x51\x5b\x5e\x89\x8a\x0a\x8b\x5c\x16\x3a\x29\x1c\x49\xdd\x51\x62\xec\x11\x25\x39\x67\x86\xb6\x00\x9d\xad\x53\x79\x53\x3a\xad\xb2\x55\x92\x9c\x61\x6a\xea\x4f\x52\x0b\x1a\x36\xb8\x1b\xba\x2e\xb4\x63\xc8\xd8\x6e\x60\x81\x88\x79\x64\xa8\xb8\x8e\xc7\xb9\xf1\xc3\xc2\x61\x5c\x27\x8a\x83\x04\x38\x0d\xdc\x56\x5a\x2b\xaa\x45\x6f\x4a\x32\xa9\x36\x9a\xf3\x4a\xba\xad\xa4\x74\x14\x32\xe1\x52\x63\x33\xb2\xcc\x28\x7c\x04\x9c\x8e\xbc\xe2\x14\x31\x17\x4c\xcc\x96\x57\x62\x22\xae\x27\x75\xda\xf2\xea\xe9\x30\xae\x86\x9d\x64\x60\x21\x26\xe5\xb8\x90\xa7\xa9\x99\x04\x18\x59\xab\xdd\x6f\x43\x3f\x76\x4a\x19\x83\x89\x68\xd1\x73\x21\x7d\x4c\x76\x70\xad\x29\x5a\x56\x5d\x72\x0e\x6b\xa9\x21\xea\x4e\xad\xc5\x52\x53\x78\xe8\x68\xb8\xac\x00\xf5\x56\xa1\xe6\xc4\x36\x0d\xb6\x1c\x57\x76\x9e\x9c\x20\x08\x2e\x1b\xfe\x34\x05\x12\xaa\xd7\x8c\x87\x0e\x25\x2b\x69\x4e\xb9\x0e\xe5\x7c\xd8\x71\x64\x39\x9f\xcb\x18\xc7\xc7\xa6\x12\xb9\x10\x97\x24\x67\x79\x93\x2d\x40\xe4\x91\x15\x6f\x5a\x61\x09\x21\xfc\xf0\xa7\x45\x5f\xb8\xdb\x35\xdc\x01\x59\x8e\x97\x59\x31\xa5\xeb\xaa\x4d\xcb\x07\xd5\x0d\x37\x3d\xff\x7c\xbe\x7b\xea\xc5\x77\x03\xd2\xab\x2d\x9c\x85\x5a\xd0\x02\x2e\x2f\x3d\x09\xf5\xe8\x52\x6a\x36\xe7\x07\x9c\x81\x70\x42\xad\x29\x26\x97\xf4\x0c\x44\x61\x3c\x17\x27\x9e\x11\x9d\x81\xa8\x13\xf9\x42\xce\x83\x3d\xa3\x12\x97\x72\x56\xbb\x3f\x64\xc3\xee\xe0\x14\x36\xbb\x64\x87\x4f\xb6\xc1\xdd\x31\xe6\xf6\x98\xe6\x3b\xb3\x6b\x64\x7a\xf3\x35\xc3\xed\x2b\xe7\xc1\xfb\xd9\x99\xb8\x1b\x90\xfa\xae\xe1\x4a\x41\xc3\xbb\xe9\x05\xe3\x8a\x0c\xc5\x26\x9d\xa1\xd8\xc9\xe6\x15\xb6\x2d\x67\x17\x31\x49\xb1\xdd\x92\xcf\xf1\x46\x9d\xaf\x18\x33\xc3\xf0\x45\x12\x72\xbc\x4f\x94\x82\x2b\xcc\xa2\x1d\x83\x61\x67\x04\xed\xd5\x6a\x76\x07\x37\xb3\x53\x03\xe3\xe1\x1f\x52\x5a\xcd\x59\x0c\xe8\xfc\xe6\xed\x29\xda\x9c\xf7\xe1\x5a\x78\xc6\xda\x99\x4c\x33\x73\x79\x33\xdf\xab\x69\xcf\x6b\xda\xc6\x7e\x40\x76\x8a\x99\x0b\x97\xbf\xf3\x0e\xd9\x1f\x61\x3f\xff\x24\x68\x02\xa7\x81\xd1\x60\x32\x78\x91\x30\xa8\xe1\x99\x61\xa5\x31\xa9\xfa\x0d\x74\x77\xec\x10\xd3\xef\xa8\x13\xf9\x3c\xfe\x59\x4d\x99\xf2\x39\xd7\x98\x6a\xbb\x2d\xae\xba\xac\x79\x65\x54\x42\x3d\x1d\x3d\x6d\x37\xde\xb4\x66\x47\x5e\x69\x26\x9b\x56\x4b\x70\x32\xb5\xa2\x3a\x1e\xe2\x61\x62\xf5\x4c\xb4\x7f\xcd\x92\x9c\xe5\x1a\x47\xa4\xd0\xf6\xd5\x4a\xbd\x46\x43\x5d\xac\x7d\xd4\xe9\xe8\xb7\xf1\xf2\x58\x93\xc9\xee\xf6\xf8\xab\xcf\x18\x3d\x86\x68\x73\xab\x21\x4c\x6a\xeb\x8a\x4a\xf2\xd3\x20\x54\x19\xa9\x8b\x35\x63\x09\xef\xd4\x18\x49\xce\x48\xed\xe3\x89\x62\x9d\x6a\xb0\xa4\xcb\xb7\xdd\x40\x9d\x3e\x17\x8e\x18\x4a\xe9\x4d\x63\x86\x62\x77\xde\x53\xd6\x9e\x0f\x1b\x08\x9e\x2d\x52\x23\xcc\xdb\x94\xbf\xf3\xfc\x9b\x92\x96\xf4\xb3\x72\xd3\x83\x0b\x1e\xca\x6a\x19\xed\x8d\x76\xe6\xca\xc5\x5d\x4f\x4e\xcb\xf6\x2e\xdb\x92\x10\x9f\xb5\x9b\xa7\xdc\x33\x77\xfb\xa3\xb0\x75\xdc\x69\xdd\x6b\xce\xec\x9a\x38\xe1\xfa\x49\x70\x36\x32\xb7\xf6\xe7\xe6\x9d\x3f\x59\x32\x77\x17\x5c\xf7\x2b\x78\xc1\x1b\x53\xcf\xdb\x3a\xaf\x75\xf4\x8f\x36\xff\xe2\x0d\xa7\x73\xe1\x65\x2d\xf5\x1f\xcd\xe9\x3c\xbd\x67\xdb\x82\x33\x7f\xf7\xda\xec\x05\xb7\xff\x75\xf5\xcc\x85\x9b\xf3\xcc\x81\x77\xde\x39\xfe\xd4\x85\xdf\xb9\xe0\x11\xc2\x0b\xc6\x2f\xe3\x0f\x80\x5a\x70\x36\x9d\xb9\x13\x4d\xb4\x76\x6a\xb6\xe4\x73\x2e\x77\x0d\x67\x8b\x2b\x81\x24\xb6\x7b\xa8\x2d\xe7\xab\x40\x5f\xa8\x3e\x36\x9f\x35\xd4\x70\xc6\xb8\x5e\x9b\xb2\x8b\x18\x3d\x09\xd4\x0a\x94\x23\x00\x7b\xba\xc8\x0a\x66\xa0\x54\x60\x62\xb8\x6d\x0c\xc4\x84\xe7\x94\x73\xa5\x84\x11\xec\x77\x7d\xcb\xa7\xdc\x73\xee\x83\xff\xbd\x09\x26\x66\xcc\x94\x3f\x6f\xf8\x97\x5b\xfb\x22\xc5\x24\xa7\xad\x6d\x58\x97\xbe\xf5\x93\x9b\xb5\x7e\xed\x63\xca\x07\xb6\xe8\xeb\xfa\x11\x7b\xb4\x03\xaa\xf6\xb0\x6f\xf6\xab\x8b\x20\xa3\xed\x7c\x55\xfb\xbc\xc8\x05\x16\xd0\x5c\xdc\xc3\xdc\x72\x10\x05\x49\xd0\x03\x32\x7e\x74\x9c\x30\x8a\x6e\x84\x09\xc3\x3f\x19\x3e\xaf\xf0\x09\xa5\x32\x99\x13\xc8\x44\x5c\xb0\x0d\x2a\xed\x98\xac\xbb\xce\x91\x57\x3b\x60\x5c\xad\x93\x24\x39\xc7\x08\x76\x9e\xe8\x17\xf1\x0c\xb9\xf1\x47\xd4\x48\xb2\x2a\x35\xa4\xd3\x8a\x5f\x52\x2a\xd2\x23\x5a\x71\x0b\x38\x92\x0a\xa7\x3a\xc7\xc0\x08\x19\xdf\x29\xfa\x80\xa4\x81\xec\x79\x0c\x96\x6d\x7a\xe0\x91\x67\xaf\x9f\xf2\x59\x18\x7a\x44\xb3\xcf\x6d\xbc\xe1\xc5\x2d\x8f\x6c\xf9\xcf\xdb\xe6\xad\x1b\x6b\x4c\xff\xe5\x1f\xdb\xaa\x77\x8f\xf9\xfb\x4b\x8b\x9f\x98\x0f\xaf\x9a\xd6\x35\x7e\xc5\x8c\x29\x63\x26\xdd\x78\xe6\x0b\x73\xce\x7f\x68\x5a\x6c\x42\x7a\x57\x5f\xf6\xe7\x70\x66\xdf\xc4\x0b\xb6\x7e\xbd\xe1\xa1\x1d\x0f\x54\x35\xb0\x0b\x67\x9e\x75\xcd\x87\x57\x76\xcf\xbd\xf9\x3f\x00\xe1\x4b\xe0\x97\x19\x96\x63\xfc\xce\x0c\x3a\x39\x53\xa8\x82\xa3\x9d\x74\x7b\x02\x68\xe3\xdc\x68\xe3\x02\x78\xe3\x9a\x0a\x1b\xd7\x8c\x36\x4e\xa7\x79\x30\x04\x30\xf5\xba\xca\x99\x29\x12\x60\xc0\x36\x0e\x60\x74\x2b\xaf\x12\x0e\xd8\xcd\xc1\xac\x6e\xf0\xa9\xb2\x42\x78\xf9\x9e\x96\x71\xbb\x09\xdd\x03\x6b\xfd\x78\x6f\x85\x30\xa8\xc4\x1e\x64\x06\xc0\x8d\xdb\x8c\x44\x1d\x04\x25\xf9\xc3\xd7\xb9\x0d\x7b\x05\x7c\x71\x37\x63\x55\x75\x26\x50\x45\x14\x69\x31\xf9\x5e\x65\x5a\x49\x49\x19\x60\x1b\x81\x25\x8a\x64\x3c\xc8\xe3\xc5\xdb\x44\xdf\xd4\xd2\x9d\x14\x38\xbc\x8d\x65\xcb\x74\x0e\xdc\xd4\xc5\xeb\x47\x56\x1a\xbb\xef\xfc\xce\xed\xbb\xb7\xfc\x75\x13\xdd\xcf\x76\xed\xeb\xbf\xa2\xdd\x6c\x2a\x5d\xb1\x3c\xad\x6b\xc2\xb5\x33\xa6\x8c\x99\xbc\x66\xf2\xc3\x73\x2e\x78\xfd\xc2\x9e\x69\x87\x9e\x7f\x19\x5e\xf4\x26\xda\xd8\x8d\x7f\xfb\xa8\xaa\xc1\xf0\x64\x79\xe7\xe8\xe6\xcf\xd7\xcc\x5c\xb8\xed\x53\xca\x41\xcf\xff\xd0\xb0\x1c\x58\x81\x1f\xdc\x4e\x3b\xa9\x46\x6b\xa1\xb3\xcd\x27\x93\x3a\x4c\xc2\xea\xc8\x2b\xd6\x22\x2d\x56\x70\x38\x5a\x2c\xab\x98\x65\xad\x8c\x33\x9e\xb5\xa0\xcf\x8c\xc5\x3a\x88\x16\x0b\xa3\x24\x58\x1d\x25\xc1\x58\x25\x39\x63\xb6\x11\x52\x3c\x3c\x68\x62\xa6\x94\x58\x29\x9d\x22\xca\x39\x08\x9d\xd5\xb6\x63\x17\x7c\x08\x2e\x39\xfe\x14\x25\xc4\xfa\x61\x39\x16\xeb\xf8\xe8\x83\xf0\xbf\x8f\x4f\xa0\xbc\x58\xe5\xca\x19\x84\xdb\x19\x18\x76\xe1\xae\xe5\x36\xba\x66\x8b\x23\x99\x24\x33\x1a\x94\xfe\x8e\x0c\x84\x39\x6c\x78\x04\x9c\x62\x43\x0a\x13\x61\x05\x1c\x08\xf9\xc1\xa2\x38\x44\x32\x02\x4e\x26\xbf\x07\x0c\x7b\xe3\x45\xe3\x99\x13\xd6\x5e\x42\x65\xb7\x4f\x30\xd8\x44\x89\x8c\x6d\x1a\x31\xfb\xaf\x2d\xad\xb3\xd6\x95\xf0\x63\x95\x2f\x1e\x83\x41\xee\x19\xc4\x92\xb5\xa1\x74\xfd\x82\xeb\xf8\x94\x72\xae\x2c\xc3\xfa\x41\x3d\x2e\xcd\x45\x79\x5d\xaa\x40\x33\x58\x43\xfa\x3f\x39\x89\xa8\xbb\xe1\x17\xbc\x91\xcd\x2b\x21\x4a\x77\x48\x1a\xe7\xd5\x62\x3e\x6b\xaf\x06\xc6\x78\xce\x4d\xf5\x35\x45\x0c\x0e\x36\x90\x06\xb9\xea\xae\x46\xde\x2c\x94\x46\x11\x6d\xaf\x85\x93\xfd\x81\x48\x23\x19\x4a\x45\x11\x4d\x00\xb3\xa5\xdb\xdd\xfe\x74\x3a\xad\x36\x4a\x92\x9c\x31\x80\x48\x7a\x88\x76\xd8\x20\x4d\x32\xe7\x60\xde\x94\xb2\x96\x18\x28\x13\x27\x1b\xcc\x9e\x52\xd2\x13\x3b\xfe\x72\xa9\x4a\x19\xbb\xa3\x9c\x46\x05\xb0\x60\x9e\xe6\xe2\x66\x73\xcb\xb1\x5d\xe2\x60\xd3\x00\xbb\x20\xb7\x50\x6f\x2e\xda\xa5\x94\x5e\x43\x71\xa3\xe4\xd7\x4e\x2c\x63\x4f\x94\xd8\xa8\x8e\xb6\xce\x9a\xcb\x6c\x54\x47\x6d\x54\x53\x3f\x8c\x8d\xea\x89\x8d\x6a\xd2\x83\x1b\x69\x83\xd5\xec\x9c\xc3\x35\xd3\xd6\x94\x19\x27\x33\x64\x33\x4d\x03\x65\x56\x09\x14\xf8\x35\x38\x72\x4e\x04\x8d\x9e\x93\xd6\x41\x16\x29\x3f\x29\x4a\x4b\x42\x4d\xa0\x28\xaa\xed\xa4\x07\x26\x39\xe0\xc0\x8c\x35\xd1\x13\xd3\x92\xa0\xcd\xc4\x11\xad\xc8\x23\x58\x2a\x24\xf9\x7f\xe1\xd4\xa0\x50\xf9\x14\x4e\xce\x2f\x51\x14\x74\x4a\xc7\x87\x3d\x97\xc4\xa3\xe8\xfc\xf0\x4f\xd2\xf3\x93\x00\xf7\x9e\xf0\x04\xe1\x74\x11\xd9\x6b\xc4\x29\x1d\xa4\x56\x6a\xbb\x8c\x14\x6a\x4a\xe3\xa3\xf4\x34\x3d\x4a\xcd\xd4\x76\x2d\x89\x81\xb6\xfb\xb7\x4f\x13\xb2\xdc\xb7\x39\x51\x02\x96\x49\xfe\x16\xc7\x8a\x79\x11\x8b\x41\x33\x78\xa6\xea\x49\xc3\x72\xe0\x03\x31\x30\x65\xc8\xa9\xaa\xfa\xc2\x54\x55\x03\x9d\xaa\xca\xda\x2a\xab\x6b\x49\x9a\x74\xea\xa3\x55\xe5\xae\xf4\x04\x83\x56\xff\x28\x75\xa7\xc3\x4c\x5d\x19\xae\x18\xa8\xc7\xb4\x47\x13\xb9\xef\x08\x61\xe0\x07\xf5\xa0\x1b\x90\x2c\xc3\x66\xcc\xa3\x04\x08\xb3\x8a\x34\xe0\xc1\x0f\x17\xe1\xbd\x55\x5d\x82\x24\x67\xad\x55\x61\xca\x0c\x4e\xb9\xc8\x6c\x52\x06\x48\x2e\x9c\x0f\x10\xd6\x0c\x43\xd9\x62\xf4\x41\x20\xb4\x6f\x03\xe2\x87\x79\x93\x9e\x3f\x6b\xf7\x73\xb7\xdd\xb8\xb1\x19\x6e\xd5\x02\xad\xec\x9c\x06\xad\xea\xc7\xaf\xec\xd4\xfe\xf4\x8b\xc3\xbb\xe1\x2d\xa5\x0b\xba\xaf\xbe\xf3\x47\x77\x2c\x59\x71\x18\xae\xcb\xbf\xac\x8d\x11\x0f\x3c\xf2\x53\xed\x1f\xdb\x66\x1a\x1e\x1f\xb0\x1e\xed\x2b\xcd\xc5\x6e\x16\xc2\x38\x36\x58\x04\xb0\x5a\xbf\x62\x48\x2a\x66\x1a\x13\x91\x39\x16\x43\x09\x45\x1b\x25\x75\xb0\x13\x51\x37\x22\xf0\x36\x48\xda\xcd\x20\x48\xb2\xea\x90\xb0\x0c\x9e\x99\x8c\x7b\x0b\x84\x80\x8d\xc0\xf7\x74\xf0\x52\xd9\xe2\xb4\xaf\xce\xe8\x3c\x63\x81\x53\x83\xcd\x14\xac\x04\x2f\x2b\x5d\xd1\x87\xee\x99\xf3\x74\x7c\xd2\xfb\x25\xcb\x60\x31\x36\x5f\xe0\x7b\x29\x0e\xfd\xa6\x6f\x81\xcc\xaf\x2c\x60\xcf\xab\x4e\x11\x7b\xae\xf2\x0e\xca\xf0\xf9\x6f\x21\xf4\x87\x46\x9d\x67\xcb\x31\xf9\x27\x41\xe1\x13\xac\x30\x00\xa6\xd6\xc2\x9a\xaf\x3d\x25\xe4\xfd\xbf\xbf\xfa\x12\xe4\xfd\xc9\xd0\xf6\xdf\x0a\x5f\x7f\x42\x44\xbd\x8e\xe7\x32\xde\x86\x71\x80\x11\xd0\x0c\x56\x7f\x6b\x14\x7d\xcb\x50\x28\xfa\xc4\xbf\x8f\xa2\x3f\x55\xe8\xfc\xbf\x01\x96\xff\x76\xf0\xf8\xb2\x9c\xad\xee\xdb\xe6\x6c\xb1\x42\xce\x56\xff\x3f\xca\xd9\x68\x87\xf3\xa4\xe9\x1a\x73\x2f\x55\x23\x3c\x51\xa6\xc6\xfb\x74\x85\xc2\xf2\x1c\xad\x03\x4c\x2b\xcd\xd1\x1a\x4a\x72\xb4\x4e\x9c\xa3\x55\x39\xf2\x6a\x0a\xc6\xd5\x2a\x1b\x4a\x2b\x98\x00\xd1\xdb\xa4\x19\x5a\x03\xca\xd0\x6a\x4e\x21\x43\x2b\x2f\xb7\xe9\x4b\x3c\x49\x72\x76\x55\x31\x1f\xdb\x42\x97\x3a\x74\x5e\xc6\x26\x0b\xb9\x18\x73\x50\x5f\x2f\x04\x1d\xfd\x47\x0c\xef\xf1\xbd\x20\x08\xfe\x45\x2b\xa8\x41\xa2\xd6\xa1\x5a\xcc\xfa\x64\x03\x2f\x24\x93\x49\xdc\x7d\x50\xc4\x64\x8e\x0d\xb8\x1c\xb6\xb8\xe2\x2f\x8a\x93\x90\x51\xfe\xa0\x03\x63\xb7\x68\xce\xa6\x30\xa4\xbf\x68\x12\xf3\x59\xde\xe4\x35\xc6\x55\xc1\x81\xe1\xae\x0e\xca\x06\x38\x60\x0a\x00\xfd\xb0\x9f\x38\x74\x5e\x54\x7c\x58\xab\xd3\xd0\x57\x64\xca\x75\x60\x0c\xac\x28\x2a\x52\x1f\xaf\x04\xc5\x2c\x1b\x64\x9c\x71\xc5\x27\x66\x39\x1f\xef\x8c\x67\xfd\xe8\x13\x7d\x1f\x40\xdf\xb3\x20\x6b\xb0\x4b\x3e\x02\x44\x66\x39\xf4\xb3\xbf\x54\xd3\x46\x15\x78\x49\x56\x2d\xae\x34\xc6\xee\x41\x52\x21\x2c\xe9\x9e\x71\x94\xb2\x9b\xf8\xc9\xb6\x55\xf0\xc5\x55\xb0\xf5\xa0\x7d\xfb\xf9\x4b\x2b\xd7\xc3\xc4\xba\x51\xda\x57\x7f\xf9\xcd\x07\xf6\xa8\x36\xfa\x56\xbe\xf7\xf8\x4b\xcc\x19\xdf\x44\x47\x8d\x5c\xbf\x76\x3b\xb3\xf8\xf8\x3d\x5a\xfe\xbf\x9e\xfe\x51\xd7\x28\xe5\xf8\x26\x72\x4f\x1f\xd0\x5c\xbc\x8f\x3f\x80\xbb\x1e\x5b\x09\xa3\x09\x66\x20\x25\xc3\x6c\x7a\xbe\x5b\xc2\xfe\x65\x76\x94\x8e\x00\x3c\x53\x0a\xca\x76\x88\x8a\xbf\x2f\x6b\x77\xf8\x31\xdf\x97\x1f\xe7\x7e\xfe\x72\xa2\xaf\x8c\x5d\xf4\x13\xce\x34\xf2\x43\x91\xe6\x4b\x31\xd0\x94\x37\xcb\x72\x66\x6f\x71\x88\x50\x6f\xf5\x00\x9e\x75\x76\xd6\xea\x63\x84\x49\xf8\xc8\xbf\xac\xc6\x79\x3f\x5d\xf0\xfd\x7d\x1f\x6a\xb3\xb5\xdf\x2f\xdd\xf3\x03\x68\xba\x7f\xe6\xc4\xcb\xf7\x24\x34\x97\x61\xf7\xb3\xd7\x5c\x78\xf8\x85\xbf\x69\x73\xb5\xbe\x73\x35\x2b\xeb\x4e\xff\x13\x26\xb7\xce\x9d\xf7\xbb\x5f\x03\x5d\x6b\x4e\x70\x19\x96\x03\x11\xf8\xc0\xe6\x21\x11\xec\x3a\x2f\x74\xf9\x04\x40\x01\x3b\x7a\x4a\x60\x74\x16\x64\x58\x8b\xa3\x85\xf2\x9b\x99\xf1\x8f\x74\x9b\x29\xb0\x1f\x05\x6c\x60\x08\x28\x39\xd4\x7b\x7b\xc3\x81\xc7\x61\x2b\x4c\xd5\x9e\xf5\xb3\xc9\x1b\x07\x81\xc5\x0d\x3d\xee\x7b\x76\xfa\x26\x3e\xa1\xe3\x4c\xb9\x65\x54\xb7\xfd\x07\x03\x11\xe2\x18\x1c\x4e\x49\xfc\x4f\xca\xbb\x1a\x3e\x01\xf4\x7b\x20\x97\x44\x09\x41\x6b\x8e\xe5\x18\x2f\xd6\x34\x13\xe5\x8c\xec\x0b\x11\xbc\x77\x46\x08\x04\x0b\x85\x8e\x93\x82\xb9\x0b\x8d\xce\xa1\xe0\xdb\x37\x52\x3b\x0c\x81\xd6\x16\xac\xd4\x12\xb8\xc7\xc7\x37\x18\xf6\x02\x11\x48\xc0\x07\xa2\x20\x81\x72\x7d\x00\x0a\xb3\x41\xb2\x25\xaf\x44\x12\x7a\xe1\x32\x91\x50\x1b\xad\x24\x1d\x61\xf1\x2c\xbb\x85\x34\xd0\xab\x61\x3c\x67\xc2\xbf\x65\x2d\xd5\x36\x3b\x1e\x1e\xc2\x59\x88\x9f\xd5\xd7\xfb\xb4\x60\x77\x7a\x43\x91\xba\x18\x46\xb3\xa3\xe4\xc4\xd2\x98\xc0\x4b\x15\x00\xca\x54\x3c\x21\x7c\x53\x46\x60\x5d\x87\x4e\xc6\x45\x9a\x36\xce\x30\x5b\x17\x8b\x08\x44\xee\x8f\xf2\x70\xa5\xb0\xee\x31\xbe\x4d\x98\xf7\x2b\x6e\xbb\xf2\x8a\xbb\xa6\xef\xd4\x0e\x57\x6a\xf1\xbd\xb0\xce\x00\xc7\xfb\xcd\xbc\x35\xde\x31\x66\xc4\x88\xc6\x54\xaa\xb1\xb1\x33\x5c\xbb\xa1\x11\xce\x39\xed\xe5\xd9\x7c\xd7\x88\xae\x2b\x6e\xfe\xde\xd2\xab\x26\x7c\xa5\xc1\x29\x5a\x2f\xdf\xfb\xcd\x03\xb0\xe3\x9c\xc7\xae\x5c\xca\x88\xcd\xc9\x64\x73\x73\x32\xf9\xa5\x3d\xb0\x2a\x61\x6e\xbd\xaa\x0e\x08\xb8\xb7\x73\xd0\xb8\x05\xf7\x76\x9a\xc0\x48\xd0\x05\xc6\xa3\xb3\x32\x14\x2a\x3c\x64\xca\x2b\x8d\x89\xdc\x08\x62\xa6\xce\x44\xae\x96\xfc\xd4\x95\x50\xcf\x40\x06\x9b\x30\xa0\xdd\x97\x6b\x26\xb6\x6b\x16\x51\xa2\x9b\x8b\xe1\xdf\xd4\x89\x25\x4d\xbf\x66\x49\xf5\x70\xe9\xb4\x92\x94\xc7\x9a\xac\x76\x7f\xa8\xb6\xd1\x96\x3e\x0d\x1d\x97\x98\x94\x33\x98\x2c\x67\x74\x95\xf6\x82\xd4\xce\x11\x92\xac\xc6\xc2\xe9\x53\x6c\x01\xd6\xa5\x4a\x8c\xea\x2c\x18\x95\x3d\x71\xab\x68\xd1\xc6\xab\xae\xb8\xeb\x8e\x6b\xae\xda\x78\xbf\x6e\xe1\x48\xec\xd6\x3a\x6c\xe1\x17\x86\xed\x08\x3e\xf8\xdd\x75\xdf\x5b\x72\xf9\x86\x75\xcb\x9a\xdb\xdb\x91\xa1\xa1\x68\xaf\xba\xa1\x11\x59\x1a\xe6\xf4\x5e\x92\x61\x39\xed\x0c\x9e\x76\x8a\xbd\x24\x74\x9f\xa1\xdb\x69\x98\x26\x52\xe1\x62\x3e\x71\x27\x49\xa1\x97\xf1\x50\xcd\xa4\xa2\x1e\x32\xed\x29\x09\x61\x5c\x11\x1e\x0f\xa6\x81\xe7\x4f\xd6\x53\x9a\x52\xd6\x53\x9a\xa0\xf7\x94\xa0\x32\x7d\xf8\x66\x52\x37\x6d\x26\xcd\x18\xdc\x4c\xca\xe1\x66\x12\xfa\xb9\x5b\x1e\x6b\x26\xad\xa4\x51\xa3\xc7\x4f\x20\xbd\xa4\x6c\xa8\x72\xcc\x58\x7c\x38\x06\xb7\x93\x26\xe0\x76\x52\x37\x16\xfc\x9b\x22\xc9\xff\x0b\x0d\x25\xdd\xb2\xec\xff\xa8\xab\xc4\x34\x50\xd3\xcf\x3e\xe5\xbe\x12\xdd\x18\xda\x5c\xc2\xfb\x73\x71\xff\x5e\x3e\x63\x58\x0e\xdc\xa0\x12\xd4\x81\x04\x58\x49\x71\x42\x61\x36\x8f\x55\xdb\xd4\x00\xab\xfb\x30\xdd\xbb\x47\x09\x40\x05\xfb\x2c\x0f\x2b\xc9\x19\xe8\xc2\x25\x83\xa8\xd4\x6b\x90\x7d\x55\xb1\xc6\x04\x41\x6d\xe7\x4c\x66\x6b\xbc\x89\xb0\x98\xca\x28\xec\x87\x2e\x22\xde\x92\xb5\xb3\x15\x04\xd1\x2f\x67\x4c\x16\x2b\xf6\x65\x63\x60\x5d\x07\xd1\x51\x4c\x79\x29\x15\x70\x4d\xcc\xe0\x74\x79\x21\x29\x39\x91\xfa\x53\xac\x60\xc3\x8b\x57\x5d\xf4\x2a\x5c\xf0\x71\xef\xea\x25\xf7\xaf\x98\xff\xaa\xf6\xf8\x07\xb9\x1b\xbf\xbb\xd7\xc8\xcc\x9e\x78\xde\x4d\x6f\x5d\xb3\x7c\x54\xcf\x8d\x6f\x5e\xcd\x6b\x9b\xa8\xa5\x42\xf7\x6f\x7e\x1f\x97\x9f\xa6\xad\x5f\xb1\xed\xd6\xb7\x70\x01\x6a\xf2\x26\xe6\xca\xea\x89\xcc\xd1\xf8\xd3\xda\x73\x5a\x67\x34\x03\xcf\x78\x7d\x26\x93\x2e\x1e\x5d\xc0\x81\x78\xff\x0e\xee\x52\x21\x0c\xdc\x20\x08\x6a\x41\x33\xb8\x9e\xda\xa6\xda\x98\xc7\xea\x2e\xaa\xcf\x48\xea\xb9\x45\xdb\xd4\x52\xf0\x4e\x43\x1b\x4e\x82\x4a\xcd\x53\x8b\xcc\xe3\x0d\x45\x49\x5d\xc9\x2e\x67\x4c\x66\x2b\xf6\xe9\xd5\x25\xc6\xf1\x49\x59\xd6\xee\xa9\x1d\xc2\x38\xed\x45\xe3\xb8\xa8\x71\x20\x71\x51\x95\x10\xc7\xdd\x05\xd3\xc4\x57\x76\x6f\x85\xf6\x7d\xeb\x17\x4e\xda\x36\xbb\x6b\x8b\xf6\xc5\xd3\xab\x2f\x5d\xf6\x1a\x5c\x16\xe9\x98\xb5\xba\xbb\xdb\xd2\xea\x3f\x73\xe5\x74\x56\xfb\x86\x9a\x46\xb8\xe7\xf2\x7b\xdf\x85\xd3\x9f\x1e\x39\xf7\x8a\x25\x97\x3f\xf8\x8e\xf6\x4c\xb6\x63\x23\x23\xc2\x57\x2a\xae\xf9\xb3\xd6\x67\x74\x5c\xf1\xc1\x06\x26\x51\xf2\x3e\x63\x5c\xc2\xed\x86\xe5\xc0\x00\x44\x8c\xdf\x99\x3e\x10\x97\x20\x15\x70\x09\xf6\x84\x52\x99\x54\xcd\x5c\x5e\xf1\xb7\x61\x1c\x0f\x1d\x5b\x8a\xd0\xb1\xa5\x2c\x13\x08\x11\xcd\x30\x28\xe1\x14\xbf\x88\x3e\x28\x5c\xd6\x4e\x0a\x43\x28\x7c\x51\x0a\x41\xd8\x09\x03\x75\xd3\x77\x4d\xde\xb8\x54\x47\x22\x24\x61\x20\x3a\x7d\xe7\xe4\x8d\x3a\x0a\xc1\xd0\xe3\xde\x75\xb7\x6f\xe2\x13\x5f\x4f\xa6\x68\x84\x35\xee\x07\xee\x47\x77\xb9\x8e\x45\x08\x03\x19\xcf\xa5\xb4\x81\x73\x86\xbe\xab\xea\x08\x41\x67\x22\xa9\xba\xb9\x52\x90\x5c\xd0\x91\x57\xdb\xf5\xe9\x0d\x32\xce\x54\x47\xc7\x99\xaa\x4e\x3c\xce\x54\x5c\xda\x80\x7c\x88\x7e\x3d\xf8\x3a\xd9\x45\x97\x79\x75\xf1\x56\xf9\x0b\x5d\xe8\x80\xa1\xa6\xa9\x74\xb9\xbf\x2a\x82\x10\x4c\x74\xc5\x14\x83\xc0\x65\x0c\x6b\x80\x41\x67\x78\x2e\xdf\x39\x6f\x61\xe7\x9c\x09\xd5\xcc\xe7\x33\x4e\xb3\x39\x9e\x1d\xeb\x34\x9a\xe2\x98\x6b\xa5\x2a\xa1\x18\x0f\x51\x91\x26\x74\xd6\x39\x18\xa7\xf3\xbe\x8a\xad\xfa\x90\x94\x13\xc9\x35\x2d\x26\x72\x36\x72\x45\x57\xa3\x37\xc0\x28\xc9\x2a\xf4\x92\x14\x9f\xaf\x08\x12\x9e\xfd\x0c\x63\x76\x92\xd0\xcd\x4b\x2a\xf5\x4e\x4a\x6e\xa3\xa3\x4f\x64\xcc\xf3\x6c\x88\x90\x68\x9d\xa5\xa7\xa0\x0c\x7f\x52\x9d\x82\xb3\x1e\xfc\xb1\xf0\xd4\x99\x67\xcf\x58\x24\xe5\xf4\x23\xa0\x6f\xbd\x10\x87\xb3\xb6\xdf\x54\x17\x1c\x77\x7a\xe7\xe4\x6f\x3a\xc8\xf6\xeb\xb3\x3a\x0f\x0b\x71\x20\x83\x30\x48\x80\xfb\x87\xde\xf5\x26\x53\x5e\xa9\xc4\x88\x8b\x4c\xa5\x1b\xd9\xa0\xd2\x69\x8a\xe3\x53\x4c\x6a\xcb\x35\x8e\x7c\xd6\x59\x03\x8c\xf1\x5c\x98\x58\xa3\x86\xc8\x55\x55\x90\x75\x23\xc7\x18\xae\x91\x64\x55\x8c\x62\x7f\xf7\xb4\x91\xb3\xda\xdd\xb6\x06\xe4\x0b\x95\x0a\x59\xb5\x98\xd0\xd2\x9b\xe8\x79\x89\x16\xce\x8b\x5a\xc9\x49\x32\x6e\x5d\x0f\x35\x06\x37\xc0\x24\x27\x9b\x83\x8b\x94\x9a\xe7\xa7\xc3\xcd\xc1\x71\x15\x25\x66\xea\x2d\x9b\x83\xc3\xb5\x2f\x6e\x97\x61\x39\xb0\x00\x17\x08\x81\xeb\x4a\xf8\x71\x8b\x92\xda\x04\x86\xc4\xb3\x79\x45\x4e\xa0\x9c\xd9\xce\xe5\x15\x4f\x5b\x99\x7e\xdb\x9e\xa3\x47\xca\x85\xb5\x4d\x1c\x11\xd6\xe6\x8e\x0d\xd0\x85\x21\xc2\xda\x64\x6c\x4e\x57\x2c\x4a\x96\xc4\x28\x85\x84\x26\x5a\x92\xd9\xb0\x6d\x7a\x90\x12\x99\xc9\x80\xce\xe3\xbd\xf4\x75\x81\xe7\xe9\xde\xa0\x10\xa2\xe8\xfe\x60\xa2\xfe\x52\x10\x3f\xd0\x25\x84\xb1\x2f\x6b\x04\x49\xf0\x3d\x8a\x47\x14\x0d\xb4\xd0\x55\xcf\xe7\x73\xe6\x1a\x0f\x67\x8b\xab\x66\x6b\x1e\xbd\x04\x23\x92\x6a\x80\xcb\x2b\x4d\x04\x98\x00\x0e\x91\x04\xa7\xd8\x51\xe8\x80\x71\xa2\x40\xea\xf3\xe3\x7e\xc2\x58\xb3\x85\x13\x3d\x81\x50\x55\x0d\xbe\x0d\x15\x83\x9c\x73\xba\x9a\x13\xad\xd8\xf5\x99\x45\x49\x56\x81\x33\x9d\xc6\x64\xf0\xba\xd3\xa8\x1d\x32\xb0\x28\xba\x0e\x3d\x80\x28\x7a\x8d\xc7\xa0\x3f\xa3\xbe\xaa\x65\xb4\xd7\x93\x0c\x46\x30\x3e\xf9\xbb\xff\xf8\xcb\x3a\x6a\x8a\x9f\x90\x48\xe1\x1e\xdd\x6b\xec\x7a\x1b\x9e\x93\x7d\xf4\xce\x5f\xbc\xe1\x76\xcd\x5f\x52\x37\xe2\xa3\x39\x7f\xe2\x47\x13\xcb\x7c\xd3\x87\x42\x03\x56\xa6\x06\x62\xe8\x19\x58\x03\x2c\xc0\x0f\x72\x27\x39\x01\xde\x84\x6a\xe7\xf3\x19\xaf\x1d\xbd\x32\x5e\xab\x29\x8e\x6b\xc0\x58\x7d\x04\xe5\x3f\x12\xc9\x7f\x5c\x30\x9e\x93\xc8\x8b\x12\xfc\x9f\x9f\x10\xd5\xe5\x97\xe4\x8c\xd9\x62\x4f\x63\x59\xc6\x0c\x6b\x20\xbc\x11\x5e\x28\xc9\xfa\x60\x7b\xf1\xfc\x94\xbf\x43\x83\x0f\x8f\x96\x2e\x7d\x6b\x8a\x07\xa7\xd4\x9b\x80\xc2\xfc\xeb\x24\x21\x0e\x2a\x40\x0c\x8c\x40\x99\x4e\xf9\xa9\x69\x41\xa7\xa6\xbe\x70\x6a\x6a\x13\x18\xe0\x5a\x1b\x40\x96\xa9\xf5\x99\xe2\x4a\x75\x41\x72\xc1\x66\xcb\x67\x7d\x36\xe4\x4c\x62\x05\x26\xdf\x26\x72\x94\x94\xca\x36\xc5\x20\x22\x27\x83\x1c\x6b\x38\x81\x47\x7c\x9a\x80\x24\xf7\x72\x16\xd1\x13\xa8\xad\x47\x81\xaa\x21\x5c\xb8\x82\x8a\x87\xa9\xa5\x9e\xe4\x3a\xb5\x1c\x2e\xd6\x9d\xe0\x50\x0d\xf4\x2b\x85\xd8\x74\xc8\x13\x05\xab\x4a\x0d\xb4\x99\x46\xa0\x83\xcf\x13\x67\x29\x1a\x8c\x86\x9b\x2c\xd1\x42\x2b\xf8\x93\x73\x4a\x26\x6b\x87\x77\x1e\xff\x93\x31\xdb\xc1\xee\xa2\x7c\xd4\x36\x38\xd0\x53\x94\x8d\xdb\x0e\xf4\x15\x6c\xff\x61\x00\x98\x0f\x85\x30\x30\x62\x95\xe3\x25\xa4\xff\xa1\x58\x93\x19\x33\xc4\xba\xaf\x8a\x90\x50\xe4\xa4\xca\x70\x44\xf7\xd7\x83\x15\xb2\x2c\xb6\x7c\xd6\x6a\x31\x1b\xe3\x44\x2b\x8b\xd4\x41\xbc\x43\x8d\xdf\x62\x42\x0b\x46\x48\xa7\x55\x0b\xba\x1a\x78\xce\x66\x47\x2e\x62\x44\x2b\xab\x3f\x7e\x00\x96\x84\x46\x0d\xf4\xe9\x1b\x3f\x83\xcd\x9f\x31\x74\x05\x82\x95\x3c\xf5\x57\x69\x3c\x8e\x6b\xd5\xdf\x63\x6c\xfb\x67\xe9\x7b\x7c\x7f\xa9\xe5\xff\xed\x97\xf6\x94\x76\x46\xf5\x5b\x25\x59\xe1\xb1\x12\xb9\xfe\xb2\xca\x2a\x7a\x57\x81\xea\xe5\xe9\xab\x5a\xb6\x77\xe5\xc7\xb2\x7c\xe3\x1e\x2d\x3d\x84\xa5\x9b\x36\xf0\x3d\x25\x33\xd2\x0d\x42\x1c\xb0\x40\xd6\x6b\x75\x25\x33\xd2\x8a\x23\xa1\x0a\x7c\x3e\xe3\x10\xd0\xea\x1d\x9c\x29\x8e\x39\x2f\x9d\x85\xc1\x69\x99\x81\xc6\x78\x8e\x23\x76\xe0\x74\x5d\x8b\xac\xc4\x01\x3b\x09\x7e\x08\xfb\x0d\x2d\xe8\x20\x33\x0d\xde\x57\x2c\xb5\x28\x38\xd0\x52\x1d\x10\xf3\x43\xd0\x81\xea\xf2\x25\xe2\x89\xea\x2f\x4a\x57\x86\xb6\x90\x7b\xaf\x74\x45\x1c\x9d\xa7\x5e\x8e\x35\x84\x50\x4e\xb2\x98\x4e\x1b\xfb\xf5\xbe\x44\x18\xa3\x45\x51\x6a\x2d\x72\x79\xa5\xae\xad\xd0\xa2\x11\x71\x8b\xa6\xb2\x04\x63\xe2\x2d\x8c\x1e\x57\x4a\x4f\x73\x16\xd1\x25\x47\x63\x71\xda\xf4\x6e\xc0\x73\x43\x61\xff\x70\x73\xd6\xfa\x29\x64\xcb\x90\x01\x85\xaf\x07\xc3\x03\x2a\xe8\x71\xe5\x8b\xc0\x00\xd8\x43\x4f\xed\x60\x70\x80\xa0\x87\xb2\xa0\x74\xee\x7a\x73\xf9\xbd\x3d\x1b\xcf\x5c\x7b\x40\x0d\x88\xa3\xb7\x91\xd8\x41\x9f\xba\xae\x36\x63\x3b\xd4\x13\x3b\xd4\xb6\xe9\x00\x13\xaa\x31\x5d\x59\x82\x23\xa9\x28\xb1\x43\x2f\x27\x5a\x5c\x72\x44\xcf\xc0\xa2\xb1\x06\x92\xa3\xf9\x87\x19\xc3\x2e\xbc\x8e\xb2\xbb\xd0\xe7\x2f\xb9\x96\x4b\x7b\xfd\xab\xa8\x05\xb6\xd3\x2e\xff\x8d\xfa\x75\x5c\x36\x8b\xdd\x41\x2f\xe2\x99\x6b\x48\x8b\x9f\xd5\x23\x78\x7d\x96\x7e\x0d\x9e\x33\x6f\x04\x1b\x86\x98\xa5\x57\x62\x09\xb5\x92\xcf\x67\x62\x95\xe8\x3c\xc7\x82\xa6\xb8\x12\x69\xd3\x05\x28\xe8\x80\x7d\x10\xc6\x73\x8d\xe4\x40\x37\x16\xc6\xed\x95\x5a\x14\xc1\x93\x8b\x06\xdf\x3e\x8d\x41\x49\x56\x25\x0b\xce\x5b\x33\x15\x95\x5c\xf9\xd8\xbd\x1a\xe3\xf0\xdc\xed\x49\xc6\xef\xcb\x0f\xf8\x09\xe7\xef\xd7\x95\x1e\xfc\x93\xcc\xdf\xb3\xe7\x96\xbe\x13\x2c\x3d\x0b\x71\x60\x03\x41\x50\x0f\xee\xa2\x76\xa9\xd2\x4f\x42\x94\x50\x15\x89\x7c\x3e\xe3\x13\x91\x5d\x7c\x76\x53\x5c\x71\xb7\xe9\xe2\xb9\x21\x5b\x3e\x6b\x0f\xa1\x0b\x38\x48\xcc\x12\x12\x71\x8e\x6a\xb0\xe5\xb3\x4e\x43\xc4\x18\x47\x39\x0f\xba\x80\x3d\x89\x9c\x93\x58\x08\xeb\x23\xd9\x25\x59\xb5\x54\xa5\xd3\x4a\x44\xca\x8a\x3e\x8e\x60\x0f\x88\x50\x82\x21\x9d\x56\x7d\x1c\x66\xae\x1a\x34\xb7\x3f\x30\x8e\x1f\x6e\x70\xdf\x5a\x6a\x91\x1d\x43\x62\x8d\x38\xa6\x24\x7a\x7f\xa1\x44\xfb\x09\x73\xc6\x61\x3c\x88\x0d\x57\xed\xeb\x41\x9f\x1e\xbb\xd9\x92\xc9\x42\xbb\xba\x8a\xf8\x8a\x28\x79\x47\xc2\x05\x8b\x50\x99\xbd\x00\x8c\xe3\xee\x75\xe3\x90\x62\x2d\x36\x51\xa9\xea\x43\xae\xee\x17\x58\xa6\xc5\x6a\xab\x72\xc6\xb3\x5e\xf4\x99\xb1\xda\xaa\x4a\xda\x36\xc8\x2c\x56\x2f\x51\xb7\xf4\x56\x15\xc9\x5b\x0a\x6f\x5d\x40\xea\x35\x9a\x45\xd9\x85\x87\x18\x15\x5e\xce\x9a\x6a\x6a\xeb\xc8\x34\x0f\xfa\x33\xbc\x85\x76\xc1\x8b\x52\x2d\x16\x58\x1e\x0a\xd7\xc5\x8b\x09\x74\x07\xec\x80\x97\x7d\xf6\x37\x5d\xbb\x65\x65\x37\x7d\xed\x7e\x3d\x63\xfd\xf6\x0b\x2e\x9d\xd2\x51\xc8\x0a\xde\x7c\xe5\xe1\x8f\x52\xc7\xef\x66\x5a\x8f\xbf\xad\x5f\xf6\xdf\xb8\xae\x59\x31\x6b\x16\xb3\xa7\x70\xe7\xe3\xfb\x63\xaf\x10\x06\x0e\x9c\x21\x74\x0f\xd2\x9c\xf3\xe0\x22\x87\x5c\x2c\x72\x10\xa0\x23\x3e\x40\x0e\x20\xc9\x19\x28\x4a\x65\x4d\x0a\x4b\x59\x93\xc2\xcb\xe2\x53\x60\x19\x1c\xaa\x44\xf1\xdc\xd5\x1b\xa3\xa2\x5d\xcd\xa9\x6b\x7f\x1a\x5d\x7a\x60\x60\xb0\xc2\xf5\xbc\xfd\xb1\x45\xfb\xa3\xf8\xf4\x8f\x35\xab\x7e\xed\x4f\x2c\xf8\x0a\xb2\xff\x6b\xf0\x3b\x11\x05\x9f\x0d\xb5\xfb\x51\x76\xb8\xf7\xa2\xae\xf4\x14\xd8\x61\xe1\xc5\x08\x92\xf1\x1b\x5e\xcc\x67\x9d\x7c\x78\xa8\x17\x23\x36\xdc\x51\x89\x96\x1d\x95\xa8\x33\x9e\x0d\xa1\xcf\x8c\xd5\x16\x2d\x39\x2a\x21\x74\x54\x42\xe4\xa8\x84\xa2\x85\xa3\x82\x5e\x35\xc5\x92\x56\xc2\x52\xd6\x2c\xfa\x8c\x28\xea\xe5\x3d\xf8\x26\x05\x6a\x54\x3f\x22\xaa\x8f\xa1\x2f\x5c\xd9\x51\x61\x9d\x43\x05\xb8\x75\xf1\x41\xe7\x64\x4a\xe9\xfb\x36\x9f\x1c\x96\xb2\x43\x52\x1a\x5c\x1c\x67\xd0\x41\xa1\xf1\xc5\x1f\x84\x38\x70\x80\x4a\x70\xc7\xa0\xd3\x11\x48\xa8\x32\x9f\xcf\x04\x30\x47\x67\x40\x34\xc5\xb1\xd4\x5a\x55\x42\x11\x0f\xe5\x2a\x49\x28\xe1\xa8\x14\x8b\xd4\x2c\x0e\x14\xf3\x63\xb1\xbf\x9c\xbb\x58\x43\x71\x88\x84\x0b\xb8\xa2\x12\x4b\x12\x5a\x64\x06\xbd\x27\x6e\x29\x23\x98\x8c\x83\xce\x96\x12\x90\x70\x29\x6d\xd0\x09\x1b\x18\x6d\x94\x1f\xaf\xae\xf2\xc0\xa3\x78\xb4\xca\x02\x10\x96\x72\x82\x2c\xc7\x11\x7c\x1d\xd8\x3d\xe4\x54\x69\x20\xa1\x44\x92\xaa\x97\xcb\x2b\x55\x6d\x3a\x24\x62\x58\x8a\x90\xfa\x53\x19\x18\x35\xb0\x92\xac\xba\x3d\xa4\x9a\x64\x22\xec\xf9\x36\x79\x9f\xd7\xe7\x27\x48\x36\xc5\x2e\xa9\x35\x91\x6f\xc3\x14\x32\xf0\x75\x1b\x66\x5c\x54\x1c\xf8\xd6\x0d\xc3\x18\xb2\x75\xe0\xfb\x57\xe4\x0c\x41\xde\x77\xf3\x10\xac\x21\x4a\x08\x7b\x5e\x5f\x99\xe7\x45\x77\x4e\x05\x32\x93\xc2\x26\xf1\xd0\x23\xd7\x56\x42\x24\x82\xef\x1d\x14\xad\x28\x98\x0e\x47\x71\xa5\x15\x9f\xac\x9a\x42\x69\xdc\x34\x14\x25\x39\x10\xac\x0e\xd7\x91\xf2\x72\xd6\x51\x53\x4b\xe1\x70\xdf\x66\x22\xd4\x39\xc8\x22\x43\x4f\x81\x3e\x36\xc8\x20\x43\x71\x8a\xac\x1e\x90\x3b\xe9\x5c\x32\x6b\x80\x0b\x44\x40\x76\xc8\x53\x53\x9d\x50\xbd\x7c\x3e\x53\xed\x45\xef\x4a\xb5\xdb\x44\x46\x3f\x6a\x87\x9f\x49\x8e\x10\xa7\x14\x29\x9c\x25\xcc\xfa\x46\x3b\xad\x6a\xf4\xdf\x23\x76\x08\x45\x24\x22\x2b\x41\x0f\x90\x52\x2d\x61\xb8\xd9\xd0\xc7\xa8\xfc\x9d\x1a\x8e\x71\xa6\xf4\xd5\x1a\x66\xce\x78\xc1\xc0\xbc\x85\x9c\x9f\x38\xf0\x80\x28\x78\x7c\xa8\xd3\x53\x93\x50\x7d\x7c\x3e\x53\xe3\x43\xe6\xaa\xf1\x9a\xe2\x4a\x65\xc1\x73\x97\x4f\x18\x73\xa2\x12\x45\x86\xf1\x12\x7b\x79\x13\xb9\x28\xf9\xa9\x78\xb0\xb2\x55\x78\x9a\x3b\x58\x70\xe2\xd4\x22\xae\x74\x5a\xb5\x45\x25\x39\x27\x4a\xb2\x0f\xcf\x1d\xdb\xab\xa8\xbc\x4c\xe9\xa9\x52\x6a\x24\x25\x78\x82\x69\xe3\x72\x33\x0d\x33\x5e\xec\x29\x33\xd3\x50\x33\xc5\xdd\x65\x46\x62\x40\x83\x36\x8a\x9b\xc3\xbf\x81\x11\x6b\x4b\xe8\x74\x14\xcb\xe6\x33\x12\x43\x94\x9f\x71\xea\x63\x3b\xa4\xfa\x44\x3c\x3c\x2c\xc0\xb8\x5a\x45\x53\x1f\x1f\x9e\x3a\x61\x6b\x62\xb8\x22\x27\x48\x6a\x7d\x43\x3a\xad\x54\xc9\x19\xc9\x43\x30\x05\x6c\x0d\xd9\x7e\x8f\x94\x85\x36\x17\xae\xe9\xd3\xdb\x25\x25\x91\x36\x70\x0b\xc4\x6c\xdc\x45\xc1\x08\xb7\xcb\xe3\xad\x84\x6e\x17\x17\xa9\x61\xf5\xee\x70\xa4\xe1\x85\xc7\xae\xba\x29\xd0\xb6\x68\xf3\x55\x37\x7e\x72\xef\x7b\xb9\x65\xbb\x6e\xf9\xce\xd2\xae\xe5\xab\xae\xd7\x7e\x7b\xfc\x0f\x7e\xdf\xd9\x4e\xe8\x0f\xaf\x99\x98\x9b\x04\xe5\xef\x9e\x33\x25\x3e\x6e\xe4\x94\x45\x2f\x5e\xb5\xee\x8d\xab\x17\xe5\xa7\xcc\x9b\x72\xc6\xfc\xa9\x33\x5f\x58\x77\xf0\x73\x6d\x69\xf2\x85\xb4\x6b\xf4\x13\xd3\xd1\x9a\xbd\xda\x28\xf6\x11\x6e\x39\xa8\x01\x4d\x60\x29\x20\x72\x9e\xac\xae\xc2\xe6\x12\xf2\x50\x69\xc6\xb4\xe3\x14\x91\x87\xd6\x1c\x72\xe4\xd5\x16\x94\xee\x59\x25\x39\x67\x62\xab\xeb\xe2\x74\xcd\xb1\xfa\x74\x5a\x09\xc9\x59\x87\xec\xf2\x13\x4f\x51\x4d\x16\xed\x92\xb2\xd0\x2a\x87\xa8\x0e\x1b\x4a\xcd\x53\x1d\xb4\xf7\x4d\x18\xc8\x07\x2e\x19\x7b\x90\xc2\x9a\xbd\x0f\xed\x9e\x79\xe9\x94\x9e\x55\x0b\xff\x70\xe0\xb5\xdd\x8b\xee\xb8\x2e\x3d\x69\xec\xdc\xd5\x57\x1c\xfb\xe3\xe5\xdf\x17\x0b\x2b\x6e\xfe\x72\xde\xb8\x91\xf1\x09\xed\x13\x36\x2e\xd8\xfb\x8b\x0b\x0e\xcf\x4e\xc6\x63\xa3\x9a\xc7\xdc\xb3\xf0\xd9\xd7\x2a\xb5\x69\x25\xeb\x5d\xab\x8d\xc2\x7a\x49\x26\x20\x81\xd9\xe4\x3d\x50\x1c\xc9\x8c\x45\x57\xc2\xb2\x4b\x54\x09\x4b\xc4\x28\xa3\x41\xda\x57\x18\x51\x45\xd0\x55\xac\x6a\x97\x48\xcd\x10\x4b\x70\x1a\x39\x8c\x9a\x29\x3e\x36\xd6\x47\x62\xc3\xce\xb5\x85\x87\x6c\xa0\xda\x48\xda\xdb\x9a\x36\x87\x3e\x94\xb0\x0a\x32\x44\x07\x0b\x9f\xc1\x91\xda\x28\xac\x51\x66\x02\x35\x60\xeb\xd0\x2a\x58\x19\x07\xbe\xfe\x1d\x36\x53\x3c\x63\xc5\x60\x99\xe1\xe4\xb0\x06\xe9\x94\x39\x03\xc7\x78\x45\xee\x63\x81\xea\xc4\x3a\x65\x32\xd5\x29\x73\x57\xa1\x48\xc0\x62\x35\x12\x05\xe0\x01\xa2\x56\x68\xd3\x2c\xe9\xd2\xa5\x0d\x10\x2c\x2b\x88\x59\x8d\x2c\x2c\xb5\xae\x4c\xb0\x4c\x57\xb3\x2a\xac\x9a\x1f\x5d\xa2\x57\x56\xaa\x67\xd5\xd0\x7f\x84\x53\xf8\x37\x40\x0c\xbd\x81\x51\x7c\x1a\x4d\xf9\x8c\x97\x21\x92\x19\x39\x8b\x39\xea\xb5\xc5\x55\x8b\x89\x00\xd0\x85\x43\x6a\x0d\xca\x42\xab\x0f\x49\x6a\x80\x22\xd1\xed\x82\xa4\xeb\x00\xb2\x51\x72\xfe\xcc\x92\x0a\x6b\xd2\x69\xc5\x22\xab\xa1\x2a\x5c\xd7\x55\x9d\x01\x5d\x28\xa7\xf8\x06\xd6\xc5\x61\x0a\x93\xfb\x47\x6a\x88\x12\x02\x3e\x8a\x06\x37\x7e\x09\xc3\x35\x75\x0d\xbd\xef\xed\x7d\x72\xc7\x63\x5b\x92\x6b\xe1\xda\x0b\x7a\xf6\x3e\xb7\x6c\xeb\xd7\xf7\xaf\x7e\x75\xd9\xfb\xaf\x6c\xfd\x91\xf6\x9c\x76\xe0\xf6\xb7\x47\x41\xc3\xa2\x55\xcb\xcf\x3f\xf7\xe8\xaf\xba\x67\xad\x3e\x38\x7f\xf2\xdc\x5d\x0b\x9f\x78\xde\x66\x94\x1e\x5f\xff\xc1\xd1\x5a\xa2\xa3\xb1\x51\x73\x61\xae\x82\x7a\x70\x25\xc8\xf8\xf0\xa6\x9a\xf3\x4a\x5d\x42\x65\xcd\x79\xc5\x9c\x50\x2d\x86\x02\x18\xbd\xc6\x91\x57\x6a\x44\x25\x88\x16\x87\x67\x9d\x12\x6a\x90\xde\xd9\x0e\x41\x92\x33\x3e\x2a\x53\xc1\xd6\x49\xb2\x52\x8f\x57\x09\xe8\x2a\xd1\x3f\x41\xbb\xe7\x0e\xa6\xd1\x95\xae\x78\x06\x80\xd5\x0b\xb8\x13\x5d\xf1\x41\xe4\x0d\x44\xc3\x22\x52\x13\x5b\x35\xed\xcd\x45\x7b\xf7\xef\x7d\x7c\x4d\xeb\xd6\x5f\xbf\xbc\x74\x51\xd7\x53\xb3\x26\x5f\xff\xd1\x6d\xfb\x3e\xd4\xb6\x31\xab\xd7\xed\xd0\xde\x7b\xfd\xe8\xee\xfb\x9a\xda\x1f\xbd\xeb\xea\x4b\x3f\xbd\xf1\xa6\x09\x13\xa3\x91\x3f\xb4\x37\xff\xe2\x21\xed\xa5\xf9\xd6\xc8\x13\x37\xec\xf9\xe7\xf7\x66\x96\xce\xae\x59\x80\x0f\xbc\x4c\xe3\x58\x83\xd1\x92\xa4\xa8\x36\x0a\x92\xcc\xb1\x66\xac\xed\x69\x2a\x82\x23\x09\xd0\xcd\xe2\xc8\x2b\x96\x32\x70\x24\x15\xa3\x43\x97\x0c\x6f\xc1\xe8\xc8\x02\xfc\x6d\x20\x24\x52\xb1\x88\x59\xd6\xc2\x38\xe3\x8a\x51\xcc\x72\x46\xde\x19\xcf\x9a\xd0\x27\xfa\xde\x8c\xbe\x67\x51\x70\x6b\xd6\x2b\xfe\x8c\x45\x92\x55\x9b\x9d\x90\xd9\x3a\x2a\xd2\xb8\x5e\x25\x79\xd3\xc8\xa7\x65\x9c\xae\x22\x1a\x8e\x0d\x3b\xb1\x56\x0e\x5b\xce\xb7\x48\x31\x8f\x87\x57\xc1\x56\xed\x0d\xed\xad\x5b\xb5\x86\x5b\x41\x7f\x29\xeb\x22\x01\x3d\x7e\x35\x85\x59\x79\x7c\x93\x41\x2e\x65\x5d\x24\x58\xb8\xbf\x19\x76\xe1\x39\x8b\x8f\xa9\x9d\x1c\xa2\x2f\x99\x4c\xea\xc3\x6e\xf5\xa5\x84\x15\xc3\x6a\x03\x37\x14\xc2\x93\xe7\x4b\x12\x25\x9f\x88\xd9\x67\x0b\xf0\xb8\x12\xef\xa5\xf8\xc4\x2c\xeb\x63\x9c\xf1\x2c\x87\x3f\x2b\xd0\x67\xa6\xc2\x57\x3e\x1c\xa7\x70\x69\x90\xb3\x4b\x15\x2c\x47\xc5\xc0\x20\x53\xfc\x8d\x06\x3b\xa2\x4f\x92\x73\xbc\xe0\x0f\x12\x41\x51\x49\x75\x57\x62\x9f\xa1\x9a\x6a\x31\xae\x4e\xa9\xd6\x87\x07\xdd\x24\x99\xb2\xc3\x02\x8c\xb2\x1c\x51\x37\x68\x98\x2e\xd6\x38\xce\x38\xfa\x81\x8b\xcb\xb0\x75\xcb\xcb\xc7\xe9\xf6\xbd\xf8\x9b\xe9\xe7\x0f\xc0\xd8\x95\x8d\xd4\x41\xd0\xa1\xb9\xf8\xfb\xf8\x03\xc0\x5b\xa8\xd8\x7a\xe9\x29\x34\xe8\xe0\x26\x7b\x42\x17\x96\xa5\x17\x9d\x9d\x50\x90\xa3\x84\x55\x82\x71\xd5\x3c\x9c\xc6\x2c\xe5\x4e\x06\x8a\xa7\x05\xaa\xd0\x43\x4d\x62\xf7\x4a\x72\x86\x61\x39\x9c\x4f\x48\xaa\xc1\x89\x19\x92\x29\x98\x54\x22\x19\x3b\x0c\x17\xad\x00\xc3\x10\x5b\x81\x31\x60\x04\x2d\xf0\x1b\xaf\x7e\x77\xf5\x8f\x0e\x39\xb5\x83\xda\x01\x98\x10\x33\x5b\x8f\x36\xef\xe0\x7b\xff\xf3\xce\x6b\x7f\xfb\xd3\x31\xf3\xbf\x5a\xcc\xdf\x3a\x29\x9d\xd1\x3e\x3a\x7c\xbc\x01\x50\xcd\x69\xee\x2b\xc1\x05\x6a\x41\x1b\x58\x07\x48\x91\x2a\x61\xc2\xfd\x33\x99\xc2\xea\x09\xca\x20\xea\xc8\x2b\x51\x51\xf5\xc3\xb8\x8e\x24\xd5\x11\xf6\xed\x30\x8e\x33\x5f\xa5\x26\xad\xf8\x25\x95\xab\xc7\x6d\xf5\x7d\x66\x6f\x65\x55\x53\x02\xc5\x69\x36\xab\x24\x67\x64\xf2\x32\xa8\x32\x95\x22\x4a\x48\x39\x11\xb8\xfc\x54\x45\x58\x35\x18\x87\xc0\xdb\x97\xdf\x10\x9d\x43\x22\x99\x06\x80\xee\x77\xdb\x66\x8d\x6c\x9d\x7a\xd5\xb6\x87\x6d\x35\x0d\xc6\xb3\x36\xcf\xdc\xfc\x28\x6c\x3d\x73\xfc\xa4\x15\xd3\x31\xfc\xbe\x1c\x6e\x7f\xc7\x88\xea\x6e\xe7\x5f\xaa\x6e\xbf\xb1\xbd\x7d\xdb\xf7\x2e\xea\x3e\xfc\xe6\xdc\xb9\x37\x1f\x5b\x39\x73\x21\xe5\x5e\x05\x33\xfa\x5f\x12\x00\xdf\x0b\x2a\x41\x23\x58\x0b\xf0\x86\x2b\x12\x26\xd6\xae\xb1\xe4\x95\xfa\x84\x6a\xb7\x10\x45\x5d\x0e\x3b\x9d\x6c\x95\x85\x43\xe9\xb3\x88\xd3\xe7\x2a\x11\x7b\xa1\x28\x0a\xf0\x44\x2a\xb1\xcb\xe1\x46\x98\x62\xc1\xba\xad\x51\x39\x67\xb4\x07\x89\xca\xae\x4f\x52\x25\x8f\xae\xc2\xad\xfa\x00\xa1\x0d\x60\x3c\xd8\x9f\x10\x71\x26\x31\x5a\xd7\xd1\xde\x99\x0a\x93\x79\xae\x6a\x67\x2a\x6c\xb0\x43\xe4\x78\x45\x10\xae\xae\x8d\x96\xe0\x01\x67\xc0\x15\xdb\xf9\x46\xd8\x5c\x6d\xb9\xe9\x5a\x18\x3c\x3d\x0c\x93\xe1\xc8\x03\xd7\x2e\xea\xd1\x6e\xd5\xbe\xaf\xe5\xb5\xb7\x61\xfa\x81\x07\x7f\xf1\xf2\x5d\xf7\xff\xec\x20\x7c\x00\xde\x70\xe7\x9c\x27\xfd\x1d\xaf\x3c\x71\x86\xe7\xbc\x0b\x61\x60\xe7\xce\x47\x0f\xb4\x9f\xfe\xe8\x32\xed\x90\xf6\xe2\xb1\x23\x97\xdd\xd0\xbb\xe7\xe2\x15\x19\x6c\x8b\xd9\xfd\x47\xf8\x24\xd6\x5a\x6c\x04\xbf\xa2\xf3\x07\x61\x33\x2e\xf2\xda\xcd\x79\xc5\x98\x50\x65\x67\x32\x89\xad\xc1\x63\xad\xb6\x6c\xa5\x95\x2f\x16\x13\x2a\x6d\x78\xc8\xb8\x96\x72\x8e\x37\x0d\x00\x1f\xcb\x2d\x76\x45\xea\xe3\x55\xa7\xfb\x98\x5d\x71\xf7\x29\x6e\x31\xeb\x72\x3b\x9d\xf1\x8c\xcb\xed\x2c\x91\x16\x54\x25\xac\x31\x29\xc9\x4e\x57\xc1\x83\x54\xf2\x92\xac\x18\x31\x06\x97\x0d\x84\x31\xb8\x49\xce\x98\xec\x31\xf4\x53\x85\xa4\x78\xd2\x40\x8d\x85\x25\x59\x05\x15\xc4\xa8\x2c\x32\xaa\x51\x56\x78\x2a\xd0\x47\xac\x6a\x20\x89\xc2\x18\x18\x36\x30\x06\xa2\x13\x54\x6a\x53\x3b\x9c\xfd\x7c\xee\x0e\x43\x12\xc6\xe3\xee\xbb\xce\x5f\x5a\x13\x87\x89\xf8\xa4\xff\xda\xaf\xe5\xb4\xf7\x7f\xa3\xf5\xc3\xc4\xa2\x9e\x9b\x1e\xef\x99\x3b\x7f\xf3\x34\xb8\xe7\x45\xe8\x1c\x77\xd9\xde\xc0\xe9\x7f\x7f\x7d\x41\xe7\xfd\xeb\xf6\xbc\xf9\xa6\xf6\xd3\xf3\x97\x1d\xd5\xfe\x53\x7b\xf5\xbf\x0e\x2c\xbc\xec\xf0\x53\xe7\x2f\x5e\xbc\x0f\xc0\xfe\x97\xb4\x06\xac\xc3\xe6\x06\xe3\x40\xc6\x0d\x88\xfc\x1a\xa9\x9d\xa3\xdb\xcc\x9a\x50\x25\x01\xeb\x6f\xaa\x5e\x18\x07\xaa\x64\xc5\x43\x1b\x8a\x5b\x52\x1c\xf8\x4c\xc0\x34\x4e\x8b\xf0\x00\x47\xa4\x30\x6a\x54\x10\x7f\xed\x1c\x03\xcf\x28\x1b\x30\x9a\x15\xbd\x67\xe3\xfc\xd3\xe3\xa9\xb6\x94\x3d\xa4\x8f\x15\x69\xab\xb3\xdf\x0f\xbc\xeb\x1c\x75\xfa\x7a\xaa\xc7\xa6\x35\x60\x3d\x36\x17\x7a\x26\x3c\x97\x60\xd0\x47\x6c\x58\x63\xf1\x99\xdc\x09\xd5\x53\xfa\x4c\xae\xe1\x9e\x29\x55\xfe\x4c\x63\x60\xa2\x6c\xf8\x65\x46\xec\xee\x5b\xd1\x23\x5d\x50\x11\xa2\x83\x2e\xda\xf6\x7d\x0f\x05\xde\x75\xae\xc4\xcf\xc3\x52\x7c\xd7\xa5\x94\xc7\xe8\xa2\x13\x71\x18\xa9\x4e\x8e\x4c\xae\x89\x58\x15\x4a\xf1\x0c\xe6\x2a\x0a\xa2\x4c\x52\x24\xa4\x33\x58\xe3\xde\x23\xa9\x8c\xf3\x84\xf4\x44\xce\x93\xf1\x11\x49\x3a\xc1\xf9\x40\x06\xa2\x77\x75\x56\xf3\x22\xce\xc7\x45\x79\x87\x16\x9f\x08\x89\xac\xd6\x72\x85\xf1\xe3\x52\x92\x21\x42\xbc\x80\x41\xc6\xaa\xe8\x21\x93\xd8\x9c\xd1\x6a\xb7\x85\x48\xb6\x14\xa2\x00\x1e\xcf\x89\x01\x5f\xc3\x02\x8a\x4f\x0c\x1c\xfe\x0d\x5d\xe6\xb0\x20\xe1\x0b\xe9\x72\x19\x74\x5f\x72\xbb\xb0\x4e\x4f\x08\xec\xa2\x3b\xe6\x4a\x92\x2e\x88\x99\xcd\x2b\xa6\xb6\x02\x5c\x43\x09\x24\x72\x76\x0c\xb7\x2e\x01\x6e\xe0\x49\x35\xf1\x50\xae\x82\x50\xea\xfc\x2f\xe0\x76\xd4\x0a\x91\x16\xea\x80\x0a\xec\x92\xac\x5a\x2b\xd2\x03\xb1\x18\x1e\xa2\x68\x95\x4a\x1a\x88\x39\x62\x43\x60\x79\xe6\x8e\x19\x7d\xe9\xe8\xb3\x16\xfe\x3c\xb6\x65\xcf\xfd\x73\xba\x8a\x78\x0c\xed\x1d\xef\xac\x9a\x66\xd3\x8e\xee\xd6\x75\xd7\xde\xe4\xd5\x67\xcd\xbb\x30\xa7\x58\x23\x48\x82\x1f\x11\x3c\x46\x2e\x5c\x32\x29\xdc\xca\xa3\xfb\x23\x17\x20\xab\x37\xc7\x75\x70\xc6\x00\x14\x4f\x08\xc6\x73\x51\x42\xc6\x16\x15\x71\xad\xa0\x14\xd3\x93\xf5\x05\xaa\xf1\xed\x11\x92\x32\x96\x70\x1c\xc3\x5e\xe5\xac\x47\xc4\x1c\x82\x4a\x42\x52\xb9\x56\x12\x8f\x12\x40\x86\x27\x80\xfe\x95\xea\x08\x8a\xb4\x54\x33\x76\x89\xae\x74\x5a\x6d\x8d\x9f\x14\xea\x33\xc8\x3a\xce\x13\x03\x33\x36\x94\x59\xea\xc0\xb0\xc0\x0c\x8d\x2f\xb5\x1c\xb7\x80\x20\x81\x79\xd2\x5b\x34\x36\xe0\xde\x62\x1d\x68\x04\x1d\xe0\xa6\xa1\xfa\x8b\xd1\x84\xd2\x4e\x78\xed\x5a\xda\xd0\x3d\x54\x6f\x25\xc3\x62\x65\xed\x45\xb5\xc6\x86\x32\x21\xbd\xb7\x98\x6d\x35\xb8\x8d\x71\x35\x6e\xcb\x2b\xf1\x84\xda\x6a\x23\x33\x65\x35\x41\x49\xce\x59\x2a\xa4\x58\x3d\x21\x6d\xc2\x02\x84\xdf\x96\xd7\x7b\x78\x0a\xb3\x13\xf5\x18\xf7\x0e\xc9\xcb\x75\xb2\x66\xe3\x4f\x86\x20\x36\x23\xbc\x66\x4b\x84\xc3\xc0\x06\x7c\xa0\x16\xd4\x83\x24\xb8\x9e\xda\x4b\x34\xe7\x33\x21\x14\xb6\x34\x25\xd5\x88\x39\xaf\xb4\xb5\x91\xf3\xe7\x31\x23\xf3\xa9\x75\xc5\x13\x47\x65\xd4\x50\x78\x47\xa6\xd5\xf1\x80\x94\xc1\x96\x57\x1a\x90\x1f\x4d\xd0\x73\x57\xed\x47\x96\xf2\x88\x51\x5c\xd9\x6d\x20\x96\xf2\x88\xc3\x34\xa4\xa3\xa5\xe3\xe6\xc3\x13\x98\x95\xb5\x1a\x13\x85\xb9\xf3\xa1\x99\xcb\x4a\x7b\x8e\x2f\xd1\x36\x23\x5b\x31\x84\x5d\xb8\xb2\x73\xd4\x0a\x3a\x74\x8e\x83\xf2\x53\xd4\x92\xd0\xf5\xee\xeb\xda\xb2\xb5\x55\x2d\xc6\x78\xae\x41\x67\xfb\x51\xda\x12\x6a\x72\xd0\xa9\xd2\x8f\x52\x1d\x3a\x4a\xfa\x08\x48\x8a\x52\xc4\xf7\x72\x96\x60\x6d\x43\x5b\x12\xbd\x64\x31\x94\x5c\x77\xe0\xea\x78\xfb\x29\x1c\x28\x5c\x3d\x60\x92\x6d\xa9\xa4\x10\xa9\x69\x61\x70\x7e\x33\x24\xcb\x41\xc9\x71\xda\x51\x71\xd3\x9c\xc4\xd4\xb1\xa9\xc0\x98\xf0\xba\x74\xae\x79\xf2\xe8\x8e\x40\x2c\x69\x19\x15\x63\x6e\x8f\x9d\xb4\x81\x7d\xcd\x0d\xc1\x48\x70\xfe\x91\x60\x4d\xb0\x23\x0a\xc7\x3e\xf7\x9c\x3e\x2b\xc1\x2d\x14\x0e\x01\x1b\x88\x80\x04\x48\x22\x5f\x8e\x6d\x57\x67\x26\x35\x4d\xa5\x22\x99\xab\xc6\x76\xca\x7a\xa4\x6a\x63\x9c\xfa\x32\xc5\x4e\x4f\x58\x93\x39\xaf\x8c\x48\xa8\xad\xc5\x13\x86\x29\xb6\x45\x5c\x82\x30\xd8\xf2\x59\x9f\xa1\xd1\xa8\xa3\x54\x95\x8a\x44\xce\x47\xec\x88\x0e\x59\x2d\x20\x81\x45\xa3\xf4\x34\x67\x71\x55\x46\xa4\x11\xad\x14\xad\xea\x09\x60\x5c\xba\x92\x4c\x03\xb5\xa9\x6e\x38\x36\xfa\xa1\x0c\x78\x22\xe2\x03\x68\x1e\xd2\x7a\x0b\xf5\x93\x18\x45\x66\x2c\x6f\x76\xc3\x52\xa3\x7d\xf3\x22\x3d\x87\x1c\x7c\xee\xb9\x02\x36\xe2\x52\xea\xbf\x2e\x1b\xda\x77\xa9\x55\xe8\xa6\x8f\x0d\x75\xb0\x6a\xb0\x8f\x0a\x8a\x79\x9c\x6a\x90\xf9\x5d\xda\xe2\x97\xd2\x28\x06\xcc\x72\x15\x55\xa4\x9f\xf2\x2d\xcf\x14\xfc\x96\x5e\x09\x7e\x8f\xde\xf4\x27\x3b\x34\x7f\x1a\x18\xdf\xcc\x16\x5c\xd4\xff\x5c\x56\xe2\x7b\x0a\xce\x26\x92\x50\x43\x5c\xbe\x40\x00\x46\x9c\x0d\xf5\x30\xd9\x6a\x83\xcb\x18\x57\xfd\x62\x5e\xf1\x27\xd4\x6a\x42\x0e\xa6\xfa\xf1\x7a\xc5\x34\xae\x00\x73\x9e\x50\x04\xaf\xf7\x54\x5d\xcd\x30\xbe\xe5\x80\x1e\xd0\x0c\xe9\x4d\xa6\x17\x16\x57\xee\x43\xaa\x40\x3d\x58\x31\x0c\xd2\x05\x79\xd7\x60\x42\x0d\x59\xf3\x7a\xfb\x8c\x6e\x6a\x75\xd9\x1d\xae\x2b\x4a\xa0\xb7\xa0\xda\x2e\xc9\x59\x8b\x84\x45\x56\x95\xa8\xa4\x56\x70\xe9\xb4\x6a\x70\x17\x2a\x90\xdf\xd6\x5f\x94\xb1\x22\x9e\x68\x77\xff\x59\x42\x8e\x78\x32\x59\x89\xfb\x06\x70\x25\xae\xa5\xf7\x4b\x08\xc4\xc0\xaa\x92\x1d\x0e\x33\xd4\x29\x14\xb6\xda\x9f\x50\x03\xd6\x82\xca\xc4\x80\xad\xae\x45\x5b\x9d\xab\x24\xf6\xa8\x4c\xe4\x6a\x49\x98\xd7\x00\xe3\x6a\x25\x36\x87\xe8\xc7\x84\x90\x78\xcf\xc3\x75\xa7\xb0\xe7\xe5\x94\x89\x43\x6f\xfb\x84\x32\xae\xc4\xa1\xf6\x9e\x63\x0a\x44\x89\x0c\x78\x06\x00\x7e\x8c\xa0\x61\x8c\xe5\xf5\x20\x63\x40\xb1\xac\x90\xc4\xe2\xea\x0a\x9b\x54\x4c\x78\x32\x01\x2a\x36\x4c\x66\x22\xd8\xf2\x8a\x20\x2a\x10\xdd\x96\xb4\x04\x00\xc5\xbc\x6a\x1f\xa8\x58\x8e\xc9\x33\x08\x91\xc6\x20\x0a\x0d\x68\x90\x64\xd5\x64\xc6\x91\xaa\x41\x92\x15\x86\xc8\xae\x63\xb5\xf2\x00\x4c\x85\x0d\xcf\xc0\x91\xeb\xe0\x75\xba\x50\x79\x88\x30\x28\x1e\x57\xa8\x44\x79\x82\xfd\xe6\x9d\x77\x00\x83\xf5\xc9\xb7\xf1\x4f\x02\x0f\xf0\x83\x89\x00\x8f\x07\x29\x62\x52\x71\xe1\x79\x7a\xc5\x9b\x50\x2b\xa8\x58\x34\xd5\x26\x0f\x52\x6d\xf2\x8c\x80\xf5\x20\x80\xca\xb8\x24\x59\xf1\xa0\x8b\x4b\x05\x18\xf0\x52\xa6\x4d\x3e\x1a\xa6\x20\xe5\xf2\x48\x85\x0d\x65\xa2\xe4\xae\x11\x0d\x90\x83\x93\x8f\xcf\x55\xb5\xb7\xe6\xa5\xe1\xef\xd1\x03\x96\x28\x92\x27\x37\x9d\xc3\xf8\xbf\x66\xb4\x9c\x53\xc8\x50\xae\x98\x77\xfb\x73\x6c\x8c\x72\x3d\xfc\x80\xa8\x80\xe7\xfc\x56\x30\x92\x8b\x93\xdc\xa1\x3a\x91\xb3\xe0\x5f\x15\x43\x42\x31\x26\x71\x13\x96\x3c\x76\x36\x64\x34\x18\xe3\x94\x4f\xa7\xd0\x62\xdd\x75\xf4\xd9\x82\x9d\xf9\x3e\xc5\x28\x2a\xa6\x3e\x85\x17\xb3\x02\x6f\x70\xc6\x33\x02\x6f\x28\x29\x27\x64\x4c\xbc\xd0\xd2\xd2\x02\xe9\xdf\xf1\x16\x84\x90\x1d\x2c\x58\xf8\x1e\xa8\x7e\x89\x68\x50\x57\x4b\x2a\x83\x59\x0a\x0d\x9d\xb8\x5e\xe0\x0c\xb3\xc5\x51\xcc\x98\x60\x80\xc5\x4a\x81\x03\xc6\xc7\xcc\xe2\xdc\x5f\xc2\xf8\x5f\xc6\x9c\x7d\xc9\xcd\x2f\xfe\xe8\x3b\x9b\x1b\x52\x0d\x30\x31\x62\x44\xfb\x98\xf6\x9a\xae\x34\xc3\x5c\x78\xb1\xd5\x1f\xbd\x8e\xbb\xeb\xeb\xe7\x1b\xd6\x2f\xd9\xf8\x50\x5d\xa4\x6b\x0c\x9c\x50\xdf\xd2\x11\xaf\xa9\x69\xb7\x13\x9c\x68\x7f\x8e\xdf\xc3\x2d\x07\x0d\xa0\x13\x3c\x41\xeb\xba\x28\x1d\xcf\x35\x13\xc3\xf8\xcb\x80\x1d\xb9\xa4\xdd\x05\x6d\xf1\x5c\x12\xff\x43\xa8\xa4\xf0\x7b\xd7\x80\x22\x37\x82\x1d\x33\x11\x32\x80\x11\x04\x36\x8b\x8c\x35\x12\xc6\xd5\x06\x3a\xd1\x1c\x91\x72\x2c\xe7\x65\xfc\x38\x71\x94\xf7\x09\x56\x57\x63\x73\x07\xe1\x71\x56\xed\x49\x64\x85\x66\xda\xe4\x4f\x4a\x99\x20\x11\x6e\xb3\xcb\xaa\xb5\x3a\x9d\x56\x20\xfa\x77\x4d\x98\xe9\xa6\x6c\xd6\x59\x30\x94\x99\x27\x86\xad\x96\x2a\x14\x6b\xa3\xa5\xe6\x2a\x8c\x40\x5b\x47\x94\x18\x6c\x3d\x32\x62\x8a\xea\x59\xe5\x0a\xc6\x23\x33\xd1\xd1\xf3\x7f\x5f\x30\xdd\x14\x64\xce\x71\x17\x42\x86\x96\x6f\xbf\x2c\x58\x92\xe9\xcf\xf7\xe7\x70\x3f\xac\x12\x34\x21\x9f\xe5\x43\x26\xac\x29\x9e\x2d\xa2\xde\x2c\x1a\xf2\x8a\xa1\x2d\x63\xc3\xa8\x23\x9b\xc5\x14\xc7\x08\xea\x5c\xbd\xd3\x67\xb1\xc5\x73\xf5\xd4\xa8\xcd\x09\x25\xaa\xcf\x1b\xe1\x06\xa6\x27\x8a\x6b\x06\x40\xad\xf1\x49\xb2\x12\x4c\x2b\xf5\x52\x86\xf1\xe0\xa2\xad\x13\xab\xab\xd9\x44\x0a\xaf\x35\xd0\xd5\xeb\x42\xc9\xc3\x1e\x1d\xc1\x01\xbd\x13\x66\x70\x9e\x25\x0f\x84\x5e\xbe\xa5\xaf\x15\x86\xda\xb4\x8f\xe7\x8d\x99\x79\xc9\xcd\x2f\xee\x99\xbd\xb9\x3e\xd1\xaa\x1f\xa2\xea\xf1\x15\x0c\x73\xe9\x05\x56\x7f\xfb\x55\xf0\x08\x6e\x85\x69\xf3\x1a\xd6\x2f\xd9\xb4\xb3\x2e\x92\x9a\xa2\x1f\xa5\x90\x17\x9d\x25\xa8\x7d\xa5\xb9\x98\x09\x5c\x0f\xb0\x82\xf3\x06\x33\xfd\xd8\x0a\x4c\x3f\xf6\x53\x60\xfa\x39\x31\xbf\xcf\x20\x46\x9f\x12\x0e\x1f\x12\x2b\x08\xaf\x09\x2e\x50\x8d\x15\x52\xdf\x04\x99\x4a\xf4\x96\xfb\x93\x6a\xad\x29\xaf\xb4\x92\xe0\x51\x71\x26\xd5\x46\x53\x5e\x49\xb5\x29\xe6\x84\x62\x49\xea\xfa\xa8\x61\x47\x5e\x09\x8b\xaa\x19\xc6\x31\x92\xbd\xc5\x62\x1e\x82\xf5\x5d\xb1\x88\x38\x88\xf4\x38\xb0\x82\x2a\x5a\xd5\x18\xc7\x3f\x25\xb2\x2a\x33\x76\x07\x16\x51\xb1\xf6\x01\xd5\x64\x45\xab\x42\x9f\xf8\xcd\xaf\x47\x29\x71\x25\x47\x38\xdf\x85\x60\x3a\xad\x5a\xcc\x92\x9c\xb5\x3b\xfc\x38\xfa\xec\x90\x54\x67\x4a\x57\x41\x42\x1b\xde\x28\xa9\x1e\x90\xc6\xc5\x6b\xc1\x5e\x2c\x5e\x7b\x31\xed\x01\x2b\x18\x92\xa3\x99\xc2\x55\x15\x2b\x14\x5f\xd0\xb5\x8d\xee\x2b\x5e\xaf\xc4\xa0\x5f\x98\x79\xb7\xff\x7d\xeb\xc3\x0b\x8c\xe6\x40\x17\x4c\xcc\x90\xdb\x6c\xa7\x4f\x3f\xf7\xb4\x6d\x3f\xba\x4f\xd3\xf6\x1c\xbc\xf6\xe6\x5f\xbf\x72\x18\xb6\x76\x8d\x99\x7d\x4d\xd7\xfa\x09\x2b\xa6\x33\x6b\xc7\x8e\x9f\xb8\xe2\xec\x5b\x53\x0b\x26\xb4\xc2\x4d\x7d\x70\xe1\xeb\x3f\xbc\x7b\x3d\x4c\x68\x3b\xce\xdd\x7c\xe6\xe9\xe1\xdf\xf5\x1d\xd4\x76\xf4\x6e\xd9\x72\xf8\xdd\xb9\x17\xde\x02\xc3\xe7\xec\xb9\xed\x1f\x0f\x4e\x9e\x70\xd3\x97\xd7\xe5\xa6\xde\xa1\xfd\x9d\xd4\x26\x84\xd7\xb8\xe5\xd8\xfe\xa7\x81\x17\xa9\xfd\x1d\x49\x35\x62\xca\x2b\x23\xa8\xfd\x8d\x05\xfb\x7b\x12\x8a\x3b\xa9\xb3\x5e\x53\xfb\x7b\x50\xaa\x63\xcb\x67\x63\x6e\x8f\x31\xae\x5b\xdd\x2d\xe2\x3e\x80\x85\x30\x69\x62\xab\xdb\xff\x69\x2a\xe8\x16\x7a\xfb\x14\xb7\xa8\xb8\xfa\x80\xea\xf2\x22\xab\xa3\x4f\x42\xac\x80\xad\x1e\xa1\x61\xad\xcf\xdf\x88\x12\xa7\x96\x98\x24\xab\x02\x8a\x75\xdb\x25\xd5\x88\xd1\xea\x91\x4a\x49\x56\x25\x1f\x56\xed\xc0\x97\x92\xc2\x51\xf6\x1a\x32\x8c\x4a\xf5\xb9\x85\x48\x4d\x2c\x22\xe0\xce\x50\x2a\x62\x67\x74\x4a\x75\x99\x56\xbc\xf8\x22\x71\x8f\xc0\xcc\xbb\x1f\xc2\x3d\x07\xaf\x5d\xf7\xf6\xab\x87\x6e\xfb\xef\xed\x0f\xcf\x37\x59\x7c\xd3\xb4\x83\x73\xbd\x4d\xd6\x49\xdd\x73\x52\x5b\x1f\x87\xad\x1b\xbe\xb3\x7a\xd4\xb8\xae\x89\x2b\xce\x66\xd6\xaf\xef\xba\xee\xac\xae\x31\xb3\xaf\x1d\x07\x37\xbc\x03\x2f\xe9\xbd\xf3\xce\xf7\x5e\x79\x4e\xdb\x7d\xe0\xd1\xf5\x6b\xb4\x0d\xf0\xae\xcb\xbf\x37\xab\x33\xf4\xdb\xb7\x73\x7b\xe0\xe8\xd6\x33\xbb\x6e\xfa\xf2\x96\x3d\x1b\xbe\x5a\x32\x77\xe1\xad\xda\x6f\x71\x1d\xb3\xff\x52\x6e\xbf\xe0\x02\x76\xe0\x06\x15\xe0\x34\x5a\x15\x13\x92\x0a\x9b\xc0\x2a\xe6\x24\x7a\xc0\xb9\xb7\x60\xc0\xcd\x1f\x9e\x34\x67\x81\x24\xf7\x1a\x4d\x56\x87\xd3\x53\x81\x5d\x6c\x04\x86\x53\x49\xd6\x19\x66\x23\x6c\xc4\x19\x61\x61\xd2\x19\x4b\x09\x06\x67\x32\xb6\x9a\xd1\xe0\xac\xf8\xfe\xec\x4a\xed\x70\xc5\x1b\x47\x5f\xff\x7c\xe2\x93\xb0\x61\xe2\xa7\x2c\x6c\x1a\x37\x6b\x8c\x91\x7f\x76\xae\x76\xe7\xd7\x3d\x70\x81\x66\x86\x5f\xe0\x1a\xe5\x7b\x97\x8e\xbd\xfe\x56\x6d\xed\x95\x98\x57\xe8\x52\x3e\x25\xb8\xf0\x54\xf1\x02\x3a\x39\x24\x95\xe0\xf7\xb3\x56\x0f\x67\x8c\x63\xd1\x6f\x12\xbb\x87\x68\x7c\x1e\x02\x58\xd8\x10\xa8\x92\x47\x92\x33\xae\x8a\x00\x21\xc2\xc8\x01\x87\x13\x4f\xd2\x2a\x61\x9c\xc3\x71\x92\x6a\xb2\x14\x42\xd8\x36\x6f\x2a\x69\xf0\x78\x0d\x75\x31\xe8\x49\xb6\xa5\x24\xb4\x5d\x86\x48\xaa\x0e\xba\xbc\x98\x7c\x68\xf5\xaf\xe1\x82\x3f\xcd\x99\xd2\xbc\xbf\xfb\xf4\xba\xeb\x92\xa7\x6b\xc6\xa6\xa9\xdb\xfb\xf6\xbf\x76\xd9\xfc\x39\xaf\xad\x7f\x06\xa6\xc2\xf0\x6d\xdf\x2d\xef\xdc\xcc\x34\x40\x01\xfe\xfc\x13\xf3\xd9\xeb\xfc\xee\xaf\x42\x81\x6f\x7a\xc4\xe9\xda\x37\xd3\xfd\x8f\x1c\xbd\x0b\x9e\x7d\xdd\x14\x76\xd6\x6e\xed\x65\x7c\x8f\x4e\xd3\xe6\x70\x6b\x04\x17\xf0\x83\x6a\x30\x81\xf2\xd0\x49\xa6\x3c\xa1\x03\xb5\x24\xa0\x12\xc6\xad\x9b\x80\x23\x8f\x55\xd0\x02\x9c\x24\xab\xd0\x8f\x2c\x2f\x55\xa0\x1f\x71\xa7\x40\xca\x71\x36\x77\xa8\x12\xdb\x3f\x00\x5b\x20\x1d\x7e\x76\x26\x59\xaf\x21\x06\x69\x91\x2c\xc6\x3a\x5d\x5e\xa7\xc0\x4c\xfb\xd5\xec\x4b\xef\x85\xf6\x9f\x34\xd5\x3f\xf3\xca\x1b\x63\x17\x74\x6b\x1f\x19\xa7\x7c\x6f\xe2\x03\x3f\x4b\x66\x57\xda\x8e\x5d\x77\x97\x36\x07\xee\x6f\x52\xb7\xfc\x06\xce\xff\x25\x07\x1f\xd3\xda\x02\x9f\x04\x8f\xaf\x49\x44\xbe\x38\x8b\xd1\x16\xb3\x53\xda\xeb\x98\x0e\xb7\xf6\x37\x5c\x8b\x07\x09\x00\xd8\x5d\x7c\x2f\xb0\x81\xf5\xa4\x5e\x8c\x27\xdd\x58\x06\x13\x13\xe4\x00\xb4\xb2\x36\x42\xe3\xaa\x02\x36\xaf\x1a\x6d\x6d\x6d\x50\xb1\xe3\xe9\x6f\xce\x91\x57\x1d\x03\xfa\x2b\x2c\xc6\x9b\x71\xd8\xfb\x59\xc5\x2c\x63\x65\x9d\xf1\x01\x75\x53\xf4\xbd\x0d\x7d\xcf\xee\x63\x78\xa3\xc9\x6a\x2b\x1d\x7c\x74\xa6\x92\x94\x87\x39\xcc\x86\x9d\x89\xd4\xfa\x75\xb0\x6d\xfd\x9f\x53\x9f\x4e\xc6\x4c\x0c\x6b\x99\xd9\x1a\x73\xf1\xf1\x5d\x9a\xf6\x64\x3f\x60\x66\xe3\xb8\xee\x35\x7a\xae\x1c\x40\x06\xcf\x83\x8c\x8d\x4e\x27\xe9\x0d\x8e\x0c\x63\x92\xdb\xda\xda\x32\x1c\x8b\xae\x5d\x4e\x30\xc5\xa1\xe2\x4c\x94\xcc\xac\xe0\x28\x4e\xb1\xb5\x28\x72\x8b\x62\x13\x55\x2b\x77\x4c\x91\x45\x95\xe1\x8e\xe9\x70\x1a\x8b\x62\x13\xb3\xd0\xc6\x90\x27\xb7\x58\x65\x67\x1c\x7d\x63\xd7\xbf\x11\xd1\x37\x19\xbb\xad\xb4\x27\x0d\xd3\x19\x8b\x55\xa6\xf4\x3d\x59\x68\xb1\x8b\xba\x7e\xaa\xc5\x6a\xb3\x8b\x72\xa9\x7e\x2a\x20\xbd\x0c\x23\xba\xc1\xa1\x33\xec\x0c\xa7\x92\x0e\x18\x81\x6c\x38\x65\x80\xa9\x48\x0a\xee\xfc\xa1\xf6\x48\x8a\x5d\x30\xe1\x67\xd7\xc5\xce\xd7\xee\xb8\x53\x7b\xdb\x76\x1f\xf3\xc0\x15\x33\x76\x30\xdd\xac\x00\x99\x9e\x1f\xfd\xfc\xf8\xdf\x8f\x2f\x48\xbf\xc3\xa9\x0f\xe1\xfd\xf4\x6a\x2e\x8c\x95\x6a\x03\xdf\x05\x05\x80\x94\xd2\x98\x50\xa3\xa6\x3c\x6e\xb1\x0e\xc6\x49\xb5\x53\x9c\xd4\x3e\x13\x5b\x5d\x43\xd8\x33\x05\x49\x8d\x34\x62\xa0\x54\xaf\x43\x76\xf9\xa3\x31\xc2\x31\x1a\x6d\x24\x28\x0e\x97\x94\xb5\xca\xb1\x96\x53\xc0\x4a\x19\xd0\xdf\x69\x8f\xb5\x05\xc6\x5a\xd8\xa1\xf1\x52\x7f\x7e\xc3\x5b\xe1\x6f\x4f\x34\x8d\x9f\x7e\xde\xdc\x55\xb3\x22\x5e\x67\x45\x68\x38\xd0\x54\xe6\x35\xa3\x77\xcc\xf4\x89\xce\xbf\x06\x4e\xbf\xe1\xa6\x59\x23\xc2\x7e\xbd\xb7\xe4\xc2\xbd\x25\x3f\x68\x07\xc5\x96\x92\x33\xa1\xda\x4d\x38\x17\x41\x49\x08\x50\xed\x44\x9a\x56\x61\xa5\x8c\x41\xf4\xa4\x8b\x5e\x3e\x52\xe0\x48\xf4\xe2\xca\x0e\x21\xb7\x68\x61\x22\x25\x2d\xa5\xfb\x47\x9e\x15\x4d\xc4\x9a\xc3\xa9\xd3\x27\x5d\x7d\xeb\xc3\xa7\x07\x13\xe3\x47\x92\xbe\x52\x85\xef\xb2\xf9\xcb\xc7\x04\x9c\x7f\x09\x6d\xf9\xf1\x77\xc6\x57\xe2\xfd\x78\x00\x00\xce\xc8\x1f\x00\x2e\x70\x43\xb1\x4b\x61\x43\xa7\x53\x30\xe3\x1e\x17\xf2\x75\x2e\x47\x5e\x71\x89\x2a\x0b\xe3\xaa\xe8\xc8\xa3\x8b\x8f\xe2\xb9\x7e\x45\x2e\x36\x02\x94\x70\x89\x8a\xb3\x0f\xa8\xd0\x89\x2e\x36\xf4\x49\x78\xa0\x00\xcd\xe5\xb0\x80\xa5\x4d\x27\xcc\x51\x4d\x22\xee\xeb\x13\x32\x64\x67\xad\x54\x06\xa5\x71\x31\x06\xf6\x81\x2d\x50\x99\x3f\x75\xf4\x9d\x17\x5c\xb4\xe1\xcd\xe5\x2f\x7c\xf8\xe1\xdf\xaf\x60\x76\xdd\x0f\xad\xe3\xcf\x69\xea\x7c\x7f\x52\xea\x95\xbd\xaf\x69\xef\x2d\x3e\xfe\x15\x5a\xc3\x04\x00\xd8\xc7\xb9\xe5\xc0\x0d\x5a\x49\x46\x8e\x01\x99\xaa\x6c\xc6\x8d\x43\xc5\x71\x08\x23\x5d\x70\xff\x50\xb6\xa0\x1b\xd5\x8d\x9f\x86\x40\x91\xf5\xff\xa0\x03\x86\x9d\xf4\x4a\x74\xc0\x09\xdb\x5f\x5e\xfa\xe2\x9f\xfe\xfc\xf7\xa8\xf6\xee\x84\xdf\x1f\x9a\x3f\x75\xd9\x2d\xa7\xb1\x5f\x4c\x49\xee\x7f\xfc\x80\xf6\xfb\x45\x0a\x9c\x30\xfd\xad\x5b\xc7\x9f\x33\xa1\x12\xb0\xfd\x9f\x00\xc0\x7d\xc4\xf7\x02\x27\xa8\x02\x31\x70\x90\x64\x6e\xaa\x8b\xf6\x30\x15\x36\xa9\xc6\xd8\x7c\x0e\x40\x89\x43\x7e\x2a\x88\xfc\x94\x35\xaf\x3a\xab\xda\xda\x72\xd5\x01\xfc\x65\x35\x95\xa2\xac\x20\xa5\x92\x5a\x94\x38\x1b\x4a\x54\x92\x1f\x3d\xfa\x3e\xf6\x01\xce\x16\x25\xd6\xa2\x38\x45\xd5\xe5\x3e\xa6\xc4\x44\x95\x75\x1f\x53\x9c\x62\x96\x71\x22\x1f\xe6\x12\xb3\x01\x57\xcc\x19\xcf\x06\xf1\x67\x15\xfe\xac\x46\x9f\xec\x58\x13\xc3\x3a\x5d\x81\x60\x55\x75\xac\xa5\x94\x8f\xac\x16\xf9\x76\x8b\x59\xc7\xaa\xab\xf6\x8a\x74\x5a\xad\x0e\xd0\x2f\x95\x18\x69\x9e\xb1\xc8\xe3\x91\x5c\x86\x60\xb8\x1a\xa0\x93\xc7\xaf\x52\x1c\x1a\x92\x86\x88\x93\xfe\x1c\x68\xd8\xd5\x07\xf7\x7e\xf2\xd7\x3d\x0f\x5e\xbc\x52\x7b\x4b\x3b\x7a\xfc\x8b\x29\x30\x94\x5b\xb1\xe1\xe9\xc7\xdc\x1f\x36\x7c\xb4\xfc\xde\x55\xab\xf6\x3e\x00\x17\xec\x67\xef\x7e\x74\xf7\x7d\x2f\x54\x1b\xfd\x5b\xae\xf8\xe4\x4b\xb8\x60\xc1\xb5\x97\xed\x9e\xb7\x9f\xf1\x5e\x38\x7f\x13\x60\x80\xdc\x7f\x84\x3f\xc8\xf7\x02\x0f\xa8\x86\x71\x82\x2b\x54\x7d\x14\x8f\x9c\xe1\x0c\xc6\x64\x32\x99\x83\x40\x64\x6d\xf1\xac\xd5\x83\xae\xa2\xa4\x0a\xd9\x7c\x96\xe1\x05\x53\xad\xb7\x0d\x5f\x63\x4e\xe2\x3d\xaa\xdb\xb2\xac\xd7\x49\xa1\xc9\x5e\x4a\xf6\x45\xae\x37\x0a\x3f\x79\x85\x9c\x5c\x56\x54\xdc\x7d\x1c\xba\x11\xaa\xfb\x4a\xbe\x36\x88\x4a\x10\x27\xcd\xb6\x3e\x5e\x71\x8b\x59\xc6\x8d\x8c\x5c\x2d\x66\xf9\x6a\x8e\x70\xbe\x09\x41\x03\x71\xb4\x26\x9b\xd1\x19\xcf\x5a\xd1\x27\xfa\x93\x1e\xfc\x27\x83\x62\x36\x84\xff\x40\xb5\x98\xad\x44\xff\xca\x33\xa3\x7f\xf2\xb9\x15\x0f\x5a\x54\xa1\x5f\x33\x55\xd5\x5c\x49\x02\x9e\xb3\xb9\x83\x55\xd5\x04\x1d\x34\xd6\x8a\xd6\x63\xb5\xb9\x3d\xc1\x50\x65\x55\x4b\xc9\xff\x08\x2a\xda\x2b\xc9\xaa\x88\x15\xd6\x81\x4f\x1f\x66\xc2\xb7\x12\x55\x08\x30\x30\x80\x32\xc9\x41\xda\xc9\xb7\x43\xb9\xf3\xf1\xab\x60\xeb\x55\xf0\xf0\x55\xb0\xed\xea\xc7\x3b\x1e\x8f\x9c\xae\xfd\x52\xfb\xcd\xe7\x8e\x4a\xc8\xfd\x72\xf5\x5d\xd5\x21\xad\x21\x66\x60\xf6\x68\x8c\x7c\xfc\x6f\xe8\x2f\x6d\xb7\xf6\xb9\xf6\xcf\x8f\x5e\xec\xee\xba\x5d\xfb\x26\xf3\xe0\x03\x1b\xf6\x8d\xc4\xbe\x6b\x03\x00\xdc\x2c\xfe\x59\x60\x01\x23\xca\x7b\xd0\x50\xb1\x16\x98\x44\x6c\x94\x49\x84\x48\x98\x00\xda\x54\x23\x1d\xe5\xba\x0e\x83\x60\x80\xab\x99\x23\x70\xce\xed\xda\x7b\xa3\x4c\xa1\x44\xa3\x36\x9b\x7f\xf6\xab\x09\xec\x84\xab\x3f\x3c\x6b\xed\xb9\xdf\x6c\x25\x1c\x07\xfd\x97\x72\xbb\x04\x17\x70\xe2\xca\xcd\x16\x8a\x30\x05\x49\xd5\xc6\xe6\x33\xa2\x0d\xdd\x94\xa2\x64\x8a\xe3\xff\xb4\xc2\x27\x55\x3f\x8b\x52\xd7\x9c\xc9\x22\x41\x5b\x5c\xf1\x60\xce\x25\xc5\xdb\x86\xc3\x4a\xe2\x51\xf1\xa6\x6f\x3f\x7a\xa7\xde\x3b\xf5\xb7\x20\xa7\x85\xde\x24\x5e\xf1\x8b\x2a\x74\x1f\x43\x6f\x90\xc7\xe5\x77\xc6\xb3\x5e\xf4\xc9\x02\xc5\xd5\x02\xf7\x01\xe8\xf2\x78\xfd\x03\xa8\x0f\x52\x49\x74\xf0\xf5\x28\xc0\x10\x49\x39\x53\x91\x54\xd2\x19\xe9\x80\x1d\xcc\xc8\xf8\xcb\xf1\xce\xce\x6b\xef\xd9\x9d\xfa\xe0\x49\x78\x41\xa7\xb6\x68\xd2\x2b\x93\x72\xcb\xd2\xa9\x95\x77\xef\xe7\x7b\x7b\x7a\xf4\x5e\xe9\x8e\x1d\x70\xe3\x51\x0d\x8e\x23\x73\x61\xf3\xb4\x39\x5c\x97\x00\x40\x10\xd4\x80\x18\x68\x82\xf3\x49\xfc\xa9\x78\x93\xaa\xc3\x40\xe6\x96\x9b\x13\x8a\xef\x50\xa1\x4b\x20\x66\x2d\x15\x21\x7b\x01\x54\x12\x22\xe3\x93\x8d\x54\xd5\x9f\xaf\x3e\x24\xe5\x04\xd2\x46\x68\x21\x6b\x3f\x63\xce\x67\x3f\x23\x28\x56\x5f\x8b\x22\xb4\x28\x3e\x51\xad\xa8\x39\xa6\x08\xa2\xca\xd7\x1c\x7b\xe6\x8c\x73\x3e\x7b\x1a\x47\x12\x3a\xb5\x21\xfa\x2f\x18\x2a\x04\x67\x3c\x6b\x43\x9f\x7c\xd6\x8e\x7f\xf1\xa2\xcf\xb2\x3f\x8d\x29\x10\xb3\x55\xf8\xb3\x1a\x7f\xd6\xe2\xcf\xa8\xfe\xff\xa5\x1e\xff\x8b\x4d\xe8\x33\xe3\xf7\xf1\x25\x31\x48\x55\x5a\xa9\x4e\x2b\xb5\x69\x25\x9a\x56\xb8\x74\xc6\x56\x21\xa0\x6f\xeb\xd3\x4a\x53\x5a\x31\xa4\xc1\x58\x3b\xc7\x0b\x06\x5b\x85\xcf\x5f\x55\x5d\x1b\xad\x6f\x6a\x29\xfb\x1f\x1c\x6b\xe5\x0c\x36\xbb\x77\x88\x7f\x88\xdf\x12\xbe\x42\x92\x95\x08\x8e\x13\x48\xd3\xd7\xe1\x91\x08\x4e\x15\xa5\x49\x29\x67\x92\xc5\xb7\xbe\x03\x7a\x0b\x81\x6b\xc4\xd9\x02\xa3\x2e\x6f\x2a\x62\x48\x25\x53\x76\xe8\xed\xec\x68\x8f\xcd\xbb\x13\x72\x7b\xaf\xdf\xb5\x6a\xd3\x6d\xff\xfa\x68\xb2\xb7\x02\xb7\x75\x53\xab\xbe\xbf\xfe\xaa\x9b\x60\xc2\xdd\x70\x3a\x13\x99\xdb\x3d\xf2\xdc\xff\x5a\xd1\x0a\x77\x3d\x0f\x27\xbc\x64\x83\xdb\xb4\xa5\xde\xef\x5f\xf3\xc8\xcb\xbe\x7f\x30\x75\x23\x3e\x9a\xc3\x68\x8b\xe1\xcf\x9a\x5e\xbd\xfb\xb4\xc6\x2d\xee\x0f\x8e\xd6\xdc\xd4\xda\x7a\xd1\x19\x5e\x00\xb5\xe7\xb4\x59\xcc\x47\x18\xf3\xf2\x20\xc8\x98\x19\x32\xa7\xee\x4c\xa8\x8c\x25\xaf\x18\x12\xaa\xe0\x48\x26\x55\x23\x9b\x57\x4d\xd6\xb6\xe2\xc8\xba\xa3\x38\xa1\x4e\xf9\x29\x71\x1a\xcf\xe3\x34\x5e\xec\xe3\x49\x71\xcf\xec\x8c\x67\x4d\xe8\x53\x11\xc5\xac\x55\xb4\x38\xe3\x59\x07\xfa\x64\x81\xca\x8b\x2d\x2d\x70\x1f\xf2\x2d\x0e\xb1\x78\x0b\xa0\xdc\x5e\xb1\xa7\x81\xca\x38\x09\x1e\xcd\x50\x56\xcb\x88\x14\x02\x5e\x0c\x5f\xd1\x9e\x9b\x3b\x6d\xd1\xea\xe0\x95\x4a\x4a\x59\x0b\x5b\xd7\x65\x52\xca\xaa\xf6\x7f\xfd\x9f\x9e\xf3\xef\x73\xad\x5a\xcf\x98\x35\x66\xc1\xf1\x1f\x6a\xc7\xdf\xf8\xe7\x07\x01\xcc\xaf\xfc\xa5\xe6\x62\xb6\xe2\xf7\xb8\x12\xfc\x04\x60\x8c\x87\x62\x4e\x2a\x12\xa9\xbf\x0a\x09\x95\xb7\x27\x93\xaa\xc1\x9a\x57\x8d\x96\xb6\x36\x25\x94\x50\xbd\x5c\x1e\x8f\x62\x99\x0e\xe1\x93\xec\x42\x77\xa1\x5f\xcc\xab\xd5\x05\x64\xe6\x73\x64\xe5\x26\x51\xe1\xfa\xd0\xfa\x1d\x7d\xbc\xc2\x89\x59\x9e\x33\xa1\x00\x1e\x7d\x2a\x0e\x31\x6b\x71\x98\xb1\x56\x81\x19\xaf\x9c\x73\xa0\x95\x73\xbc\xd1\x62\x2f\x21\x6a\x34\xbb\x24\x59\xf5\x86\xb0\x36\x89\x6a\x25\x81\x09\x43\x07\x94\x88\xca\x7c\x71\xf1\x03\xd4\xe6\xb5\x2f\xcf\xe8\xd8\x54\x7b\xed\xce\xf8\x83\x0b\x61\xcb\x85\x3b\xe2\x3b\xd6\x94\x0b\xcc\x7f\xe8\xde\xcb\x44\xf6\xc3\x3e\x6d\xec\xfe\xe3\x4a\xa9\xa6\x3c\x03\x56\x6b\x2e\x01\xf0\x07\x40\x0d\x18\x01\x2e\x03\x19\x13\xbe\xda\xb0\xcc\x92\x25\xaf\x78\x12\xaa\x68\x2a\x08\xcd\x46\xc4\xbc\x12\x11\x55\x1f\x8c\xab\x36\x91\x48\xc9\xfa\x22\x92\x9c\xe5\xaa\xeb\x9a\x09\x81\xef\x3e\xa3\xc1\x13\x0c\xc5\x71\xec\x2b\x7a\xf0\x6d\xa0\x34\x4b\x39\x1b\x90\x7d\x75\xa4\x8e\x49\x10\x0d\xa2\x0c\x08\x00\x06\x43\x09\x31\x0b\xba\x4e\x08\x4b\xb0\x84\x0c\x29\xbf\xa5\x3a\x3b\x44\x9c\x7e\x3e\x07\x67\x1c\xb8\x7a\xd7\x18\xe3\x24\x28\x6b\x19\xa1\xa9\x6e\x74\x32\x7c\xcd\x88\x07\x7e\x30\x4e\x72\x2c\x7c\x66\xd5\x8b\x9f\xc2\xd4\x8d\xd7\xdc\xf9\x1f\xc9\x48\x7e\xcd\xfe\x95\x0c\x07\x19\xf8\x32\x64\x17\x5c\xae\x1c\x3b\x1c\xf4\xd5\xd7\xbb\xff\x6a\x93\x37\xdd\x3a\x0a\x06\x52\xcb\xce\x85\xd5\x90\xd9\x74\xef\xf1\x23\x0f\x9e\x0b\x41\x4e\xfb\x29\xc5\x59\x3e\x8c\x67\x25\x46\x80\xa5\xa0\x04\xf7\xd3\x6c\xc2\x8a\x4a\x8e\x92\xf5\x3b\xf0\xfa\xbd\x14\x5e\x89\xd6\x1f\x41\xf7\x49\x15\xe6\x9d\xe6\xea\xc8\x9c\x99\xd1\x15\x08\x36\x36\x63\x13\x38\x5c\x92\xac\xc8\xd4\x04\x92\xb7\xcc\x04\x45\x0c\xd0\xd0\x68\x4a\xf4\xf2\x0f\x64\xef\x99\xb3\xe1\x34\x63\xfa\x2f\x9a\x56\x0a\xa5\xec\xbe\xf3\x3b\x73\x6f\x9b\x5e\x86\xa5\xc4\x60\xa0\xa9\xe7\x6d\xfd\xba\xab\x14\x47\xd9\x33\xed\x82\xde\x3b\x4b\x81\x94\x0c\x10\x01\xe0\x9e\xe4\x7b\x81\x04\xfc\xe0\x19\x1a\xdf\x60\x5d\x0e\x3d\x54\xf4\xe3\x50\x51\xc4\xa1\xa2\x4c\x53\x5a\x32\x4c\x11\xd0\x87\x29\x14\x07\x29\x3c\xa1\x08\x31\x58\x1e\x87\x2b\xa2\xa8\xb0\x7d\x84\xb1\x15\xbd\xfe\x8c\xc8\x92\xb7\x01\xb3\xb7\xa2\x6f\x24\xfd\x1b\x19\x7d\xc3\xee\x63\x58\xbb\x24\x17\xaf\x37\x7d\xa8\x51\xf1\x48\xaa\xd9\x4a\x30\x97\x96\xa2\x68\x89\xe2\xa7\x78\xaa\x62\x48\x88\x87\x39\xc3\xce\xa8\x0e\x8a\x17\x3b\x77\x6e\x2a\x1b\xe0\xd4\xde\x5e\x09\x2f\x25\x73\x9b\x4c\xeb\x37\xcc\xa6\x92\xd1\x4d\xa6\xf5\x1b\x3c\xaf\x09\xfb\x8f\x00\xc0\xee\xe5\x96\x03\x0f\x58\x49\x30\x80\x28\x07\x41\x21\x3c\xae\x50\xa8\x36\x0e\x59\xc5\x6d\xb4\xc5\x15\x91\x86\xcf\x1e\x64\x13\x6f\x42\x71\x1f\x52\x5d\xb6\xbc\x5a\x31\x60\xc0\xc4\x2d\x2a\x1e\x9a\x8f\xb0\xaa\xd3\x43\x49\x69\xdc\x92\xac\xb2\x0c\x7a\xcf\x6d\x90\xcc\xae\xb2\x92\xca\x0b\x69\x1a\xe5\x96\x8d\x66\xe2\xcb\xdd\xe9\xaa\xdf\x75\x51\x71\x24\x73\xe6\xb6\x64\x5f\xc3\xbb\x0b\xb5\x77\x16\xc2\xfd\xaf\xc2\x83\x64\x1c\xb3\xe7\xf2\x57\xb5\x34\xdc\x8f\xf7\xb7\x07\x00\x7e\x0c\xde\x5f\x17\x58\x01\x30\xb0\x4d\xb1\x27\x49\xb1\xc2\x90\xcc\x99\x2c\x0e\xd6\x16\x57\x01\xda\x59\x93\x35\xaf\x42\x1e\xad\xc2\x8d\x13\x14\xbb\xad\x98\x56\x15\x5a\x64\x0e\xe4\xd8\x15\x3b\x8a\x42\x81\x6a\x43\xee\x1b\x7f\x12\x74\xb4\x43\x92\x33\x3c\x27\xe3\x02\x99\xc5\x51\x8c\x04\x63\x61\x2f\xca\x10\x93\x06\x94\xa3\x3b\xd9\xb0\x37\xd5\x13\xbf\xa4\x1d\x8e\x6c\x80\xb3\x6f\x80\x73\x36\x2c\x89\xef\xd7\x7e\xb8\x52\x3b\xb8\x72\x03\x8c\x36\xaf\xe1\x9a\xf7\xbf\xf8\xe2\x8b\x2f\xee\xd7\x98\xe3\x07\x99\x04\xd4\xf6\xef\x07\x7a\xdf\x8c\xeb\x01\x3e\x50\x0d\xce\x02\x19\x0b\xc4\x95\x51\xc5\x4b\xfc\xb6\x33\xa1\x1a\xfc\xc9\xa4\x2a\x59\xf3\xaa\x09\xd7\x5b\xc2\x09\xc5\x82\xb1\xae\xb8\x7c\x64\xb5\x48\x72\xc6\x60\x26\x94\x3f\x8c\x17\x57\xc7\x14\xa7\xa4\x82\x60\x69\x07\x2d\x92\x4a\xb2\x61\x27\xf5\xaf\xa4\x89\x46\x5a\x6a\xb4\x8f\x36\xe7\xa9\x86\x25\x6d\x30\x16\xf9\xea\x11\x38\x59\x59\xd2\xf0\xb8\x76\x15\x6e\xa5\x31\xb3\xac\x46\x57\x1b\xe9\xa5\x31\x33\x5e\x85\x53\xb4\x5e\xf4\xd7\xab\xc7\x65\x2d\xe7\xe4\x62\x4b\x32\xc9\xdb\xcf\xc7\x7b\x71\x51\xff\x11\x6e\x25\xb7\x1c\x04\x41\x0c\xdc\x0b\x70\xab\x48\x75\x0b\x79\x72\xac\x90\xd7\x51\x6b\x85\x7c\xce\x51\xe9\x37\xd9\xe2\x39\x87\x15\xb4\x70\x71\xbd\x55\xeb\xb4\xe5\x15\xa7\xa8\x70\x28\x8c\x62\xc9\x54\x1e\x9b\xd0\xf9\x46\x28\x10\xd1\x4a\xc6\x05\x54\x0e\x03\x11\xd1\x25\x12\x96\xb2\x82\xdb\x8f\x07\x5e\xad\x72\xc6\x44\x3b\x88\x0e\xac\xec\xe5\x4d\xa7\xd5\x5a\x3f\xe9\x15\x14\xce\x9c\xb3\xbd\xd3\x99\xf4\xea\xf0\x75\x8e\x77\x50\xc7\xe4\xc5\xe3\x79\x29\xbd\x3c\x6b\xb8\xc8\xb4\xf3\x5d\xbb\x69\xc6\x4f\x2f\x5f\xb7\x4b\xfb\x4a\xfb\xcf\x67\xcd\x86\xfb\xd6\xbe\xd8\xfd\xab\x0f\xf6\xff\x01\x5e\x72\xcd\xf6\xdb\x27\xa4\x17\x6e\xf6\xc0\x98\xef\x34\xe6\xe3\xfb\xe7\xcd\x7a\xec\xb6\x57\xde\x30\x0a\xad\xc1\x9a\xef\xce\x3c\x70\xf1\x63\xf0\x35\x4e\xb8\xe8\x92\xd6\xd4\x35\xcb\x08\xc6\xbd\xff\x08\xf6\xbd\x32\xa8\x06\xa3\x87\x45\x5f\xe2\xfd\x24\xb0\x4b\xb4\x9f\xff\x26\xa6\xf2\xc4\x40\xca\xe1\x00\x94\x94\x1f\xa6\xff\x08\xb7\xb8\xf8\x9c\xb8\x47\x65\x47\x1b\xe8\x31\xe5\x49\xbf\x4f\xc0\x23\x5b\xe1\x84\xe2\x3f\x84\xc9\xab\xf1\x73\x62\x6e\x62\x31\xad\x40\x29\xcb\x72\xe6\x50\xb1\x19\xa7\xa7\xf8\xb8\x28\x6e\x28\xe7\xf8\x8b\x7e\xf6\xa9\x64\xea\x7a\x74\xee\xf6\x27\x6e\xfb\xdb\x5d\x2f\xce\x32\x9e\xf6\xc0\xb4\x31\xe3\x6f\x98\x3a\x7e\xf4\xb4\x1b\xa7\x70\x3d\x7b\x7b\x2e\xfc\xed\x73\xcf\x69\x0f\xfd\xfa\xd1\xad\x70\xfd\x99\xf3\x37\xff\xf7\x8a\xb9\x73\x6f\xfd\xbc\xf0\x8c\x42\x04\x04\x41\x03\x18\x4b\x9f\x11\x17\x56\xab\x4d\x98\x51\x88\x33\x11\xf9\xd0\x5a\x5c\x3d\x51\xe3\xe8\x01\xab\x01\x19\x09\x33\x49\x19\x83\xab\xae\xa4\xaa\x93\xc4\x50\x1d\xaf\xbb\x2e\x52\x63\x10\x86\x7d\x5e\xfc\xb8\x90\xa9\xcd\xed\x9c\x3f\xba\xad\xfd\x02\x7f\x53\xa5\x71\xc6\xba\x69\xc5\x07\x9f\x32\x6e\xfc\x0d\x53\xd7\x4f\xb9\x7e\x06\xf7\x92\xa2\x54\xe5\x5d\x97\x3e\x39\xfb\xa2\xee\xc2\xe3\x6f\x9d\xb9\x70\xf3\x7f\xaf\x50\xbe\x77\x8c\xd4\xa1\x8e\xf4\x1f\x61\xd7\x73\xcb\x81\x1f\x9c\x41\x3a\x82\x58\x99\x44\x46\x67\xc0\x42\x2a\x51\x8a\xf1\x90\xea\x26\xc4\xe0\x40\xe5\x7c\x64\x0a\xcc\x22\x65\xa0\x1d\x53\x67\xca\xb2\xe2\x48\x8f\x68\x8d\xa5\x08\xd5\x65\xc7\x60\x15\x57\xd7\x82\x8e\xc5\x5d\xe7\x6c\x9e\x36\xff\xec\x33\x6e\x58\xd0\xfd\xfd\x25\xfb\xdf\xbb\x4f\x3b\xfa\xe4\xd3\xc9\x4f\xbd\x91\xf5\x7f\xbc\x69\xe1\x85\x91\xc4\x17\xd1\xf8\xa1\x57\xdf\xd5\xf6\x3c\x4b\x78\xcb\xbf\xea\xbf\x9b\x3d\x8a\x7b\x32\x8d\xe0\x62\x8a\xad\x8f\x08\xf9\x4c\x15\xd0\xaf\x02\xbb\x29\x9f\x6b\x70\x05\x8c\xb6\xb8\xda\x60\x25\x33\x07\x75\x87\xe8\x10\x2d\x1e\x2d\xf0\xd6\x49\xe4\xce\x8a\x04\x24\x59\x65\xd0\x8b\xd9\x20\xa9\x9c\x37\x9d\x56\x5c\xb8\xa2\x66\x97\x90\xe3\x37\x12\x11\x2e\xd2\x92\xc4\x75\x6c\xc2\xfa\xaf\xd3\xc7\xe2\x60\xd7\x0e\x0d\xb0\xd8\x94\x9c\x3a\x36\x7e\x2f\xb4\xff\xa4\x77\xfb\x82\xce\xc5\x5d\xd7\x3d\x65\x1b\xb7\xbd\xe7\xc6\x7b\x97\xbc\xb5\xea\xe0\x05\x9e\xaa\x14\x0c\x35\xde\x32\xeb\xa2\x8e\xce\x35\xe1\xd5\x73\xe7\xad\xfe\x0d\x9c\xff\xcb\xee\x4f\xbc\x35\xff\x54\x3b\x4e\xdf\xb4\x7c\xf1\x0f\xce\x3b\xab\xba\x69\x01\xdc\x3e\x6f\x5c\x67\xa4\xe5\xff\x9f\x35\x39\xf1\xac\xc9\xbc\xfe\x23\xfc\xdd\xf4\xbd\x9a\x41\xa2\x01\x7c\x3c\x8b\xd4\x9f\x52\x42\xb5\xd2\x97\x0b\x1c\xc2\x05\x62\xfc\x72\xd5\xb9\x91\x97\xf2\x78\xab\xa8\xfa\x2e\x5a\x9c\x82\xe7\xa2\x15\xab\xa4\xd8\x4b\x17\x3a\x9a\xd1\x5f\xb6\xa1\x95\x2c\xf4\xe5\xb9\xe6\x3f\x71\xc3\xf9\xa3\xdb\xda\x2e\xf1\xf7\x83\x21\x34\x2c\xf4\x85\x7d\xf9\x97\x6b\xab\xf2\xae\x95\x5f\x77\x97\xa9\x56\x10\x4d\x65\x7c\x9e\xbd\x20\x02\x2e\xa1\xd3\x0d\x9c\x81\x52\x29\x87\xf9\x7c\xce\x18\x70\xdb\x6d\x71\xd5\x88\x8e\x72\x2d\xbe\x44\x29\x13\x52\x88\x92\x27\x47\x61\x5c\xad\xb0\x48\xb2\xc2\x61\x74\xb3\xdd\x6d\x20\x72\xb9\x6e\xf2\x36\x1a\x25\x05\xa6\xd5\x70\x80\xd2\x02\x8d\x68\x4d\x75\xe0\x01\xc5\x54\xa4\xa6\x56\x67\x21\x27\x50\x40\x97\x67\x14\x4c\x91\x83\x9c\x9c\x7d\xfb\xfc\x15\x0f\x56\xb5\x7f\xaa\x7d\xfd\xaf\xfd\x6f\x7e\x76\x8f\x76\xec\x27\xd7\x67\x61\x68\xf9\x0d\xa7\x31\xf3\xcf\x1a\x39\xf9\x8c\x8f\x5b\x6a\xaf\x5f\xf1\xf8\x3d\x3f\xfe\xf5\x17\x07\x0e\x6a\xbd\x4f\xd4\xb1\xfc\xb8\xb3\x3c\xee\xcb\xd7\x4c\xfa\xff\xa8\x4e\x34\x5e\x13\xff\x0d\xb7\x1c\x73\x2d\x2f\x04\x99\x5a\xb4\xa6\x86\xd2\x35\x05\xbd\xb5\x68\x4d\x41\x6b\x41\xc9\x2a\x46\xb9\x96\x63\xfa\x42\x80\x1a\x6c\x40\x57\x7d\x2c\x8d\xb3\x13\x7f\x13\x9e\xae\xe9\xe5\x2c\xb2\xd3\x87\x65\x14\x8b\x6b\x19\x0d\xa3\x65\xde\xd2\x9b\x22\x39\x99\x97\x10\x55\x0b\x25\x2b\x33\xd8\x61\x72\xe5\x57\xb0\xe3\x92\xf9\xb3\x36\x5c\x76\xe9\x4f\x2f\x7d\xfe\x03\xc7\xe1\xa6\x96\x51\xa3\x67\x5c\x7f\xd3\x85\xeb\xc4\x0a\xff\xa3\xfd\xe0\xa1\xa7\x5e\x80\xe1\xc5\xb3\xef\xf1\x8c\xbf\xf7\x4e\xe8\xba\x6c\xdb\xd2\x2e\xf7\xbc\xc5\xb5\x6d\x1f\xb7\xd5\xbe\xaa\xa6\x16\xf7\xcc\x6c\xde\x3b\xfb\xea\x9b\x84\xa7\xb4\x7f\x6d\xff\xfe\xf6\xb9\x7b\xd7\x3a\xaa\x7a\x70\xdd\x3f\xd6\x7f\x84\x4b\xe0\x35\x2f\xa7\x2b\xae\x34\x12\xd6\x6f\xd5\x21\xe4\x73\xee\x8a\x5a\x93\x2d\x4e\xf4\x6d\x09\x36\x33\x20\xe6\x95\x80\xa8\xc8\x28\x25\xc7\x18\xaf\x84\x2a\xdb\x08\x24\x53\x0e\x14\x22\xeb\xca\x5a\xe2\x93\x2a\x24\x15\x84\xd3\x69\xc5\x4d\xfe\x81\xe2\x90\x54\x01\x6d\xb7\x89\x4e\x41\x8b\xd1\x8e\x42\x23\x06\x7b\x5e\x37\x3a\xa1\x06\xf2\x43\x91\xb5\x1b\x76\xcf\x9c\xf3\xc5\x1f\xfe\xf9\xf0\x82\x05\xb7\x77\x5f\xb8\xf8\xc2\x8b\x37\x36\xdf\x73\xfd\xe6\x79\x73\x16\xfc\xa8\xe7\x91\xa3\x6f\xfd\x0d\xca\x10\x76\x18\xab\xae\x9e\xfc\xf0\x53\x73\xfe\xd8\x52\x3b\xf6\x8c\xf6\x11\xef\x4c\x9f\x30\xf2\x8c\x86\xd6\x2f\xce\xda\x09\x20\xf0\xf5\x1f\x61\xd1\xbe\xd6\x82\xab\x75\x26\x02\x63\x1e\x8b\xab\xa8\xa2\x90\xcf\x99\x8c\x35\x1e\x5b\x5c\x35\xf1\x04\x8f\xc9\x63\x6d\x15\xa5\x4a\x54\x7c\x68\x8d\x54\x21\xc1\x67\x23\x6d\xde\x2a\x1b\x46\x3b\x14\x49\x08\x8c\x92\x0a\xab\xf0\x8a\xd4\x20\xba\x66\x44\x49\x75\xfa\x8a\xc2\x2b\xa9\x0e\x4f\xb2\xba\xa3\xbd\x7c\x4e\x58\x47\x05\xb9\x3d\x64\x18\xda\xa7\x3c\x03\x19\x45\x69\x5e\x73\xc7\xb5\x13\xe6\x4c\x7c\x62\x7a\xf7\x07\xbf\x7d\xe1\xe0\x8d\xb7\x3d\xa7\x7d\xa8\x7d\x71\xc9\xeb\xa9\x2f\xe7\x6e\x5b\xf1\xce\xa8\x09\x2d\xed\xcd\x35\xef\xcf\xb9\x73\xe3\x65\xb7\x45\x8d\x23\xf7\xe6\xfa\xea\x01\x59\x1b\xbf\x94\x5b\x0e\x5a\xd0\x5b\xd8\xa4\xaf\xcd\x5d\x5c\x5b\x93\x9b\xac\x4d\x31\xd1\xf1\xe7\x30\x95\x6c\xe6\x31\x28\x0a\x8b\x34\x37\xf0\x92\x9c\xb1\xd5\x12\x91\x7a\xfc\xd6\xc1\x86\x34\x8e\x4f\xaa\x6a\x63\xe9\x74\x5a\x15\x83\xe8\x0f\xc8\x95\xe9\xb4\xde\x43\x2b\x5b\x12\x5a\x51\x75\xf9\xf1\x2d\x59\xdc\x8f\xb3\x5f\x29\xbb\x9a\x17\xdf\x71\xed\xa4\xe9\x6b\x94\xee\xf7\xde\x85\x35\x53\xd7\xc4\x13\x23\xc7\x4d\xbf\x6e\xed\xcc\xeb\xfd\x5d\x57\x3d\xaf\xfd\x55\xfb\xfa\x82\x57\xf4\x65\x26\x13\x67\xbd\x3f\x67\x77\x78\x09\x3e\xb2\x67\x7d\xe7\x4c\x9f\x31\xf5\xe3\x5c\x5f\x1d\x8d\x5b\xb7\x72\xcb\x81\x04\x62\xe0\x66\x92\x57\xa9\x6e\x03\x89\xe5\x71\x18\x1f\x0a\xe0\xcc\x2a\xc4\x17\xe0\x96\xb2\x2d\xaf\xc8\x98\xb4\x07\x85\xea\x8a\x55\x54\x04\x6c\x03\x1b\x56\xaf\x16\x68\xf4\x5e\x21\x4b\x72\x8e\x75\x04\x43\x28\x6c\x57\xad\xe1\x02\xea\x30\xe0\x96\xe4\x0c\x90\xad\x28\xd0\x09\x49\xaa\xd9\x84\xc7\xe9\xa8\x4a\x10\x20\xc9\xaf\x03\x7a\x30\xaf\x44\x5d\x01\xc6\x55\x62\x19\x3b\x9c\x07\xcf\x87\x23\x5e\xfa\x64\xe3\x6a\xe6\x15\xed\xcf\x5f\xfe\x59\x83\x89\x4b\x2e\xbe\xe0\xaa\x45\x0b\x13\xcd\xf1\xe5\xdf\x9d\x36\x66\xf1\x83\x67\xc3\xa7\xe0\x44\x78\xf3\x9e\x8d\xab\xd7\x48\xe6\xba\x7d\x4f\xf6\xfd\xf5\x37\x8b\xaf\x9e\x3e\x21\x75\xda\x3b\x63\xc7\xb5\xa6\xd7\xfc\x11\xc7\x69\xb8\x86\xb6\x9a\xeb\x01\x4e\xb0\xed\xa4\x15\x34\xa8\xb8\xf4\xd2\x99\xea\xfe\xdf\xaf\x98\x01\x95\x91\x48\x8d\xa9\x04\xef\x34\xb0\x4a\x36\x4c\x69\x6c\x60\x45\x4c\xd7\x1d\xe6\xef\x13\x22\x20\x06\x3a\xc0\x85\x80\x08\x1e\xb5\x99\x30\x33\x2b\x5a\x5e\x65\x42\xf5\x99\x0a\xba\x47\xf5\x54\xf7\xa8\x9e\xe8\x1e\xd5\x92\xf4\xb2\x56\x92\xd5\x1a\xe4\x73\xdb\xa4\x2c\xb0\x85\xe3\x84\x13\x44\x45\x71\x8f\x52\x29\xa9\xc1\x6a\x32\xbb\x1f\xd0\xa5\x87\x3b\x07\x4a\x21\xc9\xc5\xc8\x1b\x0e\xa5\x89\x14\x78\xe4\xd9\x77\x93\xb6\x26\x22\x85\xb4\xf5\x93\x5b\xe6\xae\x1a\x65\x74\x2f\x78\xe2\x86\xf9\xe3\x3a\x46\x5c\xe6\xd7\xbe\x2a\xd1\x44\x9a\xb4\xf2\x4c\xaa\x51\xbb\x3f\x79\x57\xcf\xb4\x43\xcf\xbf\x00\x17\xbf\x36\xfe\x42\xd0\xff\xd1\x35\x55\x79\xd7\x8a\xaf\xe3\xba\x24\xd2\xa6\xcf\x6e\x20\xf2\xb4\x25\xda\xcb\x95\xa0\x69\x78\xe5\xa7\xe6\x82\xf2\x53\xcb\xff\x1d\xe5\xa7\x6f\x2f\xf8\x74\x52\xa1\x27\x00\xf1\xfb\xba\x0c\xe7\xde\x33\x69\xe6\x2d\x99\x28\x30\xda\x6c\xca\xe7\xdc\x1e\x3f\x56\xe8\xa2\xc2\xf8\xe0\x10\xe6\x9c\xaa\xc4\xa3\x94\x7e\x4c\xb6\xad\xb8\x25\xcc\xf3\x82\x91\x33\x66\x94\x71\x0e\x40\x39\xe1\x3b\x83\x2a\x3a\x8e\x81\x91\x54\x98\x45\xce\x67\xde\xa3\xb0\xfd\xe0\x1b\x8f\x5c\x70\xfa\x8d\x33\x97\x3e\xb5\x68\xe9\xb2\xd6\x69\xb1\x83\x71\x78\x74\xe5\x2b\x7f\xf8\xf4\x18\xdc\x75\x18\x4e\xcb\xcd\xfc\x34\x58\x77\xf5\x6f\x36\x2f\xba\xc2\xf9\xec\x1b\xc7\xdf\x98\xfb\x31\xd5\x0e\xd2\x5c\xdc\x0e\xae\x07\x78\x40\x18\xc5\x69\x3c\x65\xf3\x71\x25\x54\x7f\x21\x8a\xd1\x99\x7a\x78\xfd\xfe\xf3\x92\xb1\x34\x8a\x24\x45\x41\x8d\xe0\x95\xe4\x0c\xe7\xf2\x13\xa7\xa1\x54\xa1\x93\x98\x31\x9b\x1c\x78\x9f\x78\x3f\xa1\xe6\xa9\xc2\x69\xa9\xb7\x7d\x34\x4c\x11\x14\x71\x67\x0a\x86\xe1\x00\x35\x93\x98\x1d\x76\x34\xcd\xba\xf0\x2d\x58\x3d\xd7\x2b\x44\x27\x40\x17\xec\x3a\xbe\x37\xb1\x77\xd7\xd5\x1b\xdf\x0d\x55\x34\x76\x78\x3b\x27\x7f\xd9\xb5\x71\xfb\x26\xf6\x1a\xed\xb4\x2b\xd7\xac\xb8\x02\xbe\xfd\xcd\xa2\x57\xd6\xfe\xe4\xd9\xf5\x2b\xaa\xc3\x4b\x67\x4d\x9b\xd7\xfd\x43\xb2\xae\x59\xfd\x9f\x70\x0a\xe6\xc9\xc0\x68\x0b\xcc\x52\x64\x4f\xaa\x31\x53\x5e\x71\xb6\x29\xc1\x84\xda\x64\x25\x98\x8b\xaa\x43\xb9\x06\xb2\xbc\x06\x3c\x5e\x97\xf3\x91\x55\xa1\x2c\xa3\xa1\x0a\x5d\xee\x91\x34\xca\x1e\x94\x20\x7a\x9b\x32\x46\x13\x81\x05\xc7\x9a\x30\x2e\x4b\x02\xbe\x2a\x0c\x0d\x64\x25\x15\x8a\x38\xa5\xe8\xe8\x4c\xb6\x55\x32\xde\x64\x67\xaa\xf0\x7a\x11\x7f\x49\xd2\x8a\xd1\x30\x15\x43\x3b\xa8\x83\x3e\x63\xc2\xac\x59\x13\x67\x2c\x3b\x7f\x8c\x28\x8c\xdb\x3e\x75\xf5\x94\xf1\xed\x95\xa1\x96\x69\x93\x0f\xb4\x7d\xff\xd1\xab\x37\xd4\x8c\x99\xba\x38\x32\xb6\xbe\x1a\x9e\x1e\x0c\xd6\x8d\x88\x5c\xce\xae\xf8\x30\x34\x71\xe7\x8d\x6d\xb3\x76\xcf\x9e\x14\xf8\xc8\x9c\x98\xf9\xc9\xcd\xd7\xed\xd8\xb3\x66\xd9\xe9\x97\x2f\x3e\xef\x95\x09\x63\x8e\x2f\x08\x46\xc6\x75\x74\x4f\x58\x46\xf0\x43\x57\x6a\x2e\x2e\xc3\xf5\x80\x0a\xf0\x43\x62\x01\x42\x6c\x25\x12\x25\x2c\xdf\x10\xd4\x4c\x06\xa2\x95\x44\x95\x91\x75\x96\x2f\x7f\x39\x37\xc4\x33\xa3\xef\x3b\xfa\x03\xdc\x05\xc3\x7d\x16\x9b\x33\x9e\x95\xd0\x67\x46\x12\x6d\x25\x4d\x2e\x6b\x1a\xa8\x56\x09\xd3\x5a\x49\x65\xb4\x56\x9e\x74\x9a\x30\xde\x90\xf6\x14\xab\x83\x64\x07\xb0\x35\x41\x8c\xdf\x43\x46\x2b\x27\x68\xd2\x1e\xd7\xde\x99\xe2\x1a\x6b\xdc\xa8\x6e\xde\x3e\x80\x96\xe9\x58\x2f\x9c\xb5\x64\xff\xde\xc7\x00\xa4\x1a\x51\x11\x50\x03\xee\xa3\x5c\x83\x15\xbe\x64\xb2\x50\x9d\x88\x10\xde\x7c\x32\x17\x18\x84\x71\x94\xed\x67\x2b\xdc\x41\x63\x9c\x84\xec\x09\x94\x8d\x14\x78\x70\x0a\xfc\x17\x3e\x5c\x5f\xae\x10\x15\x6f\x1f\x50\xbd\x7e\xb4\x38\xf4\x89\x17\xe7\xab\x91\xe4\x2c\x67\x75\xd8\xd1\x71\x08\x4a\x19\x93\x80\x71\xd2\x15\xb2\x22\xa7\x81\x6a\x42\xc1\xb2\xa1\x12\x47\xfd\x03\xeb\x1e\x42\x49\xe1\xa3\x94\xd0\xa2\x58\xf0\x68\x1a\x63\xf5\xb7\x0d\x62\xb2\xa0\xb5\x8e\x11\x23\x2e\xfb\xfe\x20\x0a\x0b\xb4\xff\x51\xcd\x85\x6d\xd0\x04\xee\xa1\x3d\xeb\x40\x02\xf3\xd0\xea\x56\x68\xc6\x56\x68\xb2\xe5\x95\x26\x42\x17\xef\x26\x6e\xb6\x7c\xd1\x11\x51\xa9\xed\x53\x2b\x02\xc7\xd0\xaa\xb3\xde\x8a\x48\x2d\xe1\x53\xd6\x7f\xc2\xab\xaf\x6b\x92\xe4\x7d\x9c\xe0\x08\x84\xec\x84\x0c\x10\xaf\xba\x1a\x79\xe8\x50\x5a\x01\x12\xf2\xd3\x26\x59\x35\xd4\x7f\x0b\x0b\x14\x27\xd8\x53\x27\xb1\xc5\xc3\x0d\xaf\x3d\xba\x78\xd2\x19\x1d\x67\x9c\x2f\xef\x18\xce\x26\xf6\xbe\xa7\x7d\x47\xdd\x67\x9f\xc7\xbc\x57\x30\x0d\x60\xfa\xff\x0e\x00\xb3\x45\x70\x01\x0b\xf0\x80\xc7\x41\xc6\x8c\xac\x63\x22\x95\x77\x85\x4b\xe6\x20\x30\xa3\xa8\xca\x68\x49\x26\x55\x68\xcd\xab\x0c\xdf\xd6\xa6\xb8\x13\xaa\x83\xcb\xe3\xe2\x3b\x7b\x08\xbd\x2f\x59\x13\xc7\x1a\x49\xe3\xd9\x9c\xc0\x7c\xda\xac\xa8\x58\x91\x97\x94\xc5\x62\x65\xfe\xd1\xa3\xbf\xc7\x95\x79\xb3\x98\x65\xcc\x43\x80\xee\xcc\x62\xd6\x82\xbe\x67\xb3\x0c\x6f\xb4\xe8\xfd\x08\xce\x24\xc9\xaa\xc3\x4d\x78\x78\x04\x03\xe6\x90\x61\x8b\x10\xbc\x40\x49\x4b\x4e\x8c\x3f\xd8\x03\x9b\x17\xee\x8a\xef\xb8\x58\x7b\xe7\xe2\x9f\xeb\x73\x4d\x87\x49\xcc\xa1\x35\xc0\xc3\xec\x96\xe2\xac\x16\x04\x0b\xfb\x8f\x30\x5b\xb8\x1e\x20\x82\x1b\x01\x29\x2e\x9a\x4c\x79\x7d\xe9\x50\x91\x0a\xcb\x33\xe0\xe5\xd1\x49\x16\x83\x98\x57\x65\xba\xa4\xdf\x7e\xfe\x49\x01\x43\xc2\x60\x50\x21\xdf\x07\x54\x86\x47\x2f\x04\xfa\x2c\x90\x23\x12\xf8\x27\x26\xc6\x34\xd9\x0b\x45\x60\x32\x50\x92\x2a\xbe\xef\x24\xe5\x59\xe8\x7d\x10\x36\xef\xb4\xce\xe9\xba\xe0\xca\x9d\xf7\x6c\xfd\x5b\xfb\x12\xe6\x9d\xe3\x81\x51\xde\xee\xc8\x87\x1d\x6b\x00\x80\xfd\x4f\x01\xc0\x06\xb8\x1e\x60\x29\xf0\x9e\x12\xad\x37\x6b\x02\xb9\x2a\xfc\x60\xbb\x8f\x1e\x2e\x23\x01\x0f\x9e\x02\x3d\xfb\xac\xaa\x67\x37\xdd\x1f\x66\xd6\x86\x7f\x71\xfb\x03\x55\x77\xcf\x61\xee\x98\x73\xf7\xdd\x73\x8e\x5f\x3b\xe7\x6e\x64\x33\x00\x00\xfb\x43\xc1\x05\x7c\xe0\x4d\xc2\x8b\xa0\x38\x93\xb8\x0b\x93\x44\xe9\xbe\xc2\xb7\x65\xcd\xac\xd7\x18\x57\x45\x6b\x5e\x01\x6d\x8a\x90\x50\x0c\xba\xea\x1e\x1d\x6b\x54\x7c\xa2\xea\xb2\xc4\x69\x89\x1d\x23\xfc\x0c\x25\x1a\x7c\xbb\x8f\xfe\x0e\x9f\x12\x97\x98\xe5\x5d\x82\x33\xfe\xcc\xe8\x87\x8f\xbe\x84\xbd\xac\x53\xcc\x1a\x9d\x06\x67\x3c\x2b\xa3\x4f\x1e\xfd\x09\x37\xfa\x13\x19\xd9\x59\x32\xc9\xa2\x18\x51\x1e\x23\xa3\x35\xf2\x46\xd9\x5d\x78\x31\x9d\x3e\x49\x56\xd8\x34\x91\xe6\xb5\x8a\xb8\xd5\x8b\xdc\xb0\x15\x0b\xd2\x4b\xf8\x15\x74\x86\x59\x14\x20\x26\xf1\x8b\xc7\x86\x9d\x28\x22\xac\xda\xb9\xc2\xeb\xda\x08\x9b\x77\x56\x78\x27\xd4\x3d\x50\xbd\xe3\xea\x4a\xf7\x3a\xed\x9d\xfb\xdd\xfe\xee\x6a\xe6\xa2\xbb\x7f\xc0\x33\xeb\x8f\x87\x8d\xcb\xee\x7b\x44\x38\x7e\x1f\xb3\x5f\xb8\x1c\xdd\xb9\x11\x00\xd8\x59\x82\x0b\x48\x20\x08\x7e\x5b\xc0\x7b\x2a\x8e\x84\x6a\xb1\x27\x93\x39\x37\x9e\x0e\x55\x8d\x9e\xb6\x36\x25\x90\xc8\xb1\x64\x58\x94\x5a\x2a\x84\xc3\x3c\xab\x2d\x9f\x95\xad\x36\x63\x3c\x07\x88\xcd\x00\xa6\x38\x47\x3f\x59\x8b\x26\xab\x2c\x67\x7c\x2f\x5a\xca\x26\x66\x79\x9b\x80\x6c\x64\x15\xb3\x46\x2b\xb2\x99\xc5\x6a\xd0\x41\xa1\x82\x33\x9e\xf5\xa0\xcf\x0c\x6f\x13\x4a\x10\x48\x0a\xdf\x02\x73\x28\xdc\xf7\x14\x41\x14\x56\xb9\x68\x35\xc5\x4c\xb3\x22\xca\xdf\xd9\x49\x2c\x46\xda\x64\x24\x72\x19\x05\x49\xea\x13\xb9\x7d\x45\x6a\xf4\xb5\xb0\x79\xef\x4b\xe1\x17\xd7\x6a\xef\xac\x8d\xad\x5c\xd7\xdb\x56\xd7\x6a\xa9\xab\x9e\xc1\x46\xae\xf9\x5e\x94\xa9\xf9\xe6\x83\x87\x8f\xef\x65\xe6\x5c\xb1\xac\xaa\x32\x69\xae\xa9\xc3\xef\x23\xd0\x5c\xcc\x2e\x6c\xb7\x69\x00\x59\xcb\x64\xca\x63\xfc\x8e\xac\x73\x4d\xa2\x7b\x99\x85\xf8\x8a\xc6\x0c\x4e\x06\x80\x8b\x7b\xf8\x3e\xa5\xa2\x4c\x40\x35\x39\x06\xbc\x5f\xee\x76\x14\x5e\xd1\xf7\x0b\x87\xc2\x22\xbc\x00\x36\x6b\x3f\xb0\xce\x1a\xd9\x1a\xbe\xba\x79\xdb\xae\xfc\x94\xc9\xc2\x77\x8f\xdd\xd1\x1e\xec\x76\xfe\xc5\x2e\xad\x27\x77\x86\xc8\xdf\x2d\xb8\x40\x25\x78\x92\xde\x19\x95\xc4\x2b\xaa\x21\x23\x2e\x0a\x38\xd9\xbc\xce\x2c\x55\x85\x9f\xaf\x92\x70\xc4\x42\x18\x57\x19\x42\x40\xef\x21\x3a\xa4\x05\xe4\xc2\xee\xa3\x87\xf0\xd1\xae\x14\xb3\x6c\x25\xe3\x8c\x67\x43\xe8\x93\x55\xd9\x10\x71\x75\x95\xe8\x6e\x74\x88\xe9\x34\xa6\xa6\xcf\xda\x9c\x64\xfe\xcf\x83\xae\x09\xc5\x44\x4a\x0f\x4e\x1b\xa9\x67\x02\x49\x11\xd3\x4a\x48\xce\x08\x26\x8c\x0d\x65\x25\xcc\xe2\x82\xd9\xb5\x4a\xe4\xb3\xcb\x65\xc2\x59\x4c\x06\x75\x01\x96\xcd\x7e\xea\xa5\x1d\xda\x07\xbf\x78\xf7\x87\xd3\x7e\x39\xf5\xd1\xe7\x6e\xbf\x61\x63\x33\xbc\x4b\xf3\x3f\x23\xb8\xb4\x29\x2f\x6b\x63\xc4\x83\xbb\xb0\x5e\x36\x34\xc7\x93\x7b\xb6\x2c\xbd\xf6\x30\x5c\xf7\xcd\xed\x78\x8f\x96\xf6\x1f\x31\x20\xdf\x13\x05\xaf\x91\xb8\x1e\x8b\x2d\xe3\xca\x0a\x36\x4f\x96\xb3\xd9\xbd\xb5\xde\x64\x81\xf2\xd2\x31\x20\xae\xa2\xc1\x94\x62\x27\x5d\x7d\x14\x5e\xc4\x06\xde\xb4\x25\xde\xf4\x99\xd1\x4f\x7d\xee\x20\xf8\xe7\x12\x9e\xd0\x2c\xc3\x5b\x1d\xd4\x91\xd1\x9f\x4a\x02\xab\x08\x61\x8b\xaa\x0e\x93\xf1\x2c\x67\x25\xae\xc7\x65\xfc\x54\x96\x92\xf5\x4b\x72\x2f\x30\x39\x03\x41\x4c\x6c\x3d\x98\x1e\x73\x20\x51\x66\x0c\x47\x5f\x4b\xbd\x1b\x50\xf4\x75\xd1\x82\xed\x89\x85\xb0\x79\x93\xb4\xe8\xfc\x7b\xe2\x8b\x60\xf3\xdf\x3e\x72\x19\xb7\x1d\x7c\x2f\x6e\xda\xf6\xee\x86\xed\xb0\xf9\xcc\xcb\x99\x35\x38\x0e\xfb\xc3\x41\x78\xf0\xf8\xf2\x49\xad\xab\x3f\x7d\x9d\xf0\x64\x7e\xf4\xd1\x1e\x64\x3f\xcd\x85\xed\x57\x0f\xcd\x24\x16\xcd\x21\x83\x55\xd4\x7a\x93\xc8\x49\xfa\x92\x05\xc2\xd9\x81\x76\xf3\x63\x76\xcc\x7c\xd6\xee\xf3\x17\xb5\x3b\xed\xa4\xac\xaa\x1b\xb2\xf1\x54\x0d\x89\x42\xd8\x87\xf1\x97\x7e\x31\xeb\xf1\x7b\x9d\xf1\x6c\x00\x7f\x06\xd1\x67\x26\xe0\xf7\x96\x38\xd6\x60\x5a\xf1\xa4\x41\x2f\x32\xb8\x27\x10\xd4\x51\x58\x03\x7e\x2f\xd9\x86\x3a\xb2\x0d\x91\x5a\xba\x0d\xd5\xe9\xb4\xea\xf3\x4b\xb2\x1a\xaa\xd4\xb7\x41\x35\x39\xd3\x27\xda\x00\x18\x46\xe9\x2b\x2e\x2a\x9d\x68\x0f\x50\x28\x9c\x68\x3f\xcd\x78\x4b\x76\xd9\xed\xd6\x13\x6e\xc4\xb1\xde\xdf\xfd\xd7\xcf\xf7\x5e\xb7\x0c\xef\x45\x54\x73\x09\xef\x72\xcb\x41\x02\xfc\x1f\x1a\x1b\x47\xeb\x4a\xd5\x53\x49\xd7\xdb\x9d\x50\xfd\xe6\x42\xd1\x37\x61\xcb\x2b\x09\x12\x24\x46\x6d\xb8\x33\x53\x45\x12\x05\xb5\x95\x1a\x9f\x9a\xd9\xae\xd4\x89\x4a\xac\x4f\x89\xa2\xa8\xf1\x99\xd1\x47\xff\xf1\x5d\x6c\xe7\xa0\xa8\x84\xfa\x54\x39\x70\x4c\x91\xfa\xc0\x3e\x49\x0e\x86\x6a\x29\x24\x17\x96\xfd\x86\xed\x98\xa0\x73\x89\x75\x52\x86\xe5\x18\x42\x6a\xa2\x0a\xf1\x74\x5a\xa9\x92\xb2\x46\x93\xdb\x4b\xd1\xed\x28\xc5\xf0\xbb\xc9\x64\x22\x90\x50\xf2\x0c\xe5\x5e\x96\x33\x9a\x1c\xb8\x1a\x52\x42\x3a\x3d\x44\x70\x59\x8c\x2d\x4b\x22\x6e\x32\x88\xf8\x7e\xdc\x38\xa9\x77\xf1\x6d\x5b\xbd\x0f\x35\xbc\x8e\xe2\xcb\xce\xdb\x6a\x77\x88\x17\xf5\xdc\x5f\xbf\x10\xc5\xde\x17\xe1\x38\xb3\xe7\xed\x8f\x3f\xbe\xea\xda\xbd\x0f\x4c\x5b\x4c\x23\xcc\xbd\x38\xc0\xfc\xf4\x57\x5a\xa2\x18\x84\xc3\xfe\x08\x8a\xc1\x71\x5f\x4f\x25\x2c\xc3\x8a\x94\xc4\x2d\x5c\x22\xd2\x52\x99\x50\x19\xda\x76\x76\xe3\x5a\x40\x56\xb2\xbb\x8d\x71\x52\xc3\x4b\xe0\x3e\x48\x4d\x41\xab\x3d\x87\x2d\x29\xb4\xd8\x15\xbe\x4f\xf5\x07\x8e\x29\x81\x22\x37\x9f\x22\x8b\x8a\xb3\x4f\x91\x44\x45\xec\x03\x39\x5e\x74\x52\x01\x66\xb8\x8f\x17\x0a\xbf\x10\xeb\xba\x65\x62\x31\x49\xc2\xdd\x42\xa6\x52\x92\x95\x6a\x14\x66\x2a\x20\xad\x08\x72\xd6\x68\xb2\x13\xbd\x62\x8c\x57\x48\xc1\x21\xe5\x6b\xb1\x19\xff\xd0\x32\x72\xc4\x44\x2b\x34\x0e\x12\xb0\x5d\x13\xcb\x3e\x70\xee\xd4\x4f\x9c\x63\x47\x71\xef\x0f\x50\xb0\x3d\x9e\xfb\x79\x6f\x88\xc4\xa1\x51\x6a\x9b\x88\xae\x06\x50\xc2\x54\xee\xc6\x70\xb0\x8c\x88\xe5\xce\x44\x3c\x1b\x42\xa8\x97\x23\x36\x8c\x8c\x0a\xd1\xa1\x56\xb9\x2d\x6b\x37\x85\x8c\x98\x52\x4c\xa9\x48\xe0\x72\x4a\x74\xa0\x3b\xf0\x8b\x4a\xa0\x4f\xb5\x06\x8e\x29\x96\x3e\x90\xb5\x58\x89\x39\x60\xe1\x27\x6c\x96\x08\x3d\x74\x15\x52\x86\xe1\x58\x5c\xc8\xc0\x78\x2b\xbb\x84\x41\xf3\x40\x15\xdd\xa4\x02\x08\x24\x55\xae\x48\xa3\xb3\x96\x65\x39\x53\xd5\x60\x91\xdf\x01\xa4\xa6\x03\x0e\xd7\xe6\xfb\xbd\x3b\xac\xb3\x52\xad\x53\x97\x6f\xdb\x25\xef\xa2\x59\x8b\xae\xf3\x1b\xc1\x77\x71\xd5\xfa\x9b\x27\x9d\xc5\x7c\x58\xcc\x57\x70\x3e\xcb\xa7\xb9\x1e\x60\x03\x9b\xe8\x3b\x6b\xd4\x15\x8f\x15\x21\x89\xe7\x7e\x8a\x9c\x41\x7a\xa0\xa4\x8f\x00\x3d\x71\xf4\x5f\xa5\x8c\x83\x36\x51\xb1\xf4\x65\xad\x36\x0b\xe6\xbb\xb7\x94\x92\xab\x59\xac\x2d\x2d\x30\x03\xd1\xdf\x88\x55\x04\x9b\x24\xab\x8c\x29\x8d\xc1\x91\x46\x1d\x2f\xcf\x9a\xd3\x44\x34\x06\xca\xc8\x6f\x85\xa1\x1d\xb2\xd1\xcf\xe0\x1c\x18\xaa\x91\x2e\x80\x35\x9f\x69\x8f\x6b\x9f\x48\xd1\xf3\xb9\x9e\x6f\xfe\x0e\x2d\x53\xe1\x33\x5f\xef\x66\xed\x2b\xff\xa8\x95\x68\x55\xcd\xe6\x88\x16\x44\x25\x98\xab\xb3\x29\xe8\x75\xb2\xa0\x29\x9f\xf3\xba\x2d\x9c\x2d\xae\x7a\xf9\xbc\x1e\x66\xd0\xbb\xb3\x82\x2e\xad\x1a\xb9\x7e\x3b\xca\xb8\x2d\x2e\x2f\xee\xa0\xe9\xda\xf6\x41\xef\x40\x32\x23\xa6\x58\xa9\x4e\x85\x0d\xa9\x30\x69\x49\x94\xf3\x03\x34\xcc\x9c\x36\xfd\xc6\x1a\x6d\x35\xd3\x00\xd7\x4e\x3b\x73\xea\xea\x32\x66\x80\x17\xe6\x5f\x74\xe3\x35\xa1\xbf\x07\x2f\x5e\xb2\x9a\xf4\x69\xff\x2e\xec\xa0\xbd\xcd\x05\x94\x3b\xdc\x61\xcc\x93\x26\xa7\xdf\x4c\xc5\x38\xcd\x86\xa2\xf2\x4b\xce\x62\x77\xa3\xf5\x60\x76\xd6\x5a\x5d\xf7\x05\x1d\x54\xa0\xda\xb1\xdc\xa6\xb3\x22\x9d\x4e\xab\x66\x0b\xa9\x68\x1a\xa4\xd2\x8a\x5f\x2a\x6c\x28\xfc\x5f\x4a\x18\x40\x7a\x30\x6f\x2b\xb4\x64\x6e\x99\x6f\x65\x4d\x6d\x5a\x34\x0e\x7f\x99\xd0\xc6\xb7\xc2\xf7\x5b\xbf\xf9\x92\x9b\x31\xf7\xa5\x4f\x60\xe2\xbe\x69\xd7\x77\x11\xa1\x8e\xdf\xc0\x19\x4f\xcf\x48\x7f\xf2\xca\x27\x9f\xe6\x5d\xb5\x9f\xbe\xbc\x6f\xf5\xef\x6e\x7a\xe5\x86\x23\x80\x01\x93\xfa\x8f\x08\x1c\x9e\x21\x69\x02\xb3\x01\xa6\xf5\x56\xac\x49\xb5\xc2\x98\x57\x22\x94\xca\xa5\xc1\x5c\x28\x17\x50\x65\xd1\x3a\xaa\x21\xde\x02\xe3\x6a\x9d\x47\x92\x33\x56\x8e\x48\x28\x56\x38\x49\xa4\xd6\x20\x65\x80\x31\x98\x2e\x52\x36\x70\x32\xc1\x75\xd4\xc5\x8a\x7d\x67\x82\xd1\x77\x97\xb2\xec\x4d\xfa\x35\x5c\xf7\xd5\xb3\x30\xb8\xf3\xa6\x3f\xdf\xbb\x7c\xbd\xcb\x38\xe1\x91\xab\x1e\xfb\x39\xac\x58\x3d\x63\x5e\xa0\x01\x06\x93\xe6\x11\xa7\x2d\x5a\xbd\x5f\xd9\x73\x74\x2d\xbc\xf2\x4f\xf0\xc2\x17\x36\x69\xda\x13\x39\xed\xe8\xb6\x4b\x96\x5d\x7d\xe1\x81\x67\x76\x2c\xdf\xf8\xca\xe7\x93\xfd\x9d\x1d\x2f\xdc\xfb\x90\xba\xfe\x33\x7a\xde\x34\x17\xff\x02\xc6\xe2\x06\x40\x04\x7c\x49\x51\x07\x74\x79\x84\x19\x21\xa1\x38\x92\x0a\x9f\xc0\xaf\x52\x6d\xe9\xdc\x4f\x49\x39\x8c\x87\x71\xca\xf0\x80\x4f\x9f\xb9\xc4\xd3\x3c\x76\xf4\x63\x8a\x42\xcc\x72\x22\x4f\xba\x0a\x06\x07\xce\xe2\x76\x1f\x7d\x0f\xcf\x3e\xd8\xd1\xaf\x04\x88\xc8\x3b\xe3\x59\x2f\xfa\xe4\xb3\x15\xe8\x6f\x85\x3f\x84\xfe\xb5\xa0\x03\xa3\xce\x23\xe8\x6f\x19\x49\xe4\xcb\x84\x4b\x32\x76\x87\x40\x42\x12\x90\xb5\x4b\xde\x20\x19\x5d\xe3\x0c\x76\xc9\x5b\x11\x8c\x94\x8f\xae\x61\xca\x33\x33\x20\xf5\x16\xb6\x00\xff\x0e\xb3\x24\x48\x46\xce\x1c\x03\x3f\xbd\x4e\x3b\x03\x47\x33\x1d\xed\x75\xb1\x79\x4f\xc0\xf8\x9b\xf3\x60\xd5\xbc\x37\x7f\xbf\x5b\x3b\x7c\x70\xa1\xf6\x87\xc5\xaf\x7f\x0a\x93\x73\xe6\xdc\x75\xfe\x96\x59\xf0\x8d\xf3\x37\x9d\x3d\xff\x2c\xf8\xca\xf3\x30\xb1\xc7\x06\x9f\xd2\x66\x56\x7e\xf1\xfc\x0b\xda\x7b\x7b\xdc\x5a\x1d\xfc\xd8\x7b\xec\xdd\xcb\x6e\xb3\x31\xbb\x84\x25\x2f\x69\xf7\xd9\x96\xbe\x70\xcd\xc2\xb5\x0e\x94\xb3\xf7\xf6\x1f\x61\x47\x71\x3d\xc0\x01\x52\xa4\xca\x42\xa9\x7c\x71\xe2\x2e\x16\xe8\x27\x24\x4a\x3f\x81\x2b\x05\x06\xb3\x24\x67\x59\x68\xb1\x92\x5b\xc8\xe9\x29\x8b\x4a\xa7\x74\x35\x8c\xba\xee\xa7\x91\xa5\x98\xaa\xdd\xbc\xfd\xf5\x31\x66\x18\x91\x9e\x79\x1c\xfe\x03\x05\x9b\x40\xff\x6f\x3e\x80\xe7\x0e\xe7\x17\x2b\x3b\x38\x97\xa1\xfc\x11\x65\xff\x5d\xbc\x81\x8f\x1f\x3d\x5a\x98\x7e\x11\xfa\x78\xc2\x19\xc1\x02\x45\x68\x81\xaa\x60\xa2\x2d\xa0\x61\x9e\x0b\x96\x3d\xd7\x6b\x30\xae\xf5\x96\x3e\x18\xbb\xf7\xd8\x11\xf4\x60\xb0\xbf\x57\x73\x61\x5b\x84\xc0\x5b\x94\x99\x9b\xe5\x88\xb3\x50\x8c\x49\x74\xdd\xdb\x4c\x84\xfb\x8e\x92\x5b\x58\x8c\x06\x23\x1e\xb3\x56\xdc\x09\xc5\x93\x54\x2d\xb6\x7c\x81\x0c\x8f\x3e\x30\x87\x1e\xd8\xd3\x67\xa7\x24\x17\x1e\x31\x2b\x78\x50\xda\xeb\xc5\x9f\x15\xe8\x33\xe3\xf5\x94\x96\x09\x2a\xd2\x8a\x90\x06\x39\xc1\xe4\xf1\x56\x90\x08\x21\x2b\x98\xc8\x8f\xa4\x6a\xe3\xd6\x95\x22\x2d\x92\x22\x63\xb8\x90\x23\x0d\x54\x9b\x4c\x00\x66\x41\x89\x14\xa5\x58\x0c\x6d\x34\x48\x0a\x2c\x33\x45\xd9\xd5\x47\x63\xd8\xe2\x86\x69\x1a\xbe\xf8\xae\xdc\xf6\xb0\xb1\xa9\xd6\x78\x4b\xb6\xb8\x75\x5d\xe4\xde\xbb\xfd\xc6\xe0\x19\x3f\x5d\xbe\x17\xc0\xfe\x67\x35\x17\xc6\xc5\x3a\xc0\xb9\xa0\x24\x2c\x00\xa4\x76\x2d\x16\x74\x6d\xa4\x42\x2d\x20\x57\x7a\xc5\x61\x8a\x62\xa0\xd8\x5b\xa0\x0a\xed\xfa\x1b\x51\x2e\x79\xc3\xc2\x32\xd4\x2b\x3b\x01\xce\x29\x93\x20\x79\x47\x73\x09\x53\x74\xdd\x91\x6f\xaa\x01\x04\x0c\x7d\xa6\x10\x18\x4f\x72\x18\xb2\x77\x81\x84\xea\xa6\x1b\x47\xa1\x83\x28\x34\x76\xe2\x7b\x32\x80\x3c\xa2\x3b\x40\x3a\x3b\xac\xb4\x0f\xf0\x82\xc5\xe6\xa5\x7d\x90\x54\x39\xee\x96\x2d\x4d\xd5\x19\xf7\xd7\x65\x4f\x73\x83\xa3\x90\xb4\x4f\x3b\x8f\xdb\xad\x3f\xd7\xf1\x67\xbb\x2a\x69\xf2\x0e\x41\x00\x00\x76\x1a\xb7\x92\xf0\x3c\x00\x5a\x7d\x31\x25\x54\xce\x42\x78\x1e\x00\x01\xaa\xda\x0b\x83\xc1\xbf\x2e\x1d\x61\xb4\xa2\xa8\x00\xa8\xd0\x82\x47\x18\x2d\xba\xd1\x4c\x64\x8c\xa9\x50\xb4\x75\x16\x04\x06\x0c\x6c\x60\x67\xd3\x9b\x3f\x5b\x7c\x53\xd7\xb8\x91\x5b\x22\xf7\x33\xff\xe7\x37\x2f\x47\xff\xe1\xde\x73\x3c\x89\xe2\x95\x6e\xcd\xc5\x6c\xe0\x56\x02\x19\x5c\x01\x14\x21\xa1\x5a\xd1\x33\x38\x71\x65\xd1\x21\xe6\xb3\xb2\x83\x2d\x12\xc3\xca\xb6\x7c\x61\xea\xf7\x81\xa3\x7b\xc9\xb9\x06\x2d\x76\x05\xf6\x71\x28\x65\xb0\xa3\x9c\x21\x0b\xa0\x84\x87\x73\xa1\x0a\xf5\x7e\x02\x8b\x6c\x6c\xc4\x08\x14\xab\xa0\x77\x11\x68\x29\xa6\x00\x96\x31\xc0\x6e\xc8\x08\x1d\x9d\xe9\xee\x73\x2e\x6c\xdf\xfa\xb8\x5d\xd3\x34\x17\xf7\x8b\x60\xd5\x88\xb4\xfb\x1f\x15\xb6\xdd\xdb\x9a\xa6\x7e\x5d\xd4\xe6\xe3\x56\xe3\x18\xcb\x03\xee\x2c\x53\x28\x82\x44\xa1\xc8\xc3\xe7\x73\x56\x3b\x60\x6c\x71\xd5\x6a\x25\x85\xe0\x62\xd0\x25\xc3\xb8\xca\x97\x00\xb2\xa9\xd0\x47\x51\x72\xc8\x83\x62\x2e\x8f\x33\x9e\xb5\xa3\x4f\x36\x0b\xad\xa4\xe2\xa4\x8c\xf5\xab\xb2\x8d\xc0\xcc\x79\x49\x35\x62\x35\x5e\xbb\x95\x50\xda\x7a\x68\x7d\x43\x47\x9d\xe3\xc1\xff\x82\xc8\x54\xf4\x33\xf8\x69\xee\xed\x8d\xbb\x0e\x6b\xbf\x54\xb7\xcd\x5d\xff\xc8\x05\xd7\x4f\x9b\xb1\x9b\xeb\xf9\xfe\x9d\xb7\x2a\xed\x5a\x1a\x3e\xa2\x2d\x64\x96\xcd\x9b\x9a\xec\x2a\xac\x8f\x0f\x60\x1e\x10\x17\xd8\x56\x54\xe9\xb7\xf1\x04\x59\x8a\x47\xc9\x73\xac\x0b\x0b\xf3\x63\x0c\x93\x5b\xd7\x1d\x54\x18\x42\x63\x6d\x2a\x81\x6a\x53\x4d\x41\x05\x8a\x0a\xe8\x53\x18\x51\xb1\xa1\x55\x66\x59\x1b\xe3\x8c\x67\x5d\x36\x4c\x93\x0e\x58\x9b\xce\xd2\xab\x4a\x0c\xc1\x72\x99\x24\x95\x37\xa0\x25\xba\x6c\x78\xcb\x14\x96\xc0\x6a\x71\x69\x9b\xf4\x03\xb9\x48\x8c\x8e\x56\x46\x3f\x83\xcd\xf3\xee\x80\x73\xe0\x6c\x6d\xe1\x5e\xed\xe8\xdf\xf6\xfe\xf0\xbc\x1b\x1e\x7e\x98\xeb\xd1\x16\xc2\x47\xb4\x86\x29\xbd\x3f\x7f\xeb\xf0\xbc\xee\x55\x00\xf6\x3f\x45\x67\xab\x47\x80\x2d\x14\xef\xc2\x0b\x79\xd2\x4d\xf6\x08\x79\xa5\x25\xa1\x36\x08\xfa\x74\x45\x2e\x66\x03\x55\x5c\x3c\x6b\x8f\x01\x63\x5c\xf5\x39\xf2\x4a\x8c\xf0\xc3\x57\x39\xc8\xa8\x85\x1d\x90\xea\x9f\x2f\x26\xc9\xfb\x2c\x56\xbe\x26\xfe\xff\x50\xf7\x2f\xe0\x51\x55\xe7\xfe\x00\xbc\xd6\xbe\xce\x7d\x66\xcf\x25\x93\x64\x92\x4c\x26\x43\x12\xc2\x90\x4c\x32\x9b\x64\x32\x84\x6b\xb8\x5f\xc5\x88\x08\x88\x80\xc8\xfd\xae\x88\x80\x08\x88\x88\x51\xc1\x83\x80\x22\x52\x6c\x11\xf1\x46\x29\xdd\x7b\x66\xc4\x4b\xd1\xc6\x5a\xb5\x1e\x0f\xe5\x50\x8e\xd0\xd4\x7a\x2c\xb5\x1e\x9c\x53\xab\x1e\xb4\xb6\x68\x66\xcd\xf7\xac\xb5\xf6\x9e\x99\x04\xf0\x72\x4e\xfb\xff\xbe\xcf\x47\x92\x99\x49\xb2\xf6\x5a\xef\x5a\xeb\xbd\xbf\xbf\xb7\xae\x97\x37\xa6\xfa\x0d\x92\x33\x21\xb9\x0b\x68\x93\x83\x9a\x3a\xc9\xa9\xf4\x8d\x29\x15\x52\x1c\x54\x87\xb0\xf6\x56\xc0\x63\xfe\x62\xd3\xba\x73\x48\x24\x2b\x5d\xec\x17\x75\x7d\x5b\xab\x8a\x6a\x31\x8f\x6d\xb6\x99\x66\x5d\xa1\x5d\xc5\xac\x26\x9f\x30\xb6\xbe\xdf\xe8\xd9\x1b\xb6\xfd\xbd\xae\x1e\xfe\xfc\x4a\x0d\x2b\x0c\x5b\x4b\x0a\xc7\x38\xdf\xf1\x6d\x02\xd4\xfe\x64\x1b\x85\x20\x28\x00\x73\x00\x41\x7f\x32\xa6\x14\x1b\x71\x31\x42\x82\x02\x95\x65\x9f\x2a\xe5\x05\x3c\x96\x7f\xaa\xe4\xbb\x88\xed\xc8\x04\x2f\x38\x24\x2a\x23\xf4\x57\x1a\xf8\x8b\x06\x0e\x65\x93\x54\x90\x97\xda\xa4\x19\x8c\x79\x69\x05\xf9\x66\xa2\xbf\xf2\xc5\xdd\x34\xa5\x10\x7d\x98\xb5\x0f\xf9\x91\xea\xb3\xfe\x94\x7b\xcd\x57\x6f\x63\xb3\x30\x37\xdf\x32\x70\x00\x28\x25\x74\xbe\x62\x58\x15\x0a\x65\x59\x35\x88\x29\xd5\xe8\x89\x44\xb2\xa2\xd2\x1f\xce\xfa\x18\xf7\x5e\x78\x3a\xbb\x00\x53\x87\x5a\xe4\xbb\xa8\xb8\x2f\x2d\x0c\x2b\x72\x24\x3c\x45\x6e\x82\x56\xef\x76\x85\x58\x90\xe0\x4d\xee\x22\xaa\x44\xf1\x82\xd1\xe4\xf6\x14\x16\xe5\x29\x51\x40\x65\x4a\xb2\xfa\x38\x88\xa9\x4e\x03\x95\x81\x56\x89\xa4\xff\x8a\xb9\x32\xb1\xdc\x8a\x73\xf5\x62\x74\xd5\xed\x8f\x36\xec\x5d\x98\x5d\xf8\xdc\x1f\x34\xec\xdf\x9a\x5d\x3b\xb3\xee\x43\xf8\x11\x5d\x3e\xaa\xf9\x30\xdd\x4e\x0d\x63\x08\x8a\x90\x9b\x71\x70\x6b\x40\x19\x78\x84\xd0\xc0\x4b\x69\x60\x35\x53\x63\x88\x3f\xa3\x3a\x1c\xa9\x84\xc7\x41\xb0\xb5\xed\x84\x85\x7a\xec\x39\x77\x6b\xfa\x8b\x67\xf3\x63\x20\x2e\xdf\x45\xc5\x49\x62\x20\x4e\x97\x1e\x03\xa1\xaf\x68\xb9\x60\xb6\x46\xdd\x23\xa9\xd6\x12\x92\x4b\x4b\xe4\x7f\xae\x8d\x87\x28\x25\x80\xd1\x41\xf0\x92\xad\x34\x79\xd8\xab\x9b\xb5\x39\x2e\x9b\x6f\xf5\x16\xb9\x9f\x11\x26\xf5\x69\x1a\x3f\x49\xde\xfc\xb0\xed\x08\x35\x76\x77\xfd\x20\x35\x62\x06\xeb\x2d\xf1\x2f\xc2\x6c\x77\xff\x7d\xc3\x87\x76\x9d\x6d\x29\x22\xc6\x2e\x00\x0c\xda\xa7\xed\x7b\x21\x08\x82\x7d\x20\xce\x92\x7c\x51\x87\x2c\x6b\x90\xb9\xaa\xab\x3c\x12\x51\x0a\xc2\xc9\x12\x1a\x35\xb0\x86\x55\x83\x51\xb7\xa5\x74\xdc\xc8\xca\xac\xa7\xe4\x18\xe1\x4c\xe5\xc4\x53\xc2\x63\x0a\xd8\x48\xea\x4f\xb9\x23\xc1\x95\x63\xf5\xdc\xe5\x48\x38\x5c\x76\x5a\x1a\xa8\xa5\xfb\xd8\x1d\xae\xf2\xbc\x9d\x0f\x94\x50\x6b\xd2\xca\xd2\x72\x19\x03\xad\xd6\x87\xfd\x9a\x5a\x60\xfe\x01\x97\x45\x6a\xcc\xd0\xf4\x85\xc1\x30\x58\x21\xa0\x7d\xcf\x3f\x1b\x82\x5c\x76\xd3\x33\xe0\xe1\x8a\xbd\x0d\x3f\x7f\xec\xb6\x07\x8f\xf9\x4b\xaa\xfa\x9b\x2d\xe1\x01\xa3\xd0\x27\x77\x3d\xc8\xbd\x45\xf7\xfe\xeb\xd1\x3f\x3c\x72\x70\xdd\x92\xe2\x0a\xb9\x69\x60\x7f\x3d\xd6\xe4\xe0\x67\x83\x42\xb0\x1d\xc4\xbd\xba\xba\xac\x5a\xb4\x36\x2e\x49\x00\xbd\x96\x6c\x99\x14\xb6\x28\x8b\xc8\xa1\xb0\xdb\xf3\x43\xf5\xbf\x20\x24\x60\xea\x6c\x0a\xdb\xc1\x67\xa5\xa8\xca\x4a\xf4\x04\x50\x59\x4a\x4e\x80\x9d\xc7\xd6\x9b\x96\x2e\x0d\xb4\x74\x69\x48\xba\x79\x89\x84\x41\x5b\xe8\xda\x1b\xa3\x01\x7d\xd3\x75\x4f\x87\x6c\x67\x82\xd1\x06\xe8\xbb\x45\x9c\x3a\x8c\x04\xed\x2c\xab\x1e\x29\x79\x7d\xcb\x6b\x91\x4f\x3e\x64\x7c\xc5\xbe\xb1\xc1\x73\x8d\x1b\xb6\xca\x03\xd3\x1f\x3e\x74\xcd\xc7\x9f\x90\xb3\xed\x44\x6e\x82\xc7\x55\x08\xb6\xd1\x9c\x2e\xd5\x22\xa6\x14\x36\x12\x37\x5a\x4c\xa1\xc4\x10\xa3\x68\xa4\x15\x0e\x4a\x41\x58\x95\x8c\x29\x2d\x4d\x41\x61\x22\xa4\x00\xcc\x1a\xc9\xae\x50\xab\x14\xe2\x14\xa6\x8e\x57\xd8\x0e\x4e\xb5\xfa\x2e\xf2\x8a\xa5\x83\x05\x2a\x63\xc5\x5a\x02\x6b\xd1\x0a\xbb\x80\xe4\x8c\x73\x42\x01\x59\x9e\x44\x6b\x61\x15\x8b\x44\xfa\x52\x63\xc6\xc5\x6b\xe7\x39\x78\x99\x9e\x34\x4e\xeb\xd9\xbd\xb9\x46\x34\x67\x85\xa9\xad\xb3\x6e\x7e\xf4\xe1\x7f\x49\xd5\x0e\x63\x2f\x10\xd4\xad\x2e\x1b\x69\x40\xd3\xb4\x89\xc4\x94\x33\x1f\x73\x9f\x91\x7c\x8b\x72\x70\x92\x46\x56\x09\x24\x02\x8d\x9f\x70\x22\x29\xe1\xb7\xb1\xd6\x50\xdc\x5c\xe8\x97\x69\x64\x39\xce\xf0\xc6\x48\x24\x12\x07\x10\x2f\x1f\x38\x8d\xb4\xb6\x43\x0b\xc0\x16\x91\x00\x2c\xb5\x00\x68\xfb\x35\xad\x9e\x3f\xcf\x2f\xa8\xdb\x9e\xac\x43\x29\x24\x3e\x6f\x7f\x87\x52\xe8\x48\x30\x85\xac\x2b\xa4\xf8\x1d\x09\xde\xcf\xd1\xd8\x72\xa1\xde\xeb\x52\x2d\x62\x69\xb1\x20\x27\x29\x3e\xd2\xff\x5d\xb0\xd9\x1d\x65\xf8\x7e\x1b\xa4\xb8\xd1\x62\x8d\xe9\x38\xd9\x09\xbb\xc3\xe3\xa3\xda\x72\x7e\x9d\xbd\x5e\xf6\xd2\xd8\xaf\x29\xca\x13\x97\x75\x40\x70\x84\x76\x4e\x87\xb5\xd3\x61\xdb\x74\x58\x3b\x63\x5f\x68\xef\x42\xad\x8f\x96\x55\x84\xde\xa5\x23\xd7\x87\xd1\x0b\x6e\x98\x7a\x13\x1e\x45\x6d\xf8\xdf\x9b\xc8\x7b\xf2\x83\x27\xf7\x07\xd6\x06\x77\xac\x6f\xdf\x32\x99\xfa\x03\x87\x67\x3e\xe6\x47\x73\x33\x41\x19\x58\xa8\xd9\x47\x56\x43\x8a\xea\xfd\x2e\x59\xe5\xc4\x14\x69\x06\x49\xdd\x41\x24\xe6\x4e\xcd\xf3\x22\xcd\x1d\x64\xc2\x1b\xcd\x72\x7c\x8c\x64\xa4\x26\x04\xa7\xab\x84\xf4\x55\x70\x92\x06\x00\x9c\x55\x72\x26\x80\x89\xb2\x31\x5e\x52\x45\xa7\x56\x88\x14\x0d\x92\x36\x0a\xba\x0f\xa2\x3a\x1a\x10\x83\xb4\xa5\x42\x45\xaf\xe1\xed\x8f\x7c\xde\xc0\x04\x22\x0f\xec\xbc\x63\xd1\xfd\xcf\x2e\x6c\x80\x5f\x36\x74\x8d\xbe\x06\xfd\x04\xbd\x7f\x1e\xa5\xe0\xee\x5d\x17\xe6\x7c\x78\x6e\xd2\x47\x3b\x16\xae\x7e\xf3\xd0\x53\xbb\xcf\x7d\x38\x42\xb9\x0e\x7d\x81\xde\x4e\x01\x08\xd6\x64\x3e\xe6\xce\x12\xdf\xe6\xe3\x20\x1e\x20\xc8\xe7\xa6\x6c\x8c\x3d\xee\x25\x18\x1d\x59\x06\xa6\xc5\xf8\x48\xd9\x15\xe9\xe2\xcc\x86\x49\xac\x4f\x67\x68\xe8\x0b\xe5\x32\x71\x8d\xdd\x17\x76\xe8\x71\x0d\x5b\x87\x5a\xea\xbb\xa8\x94\x74\x80\xe7\x18\xde\x6a\x2b\x29\xd5\x5d\xeb\xf9\xef\xa8\xe8\x76\x9a\x24\x67\x1c\xd0\x4c\x2d\x96\xb6\x66\xcc\x86\x21\xa8\x40\x8b\x52\xf5\x59\xbf\xe3\x04\x41\x6b\x8d\x63\x33\xac\xdd\x6c\x99\x3e\x73\xc9\x9d\xa5\xfd\xb9\x50\x65\xa4\x69\xe9\xdc\xad\x0f\x99\xfa\x57\xed\xfa\xf4\xf0\x7b\x9f\xc0\x15\x23\x46\x32\x73\xd3\x7b\x5a\xea\xa6\x4c\xbe\xef\x7e\x68\xab\xec\x53\xe7\xfc\x30\xb0\xab\x3d\xd2\x0f\xfd\xcf\xb1\x77\x96\xbf\x45\xf1\x13\xd8\xa3\x24\x76\x5f\xdf\xbd\xeb\xf5\x77\xc7\x4f\x08\x12\xfc\x84\x19\x70\xf8\x7d\xa8\xb3\x56\x30\x0d\x29\x44\x67\xb9\x99\x5f\x1f\x64\xc6\xc6\x8e\xaa\x75\xe9\xa3\xb4\xb6\x67\x1f\x00\xfc\x69\x6e\x26\x28\x01\x33\x35\x0d\xde\xec\xd6\xfd\xa4\x46\x1a\x67\xf6\x9c\x49\xf2\x34\xe3\x8b\x89\x28\x3c\xad\x2b\x31\xd3\xb0\xb2\xca\x63\xeb\xb7\xb0\x88\xc0\x58\xc5\x8d\x0e\x77\x8c\xf6\x43\x32\xd9\x75\xa8\x90\x38\x6f\x2f\x24\x3e\x2d\x3c\x2b\xb7\x48\x80\xde\x5c\x01\xb6\x5f\x34\x68\x83\x22\x1b\x90\xfa\x45\x83\x82\xc8\xce\x67\x9c\x70\xac\x60\xb2\x5c\x57\x96\x82\xc3\x65\x74\x9e\x33\x1b\x9d\x23\x9d\x1f\xa1\x17\x4d\xa6\x31\x75\xef\x72\x33\xd3\x7f\xff\xc1\x8b\x7f\x1b\xc3\x94\x7c\x7d\x10\x7e\x76\x6a\xf3\xd0\x5f\x54\xa5\xcf\x33\x45\x1d\x8b\xce\x2f\x41\x0e\x00\x33\x3b\x00\xe0\x8e\x0a\x7e\x50\x90\xc5\x09\xb3\xca\x8a\x81\xb4\x78\x22\x36\x87\x8d\xd8\x1c\xc4\x15\x6a\xb5\x69\x10\x84\x06\xa0\xc3\xa5\x69\x11\xd1\x20\x74\x06\xb2\xd9\x67\x94\x7e\x36\x28\xc2\x9b\x99\x67\xe2\x30\x32\xb5\x65\x50\x74\xd2\xc6\xfe\xc5\x4f\xa0\xce\xa8\xc5\xe0\x6e\xe8\x8d\xba\xb8\x77\xe1\x70\xd7\xa7\x96\x6b\xe7\xd5\x7f\xfd\x2a\xbc\x30\x3f\xd9\xb0\xa5\x2d\xfd\x15\xbd\x97\xf3\x01\xe0\x5e\xe7\x66\x02\x03\xe8\x47\x11\x50\xe3\x00\x92\x0d\x84\x8a\x31\x8b\x5c\x66\xca\x22\x97\x41\xda\x04\xf4\x12\xf4\x52\xd7\x7c\xd8\xb4\x03\xc6\xe0\x8d\xe9\xb3\x53\xd1\xe9\xa9\xdc\x4c\x34\x15\x3e\x93\x1e\x8e\x66\xc2\x83\xdd\xf1\x81\x0a\xb1\xfd\x5a\x78\x49\xef\x09\xac\xf5\x09\x54\x22\x78\xce\x24\xcd\x44\x87\x27\xe1\x41\x33\xde\x34\xa6\x30\x96\xe7\xa6\x28\x94\xe2\x66\x3b\xa9\xd5\xba\x62\x4f\x8a\x6e\xae\x8a\xa6\x68\xf7\xbe\x14\x93\x84\x31\x0d\x44\xd3\x16\x2a\xf5\xbe\x14\xf7\x68\x5a\xf5\xea\x42\xf9\x27\xb4\x66\xeb\x54\x66\x22\x37\x91\x9b\x09\xbc\x20\xa0\xfb\x81\xb1\x3d\x55\x68\x20\x68\x92\xfa\xbc\x93\x7e\x8b\x93\xb3\x86\x92\x7e\x0d\x46\xb2\x22\xac\x94\x9c\x49\xda\x73\xb9\x93\xf6\x12\xbc\x75\x3c\xf1\x9d\x3a\x69\x0c\xc2\x2f\xe9\xe1\xfd\x6e\x93\xd6\xe1\x04\x85\x10\x14\xc4\xea\x68\x65\x36\xbd\x3e\x7f\xf2\x0b\xd6\xdd\x76\xdb\xa8\x9b\x6e\xf9\xf3\x1f\xb7\x0d\xac\xbf\x6f\x30\x9c\xd6\x30\x63\x86\xaf\xb8\xef\xb5\xda\x32\x0e\xac\x6c\xda\x34\xff\xe0\x33\x33\x27\x8f\x58\x96\x8a\xd4\x7a\x4a\xc6\x01\x98\x79\x0a\x39\xb8\x5a\x82\xcb\x34\x0c\xd0\x02\x1d\xab\x81\x04\x53\x58\x96\x56\xc3\x09\x67\x54\x37\xad\xb9\x56\xdd\x82\x76\xe0\xd8\x42\xaa\x1c\x5a\xa5\x38\x90\xdc\x14\x11\x54\x71\xf4\xe8\x13\xa6\x03\x36\x69\x51\xf9\xe9\x23\x7f\x7e\xd5\xc1\x57\xee\xbd\xa3\xbd\x16\xee\x40\xbe\x06\x12\x8f\xff\xf1\xeb\x3f\x40\x7f\xfc\xd9\xd9\x83\x7b\x7a\x37\x3d\xbd\x7d\xd1\xea\xb3\x70\x73\xea\x97\x68\xb0\xe3\xc4\x01\x12\x88\x27\x74\x1e\x8d\xdc\x64\x7e\xe5\xa0\x0f\xd8\x08\xe2\x0e\x48\xfd\xed\x4a\x59\x58\x29\x96\xd5\xa0\x40\xfa\xf0\xb0\x5a\x4d\x1c\x38\x93\x0c\xd0\xdb\x1d\xa0\x46\x5d\x81\xd6\x79\xc7\x10\x90\x9c\x43\x8c\xac\xc5\x6a\x77\xb8\x4a\xca\x2a\xb5\xee\x1f\xb6\xe2\x2c\xb2\x60\x21\x56\x7e\x7b\x4b\x2a\x10\xa8\x7f\xcb\x10\x53\xec\x52\xdc\xec\x22\x79\x06\x0e\x2c\x30\xb1\x39\x47\x72\x89\x7b\x2e\xcf\x21\x7a\xc5\xaa\x6a\x9a\xc6\x2a\x47\xa2\xa4\xaa\xe3\x85\x5f\x3e\xb3\xfc\xa5\x1b\x82\x7b\xef\x5a\x95\xb7\xda\x43\xff\xf6\x64\xf4\x60\x2f\xe9\xf1\x5f\xbe\xfe\xfb\x77\x1e\xdf\x3e\xa5\x69\xc3\x55\x2d\x23\x5f\xf9\x97\x27\xae\x5f\x38\x72\xce\xd2\x3b\xcf\xc2\xe9\xa9\x5f\xa2\xf9\xee\xdf\x3d\x86\xfe\xf6\x48\xdb\x8a\x41\x05\x93\xf7\x3d\x35\x5b\x6e\xbd\xa6\x11\x40\x70\x08\x00\x2e\x2c\xf8\x81\x0b\xac\xd5\x78\x82\x4b\xc6\x46\x81\x05\xf3\x04\x77\x5e\xed\x2e\xa9\x35\xc2\xaa\xa0\x9e\x05\xff\xf8\x85\x77\xf2\xdd\x3c\x2e\x07\xb6\x06\x54\xe8\x24\x9e\x14\xa7\x9e\x25\x94\xb5\x02\x38\x49\x15\x89\x47\x45\x24\x1f\xd9\x63\x59\xfd\x4f\xd6\x31\xa2\xf4\x62\x0e\x46\x64\x0f\x1d\x38\xf9\xe7\x59\x63\xee\x54\xe7\xfe\xe5\xec\xab\xa9\xaf\xce\x6d\x61\x3e\x1b\x7e\x66\xc3\x98\x69\xb3\x3b\x37\xfc\xe6\xc7\xaf\xa2\xdf\x8d\x4f\xef\x04\x10\xcf\x97\x9b\x23\xf8\x81\x07\xcc\xcd\xc6\x40\x15\x53\x58\xe5\x34\x90\x2a\xe7\x19\x55\xb2\xa6\x14\xa0\x95\x9e\x64\xb1\x3e\x1e\xb9\xf0\x14\x9d\x79\x7e\x6c\x53\x75\x10\x8c\x2d\x87\x4b\x17\x68\x26\xa7\xe4\x54\x81\x81\xfa\xb9\x45\xad\xca\x08\x6f\x52\xd6\xcc\x26\x9e\xee\x78\xfb\xc5\x27\x96\x1e\x5b\xb2\x6d\xf7\xba\x85\xf7\x3c\xba\xfd\x00\x3a\xbd\xf5\xee\xbb\xb9\xd0\xbe\x3f\xdd\xd6\x3c\xa2\x73\xf6\xbd\x8b\x97\x3e\xd3\x98\x76\x32\x2b\xae\xfe\x1d\x80\x99\xb7\x32\x1f\xb3\xeb\x04\x37\x70\x83\xe5\x5a\x74\x87\x36\xd7\x23\x30\xa4\x1e\x0a\x49\x62\x4d\x29\x66\x87\x62\xcf\xab\x08\xb2\x77\xf3\x8d\xbc\xfc\xad\x60\xa3\x40\x65\x9d\xb9\xf6\x82\xf6\x18\x29\x28\xd5\x5d\x05\x9a\x9b\x1e\xe0\x13\x75\xdf\x43\xb7\xcf\xbb\xef\xa1\x9d\x07\x60\xed\xd6\xad\x5b\xd0\xfb\x7f\xbf\xf5\x97\x8b\x7f\x77\xd3\xfd\x4b\x17\x3f\xd3\xcc\x7c\x9e\xde\x7e\xed\xd9\x9d\x29\x74\x61\x00\xe9\x7d\x88\xdc\x5c\x03\xa9\x4f\x6b\x01\xd9\x94\xf3\x2c\xb0\x46\x51\x36\xdd\xbc\x18\x86\x34\xcc\x0c\x37\x7e\x78\x1c\x88\xae\xbc\x82\xdc\x28\x41\xcc\xd0\x4a\x93\x18\x8f\x43\x8e\x0c\x86\x98\x4b\x32\x35\x71\x38\xe0\x37\xc7\x76\xcd\x68\x5a\xd0\x7a\xcb\x0b\xb7\xbc\x30\x6b\xce\xd0\x7d\x3f\x3e\x7d\xda\x07\x87\x33\x2c\x94\x46\x7f\xe8\xad\xf8\x1d\xba\xe1\x33\xf4\x65\x43\xe0\xcb\x49\xd0\x00\x74\x0c\x7c\xfe\x04\xc1\x4d\xaf\x06\xcb\x2e\x83\x9a\x9e\xac\xf4\x9b\x31\x6f\xac\xe4\x80\x2b\x57\x84\x9e\xeb\xdc\x91\xac\x70\x80\x52\x2e\x94\xd7\xbc\x83\xd4\xae\x54\x94\x90\xc0\x5f\xa1\x44\x91\xef\x24\xc9\xa9\xda\x40\x2c\xa6\x16\xfa\x25\xa7\xea\x11\xbf\x0d\x2d\xdd\x9b\x4b\x9d\xac\xfa\x46\xb0\xf4\xa7\x96\xdc\x38\xbc\x6d\xf9\xb4\x31\x6d\xdf\x82\x94\xee\x9d\xbe\x74\xfc\x88\xeb\x96\x8e\xd3\x62\x9b\xd3\xb9\x55\xc0\x4d\xb8\xd5\x7a\xed\xfc\x14\xf2\x9a\x1c\xeb\xcd\xa7\x92\x01\x3f\x96\x07\xb4\x26\x89\x30\x2c\xaa\xe0\xd3\xfe\xf6\x34\xcc\xa9\x88\xf8\x60\x91\x44\x8b\x30\x09\x77\x62\x06\xe6\xf3\xe0\x55\x3b\x03\xbd\x49\xdf\xdb\x4a\x2d\x31\xcd\x5f\x88\x8f\xbf\x8d\x54\xe1\x53\xf4\xb2\xde\x3d\xc2\x9f\x1a\x7a\x59\xae\x96\x95\x72\x2f\x31\x57\x9d\x35\xfd\x51\xe8\x7b\xf1\x67\xbf\x5d\xbd\x61\xda\xf4\xd5\xef\x3e\xf4\xc1\x57\xb0\xf6\xfa\x69\xd7\xce\xb8\x71\xe5\x2e\x26\xf4\xd6\x75\xb3\x5a\x1b\xaf\xdd\x0e\x95\x7f\x85\xc3\x8e\x3d\x71\xff\xf2\x2d\x25\x86\xa2\x5b\x26\x2f\x7e\x62\x5a\xea\xcd\x45\xab\xa7\x0c\x6f\x1d\xea\xff\x64\xe4\x88\xfa\xc6\xbb\x00\x60\x40\x43\xe6\x63\xee\x66\x52\xbb\x5e\x05\xee\xd4\x30\x3e\x0a\x84\x14\xc9\x74\x50\x4b\xc4\x54\x32\xd0\xcb\x61\xb2\x92\xf2\x4f\xbd\xb2\x4e\xc3\x1b\xf0\x13\xe0\x37\x2b\x71\x73\xf8\x29\x1b\x2b\xd2\xaa\x7d\x7b\xc3\x90\xea\x12\x25\xa7\xca\x72\xb1\x98\x5a\xe4\x97\x9c\x49\x47\x81\xa9\x82\xb6\x02\xe8\x55\x40\x6f\x50\x40\x8a\x73\x56\x12\xb3\x2f\x71\xaa\x62\x91\xa6\xd9\x0f\x26\x50\x9d\xbd\xe4\x08\x47\xb4\x79\xba\x78\xed\x10\x78\xdc\xb4\xe4\xae\xe1\x81\xbb\x99\xe9\x37\x41\xeb\x5f\x53\x20\x83\x9e\x40\x27\x5f\xff\x0b\x0c\x5f\x3d\xf8\x87\xc9\x15\x73\xa7\xcf\x7b\x35\x5c\x1b\x5a\xb5\x1a\x06\x6f\xde\x51\x68\x2e\x5d\x39\xf1\xa0\xf2\xe5\x59\xf4\x3c\xda\xf1\xec\x4f\x9a\x07\x42\xf0\xde\xb2\xdb\x06\x0f\x58\x7a\x7a\x12\xad\xf9\xe0\x57\x08\x7e\xd0\x1b\x5c\x03\xe2\x55\x80\x42\x09\x68\x60\xf8\xc6\x54\x32\x50\x51\xa5\xed\xb7\x62\x0f\xe3\x2b\xa9\xe7\x3a\x15\xdb\x49\xea\x12\x50\x03\xa5\x74\x19\x15\x12\x96\xa8\x05\x4e\xc5\x15\x53\xed\x58\x0f\xb6\xe6\x05\x81\xb3\x4e\x07\x3b\x73\xe5\x0a\x90\x11\x43\x5c\x7d\x1e\xbb\x67\xdc\xc0\xfa\xe8\x8d\xc5\xe5\xdf\x50\x0c\x62\x9e\x72\xfc\xc9\xd2\x94\x73\xd5\x23\x7f\xba\xa4\x28\x84\xe6\xce\xbf\x4d\x74\xf5\x23\x3d\x3a\x6f\xc2\xcb\x76\xde\x14\x69\xe7\x4d\x0b\xf5\x16\xdb\x53\x09\x33\x03\x73\xde\x7d\x33\x75\x1f\x6b\xd1\xd3\x84\x28\xf0\x06\x62\xc0\x62\x8d\x56\xa4\x4a\x7f\xbe\x0b\x32\x67\xd0\x7e\xaf\x2e\x9c\x80\x3a\x90\x03\xda\xbf\xca\x4f\x61\xfd\x0d\xf0\x86\xe9\xb0\xf6\x13\x74\x7a\x36\x7a\x6a\x0e\x37\x13\x1b\x9e\x5f\x1f\x84\x27\x90\x0c\x00\x8b\xf6\x6b\xf8\x4c\x76\xd2\xaf\xe2\x27\xba\xc7\x09\xdb\xe8\x5e\xea\x71\x32\x15\x44\x22\xd4\xf8\x14\x64\xc5\x1a\x4e\xba\xa8\xe7\xa9\x5b\x17\x8b\xa4\x83\x26\xa7\x3a\x72\xd1\xe1\x62\x7c\x94\xb5\x06\x16\x64\x5d\x7b\x2e\xfc\x88\x2c\x87\x27\xc0\x2c\x82\x43\x31\x91\x38\x1d\x57\xc0\xd3\xdc\x6f\xd1\x24\xe0\xb5\x70\xa2\x29\x1b\x0d\xe0\x1d\x64\xef\x55\xa1\x58\x72\x26\x0c\x46\xad\xef\x85\xd7\xa5\xa5\xa0\x12\x27\x14\xb5\xc4\x73\xbe\x27\xe2\x7a\xca\xc7\x69\xda\xff\xfc\xb3\x35\x9f\xc2\xba\xcf\x1e\xa9\xd8\xdb\xf7\x97\xd4\xf9\x34\xc5\x63\x09\x0f\x18\x05\x2f\x68\x19\xe2\xc4\x09\x35\xf3\xeb\x83\x3f\x3c\x7c\x68\xdd\x92\xe2\x8a\x45\x03\xfb\x0b\x03\xf2\xf2\xc4\x33\x3f\x44\x6e\x6e\x21\x89\xdd\x6a\xd1\x10\x12\x08\x51\x05\x91\x14\x52\xe8\x91\x54\xe3\x19\xba\x9b\xb9\xb4\x13\xa9\x7b\xe2\xbb\x1e\x9c\x33\xd3\xc4\x77\xc1\x15\x4a\x98\xf0\xd7\xb8\xc9\x98\x97\x86\xab\xf0\x31\xa0\xf2\x26\x02\x32\x6e\xd2\xb4\x12\x83\x51\x72\xc6\x39\xab\x8d\x56\x7b\x61\x7d\x84\x23\x59\xcb\x41\x23\x0c\xb8\xb4\x12\x91\xc1\x30\x08\xe7\xc0\xff\x41\x7f\x82\x93\x8e\xad\x1b\x03\x6b\xd1\x61\x74\xfa\x80\xb5\x97\xd5\x88\x06\xc0\xbf\x33\xf3\xd1\x8c\xd1\x70\xc6\xc5\x63\xcc\xc7\x43\x57\x84\x50\x25\xd0\xcf\x37\x1b\xe5\x66\x02\x1e\x8c\xd0\x6c\x44\xd6\x40\x43\x20\x24\xad\x55\xd0\xa3\x1e\xaa\x78\xa5\x50\x07\xdb\xc1\xaa\x80\xed\x76\xf0\xc4\xca\xbf\xc0\xda\xe3\x30\xd9\xc0\xcd\xec\xda\x96\xd2\xfb\x6a\x92\x1a\x3f\x3f\xa8\x05\xa7\x34\x89\xdc\xc7\x48\xa2\xb9\x6e\x39\x5b\xcb\x5f\x47\x78\x41\xb9\x9d\x34\x5c\xc2\x52\xce\x6d\x25\x3d\xc1\xc9\x93\x3b\x3e\x5f\x4c\x15\x09\x0f\x56\x81\x54\xb7\xcb\x40\xa1\x7d\x5e\x6a\x79\xf6\xa3\x77\x08\x4d\x3d\x8e\x84\xc9\xe3\x72\x85\x12\x05\xe4\xab\x97\xb4\x4c\x2c\xc8\x6f\x99\xa8\x78\x63\x58\x52\x24\x4c\xae\x02\x2f\x75\x00\xeb\xaf\x08\x91\x09\x32\x47\x09\x29\xd9\x08\xc6\x14\xb7\x33\xc9\x15\x16\x55\xf7\x21\x27\xae\x0f\x41\x70\x09\xea\xaa\xd5\x15\x20\x05\x9a\xa2\xba\xa5\x29\xd2\xbc\xc5\xcb\x63\x4a\xfd\xb9\xfd\x9a\x75\x4d\x06\xc1\x37\x02\xd6\x69\x05\x84\x7b\x69\xf6\xe2\x95\x60\xa5\xc6\x4e\xbf\xe5\x7e\x38\xd5\x9f\x72\xaf\xbe\x38\xfd\x77\x9f\xbe\xd8\x13\x54\x8a\xe0\x23\x13\x9d\xd8\x07\x9e\xa4\x39\xb9\x4a\x91\x8c\x39\x4e\xa1\x4f\xaf\xda\xf0\x44\x22\x8a\x91\x74\xa7\x84\x4a\x09\xb1\x63\x24\x7b\x4a\x2d\xd5\x88\xbb\xed\xc2\x62\x9a\x03\xaa\x39\x49\x8b\x4a\x2e\xda\x48\xd4\xa0\xd8\x91\x60\x8a\xd9\x4b\xe2\x05\xf8\x73\x1f\xfe\x9c\x05\x2a\xeb\xae\xab\x83\xcf\x33\xac\xdb\x53\x58\xa4\x67\xd7\x69\x71\x2e\x41\xa2\x1e\x27\x23\xd4\xbb\xf5\xd8\xb4\xf2\xf7\xe8\xa5\x2a\xb4\x1d\xd2\x3c\xf2\x70\x48\xe9\xdf\x4d\x95\xf6\x9f\x0d\xbd\xd3\x82\x4e\x0f\x84\xfe\x37\xa0\xb9\xbb\x52\x7d\xff\x1b\xe8\x1c\xf4\xd3\xb3\xbc\x5f\xd3\xad\x4b\xc1\x18\xea\x33\x53\x40\x58\x29\x22\xcb\x57\xbc\x11\xc5\x11\x56\x4d\x26\x1a\x9b\x16\x88\xb4\xa5\xb1\x69\x41\x72\x26\x20\x4b\xba\xce\x00\xd5\x81\xe7\x29\x60\x0d\xc2\x24\x51\x89\x13\x95\xa3\x7a\x2b\xf9\x7c\x35\x9a\xce\x74\x7f\xe8\x9d\xb2\xbb\xef\xee\xa6\x4d\xc7\x94\x90\x32\x00\x9d\x1e\x04\xfd\x6f\xdc\x7f\xf5\xef\x76\xe6\x2b\xd5\xe8\x6f\xfa\x64\x89\x6e\x24\xee\x15\xdc\xc0\x07\x7a\x83\x10\x78\x82\x66\x1a\xa9\x92\x21\x45\x8c\x7d\x6a\x79\x86\x74\x8b\xbf\x92\xa0\x81\x28\x56\x59\x6f\x85\x58\x62\x4f\x29\x25\x39\x14\x90\x5a\x0d\x61\x1e\x7c\xf1\x22\xbd\x21\x24\x7e\xcd\x53\x6f\x18\x0b\x14\x73\x1d\x54\xcd\x34\xf4\xaf\x5a\x4a\x24\x67\x92\x73\x7b\x8a\x2a\x28\x76\x9c\x5a\x13\xc2\x1c\x25\x24\x49\xce\x38\x28\xa9\x88\xc5\x62\x6a\xa5\x4b\x72\x26\x3c\x05\x65\x35\x3a\x84\x86\xe3\x52\x7c\x10\x36\x20\xc2\x80\x18\xb8\x1c\x6c\x86\x11\x06\xba\x03\x83\xcc\x64\xba\x88\x23\x21\xd2\x65\xbf\x14\x3d\x83\x99\xc4\xd4\xa0\xf9\xdd\xc0\x41\xd0\xd8\x5f\xa5\xaf\x49\x75\x43\xd1\x40\xff\xc6\x3c\xa5\xf1\x11\x87\x78\x41\x70\x83\x06\x30\x08\xfc\x02\xc4\xfb\x60\x62\xd5\x65\x29\xd6\x5b\xa7\x58\x8b\x91\x18\xed\x65\x6c\x96\x70\x83\x09\xe1\x22\xf6\x94\x12\xc9\x12\x4e\xb1\x52\x14\x27\x6c\xd0\x0f\xf9\x3e\x34\x8c\x48\xce\xe7\xb8\x62\x5f\x4d\xb8\x99\x12\x31\x59\x58\x56\x59\xd5\x5b\x43\x79\x97\x48\x0b\xd0\x6a\xcc\x33\xca\x24\xa7\xe2\xc3\x86\xf4\x10\x23\x70\x07\xa4\x50\xdf\x48\x3f\xf2\x17\x36\xe7\x15\x89\x7a\xa5\xb4\xfd\x6f\x44\x28\xd1\xe8\x8c\xcd\xea\xb2\x6e\x49\xfd\xf7\xde\x71\x6f\x1d\xdc\x81\x8a\x5f\xfa\x06\xdc\x12\x8d\xe6\x97\xa4\xfc\x13\x07\x44\xd7\xb6\xee\x68\x26\xb4\xff\xd1\x44\x43\x50\x70\x93\x7e\x2c\x31\x30\x0c\xfc\x4e\xbb\x6d\x01\x59\xed\x6f\x48\x29\x52\x84\x28\x7e\x74\x47\x62\xfa\x8e\xc8\xc6\x54\x72\x68\x41\x09\xb6\x70\x86\xd2\x06\x36\xda\xc6\x0c\x27\x1b\xd3\xc7\x9e\x52\xfa\x74\xdb\x98\x41\xb9\xfa\xd3\x11\xdf\x67\x6f\xfa\xe0\xf3\x5d\x11\xac\xae\xa7\x5b\x13\x2f\x8f\xc6\xb0\x32\x3c\xc8\x79\x4c\x2a\x28\xf5\x07\x9a\xfb\x6b\x0d\x86\x1d\xc4\x8f\x39\xb4\x3f\x05\x26\x2b\x90\x54\xd0\x27\x16\x53\x62\x4e\xa5\x9e\xc4\x72\xaf\xb4\x3f\x3d\xfc\x4e\x57\xba\x01\x30\x67\x50\xf4\xd8\x23\x70\x89\x5f\x2a\xfd\xfc\x65\xaf\x45\x2d\x9a\xc3\xb0\x9a\xc7\xea\xd2\xfb\x91\xe7\xbc\xea\x7e\x53\x7e\xc5\x1c\x4e\xdf\x4a\xdd\x59\x14\x8b\x4e\x10\xf8\xf1\xc0\x0f\x1a\xc0\xbf\x6a\x55\xd8\x15\x62\x4a\x43\xd4\x13\x68\x48\x41\x0d\x8b\x29\xc5\x1f\x89\xf3\x61\x53\x28\x31\x84\x67\x8d\x54\xbb\x81\x4a\x24\xac\x94\x9c\x51\xca\x22\x44\x24\xd7\x47\xb0\x54\xee\x4b\xc1\xbf\xb1\x9a\x57\xa5\xb5\x15\x91\x35\x19\xb2\xe3\xc2\x66\x1a\x86\x2a\xab\xe3\x15\x7f\x07\xa7\xd6\xfb\x2e\xf2\x4a\xb8\x83\x05\x6a\x59\x3d\x56\x66\xfc\x61\xba\x47\xe5\x25\x92\x53\x85\x4c\x2c\xa6\xf4\x95\xb2\x51\x0a\xa7\x5a\x53\x17\x8b\xa9\x05\x55\x92\x33\x61\x36\x58\x5d\x84\x1f\x87\x2b\x24\x67\xc2\x51\x50\x62\xc6\x76\x1e\x6f\xc5\x7f\x46\xd2\x6d\x5d\x24\x40\x75\x99\x04\x82\x40\x79\x63\xbf\xa8\x0f\xba\xe5\x40\x2e\xcf\x20\x1a\x64\x85\x99\x34\x74\x95\xbc\x6a\xc4\xaf\x0e\xce\xd9\x7e\x5b\xcb\xf0\xfe\x37\x6c\x58\xf6\xe9\x47\xe9\x13\xe8\x3d\xcb\xaa\xe4\x54\xf8\xd2\x4d\x93\x87\x2c\xbc\x75\x5e\xe1\xf9\x55\x02\xbb\x6e\xf7\xe4\x8f\x3f\xf1\xcc\x3a\x3b\xb9\x5f\x9f\xca\xfe\xf5\x43\x1e\x9a\x95\x7c\xf9\x8b\xc8\x20\xc6\x93\x3e\x36\x36\x5c\x5f\x33\xb8\x65\x48\xfb\xec\x7e\xd1\xf4\x9f\xcb\x08\x7d\x91\x9b\x7f\x4a\xf0\x83\x4a\x50\x07\x5d\x80\x40\x54\xa9\xbd\x8d\x29\x5d\x59\x56\xfb\x8a\x29\xb5\x32\x84\xb5\xe7\xbe\xdd\x68\xab\xb8\x09\xaa\x41\x36\xff\x20\x1c\x56\x2a\xce\x28\xbd\x22\x6a\x95\x3d\xa5\xd4\x46\xd4\xfa\xac\xdf\xe7\x49\x4a\xd3\x5e\x75\xbc\x52\xd9\xc1\xa9\xb5\x98\xa6\x7d\x3b\x5e\x1a\x74\xdb\x05\x2b\xbd\x0c\x25\x0e\x45\xd4\xd3\x14\xf8\x2c\x26\xb5\x9e\x06\x60\xa6\x08\xd4\x89\x3e\xf8\x2b\x9f\x08\xe1\x6f\xf1\xd2\x92\xfc\x34\xb8\x3e\x31\xf0\xbc\xe8\x90\x4a\x4a\x7b\xf5\xa9\xcd\x21\xeb\x9a\x04\xf2\x59\x65\x9f\x50\xdf\x1e\xa8\xba\x55\x15\x92\x33\x09\x19\xaf\xbf\x80\xc2\xf5\x14\x91\x1c\x7a\xb5\x6f\x6f\x8a\xf9\xc2\x4b\x0a\x24\x1e\x50\x4b\x76\xa3\xf2\xb4\xa2\xfc\x96\xcc\x5a\x56\x38\xde\xae\x08\x09\xbb\x68\xbb\x14\xf6\x8e\x81\xd5\xd7\x0f\x6d\x0c\xd3\xf4\x88\x47\xaf\x1b\xd7\xd0\x54\x3f\xdc\x1a\x58\xf2\xc8\x9e\x07\xf0\x6e\xdd\xb0\x7c\x2b\x3a\xa5\x6f\xd4\x02\x38\x9d\x24\x4d\x9c\x7c\xf1\x58\xe9\x7f\xbb\x86\xb4\xec\x6b\xd8\x78\x77\x64\x10\xe3\x4b\x2b\x63\x83\xcc\x9a\xf4\x87\x65\x14\x93\x31\xf3\xb1\xf0\x0c\x3f\x1e\xf4\x03\x83\xc0\x7f\x02\x22\x32\x94\x1a\x59\xb5\x1a\x53\xe4\xb5\x1a\x15\x34\xd4\x14\x9f\xb6\x79\xaa\x41\x4c\x29\xfd\x22\x71\x8f\x0f\xef\x9b\x47\xdf\xb7\xe4\xc0\x8a\x3a\xd6\x1a\x52\x07\x5a\x52\x44\xa6\x34\x9c\x51\xe4\x88\x6a\xb6\xa7\x14\x63\x44\x31\x3b\xd4\xfe\xb4\xbd\x1d\xe6\x5a\x43\x7a\x6e\xa1\x5c\xc7\x2b\xfd\x3a\x38\xd5\x88\xb7\xd0\x80\xaf\x85\x51\xc6\xd7\xc2\xd0\x4f\xc3\xe0\x6d\x90\x9c\x71\xc8\xd4\xe1\xeb\xd0\x5f\x1a\x62\x64\x05\x8f\xcf\x5f\x51\x13\x22\xed\xa7\x2a\x9d\x4a\x61\x0c\xa8\x03\xad\x92\x33\x29\x55\x36\x34\x12\x36\x56\x41\xe0\x05\x0c\x24\xa3\x8e\x97\x54\xe8\xcd\xdd\x8d\x6c\xf0\xb6\x1b\xb2\x99\x0d\xe6\x41\x9b\x95\x57\x6b\xa0\x10\x51\x57\x0e\xe0\x6c\x66\x2e\xc6\xbb\x4a\x98\xba\x7e\x9f\xa8\xa3\x9d\x2d\x68\x9d\xd0\x3e\xc5\x70\xe3\x7d\xa3\xd7\x3f\xbc\xe8\xd7\xeb\xd0\x85\x45\x8b\xd0\xb5\x78\x3b\xd8\xa9\x7d\xee\x6e\x9b\xd3\xaf\xe9\x06\xba\x1d\x1f\xa6\x3f\x2c\xf3\x8e\x9d\xd8\x3b\xa2\xa3\x9f\xad\x7c\xfd\xe6\xa1\xf5\xf7\xdf\xb2\xf0\xf1\x69\x8f\x0d\x9b\xae\x6d\xcd\x11\x0d\x03\x0d\x66\x2a\x91\x5b\x38\x21\xf8\xc1\x00\x38\x18\xc4\x1b\xf1\xae\xf4\x93\x29\x34\x4f\x54\x4c\xc5\x85\xfa\xa6\x48\x24\x12\x2f\x88\xe2\x3d\x28\xf0\x19\x29\x44\xa1\xd2\x3f\xac\xf4\x92\x09\x36\x48\x4d\x04\x9b\x20\xa0\xfc\x8c\xa4\x54\xcb\xea\x00\x63\x4a\xa9\xca\xa5\xc4\x0c\x0c\x2b\x8d\x67\xd4\x7e\xd6\x94\xd2\xcf\x41\x72\xb3\xcb\xac\x29\x2c\x56\x34\xe8\xf7\xd7\xf2\x93\x64\x9a\x7d\x17\x15\x4f\x47\xb6\xae\x9f\x57\x1a\x1d\x4a\x53\x87\x4d\xe9\xe7\x50\xe4\xbc\xd2\x9d\x90\x43\xe9\xdb\xa1\x06\x7c\x17\x95\xf2\x4b\x33\x6a\x9a\x1d\x89\x82\x66\x8f\x2b\x94\x88\xe2\xaf\x2c\x18\x62\xe4\x4d\x9e\xf2\x40\xa8\xaf\xdc\x9c\x87\x58\x6d\xe3\x05\xa3\xc9\x53\x40\x3e\x6f\x8a\x36\x77\x07\xb4\xc6\xc7\xa0\x5f\xa3\xe4\x54\x1d\x56\xd2\x78\xe9\x39\x7b\x61\x51\xaf\x2a\x52\xe3\x53\x86\x55\x09\xa0\x46\xf1\x4f\xcb\xea\x62\x44\x64\x91\xe8\x9c\x53\x8b\x35\x68\x29\x38\x83\x99\x6c\x56\xa2\x60\x87\x81\x5c\x29\xc6\x65\xab\x7d\x02\x04\xad\xe5\x5d\xd2\xa3\xea\xdf\x9e\x28\x7b\xde\x59\xf3\x9a\xb2\x65\xe1\xa4\x11\x43\x62\x23\x2d\x16\x78\xde\x6d\xd8\xf5\xef\xdb\x1f\xce\xab\xfd\x79\x54\x5a\x76\xc3\xc3\xa1\x39\xe8\xf4\xcb\xe8\xeb\xb3\xd9\x7e\x56\xec\xeb\x3b\x27\x4f\x7e\xe5\xa7\x0d\x7f\xf0\x4f\x1a\x3a\xe8\xe4\x9f\x9e\xd9\x97\x5f\x09\x34\xb2\x61\xfd\x47\xbf\x42\x0d\xec\xba\x2e\x1b\x7a\xa0\x08\xdb\x9c\x99\x8f\xf9\x0d\x82\x1b\x54\x81\x0d\x9a\x2d\x7d\x69\x92\x1a\x0c\x13\xb7\x18\x35\x3e\x13\x36\xe2\x44\x29\xb2\x13\xef\x89\x9e\x9d\xd6\x1b\x86\x54\x1b\xd4\xb2\xd3\x18\xc9\x99\xe0\xcd\x96\x8a\x4b\x73\xd3\x78\x6c\xd3\x55\x62\x72\xe5\xf2\xd1\x28\x4a\x2a\xc9\xb0\xfb\x96\x7c\xb4\xaa\x6a\x91\x14\x4c\xa2\xbf\xfd\xfb\xbf\x4f\x9a\x3f\xf2\xc6\x75\x37\xbe\x77\xe2\x2d\x5d\x82\xdc\xbe\xf2\xe2\x7f\xfe\xe8\x4f\x37\xda\x04\xf7\xd7\x81\xc5\x43\x9b\x43\x43\xa3\xad\xf7\x5f\x4f\x32\xd0\x88\xe4\x18\xf4\xf0\xec\x97\xde\x0e\x35\x8c\xd6\xf3\x0d\x07\x0a\x6e\x60\x00\x66\x70\x33\x88\x1b\xb4\xf8\x98\x60\xd0\xe0\x8b\xcc\x86\x6c\x29\xa9\x25\x6b\x73\x5b\xb3\x36\xf7\x8b\x39\x9b\x9b\xe4\x32\x19\x3b\x78\xc5\xe8\x48\xb0\x46\xc6\x15\x4a\x98\xf1\x57\x16\x28\xc6\x3a\x98\x00\xac\xd1\x9c\x4d\xdc\x61\xcd\x92\x33\xbf\x24\x34\x20\x56\xc2\x80\x56\xff\x09\x42\xe9\xb7\xe1\xb1\x86\xb4\x0f\xeb\x19\x82\x9b\xea\xdc\x6f\x33\x87\x01\x03\xdc\x00\x70\x67\xf9\x63\xc0\x02\x8a\xc0\x27\x5a\x6e\xa4\x81\x76\x03\x89\xdb\x1c\x2e\x59\xa6\xd5\xdc\xd6\x33\x49\x1b\x71\xf9\x24\xa0\xad\x7b\x99\x32\xa4\xaf\x6c\x0e\xd5\x08\x43\x49\x9e\xbe\x33\x95\x9f\x91\x92\x1c\x7d\xcd\x93\xc2\x58\xbd\x9c\xd9\x8b\x7f\x22\xd1\xbc\x25\xad\x04\xbc\xa3\xa8\x6b\x03\x59\xb2\xa5\x8e\xc3\x6b\x56\x99\x5e\x17\x39\x05\x76\xbc\xd4\xe1\xeb\x9a\x4e\xef\xad\xd5\xa1\x14\xe9\xb5\xa0\x49\x00\x19\x7b\x91\x96\xc2\xcd\x58\xe8\x4b\x8a\x8f\x6b\xa5\x39\x4b\x26\x49\x65\x0b\xa9\x63\xdf\x11\x53\x25\x9e\x64\x94\x02\x02\x8f\xf8\x1c\x6b\x72\x7a\xbc\xb4\xa3\x94\x4b\xf6\x41\xfc\x3f\x0c\x9a\x61\xb0\xdb\x1b\xf7\x4f\x8a\x3b\x4f\x7a\xde\x3f\x8e\x9e\x7a\xc7\xf1\xee\x5b\x0b\x8f\xf8\x3a\x4f\xba\xff\x40\xde\xfd\xfe\x57\x8c\x82\xaa\x61\x27\xaa\x84\xef\xa6\x27\xc1\x4f\x90\x93\x3f\xd6\xfd\xbd\x96\x4f\x8b\x69\x2a\x02\x3b\xf8\x58\x3b\xf5\x2c\x27\xca\xb2\x4c\xb0\xbf\x15\x93\xac\xda\xc4\x94\x62\x8d\xc4\x6d\x46\xcc\xec\x6c\x06\x63\x28\x6e\xb6\xd8\x23\x91\x48\x52\x80\xc0\x68\x0d\x29\x8c\xac\x0a\x62\x4a\xe1\x23\xc4\xd5\x64\xd0\xe3\xa6\x09\xd1\x6e\xa0\xd4\x97\x28\xf5\x45\xfa\xca\x4e\xc2\x5f\x1a\x72\x6d\xc2\xc2\x72\x86\x50\xd2\x4c\x25\x93\xee\x94\x3a\x7c\x21\xad\xa7\xe5\x1a\x49\x73\x3b\x5b\x47\xee\x43\x8e\x64\xb1\xb2\xc4\x47\x07\x1c\x09\x08\x8c\xae\x90\xc2\x3a\x12\x0c\x8b\x79\x1d\x41\x8e\xb2\xba\x42\x8a\xe8\x48\x08\xa2\xcd\x15\x62\x9f\x87\x0c\xe6\x6c\x56\x5b\x7e\xd6\x20\x75\x08\x05\x5d\x01\x33\xa4\xdf\xd9\xca\xa5\xec\x86\xa5\x9f\x0d\x40\x73\x06\xf4\x5e\xce\x6e\x58\xf1\xe9\x40\x74\xd3\x20\x46\x48\x7f\x05\x03\xe8\x7d\x56\xd1\x5f\xe9\xf9\x51\xdc\x71\x6e\x0d\xa8\x06\xbf\x01\x04\x92\x54\x71\xc9\x09\x8b\x93\xb3\x85\xd4\x2a\x73\x2a\x5e\xc5\x61\x42\x55\xf9\x8c\x21\xea\x45\x22\x21\x93\x32\x92\xd7\xad\x04\xb5\xee\x29\x8a\x25\xeb\x47\x52\xdc\x34\x2f\xd9\x65\xcd\xf5\x54\xb9\x04\xc5\xc5\xe3\x48\x48\x1e\x27\xf1\x20\x39\x89\x07\xc9\x49\x3c\x48\xce\xee\x1e\x24\x29\x06\xe2\x12\x71\x1b\x41\xed\x3b\x2d\x17\x08\x4a\x4e\x95\xf3\x91\xf4\x41\xc5\x16\x53\xdc\x34\x7d\x42\xc3\xa4\x14\x81\x0d\x9f\x31\xc5\x49\xeb\x04\x5c\x7a\xb6\xa0\x86\xf7\xdb\xbd\xd4\xb5\xb1\xdf\x60\x2d\x77\xdb\x39\x7e\x92\x7c\xe7\x23\xf6\x46\xc7\xd2\x19\x0f\xf7\xd5\x20\x5f\xea\x1b\x63\x86\x76\x65\xdb\xae\x82\x5a\xb1\x77\xef\x10\x3b\xf3\x8b\x42\xeb\x0f\xee\x1f\x32\xa2\x6b\xb8\xbc\xfe\x83\x13\xf0\xe4\xc5\x63\xbf\xbf\x90\x3c\xfc\xd4\x0f\xae\x5f\xde\x59\x1c\xa8\x8f\x75\xa3\x65\x04\xec\xa0\xb4\xd4\x08\xd9\x60\x4e\xc5\x1b\x08\x21\x1b\xaa\x8c\x21\xa5\x34\xac\x16\x6a\x0d\x98\x6a\x28\x25\xeb\xf2\x28\xa9\x91\x2f\x51\xe0\x72\x1a\x42\xd4\x4d\x17\x26\x16\x40\x3f\x18\x52\xc5\x3a\xbc\xfa\xaa\x58\x4c\x29\x27\xab\x2f\x70\xc6\x4b\x2b\x82\xb4\x0c\xaa\x94\xda\xc1\x0d\xd2\x31\x11\x14\xd8\x8a\xcb\x89\xef\xc1\xe9\xbc\x32\x21\xba\x25\x24\xb8\x74\xf0\xaa\x2b\xd2\xa4\xcb\x34\x29\xda\x30\x6e\xd9\x83\x4f\x4c\x37\xb4\xee\x9e\x73\x45\xc2\x7c\x3d\xa4\x77\xd5\x68\xd7\x47\xfe\xed\xeb\x6f\x81\xc6\x6b\xae\xcb\x51\x08\x82\x7d\xb0\x9d\x3d\x29\xb8\x41\x21\xf8\x0d\xd0\x19\x31\x89\x12\x26\x0b\xe9\x75\x2a\x24\xcb\xd7\x6e\x50\xc2\x66\x76\x1a\x42\xda\x05\x54\xec\x61\xbd\xeb\x6a\x71\x77\x27\x29\xa7\x80\x3a\x9e\x64\xee\x17\x0a\x17\x79\x85\xe9\x78\x69\x30\xf3\xc5\xaf\xe8\x4f\xec\x75\x36\xc5\xd1\xc1\xa9\xb6\xca\x8b\x36\x7c\xd1\x0a\x1d\x09\xb6\x90\x21\xdd\x35\x18\x57\x28\xee\x2d\xcc\x6f\xd4\xc5\xc6\xc0\xf3\x80\xb5\xda\xec\x0e\xad\x50\x85\x24\x34\x41\x86\xb5\x3a\xbc\x79\x8a\xb9\xbd\x50\x72\x12\x54\x69\x7c\xc8\xdc\x44\x07\x37\xc4\x40\x7d\x83\x0f\xca\xa2\x90\x53\x04\x82\x59\xf9\xbf\xef\x6f\x7f\x0c\x15\xf4\x15\xe6\xb5\x2f\x59\x2a\xcd\x3d\x37\xdf\x3a\x69\xf8\x8a\x8a\xb1\xb0\x9d\x7b\xe0\x5f\x67\xed\xd8\xb4\x79\x79\xf3\x24\x14\x84\xff\xdd\xaf\xd7\x8c\x43\x07\xd0\x53\xd4\xc7\x46\xe9\xe4\x07\xe5\xe0\x11\x40\xea\x29\x2c\x3a\x50\x74\xb2\x9c\x52\xa3\x9c\xd4\xa9\x27\x5d\x94\x50\x05\xae\x62\x43\x48\x07\xcd\xf2\x86\xf5\x96\xa1\x5a\xc2\x5e\x8e\x1c\xde\x3a\x9b\x52\xd8\xc1\xa9\x05\x98\x1c\x9e\x0e\x90\xf0\x68\x35\x39\x50\xf5\x14\x6a\xcb\xf3\x96\x4b\xce\x38\x67\xb3\xc6\x48\xaf\x86\xb8\x51\x28\xd1\x70\xce\x1c\x31\x40\x30\x62\x48\xcc\xd6\x07\xf3\xa2\x43\x97\x5b\xf3\x2f\x4a\xee\x5a\x33\xbe\x77\x45\x68\x84\xbb\xc6\x71\xc9\xd2\xd9\x5d\x77\xdd\xed\x3d\x6a\x1b\xb5\x3b\x72\xb9\xf5\x33\x99\xa7\x80\x97\x99\x2a\xb8\x81\x05\x14\x80\x4d\x40\x31\x93\x64\x8b\x38\x6b\xc6\x37\x88\x15\x8d\x21\xc5\x40\xb0\x71\x1c\x02\x4d\x4f\x12\xcf\x24\x0d\x74\xed\x56\x2c\xe4\x9c\xb4\xbd\x73\x61\xf7\xe4\x5c\xad\xd2\x8a\xd6\x2d\x01\x52\x63\x95\xad\xb4\x82\xaa\x01\x5b\xbd\x0e\x52\x75\x4b\xe4\x39\x20\xec\x05\xdf\x1c\x1d\x17\x48\x66\x99\x60\x05\xa4\x2d\xaf\x85\x60\xc5\xf4\xbe\x7d\xea\x46\xd8\x5e\xf9\xe3\xeb\xfd\xff\x7a\x15\xbc\x7b\xf4\xd0\x9b\x5b\x47\xac\xaa\x39\xe6\x18\xd8\xca\x6e\xea\x9a\x8d\xfe\x9b\xbf\x7d\x68\xeb\xf4\x01\x63\xb4\xbd\x1c\xc8\xbd\x4b\xea\xd1\x88\x4c\x81\x67\x92\x0c\x95\xe8\x76\xac\x70\xe5\xc9\x14\x7b\x56\x70\xa8\x8c\x5d\x0b\x40\x6a\x07\x4b\xce\xaa\x4d\x22\xbb\x2f\x7e\xc4\x6e\x5c\xf0\x58\xb8\xb0\xa1\xb4\x6e\xea\x5d\xc5\x93\x60\x3b\x3b\x72\xff\x61\xe1\x5d\xcb\xfd\x1b\xd1\x7d\xe4\xfc\xf8\xe0\x3a\xe6\x15\xee\x44\xee\x99\x59\x0a\x25\x8c\xa4\x7f\xb1\x49\xd3\x16\xc2\x49\x23\xd5\x08\xf0\x33\x45\x93\x0e\xaf\x5a\xdf\xe0\x8a\xea\xab\xa6\x99\x97\xbe\x86\x8a\x3e\x93\xb7\x96\x4c\x3a\x17\x3f\x22\x19\x97\x3c\x2a\xc3\xcd\x9d\x96\xbb\xef\x86\x6b\xba\x5e\xda\x7f\x98\x9e\x59\x1f\xf0\x92\x67\x96\x80\x15\x40\x71\x86\x93\x56\xea\x7f\xf2\x85\x55\x96\x4f\xc5\x59\x9f\xbe\x77\x7a\x46\x9c\x76\xc7\x45\xb3\xc7\x10\xd2\x26\x47\x12\xe2\xc4\x6c\x42\xdc\x65\xcb\xc1\x7c\xd9\x3c\x2b\xd6\xa9\x82\x42\x62\x8a\x65\xe7\xda\x8d\xa1\x0d\x86\x74\xe2\xa5\xe1\x69\x9b\x7d\x13\x3f\xf8\x85\x61\xa0\x3f\x3c\x64\xdc\xf2\xdb\x1a\x24\x61\xfe\xdd\x61\xb8\xe9\x5d\xcb\xb6\x0d\x70\x4d\xd7\x2d\xe5\xbe\xa8\xed\x68\xc1\x82\x1b\x46\x3e\xde\xb4\x09\x30\x78\xbf\xb8\x36\xee\x04\xa9\x59\x79\x0c\x60\x3d\x11\xc8\x78\x31\x16\x2e\xa4\xb8\x75\x10\x99\x38\xeb\x26\xeb\x81\xc6\x10\x41\x6a\xd2\x2a\x57\xf0\xc6\x92\x34\x3f\x52\xbc\x82\x69\x8b\x57\x55\x90\xcd\x9b\xfd\xe8\x1f\x5a\xbf\xe2\x83\x32\x2b\x43\x99\x22\xbd\xe9\xf5\x2b\xfb\xe2\xe7\x86\xce\x87\x0c\x42\x6f\x6d\xfa\xd5\x73\x9b\xd6\x0f\x9b\xbe\xe6\x56\x7c\x3e\xd0\x5b\x30\x8a\x0e\xc4\xee\xbd\x6f\xff\xc1\xe1\x8d\xd3\xf1\x7e\xbd\x05\xdb\xf9\x55\x64\xbf\x5a\x81\x06\x0d\x98\x37\x7d\x0f\xe5\xc2\x66\x6d\x53\x18\x92\xd2\xcc\x13\x56\xe0\x91\xe2\x46\xda\x78\xd3\xec\x54\xad\x36\x7a\x5c\x64\x97\x5b\x94\x07\xc1\xa8\x4b\x96\x68\x8e\xa2\x0c\x83\x6c\xbf\x68\xd0\x0e\xd9\xe0\x5b\xa7\x38\x83\x60\x6a\xb6\x1d\xfd\xab\xc1\xd0\xbf\xec\xd0\x47\xe8\x96\xbf\xf1\xa2\xb1\x6f\xdf\xa3\x9f\x73\x27\xd0\x03\x3f\x9a\x15\xfc\x51\x29\xdc\x85\x96\x6f\x9b\xfc\xb3\x61\x70\x55\xd7\x4b\x70\xeb\xc1\x99\x1b\x6f\x46\x8b\x49\x5e\xba\x97\x3d\xcb\x9d\x00\x05\xa0\x12\xe0\x0b\xcf\x6a\x35\x50\x86\x33\x3a\x6d\x0b\x61\x48\x35\x1a\x48\xde\x26\xa8\x6f\x18\x08\xb5\x86\x07\xb2\xd6\x32\xdc\x25\x43\x21\x58\xd1\xbb\x7e\xe4\xcc\xa0\x73\xfd\x7b\x21\xa3\x60\xef\xe5\xff\xc5\x97\x88\xb9\xeb\xa3\x61\x95\x49\x53\xdb\xd0\x4a\x76\x24\x5a\x3f\xf1\x81\xaa\x05\x83\xe1\x43\x5d\xc3\x2e\x12\xdc\x15\xf6\x55\xa6\x8d\x3f\x06\x04\x50\x01\xe2\x0c\x03\x42\x49\xc0\x01\x23\x17\x82\x8a\x48\x68\xc4\x39\xf0\x3b\x6c\x1f\xe1\x75\x37\xb9\x02\x5e\x41\x5c\x3c\x6d\x31\x2c\x35\x2c\xf8\x11\xfb\xea\xaf\x61\x75\xc1\x07\x5d\xd8\x16\x59\xcc\xbe\xca\x39\xc8\x38\x36\x50\x46\x47\x52\x4c\xb2\x36\x98\x22\x46\xa0\x62\x0f\xab\x8e\xfc\x51\xe4\x41\xb0\xdb\x68\xef\x79\xc3\x1b\x60\x49\xde\xb0\x8d\xb7\xc2\xf1\x64\x74\x3c\xcf\x55\xec\xab\xcc\xf4\x6e\xf3\x14\xba\xcd\x93\xed\x3e\xcf\xa8\x2c\xb0\x81\x55\x0b\x7e\x74\xee\xfa\x05\xe8\x03\xf6\xec\x07\x5d\xef\xa0\x3f\x80\x7f\xdc\x7a\x21\x78\x9f\x7d\x15\x22\xfe\x18\x30\x80\x5a\x40\x9a\x85\x25\x45\x6d\x1c\x92\xb2\x99\x14\xf4\x0c\xd8\x6c\xe2\xa6\xc2\x51\x4e\x13\x10\x3c\x6e\x6f\x90\x79\xdf\x0a\x2d\x9c\xe9\xd4\x30\xfe\x40\xc1\xc2\x05\x3f\x5e\x0f\xad\x34\x26\xbc\x98\xdb\x07\xf6\x0a\x37\x03\x07\x28\x01\x58\x09\x80\xe4\x02\x12\xd0\x30\xfe\x4c\xd2\x42\xce\x28\x45\x2a\xa3\x36\x66\x54\xb3\x29\xf7\x94\xda\xfb\xf4\xef\x53\xee\x9f\xbd\xe8\x81\xd5\x85\xdc\x0f\xef\xab\xaf\xaf\x8a\x08\xdb\xa5\xdb\x6f\x58\x76\xd7\xa5\xe3\x8a\xfa\xc5\x26\xe3\x82\x33\x1a\x83\xc4\xe3\x52\x83\x55\xb3\x57\xc5\x3a\xb8\x67\xc7\xad\x5e\x77\xa9\xad\x4f\x4b\x9f\x72\xff\x0d\x4b\xf9\x4d\xcb\xef\xe6\xee\x27\x63\x6f\xb3\xaf\xc5\x74\x38\xcd\x1e\x64\xbe\x14\x02\xc0\x05\x06\xd3\x6e\x1e\xaa\xc9\x92\x52\x1c\xe1\x24\xa3\x3d\xc0\x4d\x8c\x3a\x9a\x10\x8c\xef\x19\xa0\x6d\xa1\x0c\x04\xd5\x98\x77\xc5\x62\x0a\xa3\x01\x3f\x69\xa1\x75\x3b\x0c\x46\x75\x54\xe3\xd3\x5b\xdb\xef\xde\xbd\xed\xa1\x82\xb7\x6a\xff\x5c\xdf\xa7\xbe\xad\x2f\xff\xc1\xa0\xcd\x2b\xd6\x3c\x58\x31\xff\x54\xc3\xe6\xaa\xba\x52\x37\x3d\x1b\xaf\xb0\x07\x59\x1f\x99\x43\x04\xeb\x0f\xd9\xb5\x91\xb4\x3d\x4c\x33\xed\xd1\xaa\x05\x48\x4e\x55\x72\x12\xb1\x67\xd4\xcc\x58\x57\x77\xa0\x68\xaf\x18\x8c\x56\xbd\xf2\xea\xc1\x7b\x6f\x19\xdf\x7b\x9c\xdc\x32\x76\x7a\x5b\xed\x5b\xde\x04\xf7\xd5\x3d\x8f\x0f\x79\xcc\x5b\x36\xac\x39\x36\xc4\x79\x6a\xe1\x48\xfa\xdc\x65\xc0\xcd\x55\x72\x63\x80\x00\x80\xab\x11\x7a\x8c\xd0\xb3\x8c\x7d\x21\xbd\x81\xd9\x02\xff\x75\x07\xfc\xec\x33\xf4\x1a\x3a\xff\x69\x8f\xdf\x8b\x36\x1a\x61\x23\xf4\x2c\x63\xb6\xa4\x37\xb0\x2f\xb8\x3f\x85\x45\x70\xe0\x67\xc8\xb1\x83\x8c\x57\x0b\x5a\xb8\x39\x5c\x29\xf9\x3d\x6c\x21\x1a\x61\x2d\xfc\x6c\x07\x3c\xf6\x29\x3a\x8f\x5e\x6b\x61\xff\xd8\x55\xc6\x1c\x49\x6b\xb9\xfc\x79\xbf\xeb\x92\x8d\xf8\xb7\x6b\x3f\x83\x03\x61\xd1\xa7\x68\xec\x0e\xae\x34\x3d\x99\x39\xd2\x55\x06\x00\x84\x51\xae\x93\x9b\x2d\x04\xc8\xad\x54\x40\x58\x31\xca\x2a\xc7\xa5\xb2\xb7\x51\xe5\x80\x44\x9d\xaa\xb0\x71\x10\x8c\x06\xca\xa0\xd7\x13\x24\x3d\xd3\xa3\x83\x93\xfd\x60\x5b\xc1\xc2\xc8\x1b\x83\x6f\x5a\xb4\x89\xeb\x2c\x8a\x25\x5b\x9b\xd4\xd1\x45\x8d\xab\xa6\x4e\x02\x10\xae\xe3\x3a\xb9\x83\x42\x00\x58\xf1\xb8\xa6\xb0\x2a\x70\x29\x05\x92\xfe\xb8\xaa\x1d\x8f\x2b\x98\xc8\x89\xc7\xe3\xca\x05\xde\xa6\xa8\xec\x11\xc4\x40\x1d\x84\xeb\xde\x18\x7c\xd3\xaa\xd5\x9d\xff\x71\x0d\x3a\x5a\xb0\x50\x30\x14\x35\xae\x9a\x39\xb6\xe8\x8d\x45\x4d\x2a\x5e\x13\xf7\x3a\x1c\x29\xd4\x00\x16\x0c\x26\x73\x65\xe5\x24\xe4\x80\x93\x5c\x23\xa8\x70\xf9\x22\x07\xe4\x35\x50\xa1\xfe\xd0\x27\xb0\xb0\x61\x21\x35\x10\xb1\xac\xa8\x1d\x7f\x62\x3c\xf7\x3a\x9c\x8b\xf6\x63\x3a\x6c\xe6\x3a\xb9\x22\xfe\x08\x60\x41\x00\x8f\xad\x42\x3e\x85\xff\x91\x61\xb1\x28\x70\x00\x91\x0b\xa9\x3c\xb9\xf6\x30\x1a\x10\xe1\xe6\x5a\x66\x49\x2d\xd7\x79\xfa\x34\xbd\x97\x7f\xe0\x3a\x19\xab\x10\x00\x06\xed\xef\x59\x4c\x44\x23\xf9\x5b\xde\x01\x0c\xf8\x6f\x81\x7e\xc7\xd9\xc6\xa6\x68\xc0\x63\x83\x62\xf9\x55\x3b\xe0\x55\x75\xbf\x9d\xc2\x75\x16\x4d\x3d\x2b\x35\xbf\x3a\x88\x8e\xf5\x34\xd7\x09\xaf\x26\x63\x15\x91\xda\x5d\x26\x37\x16\xe7\x00\x26\x7a\x11\x1b\x03\x05\x5e\x4f\xb0\x0e\x4e\x83\xd1\x5e\x57\xbd\x30\xaa\x5d\xb0\x78\x1e\xfa\x41\xd1\x88\x67\x01\x44\xbf\x41\xe3\x32\x7f\xce\xfc\xf4\x1f\x40\x27\xe8\x92\x59\xf4\x9b\xf1\x27\xc6\xa3\x71\x84\x50\x10\x55\xa1\x5d\xe0\x95\xcc\x3c\xc0\x82\xd2\x2b\xd3\x49\xa3\x11\xaa\xc2\x34\x42\xbb\x34\x1a\xa1\xc7\xd0\x2c\x30\x2a\xf3\x34\x5d\x17\x1f\x56\xa1\xb6\x2e\x03\x61\xcf\x74\x5d\xbc\xb6\xac\x6a\xf4\x98\xb6\xb0\x5e\xd3\xc8\xba\x46\xd0\x31\x46\xa2\x59\x60\x15\x19\x23\x00\x14\x43\x8e\x36\x06\x42\x1b\x4c\x67\xce\x40\xdc\x73\x78\x0e\x1a\x99\x83\x68\xa4\x46\xe8\x53\x68\x6d\x96\xd0\x0c\x3a\x0f\x00\x6c\xe1\xc6\x02\x06\xf0\x20\x40\xfd\x23\x24\xfb\x84\xd2\x19\xef\x37\x3e\xfd\x2a\xc3\x12\xa1\x1e\xf0\x41\x36\xc0\xa2\xf3\x17\xd6\x6d\x86\x8b\x3f\x87\xa5\xe8\x03\x6e\x2c\x22\xb8\x02\x6f\xb2\xb5\xb0\x81\x8c\x53\x04\x14\x26\xac\x02\x3c\x27\x96\x8c\x03\x1d\xc0\x4b\xf7\x2b\xc0\xc6\xe0\xe2\x2f\xe8\x9f\x60\x7e\x0b\xcf\x81\xbd\xec\x0b\xff\x37\x3e\x0e\x3f\xbc\x94\x8f\xe7\x8f\xfb\xbf\xe6\xe3\xcc\x1b\x3d\xf8\x38\x9a\x81\xa6\x80\x60\xe6\x87\x40\x04\xe3\xc8\xb8\x3c\x55\x01\x99\x48\x9c\x17\xf5\x20\x13\xc9\x42\x33\x84\x15\xf6\x8c\xee\x73\xa3\x59\x48\xef\xd1\x52\x38\xad\x70\x86\xd5\x11\x2a\xc9\x29\x91\x49\x47\x4b\x34\xc3\xb7\x3b\xd4\x1e\xda\xe5\x43\x53\xd6\x9f\x38\xb1\x1e\x40\xb4\x1f\x4d\x01\x73\xc8\xf3\x26\x90\x73\x46\xab\xb7\xa8\xb6\xa9\xd5\x6a\xf1\xc6\x90\x22\xd0\x27\x0a\x67\x74\x8f\x5f\xfe\x13\xc5\x0e\x85\x77\x28\x5c\x07\xab\x72\xa2\xfe\x44\x3e\x1a\x10\x83\x62\x30\x8a\xf6\x17\xc3\x23\xc5\xbb\x42\xed\xa1\xf7\xd6\xaf\x3f\x71\x82\x9c\xad\x76\x54\x0b\xc6\x67\xde\x04\x66\xf0\x20\x79\xa6\xc1\x9c\x7d\x26\x51\x6b\xf5\x07\x9b\x8c\x21\xc5\x18\x89\x43\x80\xdf\x41\x7d\xe1\x96\xbc\x85\x53\x60\xd2\x4b\xec\x0a\x32\xbb\x9d\x17\xee\xc5\xb3\xfb\x1e\x58\xa4\x79\x84\x22\x53\x6f\x2f\xda\xed\x6f\xf7\xef\x2a\xda\xe9\x6f\xf7\xa3\xe3\xeb\x1f\x7c\x70\xfd\x8e\x1d\x74\xfe\xc7\xc1\xf8\x4c\x14\xb0\x20\x08\x88\x4b\x94\x4c\x3d\x7b\xb4\xb2\x37\xd4\x94\xbb\xa1\xed\x45\xf0\x48\x11\x3a\xbe\x7e\x3d\xe6\x81\x47\xb9\x4e\x6e\xbd\x10\x02\x36\x30\x14\x6b\xfa\xaa\xc0\xa7\xe2\x02\x29\x0b\x14\x8c\x46\xca\x3c\xec\x54\x99\xa2\xab\x61\xa9\xaf\xd5\x44\x05\xa8\x03\xeb\x9e\x2c\xad\x4e\xa8\x6f\x80\xfd\xa2\x32\xad\x67\x92\x99\x40\x45\x15\x3c\x2a\x1c\x1d\x73\xf5\xc4\x9b\xa4\x97\xa3\xe8\xe8\xa3\x3f\xe6\x53\x55\x25\x43\x07\x34\x8d\x42\x47\x77\x01\x08\x5b\xb9\x14\xc1\x82\x35\x81\x0a\x62\xdf\xb3\x5c\x8a\xf2\x4f\x33\x09\xd3\x0b\x8e\x14\xf9\x67\xa1\xcc\x37\x97\x62\x07\x5b\xb5\x44\x3a\x7e\xae\xde\xe3\x90\x71\x73\x67\x39\x93\x10\x07\x66\xe0\x05\xe3\x89\xb4\xb7\xd3\x93\xea\xc9\xdd\x85\x42\x5d\xee\x6b\xb8\x96\x4e\x18\xd2\x7b\x96\x16\xc1\x90\xea\xb4\x48\x4e\xd5\xc8\x12\xe4\x08\x6c\x77\x0a\x20\x16\xeb\xf6\xdc\x2c\x56\x36\xc9\x66\x76\xdf\xb7\x62\xf9\x83\xdb\x6f\x59\x7e\xff\xde\xfa\xfa\x3e\xd1\x68\x9f\x3e\x4d\xfc\xeb\xcb\xee\xbc\x6b\xd1\x92\xad\x9b\x56\xd4\xf6\xeb\x57\x5b\x2b\xcb\x00\x66\x26\x23\x37\xb8\x00\x00\x90\xc0\x00\x9a\xeb\x48\x72\x51\xb1\x02\x4f\x50\x26\x35\x07\x6a\x16\x5d\x52\x65\x49\xa6\x80\xc9\x4e\x12\x11\x09\xa6\xa4\x85\x34\x8b\xeb\xd7\x14\x95\xb5\xd4\x53\x6a\xd9\x1d\x99\xb5\xf6\xcd\x35\xa3\xcb\x4b\xfa\xf6\x9f\x3c\x69\xfe\x1a\x74\xb6\xed\xfe\x09\xb3\x17\x46\x4a\xfc\x4e\xa5\x68\x09\x80\xb0\x85\x3b\xcb\x6d\x16\x6c\xc0\x03\x46\x00\x82\x41\x41\x20\xfb\x13\x4e\xd1\x6a\x08\xa9\x8c\x25\xa5\x98\x68\x9b\x4f\x70\x26\xe9\xa1\x04\xf1\x38\xb0\x4a\xaa\x9b\x3b\x5e\x18\x52\x4d\xa4\xbe\xc7\x4a\xb8\x20\x74\xca\x91\x32\x86\xee\x6b\xb0\xa2\x8e\xc1\x5a\x18\x6c\x69\xf9\xcf\x86\x09\xad\xfd\xfd\x15\xf5\x05\x47\x5a\xdf\x6b\x18\x37\xa4\x25\xe0\x6f\xb0\x71\x67\x61\x63\xa0\xba\x5c\x8e\xa2\xb7\x03\xd5\x81\x66\x19\xf3\x5c\xe8\xe5\x3a\xb9\xe3\x44\xb6\x49\x39\x8d\x83\x6c\xb6\x33\x8c\x57\x0f\x08\xa8\x84\xa6\x71\x68\xfc\x5b\xd6\x5f\x40\xef\x2d\xab\x61\x43\xe8\xdd\xd9\xef\x6a\xdf\xb9\xce\xa2\x3b\x7f\x2a\x35\xbe\x3c\x42\xfb\x46\x65\x44\x27\x1c\x0f\xab\x59\x19\xd8\x40\x15\xd1\x3d\x78\x4b\x4a\x3b\xb9\x24\xc2\x81\xad\x37\xc5\x4a\xb2\x1d\xb5\xe6\xf2\xb0\xb2\x5b\x17\x14\xd4\x09\x6b\x73\x9d\x4e\x66\x32\x1f\x4e\xd4\x7b\x99\x14\xd0\x3a\x29\x6e\x27\x7c\x46\x90\x81\x19\xf4\x05\xf8\x8c\x1a\xe5\x24\xcb\xe1\x5b\x45\xfc\xe4\x16\x42\x4c\x81\xd8\x09\xd4\x7d\xa2\x72\x26\xda\xe8\xaf\x3a\xea\x8d\x7a\x45\xaf\x58\x2d\x86\x77\xcf\x5c\x34\x7b\xf7\xc8\x3d\x37\x2e\x99\xb9\x87\x3b\xbf\x7e\xdd\xd4\xf5\xeb\xa7\xae\x5b\x3f\x65\xdd\x3a\x6c\x2b\x29\xc0\xcb\x76\x71\x27\x80\x07\xf8\xc1\x64\xa0\xb8\xc2\xc9\x42\xed\xe4\x96\x93\x62\x5c\x2e\x92\x2c\x20\xbb\xa3\xd7\xd1\x15\x90\xdc\x75\x2d\x19\x96\x64\x17\xf1\x05\x92\x33\xce\x12\x50\x2b\xc5\x27\x29\xa5\x31\xc5\xe1\x8c\x1b\x0d\x24\x93\xb3\xbe\x21\xda\x4f\x37\x0a\x89\x69\x9a\x3d\xd5\x3a\x00\xbc\xb2\xac\x65\xff\xef\x86\x3a\xf9\x82\xe8\xc9\x0b\x68\x70\xf0\x8e\xb5\xd7\xce\x3b\x50\x53\x56\xed\xe8\x1b\x39\x71\xfb\xfe\xc9\xcc\x1e\x74\x64\xd2\xec\xf1\x33\xe1\xf4\xf4\xd8\x7b\x17\x6f\x7c\x70\xee\x94\x86\x09\x43\x06\x0e\x6a\x59\x83\xf5\xce\x2d\xb0\x9d\x99\x21\xb8\x01\x8b\xf9\xb6\xe6\xd3\xe4\x74\xa6\x21\x51\xa6\x01\x61\x48\xd3\x3f\xb0\x42\xa5\x75\x4f\x7c\x93\xfa\xe4\xf2\x52\x3c\x19\x3d\xc5\x13\x6a\x1a\xdb\x96\xbf\x9f\xfb\x12\xb6\x73\x0f\x7c\xbd\x8a\xea\xb8\x1b\xe0\x3a\x36\xc8\xbd\x0b\x2a\xc0\x62\xa0\x94\x67\x11\x6d\xdd\xfa\x9d\x27\x30\xe3\x96\x2c\x7c\x3e\x6d\xeb\x9f\x2c\xa5\x4f\xee\xa5\x75\xf6\x8f\x1b\xd9\xf2\x58\x2c\xa6\x96\x0a\x92\x33\x61\x77\xba\x8b\x49\x00\x8f\x2d\xa7\x5e\x2f\xb7\x94\x80\x16\x67\x69\x5e\x37\x7f\xd7\xb7\x74\xf3\x0f\x56\x54\x6d\x58\xb3\x6e\xe0\xf8\xa6\x31\x33\x46\x3e\xbb\xe7\xd1\xdb\xc6\xce\xbb\xbe\x2a\xd6\x67\xd4\xf5\xd7\x3c\xff\xec\xd5\xb7\xc1\x67\x5e\x1a\xd6\x50\x53\x51\x5f\xd3\xef\xa6\x91\x77\xdd\x3b\xe2\xe0\xe0\x8a\x60\x69\x9f\xaa\xf0\xb2\x31\xf7\x3f\xea\xa1\x6b\xaa\x81\xed\xec\x27\xdc\x09\x60\x06\xc0\x05\x59\xd9\x1b\x0d\x40\x57\xd0\x0c\x6b\xe0\xc2\xc3\x17\xa6\x1c\x83\x46\xf4\xc4\xf3\x5f\xcc\x7c\x13\xb6\xc3\xa3\x70\xef\x57\x5f\xa1\x19\x68\x26\x04\x19\x40\xff\xf6\x3d\xd8\xce\x1e\x20\x75\x3e\x73\xc8\xb9\x27\xfe\x01\x7a\xb7\xad\x94\x04\x4e\x2d\xea\x25\xd1\x9b\xad\xb5\xa6\x7e\x80\x92\xde\x59\x67\x53\x5c\x1d\x9c\x2a\x55\x5e\xb4\x11\xf4\x09\x87\xa4\x21\x16\xe4\x55\xfb\xb0\x26\x49\xef\x86\x40\x92\x94\xc4\xea\x6c\x7a\x62\xd0\x55\x07\xdf\xfb\xfd\x2b\x13\xee\x99\xb2\xa0\xf7\xb5\x13\xae\x9a\xb3\x72\xe9\xba\x3f\xce\x9b\x7b\x13\xf7\xcc\xd1\xb7\xaa\x9a\x0e\x79\xeb\xe7\x4e\xba\xea\xce\x9a\xf4\x09\xf8\xce\x20\x5a\x6f\x08\x0e\x00\xc0\xbc\xc0\x6f\x06\x3c\xa8\x07\x71\x8e\xe6\x4e\x66\xa5\x95\x10\x56\x38\x5d\xd2\xc4\x39\x16\x4b\x21\x0e\x18\x43\xaa\x48\x2d\xef\xc6\x80\x14\x94\x0e\x30\x85\xed\xdc\x57\xed\x5f\x6d\xe2\xbe\xca\x1f\x4f\x04\x83\x40\x5c\xe8\x36\x5e\x9e\xb0\xd6\x14\x06\x85\x89\x68\x3a\x43\x5c\xe0\x89\x8c\xc3\xa3\x1b\xb3\xa3\xcb\x78\x7c\xb8\xb3\xbd\x9d\x7d\xa6\x1d\xb6\x7d\xb5\x89\x7d\x06\xfc\xf3\x9e\xc1\xec\x6f\x67\x66\x7e\xb5\x89\xd9\xff\x4f\x7c\x06\x9c\xd2\xce\x1e\xfa\x6a\x13\x9c\xd2\x83\xf6\xcd\x54\xf3\xbd\xdc\x03\x84\xb0\xc2\xe8\x9a\x55\x9c\x21\xa3\x33\xb9\x3d\x90\xc9\xe8\x64\x6c\xee\xab\xaf\x36\xf5\xdc\x53\x7d\x5c\xdd\x45\x08\x74\x17\xa1\xae\x63\x6b\x7b\xab\xfd\x80\xcf\x8d\x2b\xc9\x52\xc0\x73\xa0\x1d\xee\xe4\x37\x7f\x2d\xb4\x83\x4b\x69\x42\xea\xef\x84\x9c\xf7\x51\xc8\x0d\x6d\xd0\xa5\xa9\x99\x6a\xa7\x22\x19\x5d\xe4\xb3\x34\xa1\xa3\x07\x24\x3c\x3e\x5a\xc1\x6f\x4e\x1f\x6c\x4f\xcf\x25\xcf\x48\x7f\x8e\x16\xc1\x92\x8c\x0a\xac\xa0\x98\xe8\x21\x3c\x97\x52\x00\xb1\x59\x81\xca\x1b\x89\x55\x51\xdf\xc0\xe7\x9b\xab\xd5\xe9\xcf\xf3\xed\xd5\xc8\x55\x59\x73\x75\x34\x60\x33\x63\xb9\x27\x99\x77\x84\xb9\x80\x05\x22\x30\x60\x7d\x3c\xbb\x8d\x0a\xa7\x6b\xd0\xd8\x78\x21\x7a\x7e\x40\x24\x66\xe5\x31\x3f\xdb\xe8\x4f\x33\x7e\xb6\xb1\x2c\x5d\xcd\xfd\x62\xdb\x36\xe8\xdd\xb6\x0d\xfd\x1b\xf8\x7f\xe0\x43\x43\xd5\xc8\x0d\x4e\x65\xde\x05\x02\x5e\xbf\x10\xc6\x46\xa3\xe6\xf9\x02\x2a\x14\xf4\xf6\xd4\x34\x3a\x8d\xaa\xf7\xdd\x76\xe1\x19\xb4\x69\x6e\x25\xfa\x04\x3a\x51\x0c\xd3\xef\x24\x72\x83\x75\x99\xb3\x40\xa0\xb6\xa1\x66\x77\x9a\xb2\x43\x00\xcd\xa5\x62\x84\x32\xe6\x69\xe9\x93\x70\xcb\x9c\xd7\xf7\xad\xfe\x1c\xb9\xe1\x6b\x68\x20\xb4\xa3\xff\xa1\xf3\x68\x41\x6e\xb0\x09\x84\x81\x80\x69\x26\x84\x93\x0c\x87\x0d\x3b\xdd\x03\xc7\x10\x33\x8f\x28\xb0\x95\xa2\x15\x8a\xa8\xc5\xc3\x84\x03\x68\x1f\x6c\x28\x45\x9f\xcd\x7d\x77\xf7\x96\x0d\xf7\x02\x88\x1a\xf1\x5c\xf4\x31\x40\x38\xc9\x75\x1b\x83\xcf\x8d\x51\x0b\xa3\xbc\x88\x1a\x03\x70\x3e\x3a\x59\x0a\x4f\x79\x90\xfb\xa1\x2d\x1b\xda\xdf\x9d\x0b\x98\xcc\xbe\xf4\x33\x70\x47\x66\xcb\x3f\x5e\x97\x64\xaf\xa0\x4b\xce\x6f\x5f\x89\x55\xc9\x95\xed\x8f\xe8\xaa\x24\xda\xb3\x74\x33\x56\x25\x37\x2f\xd3\x55\x49\x00\x33\x7d\x99\xe1\xe0\x0c\xbb\xfd\xbb\xf9\x07\xfe\x43\x33\xa3\xd9\x35\x9a\x7f\x80\x41\x61\x66\x08\xfc\x0f\xf6\x5e\xa2\x83\x15\xf7\xd0\xc1\xbe\x51\xff\x42\xe1\x1e\xfa\x17\x33\xe4\x52\xfd\x8b\x41\xb5\xcc\x10\xf8\x1b\x6d\x7c\x00\xcb\xa0\x57\x6e\xac\xaa\x0e\xf0\xfa\x0b\x54\x1b\x7a\x77\x76\xfc\x96\xd5\xe8\x24\x7c\x40\x7f\xc5\xae\xc9\x0d\x52\x74\xe7\x4f\xe9\x39\x98\x85\xa6\xc1\x27\x33\x0f\x02\x0f\xb6\x47\xfe\x17\xba\xeb\xb7\xe9\xad\x68\xd6\x65\xf5\x56\x34\xed\x52\xbd\x35\x33\x01\xee\x86\xf3\x84\x00\x39\x0b\x63\xa8\x17\x91\xd4\x4c\xe2\xb3\x60\xd7\xaa\x27\x0b\x75\xcd\xaf\x94\x0b\x25\x2c\x02\x30\x84\x92\x4e\xf2\x86\x38\x16\x15\x63\x4c\x11\x24\x95\xf5\xe8\x0d\x4c\x41\xf7\x83\xe0\xca\x7b\x9d\xd0\x0b\x1f\x8f\xad\x98\x39\xfc\xea\x65\xd3\x47\x5f\xc3\x04\xb4\x1a\x47\xf6\x8e\x19\x4b\x26\x8c\x98\xb2\x74\x0c\xf5\x15\x4d\xe1\xfc\xe0\x30\xbf\x0a\xf0\x20\x02\x30\x57\xd1\xb8\x38\x07\x75\x81\xa9\x73\x5b\x8d\x8b\xf3\x40\xb7\xd6\xf1\xe3\xa5\x80\x27\xe8\x39\x0c\x27\x9f\xe7\xfc\x70\xf2\xb2\xf3\x3d\xc7\xcb\x89\x1d\xcd\xf2\xe5\x8c\x57\x96\xcc\xf4\xd0\x49\xc1\xc6\xc3\x70\xf2\x32\x5e\x58\x86\x8e\x90\xf1\xe0\x79\x70\x98\x6d\xc9\x8e\xf7\xdd\xa5\x01\x99\x9f\xec\x91\x3d\x87\x97\x9d\x87\xe7\xe1\xe4\xf3\xcb\xc0\x65\xc6\xfb\xee\x52\x8b\xcc\x4f\x6e\x94\xa5\xc3\xe7\x97\xc1\xf3\xcb\xce\xa3\x23\x98\x67\x1d\x47\x53\xe0\xc4\xcc\x33\x44\xae\x28\x62\x18\x33\x53\x17\x51\xe4\x35\x07\x35\x66\x1c\xf8\x03\x48\x1d\x0d\xa2\x1e\xad\x54\x18\xd2\x12\x40\xbb\xeb\x00\xf3\x45\x4f\xa0\x51\x96\x02\xe9\xe3\xab\x98\xc3\xab\xbb\x96\x4f\x7d\xfb\x6d\x44\x31\x31\xb2\xcf\x20\x73\xe6\x75\xd7\x77\xde\xd4\xc8\x9c\x79\x7d\x68\xfd\x07\x9c\x51\x1f\xd7\x83\x47\x65\xfd\x78\xd0\x76\x00\xd3\x49\xe4\x86\x53\xc0\x3e\x60\x04\x7e\x40\x94\x80\x1c\x3b\x32\xe1\x0b\x2c\x48\x4e\x15\x18\x31\xa3\xe1\xa1\x87\x0f\x78\x02\xbc\x07\xa6\x93\x0c\x83\x2e\x30\x47\xd3\x6d\xd0\x96\x46\x6b\xa0\xb4\x6e\xdb\xfa\x7f\x59\x07\xf1\x05\xed\xfa\x94\xeb\x44\x8f\x7e\x8b\xbf\x11\xea\xfc\xa4\xeb\xd3\x9e\x0e\x47\xb2\xc6\x9f\x72\x9d\x99\xdf\x7f\x47\xff\x67\x96\xb1\xa4\x7f\x7a\x19\x07\x28\x44\xcb\xb8\x4e\xb8\x87\xf8\xa4\x8b\x7b\xf8\xa4\xaf\xec\x8f\x46\xcb\xbe\xd1\x1f\xdd\x75\x27\x77\x36\xf3\x06\xb1\x83\xff\x39\xbc\xa4\xeb\xce\xef\x6a\x03\xc3\xcc\x08\xae\x13\xbe\x47\x7c\xcd\xdf\xec\x43\xc5\x4a\xc1\xcf\xb2\x6e\x66\x98\x71\xf3\x29\x66\xbd\x70\x1c\xb0\xc0\xd5\xf3\xef\xb4\xdf\xfe\x38\xc4\x0e\x08\xf1\x29\xe2\x70\x85\x99\x31\x5c\x27\x53\x40\xfc\x39\x03\xff\x17\xfe\x9c\x9c\x2f\x87\xed\xee\xcb\x79\xfe\x8a\xae\x1c\x00\x33\x33\xb8\x14\x78\x9a\xf8\x72\xca\xbe\xc1\x97\xd3\x9d\xf5\x1d\xea\xe9\xc6\x01\x0c\x7a\x81\xfb\x3b\x1c\x27\x70\xc0\x08\x5c\x20\x44\x4e\xb9\x53\x56\x59\x33\x81\xa0\x62\xcd\x59\xcc\x05\xde\x9a\x52\x78\xb2\x51\xaa\xdd\x9a\xd2\xdd\x43\x64\xd4\xca\xec\x2b\xf4\xc2\x55\xa3\x37\x8c\x9e\xb0\x09\x6e\xa2\xdf\xf9\xf9\x13\x27\x2d\x1d\x73\xdd\x72\xf2\x15\xc0\xf4\x21\xee\xb5\x4c\x9b\x70\x08\x38\xc1\x70\x6c\x37\x25\xcd\x54\xca\x4b\xb9\x6b\xe5\x0a\x2b\x36\x12\xb3\x2b\xe4\x42\xaa\x60\xd3\x70\x72\xf5\x40\x95\x24\x11\xb9\xae\xb0\x34\xb9\x08\x6a\xd0\x3d\x76\x18\xd4\x3b\xa9\xa7\x0f\x8d\x99\x77\xfb\x3d\xaf\xbb\x8f\xd9\x26\x0e\x2d\xf7\xcb\xfc\xf9\x43\x45\xb3\xa6\x3d\x35\x60\xd4\x6e\x5b\xb4\x6f\x61\x29\x96\x2f\x3f\xe5\xce\xc2\x27\x35\xbf\xd5\xe8\xef\xaf\x6b\x7c\x3f\x3d\xe3\xea\xef\xe0\xb2\x02\x0c\xfa\x15\xd7\xc9\x2c\xd3\x7c\x35\xdf\x4f\x4f\xf8\xd5\x77\xf2\xd3\x2c\xe7\x3a\xe1\x23\x24\x46\x54\xdc\x23\x46\x74\xc5\xf8\x10\x5a\xfe\xff\x95\xf8\x10\x83\xde\xe2\x5e\x87\x51\x32\xb6\x08\x6e\xc1\xa3\x6b\x99\x94\xda\x13\x54\x46\x88\x44\xf4\xa7\xf1\x54\x56\x5c\xfe\x69\xb4\x14\x5b\x8f\xff\x92\x46\xff\x62\x6e\x1e\xf1\xcf\x2b\x69\x72\xe0\x81\x0b\xbf\xee\x19\x88\x91\x5d\x32\x8b\xde\x1a\x73\x62\xfc\xf6\x71\x27\xc6\xd1\x99\xd1\xd9\x01\xc0\x74\xcd\xe6\x3a\x33\x8b\xb5\xbd\x22\x5c\x5c\xb1\xc9\x98\x91\x2b\xa6\x08\xe5\xe7\xce\x70\x3e\x17\xaf\xcc\xb2\xf3\xd9\xd0\x57\x35\x61\xff\xa8\x76\x38\x0d\xfa\x2a\x27\xfc\x80\xf0\xf5\xfd\xbb\x8b\x46\x3c\x3b\xc2\xb3\xf7\x11\xaa\x2f\x1e\xe0\x3a\xe1\x6c\xe1\x34\x39\x9b\xd7\x91\x1b\xa2\x4b\x71\x53\x36\x05\x09\xd0\xf6\x5c\xa6\x94\x7e\x4c\xb5\x7c\x5c\x48\xea\xab\x92\x4e\x82\x16\xa4\x38\xa9\x0b\x46\xcc\x3b\xb4\x26\x1a\x5d\x81\x32\x49\xc3\x93\x6d\x30\x58\x9e\xaf\x09\xa1\x03\xbb\x93\xd3\x6e\x2e\x7e\xb8\xe2\xc4\x5e\xf4\xe6\xfb\xe3\x87\x46\x86\x8d\x19\xde\x34\x58\x08\x1d\xbe\x61\xc2\xa1\xa3\x70\xd1\xa8\xb1\x0d\x72\x6b\x5b\x3f\xaa\x0b\x35\x72\x9d\x0c\xa3\xf3\x3b\x73\x58\x65\xf8\x54\xdc\xcc\xe0\x29\x9a\x81\x51\x37\x90\xf0\xdc\x68\xe6\x9c\x62\x23\x79\xdd\x9a\xa6\xa0\x1a\x6c\x14\xf8\xaa\xbe\x81\x75\x12\xb0\x57\x31\x48\x83\xcc\x6f\x47\x61\xdb\xa3\x3f\xd6\x98\x1e\xd7\x09\xdb\x76\x6d\xa4\x2c\x0f\x3f\xf3\x31\xf6\x55\x78\x37\xb1\xc9\xca\xbe\x21\xef\x00\x0f\x4a\x73\x0e\x6e\xba\x34\xe7\x20\xb3\x9d\x7d\x15\xde\xda\x6d\x8c\xcb\xe5\x1c\x90\x31\x88\x35\x77\xeb\x65\xf2\x0d\x20\xfb\x2a\x2c\x27\xf9\x06\x35\xdf\x92\x6f\x70\x99\x5c\x03\x78\xf9\x5c\x83\x7f\xc0\xbc\x90\x8a\x66\x81\xeb\xbf\x73\xcc\x4f\xbd\x6c\xcc\x2f\x82\x66\x81\x59\xdf\x3b\xe6\x17\xb9\x4c\xcc\x0f\xa2\x43\xa8\x15\xb4\x66\xde\x04\x22\x58\x41\x78\x84\xa8\x47\x78\x14\x26\x1b\xdf\x11\x8c\xf8\x0e\xf7\x8c\xef\x5c\x12\x66\x7a\xfc\xc2\x29\x0a\xfc\xa7\x85\x99\x14\xc1\x91\x60\x04\xd6\x15\x4a\x88\x02\x0d\xe1\xb0\x9c\xd8\x23\x84\xc3\x06\xa3\xe8\x50\xf1\x1f\x4a\xee\x9d\x7c\x4f\x29\x7a\x73\xfd\x56\xb4\x7e\x2b\xd0\x62\x4f\xad\xa0\x92\xcc\x6b\x15\xc8\x73\x6d\x08\x44\xbd\x16\xe8\x0d\xcb\x73\x74\x10\x8e\x66\xc8\xcf\x9e\x13\xf5\xec\x39\x73\x36\x23\x5b\x9f\xe8\x8e\x0b\x1b\x69\x3c\xcc\x91\x60\x45\xc6\x15\x4a\x08\x22\xed\xff\x24\x64\xe7\xe6\xa2\xc1\x25\xd4\x3e\xb9\xbd\xe4\x7d\xdf\xfb\xa5\xa8\x15\x6e\xdd\xaa\xcd\x2d\x73\x33\x77\x8a\x99\x23\x2c\x06\x3c\x98\x48\x68\xc6\x5f\x86\x66\x3a\x95\xf2\x8d\x03\x2d\xdc\x75\x3f\x85\x5f\xe8\xa0\xe8\x79\xf9\xe1\x3f\x36\x1a\x60\x83\xae\x1d\xc5\xcc\xd9\xa9\xed\x83\xf8\xcf\x6e\x47\x0b\xa0\x1f\xc0\xcc\x0b\x5c\x0b\xfc\x4c\x70\x03\x11\x4b\x7e\xac\xe7\x58\x52\x0a\x17\xc6\xeb\x55\x01\x66\x9d\xd4\x78\xd7\x01\xea\x74\x64\x6c\x36\x8a\x15\x42\x2f\x33\xba\x7a\xf6\x8d\x05\x30\x6c\xbe\x83\x6b\x79\xdb\xbc\xea\xc1\x42\x34\x8b\xc4\x45\x91\x1b\xec\xcd\x7c\x00\x1c\xa0\x1a\x28\xb6\xf0\x15\x43\xa3\xaa\x68\xd3\x1c\x1d\x97\x86\x48\xff\x65\x75\x36\x44\x3a\x7b\x11\xfa\x72\xc9\x5d\xdc\x7d\x75\x75\x95\x61\x61\xbb\x74\x1b\xd9\xc3\x85\x68\x0a\x08\xff\xf3\x62\xa4\x0b\x7d\x0f\x85\xb6\x86\x76\xe7\x62\xa4\x7b\xd0\x14\x30\xfd\x9f\x19\x23\xdd\x53\x08\x8f\x14\x3e\x14\x6a\xaf\xcd\xc5\x48\x37\xa1\x5a\x30\x92\xc4\x48\xef\xfb\xdf\xc5\x48\x4d\x67\xb4\x60\x68\x82\x35\x9a\x0c\xa1\x7c\x2a\x68\x91\xd1\xef\xd7\xa8\xb1\x67\x70\x74\x93\x6f\xb7\x7f\xab\xff\x21\xdf\x4e\x7f\x7b\x59\x36\x38\x0a\x91\x07\x3d\x0e\x7e\x92\xb9\xf5\xbb\xe5\x2d\x78\x48\xde\xc2\xe3\x5a\xde\x42\xfa\x38\x72\x67\xde\x06\x8b\x81\x15\x2c\xa5\x72\x45\x48\xc5\x19\x92\x7d\xcb\x08\x9a\x5c\xb1\x11\xfa\x8a\x44\x41\xd4\xf0\x90\x9f\xd1\x4a\xbd\x48\x91\x83\xb1\x03\x2f\xc6\x60\x14\x5d\xa1\xb8\xc1\x28\xe6\xb7\x7c\xe1\x0d\x04\x73\xc3\x90\xc5\x76\x36\x6b\xc0\x33\xbc\x9e\xc7\x49\x8a\xa8\xd2\xc7\x43\xcd\x0d\x31\x6b\x14\x35\x57\xef\xde\x7a\xdd\xd0\x2e\x67\xff\x01\x90\x41\x5d\xc9\x1f\xfa\xc8\x1d\xad\x46\x35\xe0\x5d\xb0\x18\x38\x40\x0d\x20\x05\x9e\x42\x4a\x3f\xd9\x22\x45\xea\x13\x29\xa8\x76\xb6\x11\x24\x01\x53\x73\xc9\xf9\xd8\xd7\x9d\x5c\x0b\x92\x85\x49\x7d\xfb\x8d\x9a\xb7\xf6\xc1\xf3\x05\x7d\xa0\xf4\x97\x72\x69\xa4\xeb\x1d\x1f\xc9\x2d\xe8\x9a\x83\xda\xd2\x47\x33\x1b\xbe\x5d\xb7\xcf\x8b\x95\x76\xcd\x99\x7d\xdd\xc8\xab\xa6\xce\xd8\x8b\x4e\x4c\x99\x3e\x70\xc0\xa4\x39\x80\x41\x6e\x74\x0b\x78\x3a\xb3\xf1\x1f\xa3\xdb\xbb\xbb\xeb\xf6\xe8\x0f\xf9\xba\x3d\x83\x96\x21\x37\x98\x93\x79\x9f\xf4\x19\xa5\x7a\xb5\xad\x47\xf2\xaa\x06\x23\x9f\xa7\x57\x4b\x39\xbd\x5a\xca\xe9\xd5\x6e\xdb\x15\x62\xc1\x59\xb5\x1a\x2d\x6b\x5f\xb9\x62\xc7\x8e\x15\xcb\xef\x7b\x64\x76\xdf\xc6\xc6\xbe\xa1\x46\xf4\xd5\x82\x8d\x77\xde\xb4\x60\xf3\xc6\x85\xd3\xeb\xfb\xf4\xa9\xaf\xa7\xbc\x7e\x31\x6a\x01\x30\xb3\x05\x18\xb1\x3c\x33\x6a\xb6\xb2\x29\xac\x18\x89\xad\xec\xc0\xb6\xb2\x31\x6b\x2b\x63\xa6\x46\x05\xda\xe2\xa2\xab\x5d\xb0\x38\xb0\x61\x44\x12\x4d\x91\x5f\x8d\xb9\x07\x3d\x3b\x81\xf2\xe7\x0d\xc8\x0d\xdb\x48\x6c\xb9\x45\xab\xf2\xb2\xe7\xf2\xeb\x9c\x84\x21\x5b\xa8\xe9\x62\xe1\xb2\x6d\xe6\x19\xbb\x44\x60\x03\x0c\xd9\xd0\x32\xe9\xb0\x5f\x55\x1d\x95\x45\xba\xb4\xea\x2d\x83\x07\xcd\x1f\x74\xd5\xec\x17\xab\x1f\x78\xea\x91\x29\xad\xe8\xb4\xb7\xad\xa2\xd6\xb8\x6f\x74\xc3\xe6\x5b\x37\x7a\xf1\x3a\x56\x22\x37\xb0\x91\xe7\x36\x7f\x53\x4c\xfb\x9b\xe2\xd9\xf0\x92\x78\x36\x5a\xf9\x4d\x01\x6d\x42\xbf\x5f\xa3\x71\x99\xf3\xff\xb8\xfc\xa6\x5f\xe7\xe5\x37\xa5\x4f\xa2\x56\xf0\x19\xe1\xa9\x9b\x88\x16\xdd\x4d\xd6\x09\x50\x97\xc6\x71\xc0\x72\x91\x48\xa4\x47\xbc\x41\xcc\x96\x3f\x11\x57\x16\x29\x71\x61\x19\xa3\x8e\xaf\xa4\xe4\xf5\x23\x20\xd9\xf7\xb9\x0f\x29\xd7\x8f\x43\x5e\xc8\x71\x35\xd2\x71\x25\x20\xa6\x4f\x8e\x65\xce\x8e\x6d\x6f\x40\xd1\x06\xd4\x0a\x67\xa0\x43\xe7\xce\x01\x98\xfe\x12\xed\x81\x5c\x66\x0b\x28\xc5\x3c\xa9\x24\xac\x78\xe5\xa4\x48\xe7\x69\x8f\xc4\xc5\x12\x12\xf4\x70\x19\x43\x2a\x63\xc2\xb3\x2c\xcb\x73\x01\x6a\x77\x4a\x73\x6c\x28\x66\x6a\x47\xba\x34\x37\x07\x4f\xc1\x68\xcc\x04\x09\xcb\xe9\x54\xed\x5e\x82\x45\x48\x91\xc8\xeb\x1b\xf8\x7e\x51\x59\xab\x98\xc9\x7e\x27\x00\xb5\xd5\x42\xb0\x22\xfd\xa5\x61\x85\x78\xbd\x3c\xde\x31\x5b\x98\x21\x4f\x70\x2c\x17\xc7\xdc\xd2\x7f\xdc\x44\xd7\x88\x1b\x3b\x5e\xef\x5d\x5e\x54\x3c\xb9\x75\x84\xaf\x60\x4a\xeb\x88\x11\x4b\x06\xf6\x0a\x8e\xfa\x87\xc7\x5b\x60\xfa\x00\x5a\x00\xde\xca\xfc\x94\xfa\x8d\x6c\x61\xc5\xa0\x59\xab\x76\x6c\xad\xda\x24\x8a\x91\x0f\xbb\xb9\x8d\x82\xe9\x03\xdd\xfc\x46\x9d\xe8\xce\x6e\x7e\x23\xe4\x45\xa3\xc0\x9f\x32\x8f\xfe\x9f\x7d\x28\x7c\x77\x1f\x0a\xf2\x76\x73\xa2\x3c\x9b\xef\x43\x49\x7f\x82\x46\x81\x9f\xe9\xcf\xfc\x3f\xd8\x31\xb0\xbb\x1d\x93\xfe\x24\xdf\x90\x41\xa3\xf2\x0c\x19\x98\x56\xd1\x34\xf0\xb7\x7f\xa2\xaf\x3d\xad\x7e\x57\x5f\x3b\x44\x12\xda\x05\x9e\xfd\xae\x39\x86\x52\xb7\x1c\xc3\xf4\x4e\x74\x1c\x0e\xcf\x8c\x06\x2c\xb6\x37\x2e\x97\x03\xa5\xfd\x5d\x7a\x67\x29\xbb\xa7\x14\x1d\xdf\xbe\x9d\xc0\xbd\xa7\x7f\x8a\xdc\xb0\x7f\xe6\xf4\x77\x89\xd5\x41\x3d\x56\x97\xfe\x69\x7e\xb0\x0e\x35\xe4\x82\x75\x10\xcd\x82\x4f\xc3\x27\x99\xff\xfc\x7f\x1d\xbb\x80\x4f\x5f\x86\x9e\x13\xe1\x49\xf8\x1c\x73\xf0\x0a\x7e\x43\x42\xc5\x89\x21\x76\x40\x08\x9e\xc4\x54\x84\x69\x07\x3c\xc9\x7c\xf6\x8d\xbf\x9f\x76\x84\xf8\xe7\xf4\xdf\x47\xfb\x60\x08\x2e\x64\x27\x01\x16\x38\x81\xc2\x92\xb8\xa1\x21\x4b\x6c\x23\xf4\x42\xb4\x8f\x99\xbb\x38\xfd\x43\x78\x0e\xae\x48\x22\x92\xcb\x9c\x7e\x25\x73\x1f\xd3\x4a\xf2\x44\xcc\x80\x14\x5e\x93\x5f\xe6\xa1\x0c\xd3\xaf\xb0\x2f\xbf\xd9\x35\x74\x8d\xb0\xed\xe2\x6a\xca\xef\x93\xc8\x9d\x39\x47\x74\xf7\x6f\xcc\x95\x84\x3d\x73\x25\x51\x52\xd3\xd6\xe7\xcc\xdf\x7e\x9b\x13\x15\x51\x6d\x7d\x9b\x73\xf5\xf4\xa5\x77\x81\x6e\xbc\xfe\x4e\xdd\x16\xd4\x52\x48\xb8\x48\x5e\x20\x22\x0e\x19\x41\xe7\xf5\x59\x7b\x2b\x0e\xc9\x85\x84\xf8\x42\xe6\x5c\x3a\xba\x26\xfb\xec\x85\xbf\x6b\xbc\x5e\x65\x9d\x17\x73\xef\x75\x3b\x51\x11\x3b\xd8\x38\xb5\x0e\x73\x06\x58\x20\x2a\xb3\xe9\x93\x63\xdb\xc3\xf0\x57\xe1\x7b\xc7\x62\x5e\xff\xc7\x3f\xa2\x43\x80\x41\xb3\x51\x2d\x98\x94\x79\x93\x9c\xcd\x5b\x75\x89\xc7\xd1\x99\xf2\x11\x6c\x8c\x0b\x79\x52\x2a\x3b\x4f\x62\x5e\x6b\x12\x90\xbe\xa6\x12\xf0\x20\x55\xfc\xeb\xf0\xec\xb8\x9a\x8b\xb9\x8f\x84\x3a\xcc\xbe\xf8\x9a\x8b\x6c\x82\xe3\x85\x7c\xd3\xd5\x15\x60\x2b\xe5\x68\x10\xcd\x9e\x0a\xf7\x4e\x45\xff\x93\xa8\x49\xa0\x5a\xb8\x0f\xcd\x5f\xd6\x81\xe9\xf8\x3e\xda\x03\x3e\xc9\x6c\x01\x65\x58\x16\xf9\xb0\x36\xa7\xd3\x51\x8c\xc4\x7d\xc4\x82\xf5\x01\x63\x48\xb5\x78\x22\x3a\x7e\x7c\xb2\x8c\x12\xab\x8c\x16\x65\xe7\xae\x80\x1d\xea\x69\x93\x6a\x41\x99\xd6\xc1\x49\xf1\x48\x0a\x4f\x12\x70\xc4\x18\x50\x59\x9f\x16\x46\xa6\x35\x77\x5a\xb1\x5d\x50\x2f\x09\xc8\xbe\x48\xbf\x5f\xb0\x7b\xe9\xf2\xca\xd6\x95\x93\x6f\x34\x2e\x17\x2a\x9a\xe5\xf1\xb6\x9b\xf8\x60\xb3\x3c\xd1\x86\xf6\x2c\xdf\x34\x7a\xf4\xe4\xc9\x95\xe5\x25\x9e\x40\x63\xeb\x08\x9f\xa7\xa2\xb1\x95\xfa\x1a\x32\xa7\xff\xef\xb9\x5d\xb5\xbb\x67\x2f\x9a\xbd\x7b\xe4\x43\x37\x2e\x99\xbd\xbb\x47\x6e\x17\xcc\x74\x71\xfb\xe1\x66\xe1\x13\x50\x08\x06\xe4\xf3\x18\x5b\x58\x2b\xaa\x22\x15\xa0\xdc\x19\x2d\xc1\x4b\x31\xe6\xca\xd4\x01\x01\x1e\x50\x8d\x05\xf4\x79\xf8\xa8\xd7\x31\x04\x24\x4c\xc4\x26\x6a\x19\xe3\x71\x0b\x5c\xc1\x80\xf1\x05\xc5\x05\x93\xb6\xb5\x79\x5b\x26\x16\x14\x17\x1c\xe6\xf6\x2f\xac\xaf\xf2\xd4\xf7\x6b\x2e\xeb\x3f\xbd\x61\x81\x1c\x70\xf5\x95\x5b\x2a\xa6\xdc\x42\x78\x5e\x66\x34\xff\x17\xe6\xb4\x78\xe4\x7b\xe5\x27\xbc\x90\xcf\xf2\x04\x53\x5e\x7e\x02\xcc\xec\xe6\x3a\xe1\xc0\xef\x9a\xb7\xbe\xec\x92\xbc\xf5\x7f\x68\x0e\x3d\xcb\x9d\x65\xc6\xfc\x83\xe2\x3d\xec\xe5\xe4\xd9\x77\x0d\xf7\x00\x98\x79\x83\x5b\x09\x6f\xe0\x9f\x07\x06\x10\x04\x71\x96\x01\x21\x9a\x21\x9e\x5d\x99\xe3\xf2\x2b\xeb\x7f\x4d\x0d\xf4\x95\x6d\x1d\xc2\xad\x2c\x8e\xaf\x77\xc7\x9e\x1b\x81\xf7\x4c\xe4\x8e\x33\xcd\xc2\x5a\x60\x02\x2e\x50\x06\xae\xa2\xe3\x29\x5e\x59\x35\x9a\x53\x4a\x69\xf6\x7a\x09\x56\x50\xc5\x85\x14\xc1\xa1\xba\x61\x28\x59\x4c\xde\x11\xec\xf0\xb8\xd9\xee\xa2\xb5\xac\xaa\xe4\xd0\x0b\x5d\xe2\x66\x8b\x2b\xd6\x23\x60\x50\x49\xe2\x6b\x1e\x41\xcc\x43\xeb\xbd\x38\x61\xf8\x80\x81\xa3\xc6\xae\x83\x61\xcf\x98\x22\xc8\x4d\x7f\x68\x89\xf6\x01\xdf\x67\xe2\xa4\x98\x3c\xe6\xba\xd5\xc5\x7d\x5e\x18\xe7\xde\x71\x48\xa4\x6f\x01\x44\x1f\x21\x37\x18\x9f\xd9\x03\xec\x60\x18\x20\x5d\x63\x2c\xa9\xb8\xc1\x8a\x59\x82\x81\x04\x93\x1d\xfa\x74\x25\x2e\x14\x17\x08\xcf\x15\x4c\xc6\x90\x2a\x10\xa3\x01\xd3\x9f\x16\xa3\xd2\x96\xea\xc4\x5c\xc8\x33\x58\xd1\x47\x6c\xaf\x53\xbe\x41\xd5\x15\x2d\x33\x67\xac\x40\x6f\x5a\x4a\x9e\xbe\xdb\x11\xb5\x3c\xe3\xbb\x91\xc8\x8d\x2f\xb8\xe3\xcc\x06\xa1\xe8\x9f\xa0\xcb\xe7\xf8\x7b\x9e\x2e\xaf\xa3\x54\x7e\x83\x2e\x8f\xbe\x18\xc3\x0e\x19\xdb\xde\x90\x3e\x11\xe6\x8e\xc3\x1b\xd0\x13\x7f\xfc\x23\x60\xd3\x3f\x46\x6e\xd8\xf4\x7d\x75\x8f\x1f\x5f\x49\xf7\x60\xd0\x5b\x68\x1c\x8c\x12\xfb\xe8\xff\x37\x62\x15\xd4\xb8\xd2\x63\x15\x10\x1d\x47\x6e\xd0\x96\xd9\x0a\x78\x30\x12\x60\x9d\x8e\x95\x7b\x7a\x15\x2f\xe3\x47\xfc\xf1\xe7\xcc\x15\xfd\x88\x7c\x14\x93\x17\x1d\xf7\xc1\xf5\x93\xb6\xca\x5f\xae\x47\x3b\xbe\xc4\xf7\x4e\xe6\x1e\x60\x6a\x84\x5a\x82\xab\x4f\x0e\x9a\x9c\x34\x92\x27\x24\xbc\x46\x87\x21\xa4\x99\xc8\x8a\x25\x42\x40\xf6\xc1\x19\x7c\x4f\x08\xa3\xf5\x3a\x24\xa7\xea\xf4\xc4\x62\x2a\x63\xc4\x2c\x9e\x20\x5a\x63\x2e\x80\x59\x7c\x81\x1e\xa7\xa8\xa8\x16\xab\xa3\x44\xd4\x9c\x88\xbd\xd8\x7f\xe8\xd0\x19\xc3\x2a\xcb\x7b\xcb\xc5\xab\x2b\xd6\xdc\x10\x1d\x3f\x76\xc6\xd8\x0a\x5f\xdf\x70\x01\xd7\x09\x85\xca\x55\xd1\x9b\x0b\xc2\xc3\xee\xbc\x27\xbc\xa1\x79\xad\xbd\x7f\x0c\xdf\xe3\xf1\xdc\x7a\x66\xa4\xd8\x0e\x0a\x40\x05\xa8\x03\xb7\x01\xa5\x9c\xb4\xfb\x56\x5c\xd9\x34\x56\x73\x24\x61\x60\x5d\x86\x90\xee\xb0\x00\x11\xa5\x6f\x58\xad\x32\x51\xe0\xae\xe0\x99\x64\x0d\x8d\xa9\x10\x24\x93\x52\xfa\xba\xc6\xa1\x9a\x61\x48\x53\x89\xd4\xa0\x57\x72\xaa\x2e\x36\x16\x53\x4a\xa5\xe7\x04\xa9\xb8\xbc\xaa\x6f\x2f\x6f\x4c\xa9\x71\xaa\x06\x5a\xa7\xca\x62\x09\xda\x93\xb3\x79\xaf\x90\x93\x92\x2c\xd9\x38\xad\xae\x6d\xd4\x80\xc2\x50\xbf\xc2\xd5\x23\x12\x7d\x26\x8c\x1c\xea\x0f\x45\x0a\xda\x26\x0c\x6d\x20\x31\x99\x15\x7a\x70\x86\xdf\x70\xd7\xdd\xc1\x50\xb0\x71\x10\xfa\x2a\x18\x0a\xf6\x8f\xed\x1f\x35\x2e\x22\xb7\x5e\x2d\x33\xa3\xb3\xd1\x1a\x26\xd3\xc2\x9d\x65\x26\x0a\xe7\x80\x17\x84\xc1\x70\x8d\x8b\x99\xe5\xa4\x9b\xee\x8f\x81\x75\x1b\x42\x7a\x04\x94\x2c\x3c\xe9\xd3\xe0\x7f\x23\x89\x72\x5f\x5f\x43\x28\x59\x4d\xdf\x17\x46\xa0\x52\x1f\xee\xb1\x16\x02\x80\x4a\x16\x73\xf9\x4f\x5f\x2f\xd9\x38\x3d\x34\x6a\x60\x63\x71\xef\x86\x82\x5b\xcb\xb7\xb6\x85\x46\x0e\x68\xf2\x05\x6b\x4b\x1b\xb5\xcf\x8b\x6a\xea\x0b\x56\x97\xdf\xd3\x16\x1a\x31\xa0\xa9\xa4\xba\xce\xcb\x9d\xbd\x79\x7d\x49\xa0\xa4\xa6\x7e\xe5\x1d\xbe\x40\x49\x79\x33\xf4\xaf\x5c\x5f\x12\xf0\xf5\xae\x5f\xb9\xde\x17\x28\xe9\x5d\x0f\x60\x1a\xa1\xc1\xe0\xad\xcc\x0b\xc0\x88\xef\xaf\x21\xe7\x7e\x31\x85\x81\xca\x18\x30\x03\xe3\x09\x03\xab\x14\xe5\xa8\x97\x8f\x06\xc5\x34\x82\xd5\xbe\xb7\x7d\x9d\xe8\x6c\xf1\xbf\xfa\x50\xd7\xf1\x4d\x9b\x8e\xbf\xbc\x69\x53\xf6\x7e\xc8\x99\x13\x40\x00\x57\x01\x85\x0f\x2b\x5c\x7e\x1e\x1d\x56\x79\xb9\x4b\xae\x85\x4d\x11\x88\xeb\x98\xed\x00\xc4\xad\x0f\x75\xe7\x3e\x04\x2a\xe4\xf1\xe3\x19\x92\x0f\x12\xf5\x12\x27\xe9\xf1\xff\xda\xb9\x4e\x6e\x6f\xfc\xf2\xb5\xd7\xbe\xfc\x12\xdf\xc9\xc2\x74\x25\x00\xcc\xbb\xfc\x31\xc0\x03\x23\xc1\x64\x0e\x82\x5a\x10\x05\x43\xc1\x38\x70\x0d\xb8\x0e\x5c\x0f\x6e\x02\x4b\xc0\x6a\xb0\x01\xb4\x83\x9d\xe0\x51\x70\x10\x1c\x06\x0a\x38\x06\x5e\x62\x96\x6b\x08\xbe\x93\x7f\x2c\xeb\x5a\x9f\x7a\xed\x91\x48\x84\x7e\x0a\xb9\x94\x72\x34\xa2\x40\x87\x32\x13\x9f\xd2\x39\xd4\x37\x6d\xc6\x22\x70\x5a\x5c\x96\xb5\xa3\xad\x4e\x55\x23\x11\xfa\xa9\x89\x4b\x29\xc9\x88\x62\x72\x28\x6d\xe5\x67\x24\xe5\x0e\x39\x39\x91\xee\xf3\xda\x48\x7c\x31\x04\xa1\xe4\x7c\x6a\xcf\x8d\x19\x0e\xe6\x5b\x43\xca\x72\x39\x39\x86\xfe\x7c\x55\x24\xd9\x58\x4f\x3e\xbb\x53\x4e\x36\xd2\xcf\xb6\x46\x92\x81\x52\xf2\xd9\x43\x7a\x1f\x33\x65\x6f\x24\x29\x0a\xe4\xb3\xe7\x65\x55\xe4\x52\xca\x0b\x91\x44\xa1\x28\x18\x42\xca\xb3\x72\xd2\x49\x7f\xe7\xc9\x48\xb2\x3a\x44\x7e\xe7\x71\x59\x3f\x67\x8f\x45\xd4\xfe\xf3\x1d\xe5\x1d\x61\xe5\x7e\x39\x39\x98\x7e\xb6\x23\x02\x95\x9f\x51\xd7\xa7\x29\x12\xd1\x98\x95\x6a\xb0\x45\x22\x2a\xef\x48\x29\x96\x08\xd6\xf7\x3d\x78\xe1\x3a\x4c\x75\x58\x53\x36\x12\xc5\x3c\x30\x84\x94\x5e\x72\xd2\x4f\x7f\x52\x13\xc1\xaa\x77\x1d\x0c\x29\xcd\x91\x64\x84\x7e\x36\x20\xa2\x44\x1c\xea\x64\x18\x52\xa6\x46\xd4\xeb\x1c\x29\x65\x7a\x24\x31\xf2\xba\xc9\x86\x50\xb2\x95\xfe\x42\x6b\x58\x19\x2f\x27\x47\xd2\x37\x93\x22\x89\xd9\xe4\x87\x33\xe8\xfb\x19\x61\x65\xae\x9c\x9c\x4d\xdf\x2c\x8c\x24\x96\xe2\x1f\x2a\xb7\xc9\xc9\x95\xf4\xa3\xdb\x23\xca\x75\x0e\x75\x17\x0c\x29\xfb\x22\xc9\x3d\xf4\xb3\x1f\x45\x12\x77\xed\xd9\x65\x08\x25\x37\xd2\xf7\x1b\xc3\xca\xbd\x72\xf2\x2e\xfa\x66\x7b\x44\xd9\xe5\x50\x9e\xc0\xcb\x79\x9a\x7e\xb2\xc7\xa1\xfe\x04\x86\xd4\xe7\x9e\x8f\x44\x92\x0a\x5d\x7c\xe2\x45\xbc\x78\x16\xb3\xcf\xc2\x58\x4c\xf5\x38\x24\x67\xa2\x34\x50\x1d\xea\xe5\x8d\xa9\x7b\x76\x49\xce\xe7\x9e\x7c\xf6\xc7\x47\xd4\x38\x7e\xfb\xf4\x13\x92\x33\xf1\xd0\xde\xc7\x1e\x27\x09\xf7\x90\x95\x9c\xcf\xb5\x8e\x9c\x31\x7b\xe9\x4a\xfc\xc3\x89\x6d\x92\x53\x9d\xbb\x30\x16\x53\xe7\x2f\x96\x9c\x89\xf1\x93\x6e\xbb\x9d\x60\x25\x05\x48\x46\x18\x94\x64\x89\xe6\xae\xb9\xfa\xe9\xfc\xc9\x4b\x5d\xc2\xc1\x8a\x2a\x29\xfb\x0a\xff\x94\x32\x2f\x29\xfb\xaa\xe7\x67\xc1\x0a\x57\x63\xc0\x03\x1b\x03\x1e\x56\x7b\x9f\xfd\xfc\xd2\xdf\xbc\xe2\x78\xf8\xaf\xb4\xa7\x7a\xb3\xc3\xca\x8d\xb2\x04\x49\x4a\x5c\x11\x94\xa5\x74\xe5\xf2\x53\xe8\xd5\xe5\xcb\xe1\xe0\x53\x6b\x9a\x7d\x25\x25\xbe\xe6\xca\x12\x5f\x33\x7d\xd5\xec\x2b\x99\x1a\x6d\xf6\x17\x15\xfa\xe9\xd7\x5d\xd1\x68\x59\x51\x51\x59\x34\x1a\x8d\x8e\x80\xc3\xd1\x71\x38\xbc\x33\xaa\xfd\xa7\xe4\x7e\xb4\xb3\x39\xea\x2f\x2c\xf2\xd3\xaf\xb3\x9b\xa3\xd1\xe6\x92\x92\x68\xb4\xb9\x1a\xbf\x32\x9f\x5e\x8a\x5e\x85\x83\x97\x2e\x85\xad\xa7\x57\x30\x2d\xb0\x15\xbd\xc2\x0c\x80\x83\x97\x9f\x42\x73\xc9\xdf\xaf\xc3\x43\x94\xc1\x75\xf8\xcf\xcb\x50\x9f\x68\xb4\xa4\xa4\x84\xf9\x01\xf9\x96\x1e\x44\x66\xc5\x5e\x17\x8d\x46\xbf\x7e\x65\xc5\x0a\x7e\xf4\xf2\xe5\x5f\xbf\x13\x8d\x36\xb3\xcf\x45\xa3\xcd\x5d\xef\xe6\x7e\x9a\x9e\x9e\xff\x77\xa8\x6f\x34\x1a\x85\x8f\xe0\x11\xd7\xe1\x1f\xce\x58\x71\x1a\xbd\xc2\x8f\x5e\x8e\x5e\x3d\xd5\xf5\x39\x9e\x00\x00\x10\x18\xb8\x17\xe0\x54\xa1\x0d\x58\x40\x2f\xa2\xe7\x08\x1a\x63\x23\xed\x71\x15\x3e\xa2\x9a\x1c\x29\xd2\x49\x8c\x86\x73\x5d\x8d\x4d\xd1\xaa\xea\x46\xb9\xc0\xeb\x11\x44\x43\xf5\x9e\xe5\x57\x79\xcf\x4d\x5d\xfb\x2a\xf7\xc2\xa2\xe2\xb1\x4d\x0d\xf3\x6f\x2e\xdc\x5e\xb6\x80\xe4\x87\x47\xb9\xa3\x70\x9e\xb0\xf5\xdb\xea\x1e\x5d\x3d\x83\x7a\xd1\xee\xf5\xeb\xbb\xbb\xd7\x3d\x32\x99\xe1\x5c\x27\xc3\xe5\x72\x1f\x68\x8e\x03\x66\xf0\x5a\x80\xd6\x40\xcc\x5b\x03\x30\x52\x55\x8a\xe6\x3e\xe4\x5c\xab\x97\xe6\x3e\xf0\x79\xb9\x0f\xac\x21\x2b\x86\xcb\xa5\x60\xbf\x9e\xd2\xf7\x78\xc5\x89\xbd\x30\xb6\xfb\xb9\x69\x2b\x8b\xc7\x66\x85\xeb\xe6\x43\x47\xd1\xd1\xc3\x37\x4c\x68\x1d\x3d\xb6\x41\x1e\x76\xb5\x0c\x20\x7a\x0d\x45\xc1\xe8\xcc\x71\x60\xa6\x39\x8c\x9a\xcd\x6a\xd6\xb2\x16\x89\xcd\xaa\x98\x22\xd8\x06\x73\x60\x9b\x20\x42\x92\xe8\xe2\xbc\x68\x26\x40\x49\xac\x88\x2d\x1d\x83\x26\x1e\x34\x1b\xb6\x3a\x8a\x5e\x9b\xb2\x70\xee\x8d\xf3\x16\x4c\x59\x34\x77\xf6\xdc\x7d\x53\xe6\xcf\x9d\x3d\x77\xd1\x94\x05\xf3\x6e\x9c\xab\xd5\x58\x21\x37\xa8\xc9\x1c\x05\x56\x5a\x63\x95\x64\xb4\x7d\xb4\x85\x15\xeb\x19\xd5\xe0\x48\x29\x5c\x84\x6a\xee\xac\x40\x16\xc9\x53\x27\xae\x1e\xe9\xef\x5c\xfb\xaa\x37\xfc\xc0\xcd\xe3\xbc\xbb\xd6\x86\xcf\x96\x2d\x58\x58\x3e\x22\x1a\x5e\x30\x46\xb6\x61\xbd\x8d\x21\xfa\xe1\x51\x7a\x46\x68\x4e\xa6\x7e\x46\xc4\x33\x0a\x88\xa8\x9c\x23\xa5\x72\x22\x6d\xc0\x51\xdf\x20\xd2\xd3\x11\x24\x47\x05\x79\xdf\x99\x7b\xeb\xeb\xde\x9a\xdd\x8b\xae\x69\x5b\xec\xdf\x56\xba\x68\x51\xc9\x68\xb9\x1f\xcd\x4b\x0e\x20\x37\xa4\x73\x2e\xd5\x32\x09\x0a\x4a\x64\x39\x3b\x7c\x59\x18\xa8\x00\x8b\x6a\x89\x34\xb0\xe0\xf1\xb0\x36\xa8\x8d\x0b\x07\xc1\xa8\xac\xb9\x8d\x45\x41\x0c\xa2\x40\xc1\xe9\x05\x11\x65\x6a\x01\x7e\x12\x5c\x5a\x71\xad\x67\x9b\x73\xaa\x6f\x61\x5d\xac\xb0\xd6\xbf\x08\x3f\xd9\x32\xb6\x9e\x3c\x1a\xfd\xb9\xf5\x77\xc3\x27\xfc\x57\x6d\xe1\x90\x27\x07\xac\x89\x10\x7b\xf0\x22\x77\x14\x56\xeb\x67\xf5\x7b\xd4\xfe\x8a\xdd\x30\x1c\xe2\x3d\x6b\x7f\xf3\xea\x28\xbf\x7b\x7c\xee\xd2\x1a\x4a\x88\x1e\x40\x6e\x30\x38\x13\x07\x36\xd0\x9f\x20\xbe\x98\x74\x1f\x08\xf1\x3b\xb3\x67\x14\x5b\x44\x57\x41\x0c\x11\xd2\x25\x2b\xc1\xf0\x26\x0b\x2d\x9c\xb2\xe8\x7e\xf6\xa8\xb7\x5a\x16\x73\xc7\xe9\x81\xda\x4d\xc5\x3b\x7c\x9b\x6a\x77\x2c\x5a\x35\x64\xf0\xaa\x45\xe8\x5c\xfb\x88\x1d\x3b\x46\xb4\xbb\x6f\x9a\x72\xf7\xdd\x53\x6e\x22\x3e\xd8\xd3\xc8\x0d\x3e\xc8\xbc\x0e\x5c\xc0\x0f\x42\x60\x23\xc0\x04\xb1\xea\xfd\x20\x94\x60\x44\x29\x0d\x2b\x35\x79\xbe\x25\x0d\x99\x3c\xe9\xa6\x73\x71\x53\x10\xa8\x72\xfa\xae\x9c\x60\x05\xeb\xbe\xa4\x62\x37\xde\x57\x96\x00\x85\xa9\x76\x3e\x16\x53\xaa\x9c\xaa\x95\xc0\xc8\x78\x25\x0a\xab\x5f\x2a\xd1\x6e\xfd\xac\xe6\x5d\x22\x9c\x22\x4b\xa7\xea\x9e\x39\x74\x7c\xde\xeb\xf4\xe9\xb5\x0b\x56\x45\x1b\x57\x2d\x58\xbb\x76\xc1\xaa\xc6\xd8\xcd\x0b\xd6\x2e\x6d\x69\x96\x87\x0c\x8d\x34\xb4\xc2\xb6\x21\x72\x73\x0b\x7e\x85\x3e\x99\xb3\x7a\xd2\xa4\xd5\x73\xe6\xad\x6e\x6b\x5b\x3d\xaf\x69\xe0\xc0\xa6\xa6\x01\x03\x9a\xb4\xef\x84\x87\x01\xee\x75\xb8\x55\x18\x0e\x44\xd0\x46\x35\x62\x2d\xa4\x13\x17\x59\xbd\x88\x25\xce\x8a\xdd\x6a\x5d\x60\x7e\x3e\x72\x1e\x7b\x61\x34\x8c\x4a\x5e\xd0\xc1\x60\x24\x1a\x22\x8f\x8e\x5c\x58\xd9\x35\x72\x61\x25\x3f\xf1\xcb\xfb\xff\x7a\x1f\xbd\xcb\x1f\x22\x37\xf7\x65\xe6\x30\x30\x83\x52\x7a\x6e\x2c\xa9\x38\x6b\xcc\x4b\xed\xc2\x4c\x84\xa4\x22\x17\x04\x22\xbd\xa2\x32\x08\x94\xf7\x42\x1f\xbe\xbc\x1d\x3e\xd8\x01\x07\x2f\x3d\x81\x3e\x4d\x9f\x40\xa7\xd0\xc3\x53\xde\x9e\x37\x1f\x2d\x3e\x49\x7d\x1e\x7f\xe3\xe2\x82\x41\x18\xfd\xad\x63\xb2\x79\x63\x1a\x2f\x19\x52\x18\x9d\x3f\xe6\x07\xdc\x59\x6e\x19\xbf\xf0\x1b\x7d\xfb\x6c\x34\x20\x96\xfa\xb9\x25\x7e\xee\xec\xce\x9d\x00\xa2\x1f\xa2\xdf\xb2\xbd\x33\x8b\xbe\x35\x1e\x80\x7e\x88\xff\x08\xfd\x76\xe7\x4e\xfa\xac\x97\xb8\x77\x05\x1b\xc1\x66\x7b\x11\xdb\x8e\x2a\x90\x64\x59\x35\x5a\x52\x8a\x21\x92\xf0\x60\xeb\x51\x71\xcb\x78\x51\x2a\x67\x89\x44\x88\xd3\xae\xa9\xf8\xa5\xcf\x6f\x79\x75\x10\x31\x52\xdd\x75\x8a\xa1\x0e\x1f\x48\xae\xcf\x45\xc5\xe0\x50\xa5\x3e\x17\x5f\xfa\xeb\x8a\x8e\x73\x04\xef\x8f\xc0\x18\x1a\x5c\xa1\x84\x40\xbe\x8a\xf8\xab\xe2\x76\x24\x9c\x6e\xc9\x15\x4a\xb8\xf0\xd7\x38\xcf\x19\xf2\xa0\xd8\x84\x98\x22\xc6\xe2\x2e\xb7\x84\xdf\x38\x63\x20\x29\xf0\x22\x2d\xcd\xab\x83\x43\x8c\x02\xc7\x8b\x06\xc9\xe9\x72\x77\x43\x4c\xd6\x4d\xa2\x02\x2f\xc1\x74\xcf\x37\x7f\x46\x86\x3b\x1f\xba\xe1\x67\x7b\x1e\x54\xa6\x8f\x5e\xe9\x7f\xb4\xef\x7b\x7b\xd6\x9c\x7a\xf3\xcd\xe5\xa3\x56\x95\x72\xef\x3e\x7c\xc8\x5b\xee\x2f\x6c\x6e\xda\xf9\x54\xb0\x26\xd8\xd2\x44\x69\xf1\x3a\x17\xe7\xdf\xd1\xf7\xd2\x10\x56\x19\x4b\x2a\x6e\x60\xba\xc9\x3d\xba\x97\x20\x50\xce\x79\x83\x55\x81\x0a\x4e\x6c\x81\x12\x13\x81\x61\xb8\x44\x3e\xbe\x1d\xad\xe8\x40\xbf\x58\xc6\xc5\xe1\x9e\x93\x6f\xbe\x3d\x6f\xbe\x16\x03\x0f\x71\x0a\xb1\x71\x8a\x41\x7e\xd9\x5f\xb6\x50\x88\xe4\x7e\x46\x03\x8d\x56\xd8\x88\x16\xfb\x79\x2b\x2c\x46\xff\x85\x8e\x6d\xdf\x76\xea\xd4\x36\x2c\x97\x2d\x4c\x0d\x3c\xc6\x03\x20\x81\x12\x70\x35\x88\x17\x63\xdb\x80\xd3\xc6\xa0\xe8\x4d\x4e\xad\xe4\x91\x9a\xc4\x1a\x1f\x30\x3b\x25\x67\x82\xb3\x93\x2a\x4f\xc5\x24\x25\x45\xc1\x62\xf5\x12\xc6\xc5\x15\x4b\xce\xb8\x60\x30\x6a\x7e\x30\xe2\x5b\xa6\x09\x5b\xc1\x1e\x61\xfe\x2f\xae\x7b\x78\xea\xed\x11\x21\xb8\x73\xf7\x03\x06\x6e\xf2\xea\x19\x8b\x7e\x3e\x69\xd8\xa2\xba\xde\x43\xe7\xb1\xd5\x6b\xff\xb0\x79\xe1\xf4\xf4\xb0\x19\x0b\xef\xb9\x73\xf9\x0b\xed\xb5\xb1\xe3\xa4\x76\xa4\x86\xa9\x81\xfb\x78\x00\x8a\x40\x05\x58\x0a\x14\x6f\x38\xe9\xa0\x2c\xcc\x14\x4e\x16\xd3\x57\xe5\xe1\xec\xec\x83\xf9\x05\x9b\x56\x87\x5a\x96\x4b\x98\x2c\xb3\x4a\xce\xa4\x99\x73\x78\xc9\xf4\x45\x49\x75\xb9\x31\x07\x73\x78\xf5\x56\x62\xa4\xa9\xae\x5a\x5e\xac\x75\xee\xa4\xcb\xa0\xc0\xf1\xa2\xd6\x5e\xd4\x43\x70\x0d\x69\x07\xfb\x60\x85\x70\x76\x8e\xb2\x6a\xf9\xc6\x33\xaf\xf8\x99\xa1\x03\xea\x66\x8c\x18\x72\x4b\xeb\x5d\xbb\x4e\x97\xce\x59\x3c\xb4\xff\x8d\x6c\xf4\xce\xff\x58\x3d\x6f\xc6\x9a\x3b\xac\x96\xd8\x70\x6f\xe0\xc1\x32\xef\x76\x58\x30\x28\x32\x60\x1e\x5e\xd3\x01\xa6\x11\x06\x05\x01\xb0\xc0\x06\xd6\x12\xcf\x9e\xa8\x55\x59\x67\x5d\x49\x09\xb6\x07\xa0\x9b\xe6\x55\x82\xb4\xd1\xaa\x16\x23\xd5\x62\xe3\x71\x1d\xbb\x50\x61\x48\x60\x82\x2d\xbb\x88\x59\x1a\x2c\xbb\xc8\x24\x00\x64\xd8\x2c\xde\x20\x83\x8d\x0b\x51\x73\xcc\xba\x64\x73\x9e\x2c\x9b\xfd\xf0\xcb\x7b\x4c\x03\x9b\x6a\x1b\x9a\x63\xb3\x99\x46\xe6\xe5\xf4\x30\xf6\xa6\xa6\xe6\x9a\xa0\x3c\x90\xe2\xe8\x05\x99\x1a\x78\x80\x07\xc0\x0c\x3c\xe0\x2a\x10\x77\xc1\x5c\x75\x22\x81\x4e\xcf\x26\x87\xe8\x9e\x61\x0a\x0d\x94\x97\x12\x22\xe9\x29\x21\xac\x11\x13\xde\x65\xc3\x96\xb5\x70\x69\xaa\xb5\x4e\xdd\xf7\xde\x7e\x66\xe3\xf6\x37\x7e\xb2\x6e\xe7\xf1\x99\xa3\x67\x4c\x1f\x33\x8b\x6d\x3c\xf5\xd5\x23\x77\xfe\xea\xef\x3b\xd7\xdf\x72\xf8\x8e\xf5\x49\x00\x33\x26\xa6\x06\xbe\xc0\x7d\x01\xbc\xe0\x5e\xa0\xab\x8f\x9a\x8f\x8d\xd5\xc0\x6b\x25\xea\x8d\xb4\xc2\x90\x16\xf0\x4d\xd8\x09\xf6\x6d\xce\xa8\xb4\x67\xfd\x01\x83\x7d\x7f\x9d\x4c\x29\xc9\xd6\xd9\x14\xa6\x83\x53\xb9\xd0\x45\x9b\xc2\x93\xfe\xe3\x1c\x4f\xab\x79\x35\xc7\x19\x24\xa2\x5b\x35\x7a\x62\x31\xd5\xee\xd0\x91\x8f\x48\xba\xbf\x0e\x1e\xa7\x43\xde\x91\x33\xf3\xa5\xfd\xaa\x9f\x4f\x31\x0d\xeb\x3f\xab\x68\xc8\xf1\x87\x1f\xb4\x0a\x7d\x16\x8f\x9d\x3e\x95\xb9\x30\x64\x14\x5c\x8f\xe6\xf6\xae\x98\xf0\xd0\x1d\x30\x98\x1e\xba\x79\xd0\x55\xcb\x00\xcc\xb4\x32\x35\x70\x33\x0f\x40\x01\x18\x42\xfb\x4c\xeb\x01\x2b\x77\x8e\xc8\xde\x3c\x22\x03\xd5\xe6\xa6\x4d\x91\x8d\x52\x1c\x88\x52\x5e\x43\x3c\xed\x32\x6a\x65\xd6\xe4\x0c\x63\x2a\xbf\x72\xfd\x33\xcb\x16\xcf\x6b\x99\x30\xf8\xea\x45\x8b\xeb\xaf\xee\x3b\xfb\xe6\x8d\xf7\xb0\xa1\x2d\xbf\xbd\xbd\x76\x67\x2f\xf5\x8e\xb5\xa5\x05\xfb\x1a\xb6\x02\x26\xc3\x31\x35\xf0\xbc\x20\x10\x3f\xdb\x2f\x40\xbc\x3c\x9f\x4f\xd0\x9b\x96\xab\x0e\xb7\x53\x0a\x6b\x30\xc2\x58\x75\xb7\xe6\x8e\xe8\x53\x17\xfe\x4c\x09\x6b\xa9\x53\x6c\x75\xf8\x4c\x58\xfb\x5e\xb4\xe1\x5f\xf4\xf5\xbd\x98\x30\xf9\x2c\xae\x50\xc2\x4c\xbe\x96\xe0\xaf\xf1\x12\x9f\x25\x8f\x83\x9b\x62\x8a\x39\x06\x8e\x59\xac\x36\x93\xd9\x57\xa2\xa3\x69\x26\xf4\x37\x14\x49\xd3\x8b\x79\x93\xbb\xa8\x9c\x74\xeb\x90\x12\xa2\x43\xa2\x0d\x62\xb8\x72\x7c\xe4\x0d\x39\xc6\x54\xe0\x95\xfb\x61\x7d\x34\xbb\x35\xd1\x5c\x27\x08\xa1\x6b\xca\xc3\xd3\x1a\xc6\xf6\xe2\x4d\x96\x9a\xe3\xff\xb6\xcb\xca\x57\xcd\x1c\x3e\x63\xd1\xcf\xa7\x84\x46\x47\x6a\x6b\x5a\x6f\x62\x6b\xd6\xfc\xe7\x5d\x7d\x07\x38\x66\xb7\xbc\xd6\x15\x9e\x51\xdf\xdc\xbe\x69\xf9\xc4\xc7\x47\xcb\x2d\x2f\x03\x88\xce\x31\x8d\x70\x87\x20\x80\x42\xf0\x7b\x70\x59\x24\x52\xc5\x11\xd1\x80\x0a\x15\x6b\xe4\x0a\x78\xa4\x5a\x76\xe1\xfb\xfa\x7d\xb6\x51\x2c\x52\x4c\x2b\xa6\xe3\xa5\x41\xf1\xcf\xab\x74\x2c\x52\xc5\x5a\xa7\xd8\x1d\xaa\xad\xef\x45\xcc\xe6\x1c\x7d\x2f\xbe\x34\x68\xff\x85\xe3\x44\x44\x7e\x1b\x30\xe9\x10\x13\xe6\x09\xdd\xb1\x49\x31\x3d\x21\xc3\x7a\xbf\x15\x99\x14\xba\xe4\xcb\x82\x74\xa2\x73\x27\x5f\x0e\x06\x3d\xfc\xe4\x95\xd7\x4f\xb3\xb5\x1d\x9f\x62\x1a\xd9\xff\x06\xdf\x40\xa6\x91\x3d\x75\x78\xf3\x88\xc5\xcb\x6f\x68\x6e\x46\x2b\xe1\xbe\xbe\x65\x13\x1e\xdc\x88\xde\xc3\x32\xcc\xcd\x34\x32\x23\x79\x00\xaa\xc0\x45\xa0\x21\x87\xeb\xd9\xb8\x55\x3d\x58\x5f\x55\xd6\xa1\x5e\x0a\x43\xc9\x12\xfa\xae\x84\x06\x3f\x35\x0a\x3a\x22\x09\xa7\xbd\xc0\xa0\xa3\x98\x2a\xae\xb0\x2e\xc2\x9a\x8a\x5f\x1a\xf8\x97\x4f\xdf\xa1\x74\x2b\xad\xb3\x29\x65\x1d\x9c\x5a\x52\x7b\xd1\xa6\xf8\x3a\xf0\xc1\xfc\x88\xfe\xc4\x55\xa7\x38\xea\x14\x97\x43\x75\x62\x62\x3b\x1c\xaa\xbb\xef\x45\xc5\xe9\x48\x48\x4e\x87\x2b\x14\x97\x9c\x8e\xbc\xac\xc3\x21\x46\xa7\xcb\xed\x2b\x29\x2d\x73\x48\x79\xe4\x73\xfb\xca\xa4\x1c\xa3\x85\x7a\xd3\xbf\x92\x52\x7c\xfe\x2a\x62\x31\xc5\x25\xd1\x26\xa5\x4e\xa7\x6a\x29\x8c\xc5\xf4\xcc\x61\x2a\x2c\x35\x06\x98\x47\xd1\x3c\xda\xba\xf7\xec\xb0\x70\x8d\x8b\x06\xdf\x5f\x2c\x4c\xdb\x7a\xdd\x34\xcb\x75\xc7\xa7\x98\x06\xf6\x9f\x59\x3c\x08\x7f\x8f\xcd\xc2\x74\x66\x5e\xde\x3c\x71\xe8\x8e\x1d\x2b\x66\x14\x8e\x45\x73\x08\xa1\xb7\xdf\x85\xde\x83\xfb\x2a\x2b\x27\xec\xd8\x84\x29\x8e\x75\x91\x91\x4c\x23\x5c\xcf\x03\x60\x07\xf2\x77\xc4\x0f\xcd\xc7\x0e\x65\x5d\xdd\xb1\x43\x5f\x7a\x78\x87\x45\xb8\x7e\x63\xa0\xb4\xc6\x5b\x33\x6a\xb9\x77\x38\x99\xc4\x0e\xc3\x31\xd3\xf2\x15\xe8\x0d\xf2\x3c\x1b\x53\x03\x8f\xff\xff\x07\x7f\xbe\xf0\x7d\xf8\xf3\x44\xa6\x11\x7e\xc2\x7d\x01\x4c\xa0\x18\x68\x06\xa2\x56\xb2\x41\xd5\x2f\x62\x59\xb3\xb2\xcb\xab\xa1\x57\xc6\x5f\x2a\xe5\x84\xe2\xd2\x9f\x9d\x40\x5b\xde\xe6\xbe\x40\x3b\x76\x5e\xd3\x1f\xae\x4e\x0f\x25\xba\xdc\x31\xa6\x11\x9e\xe3\xbe\x00\x66\x00\x8c\x04\xb3\x42\x86\xae\x60\xb5\x88\x8e\xc1\xda\x07\xde\x1e\xb5\xef\x7d\xd4\xb9\xef\xc4\xc4\xa7\x98\x46\xb8\x08\x4e\x39\x75\x0a\xfd\x08\x1d\x3c\x7b\x16\xdb\x3b\x6f\x70\x2b\x19\x1a\x17\xad\xbe\x62\x5c\xd4\x04\xf3\x63\xa3\x2e\x3d\x36\xfa\xc6\xa5\xb1\x51\x98\x99\x81\x06\x82\x2f\x32\x5b\x81\x11\x54\x5e\x26\xaf\xd2\x84\xd5\x3f\x98\x9f\x5b\xc9\x62\x1e\x8a\x47\x0b\x1c\xf2\x6f\x1e\xf6\x9c\xb7\xcd\x8d\x3e\x44\x6d\x2d\x47\xc7\xfa\xea\x5e\x19\x0a\x60\xe6\xf7\xc8\x0d\x87\x90\xd8\xe5\xa8\xef\x15\xbb\x94\xe0\x95\xe2\x97\x6c\x8f\xf8\x65\xaf\x2b\x87\x2f\x01\xcc\x7c\x9c\xf9\x98\xdd\xc2\xad\x02\xc5\x60\x20\x88\x17\x91\xfe\x88\xc6\x14\x01\xd2\x56\xcd\x46\xda\x19\xda\x70\x46\xf5\xd8\x49\x67\x68\xa0\x72\x45\x14\xb3\xc4\x2c\xc5\xa1\x8d\x60\xc2\x92\x32\xe3\xfa\x86\xea\x28\x36\x01\x74\xf9\x20\xea\xd8\xd7\x0c\x17\xac\x70\xcf\x68\x5c\xd8\x7a\xed\xfd\xe3\xaf\xbf\x7a\xe0\xed\x33\x46\xff\x68\xd1\x9b\x9d\x7b\xd0\x85\x23\xcf\xcb\xff\xe5\x0d\x6e\xf9\xcf\x8d\xb3\x6f\x0c\x86\xbf\xac\x0c\x9d\x79\xe3\x1d\xf4\xd4\x71\x40\x7b\x61\x65\x3e\x66\x2f\x70\xab\x48\xd7\xc6\x9b\x41\xdc\x4b\x3a\x88\xe9\xdd\x36\x4d\xc6\x54\x32\x58\xea\xe5\xac\x21\x35\x98\xed\xd1\xa8\xda\xec\xa4\x9d\x6c\x31\x0c\xe9\x7d\x19\xd5\x62\x1b\x69\xdf\xa2\x94\x4b\x49\x4e\x32\x79\xdc\x44\xcc\x49\x58\x8d\xf5\xc4\x94\xa0\xa4\x02\x77\x2c\xa6\x94\x3a\x15\x1b\xe9\x89\x26\x66\x55\x01\x57\xb7\xb6\x22\xba\x46\x8b\x29\x99\xa7\x06\x4e\xd7\xbb\x87\x2c\x6c\xbd\xf6\xbe\x09\xd7\x5f\x3d\xfe\xae\x11\x7b\x5f\x78\xeb\x2c\xfc\xad\xe6\xe9\x80\xed\x7a\x9b\x90\x3b\xdf\xbf\x73\xf6\x8d\xe1\xe0\x97\x57\x9d\x85\x6d\xd9\xc6\x8b\x4c\x1e\xdd\x2b\xf1\x1a\x2f\xa1\x7c\xb2\x57\x59\x91\xd3\x1a\x52\x7b\xe1\x35\x56\x85\x15\xdf\x19\x35\xe0\x48\xe9\xfd\xae\xf1\x7e\x54\xc3\x90\x1a\xf0\x11\x65\xdd\x5e\x64\xc3\xf2\xdc\x20\x61\xc3\x2d\xbb\x47\xbd\x48\xbf\x9a\x32\x52\x3e\x68\x96\x54\x9b\xe7\x3b\xed\x56\x9e\x92\x79\x85\x8d\x2b\xd4\xd6\x78\xb9\x0d\x64\x6a\xf2\xd6\xb8\x0f\xfd\x9d\x69\xe0\x56\x01\x01\x38\x41\x5f\x40\x5a\xc4\x26\x1d\x5a\x1d\xbb\x8b\x54\x0c\x59\x69\xe9\xba\x1b\x86\x54\xab\x98\xc7\x42\x69\xad\x4f\x7e\x64\x70\xfe\xd8\xb5\xb0\xd4\x70\xdb\x83\x93\xf5\x62\x75\xf4\xf7\xa7\xe1\x55\xde\xcc\x1f\xb8\x64\x5e\xad\x3a\xc3\x34\x72\x9d\xec\x79\x61\x26\x89\x72\xd7\xd3\x6a\x70\xe2\xa6\xcc\xbb\xf2\xa6\x1e\x57\x9e\x56\x19\x1a\xb2\x55\x86\x82\xe8\x62\x1a\xc7\x8f\x85\x25\x6b\xef\x19\xc7\x75\xfa\xf7\xfe\xba\xf0\x8d\xa7\xe1\x48\xc0\xc2\x29\xdc\xdf\xb9\x76\x21\xa9\xe5\x45\x5c\x8d\xef\xbf\x52\x4a\xb3\xca\xbd\xdf\x9c\x15\x51\x0e\xbf\x4b\x66\x04\xfc\xe6\xcc\x08\x38\xe5\x8a\xa9\x11\xf3\x2f\x9f\x1a\x01\xb8\xcc\x56\x00\xb8\x6d\xfc\x5f\x49\x7f\x06\x07\x28\x04\x63\x35\x64\x13\x56\x26\x15\x5c\x71\x07\x29\x27\x93\x00\xb4\x86\x54\xc1\x9c\x4a\x18\x00\x34\xe8\x09\x42\x2a\x6b\x25\x8d\xa4\x55\x96\xa3\xe9\x9e\x2a\x34\x48\xce\xb8\xd1\x53\x40\xa6\x1b\x84\xa4\x13\xab\x59\xa7\x9a\x0f\x06\xd8\x30\x0c\x0a\xe2\x7a\x06\xc1\xd5\xbb\xd1\xd9\x42\x54\x7d\x64\xbd\x46\xc8\x27\xe1\x84\x62\x9e\xe5\x9b\xfa\xf1\xc7\xbf\x1a\x0e\x67\xa0\x43\xdc\x4a\x9d\xb2\x5d\x87\xe1\xcc\xad\xfb\x77\x2f\x21\xfe\xa9\x2d\x4c\x0d\xfc\x90\xdd\x00\xcc\xa0\x2e\x0f\x01\x41\xfb\x96\x97\x1c\x55\xca\x85\xb4\x6f\x58\x28\xea\x5e\x77\xed\xb0\x6c\xc9\xf6\x74\x7e\x5e\xef\xda\x0c\x00\x0b\x2a\x00\xe0\xc3\x84\x16\x2e\xe0\x06\x77\xd0\x3c\x76\x55\x62\x53\xa4\x55\x85\x6a\x61\x53\x71\x37\x26\x87\xd5\x61\x30\x5a\x43\xaa\x95\x4d\x25\x80\xc1\x88\xc9\xe1\x09\x67\x21\xa5\x9f\xba\xf0\x31\x71\xbf\x18\xea\xb0\x96\x6e\x70\xa8\x12\x77\x11\x6b\xea\x46\xee\xa2\x22\x39\x12\x56\x09\xab\xe7\x0e\xfc\x95\x7d\xce\x60\xb4\x58\x75\xe5\x87\x34\x2e\x21\x18\x0d\xb4\x39\x00\xa5\x19\x0b\x03\x62\x80\x25\xff\x58\x58\x41\x69\x65\x83\x8d\x6c\xa4\x09\x81\x61\xf0\xbd\x28\x0a\x4e\x62\x40\x53\xba\xb7\x4e\xad\xaf\x1f\xe4\x8f\x21\xf4\x73\x84\xda\x33\x80\x3f\x46\xd7\x24\x44\xb3\x6b\x7a\x99\xae\x29\x6e\x27\xdd\x4c\xc8\xb2\xe2\x26\xab\x0d\xbf\x26\x2b\x33\x3b\xf1\xca\x14\x49\x56\xcd\x6c\x4a\xb1\x44\x72\xeb\xc3\x5c\xde\x65\x27\x5d\x99\x8d\xe6\x90\x6a\xb2\xa7\x14\x93\x83\xe0\xed\xd9\xed\x29\xac\x42\x5b\xcd\x21\xd2\x58\xbc\x20\xdb\x67\xe8\x97\x34\x33\xe3\x87\x14\x56\x4b\x71\x39\x12\x66\x97\xc9\x15\x52\x1c\x8e\x84\xc5\x61\x75\x85\x12\x12\xfe\x8a\x3f\x77\xe2\xcf\xd9\x84\xd9\x22\x39\x75\xa4\x6d\x97\x01\xeb\x7b\xf8\xba\xab\xc6\xcb\x10\x85\x0d\x90\xce\xaf\x01\x73\x1e\x51\x60\x64\x1d\x3c\xbb\x0e\x36\xa0\xb7\xd1\xaf\xef\x41\x35\xf7\xfc\x36\x9f\x28\xe9\xd7\x98\x81\x5f\x8d\x65\xd6\xa4\xef\xe3\x8f\x69\x7b\xcd\x6d\xc9\xd2\xe5\x7a\x8d\x2e\xa4\xd5\x0b\xa6\x44\x02\x18\xac\x3d\x36\x76\xdf\x85\x44\xb6\x9f\xbb\xb9\x83\x6c\xab\xa3\x03\x24\x4c\x66\xba\x83\x30\xfb\x8a\x46\xbc\xad\x97\xcc\x7a\x30\x74\x55\x47\x03\x76\xc8\x7a\x45\x7d\xd6\xf6\x5e\x3f\x7b\x6b\x6f\x25\xd3\x5e\xf9\xca\x5b\xfb\x2b\xd3\xa7\x73\x13\x56\xda\xd8\x78\x9b\xa2\xb4\x75\x4d\x6c\x53\xf8\x63\x80\x03\x83\x32\x1f\x0b\x76\x32\x5f\x0f\x28\x00\xbd\xc0\x6c\xad\x73\x66\xb1\x39\x15\xb7\xe0\xd3\x19\x60\x53\xf1\x02\x32\x73\x97\x05\xcf\xbc\x92\x6c\x99\xd7\x91\xc2\x56\x65\x19\xde\x27\x4d\xee\x79\x75\xca\x2a\x65\x92\x8a\x39\x0b\x50\x01\xe9\x31\x6c\xf7\x96\x91\x4e\x8e\x52\xb7\x69\x4b\xdd\x9a\xa8\xfb\xba\x77\x51\x1f\x44\x97\xd1\xb3\x7f\xfa\xb8\x8f\x73\xfd\xd3\xf5\x35\xa5\x9f\xed\xd9\x3e\x9d\x7b\xa2\xeb\xa6\xbc\x06\xea\x40\xbf\x83\xc2\x6d\x64\x9d\x06\x20\x81\xb5\xb4\x83\xb8\x62\xd7\xba\xc5\x58\xe4\xb8\x81\xac\xd1\x41\x8e\xa5\x33\xac\x38\xce\xa8\x76\x2b\x3e\x80\xa4\xcf\x8e\x6a\x74\xa4\xb0\xd6\x65\x72\xa4\x54\x97\xb6\x6f\x8f\x5e\xf8\x09\xdd\x37\x87\x43\x91\x3a\xf0\x6f\xda\x3a\x80\x6a\x93\xb0\x96\x8b\xbf\xd2\xed\x02\x0e\xda\x2f\xc7\xd8\x7d\xf5\x2e\x39\xe0\x82\x01\xc8\x06\x5c\xda\x8e\x8d\xfb\x77\xd8\xbc\x19\xde\x06\xa7\xa4\xf7\xac\x41\xa7\xd6\xe4\xb8\x54\x5a\x61\x26\x75\xad\x4b\x9f\x62\xc2\x64\x1d\x83\x00\x10\x5a\xc8\x3a\x6a\x40\x1f\x70\x9b\xd6\x9b\xd6\x20\xab\x85\xe6\x94\x62\x8c\xc4\x25\x7d\xcf\xfa\x90\xf5\x14\x4b\x78\x3d\x21\x12\xb8\xaa\xb4\xa7\x94\x4a\xba\x67\x1e\x07\x6d\xfb\x5e\x69\x95\x9c\x71\x9e\x33\xc5\xc8\xae\x25\xa5\x42\x5f\x6f\xd2\xa4\xd4\xe3\x54\x8b\x8a\xc9\x0e\x16\x4a\xce\xe7\xac\x9e\x92\xb2\xca\xde\x97\xd9\x43\xd6\x15\xa8\x83\xb4\x1d\x1a\x87\xc5\x38\x66\x27\xae\x5e\x12\x6d\xda\x48\x70\xd3\xa0\xb6\x93\x7b\x1a\xe1\x92\x25\xeb\x7f\x09\xaf\xee\xfc\x09\x64\xee\x3d\xfb\x36\x5c\x16\x4d\x6f\x6b\x81\x2b\xf6\x6c\x5e\xf5\xb3\xd5\xa3\xc6\xb6\xa0\xc7\x72\x67\x14\x72\xc3\x3e\x7f\xf8\x5d\xb8\xe0\xf8\xe6\xbf\xec\xfb\x0c\xed\x9c\x83\xba\xa0\xfb\x2c\x7c\x6e\xfb\x8f\xb6\x5e\xbc\xe7\xc0\xaf\x47\xa0\x8f\xf1\x4d\x03\x80\x03\xa3\x32\x1f\xb3\x6b\x89\x5c\xf4\x81\x5e\x20\x0c\x7e\xa6\xe9\x33\x6e\x63\x8a\x34\xcb\x54\xec\xa4\x97\x74\x1d\x15\x95\xbd\x49\x36\x8d\x62\x23\x1b\x9b\x70\xda\x6d\x86\x90\x6a\x76\xa4\x14\x73\x58\x75\x3a\x52\x34\x37\x4c\x13\xa2\x76\x87\x5a\x09\x43\xc9\x10\x15\xa2\x0d\xda\x86\xff\xf6\xf3\x0f\xe9\x86\xdb\x08\x9e\xbf\xdd\x81\xef\xa9\x6a\x75\xe0\x0d\xc7\x5f\x89\x59\xe3\x34\x4b\xce\x24\x6b\x2c\x22\xfd\x6f\x55\xbb\x4d\x72\xc6\xdd\xe5\xbd\x48\x30\xd2\x4d\xfb\xfa\x29\x36\x49\x35\x17\xc4\x62\x54\x06\x97\x94\xf6\x8a\xc5\x62\xdd\xc4\x88\xab\x1f\xe9\xdd\x97\xd3\xa4\xe1\x65\x84\xf2\x28\x4d\x04\x17\x79\x1f\x85\xb5\x3f\xb0\x4c\x69\x9d\xb5\xe2\x07\x0f\xed\x80\x05\x57\x90\xd0\x5f\x7f\xd9\x6f\x11\x73\x3a\xed\x6b\xf1\x8e\x0e\x9e\x6b\xdc\xc0\x73\x3d\x25\x36\xd6\x9b\xa8\xcc\x3e\x4e\x64\x76\x4b\x77\x79\x9d\x14\x0c\xba\xa8\x26\xb6\x81\x26\xa4\xa5\x9e\x42\x9a\xd4\xde\x69\x02\x9a\xbd\x9c\x5c\x86\x35\x3d\x05\x32\x33\x3b\x2b\x86\x01\x0b\x1a\x01\xe0\x3e\xe0\x8f\x01\x3b\xf0\x02\x3f\xf8\x11\x88\xdb\xb5\xce\x5e\x0e\x36\x45\x51\xc1\xa0\xac\xfa\xd9\x54\xb2\xd0\x6b\x67\xac\x21\xb5\xd0\x94\x22\xd0\x91\xee\x33\xaa\xc5\x91\x52\x4a\xf0\x65\xe5\x1d\x29\x35\x00\xf5\xba\xcb\xfb\x68\x36\x63\x9d\xe2\x27\xce\x57\x87\xe7\xa2\xe2\x77\xa8\xd0\x73\x11\x0b\x0c\xaf\xc3\xef\x0a\x25\x0a\xf1\x57\xf6\x39\x00\x1d\xde\x42\x7f\xae\x71\x5c\x89\x1b\x9b\xa8\x06\x12\x48\x73\x90\xb5\x29\x85\x12\xf9\x40\xf1\x67\xfb\x80\x91\xfd\x10\x3d\x65\xd0\xe3\xe6\x02\xac\xd6\x9a\x21\xaa\x7d\x6f\x84\x8d\xf0\xf0\x87\xff\xfd\xd4\xa3\x73\xd7\xa0\x5f\xa3\x0b\x4f\x24\x57\x6f\x7d\xfe\x49\xf9\xe1\x75\xeb\x0e\xef\xe5\x8f\x3d\x71\x70\xcf\xab\xe5\xff\x1f\xf6\xde\x04\xcc\x89\x2a\xeb\x1f\xbe\xb7\x96\x54\xb6\x4a\xaa\x2a\x5b\x27\xe9\x2d\x9d\x5e\x68\x42\x77\xe8\x0e\x4d\x13\x11\x10\x44\x44\x44\x41\x64\x90\xb5\x05\x54\x14\x90\x71\x69\x11\x11\x11\x51\x11\xd9\x06\x41\xc5\x05\x74\x7c\x11\x15\x11\x9d\xaa\x24\xb4\x8a\x8a\xad\xb8\x82\x88\xc8\xd0\xea\xeb\x38\xca\x28\x8e\x99\x69\x51\x5b\x87\x91\x25\xb7\xbf\xe7\xde\x5b\x95\xa4\xa1\x19\x9d\xff\xf2\xfd\xdf\xef\xff\xbd\xcf\x3c\x53\xa4\x93\xcc\x33\xb9\xf7\x9e\x7b\xce\xef\x6c\xbf\x63\x0e\xac\xfa\xed\xa1\x9f\x21\xb8\xe1\xca\x8d\x47\xa6\x4d\xa2\x33\x3d\xf0\x1e\x3c\x48\xea\x95\xf4\x19\xe2\x2a\x4f\x4f\x41\xe3\xd8\xb4\xce\x29\xa4\xf1\x79\x33\xc4\x75\x9b\xa8\x97\x6c\xea\x3d\xaf\x90\xcb\x8e\x8c\xc2\xc6\x1e\xff\x16\xb6\xb6\x2f\x02\xd8\x80\xa3\xe3\xc3\x01\xd3\xb9\x1b\x00\x6e\x3a\xff\x32\xe0\x81\x1d\x4c\xd1\x6b\x9d\x4c\x6c\x5a\x15\xea\xe9\x4e\xb3\x31\x88\x5d\x43\x87\x3e\x42\x6c\xcc\xd1\x47\xf4\xea\x7a\x87\x6a\x6e\xd5\xb8\xda\xa3\xbc\xca\xb6\xb2\x40\xe3\xcc\xd8\x4c\xb1\x9c\x60\xce\x02\x0e\x13\xb5\x52\x2a\x23\xab\x56\x2c\x11\x8d\x30\xe4\x12\x60\x88\xad\x6c\x30\x09\x0d\x61\x66\x29\x9c\xba\xaa\x2a\xc3\x31\xfc\x48\xb3\xd4\x33\xc5\x9b\x8f\x75\x3c\x07\x19\xe6\xc8\xd4\x81\x8d\x97\xe8\xeb\xdf\xc0\xb7\x00\x1b\x98\xa9\xff\x2a\x0b\x9b\xce\x6e\x40\x8a\xa7\xa2\xc8\xe3\xbd\xb0\x47\xb3\x43\xdd\x0c\x80\x04\x6a\x55\x8e\x9c\x34\x46\x46\x9c\xa4\x41\xee\xe8\x49\xcd\xb6\xf8\xa4\x39\xde\x6c\xe9\x32\x56\x2b\x0f\x10\x35\x9c\x02\x84\x72\xe0\x07\xfb\xae\x3b\x01\xe0\xb0\xf5\xb4\x80\x5a\xfd\xf7\x09\x6c\x3a\xc1\xe1\xdf\xc7\xb2\xc4\x2d\xc7\xce\x38\xa0\x5d\xa9\x30\x4e\x42\x1d\xc4\xc5\x23\xdb\x10\xc2\xfb\x30\xa0\x92\xb5\x64\x0e\x36\xb0\x9b\xab\x4f\x74\x30\x63\x1b\xde\x65\xbf\x85\x60\xd7\x09\x77\xa7\x71\xfe\xfc\x26\xb2\xfe\xc7\xf4\xc9\x66\x82\xd9\x86\xb1\x14\x41\xce\x0c\x6f\x8a\xc5\x62\x29\xd6\x8a\x77\x81\xb0\x96\xb0\x69\xa3\x01\x19\xb4\x91\xd1\x99\x36\x49\x83\xb6\x88\xc6\xe4\xe6\xfb\x09\xce\xb4\x2a\x48\x1a\x6f\x8b\x68\x26\x67\x6e\x10\xde\x29\x60\xca\x26\x25\x59\x1b\xe3\x8a\xa8\x66\x29\xc9\x99\x79\x57\x24\x69\xc1\x4f\xfc\xbe\xd5\x46\xc6\x96\xb0\x9c\xc5\xda\x65\xdb\x0c\xc8\x84\xb7\xed\x64\xa8\x94\x8f\x8f\xe8\xfd\x5e\xd0\xd9\xce\xab\xfc\x1e\x20\x82\x20\x28\x01\x93\x41\xc2\x46\xb0\xb0\x4d\xdf\xbf\x02\x36\x9d\x2a\x2a\xb4\x61\x2f\xbb\x88\x4d\xeb\xa4\xb0\x9a\x43\x22\x5e\xb6\x07\x2f\x84\xde\x6d\xcd\xe3\x90\x95\x24\x67\x2b\x2c\x26\xee\x75\xa1\x2c\x2b\x1a\x70\xc4\xe3\x64\x34\x96\x26\x78\x88\x4a\xed\x82\x30\xba\x02\x0c\x5f\x63\x48\x58\xf0\x2e\xbc\xf4\x2b\x28\xc0\xb2\xed\xe8\x89\xbf\xa2\x9f\xd0\x7e\xd8\xb8\x76\xe1\xdd\x6f\xcd\x5a\x31\xff\xce\xf7\x9a\xe7\x34\xc0\x97\x1b\x98\x08\x74\xc2\xc4\x41\xb4\x07\x7d\x8b\x3a\xd0\xb8\x2f\x61\x0c\x72\xbf\x7b\xe2\x69\xd8\xef\xcd\xdf\x3d\xb5\x19\xed\x98\x8f\x10\xcd\x21\x02\xc0\x2e\x26\xe7\x35\x5c\x3f\x2f\x9e\x01\x91\x2e\xc2\x99\x05\x79\x84\xfd\x95\x88\xa6\x99\xc4\xc5\xa8\x14\xc2\xec\x2b\x3d\xbd\x19\xce\x03\x75\xfd\xf3\xc1\x5c\x3e\x80\xcb\x97\x15\x3b\x58\xaa\xcb\xa2\xd9\xae\x4b\x8a\xc6\xf0\xb1\x98\x5e\x7d\xa4\xd9\x9d\x64\xe2\x98\x2e\x16\xc6\x9d\x36\x22\xff\x46\x81\xb7\x4d\xb5\x4b\x49\xd6\x4e\x86\x20\xe2\x67\xc2\x66\x3f\x29\x3a\xad\xb1\x36\x52\x81\x69\x33\x22\xa9\x76\x1a\x50\x33\x22\x6b\x54\x24\x1a\x61\xc8\x02\x43\xac\x40\x65\xe2\xe1\x0d\xf0\x11\x38\x33\xf3\x1c\x0c\xa3\xe7\xf6\x2f\x9c\xc3\xb7\x64\x06\xee\x83\x3f\x64\x86\x66\x4c\xcc\xe8\x61\x99\x23\x64\x0f\xb1\xed\x19\xc3\xbf\x0c\x6c\xa0\x77\x57\xcb\x43\xe4\x5a\x37\x37\x62\x17\x73\x03\xf4\x4c\x20\x35\x37\x95\x0d\x82\x49\x80\x0b\x98\x76\x38\x6e\x05\xfa\xa4\xbf\xa5\x28\xda\x13\x8d\xc5\x36\x86\x1d\x7a\xdd\xc1\x51\x8b\x2e\x39\xb1\xda\xb8\x5b\x82\x9b\x6f\x01\x2e\xf0\x42\xf6\x6e\x39\x62\xd9\x1d\x33\xe1\x1d\xa3\x2d\xda\x2e\x91\x78\x25\xe4\xf6\x88\x69\x2c\x7c\x44\x0b\x16\x9d\x88\x91\x9b\xe2\xa8\x75\xa8\xce\x56\x8d\x35\xd3\x41\x64\x03\x37\x75\x7c\x41\x4f\xd8\x4c\x67\x69\xeb\x85\xf3\xcd\x1d\x80\xec\xab\x59\x4a\x5a\xcc\x36\x57\x24\x61\x31\xdb\xf2\x62\xd5\x49\xd6\x62\x73\x12\x09\x68\x61\x58\x93\xc5\xe6\x70\xe6\x0f\x06\x36\xbb\x64\x25\x01\x39\x32\xa0\x4b\x90\x35\x9e\x0e\x6c\x8a\xc1\x90\x2b\x06\xf1\x9d\xeb\xeb\x0a\xc3\x10\x1b\x36\xd9\x88\xa1\xb9\x6f\xb0\x85\xa9\x80\x4f\xa1\xdd\xe8\x9b\x35\xe5\xe7\x59\x32\x6f\xa3\xbf\x0e\x30\x7b\xfb\xad\xe6\x5b\x8e\xbf\xc4\x9d\x73\x6c\x04\x93\x7a\x1a\x4a\xc7\xef\xe5\xe6\xb4\xa0\x1f\x32\xe3\xe9\x5e\x98\xf0\x5e\x48\xe0\x2e\x5d\x76\xac\x52\x76\x27\x04\xbc\x13\xa4\xc2\x4c\x93\x44\x32\x9e\x5a\x80\x11\xcd\x2c\xa6\x49\xb2\x04\xcb\xce\x63\x1d\x7b\x72\x56\x87\xc0\x60\x67\xeb\xf6\xd7\x7f\x6e\x7f\x99\x0e\x7c\xb5\xd6\x3a\xb0\x3f\xc3\x16\x90\x0d\x62\x41\x82\x25\x2b\x25\x63\xd6\xac\x36\x67\xce\xcc\x0a\x12\xe5\x9c\xa2\x03\x44\x63\x74\x70\x1f\x0c\x0b\x26\x2a\x3e\x57\xc0\xb1\xe6\x70\xe8\x5e\xa8\xa0\xdd\x68\x0b\xda\x60\x35\x07\x4b\xd6\xf0\x2d\xc7\x77\x7f\xbe\x91\x49\x1d\x1b\xc1\x8d\xe9\xdf\xb6\x26\x33\x9a\xf4\xfc\x1c\x00\x80\xbb\x8a\x78\xa7\x02\xb0\x81\x6a\x7d\x4d\xd0\xf0\xb3\xcd\xd8\x76\x70\xc0\xd2\xd5\x76\xe0\xcb\xe6\x0a\xb1\x46\xf3\x41\x24\xc6\x2e\x6d\xc8\xcc\x6d\x64\x36\xf4\xcb\xac\x6d\x60\x1b\x1b\x20\xe8\x04\xcc\x7c\x84\x98\x41\x08\x01\x86\xe8\xaf\x07\x75\xfd\x35\xb4\x1b\xed\x05\xd5\xc2\xee\x54\x56\x91\xae\xb2\x34\xce\x46\x06\xf8\x61\x7d\x25\x80\x5f\xd2\x52\x0b\x4e\x76\x80\x60\x63\xce\x01\x62\xfc\x27\x3b\x3e\xd0\x94\xef\xf6\x50\xdd\xf0\x30\x99\x91\x79\x7b\xd7\x09\x99\xf8\x84\xc9\xf8\x4b\x36\x6d\x34\x49\x80\x36\xc3\x46\x40\x5b\x44\x6f\x43\xa5\x49\x6e\x8d\x73\xa6\x55\x2e\xaa\xb1\xce\x74\x5e\xab\x88\x66\x39\x09\x7b\x74\xdb\x28\xa2\xf1\xa6\x3c\x4b\x41\xfe\xd3\x00\x1b\xb8\xde\x68\x17\xda\x0b\x01\x8a\x61\x2c\x72\x6c\x04\x97\x3a\x3e\x12\x00\x86\xd8\x7d\x0c\xee\xad\xc0\x85\x3d\x1b\xa2\x05\xac\xb1\x2c\xea\x73\xb1\xe9\x94\xc5\x06\x30\xea\xb3\xb0\x59\x26\x05\x3d\x62\xe0\x84\x11\x8d\x77\x66\xaf\xa9\x91\xa5\xd3\x21\x91\x55\x52\x5d\xad\x49\x8b\xd5\x85\x15\x1b\x7e\xb2\x49\x68\xb1\xb9\xb2\x70\xc5\x95\x37\xd8\x15\x03\x3a\x10\x0a\xb3\xb4\x8c\xa0\x92\x82\xb8\x07\x3b\x7e\x46\xcf\xa2\xb6\x0d\x73\x36\x2d\xfc\xdd\xe3\xd3\xa6\xdd\xc3\xb7\xb4\xfd\xf1\x07\xf4\x6d\xe6\x67\xd6\xb4\xfc\x86\x29\x97\xd0\x98\x36\x96\xbf\x47\x89\x1d\xa8\xcf\xc3\x2d\x44\x32\x84\x3c\x81\x33\x02\x0f\xaa\x20\xab\x0c\x09\xff\xb2\x04\x1b\x58\xb0\xfc\x11\xbd\x19\xa9\x63\x4a\xd0\x8e\x3a\x76\x79\xdf\xcc\x3e\x38\x10\xd9\x99\xb1\x0d\x1d\xf0\x18\x3c\x98\x46\xa8\x04\x55\x77\x62\x3d\xb6\x19\x00\x6e\x1f\x39\xdb\x11\x3a\x8f\xb2\x81\x11\x01\x9b\xd6\x38\xa1\xde\x20\x46\x21\xbb\x62\xc9\x52\x91\xef\xa2\xdd\x90\x52\xb7\xe4\x28\x41\x6c\xcd\xd9\x90\x6b\x73\x23\xdb\xd1\x88\x7e\x8f\xd0\x5e\xc4\xa5\x20\x83\xd0\xf1\x91\x5c\x8a\x72\x15\x6f\x07\x80\x1f\x44\xb8\x98\xae\x04\x09\x81\x70\x15\xc7\x12\xc0\x40\x8b\x84\x8f\x49\x33\x89\x69\xfc\xff\x00\x31\x16\x07\xd8\xb5\x8a\x6a\x50\x4a\x6b\xd6\x93\x1d\x67\x41\x52\xcd\xa4\x63\x94\x6f\x3d\x95\x2a\x04\x08\x44\xcf\xf7\xae\x73\x19\x9e\xf2\xf6\x2e\x1e\x32\xdf\x92\xe7\x19\x13\x5c\x61\x1a\xce\xef\x06\x0a\xf0\x83\x52\xf0\x17\x90\x70\xe0\xdf\x26\xc6\xc8\xf6\xab\x7c\x2c\xe5\xf4\x3a\x38\x31\xa2\x06\x62\x9a\xd3\x92\x56\xed\xf5\x29\xd6\x47\xde\x28\x8d\x69\xac\x25\x4d\x88\x64\x42\x54\xef\xd3\x68\x14\xbe\xb1\x16\x67\xda\x98\xac\x38\x50\xfd\xb1\x48\xd7\xfb\x2a\x5f\x8b\xaf\xb6\x18\x3d\xaa\xf2\x92\xc6\x45\x8f\xaa\x0e\x29\xc9\x3a\x38\x57\x44\x15\xa5\xa4\x49\xc4\xa8\xc9\x8e\x9f\xf8\x7d\x27\x7e\x3f\xe9\x25\x4f\x9f\xf1\x9d\x00\xf9\x4e\x29\x7e\xb2\x67\xd9\x59\x8e\x37\xd9\x45\x87\xd3\xeb\x0b\x94\x9e\x34\xbb\x1a\x68\x5e\x27\x1d\x86\xe7\x93\x35\x0b\xad\xe0\xd3\x18\x81\xea\x0d\x50\xd1\x18\x12\x8a\xa1\x47\x02\xbc\x10\x6a\xac\x65\x2a\xdc\x5e\x9f\xcb\x01\x21\x09\xaf\x57\x2d\x80\x37\xc0\x09\x15\xb0\xb0\xe2\x9b\x13\x68\x09\x7a\xae\x0e\x7d\x59\x77\xef\x27\xf3\x60\xdd\x8d\xd7\xdc\xb1\xb9\x95\x61\xd4\x17\x6f\xbc\x96\x49\x40\x3f\x1c\x24\xa6\x52\xee\xe3\xfb\xd1\x41\xf4\x12\x77\xf0\x73\xdb\x0d\x1f\xad\xbe\xf6\x36\x8e\x99\x69\x7d\x1d\x5d\x66\x7f\xfb\xc9\x39\x8b\x38\x2a\xdb\x2b\x00\xe0\xe7\x13\xd9\x1e\xa3\xdf\x4c\xb3\x7e\x33\x79\x3a\x62\x99\x69\xd3\x58\x29\xad\x73\x04\x68\x66\x49\xb7\xd6\x8c\xac\x68\xd0\x16\x27\xa3\xed\x38\x6b\x3c\xae\x9a\x15\x7d\xc4\x1d\x03\xb2\x1d\xa6\x61\x7c\xbc\x14\x32\xc0\xb9\xcc\x59\x87\xe1\x59\x0f\xc1\xd9\x70\x7c\xe6\x73\x68\x47\xdb\xb6\xa2\x1b\x98\x13\xcc\xf6\xcc\x31\xc6\x94\x89\x64\x4a\x98\x92\xcc\x41\x00\xf1\x6f\x30\xed\xe7\x5b\x40\x31\xf4\xe9\x31\x10\x7f\x8c\xd6\x15\x72\x76\xd1\xe5\x2e\xf7\xc5\x52\x85\xd6\x00\x2b\x46\x34\x9b\x23\x16\xd3\x0a\xd9\xb4\x56\x10\xcc\xb6\xe8\x62\x8b\x8e\xc5\x8f\xc3\x22\xca\x8a\x69\x95\x8d\x6a\x1c\x79\x8b\xc4\x9d\xfd\x62\x5a\xf5\x93\x2a\x09\x4d\x14\xd3\xaa\x28\x91\xd9\x15\x6e\x31\xad\x95\xea\x73\x36\x9d\xff\x90\xa8\x0c\x93\x7e\x2d\xaa\xed\xba\x8d\x4d\xaa\x4a\xab\xea\x96\x54\x6f\x2b\xaf\x06\xa4\xa4\x2d\x60\x77\x45\x54\xbf\x94\x74\xf8\x45\x57\x64\xfb\xc0\xfb\x3b\xd6\x13\x74\xe0\x95\x92\x1e\xaf\xdb\x15\xe1\xf1\x67\x05\xf8\x33\xfc\xed\x20\xfe\x76\xc2\xe3\x75\xe7\x03\x06\x86\x57\x3c\x04\x30\x3c\xcf\xf0\x36\x87\xe2\x29\x08\x76\xa9\x8c\xa3\x24\xf6\x64\xa6\x98\x11\x46\xf0\xf6\x87\x2e\xe2\x99\x36\x92\xe9\xe4\x61\x36\xe4\x0a\x97\x55\x26\x7c\x4d\xb0\xea\x0a\xc7\x35\xd7\xca\x9b\x60\xe1\x26\xf9\xde\x07\xca\x66\xc0\xea\x6b\xe6\x64\x3e\xf0\x4c\x46\x5f\x5e\xea\xfc\xf3\x51\x36\x3e\xe1\x6a\xf8\x02\x0a\x0d\xad\x9b\x3e\x86\x35\x9f\xf8\x79\xf9\x7a\xf8\x65\xe6\x18\x62\xd0\x85\x30\xb1\x97\xc8\xc4\x47\x00\xf0\x2d\xfc\x1e\x10\x02\x97\x82\x84\x62\xf8\xe9\xb6\xb4\x0a\xeb\xa9\xc5\xf5\x63\xad\x57\x16\x55\xf9\x36\xad\xc8\x99\x56\x8b\x48\x4d\x80\x26\x4a\x69\x2d\x0c\x23\x5a\x11\x4f\x6e\xb8\xea\x95\x53\x16\xc9\x55\x1a\x2a\xf7\xc5\x55\xd1\x98\x51\xe6\x97\x64\x25\xc9\x8b\xee\x52\xd2\x1a\x11\xfe\xc5\x40\x53\xf5\x2f\x04\x98\x7e\x31\xa8\x04\x58\x82\xe3\x9f\x15\xc6\x91\x1a\xaa\x12\x30\x2f\x0f\xcb\x63\x5b\x53\x1c\xd3\x9c\xb6\xb4\xea\xaf\x27\x5e\x89\xbd\x4d\x93\xc5\xb4\x2a\xd3\x25\x05\xc5\x5c\xc4\xe1\xdf\x82\xfa\x9a\x17\x23\x01\x9b\x95\x8e\xb2\x30\xc5\x4f\x82\xfe\xdd\xb1\x02\x75\x71\x07\xd0\xfb\x5d\x29\x82\xf2\xdd\x03\xd3\x0b\xf9\x74\x41\x80\xa5\xba\x5b\x18\x07\xcc\x40\x01\x85\x60\xd3\x29\xfa\x1b\xc3\xbd\x60\x4c\xb3\xdb\xd2\xaa\xb7\x9e\x94\x1a\x9e\x56\x99\xe3\xb7\x1c\x24\x30\x2a\x92\xc0\xa8\x83\x7c\x8b\x5c\x93\x02\x31\xad\x15\xff\x1b\xaa\x9e\x90\xf6\x69\x76\x39\x1e\xd7\x1c\x16\x1d\xdb\x9f\xa2\xfc\x83\xdd\xed\x44\x57\x83\x50\x74\x12\x11\x6a\x9e\x7d\xe0\x96\x75\xd9\x09\x00\x38\x30\xb1\xb3\x9d\xfb\xc4\xd4\x04\x42\x20\x0a\x1a\x41\x3f\x8c\x37\x4a\xa8\x16\xd1\x2a\x2c\x69\xd5\x5d\x4f\x06\xfa\xd1\xd4\x6f\x2f\x4b\x1a\xaa\x71\xa2\x37\xca\x9c\x69\xb5\x4c\xd2\xaa\x69\xeb\x83\xcc\x45\xb4\x33\x60\x44\x2b\xc3\x06\xbd\x24\xae\x56\xcb\xc9\x20\xd7\x3b\x46\x87\x31\x27\x05\x9b\xbf\x91\x78\xa7\x15\x25\xb2\xa2\xf9\x82\xf1\xb8\xda\x4b\x4e\x28\xc0\x4b\x07\x6a\x12\xdf\xc5\xd5\x47\x21\xa3\x26\x62\x03\x61\x63\xcc\x01\x85\xbc\xb0\x5f\x15\xad\x7c\xa8\xc8\x43\x84\x0e\x98\x8d\x1f\x4f\xbc\xab\x63\xdd\x84\x85\x31\xb3\x33\x1e\x40\x35\x53\x02\x67\x9b\x06\x94\x17\x0d\x9a\xf1\x76\x8d\xf9\xa2\x35\x93\xd7\x3c\x06\xeb\x06\x0f\xbd\xe0\x86\xb3\xcf\x1a\x7c\xee\xfc\xe1\x87\xf5\x00\x33\x5c\xfc\x47\x38\x69\xe7\x85\x4d\x25\x4d\x81\x8b\x7f\xb8\x09\xb5\x16\xfb\x06\xdb\x0f\x17\x3f\x71\xe9\xb0\x03\x9f\x5d\x36\x79\x15\x14\xc7\x8d\x9e\x7a\xf7\x41\x66\x67\x2e\xef\x08\xaa\x3a\xdb\xb9\xa8\xa9\x09\x54\x82\x5a\x10\x05\xcd\x20\x51\x8e\x31\x4d\xb1\x39\x4d\x8a\xde\x34\xa7\x29\x9d\xf2\x14\x94\x63\x3c\xed\xe1\xd3\x24\xb8\x0a\xda\xb4\xa0\x94\x56\x83\x12\x99\xc6\x41\x65\x27\xaa\x29\x62\x5a\xab\x83\x11\x4d\x09\xca\x8a\xc6\x32\xf8\x7a\x17\x97\xcb\x8a\x5a\x46\xe2\x69\x20\x14\x27\x01\x67\xfc\x81\xea\x94\x35\x93\x1d\x5b\x0b\x5a\x68\xef\x92\x2a\x1a\xb2\xa3\x48\x8c\x31\x85\xfd\xa1\xde\xe3\x92\x4b\x90\x1b\xbb\x52\x05\x87\x8f\x1e\x77\xe4\xb3\x7f\x3c\x3a\x79\xf2\x8a\xe1\xd3\xae\x9a\x76\xf9\xd2\x9a\xfb\x6e\x5a\x3e\x71\xdc\xe4\xa7\x9a\x1e\xeb\x78\xff\x30\x63\x33\xf6\x42\x81\xb0\xc1\x5c\x72\xdd\xb9\x8f\x3e\x37\xee\xcf\xb5\xe5\x67\x0d\xe8\xd3\x7b\xff\x05\x43\xfb\x0d\xa8\xae\x3b\x32\x6a\x3d\x37\x26\x6f\x0f\x2a\x90\x9b\x9b\x63\x6a\x02\x5e\x50\x0c\x4a\xc0\xcd\xba\x4e\x80\x58\x36\x48\x5d\xa5\x18\x35\x82\x14\x5e\x31\xad\x7a\x69\xea\xca\xe2\x4c\x27\xed\x16\xc9\xac\x9b\x8f\xa8\x66\xa7\xfa\x41\xf3\xea\xc8\x4f\x94\x13\x0c\xc7\x62\x39\x90\x94\xa4\xe2\x0b\x90\x04\x89\x1d\x2b\x00\xd5\xa2\x68\xc1\xc2\xb8\xee\xdf\xa6\x58\xce\x22\x29\x44\x05\xc6\xf4\xf2\x1e\x52\xd8\x15\xca\x16\x1f\x65\x97\x5e\xf1\xed\x57\x1e\xf3\xda\x7d\xcb\x1f\xf0\x1d\x46\xfb\x3b\xa4\xab\x27\xaf\x8b\x4c\x87\x15\x46\x3a\xb9\x69\xef\x57\x4f\xad\x3f\x6f\xf6\xf1\x07\xb8\xf9\x43\x63\x0b\xbe\x7a\x0f\xd5\xe5\x65\x98\xb1\x6e\x98\xda\xd9\xce\x74\x9a\x9a\x48\xae\xd6\x0f\xee\xa4\xf8\x49\xb3\x58\xd2\x09\x16\x2f\x93\x8b\x41\x35\x10\x55\xd9\x36\x6c\x26\x93\x02\xc7\x9a\x23\x86\x36\xc0\xee\x4d\xf0\xe4\x10\x79\x9e\x59\x04\xa4\xe6\x27\xaf\xf2\x47\x60\x65\x25\x81\x8d\x59\x3c\xae\x72\x72\xc2\xe2\x2e\x20\xe1\x71\x9d\xba\x8d\xf0\x67\x91\x82\x92\xc6\x93\xe3\xe0\x59\xe1\x9f\xda\x25\xe8\xfd\xad\xbe\xc8\xc3\x5d\x42\xdc\xb9\x0c\x0a\xb9\xef\xf3\x3a\xdb\xb9\x7b\x4d\x29\x92\x41\xaf\x02\xf5\xe0\x59\x90\x90\xc9\x0a\xad\xfa\x0a\x6d\x31\xac\xf0\xea\x62\x9a\xcf\x96\x56\x23\xf5\x64\x64\xfb\xe9\x81\x02\x27\xa9\x81\xd2\x36\x39\xe5\xa6\x09\x03\x77\x54\xcf\xb8\x63\x04\x61\x83\x11\x3a\xe9\xbd\x5e\xb5\x4b\xa9\x1e\xf4\xfd\x1e\x51\x32\xd4\x9d\x34\x94\x58\x64\x1f\xc9\x0e\xd8\x02\xb2\x92\x28\x09\x57\xc5\xe3\x71\x9a\xa1\x2d\x37\x86\x73\x82\xb8\xe6\x2b\xc2\x1f\x96\x56\xe9\xd9\x01\x63\x2b\x4a\xe5\x90\x64\x85\x27\xf5\x2f\x77\x97\xb5\x9f\x27\x2d\x86\x91\xc5\x8e\x55\xb0\x01\xd6\x8c\x5e\xff\xc3\xe3\xef\xfe\xf1\xef\xa7\x4b\xe3\xc3\xab\x86\x8d\x66\xa6\x66\x1e\x1c\x70\xe6\x06\x76\x21\xda\x86\xa6\xa1\xce\xa5\x6f\x71\xa9\xd3\xe4\xf6\x19\xaa\x3b\xb9\x66\xa2\x3b\xaf\xff\x25\xbd\xd9\xfb\x34\x7a\xb3\xae\x8b\xde\xd4\x82\x1c\xa9\x12\x49\x08\x36\x3f\x91\x86\xff\x85\x3a\xf3\xd7\xab\xca\x5f\xa5\x22\x69\xae\x64\x07\x72\x73\x7b\xc9\x3c\xa2\x08\xd8\xa1\xcb\x92\xdf\x82\x2f\x84\xea\x89\xa9\x25\x51\x2d\x64\x49\xe3\x43\xe7\xf0\x1e\x90\x56\x1e\xcd\xe3\x4c\xab\x1e\x49\x2b\xa4\x10\x48\x15\x25\x55\xc0\x52\x55\x21\xa5\xd5\x0a\x7a\x8d\x6a\xf4\x6b\xf4\x54\xc7\x0f\xf4\x1a\x51\xef\xd5\x23\xa9\x91\xd6\xa4\xdb\x13\xc1\x9e\x04\x7e\x26\xdc\x9e\x48\x5e\x58\xce\x1b\x07\x49\xe8\xf6\x46\xf4\x3a\x51\xfd\x15\xb9\x6b\x85\x1e\x59\x49\x71\x72\x69\x88\xa4\xef\x2a\x64\x12\xaa\x0b\xd1\x50\x9d\xda\x83\x0e\x97\x66\xa1\x51\x49\x8f\xbd\x09\x37\xd9\xc1\x2a\xd6\x45\x5a\x2b\x88\x03\xdc\x98\x6d\x0f\x10\x86\xc0\x09\xb5\x99\x83\xef\x7d\xf1\xe2\x53\x0b\x57\x2f\xfe\xe2\x81\x51\x77\x8f\xbc\xfe\xf1\xe0\x55\x7d\xaf\xbb\x7d\xe6\x65\xd1\x58\xff\xdf\xde\x32\x62\xe0\xc5\x33\x02\xc8\x6d\xba\xec\xd3\x3d\xdb\x37\xa9\x6f\x15\xfa\xb6\x2e\xb9\xff\xbb\x79\xa1\x9e\x99\xcf\x58\x4b\x30\xfc\xc0\xad\x93\x27\x77\xdc\x7d\xcb\xd0\xf3\x6f\xba\x05\xfb\x92\xfd\x91\x9b\x5b\xcd\x35\x01\x19\x0c\x06\xf4\x12\xda\x63\x2a\x88\x92\xfc\x2b\xd5\x34\xf8\x9e\xc9\x79\xc8\x43\xa6\xf9\x57\x4d\x66\x75\xa0\xc0\x1a\x41\x40\x97\xd2\xc8\x86\x8c\x51\xd0\x21\x68\x62\x84\xfe\xb1\x3b\x57\xc2\xaa\x2a\xb3\x45\xa9\x3f\xff\x67\x78\x76\xe6\x93\xe9\xb3\x4a\x90\x1b\xc2\xa3\xdc\x68\x64\x9f\xfd\x41\xec\x86\x87\xe0\x77\x27\xec\xdb\xd0\xe1\xd5\x58\xa6\x1b\x3b\xdb\xc9\x79\x16\x82\x2a\x30\x83\x7a\x14\x5a\xa9\x35\xad\x3a\xa2\x9a\xd9\x94\x86\x6a\x0f\x72\x84\x45\x12\x41\xb1\x3c\xfe\x09\x14\xfd\x61\x20\xeb\x93\xd2\x58\xb2\x35\x99\x97\x95\x24\x1b\x28\xad\xc0\x97\xdb\x17\x96\x95\x84\x99\xd4\xaa\x01\xcd\x51\x2a\x2b\x29\xc0\xdb\x7d\x15\x7a\xbd\x94\x8d\xca\x71\x63\x65\x83\x3e\x6a\x8a\x16\x80\x17\x43\x9f\xd7\x23\x81\x90\x21\xc2\x64\x62\x59\xe3\xcf\x5f\x3e\xf0\xfd\x7b\xd7\xbe\x79\xd9\xbc\x47\x6e\x3f\x7b\xb4\xbb\xf6\xaa\x34\x7a\x07\x7d\xbb\xeb\x5b\x38\xf0\x82\x0b\xaf\x58\x3a\xe3\xd6\xc7\xe1\xdc\xf7\x60\xf8\x8c\x5b\x1f\x7d\xf2\xd5\x86\x33\x3f\x9a\x71\x56\xbf\xe2\xde\xf5\xbf\x79\xe9\x18\xfa\x01\xb5\xee\xff\xe3\x6f\xa6\xec\xb8\xef\xde\x8b\x22\x6d\x78\xbf\x89\x3d\xe7\x9a\x41\xe5\x2f\xdb\xf2\xaa\x7f\x65\xcb\x7b\xfc\xef\xb4\xe5\xbf\x60\xc2\xff\xa5\xe5\xc6\xba\x09\x2d\xe1\x16\x9a\xdc\x20\x04\xca\xc0\x70\xa0\x0a\xfa\xf1\x85\xf3\xab\xf5\x0a\xf5\x4a\xb6\x72\x18\xd1\x1c\x40\x56\x92\x82\xd9\x5f\x82\xcf\xcc\x53\x28\x2b\x09\x99\xa3\xf6\xc8\x2c\x64\xfd\x53\x57\x9f\x00\xac\x30\x45\x60\x63\x48\xe0\x00\x1d\x87\xc6\xe0\xeb\x12\xa2\xae\x76\x2d\xe4\x27\x2e\x3c\x02\xdd\x17\xce\x38\x5c\xcf\xda\xab\xd0\x5f\x51\xdb\xdd\xe3\x26\xcf\x9a\x56\x77\xc9\x65\xe8\xcd\x79\x17\xf4\xbb\x68\xfd\x72\xe6\x39\xd8\xb2\x01\x2a\xd0\xfe\xa1\xf8\x79\xcb\x5f\xd0\x47\x47\x6e\x19\x39\xbb\x67\xfd\xa8\xe9\x43\x26\xfd\x7e\xf2\xbc\xb9\x35\x65\x7d\x2a\x86\xbd\x3d\x04\x9f\x11\xc1\x1b\x5c\x33\xf0\x82\x39\xdd\x62\x0d\xdf\xaf\xc2\x1a\x05\xa7\xc1\x1a\xaa\xa2\xc3\x8c\x5f\x0b\x2f\xba\x43\x15\xdd\x80\x09\x9a\xdb\xb9\xbc\xb3\x9d\x5b\x66\x2a\xd1\x73\xb7\x63\x40\x42\xc4\x32\xa6\x98\xd2\xaa\x37\xaa\x15\x08\x69\xb5\x38\xaa\x99\x4c\xd9\xac\x8e\x1e\x56\x0e\xe2\x45\xe8\xf8\x28\x88\xbd\x3e\x93\xe8\x29\x20\xb8\xd9\xab\x50\x53\x58\x5c\x40\x02\xc4\xf4\x1c\xa8\xae\x92\x18\x40\xf4\x3c\x16\x9b\x90\xc9\x15\xa2\xfa\xe9\xf2\x33\x6f\x7a\x70\xcf\xaa\x1d\xaf\x3d\x83\x3e\xdf\xf7\xea\xbb\xb0\x6a\xde\xa4\xdb\xfb\xa1\x7b\x4b\x46\xc3\x99\x85\x0d\xf1\x67\xe0\xd6\xe5\x70\x12\x1c\xfb\xfe\xd5\xe9\x3f\xa1\x7f\x66\x9e\x41\xdf\x1f\x52\x5f\xf8\xea\xdb\xc7\xe1\x5d\x0f\xdf\x32\x6a\x2a\xde\x7b\x8c\x81\x56\x71\x18\x03\xdd\xd2\x1d\xfe\x91\x4f\x8f\x7f\x94\x7f\x17\xff\xa8\x0e\xc2\xed\x6c\xf9\x55\xb8\xa7\x2b\xdc\xe9\x0a\x73\x88\xcc\x00\xc0\x7d\xcf\x35\x01\x07\xb8\xc7\x88\xe3\x3b\x62\x31\x22\x38\x7a\x1c\x9f\x0e\x88\x74\x88\x69\x2c\x32\xe4\x97\x1a\x71\x5a\x6a\x61\x1c\x12\xc9\x61\xe8\x49\xa0\x24\xeb\x60\x5c\x91\x24\x47\x9e\x22\x7e\x26\x44\x47\xd7\x3c\x90\xca\xc5\x41\x42\x64\x39\x6c\x71\x52\x90\xa1\xaf\xb2\xa4\x1c\x40\x56\x48\xb2\x02\x8b\x55\xc8\x01\x85\x98\x91\x0e\xaa\xf8\x16\xd6\x84\xab\x7b\x99\xe1\xbb\x70\x3c\x72\xc0\x22\xa4\x3e\x7f\xd3\x08\xae\x69\xfd\x8b\xab\xe0\x41\x64\xce\x3c\x0c\x37\x0d\x47\x9b\x88\x7d\xdd\xd4\xd9\xce\x35\x9a\x42\xa0\x14\x84\xc0\xfd\xfa\x4d\xf0\xea\x65\x73\x2a\x1f\xd5\xac\x34\xb4\x80\xf5\x2f\x49\xcb\x4c\x3d\xea\xcd\x7a\xdd\xfe\x56\x4d\x0c\x1d\x55\x1d\xad\x2a\x23\x25\x21\xe3\x77\x45\x92\x01\xfc\x4c\x40\xc6\x9f\xb7\x8a\x40\x1c\x6c\x83\x8c\xe8\xf0\x07\xf4\x1e\x81\x2e\x7f\xd1\xa5\xc8\x80\xb6\x9f\xf1\x72\x4a\x70\x15\x16\x93\x18\x85\x95\x16\x6d\x86\x61\x15\xd6\x62\x42\x15\x51\xe0\xc4\x5c\xd2\xe3\x8a\xc2\xca\x2a\x0c\x4b\xe0\x64\xe6\x72\xab\x65\xc0\xa0\x5e\xf1\xf2\x4b\x66\x6e\xfc\x43\x60\x86\x33\x56\x57\x1a\x3e\x6f\x6e\xf3\x7c\x77\x91\x4d\xf0\xd5\x97\xfe\x03\x26\xb8\x8a\xc9\xe3\x87\x8b\x47\x7c\x7f\xd8\x91\x61\x9a\x2f\xb1\xfe\xad\xf4\xce\x95\xef\x9e\xf7\x64\xef\x85\x67\xa2\x06\xae\x09\x00\xd8\xf9\x32\x72\x73\x3b\xb8\x26\x10\x00\xad\xb4\x16\x82\x96\x67\x99\x2d\x69\xfd\x7c\xed\x31\xc2\x30\x14\x88\xe9\x44\x3f\x5a\xc0\x99\x56\x03\x64\x10\xa5\xc6\x88\x24\x01\xac\xc7\xb1\xb0\xde\x23\x67\xbf\xb9\xe3\x27\x83\xdc\xe8\x03\x12\x7e\x0a\x48\x49\x36\x80\x0f\xbb\x80\x3c\xfd\xf8\x99\x28\x08\xe4\x1f\xb9\x9f\x64\xff\x12\x6c\x81\x1f\xef\x94\xfe\x6f\xae\x97\xc2\xec\x8a\x63\xcd\x92\x70\x4a\xa4\xbb\x49\xc4\x02\x0e\x34\xb3\x53\x56\x92\x92\xec\xf5\x11\x15\xc3\x42\x1a\x8e\xd2\x23\x51\x7a\xf3\x21\x86\x6c\xec\x50\x38\x0e\xd6\x2c\x95\x06\xf5\x9e\xb8\xa6\x66\x3a\xac\xf9\xf6\xa0\x62\x9d\x7b\x7f\xec\x02\xb7\x55\x74\x9c\x87\xdc\xa6\x11\x99\x05\xc3\x1a\xcf\x1c\x7c\xe0\x00\x3c\x70\x7c\xa3\xfa\x46\x55\xe1\xcc\x71\x44\x4c\x00\x04\x33\x00\xe0\xe6\x73\x4d\xc0\x8e\x31\x84\x1d\xef\x0f\xc0\xf7\x55\xc8\x26\x3e\xa1\x98\x56\xa1\x9e\xbc\xa2\x89\x4f\x9a\x39\xb4\x93\xf8\xbb\x2d\x0e\x34\x60\xd7\x5b\x32\x5d\x18\x40\xf4\x55\x5c\x21\x06\x08\xa1\x19\xb0\x6a\xa0\x75\xc9\xb3\x83\x60\x6c\x30\xfa\xd3\x51\xf4\x11\xd7\x94\x79\x70\xda\x92\x47\xe0\x2a\x58\x8e\xd6\x67\xd2\x7f\x01\x0c\x98\x8c\x96\x70\x71\x93\x1b\xf4\x06\x75\xe0\x26\xa0\x06\xa2\x9a\x8f\x4f\xab\xb6\xa8\xea\x8c\x69\x22\xd6\x73\xf5\x14\x34\x88\xe9\xa4\xa9\x08\x98\x23\x9a\x9b\x06\xc1\x22\x30\xa2\x95\x4b\x69\x2d\xa6\xd7\xd2\xab\xd1\xb8\x5a\x24\x27\xed\x62\x8f\x5a\x2c\x5f\x11\x6a\x3f\xb5\x72\xb7\xac\x24\x2c\xc4\x03\x00\x9a\x2f\xa0\xdb\x5b\xd5\x26\x6b\x26\x37\xdd\x63\x4b\xbe\x59\x6d\xa4\x06\x4a\x8f\x88\x65\x0d\xeb\x29\xa6\x6a\x32\x9c\x3d\x75\xf6\xfa\xcd\x2f\x9e\xd1\x50\xc7\xfc\x50\x53\x70\xd7\x81\x59\x73\x9b\x67\xd4\x0c\x4b\xbe\x37\xec\xea\x9b\x2e\xa9\xc1\x26\xeb\xba\x51\xfd\x47\x3c\xb8\x82\xd9\x0e\x1f\x86\xfd\x9b\xcc\xbe\xeb\x47\x5f\x7b\x5f\x4f\xf1\xf3\x0f\xcf\xba\xe9\xe2\xd1\x63\x3f\x5c\xdc\x3c\xf4\x37\x7d\xce\x1c\x79\xe9\xc0\x49\xbf\x9f\x7c\xdd\xcd\xb5\x95\xb1\xb2\x61\xdb\xeb\xb3\xf5\xf3\xdc\x58\xae\x19\x88\xc0\x9f\xcd\x8d\x49\x56\xbd\x7e\xde\x6b\x4d\x13\x17\x92\xea\x21\x6c\x86\xdd\x7a\x66\x15\x1b\x00\x77\x2e\x37\xe6\x95\x64\x45\x03\x34\xc6\x4d\x22\x7e\x7a\x81\x38\xd1\xf6\x78\x15\x04\xd3\xaf\x86\x8e\x6d\x6f\x7c\xb5\x0a\x1d\x79\x7e\x67\x1a\x46\xd7\x9d\x7f\xd3\xd9\xab\xcf\x9f\x77\x3e\x7c\xf8\x00\xbc\xe0\xf9\xf6\xbd\xfb\xd1\xf6\xe4\xdf\x77\xbe\xb8\xe0\xd3\xc5\x6f\xde\xdc\x4e\xe4\xa4\xa9\xb3\x9d\xff\x8c\x6b\x02\x7e\xb0\x17\x24\x0a\x00\xe1\x95\x23\xf7\x49\xb3\x5a\xd2\x09\x06\xff\x42\xbf\x90\x4e\xf0\x1e\x2f\xa1\x4b\x0b\x44\xd5\x82\x36\xcd\xe7\x24\x55\x8e\x58\xbb\xbb\xea\x09\xf1\x83\xa9\x3e\xeb\xeb\x3e\xd2\xf1\x3a\xd1\xa0\x05\x58\xe1\xa8\x3e\x49\xf5\xb6\x6e\x1f\xb8\xf3\xc7\xf9\x46\xc3\x12\xaf\x7a\x5a\x39\xcd\xe4\x39\xca\x93\xd8\xf0\xae\x1f\x1f\x26\x77\xcd\x25\x25\xdd\x2e\x0f\xc6\xf0\x2e\x4f\x5e\x5c\x37\x61\x22\x3d\xce\x30\xc5\x7b\xbc\x7e\x77\x2e\x05\xec\x2b\x20\x48\x57\x33\x2b\xa4\x93\x1f\x68\xd6\x02\x4a\x33\xed\x97\x35\xbb\x42\x36\x69\x10\x0c\x09\xe1\x7c\x7b\xd1\xd0\xa7\xaf\x2b\xc4\x86\x5c\x4d\x45\x6f\x70\x8f\x46\xbf\xbf\xda\x3c\x72\xf0\x90\xcb\xef\xbb\x63\xa5\xed\x7a\x74\xf8\x65\xf4\xfe\xab\xec\xfc\x7b\xc7\x1c\xca\x7c\xd9\x43\x1e\x1e\xfa\xa4\xf1\xb6\xf9\xc1\x61\x4c\xec\xc4\x52\x76\x7e\xd6\xaf\xb9\x8a\x6b\x26\x13\x8c\x9f\xa6\x37\x8a\xd4\xd3\x61\x00\xa2\x05\xa9\x83\x23\xc7\x8c\x30\xba\x0e\x82\x0b\xf4\xcb\x55\x9a\xcd\x0c\xbf\x9f\xef\xbf\xc8\x92\x5a\xdc\x9a\x74\xca\xc5\xa4\x42\x19\x3f\x15\xfc\x4c\x38\xe5\xe2\x3c\x0d\x23\xd1\xf6\x6f\xa8\x14\x3b\x25\xaa\x8f\xf3\x5e\x93\xbd\x20\x59\x53\x92\x04\xd7\xdc\x76\x6a\x43\x83\x32\xd1\xc5\xac\x6b\x20\x43\x05\x05\x3b\x81\x0e\xc8\xba\xbc\x79\x6d\x06\x43\xbe\xaa\xbd\xab\xed\x91\x9d\x7f\xba\xfd\xfb\x87\x1f\xbf\xd4\x52\x3a\x3c\x59\x77\xf9\xb0\xe6\x0b\x86\x0c\xba\x64\x56\x19\x72\x73\x67\x7c\xfc\xe7\x6b\xbe\x7e\xef\x43\x94\x7a\xfe\x96\x31\x2a\x7a\x8e\x0d\x8f\xbf\xed\xc8\xb5\xe3\xa7\x3f\xf2\x38\x95\x69\xb4\x84\xf4\x84\x60\x3b\x34\x0c\x50\x51\xb6\x58\x68\x58\x1b\xb4\x69\xa2\x93\xa4\x07\x88\x08\xeb\x61\x6d\x11\x5b\xbf\x82\xe2\x78\x5c\x73\x07\xb1\xb3\x2f\x71\x7a\x13\xb6\x45\xee\xda\xe8\x91\x0d\x5e\x9f\x02\x26\x1f\x87\xf6\xa7\x9f\x7e\x60\xf2\xad\xd3\xc7\xde\x3d\xea\xc2\xcb\x75\x20\x79\xdd\xa8\x81\xe7\x3e\x72\x37\xf3\x24\xdc\xb1\x03\x9e\xbf\x75\xf8\xa1\xf8\xb5\xad\x57\x8d\x9e\x55\xa3\x83\xc8\xeb\x6e\xae\xed\xd1\x58\x7a\xee\x5b\x03\xe8\x3d\xe4\xfb\x13\xbf\xaa\x08\x9c\x4f\xad\x86\xe6\x36\xee\x61\xc0\x44\x93\x5d\x84\x36\x1b\xc3\x79\x55\x91\xe8\x24\x6c\x31\xad\x95\x60\x6f\x86\x4a\x1a\x6d\x4e\x01\x94\x5d\x02\x58\xb3\xd7\x31\x24\x84\x88\x97\xc8\xe8\x37\x52\x69\xe8\x53\x45\x6e\xe4\x63\xb0\x6e\x2f\x33\x38\x8a\xbe\xaa\x68\xb8\xe4\xfe\xbd\x77\xbc\x8b\xaf\xe5\x0d\x6b\xab\x8b\x66\xae\x1f\x03\x37\xef\x87\xfd\x37\x7f\x5e\xf3\xc8\x95\x73\x3a\x36\x4f\x6a\x6f\xdb\x03\x4d\x3b\xaf\x99\x71\xd3\x01\x7a\x2f\xb9\x0a\xae\x09\x78\xc0\x5c\x70\xd2\x7d\xf4\x08\x34\x3b\xed\x8d\xaa\x4a\x9b\xea\xae\xc7\x22\x86\x2f\xa0\x31\xdc\xf7\x81\x8e\x27\xe8\x5d\x73\x1b\x77\x2d\x48\xee\x1a\x0b\x34\x93\x9b\x44\x98\x3d\xb4\xc0\x00\xdf\x1d\x8d\xe9\x42\xd2\xee\xe9\x72\x7b\x42\x5d\x6f\x4f\xa3\xab\xa9\x68\x07\xd3\x5e\x87\x12\xcd\xa6\xf1\x83\xa7\x61\xd0\x65\x6f\xa6\x97\xe6\x50\xb1\x6f\x04\x86\x5d\x4b\xea\x07\x32\x41\xac\x57\x48\x5c\x89\x6b\x02\x2e\x30\xf6\xd4\x88\x92\x91\xa3\x3e\x7d\xb6\x49\x8f\x15\x91\x3a\x01\x0e\x3b\x1c\x16\x39\x9e\x0b\x02\x75\x1f\xf8\x39\x35\xb2\xd3\x6d\x00\x47\xd7\xc9\xc8\xcd\xef\x24\xfd\x3e\x61\x70\x00\xd0\xb2\x58\x36\xa6\x85\x4c\x69\xec\x4a\x78\x63\x50\x2d\xcf\x4f\xfe\xfb\x6c\x11\xc3\xb9\xc0\xb2\x20\x3b\xd3\x5a\x05\x3c\x69\xea\x83\x4f\x52\x6d\xad\xaa\x57\x52\xc3\x58\xed\x25\xad\x3e\x9b\x2b\x42\x33\x58\x61\x57\x04\xbf\x53\x60\xbc\x13\xc4\xef\x24\x0a\x7c\xb6\x2e\xdd\xc2\x09\x8f\x37\x8c\x5f\x05\xe3\x60\x9b\xd5\xe6\x29\x08\x86\x0d\xfc\x95\xff\x17\xcd\x8e\x18\xcd\x39\x6a\x89\x4c\x10\x45\xc8\x27\x2b\x09\x01\x10\x90\xe1\x90\xa9\xd5\xee\xa3\x34\xfa\xe8\x45\x72\x65\xfb\x89\xb0\x0f\x53\x0b\xf9\x81\x0c\x36\x17\xc2\xc4\x27\xde\x78\x63\xe5\x6f\xc7\x0e\xfd\x6d\xf4\xbd\x3f\xbc\xf0\xfe\xd3\xe8\xcd\xbd\x53\xd1\x67\x33\x5f\xf9\x9c\xf9\xdb\x8c\x75\x17\x35\x4d\xe8\x01\xf7\xbc\x09\x07\x6c\xda\xf2\xbb\xf4\x82\x39\x37\xc9\x0c\xf7\xe1\xcb\x5f\xbf\xb3\x0f\xbd\xfc\xa2\x05\x55\xc2\xbf\xf8\x7f\x2e\x97\x56\x7e\x76\x47\x42\xa5\x7c\x22\x27\x90\x9b\x6b\xe7\x9a\x41\x09\x18\x04\x12\x4e\xec\x9a\x59\xb1\xac\xf2\xb6\x34\x31\x6e\x31\xcd\x43\xcb\xd6\xb0\x3b\x03\x34\x4f\x40\x56\xd4\x02\x0c\x1f\xb7\x41\xc1\x21\xd3\x42\x78\x27\xc5\x8f\x16\xc8\xe6\xf0\x63\x09\x84\x21\x98\x87\x21\xab\x58\x88\x4e\x30\x8b\x1a\xc4\x9e\x3d\xcb\xaa\xfa\x5c\x31\xe3\x96\x45\x05\x01\x78\x16\x1c\x99\x79\x7d\x84\xa5\x77\x5d\xcd\x19\xd3\xa6\xdf\x7a\x87\xaf\x1a\x2d\x42\x6e\x76\x21\xbc\xf0\x82\xc1\xce\xc3\x55\x2b\x1f\x7f\x1e\xee\x3b\x71\x0c\xd5\x9d\xd1\xdf\x79\x38\xb4\xe2\x31\xe8\xcf\xbc\x4c\x31\xd2\x3c\xe4\x36\x15\x99\x14\x10\x00\x2f\xea\x71\x16\x29\x46\x4f\x5f\xf5\x44\xd5\x82\x98\x26\x5a\x28\x67\x6c\xf0\x17\xa4\x15\xab\x09\x5d\x3a\x8c\x20\xa7\x9d\x7a\xa1\x72\x1e\xbc\x5c\xdf\xf1\x22\xbd\x97\x59\x41\xb1\xb7\xf2\x5d\x24\x45\xf4\xda\x5d\x91\xa4\x07\x3f\xb3\xf2\xc2\x02\xcd\x66\x27\xed\x0e\xa2\xa7\x20\x9b\xfe\x66\xc5\x53\xb2\x99\x3e\x18\x82\x7d\x15\x39\x24\x19\xa7\xac\xdf\x87\x49\x97\xc0\x22\x58\x8a\xbe\x7a\x63\x1b\xac\xd9\x80\x76\x1c\xbf\x0c\x7d\x31\x7d\xdf\xa7\xb9\xab\x71\xc1\x78\x9e\x1f\x74\xec\xcd\x52\xa8\xc1\x16\x34\x15\xd5\x74\x78\x51\x1d\xdc\xeb\x79\x8b\xee\xd1\xc4\xce\x76\x13\x86\xdc\x15\xe0\x0d\x90\x08\x63\x7c\x50\x1c\xd3\xcc\xe6\xb4\xaa\xd4\x13\x6d\xa4\x16\xc4\x48\x3f\x1c\x30\x32\x62\xf9\xd9\x61\x23\x05\x58\x05\xbb\xf0\x50\x73\xaa\x9d\xd4\x40\x71\x9a\x18\x3d\xea\x50\x9d\xad\xaa\x53\x4a\x3a\x9c\xa2\x2b\x92\x70\x38\xc5\x3c\xe3\x9f\xb2\xd9\x45\xbd\xf2\x0b\x26\x68\x0d\x18\xcd\x8c\x01\x9a\x21\xb5\xcb\x1a\x1b\x26\x90\x4f\x93\x4a\xe3\x71\xd5\x2b\x27\x14\x6c\x61\xe2\x6a\x50\x51\xfd\x18\x68\x87\x65\x45\x2d\x8d\xab\x8c\xac\x81\x20\xad\x0e\x70\x85\x4c\x8c\xde\x46\x1b\xc2\xb7\x83\x06\x44\xab\x42\x34\xbe\x54\x45\xa2\x7c\x13\x8f\xc0\xe8\x4d\x2b\xaf\x1b\x36\xb6\x70\x10\x2c\xaa\xae\xbe\x7c\xf8\x4d\xe7\x95\xc0\xa2\x62\xf4\x25\xea\xfc\xcf\xf8\x90\x8d\xb3\x9e\x6c\x81\x0b\xe1\x44\xb8\x54\x45\x0b\x9f\xdc\x7a\xe3\x9d\xb0\xea\x95\x9d\xb5\xcd\x8f\xc0\xaa\x8d\x0f\xdc\xbd\x70\x05\x9a\x8d\x22\xbb\xe6\x4c\xd9\x0f\x8c\xfc\x01\x7b\xa6\x89\x03\x12\x08\x80\x72\xb0\xf5\x54\xff\x59\xf5\x47\xd5\x70\x4c\x73\xdb\xd2\x6a\x71\x3d\x69\x23\x39\x8d\x33\x8d\x65\xcf\x8b\x65\x8f\x80\x8b\x28\x16\xb8\x64\x90\x7c\xa7\x54\x24\x9d\x26\xbf\xde\xd3\xf6\xca\x04\x25\x90\xa8\x7b\xc2\xe2\xf6\xff\xda\x3c\x43\x37\xb9\xc6\xae\x3e\xf8\x79\x5d\x73\x8d\x27\x65\x1e\x32\x27\xe5\x5d\x69\xee\x81\x03\x2e\x50\x04\xaa\xc0\xc2\x6e\x32\x0f\x85\x51\xb5\x92\x66\x1e\x42\xf5\x46\xac\xf1\xf4\xd7\xd0\x6d\xcb\x96\x28\x18\xd7\xb0\x18\x7f\x2b\x2c\xd2\x38\x24\x5d\xae\x5c\x88\x05\xc4\x2f\xab\xbe\x5f\x32\x28\xdd\xe5\x56\xbb\x31\x32\x35\x5d\x17\x7d\xda\xac\x41\xde\xda\x69\x9e\x75\xac\xa9\x89\xf8\x04\x21\x50\x06\x46\x1b\x35\x73\x06\x1e\xf1\x59\xb3\xe1\x39\xda\x70\x43\x6b\xe6\x44\x1a\x9e\xf3\x38\x65\x25\xc5\xd9\x02\x45\x21\x9d\x15\xa6\xb8\xc4\xe0\xb5\xea\xd6\x47\x00\x9e\xac\x93\x60\xca\xe5\x4a\xbb\x75\x16\x6e\x33\x72\x81\xf9\x3e\x03\x3c\x6b\x21\xf5\x1a\x60\x5b\x5e\xfa\x28\x7b\x86\xd8\xce\x07\x41\x21\x98\xd1\x9d\xad\x2f\xfa\x95\xb6\xbe\x38\xdf\xd6\xab\x36\x39\xe1\xf6\x05\xf1\x51\xd9\x15\xad\xc0\xff\x8b\xd6\x3f\x9b\xf0\xeb\xe6\x84\xbe\x33\x96\xd4\xed\xd1\x54\xe5\x56\xc4\x52\x7d\x67\xc2\xfa\xae\x06\xd4\x82\x5d\xa7\xd7\x79\xd1\x5f\xd0\x79\xbd\xff\xb7\xeb\xbc\x94\x54\x5a\x59\x5d\x83\xcf\xdf\x2b\xa7\x94\x82\xe2\x9e\x11\xfc\xfa\x7f\x4e\xf3\x65\x77\xf1\x97\x55\x20\x93\xdd\xd5\x5f\xd6\x85\x5c\x20\x7f\x8f\xa7\x77\xb6\x73\x5b\x4d\x25\x20\x08\x7a\x80\x3e\x60\x95\xde\x9d\x54\x62\x25\xf9\x1e\xc5\x94\x56\x6d\xd1\x54\x2f\x3b\xe8\xc7\x45\xd4\xfa\xa8\xc6\xdb\xd3\x50\x6d\x20\xbb\x5d\x28\xa6\xd5\x42\x49\x2b\xa3\x71\x6a\xd5\x23\xa9\xe6\xd2\x36\x39\x15\xa5\x7c\x0c\xd1\x68\xca\x4c\x73\x68\x7d\x61\x44\x2b\x2b\x94\x95\x6d\x36\xc5\xef\xac\x26\x04\xc8\x51\x59\xe3\xeb\xb3\x09\x34\x0f\xa0\x0c\x21\xce\xb8\xd6\x8b\x8e\xde\x52\xeb\xa9\xc7\xe4\xea\x13\x80\xe5\x39\x02\x38\x21\xaf\x13\x9b\xa9\xc8\xd1\xbf\x09\x26\x68\xe4\x81\xc2\x65\xa6\xe9\xb7\x7e\x08\x0b\x9f\x5d\xb5\xe9\xfd\x17\x1f\x98\x79\x49\xf9\x79\xcf\x4f\xdc\xfa\xf6\x7d\xe8\xb0\xda\x96\x86\xa1\xcb\x26\x5c\xb7\xae\x69\xf8\xca\x25\x76\x68\x2a\x6a\xaa\x3b\xef\xe2\x33\x6a\xe2\xb7\xc2\x4f\x12\xf0\x15\xd8\xb0\xf1\x8e\x39\xbf\x7b\x64\xe8\xbd\xcf\x5e\x38\xf9\x03\x6d\x2b\xfa\xe7\x3d\xa0\xf3\xab\xe6\xf9\xc9\xa5\x17\x5d\xb1\xe4\x5c\xe6\x90\x2f\x18\xef\x55\x56\x75\x0e\xc1\xaa\x73\x3b\xdb\xf9\x94\xa9\x04\xd4\x80\x7e\xe0\x0f\x20\x51\x86\x77\xcb\x6e\x4e\xab\xbd\xa2\x1a\x6b\x4e\x27\x8b\xd9\x5e\xe6\x88\xea\x8c\x69\x41\x21\xad\xd6\xd5\xab\x7d\xa3\x9a\x57\xa0\x95\x19\x3d\x89\x84\x26\x7a\x92\x19\x82\x3d\x81\x25\xa2\xf6\x94\xd4\x0a\x7c\x05\xad\x62\x3a\xe9\x32\xf5\x34\x47\xb4\x5a\x2a\xc2\x31\x18\xd1\x02\x62\x5a\x0d\x48\x54\x69\x12\xa5\x13\xd5\x8a\xc5\x34\x29\xe5\x30\xf5\xa4\xe4\x72\xb5\x2e\x59\xd1\xec\x65\x34\x8d\xe1\xed\x8b\x77\xb4\x97\x5d\x56\x12\x66\x50\x81\xef\x2a\x2b\x6b\xd0\x14\x8f\x6b\x7d\x83\xb2\xa2\xba\x68\x4b\x1c\x0d\x9e\x13\x3b\xa2\xb8\x6a\x19\x92\xe9\x50\x8a\xa0\x10\x13\xc2\x56\xc8\x51\xcf\x82\xaa\x26\xe8\xf6\xfa\xf4\x2d\x9d\x7b\xc3\x9c\xd9\xb3\xc2\x81\x5b\x6e\x56\xfb\x3f\xfe\xed\x2d\x3f\xec\xde\xf5\x31\x73\x7f\xdd\x92\xbe\xdb\xd1\x8f\x9a\xf6\x41\x89\xc5\x19\xaf\x64\xce\xb9\xfb\x16\xd3\xf0\x41\x43\x06\x33\x75\x1f\xd5\xcc\x1a\x3b\xe2\xba\x8b\x7b\xce\x80\x16\xe8\x36\x5f\x9d\xbc\xf6\xa5\x8f\x50\xe6\x9f\xe1\xf0\x21\xf4\x17\xf4\x87\xdf\xaf\x5f\x32\x78\x4a\x51\xbd\xef\x0c\x66\xf4\xb8\xe9\x6c\x7d\xe3\xdc\x5b\xc6\x03\x08\x5e\x00\x80\x1f\xce\xef\x04\x0a\x68\xa6\x3a\x4b\x95\x62\x09\x13\x43\x6b\xb5\x08\xd3\x82\x2b\xaa\xca\x46\x30\xfe\x94\x9a\x4d\x77\x16\xfc\x3f\x4d\xcd\xad\x4c\x2a\xda\x48\xad\x37\xd0\x9c\x0a\x36\xb7\xf8\x49\xa3\xa5\x36\xac\x96\x2d\x4c\x3c\xae\x9a\x74\x29\x0b\xb9\x1a\x15\x83\x93\x44\x30\xd9\x60\xc8\xf5\x02\xec\xb7\xf8\xec\x47\xf6\xdd\x79\xf1\xa8\x7e\x25\x95\xfd\xcf\xba\xfb\x9f\x73\xf5\x62\xce\x05\xb0\x64\x67\xf0\xaf\x8e\xd1\x9b\xd1\x85\x99\x4f\x49\x4d\xa7\x0b\x00\xd3\x1c\xbe\x83\xf4\x6c\x06\xc1\xe2\x5c\x9d\x9f\x13\xff\x7e\x4b\x4c\x73\x5b\xd2\x49\x10\x70\x9a\x23\xa4\xea\x3a\xd0\xa6\x5b\xc5\x53\x5a\x36\x8b\x4e\x5e\x45\x40\x52\x83\xad\xf8\x9b\x05\xad\x40\x2b\x08\xe2\x55\xe0\xa7\x5e\x79\x1a\xa0\x2d\x9b\x6e\x59\x83\x0a\x16\x00\x45\x33\xcb\xf1\xfc\xe6\xcd\xc6\x53\x97\xe5\xd2\x95\xc4\xee\xee\x96\xc7\xcd\x31\xd4\x02\xdb\xdd\x3a\xc9\x19\x09\xe3\x48\x55\x56\x25\x50\xbb\x3d\x27\x8c\xcd\x2b\x62\x9a\xd7\x96\x56\x4b\xeb\x49\x7e\xee\xb4\x87\x86\xdf\x2a\xc0\x6f\x91\x0e\x86\xa8\x56\x40\xf3\x2c\x45\x58\x59\xd0\xec\xdd\xaf\x3e\x52\x4d\xc2\x27\xea\x0d\xc6\xe3\x5a\x81\x4b\x4f\xb9\xfe\x8a\x43\xee\xb6\x5a\xab\xdb\x83\x2f\x39\xb5\x68\xeb\xa4\xfd\x39\xa5\x76\x8b\x25\x3e\xed\x6b\x26\x37\xb1\xc5\x61\xf0\xb3\x1e\x95\x29\x30\xa7\xd5\x70\x7d\x42\x20\xfe\x4d\x54\x75\xc6\x54\x3e\xaa\x9a\xb2\x0e\xae\xdb\x99\x56\xdd\x7a\x67\x39\xc5\x19\x3c\xbe\xee\x54\x29\x94\x42\xd2\x7a\x9e\xf5\x75\x9f\xe8\xf8\x8a\xc4\xf6\x24\x29\xc9\x49\xbc\x2b\x82\x8d\x98\xe0\x34\xb9\x22\xdb\x07\x6e\xec\xf8\x84\xe4\x48\x1c\xf8\x4f\xfc\x05\x19\x7f\x21\xe9\xc3\x4f\x3e\x59\x80\xff\xc9\x7e\x09\xff\xcf\x0a\xf1\xf7\xf8\x64\x18\xff\x93\x90\x25\x3e\xcf\x15\xf6\xc5\x13\x0e\xa7\x09\xbf\x2a\x8c\x83\xa4\x43\xf6\x15\xd2\xc2\x4e\x0e\xbb\x8a\x05\x85\xe1\xae\x85\x9d\x05\x92\xac\x50\x16\x4f\x4e\x26\x15\xe3\x18\xf9\x60\x7c\x50\x0c\x73\x1e\x2f\xad\x01\x66\x20\x76\x7c\x2b\xab\x26\x3e\x0d\x23\xef\x4d\x84\x25\x13\xdf\xfb\xd3\x46\xf4\xd1\xbe\xa9\xe8\xb3\xab\x76\x7d\x0d\x63\xe3\xc6\xdd\x33\x65\xd5\x18\xb8\x7b\xca\xb2\x8b\x26\x8d\x82\x6f\xbe\x0a\xa3\x4f\x8a\xf0\x39\x34\xba\xf8\xc8\xab\xaf\xa1\x4f\x9e\xf4\xa0\x4a\xf8\x95\xef\xe8\x81\x2b\xef\x16\x99\x0d\xa6\x99\x3b\xd1\x3a\x71\xd6\x6b\xd7\x4f\x5d\xe4\xc4\x3a\xba\xa9\xb3\x5d\xd8\xcc\x35\x01\x1f\x88\x80\x2b\x74\x49\xb5\xc5\xb4\x80\x39\xad\x96\x53\xd4\xa0\xf9\x84\xb4\xc6\x55\xd7\x53\x0a\x53\x77\x1b\x91\xbf\x02\x89\xf0\x86\x60\x58\x57\x03\x23\x5a\x81\x5b\x56\x34\xc6\x17\x8f\xab\x55\xb2\x66\xc3\x30\x48\x50\x54\x3e\x0e\xb4\x00\x45\xec\xaa\x4f\x4e\x08\xee\xe2\x78\x2e\xbe\xa9\xc7\xf6\x2a\xa9\xf9\x6e\xe8\xa3\x34\xba\xb0\x61\xc7\x9f\x51\x8d\x8b\x2d\x3c\xd3\x54\xf4\x86\x69\x66\xf4\x27\xf9\x9e\xf6\x35\x57\xdf\x5d\x4c\xcc\xf7\x84\xf3\x16\x5d\x7b\xce\xc5\xc5\x25\xb0\xa8\x44\xb9\xfc\xfa\xbb\x4c\x19\xf3\x6a\x12\xca\x19\x7f\xcd\x5b\xe8\xd9\x67\xa7\xcd\x9c\x33\x65\xff\x8e\xdb\xa0\x6b\x26\xb2\x6f\xbd\x66\xc5\xb2\x65\xbf\xa9\x6f\x86\x91\x13\xe7\xf5\x46\x7f\xa5\x75\xcf\x1f\x21\x37\x1f\xe1\x9a\x40\x2f\x70\x8b\x5e\xf7\x5c\x15\x23\x25\x2e\xaa\x12\xd3\x4c\x26\x92\xd3\x0c\x9b\xd2\x50\xad\x21\x73\x4f\x1d\x94\x0f\xd9\x41\x4b\x5d\xbc\xb4\x81\xb8\x16\x46\x34\x07\x4b\x47\x12\x56\xcb\x5a\x69\x08\xbb\x70\x4a\xb2\x38\x4c\xb8\xc3\x81\x16\x2e\xa6\x18\x06\xc8\x6a\x28\xae\x9a\x94\x16\xb3\x43\xf6\x16\x04\x08\xcc\xb1\xc9\x24\xca\x1f\xd6\xab\x59\x68\xb4\xc0\xe3\x36\x09\x50\x47\x39\x8d\x74\x84\x66\x83\x97\xec\x06\xb6\x31\xb0\x7a\x89\x1a\x8b\x54\x45\x22\xc3\x67\xdd\xbf\x21\x58\xce\x8c\x80\xf6\xfb\xdf\x9d\xdf\xb7\x72\x74\xd5\xbd\x77\x8d\x1b\x5c\x1d\xaf\x8f\xdb\x43\x89\x51\x99\xbd\x2f\xc2\x1d\x4b\x86\x0e\x96\xf6\x15\x3e\x7c\xef\xd9\xb7\x4f\x64\x46\xbe\x8d\x06\xdf\x37\x5f\x41\xcb\x52\x8f\x06\x0f\x28\x67\x9c\xf9\xe0\x80\xfd\xf7\x3d\x9a\xd9\x01\x18\xb0\x15\x00\xbe\x83\xdf\x43\xe2\x89\x7a\x56\x37\xe5\x21\x73\xb0\x68\x73\x43\x90\x4d\x67\xe3\x89\x12\x89\x27\x16\xe8\x25\xe0\x25\xf8\xac\x09\x2d\xa5\xdd\xe1\x24\x6b\xf5\x88\xd8\xae\x3a\x49\xbd\xab\x06\xcc\x39\x04\xcf\x65\xe3\x36\x95\xf9\x00\xc4\xb4\xf5\x45\x38\xfe\x50\x12\x3a\x56\xff\x1e\x1d\x78\xbd\x11\xed\x8d\xbf\xfd\x06\x3c\xeb\xde\xd5\xaf\xfc\xf5\x3f\x6e\x7b\xe9\x6f\xac\xf9\x8f\xf0\xec\xe7\xee\xfc\x7e\xfd\xcb\x68\xff\x8b\x5e\x74\x0c\x3a\xfa\x42\xf6\xc3\xdb\x56\xb7\xbf\xbe\x70\x5d\x87\x11\xff\x22\x39\x09\x27\xb5\x20\x54\x53\x58\xd3\xaa\x3d\x4a\x30\x7b\x61\x5e\x26\x5a\xb5\x61\xa5\x49\x82\x1a\x51\xcd\x46\x95\xa6\x57\x17\xda\xa2\xae\x3d\x4f\x0e\xd5\x4e\x7a\xc0\x6d\x92\x6a\x6d\x05\x9a\x55\xc4\x4a\x13\x3f\xa9\xdb\x69\x93\x95\x04\xa7\xd0\x32\x82\x02\x3b\x89\x58\x29\xf1\x7c\x67\x45\x62\x8c\xeb\x7a\x4a\x4a\xe3\xf8\x9f\x66\xa0\x0f\x67\xdf\x70\xd7\xa9\x49\x0d\x74\x10\x2d\xa9\x44\x85\xf0\x48\x74\xf7\xba\x5c\x6a\x03\x40\xb0\x09\x00\xbe\x84\xdf\x03\x7c\x20\x0e\x12\x6e\xa3\x66\x59\xb3\xb2\xe9\xa4\xd9\xcd\x9b\x8d\xe9\xfa\x84\xa9\xc1\x0f\x23\x40\x33\x93\x98\xae\x33\x1e\xd7\x78\xab\x9c\x2b\xaa\xca\x46\xa5\x19\x8f\x14\x8a\x91\x1f\xb8\xe9\xb2\xb7\xa1\xfc\xd8\x67\x3b\xe7\x3d\x7e\xf7\xa4\x47\xaf\x39\x03\x0e\x6b\xba\x06\xed\x3d\x33\xb5\x93\xe5\x56\x41\xd3\xae\xab\x67\x1e\x9b\x36\xe4\xe6\xa7\xc6\xa2\x23\x99\x23\x30\x14\x3d\x4a\xf6\x7b\x22\x37\x88\x6b\x06\xe5\xa0\x02\x4c\xcb\xc5\xcb\x55\x6f\x54\x2b\x32\xa5\x8d\x10\x8a\x1e\x36\xc7\xe2\xe1\xd2\x29\x85\x44\x20\x2b\x49\xaf\xbf\xa8\xac\xdc\x17\xd7\x5c\x25\xd8\x83\x95\x38\xb2\x83\x45\x5e\x19\x63\x7d\xd5\x22\xa7\x80\xe0\x0a\x90\x12\x1a\xee\x74\xa1\x74\xca\x26\x5d\x59\xd5\x80\x61\xab\x11\x4f\xdf\x04\x95\xcd\x3b\xdf\x98\xfe\xfb\xdb\x27\x2f\x3f\xff\xfc\x2b\x57\x5e\x7b\xf4\x6f\xfd\x6f\x2a\xac\xbe\xae\xe2\xf5\x33\x2e\x5e\xb7\x82\xd9\x06\x5f\x4b\xc2\xf3\x53\x63\xff\x36\x62\xf6\xcb\xd7\x5c\x38\xa3\xe1\xdc\x95\xe3\x9e\x7f\x4b\xb1\x1c\x92\xe4\xd9\x65\xf5\x55\xe7\xbe\x3f\x32\xbf\x27\xdb\x06\x66\xeb\x7a\xc0\x96\xeb\xc9\x4e\x59\x79\xd2\x92\x6c\x65\xd3\x09\x2b\x8f\x31\xa8\x55\xb0\x44\xf2\x3a\x72\xb3\x7d\xa0\x9b\x3a\xbe\xcc\x4b\xbb\xdb\x24\x95\x6b\x4d\xf2\x36\xce\x15\x49\x5a\xf1\x93\x4d\x42\x8e\xb7\x9e\xd2\x95\xcc\x86\x1a\xc3\xac\xde\xbf\xcd\x8d\x82\x9f\xcd\xec\x04\xb1\xcf\xe7\xf3\x2d\x08\x2d\x45\xae\xef\x33\x3b\xf4\x3c\x71\x7f\xae\x09\xd8\xb0\x56\x26\x99\x61\x4e\x20\xc9\x1a\x5b\x4c\xb5\x46\x35\x5e\xe8\xf6\x97\x89\xb9\x5f\xb6\xbe\xe3\xf9\x7f\xe7\x97\xe9\x04\x32\x6c\xb8\x31\xcc\x0e\x85\xe3\xd8\xea\x3a\xc4\x9d\x0f\xf7\x5f\x76\xa4\xcf\x9f\xb7\x20\xb7\x69\xc4\x21\xb4\x11\x45\xff\x7e\xe2\x73\xbc\x77\xd1\xce\x76\xf6\x30\xbf\x1b\x54\xe1\x1b\x58\x0a\x68\x12\x82\xb2\x8b\x08\xa6\x74\xca\x55\x55\x6a\x17\x23\x9a\x8b\xa5\x65\x56\x61\x62\x31\x12\x05\x61\xfc\x6b\x0b\x8a\x2c\x11\x35\xac\xbb\xd3\x4e\x3d\xbe\x11\xe6\x68\x04\xc7\x29\x6b\xae\xaa\x78\x5c\x2d\xc0\xda\x13\x68\x81\x52\x59\xd1\x8a\xc2\xd4\xa8\x14\x14\xc6\xe3\x9a\xe0\xc2\x17\xd1\xe2\x24\xde\x35\xed\x44\x0f\x42\x3d\x2d\x94\xd5\xa4\x4e\x18\x62\xa9\x9b\xa8\xf3\xc7\x36\xf4\xe9\x3b\x08\x46\x0f\xca\xe1\x8a\xa2\x1e\xb5\x35\x4d\xd7\xdd\xf9\xbb\x70\xd9\x48\xa6\x04\xb9\x4b\x07\xd6\xf6\x0d\x5e\x55\x73\xfb\x7d\x3d\x4b\x66\x33\xf3\xe0\xcb\x65\xc3\x4b\xfc\x7e\xdf\xde\x8a\xf9\xb3\xeb\x66\x0c\xb9\x1f\x99\x7a\x0c\x2e\xac\x53\x0e\xd8\x9c\xcd\x97\x9f\x31\x7b\xe0\x3e\x7a\x37\x63\xc8\xcd\x29\xa6\x30\xa8\x00\x97\x02\xb5\x24\x4a\xd3\x2f\x51\xcd\xa6\xdf\x85\xb2\x36\xcd\x27\xa6\x93\x9c\xaf\xcc\x1c\x21\x79\xd1\xc2\x7a\x72\x1b\xb8\x32\x23\x3e\xe0\x93\x31\x16\x75\x28\x5a\x49\x05\xbe\x0c\x81\x12\x59\x51\x8b\x30\xf6\x4a\x9a\x1d\x85\x65\xc4\x44\xe8\x89\xe0\x46\x48\xaa\x76\x8c\x85\x09\x6c\x85\x00\xbb\x8c\x9f\xc5\xb6\x21\x56\x0d\xc7\xc5\xe2\xb5\xb5\x35\x17\x37\xdf\x79\xef\xc8\x13\xcc\xc4\x42\xb4\x24\x50\x56\xd3\xab\x2e\x76\xe1\xd5\x2b\x9f\x1c\x0e\xe3\x70\x7e\x2b\x33\x7a\x42\x7d\xbd\x6f\x5f\xf8\xa6\x99\x13\xef\x42\xc3\x17\x6e\xce\x4c\xef\x3d\x2a\x1c\xee\xa9\x7c\xe4\x5f\x38\x7b\xc2\x6d\x4c\x05\x5e\xd7\x22\x00\xb8\xf1\xfc\x1e\xe0\xc7\x3a\x87\x70\xdc\x30\xf8\x3c\x7d\x2c\xcd\xf2\x3a\x29\x41\x41\x90\x74\xe5\x51\x9a\x6e\x4a\x10\xc3\xfb\xe3\x84\x15\x80\x84\x37\xfa\x92\xc6\x47\x18\xea\xab\x34\xf2\x55\x15\x8d\x0d\x7d\xaa\xf8\xaa\x0a\x7c\x36\x8b\x5e\x39\x0e\x19\x58\x82\x3e\x45\x7b\x6e\xbe\xa3\x10\xb5\x34\xc0\x7b\x19\x2f\x3a\xa7\x11\x3e\x76\x56\xf3\x3d\xeb\xf9\xe9\xb3\xd1\x76\x74\x10\x8d\x47\x67\xed\x84\x8d\xf7\x3e\xf7\xf0\x47\x2e\xf7\xa5\xf5\xdf\xae\xff\xa2\x61\x34\xd9\xf3\xb1\xc8\xcd\x4e\x24\xb5\x99\xf7\x13\xae\x2c\x31\xaa\x2a\x51\x92\x47\x72\xb5\x91\x02\x00\x3b\x8c\xa8\xce\x7a\xd2\x19\x47\x93\x49\x6a\x65\x00\x6a\x8a\xab\xf6\x5d\xa0\xb9\x94\xda\x77\xf1\x85\x70\xcd\xdc\xc9\x51\x55\xef\x92\x54\x77\xab\xaa\x10\x96\x17\xfc\x3d\xd1\x81\xbf\xe7\x10\xf5\xef\x8d\x7c\xfd\x18\x6d\x0c\xc3\x00\x5a\x15\x25\xd5\xde\xca\x24\xed\x4e\xd9\x4d\x09\x0f\xf1\xbf\x14\xc0\x29\xa2\xde\x64\xe8\x92\xbd\x40\x91\x25\x46\xd0\x17\x5e\x49\x96\x3d\xf6\xaf\x70\xda\x8e\x94\x8a\xde\x78\xe2\x25\x11\x2d\x90\xe1\x06\x53\x11\xba\xce\x05\x2f\x6d\xe6\x7e\x86\x55\x31\xf4\x17\x34\x16\x1d\x47\x28\xf3\xe3\xb1\x9f\xe0\x87\xaf\x2f\xd8\xb2\xf8\x9e\x8b\x16\x3d\x77\xdd\x5b\xa4\xef\x10\xb9\xcd\xc3\xf8\x16\x10\x05\x3f\xea\x7c\x19\x96\x98\x16\xb4\xa5\xd5\x8a\xfa\x84\x87\x01\x91\x94\xb7\xa4\xb4\xba\x67\xb9\x2f\x46\x1c\x04\x96\x16\xe5\x7a\xda\x34\xaf\x33\x9d\xf4\x7b\x3d\xe6\x08\x35\xdb\x51\xcd\x2f\x65\x33\x3f\xa5\xce\xb4\x5a\x4a\x50\x8c\xd6\xd3\x99\xce\x72\xa0\x74\xfc\x34\x87\x6e\x8a\x87\x6c\x8a\x57\x52\x7d\xad\xdb\x07\x3e\xd2\xd1\x4a\xb6\xa0\x44\x52\x8b\x5b\xd5\x52\x49\x0d\x91\x66\xa8\x9d\xe4\xcd\x6a\x49\xed\xd1\x8a\xfd\xf1\x48\x2b\xd8\xe6\xf6\x15\x87\x7a\x44\x8c\x7c\x4f\xfe\x5f\xd4\x72\x7a\x64\x45\x73\x06\x49\xbe\x47\xb3\xd9\xe3\x71\xb5\x54\xd1\x2c\x15\x71\x82\x9b\x4c\x3c\xbe\x00\x41\x27\x96\x22\x1b\x9d\x9c\xa8\x90\xdc\x6f\xa8\x7e\x10\x24\x85\xbf\x7a\xf9\x6f\x43\x2e\xa0\xdb\xb7\xcb\x2b\xe8\x80\x5c\x38\xd2\xc8\x6d\x3e\xda\xb7\x8f\x6d\xf8\xa6\xab\xda\x2f\xb0\x5f\xfc\xa7\xeb\x36\x6d\x77\x7c\x02\x63\xbb\x9c\xf7\xcc\x7d\xbc\xa2\x05\xd6\xed\xb2\xae\x69\xde\xd0\xfb\x39\x58\x8f\xde\xaf\xfa\x3d\x3a\xf2\x36\x72\x43\x70\xe0\xd5\x49\xd3\x3e\x98\xfe\xdb\x67\xd6\x0d\xec\xcf\x49\x27\x86\x9c\x53\x7b\xff\x4b\x7f\x60\x27\x9f\x18\xd2\x70\xe6\x03\xcf\x7f\xcc\x36\x1e\x6b\x7a\xe5\xa3\xab\x29\x5e\xfc\x04\xb9\x85\x20\xd7\x04\x6a\xc1\x4b\x20\xe1\x81\x20\x92\xc4\x9b\x6f\xec\xbd\x40\x07\x5c\x29\x6d\x9a\xdf\x99\x4e\x7a\xfc\x8a\x99\x26\x54\xfc\xfa\xa6\x8b\xb9\x4d\xcf\x0b\xad\x1d\xff\xe9\x91\x6e\x36\xfd\xb9\x1f\x9d\x27\x6f\x3a\x48\xe2\x1d\xd5\xf9\x4e\xf5\x57\xa7\xee\xab\x5d\xec\xb2\xaf\x09\x4e\x30\x11\x3b\xeb\x81\xb2\xa2\x05\x2b\xe8\x08\xc6\x50\x69\x63\x5f\xa3\x40\xc7\xf4\xaf\xf6\x94\x65\xb8\x50\x55\x1d\x9b\x80\xc2\x00\x29\x6c\xbe\x33\x39\x67\x85\xdd\xb2\xe6\xc0\x92\xb5\xbe\x25\xb0\x66\x99\x34\x7d\xf2\xda\xe8\x54\x58\xb3\x4c\xbe\x6c\xca\x7d\x91\xcb\x60\xcd\xdf\xe2\xe8\x55\x74\x10\xb9\xbf\xfe\x76\xe0\x75\x5b\x6e\x9c\xf3\xe5\x93\xeb\xcf\x9b\xcd\x2c\xcc\x34\x0f\x8d\x2d\xf8\x6c\x1f\xdc\x97\x69\x1e\x56\xb7\xe0\xeb\x5d\x70\xef\xf1\x16\xf4\xed\xb7\x06\xb6\x99\xcb\xef\x06\x45\x20\x01\x12\x1e\x2c\xdb\xee\x58\x42\xc1\x7e\xb1\x8b\xf6\x76\x6a\x16\x5b\x16\x7d\xea\xb0\xc2\x03\x23\x86\xbb\xa7\x60\x84\x41\x13\xdb\x64\x2b\x6f\xed\xe8\x4d\x4b\x9f\x68\xf2\xd8\xa6\x7a\xa4\xa4\xec\x51\x48\x61\xb5\xe2\x8a\x24\xbc\x1e\x25\xcf\x41\x93\xe3\x40\x93\xbd\xe4\x16\x7b\xf5\x9d\xc4\xf8\x35\x69\xe1\x9c\x41\xac\x79\xdd\x72\x52\x30\x15\xf8\x09\xb0\xb5\x78\x64\x25\x09\x04\xfa\x81\x22\x1b\xf0\xa4\x6f\x1e\x3c\x89\x95\x06\x69\xdb\x3e\xdd\xd8\x4d\xf7\x64\x9e\x6c\xbe\x6a\xea\x59\x8d\xe7\xdd\x78\x4e\x0a\x4a\x33\x87\xc0\x28\xda\x85\xf6\x5e\x61\x0e\xd9\x36\xbd\xaf\xed\x62\x47\xbc\x08\x23\x8f\xd4\xfd\x14\x9c\xfa\xe4\x84\x16\xf8\x29\x8c\x1e\x1b\x01\x3f\xad\xba\xea\xad\xcf\x69\xbe\x0a\xb9\xb9\xb7\xb9\x66\x5a\xa5\x41\xc8\x1b\x4d\xae\x58\x4c\xc7\x5b\xd6\xb4\xea\x89\xaa\xee\x6c\x99\x46\xfe\xbe\x88\x5d\xf6\xc5\xa8\xd8\xf8\x8f\x8e\x0f\xe9\xbe\x3c\xdc\x91\xfa\x1f\xde\x17\xcd\x59\x18\xc7\x9b\x92\xe2\x2c\xf9\xbb\x92\x00\x82\xd3\x40\xbf\x59\x7e\x5a\xe2\xbb\x64\xb7\x83\x66\xa3\xee\xfa\xfe\x0f\x83\x86\x0f\x28\x29\x19\x3e\xe7\xfc\xb5\xaf\x4c\xbb\x14\xd6\xa0\x2d\x68\xff\x58\xe7\x19\xe6\x91\xeb\x2f\x5d\xb3\x19\x2e\x7e\x1d\x5e\xbf\xc3\xf7\x77\xfb\xe2\x4e\x30\xbb\x05\xee\x81\x2d\x47\x5b\xe0\xed\xe7\xbc\x32\x65\xd4\xa7\x18\x9f\x21\xc0\xed\xe4\x5b\x40\x21\x78\x55\xc7\x67\x85\xd9\x3e\x77\x55\x8c\x6a\x0a\x9b\x56\x9d\x18\x44\x48\xb6\x74\x8a\xf7\x53\x06\x19\x2c\x39\x45\xf9\x11\xd7\xbc\xa2\x39\x8c\xfc\x2d\x52\xae\x95\x4d\xaf\x36\xc8\x31\x65\x14\x4a\x49\xb6\x90\x71\x45\x92\x41\xfc\x4c\x04\x0b\x4f\x61\xca\x20\x71\x25\x36\x68\x94\xe2\x03\xbc\x43\x52\x3c\x4e\x2a\xe6\x12\xa2\xe2\x8f\x93\x54\x1e\xf1\x7b\xfd\x20\x3b\xfe\x34\x06\x43\x2c\xb6\xe0\x0a\x8d\xc6\x56\xc9\xb9\x5e\x06\x81\x6d\x80\xfd\x60\xcd\x35\xd7\x4c\x5e\xb6\xaf\x79\x2b\x7a\xff\xad\x67\x6f\x5e\xbc\x6a\x4e\xf2\x8a\xa5\x8b\x47\x0f\x58\xcb\xb7\x64\xbe\xaf\x58\x8b\x0e\xbf\xf2\x0f\x34\xf3\xcf\x75\x90\x8b\x3d\x0c\x9d\xff\xf1\xfc\x1b\x45\x99\x71\xb4\xae\xd8\xca\x7e\xc9\x35\x81\x20\x78\x47\xdf\x9f\x20\xad\x10\xc5\xfb\x63\x8f\x6a\x32\xde\x96\x02\xba\x2d\x16\xca\x62\x00\xdb\xf0\x5e\x24\x83\x84\x04\x00\x88\x24\xbc\x14\xa4\x9b\xe3\xd1\x0b\x7e\x0c\xb7\x68\x4b\x47\x67\xd7\xcd\x09\x4a\x49\x36\x88\x37\x27\x80\x9f\x89\x40\xf0\x94\xcd\x09\x90\xcd\x09\xe8\x9b\x43\x4a\x46\x1d\xd8\x23\x61\x82\xb2\x92\xb0\xcb\xd8\x79\xa2\xb3\x71\x01\x61\xa5\x57\x1d\xc4\x3f\x76\x62\xb4\xa7\x99\x3d\x7a\x6d\x29\xde\xa8\xfc\x7d\x32\xb0\x1d\x29\x34\x9d\x38\xe8\x02\xf5\xf5\xf5\xe8\xc7\x96\xfb\xc7\xcc\x98\x77\xe9\xca\x91\x97\xfc\xa6\x57\xcf\x26\xae\x09\x8d\xf3\xa3\xcc\xa1\x8f\xd1\xe6\x67\x22\xd0\xd9\xb7\x79\xef\xe2\xc5\x4b\xdd\xa8\x3f\xd9\xa3\xce\x76\x6e\x2a\xbf\x1b\xf4\x02\xd7\x83\x44\x4f\x8c\x53\xcb\x75\xf2\x3b\x5a\x6e\x5a\x43\x44\x25\xe4\x4c\x27\x95\x10\xd0\x0b\xae\x43\xb4\xb4\xd0\xef\x4c\x13\x37\x3f\xa4\xd0\x76\x6d\x51\xd6\xd8\x9e\x24\xac\x91\xe2\xbc\x45\xc5\xe5\x58\x29\xf8\x65\xad\xaa\x07\x56\xb4\xe5\x3d\x65\x45\xed\x41\x66\x34\x00\x49\xf1\x57\x91\xea\x48\x57\x9f\xbe\x8d\x24\x6a\x43\xca\xf6\x7c\x7c\x65\x83\x31\xe0\xc0\x01\x05\x07\xa3\xd7\x4d\xca\xa6\x50\x59\x65\xc5\xeb\x47\xd6\x2d\xea\x7f\xc1\x19\xbf\x99\xc6\xa1\x7f\x78\xe7\x1f\x5c\xf7\xe2\x57\xd3\x5e\x49\x3e\x74\x45\xbc\x69\xfc\xf8\xc4\xf2\xb7\x3b\xc1\xee\xbf\xc3\xc9\xa9\xff\x3c\xaf\x66\xe8\x84\x21\x67\x5e\x38\x77\xb2\x4f\x3a\xab\xdf\xe0\x3b\xde\xbb\xfe\x83\xa7\x6e\xdb\x7e\x47\xbc\xf7\x19\x17\xf4\x1b\x78\x4e\x55\x23\x42\x93\xdf\xa5\x36\x6b\x07\x72\xb3\x3f\x71\xcd\x20\x02\xae\x01\x09\x2f\x21\x82\x35\xa5\xd5\xea\xa8\x56\x6e\xca\x36\xaf\xe0\x55\xbb\xf0\xaa\x53\x0e\xda\xd0\xa4\x33\xc2\xe2\x85\xd7\xe0\x85\xbb\x48\x7c\x83\x4c\x68\x6f\x61\x25\xbc\xe6\x6a\x7d\xd1\x95\x55\x64\xd1\xd5\xb2\xa2\x56\xc5\x55\x9b\x9c\x02\xb2\xcb\x5f\x49\x16\x2d\xf4\x51\x1a\x07\xb2\xd9\x45\x0b\x7a\x3b\x44\xfe\x9a\x29\x74\x1d\xb2\xef\xeb\x73\x6e\x9e\xd8\x70\xd1\xe0\xb1\xb3\x1c\x27\x82\xe8\xeb\xd7\x0e\x4d\xde\xf9\xe6\x6d\xb3\xfa\xcd\xfc\xcd\x43\xaf\x26\x3e\xda\xf3\xfd\xd4\x16\x68\x99\x14\xec\x33\x74\xca\xd0\xf3\x26\xde\x7a\x59\xdf\x1e\xfd\xcf\x1d\xf9\xc9\xf7\xfb\x36\x2f\x78\xe3\xfe\x51\x8d\xa3\xae\x18\x3a\x61\xd2\xc4\xaf\xc6\x7d\x02\x74\xce\xab\x63\xfc\x6e\x10\x00\x45\x60\xa8\x5e\x2d\x1d\xc4\x6e\x1b\x43\x42\xae\x1a\x8f\x75\x27\x29\x8f\xc2\x36\x03\x68\x41\x2c\x98\x10\x83\x56\x5e\x4e\x31\x82\xab\xa0\x88\x96\x00\x27\xcc\x22\x75\xe9\xc3\x8d\x30\xaf\x0c\x38\xc7\xe6\x2f\x40\x01\x86\xd8\x86\x30\x73\xbf\x67\x40\x75\xaf\xbe\xd1\xa9\x4d\xe3\x6f\xe8\x31\x6c\xe5\xc5\x93\x47\x5f\x58\x5e\x5b\x35\xf2\x6c\x68\xaa\x3a\xf1\x2e\x33\x68\x7d\x82\x5d\x74\xc9\x05\xca\xe7\xd5\xa3\xa7\x4e\x1c\x57\xdd\xee\x1a\x30\xe9\xc4\x22\x15\x32\xcc\x70\xc0\x74\x6e\x04\x80\xe3\x48\xed\x6f\xde\x6f\xc5\x8e\x1c\xd4\x7f\xab\xe9\x7f\xcd\x6f\x75\x42\x97\x50\x11\x62\x9b\x2a\x18\x7b\x41\xbc\x2c\x52\x57\x35\x64\xea\xe8\x59\x15\xc3\x6e\xbe\x78\xc2\x19\x67\x57\xf6\x3a\xff\x6c\xf7\x77\x65\x99\xeb\xe1\x63\x0b\x9e\x63\x2e\xef\xdf\x47\xf9\xa0\xe4\xac\x41\xc3\x1b\x43\xef\x2b\xe3\x7d\x99\x87\xb7\x1e\x82\xd3\x48\x9c\x65\x41\x67\x3b\xbf\x9a\xec\x6b\x25\xf6\x90\x0b\x48\x77\x89\x2d\x4d\x23\x11\x36\x36\x9d\x92\xca\x0b\x78\x31\xa2\x49\x6c\xae\xbb\x44\x4c\xab\x41\x89\xd4\xfd\xbb\x25\xda\x55\x42\x78\x85\x79\x9b\x54\x20\x52\xf3\xaa\x9a\xb1\xe4\x14\xcb\x8a\xe6\x06\xf1\xb8\x2a\xc9\xaa\x48\xfc\x1d\x33\x5e\xa2\x1e\xb7\x08\xc0\xf2\x58\x29\xe9\x28\x29\x65\x63\x7d\x63\xf5\x34\x1c\x1a\x2e\x05\xf9\x51\xa4\x05\xb7\x7c\x04\x7b\xed\x80\xf6\xdd\x57\x5d\xf2\xd6\x54\xf4\xda\x02\xf3\xce\x4f\xef\xfe\xe3\x8d\x2a\xda\xf1\x01\xfa\x19\x7d\x06\x23\xcb\x6f\xd5\x3e\x5c\xb5\x6c\xf3\x1e\xf8\xf3\x13\x70\x15\xf4\xae\x98\x9d\xae\xaa\x41\xab\xb7\x5f\xbd\x7b\xe9\x2b\xe8\x9b\xfb\xa1\xfc\xc5\xec\xdb\xb7\xad\x9b\x7d\xdd\x66\xa3\x56\x84\x5b\x44\xfa\x68\x7e\xab\xf7\xd1\x74\x61\x89\x2e\xf6\x95\x73\x62\x44\x2b\xb6\x64\x57\x9a\x57\xf0\x1a\xd2\xfb\x67\xdc\x0e\x59\x49\x59\xb9\x00\x55\x0d\x21\xba\x52\x9f\x2c\x2b\x49\x07\x08\x90\x64\x77\xb1\xac\x06\xf5\x62\x73\x95\x33\x16\x4b\xc2\x47\xb9\x78\x47\xae\x31\xab\x51\x57\x16\x5c\xb8\xac\x7c\xe2\x93\xb0\xfc\xf9\xbb\x5f\x9f\x38\xf9\xee\x67\x67\x6d\x9c\x30\xeb\xca\x89\xcd\xc3\xcf\xa9\x9e\x70\x5e\xdd\x99\x37\x8e\x78\x78\x07\xfa\x26\x73\x10\x9d\x80\x1b\xf7\xc2\x0b\xb6\x85\x2b\x0e\xc5\x6f\xf9\x78\xf1\xd4\x39\x57\x8e\xeb\x73\x46\x51\xcf\xbf\x57\x54\x3d\xb3\xe6\xcf\x1d\x7f\xc7\x6b\x1c\x0a\x00\x5f\xc1\xb7\x80\x12\x8c\xbb\x7c\xd8\x5e\x78\x63\xb4\x15\xde\x14\x23\x29\x6f\x8d\x13\x62\x31\xcd\xcf\xa6\x35\x4f\x41\x7d\xbd\xde\xd3\x91\x0a\xd2\x14\x65\x50\xaf\x15\x72\x12\x7f\x42\x67\x1d\x53\x4d\x74\xd6\x88\x4d\x04\x05\x5c\x24\xdb\x2f\xbf\xb6\x63\x39\xc1\xb1\x3e\x29\xc9\xf9\x78\x5a\x20\x24\x78\x4d\xa4\x40\xc8\x64\x14\x08\xf1\xae\x08\x9b\xe4\x84\x6c\x65\x90\x26\x9b\x68\x95\xa2\x8d\xd6\x85\xf9\x7d\xb2\x92\xb4\x01\x47\x91\xa1\x4b\x75\xce\x03\x12\x2a\x0d\xd3\x36\x36\xc2\x7b\xe0\x71\xfb\xc2\x95\x43\xf7\xb5\x2e\x1d\x01\xeb\x46\x8c\x79\x78\x6b\xb9\xe7\x9b\xaa\xc6\xd8\xec\x14\xda\xdb\x32\xfd\x41\xee\x73\x07\x73\x62\xcb\x0b\x70\x3c\xda\xfc\xbb\x5b\x06\x4d\xf6\x0f\xad\xec\xd1\xf3\xc4\x26\x76\xf2\xaa\x22\xa5\x27\xdd\x13\x6e\xa3\xc9\x0d\x3c\x60\x0d\xad\x8c\x55\x6d\xf9\x7b\xe1\x10\xd2\x9a\x55\xac\xaf\x37\xf2\x0e\x74\xce\x8a\x4c\x77\x44\xa6\xc9\x73\x9b\x48\xd8\xd9\xf4\xd4\x43\xb6\x94\x71\x63\xc7\xc7\x64\x0f\xec\x52\x92\xb3\xeb\x7c\x6b\x82\xcd\x44\x82\x2f\x78\x0f\xec\x52\x52\xb4\xeb\x7b\x60\x15\xb3\xd5\x51\x0e\xbb\xac\x90\xb1\x38\xb9\x25\x93\xa8\x8c\x8b\xaa\xd3\x70\xe5\xd0\x57\x9e\x9e\x3b\x19\xd6\x4c\x86\xe3\xea\xd0\x96\x57\xd0\xfe\x57\xc6\x0d\x3a\xcb\xbc\xdf\xca\x86\x1f\xda\x08\x5b\xd0\x88\x43\x27\x96\xb2\xf3\x07\xc6\x7d\x05\x85\x34\xd6\xdd\xd9\x4e\x62\xdd\x61\xf0\xdb\x1c\x46\x28\xc2\xf2\x5d\x60\x4a\xab\x40\xd2\x02\x7c\x3a\x3f\xf6\x4d\x52\x2b\x5d\x82\xde\xa5\xb9\xa0\x77\x45\x2e\xe8\xad\x79\x4b\x49\x87\x18\xd0\x4c\x01\x6c\x1d\xcc\x0e\xd9\x5b\x5a\xf6\xeb\xa2\xdb\xd9\xc0\x45\x7e\x50\xdb\x5f\xa9\x07\xb5\x6b\x22\x83\x26\x3d\xfa\xf8\x49\xb1\xec\x85\x97\xea\xb1\x6c\xe9\xa3\x82\x07\x56\xe9\x31\xec\x22\xd2\x6b\x48\x7b\x56\x17\xe9\x75\xcd\x15\x96\x34\x6d\x2c\x91\x81\xde\x62\xa5\xf5\xb2\xa4\xd5\x40\xd4\xe8\x5a\xd5\xcb\x9b\x0b\x61\x44\xf3\x89\xa4\x14\xbc\x5a\x07\x3e\x75\x30\x42\x7b\x43\x4a\xe3\x6a\xa1\x9c\x72\xb8\x03\x25\x64\x41\x3e\x65\x1b\xef\xb1\xfb\x2b\x7a\x11\xf4\x6b\x0f\x60\xcd\x55\x1a\x27\x9d\x97\x8e\xb8\xda\x8b\x56\xfe\xf9\xfa\x04\x60\xdf\x6c\xba\xbd\x2a\x6c\x32\x22\x97\x02\xe9\x63\xaa\xaa\x85\x30\x8f\x26\x9d\x61\x8b\xae\x7d\xfa\x87\x97\x5b\xdb\x97\xa3\xce\xcd\x1b\x6e\x34\x0b\xe3\x2f\x7d\x66\x65\x15\x3a\xe2\xe8\x37\x23\xf5\x00\x3c\xbf\x64\x41\x7c\xcc\xed\xa3\xc6\x9c\xbb\xe0\xc9\x46\xe6\x39\x88\x60\xbf\x35\x47\x3f\x3c\x80\x5e\x7f\x7a\x7c\xa8\x6a\xc0\x50\xb9\xe8\xca\x4b\x07\xd7\xfb\x14\xbf\x5f\x29\xde\x06\x0f\x47\xce\xb8\xf1\xeb\x79\x33\x67\xa0\xef\xd0\x37\xba\x1e\xd3\xf9\xee\x07\x74\xc3\x76\x9f\xad\xd6\x77\x92\x38\x4e\x8e\xc3\xde\x2a\x27\x80\xe0\xce\x1b\x62\x73\x7a\xe6\xfa\xd3\xd1\xd5\x77\xc3\x52\x0f\x18\xf4\x33\x72\x33\xab\x4d\x6e\x60\x03\x5e\xd0\x0c\x68\xcf\x9b\x29\xa6\x5a\xa2\x1a\x43\x3c\x1a\xcd\xc9\xa5\x49\x07\x1c\x4f\x0b\x52\xec\x18\xcf\x2b\x12\x69\x77\xd3\x4b\xf2\x77\x50\x47\x99\x30\x1b\x51\x96\x23\x40\xf8\x8d\xa0\xc1\x72\x04\x35\x13\xbe\x34\x4e\x0f\xa1\xa0\xb1\xd0\x4c\x2f\x4f\xe3\x51\x3c\x86\x1b\xae\x10\x64\x42\x65\x55\x79\x9c\xe8\xe8\xe7\x01\x0d\xcb\xca\x33\xb0\x16\xfd\xf3\x02\xb4\xfd\xaa\x61\xcc\x48\x9d\x88\xfe\xa0\x67\x0b\xb7\xe5\x78\x35\x5a\xe5\x17\x1a\xb3\xf4\xf3\x3a\xc7\x21\xe5\x08\xf3\x82\x62\x30\xe1\x64\x96\xb0\x42\x36\x9d\xf2\x79\x08\xc7\x21\x09\x97\x95\xe4\x13\x86\x15\xe8\x84\x61\xa5\x30\xa2\x15\x38\x48\xf1\x93\xdb\x57\x48\x53\x27\x32\x6d\x87\x2b\xf4\x19\x31\xfb\x6e\xa8\xc3\x48\x37\x5c\x23\xb5\x79\xa7\xb0\x87\x35\x2c\x9d\xbf\xf8\x8f\x7d\x32\x0b\xb8\x46\x66\x3e\x73\xfb\x4d\x37\xbd\xd7\x3d\x87\xd8\xbb\xa9\x42\x58\x1c\x5b\xf1\xe8\xf3\x79\x32\x52\x08\x2e\xd4\xbb\x62\xdd\xf9\xb6\x4e\x94\x02\x78\x1d\xa2\x3d\xeb\x49\x29\xb4\xc2\x09\x68\x6e\xbd\xf6\x55\x92\x35\xe0\x8b\xc7\x35\xab\x48\x7e\x36\xb6\x65\x27\x0b\x8d\x49\x08\x09\x21\x21\x6f\xfe\xd1\xc4\x07\xa0\xf5\x0f\x54\x6e\x26\xad\x28\x83\xd7\x44\xd0\x43\xcc\x73\x44\x78\xde\xf9\x18\x2e\xfb\x13\x9c\x98\xc2\xc2\xd3\x7c\xfd\xee\x02\xdf\x6b\x58\x7a\x3e\x26\x76\xb9\x44\x9f\x6d\x50\x84\x7f\x6b\xa1\x31\xd9\xc0\x43\xfa\x5b\x2d\xe9\x94\xc5\x5c\xe8\x11\x23\x9a\xc5\x4e\xe3\x05\x36\x12\x67\xa6\xc8\x89\x2b\xa4\xa3\x0b\xcc\xb2\x0a\xe3\x9a\xd3\xa2\xcf\xf8\xc5\x0e\x88\x2b\xde\xbb\xae\xb1\x81\xce\x99\x0b\x35\x86\x1a\x75\x7b\x5b\x95\xbb\xc0\x25\x7d\x6e\xba\xf0\xba\x95\x21\xb4\x32\x02\x2f\x67\x2e\xb9\x28\x3e\x25\x3e\x7a\xd3\x0b\x3b\x3f\x5a\x83\xda\x5f\x7d\x30\x7c\xc2\x5f\x35\x77\xc1\x6e\x97\x7b\xd2\x65\xa5\xc1\xcf\xc6\xfc\xed\xa3\x03\x68\xc7\x1f\x0c\xae\xb3\xcd\x84\xb7\xd1\x8d\xad\x09\xd1\xb6\xf6\xac\xc7\x8a\x6d\x24\x76\xc5\x30\x70\x62\xdd\xe4\x25\x61\x16\xf5\x90\xb4\xbf\x70\x2a\x1d\x7a\x6e\xb8\x98\x9d\xa3\xc3\xc5\x08\x3b\x7c\x3e\x97\x63\x52\x24\x4f\x37\x7e\xb2\xcf\x03\xc8\xb0\x36\xbb\xe8\xee\x42\x36\xe5\x16\x75\xc9\x8a\xc1\x90\x10\xeb\x4a\x84\x46\x79\xd0\xea\xeb\xc7\x76\xfc\x8c\x9e\x41\x1f\x2f\x1d\x38\x77\xe6\xca\x27\x76\x2e\xe0\x5b\x0e\x1d\x38\xf0\x23\xfa\x01\x7d\xca\x84\x97\xce\x4d\x91\x1e\x92\x97\x91\x9b\xbb\x8a\xd8\xc9\x30\xd8\xa1\x57\xf5\xe7\x7a\xe3\x61\x54\x65\xb2\x59\x79\x8f\x48\x7a\xe2\xf3\xfc\xee\x22\x6c\x25\xf3\x52\xf1\xfa\x9d\xee\x12\x99\x60\x3d\x64\x25\xe4\x59\x86\x9f\x09\xb7\x27\xdf\xc1\x2c\xd3\x9b\xd5\xdc\x65\xb4\x59\x8d\xfc\x4b\xfd\x4c\x0f\x4d\xc3\x32\x72\x8a\x37\x39\xbd\x7e\xac\xb3\x8b\x14\xcd\x5c\x4a\x38\x87\x9c\xf4\x43\x28\x27\xcc\xb6\x52\x3a\x2c\x0f\x86\x58\x93\xd1\x18\x4b\x9a\x4b\xc2\x26\x81\x75\xb9\x73\xbe\xa6\x03\x0e\x85\x49\x58\x33\xa4\x28\x66\xbe\xe3\xc1\x75\x4f\x2c\xff\xcb\xb2\xc4\x14\xb3\xbd\x64\xf8\x4b\x67\x0f\x3f\x77\xc1\xb0\xf3\x87\x9c\x7b\xe3\x79\xc8\x6d\x06\x68\xcf\x1d\xf7\x6f\x39\xb0\xf3\x6d\x74\xdf\xcb\x8f\xff\xfe\x6e\xb4\x95\x5d\x30\x7a\xea\x8a\xf4\x2d\xe3\xc7\xdf\xfe\x1d\x91\x5d\xac\x33\x1a\x49\x3c\xfd\x1c\x5d\x17\x2b\x86\xbe\xb0\xb1\xe9\xa4\xd9\xc7\x99\x23\x86\x46\x76\x4a\xba\x46\x56\x74\x8d\x6c\x96\x13\xc0\x89\x35\xb2\xc6\xd9\xf2\x75\x43\xbd\x57\xbf\x5f\xba\x2b\x25\x9b\xc2\x65\x60\xc1\x07\x70\xf2\x5f\x16\xbe\x7e\xcd\x8d\xb3\x96\x0f\xbd\x73\xff\x6d\xcb\xd6\xad\x6d\x7d\xfb\x5d\x84\xbe\x66\xaa\xa1\x09\xbe\x78\xa8\xe6\xcc\x63\xfd\x2b\x37\xa2\x37\x52\x4f\x6d\xbc\x00\x9d\xb8\x00\x46\xc0\x49\xbc\x99\x28\xcb\x9b\xe9\xfa\x37\x78\x33\xbb\x72\x14\x93\xa0\xba\xd4\xba\xfd\xf5\xc9\x87\xdf\xa1\x6c\x91\x4c\xad\x43\x65\x5b\x35\xa7\x70\x54\x75\x90\xc1\x4f\xdf\x76\xc7\xa6\x39\xb7\x43\xe8\xc2\xa6\xa9\xba\xa4\xa4\xec\x92\x5c\x91\xa4\xe2\x22\x83\xa0\x5c\x79\x83\xa0\x54\x25\x9e\xb0\x98\x6d\xb2\x12\x07\xcf\xb3\x16\x9b\xc3\x29\xd1\x31\x00\x74\xb4\xa4\x0d\xea\x84\x9b\x79\xef\xe6\xf3\x6e\x6a\x9c\x98\xc7\xba\x49\x7b\x06\xc5\xf8\xc9\xec\x9b\x61\x36\x6c\x62\x08\x4d\xe5\xcc\x9d\x26\x78\x08\xde\x8b\x76\xa3\x6f\x56\x14\x5c\x66\x46\xa5\x3f\xbc\x6a\x2e\xa9\xbb\x9f\x6f\xc9\x0c\x63\xb6\x1f\x1b\xc1\x3c\x7c\x13\x5c\x9c\x99\xc0\x6c\xd9\x81\xbe\xc8\x0c\xd7\xe7\x70\x22\xb7\xa9\x8e\xf4\x2e\xae\xc9\x71\x31\x91\x98\x0c\x4f\x7a\x3a\xed\x39\xf6\x56\x5a\x69\x2f\xe8\xb0\xd1\x91\xa5\xf3\x7b\x27\x7f\x4f\xed\x78\xaf\x30\x98\x6c\x33\x18\x19\xcd\xad\x3c\x25\x5d\x62\x81\x66\xb6\x11\x76\x08\x1e\xff\xab\x13\x6f\x1a\xd3\xfe\x54\x93\x4c\x06\x92\x40\x41\x7f\x83\x08\xbe\x8b\x70\xfb\xc2\x30\x0b\x87\xc1\xf1\x70\xe5\x43\x70\x1c\xdc\xf4\x77\xf4\xe9\x0b\xe8\xe1\x03\x4f\xa2\xcf\x91\xdb\x34\x02\x8d\x84\xa9\xe3\x1b\xd9\x26\x54\x05\xbf\x39\xf6\x14\xb9\xfb\x97\xeb\xfd\x63\x05\xa0\x02\xbc\xab\x57\x81\x07\x2d\x69\x52\x96\xa3\x95\x59\xf4\xae\x13\x15\x44\x35\x4f\x41\x2c\xa6\x41\x7b\x5a\x63\x14\xec\x3f\x54\x46\xd5\x12\xc2\xe6\x98\xad\xa2\x37\x1a\xec\x7c\x44\x34\x78\xcd\x5b\x78\xd4\xa1\x56\xd0\x56\x02\xc6\xc7\x52\x4f\x41\xf1\x56\x10\x4f\xa1\xc2\xf0\x14\x58\x57\x64\xfb\xc0\x3b\x3b\x46\x18\xbc\x6a\x7e\xfc\x51\xc2\xef\xad\xc8\x6f\xb6\x63\xfd\x15\x74\xbe\x28\xc3\x2a\x1e\xaf\xaf\x80\xfc\x99\x5f\x6c\x13\xf4\xd1\x38\x4e\x19\xcd\x1a\xb2\x8d\xb1\x2e\x1d\x66\xd4\x60\x85\x1a\x61\x7e\x9b\xd9\x86\xea\xe6\x8d\x79\x8d\x66\x52\x09\xbc\xb0\x1a\x25\xfc\xe8\x80\x1f\xbe\x99\xd7\x71\xb6\xec\x6d\x06\xe5\x5a\xce\x6e\x7b\xf0\xed\xb9\x73\x99\xe7\xf2\x7a\xce\x60\x67\xba\xb3\x9d\x7b\x92\xe8\x02\x03\x97\x71\x6c\x9a\x4c\x4c\xd1\x6c\x36\x8a\xcb\xcc\x6d\x9a\xcb\xd0\x02\x9c\x2f\x37\x1b\x49\x74\xe9\x8d\xfe\x8e\xec\xb4\x1d\x03\x5b\xcb\x7d\x0d\xac\x50\x56\xe9\x9b\x37\x6c\xdd\xe4\xa5\x1f\xde\xba\x6c\xdd\xea\x9d\xef\xbe\x05\x01\xf4\xef\x41\x8f\x1d\x5c\xf4\xd6\xd8\x63\x3d\xfa\x6d\x82\xfd\x13\x4f\x3d\x7e\x21\xe4\x2e\x44\xfb\xd1\x77\xa8\x13\x0d\xfd\x3a\x0a\xb2\x3e\x3e\xd5\x51\x15\x18\x9f\x9d\xa2\xa5\xf4\xf9\x48\xa9\x30\x19\x9a\x62\xe8\xac\x4a\x43\x67\xa9\x4e\x7d\x88\x31\x1d\x9f\x52\x05\x23\x5a\xc0\x69\xcc\x4a\x4a\xd8\x14\x9a\xed\x0f\x2b\xd8\xa7\x71\xc7\xe3\x9a\xd9\x47\x5c\xbc\x5f\xa3\xd3\xf2\xd0\x5a\xe5\x69\xf5\xdb\x19\xd9\xe9\x2c\xa7\xd1\x74\xf0\x49\x63\x6a\x0b\x93\x77\x06\x15\x60\x6e\x37\xa7\x80\xd7\x2a\x65\xd7\x4a\x56\x19\x68\xd3\x97\xa6\x96\x52\xf5\x87\x4f\x08\xaf\xb2\x34\x20\x2b\x09\x9b\x0f\xaf\x0f\x23\x0c\x29\x9e\x3b\xb3\x30\x99\x95\x54\x64\xcc\x4a\xc2\xc7\xf7\xcb\xa7\x97\x3f\x72\xe6\x74\x27\xb9\xdd\x58\xec\xe9\x8e\x94\xd9\x98\x1b\x51\xa3\xe3\x91\x0d\x42\x33\xb0\x01\xf7\x2f\xb3\xae\x77\x33\x96\xe6\x7f\x9e\x75\x1d\x36\x84\xe8\x00\xf5\x53\xe9\xd7\xd1\xcd\xb0\xb1\x7c\xd4\x0b\xe7\x2e\xcd\xf1\xb0\x0b\x4d\x9e\xfb\xd6\xfb\xcf\x79\xda\x98\x19\xb0\x21\xcb\xdb\xb7\xee\x5f\xff\xfa\x7f\x87\xca\xef\x7f\x62\x71\x5a\xd0\x2b\x2b\x29\x56\xb0\xda\x4c\x18\xbc\x9f\xb4\xd4\x6e\xca\x23\xbb\x59\xf5\xdc\x93\x8b\x23\x8d\xc5\x9f\xc4\xec\x47\xf8\x60\x3b\xdb\xf9\x59\x7c\x0b\x28\x05\xf7\xeb\x8c\x4c\xc5\x7a\x7f\xb3\xdb\xd8\x07\x42\x0c\x5b\x5a\x5f\x9f\xe2\x8b\x9c\xd9\xa3\x0c\x11\xb5\x5b\xec\x4c\xab\xc5\x92\xe6\x3f\x89\xf3\x54\xe7\xb4\x56\x4b\x24\xb5\xb4\x55\x2d\xa6\x35\x21\xc5\x78\xd1\x45\xc5\xa4\x26\x84\xe3\x8b\x4a\x8d\x05\xfb\x8b\x65\x25\xe1\x94\x89\x63\x68\x91\x75\x6e\x18\x92\xfc\x57\xe2\x06\xb5\x2c\x15\x5b\xc6\x01\x05\x5a\xb1\x36\x90\xa9\xa2\x91\x19\xb8\xb9\x91\xab\x68\x44\x57\xc7\x3b\x12\x6f\x99\xfa\x4c\x7f\x6c\xf9\xdc\x0b\x47\x0f\x3d\x6f\x64\x85\x95\x19\x34\x2c\x7d\x0f\xda\x0b\x01\x25\xa2\x45\xdf\x3f\xb7\xa1\x6a\x08\x4a\x3f\x36\x92\xa9\x44\x55\x23\x9f\x1e\x66\x1b\xd0\x37\xd3\x44\xc8\x69\xa9\x0c\x3f\x28\x34\x03\x1e\x38\xba\x9f\x9c\xe0\xcc\x4e\x4e\x90\xfe\x9d\xc9\x09\xd9\xc9\x7c\xb9\x11\x0a\x68\xd4\x6a\x38\xaa\xf6\xe3\x71\x64\x94\x82\x29\xe2\x1f\xff\x91\xdc\xef\xb5\x81\x79\x38\xae\x10\x0c\xd7\xfd\x25\x4f\xbe\x86\x74\xc8\xc4\x5f\x72\x60\x48\x17\x20\xea\x91\x7a\x4d\x2e\x49\xf7\x9a\x64\x0f\x56\x7f\xbe\xd3\x43\x39\xea\x2a\x49\xa1\x7c\x34\x77\xf3\x7b\x57\xdd\x38\xfc\xa1\x4b\xd6\x7e\x1a\x67\x3c\x0d\x99\x1f\x18\x58\xb2\xb6\xf5\xa5\x03\x39\x4c\x57\xd7\xef\x58\x75\xbf\x57\xb7\xa2\xe2\x12\xb4\x3b\x0b\xea\x20\xa8\xee\x6c\xe7\xc6\xf1\xbb\x41\x18\x4c\xd3\xab\xed\x59\x36\x4d\x27\xc8\x78\x59\x1a\xdd\x11\xdb\x48\x51\x80\x9f\x0c\x60\xd7\x4a\x24\x82\xcb\x35\xbf\x28\x2b\x09\x2b\x5b\x86\x11\x67\x89\x49\x56\x12\xb2\xb7\x90\x28\x6f\xb6\x8c\xaa\x35\xaf\x9c\x84\xa2\xbb\x04\xa3\x6b\xbd\x3e\xbe\x51\xa6\xc1\xca\x5a\x58\x55\x0b\x1b\xba\x4c\xbd\xa5\xb1\x0f\x2e\x5c\x56\xfd\xda\x13\xd7\xde\x1a\xac\xbf\x6c\xf9\xb5\xb7\x1c\xba\xff\x93\xd4\x9c\x0d\x77\x5e\x3c\x6b\x48\xf3\xfc\x9b\xd0\xc7\x99\xcf\x86\x41\xe5\xea\xdf\x8c\x88\x0c\xee\x37\xe2\xb2\xd7\xaf\x5d\xbc\xfb\xba\xcb\xd2\x23\x26\x8e\x18\x30\xe9\xfc\xd1\xaf\x2d\xde\xf7\xe3\xff\x51\x0e\xfe\xff\xdb\x79\x43\x21\xda\x81\xc6\x30\x09\xbe\x05\x88\x60\x02\xa0\x35\xe9\x42\x4c\xb5\x45\x35\x06\x83\x11\x07\x21\x99\xc6\x2e\xa9\x33\x5b\x49\xb6\x8d\x2e\x84\x20\x4f\x0a\x43\x4f\xe5\x77\x66\xf4\x7e\x14\x53\x2e\xf6\xd2\xb7\x11\x86\x20\xa9\xe3\x40\x3b\xc6\x8f\xbc\x6c\x41\x21\xac\x80\x75\x68\x5f\x9f\x7f\x7e\xde\x34\x65\x9d\x7b\xfe\x1d\xfc\xe5\xc7\xae\xfb\xc7\x17\x41\x82\x33\x77\x76\xb6\x0b\x83\xf8\x16\x32\xf9\xa7\x93\xb2\xcf\x6a\xc0\x45\x99\x7e\x55\x58\x4f\xaf\x1e\xab\x53\xbf\xab\x56\xd2\x97\xab\xba\xeb\x53\xb6\xf2\x80\x85\x3a\xd6\xa4\x07\xb1\xb4\xcd\x98\x5f\x45\x26\xd1\xfe\xf0\x1d\xe9\x2a\x54\x2d\xb5\x0e\x55\x68\xe5\x35\x8f\xfb\xa8\x83\x14\x5b\xac\xef\x78\x81\xfa\x29\xae\x5a\xd5\x4a\x06\xd1\x16\x72\x47\x55\xab\xa4\xb9\xb9\xa3\xdb\x07\xa4\xbe\x83\x04\x6e\x0a\x52\xd2\x2c\x58\x5c\x11\x5e\x2d\x94\x92\xb6\x42\xab\x2b\xb2\x7d\xc0\xf5\x87\xfd\xe4\x33\x9f\x94\xf4\xfa\x3c\xfa\x67\xe5\xf8\xb3\x84\x59\xb0\xe4\x40\x69\xc2\xeb\xf3\x10\x82\x5f\xc1\xec\xf5\x51\x17\xc5\x6e\xb1\xda\x5c\x6e\x4f\x61\xb9\xf1\x56\x57\x8c\x5a\x5e\x28\xeb\x53\x15\x89\x2a\x85\x81\x6c\xc8\x1b\x54\x43\x57\xd8\x8a\x91\x6a\x96\xc3\x6d\x40\x43\x74\xf0\xd8\xd1\x33\x17\x9f\xcb\x8e\x9c\x37\xf4\xdb\x13\xe8\x0d\xd4\x86\x46\x20\x34\x6a\xd3\xbd\xdb\xd6\x8d\xe6\x96\xce\x5b\xbc\xec\xd2\x69\x73\x38\xe4\x1e\xb4\x12\x56\xc1\x56\xe8\xcd\xec\x7d\xff\xb5\x1f\x51\x86\x4b\xa1\xd6\x0c\x42\xdf\xcd\x85\xca\xfc\xb9\x23\x2e\xca\x62\x05\xc1\xc7\xb7\x00\x05\x04\xc0\x27\x14\xe3\x27\x80\x53\x89\xc5\x08\x47\x7b\xd7\x29\x25\xb2\x03\x9b\x1a\x29\x10\x23\x73\x4a\x74\x62\x72\xda\x67\xac\x38\x49\xad\x70\xde\xa4\x12\x12\x16\xa7\x89\x02\x1f\x24\xd3\x99\xb2\x4d\xc5\x59\x6a\xe5\x7b\x3a\x6e\x27\x47\xc4\x93\x72\x2b\x93\xa4\xba\x5a\x55\x45\x4a\xb2\x0a\x43\xcb\xf4\x39\x27\x4f\xfd\x42\xc1\x65\xa2\xef\x48\xe4\x1d\x32\x2c\x98\xa1\x1f\x05\xf0\x47\xec\xf3\x2c\x27\x38\x25\xd9\x15\xe8\x12\x03\x91\x5d\x32\xe5\x2b\xd3\x47\x9b\xe4\x76\x34\xc4\x56\xe4\x47\x42\xe6\xc1\x35\xf3\x61\xdd\xbc\x71\x5f\x77\xa0\xb7\xd1\x9f\xd0\x59\xcb\xd0\x9c\xe5\xcc\xb1\x45\x0b\x97\xb4\xce\xe1\x5b\x32\x7b\x99\xba\xcc\xde\xf7\x5e\xfd\x09\x1d\x63\x96\x66\xe6\xa3\xf9\xbf\xdd\xa8\xdb\x69\x00\xf8\xab\xf8\x16\xe0\x03\xaf\x02\x42\x68\x94\xb0\x8b\x9e\xac\x1f\x4d\x4c\xb4\x0f\x9b\x68\xb7\x37\x6b\xa2\x0b\xa2\xaa\x37\xcb\x1e\xa8\x53\x7e\xa9\x16\x89\x86\x3f\x09\x93\x60\x94\xcc\x3e\x62\xea\xb1\x01\xef\x62\xb8\x49\xa9\x90\xea\xc1\x66\x6d\xfb\x20\xdf\x3f\x06\xd3\x7b\x29\x4a\xaa\xa3\x95\x7a\x8b\xbc\xea\x91\x92\xbc\x87\x23\xe1\x14\x8e\x76\x61\x3b\x6a\x6b\xe1\x36\x8e\xb7\x39\xdc\xbe\x1c\x9c\xb1\x4b\xa4\x2f\x0a\x68\x6e\xaf\x4e\xc6\x95\x67\xd1\x75\xc6\xb0\xae\x96\xfc\xe0\xce\x37\xbc\x63\xd1\xee\xcb\xad\x23\xce\xff\xa4\x8b\x05\x4f\x3d\x36\xf0\x5a\xd4\x04\x3f\xaa\x2f\x1e\xda\x98\x6f\xbb\xf9\x45\x42\x33\xe1\xfe\x9f\x67\x4c\xd5\xb1\x66\xe3\x0b\x5c\x2e\xbe\xa0\x13\xfe\x1b\x93\x4c\x3c\x27\x0b\x88\x51\x82\x60\x95\x92\xac\x95\x71\x45\x92\x16\xfc\x4c\x58\xac\xa7\x94\x20\x58\x48\x09\x82\x25\xab\xf0\xf1\x89\x13\xa6\x2a\xa8\xd3\xaa\x52\x93\x0f\xeb\xd7\x32\x45\x70\x7c\x66\x3b\xac\x42\xcf\xa1\xef\x1f\x84\xe3\xb3\xc6\x3f\x33\x96\xd9\x9a\xa9\xc9\x14\x31\x7b\x33\x75\x39\x14\xa0\xaf\xc7\xe4\x16\x9a\x81\x13\x14\x80\x83\x06\x22\xcd\xad\xc7\x8c\xd7\xe3\x37\x6a\x2c\xb0\xec\x5b\x75\x1a\xb4\xc0\x49\xc8\x04\x4a\x2a\x68\x25\x46\x81\x6f\xc5\x1e\xff\x6e\xf2\xae\x55\x52\xc5\x56\x1e\x4b\x81\xb9\x75\xfb\xc0\x85\x1d\xbd\xc8\x92\x79\x29\xc9\xf2\x58\xc6\xad\x52\xd2\x66\x15\x5d\x91\xa4\x1d\x3f\x13\x2c\x9f\xb7\xf6\x84\xcd\x2a\xe2\x2d\xb0\xc7\x41\x8a\xe5\x45\x9b\x9d\x06\x44\x5a\x00\xcb\x9b\x8d\xbf\xf2\xa9\x9d\x4c\xce\x38\x89\xf9\x4b\x0a\x21\xe1\xb4\x28\x49\xc1\xe1\xf6\x90\x88\x34\x09\x8a\x38\xf4\xbb\xc2\x08\x24\x2c\x12\x80\x8d\x55\xd0\x95\x87\xe5\xa1\xff\xde\xc1\x2e\x2b\x73\x02\x5e\x8f\x76\xa3\xf6\xa6\xcb\xc3\xe6\x0c\xf7\x75\x16\xcf\x67\x46\xa2\xaf\x87\x71\xee\x63\x23\xe0\x0e\xf8\xf1\x6a\xe6\xf8\x27\x59\x60\xcf\x80\x92\xce\x76\x7e\x89\xb0\x06\x78\x41\x0f\x70\x2d\xad\xfe\xd2\x58\x5b\x9a\x8c\xea\x53\x9d\x31\xb5\x32\x9a\x2a\x26\xe3\xee\x13\xc5\x95\xd6\x48\xf2\xac\xe2\x32\x4b\x84\xd8\xd9\xea\xa8\xea\x6b\x4b\x15\x92\x44\x54\xd2\x52\xe8\x33\x93\xa4\x8d\x6a\x8e\x12\x74\xdb\xd3\x18\x56\xc8\x7a\x08\x54\x25\xc5\xa9\xac\xc7\x88\x00\x6b\x90\x30\x97\x35\xd2\x7a\x92\x46\x18\x72\x79\x7d\xd4\x32\x31\x64\x36\x9b\x11\xa8\x0e\x11\x0a\x94\x92\x8b\xe6\xf6\x1e\x31\xa8\x0e\x7d\x09\x63\x0f\xfb\x4c\xb5\x1e\x38\x1e\x5e\x98\x79\xf2\xce\xb5\x5b\xe7\xdd\x72\x84\x87\x56\x66\xcb\x65\xb3\x7d\x50\x2a\xbb\xed\x8f\x0f\xbe\xd3\x66\x87\xb6\xaa\xb2\xc1\x17\x71\x4a\x66\xd9\x94\x33\x7e\x5b\xc5\xcc\x3f\x7e\xec\xe0\xc3\xe7\x09\x37\x16\xf8\x02\x9e\x15\xe3\xa7\x2f\xb9\x7f\xe4\x43\x34\xd6\x86\xc6\x91\xb9\x1d\x36\xf0\x90\x9e\x3b\x00\x42\xcc\x98\xf3\x94\xb0\xb1\x78\xad\x36\x8b\x25\x92\xaf\x69\x49\x49\x37\x96\x26\x7c\x3b\x0c\x62\xee\x9c\x4a\x3d\x79\xe2\x13\x15\x2b\x0a\x35\x30\xf4\xd0\x0c\x9d\x6a\xa4\x4d\xd8\x24\x60\x39\xc1\xb8\xfd\x16\x48\x94\xa2\xc6\x33\xb2\x3e\x68\xde\x18\xe7\x81\x75\x24\x3e\xe4\x3e\x9d\x00\xbe\x07\x01\xec\x8d\x76\xa1\xc5\x93\xd1\xbe\xc9\x7c\xcb\xf1\x91\x5c\xea\xd8\x08\x34\x0e\x6e\xf9\x2f\x31\x5b\x8e\xfa\x07\x8f\xe9\x31\xf7\x05\x7a\x06\x17\xc4\x34\xb1\x8b\xa3\xe8\xb6\xe7\xb9\xb9\xaa\xdc\x46\x8a\xc0\xbc\x5d\x83\xd1\x39\x87\x50\x0c\x52\x87\x30\x78\x54\x15\xa5\x24\x2f\x12\x45\x2a\x66\x1d\x42\x23\xbe\x9e\x8b\xae\x5b\xe2\x86\x2b\x48\xd3\xf5\xa1\xaa\x9c\x4d\x61\xfb\xf6\xcd\xfc\x3c\xf8\xec\xc3\xd8\x3a\x1f\x18\x75\xf9\x8a\xb5\xaf\x5d\x8d\x7d\xbe\x3d\xfb\xde\xf9\xb6\x13\xcd\x9d\xb5\xe5\xbf\xe7\xe3\xfd\xbf\x3b\x1f\xaf\x3f\x1a\xc7\x2f\x22\xb8\x57\x01\xcf\xe8\x39\x63\x07\x16\x16\xc1\x59\x5f\x5f\x9f\xb0\x3b\xf0\x45\xb4\x5b\x2c\x11\x0d\x88\xf5\xf5\x46\x75\x04\x61\x28\x94\xea\x49\x63\x2d\x68\x33\xda\xe5\x0d\xf5\xee\xce\x16\x5c\xee\xcb\xfb\x49\xa4\x6a\x3c\x77\x0f\x9d\xb5\xaa\xa9\x56\x75\x4a\x9a\xe0\x3c\x8a\xc1\x90\xe4\x3c\xca\x6e\x83\x26\xc1\xae\xb3\x61\x91\xdd\x17\xf5\x46\x79\xab\x9c\xe0\x1d\x72\xdc\x20\x5a\x05\xbd\xeb\x58\x57\xac\x2f\x70\x85\x60\x8c\xe0\x17\x18\x72\x85\x99\x37\xef\x59\xfc\x0c\x94\xe7\x33\xa8\x13\x6c\x5f\x83\xf6\x4d\x3e\xf1\xfd\x14\xd8\x17\x6e\xde\xf5\xce\x47\x68\x1c\xb3\xf5\x9f\xcc\x85\xf0\x9a\xe3\x23\x33\x63\xe1\x16\xfc\x27\x9b\xc8\x3c\x08\xfe\x3f\x30\x87\xef\x0e\x00\x84\x75\x7c\x0b\x90\xf1\x3d\x20\x3e\x97\xcd\xe1\xc4\x58\x0a\xdf\x83\x04\x6f\x32\x13\xbd\xa8\x90\x6e\x04\xbd\x04\xc7\x28\xbc\x70\x65\xab\x3a\x37\x19\x13\x3b\xde\x30\x3a\x36\x29\x82\x74\x48\x49\xc1\x61\x22\x04\x98\xf9\x38\x32\x21\x39\xf3\x5b\x38\xb9\x78\x42\x74\x90\x16\x4e\x21\x0e\x92\x9c\x20\x4a\xd4\x57\x33\x5e\x19\xae\x24\x06\x15\xae\x2c\xba\x08\xb9\xe0\x42\x66\x36\x4a\xc3\x28\xb4\xae\x85\x15\x6b\x19\x3f\x1c\x4e\xe0\xc5\x1b\xe8\xf0\x83\xe8\x4f\x0f\x64\x0e\xb0\x76\x66\x0b\x01\x17\x79\x00\x83\xd9\x93\x89\x65\xfd\x76\x95\xf4\xd3\xcc\x04\x89\x0a\x62\x15\x2d\xe9\x84\x8f\xa1\xb4\x1a\x29\x9b\xb5\xc2\x27\xea\x63\xf4\x7b\x10\xef\xac\x4c\x4a\xd3\x69\x0d\x41\x9d\xa9\x18\xff\x64\x9d\x4a\x83\xad\xa0\x86\xcf\x2a\x6b\xb0\x8c\x90\x6c\x6b\x45\x25\xf1\xb8\x2a\xcb\x9a\x2b\x18\x8f\xab\x3e\x45\x75\xe7\xf9\xef\x84\x0e\xba\x54\xaf\xd6\xc0\x5e\x3c\xe9\xb8\x32\xee\x77\x59\x65\x75\xcb\x27\x5b\xb6\x3e\xfc\xc4\xaa\xd8\x22\xb8\xe8\xd2\xa6\x2d\x3b\xe6\xac\x3e\xfe\xc0\x82\xb7\xe6\x7c\xfa\xe6\xea\xa7\xd0\x0e\xb4\x67\xc5\xde\xfe\x50\xb8\x6c\x7e\xf3\x94\x4b\x3a\xde\x19\x3e\x66\xc1\xbe\x49\xe7\x8e\xdf\x30\xf5\xe9\x57\x45\xb3\xbc\xf9\x8e\x2f\x3a\xca\xb3\xb9\x26\x32\x97\xcc\x09\xda\x4e\x83\x9c\xa4\xee\x90\x93\xfc\x5f\x11\x39\x69\x16\xab\xac\x68\x82\x23\xfe\xaf\xe0\xd2\x69\x50\x52\x37\xe8\x28\x0f\x5b\xae\x01\x4e\x10\x82\x5c\xb7\x3b\xa4\x96\x44\x53\x3e\x0a\x8d\x7c\x25\x58\x4b\xf9\x82\x96\x88\xaa\xd4\x13\xda\x3a\xbd\xae\x57\x62\xa0\x39\x92\xf2\xd0\x6a\xce\xbc\x6d\x0c\xff\x17\xda\x46\x29\xbb\x8d\x56\x0f\xa5\x8a\xb7\xc8\x49\xc1\xe1\x0b\xfc\x02\xfc\x3c\x19\xa5\x9d\x66\x83\xaf\x3f\x19\xa1\x75\x87\x47\xa7\x77\x85\x67\xfa\x5c\xb5\x45\x64\x4e\xd9\xe9\x3c\x15\x5b\x77\x9e\x8a\xfd\x7f\x8b\xa7\xd2\x8d\x83\xd2\xd5\x2f\xa1\xb9\xc6\x9d\x9d\xed\x04\x53\xba\xc1\xeb\xba\x25\x03\xb6\x58\x8c\x92\xc9\xe6\x87\x49\x1c\x6c\x5a\x15\xeb\x09\xf6\xb1\x93\x06\xc1\x84\xcd\x4e\xf0\xa6\xd5\x12\x31\x60\xd0\x29\x61\x12\x87\xfb\xa8\x43\x95\x72\x06\x8c\xa7\xed\xb1\xa7\x06\x46\x30\xa4\x70\x4a\x8e\x53\x62\x1f\x4e\xc9\xa1\xc7\x3e\xa8\x85\x83\x2d\x16\xd1\x61\xfc\x91\x0d\x78\x90\x72\x32\xd8\x35\xe0\x81\xcf\x9c\x44\x3a\x72\x01\x8e\x29\xe8\x1d\xb4\x0f\x02\xf4\xbd\x1e\xdc\xc8\x05\x35\x8e\x8d\xc8\xc6\x33\xfe\x7b\x16\xe4\x29\xb3\x20\xff\x2f\x9d\x39\xfb\xdf\x33\x1b\xff\x7b\x66\xe3\x69\x67\x36\xfe\x97\xaf\xbb\xf9\x3f\x35\xe7\x91\xc4\x5e\xf8\x16\xe0\x05\x67\x9d\x1a\x79\x21\x45\x98\xe6\x36\x12\x4d\x29\xc0\xb0\xc1\x2c\x2b\x09\x56\xa0\xb3\x2e\x7e\x65\x24\xe5\x5f\x04\x4e\xba\x8f\x93\x64\x6b\x2b\xff\x7b\xce\xe3\xff\x8f\xe6\x3c\xe6\x62\x61\xba\x8f\x67\x84\xc1\x4e\x13\xfb\xca\x85\xbc\x92\x16\x13\x6f\x26\xb4\xc6\xaa\x35\x4a\x90\xed\xaf\x8f\x81\x39\xf4\xda\x61\x55\xa8\x85\xf9\x81\x30\x48\x09\x33\x6c\x71\xcd\x64\xa1\x91\x30\x3a\x81\xc6\x1c\xcf\x29\xcb\xd8\x29\x11\x31\xf4\xc1\xea\x6c\x40\xec\xf8\x59\x99\xa9\x70\x0b\xbd\x63\x2f\x00\xc0\xcf\x21\x98\xec\x43\x3d\x8e\xe3\xa0\x33\x2c\x13\x9c\x5d\xc4\xf6\x56\xb1\x38\x59\x31\xa2\x29\x7a\x30\x8a\x6d\xa3\x7a\x5d\x1f\x1c\x44\x19\x9f\xb0\x4d\x10\x24\x6c\x13\xb0\x93\x8d\x55\xaa\x3e\xe5\xc4\x6e\x8b\x68\x62\x5e\xa5\xe8\xb6\x1f\x1b\x28\x41\x5f\x97\x91\x95\x3a\xed\x43\x17\x07\xd8\xe6\xb4\xbb\x22\x49\x09\x3f\x13\x92\xd3\x9e\x07\x46\x6d\x64\x00\xa5\x8d\x62\x34\x0d\xff\x4b\x36\xc5\x49\xba\x17\x95\xd3\x70\x17\x92\x9a\xea\x90\xcb\x14\x2e\xab\x7c\x41\xbc\x16\xd6\x5d\x6d\x7d\xe8\x8e\x4d\x2b\x60\x3d\x36\x28\xf3\x5e\xfa\x8f\xa7\x5e\x67\x8b\xe2\xfd\x99\x8a\xcc\x89\xda\xf2\x3b\x46\x30\xab\x8f\x8d\x60\xea\xc6\x6d\xd1\xf1\x99\x59\x21\x67\xff\x1f\x59\xce\x0d\x02\x56\x39\xc1\x5c\x5f\x4f\x45\x20\xc5\xf0\x26\x8b\xb5\xdc\x97\x13\x02\x29\x9d\x80\x0c\x36\x79\x10\x58\x22\x59\x79\x20\x23\x0b\x89\xc8\x5a\xa5\x53\x25\x01\x48\x1a\x5b\x77\xb4\xdb\x40\x68\xee\x4d\xe2\xeb\x60\xb3\x64\x6b\x65\x53\x2c\x27\xd0\x42\xba\x93\x4c\xa5\x6e\x2e\xe1\x19\x9d\x00\x2e\x84\x00\xf6\xd7\xff\x8d\xa3\xdd\xba\x00\x90\xa8\xa8\x11\xe7\x25\xeb\x73\x82\xd7\x72\xb2\x7d\x9a\xc5\x49\xc6\xe2\xba\x5f\x51\x52\xb4\x5a\x74\x06\x09\x47\x94\x0c\x7b\xe8\xd6\x1b\xfe\x17\x01\xdf\x93\xd6\xe9\xa0\x0b\x05\xaa\xad\x16\x6e\x03\xb9\xd5\xd2\x03\x17\x1d\x3a\x1b\x3d\x0b\xf4\xb8\x6c\xfe\xfa\x8d\x1b\x70\xea\x1e\xa0\x7d\x79\x37\x21\xef\x36\x30\x24\x2f\x56\xa5\xc7\x66\x17\x83\x84\x55\x3f\x6d\x23\x36\x8b\xa5\x1c\xb0\x54\x9f\xbb\xad\x27\xd7\x43\xe7\x45\x68\xf5\x44\xad\x6a\x23\xf5\xd0\x36\x49\x13\x69\x3d\xb4\x9d\x23\x11\x5a\x56\x24\x95\xc3\xf8\xc9\x6e\xcb\xaf\x80\xee\x5a\xff\x8c\x0d\x24\x8d\xcf\x56\xc3\x20\xd4\x83\x95\x9b\x1b\x99\xb5\xf3\xce\xfe\xfe\x18\xc9\x9d\x9e\x87\x66\x92\x00\x2d\xb6\x9b\x99\xbd\x1f\xbe\xfd\x6d\x27\x97\x3a\x31\x62\xee\xac\x2d\x34\x46\x2b\x94\x10\x4c\xa4\x00\x2f\x78\x9a\xae\x26\x01\x5c\xde\x58\x2c\x86\x51\x85\xae\xbb\xdc\x1e\x9a\x21\xc5\xcb\x51\x95\x18\x5d\x91\x2f\x5f\x93\x39\x29\x12\x25\x9c\xaf\x18\x8c\x4a\xe9\xa4\xd7\xe3\x36\x93\xca\x32\xd5\x15\xd5\xbc\x79\xbd\x0f\xa7\x9c\xb3\x2d\x37\x90\x36\x0b\xb1\x93\x0a\x05\xd4\x80\xb5\x29\xb9\x8c\xa7\x2d\x57\xf5\x7d\x72\x54\xda\xa2\x8b\x73\xfd\xbc\x8a\xef\x8f\xe2\x85\xd7\x9d\xb3\x62\xed\x6b\x17\x30\xad\xf8\x78\xd1\x2e\xbe\x85\xae\x1d\xcd\x9d\xb5\x25\x33\x1f\xe3\x42\x03\x13\x8e\xd1\xd7\x3f\x5f\x3f\x4b\x90\x5b\xb9\xca\xc4\x52\xac\x92\x3b\x44\x57\x37\x4b\xce\xc6\x49\xbb\x59\xd6\xbf\x5e\x8d\xf2\x2f\x56\x43\x57\xa2\x1f\xe1\x68\x3d\xc0\x9e\x5b\x01\xbe\x93\x41\xbd\xee\x2f\xd7\xef\x80\xef\xa4\x0b\x03\x2e\x91\x4d\xa7\xcc\x42\xc0\x25\x92\x51\xf2\xa4\x72\xc7\xda\x46\xce\x80\x54\xee\xb0\x01\x8a\x7b\x04\xd2\x43\x20\x9a\x65\x45\x93\xbc\xf1\xb8\xea\x92\x55\x39\x1b\x40\xa3\x2d\x04\x52\x88\x76\x10\x64\x2b\xfa\x82\xcf\xbe\xf2\xf4\x7f\x9e\x99\x39\xd4\xc0\x38\x19\x84\x06\x2f\xbc\x73\xf4\x07\xdf\x40\x06\xca\x6f\xa1\x67\xbe\x9c\xff\xda\x20\xe8\x9c\xfa\xfc\x2b\xc8\x1f\x80\xfd\x82\xb1\x23\x13\xd1\xa7\xe8\x7b\xf4\x13\x3a\xe7\x50\x05\xde\xeb\xce\x76\x61\x0f\xbf\x87\xd4\xda\x3f\xad\x6b\x49\x4f\x8c\xd6\xdd\xfa\x6d\xd9\x0d\x4f\x08\x78\x05\xa5\xa4\x9d\xc0\x21\x18\x3b\x5f\x9e\x3f\x97\x2e\xcf\x7b\x93\x61\x04\xaf\x4b\xf5\x52\x78\x64\x95\x72\xe5\xf8\xc6\x79\x74\xad\xc2\x67\x35\x96\xd2\x9c\xd0\xa9\x53\x5c\x5c\x2d\x92\xf5\xa0\x97\x1b\xdb\x06\xd9\x1b\x8f\x6b\xa5\xac\xac\x68\xd6\x22\xa3\xc7\x3d\xa4\x80\x58\xbd\xbe\x01\x40\xee\xd3\x18\x62\xbb\x3a\x52\xba\x6b\x67\x1a\x0d\xaf\xf8\xc7\x0f\xd0\xa2\xa2\x57\xfe\xf4\x03\xfa\x8e\x43\xed\x77\x31\x7b\xe6\xcd\x9a\x9d\xb8\xe2\xfa\xab\x67\xa7\x66\x60\x6f\x0f\x96\xc2\x3e\xc4\xa5\x4a\xa3\xa1\x7f\xc7\x2e\x55\x7d\xaf\xcc\x32\xc6\x8f\x1d\xab\xfe\xef\xae\x78\x14\x3b\x56\xa4\x66\xe4\x0e\x00\xb8\x0e\x12\xcf\xf7\x82\x0d\xf9\x71\x33\xbc\x39\xaa\x39\xa6\xb9\xd9\xb4\xea\xaa\x4f\xd9\x65\x20\xd0\x2b\x69\x67\xd3\xaa\xad\x9e\xdc\x4a\x2e\xeb\x1f\x5a\x75\xc4\x58\x70\xd2\x28\x25\xe2\xb0\x64\xad\x04\xf5\x59\x92\x0a\xf5\x5c\xcc\x36\xc5\xf0\x5c\x34\x07\x87\xb1\x92\xa8\xc7\x06\x55\xbb\xd1\xe1\x0e\x49\xc7\x2b\x47\x70\x52\x2d\x6c\xe8\x53\x5e\x0d\x61\xc8\x15\xb6\x40\x32\xc1\x39\x5c\x66\x5a\xc8\x30\xb3\x27\xc0\x18\x2c\x80\x5f\x13\xdb\x39\x17\x4d\x83\xca\x9c\xa6\xab\xc7\x2e\x5d\xb4\x84\x59\x33\xf4\x91\xd9\x9f\x1f\xc3\xc6\x33\xb3\x97\xfd\x68\xd4\x24\xb8\xe2\x7a\x63\x26\xcb\xa3\x5c\x33\x50\x40\x29\x18\xa8\x4f\xc8\x21\x63\x84\x2c\xd9\x31\x8d\x45\x96\x74\x1e\x26\xc6\x40\x18\x68\x45\x76\x59\x49\x02\xd1\xe1\x2d\xf7\xe9\x29\xd2\xbc\xb9\x8b\x8d\x31\x63\x78\x4f\x45\x97\x46\x88\x89\xf7\xfc\x6d\xe5\xb4\x55\x55\xe6\xf8\x37\x87\x0f\x3a\xcc\x77\xbd\x78\xef\xd3\xb0\xee\xec\x81\xe7\xdc\x76\xe1\x05\x83\x86\x2e\x38\x0f\x2e\x7e\x0b\x5e\xf9\xe6\xd8\xd1\xab\x8f\x6f\x5c\xf3\xc4\x81\xf7\xc7\x8f\xbf\xeb\xd0\x9a\x73\xa7\xdc\xd3\x4e\x7d\xf4\x39\x9d\xed\xdc\x4f\xa6\x12\xe0\x07\x95\x18\x79\x12\x4f\xac\xd0\x9a\x56\xcb\xa2\x9a\x64\xca\x36\xd2\xea\xb3\x8d\x4a\x75\xf6\x8a\x1e\x46\x71\xad\xe8\xb3\xc7\xe9\x55\x93\xe2\x80\x50\xe2\x6a\x2e\xda\x30\x4c\xd8\x4e\xf4\x36\xe1\x0a\x97\x60\x12\x1c\x50\xf0\xe5\x91\xdd\xe6\x4d\x95\x31\x09\xa6\x39\xab\x8e\xc0\x73\xe0\x63\x25\x33\x3b\x2e\xde\xb0\x39\x62\x1a\xf2\xcc\xa5\xbf\x5b\x7f\x1f\xfa\xe7\x33\xef\xfe\x11\xd6\x2d\x1b\xd2\x7c\x6e\x73\xbf\xbb\xce\x2c\x80\x7b\xbe\x85\x2a\x0c\xcc\xac\x47\xc8\x59\x26\x97\x6c\xdd\xcc\x5c\x3c\xe1\x95\xe4\x9b\xe8\xa5\xad\x47\x0e\x7e\x31\x7f\xdf\xec\x87\x26\x8e\x69\x06\x3a\xc7\x32\x37\x91\x6b\x06\x6e\x50\x0a\x7a\x82\x05\x7a\x95\x52\x01\xaf\xf7\x4f\xf5\xe0\xd3\xa9\x50\x89\xc2\x89\x11\x2d\x64\x4f\x43\x35\x92\xdf\x11\x13\x84\xba\x35\x37\xa6\x44\x8a\x74\x4a\xa4\x98\xd6\x7a\xc1\x88\x16\xf4\xc8\x4a\x92\x53\xc8\x58\x47\xcd\x51\x41\xe6\x39\x02\xad\xa4\x40\x56\x34\xe0\x88\xc7\xd5\x90\x4c\x8b\xc3\x7a\x28\xf9\x8d\xc3\xd9\x48\x7d\xde\x94\x4c\xe2\x2e\x0b\xb9\x11\x8f\x13\x1f\x82\xc1\x17\x5f\xfa\x78\xee\xc2\x09\x13\xe7\x7e\x7a\xdf\x97\xc7\x60\xcd\xa4\x09\xbf\x99\x3c\xed\xda\xb5\x4c\xe4\xdd\x4b\x2e\x1d\xd2\xf0\x9b\x95\x50\xdd\x05\xcf\x6e\x79\x7c\xf9\x6f\xef\x28\x34\xfb\xaf\x1f\x3b\xeb\xf1\x09\xe9\xb7\x67\xce\x1d\x37\x74\xc8\xe0\x92\xc3\xc3\xce\xe9\xdd\x70\x3b\xd6\xa3\xee\xce\x76\x76\x23\xe9\x91\xbe\xca\x98\x35\x68\x4a\x27\x24\x9d\x5c\xc0\x38\xcf\x42\x27\xa1\xdd\xb0\xe4\x9d\x27\xa1\xc9\x10\x1d\xc4\x93\xd8\xc6\xdb\xa4\x02\xda\x21\xed\x52\x08\x6f\xa2\x3e\x6d\x30\x14\x57\x6d\x72\x12\x88\xae\x52\xfc\x99\x5e\x30\xed\xea\x33\x90\x69\xd4\x27\x3e\xe8\xed\x59\x0e\x86\xd0\x08\x64\xa9\xbd\xdc\xc3\xae\x59\x79\xce\xe4\x09\xe5\xf3\xaf\x7f\x70\xc4\xf3\x1f\x24\x5f\x1f\x72\xed\x7d\x63\x2e\x1f\x5c\xb2\x7a\xe9\xab\x4d\xdb\xae\x7f\x61\x17\xac\x9e\x72\xcb\xc5\x7d\x7d\xc5\xd5\x3d\x7a\x8e\x3b\xff\xc0\xf8\x47\xd6\x5e\xba\x60\x6c\xff\xa2\x70\x79\xcf\xe2\xcb\x27\x7e\x19\xad\x7a\x4a\xbf\x4f\xab\x4c\x25\xa4\xcf\xfd\x4a\xa3\xcf\xdd\x9a\x56\xcb\xa3\x1a\x67\x26\xcc\x81\xb2\xf5\xe4\x0e\x77\xb3\x3e\x3c\x1e\x2f\x2f\x08\x68\xdf\xb2\x59\x4e\x71\x0e\xb9\x20\x44\x02\xd9\xe5\xc5\xd4\x74\x70\x72\xc2\x44\x3b\x2b\xed\x84\xf0\x42\x96\x49\x7d\x97\xce\x9b\x12\x6b\xcc\x36\xc9\x66\x0d\x07\x3d\xc3\x46\x12\x6c\x98\x38\xff\xb3\x55\xcf\x4f\x35\x33\xb7\xdd\x3d\x6b\xda\xa0\x25\x29\x08\xa1\xf0\x18\x3a\xf8\xc6\xde\x83\x30\x3a\x72\xd8\xac\x7b\x43\xee\x09\xe7\x36\x2f\x83\x4f\x6e\x87\xc5\x8f\x3c\x5f\x5e\xfc\xfe\xb6\xea\xc3\x75\x68\x07\xda\x89\xbe\x42\x23\xfe\x92\x7e\x7b\xfc\x65\x5f\x7c\x32\xe4\x92\xcf\x0c\x9d\x31\x84\xf4\x70\x84\xc0\x4c\x5a\xa5\xa4\x49\x82\x2e\xb5\x25\x7c\x3a\x65\xf5\x7b\xb1\xd4\x5a\xed\xb9\x39\x38\x34\xcb\x59\xa4\x07\x48\xc9\x78\x77\x51\x56\x52\x36\x4e\xa2\x4d\x56\x82\xac\xb9\xdc\xf8\xfc\x24\x2f\x9d\xa8\x66\x95\x49\xe7\xb2\x56\xe2\x97\x4f\x92\x51\x2e\x14\x16\xba\x4c\x77\x26\xb2\x89\x17\xf8\x04\x0c\x24\xb4\xb7\x50\x02\xed\x8a\x31\x57\x4e\xbd\xe4\x77\x57\x6c\xfd\xcf\x0f\xbf\x81\x63\x6a\xd6\x3f\x3b\x73\xfc\x06\xb8\x61\x2f\xfc\x4d\xf2\xf1\xdf\xbd\xb4\xdb\xe3\x9e\x34\xb3\xb2\xf7\x97\xe3\xfe\x02\x5f\x9c\x76\xf1\xa5\x8f\x11\xbf\xb6\xbd\xb3\x5d\xd8\xc9\x35\x83\x38\xf8\x04\x24\x62\x78\x45\x3d\xeb\x63\xb1\x44\x3f\x6c\x2f\x7b\xd1\xd0\x40\x55\xbd\x1a\x93\xb4\x6a\x4b\x9a\x72\x60\x88\xbe\x58\x8c\x4c\xf8\x50\x0b\x63\x9a\xd5\x92\x56\x4b\xea\xb1\x41\xb4\x5b\xd2\xa9\x06\x77\x3f\xa7\x18\xa1\x1d\x2c\x0d\xf6\xb4\x56\xd7\xa7\xbe\x1e\xaa\x67\x90\x79\xe9\x7a\xa8\xd8\x4b\x7b\x86\x93\xf5\x3e\xaf\x39\xa2\xc5\xc4\xb4\x1a\x8b\x6a\xf5\xb4\x89\x38\x0a\x23\x5a\xb9\x98\xd6\xfa\x67\x3b\xe0\x57\x10\x03\x12\x93\x92\x9e\x98\xd7\x15\x51\xeb\xa5\x64\x41\xbd\xcf\x15\x49\xd6\xe1\x27\x7e\xbf\x0f\x7e\x9f\x4d\x7a\x0a\xea\xfa\x64\x91\x4e\x43\x35\x19\x19\xac\xd9\xdd\xfa\x0e\x0a\x8d\x79\x14\x28\x84\x8f\xba\x08\x0a\x31\x57\x88\x8d\xf5\x05\x7a\xb9\x6d\x3e\xa7\x46\x43\x63\x98\x0d\xb9\xc2\x26\x2e\x5c\xe6\x8e\x36\x04\xc6\xde\x31\x7c\xf8\xe0\x9a\x91\x23\x67\xfc\x61\x17\xf3\xe4\xe5\x30\x74\xf9\x23\x71\x58\xbe\xeb\xdc\xc1\x7d\x1a\x82\x0b\xff\x03\x7f\x72\xde\x4c\xed\x1d\xe6\xb9\xa9\xe8\xf3\xa9\x0f\xc6\xd1\x97\xbb\x2e\x30\x7f\x67\xbe\xed\xcf\x8b\xa7\x4e\x0b\xfe\x14\xfc\xea\xbd\x60\x10\xee\x43\xd1\x2f\x21\x2b\x7e\x67\x46\xdf\xef\xc5\xef\x06\x3e\xdf\x5d\x83\x06\xc0\x9d\x9f\xff\x0c\x20\xf0\x77\xb6\xb3\x27\x08\x2f\xe4\x75\x46\xad\xb1\x59\xdf\x68\xc9\x94\x4e\x59\xcc\x65\x5e\x31\xa2\x59\x78\x5a\x96\xc9\xb7\x69\x25\xce\xb4\x5a\x22\xa9\x7e\x52\xe4\x46\x27\x5b\xfa\xe9\xfc\x07\xad\x04\xc3\xf4\xc2\xbc\x72\x63\xb3\xac\xc1\x12\x92\x00\xd7\x0a\x8b\xa8\xda\x77\xf9\x09\xc9\x2a\xcd\x5d\x36\x78\x63\xa5\xb9\xb2\x83\xfc\xfe\x4d\x93\xe0\xf1\xd2\xc4\xa5\x5f\xdd\x0e\x19\x55\xad\x59\xb8\xf2\x86\xa1\xe3\xce\x79\xfa\x82\xe1\x5f\x7c\xfc\xda\xbe\x5b\xee\xde\x81\x0e\xa2\x23\x57\xec\x6a\xfc\x79\xfc\x9a\xb9\xfb\xfb\x0f\xad\xed\x53\x53\xf6\xe9\xb8\xdf\x2d\xbd\xf2\xee\x0a\x73\xbf\x2d\xa9\xd6\x1e\x58\xd7\x5d\xd3\xd9\xce\x25\xb8\x26\xe0\x05\x57\x80\x84\x64\xcc\xe8\xa3\x83\x01\xc4\x98\x31\xb3\x53\x10\xd3\x49\x56\x00\xe6\x88\x31\x0f\x40\xa4\x2a\x9e\xb6\xfc\xb2\xf4\x56\x90\x99\x90\xaa\xa8\x24\x24\x3a\x1f\xdb\x21\x53\x37\x4b\xc2\xe6\xd8\x22\x2b\x3a\xbd\x41\x57\x06\x2e\xdd\x18\x5f\x53\xb0\x08\xd6\x2c\xd3\x27\x7f\xd7\x7c\xfb\xb5\xc7\xb6\x66\xcf\xf2\xb5\xb0\x66\xca\x4d\xcc\x64\xc2\xb0\xf5\xd5\x7b\x70\xef\xf1\x8d\x7b\xbf\x7c\x02\x30\xe4\x37\xff\x60\x1a\x44\x6a\xab\xee\xe9\xe6\x57\xff\xcb\xe2\xaa\x53\x56\xc3\x49\xa4\xb2\x24\xe5\xa3\xd9\x44\x5f\x54\x2f\xbe\xca\x5f\x66\x4f\x7d\x32\x85\x66\x71\xc7\xe3\x9a\x58\x28\x2b\x29\x49\x56\x8a\x2b\x89\x06\xfc\x55\x0b\x3c\x25\xad\xd7\xfd\x8a\xdb\x4e\xce\xea\x75\xb7\x05\xfc\xa2\xfc\xb4\x1e\x9d\xa1\xf9\x25\xd7\x04\xac\x60\x61\x97\x9c\x1e\xcc\xcf\xe9\xe9\x99\x53\x6b\x3e\x23\x92\x55\xcc\x65\xf6\xd6\x75\xfc\x9e\x06\x53\xee\xed\x58\xf3\x3f\x9a\xd9\xcb\x55\x09\x54\x7c\x07\x6b\xaf\x81\x2f\xc0\xf1\x28\x04\x3d\xe8\xb9\x4e\x30\x97\x6b\xca\xfc\xcc\x98\x33\x7b\x33\xfb\x99\x50\x86\xf0\x80\x75\xbe\xd9\xd9\xce\xed\x20\x3d\xcf\xd7\xd0\x53\xd4\x80\x33\x16\xa3\xdd\xcf\xd8\x73\xb1\xe1\x05\xb8\xac\x69\x55\xa6\x33\xbf\x24\x32\x66\x23\xcb\x87\x46\x89\xaa\xad\xaa\x24\xa9\x72\xab\x43\x75\x4a\xaa\xa3\x15\xa8\x8e\x5a\xa8\x39\x64\x23\xb8\x23\xc9\x8a\x66\x73\x61\xdd\xed\x62\x65\x25\x01\x85\x02\xd2\x1a\x4b\x29\x87\x1b\x15\xd2\x17\xe7\x63\x43\x2e\x82\x01\x05\x07\x1b\x2e\xeb\x5f\x11\xad\x1f\x55\x39\xe3\xda\x25\xad\xcb\x2e\xd9\x71\xce\x97\x68\xff\xcb\x3d\x7c\x67\x4f\x1c\x31\x3c\x7c\xf6\xa4\xc5\x53\x27\x70\x3f\x4b\x33\xaf\x81\xd1\x0f\xe7\xc6\x4b\x82\xc7\xdf\x66\xe7\x9a\x07\xad\x68\xbb\x72\xdb\xd2\x0b\x49\x4c\xc4\x07\x80\x29\x46\xf8\xa5\xff\x4c\xcf\x21\x69\x17\x15\x5f\xb9\x4f\x6f\x8c\xb4\xc5\x0c\x32\x5b\x9d\x90\x41\xd4\x87\x6a\xf8\xbb\xcb\x21\x38\xf4\xb1\x7c\xad\xb7\xfc\x5c\x81\xdf\xd5\x7c\x5e\xb3\xea\x95\x1c\xaa\x9b\x24\xeb\x48\x00\x4c\xef\x96\xd4\xab\x62\x79\xbd\x89\xb2\x75\xd0\xb1\xab\xc8\x09\xb2\x52\x92\x63\x79\x57\x24\xc1\xb1\x79\x75\x1f\x60\x1b\xeb\x70\x7b\x39\x5e\x6f\x26\x7d\x1e\xb2\xb6\xbc\xbf\x8d\x20\x89\x4f\x56\x12\x8c\x49\xa1\xec\xa3\x9a\x55\xca\xd6\x00\x98\x28\x7b\x95\xab\x18\xfa\x48\x5c\x9c\x0d\xb9\x1c\x50\x80\x61\xb6\xb2\x8a\xf5\x7d\x07\xd7\xf5\xb7\x59\xf8\xc0\x90\x1a\xe8\x80\x5b\xff\x8e\x3e\xdd\x5a\x38\xa6\x27\x6a\xff\x66\x50\x81\xb0\x85\x6b\x42\xe1\xb1\xf7\x9c\x7b\xe6\x83\xa3\xe0\xa1\xe3\x1b\xd9\xaa\x81\xf7\x8d\xca\x1c\x83\x3f\xef\xbe\xea\xc4\x01\x5d\x86\x77\x13\x0e\xd8\xad\x27\xe5\xf0\x60\xb7\x39\x3c\x21\x9b\xc3\xa3\xfe\x77\xd2\x96\x2f\xd8\xb6\xbc\x02\x42\x31\x9d\x14\x48\x34\xd5\x2c\x92\x32\x4a\x21\x2f\x9a\xaa\x87\x8d\x72\xa4\xe9\xff\x76\x3e\xcf\x45\x0b\xad\xf1\x7f\x2b\xbe\x83\xbd\xa7\xc0\x29\x13\x61\xcd\x61\xb4\x7f\x2a\x7a\x72\x3a\xd7\x84\xc6\xc0\xe7\x8e\x6f\x84\x7b\x50\xec\xbf\xfa\x8c\x49\xbc\xff\x74\x76\xf3\x03\xba\x0e\xb1\x8b\xc6\xee\xf3\x10\x44\xfe\x8d\xe9\xcd\x5d\x79\x1f\xf3\x0a\xb6\xf5\xfa\x6c\xf2\xa4\x8d\x20\xb9\x31\xcf\x2c\xc7\x74\x3b\xe6\x19\xef\xf7\x2f\x4c\x79\xfe\xda\x63\x59\xfb\xfe\xf2\x07\x7c\x4b\xd0\xfe\x65\x5d\xa7\x3c\x67\xee\x60\x56\x65\xa7\x3c\xeb\xbd\xfd\xc4\xa7\x09\x81\x8d\xfa\x84\xe7\x02\x7d\x18\x2d\x65\xec\x00\x94\x79\x90\xe2\x42\x9d\x6e\xb0\x50\x77\x99\xc3\x27\xd7\x51\xd2\x5b\xea\x96\xd4\xd2\xd6\xa4\xcb\x5d\xea\x8a\x24\x43\xf8\x99\x70\xb9\x4b\xf3\x34\x65\x28\x0e\x12\xae\xd2\x10\x1d\x6f\x4f\x5f\xe8\x9c\x7a\x6e\x59\x49\x98\x44\x9a\x78\x2a\x10\x69\x0a\x05\xca\x78\xc1\xc5\xfa\xcc\xd9\x58\x7e\xf7\x7e\x65\xd7\xf6\x7d\xda\xbd\x3f\xee\x6b\xd9\xb2\x3c\xb9\xf6\xe9\x65\x87\x57\x5f\x7c\x53\x8c\xf4\xee\x8f\x18\x7c\xf6\xcd\xe7\xdf\x31\x62\xfe\x05\xc8\x6d\x1a\xb1\xe5\xd5\x8f\x5e\x7b\x15\xfd\x7e\xef\x88\x09\x46\xe3\xfe\xf2\x1f\xe6\xaa\xb7\xff\x13\xfc\xd7\xe3\x50\x21\x32\x68\x3a\x40\xfc\xae\x0f\x74\xfd\xa9\xb8\x0a\x8b\x0c\xfd\x49\x4e\x88\xd8\x04\xc3\x45\xa9\x14\xd3\x6a\x25\x05\xee\x3a\x07\xa2\x97\x4e\x48\x48\x2a\x4e\x8c\x5c\xf5\x19\x12\x4a\xde\xe0\x08\x9d\x78\xd4\xa1\x16\x11\xe6\xd1\x42\x49\x0d\xb6\x6e\x1f\xd8\xf1\xd3\xd5\xe4\x48\xf3\xd8\x72\x41\x52\x76\x07\x8b\x69\x41\x9c\xf1\x8a\x1c\x5b\x51\xa5\xac\x18\xd2\x5a\x28\x6b\xa6\xb2\x38\x71\xf0\xcc\x16\x32\xad\x46\xb3\x17\x18\x9a\xb2\x85\xe5\xcc\x16\x67\x41\x59\x17\xe1\xf5\xc5\x74\xff\x3d\x5f\x84\x4f\x11\xe6\x4f\x23\xe6\x61\x2d\x57\xdd\xbd\x1a\x8b\xf4\x72\x69\x7a\xd3\x03\x3d\xa6\x62\xd9\x9e\x6e\xc8\xf6\x57\xd7\xde\xb0\xe5\xc1\x91\x57\xe9\xe2\xfd\xf5\x3b\x28\x9a\x27\xe7\xb0\xb3\x19\xb9\xb9\x35\x04\xd3\x9d\x01\xf4\x99\x12\x31\xd5\x4d\x98\x68\xc8\x35\x16\xda\xb0\x2e\xa4\x44\xf7\x02\x51\xe9\x40\x63\x30\x10\xf7\x12\x5f\x87\x4e\x16\x13\x28\x29\x3f\x1b\x72\x79\x3d\x31\xa2\xe9\x09\xb7\xcc\xaa\xa1\xbd\xc7\x2e\xea\x1b\xd8\x04\xab\xfa\xd9\xcd\xee\xde\xd5\x90\x83\xe7\x66\xc6\x6b\xe8\xfd\x89\xf1\xff\x87\xbd\x77\x01\x8f\xaa\xba\xfa\xc6\xf7\x3e\x97\x39\x73\x9f\x73\x99\x4b\x66\x26\xb7\x99\xc9\x85\x64\x48\x86\xcc\x90\x84\x01\x92\x70\x09\x57\x11\x29\xa5\x31\x20\x44\x44\x45\xbc\x20\xb6\x14\x2d\x45\x6a\x29\x55\x44\xa4\x88\xf7\x0b\x5a\xa4\x88\x96\x52\xbb\xcf\xcc\x80\x8a\x68\xe3\x5d\xeb\xed\xa3\x56\xac\xb5\xd6\xb7\xb5\x5a\xc7\x52\xb5\x68\xfb\x8a\x90\xc3\xff\xd9\x7b\x9f\x73\x66\x26\x09\x68\xdb\xf7\x7b\xbe\xe7\xfb\x9e\xff\xf3\x3e\x9c\xce\x9c\xe4\x35\x67\xaf\xbd\xce\xde\x6b\xaf\xf5\x5b\xbf\x5f\xde\xb5\xf8\xfc\x16\xae\x6f\xe0\x8b\x0b\x0f\xa4\x36\x7e\x83\x09\x1d\x63\xb4\x9c\xf2\xff\x6b\x5e\xfc\x9f\xd4\xbc\x80\x27\xb6\x01\xc0\xed\x24\xfb\x6a\x5d\x51\x4d\x14\x9a\x35\x51\xbc\x15\x0e\xa9\x73\x86\x75\xc4\xe7\x79\xf0\x9d\x3f\xc2\x89\x2b\x3f\x83\x4b\xb4\xa6\xcf\xb4\xfd\x6b\xb5\xcf\x99\x0e\x26\xa2\x65\xe0\x6c\x1c\xc7\xc1\x1e\x6d\x37\x59\x47\x2e\xd2\x56\x90\x33\x44\x35\x78\x82\x6a\x34\x66\x38\x97\x9b\xd4\x36\x23\x06\xd0\x63\xd8\xd3\x03\x0a\xe0\x03\x92\xdf\x65\x16\xb0\xbb\xf8\xcf\x7e\x3b\x44\x19\xcf\x24\x78\xe5\x08\x9b\x42\x59\x3f\xa7\xfa\xfd\x47\xdd\xc8\x47\xc8\x9b\x7f\x49\xe6\x9d\x60\x90\x29\x8b\x35\x78\x88\xe1\x9d\x1e\x9f\x3f\x50\x66\x4c\x07\xdc\x4b\xee\x94\x15\x85\x37\x34\x96\xaf\x24\x14\xe5\x6a\xb8\x9c\x1e\xb7\xa4\x34\x18\x1a\xbe\xd3\x22\x20\x99\x2b\x4a\x26\x7c\x51\x45\x71\xdc\xbe\xc3\xd2\x59\x9f\xda\xa8\xe5\x17\x8f\x69\x75\x5b\x7f\xf4\xec\xc6\xdb\x61\x53\xf7\xd6\xa2\x78\x7d\x80\xab\x0c\x4c\x74\x0f\xac\x82\x5b\x43\x67\x8f\x7b\xfe\x3e\x53\xf3\x80\xdb\x4e\xf4\x9c\xcf\xa0\x2a\x24\xf4\xe0\xe2\x4e\x19\x4b\x2e\xd5\x61\x23\xa9\x6c\x51\x0f\x00\x04\x3c\x43\x6c\x80\x82\x5b\x49\x91\x5a\x94\x33\x6e\xaf\x0e\x5b\x90\x48\x12\x0d\x3f\x7d\x57\x41\xa8\xbc\x8b\x04\x67\x06\x61\x6f\x45\x0a\x36\x75\x8a\x9d\xe9\x25\x57\x35\x85\x49\x84\x32\x41\xac\xb0\x7d\x7f\xe7\x86\x3b\x99\xdb\xcf\xb8\xe6\xef\xda\xdb\xdd\xc9\xae\x09\xcf\xfc\xe6\xaa\x63\x3b\x60\xe2\x1b\x67\x6f\xde\x43\xe6\xf5\xc4\x61\xc2\x07\x4d\xd8\x30\x42\xf8\x39\x2b\xf0\x25\x6a\x3c\x71\x96\x73\xb9\x03\xa4\xc2\x57\x77\xea\x79\x76\xd3\x9e\xb8\xb2\x22\x99\x49\x33\x3e\x28\x99\x69\x83\x17\xba\x78\x3e\xb3\x78\xf6\xf4\x2e\x52\xfd\x53\xd1\x1c\x12\x99\x35\x5d\x97\xc4\x2d\xab\x0a\x9d\xd3\x4c\x28\xac\x37\xf5\x86\x24\x79\x1f\xb0\x29\xe1\xf2\xea\xc8\xb0\xc7\xb3\xc1\x07\x35\x7d\x92\x87\x67\x80\xfe\xe8\x5d\xaf\x75\xeb\xc1\x37\xe3\x84\x24\x1a\x36\x9d\x84\xfe\x79\xc7\xab\xef\xbe\xfb\xee\x2e\xfa\x5e\xe8\x7c\xda\xc7\xe9\x7b\x91\xc3\x06\x2b\x23\x16\x4b\x7c\x55\x8b\xa1\x08\x7e\x49\xaa\x87\xa3\xd4\xfe\x32\xd3\x15\xbd\x39\x91\x66\x37\x8a\xf6\x73\x6a\x35\x7e\x73\xaa\xfa\xf1\x71\xef\x1e\x9d\xb9\x10\xf9\xfb\xa9\x0e\x38\x98\x60\xc7\x06\xf6\x07\xab\xaa\x23\xd1\x02\xc4\x03\x3e\xa4\xdf\x8d\x96\x9c\x10\xa8\xf9\x47\x52\xf3\x37\x34\xea\xe6\xaf\xa7\xf9\xdb\x9a\x5a\x42\xd3\x8d\xc2\x27\x7d\xa5\x4a\x5f\x2e\x4a\xd4\x7d\x4a\xdb\xef\xb0\x74\x34\xb4\x6c\xd4\xf2\xe7\x9c\x13\xb2\x6e\x7d\xea\x4b\xe6\xa0\xf0\xda\x8d\xbc\xfe\x25\x3c\x19\x24\x4f\xbf\xf0\xc4\x61\xee\x08\xd7\x07\x64\x50\x05\x1e\xd6\x91\xa4\x7e\x9e\xc6\x7f\x2a\x10\xf2\x48\x4e\xe6\xf8\x30\xed\xa1\xe1\x69\xeb\x89\x87\x26\xc5\xaa\x92\x48\xa1\x14\x03\xd6\xa2\xae\xe7\x6b\x8f\x2c\xa2\xd6\xad\xa2\x04\x40\x52\xf9\x51\x1e\xc9\xfd\xfb\x3b\x9f\xfd\xf4\x1a\xb2\x9d\x54\x89\xd9\x8a\x2a\x56\x89\x67\x2b\xf1\x35\x53\x59\xc5\x16\xed\x26\x15\x69\x90\x63\xa5\x8a\x4a\xda\x94\x02\x73\xac\x24\x57\x54\x16\xec\x1b\x54\xf0\x09\x8c\x77\x12\x37\x0e\xfb\x25\x59\xb5\x7a\x48\xcc\xdf\x4e\x29\x96\xf5\x44\x78\xeb\xe8\xf6\x30\xd4\x93\xe1\xb1\xa8\xe0\x86\x0b\x5b\x98\xeb\xcf\xed\x5d\xb7\xeb\xb1\xb5\x1f\xff\xec\xa9\x97\xca\x7a\x1f\x9d\x35\xb9\xe7\x82\x5b\xa7\x2e\x10\x3c\xec\xea\xf7\xb4\xb1\xfe\xfb\xae\xfb\xce\xbe\xf3\x77\xdd\x3b\xf5\x52\x78\xe3\xc0\xd3\x1d\x93\xe6\xcf\x58\x23\x57\xcf\xa6\xf8\xa4\x8b\x4e\x1c\xb6\xcc\xe4\xfa\x80\x07\x94\x83\x6a\xf0\x2a\x20\xaf\x3b\xaa\xd6\x2b\x72\x0a\x9f\xd7\x17\xf7\xca\x2a\x7c\x18\x13\xca\xdc\xac\x2b\xae\x0a\x7c\x9e\xca\xff\x45\x4c\x55\x54\x91\xaa\xa2\xd2\xa3\x98\x48\x52\x2c\x24\x32\x23\x70\x16\x91\x68\x48\x56\xb9\xf2\xd9\xea\xaa\x4a\x6b\x5c\xad\x70\xe5\x51\x45\x82\x38\xb8\x01\x63\xda\x72\xe4\xaa\x41\x0e\x1e\xea\xdf\xdf\x79\xc7\x91\x9f\x53\x7c\x6e\x48\xcc\xf2\x21\xda\xef\xc9\x84\x9a\x9b\x61\x86\xe1\x43\x7a\x79\x8a\xa8\x87\xba\x95\x32\x9d\x9d\x5a\x48\x03\x95\x77\x9b\x6b\x63\xbb\x52\x64\xba\xea\x12\xab\xe1\xed\xee\xa2\xc0\x06\xd8\xb4\x64\xc9\x85\x9b\x1e\x5c\xf9\xfb\xdb\xb5\xef\xc2\x91\x9d\xa3\x67\xcc\x5f\x9b\x9e\xe9\xe1\x99\x3b\x3e\x82\x4d\x1f\xc1\x96\x33\x97\x32\x97\x69\x63\xfd\x3b\xaf\x5e\xfd\xf0\x32\x78\x7a\x47\xe7\xa2\x19\x57\xc8\x93\x5b\xb5\x5f\x70\x7d\xc7\x76\x00\x06\x2c\x3b\x71\x98\x73\x73\x7d\x40\x04\xe5\xe0\x67\x3a\x7f\x90\x97\x37\x55\x64\x73\x42\xd0\xb0\x18\x29\xc0\xea\xd6\x92\x8a\xad\x25\x51\x6b\x19\x9a\xe6\x06\x81\xf7\x2d\x47\xb6\x0d\xb2\x48\xb8\x1f\x85\xc5\x2c\x1f\xe6\x94\x78\x86\x0f\x73\xc5\x04\x41\x0c\x1f\x6e\xa6\x66\x09\x9b\x2f\xab\x24\xc9\xaa\xdb\x4b\xf7\x3b\x81\x08\x75\x06\xbd\x7a\x78\x32\xc4\x32\x85\xea\x4a\x2c\x2a\x58\x96\x05\xb1\x55\x7a\xd6\xef\x3a\x70\xe5\xc7\x3f\x7b\xea\x65\x18\x9f\x3d\xa9\x67\xe9\x2d\x53\x17\x04\x60\x6a\xe2\x4a\xe6\x0a\x6d\xac\x7f\xd7\xc6\xd5\x7b\xcf\xbf\x7f\x77\xe7\xc4\x05\xd3\xd7\xc8\x17\xfc\x5f\xc6\x65\x57\x7b\xe2\xb0\x65\x9e\x5e\xe7\xfa\xb9\x1e\x21\x79\x75\x8f\x0f\xd8\xf3\x06\xcd\x38\xe5\x80\xaa\xb0\xe7\x73\xac\x42\x6b\xd0\x02\x75\x79\x3d\xfb\xe0\x2d\xce\x3e\x78\x5d\x66\x25\xba\xa8\x22\x66\x2f\xf2\x70\x03\xae\xe2\x15\xb3\xac\x97\x51\xe2\x59\xc5\x4b\x2b\xd1\x0a\xf5\x63\x42\x97\xc8\x11\x9d\x29\x5a\x89\x56\x00\x39\x7b\xa9\x15\xa4\x0e\x1d\x36\x28\xc4\x53\x6d\x35\x85\xf3\x61\x07\x8c\xb1\xb0\x28\x07\x40\xf2\x11\x4f\xa4\xa1\xf7\xb9\x27\x0f\x6d\x38\xf1\x8b\x27\x7f\xfb\xea\x12\xa6\x77\xe3\x84\x4b\x27\xad\xef\xbe\xb4\x9b\xeb\xd3\xe6\x1e\xfa\xdb\x87\x07\x5f\xd3\xf6\x67\xff\xf4\xab\x56\x2d\x05\xef\x7c\x64\xed\x3b\x6b\x9e\xf9\xc1\x07\xb4\xde\x7c\xf8\xc4\x61\x6e\x3d\xe1\x6f\x8e\xe1\xb3\x32\x51\x8c\x05\x62\x2a\x45\x75\x40\x59\x36\x4f\xe5\xd8\x3d\x29\x35\xc2\xe7\x51\x75\x32\xa7\x54\x06\xdd\xae\x38\xaa\x4a\xa9\x8a\x33\x4f\xda\x35\x6a\xc8\xdc\x86\x3d\xa4\x8e\x64\xc4\x32\xb5\x66\xf2\x8e\x12\x7d\x49\x84\x9e\x85\x08\xf8\x21\x49\xcc\xca\x12\x3e\x47\x57\xe1\x2b\x9b\xf5\xc8\x55\x26\x43\x4b\xd8\x21\xc9\x59\xc1\xe6\x0f\x90\x94\x6b\x65\x50\x92\x55\x68\x23\x9b\x0d\x69\x78\xd7\x13\x7a\x9d\xb0\xbd\xae\x75\x74\x4d\x4a\xe7\x91\x15\xb0\x37\x9b\x25\x68\xef\x88\xda\xc6\x56\xef\xd8\x33\x5a\xef\x06\x27\xfe\x0c\x5f\xfb\xab\xf6\xeb\xb3\x3a\xd3\x73\x9b\x27\xdd\xb9\xe2\x2c\xf8\xdb\xa9\xa7\x2f\x1a\x77\xd5\x19\x8b\xb8\xcf\xc5\xa6\xe8\xe2\xd9\x9e\x89\xbb\x33\x2f\x1c\xdb\x01\xb7\x9f\x71\xde\xe6\x6f\x33\xc7\xda\x27\xc3\x90\xa1\xdf\x77\xe2\x30\x37\xc9\x12\x21\xf5\xa5\x46\x70\xf9\xe0\x0a\xd3\x08\x3e\x9f\xb3\x47\x0b\x15\xa6\x78\x71\x85\xa9\x4e\x4f\xe8\x8c\xd4\x25\xa3\xd4\x60\x28\x9d\x46\x75\xd2\x3e\x07\x27\xfa\xc3\x94\x84\x55\x90\xb3\x8a\xb7\xa2\x92\x8c\x72\x70\xb9\x69\x44\xf4\x4b\xcb\x4d\x46\xef\xb2\xf2\x25\x75\xa7\x3a\xbd\x89\xd9\x7a\xd2\xfa\x13\xdf\x49\x7b\x99\x8f\xf7\xeb\x75\x28\x4e\x1f\x3b\x07\xca\x40\x14\xc4\x41\x2b\xd8\x3a\x78\xf4\x0d\x78\xf4\x31\x63\xf4\xf8\xf5\x18\x9d\x52\xcb\x1d\x79\x94\x48\x42\xd4\x96\x40\xc1\x43\x6a\xa5\x2b\x9f\x75\x55\x06\x0b\x2f\x0b\xb6\x4d\xa5\xa9\xb0\x87\x46\xe2\x68\xa7\xc5\x95\x57\xdb\x61\x9c\x4c\x73\xd6\x21\xfa\x63\xd8\x32\x23\x25\x95\x6b\x48\xa7\x51\x8b\xac\x7a\x49\x46\xd7\x2e\xea\x0c\xc2\x6a\x43\xec\x4b\x0d\x63\x52\x89\x98\x96\x29\xdc\x3a\x89\x8d\xca\x29\xbd\x48\x9b\x6e\xa2\x16\x9d\x75\x64\xa8\xa9\xb8\xdb\x09\xdd\xc8\xc0\x16\x6c\x29\xe6\x12\x9d\x7b\x84\x01\xb5\x9a\x97\x5b\x6c\xf1\x82\x46\x10\x87\x2e\x7d\x6d\x69\x4c\xa1\x60\x82\x54\x5d\x99\x84\x0a\xed\xa9\x94\xca\x3a\x29\x16\xda\x38\xfe\x52\xce\xfa\x46\x57\x1e\x35\x8a\x44\x47\x5a\xa1\xc2\x83\xba\x86\xdb\x2b\x46\xf2\x89\x27\xc2\x34\x96\xfe\xfd\x5d\xec\x67\xaf\xd2\xdd\x21\x22\xa2\x68\xbf\xea\x0f\x1f\x45\xbe\x7e\x1e\x01\x31\x0b\x01\x3e\xeb\x72\xf8\x8a\x1a\xc5\xac\xd0\x48\x68\x99\x1b\xc9\xc1\x78\x1b\x91\xba\x77\x64\x1b\xf0\xd7\x4c\x43\xa3\xa5\x58\xe0\xd8\xe7\x8f\x44\x1b\x68\x60\x32\xc1\x01\x39\xde\x22\xd8\x0b\xb7\x8a\xa2\xc0\x46\xbd\x91\xb3\x46\xca\x3a\x5d\xc1\x30\xad\x76\x67\x6c\xa2\x95\x84\x2d\x78\xfe\x50\x98\x88\x1f\x94\xa7\x11\x23\x67\xc4\xba\x78\x9a\xae\x5d\xb1\xf6\x54\x3b\xe1\xa1\xb3\x08\x85\x94\x48\x41\x0d\xb0\xdd\x4c\x89\xc0\xda\xe3\xdb\xe3\xdb\x63\xb0\x29\x02\xe3\x71\xed\x8d\xba\x91\xd6\xce\x5b\xce\xbb\xfe\x16\xff\x8d\x0d\x2f\xfc\x64\xd9\xd4\x8e\xd6\x8e\x45\xf2\x8f\xc4\x8b\x16\xde\x32\xb2\x97\xf9\x98\xdb\xf3\xdc\xbd\xf7\x3e\xf7\xe8\xd2\xd9\x0b\x1f\xb8\xe3\x8c\xa5\x03\xb3\xfa\x1f\x0a\x1e\xf1\x7d\x6d\x3e\xb3\xad\x3b\xb5\xe6\xdd\x57\xb4\x15\x5c\x1f\x89\x03\xbd\x27\x0e\x73\xb2\x25\x02\xea\x40\x02\x2c\x1f\xb6\xc2\x3f\x6a\xb8\x0a\x7f\xcb\xa0\x0a\xff\x43\xb4\xc2\x5f\x3f\x82\x8e\x3a\x5b\x1d\x69\x4c\xd0\xd5\xe9\x3f\x29\xf3\x9b\xec\x0d\x5f\x56\xef\x3f\xa8\x33\x39\x7c\x59\xe1\x9f\x9b\x5a\xe0\x76\xf8\xbf\x8b\x13\x37\x70\xe2\x30\xbb\x9d\x5b\x09\xa2\x60\x89\xae\xbd\xc6\x5a\xf2\xa4\xac\xad\x7a\x2d\x54\x79\xdd\x79\x48\x0d\x78\x48\x31\xc5\x02\xe3\x6a\x85\x87\x2a\xaf\x07\x9c\x92\x9c\xb1\xb1\xd5\xe9\x74\x5a\xad\xb0\x48\x72\xd6\x23\x7b\x69\xdb\x1d\x5b\x4d\x03\x0c\xaf\x94\x85\x4e\x99\x68\x0c\x78\x64\x8a\x71\x6b\xd5\x11\x25\x84\xe3\xa9\x6d\x30\xc5\x13\xe1\xab\xbb\x7b\xc7\x9c\xa5\x33\xfb\x56\x2f\x7e\xfb\xe5\x17\x76\x9c\x7b\xfd\xe5\xe9\xa9\x13\x7a\xd7\x5c\x7a\xf4\x0f\x17\xff\xb8\xe9\xf3\x05\x13\xc7\xc4\xbb\x47\x77\x6f\x58\xb8\xfb\xd1\xb3\xdf\x98\x97\x8a\xd7\x8f\x6b\xea\xba\x79\xf1\x81\x17\x2a\xf1\x3a\x00\x00\xb3\xd9\xe2\x05\x2c\x70\xe3\x91\x98\xfc\x01\xd0\x54\x78\x11\x38\xca\xf0\xa5\x17\xe9\xd8\xe2\x68\x82\x75\xe5\x11\xd4\x55\xe4\xec\x62\x81\xfe\x4b\x87\x6e\xb1\x10\x6f\x8f\x0c\x8e\x0b\x04\x17\xed\xab\x52\x22\x8e\x22\x52\xc1\xda\xbf\xc1\xa6\xbf\x89\x3a\xed\x33\x8e\x54\xf9\xf3\x4c\xc2\x67\x16\x3f\x1b\x5b\x63\xe1\x00\x0b\x5c\x20\x00\x56\x0c\x7d\x3a\x67\x02\xf9\x53\xaa\xe0\xa0\x55\xb8\x32\xb3\x79\x95\x33\x88\x1a\x6c\x22\x62\x09\xa4\xdb\x7c\xdc\xac\x9b\x3c\xbf\x52\x54\xda\x2a\x7d\x58\x48\x55\xd5\x8a\x1e\x75\x10\xdf\x13\x79\xe6\x27\x4a\x69\x9e\xc8\xa3\x2f\x2d\x25\x8f\xfb\x7f\x85\x77\x9b\x39\xf1\xcc\x89\xc3\x96\x35\xdc\x4a\x30\x02\xb4\xe2\xa8\x82\xa8\x16\xd4\xa5\xd4\x91\x7c\x9e\x66\xe6\xcd\x7a\x28\x8e\x41\xc5\x96\x80\xc3\x15\x57\x45\x7c\x90\x68\x23\xe2\xd1\x0d\xae\x3c\x6a\xa0\xe8\x0c\x45\xdf\x3c\x1b\x42\x92\xac\x3a\x2a\xd2\x69\x94\x90\xb2\x6e\x31\xe0\xa2\x31\x45\x40\x92\x73\x50\x70\x87\x48\xb4\x51\x21\x11\xf2\x46\xca\x0e\x6b\xe8\xb0\x76\x32\xa9\x64\x60\xd0\x19\x53\xa9\x27\xf5\x51\x06\x2f\x50\xc5\xe7\xa6\x71\xb5\x89\xd4\xe9\xb1\xf8\xd7\x7e\xf4\xd2\xdd\xaf\xdc\x7d\xd6\x25\x97\xde\xf7\xd8\x95\x1f\xef\x79\xea\xa5\xe0\x82\xa6\xc9\xf3\xa7\x75\x4f\xbf\xe0\xfa\xf3\x53\xe3\xb8\x10\x39\x82\x4e\x59\xe0\x65\xb9\xcf\xc5\x0b\x2e\xdb\x70\xec\xd7\x0b\xc7\x6a\x67\xfb\xef\xbb\x6e\xf5\xde\xf3\x77\xdd\x3b\xe3\x62\x78\x23\x37\x61\xc3\x9b\x1f\x3c\x78\x96\x13\x4e\xa1\x27\xd2\xb3\x62\x78\x9d\x6e\x21\x36\xe9\x03\x01\x50\x03\xd3\xba\x67\x06\x52\xb4\x52\x1c\xd6\xcf\xed\x66\x69\xd0\x2f\xe2\x73\xbb\xaf\x3a\x45\x8a\x83\x2a\x67\x4b\x26\x09\x1c\x43\x7f\xa5\x02\xc5\xaf\x54\xa0\xb4\x3c\x58\x46\xca\x83\x45\x8a\xd3\x35\x49\x64\xa1\xe7\x54\xa7\xcb\x24\xd8\xd2\x0b\xe3\x45\xc5\x42\x5e\x44\xbe\x7e\x0e\xbb\x4c\x0d\x65\x76\x65\x03\x8c\x12\x47\x3e\x31\xcb\xf9\x48\x5a\x19\x7d\x4a\xf9\xb3\x6a\xc4\xac\x50\x63\x51\xe2\x3c\x65\xd2\x62\x06\xfd\x2c\x8a\x7f\x96\x8d\xe1\x6b\x26\x56\x63\x29\x25\x83\x16\xd2\x20\x2b\x44\x63\x35\xb4\xb9\x92\xe5\x04\x9f\x3f\x1a\x2b\xde\x82\x2d\xbc\x24\xab\x62\x38\x9d\x46\x95\x92\x6a\x23\x64\xd0\x7e\xa2\x43\xa4\x54\xa6\x8d\x73\x42\x44\x19\x9c\x34\x30\x10\xab\xfa\x3c\xb6\x7c\x02\x13\x0b\x61\xfd\x02\xd8\x74\xee\xb7\x97\xea\x93\xe8\xd5\x7e\x77\x2e\xb3\xbd\x30\x77\xa4\x9a\x49\x32\x08\x64\xde\x3a\x16\x69\x29\xd8\x51\x3c\x5f\xb5\x00\x90\x78\xa7\x1a\x44\x20\xd4\xab\xb8\xfe\x40\x75\x2a\x95\x3a\x69\xb0\x43\x2b\x6d\xba\x76\x5c\x88\x7a\x6f\x21\x2d\x1c\x33\x81\xf1\xb9\xa2\xa8\xa7\x7a\x50\xd4\x13\x10\x51\x19\x51\x96\x1b\x26\xe8\xa9\x16\xb3\x42\x35\x09\x7a\xaa\x4b\x82\x9e\x2a\xfc\x35\x53\x55\x5d\x1c\xf4\x64\x7c\x84\x20\x04\x4e\xb0\xe9\x01\x8f\xc1\x17\x62\x58\xba\x5a\x0f\x76\x02\xba\x0e\x5d\x48\xc6\x61\x8d\x5f\x32\xe3\x1d\x06\x48\x72\x46\x2c\x8f\x9c\x2a\xc6\x89\x14\x45\x36\xda\x8e\x42\x64\xf3\x7a\x5d\xa3\x1e\xd9\xac\xd6\x5e\x5b\x2b\x5e\xb4\xe8\xb6\x78\x0f\x73\x98\x46\x34\x3b\xd7\xea\x11\xcd\x13\xcc\x9c\xee\xd4\x9a\xbf\xfc\x4a\x0f\x65\x74\x9b\xbf\x6b\x89\x90\x1e\xc6\x93\xa1\x3f\xbc\x27\x47\x7f\xf8\xfe\xb7\xa0\x3f\xcc\x18\x66\x28\x0c\x04\x56\xea\x61\x4b\x29\x1e\x84\x7b\xd3\x0c\x52\x28\xbe\x27\x63\x89\x00\x3f\xa8\x02\x97\x0c\x8b\x4a\xaa\x3e\x35\x2a\x29\x52\x82\x4a\xca\xd8\x02\x24\x21\xe4\x92\xf7\x8a\x92\x1c\x0c\x93\x5d\xff\x5f\x01\x27\x99\xa7\xaa\x93\xa0\x94\x46\xeb\x87\xa9\x61\xb1\x3a\x6b\x0c\xae\x57\x86\xd6\xe5\x74\xdc\xd2\xa5\x83\x2b\x73\x5f\x8d\x11\x0a\x95\x8b\xc8\x8a\x5f\x0f\x52\x22\x48\x90\x74\x64\x23\x8c\x53\xbe\x61\x4b\x1a\x95\x4b\x04\x93\xfd\x55\xab\x79\x70\x30\x2a\xe9\x14\xe5\x3d\x78\xfe\x60\x6c\xd2\xb0\x05\x3f\x21\x3f\x88\x73\x80\x01\x17\x69\x5e\x1d\x63\x16\x06\x7b\x06\xcf\xa7\xca\xb9\x52\x29\x14\x48\x18\x8d\xcc\xb4\x2b\x18\x85\xf1\x20\x09\x4e\x26\x81\xd8\x14\x41\xa3\x72\xc9\xe2\x39\xae\x38\x45\xc9\x08\xa8\x0c\x8f\xbd\x13\x5f\xc9\x9b\x2b\x04\x24\x59\xf5\x96\x51\xc6\x49\x02\x52\xcb\x61\x57\x08\x15\x79\x02\xde\x18\x51\x30\x8d\x58\xe9\x4b\xfd\x21\x0c\xdb\x53\x6c\x69\x1d\xe8\x6f\x7f\xf6\x59\xb7\xfe\x7a\xe3\xed\x3b\x66\x1d\x6f\x59\x3c\xa8\x06\x44\xfc\x60\x60\x3d\x9c\x7f\x91\xd6\x41\xe2\xda\x75\x27\x0e\x0b\x9f\xf0\x2f\x80\x56\x70\x01\xc5\x73\xa2\xe6\x94\x2a\x3a\xf2\x28\x9c\x24\x2d\x74\xa8\x3e\xa5\xda\xed\x79\x14\xa1\xa7\xe6\x42\x77\x77\x15\x8c\xab\x8d\x22\xdd\xde\xab\xdc\x92\xbc\x97\xb5\xd4\xd6\x37\xa7\xe8\xc6\x9e\x92\x64\x34\x8a\x0a\xb3\x09\xde\x9a\x46\x3c\x34\x56\x56\x2d\xb5\x7a\x23\x66\x24\xe9\x0f\x08\xf5\x54\xbe\x50\x2c\xa8\xcf\xd3\xae\x05\xb1\x90\x4a\x23\xd8\x5c\xa2\x54\xcf\xac\x83\x97\xc1\xee\x73\xee\x19\x7d\x75\x4d\xf7\xf4\x65\xbf\x38\xef\xa9\xf9\x97\x96\xb7\xc2\x51\xf5\xca\x8c\x19\xab\xf7\x5d\xba\x27\xd5\x9b\xba\x70\xe7\xbe\xd7\xfe\xf0\x90\xf6\xe2\xbb\x9f\x9f\x37\x63\xc7\xf7\xff\xeb\x28\x13\x86\x9b\x99\xc8\xb8\x91\x6f\x86\x46\x3d\xa6\xfd\x72\xbf\xf6\xfa\x25\x57\x7c\xfe\xc4\x37\xc6\x74\xcd\xce\xc0\xf3\x7f\x05\x99\x86\xd8\x9b\x17\x6a\x47\xb4\x77\xb4\xe6\x2f\x1e\xbe\xe0\x6b\x90\xe0\x0f\x97\x02\x60\xd9\x47\x7c\xe3\xa7\x34\x9b\x80\xa4\x54\x06\xe0\x8d\xdd\x22\xb8\x48\x0d\x91\xe2\x4e\x20\x89\x82\x49\x94\x2f\x14\xbd\xec\x85\x40\xae\x7f\xf2\x17\x1d\x26\x75\xa7\xa2\x53\x77\x22\x8b\x98\xe5\x2d\x8a\x12\xcf\xf0\x16\xa5\x78\xa9\xe7\xad\x0a\xc9\x91\xd2\xff\x35\x65\xfc\xf0\x3b\x63\x91\x54\xce\x47\xe4\xef\x54\xd9\x4b\xca\x1b\x44\x33\x12\xf8\xcd\x12\xa9\x12\x51\xfc\x01\xfa\x2e\xb5\xc9\x4a\x84\x01\x42\x84\x8d\xb1\x91\xa5\xb0\x7e\xac\xd5\x02\xe5\x6a\x18\x8d\xdb\xbe\xbf\xbd\x1b\xb6\x4e\xd6\x0e\x7d\xaa\xbd\x5d\x6b\x7d\x5d\x7b\x82\xeb\x1b\x78\x60\xde\x0e\x78\x18\x2e\x19\xd8\x35\x6f\xfb\x9d\x70\x2d\x6c\xd7\xee\x1e\x78\xfb\xb7\x70\xbb\xb6\x98\xbc\x23\x3a\x5f\x91\x0c\x42\xe0\x29\xfa\x8e\x20\x89\x72\x52\x12\x97\xe0\x52\x39\x5b\x48\x64\x69\x2f\x7a\x0e\x02\xf2\xd1\x2a\xa7\x52\x2a\x14\xf2\x2a\xc3\xeb\xd4\x94\x81\x43\xaa\xab\x88\x79\xf2\xe1\x4f\x27\xd3\x2c\x1b\xe1\x33\x92\x44\x55\xa1\x7c\x46\x2c\x77\x14\x49\x62\x96\x91\x58\x4a\x2a\xc9\x2b\x84\xd8\x88\x5c\x6d\xf8\x4a\x73\x71\xac\x41\x39\xc9\x29\x71\x76\x82\x9d\x61\x39\xde\x6a\x93\xe4\x02\xeb\xa4\xce\xe6\x84\xdf\x2e\xc1\x42\x24\x9e\x15\x5d\x6a\x40\x31\xf6\x3e\x61\x48\x2f\xda\x45\xc9\xbf\xd7\xc3\x96\x7a\x18\x6b\xd1\xde\xae\xd4\x19\xc3\xb4\x99\xef\x6c\x38\xff\xfa\x1b\xfa\x97\x73\xe2\xfb\xfd\xfd\xef\x6f\x3a\xf8\xfc\xdf\x4e\x70\xe2\xf1\x8f\x48\x67\x13\xb6\x4f\x07\xd1\x37\xac\x07\x65\xa0\x06\x1c\xd6\xbb\x11\xca\x8d\xda\x0d\xc3\xa7\x52\x2a\x10\xf2\xaa\xb5\x2c\x99\xcc\x40\x40\x3a\x28\x39\x5b\x1c\xb1\xc9\x5c\xc4\x41\xbb\x14\x74\x74\xae\xef\x90\x1a\x2c\x88\xd6\xba\x8b\xc2\xbb\x5b\x8e\x90\xb2\x1a\x62\x9b\xdd\x28\xd0\xcf\xab\x5c\xf9\x51\x37\x8a\x15\x53\xf6\xc7\xc4\x2c\x1f\x23\x86\xc2\x57\x83\x80\xc9\x91\xb5\xe1\xaf\xbc\x49\xe1\x9f\xb1\xc5\x4a\xf2\xf1\xb6\x40\xcc\x20\xec\xc7\xf6\x0b\x94\xc5\x4a\xc3\x8a\xaa\x20\x0e\xd4\x65\x82\x98\xd5\xcd\x18\x29\x97\x64\xd5\xed\x4b\x97\x18\xf2\xe4\x55\x1f\x4b\xc7\xa8\x8f\xe3\xb0\xa9\x09\x56\x25\xb4\x77\x5a\x7a\xd6\xe3\x00\xee\x67\x4f\xbd\x1c\xec\x39\x60\x24\xeb\xd9\xd5\xef\xbd\xf0\xc2\x7b\x7f\xa4\xb1\xdb\xfd\xdb\xbb\x57\xc1\xcd\x03\x4f\x1b\x19\x7b\xd2\xcf\x79\xe2\xb0\x70\x11\xff\x32\xa8\x01\xb7\xeb\x91\x76\x4d\x2a\x53\x49\x10\x52\x83\x3b\xb1\x5c\x6c\x3e\x27\x2a\x95\x82\x2b\x8e\x62\x84\xbb\x0d\xb1\xc9\xac\xa3\x52\xb0\xc6\x89\x85\xc1\x21\xb5\xc6\x93\x47\x35\x25\x5d\x59\x11\xda\x02\x68\x1a\xdb\x68\xc5\xaa\x11\xb3\x6c\x0d\x43\xa2\x5f\x9a\x00\x8f\xe9\x09\xf0\x08\x49\x80\xd3\xc4\x37\xa9\xd0\xeb\x4d\x71\x32\x5d\xc8\xea\xf4\x24\x83\xc5\xd4\x96\x8c\x45\x81\x44\x95\xe6\x61\x72\xf5\x81\xb9\x70\x1d\xb4\x7f\xf7\xa5\x65\x97\x3f\x70\xc3\xa6\xb7\xda\x19\xb9\x75\xe0\x13\x61\xd3\x95\x33\xef\x5e\xff\xe8\xef\x34\xed\xaf\xdc\xb3\x84\x69\x03\x06\xe1\xb8\x96\x31\x5f\x9c\x93\xd9\xae\xc5\x52\xb7\xfe\xb8\xba\x89\x32\xe9\xdb\x7b\x06\x28\x57\x5b\xed\x89\xc3\x16\x2f\xb7\x12\xd4\x82\x1d\xba\x4d\x6a\x0d\x9b\xd8\x06\x55\x06\x5c\xb6\x7c\x8e\xad\xa9\xd4\x5b\xaf\x58\x0b\x65\x51\xab\x33\xeb\x03\xb5\xc5\x81\x57\xad\xab\x60\x13\x57\xb1\x66\x04\x05\x33\xd4\x8a\x59\xb6\x16\xdb\xa4\xa6\x96\xda\xa4\x66\x90\x4d\x6a\x70\x98\x19\x26\x61\xa6\xea\x62\xf5\xf2\x96\x59\x0e\x28\x4d\xc1\x14\x52\xa0\xad\xa3\xdb\x63\x14\xa3\xf8\xcb\x49\x30\xf6\xe4\xde\x1b\x17\xb6\x2e\x9b\x34\xe7\xea\x7a\x78\xc1\x28\xed\x4e\x66\xd1\xd7\x3a\xd6\x9c\x75\xe7\xbe\xe7\x7f\xcb\xbd\x48\x70\x8b\xaf\x7f\x34\xfd\x3d\x7f\x6c\xf9\x92\x3f\x96\x05\x16\x9f\x13\x4b\xfc\xf3\x8c\xdf\x3e\x53\x57\xad\xb5\x90\xb3\xea\xd5\x00\x70\xef\xf0\x07\x80\x03\x88\xe0\x7b\x06\xd3\x87\x60\x35\x98\x3e\x20\x92\x08\xc3\x82\xbe\x4e\x73\x30\x4e\x38\x11\x65\x7d\x98\x8f\x7f\x7a\xb6\x49\x30\x63\xeb\xa7\x3c\x1e\x40\xb5\x90\x70\xd2\x62\x33\x36\x6c\xab\x24\x67\xa0\x9d\x74\x46\x71\x92\xea\xf2\x10\x5a\x01\x4a\xa7\x88\x47\xcf\x3b\xa9\x2c\x2f\xa5\x54\x24\xbd\x00\x36\x98\xaa\xab\xb7\xac\x61\x1b\xe0\xaa\x03\xda\xfb\xdd\x2d\x57\x69\x7f\xd9\x90\xd0\x1e\x82\x2f\xbd\x16\x16\x5a\xf9\x03\x5f\x74\x33\x57\x0c\x6c\xc4\xff\xd8\xf3\x3e\xfd\xde\x1a\xa3\xa7\x6e\x1c\xc1\xc6\x78\xc0\x37\x8c\x2e\x66\x41\x8f\x9d\x49\xdb\xf2\xd0\x51\x48\x78\x03\xb2\x4a\x72\x16\xda\xec\x4e\xbc\xc7\x0e\xf3\x74\x59\xde\xe6\xf4\x90\x00\xa2\xe8\xf1\x58\xfc\x78\x6b\x99\xad\xf0\xe2\x03\xda\x87\xe9\xda\x39\xda\xdf\xcf\x69\xf8\x10\x9e\xbb\xbf\xc2\xce\xf5\x1d\xdb\x01\x77\x69\x0b\xf0\x3f\x66\xd5\x81\xf3\x4d\x9e\xac\x3c\x7f\x00\x28\xa0\x0c\xbc\x4c\x9f\x2d\x27\x38\x9c\x1e\x85\xc0\xe1\x18\x7d\xd1\xcb\xb1\x32\xe1\xb1\xb3\xbb\x52\x7a\x0f\x6e\xb0\x98\xf3\xa7\x48\x9a\xa8\x48\xc0\xcf\x60\x02\x0a\x99\x39\xe5\x97\x69\xec\xaf\xcf\x0c\x25\x40\x42\x0e\x11\xd9\xfb\xf1\xf2\xcf\x2a\xa4\x5f\x55\xa1\xf0\x57\xbb\xcb\xe8\x57\xa5\x79\x1c\x31\x8d\x9c\x52\x86\xf3\x10\x16\x3f\x87\x9c\xe1\xdd\x5e\xaa\x15\xa1\xfa\x02\x04\x81\x21\xe3\xd0\x0b\x6f\xa8\x50\x42\x01\xa3\x7f\xb2\x60\x17\xc2\xc3\x49\xa6\x0e\xbf\xba\x0d\xdf\x81\x7d\xb0\xcb\x9c\xc1\x0f\x36\x24\xb4\x7d\xda\xe3\x70\x81\xf6\xc5\xd5\xec\x84\xd7\xc2\xd6\x46\xc2\x90\x33\xb9\x30\x99\x74\x42\x7f\x77\xdb\xb9\xf4\x2c\x64\x99\xce\xf5\x01\x05\xf8\xc1\x1b\x43\x6c\x06\x87\xb5\x99\x90\x47\xde\xa4\xd9\xba\xec\xca\x67\x15\x42\x2d\x06\x5c\xa0\x89\x8b\x23\x90\xc8\x29\xf4\x13\x35\x61\xce\x41\xbf\x15\x59\x71\x50\x27\xe5\xfe\xce\x0f\x3f\x9b\xfc\x3f\x6a\x45\x3f\x01\x14\xb2\x24\x38\x31\x4f\xf3\xa6\x57\x51\xeb\xd5\xd7\xfe\x0d\x4a\x0b\xe1\x42\x0d\x5e\xf4\x98\x96\xef\x0a\xf6\x68\x47\x96\x95\x6b\xda\x4b\xd0\xa3\x7d\x7e\x2e\x2b\xdd\x54\x55\x0c\x45\x36\xfe\x31\xe8\x7d\x9a\x7b\xda\x0d\x80\x05\x10\x3e\xf2\x4a\xb0\x51\x7f\x9f\x5d\xa4\xc3\x9b\x30\xa6\xab\xe5\xba\xd2\x9b\xef\x90\xea\x15\x09\x2a\xcf\x0d\x09\xe8\xd7\x94\xe0\x7e\xf1\xd3\x9d\xa6\xca\xbb\xbf\x1f\x79\x71\x04\x06\x54\x85\xc8\x6c\x2b\x86\xcc\xb6\xd7\x87\x23\xa8\x72\xda\x19\x52\x81\x83\x70\x02\xc1\x02\x24\xa9\x9e\xe5\x6c\x34\x1d\x6b\x91\x54\xde\x4a\x5e\x6d\xa5\x13\xb6\xb3\xed\x11\x01\x56\xc2\x80\x12\x61\x9b\xa1\x2e\x83\x89\x8f\xce\x0a\xec\x39\xde\xbd\x67\xf3\x3b\xe5\xdc\xf6\xb0\x36\x7d\xf5\x37\x9d\x11\xed\xf5\x00\x9f\x68\xb6\xae\xd5\x7e\xb5\xde\xda\x7e\xe6\x88\xa7\xe0\xde\xad\x90\x63\x2a\xb6\x5e\x1f\x82\x6f\x6e\xdc\xa2\x55\xd5\x3c\xfc\xa0\xd6\x0d\x9f\x5b\x3c\x6f\xe0\x6a\x66\xcd\x19\x67\x6b\x29\x2e\xa7\x3d\x06\x27\xe3\xf1\xdf\x09\x00\xf7\x04\xc1\x63\x95\x1b\xe8\xf3\xac\xcb\xad\x78\xb1\xdb\x58\xb0\xdb\x84\xf4\x74\xb8\xf7\x10\x76\x07\x7c\x0c\x53\x88\x0d\x50\x79\x32\xe7\xa2\x8a\xa0\x95\xa5\x4c\x15\x04\x17\xec\xc3\x13\x8f\xe4\xfe\xfd\xfd\xcb\x3f\xdf\x4e\xef\x12\x5c\x0e\xc5\xe8\x80\xac\xd3\x23\xfb\x28\xb0\xc9\xf8\x44\xec\xa4\x78\x25\x39\xc3\x85\xc2\x64\x79\x77\x13\xde\x55\xa0\x86\xf0\xaa\xc7\xd9\xf0\xcd\x93\x99\x28\xc6\x36\xc3\x7a\x0a\xc7\x67\x61\xa0\x7d\xe9\xc3\x1d\xd7\x7d\xf7\x69\x3f\xfb\x7b\x9f\x76\xcf\x9c\xb9\xde\x5a\x2d\x60\x89\x54\x2f\xd4\xfe\x71\x41\x62\x4c\x68\x3b\x5c\x78\xe1\x7e\xb8\x72\xed\x55\x21\xb8\x7c\xd9\x32\x6d\x4b\xd5\xb5\x3f\xd6\x9e\x80\xa9\x19\x13\x04\xad\x03\x3e\xc7\x8e\x19\xa3\xed\x61\xb7\xfc\xe5\x2f\x74\x1d\xb2\xda\xf9\x7d\x20\x0a\x6a\xc1\xeb\xfa\x3b\xe5\xf6\xf9\xcb\xa3\xc4\x38\xd8\x3b\x20\x93\x4a\xa9\x31\x36\x9f\x63\x23\xc0\xe2\x8a\xab\xde\x80\xb1\x16\x51\x54\x58\xd4\x93\x47\xd1\x92\x60\xc0\x4f\x83\x01\xe4\xd3\x39\x3f\x8a\xf6\x40\x93\x60\x4b\xf7\xa8\x02\x0b\xb8\xb7\x1f\x45\xc5\x2c\x1b\xc5\x6f\x51\x24\x4a\xdf\x22\x6f\x20\x62\xbe\x45\x51\x49\x46\x15\x69\xd5\x07\x24\x39\xc7\xf1\x96\x6a\x52\x33\xf4\x48\xa8\x86\x00\x93\x6c\xb5\x64\x2d\x8a\x48\xb2\x6a\xab\x49\xa7\x55\x4b\x4c\x92\x75\x23\x92\xf5\x88\x1a\x91\x19\xec\x67\x11\xa5\xad\x3d\x82\xbd\x4d\x6f\xe8\x3e\x7e\xb0\x9c\xdb\x1e\xd2\xa6\xf5\x2d\x4a\xda\x88\xc7\x35\x27\xac\x6b\xb5\x17\xd7\xdb\xd2\x73\x1a\x9e\xd5\x9e\x7c\x3d\x39\x4e\xfb\xe7\x35\xec\x84\xad\x90\x21\xf1\x45\x0e\x3b\x5e\xdd\x59\x5b\xbf\x53\xf0\xbc\xd3\x17\x69\x09\xf8\xc2\x8a\xae\x81\x8d\xa6\xff\x91\x75\xeb\x71\xae\x0f\x54\x81\x28\x14\xa8\x8d\xf7\x62\xff\x0b\x56\x99\x1e\x48\x8c\x5c\xed\xcc\xe7\xd8\x4a\x6c\x64\xe4\x4b\x51\x04\x42\xcc\x5c\xb7\xaa\x06\xad\x5b\x55\xe6\xba\xe5\x85\xf1\x41\x6e\x1b\x35\xdd\xb6\x66\xf0\xea\xf5\xe0\xa7\x8a\x8e\x4c\x40\x3e\x2a\x75\x76\x32\xff\xe5\x51\x95\x98\x65\xab\x18\x02\x6f\xc2\xf3\x01\x32\x4e\x8f\x4c\xf0\x96\x2c\xf6\xe7\xca\xc2\x01\x81\x2c\x71\x21\x52\x75\xe1\x2d\xc1\x0a\xbd\x4a\xc8\x55\x47\x28\x46\xaf\x12\xcf\x4a\x04\xcf\x4a\x75\x61\x56\x14\x73\x56\x06\xb9\xb6\x3e\x27\x81\x76\xba\xe6\xed\x43\x7e\xf6\x2d\xaf\x76\xcf\xd7\xe7\x28\xb5\x5a\x80\x8f\x55\x2d\xd2\xfe\x49\x5c\x5c\x3b\xf2\x93\x78\x52\xd3\xce\x65\x5e\x5d\xf6\x28\x59\xfe\xa6\x62\x4f\xaf\xbe\xfe\x4e\xec\xe9\xd3\x27\x16\x3c\x1d\xce\xea\x6d\xd0\x52\xc4\xdf\xe1\x09\xa4\x25\x38\x64\xf9\x04\x9c\x06\xee\x03\x68\x46\x42\xed\x14\xf2\x68\x52\x92\x00\x65\x6d\x79\x34\x22\x91\x8b\x91\x1c\x0d\x44\xb3\x88\x73\x8f\x77\xe5\x33\xe3\xc9\x79\x63\xfc\x14\x5b\x1c\xb5\x24\xd1\x78\xba\x35\xb4\x8a\x79\x24\x56\x1f\x92\xd4\x66\x31\x8f\x6a\x93\xea\xe9\x30\xae\x5a\xc7\x4b\xf2\x04\x3b\xe7\x74\x29\xfe\xaa\x31\x93\xa6\xcf\xa8\x09\xa4\xd5\x56\x51\x92\x51\x3c\x8d\x9a\x25\x35\x46\x04\xd6\x3b\x67\x48\x32\xea\x26\x5d\x37\xa0\x95\x64\xad\xd4\x51\xc9\x74\x1a\x8d\x90\xb2\xc1\xaa\xba\x66\x6c\xbb\x98\x9c\x0d\x57\x94\xd7\xea\x2a\xe4\x9d\x90\x6a\xaf\x97\x92\x9b\xb6\xd7\xd5\xb7\xa6\xfc\x01\x92\xcb\xf7\x91\x68\xb9\x98\xec\x94\xd7\x4b\x8e\x6d\xf8\xa7\xcd\x30\xc6\x47\xeb\xe6\x2c\xfe\xcd\xdb\xab\x6f\x9c\x74\xdb\x03\x05\xfa\xd3\x1e\xf5\xd2\xe4\xd2\x5d\x17\x27\xe6\x2c\x5e\x32\x76\x7c\x63\xb4\xae\xf6\xec\xaf\xfd\xe0\xae\xb7\x9e\xb9\xe3\x6e\xed\x0f\xda\x53\xeb\xfb\x1a\xae\x98\xd6\x7b\x66\xfb\x77\x2b\xc5\x99\x63\xb4\x4d\xf7\x3d\x76\xd3\xe5\x5b\xe6\x47\xa4\xb1\xf3\xa6\x9e\xf5\x75\xca\x8f\xda\x7e\xba\xb4\xec\xe6\xe0\x65\x9d\xf3\x4f\xab\x97\x6e\xb1\x4f\x3e\x33\xf2\x8b\x95\x3f\x7d\xca\x65\x55\xee\xfb\xfe\xab\xef\x44\xc5\x50\x43\xe5\x4c\x9e\x6f\x78\x4f\x0c\x5a\x6f\x07\xf0\xc4\x4e\x2d\xc1\x35\xf0\xe7\x81\x59\xe0\xa7\x00\xcd\x4c\xa0\x69\x29\xb5\x43\xc8\xa3\x09\x49\xe4\x48\xa8\x4e\xbe\xc4\xf4\xa7\x13\x71\xe2\xb1\x54\xb9\x77\x2c\x95\x96\x4b\x79\xf2\x28\x25\xa2\x26\x6c\x72\xd1\x95\x47\x62\x42\x6d\x72\xe5\xd5\xd9\x78\x97\x1e\x8b\xcd\xce\x3a\x9c\x4a\xa0\xaa\x7d\xc2\xb4\x99\xd8\xec\x29\x51\x92\xb3\xf1\x51\x93\xbb\xb1\x3d\x9b\x0c\xdb\x77\xcc\x94\x64\x34\x99\xa8\x59\x81\x14\xe9\x64\x56\x47\xb5\x98\xb6\x6f\x1a\x6a\xfb\xb6\x82\xe9\x8b\xba\x33\x87\xda\xde\xec\xd6\x74\x43\xc1\xe8\x90\x48\x25\xfd\xc4\xf6\x51\x1c\x9c\x2f\x7c\xf5\x9d\xeb\x57\x8e\xee\xed\x45\x4d\xeb\x37\x2f\xa7\x3d\x9c\x9b\x57\x35\xcc\xdb\x75\x71\xe2\x6b\x67\x9f\xdf\xde\x39\xa2\x36\x56\x33\xbb\xf3\xc5\xd5\x9b\x1e\xff\xf6\xfb\x1f\x5f\xf6\x8d\x69\x9d\x53\xb6\x4c\xec\x9e\xe4\x91\x66\x8d\xee\xb9\x6f\xd1\xce\x5d\x9b\x6f\xdb\x13\x14\x63\xe3\x92\xa3\xc7\x1a\x6d\x9e\xa3\x95\x39\x6b\x82\x97\x75\x2e\x98\x51\x2f\xde\xea\x68\xe9\xec\x7a\x6c\xe9\x35\x75\xf6\x31\xbb\xbf\x7d\x6b\x6f\xd8\xd9\x14\x8f\x47\xec\x3e\xef\x7b\x52\x99\xf5\x2e\x72\xce\xc9\x00\x60\x79\x8d\xdf\x07\x2a\x61\x80\xd6\x84\x51\x90\x72\x39\xe5\xb0\xaf\xe2\x6d\x30\x57\x6e\x0f\xb1\xae\xb8\xea\x70\x53\x95\x12\xb5\x2c\x9c\x4c\x1a\xea\xaf\x34\x42\xa6\x05\x41\xd6\x95\x47\x6c\xc2\xc8\xc7\x86\x88\xde\x0e\x39\x6d\x3b\x61\xdc\x80\xc1\x28\x7a\x4b\xb9\x1e\x3c\x74\x79\xfe\x21\x0e\x83\x67\x1d\x42\xb5\x48\x96\x22\xbc\x2e\xf9\xfb\x09\x06\xd0\x11\x72\x2a\x71\x14\x14\xb3\xee\xa0\x0b\x9f\xc6\x6f\x39\x72\x97\xa1\x9b\xe7\xf3\x7b\xf1\x81\x3c\x28\x66\xcb\xf0\xcf\xf0\x6f\x87\xf1\x6f\x67\x7c\x7e\x6f\x31\x69\x25\xc3\xeb\x1b\xf0\x43\x0c\xef\x70\xcb\xbe\xb2\x70\x29\x84\x9f\xb5\x0f\x26\x84\xf2\xeb\xda\xdc\x24\x1d\xc8\x44\x48\x0c\x16\xad\xcb\x04\xfa\x60\xfd\xf9\xee\x15\x97\x49\x3b\x61\xf9\x4e\xe9\xa6\xdb\xa2\x4b\x61\xc3\x8a\xe5\x03\xff\xcb\xb7\x50\x7b\xf7\x6c\xcf\x1f\x8e\xb2\xe9\xf9\x97\xc0\x87\xb5\x48\x77\xcb\x92\xb9\xac\xf5\xf8\xe7\xd7\xdd\x05\xdf\x1d\xf8\x42\x63\xb4\xd9\x30\xf3\x2a\x99\x83\x2b\x34\xaf\xa5\xc2\x22\x83\x10\x78\x84\x62\x85\x91\x98\xd2\xf5\x06\x7d\x09\x54\x96\x22\xcb\x8f\xdd\xd4\x1f\x39\xb9\xcd\x89\x76\x39\x6d\xd2\x72\xd0\x02\x16\x72\xd2\x36\x0a\xc9\x55\x48\x0c\xdd\x45\xea\x20\x76\x0e\x05\x08\x2b\x8d\x9f\x2e\xe8\x01\x31\x6b\x0f\x38\xa8\x38\xa1\xcb\xef\x24\xe2\x84\x4e\x43\x9c\xd0\x41\x15\x36\x9c\x38\x5e\xb1\xbb\x4c\x35\x73\xa0\xb2\xae\x21\x56\x0a\xc0\x08\x6c\x93\xa5\x88\x68\xf4\x39\x5c\x21\xae\x83\xf1\x75\xee\xb3\xce\x84\x15\xb0\x5a\xfb\xf3\xd3\x7b\x61\xd3\x36\xed\xf1\x63\xe7\x6a\xff\xb5\xe4\xe0\x5b\x70\xd9\xd4\x39\xcc\xe2\x81\xdb\x3b\xc6\x9f\xde\xcb\xf3\x5d\x5f\x3c\x53\x0d\x55\xb8\x4f\x5b\xac\x35\x1d\xf1\x6b\x2d\xf0\x55\xdf\xb3\xff\xaf\x69\x13\xb3\x45\xbd\x80\x78\x2c\xbd\xc6\x58\x0c\x2c\x46\xb9\xad\x30\x16\xbe\x30\x16\x57\x61\x2c\xae\xc2\x58\xb2\x78\x2c\x27\x19\xca\xa0\x0e\x41\x3a\x14\xa1\x3d\xa2\x13\x66\x94\xb4\x09\x36\xcc\x99\x75\xfa\x95\x51\x6d\x0d\xd3\x00\xaf\x9a\x35\xe3\xb4\x35\x25\xdd\x82\x4f\x9c\xb5\xe4\xca\x6f\x55\x7c\x52\x7e\xde\x85\x6b\x0c\xfe\xb7\x27\xf8\xa7\x40\x19\xe8\xa4\x4c\x12\x19\x37\x43\xa9\x92\x94\xc2\x31\x14\xd2\x53\x26\x4d\xad\x96\xa5\x81\xaa\x94\x49\x72\xc6\xc2\x4b\x7a\x7b\xb8\x48\x93\xa9\x01\xaf\x90\xea\x84\xed\x4a\xd1\x82\x09\x23\x0f\xc3\xfa\x14\x2f\xd8\x94\x99\xd2\xfb\x0b\x2f\xdf\x74\xf6\xdc\xa9\xa3\x9b\x26\x2c\x48\x0d\x1c\xd1\x32\xfc\xbe\xe3\xe8\xa6\x19\xf3\xc7\x3e\x12\x85\x7f\xfc\xe5\x2d\xd3\x2b\x3e\x57\x16\x9c\x7b\xec\x38\xcd\x25\x73\xbb\xb8\xa5\x20\x80\x9f\x29\x40\x4e\x31\x90\x3e\x93\x6c\xcf\x1b\xbd\xb7\x90\xa2\x12\xe8\x33\x61\x9b\xc9\x01\xf2\x4c\x62\x9a\xe6\x7a\x3d\x7a\x82\xb7\x02\xa6\xda\x8a\x1e\xc9\x0d\x61\x64\x29\xac\x6f\xe2\x6c\xd5\xe3\x37\x4e\x5a\xba\x66\xde\x69\x63\x1a\xeb\x62\x1d\x4d\xda\x45\xda\x63\x5c\xdf\xc0\xbe\x79\x73\xc6\xcd\xff\x1e\x0c\x6e\x5c\x3b\x2e\xf4\x91\x32\x6a\xee\x80\x04\x58\x6a\x23\x61\xa5\x8e\x15\x3c\x63\xa8\x9d\xf0\xb4\xd6\xa7\xd4\x30\x97\x47\xb1\xa4\x01\x16\x84\x3a\x42\x90\xe4\x39\xca\x82\x21\x12\x23\xfd\x0b\x86\x33\xf5\x4b\x6a\x8d\x0f\x27\x37\x65\x18\x86\xeb\x4e\xdf\x36\x6d\x03\x9c\x0f\xc3\xb5\xa7\xdf\x35\x6d\xc3\xf0\xb6\x15\xfa\x7c\xdb\x6e\x0a\x4e\xf9\xe9\x14\xdf\xed\xb7\xe9\xba\x85\xc4\xd6\x96\x08\x08\x80\x6a\xd0\x80\xc7\x36\xd8\xde\xa8\x32\x81\xea\x52\x6a\x88\xcb\xa3\x68\x12\xa2\x46\x73\x6c\x71\x63\x6c\x81\xb2\x20\x19\xdb\x57\x9f\x00\x76\xc8\xd0\x4e\x36\x25\xdd\x83\x07\x36\xec\x1c\x59\x9c\x43\xc6\xb5\x46\xf3\xda\x7b\x75\xbe\xdd\x24\xb8\xba\x68\x8d\x21\x6d\x2f\x06\xed\x6e\x26\x06\x09\xf9\x06\x1a\x45\xc0\x7c\x10\xa5\x86\x61\xe1\xc5\xcb\x71\x4c\xe7\xcb\x18\x5d\x4c\xc8\x8b\x04\x49\x2d\xc7\x41\x5d\x4c\x56\x2b\x47\xa5\xd3\xa8\x46\x42\xd1\x34\x50\x1d\x95\x84\x1c\x42\x8d\x8d\x92\xe4\x9c\x00\xdc\xbe\x7a\x5a\x86\x3a\x05\x65\x2f\x1c\xbe\xb0\x77\x4a\x26\x5f\xf6\xda\x93\x57\xf9\xbe\x84\xe5\xf7\xf8\xe4\x61\x9b\xfc\x48\x8f\x9f\xf5\x2f\x7a\x6f\xf3\x28\xf0\xc3\xa2\xee\xe6\x6a\x6c\xb7\x08\x24\xd8\x47\xb3\xd5\x19\x35\x27\xd4\x72\x6c\xb7\x96\x61\x3a\x9e\xb1\xdd\x22\x30\xae\x46\x5d\x79\x35\x59\xdc\xfc\x8c\x04\x29\x13\x2a\x1f\x85\x1d\x25\x22\xa3\x66\x22\x71\x5b\x8d\xed\x56\x4e\xce\x17\xaa\xbf\x59\x92\xb3\x02\xa8\x1d\xa1\x57\xef\x4e\xd6\x1d\x7d\x12\xa3\x9d\xa4\x69\x9a\x99\x70\x8a\xa2\xe8\x70\x0d\xd5\x03\x60\xf8\x4e\x48\xca\xe7\xbc\x9e\x7f\xd5\xd2\x02\x82\xa0\x09\x5c\x08\x32\x0d\x10\xc4\x73\x02\x07\xec\x5c\x3c\xe3\x84\x44\x74\x2f\x57\x45\xbe\x42\xd4\x4c\x69\xa3\x44\x42\x1b\x55\x83\xe3\x27\x31\x4f\xf9\x57\x42\x78\xcd\x97\xec\x74\xcd\xaf\xf2\x4a\x72\x56\x0a\x54\x44\x70\x78\xda\x20\x65\x81\x2b\x54\xa3\x23\x89\x39\x7b\x7d\xdc\x34\x45\x3b\x81\x20\x04\xfc\x32\xe9\x3e\xa4\x65\x84\x3a\x42\xc8\x8a\x4f\x01\xc4\xa1\xea\x89\x3e\x30\xb3\x66\x37\xac\x7b\xc2\x3d\x79\xe2\xb8\x09\xcc\x2b\xef\xff\x44\xfb\xdd\xd3\xae\x49\x13\xc7\x4f\xfc\xcd\xfb\xb0\x7d\xc1\x9c\xd6\xd9\x67\x44\x6f\x53\xe7\xcd\x49\xcd\xed\xa9\xba\x35\xc3\xcc\x7b\x1f\x5e\xfd\x97\x8a\xb6\x31\x63\xdb\xea\xb5\x57\xfe\xf1\x89\x76\x45\x3e\x3c\x66\x5c\xc7\x98\x11\xb0\xeb\xd8\xb5\xbb\xa3\x93\x26\xb5\xc2\xd3\xfe\xbc\x7a\x77\xed\x94\x69\x63\x34\x15\xd0\x1e\xf8\xad\xdc\x3e\x2e\x07\xbc\xa0\x1e\x2c\x01\xc8\x93\xc8\x85\xc8\x70\x51\x2c\x91\xe3\xf5\x81\x8f\x28\x26\x93\xaa\xd2\xa1\xf3\x0d\x30\xae\x56\xf9\xf0\xfc\xba\x58\x99\x0c\x3c\xe4\x91\xe4\xac\x4b\x26\xbb\x38\x8a\x49\x59\xbb\x0f\x10\xd5\x46\x5e\xce\xb2\x42\xa4\x56\x7f\x75\x00\x39\xe4\x10\x0a\x5a\x81\x74\x51\x37\xc3\x5a\x2f\x61\xd1\x0a\x60\x77\x20\x43\x76\xc3\x05\x50\xfa\x7b\xf9\x39\x0b\x7d\x3f\x7d\x4a\xfb\xef\xbf\x07\x2f\x69\x1b\xcf\x3c\xf0\x04\x4c\xf4\x05\xc6\x34\x9e\x5e\x79\xe6\xf9\x3d\xf1\x79\xf3\xca\xe7\x9d\x0f\x9f\x82\x01\x78\x61\xed\xac\x59\xd5\x5f\x3c\xa6\x7d\xac\xdd\x5d\x7f\x7e\xfb\xa8\xd8\x91\x7d\xb7\x8d\xae\xaa\xee\x6a\xf8\xfd\xcd\x77\xb6\xce\x9d\xdd\xf2\x47\xc0\xd2\xfa\xae\x75\x33\x48\x81\x69\x60\x01\xf8\x2b\xc8\xb4\xe0\x98\x3a\x9e\xc2\xcb\x08\x2a\x4b\x52\xba\xdf\x9a\x94\xea\xc0\xab\x64\x12\x4d\x4f\xe4\x66\x90\x93\x0d\xea\x4e\xa8\xed\xce\x7c\x76\x7c\x7b\xb7\x35\xae\x76\x39\xf3\x68\x74\x12\xa2\xb3\x8a\x35\x88\x47\xc3\x78\x6e\x9a\x0b\x48\x5c\x1c\x4d\x13\xd5\x59\x30\x9e\xeb\x25\xdf\x32\xb3\x7a\xf1\x21\x74\xd6\x74\x5b\x3c\x0b\x66\xcd\xb5\xc5\x51\x2f\xed\x5c\xaf\x17\xf3\xea\x42\x18\x57\x47\x7b\x48\x9c\x20\xb5\x60\x0b\x4d\x93\x32\x5e\x6b\x33\x7e\x8d\x66\xc9\x99\xf6\x6e\x01\x7f\xea\x95\xb2\x91\xb2\x38\x41\x85\x95\xcb\xb9\xca\x9a\xb1\x1d\x9d\xc4\xca\x0e\x49\x92\x73\xc0\xea\x8d\xd4\xeb\xd9\x6e\x21\x9a\x4e\xab\x33\xa6\x4b\x32\x5a\x90\x46\x5d\x92\x3a\xb7\x37\x9d\x46\xe3\x65\xf4\x8d\x62\x06\xe9\xa2\x42\x73\x7b\x25\x33\x6c\x8d\xb9\x8e\x16\x99\x21\x11\xe2\x60\xc6\x41\x21\x16\x6d\x66\x48\xd6\xa5\x95\xb2\x03\xeb\x38\x4c\x7c\x76\x5a\xf7\x00\x1c\xfb\x6b\xbd\x12\x7d\xee\x83\x17\xbd\x7c\xe6\xa3\x67\x35\x9c\xb1\xbc\xfb\xf2\xfd\xcb\xcd\x32\x74\x4e\x7b\xf4\xd0\xda\x07\x3a\x7b\xee\xbb\xf0\xbf\x8e\x32\x6f\xbb\xef\xfe\x41\xe7\x15\xab\xbe\x33\x21\xda\x90\x9a\xf6\xdd\x65\xbd\xf5\xf1\x94\x9b\x99\xde\x25\x2b\xc1\xca\xae\xce\x69\x3d\xf7\x30\x61\xe8\x87\x3f\xff\x2b\xa9\x54\x67\xb5\x47\x1e\xd7\x5e\xbf\xec\x9b\xbd\x67\x26\xfb\x61\xef\x0b\x66\x99\xfa\x15\x6d\xcc\xa7\xb3\x4f\xeb\x99\x0c\x47\x58\xc6\x6f\xbb\xb7\xae\xa9\xee\xc9\xe8\x88\x68\x6a\x9c\x76\xf5\x42\x77\x4b\xa3\x24\x5a\x9d\x15\xd1\xa6\xe4\xd7\x26\x5e\xb6\xd9\xe8\x0b\xb0\xcc\x13\xe6\x82\x91\x60\x02\x98\x0b\xf2\x20\xd3\xa8\x23\xf8\x3c\x24\xc3\x4c\x16\x3e\x54\x95\x52\x6d\x96\x3c\x0a\x25\xd1\xc4\x44\x6e\x12\x9d\xf3\x8e\x84\x3a\xca\x99\xcf\xb6\x8e\xea\xb0\xc6\xd5\x31\xce\x3c\x6a\x4a\x42\xf4\xf5\xe2\xb6\x81\x26\x18\xcf\x4d\xa0\x73\x3e\x41\x54\xa7\xc0\x78\x6e\x0e\x9d\xf3\x29\x73\xf0\x9c\x4f\x99\x88\xe7\x7c\xca\x69\xb6\x38\x9a\x43\xc3\x7f\xbc\x6e\xce\x83\x71\xb5\xc9\x25\xc9\xaa\xa7\x31\x9d\x46\x13\xa4\x1c\x27\xc8\x36\x82\x54\x9e\x22\x67\x46\x75\x58\xf0\x94\xcf\x91\x72\xde\xf2\xba\x71\x24\x1f\x13\x90\x33\xa1\xaa\x14\xd9\x8f\x6d\x1e\x3c\xe3\x82\x5c\x1e\xd5\x67\xdc\x52\x91\x4e\xab\x93\x26\x4a\x32\x9a\x9b\x46\x63\x24\xf5\xb4\x39\xe9\x34\x6a\x95\xd1\xe9\x05\x7e\x2f\xa1\x8e\xb6\xfe\xe3\xf9\xf6\xa7\x92\xb2\xc9\xf6\x55\x90\x1d\x8f\x45\xeb\x4e\x3d\xd7\x74\xaa\x17\xdc\xf0\xcf\xfb\x7e\xb4\xb4\x67\xfc\x8c\x99\xdf\x3f\xed\xf6\xf4\x9a\x39\xf3\xaf\xf9\xc1\x8f\x27\x75\x8d\x3b\x73\xdc\x0f\xaf\xcf\x3d\xb2\xe5\xd8\x4f\xf6\x5d\xb8\x61\xfb\xe3\x2f\x30\x11\x3c\xc3\x97\x5f\x7e\xc5\x84\x58\x43\x6a\xfa\xea\x65\xf3\xeb\xe2\xa3\xdd\xcc\x8c\x2e\x45\x0e\x56\xad\x9d\xde\x73\x3f\xdc\x79\x10\x7e\xe3\xa7\x9d\x2f\x37\x7c\xf7\xed\xeb\xdf\xe9\x9a\xbd\x19\x96\xff\xee\x92\xc5\x0d\x2f\x77\xbe\x7d\xf0\x90\xf6\xc0\xcf\x2e\xbd\xf4\x8f\xfc\xb4\x6d\x3b\xf4\x39\x1d\x3d\x4e\xbb\x66\xa1\x7b\x14\x9e\x53\x57\x45\xb4\x6f\x6e\xd7\x15\x1b\xe8\x5a\x4d\xde\x63\x61\x22\x68\x05\x93\xc1\x35\x5f\x82\xd4\x40\x13\x13\x68\x7c\x2a\xd7\x4e\x27\xb5\x5d\x54\x27\x3b\xf2\xea\xd8\x4e\x7c\x4a\xee\x1e\x0e\xc2\x31\x45\x87\x70\x3c\x44\x21\x1c\x6d\x63\xc8\xcb\x66\x17\x89\xe9\x29\x7c\x43\x9d\x4c\x21\x1d\x6a\xfb\x44\x49\x56\xdb\xd2\xff\x3e\x90\x03\xb6\x47\x3c\x30\x56\x1f\x13\xc8\xbf\x7f\x1d\xd6\xf1\xba\xc2\x36\x29\x2b\xa7\x04\xd7\x4f\x99\x8a\xff\xfd\x8b\x30\x0f\xfe\xf5\xde\xde\x3d\x17\x5c\x70\xc1\x05\xd8\xa6\x04\xef\xc1\xff\x05\xf8\x41\x0d\x78\x63\x58\xc4\x07\x8a\x26\x50\x45\x2a\x57\x46\x2d\x59\x26\xaa\x35\x8e\xbc\x1a\xae\xd2\xe1\x9c\xa7\x84\x82\xd4\xfd\x8f\x43\x41\x72\x9c\x2f\x50\x16\xd3\xb7\x53\xd9\x4b\x7b\x74\x5c\x52\x46\x0a\x56\x92\x77\xc5\x44\x85\xa8\x65\x51\x49\x56\x03\xa1\x53\xe0\x43\x4a\x67\xe1\x94\x68\x11\x38\xa3\xd4\xe2\xa7\x42\x8f\xf0\x5b\x4c\xf3\x02\x88\xe3\x57\x5d\x13\xe0\xfb\xc0\x94\x02\x40\xbe\x04\xf2\xa7\x72\x32\x07\x04\x2e\x8e\xac\x89\x22\x51\x00\xbc\xa9\x90\x7c\x3c\x65\xf9\x28\x66\xe0\x77\x17\x27\xdf\x81\xea\x0d\x34\x37\x43\x72\x25\x36\xf2\xf9\x89\x3a\x36\x50\x65\x1f\xed\x0b\xb0\x4a\x2a\xf0\x7c\xa9\x9c\x00\x1b\x51\xea\x98\x35\xaf\xc0\x85\x7f\xd6\x85\x9f\xaf\xf9\xcd\xda\x4d\x37\x5c\x7a\xe3\x0e\xed\xd5\xa5\x1f\x0c\x30\x11\x68\x83\x07\xfe\x42\x34\x9f\x77\x69\x07\x0e\xdc\x75\x67\xcd\x00\x80\xbf\x73\xc3\x3a\xd2\xbb\xa0\x79\x49\xef\x02\xc1\xa9\x1b\x2d\x0b\xc8\x9b\x40\x8a\xc9\xac\xe4\xf6\xe4\xb3\x5e\x37\x18\x84\x3e\xbf\xfd\xc8\x03\x43\x8a\x32\xf8\xc1\xf1\x80\xf0\x95\x96\x5d\xdc\xa4\x0e\x07\x54\xbb\x57\x92\x33\x40\x10\x69\xed\x79\x58\x86\x13\x83\x12\xa0\x94\xdf\x04\x9d\x77\xe1\x0e\xed\xb5\x8b\xb7\x3d\x58\xc2\x6f\xf2\x44\xd3\x80\x15\xfe\xde\x7b\x88\xf6\xfe\x2f\x3b\xf1\x05\xb7\x9a\xb7\x03\x05\x48\xb4\xab\x0e\x22\x6f\x02\x1f\x18\xc0\xa8\x16\xa5\x9d\x57\x6a\xdb\x79\x25\xc0\xf2\x42\x2d\xf9\x57\xaf\x2c\x9b\x0a\xab\x9e\xd5\xfe\x3c\x0d\x56\xec\xbb\x6a\x1f\xac\x9a\xa9\xbd\xf7\x3c\x2c\x9f\xa6\xbd\x9b\x5b\x97\x63\x62\x6b\x76\xc2\x05\x3b\xd7\xee\x84\xe9\x19\xda\xd3\x3b\xd7\xec\xd4\x76\xed\x5a\xb3\x53\x7b\x6e\x26\x1c\x47\xfe\x16\x6c\xe2\xd6\x70\xd3\xf9\x97\x81\x04\x46\x02\xe4\x4a\xe4\x58\x0a\x2f\x74\x11\x11\x46\x97\xc7\x16\xcf\xb0\x2e\x7b\x3c\x0b\x58\x8b\x2d\x0e\x91\x9c\x50\x15\xf2\x18\x70\x74\x5b\x2a\x62\x20\xd9\x23\x64\xdd\x6e\x9a\xde\x05\x1f\xa9\x9a\x9f\x1a\x35\xbd\x43\x9b\x16\x9d\x3f\x2a\xc9\xbd\x3b\x7e\x4e\x5f\x6b\x7c\xf2\xd7\xfa\xf4\xbf\xd5\xc5\xbd\xc1\xcd\xb5\x78\x81\x17\x24\x01\x9e\x12\x47\x4a\x85\xce\x7c\xd6\x03\xbd\xd6\xb8\x6a\x71\x52\xbe\x6b\xd7\xa1\x9c\x8d\x6c\x5d\xd8\xe5\x80\xea\xf1\xea\xa2\x82\xb0\x9d\xe6\xa2\xfd\x3e\xaf\x10\x6b\xc7\x21\x3a\x13\x83\x5d\x0d\x81\x6f\x6f\xf9\xd1\x82\x4b\xae\xb4\x3e\xc4\xce\x6e\x9c\x7f\xd9\xe6\x3e\xee\xcd\xa7\xc6\x8f\xff\xce\x8a\x96\xda\xaa\x39\xd1\x86\x28\xf9\xbb\xcc\x02\xee\x29\x76\xa3\xa5\x17\x48\xa0\x85\x44\x93\x2c\x07\x1c\x1c\x19\x0d\x02\x87\x72\x4e\x17\xfe\x96\x71\x02\x3c\x4c\xa7\xc5\x16\xcf\x4e\x70\x7a\x6c\xf1\xa2\x81\x52\x22\x3d\x3c\xa7\x01\x5f\x33\x64\x16\x5c\x38\x6f\x7c\x5b\xb4\x36\x58\xb1\xf0\xca\x1b\xf9\xed\xb3\x2f\x6a\xab\xab\x18\x21\x39\xc2\xa1\x31\x81\x79\xd6\xd5\xf8\xef\x8d\xe3\x9e\x60\x37\x5b\x7a\x81\x88\xff\x1e\x48\xe4\xa0\x9e\x93\x96\x12\x88\x3b\x94\xf3\xd0\x8d\x99\xf3\x60\x0b\x73\x00\x6f\xcc\x9c\xdd\x16\x57\x65\xfa\xf7\x06\x6f\x76\xcc\xb8\x19\xa7\xe1\x98\x64\xed\xb4\x1e\xee\x09\x7d\x0b\x72\x56\xe2\x2d\xe8\x1f\x00\xc0\x13\xf3\x2c\x5e\xe6\x6a\x61\x2e\x50\x40\x1d\x40\x62\x42\x65\x9d\xf9\xac\x95\x15\xad\x71\xd5\xe1\xcc\x23\x90\xd4\x25\x49\x72\x0a\xf9\xab\x60\x54\x0b\x3b\x64\x7f\xdd\x33\xcc\x36\x69\xf1\x16\x6d\x7d\x00\x58\x41\x83\xf6\x84\xf0\x04\xbf\x95\x9c\x79\x1b\x40\x3b\xe8\x06\x73\xc1\x62\xb0\x1c\x5e\x03\xd0\xe8\x44\xae\x89\x7a\xcd\xe8\x26\x3c\xa6\xd1\x8d\xb6\x38\x1a\x95\xc4\x6f\xdb\x19\xa9\x9c\x44\xd7\xe8\xe9\xc9\x4c\x99\x84\x7f\x5a\xe6\xb6\xc5\x33\xde\x29\xa7\x25\x93\x49\x64\x4f\xa0\x8b\x52\xba\xcb\xa1\x73\x93\x19\x3b\xf1\x3a\x3b\xb0\xc5\x33\x96\x73\x96\xe2\xdf\xa8\x4b\xa0\x45\xa9\x5c\x15\xfd\x8d\x9e\x64\xa6\x8e\xa8\x7d\xd5\x95\xdb\xe2\x99\xe8\xd7\xe7\xe3\xdf\x98\x98\xc8\x8d\xa5\x7f\x7d\xe2\x58\xfc\xb3\x89\x63\x6c\x71\xd4\x91\x84\xe8\x52\x32\x6e\x17\x99\x5d\x1c\x22\xe9\xb5\xd8\x30\xbd\xd1\x90\x44\x61\x52\x15\xc8\x59\xe8\x0d\x0b\x39\x92\xa3\x58\x32\xe7\xa5\x37\xa2\x49\xe4\x15\xd5\x46\x18\x47\x63\x92\xb9\x76\x7a\xaf\x3b\x89\xb7\xed\x16\x18\x47\x9d\xc9\xdc\x28\x7a\xaf\x23\x89\x46\x91\x90\x0b\x7d\x3d\x99\x9b\x4b\xef\x2d\x4e\xa2\xb9\xa2\x7a\x0e\x8c\xe7\x96\xd3\x1b\xcb\x49\x20\x8e\x16\x24\x73\xa7\xd1\x1b\xf3\x93\xe8\x34\x51\xbd\x00\xc6\x73\x4b\xc9\x0d\x75\x05\x8c\xab\x61\x7c\x88\xb5\xb3\xe9\xb4\x6a\x11\xf0\x81\xad\xac\xaa\x0e\xef\xf1\x2d\xed\x92\xac\x36\x8d\x4d\xa7\xd5\xe5\xe7\x48\x72\xf6\x8c\x9e\x45\xd3\xf1\xed\xd3\x66\x49\xb2\x7a\xee\x45\xa4\x9f\x47\xa1\x07\xb7\x18\x85\xf5\x94\x7e\x63\x4b\xbe\xc1\xd2\x9f\xb5\x9d\xfc\x47\xa5\xff\xc9\xe2\x5f\x6c\xe0\xcf\xbf\x60\xe1\x4a\xcb\x1c\x7e\x7c\xf7\xec\x24\xbf\xb4\xe4\xdb\xac\x92\x6f\xf0\x08\x7f\x1e\xfe\x7a\x06\x3f\x7e\xca\xec\x24\x7f\x9a\xe3\x99\x45\xdf\x14\xf4\x2f\xf0\xf3\x53\xfc\x3f\xae\x74\x3c\x6b\x7c\x49\xf1\xf0\xc5\x05\xcb\x96\x2e\x6c\x8a\xd7\xb7\x68\xce\x05\x17\x2e\x5d\x84\x3f\xb1\x6f\x19\x9f\x8e\x79\xe6\x5f\xb8\x74\xe1\xc8\x91\x0d\x09\x8b\xfb\xc9\xf3\x17\xe1\x0f\xc7\xac\x43\x7f\x4d\x0b\x3e\xb9\x6c\xc1\xc8\x91\x23\x46\x01\xea\xcf\x57\x09\x6b\xf9\xd7\x80\x00\xdc\x24\xbb\x5a\x07\x9a\x40\x2b\xe8\x00\x97\x01\xd4\x96\xc8\x8d\xa1\x0e\x07\x93\x88\xaf\x3e\x24\xe1\xa0\x8d\xd5\xdf\xe1\xce\x04\x0a\x1c\x42\x55\xc9\x5c\x25\x9d\xc7\x4a\x51\x8d\xc2\x78\x2e\x46\xbf\x85\x93\x6a\x17\x8c\xab\x95\x01\x49\x56\x83\x75\xe9\xb4\x1a\xc3\x3b\x7e\x88\x14\x96\xdb\x78\xda\xaf\xcd\x4a\x2a\x18\x97\x4e\xa3\x31\x32\x6a\xc7\xdb\x46\xab\x3f\xe0\x13\x9a\xa1\xd2\xd6\x1e\xf0\x5a\x04\xa5\xdd\x1f\x10\xa2\xcd\x10\xb6\xb5\xa7\x02\x6e\x88\x67\xa1\x3d\x65\x11\x62\xfc\xe8\xb6\xf6\x80\x45\x60\xdb\x03\x95\x30\x20\xd4\x29\xad\xed\x95\x30\xe0\xab\x6b\x78\x7b\x9d\x7b\xd2\x2f\xbf\xfd\xd8\xc5\xe7\x3e\xba\x49\x99\xbc\x66\xd6\x12\x69\xcc\x1c\x46\x69\x95\x36\x39\xa4\xa9\x35\xe7\x28\x33\xaa\xce\x19\x2d\x6f\x82\x07\x1e\xbc\x7d\xca\x87\x5d\xe9\xc5\x4a\xdd\x82\xc0\xe4\x1b\x6e\x74\x4f\x7b\x7e\xe2\xdb\x4c\xeb\x39\xf4\xd7\x06\x1e\x5e\x75\xc6\xe2\x40\x5f\x8a\x6f\x9a\xfa\xec\xb9\x4b\xce\xec\x3f\x7a\x8c\xfc\x37\xcf\xb0\x70\xd3\x9e\x9f\xf8\xfb\x1f\xac\x0d\x9c\x35\xa6\xfb\xf6\xe6\xe3\x8f\x2f\xe1\x26\x3d\xd9\x31\xf5\x0f\xf0\x1f\x9b\x1c\xf8\xbf\xdb\xaa\x6b\xce\x6a\x3d\x96\xe9\xc2\x26\xa0\x80\x1a\xf0\x89\x8e\x80\x73\x17\x2b\xf5\x45\x13\xb9\x10\x7d\x3f\x43\x51\xfc\x7e\x86\x2a\x6d\x71\xe4\x2f\xe9\xbb\x21\x8d\xf1\xb9\x32\x52\x7e\x1e\x82\xfe\x2b\x95\xe7\xbb\xfb\xc8\x13\x94\xe0\xc1\xdd\xec\x46\x52\xbf\x6a\x0b\x1c\xe5\x87\x57\xe8\x23\x9a\x35\x92\x12\xcf\x8a\xf8\x3a\x48\xa1\xcf\xe3\x96\x24\x39\x8d\x77\xf2\xbd\x2c\x6f\x93\x0c\x1d\x36\x38\xc1\x06\x58\xde\x6a\x73\x9b\x77\x8c\x68\xcf\x4b\x84\xfa\x14\x83\xb7\x4b\xb5\xcb\xe9\x62\x5d\x3e\x36\x02\x23\x30\x56\xd0\xe6\x3b\x99\x34\xdf\x00\x6c\xd1\x9e\xd7\x76\x41\xcb\xdf\xa9\x40\xdf\x06\x0e\x3a\xd8\xdd\xe7\x5d\xe2\x1f\x22\xd0\x77\x6c\xde\xc0\x2c\xb8\xdb\x14\xe9\x5b\x18\xf4\x27\x36\x9d\x75\x76\x31\x5e\x7e\x05\x77\xc4\xd2\x05\x42\x20\x0e\x5e\x28\x61\x54\x42\x0d\x89\x5c\x94\x5a\x3c\xda\x80\x2d\x1e\xad\xb3\xc5\x51\x45\xd2\xe8\x1a\x2e\xe5\x93\xe1\x44\x54\x5d\x7d\x48\xc2\xcb\x62\x1d\x76\xe0\x44\xae\xba\x98\xd9\x14\x29\x49\x82\xbd\x68\x3a\x25\xf9\xd2\x70\x14\x4b\xa7\xa2\xe4\xc9\xd8\xca\x2a\x08\x72\xa5\x5a\x92\xf7\xca\x5e\x9f\x3f\xda\x80\x8f\x36\x43\xc1\xf4\x29\x18\x51\x86\x23\x47\x85\x43\x48\x96\x1e\x3f\xae\x7d\xac\x1d\x7c\x73\x9f\x97\x30\x2c\xfd\x9e\x33\xda\x10\xa4\xe4\x89\x3f\x3c\x77\x68\x10\xda\xfe\xf8\xba\x81\x1b\xe0\xd6\xdc\xf3\xf7\xf1\x57\x05\xfd\xa4\x11\xe1\xc9\x9d\x77\x16\x34\x94\xe7\xea\x18\xeb\xc7\x28\x86\x58\x4f\xc4\x1b\xfa\xb7\x39\x47\x48\xe6\x5d\x24\x66\xce\xb1\x0c\xf9\x48\xdb\x96\x8a\xe5\xff\x03\x54\x4d\xab\xdc\x6c\x9d\xb9\xc7\xd0\x8c\xb5\x10\xcd\x58\xc5\x47\x84\x6f\x79\xdf\xd1\xc1\xdd\x48\x86\xb2\x7f\xd6\x4e\xae\x0e\x72\xa5\x82\xfe\x13\xec\x80\x76\x1d\x39\x06\xa3\xab\x3d\x01\x53\xa9\x98\xa0\xab\x3d\x45\xbd\x45\x29\x21\x26\x0c\xd6\x89\xf8\xd3\xad\xed\x37\x56\xc3\x64\xe4\xf3\x31\xff\x88\x94\xc8\x45\x70\x11\xed\xb6\xdb\xb4\x6d\x05\xc5\x08\x00\x58\xb0\xf2\xc4\x61\x2e\x68\xf1\x82\x32\x50\x0b\xea\x20\xd0\x3b\xfa\xcb\x0d\x9e\x77\xd6\x99\x4a\xa9\xbc\x33\xaf\x5a\x6c\xc9\x64\xa6\x0e\x82\x78\x2e\xe2\xf1\xf3\x14\x50\x8d\x84\x04\xb2\xa6\x74\x36\x3e\xc4\x25\x49\xad\xb7\x36\x69\x80\xab\x65\x4f\x81\x77\x6f\xcb\x91\x2b\x69\xbd\xb1\xb6\x19\xbf\xd3\x6e\x95\x29\x3f\xca\x23\xa1\x3f\xcb\x32\x82\x12\xcf\x5a\xf0\x15\xd5\x8a\x59\x5b\xad\x55\x89\x67\x9d\xf8\x6a\xb4\x66\x3a\xb2\x2e\x72\x33\x46\xae\x35\xf8\x9a\xa9\xa9\xb5\x16\xb5\x23\xc5\xd2\xc8\x95\x06\x39\xc6\x15\xab\xa9\xd5\xdf\x75\x3b\xc3\x5a\x04\xab\xcd\xe9\xa2\x8d\x73\x83\xd1\xd6\x1e\x3f\x65\xeb\x73\xd8\x4d\xb4\xb5\x6c\x52\xa1\x98\x6d\x5b\x27\xa1\x44\x71\x43\xb8\xb2\xec\xfa\x7b\x1a\xb6\x27\x60\x53\x0b\x4c\x34\x68\xaf\x9e\x6f\xf2\xed\xc0\xf8\xac\xc9\x04\x71\x2d\x78\x98\x32\x98\x9a\x7a\x29\x73\xed\xb3\xef\xbc\xf3\xac\xd6\xa0\xf3\xee\xfc\xac\x63\xd2\x82\xe9\x6b\xe4\xea\xd9\x2c\x5b\xf0\xc9\xc3\x44\x47\x27\x0c\x6e\xd5\xd7\x58\x4f\x41\x83\x2e\xcc\xe6\x73\x6e\x91\x68\xd0\xb9\x0b\x62\x7f\x1e\x0f\x39\xb7\x05\x74\x0d\xba\x8a\x61\x35\xe8\x3c\x22\x0a\xf7\x67\xdd\x9e\x30\xd1\x43\x0a\x13\x0d\x3a\xb7\x18\x36\xdc\x2a\xe0\x21\xc0\x61\xc4\x4b\x84\xbb\x10\xa8\x6e\x22\x84\x64\xa7\x14\xd4\x56\x47\x3a\x8d\xc2\x83\x84\xb0\x03\x42\xbd\x25\x0e\x59\x25\xd5\x5e\xdf\x1e\x28\xd1\xaa\xbb\x66\xdd\x98\x07\x27\x9d\x75\xee\xb6\xe5\x3b\xef\x08\xb7\xee\x1e\x3f\x43\x57\xac\xbb\xf5\x9d\x89\xab\xe6\x5e\x27\x0d\x7c\xce\x5a\x98\x55\x73\xd7\x4e\x5e\xb1\xe8\x4c\x83\x87\x13\x11\xde\xc9\x11\x60\x11\x7d\x0f\x4b\x38\x38\x0d\x9e\x66\x1d\x3a\x10\xd3\xc9\xfe\x1a\x61\x5c\x8d\x05\x25\x39\x07\x2d\x2e\x0f\x69\xdd\xb1\x4b\xc8\x8d\x4f\xa0\xf8\xc9\xdd\x1e\x02\x31\x7d\x88\xe5\xec\x2e\x9f\xbf\xa2\xb6\x84\x42\x93\x50\xee\xe1\xe7\x17\x8a\x78\x34\x03\xf5\xed\x81\x52\x26\xcd\x3b\x9f\xbf\xf0\x9e\x33\x7f\xf6\xa3\xd4\x83\x9d\x2e\xd7\xb7\x6e\x1e\x4b\xe8\x34\xbf\x7e\xe6\xf4\xdd\x33\xc7\xcd\xbc\xf3\xcc\x2d\x67\x51\x42\xcd\xbe\x87\xd6\xbf\xae\xad\x5d\xb0\x7c\xee\x0f\x99\xa9\x8b\x28\xab\xe6\x69\x67\x5b\xb6\xcd\xbd\x67\xe2\x1b\xd7\xa2\xf5\x9f\xeb\xda\xd3\x6f\x58\x0e\x03\x01\x9c\xab\xcf\xa8\xa0\xef\x9a\x16\x36\x9f\x81\x16\xd2\x9e\xc0\xe2\x33\x97\xb5\x98\xee\x8d\x85\x64\xd9\x1e\xa2\x74\x48\xa7\x93\xe0\xa4\x59\x15\x5a\x0a\x4c\x47\x88\x37\x64\x34\xf1\x26\xd5\x0a\x5b\x99\xf0\x24\x28\xae\xa2\x32\xe0\xb0\x6d\xe0\xa5\x63\xd3\x4d\x6e\xd7\x56\x7e\x0b\x10\xc0\x25\x85\xe7\x21\x1c\x80\x30\xa5\x5a\xec\xf9\x0c\x43\x1e\x89\xf9\xf2\x47\xba\xfb\xc8\x93\x27\x7f\x24\x56\xa0\xed\x91\x9c\xa4\x3f\x98\x42\xe5\xee\x6b\xff\x06\x5f\x9e\x00\xfd\xdf\xd6\x66\x3c\xcc\xf5\xc1\x96\x81\x37\x8e\xdf\x49\xcf\xc2\x15\xba\x16\xba\x0b\x6c\xd2\x15\xed\x1d\x14\x77\x82\xed\x94\x03\xd0\xc9\xba\xe2\x2a\x23\xa4\x88\x7c\x92\x6a\x77\xe1\xf5\xd7\x6d\x68\xbb\xaa\x9e\x52\xf8\x32\x72\x8a\x88\x25\x78\x5b\x4b\x3f\x72\x8a\x59\xc6\xc9\x52\xde\x5e\xc1\x41\x56\x5c\x7c\xc5\xf7\x5d\xf8\x3e\xbb\x17\xaf\x0f\x76\x57\x61\x95\x75\x50\x15\x13\x72\x0a\x4f\x29\xa6\x8e\xb7\x52\xd1\x7e\xcb\x3a\x22\xad\x7e\x1a\x6c\x1d\xa3\xbd\xb8\x56\x7b\xed\x2a\x66\x9e\xc6\x9c\xa7\x69\x77\x6a\x03\x7b\x98\x79\xf8\x9c\xf6\x19\x00\xec\x3f\xb9\x3e\xe0\x02\x57\x15\x8d\x03\x2f\x9f\x16\xfb\xa0\x71\x58\xbf\xd2\x38\x18\x7d\x1c\x43\x9f\x9d\x51\xe2\x6c\x8e\x31\x1f\xdd\x78\x72\x15\xb2\xe4\xa8\xc0\xd2\x67\x17\xe8\xb3\x3b\x5b\x36\x2d\x61\xfe\xdc\xaa\xcd\x48\x40\x4b\x8b\xf6\x45\xaf\xf6\xda\x02\xb8\xe3\xaf\xf0\xe0\xe7\x6f\xfe\x55\xeb\x83\x3b\x74\x1d\x2f\xc0\xed\xe2\xf7\x81\x0a\xf0\xa4\xee\x1b\x15\x05\x3d\x7a\xe4\x49\x10\x5d\x19\x89\x34\xcd\x3b\xf2\xb9\x90\x40\xa0\xd3\x21\x07\xa5\x6e\x02\x87\x28\x7d\x17\x5d\x8a\x1c\x62\x81\x9b\xbb\xd4\x77\x2b\x44\xc4\x11\xad\xce\x47\xc9\x7a\xce\x57\x70\x4a\x3c\x5b\x8e\xaf\x99\xf2\x8a\xa2\x5e\x19\xec\x37\x2a\x5f\x4e\xa8\x72\x39\xbe\xbc\xc0\xb9\x4a\x74\x78\x64\x4a\xed\x27\x10\xd5\x4a\xe4\x90\x55\x96\x49\xeb\xc8\x58\xd5\x11\xd0\x63\x36\xba\x6a\x53\x8a\xcd\x58\xb4\x5e\x2a\x24\xa3\x59\x43\x24\xbf\x67\x4e\xef\x6d\x1f\xac\xbc\x5f\xfb\xed\xe3\x3f\xfd\xee\xba\xcd\x3f\x79\x7e\xeb\xb5\x33\xda\x56\xf1\xfb\x34\xed\x02\xef\x96\xe3\x0f\xbc\xa3\xdd\xfe\x48\x0b\xe4\x52\xd0\xfe\xda\x7d\x3f\x73\x0e\xbc\x8d\xdf\x1f\xcd\x4e\xe6\xb7\x1c\xec\xd5\x6d\x54\xae\xe3\xc9\x39\x3b\xd1\x2c\x53\x1c\xf9\x5c\x90\x9a\x26\x68\x33\x99\x33\x8a\x38\x69\xf1\xf2\x55\x69\x6a\xcc\x7f\x58\x64\x9a\x72\x6a\x1a\xfa\x62\x39\xb2\x7c\x39\x36\x4d\x18\x5f\x33\xe1\xf2\x21\xa6\x09\xeb\xa6\x09\x17\x58\x84\xf1\xe8\x45\x89\xf0\x9d\x65\x04\xb7\x82\x4d\x63\x97\x49\x87\x2e\xc0\xd1\x82\x44\xb1\x94\x66\xfb\x90\x69\x95\x36\xdd\x2a\xb5\x7f\x23\x2e\xd2\x9a\x9a\x93\xfd\xd5\x8d\xda\x3f\x73\xb7\xcc\x5d\xbc\x76\xf3\xb6\xf9\x67\x26\x62\x73\xb8\xbe\xcf\xff\x5b\xfe\xec\xf5\x83\x5a\xff\xdd\x71\xe8\x69\xfb\xed\x81\x6f\x7e\xd7\xad\xad\xa3\x5a\x8b\xeb\xb5\x1e\xa2\x5f\xef\x33\xfc\x26\xe3\x91\x95\x21\xfa\xf5\xfe\x04\x52\x08\x85\x08\x92\x4b\xf8\x5b\x0d\xfc\x78\xe0\x64\x52\xf6\x8a\x98\xe5\x14\x1c\x32\xc9\x62\x56\x90\xf1\x4b\x20\xe1\x2b\xbe\xef\xc5\xf7\x33\x5e\x65\x90\x94\xbd\x24\x17\x49\xd9\x4b\xde\x66\x5d\xca\x9e\x7e\x32\x85\xdf\x72\x56\x87\xdd\x23\x92\x5c\x3b\xe1\x3c\x75\x10\x95\xcf\x82\xc4\x3d\x54\x52\xa4\x29\xe1\x24\x32\xf7\x4f\x13\x0d\xb8\xe9\xc3\x2b\xdd\x6b\xca\xc0\x62\xb8\xdb\x54\xbb\x87\x27\x0e\x6b\x2b\x74\xdd\x8e\x8f\xf4\xea\x41\x92\xaa\x76\x10\xcd\xfb\x91\xa4\x3d\xfe\x7f\xaf\x5a\x47\x1c\xc6\xd5\x46\x57\x3e\x5b\xd3\x18\xb7\xc6\xd5\x84\x2b\x8f\x12\x89\xff\x5c\xbe\x43\xad\x49\xe0\x33\xf0\x48\xfc\xf6\xb5\xa6\x24\x39\x53\x53\xdf\x80\x43\xfe\x7f\x43\xcc\x83\x64\x51\x3b\xe0\x57\x17\xf3\x98\x3d\x65\xee\x9c\x8d\x5a\x7e\xe1\x35\x37\xef\xf9\xaa\x6a\x1e\x91\x81\x15\x70\x43\xf8\xd0\x2f\x0c\x41\x0f\x12\x77\x35\xe0\x18\x84\x7f\x11\xd4\x83\x76\xb0\x05\x64\x6a\x01\x88\xe7\x12\xba\xea\x3c\x5e\xfd\x24\x7b\x1e\xb5\x26\xd4\x46\x67\x3e\xe7\xb0\xd7\x06\xf0\x99\x00\xbf\xd9\x63\x12\x68\xe4\xa1\x5c\x92\x56\xe3\x92\xb4\x08\x11\x15\xf3\xc8\x8d\x57\xc8\xb0\x98\x57\xd3\x30\xae\x26\x47\xd2\x56\x5c\x8b\xa4\x4a\x01\x4a\x8c\x59\x59\x85\x8d\x55\xdb\x28\xc9\x99\x11\x23\x93\xd8\x58\x76\x6c\x43\x10\x4d\x13\xb4\x69\x45\x55\x3a\x8d\x24\x59\x55\xc2\xa6\xe8\x6c\xdb\x10\x48\x2f\x5d\xd6\x0c\x08\x6f\x24\x5a\xa7\xf8\x53\xc9\xd6\xd1\x75\xf5\x29\xca\x39\x52\xdf\xb0\xef\xcd\xdd\x7b\xee\xbc\xaf\x00\xe0\xdd\x72\xec\xb6\x35\xcf\x2e\x7f\xeb\x99\x2d\xf7\x6b\x8f\x6b\x2f\x6f\x7a\xf5\xea\xb1\x6d\xcb\x5b\x9a\x72\x57\xdd\xba\x7e\x61\xc7\x38\x28\x9c\xbb\x7a\xe5\xa2\x33\x29\x56\xf7\xac\x69\xbd\xdb\x16\xff\xf4\x97\x2e\xab\xf4\xc0\xfa\xff\x3a\x52\xa3\x1d\xf4\x2f\x6d\x3d\x27\x7d\xf9\xb5\xdf\xba\x32\x48\xed\x15\xd4\xbc\xba\x06\xca\x68\x70\x07\x55\x41\xc9\x8d\xa4\xf6\x32\x84\x50\x50\x32\xa1\xd6\x3b\x4b\xf5\x50\x5a\x13\xa8\xe1\x50\x2e\x41\xed\x95\xa0\x6b\xc0\x49\xd4\x51\xda\x60\x5c\x4d\x34\xe0\xd5\xac\x29\x4d\xe8\x55\xfc\xe9\x82\x5a\x4a\xb4\x5e\x92\x33\xb5\x0d\x09\x6c\x39\xeb\x48\x6c\xb9\x2a\xaa\xd7\x4a\x35\x53\x64\xa2\x99\xf2\x15\xd5\x52\x06\x9b\xed\xd4\xea\x29\xf3\x8b\x6c\x76\x52\x25\x15\xed\xe5\x52\x7b\x51\xed\xd7\xab\xf8\x7d\xc0\x6d\x68\x92\x13\xec\x6c\xb1\xce\xbe\xc7\x28\x58\x20\x77\x49\x77\x04\x91\x68\x73\x15\x78\x7e\x86\x48\xee\x13\x25\x5f\x46\x89\x67\x5d\xf8\x9a\x71\xb9\x87\x50\x33\xb8\x08\x35\x83\x4b\x5f\xf7\xec\x8c\x24\xab\x16\x27\xb1\x57\x86\x13\x1c\x69\x33\xd3\x21\x98\x0d\x10\x74\xfd\x23\x2b\x5f\xb1\x28\xff\x73\x30\x76\x83\x76\x70\x51\xb6\x48\x98\xbf\xb0\xca\xd1\xd8\x52\x5b\x41\xb4\x47\xdc\xe0\xbe\x92\x71\xc2\xe2\x71\xea\xb9\x20\x77\x71\x13\xa4\xdb\x35\xec\x68\x87\x10\x51\xfc\x3b\xa3\x45\x4e\x3c\xd6\x2c\x27\x58\x1c\x64\xa9\x2f\x1e\x6c\xe9\x32\x5f\x44\x50\x71\xfb\x3f\x36\x6a\x1f\x2e\xde\x54\x24\x55\xa2\xbd\x3c\xb0\x0a\x6e\xd5\xe5\x4a\x74\x7d\x73\xd2\xa3\x0d\x2d\xc6\x58\xe5\x54\x51\x3e\x8c\xc8\x41\x82\x43\xf8\xe0\x8b\xf7\x3b\x7d\x4e\xe9\xb0\x73\x1e\x9a\x45\xf4\x24\x72\x6e\xfa\x89\x12\xd0\xe8\x29\xea\xc1\x9a\x91\xfb\x3b\x77\x1e\xf9\x23\x3d\x31\x7b\x48\x5e\xc1\x23\xaa\xee\x56\x9a\x57\x68\x3d\x5a\xf0\x05\x59\xcc\xb2\xb2\x9e\x12\x13\xdc\x16\x62\x26\x0b\xdd\x36\x25\x7c\x3f\x23\xc9\xa5\xf6\xca\xb8\xdc\xc6\x3e\xf9\x10\xcb\x5b\x04\x97\xdb\x23\x99\x4c\xbf\x59\x56\x70\x49\xe6\x7e\x89\x0f\x84\x48\x4c\x23\x46\x42\x5c\x9a\xd2\xcc\xd8\x9d\xa6\x0e\x88\xa8\x7b\x4e\xbb\x92\x12\x14\x22\x8b\x2c\xc4\x14\x41\xf7\x9e\x1b\x4f\xbb\xa1\xea\x30\xec\x1d\xb8\x0b\x36\x68\x8f\xae\x09\x6e\xe9\x59\xbd\x02\xfb\xcf\x23\x70\xe9\x66\x18\x1a\x48\x0c\x84\xe1\xec\xcd\xf0\xee\x79\x03\xff\xa4\x9c\x64\x00\xf0\x41\xd2\xb7\x77\xc4\xd0\x9e\x50\x4c\x1f\xb2\x96\x32\x98\x28\xc5\x3e\xa4\xb8\xf2\x59\x0f\xb1\xae\x48\x6d\x2a\x26\x74\x3b\x17\x11\x9b\xdc\x4d\xed\xb9\xf5\xc8\x46\x6a\x4f\xb1\xd9\x8d\xf8\x7e\x4e\xf5\x8c\x38\xea\xc6\x67\x05\xa3\x37\xcf\xe4\x8c\x1f\x44\x15\x8f\x7f\x81\xb4\xed\x65\x64\x65\x90\x2d\x25\x91\x97\x64\x93\x14\x5e\x48\x83\x09\x36\x6c\x53\xb7\x47\x94\xe4\x02\x7f\xf2\x3e\x72\xcf\xbc\x63\x0a\xd3\x20\x4e\x3f\x25\x11\x1b\xb6\x47\xa0\x40\x8d\x58\xcf\x2e\xf8\x04\x36\xad\xe8\xe9\xbe\x3a\xf8\x28\x9c\xa3\x45\x19\xe8\xd3\xf6\xad\x8d\x6d\x98\x9d\x20\x9e\x79\x1e\x1c\xff\xcd\x37\x07\x5e\x77\x0e\xbc\x09\xed\x08\x9e\x77\xfe\xc0\xdb\x86\x6f\x66\xf8\x7d\x40\x01\xcf\xea\x36\xf4\x60\x1b\xf2\xe4\x34\xe5\x4c\xa5\x72\x2c\x03\x86\x49\x67\x79\x4d\xe9\x44\x9f\x19\x9e\xfe\xb5\x88\x6b\x47\x21\xc7\xa9\x53\xa6\xb1\x4c\x67\xd4\xf3\x59\x32\xbe\x66\x64\xc5\x52\xaa\xbd\xac\x3a\x64\xa2\x36\x43\x93\x5c\x72\x49\x4e\x46\xa1\xc4\x3a\x7a\x4c\xe6\x96\xd2\xa5\x29\x2e\x4a\x2b\xc3\x0a\x6c\xeb\x9f\xd7\xb5\xae\x2b\x87\xc9\x8a\xab\x5b\x37\x74\x33\x53\xe1\xb2\x81\xed\x30\xa6\x3d\xf8\xda\xda\xe5\x5c\x8b\xb6\x61\x83\xa6\x3d\xc7\x3c\x3e\x30\x76\x40\x64\xe6\x4c\x25\xae\xa5\x9f\x7d\x3f\xb1\x78\x81\x1f\x3c\xa5\xdb\x45\xf6\x1b\xd1\xd6\xc9\x48\x89\x4c\xa5\x13\xb3\xb9\xb3\x94\x80\xc8\x3f\x9c\x51\xfc\x62\x56\xf0\x13\xa3\xf8\x4b\x98\x86\x1c\xe4\xa6\x0f\x5f\x33\x3e\xff\x10\xa3\xf8\x8a\x8c\xe2\x2b\x31\x8a\xdf\x30\x0a\x51\xa8\x76\x79\x07\x71\x0a\xb1\x16\x21\x65\xd8\xa5\x56\xdb\x1e\xdf\x1e\x81\x4d\x31\xd8\x12\xd7\x5e\x9d\xea\xaf\xb5\xc2\xa7\x60\xaf\xe6\x86\x15\x1a\x7a\xe8\x3b\x33\x29\x89\x90\x96\x59\xba\x12\xbe\xa9\x59\x07\xee\x84\x3b\xa7\x6b\x3b\xa9\x3e\xbf\xa5\x9d\xe8\x16\x5f\xab\xe3\x35\x29\x73\x90\xb1\x47\xe9\xaa\xc5\x10\xb9\x08\x93\x2b\x3e\xc4\xb8\x07\xe9\x86\x3a\x48\x56\xd8\x8e\x8f\xac\x66\xf0\xfe\x55\x88\x83\xb2\x0c\x6b\x73\x16\x1a\x2d\x80\x43\x57\x16\x0a\x43\x93\x44\x28\xa2\x3c\xd0\xca\x5c\xb1\x95\x29\x87\xbd\x03\x8f\xc2\x7a\xed\x41\xed\xe3\xdb\x74\xb1\x7f\xba\x13\x0d\x54\xe0\x5d\x88\x88\xfe\x43\x30\x13\x00\xfe\x26\xae\x6f\xc8\x58\xa0\x39\x16\xa1\x64\x2c\xae\xc2\x58\xf4\xc3\x47\xe9\x58\xf4\xed\xe7\x3f\x19\x8b\xd2\x5e\x34\x96\x99\x2d\xcc\x15\xa5\x4c\x48\xda\x6b\x8f\xb3\xab\xdf\x2b\x26\x41\x62\x57\x17\x62\x87\xc7\x49\x4e\xd0\xf0\x59\xa7\x47\x9f\x17\x93\xee\xcc\x4d\x94\x90\x5c\x29\x5d\x52\x9e\x74\xab\x17\x32\x83\x45\xe1\x84\xae\x28\x8f\xec\x3a\x5f\xdf\x60\x71\xed\x42\x83\x0d\x8f\xc7\xaf\xab\xc7\xf3\x78\x35\x64\x3d\x0c\xcd\x3b\x70\x4e\xec\xe7\x2e\xa7\xae\xac\xe1\xf6\x90\x76\x3f\x24\x34\xc3\xbd\x2c\x27\x38\x5d\xee\x42\x1e\x85\x07\x84\x1e\x8f\xa6\x13\x0d\x6d\x79\x36\xa2\x44\xa0\xd1\xb7\xac\xb7\x52\xbe\xb1\x1a\xb6\x68\x1a\x2c\xc7\x07\x2a\xed\x8f\xd7\x68\x0d\x84\x92\x81\xe9\xa0\xb2\xda\xcc\x15\x06\x07\x83\xb6\x82\xfb\x8c\x70\x92\x3f\x67\xec\xb9\x9e\xc1\xaa\x50\x05\x5b\x08\xa6\x2d\x74\xde\x05\x4f\xf1\x76\xe1\x29\xa1\x7d\x1b\x6a\x91\x21\x6a\x50\xbc\x88\x5c\xc3\x58\xc4\x25\x66\x39\xd7\x50\x5b\xe4\x58\x4e\xd0\x4d\x81\x2d\x51\x08\x44\x06\xd9\x43\xe7\x63\x4b\xe9\xf6\x28\xc8\x46\x3d\xf2\xa7\xeb\xb4\x0f\xfb\x34\xad\xa0\x1d\x75\x7c\x1b\x8e\x40\xa8\x7e\x14\x59\xe3\x2d\x6f\x92\x7c\xd9\xfd\xfa\x99\xdb\x66\x77\xa5\x8c\x55\x9e\xb4\x88\x5a\xd9\x7c\x8e\x75\xe2\x95\x5e\xd7\x9b\x27\xf6\x70\x53\x38\xa1\x87\xc0\x09\x07\x87\x9a\x9e\x42\x0a\x6a\x88\x4b\xd8\xc9\x7a\x47\x65\x81\x0d\x05\x72\x64\x17\xb3\x9c\x1d\x3b\x84\x03\x5f\xf1\x7d\x27\xd5\x24\x67\x39\xde\xea\x70\x9a\xbe\x00\xcc\xb9\x67\xe9\xd5\x9c\x79\x66\x69\xab\xf6\x82\xa6\xbd\x52\x98\x75\x4d\x3b\x36\xab\x30\xe7\x00\x58\x22\x24\x9f\xf6\xf3\x41\xe3\x34\x5b\x61\xad\x42\xc9\x38\x05\x73\x9c\xfa\xbc\xbb\x8a\xe7\xdd\x55\x1a\x6a\x7a\x4e\x36\xdd\x76\xc2\x00\x39\x74\xb4\x0e\x3b\x57\x3c\xce\x1c\xcb\x19\xc3\xc4\xf3\x4c\x84\x90\x8d\x84\x27\x1e\xa7\x50\x2a\x07\xc6\xac\x6f\xd1\x76\x3f\x56\xac\x08\xf6\xde\xf1\x0d\x74\x4a\x69\xfe\x4d\xb8\x89\xdf\x07\xaa\xc0\x07\xfa\x58\xc3\xe5\x55\x06\x93\x06\x62\x52\x6a\x25\x9b\x47\x15\x49\x7c\x48\x92\xd9\x3c\xf2\x90\xfe\x46\x47\x3e\x57\xc6\x93\x74\x53\x99\x23\x6f\xb0\xa1\xd1\x63\x15\x01\xfd\xea\xda\xad\x3e\x3c\x60\xb1\xa0\x57\x50\x9a\x94\xab\x12\x51\x65\xff\xfe\xce\x9f\x1c\xf9\x03\xb9\x59\x2e\xa2\x8a\x7e\x14\x1e\xb4\x92\x87\xf1\xea\x17\xc2\xd7\x4c\x28\x3c\x64\xf5\x0b\x35\x37\xc3\xbd\x90\x61\x43\x15\x95\x45\x1b\x57\xb8\x1c\x1f\xe2\x3c\x84\xb6\x3d\xc3\xbb\x64\x2a\x70\x45\xaa\x0b\x3e\xe3\xbc\x71\xb2\x1c\x5d\x84\x6a\xb6\x73\xe1\x4d\x33\xce\xbe\xe5\x83\x6f\xdf\xa7\xbd\xf5\xcb\x3d\x6b\xd6\xfd\xe8\xde\x17\xb6\x6e\x38\x3d\xb9\x4a\x3b\x08\x81\x36\xe5\x04\xe0\xf7\x0d\x5c\xe8\xbd\xe1\xf8\xfd\xbf\xd7\xee\x78\x8c\xe4\xea\x6c\xbf\xf9\xc9\xcf\x9d\x03\x6f\x73\xb9\x63\xb3\x68\xbe\xce\x32\x8b\xeb\x03\x95\xe0\x6d\xdd\xa6\xa1\x70\xa5\xa1\x25\x87\x6d\x5a\x21\xe4\x51\x39\x69\xea\x95\x1c\xf9\x5c\x80\x9a\x32\x60\x33\xfb\xac\x2a\x29\x27\x75\x18\xc6\xd5\x90\x8b\xc0\xef\xbd\x30\xae\x5a\x3d\x05\xc2\x83\xd2\x44\x78\x25\xb6\xdd\xfe\xce\x5b\x8e\xdc\x41\x6e\x86\x45\x54\xde\x8f\x42\xd4\x94\x46\x70\xc4\x86\xb0\x29\x83\xf8\x9a\x09\x86\x86\x98\x32\xa8\x9b\x32\x58\x5e\x51\x64\xca\x50\x58\x92\x55\x8f\x3b\x9d\x46\x5e\x29\xc3\x3b\x25\x8a\x39\x94\xcc\x2a\xa0\x51\xa2\x1a\x92\xd5\xa3\x0e\xc8\xee\xb8\xc8\x48\xeb\xdd\xd8\xb3\xe4\xca\xcd\xdb\xce\xea\x69\x8e\xcd\xd1\x5e\xdb\xaf\xed\x3f\xc0\xf5\x69\x52\x49\x72\xef\x5b\xab\xdd\xda\x3a\x76\xf5\xf1\x0d\x7a\x9f\xc2\x1e\xfe\x6a\xfe\x65\xd0\x08\x46\x83\x1b\x40\x66\x04\xe9\xe6\x60\xf3\xa8\x06\x3b\x60\xa5\x4d\x6f\xb9\xb3\xb1\xba\x0e\x6a\xd2\x4a\x0f\xfb\x80\xf0\x4f\xe1\x65\x46\x86\x71\x35\xee\xca\xa3\xb8\xa8\x8e\xa2\x6d\xa0\xe4\x84\x1f\x97\x25\x39\x67\xe3\xc4\x3a\x82\x45\x1e\x25\x65\xfc\x42\x79\x3a\x9d\x46\x41\x39\x6b\xa9\xac\xae\xa1\x54\x66\x23\x24\x39\x53\x5e\x5d\x87\xef\x27\xa5\x1c\x70\xc9\xc1\xa6\x9a\x40\x5a\xb5\xf9\x4b\x90\x85\x94\x05\x88\xf1\x79\xfd\x81\xba\x56\xaa\xef\xed\xf3\x32\x82\xdf\xa0\x52\xae\xb7\xc4\xa2\xa0\xd6\x4b\x5a\x1b\x68\xdb\xde\x82\x3f\x6d\x58\x39\xef\x6b\xdf\xf8\xc1\xab\xdf\xbd\xfe\xca\xae\x6f\xbe\xb2\x7e\xdb\x9e\xbb\x7f\x58\x96\xec\x9a\x55\x7e\x5e\xf2\xde\x6f\x2e\x5e\x33\xa0\xfd\x81\xf5\x46\xe6\x2d\xef\x9c\x72\x36\x23\x43\x0f\xec\x3f\xdc\xf4\x49\xd5\x83\xda\xde\xc7\xae\xdd\xc9\x7d\x27\xbb\x17\xca\x37\x3f\xb4\x2b\xab\xed\x5f\xee\x0c\x7d\xea\x10\x17\x57\xc3\x9a\x0f\x97\xcc\x99\x05\xc5\xb5\x4b\xff\x00\xf4\xde\x86\x87\xb9\xcd\xdc\x4a\xd0\x08\xda\xc0\x36\xdd\x66\x92\xa0\xdb\xac\x8a\x2f\xa2\x59\x0e\x8c\x1e\x41\x5a\xfb\x9c\x79\x88\xda\x07\x75\xc0\xe4\xe2\xa4\x35\x1f\x1b\xae\x05\xc6\x73\x21\xda\xa8\x3f\x46\xef\x83\x41\x23\xd2\x28\x2e\x65\xed\x9c\x54\x87\x0d\xd8\x22\x67\xac\x01\x82\xdf\x0f\x49\x99\x8a\x48\x0d\x71\x10\x09\xdb\xaf\x22\x42\xec\x37\x5a\xca\xb9\x81\x37\xd4\x8c\xed\x67\x0f\xe8\x5b\x90\xde\x19\x63\xa2\xb6\xfd\x81\x22\xac\xbd\x60\x88\xec\xd6\xeb\x2a\xe9\x01\x3d\x93\x67\x59\x70\x07\x74\x67\xc7\xaf\xae\x9e\x36\xa1\xfb\xac\x4d\x67\x2c\xfa\xba\x3f\xdc\x7f\xdf\xc6\xdb\x56\x2f\xf0\x47\x3b\xc7\x4c\xfd\xc6\xa6\x8b\x17\xaf\x7d\xfe\xb7\xcc\x4e\x8f\xbb\x6d\x5a\x30\x98\x48\xc3\xcc\xab\x70\xfa\xee\xa0\xfb\x2d\xef\xb7\xff\x6b\xed\x25\xab\x98\xda\xef\x25\x9f\xfc\xd3\x8d\x1b\xbe\xfb\xe1\x58\x8b\xef\x60\x70\x41\xdd\x27\xcf\xd7\xf4\x86\x46\xfe\x6c\x56\xb4\xf1\x07\xd8\xdf\x4c\xdc\x6a\x03\xb8\x8a\x76\x93\x19\x48\x07\x13\xc5\x5a\x9f\x50\xcb\x9d\xf9\xac\x35\xc0\x59\xe3\x46\x47\x99\x0e\x61\xad\x84\xf1\x5c\x0d\x85\x16\xc6\x61\x9c\x86\xcc\xa1\x06\xc2\x89\x9a\x29\x8f\xd4\x63\x4b\xd4\xc8\x99\x80\x1c\x25\x06\x0a\x94\x4b\x72\x26\x54\x59\x43\xb2\x49\xf5\x92\xfc\x55\x80\xab\x84\x61\x0a\x0e\x4a\x1d\xad\xf9\x5f\x70\xe1\x9f\xd6\x3e\xb9\xe2\xf2\x8b\xae\xeb\xfe\xe1\x6b\xdf\xdf\x78\xeb\x8d\xfd\xcf\xbd\xa0\x69\xef\x43\x4b\x51\xd6\x88\x69\x80\x16\xf8\xc8\x7b\x4d\xe3\xbf\x18\x57\xb7\x43\x7b\x3a\x77\xff\x8e\xd3\x09\xd1\xd4\xc0\xaf\x4a\x92\x46\x8c\x89\x6f\x1d\xce\x06\x06\xda\x95\xda\xc0\x18\xbd\x9e\x3d\x1a\x34\x7a\x1c\x6a\x64\x43\xe5\x91\x06\xec\x21\x95\x12\xaa\xc7\x83\xcf\x72\x01\x29\x4a\x5e\xaf\xf2\x7a\x49\x46\x0d\x54\x26\x89\xda\xc0\x1e\x25\x88\x57\xdf\x29\x10\xaf\x05\x1e\xa9\xc1\xe9\xb3\x93\x68\xfc\xed\x28\xb2\xc0\x70\x7a\x7f\x5a\x65\xd1\xe8\x21\x78\x40\xeb\xe1\x0e\xf2\xfb\x80\x03\xcc\x07\xf4\x04\x02\xf0\x21\xd5\x91\xa4\x22\x9f\x94\x88\xc9\xd4\xed\xfc\xf1\x91\x97\x68\xc8\xde\xec\x46\xf6\x7e\x5e\xe5\xb8\xa3\x6e\xc2\xfb\xc8\xdb\x49\xda\x9f\xb7\x3b\xcc\x35\x54\xb0\x52\x0a\x15\x7a\xb8\xd0\x63\x11\xe5\x81\x76\xf6\x48\xbb\xf6\xe3\x5f\x19\x01\x28\x39\x57\x68\xda\xf1\x49\x38\xfa\xd4\xcf\x14\xb5\xda\x0a\xc1\xcb\xad\x04\x49\x83\xbd\x3f\x13\x1e\xd1\x90\x4a\x0d\x95\x23\xa4\xcd\x7f\x49\x57\x1e\x25\x45\xd2\xa8\x34\xc2\x95\x47\x23\xa8\x32\xa1\x57\xcc\xa3\x20\x81\x1b\x92\xad\x24\x81\xbc\x22\xdd\xc5\xa3\xae\x3c\x8a\x92\xa0\x54\x1d\x3d\x58\x9d\xb0\x41\x44\x8d\xfd\x68\x84\x88\xea\xfb\xf7\x77\x7e\xfc\x19\xa5\x65\xaa\x12\x51\x75\xbf\x2a\x87\x8f\x22\xa9\x58\xda\x29\xd4\xcc\xa3\x70\x3f\xa7\x06\xdb\x8e\xba\x51\x59\x3f\x98\x60\x93\xe4\xb2\x60\xa8\xaa\xba\xbe\xb1\x90\x83\x78\x48\x92\xcb\xc2\xc5\xb7\x88\x69\x1a\x92\x05\x2d\xc3\x11\x92\x6a\x69\x4e\xa7\x51\x85\x9c\xb1\xda\xb0\x57\x20\x2f\xe5\x12\x85\x40\x92\x1f\x22\x5a\x86\xfe\x9a\xe6\x93\x89\x19\x16\x94\x9c\x5a\x47\xb7\x0f\x2b\x6c\xf8\x67\x9f\xf5\xc6\x83\x6f\xc6\xad\xdd\x8f\x5c\x78\xed\x96\xc0\x38\xaa\xe6\xf4\xe1\xe2\xcd\xee\x09\xc3\x09\x1c\x5e\x7a\xf9\xee\xdb\x67\x2e\xd3\xde\x35\x64\x9c\x5a\x1e\xec\x9c\x08\x13\x43\xc4\x0e\x21\xd8\x0f\x00\xdf\xc5\xef\x03\x56\x70\x01\xc8\x08\x80\xa0\x78\x32\x80\x21\x1c\xe6\x10\xd9\x48\xa1\x84\x16\x9d\x10\x24\x2c\xe5\x22\x09\x09\xa1\x98\xc7\xf1\x20\xb1\xba\x2e\x2c\xe4\x36\xfb\x04\xa8\x27\x59\x9b\x9b\x21\xb9\xea\xc7\x3a\x5a\xdd\x26\xe8\x7e\x7a\xa4\xdb\x0f\xc7\xac\x83\x97\xc3\x9e\x81\x5b\xaf\xd0\x0e\x5e\xc1\xef\x1b\x40\xcc\x9c\xe3\xab\x07\x0e\x32\x09\x00\xc1\x52\xcd\xcb\x6d\x21\x31\xec\x22\x40\xba\x1b\x90\x95\x70\xa9\x3b\x52\x66\xed\x57\xc4\x41\xeb\xe0\xd8\xdb\x5d\xcc\x1b\x05\x54\x3b\x49\x6e\xda\x8d\xe4\xa6\x51\xa5\x56\x81\x93\xe4\x8f\x68\xaf\x81\x2f\xd5\xd6\x4e\x1f\x69\x29\xac\x1f\x65\xb1\x8e\x1c\x09\x1b\xe0\xe4\x81\x7b\x96\x69\xcf\x5f\xc8\xf5\x0d\x5c\x3b\xe7\x9c\xab\x7a\x99\xb9\xc7\x76\x68\x5e\x78\x18\xfb\xf5\x2c\xdd\x66\x22\x98\x0a\x32\x1e\xa3\xad\x15\x09\xa9\x1c\x80\x1e\xce\x15\x47\xf6\xc2\xd1\x9f\xe0\x9a\x55\x5e\x24\xfc\x6d\x2a\xcf\x49\x72\x96\x61\xf5\x0a\x1a\x07\x0b\xa7\x76\x3c\xf7\x30\x02\x05\xfa\x7e\xcd\x6a\x85\x55\x96\xc3\xa6\x7d\x2c\xb0\xbe\x55\x7b\x63\xac\x76\x30\x0d\xdd\x90\xa9\x62\x37\x50\x53\x55\x69\x9a\x76\x04\xba\x49\x3d\xf1\x29\xdd\x5e\x0a\x68\x06\x19\x08\x08\xcf\x2f\x39\xb3\x7b\x92\x94\x0e\xc1\x91\x42\x72\xc2\x04\xcb\xab\x2c\x34\x6b\x4d\x11\xb6\x60\x03\x1a\x7c\x77\xb4\x40\xe6\x06\xd2\x19\x3c\x62\x34\x35\x05\x94\x5b\xb4\x8f\xda\xb5\xe7\xc7\xbc\xf7\x1e\xd7\x37\xb0\x2f\xbd\xfb\x8a\xf3\xb0\x45\xde\xd3\x8e\x42\x81\xfc\xfd\x4d\x5a\x0f\xbf\x9a\x9c\xb9\x17\xe8\x35\x5e\xa7\x8e\xc2\xe1\x53\xe4\x40\xc9\x1c\x52\x59\x31\x8f\x58\x4a\xab\x60\xd7\xa9\xe0\x58\x46\x92\x55\xe8\x21\x55\x9c\x0c\xe7\x72\xd3\xf2\x6b\x96\xb7\x0a\x4e\xb3\xc8\x98\xe5\xac\x36\xb7\x4e\x07\x47\xad\x44\x53\xed\x2c\x5c\xc5\x4c\xf8\x08\x4e\xb8\x03\x5e\x0c\x7b\x07\xde\xc9\x40\x2b\x5e\x8a\x6e\xdb\xa3\x7d\x9b\x39\xce\xec\x1f\xf8\x82\xb1\x0c\xc4\x35\x1f\x39\x0d\x57\x0d\xfc\x11\xc0\x13\xdb\xb4\x15\x44\xcb\xd1\x03\x3a\x8a\x9e\x11\x16\x9e\x51\x4f\x6c\xe0\x07\xb3\x3b\xa4\x53\x3e\x46\xb8\xe8\x31\x8a\x65\x1e\xaf\x86\xf6\x8d\xda\x87\x7d\xdb\x4b\xb4\x1e\x69\x22\xdc\xd4\x7b\x7c\x40\xeb\xb1\xac\x20\xb6\xca\xe9\x2a\x57\x3c\x9b\x47\x96\x24\x5d\xb7\x05\xab\x0e\xd8\xe0\x3c\xc9\x64\x06\x40\x7b\x3c\x3b\x01\x38\x6c\x94\x50\x4f\x38\x84\xc3\xe8\xac\xc3\x2a\x58\x75\x6e\x0a\x22\xd6\x6c\x1e\xc1\x8d\xa3\x98\x9b\x10\x96\xba\x45\x95\xa7\x84\xa5\x1e\xee\x68\x21\x0b\x47\x70\x27\x3a\x7f\x20\x40\xb6\x66\xb8\x97\xe3\x2d\x36\xb7\xa7\x68\x65\x13\x9c\x92\xac\x32\x2e\xbc\xbf\x3b\x08\xce\x09\xa8\x80\xd7\x99\x12\xf5\x6d\x00\x1a\x47\xf0\x07\xda\xd9\xd7\x5a\xb5\x03\xcf\xc2\x97\x20\x80\xa3\xb4\x83\x37\x6b\x07\x17\x1e\x4f\x18\x1b\xc2\x6c\x2e\x47\xf1\x9a\x78\x53\x80\x60\xa1\xb6\x82\x6f\xe1\xfa\x40\x0d\x38\x04\x68\x76\xc9\xe5\xd6\xc9\x47\xb9\x9a\xc2\x78\x03\x05\x20\x6c\xc4\xe0\x34\x1e\x2a\x7b\x69\xe0\x61\x77\x1f\x39\x41\xd9\x30\x9b\x09\xe3\x28\xa5\x1e\x2d\x52\xbe\x2c\xa6\x38\x1f\x1e\x91\xb9\x97\x28\x5c\xc6\x8c\xd5\x9e\xa3\x5f\x6b\x4a\x56\x7b\x21\x22\xc9\xa8\x92\xec\xfb\x2c\x91\x47\x44\x2e\x82\xd7\xf1\x4b\x48\x4a\x23\xb7\x8c\x14\x0a\x7f\x89\x08\xb1\x53\x09\x60\xe2\x05\x7e\x61\x0b\x5b\xd1\xf2\x79\xaf\xb8\xf4\x9c\xdb\x86\x55\xc1\xac\x98\xc3\xae\x7e\xef\x3d\xad\xb7\x3b\xbd\xaa\x54\x8e\x2f\x74\xf6\xb8\xe7\xef\xbd\x71\xc1\x06\xb8\x1a\x40\xf0\xb0\xd6\xc3\x6f\xe0\xf7\x81\x32\xf0\x3b\x40\x70\x3f\x19\xce\x49\x3a\xc0\xfc\x09\x7c\xb2\x20\x2c\x12\xec\x21\x95\xf3\x10\x28\xab\x50\x58\xbe\xf1\x19\x4e\x10\xf3\x88\x4f\x62\xdf\x20\xd4\x32\x1e\x1d\xa5\x22\x16\x11\x1b\xea\x5c\x6c\x5c\x29\xa0\xf5\xae\x23\x0f\x99\x0b\xad\xd2\xaf\xeb\x53\x2b\x62\xd6\xa1\x38\x95\x78\xd6\x8b\xaf\x19\xaf\xe2\x2c\x4d\xd4\xee\x65\x78\x87\x5b\xf1\x1a\x75\x12\xe3\xb3\x89\x7a\x45\xfe\x34\x92\x08\xb5\xb4\x48\xbb\xa2\x58\xdb\x60\x52\x14\xaa\x13\x41\xa3\x0f\x6c\xc7\x87\x5d\x97\xc1\x96\x4b\xec\x77\xac\xdf\xb9\x09\x26\xb5\x01\x58\x41\x03\x91\x2b\x1e\xbd\xf7\xfe\x27\xd9\x8a\xf4\x38\xa6\x76\xe0\x78\x73\xcd\xfa\x99\xcc\x16\x3d\x25\xd6\xd2\xb3\x5b\xd7\x0f\xd5\x56\x70\x2f\x70\x7d\xa0\x02\xaf\xdf\xa6\x74\x68\x65\x31\x70\x4b\x81\x71\xa2\xdc\x52\x65\x4a\x87\x86\xd3\x69\xa4\x48\x39\xce\xee\x2b\x0b\xe2\xb8\x50\x96\x33\x6e\xd1\x9b\xa6\x1d\x06\x83\x65\x43\xe9\x8b\xd1\x05\x87\x93\x0e\x25\x59\xaa\xc5\xda\xf1\x09\xbe\xb2\x61\xf4\x43\xf5\x8c\x55\xa2\x77\x21\xd5\x10\x7d\x18\x00\x7e\x39\xbf\x0f\x84\xe0\xd7\x75\xc4\xad\x94\xd2\xe7\xda\x23\x12\x8c\x48\xf8\xab\x4c\x32\xf2\x57\x1f\x92\x72\x01\x5a\xe5\x09\x24\x72\x7e\xfa\x89\xa3\xe7\x4c\x09\x2f\x29\x92\x6c\x8d\xe7\xec\xf4\xbe\x3d\x91\x73\xd0\x4f\x92\xa8\x7a\x1c\x71\x55\xf4\x14\x00\xbb\xc3\xbb\xc5\xbd\x47\x5e\xa3\xaf\x5a\x33\x72\x34\xa3\x80\xa8\xfa\xdb\x8f\x22\x87\xa8\xda\xdb\x8f\x9a\x3e\xb3\xbf\xf3\xd6\x23\xdb\x49\xdd\x2d\x20\x66\x6d\x01\x3b\x4d\xfb\x3b\xfd\x0e\x5a\x71\x73\xcb\x1e\x25\x9e\x55\xf0\x95\xb2\x10\x39\x0c\xee\x1c\xbb\x12\xcf\x94\x05\xec\x45\x3e\x65\x4b\x67\x7c\x7e\x07\xfe\xe4\x4c\x67\x14\xd9\x83\x3f\xb9\xd3\x60\x82\x93\xe1\x6d\x76\x87\xd3\xad\x14\x2b\xd8\x12\xa7\xdb\x6b\xc3\x77\x8b\x54\x6c\x8b\x31\xd5\x01\x25\xc5\xb6\x11\xff\x52\x2c\x02\x1b\x53\x4c\xf7\x5a\x3b\xe5\xc6\xee\xb9\x7d\xd8\xc3\x7e\xa5\xbd\x7a\xc5\xd2\x59\x53\xb7\x4e\xdc\xf7\x5c\xc1\xbd\x2e\x77\xc1\xe9\xda\xd3\xf2\x48\x66\xcb\x17\x33\x99\x96\x66\x45\x3b\x00\x13\x3f\x35\x34\x6a\x33\x24\x87\xf2\x1e\x28\x22\xdf\x17\x53\x45\xac\x4f\xd9\xb0\x00\xac\xe4\x84\xea\xa0\xa0\x72\xdd\xeb\xb2\x0e\x59\x19\x66\x2e\xcc\xe4\x89\xae\x66\xc8\xa1\x30\xb1\x75\x58\x54\x43\x32\xb5\xb5\x7c\x74\x7f\xe7\x75\x47\x96\x11\x13\x87\xc5\xac\x2d\x6c\xa7\xec\x4d\xce\x90\x83\x24\x4f\xb0\x41\xc3\x62\xb6\x1c\xdf\xcf\x94\x87\x07\x19\x34\x18\xd2\x0d\x0a\x1e\xc2\x36\x0c\x86\xc2\xe5\x85\xd2\xa6\xcd\x19\x2c\x2f\xc9\xab\x10\x2a\x5d\x56\xd1\x79\x35\xcd\x57\x20\xd0\x9e\x12\x3a\x61\x41\x3b\xd7\x03\x63\xed\xe6\x3b\x30\xbd\x65\x63\x62\xca\xc2\x58\x18\x36\xfd\x4d\x7b\xad\xcb\x56\x63\xed\x9c\xd1\xb6\x31\x71\xc7\x03\xe6\x3b\xd0\x17\x7c\xef\xcd\xd8\x53\x3f\x26\x32\xba\x4d\x1b\xba\x6b\xbe\x78\xfd\x01\xb3\x76\xcc\xe5\xf9\x7d\xc0\x6b\xd4\xe7\x32\x0e\xa7\xb7\x28\xcf\x97\xe3\x25\x92\x85\xe2\x59\xda\x2a\x57\x50\xc0\x2e\xca\xd7\x12\x12\x57\x0f\xcd\x02\xe2\xf8\xc8\x2a\xe6\x91\x3d\xa9\xfa\x07\xa7\x6f\x4d\x0f\x2f\x8a\x25\x0b\x35\xe3\x52\xd1\xc1\x8c\xe2\x1d\x94\x8c\xca\xb2\x76\x97\x42\x8c\x66\xe8\x11\x42\x72\xa0\x26\x10\x34\xa9\x38\xad\x3f\x48\x8d\x5f\xaf\xfe\xe2\x15\xec\x09\xe7\x65\xda\x2b\xcb\xf1\xe2\x76\x3d\xbf\x6f\xe0\xd5\x9e\xdd\xb7\xb5\x4e\x18\x78\x8b\xe1\xf0\x82\x36\xf0\x4d\xbd\x2e\x17\x21\x9c\x9b\xfb\xf4\xbc\xbe\x3b\x58\xc8\xd0\x91\x06\x55\x5d\x68\x88\xa1\xef\xb8\xc3\x55\x68\x50\x35\xaa\x4f\xa4\x7f\x04\x31\x22\x0a\x16\x0d\x2f\x28\x66\xd9\x20\x1e\x1e\x47\xae\x65\xf8\x9a\x29\x0b\x32\x25\x70\x31\x3c\xce\x0c\xcb\x95\x11\xe5\x55\xc0\x72\x65\xc1\xc2\x3e\xc9\x40\x49\x56\x79\x0b\x45\x88\x7b\x7c\x14\x6b\x68\x75\x9b\xa8\x09\xab\xcf\x00\x12\x78\xa0\xae\xcf\xef\x81\xc4\x04\x75\xb1\xa8\xc5\x03\x6b\xff\x06\x9b\xba\x7c\x65\xd6\xef\xdf\xb7\xe1\xce\x8a\x94\xf6\x5a\x87\x44\x97\x4e\xae\x4f\x3b\xb8\x60\xc1\xe6\x3d\xb7\x74\x6f\x3d\x02\x63\x53\x5b\xba\x26\x3c\xf3\xfa\x55\x3a\xb7\xb9\x65\x1c\xff\x32\x88\x81\x26\x70\x23\x55\x5d\x25\xac\xdb\x4e\x1c\x4e\xc5\xd9\x7c\xae\x46\xa9\x70\xba\xe2\x28\x92\x52\x6b\xec\x79\x64\x4d\x1a\xdc\x20\xbc\x2b\x8f\x78\xaa\x86\xae\xf3\x69\x8e\x80\x71\xd5\xe3\xa1\x34\x21\xbc\x2e\x57\x52\x2d\x21\x36\x8d\x7c\xf8\x10\x8c\x46\x48\x39\xc5\x59\x56\x51\x43\x85\xaf\xd4\x50\x98\xe4\x66\x2b\xa8\x4c\x9b\x22\xa1\x50\x1a\xd5\xc8\x28\x9a\x46\x71\x29\x03\x18\xca\xb1\xac\x8c\x6e\x4f\x51\xea\x33\x42\xbe\x5d\x24\xae\xd7\x2e\x59\x62\xd5\x40\x6a\x6f\x86\xb5\x26\xde\xa6\x63\xe6\xf1\xd6\xa6\x26\x7b\x2f\xfc\x3e\x14\x9f\x7f\x53\xbb\x5c\xfb\xde\x45\xcc\xe6\xad\x3b\x9e\x51\xf3\xda\x17\xda\xbb\xdc\xae\x3d\xcc\x23\x0b\xdf\x7a\x6b\x4a\xf7\xf7\xdf\x64\xbf\xb9\x6a\xc9\xd7\x3a\xea\x13\xb0\x1e\x4e\x7a\x36\x7b\xe4\x73\x7f\xf8\xfe\x1d\xa7\x69\xda\xe9\xb0\x0e\x7a\x7a\xac\xeb\xce\xbb\xfc\x5b\xe3\xba\x5f\xd0\xf5\xda\xf8\x00\xb7\x12\xc4\xc0\x48\x6c\x1f\xca\xc0\x2d\xe4\x09\x61\x8a\xda\xc8\xe7\x73\x72\x4d\x25\xb6\x8f\x35\xa5\xca\xce\x3c\x44\x4d\xa4\x3b\x90\xa7\xa0\x23\xde\x24\xda\x36\xed\xe3\xca\xab\xcd\x45\xf6\x89\x0c\xb1\x4f\xa5\x61\x1f\x1c\x26\x01\xb5\x8c\xd2\xf2\x20\x59\xc2\x56\xa2\xf6\x69\x1c\xce\x3e\x6d\x60\x58\xf1\xc1\xd6\xf6\x9a\x5a\x43\x75\xd0\x3b\xf6\xf5\x78\x43\xc4\x39\x1e\x76\xbc\x39\x44\x71\x90\xd1\xde\x65\x96\x53\xb5\x41\x26\x73\xde\xdc\x09\xd3\x1a\x9b\xff\x02\xd9\x12\xa9\xc1\x57\x1a\x2a\x77\xea\x7a\x8c\x0c\xe8\xd0\x7a\x88\xdf\xd4\x81\x51\xd8\x2e\xc4\x5d\x9a\xd9\x3c\x52\x12\xa8\x26\xa5\xd6\xeb\xae\xd2\x52\xec\x2a\x38\x1e\xa8\x74\xe5\x33\x95\xa4\xd7\xb2\x32\x6c\x8b\x67\x7d\x95\x55\xd6\xb8\x1a\x13\xf3\x28\x96\x20\x6e\x54\x49\x71\x83\xd8\x8d\x92\x30\xae\xc6\x70\xdc\xcc\x12\x0d\x56\x5b\x5a\xad\xac\x92\xe4\x8c\x52\x4d\x32\x6a\x71\x29\x5b\x56\xe1\x6c\x26\x27\x8c\x7a\xbc\x90\xd6\xa6\x51\xf3\x57\xf4\x1b\x81\x34\x82\xb7\x0e\xe7\x3a\x7d\xf0\x7b\xd0\x59\xec\x3a\xd7\x3c\xdc\xa3\x1d\xec\xbb\x5f\x1d\xd6\x79\x46\xc2\x8e\x22\xe7\xe9\x70\x6a\x4b\x21\x4a\x42\xff\x6b\x45\x1e\x44\x7c\x48\x5b\x41\x7c\xa8\x0e\x24\x40\x3f\xa0\xae\xd3\xc4\xe7\x91\x4c\x30\x6b\xc4\x50\xa3\x06\xb9\x4d\x35\xd5\x29\xce\x54\x55\x63\x5b\x55\x95\x63\x5b\x55\x55\x5b\x09\x9f\x13\xaa\x49\x10\x97\xaa\xd2\x6d\x45\xe5\x01\xc9\xe2\xf4\xd3\x23\xc7\xe8\xe2\x5b\xdd\xec\x46\x91\x7e\x4e\xad\x4a\x1d\x75\xa3\xca\x7e\x90\xad\xac\xaa\x8e\xd0\x75\xb5\x32\xa2\xaf\x35\x35\x25\xc6\xad\xaa\x96\x74\x0d\xed\xb8\x94\x29\x73\x36\x91\x64\x65\xbd\x4c\x2d\xdb\xf4\x55\x3d\x4e\xd0\x41\x95\x5f\xee\x74\x57\x6f\x9f\xa3\xe5\x17\xae\xdf\xac\xbd\x77\x6a\xbf\x9b\xec\xd1\xae\x82\x37\xd5\xff\xfa\x5e\xc3\xfb\xe0\x89\x67\x00\x60\xd7\x91\x7c\xdd\x74\x7d\x3f\xe3\x09\xf5\xbb\x33\x61\x26\xe9\xee\x3c\x92\xa5\x81\x36\x23\x22\xb6\x5f\xb5\x71\x47\x91\xb5\x1f\x64\x19\xd6\x6a\xd3\x7b\xc7\xf4\x4f\x7a\x30\x13\xeb\x82\x4a\x7d\x7b\xc4\x03\xd9\x80\x30\xae\xe6\xd1\x17\x6e\xaf\x65\x36\xd4\x3e\xfe\xc2\xb6\x5a\x34\x97\xcd\xcc\x45\x68\xee\xf1\xd9\x73\x91\xce\xdb\x2e\xdc\x2a\x6c\x05\x12\x88\xe1\x93\x03\xdd\x4d\xdd\x9e\x41\xe8\x63\x14\x49\xe4\x82\x34\x7b\x1a\x8c\xe0\x19\x0c\x56\xd8\xe2\x84\xec\xbb\x86\xe8\x7a\xd3\x8c\x3b\x39\x8c\xe5\x64\xda\x17\x27\x27\x70\x88\x89\x3f\xb9\xcd\x32\xb1\xa9\x58\x3b\x04\xa3\xec\x11\xb3\x9c\x87\x1f\x8a\xbd\xf2\x88\x59\x11\xdf\xcf\x88\x9e\x41\x18\xe5\x02\xf6\x2a\xcb\x09\x2e\xd1\xc0\x28\xd3\x4f\x54\xcc\x8b\x74\x97\x46\x48\x54\x5e\x40\x25\xeb\x18\x02\xdb\x10\xb9\x9e\x61\x20\xca\xb0\x5e\x7b\xda\xc0\x27\xc3\xa7\x07\x4b\xf6\x94\x22\x96\x29\x82\x82\x79\x79\x20\x25\x2c\x29\x51\xed\x21\xfa\xbf\xc2\x53\x96\x2e\x90\x06\xa7\x41\x81\xa2\x97\xd5\xc6\x64\x8a\xe2\x97\xd1\xc8\x94\xca\xda\xf2\xa8\x3e\x89\x52\xa2\xda\x60\xcb\xff\x5b\x38\x66\x34\x23\x91\x9b\xa8\xb7\x77\xcf\x20\xed\xdd\x53\x6c\x71\x34\x3e\x49\xb8\x75\xbf\x02\xbe\x79\x2c\x9e\xb9\x2e\x3a\x5f\x01\xaa\x7d\x57\xe3\xca\xab\xa7\xff\x47\xd0\xe6\x80\x5f\x92\xd5\x89\x33\x08\xb4\xb9\x41\x92\x51\xcd\xbf\x05\x6b\xd6\x97\x7d\x13\xd6\x3c\x64\xe2\xbe\x14\xe7\x8c\x7f\x32\xe3\x42\xf5\x79\xe6\xc1\x02\xcc\x99\xb9\x61\xf0\x74\x9e\x1a\xf8\x1c\xfe\x2c\xf4\xce\x8b\x3a\xea\xd9\x52\x53\x3c\xc1\xa4\xee\x4c\xf0\xa9\x61\x70\x40\xcf\x25\x85\x8b\x90\x3f\xa4\xa9\x81\xd5\x19\x8c\x25\x87\xd9\x78\xa6\x8b\x39\x0f\xe2\xf2\xb6\x8b\x43\x7a\xd0\x0a\xe1\x58\x58\xfc\x2a\x55\x64\x72\xa5\xd5\x63\xb3\xa1\x81\x91\x4c\x29\x77\xa2\x6d\x65\x97\x48\xc8\x4e\xb8\x03\xed\xfe\xb2\x74\x11\x76\xb5\x92\x29\xa9\x25\x8b\x11\x23\x16\xa5\x38\xd6\xd7\x2f\xff\xc5\x92\x5d\xda\xdb\x4f\x3f\xb0\xe6\xbb\x37\xff\xe4\x79\xed\xd5\xaf\x9f\xbe\x5c\x87\xb3\xce\xf5\x6d\xfc\xe3\xd6\x37\xb5\x6d\x8f\xea\x2d\x1f\x70\x52\x70\xe0\x73\x9a\xfb\xb7\x13\x5c\x6b\x18\x3c\x53\x64\x1f\x03\x4d\x44\xca\xf1\xba\x59\x74\x60\x62\xb8\x18\x71\x10\xa6\x71\xab\x4f\xc7\x57\x54\x0c\x66\xd9\xfe\x77\x8d\x43\xe2\x4f\x8f\x98\x4e\xab\x4c\x58\x92\x33\x2e\x19\x5b\x41\xb5\x11\x62\x7d\x22\x1c\x23\xbb\x48\x6d\x18\x01\x09\x89\x69\x04\xe5\x8c\xcd\x57\x96\x2e\xc2\xbd\x96\x14\xdd\x0b\x2d\x20\xb0\xe9\x52\xb8\x1f\xf6\x6a\x4d\x5b\xee\xd9\xac\xfd\xe3\xa1\x4d\x8b\x96\xac\xd9\xb8\xfd\xca\x15\x53\xc7\xcd\xd6\xb1\xb0\x1f\x96\xbf\xf5\xd0\x13\xda\xeb\x3b\xe3\xd0\xd3\xf6\xfc\xde\x6f\xff\x30\xa8\xdd\x0a\xf4\xbc\x6d\x0f\xff\x22\xc9\xe1\xbc\x04\x0a\x4a\x95\x44\xe2\xcb\x86\x4f\x36\xf6\x14\xc1\x2d\x48\x49\x88\x82\x09\x23\x33\xd3\xf1\xf7\x8f\xdf\x23\xef\xa6\xad\xd9\x8d\x84\x7e\x5e\x95\xbd\x47\xdd\xc8\xdb\x6f\x90\xf8\xda\x79\x24\x36\x23\x7b\xb3\x1b\x89\xa2\xea\x08\x1f\xe5\x91\x5d\x54\xa5\xf0\xd1\xfd\x1d\xb9\x8f\x21\x31\x9c\x20\x66\xad\x82\x4d\x89\xe3\xc3\x8c\xe2\x95\x95\x78\xc6\x2a\xd8\x8a\x9a\xc0\x15\xaf\x4c\x74\x8c\x1d\x82\x55\xcf\xda\xc0\x09\x76\x9b\xdd\x21\x4a\xb2\x79\xa7\x70\x90\x56\xd9\x00\x95\x85\x95\x25\x15\x92\x8e\x10\xa2\x85\xd9\x09\x43\x10\x1f\xa9\xe9\xff\xd9\x19\x4b\x2c\xda\xd1\x9a\x98\x38\x6f\xce\x85\xeb\xa6\xb1\x8b\x4e\x00\xa3\xe1\x5b\xfb\x0c\x02\xed\x93\x33\x76\xde\xb4\xf7\xd6\x39\x9c\xe6\xed\xba\x1e\xd6\xc3\x7e\xe8\x37\xd2\x86\x5a\xff\x80\xa6\x7d\xbc\x8a\xda\xeb\x19\x6d\x05\x6f\xe5\x56\x82\x08\xb8\xcc\xd0\xb4\x65\xf3\x19\x2f\xd0\x6b\x49\x6a\xc0\x9e\x47\xbe\x24\x44\xd1\x84\xa9\x7e\xf8\x93\x23\xbf\xa7\x94\xec\xcd\x84\x7f\xdd\x2b\xaa\x1e\x6c\x12\xb7\xa8\xfa\xc2\x47\x59\xa0\xba\x3d\x78\x1b\x71\x7b\xbc\x86\x84\x00\x95\xb9\x55\x81\x48\x1b\xa6\x20\xa9\xb0\x9b\x1a\xe9\x72\x27\x93\x4a\xfa\x03\xb4\xff\x5a\x21\x15\x60\xc1\xcd\xc6\xa2\xe3\x6a\x13\xc9\x33\xea\x96\x5e\x76\x75\xff\xc6\x33\x1f\x9f\x92\xd3\xb4\x4f\xb4\x83\x6f\x7e\x76\x60\x44\x60\xf2\x82\x99\xd3\x63\x93\xcf\x5a\xb7\x78\x3e\xf7\xb9\x78\xe1\x0a\x98\xf8\xf5\xaa\x74\x55\xf8\xf8\xae\x81\x1b\xe0\x56\x76\x95\xb5\x6b\xd3\xa1\x0b\xf6\x6e\x98\xad\xaf\x29\x3b\x49\x4f\xd0\x4b\xfa\x3b\xe3\x2b\x41\xad\x21\x7b\x42\xf5\x38\x74\x0d\x56\x97\x23\x9f\x63\xbd\x04\xb9\xa5\x14\x90\x4a\x7e\x4a\xfd\xe7\x21\xc1\xfa\x50\x14\x9b\xd9\x30\x34\x18\xa9\x44\xe4\x5b\xe5\x7e\x03\xaa\xe5\x13\xb3\xac\x8f\xa1\x59\x19\x4e\xe6\x49\x56\x86\xa7\xd2\x9c\x5e\x1f\x01\x6c\xa9\x82\xdc\x4c\xe1\x6b\xb2\xe1\x0e\x44\x63\x07\xbf\x60\x44\xdc\x91\x91\x54\xbb\x27\x9d\x2e\x80\x98\x20\x03\x8c\xf7\xa6\x7d\x10\x8c\xed\x8d\x0e\xed\xad\x2f\x76\xaf\x59\x7b\xd3\x86\xed\xf5\x17\x9b\x98\xa6\x2f\xd6\x6b\xef\x68\x1f\xb4\x40\x29\x99\x79\x14\x7e\x61\xe2\xd9\xec\xdc\x8b\x5c\x1f\xf0\x81\x37\x0d\xb5\x46\x5f\x29\x9e\x4d\xb7\x52\xb1\x71\x04\xd3\x38\x3a\xbc\xc9\x57\xbc\xd8\xf8\x4a\x60\x6d\xa6\x89\x06\xc3\x9b\x74\x13\xf1\xd4\x46\x5f\xc1\x44\x48\x1e\xc6\x40\xd0\x30\x90\xca\xe0\x55\x87\x98\x48\xf5\xd8\x29\xd4\x0d\x48\x44\xfb\xcb\x40\xb8\x11\x10\x86\x69\xb0\x02\xce\xed\xa3\xd6\xff\xfe\xcd\x5d\x17\x7c\x6b\xc5\x92\xef\x44\x7b\x4d\x50\xd4\xb1\x1d\x47\x07\xc6\x42\xcb\xf8\x75\xb7\xc3\x5d\x26\x36\xaa\x87\x7f\x83\xd4\x19\x9e\xfc\x1f\xc3\x41\xfe\xef\x86\x3f\x32\xd8\x28\x0e\x22\xd2\x41\x74\x3b\x06\xc3\x20\x09\xc2\x69\x30\x0c\x12\xb6\x68\x2f\x90\x85\xe4\xef\x45\x38\x48\xb2\x7a\x14\xe3\x20\x79\x3b\xa9\xfd\xbc\x50\x62\x8b\xff\x0c\x07\x89\x1c\x49\xe2\x33\xa7\x42\x40\xfe\xcf\x18\x05\xd9\x87\x31\x89\x81\x84\x24\x2b\x51\xb1\x87\xfc\x52\x5f\x7d\x8a\x90\x90\x84\xd6\x41\x87\xcd\xe9\xb5\x83\xe5\x78\xdf\x81\xfc\x7f\x50\x3b\xd0\x03\x1c\x57\x1e\x49\x09\x22\x1b\x50\x28\x27\x7c\x49\x15\xe1\xb6\x23\xf7\xea\xca\x7a\x6e\x24\xf7\x73\xaa\x58\x7e\xd4\x8d\x3c\x85\xf2\xc2\xbf\x54\x5d\x98\x60\x67\x78\x07\xe9\x1a\x28\xde\x9a\xe0\x5e\x87\xdb\x53\xfc\xf2\x99\xa5\x06\x55\x94\x74\x59\x98\x7f\xb5\xcc\xf0\x2b\xed\x4f\x67\x69\x07\x6f\x86\xfe\xee\xa1\x65\x86\x2f\x66\x6a\x3d\xcc\x76\x38\xae\x67\xb7\x5e\x63\xd8\x4e\x34\x49\x56\x16\xd5\x18\xaa\x8b\xc9\xe7\x65\x6c\x3b\x5d\x35\x59\x76\x15\x60\x86\x66\xe7\x8a\xd2\x8c\x37\x75\x4e\x95\xd9\xa3\x6e\x24\xf5\x83\xac\x31\x3e\xa8\x4a\xde\x62\xe8\x3f\x9b\x46\x02\x91\x04\x92\xf5\xa6\x88\x21\x05\x09\x3c\x9e\x54\x7b\x27\x6c\x8f\x11\x36\x86\x41\x25\x89\x8f\xb4\xf7\xe7\x69\xf9\xdb\x3f\x75\x59\x2b\x2c\xb6\xf1\x9b\xce\x1a\x5c\x94\x38\xb6\x43\x5b\xc1\x6c\x6a\x6f\x5a\x25\x4e\x3a\x6d\x8f\x89\xb1\x16\xa6\xf3\xfb\x40\xc0\xc0\xd2\xaa\xce\x42\x2f\x8f\x25\x65\x12\xca\x05\x0a\x34\x72\xfd\x15\xc7\x53\x64\x6a\xe5\x66\x37\x52\xfa\x55\xd6\x7a\x94\x27\x10\x3f\x9d\xb8\x06\x39\x9b\xb1\x0b\xa8\x82\xff\x28\x8f\x2c\xfd\xfb\x3b\x57\x1e\x01\x24\x58\x21\x9d\xdb\x1e\x25\x9e\x71\x39\x3d\x45\xcc\x83\x39\x56\x70\x79\x14\x3d\x38\xb1\x31\xac\x45\x70\xba\x3c\xb2\x32\x28\x34\x81\x45\x0b\x88\x62\xd2\xd1\x28\x6d\xed\x31\x18\x61\x63\x0c\x8d\x73\x6f\x9e\x68\x63\x6a\xe1\xfd\x26\x05\xcd\x3f\xb6\xc6\x27\xd9\x06\x9e\xd3\xfe\xd2\x61\x8d\xc7\xb6\xf0\xfb\x8e\x3d\xca\x4d\xd1\x17\x94\xdc\xb3\x9f\x1e\xbb\x89\x5b\xae\xfd\xfa\xb6\x81\x5e\x00\x41\x40\x5b\x61\x59\xc5\xf5\x81\x90\xb1\xae\x64\x44\x5f\xc8\xc4\x4a\xda\x53\x86\xe0\x40\xa8\x48\x3c\xa0\x84\x67\xc2\x8d\x42\x24\xff\xda\x7f\xe5\xe7\xb5\xf8\xae\x1a\x0a\x5a\x51\x50\x74\xa3\x00\xb1\x10\x79\x59\x76\x1c\xf9\xad\x11\xd5\x11\x66\x1f\x87\x17\x87\x74\xfd\xfb\xfb\xbb\xbe\xa0\xb9\x7e\x56\xcc\x72\x2c\x3e\x32\x73\x6c\xd1\x91\x19\xec\x63\x1d\x52\x20\xc8\xf1\xc6\x0b\x31\xc1\x0e\x59\x1c\xc3\x15\xdd\x2b\xb1\x13\xe9\x72\xa3\xc4\x03\x95\x30\xd0\xd6\x0e\x8d\xb5\xc5\x0d\x05\x18\x63\xeb\xea\xd9\xc0\xc7\xf0\xd6\x71\x0e\x1b\x3f\x61\x06\x74\xc3\x3d\x07\x34\x42\x2c\xf3\xd7\x3d\xe5\x73\x1b\xb5\xc3\x1f\x74\x95\x09\xbb\xb9\x3e\x2d\x36\xef\x86\x69\xdb\xd7\xc3\xf7\xe8\x92\xc3\xd6\x77\xde\x7c\xc6\xc0\x17\xf0\xf3\x17\x97\x1d\x7f\x5d\x8f\xe1\xfe\x8f\xe5\x3e\xd8\x13\x57\x03\xc0\xf7\x09\x5b\x81\x00\x82\x20\x02\xbe\x53\xa4\xd7\xcf\x80\x78\xce\x12\x22\x45\x04\x8b\x23\x8f\x02\x89\x9c\x87\x1e\xae\x3d\x01\x7c\xb8\xf6\x28\xb6\x38\x11\x90\x88\x26\x90\x95\x70\xa7\xd5\x51\xee\x34\x43\xd9\x2e\x86\xd7\x3d\xab\x24\xab\x30\x44\x60\x60\x59\x3e\x10\xae\xa2\x2a\xb2\x19\xc6\x43\x51\xbc\x30\x44\x4a\xc8\x86\xb0\x5d\x84\x55\x06\x1f\x6c\x95\x08\x9b\x80\x31\x8b\xb0\x86\xd1\xe0\xaa\x9b\xb4\x37\xca\xb4\xfa\x3d\x7f\x1b\x7c\x6c\x1d\x0f\x4f\x0f\xf1\x2c\xdf\x36\x9a\x3f\xf0\x45\x37\x5c\xa8\xed\x2c\x49\x3f\x1c\xdb\x06\xfb\xae\xde\x76\xd3\xc5\x06\xaf\x2e\x37\x60\xe9\x02\x32\xa8\x01\x49\xb0\x9c\xf2\x2b\x50\xd0\x8a\x8d\xf0\x22\xe1\xa0\x39\x61\xcb\x0f\xcf\x45\x85\x23\x69\x0a\xce\xaa\xf5\xe4\xb3\x4a\x2d\x28\x70\x51\x8d\x86\x71\xb5\xac\x16\x9f\x35\x89\xf4\x4b\xc2\x29\xc9\x59\xe0\x72\x13\x58\xaa\x4d\x32\xc4\x13\x08\x33\x5a\xaa\x3d\xc5\x0e\xc7\x54\x44\xc6\xeb\x2d\xe4\x04\xdc\x70\xc1\x0d\x1f\x5e\x7f\xce\xe6\x7a\x6b\xfa\x83\x8f\xfe\xe8\xb6\x5e\xf3\xc8\x4d\x3f\xfd\xef\xc1\x63\x1f\x3b\xb9\x73\xca\xf7\x67\x9f\xde\xd5\xbd\x66\x06\x5c\xf7\x2c\xbc\xe0\x99\x79\x73\xb6\x1c\xdb\xb1\xf5\xbe\xd7\xf9\x33\x8a\x6c\x70\xbc\xa2\xb7\xf7\x9a\xf7\xb6\x4e\x5b\x74\xc3\x61\xec\x73\x1c\xd1\x5c\xdc\x29\xf4\x00\x01\x78\x40\x10\xc4\x0c\xdd\xc5\xc2\xcc\x5b\xcd\x99\x2f\x4b\xa0\x68\x4a\x55\x1c\x79\x42\x0c\x55\x93\x40\xa2\x49\xa6\x1d\xa2\x29\x4d\x54\x25\x22\x16\xaf\xde\x84\x25\x2a\x41\xa6\xbf\x96\x14\x11\xf0\xd1\x1a\xba\x74\xd5\x45\xde\x96\x4e\xab\x6c\x48\x92\x33\x4c\x05\x05\x4e\x42\x2b\x09\xf4\x0a\xf3\x0f\xf5\xe9\x66\x47\xb7\xa5\x92\x04\x0f\x58\x6b\x7e\x2a\x76\x01\xd8\x60\x4c\xf9\x1d\x67\x4c\x5f\x3b\xfd\xf4\xab\xe0\x55\xf4\x7f\x0d\x0f\x60\x16\xd3\x49\x67\xde\x98\x3d\xe7\x92\x19\x67\x5e\x4a\xae\x80\x23\xf3\x7f\x8f\x85\x03\x32\xa8\x26\x58\xe4\xeb\x86\xf7\x80\x0a\x5b\x1e\x35\x24\x50\x2a\xa5\xd6\x38\xf2\xa8\x39\x69\x80\x91\x15\x0f\xc9\x21\x45\x60\x5c\xad\x73\xe5\x51\x1d\x49\xd7\xa2\x50\x52\x1d\xa5\xe3\x91\x23\x0a\x6d\x72\xac\x93\x32\x5c\x85\x9f\x64\xb5\xe5\x8c\xd3\x4d\x4c\x30\x4a\xca\x08\x36\xda\x2e\x5b\xa1\xbb\x87\xff\xd4\xee\x51\x5b\xe2\x0d\xca\x30\x46\x19\xea\x21\xb0\xa5\xe0\x11\x81\x52\xe3\x94\x3a\xc8\x2b\xa6\x4b\xb0\xe7\x16\x1b\xc9\xd0\xe4\x14\x28\x26\x47\x01\x63\x75\x16\x12\x90\x22\x00\x6d\xb2\xa7\x29\x44\xa6\x35\xe7\x16\x9d\xd8\x4d\xdc\x8e\x7c\x8e\xb7\x3a\xcd\x82\xa3\x49\x41\x1a\x83\x26\xf5\x09\x09\xcd\xf0\xea\xb9\x86\xbd\x93\x9b\xd3\xa6\x81\xc9\xf0\xed\x76\x2d\x7a\x06\x03\xda\x8e\xbf\x3a\x53\xeb\x79\x0b\x5e\x05\x3b\xae\x9a\xc3\xef\xd3\xb4\x5f\x6a\xda\x86\x13\x80\x4e\x23\xd3\x6b\xf2\x61\x3f\xc7\xad\x04\x23\xc1\x58\x30\x19\x3c\x4c\x3b\xec\xc9\x81\x17\x35\xa6\xd4\x90\x90\xa7\x93\xe7\x86\x44\xdb\x58\x9d\xc8\xe7\xc9\x67\xb5\xdd\x96\xcf\x79\xc7\x55\xbb\x5d\x71\xd5\xeb\xcc\x1b\xe4\xc9\x4d\x9e\x3c\x6a\x12\xb1\x8f\xea\x38\x57\x54\x23\x12\x36\x3e\xc9\x45\xa9\x94\x6b\x9b\x24\x39\xcb\x35\x8e\x6a\xc7\xf3\x53\x23\xe5\xac\x42\x5d\xfd\x68\xfc\xb9\x4b\xde\x67\x73\xfb\xfc\xa1\xea\x71\xf8\x9b\x24\xa9\x15\x44\x72\xd0\x5b\x2b\xc9\x0f\x81\x8a\xca\x58\x5d\x7d\xd3\xa8\x9a\x40\x5a\x6d\x1f\x27\xc9\x19\x69\x74\x57\x3a\x9d\x56\xdd\x13\x25\x59\x15\x1c\xe9\xd2\x39\x16\x74\xb0\xe3\xe0\xea\x4e\xbd\x10\xd3\xa3\x92\xd2\xd9\x37\xb3\xef\x0b\x36\xe6\x7f\xb4\xe8\x7b\x29\x47\xfa\x80\x3c\xf2\x8e\x85\x77\x67\xb5\x8c\xf6\xe2\x68\x66\xc5\xb2\x49\x7b\x66\x65\xf7\x2d\xdf\x9c\x10\x0f\xb8\xed\x33\x6f\xee\xbd\xf1\x27\xb0\x65\xe2\xd8\xe9\x6b\x67\x4c\x9a\xd2\xfd\x9d\xa9\xcc\x2e\x9a\x90\x87\xeb\x9e\x87\x67\xbf\x78\xda\xfc\x2d\x0b\x5a\x3a\xef\xbf\xee\xd1\x17\x15\x65\xf1\x05\xcd\x23\xde\xed\x69\x1b\xdf\xb7\x75\xe1\x8c\xdf\xbd\x30\x6f\xe1\xa6\x0f\xd7\xcc\x59\x7c\x5d\x7e\x8d\x5e\x16\xa2\x9c\x52\xbc\x28\x6c\x05\x0e\x50\x01\x7e\xa8\x47\x37\xa6\x23\x70\x2c\x9e\x7a\xa3\xd6\x8c\xc2\x89\x9c\x42\x97\x4d\x25\x8c\x97\x4d\x25\x60\x8b\x23\x77\x92\xc0\x49\x9c\x87\x10\x4c\xe6\x24\xba\x53\x70\x49\x93\xdc\x65\xd7\x91\xc3\x7a\xf6\x06\x41\x8a\xd0\xb2\x89\x2a\x20\xff\x93\xb5\xda\x78\x25\xce\x66\x01\x6f\x6e\x6f\xc0\xe0\x65\xa1\x5e\x35\x24\x15\xda\x0a\x5b\xd9\xa4\xe1\x5e\xb1\x39\x0c\x68\x1b\xd0\x06\x2f\x9a\x05\x27\x2b\x4d\x54\xd3\xfd\xe1\x4f\x96\x2e\x50\x06\x1a\x41\x0a\xdc\xa5\xf3\x97\x89\x82\x0e\xb6\x6f\xe1\xf3\x39\x7b\xdc\xcf\xb9\xe2\xaa\xdd\x49\x44\xc4\xaa\xe9\x68\xab\x47\xe0\xd1\x56\xd7\xd8\xe2\x28\x9c\x84\x68\x74\x02\x05\x0f\xe5\x2a\xc9\x50\xb3\xae\xca\x60\x69\xf3\x50\x25\xcd\x2e\x0b\xae\xbc\xda\x4a\x0a\x68\x92\x9c\x71\xf8\xe3\x78\x8d\x48\x48\x39\x91\xab\x1e\xd1\x42\x29\xa2\x33\x8a\x37\x46\xd6\x0b\xbb\x28\xc9\x2a\x50\xd2\x69\xb5\x25\x3e\x58\x8a\x67\xb0\x03\x0d\xdd\x53\x4c\xcf\xb9\x0f\x86\x32\x43\xca\x84\xbf\x1f\x6c\x9d\xcb\x75\x57\xd9\xf6\x2a\xfc\x46\xb6\xa4\x5c\xc8\x4f\x2a\xb2\xd6\x80\x8f\xb8\x08\x03\xba\x4f\x1c\xe6\xad\xfc\xcb\xa0\x0c\x44\xc1\x85\x06\xe3\x1b\x9b\xcf\x78\x48\x4b\x87\x23\x9f\xab\x62\xfd\x1e\x57\x5c\xad\xb2\x53\x85\x41\x70\x48\x0d\x7a\x08\x15\x97\x05\xc6\x55\x59\xcc\x13\x35\x8a\xa0\x99\x2a\xb1\x48\x39\xce\xe6\xf1\x57\x51\x39\x8a\x72\x2a\x41\x64\x63\xf1\x8f\xe5\x34\x11\x61\x24\x8a\xe0\xa3\x6b\x22\x29\x83\x94\x41\x6a\x33\x04\x4d\x4c\x55\xa2\x58\xd4\xd2\x0d\x6f\x85\xd7\x5d\xcc\xfd\x68\xcb\xf2\xdc\xd7\xb3\xef\x43\x07\x8c\xbe\xa8\xed\x78\xe7\x37\x1f\xc0\xd4\xec\x8e\x4d\xaf\x4d\xb8\xf3\x89\x57\xe0\x79\xff\xfd\x69\x59\xc3\xcd\xbb\x46\x56\x43\x66\xb6\xf6\x5b\xed\x43\xed\x84\x36\xf5\x83\xa7\x7f\x39\x7e\x4a\x2e\x73\x05\xf6\xfd\xd4\x89\xc3\x5c\x98\xa3\x9a\x3b\xcb\xf4\xb1\x85\xf9\x3c\x29\x4b\xd0\xae\xb1\x2a\x32\x36\x16\x2f\x2e\xd1\x62\x9a\x31\x4e\xa7\xac\x8b\x19\x63\x73\x38\x69\x1c\x64\xf5\xf8\x2b\xe9\xd0\xc2\x74\x68\x56\xd6\x10\xec\xf6\x48\x64\x37\x24\x43\xa3\xe2\x50\x42\xab\xbe\x4c\x98\xa2\x23\x64\x64\x29\x78\x3a\x6c\x4b\xb1\x64\x0e\x2f\xd8\x7b\xe1\xaf\xf3\xf7\x6a\xef\xed\x55\x9f\x85\x91\x65\xbd\xdb\x82\x4d\x77\xfd\x1c\x56\xec\x7f\xb1\x01\x4f\xda\x9f\x5b\x6a\xdf\x7d\xf9\x25\x6d\xcf\x43\x3f\xb9\xb9\xef\xee\x55\xe7\xe0\xbd\x9f\xce\x97\xd0\x43\xe6\x6b\x24\x68\x03\x5b\x4f\x3d\x67\x28\x9e\x40\xad\x29\xb5\xce\x91\x47\xa3\x92\x46\x7f\x89\x3e\x81\xb1\x02\x38\x5d\x9f\x4b\x22\x99\x87\xaa\x52\x6a\xd2\x95\x27\x5d\x26\xb1\xa0\x24\xab\xfe\x72\x0a\x09\xf7\xe0\x10\x20\xd9\xa4\xa3\x65\xfe\x93\xb9\x1d\x6e\x33\xfc\xf2\xf9\xde\x35\x68\x43\x3c\xd5\xf4\x73\x6f\x95\xec\x8a\x1c\xf5\x05\x0b\x47\xec\x16\x07\xad\x60\xdb\xff\xc7\xde\xbb\xc7\x45\x59\xad\x7f\xc3\x6b\xdd\xf7\x3d\xf7\x0c\xe7\x39\xc1\x20\xe7\x61\x84\x11\x47\x40\x18\x86\x01\x39\x1f\x45\x40\x44\x44\x44\xc4\x11\x11\x11\x54\x52\x44\x45\x25\x22\x24\x52\x54\x54\xd4\x3c\x8b\x84\x44\xe6\x76\xdb\x0c\x12\xa9\x99\x4a\x6a\x56\x66\x6c\x37\x99\xbb\xdc\xe6\x36\xd3\xa2\xc8\xcc\xfa\xf5\x33\x85\xc5\xfb\xb9\xd7\x7d\xcf\x30\x20\x5a\xbf\xe7\x7d\x9f\xf7\x7d\xfe\x78\xff\x08\x07\x3e\xcd\x3a\x5c\xeb\x5a\xd7\xba\xae\xb5\xae\xeb\xfb\xe5\xe4\xe6\x35\x44\x1f\x7c\x8c\xfa\xa0\x97\xfb\xeb\x83\xd4\x06\x17\xab\x1e\xbd\x7f\x20\xd4\x07\x33\x26\xc1\xe0\x66\xd3\x73\x5c\x61\x6e\x0f\x14\xac\x3d\x18\x07\x55\xfa\x31\x81\x86\x00\xc6\x81\xc2\xe8\x58\x76\x3d\x06\x2d\x63\x1b\x14\x22\xf1\x3b\x76\x02\x07\x17\x4c\x40\x62\xa0\xd8\x72\x58\x7d\x80\xc8\xe0\x1f\xc4\x18\x06\x1f\xaf\xff\xa9\x0e\x41\x93\xb8\x24\x46\x6d\x1a\xfc\xd3\xb3\xf4\xca\x8d\x95\x17\x69\x54\xaf\x17\x39\xf9\x3d\xad\x66\x14\xeb\x70\xf5\xa9\x18\x75\x23\x1f\xb0\xc2\x23\xb9\x37\xd6\x2c\x20\x02\xce\xc0\x0b\x74\x3d\xfb\x95\xd5\x09\x27\x1b\xd8\x5b\xf5\xe8\xdd\x59\xc6\x73\xd3\xd3\xaa\xf1\x46\xf2\xb8\x8c\xe6\x09\x54\x2c\x0a\x94\x3f\x7e\xca\x73\xc1\x7f\x90\x9b\xf1\xbe\xfe\xbf\xf3\xb8\xca\x13\x89\xf5\xf6\xcf\x7a\x5a\x7d\x5a\x3d\xff\xe4\x75\x95\x08\x19\xaa\x9c\xcf\x7a\x5b\xa5\x4f\x0c\xd1\x4b\x92\x7b\x5b\xa5\x40\x28\x88\x03\x93\xa1\xcd\xff\xa6\xd7\xd5\x58\x7f\x7d\xaa\xda\x10\x61\xd5\xa3\x9f\x18\x08\xf5\x69\x7f\xe9\x49\x35\x50\xa8\x8f\x62\xb4\x79\x82\x4d\x8f\x7e\x02\xde\x0d\x51\x36\x3d\xc7\xe3\xf1\xff\x36\x89\x85\x94\x32\x3e\xb3\x4e\xf9\x6b\xcf\xac\x64\x9b\xbd\x63\x00\x77\x0f\x18\xa8\x16\x89\x0d\x11\xb1\xa1\xa1\x86\x49\xf1\x22\xb1\x7e\xd4\xff\xd3\x6f\xac\x4f\xaf\xe0\xff\xd2\x33\x2b\x69\x31\x74\x5d\xff\xfa\x23\x2b\x6f\xcd\x30\xbf\x9c\x04\x3e\x03\xbd\x94\x9e\x9f\x05\x94\x20\x00\x84\x81\x3d\xac\x1f\x8c\xf1\xbf\x8c\x30\x53\x66\xf8\x52\xfa\xf1\xfe\xfa\x09\x6a\x83\xca\xaa\x47\xaf\x09\x84\xfa\x70\x7f\xfd\x98\x2f\x0c\xbe\x36\xd8\xf7\x35\x22\x4d\x79\x0a\xf5\x5a\x66\x89\xf0\x72\xf9\x1b\xb4\x6c\x6d\x8b\x09\x7f\x2a\x82\xd9\x73\xbe\x98\xda\x4e\xef\x29\x6a\x73\xd3\x4c\x60\xfd\x11\xc6\xdc\xc0\x11\xd0\xa6\xf4\x32\x91\x5e\xfa\x3f\xc0\x9c\x1a\x49\xca\x7f\x8a\x3b\x05\xb3\x86\x4a\xf4\xb9\xd8\x53\xf4\xe1\xa1\x42\x24\xc1\xa8\x81\x5e\xb2\x8f\xa6\xc0\x68\xe0\x07\x42\xc0\x6e\x16\x7d\xca\x40\x0a\x7a\x4c\xd0\x53\x66\x98\x53\x7a\x5f\x7f\xbd\x56\x6d\x18\x63\xd5\xa3\x0f\x0c\x84\xfa\x50\x7f\xbd\xd7\x17\x86\xb1\x36\x3d\xfa\xb1\x58\x77\xf5\x36\x81\x86\x20\x9b\x1e\x7d\x90\x50\xef\xce\xc8\x8c\x67\xd7\xa3\xe7\xf9\xe3\xe2\x69\x7f\x21\xae\x52\x9d\x00\x55\x06\x7f\x2f\x91\xf8\x38\x29\x74\xc0\x74\x1f\x41\x22\x0c\x41\x85\x2d\x36\x1c\x01\x76\x4a\xef\xc0\x89\xf0\x2f\x81\x4f\x8d\x20\xbf\xe7\x03\x50\xfd\x31\x54\x76\xcf\xc4\xa0\xe2\x65\x0c\x95\x1b\x1c\xe8\x1b\xe8\xa5\xea\x78\x1d\x60\x14\x48\x60\xb9\x07\x0d\x94\x05\xe7\x31\x60\x30\x59\x27\x6c\x13\xec\x85\x38\xb1\xd2\x60\xcf\x17\x89\xf5\x36\xa1\xc0\x40\x39\xb2\x8f\xa1\xb6\xa2\x36\x28\xc6\x35\x81\x76\x2c\x8e\xa0\x52\xe4\x06\x4d\x4a\x02\xe5\x12\x4c\xce\x6c\x2f\x05\x72\x4f\x2a\xe5\x7a\x72\x53\xdb\xcb\x6b\xf7\xf8\xc2\x0a\x14\xa0\x25\x73\x54\x48\xf5\xb7\x33\xe8\x1d\xf4\xd5\xc3\x30\xc8\x1f\x1b\xfa\xf2\xf2\xb9\x33\xaf\xc0\x5c\x08\x2e\xa0\x1c\xc9\xe9\x96\x1f\x50\x3f\x33\xbe\x56\x24\xa4\x7c\xf1\xdd\x63\x1c\x60\xa3\x3f\x1b\x41\x8f\xde\xd1\x9f\x65\x0f\x77\xf6\xd7\xd3\x98\x70\x1e\x97\xb4\x4b\x69\x7c\xf3\x00\x0c\xa4\x23\xcb\x25\x6d\x23\x6a\x03\x22\x8c\x04\x69\xcb\x82\x11\xf1\x87\x0c\x4e\xcb\x0d\x0e\x3f\x76\xe7\x24\x9e\x9d\xd2\x7c\x66\xfd\x8b\xeb\x7c\xe1\x16\xe4\x1c\x40\x66\xf9\x20\xf7\xbf\x5d\xdc\x87\xbe\x79\xef\x7a\xf3\xce\x31\xc1\x6f\x6e\x2a\x5e\x71\x1d\x56\xf7\x5c\x40\x51\xc2\x2b\x4d\x6f\xa3\xdf\x1a\xd2\x8d\x71\x14\x2d\xa5\x11\x8e\xa9\xef\x18\xe3\x28\x4b\x73\xc4\x27\xbd\xd0\xdf\x20\xe2\xf5\x98\x01\x14\x99\x03\x0d\xd8\x3f\x17\xee\xfc\xe0\xc3\xcb\x46\xd4\x01\x9b\x73\x3c\x16\x76\x60\x04\xac\x73\x8c\x3f\x60\x23\x51\x1d\xb7\x66\x7e\x0e\xc3\x3a\xb7\xb2\xb4\xe1\x32\x9e\xdb\x49\x9e\x0d\x07\x4a\x00\x3b\x00\xc9\x13\x18\x7f\x33\x4f\x6a\xa5\xed\x42\x43\xf5\x96\x22\x36\xbd\xc2\x42\x6c\xe0\x9b\x92\x5a\xf5\xb6\xe6\x90\xe7\x50\xce\xc2\x9d\x6b\xe5\xfc\x21\x10\xe7\xe8\x32\xea\x65\xc1\xcd\x6f\xfb\x12\x8b\x7c\x4d\x80\xe6\x8f\x93\x8d\x60\xe6\xb4\xaa\xbb\x1b\xcb\x6e\xc9\x40\x2f\xd5\xc6\x3b\x0a\x1c\x80\x13\x58\x0e\xd8\x84\x80\xc1\x34\x72\x1b\xb5\x5e\xe6\x6f\x70\xe4\xf5\x98\xf1\xd9\x9a\x01\x97\x0f\xd6\xca\xe0\xb5\xe7\x93\x22\xb1\x5e\xca\xf8\xe2\x6d\x16\x32\x47\xb6\x70\xa5\x4d\x28\x12\xb3\x64\x98\x6d\x76\x1c\x47\x26\x29\x14\x89\x8f\x03\x0b\x91\x98\xa3\xbc\x1b\x0a\x37\xce\xdd\xd0\x40\xad\x9c\xbf\xc4\xd1\x1c\x5d\xfc\xa7\x7b\xf6\x56\x0d\x57\x36\x6c\x83\x09\xcc\x9c\xa0\xef\xec\x55\x66\x68\xe2\x4f\x9a\xbb\xee\xbc\x41\x25\x31\x93\x22\x59\x7d\xe0\x67\x71\x37\x70\x0f\x46\xd6\x88\xa7\x6e\xdf\x06\xf5\x42\x38\x98\x87\xca\xa9\x88\xde\x09\x97\x86\x9b\x65\x99\xfd\x9f\xa0\x2b\x16\x96\x22\xf1\x71\xbe\xad\xab\xa7\x09\x3c\x6d\x64\xf5\x18\xc1\x94\x3d\x43\x5d\xee\x0d\xbb\xf4\x1b\x41\x71\x86\x38\x49\x24\xab\x3f\x34\x05\x1c\xf0\xbd\xdf\xab\x23\x69\x90\xbb\xbf\xde\x47\x6d\x70\xb2\xea\xd1\x8f\x36\x91\xa7\x3e\xa5\x47\x32\xa8\x32\x02\xb1\x1a\xcb\xaf\xe4\x8c\xcc\xbd\x39\x96\x55\x16\xb2\x5e\xea\x1e\x1a\x1a\x8a\x71\xc0\xdb\x84\x62\x4c\xb2\xea\x2d\xd2\xdb\xfd\x65\x9d\x1a\x41\x10\xcf\xd0\xb1\xa8\x61\xf1\xcc\x48\xda\x76\x6d\xa8\x1d\xa7\x58\xde\x63\x7e\x16\xe6\x67\xf1\x02\xfe\xa0\x64\x38\xf3\xb1\x23\xd9\xc3\x68\x9a\x9f\xda\xe0\x6e\xd5\xa3\xf7\x31\xe6\xb2\x1a\x39\xc7\x98\x3d\x24\x67\x26\x3e\xc8\x4c\xea\xcd\xc8\x40\xc5\x66\xad\xb2\xf3\xb6\x72\x34\xce\x9b\x89\xf4\x1c\x45\x22\xb1\x81\xcf\x42\xa2\x3f\x87\x7d\x74\x24\x15\x78\x2e\xf5\xe8\x91\xa1\xf3\xff\x13\xb6\x51\xf2\xdb\x61\xfe\x14\x7b\x1f\x9c\x49\x53\x98\x67\x54\x01\x7c\x41\xb9\x19\xd3\xa8\x89\x5c\xd4\xd3\x9f\xf1\xa1\x5d\xad\x18\x1f\xda\x98\x2b\xcf\xc5\x24\x4e\x56\xc6\x1b\x70\x13\xdb\x28\x86\x67\xf0\xb1\x61\x93\xe6\xdd\x6d\x19\x59\x08\x1d\x18\x7d\x90\x02\x96\xd5\xc3\x47\x64\x50\x62\xb0\x53\x07\x7c\xab\xc3\x0f\x7d\x2e\xb9\xe8\x88\xb7\xbe\x23\x33\x8b\xc2\x61\xda\x30\x12\x99\x28\x39\xe5\x29\x9f\xf2\xff\xe7\xc1\xfe\x3f\x85\x07\x9b\x67\xb6\x37\x99\xf1\x8f\x01\x81\x60\xd3\xf3\xd7\x43\xaf\xf4\xd7\x07\xa8\x0d\x9e\x56\x3d\xfa\x71\x81\xc3\x78\x83\xdd\x21\x97\x5c\x6e\x5a\x27\xbd\x0f\xa3\x9c\x7e\x1c\x81\x30\xa3\x9c\x06\x7b\x19\x26\x0c\x6e\xb3\x72\xc1\x1b\xd6\x07\xab\xa8\x1f\xe3\x82\xfe\xcf\x97\xf0\xaf\xed\xdf\xa7\x96\x35\xe4\xaf\xec\x62\xd3\x2a\x13\x2d\x43\x34\x98\x67\xb6\x87\x19\xeb\xce\xc8\x6c\xfd\xf0\x75\xf7\xb6\xe8\x69\x97\xb3\x32\x93\xf3\x30\x4f\x76\x00\x6b\xea\xcd\x64\xc6\x2a\x81\x99\x81\xf7\x81\x2a\xbd\x34\x90\x91\x96\xde\x93\x11\x1b\x9f\x13\x9b\xcc\x16\xc7\xfd\x7a\x17\xd1\x71\x2b\x91\x1c\xe3\xa6\xf8\xb0\x17\x5a\x46\x79\x79\xcb\x9f\xaf\x27\x83\x72\x92\x70\x1a\x03\x9f\xb1\xb7\x4d\xba\xc3\x67\x65\xe3\xc9\xa9\x50\xe8\x08\x5b\x9c\x55\x25\xf2\x14\x16\x4c\x7f\x0b\xa3\x52\x44\xae\xd9\x3e\x77\x1e\xe8\xa5\x5a\xf9\x59\xc0\x05\x57\x78\xac\x03\x6d\x4e\xc6\x7c\x41\x09\xa3\x57\x36\x64\x4f\xbb\x80\xef\x24\xb1\x51\x19\x04\x64\x8f\xde\xcb\x5f\xef\xaf\x36\x78\x58\xf5\xe8\xc7\xb2\x55\x1f\xae\x5f\xb0\x18\x13\xac\xb7\xe1\x20\xec\xd1\x2b\x19\xa9\x8c\xe3\x58\x95\x3d\x5d\x45\xe2\x36\x89\x93\x0d\x06\x00\x51\x8a\xc4\x06\x0b\x3a\x34\x54\x3f\x4e\x64\x18\xeb\xcf\xd8\x3a\xec\x74\xc1\x50\xf6\x49\x98\xb1\x87\x7a\x89\x08\x47\x01\x6c\xa4\xa8\x95\x6b\xe5\x5a\x8d\x50\xce\xc6\x38\xa6\xfb\xbe\x91\x8e\x42\xe7\xbf\xbf\xff\xd6\x57\xe1\xfd\x77\x35\x84\x1d\x81\x50\x4c\xe5\x2b\xe9\xff\xf8\x1e\x12\x50\xf4\x21\xfa\xdb\x9d\xd5\x9d\x30\x70\xa8\x32\x45\x41\xbb\xbc\x77\xdf\x47\xa3\x9c\x60\x88\xb3\xfa\xf7\x1c\x74\x03\x3d\x40\xbf\xa1\x84\xbb\x5e\xf4\x9b\xc3\xe3\x42\xf7\x81\x5e\xb2\x86\xa6\x80\x2b\x8e\xae\xd7\x82\x36\x17\x63\x8c\x63\xcf\xe8\x90\x9d\x05\x13\x17\xba\xd8\x33\x71\xa1\x75\x8f\xde\xdb\x5f\x3f\x5e\x6d\x90\x5b\xf5\xe8\x55\x81\x50\x1f\xe8\xaf\x77\xfb\x02\x5f\xe6\x29\xd8\xaa\x20\x26\xcc\x76\x0c\x64\x22\x6d\x2b\x9b\x1e\xbd\x95\xbf\x41\x0d\x55\x06\x85\x1b\x63\x55\xec\x5d\xec\x18\x9d\xb1\x12\x19\x2c\xf9\x8c\x68\x04\x14\x2b\x1a\x3b\x0b\x91\xd8\x20\x76\xc4\x40\x57\x7a\x09\x8e\x00\x71\x0c\xc2\xca\x66\x48\x00\xc8\x08\x67\xa4\xcd\xe6\x1e\xb4\x2a\xad\x74\x93\x1c\x6d\x52\xc1\x02\x62\xc6\xd4\xd0\xd9\xa1\xe9\x2d\x27\xce\x5f\x6f\x40\xbd\x67\x77\x17\x0d\x15\x8c\xa2\x6f\x94\x72\x45\xc5\x65\x89\x74\xd6\x3c\x0f\xe7\x9b\x19\x3f\x5c\xbf\x86\xce\xbc\x3d\xec\xc6\x81\x60\x64\xc2\xab\xa5\x11\xf6\xbb\x27\x82\x36\x7b\xac\x31\x56\x3d\x6d\x02\x02\x13\x8b\x98\xbb\xdd\x82\x2f\x70\x72\x32\xe3\x1d\x58\x08\x44\xe2\x36\x12\x03\xc0\x00\x03\x69\xcf\xc6\x7f\x02\x63\x32\x2c\x5e\x71\x4c\x93\x2d\x71\xc0\x59\x15\xd0\x96\x50\x78\x32\x9e\xb4\xfb\xd4\x15\xe3\x93\xa3\x02\xd0\x1d\xa8\xde\x2b\xa3\xfd\xec\x61\x36\x4c\xeb\x6f\x7d\x65\xdb\xd1\xf2\x17\xe1\x2a\xc6\x9d\xb6\x86\x56\x4a\xcf\x98\xa9\x94\xb8\xbf\x6e\xf6\x84\x17\x94\xc4\xea\x27\x8f\x6f\xef\x9d\x44\x47\x75\x77\x03\x62\xa0\x0c\x49\xa9\x06\x2e\x46\x48\x00\x6d\x7c\xb6\xc0\x54\x2f\xf5\x37\x10\x96\x3d\xe6\x23\xe5\x7f\x61\x10\x70\xb1\x80\x80\x2f\x12\xb7\xd1\x38\x0a\x00\x06\x42\xca\x56\x5e\xf3\x45\x06\x80\x9f\xeb\xf8\x23\x13\x7b\x33\x43\xad\x7f\x0e\x89\xf7\x57\xcc\x50\x7b\x46\x22\xed\xa6\xdb\x70\x3c\x43\xb2\x72\xe5\x67\x71\xfe\xe8\x4b\x23\x48\xf6\x29\x77\x54\xf6\x85\x9e\x1f\xc8\xd8\xa6\xe3\x16\x2e\x32\x01\xc6\x0f\xd3\x0b\xfc\x19\x99\x33\xc6\x8a\x7b\x92\xc6\x4e\xa8\x8c\xd9\x63\xa4\x7d\x68\xa8\xc1\xc5\x42\x24\x6e\xb3\x76\xc2\xee\x28\x36\x4a\x76\xff\x83\x05\x19\x49\xbf\x9e\xb3\x40\xb3\x86\xea\xd7\x33\x96\xea\xd3\x21\x7e\x39\xbb\x66\x26\xbf\xbc\xfc\xa9\x55\x1b\x41\x0a\x58\x04\x02\x2c\x02\x9c\x39\xe6\xcf\x2c\xe6\x53\x22\xe0\x63\x2c\x11\x83\x0b\xa3\x89\xb6\x66\x02\x10\xfe\x4f\xd6\x79\x04\x09\x3c\x6f\xdd\x3f\x1b\x2a\x81\x11\x35\x80\x1f\xf5\x94\xff\xc5\xea\x42\x19\x70\x00\xee\x60\x0c\x88\x7d\x5a\x17\x30\x81\x0d\xb7\xbd\xc6\x72\xdb\xab\x9d\xe4\xdb\xcb\x1c\xb1\x77\xf2\x57\xd7\x53\x13\xac\x95\xdb\xdb\x42\xbe\xda\xf8\xe1\x79\xab\x59\xb8\x6c\x05\x0c\x50\xdd\xc8\xbb\xc1\xfd\xfb\xac\x9d\x37\xea\xe5\xb7\x45\x9a\xf7\x13\xb8\x7f\x98\xf9\xe0\x35\xbd\x46\xcb\xb9\xf9\x44\x0e\x5f\x53\x3c\x1b\x6e\x0b\x8e\xfd\x5f\xde\x82\x4f\x4d\xe6\x79\x0b\xf3\xfe\xb0\xc9\x3c\x63\x6f\x3e\x3d\x17\x16\x6f\x80\x9f\x05\xa4\x8c\x37\x06\x2d\x59\x7c\x1b\xbd\xad\xda\x3c\x47\xb4\x5d\x6c\x61\x47\xda\xa8\x70\x61\x82\xab\xbf\x5e\xa9\x36\x38\x5a\xf5\xe8\x3d\x03\xf1\x44\xff\x24\x69\xf4\xb8\x3d\x45\x0a\x58\x58\x40\x4a\x68\xb0\x63\x42\x4a\x8c\xc1\xc5\x81\xbc\x31\x91\x05\x66\x58\x60\x5c\x13\x6b\x2b\x36\x93\x74\xec\x5f\xc1\xa3\x18\xf2\xf4\x61\x65\x67\x8d\x59\x9b\xac\xf1\x43\xc7\xb0\x6c\xd1\xe3\x04\xcf\x8a\x7d\xde\x30\x30\xff\x0e\x26\x86\x8a\x43\x0d\x4e\xf6\x38\x31\xd4\x60\x6b\x27\x12\xeb\x95\xcf\x4b\x10\x95\x3c\x2b\x72\x1d\x9e\x30\xda\x85\x11\x29\x60\xe9\xb0\xc7\x8e\x61\xa9\xa3\x44\x40\xd6\x11\x4a\x3d\x34\x86\x6f\x01\x80\x6a\xa2\x29\x2e\x52\x5b\xc9\xf2\xdd\x1a\x93\x49\x47\x0c\xd2\x98\xf0\xdd\x09\x87\xef\xee\x6c\xf8\x2e\x82\x2a\x9c\x97\x2b\x14\xb2\x9e\x30\x57\x7a\x69\x8a\xd6\x9c\x44\xe2\x36\xca\x52\xc6\x58\x0b\xa1\x48\x24\x3e\x6e\x2b\xb5\x1f\xc7\xee\x31\x11\x87\xf6\xf2\x74\x2a\x29\x2e\xeb\x7f\xc6\xe4\x9f\x4a\x2c\xed\x8e\x16\xba\x62\x98\x0b\x48\x0c\x73\x7a\x87\x65\x98\x42\xff\xe9\x73\xea\x8f\x92\x05\x43\xac\x05\xce\x33\xc5\x1c\x47\x16\x60\x0e\x30\x25\x60\xb4\x51\x18\x25\x86\x12\x58\xa8\xa0\xde\xd2\x84\x6e\x66\x65\x2a\x13\x3a\xc9\xde\x01\xf9\xd9\xea\xc1\x39\x9e\x81\x72\xe6\xd0\xcd\x00\xcf\xcf\x0f\x1e\x07\x90\xcd\x7e\x1c\x86\x6e\xc6\x25\x59\x90\x72\x89\x91\xe8\xe6\x53\x16\xdc\x8c\xd7\x81\xfa\x22\xfb\xf3\xe0\x11\x2e\x8f\x9c\xfc\x8d\xd2\x01\x0b\x90\x09\x4c\x1c\x36\x23\x0d\xa2\xf1\xe1\xc5\xff\x95\x41\x60\xf8\x53\x35\x29\x97\x78\xfd\x44\x7c\xa3\x46\x93\x6a\x6e\xd7\xa1\x1f\xf2\x28\xdd\xa3\xfe\x1d\xfd\x2b\x60\x03\x60\xfc\x7f\x0d\x00\x7c\x77\x7e\x16\xb0\x04\x62\xec\xdb\x8e\x05\x9f\x80\x36\x4b\x46\x37\x80\x72\xac\x5a\xad\x36\x58\x71\xc9\x2a\x6d\x04\xc6\x5b\x6b\x27\x45\x96\xd0\x46\xa5\x17\xb3\x59\xfe\xce\xfe\x7a\x2f\xb5\xc1\xc1\xaa\x47\xef\xc1\x1e\x31\x6c\x8e\xbb\x9e\xc0\xfb\x51\x2f\x09\xc4\x01\xae\x23\xab\x40\xae\x2c\x1f\x3e\xeb\xfa\x8e\xc5\xef\x27\xd8\xdd\xf3\x11\xe2\x73\xe7\xe9\x3b\x37\x3d\x21\xd4\x5b\x9d\x1b\xfc\xa3\x95\xf0\x38\x69\x45\x48\x54\xc7\xc5\xcc\x4f\xf2\x38\x20\x59\xf0\x72\x7d\xb4\x93\x61\x2c\xe3\x36\x7b\x60\x06\x50\x91\x11\x3c\x50\x0d\xe5\xe4\x30\x4a\xbe\x91\x14\x4d\xc2\x02\x9d\xc2\xc0\x72\xaf\x07\x7f\xa0\x0b\xe8\x8b\x80\x84\x8d\xdb\x3a\x27\x0f\xd7\xb2\x28\xa8\x81\x13\xd0\x27\xbc\x8e\xfe\x2e\x23\x6f\x1f\x15\x60\xa6\x62\x7f\x74\xf0\x3a\x1e\x27\x03\x1e\x58\x38\xd0\x4b\x27\xd3\x14\xb0\xe3\xa2\x85\x20\x08\x40\x5b\x00\x63\xfb\x82\xd4\x2c\x46\x93\x84\xd7\xc3\x51\x49\x06\xaa\x19\xa1\xf2\x1d\x6d\x19\x23\xc8\xe7\xf5\x18\x78\xd6\xc3\xc3\x07\x0d\x6b\x08\x6d\x7a\x8e\x0b\xb1\xbd\xe3\x1e\xbf\xb9\x14\x79\x07\x16\x01\x4b\xef\x6a\xc4\xb1\xb3\x14\x1a\x94\x50\xc5\x84\x16\xfa\x00\xe6\x6f\x41\x36\x3d\xfa\x71\x42\x1c\x66\xa8\xd9\x44\x3b\x8e\x05\xb0\x6a\x18\xc3\xa4\xd3\x39\x13\xfe\x1a\x4f\xef\x24\x3c\xce\x73\xa2\x70\x75\x0e\xe1\xe4\xe7\x07\xdb\x08\x9e\x93\xdf\x20\xdd\x19\x57\x0d\x88\x03\x17\x3d\x3f\xd4\x60\xe9\xc0\x49\xdf\x10\x14\x20\x12\x73\x61\x8b\x23\xf3\xd1\xd2\xc4\xe5\x67\xc6\xe1\xe7\x01\xcd\x29\xfc\x46\x72\xc6\x9d\xa1\x9c\x5c\x28\x5b\x07\x7d\xf3\xf3\x8b\x37\x1e\x2b\xfb\xf7\x6e\xb4\x06\x8e\x8b\x0c\x9a\x34\xb3\x32\x34\xd9\x8e\x77\x7d\xe8\xca\xc4\xdd\x87\xbe\xf7\x61\xc0\x8c\x42\x62\x29\x9a\xe0\xd0\x52\xbb\xfa\x44\x11\x9c\x1c\x11\x39\x7b\x52\xb9\x38\x4e\x43\xd9\x9b\xad\xd1\x13\x01\xa5\x7b\xd2\x0c\x08\xe0\x8a\x84\x1c\xdf\x99\x33\xb8\xf1\x34\xe3\x99\x7e\x94\x3f\xbe\xc6\x12\x8e\x62\x8c\x83\x50\x8a\xf3\x57\x9f\x41\x83\xe6\xe2\xaf\x97\xe2\xac\x4e\x53\x6d\xa1\x89\x3e\xcc\x4f\x4f\xfb\xd9\xea\xad\x85\x06\x89\xf3\x1f\x3c\x3d\x2d\x34\x90\xce\x7f\x9c\x8a\x3c\xf4\xf0\x26\xce\xce\x96\xd0\x02\xbd\x54\xa8\x97\x9c\xb3\xd5\xdb\x0b\xf5\x0e\xe7\x78\x83\x5c\x69\x4f\xb1\x53\x4a\xcd\x19\xd3\x80\x41\xe2\x60\x62\x56\xb4\xb4\xb2\xb6\x61\x7e\x35\x4b\xc1\x06\x06\x6b\x21\x77\x51\x3c\x94\x41\x8d\x34\x16\x00\xe1\x72\xa0\x11\xf8\xd4\x56\x6b\xc3\xe3\x26\x8b\x33\xa0\x4f\xb6\xf2\xfd\x96\xa2\xa4\x21\xf4\x6a\x7d\x97\xec\xa7\xcd\x80\x55\x28\xf3\x6c\xbb\x33\x7e\xd3\xfa\x0d\x09\x31\x17\x97\x33\x08\x03\x26\x8e\x35\xbd\xd0\xdf\x60\x6f\x89\x0f\x6a\x0b\xb5\x01\x0a\x7a\xf4\x7c\x2c\x23\x46\x38\x00\x67\xb5\xea\xc5\xa1\x7a\x20\x6a\xb3\xb2\x96\xe0\x52\x38\x33\x9e\x34\x3e\x37\x30\x0d\x77\x3e\x0c\x67\x4d\x93\x43\x65\x9a\xf2\x74\x4b\x51\x92\x36\x3c\x2e\x55\x2c\x42\xd7\x4c\x1c\x6a\xfb\x51\x65\x67\x9b\xf3\x03\xfb\xcc\xac\x74\xd8\xcc\x62\xc8\x09\x31\x86\xdc\x28\x30\x99\xcb\xce\x75\x30\x61\xc8\xe1\x8a\x51\x4b\xf6\xd1\x8d\x85\x92\xc3\x8f\x6e\x2c\x7e\xdc\xa8\xa7\x4b\x37\x09\x8c\xd7\xe6\x38\x1c\x36\xce\x7c\xa8\xc3\x01\xe4\x1a\x8d\x12\xc4\xf2\x14\xee\x1b\x0a\x24\x97\x86\x65\xf8\xc0\x7e\xda\x8c\x74\x0c\x27\x87\xf1\xe4\x84\x18\x4f\x6e\x14\x08\x37\x1b\x2f\x1c\x3e\x5e\x66\xa0\x7f\x36\x3c\xe7\x11\x87\x67\x0e\x2c\x57\x6d\x92\x63\x58\xdc\x64\xb1\x68\xef\x50\x80\xb9\x2f\x39\x59\x4e\x9b\x91\xce\xc1\xcc\x31\xf2\x04\x00\xcb\x53\x04\x4a\x06\xd9\x87\x31\x53\xab\xc0\xc8\x67\xa1\xb7\x66\xcf\x04\xcb\x40\x4c\xf9\xce\xfb\xc2\x40\x0b\x31\xc3\x18\xf6\xcc\x84\x3d\x18\x92\x88\xe6\x31\x5e\x02\xc4\xd7\x65\x76\x22\x03\x5f\x88\x1f\x0d\xdb\x04\x36\x96\xac\x0b\xcb\xd2\x99\x18\x78\x24\x67\xc2\x15\x50\xa1\x55\xb3\x22\x57\xf3\x15\x12\x39\x09\x57\xc0\xee\xbb\x9a\xc7\x97\x39\x51\xa3\x98\xdf\x35\x8f\xef\xa0\x77\x18\x01\x2f\x44\x44\x1a\x96\x70\x1b\xea\xdf\x69\xc4\xe9\x03\x00\xcb\x55\x64\xc2\xe9\xb3\x65\xb1\xcb\x87\x8d\x9b\x6f\x1c\x37\xe6\xa3\x7f\xe6\x38\x9c\x07\xc7\x51\x00\x2b\xce\x06\x5c\xea\xe0\x64\xda\x70\x29\xe0\xca\x25\x74\xaa\x12\x3d\x82\xe7\xef\xc2\x0e\x46\x94\x28\xf9\x2e\x8a\x60\x25\x48\x80\x08\x00\xa8\x63\xbc\x0e\x60\x09\x24\x60\x2d\x68\x13\xb0\xcc\x8f\x06\x5b\x12\xa3\x2a\x1a\x29\x6f\x49\x91\x80\x19\x90\x70\xb0\x84\x8e\x25\x05\xb1\xb2\xeb\xd1\x5b\x0d\xd6\xcd\x19\x1f\x33\xdf\x7c\xf8\xb3\xb1\x32\xcc\x8e\xab\xb7\x34\x25\xeb\xb0\xa9\x39\xe4\x71\x8a\x6f\x27\x34\x99\x05\x91\xad\xc9\x03\x05\x72\x35\xe3\x7a\xe2\x8b\xb5\x30\x28\x51\x78\xd2\x11\x30\x01\x7a\x14\xae\x80\x01\xe8\x32\x3a\x7a\xff\x31\x0c\x5a\x30\x2b\x39\x33\xb5\x76\x0b\x6c\xbc\x0b\x09\x22\xe0\x71\xf2\xb5\xee\x19\xd3\x60\xdd\x12\x0e\x5f\xb9\x97\x7a\x8c\xb9\x3c\x14\x20\x8b\x43\xae\xc4\x2f\x42\xf8\xca\xd0\xc3\xa2\x47\x6f\xed\x8f\x9f\xdc\xc0\x17\x06\x99\x1d\xce\x56\xb1\xe6\x88\xe6\xbc\xa0\xca\x60\x2d\x13\x89\x8f\x53\xb6\x52\x57\xec\x20\x7a\xd8\x89\xc4\xc7\x81\x50\x84\xc1\xd0\x28\x11\x47\x0f\x34\x98\xef\x8b\xd1\xb4\x06\x33\x7b\xcd\x93\xfc\xb7\xfc\x50\x9f\x51\xae\x11\x10\xb4\x24\x15\xfa\xa2\x8e\xbb\x62\xc1\xc4\x7d\xb3\xb7\xbf\x05\x03\xea\x12\x57\x4e\x49\x89\x89\xaf\x98\x04\x6b\x2e\xc0\xf9\x97\x92\x73\x5c\x5e\x98\x0e\x0b\xff\xe8\x6d\x98\x91\xf6\xc5\x15\x7d\x55\xdf\x8a\xf4\x3c\x36\x9f\x9f\xc5\xfc\x61\x74\xdb\x0d\x8c\x01\x5f\xb2\x37\x57\x7a\x07\xb5\xc1\x93\xec\xd1\xdb\x04\xb6\x79\xba\x60\x72\x67\x91\x85\x4a\x2f\x0e\x6c\xa3\x39\x74\x4e\xca\xdb\x85\xb6\x51\x31\xce\x0f\x45\x32\xb1\x88\x91\x27\x95\x43\x7e\xa7\xb9\xf7\x0c\xce\x6d\x16\x0b\x07\x23\x8f\x7d\x0f\x4f\xb0\x07\x2f\x2d\xd4\x8f\x3e\xc7\x02\x9d\x9e\x8a\x3c\xf0\xf0\x1c\x5b\xc3\x26\xd4\x0b\xcf\xe9\xc5\xcc\xa9\xc0\xd3\x8f\x16\x1e\xe7\x8d\x66\xec\xbf\x17\xf3\x93\x04\xc7\x05\x42\xc9\x68\xb6\x1c\x8d\xc7\x7c\xf4\x1a\xac\xeb\xa3\xdd\x45\x62\xc3\x28\x97\x50\x1c\xfd\xd9\x38\x30\x7b\xc9\xd3\x05\x27\xf6\xe8\xbd\x45\xdc\x92\x07\x8f\x0e\x83\x12\x93\xff\x6d\x3c\x06\xbc\x95\x83\x09\xd3\x51\x90\xd1\x83\x3d\xd0\xe9\x44\x5e\x39\xf4\xbf\x29\x88\xd2\x26\x66\x8c\xca\x84\x9a\x7c\xbf\x1f\x3e\x99\x77\x78\xcc\xac\x86\xec\xf6\x2b\x30\x30\x25\xbc\x46\xa1\xd1\x6c\x3e\x08\xf3\xdf\x78\xfc\x0a\x11\xf0\xa4\x57\xe1\x1e\x1a\x56\x58\x0a\xeb\x91\xef\x3f\x3a\xe3\x22\x53\x82\x3e\xbc\x9c\x92\x74\x00\x6d\xe4\xf4\x84\xae\xa7\xa5\x40\x01\x02\x18\x2f\x48\xce\x56\xef\x1b\x94\x16\x3d\x8c\x34\x95\x18\x0c\x44\xe9\x60\xa1\xd2\xcb\x02\x59\xd5\xf1\xb3\xe8\xd1\x5b\xf9\xeb\xad\xd5\xf8\x5e\x10\x7c\x61\x18\x6d\x87\x2f\xe1\x55\x10\xf3\x36\x89\x28\xd5\x71\x2b\x3b\x15\x8b\x58\x69\x50\x73\x32\x6d\x7e\x78\x9d\x95\xa9\x95\x50\xef\x73\x8e\x85\xda\x32\x73\x66\x1c\xfc\x6c\xf5\xf6\xe7\x78\x06\x19\x85\x61\x79\xf5\x3e\xc2\xe3\x16\x3e\x56\xcc\xe9\xca\xfc\x6c\xb3\xf0\xb1\x32\x8b\xea\x2c\x43\xc1\x3b\x36\xf6\x8e\x16\x96\x3e\x46\x04\x47\x1b\x7b\x07\xd9\xe0\xef\x9c\x9f\xad\x1a\x2d\x12\x1b\xe4\x14\x8b\x36\x4a\xbb\xe1\x4b\x12\x6b\x3b\x91\xd8\x20\xc6\x38\x4e\x4a\x0e\xe0\xd1\x8f\x11\xbe\x9e\x12\x1b\x81\x9c\x31\x54\x6f\x50\xa4\xd9\x3a\x30\x71\x10\xbb\x0e\x23\x94\x2d\xe4\x6c\xbc\xbb\xe1\x48\x9e\x80\x6f\x33\x0d\xfa\x3e\xb0\x8c\x56\xa7\xa4\x39\x6b\x60\x40\x9c\xef\xad\xf7\xcb\xfe\x3e\xce\x7a\x63\xd7\xa9\xf7\x60\x40\x6a\xec\xa4\xf2\xc4\xb8\x49\x09\xab\x52\xe0\x96\x33\xb0\xe8\x4c\x8b\x63\xca\x2c\xb8\xee\xc9\xce\xc0\xd1\x21\x11\xf3\xaa\xff\x40\x9d\xff\xe8\xcc\xca\x3c\x72\xe3\xa3\xec\xec\x75\x3f\xbd\x98\x9e\xb7\xf6\x27\x26\xf6\xb8\x38\xd0\x4b\x97\xf2\x2e\x83\x71\x00\x48\x82\x39\x4e\x61\x7b\x37\x68\xcf\x97\x9a\xab\x86\x26\xc8\x98\x86\x64\x04\x28\xb8\x78\x15\x8a\xdf\xbb\xdd\xf1\xd6\x0b\xcb\xa9\x35\xb1\xe9\x8e\x99\x30\x78\xde\xb8\x9e\x7f\x76\x7e\x66\x59\xb2\xf8\x9e\x7f\x63\x4b\xdb\xd4\x29\x9b\x0e\xf1\xc2\xb6\x9e\xdb\xbd\xf5\x13\x1f\x0b\xd7\xaa\x17\x2a\x97\xe7\x95\xb3\x8a\x71\xec\x75\xef\xc9\xbe\x53\xa6\xdf\x28\x2f\x8b\x4a\x2b\xc6\x75\x7f\x75\x03\xbd\xb4\x94\x2a\x03\x2a\x66\x0c\xa6\xdc\x1c\x57\x38\x54\x3d\x23\xe0\x90\x11\xd0\xfc\xba\xaf\x3f\xef\xbc\x5a\x51\x73\x22\x26\x70\xd2\x64\x87\x08\x18\x10\xa7\xba\xdb\xf5\x7e\x57\x6e\x65\x83\x6f\xcd\xd6\xa5\x93\xa6\x26\x1a\x92\x29\xd7\xac\xcd\xeb\x16\xae\x1f\x6d\xe1\x76\xcc\x27\x58\x93\x53\x0c\x9d\x50\xe7\xa7\x17\x9b\xb7\xfb\x4c\x89\xef\x9e\x90\x10\x3c\xce\x4f\x8e\xfb\xaf\x41\x59\xd4\x15\xde\x65\xe0\x05\x80\x64\x58\x7a\x15\xcd\x12\x47\x48\x82\xd9\x1c\x22\x2e\x09\xab\xc6\x98\x4c\xb5\xfe\x80\xa5\x33\x74\xde\x8a\xae\xe6\xa2\xaf\xa6\x88\x6e\xdc\x0b\xaa\x82\x2f\xe9\x74\x47\xce\xf0\x7c\x4c\x09\x54\xb6\xdb\xca\xdd\xa6\xbc\xcc\x84\x7a\xb0\x24\xca\xf7\xf0\x83\x8f\x92\x32\x2a\x00\x04\x6d\x68\x09\x55\x85\xb9\xfb\xcc\xe7\x6c\x2f\xe5\x63\x12\x34\xed\x30\x71\xd3\xfc\xb6\xff\xfc\xab\xf3\x6a\x45\xdd\x09\xf1\xed\x3a\xd4\x93\xf7\xab\xd6\x56\xa7\x1b\x4c\x4e\x62\xe7\x59\xab\xb0\x54\xef\xf6\xca\x66\x42\xba\xc7\xf1\x2e\x49\x61\x5c\x42\x12\x87\x09\x31\xd0\xcb\x2f\xe0\x75\x00\x6f\x00\xcc\x70\x14\x9e\xb2\x01\x1a\xc6\x3f\x1f\x8e\xaa\x70\xdd\x2e\x3c\x2c\x21\x53\xc6\xec\x7f\xd5\x0f\x9f\x5e\xfc\x72\xd4\xae\x11\x90\x15\xfa\xe8\x70\x4f\x75\x14\xbb\xfb\x3f\x3b\x6f\x68\x8a\x2c\x25\x3e\x32\xa1\x2c\xc0\x01\x46\xcf\x4e\x50\x65\xc0\x9f\xeb\x7f\x10\xf3\x60\xb8\xfa\x33\x43\x78\x16\x02\x42\x9d\x99\xea\x7f\xf7\xd9\x85\x6e\xeb\xfc\x67\x41\x21\xf4\x97\x9a\xd4\xbe\xeb\x83\xb7\x1b\x83\xc3\xe0\x65\x13\x2a\x02\xbe\x03\x18\xe8\xc5\xb5\x39\xae\x00\x18\xab\xc0\x9f\x96\x45\xb0\x76\x48\x4d\xb8\x49\x0e\xc1\xf3\x54\x3f\x7c\x7a\xee\x2b\x91\xdc\x54\x19\x3e\x74\xf6\xed\x2d\xbe\x8b\xf6\xf5\xd7\xe1\xd8\x7e\xa0\x97\x3e\x8d\x31\x1b\x81\xb1\xb4\xfa\xe9\x09\xe3\xcf\x83\x95\xd6\xdb\x2c\xe3\x82\xe3\xa6\x3a\xb1\xb3\xbc\xf2\xc1\x17\x56\x24\x85\x5a\xb8\x9a\xeb\xfe\xac\x20\xef\xe0\x90\xbc\x72\x3c\xaf\x63\x07\x5d\x42\x5c\x15\x48\x0d\x20\x7e\xf3\x6c\xe6\x5d\x01\x2e\x00\x18\x99\x18\x38\xa4\x7c\xa1\x3c\x30\x58\x2b\x97\xc8\xf9\x04\x90\x7b\x80\x8a\x7f\xc1\xaa\x27\xf7\xdb\xca\xe6\x6f\x49\xde\xf1\x53\x1d\x74\xae\xd3\xcb\xd1\xf6\x10\x42\xaf\x88\x47\x7a\xd4\x85\x7e\x46\xff\x24\x54\x90\x86\x6d\x3f\xcc\x7b\x12\xec\xf9\x16\xfa\xe4\x5d\xf4\xfe\x1b\x4d\x90\xe8\x40\xcd\xe8\x32\x1c\xcf\xd6\xe9\x32\x67\x7e\x07\x55\x86\xfb\x32\x63\x2d\x30\xca\x4f\xae\xc5\x7d\x79\x7a\xe7\xbc\x01\x03\xaf\x94\x7c\x10\x5f\xb2\x76\xc3\x9b\x1f\x15\xcd\x2a\x5e\xe7\x88\xfa\xfc\x09\xad\x47\x08\xba\x81\xd0\xed\x3e\x78\xb8\x1b\x4e\x34\x04\x7a\xdf\x4b\x1a\xf8\x7c\xee\xe2\x45\x0b\xbf\x6d\x44\xff\x85\x06\xbe\x63\xfb\x38\x3c\xd0\xcb\x0b\xc5\x7e\xbb\x6b\xb4\x9d\xc4\xb2\x78\xa6\x44\x62\x4b\x01\x08\x8a\x67\x42\x12\x44\xa9\x44\x40\xed\xe8\x1f\xa5\x0a\x18\xcf\x02\x07\x8f\xa4\xc6\x87\xb5\x24\xd2\xa2\x86\x83\xcc\xa2\xb1\x87\x17\xab\xbc\x7b\x58\x10\xe1\x7e\xc1\xd3\xfa\x0a\x20\xd0\x0d\xf4\x52\x0f\xb0\xff\x0d\x24\x5a\x4c\xe9\x35\x82\x7a\xea\xfc\xc9\xf7\x03\x50\x7b\x9e\x15\xa7\x8d\x81\xf1\xaa\x1f\x3e\xed\xbc\xe6\x9c\x89\x11\x76\x03\xb4\xee\x9c\xe6\x7d\x76\xde\xd0\x9c\xb0\x1c\x56\x03\x08\xe2\x07\x7a\xa9\x3e\xcc\x6d\x0a\x24\x41\xc1\x5a\x8d\xb7\x26\xc8\x8c\xcf\x00\xe3\x86\xf1\x07\x45\x28\xa2\xe5\x9e\xa3\xe3\x3f\xff\xcf\x43\x38\xee\x97\xaa\x7f\xbf\x54\x1f\x63\x28\x5c\xb8\x66\xf3\xf6\x8d\xea\x8a\x3b\x97\xeb\x2a\x66\x5f\x9d\x72\x0a\x3d\xba\x8f\x1e\xc0\xc2\x63\x1f\x79\x08\x92\xee\x74\xde\x88\x4c\xbf\xed\x1f\xad\x4b\x9b\x35\xed\xe1\x8a\x65\xb9\x69\x1a\x15\xfa\x2d\xeb\x23\x2c\x47\xe5\x40\x2f\xe5\x8f\x31\xd6\x80\x44\xe8\xa5\xe1\x38\x25\x9e\xd1\x2d\x5b\x3b\x05\x93\xd2\xb3\x7e\xbf\xf9\x5f\x8d\xb9\xb9\x1b\x93\xe6\x16\xcd\x2d\x58\xe7\xbb\x63\xd5\x86\x9c\xac\xdc\x37\x75\x4d\x0f\x3f\xbb\x0f\xc5\x10\x6a\x04\xee\xa5\x13\x1b\x8f\x65\x7d\xed\x37\x3a\x3a\x22\x68\x7c\xf7\xe4\xf8\x90\x08\x9f\x80\xdf\xa7\xec\x33\xe2\xcf\x08\x79\x57\x78\x1d\xc0\xc3\xb8\xd7\xc5\xb8\x2e\x71\x48\x48\x07\xe5\x96\x90\xf9\x43\x84\xc6\x3f\x67\xdd\xc1\x9d\xe4\xec\x47\x50\x95\xad\x7c\xef\x8d\x62\x2e\x52\xc2\xb4\x32\x0f\x8a\x77\x6c\x7f\x67\x13\x63\x65\xde\x83\xff\x20\x22\x9e\xac\x46\x99\x67\xde\x61\x23\x12\xaa\x1d\xcd\x42\xf1\x8f\x96\xb0\xf8\x2d\x42\x5e\x28\x7b\x7e\x0c\xb3\x2d\xc3\xe3\xc8\x67\xd9\x95\xa3\x50\x39\xd9\x2c\x4c\x43\xd7\x9e\x0d\xb1\x72\x05\x55\x1a\x63\x36\x33\xa0\x15\xa3\x8d\x15\x24\xf2\x3a\x98\x7d\x61\x66\x63\x25\x2c\x23\x1c\x94\x43\x52\x31\xd4\xb2\x12\x47\xf7\xb2\x51\x22\xb4\x46\xed\x47\xd1\x0a\x74\x84\x88\xde\x79\xeb\x29\xcb\xca\x06\x8b\xfd\xee\x4c\x24\x43\xf4\xc1\x13\x43\xb1\x6b\x06\x7a\xf9\x96\xec\x39\x62\x3e\x77\x99\xb3\x89\x3d\x99\x1c\x71\xd2\x0b\xca\x97\xe1\x10\xf0\x37\x1c\xab\xa0\x66\x78\xab\x66\xb4\xdd\x48\x53\xb6\x67\xa3\xc1\xfe\x6e\x26\x82\x21\x22\xe0\x04\xda\x6c\xce\x38\x1f\x93\x1f\x86\x71\xeb\x1d\xb1\x25\x0d\x74\x70\x85\xec\x84\x69\xb9\x82\x94\x70\xb7\x6d\x8c\x11\xcd\x78\xf8\x08\x46\xc0\xec\xfe\xff\x30\xb3\xed\x7e\x13\x7d\x94\x55\xd2\x12\xb2\xf9\xd0\xf9\x64\x5e\xc7\xb5\x6b\x2e\xf0\x43\x3c\xc5\xfd\x3b\xfa\x1f\x91\xf4\x86\xe5\xed\x00\x10\x03\xa7\x91\x94\xbe\x89\xb9\x37\xbc\x01\x20\x21\x4b\x70\xe0\x20\x1b\x0c\x6b\x19\x57\x89\x4f\x9a\xca\x7d\x99\x79\xc6\xc3\xac\x7b\x22\x8b\x0d\xc7\xb7\x1c\x21\xa0\x84\x9b\x60\x7d\xe2\x2f\xdb\xa6\xad\x52\x0b\xac\xdd\x93\xde\x4b\x8e\x89\x5b\x93\x52\x93\xbc\x7a\x32\x92\xd2\xc9\x47\xce\xfe\xf3\x1c\xac\xc4\x93\xab\x3e\xfb\x45\xf2\xcc\x83\xeb\xd1\x51\xb2\x22\x3d\x6f\xc3\x2f\x2b\xf4\x6b\xff\x1b\x70\xb8\x76\xf4\x4d\x8c\x9f\xe3\x06\x80\x02\x32\xfb\x67\xb4\x0f\x34\xab\xc7\x54\x58\x40\x63\xe0\x54\x49\x10\x8b\x66\x42\x35\x74\x24\xaf\x6a\x10\x88\x87\x5f\x87\xe0\xda\x39\x4d\xdf\x9d\xf2\x15\x68\x2e\x14\x97\xe8\x16\x67\xae\xab\xaa\x25\x1a\xe2\x0f\x2c\xba\xf5\xd8\x58\x3d\x47\x04\xf4\x77\x91\xd7\xa7\xcc\x82\x1b\x97\xb1\x75\x08\xf4\x11\xaa\x0c\x04\xe0\x1a\x4d\xe3\x9a\x46\x42\x2d\x36\x18\x46\xc6\x70\xf3\x72\x35\xd6\x2a\x69\x19\x27\x81\xf9\x68\x1a\x0d\xcf\x84\x34\x38\xc6\x6b\xac\x46\x3a\x61\x8a\xe6\x00\x18\xf8\x16\x1e\xb1\x5d\xbe\xe9\xd0\x7b\xa8\x0d\x5d\x56\x13\x85\x79\x33\x36\xcf\x9f\x7d\x72\xc9\x3f\xbf\x27\x22\x43\x33\xfc\x62\xf7\x2e\x99\x05\xff\x95\x38\x79\x76\x58\xd5\x94\xd9\x84\xd4\x6f\xdf\xd1\xa2\x99\xfb\xa8\x47\x42\x5f\xcf\xbc\x34\xbb\x98\x23\x6d\x1f\x47\x65\xb6\x6e\x34\x55\xb2\xf9\x8d\xf9\xe6\x33\x6a\x4a\x41\xfd\x72\xe2\x89\x36\x0e\x3a\xcd\x78\xcb\x84\x81\x59\x81\x5a\x70\x2e\x94\x90\x91\xd9\x60\xb6\x0b\x5f\x22\x27\x9f\xca\x56\x33\x65\xb6\xfc\xd7\xe7\x08\xed\x69\x73\x1a\x9e\x9c\x66\x9e\xc7\x72\x01\xc9\xf3\x51\x39\x4c\x1a\x96\x91\x66\xe4\x69\xa1\x1a\xa9\x32\xe0\x80\x3d\xaa\xc1\x0a\x51\x28\x37\x02\x54\xf8\x41\xaf\xa7\xea\xc2\xb3\x6a\x27\x08\x42\xbf\x47\x47\x50\xb7\x7f\xd0\x04\x41\xd2\xe6\x69\xd9\xeb\x27\xc3\x80\x49\x71\x89\x2b\x26\xb3\x31\x23\x2e\xf6\x4d\x99\xb9\xe5\x8f\x8e\xaf\x7e\x3e\xa9\x4b\x9d\xd3\xb1\x39\x3b\xfb\xe5\x3f\xca\x8d\x31\x23\xc6\xd2\xe6\x7f\x87\x63\x46\x20\x91\x4b\xa4\x34\x9f\x7d\x5f\x93\x48\xf9\x1c\xf9\x01\xa9\x0c\xd2\x2a\x68\x3e\x94\x9f\x80\xee\xb4\x80\x16\xc8\xa7\x5a\xc1\x52\x68\x6b\x6f\x21\xd0\xa4\xc2\x64\xa8\xe9\x5f\x8d\x5a\x1d\x08\x5a\x10\x14\x81\x4e\xa3\x63\xbc\x8e\xbe\x6f\x82\x1e\x6a\x66\xff\x53\x46\xaa\xfb\x76\x6d\x7b\xe9\xe0\x19\xd2\xe5\x71\x32\x71\xb5\x54\x97\x73\x68\x3d\xa6\xf7\x05\x10\x54\x02\x40\x77\x60\xee\x7b\xdc\x27\xee\x52\x22\x17\xe1\x2e\x31\xce\x08\xee\x91\x94\x57\xc2\x51\x94\x95\x85\x75\xbc\xd3\x77\x30\xc9\xd2\x72\xaa\xf7\x0d\xa8\xee\xbf\x8f\x3a\x68\x4b\xeb\x1c\xe7\x1e\x84\xd9\xa6\xae\x56\x8f\x3b\x17\x41\x38\xf6\x7f\xdf\x59\xf4\x38\x1b\xfe\xfc\xa4\x99\x10\xec\x3b\x39\x10\xdd\x7f\xc7\x9c\xbf\x54\xcc\xfa\x48\x50\xa9\x95\x69\xe5\x50\xc6\x57\xf2\x19\xb3\xc2\x62\xb9\x41\xdf\x65\xaf\x67\x35\xc2\x6c\xb4\xa3\xbe\xe5\x85\xf5\x30\x07\xbd\x8d\x4e\x63\x5e\x62\x98\x7b\xb1\x60\x4b\x07\x9a\xdb\x5b\x70\x62\x3f\x5b\x77\x63\xe4\x91\xe3\xc9\x29\x1d\x6e\x53\x22\x27\x25\x43\xdb\xc4\xd4\xbf\x8f\xe7\x35\xa6\xae\x80\xd9\xe8\x4c\x75\x73\x51\x06\xcc\x40\xc7\xd0\x79\x4c\xb2\x0a\x89\xbd\x45\x2b\x56\xa3\xb6\x0b\xc5\x4d\x59\x2c\x39\x23\x3e\x6b\x00\xbf\x85\xd7\xc1\xc4\x2f\xe6\x7e\xed\x73\xb8\xcc\x86\x7b\xb7\x5b\xd3\xb3\x77\xde\x5b\xf9\x26\xfa\xd7\x99\xc3\x15\xd5\xf5\x87\x3e\x6a\x58\x3f\x29\x78\x05\xea\x1e\x11\x3e\xac\xbf\x58\x5a\xdf\x77\xe4\x16\xda\x7d\x92\xc3\xa6\x7b\xe3\x6f\x98\xe2\xcc\x68\x92\x99\xb3\xc8\x92\xd6\x51\x65\x8c\xec\x86\x9d\x45\x83\x49\x27\xde\xc3\x68\xc1\x9e\x75\x2a\xe5\x19\x89\xc2\x62\xaa\x94\xf9\x15\xf5\xfb\x67\xce\xf0\x57\xa4\xa3\xee\x67\x9e\x4d\x28\x98\x23\x0f\x73\xb0\xc7\xec\x61\xa5\x6b\x6c\x51\xf5\x90\x43\x8a\xe5\xb6\x3b\xc6\xeb\x00\x8a\x41\xbf\xf7\x99\xb2\x1a\x8a\x88\x34\x28\xa7\xd6\xca\xea\xfa\xd7\x3f\xe1\xe4\x34\x88\x8e\x34\x4c\x38\xf4\x75\x2c\x1c\x8c\x96\xc4\xf2\xbf\xe5\x51\x3a\xdc\xaf\xc4\xd4\xef\x33\x04\x62\xee\x0c\x2f\x7a\x4a\x08\xbe\x5e\xe9\xe6\xcc\x7d\x26\xca\x34\xf3\x59\x9b\x71\xf9\x65\xf1\xda\x31\x2e\x08\xc0\x59\xd2\x2c\xed\x25\xe6\xb3\x1b\x3f\x48\x75\x09\x01\x52\x0f\x00\x5e\x07\x8b\xea\x8f\x29\xeb\x38\x9e\xcb\xef\xa8\x32\xe0\xc4\x8c\x99\x3b\x7d\xec\xa5\x7c\x0e\x89\x7f\x90\x46\xe7\x9e\xbd\xc5\xb6\xcf\x36\xec\x92\xa5\xdf\xae\xc3\x5c\x91\x5c\x8a\x31\xa5\xeb\xfa\xf6\xcd\x7d\x93\x16\xa1\x4a\x4c\x59\x6d\x22\xc8\x31\x8d\xeb\x34\xc6\xe8\x03\x43\x50\xbb\x07\x9b\x1e\x82\xdc\x1d\x61\x1c\xe9\x30\xfc\x6e\x74\x15\xd3\x10\x98\x61\x78\x33\x63\xa6\xa5\x5c\x5c\x63\x0b\xf9\x83\x7c\x40\xc3\x86\x0d\x93\xa1\xaf\x72\x6c\x8c\x20\x72\x77\xc1\xd3\x63\xa7\xa5\xef\x7c\xf0\xf9\xe4\xd9\x23\x0d\x9f\x18\xd8\x0b\x00\xa9\xa3\x74\x80\x0f\x44\xcc\x99\x28\x97\x28\x48\x39\x29\x51\x13\x11\xd0\x96\xe4\x17\x12\x51\x70\xd4\xe2\x5b\x62\x74\xa0\xfa\xd6\x63\x27\xbe\xd4\xc1\xc1\x82\xd2\x3d\x69\x86\x34\x7a\x0c\x3f\x86\xdb\x26\x3a\xd8\x07\x04\x06\xd8\xe3\xb3\x75\x0b\x00\xbc\x2a\x8c\x9f\x25\xc1\xed\x70\x57\xff\x72\x3e\x46\x39\x50\x4b\x14\xa5\xc4\x71\x32\xc2\x07\x55\xab\x61\xa1\x0a\xed\x8f\x84\xd5\x63\xfa\xf7\x69\x51\x67\x0b\x74\xff\x69\x6e\x38\xa5\x3b\xf3\xf8\x2c\xfa\xaa\x13\xda\xa2\x87\xf0\x2a\xec\x62\xf3\x40\xd4\x03\xbd\x74\x13\xf6\x05\x83\x40\x2c\x73\x12\x98\x55\x70\xe2\x33\x41\xab\x36\x89\x84\xc0\xee\xae\x82\xaf\xd0\x9a\x2e\x14\x71\x29\xe7\xd0\x73\x82\x2b\xe7\x5c\x5a\x14\xfb\xf7\xe4\x13\x06\x0e\x1b\x60\xd2\xb6\x9c\x86\x37\xea\x7a\x36\xcf\x7e\x39\xd0\x32\xf4\x7d\x89\xef\xbe\x99\x07\x8e\x9b\x0a\x87\x89\x86\xd8\xc4\xf8\x55\x89\x31\x13\x92\x2a\x93\xa1\xeb\xa9\xcb\xca\xb9\xf3\xfd\x95\xdf\x66\x69\xc3\x75\x0d\x39\xa9\xd7\xcf\x7e\x84\x9a\x3e\x4e\xc9\xde\x92\xa3\x0e\x7b\x73\xab\xee\xc0\x8a\xb9\xa3\xd2\xf3\x36\xf4\x54\x66\xe6\xd6\xf5\x00\x12\x08\x01\xa0\x68\xcc\xb9\xe3\x82\x4f\x32\xad\x5a\x82\x6f\x65\xf8\x6a\xbe\x02\x93\x7b\xc9\x9d\x07\x4b\x6a\x38\xef\x4a\xa8\xdc\x9a\x0b\xa3\x8e\xe8\xa7\xec\x51\xee\x51\xdd\xfd\x18\xad\x5c\x70\x78\x5d\x56\x41\x4c\x7c\x95\x57\xe9\x8c\x39\xd5\xa5\xb0\xf7\x04\x3c\x55\x59\x51\x9e\x72\x22\x78\xa2\xfe\x2c\xec\x45\xd7\x72\xa6\x84\x27\x9e\x48\x49\x5c\x04\x20\xc8\x18\x78\x40\xde\xc5\x3e\xd6\x60\x2c\x67\xc6\x2f\xc6\x86\x04\x19\x7b\xa1\xc5\xdf\x17\xee\x48\xc8\x09\x5a\x9a\x30\xff\xf5\xb9\x0b\x96\x2e\xd8\xb5\xa5\xf1\xec\x3f\xe1\x91\x4b\x30\xbd\x4d\xa9\x7c\xcf\x55\x55\xf9\xfb\xc6\xb5\x2f\x4d\x38\x1f\xf6\x1d\x73\x16\x87\x02\x40\x3e\xa4\x74\x40\xc0\xe8\x07\x3b\x7e\x21\x90\x2b\x59\xcb\xa2\x82\xa1\x3f\x40\xe5\x95\x1b\xe8\x24\xfa\x4f\x5c\xfa\x91\x0f\x97\xce\xcb\xa2\x74\x37\xae\xa0\xf7\xd0\x96\x4e\x68\x7b\xb3\xb2\x9c\xf5\x2b\x7d\xb9\x36\xac\xd9\x48\xcc\xd8\x8a\x0f\x64\xa6\xcf\xb6\x43\xaa\xf9\x0a\x5f\x55\x71\xbe\xb1\x35\x74\x6c\x8e\x9e\x6d\x30\xb4\xcd\xa7\x0d\x5e\x39\x03\xbb\xd9\x76\xe1\x15\xf4\x1b\x6e\x1a\xfd\x78\x86\xd9\x7b\xcc\xf8\xd6\x51\x3a\x6c\x13\x24\x83\x5a\x17\xfa\x03\x51\xc0\x2a\x9b\x0f\xda\x1b\x06\xab\x94\x46\x0d\x63\xbe\x03\x06\x1e\x90\x05\xd4\x12\xe6\xfc\x8a\x80\xcf\x28\xcb\x73\x18\xbc\x36\x52\x78\xae\x6b\xa9\xa8\x5d\xf6\x52\x91\x57\x1e\x74\x4f\x4c\xaa\xae\xcf\x58\x7a\x62\xd9\xe6\xe3\x87\xb7\x2c\xac\xfc\xfd\xf6\x65\xdf\x8b\xc9\xb9\x39\x93\x62\xdf\x3d\x10\x1c\x93\xbb\x7f\x62\xd0\xf6\x65\xd5\xaf\x09\x68\x9b\xca\x02\xfd\x09\xbc\x2f\xae\xa3\x64\x22\x8a\xd2\x01\x4b\x60\x0b\xc0\x20\x8a\x8b\x37\x13\xeb\xfa\xcc\x9e\xb1\x3b\x2f\x6b\xd2\xe4\xb4\x9f\xa0\xef\x4f\xe8\x7c\xa6\xae\x62\xc6\xcc\x48\xb8\x0a\xbf\x66\x32\xf1\x80\x3b\x3a\x4d\x38\x63\x8e\x2b\xc0\x67\x43\x62\x35\x1b\x03\xdd\x8e\x88\x4c\xce\x75\xb8\x75\xef\xfb\x31\x27\x0f\xc7\x24\x97\xda\xce\x9c\x47\xc9\x9f\x9c\x7d\xf7\x88\x3d\x6b\x8f\x42\x01\xa0\x32\xb0\xbc\x19\x5b\x47\x32\xae\x8b\x44\x41\xf2\xc9\xd0\xfb\x77\x96\x2d\x87\x21\xd0\x16\xc5\x5c\xef\xdf\xab\xcb\xa2\x74\xfd\xf7\x0f\xc0\x15\xfd\x0f\xfb\xf5\xf0\xaa\x1a\xe5\x33\xdf\xb5\x05\x80\xb8\xc8\xf6\x29\x61\xfa\xd3\xca\xf8\x78\x13\xf3\x6d\x5b\x4b\xef\x64\x2e\x4a\xff\x21\x0a\x56\x29\xfb\xf7\xa5\xa9\x60\x6f\x36\xe1\x84\x4a\x43\x77\x55\xa1\xae\x4e\x58\xe4\xc0\xf6\xcb\x2b\xc4\xfa\xce\xac\x05\x06\xd3\x62\x81\xb4\x14\x24\xe3\xc3\x84\xde\x87\xbe\xbe\x34\x6c\x82\x51\x3f\x5d\x2d\xb5\x8d\xa3\x51\x7a\xb7\x0f\x2d\xf6\x59\x42\xe9\xfa\x3a\xc8\xe4\x27\xcd\x84\x6b\x6a\x7f\xdf\x5e\xb2\x70\xf3\x87\xfd\xf7\x4d\xf3\x68\xa5\x74\xcc\x3e\xc2\xed\x69\x23\xa1\x44\x4d\xca\x21\xd7\x98\x65\x1f\x6d\x69\x21\x5b\xd3\xd5\x8b\x10\x7a\x2c\x10\xbb\x97\x52\xba\xbe\xf3\x11\xd1\xaf\x10\xe1\x4f\x9a\xc9\xcc\xd6\xd7\xfa\xbf\x03\x04\xc8\x1a\x78\x40\xa9\xa8\x25\xf8\x4d\x18\x0c\xcd\x3e\xd6\x0e\x31\x0d\x59\xfb\x21\xf9\x46\xe7\x3f\x1a\x10\x3a\xd2\x79\xbd\xa7\x60\x56\xce\x6b\xd3\xe7\xe6\xe4\xec\x9a\x01\xf7\xff\x13\x66\xfd\xed\xdf\x1f\x5e\x47\x7f\x33\xdc\xfe\xb8\xac\xec\xd5\xdf\xf6\x2d\x5a\xb3\xf1\x11\xb3\x3e\x77\x06\x1e\x90\xa5\xd4\x12\x46\xab\x95\x5a\x37\x38\xac\xae\x96\xeb\xc5\x35\x3b\x78\x49\x42\xe1\xc1\xd9\x85\xa5\x45\x3b\xf7\x6c\x3b\x7b\x6d\x0f\xfa\xef\x23\x85\xdb\x23\xde\x73\x55\x55\x3f\xac\x7b\xf9\xa5\xd0\x0f\xc2\xbf\xbd\x76\x01\xbd\x6d\xf0\x62\x6d\x5e\x2e\xf0\xc2\xb8\xb8\x36\xc0\x91\xdd\xc7\xc1\xea\x40\x4a\x8c\x75\x66\x34\xa1\x95\x52\xea\x40\x4d\x10\xb3\xa7\x61\xee\x0f\x17\xfe\x05\xd3\x0d\xbd\x9f\x75\xa3\x93\xc7\x7f\x87\x36\x9f\x5c\x2c\xff\xe9\xe5\x13\x84\x35\x51\x76\xae\x77\x07\xfa\xad\xed\xc2\xb7\xf5\xd0\xea\x40\xd9\xf6\x2d\x49\xab\x26\xc3\x17\xf0\x3e\xcc\x05\x49\xb8\xed\x51\xc0\x09\x78\x45\x8b\x2c\x2d\x64\x16\x32\x0b\xd2\x99\x14\x2d\x98\x49\x92\x2e\x4e\x76\x20\x4a\x1c\xea\xaf\x12\x89\x41\x68\xa8\xa3\xbf\xbf\x48\x1d\x30\xde\xd4\x3d\xb3\x29\xd8\x8e\x69\x7b\xa9\x83\x4c\xe1\x0d\x73\xbf\xf8\xf0\x1a\xcc\x39\x3d\xf1\x9e\x4c\x51\x7d\xeb\xe5\xbc\x3c\x7f\xc5\xef\xe9\xc4\x02\x22\xea\xd2\x97\x3b\xd1\xc3\xa3\xef\x6e\xcd\x0d\x5e\x10\x9b\xb5\x7e\x72\x4e\x46\xca\xda\x84\x5d\xc4\x75\x00\x28\x20\x00\x62\x1e\x81\xb1\x39\x5d\xc1\x68\x7c\x43\xab\x95\x19\xdb\x97\xf1\x95\x78\x8a\x9a\x20\xad\x4c\xea\x06\xd5\xd0\x16\x6a\x61\x30\xd3\xa5\x44\x50\xb2\x7d\xd1\x6b\xd7\xe0\xe4\x77\xb5\xd9\x4b\x8a\x16\xee\x65\xe6\xab\x79\xb7\xfc\xde\x4a\x14\x27\xb0\xed\x86\x17\x46\x95\x7c\x7d\x83\xec\xac\x2f\x4f\xda\x82\x1e\x1e\xaf\xd5\x25\xee\xc8\x8c\xa9\x87\x56\x1d\xe5\x0b\x1f\xa7\xae\x49\x86\x85\x56\x01\xaf\xa0\xed\xa3\x83\xa6\xac\x49\x82\x0b\xb9\x33\xa5\x1d\xe3\xc3\x8e\x05\xda\x61\x67\x0a\xde\xf7\x32\x33\xc6\x57\xda\xfc\x24\x19\x6d\x6f\xa6\x2f\xc3\x70\x01\x96\x77\x8c\xaf\xfd\xfa\xbd\x7f\x6f\x40\x4f\xda\xba\x17\xec\xf9\xdd\x0c\x78\x82\x68\x4d\x4e\x48\x2c\x4d\x98\x94\x54\x62\x8e\x0d\x90\x32\x71\xdb\x8f\x97\xbe\x44\xef\x1e\x3f\x78\x90\xc5\xa1\xe8\xfb\x34\x6f\xfe\xea\xef\xab\x66\xcd\x65\xd6\x29\x76\xe0\x21\x55\x87\xf9\x87\x7c\xf0\x4d\x8f\xb7\x26\x28\x0a\xaa\xd9\x8b\x9d\x28\xa8\xe6\xdb\x42\xbe\xb1\x5c\x58\x2b\x35\x39\x5b\x74\x2c\x74\x5c\x6c\xe9\xf4\x8d\x22\x5b\xf7\xcf\xf1\xce\x77\x9d\x64\xc5\x05\x29\x13\xd1\x8f\xe8\xc1\xd5\xbb\x3f\x2e\x2b\xdb\x56\xbf\x68\xd9\xd6\x5d\x30\x03\x0a\x16\x45\xbf\xec\x37\xb6\xfa\x1d\x51\xd4\xe4\x6b\x95\x55\x0b\x9b\x7d\x7d\x57\x67\xdc\xb8\x7d\xaa\x6d\xf2\xac\x95\x2f\x4e\x9a\x59\xc9\xf4\x9f\xcf\xd5\x8c\x08\x19\x9b\x2f\x11\xb3\x10\xf8\x7c\x39\xe7\x6d\x48\xf2\x15\x50\xf3\xf0\xc2\xb7\x96\xa8\xcb\x7a\xcb\x9c\x3a\xc7\xf7\x09\x25\x14\xc2\xf0\xde\xae\x94\xc4\xc4\x94\x8b\x67\x77\xf5\x5f\x34\xbe\x25\x26\x9b\xda\x08\xd2\xca\xb9\xaa\x2e\x39\x01\x14\x9e\xde\x30\x47\x00\x83\x6c\x76\xe6\xbc\xea\x04\x03\x3c\xd1\xa7\xf7\xcf\xf7\x10\x00\xee\x9d\x1e\x32\x31\xf1\xe4\xdb\xbb\xd0\xaf\xe8\x9f\x3f\x92\xfb\xd9\xb3\x83\xb1\xef\x2d\x38\x9f\x8a\x3d\x7f\x3c\x44\x52\x4a\x05\x4d\x97\x11\xa1\x3f\x40\x21\x2c\x45\x03\x5f\x67\x66\x54\x44\x2c\x5a\xd3\x90\x4a\xe9\xd0\xfb\x27\xaf\xa2\x25\x44\xfa\xa2\x99\x9b\x00\x31\x70\x02\x00\xf2\x32\xde\x4f\x0e\xc6\x98\x3f\x58\xcd\xd8\x25\x05\x94\x18\xa3\xeb\x24\x58\x3d\x39\xf1\xc7\x2e\xb8\xe8\xfb\xbb\x39\xd9\xe8\xe3\x2b\x19\x13\xd3\xa3\x0a\xf2\x0a\xe0\xe3\xf1\x6b\x32\x8f\x9c\x7e\xd2\x0c\xdb\x50\x1a\xf1\x30\x32\x01\x06\x64\xe3\x31\xa5\x72\x63\xb2\x01\xf6\xec\x0d\x20\xa9\x96\x30\x86\x96\x5d\x0f\xdc\x66\xea\x4b\x65\x1f\x3c\xda\x97\x33\xeb\xf6\xf7\xe8\xb7\xb6\xb6\x9e\xc4\x34\x6d\x6c\x64\x17\x54\xaf\x36\x8c\x81\x5f\xb2\x68\xac\x07\x9a\xa2\xa2\x61\x30\xb6\x73\x0b\x01\x20\xeb\xb0\x0f\xc6\xdd\x53\x2a\x24\x0b\xc7\x11\xbf\xfa\xa0\x47\x1f\xdc\x3b\x4f\x36\x9e\x3b\xd7\x97\x4f\x36\x02\x08\xca\x07\x7a\xa9\x1e\x4a\x07\xa4\x58\xa2\x43\x2a\xe5\xb0\xa9\x29\x17\x56\x41\xdf\x6a\xeb\xd6\x39\xa5\xee\xd5\xd0\xb7\x2a\x02\xdd\x7f\x70\xf5\x0e\x5c\x98\x9c\x4a\xe8\xfa\x77\x47\xfa\x1e\xa9\xde\x46\x2c\xec\x6f\x42\xdf\xfc\x76\x89\x3d\x27\xb4\x40\x4a\x1d\xa1\x72\x81\x0c\xf8\x46\x3b\x40\xca\x9e\x5a\x30\x13\xd8\xdb\x5b\x39\xda\x0a\x04\x96\x56\x96\x0b\x66\x5a\x5b\xd9\x81\x28\xb5\x4a\x04\xd4\x22\xb5\x48\x1c\xea\xe8\x8f\x3f\x07\x8c\xd7\x8a\x78\x1c\x47\xa9\x97\x88\x67\xaf\x34\x9e\x92\x4a\x2d\xb1\x39\x3e\xb0\xe2\x76\x17\x0a\xa0\xe6\x74\x95\x2f\x7e\x6b\xcf\xa4\x45\x7a\x5c\xa4\x37\x6b\xe7\x38\xb6\x48\x4f\x90\xf6\x36\xe3\xa0\x02\x12\xc4\x03\x29\x9d\x46\xe5\x02\x4b\x60\xcf\xf8\x07\x12\x8e\x1d\x57\xe1\x07\x45\xc6\x8f\x9e\xde\xf0\x19\x1d\xc5\x87\x04\x25\x65\x2f\x99\x9c\xce\xfd\x03\x77\x11\xf5\x89\x01\x6c\xc7\xba\xae\xd5\x8b\xde\xda\x13\xdf\x00\x6f\x86\x47\x25\x4d\xae\x24\x26\xc3\xfb\xe1\x51\x49\x69\x2f\x4e\xe9\x5f\x31\x6c\x28\xe9\xc7\xe6\x6d\xd8\xe5\x8a\xe5\x80\x6e\x51\x47\x78\x5b\x18\x8b\x24\x33\xef\x71\x48\xdf\xcc\x16\xb0\x77\x30\x4d\x34\x71\x7c\xc5\xdd\x8f\x91\xbf\xf9\x8c\xef\xdc\xb9\x73\x64\x77\x6a\x51\x2d\xf4\xad\x13\xcd\x9b\xbd\x6b\xcc\x5c\xe8\xbb\x41\x98\x3f\xd8\x61\xc3\x3f\x6e\xa8\x04\x0d\xdd\xeb\xb7\xc8\x00\x04\x55\x00\x50\x96\xec\x19\x2d\x51\x4b\xec\xd9\x2b\x06\x35\x54\x54\xdd\x74\xa7\xe8\x48\x29\x4c\xfb\xa9\xff\xe2\x63\x4a\xd7\xef\x1f\x90\xe5\x75\x54\x49\x1c\xc1\x2e\x01\xfb\x3d\xde\x1d\x6c\x1b\x98\xef\x49\x69\xbe\x3a\x0a\x42\xb6\x81\x48\x08\xd5\xa6\x0b\x03\x45\xd5\x75\x5a\x40\xd1\xa3\x12\xa0\xfd\x27\x22\x9a\xb6\xd5\x40\xfb\xef\x90\x33\xea\x93\xf0\xf8\x6e\xc1\xbf\x20\x4a\xd7\xbf\xc3\xfd\x84\x6f\x5c\x1b\x51\xd1\x5f\xeb\xb3\x64\xb6\x6f\x03\xd1\xf6\xa4\x99\x58\x17\x34\x7d\xc1\xaa\xfe\x2e\x0e\x83\xb1\x12\xef\x3b\xa0\xe0\xca\xbd\xe5\xfc\x30\x37\x22\x15\x15\xfb\x10\xa7\xdd\xfb\xf5\xf0\xac\x72\x37\x49\x9f\xdb\xd5\xf7\x98\xf1\xa9\x06\x7e\x1f\xe8\x25\x0b\xd9\xbb\x76\xa5\x66\xc4\x4a\x71\x5a\xe1\x69\x39\xfe\xcd\x88\x15\x1b\xf3\xf3\xcb\xe4\xd0\x0d\x35\xab\x88\x75\x6e\xe8\xc0\xcb\x0d\x7f\xfc\xc7\xe0\x73\xd1\xd9\x7f\xce\x9c\xd4\xa4\x3d\xd0\xee\xdc\x76\x74\xca\xb6\xe1\x65\xc3\xc7\xec\x7c\x47\x0d\xf4\x92\x1a\x6a\x09\xb6\x84\x41\x91\x50\x1b\x49\x1a\x0b\x3f\x38\x2f\x8d\x89\xb6\x09\xf3\x3b\xef\x51\x09\x55\x15\xc1\xb9\x09\xca\xc8\x50\x4d\xf1\xa4\xd8\xe2\xcd\x53\x37\xfc\x3d\xf6\xd5\xad\x25\x53\x94\x13\x63\x23\x2a\x4a\x5e\x7b\xeb\x75\x3d\x14\xea\x36\x16\xf8\xd9\x8f\x56\x85\xf8\xf8\xfa\xbb\x7b\x74\xf8\xba\xef\xad\xca\xa9\x99\xa7\x1d\x17\x18\xa6\x0c\x0e\x73\xf6\xbd\x98\xd0\x88\xfd\xaf\xc6\x81\x5e\xb2\x9e\x5a\x02\x3c\x99\xf3\x1d\x77\xe0\xad\x09\x32\x39\x87\xcc\x24\xb9\x5b\x76\x1c\x72\xe4\x2b\x03\x83\xc6\xce\x9b\x5f\x5b\x7a\x71\xcd\xa6\x93\x0d\x47\xfc\x26\x7b\xc5\x45\x4f\xc8\x2b\x79\x39\xbe\x62\x7f\xae\xef\x74\xdb\x93\xa3\xa2\x16\x9c\x33\x2c\xff\x70\x69\x6b\x65\xd5\xaf\x9b\x67\x26\x8c\x3a\xe9\x39\x7b\x55\x65\xb6\x04\x40\xe0\xcf\xc9\x9a\xc7\xf9\xb0\xa4\xff\x7d\x22\x4f\x89\xaa\xce\x53\xba\x33\x7d\x79\xec\xdd\x70\x0d\x00\xa4\x2b\xeb\x47\xbe\xc3\x87\x76\x14\xb0\x07\x51\x81\x51\xea\x80\xf1\x6c\xcc\xe6\xad\xa1\xf9\xb0\x92\x50\x43\xb0\xe0\x6b\x15\x3d\xc1\x0d\xbd\xcf\x78\x91\x44\x4d\x5e\x63\x73\x68\x7f\x0e\xdb\x07\x95\xc9\xda\x18\x26\x66\x57\x48\x98\x5e\x48\x6d\xef\xdd\x8b\xa8\xe1\x22\xf3\xff\x92\x8d\x7d\xf9\xff\xb7\xed\x2d\x04\x75\x00\xf0\x7c\xd8\x37\x32\xc6\x46\xa9\x49\xf6\x61\x42\xa2\x26\x39\x07\x96\x90\x2b\x18\xeb\xeb\xe9\x5d\x27\x9a\xfc\x75\x86\xd5\xb4\xe9\x36\xd5\xd7\xaa\xad\x97\x96\xca\x32\x6f\xe5\x64\xa0\x5c\x61\xfc\xf5\x24\xcb\xb7\x4e\x11\x25\xe1\x33\xa0\x0e\xd5\xf8\x8d\x49\x8e\x20\x72\xfa\x5b\x17\x96\xc2\x2a\xb4\x00\x55\xa3\x53\x30\xb1\x91\x91\x47\xf3\xc0\x03\x2a\x80\xf5\x35\xb9\xbb\x22\xb1\x16\x9b\x75\x9a\x60\x56\x43\xe7\xed\x1d\x35\x3d\xb3\x24\x9a\x38\xf6\xd3\xb7\x17\x7f\x8f\x58\x55\xba\x6e\x79\x28\x75\x56\x34\xef\x5f\x70\xcd\x7f\x33\x73\x7d\x84\x5e\xbc\x3e\x0b\xdb\x72\xa2\x9d\x72\xa6\xf5\x80\x8f\x3d\x5e\x46\x96\x4a\x39\x5f\x22\xf7\x83\x4a\x7e\x2a\x11\x0a\x25\x35\x5f\x3b\xa2\xd7\x2a\xaf\x43\x9e\x9d\x90\x9e\x47\xb4\x93\x7d\x7d\xd4\xc3\x87\xb0\x75\xff\xc1\xca\x4f\xf0\x59\xa0\x25\xda\x79\x8f\xe8\xa3\x6c\xdc\x2b\x31\x8f\x7b\x19\xbd\x57\x4b\x14\x5a\xa2\x91\x54\x28\xd1\x16\x7f\x98\xed\x85\x0e\x6b\x61\xa9\xb2\x5f\xaf\x46\x17\x77\x42\xea\xb7\xec\x44\xa2\x9d\x7c\xa4\xbf\xa5\x47\x7f\xb4\x31\x8d\xc2\x66\xd6\x07\xec\x24\xda\xa9\x28\xfa\x28\xb0\x05\x32\xe0\x0e\x80\x33\x94\x7b\x98\x45\x23\xca\xe1\x21\x63\xe7\x97\x30\x0e\xe6\x97\x17\x65\x64\xfd\xf2\xf1\xba\xfa\xbc\xe2\xb4\xec\xd5\x5e\x95\xd9\xb9\xfb\x0b\x99\xd6\x1f\xe4\x55\x89\x69\xe9\x92\xb4\x5d\x6f\xb5\xa5\xc7\x07\xc5\x1c\x9d\x10\x57\x80\xfb\x68\x26\xda\xa9\x7a\xfa\x28\x10\x03\x67\xa0\xe0\xa2\x32\x8f\xe7\x87\xa6\xcd\x5e\xeb\xb2\x60\x1c\x9c\x97\xba\xc5\xeb\x45\xef\x5f\x3e\x46\x65\xba\xc3\xf5\x79\xc5\x99\x19\xb8\xb7\x7d\x0b\xa8\x25\x47\x61\xc3\x83\xdc\x84\xa3\x9a\xc4\x5d\x6f\xc1\xf7\xd0\x7f\xa7\xc7\x87\x44\x70\xfd\x11\x78\x4e\xeb\xe8\xa3\x6c\x1c\xe9\x0c\x07\xe3\x48\xb6\x8f\xce\x2f\x61\xd8\x95\xbb\xe8\x10\xfa\xd0\xa7\xf0\xef\x1f\x55\x2c\xc1\x63\xbf\xd9\x89\xee\xa0\xf3\x6d\xdf\x5c\x28\xad\xc2\xb6\xa0\x93\x68\x27\x7b\xe8\xa3\x4c\xac\xe7\x6c\x26\xe9\xce\x2f\x89\x29\xde\x83\x02\x5e\xaa\x1c\x94\x2a\x6b\x43\x9a\x89\x76\xf2\x0a\xfb\x3d\x89\x56\x2e\x91\xe3\xfa\x31\x39\xd9\xac\x84\xcb\x42\xd0\xe1\xd1\x70\xa6\x3f\xaa\x57\x12\x19\x5f\x12\xed\x6d\x90\xaf\xbf\xa5\xef\x13\xb0\xdf\xfb\x8d\x68\xa5\xca\xe9\x53\x83\x91\xc3\x20\xa1\x3b\x4e\xab\xd1\xca\x49\x66\xfb\xff\xb6\x1b\xda\xbd\x73\xe8\x95\xf4\xb2\x85\x2f\xbc\xa5\x9b\xf3\x42\x68\xa4\xef\x49\x2f\xb8\x75\x49\xd3\x99\x77\x3f\xa1\x02\xde\x87\xaa\xd7\xe3\xf4\x11\xab\xae\xae\x2e\x2d\x17\x5e\x3d\xde\xff\xb3\xf6\x1f\xc6\xb9\x50\xb7\x8d\x73\x51\x93\x72\x89\x1a\xef\xc9\xce\x2f\x6f\x65\xc2\x75\x99\xb7\xbf\xbc\xad\x43\xab\x75\xcc\x44\x50\x19\xac\xef\x13\xc0\x0e\x94\x8c\xbf\x57\x40\xb4\x93\x52\x6e\x2e\x66\x98\xb6\x05\xce\x75\x1b\x97\x3a\xc1\xeb\x4e\xeb\x36\x2d\x71\x26\xda\x2b\x42\x89\x6d\xda\x8a\x0a\x6d\xff\x0b\xa1\x15\x2c\x7e\xe5\x19\x58\x47\x30\xf2\xb7\x66\xf4\x9c\x64\x76\x8c\x31\x9a\x84\xb1\x09\x7e\x75\x8a\xcb\xb7\xba\x15\x86\xd7\xe3\x08\x12\xee\xd7\xdb\x19\xc8\x33\x7d\x8a\xa3\x7b\xa1\x0a\x98\xc6\xba\x17\x7f\x17\x8f\xd5\x14\x4f\x76\x5e\xbf\xb9\xa8\x04\xba\x43\x0a\x15\x5c\xfe\xbd\x61\x66\x0a\x1e\xae\x7d\x03\xcc\x41\xa3\xfa\x7f\x86\xfb\x03\xd0\x6b\xa6\xef\x93\xf9\xf4\x51\xc0\x03\xd6\xed\x70\x12\x09\xd2\x18\xd3\x15\x30\x1e\xcf\x9b\xdf\xf9\xe5\xad\x36\xb8\x0f\xaf\x59\xdf\xa9\x36\xe3\xff\xcf\x6b\xa5\x8f\x32\x7e\x8e\x33\x34\xc5\x91\x51\xd0\x18\x48\x76\x5e\x87\x3e\xbe\x34\xac\x84\x9a\x6b\x97\x17\x38\xc8\xc5\x14\x5a\x71\x5d\x45\x0b\xfc\x18\xd9\x3c\xea\x17\x10\x8f\xfa\x04\xf0\x9b\xc5\x55\x89\x7d\x3f\x91\x92\x9c\x6f\x90\x8f\xb1\x4d\x05\xde\xa7\xcc\x1c\xa0\x1a\x87\x92\x0a\x1c\x4a\x76\xde\x7a\x0c\x95\x02\x4b\xe7\x65\xe7\x6f\x3e\x40\x57\x04\x22\xb7\x62\xdc\x8e\x6d\xf2\x6e\x42\xd8\x27\x20\xe9\xf5\x3b\x91\xa3\x69\x5c\xfe\x78\x5f\x32\x6d\x58\xc1\xc1\x00\xb7\xf3\xce\xb9\xa2\x44\x8a\x98\x0b\xa5\x5f\x7e\x5c\x2c\x0b\xa4\xfb\xb7\xb1\xb2\x40\x3d\x24\xd1\x27\x80\xdf\xbf\x70\xb2\xef\x17\xd6\x9f\x7d\x48\xb4\x52\x5b\xe8\x53\xc0\x1a\x38\x99\xde\x36\xec\x85\xe0\xa9\x70\xf4\xe1\xab\xbf\xb7\x1c\xff\x04\x7d\xfd\xb8\xe3\xf2\xad\xdc\xcc\xcc\x4d\x93\x67\x4c\x9f\xb6\x39\x9d\xf2\x39\x09\xfd\x8e\x7c\x62\x40\x5f\xa2\xcd\x9f\xbd\x53\x58\x5c\xf1\xef\xf5\xba\xd2\x97\xbf\x06\x04\xb8\x48\xb4\x52\x6d\xf4\x51\x5c\xab\x89\x7d\x52\x9c\xf2\xa0\xb6\x85\x32\x29\x7e\x2f\x55\xf3\x69\x3e\xb3\xb1\xb1\x8f\x8a\xfd\x1a\x85\x27\x7d\xb1\x76\xf5\x02\xca\xf5\x86\xad\x84\x6a\x2c\x5a\x24\x96\xdd\x74\x18\xfb\x66\xed\x6f\x08\x75\x7e\x7e\xf7\xe3\xbe\xa2\xd9\x15\xb5\x64\xef\xaa\x63\x5e\x91\xe5\xc2\xd1\x9b\xd2\xe7\xc0\xea\xa2\xdc\x92\xd2\xab\x93\x27\xbd\xf5\xe1\xd9\xa3\xad\x8d\x97\xa7\x4c\x5b\xc4\xed\x6b\xf2\x16\x7d\x14\xe7\x40\x32\x52\xc1\x67\xa3\xe9\xc0\x60\x76\xf6\xf5\x5f\x8f\x1c\xb9\xff\x69\x78\xca\x32\xd7\xb9\xcb\xe2\xe2\x7d\x18\xc1\xec\xda\xf6\xd6\xfb\x68\x17\x31\x2a\x2f\x3d\x26\x9c\x6b\xe3\x0e\xd6\x2f\x76\xc5\x3d\x44\x52\x9a\x2f\x51\x90\x83\x6f\x8e\x9d\xd7\x21\x01\x27\xad\x2c\x6e\xff\x79\xeb\xc4\xcc\xd5\xaa\x59\xf3\xeb\x70\x3b\xe8\xbb\x25\x07\xbc\x50\x06\xac\x45\x15\x84\x66\xca\xd4\x52\x00\xa1\x80\x68\xa7\xd4\xf4\x51\xe6\x9c\x83\x9c\x2f\x0d\x05\x4a\x92\x52\xa2\xde\xb6\xaf\x8f\xf3\x1e\xb7\xb5\xf5\x9d\x22\x13\x59\xbd\xec\x23\x5a\xa9\x06\x56\xcf\x06\xcf\x2a\xd3\x31\xe5\xe9\xdd\x67\xb9\xee\x3f\xeb\xad\x53\x62\xd3\x75\xb2\x75\xb7\x36\xa6\xa1\x1d\x07\x8e\x93\x97\x83\xc7\x12\xd5\xfd\xd5\x81\xa3\xc3\x63\xe6\x2d\x23\x2a\xfb\x97\xa0\x8d\x07\x00\x80\x50\x4e\xb4\xd3\x8c\xcd\x76\x01\x00\x1a\xfd\x39\x89\x5a\xc2\xb8\x67\x58\x81\x35\x9c\x5b\x06\xe5\x97\x05\x34\x3d\x76\x1c\xfa\x50\x46\x50\x8e\xf1\x37\x6f\xa1\x44\xf4\x48\x48\xf1\x15\x63\xbf\xfe\x83\x3e\xda\x7f\x6d\x5c\xd9\xd4\x9a\x39\x44\x68\x7f\x5e\x5d\xfc\x69\xc2\xa7\x4f\x00\x7f\x4b\xcb\xf6\x59\x92\x87\xac\x01\x01\x4e\x13\xad\x64\x03\xef\x13\xe0\x8c\x33\x00\x82\x82\xa3\x20\x7b\xb9\xac\x34\xde\x38\x2b\x94\x6c\x3a\xa5\x96\x4b\x73\xe0\xdb\xc2\xd3\x67\x3b\x6a\x6c\x8a\xb3\xea\x02\x36\xed\xd9\xb0\x57\xb0\x70\x87\x25\xad\x5d\x95\x92\x5d\xf2\x71\x80\x57\xec\x5c\x3b\x9b\xf4\x45\x39\xe4\xca\x86\x5a\x1e\x15\x6a\x9f\x3a\x61\x6b\x42\xe9\x42\xb1\x2f\xa2\x8a\x22\x43\x96\x96\x79\x29\xd2\x93\xa3\x28\x32\x89\x59\xe3\xef\x88\x56\xf2\x34\xef\x13\xe0\xc2\xe9\x96\x44\x6d\x62\xa6\xa7\xed\x20\x17\x84\xc8\x30\xd4\xa6\x96\x53\x60\x9a\xff\x1d\xb9\x74\x87\x25\xed\xbf\x22\x2b\x67\xe1\xd9\x77\x6a\x6c\x8a\x83\x5f\x08\x63\xc6\xb0\xef\x51\xfa\xc2\x59\xb8\x73\xb2\xda\x52\x4a\xb8\x16\x69\x62\x96\xe9\xb6\xd5\x52\x94\xda\x39\x55\x2e\xdb\x9c\xb0\x0c\x46\x12\xbc\xa4\x58\x85\xd7\x94\x14\xbc\x5f\x6e\x12\xad\xe4\x55\xde\x65\x20\xc2\x1e\x2f\xf6\xbe\xcc\x01\x81\xb5\x83\x89\xa3\xf4\xcd\xd9\x6f\xcc\x5f\x1f\x42\x2b\x9b\x5a\xf6\x5b\x50\x73\xaa\xe7\xad\xec\xce\xf1\x9f\xa5\x09\xf2\x9f\x54\x42\x9e\x79\xf5\xb7\xed\x65\x05\x7d\x8f\xe6\x97\xed\xac\x5f\x9d\x77\x60\x5e\x60\xd4\x57\x80\x64\xe4\xc9\xd3\xf0\xae\xe0\xfb\xe5\x28\x3c\xb3\x30\xa8\x35\xbb\xc1\x31\xbf\x5f\xe6\x9e\xa8\x8d\xf7\xcb\xda\xc1\xfb\x65\x53\xfc\x7d\xfa\xde\x0d\x05\x31\x65\xe2\xdc\x35\xaf\xae\x4c\x29\xf0\xb0\xac\xb5\xa4\x43\xe6\x85\xcf\x5f\xa6\x6b\xc9\x8f\x9e\xe5\x49\xfb\xd4\xd8\x79\x2e\x0e\x5b\x52\x79\x39\x29\x7c\xb1\xd8\xbd\xa8\x02\x7e\xac\x4b\x5e\x18\xe4\x39\x79\x09\x59\x51\x5d\x6f\x67\x1d\x3f\x31\xe2\x60\xb8\xf7\xd8\x98\x82\xd8\x80\x9d\xb5\x1b\x7f\xab\xd7\x44\xce\x8f\xf6\x1e\xb3\x7c\x7e\xec\xc2\xe9\xb1\xa2\x8a\x6b\x35\xb1\xa1\x57\xb9\x73\xb4\x95\x6c\xa7\x7b\x80\x14\x78\xe0\xfd\xc6\xa7\x87\x0c\x51\xa9\xe0\x4b\x4c\x65\x18\xb6\xb0\xf3\xee\x55\x95\x8b\x1b\x2f\x34\x4b\x33\x7f\x79\x5e\x4b\xfe\x7a\x2d\xad\x2c\x56\xfb\x4e\x2a\xc9\x51\x4f\x0b\x26\xda\x29\xcd\x47\xcb\x67\x25\xf9\xef\xa8\x5d\xf7\x7b\x7d\xe9\x3c\x68\x1f\x12\x77\xad\x66\xf5\xcc\x23\xb8\x9f\x5e\xa2\x95\x92\xd3\xf7\x71\x2e\x30\x27\x77\x07\x36\xc9\x11\xcb\x7e\x50\xcd\x8c\xd2\xef\x9d\x7b\x28\x3f\x34\xc3\x8b\xa6\x2c\x27\x5c\xbd\x77\xd0\x9a\x1a\xbb\x30\x65\xfe\xf2\x7f\x06\xfa\x06\x64\x68\x83\xfc\x26\x2e\x25\x3b\x6b\x1f\xd5\x07\x46\x59\x06\x26\x41\xe1\x93\x0f\xe7\xab\xa3\x77\xd6\x87\x47\x64\xeb\xd3\x43\xe2\x3e\xc7\xfd\xf5\x10\xad\x64\x23\xef\x32\xc6\x15\x35\xf6\x87\x2d\xc9\x50\x28\x57\xe3\x3b\x78\x4f\xc9\xc5\xaa\x8a\xba\x1f\xae\x29\x88\xe4\xd8\xc0\xdc\xe9\x6b\x76\x34\xbc\xfe\x83\xfb\xa2\x55\x49\x11\x8b\xc9\xee\x4d\x3f\x56\x2f\x29\xa8\xd9\x64\x6b\x1b\x95\x6c\xef\xdd\x18\xd6\x08\xd5\x71\x13\x62\x5e\x00\x04\xb8\x4c\xb4\x92\x55\x83\x7d\x98\x56\x9b\x36\x5e\xd8\x0d\x5d\xda\xcb\xdf\xfe\x4b\x41\x4c\x8c\x0d\xcd\x9d\xfa\x52\xc3\xb6\xd7\x4b\x2e\xbe\xbc\xba\xee\xc3\xe4\xb0\x85\x12\xb7\x05\x95\xe4\xea\xea\x7a\x3b\xdb\xa8\x64\x07\xaf\x03\xe1\x8d\x5b\xea\x7b\xd6\x2e\x29\x8a\x5e\x94\x19\x07\x20\x68\x21\x5a\xc9\x52\xb3\xdc\xa0\xbf\x90\xa4\xd3\xb2\x64\x79\x48\xd8\x5b\xfb\xde\x5a\x1a\xad\xce\x8f\x0c\x9f\x12\x9f\x90\xeb\xb6\x60\xea\xdc\xc8\xb0\x8c\xe5\xe3\x97\xbe\xb9\xf5\x0d\xb2\x6c\xe6\x42\x29\xed\x30\xd5\xef\x85\x55\xe1\x7b\x46\x79\xf8\xf8\x7a\xc9\xb7\xab\x03\x94\x2a\xef\x51\x47\xb5\x2f\x60\x3b\xb6\x85\x68\x25\xe3\x79\x97\x19\x8d\x90\x68\x70\xd0\x6a\x74\xda\xcc\x8c\x03\x17\xbb\x6e\xa9\xaa\x6c\x5f\x53\xe1\x31\x63\xc6\xac\x45\x79\x15\xea\x1d\x07\xd7\x6d\x7d\xb7\xf6\xfc\xe9\xbd\xc4\x8d\xa3\x11\x05\x19\xdb\x47\x6b\xe2\xb4\xbb\xc2\xe7\xe5\x36\xf8\xd3\xa3\x57\x55\xae\x03\x04\xb8\x0e\x75\xe4\x23\xde\x65\xe0\x82\x23\x30\x0d\xeb\xf8\xb0\x34\xe5\x9c\x4e\x68\x59\x37\x62\x08\x52\x3b\x7d\x7d\xf9\x4b\xfb\x3d\x14\x74\x56\xf9\xdc\xa5\xf3\x0e\xe6\x45\xe5\x8e\xa5\x95\x4d\x87\x47\xb7\x1f\x4a\x5d\x79\x21\xc8\x4f\x9d\x39\x3e\xc8\x77\xd2\x12\xd8\xf0\x4e\x78\x53\x59\xf9\xee\x9a\x75\xbf\xd7\x07\x44\xe7\xf7\xdd\x6b\x6d\x94\x11\x59\x91\x11\x05\xaf\x4f\x0b\x89\xbb\x06\x08\x50\x07\x6b\x08\x0d\xef\x34\xb0\xc0\xbe\xb9\x59\x19\x91\x9a\xac\x0b\x8f\x29\x8e\x0b\x5f\xa0\x69\xe9\x6e\x85\xd7\x43\xe2\x32\xc3\xa3\x60\x00\x29\xe8\x7b\x64\xf2\x57\xa4\xf4\x7d\xee\x9c\x26\x69\xbe\x1a\xaa\x19\x8f\xc5\x8e\xd9\x0f\x0b\x84\xce\x7c\x18\xf6\x13\x3a\x7c\xb1\xa7\x2a\x33\x90\x68\xa7\x26\x20\xb7\xa4\xa9\x70\x12\x6a\x41\x99\x50\x11\xf0\x10\x40\x70\x9e\x68\xe7\x15\xb1\x39\xa4\xce\x5c\xa6\x8a\xcc\xf4\x60\xa8\x30\xbd\xba\x0d\x7e\x3a\xff\x46\x93\x2d\x5d\xb8\x79\xb7\x1b\x9d\xbf\x63\xee\x5c\x61\xee\x55\x9d\x4d\x7c\x4c\xb1\x6b\xcc\x55\x9d\x75\x42\x74\x91\x6b\x1c\xd1\x4e\x0a\xb6\x34\x36\x36\xae\x5a\xa0\x4d\x44\x09\xf0\x52\xa0\x47\xd6\xeb\x1b\xd0\x69\x78\xc9\x6f\x74\xd6\xc1\xcd\xe8\x0c\x33\x66\xa8\x23\x4f\xf1\x2e\xb3\xfe\xbe\xd9\xfb\xa4\x29\xe7\x49\x6b\xea\xad\xf3\x8d\x46\x5b\x7a\x7e\x43\x41\x81\xb0\xc4\x75\x53\x69\x42\x90\xca\x4b\x37\x6a\xb1\x65\x4a\x74\x91\x6b\x3c\xdb\x11\xd3\x4d\xff\xaf\xb5\x55\x92\xc3\x76\x2b\x60\x9f\xb1\x0f\x66\x4f\x1f\x26\x8f\xf2\xae\x00\x6b\x20\x33\xdb\x63\x84\x51\xe7\x59\x93\xd1\x3b\xef\xd4\x4b\x1b\xf6\x7d\x7d\xaa\xf6\xd0\x3f\x8a\xa7\xce\x2f\xd0\x66\x8e\x27\xbb\x77\x7c\x57\xd5\xb2\xe5\x2e\xfa\xb5\xb9\xae\xfa\xdc\xfa\xba\xd9\x4d\x00\x82\x26\xe2\x30\xe9\x8a\x31\x8e\x81\x44\x6b\x8c\xf7\x87\x6d\xa5\xa6\x28\xaf\x44\xff\x99\x2b\x23\x43\x35\x39\xe3\x17\xbe\x5c\xb7\x7b\xc1\xfb\xab\x2a\x88\x2f\x9b\x84\xb2\x33\x9b\x63\xe3\xdc\x1d\x8f\x68\x77\x6c\xdc\xf6\x73\x2d\x7b\x16\x3f\xa4\x34\x78\x6c\x42\x2e\x6f\x97\x99\xbc\x82\x9b\xf1\x43\x87\x2f\xde\xda\xb0\x8f\xee\x16\x14\xc4\xe6\x09\x29\xcd\xe9\x7f\xb7\x6c\x09\x0a\x88\x18\x53\xf7\x6a\x11\xfb\x5d\x66\x5e\xad\x94\x06\x7f\x97\x65\xee\x64\xf6\x96\x1a\x6b\x65\x2f\xdd\x6d\x51\x1c\x95\x2b\xe9\x1e\xd5\xdd\x5a\x7b\x88\xec\x1e\x1f\xe8\xaf\xae\xae\x28\x3a\xf9\x79\x33\xeb\x8f\xad\x86\x3a\xf2\x04\xef\xf2\xa0\x3d\x55\x07\x9b\xdb\x7b\xda\x0e\x9a\xdb\xd3\xd5\x3f\x35\x59\xd3\xf9\x15\x0b\x96\xe7\xb5\x14\x84\x65\x28\x68\x4b\x89\xba\xc6\x68\x4f\xa1\x8e\xd2\x2d\xaf\xd9\x59\xfb\xea\x7f\x6d\x09\x8a\x5a\x3e\xf3\x3e\xb1\x28\x24\xe6\x5a\x4d\xc5\xcc\xa3\x78\x8c\x57\x88\x56\xe2\x3e\x9d\x8f\xe5\x15\x45\xa8\x99\x38\x8b\x2b\x16\xb6\x37\x92\xfe\x5f\x91\xae\x9b\xbd\x4e\x71\x51\x71\x31\x8d\x8e\x1c\x1f\x9d\xfc\x42\x71\xbe\x20\x9d\xe7\x5e\x18\xda\xd2\x7a\x00\xd5\x39\xd8\xa9\x1d\x0f\x78\x65\xe7\x4a\xc2\x60\x39\xd3\xde\x6d\xa2\x95\xbc\xce\x3b\x0d\x1c\xcc\x7c\x17\xce\x75\xe1\x8e\xc6\xdb\x92\xec\xab\x73\x2d\x53\x63\x8b\x9c\xe3\xae\xb6\x34\xd9\xd1\x45\x9b\x0a\xe6\x91\xb5\xf1\xe9\xf0\x10\x0a\x0f\xf4\xcc\x3c\x5c\x03\x63\xfa\x1e\x6d\x6d\x5c\x05\x38\xfb\xdb\x4e\x01\xdc\x9e\x0c\x78\x45\x8b\x20\x45\x01\xa9\xd4\x4a\x96\x66\x2b\x10\x58\x5a\x5a\x5b\xa5\x80\x28\xb5\x5a\xa4\x16\xa9\xa3\xc4\xa1\xfe\xcc\xa7\x80\xf1\x12\x8d\xe9\x82\x4c\xc3\x5d\x90\xd1\x0a\x4f\x25\xbf\x07\x5e\xf4\x1b\x9d\xf5\xc6\xab\xe8\x0c\x69\xb1\xb5\x71\xc5\xc2\xd0\xf8\x0d\xa4\xff\xd5\x3c\xcb\x94\xd8\x05\x2e\x89\xff\x60\x77\xca\x9c\x62\xa1\x3b\xbb\x76\x37\x89\x56\x5e\x0d\xef\x34\x7e\x0d\x18\x36\x8f\xe1\x33\x62\x73\xe9\x6f\x8a\x72\xaf\xce\xb1\x4e\x8c\x2e\x76\x8e\x67\xb6\x59\x6c\xb1\x0b\x3b\xbd\xc2\xcd\x7b\x5c\xe9\xc2\x6d\x73\xf3\xc9\xda\xa0\x49\xf0\x14\x9e\xe3\xc1\x0d\x30\x0e\x85\xfb\x79\x67\xbe\xf1\x2a\x3b\xd9\xc6\xc6\x55\xb8\xcf\x76\xb2\x93\x77\x1a\xc7\x50\x6a\x09\x5b\x8b\xa2\x86\x8a\x9b\x57\xdc\x29\xda\xce\x55\xd4\xf5\x0d\xca\xfd\x86\x77\x1a\x2d\x6a\x1e\x33\xdd\x1d\xee\xeb\xc3\x7c\x85\x6a\xe2\x30\x29\xe3\x5d\xc1\x27\x07\x7b\x17\xc4\x59\xf6\xc1\xbb\x20\xbe\xe9\x2e\x48\x2d\xf7\xf5\x1f\x33\xc1\x6b\xfc\x18\x43\xc3\x0b\xeb\xf3\x57\x3a\x05\xba\xfa\x8d\xa7\x55\x69\xf1\xf3\xc7\xa7\xae\x48\x49\x22\x3a\x8f\xd9\xcb\xbd\x62\xd6\xaa\x37\xfd\xad\x7a\x7e\xda\x41\x9d\xd2\xd9\xfe\xd8\xa8\xf0\xb8\xc4\x50\x66\x1d\x2a\xa1\x8e\x02\xf4\xef\xc0\x1e\x8c\x65\xf4\xd1\xec\xb6\xc9\xa8\x93\xa4\x84\xdb\x6e\x43\x72\xca\x2b\x7f\x92\xb7\xed\xdd\xba\xe7\xe5\xe5\xd3\x0b\x67\x36\x16\xa9\x67\x85\xa7\x95\x8a\x26\x7a\xa7\xe7\xd4\xcb\x15\x3e\xc9\xd9\x6a\x55\x68\xa2\x04\xea\xa8\xd2\x3d\x9b\xab\xcb\xd6\x6c\x10\x0b\x57\xe6\x15\xbc\x35\xcd\xc1\x1d\xd5\x10\xae\x12\xc7\xe2\x19\x55\x87\x67\x67\x8f\x0f\xca\xcc\x62\xd7\xe4\x01\xd4\x91\x0f\x79\xa7\x99\x58\x49\x82\x2f\xb7\x31\xd2\x80\x44\x0d\x69\xfe\x03\x45\xee\xdc\x2b\xce\x34\x25\x99\x70\xfe\x1b\x54\x5d\xe1\x03\x75\x1d\x47\x08\x84\x5a\x63\xf7\xa8\x5f\x84\xaf\xf6\xc7\x7e\x79\x89\x39\x33\x88\x56\x8a\xa6\x7f\x37\xf9\x8b\x38\x16\x31\xcb\x2c\x76\x83\x32\x56\x59\x4c\xcf\x17\x4a\x5b\x78\xbd\x6d\xf7\xa2\xc3\x9b\x67\xd6\x86\x67\x2c\xce\x19\x1b\x61\x27\x4f\x68\xfe\xea\xcc\xa6\x43\x37\xb4\xc1\x89\xba\xa4\x9c\x25\x64\x47\xc3\x65\xaf\x19\x4b\xcb\x6a\x55\x5e\x3b\x93\xc6\x8c\xb3\x97\x8f\x0e\x5d\xfb\xf7\xf7\x6f\x6d\xdf\x11\x16\xfb\xca\x82\x62\x8d\xdb\x0e\xec\xb3\x40\x1d\x75\x14\x9f\xef\x1e\x6c\xbf\x32\x26\x56\x97\x19\xed\x09\x60\x4c\xb6\x1f\xe4\xb1\xe9\x85\xfc\xde\xf2\x57\x5e\x9d\x3a\xab\x28\xd5\x7d\xf3\x8b\x55\x5b\xd0\x93\xaf\xe2\x3f\x9a\xf8\xea\x4e\x82\x5a\xf4\x62\x4c\xf4\x28\xf2\x41\xdd\xbd\xc5\xe5\x53\x0f\xcf\xdb\xec\x04\x8b\x36\xd7\x1e\xdc\x74\x13\xfd\x6c\x89\x3a\x60\xba\xe4\x6f\x4e\xe2\x0b\x9b\x2a\x2a\xb0\x9c\x04\xb0\x88\x72\x67\x6d\xb6\x04\x2a\x99\x03\x9e\x3d\x6d\xdd\x19\x59\x49\x06\xef\x07\xfd\x21\x14\xc0\x8e\xd1\x7c\x57\x17\xa7\x51\x5e\xd1\x93\xa7\x67\x0b\xc5\x37\xee\xa1\xe5\x81\x7c\x2f\x77\x97\xb1\x11\xc9\xd9\xd9\x22\x17\xf4\xdf\xb0\x88\x58\xf0\x9d\x66\x9c\x45\xb3\xf3\xdc\x17\xaa\x60\x54\x7f\x2f\xfa\xc0\xdf\xd3\xb2\x45\x36\x6f\x71\x27\x5a\xca\xee\x51\x7a\x20\x0f\xb6\x91\x7b\x01\xc9\x9c\x87\x32\x89\xda\x6a\xb0\xf0\x99\x6e\xbd\xda\x62\x1d\x17\x5e\x18\x1e\x53\xd4\xc4\x9c\x83\xe4\xd9\xf0\xa8\xcc\x90\x38\x76\x3d\xe9\x81\x3c\x62\x35\x51\xce\xac\xa7\x8c\xcb\x7d\x61\x97\x82\x4f\xd2\xad\x4d\x76\xfc\xc2\x8d\x63\x9d\x7c\xdd\x95\x69\x2f\x8e\x4a\x6e\x62\xce\x0f\xfa\xb2\x75\x45\x05\x6a\xc1\xdf\xf5\x1b\x98\x46\x8e\x26\x8a\x19\x3b\xa3\x1d\xd9\xce\xf8\x8d\x60\x67\x02\x47\x30\x33\x4c\x5b\x73\x49\x31\x51\x3c\x7c\xdf\xf9\x99\xef\x3b\xa2\xd8\x7c\xdf\x11\x03\x9f\x23\x2b\x72\x06\x79\x88\xdd\x0f\xa4\xe4\x2f\xef\x87\x71\x7f\xbe\x1f\x90\xd5\x5f\xdc\x0f\x6a\x64\x4f\x6a\x88\xb2\x91\xf6\x83\x7a\xd8\x7e\x40\xf6\x4f\xef\x87\x81\xcb\x48\x4a\x52\x44\x39\x10\x32\xd1\x21\x29\xc1\x39\x64\xf8\xdc\x55\xda\x42\xbe\xc4\x94\xf0\x4a\xf3\x35\xfb\x3c\x74\xaf\x2d\xde\xf0\xda\x47\xcd\x65\xb1\xb4\xfd\xf8\x55\x5e\xf1\x81\xe9\x41\x39\xe1\x93\x46\x21\x29\x71\x6f\xe7\xbe\xd4\x43\x1b\x6e\xa2\xbb\x59\xa1\xab\xee\x10\x5e\x11\xb9\x87\x53\x6b\x4a\x96\x61\xbd\x88\x41\xf6\x14\x24\xd6\xb2\x7a\xaf\xfd\x33\xbd\x8f\x79\x8e\xde\xbf\xf9\xe7\x6a\x0f\xe0\xc0\x5c\xe4\x4e\xae\x22\xd6\x32\x7a\x4f\xfe\x89\xde\x1f\xfc\x53\xbd\x47\xee\x7f\xaa\xf7\xe5\x03\xbd\x34\xa2\xca\x30\x03\xc5\xf0\x97\xaf\x67\x24\xd1\xe2\xa7\x5b\x68\x8c\x16\xb8\x87\xb1\xc6\x9c\xc5\xae\xd5\x70\x94\x4d\xc1\x2b\xcd\xe7\x86\x26\xcd\x7e\x37\x67\xcd\x83\x2b\x37\xc9\x5f\xd8\x34\x59\xb3\x27\xb3\x0d\x75\xc4\x42\x6d\xea\x1b\x9b\xcc\x32\x65\x5f\x7b\xed\x12\xfc\xdc\x94\x1f\x4b\x0f\xf4\x52\x45\xb4\x14\xf8\x80\x60\xce\x73\x91\x69\xe5\x7c\xc6\x5f\x53\xb3\xe3\x18\x92\xa1\xc4\x04\x90\x90\x89\x2f\xa1\x79\x9e\x33\xed\xbe\x77\xa5\xb3\xd0\x0e\xfa\x2a\x9c\xa5\xf1\xde\xbb\x3d\xf6\x2c\x73\x75\x18\xed\x26\x48\x79\x31\x6d\xd7\x91\xf5\xf7\xb7\x7e\x90\x21\x98\xf0\x1d\x14\xda\x3b\x25\x79\x40\x1a\xe7\x3c\xd7\x25\xad\x4c\xa5\x9a\x1a\x9a\xa9\x84\xd7\x2d\x4a\x76\xbc\x4e\x37\xa4\x65\x45\x5d\xee\x38\x83\x0e\xfc\xe3\xd0\x16\x1e\x45\x2f\xec\xfb\x19\xe7\x3d\xef\x7b\xf1\xbe\xb1\xae\x93\x16\xd0\x52\x30\x0e\x84\x9a\xe7\xd3\x06\x47\xe1\xa1\x28\x9e\x1e\x34\x39\x72\x5d\xe6\x86\x1f\x1b\xa6\xad\x52\x0b\x08\x81\x48\xcc\x0c\x66\xb7\xe7\xde\x32\xe3\xb0\x13\xbc\x77\x79\xec\x59\xe6\x62\xdf\x37\xbc\x58\x33\xb1\x62\x22\xac\xb9\x00\xb3\x3a\x53\x66\xba\xd7\xa5\x66\xd1\x0b\x77\x1e\x30\x8e\xfa\x49\x36\x5b\xb7\xb9\xe6\xf7\x65\x93\x73\x5f\xb9\xc9\xea\x96\x17\x92\x92\x37\x68\x77\x10\x64\xca\x79\x31\x1b\xa3\x22\x8a\xc0\x1f\xb0\xf1\xb2\x83\x8c\x0f\x65\x36\x68\x42\xee\xa9\xbc\x11\x11\x1c\x91\x2b\x59\x6e\xef\x98\xe4\xb1\xdb\x7d\xef\xca\x51\x42\xdf\x43\x6e\xef\x8a\x7d\xce\xeb\x6b\x8a\xd2\x13\xa2\x43\x13\xad\xad\x6f\x04\xfc\x3b\xca\x51\x66\x1c\x6f\xc9\x64\x74\xaa\x28\xf1\xb6\x7d\x7a\x0e\xe1\x43\x2f\x6c\x68\xa6\xae\x36\x64\x66\x9e\x79\x3b\xe0\x3f\xee\xe9\x31\x91\x77\x51\xb7\x60\xf1\x8e\xd7\x69\x44\xa3\xfa\x51\x80\x1c\x28\x07\x80\x7f\x0d\x73\xee\x04\x81\x48\x00\x48\xb1\xd6\x68\x4d\x8d\x6b\x6c\x07\x23\xa1\x56\x4d\xf0\x48\xb9\xc4\x5b\x49\xca\x25\x7e\x24\xf3\x93\xe6\x43\x1e\xab\x88\x3c\x07\x99\x96\xfd\x54\x17\xdf\x9f\x83\x73\x0d\x6f\xa8\x04\x89\x1d\x45\xeb\xb7\xc8\x5c\xd4\x49\x1e\xbb\xd3\xd0\x83\x48\xd4\x1d\xbf\xf6\x74\x0a\xea\xce\xf6\x48\x9d\x36\x7d\x4c\x01\xea\x2e\x9a\xeb\x06\xbf\x85\x3e\x8e\xf9\xd1\x65\x84\xbc\x7b\x81\xab\x30\x7f\x6a\x2d\x2c\x85\xa1\xd6\xf0\x70\xd7\xb7\xdf\x2e\x5d\x7e\x64\x77\x6a\xd1\x3a\xc1\xc4\xe9\xe8\x0d\x31\xea\x86\x51\x22\x2f\xb4\x11\xb6\xf2\x6c\x6c\x6c\x78\xc8\x07\xf6\x8a\x16\x42\xdf\xa0\xe2\x80\x8a\x65\x5f\x28\x6c\xd7\xc5\xab\x2b\x70\x7c\x3f\x50\x0f\x00\x2f\x99\x2a\xc3\x28\x53\x66\x33\xc1\xb6\x95\x99\x83\x2d\xe4\x93\x72\x89\x3f\x24\xe5\x98\xdc\xcd\x0d\xca\x58\x6d\x2d\x8b\xfb\x3e\x87\xcb\x91\xb4\xf2\x18\x13\x20\xdb\xad\xda\xb6\x3c\x09\x75\xa7\xed\x6f\xce\x47\xdd\x45\xde\xe3\xc5\xf0\x42\x5a\xc3\x54\x37\x7a\x71\x1d\x2c\x85\x01\x42\x78\xb4\xeb\xdb\x37\xf7\x29\xa6\xef\xb7\x9a\x10\xb2\x7b\x9f\x1d\x3a\x0c\xcb\x7c\x7d\x91\x1a\xf6\x0a\x34\x91\xd0\x41\x3a\x5e\xba\x45\x2d\xa9\x00\x80\x40\x27\x90\x94\x2a\xc2\x7b\x5c\x0b\x00\x76\x7b\x64\x83\xce\x38\x97\xdc\x67\x0b\xcd\x74\x94\x2f\xd7\x3e\xb5\x91\xd0\x09\xbc\xe6\x90\xc0\x65\x03\xdb\xde\xaa\xbb\xbf\x85\x51\x58\x9e\xd4\x49\xea\x9c\xe0\xbd\xcb\x7d\x4f\x99\x8b\xbd\x3d\xea\xf6\x61\xd4\x83\xc8\x1c\x2c\x1f\x28\x6b\x68\xa6\xa8\xd3\x47\xce\x5e\xef\x3c\x8b\x0e\x76\x25\xcf\x9c\xb8\x79\xa5\x45\xc9\xb6\xd7\xe9\x05\xe7\xe9\x85\xa4\x8b\x59\x0d\x01\x1c\xc8\x00\x80\x3c\xc2\xd6\x68\x90\x78\x94\x46\x15\x20\xf1\xb1\x63\xa6\x8e\x38\x17\x98\x7f\xcc\x7d\xdf\x0a\x89\x74\xe1\x3d\x7b\xab\x86\xcb\x61\x5e\xb1\xbe\xda\x65\x7f\xf3\x16\xbb\xb2\xbb\xdc\x49\x16\x8f\xba\xb3\xc5\xb2\x24\x05\x0c\xdb\xfe\x3a\x0f\xfe\xd6\xf5\xad\x15\xfa\x5a\x78\xac\x91\x2e\xd9\xd1\xc4\x43\x67\x60\x33\x5d\xc2\xf4\x99\x08\x00\x99\x4a\x95\x03\x85\xb1\x4f\xad\x69\x17\xd8\xe1\xfc\xb5\xa1\x5d\x9e\x72\xdf\xb7\x42\x26\x76\x1c\xf7\xe9\x89\xa2\x97\x62\x63\x42\xea\x15\x3e\xce\xd2\xd1\x6a\x29\xa3\xf0\xf6\x2e\x71\xe8\x6a\xb6\x83\x3d\xd7\xe3\x8a\xcf\x2f\x78\xfd\x66\xdf\xda\x29\x08\x0a\x1d\xec\x10\x0e\x5c\x1d\xe8\x25\x1f\x51\x65\xc0\x0f\x00\xd2\xe8\xbc\x99\xaa\xc2\x64\x0e\x32\xa6\x43\x9a\x2f\xc3\x1e\x1c\x9b\x18\xad\x09\xf2\x23\x14\x9e\x7c\xff\xa0\xcd\x82\x9b\x57\x3e\x6e\x9e\xb7\x69\x65\x68\x62\x74\xf6\xac\x20\x9f\xb0\x51\xbb\x83\x36\x52\x7f\x7c\xbd\xe8\x60\xc2\x81\xe6\xf4\xc2\xc8\x9d\x01\x6e\x33\xc6\xc2\xd6\x3b\x13\x9c\xc7\x1f\x79\x6f\xce\xf5\x4c\xb5\x4a\x19\xe6\xeb\xaf\x56\x87\x7e\x1e\xab\x3c\xfd\xb1\x9b\xe2\x51\x4e\x4c\xc8\xd8\x88\x2c\xd1\x62\x66\xde\x2b\x06\x7a\xc9\x25\xbc\x54\x30\xce\x34\x6f\x05\x13\x3a\xc9\xf9\x72\x76\xdb\x33\x27\xe8\x90\x18\x8a\x35\x68\x1b\x99\xf9\x4b\x95\xbb\x5d\x2f\xbc\xf2\x41\x00\x74\x0e\x44\xf7\x22\xc5\x1e\xf1\xde\xbb\x13\xef\xba\xda\x8b\xb3\x63\xe6\x2e\xd9\xb7\xb3\xde\x5a\xee\x24\x49\x52\xc0\xfa\xed\xaf\xf3\xde\xdf\x9e\xd9\x7b\xff\x2e\xba\x2b\x28\x41\x9f\xf2\x33\x47\x25\x2b\x6e\x6b\x5e\x7a\x25\x30\x72\x27\x2b\xfb\xab\x00\x90\x1f\x53\x3a\xe6\x64\x55\x68\xa1\x92\x59\x63\x85\x58\xce\xd8\x4b\xad\x9c\x0f\x65\x83\xc2\xe7\xcb\xf9\xfe\x0a\xe8\x66\x67\xa3\x8d\x71\xd8\x15\x0b\xe1\xc4\x88\x7d\xa8\x4c\x4d\xdc\x57\xa1\xbb\x76\xc2\x88\x09\x4e\xbb\xc7\x35\xbd\x1a\x17\xb9\x15\xbe\x1b\xd0\x0e\x75\x84\x6f\x0c\x54\x2b\xce\xf6\x7c\x84\xde\x22\xd4\x91\x8d\xaf\xb9\xbe\xdd\xc3\xd6\xc8\x50\x51\x54\x19\x70\xc7\x19\x93\x92\x60\x9c\xc1\x29\xc2\x7a\x45\x3f\x95\xe8\x3a\x94\x18\x2f\xfe\xb7\x40\x48\xff\x58\xd8\x9a\xd7\x74\xba\xb8\xc6\xc5\xdd\x49\x90\xba\x69\xea\xa6\xd7\x37\xfd\x58\x37\x7b\x6d\xb8\x20\x74\x57\x4a\x54\x62\xc5\xa4\x94\xd8\xa4\x95\x93\x90\x0f\xb5\xfa\x87\xef\x5c\x55\xe8\x71\x56\xde\x82\xb2\x29\x79\xc9\x5f\xbe\xff\x01\x3a\x70\x65\xd2\xac\x2d\x70\x4b\x7a\x5e\xfd\x8f\xab\xb2\xb3\xeb\x1e\xe2\xf8\xbe\x9d\x0a\x63\x73\xad\xcd\xdf\xa7\x9a\x5a\x6e\x87\xc3\xe0\xb0\xdb\x87\xbe\x89\x45\x97\x63\x89\x76\x92\x40\x3f\x40\x87\x3e\x04\xd5\xe8\x0a\xb6\x2b\xad\x48\x4a\x95\xe3\x1c\x2f\x4f\x00\xf8\x41\x91\x50\xab\xd4\x7a\xb1\xb2\x72\x83\xf6\x42\x20\x1f\x5a\x0d\x4d\xe7\xbc\xf2\x5f\x7b\xb6\x4b\xe1\x3c\x64\xa9\x26\x1b\x7d\x91\xb2\xe0\xc5\x45\xe8\x33\xf4\xf3\x17\xfd\xd0\x3f\x53\x37\xb9\x3c\x76\xfa\xd4\xd5\x7b\xb2\x77\xfe\xbc\xd5\x7a\xe9\xfc\xeb\x3d\x57\xd0\xd5\x8c\xf9\xff\xaa\x42\x0f\xd1\x67\x5f\xb5\x4f\x99\x93\x7d\x70\xf6\xb4\x59\xe7\xd8\x73\xe3\xe8\x40\x21\xbf\x9d\x96\x82\x10\x00\xf8\x5a\x1c\x4e\x9b\x74\x05\x4a\xe4\x7c\xad\xda\x3c\x7b\x7a\x30\x73\x5a\x2e\x31\x7a\x2b\x4a\x7e\x66\xaf\xdc\xba\xcc\x4c\x6b\x4a\x88\xdd\x45\xd0\x57\x9a\x73\x13\xad\x0b\x13\x44\xee\x2a\xd8\xf4\x9a\x43\x2d\xea\xae\x13\x2e\xce\x7d\x6d\x5c\x3e\xea\x3e\xd4\x7f\xcf\x9a\x51\xa6\x29\x41\x5b\xf7\x3e\x0c\xcf\x09\x8c\x24\x9c\x59\x4d\x12\x10\x47\x60\x4f\x6e\x2e\xaa\xfc\x68\xf2\xec\xc3\x7b\xd3\x0a\xfb\x6b\x70\xc2\xf5\x9d\x2b\x28\x80\xb4\xec\xbf\xa6\xb8\xad\x11\xee\xc4\x63\x7e\x00\x00\x51\xc1\xe6\xae\x62\xc0\x14\x92\x39\xd0\xe4\x12\xa1\x6a\x8f\x0e\xfa\xe6\xed\x57\xed\x2d\x40\xdd\x05\xf0\xfa\x25\x78\x0e\x45\x5f\x42\x3e\xf0\x3a\x80\x03\xf7\x07\x7a\x89\x26\x4a\x07\x64\x66\xdf\x19\xb2\x07\x82\xb5\x62\xd5\xae\x3c\xe8\xab\xeb\x54\x75\xba\x65\xc5\xce\x59\xb2\x6f\xc7\x16\x81\xbb\xb1\x95\x03\x92\x24\xc5\x6d\x4d\x65\xad\x63\xc4\x0e\xfc\xd6\x8c\x75\xee\x0a\x55\x06\x9c\xc1\x68\xbc\xcf\x24\x0a\xed\x60\x7e\x3c\x9f\x69\x1c\x0c\xa9\xcd\x0a\xd6\xca\x69\x8c\xbe\xa9\xf0\xa4\xe3\xaf\xec\x51\xed\xd1\x71\xb6\x96\x58\xa0\xca\x0d\x45\x4f\x5a\x07\x8b\xb3\x62\x56\x7b\xa1\xbd\x94\x3f\xcc\x27\x6a\x92\xca\x90\x94\x3c\x7f\x09\x9e\x63\x6c\x6c\xc4\xa5\x7f\xa3\x5f\x06\x0b\xb4\x6a\xcb\x9c\xbf\x19\xe5\xa8\x5f\xc1\xbe\x53\xf6\x0c\xf4\xf2\xbc\x70\x8e\x93\x8b\x71\x86\x72\x76\x96\x38\xc5\x49\x13\xa4\xe5\xb1\x79\x64\xb4\x4c\xb5\x43\x07\x7d\x75\xb0\x8e\xf9\xb9\x57\xb5\x3b\x1a\xfd\xf2\xfd\xd5\x3b\x02\xa8\x6c\x9d\xf5\x82\x07\x2a\xa7\xb9\x29\xb3\xc2\xfb\xef\x6f\x2e\xbd\x1b\xed\x9b\x7a\x64\x45\xf5\x38\xb6\x9f\xfb\x03\xbd\xbc\x24\xcc\xbf\xab\xc4\xfd\x04\x6b\x15\x5a\x39\xdf\x16\xf2\xe5\xde\x4a\xad\x9c\xaf\x70\x90\xa9\xf9\x0a\x5b\x48\x29\x3c\x47\x6b\xb4\x3c\x6e\xe6\x62\xd5\xf2\xb4\x75\xbf\x06\x10\xf2\xc0\xb8\x0a\x1f\xf8\xa5\x68\x4a\x00\xfc\x3d\xa0\x2f\xcb\x67\x8f\x2a\xc7\xe6\xef\xe8\x7e\xd3\x3d\xf4\x90\x80\x8a\x95\x25\x45\xfb\xdc\xfa\xfb\xe0\xf5\x4b\xdb\x93\xee\xde\xb6\x5b\x3d\x63\xed\xec\xdb\x77\xe7\xaf\xbc\xb4\xee\x6e\xd5\xcf\x9f\x04\x3a\x2c\x59\xbd\x61\x39\xeb\xd7\x7a\x21\x1f\xec\x3b\x7a\x30\xfb\x5d\x0d\xe5\xa4\xd9\x2e\x37\xbb\xf9\x8b\x82\x7c\x4f\xf3\x0d\x8f\xc9\xef\x60\x32\xf4\x8d\xf4\x51\x09\xd2\xaa\x53\xb7\xbd\x95\x9b\x1e\xa3\xdc\xfe\xea\xac\x70\x95\x76\x8e\xe3\xa8\x20\xc6\x5f\xdc\xcd\x1d\x6e\xab\xd2\x68\x29\xfa\x4f\xc7\x8a\xfc\xa4\x7f\x9d\xd9\x8f\xbe\x28\x46\x57\xde\x39\xe0\x7c\x4d\x52\x5e\x46\x1d\xc2\x1b\x1e\x9f\x6c\x7f\xe0\x9a\x2b\x1f\x8c\xfd\xa1\x00\xe3\x87\xf8\x88\x5a\x89\x1c\xaa\xcd\xc7\xf2\x57\x20\x3b\xee\x96\xa4\x2a\xb7\xd7\xe6\x86\xfb\x6a\xe6\x38\xba\x66\xfe\x09\x7c\xc7\xe3\xcb\x68\x3f\x3b\xa8\x9a\xa7\x70\x3c\x06\xfd\x41\x5f\x93\x3f\x38\x82\x13\x28\x37\x1f\xa0\x9c\x3f\xe8\x08\x7e\x3a\x82\xf7\xb7\x8e\x00\x19\xec\xe8\x82\x75\x8e\x5e\x08\x29\x4c\x2e\x20\x79\xd1\xdc\xf9\xeb\xaf\x41\x55\xec\xb8\x8e\xb5\x30\xfe\x1f\x01\x9c\x91\x94\x77\x97\x2a\x03\xbe\x20\x0c\x00\x19\x0b\x29\xa9\xe0\x0a\x89\x07\xa9\x2a\x87\x0d\x86\xc6\x35\x31\x70\x88\xb5\x76\x6e\x3a\x5d\x54\x13\xe2\x26\x48\xda\x3c\x6d\x63\x73\xfd\x0f\x75\x39\xd5\xd1\x82\xd0\xef\x4f\x0e\x0e\x6c\xb6\xd3\x68\x84\x6c\x83\xd0\x93\x1f\x8a\xde\x9a\x05\x97\xa6\xc6\xc6\x2f\x4f\x4b\x8e\x9a\x58\x39\xb1\x31\x6b\xce\x27\x73\x75\xa9\x5f\x9c\xbd\x00\xf3\x3f\x4d\x98\xb3\xa5\xaf\xd1\x34\xc8\xc4\xfb\x77\xdc\x7d\x48\x75\x76\xf6\xcb\xbf\x56\xa6\xe7\x35\xdc\x03\x1c\xaf\xb9\x0f\xf5\x80\xc6\xbb\x09\x6b\x98\x1d\x54\x43\x39\x94\x0c\x5d\x52\x92\x2b\x21\xd9\x61\xe5\x65\x23\x80\x17\x61\x36\xb2\x6d\xaf\x4a\x35\x09\xc9\x35\xf4\xdd\x55\xc9\xb4\xb4\x3f\x39\x74\xe5\x38\x78\x03\x09\xd0\x6a\xd3\x8a\xc1\x96\x24\xd4\xc2\xac\xd3\x65\xe4\x43\xec\xa7\xa5\x40\xc4\xad\x53\x14\x54\xc0\x41\xcd\x51\x69\x03\x43\x6c\x5c\xf7\x33\x7d\xb0\xca\xf1\xea\xac\xf0\xef\x24\x61\xe1\x35\xb4\x94\x5b\x7e\x6e\xac\x34\xe3\x5f\xab\x07\x6b\x74\x64\xe6\x25\x2f\xe6\x43\x36\xb3\xe0\xc3\x8a\x77\x4c\x0e\x75\x96\xb9\x16\xee\xdf\x20\xcc\xd7\xed\x1a\x93\xc7\x18\xf0\x7c\x63\x45\x0f\xe7\x3b\xa3\x7c\xd3\x7c\xb0\xa5\xbe\xf7\x11\xf2\x1f\xac\x91\x61\x65\x58\xc2\xfa\x7c\xc3\x6a\x87\x86\xe0\x31\x8d\x50\x45\x94\xc5\xcd\x15\xcf\xdf\x65\xdf\xf0\x62\x22\x63\xbf\x61\xe1\x35\xe6\x35\x39\xa7\x39\x5f\x18\xdb\x05\xd2\xcc\x0d\x1e\x66\x14\x9e\x53\x32\x3b\xdc\x26\x3c\xa3\x64\xf6\x7a\xe7\x5e\xf4\xaf\x45\x83\x46\x61\x84\xb2\x59\x76\x6d\xb1\xcf\xeb\x3a\xb8\xb6\x43\xbd\x5e\x72\xd8\x3a\xff\x34\xe8\xee\x2e\x7f\xdb\x2b\xcc\x7c\xc1\x99\xb9\x33\x4e\xee\xbb\x7f\x43\x3f\xb2\x0b\x0f\x81\x0c\xf9\x90\x4d\x2c\x9e\x84\x96\x73\x27\xbd\x95\xa6\x87\x33\xa3\xdf\xe9\x06\x99\xf8\xca\x4c\x00\xcc\x79\x27\x63\xbc\xca\x64\xdd\xea\x3c\x33\xb7\xb3\xe2\x85\xa5\xfe\x63\x76\xbc\xc2\x4c\x7d\xb6\x93\xe3\x98\xb1\x8b\x0e\xfa\x32\x6e\xa5\x2a\x3e\x28\x7e\x5d\xee\xa0\xd7\x19\xb5\x23\xef\xed\xa2\x5b\x1d\xfb\xd9\x99\xbb\x01\x38\xa0\x40\x52\x72\x1d\xad\x00\x5e\x46\x5b\xc3\xc6\x21\xf6\x6c\x25\xdb\xd0\x6d\x8d\x7f\xb9\xe9\x17\x32\x3e\xc1\x1a\xba\x7b\x9d\xdc\x3e\x3b\x32\x30\x70\xbe\xd3\xe5\xe1\xb6\x45\x79\x7c\xf7\x8c\x94\xbb\x92\xe8\x30\x5e\xa2\xe1\x2d\xf7\x1e\x69\x79\x5f\xbc\x69\xc3\x1e\x3e\xd9\xe1\x8a\xf7\x68\x21\xf2\xa1\xb6\x50\x3a\xfc\x36\x80\x61\x5d\x71\xb5\xe9\x10\x7d\x97\x17\x42\xa5\x2f\xdf\x32\xda\x11\xfa\xc0\x38\xe4\x7a\x7d\x70\x73\x3a\xa3\xfd\x94\xae\xbf\xa3\x36\xdf\xe0\x47\x64\xf4\x55\x9b\x34\x19\xe3\x8f\xf9\x60\x9c\x2c\x47\x00\x4c\x18\x62\xc3\x36\xfe\x10\x08\xb1\x86\xda\x14\x93\xdc\x9c\x42\x87\x02\x88\xb5\xa1\xfd\xac\xa8\x6a\x06\xf1\xc3\xae\x22\x1f\xf2\x12\x9b\x8f\x6c\xca\x11\x35\x6f\xde\x5f\x41\x44\xb1\x3e\x70\xff\x27\xf0\xdd\x34\x93\x3a\xba\xb6\x13\x9d\x3d\x1f\xf5\x4f\x43\xdb\x8c\x63\x65\xcf\x9f\xa3\x54\x19\x50\x80\x80\x21\x35\xbf\xa4\x9a\x1c\xe6\xde\x8c\x48\x05\x3c\x48\xfb\x7b\x76\x49\x2a\x9d\x3e\x2e\x68\xe2\xfc\x55\x5b\x79\xa3\x33\x9e\xa6\x00\x36\x71\xfe\xf6\x55\xa3\x46\x0f\x51\xa2\xe4\x9a\xf3\xda\x17\x1c\xc6\xbd\x31\x84\x00\x18\x70\x75\xc8\xff\x27\x8e\x49\xca\xdb\x4e\x2b\x80\x6a\xc8\x5d\x4e\xb0\x96\x89\x49\xb0\xa2\xc2\xa1\xaf\x4a\xc1\xcf\x2a\x98\xfe\x71\xdd\xb4\xd5\xc1\x02\xda\x39\x01\xfa\xcd\x8a\x0c\x1c\xbf\xc0\x09\xf5\xda\x64\x84\x04\xa4\x2c\x6d\x68\xb4\xf1\xf4\x79\x66\xfd\x74\x72\xce\xb2\x0d\x30\x9b\xd1\xe4\xc7\xdf\x8f\xf7\x48\x92\x7c\xef\xbe\xf1\xc5\xa0\xa0\x86\xb5\x4f\xd7\x53\xb3\xf2\x8b\xa5\xca\x80\x92\xf3\x29\x9e\xa2\x67\x1d\x2e\xc6\x21\x97\x76\x4f\x93\xb3\xce\xa2\xd3\xfd\x02\xb1\x10\x3d\x3c\x47\xff\xf3\x7b\x98\x31\x32\x2f\x2b\xca\x36\x89\x50\xb5\x93\xfa\x06\x9e\x64\x2f\xeb\x20\x50\x22\x1f\x8c\x9f\xa1\xf9\x2b\xf8\x19\xe4\xb0\xc8\xf2\x4f\xe0\x34\x72\xf9\xe9\xbe\x41\x13\xe7\xaf\xde\x6a\xe5\x34\x7a\xdc\xf3\x90\x35\x50\xaa\xab\x94\x19\x5d\x4d\xc9\x38\xbf\x4a\x6a\x1f\xb3\x8f\xf4\xc8\x87\xec\xa3\xca\x40\x20\x13\x31\x69\x25\x7f\xce\x72\xa6\xe4\x9b\x0d\x2e\xdd\x72\xce\x73\xf8\xcd\x0a\x32\x9d\x8d\x52\xfb\xce\x6f\x1c\x3c\x3d\x32\xb9\x99\xb0\x8a\x13\x19\x5e\x37\x35\xf2\xe1\x39\x0f\xde\xb7\x3e\xcd\x9b\xc9\x57\x0f\x7f\xbb\xa4\x9f\xcf\xc6\x4a\xfd\x71\xd0\x24\x9f\xa5\x93\xd0\xf5\x8b\xcf\xa4\x66\xf5\xf6\xec\x27\xbc\xac\x8d\x02\x22\x84\xe7\xae\x1b\x89\x5a\xb1\xbf\x4c\xd4\xd3\x52\x20\x05\xee\x6c\x16\xf3\x53\xfb\xd0\x58\x46\x40\x2b\x3c\xbd\x7e\x82\xbe\x67\x4a\xcc\xf6\x5d\xf5\x9c\x19\x93\x52\xb3\x73\x77\x51\xba\x61\xbb\x8c\x57\x30\x63\x66\xe4\x84\xf4\x79\xd8\xa6\x75\x20\x1f\xb2\x86\x2a\x03\x3e\xec\x5a\x98\x55\x75\x0d\xa5\x0d\x1d\xb2\x04\xc9\x56\x3a\xf5\x6b\xd1\xd3\x37\xa4\xce\x9a\x1a\xb1\x26\x37\xe9\x60\x31\x5b\x04\x35\xce\xcf\x91\x6f\x94\xfd\x38\x3f\x78\x62\xf4\x98\x9a\xaf\x5f\xca\x9b\xab\xf0\xff\xdd\x4b\xf5\xc5\x87\xd7\x50\xeb\x69\x7a\x05\xab\x0c\x6b\x71\xdf\x2a\xe4\x43\x6a\x68\x05\x50\x18\xf5\x80\x71\x77\xcd\x8e\x20\x5b\x68\x67\xbe\xbb\xaf\x59\x66\x04\x04\x8f\x8f\xb7\x39\x65\x3a\x7e\x3a\xbc\x5b\x5e\x19\x65\xbe\xdc\xd5\x92\xe8\x30\xb2\x84\x3b\x79\x5a\x0c\x7a\xab\xb2\xc1\x75\x86\x60\x09\xf2\xa1\xce\x50\x3a\xf6\x95\x6e\x68\x3d\xc9\xb3\x2c\xdc\x50\xda\xa5\x33\x8b\x53\x4d\x5b\x72\x74\x26\x47\xc1\x34\x94\x72\x69\x98\xac\xbb\xee\xbc\xc1\x9e\x1d\xc7\x90\x0f\xae\x51\xf4\x32\xd3\x79\x6f\x15\x64\xef\x0a\x78\xd4\xd3\x6a\x9e\x61\x39\xe7\xf5\x4e\x18\xb0\x7c\x5b\xab\x17\xcc\x45\x4a\x35\xb9\x5a\x85\xd6\x41\x05\xfa\x37\xfa\x57\xe2\xe2\x21\x3a\x7e\x2a\x6b\x7b\x48\xc0\x91\x47\x3d\x1f\x3e\x0a\xfa\xf5\x93\xf3\xd6\x15\x83\x53\xe6\xf2\xa7\xda\x78\x17\xd9\x7c\xb2\x61\xef\xfd\xc3\x93\xa7\x0e\x35\x59\xd3\xba\xca\xf9\xcb\xe7\xbd\x9e\xb7\x6e\x02\xe5\x83\x33\xa7\xb2\x35\xd3\x83\x88\x76\x92\x58\x5e\xb3\x6b\xed\xab\x8f\xd6\x97\xce\x83\x96\x01\x51\xdd\xd5\x15\x73\xfe\x6e\x7a\xcf\x26\xb3\x79\x17\xf1\x59\xce\x66\xab\x99\xcc\x8b\x29\xe1\xe7\xe6\xfc\xd3\xab\x2b\x0b\xa2\xbc\x13\xfd\x66\xae\x8c\x0a\xd1\xcc\x1c\x5f\x54\xbd\x71\x07\xd9\xd9\xd0\xbb\x2e\xe8\x80\xc8\xf1\x83\xf5\xb1\x71\x1e\xa3\x8e\x68\x77\xe0\xf1\x6e\x24\x16\x92\x49\xbc\x8b\x18\xc7\x10\x48\x4c\x15\x08\x5c\xab\x7c\xb3\xc1\xd3\xf8\x29\x89\x35\x19\x1b\xdd\xe2\xdc\xe7\x9f\x5e\xf5\x52\x41\xb4\x57\xa2\xdf\xb4\x55\x82\x82\x25\xd3\x17\x4c\xde\x90\xb9\x2d\xca\x2a\xe6\xa2\xdb\xac\x90\x04\x2f\xaf\x6c\xa2\x31\x70\x4e\x64\x66\xc3\xfd\x5a\xa6\xcf\xbf\xaf\x4c\xcb\x4b\x4b\x2d\x09\xd3\xda\xce\x87\x92\x48\xbf\xd1\xa3\xe4\x4c\xdf\x5f\x12\xad\xe4\x15\xba\x8f\xab\x43\xe3\x72\xef\xfc\xa0\x92\xaf\xd4\x7a\x2b\xb5\x0e\x32\xad\x8c\xef\x06\xed\x85\x84\x62\x68\x1d\xda\x97\xb3\x0e\x15\xae\x8a\xa2\x79\xe3\xdc\x9b\x23\x36\x0a\x13\x33\x66\x27\xb4\xaa\x6b\x43\x55\x5f\x5d\xd8\xd5\xd8\x1d\xa2\x89\x2f\x08\xd4\xa4\xcc\x23\xbb\xca\xce\x14\x65\x25\x2e\x73\xcf\x5d\x90\x2e\x54\x56\xab\x34\x39\xc5\x93\x52\x8e\x17\xa3\xc7\xa8\x6b\x4f\x85\x36\xea\x50\x69\x60\xdc\xc1\xff\xcd\xb9\x4d\x70\x00\xc1\x6c\x32\x91\x7e\x08\xdc\xb8\x8c\xe8\x91\x83\x4b\x42\xe1\x49\xa8\x9d\x55\x31\x36\x5b\xca\xec\xab\x6c\x5d\xd6\xad\xd1\x25\x4d\x50\xfb\x8c\x19\x2f\x10\xec\x52\xec\xda\xa9\xb9\x33\x15\x16\x1d\xb6\x0d\x8d\x24\x9a\x0a\x43\xc3\xd7\xbe\xa8\xd8\x2f\x9b\xe0\xab\x3a\xd8\x1f\x83\x10\xd6\xf3\x5e\x98\x4f\x64\xf3\x3a\x18\x1f\x89\xcb\xba\xc6\x17\x2c\xf8\xaa\x87\x59\x36\xa9\xaf\x67\xae\x73\xfa\x62\xb7\x45\x31\x57\xe3\x16\xba\x17\x65\xb9\x6d\x2a\x49\x81\x65\xad\x76\xe5\xb0\xbc\x0e\x6a\xd0\xe5\x3a\x54\xf4\xca\x9a\xff\x4f\xf3\xb0\x20\xb8\x0d\x0b\xc8\x2e\x16\xdf\xe0\xe9\x5c\x13\x0e\xec\xfd\xb6\x28\xbb\x6b\x8e\x75\x6a\x64\xa1\x5b\x7c\x57\x6f\x57\xa0\xad\x2f\x3d\x67\x65\xc1\x5c\xb2\x36\x6c\x06\x3c\x88\xa2\xfd\x15\x99\x7b\xb6\xc2\x88\x27\xc7\xbe\x9f\xb8\x61\x05\xe6\x11\x6f\x24\xda\x89\x85\xf4\x1d\x60\x85\x6b\xe8\x4c\x22\x51\x38\x0f\xbe\x69\x37\xba\x2d\x8a\xea\x8a\x59\xe8\xb2\x28\xfe\x1f\x09\x55\xb1\x61\x85\x61\x51\xc5\xe4\x23\x4e\x28\xa7\x61\x3c\xb1\x2c\x2c\x32\x33\x38\x16\x40\x46\x4f\xb1\x8c\xed\xb8\xec\x54\x92\x6f\xb2\x1a\x5f\xda\xbc\xd0\x55\x22\x08\x0b\x88\x4c\x5e\x5c\x34\x97\xcc\x76\x48\x81\xfd\x88\x08\x0d\x70\xdc\xe7\x35\x83\xdd\xaf\x0b\x89\x76\xe2\x12\x7b\xcf\x69\x9e\x4f\xbf\x50\x56\xad\x2b\x72\x80\x27\x65\xd5\xba\x42\x29\xd1\xbe\x20\x14\x9e\x0b\x2f\x2c\x0c\x47\xd1\xa1\x0b\x86\x7e\x4f\x82\xf3\x79\x14\x5a\xb5\x96\xf9\x2a\xa1\xe6\x2b\xf8\xf8\xdb\x8a\x45\xee\xc5\x6e\x6c\x0b\xee\x8b\x5c\x17\x2a\xd8\x56\x5a\xeb\x1a\x98\x66\x1a\xea\x5a\xd9\x76\xc8\x81\xfd\x30\x9b\xc8\xa1\xef\x72\x9c\x87\x80\x0c\x0a\x66\x8b\x65\xf8\x66\x29\x96\x18\xc1\x73\x50\x2e\x05\x6b\xcb\x9c\x0f\x5f\x6d\x2d\x72\x2c\xf6\x5c\xbf\x30\x33\xbf\xca\x41\x32\xc1\xce\x42\x3e\x76\x3c\xcc\x89\x0d\x2b\x0a\x8f\x29\x82\x0f\x72\xf3\x49\x41\xdf\xa3\xc5\x95\x25\x33\x26\x8a\x1c\x93\x55\x63\xa9\xe9\xe1\xe1\x99\xda\x38\x66\xdc\x3b\x61\x3e\x91\x4f\xf7\x70\xb9\x52\x92\x21\x76\x7e\xa7\xf5\x2f\x5d\xbf\x58\x84\x28\x3d\x03\xa7\xcd\x5b\x44\x48\xc3\xc6\x52\x4b\x9f\x6c\xf2\x74\x50\xdb\x35\xc9\x72\x18\x5d\xee\x82\xd9\x84\x96\xee\x31\x55\x10\x98\x0a\xd2\x03\xc6\xba\x79\x8c\x17\xfc\xd1\xf5\xc8\xf9\xa5\x05\xb1\xb0\xe4\x75\x5b\xbf\x31\xd4\xf6\x27\x25\x6b\x5f\x34\xe5\xff\x13\xb7\x78\x1d\x80\x07\x84\xef\xc2\x94\xdd\x24\x64\x4b\x00\x66\x0f\xd6\x00\x1c\xba\x5a\x03\x7d\xe5\x8c\x5d\xed\x6f\xc2\xb5\xef\xa0\x1d\xe6\xf3\x32\x78\x17\x81\xdf\x48\x39\x78\x23\x24\xc5\x0d\x46\xdf\xed\x2d\x4d\x76\xfc\xf9\x9b\xf6\xb8\x51\xf3\xb7\xce\xcd\xb3\x2d\x71\xdd\x58\x9a\xe2\xab\xf2\x9a\x23\x5b\x64\x19\x1f\x55\xe4\x1a\x7b\x75\x8e\x75\x7c\x44\x91\x7b\x3c\xd3\x5b\xfd\xfe\xfd\xfb\xcb\x17\xf8\x64\xf6\x3f\xae\xad\x14\x31\x9b\xee\x77\xbf\xd1\x99\xfb\x36\xa3\x73\xf0\xbc\xdf\xe8\xcc\x3d\x5b\xd1\x39\x66\x2c\x77\x61\x01\xaf\x92\xd7\x81\x2d\xf0\x73\x72\x94\xb8\x9d\xc0\xa6\x29\xdd\xb5\xcb\xed\xd2\xd9\xc4\xc7\x2c\x70\x89\x65\xfe\x8d\x5e\xe0\x1a\xdf\x75\xff\x33\xb5\x95\x1f\xa5\x5b\x3d\x59\xc7\xa7\xe7\x37\xcc\xc9\x23\x6b\xc3\xa2\x61\x07\x8a\x56\x29\x33\x0f\xae\x87\x51\xf8\x43\xe3\x46\xbc\x4d\x42\x77\xaf\xc8\x4c\xda\xbf\x8a\x95\x9f\x25\xcc\xc7\x67\x96\xd1\x06\x06\x6b\xcd\x6f\x21\x06\x67\xce\x88\xc5\x52\xae\xf4\x18\x2f\xe8\x68\xb2\xa5\x0b\x37\x16\xcc\x17\xe6\x76\xe9\x2c\x27\x45\x2f\x70\xcb\x72\xad\x2a\x88\x83\xe5\x4d\x36\xe3\xc6\x90\xd9\x5b\x1a\x57\x15\x6a\x92\x50\x32\xec\x0c\xf4\xc8\x6a\xac\x47\x8b\x5f\x59\xc5\xae\x13\xcc\x27\x3b\x78\x17\x19\x3d\x1c\x92\x83\x38\xcc\xd7\x33\xe5\x21\x1e\x6a\xb2\xa5\xe7\xd7\x17\x14\x08\x17\x09\x26\x78\xcb\xc7\x4f\x2b\x28\xb1\x59\x8c\x7b\xc3\xb2\xdd\xd2\x58\xbe\x40\x93\x84\x2c\xdc\x9c\x02\x6c\x9a\xec\x67\xce\x1c\x13\x05\x1f\xb3\xfd\x7d\xc0\xe5\x68\xc6\xf3\x3a\xb8\x1c\x4d\x09\x2b\x42\x92\x6f\x0b\xc9\xce\x43\xf7\x2f\xda\xdb\xc4\x7e\xdc\x72\xff\x82\x0d\x65\x99\x8c\x95\xe2\xdb\x63\x11\x30\xa0\x0f\x11\xce\xd3\x5d\x22\xd0\x76\x00\x48\xd0\x4b\xb4\x92\x47\x78\x17\x81\x15\x90\x72\x95\x14\x66\xc9\x8c\x66\xec\x73\x0a\xcf\xde\x5b\xa7\xd6\x1f\xb8\xf1\xde\xab\xcd\x9f\x86\x68\x42\x32\x1d\xd0\xaf\x84\x2b\x14\x14\x16\x93\x5d\xdf\x40\x69\xcb\xe6\xff\xa0\x5f\x0f\xbd\x12\x15\x3b\x23\x45\xd2\x22\xdd\xcc\xb4\x0b\x33\xa9\x53\xf4\x23\x20\x06\x4e\xc0\x13\xb7\xcb\x8c\x8c\xcd\x36\x61\xf3\x28\xb4\x52\x07\x99\xc4\x96\xe0\x45\x12\x9a\x20\x6f\x65\xef\x1f\xff\x89\xba\x1c\xbd\x75\x5f\xe9\xe7\xdb\xe2\xae\x24\x6f\x69\xfe\x32\x3c\x7c\x7e\x62\xbe\x06\xc6\x25\xe5\xa9\x23\xc2\xc9\xfb\x1f\x41\xca\x0e\xfa\xa3\x2e\xa9\xfe\xd5\x75\x5d\x2b\xed\x50\x1b\xcc\xb4\x33\xec\x4c\xca\x13\xc0\x6b\x54\x46\x4d\x9f\xe5\xb4\x97\xd3\x62\x72\xad\xd8\x75\x5e\x02\xd3\xc9\x00\xde\x45\xe0\xcf\xea\xd9\x73\x6f\x42\xe8\xa1\x6f\x5f\x4b\x04\x31\x25\x65\xc1\x93\xc6\x4c\x9e\x11\x73\x60\x53\x7d\x69\xc2\x82\x34\xcf\xe0\x80\x09\x33\x52\x8e\x36\x86\x04\x38\xa8\x3d\xbd\x83\xe2\x66\xcc\x85\x8f\xbd\x5d\x61\x48\xb4\xdf\x18\xa7\x71\xbe\xfe\xb3\x63\xd6\xbc\x1c\xbb\x2b\xcc\xc3\xd3\x55\xe5\xe2\xbb\x20\xee\xe5\xad\x74\x99\xad\xda\x7a\xa7\x38\x1b\xc0\x81\x6b\x30\x9b\x38\x42\x3f\x64\x2c\xb3\x71\x9f\x07\x9b\x39\xa1\x0a\x4f\x95\xc7\x18\x8f\xf1\x82\x8f\xd4\x57\xe2\xc6\xca\xbd\x12\xc5\x17\x5c\x6b\xf2\xe3\x60\xc9\xeb\xd6\xe3\xc6\x92\x47\x1e\xd8\xb7\xd8\x65\xf4\xe5\x6f\x58\xc9\xce\xe9\x32\xcc\x27\xee\xd2\x39\x38\x6f\xce\x98\xf7\x88\xcd\xf3\x90\x7b\x08\xec\x63\x4a\x2e\x8b\xd7\xe5\xbc\x2a\xff\xc0\xf3\x7c\x1a\x15\x16\x35\x2d\xdc\xf1\x85\xd9\x51\x3e\x9e\x5e\xa9\x12\xa1\x60\x41\x1e\x39\x8d\x37\xaa\x20\xac\xb9\xe5\x00\xaa\xf7\x52\x3b\xa2\x7b\x2f\xbe\x20\x69\xb0\xce\xcc\x9e\x31\x4b\xaa\x84\xaf\x02\x02\x6c\x27\x5a\x29\x01\x3e\xa3\x3c\x4c\xe7\x89\xf1\x4c\x31\x5d\xd2\x6a\x65\x6c\x84\x42\x6f\x77\x9f\x1f\x71\x35\xfa\x87\xa8\xae\xa8\x85\xee\x45\x49\x07\x6c\x05\xa1\xcb\x13\x0a\xf2\x6c\xcf\xa5\x06\x64\xba\xdf\xb6\xa3\xa8\x3a\xe8\x83\xae\x33\xff\xd5\x21\xfd\xe6\xcc\xa4\xf2\xc2\xc0\x29\xf9\x99\xba\xec\x09\xec\x9c\xbe\x23\x5a\xa9\x5c\x16\x6f\x54\x12\xc4\x3e\x1c\x70\xfe\x9d\x26\x08\x3f\x1e\x70\x0b\xe4\xfd\xdd\xec\xa2\xc3\x0a\x58\x2e\xbf\x34\x63\xa2\xae\x3c\x49\x0e\x73\xe4\xc7\x02\x26\xfc\xf0\x61\x53\x27\x79\xb9\xe0\x8d\x84\x03\xfb\x4a\x3f\x4e\x9a\x52\x57\x5a\x5a\xb8\xef\x80\x5f\x45\xc4\xbb\x5f\x1c\x62\xdb\x26\x1f\xb3\xfe\xc2\x70\x5b\x83\x27\xf1\x9d\x4d\xd6\xd5\x1c\x8b\xb2\xd8\x34\x87\xec\xab\xd9\xe3\xde\x7f\x63\xeb\x01\xf2\x98\x5f\x08\x6c\x46\xd9\xfe\x4e\x2b\xb2\x0b\xe0\x11\x94\x7b\xe9\x8d\x0d\x5c\x1e\x1f\xd1\x4a\xfe\xc6\xbb\xc8\xea\xb1\x79\x7d\x4b\xf0\x10\x98\x0a\xf6\x52\xcd\xfb\x81\x75\x76\x57\xb6\x20\x32\x26\x39\x5b\xaa\x72\x77\xf4\xf6\x9c\x11\x92\x3b\x9f\x56\x2a\x2f\x1d\xdd\xd5\x4a\xea\xc7\x8f\x87\xad\x28\xcb\x43\x19\x1e\xaa\xd3\x7d\xc6\x73\x95\xdb\x35\xc9\x0a\x67\xcb\xbd\x4e\x9d\x68\xe1\xfa\x4a\x24\xda\x49\x05\xaf\x03\xd7\x33\x43\xb5\x44\x41\x7a\x47\xe0\xe2\xaa\x44\x78\xf0\x3f\xba\xcb\xee\x94\xc0\xdb\xfe\x0a\xb3\x95\xfb\x10\xdc\xe1\x94\xeb\xb3\x4c\x89\x0a\xf1\xf7\x56\x13\xed\xa4\x06\xf3\xb7\x00\x89\xa9\xce\x78\xb5\x23\xdc\x8c\x7e\x52\x10\xb4\x1b\x5a\x03\x7d\x3d\x88\xf6\x4a\x78\xa7\x79\x23\xf2\x69\x62\xfb\x5a\x0d\xf3\xf1\x77\x1c\xcd\xbe\x33\x3c\x5e\x19\xda\x84\x86\x56\x7b\x78\x8f\x9d\x94\x95\x6f\xe1\x60\x6a\x0c\xf5\x89\x45\x6a\xeb\x06\xc9\x8c\xa9\x76\xc1\xf3\xd9\x5c\x60\x22\x94\x6c\xe0\x75\x00\x19\xae\x5e\xe5\x5a\x56\x73\xe9\x5a\xb4\x0a\xf2\x95\xc1\x51\x90\x71\x41\x15\x9e\xe6\xcd\x27\x4e\x4f\xcf\x18\x1f\x3f\xe5\xf0\x6b\x79\xa9\x3a\x99\xc3\x4f\xf2\x2a\xaf\x20\x53\x27\x4b\x53\xbc\x67\x24\xae\x58\x52\x11\x30\xd6\xa3\x29\xd6\x13\x40\x10\x06\x8b\xc8\x0c\x8c\x85\x0a\x24\xcf\xac\x93\x0e\x53\x57\x05\x2f\xad\x9e\x3d\x3d\xd7\x1d\x0a\x51\xbb\x82\x48\x74\x45\x27\x57\xbc\xfa\xc3\x85\x6d\xb0\xb1\xc3\xd9\x6b\xd9\x9c\x89\x53\xb7\x43\xfe\xc1\x75\xa8\xcb\x72\xcb\xa2\x13\x5f\xe1\x7a\xce\xdf\x89\x56\xf2\x1a\xfd\x18\x63\x12\xb8\x0e\x56\x96\xb1\xcf\xc5\x5c\x49\x03\x2d\x51\xb3\xb6\xfb\xf7\xaa\x0b\x3b\x6a\x6a\x57\x7e\xb4\xbd\xb6\xee\xca\xd4\xc8\x59\xde\x8f\x1d\xb4\x8f\xa5\x69\x91\xb3\xc9\x5b\x9d\xb0\xa5\xe3\xd0\x9e\x93\x68\xce\x99\xa6\x8a\xb5\x07\xdf\x5c\x0a\x6d\x57\xa5\xae\x6e\x06\xe4\x80\x90\x7a\x44\xe8\xe8\xed\xb8\x2e\xd8\xd9\x1c\xc9\x06\x6a\xd5\x52\x19\x5f\xe1\x3d\x48\xf3\xf1\x20\x39\x7e\x59\xfc\xc4\x15\xd0\x9e\xfa\xd1\x8e\xae\x9a\x0b\xe5\x93\x12\x98\xdf\x79\xb9\x49\xa9\xf3\xe3\xa7\xc0\x4c\x69\x45\x9b\xd3\x69\x55\x52\x4a\x41\xfc\x14\xec\x03\xa1\xef\xa8\x47\xc4\x3a\xdc\xb6\x98\x19\xbb\x19\x9d\x8b\x26\x12\x6a\xd5\xf6\x34\xdf\x6b\x30\xae\x47\xdf\x71\xcd\xcb\xfe\x2f\xda\xbe\x04\x3e\xaa\x22\xf9\xbf\xfb\x9d\xe1\x0a\x49\x66\x92\x49\x08\x39\x26\x43\x32\x86\x10\x92\x30\x4c\x26\xe1\x0a\x84\x00\x21\xdc\x11\x63\x88\x10\x4e\x39\xe5\x32\xb0\x88\x18\x11\x11\x01\x31\x72\x4a\x00\x11\x01\x59\x44\x44\x44\x16\x23\x22\x8a\x88\xe8\x22\x22\xb2\x59\x65\x91\x45\x17\x11\xaf\x8d\x2c\xe2\xca\x8f\x85\x4c\xcf\xff\xf3\xfa\x1d\xf3\x8e\x7e\x33\x93\xe8\xff\xb3\x1f\x57\x90\xf0\xfa\x5b\xdf\xae\xae\xaa\xee\xae\xaa\x8e\x1e\x18\xd7\x38\x66\x2d\x64\x06\x16\x75\xcb\xf7\x7f\xdf\xde\xae\xe3\xe1\x41\xd6\xd5\xbb\xbe\x2f\x1e\xe4\xce\x12\x46\xa0\x7c\x2d\xbd\x7b\x7c\x0d\xbe\xbd\x20\x03\x74\x02\x80\xc7\x1f\x0f\xa7\xa2\xad\x89\x94\xf8\x6f\x5b\x74\x8a\xbb\xab\x60\xcd\x3b\x53\xe2\xbf\x1d\x29\xbc\xe5\x66\x91\x7b\x5a\xb2\x33\x39\xa1\x43\x42\x42\x87\x84\x8a\x83\xf6\x74\xbb\x3d\xdd\xee\xc8\x70\xe4\x64\x76\x9e\x34\x37\xbe\x67\x5c\x82\xa5\x4d\x0b\x8e\x6f\x65\x89\x8a\xb4\xb4\x6e\xc1\x87\x33\x39\x05\x11\xd1\xe1\xad\xb8\xb0\x16\x2d\x23\x22\xda\xda\xa2\x22\xc2\x22\xa3\xd1\x70\x00\x7d\x49\xcc\x51\x2a\x9d\xbd\x2d\xc4\x89\xb4\x0b\x9f\x26\x50\xf8\x98\x29\x5c\xf0\x54\x97\x8f\xb0\x77\x65\xa6\x8e\x9c\x53\x3b\x35\x3c\xbd\x75\xbf\x87\xe6\xce\x29\x58\xb0\x84\xbd\x9d\xe7\x49\x49\x4f\x39\x91\x96\x99\xb6\x1b\x40\xdf\x7c\xe6\x24\xbc\xc2\x31\x80\x15\x6c\xb1\xdd\x63\x63\x57\x41\xc7\x6f\x65\xe8\x2b\xe6\xe4\x91\x65\x3b\x9f\x17\xf7\xd2\x93\x98\x93\xb0\x5e\xfa\x19\x8f\xcd\x1e\x6d\xdf\x5a\x76\x13\x3a\xd0\x21\x76\xc2\xce\x65\x47\xf0\x37\x0e\xc1\x2b\xec\x7f\xa5\x6f\xb0\xbc\x73\x15\x1c\x0c\x53\xca\x7e\x63\xf3\xdf\xde\xb6\x73\x99\xfc\x8d\x43\xb0\x5e\xfa\x99\x54\x7b\xb4\x9d\xdf\x0a\x1d\x70\x30\xba\x74\x93\x2d\xdb\xf6\xb6\xf8\x33\xe8\x12\xb3\x8f\x9a\xce\xde\x12\x6b\xeb\x6c\xa9\x2c\xef\x64\xd1\xa5\xb2\x9f\x60\x7b\x98\x53\xf6\x23\xba\xc2\x0e\xdd\x59\xbd\x6c\xe7\xce\xea\x65\xfa\x9f\x4d\x65\x3d\x36\x36\x95\x47\x97\x60\x0e\x4c\xf8\xb1\x0c\x9d\x45\xdf\xfe\xc4\x96\xed\x5c\x56\xbd\x73\xe7\xb2\x6a\x00\xd1\x62\x64\x05\x4e\xdf\xbb\x42\x2c\x00\x2d\x2e\x3e\xd7\xbf\xff\x42\x8b\x2b\x56\x86\xf7\xbc\x2f\x31\x21\x35\x25\xc9\x35\xc4\x6a\x45\x56\xb8\x7d\xc2\x03\x61\xb5\xad\x2b\xcb\xc7\x8b\xb8\x6f\x31\x87\x61\x31\x57\x2a\xd8\x1d\xda\x9d\x8b\x95\x25\xc6\x16\xed\x48\x0b\x7b\xe8\xb8\x2d\x73\xcd\xfc\x62\xdb\x97\x6c\xe1\xaa\xc4\x29\xd3\x12\x06\x74\xeb\x34\x65\x26\x3e\x03\xf0\x5e\x43\x56\x70\xd3\xb7\x1f\xb4\x11\xb4\x8d\x75\xc5\xd8\xa2\xc3\x21\xef\x70\xe7\x7a\xd2\x9c\xa9\xae\x18\x9b\x47\xf8\x8c\xf0\x5f\x3a\x43\xa7\xf7\x5a\xcc\xe7\x93\xb2\x5e\x19\x1b\x93\xbe\x7e\xda\xdd\xf0\x81\x69\x77\xf5\x8a\xed\x94\x3c\x2d\xe5\x9e\xe8\x55\x51\xe5\xf1\xa5\xd3\x93\x56\xb5\x2e\xee\x32\xad\x7d\xb1\xab\xeb\x20\xcf\xfe\x1e\xf3\xbb\xc6\x16\x7e\x59\x34\xe4\xbb\x4c\xc0\xf8\x96\x79\xf7\x30\xab\xd8\xa3\x80\x07\x16\xf1\x8e\xd9\x01\xed\xb8\x73\xae\xea\x88\x4a\xb3\x6b\xb6\xd8\xe9\x2c\xc1\x62\x2e\xa2\x10\x9c\xbf\x1e\x9d\x8f\x45\xce\x7d\xae\xe5\x73\x66\xad\x79\xfa\xc1\x39\xcb\x6b\xb3\xb3\x3b\x7a\x3c\x1d\x3b\xe6\x8e\x85\x43\xda\xb1\x34\x9b\xdb\x95\x3d\x7a\xbb\x08\x8e\x46\xbb\xd0\xc6\x07\x96\x3c\x3e\x6d\xc6\xb2\x25\x33\x33\xbb\x76\xcd\xcc\x74\xb9\xe8\xe7\x61\xe5\xb2\xad\xeb\x67\x00\x06\x54\x78\xf7\xe0\x3e\x9a\x51\x20\x11\x74\x04\x79\xda\x33\x6c\xe9\x40\xc7\x14\x8e\xc9\x51\xf6\xb5\xcb\xe2\xf1\xf5\xe3\x06\x68\xb1\x84\xf3\xec\x3b\x3b\xd7\xfe\xf9\x73\xef\xe7\x3a\x88\xd4\x27\xea\x43\x6d\x06\xb8\x01\x60\xae\xf0\x93\x41\x5b\x5c\xef\xde\x51\xea\x3d\xab\x94\xbc\x33\x76\x5a\x93\xdf\x9b\x01\x55\xa0\xdd\xd0\x0d\xf7\x5e\xfd\x69\xf7\xe6\x49\x0b\xd0\xa7\xe8\xc6\x8b\x87\xe6\x2f\x7b\xf3\xcf\xae\x67\x17\x2e\xdc\xbb\xa9\x87\x74\xe0\xc7\xd6\xbd\xb8\x73\xe3\xf1\xe4\xb0\x76\x35\xb3\xae\xde\x82\x60\xde\x94\x9d\x37\xc7\xdf\xb7\x12\x22\xe9\xd4\x8f\x06\xa9\x52\x0e\xa7\x15\xd8\x05\x0b\xa1\xbb\x89\xe7\x1c\x86\xdb\x77\xa8\x3a\x66\xd4\x5c\xc4\x4b\xd9\x9a\xfe\xdb\x77\x38\x57\x02\xe1\xbf\x86\x17\xd3\x34\xfd\x97\xef\xf4\x38\xe5\xf8\x51\xe0\x02\x95\x32\x57\xf0\x5e\x56\x88\x3f\x49\x5c\xf8\xc7\xb6\xe8\x68\xd1\x71\xf1\xef\x71\xf7\xf6\x1f\x56\x3e\x7a\x53\xb1\x8a\x13\x0d\x17\xe8\x4c\x59\x45\xcf\x1e\xc3\x27\x50\xfb\x25\x4e\x04\x2e\x50\xa9\xc4\x45\x92\x39\x17\x2a\x08\xe6\x49\x09\x12\x17\x19\x12\x8a\x99\x84\x8c\x04\x91\x0a\x19\x06\xdd\x53\xc9\x47\x10\x78\xd8\x21\xf1\x60\x11\x3b\x14\xe8\x79\x80\xd8\x39\x07\x24\x00\x8d\xce\xa4\x66\x64\xa2\x8d\xa6\xf2\xef\xa8\xaf\xa7\xc6\xaa\x65\xdf\x21\xc9\x1e\x0b\x52\x4d\x64\xa7\x85\x61\x83\x0a\xfd\x22\x1e\xf8\x33\x73\x91\x85\x91\xaf\x29\xe2\x02\x1a\x2c\x42\x56\xd6\xc3\x57\x81\x38\x5c\x8d\x2a\xf5\x7d\x8f\x51\x1a\xbf\xe3\xfe\x7d\x91\x9c\x23\x05\x58\xa4\xa2\x1b\x8f\x8b\x97\x2a\x6e\x94\xa7\x1f\x17\x7d\x06\x47\x7f\x53\xfd\xfe\xec\x3f\x4d\x7f\xaa\xe8\x89\xfa\xc7\x56\x6e\x5c\xf7\xde\x47\xa7\x10\xfa\xee\xc7\x82\x5e\x93\x7b\x0d\x1b\xf7\x96\xb3\x66\x77\x6d\x59\x21\x5c\x34\x6c\x35\x1c\xd6\xf9\x1f\x65\x54\x3a\xe4\xe0\x5b\x57\x33\x7b\xdc\xee\x9e\xb6\x13\x7d\x70\xe8\xa5\x9d\x43\x50\xe3\x10\x98\xe1\x3d\x6a\x2b\x4d\xc9\x6c\xb1\xa5\x38\x67\xc9\xbc\x47\x6d\x61\x20\xae\xfc\x7c\x64\xde\xf1\x5e\x62\x6f\x8a\x0a\x64\x65\x32\x38\xbb\x82\xb3\xab\xbf\x3f\xbd\xd4\x18\x41\x2e\xd5\x34\xc7\x59\xf1\x2c\x0c\x7f\xb5\x6e\xdd\xe8\xdc\xa9\x85\xf7\xac\x1c\x72\xdf\x88\xc1\x8f\xf7\xdb\x74\xf8\xd4\xf9\x4a\x2d\xcc\xfe\x12\x4c\xb8\xfc\xef\xf0\xbe\x77\x8a\xaf\xda\x52\x1e\xfb\xfa\xb1\x71\xe3\xb3\x1c\x37\x87\x9d\x47\x11\x6a\x88\xdc\x7e\x19\x22\x8d\xfb\xdc\x66\xf0\x93\x41\x0b\x60\xc1\x7d\xfa\xa1\x5d\x7a\x3b\x99\x96\x1a\x15\x1b\xac\xc7\xd3\x30\x1c\x3a\x3f\x40\x35\x8d\xa3\xa7\x6f\xf8\xe7\x23\x6b\x57\x54\x4d\x53\xec\x06\xfa\x06\xfd\x86\x7e\x40\x13\xff\x01\xc1\x26\xe8\x7c\x77\xcb\x0e\xc5\x68\x88\x5c\xa8\xde\xcb\xe9\x6c\xc8\x9a\x21\x26\xca\xa8\xc6\x0e\xe1\x99\x9b\x42\x09\x49\xa0\xe7\x6e\xe8\xf1\x8a\x1d\x73\xa3\x52\x36\x03\xc7\xd2\x56\x9d\xec\x5a\x9b\x21\xd2\xa0\x91\x7d\xbb\xb4\x4a\x8b\x24\x0e\x54\xb2\xfb\xad\x84\xc8\x81\xac\x07\xa5\x92\xec\xf6\x00\xb2\x6b\x2c\x45\x08\x4f\xfc\xfc\x28\x9b\xac\x40\x2f\xfd\xa0\x56\xb2\xbd\x50\x52\x85\x04\xd9\x77\x48\xb2\xb7\x01\x36\xb5\xec\xb2\x9d\x20\x08\x8d\xde\xc4\xcb\xf4\x71\x82\xcc\xd8\x32\x68\xe5\xdd\x21\xc9\xdb\x4e\xbc\x2f\x21\xcb\x8b\xad\x43\x08\x82\x76\xc3\x23\x3f\x1d\x48\x4c\xef\xd7\x82\x8d\xf0\x67\x43\x09\x32\x76\x97\x64\xb4\x48\x3d\x61\xe5\xf9\xed\x05\xc5\x95\xe5\x30\x99\xde\xaf\xe3\x46\x58\x60\x3b\x7b\x75\xbf\x43\x4b\x09\xc2\x96\xb9\x8e\xe7\x5b\x7b\xbd\x3c\x84\x3a\x29\x4b\x2c\xc8\xdb\x5d\x92\x37\x59\xec\xcf\x45\x96\xd7\x3f\x70\x28\x52\xaf\x54\x60\xec\x09\x28\xf9\x06\x09\x10\x3d\x52\x95\x0c\x26\xc8\x3f\x45\x92\x3f\x56\xd8\xd3\xaa\xe6\x58\x80\x91\x08\x85\xb8\xcf\xc9\xf1\x0e\xb3\xe9\x2e\x2d\x38\xd4\x15\x96\xc6\x4c\xed\xf2\x61\xc1\xc4\x69\x8b\x2f\xc0\x52\x02\x17\x8f\xe5\x1f\x2a\xcc\x7d\xbd\x38\xce\x5d\x55\x3e\x9c\xda\xec\xe7\xa3\x2b\x9a\x82\xf9\x08\x07\xa9\xa0\x0b\xae\xf4\x50\x8f\x18\xca\xd2\xef\xaa\x1d\x3d\x2d\xf8\xf2\xd7\x80\xa1\xdb\x07\x78\xf2\x0a\xdb\x3d\x66\x6b\x58\x25\x68\x05\xda\x4a\x7d\x88\x95\xbe\xf6\x78\x05\xb8\xed\x42\x58\xdc\x59\x60\x84\xee\x92\x8b\x40\x5f\x78\xc9\x83\x3b\xda\xe7\xa2\x19\x4e\x6a\x95\xd3\xfb\x39\xb4\x74\x1a\x7f\xa0\xe8\x49\xb6\x4e\x6e\x66\xcf\x65\x1c\x3b\x46\x25\x59\xe7\xbe\x10\xd7\x73\x33\x8e\x4d\x04\x7b\x57\xc8\xb7\x06\xb1\xa0\x3d\x48\x95\x56\xbd\xe1\x4e\x1f\x1b\x7f\xbf\x73\x16\x42\x49\x79\x6c\xe3\x8d\xfe\xbe\x2f\xff\xf6\x03\xcc\xc1\xe3\x6f\x14\x2f\xf3\x9d\x12\x0c\xfd\xa5\xfe\x95\xb2\x6f\x98\x56\xc7\x8e\x79\xf7\x8f\xbf\x7b\xec\x76\x1a\x49\xa8\x44\xb9\xdf\x91\xe4\x8e\x23\xc9\xed\x91\x9c\x8e\x89\xe0\x69\xa8\x7b\xfe\xe3\xd9\xb0\x5b\xc6\xc7\xf3\xb4\x92\xc3\x96\xb6\x5e\x4f\x17\x47\x75\xda\x3a\x4c\x91\x7d\x81\x22\x7b\x56\xe8\xb2\xcb\xe3\x07\x10\x3e\xcd\xfb\xac\x28\xfc\x33\x32\x94\x80\xd2\x53\x3f\x2a\xc8\x28\xdf\x7f\xd1\x14\x66\x2b\x3e\x47\x6d\x87\xb3\xe4\x35\x5a\xa9\x22\xa3\xb5\x56\xfb\xfa\x18\xd9\x50\x2b\x1b\xdc\xec\x27\x43\xb4\x7f\x1d\xd1\x14\x9c\xcb\x11\x2e\x65\x73\x18\xf4\xdf\x84\x0c\x99\x88\x8e\xda\xf1\xb3\xc9\x6c\x48\x19\x1d\x5a\xc5\x77\x1b\xb8\x90\x53\x3a\x00\x05\x78\x34\x0a\xcb\x1f\x8d\x4f\x18\xa3\x5c\x5d\x12\x29\x9c\x93\x4f\x39\x52\x3a\x53\xf8\x98\x5a\x45\x02\xdf\xfd\xab\x9c\x21\x85\xdd\x92\x52\xb2\x63\xf6\x15\x5e\xca\x19\xd4\xbb\xbb\x3d\x29\x27\x7c\xa9\x91\x8b\x51\xd0\x6d\x77\x26\xbb\x3c\xe8\xb4\xdd\x69\xcf\x73\xc1\x97\x54\x74\xd0\x20\x1e\x8d\xc2\x5c\x44\x83\xce\xb8\x87\x28\x69\xd4\xa0\x84\xc4\x13\xb1\x3c\x18\x98\x17\x1d\x2e\xba\xaf\x39\x35\xd8\x5e\x5a\x99\xad\x7c\x35\x68\x05\x12\xa4\x58\xde\xbf\x36\x8c\xd1\x59\x57\x8f\x4b\xc4\xe9\xa2\xec\x29\x69\xc6\xe5\xe2\x2d\xd7\xc6\x67\x6d\xb9\xfd\x03\x47\x0c\x9d\x18\xf9\x8e\x07\xed\xdf\xfc\x8a\x9f\x20\x54\xaf\x8e\xcd\x5a\x44\xa4\xb5\xef\xd3\x23\x77\x00\xda\xbf\x4e\x5c\x47\xc8\xca\x4c\xe4\x32\x40\x2c\xe8\x08\xf2\xc5\xae\xde\x26\x4c\x19\x03\x48\x8b\x16\xa2\xc5\x3c\x53\x48\x20\x6d\x99\x06\xee\x9b\x1a\xb4\x31\xe4\xcc\xa1\x2b\x65\xdf\x20\x56\x8d\x9e\x7f\x57\x41\xef\x6d\xaf\xe8\x9c\x60\x73\x36\xe1\x18\xd3\xaa\x66\x15\x6a\xe2\x4a\xba\x73\x2e\x62\x86\xc1\x0b\x79\xc8\xb9\x10\xb6\xf1\x87\x94\x68\xb9\xd7\xfb\x2e\x57\xe7\x8f\x23\x29\x31\xc7\x99\x5f\x0d\x12\x71\xd6\x89\xf9\x45\xb4\xfc\x02\xbf\x38\x86\x79\x86\xf3\x79\x9c\xd1\x4c\x03\x69\x50\x63\x6a\x73\x63\x38\xaa\x89\x0b\x3b\xa8\xc2\x80\xdf\x9c\x9a\xc9\x21\x90\x80\xd7\x51\x44\x54\x07\x7b\x17\xed\xe6\xc3\x62\x17\x1f\x6a\x49\xc6\x7d\x95\x16\xd5\xc3\xc7\x21\xfd\xe5\x7b\x55\x25\x1b\xee\xdd\xfc\xcb\xca\xb5\x1b\x07\x57\x16\xa2\xdf\xf2\x28\xd7\xce\x27\xaf\x3e\x86\xbc\xe8\x3b\x78\x59\x88\x70\xa8\x54\xd8\x12\x1e\xb8\x36\xf1\xce\x5d\xd9\xbb\xd1\x99\xd7\xf7\xed\x88\x85\x19\x90\xf2\x72\x9d\xed\x30\x8d\x8d\xab\xaf\x17\xf5\x34\x1e\x59\x99\x6d\xec\x3e\x90\x08\x52\x04\xdb\x62\x9a\x59\x2d\xa5\x52\xab\x77\x60\x01\xd2\xa9\xff\x2b\xa7\x4f\xdf\x2d\x20\xf1\x1e\x34\x4f\xa2\xbe\xb3\xfc\xda\x95\xa4\x74\xae\xba\xbe\xbe\xb1\xce\x9f\x3e\x8d\xe7\x99\xdd\xc5\x4f\x06\xad\x40\x8c\xf2\xc2\x02\x3e\xc5\xd1\xce\xb4\xfc\xa8\x02\x3a\x8d\x3e\x7d\x12\xa5\x3f\x09\x5f\x52\x66\xdb\x7b\x82\xea\x79\xbb\x84\x5a\xe0\x5d\xe9\x9f\x71\x4a\xd8\x5b\x32\x33\xf9\xc9\x20\x0e\x67\x14\xeb\x3a\xfb\xfb\xf3\x99\xf5\xa7\x0c\xfe\x06\xff\x52\x19\xca\xc6\x8c\x09\x70\xa6\x72\xbe\xa0\x34\xf9\xf7\xfa\x93\x89\x35\x7a\x86\xf7\x07\xbb\xf0\x5d\xb7\x4e\x1e\x4b\x40\x79\x9c\x52\x50\xae\x16\x47\xde\x14\x48\x75\x0c\xa5\xcc\x4c\xce\x1a\x44\x9e\x56\xa1\xc8\x23\x8f\x45\x16\x47\x19\x95\x96\xe6\xa6\x0c\xe7\x0f\x24\x11\xa4\xd1\x3d\x3d\x4d\x10\xeb\x8e\xf6\xbd\x69\xcd\x64\x1d\xd6\xbc\x32\x2f\xe8\xa8\x30\x67\xab\xf9\x72\xe9\xad\xfd\x00\xb3\x46\x1a\xdd\x54\xdc\xbd\x5a\x0c\x26\x93\x78\x44\x83\x86\xf2\x7d\x80\xac\x78\x1e\x71\x0e\x13\x6d\x34\x93\x2a\x2e\x7a\x68\x8c\xe0\x5c\x23\x0b\x5a\x6b\x0d\x3f\x57\xd3\x20\xbd\xdb\x84\xe7\x36\x12\x64\x98\x8c\x65\xc2\x43\x91\x66\xe4\x69\x66\x0c\xe8\xc7\x27\x53\x20\xeb\xef\x00\x49\x7f\xdb\x69\x67\x9c\x37\xf8\x2e\xbd\x98\xcf\xe8\x9c\x95\x5f\xc8\x97\xd5\xfe\x49\xd0\xe5\x01\x92\x2e\xdf\x15\x68\x96\x75\x23\x9a\x4e\xf0\x27\x9a\x71\xc9\xc2\xa9\x10\x50\xbe\xfe\x68\x14\xbd\x44\x8e\x67\x68\x52\x64\xa1\xca\x52\x39\x42\x8c\x21\xba\x74\x78\xfb\xd4\xa6\x54\x6a\x79\xea\xbb\xa7\xb6\xa6\x1a\x43\x99\x03\xa5\xf4\xc1\xd2\x03\x07\x4a\x1b\x87\x96\x1e\x10\xef\x5f\x6e\xa2\x51\x38\xaf\x32\x5a\x5c\xc1\x90\x30\x6a\x3c\xb4\xab\xd7\x2f\xba\x49\x1c\xf9\xd1\x9f\x61\xe6\xcf\x11\x92\x45\x32\x8e\xcc\x54\xde\xd9\xe9\x4f\xb6\x64\x70\x8f\xe1\x5f\x70\xec\x1e\x2d\xfa\x3e\x87\x4a\x36\xff\x2d\x90\x45\x3e\x37\xb2\xf9\x01\x74\xd7\xc8\xf8\x37\xf1\x4a\xe8\xd4\xc8\xb9\xb0\x5f\xd6\xe1\x09\x14\xbe\x11\x2a\x9e\xa7\x96\x94\x5b\x22\xde\x3e\xc5\xda\x2a\x0f\x45\x75\x7d\xbe\xff\xa1\xe2\xc1\xb9\xf8\x7a\x08\x30\xc2\xda\xa6\x47\xf3\xad\x71\x5f\x8d\x18\x81\x77\x97\xc5\xde\x2a\xf0\xf8\xa9\x82\xa4\xa7\xc8\xc3\x62\x31\xb3\xcc\x86\x53\xfc\x4a\x15\x68\x0d\xa2\x45\x3d\xf6\x88\xaf\xac\xf1\xb4\x72\x44\x86\x55\x78\xcb\x56\xf8\x3c\x9c\xe6\xdd\x0f\x1d\x68\x7f\x7d\xf5\x4c\x38\x4d\x3a\x11\x63\xeb\xbc\xbd\xce\xc1\x5f\xbc\x45\x5e\x8e\x1a\xde\xdf\x7b\x93\xcb\x90\xcf\xbf\x44\xdf\x72\x9d\xdf\xaa\xec\x02\xa5\x8a\x1f\xdd\xe7\xf5\xd5\x3e\x30\x01\x1d\x78\xf3\xa1\x12\x58\x29\x8d\xa0\x2a\xf6\xf1\x6e\xc1\x35\x3e\xdc\x48\xff\x18\xb2\x1f\x69\x2d\x9d\xb4\xf8\xf1\xeb\x1d\x89\x4e\x82\x68\xbf\x27\xd1\x08\xa0\xd8\x75\xd1\x97\x5c\xe7\xac\xf8\xfc\x5b\x8f\xdf\xe0\x41\x8c\x12\xd8\x14\xff\xa1\x17\x40\x35\x86\x1b\xed\x90\xf0\x47\x68\xf1\xb7\x12\x62\x0b\x12\xf0\x0d\x42\x08\x61\x40\xbd\x03\x07\x30\x14\x3e\x37\x16\x31\x5b\x08\x98\x3d\x76\x33\xba\x5f\x12\xbe\x4a\x40\x2a\x7f\xd7\x8d\x4a\xe9\xad\x62\xde\x94\xfc\xe2\x91\x3e\xf2\xf0\x01\x21\x32\xaf\x51\x78\xbd\x53\xe2\x03\x6a\xdf\xec\xbb\x8c\x4a\x71\x5d\x96\xff\xfd\x11\xe9\x38\x0e\xda\x61\x92\x7c\xe8\x87\xeb\xb2\xea\xe4\xbf\x07\xf7\x73\xd6\xff\x89\x67\x6a\xa5\xf4\x56\x3e\x0e\xb0\x4a\xa4\x0b\xa5\x5d\x35\x11\xc5\x3c\x1c\x67\xed\xd7\x60\xe1\xfa\xd7\xd7\xdf\x5a\xae\xe0\xa1\x05\x3c\xf4\x2c\x7e\x38\xc6\x13\x65\x40\x44\x7b\xec\xbc\x0e\xd5\x23\xf8\xa4\x4c\x03\x4d\x88\xd4\x44\x7e\x76\x48\xfc\xb4\x50\xa3\xf3\x43\x6a\xfc\x4d\x9c\x37\xcc\x8a\xc0\x2a\xe5\x1b\x80\x76\x60\x3e\x68\xc0\x03\x20\x0c\xd7\x02\xda\xe1\x5b\x78\x8c\x2a\x89\x86\x1d\xf5\xf5\x70\x2c\xa6\x00\x50\xbe\x9b\x68\x0a\x2d\xee\xaf\xad\xa4\xfd\x35\xb4\xd3\x2d\xb5\x3b\xdb\x02\x65\x74\xc3\x8e\x5a\x80\x01\x00\x85\xbe\x42\x53\x30\x06\xcc\x80\xee\xec\x4a\x80\x83\xbe\xd2\x1d\x54\x0d\x90\x90\x69\x3f\x28\x42\x94\xde\x6d\xb4\xf2\xf3\xf1\x3b\x43\x02\x0f\x16\xcc\x85\x25\xd7\xe2\x80\x76\xda\xc1\xb5\x82\x1a\xb3\xb2\xa1\x4f\x0b\x2a\x15\xbe\x84\x4e\xa3\x1f\xd6\x76\x18\xd8\xc2\xfb\x11\xfa\xbe\x67\x58\x4c\xde\x6a\xea\x5e\xc5\xbc\xdc\x79\x9b\xe9\x77\xbb\x84\x3a\xf4\x32\x8c\xb8\xb3\x9e\x99\x59\x87\x7e\xf1\x96\x73\x99\xaa\x7b\x00\x6c\x67\xb8\xcf\x39\x3b\x48\x03\x59\xc4\x6a\x3d\x3b\xa1\x40\xcf\x6f\x7e\x74\x95\x7a\xcb\x50\xbd\xbe\x3c\x8f\x92\x4d\x91\xaa\x4e\xcf\x4b\x28\xcf\x63\x2e\xa8\xec\x12\xe6\x61\xb2\x72\xf2\x6f\xe4\x41\xab\xb7\xa6\x4c\x8c\x53\x02\x78\x22\x13\xfe\xa0\x5a\xe6\xc1\x0a\xd2\x40\x4e\xe8\x3c\xa8\xfd\x48\x70\x26\x2a\x94\xc2\x85\x80\x4c\xa8\xca\x18\x44\xdb\xc1\x5b\x71\x7e\xaa\x09\x17\x96\xd0\xb8\xb8\xe4\x5f\xce\x04\x2a\x54\xa6\x46\xb4\xdd\xb8\x7e\xb3\x29\x5c\x58\x9a\xc4\x05\x92\xd0\x04\xa1\x42\x6d\xeb\x01\xe0\x04\x9d\x88\x00\xf1\xa2\x8d\x90\xde\x55\x84\x0e\x5e\x3b\x13\x02\x09\xf7\xc3\x91\x61\x0e\xfb\x7a\x18\x85\x4e\xa3\xbd\x68\x6b\xcb\xb0\xf8\xa4\xb5\xb0\xc1\xaf\x0c\xa7\xbf\xde\x49\x1d\xba\x5d\xc2\x94\x76\xff\x62\xad\x77\xb8\x5e\x0f\x70\xdc\x28\xc5\x0f\xaa\xec\xc9\x40\xf3\xae\xdd\xcb\x25\xa9\x26\x5a\x17\x23\xaa\x26\x17\xcf\x2d\x67\xc5\xef\xb4\x92\x64\xb2\x04\x97\xe9\x41\xff\xa4\x6a\x45\x32\xcc\x27\xae\x7b\x0d\x20\x53\xab\x20\x32\xa5\xab\x26\xcc\x6c\x33\x27\xc9\xb4\x43\x92\xc9\x6a\x94\x49\xf1\xcb\x24\x61\xf2\x25\x1b\xaf\x93\x64\x87\xe8\x23\x04\xdf\x2c\xca\xa0\x7f\xf9\x4f\x25\x83\xe0\xa2\x09\xe0\x3f\x11\xbe\x4c\x42\xbe\x43\xf6\x3f\x53\x24\xcc\x49\x24\xcc\x5a\xc3\x6e\x06\xbf\x46\x6b\xeb\x8d\x82\xa8\x8d\xbe\xc8\x55\x1c\x9a\x82\x65\x0a\x97\x5e\xb9\x57\x0f\xa3\x49\xdc\xf5\xab\x5e\x9c\x76\x94\xd6\x04\x69\x75\xde\x85\x20\xb7\x10\x2b\x2f\xf2\x35\xb0\x9b\xc2\x2a\xf1\x7b\x5a\x39\xa0\x9b\xfa\x4d\x58\xc6\xf0\x20\xac\xf8\x02\x3f\xe5\xea\xe2\x71\x71\xf2\x4e\x42\x89\xa6\x95\xd7\x62\x3f\x44\x7b\xfe\xa5\x7f\x2a\x76\x6f\xec\xa3\xf7\x64\x0d\xea\x9d\x17\x5f\x60\x5f\x92\xff\x46\xa7\xe2\x9e\xb9\xf1\x69\xae\x56\xcb\x6a\x8a\x60\x7e\xa7\xf7\x26\xa8\x1f\x92\xbd\x8a\xfa\x7c\xab\x7b\x44\x96\xbe\xe7\xc1\x87\xdb\x3b\xda\xdf\xd7\xd0\x3e\xa5\xbd\x3b\x15\x26\xc5\x3c\x3f\x31\x2a\xb3\xb6\xb7\x72\x8e\xbf\x99\x6f\x0d\xda\x00\x07\xc8\x92\x72\x62\x54\x6f\x82\x41\x02\x62\x2a\xda\xaa\xb4\x68\x53\xd0\x57\xac\x86\xe1\x6f\x7c\xf0\x6d\x0d\xba\xf9\xe6\x89\x1f\x61\x06\x11\xee\x92\x8d\x83\x1e\xea\xbb\x7a\xd0\x82\xb7\x25\xd8\x70\xcb\xe7\x70\xc8\x9b\x0d\x67\xeb\xd1\x91\xbf\xfc\x9b\x01\x6a\x90\xde\xde\xd5\x6f\x2d\xba\xb8\xe4\xe4\xc3\xd4\xaf\x32\x5a\x56\xe2\xda\x83\xb9\xee\x02\x7a\x80\xfe\x21\xb3\x8d\x4b\x3e\xa5\x83\x68\xe3\x71\x44\x30\xe6\xcb\xb2\x06\xf5\xf6\x08\xa2\x24\x54\xdf\x9d\x39\x40\x90\xa5\x6b\xab\xcc\x61\x03\x16\x15\x0f\xae\x86\x8b\xc4\x7f\x87\x38\x03\xd5\xb3\xc5\x29\x58\x84\xb3\xfd\x26\x29\x39\x7f\x2c\x9e\x87\x69\xdc\x55\xd0\x06\x74\x00\xd9\xa0\x1b\x28\x0a\x30\x13\x2a\x69\xac\xfe\xc4\x0b\xd2\x41\x8b\x61\x56\x48\xa2\xc8\xd3\x32\x68\xa4\x56\x26\xe2\xf4\x48\x12\x34\x9e\x10\xa7\xa7\x81\xe9\xae\x16\x45\xbb\x1e\x92\x70\x85\x40\xa0\x19\x52\xdf\xc4\x05\x9c\x85\xdd\x9a\x3b\xb9\x60\x6c\xdf\xab\xbe\xa8\x13\x75\x7c\x24\xd6\xf1\x48\x90\x20\xf6\x8a\xd7\x30\xeb\xb1\xf3\x40\xa3\xd3\xf2\xfd\x9c\x86\x3d\x07\x86\x20\x93\xd5\x42\xbe\x97\xd3\x90\x44\x1d\x3b\xe6\xed\x25\x69\x2e\xfd\x9b\x72\x55\x68\xe0\x25\x3d\x14\x5e\x3c\xa1\x18\x86\x3d\xda\x3b\xbb\x10\x98\x51\x5f\xe4\x89\xdc\x4c\x53\xb8\x71\x92\xb8\x81\x6a\x25\xf3\xdf\xdf\x19\xc8\x49\xf3\x3e\x26\x6b\xd2\xdb\xca\xc5\x9d\x9e\x9e\xc6\xe3\x92\xe2\xd0\x9f\xa8\xee\x13\xc5\x7b\xcb\x06\xbe\x0a\xbf\x9b\xd0\x5e\xc9\x6e\x02\xca\x3b\xeb\x69\x19\xd0\xa2\x8e\xda\x37\xdd\xb8\x85\x5e\x45\x5f\x6c\x9d\xb9\xab\xfa\x99\x17\xc7\x8f\x5f\x43\x29\xc1\xfa\x17\x7f\xff\x05\xfd\x2c\xbe\xb4\x3e\xe6\x5e\x58\xa5\x44\xe9\x62\x6f\x9f\xa5\x9c\x1d\xe7\xb5\x75\xd4\x76\x92\xe0\x88\x0f\xae\x2b\x23\xfa\xdb\x48\x48\x2d\xd4\x34\xbd\x23\x0e\x4a\x63\xcb\x3d\x24\xc4\xa6\x69\xda\xce\x11\x54\xbd\x26\x27\x87\x69\xe0\x27\x63\x59\x13\x4d\x64\xd5\x06\x2d\x7a\x69\x3b\x2a\x31\x98\x56\x5a\x25\x87\x4f\xec\x99\xe1\xcf\xe1\x0b\x41\x56\xff\x88\x81\xa5\xfd\x48\x3e\xcf\x0a\x20\x2d\x5d\xa9\xce\x0b\x12\xe4\xdd\xc7\x4f\x56\x4e\x93\xe4\xcc\x35\x21\xf2\x36\x15\x79\xca\xcf\xd7\x76\x6f\x85\x2c\x3a\x74\x76\xc1\x82\x7d\x43\x97\xae\x1b\x3b\xb9\xc4\x9f\xc0\xf8\xc9\xc9\x6d\x57\x3c\xde\xf5\xf8\x79\xf9\xcc\x07\xe7\x97\x96\xaa\x12\x91\x70\xec\x49\xef\x55\xce\x4c\x74\xad\x39\x74\x01\xb6\xaa\x2f\xc7\xf4\x67\x54\xf1\xa6\xd4\x93\xa3\xb5\x3f\xd0\xc4\xfb\x7f\x66\x1f\x5b\x87\xdf\xa2\x34\xca\xa1\xcf\x43\x94\xd2\x2d\xd4\x72\x58\xa4\xe8\x6f\xb3\x28\x8f\x46\x0e\x39\xfc\x63\x2e\x0a\xf2\xc8\x67\x15\xb8\xcf\x48\x4b\x7c\x97\xed\xff\xbe\x52\x00\x26\x89\xa4\x9c\x10\xe8\xe4\xf1\x9f\x12\xa8\x25\xf2\xe7\x55\xee\xe3\x10\x96\xa5\xbd\x94\xdd\x67\x22\x8d\x72\x7f\x1f\x40\xa2\xa1\xf8\xac\xe3\x5f\x01\xe4\xe2\x2f\xd4\xd7\x7b\x29\x49\x36\xf1\xdc\xe3\x13\x76\x1f\x96\x2d\x31\x90\x74\x38\x1a\x35\x93\x30\x51\x7b\x18\xa2\x16\x93\xb9\x50\x5f\x2f\xe6\x41\x49\x73\x16\x29\x9d\xa0\xf9\xa5\x6c\x05\x03\x89\xf6\x0c\xfe\xf6\x59\x92\x48\x3b\xea\xeb\x99\xa7\x25\x51\x00\xe5\x1b\x88\x76\xe0\x79\xa2\x71\x56\xbb\xf0\x4d\x9d\xce\x89\x79\x55\x73\xf5\xd3\x83\x0f\x56\x34\x53\x43\x81\x74\x5f\x03\x53\xc6\x4f\x16\x33\xe8\x3c\xd2\xd3\xe1\x9d\x21\x2e\x7a\xf2\x5f\x80\xca\x55\x4f\x8c\x23\x45\xb5\xe1\x48\x3f\xfe\xe7\x39\x8f\xc6\x77\x99\xf8\xd4\x9c\x47\xae\x3e\x7b\xe1\xd0\xcc\xad\x4f\xdc\x3d\xbd\xb0\x6a\xe1\x43\xe8\x1f\xde\x4b\x50\x56\xee\xfe\x30\xea\x81\x7b\x4a\x32\xfa\xe4\x95\x4c\x7c\x7f\xce\x92\xd3\x73\x27\xfe\x58\x52\x51\xd2\xf3\xbe\x41\xc3\x8f\x2f\x39\xf7\x2b\xf7\xb1\x7a\xcf\x6c\xf3\x35\xd0\xdb\x39\x2b\x48\x01\x99\x41\x3b\xd1\xe0\xbb\x7c\x3f\x14\x72\x1f\x9a\xff\x7d\x35\xe3\x05\x38\x43\x02\x62\xd6\x84\xe6\xe8\xa9\x44\xb6\x42\x82\x41\x81\x74\x54\xca\x94\xb1\xa7\x43\xe7\xc3\x12\x1a\x1f\x6e\x49\xa3\x02\xd2\x81\x2e\x2b\xfb\x66\x1b\x2a\xc5\x3d\x79\x42\xe5\xc2\x12\x0a\x17\x25\x12\x88\x00\x54\xa0\x13\xf2\xae\x90\xc6\xba\xf1\x2b\x5f\x85\xb9\xf0\x34\x59\x3b\x6c\xb2\x33\x0b\xa8\x26\x59\xc5\x7d\xba\x75\x2f\x1c\x30\xff\xd6\xd0\x55\xb0\x6f\xbf\xcf\x0b\x03\xab\xcb\x87\xfd\x06\x75\xcd\x29\x1c\x91\x64\xbb\xf7\x4b\xcb\xe0\xb7\x3b\x03\x5a\xd0\x19\x66\x20\x67\xc7\x3c\xe5\x36\x99\x29\xe5\x66\xc1\x94\xb2\x0b\x3a\x7c\x81\xb4\xa8\x4c\x87\x4e\xe6\x70\x66\x98\x07\xf7\xb0\xe9\x1e\xa2\x46\xb9\x5d\x89\xd0\x26\xd6\x52\xd8\xd3\x3c\x4a\x70\x1d\x88\xc7\x0b\xdb\xe2\x1f\x4c\x78\xf8\xe1\x3d\x7f\xbf\x1b\xdd\xec\x36\xbf\xb8\xcf\xfc\xc2\x01\xf3\x03\x52\xc9\xcf\x8a\x8b\x7d\xc4\x31\x79\x44\xdc\x87\xd3\x1e\xbf\xd3\xaf\x64\x52\xe1\x08\xd1\x77\x0a\x6b\xf0\x3a\x77\x15\x67\x02\x74\x0b\x8d\x4f\x13\xb8\xe6\x9c\x1e\x20\x80\x0d\xc4\x2b\x32\x40\xa5\xc5\x75\x2a\xd9\xad\xfc\x26\xaf\xd4\x10\x8d\x98\xbc\x68\xe1\xa8\x50\x8c\x99\xbc\x7a\xc3\xfc\x67\x45\xb4\xb8\x8e\x25\x9b\x96\xd7\x54\xfd\x0c\xc9\xc0\xc9\x8b\x1a\xda\x83\x1b\x3a\x79\x75\xf3\x51\x6a\xbb\xbb\x07\x00\xe6\x1c\x3f\x19\xf0\x20\x0a\xbf\xff\x45\xdb\x69\x7b\xbc\x6a\xec\x3d\x1e\xfa\x86\x07\xbd\x80\xd0\x59\x34\x42\x0e\x59\x0e\x41\x0a\xa1\x3b\x83\x99\x43\x14\xa5\xd8\xce\x4a\x5f\x03\x3d\x9b\x6f\x09\x62\xf1\x9b\x45\x72\xfb\x4f\x6d\xf5\xb2\xfa\xbb\x95\xfe\x5e\x9f\x55\x9c\xdc\x18\xb6\x6a\x9b\x34\x04\xbd\x10\xb7\xf3\xf4\x5e\x4d\xb4\xc9\x3d\x61\xa9\x78\xea\xb2\x2a\xee\xda\x83\x4a\x99\x73\x6c\x9d\x06\xb7\x85\x8c\x1b\x7d\x20\x1f\x84\x29\xc0\x6f\xc7\xa9\xcf\xbf\x2a\x51\x29\xee\x75\x1b\x08\xbb\x85\x0e\x86\xfd\x3e\x69\x14\x22\xf6\x3b\x23\x55\x39\x1b\xd9\x68\x07\xc6\x4e\x4b\xaf\x22\xf2\xd0\x22\xe2\xcf\xc6\xbe\xbb\x8d\x0a\xfa\x8e\xfa\x7a\xce\x22\xa3\x16\xfc\xff\xff\xa1\x1d\x18\x2b\x2d\xf6\xe8\xb4\xf3\xd0\x04\x6f\x0b\x1c\x25\x35\x12\xa1\xe2\xa0\xe2\x1f\x04\x98\x62\x8c\x71\x1c\x4d\xc1\xf8\xc2\x41\x8c\xe1\xde\x45\xa6\xba\x40\x7b\xa8\xf5\xbd\x0a\xb3\xfa\x2c\x8b\x1b\xa2\x80\xa7\x7c\x4f\xa2\x29\x18\x7b\x38\xee\xfb\xa9\xbb\xcf\x31\x11\xe3\x61\xed\x38\xff\x20\xcb\xa3\x1e\x92\x8d\x22\x0b\x46\x83\x1a\xf4\x20\xbb\x05\xd7\xf7\x26\xca\xfd\x04\x34\xef\x38\x03\xbb\xb4\x02\x75\x27\x1b\x35\x6d\x3f\x80\x39\xef\x47\xbe\xb3\x68\x4d\xf2\xfb\xb0\xcb\xa9\x7c\xf4\x2e\x42\x7f\xff\x75\x98\x36\x7f\x04\xae\x2d\x2e\xa4\x9f\x6b\x9c\x56\xe2\x3a\xb8\x79\x13\xfd\x6c\xe3\x50\x74\x13\xdd\xb8\x82\x22\x35\xf9\x23\x34\x98\x8d\x1e\x64\x0e\x32\x95\x38\xb7\xbb\xa3\x11\x83\xba\x32\x4c\x87\x42\xdb\xfe\x07\xc7\x77\x67\x9e\x5a\x97\xad\x43\xa1\xed\x00\x74\x67\xe7\xd9\x2b\x7f\x46\xc3\xb4\x39\x2c\xe0\x09\x34\x0a\xf3\x80\xdf\x75\x20\x67\x50\x12\x98\x79\x82\x98\x76\xb0\x87\xc8\x8d\x21\x59\x32\x8f\x44\x8e\x80\xa5\x37\x1a\x85\xf9\x88\x16\x76\x8e\xa1\x60\x91\x18\xea\x4d\x44\xf3\x38\x91\x23\x3d\x1a\xea\xef\x46\x92\x44\x5e\xa6\x60\x5e\xc2\xb1\x1d\xd0\x67\xd9\x92\x28\xd1\x2a\x67\x0b\x32\x17\x9a\x84\xda\x8e\x44\x22\x28\xd0\x0d\x4d\xc1\x3c\x90\xce\x95\x4d\x94\xa4\x9b\x76\x74\x37\x59\x76\x4d\x52\xfd\x87\x04\xc1\x69\x50\xe3\x6b\x60\xb7\x84\x55\x02\x2b\xf1\x95\x07\x51\x54\xd2\xe1\xac\x72\x64\x41\x5e\x20\x70\x77\xc0\x83\x64\xf2\x82\x61\x2b\xcc\xce\x8f\x69\x30\xdb\xd7\xc0\x1c\xe4\x5b\x83\x18\xd0\x09\xf7\x91\x23\xd3\x12\x10\x29\x79\x11\xc1\xf4\xc0\x48\x09\x8b\x8a\xe9\x6f\x7e\xce\x2d\xf2\xe9\xc1\xb5\x6c\x29\x58\xaf\x89\x8c\xca\x97\xf9\x21\x59\x1b\x78\xd8\x49\x3d\xed\xf4\x7e\xa8\x3a\x36\x1d\x38\xa8\xda\x84\xc3\xd1\xc7\x8e\xc1\x85\xda\xb3\x52\xcc\x1d\x77\x15\xdf\xc5\x74\x10\xeb\x07\xc8\xec\x99\xa0\x32\x21\x2e\x97\x88\x8a\xc4\x57\xb1\x1e\x13\x05\x0e\x03\xc0\xce\xe5\xc7\x81\x70\xd0\x01\x77\xdf\xb4\x45\x5b\x79\x97\x07\x37\xe0\xb4\x93\x4c\xc1\x61\xe8\x74\x51\x4c\x8b\x78\x57\x22\x3c\x00\x7b\x78\xad\xe8\x60\x31\xd1\x0a\xb0\x75\x8d\x6b\xdc\xbd\xab\x5c\x43\x37\xe4\xd3\x73\x6e\x97\x70\xe9\xda\xe5\x8f\x7d\xf0\x64\x00\x98\xd5\x5c\x38\x68\x85\x73\x6e\xfd\x9d\x3f\xed\xa4\xbc\x2f\x75\x03\x50\xef\x2e\xf4\x4e\x04\x71\x58\x7f\x2b\xd0\x3b\x3b\x99\xf3\x84\x31\x0f\xa3\x52\x76\x2e\xb6\x2f\x71\x06\x79\x55\xe1\x85\x51\xcc\x74\xe5\xce\x50\x23\x98\xff\x16\x8f\x02\x93\x51\x29\xee\x63\x8a\xf3\x4b\x35\xf2\xf8\x3f\xac\x17\x23\x49\xb9\x20\xf4\x03\x57\x7f\xf3\x30\x00\xfc\xf7\x7c\x15\x48\xc4\x67\xb5\x76\xfc\xe2\x7d\x2f\xe8\x81\x76\x8b\xf8\x64\xbe\xf0\x75\x27\x7e\x5b\x15\xda\x95\xa3\xf5\xc3\x30\x89\x0b\xe3\xc2\xec\x23\x5a\xc1\xb9\x30\x3c\xba\x45\x98\x7b\x30\x2c\x81\x6e\xef\x42\xb4\x3b\x86\xe2\xc2\xba\xf6\x44\x47\xd1\x7e\xaa\x07\xf4\x74\x18\x76\x78\xc0\x72\xb6\xae\xf1\x9b\xae\x37\xdc\x63\xfe\x66\xa3\x5d\x8d\xb5\xeb\x1e\x7d\xe1\x5d\xba\xfd\xed\x12\xea\xdc\xdc\xca\x8a\x17\x57\x78\x73\xf8\xca\xe8\x0d\xcf\xc5\xf5\x7b\x59\x8c\xd3\xaa\x01\xe0\xea\x38\xbb\x78\x86\x64\xc1\x28\x7a\x41\x8f\xc5\x1e\x29\xbe\xf8\x6a\x57\x1e\xe0\xf7\xa3\xa9\x86\x71\x4c\xab\x16\xad\x8b\xda\x7d\x0f\x8b\x5b\xb6\x1c\x91\x76\x11\xba\xbc\xd7\x50\x1d\xd7\xb2\x75\x45\xfc\x8f\xe8\x28\x3c\x26\xe1\x60\x2a\x51\xe4\xb9\x25\x9d\xde\xeb\x49\xc5\x7a\x7f\x38\x3e\xf5\x76\x39\xfc\xcf\x9d\x9d\x54\xd8\x73\x6f\xf9\x7a\x7b\xaf\x70\xad\x65\x14\x4d\xe5\x44\xb2\x3a\xa1\x71\xf2\xb9\x72\xac\x1c\x90\x13\x7f\xc6\x59\x53\x39\x91\xd0\x04\xe1\x84\x9a\xa5\x64\x7f\x04\xe0\xc4\x9f\xfb\x41\x4b\x9c\x94\xe1\xa8\xaa\x4b\x70\x56\x08\xd6\x25\x34\x82\xf2\xf4\x59\xc3\x81\x79\xd2\x25\x12\xd3\x12\x57\x0c\x68\x0f\xd2\x70\x1d\x4d\x40\xb6\x08\x28\x83\x29\xd3\x3e\x2d\xbe\x80\xfc\xb1\x93\xd5\xe8\x64\xbd\x9a\x2c\xe6\x62\x86\xc2\x60\x4c\x13\x88\xf3\xa7\x51\x04\x66\x4c\x95\x27\x2f\x72\x65\x95\xde\x91\x0b\xca\x54\x4c\x28\x04\x51\x13\x95\x43\xef\x40\xcc\x68\x72\x69\x0e\xa3\x52\xfe\x7b\xb6\xee\xff\x0b\x2f\x70\x91\xdf\xae\x06\xe2\x45\x6d\x13\xab\x51\x29\x57\xc7\x54\xfe\xa1\xbc\x40\x7f\xa6\x46\x00\x5e\x34\x39\x1b\xbe\x55\x00\xb0\x0b\xe5\xfa\x08\x07\x14\x36\xbf\x38\xe9\xb1\x85\x6a\xd8\xf9\x54\xef\x6b\xb0\xf7\x66\x38\x03\x96\x7b\xbf\x86\xad\xd1\x1b\xfb\xd0\x3c\xf8\x8e\x34\x07\x54\x23\x75\xc4\x7b\x9b\xe2\xbc\x19\xde\x24\x2a\xc9\x7b\x59\x99\x7c\xca\xb7\x15\x00\x66\x17\x67\xf5\x7f\x1b\x77\xaf\xd6\x7e\x5b\xdd\xbb\xfa\xbf\xe8\x48\x35\xba\x05\x13\xe4\x2f\x2b\x9d\xab\xbd\xf5\xb0\x0c\xed\x55\x4d\x28\x2d\xe1\x56\x6a\x07\x0c\xc8\x75\x4b\x8e\x28\x42\xa4\x76\x9d\x19\x24\xd1\x2e\x7c\x5a\x92\x87\x51\x8f\x29\x49\x44\xbc\xc8\x36\x8a\x36\x4f\x37\xa0\x5e\x40\xdd\x5a\x3e\x02\x00\x5b\xc0\x4f\x06\x61\xb8\x43\xa1\x1d\x27\x57\x6a\x0e\x55\x8e\xc0\xbc\x25\xf0\x4f\xb0\xcc\xbb\x71\x01\x3a\xb7\xe0\x98\xbf\x64\xe5\x00\x35\xbc\x71\xa1\xf7\x1c\x95\xc5\x2c\xf7\x9f\x75\xf8\xaa\x90\x95\x59\x2b\xe7\x37\x49\x5d\xe0\x69\xbb\xf8\x12\x9e\xb0\x02\x74\xc5\x49\x35\x45\xd9\x23\x17\xe7\xb6\xdb\x05\x9d\x79\xad\xc3\xac\xd9\xe9\x90\x81\x03\xbc\xe5\xaf\xa3\x4f\x2b\xf2\xa9\xc5\xd2\x58\x3f\xb6\x19\x77\x7f\x0e\x53\xe9\xbd\x3d\xed\xa8\x6b\xe5\x3d\x54\xbb\x3b\x14\x3a\x64\xe1\x7b\x2a\xeb\xdf\x77\x02\x00\xe6\x00\x5f\x85\xeb\x7d\x71\x87\x71\x0b\xee\xf4\x04\xdd\x9a\xad\x49\xcf\x34\xba\x85\xf7\xb2\x9b\xde\x93\xde\x78\x83\x1a\xe9\xf6\xbe\xa7\xd9\x92\x9c\xa2\x7f\x86\xe0\xe3\x46\xab\x0f\x70\x19\x71\x9a\x4c\x1a\x0a\xbf\xed\x73\x83\xb3\xfb\xbf\x2f\x76\x9f\xd2\x7d\x5f\xdb\xc5\x3c\xc7\x7b\x49\xf3\x7d\xa9\x95\xf9\x8f\xcc\x85\x38\x7d\x9e\x8e\xef\x04\x2a\x65\x0e\x48\xf5\xf8\x6a\xfc\x7e\x9a\xf4\xd8\xef\x91\x16\xa1\x1f\xb5\x6a\xdd\xfb\xce\xa1\x52\xdc\x6f\xbd\x85\xa6\xe3\xba\x3a\x1b\x57\x8f\xf5\x35\xe9\x7b\x32\x4a\xed\xfa\x3d\x81\x76\x48\xf8\xda\x68\xf0\x79\xec\x7a\x52\x1b\xf7\x64\x52\x33\x32\x55\xa8\xc4\x14\x65\x8c\x69\x87\x84\xa9\x8d\x06\x93\xc7\x6e\x20\x8e\x17\xbe\xa1\x20\x51\xe7\x67\xe1\x7a\x8b\x84\x80\xb5\x43\x72\x16\x35\xa9\xc8\xe2\xaf\x62\x1e\x35\xb1\x62\x48\x04\x4a\xe3\xb3\xc1\xa7\xb8\xdb\xca\x6e\x28\xd0\xe9\xa0\x6e\x2d\x92\x8f\xda\xa0\x76\x3d\x92\x4f\x0b\xaf\x18\xea\x88\x44\x9f\x76\x10\xb4\x07\x77\xe1\xfe\x19\x21\x5a\x6f\x4d\x6f\x9e\x60\x2e\x8e\x59\x39\x7b\xd6\x9a\xa7\x1f\x9c\xf5\xd4\x26\xb9\x37\x4f\x60\x67\x77\x72\xe6\x63\x8f\x4f\x9b\xb1\x6c\xf1\x6c\xa9\x3f\x8f\x60\xaf\xc4\xf5\x7e\x10\xc4\x80\x14\x61\xa7\x16\x7c\xc5\x6b\x10\x06\x5a\xfe\x76\x03\x3a\xb2\x21\xd8\x66\x40\x25\xf7\xdc\xd8\xc6\x2d\x03\x51\x20\x59\xdf\x95\x9f\xd8\x84\xdf\x22\xb5\x51\x77\x7a\xa4\xf3\x6d\x63\x2b\x23\x75\x27\xfe\x0f\x13\xda\x76\xec\xd6\x31\x39\x69\xdc\xb4\x9a\xf9\xb1\xda\x36\x46\xfe\x4e\xfc\xd4\x6b\x2b\xb3\xb3\xd3\xba\x70\x4f\x47\x3e\x3c\x66\xa6\xd8\x57\xda\xd7\x12\x59\xe9\xe3\xfc\x6a\x10\x0d\x92\x45\xb6\xa4\xc7\x23\xc4\x77\x56\xf5\x64\xdd\xec\x99\xbb\xa2\x03\x8c\xe8\x78\xe2\xb5\x25\x33\x86\xf7\xeb\x9d\xdf\x2f\x1c\x35\x0c\x41\x6f\x4d\xed\x4f\x43\xa5\x68\x73\x2f\x83\xde\x7b\x15\x17\x6c\xde\xfe\xb7\xba\x5c\x13\x82\x74\x5f\x03\xbb\x10\xdf\x11\xe6\xf6\x4e\x08\xb7\xce\x1e\x15\x11\x6e\xe1\x13\x12\xda\x27\x31\x49\xd3\x46\x85\xb5\x8f\x8f\x6f\xff\xc0\xa8\xf8\x78\x86\x01\x51\xa0\xa0\x20\x3f\x2b\x23\x32\x0a\xe4\xe3\xff\x8b\x74\xc5\x16\xb8\x32\x72\xb2\x5d\x96\x28\x60\xef\xc2\xd8\x58\xb1\x95\x4e\x8a\x33\x32\x51\x75\x2d\x2c\xde\xe1\xa6\x9f\xec\x05\xb3\x60\x8b\xbf\xc1\x98\x54\xf4\xef\xa7\xd7\xa2\x6f\xd0\xff\xea\x97\x15\xee\x19\xb1\x68\xdd\xfa\x8d\x71\x30\x23\xef\xc5\x47\x6a\xef\x7a\x87\xde\x06\xd3\x20\xff\xd5\x07\x0d\x1d\x8f\xad\xfc\xe1\xff\x06\x41\x26\x33\x73\xe1\x8c\x91\x53\x4f\x40\xb0\xb4\xf6\x2f\x8d\x4b\x01\xed\x5b\x86\x4a\xa5\x3e\x58\x51\xa0\x1d\xb1\x0b\x16\xa9\xf1\xd5\x93\x92\xdd\x7a\xd1\xd0\xee\x4a\xce\x1a\x08\x97\xba\x5c\xc9\xbd\x48\xc4\x3e\x57\x09\x20\x23\x58\x97\xab\x60\x8d\xad\x2e\x4b\x43\x0f\x37\x6b\x67\x85\x5a\xcb\xed\x47\xfc\x5d\xac\x68\xdf\x32\x00\x98\x55\xfc\x4d\xc0\x83\xb6\x20\xc5\x2f\x27\x94\x84\xb3\x28\xbd\x16\x1d\x1e\x69\x70\xb5\xbc\x30\x5d\x16\x34\x7a\xe0\xfd\x0f\x3f\x79\xd2\x5a\x17\x3e\xb4\x4f\x72\x92\x4b\x16\x9b\x1a\x27\x8a\x4b\x97\xef\x8a\x1b\x3b\x6a\x77\x8f\x01\xeb\xc3\x3d\x9d\x62\x13\x94\xf5\xb0\x0b\xaf\x07\x57\x28\xeb\xc1\x08\x24\xf0\x8a\x38\xa7\x01\x64\xb6\x24\xe8\x6f\xb5\xc0\x00\x00\x8c\xc0\x09\x97\xc0\x9f\x03\x3c\xee\x49\x98\xa6\x9a\x7d\x9c\x55\x15\x23\x39\x58\x5a\xe2\x08\xba\xa5\xc6\x6b\x6a\x66\x50\xe1\xea\xbe\xb0\x57\x8f\xe9\x6f\x0f\x1a\x5a\xb1\x78\xbb\xcc\x12\x3c\x5f\x34\xee\x56\xdc\xf6\x01\x32\x3f\x5c\x86\xad\x60\xc5\x3d\xcb\x9f\xb5\x15\x8e\x1e\x5c\xda\xe8\x96\xc8\x6a\x13\x55\x54\xd3\x32\x71\x55\xb6\x94\xf7\xc5\x6e\xe3\x16\x63\x9e\xc4\xaa\x7d\x82\x96\x68\x61\x69\x78\x53\xc0\x19\xd9\xfa\x49\x0d\xf1\x09\x3f\x73\xd4\x02\x11\xa4\x96\x33\x26\x56\x0d\xb5\xce\xcf\xe0\x66\x05\xad\xc4\x1d\xf3\x36\x5f\x0f\x78\x10\x01\x12\xb5\xdc\xb9\xc4\x63\x05\x32\x89\x6a\xee\xba\xff\x60\xeb\xb9\xb2\xfb\xa4\xd7\x88\x14\xca\xd4\xf1\x27\xc3\xc7\xce\x8b\xc8\x5d\x80\x9e\x21\x50\x08\x94\x9c\xd9\x6d\xdc\x12\x10\x05\xe2\x41\xba\x29\x77\x64\x58\x41\x56\x5b\x4f\x02\xc4\x2d\x66\x2b\x8f\x3d\x48\x82\x5a\xa7\x6a\x26\x87\x79\x63\xdf\x0a\x2b\x91\x74\xae\x73\x50\x9d\x13\x9f\x63\xf5\xb7\x42\x0d\x41\xf7\x1a\xc2\x17\x7b\x3a\xdd\x95\xd5\x7f\xc4\x7d\x5b\xc2\x03\x2b\x60\x8b\x79\x5c\xff\xd4\xf0\x87\x22\x87\xf5\x79\xc8\xe1\x56\xb8\x64\x07\xe3\xfe\xc2\x82\x1e\x16\x34\x5d\x0f\xf5\x80\x8d\x9c\x36\xaa\x61\x6f\x54\xe9\xe3\x36\x15\xf0\x10\x95\xf2\x59\xad\x04\xa2\x5e\x5e\x0b\x9b\x20\xf1\xeb\x36\xf0\x9b\x04\x05\xd4\x0a\xbf\xb4\xd8\x9c\x5e\xac\x94\xc5\x89\x78\xe2\xbb\x05\x1a\x9a\xfb\xac\xee\x01\x7b\x75\xa8\xec\xf4\xf6\x43\xe9\xe7\x14\x9a\x6b\x2c\x0b\x47\xf4\x9a\x1b\xd9\x29\xd3\x91\x1a\xb1\xd4\xbd\x37\xb5\x4f\x6e\xcf\x74\x5b\x6a\x4a\x2b\x15\xe3\x3d\x16\x0f\x29\x7d\xb8\x87\x6d\x5c\xfa\x4a\x85\xf1\x67\x16\x3e\x94\xd3\x22\xd6\x99\xf9\x6b\x44\x7c\x42\xcb\x2c\x87\x4a\x7f\xf9\x08\x89\xf3\xfe\x81\x38\x97\xe1\x6b\x6d\xa6\x89\x10\x46\xea\x6f\xa9\x45\x59\xe7\xa7\xde\x6e\x22\x8c\x61\x16\x54\x22\xf9\x67\x81\x69\xa7\x97\x8a\xc1\x7e\xb5\x9e\xaf\xc2\x7e\xd5\x8e\x6b\x67\x09\x9e\x55\xbb\x91\x21\x99\x08\xd9\xd1\x8e\xd5\x6c\x6a\x9e\x35\x73\xbb\xbc\x66\x97\xe3\xb7\x12\x8c\xe8\x83\xb9\x64\x8c\xa6\x13\xae\x0b\x20\x71\xac\xc5\x13\xba\x53\xfe\x42\x03\xef\xd3\x60\x2e\x9a\xb1\xa9\x61\xfe\xef\x37\xa3\xc3\x56\x6c\xec\xb9\x30\x0b\xf6\xd9\xf1\xa0\x83\xd1\x6b\xd3\xb8\xc6\x1b\x27\xa0\x27\x5b\x48\xde\xc9\xef\xb7\xb7\x6c\x18\x59\xf6\x4a\xe1\xc6\x94\x73\x2f\xa0\x73\x57\x0b\xee\xbf\xa0\x72\x4e\x8a\xf3\xde\x3a\x6a\xc4\xde\x5d\xfb\x21\x63\x29\x58\xd7\x4a\x34\xf4\xb2\x6d\x3d\x8e\x75\x53\xba\x51\x0a\xe6\xc1\x49\xa0\x02\xfb\xf0\x1c\x23\x38\x33\x47\xce\xdc\xa5\x07\x29\xf2\xf4\x4f\x89\xa7\xf6\x41\x78\x52\x3c\x41\x1a\x99\xa7\x9a\x75\x32\x94\xad\x6b\x57\xd6\xb7\xcf\x9b\xf7\xa8\x09\x4d\xbb\xa0\xbb\xed\xf4\x69\x91\x55\x3a\x8e\x32\x9b\xca\x91\x1f\x50\x10\x8e\x0c\xc0\x82\x50\xa4\x00\x54\xe9\x52\xb9\xc4\x51\x56\x50\x8e\x24\xd5\x97\xc3\x30\xb3\x70\x70\x93\x82\x6a\x7b\xcd\xcd\x8e\x3d\x8a\x87\xf7\x2d\x6a\x33\xb5\x75\xae\x2b\xb3\xa3\x29\x6d\x31\xf7\x87\xf7\xcb\xcb\x1d\x14\x9e\x31\x2b\x2c\x29\x29\xc1\x6f\xff\x38\x89\xbf\xde\x4d\xe7\xcf\x00\x36\x30\x95\x59\xa6\xa0\x83\x52\xaa\x03\x2f\xf2\xfa\x3d\xf6\x37\x6d\x41\x82\xb0\x63\x26\xf3\x2a\xbd\xc2\x9c\xe6\x21\x9a\x6a\x93\x35\xbb\x7d\x7d\xe9\xd8\xf2\x07\x1c\xeb\x53\x3e\x79\x6e\xd7\xda\xa8\x98\xf9\x23\xdc\x23\xbb\xe4\xa5\x3a\x9c\xad\x97\xb8\xf7\xa4\xf7\x72\xa7\x66\x77\xe8\x15\x6d\xa0\xb9\xaa\xa0\x30\x6f\xe0\x9a\xcd\xb5\xc7\xe7\xcc\x6c\xdf\x2e\xb1\xf3\x5d\x5f\x47\xb6\xb3\x84\x0f\x26\xf8\x99\x7e\x21\xf3\x1c\x04\x7c\x60\xb2\xed\x21\x08\x61\x1a\xb5\xfb\x4c\x84\x11\xfd\xcb\x79\xbe\x5a\xda\xb7\x99\xf8\x17\x79\x0a\xb4\xcd\x30\x02\x6e\xe4\xb6\x6b\x1b\x71\x98\x6c\xeb\xe8\x0a\x7f\x4f\x0c\xd9\xb7\x64\x48\xfb\x3b\x13\xdf\x62\xe6\x4c\x74\x4d\xa3\x42\xda\xf0\xa5\x6b\x40\x06\xdd\xfe\xd1\xdf\x69\x7b\x88\xb8\x51\x29\xee\x49\x26\xf7\xd9\xf1\x77\xdd\xd2\x76\x88\xd2\xf5\xd7\xda\xaa\xdc\x04\x28\xad\xb4\xfc\xfd\x6e\x04\x0e\x0a\x99\x2a\x9c\x1f\xd6\x29\x50\xd7\x2c\x7d\x5a\xbe\x69\x7f\xac\xf7\xa4\xe1\xd6\x99\xf6\xc2\xf2\xfa\xa4\x59\x71\xcb\x3d\xc5\xc4\xde\x57\x5b\xf9\x9b\xa0\x95\x54\xc9\xa1\xc8\x46\xf1\x86\x9d\xa5\x51\xc6\x17\x4b\xd4\xbb\x49\xbf\xa0\xfc\xd0\x68\xc3\xfe\x51\xdc\xdb\x16\x72\xbb\x70\xf5\x41\xd7\x40\x1d\xf7\xfc\xdd\xf6\x8c\x9b\xdb\x80\x0d\xd5\x1e\xd6\x6e\x6e\x8d\x14\x88\xed\xd4\xa8\x9f\x75\xe8\x44\x1e\xce\xf2\xe3\xc4\xbb\x7b\xcd\x1c\x13\xee\xee\x09\xbd\x07\x1d\x26\x59\x03\x4a\x0b\x42\x43\xc2\x80\xc8\xc7\x4a\x2e\x1c\xc4\x2a\x3b\x58\x13\x1d\x20\xa5\x30\x05\x56\x86\x1f\x89\x70\x8a\x4d\x55\x83\x69\xa1\x85\xe7\x3d\x80\x55\x44\xec\xcb\xf4\x3d\x7f\x0e\xb4\x02\x71\x52\x8f\x4e\x3f\x33\x9a\x6d\x4d\xaa\x1c\xba\x10\xc8\x71\xaa\x77\x30\xf0\x57\x69\xaf\xaf\x6a\xcf\xa8\xda\xad\x9c\x90\xb7\xcd\xe2\xde\x6a\x2d\xb7\x18\xc4\xe2\xae\x04\x79\x81\x18\xd2\xee\xb0\x64\x6e\xfc\x9b\x7c\x22\x49\x97\xd4\xb0\xca\x44\x6e\xa8\x1c\x69\x93\x4f\xea\xd8\xa8\x82\x29\xb5\x6e\xdc\xe9\xdf\xe4\x4b\x3d\x3b\xf9\x7a\xfc\x86\x8d\x81\x2b\xe2\x76\x9a\x60\x35\x26\x11\x76\xd0\xaa\x85\x45\xda\xdd\x2b\xbd\x3c\xb9\x25\x78\x6d\x05\xe3\x8a\xbc\xb3\x0f\xac\x50\xed\x08\xb0\xca\x4c\xd5\x89\xfd\x33\x01\xa6\x48\x99\xa4\x53\x4b\xc3\x4a\xb0\x4e\x75\x0c\xa8\x53\xfa\xcd\x71\x30\xdd\xa2\xc2\xd4\x7b\x79\xb2\x82\x1d\xd3\x6d\xe2\x45\x3d\xcb\xe4\x6e\x49\x7a\xd6\xbb\x19\x7a\x66\xd8\xc4\x87\xae\x6f\xfd\xd5\x9b\xf8\xd0\x94\x6e\x9b\x46\x02\x51\xef\x0e\x87\x4d\xc0\x7c\xe6\x10\xf9\x94\xb7\xc1\x26\x1b\x5f\x12\xad\xea\x9d\xef\x5c\xb3\xbd\xbb\x9a\x61\xff\x56\x17\x16\x19\xf6\xb7\x58\x3f\x27\xf0\x11\x98\xe3\x5e\x60\x40\x70\x8e\x83\x40\x0e\xa2\xae\x97\x42\x81\xff\x80\xb9\x39\x6c\x15\x40\x9c\xc6\xe9\xb2\x1e\x0b\x71\x01\x5f\x85\xe3\x82\x54\xd3\xc8\x40\xb7\x4b\x0e\x10\x28\xcc\xd2\xec\x8a\x8d\x61\x03\x6f\xb8\x93\x14\x63\xa9\xfe\x9c\x1d\xc7\x11\x5d\x40\xf7\x10\x23\x09\xdd\xc6\x3d\xb4\xc0\x82\xd6\xc0\x2b\x09\x1a\x66\x70\xcb\xd5\x70\xa5\xd5\x0f\x00\x85\xfb\x84\x2d\x91\x63\x0e\x75\x8f\x30\x42\xcc\xa1\x69\x0c\x36\x58\x13\x6e\xa8\xdb\x81\x11\x02\x0e\x5c\x47\x49\xfd\xc0\xed\x02\x34\x8e\xdb\x2c\xf6\x56\xd0\x18\x4f\xe0\xc6\x5f\xb1\x9a\xb0\x01\xf7\xfb\xfa\xde\x10\xbf\x50\xbe\x93\xa8\x14\xf7\x72\x13\x73\x18\xf4\xbd\xcd\x08\x8d\xcc\xbc\x57\x25\xea\xd4\x50\xd5\x77\xb6\xb4\xef\x6b\x54\x8a\x7b\xb5\xb5\x14\x33\xf8\x34\x75\x84\x9a\x16\x6d\x76\xb9\xe0\x4b\xd3\x93\x4d\x55\x3a\xa8\xee\xc5\x46\x83\x45\xa8\x94\xdd\xc4\x9e\xc1\xf5\x91\x69\x86\x6a\x6d\xff\x67\x23\x35\x85\xdb\x84\x52\x6d\x69\x58\x7f\xc5\xb6\xb1\x44\xdb\x7b\x44\x0a\xa1\x3f\x52\x95\x6a\x4b\x31\xee\x48\xa6\x0a\x63\xe8\xa0\xaf\xcc\x26\xb4\x92\x17\x5b\x8d\xab\xca\xb2\x2f\x48\x83\x97\xc9\x75\xd9\x9a\x72\x6c\xef\x4d\x69\xd8\x62\xa9\x24\x1b\xcb\xed\x6b\x60\x37\xf1\x37\x71\x9d\x7a\xe7\xc0\x55\xea\x04\x6d\x08\x58\xaa\x0e\xe7\x6a\xd4\x24\x48\xa9\x3a\x73\xbf\x4e\x83\xc4\x78\x6f\x24\xb7\x0b\xb4\x01\x71\x9a\x98\x9f\x62\x54\xbd\xc5\xcd\x2e\x75\x34\xe5\xea\x59\x32\x21\xaf\x6b\x03\x5e\x35\x3d\x72\x87\x03\xfa\x33\x2d\x10\x5c\xcb\xcf\x4d\xe7\xcf\x61\x8e\xd2\x71\x76\x5d\xa0\x5a\x7e\x72\x94\x17\x90\xa9\x4a\x52\xbc\x17\xb4\xb4\x9f\x14\x04\x2a\xfe\x79\x3b\xb7\x18\xe3\xd5\xbe\x3d\x2e\x6a\x92\x06\xa1\xba\xbb\x87\x3f\xfe\x53\xb3\xd7\xa0\x46\xb7\x42\x62\x92\xca\x96\xe2\x3e\x6d\xc1\xbf\xda\xf9\xca\x8d\x11\xa8\xcd\xaa\x7b\x28\x51\xdf\xea\x71\x6d\x78\x07\x23\x97\xfe\x60\x2b\x00\xa9\x06\x2e\xff\x26\x06\x5b\x23\x4c\x18\x35\x32\xc9\x49\x37\x29\xb7\x1f\x31\x63\x54\xe9\x23\xc1\x2d\x91\xb0\x12\x78\x34\xb9\xf2\x31\x59\x9d\xe9\x84\x90\x70\x05\x71\xa5\xb2\x5b\x49\x17\x3d\xc7\x95\x65\x2b\xe9\x24\x17\x56\x22\xe9\x64\xb0\x3e\x34\x81\xa3\xc4\xd0\x75\x53\x13\x2f\x36\x45\x41\x75\x41\xa4\xa8\xa3\x3d\xb8\x5b\x92\x8e\x1a\xfa\xd0\x98\x53\x6a\x8c\x1d\x83\xea\xea\x20\x6a\x8d\x3a\x68\x34\xd5\x58\x7f\xaf\x8a\x25\x86\x98\x57\xec\xe7\x31\x41\xe2\xbb\x4f\x48\x7c\x07\x09\xc9\x02\xd3\x1e\x4a\x40\x16\x7c\x06\x02\x04\x99\xa2\x7e\xcf\xe5\x23\xa4\x39\x28\x30\x99\x03\xe5\x4a\x48\x65\x6f\xcd\x2e\x84\x34\x53\xa1\x96\x40\x99\x0a\x9b\xd9\x4d\x90\x6e\x56\x54\x17\x41\xf2\xac\x30\x9c\xe1\x72\x8b\x11\xfd\x36\x5f\x25\xf9\x6d\x77\xc8\x9e\x5b\x17\xd2\x85\xe2\xc8\xfb\x68\xe2\xb9\x10\xdd\x3a\x7d\x2f\x39\x06\xbd\x87\xb3\x83\x36\x38\x83\xd5\x65\xe4\xdd\xfc\x9a\xc8\xc4\xb4\xfc\x4d\x03\xed\x6f\x01\xc3\x00\x86\xd2\x5c\x0e\xfd\x57\x1f\x14\xe0\x98\x80\xe7\xf8\x2a\x10\x2d\x9d\xb5\x61\x46\x6d\xb9\x1e\xbb\x2d\x1c\xf2\x31\xd1\x26\xb1\x81\xaa\x79\x0d\xec\xf2\xd4\x9c\x64\x98\xd5\x32\xeb\xed\x5a\x0b\x31\x32\x28\x90\x9f\x60\x12\x49\x3c\x5b\xf2\x49\xec\x0b\xe7\xba\x8d\x1c\x49\xd6\x62\x7f\xae\x3d\x8e\x09\xd8\x0b\x9c\x1d\xe7\x65\x65\x28\xef\x2f\x09\x84\x89\xe0\x88\xc1\x81\xaa\x83\xcd\xc5\xaa\xa2\x91\x31\xd0\xd9\x32\xfb\xad\xbd\xe1\xfa\xe0\x60\xa7\xfc\xe2\x12\xa6\x6b\x5d\xfc\x53\x8f\xc5\x1e\x3a\xd9\xc3\x35\x54\x13\x1e\x50\xef\x6b\xde\x83\x6a\x06\x57\x16\x4d\x07\xa4\x60\x5c\x1d\x97\xaa\x23\x42\xa1\x8a\x79\x4a\x2a\x92\x68\x1e\x4f\xea\x36\x48\x81\x78\x8a\x92\x20\x05\xe4\x89\xfe\x4d\xc1\x22\x72\x74\x13\x73\x94\x1b\xb2\x3e\x11\x63\xcd\xa0\x9a\x45\x8c\x39\x03\x93\x76\x3f\x21\xa7\x88\xbd\xc0\xed\xc2\xdc\xb9\x43\xd5\x31\x62\x00\x1a\x88\x45\x52\x28\x6a\xc6\xe5\x67\x86\xd8\x58\xe4\x74\x1c\xe6\x34\x3f\x44\xbd\x23\x1c\x8b\x86\x44\x6a\x19\xf1\x70\x34\xa4\xb5\x7b\x8f\xa1\x04\x4b\xe1\x37\x1c\xd7\x10\xe6\x99\xf2\x4b\x3c\xc5\xd5\x1b\x40\x23\xc1\x5f\x10\xc1\x96\x6b\x4d\xa1\x8e\x67\x06\x68\x61\x2a\xdd\xce\xa4\x35\x8e\x4a\x79\x0e\xf7\x07\x4f\xf6\xef\x91\x0c\x5c\x07\xdc\x23\x92\x29\x36\xdb\x2b\xea\x39\x25\x6f\x18\xe5\xdc\x3f\xf6\x02\xcb\xe1\xbc\xf4\x4c\x73\x2e\x03\xf8\x10\x23\x85\x26\xdb\x48\x1d\x69\x84\xed\x24\xa0\x40\x0d\x2a\x95\xea\xbb\x93\xcc\x6a\x2e\x55\x59\xf2\xe4\x32\x4b\x4e\xee\xa8\x40\xac\xac\xf4\x22\x75\xdf\x80\xd9\xa8\x54\xaa\xe5\xb6\x07\xae\xe4\x8e\x09\x50\x42\xf9\x85\x3c\x20\xa9\x72\xbb\x87\xd2\x13\x06\xd7\x94\xf2\x37\x81\x55\xec\x9b\x46\x92\xcd\x68\x07\xc8\x32\x52\x0b\xb4\xab\x9f\x28\x29\x37\xdd\x78\x46\x23\xd6\x90\x0a\xb6\x29\xdd\xbc\x7e\xd4\x88\xc2\xa4\x74\xf4\x17\x2d\x0a\x82\xf8\x6c\x99\x11\x43\x8d\xaf\x81\x1f\xc7\x57\xc9\xbd\xf5\x34\x18\x78\xac\x7a\x1c\xc3\x2b\x84\x90\xca\x93\x9d\x83\x47\x5a\x61\x56\xcb\x1e\xe8\xda\x5f\x17\xca\x8c\x4c\x95\xbd\xaf\x96\x8b\xc3\xb1\xd5\x4b\x62\x3f\xb9\xdc\xc6\xfb\xbe\x54\x57\xeb\xef\x77\x3c\xdd\xd7\xc0\xad\xe4\xec\x20\x99\xc0\x05\xdf\x8b\x92\x70\xf8\x49\x11\x91\x4c\x4f\x50\x53\x11\xeb\x2a\xca\x10\xa0\x74\x43\xd7\x3f\xd9\xff\x6d\x74\xd8\xda\xbf\xad\xdc\x04\x7f\x92\xa1\x64\x16\xad\x55\x11\x32\xa7\x4d\xaf\xf1\xd3\x63\x4f\x7d\x13\xd1\x78\x16\x57\xd3\xaa\x6b\x00\x9b\xc4\x89\xe4\x68\x83\x72\x02\xff\x22\x7b\xda\x80\x9c\x70\xab\xfd\xb5\x91\x4d\xe4\x44\x42\x12\x02\x27\xf9\x32\x94\x40\x9c\xb0\x8b\xd4\xb5\xa2\x22\x27\x37\x41\x82\xb8\x77\x0e\xa2\x27\x81\x17\x0e\x49\x63\x02\xae\x21\x3d\x47\x84\xb5\x24\x72\xb5\x4b\xce\x1c\x0e\xaa\x3f\x7a\x84\x21\xb0\x76\x53\xb7\xc0\x02\x71\xa7\x5b\x69\x32\x7f\xe3\x40\x02\x11\x9f\x96\x3f\x82\xb3\x0c\xae\x5e\x73\x89\xbe\x32\xc8\x02\xac\xd0\xb9\x74\x99\xc7\x70\x90\x8c\xa3\xbb\x60\x3c\x12\x90\x86\x40\x24\x45\x86\x1a\x70\x81\xf6\x27\xd4\x7f\xd7\xa0\x52\x7e\x1c\x67\x05\x09\x84\xee\x23\x7a\x4e\xcd\x1c\x15\x89\x4a\x13\x9f\xa5\x23\x4f\xeb\xbb\xa6\xa3\x52\x6e\x25\xcb\x80\x64\x31\x42\x0f\xcc\x9b\xca\x89\x05\xa7\xeb\xa2\xe2\xd0\x02\xf0\xa3\x78\x36\xa0\xd4\xcb\x55\x81\x30\x10\xa9\xae\x97\x93\x0d\x84\xb6\x5a\x2e\x52\xa9\x1c\xf7\x57\xcb\xb1\x59\xd2\xd2\x97\x6b\xe5\x84\xbd\x47\x92\x79\xe5\x8c\x62\x04\xcd\x4b\x65\xe0\x17\xd2\x38\xe4\x02\x99\xab\x6a\x5b\x73\x04\x95\xb2\x05\x6c\x9d\xb6\xde\x4f\xdd\x30\x48\x2b\xc1\x5b\xfe\x97\x38\x14\x09\x1a\xb7\xa9\xde\x8d\xc0\x32\xc8\x71\x85\x89\x0c\xa9\xa1\xd5\xfb\x7d\x26\x8d\x45\x94\x62\xb7\x61\x0e\x6e\x82\x30\x10\xaf\x99\x03\x83\xe1\xd1\xca\xb2\x4f\x5b\x32\xa1\x9e\x93\x96\xfa\xbc\x0d\x69\x6e\xa4\xf8\xc1\x74\x6e\x8c\xc6\x38\x80\x7c\x0b\x35\xe3\x93\xe7\xea\x3d\xbd\x6d\x13\x65\x1d\x07\xc2\x40\xa2\x7a\xbe\x08\xc6\x41\x2b\x6c\xa1\x49\xde\x88\x5f\x68\xfa\xb6\x71\xcf\x21\xcb\x2d\xee\x39\x4c\xe5\x26\x19\xd1\x00\xea\x59\x4d\xc4\x42\x24\x80\x3b\x60\x00\x25\xde\x6f\x5c\xe0\xca\x71\x06\x42\x2f\x55\x56\x57\x2f\xe8\x71\x85\x43\x5e\x55\x9b\xe7\x94\xdf\x53\xf5\x6f\x2c\xf0\x49\xa8\x47\xea\x62\x26\x28\x61\xc5\x93\x37\x36\x8e\xaa\x76\x85\xb5\xcd\x6f\x87\x32\xc7\xb4\xeb\xcb\xf5\xec\x90\x50\x30\xf9\xa3\xcc\xb0\x11\x6b\x47\xaf\xdd\x0e\x73\xfa\x14\x0d\x99\xd7\xb7\x77\x9f\x01\x0b\x8b\x61\x5c\xd4\xdc\xa8\xce\xb9\x85\xee\xbc\x01\x2f\xc2\x25\x7f\x87\xf7\x9d\x18\x5a\x99\x54\xd9\xee\xee\x5f\x1e\x42\xef\x25\xda\xfa\xb4\xbe\x96\xf8\xe7\xb1\xfd\x3f\xbf\x34\x71\x74\x0d\x6c\x53\x36\x7c\xdc\x8a\xcb\xd4\xab\x65\xad\x06\xb5\xc8\xcb\xcc\xed\x37\xa4\xd7\xa2\xd5\x06\xec\x7d\x9a\x8e\x5d\xb1\x66\x6d\x61\xb4\x15\x3f\xf3\x1d\x3a\xfc\x73\xf7\x0d\xca\xee\x56\xda\x97\xea\xd5\x35\x6a\xca\x83\x21\xe1\xa7\xe7\x57\xce\xce\xcf\xe8\x56\xcc\x86\xf1\x09\x69\x54\x19\xa5\xaa\xeb\xb8\xc0\xb9\x25\xfe\x07\x34\x43\x0a\xed\x0c\x58\x3c\xae\x18\x1b\xef\x68\x8a\x2c\x3d\x2d\x55\x11\x99\x9e\x02\x57\xaf\x9e\xdb\x8f\x31\xff\x66\x2c\xdc\xf2\x8c\xbe\x21\x4f\x49\xff\x96\x9d\xb3\x32\x3d\x43\x7a\x4c\x5f\x0c\x07\x46\xaf\xde\x16\x5f\xfa\xb2\x51\xae\x02\x50\xdc\xfc\xd9\x69\x0b\xc5\xb9\x49\x6d\xba\x60\x65\xe5\xc5\x99\xae\x55\xc2\x1c\x4d\x9c\x03\x53\x9b\x24\x1a\x3d\xed\x9e\xf1\x39\xa9\x53\x5b\xb6\xc1\x73\x35\xe9\xb2\x24\x9a\x7e\xbe\x9a\x23\x97\x76\xbe\x3c\x6e\xf9\xf9\xe6\xd0\xe5\xaa\xf0\x4f\xd8\xbe\xa4\x5e\x11\x90\x4b\x59\x51\xd0\x8c\x09\x8b\x89\x2f\xda\xdf\x3d\xba\xdb\x9b\x85\xc6\xf9\x1a\xf8\xfb\xe7\x8b\x6d\x86\x60\x55\xea\x09\x8b\x6a\x92\x68\xba\x09\x2b\x35\xca\x76\x19\xcb\xd6\x1f\xdc\xd3\x0c\xd9\x48\x7d\xf0\x2d\xcd\x35\x7d\x9e\xc8\xc7\x2a\xb2\x4b\xfb\xf7\x88\x2f\x4c\x5e\x62\x5d\x34\x3a\x73\x68\xff\x5e\xed\x53\xbb\xb4\x4a\x8d\x98\xde\x36\x2d\xbb\x67\x76\x6e\x8f\xda\xd0\x24\xfe\xd7\xcc\x47\xdb\xdb\xe3\xcb\x1f\x5c\x18\x6f\x6f\xef\x4a\x45\x07\x87\x73\x39\x5c\x86\x23\xc3\xd3\x23\x7b\xec\x83\xc0\x28\x77\xf9\x1f\x24\xb7\xed\x77\x98\xcd\x14\xb2\xe8\xc5\xa5\x05\x1d\xb3\x3d\x85\x54\x6e\xc7\x88\xf2\xa9\xcd\x11\xfe\x40\xff\x51\xe9\xc9\x59\x5d\x5b\x32\x8c\x35\x8e\x1a\x4e\x89\x75\xde\x62\x3d\x28\xfb\x09\xe0\x41\x0c\xce\x5a\x11\xb3\xa7\x5b\xe9\x7c\x16\x24\x94\xe4\x8c\x55\x39\x27\x46\x5f\x88\xc3\x78\xd4\x9e\x08\xa5\x4b\x05\x38\xea\xf1\xe2\x84\x88\x4d\x19\xcf\x40\x18\x69\xc8\x9e\x1a\x8f\x32\xd9\x30\xa8\x4f\xe7\x3e\xbc\x47\xa5\x71\x19\x30\x13\x00\x76\x33\xfb\x09\xee\xd3\x98\x84\xcf\x85\xb4\x12\xd2\x8a\xe0\x92\x09\x95\xc7\x9f\xe9\x37\x24\xa3\x54\x50\xee\x52\x4c\x65\x7f\x19\x06\x53\xa1\xb6\x1c\x77\x76\xcb\xb0\xd8\x17\x45\xcb\xd8\xf8\x9b\x52\xac\xc8\x80\x15\x12\x9e\xb6\xc0\x06\x92\xc5\x3d\x8e\xd6\x36\x58\xcc\x00\xad\x50\x19\x80\x56\x2a\x44\x69\x0a\xa2\x22\x85\x98\x18\xcd\x82\xbf\xd3\x2b\x00\x24\x1d\x47\x22\x26\x13\x8e\x14\xb3\x65\x09\x4c\x52\x77\xd9\x3c\x7d\x19\x8c\x23\x66\x8e\x6c\x8c\xbc\xd7\x95\x39\x53\x73\x64\x17\xcf\x49\x4c\x38\x32\x00\x32\x23\x29\x5f\x46\xf4\x8f\xa0\x1c\x11\x20\x01\x06\x94\x01\xc0\x8e\xe6\x1e\x01\x3c\x48\x14\x6b\x7c\x5c\x72\x9d\x47\x08\xf6\x4f\x9e\xc2\x32\x75\x55\xe1\x47\xc1\x4d\x5d\x4f\xbd\xa6\xb3\x6b\x03\xd8\x35\x94\xa0\xd2\x33\x35\xde\x6c\x90\x17\x04\xaf\xd1\x6e\x35\x05\xb2\xd6\x44\x19\x8a\xf3\x74\xa0\xf5\xf6\xc8\xfb\x81\x5f\x17\x29\xe0\xf4\x35\x30\x59\x5c\xb9\x7c\x57\x9c\xea\x56\xfa\x00\xe3\x2b\xec\x68\x6b\x4c\x77\xc8\x8b\xbf\x50\xbd\x68\xaf\x61\xdb\x09\x8b\x87\x97\xdd\xbc\xf4\xdb\xb6\xd1\xa3\x57\x15\x8f\x9f\x3a\x7e\xd2\xf2\xcc\x0d\x0f\x3d\x55\x51\x36\xfa\xa5\xca\xed\x37\x3e\xbd\x46\x39\x55\x06\x2c\x0a\x42\x77\x58\xd2\xdc\x01\xdb\xf6\x97\x7d\xd5\xb9\x43\xef\x9e\x5d\xb3\xeb\x87\x14\xe5\xf5\x4c\xcf\xb9\x39\xec\x39\xa6\x87\x26\xaa\x56\x63\xcb\x0b\x1d\x9b\x81\xd9\x60\xf0\xb2\x34\xc6\x2e\x10\x40\x96\xd1\x87\xcd\xb4\x84\xd1\x8d\xf9\xeb\xd5\x5c\x06\x95\x40\x39\x08\x56\x38\x9f\x14\x1e\x07\xe3\x94\x10\x16\xab\x71\xe7\xe2\x4c\x87\xa6\xb1\x6b\x08\x84\x83\x01\x7f\x98\x1c\xfe\x06\x84\x7e\x8b\x18\xf6\x4a\xd8\xc7\x49\x9c\x37\x01\xbb\x59\xb0\x1b\x0c\xfb\x73\xa4\x10\x37\x74\xd2\x55\xa1\xad\x84\x7d\x88\xc4\x7b\xef\x66\xf3\xce\x86\x0c\x7e\x07\x39\x8c\x6d\x02\xf1\xaa\xf0\x55\xec\x51\xc9\x96\x61\xdf\xd5\xce\xe0\xb7\x2c\xaa\x04\xe6\xc9\xfe\x45\xcf\x1a\x32\x96\xb5\x51\xcb\x9d\x53\xfe\x54\x65\x3c\xc6\x0a\x69\x0c\xfc\x9e\xb5\x71\x67\xac\x1e\x66\x85\x7a\xf1\x4e\x31\x0e\xa4\x8f\x54\xee\x8c\xd6\x8c\x45\x83\xd9\x00\x70\x4b\xb1\x3c\x36\xdc\x61\xd7\x64\x61\xaa\xc7\x9c\x4d\x58\x84\x93\x8c\x43\x57\x90\x56\xde\xed\x67\x75\xe3\xaf\x90\xc6\x6f\x2b\xe7\xb8\x9a\x2c\x30\x8d\xd0\xc4\xc5\x64\x84\xa0\x73\xb9\x97\x89\x10\x34\x1c\x88\x18\xcc\x16\x0a\x4d\x26\x41\x59\x14\x61\x41\x48\x50\x56\xc2\x9d\x35\x2a\x08\x6a\x0e\xe2\x70\xc7\x48\x53\x65\xa7\xcd\x48\x88\x32\x87\xa0\x23\xa1\x94\x88\x81\x02\xa9\xf8\x5d\xf3\x72\x29\x13\xdf\xe4\xbd\x46\x2d\x31\xa9\x3f\x7f\x1b\x1d\xb6\xee\xdc\x53\xb5\xb6\x6b\xa8\xfe\x86\x74\xfc\x5c\xec\xd7\x7b\xf9\xc5\xbc\x3b\xb5\xcc\x42\xf9\x75\xd2\x13\xda\x83\x23\xf5\xb8\x77\x05\x7f\x27\x52\x59\x02\xc4\xa1\x33\xd4\x6b\x81\x30\x38\xbb\xca\x70\xea\x43\x4b\xe3\xbb\xb1\xdc\x9d\x4d\x11\x98\x2d\x0b\x12\x8e\x39\x84\xe5\x61\x42\x05\xf1\xc0\x46\x8d\x49\xf3\x9a\x2c\xe9\x61\x7d\xd2\x52\x21\x81\x5a\x49\x5c\x32\x24\x92\x16\x93\xbd\x8e\x8c\x6b\xad\xc4\x55\x00\x5c\x66\xcb\x87\x84\x6b\x07\x61\x19\x05\x25\xcb\xef\x51\x44\x4c\xd5\x12\x57\xd9\x21\x73\xc5\x06\x04\xb5\x9b\xb8\xb4\x82\x93\x55\xaa\xc3\xf5\x3e\x77\x19\xc4\x80\x4c\xd0\xc3\x1c\x57\x08\xc1\x3c\x09\xe1\xd2\xa0\xb1\x3c\x09\xed\xcd\x80\x87\x14\x22\xe6\xd7\x24\xcc\x05\x4d\xc3\x6c\x0c\xe8\x89\x4b\x23\x84\x78\x3e\x38\x70\xc2\x01\x03\xf6\xcb\x5c\xa5\xb9\x5f\xa6\xed\x16\x3b\xde\x90\x68\xfd\x32\xec\xb2\x10\x9e\x5f\x08\x73\xd0\x69\xf4\xe9\x93\x28\xfd\x49\xa3\x63\xf6\x9e\xa0\x7a\xde\x2e\xa1\x16\x78\x57\x2a\xbe\x19\x8f\x63\xee\x9b\x95\xa1\xf4\xbe\xd9\x30\x18\xc9\x39\x6b\xc7\xc3\xbe\x89\x5f\x15\x92\x7f\x56\xc6\x35\xf1\xcf\x86\xe1\x4d\x1d\xb4\x1e\xc3\x0a\x09\x43\x08\x3e\xda\x2f\xbc\x99\x8f\xd6\xc3\x30\x77\xd2\x2a\x18\x6a\x1e\x82\xfa\x68\x12\x11\x6a\x1f\x1d\x98\x08\x8d\x93\x56\x33\xa1\xe6\x21\xb8\x9f\x26\x13\x11\x15\x00\x46\x20\x47\xad\xc5\x31\x06\x00\x7e\x11\xf7\x08\xb6\xc3\x39\xf8\x65\x82\xa0\x46\x44\x3d\x35\x63\x82\x1a\x8f\xa7\x08\xe8\x02\x9d\x04\xdc\x79\x47\xa7\x34\x6a\x8c\x62\x5f\xc7\xd0\x8c\x46\x08\x30\x35\xc6\xe2\x9b\xa0\x40\xf5\xc6\xe2\xce\x24\xe3\x9a\x1e\xe7\x6b\xa0\x6a\xb8\x72\xf1\xdd\x62\x8f\xff\xde\x5d\xaa\xfb\xd3\x32\x39\xce\xb6\x19\x66\x3e\xd7\xba\xac\x70\xec\xec\xe7\x36\xac\xbe\xed\x37\x27\xd7\xba\x4e\xa3\xea\xbd\xf1\xdd\x6d\xc5\x8e\xcb\xee\x6a\x41\xa9\x34\x57\x64\x9a\x71\x52\x48\xe3\x18\xd8\xd0\x0e\x75\x55\x6d\x4e\xb4\x83\xb1\x29\x84\xfb\x2c\x1a\x8f\xf7\x77\xce\x8d\xe5\xba\x2b\xb8\x64\x8a\x31\xd1\x8e\x9b\x4d\x30\x27\x46\x59\xc9\x77\x4f\x6a\x0c\x38\x03\xc9\x54\x6a\x83\x31\xd1\x82\x18\x48\x34\x27\x3a\x16\x88\x96\x44\xc4\x40\x0f\x94\x78\x20\x62\x30\x33\x26\x5a\x0c\x83\x08\xe6\x24\x10\x11\xaa\x8d\xaf\x1a\x03\x7e\x63\x26\x28\x0f\xac\x09\x88\x49\x44\x73\x12\x90\x88\x52\x3d\x8e\x4d\xdc\x65\x10\x01\x9c\xf8\x7d\x36\x03\x8e\x10\x8c\x89\x8e\x96\xa0\xe6\x44\x87\xae\x26\xf0\x5d\x89\x88\xf1\x09\x09\x63\x7e\xa8\x18\x8d\xc6\x44\x0b\xd3\xe4\xa6\x47\x63\x4e\x02\x02\x25\xdd\x6b\x50\x60\x0e\x00\xcc\x5a\x93\xb8\x83\x56\x95\xb8\xce\xf1\x1b\x8a\x24\x75\x89\xab\x3e\xe2\x50\x57\xba\x4a\xf1\x06\xb3\x2c\x40\xbc\xa1\x1a\x42\x13\x6f\xf4\xd1\x0c\x62\x8c\x34\xb4\xe3\x60\xff\xca\x6e\x09\x21\xce\x50\x8d\x47\x8a\x33\xd2\x34\xc3\x9a\x44\x18\xfa\xb1\x57\x48\x63\x07\x8d\x2f\xd4\xc2\x12\x0d\x82\x66\x78\xb3\xc8\x42\x3b\xbc\x24\xfb\x89\x50\x62\x0b\xb2\xf0\x8a\x31\x48\x30\x17\x5e\x15\x55\xe8\x86\x97\xe4\x3f\x11\x52\x5c\x61\x46\x40\x14\x11\x82\x79\x44\x61\xc4\xf0\x08\x00\xec\xf9\x26\xc6\x14\x2a\x34\x8f\x04\x35\x02\x0f\x6b\x90\x05\x8e\x26\x34\xf0\xd4\xd8\x9a\x14\x4b\x04\x87\xa7\x59\xfc\x7f\x0b\x00\xd0\x18\x45\xe8\x75\x58\xac\x0d\x2d\xc7\xb5\xc9\x77\x05\xac\x4d\xd6\x5d\x55\x93\xeb\x92\x6f\xa8\xee\x0c\x48\x45\xc9\xd4\x3e\x4d\x78\xa1\x1d\x3f\x23\xe0\xf8\xc6\x2b\x63\x32\x84\x1f\x34\xf7\x02\xc4\xca\xe8\x79\xfa\xb0\x43\xae\x91\x75\x4b\x3c\xe4\x34\x81\x09\x7f\xb6\x0c\x19\x4f\x67\xd2\xd9\xbf\x19\x37\x84\x70\x44\x8b\x4d\xac\xdb\x0e\xca\x92\x31\xe3\x85\x0c\x6e\x00\xf9\x7c\x9f\xc8\xda\x54\xf2\x09\x8b\x88\x6f\x91\xc2\x5d\x60\x7c\xa6\x99\x2b\x64\x7c\x23\x49\x67\xf8\xc1\xc9\x53\x9f\xdd\x8b\xf8\x26\x2b\xfc\x19\xea\x14\x03\xf1\xc7\x06\x03\x58\x4e\x3e\xa7\x0f\x81\xc0\x52\xcd\xfd\xc2\x1c\x5f\x03\x57\xcc\x9e\x01\xe1\xa0\x3d\x7e\x49\x4f\xa7\x63\x01\x8a\x74\x55\x1e\xda\x13\xa8\x12\x57\xeb\xb1\xbd\xdf\x04\x2c\xb9\x15\xed\xbb\x84\x29\x12\x24\x89\x35\x39\x06\x53\x15\x00\x96\xc6\xab\xbf\x18\x10\x98\x21\x2d\x61\x7e\x30\x6c\xf8\x0d\x32\x7e\x09\xe6\xcb\x06\x52\xf1\x9c\x9a\x79\xfe\x00\x18\x49\x91\xc0\xbe\x80\x50\x89\x91\x41\xe3\xfe\xe0\x78\x57\x48\x78\xdb\xe2\xfa\xde\xae\x81\xa2\x85\x40\xa4\x12\x97\x6b\x40\xc8\xe4\x68\x22\x38\x64\x89\xe3\xa1\x98\x63\x19\xb3\xd9\xea\x0d\x91\x64\x65\x09\xb7\x09\x9d\x64\x65\x29\x7b\x5f\x0e\x0c\x59\xe4\x78\x28\xe6\x38\x0e\x38\xc5\x8a\x47\xb3\xd5\x1c\x32\xc9\x51\x21\x41\x36\x8b\x58\x82\x61\xa6\xc0\x02\x5f\x03\xb3\x9e\x2b\x07\x16\x61\x6f\xed\xcf\x9d\x4f\x8e\xb4\x47\xb4\x84\x84\xeb\xcf\x05\x11\x4b\x60\xc6\x92\xf0\x1a\xe8\x86\x99\xc3\x9f\xfb\xe5\xc5\x53\x7f\xa7\xc2\x55\x3e\x77\x6a\xff\xe1\xd4\x38\xef\xa6\x9e\x3d\xb6\xd2\xd5\xe8\x0d\x34\x1e\xf9\x96\x7f\xc8\x44\xea\xee\xe7\xfd\x63\xa6\x9a\x8c\x69\x58\xe9\xc6\x61\x61\xa3\xc6\xcf\x12\x07\xbe\x60\xbc\x77\x17\xc7\x76\x63\x79\x33\x42\x92\x58\x59\xc9\x04\x0c\xb9\x24\xdf\x6a\xc6\x01\xf1\x3e\xdd\x8f\xc7\xa1\x7d\x5d\xd1\xc8\x86\x61\xa5\x12\x00\x0d\x23\xfb\x53\x22\xa4\x33\x66\xf7\xe4\x6a\x8e\xcc\x30\x99\xad\x44\x02\xa6\xc9\x24\x1f\x1a\x9c\x24\xed\xfd\xb7\x9a\xa7\xcc\xd0\x78\x62\x03\x81\x9a\x4e\xf6\x9b\x21\x10\x55\x6a\xc0\xf5\x3a\x77\x19\x58\x40\x47\x5c\x3f\x4c\xc2\x15\xc2\x9e\x80\x80\x70\x48\xf0\xbc\x23\x12\x5a\xb6\x28\xf0\x31\x81\x84\x79\xab\x84\xb9\x47\x13\x30\x1b\xf7\x0a\x04\xd8\x79\xa1\xe4\x1e\x85\x00\xdc\x70\x6c\x20\xde\x21\x4c\xc2\x7b\xfa\x76\xa4\x68\x00\xca\xd5\x0f\x1a\xd7\x0f\xef\xd5\xd4\x3d\x18\x9c\x3d\x8c\xf2\x97\x3c\x48\x67\xd5\x8f\x48\x7b\x6a\x7b\x00\x2f\x99\xaa\x0c\x46\x5e\x71\x05\x9a\x51\xc9\x4e\x70\x90\x6a\x64\xf9\x9c\xfc\xcf\xd2\x7e\x36\x25\xa0\xf7\x20\x0e\xae\x68\x71\x63\xa0\xb1\x15\xf5\x85\xfd\x35\xc3\x8b\xfb\x45\xfe\x88\xb4\x5f\x34\xdb\xcb\x92\x32\xd0\x24\x30\xa1\x6c\x16\x61\x83\x16\x5b\xe0\xed\x22\x6c\xa7\x82\x48\x09\x71\x34\xe7\xe6\xca\x41\x2a\x8e\x05\x22\x2c\x76\x8e\x92\xcb\xbc\xc2\x21\xfe\x55\x94\xbb\xab\xd3\x1e\x13\x1d\x01\xec\x29\x4e\x9c\x0b\xac\xaf\xed\xb8\x09\xb3\x1e\x7a\x7a\x6e\xff\x91\xed\x0b\x60\x42\x7a\xfa\xa4\xe2\x87\x06\x26\xc1\x84\x44\x74\x05\xf9\xbe\xcc\x2f\xdc\x39\x7d\x77\x1d\xdd\x42\xe5\xcd\xaa\x61\x05\x5c\x7e\x00\x55\xef\xde\xf7\xa7\x27\xa0\xf3\x9d\x13\x9d\xab\x9e\x87\xce\x9d\xb5\x2b\xaa\x57\xa1\x19\x28\xe3\xe3\x99\x63\xea\x19\x46\xe7\xdb\xfc\x18\x3d\x21\x63\x34\xee\x2c\x83\xc2\xa4\x1a\x34\x3a\x1e\x02\xd0\x4f\x8c\xbe\x50\xc4\xea\xc6\x7c\xf6\x6c\x26\xa3\xfe\xdd\x67\x70\xcc\x39\x24\x6f\x19\x1a\xc7\x44\xdf\xe9\xc7\x2f\xe5\xd0\x35\x85\x6d\xe3\x0e\x35\xb8\x00\x25\xe4\xb5\x1e\x82\x08\xef\x99\xf9\x5a\xf5\x1c\x84\x2e\x83\xe9\x2e\x36\xb8\x0c\xe5\x24\x6f\xdc\xd4\x49\xd0\xfa\x66\xf5\x3c\x14\x34\x77\x1e\xd8\xa6\x08\x31\x97\xec\xbd\x9b\x3c\x11\xa5\x04\x39\x2e\x83\x54\xd0\x03\x0c\x0a\x59\x8e\x50\xea\x2a\x82\x4b\x54\x14\xdc\xdb\x07\x97\x8e\xf5\x04\xf5\xfd\x6a\x19\x87\xfe\x2e\x19\x09\x35\x14\xc1\xc5\xcc\x0a\xc5\x47\x34\x59\x50\x42\xac\x30\x07\x00\xee\x41\xbc\x77\xcc\x36\xde\x2f\x58\xec\xc2\xef\xa2\x3a\xb8\xba\x30\x31\xd1\x56\x8a\xb7\xd3\x76\x4b\x87\x48\xb1\x5e\x44\x90\x85\x56\x9d\x69\x8c\x77\xc3\x19\x33\x16\x7d\x00\x47\x5c\x78\x15\x52\x2b\xce\x9f\x86\x33\x3d\xde\x55\xdd\xe1\xec\x8d\x4b\xaa\xde\x9e\x3f\xa0\xa4\xbb\xfe\x22\x02\x32\x7d\x7f\x7d\xf6\x22\x9c\x72\x74\xc9\xcf\x5b\xae\xa3\xb5\x13\x50\x23\xb4\x9e\x87\x6f\x3c\xfd\xc2\xb2\xff\x3d\xb9\xfd\xd3\x7e\xa8\xc1\x9f\x0f\xf1\x20\x3e\xdb\x70\x91\x62\x99\x78\x18\x0c\xa2\x26\xc8\x69\x15\x0c\xa4\xf1\x22\x23\x24\x9c\x62\xfe\xc0\x3e\xe9\x9c\x23\xdf\xfc\x94\x23\x38\x5e\xd2\x59\x47\x74\x30\xd8\x26\x17\x21\x21\x62\x5f\x21\x61\x17\x62\xb9\x6e\x01\x62\xb9\x10\xc8\x26\x1a\xfe\x60\xf0\xcd\x2e\x52\x82\xc3\x17\x79\x5f\x28\xe9\x6f\x37\x03\xef\xc1\x11\xfb\x4b\x2e\xd4\xe7\x1f\x41\x00\x7b\x8f\x2a\x49\x5b\xba\x3a\x90\xa0\x90\xfd\xd5\x18\x7e\xee\x17\x62\xee\x73\xc4\xee\xc0\x5a\xee\x61\xd0\x25\xe8\x17\x40\x1b\xe4\x86\x2c\x82\xa1\x70\xa4\xc9\x32\x08\xf1\x70\xac\x74\xb7\x33\x20\xb4\xbb\x9d\xe0\xa6\x25\xf8\x8d\xcf\xd4\x60\x6a\x15\xf8\x12\x28\x94\xc5\xa1\x96\x2d\x0f\x94\x98\xc8\x16\x82\x96\x19\x0c\x97\x89\x78\x79\xc1\xa6\xed\x13\xb5\x07\xd0\x49\x78\x7b\x76\xf0\xa9\xbb\x6c\xb8\x65\x96\x6b\xab\xed\xb8\x76\xd0\xd3\x9c\x2a\x57\x97\xd5\xc6\x3b\xd2\x42\x2f\x0d\x7c\x85\xb9\x1e\xc5\x2d\x9f\x10\x5a\xf5\xdf\xcd\xe8\x4d\xcf\xc6\x9f\xd4\xe3\xcc\x6b\x46\xfd\xba\xb8\x52\xb8\x26\x14\xa9\x42\xce\x3a\x24\x19\xb6\x98\xbf\x2a\xb4\x92\xdb\x13\xf1\x69\xaf\x95\x47\xbf\xb8\x46\xa9\xad\xb1\x83\x34\xb1\x83\x57\x88\x15\x14\x22\x91\xc1\x6a\x0e\xde\x91\xe8\x0b\x58\x4b\xb3\x4c\xa2\x4d\x83\x25\x2b\x74\x2c\x32\x59\xc1\xca\x7b\x46\xc8\x0c\x05\x2c\x79\x28\x95\x99\xf1\xe7\x64\xdb\xc5\x4a\x4d\xd3\x2c\x5f\x91\x0b\x52\x9a\xe7\x0f\xa2\xfc\x84\x4c\x4e\xae\xb5\x28\xb5\x7a\x8c\x24\xf3\xbc\x6f\x59\x46\x62\xba\x77\x81\x24\x18\x29\x5d\xf8\x82\x5f\x1c\x25\xef\xca\x0e\x22\x40\x2c\x31\xfb\x47\x94\x44\x9b\x2e\xf2\xa1\x28\x83\x2e\x23\xe4\x45\x69\xd2\xc4\x6f\x7e\x86\xbf\x19\x47\xfa\xa6\x8c\x5c\xfb\xd1\xef\x24\xc8\xba\xac\xa1\x39\x0a\x5a\xf9\x1e\xd7\x8e\xef\xd8\xec\x81\x6f\x00\xa5\x55\x4d\xbe\x4f\x7b\x4e\xd2\x41\xe2\x05\xda\x6f\xb2\xee\x69\xc7\x4b\xd1\x8f\x07\x54\xbd\xa0\x15\x91\xc8\x03\x6e\x95\xd5\x4c\x3d\x20\xec\x2d\xb5\x7c\x86\x5f\xa8\xf5\x4b\x3c\x03\xb5\x03\x0b\xee\x6b\x42\x3c\x95\x15\x65\x23\x1c\xcb\xbd\x2e\xc9\x45\x3c\x79\xab\xf0\xaf\x29\xff\x18\xed\x4d\xc6\x90\xe5\x21\xdc\x04\x44\xc9\xc2\x10\x8f\x51\x9d\x6a\x59\xc4\x7d\x88\x1d\xa4\xe2\xd3\xdc\x10\x77\xbd\xd2\xcc\x05\xdf\x66\xec\x92\xa4\x0d\x61\x27\x31\xc4\x2f\xbb\x1f\x53\xe7\x90\x31\x29\xb3\x1b\xfc\x64\x49\xb1\xb9\x21\x6c\x53\xdb\xf9\xb9\x62\x40\x05\xb2\x4a\x3d\x42\x72\x40\x01\xde\xb5\x05\xf5\x10\x96\xae\xb9\x1e\x97\x7a\x61\x35\xbf\xe3\x09\xa2\x3b\x9c\x8b\xef\xe5\x4c\xe9\x5e\x39\x7a\xb6\xab\xa9\xcd\x4f\x10\xd7\xba\xfd\x4b\x4f\x44\x78\x5a\xef\x89\x1f\x4f\xa7\x9b\x76\x42\xd1\xcb\x38\xe2\xf7\xcb\xd8\xd4\xce\x28\x26\x62\x86\xd8\x24\xc5\x4c\x4e\x42\xc7\x14\x56\x92\xd5\xad\xcc\xe7\xbd\x7f\x80\xb4\xcd\xea\xa0\x62\x22\x73\xd3\x9a\xa9\x04\x9a\x62\x52\x76\xab\x5e\xfe\x61\xa1\x75\x75\x08\x6d\xb6\x9b\xd8\x69\xc5\x84\x80\xa6\x36\x5d\x31\x9d\x7d\x72\x07\x16\x92\x0e\xfc\x11\x1c\x34\xaf\x2b\x8b\x09\x07\x4d\x6b\xd0\x12\x9a\x12\xa8\x8f\x0d\x09\x7a\x30\xea\x8f\xd7\x83\x50\x3b\xb8\x98\x90\xd0\xd4\x66\x2e\x21\x2a\x42\x29\x89\x87\xcb\x12\x0f\x65\xe0\xfe\x3f\x80\x87\xdf\xdd\xed\xc5\x84\x91\xdf\xd3\xf8\xc5\x94\x9d\x80\x5d\x60\x8c\xfc\x4c\xfd\xff\xc4\x4f\x53\xbb\xc2\x98\x50\xf4\xfb\x1a\xc4\x84\x48\x92\x31\xab\x9a\xf1\x2d\xf3\x35\xf0\xd3\x95\x5e\x31\x59\x41\xbb\xc5\x40\x7d\xf8\x1d\xb4\x7d\x0c\xb5\x5e\x13\x97\x07\xee\x26\xe3\x6d\xa3\x09\xd7\xa5\xf7\x6d\x15\x8c\x42\x9c\xde\x25\x94\x0e\x33\x01\x61\x9a\xb4\x9c\x31\x03\x6a\xd6\x81\x86\x80\x95\x05\x33\x7d\x0d\x61\x0b\x55\x3d\x69\xf2\x42\xef\x4a\x63\xc0\x1c\x7a\x9b\x1a\x6a\x83\x06\x7a\xa8\x5d\x6b\x0c\x12\xb0\x60\x85\x84\x5f\xee\x61\x93\xdf\x84\x2e\x36\x06\x01\x9a\xd0\xd6\x46\x27\x41\xc8\x5d\x6e\x8c\x93\xa0\x9d\x03\x59\x86\x50\xbb\xde\x84\x3a\x09\xc6\x36\x38\x21\xce\x81\xb1\x05\x0d\x51\x8f\xd4\xf3\x60\x97\x5e\x99\x09\xb9\x53\x4e\xc8\x13\x61\x6c\x9d\x13\xea\x3c\x04\x17\x83\x05\x65\xbe\x86\xb0\xee\xaa\xbe\x3a\xfd\x9b\xd7\x59\xc7\x20\x4d\xb3\x5b\xed\x98\xac\xf0\x90\x3a\xef\x10\xd6\x8a\x5a\xbe\x6c\x90\x07\x06\x36\xbb\x13\x4f\xb3\x44\x34\x69\xcd\x13\x9a\x90\x66\x9d\x7a\x8c\xca\x48\x03\x28\xf5\x0d\x68\x2b\x75\xee\xd1\x79\xc9\x78\x18\x4a\x07\x03\xa8\x72\x7c\x1d\x82\x74\x33\x40\x1f\xf9\xfd\x19\x24\x1e\x3a\xe9\x7a\x1b\x68\x31\xe6\x85\x8e\xd1\x38\x23\xc1\x60\x6a\x3a\x1f\x04\x05\x4a\xe8\x83\xc0\x48\x58\xdd\x12\x9f\xbd\x42\x46\x6b\xb6\x61\x0b\x86\x99\xd4\x25\x21\x24\x8a\x89\x85\x86\x5a\xfc\x62\x47\x9f\x10\xf1\x9b\x6d\xb8\x82\x09\x40\xee\xa8\x10\x9c\x7c\xd3\xfe\x0a\xa2\x0c\x6b\x95\x39\x68\x82\x0c\x66\x1b\xa6\x60\x32\x90\xba\x2f\x34\x71\x12\xfc\x5b\x21\x11\x7f\xb5\x32\x07\xbd\x9b\x3d\x07\x6c\xc8\x02\x90\x3b\x35\x34\x75\x12\x4a\x75\x32\xbc\xcf\x5d\xc6\x32\xf4\x04\x83\x43\x97\x21\x14\xe7\x11\x44\x9a\xe0\x5d\x1d\x82\x4b\x16\xb8\xc7\x83\x28\xdf\x6b\x8a\x7c\xc3\x7e\x9f\x7c\x04\xe7\x11\x6c\xd9\x87\xe0\x36\x9a\x2a\x24\xa1\x30\x93\x06\x93\x7d\x0d\x61\x87\xa5\xba\xcc\x8c\x80\x1d\x21\x52\xf5\x7e\x2e\x48\x8b\x88\x19\xda\x90\x2a\x40\xc7\x88\x6b\x86\x18\x0a\xd7\x82\x60\x5c\x91\x20\x01\x9f\xce\x06\x2c\x81\x37\x40\x0b\xda\x52\x42\x07\x2e\x70\x87\x09\x23\x3e\x5c\xab\xd0\xe2\xaa\x52\x07\x6a\xac\x55\x20\x76\x9c\x30\xe0\x0c\xb5\x05\xc5\x8c\x00\xe1\x29\xb9\x23\x05\x09\xf3\x0a\x09\xb3\x58\x3f\x4a\xa8\x57\x20\x76\xa8\x30\x92\x1b\x6a\xcb\x0a\x1d\xec\x50\x3a\x58\xe8\x60\xab\x79\x96\x31\x87\xd2\xd1\x22\x10\xd1\x01\x5b\x5c\x04\x22\xda\xa4\xe3\x85\x9e\x69\x35\xcf\x71\x20\x55\x7c\xdb\x21\x94\x0e\x18\x81\x89\x0e\xd4\x12\x23\x30\xd1\x26\x1d\x32\x8c\xb8\xc7\xf8\x1a\x5a\x7c\xae\xd4\xb6\x16\x36\xbd\x63\x86\x41\x82\x66\xb5\xd0\xd0\x4b\x13\x7a\x47\x0d\x83\xd2\xab\x65\xba\x0b\x74\x05\xfd\x9a\xd5\x61\x23\x54\xb1\x82\xb5\xdc\x08\x2c\x58\xe0\x0e\x1c\x24\x1b\x59\x81\xac\x52\xee\xb1\x1b\x14\x35\x21\x0f\x53\xe3\xc7\x9a\x9c\x31\x0d\xaf\xa8\x7c\x17\x4c\x6b\x52\xfa\x34\x0a\xf3\xbb\x2c\x6e\xa8\x7e\x1f\xa0\x96\x67\x40\xb3\xe5\x69\x46\x9a\xa2\x56\xa4\x16\x4d\x4c\xb5\x56\x0b\xc5\xc7\x10\xf6\x0c\xa2\x5c\x6e\x69\x9e\x86\x34\x57\x32\xd3\x3b\x9f\xa6\xc9\x37\xb4\x79\x59\xd9\xfa\xa9\x33\xd9\x5f\xa8\x65\xed\xd7\x84\x8c\x53\xbd\xac\xcd\xcf\xda\xd6\x08\x3b\xa5\xb9\x19\xdc\x9a\x49\x6d\x69\xbe\x17\xd1\xce\x6d\xf3\xe5\x6d\x7e\x86\xb7\x46\xde\xf9\xcd\xcb\xf6\x36\x9f\x5c\xf5\xbe\x45\x3b\xb7\xc3\xfe\xa8\xb9\x6d\x4a\x26\xb8\x46\xd8\x67\x9a\x9b\x15\x1e\x60\x72\x4b\x0d\xf2\x5e\xc6\xf2\x0e\x06\xf7\x35\x5b\xde\x3f\x24\x63\x5c\x23\xf9\xf8\x3f\x22\x7b\x5c\xc3\xc2\x92\x20\xfb\x21\x2d\x17\x95\x7f\x28\x17\xcd\xc9\x2c\xd7\xd0\x31\xf8\x8f\xc9\x32\x0f\x40\x08\x71\xef\x34\xc7\xd7\xd0\x02\x48\x39\xbb\x7d\x9a\x91\x75\x6e\x88\x2b\x9a\x90\x86\x4e\x37\x06\xdc\x5e\x05\x4d\xa0\x34\xd9\x73\x61\x79\x22\x81\x0b\xc7\x13\xcd\xc8\x52\x0f\xbc\x13\x0b\x96\xb6\xae\x17\xaa\x19\x59\xec\x26\x7b\xb5\x96\xf9\x4a\x4e\x7b\xc9\xef\xc9\x6a\x0f\x69\x07\x17\x2c\x4f\x9c\xbe\x13\xd2\x76\xae\x59\xb2\xae\x90\x64\x15\x73\xe0\x07\xfd\xae\x2c\xf8\x10\x77\x7e\x4d\x14\xb7\xd9\x59\xf2\xa4\xbd\x61\x4b\x4e\xc9\x99\x1f\xf4\xbb\xb2\xe6\x0d\xa7\xf8\xcd\x4a\xa3\x67\xdf\x08\x78\x8f\xd4\x84\x8c\xf4\xc6\x47\x8d\x7b\x99\x15\x92\xbc\x62\x8e\xfd\xe0\xdf\x97\x65\x1f\xf0\x9e\xa9\x29\x69\xf7\x6f\x04\xbe\x74\xfa\x9d\x32\x3f\xe2\x6b\x68\xb1\x5b\xc9\xc9\x2f\xff\xa3\xb2\xf2\x0d\xaa\xfd\xfb\xd3\xf4\x75\xc6\xeb\xf7\x66\xed\x13\xf6\xb2\x7e\x2e\xf2\x40\x09\x8e\x47\xfe\xa8\x2c\x7e\x83\x32\xfc\x21\x69\xfd\x5c\x76\x20\x46\x9a\x93\xe5\xdf\x58\xaa\x65\x45\xce\xa5\xcf\x68\xee\x5b\x70\x96\xae\x1e\x97\x98\x2d\xee\xa2\xec\x29\x4d\x48\xfd\x8f\xe2\xf6\x0f\x1c\x31\x74\x62\xe4\x3b\x1e\xb4\x7f\xf3\x2b\xa1\x55\x00\xd4\xa7\xb5\xef\xd3\x23\x77\x00\xda\xbf\x0e\xf8\xdf\x82\x63\xf7\x61\xec\xae\xe6\xd4\x2b\xd8\x9b\x50\x02\x10\x97\x49\xcd\xc8\x0c\x31\xfd\xbf\xbe\x5e\x95\x87\x6a\x97\xf2\x70\x42\x7a\xe7\x2d\x58\xc6\x5a\x28\x15\x16\x26\x69\x36\x41\x8b\x2d\x4c\x33\x69\xe4\xca\x0b\xe9\x8c\x81\xb9\xc0\x54\x49\x32\xfd\x6e\x89\x9a\x97\x4a\xdb\x64\x11\x00\x61\x3e\x42\x7a\xc7\x2d\x48\x5e\x70\x68\x95\x24\x66\x62\x04\x2f\x2a\x31\x4d\x13\x3c\xe1\xcf\x77\x96\xd7\x70\x38\xb0\x03\x0f\x3e\xa1\x0b\x2e\x15\xf1\x89\xfb\xd0\xe7\xe5\x57\xe2\x03\x94\x55\xa1\xcc\x10\x13\xa3\x7b\xf2\xfe\x23\xf5\x2c\xc9\x73\x24\xca\x32\x20\xb4\x77\xdb\x88\xd2\xfc\x0e\xad\x23\x4b\xb7\xbb\xa9\xba\xa8\x97\xf4\x7f\xd7\xcd\x75\x53\x7c\x47\xec\x3c\x5f\x0d\x78\xd0\x56\xf5\x6e\x19\x2d\x27\x49\xd0\x5a\x3b\xab\xce\xe8\x82\xe9\x72\xf6\xc3\x76\x8d\x4d\x95\x93\x1f\xa8\x71\x62\x76\x03\x5d\xe1\x37\x9f\xe2\x78\xfb\x38\x84\xc7\xb3\x10\xc6\xf3\xd8\x79\xf2\x20\x1b\x05\x3b\xa8\xff\x36\x55\x82\x4d\x9e\xf2\x1e\xda\x51\xfc\x5d\x9b\x3a\xa3\x4e\xb4\x5c\xa4\x57\xd0\xee\x92\x0c\x53\x37\xc3\x03\x4b\x62\x19\x8c\x37\x43\x79\x48\x49\xfd\x7d\x5c\x65\xe3\xd0\xe6\x01\x71\x4a\x1a\x90\x7a\x80\x52\x69\x9d\xfd\x62\x78\x60\x4d\xae\x88\xf1\xbf\x88\x85\xc7\xc0\x39\x77\xa2\x0c\xc9\x46\x6e\x02\xe6\xd7\xf9\x89\x32\xc9\x45\x91\x29\x33\x24\x9b\x40\x98\xc4\x9c\xa0\xfa\x73\xe5\x20\x1c\x00\x7d\x02\x49\x92\xea\xb9\x0b\x5d\xfe\x07\x84\x00\x59\xa9\x49\xbe\x8d\xa0\x2d\x00\x86\xd3\x5c\xa0\x52\x5b\xf5\x85\xa7\xf0\xf7\x62\x98\x61\x54\x4f\xf6\x5b\xd2\x78\x31\xaa\xf1\x86\xe9\xc7\xeb\xce\x9c\x67\x96\x70\xe1\x20\x1a\x00\xd2\xd3\xb5\xb0\x3b\x71\x01\x31\xe7\x8d\xef\xe3\xd2\x70\x37\x73\x9a\x59\xcf\xfd\x88\xdf\x3b\xce\x00\x80\x94\x3b\xd4\x56\xf5\x20\x36\x7e\xfa\x18\xff\x0a\xee\x8e\x7c\xbc\x3c\x6b\xc4\x80\x9e\xf1\x05\x8e\x25\xb6\xc5\xf7\x64\x0e\xed\xdf\x33\xde\xee\x69\x5d\x3d\xb0\xa8\x5b\x7e\xd1\x80\xf9\x70\x55\x49\xd1\x83\x45\x03\xe6\xb3\x37\xe7\x2c\x4d\xec\x90\x38\xee\x91\x05\x89\x1d\x12\xbb\x76\xfa\xa8\x78\x70\x6e\x56\xd1\xb0\x49\xc5\x83\xef\x2f\x1a\xa6\xe4\xce\xd8\xf1\x3d\x75\xe7\x26\x64\x42\x48\xea\x1c\xe4\x1a\x5a\xaa\x50\x0b\x7a\xd3\xec\xaf\x57\xc3\x78\x98\x2a\x8c\x27\xe4\x4c\x9e\x20\x28\x82\x0e\xaf\xe3\x21\x2b\xf4\x91\xe5\x65\x17\x34\x75\x48\xae\xa2\x0b\x9e\xf6\xa1\xad\xa9\x4b\x45\x56\x66\x9f\xfc\x7e\xb2\x59\x8d\x20\x41\x09\x49\xa5\x7c\x56\xb2\x5e\x12\x30\xe8\x55\x55\xe4\x47\xc0\x21\xf0\xd3\x23\x74\x3d\x21\x2d\x8f\x20\x54\x91\x51\x06\xe7\x4d\x8f\x99\x02\x4f\x00\xc0\x56\xb0\x87\x01\x8f\xdf\x26\x97\x54\x56\xfd\xc0\xd1\x13\xa2\x7a\x96\x1b\x1f\xf3\x11\x2d\xef\xed\xd3\x9a\xb7\x7b\x86\x03\xc0\x0e\x67\x0f\x83\x30\x60\x05\x40\xa9\xd3\x53\x7f\x70\xb8\x34\xcb\x6d\x8d\x2f\x14\xc9\xa6\x56\xf7\x1e\xd0\x13\x00\x70\x13\x08\x18\x95\xcb\x43\x3f\x46\x43\x07\x7e\x3f\x48\x75\xa7\x7d\x8c\x93\x2b\x27\xe1\x54\x3e\xaa\xc2\x69\xb8\x64\x54\x03\xd5\x7e\xd7\xed\x6b\xe0\x11\x5b\x07\x5a\x81\xf6\x38\xdb\xd1\xfc\x82\xd3\x1d\xfc\xf2\x32\xe0\xdd\x24\x05\x8f\x30\x27\x68\xc4\xb9\xf1\x99\x9b\xde\x3a\xfb\x93\xdf\x8e\x90\xde\x00\x32\x49\x5e\xc3\xdf\x64\xca\xf1\x37\x63\x0d\xdf\x54\x25\x73\x1d\x21\xbd\x95\x63\x92\x8c\x85\xb1\x9e\x61\xf6\x30\x47\xf0\x7b\x2e\xa9\x64\x0b\x6e\x48\x50\x3a\x13\xf4\xb4\x20\x70\x82\x11\xae\x8b\xa5\xef\xe6\x32\xcc\xde\x52\xd0\x86\x4b\xda\xea\xd8\x34\x4d\x98\xa4\xab\xbc\x7d\x4c\xb3\xc7\x14\xc7\x89\x65\xf7\x81\x08\x41\x97\x08\x35\xbd\x76\x5d\xe9\x6d\xb2\x10\x1e\xe9\xeb\x6e\xa5\xfd\x60\x67\x5f\x03\x3d\x8f\xcb\x07\x2d\x41\x3c\x70\x68\xb2\x72\x1c\x29\x16\x42\xb9\xb0\x30\xc9\x69\xac\xff\x67\x3a\x4b\xae\xad\x8b\x66\xc4\x7f\x32\xdf\x31\x09\xfc\x92\x99\x30\x05\xff\x71\xf1\x3c\xb6\xb8\x78\x90\x3b\xab\x68\x78\x63\x2b\xad\x68\x47\xad\x4f\xef\x68\xf7\xc1\x2c\xf1\x0f\x05\x3c\x29\xbe\x06\xfa\xb1\x90\xf1\xb8\x73\x3d\xae\x68\x8e\xf7\xf8\x7f\x46\x1e\xb0\x97\x06\xcf\x97\x5d\xfa\x36\x8e\xad\x39\x2e\x61\x35\x01\xc3\xac\x6c\x37\xe9\x94\xb5\x76\x6b\x99\x8c\x46\xe0\x3a\xd7\xd7\x40\x3f\x82\xe3\x0a\xc1\xf7\x11\xa3\x7a\x1d\xa8\x5c\xa2\xad\x5c\xae\x3d\x44\xd4\x19\xc6\x46\x9b\xfe\x1c\x54\x98\xe3\x69\xdc\x8f\xf8\x1d\x80\x2e\x82\x75\x0f\xe9\x25\x00\x72\x58\xa2\xd5\x86\xf6\xa1\xc5\x28\xfa\xf7\x00\x02\x44\x2c\x00\x50\xbe\x93\x00\xd0\xff\xe0\xab\x41\x2b\xd0\x0e\x00\x87\xaa\xfd\x38\xd4\xaa\x7d\x77\x75\xa7\x71\x74\x4c\xa3\xf6\xea\xbe\xe2\x7c\x77\xb5\xd2\x8b\xdf\x3f\xc8\x21\xd0\x4a\x88\x28\x35\xdf\xf7\xd8\x79\xed\x47\x3f\x15\xd4\x5d\xfd\x2d\x2e\x43\x50\x76\x6c\xd7\x99\x45\x06\xbb\xae\xfa\x96\x64\xd7\x3b\x68\xba\xa1\xcb\x16\x5d\xdf\x37\x9e\x02\x77\x03\xc0\xac\x36\xd8\x74\x75\xa3\xfa\xbb\x25\x9b\xde\x52\xd3\x1d\xdf\x6f\xcd\x0d\xdf\x84\xf5\xcc\x49\x6c\x63\xdb\x62\x7b\x68\x9a\xa0\x5b\x4f\x3c\xb5\x37\x4d\xb0\xc5\xdf\xc5\x76\xb6\x2d\x88\x33\x7e\x57\x95\x74\x5a\x4f\xbc\x7f\x35\x4d\x1a\xd5\xd9\xda\xbb\x4c\x6c\x2d\x21\x59\xd2\xc4\xdc\x6a\xee\xf7\x82\x26\x3b\xca\xb5\xee\x19\x01\x7a\xdf\x6a\xf5\x8f\x50\x56\x6f\xd7\x1e\xfb\x11\xab\xeb\x3d\x7e\x6d\x94\xc6\x64\xf7\x01\x8b\xe0\x07\xc9\x35\xfc\x76\x52\xbf\xd2\x1c\x7c\x5c\x47\xae\xab\x17\xf7\xaa\x8c\x24\x4f\x3e\xb0\x80\x44\x90\x26\xf6\x90\x37\x7e\x5f\x65\x13\xa1\xd1\x24\x1b\x47\xfe\x54\x5e\xdb\xe1\x7a\xbb\x4c\x46\xb3\x51\xb4\x80\xb0\x50\x6b\x9d\x65\x7c\xb5\x4d\xc0\x97\x6a\x34\xd1\x46\x7c\xef\xcb\x68\x62\x35\x76\x3a\x20\xb8\xb6\x7a\x63\x4d\xfb\xde\x45\x56\x66\x2a\x57\x0e\x22\x71\x7d\x0b\xa0\x2d\xbd\x28\xb1\x9f\x03\xe7\x48\x71\x86\x43\xda\x12\x23\x76\x74\x48\x23\xb8\xff\xc2\x6f\x3b\x3f\xf9\xc5\xf3\x27\xfe\xf9\xf8\xf5\x2d\x2f\x8e\x6d\x91\x5c\xfc\x97\x9c\x49\xfd\xab\x86\x14\x16\xdc\x3b\x3d\xe5\xa0\xaa\x10\xc2\xca\x74\xfb\xc7\x57\xb3\xbf\xfb\xe4\x6f\xe8\xd0\x9b\x8f\x94\x1e\x40\xfb\x69\x47\xf9\x63\x37\xe7\x94\x4f\x78\xfe\x45\xea\x09\x5d\xee\x93\x06\x4f\x76\x50\x3c\x86\x25\x12\x00\xd2\x26\x4d\xd1\x43\x00\x50\xf4\x60\x43\xee\x92\xa8\xbf\x3b\xb9\x70\x60\x11\xdf\xfb\x26\xcc\x1f\xc1\xcf\x19\x67\xed\x2a\xd1\xd1\x91\x27\x2d\xd5\xb8\xcf\x96\x75\xfd\x0b\xdc\xc3\x56\xca\xf9\x0f\xad\x8b\x2d\xd9\xcd\x11\x56\x5c\x5a\x68\xbe\x8e\xbc\xe6\x73\x02\xba\x3c\x40\x81\x23\x00\xb0\x05\x7c\x35\x08\xc3\x76\x40\x6a\xa1\x1a\xaf\x33\x38\x47\x34\xcd\x52\x5b\x6b\x8f\xc3\xea\xfc\xbd\x51\xd9\xd6\x2a\x87\x27\x7d\x9b\x43\x20\x0c\xb4\x56\x7f\xdb\x63\xe7\xb5\x1f\x4c\xc0\x47\x5f\xaa\xef\xd0\x8d\xf5\xf5\x80\x02\xaf\xe0\x77\x55\x0f\xe3\x33\x29\xc5\xd7\x29\x0d\x6f\xe5\x73\xf7\x1e\xda\x4e\xae\xa2\xab\x5b\xa2\xed\x29\x4b\x81\x51\xd2\xb7\xc2\x40\xa4\xca\xcf\x29\x3d\x63\x47\xc9\x47\xc6\xf1\xda\x2e\xbd\xb2\x9b\xd3\x35\xa9\x15\xdf\x7c\xd9\x8d\xf3\xc0\xdb\xab\xdf\x7c\xd1\x24\x6a\x0a\xff\x01\xd8\x1d\xb4\xc5\xd5\x25\xd7\xdd\x35\x2d\x03\x1a\xd2\xbf\x37\xdd\xb8\x85\x5e\x45\x5f\x6c\x9d\xb9\xab\xfa\x99\x17\xc7\x8f\x5f\x43\x4c\xf8\xfe\xe2\xef\xbf\xa0\x9f\xbd\xb7\x68\xee\xa9\x79\x63\xee\x05\x80\x86\x65\xcc\x15\x66\x2b\x8e\x2f\xa3\x40\x82\xdf\x13\x92\x2d\x29\x2c\x33\x35\x9c\x72\x0c\x69\xb4\x91\x34\x2c\x61\xae\x30\x7b\x88\x63\x10\xac\x21\x2c\x21\x1b\x3f\x79\x00\x83\x9d\x83\x54\x29\x73\x81\x2e\xe7\xec\x80\x17\x76\x4c\xe2\xcc\x52\xa5\xe2\x8c\xca\x87\x36\xaa\x5c\x52\x3b\xce\xef\x09\xbd\x37\xac\x21\x8b\x2d\xd4\x8e\x2d\x9a\xf4\x9d\xe3\x21\x77\x6f\xd1\x64\xe8\xd4\xca\x67\x4e\x18\x3b\x53\x89\xb1\x37\x13\x79\x53\x73\x44\x9b\x06\x55\xc7\x6f\x53\x7a\xd7\x6a\x4f\x43\x43\xef\x3e\xa3\x85\xeb\x08\xbd\x15\x8d\x26\x15\x70\x92\xe6\x2c\x4b\xec\x97\x13\x0e\x52\x71\x87\xbf\xd0\x24\x20\x78\x87\x10\xc0\x5f\x20\xbb\x8b\x10\x1a\xe9\xc4\x1a\x9c\x87\xcc\xbd\x88\x3b\xf4\x3e\xaf\x21\xdc\xca\x34\x5b\x92\x97\x9a\xa6\x4b\x7a\xa9\xd4\x57\x31\x80\x06\x4f\xf8\x1a\xb8\x51\xec\x19\xc0\x83\x68\xf1\x4d\x32\x69\xb7\x12\xe0\xcd\x09\x69\xf7\xb2\x23\xe0\x23\x13\xa2\x89\x6f\xfc\x36\xf0\x9b\x12\x34\x18\xee\x6b\xe0\xe2\xd9\x33\x20\x0c\xc4\xe0\x77\xc1\x94\x13\xab\x00\x00\xe4\x13\xac\x0e\x01\x5f\xe6\x50\xee\x37\x82\xbe\x6b\xf1\x04\xf6\x3b\x02\x07\xe9\x7e\x06\x82\xa7\x42\x48\x3c\xb4\x08\xd6\x82\x51\xde\xd8\x85\xd0\x6c\x51\x3c\xbf\xeb\x87\xf9\xe8\xa8\xde\xeb\x05\x4d\x4a\x91\x39\x99\x17\xac\x4d\xaa\x7f\x53\x18\x0a\x1e\xdf\x79\x5f\x43\x58\x5f\xf6\x8c\xd4\x7f\xa1\xe9\xb9\x31\xe9\x4d\x4b\xf0\x6a\x46\xde\x1a\xa4\x26\x33\x17\xe8\xeb\x9c\x1d\x84\x01\xa0\x58\x39\x6a\xb2\xdc\xba\x4e\x7d\xa6\x0e\xe1\x60\xe6\x04\x35\x1a\xc7\xca\x80\x90\xca\x32\x58\xed\xfc\x09\x35\xbc\xd0\xf7\x39\xba\x0e\x32\x58\x0e\xd0\x00\xd0\x91\xae\xc8\x8c\x32\x74\x9d\x8b\xf9\xdf\x4f\xc2\xb7\x7d\x76\x74\x1d\x7c\xcd\x2e\x03\xe1\x00\xd0\x1e\xa7\xc7\xe6\xb1\xf1\x36\xde\x19\xe9\x88\xe4\xbf\xde\xb3\xc7\xbd\x77\xaf\x7b\xcf\x1e\xf7\xe2\xb2\xc5\x0c\xd8\xb3\xdb\xb3\x77\xaf\x67\xf7\x1e\xcf\xe2\xdb\x7b\xd8\xf2\xc5\xc2\xdf\x3d\x8f\xae\xc3\x83\xec\x32\xd0\x52\xf8\xae\xdd\xe9\xb1\xf1\x4e\x8f\x23\x32\x1d\x96\x2c\xf5\x5c\xba\xe4\x59\x7a\x0b\x5d\x67\x2f\x57\x7b\x2e\x5e\x74\x57\xdf\x9e\x0d\x00\x44\x83\xd1\x75\x90\x2e\xfe\x3c\xf4\xd8\x78\x7b\xa4\x23\xd2\x61\xe3\xd1\xe0\xaf\x3d\xcb\xe0\xe0\x91\xb7\x96\x79\x98\xbd\x17\x3d\xd5\xb7\x93\xd8\xb5\xd5\x6e\x00\x20\x48\x87\x7b\xa8\xe9\xd4\x4e\x01\xb7\xc5\x63\xe7\xd3\xdd\x54\x6b\x37\xdc\x73\xfb\x76\xb0\x3f\x2b\xa1\xca\x98\x02\xba\xbb\xfc\x67\x25\x59\xf4\x87\x59\x54\xd9\xd5\xab\xe2\xdf\x3b\x44\xef\xa7\xb6\x00\x1a\xb4\x7d\x13\x82\x89\xa3\x5e\x83\x10\x82\xac\x31\x19\x39\xd9\xf8\x33\x39\xf4\xc8\x1c\x78\xe8\xbb\xef\x80\xf4\xb3\xfc\xb2\x00\x3f\xcb\x67\x90\x7e\x16\xe8\xfe\x90\x02\xef\xa2\x2c\x7a\x1f\x17\x0e\x68\x21\x2a\xb1\x44\xba\x22\xed\x91\xae\xc8\x77\x2f\xc2\xbc\x8b\x28\x8b\xff\xfa\x96\x5d\xf8\x47\xd8\x13\x65\x20\x2b\x55\xe7\xab\xc7\x3f\x17\x26\xcc\x87\x1d\x9f\xe0\xc0\xcf\x93\x68\x77\x92\x97\x4a\xa2\xdd\x89\x5e\x27\xca\x59\xb5\x0a\xda\x56\xad\x42\x9f\xe0\x71\xab\xe8\xe3\x54\x05\x5b\x07\x38\x00\x2c\x82\xb1\xa6\xed\x55\x53\x5e\xb8\x7c\xdf\x14\x74\x85\x3e\x7f\xa5\xf1\x73\xf4\x2f\x00\xc1\x74\xfa\x38\x55\x2a\xff\x8c\xc5\x6e\xe3\xf8\xe9\xa3\xa6\xc3\x84\xb0\x29\x2f\xd0\xc7\x3f\x85\xce\x98\x2b\x8d\x58\xcf\x7c\x5b\xd0\x2d\xb8\x04\x5c\x13\x7e\x8e\x16\x7f\x6e\x72\xb9\xf8\x73\xe8\xd6\x59\xe8\xb4\x49\x3f\x07\xbe\xa6\x8f\x43\xc4\xd6\x09\x18\x2d\x1e\x3b\x17\x6d\xb5\x39\xa8\xaf\xdb\xc0\xd6\x4c\xcb\x73\x7d\xd9\xed\x31\x53\xa7\xbc\xb2\x08\xb6\x01\x94\x80\x8d\x89\xc3\xe3\xb6\x51\xd0\xa5\x6a\x41\xc2\xba\x29\x2f\x7c\x33\x7e\x82\x82\x36\xe6\x4a\xe3\x15\x74\x0d\x50\x02\x66\x26\x02\xff\xdd\x70\x05\xb5\xab\x17\xd4\xa0\xbf\x64\xcb\xaa\x86\xed\x55\x62\xb8\xe7\xc1\xc1\x58\x1a\x4a\x90\x85\x2e\xc4\xb2\x84\x2b\xd2\x48\x7f\x9f\x96\xa5\xfa\x3a\xb6\xcb\x42\xd8\xbe\xc5\xa4\x17\x65\xf1\xf2\x17\xc1\x42\xdb\x25\x84\x00\x05\x7e\xa4\x8f\xd3\x47\xd9\x3a\xd0\x02\x44\xf9\xa5\x4c\xa3\x52\x65\x79\x7f\x14\xe5\x4d\xea\x08\x0f\xb4\x16\x7e\xf5\x99\x2c\xf9\xc3\x90\x1b\x2b\x53\x00\x20\x78\x17\x00\xa6\x35\x67\x05\xad\x84\xaf\xb0\x16\x3b\x9d\xca\xa7\xd2\x76\xf8\x6e\x57\xe8\x4c\x81\xf1\x35\xb0\xaf\x0b\x9d\xda\x84\xbe\x83\x80\xde\xfe\x4b\x7b\xf8\x02\x1a\xdf\xfe\x97\xc4\xc6\x42\xfa\xa8\xf0\x77\x73\x00\x60\x6c\x9c\x15\x44\xe3\xbf\x5b\x00\x59\xf9\x03\xd1\x3c\xfe\x8a\x25\xc7\x05\x73\xc3\xca\xd1\x51\x17\xcc\x6b\x07\x13\x96\xc1\xa2\xae\xe8\x54\x25\xfe\x64\x3c\xfa\x76\x19\xac\xb8\x91\x70\xa5\xbe\xfd\x2f\xed\xe1\x9f\xd0\x53\xed\x7f\x69\x5f\x7f\x25\xe1\x46\x02\x5a\x09\x17\x08\xdf\x5e\x05\xf7\x53\xa7\x98\x74\xd0\x0a\x84\xbd\xde\x82\x06\x59\xae\x9c\x6c\xd5\xc9\x44\xda\xaa\x0d\xab\x56\x6e\xac\x5d\xf1\xd4\xb3\x54\xc3\x96\x17\x77\x6d\xde\xb4\x7b\x37\xa0\x41\x9c\xef\x2a\x7b\x09\xe6\x83\x56\xe2\x5b\xa0\xaa\x40\x3d\x2d\xd5\xe4\xd7\x71\x33\xc6\x17\x95\xce\x1a\x35\xb0\x94\xca\x31\xfe\xaa\xaa\xe2\x81\xc1\xfd\xee\x7d\x60\x50\x5f\xdd\xbf\x15\xdb\xc2\x9c\x03\x2c\xb6\x2d\xd1\xf6\xc8\x74\x78\x11\x2d\x14\x2c\xca\xf0\xdb\xb3\x01\x44\x43\x05\x5b\x82\xff\xbc\xe5\x41\x06\x40\x90\xe5\xca\xca\xc9\x86\x6e\xc1\xa6\xa0\xa1\xf0\xe2\x48\x66\xc9\x70\xc1\x90\x60\xbd\x8e\x42\xd7\xc1\x35\x76\xa9\xb0\xfa\xe8\x48\x6c\x75\x22\xaf\xc1\x7f\x9e\x28\xa3\xcf\xc1\x83\x68\xe8\x9d\x24\xe6\x32\xd0\xfc\x5c\x2b\x79\x4c\x7b\xb4\xf4\xb3\x68\x1e\x7c\x5a\xfc\xf9\xe1\xa8\x41\xfa\x1b\xda\x9f\x77\xdb\x23\xed\x6e\xf9\xdb\x4f\xa3\x79\xe2\xf7\x87\x42\xeb\x70\x79\x04\x1e\x54\xf9\xae\xb5\x98\xcf\x9e\x06\x6d\x40\x24\x88\x07\xe9\xc0\x0d\xfa\xaa\xba\x1d\x8a\x67\x1f\x69\x16\xe8\x82\xb4\xd5\xd5\x25\xca\xdd\xd5\x91\x42\x41\xcd\x9f\x79\x54\x7d\x3e\x59\xc3\x9f\x44\x89\x7f\x50\x35\xfb\xc8\xa2\x95\xcf\xce\x79\xf7\xe1\x55\xab\xe7\x31\xbd\xff\x7d\xe7\xe4\xec\xbc\x3e\x95\xf9\x05\x63\xa9\xfb\xa7\xbf\x53\xbd\xf2\xd9\x07\x8e\x2e\x5c\xb3\xf6\xa6\x27\xbd\x38\xab\x9b\xb3\xb8\x33\xfc\xcf\xf4\x77\x1f\x59\xb9\x71\xf6\xdb\x0f\x09\xff\xb1\xb0\x32\xdf\x39\xb0\x33\x3d\xff\x65\x98\xb0\x66\xfb\xb6\xdd\xe8\x5f\xeb\x5e\xf2\x76\x60\xeb\x6e\x97\xd0\x93\xc6\x41\x6e\xcd\x38\xe4\xf3\xa6\xbc\x0e\x53\x9e\x7d\x7e\xd3\x4b\xe8\xe2\x86\xe7\xd7\x8d\x9f\xf5\xd1\xf8\x71\x73\xfe\x3a\xf6\x20\xb4\xe3\xff\xf6\xe5\xfa\xe7\xd7\x8d\x17\x7e\x70\xce\x5f\x05\x1d\x3b\x45\xef\xa6\x52\xd9\x3a\xc1\x26\xc6\x43\x3b\x7d\x6a\x00\x8c\xde\x44\xef\xa6\x22\xbc\xd7\xc5\xf8\xfa\x14\xbd\x9b\x3e\x82\xff\x9c\x17\x7f\xc2\x65\x91\x7e\xea\x6c\x09\xb4\xd6\x8a\x3f\x8a\x7f\x9c\x16\x7e\x96\x1d\x2e\xfd\x6c\x2b\xff\x4f\x6b\xff\xc6\x39\xff\x08\xca\x5f\x05\x10\x14\x83\x0a\x6a\x13\x13\x86\xed\x9f\x1b\xda\xa0\x85\x2f\x86\x6b\x8f\xa1\x1f\x97\xdf\xa4\x9c\x51\xf0\xec\x73\xe8\x20\xda\x39\x05\x40\x00\x40\x05\x35\x5c\xfc\x39\x37\xa4\x3d\x96\x68\x08\x6d\x2b\x6e\x9e\x46\xb3\x7e\x83\x43\x61\xe5\x14\xe4\x8a\x42\xc2\x92\x14\xd6\x01\x73\x04\xdf\x2b\xb6\x05\xf1\xe2\x7d\x96\x5f\xe3\xe3\xa1\x1d\x5a\x74\xbf\x57\x56\x41\xf5\xf3\x70\xa4\x0f\x9c\xd4\xfe\x56\x5e\x06\xf0\x0d\xfa\x5c\x63\x16\x7a\x46\xf3\x5b\x01\xff\x41\xce\xca\x34\x70\x97\x64\xdf\x72\x30\x93\x69\xd3\x99\xb3\x9e\x3a\x05\x00\xf4\x36\x00\x40\xdb\x44\x8e\xed\xd0\x05\xbd\x0d\x4c\x41\xc3\x9d\x0f\x84\x39\x13\xcf\x91\x6a\x7c\x67\x61\x03\x7b\x19\xb4\x04\xd1\x20\x19\x64\x80\xf1\xbd\x0b\xd3\x13\x61\x6c\x22\x4c\x8c\x4d\xb7\xc0\x58\x0b\xb4\xb4\x89\x6d\x13\xdb\x86\x4a\x4f\x87\xb1\xe9\x30\xfd\x3f\x0e\xf8\x99\x03\x16\x38\x16\x3b\x5e\x70\xd0\xc9\x0e\xe8\x48\x0f\x83\xb1\x61\x30\x2c\x9b\xea\x4d\x0d\xa7\xe6\x50\x8f\x51\xdb\x29\x8e\x02\x59\x63\x5c\x63\xc6\x64\x8d\x19\x33\x46\xf8\x77\x54\x7e\x7e\x56\x56\xa4\x6b\xcc\x18\xe1\x9f\x9c\x6c\x4f\x57\x45\xf6\xc8\x60\xbf\xac\xd9\x3f\x7c\xfc\xb8\x11\x23\xc6\xc8\xff\x1a\x31\x4e\xf5\xbb\xd9\x2f\x0c\x29\x1d\x31\x6c\x18\x6c\xd8\x3e\xe4\xee\xe1\xc3\x87\xe3\x7f\x0b\xbf\xff\x59\xfc\xef\xda\x35\xdb\x56\x58\x83\xae\x48\x87\x5b\x58\xb3\x2e\x71\xdd\x9e\x38\x01\xff\x79\xe2\x84\xbc\x0e\xfd\x2b\x57\xf0\x0f\x7e\x9b\xd0\x0a\xc4\xf7\x0e\x07\x61\x80\x89\x60\x92\x19\x9a\x61\x5b\xd2\xac\x60\x4d\x22\xce\x8c\xe9\xd2\x25\x27\x5b\x36\x18\x4e\x7b\xa4\x1d\x1b\x8d\x2a\xd8\x03\x7d\xe0\xb7\x1c\x43\xa1\x15\xe3\x88\x40\xd7\xc1\x75\x76\x29\xb6\x57\x76\x3a\xd2\x11\x79\x1d\xfe\xeb\x64\x19\xbb\x14\xad\xbd\xfd\x4f\xb6\x03\x50\xfd\xcc\x4a\xec\x5f\xe3\xa1\xf0\xd5\xeb\xd7\xaf\x9f\x14\xcc\xca\x61\x54\x8c\xa1\x51\xd2\xcf\x2c\x03\x1c\x8e\xaa\x3c\x36\x5e\x18\xdb\xe6\x71\xe2\x9f\x1c\xb9\x78\xf1\x62\x66\xef\xc5\x8b\x75\xb7\x1b\x59\xa6\x6e\xee\xdc\xb9\x5a\x0e\xda\x28\x1c\xa8\x18\x88\x53\x08\x40\x5b\xfd\xf2\x83\x09\x94\x9b\x4e\xc5\xb6\xc8\xa6\xb7\x40\x8a\x2d\xa1\x26\x4c\x7b\xfb\xb1\x95\x1b\xa7\x1d\x7f\xf4\xf1\xcd\xd8\x38\x14\x8c\xa5\x27\xbc\x09\x93\xd7\x6d\xab\x7d\x1d\xfd\xb8\xf9\x85\x35\x92\x51\x10\xbe\x97\x45\x95\xd0\x99\xec\x51\xd0\x52\x3c\x53\x13\x96\x27\xef\xe0\x1d\x1e\xa7\xab\x00\x86\xc3\xac\x24\x78\x11\x32\x0b\x17\x38\x16\x24\x5f\xb3\xaf\xda\xdf\x2d\xa6\x4d\x0f\xea\xf2\x7e\x2a\xd3\x7b\x66\x4f\x6d\xed\x9e\xef\x4b\xac\x83\x05\x3d\xaf\xa4\xf2\x69\x37\x5b\x87\x5f\xbf\x72\x27\x42\x7c\xba\xe5\x48\xe1\x9d\x16\x3b\x6f\xe7\x95\x15\x55\xe9\x7a\x24\x7f\xd4\xc4\xa5\x05\xfd\x07\x2f\xa0\x22\xd2\xd1\xb6\x8c\x0e\xfd\xe7\xae\xfe\xf2\x2f\x3b\xa8\xd9\x75\x49\x8e\xa1\xfd\x67\x59\xfb\xc2\x9d\x87\x57\xb5\x5e\x36\xe3\xb9\xb7\x85\x3d\x3c\x95\x4f\x3b\xd8\x53\xf2\x0b\xd2\x62\x6e\x22\x8f\x4f\x95\x5d\xfe\x45\xea\xc1\x7b\x35\x71\xab\x56\xf1\xd4\xff\xed\xed\x30\xd9\x9a\x91\x7f\xef\xcc\x8d\x49\x61\xc3\x1f\x9c\xb6\xf0\xc3\x1d\x5b\x6a\x2f\x66\x65\xf4\x1c\xe4\xea\xd8\xb3\x98\xae\x7e\x15\x46\x3e\x13\xce\xd7\xc5\x2c\x98\x53\xfe\xc8\xcc\xe7\xfe\xba\xaf\x2a\xa7\xf0\xbe\x01\xd9\x9e\x21\x38\x36\x5a\x44\x95\xd0\x33\x71\xdc\x12\xdf\x3b\x9c\xa5\x92\x29\xb8\x8a\x82\x1c\x45\x27\x82\x64\x50\x50\xe0\x1a\x3b\x66\x6e\x54\x7e\x4e\xb6\x05\xda\x85\xc0\x6e\x11\x3c\x8b\xa6\x3b\xa9\x75\x49\x28\x8b\x2a\xa1\x0e\x1d\x7e\xd6\x9b\x2e\xec\xdf\x4b\x29\x37\xed\x64\x4f\x03\x9b\xfc\x3e\x9d\xe6\x34\x9e\x4f\x84\x3a\xd0\x4e\xce\x62\xb5\x49\xe8\x4b\x1f\x9a\xe9\xca\x3f\xb0\x72\xd5\xa6\x49\xa3\xfa\x0c\xfb\xf0\x95\x67\x5e\xfe\xde\xdd\xa9\x6b\x8f\x0c\xe7\xe2\xf9\xbd\x2b\x3b\x26\x3b\x72\xe8\xa4\xca\x87\xd2\x1c\xf7\xf6\x9a\xf5\xd4\x9c\xf1\xe5\xd3\x92\x3b\x4c\x18\xb8\x74\xdd\x92\x85\x1d\xbb\x14\x64\x74\xca\xb3\x75\x82\x03\xf2\x3a\xa6\x0f\x4a\x49\xeb\x22\x9e\x7f\x50\xf9\xb4\x8d\x3d\x25\xbd\xfc\x2d\xce\x88\x07\xa7\x4b\x74\xf5\xab\x8b\x45\x4d\x5d\xfb\xd1\xc9\x0f\x3f\x97\x56\x51\x35\x75\xe1\x87\xdb\xd7\xbf\xf0\xe4\x9d\xbd\xa3\x4e\x75\xe9\xd8\x6d\x50\xa7\xec\x6e\x83\xa8\xc1\x47\x5a\xb5\x99\xb5\xa8\x62\xd1\xac\xe7\x3f\xdc\x51\x5b\x87\xae\xad\xa1\xfa\x67\xe7\x96\xf6\xcb\xee\x39\x4a\xe0\x6d\x19\xd5\x48\x97\xb3\x1f\x09\xb1\x4e\x3c\x74\xf1\x72\x6a\x8e\x43\x49\xcd\x59\xb6\x61\x6f\xe4\xa4\xea\xf1\x93\xc2\xca\xcf\x8d\x0c\xeb\xd3\x63\x74\x7c\x4f\xaa\x91\x3a\xb2\xf0\xa9\xd9\x95\x99\x0e\x54\x0a\xd7\x26\xa7\x94\xac\x7a\x04\xfd\x24\xe0\x8e\xf7\x8d\xa0\xdb\x52\x7f\x12\xdf\x46\xf7\x74\xed\x05\x5d\x5d\x6c\x2e\x8f\x8b\x76\x78\x1c\x6a\x2f\x2a\x20\x8e\x1f\xf3\xe7\xfb\x57\xe4\x71\xce\xed\xbb\xb6\xb6\x60\xc6\x2e\x99\xf8\xa7\xfa\x8a\xac\xfb\xdc\x5d\xb3\x06\xce\x9c\xf6\xe4\x7f\xd7\x57\x4d\x6a\xbc\x75\x7f\xd5\xc6\x9a\x85\xe3\x9e\x9f\xd8\xa5\xe0\x4b\x9c\xdf\xe4\xbb\x9b\xfa\x92\x7a\x48\x7c\x3d\x4d\xfc\xb6\x30\x29\x19\x90\x57\x77\x61\xb7\x48\xba\xcb\xa5\xce\x3c\xb9\x78\xd1\xca\x9f\x3e\x77\x50\x25\x85\x5d\x46\xdf\xf3\xf0\x86\xb5\x3b\x7e\x4a\x9a\xf1\x50\x71\xcf\x07\x1e\x7b\xfa\xdf\x4b\x66\x4f\x5a\xfa\x74\x78\x78\x41\x49\x74\xda\xb6\xee\xdb\xa0\xab\x6f\xb7\x3e\xb3\x84\x31\xba\xfb\xee\xa1\xee\x50\x0f\x83\xd6\xc2\xda\x54\xc6\xa0\x24\xe8\xb9\xa2\x9b\xef\x3e\xf1\xc8\xa3\x4f\x3d\xf7\xd5\x91\x65\x2f\x7e\x36\x6d\xc4\xfd\x93\x3c\x23\xb3\x1f\xdb\xf0\xfd\xe2\x5d\xab\xaf\xa2\x5f\x77\xae\x5c\xf2\xde\x8a\x95\x63\xb6\x0b\xb6\xe1\xb0\x6f\x1c\x9d\x4f\x4d\x17\x7c\x26\x0f\x69\x97\xcd\xe3\x82\x16\x87\x93\x2f\x86\x43\xb7\x7d\x33\x7c\xcf\xff\xa1\xb7\xf7\x7e\x5b\x76\x78\x3b\x5c\x03\x1f\xfe\xfe\x7b\xb4\x10\x55\x5f\xbb\x26\xda\x87\x76\xbe\xbb\xa9\x4f\xfd\x72\xe6\x76\x87\x1e\xe9\x32\xc6\x2d\xce\x0d\x3e\x34\xc2\x78\x3c\x8e\x14\xae\xdd\xb7\xff\x70\x50\x03\x0a\xf3\x47\x8f\x78\x74\xed\xba\x1d\x33\x4f\x3e\xb6\x70\xe5\x87\x25\xdd\xa7\x5b\x12\xa7\x54\xa7\x2d\xa9\x69\x1b\x5e\x50\x12\x93\xfa\x7c\x8f\x6d\xab\x6b\x7e\x7c\x7c\xf6\xd4\xde\x33\x46\xf6\xc5\xeb\x1d\x00\x66\x3b\x7b\x1a\x24\xca\xfd\xc5\xc5\x85\x19\x6d\xb5\xe1\x15\x2f\xfd\xcf\xe2\x48\x49\xab\xac\x81\xf4\xfe\xdd\x4b\xc7\x8e\xbf\xff\xb1\xe7\x97\x0f\xa7\xfa\xe7\xa0\xbf\x26\xc2\xc4\x1c\x74\xb9\x03\xf4\xe4\x78\x8f\x94\xb5\xde\x77\x82\x76\x1c\x83\xf9\x07\x8a\x7e\xf4\x5c\x79\xab\x8e\x81\x8b\xbe\x7b\xf6\xea\xeb\x3f\xc2\x2d\xe7\x84\xf5\x54\xe8\x5b\xc9\x32\x5c\x14\x48\x96\x73\x06\xa3\x3a\x14\x40\x17\x1f\x63\xf3\x08\xff\xc7\x3b\x61\xae\x27\x92\x6b\x0b\x1d\x9e\x34\x27\xef\xf0\x74\x86\xa9\x56\x1b\xe4\x28\x4b\x8c\x0d\xa6\x65\x40\xbe\xf0\x5d\x58\xf8\x71\x8f\xda\xee\x83\x7a\x14\xd6\x8e\xcc\x48\x9a\x9f\x8f\x4e\xf7\x7a\x6c\xe3\xfa\x9e\x9b\x7a\x0e\xec\x36\x60\xcb\xb8\x49\xd3\xa1\xc7\x0a\xb9\x47\xb6\x2d\xce\x2a\x85\xc3\x3b\x7b\xac\x16\x2a\xf3\x9f\xf0\xb1\xaf\xac\xb5\xcf\xd2\x11\x7b\x3e\x8f\x8a\xba\x95\xd8\x78\xa3\xad\x0b\x35\xf6\x6a\xbd\x75\x2b\x17\x75\xe8\x46\xe1\xa5\xbd\x65\x79\xd4\xc6\xbe\xe8\x9f\xa8\x22\x96\xa1\x87\xb7\xa4\x04\x2e\xfa\xfb\x1a\x98\x6b\xec\x19\x7c\x9a\x13\x81\x7b\xad\x4b\x5d\xfe\x29\x61\x9f\x2f\xe5\xd1\xd9\x68\x7c\x6a\xd1\x16\x03\x76\xa4\x80\xfe\x7f\x85\x23\x2f\x3d\x7a\xf2\x81\x05\x13\x9e\x29\x5e\x7c\xfa\x21\x4f\xe1\xb2\x53\x96\x96\x93\x37\x38\x1c\xf9\xc9\x77\x0d\x1d\xd8\x25\x3c\x7d\x42\xf5\x47\x7f\xbd\x83\xfe\x8f\x4a\x87\x10\x1e\xfe\x77\xe7\xee\xb7\xf3\xd2\xf7\xa0\x13\xaf\xce\xdf\x98\x42\xcd\x3d\xf4\x61\x98\x0f\xb4\xed\x38\xfe\x9e\xa3\x11\x2e\xd4\x38\x04\xa6\x62\xfb\x25\x04\x0d\x42\x6c\x13\x09\x40\xa4\xc7\x65\x91\x52\xc5\x78\xfc\x6f\x4b\xea\xea\x0b\x74\xa6\x1b\x81\x62\xf8\x55\x1e\x72\x38\x61\x58\x07\xf4\x7f\x6e\x54\xef\x81\xdc\x41\x1a\x21\x74\x00\x1d\x3c\x88\x6e\x43\x4e\xd0\xbb\xff\x02\xc0\x5c\x60\xcf\x08\x96\xc3\xe1\xe9\x05\x3d\x0e\x8f\x0b\xff\x83\x17\x23\x9e\xe6\xb6\x50\xfa\x30\xc7\xdb\xe9\xd6\x39\xf7\xcf\x8c\x7b\x2f\xf5\xbd\xb8\xe3\xce\x63\xed\xd2\x7f\x3d\x76\x62\xff\xdc\x9a\x71\xc5\x13\xad\xb1\xb0\xd2\x89\x76\xc5\xc1\x31\xa9\x68\x47\xc6\x66\x6a\xad\xe7\xa6\x7d\xd6\xe8\x03\x0b\xf6\x2f\xfd\xf0\xd3\xb2\x1f\x8a\x86\x8c\x9d\xbb\x7f\xc1\x81\x4d\xfd\x50\x23\xc6\x9e\xea\x4b\xe2\x3e\x67\x47\x82\x0c\x7f\xe6\xa1\xc0\x9c\x31\xcd\xcf\xee\xa1\x1d\xd0\x23\xff\x2e\xf5\xe7\xef\xa2\x5b\xac\xfb\x74\x4f\xdf\x1b\x67\xb6\xe5\xb8\x57\xac\xb6\x2d\x43\xf5\x4f\x45\x4c\xa8\xac\xbd\x6b\x1c\xaa\xb7\x9e\x3b\x03\x1b\x6d\x11\x13\x46\x6f\xcc\xc0\x0f\x17\x3c\x03\x67\x5f\x6f\xbb\x77\xd3\xe0\xa9\xde\xa5\x54\x4d\x91\x6b\xd1\x77\x7f\x45\x59\xa3\xd1\x09\x1a\xcc\x92\x73\x33\x59\x61\x5f\xcc\x1c\x62\xeb\x70\x6c\xe8\x00\x4e\xb1\xcf\x10\x16\xdf\x62\xb7\xb8\x2c\x2e\xec\x1a\x5d\xbc\x83\xb6\xd3\x0e\xda\x61\x49\x75\x39\x1d\x1e\x97\xd3\x61\xb1\xb9\x3c\xb4\xcd\xe5\x09\xb3\xcf\x4d\x9c\x93\x3c\x7b\x26\xec\x97\xb3\x75\xe6\xbf\xa7\xcf\xb1\xcf\x49\x9a\x6b\x9f\x3b\x1d\x9d\xca\x3e\x30\xfd\xa7\x19\xb0\xe5\x92\xd6\x15\xb1\xae\xd6\x2d\x6f\x85\x17\xb5\x1b\xde\x2a\x2c\x02\xde\xae\xdd\x50\x0b\x6f\x23\x4e\xf8\xa7\x76\x43\xad\xf8\x0b\xfc\x5f\x37\xa2\xfa\x0d\x1b\xd0\xe7\x4b\x97\x8a\x77\x1e\xf9\xbe\x06\xee\x38\x5b\x07\x5a\x02\x8b\xb0\x0e\x5c\x84\x9b\x24\x58\x40\xb9\x30\x34\xcd\xa3\x12\xee\xae\x1e\x4b\x3e\xcc\x83\x3d\xff\xf5\x1b\x7a\x13\x7d\x5d\x3a\x7b\x97\xab\x66\xdb\xb8\xca\x22\x78\x2e\x66\xeb\xa2\x7d\xae\x1b\x9d\x7f\x29\xe4\x3a\xa7\xa5\xf5\xce\x98\xba\xe8\xf1\x75\x51\xbd\xd8\xba\xbf\x1f\x43\xe8\x8a\xf7\x16\xcd\xad\x7f\x62\xd0\x70\xef\xc9\xe9\x55\x97\x7f\x3e\x87\xce\xb4\x8b\xeb\x70\x57\x8c\xa5\xde\xbd\x78\x5e\x56\x19\x8c\x13\x31\xc5\xfb\x1a\x78\xc1\xe7\xb7\xc1\x55\x5e\x32\x26\x9c\x17\xae\x86\xe5\x96\x5d\x9d\xf2\x04\x86\x68\x29\x62\x6c\x92\x37\x8c\x87\x6e\x98\xff\xcf\x7f\x3f\xb3\xec\x09\xf4\xc9\xa4\x99\x7f\xda\xe7\x5c\xb8\xbc\x74\x6c\x0a\xdc\xff\xd4\x9a\xe2\x8a\xdc\x51\x33\x86\xd6\xbf\x7e\x78\xed\x84\x47\xa6\xb8\x7a\x15\xf6\xa9\x2a\xbb\xfc\xd1\x11\xb6\xee\xc4\xc7\x9b\xbe\xed\xe5\x5d\x4b\xe5\x78\xcf\xd2\x99\x8b\x67\x8f\x18\x7c\x67\xfe\xad\x8a\x42\x4f\x7a\x41\xf7\x01\x4f\x54\xec\xf8\x70\xec\xf9\x91\xae\x8c\x8c\xe2\xb4\x7e\x2b\x46\xbf\xfd\xb1\x80\x15\x9f\xc9\x70\xc5\x6c\x1d\x48\x02\x29\x20\x0d\x74\x04\x99\x20\x5b\xec\x84\x24\xce\xad\x8b\x56\xfe\x91\xe7\xd7\x22\xfc\x63\x13\x95\x9f\x15\x17\x80\x45\xfc\x5d\x98\x7d\x2d\xbf\x30\x79\x62\xec\xbf\xec\x87\x8e\xff\x2f\xf6\xe0\xe1\xef\xde\xbe\xdf\x5e\xed\x5e\x6f\xdf\x77\x04\xfd\x18\x79\xe8\x38\xfa\x21\xf6\x48\x51\x66\xeb\xf2\xdc\xa5\x30\xa6\x9a\x1b\xdc\x35\xcd\x52\xdd\x27\xab\x55\x99\x6b\xa9\x66\xb6\x75\x33\x7e\xe6\x4c\xed\x86\x0d\x1b\x6a\xdf\x69\x3c\x74\xa6\x76\x03\xa0\x41\x2e\x3a\xca\xce\xe5\xac\x80\xc6\x15\x57\x78\xef\x00\xe5\xea\x8c\xae\xb9\x1e\xbb\xf0\x3f\x8c\xd3\xe1\x51\xd5\x5b\x49\xae\x31\x1c\xe6\x26\xd2\xb9\x49\x8d\xff\x79\xfa\x9b\xa7\xcb\xab\x33\xc3\x5a\xc5\xa2\x0b\xe9\xd0\xe9\x80\x99\x8e\x2d\xe9\x5b\x1b\x2f\x87\x87\x0d\x59\x7f\xcf\xa6\xfd\x30\x67\x70\x61\xd1\xbc\xc1\x7d\x06\x0e\x78\x78\x00\x3a\xfa\xf4\xd3\xd4\x47\x6f\xc0\xa1\xaf\xf5\x1b\x1e\xff\xc0\xb2\x8f\x76\xec\xf8\xe8\xce\xc8\xb5\x15\x83\xfe\x7e\xb6\xbc\x7c\xc1\xbf\x1e\x28\x2e\x7f\xf8\x63\xf1\xac\xcc\xd7\xc0\x5c\x62\xcf\xe0\xac\x31\x8f\x2b\x57\x20\x24\x17\xf8\x2d\x9e\x64\x13\x78\xbb\x80\x46\x30\x74\xc9\x91\xe9\xa9\x8b\x5b\xb4\xa9\x76\x2e\xbf\x17\x0e\xa8\x9f\xb4\xad\xac\xfa\xde\xf2\xce\xe3\xb7\xe5\xc1\xd1\x4e\xb4\xa9\x55\x38\xcc\x48\x45\x3f\x8c\x9a\xb2\x6c\xe3\xa3\x9f\xa0\x42\x78\xf9\x60\xdf\xec\x03\x8d\x30\xbe\x73\xfe\xd7\x39\x09\xcf\x3e\x75\x20\x65\xc4\xc1\x87\x16\x15\x20\x54\x00\x7f\x13\xc6\x4e\x00\x80\x9d\xc0\xd6\x01\xab\x60\x23\xf0\x8a\xa4\x5d\x1e\x68\x87\x76\xde\x61\xb1\xd3\x3c\x9d\xb0\xb4\x3a\x63\xd1\x4a\x98\xb3\xaa\xf5\x4c\xb8\x12\x4e\xf5\xde\x80\x31\x19\xdf\x5f\x44\x07\xdf\x9b\xf1\x00\x35\xf3\x43\x6a\xa9\xb7\x7a\x1d\xfc\xc5\x5b\xfd\xa1\x77\x3d\x35\xbc\xbf\xf7\x26\x96\x67\x38\x00\xcc\x39\xb6\x0e\x47\xd2\xa9\x1e\xde\x99\x6a\xc1\x05\x08\xbc\xc7\xc6\x0a\xff\xd0\x76\x0f\x3f\x1c\x5a\x9d\x75\x45\xd0\x5e\x86\xb6\x7b\xe8\x1b\x1e\xf4\x42\xfa\x3b\x7d\xd1\x85\xb4\x0f\x8b\xd0\xd9\xf1\xe8\xac\x6b\x1f\x04\xfb\x0e\xcd\x79\xe8\x2f\x70\x33\xa4\x10\x7a\x77\xde\x43\x6f\x1d\x5a\xb4\xf0\x28\x72\xdf\x98\x21\xac\x91\x74\x64\xe5\xcf\xb3\xa7\x41\x1c\xe8\x84\xfb\x45\xf6\x82\xae\x64\x10\x69\xa5\x18\x87\x30\x8e\xff\x92\x81\x17\xdb\x3e\xcb\xce\xd9\xe9\x90\xf2\x28\xa4\xe8\x8c\x4f\x1f\xd4\xf8\x08\x2c\x85\x8f\x7d\x82\x9e\xfe\x19\x6d\xbf\x06\x9d\x6f\xb5\xdd\x78\xf5\xe1\xeb\xef\x8d\x7c\x6b\x18\xbd\xee\xa5\x4e\xe7\x8e\xbc\xf2\xe6\xe8\x03\x0b\xfb\x4d\x6f\x17\xc6\x45\x0f\xdb\x9c\x36\x65\xd0\xf8\xde\xdd\xfa\xdf\x1b\xc3\xce\x75\xba\xd0\x3e\x74\xde\x8b\x1e\x3d\xcb\x54\x36\x6e\xa9\x85\x96\x03\xfb\x3e\xef\xd0\xe1\x7f\x2b\xe9\xd4\x4f\xdf\x78\x65\xdb\x83\x07\xee\x4f\x6f\xdf\x75\x16\x5a\x46\x7d\x35\xb4\xaa\xa2\xdf\xd0\x89\xb3\x00\xe5\xab\x41\x56\xe6\x30\x3e\x83\xef\x04\x80\x03\x5a\x3c\x94\x1c\x34\x86\x43\x3e\x0a\x2f\x59\xa7\xb4\xa8\x9d\x90\xe6\xa1\xd5\x26\x87\x64\x55\x70\x5f\xc5\xce\x59\xff\x39\xfb\xcc\x9f\xbb\x3d\xba\x69\xca\x99\x0b\xbd\xfb\x74\xec\x31\x60\x50\x06\xba\x34\x61\x23\xb5\xd5\x39\x70\x4c\xc7\xe4\xfc\x12\x6a\x30\x3a\xff\x01\x74\x5c\xbc\x76\xfb\xe5\x67\x2a\xf6\x7d\xf0\x32\xfa\xf2\xd7\xc6\xdb\x96\x7f\x5b\x97\x2c\x7c\xea\xcf\x68\x3b\xe4\xce\xd0\x57\x1e\x9c\x32\xbe\x7e\x40\x76\xe7\x1a\xc0\x08\x3b\x29\xe6\x73\xbc\xaf\x48\x02\x1d\x04\x0f\x8b\x67\x5e\xb4\xc7\xc2\x5a\xe0\x1d\x9c\xb0\x0c\x38\x26\x03\x0a\x26\x47\x58\x16\xb9\x6e\xbb\xc7\x9e\x96\x01\x5b\x6e\x99\x9d\x34\x3b\x76\x56\xe2\xec\x7e\xb0\xfa\xc8\xf9\x36\x8b\x92\xc6\xd1\xd6\xb1\x49\xf3\x07\xa1\x8f\xbe\x72\x96\x2e\x4f\x78\x69\x04\x42\x89\x30\x33\x0e\xd5\x27\xc1\xf0\x84\x3f\x4d\xa3\xce\xd7\x2c\xac\x81\x83\x5f\x7d\xa1\x26\x63\x68\xcd\x8b\xaf\xa0\x05\xd4\xe2\xf2\x1a\x77\x51\x8d\xd8\x3f\x61\x91\x6f\x34\x3b\x93\xb3\x82\x58\x90\x88\x23\x6a\x25\x0e\x11\xf4\x9e\xb6\xd3\x82\x67\x77\x78\xd2\x28\x68\xb5\x59\x38\x0a\xe6\x7a\x2c\x8e\x45\x07\x60\xd1\x85\xa8\x83\x11\xef\xbf\x56\x55\xb2\xe1\xde\x32\x58\xb7\xf3\xc9\x33\xf3\x12\x0f\x26\x1f\xfb\x1b\xf4\x6c\x7c\x7f\xeb\x51\x58\x98\x77\x6f\xe1\x33\x54\xea\x0d\xb8\xfe\x4e\xe2\x88\x81\xdc\x7d\x77\xee\xca\x46\xb3\xbc\x5c\x66\x32\xb5\x66\x9b\x03\xc6\x41\xfe\x46\x5f\x7a\x6b\x01\xda\xeb\xbd\x4c\x47\xc3\x0c\xa5\xe6\x87\x65\xd8\xa3\xc0\x06\xe2\x71\xbd\x8c\xc4\x06\xce\x8d\xe6\x1d\x02\x1f\x52\xfd\x8c\xe0\x97\xd2\xdc\xdc\xa2\x86\x65\x89\x87\x4a\x2e\xd9\x61\x4b\x18\x0f\xcb\x5c\xb0\xa5\xfd\x62\xdb\x7d\x49\x8b\x33\xd1\x05\x3b\xda\x7a\x19\x66\xc0\x88\x96\xc7\x4a\x66\xb0\x99\xf0\x5c\xed\x86\x5a\x2a\xdd\x7b\x5e\xb0\x49\x59\xf0\x1c\xca\xa2\xa6\x6e\xa8\x5d\xf6\xe8\xe3\x00\x82\x30\x5f\x03\x73\x98\x3d\x8d\xb3\xa2\x84\x35\x8f\x39\x16\xd5\xd2\x29\x29\xad\x30\x07\xe1\x10\xaf\x7e\xc9\xf9\x44\x4a\xce\x27\xcc\xfe\xec\xd0\xa7\xd1\x81\x64\x6a\x5d\xe9\xdd\x83\xba\x2f\x9d\x5f\xf6\xe8\xa9\x19\x87\xbf\x8d\x1f\x97\xbc\xab\xcb\xca\x52\xb8\xce\xee\x2d\x77\x55\x96\x8f\x78\xfe\xd9\x77\xbf\xfb\xf4\x7a\x0c\xbc\x5d\x7b\x4f\x41\x6d\xde\xe8\xfc\xde\x29\x5d\xfe\x93\xdf\xf9\x93\x3f\xdf\x3d\xa8\x36\xab\x5f\x72\xad\xab\xa4\xdf\xe0\x94\x1e\x08\x8d\xfe\xf8\xc0\xc8\xde\x38\xc6\x15\xe6\xc3\xc3\x59\x81\x4d\x8e\x40\xa5\xd9\x48\x73\xd2\x4a\x44\x48\x41\x21\xfc\xe2\xa8\x45\xef\xc1\x21\x5f\x44\x1e\x8c\xac\x5d\xf3\xa7\xe5\xe3\xcf\x2e\xdc\xbe\xfd\x40\xd2\x21\xfb\x27\x5f\x42\xcf\xf0\xf2\xd3\xfb\x3e\xa2\xd2\xef\xc0\xfd\xff\x69\x39\x70\x58\xd4\xb0\xdb\x83\x22\x1a\x33\xc3\x7b\xa2\xc6\x5e\x6d\xd6\x6d\x4a\x82\xa9\x10\x3e\xfe\x5c\x7b\xfa\xdd\xce\xe8\x19\x6c\x2b\x6a\x00\x60\xd6\xb2\x75\x20\x16\xf3\x80\x75\x2d\x2d\x03\x7a\xec\xbc\x1d\x2b\x62\x38\xe4\xa1\xbd\x26\xe3\xa9\x8b\x59\xa8\xda\x01\x27\xb5\xdf\xba\x26\x83\xae\x4c\x46\xfb\xc6\xb4\x39\x96\xb4\x37\xe5\xf2\x51\xd8\x19\x1d\xa6\x66\xbf\xbb\xb1\x76\xf9\xe7\xb5\x03\x1e\xad\xdd\xbc\xdb\xe6\x5d\x8f\xbf\x1b\xe5\x6b\x60\x8a\xd8\x3a\xfc\xaa\x4d\x01\xc5\x17\x40\x7c\x52\xcc\xf2\xa9\x3c\x4b\xf7\x82\x1e\x3b\x05\xec\x29\x69\x4e\x4b\x54\xea\x9b\xed\xeb\x9c\x75\x43\x61\x42\x37\x38\x3b\x15\xad\x6d\x0f\x67\xa5\xa2\x35\x93\x76\xfd\x25\x0f\x26\x0d\x41\xcb\xd0\x5b\xdd\x37\xa6\xae\xa0\xf2\xff\x92\xb3\x32\xe7\x60\x0e\xac\x44\x37\x27\x1f\x9c\xbc\x7c\xd2\xc1\x29\x28\xb5\xf5\xe9\xeb\x68\x2d\x7a\xbd\x0d\x4f\x4d\x07\x00\xa2\x57\x69\x27\xb5\x82\x6f\x29\xd6\x22\xb1\x16\x96\x4e\xe5\x53\x2d\x7c\x2b\xe8\x4c\x45\xaf\x96\xc1\x52\x3b\x04\x73\xe1\xd2\x28\xb4\x7f\xfb\xcd\x8a\x93\x67\xa1\x85\xad\xf8\x79\x3f\x9c\xeb\x42\x2f\x24\xa0\x0c\x74\x60\x20\x1c\x81\x7e\xda\x75\x0b\x00\x06\x2c\xf2\x35\xb0\x47\xd9\x8f\x84\x48\x00\x38\x81\x4b\x88\x00\x5c\x90\xee\x1a\x25\xb9\x78\x7c\x45\xe7\x7f\xdc\xaa\xab\x71\xcb\x2e\xfc\xcc\x22\x7c\xe8\xf5\xd9\xc7\x7b\x66\x4e\xf0\xdc\xd3\xbd\xcb\x90\x8c\x5c\x97\xbd\x67\xef\x71\x53\x1e\x5b\x43\x3d\xf7\xc9\xab\x8b\x57\x7f\xbc\xbf\x7a\xdd\xb9\x8e\x69\x05\x23\x07\x65\xf4\xbb\x8b\xad\xbb\x5d\xc2\x80\x8f\x20\x48\xdf\xe6\x18\xfe\x78\x9f\x1e\x7d\x22\x92\x77\xe6\xac\xf7\x56\x9f\xbe\x55\xfb\xe4\x5f\x6f\xac\x5f\x9c\x9b\xff\xca\xc3\x33\x46\xd4\x00\x0a\xa4\xfb\xae\xd1\x75\xec\x29\x90\x80\x33\x71\xdc\xb9\x9e\x48\xbf\x09\x8b\xc4\x3b\x1f\x9c\x76\x95\xd6\x13\x72\x50\x0c\x26\xa3\xd3\x27\x8c\x7c\xed\xdd\x2d\x07\x87\x6e\xdf\x3d\xc3\xd5\x9b\x3d\xdb\x6a\xff\x6b\xaf\xbe\xff\x20\xac\xad\xe9\xd7\x31\x11\x9e\xfd\xa0\x5d\x7b\xf8\xdc\x1b\x07\x5e\xad\x9d\x7f\x68\xcd\x3d\x3e\xf0\xd6\xc4\xc9\xff\x7c\xe7\xec\x07\x8b\xed\x70\xf6\xb0\x6f\x56\x0d\x2e\xc0\xe7\x75\x71\x00\xf0\x9b\xd8\x3a\x10\x0e\x84\xfd\x4a\x26\x8e\x88\x04\x4b\x60\x87\x76\xc8\x51\x42\xe8\x2a\x38\x71\xb5\x99\x57\x6d\x67\xc3\x61\x1c\x74\xc3\x4c\x48\x59\xb3\x97\xc3\xd6\xe8\x34\xaa\x47\x28\x2c\xab\xed\x32\x7a\xb5\x93\x1a\xea\x44\xe1\x13\x5f\x9e\xfd\xf0\xfa\x31\x2f\x57\x3d\xb6\xfa\x5c\x49\xc7\xfe\x9d\x3b\xa4\x65\xf4\xcf\x64\xeb\xee\x7c\xf3\xc1\x25\xaa\xfa\x76\x09\x93\x30\x14\xfd\x54\xe4\x5d\x75\xf4\x28\x65\x5f\xfa\x8f\x99\x9b\x97\x2d\x3c\x53\xb5\x66\xc1\xc4\x41\x9b\xfb\x66\xf6\x18\xb6\x11\x30\x60\xa5\xaf\x81\x9b\xca\x9e\x06\x6d\x41\x12\xe8\x08\xba\xc8\xbb\x36\x26\x4a\x7c\x16\xaa\x03\xe5\xb1\x46\x31\xae\x2e\x1d\xa2\xdc\x5d\xa9\x0e\x8e\x14\x86\x82\x91\x76\x69\x77\x1c\x07\x5d\x5d\x70\x24\xb7\xf2\xaf\xb0\xf2\xe3\x93\xb0\xe2\xb3\x53\xe8\xa5\x33\x67\xd1\xce\x13\x33\xf7\xc1\x8c\x7d\xfb\x60\xc7\x57\xf7\xa1\xcf\xf7\xed\x43\x5f\xbc\x0a\x17\xc2\xac\x3d\xcf\xbd\xfc\xe4\x9e\x35\x7b\xef\x1e\xf5\x0c\x75\x51\xf8\x0b\xef\xa3\x9d\x9f\x7d\x82\x5e\xfa\xf8\x2c\xac\xf8\x50\xf8\x19\xd5\xdf\xf1\x6e\xa0\x17\xd7\x3c\xfd\xf8\x8b\xe8\x18\x7c\x6f\xe7\x88\x81\x38\x87\x8f\xba\xca\x6e\x67\xeb\x00\x2f\x9e\x24\x89\xa7\xf8\x30\xd2\x15\x0f\x5d\x91\x8e\xc8\xae\x1e\x87\x10\x76\xc7\x44\x47\x2e\xa0\xc2\x3e\xaa\x86\x4f\x1e\x39\x74\xec\xe0\x62\x2e\xec\xc4\xa4\xb7\xc3\x38\xb6\xe4\x81\x07\xbc\xcf\x51\xf7\x7b\x9f\xa3\xce\x79\xcf\x53\xe9\xde\x2c\xb8\x2f\xa7\xd8\x7b\x91\x4a\x1d\x9a\x81\x46\x02\xe8\x3b\x0f\x00\x5b\x87\xfd\x5a\x08\x37\xcb\xc1\x2e\x92\x43\x7c\xe7\x73\xa6\xef\x12\xb3\x96\xa9\x04\x36\x10\x2b\xd8\x6b\xe9\x14\x2b\x2a\xda\x1e\x29\x1e\xc9\xd8\xb0\x1e\x50\xf1\xd0\x1e\x29\x04\x50\xfc\xcc\xc5\xb7\x37\x6f\xfa\x75\x79\xe3\xc9\x9c\xdd\xa5\x4f\xbc\x51\x5a\x3c\xe1\xc2\xa6\xe7\x6f\x2c\xdd\x36\x88\x1a\xd9\xe5\xc5\xf2\x57\x1f\xa6\xa2\x76\x00\xdf\xc6\x67\x90\xf7\xcf\x68\xab\xbb\xff\xd4\xc7\xd3\x9f\x7b\x64\x3d\x64\xa9\x1f\x51\x4b\x18\xed\x2e\x9c\x2f\x9e\x1b\x7b\x7c\xb7\x38\x1b\xe6\xb0\x15\x88\xc4\x73\x0d\x5d\x16\x87\xd3\xc1\xd3\xc2\xfa\x74\x65\x41\x37\x0f\xf1\x89\x90\x10\x94\xa7\x91\x63\x72\x0f\x5c\x76\x7e\xec\x9b\xe1\x97\x86\x5b\xf1\xfa\xec\xb9\x34\x92\x4a\x84\x7b\x73\x47\xe7\x2e\xca\xcf\xdc\xb2\xf9\x89\xf9\x0f\xe5\x4f\x2e\xeb\xd8\xa9\x5b\xee\x80\x21\xcf\x6d\x58\x4c\xdd\xa4\xde\xf3\xf6\xae\xad\xf5\xb6\xc4\x0b\x34\x7d\xaf\xdd\x51\x7c\xa7\x62\xa7\x2d\xb1\x7b\xbb\xe4\x98\xe2\x47\xa7\x2c\x72\x6d\xcc\xb0\xc7\xda\x3a\xd8\x92\xee\xe9\xfb\xe0\x62\x7c\xee\xf9\x11\x00\xf4\x36\xa6\x12\xb4\x10\xf6\x98\x76\x8b\x5d\xf8\x87\xce\xcf\x82\xef\x76\x43\x53\x73\xe0\xc6\x91\x30\xf3\xda\x55\xd8\xe6\x2a\x5c\x7e\x67\x27\xe6\x71\x86\xef\x3a\x77\x10\xef\x7f\xc2\x71\xdc\x9e\xea\xa2\x1d\x96\x5c\x0f\xd7\x16\x0a\x42\xa5\xca\x7b\x8c\x0c\xe8\x91\x63\x26\xde\x29\x1f\xba\x45\x4b\x66\x67\x06\x5c\x7d\xf6\xc8\xff\x63\xef\x6d\xc0\xa2\xba\xce\x85\xd1\xf7\xdd\x7b\xed\x3d\x03\x22\x32\xfc\x38\x12\x44\x1c\x27\x23\x21\x04\x11\xc7\x61\x44\xe4\x47\x54\x44\x24\x46\x09\x21\x86\x20\x22\x12\x82\x24\x84\x18\xb4\x84\x52\x3a\xa5\xd4\x4c\xd4\x18\x8b\x24\xc6\x28\xb1\xd4\x72\x3c\x7e\x1c\x8f\xa5\xd6\x18\x6a\xac\x09\xa1\xd6\x50\x6b\xf3\x59\xcb\xa1\xd4\x63\xad\xb5\xd6\xd8\x98\xc4\xda\x1c\x6b\x86\x99\xb5\xef\xb3\xd6\x9e\x19\x86\x3f\x35\xf9\xce\x77\xef\xfd\xee\x73\x49\xb6\x1b\x66\xd6\xbb\xde\xff\x9f\xb5\xf6\x5a\x6b\xdf\xca\x9b\x14\x15\x94\xde\x38\x91\xb3\x25\x58\xeb\x1b\x72\x4a\x66\xa7\xda\xa6\x15\xe4\xad\x99\x1d\x97\x5f\x96\xfb\xea\xbf\x7d\xf7\xcd\xb2\xea\xdd\xff\x71\x78\xe9\x36\x72\xe2\xb6\xf3\x35\xdc\x56\x59\x32\x21\x6e\xc5\xc0\x55\xc6\xd9\x03\xef\x67\xa5\xcc\x35\x99\x5b\xe7\x24\x3d\xf0\x40\xc6\xce\xc2\xaa\xd2\xfc\xea\x28\xad\x61\x5b\x63\x4b\x94\x7b\x3c\x74\x43\xbe\xcd\x6b\xbd\x48\x58\xc0\x72\x84\x29\x55\x70\x93\xe2\x75\x7a\x36\x72\xf6\xbb\x67\x8a\x23\x8c\xa8\xab\x9a\x17\x69\x36\xe6\x97\x95\x66\xb7\x3d\x57\xd7\xfc\x50\xf1\xb6\x06\x7c\x32\x86\xbe\xa0\x92\x6f\xbc\x03\xf9\x42\xf6\xfe\xf3\x4f\xa6\xce\x99\xfc\xe0\x03\xb9\x7b\x93\xe6\x7d\x7b\x4d\x66\xc5\x53\x65\xab\x3f\x74\x1d\xbd\x1b\x23\x12\xac\x51\x3e\x96\xb7\xba\x65\x3d\xdd\xfd\x8e\xd4\x61\xf2\xfe\x2a\xd3\x9a\x6b\x46\x8a\x7d\xe2\x5d\x66\x3a\x47\x8a\xfe\xb7\xf7\x3a\xf5\x09\x12\x14\x2a\x1f\xcb\x17\xa4\x1e\x30\x41\x0c\xcc\x87\x1c\xc8\x67\x91\xe4\x5e\xc4\x1d\xf2\x55\x59\x2b\xbc\x83\xfc\xed\x2a\xab\xe4\x2e\xac\x0a\xeb\xc7\xd4\x85\xeb\xc0\x57\xe1\x5c\x82\x32\xe5\x63\xf9\x34\xaf\x95\xa7\x40\x22\xcc\xe7\xeb\xc7\xc6\x9e\x8b\xff\xca\xcc\x96\x8d\x31\x79\x9f\xa1\x32\x2a\xdc\x8d\xd1\x91\x73\xfc\xae\x53\x5f\x81\x41\x09\x5e\x53\x3e\x96\xb7\xf1\xf9\x79\x7f\x98\x06\x71\xfc\xbd\xa9\xea\x64\xfc\x57\xb6\xc9\xd7\x06\x67\xef\x2f\xdf\x9b\x49\x7a\x26\xf9\x55\x07\xba\x47\x9a\x51\xb9\xae\x5c\x17\x1b\x49\x35\xcb\x66\xd1\x56\xa6\x0b\xef\xc2\x78\x8b\x67\x6e\x98\x18\xa7\x85\x16\x5a\xca\x33\x1e\xdb\x92\xf3\xe4\x8a\x94\x6f\x16\x66\xfd\x60\xdd\xa9\xfe\x9d\xf4\xe6\xc1\x77\xcc\x7f\xd5\x1b\x1b\xff\xf8\xed\xe2\x35\xc6\xf8\x5b\xa6\xd8\xff\xf8\x65\x2f\xdd\x7f\x1c\x10\xf7\x41\xa9\x5c\x24\x2c\x84\xf1\x00\x68\x49\xb4\x9a\x65\x8d\x21\xcc\x30\x51\x6f\x9c\x8e\xfb\xb6\xdb\xb2\x52\x93\xc4\x0b\x4e\x63\x52\x6a\x96\x0d\x33\xee\xcf\xda\xd9\xb0\x30\x7f\x61\xc3\x4e\xbe\x16\x29\x48\xe9\x16\x6e\x10\x9b\x17\x6e\xa2\x3e\x6c\x7a\xb4\xce\xa8\x93\x31\x68\x67\x96\xbb\xa9\x18\x93\x65\xdb\xbe\xdd\x96\x95\x32\xd7\x69\x14\x2f\xcc\xe5\x70\x43\xf0\x19\xa6\x47\x33\x40\x59\x63\x4c\xb4\xe2\x3e\xf1\x02\x43\xb4\x9d\xa3\xc5\x18\x86\x49\xed\x68\x38\x3e\x93\x65\xa2\x5e\x67\xd6\xb1\x5a\x50\x63\x9c\x8e\x41\x2a\x55\x59\xf7\x67\x9d\xf5\xa1\x77\xfb\x76\x18\x82\x4f\x3f\xc8\x9f\x0f\x52\x5f\x4e\x05\x3a\x88\xde\x25\xf8\xf0\xec\x25\x64\x38\xef\x7a\x37\x2d\xb2\x66\x50\x02\x3e\x54\xf9\xc2\xb9\xa9\x13\xe8\xdc\x14\x8f\x4c\x54\x1c\x2a\x9d\x02\x06\x29\x59\xbc\x4f\x56\xff\x82\x64\x08\x33\xe8\xc6\xec\x19\xff\x44\xa7\x8e\xe8\xbd\x7c\x39\x6e\x1e\x1b\x81\x00\x39\xca\x75\x52\x2d\x9d\xf6\x7d\xfe\xa5\x8f\xe6\x55\x82\x2e\xd1\x3c\x2b\x98\xaf\x55\x54\x5f\x20\x1a\x6c\x65\x1f\x07\x62\xce\xf6\x4f\x76\x6e\xce\x13\x02\xaa\x4a\x37\xdb\xdf\x7c\xe7\x2f\xff\x6c\xa7\xe7\xdf\x3b\xf5\x5b\x9c\xbf\xae\xbc\x2d\x3a\x74\x85\x25\xb3\x7a\x09\x6e\x6f\x47\xeb\xde\x05\x81\x9b\xaa\x0b\x50\xc8\xa5\x7f\xa6\x9f\xd0\x2f\x69\xc6\xd5\xdf\xbd\xb3\x0b\xb5\x7f\x7d\x20\xf1\xd9\xdf\x83\xa0\x9c\x06\x20\x25\xd2\x71\x90\x20\x80\x65\x67\x34\x84\x68\xd0\x20\x4e\xb7\xc8\x1a\x8b\x51\xb0\x63\xf1\xb6\x68\x17\x11\xa4\x1c\x6d\xd0\x83\x47\x24\xad\xe3\xe6\x21\x14\x84\x5b\xc5\xa9\xd6\xc7\xd9\x58\xa6\x8b\x5a\xf9\x1c\x0d\x5f\x2d\x65\xe0\xff\x75\x91\x1f\xd2\x6e\x57\x3f\xb5\x6a\x6c\xb7\x1b\xe4\xfa\x2f\x1b\xf9\xb3\x36\x6a\x95\xf2\xf8\x73\x78\x08\xf1\x43\x8b\x21\xcc\xe0\x87\x86\x30\x43\x9d\x90\xe6\x3a\x4b\x5e\x75\x05\xe0\xa7\x2e\x87\x98\x35\x10\x4d\x2f\x89\x19\xc2\xa7\xfb\x9d\xae\x2a\x57\x00\x05\x84\x4a\xa1\x94\x98\xc4\x34\x10\x61\x4a\x7a\x08\xc2\x77\x9f\xd8\x8e\x58\x8c\x78\x03\x31\x1e\xab\x50\x40\x88\x5f\xb5\x6a\xfd\xfa\xd8\x84\x99\xac\x76\xac\x14\x3b\x85\xd2\xf3\xe7\xef\xfe\xac\x1d\xa1\x51\x88\xc1\x2b\x62\x3d\xa7\xc7\x67\xa4\xd2\xe8\x5d\xf9\xf2\x8e\x67\x81\x0b\x42\x89\x72\x53\x4a\x92\x2f\xf0\x35\x54\x16\x03\x8b\xa3\x46\x2c\xc1\xcc\x33\x78\xed\xbc\xab\xe5\x28\xfd\x87\x70\xae\xd7\xd5\x23\x3d\xfb\x65\x98\x70\x89\xd7\x05\x9b\xb0\x4e\xca\x21\x46\x08\x85\x29\xf0\x80\xbb\x7f\xbd\x17\x47\xb4\x7b\x24\x30\xd1\x3c\xcb\xca\x02\x83\xe4\x9d\xf5\xd9\xf4\xf6\xb6\x9f\xac\xaf\x3f\xf0\xca\xe1\xa3\x2f\x77\xd4\xa5\xec\x78\xf8\xd5\x23\x67\x16\xcd\x5d\xb9\x6c\xe9\xaa\xb9\x0b\x04\x79\x79\xc1\xdc\x05\x59\xd6\xc7\x85\x73\xdf\x7f\xff\x50\x7b\xe7\xee\x57\x7f\xd1\xb1\xbc\xa0\x73\xd7\xbc\x25\x76\xfb\xb2\x94\xcd\x2b\xe6\x24\xab\x7c\xe1\x2e\x00\xb9\x98\x9c\x02\x09\xc0\xa0\x33\xeb\x0c\x61\xb8\xab\x88\x54\x90\x53\x03\x6f\x14\xf1\xef\xf5\x0a\x25\xed\x44\x0b\x21\x30\x25\x3d\x20\x04\xfc\xc7\xc1\xb8\xd0\xb0\x71\x30\x81\x3f\x47\x9f\xa5\x0b\xc6\xa4\x24\x9d\x59\x67\x4e\x98\x29\xe9\xf8\xc8\x65\x0a\x86\xb1\x3a\x9c\x57\x8b\x3a\xd4\xbf\x70\xb6\xb1\xf1\x5c\x4d\xd9\xc9\xd6\x7d\xef\x0b\x02\xbc\x7e\x63\xd3\xa6\x9b\xcd\x14\x04\xe1\xc4\x5f\x2e\x75\x53\xfe\x4c\x82\x86\x8a\x39\x72\x28\x4c\x04\x08\x9b\x68\x9e\x65\xe1\xc3\x30\x7d\x98\x0a\xcf\xd9\x7f\x72\xc1\x73\x1f\xbc\x5b\x99\xff\xc4\x22\xf3\xbc\x5f\x74\x56\xe6\x9f\x8c\x7e\x95\xdc\xfe\x59\xd7\x03\x74\x7a\xd6\xfc\x01\xf2\xee\xfb\x31\xea\x33\xad\x4a\x2c\x24\x26\x92\x01\x13\xf9\x53\x20\xfe\x1c\x4b\xcf\xc2\xa9\x3a\xb8\xe4\x5e\x21\x8b\x83\x1f\x27\xfa\x7e\x5e\x59\xb6\x3b\xb9\x74\xcd\x92\xc7\x66\x3e\xfb\xed\xa7\xdf\x4c\xaf\xc8\x5f\x96\x1b\x6f\xae\x4d\x29\x6d\x49\x2e\x5d\x93\x5e\x34\xd3\xfc\xcd\x14\xfe\x3d\xfb\xf4\x9b\x58\xf8\xf1\xb3\xfa\x07\xa2\xc2\x6b\xaf\x56\x4e\xbe\xdf\x30\x71\x1e\x3e\x7a\xf5\x59\xfd\x03\x11\x93\x53\xe6\xb1\xcf\x0d\x13\x53\x18\x4f\x95\xb0\x9d\x98\xa4\x70\xbe\xdb\xd2\x62\xb0\x1a\x2c\x86\x10\xbd\xc6\x1c\x66\x60\x61\x58\x8c\xb6\x56\x62\xf2\x72\xba\x11\x3f\x6f\xec\x29\xec\xa7\x1f\x3c\x82\xdb\x68\x80\xad\xe7\x09\xdc\x77\xbe\xbd\x1f\xc3\xf3\xbb\xfb\xdb\xcf\xd3\x4f\xf3\xde\x03\x11\x4a\xe1\x0b\x92\x45\x96\xbb\xd7\xc5\xa4\xa7\x4f\xd7\x02\x19\x27\x6a\x88\x26\x60\x3c\x59\x2e\xa1\x04\xab\x11\x51\x2b\xa1\x38\xc1\x2f\xde\x2f\xcd\xaf\xca\xef\xa2\xdf\xe7\x7e\xb2\x1f\xc4\xaf\xd2\x9b\xe3\x57\xb1\xff\xdd\xfa\x31\xeb\xcc\xe6\x84\x99\x56\x8b\x21\x0c\xdd\x57\xa9\xf8\x17\xe7\x64\xf5\xfa\xa2\xb9\x19\x4b\x5f\x7b\x8d\x5d\x4c\x8e\x00\x24\x5a\x4a\x01\x11\xfc\x01\xcc\xbc\x35\x86\xf9\x21\x73\x15\x67\xb6\xd8\xe9\xaa\x17\x1a\xcf\x9f\x17\x4e\x7c\x1f\x3f\xff\x9c\x7e\x40\x3f\xbe\x01\x6e\x18\xd3\x50\x18\x3f\x06\xc6\x60\xb2\x84\x46\x57\xbd\xd8\x79\xfe\x3c\x6a\x6f\xe0\x24\x4c\xfd\x9c\xea\xbe\xcf\x60\xf6\x02\x10\x2b\x69\x00\x02\x7e\xcc\xb2\x24\x20\x32\xc8\xfe\xe3\x24\xd0\x0a\xc3\x2d\xcb\xac\xf3\x43\x9d\xc9\xa0\xf3\xc3\xbd\xf8\x6b\x3c\xe3\x7c\x47\xf8\x92\x36\xd2\xef\x09\x75\x82\xec\x72\xb8\x36\xe5\x0a\x32\xb6\xd3\x7c\x2e\xf7\xdb\xdc\xf7\x25\x00\x2b\x5f\xe3\x55\x29\x76\xba\x8c\xb7\x85\xc5\xe7\xe9\x6b\x00\x28\x18\x69\xa8\x78\x4e\x6e\xe7\x67\xa5\xe8\x06\x9d\x38\x7a\x7a\x34\xab\xf6\xe4\x30\x9d\x60\x3c\x50\x9f\x96\x63\x36\x45\x05\xe8\xa6\x1b\x74\xd3\xc6\xc9\x34\x54\xfe\xcf\x5f\xdc\x4a\x8f\x8f\x31\xfb\xfb\xc5\x44\x47\x1b\xd7\xdd\xde\x04\x88\x84\x86\x0a\x47\xe4\x76\x08\x75\xaf\xd9\xd5\x4f\xd4\x73\x9f\xd4\x99\xb9\xc5\x4e\x47\x62\x36\x1a\xc3\xfd\xa7\x44\xe9\x26\x87\x37\xed\xdb\x94\xb4\x9c\x36\x44\x5b\x82\x48\x8c\xc9\x6c\xd3\xd4\x7f\x69\xec\xbe\x95\xaa\xae\xed\xb8\x25\xec\x97\x8e\x88\x56\x10\x41\xf7\xb6\x28\x81\xba\xd4\x4d\x87\x9c\x69\xd1\x62\x08\xf3\x97\x4e\x08\xfb\x9b\xf8\x3a\x37\xec\xa3\xa1\x42\xb9\xa6\x87\xc5\x27\xd4\x99\x75\xd8\xd7\x44\x43\xfd\xde\xbe\xb5\x94\xf1\xb5\x8d\x86\xf2\x7e\x24\xf6\x1d\xe3\x5b\xd8\x26\x46\xbb\x9e\xa1\xa1\x92\xb1\x69\xe0\x39\x37\x2e\x1a\x2a\x46\xf1\x36\x93\xd2\xfd\x40\x24\x44\xd6\xb8\x97\xd6\x31\x49\xeb\xcc\xb3\x38\x4a\x9d\x51\xe7\x2f\xc6\xec\x10\xf6\x37\x39\x2e\x90\x1d\xbc\x6f\x46\xa3\xa6\x47\xed\x9b\xc5\x07\x61\xdb\x0e\xe1\x75\x61\xbf\x64\x1c\x78\xae\x49\xe5\x41\x8c\xe2\xdf\xb3\x7e\x25\x41\x90\x35\x80\x22\xc4\xc7\x9b\x87\xf4\x6b\xd6\xf9\x0b\x6f\xb0\x7e\xc9\x0e\xc7\x05\x2f\xcd\x9a\x1e\xbe\x97\x87\xf7\xcb\xa8\xde\x21\xbc\xce\xc8\xf6\x7b\x7b\xe0\x39\x95\x70\x37\xdd\xbc\xdd\xe4\xf4\x71\x20\x09\xb2\xac\xf5\x03\x94\x19\x06\x0f\x8a\x41\x1c\x46\x8e\x45\x45\x73\x6b\x29\xd9\xa1\xc2\x73\xd9\x68\x98\x95\x89\x7e\x20\xb1\x0e\x64\x95\xf5\x59\x1e\xde\x3d\x02\xe7\xfc\x4b\x27\x5c\xcf\xb0\x2e\x9a\x06\x9e\x63\x22\xf0\xe8\x89\xd3\x30\x25\x3d\x40\xc3\xb9\xd4\xfa\x81\xa4\xb2\x69\x1e\xda\x07\xe7\x85\xf3\xfa\x3a\x27\x83\x49\x09\x3c\x74\x68\x7a\x60\x1c\x3c\x90\xae\xd3\x8c\x07\xc9\xcf\x4f\xf0\xf7\x0f\x18\xaf\x05\x09\xfd\x55\x6e\xcc\xb3\xdc\xfc\x0c\xeb\xcd\xe0\xe6\x8b\x09\x67\x87\xa7\x53\x95\x38\x41\xb9\x85\x37\xa5\x23\xe2\x75\x1e\x23\x12\xd3\x23\x45\x8d\xc6\x0f\x08\xd1\x92\xd5\x12\x8a\xd2\x01\xc0\x0f\x01\x65\xe8\x40\x9c\xa0\xae\x6f\x5e\x65\x5e\xbd\x6a\x7d\xfc\xea\x55\xaa\x99\xe9\xbc\xa6\x86\xaa\xb9\x39\x32\xa4\x13\x78\xb3\xa9\x09\xcb\x77\xa8\x67\x2e\x60\x3f\xf3\x19\x6e\x77\x6e\x4d\xb1\xff\xb0\xbf\xe9\xf7\x6e\xfb\x1b\x6a\x83\xd7\xd9\x78\x9d\xdb\x60\xd8\xa0\x1d\xaa\x4a\x95\x7e\xbf\xa3\xaf\xc9\x39\x8d\xd9\x72\xbf\x5b\x27\x9e\xb6\x7c\x11\x16\xf6\x8b\xe7\x69\x54\xd3\xef\xdd\x56\xcb\x98\x74\xe3\xe7\xfd\x4a\x2c\xf3\xaa\xad\x55\x99\xb0\xf6\xce\xa3\xbf\x17\x5e\xa0\x51\xbc\x73\xc7\x31\x52\xa5\xf6\xef\xb6\x75\x46\xcb\xdc\xf4\x28\x02\xa0\x11\xb4\x5a\xff\x71\x2c\x5a\x8a\xa8\x3d\x40\xf0\x43\x82\x32\xe9\x90\x70\x02\x8b\xa1\x1e\x99\x70\xa1\xb8\xed\xc9\x2d\x15\x8b\xba\xea\xd3\x5f\x78\xc3\xb5\x4e\x8c\xd9\x81\x37\x9b\xfa\x76\x38\x1e\x10\xff\xe8\xc1\x71\x8e\xf3\x30\x2d\x3d\x10\x34\x5a\x91\x68\x89\xff\x38\xa2\x95\xdd\x96\x65\xf6\x06\x30\xaf\x67\x19\xb9\x77\x5d\x68\xfa\x7d\x93\xdb\xbf\xbc\x3a\xe4\x7d\xb9\x79\x54\xdb\xa2\x1b\xf3\x86\x26\x1a\x29\x5e\x68\xc2\x9b\x4d\x03\x4d\xe2\x1f\xb1\x7c\x87\xe3\x01\x29\x93\xcb\x9b\xe9\x5d\xd3\xa3\xca\xd0\xec\x96\xb8\xdb\x83\x84\xd7\xf1\xa6\xd4\xe7\x34\xee\xe8\x53\x63\x47\xbf\xdb\x7e\xfd\x06\x35\x68\x08\xe3\x3a\xc4\x4b\xaa\x27\x7b\xec\x54\xc0\x7e\x77\xbf\x6e\x79\xf3\x96\x9e\xf6\x62\xb6\xeb\xd5\x26\xbc\xc4\x3a\x77\x1c\x6b\xc2\x72\x52\xe5\x34\x72\x1f\xc3\x9b\xdc\x47\xfd\x60\x4e\xfa\x14\x02\xe0\x27\x0b\x82\xff\xb8\xe1\x82\x66\xc9\x4a\x03\xf1\x3c\x31\x71\x91\x8f\x26\x6d\xb3\x2a\x6d\xe1\x0d\x55\xda\xe2\x05\x47\x8c\x37\x56\x72\x3b\xf4\x53\x25\xa4\x72\xe1\x8f\x97\x55\x69\xaa\xb2\x64\x91\xc5\xed\x13\xbc\xad\x57\x9e\x66\x2e\x4f\xb3\xce\x5f\xcc\x69\x72\x1a\xf1\x32\x93\xa7\x94\xe9\x88\xc1\xf2\x1d\xe2\x85\x81\x26\xdf\x78\x34\xce\x57\x9e\xde\x98\xe4\x89\x4b\x5c\xa6\xce\x69\x1e\xbb\xe4\x7e\x31\xce\x57\xaa\x06\x9d\x5b\xae\xcc\x2a\x55\xff\xf0\xc4\x32\xd1\x07\xc6\x8f\x9f\x0f\xe6\x85\x11\xbd\x1a\x61\xe6\xdc\xc4\xc0\x39\x30\xb7\x68\x29\xd3\x2b\x67\x77\x2c\x1c\x07\xa9\xe9\x06\x55\xce\x2c\x84\xa8\x86\x3d\x4c\xdc\xfe\x4c\xd4\xbe\xfe\xae\x0a\x7b\xb8\xb4\x8d\x5e\x79\x7b\x04\x7e\x6b\xa9\xf8\x47\x8f\x4d\xf2\x98\xe7\x95\x21\x9f\x67\xe5\x32\x6f\xc2\x75\x4d\xde\x20\x3b\xf0\x9c\x1a\x03\x44\x2f\x8c\xa4\x9e\x56\x31\x68\xc9\x66\x5d\x08\xd7\x2c\xb3\x66\xae\xb2\x41\x7b\x66\xf2\x77\x1c\x53\x7b\x70\xfb\x02\xf7\x77\x86\x37\x23\xdd\x38\x4e\x14\xc7\x6b\x81\x45\xed\x80\xf1\x44\x65\x54\x3e\xa0\xc5\x0f\xb5\x28\x6b\x3b\xfc\x70\x82\x1f\xfa\x0d\xf1\xe0\x59\xde\x68\x3c\x18\xdb\xdc\x54\x84\xa9\x91\xdd\xb5\x4e\x0d\x71\xce\x69\x1c\xbf\x6f\x8e\xe0\xb1\x59\x1c\x0f\x7e\xfe\x92\xec\x2f\x07\x8c\x97\xfd\x89\x56\x75\xe7\x21\xfe\xec\xdb\xaf\x51\xcd\x18\x2c\x70\x35\x79\x72\x86\x3b\x6f\x88\x5e\x5e\x24\x55\xdf\x5e\x79\x84\xa9\x71\x4c\x95\x87\x74\xc2\xf5\x2a\xd3\xfa\xa0\x48\x06\x43\x99\x27\xbe\xbb\xed\x2c\x3d\x7d\x9a\x66\xdc\xb8\xf1\xa0\xd5\x4a\x82\x10\x30\xde\x13\xdd\x25\x77\x78\xd7\xae\xf6\x43\x3f\xd1\xeb\x61\x83\x2e\x36\x6b\x58\xa4\x57\x73\x14\x8b\xf6\x3c\xab\xb8\x03\x3e\x1b\x65\x0f\xcd\x77\x5c\x1e\xe3\xc6\x83\x24\xf8\xc9\x82\x1c\x30\xde\x4f\x02\xd4\x88\xac\x66\x30\x9b\x47\xca\xc3\xeb\x03\xaa\x57\xb2\xd0\xe2\xf6\x4b\x35\xb6\x88\x3e\xbc\x78\xe4\xe1\xa6\xc6\x3c\x48\x91\x1b\xd6\x4b\xd3\x40\x93\x6a\xfd\xbe\x39\x34\x04\xf2\xd3\xe3\xc6\x4d\x98\x10\xc6\x7c\x60\xbc\x4e\x27\x0b\xc1\xc1\xa1\x61\x41\x30\x9e\xdb\x47\x00\xf1\xb8\x82\x9f\xdb\x17\x82\x3d\xbe\xc0\x45\x62\x66\x76\xe2\xcd\xb5\x66\x35\x02\x79\xe5\xe3\xf6\x0b\x8f\xff\x0f\xfa\x87\x27\x0c\x78\xfc\xc4\x1d\x0a\x58\x36\x18\x4a\x1b\xf8\xca\xc2\x6b\x23\x6e\xbe\x3c\x86\xe2\x15\xcc\xa0\xc1\x10\x6f\x1f\x12\x9f\x97\xd7\x0f\xf7\xa0\xc1\x48\x31\xe8\x49\x9e\x78\x31\xdc\xa1\x86\x44\x0e\x3e\xce\x12\x3e\x93\xda\xd5\xfa\x31\x1c\x0d\x3a\xa9\x5d\xf8\x8c\x9c\x1f\x70\xaf\x0b\xa3\xa1\xec\xef\xc1\xef\x68\x28\xf9\xc3\xc0\xf4\xc1\xef\x7c\xe1\x3c\x65\xa7\xfa\x9d\xd0\x3b\xf8\x9d\xd0\x3b\xf8\x1d\xfb\xdd\x03\x87\x3a\xf6\x9d\xf7\xdb\x07\xa1\x8c\xd6\x48\xed\x1a\x93\x7b\x5c\x33\x81\x9f\x27\x32\xb8\x9e\x2a\x1e\xcc\x60\x85\x64\x48\x83\x05\xb0\x18\x96\xc2\x23\xf0\x28\x3c\x0e\x4f\xc2\x6a\x58\x0b\x4f\xc3\x33\x50\x05\xd5\x50\x03\x75\x60\x83\x46\xb0\xc3\x56\xd8\x0e\xcd\xf0\x06\xec\x81\x1f\xc0\x8f\xe0\x5f\x01\xf4\xe6\x30\xa3\xce\x62\x0e\x13\x87\x5d\x21\xec\x3e\xca\x77\x21\xff\x0f\xb5\x2f\x5b\x37\xf8\x33\xd6\xef\xe5\x3e\x3f\xeb\xca\x06\x7f\xc6\xfa\xbd\x7c\x2d\x36\xae\x5d\x8b\x9b\xd6\xac\xc1\xef\x15\x17\x63\x43\x49\x09\x36\x16\x17\x7f\x69\x29\x2c\xa4\x17\x8a\x45\x52\x54\x84\x8d\xee\xcb\x56\x52\xf2\xe5\xae\xff\xdb\x5b\x43\x1e\xc0\xff\x46\xdd\xff\x1b\xfc\x18\x7e\x0a\xef\xc0\xbb\xf0\x1e\x74\xc3\x29\x38\x0d\x1f\xc1\x39\xe8\x83\xf3\x70\x11\x2e\xc3\x55\xf8\x04\x3e\x87\x7f\xc0\x3f\x61\x00\x14\x14\x51\x83\xe3\x70\x02\x86\xa0\x1e\x23\x30\x0a\x8d\x18\x8d\xb1\x18\x8f\x66\xb4\x62\x32\xa6\xe1\x02\x5c\x8c\x4b\xf1\x11\x80\xb0\x31\xf4\xaa\x1b\x43\xaf\xba\xff\xbf\xfd\x1d\xdb\xfb\x9a\xae\x8f\xd5\x7f\x85\x4f\xcb\x47\xfd\xf9\x9a\x9d\xf9\x7c\x2a\xff\xbf\xc5\x4d\xfe\x4f\x6d\x0d\xb0\x80\xe7\x8b\x5e\x8d\x09\x96\xc0\xc3\xb0\x02\x1e\x83\x27\x60\x15\xac\x81\xa7\x60\x1d\x54\xc2\x7a\xd8\x08\xb5\x50\x0f\x0d\xb0\x09\x36\xc3\x36\x68\x82\xd7\xe1\x4d\x78\x0b\x7e\x08\xff\x02\xff\x03\xfe\x1d\x7e\x02\x6f\xc3\xcf\xe0\xe7\xd0\x05\x27\xa1\x07\xce\xc0\x59\xe8\x85\x7e\xb8\x00\x97\xe0\x0a\x5c\x83\x4f\xe1\xef\xf0\x5f\xf0\x25\xb8\x10\x51\x42\x3f\x1c\x8f\x3a\x0c\xc3\x70\x8c\x44\x03\x9a\x30\x06\xe3\x30\x01\x2d\x98\x84\x29\x38\x1f\x17\xe1\x12\x7c\x18\x57\x00\x84\xe9\xcc\x16\xe3\xb0\xcb\x1c\x36\xd6\x65\x0c\x33\xeb\x46\xb9\xd8\x98\x33\x05\x19\x70\x98\xd9\x22\x0e\xeb\x30\x64\xb4\xcf\xfe\x3f\xdc\xb6\xc2\xf3\xf3\x0c\xff\xaf\x92\xfd\x53\xf1\x8c\xef\x8f\x23\x76\xe8\xdf\x15\x83\x3f\x5f\xf5\xf3\x4a\xdf\x9f\xd1\x9b\x0c\x01\xae\x18\xfd\xa7\x1c\xa7\xae\xc5\x69\x6b\xd8\xbf\x86\x12\x34\x14\xfb\xfe\x74\x97\xd0\x8b\x45\xf4\xbc\xfa\x3f\x33\xf6\xb5\x68\x58\x5b\x52\x48\x1b\x8a\x8b\x85\xb6\x22\x34\xf1\xff\x0d\x25\x5f\x26\xae\x5d\xeb\xdb\x8b\x23\xff\xff\xa8\x26\xea\xfe\x25\xb8\x45\x0a\x48\x2f\xab\xc9\xac\x3a\x83\xae\x4e\xbc\x78\x4b\xbc\xe8\x34\xf0\xf9\x73\x19\x80\x7c\x44\xdc\xf3\x3c\x66\x9d\x41\x67\x32\xe8\x0c\x32\xe9\x19\x68\x24\x09\x03\x1f\x91\x9e\x01\x6b\x0e\x49\x00\x84\x4a\xb4\x09\xe5\x62\x1d\xdf\xaf\xa8\x33\xe8\x2a\x71\x00\x6d\xe8\xa4\x44\x9d\x83\xf7\x7c\xe7\x7e\xba\xc3\xfa\xa8\xc4\x01\xba\x1c\x9f\xa2\x7b\xd4\x76\x39\x58\xe2\xde\x8b\xd0\xa0\x05\xe1\x1a\xeb\xc7\xa2\x33\xe8\xb4\xd0\x20\x94\xbb\x76\xa9\xcf\x24\xf6\x02\xc8\x39\xe4\x10\x08\xa0\x7b\x1b\x04\x91\x4f\xd6\xf1\xa9\xba\xa4\x84\x99\x06\x3f\xc4\xbd\xc2\x4a\x21\x9f\x1c\x1a\xc8\x05\xc4\x26\xe5\x8a\x5c\x40\x0e\x82\x00\x20\xe9\x10\x9b\x48\x4f\x04\x39\xe5\xda\xab\xf6\xa3\x5c\x91\x73\x48\x33\xfb\x0e\x0d\x88\x7b\xc9\x21\x57\x3b\x69\x1e\xc8\x85\xa1\x70\x7e\xa8\x63\x70\x42\xb6\x50\x32\x90\xc4\xf8\x58\x0f\x40\xca\xa5\x2e\x3e\x6e\x83\x10\x34\xfb\xa1\x51\x8c\x40\x71\x3d\x7e\x50\x8d\x1f\xd0\xd4\xea\x63\x5f\xfc\xe3\x1f\xc2\x45\xe1\xcf\xae\x29\x2e\x83\x70\x91\x3e\x8d\x6f\xe2\x6e\x06\x77\x00\xf6\x91\x38\x12\xc3\xd7\x50\x4d\x49\x0f\x08\x02\xed\x24\x98\x34\xd5\x10\x1a\x30\x99\xf0\x41\x93\xcf\x9c\x76\x88\xe7\x61\x09\x5f\xe7\x35\x03\xad\xa1\x9e\x67\xbf\xea\x83\xba\x03\x35\x67\x5f\xac\x3b\x5b\x5b\x7b\xb6\xee\xc5\xb3\x35\xf9\xc5\x07\x4a\xd6\xb6\x97\x14\x1f\x5c\x5b\xdc\x5e\x2c\x94\xd6\x9e\xab\xad\x3d\x57\xfb\xe2\xd9\xda\xda\xdf\xd4\x95\xb4\x17\x17\xb7\xb3\x2f\x4b\x0e\x30\xd9\x05\x41\x09\xe4\x93\x22\x92\xeb\x3e\xf3\x3d\x0a\xa2\x21\x1e\xac\xfc\x8d\x17\x8f\xc0\xe3\xb0\x1a\x9e\x86\x2a\xa8\x01\x1b\x40\xc8\x6c\xf3\xac\xb0\x50\xe3\x34\xbd\xfb\xae\x73\xdf\x43\xfe\x37\xff\xed\xc1\x57\x32\xc7\x62\x99\x63\xb4\x26\x26\x5a\xad\x89\xb3\x93\x4a\xd9\x8d\x5d\xaf\x59\xac\x56\x0b\xbb\x0e\x59\x12\x13\x2d\xec\x3a\x98\x34\x7b\x76\x12\xbb\x76\x5a\xcd\x66\x2b\xbb\x4a\xd8\xf7\xec\x3f\x13\xfb\x4b\xc8\xb3\x58\x2c\xb5\x56\xab\x05\x9b\x2c\x16\x2b\x5d\x34\x67\x8e\x45\xe8\x9c\x6b\x4d\x74\x2d\xb3\x9a\xad\x62\xbd\xd5\x6a\x71\xfe\x2a\x31\xd1\x2a\x9e\xb2\x58\xe6\x38\x7b\xac\x56\x33\xff\xcc\xf5\x30\x6b\xf7\xae\xd5\x9a\x48\x33\x3d\xb0\x35\x16\x0b\x3f\x9b\xe2\x30\x6c\x26\x46\xd1\xc1\x4f\x36\xf0\xea\x09\x8c\xd3\xe0\x70\x55\xdf\x0b\x95\xfd\xd5\x94\xbe\x73\x94\x52\x21\xe3\xd9\xde\x9a\x8d\xfd\x15\xef\x50\x8a\x02\xf7\xa1\x18\x00\x72\x90\x34\x82\xa8\x3e\x2d\x23\x20\x06\x40\x40\x68\x98\x16\x82\x10\xe2\xcf\xc4\x9f\x19\xf2\x4c\xc3\xa0\xc3\x61\x3a\x8f\x21\x8d\x4e\x52\x73\xfa\x1b\x1b\xcf\xd4\xd4\x9c\xae\xf9\xc6\x99\x8d\xa4\x71\xa0\x5e\xc8\xa8\x39\x5d\x53\x73\x66\xe3\x86\x33\x35\x35\x67\x40\x1c\x82\xc3\x08\xd1\xe9\xc1\xa1\x20\x4e\x9e\x1c\x40\x80\xdc\x6f\xd2\x4e\x0d\x9a\x04\x53\x39\xae\x0b\xbf\x09\xfa\x8d\x2e\x18\xf5\x77\x40\xa7\x1f\x66\x82\x23\xd0\x2f\x2b\x6e\x2f\x59\xd3\x5e\x52\xd2\xbe\xa6\xa4\xbd\x78\x04\x2d\x1b\x8a\xd9\x57\xc5\x6b\x99\x01\x82\x00\xd5\xb8\x49\x28\x11\x37\x42\x00\x5f\xfd\xaa\x3e\x15\x19\xb9\xff\xb2\xba\xb9\x74\x5d\xe6\x92\xd7\xd7\x96\x35\x2d\x5d\xbb\x64\xd9\xea\xa7\x33\x17\x3d\x2d\xd4\x97\xed\xc8\xce\x2a\x7b\x66\xdb\xf7\xcb\xb3\x4a\xcb\x17\x66\x96\x95\x01\x80\x84\x1d\xca\x15\xb9\x96\x1c\x84\x71\xfc\xe9\xf6\x0c\x98\x0b\x80\xb3\xc1\x30\x15\x54\x4d\x58\x43\xc1\x3c\x0b\x2c\xb3\xc1\x38\x4d\x23\xeb\x7d\x1e\xc8\x86\x58\x27\x9a\x67\x59\xf5\xb2\x71\x9a\xef\x82\x52\xec\xc0\x12\x14\x50\xc4\x12\xfa\x86\x73\x80\xbe\xb9\x12\xcd\x7d\x7f\xc0\x04\xfa\xd1\x1f\xfa\xdf\xd8\x7d\x2e\xce\x60\x88\x63\x57\x64\x72\x4e\xf3\x8e\x9c\x94\xe2\x77\x3b\x31\x2f\xde\x60\x88\x8d\x35\x18\xe2\x85\x2c\x07\x56\xd0\x9d\x0e\x4a\xf7\xe0\xd3\xce\x3e\xfa\x6b\x9c\xdd\xd7\x8f\xe6\xdd\x6f\x16\x4c\x8d\x8b\x9b\x1a\x15\x1f\x4f\xcf\x1b\x37\x6f\x36\x1e\x43\xea\xfe\x1b\x08\x9e\x55\xae\xc8\xbb\x39\xed\x7a\x30\x40\xdc\x50\xca\xd1\x47\x1c\x21\x8c\xd6\x68\xd9\x38\x2d\xda\xf7\x53\x3c\xcb\x89\x15\x70\x2d\x7d\xc3\x49\x69\x0b\xc6\xc6\x19\xa6\xcc\x9c\x39\xc5\x10\x17\x59\xd2\xf9\xb3\x92\xd4\xa5\x3b\x9a\x73\xb0\x2e\xde\x30\x65\xc6\x8c\x29\xc3\x08\xc4\xba\xa8\xf8\xf8\xa8\xa9\x71\x71\xb4\xe5\xd8\x31\xe3\xe6\xcd\x68\x70\xff\xcd\xe7\x76\x33\x95\x6a\x39\x90\x24\xf3\xd3\x09\x00\x2d\xe6\x44\x6b\xb4\x55\x9f\x68\xb5\x98\xc3\xa6\xa0\xde\xaa\xd7\x4c\x64\x63\x67\x59\xa3\xd7\x44\x07\xa2\x26\xcc\x68\x99\x1e\xad\x89\xb6\x4e\x8f\x56\x15\x18\xad\xd2\x96\xd9\x17\xb0\xfc\x48\xcc\xf1\xaa\xe7\x33\xe6\x3f\x95\x7c\x2c\xae\x33\x5f\xee\xeb\x0b\xca\xe9\x4c\x38\x3a\xeb\xf1\x95\x19\xb5\xa5\xc7\x63\x8f\x2e\x0b\x4a\xeb\xde\xbc\xf5\x97\xe2\xc9\xcd\x5b\xbb\xb0\x33\xb5\xa1\xa8\x33\xe1\xe8\xb2\x80\xfe\x7e\x39\x3a\xee\x68\x5c\xe7\xfa\x0d\xa9\xf5\xc5\xc7\x63\x8f\x9a\x1e\x1c\xdf\xdf\x1f\x94\x7d\x24\xae\xb3\xb4\x3e\xca\x7e\xf2\xc3\xef\xd9\x4f\x9d\xe2\xf3\xcf\xb0\x9c\x44\x93\x06\xd0\xc3\xfd\x7c\x35\x89\xc5\xb3\x29\x48\x5d\x88\xa5\xce\xa8\xf0\xf7\xa3\x58\x3d\xe2\xea\x47\x61\xfd\xe6\x43\xeb\x6b\xf2\xf2\x77\x94\x23\x28\x90\xd3\x5e\x97\x97\x9f\x9c\x5a\xb3\x72\x65\x0d\xe6\x67\xee\x0f\xde\x57\x5e\xbf\x3f\x3f\xaf\xf6\xd9\x7d\x81\xfb\x33\xa9\x03\x65\xc1\x3f\xbf\x36\x35\x25\x2f\xbf\xe6\x45\x10\x30\x17\x1c\xe4\x10\x69\x50\x77\x5f\xa8\x4f\xf3\xac\x7c\xd1\xa3\x35\xd1\xac\xe7\x58\xcc\xb3\xc2\x34\x72\x58\x68\x14\x86\x4e\xc0\x69\x33\x30\x5a\x33\x8a\x5d\x63\xee\x81\xba\x45\x79\x37\x9b\x63\xfd\x64\x8d\xd6\xb0\x60\xde\xca\x98\x69\x13\x02\x49\x50\x00\x21\x81\x61\x26\x63\xe0\x27\x79\x3f\x79\x61\xe3\xc1\x65\xf5\x2b\x57\xd6\xd5\xe7\x17\xd4\x09\xfa\x17\xdb\x63\x6f\xc6\xc6\x92\x40\x3f\x2d\x21\xba\xf1\x01\x81\x11\xc9\x6b\x1f\x9e\x3d\xd5\x4f\x96\x33\x0a\x12\x3e\xcb\x7d\xb6\xfe\x50\x5b\xfd\xea\x6f\xb0\xe6\xb5\x2c\x1e\x25\x03\x10\x42\x3e\x02\x83\xba\x5f\x38\x15\xad\x53\x50\x3f\x05\xf5\xfc\xe1\xe5\x14\x21\x0a\x0d\xd6\x59\xa9\x98\xc2\x8f\x8d\x4c\x5e\xf9\xd4\xe6\x4d\x11\x93\xd6\xbc\xbe\x2d\x53\x68\x58\xd9\x52\x4a\x96\xef\xdb\x24\x3b\xff\x26\xd7\x1d\x5c\x59\xd0\xfe\x64\x03\x7e\x56\x60\xcf\xad\x39\x56\x5f\x7c\xe0\x15\x5b\xe3\xe2\x35\xb6\xf7\x5a\xf7\x17\x69\x4d\xa6\xe2\x83\x3b\x02\xdf\xb3\xb9\x71\x49\x84\x9c\x52\xdf\xe1\x94\x68\x9d\xa5\xf7\xac\x00\x9d\x18\x16\xaa\x49\xb4\x0e\xfa\xf5\x0c\x8c\x9e\x22\x32\xd4\xa9\xa2\x45\x5d\xa2\x90\xfc\x5a\x61\xca\x53\xa6\xe0\x71\xfb\xd6\x6f\x68\x5d\x94\x17\x34\x31\x7a\xdd\x82\xec\x96\x0d\x73\xbe\xb1\x3a\x85\x24\x54\xd9\x9e\xf7\x73\x1e\xd5\xda\x6b\x8a\x12\xc5\xa4\x8e\x82\xea\x7d\x82\xa9\xfa\x2d\xc1\x9c\x11\x7d\x7f\x74\xed\xce\xd6\x67\xf2\x4b\xa2\x89\x76\xd9\xd2\x8d\x1b\xdb\x66\xad\x58\x57\xbf\xfb\xc5\xc4\x50\xa3\xf1\xbe\x39\x35\xaf\xe7\xc4\xd7\x6e\x7c\x8b\xd7\x0b\x65\xca\x35\x52\x40\x6a\xbd\xd1\x65\xa2\xde\xb3\x3d\x57\x13\x88\x9a\x19\x18\x8f\x33\xb0\xec\x95\xd2\xfc\xed\xd1\x86\xed\x2b\xd7\x6c\x5f\x59\xb5\xad\xc1\x38\xb1\xa0\xe3\xc9\xa5\x89\x62\xe3\x33\x9b\xab\x6b\x6a\x36\xda\xd7\xe6\x9f\xd8\xfc\xd3\xde\x86\xfc\x77\x3e\xa9\x7b\xaa\x81\xf5\x99\xa1\x5c\x15\xcf\x91\x53\x7c\x4d\x47\x22\x58\x27\x82\x5e\x06\xcd\x74\xc8\xd8\x80\xc2\xb2\x6c\xd4\xd6\x65\xd2\x8f\xf2\x62\xa9\x43\x58\xb9\x19\x57\xbe\x5a\x4f\xdf\xd8\x9c\x49\xd7\xbd\x96\x8b\x95\x0c\xf6\x24\x44\x8a\xc9\xa4\x01\xc2\xdd\x27\x44\xe8\x75\xe6\x30\x26\x19\x8d\x91\x2f\x25\x53\x1f\x04\x9f\xac\x7f\x38\x36\x3e\x67\xf7\xb3\x45\xf1\x49\x2f\xa4\x37\x3f\x93\x94\xd4\xb0\xac\x3a\x44\xcc\x2d\xed\x6a\x6e\xdf\x59\x6b\xab\xad\x69\xf5\xa7\x72\xdd\x1b\x56\x75\xad\x50\x2f\xb9\x41\xec\x7c\x6d\x1e\x98\xd4\x1e\x4d\xbc\x17\xd5\xfc\x75\x92\xfb\xd9\xb2\xc9\x22\x61\x50\x4d\x76\xe2\x0c\xe1\xdd\x3d\xab\xab\xeb\x96\xc5\xc7\xba\xfa\x37\x57\x27\xcd\xc5\x2a\x21\xda\xd5\x6f\xcd\xd9\x18\x22\xdc\x38\xec\xfc\xb9\xed\xb5\xa7\x56\x54\x05\xe3\xfb\xaf\xd3\x6f\x6c\x68\xb1\x08\x7f\x79\x7d\xe3\x2e\x9e\xa3\xca\x14\x2b\x11\xa4\x33\xee\xb3\x2d\x2c\x56\x9d\xc6\x62\xd5\x99\x75\x26\x9d\x59\x67\x0d\xd3\xf0\xcb\xa8\x93\x74\x46\x9d\xd5\xa4\x93\xca\x7a\x7a\x7a\x8a\x31\xbb\xb8\x87\xdd\xe9\xd1\xe2\x62\xcc\xa6\x47\xf5\x3f\x28\xc2\x5b\xc5\xad\xc5\x98\x49\x2f\xb5\x62\x21\x3d\x5d\xb4\xb7\x98\xfa\x17\xb4\xae\xa4\x2d\x98\xf2\x03\xfa\x26\xa6\xff\xa2\x15\x6f\xb5\x02\x2a\x57\x00\xc4\x16\xe9\x28\x84\x01\x88\x9e\x3d\x39\xa2\x77\xef\xaf\x68\x08\x89\x30\x75\x18\x3a\x4c\x87\x9e\xc5\x59\x95\x68\x36\xd1\x33\x53\x30\xc1\x44\xcf\xc4\x08\x90\xe8\xfc\x68\x0d\x9e\xea\x78\xe3\x20\x2b\x19\x0f\xbe\xd1\x71\x4a\x01\x3c\xa5\xce\xb3\x02\x08\x5d\x72\x28\x9f\x67\xf5\xf6\x39\xb8\x27\xcf\xdf\xf4\x86\x61\x97\x69\x57\x0d\xc6\xd5\xb4\x98\x5a\x0c\x2d\xa6\x96\x72\x7a\xae\x1c\x6f\x1c\xdc\x73\x50\x48\x70\x7d\x74\x70\xcf\x41\x1a\x84\x37\x00\x95\x9d\x6e\xda\x22\x00\x44\xbe\x6f\x35\xc4\x20\x4e\xf4\x1c\xb6\x1a\x2d\x32\xea\xa6\x1b\xa7\x69\x2a\xa6\xbe\xb9\x21\x22\xe8\x5b\x38\x6b\x47\xc4\xc4\x45\xd3\xdf\x98\xba\x7b\x7d\xe4\xc4\x05\x9c\xbe\x57\xf5\xe1\x0b\xa7\x09\xd6\xd7\xf7\x12\x61\xb9\x2b\x4f\x5b\xb9\xb3\x55\xa6\x5d\x0a\x08\x2d\x32\x3f\x6b\xd6\x02\x40\xae\xf3\xb5\xfe\x11\xde\xdd\x68\x23\x76\x64\x32\xa2\x2d\x3f\xdf\x1d\xd3\xf2\xf0\x88\x53\x3d\x27\x9d\x8b\xe9\x15\x1b\x4e\xe1\x73\x43\x4e\xf2\x7c\x9e\xc5\x48\x08\xa4\xa1\xe4\x20\xa7\xfd\x7e\x00\xfd\x6c\xab\x67\x5f\x25\x1a\x44\xa3\xe7\xac\x33\xf5\xdc\x3f\x0f\xa2\xc0\xf1\xf8\x08\x3e\xfd\xe9\x67\xfb\x5b\x50\xa2\x47\x3e\xaa\xd9\x2e\xe7\x25\x9b\x0d\xcf\x5a\xde\xfc\xa1\x40\x96\x35\xee\x58\x5d\x96\x7d\x79\x56\xa2\x9c\xf0\xeb\x93\x7b\x2f\x5b\x5d\xcd\x42\x82\xab\x70\xb2\x3e\x37\xec\x6f\xe3\x83\xb7\x92\x57\x5f\xd8\x98\x9b\xab\xee\x2d\xfa\x82\xe6\x93\x4e\x7e\x66\xd1\x64\x86\x59\x0c\x99\x6e\x51\x17\x9d\x85\x98\x45\x75\x07\x7e\x2c\x8a\x21\xbc\xb8\x08\xd3\x9b\x79\x48\x8a\x0e\xf8\xd4\xfe\xfd\xbf\xbd\x52\x9c\x79\xfd\x97\x97\x4e\x7d\x76\x29\x50\xfb\xd2\xcf\xc6\x9d\x3d\x8b\x21\xe3\x16\xd6\x2d\xa9\xd7\x2e\xb0\x3d\x2c\xd0\x7c\x3c\x53\x7e\xeb\x97\xf8\xf4\xc9\x18\xfc\x15\xcd\x1e\xd8\xd7\xf4\x2f\xb4\x42\xd4\x0b\xc1\xdf\xbf\xbe\xa1\xe3\xe5\x3f\xef\x08\x1c\xcf\xed\xb6\x88\xe6\x13\xad\x1c\x0a\xf7\x41\x24\xdf\x05\x63\xd6\xb8\x37\x63\x8a\x7c\x0d\x9d\x68\x64\xc4\x58\x23\x04\x63\x51\xe4\x2f\xbe\xf7\x41\x42\xc5\xfe\xb6\xfd\xe3\x67\x25\x38\x93\x9f\x58\xb3\xfd\x8d\xb6\xbd\xad\x01\xd5\xc7\x3a\x1f\x11\x6b\x9b\xf3\xae\x7f\x86\x47\x69\xf6\x15\x57\x99\x38\xf5\x52\xbc\x4c\x2b\x70\xff\x83\x1f\xce\x4a\x15\x22\xe8\x24\xfc\x98\xf9\xb5\x85\xe6\x4b\x27\xa4\xa3\x30\xc1\xe7\xad\x12\xec\xdf\x10\x83\xe8\xfb\x22\x09\x8a\x93\xb7\xd3\xb3\x85\xf4\x12\x7f\xf9\x05\x7f\x7f\xc4\x40\xba\xab\x18\xdb\xd5\xf7\x53\x20\x98\x68\x15\x69\x93\x43\x19\xb5\x66\x34\x04\xa2\xc6\xec\xd9\x09\x25\x9a\x45\x43\xc8\xe0\xd9\x07\x26\xcc\xc6\xb8\xe8\x07\xe7\x6b\x53\x77\x95\x6e\x79\x43\x9f\xdf\xb6\x89\xfe\x3d\xff\x83\xcd\xea\xfb\x47\xe4\xd0\xb7\x3f\xf8\xdd\xc3\xab\xfe\x75\xcf\x92\x67\x68\x89\xeb\xfb\xd8\xc4\xf7\x25\xf3\xad\xc8\x6e\x5a\xdb\xa4\xa3\x10\xa4\xd2\x6a\x45\x03\x86\xf0\xce\x45\x8d\x4a\xec\xee\x16\x7c\x0b\xd7\xb9\x0e\x1d\x7f\xf7\x35\xda\x5f\xb8\xf8\x5c\x7d\xa5\x74\xd4\x95\x7a\x16\xff\xee\x5a\x48\x83\x5c\x39\xd8\x3e\xb8\xcf\x91\xd1\x7b\x43\xf5\x2b\xd6\x97\x3c\x01\xcd\xbe\xdd\x71\x2a\x5f\x1b\x67\x1a\xaf\xc5\x93\xb8\x92\x06\x1e\xd9\xb7\x89\xde\xcc\xcf\x79\xe7\xc5\x6c\x39\xd4\x95\x9d\xf4\x8d\x87\xf0\x3c\xd5\xd2\x5a\x46\x22\xb6\x65\xd1\x36\xee\xab\xdd\x34\x9f\x74\xa8\x6b\xf8\xf8\x2a\x41\x83\x86\xcb\x32\x65\xba\xe8\xe7\xba\x64\x11\x0f\xc4\x38\x6f\x0a\x79\x3b\x68\xff\xaa\x1e\xf1\x53\x84\x5f\x39\x43\x5d\xf9\xd8\x0e\xa8\x9c\xa5\x55\xe2\x29\x52\xe4\x81\xb3\xba\xe1\xe2\x8d\x42\x1a\xad\x36\x0b\x9f\xc5\xba\x7e\x85\xef\xd8\xe9\xe7\xf9\x47\x84\xae\x6b\x1f\xba\x1e\x75\xbd\x84\x4d\xea\x9e\xaf\xeb\x32\x48\x67\x20\x94\xef\xc0\x73\xef\xb4\x37\x5b\x0d\x68\x8c\x36\x06\x0a\xc6\x69\x82\x5a\x65\x59\x53\xd1\x12\x64\x9c\xc6\xf7\x7d\x2d\xef\xa9\xfa\x41\xaa\x36\x13\x83\xe9\x69\xaa\x9d\xb0\x74\xc3\xcb\xb9\x27\xfe\x82\xd6\x6f\x3e\xf7\xfa\x6f\x12\xc3\xfd\x6f\xbc\xf8\xe1\x06\x74\xe0\x44\x7c\xdf\xb5\xaa\xa2\xc3\x91\xdd\xf1\x68\x8e\x89\x0d\x24\x5f\xde\x79\xeb\x1f\xcf\xac\x7a\x00\xe1\x18\xfd\x29\xcf\x4d\x00\xe4\x0c\xa9\xe6\x67\x79\x19\x42\x26\x86\x99\x13\xad\x21\x83\x7b\xe1\x35\x68\x28\xc3\xe8\x38\x8d\x7f\x72\xd4\xd1\xf9\x7b\x9f\x7e\xe2\xd1\xb9\xa6\xfb\xcc\x2b\xe3\x69\x3b\x3d\x44\x8a\x5c\x47\x37\x95\xb4\x25\x63\xe5\x77\x5f\x8c\xba\x3e\xae\x6c\xad\x2b\x9f\xf5\xd7\x09\xa0\x35\x4b\xa7\x21\x9a\xf7\x17\xca\x0f\x37\x63\xf2\x0b\xd5\x98\x83\x87\xf5\x2c\xce\xb6\x1a\xd9\xbd\x13\xa3\x64\xad\xac\x35\xac\x18\x87\xeb\x31\x30\xcc\x4f\xfb\xc4\xfd\x7f\x5a\xb0\xfb\xb9\xdc\x5c\xeb\x94\xfb\x67\x66\xce\xa4\x39\xb4\x6d\xa2\xac\x9d\x9d\x42\x8f\xd3\x43\xd2\x51\xe7\x9f\x67\xdf\xb4\xac\xfa\xad\x5e\x34\x3b\xdf\xd8\xf1\x6d\x0c\x7a\x4c\x08\x78\xeb\x3b\x91\x37\x27\xac\x7a\xde\x29\x88\x19\x45\x05\x3f\x7a\xd9\xc5\xc6\xfa\xf5\x00\x1a\x81\x54\xf3\xbd\xbc\x1c\x7b\x2a\x5a\x43\x0c\xba\x50\x8d\x39\x31\x0d\x47\x21\x43\x34\xd4\x63\x38\x19\xe7\x17\xb0\xf0\xbe\xab\x98\xe5\xaf\x9d\x9f\x51\xb2\x62\x67\xe5\x82\xc7\x93\xa6\x4c\x99\xb9\x6c\x06\xfd\x39\x3d\x2e\xfb\x07\x14\x44\x5c\xa3\xc7\x49\x11\xd5\x9d\x6d\x78\xe8\xfd\x14\x61\x92\xeb\xe3\xae\xf2\x5f\xbc\xda\xfb\xe3\xef\x44\x5d\x1f\x97\xbf\xc6\xb5\x50\xd0\xee\xf9\x99\x92\xee\xba\x0c\x02\x8b\xf5\xe4\x14\x5f\x1b\x6d\x62\xd1\x7e\x96\x75\xfa\xe0\xea\x6d\x3d\x17\x33\x32\xef\x94\x43\x06\x37\x98\xfa\x9b\x16\xcd\x0d\x6b\x6d\x7a\xee\xa5\x86\xfa\xc9\x7a\x6d\x6c\x16\xc6\xe0\x42\xd7\x0f\xe9\xbb\x55\x79\x34\x2a\x3a\x39\xea\x3e\xa3\x09\x7b\x0f\xf8\x3f\x37\x67\xcf\xbf\xd9\x9f\x79\xb6\x63\xee\xf6\x17\x66\xbc\xb4\x45\xc8\x1d\xd8\x87\x57\x82\xb0\x31\x71\x45\xf0\x1a\x73\xd4\xf4\x24\xee\x5b\x00\xc4\xa8\xae\x53\xe5\x71\x40\xf4\xf8\xbf\x00\x56\x0a\xdc\xe5\x29\x65\xae\x0e\xc8\xac\x4d\xac\x20\x45\xbc\xad\x9a\xe1\x44\xe3\xe7\x38\x73\x15\x6e\x32\xd3\xfa\x12\x52\x44\x73\x2f\x53\xb3\x7a\xe6\xac\xd4\x4d\xaa\x41\xef\xde\xe9\x63\xd5\xab\x7b\x89\x42\xbc\x2b\xbd\x0d\x53\xef\x97\x52\x05\xbe\x1a\xbf\xe0\xdf\xdf\x7f\xff\x7b\xdf\xc8\x5b\xf8\x5c\xfc\xaf\x7f\xdc\xf9\x9b\x63\x74\x27\x55\xe8\xc7\xf4\x77\xc2\xdf\xca\x76\xae\x28\x7a\xe2\x01\x3c\x75\x0a\xb3\xde\xea\xf8\xee\x17\xdf\xaa\xd8\xa8\x13\xc8\x6f\x8f\xff\xf5\xc3\xbf\xd0\xce\x7f\x1f\x20\x41\xaf\x5c\x68\x3c\xdc\xc1\x63\xa6\x01\x76\x09\xcd\xee\xb5\x41\x10\x82\x7a\x14\x51\x8f\x06\x21\x66\x89\xab\x6f\x09\xff\x17\x09\xd6\x55\xd2\x97\xb0\x9f\xdd\x36\xf1\xe7\xcd\x36\x29\x1c\x9b\x34\x27\xdc\x4f\xf0\x7d\x87\x50\x3a\xb3\xae\x21\x3b\x29\x39\x33\x33\x39\x29\x1b\xf3\x4e\xc8\x15\xf3\xd2\xd2\xe6\xa5\xa5\xa4\xd0\xcf\x84\x7f\x71\x3d\xc9\x60\x0f\x90\x32\xc1\x2a\x5f\x19\x09\xcb\x70\xaf\xf4\xc0\xc6\xe0\x45\x3b\x35\x0c\x82\x77\xb3\xbf\xa7\x32\xf8\x32\xd2\x2f\x04\xc8\x57\x40\xf4\x3e\x1d\xf6\xe9\x63\xb7\xb0\x9f\xc6\xaa\x7d\xcc\x59\x4a\xfa\xdf\x7b\x0f\x9b\xd4\x1e\x52\x79\xac\xa9\x20\xdd\xb8\x55\xd6\x83\x04\xe3\x8f\x20\x7c\x47\x04\x48\xbb\xef\xd7\xea\xd2\x1b\x8b\x59\xb7\x13\xdf\x7e\x96\x74\x3f\xfb\x31\x3d\x08\x80\x68\x26\x07\xc5\xdb\x9a\x64\x90\x01\xfc\x04\xfe\x84\xd5\x8c\x6b\xb1\x84\x7e\xb2\x47\x3a\x8a\x9b\x68\x1d\xbd\x85\xfe\xac\x5d\x3c\xd9\x2e\x7e\xa1\x89\x62\xed\x90\x3f\x14\x46\x8c\xc7\xb0\x3d\x18\x46\xdf\x92\x43\x71\x1c\xfd\x2f\x5a\xc7\xe5\x7c\x48\x68\x15\x76\xcb\x5f\xf0\xfd\x30\xbe\xab\x83\x23\xd0\x20\x1e\x5a\xb1\x24\x2d\x3d\x7b\x59\x43\xd9\x1a\x34\x9d\x16\x83\x1f\x79\x74\x6e\xe2\xd2\x27\xb0\x59\xe8\x72\xa5\x71\xd8\x6d\xc2\x11\xa1\x56\xa3\x05\x91\xc1\x46\xa0\x79\x9c\x0f\xcf\xdb\x4e\x1f\x2b\xce\xcd\xcd\xe2\xf0\xc2\x11\x06\x22\x1e\x56\x3b\x50\xd7\xbc\x66\xe3\x8b\x42\xa2\xf4\xeb\x51\x61\xb3\x7d\x60\xf1\xc5\xe1\xb0\xa8\xec\x25\xdd\x02\x91\xf5\x7c\x3d\x4d\x88\x81\x1f\xe7\x64\xd4\x94\x2c\x16\xa2\x26\xbe\x97\x50\x39\xeb\xe5\x04\xd2\x8d\x79\x95\x57\xaf\x5e\x05\x40\x5a\x0b\x00\x17\x31\x0f\xfc\x20\xf8\xa8\x46\xfc\x8e\x84\x08\x10\x3f\x4b\x67\xe6\x02\x36\x58\xcd\x56\xb3\xc6\x6c\x35\x8b\xb4\x76\xe2\x7b\x09\x15\x09\x5b\x12\x9e\x5d\xcc\x20\xb9\xac\x95\x5b\xf4\x51\x31\x4a\xd9\xc3\x4f\x6a\x4c\x45\xab\x61\x0a\xea\xc3\x8c\xd3\xa3\x65\x8d\xd1\x3f\xed\xc8\x6c\xcc\x9d\x58\x3e\xeb\x97\x69\x6b\xd7\xd9\xfa\xe9\xb3\x49\x47\x32\x12\x7f\x92\x15\x6e\xa9\x5e\xe9\x7e\x07\x8d\x09\xea\x85\x50\x52\xcd\xc7\xd1\x93\xd3\x03\x45\xbf\xfa\x27\x44\x71\xc2\xa4\x09\x61\xf5\x4f\x4c\x08\x82\xb4\x58\x5d\x30\x24\x4d\x8a\x8f\x1d\x7a\xba\xa1\xef\xef\xa6\xca\xe2\x85\x2b\x2a\x9f\xc8\xce\xdd\x56\x55\xb4\x70\xc5\xb3\x05\x4b\x1e\x45\xff\xc2\x67\x72\x32\xf3\x9f\xcd\x11\x2e\x17\x3e\xf3\xf0\xa2\xc7\x2a\xb3\x41\x80\x78\x2c\x14\x77\x8b\xc7\xb8\x9f\x44\xa5\x07\x49\xe4\xbb\x4f\x48\x12\x6a\x11\xbe\xfb\x84\xe2\x3e\x16\x74\x10\x95\xfb\xe0\xce\xf8\x38\xe1\x6f\x71\xae\xf2\x78\xe1\x6f\x33\xb1\xf0\xfc\x79\xdc\xd4\xdf\xcf\x63\xc1\x4e\xbc\x22\xd8\xbd\xe7\xe2\xe1\x4e\x7e\x0a\x1c\x5e\x51\x8f\x7b\x63\xe3\x06\xe1\x96\x10\x3f\x78\x6e\xde\xc9\x5c\x9c\x74\x42\xdd\x1e\x07\xde\x33\x5a\x8a\x49\x31\xfb\x3e\x41\x67\xd0\xb1\xdf\x07\x5a\x41\x54\x4c\x34\x54\xda\x20\x47\xc1\x14\xbe\xb3\x05\x34\x3c\x91\x85\x18\xd3\x04\xdf\x43\x57\x58\x39\x24\x18\xa6\x45\x63\x88\xc1\xd7\x16\xce\xa7\x24\xa6\x14\x86\xfc\xfa\x47\x53\xde\x09\x8e\xe9\xee\x68\x2c\x5f\xbe\x28\x3d\x29\x33\x20\xe0\x7c\xc2\x7f\xf6\x3d\x4c\x8f\x95\x67\x8a\x57\x3f\xc5\xb8\x4f\x83\x56\x3f\xbe\x24\x67\x65\xe1\x1b\x97\xc2\x96\x17\x88\x27\x9b\xf2\xf2\x4e\xfc\x38\xe1\x4f\x51\xcb\xe7\xa7\x5e\x71\x06\xd2\x6d\xe1\x78\x8e\x14\x0d\xec\x93\x4a\x1f\x7f\x22\x75\xee\xf2\xb5\x3c\x56\x30\x9a\x1a\xdd\x34\xdd\x85\x22\x3f\x34\xe0\xdd\xc9\x60\x45\x06\x3d\x3a\x26\x01\x72\xe8\x97\xd7\x41\x95\x85\x36\x4e\x8e\x82\x39\x30\x0f\x16\x8f\x85\xd9\x60\x1d\x8d\x0e\x0b\xab\xf1\x43\x0c\x5f\x41\x4a\xb8\x55\xfd\xf3\x91\x45\xf3\x93\x16\x8d\x0f\x38\x9f\x70\xbe\xef\x61\xfa\xb3\xf2\xcc\x94\xc4\x97\xef\x3f\x43\x37\xa8\xa4\xcb\xad\x4c\x82\xba\x62\x2e\xc1\x5d\x23\x18\x18\xc6\xc9\xcd\xb0\x76\xf1\xe4\xa8\x42\xe5\x32\xd5\x26\xbb\x79\xfb\xda\x9c\xdd\x41\xda\xf7\xc8\x0e\x2e\xc1\x38\xfa\xce\x57\x61\x84\x2b\x07\x5d\xe5\xe4\x30\xb4\xc9\x59\xa0\x81\xb0\x74\xff\x25\x04\xe7\x10\x24\xe2\x77\x00\xe2\xef\x3b\x33\x6b\xd5\xaa\x84\x99\x98\x78\xbf\x29\x6c\x1a\xd1\xb8\xca\x5f\xc6\x37\x30\xb2\x9b\x76\x55\x92\xc3\x3d\xa7\x85\xd3\x4f\x95\x71\xfb\x6f\x23\x87\xc5\x5a\x0e\x0f\x21\x16\xf3\x54\xa2\x37\x4e\x6f\xd3\x62\x3c\x3e\x63\xfe\xf9\x2b\x52\xfd\xe9\x8f\x4e\x9d\xe2\x7e\xe2\xaa\x23\xe7\x81\xd5\xd7\xe3\xdd\x6f\xde\x99\xa8\x0f\x53\x0f\x18\x71\xd5\xc5\x5d\xd8\xb1\xbe\xfb\x89\x33\x3f\xca\xca\xaa\x8e\x24\xe7\x5f\x6f\x9b\xa6\x3b\xfb\x40\x68\x72\x22\xb8\xfb\xbf\x20\x7e\xa4\xc2\x79\x4e\x3d\x53\x37\x7a\xb7\xbd\xfd\x6e\x76\xd6\xf3\x51\xbb\xe3\x2f\xbc\x56\xd9\x2d\x05\x9d\x35\x4d\x9c\x93\xd8\xdc\x66\x00\x98\x08\x79\xb4\x41\xd3\x25\x7d\xc6\xd7\x2d\x8d\xe7\x2b\x73\x8c\x3e\x6b\x15\x96\xc2\xa3\x50\x08\xc5\x50\x0a\xeb\xa1\xc6\xfb\x74\x13\xd8\xa8\x5a\x63\x0e\x33\x87\x19\xc2\xd1\xcc\xd7\xed\x88\x3a\x43\x98\x31\x2c\x64\xc8\x3e\x77\xf3\x2c\x96\xec\x43\xf8\xde\x20\x43\x98\xe7\x2e\xea\x3c\x1b\x0f\xd5\x4d\x6a\xd1\x7c\x1c\x17\x8b\x16\xcf\x78\xce\xdb\xd0\xc2\xf7\x4c\xa8\xeb\xce\x43\xcc\x16\xb3\x8e\x7d\xac\x33\x5a\x06\x71\x9a\x75\x79\x55\x55\x55\xef\xd3\xb3\x55\x55\x55\x55\x18\xff\x7e\x93\xdd\xf6\xed\x97\xed\x36\x9b\xdd\x66\xb7\xdb\xed\x31\x18\x48\x6f\x62\x60\x2d\x06\xd1\x1b\x18\x74\xf1\x60\xe5\xf3\x33\x1e\x4a\x9e\x59\x59\x94\x97\x9d\x60\x2a\xc8\xcc\x98\x71\xff\x83\xf1\xc9\xe7\x51\x47\x3f\x47\xdd\xae\xd8\xf0\xfc\xfa\x75\x45\xb3\x6f\x76\x57\xd2\xff\x89\x33\xd5\x67\x72\xd1\x0c\xbe\xe6\x83\x4a\x31\x8e\xf7\xb0\x19\x27\xd0\xbf\xa3\x1d\x67\x56\x75\xb9\xde\xd9\xb1\x67\x77\x73\x53\x4b\x4b\xd3\xc9\x93\xbf\x18\x78\xbb\x52\xa6\x55\x55\x5f\x56\xf1\xdb\xc0\x59\x21\x7b\xc1\xa3\x09\xe9\x5a\xed\xf8\x85\x73\x56\x3c\x51\x16\x6b\xca\x2e\x99\x36\x75\x5a\xe4\xc0\xbb\xea\xd7\xbd\x65\xda\x7c\xdc\x41\x5f\x58\xbd\xd6\xd5\xf6\x01\x3d\x2b\xd3\x2a\xfa\x3f\xbb\x1c\x07\x38\xa9\xf6\x41\x3c\x7c\xef\x4c\x1e\xed\xd2\xb4\xf3\x73\x70\xa6\xf0\x13\xca\xfd\x44\xcf\xce\x19\x4d\x20\x46\xa2\xd9\xc2\x27\xcc\xdc\xd3\xad\x3e\x33\x76\x79\x62\xbb\x78\xd0\x99\x47\x0f\xe5\xb6\x16\xa4\xa5\x26\x64\xe5\xa6\xfc\x36\x3a\xb3\x34\xe7\xdd\x7f\x79\xe4\xd8\xea\xc5\x99\x19\x4b\xb2\x16\x64\x2d\x12\x2a\xc4\x76\x67\xbe\xf3\x71\xa9\xfc\xf0\xf2\xb9\xf1\x96\xa5\x89\x0b\x9e\x5f\x9a\x1c\x1f\x9f\x32\x67\xd9\x77\x0a\xec\xbb\xe7\x38\xfd\xd2\xb2\x96\xa4\xa6\x2f\xc9\x62\xb5\x42\x0a\xe9\x27\xd7\xe4\x34\xf5\x1c\x6f\xab\x41\xa3\x1e\xc9\x6f\x60\xc3\x8e\xe9\x98\x22\xa1\xbf\xd0\xbe\xf6\x19\x3d\x06\x4d\xfb\xce\xef\x76\x7d\xf8\x1f\x72\xd0\x24\xfd\x7d\x61\x5b\x57\x96\x6c\x7a\x3d\xe7\x4d\xfe\xac\xea\x33\x72\x46\xdc\x24\x87\xaa\x67\x86\x27\xba\x5f\x4a\xf5\xd9\xa3\x31\x18\x31\x65\x53\x3a\x39\x73\xdf\xe1\xba\xd0\xa4\xb7\x17\xa9\x36\x5c\x47\x93\x85\x60\xa5\x11\xfc\x20\xe0\x48\x94\xba\xe6\xef\xd7\xab\x12\x66\x86\x78\x5e\x66\x65\xac\x0b\x5f\x11\x82\xf7\x19\xea\x17\x1d\xa1\xf9\xe6\xae\xa4\xd0\xd4\xff\xf1\x30\xc3\xd1\x4b\xfa\xc5\x4a\xd9\xc0\xd7\x01\x5b\x52\xd1\x6a\xe6\x48\x7a\xa3\x1a\x16\xbc\x1d\xfa\x78\x30\xe9\x0f\x4b\x3e\x94\x1d\xf1\xc0\xaf\x92\x01\x88\xf2\x7b\xe5\xba\xfc\x57\xe9\x0c\x04\xc3\x7d\xf0\x00\x24\xf2\x7a\xce\x1a\xa6\xd6\xab\x9e\x9d\x93\x12\x27\xf4\xce\x67\xe3\x3f\xb0\x73\xdf\xa2\x47\x82\x27\x4c\x8c\x98\x93\x98\xf4\x08\xce\x49\xc9\x45\xf9\xc5\xef\x4d\xbd\xe3\x41\xf9\x17\x8a\x36\xdc\x97\xad\x8b\x99\x1e\x38\x5e\x3b\xee\xbe\xc8\xe9\x0f\xcd\x33\xdf\x57\x7b\x24\xf4\xdf\x5e\x76\x1d\xb8\xf3\xc1\xf9\xea\xfc\x16\x29\x17\xcd\x52\x0f\xa7\x9b\xcf\x60\x8e\x41\x73\xd9\x68\x74\x8d\x89\x5a\x8d\x39\x6d\xa4\x5b\xc9\x95\xdb\x20\x98\xeb\xc8\xfd\x26\x31\xa3\xc7\xbc\x5c\x6d\x4b\x9e\xfa\xe6\x4b\x27\x43\x8f\x06\x2e\x9b\x3f\x35\xca\x2c\x5d\x6d\x0b\x5f\xfd\xc4\xfe\x79\x8b\x9b\x03\xad\x0f\x4d\x8a\x04\x10\x9c\x07\x48\x3f\x0a\xb2\x8d\x9f\x87\x05\x68\xb1\xf2\xbd\x8a\x6a\x35\xa4\xbe\x20\x25\x10\x35\xce\x03\x19\xdb\x17\x60\xea\xbc\x8a\x77\x97\x2e\x2b\xb0\xe1\x3f\x16\x16\xdf\x0e\x6f\x5d\x4c\xfa\xf5\x69\x2f\x3f\x66\x7f\x5d\x9f\x51\x98\x93\xdb\x1d\xbc\x70\x9b\xff\x94\xad\x33\x19\xbf\x03\x57\x48\xbf\xd2\x2a\x37\xf0\xf7\x15\x00\x5a\xcc\xac\xc3\x19\x18\x32\xa4\xf3\x81\x2b\x1f\xeb\x53\x36\x27\x97\xfe\xd8\xb7\x6b\xb9\x3a\x70\xf5\x86\xa0\xc4\x1a\xfa\xaa\x4f\xd7\x5c\x86\x8c\x4e\xd8\x2b\xdf\x86\xf1\x30\x65\x04\x9d\xea\xc9\x6a\x1a\x2f\xfb\x43\xe9\x15\xb4\x81\x36\xeb\x43\x0f\xc4\x67\xae\x78\x72\x77\xe0\x10\xa2\xdf\xdb\x20\x67\x9a\x02\x5f\xd4\x3d\x32\xff\x45\xa3\x45\xc5\xa1\x9c\xd3\x04\xc1\x78\xfe\x9e\x4a\x15\x47\x14\x32\x24\x1a\x51\x8d\xe7\xea\xab\x84\x06\x77\x69\x69\x9c\x07\xe6\x6f\x9f\x87\xa9\xf7\x17\x3d\xf4\xee\x8b\x31\x67\xd7\x87\xd4\xae\x48\x5d\xaf\x7b\x28\xce\x68\x0a\x6a\xb4\xb4\x9b\xe6\x27\xa6\xc4\xe8\x4d\xd3\xc6\x91\x7e\xfd\x3c\xdb\xc3\xb9\xdf\x9c\xa7\x2f\x8e\xd9\x8c\x0b\x6b\x5f\x4c\xf0\x9b\x14\x1d\xf7\x8f\xa0\x88\x48\xff\x78\x23\xe7\xcf\x45\x48\xbf\x72\x52\xee\x82\x71\x7c\x07\x0f\x7f\x69\x11\x4f\x02\x53\x43\x3c\x5a\x70\x91\xd7\xf2\xf2\xff\x2d\x63\xe7\xb4\xb3\x3f\xa0\x67\xaf\xa4\x3d\xd5\x1f\xde\xba\x58\x8e\x7d\x62\x45\x7b\xdb\x21\x24\x21\x69\x3b\xc6\xa9\xe2\x07\xc1\x25\xbb\xfb\x0a\x18\xd6\xd7\xb4\xe9\x21\xaa\x32\xa6\xbb\xe4\x1d\x9e\xbe\x5a\x9a\x36\x9f\x9b\x3c\x67\xc3\xb7\xdd\x5d\xb5\xa1\x65\x42\xc5\x3a\x5d\xb5\xb7\x1f\x8d\x0c\x01\x10\x35\xa2\x1f\xef\x6b\x01\x54\x5b\x33\x4e\xf3\xe9\xb2\x75\xdb\xad\x07\xe7\x65\x2d\x5f\xb0\x70\x7c\x79\x40\xa2\x39\xee\x41\x6f\xd7\x13\x9f\x0a\x5c\x34\x27\x71\x69\x60\xec\x73\xda\xa8\xa8\x48\xae\x57\x4a\xfa\x95\xf3\x5c\xe6\xf7\x7b\x70\x78\xb2\x9f\x75\x54\x99\x6b\x9c\xb4\x39\x77\xf5\xca\x67\x8d\xcd\xd3\x7e\xbd\xa7\xad\x29\x78\xe2\xc6\x15\x96\xbc\x59\x73\x4c\xc6\xe8\x80\x06\xcb\x81\x98\x54\x8b\x69\xe6\xfd\xa9\x61\xb2\x90\x96\x31\x67\xc9\xf7\xdf\x7c\xa3\xeb\xf9\xca\xc9\xf7\x4d\x99\xf1\xc0\x45\xdd\x7d\x21\x81\x39\xea\x38\x23\x93\x86\xc2\x6d\x00\x3e\xa2\x9b\xa8\x9e\x28\x61\x76\x6f\xbb\x3a\x36\x37\xb1\x32\x21\xee\x88\x6d\x67\x63\x61\x0a\xbd\x34\xb1\xcc\xb2\x26\xe9\x1b\x2f\xbf\xf0\xad\x70\x0e\x57\x4c\x83\xf0\x06\xc6\xb3\x3c\xed\xae\x82\x0c\x22\x9f\x9a\x6d\xb5\xce\x5b\xf0\x70\x70\x2e\xc6\xac\x8c\xfe\x79\x5b\x79\xd6\x95\xb0\x47\x1f\x47\x1b\xcd\x7b\xef\x48\x04\xcb\x07\xf4\x18\x39\x8d\xdb\x34\x01\xfc\x6c\x77\xcf\x3b\x88\xd4\xed\xec\x9e\xa8\xea\xf3\xb4\x90\x1e\x53\xdf\x83\xd5\x93\xb7\x1e\x17\xc5\x77\x96\x08\x9e\x97\x1c\xc5\xf3\xb7\x5d\xe1\x24\x7d\xd1\x91\xe0\xd9\x6f\x65\x1e\x51\xdf\x81\xe5\xe9\x3f\x73\xf4\xfe\x0d\xaa\xef\xe1\xc8\xfe\x33\xd0\x30\xf5\x89\x9f\x3c\xf5\x34\xc6\x0d\x45\x20\xc4\x85\x56\xfe\x28\xbc\xe4\x9b\xf4\x79\x37\x02\x84\x63\x72\x28\xe9\x19\x3c\x0f\xfa\x58\xac\xf8\x97\x58\xf7\x79\xd0\xd0\x0a\x20\x1e\x95\x1a\xf8\xaa\x04\x8b\x01\xd5\x25\xf9\xad\x58\x8a\xb1\x76\x3b\x6d\x23\x0e\x3b\xed\xc5\x58\x87\x4d\xdc\x8b\x85\x70\xd7\xf6\xdb\x59\xfb\x4c\x3c\xe6\xb0\x09\xbd\x82\xe9\x4e\xed\x9f\x43\x83\xdd\x4e\x37\x11\x87\xdd\x55\x20\xec\x77\xd8\xb0\x55\x2c\x18\xd2\x5e\x3b\xd8\xde\xdb\xdc\x46\x1c\x76\xe7\x42\xf1\xb8\xc3\x46\xf8\x7b\x1b\x96\xf9\xb4\xb5\xfa\xf1\xc3\x5a\x70\x59\x21\xa6\x60\x96\xdd\x4e\x3b\xa5\xf0\x62\xda\x8b\x66\x87\x8d\x9c\x72\xbf\xfb\x20\xd7\x87\x16\x2b\xaa\xdb\x0f\x0c\xb9\x25\x98\x85\x66\xbb\x9d\xbe\x26\xe9\x8b\x69\x27\xe6\x3a\x6c\xe2\x01\x35\x27\x7a\xfa\xd7\xf0\xf6\xbc\xf9\xb2\x22\xa1\xd1\x6e\x97\xf4\x45\xae\x37\x85\x6a\x87\x4d\xc8\xf6\x6d\xa7\xf6\x1b\xc2\x1a\x5a\x70\x59\x2e\x1e\x39\xcf\xe9\xd0\x57\xd0\x72\x3a\x53\x2c\x77\xd8\xae\x0b\xff\xc2\xcf\xee\xf4\xa5\x5b\x6d\x8f\x99\x05\x78\xe8\x92\xdd\x4e\xf7\x4b\x11\x65\xf4\x19\xd7\x1e\xd1\xe1\xb0\x89\xfb\x54\x3a\x32\x01\x84\xf5\x43\xe9\xc8\x2c\xc0\xc5\x5b\xb6\x48\x91\xa5\xb4\x0f\x63\x98\x7a\xdc\xf3\x4b\x23\xe4\x61\x79\x06\x17\x73\x79\x1c\x91\xcc\xcb\x5c\x17\x05\x83\xc3\x46\x6a\x5d\x7d\xe0\xdb\xde\x4f\x6d\xaf\xf3\x00\x14\x63\x3c\x07\xb0\xe4\xb8\x0e\x63\x1c\x1a\x18\x25\xb4\x03\x3c\x67\xd7\x8d\x94\xe1\xf2\x6a\x2c\x45\xad\xdd\x4e\x0f\x48\x49\x59\xae\x7d\x42\x91\xc3\x26\xb4\xa8\xed\xe3\x86\xb4\xd7\xab\x38\xe2\x6a\xb0\xf9\xb6\xdd\x4e\xf7\x4a\xc9\x99\xae\xcc\xdb\xe2\x61\x87\x0d\x03\x71\xad\x7a\xf6\xba\xda\x5e\xf6\xf2\x9a\xf5\x0d\x61\xbd\xdd\x2e\xa5\x2c\x1c\xd8\x4d\xca\x1c\x36\xb5\xcf\xe1\xf2\x88\xab\xe6\xf2\x48\xca\x52\x59\x14\xf8\x9c\xa7\x69\x14\x79\x98\xea\xdc\xf2\xe8\x94\x96\x27\x38\x2f\x88\x46\x87\x8d\x84\x3b\x2f\x80\x6f\x7b\xb7\x3c\x2c\x2a\x80\x0d\x57\x72\xfb\xe8\x96\x72\x2c\xce\xab\xc2\xd3\x87\x1d\x36\xb1\xd5\xb5\x69\x64\x7b\x9d\x07\xc1\x0b\x18\x69\xb7\xd3\xc3\x0c\x41\x3d\x06\x0b\xeb\x19\x3d\x1e\xf9\x45\x8f\x26\xbf\xe8\x5a\x6c\xc4\x00\xbb\x9d\xee\x64\x30\x2b\xc5\x03\x0e\x1b\xe6\xaa\xed\xe3\x87\xd8\x0a\x97\x1f\xc6\xdb\xf0\x60\x2f\x67\x21\xdb\xea\x0c\xfb\x3d\xe9\x76\xd8\x30\x4b\xa5\x67\x98\x5c\x2c\x8c\xdd\x2d\x5b\xbc\xac\x7e\x01\xee\x33\x0d\x47\xc8\x25\xb2\x1e\x1f\x76\xcb\x25\x37\xde\x19\x23\xf6\x39\x6c\x62\x9f\x33\x86\xb7\xd7\x8f\x26\x17\x3d\x93\xcb\x7c\x55\x90\xf1\x4e\xbd\x58\xd1\xe0\xb0\x89\x1b\x9d\x5b\xc7\xb4\x2b\x1b\x2e\xc3\x38\xde\x3e\x2f\x76\xe0\xb2\x50\x85\x1d\x0e\x9b\xb0\xdd\xa5\x9e\x49\x3e\x14\x06\x4d\x5e\x98\x8d\x28\x7b\x60\xea\x1d\xe2\x56\x87\x0d\xad\xb4\xc7\x47\x2e\x2a\xaf\x7c\x63\x44\x7c\x03\xbe\xf6\x89\x9d\xc6\x4a\x79\x71\x03\x32\x71\x38\xf8\xb3\xe7\x18\xb7\x4c\x06\xed\x29\xa6\x01\x53\xb6\x6c\x91\xf2\xe2\x54\x2e\x7d\x6c\x9a\xcf\x68\x1a\x98\x42\x70\x39\x56\xe3\x3f\xec\xf4\x0c\x3d\x42\x82\xb1\x8a\x05\x1c\x7a\x94\xd3\x99\xe3\x43\xa7\x9b\x35\x3f\xcc\xc1\x3d\x5c\x76\x47\x69\x37\xd1\x62\x2d\x3d\xc3\xc2\x8e\xd8\x84\x89\xf4\xfc\x5d\x61\x76\xd1\xf3\x0c\xc6\xd5\x25\xa4\x39\x6c\x42\x8c\xd0\x40\x6f\x8d\x0e\x63\x41\xc9\x03\xd3\x48\x3f\x63\x30\xce\x73\x62\x9c\xc3\x76\x4d\xfc\xf7\x5b\xaa\x0c\x8b\x7c\xf4\xaa\xc2\xa0\x54\x84\x2d\x68\xb1\xdb\xe9\x36\x7a\x93\x83\xa4\x88\xdd\x0e\x1b\xd9\x7c\xd5\x8d\xc3\x2b\x1b\xd5\x0a\x72\x70\xcf\x96\x2d\x2a\x13\x0e\x1b\xe9\xa6\x17\x46\x8b\xc9\xac\xa5\xd4\x8a\x79\x98\x6c\xb7\x2b\x20\x5e\xb6\xa3\xde\x61\x23\x27\xff\x7c\xa7\x78\xaf\x86\x94\x16\xf1\xb2\x9d\x76\x0b\x79\x0e\x9b\x50\x8e\x75\x77\x6a\x6f\xc3\x20\x16\x1f\xc4\xcb\x76\xd7\x4d\xd1\xe4\xb0\xa1\x45\x38\x34\x0a\x2d\x21\xee\xfc\xf0\xd6\x4d\xbb\x9d\x1e\x64\xad\xd3\xb9\xe5\x5e\x1e\x12\xab\x7c\xed\x7c\x79\x31\x46\x61\x31\x33\x29\xf1\xb3\x12\x7a\x5e\xc8\xe7\xf1\xb0\x77\x84\x6e\xbd\x76\x9b\x53\x8c\xc9\xaa\x63\x10\x52\x4c\x4f\x61\x26\x06\x39\x6c\x62\x07\xed\xf4\xc6\xe6\x91\xfe\x9c\x59\x82\xb1\x58\x68\xb7\xd3\xa7\x49\xd0\x2a\x7a\xd4\x37\x1e\xe6\x8c\xcc\x29\x39\x45\xc2\x26\xbb\x9d\xf8\x3f\xe5\xfa\xa6\xb8\xcb\x61\xc3\x68\xdf\x76\xbe\x39\x22\xa7\x10\x0f\xf5\x73\x4a\x02\x9e\xa2\xb9\xb4\x94\x14\x38\x6c\x42\xb5\xb7\xdf\xe1\x31\x31\xa7\x88\x19\x3a\x81\x52\xda\x2d\xb0\x96\xa5\x23\xe2\x89\x5b\x26\xf1\x1b\xd1\x8a\x79\xbc\xe3\x92\x2c\xd7\x2e\x31\xcd\x61\x23\x91\xce\x2b\xbc\xdf\xa4\xd1\x7c\x3f\x69\x23\x26\xb9\x65\x92\x9f\xe9\xfa\xa1\xf0\xfd\x23\x2c\x05\xb9\x9e\x07\x84\xb4\xd1\x64\x98\x56\x83\x85\x3c\x26\x76\x93\xaa\x14\x57\x1e\x26\x09\x59\x8c\x72\xfe\x48\x6f\x38\x8c\x47\x86\x69\x35\x58\x85\xfe\xbc\x08\xa9\x4a\x71\x25\x88\x6d\x0e\x1b\xe6\x0f\x6d\xef\x1b\x13\xd3\x6a\x70\xf7\x45\x96\xb5\x48\x55\x8a\xf3\xc2\x69\x1e\x13\x2d\x6a\xdb\xe1\x72\x49\xab\xc1\x84\x2d\x5b\x58\xaf\xed\x62\xac\xc3\x86\x71\x63\xe6\xce\x7a\xb4\xb8\x63\xa2\x36\xc1\xb9\x7e\x48\x4c\xb4\x8c\x26\x17\x4b\x3d\xce\x73\xc7\x44\x6d\x82\x73\xd5\x57\x89\x89\xfe\x71\xce\xd8\xaf\x1a\x13\xfd\xe3\x06\x4e\xfa\xc6\x44\xcb\xc8\x98\x68\xb1\x61\xcb\x45\x3b\x4d\x60\x6d\x97\x7b\x62\xa2\x65\x44\x4c\xb4\xd8\xd0\xbc\x65\x0b\x23\xa2\x56\x3c\xcb\x63\x62\xce\xc8\x98\x98\x83\x35\x2c\x26\x5e\xa2\xed\xa2\x2c\xd4\xb1\x98\xe8\xfa\xe0\xee\x31\xf1\x2c\x3d\xc6\x9a\x7b\x63\x62\x14\x0d\xb8\x2b\x4c\x07\x3d\xcf\x60\xbc\x31\x31\x8f\xa6\x8d\x11\x13\x07\x61\x5a\xe8\xe7\x0c\xc6\x13\x13\x37\xd2\x22\x18\xee\x47\x2a\x0c\x03\x39\xc4\x63\xe2\x5e\xfa\x29\x07\x51\x63\x62\x2e\xad\x00\x84\xf2\x11\x31\xb1\x1c\x6d\x5b\xb6\xd0\x1b\x6e\x9e\x6d\x34\x79\x48\xbf\x3e\xb1\x53\xb8\x6c\xb7\xbb\x9e\x71\xb7\xfb\xc8\x75\x76\x44\x7c\xf0\x98\x36\x66\x62\x05\xda\xec\x76\xfa\x1e\x3d\x26\xf4\x61\x33\x8b\x9f\xe2\x65\xba\xeb\x5e\xf2\x8b\x70\x1b\x6b\xe9\xaf\x84\x4c\x87\x4d\x68\x40\xcb\xbd\xe5\x17\x06\xe3\x7a\x5f\x5c\xee\xb0\x61\xb8\xd0\x40\xff\x6b\x74\xb9\xa0\x98\x83\x2f\xe0\x7a\xbb\x9d\xae\xfb\xab\x70\x1b\xdf\x77\xb6\x11\x93\xc3\x26\x1e\xa5\x7f\x1d\x1e\x5f\xdc\xd6\xee\x4e\x16\xc2\x0d\xdc\x73\xcb\x61\x13\x7b\xe8\xfb\xa3\xe7\x0a\xb1\x15\xf3\x31\xc9\x6e\xbf\x2a\xb4\xd8\x59\x28\x24\x05\x34\x63\xcc\xd8\xaf\x69\xc5\x32\x8c\xb1\xdb\x6f\x0a\x2d\x76\x4c\x42\x46\xc1\x6e\x3a\x76\x9e\x28\xe1\xee\xb3\x57\x68\xb1\xd3\x5f\x88\xbb\x1d\x36\x34\x61\xcd\x1d\xc6\x11\x9b\xb9\xe7\x1c\x60\xcd\x09\x8f\x9e\x2d\xac\x6d\xbe\xaf\xef\x4b\xaa\x36\xf3\x8b\xd0\x9f\x0b\xa3\x4b\xe8\x2a\xa2\x62\xb1\xc3\x46\x4c\xae\x20\xd5\x2f\xf3\x47\xf3\xfd\xfc\x22\x0c\xc1\x72\xe6\x97\x0c\xe0\xb6\xf0\xe2\x4d\x87\x4d\xb4\xb9\x4e\x00\xc2\xca\xd1\x7c\x7f\x65\x21\x9a\xd5\xe0\x22\x1c\x7b\x9a\xf6\x62\x02\x8f\xd1\x95\xf4\x57\xa3\xe0\xf0\x18\x4e\x7e\x09\xe6\xf0\x81\xd6\x2e\xa1\xbb\x90\x9e\xf0\x8d\x89\xf9\x23\xea\xe6\xfc\x22\xa1\xce\x6e\x17\xba\x8a\x5c\x6f\x91\x93\xdc\xa7\x0b\x47\xc6\xc2\xc2\x42\x8c\xdf\xb2\x45\x38\xf1\x34\x3d\xcb\x03\x89\x99\xf5\x65\x1d\x25\x16\x5a\xd7\xbb\x53\xda\x69\xa1\x3f\x87\x4e\x22\x0b\x1d\x36\xb1\xdb\x99\x02\xbe\xed\x87\xc8\xc3\x5a\x85\xb1\x58\xc4\xf9\xeb\xcf\xa1\xfe\xe2\xba\x6b\x0e\x9b\x18\xe7\x3c\x37\xb2\xbd\xce\xd3\x3e\x0d\xb3\xdd\xed\x5d\x57\x85\x1c\x21\xc6\x61\x13\xd2\x5c\x5d\x2a\x7f\x56\x85\x8e\x02\xb3\x1e\x57\xf2\xc2\x82\xc3\x74\x62\x86\x58\xe2\xb0\xe1\x4a\xba\x1f\x86\xd0\xe5\x13\x0f\xad\xeb\x71\xab\xd3\x4e\x13\x58\xfb\x12\x4f\x3c\xb4\x8e\x88\x87\xd6\xf5\x98\xb6\x65\x0b\x6b\x74\x89\xd4\x71\xd9\x65\x0d\x8f\x87\x46\xcc\xc2\x37\xb1\xd7\xfe\x29\xb5\xa1\x9d\x8d\xd6\x88\xc3\x59\x38\xb2\x26\xf0\xfa\x63\x26\xee\xc1\x65\x76\x3b\xbd\x4c\x7f\xcc\xda\xd3\x0e\x5c\xee\xb0\x89\xb5\x18\xe4\x3c\x73\x07\x98\x1f\x72\x13\xf9\x88\x76\x33\x18\xd7\x55\x21\xdc\x61\x13\x4a\xf0\xa6\x4b\x18\x84\x69\x1c\x1a\x0f\x3d\x30\x47\xe8\x1f\xd1\x2e\x3a\x9d\xfb\xc4\x42\x87\x6d\xaf\xb8\xc1\xb5\x10\x86\x8f\x3d\x3d\xf1\xd0\x03\x72\x90\xfe\x95\xa1\x71\x57\xff\xd4\xb5\xd2\x67\xec\x39\x18\xe7\x32\xf1\x87\x5b\xb6\xd0\x3f\xb8\x99\x8e\x74\x25\xf1\x7e\x1b\x86\xf4\xcb\x3d\x19\x1b\xb0\x04\x73\xec\xf6\x8b\xf4\x00\x36\x0b\x3f\x43\x0b\x2b\x29\x4f\xbb\x8a\x86\xb4\xf7\x89\x8b\x46\x6c\xc0\x6a\x56\x54\x5e\xa3\x87\xb1\x59\xe8\x53\xc3\xa2\xab\x7a\x44\x1d\xe2\x95\x4f\x12\x1e\x72\xe7\x98\x43\xb8\x57\x5c\x44\xf3\x84\x6c\x87\x4d\x58\x89\xdb\x58\x06\x1d\x0d\xc6\x32\x08\xd3\x41\x3f\xc2\xbd\xe2\x62\x57\x94\x58\xef\xb0\x1d\x11\x6e\xb8\x0e\x0f\xc1\xe3\x2b\x1f\x0f\xc8\x01\xda\xc7\x40\x9c\x3b\x89\xec\xb0\x89\xcd\xae\x6e\xb5\xfd\xf0\xb8\x98\x84\x87\xb6\x6c\xa1\x3d\xb8\x53\x5c\xda\xea\xb0\x89\x9d\xae\x56\x40\x68\x1a\x21\x1f\x11\x9b\x30\x9f\xf5\xdb\x4f\x77\x62\x27\xe6\x0b\xd5\x3c\x34\x96\xaa\x79\xa0\xc9\xd7\xde\xd4\x7e\x9b\x84\xbd\x76\xbb\xeb\xe7\xd8\x29\xfc\xe5\x8a\xc3\x26\x9e\x77\xd5\xf9\xb4\x1b\x92\x5f\x9a\x30\x0b\xf3\xed\x76\x7a\x91\xfe\x11\x3b\xf1\x19\xb5\xfe\xa4\xc7\x60\x58\x7b\xaf\x1c\xdd\x84\xd0\x9f\x2b\x80\x9d\x6c\xfc\x22\x36\x3a\x6c\x98\x81\x09\xf4\x32\x8c\xa0\x9d\x87\x52\x8d\x07\x64\xef\x05\x06\xe1\x3a\x47\xea\x1d\x36\x21\xe7\xf6\x88\x5a\xd4\x53\x45\xab\xb9\x02\x8f\x61\x8b\x10\xeb\xb0\x09\xcd\xb4\x1b\xc6\x1a\x5b\x88\xad\x98\x8b\x29\x76\xfb\x79\xcc\xb7\xb3\x10\x27\xf6\xb9\x6c\x63\xe6\x0b\xb1\x15\x97\xb1\x92\xeb\x06\xe6\xdb\x85\x2a\x66\x63\xa2\x89\x26\xc0\x9d\xc6\x16\x53\x78\x5c\xef\xc5\x7c\x3b\xda\x85\x48\x2f\x31\x63\xe5\x0c\xf7\xd4\x16\xe6\xdb\xe9\x75\xd2\xa9\x46\xdc\x61\xf5\xb9\x3b\x67\xe4\x14\x22\xa0\x9d\x85\x23\xac\x2d\xfb\x84\x6c\x73\xd8\xc4\x73\xce\x38\x18\x39\xb6\x90\x3c\x19\xb4\x10\xfd\xb1\xde\x0d\x70\x5b\xfc\xc3\xfb\x0e\x9b\x98\xef\x6c\x1f\x7b\x2c\x52\x88\x91\x58\xe1\x6e\x4f\x1d\x82\x6d\x68\x8c\x1c\x0b\x26\x45\x8d\xab\x0c\xe6\x3c\x26\x8a\x4d\x2c\xce\xd3\x33\x43\xe7\x73\x34\xde\x3c\x63\x58\x5e\x88\xb5\xe8\x6f\xa7\x09\x58\x53\x4e\x0f\xf0\x20\xc9\xdb\x0d\x8b\x91\xcb\x0b\x31\x79\xcb\x16\xd6\xe6\x22\xab\xb6\x87\x8e\xc9\xad\xee\x18\x19\x8f\x87\xb1\xd7\xfe\x09\x7d\x36\x4e\xca\x63\x21\x72\x40\x1e\x5a\xd7\x7a\xc8\x34\xa1\x05\x0f\x73\x83\x72\xd0\xad\x71\x52\x1e\xed\x41\xab\xc3\x26\x6e\x75\x0c\xd4\x8d\xa8\x85\xad\x5e\xbb\xf5\xc0\x9c\xa7\xed\x71\x52\x9e\xab\x97\x9b\x56\x36\x7e\x3a\xd0\x33\x7c\xde\xc2\xea\xf5\x7f\x3d\xfe\x4f\x0e\xd3\x4d\xdb\x12\xa4\xe5\xce\xf3\x6c\x74\x79\x4d\xd4\x39\xb5\x30\x7c\x6e\xc4\xea\xf1\xff\x48\xfc\x95\x9a\xa9\xe9\x4f\xe3\xa5\x5c\xdf\xc9\x91\x21\xf3\x0b\x56\xd5\x0a\x62\xf0\x04\x33\x75\xce\xb0\x7b\xb8\x30\x74\xdc\x65\xf5\xc4\xc7\x78\xec\x64\xfd\xf6\xd2\x3c\x2b\x11\x30\x8b\x85\xc7\x3e\x67\xe8\x88\x79\x22\xab\x37\x3e\x46\xe3\x11\x36\x4e\xfb\x82\x3e\x95\x40\x92\xd4\xf0\xe8\x8c\x84\xe1\x73\x57\x83\xf2\x31\xe1\x71\x77\xce\x79\x35\x81\x64\xd3\x0e\x36\xda\x15\xd6\x63\xb0\xb3\x7e\x0c\x18\x0b\x83\xe9\xe3\xd3\x5d\x7d\x74\xaf\x85\xa4\xbb\x1a\x58\x59\x70\x4a\x28\x77\x9e\x1d\x8a\xc7\x57\x3e\x26\xfc\xc0\x2d\x9f\x9f\x25\x90\x02\xe7\x05\x12\xee\xb0\x89\x46\xe7\x05\x18\x3a\x27\x65\xf5\xcc\xa8\xe1\x07\x5b\xb6\xb0\xa6\x5d\xdb\x59\x06\x74\xda\x87\xcd\xfb\xb9\xe5\x98\x25\x5c\xb5\xdb\x5d\xdb\x17\x4a\x29\x0e\x1b\x29\x1b\xd8\x3d\x62\x3e\xd1\xc3\xa7\x06\xe3\x58\x25\x68\xb7\xdf\xa6\x95\x99\xc2\xaf\x70\x2d\x06\x3a\x6c\xe2\xe1\xdb\xae\xcc\xa1\xf3\x95\xde\x32\x0a\x97\xa3\x1d\x57\xda\xed\xf4\x36\x6d\xc9\x12\xce\xab\xe1\xd1\x55\x7a\x27\x3b\x3b\xc4\x12\x19\x3d\x4b\x5b\x73\x84\xcb\xb4\x43\xdc\xe7\xb0\xa1\x01\xe3\xdc\x39\xc3\x32\x8a\x4c\x3c\x20\x9d\xf4\x67\xcb\x84\xcb\xae\x3e\x52\xeb\xb0\x09\x06\xd7\x45\x18\x3a\x7f\xe9\x2e\xc3\x30\x0e\x8f\x31\x99\x64\x09\x97\xb9\x8e\x58\xc3\x21\xb9\xda\xea\xc9\x19\x99\xb8\x1d\x0b\xec\xf6\x4b\x34\xb7\x0c\x6b\x19\x1d\xa2\xc3\xd5\x42\x2b\x60\xd8\x3c\xb4\xa7\x0c\x13\x71\x19\xbe\xc9\x94\x73\x9e\xe6\x54\xe0\x4b\xc2\xfe\x4f\x1c\x36\xb1\x9c\xce\xa4\xe5\x43\xe7\xb7\x3d\x74\x2c\x13\x2e\xd9\xed\xae\xfa\x0a\xe1\x0c\x4f\xa5\xd5\xae\x37\x87\xce\x9b\x0f\xca\x30\x17\xd7\xe3\xb3\x76\x3b\x3d\x43\x3b\x2b\xb0\x5a\x2d\x45\xe9\x11\x18\x36\x2f\xef\x95\x87\x9b\x0c\xda\x49\xbb\xcb\xf1\x25\xfa\x6b\x72\x8a\x47\xa1\xde\x61\xf3\xdb\x1e\x3a\xd4\x22\xe3\x67\xa5\x68\x13\xf7\x3a\x6c\x18\x43\xfb\x86\xc6\x67\xb3\x3b\x57\x60\x2b\x06\x62\x03\x4b\x75\x76\x16\xa8\xc4\xe3\xce\x85\x23\x62\x3f\x6b\x6b\x71\x37\x0e\xe2\xe3\xae\x8b\x76\x12\x73\xd6\x61\x13\xa3\x9d\xfd\xa3\xb4\xf5\xe4\x89\xc9\x58\x6d\xb7\xd3\x4b\x76\xe1\x0b\x41\x76\xd8\x84\x85\xae\xe3\x63\xb7\x35\xf3\xda\xb8\xd7\x8e\x85\x9c\xde\x58\xda\x0b\x12\x14\x28\xd7\x49\xbf\x66\x22\x7f\x9b\x8e\x19\x32\x20\x7b\xf0\x8d\x82\xe6\x54\xb4\x9a\x03\x51\xe3\xf3\x1a\xf1\x68\x9f\x77\xea\xb8\x1f\x75\x07\x62\x88\xd5\xa0\x31\x59\x87\x1c\x32\x1c\x62\x35\x4f\xd4\x6b\x8c\xd3\x0b\x5e\xba\xb9\xf3\x89\x7a\xb3\x76\x42\xd2\x7d\x34\x6e\xd5\x7d\x0b\xe4\x94\xfb\x23\xd3\xca\x4e\xc5\x69\x57\x34\x15\x36\xb5\x62\xc2\xfc\x85\x0f\x6f\x58\x90\x3e\x7f\x71\x6d\x96\x5f\xb4\xb0\x35\xda\xd5\x15\x5c\x1d\x14\x67\x4d\x37\xa7\xa4\xec\xfd\x39\xb9\x4e\x82\x65\x7b\x09\x36\xfc\x0e\x9f\xec\x5e\x56\x14\x55\x74\xdf\xa3\x7f\x7f\x91\xbe\x3f\x45\x3f\x3f\xe0\xb3\x29\xff\xb2\x3a\xb3\xf7\xc2\xda\xc2\x6d\x38\x3e\x7f\x79\xf1\xcb\x97\x84\x03\x27\x4e\x5c\xc9\x1f\xbf\xc8\x7f\x46\x7c\x9c\xf5\xe1\x79\x15\xdf\xc1\xec\xb0\xdd\xcd\x11\x27\xd5\x73\xaf\x87\xf3\x98\xf3\xdf\xc2\xa3\xd5\xe2\x59\x77\xf0\x55\xb9\xbc\x18\xc2\xb8\x4c\x33\xa7\xa6\xec\x6d\x8f\x4a\x0d\x42\x79\xda\xcb\x69\x5f\x8f\x4d\x7d\xc4\xc2\x43\xc9\x61\x73\xdf\xc9\x18\x85\xcf\x05\xfc\x9c\xeb\xaf\xc1\xa7\xe7\x41\xde\x04\x54\xdf\xc6\x6e\xfa\x9a\xca\xec\x5f\x99\x15\x67\xde\x2a\xa4\x5a\x42\xd6\x3e\x8f\xa6\xaf\xaa\x4e\xdc\xf7\xd8\x9a\x04\xd3\x3a\xff\x80\xc8\x68\x21\x5f\x28\xfd\xf3\x98\xfa\x5c\x00\x0f\xff\xf7\xf0\x29\x7d\x6d\x85\xde\x72\x73\x3a\x3b\x78\xed\xf3\x18\xfc\x95\x55\x3a\x8c\xd5\x15\x83\x4a\xf5\xf0\xfa\x28\xe7\x35\x05\x96\x42\xde\xd7\xe0\xd5\xec\xbb\xde\x2b\x0d\x13\x7d\xd6\x93\xbb\x1d\x75\x06\xde\x3b\xcb\x91\xcd\x9a\xc7\xf3\x57\x54\xde\xff\xfa\xb4\x0f\xf7\xb4\xbd\x9e\x13\xfc\x82\xae\x94\x9b\xb2\xdb\x61\x53\x67\xdd\x13\xdf\xe2\x21\x6b\xdc\x43\x73\xbe\xbb\x65\x73\x6b\xfe\xb8\xc5\xa1\xb9\xdc\x9c\x6d\x98\x1d\xba\xbb\x39\xe2\x3b\x2f\xfd\xef\xe7\xdb\xed\xbc\xf2\x57\x50\x75\xc4\x10\xbe\x4b\x82\xab\x75\x4f\xa5\x9b\x53\x53\x5a\x0f\x72\x7d\x3f\xf7\xad\xaf\xca\x76\x40\xa6\x87\xed\x89\x4c\xe1\xa1\x3f\x6d\x18\xa9\xef\x87\xe1\xb1\xff\x55\xbe\x43\xfe\x97\xbd\x79\x28\xe3\xcb\x1f\xcf\x8a\x9b\xfd\x8a\x90\x6a\x09\x7e\xea\x39\xbc\x5f\xfa\x84\x84\x68\xec\xa5\x5f\x8d\x77\x2c\x7c\x6c\xcd\xcc\xe9\xe5\xfe\xe3\x23\xa7\x73\xd7\x0e\xdd\xbe\x37\xe2\x37\xa3\xf0\x9e\xff\xdf\xcd\xbb\xe4\x59\x0b\xf1\x75\x99\x2f\xf3\x0d\x69\x21\xe9\x0f\xa1\x6c\xfa\x5e\xfa\xff\x12\xf3\xb9\x11\xaf\xfc\x30\x34\xed\xa7\x19\x00\x04\x8a\x95\xeb\xe2\x03\x9a\x89\x10\xc4\x77\xf2\xc4\x02\x58\x67\x5b\x43\x0c\x3e\x2c\x4f\xbf\x43\xaa\x2d\xd6\xbf\x89\x71\x7b\x02\xf2\x33\x56\x57\xed\x79\x6d\xfb\xc4\xb1\xd2\xe9\x67\xb3\xd7\x09\xe7\x5c\x11\xc9\xfa\x2c\xe3\x25\x4b\x3d\x79\x6c\xec\xbc\xa9\xd2\xf3\x6d\x2f\x3d\x71\xf7\x46\xcf\x60\x5a\x1c\x8d\xa2\xd1\x52\xdf\x5d\x48\xf2\xcd\x71\x43\x65\x74\x3f\x3c\x34\x06\x4d\x63\xa5\xb0\xd1\x48\x1a\x35\x4d\x8d\xa4\x69\xcc\x7c\xa4\xd2\xf4\x2d\x2f\x4d\x33\xee\x91\x26\xe9\x8e\x82\x1a\x3d\xa5\xdc\x95\x2c\x9f\xdc\xa1\xd2\x35\x57\xf3\x28\x04\xc1\x14\x78\x88\x8d\x00\x46\xd2\x75\x2f\xa9\x61\x28\x79\x93\xef\x16\xfe\x87\xd2\x28\x3d\x79\xa7\x38\xef\x91\xdd\xd7\xa5\xd1\x1b\xc6\xef\x44\xe3\xc8\x50\x3d\x26\x89\xa3\xc5\xe4\xa1\x72\x9c\x01\x89\x77\xa5\x71\xac\x90\x7b\x27\x22\x47\x0d\xab\x63\xd0\x39\x7a\xfc\x54\xe9\x7c\xda\x4b\xa7\xf5\x2b\xd3\xe9\x0d\x8f\x77\x22\x74\xd4\x10\x78\x6f\x84\xfa\xc6\xba\x1a\xe5\x3a\x69\xd6\x18\xf8\x39\x78\xee\x37\x18\x7b\x68\x9d\xaa\x33\x04\xf9\xf3\x4d\xfd\x38\x76\xb8\xab\x09\x6a\xc0\xd8\x86\xc0\x6d\x68\xc1\xb8\xe5\x7b\xfe\xfe\xa3\x9e\xdf\xa1\x61\xcc\x21\x44\x79\xe6\x72\xa1\xd8\xb5\x2b\x65\x5e\x8b\x58\x4f\xdf\xa6\x6b\xa8\x62\xff\x25\xd1\x8f\x11\xfa\x54\xda\x5a\xbd\xb4\xcd\xbc\x67\xda\x06\x43\xdf\x98\xd4\x8d\x5a\xfa\xdf\x13\x79\xbe\x61\x70\x98\xfc\xa2\xf9\x9b\x50\xc7\xa0\x71\xac\x50\x38\x26\x89\xa3\x97\xed\x63\xd1\x38\x7a\x58\x54\xe9\xdb\xeb\xa5\x2f\xe1\xde\xe9\x93\xee\x2e\xc4\x31\xca\xed\x7b\x24\x71\xc5\x90\x7c\xa2\xca\xf1\x51\x08\xe1\x55\xc7\x9c\x31\xe8\xbc\x97\x30\x39\x0a\xb9\x11\x77\x2d\x95\x47\xa3\x59\x0a\xbe\x53\xc8\xfc\xef\xa0\xd9\x1b\x36\xef\x4a\xf3\x28\x65\xee\x5d\x48\x1e\x2d\x84\x0e\xa3\x39\x01\x92\xee\x85\xe6\xb1\xc2\xe8\x5d\x89\x1e\xbd\x44\xbd\x23\xdd\xa3\x87\xd4\x11\x74\xcf\xfd\x3a\x74\x7b\xc3\xea\x5d\x09\x1f\xbd\xbc\xfc\x2a\x84\x0f\x86\x58\x90\x78\x3e\x58\xa5\xe9\x81\x20\x7e\xba\x06\xf7\xc2\x91\x19\x61\x70\x21\x2f\x73\x46\xef\x42\x7a\xef\xc7\x43\x73\xc1\xf4\x65\x8b\xeb\xb2\x96\xd6\x9b\xa6\x0b\xaf\x44\x53\xe3\xb9\x49\xf3\x36\xce\x2a\x7b\x55\xfd\x6c\x58\x6d\x72\x38\x6b\x69\xe9\xc2\xe5\x38\xe7\xc4\x09\xfc\xf5\x84\xb5\xcf\xeb\x66\xd4\xb8\x9a\xf8\x47\xf0\x35\x69\xf3\x6e\x15\x10\xef\x85\xb6\xda\xc5\xab\x2e\x4e\xdb\xb3\x24\xf6\x2e\xb4\xfd\x33\x64\xe9\x4b\x13\xa6\xdb\x66\xd2\xc4\x61\xb4\x7d\x5b\x73\x82\xd3\x16\x0d\x33\x99\xd6\xef\x44\xdb\x28\x8b\xdf\xef\x2a\xc0\xa4\xa6\xbc\xfc\x83\x3e\x6b\xe3\x37\xce\x2a\xfb\xc1\x1d\x48\x15\xaa\x3d\x0b\xe7\x03\x2b\xca\x99\x28\xf7\xa8\xe4\x0e\xa5\x75\x3a\xc4\x33\xcf\xba\x37\x5a\x07\x17\xfd\xdf\x45\x9e\xd6\x66\x0f\xa9\xf4\xec\x15\xf3\xfa\xfe\xf0\xd6\xc5\x53\xee\x4e\x2a\x92\x10\xf3\x5b\xfe\x53\xb6\xce\xa4\xe9\x6e\xc9\x4a\x6e\x5f\xea\x81\x10\x88\x04\x03\x3c\xc8\xdf\x57\x38\x9a\x37\xdd\xcd\x24\x47\xf1\xa3\xb8\xb1\xed\x72\xf4\xbc\xb0\x6e\x4c\xf3\xfc\x9a\x74\x8e\x62\x9e\x77\xa3\x73\xa8\x8d\xde\x8d\xce\xe1\xa6\xaa\xd2\xd9\xa2\x39\xc1\xe9\x7c\x10\xcc\x90\x72\x57\x3a\xef\x62\xaa\x63\x13\x3c\xb6\xbd\xde\x89\xec\xb1\xcc\x76\x18\xed\x31\x30\x0b\xe6\x7d\x05\xda\x47\x33\xdd\xb1\x49\x1f\xdb\x7e\xef\x81\xf4\x91\x66\xcc\xcf\x1f\xc9\x95\x76\xaa\xef\x4b\x35\xa3\xc1\xe7\x84\x13\xbe\x51\xc3\xa2\x6e\xdb\xe0\xfb\x85\x04\xf5\x40\x12\xb8\x4f\xbb\xbe\xb7\xee\x5f\xff\x23\xe4\xc4\xec\x7f\xfe\x69\xf5\x93\x8f\x3d\xb2\xb6\x6e\xf2\xe1\xa0\xc3\xdb\x6f\xc6\xed\x96\x8e\x7e\xf2\xea\x86\xdf\xff\x38\xed\x49\x67\xdd\x7f\xfd\x29\xc2\x15\x5a\xdb\x28\x66\x65\x26\x1d\xa6\x97\xfb\x5c\x31\x6e\x5c\x72\xa8\x7a\x5e\x8f\x19\x0d\x68\xb6\xf2\xf7\xe6\xca\xc4\x8b\x08\x8d\x1a\x59\xc5\x92\x8d\xf5\xfe\x01\x91\x11\x8d\x18\x4c\x4f\xcf\xa0\xff\x3c\xfb\x62\x66\xc1\xe2\xaa\x6f\x4f\xa5\x45\x5a\xed\xd4\xc9\x4d\xd2\x51\x67\xf4\xf2\x0f\x37\x0a\x39\x8e\xec\xbe\xbe\x49\x37\x27\xe6\x97\x92\xdc\xe4\x3f\xd9\x5d\xcb\xdd\xfb\x43\x95\xeb\x9c\x27\xfe\x46\x35\xab\x81\x6b\x21\x02\xdd\x4c\x18\x42\x7c\xb9\x14\xc0\x30\xed\xfe\xb6\x20\x8c\x0b\xb8\x88\x7e\xf3\x97\x07\x1f\xde\xfe\x79\x22\xfd\xe8\x87\x83\x5c\x16\x24\xd1\x63\xf4\xda\x5f\xe9\x3f\xb1\x29\x27\x3d\x35\xe5\x30\x26\x60\xed\x23\x33\x0f\xd3\x3f\xff\x5d\x70\xb8\xb9\xa5\x2b\xe9\xdf\xe9\x3f\xff\x02\xee\x77\x56\x5f\x27\x5d\x72\x94\xfb\x1d\x56\xb3\xdd\xa7\x88\x78\x5f\x56\xe8\x33\xcd\x33\xf4\x45\x95\xb2\x46\x94\xeb\x74\x9a\x67\x2c\xce\x2b\x67\xfe\x74\xec\x5f\x6d\xaf\x36\xbb\x0e\xfc\xee\xaf\x18\xbb\x3c\xbf\x6c\xeb\x86\xa7\xe3\xcd\xf3\xd6\x6f\x5a\xb1\xe0\xd1\xb2\xfb\xea\x03\xb1\x31\xe6\x7b\x53\xd1\xf1\xe5\x7f\xbe\xfb\xa3\x8e\x5f\x4e\xd6\xff\xf8\xbb\xdf\xff\xc7\x8b\x7d\xbf\x58\xb9\xfc\x87\x1b\x9e\x58\x7d\xf3\x95\x17\xd3\x1f\x79\xf1\x5b\xae\x53\xf3\x01\x44\x38\x47\xda\xc5\x4d\x1a\x01\x44\xf7\x4e\xba\xb1\x47\x20\xe7\xc6\x1a\x6e\x90\xf6\x31\x27\x55\xd4\xfe\xcf\xbb\xfb\x9f\x3c\x6a\xff\x83\xa3\x88\x73\x63\x0e\x19\x46\xa0\xf0\x19\x1d\xf8\xf2\x10\xc2\xec\xe6\x4e\x13\x22\xe7\xc6\x2e\xf9\x19\x8e\xb1\x26\x3d\x54\x1c\xfd\x6e\x1c\x91\xa3\xe3\x90\x86\x31\x32\x7a\xd9\x3e\x0a\x9a\xc1\x0a\x5d\xa0\x35\xa4\x1f\xb7\xca\x06\xf0\x87\x10\xf7\xae\x23\x75\x8b\x91\xde\x53\x54\xd1\x9a\xac\xf9\x73\x93\x33\x16\x6f\xbc\xbd\x6c\x2b\x2e\x58\xd4\x9b\x21\x15\x2f\x5a\x3a\x3b\x21\x63\x45\x94\xfe\xf1\x3f\x84\xe4\xbc\x3b\x83\xdb\x18\xdd\x4e\xfa\xb1\x5a\xbe\x02\xe3\xd5\xb7\x27\x9a\xa7\xa0\x9e\xc5\x10\x59\x63\x98\x6e\xf5\x06\x11\xba\x7d\x6f\xc4\x0b\x91\xdf\xfc\xe6\x81\xdf\x3d\x4a\x6f\xcd\xdd\x98\x35\x7f\x63\xc6\xe2\x8d\xb2\x36\x7c\xd2\xb7\x8c\x65\x2b\xc2\x7f\xb9\xee\xbb\x03\x8b\xb2\x4b\x33\x56\x00\x88\xb4\x89\xf4\x63\x15\x3f\xb3\x43\xed\xd1\xc3\x3f\xef\xc7\x34\xd8\x63\x53\xb4\xf0\x4a\xb4\xeb\x97\x8f\x2c\xae\xcb\xca\xa9\xc7\xba\x47\x16\xd7\x2d\x59\x5a\xcf\x8f\xf1\xa8\x65\x01\xe5\x91\x52\xfe\x2f\x3f\x67\x8a\x6e\x27\x7d\x9c\xc6\x89\x30\x15\x1e\x74\xef\xef\x9e\x22\x78\x02\xf6\x0c\x81\x5b\xfc\x68\x48\xb6\x4f\xfa\x76\x7e\xfc\xd2\x74\x6b\x44\x9a\xa1\x21\xb2\xfe\xd1\xb8\xc5\x29\x89\x11\xd3\x67\x8f\x8b\xf3\xc1\x9a\x95\x53\x4f\xfa\x5e\xf8\xe6\x64\xe3\xe4\x27\xeb\xab\x26\x4f\x9b\x6c\x31\x61\xdd\x50\x02\x04\xda\x4c\xfa\xb0\x52\x13\x00\x61\x7c\x87\xd7\x20\x76\xd9\x83\xdc\xbd\xd7\x6b\x3a\x6d\xf6\x20\x4c\x37\x34\x24\xbd\xad\xe2\x33\x8f\x0b\xc2\x50\x53\x41\xc7\x8f\x3c\x78\xae\x73\x34\x82\x21\xb4\xb2\x69\xd2\x4e\xe0\xba\xec\xc3\xad\xbc\xff\x29\x63\xf5\xef\x55\xea\xa4\x6f\x3f\x16\xbf\x34\x7d\x0e\xe3\x28\xe9\xed\x87\xb2\x54\x04\x9b\xb6\x2d\xc4\xa4\x87\xde\x2f\x19\x8a\x01\xa3\x26\xbe\xb5\x36\x38\xee\x8d\x74\x86\xe3\x00\xe9\xc7\x02\x4d\x00\x88\x10\xe0\xd6\x8a\x67\x7f\x1a\x3d\xc0\xad\xb0\x17\x43\x1e\x5a\xd3\xb1\xf0\x25\xa6\x03\x21\x2a\x74\xfd\x0f\xc2\x53\xde\x04\x81\x6e\x25\xfd\x58\xc3\xe1\xc6\x7b\xe0\xac\x1e\x62\xb6\x46\x0b\x5b\xa7\xd3\xe4\xa4\xef\xce\xc4\xb9\xb1\xbf\xda\xc0\xb5\xe7\xaf\x4f\x7d\x25\x2b\xf8\xa1\x96\x47\x40\xa4\xb5\xe4\x34\x6e\xd6\x04\x82\x3f\xe8\x61\xda\x10\x2b\xe5\x39\xd6\x63\x67\x3e\x3b\xe0\x69\xed\xb2\xc5\x29\xa9\x59\x4b\xeb\xa3\xf7\x2d\x2a\xde\xb3\xe2\xe8\x9f\x96\xd0\x2f\x96\xdf\x70\x7f\x26\xc5\x67\xe5\x58\x66\x2e\x7c\x44\x88\x0f\x9d\xf5\xd4\xba\x19\xa1\xc7\x97\xbd\x4a\x7f\xa2\x7e\xa4\xda\x49\x33\x39\x8d\x95\x72\x1f\x3f\x77\x25\x7c\x28\x3e\xab\x41\x23\xf9\xa0\x69\x7e\x84\x75\x99\x53\x1f\xcd\xac\x90\x7e\xe8\xfe\xcb\x83\x00\x97\x9d\x38\xf1\x37\x6f\xc7\x02\x6d\x24\xfd\x68\x93\xfb\x20\x8c\xf7\x3a\x8a\x7e\x44\xab\x41\x43\x1b\x7d\x8c\x2d\xe9\x48\xdc\xe2\x54\x4b\x44\xb4\x79\x5c\x32\x13\x2e\xe9\x1f\xa2\x97\xf4\x13\x27\x40\xd5\xc9\x69\x2c\x90\xfb\x06\x65\xeb\x21\xd1\x38\x4d\x55\x0a\x0d\x5f\x92\x31\x27\x69\xcb\x0b\x72\x38\x27\x28\x31\xbe\x99\xc3\x5d\x93\x23\xb1\x45\x1b\x33\xa8\x4b\x49\x35\x79\xe3\x34\x7a\x8d\x33\x34\x29\x3b\xe3\xf9\xcd\xd5\x9a\x8a\xf7\xde\xbb\x96\xb5\xb4\xb4\x99\x8d\xd7\xbe\x20\x47\xc5\xeb\x9a\x13\xe0\xc7\xad\xcc\xf3\x56\xc9\x7b\xa9\x20\xbe\xb8\x5b\xb9\x20\x45\xdc\xb1\x32\xf0\xc5\x3d\x11\xa2\x20\x66\x0c\xdc\xa3\x56\x5e\x5f\xdc\xad\xcc\x1a\x8a\x7c\x64\x45\xe5\xe1\xfd\x34\x7f\x57\xd4\x78\x1e\x43\xe0\xae\x03\xa8\x2f\xc6\x2e\x47\xdd\x08\x47\x1f\x24\xdd\x15\xd7\x28\x55\xfb\x17\x63\x97\xe8\x3e\xb8\x46\x0e\x16\x45\xb8\x45\xda\xc4\x4b\x9a\x34\x18\x0f\x91\xfc\x4c\xae\x7b\x1b\x6d\xdf\xba\xfb\xd0\x5a\xea\xb8\xcb\x28\x5a\xc5\x7d\xc4\x8d\xdb\x74\x37\xdc\x9e\xac\x7a\xeb\xee\xd3\x11\x63\xa1\xf6\xcc\x3c\x78\xf8\xbe\xc5\x71\xf3\x13\x0f\xef\x69\x22\xfc\xd6\x5d\xa6\x6f\xbc\x78\x47\x9d\xa9\xf1\xe5\xf7\xae\x38\xbd\x33\x5f\xb7\xee\x36\xcd\xe5\x83\x74\xb4\x19\x2d\x56\x7f\x76\x90\xcb\xe2\x0d\xe9\x2a\x3f\x9f\xc4\x6a\x98\x80\xc6\x68\xa3\x86\x5f\x1d\x21\x62\x5c\x48\xf5\xa2\xf0\xc6\x45\x99\xec\x92\xb6\xaf\x5c\x79\xf0\xe9\xa7\x9f\x7e\x9a\x9f\x19\x84\xfe\x29\xef\x3d\xd9\xf4\xbb\xd5\x13\xe6\xfd\x97\x10\xc5\x57\xc7\xc1\x6f\x02\x36\xdd\xf4\xdc\x07\xae\xb8\x0e\xf8\xaf\xd4\x6e\x03\x11\xb4\x9e\x53\x86\xd8\xbf\xda\x6d\xae\xef\x00\xf8\xb7\x0c\x5c\xf9\xf2\xa6\xff\x4a\x28\x85\x30\xf0\xf9\xf1\x7b\x8e\x9c\x01\xbe\x5c\x91\x84\x02\x08\xec\xca\x86\x70\xb1\x15\x7a\xa4\x58\x88\x21\xe5\x60\x96\xfb\xa1\x5a\x6a\x87\x85\x82\x3f\xf4\x08\x47\x21\x5b\x38\xaa\x54\x92\x42\x38\x48\xca\xa1\x52\xc8\x52\x76\x0b\xcd\x10\x23\x64\x41\xb8\x58\xa4\xec\x27\xe5\x90\x41\xca\xe1\x28\x29\x57\x3e\x22\xe5\x10\x48\xca\x95\xab\xa4\x1c\x22\x48\x39\xac\x24\xe5\xb0\x8c\x94\x83\x95\x94\x43\x3e\x6b\xcf\x60\x59\x1f\x9e\x4b\x3c\x08\xfb\xe5\x7e\x28\x94\x64\x65\x13\xb9\x05\x16\x72\x05\xea\xa4\x0a\xb0\x90\x7c\xb0\x90\x34\xb0\x48\x9b\xa0\x4e\xda\x0d\x16\x31\x48\x39\x29\xec\xa7\x27\xc8\x55\xb0\x10\x13\x58\x34\xfe\x60\x91\xfd\xc1\x22\xf5\x41\x1d\xb9\xe4\xbe\x5f\x04\x0b\x49\x81\x18\x92\x06\x07\x24\x3b\x6c\x23\x9d\xd0\xa9\x89\x86\x4e\xd2\xaf\x6c\x25\x8d\x70\x8c\x64\x2b\xdd\xc2\x7e\xe5\xbc\x58\x04\x17\x84\xfd\x4a\x0d\x29\x07\xa3\x68\x56\x32\x49\x15\x3a\x49\x17\x14\x90\x6e\x30\x89\x17\xa0\x80\xff\xbe\x11\x0a\x04\xa7\x62\x22\x5d\x10\x41\x7a\xc1\x24\x14\xb3\x8b\xde\x26\x5b\xd5\xdf\x35\x29\x60\x62\x9f\x93\x43\x0c\x4e\x39\xce\x60\xc4\x22\x30\x89\x3d\xa0\x17\xb3\xa0\x88\xf4\x42\x15\x09\x87\x32\x79\x19\xd4\x93\x34\xa5\x85\x44\x2b\xd5\x62\x9b\x72\x56\xe8\x53\x6e\x93\x72\x3c\x25\xf4\x29\x2d\x5c\x96\x5c\xf6\xca\x51\x52\x0e\x6d\xa4\x5c\xf9\x82\x94\x43\xb5\x2a\x37\x3c\x25\x5e\x86\x50\x52\x85\xad\xf2\x01\xd8\x2c\x12\xd8\x45\x6c\x90\xc5\x61\x9a\x21\x86\x7d\x46\x00\x0e\x8b\x95\x0c\x0e\x2a\x45\x2d\x24\x8b\x5a\x28\x24\x55\x78\x99\x5c\x52\x8e\x4b\x29\xd0\x2c\x64\x41\x23\xb6\x29\x09\xa2\x16\x1a\x84\x9b\xb0\x8f\xd8\x00\x34\x01\xb0\xc6\x7d\x6d\x12\x0f\x2a\xc7\x99\xdc\x47\xbb\x34\x31\xca\x26\xa6\x0b\xae\x07\x9f\x8b\xe9\xc1\xf7\x92\x2a\xc0\xe4\xd1\xc3\xf0\x8b\x94\x43\x83\xd4\x07\xa5\x4c\x17\xbe\x17\xd7\x45\x3f\x58\xa4\x4c\xaa\xca\x7d\x94\x4b\x76\x40\x01\xd7\xc5\xc6\xa1\x97\xaa\x07\x7e\xdd\xcf\xee\x64\x2f\x64\x79\xf5\x30\xfc\x62\x36\x76\x08\x62\xb9\x2e\x7c\xaf\x68\xa5\x9a\xeb\x2c\x5a\xa9\xe6\x76\xd7\x05\x05\xc3\xef\x8c\x77\x8e\x7f\x8c\x3b\xb7\xd1\x2e\x7e\x37\xf1\xf6\x4c\x3e\x1b\xef\x7e\x67\xf6\xcc\x6c\x6a\xcc\xfb\x6e\xb0\x30\x7e\x3c\x77\x6e\xf7\xc5\x63\xdd\x95\x0e\xcf\xdf\xd2\x51\xe5\x24\xe9\x02\x13\xf3\x11\xa1\x98\x3a\xb8\x9f\x6c\x05\x13\xbf\x4c\x60\xe1\xb2\xe2\x77\xe5\x2d\xdf\xbf\xc5\x5a\x76\x57\xa8\xb0\x17\x80\xe9\x91\xe1\x1c\x7e\x97\xf6\xc3\x6c\xef\xef\x4c\xaf\x87\xa0\x60\xf8\x5d\x63\x81\x3a\x4d\x20\x14\x30\x1f\x64\x7e\xa0\xde\x95\x1f\x7a\xff\x4e\x81\x18\xe6\x1b\x63\xde\xd3\x60\x9b\x98\x05\xf9\xcc\x77\xb9\xff\xa4\xc1\x7e\x31\x0b\xa2\xb8\xbd\xf4\x42\xd5\xbd\xde\x99\xbf\x73\x9f\x63\x36\xc6\xf4\xec\xf6\x7b\xe6\x7b\xc3\xef\xc2\x05\xc5\x9f\xf9\xbc\xd4\x07\x65\xe4\x38\x58\xf8\xef\x06\xa8\x27\x9d\x50\x4f\xae\x28\xd7\x7c\x74\x6d\x92\x73\x78\x9b\x34\xb7\x7d\x86\x92\x7c\xc5\x21\x65\xc1\x42\x72\x92\xc5\x1b\xc5\x4c\xca\x95\x4b\x5c\x87\x9d\x70\x48\x93\xcb\xf4\x03\x65\x4c\x37\x1e\x3d\x08\xc5\x10\x48\x9a\x95\x36\xcd\x17\x50\x2b\xfb\x2b\x66\x8f\x2c\xe5\x38\xa8\x93\x4c\x50\xa0\xed\x80\x0a\x8d\x11\x0a\xa4\x6e\x28\xe3\xb6\xe9\x8e\x65\x62\x0f\x44\x92\x95\x4a\xaf\x70\x14\x62\xb9\x5c\x5a\xa0\xcc\x2d\x9f\x03\xb2\x19\xb6\x49\x1d\x50\x21\x9d\x86\x2a\x72\x0b\x3a\x49\x0f\xb4\x91\x1a\xa5\xda\xcb\xe7\x7a\xc5\x49\xd6\x43\x0a\x29\x55\x7a\x49\x9a\x72\x88\x94\x29\x67\x49\x0d\x00\xc9\x02\x10\x4f\x01\x70\x3c\x06\xdc\x47\x0c\xb0\x87\x18\xa0\x8c\xe5\x00\xbf\x23\x60\xf1\x0b\x04\x8b\xb6\x14\x0a\xe4\xd3\x60\x91\x37\x71\x3b\x37\x69\x3b\xc0\xa2\xad\x00\x8b\xc6\x02\x26\x8f\x8f\x78\x6d\xcf\x63\x0b\xf7\xa8\x23\xb2\x11\xcc\xc3\xfd\x8d\xc5\x1b\xe6\xf3\xc3\xfd\xc1\x23\xbf\xe1\xf6\xc6\x79\x2b\x56\xf6\x33\x5b\xf7\x6b\x1d\xa4\xd9\x03\xa7\x0d\x02\x8b\x14\xa3\x9c\xf1\xda\xed\x70\x3c\x7d\x50\xca\x62\xc3\x08\xbf\x1f\xe6\xaf\x6e\x3f\xeb\x1b\xc1\xab\x87\x8e\x21\xf6\x0e\xa6\x11\xbc\x0e\xda\xb7\x4d\xcc\x82\x39\xdc\x5e\x2a\x15\xbb\xd7\xcf\x2f\xba\xe3\xc8\x6d\x58\x26\x69\x21\xcf\xa3\xbb\xe1\xf4\x8c\xe5\x77\x5e\x3a\xdc\xf6\x2e\xe6\x2a\xbd\xd2\x59\x30\x89\x65\xca\x35\x26\x1b\x66\x53\xdc\xae\x64\x35\x9e\x8b\x17\x20\x87\x98\x20\x9e\xa4\x29\x3d\x3c\x57\xb5\x29\x67\xc5\x5e\xd8\x25\xf6\xc2\x42\x72\x4b\xb9\x22\xd9\x21\x98\x9c\x51\x36\x79\xf0\xba\xe3\xc9\x6d\xe9\x16\x97\x2b\xe3\x37\x48\x2c\x52\xae\x93\x46\x28\xe2\xfe\xd5\x0e\x25\x9e\xdc\xa9\xe6\x4f\xe5\x3a\x01\xc5\xe1\x8d\xe5\x39\x60\xe6\xfa\x76\x82\x99\x44\x40\x34\x49\x80\x70\x29\x03\xc2\xc9\x69\x16\xcb\xe9\x6d\xae\x63\x76\x1d\x85\x02\x12\x0e\x16\x52\x04\xb9\xee\x38\x6d\x52\xf3\xae\x72\x43\xb8\x01\xc5\x42\x8f\x72\x48\xcc\x05\x10\x63\xc0\x28\x14\x03\x48\xa7\x78\x0e\xae\x70\x5f\x26\xd2\xab\x18\xb9\x3c\x0b\xd5\x5c\x20\xef\x85\x02\xb9\x0c\x32\xe5\x08\x96\x97\x95\xa3\x3e\xd7\x71\xb1\x08\x04\x51\x86\x08\xe1\x0a\x64\x91\x43\xbc\xbd\x49\xec\x51\x0e\x09\xc5\x8a\x91\x5f\xeb\x21\x5c\x28\xa6\xbb\x45\xe6\x27\x59\x10\x4c\x7a\x95\x1b\x52\x04\x2c\x94\xcc\x50\x43\xc2\x95\x4d\xf2\x32\x65\x37\x89\x56\xb6\x93\x6c\x28\xe3\x7e\x56\xa3\x9c\x65\xb6\x48\x8a\x95\x2c\xb1\x17\xda\xc4\x5e\x38\x2c\xf6\x2a\x3d\x24\x12\x62\xb8\x7e\x76\x42\x01\x39\x0d\x09\x9c\xc7\xcf\x78\x1d\xd1\x42\xb6\x2a\x7b\xc5\x83\x6a\xee\x10\x7b\x21\x5e\xec\x85\x16\xcd\x46\x28\xd0\xb2\x58\x90\x03\x05\x72\x3c\x14\x91\xb3\x50\x24\x1f\x85\x22\x8d\x45\x61\x31\xd8\x24\x45\x80\x89\x18\x20\x94\x74\x70\x7b\x0b\xe6\x57\x32\xec\x66\x97\x10\xad\xec\x17\x6e\xc2\x6e\xe1\x26\x44\xb0\x4b\xfc\x02\x76\x4b\x06\xe8\x11\x6d\x00\xd8\x09\x15\x62\x0d\x54\x60\x27\x54\xb3\xdf\xb1\x13\x2e\x02\x28\x15\xec\x12\x36\xc2\x39\x61\x23\x9c\x20\x4d\x50\xe9\xbe\xe2\xf8\x55\x85\x56\x52\x85\xb5\x00\x10\x47\xb2\xb0\x01\x40\xf9\x13\x80\xf2\xaf\x00\xf4\xb7\x00\x74\x3a\x00\x7d\x0b\x80\x66\x02\xd0\xab\x00\xca\x29\x4f\x7f\x00\xb4\x10\x80\xb6\x00\x50\x3b\xbb\x48\x15\x1e\x12\x8a\x31\x83\xec\x15\x42\x71\xbf\x92\x47\xaa\x30\x99\x54\xa1\x1e\x80\xf6\x03\x28\x67\xc5\x83\xd0\x21\xc4\x40\xa3\x98\x0f\xf5\xe2\x39\x88\x11\x93\xe0\x82\xb8\x12\x5a\xc7\xba\x00\x5c\xff\x00\x50\xb2\x19\x3f\x00\x34\x1a\xc0\xf5\x11\x00\x4d\x06\xa0\x16\xa1\x5d\xd9\x0d\xa0\x3c\x04\x40\xe3\x01\x68\x1c\x00\x5d\x0d\xa0\x3c\x0c\xa0\xe4\x0f\xbd\x5c\xc7\xdd\xd7\x11\x00\xe7\xe7\x00\xae\x1f\x03\xd0\x4a\x00\xe7\x77\x00\x94\x45\x00\x4a\x28\x80\xb2\x04\x40\x61\xbc\x74\x02\xb8\xda\x00\x14\xd6\xe6\x43\x00\xfa\x1c\x93\x09\x00\xed\x01\x70\x16\x03\xd0\x56\x00\xc5\x02\xa0\xbc\x05\xa0\xbc\xa2\x56\xdf\xec\x4e\x7f\x02\x40\x67\x01\xd0\x36\x55\x16\xca\x7a\x00\xa5\xd3\x2d\xa3\x72\x00\xba\x13\x80\xda\x00\x68\x98\x4a\x8b\x12\x0d\xe0\x2c\x01\xa0\xa1\x2a\x2d\x94\xc9\xb3\x1e\x80\x3e\x0f\x40\x7f\xa3\xf2\xe9\xba\xa5\xf2\xef\x6a\x05\xa0\x7a\x00\xd7\x67\x00\x2e\x86\x47\x07\xe0\x6a\x72\xf3\xb1\x1a\x80\x2e\x03\x70\x05\x01\xd0\xdd\x00\xae\x13\x00\xf4\x88\x5b\x4e\xc5\x00\x2e\xa6\xfb\x73\x00\x8a\x13\x40\xc9\x02\x50\x9a\xdd\xba\x15\x01\x94\x5f\x02\x28\x1a\x00\xfa\x31\x00\xfd\x02\xc0\xf5\x6f\x2a\x9f\x94\xd1\x67\x06\x50\x72\x00\x94\x64\x00\x17\x55\x3f\x73\x99\x00\xf8\xb8\xc3\x0a\xa0\x2c\x04\xa0\xdd\x6e\xbd\x0a\x00\xd4\x00\xa0\x7c\x09\x80\x19\x00\x74\x1b\x80\xeb\x9c\x3a\xf6\xa0\x57\x00\x94\x7f\x02\x28\x97\x01\xe8\x5e\x00\xe5\x18\x80\x72\xd2\xcd\x6f\x00\x80\x12\x03\xa0\x30\x99\x1a\x01\x14\x7f\x00\x25\x03\x40\x21\x00\xf4\x92\x2a\x1b\x25\x13\x40\x09\x04\x50\x96\x01\xd0\xa3\x78\x01\x7e\x89\x17\x94\x42\x41\x56\xfe\x93\xc5\x1e\x96\xaf\xd9\x9d\x8f\x33\xaa\x04\x0b\xa9\xc2\x7c\x16\xfb\x58\x2d\x4c\xae\xc1\x34\x39\x0e\xa6\x91\x60\x98\x26\x2f\x83\x54\xe9\x18\x4c\x93\xab\x20\x55\xb8\x01\x8b\xbd\xe3\x0f\x19\x2c\xa4\x4f\x39\xcd\xe3\x5f\xb6\xd2\xcd\xe2\xb4\x74\x03\xea\xbc\xb9\xfc\x8c\xb2\xc9\x33\xf6\x20\xb1\x4a\x2f\xaf\x75\xb7\x83\x85\x8d\x41\x58\x9e\x66\x79\x99\xc5\x62\xd9\x0e\x75\x6c\xdc\x21\xdb\xe1\xb0\x74\x4d\xcd\x1f\xee\xba\xb7\x80\xc7\x41\x16\xdb\x6e\x40\x31\xf9\x0c\x6a\xf8\x67\xb7\x94\x13\x24\x1c\x92\xc9\x11\xb0\xb2\xef\xc5\x23\x50\xe0\xae\x6b\x4b\x79\x3b\x56\xc7\x35\x2b\x6d\xac\xb6\x27\x65\x50\x26\x1e\x81\x42\x1e\xff\x3b\xa1\x88\x74\x2b\x27\x78\xfb\x9b\x50\x20\x52\x28\x62\x7d\xca\x91\x50\x40\x2a\xa8\x53\xae\x81\x1a\x79\x3b\x14\x78\x71\x1d\xe2\x31\x88\x7f\x46\xae\x40\x89\xb4\x15\x36\x92\xdd\xd0\x29\x9d\x80\x10\x76\x67\xf1\x52\xd3\x00\x45\x12\x28\x7d\xb2\x05\x0e\xf2\xf6\x67\xa0\x8d\xf7\x9f\x06\x16\x12\xac\x1c\x17\xfb\x59\xfe\x00\x33\xd9\x05\x36\xf1\x34\xe4\x69\x93\x95\x5e\x4d\x8a\xd2\x2f\x55\x40\x1b\xb9\x06\x05\x52\x09\x58\x48\x03\x98\x48\x3e\x98\x48\xb4\x72\x42\x8a\x52\x4e\x93\x68\x65\x9f\xd4\x0f\x75\x2c\x06\x4a\xe1\xb0\x90\x24\xc1\x42\x86\x83\x5c\x87\x48\xa6\x33\x9e\x63\xfa\xd4\x7a\x4b\xbc\x00\x51\x6c\x7c\xc0\xeb\x93\x2b\x50\xc7\xe5\x9d\xaf\x1c\x23\xdd\x4a\xa9\xa7\x2e\xe3\x77\xf7\x98\x44\xba\x01\x07\xb8\xde\xd8\xe7\x2c\xdf\xba\xc7\x26\x2c\x77\x69\xda\x95\x6e\x4d\x83\xbb\x4d\xb7\x5b\x6f\x3d\x10\xc5\x74\xc6\x75\xce\xea\x3e\xb7\xde\xa5\x6e\x25\x99\xf5\x27\xdf\x50\x1a\x59\x9e\x96\x3d\x7a\xee\x06\x8b\xb4\x5d\xe9\x66\x74\x70\x7b\xf0\xd5\x39\xc3\xc9\x74\xde\x03\x51\x1e\x9d\x4b\x17\xc0\x22\x95\x40\xa7\x56\x0b\x16\x2d\xa3\xaf\x09\x0e\x68\x42\xc1\xc2\x71\x5d\x81\x08\x6d\x00\x58\xc8\x55\xa5\x91\xe7\xc7\x43\x50\xc9\xf2\x83\xd8\x0b\xa1\xe4\x23\x75\x8c\xa3\x39\xa4\x5c\x67\x79\xd2\x3b\x5e\x69\x05\x13\xb9\xae\x9c\x94\xf3\x40\xcf\xf2\x07\xd7\x09\xb3\x8d\x6e\xe5\x38\x93\x17\xcf\x7f\xd1\x4a\x35\xd3\x1d\x1f\x6b\xde\x82\x0a\xd2\x0d\x6d\x3c\x37\x16\x41\x85\x54\x0a\x85\x72\x25\x54\x90\x06\x28\x67\xb2\x95\x59\xce\x3b\xa0\x5c\xf7\x8e\xab\xd8\x38\xa3\x17\x42\xb9\xec\x7b\x40\x3f\x38\xc6\xa2\xb7\xe5\xab\xca\x49\xf9\x2a\x24\x70\x7c\xad\x3c\x27\xab\xe3\xa7\x5e\xa8\xd0\x26\x40\x83\xdc\x06\x65\x92\x0c\x15\xe4\x1c\xa4\x68\xc2\xc1\x22\x03\x98\xa4\x02\x65\x13\x69\x53\x1a\x35\xa5\x60\x91\x3b\x58\xcd\xa4\xb4\x93\x7d\xca\x6e\xcd\x25\xb0\xc8\xac\x8f\x93\x4a\x07\x49\x50\xda\x98\x6f\x30\xfb\xf4\xd6\x32\x66\xe8\x24\x45\x50\xe6\xb9\xfb\x7d\x06\x75\xda\x7a\x28\x90\x03\xa1\x4e\x0a\x82\x02\x8e\xef\x90\xfb\xde\x06\x65\xde\x31\xd9\x45\x28\x27\x59\x18\x47\xd6\x63\x1a\xa9\x12\x0a\x48\x95\x90\x0c\xa0\xe4\x69\xae\x41\x8c\x66\x3f\xc4\xc8\x4d\x60\x91\xb4\x50\xc1\xe5\xbf\x09\xaa\xf9\x7c\x81\xbf\x72\x9c\xe9\x5c\x3c\x02\x26\x22\x43\xa4\x78\x44\xf9\x42\xca\x03\x0b\xd9\x09\x26\x4d\x81\xd2\xc8\x75\xc0\x6a\x35\x56\xaf\xd8\xb8\xde\x58\x7d\x63\x21\xcc\x0f\x3c\x35\x69\x1d\x1c\x90\xe2\x21\x5b\x36\x80\x45\xca\x02\x93\x1c\x03\x16\xa9\x03\x4c\xda\x0c\xb0\xc8\xd7\xdc\xb5\xe2\x55\x9f\xb1\x63\x1a\x1c\xd0\x94\x83\x89\xc7\x81\x70\x28\x23\x8d\x90\x43\xc2\x95\x6e\xc9\xae\x6c\x25\x47\x94\x16\xf9\x30\x1c\x90\x36\x42\xa1\xe4\x84\x4e\x29\x12\xda\x98\x0d\x91\x5e\x7e\x57\xc7\x63\xc9\x90\x22\x65\x43\xa8\xe7\xce\x6c\x9c\xd9\x2a\xa3\x55\xda\x0c\x16\xf2\x05\x98\xe4\x50\xa5\x5b\xca\x54\x4e\xf2\xfa\xf2\x33\x30\x79\x68\xe3\x7d\x31\x9b\x68\x02\x8b\x7c\x18\xf4\x7c\xec\x3e\x46\x0d\xee\xad\x39\xd9\xf8\x86\xd5\x6e\xee\xbb\x07\x97\x47\x2e\x9e\x1a\xdc\x5d\x63\x57\x79\xee\x63\xd6\xa8\x57\x20\x82\xfb\x76\x0f\x44\x71\x1b\x1a\x76\xf7\xd0\xe8\xd1\x0b\xf3\x19\x6e\xb7\x1e\xfd\x30\x39\x9d\x56\x5a\xf8\x7c\x0e\xb3\xf3\x36\x48\xe1\x73\x05\xd7\x20\x45\x03\x50\x20\x5f\x82\x93\xb2\x1d\x36\x4b\x19\xd0\x48\xce\xc1\x61\x4d\xaf\xd2\xad\x89\x55\x4e\x6a\x2e\x82\x45\x13\x0f\x26\xe9\x32\xd4\x49\x01\x50\x20\xb5\xc3\x01\xa9\x04\x8a\x48\x27\x2c\x64\xb1\x56\xb6\x28\xdd\xd2\x56\xe5\xa4\x66\xbf\xd2\x2d\xef\x57\x4e\xca\x2d\x60\x91\x6b\x95\xe3\xf2\x2e\xa5\x51\xbe\xa0\x5c\xe7\xf4\x33\xf9\x78\xc6\x96\xd7\xc1\x42\xce\x81\x49\x9b\xab\x74\xcb\x4e\xe5\xa4\xb6\x10\x2c\x32\x05\x93\xac\x07\x8b\x94\x0c\x26\x39\x4a\xbd\x8b\x17\x95\xdd\x52\xa5\xb2\x5d\x76\x80\x99\xc4\x40\x90\x78\x11\x72\x49\x31\x24\x91\x62\x88\x13\x37\x42\x92\xd8\x02\xc0\xc6\x16\x42\xb6\x12\x25\x5e\x84\x24\x31\x0b\x02\xa5\xbd\x90\x44\x2e\x42\x12\xd9\x0d\xf9\xe2\x59\xe5\xb2\x94\x06\x85\xee\x4b\xab\x09\x04\x33\xe9\x84\x0c\x72\x08\x4a\x98\x3c\xc5\xd3\x90\x44\xb4\x4a\xa7\x78\x09\x72\xc4\x85\x50\x21\x11\xa8\x91\x08\x58\xe5\x03\xb0\x90\xdd\xc5\xdd\x60\x93\x5a\xc0\x26\x96\x2b\x27\xc5\x3a\xe5\x96\x58\x05\xe1\xe2\x55\x65\xaf\x98\x04\xf1\x62\x9b\xd2\x48\x76\x41\x3c\xeb\x43\x4a\x82\xcd\xa4\x46\xd9\x47\x32\x20\x47\xaa\x05\x2b\x89\x81\x2e\x12\x03\xfb\xc8\x56\xe8\x12\xeb\xa0\x4b\xb4\xc1\x3e\x92\x09\x5f\x90\x9d\xd0\x25\x94\x43\xa9\x90\xa0\x9c\x10\x2f\x42\x97\x58\x05\x5d\x52\x01\x74\x91\x3e\xe8\x22\x97\xa0\x8b\x34\xc3\x4d\x52\x0a\x27\xc5\x66\xe8\x12\xbb\xa0\x4b\x6c\x42\x2d\x49\x06\xa7\x74\x00\x0d\xe2\x5e\x38\x2e\xee\x85\xab\xe2\x5e\xb8\x20\x59\xe0\xb8\xd8\x03\x5d\xe2\x51\xb8\x2e\xda\xe0\x9a\x68\x83\xd3\x62\x3c\xb4\x89\x26\xd8\x2e\x9e\x85\x3e\x41\x80\xcd\xe2\x11\xe8\x92\x2a\xa0\x5b\xec\xe4\x7d\x5d\x17\x23\xa1\x55\xec\x82\x9b\xfc\xf7\x33\x50\x2b\xd4\xc3\x19\xb1\x03\x2e\x89\x97\xe0\x9a\x54\x08\x17\xc4\x18\xb8\x20\x5c\x01\xb3\xd8\x0b\xf5\x62\x3e\xdc\x10\x3b\xa1\x8f\xb0\xb6\xad\xa0\x15\x00\x64\xe1\x04\xc8\x62\x07\xcc\x10\x63\x60\x86\xd8\xab\xfc\x4e\xcc\x07\xb3\xd8\xa1\x9c\x26\x5d\x30\x5f\x6c\x55\xd6\x68\x12\xa0\x86\x74\x83\xcc\xf4\x2c\x38\x15\x93\x26\x45\xa9\x21\xbd\xca\x36\xd2\x4d\x3b\xc5\x22\x25\x57\x94\x95\x4c\xb1\x47\x39\x2b\x66\x29\x1b\x79\xcd\xdf\xa5\x1c\x27\x5a\x68\x25\x45\xca\x7e\x6d\xa4\x72\x50\x1d\xa7\x28\x9f\xb1\x98\x2c\x11\xe5\x9a\x14\xc1\x7e\x77\xcf\x0d\x85\x2b\x26\x39\x0b\x22\xd4\x79\x00\xe5\xb4\x77\xee\x90\xc5\xef\x22\xe5\x34\x1f\x87\x5d\x53\x8c\x3c\x26\xa4\x29\x2d\x6a\xff\x3e\xf3\x61\x1b\xdd\x35\x43\x82\xd2\x21\x6d\x07\x33\x9f\xff\xb9\xa0\x1c\x15\x8a\x15\x75\x6e\x2b\x4b\x39\x24\x9e\x82\x2e\x31\x02\x2e\x88\xb1\xb0\x55\x3c\x04\xfd\x4c\x96\x42\xbe\x42\xf1\x96\x72\x9d\xc9\x54\x3c\x00\x97\x04\x80\xbd\x42\x19\xf4\x0b\xb9\x50\xc1\x2e\xbc\xa6\xb4\xe0\x2d\xd8\x89\x5d\xca\x47\xc2\x39\xe8\x92\x0a\xe1\x88\x54\x08\x57\xc4\x0e\xf0\x67\xf2\x27\x91\xff\x17\x2b\xef\x03\xd7\xe7\xf4\xff\xff\xdf\xcf\x39\xcf\xe7\x75\x5d\xaf\x09\x99\x10\x86\xd0\x68\xcc\x16\x6b\x0c\xb1\x58\xa6\x4d\x26\x93\x09\xd9\xda\xd6\xa6\x4d\xdb\x62\xcd\x1a\x21\x84\xd0\x88\x85\x90\x09\x21\x13\x42\x08\x99\x8d\x58\x68\x84\x66\x21\x0c\x21\x84\x90\x09\x59\xbf\x5b\x69\x3e\xde\xde\xef\xf7\xc7\xe7\x7b\xbb\xfd\xb6\xdb\xa3\xc7\xf3\x3a\xaf\xf3\xe7\x79\x9e\xe7\x5c\xd7\xeb\x9c\xc7\xb9\x6e\x2f\xd6\xba\xd5\x74\xca\x1b\x74\xba\x80\x45\xa6\xa2\x6f\x83\x5d\xca\x6b\xee\x45\x56\x48\x18\x5f\xb8\x57\xf8\xc2\x75\xd2\xe5\xf6\x65\xa2\xfd\x82\x65\xfd\x70\x97\xb2\xcc\x09\x47\xba\x27\xd9\x0c\x7d\xe1\x83\xfb\x83\xfe\x75\xdc\x5e\xd0\xb7\x04\xfa\x32\xff\x87\xb7\x7c\x30\x88\x4b\xa0\xaf\xa7\x7f\x3d\xfb\xe7\xbe\x77\xf3\x1f\x7a\xcc\xbf\xf1\xbf\xeb\x6f\xff\x1b\xc7\xfd\xbb\x0e\xd7\xd7\x2d\x4b\x38\x40\xa6\xe1\xcb\x12\x76\xff\x33\x7d\x3c\x63\xfb\xc7\xfd\xbf\xe9\x70\xff\xc3\x7d\x0d\xb2\xa1\xaf\xfe\x2f\xfa\xdc\x44\x9b\xb1\x65\xf3\x56\x7d\xe0\x4f\xdd\xed\xef\xfc\x87\xf6\xf6\xf1\xdf\xf8\x78\x19\xde\xb7\xd9\x66\x6c\xf9\xb0\x7f\x6d\xd1\x3f\x2f\xfe\xce\xff\x4d\x93\x1b\xe4\x5d\xff\x51\x17\xf8\x78\x70\x1d\xb5\x95\xff\x55\x9f\xfb\xf8\x6f\x3c\xe9\x1f\x75\xba\xff\xd1\x33\xb6\xea\x74\x5b\x39\xd6\x25\xf5\xfd\x2c\xe3\xfb\xd6\xba\xa4\xbe\x2b\xff\xa2\x83\x14\xca\x06\x12\x06\xf9\x88\x7f\xd3\x47\xea\xa8\x1b\x98\xf7\x83\xbc\xf5\x19\xfb\x4f\xfc\xe7\x77\xc0\x56\xde\xaa\xf7\xfd\x17\xad\x6f\x60\xac\x92\x98\x3e\x50\xb6\x3f\x5f\xff\x7d\xfe\x41\xdf\x10\xfd\x81\x11\xff\x4d\x03\xfe\xff\x8b\xff\xaf\xda\xf0\x7f\xe3\xbf\x69\xbe\x1f\xfd\xd3\x98\xff\x37\xde\xaa\x35\xfe\x13\xff\x7d\x8c\xb6\xea\x8c\xff\xc4\xff\xa2\xb9\xfe\x27\xee\xdf\xe7\xfc\x2f\xd8\x7a\xf6\xe0\x45\xb0\xc0\x8b\xa0\x68\x2b\xeb\x46\xa6\xf5\x63\xe0\x19\xf8\x1f\xa0\xe1\xcc\xd5\x70\x8a\xbc\xa3\x58\xe4\x1d\xf5\x3f\xbc\x55\x43\xfa\x6f\xf0\x52\x99\xeb\xa5\x52\xe4\x5f\xca\x22\xff\xd2\xbf\xf0\xb9\x9c\xd5\x8f\x01\xdd\xe9\x7f\x81\xec\x4d\x8e\xf4\xfb\x37\x82\x45\x3a\x82\x22\x9d\xca\x22\x9d\x4a\x91\xce\x25\xbf\x1f\xff\xf1\x4c\xa2\x7f\x1c\xae\x22\xc7\xbb\x8a\x22\x7f\x2d\x8b\xfc\xb5\x14\xf9\xcb\x59\xe4\x2f\xa7\x68\x60\x7f\xf6\xbf\x40\xab\x28\xf2\xd6\x52\xe4\x7d\x49\x91\xb7\x85\xfc\xfe\x3d\xdc\xff\x8a\xfb\xc8\xf1\xee\xa3\xc8\xff\x88\x45\xfe\x47\x14\xf9\xd5\x2c\xf2\xab\x29\xf2\x93\xc9\xef\xc7\x9f\xb1\xdf\x1a\xcb\xad\x9a\xdb\xd6\xfe\x6d\xf5\x79\xb0\xfd\xad\xf5\xfe\xd3\x38\xfa\xfd\x7b\xe4\xf5\x7d\x57\x04\xef\xb3\x20\x78\x9f\xa2\x3f\x79\x25\xd3\xfa\x21\x1b\x30\xff\x1b\x42\xbb\x33\x37\xb4\x3b\x45\x43\x92\x58\x34\x24\xe9\x2f\x7c\x18\x67\xf5\xe3\x9f\xfa\x1d\x9a\x45\x4e\x68\x16\x45\x43\xca\x59\x34\xa4\x9c\xa2\x21\x59\x2c\x1a\x92\x45\xd1\x90\x80\xfc\x7e\xfc\x5f\xe6\xe0\x9f\xe7\x60\xeb\xfb\xae\xb0\x23\xcc\x5e\xb2\xc4\x60\x47\x98\x9d\x07\xf5\xab\xfb\xfe\xe6\x73\x7f\xdc\x8c\x46\x50\xa8\x43\x48\xf1\xd2\x28\xf4\xa6\x90\x12\x64\x30\x56\x56\x9a\x67\x06\xb0\xda\xac\xff\xcb\xdc\x19\x65\xbb\xd8\xc7\x76\x71\x68\xff\xf5\xd6\xfd\xaa\x0c\xa1\x50\xf6\xe2\x14\x59\x69\xde\x1e\xc0\x6a\xb3\xfe\xdf\xe6\xc1\x8b\x7d\xab\x07\xb0\xf5\xba\xff\xde\xba\x9c\x67\x74\x1d\x0f\xea\x3a\x4e\xd7\x72\x8a\x64\xa5\x99\x26\x2b\xcd\x64\x59\x69\xa7\xfe\xc7\x18\x95\x51\xe8\x9d\x41\x8a\xf7\x24\x85\xde\x32\x52\x82\xfb\xfa\x36\xca\x4a\x3b\xd7\x8e\x30\xc9\x32\x28\xe8\x6c\x65\xbb\x0a\x2c\x60\xa6\x81\x2c\x03\x9b\x04\xe6\x36\x60\xfd\xd6\xb3\xe4\xbe\x0d\xd0\xb7\x37\xf4\x6d\x84\x2d\xc9\x03\xe7\xc2\x2b\x06\xce\x90\x27\xbb\x8d\x8c\xf0\x1f\xfe\x03\x92\xc5\x6a\x37\xa6\xef\xc0\xad\x1a\xa4\x3d\xbc\xef\x36\x53\xc7\x47\x6e\x29\x8b\xdd\x52\xe6\xbb\x5f\xfb\x6e\x73\x4b\xf9\x52\xc2\x58\x2d\x61\x1c\xec\x2c\xd7\x7a\xab\xd8\x75\xb0\xde\x29\xd0\x37\x74\x2b\xfa\xdb\x0f\xad\x66\xb1\x1d\xc2\x2b\x03\x67\xd6\x63\x79\xc5\x96\x91\x64\xcb\x40\x2e\x62\x57\x81\xc7\x0c\xbf\x77\xda\x24\x96\xdb\x81\x1f\x86\xff\xb3\x6c\xf8\x5f\x30\xd4\x05\xcc\x72\x01\xa3\x5d\xc0\x74\x17\x70\x86\x0b\xb8\xd0\x05\x4c\x1d\xb0\x77\xe5\x0a\xb7\x92\xdd\xdd\x25\x0c\x77\x6b\x39\xd2\xdd\xdc\x57\xe7\x2e\x61\x37\x59\xc1\x74\x99\xcf\xb1\xb2\x82\x89\x92\x05\x92\xd5\xd7\x3d\xb0\x9e\x5b\x41\xe0\xbd\xcb\xe1\xfe\x81\xec\xae\x6f\x12\xc8\x5a\x0e\x95\x2c\x46\xc8\x0a\xf6\x90\xf1\xa4\x04\x11\x8c\x90\xba\xbe\xe5\xb2\x82\x21\x03\x6b\x8c\xf5\x7d\x57\xc8\x0d\x04\x03\xfa\x41\x16\xcb\x25\x8b\xa1\xb0\xe5\x21\x6f\x2f\x2e\x14\x18\xe1\x6f\x60\x57\xaf\x8a\xab\x75\x0b\x4b\xf5\xcb\xbe\x8d\xd2\xcd\x02\x6f\x17\x0e\x73\x6b\xfb\xd6\xf9\x61\x9c\xe3\x87\xb1\xfb\xe0\x39\x6e\xba\x1f\xc6\x5c\x3f\x8c\x52\xf7\x41\x5f\x67\x80\xb9\x5b\x30\xe1\x7f\xe7\x01\xdc\x47\xb2\x6c\xec\x7b\x4d\xbf\x65\xad\x86\x0d\xb4\xbb\x60\x30\x4e\x97\x4b\x26\xb3\xb4\x8a\x2b\xfc\x0d\xa6\x4c\xd7\x9a\x5d\x5c\x72\x7f\xdf\x06\xcf\xe9\x57\x91\xf9\xa7\xbd\x81\x95\x7f\xb0\xdd\x57\x36\x18\xd1\x55\x7d\x9b\x15\xb3\x51\x57\xd9\xe5\x03\xf6\xbf\xf1\xdf\x61\xde\xfd\xe3\xb3\x7e\xee\xc7\x5f\x3f\xfb\x7f\x4d\xff\xbf\x00\xfe\x15\x76\x83\xae\x62\xee\x80\xbd\x01\x64\x03\x17\xca\x06\x3c\xbb\x81\x05\xfd\xe8\x9f\xf3\x7e\xa7\x59\xe9\x77\x9a\x1b\xb6\xb2\xac\xe2\x5c\xd9\x40\x95\xac\x65\x96\x6c\xe0\x31\xd9\xc0\x88\x7e\xd8\x0d\x2c\x0e\x0e\x34\x35\xc1\x7c\xf3\xa6\x3f\xcd\x4c\xf4\x30\xef\x7a\x98\xa9\x32\x9e\x23\x75\x3c\x47\xca\x5a\xe6\x4a\x04\xc7\x0a\xbc\xe4\xf5\xc7\x3f\x8b\xb9\x32\xbc\xef\x33\x9b\xd1\xb7\x59\x86\xf7\xdd\x3c\xb0\x26\xfb\x88\xed\x64\x6d\x5f\xf7\xc0\xda\x64\xef\x01\x2d\x6a\xb8\xee\xcf\x58\xb9\x8f\xe1\x7f\x9e\x05\x6d\xe6\x42\x39\x96\xb9\x7e\x0a\x75\xde\x52\x2e\x92\x94\xbe\xcd\xb2\x80\xb1\xae\x82\x7d\xbd\x3d\x38\xc3\xd6\xd2\x7f\xff\xf5\xaf\xa1\xab\xa0\x6f\x2e\xf4\xcd\x77\x9f\x9a\x31\xee\x53\x33\xda\x46\xf0\xb0\x8d\x60\xb9\x8d\x60\x32\xf4\xad\x84\x2d\xcb\xa0\x6f\xb3\x4d\x62\xb8\xab\x64\xb4\x9d\xcc\xcd\x36\x82\x97\x24\x03\x34\xa9\x6f\x78\x3f\x02\xfe\x00\xfc\x9e\x05\x54\xc2\xef\x17\xfe\xc1\x03\xcf\x84\xd4\x7e\xc8\x22\x73\x94\x60\xbe\x15\xfa\xe7\xab\xd9\xe0\x0f\xef\x6b\xb5\x30\xf7\x0f\xad\xbc\xb7\x0a\x7e\xfb\xec\x0f\xee\xc7\xef\x02\xbf\x7b\x7f\xa0\x77\x8b\xb9\xaf\x6f\xa2\x9d\xd6\x97\x01\x5b\x9e\xe9\x87\xdb\xc8\x33\x32\x8d\x8a\xbf\x61\x8a\x4c\x63\xea\x20\xf7\x63\xa2\x0b\x67\xe2\x5f\xde\x45\x48\x91\x69\x1c\x24\xd3\x48\x72\xe1\x03\x3c\xfc\x2f\xd8\x5f\xa6\x31\xda\x85\x0f\xd8\x7b\xc8\x34\x76\xf9\x4b\xb9\xfe\xf4\x11\x83\xe5\x93\xff\x82\xe9\x2e\x7c\x80\xff\xee\xc7\xd6\x7c\x13\xb7\xe6\x1d\xcc\x37\x5a\xa6\x71\xb8\x4c\x63\xfc\x56\xb8\xf0\x01\x1e\xfb\xef\xef\x4c\x0c\x70\xf2\xdf\xe1\xc2\xc9\xfa\x7b\xdd\x7f\xa9\xff\xef\x7e\x4c\x1b\x44\xda\x56\xdb\x85\x93\x2e\xd3\x38\xec\xef\x70\xe1\x03\x9c\x34\x58\xef\x9f\x18\x8c\xdf\xa5\x83\x38\x7c\x2b\x5c\xf8\x00\xdf\xf0\x77\xfc\x17\x3f\xfe\xde\x8f\x14\x17\x3e\x10\xa3\xd1\x7f\xe9\x73\x7f\xbc\xf7\x18\x8c\xf3\xe8\xc1\xf1\xf8\x73\x7c\x06\xc7\x25\x69\x70\xfc\x52\xfe\x12\xa7\x83\x06\x7d\x9d\xf2\xd7\xf1\x1f\xf4\xfb\x5f\xfd\xf8\x87\x35\xc8\x3f\xae\xdd\xfe\x61\xad\xf5\x4f\xf9\xf5\xa3\xc1\xf7\x8f\x3e\xa2\x52\xbe\xe0\x42\x37\x86\xb7\xff\x0a\xd8\xb2\x14\xb6\x5c\x0f\x5b\x6e\x18\xe4\x15\x83\x69\x55\xb0\xe5\xda\x3f\xee\xc3\x81\xb4\xcb\x07\xd3\xbe\x74\x63\xe8\xfe\x1b\x36\xff\x15\xb2\x92\x9a\xc1\x2f\xdd\x98\xbf\xa1\x1c\xe8\x00\x5b\x05\x92\x0f\xda\x02\x5e\x17\xf8\xb1\xe0\x17\x83\xdf\x0e\xc1\x48\x08\x6a\x20\xe8\x81\x50\x1c\x84\x4a\x20\xd4\x00\x43\xb2\x60\x48\x0f\x6c\x53\x06\x61\xb9\xb0\x6d\x21\x6c\x17\x07\xdb\x0b\x6c\x9f\x02\xe1\xa9\xb0\x43\x34\xec\xb0\x06\x86\xc6\xc1\xd0\x74\x18\x5a\x01\x43\x1b\x61\xc7\x3a\xd8\x29\x0f\x76\xea\x85\x5d\x80\x5d\x2a\x20\x32\x19\x22\x3b\x61\xd7\x7c\xd8\x2d\x0e\x76\x0f\x87\xdd\x8b\x61\x58\x14\x0c\xeb\x80\x3d\x52\x61\xcf\x0c\xd8\x2b\x16\xf6\x6a\x83\xa8\x72\xd8\x3b\x1b\xf6\xc9\x80\x7d\x47\xc2\xbe\x95\x10\x9d\x0d\xd1\x6d\x30\xbc\x1e\xf6\x4b\x86\xfd\xda\x61\xff\x44\xd8\xbf\x1e\x62\x62\x20\xa6\x0a\x46\x44\xc1\x88\x34\x18\x51\x01\x07\x24\xc1\x81\xd1\x70\x60\x2d\x8c\xcc\x87\x83\x52\x60\x54\x2a\x8c\x8e\x81\xd8\x64\x88\xed\x80\x83\x6b\xe0\x90\x12\x38\xa4\x07\xe2\x12\x60\x6c\x34\x8c\x5d\x03\x87\x36\xc3\x38\x60\x5c\x2e\x1c\x1e\x0f\x47\x0c\x83\x23\x9a\xe1\xc8\x71\x70\x64\x2f\xc4\x67\x40\x7c\x17\x1c\x95\x02\x47\xd7\xc2\xd1\x9d\x90\x10\x0b\x09\x35\x7f\xe0\x98\x61\x70\x6c\x16\x4c\xc8\x84\xc4\x74\x48\xec\x81\xe3\x12\x61\x62\x2e\x4c\x6c\x87\xa4\x68\x48\x6a\x81\x49\xc3\x60\x52\x0e\x4c\xaa\x86\x13\x22\xe0\x84\x24\x38\xa1\x03\x92\x8b\xe0\xc4\x18\x98\x12\x09\x53\xb2\xe0\xa4\x22\x48\x09\x87\x94\x6c\x48\xe9\x80\x93\x13\xe0\xe4\x2e\x98\x1a\x07\xa7\x84\x41\x6a\x14\x9c\x5a\x02\xd3\x72\xe1\xb4\x08\x38\xad\x0e\xd2\xb2\xe1\xf4\x5c\x38\x23\x1b\xce\x4c\x87\x33\x3b\x21\xbd\x17\xce\xaa\x83\xe9\xb9\x30\x23\x11\x32\xfa\xd1\x06\x33\x73\x61\x56\x14\xcc\x06\x32\x05\xe6\x24\xc3\xdc\x48\x98\xdb\x05\x67\xb7\xc2\x3c\x60\x7e\x18\xcc\x4f\x81\x73\x92\x20\x7b\x1c\x2c\x18\x09\x0b\xc7\xc1\xa2\x74\xc8\x19\x06\x39\x3d\x70\x5e\x32\x2c\x0e\x83\xc5\xcd\x90\x5b\x0d\x4b\x9a\xe1\xfc\x1e\xc8\x8b\x83\x65\x35\x70\x41\x2d\x5c\x58\x05\xf9\xe5\x70\x51\x15\x5c\xdc\x0a\x97\x64\xc3\x25\xbd\x50\x50\x09\x97\x66\xc2\x65\xc9\x70\x79\x35\x14\xe6\xc0\x15\x23\xe1\xca\x30\xb8\x2a\x16\x8a\x62\xa0\xa8\x06\xae\xae\x80\x6b\xf2\xe0\xda\x14\x28\x4e\x80\xe5\xc9\xb0\xbc\x07\xae\x1f\x09\x25\xb1\x50\xd2\x04\x37\x14\xc1\x8d\x85\xb0\xa2\x1a\x4a\x2b\xe0\xa6\x3a\xb8\x39\x17\x6e\x89\x86\x5b\xba\xa0\xac\x0e\x6e\x2d\x86\xdb\x32\xe0\xf6\x18\xb8\xbd\x13\xca\x9b\xe1\x8e\x35\xb0\xb2\x01\xee\x2c\x85\x8a\x64\xb8\x2b\x0e\xee\x4e\x84\x7b\x0a\xa1\x32\x0d\xee\xcd\x80\xfb\x32\xe0\xfe\x32\xa8\xca\x84\x07\x72\x60\x55\x1a\x3c\x98\x0e\xd5\x25\xf0\x50\x0b\x3c\xdc\x02\x8f\x74\x42\x4d\x33\x3c\xda\x00\x8f\x75\x41\x6d\x3a\x3c\xd1\x02\x4f\x25\x41\x5d\x32\x3c\x3d\x12\x9e\x5e\x03\xcf\x24\xc0\xb3\x31\xf0\x6c\x0f\xd4\xb7\xc1\x73\x1d\xb0\xba\x0c\x56\xf7\xc0\xf3\x9b\x60\x6d\x34\xac\xed\x82\x17\xea\xe0\xc5\x6a\x68\xa8\x81\x97\x0a\xe1\xe5\x48\x78\xb9\x1c\xd6\xc5\xc2\xba\x3a\x68\x4c\x81\xc6\x16\x78\x25\x1f\x5e\x0d\x87\x57\x3b\xe1\xb5\x16\x68\x6a\x82\xf5\x2d\xf0\x7a\x23\xbc\xd1\x02\xcd\x6d\xf0\x66\x37\xbc\x1d\xc0\xdb\x5d\xd0\xd2\x05\x1b\xd6\xc0\x3b\xf9\xb0\xb1\x10\x5a\x8b\xe0\xdd\x7c\x78\x2f\x0b\xde\xcf\x83\xb6\x5a\xf8\xa0\x11\x3e\x4c\x83\x8f\x72\x61\x53\x18\x7c\x1c\x0b\x1f\x37\xc3\x27\x0d\xf0\x69\x0d\xb4\xd7\xc2\x67\xb5\xf0\x79\x37\x74\x8c\x83\x2f\xc7\xc1\x57\x71\xf0\x75\x0c\x74\xe6\xc2\x37\xc3\xe0\xdb\x48\xf8\xb6\x1d\xbe\xab\x83\xae\x1e\xf8\x21\x12\x7e\x14\xf8\xb1\x15\x7e\x02\x36\x0f\x83\x9f\x73\xa0\xa7\x1c\x7e\xa9\x85\x5f\x6b\xe0\xb7\x36\xe8\xed\x82\x2d\xc0\x96\x1e\xe8\x6b\xc6\x50\x8a\x31\x15\x18\x3b\x0c\x63\xcb\x30\x2e\x16\xe3\x1a\x30\x92\x82\x91\x56\x8c\x16\x61\xbc\x56\x4c\x10\x8e\x09\x5a\x30\xa1\x7c\xcc\x90\x3c\xcc\x36\xe5\x98\xb0\x38\x4c\x58\x17\x66\xdb\x6a\xcc\x76\x35\x98\xed\x4b\x30\xe1\x79\x98\x1d\x2a\x31\x43\x8b\x30\x3b\xc6\x63\x22\x22\x31\x11\x3d\x98\x9d\xea\x30\x3b\x37\x63\x76\xa9\xc6\x44\xe6\x63\x76\xed\xc0\xec\x56\x85\xd9\x3d\x0f\x33\x2c\x13\xb3\x47\x2a\x66\xcf\x70\xcc\x5e\x15\x98\xbd\x03\xcc\xde\x3d\x98\x7d\x6a\x31\xfb\x16\x60\xa2\xd3\x31\xc3\xa3\x31\xfb\x25\x61\xf6\x4f\xc5\xc4\x24\x63\x46\xe4\x63\x0e\x28\xc6\x1c\x98\x8b\x19\x99\x84\x19\x59\x8b\x39\xa8\x1d\x33\x6a\x13\x66\x74\x21\x26\xb6\x0e\x73\x70\x1e\xe6\x90\x22\xcc\x98\x1a\x4c\x5c\x01\x66\x6c\x3c\x66\x6c\x17\xe6\xd0\x6a\xcc\x61\xe3\x30\x87\xd5\x63\xc6\xa5\x63\x0e\x8f\xc2\x1c\xbe\x06\x73\x44\x19\xe6\xc8\x14\xcc\x91\xed\x98\xf8\x1c\xcc\x51\x29\x98\xa3\x47\x62\x8e\xce\xc6\x1c\xdd\x80\x19\x9f\x89\x19\xdf\x8a\x49\xe8\xc4\x1c\x1b\x60\x26\xa4\x62\x12\xe3\x31\xc7\xa5\x63\x26\xe6\x60\x8e\xaf\xc3\x4c\x4a\xc2\x4c\x6e\xc6\x9c\x50\x80\x49\x4e\xc7\x9c\x28\x98\x13\xab\x30\x53\x8a\x31\x27\x65\x62\x52\xb2\x31\x27\xa7\x61\xa6\x56\x62\x4e\x69\xc6\x9c\x1a\x8b\x99\x96\x8d\x39\xad\x15\x73\x7a\x14\xe6\x8c\x02\xcc\x99\xf5\x98\xf4\x12\xcc\x59\x55\x98\xe9\x9b\x30\x33\x6a\x31\x19\x35\x98\x99\xa9\x98\x59\x1d\x98\xd9\x75\x98\xcc\x1a\xcc\x9c\x52\xcc\xdc\x52\xcc\xd9\x45\x98\xac\x62\xcc\xbc\x4a\xcc\xfc\x5a\xcc\x39\xed\x98\x05\xe1\x98\x05\x9b\x30\x0b\x6b\x30\x8b\x72\x31\x39\x59\x98\x73\x53\x30\xe7\x65\x62\x16\x8f\xc3\xe4\xc6\x60\x96\x14\x61\xce\xcf\xc7\x2c\xcd\xc6\xe4\xe5\x62\x96\x95\x60\x2e\xe8\xc5\x5c\x58\x85\xb9\x28\x09\x73\x71\x26\xe6\x92\x3c\x4c\x41\x02\xe6\xd2\x38\xcc\x65\xe3\x30\x97\x67\x62\x0a\x93\x30\x57\x64\x61\xae\x2c\xc0\x5c\x55\x8b\x29\xca\xc5\x5c\x1d\x8b\xb9\x26\x06\x73\x4d\x0f\xa6\x18\x4c\x71\x37\xe6\xba\x30\xcc\xf5\x51\x98\x92\x2c\xcc\x0d\x51\x98\x1b\x8b\x30\x2b\xf2\x30\xa5\x15\x98\x9b\x6a\x30\x37\x6f\xc2\x94\x09\xa6\xac\x07\x73\x6b\x07\xe6\xb6\x22\xcc\xed\x45\x98\xf2\x2c\xcc\x1d\x29\x98\x95\x79\x98\x3b\xdb\x30\x15\xf5\x98\xbb\x5a\x31\x77\xb7\x63\x2a\xe3\x30\x95\x8d\x98\x7b\xd3\x30\xf7\x45\x61\xee\x0f\xc3\x54\x85\x63\x1e\x48\xc1\xac\x2a\xc0\x3c\x58\x86\xa9\x6e\xc1\x3c\x1c\x8e\x79\x04\xcc\x23\x6d\x98\x9a\x4d\x98\x47\x5b\x31\x8f\x95\x60\x1e\x8f\xc7\xd4\xa6\x60\x9e\x28\xc3\x3c\x59\x8e\x79\x6a\x24\xa6\xae\x1a\xf3\x4c\x14\xe6\x99\x7a\xcc\xb3\x65\x98\xfa\x54\xcc\x73\x11\x98\xd5\xd1\x98\xe7\xfb\x51\x8b\x59\x93\x87\x59\xd3\x8d\x79\x21\x01\xf3\xe2\x26\x4c\x43\x12\xe6\xa5\x71\x98\x75\x31\x98\xc6\x70\xcc\x2b\xd1\x98\x57\xa3\x31\xaf\x45\x61\x9a\xc6\x61\xd6\x83\x59\xdf\x88\x79\xbd\x18\xf3\x46\x05\xa6\x39\x09\xd3\xdc\x89\x79\xb3\x1a\xf3\x56\x02\xe6\xed\x18\x4c\x4b\x22\x66\x43\x38\x66\x43\x3b\xe6\x9d\x3a\xcc\xc6\x6a\x4c\x6b\x09\xe6\xdd\x6c\xcc\x7b\x69\x98\xf7\x53\x31\x6d\xb1\x98\x0f\xe2\x30\x1f\x06\x98\x0f\xeb\x30\x1f\x95\x60\x36\x95\x62\x3e\x2e\xc1\x7c\x52\x8a\xf9\xb4\x06\xd3\x5e\x8d\xf9\x2c\x13\xf3\xd9\x26\xcc\x17\x82\xe9\x88\xc7\x74\x34\x62\xbe\xdc\x84\xf9\x3a\x0a\xd3\x59\x8d\xf9\x36\x12\xf3\x5d\x1c\xa6\x2b\x03\xf3\xfd\x48\xcc\xf7\x9d\x98\x1f\xea\x31\x3f\x96\x63\x7e\x8a\xc4\xfc\x54\x8c\xd9\x1c\x8d\xf9\x39\x05\xf3\x73\x3b\xa6\xa7\x10\xf3\x4b\x38\xe6\x97\x06\xcc\xaf\x95\x98\xdf\x0a\x30\xbd\x65\x98\xdf\x93\x30\x5b\x92\x31\x7d\x09\x58\x92\xb1\x26\x06\x6b\x05\xeb\x12\xb1\x12\x8e\xd5\x28\xac\x16\x61\xbd\x64\xac\xd7\x86\xf5\x13\xb1\x7e\x37\x36\xa8\xc7\x86\xd2\xb1\x43\x32\xb0\xdb\x0c\xc3\x6e\xd3\x84\x0d\x2b\xc4\x6e\x1b\x81\xdd\x2e\xc0\x6e\x2f\xd8\xed\x7b\xb1\xe1\x4d\xd8\x1d\x6a\xb0\x43\x5b\xb0\x3b\x56\x63\x23\x22\xb0\x3b\xe5\x62\x77\xce\xc3\xee\x12\x8d\x8d\x4c\xc7\xee\xba\x09\xbb\x7b\x31\x76\x58\x27\x76\xcf\x52\x6c\xd4\x48\xec\x3e\x51\xd8\x7d\x23\xb0\xfb\xae\xc1\x0e\x8f\xc0\xee\x97\x84\xdd\xbf\x14\x1b\x53\x8b\x1d\xd1\x86\x3d\xa0\x0d\x7b\x60\x15\x76\xe4\x30\xec\xc8\x12\xec\x41\x69\xd8\x51\x09\xd8\x51\xed\xd8\xd1\x69\xd8\xd1\x15\xd8\x58\xb0\xb1\x49\xd8\xd8\x12\x6c\x6c\x07\xf6\xe0\x04\xec\xc1\x65\xd8\x43\x86\x61\x0f\x29\xc5\x1e\x52\x8f\x3d\xa4\x1d\x3b\x26\x1c\x3b\x66\x1c\x76\x4c\x09\x76\x4c\x3b\x36\x2e\x01\x1b\x57\x80\x8d\x6b\xc2\x8e\x0d\xc3\x8e\xcd\xc2\x8e\xad\xc4\x8e\xed\xc0\x1e\x1a\x87\x3d\x34\x1f\x7b\x68\x0d\xf6\xb0\x00\x7b\x58\x06\xf6\xb0\x66\xec\xb8\x44\xec\xe1\x82\x3d\xbc\x9f\xeb\xb1\x47\x04\xd8\x23\x2a\xb0\x47\x46\x62\x8f\xac\xc2\xc6\x87\x61\xe3\xb3\xb1\xf1\x4d\xd8\xa3\x8a\xb0\x47\x75\x63\x8f\x6e\xc4\x8e\x17\xec\xf8\x5a\x6c\x82\x60\x13\xb2\xb0\x09\x4d\xd8\x63\x62\xb1\xc7\x14\x61\x8f\xd9\x84\x3d\x36\x11\x7b\x6c\x29\xf6\xd8\x76\xec\x84\x44\xec\x84\x42\xec\x84\x26\x6c\x62\x38\x36\x31\x15\x9b\xd8\x89\x3d\x6e\x24\xf6\xb8\x62\xec\x71\x2d\xd8\x89\x19\xd8\x89\x3d\xd8\xe3\x93\xb0\xc7\x97\x61\x8f\xef\xc0\x26\x8d\xc3\x26\x95\x63\x93\x3a\xb1\x93\xe2\xb1\x93\x0a\xb0\x93\x9a\xb0\x93\xa3\xb0\x93\xab\xb1\x93\xdb\xb1\x27\x44\x60\x4f\x28\xc2\x9e\xd0\x8c\x4d\x8e\xc7\x26\xaf\xc1\x9e\x98\x8a\x3d\xb1\x16\x3b\x45\xb0\x53\x32\xb0\x27\x81\x3d\x29\x1d\x9b\x22\xd8\x94\x3c\x6c\x4a\x3d\xf6\x64\xb0\x27\xa7\x62\x4f\x2e\xc3\x9e\xdc\x86\x9d\x1a\x83\x9d\xba\x06\x7b\x4a\x3a\xf6\x94\x26\x6c\x6a\x14\x36\xb5\x10\x9b\xda\x8d\x3d\x35\x0b\x3b\x2d\x0a\x3b\x2d\x1d\x7b\x1a\xd8\xd3\x32\xb1\xa7\x55\x63\xd3\x22\xb1\x69\xfd\xdc\x8b\x3d\x3d\x17\x7b\x7a\x27\xf6\x8c\x24\xec\x19\x5d\xd8\x33\x6b\xb1\xe9\x82\x4d\x4f\xc3\xa6\x37\x61\xcf\x4a\xc0\x9e\xd5\x84\x9d\x1e\x60\xa7\x27\x60\xa7\x97\x60\x67\x0c\xc3\xce\x48\xc6\xce\xc8\xc7\xce\xa8\xc1\xce\x68\xc3\x66\xc4\x61\x33\xda\xb0\x33\xf3\xb1\xb3\x92\xb0\xb3\xaa\xb0\xb3\xe3\xb0\xb3\x0b\xb1\xb3\x1b\xb0\x99\xe1\xd8\xcc\x72\x6c\x66\x07\x76\x4e\x19\x76\x6e\x04\x76\x6e\x3d\xf6\xec\x30\xec\xd9\xd5\xd8\xac\x08\x6c\x56\x0d\x76\x5e\x0d\x76\x7e\x01\x76\x7e\x13\xf6\x9c\x04\xec\xa2\x2a\x6c\x0e\xd8\x9c\x34\x6c\x4e\x2f\xf6\xdc\x1c\xec\xb9\x4d\xd8\xf3\xa2\xb1\xe7\x55\x63\x17\x0b\x76\x71\x32\x76\x71\x03\x36\xb7\x01\xbb\x24\x1e\xbb\xa4\x04\xbb\xa4\x1d\x7b\x7e\x24\xf6\xfc\x14\xec\xd2\x74\xec\xd2\x1a\xec\xd2\x2e\x6c\x5e\x39\x76\x59\x0e\xf6\x82\x68\xec\x05\x75\xd8\x0b\x4b\xb0\xf9\x91\xd8\x8b\x12\xb1\x17\xe7\x62\x2f\xe9\xc0\x16\xa4\x61\x2f\x8d\xc5\x5e\x9a\x8f\xbd\xb4\x16\x7b\x99\x60\x2f\x4b\xc5\x5e\xd6\x82\xbd\x3c\x0b\x5b\x98\x8c\xbd\x22\x16\x7b\x45\x25\xf6\x4a\xb0\x57\xd6\x62\xaf\xca\xc4\x5e\xb5\x06\x5b\x54\x8a\xbd\xba\x1a\x7b\x4d\x3a\xf6\xda\x44\x6c\x71\x18\x76\x79\x24\xf6\xba\x2c\xec\x75\x9d\xd8\xeb\xbb\xb0\x25\x69\xd8\x92\x2e\xec\x0d\x25\xd8\x1b\xba\xb0\x37\x36\x61\x57\x54\x60\x4b\x87\x61\x4b\xdb\xb1\x37\x25\x63\x6f\x4e\xc3\xde\x12\x83\xbd\xa5\x18\x5b\x36\x0e\x5b\xd6\x81\xbd\xb5\x0a\x7b\x5b\x04\xf6\xb6\x62\xec\xed\xd1\xd8\xf2\x42\xec\x1d\x11\xd8\x95\x65\xd8\x3b\xb3\xb0\x15\x49\xd8\xbb\x52\xb1\x77\xe7\x61\xef\xc9\xc7\x56\x66\x62\xef\x4d\xc4\xde\x57\x82\xbd\xbf\x14\x5b\xd5\x8a\x7d\x20\x13\xbb\x2a\x09\xfb\xe0\x48\xec\x83\x9d\xd8\xea\x2a\xec\x43\x59\xd8\x87\xa3\xb0\x0f\x77\x63\x1f\xe9\xc5\x3e\x3a\x0c\xfb\x68\x19\xf6\xb1\x2a\xec\xe3\x89\xd8\xda\x6c\xec\x13\xf9\xd8\x27\x63\xb1\x4f\xb6\x61\x9f\x2a\xc7\xd6\xc5\x63\x9f\x2e\xc6\x3e\x93\x80\x7d\x36\x13\x5b\x5f\x89\x7d\x6e\x0d\x76\x75\x3d\xf6\xf9\x42\xec\x9a\x54\xec\xda\x3a\xec\x0b\x1d\xd8\x86\x78\x6c\x43\x0f\xf6\xa5\x4d\xd8\x75\xe1\xd8\xc6\x62\xec\x2b\xf9\xd8\x57\x0b\xb0\xaf\xc5\x63\x9b\xa2\xb0\x4d\xd5\xd8\xf5\x85\xd8\xd7\xa3\xb1\xaf\xaf\xc1\xbe\x51\x8f\x6d\x2e\xc5\xbe\x19\x8b\x7d\x2b\x0a\xfb\x76\x35\xb6\xa5\x17\xfb\x4e\x04\x76\x63\x34\xb6\x35\x11\xfb\x6e\x16\xf6\xbd\x0c\xec\xfb\xc9\xd8\xf7\x7b\xb0\x6d\x95\xd8\x0f\x4a\xb0\x1f\xe6\x62\x3f\x2a\xc2\x6e\xca\xc2\x7e\x9c\x88\xfd\x24\x0d\xfb\x49\x07\xf6\xd3\x1a\x6c\x7b\x3e\xf6\xb3\x18\xec\x67\x2d\xd8\xcf\x6b\xb0\x5f\xb4\x63\x3b\x0a\xb1\x5f\xb6\x62\xbf\xaa\xc6\x7e\xdd\x85\xed\x2c\xc2\x7e\x93\x8b\xfd\x36\x13\xfb\x5d\x14\xb6\x2b\x1a\xfb\x7d\x0c\xf6\xfb\x6a\xec\x0f\x69\xd8\x1f\xa3\xb1\x3f\x56\x60\xbb\x0b\xb0\x3f\x45\x60\x37\x97\x60\x7f\x6e\xc2\xf6\xb4\x63\x7f\xa9\xc5\xfe\xda\x83\xfd\xad\x0b\xdb\xdb\x80\xfd\x3d\x09\xbb\x25\x0c\xdb\x17\x8e\xed\xcb\xc3\x91\x87\x33\x91\x38\x1b\x8e\xb3\x5d\x38\x09\xc7\x69\x09\xce\x4b\xc4\xf9\x69\xb8\x20\x13\x17\x4a\xc0\x85\x3a\x71\x43\xca\x71\xdb\xa4\xe3\xb6\xe9\xc5\x85\xe5\xe2\xb6\x0d\xc3\x6d\x97\x8d\xdb\xae\x17\xb7\x7d\x2b\x2e\xbc\x07\xb7\x43\x2b\x6e\x68\x3b\x6e\xc7\x1a\x5c\x44\x0d\x6e\xa7\x6c\xdc\xce\xc3\x70\xbb\x24\xe1\x22\xe3\x71\x91\xed\xb8\x5d\xeb\x70\xbb\xd5\xe2\x76\x2f\xc6\x0d\xcb\xc1\xed\x91\x88\xdb\xb3\x01\xb7\x57\x05\x2e\x2a\x15\xb7\x77\x26\x6e\x9f\x61\xb8\x7d\x3a\x71\xd1\x31\xb8\xe1\x61\xb8\xe1\x55\xb8\xfd\x8a\x71\xfb\x97\xe3\x62\x46\xe2\x46\xe4\xe2\x0e\x10\xdc\x81\x05\xb8\x03\xdb\x71\x07\x45\xe0\x0e\xaa\xc7\x8d\xea\xc5\xc5\x16\xe3\x0e\xae\xc6\x1d\xd2\x89\x1b\xd3\x8d\x8b\xab\xc0\x8d\xad\xc3\x1d\xda\x8c\x3b\xac\x09\x37\xae\x17\x77\x44\x29\xee\xc8\x12\x5c\x7c\x3c\xee\x28\xc1\x1d\x55\x81\x3b\x3a\x03\x37\x3e\x06\x97\x10\x8f\x3b\xa6\x13\x37\x21\x03\x97\x18\x87\x3b\x2e\x0c\x37\x51\x70\xc7\x47\xe0\x92\xa2\x70\x93\x62\x70\x93\x93\x70\x27\x54\xe1\x92\xeb\x71\x27\xb6\xe0\xa6\x94\xe3\x4e\x1a\x87\x4b\xc9\xc6\x9d\x5c\x89\x9b\x5a\x89\x3b\x65\x0d\xee\xd4\x68\xdc\xb4\x1a\x5c\x5a\x0c\xee\xf4\x4a\xdc\x99\x31\xb8\xf4\x64\xdc\x59\x91\xb8\xb3\x5a\x71\xd3\xb3\x71\xd3\x7b\x71\x33\x5a\x71\x19\x35\xb8\x99\x1d\xb8\xd9\xe1\xb8\xcc\x7e\x74\xe3\xe6\x76\xe0\xb2\xea\x71\xf3\xc3\x71\xe7\xe4\xe0\xb2\x93\x71\x0b\xc2\x71\x0b\xf2\x71\x0b\x3a\x70\x0b\x33\x70\x0b\x9b\x71\x8b\xe2\x71\x8b\x2a\x71\xe7\xe5\xe2\x16\xd7\xe3\x96\xc4\xe1\xce\x2f\xc6\x2d\xad\xc0\x2d\x8b\xc2\x5d\x10\x81\xbb\xa0\x1b\x77\x61\x21\x2e\x7f\x18\x2e\xbf\x1d\x77\x51\x05\xee\xe2\x06\xdc\x25\xad\xb8\x82\x5e\xdc\x65\x65\xb8\xcb\x1b\x71\x85\x3d\xb8\x2b\x36\xe1\xae\x6c\xc2\x15\x45\xe3\xae\xce\xc2\x5d\x53\x80\xbb\xb6\x1c\x57\x9c\x85\x5b\x1e\x87\xbb\x2e\x01\x77\x7d\x32\xae\x24\x0e\x77\x43\x14\xee\xc6\x5c\xdc\x8a\x3a\x5c\x69\x27\xee\xe6\x18\xdc\x2d\x23\x71\x65\x31\xb8\xb2\x7a\xdc\x6d\x19\xb8\xdb\x7a\x70\xb7\x97\xe2\xca\x63\x70\xe5\x55\xb8\x3b\x92\x71\x77\xb4\xe0\x56\x36\xe3\x2a\x86\xe1\xee\x4a\xc5\xdd\x0d\xee\x9e\x3a\xdc\xbd\x01\xee\xbe\x48\xdc\xfd\xd1\xb8\xaa\x44\xdc\x03\xe9\xb8\x55\x45\xb8\x07\x5b\x71\xd5\xa9\xb8\x87\xea\x70\x8f\x94\xe1\x6a\xea\x70\x8f\x6e\xc2\x3d\x1e\x8e\x7b\xbc\x13\xf7\x44\x38\xee\xc9\x78\xdc\x53\x49\xb8\xba\x34\xdc\xd3\x75\xb8\x67\xca\x70\xcf\x56\xe0\xea\x5b\x70\xcf\xa5\xe0\x56\x27\xe0\x9e\x4f\xc2\xad\x49\xc0\xad\xcd\xc2\xad\xed\xc1\xbd\x98\x8b\x6b\xc8\xc0\xbd\x54\x8a\x7b\x39\x07\xb7\x2e\x11\xd7\x98\x8f\x7b\xa5\x0e\xf7\x5a\x04\x6e\x3d\xb8\xd7\x13\x71\x6f\xe4\xe3\x9a\x87\xe1\x9a\xeb\x71\x6f\xf6\xe0\xde\x6a\xc2\xb5\x8c\xc3\x6d\x48\xc4\xbd\x93\x82\xdb\x98\x8a\x6b\x8d\xc2\xb5\x6e\xc2\xbd\x17\x81\x7b\x3f\x1e\xd7\x96\x8e\xfb\x20\x07\xf7\xe1\x30\xdc\x87\x8d\xb8\x8f\x9a\x71\x9b\x5a\x70\x1f\x57\xe2\x3e\xc9\xc1\x7d\xda\x8b\xfb\x0c\xdc\x67\x25\xb8\xcf\x23\x70\x5f\x64\xe1\xbe\x0c\xc3\x7d\x95\x82\xfb\xaa\x13\xf7\x75\x39\xae\x33\x1e\xd7\xd9\x8d\xfb\x26\x1f\xf7\x6d\x32\xee\xbb\x48\x5c\x57\x2e\xee\x87\x30\xdc\x0f\x25\xb8\x1f\xc3\x71\x3f\x16\xe2\x7e\xec\xc6\x75\xe7\xe2\x7e\x12\xdc\x4f\xd9\xb8\x9f\x5a\x70\x9b\x13\x70\x9b\x2b\x71\x3f\x0f\xc3\xfd\x9c\x8b\xfb\xb9\x13\xd7\x93\x81\xeb\x69\xc6\xfd\x92\x86\xfb\xa5\x09\xf7\x6b\x32\xee\xd7\x2a\xdc\x6f\x23\x71\xbf\x95\xe3\x7a\x33\x70\xbd\x2d\xb8\xdf\x93\x71\xbf\xaf\xc1\x6d\x89\xc1\x6d\xc9\xc7\x6d\x69\xc2\xf5\xa5\xe3\xfa\x7a\x11\x72\x11\x3a\x11\x13\x83\x98\x42\xc4\xb4\x21\x36\x01\xb1\x45\x88\x6d\x43\x5c\x39\x22\x61\x88\x64\x20\x52\x89\x28\x88\xc6\x21\x5a\x81\x68\x1b\xe2\x45\x20\x5e\x0a\xe2\x15\x23\x5e\x1b\xe2\x47\x21\x7e\x3e\xe2\x37\x23\xc1\x48\x24\xa8\x46\x42\xb1\x48\xa8\x05\x19\x92\x8a\x0c\x29\x43\x86\x6c\x42\xb6\x89\x42\xb6\xc9\x45\xb6\x69\x40\xb6\xe9\x44\xc2\xe2\x91\xb0\x3a\x64\xdb\x44\x64\xdb\x7e\xee\x42\xb6\x4b\x43\xb6\x2b\x42\xb6\xdb\x84\x6c\x9f\x8e\x6c\xdf\x80\x6c\xdf\x81\x84\xc7\x20\xe1\x29\x48\x78\x09\x12\xde\x83\xec\x90\x80\xec\x50\x80\xec\xd0\x82\x0c\x1d\x87\x0c\xad\x42\x86\x76\x22\x3b\x46\x23\x3b\xa6\x23\x3b\xd6\x21\x3b\x76\x21\x11\x31\x48\x44\x26\x12\x51\x89\x44\xb4\x20\x3b\xc5\x20\x3b\x65\x23\x3b\xd5\x20\x3b\x07\xc8\xce\x05\xc8\xce\x0d\xc8\x2e\xe1\xc8\x2e\xf1\xc8\x2e\x45\xc8\x2e\x9d\x48\x64\x26\x12\xb9\x09\xd9\x35\x1e\xd9\xb5\x0b\xd9\x2d\x0d\xd9\xad\x11\xd9\x7d\x24\xb2\x7b\x09\x32\x4c\x90\x61\x19\xc8\xb0\x36\x64\x8f\x08\x64\x8f\x54\x64\x8f\x46\x64\xcf\x91\xc8\x9e\x79\xc8\x9e\x8d\xc8\x5e\x82\xec\x95\x80\xec\x55\x85\xec\xd5\x83\x44\x25\x21\x51\x6b\x90\xbd\xe3\x90\xbd\xb3\x90\xbd\x9b\x91\x7d\x52\x91\x7d\x4a\x91\x7d\xc3\x90\x7d\xf3\x91\x7d\x3b\x91\xe8\x68\x24\x3a\x03\x89\xae\x46\xa2\x37\x21\xc3\x33\x91\xe1\x95\xc8\x7e\x82\xec\x97\x8b\xec\xd7\x8e\xec\x5f\x80\xc4\x44\x23\x31\xcd\xc8\x88\x6c\xe4\x80\x71\xc8\x01\x8d\xc8\x81\x39\xc8\x81\xed\xc8\xc8\x54\x64\x64\x1b\x72\x50\x06\x72\x50\x13\x32\x2a\x0d\x19\x55\x82\x8c\x0e\x90\xd1\xf5\xc8\xe8\x2e\x24\x36\x01\x89\x6d\x46\x0e\x1e\x87\x1c\x5c\x8f\x1c\x92\x84\x1c\xb2\x09\x19\x93\x8d\xc4\x45\x21\x71\x45\x48\x5c\x13\x32\x36\x13\x19\xdb\x82\x1c\x9a\x89\x1c\xda\x80\x1c\x96\x8c\x1c\xd6\x80\x8c\x1b\x86\x8c\xcb\x47\xc6\x35\x22\x87\xa7\x23\x87\x77\x21\x47\x94\x23\x47\x8e\x44\x8e\x6c\x40\xe2\x53\x91\xf8\x4e\xe4\xa8\x14\xe4\xa8\x26\xe4\xe8\x78\xe4\xe8\x3a\x64\x7c\x2c\x32\xbe\x04\x19\xbf\x09\x49\x48\x47\x12\x36\x21\xc7\xc4\x23\xc7\x54\x20\xc7\x74\x20\xc7\x66\x22\xc7\xd6\x21\x13\x04\x99\x90\x80\x4c\xc8\x43\x26\xac\x41\x12\x63\x91\xc4\x6c\x24\xb1\x12\x49\x6c\x45\x8e\xcb\x44\x8e\x6b\x47\x26\x26\x23\x13\xeb\x90\x89\x3d\xc8\xf1\x29\xc8\xf1\x4d\x48\x52\x2a\x92\x54\x81\x4c\x0a\x90\x49\xb9\xc8\xa4\x66\x64\xf2\x30\x64\x72\x11\x32\x79\x0d\x32\xb9\x1b\x39\x21\x19\x39\xa1\x06\x49\x0e\x90\xe4\x2c\x24\xb9\x01\x39\x31\x1a\x39\xb1\x02\x39\x71\x13\x32\x45\x90\x29\xd1\xc8\x94\x24\x64\x4a\x36\x32\xa5\x0c\x99\xd2\x80\x9c\x04\x72\x52\x1c\x72\x52\x19\x92\x32\x0c\x49\x69\x40\x4e\x4e\x44\x4e\x6e\x46\xa6\xa6\x20\x53\x5b\x91\x53\x92\x91\x53\x1a\x91\xd4\x1c\xe4\xd4\x70\xe4\xd4\x7c\x64\x5a\x18\x32\x2d\x0f\x39\x2d\x40\x4e\xcb\x42\x4e\xeb\x44\xd2\xd2\x90\xb4\x4e\xe4\xf4\x2c\xe4\x8c\x00\x39\x23\x1b\x39\x13\xe4\xcc\x2c\x24\x1d\x24\x3d\x0b\x39\x0b\xe4\xac\x5c\x64\xfa\x30\x64\x7a\x0d\x32\x23\x17\x99\xd1\x80\x64\x24\x21\x19\x0d\xc8\xcc\x74\x64\x66\x2d\x32\x6b\x24\x32\xab\x10\x99\xd5\x83\xcc\xce\x42\x66\x77\x23\x99\x19\x48\x66\x27\x32\x27\x05\x99\xd3\x8c\xcc\x4d\x44\xe6\xd6\x23\x67\x27\x22\x67\xd7\x22\x59\xe1\x48\x56\x2e\x92\xd5\x8c\xcc\x8b\x43\xe6\x15\x22\xf3\xda\x90\xf9\x51\xc8\xfc\x74\x64\x7e\x0d\x32\xbf\x17\x39\x27\x16\x39\x27\x03\x39\xa7\x16\xc9\x16\x24\x3b\x0f\x59\x10\x86\x2c\x28\x40\x16\x46\x22\x0b\x8b\x91\x45\x51\xc8\xa2\x22\x64\x51\x37\x92\x93\x8e\xe4\x34\x22\xe7\x46\x21\xe7\xe6\x23\xe7\x76\x23\xe7\xe5\x20\x8b\x63\x91\xc5\x6d\x48\x6e\x1d\xb2\xa4\x00\x39\x3f\x02\x39\xbf\x0c\x59\x1a\x8b\x2c\xad\x43\xf2\x86\x21\x79\x95\xc8\xb2\x00\x59\x56\x8a\x5c\x20\xc8\x05\xe9\xc8\x05\x4d\xc8\x85\x31\xc8\x85\x55\x48\x7e\x38\x92\x9f\x8b\xe4\xaf\x41\x2e\x4a\x46\x2e\x6a\x46\x2e\x4e\x43\x2e\x6e\x43\x2e\x29\x40\x0a\xa2\x90\x82\x66\xe4\xd2\x3c\xe4\xb2\x28\xe4\xb2\x06\xe4\xf2\x30\xe4\xf2\x7c\xe4\xf2\x46\xa4\x70\x1c\x52\x98\x8b\x14\xb6\x22\x57\xc4\x22\x57\xd4\x20\x57\xc6\x21\x57\xd6\x21\x57\x25\x22\x57\x35\x23\x45\xc9\x48\x51\x23\x72\x75\x0e\x72\x4d\x24\x72\x4d\x35\x72\x6d\x02\x72\x6d\x3d\x52\x1c\x8b\x14\x17\x23\xc5\x9b\x90\xe5\x39\xc8\xf2\x6e\xe4\xba\x42\xe4\xfa\x00\xb9\xbe\x06\x29\x49\x46\x4a\xda\x90\x1b\x32\x91\x1b\xba\x91\x1b\xf3\x91\x1b\x5b\x91\x15\x71\xc8\x8a\x2a\xa4\x34\x12\x29\xcd\x42\x4a\xdb\x90\x9b\xe2\x91\x9b\xca\x91\x9b\x3a\x91\x9b\xe3\x91\x9b\x0b\x90\x9b\xd7\x20\xb7\xc4\x20\xb7\xd4\x20\x65\x69\x48\x59\x17\x72\x6b\x11\x72\x6b\x37\x72\x5b\x05\x72\xbb\x20\xb7\x17\x21\xe5\x20\xe5\xe5\xc8\x1d\x31\xc8\x1d\xad\xc8\xca\x4c\xe4\xce\x70\xe4\xce\x1a\xa4\x22\x07\xb9\x2b\x1a\xb9\xab\x07\xb9\xbb\x08\xb9\x27\x1e\xb9\x67\x0d\x52\x99\x89\x54\xb6\x23\xf7\x16\x21\xf7\x45\x23\xf7\x6d\x42\xee\x2f\x46\xaa\xd2\x90\xaa\x76\xe4\x81\x52\xe4\x81\x0e\x64\x55\x0e\xb2\xaa\x0d\x79\x30\x0f\x79\xb0\x13\xa9\x2e\x41\x1e\x0a\x43\x1e\xaa\x47\x1e\x1e\x87\x3c\xdc\x8e\x3c\x92\x8b\xd4\xc4\x21\x35\xad\xc8\xa3\xd5\xc8\x63\xb1\xc8\x63\xed\xc8\xe3\xc9\xc8\xe3\xe5\xc8\xe3\x5d\x48\x6d\x12\x52\xdb\x84\x3c\x91\x80\x3c\xd1\x86\x3c\x99\x89\x3c\x15\x81\x3c\x55\x83\xd4\xa5\x23\x75\x3d\xc8\xd3\x75\xc8\x33\x59\xc8\xb3\xf1\x48\x3d\x48\x7d\x2d\xf2\x5c\x2a\xf2\x5c\x17\xb2\xba\x00\x79\x3e\x12\x79\xbe\x12\x59\x93\x8a\xac\xe9\x41\xd6\xd6\x22\x2f\x64\x22\x2f\x82\xbc\x58\x82\x34\x80\x34\x64\x23\x0d\x5d\xc8\x4b\xb9\xc8\x4b\xbd\xc8\xcb\x45\xc8\xba\x70\x64\x5d\x39\xd2\x18\x8f\x34\xb6\x21\xaf\x14\x22\xaf\xc6\x22\xaf\xd6\x23\xaf\x25\x21\xaf\x95\x22\x4d\x01\xd2\x94\x86\x34\x35\x21\xeb\x63\x91\xf5\x75\xc8\xeb\x31\xc8\xeb\xf5\xc8\x1b\x79\x48\x73\x3c\xf2\x66\x04\xf2\x66\x27\xf2\x56\x03\xf2\x76\x05\xd2\x52\x86\x6c\x28\x43\xde\x09\x90\x77\x0a\x90\x8d\xe1\xc8\xc6\x4a\xa4\x35\x0e\x69\x6d\x44\xde\xcd\x43\xde\x8b\x45\xde\x6b\x42\xde\xcf\x41\xda\x62\x90\xb6\x76\xe4\x83\x0a\xe4\xc3\x0c\xe4\xc3\x06\xe4\xa3\x58\xe4\xa3\x1a\x64\x53\x1c\xb2\xa9\x16\xf9\x78\x1c\xf2\x71\x0d\xf2\x49\x2c\xf2\x49\x03\xf2\x69\x3a\xf2\x69\x17\xd2\x5e\x84\x7c\x16\x8f\x7c\xd6\x83\x7c\x9e\x81\x7c\xde\x8c\x7c\x91\x8a\x7c\xd1\x8a\x74\xa4\x23\x1d\xed\xc8\x97\x45\xc8\x57\x71\xc8\x57\xe5\xc8\xd7\x61\xc8\xd7\x25\x48\x67\x04\xd2\x59\x86\x7c\x13\x85\x7c\xd3\x80\x7c\x9b\x83\x7c\xdb\x8c\x7c\x37\x0e\xf9\xae\x16\xe9\x8a\x43\xba\x6a\x91\xef\xc7\x21\xdf\xb7\x20\x3f\xe4\x21\x3f\xf4\x20\x3f\x16\x20\xdd\xc3\x90\xee\x7a\xe4\xa7\x74\x64\x33\xc8\xe6\x52\xe4\xe7\x58\xe4\xe7\x4d\x48\x4f\x29\xf2\x4b\x22\xf2\x4b\x0f\xf2\x6b\x36\xf2\x6b\x07\xf2\x5b\x1e\xd2\x1b\x86\xf4\x56\x20\xbf\x8f\x43\x7e\xef\x44\xb6\x54\x22\x7d\x01\xd2\x57\x88\x22\x28\x95\xa8\x49\x42\x4d\x37\x6a\x6b\x51\x97\x87\x4a\x3c\xaa\x82\x6a\x07\xea\x35\xa3\x7e\x0e\x1a\x44\xa2\x41\x0b\x1a\x2a\x41\x87\xa4\xa0\xdb\x44\xa0\xdb\x74\xa1\x61\x2d\xe8\xb6\xf9\xe8\x76\x31\xe8\x76\xb5\xe8\xf6\x89\xe8\xf6\x55\x68\x78\x04\x1a\x9e\x85\x86\xaf\x41\x77\x88\x45\x77\xa8\x44\x87\x06\xe8\xd0\x1c\x74\x47\x41\x77\x2c\x47\x23\x0a\xd0\x9d\xb2\xd1\x9d\xb3\xd1\x5d\x72\xd0\xc8\x5c\x74\xd7\x7c\x74\xb7\x72\x74\xf7\x06\x74\x58\x16\xba\x47\x04\xba\x47\x0b\xba\x67\x19\xba\x57\x3a\x1a\x15\x85\xee\x0d\xba\x77\x07\xba\x4f\x31\xba\xef\x38\x74\xdf\x1e\x34\xba\x1e\x1d\x9e\x8f\xee\x97\x80\xee\x1f\x85\xc6\x04\x68\x4c\x05\x3a\x22\x01\x1d\xd1\x8d\x1e\x50\x85\x1e\x98\x8e\x8e\x8c\x40\x47\x76\xa0\x07\x35\xa0\xa3\x4a\xd1\xd1\xd9\x68\x6c\x1a\x7a\x70\x12\x7a\x48\x1c\x3a\x26\x1a\x8d\x8b\x45\xc7\x26\xa2\x87\x46\xa0\x87\x76\xa2\x87\xb5\xa2\xe3\x1a\xd0\xc3\x6b\xd1\x23\xaa\xd0\x23\x6b\xd1\xf8\x46\xf4\xa8\x42\xf4\xe8\x68\xf4\xe8\x1e\x74\x7c\x2d\x9a\x50\x8c\x1e\x93\x86\x1e\x9b\x82\x1e\xbb\x06\x9d\x10\x89\x4e\xc8\x43\x27\xb4\xa1\x89\xa9\x68\x62\x31\x9a\xd8\x80\x26\xf6\xa2\xc7\x25\xa1\xc7\x35\xa2\x13\xd3\xd0\x89\xcd\xe8\xf1\x59\xe8\xf1\x5d\x68\x52\x25\x9a\xd4\x8d\x4e\x4a\x42\x27\x95\xa3\x93\xba\xd1\xc9\x19\xe8\xe4\x5a\xf4\x84\x30\xf4\x84\x02\xf4\x84\x0e\x34\x39\x0e\x4d\x6e\x40\x4f\x4c\x45\x4f\x6c\x42\xa7\xe4\xa3\x53\xda\xd0\x93\xa2\xd0\x93\x72\xd0\x93\x1a\xd0\x94\x61\x68\x4a\x1e\x9a\xd2\x8d\x9e\x9c\x85\x9e\xdc\x80\x4e\xcd\x44\x4f\x01\x3d\xa5\x04\x4d\x8d\x41\x53\x6b\xd0\x53\x73\xd0\x53\x9b\xd0\x69\x61\xe8\xb4\x34\x74\x5a\x15\x7a\x5a\x34\x7a\x5a\x11\x7a\x5a\x07\x9a\x16\x8e\xa6\x35\xa1\xa7\xe7\xa0\x67\xc4\xa1\x67\x74\xa2\x67\x36\xa1\xe9\xc9\x68\x7a\x33\x7a\x56\x3a\x7a\x56\x27\x3a\xbd\x04\x9d\x5e\x8f\x4e\xef\xfd\x7f\xc7\x8c\x48\x74\x46\x2a\x3a\xa3\x10\x9d\x51\x8b\xce\x68\x46\x67\x74\xa2\x19\x01\x9a\x11\x87\x66\x64\xa0\x19\xf9\x68\x46\x25\x9a\xd1\x8a\x66\xf4\xa2\x33\xa3\xd1\x99\xc9\xe8\xcc\x5c\x74\x66\x0d\x3a\xb3\x0b\x9d\x15\x8b\xce\xca\x43\x67\xd5\xa2\xb3\xc3\xd1\xd9\x89\xe8\xec\x1a\x74\x76\x33\x3a\xbb\x17\xcd\x8c\x46\x33\x53\xd1\xcc\xc2\x3f\x30\x27\x17\x9d\x53\x8a\xce\x59\x83\xce\xe9\x45\xe7\x46\xa3\x73\x93\xd1\xb9\xf5\xe8\xdc\x56\x74\x6e\x0f\x7a\x76\xeb\x1f\xc8\x0a\x47\xb3\x32\xd0\xac\x42\x34\xab\x0a\xcd\x6a\x43\xe7\x85\xa3\xf3\x32\xd0\x79\x95\xe8\xbc\x1e\x74\x7e\x16\x3a\xbf\x1a\x3d\x27\x0e\x3d\xa7\x02\x3d\xa7\x13\xcd\x4e\x42\xb3\xab\xd1\xec\x1e\x74\x41\x2c\xba\xa0\x14\x5d\xd0\x8b\x2e\xac\x40\x17\xc5\xa0\x8b\x72\xd0\x45\xed\x68\x4e\x36\x7a\xae\xa0\xe7\x96\xa1\xe7\x25\xa2\xe7\x75\xa3\x8b\x8b\xd1\xdc\x00\xcd\x4d\x47\x73\xeb\xd1\x25\x39\xe8\x92\x5e\xf4\xfc\x42\x74\x69\x18\xba\xb4\x00\xcd\x8b\x40\xf3\x8a\xd0\xbc\x4d\xe8\xb2\x14\x74\x59\x19\x7a\x41\x1c\x7a\x41\x15\x7a\x61\x22\x7a\x61\x27\x9a\x9f\x84\xe6\xd7\xa3\x17\xc5\xa2\x17\xb5\xa0\x17\x0b\x7a\x71\x15\x7a\x49\x0e\x5a\x10\x8b\x5e\x1a\x83\x5e\x16\xa0\x97\xd5\xa3\x97\x87\xa3\x97\x27\xa1\x97\x17\xa0\x97\xd7\xa1\x97\x77\xa1\x85\x89\x68\x61\x19\x5a\xd8\x83\x5e\x91\x83\x5e\x51\x8d\x5e\xd1\x82\x5e\x19\x86\x5e\x99\x88\x5e\x99\x89\x5e\x59\x82\x5e\xb9\x06\xbd\x2a\x1e\xbd\x2a\x1d\xbd\xaa\x1e\x2d\x12\xb4\xa8\x04\x2d\x6a\x45\xaf\x4e\x46\xaf\x2e\x40\xaf\xae\x45\xaf\x09\xd0\x6b\x62\xd0\x6b\x72\xd0\x6b\xea\xd0\x6b\xda\xd1\x6b\x41\xaf\x8d\x46\xaf\x4d\x47\xaf\xcd\x47\xaf\xad\x45\xaf\x6d\x43\x8b\x87\xa1\xc5\x19\x68\x71\x25\x5a\xdc\x8b\x2e\x4f\x47\x97\x17\xa2\xcb\x6b\xd0\xe5\x6d\xe8\x75\xe1\xe8\x75\xb9\xe8\x75\x6b\xd0\xeb\xba\xd1\xeb\xa3\xd0\xeb\x93\xd1\xeb\x0b\xd0\xeb\xdb\xd1\x92\x70\xb4\x24\x11\x2d\xc9\x45\x4b\xaa\xd0\x92\x0e\xf4\x86\x54\xf4\x86\x22\xf4\x86\x26\xf4\xc6\x04\xf4\xc6\x32\xf4\xc6\x36\x74\x45\x0a\xba\xa2\x0a\x5d\xd1\x81\x96\x16\xa2\xa5\x8d\xe8\x4d\xd1\xe8\x4d\x09\xe8\x4d\xe9\xe8\x4d\x79\xe8\x4d\xa5\xe8\x4d\x35\xe8\x2d\xd5\xe8\xed\xc5\xe8\x9d\x31\xe8\x9d\x89\xe8\x9d\xd9\xe8\x9d\x45\xe8\x9d\xb5\xe8\x9d\xcd\xe8\x9d\xbd\x68\x45\x24\x5a\x11\x87\x56\xa4\xa0\x15\x45\xe8\x5d\x61\xe8\xdd\x29\xe8\xdd\x45\xe8\xdd\x9d\xe8\x3d\x85\xe8\x3d\x2d\x68\x65\x09\x7a\x6f\x0c\x7a\x6f\x13\x7a\x5f\x3c\x7a\xdf\x26\xf4\xfe\x64\xf4\xfe\x76\xb4\x6a\x1c\x5a\x95\x8b\x56\x35\xa0\x0f\x8c\x44\x1f\x28\x43\x1f\xe8\x44\x57\xc5\xa1\xab\x4a\xd1\x55\x5d\xe8\x83\x59\xe8\x83\xed\x68\x75\x32\x5a\x5d\x8a\x56\xf7\xa0\x0f\x25\xa2\x0f\x95\xa1\x0f\x35\xa3\x0f\x07\xe8\xc3\x05\xe8\xc3\xcd\xe8\x23\x69\xe8\x23\xad\x68\x4d\x2a\x5a\x53\x80\xd6\x54\xa1\x8f\x46\xa2\x8f\x26\xa3\x8f\x16\xa1\x8f\x36\xa2\x8f\x09\xfa\x58\x2c\xfa\x58\x1a\xfa\x58\x01\xfa\x58\x3d\xfa\x58\x0f\xfa\x78\x1c\xfa\x78\x06\xfa\x78\x39\xfa\x78\x2b\x5a\x9b\x80\xd6\x16\xa3\xb5\xd5\x68\x6d\x13\x5a\xdb\x8e\x3e\x91\x87\x3e\xd1\x85\x3e\xd9\x84\x3e\x55\x8c\x3e\xd5\xcf\xdd\x68\xdd\x48\xb4\x2e\xe3\x0f\x3c\xdd\x8b\x3e\x53\x88\x3e\xd3\x80\x3e\xd3\x85\x3e\x1b\x83\x3e\x9b\x8a\xd6\x87\xa1\xf5\x59\x68\x7d\x15\x5a\xdf\x8b\x3e\x97\x82\x3e\x57\x8b\xae\x8e\x45\x57\xe7\xa3\xab\x1b\xd0\xe7\x63\xd0\xe7\xcb\xd1\xe7\x5b\xd0\x35\x61\xe8\x9a\x6c\x74\x4d\x13\xba\xa6\x03\x5d\x1b\x89\xae\x4d\x42\xd7\xe6\xa1\x6b\x2b\xd1\xb5\x2d\xe8\x0b\x82\xbe\x30\x12\x7d\x21\x1d\x7d\xa1\x18\x7d\xa1\x16\x7d\xa1\x1d\x7d\x31\x12\x7d\x31\x09\x7d\x31\x0f\x7d\xb1\x1c\x7d\xb1\x01\x7d\xb1\x1b\x6d\x88\x46\x1b\xd2\xd0\x86\x22\xb4\xa1\x16\x6d\x68\x43\x5f\x0a\x43\x5f\x8a\x47\x5f\xca\x41\x5f\xaa\x40\x5f\x6a\x44\x5f\xea\x44\x5f\x8e\x44\x5f\x4e\x46\x5f\x2e\x40\x5f\xae\x45\x5f\x6e\x47\xd7\x85\xa1\xeb\xc6\xa1\xeb\xb2\xd0\x75\x65\xe8\xba\x06\x74\x5d\x37\xda\x18\x83\x36\xa6\xa1\x8d\x05\x68\x63\x0d\xda\xd8\x8a\xbe\x12\xa0\xaf\x8c\x43\x5f\xc9\x46\x5f\x29\x47\x5f\x69\x44\x5f\xe9\x42\x5f\x8d\x42\x5f\x4d\x41\x5f\x2d\x44\x5f\xad\x45\x5f\x6d\x43\x5f\x03\x7d\x6d\x24\xfa\x5a\x06\xfa\x5a\x29\xfa\x5a\x23\xfa\x5a\x0f\xda\x14\x85\x36\x25\xa1\x4d\x79\x68\x53\x35\xda\xb4\x09\x5d\x1f\x8e\xae\x1f\x87\xae\xcf\x44\xd7\x97\xa0\xeb\xd7\xa0\xeb\x3b\xd1\xd7\x87\xa1\xaf\x27\xa3\xaf\x17\xa0\xaf\xd7\xa0\xaf\xb7\xa0\xaf\xf7\xa2\x6f\x8c\x44\xdf\x48\x47\xdf\x28\x41\xdf\x68\x40\xdf\xe8\x44\x9b\xc3\xd1\xe6\x78\xb4\x39\x07\x6d\xae\x44\x9b\x5b\xd1\x37\x03\xf4\xcd\x58\xf4\xcd\x0c\xf4\xcd\x12\xf4\xcd\x06\xf4\xcd\x1e\xf4\xad\x18\xf4\xad\x14\xf4\xad\x02\xf4\xad\x2a\xf4\xad\x56\xf4\xed\x30\xf4\xed\x78\xf4\xed\x2c\xf4\xed\x52\xf4\xed\x06\xf4\xed\x6e\xb4\x25\x0a\x6d\x49\x41\x5b\x0a\xd0\x96\x5a\xb4\xa5\x03\xdd\x10\x8e\x6e\x88\x43\x37\xa4\xa3\x1b\x4a\xd0\x0d\x0d\xe8\x86\x1e\xf4\x9d\x18\xf4\x9d\x14\xf4\x9d\x02\xf4\x9d\x1a\xf4\x9d\x76\x74\x63\x24\xba\x31\x09\xdd\x98\x83\x6e\x2c\x43\x37\x36\xa2\x1b\x7b\xd0\xd6\x91\x68\x6b\x3a\xda\x5a\x88\xb6\xd6\xa2\xad\xed\xe8\xbb\x61\xe8\xbb\xf1\xe8\xbb\xd9\xe8\xbb\xa5\xe8\xbb\x6b\xd0\x77\x3b\xd1\xf7\x22\xd1\xf7\x12\xd1\xf7\x63\xd0\xb6\x70\xb4\xad\x07\xfd\xa0\x1d\xfd\xb0\x0d\xfd\xa8\x05\xdd\xd4\x8c\x7e\xdc\x8c\x7e\x92\x81\x7e\xd2\x8d\x7e\x5a\x84\xb6\x47\xa1\xed\x0d\xe8\x67\x59\xe8\xe7\xe1\xe8\xe7\xf5\xe8\x17\x69\xe8\x17\xbd\x68\x47\x39\xfa\x65\x22\xfa\x65\x0f\xfa\x55\x35\xfa\x75\x26\xda\x19\x85\x76\xd6\xa3\xdf\xa4\xa1\xdf\x0a\xfa\x6d\x0d\xfa\x5d\x1a\xda\x05\xda\x55\x8f\x7e\x9f\x87\x7e\xdf\x8e\xfe\x90\x8c\xfe\xd0\x88\xfe\x98\x8a\xfe\x58\x8b\x76\x47\xa2\xdd\xf9\x68\x77\x3b\xfa\xd3\x48\xf4\xa7\x7c\xf4\xa7\x66\x74\x73\x0a\xba\xb9\x06\xfd\x39\x02\xfd\x39\x19\xfd\xb9\x08\xfd\xb9\x07\xed\x49\x41\x7b\xaa\xd0\x9e\x4d\xe8\x2f\x11\xe8\x2f\x25\xe8\xaf\xe1\xe8\xaf\xf9\xe8\xaf\x1d\xe8\x6f\x99\xe8\x6f\x9b\xd0\xde\x54\xb4\xb7\x09\xfd\x7d\xe0\x97\x01\x42\x0b\xcd\x54\x52\xf9\xe3\x57\x61\x0d\x96\x9d\xfb\x93\xed\xc2\xc1\xf7\xba\x76\xe0\x2d\x1c\x46\x42\xc0\xf4\x81\x5f\x48\xeb\xb7\x0d\x43\x99\x3e\x68\xf7\x97\xc8\x19\xb4\x1d\x29\x5c\x39\x68\x0b\x07\xf0\xce\xa0\xad\x44\x9a\xad\x65\x3d\xf6\x33\x91\x83\xb6\x4f\xa5\x39\x7a\xd0\x0e\x38\xc0\x7c\x32\x68\x87\x88\xb1\x61\x83\xf6\x10\x12\x6c\xdc\xa0\xbd\x0d\xf1\x36\x77\xd0\x0e\xa3\xc8\xd6\x0c\xda\xdb\x92\xee\xc6\x0d\xda\xdb\x91\xea\x4a\x07\xed\x46\x76\x76\x1d\x83\xf6\x2b\xc4\xba\x2d\x4c\x60\x11\x39\x2c\xe3\x3c\xe6\x71\x36\x59\xe4\x12\xc5\x21\xc4\x72\x30\x87\x10\xc5\xf1\x2c\x62\x11\x67\x93\xcd\x1c\xa2\x98\xc4\x42\x66\x33\x8a\x28\x8e\x21\x9b\x6c\xa2\x98\xfa\x67\xa9\xc5\x03\x57\x73\x58\xcc\x1c\xce\xe3\x7c\xe6\x90\xc9\x28\xa6\xb0\x88\x5c\x16\x11\xc5\x29\xcc\x64\x21\x8b\x39\x96\x45\x64\x93\x39\x50\x5b\x2e\x33\xc9\x66\x1e\xb3\x39\x91\x45\x2c\x1c\xc8\xbb\x8c\x9c\xc1\xb6\x16\x30\x93\xb3\x99\xc7\x42\xce\x26\x8a\x83\x88\xfa\x0f\xb5\x45\xfd\x97\xfa\xfe\xef\x39\xa7\x0d\xf8\xbb\x98\x79\x03\x1e\x44\x71\x30\xa3\x88\x25\xee\xcf\x1a\xb6\x96\x3f\xe8\xcf\xf2\xff\xb9\x9d\x79\x03\x6d\xcc\x24\x8a\x5c\xce\x63\x26\x99\xcc\x19\xe8\xc1\x79\x9c\x43\x14\x8b\x98\xfb\xbf\x44\xb3\xbf\x85\x7e\xbf\xfa\xf3\x2f\x23\x8a\x59\x03\x9f\x9f\xc7\x9c\x81\xfe\x2f\x26\x77\xc0\xc7\x39\x03\x79\xe6\x0d\x78\x39\x7b\x20\xa5\xdf\x8f\x3f\xae\xe7\xb3\x64\x60\x04\x17\x93\x39\xe0\x57\xee\x60\x7f\x16\x33\xea\xff\x10\xdb\xad\x9e\xfc\x7b\xce\xc4\x81\x11\xed\x1f\xe3\x85\x03\x3d\x9b\xc3\x4c\x16\xfc\x4b\xea\x1f\x5e\xcd\x1a\xf0\xfb\xdf\xcb\x67\xfe\xc7\xf2\xfd\xf3\x25\x97\x1c\x8e\x60\x34\xa3\x99\xcd\xa2\x81\x7c\xa3\x38\xfb\x2f\xf1\x19\x35\x90\xbe\x80\xd1\xe4\x30\x7a\xb0\xd6\x45\x8c\xfe\x5b\xd9\xa5\x03\xff\x47\xb1\xe0\x6f\x2d\xcf\xfb\x97\x1e\xfe\x4f\x5d\x29\x9c\x37\xd0\xda\x92\x81\x18\x2d\xe6\x94\xc1\xd9\x3a\x6f\x20\xa2\x8b\x19\x4d\xea\x60\x0d\xff\xda\xc7\xf3\x38\x85\x2c\x16\xb1\x94\xd9\xcc\x1c\x98\xe3\xc9\x83\x65\x16\x0e\x5c\xf5\xc7\x60\xc9\xc0\x28\xf6\xe7\xed\xef\x69\xd6\x40\xff\x8f\x21\x87\x99\xcc\x1e\xbc\xfa\xd7\x32\x23\x89\xfa\xb7\xd9\x77\xc8\xc0\xec\xfb\xcf\x7d\x9c\xf9\x97\xba\x46\xb1\x88\xf3\x38\x9b\xd1\x83\xf3\x70\x6b\x9d\xfd\x3d\x48\x66\x12\x13\x38\x8e\x29\x9c\xc2\x71\x1c\x34\x58\xe7\x69\xcc\x61\x16\x73\x07\xda\xc9\xfd\x73\x9e\x9f\x36\xe8\xfb\x64\x96\x0c\xdc\xcf\x07\x73\xd8\xc0\xdf\x31\x1c\xc1\x98\x81\xbf\x71\x03\xcf\x81\x3f\x9e\x08\x63\xb0\xd0\xd7\x3d\xf0\x06\xfb\x5c\xfe\xc3\xbf\xd0\x42\x30\xd6\x38\xdc\xc0\x1e\xda\xc3\x27\xa0\xff\x89\xb5\x0d\x61\x6c\xcb\x76\x6c\x4f\x38\x3b\x30\x94\x1d\x89\x60\x27\x76\x66\x17\x22\xd9\x95\xdd\xd8\x9d\x61\xec\xc1\x9e\xec\x45\x14\x7b\xb3\x0f\xfb\x12\xcd\x70\xf6\x63\x7f\x62\x18\xc1\x01\x1c\xc8\x48\x0e\x62\x14\xa3\x07\x9f\x4c\x63\x88\x63\x2c\x87\x72\x18\xe3\x38\x9c\x23\x38\x92\x78\x8e\xe2\x68\xc6\x93\xc0\x31\x1c\xcb\x04\x12\x39\x8e\x89\x1c\x4f\x12\x93\x98\xcc\x09\x24\x73\x22\x53\x38\x89\x14\x4e\x66\x2a\xa7\x90\xca\xa9\x4c\xe3\x34\xd2\x38\x9d\x33\x38\x93\x74\xce\x62\x3a\x33\xc8\x60\xa6\x11\xee\xa1\x90\x2b\x78\x8e\x9b\xe9\xe0\x4a\xae\xe3\x5a\xee\xe0\x01\x2a\x8d\x72\x0d\xef\x71\x39\x2b\x8c\x67\x7c\x96\x9b\x80\x22\x5e\xe4\x43\x13\x62\x25\xab\xf8\x89\x6e\x36\x73\x37\x0f\xf1\x0a\xeb\x78\x98\x59\xcc\xa6\x84\x4c\x5e\x63\x0e\x8d\xbc\xca\x1b\x34\xb1\x9e\xd7\xf9\x92\xb9\xbc\x4d\x33\x6f\xf2\x08\x67\xd3\xc5\x0d\xbc\x43\x0b\x1b\xc8\xe2\x6b\xbe\xe1\x6a\xe6\x33\x8f\x73\x58\x40\x36\x0b\xa9\x60\x11\xe7\x92\x33\x30\x4b\x96\x90\xcb\xf9\x2c\xe5\x2b\xf2\xb8\x80\x65\x5c\xc8\x45\xe4\x53\xc7\x5d\x5c\xc2\xc5\x14\x70\x29\x9d\x7c\xcb\x33\x66\x88\xd9\xc6\x84\x99\x6d\xcd\x76\x66\x7b\x7e\x67\x8b\x09\x37\x3b\x98\xa1\x66\x47\xfa\x0c\x26\xc2\xec\x64\x76\x36\xc6\xec\x62\x22\xcd\xae\x66\x37\xb3\xbb\x19\x66\xf6\x30\x7b\x9a\xbd\x4c\x94\xd9\xdb\xec\x43\x0f\xbf\x98\x7d\x4d\xb4\x19\x6e\xf6\x33\xfb\x9b\x18\x33\xc2\x1c\x60\x0e\x34\x23\xcd\x41\x66\x94\x19\x6d\x62\xcd\xc1\xe6\x10\x7e\x65\xa3\x19\x63\xe2\xcc\x58\x73\xa8\x39\xcc\x8c\x33\x87\x9b\x23\xcc\x91\x26\xde\x1c\x65\x8e\x36\xe3\x4d\x82\x39\x86\x4f\xf8\xd4\x1c\x6b\x26\x98\x44\x73\x9c\x99\x68\x8e\x37\x49\x66\x92\x99\x6c\x4e\x30\xc9\xe6\x44\x33\xc5\x9c\x64\x52\xa8\xe1\x51\x73\xb2\x99\x6a\x4e\x31\xa9\xe6\x54\x33\xcd\x9c\x66\xd2\xcc\xe9\xe6\x0c\x7e\xa3\x97\x76\x3e\x33\x67\x9a\x74\x73\x96\x99\x6e\x66\x98\x0c\x33\xd3\xcc\x32\xb3\x4d\xa6\x99\x63\xe6\x9a\xb3\x4d\x96\x99\x67\xe6\x9b\x73\x4c\xb6\x59\x60\x16\x9a\x45\x26\x87\x67\xcd\xb9\xe6\x3c\xb3\xd8\xe4\xf2\x39\x5f\x98\x25\xe6\x7c\xb3\xd4\xe4\x99\x65\xe6\x02\x73\xa1\xc9\x37\x17\x99\x8b\xcd\x25\xa6\xc0\x5c\x6a\x2e\x33\x97\x9b\x42\x73\x85\xb9\xd2\x5c\xc5\x7d\xa6\xc8\x5c\x6d\xae\x31\xd7\x9a\x62\xb3\xdc\x5c\x67\xae\x37\x25\xe6\x06\x73\xa3\x59\x61\x4a\xcd\x4d\xe6\x66\x73\x8b\x29\x33\xb7\x9a\xdb\xcc\xed\xa6\xdc\xdc\x61\x56\x9a\x3b\x4d\x85\xb9\xcb\xdc\x6d\xee\x31\x95\xe6\x5e\x73\x9f\xb9\xdf\x54\x99\x07\xcc\x2a\xf3\xa0\xa9\x36\x0f\x99\x87\xcd\x23\xa6\xc6\x3c\x6a\x1e\x33\x8f\x9b\x5a\xf3\x84\x79\xd2\x3c\x65\xea\xcc\xd3\xe6\x19\xf3\xac\xa9\x37\xcf\x99\xd5\xe6\x79\xb3\xc6\xac\x35\x2f\x98\x17\x4d\x83\x79\xc9\xbc\x6c\xd6\x99\x46\xf3\x8a\x79\xd5\xbc\x66\x9a\xcc\x7a\xf3\xba\x79\xc3\x34\x9b\x37\xcd\x5b\xe6\x6d\xd3\x62\x36\x98\x77\xcc\x46\xd3\x6a\xde\x35\xef\x99\xf7\x4d\x9b\xf9\xc0\x7c\x68\x3e\x32\x9b\xcc\xc7\xe6\x13\xf3\xa9\x69\x37\x9f\x99\xcf\xcd\x17\xa6\xc3\x7c\x69\xbe\x32\x5f\x9b\x4e\xf3\x8d\xf9\xd6\x7c\x67\xba\xcc\xf7\xe6\x07\xf3\xa3\xe9\x36\x3f\x99\xcd\xe6\x67\xd3\x63\x7e\x31\xbf\x9a\xdf\x4c\xaf\xf9\xdd\x6c\x31\x7d\x16\x6b\xac\xb5\xce\x8a\x55\xeb\x59\xdf\x06\x36\x64\x87\xd8\x6d\x6c\x98\xdd\xd6\x6e\x67\xb7\xb7\xe1\x76\x07\x3b\xd4\xee\x68\x23\xec\x4e\x76\x67\xbb\x8b\x8d\xb4\xbb\xda\xdd\xec\xee\x76\x98\xdd\xc3\xee\x69\xf7\xb2\x51\x76\x6f\xbb\x8f\xdd\xd7\x46\xdb\xe1\x76\x3f\xbb\xbf\x8d\xb1\x23\xec\x01\xf6\x40\x3b\xd2\x1e\x64\x47\xd9\xd1\x36\xd6\x1e\x6c\x0f\xb1\x63\x6c\x9c\x1d\x6b\x0f\xb5\x87\xd9\x71\xf6\x70\x7b\x84\x3d\xd2\xc6\xdb\xa3\xec\xd1\x76\xbc\x4d\xb0\xc7\xd8\x63\xed\x04\x9b\x68\x8f\xb3\x13\xed\xf1\x36\xc9\x4e\xb2\x93\xed\x09\x36\xd9\x9e\x68\xa7\xd8\x93\x6c\x8a\x3d\xd9\x4e\xb5\xa7\xd8\x54\x7b\xaa\x9d\x66\x4f\xb3\x69\xf6\x74\x7b\x86\x3d\xd3\xa6\xdb\xb3\xec\x74\x3b\xc3\x66\xd8\x99\x76\x96\x9d\x6d\x33\xed\x1c\x3b\xd7\x9e\x6d\xb3\xec\x3c\x3b\xdf\x9e\x63\xb3\xed\x02\xbb\xd0\x2e\xb2\x39\xf6\x5c\x7b\x9e\x5d\x6c\x73\xed\x12\x7b\xbe\x5d\x6a\xf3\xec\x32\x7b\x81\xbd\xd0\xe6\xdb\x8b\xec\xc5\xf6\x12\x5b\x60\x2f\xb5\x97\xd9\xcb\x6d\xa1\xbd\xc2\x5e\x69\xaf\xb2\x45\xf6\x6a\x7b\x8d\xbd\xd6\x16\xdb\xe5\xf6\x3a\x7b\xbd\x2d\xb1\x37\xd8\x1b\xed\x0a\x5b\x6a\x6f\xb2\x37\xdb\x5b\x6c\x99\xbd\xd5\xde\x66\x6f\xb7\xe5\xf6\x0e\xbb\xd2\xde\x69\x2b\xec\x5d\xf6\x6e\x7b\x8f\xad\xb4\xf7\xda\xfb\xec\xfd\xb6\xca\x3e\x60\x57\xd9\x07\x6d\xb5\x7d\xc8\x3e\x6c\x1f\xb1\x35\xf6\x51\xfb\x98\x7d\xdc\xd6\xda\x27\xec\x93\xf6\x29\x5b\x67\x9f\xb6\xcf\xd0\xca\xc7\xf6\x59\x5b\x6f\x9f\xb3\xab\xed\xf3\x76\x8d\x5d\x6b\x5f\xb0\x2f\xda\x06\xfb\x92\x7d\xd9\xae\xb3\x8d\xf6\x15\xfb\x2a\xef\xd3\xc6\x07\x6c\xe2\x5d\x3e\xb2\xaf\xd9\x26\xbb\xde\xbe\x6e\xdf\xb0\xcd\xf6\x4d\xfb\x96\x7d\xdb\xb6\xd8\x0d\xf6\x1d\xbb\xd1\xb6\xda\x77\xed\x7b\xf6\x7d\xdb\x66\x3f\xb0\x1f\xda\x8f\xec\x26\xfb\xb1\xfd\xc4\x7e\x6a\xdb\xed\x67\xf6\x73\xfb\x85\xed\xb0\x5f\xda\xaf\xec\xd7\xb6\xd3\x7e\x63\xbf\xb5\xdf\xd9\x2e\xfb\xbd\xfd\xc1\xfe\x68\xbb\xed\x4f\x76\xb3\xfd\xd9\xf6\xd8\x5f\xec\xaf\xf6\x37\xdb\x6b\x7f\xb7\x5b\x6c\x9f\xc3\x19\x67\x9d\x73\xe2\xd4\x79\xce\x77\x81\x0b\xb9\x21\x6e\x1b\x17\xe6\xb6\x75\xdb\xb9\xed\x5d\xb8\xdb\xc1\x0d\x75\x3b\xba\x08\xb7\x93\xdb\xd9\xed\xe2\x22\xdd\xae\x6e\x37\xb7\xbb\x1b\xe6\xf6\x70\x7b\xba\xbd\x5c\x94\xdb\xdb\xed\xe3\xf6\x75\xd1\x6e\xb8\xdb\xcf\xed\xef\x62\xdc\x08\x77\x80\x3b\xd0\x8d\x74\x07\xb9\x51\x6e\xb4\x8b\x75\x07\xbb\x43\xdc\x18\x17\xe7\xc6\xba\x43\xdd\x61\x6e\x9c\x3b\xdc\x1d\xe1\x8e\x74\xf1\xee\x28\x77\xb4\x1b\xef\x12\xdc\x31\xee\x58\x37\xc1\x25\xba\xe3\xdc\x44\x77\xbc\x4b\x72\x93\xdc\x64\x77\x82\x4b\x76\x27\xba\x29\xee\x24\x97\xe2\x4e\x76\x53\xdd\x29\x2e\xd5\x9d\xea\xa6\xb9\xd3\x5c\x9a\x3b\xdd\x9d\xe1\xce\x74\xe9\xee\x2c\x37\xdd\xcd\x70\x19\x6e\xa6\x9b\xe5\x66\xbb\x4c\x37\xc7\xcd\x75\x67\xbb\x2c\x37\xcf\xcd\x77\xe7\xb8\x6c\xb7\xc0\x2d\x74\x8b\x5c\x8e\x3b\x97\x2a\x77\x9e\x5b\xec\x72\xdd\x12\x77\xbe\x5b\xea\xf2\xdc\x32\x77\x81\xbb\xd0\xe5\xbb\x8b\xdc\xc5\xee\x12\x57\xe0\x2e\x75\x97\xb9\xcb\x5d\x21\x77\xba\x2b\xdc\x95\xee\x2a\x57\xe4\xae\x76\xd7\xb8\x6b\x5d\xb1\x5b\xee\xae\x73\xd7\xbb\x12\x77\x83\xbb\xd1\xad\x70\xa5\xee\x26\x77\x33\xb7\xb8\x5b\x5c\x99\xbb\x95\xdb\xdd\x6d\xee\x76\x57\xee\xee\x70\x2b\xdd\x9d\xae\xc2\xdd\xe5\xee\x76\xf7\xb8\x4a\x77\xaf\xbb\xcf\xdd\xef\xaa\xdc\x03\x6e\x95\x7b\xd0\x55\xbb\x87\xdc\xc3\xee\x11\x57\xe3\x1e\x75\x8f\xb9\xc7\x5d\xad\x7b\xc2\x3d\xe9\x9e\x72\x75\xee\x69\xf7\x8c\x7b\xd6\xd5\xbb\xe7\xdc\x6a\xf7\xbc\x5b\xe3\xd6\xba\x17\xdc\x8b\xae\xc1\xbd\xe4\x5e\x76\xeb\x5c\xa3\x7b\xc5\xbd\xea\x5e\x73\x4d\x6e\xbd\x7b\xdd\xbd\xe1\x9a\xdd\x9b\xee\x2d\xf7\xb6\x6b\x71\x1b\xdc\x3b\x6e\xa3\x6b\x75\xef\xba\xf7\xdc\xfb\xae\xcd\x7d\xe0\x3e\x74\x1f\xb9\x4d\xee\x63\xf7\x89\xfb\xd4\xb5\xbb\xcf\xdc\xe7\xee\x0b\xd7\xe1\xbe\x74\x5f\xb9\xaf\x5d\xa7\xfb\xc6\x7d\xeb\xbe\x73\x5d\xee\x7b\xf7\x83\xfb\xd1\x75\xbb\x9f\xdc\x66\xf7\xb3\xeb\x71\xbf\xb8\x5f\xdd\x6f\xae\xd7\xfd\xee\xb6\xb8\x3e\x41\x8c\x58\x71\x22\xa2\xe2\x89\x2f\x81\x84\x64\x88\x6c\x23\x61\xb2\xad\x6c\x27\xdb\x4b\xb8\xec\x20\x43\x65\x47\x89\x90\x9d\x64\x67\xd9\x45\x22\x65\x57\xd9\x4d\x76\x97\x61\xb2\x87\xec\x29\x7b\x49\x94\xec\x2d\xfb\xc8\xbe\x12\x2d\xc3\x65\x3f\xd9\x5f\x62\x64\x84\x1c\x20\x07\xca\x48\x39\x48\x46\xc9\x68\x89\x95\x83\xe5\x10\x19\x23\x71\x32\x56\x0e\x95\xc3\x64\x9c\x1c\x2e\x47\xc8\x91\x12\x2f\x47\xc9\xd1\x32\x5e\x12\xe4\x18\x39\x56\x26\x48\xa2\x1c\x27\x13\xe5\x78\x49\x92\x49\x32\x59\x4e\x90\x64\x39\x51\xa6\xc8\x49\x92\x22\x27\xcb\x54\x39\x45\x52\xe5\x54\x99\x26\xa7\x49\x9a\x9c\x2e\x67\xc8\x99\x92\x2e\x67\xc9\x74\x99\x21\x19\x32\x53\x66\xc9\x6c\xc9\x94\x39\x32\x57\xce\x96\x2c\x99\x27\xf3\xe5\x1c\xc9\x96\x05\xb2\x50\x16\x49\x8e\x9c\x2b\xe7\xc9\x62\xc9\x95\x25\x72\xbe\x2c\x95\x3c\x59\x26\x17\xc8\x85\x92\x2f\x17\xc9\xc5\x72\x89\x14\xc8\xa5\x72\x99\x5c\x2e\x85\x72\x85\x5c\x29\x57\x49\x91\x5c\x2d\xd7\xc8\xb5\x52\x2c\xcb\xe5\x3a\xb9\x5e\x4a\xe4\x06\xb9\x51\x56\x48\xa9\xdc\x24\x37\xcb\x2d\x52\x26\xb7\xca\x6d\x72\xbb\x94\xcb\x1d\xb2\x52\xee\x94\x0a\xb9\x4b\xee\x96\x7b\xa4\x52\xee\x95\xfb\xe4\x7e\xa9\x92\x07\x64\x95\x3c\x28\xd5\xf2\x90\x3c\x2c\x8f\x48\x8d\x3c\x2a\x8f\xc9\xe3\x52\x2b\x4f\xc8\x93\xf2\x94\xd4\xc9\xd3\xf2\x8c\x3c\x2b\xf5\xf2\x9c\xac\x96\xe7\x65\x8d\xac\x95\x17\xe4\x45\x69\x90\x97\xe4\x65\x59\x27\x8d\xf2\x8a\xbc\x2a\xaf\x49\x93\xac\x97\xd7\xe5\x0d\x69\x96\x37\xe5\x2d\x79\x5b\x5a\x64\x83\xbc\x23\x1b\xa5\x55\xde\x95\xf7\xe4\x7d\x69\x93\x0f\xe4\x43\xf9\x48\x36\xc9\xc7\xf2\x89\x7c\x2a\xed\xf2\x99\x7c\x2e\x5f\x48\x87\x7c\x29\x5f\xc9\xd7\xd2\x29\xdf\xc8\xb7\xf2\x9d\x74\xc9\xf7\xf2\x83\xfc\x28\xdd\xf2\x93\x6c\x96\x9f\xa5\x47\x7e\x91\x5f\xe5\x37\xe9\x95\xdf\x65\x8b\xf4\x29\x6a\xd4\xaa\x53\x51\x55\x4f\x7d\x0d\x34\xa4\x43\x74\x1b\x0d\xd3\x6d\x75\x3b\xdd\x5e\xc3\x75\x07\x1d\xaa\x3b\x6a\x84\xee\xa4\x3b\xeb\x2e\x1a\xa9\xbb\xea\x6e\xba\xbb\x0e\xd3\x3d\x74\x4f\xdd\x4b\xa3\x74\x6f\xdd\x47\xf7\xd5\x68\x1d\xae\xfb\xe9\xfe\x1a\xa3\x23\xf4\x00\x3d\x50\x47\xea\x41\x3a\x4a\x47\x6b\xac\x1e\xac\x87\xe8\x18\x8d\xd3\xb1\x7a\xa8\x1e\xa6\xe3\xf4\x70\x3d\x42\x8f\xd4\x78\x3d\x4a\x8f\xd6\xf1\x9a\xa0\xc7\xe8\xb1\x3a\x41\x13\xf5\x38\x9d\xa8\xc7\x6b\x92\x4e\xd2\xc9\x7a\x82\x26\xeb\x89\x3a\x45\x4f\xd2\x14\x3d\x59\xa7\xea\x29\x9a\xaa\xa7\xea\x34\x3d\x4d\xd3\xf4\x74\x3d\x43\xcf\xd4\x74\x3d\x4b\xa7\xeb\x0c\xcd\xd0\x99\x3a\x4b\x67\x6b\xa6\xce\xd1\xb9\x7a\xb6\x66\xe9\x3c\x9d\xaf\xe7\x68\xb6\x2e\xd0\x85\xba\x48\x73\xf4\x5c\x3d\x4f\x17\x6b\xae\x2e\xd1\xf3\x75\xa9\xe6\xe9\x32\xbd\x40\x2f\xd4\x7c\xbd\x48\x2f\xd6\x4b\xb4\x40\x2f\xd5\xcb\xf4\x72\x2d\xd4\x2b\xf4\x4a\xbd\x4a\x8b\xf4\x6a\xbd\x46\xaf\xd5\x62\x5d\xae\xd7\xe9\xf5\x5a\xa2\x37\xe8\x8d\xba\x42\x4b\xf5\x26\xbd\x59\x6f\xd1\x32\xbd\x55\x6f\xd3\xdb\xb5\x5c\xef\xd0\x95\x7a\xa7\x56\xe8\x5d\x7a\xb7\xde\xa3\x95\x7a\xaf\xde\xa7\xf7\x6b\x95\x3e\xa0\xab\xf4\x41\xad\xd6\x87\xf4\x61\x7d\x44\x6b\xf4\x51\x7d\x4c\x1f\xd7\x5a\x7d\x42\x9f\xd4\xa7\xb4\x4e\x9f\xd6\x67\xf4\x59\xad\xd7\xe7\x74\xb5\x3e\xaf\x6b\x74\xad\xbe\xa0\x2f\x6a\x83\xbe\xa4\x2f\xeb\x3a\x6d\xd4\x57\xf4\x55\x7d\x4d\x9b\x74\xbd\xbe\xae\x6f\x68\xb3\xbe\xa9\x6f\xe9\xdb\xda\xa2\x1b\xf4\x1d\xdd\xa8\xad\xfa\xae\xbe\xa7\xef\x6b\x9b\x7e\xa0\x1f\xea\x47\xba\x49\x3f\xd6\x4f\xf4\x53\x6d\xd7\xcf\xf4\x73\xfd\x42\x3b\xf4\x4b\xfd\x4a\xbf\xd6\x4e\xfd\x46\xbf\xd5\xef\xb4\x4b\xbf\xd7\x1f\xf4\x47\xed\xd6\x9f\x74\xb3\xfe\xac\x3d\xfa\x8b\xfe\xaa\xbf\x69\xaf\xfe\xae\x5b\xb4\xcf\xc3\x33\x9e\xf5\x9c\x27\x9e\x7a\x9e\xe7\x7b\x81\x17\xf2\x86\x78\xdb\x78\x61\xde\xb6\xde\x76\xde\xf6\x5e\xb8\xb7\x83\x37\xd4\xdb\xd1\x8b\xf0\x76\xf2\x76\xf6\x76\xf1\x22\xbd\x5d\xbd\xdd\xbc\xdd\xbd\x61\xde\x1e\xde\x9e\xde\x5e\x5e\x94\xb7\xb7\xb7\x8f\xb7\xaf\x17\xed\x0d\xf7\xf6\xf3\xf6\xf7\x62\xbc\x11\xde\x01\xde\x81\xde\x48\xef\x20\x6f\x94\x37\xda\x8b\xf5\x0e\xf6\x0e\xf1\xc6\x78\x71\xde\x58\xef\x50\xef\x30\x6f\x9c\x77\xb8\x77\x84\x77\xa4\x17\xef\x1d\xe5\x1d\xed\x8d\xf7\x12\xbc\x63\xbc\x63\xbd\x09\x5e\xa2\x77\x9c\x37\xd1\x3b\xde\x4b\xf2\x26\x79\x93\xbd\x13\xbc\x64\xef\x44\x6f\x8a\x77\x92\x97\xe2\x9d\xec\x4d\xf5\x4e\xf1\x52\xbd\x53\xbd\x69\xde\x69\x5e\x9a\x77\xba\x77\x86\x77\xa6\x97\xee\x9d\xe5\x4d\xf7\x66\x78\x19\xde\x4c\x6f\x96\x37\xdb\xcb\xf4\xe6\x78\x73\xbd\xb3\xbd\x2c\x6f\x9e\x37\xdf\x3b\xc7\xcb\xf6\x16\x78\x0b\xbd\x45\x5e\x8e\x77\xae\x77\x9e\xb7\xd8\xcb\xf5\x96\x78\xe7\x7b\x4b\xbd\x3c\x6f\x99\x77\x81\x77\xa1\x97\xef\x5d\xe4\x5d\xec\x5d\xe2\x15\x78\x97\x7a\x97\x79\x97\x7b\x85\xde\x15\xde\x95\xde\x55\x5e\x91\x77\xb5\x77\x8d\x77\xad\x57\xec\x2d\xf7\xae\xf3\xae\xf7\x4a\xbc\x1b\xbc\x1b\xbd\x15\x5e\xa9\x77\x93\x77\xb3\x77\x8b\x57\xe6\xdd\xea\xdd\xe6\xdd\xee\x95\x7b\x77\x78\x2b\xbd\x3b\xbd\x0a\xef\x2e\xef\x6e\xef\x1e\xaf\xd2\xbb\xd7\xbb\xcf\xbb\xdf\xab\xf2\x1e\xf0\x56\x79\x0f\x7a\xd5\xde\x43\xde\xc3\xde\x23\x5e\x8d\xf7\xa8\xf7\x98\xf7\xb8\x57\xeb\x3d\xe1\x3d\xe9\x3d\xe5\xd5\x79\x4f\x7b\xcf\x78\xcf\x7a\xf5\xde\x73\xde\x6a\xef\x79\x6f\x8d\xb7\xd6\x7b\xc1\x7b\xd1\x6b\xf0\x5e\xf2\x5e\xf6\xd6\x79\x8d\xde\x2b\xde\xab\xde\x6b\x5e\x93\xb7\xde\x7b\xdd\x7b\xc3\x6b\xf6\xde\xf4\xde\xf2\xde\xf6\x5a\xbc\x0d\xde\x3b\xde\x46\xaf\xd5\x7b\xd7\x7b\xcf\x7b\xdf\x6b\xf3\x3e\xf0\x3e\xf4\x3e\xf2\x36\x79\x1f\x7b\x9f\x78\x9f\x7a\xed\xde\x67\xde\xe7\xde\x17\x5e\x87\xf7\xa5\xf7\x95\xf7\xb5\xd7\xe9\x7d\xe3\x7d\xeb\x7d\xe7\x75\x79\xdf\x7b\x3f\x78\x3f\x7a\xdd\xde\x4f\xde\x66\xef\x67\xaf\xc7\xfb\xc5\xfb\xd5\xfb\xcd\xeb\xf5\x7e\xf7\xb6\x78\x7d\x3e\xbe\xf1\xad\xef\x7c\xf1\xd5\xf7\x7c\xdf\x0f\xfc\x90\x3f\xc4\xdf\xc6\x0f\xf3\xb7\xf5\xb7\xf3\xb7\xf7\xc3\xfd\x1d\xfc\xa1\xfe\x8e\x7e\x84\xbf\x93\xbf\xb3\xbf\x8b\x1f\xe9\xef\xea\xef\xe6\xef\xee\x0f\xf3\xf7\xf0\xf7\xf4\xf7\xf2\xa3\xfc\xbd\xfd\x7d\xfc\x7d\xfd\x68\x7f\xb8\xbf\x9f\xbf\xbf\x1f\xe3\x8f\xf0\x0f\xf0\x0f\xf4\x47\xfa\x07\xf9\xa3\xfc\xd1\x7e\xac\x7f\xb0\x7f\x88\x3f\xc6\x8f\xf3\xc7\xfa\x87\xfa\x87\xf9\xe3\xfc\xc3\xfd\x23\xfc\x23\xfd\x78\xff\x28\xff\x68\x7f\xbc\x9f\xe0\x1f\xe3\x1f\xeb\x4f\xf0\x13\xfd\xe3\xfc\x89\xfe\xf1\x7e\x92\x3f\xc9\x9f\xec\x9f\xe0\x27\xfb\x27\xfa\x53\xfc\x93\xfc\x14\xff\x64\x7f\xaa\x7f\x8a\x9f\xea\x9f\xea\x4f\xf3\x4f\xf3\xd3\xfc\xd3\xfd\x33\xfc\x33\xfd\x74\xff\x2c\x7f\xba\x3f\xc3\xcf\xf0\x67\xfa\xb3\xfc\xd9\x7e\xa6\x3f\xc7\x9f\xeb\x9f\xed\x67\xf9\xf3\xfc\xf9\xfe\x39\x7e\xb6\xbf\xc0\x5f\xe8\x2f\xf2\x73\xfc\x73\xfd\xf3\xfc\xc5\x7e\xae\xbf\xc4\x3f\xdf\x5f\xea\xe7\xf9\xcb\xfc\x0b\xfc\x0b\xfd\x7c\xff\x22\xff\x62\xff\x12\xbf\xc0\xbf\xd4\xbf\xcc\xbf\xdc\x2f\xf4\xaf\xf0\xaf\xf4\xaf\xf2\x8b\xfc\xab\xfd\x6b\xfc\x6b\xfd\x62\x7f\xb9\x7f\x9d\x7f\xbd\x5f\xe2\xdf\xe0\xdf\xe8\xaf\xf0\x4b\xfd\x9b\xfc\x9b\xfd\x5b\xfc\x32\xff\x56\xff\x36\xff\x76\xbf\xdc\xbf\xc3\x5f\xe9\xdf\xe9\x57\xf8\x77\xf9\x77\xfb\xf7\xf8\x95\xfe\xbd\xfe\x7d\xfe\xfd\x7e\x95\xff\x80\xbf\xca\x7f\xd0\xaf\xf6\x1f\xf2\x1f\xf6\x1f\xf1\x6b\xfc\x47\xfd\xc7\xfc\xc7\xfd\x5a\xff\x09\xff\x49\xff\x29\xbf\xce\x7f\xda\x7f\xc6\x7f\xd6\xaf\xf7\x9f\xf3\x57\xfb\xcf\xf3\x18\x8f\xfb\x6b\xfc\xb5\xfe\x0b\x3c\xc9\x53\x34\xf8\x2f\x52\xcb\x13\xbc\xe4\x37\x70\x19\x2f\x70\x15\x0f\xfa\x2f\xf9\x2f\xfb\xeb\xfc\x46\xff\x15\xff\x55\x5e\xf6\x5f\xf3\x9b\xfc\xf5\xac\xe6\x79\xff\x75\xff\x0d\xea\xfd\x66\xff\x4d\xff\x2d\xff\x6d\xbf\xc5\xdf\xe0\xbf\xe3\x6f\xf4\x5b\xfd\x77\xfd\xf7\xfc\xf7\xfd\x36\xff\x03\xff\x43\xff\x23\x7f\x93\xff\xb1\xff\x89\xff\xa9\xdf\xee\x7f\xe6\x7f\xee\x7f\xc1\xcf\x7e\x87\xff\xa5\xff\x95\xff\xb5\xdf\xe9\x7f\xe3\x7f\xeb\x7f\xe7\x77\xf9\xdf\xfb\x3f\xf8\x3f\xfa\xdd\xfe\x4f\xfe\x66\xff\x67\xbf\xc7\xff\xc5\xff\xd5\xff\xcd\xef\xf5\x7f\xf7\xb7\xf8\x7d\x14\x07\x04\x26\xb0\x81\x0b\x24\xd0\xc0\x0b\xfc\x20\x08\x42\xc1\x90\x60\x9b\x20\x2c\xd8\x36\xd8\x2e\xd8\x3e\x08\x0f\x76\xa0\x2c\x18\xca\x6d\xdc\xca\x77\xc1\x8e\x41\x04\xf7\x72\x63\xb0\x53\xb0\x33\xe5\xdc\xcf\xf5\xc1\x2e\x94\x72\x53\x10\x19\xec\x1a\xec\x16\xec\x1e\x0c\x0b\xf6\x08\xf6\x0c\xf6\x0a\xa2\x82\xbd\x83\x7d\x82\x7d\x83\xe8\x60\x78\xb0\x5f\xb0\x7f\x10\x13\x8c\x08\x0e\x08\x0e\x0c\x46\x06\x07\x05\xa3\x82\xd1\x41\x6c\x70\x70\x70\x48\x30\x26\x88\x0b\xc6\x06\x87\x06\x87\x05\xe3\x82\xc3\x83\x23\x82\x23\x83\xf8\xe0\xa8\xe0\xe8\x60\x7c\x90\x10\x1c\x13\x1c\x1b\x4c\x08\x12\x83\xe3\x82\x89\xc1\xf1\x41\x52\x30\x29\x98\x1c\x9c\x10\x24\x07\x27\x06\x53\x82\x93\x82\x94\xe0\xe4\x60\x6a\x70\x4a\x90\xca\xd3\xc1\xa9\xc1\xb4\xe0\xb4\x20\x2d\x38\x3d\x38\x23\x38\x33\x48\x0f\xce\x0a\xa6\x07\x33\x82\x8c\x60\x66\x30\x2b\x98\x1d\x64\x06\x73\x82\xb9\xc1\xd9\x41\x56\x30\x2f\x98\x1f\x9c\x13\x64\x07\x0b\x82\x85\xc1\xa2\x20\x27\x38\x37\x38\x2f\x58\x1c\xe4\x06\x4b\x82\xf3\x83\xa5\x41\x5e\xb0\x2c\xb8\x20\xb8\x30\xc8\x0f\x2e\x0a\x2e\x0e\x2e\x09\x0a\x82\x4b\x83\xcb\x82\xcb\x83\xc2\xe0\x8a\xe0\xca\xe0\xaa\xa0\x28\xb8\x3a\xb8\x26\xb8\x36\x28\x0e\x96\x07\xd7\x05\xd7\x07\x25\xc1\x0d\xc1\x8d\xc1\x8a\xa0\x34\xb8\x29\xb8\x39\xb8\x25\x28\x0b\x6e\x0d\x6e\x0b\x6e\x0f\xca\x83\x3b\x82\x95\xc1\x9d\x41\x45\x70\x57\x70\x77\x70\x4f\x50\x19\xdc\x1b\xdc\x17\xdc\x1f\x54\x05\x0f\x04\xab\x82\x07\x83\xea\xe0\xa1\xe0\xe1\xe0\x91\xa0\x26\x78\x34\x78\x2c\x78\x3c\xa8\x0d\x9e\x08\x9e\x0c\x9e\x0a\xea\x82\xa7\x83\x67\x82\x67\x83\xfa\xe0\xb9\x60\x75\xf0\x7c\xb0\x26\x58\x1b\xbc\x10\xbc\x18\x34\x04\x2f\x05\x2f\x07\xeb\x82\xc6\xe0\x95\xe0\xd5\xe0\xb5\xa0\x29\x58\x1f\xbc\x1e\xbc\x11\x34\x07\x6f\x06\x6f\x05\x6f\x07\x2d\xc1\x86\xe0\x9d\x60\x63\xd0\x1a\xbc\x1b\xbc\x17\xbc\x1f\xb4\x05\x1f\x04\x1f\x06\x1f\x05\x9b\x82\x8f\x83\x4f\x82\x4f\x83\xf6\xe0\xb3\xe0\xf3\xe0\x8b\xa0\x23\xf8\x32\xf8\x2a\xf8\x3a\xe8\x0c\xbe\x09\xbe\x0d\xbe\x0b\xba\x82\xef\x83\x1f\x82\x1f\x83\xee\xe0\xa7\x60\x73\xf0\x73\xd0\x13\xfc\x12\xfc\x1a\xfc\x16\xf4\x06\xbf\x07\x5b\x82\xbe\x10\x21\x13\xb2\x21\x17\x92\x90\x86\xbc\x90\x1f\x0a\x42\xa1\xd0\x90\xd0\x36\xa1\xb0\xd0\xb6\xa1\xed\x42\xdb\x87\xc2\x43\x3b\x84\x86\x86\x76\x0c\x45\x84\x76\x0a\xed\x1c\xda\x25\x14\x19\xda\x35\xb4\x5b\x68\xf7\xd0\xb0\xd0\x1e\xa1\x3d\x43\x7b\x85\xa2\x42\x7b\x87\xf6\x09\xed\x1b\x8a\x0e\x0d\x0f\xed\x17\xda\x3f\x14\x13\x1a\x11\x3a\x20\x74\x60\x68\x64\xe8\xa0\xd0\xa8\xd0\xe8\x50\x6c\xe8\xe0\xd0\x21\xa1\x31\xa1\xb8\xd0\xd8\xd0\xa1\xa1\xc3\x42\xe3\x42\x87\x87\x8e\x08\x1d\x19\x8a\x0f\x1d\x15\x3a\x3a\x34\x3e\x94\x10\x3a\x26\x74\x6c\x68\x42\x28\x31\x74\x5c\x68\x62\xe8\xf8\x50\x52\x68\x52\x68\x72\xe8\x84\x50\x72\xe8\xc4\xd0\x94\xd0\x49\xa1\x94\xd0\xc9\xa1\xa9\xa1\x53\x42\xa9\xa1\x53\x43\xd3\x42\xa7\xfd\x7f\x8c\x9b\x5d\x93\xdb\x46\x76\xb0\x65\xcd\x0c\x47\x1c\x8d\xd6\xfb\x56\xf9\xea\xad\x7d\xab\xb4\xb5\x6f\xe5\x22\xaa\x4a\x11\xdd\x8d\xaf\x4b\x12\x38\xc7\xd6\xda\xb1\x1c\xdb\x2a\x5b\xce\x26\x1b\x0c\x09\x0d\xb9\xe2\x10\xb3\xfc\x90\xec\xbd\x49\x6e\x72\x99\xfc\x16\xad\xae\x52\xb9\xcb\x8f\xc8\x5f\xc8\xdf\xd8\x14\x89\x07\x3d\x1c\x16\x06\x1e\x5f\xf8\x34\xd8\x40\x3f\xa7\x41\x02\xcf\xe9\xb6\xa7\xff\x7d\xff\x55\xff\x87\xfe\xdf\xf7\x7f\xd7\xff\x87\xfe\x3f\xf6\x7f\xdf\xff\xa7\x7e\xd1\xbf\xe8\x8f\xfb\x93\x7e\xd9\x7f\xdd\xbf\xec\x4f\xfb\xb3\xfe\x1f\xfa\x6f\xfa\xf3\xfe\x55\x7f\xd1\xaf\xfa\xd7\xfd\x3f\xf6\x97\xfd\x55\x7f\xdd\xdf\xf4\xdf\xf6\x2e\xe7\x3f\x5d\x4f\x83\xd3\xcd\x62\x36\x18\x0c\xf2\x3a\x0e\x07\x44\x8e\x47\x86\x68\x89\x21\x31\x3d\x1d\x5e\x15\xe3\x65\xb5\x38\x2d\xea\xd8\x1b\x5e\x2c\xcb\xb7\x65\xaf\xd8\x85\xd3\x61\x75\x59\x2d\xca\x37\xa7\x45\x1d\x1f\x67\xe3\xd9\x72\xbc\xb9\x7a\x3d\x2f\x7f\x7c\x3c\xbe\x69\x9f\x65\x93\x6a\x5d\x8c\xc7\xe5\x62\x7d\x36\xf6\xcd\x5e\x3e\x2e\xb6\x43\x4e\xea\x90\x8f\x97\x55\xb1\x3e\x15\x80\x25\x40\xa9\x81\xe5\x2e\x9c\xc9\xcd\x40\xa5\x6f\x9e\x0a\x69\x94\x75\xec\x49\x3d\x62\xb9\x0b\x8f\x3f\xdd\x4b\xea\x72\x2f\xa9\x4f\x6f\xc6\xba\xf4\xcd\xf3\x4f\xc7\xd5\xd5\x55\xc1\xc1\xe5\xde\xc1\xe3\xcf\xf6\xc6\x99\xde\xb4\x8f\x3f\xbb\x28\x96\xc7\xd3\x8b\x62\xd9\x7b\xbe\x9e\xcd\x27\x65\x6f\xb6\x0b\xa7\xcf\x99\xc9\x8c\x99\x3c\xaf\x67\x32\xab\x6f\xdd\x73\x72\x9e\xd5\xf1\xe1\xf3\xdf\x3e\x9c\xfd\xe1\xf1\x6f\xf7\x18\x7f\xb8\x69\x9f\x7f\xbe\x9f\xd5\x9b\x5b\x07\x97\xcb\xb2\x5c\xcc\x8b\xc5\x64\x36\xee\x7d\x51\x8c\x37\xeb\xb2\x37\xdf\x85\xf3\x2f\xf6\xcf\x9b\xef\x1d\xf4\xbe\xa8\x6f\xd0\x7c\x17\x8e\xbf\x98\x54\xeb\xe3\xf9\xa4\x5a\xf7\xbe\xac\xaf\x5f\xd4\xd7\x7f\xb9\x7f\xfd\x62\xff\xfa\x2f\xeb\xeb\x17\xf5\x0d\x5e\x14\xd7\xd5\x6a\xbd\xac\xae\xa7\xe5\x91\x2c\x2e\x8f\xca\xc5\xe5\xe9\x0b\x26\x5f\x31\xf9\x17\xf5\xe4\xab\x5d\x78\xf2\x62\xba\x59\x5c\x16\xcb\xcd\xd5\xbc\xd8\xac\x9f\x54\xfb\x47\xbd\xaf\xeb\x1c\x96\x75\x0e\x5f\xef\xe7\xb0\xdc\xcf\xe1\xeb\x3a\x87\x65\x1d\xbe\xa9\xaf\x5a\xed\xc2\xe3\x6f\xf6\x6e\xe3\x6a\xef\x36\x7e\xbb\x3f\xda\x7a\x7f\xb4\x6f\xeb\x61\xd6\xf5\x1d\xf9\x76\xfb\x95\xae\xb7\x5f\xe9\xcb\xfa\x2b\xdd\xd4\x5f\xe9\x4b\x66\xb5\x61\x56\x2f\xeb\x59\x6d\x76\xe1\xe4\xe5\x72\xb6\xb8\x3c\xd9\x6c\xff\xfd\xe4\xe5\xad\x19\x6e\xf6\x8f\x4e\x5f\xf2\xd5\x6f\x78\x6a\xbe\xdb\xcb\xf6\xdd\x5e\xfb\xd5\x5e\xfb\xa7\x9b\x76\xef\x87\x7a\xae\x7f\xda\x85\xb3\x1f\x6e\x7e\xc6\x7f\xf2\xcd\x93\x79\xb5\xb8\x5c\xed\x9e\xe2\x20\x19\x10\x03\xa2\x21\x5a\xa2\x23\x86\xc4\x88\x18\x13\x13\x62\x4a\x1c\x12\x47\xc4\x8c\x98\x13\x85\xa8\x75\x4c\xe1\xa7\xf0\x53\xb8\x29\xdc\x14\x6e\x0a\x37\x85\x9b\xc2\x4d\xe1\xa6\x70\x53\xb8\x29\xdc\x14\x6e\x0a\x37\xd5\x93\x17\xd3\x6a\xb9\x38\xa9\xb6\xff\xae\x3f\x1b\x32\xe7\x21\xec\x21\xec\x21\xec\x21\xec\x21\xec\x21\xec\x21\xec\x21\xec\x21\xec\x21\x6c\xde\xa0\xc1\x50\x4e\x5e\xee\x98\x9b\x1b\xe6\x88\xf9\xf2\x76\x0d\x78\xbb\x06\x23\xd8\xbc\x65\x83\x11\xec\x11\xec\x11\xec\x11\xec\x11\xec\x11\xec\x11\xec\x11\xec\x11\xf3\x1e\x71\xbf\x33\xee\x77\x06\x3f\x83\x9f\xc1\xcf\xe0\x67\xf0\x33\xf8\x19\xfc\x0c\x7e\x06\x3f\x83\x9f\xc1\xcf\xe0\x67\xf0\x33\xf8\x19\xfc\x1c\x7e\x0e\x3f\x87\x9f\xc3\xcf\xe1\xe7\xf0\x73\xf8\x39\xfc\x1c\x7e\x0e\x3f\x87\x9f\xc3\xcf\xe1\xe7\xf0\x73\xf8\x39\x7c\x81\x2f\xf0\x05\xbe\xc0\x17\xf8\x12\xf6\x3e\xad\x9f\xfa\xcb\x5d\xe0\x53\xe8\x02\x5d\xa0\x0b\x74\x81\x2e\xd0\x05\xba\x40\x57\xe8\x0a\x5d\xa1\x2b\x74\x85\xae\xcc\x5e\x99\xbd\x32\x7b\x85\xaf\xe9\xd9\x70\xfb\x26\xa9\x1f\xf2\xc2\x37\x4f\x87\x52\xc7\xa2\xac\xdf\x75\x2f\x56\xf3\x62\x35\xad\xdb\xd5\x4d\x7b\x37\x8a\x19\x0c\x88\x01\xd1\x10\x2d\xd1\x11\x43\x62\x44\x8c\x89\x09\x31\x25\x0e\x89\x23\x62\x46\xcc\x89\x42\xac\xef\x86\x09\xe0\x07\xf0\x03\xf8\x01\xfc\x00\x7e\x00\x3f\x80\x1f\xc4\xe7\xdf\xec\xbf\xab\x57\x7b\x07\x9c\x41\x26\x01\x99\x04\x64\x12\x90\x49\x40\x26\x01\x99\x18\x32\x31\x64\x62\xc8\xc4\x90\x89\x21\x13\x43\x26\x86\x4c\x0c\x77\xc2\x70\x27\x0c\x77\xc2\xc0\x37\xf0\x0d\x7c\x03\xdf\xc0\x37\xf0\x2d\x7c\x0b\xdf\xc2\xb7\xf0\x2d\x7c\x0b\xdf\xc2\xb7\xf0\x2d\x7c\x0b\xdf\xc2\xb7\xf0\x2d\x7c\x0b\xdf\xc2\xb7\xf0\x1d\x7c\x07\xdf\xc1\x77\xf0\x1d\x7c\x07\xdf\xc1\x77\xf0\x1d\x7c\x07\xdf\xc1\x77\xf0\x1d\x7c\x07\xdf\xc1\x77\xf0\x43\xf8\x21\xfc\x10\x7e\x08\x3f\x84\x1f\xc2\x0f\xe1\x87\xf0\x43\xf8\x21\xfc\x10\x7e\x08\x3f\x84\x1f\xc2\x0f\xe1\x87\xf0\x23\xf8\x11\xfc\x08\x7e\x04\x3f\x82\x1f\xc1\x8f\xe0\x47\xf0\x23\xf8\x11\xfc\x08\x7e\x04\x3f\x82\x1f\xc1\x8f\xe0\x47\xf0\x63\xf8\x31\xfc\x18\x7e\x0c\x3f\x86\x1f\xc3\x8f\xe1\xc7\xf0\x63\xf8\x31\xfc\x18\x7e\x0c\x3f\x86\x1f\xc3\x8f\xe1\xc7\xf0\xa9\x02\x0c\x55\x80\xa1\x0a\x30\x54\x01\x86\x2a\xc0\x50\x05\x18\xaa\x00\x43\x15\x60\xa8\x02\x0c\x55\x80\xa1\x0a\x30\x54\x01\x86\x2a\xc0\x50\x05\x18\xaa\x00\x43\x15\x60\xa8\x02\x0c\x55\x80\x49\xe1\x53\x0d\x18\xaa\x01\x43\x35\x60\xa8\x06\x0c\xd5\x80\xa1\x1a\x30\x54\x03\x86\x6a\xc0\x50\x0d\x18\xaa\x01\x43\x35\x60\xa8\x06\x4c\x0a\x9f\x35\x8f\x19\xc2\xa7\x22\x30\x54\x04\x86\x8a\xc0\x50\x11\x18\x2a\x02\x43\x45\x60\xa8\x08\x0c\x15\x81\xa1\x22\x30\x54\x04\x86\x8a\xc0\x50\x11\x98\x21\xfc\x21\xfc\x11\x7c\xaa\x02\x43\x55\x60\xa8\x0a\x0c\x55\x81\xa1\x2a\x30\x54\x05\x86\xaa\xc0\x50\x15\x18\xaa\x02\x43\x55\x60\x46\xa3\x7e\xf1\x7a\x36\x0b\xe3\xd4\xa4\xbb\x56\xe4\xd2\xe6\x9d\x41\x65\x60\xa8\x0c\x0c\x95\x81\xa1\x32\x30\x54\x06\x86\xca\xc0\x50\x19\x18\x2a\x03\x43\x25\x60\xa8\x04\x0c\x95\x80\xa1\x12\x30\x54\x02\x86\x4a\xc0\x50\x09\x18\x2a\x01\x43\x25\x60\xa8\x04\x0c\x95\x80\xa1\x12\x30\x54\x02\x86\x4a\xc0\x50\x09\x18\x2a\x01\x83\xd9\x0d\x66\x37\x98\xdd\x60\x76\x83\xd9\x0d\x66\x37\x98\xdd\x08\xe3\x09\xe3\x09\xe3\xe1\x76\x83\xdb\x0d\x6e\x37\xb8\xdd\xe0\x76\x83\xdb\x0d\x6e\x37\xb8\xdd\xe0\x76\x83\xdb\x0d\x6e\x37\xb8\xdd\xe0\x76\x83\xdb\x0d\x6e\x37\xb8\xdd\xe0\x76\xa3\xf0\x15\xbe\xc2\x57\xf8\x0a\x5f\xe1\xab\xf6\x2f\x97\xc5\xdb\x72\x5c\x5d\x5d\xf4\x77\x76\xdf\xb6\x76\x7d\x76\x60\xfa\xbb\xb5\xc9\xde\x27\x8e\x18\x12\x23\x62\x4c\x4c\x9e\x4c\xab\xea\x4d\x71\x51\xbd\xdd\xbf\x6a\x48\x1c\x11\x33\x62\x4e\x14\x62\x7d\x2f\x2c\x66\xb7\x98\xdd\x62\x76\x8b\xd9\x2d\x66\xb7\x98\xdd\x62\x76\x1b\x90\x45\x90\x10\x53\x22\x7c\x7c\x6e\xf1\xb9\xc5\xe7\x16\x9f\x5b\x7c\x6e\xf1\xb9\xc5\xe7\xd6\x98\xf3\x49\xb5\xbe\x28\xe7\xd5\xbb\x9b\x49\x21\x75\x8b\xd4\x2d\x52\xb7\x48\xdd\x22\x75\x8b\xd4\x2d\x52\xb7\x48\xdd\x22\x75\x8b\xd4\x2d\x52\xb7\x48\xdd\x22\x75\x8b\xd4\x2d\x52\xb7\x48\xdd\x22\x75\x8b\xd4\x2d\x52\xb7\x3c\xa0\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\x69\x5b\xa4\x6d\x91\xb2\x45\xca\x16\x29\x5b\xa4\x6c\x63\x39\x59\x57\x8b\x6a\xf5\x64\x32\x2b\x97\xe5\x6a\xb6\xda\x1d\x9d\x0d\xe7\xd7\xd3\x62\xd7\xec\x17\x8b\x6a\x5d\xce\xcb\x59\x71\x2e\xd7\xab\xd9\xbc\x5a\xec\x3e\x7e\x24\x6b\xfa\x9f\x57\xb4\xce\x5f\x5c\xcd\xc6\x4b\xfa\xcf\x5f\xee\x9d\x7c\xf6\xe2\xaa\xbc\xac\x4f\xfa\x3f\xb3\x6a\x5d\xdc\x62\x9d\xec\x58\xc7\xa3\x72\x5d\x9c\x7c\x5a\x5c\x5d\x15\xa7\x70\x8e\x7f\x28\xd7\xc5\x91\xac\x8b\x93\x6f\xa7\xe5\xba\x38\xde\x82\x4e\x3e\x2f\xae\xaf\x8b\xde\x17\xc5\xd5\xc5\xa4\x78\xf8\xb7\x9b\x87\x5f\x6e\x1e\x7e\x3f\x3b\x85\xfc\xf0\xab\xd9\xd1\xd7\xd3\xea\xe4\x9b\xd9\xe5\x55\x71\xf4\x6d\xb1\x39\x25\x8b\xa3\xaf\xa6\xb3\xa3\x6c\x3a\x3b\xfa\x6a\x35\x3b\x7f\xbe\x97\xc1\xc7\x9c\xd0\x1c\x9f\x15\x7e\xe2\xe7\xe5\xfe\x74\xcb\x66\xba\xb3\x66\xba\x9f\x6c\x6e\x5f\x5a\x4f\x66\x77\xfd\xf1\xc5\x76\x32\x97\xdb\xc9\x9c\x4c\xca\xf9\xba\x38\x65\xac\xe3\x3f\x6d\xa7\xb4\xed\x5c\xef\xa6\xb4\x1d\xec\xe4\xcd\x6e\x4a\xf3\x7a\x4a\x8b\xcd\xc3\x1f\x67\xa7\x55\x3d\x9f\xa3\xe5\xb4\xea\xad\xb6\x93\x09\x4e\x76\xe1\x68\x5d\x6c\x4e\xe1\x1e\x5d\x4f\x67\x47\xe3\xe9\xec\xe8\x7a\x35\x3b\xa9\xb6\x37\xf8\x7c\xff\xde\x7e\x7c\x90\xde\x79\xb5\xff\xed\x6c\xf6\xbf\x9d\xca\x7f\x3b\xf5\x6f\x22\x1f\xf4\x76\xe9\x05\x8f\xb8\x3b\xfc\x96\x91\xa4\xcd\xdd\xf1\xf5\x74\x16\xf4\x76\xd7\x35\x7d\xfc\x7e\x59\x2a\x5b\x96\xca\x96\xa5\xb2\x65\xa9\x6c\x59\x2a\x5b\x96\xca\x16\xa1\x5a\x84\x6a\x11\xaa\x45\xa8\x16\xa1\x5a\x84\x6a\x11\xaa\x45\xa8\x16\xa1\x5a\x84\x6a\x11\xaa\x45\xa8\x16\xa1\x5a\x84\x6a\x11\xaa\x45\xa8\x16\xa1\x5a\x84\x6a\x11\xaa\x45\xa8\x16\xa1\x5a\x84\x6a\x11\xaa\x45\xa8\x16\xa1\x5a\x84\x6a\x11\xaa\x45\xa8\x16\xa1\x5a\x84\x6a\x11\xaa\x45\xa8\x16\xa1\x5a\xad\xf9\x6e\x30\xd8\x95\x4c\xc1\x60\x60\x6c\xd3\x0a\x03\xdf\x32\xbe\x75\xd3\xeb\x7c\x2b\xf4\xad\xc8\xb7\x62\xdf\x4a\x7c\x2b\x6d\x5a\x91\xa7\xf1\xbe\x72\x83\xdc\x7f\xd2\xb0\x02\xe7\xc7\x0d\xfc\x68\x81\x1f\x2d\xf0\xa3\x99\x9b\xdc\x7d\xc6\xc6\x67\x6c\x7c\x9e\xc6\x8f\x67\x7c\x9e\xc6\x8f\x6c\xfc\xc8\xc6\x8f\x6c\xfd\xc8\xd6\x8f\x6c\xfd\xc8\xd6\xdf\x0b\xeb\x19\xd6\x33\xac\x67\x58\xcf\xb0\x9e\x61\x3d\xc3\x79\x86\xf3\x0c\xe7\x19\xce\x33\x9c\x67\xdc\xdc\x17\xe7\x19\xce\x33\x9c\x67\xb8\x9b\xfb\xed\xaf\x88\xfc\x15\x91\xbf\x22\xf2\x57\x44\xfe\x8a\xd8\x67\x15\xfb\x5c\x62\x9f\x4b\xec\x73\x89\xfd\xc8\xb1\x1f\x39\xf6\x23\xc7\x7e\xe4\xd8\x8f\x9c\xf8\x91\x13\x3f\xdf\xc4\x33\x12\xcf\x48\x3c\x23\xf1\x8c\xc4\x33\x12\xcf\x48\x3c\x23\xf1\x8c\xd4\x33\x52\xcf\x48\x3d\x23\xf5\x8c\xd4\x33\x52\xcf\x48\x3d\x83\x05\x97\x0b\x6f\xee\xc5\xcd\x68\x0d\x2b\xf0\x4f\x4e\x30\x08\x7c\xcb\xff\x86\x07\xd6\xb7\x9c\x6f\x85\xbe\x15\xf9\x56\xec\x5b\x89\x6f\xa5\xf0\x9b\x67\x23\x08\x3c\x8b\xc5\xa2\xc3\xfb\x2e\xf2\x6c\xff\x9b\x68\xb6\x95\x5d\xd4\xc4\x90\x18\x11\x99\x1f\xee\x77\xb8\xdf\xe1\x7e\x87\xfb\x1d\xee\x77\xb8\xdf\xe1\x7e\x87\xfb\x1d\x0b\x7a\x17\xdf\xe4\xe0\x67\xe3\xef\x6b\xe0\x7f\x97\xcd\xf6\xb6\x8b\x9b\x48\x1e\x2c\xec\x1d\x0b\x7b\x47\x0d\xe1\xa8\x21\x1c\x35\x84\xa3\x86\x70\x2c\xec\x1d\x0b\x7b\xc7\xc2\xde\xb1\xb0\x77\x2c\xec\x1d\x0b\x7b\xc7\xc2\xde\xb1\xb0\x77\x2c\xec\x1d\x0b\x7b\xc7\xc2\xde\xb1\xb0\x77\x2c\xec\x1d\x0b\x7b\xc7\xc2\xde\xb1\xb0\x77\x2c\xec\x5d\xa2\xfe\x0d\x77\xf3\xbb\x63\x2c\x16\xf7\xae\xf9\xbe\x9a\xef\x84\xc5\xbd\x6b\xee\x45\xf3\x5b\xf3\xd7\x91\x03\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\x96\xbf\x63\xcb\xdf\xb1\xe5\xef\x58\xd8\x3b\x16\xf6\x8e\x85\xbd\x63\x61\xef\x58\xd8\x3b\x16\xf6\x8e\x85\xbd\x63\x61\xef\xd8\xf2\x77\x6c\xf9\x3b\x16\xfa\x8e\x85\xbe\x63\xa1\xef\x58\xe8\x3b\x16\xfa\x8e\x85\xbe\x63\xa1\xef\x58\xe8\x3b\x16\xfa\x8e\x85\xbe\x63\xa1\xef\xa8\x61\x1c\x0b\x7d\xc7\x42\xdf\xb1\xd0\x77\xd4\x31\x2e\x6f\x9e\x92\xc4\x35\x3d\x64\x40\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x8e\x4a\xc6\x51\xc9\x38\x2a\x19\x47\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x8e\x4a\xc6\x51\xc9\x38\x2a\x19\x47\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x8e\x4a\xc6\x51\xc9\x38\x2a\x19\x47\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x8e\x4a\xc6\x51\xc9\x38\x2a\x19\x47\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x21\x1b\xfd\x21\x1b\xfd\x21\x1b\xfd\x21\x1b\xfd\x21\x9b\x02\x21\x9b\x02\x21\x9b\x02\x21\x9b\x02\x21\x1b\xfd\x21\x6f\xdf\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\x80\x90\xed\xfd\x90\xed\xfd\x90\x9d\x80\x90\x9d\x80\x90\x9d\x80\xb0\xde\x09\x08\xf2\xfa\xfe\x05\x79\x7d\xff\x82\xbc\xbe\x7f\x41\x5e\xdf\xbf\x20\xaf\xef\x5f\x90\xd7\xf7\x2f\xc8\xeb\xfb\x17\xe4\x83\xe6\xfa\x84\x98\x12\x87\xc4\x11\x31\x23\xe6\x44\x21\x6a\x1d\x03\xf8\x01\xfc\x00\x7e\x00\x3f\x80\x1f\xc0\x0f\xe0\x07\xf0\x03\xf8\x01\xfc\x00\x7e\x00\x3f\x80\x1f\xc0\x0f\xe0\x07\xf0\x0d\x7c\x03\xdf\xc0\x37\xf0\x0d\x7c\x03\xdf\xc0\x6f\xee\x9f\x81\x6f\xe0\x1b\xf8\x06\xbe\x81\x6f\xe0\x1b\xf8\x06\xbe\x85\x6f\xe1\x5b\xf8\x16\xbe\x85\x6f\xe1\x5b\xf8\x16\xbe\x85\x6f\xe1\x5b\xf8\x16\xbe\x85\x6f\xe1\x5b\xf8\x16\xbe\x83\xef\xe0\x3b\xf8\x0e\xbe\x83\xef\xe0\x3b\xf8\x0e\xbe\x83\xef\xe0\x3b\xf8\x0e\xbe\x83\xef\xe0\x3b\xf8\x0e\x7e\x08\x3f\x84\x1f\xc2\x0f\xe1\x87\xf0\x43\xf8\x21\xfc\x10\x7e\x08\x3f\x84\x1f\xc2\x0f\xe1\x87\xf0\x43\xf8\x21\xfc\x10\x7e\x04\x3f\x82\x1f\xc1\x8f\xe0\x47\xf0\x23\xf8\x11\xfc\x08\x7e\x04\x3f\x82\x1f\xc1\x8f\xe0\x47\xf0\x23\xf8\x11\xfc\x08\x7e\x0c\x3f\x86\x1f\xc3\x8f\xe1\xc7\xf0\x63\xf8\x31\xfc\x18\x7e\x0c\x3f\x86\x1f\xc3\x8f\xe1\xc7\xf0\x63\xf8\x31\xfc\x18\x7e\x02\x3f\x81\x9f\xc0\x4f\xe0\x27\xf0\x13\xf8\x09\xfc\x04\x7e\x02\x3f\x81\x9f\xc0\x4f\xe0\x27\xf0\x13\xf8\x09\xfc\x04\x7e\x0a\x3f\x85\x9f\xc2\x4f\xe1\xa7\xf0\x53\xf8\x29\xfc\x14\x7e\x0a\x3f\x85\x9f\xc2\x4f\xe1\xa7\xf0\x53\xf8\x29\xfc\x14\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x10\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\xfe\x08\x7e\x06\x3f\x83\x9f\xc1\xcf\xe0\x67\xf0\x33\xf8\x19\xfc\x0c\x7e\x06\x3f\x83\x9f\xc1\x57\x38\xb5\xa7\x03\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xc4\xda\xfb\x6e\xf7\xdf\xf0\x7a\xef\xea\xf0\x5d\xfd\x3f\xf1\xbd\xdb\x85\xfe\x77\xcd\xc6\x71\xff\x5d\xd3\xaa\xaf\xc3\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8c\xe0\x19\xc1\x33\x82\x67\x04\xcf\x08\x9e\x11\x3c\x23\x78\x46\xf0\x8a\xe0\x13\xc1\x27\x82\x4f\x04\x9f\x08\x3e\x11\x7c\x22\xf8\x44\xf0\x89\xe0\x13\xc1\x27\x82\x4f\x04\x9f\x08\x3e\x11\x7c\x22\xc3\x86\xcb\x3c\xf1\x89\xe0\x13\xc1\x27\x82\x4f\x04\x9f\x08\x3e\x11\x7c\x22\xf8\x44\xf0\x89\xe0\x13\xc1\x27\x82\x4f\x04\x9f\x08\x3e\x11\x7c\x22\xf8\x44\xf0\x89\xe0\x13\xc1\x27\x82\x4f\x04\x9f\x08\x3e\x11\x7c\x22\xf8\x44\xf0\x89\xe0\x13\xc1\x27\x92\xc1\xcf\xe0\x67\xf0\x33\xf8\x19\xfc\x1c\x7e\x0e\x3f\x87\x9f\xc3\xcf\xe1\xe7\xf0\x73\xf8\x39\xfc\x1c\x7e\x0e\x3f\x87\x9f\xc3\xcf\xe1\xe7\xf0\x73\xf8\x39\x7c\x81\x2f\xf0\x05\xbe\xc0\x17\xf8\x02\x5f\xe0\x0b\x7c\x81\x2f\xf0\x05\xbe\xc0\x17\xf8\x02\x5f\xe0\x0b\x7c\x85\xaf\x41\xef\x55\xfd\xc0\xfd\xb4\x0b\x7c\x0a\x5d\xa1\x2b\x74\x85\xae\xd0\xeb\xd5\x78\xa0\x58\x5b\xb1\xb6\x62\x6d\xc5\xda\x8a\xb5\x15\x6b\x2b\xd6\x56\xac\xad\x58\x5b\x07\xcd\x78\x43\xe2\x88\x98\x11\x73\xa2\x10\xeb\xd9\x28\xd6\x56\xac\xad\x58\x5b\xb1\xb6\x62\x6d\xc5\xda\x8a\xa5\x15\x4b\x2b\x96\x56\x2c\xad\x58\x5a\xb1\xb4\x62\x65\xc5\xca\x8a\x95\x15\x2b\x2b\x56\x56\xac\xac\x58\x59\xb1\xb2\x62\x65\xc5\xca\x8a\x95\x15\x2b\x2b\x56\x56\xd3\xf0\x98\x1f\x56\x56\xac\xac\x58\x59\xb1\xb2\x62\x65\xc5\xca\x8a\x95\x15\x2b\x2b\x56\x56\xac\xac\x58\x59\xb1\xb2\x62\x65\xc5\xca\x8a\x95\x15\x2b\x2b\x56\x56\xac\xac\x58\x59\xb1\xb2\x62\x65\xc5\xca\x8a\x95\x15\x0b\x2b\x16\x56\x2c\xac\x58\x58\xb1\xb0\x62\x61\xc5\xba\x8a\x75\x15\xeb\x2a\xd6\x55\xac\xab\x58\x57\xb1\xae\x62\x5d\xc5\xb6\x8a\x65\x35\x6c\xc6\x25\x7f\xac\xaa\x58\x55\xb1\xaa\x62\x55\xc5\xaa\x8a\x55\x15\xab\x2a\x56\x55\xac\xaa\x58\x55\xb1\xaa\x62\x55\xc5\xaa\x8a\x55\x15\xab\x2a\x56\x55\xac\xaa\x58\x55\xb1\xaa\x62\x55\xc5\xaa\x8a\x55\x15\xab\x2a\x56\x55\xac\xaa\x58\x55\xb1\xaa\x62\x55\xc5\xaa\x8a\x55\x95\xd5\x9a\xb2\x5a\x53\x56\x6b\xca\x6a\x4d\x59\xad\x29\xab\x35\xc5\xa2\x8a\x45\x15\x8b\x2a\x16\x55\x2c\xaa\x58\x54\xb1\xa8\x26\x0d\x8f\xf9\x62\x51\xc5\xa2\x8a\x45\x15\x8b\x2a\x16\x55\x2c\xaa\x58\x54\xb1\xa8\x62\x51\xc5\xa2\x8a\x45\x15\x8b\x2a\x16\x55\x56\x6b\xca\x6a\x4d\xb1\xaa\xb2\x5a\x53\xec\xaa\xd8\x55\xb1\xab\x62\x57\xc5\xae\x8a\x5d\x15\xbb\x2a\x76\x55\xec\xaa\xd8\x55\xb1\xab\x62\x57\xc5\xae\x8a\x5d\x15\xbb\x2a\x76\x55\xec\xaa\xd8\x55\xb1\xab\x62\x57\xc5\xae\x8a\x55\x15\xab\x2a\x56\x55\xac\xaa\x58\x55\xb1\xaa\x62\x55\xc5\xaa\x8a\x55\x15\xab\x2a\x56\x55\xac\xaa\x58\x55\xb1\xaa\x62\x55\xc5\xa6\x8a\x4d\x15\x9b\x2a\x36\x55\x6c\xaa\xd8\x54\xb1\xa9\x62\x53\xc5\xa6\x8a\x4d\x15\x9b\x2a\x36\x55\x6c\xaa\xd8\x54\xb1\xa7\x62\x4f\xc5\x9e\x8a\x3d\x15\x7b\x2a\xf6\x54\xac\xa9\x58\x53\xb1\xa6\x62\x4d\xc5\x9a\x8a\x35\x15\x6b\x2a\xd6\x54\xac\xa9\x58\x53\xb1\xa6\x62\x4d\xc5\x9a\x8a\x35\x15\x6b\x2a\xd6\x54\xac\xa9\x58\x53\xb1\xa6\x2a\x3c\x85\x87\x27\x15\x3f\x2a\x7e\x54\xfc\xa8\x8d\x1f\x15\x8e\xc2\x51\x38\x0a\xa7\x5e\x05\x9b\x41\xed\x51\x33\xa8\x3d\x6a\x06\xb5\x47\xcd\xa0\xf6\xa8\x19\xd4\x1e\x35\x83\xda\xa3\x66\x50\x7b\xd4\x0c\x6a\x8f\x9a\x41\xed\x51\x33\xa8\x3d\x6a\x06\xb5\x47\xcd\x60\x50\xff\x4f\x90\x51\x10\x45\xee\x74\xdb\xb2\x83\x60\x17\x4d\x9a\x72\x0c\x39\x68\x62\x70\xf6\x7a\x76\xb9\x59\x96\x93\x62\x35\xdd\x5d\x3c\x68\xfe\x6f\x77\x33\x08\xa2\x27\x9b\xc5\xa4\x5c\xae\xc6\xd5\xb2\x9c\x5c\xcc\x9f\xfc\x71\x53\xad\xcb\x65\xf9\xb6\x5c\xae\xca\x09\xe7\x68\x1d\x0d\x29\x98\x26\x85\x90\xff\x60\xbc\x6d\x39\xdf\x62\x42\x46\x7b\x57\xb3\xc5\xee\x2f\x95\xca\x71\xb5\x60\x2c\xeb\xfa\xe5\x8f\xe3\x79\x71\x35\xb9\x98\xf3\x09\x37\x2c\x6c\x22\xb4\x08\x5a\xfd\x62\x36\x83\xfa\xc5\x6c\x06\xf5\x8b\xd9\x0c\x22\xce\x8f\x38\x3f\x66\xba\x31\x37\xb6\xc9\x23\xe6\xc6\xc6\xdc\xd8\x98\x99\xc7\xdc\xd8\x98\xeb\x53\xae\x4f\xf9\xc2\x52\xbe\xb0\x94\x2f\x2c\x65\xdc\xe1\xe0\xc9\xb8\x9a\x57\x8b\xab\x6a\x51\xae\x8b\xe5\x4f\x7c\x6a\x8e\xe7\xb3\x65\xc1\x01\xe8\x61\xd4\xbb\x2e\x57\xe5\xba\xf9\x18\xf2\x30\x3d\x9e\x54\x8b\xcb\x63\xd9\x2c\x2b\x3e\x61\x4e\x43\xe6\x34\x24\xa7\x11\x39\x8d\xc8\x69\x44\x4e\x23\x72\x1a\x91\xd3\x08\xe0\x88\x39\x8d\xb8\x77\x3a\xe0\x5b\x31\xfc\xc7\xd9\x28\x30\xfc\x47\xf4\x28\xe0\x7f\x61\x33\x41\xbd\xe1\x61\x02\x13\xf5\xcb\xd5\x7a\x76\x55\xac\xf9\xe6\x83\x5a\xea\x26\x70\xf2\x68\x3b\xdb\xe9\x6c\x39\xe9\xaf\xdf\x55\xbb\xc6\xaa\x5f\x2d\xca\x72\x76\x39\x5d\x4f\xcf\xd7\xd3\x65\x49\x7b\xf5\xf8\xf5\xec\x6d\xd3\x3e\x5f\x95\x6f\xcb\x05\x07\xf5\x50\x89\xeb\x17\xcb\x65\xf5\x6e\x5e\xbe\x5e\x9f\xee\x5a\x9b\xeb\xb3\x5d\x5c\x6e\x4f\xab\x3b\x27\xd5\xbb\x45\xdd\xba\xa8\xd6\xd3\x3e\xa7\x4d\x16\xe7\xbe\x75\xb1\xda\xd5\xb7\x86\x3f\xe3\x30\xfc\x59\x85\x31\x41\x7a\x56\x2d\xd7\xd3\xea\xb2\x5a\x14\xf3\xf3\xd9\x62\xbd\xfd\x21\x8f\xd7\xb3\x6a\xf1\xb8\xfc\xe3\x66\xf6\xb6\x98\x97\x8b\x71\x79\x32\xad\x36\xab\xf2\xc9\xb2\x7c\x3b\xaf\x2e\x67\xe3\x62\xbe\xa8\xd6\x67\xdb\x93\x2f\x97\xc5\x7c\x7d\xed\x9b\x17\xeb\x47\xdf\x68\x30\xd8\xfe\xb3\x6d\x04\x34\x06\xbe\x61\x9b\x86\x69\x1a\xae\x69\x24\x4d\x23\x6d\x1a\x51\xd3\x88\x9b\x46\x48\xc3\x35\xe3\x98\xe6\xf2\xb0\x41\x84\xcd\xc8\xb6\x19\xc7\x34\x9f\x98\xe6\x1c\xd3\x8c\x13\x36\xa9\xba\xe6\x64\xdb\xa4\x61\x7c\xa3\xa1\x9b\x26\x1f\xeb\x1b\x4d\x97\x6b\x10\x81\x87\x36\x23\x9b\x26\x55\xe7\x4f\x6e\x46\x76\x4d\x3e\xce\xcf\xab\x19\xd9\x35\x97\x87\x7e\x82\x7e\x9c\xdd\x27\xa7\x9b\xeb\x8b\x79\x35\x7e\x73\x3a\x59\xec\xe2\x49\x7d\x34\x7f\x5d\xc7\xe5\x9a\xe3\xf5\x6a\x5a\x4c\xca\x93\xdd\xbf\x4f\x27\x6f\x76\xb1\xff\x7a\x36\x9f\x97\x93\x8b\xea\xc7\xde\x67\xc6\x0c\x62\xdb\xfb\x2c\x48\x42\x57\x87\x70\xfb\xfa\xdb\x76\x2f\xcb\xf1\xfa\x74\xbd\x9c\x15\x97\x9b\xeb\x3a\x2e\x39\x9e\x2c\xea\x38\x7f\xdd\x1b\xcf\x96\xe3\x79\xfd\xd3\x0a\xb3\x6c\x37\x80\xb5\xfd\xd9\xe2\xed\xc5\x66\x3e\x2f\xd7\xdb\x56\x7d\xca\x59\x75\x5d\x2e\xf8\x70\x75\x35\x9b\x97\xaf\x8b\x71\x79\x3e\x5b\xbc\xf5\x07\x47\xab\xcd\xa2\xf7\xba\xbc\x2a\xe6\xe5\xf1\xf6\x5f\x27\xab\xeb\x62\x52\x1e\x8f\xe7\x9b\x8b\x93\x69\x59\x2c\xd7\xa7\x93\x59\x71\x55\x2d\x26\x8f\xaf\x36\x2b\x7e\x83\xe5\x2f\xf6\xda\xcd\x2b\x32\xe2\x15\x97\xd5\xb5\xaf\xc9\xea\xda\xd7\x64\x75\xed\x6b\xb2\xba\xf6\x35\x59\x5d\xfb\x9a\xac\xae\x7d\x4d\x56\xd7\xbe\x26\xab\x6b\x5f\x93\xd5\xb5\xaf\xc9\xea\xda\xd7\x64\xbc\x62\x33\x5e\xb1\x19\xaf\xd8\x8c\x57\x6c\x16\xc3\x89\xe1\xc4\x70\x78\xc5\x66\xbc\x62\x33\x5e\xb1\x19\xaf\x58\x76\x50\x87\xb1\x8f\x09\x31\x25\x0e\x89\x23\x62\x46\xcc\x89\x42\xd4\x3a\xd6\x6b\xb6\x61\x5c\xaf\xd9\x86\x71\xc2\x78\x09\xe3\x25\x8c\x97\x30\x5e\x5d\xd3\x0a\x0e\xd6\x51\xed\x60\x1d\xd5\x0e\xd6\x51\xed\x60\x1d\xd5\x0e\x56\x76\x6a\x95\x9d\x5a\x65\xa7\x56\xd9\xa9\x55\xa9\x77\xb4\x15\xd7\xab\x6a\xfe\x68\xf7\xb7\xe6\x61\x14\x35\x8d\xa4\x69\xa4\x34\xe2\x01\x8d\x94\x4f\xa2\x41\x40\x23\xa0\x91\x24\xae\x69\x84\x4d\x23\x6a\x1a\x71\xd3\x48\x9a\x06\xe3\x24\xe9\xa0\x69\x34\xe3\xa4\xa6\x69\xd8\xfe\xae\xb1\x7b\xcd\x36\xad\xd0\xb7\xa2\x5f\x6d\xea\xbf\x19\xf8\xfd\xed\x18\xfd\xcd\x78\x7c\x75\x7d\x47\x67\xdc\xd5\x99\x74\x75\xa6\x6d\x9d\x51\x73\x52\x57\x67\x6b\x42\x51\x57\x42\x51\x57\x42\xd1\xad\x84\x3e\xb9\xc7\xe4\xe3\xae\x2c\xe3\xfb\x5c\xd9\x9a\x65\xdc\x95\x65\xdc\x95\x65\xeb\x70\x49\x57\x96\x49\x57\x96\xc9\x7d\x86\x6d\xcd\x32\xe9\xca\xb2\xf5\x8a\xb4\x2b\xcb\xb4\x2b\xcb\xb4\x2b\xcb\xf4\x3e\xcc\xd6\x2c\x6f\xfd\x2e\xa3\x83\x1f\x6d\xd8\xd5\x19\x75\x75\xc6\x5d\x9d\x49\x57\xe7\xad\x2c\x5b\x1f\x90\xa8\xeb\xe9\x39\xec\x6c\x4d\xa4\xf5\x01\x39\xec\x6c\xbd\x33\xad\xcf\xc2\x61\x67\xeb\x9d\x69\x7d\x16\x0e\x3b\x5b\x13\x6a\x7d\x16\x3a\xe7\xd7\xfa\x2c\x1c\x76\xb6\x66\xd9\xfa\x2c\x1c\x76\xb6\x66\xd9\xfa\x2c\x74\xde\xe8\xd6\x67\xe1\xb0\xb3\x35\xcb\xd6\x67\xe1\xb0\xb3\x93\xd9\x9a\xe5\xad\x6f\x3c\xee\x7a\x16\x0e\x3b\xa3\xae\xce\xb8\xab\x33\xe9\xea\xbc\x95\x65\xeb\x4f\x2f\xee\x7a\x16\x0e\x3b\x5b\xb3\x6c\xfd\x21\x1d\x76\xb6\x66\xd9\x6a\x92\xd6\x67\x20\xee\x7a\x7a\x0e\x3b\x3b\xaf\x6c\x4d\x24\xee\xfa\xfe\x5a\x9f\x85\xc3\xce\x56\x66\xeb\xb3\x70\xd8\xd9\x9a\x50\xeb\xb3\xd0\x39\x85\xd6\x67\xe1\xb0\xb3\x35\xcb\xd6\x67\xe1\xb0\xb3\x93\xd9\x9a\xe5\xad\x7b\x99\x74\x3d\x0b\x87\x9d\x51\x57\x67\xdc\xd5\x99\x74\x75\xde\xca\xb2\xf5\x4b\x4d\xba\x9e\x85\xc3\xce\xd6\x2c\x5b\x9f\x85\xc3\xce\xd6\x2c\x5b\x9f\x85\xd6\x5f\x57\xd2\xf5\x2c\x1c\x76\x76\x5e\xd9\x9a\x65\xeb\xaf\xec\xb0\xb3\x35\xcb\xd6\xe1\x3a\x6f\x74\xe7\xfc\xee\x35\x6c\xeb\xaf\xac\xf5\x59\x38\xec\x6c\x65\xb6\x3e\x0b\x87\x9d\xad\x77\xa6\xf5\x59\x68\xcd\x32\xed\x7a\x16\x0e\x3b\xa3\xae\xce\xb8\xab\x33\xe9\xea\xbc\x95\x65\xeb\xed\x4a\xbb\x9e\x85\xc3\xce\xd6\x2c\x5b\x9f\x85\xc3\xce\xd6\x2c\x5b\x9f\x85\xd6\xef\x2d\xed\x7a\x16\x0e\x3b\x3b\xaf\x6c\xcd\xb2\xf5\x59\x38\xec\x6c\xcd\xb2\x75\xb8\xd6\x67\xe1\xb0\xb3\x35\xcb\xd6\x67\xe1\xb0\xb3\x35\xcb\x56\x93\xb4\xfe\x92\xd3\xae\xa7\xe7\xb0\xb3\x35\xcb\xce\xc9\xdf\x66\xfe\xff\xdd\x5f\x60\xee\x3e\xb2\x03\x57\xc7\xc0\xfe\xde\xff\xb5\x7a\xd7\x49\xfe\x0f\xd9\xef\x3e\xc9\xdd\x67\x24\xd7\x35\x52\x74\x9f\x9c\xa2\xfb\xe4\x14\xdd\x27\xa7\xe8\x8e\x9c\x7e\x33\xab\xd6\x3f\x77\x9b\xda\xcf\xf9\xf9\x71\x0e\x13\x6a\x3f\xe7\xee\x71\xee\xba\x45\xed\xe7\xfc\xfc\x38\x5d\xf9\xdc\x75\x7f\xfe\x8a\x3f\x91\xfd\x99\x5b\x74\xe7\x69\xf7\x1a\xed\x30\xb1\x3b\x4f\xeb\x1c\xed\xae\xdb\x75\xe7\x69\xf7\x1a\xed\x67\x72\xbb\xcf\xef\x2a\xf1\xf3\xb8\xfb\xfe\xdf\x9c\xf3\xf3\xe3\x44\xf7\x18\x27\xea\x9e\xdd\x5d\x29\xdd\x79\xda\xbd\x46\x3b\x4c\xec\xce\xd3\x6e\x8f\xc6\x8e\x9f\x8d\xac\x6f\x39\xdf\x0a\x7d\x2b\xf2\xad\xd8\xb7\x12\xdf\x4a\x9b\x56\x3c\xf0\xad\xc0\xb7\x8c\x6f\x79\x46\xec\x19\xb1\x67\xc4\x9e\x11\x7b\x46\xec\x19\xb1\x67\x24\x9e\x91\x78\x46\xe2\x19\x89\x67\xf8\x7d\x4d\xeb\xf7\x35\x6d\xe2\x19\x89\x67\x24\x9e\x91\x78\x46\xea\x19\x69\xc3\x70\x83\xe4\xc1\x83\x07\xff\xf1\xd1\x5f\xfe\xf5\xfd\x47\xff\xf6\xe0\xf3\xf7\x8f\xbe\xfa\xfe\xcf\x1f\x7d\xf4\xef\xaf\xfe\xac\xbd\x67\xdf\xff\xfa\xfd\x2f\x5f\x7d\xfe\xfe\x93\xaf\xbf\xff\xf5\xfb\x7f\x79\xf5\xff\xde\xf7\x9e\xfd\xee\xfb\x07\xef\x8f\x9e\xca\xfb\xa3\x67\xf9\xfb\xe3\xa7\xf2\xe1\xe8\x37\x0f\x9f\xed\x0e\x4e\x9e\xca\x87\xe3\x5f\x71\xd0\x7b\x2a\x1f\x4e\xfe\x8b\x83\xd3\xa7\xf2\xa1\x37\xe6\xe0\xd1\x53\xf9\x70\xfa\x15\x07\xfd\xa7\xf2\xe1\x91\xe5\xe0\xec\xa9\x7c\xe8\xff\x35\x07\x8f\x9f\xca\x87\xb3\xa7\x1c\x9c\x3f\x95\x0f\x8f\x3f\xa9\x0f\x3e\x7a\xff\x04\xfa\x2f\x9e\xca\x7f\x3e\x78\xf2\xcf\x7f\x79\xf0\xf0\xd9\x9f\x8f\xf4\xed\xb3\xfc\xfd\xc7\xdb\x4f\x7e\xf1\xd1\xff\xbd\xf9\xe4\x97\x4f\xe5\xc3\xc7\xd7\xcd\xe1\xab\xf7\x9f\x3c\x7b\xf0\xd1\xdf\xfd\xcf\x7f\xbf\x7d\xf0\xe0\x7f\x03\x00\x00\xff\xff\xb7\x70\xfc\x1e\xf8\x13\x08\x00") - -func resourcesAppStaticFontsNotosansBolditalicWebfontTtfBytes() ([]byte, error) { - return bindataRead( - _resourcesAppStaticFontsNotosansBolditalicWebfontTtf, - "resources/app/static/fonts/NotoSans-BoldItalic-webfont.ttf", - ) -} - -func resourcesAppStaticFontsNotosansBolditalicWebfontTtf() (*asset, error) { - bytes, err := resourcesAppStaticFontsNotosansBolditalicWebfontTtfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/static/fonts/NotoSans-BoldItalic-webfont.ttf", size: 529400, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppStaticFontsNotosansItalicWebfontTtf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7d\x58\x9b\x5b\x76\x1f\xba\xf6\xfb\x0a\x49\x80\x10\xfa\x78\xf5\x89\x24\x24\x21\x84\x10\xfa\x42\x88\x0f\x83\x00\x81\x09\x43\x88\xc3\x30\x0c\xa5\x94\x32\x2e\x87\x30\x1c\xca\x70\x18\x86\x30\x84\xb8\x8c\xc3\x38\x8e\x43\xa8\xc7\x43\x5c\xe2\x32\x84\xeb\xa1\x94\x70\x79\x28\xd7\xe5\x12\xd7\xa5\x84\xba\x1e\x4a\x3c\x1e\xca\x78\x18\x0f\x25\x8c\x43\x3c\x84\x10\x97\xba\xbe\x5c\x5f\x87\xba\x7e\x1c\x06\xdf\x47\xfb\x95\xad\x2d\x40\x67\x70\x8e\xa7\xd3\x7b\x9f\xf3\xc7\x59\x5e\xe7\xc7\x7a\xd7\xde\x7b\xed\xb5\xd7\x5a\x7b\xbd\x12\x00\x02\x00\x29\x02\xe0\x80\xab\xb8\xb8\xf2\x57\xff\xe1\xf6\x17\x5a\x01\x90\x17\x00\x34\x9f\x29\xfa\xa5\xe2\xcf\xc6\x7e\xa6\x0c\x00\x55\x03\xa0\xd5\xcf\x94\x7f\xf6\xf3\x0d\x3f\x7c\xf6\x9f\x00\x68\x1b\x20\x3b\xe7\x33\x9f\xff\x7b\x85\xbf\xfd\x47\x53\x7f\x00\xc8\xe5\x02\xe0\x2b\x3f\xfb\x79\xa7\xfb\xbf\x4f\x7d\xeb\x5f\x03\xca\x2a\x01\x80\xba\x5f\xfb\xe8\x83\xb6\x3f\x9e\x2b\xca\x06\x94\x35\x01\x10\x71\xf0\x6b\x9d\x1d\x7a\xb1\x51\x94\x06\x28\x6f\x02\x00\x2a\x1a\xdb\x3e\xfc\xe8\xf3\x37\x9d\xff\x3b\xa0\xbc\x7d\x00\xea\x8b\x1f\x7e\xf0\xeb\x6d\x00\x20\x02\x54\xd0\x00\x00\xfc\x0f\x5b\x7e\xb3\xf1\xbf\xfe\xfb\xbf\xf4\x01\x2a\x68\x01\x6e\xe2\x54\xd3\x17\x3f\x68\xa0\x8b\xeb\x96\x80\xf7\xa1\x12\x00\x32\x9a\x9a\xbe\xf8\x81\xf0\xdb\xd1\xdf\x05\xde\x87\xe5\x00\x60\x6a\xfa\xa8\xa3\xeb\x5b\x31\x77\xfe\x07\xf0\x3e\xec\x00\x48\x9c\x6d\xf9\xf2\xaf\x7d\x60\xf8\x4f\x1b\x02\xe0\x7d\xc3\x06\x90\x38\xff\xd1\x07\x5d\x6d\x51\x0f\xe9\x3f\x06\xde\xcc\x0e\x00\xe8\x5b\x3f\xf8\xe8\x8b\xe7\x7e\xe7\x8f\xfe\x15\xf0\xfe\x98\x0f\xc0\x79\xd8\xf6\xe5\x5f\xef\x10\xfe\x31\xf5\x35\xe0\xfd\xdb\x6d\x80\x0f\xd3\xdb\xda\xbf\xd8\xf6\x55\x8b\xf9\xbf\x00\x3f\x5e\x03\x80\x0a\x7f\xe3\x8b\xf5\x8d\xff\x39\xf5\x73\x8f\x81\xaf\xaf\x03\x00\x2e\x00\xb6\x1e\x2c\xe7\x8e\xfe\xc0\xff\xef\x77\x86\x3c\xcf\xfd\xff\xde\x17\xfc\xce\x14\xfe\x89\x10\x00\xe9\x91\x05\x00\x28\xb0\x03\x40\x21\x20\x38\x0d\xa7\x81\x86\x22\xf8\xc7\x80\xa0\x19\x9a\x81\x86\x2f\xc1\x57\x01\x41\x27\x74\x02\x0d\xbf\x01\xbf\x09\x08\xce\xc1\x39\xa0\xe1\x9f\x50\xe7\x00\x51\xff\x84\xfa\x6d\xa0\xa9\x8b\xd4\xef\x02\xa2\x7a\xa9\x7f\x01\x34\x35\x4a\xfd\x1f\x80\xa8\x1b\xd4\x4d\xa0\xa9\x7f\x43\xfd\x1b\x40\xd4\x2d\x5a\x04\x34\x2d\xa6\xc5\x80\x68\x09\xed\x01\x9a\x4e\xa7\xb3\x00\xd1\xa7\xe8\x6c\xa0\xe9\x1c\x4e\x1a\x20\x8e\x87\x93\x09\x34\x27\x2b\x62\x10\x50\xc4\xb7\x22\xfe\x08\xe8\x88\x71\x5e\x29\x20\xde\xaf\xf0\x3e\x0b\x34\xaf\x9c\xf7\x0f\x00\xf1\x6a\x78\xb5\x40\xf3\xbe\xc0\x6b\x04\xc4\xfb\x90\xf7\x8f\x81\xe6\x35\xf3\x3a\x01\xf1\x7e\x83\xf7\x9b\x40\xf3\xce\xf1\x7e\x1b\x10\xef\x22\xef\x77\x80\xe6\x5d\xe2\x5f\x04\xc4\xff\x1d\xfe\x25\xa0\xf8\xbf\xcb\xef\x05\xc4\xff\x3d\xfe\x65\xa0\xf9\xdf\xe0\x7f\x13\x10\xbf\x9f\xff\xcf\x80\xe6\x0f\xf0\xff\x00\x10\xff\x1a\xff\x5f\x02\xcd\x1f\x8b\xfc\x3c\xa0\xc8\xca\xc8\x16\xa0\x23\x3f\x8a\xfc\x08\x10\x70\xb0\x55\xfc\xff\x69\xa8\x05\x6a\x0d\x28\x6a\x9d\xfa\x73\xa0\xa9\x0d\x6a\x03\x28\xea\x11\xb5\x05\x34\xf5\xd7\xd4\x0e\xd0\xd4\x7f\xa3\xfe\x3b\xd0\xd4\xdf\x52\x07\x40\x53\xaf\x69\x04\x14\xcd\xa1\xb9\x40\xd1\x3c\x9a\x07\x34\xcd\xa7\xf9\x40\xd1\x91\x74\x34\xd0\xb4\x80\x16\x02\x45\xc7\x62\x6b\x48\x68\x06\x28\x5a\x46\x2b\x81\xa6\x55\xb4\x0a\x28\x3a\x8e\xd6\x00\x4d\x6b\x69\x2d\x50\x74\x22\x9d\x0a\x14\xb6\x09\x15\xf1\xad\x88\x21\xa0\x22\xfe\x30\xe2\x0f\x81\x8e\x18\x8e\x18\x05\x2a\xe2\x5f\x46\xfc\x4b\xa0\x23\xc6\x22\xc6\x80\x8a\xf8\x23\xbf\xad\xf0\xea\x10\xde\xd3\x28\x28\x83\xab\x40\xff\xda\x6f\xb6\xb7\x00\xf3\x61\xfb\x17\xbf\x04\xa6\x96\x0f\x3a\x5a\xc1\x83\x57\x04\xaf\x5f\x03\x8d\xfd\x82\x0e\xf9\x7f\xea\xb8\xff\xff\xd2\x17\xdb\x5b\x41\xfd\xd1\x07\xed\x5f\x02\x3d\xa6\xe6\x8f\xbe\xf4\xd1\x97\xc0\x8b\x9f\x8f\xc6\xd4\x3f\x62\x24\xe6\x58\x0d\x11\xc0\x05\x1e\xf0\xb1\x86\x48\x88\x02\x01\xa8\xc1\x08\x56\x70\x43\x36\x14\x42\x29\x54\x40\x0d\xd4\x43\x33\xb4\xe3\xd1\xd0\x1f\x54\xb1\xff\xa2\x12\xf6\x5f\xee\x24\xfb\x2f\xbd\xcf\xfe\xfb\x41\x11\x70\x10\x00\xb2\x37\xb1\xff\x4f\xb5\xb0\xff\x4a\x1d\xec\xbf\x60\x04\x2e\x05\x80\x62\x1e\x01\x97\x06\x40\x51\x1a\xa0\x80\x0f\xd4\xa3\x17\xdb\x37\x01\xc1\x0a\xdc\x00\x04\xeb\x20\x00\x06\xac\xe0\x82\x0c\xf0\x42\x21\x94\x40\x19\x54\x42\x0d\xd4\x41\x23\xb4\x40\x3b\x74\xc1\x79\xb8\x08\x7d\xd0\x0f\xd7\x60\x18\x10\x9d\x07\x55\x80\x68\x06\xec\x80\xe8\x6f\xfa\x79\x68\x3d\xe8\xf2\x8f\x7d\xd0\x06\x88\x1e\x0e\x20\x17\x01\xd1\x5f\xc7\x73\x38\xf0\x23\x11\x7f\x8b\x9f\xfa\x43\x4c\x59\x0d\xb9\x07\xab\x80\x10\xf8\x79\xaa\x1a\xd3\x24\x8c\x63\x9d\xe8\x27\x7e\xca\xb1\x63\x7c\x09\xaa\x80\x82\x08\xf8\x25\xf8\x0c\x00\xfc\x32\xfc\x0a\xd0\xf0\xab\xf0\x39\xe0\xc2\xe7\xa1\x06\xa2\xe1\x0b\xf0\x05\x90\xfa\x6d\x4c\xfd\x15\xb5\x8d\xbd\x32\x8a\x8d\x43\xaf\x47\xf1\x6c\x30\x45\x72\x78\x04\x08\x19\xb1\xcd\x4f\xb2\xd2\x51\x98\x80\x1b\x70\x13\xe6\xe0\x0e\xdc\x85\x65\xff\x2c\xb9\x1c\x40\xa8\x89\x33\xed\x5f\x2d\xcf\x05\x88\xea\xe1\xb5\x00\xa2\x6a\xfd\x38\xd5\x82\xe9\xba\x9f\xd2\x14\xc6\xb7\x30\x92\x8d\x11\x3d\x7e\x76\x13\xf3\xe7\x30\x5e\x8f\x69\x8a\x5f\x1b\xda\xc3\x3a\x11\xa6\x45\x5c\x1b\x20\xf4\xb7\x18\xef\xc7\xc8\x00\xe6\x6d\x98\xff\x16\x21\xcf\xc7\x3a\x97\xfd\xf2\xa0\x46\x9f\x43\xdf\xa6\x67\xe8\xff\x40\x7f\x87\xbe\x4b\x7f\x8f\x5e\xa2\x7f\x40\xaf\xd2\x1b\xf4\x23\xfa\x27\xf4\x26\xfd\x97\xf4\x63\xfa\xbf\xd2\x4f\xe8\xff\x9b\xde\xa3\xf7\xe9\x03\xfa\x35\x07\x38\x14\x27\xd6\x7f\x8e\xa9\x05\xea\x3f\x52\x77\xa9\xfb\xd8\x63\x24\x00\xe0\x8f\xcd\x3a\x7f\x3c\x06\xf4\xd3\x4e\xce\xf0\x1b\xfa\x7a\x0e\x53\x91\x9f\xa2\x46\xa4\x03\x84\x5a\x40\x00\x46\x28\x86\x33\x50\x01\xd5\x70\x16\x1a\xa0\x19\xda\xa0\x13\xba\xe1\x02\xf4\xc2\x15\x18\x80\x21\x18\x81\x71\x98\x82\x19\x98\x85\xdb\xb0\x08\x4b\xb0\x02\x6b\xb0\x01\x5b\xb0\x03\xbb\xb0\x07\xaf\x10\x20\x2e\x12\x00\x42\x2b\xd8\x7f\x0b\xb1\xb7\xcf\x62\xbe\x13\x7b\xcf\x24\x46\xf6\x08\xdc\x1c\xf0\xf4\x20\xfe\x45\x4c\xff\x11\xc6\x35\x98\xbf\x84\xe9\x10\xa6\x63\x98\x9e\x3d\xa8\x05\x04\x35\x98\xef\xc7\x9a\x59\x7e\x21\xa8\x39\x80\x18\x30\x8d\x61\x9f\x0a\xce\x81\xd5\xcc\x52\x56\x32\x20\x7f\x96\x90\xac\x09\x9c\x3a\x13\x98\xc1\x02\x56\xb0\x81\x03\x9c\x90\x0a\x6e\x48\x87\x0c\xc8\x84\x2c\x28\x82\x62\x28\x81\x52\x38\x03\x65\xf0\x59\xf8\x1c\x54\xc0\xdf\x83\x2a\xf8\xfb\x50\x0d\xfd\x30\x0c\xff\x1b\xfc\x6b\x98\x86\x79\xf8\xf7\xb0\xef\x8f\x1e\xd4\x7f\xc5\x11\x84\x0b\x08\x7b\x34\xa2\x06\xa8\x32\x40\xd4\x10\x08\xa0\x04\xae\xc2\x20\x5c\x87\x31\x98\x84\x69\xb8\x05\xf3\xb0\x00\xf7\xe0\x3e\xac\xc2\x43\xd8\x84\xc7\xf0\x14\x9e\xc3\x4b\x38\x40\x1c\x14\x85\x44\x48\x8e\x34\xc8\x88\x2c\xc8\x81\x3c\x28\x1b\xf9\x50\x31\x3a\x83\x2a\x50\x35\x3a\x8b\x1a\x50\x33\x6a\x43\x9d\xa8\x1b\x5d\x40\xbd\xe8\x0a\x1a\x40\x43\x68\x04\x8d\xa3\x29\x34\x83\x66\xd1\x6d\xb4\x88\x96\xd0\x0a\x5a\x43\x1b\x68\x0b\xed\xa0\x5d\xb4\x87\x5e\x51\x40\x71\x29\x01\x25\xa1\x94\x94\x8e\x32\x51\x56\xca\x45\x65\x50\x5e\x40\x74\x66\xc4\x3c\x20\x7a\x27\xa2\x0b\x10\x67\x3c\xe2\x02\x20\x7a\xc3\xcf\xd3\x7b\x11\xb7\xde\x50\xce\xba\x1f\x8f\x30\xf8\x79\xaa\xcf\x4f\xd1\x7f\xc6\xf8\x34\xe6\x37\xfd\x94\xfb\x1b\x7e\x1a\x51\x8a\xf1\xae\x88\x06\x40\xf4\x28\xd6\x49\xf0\xf4\x7c\xc4\x6f\x02\xe2\x54\x63\xc9\x38\x2c\xd9\xeb\xa7\x3c\x09\xe6\xb3\x30\x35\x61\x6a\x65\x11\x4e\x29\x20\x7a\x95\xde\x01\x44\xd7\x72\x12\x00\x71\x3e\xe0\x32\x80\xe8\x36\x8c\xfc\x6a\xc4\xab\x50\x19\xd4\xef\xe7\x59\x4a\x5f\xc1\xfc\xa6\x5f\x9e\xeb\xc3\xf2\xac\x9e\x2b\x41\x3e\xf0\xac\x9c\x53\x01\x88\x4e\xe4\x30\x80\xd0\x0f\x23\x8a\xdf\xe2\x77\xfc\x34\x62\x03\xf3\x17\x83\x08\x5d\xe7\xa7\xec\xba\x48\xca\xae\x88\xa5\x81\x51\x08\xca\xf1\xe1\xa7\x30\x0d\xac\xdd\x17\xd4\x13\x90\x21\x78\x52\x86\xe0\x29\x88\x06\x13\xe4\x02\x40\x11\x7c\x01\xd4\x30\x00\x7f\x00\x1e\xf8\xe7\xf0\xcf\x21\x03\xfe\x10\x86\x21\x13\x6e\xc2\xbf\x81\x53\xf0\x6f\xe1\xdf\x42\x0e\xfc\x09\xcc\x83\x17\x59\x51\x0a\xe4\x71\xbf\xcc\x6d\x07\x1f\xf7\x77\xb9\x7d\x50\x84\xbd\xf4\x2f\xde\x78\xe9\xeb\x1f\x70\x9e\x03\xa2\x47\x68\x1d\x20\x7a\x1c\x04\x50\x8f\x23\xe7\x03\x58\x87\x47\xb0\x0d\x4f\xe0\x19\xbc\x80\x7d\x44\x21\x3e\x12\x22\x06\xa9\x91\x1e\x99\x91\x0d\xb9\x51\x16\xca\x43\x45\xa8\x14\x95\xa3\x2a\x54\x8b\xea\x51\x13\x6a\x45\x1d\xe8\x1c\xea\x41\x97\xd0\x65\x74\x15\x0d\xa2\xeb\x68\x0c\x4d\xa2\x69\x74\x0b\xcd\xa3\x05\x74\x0f\xdd\x47\xab\xe8\x21\xda\x44\x8f\xd1\x53\xf4\x1c\xbd\x44\x07\x14\x87\x8a\xa2\x44\x94\x9c\xd2\x50\x46\xca\x42\x39\x28\x0f\x95\x4d\xf9\xa8\x62\xea\x0c\x55\x41\x55\x53\x67\xa9\x06\xaa\x99\x6a\xa3\x3a\xa9\x6e\xea\x02\xd5\x4b\x5d\xa1\x06\xa8\x21\x6a\x84\x1a\xa7\xa6\xa8\x19\x6a\x96\xba\x4d\x2d\x52\x4b\xd4\x0a\xb5\x46\x6d\x50\x5b\xd4\x0e\xb5\x4b\xed\x51\xaf\x68\xa0\xb9\xb4\x00\x10\xf5\x97\x7e\xcf\xe6\xd4\x71\xce\x03\xe2\x5c\x8e\xf8\x2a\x20\xce\x8f\xfd\x3c\xbd\x8f\x77\x08\x53\xce\x43\x8c\x3f\x0c\xfa\x31\x1a\xc3\x78\x73\x90\xe7\xa6\xe3\x7d\x35\x63\x5a\x8c\xb5\x15\xfa\x29\xc9\xd3\x53\xd8\xd7\xeb\xf0\xb3\x2f\x30\x3d\x8f\x9f\x65\xcf\x8f\xfa\x08\x95\x61\x4f\xda\xa7\xfd\x19\xb7\x84\x63\x07\xc4\x49\x0e\x78\x36\x46\xb8\xc2\x37\x32\x1c\x91\x1f\x41\xd8\x0f\x58\x4a\xb7\x61\x7e\x0c\x7b\x76\xa5\xff\xa7\xac\x0c\xbd\x83\x29\xd6\x19\xd0\x2f\xf0\x53\xea\xc0\xef\xd9\xd4\x25\xac\x4d\x83\xf1\x29\xec\x55\xf7\x30\xdf\x18\x44\x68\x2f\x96\x91\xfd\x6c\xca\xcd\xc0\x63\xb5\x1d\x4f\xc9\xd9\x86\xcc\x7c\x87\x98\x67\x18\xca\xce\xf0\x28\x0d\xcc\x70\x2a\xa8\x8d\xdb\xc4\xda\x8a\x78\x96\xb0\x2a\xf5\x92\xf8\xa9\x95\x23\xf2\x67\xf3\xa0\x7d\xe8\x29\xce\xd9\xb7\x73\xdb\x0c\xce\x8d\x6b\x23\xc6\x6d\xc7\xd6\x1b\xc0\xa7\x4e\x16\x72\xea\xfc\x55\x86\x07\x26\xe1\xff\x84\x1c\xb8\x09\xb3\x70\x1a\xe6\xe0\x3f\x40\x09\x7c\x07\xbe\x03\x65\xf0\x37\xf0\x37\xf0\x59\x24\x43\x32\x28\x47\xdf\x46\xdf\x86\xcf\x51\x12\x8a\x81\x0a\x4a\x4e\xc9\xe1\xef\x51\x6a\x4a\x0d\x55\x94\x96\xd2\xc1\xdf\xa7\xf4\x94\x1e\xfe\x01\x65\xa6\xcc\x50\x43\x59\x29\x2b\xfc\x43\xca\x46\xd9\xa0\x96\xca\xa4\xb2\xe0\x0b\xd4\xaf\x50\x67\xe0\x1f\x51\x65\x54\x19\x7c\x80\x4f\xec\xc8\x9b\x13\x7b\xf0\x3d\xea\x87\xfe\xfc\x87\x1a\x01\x51\xfe\x7a\x34\xe5\x93\x65\x72\x24\x41\x4a\xa4\x43\x26\x64\x45\x2e\x94\x81\xbc\xa8\x10\x95\xa0\x32\x54\x09\xe8\xf5\xf8\x4f\x5f\x12\x74\xe5\x2d\x9d\x0b\xf0\xdb\x04\xbd\x0b\xe8\xf5\x7d\x7f\xc6\xfe\x69\xd5\x81\x07\xd0\xeb\xe9\x03\xf9\xa1\xa7\x48\xf9\x39\x2c\x33\x87\x35\x1f\xa5\xd3\x2c\xef\xd7\xf6\x7a\xfc\xa0\xe4\x88\x1e\x96\xce\x03\x7a\xbd\x78\xa0\xf7\xdb\x85\xd5\x49\x8c\x32\x87\x7f\x3a\x17\x18\x71\xc2\x3f\x37\xcc\xdf\xc7\xf8\x16\x41\xe7\x42\x28\xf9\xec\x0a\x50\x10\x83\xef\x48\x80\x6f\x47\x1c\x7c\x3b\x8a\xc4\xb7\xa3\x18\x7c\x3b\x52\xe2\x1b\x91\x06\xdf\x85\xb4\xf8\x16\xa4\xc7\xf7\x1f\x23\xbe\xf9\x98\xf1\x0d\xc7\x82\xef\x36\xc9\xf8\x56\x63\xfd\x39\x68\x4c\x01\x80\x1b\x00\x70\x13\x00\xe6\x00\xe0\x0e\x00\xdc\xf5\x5f\x91\x01\xe0\x01\x00\xac\x03\xc0\x23\x00\xd8\x06\x80\x27\x00\xf0\x0c\x00\x5e\x00\xc0\xbe\xbf\x38\x01\x40\x7c\x00\xe4\xbf\x35\x33\x00\x48\xed\xbf\x3d\x03\x20\x33\x00\xb2\x01\x20\x37\x00\xca\x02\x40\x79\x00\xa8\x08\x00\x95\x02\xa0\x72\x00\x54\x05\x80\x6a\x01\x50\x3d\x00\x6a\x02\x40\xad\x00\xa8\x03\x00\x9d\x03\x40\x3d\x00\xfe\x5a\x0e\x5d\x06\x40\x57\x01\xd0\x20\x00\xba\x0e\xe0\xaf\xe9\xd0\xa4\x7f\xaf\x5e\x0f\x13\x74\xf1\x2d\x65\x5e\xdf\x0f\xf3\xd3\x0e\x40\x3f\x1d\x7e\x7d\x1e\xf3\x75\x98\xb2\x92\xbd\x98\x4e\x63\x3a\x4e\x20\xc3\x04\xde\x7b\x84\x76\x60\x5a\x85\xe9\x3a\xa0\xd7\x4f\xfd\xf4\xad\xfc\xfd\x23\xf2\xec\x4f\xe7\x30\xbd\x4a\x48\x2e\x12\x74\x3a\x0c\x5d\x3c\xa2\x79\x18\x10\xd5\x48\x09\x01\x51\xb7\x41\x00\xbe\xf7\x75\x56\x51\x0d\xaa\x43\x8d\xa8\x05\xb5\xa3\x2e\x74\x1e\x5d\x44\x7d\xa8\x1f\x5d\x43\xc3\x68\x14\x4d\xa0\x1b\xe8\x26\x9a\x43\x77\xd0\x5d\xb4\x8c\x1e\xa0\x75\xf4\x08\x6d\xa3\x27\xe8\x19\x7a\x81\xf6\x01\xfd\xf4\x25\xb7\xe9\x0d\x7d\x3d\x8c\xf9\x01\xae\xcf\x3f\xd7\x08\xff\x7d\xd3\xcb\xe3\xfb\xf7\x06\xdf\x57\x2c\x98\xea\xfc\xf4\xa7\xdb\xdc\x65\x8c\xcc\x02\x82\x06\x6e\x3f\xa0\xd7\x1d\xfe\x67\xa1\x38\x48\xf7\x37\x03\xfc\x1e\xd6\xe0\x7b\xab\x81\xa4\x5e\xee\x26\xa6\xfd\x78\x2c\x17\x20\xe8\xe2\x6d\x13\x23\x72\xb0\x86\x59\xcc\xf7\xbf\xa5\x0d\xbc\xeb\x6f\xe5\x01\x23\xe5\x58\x86\x9d\xad\x97\xe5\x31\x0e\xfe\x9a\x2a\x40\x2d\x81\x75\x35\x1c\xa6\xc4\x7c\x8e\xf9\x69\x90\x52\x9a\x88\x7b\x80\x28\x83\x5f\x92\xaa\xf6\xeb\x67\x29\x78\xf1\x1a\xdf\xd0\xfe\x13\x52\xff\xcc\x29\x10\xe2\x5e\x0c\xe0\x2e\x8c\x0c\x77\x5b\xe4\xb8\xdb\xa2\xc2\x7d\x16\x0d\xee\xb0\x68\x71\x6f\x45\x8f\xbb\x2a\x09\xb8\x9f\x62\xc2\xfd\x94\x44\xdc\x4f\x71\xe3\x7e\x4a\x06\xee\xa4\x64\xe1\x1e\x4a\xfe\xcf\x4d\xaf\xef\x17\x12\x35\x00\x4d\x03\xa0\x5b\x00\x68\x1e\xc0\x7f\xff\x43\xf7\x00\xd0\x7d\x00\xb4\x0a\x80\x1e\x02\xa0\x4d\x00\xf4\x18\x00\x3d\x05\x40\xcf\x01\xd0\x4b\x00\x74\x00\x40\x71\x00\xa8\x28\x00\x4a\x04\x40\xc9\x01\xfc\x77\x41\xca\x08\x40\x59\x00\x28\x07\x00\xe5\x01\xa0\xb2\x01\x28\x1f\x00\x55\x0c\x40\x9d\x01\xa0\x2a\x00\xa8\x6a\x00\xea\x2c\x00\xd5\x00\x40\x35\x03\x50\x6d\x00\xfe\xdb\x2d\xd5\x0d\xe8\xa7\x5d\x9c\xd9\x37\xf4\x75\x16\xe6\xcb\x31\x3f\xed\xa7\x00\x7e\x9f\x7d\xbd\x8e\x11\x82\xfe\xd4\x45\x20\x1d\x7e\x7a\xb0\x8f\xf9\x45\x4e\xff\x1b\xba\xbf\x7b\xf8\xa9\xd7\x75\xf4\xe8\x1b\x0a\x80\xf9\x45\xce\x98\x3f\x8f\x71\x3a\x30\x8f\xe3\x61\xc4\xb3\x37\xa3\xbf\x1e\xe6\x54\x62\x7c\xfa\xad\x06\x2c\xf3\x96\xb2\x9a\x87\x08\xba\x88\xf1\xa1\xb7\x9a\xcf\xa0\x83\xf7\x47\x29\x3e\xc7\x1f\xf1\x22\xfd\xe3\x52\x9f\x0d\x52\x00\xce\x3a\x41\x59\x64\xfa\x0d\x65\xe7\xff\x16\x19\x26\xe8\x10\x20\xb5\x52\x75\x0d\x90\x5a\x07\x02\x3a\x95\xdb\xc0\x6d\xe6\xb6\x71\x3b\xb9\xdd\xdc\x0b\xdc\x5e\xee\x15\xee\x00\x77\x88\x3b\xc2\x1d\xe7\x4e\x71\x67\xb8\xb3\xdc\xdb\xdc\x45\xee\x12\x77\x85\xbb\xc6\xdd\xe0\x6e\x71\x77\xb8\xbb\xdc\x3d\xee\x2b\x1e\xf0\xb8\x3c\x01\x4f\xc2\x53\xf2\x74\x3c\x13\xcf\xca\x73\xf1\x32\x78\x5e\x5e\x21\xaf\x84\x57\xc6\xab\xe4\xd5\xf0\xea\x78\x8d\xbc\x16\x5e\x3b\xaf\x8b\x77\x9e\x77\x91\xd7\xc7\xeb\xe7\x5d\xe3\x0d\xf3\x46\x79\x13\xbc\x1b\xbc\x9b\xbc\x39\xde\x1d\xde\x5d\xde\x32\xef\x01\x6f\x9d\xf7\x88\xb7\xcd\x7b\xc2\x7b\xc6\x7b\xc1\xdb\xe7\x53\x7c\x3e\x5f\xc8\x67\xf8\x6a\xbe\x9e\x6f\xe6\xdb\xf8\x6e\x7e\x16\x3f\x8f\x5f\xc4\x2f\xe5\x97\xf3\xab\xf8\xb5\xfc\x7a\x7e\x13\xbf\x95\xdf\xc1\x3f\xc7\xef\xe1\x5f\xe2\x5f\xe6\x5f\xe5\x0f\xf2\xaf\xf3\xc7\xf8\x93\xfc\x69\xfe\x2d\xfe\x3c\x7f\x81\x7f\x8f\x7f\x9f\xbf\xca\x7f\xc8\xdf\xe4\x3f\xe6\x3f\xe5\x3f\xe7\xbf\xe4\x1f\x44\x72\x22\xa3\x22\x45\x91\xf2\x48\x4d\xa4\x31\xd2\x12\xe9\x88\xf4\x44\x66\x47\xfa\x22\x8b\x23\xcf\x44\x56\x44\x56\x47\x9e\x8d\x6c\x88\x6c\x8e\x6c\x8b\xec\x8c\xec\x8e\xbc\x10\xd9\x1b\x79\x25\x72\x20\x72\x28\x72\x24\x72\x3c\x72\x2a\x72\x26\x72\x36\xf2\x76\xe4\x62\xe4\x52\xe4\x4a\xe4\x5a\xe4\x46\xe4\x56\xe4\x4e\xe4\x6e\xe4\x5e\xe4\xab\x28\x88\xe2\x46\x09\xa2\x24\x51\xca\x28\x5d\x94\x29\xca\x1a\xe5\x8a\xca\x88\xf2\x46\x15\x46\x95\x44\x95\x45\x55\x46\xd5\x44\xd5\x45\x35\x46\xb5\x44\xb5\x47\x75\x45\x9d\x8f\xba\x18\xd5\x17\xd5\x1f\x75\x2d\x6a\x38\x6a\x34\x6a\x22\xea\x46\xd4\xcd\xa8\xb9\xa8\x3b\x51\x77\xa3\x96\xa3\x1e\x44\xad\x47\x3d\x8a\xda\x8e\x7a\x12\xf5\x2c\xea\x45\xd4\x7e\x34\x15\xcd\x8f\x16\x46\x33\xd1\xea\x68\x7d\xb4\x39\xda\x16\xed\x8e\xce\x8a\xce\x8b\x2e\x8a\x2e\x8d\x2e\x8f\xae\x8a\xae\x8d\xae\x8f\x6e\x8a\x6e\x8d\xee\x88\x3e\x17\xdd\x13\x7d\x29\xfa\x72\xf4\xd5\xe8\xc1\xe8\xeb\xd1\x63\xd1\x93\xd1\xd3\xd1\xb7\xa2\xe7\xa3\x17\xa2\xef\x45\xdf\x8f\x5e\x8d\x7e\x18\xbd\x19\xfd\x38\xfa\x69\xf4\xf3\xe8\x97\xd1\x07\x02\x8e\x20\x4a\x20\x12\xc8\x05\x1a\x81\x51\x60\x11\x38\x04\x1e\x41\xb6\xc0\x27\x28\x16\x9c\x11\x54\x08\xaa\x05\x67\x05\x0d\x82\x66\x41\x9b\xa0\x53\xd0\x2d\xb8\x20\xe8\x15\x5c\x11\x0c\x08\x86\x04\x23\x82\x71\xc1\x94\x60\x46\x30\x2b\xb8\x2d\x58\x14\x2c\x09\x56\x04\x6b\x82\x0d\xc1\x96\x60\x47\xb0\x2b\xd8\x13\xbc\x8a\x81\x18\x6e\x8c\x20\x46\x12\xa3\x8c\xd1\xc5\x98\x62\xac\x31\xae\x98\x8c\x18\x6f\x4c\x61\x4c\x49\x4c\x59\x4c\x65\x4c\x4d\x4c\x5d\x4c\x63\x4c\x4b\x4c\x7b\x4c\x57\xcc\xf9\x98\x8b\x31\x7d\x31\xfd\x31\xd7\x62\x86\x63\x46\x63\x26\x62\x6e\xc4\xdc\x8c\x99\x8b\xb9\x13\x73\x37\x66\x39\xe6\x41\xcc\x7a\xcc\xa3\x98\xed\x98\x27\x31\xcf\x62\x5e\xc4\xec\x0b\x29\x21\x5f\x28\x14\x32\x42\xb5\x50\x2f\x34\x0b\x6d\x42\xb7\x30\x4b\x98\x27\x2c\x12\x96\x0a\xcb\x85\x55\xc2\x5a\x61\xbd\xb0\x49\xd8\x2a\xec\x10\x9e\x13\xf6\x08\x2f\x09\x2f\x0b\xaf\x0a\x07\x85\xd7\x85\x63\xc2\x49\xe1\xb4\xf0\x96\x70\x5e\xb8\x20\xbc\x27\xbc\x2f\x5c\x15\x3e\x14\x6e\x0a\x1f\x0b\x9f\x0a\x9f\x0b\x5f\x0a\x0f\x62\x39\xb1\x51\xb1\xa2\x58\x79\xac\x26\xd6\x18\x6b\x89\x75\xc4\x7a\x62\xb3\x63\x7d\xb1\xc5\xb1\x67\x62\x2b\x62\xab\x63\xcf\xc6\x36\xc4\x36\xc7\xb6\xc5\x76\xc6\x76\xc7\x5e\x88\xed\x8d\xbd\x12\x3b\x10\x3b\x14\x3b\x12\x3b\x1e\x3b\x15\x3b\x13\x3b\x1b\x7b\x3b\x76\x31\x76\x29\x76\x25\x76\x2d\x76\x23\x76\x2b\x76\x27\x76\x37\x76\x2f\xf6\x95\x08\x44\x5c\x91\x40\x24\x11\x29\x45\x3a\x91\x49\x64\x15\xb9\x44\x19\x22\xaf\xa8\x50\x54\x22\x2a\x13\x55\x8a\x6a\x44\x75\xa2\x46\x51\x8b\xa8\x5d\xd4\x25\x3a\x2f\xba\x28\xea\x13\xf5\x8b\xae\x89\x86\x45\xa3\xa2\x09\xd1\x0d\xd1\x4d\xd1\x9c\xe8\x8e\xe8\xae\x68\x59\xf4\x40\xb4\x2e\x7a\x24\xda\x16\x3d\x11\x3d\x13\xbd\x10\xed\x8b\x29\x31\x5f\x2c\x14\x33\x62\xb5\x58\x2f\x36\x8b\x6d\x62\xb7\x38\x4b\x9c\x27\x2e\x12\x97\x8a\xcb\xc5\x55\xe2\x5a\x71\xbd\xb8\x49\xdc\x2a\xee\x10\x9f\x13\xf7\x88\x2f\x89\x2f\x8b\xaf\x8a\x07\xc5\xd7\xc5\x63\xe2\x49\xf1\xb4\xf8\x96\x78\x5e\xbc\x20\xbe\x27\xbe\x2f\x5e\x15\x3f\x14\x6f\x8a\x1f\x8b\x9f\x8a\x9f\x8b\x5f\x8a\x0f\x24\x1c\x49\x94\x44\x24\x91\x4b\x34\x12\xa3\xc4\x22\x71\x48\x3c\x92\x6c\x89\x4f\x52\x2c\x39\x23\xa9\x90\x54\x4b\xce\x4a\x1a\x24\xcd\x92\x36\x49\xa7\xa4\x5b\x72\x41\xd2\x2b\xb9\x22\x19\x90\x0c\x49\x46\x24\xe3\x92\x29\xc9\x8c\x64\x56\x72\x5b\xb2\x28\x59\x92\xac\x48\xd6\x24\x1b\x92\x2d\xc9\x8e\x64\x57\xb2\x27\x79\x25\x05\x29\x57\x2a\x90\x4a\xa4\x4a\xa9\x4e\x6a\x92\x5a\xa5\x2e\x69\x86\xd4\x2b\x2d\x94\x96\x48\xcb\xa4\x95\xd2\x1a\x69\x9d\xb4\x51\xda\x22\x6d\x97\x76\x49\xcf\x4b\x2f\x4a\xfb\xa4\xfd\xd2\x6b\xd2\x61\xe9\xa8\x74\x42\x7a\x43\x7a\x53\x3a\x27\xbd\x23\xbd\x2b\x5d\x96\x3e\x90\xae\x4b\x1f\x49\xb7\xa5\x4f\xa4\xcf\xa4\x2f\xa4\xfb\x0c\xc5\xf0\x19\x21\xc3\x30\x6a\x46\xcf\x98\x19\x1b\xe3\x66\xb2\x98\x3c\xa6\x88\x29\x65\xca\x99\x2a\xa6\x96\xa9\x67\x9a\x98\x56\xa6\x83\x39\xc7\xf4\x30\x97\x98\xcb\xcc\x55\x66\x90\xb9\xce\x8c\x31\x93\xcc\x34\x73\x8b\x99\x67\x16\x98\x7b\xcc\x7d\x66\x95\x79\xc8\x6c\x32\x8f\x99\xa7\xcc\x73\xe6\x25\x73\x20\xe3\xc8\xa2\x64\x22\x99\x5c\xa6\x91\x19\x65\x16\x99\x43\xe6\x91\x65\xcb\x7c\xb2\x62\xd9\x19\x59\x85\xac\x5a\x76\x56\xd6\x20\x6b\x96\xb5\xc9\x3a\x65\xdd\xb2\x0b\xb2\x5e\xd9\x15\xd9\x80\x6c\x48\x36\x22\x1b\x97\x4d\xc9\x66\x64\xb3\xb2\xdb\xb2\x45\xd9\x92\x6c\x45\xb6\x26\xdb\x90\x6d\xc9\x76\x64\xbb\xb2\x3d\xd9\x2b\x39\xc8\xb9\x72\x81\x5c\x22\x57\xca\x75\x72\x93\xdc\x2a\x77\xc9\x33\xe4\x5e\x79\xa1\xbc\x44\x5e\x26\xaf\x94\xd7\xc8\xeb\xe4\x8d\xf2\x16\x79\xbb\xbc\x4b\x7e\x5e\x7e\x51\xde\x27\xef\x97\x5f\x93\x0f\xcb\x47\xe5\x13\xf2\x1b\xf2\x9b\xf2\x39\xf9\x1d\xf9\x5d\xf9\xb2\xfc\x81\x7c\x5d\xfe\x48\xbe\x2d\x7f\x22\x7f\x26\x7f\x21\xdf\x57\x50\x0a\xbe\x42\xa8\x60\x14\x6a\x85\x5e\x61\x56\xd8\x14\x6e\x45\x96\x22\x4f\x51\xa4\x28\x55\x94\x2b\xaa\x14\xb5\x8a\x7a\x45\x93\xa2\x55\xd1\xa1\x38\xa7\xe8\x51\x5c\x52\x5c\x56\x5c\x55\x0c\x2a\xae\x2b\xc6\x14\x93\x8a\x69\xc5\x2d\xc5\xbc\x62\x41\x71\x4f\x71\x5f\xb1\xaa\x78\xa8\xd8\x54\x3c\x56\x3c\x55\x3c\x57\xbc\x54\x1c\x28\x39\xca\x28\xa5\x48\x29\x57\x6a\x94\x46\xa5\x45\xe9\x50\x7a\x94\xd9\x4a\x9f\xb2\x58\x79\x46\x59\xa1\xac\x56\x9e\x55\x36\x28\x9b\x95\x6d\xca\x4e\x65\xb7\xf2\x82\xb2\x57\x79\x45\x39\xa0\x1c\x52\x8e\x28\xc7\x95\x53\xca\x19\xe5\xac\xf2\xb6\x72\x51\xb9\xa4\x5c\x51\xae\x29\x37\x94\x5b\xca\x1d\xe5\xae\x72\x4f\xf9\x4a\x05\x2a\xae\x4a\xa0\x92\xa8\x94\x2a\x9d\xca\xa4\xb2\xaa\x5c\xaa\x0c\x95\x57\x55\xa8\x2a\x51\x95\xa9\x2a\x55\x35\xaa\x3a\x55\xa3\xaa\x45\xd5\xae\xea\x52\x9d\x57\x5d\x04\x44\xff\x37\xa2\x87\xbd\x8d\x69\x0f\x30\x80\xa8\x79\xdc\x39\xc6\xfd\x6c\x5a\xe0\xa7\x1c\x27\xee\x2b\xdb\x30\xee\x3e\x98\x02\x44\xef\x60\x79\x2c\x19\xd1\x85\x65\xea\x82\xf2\xe4\xb3\xac\x64\xa0\x3b\xbe\x16\x7c\xca\x5f\xc5\x00\xe2\xac\x63\x99\x51\x8c\xfc\x08\xf3\x7a\x4c\x1b\xd9\x1e\x33\xa6\x45\x04\x52\x1d\x98\x43\x89\x3f\x07\xfb\x29\x8b\xc3\x8f\x31\xb5\x60\xa4\x36\x88\x44\x3c\x38\xf2\xec\xaf\x1f\x30\x80\x68\xca\x4f\x59\x99\x40\xdf\x7d\x2c\x28\xc9\x76\xe5\xd9\x99\xb3\xf3\x81\x2e\x3c\x22\xd6\xc0\xda\xed\xe3\x69\x44\x01\x6b\x4f\xfc\xd4\x7c\x70\xd5\x24\x65\xed\x79\x94\xb2\xbb\x40\xda\xf3\xe3\x69\x58\xfd\x3f\x0a\xee\x05\xb5\x12\x5c\xdd\xc7\x53\xce\x53\xfc\xec\x66\x70\xbd\x47\x69\xc0\xda\x47\xe8\xd1\x9d\xfa\x78\x1a\x6e\x0e\xac\xb5\xd9\x9d\x62\xf9\x80\x6d\x1b\x09\x3b\xb3\xfc\xef\xe2\x37\x7d\x72\x3f\x0d\xf8\x70\x11\xe1\xcf\x1f\xcf\x63\x3b\x07\x66\x4b\xf2\xf3\xc4\x3c\xc3\xf1\x2b\x78\xc4\x09\x4c\x09\x3c\xb0\x23\xac\x67\x86\xe1\x39\x4d\x90\xf9\x96\x77\x12\x96\x27\xf8\xc0\x59\xfb\xf1\xc7\xf2\x78\xd5\x30\xe4\xa7\x24\x4e\xdd\xf3\x9f\x50\x2a\x0b\xdb\x10\x9f\xd6\xc0\xb9\x60\xfd\xb9\x36\x48\x03\x27\xfd\xc7\x7f\x17\x3e\xe0\x9f\x8d\x1f\xc7\xd3\xfb\x98\x0e\xe2\xf9\x4c\x10\x76\x20\x6d\x45\xf2\x13\xf8\xec\x7c\x13\xd3\xf2\xe0\x19\xf4\xdf\xac\x00\x71\x86\xf1\xe8\xcb\x78\xc7\x77\x08\x3b\xb0\xb1\x65\xe1\x08\xbf\x89\x2d\x73\x09\x53\x12\x1f\xf3\xcf\x04\x95\x62\xba\x06\xc1\xf7\x72\x04\xcf\xae\x94\xf4\x87\x77\xe1\xf1\x0c\xf5\x7e\x1a\x88\x6f\x3b\xc4\x79\xc4\xfe\x4c\xc6\xba\x80\x05\xc2\xf0\xec\xde\x05\x22\x21\x9e\x7f\x20\x62\xb3\xc8\x4c\x90\xf7\xdf\x15\x8f\xf5\x70\x0d\x8e\xea\x13\x84\x77\xb1\x31\x01\xbf\xb7\xa4\xca\x82\x1a\xc0\x8b\xe7\xa6\x0c\xee\x14\x9a\xc5\x5e\x3a\x0d\x6f\xa3\x22\xeb\x69\xa4\x2f\xb1\xbb\x40\x97\xf8\x29\xb7\x3d\xe8\x03\xd4\x2e\x8e\xb4\x82\xc3\x7b\xcd\xdd\xc0\x32\xff\xd1\xff\x53\xc4\xbe\x59\x65\x63\xf2\xd2\xeb\x34\x40\x94\x8b\x98\xe1\x43\xcc\x9f\xc7\xb3\xba\x84\xed\x60\x21\xf6\x48\x1b\x8c\xae\x01\x7f\x63\xe7\x8c\x33\x0b\xfa\x2f\x41\x6b\x93\xf6\xa4\x38\x84\xf5\x0c\x84\xcf\x8c\x05\x67\xc2\xc7\x36\xe1\x61\x8b\x71\xd9\x5c\xb6\x83\xb3\xde\x6a\x30\xef\x44\x5c\xf6\x23\x11\x23\xd8\x3e\xc3\x87\x63\x14\x79\x1e\xc9\xb5\x93\xb3\xf5\xdf\xf1\xdf\x64\x0a\x36\xea\x86\x8d\x1e\x84\xb5\xa9\x19\x1c\x73\xf8\x98\x92\x3c\x1f\xeb\xec\xc6\xa7\x1e\xfb\xcc\x31\xab\x20\x74\x46\xd8\x82\xeb\x0d\x39\xb3\x61\x22\x6d\xb8\x48\x18\x2e\x3a\x85\x3d\xe9\xc4\xc9\x25\xf9\x70\xa7\x29\x70\x8a\xfb\x0f\xaf\x91\x8c\x96\xf4\xdf\x60\xff\x59\x25\xb2\x2d\x3b\xb7\xeb\x10\xac\x46\xc8\xdd\xf9\x1e\xf6\xa8\xef\x1f\x8e\x48\x21\x27\x14\xdb\x8d\x93\x0f\xc1\x77\xf2\x0c\xb6\x1b\x83\x77\x8d\x09\xea\x0c\x39\x71\x6c\xe6\x65\xeb\x9c\x44\x3c\x9f\x0c\xac\x4d\x8e\x71\x3e\x71\x7e\xe7\x09\x0d\xc4\x9c\xc9\x88\xcd\x79\xca\xee\x7e\xd0\x07\x02\x76\x26\xe6\xc9\x9e\x97\x90\x7a\x89\x8d\x06\x4d\xc1\x59\xd1\x4b\xc1\x4a\x09\x2d\x1f\xa6\x01\xab\x2e\x04\x29\x1b\x19\x02\x91\x87\x4f\x50\xf6\x93\x0e\x4d\x78\x45\x38\xda\xb0\x75\xd4\xdb\xb8\x57\xf2\x76\x86\x44\xac\x40\x69\x98\x7e\x06\x53\x1f\x1b\xcd\xb0\x25\x71\x6d\x16\xf1\x59\xbf\x86\x08\x26\x38\x43\xfa\x0e\xe6\x07\x83\x36\x89\x38\x8d\xf7\xc2\x81\x11\xb1\x5f\x9e\x62\x3f\x83\xc0\xd2\x96\x60\xb5\x80\x6c\xc1\x39\xc0\x5f\xe2\xb9\xb1\x7a\xe2\xf1\xe8\x1c\xfc\x53\x26\x48\xd9\xf9\x40\x2c\xe6\xed\xc1\x19\x86\xd4\x30\x7d\x78\x56\x79\x78\x26\x19\x41\x9e\xf5\x10\x5a\x1f\xf0\x22\xe6\xcd\xb3\x01\x9a\x4c\xd8\xf9\x1b\x47\xce\x35\xab\x39\x3b\x68\x6d\xfa\x0a\x61\xf3\x6a\xbc\xc6\x7f\x14\xb4\x30\xa9\x2d\xe2\x19\xa6\x11\x7e\x49\xee\x3f\xc3\x11\x7e\x07\x8f\xfe\x18\xfb\xcc\x9f\x60\x5b\x7d\x2d\x58\x09\x07\xe2\xc6\x1c\xe6\xd9\x93\x2e\x27\xce\xcb\x40\xd0\x7f\xd8\xba\x9a\xac\x99\x03\x35\x18\x51\xe3\x91\xd5\x72\x60\x15\x45\x78\xac\x36\xea\xe6\x9b\x35\x72\x0d\x84\xfc\x6c\x50\x4f\x48\x05\x38\x80\x3f\x97\xa5\xf7\x53\xb4\xe9\xa7\x01\x1f\x9b\xf7\xf3\x70\xd9\x4f\x23\xba\x82\x32\x6f\xab\x41\xbf\xfc\x1c\x46\xf0\x0e\x52\x1a\xfc\xec\x40\x40\xc3\x45\x40\x1c\x35\x41\xef\x63\x9b\xf4\x06\x11\x54\x8a\x35\xa7\x61\xf9\x22\x8c\x74\x63\x6d\xf7\x30\xce\x04\x65\x42\xa2\x1f\x99\x73\xf9\x07\x4b\xfe\xac\xe1\xa7\x94\xeb\x60\x07\x23\x3b\x6f\xaa\xfd\x40\xe5\x4c\xd6\x93\x1a\xbf\x64\x80\x2f\xc2\x92\xec\x53\x1a\x5c\x27\xbc\xc1\xdb\x7e\x66\xfd\xc9\x27\xa2\xbd\xe6\x60\xf4\x2d\x95\x04\x90\xb6\x37\xb1\x8e\xdd\xc7\x90\x9a\x33\x4c\x9d\x79\x12\x1e\xe9\xfd\xa3\xc0\x9e\x9f\x86\x44\x78\xb2\x9e\x24\x33\x54\x35\x5e\x5d\xb6\x9f\xa2\x27\xfe\xb5\xc3\x24\xb6\x18\xc9\x1f\xf8\x7f\x0a\xaf\xb0\xcc\x1e\x9e\xf9\x88\x9f\xb2\x77\xc9\x40\x64\x08\xc3\x87\xab\x36\xa9\x09\x62\x2f\x26\x82\xb6\xfa\x19\x35\xe7\x11\x3e\x60\x43\xd6\xdf\x08\xfe\x98\xcc\x75\x13\xef\x2c\xc1\xb3\xfb\x0b\x37\xd9\x75\x11\xe7\x65\x19\xaf\xba\x89\xf5\x1c\x38\xbe\x5e\x9d\x25\x64\xc8\xba\xb4\x1f\x23\x3e\x4c\x97\xb1\xe6\x6e\x4c\x17\x70\x66\x6c\xc2\x2b\x6d\x39\xa8\xc5\x96\xf4\xfb\xde\xb7\x08\xdf\x18\x08\xfa\x46\xd8\x0c\x7b\x40\x44\x6c\x62\x9e\x64\xed\xfa\xae\x3c\x7b\xa3\x0f\xdc\xe5\x09\x9e\xcc\x5c\x64\x55\x16\x18\xf7\x2c\xa6\x9b\xc1\x35\x52\x1a\xcc\x8f\x11\x36\xef\x22\x6e\xfd\xcc\xc7\xde\x0d\x7f\x41\x3c\xda\x0c\xec\xd4\xd2\x09\xef\x92\x27\xe0\x49\x9d\xe4\x19\x84\x5d\x7c\xa6\x46\xf0\x58\x03\x98\xe2\xe8\xf4\xae\x3e\x1f\x92\x95\x3e\x81\x1e\xf2\x59\xaa\x9a\x88\x7b\x9f\xe4\x3e\x45\xe8\x09\xa9\xd0\xc6\xf1\xda\x89\xfb\xd4\x31\xfc\x2b\xac\xe7\x0e\x1c\x7f\x93\xdd\x23\x3c\xf6\x4d\x9c\x67\xde\xd6\x45\x7f\x88\x3f\x1b\x1d\xfa\x19\x99\x0b\x30\x08\x1e\x18\x82\x59\xf8\x15\x98\x43\xe7\xa0\x19\x9d\x47\x5f\x47\x29\xe8\x12\xba\x86\x9c\xe8\xdb\xe8\xdb\xc8\x87\xc6\xd0\x9f\xa0\x02\xb4\x80\x7e\x8c\xfe\x01\xda\x40\xff\x0d\x7d\x05\x3d\x43\xff\x0f\xfa\x3a\xda\xa3\xbe\x82\x7e\x3b\xe2\x97\x22\x7e\x9d\x42\x11\xe3\xdc\x02\xca\xc5\x3d\xcd\x1d\xa6\x96\x79\xbb\xbc\x5d\xda\xcc\xff\x55\xfe\xaf\xd2\x49\xfc\xb3\xfc\x06\xda\xc2\xff\x32\xff\xcb\xb4\x93\xdf\xce\x6f\xa7\x5d\xf8\x33\x32\x4f\xde\x7e\xf6\x12\xd7\x40\x69\x23\x69\x3a\xa0\xd2\x26\x41\x40\xa7\x0a\xee\x0a\x96\x05\x0f\x04\xeb\x82\x47\x82\x6d\xc1\x13\xc1\x33\xc1\x0b\xc1\x7e\x0c\x15\xc3\x8f\x11\xc6\x30\x31\xea\x18\x7d\x8c\x39\xc6\x16\xe3\x8e\xc9\x8a\xc9\x8b\x29\x8a\x29\x8d\x29\x8f\xa9\x8a\xa9\x8d\xa9\x8f\x69\x8a\x69\x8d\xe9\x88\x39\x17\xd3\x13\x73\x29\xe6\x72\xcc\xd5\x98\xc1\x98\xeb\x31\x63\x31\x93\x31\xd3\x31\xb7\x62\xe6\x63\x16\x62\xee\xc5\xdc\x8f\x59\x8d\x79\x18\xb3\x19\xf3\x38\xe6\x69\xcc\xf3\x98\x97\x31\x07\x42\x8e\x30\x4a\x28\x12\xca\x85\x1a\xa1\x51\x68\x11\x3a\x84\x1e\x61\xb6\xd0\x27\x2c\x16\x9e\x11\x56\x08\xab\x85\x67\x85\x0d\xc2\x66\x61\x9b\xb0\x53\xd8\x2d\xbc\x20\xec\x15\x5e\x11\x0e\x08\x87\x84\x23\xc2\x71\xe1\x94\x70\x46\x38\x2b\xbc\x2d\x5c\x14\x2e\x09\x57\x84\x6b\xc2\x0d\xe1\x96\x70\x47\xb8\x2b\xdc\x13\xbe\x8a\x85\x58\x6e\xac\x20\x56\x12\xab\x8c\xd5\xc5\x9a\x62\xad\xb1\xae\xd8\x8c\x58\x6f\x6c\x61\x6c\x49\x6c\x59\x6c\x65\x6c\x4d\x6c\x5d\x6c\x63\x6c\x4b\x6c\x7b\x6c\x57\xec\xf9\xd8\x8b\xb1\x7d\xb1\xfd\xb1\xd7\x62\x87\x63\x47\x63\x27\x62\x6f\xc4\xde\x8c\x9d\x8b\xbd\x13\x7b\x37\x76\x39\xf6\x41\xec\x7a\xec\xa3\xd8\xed\xd8\x27\xb1\xcf\x62\x5f\xc4\xee\x8b\x28\x11\x5f\x24\x14\x31\x22\xb5\x48\x2f\x32\x8b\x6c\x22\xb7\x28\x4b\x94\x27\x2a\x12\x95\x8a\xca\x45\x55\xa2\x5a\x51\xbd\xa8\x49\xd4\x2a\xea\x10\x9d\x13\xf5\x88\x2e\x89\x2e\x8b\xae\x8a\x06\x45\xd7\x45\x63\xa2\x49\xd1\xb4\xe8\x96\x68\x5e\xb4\x20\xba\x27\xba\x2f\x5a\x15\x3d\x14\x6d\x8a\x1e\x8b\x9e\x8a\x9e\x8b\x5e\x8a\x0e\xc4\x1c\x71\x94\x58\x24\x96\x8b\x35\x62\xa3\xd8\x22\x76\x88\x3d\xe2\x6c\xb1\x4f\x5c\x2c\x3e\x23\xae\x10\x57\x8b\xcf\x8a\x1b\xc4\xcd\xe2\x36\x71\xa7\xb8\x5b\x7c\x41\xdc\x2b\xbe\x22\x1e\x10\x0f\x89\x47\xc4\xe3\xe2\x29\xf1\x8c\x78\x56\x7c\x5b\xbc\x28\x5e\x12\xaf\x88\xd7\xc4\x1b\xe2\x2d\xf1\x8e\x78\x57\xbc\x27\x7e\x25\x01\x09\x57\x22\x90\x48\x24\x4a\x89\x4e\x62\x92\x58\x25\x2e\x49\x86\xc4\x2b\x29\x94\x94\x48\xca\x24\x95\x92\x1a\x49\x9d\xa4\x51\xd2\x22\x69\x97\x74\x49\xce\x4b\x2e\x4a\xfa\x24\xfd\x92\x6b\x92\x61\xc9\xa8\x64\x42\x72\x43\x72\x53\x32\x27\xb9\x23\xb9\x2b\x59\x96\x3c\x90\xac\x4b\x1e\x49\xb6\x25\x4f\x24\xcf\x24\x2f\x24\xfb\x52\x4a\xca\x97\x0a\xa5\x8c\x54\x2d\xd5\x4b\xcd\x52\x9b\xd4\x2d\xcd\x92\xe6\x49\x8b\xa4\xa5\xd2\x72\x69\x95\xb4\x56\x5a\x2f\x6d\x92\xb6\x4a\x3b\xa4\xe7\xa4\x3d\xd2\x4b\xd2\xcb\xd2\xab\xd2\x41\xe9\x75\xe9\x98\x74\x52\x3a\x2d\xbd\x25\x9d\x97\x2e\x48\xef\x49\xef\x4b\x57\xa5\x0f\xa5\x9b\xd2\xc7\xd2\xa7\xd2\xe7\xd2\x97\xd2\x03\x86\xc3\x44\x31\x22\x46\xce\x68\x18\x23\x63\x61\x1c\x8c\x87\xc9\x66\x7c\x4c\x31\x73\x86\xa9\x60\xaa\x99\xb3\x4c\x03\xd3\xcc\xb4\x31\x9d\x4c\x37\x73\x81\xe9\x65\xae\x30\x03\xcc\x10\x33\xc2\x8c\x33\x53\xcc\x0c\x33\xcb\xdc\x66\x16\x99\x25\x66\x85\x59\x63\x36\x98\x2d\x66\x87\xd9\x65\xf6\x98\x57\x32\x90\x71\x65\x02\x99\x44\xa6\x94\xe9\x64\x26\x99\x55\xe6\x92\x65\xc8\xbc\xb2\x42\x59\x89\xac\x4c\x56\x29\xab\x91\xd5\xc9\x1a\x65\x2d\xb2\x76\x59\x97\xec\xbc\xec\xa2\xac\x4f\xd6\x2f\xbb\x26\x1b\x96\x8d\xca\x26\x64\x37\x64\x37\x65\x73\xb2\x3b\xb2\xbb\xb2\x65\xd9\x03\xd9\xba\xec\x91\x6c\x5b\xf6\x44\xf6\x4c\xf6\x42\xb6\x2f\xa7\xe4\x7c\xb9\x50\xce\xc8\xd5\x72\xbd\xdc\x2c\xb7\xc9\xdd\xf2\x2c\x79\x9e\xbc\x48\x5e\x2a\x2f\x97\x57\xc9\x6b\xe5\xf5\xf2\x26\x79\xab\xbc\x43\x7e\x4e\xde\x23\xbf\x24\xbf\x2c\xbf\x2a\x1f\x94\x5f\x97\x8f\xc9\x27\xe5\xd3\xf2\x5b\xf2\x79\xf9\x82\xfc\x9e\xfc\xbe\x7c\x55\xfe\x50\xbe\x29\x7f\x2c\x7f\x2a\x7f\x2e\x7f\x29\x3f\x50\x70\x14\x51\x0a\x91\x42\xae\xd0\x28\x8c\x0a\x8b\xc2\xa1\xf0\x28\xb2\x15\x3e\x45\xb1\xe2\x8c\xa2\x42\x51\xad\x38\xab\x68\x50\x34\x2b\xda\x14\x9d\x8a\x6e\xc5\x05\x45\xaf\xe2\x8a\x62\x40\x31\xa4\x18\x51\x8c\x2b\xa6\x14\x33\x8a\x59\xc5\x6d\xc5\xa2\x62\x49\xb1\xa2\x58\x53\x6c\x28\xb6\x14\x3b\x8a\x5d\xc5\x9e\xe2\x95\x12\x94\x5c\xa5\x40\x29\x51\x2a\x95\x3a\xa5\x49\x69\x55\xba\x94\x19\x4a\xaf\xb2\x50\x59\xa2\x2c\x53\x56\x2a\x6b\x94\x75\xca\x46\x65\x8b\xb2\x5d\xd9\xa5\x3c\xaf\xbc\xa8\xec\x53\xf6\x2b\xaf\x29\x87\x95\xa3\xca\x09\xe5\x0d\xe5\x4d\xe5\x9c\xf2\x8e\xf2\xae\x72\x59\xf9\x40\xb9\xae\x7c\xa4\xdc\x56\x3e\x51\x3e\x53\xbe\x50\xee\xab\x28\x15\x5f\x25\x54\x31\x2a\xb5\x4a\xaf\x32\xab\x6c\x2a\xb7\x2a\x4b\x95\xa7\x2a\x52\x95\xaa\xca\x55\x55\xaa\x5a\x55\xbd\xaa\x49\xd5\xaa\xea\x50\x9d\x53\xf5\xa8\x2e\xa9\x2e\xab\xae\xaa\x06\x55\xd7\x55\x63\xaa\x49\xd5\xb4\xea\x96\x6a\x5e\xb5\xa0\xba\xa7\xba\xaf\x5a\x55\x3d\x54\x6d\xaa\x1e\xab\x9e\xaa\x9e\xab\x5e\xaa\x0e\xd4\x1c\x75\x94\x5a\xa4\x96\xab\x35\x6a\xa3\xda\xa2\x76\xa8\x3d\xea\x6c\xb5\x4f\x5d\xac\x3e\xa3\xae\x50\x57\xab\xcf\xaa\x1b\xd4\xcd\xea\x36\x75\xa7\xba\x5b\x7d\x41\xdd\xab\xbe\xa2\x1e\x50\x0f\xa9\x47\xd4\xe3\xea\x29\xf5\x8c\x7a\x56\x7d\x5b\xbd\xa8\x5e\x52\xaf\xa8\xd7\xd4\x1b\xea\x2d\xf5\x8e\x7a\x57\xbd\xa7\x7e\x15\x07\x71\xdc\x38\x41\x9c\x24\x4e\x19\xa7\x8b\x33\xc5\x59\xe3\x5c\x71\x19\x71\xde\xb8\xc2\xb8\x92\xb8\xb2\xb8\xca\xb8\x9a\xb8\xba\xb8\xc6\xb8\x96\xb8\xf6\xb8\xae\xb8\xf3\x71\x17\xe3\xfa\xe2\xfa\xe3\xae\xc5\x0d\xc7\x8d\xc6\x4d\xc4\xdd\x88\xbb\x19\x37\x17\x77\x27\xee\x6e\xdc\x72\xdc\x83\xb8\xf5\xb8\x47\x71\xdb\x71\x4f\xe2\x9e\xc5\xbd\x88\xdb\xd7\x50\x1a\xbe\x46\xa8\x61\x34\x6a\x8d\x5e\x63\xd6\xd8\x34\x6e\x4d\x96\x26\x4f\x53\xa4\x29\xd5\x94\x6b\xaa\x34\xb5\x9a\x7a\x4d\x93\xa6\x55\xd3\xa1\x39\xa7\xe9\xd1\x5c\xd2\x5c\xd6\x5c\xd5\x0c\x6a\xae\x6b\xc6\x34\x93\x9a\x69\xcd\x2d\xcd\xbc\x66\x41\x73\x4f\x73\x5f\xb3\xaa\x79\xa8\xd9\xd4\x3c\xd6\x3c\xd5\x3c\xd7\xbc\xd4\x1c\x68\x39\xda\x28\xad\x48\x2b\xd7\x6a\xb4\x46\xad\x45\xeb\xd0\x7a\xb4\xd9\x5a\x9f\xb6\x58\x7b\x46\x5b\xa1\xad\xd6\x9e\xd5\x36\x68\x9b\xb5\x6d\xda\x4e\x6d\xb7\xf6\x82\xb6\x57\x7b\x45\x3b\xa0\x1d\xd2\x8e\x68\xc7\xb5\x53\xda\x19\xed\xac\xf6\xb6\x76\x51\xbb\xa4\x5d\xd1\xae\x69\x37\xb4\x5b\xda\x1d\xed\xae\x76\x4f\xfb\x4a\x07\x3a\xae\x4e\xa0\x93\xe8\x94\x3a\x9d\xce\xa4\xb3\xea\x5c\xba\x0c\x9d\x57\x57\xa8\x2b\xd1\x95\xe9\x2a\x75\x35\xba\x3a\x5d\xa3\xae\x45\xd7\xae\xeb\xd2\x9d\xd7\x5d\xd4\xf5\xe9\xfa\x75\xd7\x74\xc3\xba\x51\xdd\x84\xee\x86\xee\xa6\x6e\x4e\x77\x47\x77\x57\xb7\xac\x7b\xa0\x5b\xd7\x3d\xd2\x6d\xeb\x9e\xe8\x9e\xe9\x5e\xe8\xf6\xe3\xa9\x78\x7e\xbc\x30\x9e\x89\x57\xc7\xeb\xe3\xcd\xf1\xb6\x78\x77\x7c\x56\x7c\x5e\x7c\x51\x7c\x69\x7c\x79\x7c\x55\x7c\x6d\x7c\x7d\x7c\x53\x7c\x6b\x7c\x47\xfc\xb9\xf8\x9e\xf8\x4b\xf1\x97\xe3\xaf\xc6\x0f\xc6\x5f\x8f\x1f\x8b\x9f\x8c\x9f\x8e\xbf\x15\x3f\x1f\xbf\x10\x7f\x2f\xfe\x7e\xfc\x6a\xfc\xc3\xf8\xcd\xf8\xc7\xf1\x4f\xe3\x9f\xc7\xbf\x8c\x3f\xd0\x73\xf4\x51\x7a\x91\x5e\xae\xd7\xe8\x8d\x7a\x8b\xde\xa1\xf7\xe8\xb3\xf5\x3e\x7d\xb1\xfe\x8c\xbe\x42\x5f\xad\x3f\xab\x6f\xd0\x37\xeb\xdb\xf4\x9d\xfa\x6e\xfd\x05\x7d\xaf\xfe\x8a\x7e\x40\x3f\xa4\x1f\xd1\x8f\xeb\xa7\xf4\x33\xfa\x59\xfd\x6d\xfd\xa2\x7e\x49\xbf\xa2\x5f\xd3\x6f\xe8\xb7\xf4\x3b\xfa\x5d\xfd\x9e\xfe\x95\x01\x0c\x5c\x83\xc0\x20\x31\x28\x0d\x3a\x83\xc9\x60\x35\xb8\x0c\x19\x06\xaf\xa1\xd0\x50\x62\x28\x33\x54\x1a\x6a\x0c\x75\x86\x46\x43\x8b\xa1\xdd\xd0\x65\x38\x6f\xb8\x68\xe8\x33\xf4\x1b\xae\x19\x86\x0d\xa3\x86\x09\xc3\x0d\xc3\x4d\xc3\x9c\xe1\x8e\xe1\xae\x61\xd9\xf0\xc0\xb0\x6e\x78\x64\xd8\x36\x3c\x31\x3c\x33\xbc\x30\xec\x1b\x29\x23\xdf\x28\x34\x32\x46\xb5\x51\x6f\x34\x1b\x6d\x46\xb7\x31\xcb\x98\x67\x2c\x32\x96\x1a\xcb\x8d\x55\xc6\x5a\x63\xbd\xb1\xc9\xd8\x6a\xec\x30\x9e\x33\xf6\x18\x2f\x19\x2f\x1b\xaf\x1a\x07\x8d\xd7\x8d\x63\xc6\x49\xe3\xb4\xf1\x96\x71\xde\xb8\x60\xbc\x67\xbc\x6f\x5c\x35\x3e\x34\x6e\x1a\x1f\x1b\x9f\x1a\x9f\x1b\x5f\x1a\x0f\x12\x38\x09\x51\x09\xa2\x04\x79\x82\x26\xc1\x98\x60\x49\x70\x24\x78\x12\xb2\x13\x7c\x09\xc5\x09\x67\x12\x2a\x12\xaa\x13\xce\x26\x34\x24\x34\x27\xb4\x25\x74\x26\x74\x27\x5c\x48\xe8\x4d\xb8\x92\x30\x90\x30\x94\x30\x92\x30\x9e\x30\x95\x30\x93\x30\x9b\x70\x3b\x61\x31\x61\x29\x61\x25\x61\x2d\x61\x23\x61\x2b\x61\x27\x61\x37\x61\x2f\xe1\x95\x09\x4c\x5c\x93\xc0\x24\x31\x29\x4d\x3a\x93\xc9\x64\x35\xb9\x4c\x19\x26\xaf\xa9\xd0\x54\x62\x2a\x33\x55\x9a\x6a\x4c\x75\xa6\x46\x53\x8b\xa9\xdd\xd4\x65\x3a\x6f\xba\x68\xea\x33\xf5\x9b\xae\x99\x86\x4d\xa3\xa6\x09\xd3\x0d\xd3\x4d\xd3\x9c\xe9\x8e\xe9\xae\x69\xd9\xf4\xc0\xb4\x6e\x7a\x64\xda\x36\x3d\x31\x3d\x33\xbd\x30\xed\x27\x52\x89\xfc\x44\x61\x22\x93\xa8\x4e\xd4\x27\x9a\x13\x6d\x89\xee\xc4\xac\xc4\xbc\xc4\xa2\xc4\xd2\xc4\xf2\xc4\xaa\xc4\xda\xc4\xfa\xc4\xa6\xc4\xd6\xc4\x8e\xc4\x73\x89\x3d\x89\x97\x12\x2f\x27\x5e\x4d\x1c\x4c\xbc\x9e\x38\x96\x38\x99\x38\x9d\x78\x2b\x71\x3e\x71\x21\xf1\x5e\xe2\xfd\xc4\xd5\xc4\x87\x89\x9b\x89\x8f\x13\x9f\x26\x3e\x4f\x7c\x99\x78\x60\xe6\x98\xa3\xcc\x22\xb3\xdc\xac\x31\x1b\xcd\x16\xb3\xc3\xec\x31\x67\x9b\x7d\xe6\x62\xf3\x19\x73\x85\xb9\xda\x7c\xd6\xdc\x60\x6e\x36\xb7\x99\x3b\xcd\xdd\xe6\x0b\xe6\x5e\xf3\x15\xf3\x80\x79\xc8\x3c\x62\x1e\x37\x4f\x99\x67\xcc\xb3\xe6\xdb\xe6\x45\xf3\x92\x79\xc5\xbc\x66\xde\x30\x6f\x99\x77\xcc\xbb\xe6\x3d\xf3\xab\x24\x48\xe2\x26\x09\x92\x24\x49\xca\x24\x5d\x92\x29\xc9\x9a\xe4\x4a\xca\x48\xf2\x26\x15\x26\x95\x24\x95\x25\x55\x26\xd5\x24\xd5\x25\x35\x26\xb5\x24\xb5\x27\x75\x25\x9d\x4f\xba\x98\xd4\x97\xd4\x9f\x74\x2d\x69\x38\x69\x34\x69\x22\xe9\x46\xd2\xcd\xa4\xb9\xa4\x3b\x49\x77\x93\x96\x93\x1e\x24\xad\x27\x3d\x4a\xda\x4e\x7a\x92\xf4\x2c\xe9\x45\xd2\xbe\x85\xb2\xf0\x2d\x42\x0b\x63\x51\x5b\xf4\x16\xb3\xc5\x66\x71\x5b\xb2\x2c\x79\x96\x22\x4b\xa9\xa5\xdc\x52\x65\xa9\xb5\xd4\x5b\x9a\x2c\xad\x96\x0e\xcb\x39\x4b\x8f\xe5\x92\xe5\xb2\xe5\xaa\x65\xd0\x72\xdd\x32\x66\x99\xb4\x4c\x5b\x6e\x59\xe6\x2d\x0b\x96\x7b\x96\xfb\x96\x55\xcb\x43\xcb\xa6\xe5\xb1\xe5\xa9\xe5\xb9\xe5\xa5\xe5\x20\x99\x93\x1c\x95\x2c\x4a\x96\x27\x6b\x92\x8d\xc9\x96\x64\x47\xb2\x27\x39\x3b\xd9\x97\x5c\x9c\x7c\x26\xb9\x22\xb9\x3a\xf9\x6c\x72\x43\x72\x73\x72\x5b\x72\x67\x72\x77\xf2\x85\xe4\xde\xe4\x2b\xc9\x03\xc9\x43\xc9\x23\xc9\xe3\xc9\x53\xc9\x33\xc9\xb3\xc9\xb7\x93\x17\x93\x97\x92\x57\x92\xd7\x92\x37\x92\xb7\x92\x77\x92\x77\x93\xf7\x92\x5f\x59\xc1\xca\xb5\x0a\xac\x12\xab\xd2\xaa\xb3\x9a\xac\x56\xab\xcb\x9a\x61\xf5\x5a\x0b\xad\x25\xd6\x32\x6b\xa5\xb5\xc6\x5a\x67\x6d\xb4\xb6\x58\xdb\xad\x5d\xd6\xf3\xd6\x8b\xd6\x3e\x6b\xbf\xf5\x9a\x75\xd8\x3a\x6a\x9d\xb0\xde\xb0\xde\xb4\xce\x59\xef\x58\xef\x5a\x97\xad\x0f\xac\xeb\xd6\x47\xd6\x6d\xeb\x13\xeb\x33\xeb\x0b\xeb\x7e\x0a\x95\xc2\x4f\x11\xa6\x30\x29\xea\x14\x7d\x8a\x39\xc5\x96\xe2\x4e\xc9\x4a\xc9\x4b\x29\x4a\x29\x4d\x29\x4f\xa9\x4a\xa9\x4d\xa9\x4f\x69\x4a\x69\x4d\xe9\x48\x39\x97\xd2\x93\x72\x29\xe5\x72\xca\xd5\x94\xc1\x94\xeb\x29\x63\x29\x93\x29\xd3\x29\xb7\x52\xe6\x53\x16\x52\xee\xa5\xdc\x4f\x59\x4d\x79\x98\xb2\x99\xf2\x38\xe5\x69\xca\xf3\x94\x97\x29\x07\x36\x8e\x2d\xca\x26\xb2\xc9\x6d\x1a\x9b\xd1\x66\xb1\x39\x6c\x1e\x5b\xb6\xcd\x67\x2b\xb6\x9d\xb1\x55\xd8\xaa\x6d\x67\x6d\x0d\xb6\x66\x5b\x9b\xad\xd3\xd6\x6d\xbb\x60\xeb\xb5\x5d\xb1\x0d\xd8\x86\x6c\x23\xb6\x71\xdb\x94\x6d\xc6\x36\x6b\xbb\x6d\x5b\xb4\x2d\xd9\x56\x6c\x6b\xb6\x0d\xdb\x96\x6d\xc7\xb6\x6b\xdb\xb3\xbd\xb2\x83\x9d\x6b\x17\xd8\x25\x76\xa5\x5d\x67\x37\xd9\xad\x76\x97\x3d\xc3\xee\xb5\x17\xda\x4b\xec\x65\xf6\x4a\x7b\x8d\xbd\xce\xde\x68\x6f\xb1\xb7\xdb\xbb\xec\xe7\xed\x17\xed\x7d\xf6\x7e\xfb\x35\xfb\xb0\x7d\xd4\x3e\x61\xbf\x61\xbf\x69\x9f\xb3\xdf\xb1\xdf\xb5\x2f\xdb\x1f\xd8\xd7\xed\x8f\xec\xdb\xf6\x27\xf6\x67\xf6\x17\xf6\x7d\x07\xe5\xe0\x3b\x84\x0e\xc6\xa1\x76\xe8\x1d\x66\x87\xcd\xe1\x76\x64\x39\xf2\x1c\x45\x8e\x52\x47\xb9\xa3\xca\x51\xeb\xa8\x77\x34\x39\x5a\x1d\x1d\x8e\x73\x8e\x1e\xc7\x25\xc7\x65\xc7\x55\xc7\xa0\xe3\xba\x63\xcc\x31\xe9\x98\x76\xdc\x72\xcc\x3b\x16\x1c\xf7\x1c\xf7\x1d\xab\x8e\x87\x8e\x4d\xc7\x63\xc7\x53\xc7\x73\xc7\x4b\xc7\x81\x93\xe3\x8c\x72\x8a\x9c\x72\xa7\xc6\x69\x74\x5a\x9c\x0e\xa7\xc7\x99\xed\xf4\x39\x8b\x9d\x67\x9c\x15\xce\x6a\xe7\x59\x67\x83\xb3\xd9\xd9\xe6\xec\x74\x76\x3b\x2f\x38\x7b\x9d\x57\x9c\x03\xce\x21\xe7\x88\x73\xdc\x39\xe5\x9c\x71\xce\x3a\x6f\x3b\x17\x9d\x4b\xce\x15\xe7\x9a\x73\xc3\xb9\xe5\xdc\x71\xee\x3a\xf7\x9c\xaf\x5c\xe0\xe2\xba\x04\x2e\x89\x4b\xe9\xd2\xb9\x4c\x2e\xab\xcb\xe5\xca\x70\x79\x5d\x85\xae\x12\x57\x99\xab\xd2\x55\xe3\xaa\x73\x35\xba\x5a\x5c\xed\xae\x2e\xd7\x79\xd7\x45\x57\x9f\xab\xdf\x75\xcd\x35\xec\x1a\x75\x4d\xb8\x6e\xb8\x6e\xba\xe6\x5c\x77\x5c\x77\x5d\xcb\xae\x07\xae\x75\xd7\x23\xd7\xb6\xeb\x89\xeb\x99\xeb\x85\x6b\x3f\x95\x4a\xe5\xa7\x0a\x53\x99\x54\x75\xaa\x3e\xd5\x9c\x6a\x4b\x75\xa7\x66\xa5\xe6\xa5\x16\xa5\x96\xa6\x96\xa7\x56\xa5\xd6\xa6\xd6\xa7\x36\xa5\xb6\xa6\x76\xa4\x9e\x4b\xed\x49\xbd\x94\x7a\x39\xf5\x6a\xea\x60\xea\xf5\xd4\xb1\xd4\xc9\xd4\xe9\xd4\x5b\xa9\xf3\xa9\x0b\xa9\xf7\x52\xef\xa7\xae\xa6\x3e\x4c\xdd\x4c\x7d\x9c\xfa\x34\xf5\x79\xea\xcb\xd4\x03\x37\xc7\x1d\xe5\x16\xb9\xe5\x6e\x8d\xdb\xe8\xb6\xb8\x1d\x6e\x8f\x3b\xdb\xed\x73\x17\xbb\xcf\xb8\x2b\xdc\xd5\xee\xb3\xee\x06\x77\xb3\xbb\xcd\xdd\xe9\xee\x76\x5f\x70\xf7\xba\xaf\xb8\x07\xdc\x43\xee\x11\xf7\xb8\x7b\xca\x3d\xe3\x9e\x75\xdf\x76\x2f\xba\x97\xdc\x2b\xee\x35\xf7\x86\x7b\xcb\xbd\xe3\xde\x75\xef\xb9\x5f\xa5\x41\x1a\x37\x4d\x00\x88\xf3\x5b\xec\x67\x5e\xfd\x94\xf3\x7d\x82\x9f\x09\xf2\x11\x55\x04\xae\x0d\xf2\xf4\x0f\x09\x99\x8f\x08\xfe\x2b\x41\x9e\x1a\x24\x78\x27\xa1\x87\x18\x97\xfe\x51\x90\xe7\xce\x11\x7a\x26\x08\xfe\x4f\x89\x67\x7f\x2f\x0c\x7e\x8d\xe0\xa3\x08\x9e\x22\xe4\x9b\x09\x9c\xe0\xb9\x3f\x26\xf0\x4c\x82\x97\x10\x7c\x3e\xc1\xff\x53\x82\x1f\x25\xd6\x32\x12\x06\x3f\x20\xec\x10\xe6\x59\x92\xa7\x44\xc7\xf3\xf4\x8b\xe3\x71\x1e\x84\xd1\xf9\xf5\x9f\x3d\x16\x4d\xec\x0b\xfd\x55\x42\xff\x44\x18\xf9\x79\xc2\x9e\xdf\x23\xf0\xbf\x38\x5e\x86\xfe\xe6\xf1\xfb\xfe\x49\x78\xee\xe0\xf1\xbe\x4a\xfa\xe7\x49\xf8\x10\xff\x3c\x01\x4f\x9e\x85\x70\xfe\xf9\x89\xf8\xe6\x77\xe3\x43\xfc\x93\x38\x17\x9c\xa9\x30\xbe\xfa\x09\x78\xee\x37\x8f\xf7\x73\xd2\xb7\x4f\xc2\x87\xf3\xed\x70\x3c\xe7\x9b\x27\xf0\xed\x4f\xc2\x87\x39\x17\x61\xcf\xcb\xfc\x09\xf0\xdf\x0a\x63\xcf\x77\xc5\x67\x8e\xb7\xf9\xfb\xc2\x43\x62\xfb\xe8\xcf\xc6\x43\xe2\xff\xc1\xff\x3c\x9c\xcc\x2f\x21\xf3\x7c\x5f\xf8\x57\xde\x0d\x0f\x89\x0f\xa2\xff\x79\x38\x87\xcc\x77\x06\x42\xc6\x19\x46\x9e\xcc\xb3\x2f\xc2\xf0\x3f\x3a\xfe\xd9\x4f\x84\xd7\xfd\x6c\xf9\x88\x30\xf9\xe5\x9d\x71\xe7\x09\x64\x48\xbb\x7d\xfd\xef\x8e\x73\x7f\x42\xf0\xbb\x84\x0c\x51\x7b\x90\xf9\xf4\x9d\x71\xa2\x6e\x21\x73\xf1\x7b\xc3\x89\x5a\x28\x24\xbf\xbf\x23\x1e\x92\x83\x46\x7f\xf1\x38\x59\xbf\x91\x35\x09\x99\x1f\x43\xe2\x73\x98\xba\x2e\xa4\x56\x79\x47\x9c\x2a\x0a\x33\xe7\x5a\x02\xff\xbd\xe3\x65\x38\xdf\x39\xde\x37\x42\x6a\x9b\x13\xc4\xf0\x88\xe7\x84\xfc\xef\x87\x19\xeb\xcb\xbc\x63\xe3\x6d\x44\x29\x81\x97\x11\x63\x11\x75\x3e\xa7\x89\x77\x7c\x2c\x25\xf6\x85\xc7\x25\x6c\xf2\x35\xde\xb1\x31\x2d\x5c\x5c\x0a\x89\x27\xc4\xf9\xe2\x11\xf5\xcc\x49\xce\x78\x04\x69\x4f\x22\x9f\xf2\x89\x73\xc1\x25\x62\x54\x44\x42\x18\x5b\x85\xb9\x53\x84\x9c\x29\x32\xf6\x56\xf3\x8e\x3f\x47\x15\x61\x70\xf2\x6e\x42\xde\xa7\x48\xfc\xcf\xc3\xec\x5d\x0e\x31\x9f\x67\x27\xf0\xdb\x9c\xe3\xf7\x97\x93\x4b\xc8\x93\x3e\xd6\x7c\xbc\xdf\x46\x12\x36\xe1\xff\x35\xc1\xa7\x12\xb6\x25\xe7\xff\x57\x84\x1e\x22\x67\xf1\xfe\x8c\xe0\x67\x89\x67\x67\x8e\xf7\x13\x72\x1f\xc3\xe5\xc7\xb0\xf1\x3c\x4c\xdc\xa0\x89\xf3\x42\xde\x29\xc8\x5a\x37\xc4\xcf\xa3\xc2\xe0\xa3\x3f\xdb\xb7\xdf\x35\xd7\x84\xec\xef\xad\xe3\xd7\x7b\x92\xbd\x08\x37\x4f\x1e\x99\x37\x05\xbc\x9f\x79\xbe\xde\xb9\x76\x7d\xc7\x1a\xef\x5d\x6b\xa1\x77\xb6\xe7\x3b\xe6\xe2\x77\xcd\x41\x61\x73\x28\x19\x4b\x89\x5a\x28\x6c\xcd\x39\x14\x06\x27\xef\xb0\x64\x6d\x1f\xee\xbc\xbf\xe3\xbe\x84\xb5\x5b\x98\x1c\x4a\x91\xbd\x1a\x22\x07\x51\xdf\x3d\x7e\xbf\x78\x69\xc7\xf3\x21\xf3\x0c\x93\xe3\x48\xbb\x91\x76\x26\xe3\x70\x08\x4f\xee\x29\x91\x83\xc8\x1e\x57\xc8\x3e\xfe\xd6\x09\xfc\x33\x4c\x8d\x4d\xc6\xed\x70\xb9\x23\xc4\xdf\xc2\xd5\x24\x4d\x61\xf6\xeb\x04\xbd\x26\xfa\xc7\x61\xe6\x40\xca\x13\x39\x82\x8c\x7b\x11\xc4\xb8\xf4\x30\xc1\x7f\x83\xd0\x43\xc4\x6a\xce\x47\xc7\xdb\x21\xec\xdd\xb9\xfa\xf8\xf5\xd2\xdf\x3d\xc1\xb3\xe1\x7a\x62\x64\x5d\x51\x43\xf0\x44\xed\x47\x4d\x12\xbc\x90\xd0\x49\xac\x9d\xec\x9b\x85\xe3\xc3\xce\x8d\x88\xb7\x21\x77\x04\x62\x6e\x5c\x3e\x61\xe7\xba\xe3\xfd\x81\x2e\x0b\x83\x87\xe1\xc9\xfe\x61\x48\x2f\xb1\xfc\x78\x3e\xa4\xa7\x27\x09\xc3\x8b\xc2\xe0\x13\xc7\xf3\x61\xfb\x30\xdf\x3f\x7e\xaf\x43\xfa\x84\xa4\x0f\x90\xfe\x49\xc6\x2e\x3b\x81\xdf\x0a\xc3\xe7\x9f\x80\x27\xea\xc0\x90\xf8\x56\x79\xbc\x3f\x73\x88\x3d\xe2\xfc\xe0\x78\xfb\x84\xdc\x9d\x2b\x8e\xb7\x49\xb8\xf9\xf0\x52\x08\xbe\x84\xe0\x09\xfb\x90\xf1\x9f\xac\x81\xb9\x44\xcc\xe4\x92\x75\xe0\x3e\xc1\x93\xe7\x97\xcc\xb9\xa4\x6d\x67\xc3\xf0\xe1\xce\x1d\xe1\x63\x27\x39\x17\xe1\x7c\x35\x5c\x6f\x99\x0e\xd3\xdf\xa3\xc9\x75\x11\x31\x84\x57\x1a\xc6\x6f\xbf\x16\x66\x6e\xd7\xc3\xf8\x6a\xb8\xf9\x57\x87\xf1\xdb\x77\xed\xbd\x9f\xa0\xc7\x4e\x93\x35\x1e\x79\x2e\xfe\x22\x8c\x7d\x4e\x92\x17\xc8\xbe\x6b\xb8\x78\x3e\x1c\xc6\xb7\x89\x9c\x42\xc6\x81\x10\xfd\x64\x6f\x39\x5c\x8d\xf1\xfd\x30\x36\x79\x57\xfc\x3d\xf5\x2d\xdf\x17\xfe\x8b\xea\x7f\x92\x77\x70\xf2\x4c\xbd\xaf\x7e\xe6\xfb\xc2\xdf\xb9\x9f\x19\xe6\xae\xf4\xae\xf8\xcf\xa5\x87\x49\xe0\xe4\x7b\x49\xf2\xbc\xbf\x2b\xfe\xde\x7a\x9e\x3f\xe7\x3e\x67\xd8\xbb\x40\xb8\xfe\x55\x38\xfc\x7d\xf5\x45\x7f\x51\xfd\xd2\x9f\x73\x1f\xf5\x7f\xb5\xfe\x2a\xd9\xc7\x0b\xb9\x9b\x84\xc1\xc3\xf5\x5d\x7f\xde\x38\xf9\x8e\x9e\xcc\x95\x61\xf1\x70\x77\xae\xf7\xd4\xfb\x0d\x89\x81\x13\xc7\xcf\x39\x64\x5c\xb2\x86\x27\xfb\xc6\xef\xeb\xbd\xe1\xff\x5f\xf1\x5f\x50\xfe\x7d\x5f\xf8\xcf\xbb\xc7\xf5\x0b\xc3\xc3\xf4\xdb\x7f\xee\xf8\xbb\xc6\xbd\x70\x3d\xf6\x9f\x33\x7e\x92\xf7\x50\x9f\x04\x0f\xe9\xd5\x13\xb6\x3a\x49\x9d\x13\x92\xbb\xaf\x1d\x6f\xe7\x90\xfb\x1a\xd1\xf7\x88\x08\xde\x43\x7f\xf1\xdf\xd8\xa1\x02\x7f\xc3\x02\x02\xbf\xc7\x1e\x05\x7e\x8f\x3d\x02\x13\xfe\xcd\x7a\xa5\xc7\xd1\x4f\xbf\xd3\xf3\xe9\x77\x7a\x3e\xfd\x4e\xcf\xa7\xdf\xe9\xf9\xf4\x3b\x3d\x9f\x7e\xa7\xe7\xd3\xef\xf4\x7c\xfa\x9d\x9e\x4f\xbf\xd3\xf3\xe9\x77\x7a\x3e\xfd\x4e\xcf\xa7\xdf\xe9\xf9\xff\xf2\x77\x7a\xb8\x1c\x3f\xc5\xbf\x7b\xe7\xfb\x98\xff\x3e\xe6\x67\x30\x3f\x83\x7f\xdf\x4e\x95\x9f\x8f\xa8\xc2\xb8\x16\xe3\x5a\xfc\xbb\x77\x7e\x88\xff\x3a\xd9\x0f\xb1\xcc\x47\x58\xe6\x23\xcc\x7f\x05\xf3\x5f\xc1\xbf\xbd\x67\x10\xff\xd5\xb2\x41\xcc\x3b\x31\xef\xc4\x7a\x88\x71\xe9\x1f\x61\x3d\x3f\xf2\xf3\xdc\x39\x3f\xcf\xc5\xbf\x3b\x28\x62\x02\xeb\x99\xc0\xfc\x9f\x62\xfe\x4f\xf1\xb3\xbf\x87\x9f\xfd\xbd\x23\xf8\x35\x8c\x5f\xc3\x7c\x14\xe6\xa3\x30\x4f\x61\x9e\xc2\xf2\xcd\x58\xbe\x19\xe3\x98\xe7\x60\x9e\xfb\x63\x3c\xee\x8f\x31\x9e\x89\xf1\x4c\xcc\x4b\x30\x2f\xc1\x7c\x3e\xe6\xf3\x31\xff\x4f\x31\xff\x4f\x31\x3f\x8a\xf9\x51\xbc\x96\x11\xbc\x96\x91\x23\xf8\x01\xc6\x0f\xb0\x1d\xf0\xb3\xd4\x91\x67\x49\x9e\x12\x61\x19\xd1\x61\x9e\x7e\x81\xf5\xbc\x38\x8c\xf3\xf0\x6f\x7e\xe7\xc1\x11\x9d\x5f\xc7\xfc\xd7\x3f\x6e\x2c\x1a\xef\x0b\x8d\xf7\x85\xfe\x2a\xe6\xbf\x8a\xf5\x63\xfb\x53\x13\x47\xe4\xe7\xb1\x0c\xfe\x1d\x50\x11\xdf\xc3\xf6\xfc\x1e\xc6\xff\x02\xe3\x7f\x71\x58\x86\xfe\x26\xe6\xbf\xc9\xee\x3b\xee\x16\xfc\xd6\x27\xe5\xd9\xcf\xdf\x71\x07\x59\x5f\xc5\xf8\x0c\xeb\x9f\x98\xd7\x9e\x94\x67\x7b\x69\x01\xff\x3c\x01\xcf\xbe\xeb\x63\xcf\x02\xfb\x5e\xe5\x8d\x7f\xb2\x1d\xaf\x4f\xcc\x37\xb3\x1d\xa9\x93\xf2\x6c\x8f\x27\xe0\x9f\xc4\xb9\xe0\x4c\x61\x7e\xea\x88\xaf\x7e\x02\x9e\x8b\xf7\x91\xfb\xcd\xc3\x7e\x4e\xfa\xf6\x49\xf8\x70\xbe\x1d\x8e\xe7\xe0\x71\x39\xdf\xfc\x58\xdf\xfe\x24\x7c\x98\x73\x11\xf6\xbc\x10\xbe\x1d\x16\x27\xfd\x96\xb4\x67\x58\x9c\x88\xc3\x24\x4e\xf8\x76\x48\x6c\x79\x4f\x38\xe9\xcf\xe4\x5a\x42\x62\x3e\x69\x07\xe2\xec\x90\x7b\xfa\xee\x38\x91\x47\x4e\x20\xcf\xbe\xbb\x66\xf3\x4b\xc8\x3c\xdf\x19\x0f\xe6\xa9\x10\x1c\xbf\xa3\x66\x73\x16\xdb\x03\x7e\x83\x07\x73\x59\x48\x7c\x26\xe3\x03\xe9\xb7\xef\x8c\x13\xf9\xf1\x04\xf2\x1c\x9c\xef\x38\x6c\xbe\xc3\x7f\x0b\x86\x63\xc0\x32\xf8\x3d\x27\x9b\x5b\x43\xe4\xc9\x3c\x4b\xe4\x8e\x10\xfe\x47\x6c\x97\x97\x7d\x96\xed\xfe\x1e\x1c\xca\xcb\x21\x39\xe8\x24\x78\x1d\xc6\xeb\x3e\x4e\x9e\x8c\x9f\x21\x7b\x41\xe4\xfd\x50\x3c\x8c\x3c\xce\x5f\x11\xce\x8f\x7d\x96\x88\xb1\xe4\xd9\x7f\x57\x9c\xfb\x13\x1c\x03\x7f\x82\xf9\x5d\xcc\xef\x62\x99\x6b\x6c\x47\xfc\xe0\x50\x3e\x25\x6b\x92\x50\x3c\x8c\x3c\x7e\x87\xcc\xd6\x2d\x64\x2e\x0e\x8f\x07\xeb\x9c\x13\xc9\x13\xb5\x50\x48\x7e\xc7\xef\x1f\x8e\xc3\x8f\x97\x0f\xc9\x41\xa4\x9d\x7f\xee\x38\x97\x73\x1c\xce\xbe\xfb\x65\xeb\x37\xb2\x26\x21\xf3\x63\x48\x7c\x26\xf3\x26\x7e\x4f\xcb\xd6\x75\x21\xb5\xca\x3b\xe2\x54\x11\xb6\x4f\xd1\x91\x39\xe3\xbf\xf7\x1b\x51\x7b\x70\x38\x47\x93\x71\xf5\x3b\x98\xff\xce\x61\x9f\x21\xeb\xf0\xf0\x31\x3c\x18\xab\x23\x9e\x63\xfe\x39\x96\xff\x7d\xfc\xec\xef\x1f\x19\xeb\xcb\x98\xff\xf2\xe1\x38\x1c\x51\x8a\x9f\xc5\xbf\x57\x93\x53\x86\xf1\xb2\x83\x43\x75\x3e\xa7\x09\xe3\x4d\x47\x62\x2c\x51\x4b\xf3\xb8\x7e\x9e\xc7\xc5\x36\xf9\x1a\xb6\xc9\xd7\x0e\xc7\xba\x70\x71\x29\x24\x9e\xe0\xf3\x45\xe3\xf3\xc5\xc3\xf5\x0c\x6f\xea\xe3\xcf\x38\xf7\xed\x5d\x20\x02\xdb\x33\x82\xb5\x27\x91\x4f\xf9\xf8\xbc\xf0\xf1\xb9\xe0\xe2\x18\xc5\xc5\x31\x2a\x22\x01\xcb\x27\x1c\xb1\x55\x98\x3b\x45\xc8\x99\xc2\xe7\x97\xc3\xc6\x5e\xfc\x37\x9f\xa9\xea\x23\xe7\xa8\x02\xcb\x54\x7c\xdc\xf9\x8a\xc0\x76\x8e\x60\xef\x53\x18\x8f\x60\xf1\x3f\xc7\xfc\x9f\x1f\xd9\xbb\x1c\xcc\xe7\xe0\xf9\x3c\xc3\xf3\x79\x76\x70\xe8\x9e\x12\xe2\xb7\x84\x3c\xb9\xbf\x9c\x5c\xcc\xe7\x62\x79\xec\x6f\x34\xeb\x63\x78\x4f\xe9\xe6\xc3\x7e\xcb\x7e\x8f\x24\x12\xdb\x84\xff\xd7\xd8\x9e\x7f\x8d\xf9\x54\xcc\xa7\x62\xdb\xe2\xf9\x73\xd9\xf9\xff\x15\x9e\xff\x5f\x1d\xb0\x39\x8b\xf3\x26\x67\xf1\xfe\x0c\xef\xe9\x9f\x61\x7e\x16\xf3\xb3\xf8\x59\x3c\x07\x2e\xeb\xf3\x61\xea\xa5\x70\xf9\x31\x6c\x3c\x0f\x13\x4f\x68\x7c\x5e\x68\x7c\x5e\xc8\x3b\x05\x59\xeb\x86\xd4\x0c\x84\x0f\x84\xab\x31\xc8\x39\xb3\x9f\x3b\x63\x7d\x3b\xe4\xae\x7a\x82\x5c\xc3\x7e\xa7\x27\xb0\xbf\xb7\xf0\x3c\x6f\x1d\x5e\x6f\x24\xf6\xcf\x8f\xdf\x8b\x70\xf3\xe4\x61\xbf\xe5\xb1\x79\x53\x80\xe7\x26\x38\xf8\x98\x3c\xfb\xce\x35\xed\x3b\xd6\x84\xef\x5a\x3b\xbd\x6b\xee\x0e\x9f\xa3\x8f\xc7\xdf\x35\x37\x85\xcd\xad\x64\x2c\x25\x6a\xa1\xb0\x35\xe7\x10\xde\x8b\xa1\x23\xe3\xe2\x58\x1d\xc1\xde\x61\x71\xfc\xe7\x8c\x7c\xec\x79\x0f\xbb\x2f\xdc\x63\x6b\xef\xb0\x76\x0b\x93\x43\x29\xdc\xab\xa1\xd8\x5e\x0d\x91\x83\xa8\xef\x62\xfc\xbb\x87\xf7\x8b\x97\x86\xfd\x2d\xed\x30\x1f\x72\xf7\x21\xf2\x5d\xc8\x1d\x93\xb0\x1b\x69\x67\x32\x0e\x87\xf0\xf8\x5c\xd0\xec\x9e\xe2\x1c\x44\xe3\x1c\x44\xf6\xb8\x42\x6a\x09\x72\x0e\x61\xec\x43\xf6\xaf\x42\xfc\x90\x88\xdb\xe1\x72\x47\x88\xbf\x11\x3d\xa5\x90\x9a\x84\xc8\xad\x61\xef\xe3\x61\x7a\x4d\x34\xee\x5f\xd1\x3f\x3e\x32\x07\x52\x9e\xc8\x11\x64\xdc\x8b\xc0\xe3\x46\xe0\x71\xe9\x61\x8c\x0f\x63\xfe\x1b\x98\xff\x06\xd6\x83\x63\x35\x07\xc7\x6a\x0e\x8e\x87\x9c\x8f\x0e\xdb\x21\xec\xdd\x19\xe7\x44\x4e\xf5\xe1\xf5\xd2\xd8\x4f\xe8\xef\x7e\xec\xb3\xe1\x7a\x62\x64\x5d\x51\x83\xf9\x1a\xcc\xe3\xda\x8f\xc2\xb5\x1f\x35\x89\xf9\x49\xcc\x0b\x31\x2f\xc4\x3a\xf1\xda\x39\x78\xed\x64\xdf\x2c\x1c\x1f\x76\x6e\x38\xde\x72\xfe\xfa\xf0\x79\xe1\xe2\xb9\x71\xf1\xdc\xb8\x7c\xcc\xe3\xdf\x79\x1e\x81\xeb\x8d\x88\xba\xc3\xfe\x40\xe3\xf8\x40\x97\x1d\xc1\xc3\xf0\x64\xff\x30\xa4\x97\x58\x8e\xe7\x50\x7e\x98\x0f\xe9\xe9\x61\xdf\xa3\x24\x47\x78\xd2\xb6\x24\x4e\xc4\xb1\x70\xfd\xc0\x90\x58\x41\x9c\xaf\xb0\x7d\x42\xd2\x07\xb0\x1e\x7a\xf4\x48\xec\xb2\x63\x3d\xf6\x83\x43\xb9\x2f\x84\xc7\x71\x8f\xce\xff\x58\x1e\xd7\x81\xf4\x77\x0e\x0e\xe7\xdf\x4a\xac\xbf\xf2\xb0\x3f\x73\xf0\x1e\x71\xf0\x1e\x71\x7e\x80\xf9\x1f\x1c\xb6\x4f\xc8\xdd\x19\xd7\x75\x74\xc5\x91\xb3\x16\x66\x3e\xbc\x14\xec\x57\x29\x98\x2f\xc1\x7c\x09\xe6\xb1\x7d\x78\xdf\x3b\x1c\xff\xc9\x1a\x98\x8b\x63\x26\x17\xc7\x4c\x2e\xae\x03\xb9\x6c\x1d\xb8\x8f\xc7\xdd\xc7\x3c\x3e\xbf\x9c\xe1\xc3\xb1\x2b\xa4\x87\x86\x6b\x2d\xce\xec\x11\x3e\xdc\xb9\x23\x7c\xec\x24\xe7\x22\x9c\xaf\x86\xeb\x2d\x87\xec\x3b\xa9\x07\xaf\x8b\xde\x3f\x1c\x43\x78\xf8\x9e\xc2\x2b\xfd\xb8\x98\x10\x32\xb7\xeb\x98\xbf\x7e\xc4\x57\xc3\xcd\x1f\x8f\x45\x57\x1f\xf1\xdb\x77\xed\xbd\x9f\xa0\xc7\x4e\xe3\x9a\x9c\xce\x39\x72\x2e\xc8\x5e\x3a\x69\x9f\x93\xe4\x05\xb2\xef\x1a\x2e\x9e\x13\x7e\x12\xe2\xdb\x44\x4e\x21\xe3\x40\x88\x7e\x7c\x17\xa3\xd9\xde\x72\xb8\xbe\x25\xfe\x8e\x4e\xe0\x5d\x12\x69\x13\xf2\x1d\xd3\x49\xf0\xf7\xd4\xb7\x7c\x5f\x78\x68\xed\x8a\x6b\xfb\x63\x6a\x5a\x12\xe7\x1e\x5b\x4b\xbc\x6b\xff\x93\xfd\x4e\x0f\x7b\x07\x67\xbf\xd3\xc3\x9e\xa9\xb0\x7d\xce\x77\xec\x67\xbe\xbb\xfc\xf1\xf8\xc9\xfa\x99\xc1\x1e\x63\xb8\xbb\x52\xb8\xfe\x40\xd8\x7e\x66\xd8\x9e\xe4\xfb\xe9\x6d\xb2\xdf\xd1\x61\xdf\x4b\x92\xe7\x3d\x3c\xce\xe5\x1c\x87\xbf\x7b\xcf\xf3\x1d\xf1\x90\x1a\x1e\xdb\xf6\x98\x3b\xd1\xdf\x1d\x67\x3f\xff\x7b\x4c\xff\x2a\x1c\xfe\xbe\xfa\xa2\xe1\xe4\xdf\x57\x5f\xf4\x5d\xf1\x90\x7e\x29\xf6\xab\x8f\xed\x97\xbe\x2b\x1e\xae\xcf\xf9\xee\x38\x79\x57\x25\xce\x75\x18\x9c\xfd\xee\x0e\xdb\xc7\x0b\xb9\x9b\x10\xfd\x3d\x12\x0f\xd7\x77\x7d\x77\x9c\xcb\x79\x17\x9c\xfd\xee\x0e\xfb\x8e\x9e\xcc\x95\x61\xf1\x70\x7d\xe0\xb0\x3d\x5e\xee\xf1\x77\xea\x70\x38\x19\x03\x09\x7f\x88\xf8\x1e\xb7\x89\xa8\x7b\x9b\xde\x8e\x4b\xf6\xb2\xf0\x77\x7a\x02\x7d\xe3\x70\xf9\x34\xf4\x2e\xdf\xf4\xf3\xc5\x31\xff\x33\xde\x57\x9e\x44\xfe\x7d\xe1\xdc\x9f\xd9\xbb\xf8\x84\xef\x25\x9b\xde\x0f\x1e\xae\x1e\xe0\x9e\xa0\xc7\x75\x7c\xde\x7c\xd7\x9e\xe1\x21\xbc\xe9\xfd\xe0\xe1\xf2\x02\x31\x2e\xfe\x1e\xc9\xd1\x7e\xfb\xfb\xc3\xb9\xc7\xf6\xf3\x4f\x16\xf7\x08\x1c\xd7\x51\xc7\xf4\xd8\xdf\x1b\xce\x3d\xb6\x87\x1f\xfe\x3d\x14\xf7\xf8\x5e\xd0\x09\xde\x5b\x85\xdc\x17\xc8\x5e\x3d\xf1\x2e\xe9\x24\x75\x4e\xc8\x3b\x29\xf2\x7d\x07\x19\xa3\xc8\xfb\x1a\xee\x7b\xd0\xb8\xef\x11\x81\xef\xa1\x11\xfe\x7b\xe8\xff\x12\xdf\xe9\xa1\x75\xb4\x09\x00\x78\x80\x40\x07\x00\x7e\xde\x0a\x08\x5c\x00\x90\x01\x00\x5e\x40\x50\x08\x88\xfa\x77\x7e\x0e\xfd\x2b\x4e\x29\x20\x78\xe2\xa7\xe8\x25\x58\x00\xa1\x7f\x81\x79\x4c\x29\xfc\x77\x29\x7f\xa9\xab\xe8\x06\xd0\xbf\x74\x1b\x04\xd4\x86\xd8\x2a\x76\x89\x33\xc4\x5e\x71\xa1\xb8\x44\x5c\x26\xae\x14\xd7\x88\xeb\xc4\x8d\xe2\x16\x71\xbb\xb8\x4b\x7c\x5e\x7c\x51\xdc\x27\xee\x17\x5f\x13\x0f\x8b\x47\xc5\x13\xe2\x1b\xe2\x9b\xe2\x39\xf1\x1d\xf1\x5d\xf1\xb2\xf8\x81\x78\x5d\xfc\x48\xbc\x2d\x7e\x22\x7e\x26\x7e\x21\xde\x97\x50\x12\xbe\x44\x28\x61\x24\x6a\x89\x5e\x62\x96\xd8\x24\x6e\x49\x96\x24\x4f\x52\x24\x29\x95\x94\x4b\xaa\x24\xb5\x92\x7a\x49\x93\xa4\x55\xd2\x21\x39\x27\xe9\x91\x5c\x92\x5c\x96\x5c\x95\x0c\x4a\xae\x4b\xc6\x24\x93\x92\x69\xc9\x2d\xc9\xbc\x64\x41\x72\x4f\x72\x5f\xb2\x2a\x79\x28\xd9\x94\x3c\x96\x3c\x95\x3c\x97\xbc\x94\x1c\x48\x39\xd2\x28\xa9\x48\x2a\x97\x6a\xa4\x46\xa9\x45\xea\x90\x7a\xa4\xd9\x52\x9f\xb4\x58\x7a\x46\x5a\x21\xad\x96\x9e\x95\x36\x48\x9b\xa5\x6d\xd2\x4e\x69\xb7\xf4\x82\xb4\x57\x7a\x45\x3a\x20\x1d\x92\x8e\x48\xc7\xa5\x53\xd2\x19\xe9\xac\xf4\xb6\x74\x51\xba\x24\x5d\x91\xae\x49\x37\xa4\x5b\xd2\x1d\xe9\xae\x74\x4f\xfa\x8a\x01\x86\xcb\x08\x18\x09\xa3\x64\x74\x8c\x89\xb1\x32\x2e\x26\x83\xf1\x32\x85\x4c\x09\x53\xc6\x54\x32\x35\x4c\x1d\xd3\xc8\xb4\x30\xed\x4c\x17\x73\x9e\xb9\xc8\xf4\x31\xfd\xcc\x35\x66\x98\x19\x65\x26\x98\x1b\xcc\x4d\x66\x8e\xb9\xc3\xdc\x65\x96\x99\x07\xcc\x3a\xf3\x88\xd9\x66\x9e\x30\xcf\x98\x17\xcc\xbe\x8c\x92\xf1\x65\x42\x19\x23\x53\xcb\xf4\x32\xb3\xcc\x26\x73\xcb\xb2\x64\x79\xb2\x22\x59\xa9\xac\x5c\x56\x25\xab\x95\xd5\xcb\x9a\x64\xad\xb2\x0e\xd9\x39\x59\x8f\xec\x92\xec\xb2\xec\xaa\x6c\x50\x76\x5d\x36\x26\x9b\x94\x4d\xcb\x6e\xc9\xe6\x65\x0b\xb2\x7b\xb2\xfb\xb2\x55\xd9\x43\xd9\xa6\xec\xb1\xec\xa9\xec\xb9\xec\xa5\xec\x40\xce\x91\x47\xc9\x45\x72\xb9\x5c\x23\x37\xca\x2d\x72\x87\xdc\x23\xcf\x96\xfb\xe4\xc5\xf2\x33\xf2\x0a\x79\xb5\xfc\xac\xbc\x41\xde\x2c\x6f\x93\x77\xca\xbb\xe5\x17\xe4\xbd\xf2\x2b\xf2\x01\xf9\x90\x7c\x44\x3e\x2e\x9f\x92\xcf\xc8\x67\xe5\xb7\xe5\x8b\xf2\x25\xf9\x8a\x7c\x4d\xbe\x21\xdf\x92\xef\xc8\x77\xe5\x7b\xf2\x57\x0a\x50\x70\x15\x02\x85\x44\xa1\x54\xe8\x14\x26\x85\x55\xe1\x52\x64\x28\xbc\x8a\x42\x45\x89\xa2\x4c\x51\xa9\xa8\x51\xd4\x29\x1a\x15\x2d\x8a\x76\x45\x97\xe2\xbc\xe2\xa2\xa2\x4f\xd1\xaf\xb8\xa6\x18\x56\x8c\x2a\x26\x14\x37\x14\x37\x15\x73\x8a\x3b\x8a\xbb\x8a\x65\xc5\x03\xc5\xba\xe2\x91\x62\x5b\xf1\x44\xf1\x4c\xf1\x42\xb1\xaf\xa4\x94\x7c\xa5\x50\xc9\x28\xd5\x4a\xbd\xd2\xac\xb4\x29\xdd\xca\x2c\x65\x9e\xb2\x48\x59\xaa\x2c\x57\x56\x29\x6b\x95\xf5\xca\x26\x65\xab\xb2\x43\x79\x4e\xd9\xa3\xbc\xa4\xbc\xac\xbc\xaa\x1c\x54\x5e\x57\x8e\x29\x27\x95\xd3\xca\x5b\xca\x79\xe5\x82\xf2\x9e\xf2\xbe\x72\x55\xf9\x50\xb9\xa9\x7c\xac\x7c\xaa\x7c\xae\x7c\xa9\x3c\x50\x71\x54\x51\x2a\x91\x4a\xae\xd2\xa8\x8c\x2a\x8b\xca\xa1\xf2\xa8\xb2\x55\x3e\x55\xb1\xea\x8c\xaa\x42\x55\xad\x3a\xab\x6a\x50\x35\xab\xda\x54\x9d\xaa\x6e\xd5\x05\x55\xaf\xea\x8a\x6a\x40\x35\xa4\x1a\x51\x8d\xab\xa6\x54\x33\xaa\x59\xd5\x6d\xd5\xa2\x6a\x49\xb5\xa2\x5a\x53\x6d\xa8\xb6\x54\x3b\xaa\x5d\xd5\x9e\xea\x95\x1a\xd4\x5c\xb5\x40\x2d\x51\x2b\xd5\x3a\xb5\x49\x6d\x55\xbb\xd4\x19\x6a\xaf\xba\x50\x5d\xa2\x2e\x53\x57\xaa\x6b\xd4\x75\xea\x46\x75\x8b\xba\x5d\xdd\xa5\x3e\xaf\xbe\xa8\xee\x53\xf7\xab\xaf\xa9\x87\xd5\xa3\xea\x09\xf5\x0d\xf5\x4d\xf5\x9c\xfa\x8e\xfa\xae\x7a\x59\xfd\x40\xbd\xae\x7e\xa4\xde\x56\x3f\x51\x3f\x53\xbf\x50\xef\xc7\x51\x71\xfc\x38\x61\x1c\x13\xa7\x8e\xd3\xc7\x99\xe3\x6c\x71\xee\xb8\xac\xb8\xbc\xb8\xa2\xb8\xd2\xb8\xf2\xb8\xaa\xb8\xda\xb8\xfa\xb8\xa6\xb8\xd6\xb8\x8e\xb8\x73\x71\x3d\x71\x97\xe2\x2e\xc7\x5d\x8d\x1b\x8c\xbb\x1e\x37\x16\x37\x19\x37\x1d\x77\x2b\x6e\x3e\x6e\x21\xee\x5e\xdc\xfd\xb8\xd5\xb8\x87\x71\x9b\x71\x8f\xe3\x9e\xc6\x3d\x8f\x7b\x19\x77\xa0\xe1\x68\xa2\x34\x22\x8d\x5c\xa3\xd1\x18\x35\x16\x8d\x43\xe3\xd1\x64\x6b\x7c\x9a\x62\xcd\x19\x4d\x85\xa6\x5a\x73\x56\xd3\xa0\x69\xd6\xb4\x69\x3a\x35\xdd\x9a\x0b\x9a\x5e\xcd\x15\xcd\x80\x66\x48\x33\xa2\x19\xd7\x4c\x69\x66\x34\xb3\x9a\xdb\x9a\x45\xcd\x92\x66\x45\xb3\xa6\xd9\xd0\x6c\x69\x76\x34\xbb\x9a\x3d\xcd\x2b\x2d\x68\xb9\x5a\x81\x56\xa2\x55\x6a\x75\x5a\x93\xd6\xaa\x75\x69\x33\xb4\x5e\x6d\xa1\xb6\x44\x5b\xa6\xad\xd4\xd6\x68\xeb\xb4\x8d\xda\x16\x6d\xbb\xb6\x4b\x7b\x5e\x7b\x51\xdb\xa7\xed\xd7\x5e\xd3\x0e\x6b\x47\xb5\x13\xda\x1b\xda\x9b\xda\x39\xed\x1d\xed\x5d\xed\xb2\xf6\x81\x76\x5d\xfb\x48\xbb\xad\x7d\xa2\x7d\xa6\x7d\xa1\xdd\xd7\x51\x3a\xbe\x4e\xa8\x63\x74\x6a\x9d\x5e\x67\xd6\xd9\x74\x6e\x5d\x96\x2e\x4f\x57\xa4\x2b\xd5\x95\xeb\xaa\x74\xb5\xba\x7a\x5d\x93\xae\x55\xd7\xa1\x3b\xa7\xeb\xd1\x5d\xd2\x5d\xd6\x5d\xd5\x0d\xea\xae\xeb\xc6\x74\x93\xba\x69\xdd\x2d\xdd\xbc\x6e\x41\x77\x4f\x77\x5f\xb7\xaa\x7b\xa8\xdb\xd4\x3d\xd6\x3d\xd5\x3d\xd7\xbd\xd4\x1d\xc4\x73\xe2\xa3\xe2\x45\xf1\xf2\x78\x4d\xbc\x31\xde\x12\xef\x88\xf7\xc4\x67\xc7\xfb\xe2\x8b\xe3\xcf\xc4\x57\xc4\x57\xc7\x9f\x8d\x6f\x88\x6f\x8e\x6f\x8b\xef\x8c\xef\x8e\xbf\x10\xdf\x1b\x7f\x25\x7e\x20\x7e\x28\x7e\x24\x7e\x3c\x7e\x2a\x7e\x26\x7e\x36\xfe\x76\xfc\x62\xfc\x52\xfc\x4a\xfc\x5a\xfc\x46\xfc\x56\xfc\x4e\xfc\x6e\xfc\x5e\xfc\x2b\x3d\xe8\xb9\x7a\x81\x5e\xa2\x57\xea\x75\x7a\x93\xde\xaa\x77\xe9\x33\xf4\x5e\x7d\xa1\xbe\x44\x5f\xa6\xaf\xd4\xd7\xe8\xeb\xf4\x8d\xfa\x16\x7d\xbb\xbe\x4b\x7f\x5e\x7f\x51\xdf\xa7\xef\xd7\x5f\xd3\x0f\xeb\x47\xf5\x13\xfa\x1b\xfa\x9b\xfa\x39\xfd\x1d\xfd\x5d\xfd\xb2\xfe\x81\x7e\x5d\xff\x48\xbf\xad\x7f\xa2\x7f\xa6\x7f\xa1\xdf\x37\x50\x06\xbe\x41\x68\x60\x0c\x6a\x83\xde\x60\x36\xd8\x0c\x6e\x43\x96\x21\xcf\x50\x64\x28\x35\x94\x1b\xaa\x0c\xb5\x86\x7a\x43\x93\xa1\xd5\xd0\x61\x38\x67\xe8\x31\x5c\x32\x5c\x36\x5c\x35\x0c\x1a\xae\x1b\xc6\x0c\x93\x86\x69\xc3\x2d\xc3\xbc\x61\xc1\x70\xcf\x70\xdf\xb0\x6a\x78\x68\xd8\x34\x3c\x36\x3c\x35\x3c\x37\xbc\x34\x1c\x18\x39\xc6\x28\xa3\xc8\x28\x37\x6a\x8c\x46\xa3\xc5\xe8\x30\x7a\x8c\xd9\x46\x9f\xb1\xd8\x78\xc6\x58\x61\xac\x36\x9e\x35\x36\x18\x9b\x8d\x6d\xc6\x4e\x63\xb7\xf1\x82\xb1\xd7\x78\xc5\x38\x60\x1c\x32\x8e\x18\xc7\x8d\x53\xc6\x19\xe3\xac\xf1\xb6\x71\xd1\xb8\x64\x5c\x31\xae\x19\x37\x8c\x5b\xc6\x1d\xe3\xae\x71\xcf\xf8\x2a\x01\x12\xb8\x09\x82\x04\x49\x82\x32\x41\x97\x60\x4a\xb0\x26\xb8\x12\x32\x12\xbc\x09\x85\x09\x25\x09\x65\x09\x95\x09\x35\x09\x75\x09\x8d\x09\x2d\x09\xed\x09\x5d\x09\xe7\x13\x2e\x26\xf4\x25\xf4\x27\x5c\x4b\x18\x4e\x18\x4d\x98\x48\xb8\x91\x70\x33\x61\x2e\xe1\x4e\xc2\xdd\x84\xe5\x84\x07\x09\xeb\x09\x8f\x12\xb6\x13\x9e\x24\x3c\x4b\x78\x91\xb0\x6f\xa2\x4c\x7c\x93\xd0\xc4\x98\xd4\x26\xbd\xc9\x6c\xb2\x99\xdc\xa6\x2c\x53\x9e\xa9\xc8\x54\x6a\x2a\x37\x55\x99\x6a\x4d\xf5\xa6\x26\x53\xab\xa9\xc3\x74\xce\xd4\x63\xba\x64\xba\x6c\xba\x6a\x1a\x34\x5d\x37\x8d\x99\x26\x4d\xd3\xa6\x5b\xa6\x79\xd3\x82\xe9\x9e\xe9\xbe\x69\xd5\xf4\xd0\xb4\x69\x7a\x6c\x7a\x6a\x7a\x6e\x7a\x69\x3a\x48\xe4\x24\x46\x25\x8a\x12\xe5\x89\x9a\x44\x63\xa2\x25\xd1\x91\xe8\x49\xcc\x4e\xf4\x25\x16\x27\x9e\x49\xac\x48\xac\x4e\x3c\x9b\xd8\x90\xd8\x9c\xd8\x96\xd8\x99\xd8\x9d\x78\x21\xb1\x37\xf1\x4a\xe2\x40\xe2\x50\xe2\x48\xe2\x78\xe2\x54\xe2\x4c\xe2\x6c\xe2\xed\xc4\xc5\xc4\xa5\xc4\x95\xc4\xb5\xc4\x8d\xc4\xad\xc4\x9d\xc4\xdd\xc4\xbd\xc4\x57\x66\x30\x73\xcd\x02\xb3\xc4\xac\x34\xeb\xcc\x26\xb3\xd5\xec\x32\x67\x98\xbd\xe6\x42\x73\x89\xb9\xcc\x5c\x69\xae\x31\xd7\x99\x1b\xcd\x2d\xe6\x76\x73\x97\xf9\xbc\xf9\xa2\xb9\xcf\xdc\x6f\xbe\x66\x1e\x36\x8f\x9a\x27\xcc\x37\xcc\x37\xcd\x73\xe6\x3b\xe6\xbb\xe6\x65\xf3\x03\xf3\xba\xf9\x91\x79\xdb\xfc\xc4\xfc\xcc\xfc\xc2\xbc\x9f\x44\x25\xf1\x93\x84\x49\x4c\x92\x3a\x49\x9f\x64\x4e\xb2\x25\xb9\x93\xb2\x92\xf2\x92\x8a\x92\x4a\x93\xca\x93\xaa\x92\x6a\x93\xea\x93\x9a\x92\x5a\x93\x3a\x92\xce\x25\xf5\x24\x5d\x4a\xba\x9c\x74\x35\x69\x30\xe9\x7a\xd2\x58\xd2\x64\xd2\x74\xd2\xad\xa4\xf9\xa4\x85\xa4\x7b\x49\xf7\x93\x56\x93\x1e\x26\x6d\x26\x3d\x4e\x7a\x9a\xf4\x3c\xe9\x65\xd2\x81\x85\x63\x89\xb2\x88\x2c\x72\x8b\xc6\x62\xb4\x58\x2c\x0e\x8b\xc7\x92\x6d\xf1\x59\x8a\x2d\x67\x2c\x15\x96\x6a\xcb\x59\x4b\x83\xa5\xd9\xd2\x66\xe9\xb4\x74\x5b\x2e\x58\x7a\x2d\x57\x2c\x03\x96\x21\xcb\x88\x65\xdc\x32\x65\x99\xb1\xcc\x5a\x6e\x5b\x16\x2d\x4b\x96\x15\xcb\x9a\x65\xc3\xb2\x65\xd9\xb1\xec\x5a\xf6\x2c\xaf\x92\x21\x99\x9b\x2c\x48\x96\x24\x2b\x93\x75\xc9\xa6\x64\x6b\xb2\x2b\x39\x23\xd9\x9b\x5c\x98\x5c\x92\x5c\x96\x5c\x99\x5c\x93\x5c\x97\xdc\x98\xdc\x92\xdc\x9e\xdc\x95\x7c\x3e\xf9\x62\x72\x5f\x72\x7f\xf2\xb5\xe4\xe1\xe4\xd1\xe4\x89\xe4\x1b\xc9\x37\x93\xe7\x92\xef\x24\xdf\x4d\x5e\x4e\x7e\x90\xbc\x9e\xfc\x28\x79\x3b\xf9\x49\xf2\xb3\xe4\x17\xc9\xfb\x56\xca\xca\xb7\x0a\xad\x8c\x55\x6d\xd5\x5b\xcd\x56\x9b\xd5\x6d\xcd\xb2\xe6\x59\x8b\xac\xa5\xd6\x72\x6b\x95\xb5\xd6\x5a\x6f\x6d\xb2\xb6\x5a\x3b\xac\xe7\xac\x3d\xd6\x4b\xd6\xcb\xd6\xab\xd6\x41\xeb\x75\xeb\x98\x75\xd2\x3a\x6d\xbd\x65\x9d\xb7\x2e\x58\xef\x59\xef\x5b\x57\xad\x0f\xad\x9b\xd6\xc7\xd6\xa7\xd6\xe7\xd6\x97\xd6\x83\x14\x4e\x4a\x54\x8a\x28\x45\x9e\xa2\x49\x31\xa6\x58\x52\x1c\x29\x9e\x94\xec\x14\x5f\x4a\x71\xca\x99\x94\x8a\x94\xea\x94\xb3\x29\x0d\x29\xcd\x29\x6d\x29\x9d\x29\xdd\x29\x17\x52\x7a\x53\xae\xa4\x0c\xa4\x0c\xa5\x8c\xa4\x8c\xa7\x4c\xa5\xcc\xa4\xcc\xa6\xdc\x4e\x59\x4c\x59\x4a\x59\x49\x59\x4b\xd9\x48\xd9\x4a\xd9\x49\xd9\x4d\xd9\x4b\x79\x65\x03\x1b\xd7\x26\xb0\x49\x6c\x4a\x9b\xce\x66\xb2\x59\x6d\x2e\x5b\x86\xcd\x6b\x2b\xb4\x95\xd8\xca\x6c\x95\xb6\x1a\x5b\x9d\xad\xd1\xd6\x62\x6b\xb7\x75\xd9\xce\xdb\x2e\xda\xfa\x6c\xfd\xb6\x6b\xb6\x61\xdb\xa8\x6d\xc2\x76\xc3\x76\xd3\x36\x67\xbb\x63\xbb\x6b\x5b\xb6\x3d\xb0\xad\xdb\x1e\xd9\xb6\x6d\x4f\x6c\xcf\x6c\x2f\x6c\xfb\x76\xca\xce\xb7\x0b\xed\x8c\x5d\x6d\xd7\xdb\xcd\x76\x9b\xdd\x6d\xcf\xb2\xe7\xd9\x8b\xec\xa5\xf6\x72\x7b\x95\xbd\xd6\x5e\x6f\x6f\xb2\xb7\xda\x3b\xec\xe7\xec\x3d\xf6\x4b\xf6\xcb\xf6\xab\xf6\x41\xfb\x75\xfb\x98\x7d\xd2\x3e\x6d\xbf\x65\x9f\xb7\x2f\xd8\xef\xd9\xef\xdb\x57\xed\x0f\xed\x9b\xf6\xc7\xf6\xa7\xf6\xe7\xf6\x97\xf6\x03\x07\xc7\x11\xe5\x10\x39\xe4\x0e\x8d\xc3\xe8\xb0\x38\x1c\x0e\x8f\x23\xdb\xe1\x73\x14\x3b\xce\x38\x2a\x1c\xd5\x8e\xb3\x8e\x06\x47\xb3\xa3\xcd\xd1\xe9\xe8\x76\x5c\x70\xf4\x3a\xae\x38\x06\x1c\x43\x8e\x11\xc7\xb8\x63\xca\x31\xe3\x98\x75\xdc\x76\x2c\x3a\x96\x1c\x2b\x8e\x35\xc7\x86\x63\xcb\xb1\xe3\xd8\x75\xec\x39\x5e\x39\xc1\xc9\x75\x0a\x9c\x12\xa7\xd2\xa9\x73\x9a\x9c\x56\xa7\xcb\x99\xe1\xf4\x3a\x0b\x9d\x25\xce\x32\x67\xa5\xb3\xc6\x59\xe7\x6c\x74\xb6\x38\xdb\x9d\x5d\xce\xf3\xce\x8b\xce\x3e\x67\xbf\xf3\x9a\x73\xd8\x39\xea\x9c\x70\xde\x70\xde\x74\xce\x39\xef\x38\xef\x3a\x97\x9d\x0f\x9c\xeb\xce\x47\xce\x6d\xe7\x13\xe7\x33\xe7\x0b\xe7\xbe\x8b\x72\xf1\x5d\x42\x17\xe3\x52\xbb\xf4\x2e\xb3\xcb\xe6\x72\xbb\xb2\x5c\x79\xae\x22\x57\xa9\xab\xdc\x55\xe5\xaa\x75\xd5\xbb\x9a\x5c\xad\xae\x0e\xd7\x39\x57\x8f\xeb\x92\xeb\xb2\xeb\xaa\x6b\xd0\x75\xdd\x35\xe6\x9a\x74\x4d\xbb\x6e\xb9\xe6\x5d\x0b\xae\x7b\xae\xfb\xae\x55\xd7\x43\xd7\xa6\xeb\xb1\xeb\xa9\xeb\xb9\xeb\xa5\xeb\x20\x95\x93\x1a\x95\x2a\x4a\x95\xa7\x6a\x52\x8d\xa9\x96\x54\x47\xaa\x27\x35\x3b\xd5\x97\x5a\x9c\x7a\x26\xb5\x22\xb5\x3a\xf5\x6c\x6a\x43\x6a\x73\x6a\x5b\x6a\x67\x6a\x77\xea\x85\xd4\xde\xd4\x2b\xa9\x03\xa9\x43\xa9\x23\xa9\xe3\xa9\x53\xa9\x33\xa9\xb3\xa9\xb7\x53\x17\x53\x97\x52\x57\x52\xd7\x52\x37\x52\xb7\x52\x77\x52\x77\x53\xf7\x52\x5f\xb9\xc1\xcd\x75\x0b\xdc\x12\xb7\xd2\xad\x73\x9b\xdc\x56\xb7\xcb\x9d\xe1\xf6\xba\x0b\xdd\x25\xee\x32\x77\xa5\xbb\xc6\x5d\xe7\x6e\x74\xb7\xb8\xdb\xdd\x5d\xee\xf3\xee\x8b\xee\x3e\x77\xbf\xfb\x9a\x7b\xd8\x3d\xea\x9e\x70\xdf\x70\xdf\x74\xcf\xb9\xef\xb8\xef\xba\x97\xdd\x0f\xdc\xeb\xee\x47\xee\x6d\xf7\x13\xf7\x33\xf7\x0b\xf7\x7e\x1a\x95\xc6\x4f\x13\xa6\x31\x69\xea\x34\x7d\x9a\x39\xcd\x96\xe6\x4e\xcb\x4a\xcb\x4b\x2b\x4a\x2b\x4d\x2b\x4f\xab\x4a\xab\x4d\xab\x4f\x6b\x4a\x6b\x4d\xeb\x48\x3b\x97\xd6\x93\x76\x29\xed\x72\xda\xd5\xb4\xc1\xb4\xeb\x69\x63\x69\x93\x69\xd3\x69\xb7\xd2\xe6\xd3\x16\xd2\xee\xa5\xdd\x4f\x5b\x4d\x7b\x98\xb6\x99\xf6\x38\xed\x69\xda\xf3\xb4\x97\x69\x07\x1e\x8e\x27\xca\x23\xf2\xc8\x3d\x1a\x8f\xd1\x63\xf1\x38\x3c\x1e\x4f\xb6\xc7\xe7\x29\xf6\x9c\xf1\x54\x78\xaa\x3d\x67\x3d\x0d\x9e\x66\x4f\x9b\xa7\xd3\xd3\xed\xb9\xe0\xe9\xf5\x5c\xf1\x0c\x78\x86\x3c\x23\x9e\x71\xcf\x94\x67\xc6\x33\xeb\xb9\xed\x59\xf4\x2c\x79\x56\x3c\x6b\x9e\x0d\xcf\x96\x67\xc7\xb3\xeb\xd9\xf3\xbc\x4a\x87\x74\x6e\xba\x20\x5d\x92\xae\x4c\xd7\xa5\x9b\xd2\xad\xe9\xae\xf4\x8c\x74\x6f\x7a\x61\x7a\x49\x7a\x59\x7a\x65\x7a\x4d\x7a\x5d\x7a\x63\x7a\x4b\x7a\x7b\x7a\x57\xfa\xf9\xf4\x8b\xe9\x7d\xe9\xfd\xe9\xd7\xd2\x87\xd3\x47\xd3\x27\xd2\x6f\xa4\xdf\x4c\x9f\x4b\xbf\x93\x7e\x37\x7d\x39\xfd\x41\xfa\x7a\xfa\xa3\xf4\xed\xf4\x27\xe9\xcf\xd2\x5f\xa4\xef\x67\x50\x19\xfc\x0c\x61\x06\x93\xa1\xce\xd0\x67\x98\x33\x6c\x19\xee\x8c\xac\x8c\xbc\x8c\xa2\x8c\xd2\x8c\xf2\x8c\xaa\x8c\xda\x8c\xfa\x8c\xa6\x8c\xd6\x8c\x8e\x8c\x73\x19\x3d\x19\x97\x32\x2e\x67\x5c\xcd\x18\xcc\xb8\x9e\x31\x96\x31\x99\x31\x9d\x71\x2b\x63\x3e\x63\x21\xe3\x5e\xc6\xfd\x8c\xd5\x8c\x87\x19\x9b\x19\x8f\x33\x9e\x66\x3c\xcf\x78\x99\x71\x90\xc9\xc9\x8c\xca\x14\x65\xca\x33\x35\x99\xc6\x4c\x4b\xa6\x23\xd3\x93\x99\x9d\xe9\xcb\x2c\xce\x3c\x93\x59\x91\x59\x9d\x79\x36\xb3\x21\xb3\x39\xb3\x2d\xb3\x33\xb3\x3b\xf3\x42\x66\x6f\xe6\x95\xcc\x81\xcc\xa1\xcc\x91\xcc\xf1\xcc\xa9\xcc\x99\xcc\xd9\xcc\xdb\x99\x8b\x99\x4b\x99\x2b\x99\x6b\x99\x1b\x99\x5b\x99\x3b\x99\xbb\x99\x7b\x99\xaf\xb2\x20\x8b\x9b\x25\xc8\x92\x64\x29\xb3\x74\x59\xa6\x2c\x6b\x96\x2b\x2b\x23\xcb\x9b\x55\x98\x55\x92\x55\x96\x55\x99\x55\x93\x55\x97\xd5\x98\xd5\x92\xd5\x9e\xd5\x95\x75\x3e\xeb\x62\x56\x5f\x56\x7f\xd6\xb5\xac\xe1\xac\xd1\xac\x89\xac\x1b\x59\x37\xb3\xe6\xb2\xee\x64\xdd\xcd\x5a\xce\x7a\x90\xb5\x9e\xf5\x28\x6b\x3b\xeb\x49\xd6\xb3\xac\x17\x59\xfb\xa7\xa8\x53\xfc\x53\xc2\x53\xcc\x29\xf5\x29\xfd\x29\xf3\x29\xdb\x29\xf7\xa9\xac\x53\x79\xa7\x8a\x4e\x95\x9e\x2a\x3f\x55\x75\xaa\xf6\x54\xfd\xa9\xa6\x53\xad\xa7\x3a\x4e\x9d\x3b\xd5\x73\xea\xd2\xa9\xcb\xa7\xae\x9e\x1a\x3c\x75\xfd\xd4\xd8\xa9\xc9\x53\xd3\xa7\x6e\x9d\x9a\x3f\xb5\x70\xea\xde\xa9\xfb\xa7\x56\x4f\x3d\x3c\xb5\x79\xea\xf1\xa9\xa7\xa7\x9e\x9f\x7a\x79\xea\x20\x9b\x93\x1d\x95\x2d\xca\x96\x67\x6b\xb2\x8d\xd9\x96\x6c\x47\xb6\x27\x3b\x3b\xdb\x97\x5d\x9c\x7d\x26\xbb\x22\xbb\x3a\xfb\x6c\x76\x43\x76\x73\x76\x5b\x76\x67\x76\x77\xf6\x85\xec\xde\xec\x2b\xd9\x03\xd9\x43\xd9\x23\xd9\xe3\xd9\x53\xd9\x33\xd9\xb3\xd9\xb7\xb3\x17\xb3\x97\xb2\x57\xb2\xd7\xb2\x37\xb2\xb7\xb2\x77\xb2\x77\xb3\xf7\xb2\x5f\xe5\x40\x0e\x37\x47\x90\x23\xc9\x51\xe6\xe8\x72\x4c\x39\xd6\x1c\x57\x4e\x46\x8e\x37\xa7\x30\xa7\x24\xa7\x2c\xa7\x32\xa7\x26\xa7\x2e\xa7\x31\xa7\x25\xa7\x3d\xa7\x2b\xe7\x7c\xce\xc5\x9c\xbe\x9c\xfe\x9c\x6b\x39\xc3\x39\xa3\x39\x13\x39\x37\x72\x6e\xe6\xcc\xe5\xdc\xc9\xb9\x9b\xb3\x9c\xf3\x20\x67\x3d\xe7\x51\xce\x76\xce\x93\x9c\x67\x39\x2f\x72\xf6\xbd\x94\x97\xef\x15\x7a\x19\xaf\xda\xab\xf7\x9a\xbd\x36\xaf\xdb\x9b\xe5\xcd\xf3\x16\x79\x4b\xbd\xe5\xde\x2a\x6f\xad\xb7\xde\xdb\xe4\x6d\xf5\x76\x78\xcf\x79\x7b\xbc\x97\xbc\x97\xbd\x57\xbd\x83\xde\xeb\xde\x31\xef\xa4\x77\xda\x7b\xcb\x3b\xef\x5d\xf0\xde\xf3\xde\xf7\xae\x7a\x1f\x7a\x37\xbd\x8f\xbd\x4f\xbd\xcf\xbd\x2f\xbd\x07\xb9\x9c\xdc\xa8\x5c\x51\xae\x3c\x57\x93\x6b\xcc\xb5\xe4\x3a\x72\x3d\xb9\xd9\xb9\xbe\xdc\xe2\xdc\x33\xb9\x15\xb9\xd5\xb9\x67\x73\x1b\x72\x9b\x73\xdb\x72\x3b\x73\xbb\x73\x2f\xe4\xf6\xe6\x5e\xc9\x1d\xc8\x1d\xca\x1d\xc9\x1d\xcf\x9d\xca\x9d\xc9\x9d\xcd\xbd\x9d\xbb\x98\xbb\x94\xbb\x92\xbb\x96\xbb\x91\xbb\x95\xbb\x93\xbb\x9b\xbb\x97\xfb\x2a\x0f\xf2\xb8\x79\x82\x3c\x49\x9e\x32\x4f\x97\x67\xca\xb3\xe6\xb9\xf2\x32\xf2\xbc\x79\x85\x79\x25\x79\x65\x79\x95\x79\x35\x79\x75\x79\x8d\x79\x2d\x79\xed\x79\x5d\x79\xe7\xf3\x2e\xe6\xf5\xe5\xf5\xe7\x5d\xcb\x1b\xce\x1b\xcd\x9b\xc8\xbb\x91\x77\x33\x6f\x2e\xef\x4e\xde\xdd\xbc\xe5\xbc\x07\x79\xeb\x79\x8f\xf2\xb6\xf3\x9e\xe4\x3d\xcb\x7b\x91\xb7\x9f\x4f\xe5\xf3\xf3\x85\xf9\x4c\xbe\x3a\x5f\x9f\x6f\xce\xb7\xe5\xbb\xf3\xb3\xf2\xf3\xf2\x8b\xf2\x4b\xf3\xcb\xf3\xab\xf2\x6b\xf3\xeb\xf3\x9b\xf2\x5b\xf3\x3b\xf2\xcf\xe5\xf7\xe4\x5f\xca\xbf\x9c\x7f\x35\x7f\x30\xff\x7a\xfe\x58\xfe\x64\xfe\x74\xfe\xad\xfc\xf9\xfc\x85\xfc\x7b\xf9\xf7\xf3\x57\xf3\x1f\xe6\x6f\xe6\x3f\xce\x7f\x9a\xff\x3c\xff\x65\xfe\x81\x8f\xe3\x8b\xf2\x89\x7c\x72\x9f\xc6\x67\xf4\x59\x7c\x0e\x9f\xc7\x97\xed\xf3\xf9\x8a\x7d\x67\x7c\x15\xbe\x6a\xdf\x59\x5f\x83\xaf\xd9\xd7\xe6\xeb\xf4\x75\xfb\x2e\xf8\x7a\x7d\x57\x7c\x03\xbe\x21\xdf\x88\x6f\xdc\x37\xe5\x9b\xf1\xcd\xfa\x6e\xfb\x16\x7d\x4b\xbe\x15\xdf\x9a\x6f\xc3\xb7\xe5\xdb\xf1\xed\xfa\xf6\x7c\xaf\x0a\xa0\x80\x5b\x20\x28\x90\x14\x28\x0b\x74\x05\xa6\x02\x6b\x81\xab\x20\xa3\xc0\x5b\x50\x58\x50\x52\x50\x56\x50\x59\x50\x53\x50\x57\xd0\x58\xd0\x52\xd0\x5e\xd0\x55\x70\xbe\xe0\x62\x41\x5f\x41\x7f\xc1\xb5\x82\xe1\x82\xd1\x82\x89\x82\x1b\x05\x37\x0b\xe6\x0a\xee\x14\xdc\x2d\x58\x2e\x78\x50\xb0\x5e\xf0\xa8\x60\xbb\xe0\x49\xc1\xb3\x82\x17\x05\xfb\x85\x54\x21\xbf\x50\x58\xc8\x14\xaa\x0b\xf5\x85\xe6\x42\x5b\xa1\xbb\x30\xab\x30\xaf\xb0\xa8\xb0\xb4\xb0\xbc\xb0\xaa\xb0\xb6\xb0\xbe\xb0\xa9\xb0\xb5\xb0\xa3\xf0\x5c\x61\x4f\xe1\xa5\xc2\xcb\x85\x57\x0b\x07\x0b\xaf\x17\x8e\x15\x4e\x16\x4e\x17\xde\x2a\x9c\x2f\x5c\x28\xbc\x57\x78\xbf\x70\xb5\xf0\x61\xe1\x66\xe1\xe3\xc2\xa7\x85\xcf\x0b\x5f\x16\x1e\x9c\xe6\x9c\x8e\x3a\x2d\x3a\x2d\x3f\xad\x39\x6d\x3c\x6d\x39\xed\x38\xed\x39\x9d\x7d\xda\x77\xba\xf8\xf4\x99\xd3\x15\xa7\xab\x4f\x9f\x3d\xdd\x70\xba\xf9\x74\xdb\xe9\xce\xd3\xdd\xa7\x2f\x9c\xee\x3d\x7d\xe5\xf4\xc0\xe9\xa1\xd3\x23\xa7\xc7\x4f\x4f\x9d\x9e\x39\x3d\x7b\xfa\xf6\xe9\xc5\xd3\x4b\xa7\x57\x4e\xaf\x9d\xde\x38\xbd\x75\x7a\xe7\xf4\xee\xe9\xbd\xd3\xaf\x8a\xa0\x88\x5b\x24\x28\x92\x14\x29\x8b\x74\x45\xa6\x22\x6b\x91\xab\x28\xa3\xc8\x5b\x54\x58\x54\x52\x54\x56\x54\x59\x54\x53\x54\x57\xd4\x58\xd4\x52\xd4\x5e\xd4\x55\x74\xbe\xe8\x62\x51\x5f\x51\x7f\xd1\xb5\xa2\x61\x40\xd4\x15\xdc\x21\xda\xc1\x3d\x23\xf6\xef\xcd\xf7\xe0\x5e\xd2\x19\x8c\xf4\xb0\x7f\x91\x1a\x23\xd3\x58\x92\xfd\xeb\xd4\xb8\xc7\xc4\x79\xca\x76\x9a\xd8\xbf\x54\x4d\xe8\xa9\x3e\x1e\xa1\x3d\xb8\x03\x85\xdf\xb1\xd1\x1e\x2c\xf3\x3f\x30\xc2\x60\x99\x3f\x65\xff\x6e\x3a\x2b\xef\xa7\xe8\x33\x18\xe9\xc6\xfc\x26\xa6\xca\x83\x62\x40\xd4\x4c\x70\x3e\x54\x1f\xd6\x83\x3f\xcf\x4d\x5f\xc4\x48\x11\x1e\xeb\x5f\xe0\xb7\x11\xf8\x59\x1a\xeb\xa1\xf1\x7b\xa6\x08\xfc\x69\x1b\x8a\xfd\xdb\xea\x7a\x8c\x78\x31\xb2\x85\xf5\xb4\x10\x6b\x6f\x39\x22\xd3\xf7\xba\xf7\xcd\xba\x02\x32\x03\xc4\xe8\x3b\xc1\xd1\xa9\xec\xa0\x0c\xfb\xf7\xe0\xa9\xff\xeb\xf0\x4a\xa9\x0f\x89\x55\xa4\xe0\xb1\xfe\x9d\x9f\xe7\xe1\x67\xe9\xaf\x11\xf3\xc1\x1d\x43\xca\x15\x1c\x8b\x45\x02\x9a\x7f\x19\x23\x6c\xc7\xf0\x97\x31\xe2\xe2\x4c\xfb\xad\xe1\xa7\x81\xa7\x3a\x71\x1f\x9c\xb5\x4f\x27\x46\x34\x58\xa6\x16\xcb\x68\xd8\xbf\x0b\x8e\x7b\xca\x59\xc1\x7d\xa7\x8a\x08\x3d\x45\x81\xd1\xfd\x7a\x70\xb7\x14\xba\x0e\x98\x37\x7a\x38\x59\x7e\x8a\xf6\x30\x32\x80\x65\xf0\x27\x0f\xa8\xcf\xe1\x1d\x6c\xe2\xda\xde\xee\x23\xff\x28\x82\x9f\x6a\xc1\x4f\xdd\x09\xae\x14\x75\x73\xfb\x43\x9f\xa2\x07\xfd\xa3\x70\xc7\xf0\xac\xd8\x19\xb6\xe0\xd1\xcf\xe0\x19\x7e\x2e\x38\x67\x8e\x1a\x23\x05\xec\xda\x09\x99\x32\x3c\x56\x76\x70\xce\xd4\xe7\xfc\x08\xda\xc4\x3a\xf5\x78\x15\x9b\x78\xf4\x05\x02\x59\x63\xe7\x1c\x71\x0f\x10\x35\x1f\x94\xa1\xea\x0f\x8f\x1e\xd0\xb3\x83\x65\x7e\x88\x65\x5e\xe2\x39\x0b\xb1\xcc\x77\x8e\xc8\xec\x1d\x7d\x0a\xcf\x67\x2b\xb8\x3b\x88\xf5\xcc\x79\xde\xc0\x5b\xaf\xab\x7d\x07\xa4\xe5\x04\x88\x2b\x14\xe1\x9c\xc7\x67\x07\x9f\x44\xba\xe2\x70\x04\xa0\xae\x63\x1b\xae\xf8\xc7\x0a\x39\xef\x27\x43\x5a\x42\x11\xb4\xe9\x97\x09\x39\xef\x7b\x18\x99\x38\x82\xcc\x13\xc8\xa6\x5f\x0f\x89\x1c\x8d\x48\x74\x9b\x5f\x26\xe4\xbc\xb7\xf9\xf5\x90\xe7\xfd\x44\x88\x07\xeb\x09\x87\x3c\x65\x77\xf9\x70\x24\xa1\x4b\xb0\x1e\xe2\xbc\x9f\x08\x61\x35\x93\x51\x62\x00\xef\x29\x79\xde\x03\x31\x8a\xf3\xf4\x4d\x8c\xa2\x7a\xfc\x27\x85\xa3\x8e\xb8\xf9\xd6\xce\x2d\x5c\x9f\xff\x34\x61\x19\xd7\x89\x91\x7a\xae\x12\xfb\x21\x29\xa3\x3c\xf2\xd4\x98\xff\x74\x47\x74\xbd\x41\x58\x2f\xe5\xfa\x58\x8f\x3d\x1c\x5b\x02\x31\xa1\x88\x18\xeb\x4d\x24\x39\x09\xa2\x0c\x45\x90\xcf\x2f\x43\xf1\xfd\x48\x20\x92\xb0\xc8\xc4\xcf\x40\x94\xa1\x08\xa5\xf1\xcb\x70\x44\x58\x73\x5f\x20\x42\xfa\xde\x5a\xf5\x73\x41\xfb\x70\xd4\x18\x29\xf8\x44\x88\xf2\x10\xe2\x3a\x1a\xa3\x8e\x8c\x7e\x32\x44\x79\x08\x89\xc2\x36\xc4\x3b\x88\xb6\xb0\xe5\x71\xe4\x7f\x13\xa3\x30\x72\x54\x66\x9e\xc7\x07\xc4\x31\x11\x31\xa1\xc5\x1f\xeb\x42\xf6\xfd\x0a\x8e\x1b\x21\x32\xfe\x18\x1e\x2a\x13\xcc\x83\xe8\xe5\x41\x2b\x91\x41\x9e\x62\x4f\x68\xc5\x1e\x3e\xf0\xb6\x06\x10\x04\xf2\x8e\x5f\xcf\x2a\xd6\xa3\x61\x73\x2e\x21\x23\x0f\xe4\x53\xbf\xcc\x14\x96\xc9\x0e\xc8\xb4\xbc\x95\xd1\x07\xf4\x70\xde\xca\x54\x87\xd1\x53\x44\x8c\xc5\xfa\xd8\x36\x3e\x5f\x64\x25\x83\xf3\x60\xe0\x0c\xf6\x84\xa9\x76\xd8\x5c\x79\x86\x94\xf1\xdb\x30\x24\xd6\x55\x13\x36\x64\xc7\xba\x7b\x38\xfa\x05\x6c\x48\xce\x67\xfe\x88\x4c\xf5\x11\x99\xeb\x84\x9d\xf7\x0e\xbc\x87\xec\xbc\x89\x2d\xcf\xe6\x02\xf5\x11\x3d\x3b\x41\x3d\x81\xf8\xc3\xda\xa7\x24\x28\xc3\xc9\x0a\xec\x17\x03\x88\xce\x23\xec\x4c\xec\x7b\x88\x4c\x2d\x21\xd3\x18\xf0\xcc\xc3\x32\x44\xed\x47\xad\xe0\x39\x4f\x70\x2b\x0f\xc9\xe8\x0f\xc7\x43\x6a\x9e\x37\x81\x3f\x5d\xea\x7b\xeb\xe1\x47\x2a\xc6\x63\xea\x8d\x3d\x6c\x43\x3d\x91\x2f\x7c\xfe\xf9\x50\x2b\x44\x4c\x58\xc0\xfb\x15\x22\x83\xf3\x3b\x29\xb3\x7c\x44\x4f\xe5\x11\x3d\x63\x64\xbd\xea\x5f\xd7\xa1\xda\xc6\xfb\x36\x5b\x91\x39\xce\x86\x63\x63\x37\x11\x91\x58\x1f\x33\x05\xf6\xb4\xf5\xad\x6f\xb4\x61\x64\x12\x57\x05\x63\x38\x0f\xae\x04\x2a\xe1\xd6\xb7\xf3\x69\x61\xf5\xb0\x67\x99\xc8\xd4\x1a\x6c\x67\xa2\xb2\x42\xcb\x18\x61\xeb\x43\xf2\xe4\x16\xe1\x4c\x4d\xd4\xcf\x68\x93\x37\x8f\xb5\x35\xbd\x9d\x61\x75\xb0\xc6\x46\x9b\x78\x5d\xdd\xf8\xa7\x78\xa5\x30\x86\x35\x57\x1f\xae\xc3\x59\x19\x36\x67\x1d\xd5\x43\xca\xa0\xbd\x13\xc8\x90\xd5\x20\x9b\xa9\x89\xfc\x4e\xf5\x60\xaf\x23\xe2\x61\x48\xcd\x7f\x9e\xb5\x46\xa0\x66\xf3\x5b\x6c\xcd\x8f\x04\x4e\xc1\xc7\xea\xa1\x7e\x8a\x9f\x9a\xc6\xc8\x4f\x8e\x68\xee\x65\xf7\x8b\xd0\x1c\xf0\x79\xbf\x8f\x85\xde\x2f\xfc\x3e\x46\xe6\x82\x40\x1c\x0b\xbd\x83\xd8\x0e\xc9\x78\x0e\xd7\x24\x01\x99\xba\xa0\x0c\x1b\x8b\xb8\xf8\x96\x44\x3f\xc2\x4f\xdd\xc1\x79\x79\xcf\x2f\x43\x0f\x12\xb5\x04\x71\x73\x41\x9b\xd8\xc7\x3c\x6c\xdc\x00\x38\x74\xbb\x71\xb1\xde\x1b\xa8\x84\x9f\x02\x82\x11\x6c\x43\xb2\xce\xec\x61\x4f\x1c\xeb\xab\x84\x9e\x6a\xa2\xf6\x63\x77\x70\x0d\xcb\xb0\x31\x6a\x2d\x8c\xcc\x02\x96\x19\xc4\x32\x4f\xe0\xd0\xdd\x0a\xcd\xe2\x53\xc0\x56\xe6\x25\x58\xc6\xc7\x56\x17\x44\xac\x63\xf5\x2c\x63\x3d\xa3\xec\x5e\xc0\xe1\x1b\xd9\x18\xd6\xf3\xa6\x9e\x0f\xea\xe9\x09\xae\x8b\xad\xb5\x90\x12\xc7\x70\x3d\xb1\xae\x23\x37\xbb\x10\x3d\x9b\x6c\xb5\x8c\x3f\x71\x42\xc6\xa8\xce\x23\x9e\x29\xc0\xbe\x11\x22\x83\x7d\x83\x94\xd1\x1f\xa9\x06\x8f\xea\xd1\xf3\x56\xb0\xcc\x18\x21\xb3\xec\x97\xc1\x15\xda\xe7\x88\x3c\xf8\xb1\x7a\x42\xee\xa7\x5f\xc5\xbb\x5c\x1f\xf4\x67\x4a\x82\x4f\xca\x9f\xf9\xf5\x84\xdc\x4f\x5f\xfa\xf5\x70\x85\x58\xe6\x3b\xac\x67\x1e\xa9\x57\xf9\x44\xde\x09\xdc\xf5\x70\x2d\x11\x72\x87\xc5\x4f\x11\x77\xd8\xc0\x0e\xb2\xde\xc2\xfa\x7c\x27\xbe\xa7\x90\x32\x5b\x58\xa6\x96\x90\x19\x38\xa2\x87\x95\xb9\x12\x94\x41\xb3\x38\x22\x61\x3f\x87\x72\xbc\xd2\x4e\x76\x2c\xee\xdb\xdb\xf1\x31\x1d\x8f\x4e\x8c\xa8\x83\x32\x6c\x94\x08\x78\x6f\x7d\x30\x86\xb3\xdf\x85\x08\xd4\x09\xac\xe6\x55\xe2\x29\x7e\x30\xce\x53\x6c\xac\xc3\xf1\x3c\xe2\x19\x9b\x19\xd9\xd3\x84\x2d\xbf\x1e\xac\x88\x8e\xb9\xdd\xe0\x6f\xa4\x44\x5c\x26\x72\x37\xdb\xb7\x11\x11\x35\x09\x1b\xc7\x4c\x04\xc2\xe6\x14\x76\x86\xec\xdd\x41\xc2\x56\x4d\x6c\xde\x61\x73\x2e\xd6\xb3\x4e\xc8\x74\x12\xeb\xea\x84\xb7\x77\x90\xc0\xa9\x5c\xc6\x7b\x8a\x6f\x40\xf4\x60\x20\x7f\x31\x6f\xf2\x26\xb7\x89\xa8\xd0\xd8\x9b\x4b\x5d\xf0\x0c\xb2\x59\x29\x70\xd3\x1c\x0c\x66\x58\x84\x9f\x42\xdd\xc0\x76\x84\x6c\x6f\xb3\xe7\x3f\xc4\x7a\xd8\xfe\xcf\x22\x9e\xcf\x0c\x59\x47\x71\xc9\xee\xc1\xe1\x9e\xc3\x26\xa1\x07\xaf\x94\xdd\x4d\x5e\x60\x2d\x87\xa3\x3a\x1d\x05\x10\x1a\xd5\x59\xef\x25\x3b\x42\x81\x75\xb1\xb7\xbf\x7d\x02\x29\x22\xf2\x05\xdb\x47\xc2\xb6\xe2\x75\x12\x63\xe1\xde\x42\x44\x17\x8e\xcf\x7a\xc2\xeb\xce\x87\x78\x9d\xed\x6d\xa4\x95\x04\xea\xf9\x60\x7c\x66\xf7\xc2\x15\xdc\x8b\xc0\xda\xd9\x0e\x89\x94\x88\xb4\x45\x84\xf7\xb2\x32\x36\x9c\x4f\xb1\xe5\x51\xe5\x91\x78\xd8\x8f\xc7\x62\xbd\xae\x03\x3f\x55\x46\x9c\x1d\xf6\xde\xdd\x7f\x38\x1e\x06\x4e\x37\x8e\x24\x5c\x13\x11\x6d\x70\x24\x89\xb0\x60\x6b\xb0\xe7\x0b\x7f\xb7\x3c\x62\x03\xcf\xdc\x80\x65\x3e\x0c\xfa\x06\x95\x7e\xd8\x5b\xd8\xfe\x18\x9b\x89\xd8\xcc\xc8\xfa\xcf\xd1\xde\xd7\xdb\xce\x49\x30\x26\x90\xdd\x39\xf6\x34\xd5\x13\x73\xae\x0f\xae\x82\x7e\x88\x11\x33\xd6\x33\x85\xf5\xa4\x63\x3d\x4b\xc1\x3d\xa5\xff\x1d\x5b\x3f\xfb\x47\xe7\xed\xfa\xa3\x4d\x64\xab\x7f\x8f\x78\xf8\x33\x68\xbc\x32\x7f\xa5\xca\xc7\x77\x10\x1e\xb6\x33\xf7\xf7\xfd\x08\xef\x95\x1f\xe1\xfe\xbe\x1f\x89\x28\xc6\x6b\xff\xe7\x78\x0e\x5b\x07\x6d\xd8\x97\x94\x80\x22\xb6\xfc\x32\x11\x0c\xf6\xb1\xc6\xe0\x9d\x91\xd6\xe3\xb1\x70\x5f\x8e\x87\x2b\x7f\xee\xaa\xff\x29\x1e\xdf\x2f\xc3\xc3\xb7\x5a\xee\xa6\x5f\x86\xcb\xf1\x23\xdc\x49\x8c\x70\x82\x5d\x1a\x8e\x09\x7b\x7e\x6d\x20\xbf\xfb\x42\xef\xf8\x68\x0d\x67\x61\x3d\x3e\x2f\x6c\x75\x5a\x8d\xeb\xed\x81\x60\x75\xca\xd6\x48\x9c\x69\xac\x27\x10\x8d\xb1\x9e\x55\xa2\x4a\xb1\x62\x99\x61\x2c\xf3\xa7\x81\xf8\x13\x1c\xeb\x73\xc1\xc8\x16\xc8\xa7\x81\x33\xe8\xcf\x83\x5c\xfc\x3d\x31\x7a\x14\xeb\xf9\x96\xdf\x0f\x23\xfe\x04\xaf\xfd\x9f\x60\x24\x9d\x38\x71\xac\x6f\xb0\x5d\x47\x2e\x51\x6b\xfd\x72\xb0\x46\xa2\x7f\x19\x82\x37\x71\x42\x86\xc2\xfb\x15\x88\x6c\x7d\x81\x7c\x31\x8f\x23\x9b\xed\x6d\x37\x43\x4f\xe4\xc1\x79\xb6\xba\x08\xde\xad\x02\x11\xc0\x4a\xe4\x6e\x56\x86\xbd\x2f\x4f\x11\x39\xae\x0f\x5b\xf5\xcf\x09\x8f\xfa\x4f\xd8\x1a\x5e\x3c\x9f\x0f\xf1\x89\xab\xc4\x76\xee\xc1\x08\xee\x6c\xb3\xfb\x1b\xf9\x07\x78\xaf\x71\x85\xc6\xe3\xfb\x47\xe7\x7f\x05\x7b\x14\xd6\xc3\x6d\xf7\x23\xbc\x6d\xbc\xcb\x7d\xc1\xfa\x90\xc3\x46\x60\x4f\x20\x26\x1c\x5e\x3b\x3e\xb3\x5c\x5c\x11\x51\x0f\x89\x38\xcf\xf6\x96\xab\x03\xf5\xaa\xdf\x86\x2a\x2e\x59\x09\xfb\xe7\x7c\x83\xa8\x13\xae\xe0\xb1\xb8\x84\x47\xe1\x5e\x4a\xe0\x5c\xb0\xb7\x89\x51\x9c\xdf\xf1\xef\x16\x09\xe9\x15\xdc\x22\x64\x58\xfb\xb0\x96\xaf\x0e\xce\x99\xce\x0f\xde\xdf\xa9\x09\x7c\xff\x62\xf3\x4e\x35\x71\x96\x2f\x06\x65\xd0\x72\xe0\x4e\x14\xf4\x5e\x1b\xb6\x6a\x11\x71\x47\xc3\xf7\x2f\x36\xba\x86\xdc\x07\x49\x0f\xaf\x0d\xf8\x46\xd0\xc3\x7b\x88\x7b\xf7\x9b\x3a\xfc\x70\xad\x5e\x1d\xac\x52\x02\x9d\x9c\x9e\x40\xfd\x63\x7b\x93\xa9\xd1\x2c\x5e\x17\x5b\x63\xcf\xb2\xf9\x2b\x58\xff\x04\x64\xd8\x3a\x5c\x10\x52\x43\xfa\xf7\xc2\x42\x9c\xa6\x7a\xac\xe7\xf9\x91\xfa\xd0\x42\x44\xda\x3e\xac\x87\x90\x09\xc4\x67\xfc\x7d\x3c\x74\xe3\x20\xef\x6d\x9c\x67\xc7\xfa\x7f\xc9\x7b\x17\xf0\x28\xaa\xfb\x7f\xf8\x73\xe6\x9c\x9d\xdd\x84\x04\x72\x59\xae\x01\xb2\x49\x48\xb8\x24\xdc\x36\x08\x44\x01\x29\x20\x88\x28\x02\xa2\x82\x22\x82\x20\x22\x45\x6e\xa2\x78\xe3\x22\x57\x45\x45\x54\x54\x44\x54\x0a\x18\x10\x2f\x9d\x4d\x00\x71\x8b\x72\x71\xb5\x54\xed\xb4\x56\xa5\x53\xf1\x3a\x8a\x34\xed\x68\xad\xb5\x53\xab\x25\xdf\xf7\x99\x33\xb3\x9b\xd9\x0d\xfe\xda\x7f\xff\xbf\xe7\x7d\xde\xe7\x79\xc9\xf3\xd9\xd9\x9c\x9c\x99\x39\xe7\x7b\xbe\xe7\x7b\x9f\x61\xaa\xd3\xa2\x94\x4a\xaa\xca\x77\xdf\x28\xa5\x72\x3c\xdb\x64\xbc\xa8\x56\xf6\x99\xe7\xf1\xfc\xa6\x8c\x7b\xd5\x79\x56\x77\x55\xea\x5e\x7f\x91\xf7\xfa\xd2\xd7\x47\xc6\x49\x52\x91\x0a\x87\x0f\x3f\x97\x1a\x4d\x3e\xd3\xa8\xfc\xdc\xb3\x6d\x9c\x3e\x5f\xfa\xec\x0d\x57\xaa\x5f\x24\xcf\x3a\xe9\xc8\x3a\xa6\xfb\xe4\xc6\x1c\xa7\x45\xd9\xdf\x8c\xc7\x64\x34\x2c\x8d\x0f\x37\x35\xd9\x2d\xc9\x38\x64\x5a\x3c\x4a\x4a\x5a\x9f\x8d\x9d\xf4\xad\xda\x65\xac\xe9\x5c\x19\x1f\x73\xed\x16\xcf\xa6\x6d\x8a\xed\x78\x11\xfb\xd9\x52\x9f\xca\x68\x00\x9b\x4b\x86\x33\x77\x79\x2f\x97\x7f\x64\x8b\x4b\x79\xf6\x96\xfc\xdc\x29\x5b\x42\x5e\x1c\x40\x4b\xfa\xef\xfc\x5f\x32\xfa\xf4\x27\x39\xf2\x27\xe4\x2a\xef\x92\x7e\x1c\xa4\x3c\x2c\x97\xb3\x70\xe3\x6c\xf7\xb9\x73\x97\x39\x29\xb9\xf7\xc5\x09\xd7\x72\x70\x5a\x5c\x6f\x3a\xe5\xef\x2c\x38\x53\x8e\xcc\xe3\x8d\x29\xee\xbc\x68\xab\x2f\xeb\x91\xb2\x01\x3c\xca\xbb\xdc\xfb\xa0\x6c\x91\xcf\x21\xbb\xb6\x16\x9b\x28\xb9\x65\xb6\xe4\x96\xf7\x65\x1f\xd9\xa2\x3c\xe2\xd3\xb9\xbb\x9b\xf9\x17\x2e\x6f\xcc\xf3\xf5\xb9\xc2\x67\x63\x97\xbb\xfb\x5d\xce\xab\xa3\x6c\x69\xeb\xad\xe0\x82\x66\xd9\xc0\x05\x92\xf2\xed\x52\x94\x77\x65\xef\x47\xf2\x5e\x3f\x95\xd7\xf9\xa8\x49\x5f\x78\xfb\xa2\x23\x32\xfd\xdc\xdd\x4d\xd6\x85\xdf\x8f\xf3\xac\x26\xbf\xaf\xe7\xfa\xc2\xcf\x35\xad\x7b\xda\x2a\x7b\x72\xcc\xcb\x2e\x35\xc5\xeb\x6e\xf6\xf2\x3b\x29\xfb\xc7\xf3\x0b\x7c\x2d\xae\xcd\xe6\x45\x96\x76\xfa\xc6\x7c\x9b\x6f\xcc\x5e\x74\xce\xc7\xcf\xee\xb3\xd6\x5b\x55\x5f\xdc\xa6\x69\x84\xee\x59\x9e\xce\x6d\xd6\x12\x98\xe9\x6b\x69\xf4\xad\xbb\x3b\xd3\x03\x72\x3c\xdf\x35\x49\x2d\xb7\x45\x2c\xf3\xc9\xb1\x11\xbe\xb9\xbb\x77\x0f\xf9\xe3\x5a\xcd\x46\xd8\x31\x2d\x63\x68\xa5\x5a\xfc\x1a\xd6\xf3\xdf\x9b\xae\xcc\x16\xf9\x32\x74\x7f\x6c\x1a\xa1\xdf\x3f\x65\x2f\x78\x99\xc7\x26\x89\x3d\xd7\x5b\xe5\x54\x8b\xeb\xa7\x24\x3d\x0b\x9f\x5f\x20\xe4\x98\x27\xca\x3e\xae\xc7\x31\xca\xcd\x9c\xca\x16\x57\x5f\xbc\x20\xf5\x8b\xcb\x75\xd2\x07\x71\x23\x15\x5e\xcb\xfc\xe6\x1e\x87\x6b\x6f\xb8\xfe\x97\x1c\xcf\x6e\xb9\xbb\x9f\x91\x7b\xf9\x2d\xb9\x97\x6f\x90\xbb\xbb\x79\x8b\x9b\xe5\x3c\xd0\xd4\xd2\xdc\x07\x39\x43\xcb\x8d\xbe\x96\x75\x4d\x67\x79\x3c\xe6\xfa\x20\x6e\xa6\x46\xae\x8e\x1b\xcb\xe5\x39\xcd\x7c\x10\x69\x07\x7a\x36\xd2\x20\x49\xb1\x8d\x92\x1a\xae\xae\xdc\x88\x94\x6f\xee\xee\x20\xaf\xc5\xdf\x67\x62\x5a\x46\xb5\x49\x92\x34\x6f\x71\x79\x7e\x77\x13\xcf\xb3\x89\x6e\xce\x48\xb6\x54\xc9\x79\xf5\xf1\xf1\x86\x2b\xd5\xfd\x3b\xce\xb5\x60\xfd\x11\x21\x37\xb6\xf3\xad\xf4\x53\x5c\x5f\x4f\x9c\xb9\x05\x5f\xcb\x7b\x0d\x95\x71\xad\x0f\x7c\x7d\x46\xf8\xce\x92\x31\x61\xf6\x89\xfc\x1c\x8a\xcc\x68\x8f\x9c\x69\x5a\x9c\xe4\xe6\xa6\x7d\x21\xe6\xf8\xf8\x70\x52\x93\xe7\xe2\xd9\x2d\xdf\xfa\xe4\xaa\xeb\x77\x9f\x6e\x5a\x0b\xa5\xc1\x93\x3f\xb3\x53\x92\xd6\xcd\x14\x9f\x94\x67\xb9\xf1\xb1\xb7\x9b\xf9\x3b\xb5\x69\xb9\x63\xe9\x01\xd1\x65\xa9\x96\x05\xcd\xfa\x2c\xf0\x49\xf5\xa3\xf2\x5e\x11\x9f\x54\xff\xc4\xd7\xf2\x09\x32\xbd\xbf\xd9\x3e\x09\x70\x5b\xd3\x5e\x3e\x83\x77\xdc\x27\x73\x77\xa7\xf2\x83\x99\x12\x29\xec\xa3\xd8\xbd\x3e\x29\x31\xcf\xa5\x7c\xd3\xce\x85\xf4\x77\x3c\x29\xb1\xba\x19\x8f\xf9\xec\x28\x4f\xfe\x58\xee\x2c\x9a\xcd\xf4\x82\x66\x33\x95\x51\xc7\x80\xbc\x7b\x50\xda\x90\x81\x99\x99\x2d\xc2\x70\xae\x93\xde\xc7\xa1\xb3\x9b\xc1\x77\xe5\x2a\x7f\xd7\xbb\x72\x93\x05\x22\xef\x2e\x16\xcb\x3e\xc7\xe4\x75\x34\xe9\x01\x5d\x25\x5b\xf6\xca\xb3\xfe\xe9\xfa\x32\x4d\xd1\x03\xd7\x97\xe1\x41\xd9\xb2\x58\xb6\x04\xe5\xbc\xce\x6b\xd2\xc2\x4a\x96\x6b\x99\xfb\x5a\x26\x64\x4a\x48\xa5\xac\x19\xaf\x96\xf9\xea\x2e\x56\xfb\xac\x2f\x7f\x1d\xc8\xcd\x3e\x3e\xf4\x55\x7d\xa4\x2a\x31\xac\x66\x95\x18\xbe\xfc\xa9\xaf\x65\x6c\x33\x09\xf0\x89\x4f\xeb\x1d\xf4\x49\x80\x17\x7c\x7b\xf9\x78\xb3\x1d\x77\x47\x33\x9e\x37\x7d\x7c\xf8\xb6\xb0\x52\x71\x92\xb1\x3e\x6b\x67\xbd\xb2\x29\xc5\x75\xaf\xfb\x6c\x3f\xe9\x7d\xa8\x8b\x64\xcf\xe7\x9a\xeb\xaf\x66\x2d\x73\x9b\xcd\x6b\x84\x8f\xaa\xee\xee\xbe\xc6\xb7\xdf\x97\xf9\x64\x82\x9f\xce\x21\x69\x8f\xf9\xe9\x5c\xe0\x59\x68\x29\x3a\xb3\xa1\xb2\xc5\xaf\x2b\x9b\xd5\xc9\xb0\x4f\x3c\x8b\xc8\x97\x19\x71\x5a\xd2\x56\xe7\x9c\xc6\xcd\xcd\xf4\xc5\x82\x33\x65\x2b\xd2\x56\x47\x5a\x8c\xde\x5a\xf8\x5b\xe4\x4e\x71\x23\x4e\x6c\xb4\xef\x2c\x57\xc3\xde\xe1\xf6\xf1\xd9\x48\x07\x64\x8b\x7f\xbd\x96\xb9\x33\x4d\xcb\x57\x6e\x3e\x63\x8b\x4b\x9f\x1f\x9a\xf6\x4e\x5a\x9f\x17\xe4\x75\x42\x69\x92\x7f\x41\xd2\x4a\xf1\x5a\xee\x68\x3c\x3f\x35\x9e\xa4\xcd\xbf\x39\x3d\x43\x87\x03\xb2\xcf\xc6\x34\xdd\x74\x7e\xc6\x4c\xdb\x39\x2d\x19\xf1\xf0\x05\x29\xf9\x33\xa5\xe9\x5e\xe9\x19\xf0\xd3\x76\x86\x6d\xd3\x51\xb6\xfc\xd6\x57\x81\x73\xaf\x67\x0d\xce\x4e\xbe\x5f\xc9\xe3\x96\xf5\x3e\xeb\xb4\x40\x52\xc3\xdf\xc7\x6d\xf1\xf7\xa9\xf0\xfa\x4c\xcc\xe8\xf3\x95\xbc\x97\x1b\x37\x3e\xd8\xc4\x87\x69\x55\x5e\xfe\xd8\xf2\x08\x1f\xe5\x07\x7a\x36\xdb\xe6\xff\xaa\xcf\x90\x66\x7d\x86\x34\xeb\x93\xb9\x0b\x3a\xca\x16\x5f\xdd\xa0\x6b\xf3\x67\x78\x6d\xff\x71\x1f\x5f\x26\xdd\xdd\x95\x1d\x65\xcc\xc1\x2f\xc7\xce\x97\x91\x1c\x7f\x06\x7c\x82\xcc\xc2\xa4\x65\xae\x9b\x65\x61\x3e\x97\x57\xf6\x65\x9c\xd3\xb2\xd2\xcb\xdd\x1d\xe7\xcb\x4a\x87\x9c\x96\x33\x5c\xc7\x5f\x8b\xd5\xfc\x3a\xd3\x7d\xfb\x3d\x79\x9d\x70\x46\x9f\xbb\xcf\x7c\x2f\x7f\x15\x25\xfe\xe1\x79\x49\xc2\x97\xab\x75\xe8\xf3\xbe\x17\xd3\xcb\x88\x86\x89\x0e\x32\x7e\xe2\xda\x5a\xfe\x4a\xcb\xb1\xbe\x7b\xb9\xf2\xa7\x51\xb6\xfc\x27\x7d\x7c\xbe\xa7\xdb\x92\x96\x3b\x3e\x2a\x5b\x76\xca\x8c\xbc\xbf\xcf\xc6\xe0\xa4\x24\xcf\xb8\x7d\xce\x70\x9d\xd9\x99\xd7\xc9\xe8\xe3\xcc\x7d\x6e\x5a\x1f\x47\x42\x1e\x72\xe6\x9e\x56\x1d\xfa\x8a\x33\x6b\xcf\xea\x76\xab\x5e\x65\x84\x21\xad\xcf\x2f\xa5\xbe\xb8\xc3\xd7\xc7\x5f\x65\xda\x5a\xae\xf2\x66\x9f\x8d\xdd\x57\xb6\x4c\xc9\xac\x43\x73\xbd\x92\x1f\xcd\x53\xd7\x9e\x41\x62\x6f\xfe\xaf\xfa\x2c\x38\xa3\xe4\xbf\xd9\x97\xbd\x4d\x6a\xfc\xa1\xe9\x9a\xda\xad\x54\x49\xeb\xe3\x1f\xf3\x58\x2f\xb6\x3c\x37\xa3\x0e\x56\x46\xa4\xd3\xb2\xa5\x7e\x2f\x5b\xca\x8d\xb4\x6c\xf2\x2b\x72\x16\xff\x49\x9f\xb9\xbe\xbd\x9c\xcc\x26\xb7\x4b\xb7\x13\xd2\x32\xc5\xc7\xe5\x75\xfc\x7e\xc1\x5a\x79\x9d\x15\xcd\x32\xc5\x47\x65\x54\x6d\xb3\xef\x3a\x9b\x42\xfd\x64\x9f\xb7\x9a\x7c\x6a\xf5\x5b\xa7\x4f\xe0\xde\x94\xad\x7e\xb3\x9c\x7b\x07\xdf\xbd\xfe\x24\x3d\x4d\xff\xbd\x36\x35\xd1\xc7\xf3\xa9\x37\x3a\x1c\xae\x1c\x74\x7d\x0a\x64\x64\x4f\xd8\x0b\x2e\x3f\xa7\xf9\x17\x9b\x33\xfa\x1c\x68\xd6\x67\xf6\x19\xfa\x2c\x68\x76\x9d\x05\x19\x11\x98\x27\xe4\x59\xe9\x1a\x6d\x73\x46\x9f\x4d\xf2\xac\x66\x5a\xef\x3f\xea\xf3\x98\x9c\xbb\xaf\xb6\x99\x7d\xdb\x54\x5b\xe8\x55\xc6\xfa\xea\x9f\xd9\x3f\xe5\xbc\xde\xf2\xf9\xf8\x1b\x25\x3f\xbf\x94\x99\x71\xe6\xe5\x72\x9f\xfa\x32\xce\xcd\xb3\xd2\x3c\xe7\x0c\x7d\xe6\x36\xcb\x5c\xb7\xcb\xe8\xf3\xc7\xcc\x3e\x3c\xd8\xac\x8f\xbf\x42\x7b\x8c\xa4\x58\xb2\xbe\xd7\xe9\xf3\x98\xab\x97\x7d\xd1\x5d\x57\x8a\x16\xfa\xe6\xfe\xad\x27\x69\xff\x7d\x9f\x6b\x32\xb3\xe4\xe9\x34\x94\x7b\xd0\xa5\xb3\xbf\xf6\x1b\x3e\x7e\x76\x6b\x53\x7d\x39\x32\xf6\x17\x49\x67\xbf\x3d\x76\x97\x1c\xf3\xff\xdc\xe7\x41\x6f\x9f\x66\x6a\x99\x9d\x2e\x3f\xbb\x5c\xe7\xad\xce\x4e\x87\x1a\x81\x99\xa9\x7a\x80\x90\xac\x17\xfd\xa3\xd3\xe2\x8d\x79\x8c\xba\x31\xc3\xa3\xcf\x6e\xaa\xef\xf5\xaa\xca\xfd\x4f\x25\x44\x32\xed\x43\xf7\xee\xca\xc1\x50\x8e\xec\xb3\xd3\x97\x65\x38\xe0\xf4\x09\x8c\xcb\x88\x00\x27\xed\x84\x33\xdb\x99\xbf\xf5\x5d\x27\x99\x65\x68\xba\xce\x88\x66\x9a\x3a\xd9\xa7\xa9\xaa\xd3\x95\x12\xdf\x3a\xd7\x51\x3e\x77\xae\xe3\x45\x8d\xa6\x3a\xd7\x51\xc6\x3a\xd7\xf1\xbc\x09\xff\xd3\x0d\x2d\x24\x0d\x87\xfa\xf4\xb2\xdc\xdd\x69\x4f\x1c\x6c\xf2\xc9\xf9\x0e\x9e\x97\x2d\x75\x8a\x73\xaf\xc0\x20\x49\xdb\x48\xd3\xdc\x45\x07\x39\x66\x37\x6a\xfd\x65\x33\x3b\xa1\xd9\x7e\xe7\x11\x79\x1d\xb7\x7a\xe4\x4b\xcf\x16\x3d\x20\xab\x47\xc6\x35\x79\x7f\x67\xa8\xe8\x18\x9a\xc1\x87\xfe\xa7\x12\x0e\xf8\x64\xb8\xbf\xcf\xcd\xce\xbd\xc4\x1c\x49\x9f\x24\x3f\x1f\x90\xbc\x31\xae\x29\x9a\xda\x8c\xe7\x3f\xc9\xe4\x79\x2f\xd6\xf4\x5b\xe9\x97\x6d\xf4\x79\x7f\xd2\xfb\x4e\xcf\x13\xf9\xe4\xfc\xdc\xcc\xfa\xb1\x33\xc4\xc3\x9b\x3d\xfd\x91\x51\x0d\x15\x4e\x45\xa4\x2f\xf4\xbc\x9b\x70\xf2\x9a\x9e\x07\xd4\x4e\xf6\x09\xf9\xe6\xee\xe9\x14\x49\x79\x37\x37\xb1\x1b\x80\x82\x92\x7f\xfb\x06\x96\xe5\xac\x92\xdd\xc9\xee\x64\x3d\xe5\x7b\x58\x7a\xc9\xf7\xb0\x9c\x2b\xdf\xc3\x32\x54\xbe\x87\x65\x92\x7c\x0f\xcb\x02\xf9\x1e\x96\x15\xf2\x3d\x2c\x2b\xe5\x7b\x58\x10\xa8\x0d\x3c\xaf\xf4\x0e\x68\x81\x97\x94\x01\x81\x57\x02\x47\x94\x9f\x04\x12\x81\x77\x94\xf3\x02\xc7\x03\x7f\x55\x2e\x0d\x7c\xaf\x32\x65\xa1\x2a\xd4\x4e\xca\xad\x6a\xa9\xfa\x13\xe5\x21\x75\xb8\x3a\x52\xa9\x57\xaf\x54\xa7\x29\x2f\xaa\x3f\x55\x17\x29\x2f\xab\xeb\xd4\xf5\xca\x6b\xea\xc3\xea\x56\xe5\x57\xc1\xaf\x82\x5f\x29\x6f\x87\x2e\x0a\x5d\xa4\xfc\x2e\x34\x35\x34\x53\x79\x27\x34\x3f\x34\x5f\x79\x3f\xb4\x28\xb4\x48\x39\x01\x05\x2d\x94\xa3\xca\x07\x80\xf2\x91\x62\xa2\x48\x39\xa9\xfc\x11\x11\xe5\xcf\xca\xdf\xd1\x45\xf9\x81\x33\xf4\xe6\x82\xe7\xa1\x3f\x2f\xe0\xed\x31\x9c\x17\xf1\x4e\x18\xc3\xcb\x79\x5f\x8c\x15\xfd\xc4\x00\x5c\x19\x78\x2c\xf0\x34\xae\xc6\x5c\x80\xd5\x01\x8e\x14\x61\xaf\x00\x2c\x01\xb0\x37\x00\xf6\x5b\xc0\xa1\x20\xfb\x00\x70\x3c\x7d\xf6\x47\x80\x7d\x05\x38\x12\x92\x7d\xef\x90\x11\x50\x54\x40\xc9\x01\x94\x02\x40\x69\x07\x28\x9d\x01\xa5\x0b\xa0\xf4\x90\x52\x40\x51\xfa\x43\x51\x06\x41\x51\x86\x41\x51\xce\x07\x94\xb1\x50\x94\x89\x50\x94\x2b\xa0\x28\xd3\xa0\x28\xb3\xa0\x28\x73\xa1\x28\x8b\xa0\x28\xb7\x40\x51\x96\x41\x51\x56\x43\x51\xd6\x43\x51\x36\x42\x51\x1e\x81\xa2\x6c\x85\xa2\x6c\x87\xa2\xec\x86\xa2\xbc\x00\x45\xd9\x0b\x45\x89\x43\x51\x0e\x43\x51\x5e\x87\xa2\xbc\x05\x45\xf9\x1d\x14\xc5\x80\xa2\x7c\x04\x28\x9f\x03\xca\x9f\x00\xe5\x6b\x40\xb1\x01\xe5\x5f\x00\x57\xa0\xf0\x10\xc0\x5b\x42\xe1\x61\x28\xbc\x03\x14\x67\xef\xf2\x0a\x80\x57\x01\x3c\x0a\x85\x0f\x84\xc2\x87\x00\x7c\x04\xc0\x2f\x00\xf8\x38\x28\xfc\x32\x28\x7c\x0a\x14\x7e\x0d\x14\x3e\x1b\xe0\xf3\xa0\xf0\xc5\x50\xf8\x6d\x80\x63\x85\xf2\xb5\x00\xbf\x17\xe0\x0f\x02\x7c\x33\xc0\x9f\x04\xf8\x4e\x80\xef\x01\xb8\x06\xf0\xfd\x00\x3f\x08\xf0\xa3\x00\x3f\x06\x70\x1d\xe0\xef\x02\xfc\x7d\x80\x7f\x02\xf0\x2f\x00\x6e\x01\xfc\x1b\x28\xfc\x3b\x80\x37\x02\x42\x00\x22\x1b\x10\x79\x80\x68\x03\x88\x8e\x80\x28\x85\x22\xba\x01\xa2\x17\x14\xd1\x0f\xec\xf4\x3d\x0e\x4f\xbb\x9f\xb4\xcc\xf7\xdd\x72\x3e\x21\xe5\x17\x20\xbf\x77\x16\x3a\x18\xb2\x65\x9f\x15\xb2\x25\x2c\x7b\x6a\xf2\x53\xd6\xa6\x03\xe2\xae\xe4\xe7\xe9\xf3\xbc\x16\x2d\x79\x16\x6d\xe5\xab\x93\x9f\x80\xfc\x3e\x8b\x3f\xe6\x7c\x77\x76\xd7\x99\x3e\xdd\xbb\xfc\xd8\x5f\x9d\xcf\xd3\xf7\xfc\x4f\x7f\xfd\xaf\x3f\x67\x3a\x14\xf8\xd1\x51\x2d\x4e\x7d\x4a\xfa\xb8\xb4\x22\x4b\x5c\x28\xdb\x13\xbe\x9e\x89\xe4\xd5\x9a\xcf\x8b\x6c\xb1\x2c\x35\xc7\xf4\xbf\x2e\x93\xb4\x5d\x96\xa4\xf0\xff\x40\x9f\xad\x67\x3a\x97\xb6\xb2\x4f\xfe\xf7\x3e\x95\xb3\x9d\x6b\xba\x4f\x5b\x29\x17\x37\x7d\x02\xc2\x6c\xfa\x94\x77\xef\xe6\x5b\xf1\x41\xbe\xef\xcd\x5a\x48\xc6\xfb\xbc\x39\xca\x73\x03\x1b\xe4\xff\x0b\xdf\x06\xfd\xf1\x1c\xbe\x80\xc5\x2a\x58\x15\x3b\x9b\xcd\x66\x7b\x94\xc5\xca\x7e\x9e\xc7\xf7\x88\x71\x62\x9c\x58\x26\x0e\x8a\x83\x62\x9c\x78\x3d\x30\x48\x8c\x43\x27\xb4\xa2\x04\xf2\x29\x81\x52\x84\xd1\x85\x2c\xac\x24\x0b\xab\xc8\xc2\x6a\xb2\xb0\x86\x2c\xac\x25\x0b\xeb\xc8\xc2\x51\xb2\x90\x20\x0b\xaf\x93\xc5\x0e\x92\x15\xa8\x25\x4b\x1d\x4e\x96\x7a\x1e\x59\xea\x28\xb2\xd4\xd1\x64\xa9\x63\xc8\x52\x2f\x22\x4b\xbd\x98\x2c\x75\x3c\x59\xea\x25\x64\xa9\x97\x92\xa5\x5e\x4e\x96\x3a\x99\xac\xe0\x36\x4a\x04\x77\x52\x02\x2d\x11\x40\x37\x64\xa3\x1b\x72\x30\x12\xa5\x18\x87\xa1\x18\x89\xf3\xd0\x19\x63\xd0\x19\x63\xd1\x19\x17\xa3\x33\xa6\x61\x24\x4e\xa1\x33\x1a\x30\x28\xf8\x14\xba\x05\x77\xa0\x1b\x18\x7a\x22\xda\xec\xfc\x91\xff\xe6\xfc\x91\x4d\xe7\xf3\xc9\x64\x81\xf3\x31\x64\xf3\x09\x64\xf3\x49\x64\xa2\x05\x5a\xd1\x32\xe4\xd3\x32\x7e\x0e\xe9\x7c\x04\xe9\x7c\x14\xe9\x7c\x34\xd9\x7c\x2c\xe9\x4e\x7f\x7e\x83\x1c\xfb\xb2\xe0\x4e\x5a\x86\x3c\xb4\x22\x1d\xf9\xa4\xf3\x73\xc8\xe2\x23\xc8\xe2\xa3\xc8\xe2\xa3\xc9\xe4\x63\xc9\xe2\x97\x92\xcd\x2f\x23\x83\x5f\x4e\x26\x9f\x4c\x36\xbf\x8a\x4c\x7e\x03\xd9\x7c\x15\x99\xc1\x6d\xa4\x07\x77\x92\x8e\xa8\xa4\x79\x1e\x19\x92\xee\x35\xa4\xe3\x6c\xd2\x31\x88\x74\x3c\x45\x3a\xeb\x4f\x3a\x1b\x48\x3a\x3b\x5b\xde\x41\xe3\x23\x48\xe3\xa3\x48\xe3\x63\xe4\x1d\x34\x3e\x81\x4c\x3e\x89\x74\x7e\x25\x99\x7c\x2a\xc5\xf9\xd5\x64\xf0\x69\xa4\xf3\x19\x14\xe7\xd7\x92\xc5\x67\x91\xc5\xaf\x23\x83\x5f\x4f\x3a\x9f\x4b\x3a\x9f\x47\x3a\x9f\x4f\x16\x5f\x48\x71\x7e\x23\xe9\x7c\x31\xc5\xf9\x4d\x14\xe7\xb7\x50\x9c\xdf\x4a\x16\x5f\x46\x71\xbe\x92\x2c\xb5\x82\x74\xb5\x1b\xe9\x6a\x0f\xd2\xd5\x87\x49\x57\x1f\x25\x5d\x7d\x8c\x74\xf5\x71\xd2\x83\x8f\x91\x11\xdc\x42\x46\xf0\x71\x32\x92\x6b\x18\xfc\x33\x99\x92\x16\x26\xf2\xc8\x42\xbe\x1c\x8d\xc5\x67\x78\x23\x58\x48\x16\x5f\x4c\x16\xbf\x89\x2c\x7e\x8b\xbc\x8b\x15\x7c\x8c\xac\xe0\x16\xb2\x82\x8f\x4b\x6a\x9a\xc1\x9d\x64\xa2\x0d\x3f\x42\x71\xfe\x1e\x59\xfc\x3b\xb2\x44\x21\x59\xa2\x2d\xc5\xc5\x60\xb2\xc4\x70\xb2\xc4\xc5\x64\x89\xd9\x64\x89\x39\x64\x89\x1b\xc8\x12\xf3\xc9\x12\x4b\xc9\x12\x77\x52\x5c\xac\xa2\xb8\x58\x43\x71\x51\x4b\x96\x78\x96\x2c\x11\x23\x4b\xd4\x93\x25\xf6\x93\x25\x0e\x90\x85\x0a\x04\xc8\x44\x36\x99\xbc\x9e\x4c\xfe\x12\x66\xf2\x83\x64\xf2\x77\xc8\xe4\x06\x25\xf8\x09\x32\xf9\xdf\xe4\x5d\x75\xfe\x03\x59\xa2\x84\x12\xa2\x9c\x4c\xd1\x95\x4c\x31\x9e\x4c\x31\x81\x2c\x71\x15\x99\x62\x2a\x59\xe2\x6a\xb2\xc4\x74\xb2\xc4\xb5\x64\x8a\x59\x64\x89\xeb\x28\x21\x66\x93\x2e\xae\xa7\x84\x98\x43\xba\xb8\x83\x12\x62\x29\xe9\xe2\x69\x4a\x88\x5a\xd2\xc5\x3e\x39\x0a\x5d\xbc\x28\x47\xa2\x8b\x43\x64\x8a\xc3\x64\x05\x9f\x22\x33\xb8\x83\x4c\x74\xf7\x8d\x4c\xe3\x07\x49\xe3\xef\x50\x2d\x37\xa8\x96\x9f\x20\x8d\xff\x8d\x0c\x87\x16\xfc\x07\x32\x44\x09\xd5\x8a\x72\x8a\x8b\xae\x14\x17\xe3\x49\x13\x13\xc8\x10\x57\x51\xad\x98\x4a\x86\xb8\x9a\x34\x31\x9d\x34\x71\x2d\x69\x62\x16\x19\xe2\x3a\xaa\x95\xb4\xba\x9e\x6a\x3d\x7a\x99\x62\x9e\xa4\x99\x29\x16\x90\x25\xee\xa0\x5a\x49\xbb\xa7\xa9\x56\xd2\x6c\x1f\x2d\x96\xb4\x7a\x91\x16\x3b\xf4\x12\x87\x48\x13\x87\xc9\x48\x8d\xb2\x45\x6a\x8f\xb5\x92\x9c\x6a\x38\x12\x42\x44\xd0\x59\x94\x92\x2d\xf7\xd3\x36\x32\x9c\x3d\x15\xdc\x49\x06\x5a\xf1\x7a\xb2\x3c\x2a\x5b\x92\xca\x27\xc8\x12\xe5\x64\x8b\xae\x64\x8b\xf1\x1e\x35\xaf\x26\x5b\x4c\x27\x5b\x5c\x2b\xef\x6f\x49\x0a\x1d\x22\xcb\xd1\xe7\x64\x89\x52\xb2\xd0\x09\x01\xd2\x91\x4d\x7a\xf2\xae\xfc\x08\xd9\xfc\x97\xf2\x9a\x16\x3f\x2e\xf9\xc3\x4e\x5d\x77\x94\xbc\xae\x95\xba\xee\x0c\xb2\xc4\x22\xc9\x1f\xb6\x58\x45\xb6\x58\x43\xb6\xb8\x8f\x2c\xf1\x3c\x59\xe2\xe7\x72\x55\x0c\x71\x40\xce\x51\x77\x47\x2f\x77\xa4\x81\x30\x02\x64\x21\xdb\x9b\x81\xc3\x8d\xa7\xc8\xe6\x36\xd9\xa2\x80\x6c\x51\x41\xb6\xe8\x46\xb6\xe8\x43\xb6\x38\x9f\x6c\x31\x93\x6c\x71\x23\xd9\x62\x03\xd9\xe2\x05\xb2\x85\x46\x76\x92\xeb\x82\x4f\x91\x15\xdc\x41\x16\x18\xda\xa0\x3b\xde\xc6\xd7\x0c\xfc\x3c\x3e\x9a\x4f\xe4\x93\xf8\x6c\x7e\x2b\x7f\x47\x9c\x27\x46\x8a\x51\x62\x8c\xb8\x5c\x5c\x2d\xa6\x8b\x19\x62\xae\x58\x2c\x9e\x07\x1b\x5e\xe7\x48\x6f\xf6\x31\x3f\xc6\x8f\x89\x1e\x01\x11\xbc\x20\x20\x82\x53\x82\x8b\x42\x1d\x83\x8b\x42\x1b\xb2\x22\xd9\xdf\x64\x7f\x17\x5c\xd4\xa2\x34\xb8\x28\xe7\xf3\x96\xfb\x5b\x3d\xd7\xea\xb9\xec\x6f\x5a\xbd\x92\x17\x11\x3d\xf2\x0b\xf2\xab\xf2\x87\xe4\x57\xe5\x8f\xcb\x2f\xc8\x9f\x95\x5f\x20\x7f\xaf\x2a\x98\x54\x38\xb6\xf0\x58\xe1\xb1\xfc\x59\x85\xc7\x44\x8f\xe0\x94\xa6\x9f\xd0\x86\x50\xc7\xd0\x06\xf7\x27\xb8\xc8\xff\xd3\x72\xbf\xfb\xd3\xea\x95\x16\xa5\xf2\x3a\xc9\x9f\xaa\xf4\x9f\xf0\x86\xfc\xaa\xc2\x63\x0e\x82\x53\xf2\x0b\x92\x08\x75\x74\x7f\x82\x8b\xc2\xdb\x9c\x31\xe7\x57\x65\x22\xbf\x20\xfb\x9b\xfc\x59\xf9\xb3\xb2\xbf\x73\x7e\x5a\xaf\x74\x3e\xf3\x0b\xdc\x7b\x87\x36\x14\x4c\x72\x7e\x72\x3e\x2f\x1c\xeb\x22\x39\x1a\x39\xa2\xe7\x0a\x8f\xb5\x7a\xc5\x41\x5e\xc4\xf9\x69\x33\xb3\xcd\x17\xf2\x9e\x1b\x1c\x7a\x14\x8e\x6d\xf3\x75\xbb\x5e\xed\x45\x87\xe3\x45\x68\xf3\x75\x91\xdd\xe6\xeb\xce\xcf\xb5\xeb\xd5\xf9\x23\xa7\xb5\xb8\x4b\x91\xdd\x5e\x14\x1f\xef\xfc\x51\xc4\xe8\x70\xbc\xbd\x28\x51\xc2\x1b\x4a\x57\x94\x28\xa5\x0f\x56\x88\xf0\x86\xee\x3d\x4a\x57\x74\x1f\xd4\xfd\x8a\xd2\x07\xf3\x87\xe4\x0f\xe9\xbe\x39\x7f\x48\xf7\xd7\x8b\x90\x3f\xa4\xc7\xb1\xf6\xa2\x74\x45\x8f\xf7\x2b\x23\x95\x15\xa5\x2b\x9c\x9f\xca\x3e\x95\xfd\x2b\x2f\xac\xfc\x9d\xd3\x5a\xd5\xae\xb2\x8f\xd3\xd2\x73\x5e\xcf\xbd\x95\x91\x5e\x13\x2a\xfb\xf7\xde\x5b\xd9\xa7\xaa\x5d\x55\x3b\xa7\x67\xcf\x79\x3d\xe7\x95\xae\xe8\xf3\x60\x9f\x77\xfb\x7c\xdf\x7d\x73\xdf\x05\x7d\x1e\xec\xbb\xc0\x69\xef\xf3\x6e\xdf\xf5\xa5\x2b\xfa\x2e\xe8\xf3\x7d\x9f\xef\xfb\x6e\xed\xbb\xd5\x69\xeb\xbe\xb9\xfb\xe6\xbe\xdb\xfb\xbc\xeb\xfc\xde\x77\x7b\xdf\x05\x7d\xd7\xf7\x9c\xd7\xf7\x60\xdf\xef\xfb\x6e\xad\x8c\x54\x5e\x18\x5d\xec\xa0\x5f\xff\x7e\xfd\x4b\x57\xf4\x9b\xe9\x5c\xb9\x74\x45\x65\xff\xbe\x07\x1d\xf4\x5d\xef\xf4\x75\xdb\x9c\x73\x2a\x23\x55\xed\xfa\x7c\xef\x9c\xd9\x73\xaf\x33\xc6\x3e\xef\xf6\x7b\xfd\xac\x63\x67\xfd\x69\xe0\x85\x67\xdb\xe7\xec\x76\xc6\xe3\x1c\x2b\xfb\xf4\x5d\x90\x84\xd3\xbf\xdf\xeb\x7d\xde\x1d\xd4\x79\x70\xde\xe0\xfd\xa5\x2b\x2a\x23\xce\x59\x43\xa6\x0d\x59\xe9\xc0\xe9\xed\xf4\x90\x57\x5d\x30\x64\xa7\x33\x52\xe7\xac\xa1\x37\xff\xe4\x40\xb2\xdd\x41\xe5\x85\xa5\x2b\x1c\x38\x7f\x4f\x8e\xc7\xe9\xe7\xdc\x71\xd8\xac\xa6\x11\xa6\x46\xbf\x3e\x89\xe4\x18\xdd\x71\x9d\xb3\x7b\xd8\x1d\xc3\xee\x70\xae\xe8\x1c\x87\xad\x1c\x76\x60\xf8\x6d\xc3\x9f\x73\x7e\x77\xd6\x59\xae\xbf\x07\x3f\xcf\xfd\x27\x38\x13\x27\xfa\x11\x5c\x94\x44\xf2\xa7\xcd\xcc\xe4\x4f\xcb\xfd\x6d\xbe\x48\xfe\xb8\xfc\xd7\x84\x76\xbd\x82\x17\x38\x3f\xce\x8e\x0d\x08\x07\x1d\x8e\xa3\x1d\x7f\x2f\xa5\x59\x0c\xa9\x59\x1c\x9d\xe6\xd7\x67\x8e\x66\x71\xb4\xca\x2c\xa9\xdb\x0c\x31\x87\x8c\x66\xb2\x7a\x29\x19\xe2\x41\x7c\x20\x6a\xc9\x90\xba\xcd\x93\x2e\x8e\x16\x41\x7f\x04\x28\x8e\x6c\x8a\x63\x34\x59\x7c\x1f\xd9\xfc\x37\x64\xf3\xdf\x91\xcd\xff\x46\x3a\xff\x56\xde\xd9\xe4\x3f\x90\x2e\x80\xce\xa2\x15\x59\x22\x5f\xca\x31\x53\x94\x49\x59\x66\x8a\x6e\x64\x8a\xee\x64\x8b\x4a\xb2\x45\x4f\xb2\x45\x6f\x29\xdb\x4c\xd1\x97\x6c\x31\x81\x74\x31\x99\x6c\x71\x25\xd9\x62\x2a\xe9\x62\x1a\x59\xe2\x1a\x39\x5a\x5d\xcc\x26\x53\xcc\xf1\x46\xea\x8e\xd2\x14\x77\x93\x25\xee\x21\x4b\x3c\x4a\xb6\x78\x8c\x6c\xf1\x38\xd9\x62\x1b\x59\x62\x3b\x59\x62\x27\x59\xa2\x96\x4c\xb1\x9f\x6a\xc5\x01\xaa\x15\x2f\x93\x2d\x0e\x93\x1e\x7c\x8a\xe2\xc1\x1d\x14\x0f\xad\x21\x2b\xb4\x96\xac\xd0\x3a\xb2\x42\x77\x91\x85\x07\xa4\x65\xe5\x5a\x13\x3a\xaf\x47\x98\xef\x23\x93\xc7\xc9\xe0\x07\x11\xe6\x47\x28\xc1\x5f\x23\x83\xbf\x45\x06\xff\x0d\x99\xfc\x77\x8e\x36\x47\x58\xd2\xfb\x04\xc2\xfc\x33\x84\xf9\xe7\x08\xf3\x93\xa4\xf3\x2f\xa4\x04\xb7\x78\x03\xc2\xfc\x4f\x08\xf3\x3f\x23\xcc\x2d\xd2\xf9\x97\x08\xf3\xaf\x10\xe6\x7f\x21\x8b\x7f\x8d\x30\xff\x2b\xc2\xfc\x1b\xb2\xf8\xdf\xc9\xe2\x36\x59\xfc\x1f\x08\x4b\x8b\xe0\x9f\x08\xf3\xef\x11\xe6\xff\x42\x98\x9f\x46\x98\x13\xc2\xc2\xf1\x4e\x14\xb2\x84\x40\x58\x04\xc8\x12\x2a\x99\x22\x9b\x74\xd1\x02\x61\x91\x8b\xb0\x68\x89\xb0\xc8\x43\x58\xe4\x93\x29\xd7\xbc\x0d\xc2\xa2\x2d\x25\x44\x3b\xd2\x45\x07\x84\x45\x47\xb2\x44\x67\x84\x45\x19\x99\xa2\x0b\x59\xa2\x3b\x99\xa2\x07\x59\xa2\x92\x4c\x51\x45\x96\xe8\x49\xa6\xe8\x45\x96\xe8\x2d\x57\xc2\x14\x51\xb2\xc4\x20\x84\x25\xef\x0c\x45\x58\x0c\x43\x58\xf2\xd0\x48\x84\xc5\xf9\xd2\x53\x0a\x8b\xb1\x08\x4b\x9e\x1a\x8f\xb0\x98\x88\xb0\xb8\x0c\x61\x31\x09\x61\x31\x99\x4c\x71\x05\x59\xe2\x4a\x32\xc5\x14\x47\x47\x22\x2c\x66\x3a\x16\x0c\xc2\xd2\x72\x71\xac\x96\xb9\x08\x4b\x9b\x6a\x1e\x99\xd2\xae\x5a\x40\xa6\xb8\x91\x2c\x71\x13\xc2\xe2\x66\x32\xc4\x12\xd2\xc5\xad\x08\x8b\xdb\x11\x96\xd6\xcd\x72\x84\xc5\x9d\x94\x10\xab\x28\x21\xd6\x50\x42\xdc\x45\x96\xb8\x9b\x0c\x71\x0f\x19\x62\x03\x59\x62\x13\xc2\xe2\x11\x84\xc5\xa3\x64\x8a\xcd\x64\x89\xc7\xc8\x14\x5b\xc8\x12\x8f\x93\x29\xb6\x4a\x4e\xd0\xc5\x6e\x84\xc5\x1e\x84\x25\x4f\xbf\xe0\xf8\x7c\xd2\x6e\xd3\x45\x9d\xb4\xdd\x74\xb1\xd7\xc7\xeb\x2f\x91\x21\xe2\xa4\x8b\x83\x08\x8b\x97\xc9\x14\xaf\x38\xb6\x02\xc2\xe2\x28\x59\xe2\x55\x32\x44\x42\xda\xa5\x7e\x8b\xd2\xb5\xae\x05\xbf\x8c\x2c\x7e\xb9\xb4\xbd\x1d\xbb\xdb\x46\x80\x8f\x21\x8b\x4f\x20\xcb\xb1\xf6\xf9\x22\xb2\xf9\xcd\x64\xa3\x47\xca\xf3\xa9\x21\x03\x67\x93\x81\x41\x64\xe2\x29\x32\x59\x7f\x32\xd8\x40\x32\xd9\xd9\x64\xf2\x73\x28\xc1\x47\x50\x82\x8f\xa2\x84\xbc\xca\x58\x4a\xa4\xae\x74\x25\xd9\x7c\x2a\xe9\xfc\x6a\x32\xf9\x34\x32\xf9\x0c\xd2\xf9\x2c\x32\xf9\x75\x64\xf2\xeb\xc9\xe4\x73\xc9\xe4\xf3\xc8\xe4\x0b\x49\xf7\x2c\x6f\x9d\xdf\x44\x3a\xbf\x85\x74\xbe\x8c\x74\xb5\x82\x0c\xb5\x1b\x19\x6a\x0f\x32\xd4\x87\xc9\x54\x1f\x25\x53\x7d\x8c\x4c\xf5\x71\xe9\x2b\x24\xad\x6c\x1b\x1d\xd1\x4a\xee\x09\x0b\x5d\xc8\xc6\x4a\xb2\xe1\xcc\x6a\x35\xd9\x58\x43\x36\xd6\x92\x8d\x75\x64\xe3\x28\xd9\x48\x90\x8d\xd7\xc9\x66\x07\xc9\x0e\xd4\x92\xad\x0e\x27\x5b\x3d\x8f\x6c\x75\x14\xd9\xea\x68\xb2\xd5\x31\x64\xab\x17\x91\xad\x5e\x4c\xb6\x3a\x9e\x6c\xf5\x12\xb2\xd5\x4b\xc9\x56\x2f\x27\x5b\x9d\x4c\x76\x70\x1b\x59\xc1\x9d\xce\x7d\x92\x1e\x11\xba\x90\x8e\x73\xa4\x57\xa8\x63\x15\xe9\x58\x4d\x3a\xd6\x90\x8e\xb5\xa4\x63\x1d\xe9\x38\x4a\x3a\x12\xa4\xe3\x75\xd2\xd9\x41\xd2\xf9\x35\x64\xf3\x25\x64\xf3\xdb\xc8\xe6\xb7\x93\xcd\x97\x92\xcd\x97\x93\xcd\x57\xc8\x11\xe9\xea\x70\xd2\xd5\xf3\x48\x57\x47\x91\xae\x8e\x26\x5d\x1d\x43\xba\x7a\x11\xe9\xea\xc5\xa4\xab\xe3\x49\x57\x2f\x21\x5d\xbd\x94\x74\xf5\x72\xd2\xd5\xc9\xd2\x4a\x73\xbd\xae\xc5\x72\xb5\xfc\xc8\xcf\x80\xe3\xbf\xfa\xd1\x45\xd2\xab\x09\x2b\x33\xb0\x2a\x03\xab\x33\xb0\x26\x03\x6b\x33\xb0\x2e\x03\x47\x33\x90\xc8\xc0\xeb\xe9\x70\x7c\x68\x3f\x1c\x7f\xda\x0f\xe9\x5b\xfb\x71\x5e\x06\x46\x65\x60\x74\x06\xc6\x64\xe0\xa2\x0c\x5c\x9c\x81\xf1\x19\xb8\x24\x03\x97\x66\xe0\xf2\x0c\x4c\x4e\x87\xe4\x60\x3f\x76\xa6\x03\x8c\xcf\x26\x1b\xd9\x49\x3b\x3f\x65\xd3\x27\x6d\x79\xcf\x3f\x90\x76\xba\x63\xa3\x2f\x48\xfa\xdd\xde\xea\x1a\x18\x48\x16\x06\x93\x8d\x11\x64\xe3\x02\xb2\x30\x8e\x6c\x8c\x27\x1b\x97\x90\x8d\x4b\xc9\xc6\x24\xb9\x5b\x0c\xac\x22\x03\xab\xc9\xc0\x1a\x32\xb0\x96\x0c\xac\x23\x03\x8f\x93\x85\xad\x64\xe1\x09\xb2\xf0\x24\x59\xd8\x41\x36\x76\x92\x8d\xa7\xc9\x46\x2d\xd9\xd8\x45\x36\x76\x93\x8d\x5f\x90\x8d\x83\x64\xe3\x65\xb2\xf1\x8a\xdc\x65\x06\x5e\x95\x3b\xcd\xc0\x6b\x72\xb7\x19\xf8\x25\xd9\xf8\x98\x2c\x7c\x4a\x16\x3e\x23\x0b\x27\xc9\xc2\xf7\x64\x33\x95\x6c\x16\x22\x9b\xe5\x92\xcd\xda\x92\xcd\xda\x93\xcd\x7a\x90\xc5\x2a\xc9\x66\x55\x64\xb1\x9e\x64\xb3\x5e\x64\xb1\xde\x64\xb3\x3e\x64\xb1\xbe\x64\xb3\x28\x59\xac\x9a\x6c\xd6\x8f\x2c\x76\x16\xd9\xec\x1c\xb2\xd9\x60\xb2\xd9\xb9\x64\xb3\x85\x64\xb1\x45\x72\x77\x1b\xec\x65\xb2\xd9\x21\xb2\x1d\x1a\x06\x6a\xc9\x08\xec\x22\x3b\x70\x52\xee\x78\x43\x1d\x21\x77\xbd\xa1\x8e\x94\x3b\xdf\x50\xcf\x97\xbb\xdf\x50\xc7\x90\xa1\x5e\x28\x25\x80\xa1\x8e\x95\x52\xc0\x50\xc7\x49\x49\x60\xa8\x13\xa4\x34\x30\xd4\x89\x52\x22\x18\xea\x65\x52\x2a\x18\xea\x24\x29\x19\x0c\xf5\x0a\xb2\xd5\x75\x64\xa9\x77\x91\xad\xde\x4d\x96\xba\x9e\x6c\xf5\x1e\xb2\xd4\x7b\xc9\x56\xef\x23\x4b\xdd\x40\xb6\x7a\x3f\x59\xea\x46\xb2\xd5\x07\xc8\x52\x1f\x24\x5b\x7d\x88\x2c\x75\x93\x94\x2a\xae\x64\x5e\x9c\x11\x6b\x4a\x60\x20\xe9\x18\x4c\x16\x46\x90\x89\x0b\x48\xc7\x38\x32\x30\x9e\x0c\x5c\x42\x06\x2e\x25\x03\x97\x91\x85\x49\x64\x60\x25\x25\xb0\x8a\x12\x58\x4d\x09\xac\xa1\x04\xd6\x52\x02\xeb\x28\x81\xc7\x49\xc7\x56\xd2\xf1\x04\xe9\x78\x92\x74\x38\x7e\xeb\x4e\x32\xf1\x34\x99\xa8\x25\x13\xbb\xc8\xc4\x6e\x32\xf1\x0b\x32\x70\x90\x0c\xbc\x4c\x06\x5e\x21\x03\x47\x29\x81\x57\xc9\x44\x82\x12\x78\x8d\x4c\xbc\x4e\x09\xfc\x92\x4c\x7c\x4c\x3a\x3e\x25\x1d\x9f\x91\x8e\x93\xa4\xe3\x7b\x32\x98\x4a\x06\x0b\x91\xc1\x72\xc9\x60\x6d\xc9\x60\xed\xc9\x60\x9d\xc8\x62\x25\x64\xb1\x1e\xa4\xb3\x4a\x32\x58\x15\xe9\xac\x27\x19\xac\x17\xe9\xac\x37\x19\xac\x0f\xe9\xac\x2f\x19\x2c\x4a\x3a\xab\x26\x83\xf5\x23\x9d\x9d\x45\x06\x3b\x87\x2c\x36\x98\x2c\x76\x2e\x59\x6c\x21\xe9\x6c\x11\x19\xec\x20\x25\xd8\xcb\x64\xb2\x43\x64\xb2\x13\x64\x39\x9e\x70\xa0\x96\x12\x81\x5d\x64\x06\x4e\x92\xa1\x0e\xa7\x84\x3a\x82\x4c\xf5\x3c\x4a\xa8\x23\xc9\x54\x47\x51\x42\x3d\x9f\x4c\x75\x34\x25\xd4\x31\x94\x50\x2f\x24\x53\xbd\x88\x12\xea\x58\x32\xd5\x8b\x29\xa1\x8e\x23\x53\x1d\x4f\x09\x75\x02\x99\xea\x25\x94\x50\x27\x92\xa9\x5e\x4a\x09\xf5\x32\x32\xd5\xcb\x29\xa1\x4e\x22\x53\x9d\x4c\x09\xf5\x0a\x32\xd5\x75\xa4\xab\x77\x91\xa1\xde\x4d\xba\xba\x9e\x0c\xf5\x1e\xd2\xd5\x7b\xc9\x50\xef\x23\x5d\xdd\x40\x86\x7a\x3f\xe9\xea\x46\x32\xd4\x07\x48\x57\x1f\x24\x43\x7d\x88\x74\x75\x53\x53\x0c\x08\x83\x53\x5e\x7a\x3d\xd9\x3c\x4e\x16\x3f\x48\x36\x3f\x44\x16\x3f\x42\x16\x7f\x8d\x2c\xe9\xb9\x1f\x23\x9b\xbf\xe5\x45\x05\xde\x75\xbd\x78\x6e\x90\xc5\x4f\x90\xcd\x3f\x22\x9b\x9f\x24\x9b\x5b\x64\x8b\x6c\xb2\x45\x5b\xb2\x44\x3b\xb2\x45\x31\xd9\xa2\xc4\x17\x41\x70\x3c\xfd\xd1\x32\x92\x60\xa7\x45\x12\x66\xc8\xb8\x8c\x2d\xae\x93\x91\x0f\xd7\xfb\xbf\x99\x2c\xb1\x84\x6c\x71\x87\x8c\x04\x58\x62\x15\x59\x62\x0d\x59\x32\x12\x70\x3f\xd9\xe2\x09\xb2\xc5\x53\x64\x89\x9f\x91\x25\x76\xc8\x88\x48\x53\x84\x20\x19\x95\x78\x89\x2c\x11\x27\x5b\x1c\x22\x5b\xbc\x4a\x96\x48\x48\x3e\x76\x25\x91\x10\xa5\x08\x4b\xfb\x3c\x19\x6b\x6a\xc7\x5f\x22\x5b\xc6\x0d\x0c\x5f\x24\xab\x24\xc3\xf2\xbf\xce\x8b\x66\x5d\x9f\x8a\x68\xe9\x62\xbe\x8c\x1f\x59\x5e\x64\xc6\xfa\xd1\x68\xd6\x20\x04\xc8\x40\x36\x19\x98\x4c\x06\xae\x20\x03\x57\x92\x81\x29\x64\xe0\x10\x19\x6c\x80\x5c\x81\x04\x3f\x48\x09\x49\xfd\x77\x48\x97\x94\x36\x68\x2b\x3f\x41\x09\xe9\x8f\xb8\x9e\x81\x25\x7d\x12\xc7\x2b\x28\x90\x23\xdc\x2a\xca\xc9\x10\x15\x64\x89\xae\x64\x88\x6e\x64\x89\x3e\x8e\x3d\x49\x09\x2f\x02\xa6\x7b\x11\x30\x5d\x4c\x27\x5d\x5c\x4b\x09\x2f\x02\xb6\xd5\x9b\xc9\x56\x39\x93\x3b\x68\xab\x9c\x81\x43\xd5\x6d\x1e\x65\xb7\x7b\xd4\xdd\x29\x67\xb6\xd5\x8b\x39\x6d\x15\xfb\xc9\x14\x2f\xd2\x56\x71\x80\x4c\x71\x88\x12\x8e\x4f\xa3\x76\x25\x43\xed\x4e\x86\xba\x59\xc6\x66\x8c\xe0\x0e\x32\xa0\x22\xe0\xe8\x07\xb2\x65\x54\x73\xbe\x8c\xad\xd8\x41\x47\x4e\x0b\xb4\x22\x1b\xf9\x72\x45\xec\xe0\x4e\xd9\x12\x40\x18\xd9\x08\x07\x9f\x42\x38\xb8\x03\x61\x04\xa4\x46\xc8\x94\xca\x83\x92\xd7\xc4\x48\xb2\x30\x8a\x2c\x9c\x4f\x16\x26\x90\x85\x89\x64\xe1\x32\xb2\xb1\x9d\x2c\x3c\x43\x16\xf6\x90\x85\x67\xc9\xc2\x73\x64\xe1\x79\xb2\xb0\x97\x2c\xec\x23\x0b\xfb\xc9\xc2\x8b\x64\xc1\x59\x93\x38\x59\xf8\x15\x59\x78\x93\x2c\xfc\x9a\x2c\xfc\x86\x2c\xbc\x4d\x16\xde\x21\x0b\xef\x91\x85\xdf\x93\x85\x3f\x90\x85\x13\x64\xe1\x43\xb2\x58\x2b\xb2\x58\x3e\x59\xac\x90\x2c\xd6\x9a\x2c\xd6\x89\x6c\x56\x42\x36\x9b\x41\x16\x3b\x42\x16\x3b\x41\xb6\x3a\x85\x2c\x75\x2a\x59\xea\x34\xb2\xd4\x6b\xc8\x52\x67\x91\xa5\xce\x26\x4b\x9d\x43\x96\xba\x80\x2c\x75\x11\x59\xea\x62\xb2\xd4\x5b\xc8\x52\x6f\x23\x4b\xbd\x83\x2c\x75\x19\x59\xea\x0a\xb2\xd4\x95\x64\xa9\xab\xc9\x52\xd7\xfa\x68\x35\x18\x23\x11\xc5\x28\x44\x71\x3e\xa2\x98\x80\x28\x26\x22\x8a\xed\x88\xe2\x19\x44\xb1\x07\x51\x3c\x8b\x28\x9e\x43\x14\xcf\x23\x8a\xbd\x88\x62\x1f\xa2\xd8\x8f\x28\x5e\x44\x14\x07\x10\x45\x1c\x51\xfc\x0a\x51\xbc\x89\x28\x7e\x8d\x28\x7e\x83\x28\xde\x46\x14\xef\x20\x8a\xf7\x10\xc5\xef\x11\xc5\x1f\x10\xc5\x09\x44\xf1\x21\xa2\xac\x15\xa2\x2c\x1f\x51\x56\x88\x28\x6b\x8d\x28\x9b\x81\x28\x3b\x82\x28\xff\x23\xa2\xbc\x11\x51\xc1\x11\x15\x39\x88\x8a\x21\x88\x8a\x0b\x10\x15\xe3\x10\x15\x1b\x11\x15\x4f\x22\xaa\x4e\x41\x54\x9d\x8a\xa8\x3a\x0d\x51\xf5\x1a\x44\xd5\x59\x88\xaa\xb3\x11\x55\xe7\x20\xaa\x2e\x40\x54\x5d\x84\xa8\xba\x18\x51\xf5\x16\x44\xd5\xdb\x10\x55\xef\x40\x54\x5d\x86\xa8\xba\x02\x51\x75\x25\xa2\xea\x6a\x44\xd5\xb5\x88\xa2\x73\x72\xb7\xf0\x7a\xd2\xb9\x63\x97\xbe\x43\x86\x17\xf7\xd5\xe5\x6e\x68\x1e\xf3\xd5\x3d\x8e\x37\x3c\x8e\x37\xc5\x74\x32\xc5\xb5\xa4\xa7\x62\xbe\xd7\x53\x42\xc6\x7a\x9f\xa6\x84\xd8\x27\xe3\xbb\xba\x38\x44\xba\x17\xdb\x75\xb9\xb6\x2f\x02\xa4\x21\x9b\x34\x54\x90\x85\x1e\x64\x21\x4a\x16\xfa\x91\x85\x01\x64\xe2\x6e\xb2\xb0\x89\x2c\x3c\x4c\x16\x1e\x21\x0b\x8f\x92\x85\xcd\x64\x61\x0b\x59\x38\x46\x16\xde\x20\x0b\x6f\x91\x05\x9d\x2c\x7c\x44\x16\x3e\x21\x0b\x26\x59\xf8\x9c\x2c\xd6\x92\x2c\x96\x47\x16\x2b\x20\x8b\x85\xc9\x62\x5d\xc8\x64\x15\x64\xb2\x6b\xc8\x62\x87\xc9\x62\x1f\x90\xc9\xa7\x4b\x8b\xc0\xe2\x3f\x25\x5b\x44\xc8\x52\xe7\x93\xa5\x2e\x24\x4b\xbd\x91\x2c\xf5\x26\xb2\xd4\x25\x64\xa9\xb7\x92\xa5\xde\x4e\x96\xba\x94\x2c\x75\x39\x59\xea\x9d\x64\xa9\xab\xc8\x52\xd7\xc8\x59\x68\xc1\x1d\xa4\x39\xfb\xc9\x8d\x87\xa6\xe2\x99\x03\x65\x34\xd8\x8f\xec\x0c\xe4\x60\x64\x1a\x4a\x31\x2e\x0d\x43\xbd\x2c\xcd\x50\x5f\xb6\xc6\x8f\x31\x19\x18\x9b\x81\x8b\x33\x30\x0d\x23\xd3\x70\x0a\x9d\xd3\xd0\x80\x41\x7e\xc8\x88\xb5\x1f\x3b\xd2\xf1\x5f\xcd\x30\x1d\xff\xef\xcf\x70\xa4\x1f\xff\x76\x86\x91\xd4\xac\x92\x96\xb3\x23\x23\x33\x2d\xe1\x0c\x99\x29\x2d\x56\xc7\x5a\x75\x2c\x55\xc7\x4a\x75\x2c\x54\xc7\x3a\xcd\xb0\x4c\xa5\x75\xe8\x58\x86\x8e\x55\xe8\x58\x84\x8e\x35\xe8\x58\x82\x0f\x39\x5c\xe4\x8d\x40\x11\xfb\xc8\x16\x2f\x92\x8d\x8b\x53\x59\x05\xc7\x37\xab\x70\xfc\x71\xb2\x11\x25\x1b\xfd\xc8\xc6\x00\xb2\x3d\xaf\xf3\xcc\xb9\xc8\xbb\xc9\xc6\x26\xb2\xf1\x30\xd9\x78\x84\x6c\x3c\x4a\x36\x36\x93\x8d\x2d\xd2\x42\x6f\xf2\xb7\x8e\x91\x8d\x37\xc8\xc6\x5b\x64\x43\x27\x1b\x1f\x91\x8d\x4f\xc8\x86\x49\x36\x3e\x27\x9b\xb5\x24\x9b\xe5\x91\xcd\x0a\xc8\x66\x61\xb2\x59\x17\xb2\x59\x05\xd9\xec\x1a\x69\x65\x3b\xfb\xca\x66\x1f\x90\xfd\x3f\x79\xb5\x7c\xbf\xdc\x6b\xe6\x7f\x93\x0f\x55\xe7\x93\xad\x2e\x24\x5b\xbd\x91\x6c\xf5\x26\xb2\xd5\x25\x64\xab\xb7\x92\xad\xde\x4e\xb6\xba\x94\x6c\x75\x39\xd9\xea\x9d\x64\xab\xab\xc8\x56\xd7\xf8\x2c\x90\xb3\x52\x31\xc0\xc9\x64\xe1\x0a\xb2\x70\x25\x59\x98\x42\x16\xae\x22\x0b\x87\xc8\x62\x03\xc8\x62\x83\xc8\x62\x43\xc8\x62\x43\xc9\xf2\xc9\xc1\xb8\x67\xa7\x34\xc9\xc2\xef\xd2\xe4\xa1\x21\x2d\x81\x26\x79\x18\xf7\xe4\x61\x42\x4c\xa7\x44\x9a\x3c\x74\x2d\x80\x44\x86\x2d\x93\xf0\x6c\x99\x84\xa7\xf1\xe3\x5e\x96\x29\xee\x65\x99\x74\x4f\xe3\x5b\x6a\x77\xb2\xd4\xcd\x52\xc6\xc8\x78\xa0\xe7\x1f\x78\x79\x51\xbe\x8f\x74\x1e\x27\x5d\xe6\x07\x5f\x23\x9d\xbf\x45\x3a\xff\x0d\xe9\xfc\x77\xce\x2c\x64\xdc\xcf\xe0\x27\x29\x91\x8a\xf5\x59\x94\x90\x71\xbd\x6f\xc8\x92\x39\xb4\x6f\xc9\x48\xc5\xf5\xdc\x2c\x9f\x21\x40\x66\x2a\x8e\xe7\xc6\xf0\x12\x22\x9b\x12\xa2\x15\x19\x22\x9f\x74\x51\x40\x46\x2a\x07\xd9\x8e\x12\xa2\x23\xe9\xa2\x54\x46\x4e\x75\x19\xb3\xab\x90\x36\x92\x21\xba\x93\xee\xc5\xee\x74\x2f\x76\xa7\x7b\xb1\x3b\x5d\xf4\x21\x43\xf4\x25\x5d\xc6\xef\x92\xd6\xdf\xf9\xa9\xd8\xaf\x21\x26\x93\xee\xc5\xe6\xf4\x54\x6c\x6e\x2a\x19\xa9\x48\xeb\x4c\x19\x6d\x35\x52\x71\x3a\x87\xb2\xf3\x28\x2e\xa9\xbb\x80\xe2\x32\x46\x77\x33\xe9\x62\x89\x97\x75\xf4\xe7\x42\xdd\x98\x5c\x5c\xdc\x43\x71\x19\x93\x7b\x94\x74\x2f\x16\xa7\x7b\xb1\x38\x5d\xc6\xe2\xb6\x91\x21\xb6\x93\x21\x76\x92\x21\xe3\x72\xe9\xf1\xb8\xb8\x17\x8f\x8b\x7b\xf1\x38\x5d\x66\x31\x5f\x22\x5d\xc4\x29\x21\x5e\x26\x5d\xc6\xe2\x0e\x93\xe1\xc5\xe2\x74\x91\xa0\xc4\x99\x72\xc4\xc8\xe6\xdf\x91\x2d\x3a\x22\x2a\x66\x93\x2d\xe6\x90\x2d\x96\x92\x2d\xee\x26\x5b\xdc\x43\xb6\xa8\x6d\xca\x9b\xfd\x7f\xca\x4e\xe9\xc6\x1b\xd1\x4d\x70\x74\x13\x39\xe8\x26\x86\xa0\x9b\xb8\x00\xdd\xc4\x38\x74\x13\x1b\xd1\x4d\x3c\x89\x6e\xff\x6b\x76\xca\xf3\x69\x95\x00\xae\x57\x1c\xc7\x40\xd2\x30\x98\xe2\x18\x41\x7a\x9a\x9d\x7a\x01\xc5\x31\x8e\x12\x18\x4f\x09\x69\xb3\x5e\x42\x09\x69\xb7\x5e\x4a\x09\x5c\x46\x06\x26\x51\x02\x2b\x29\x8e\x55\x14\xc7\x6a\x8a\x63\x0d\xc5\xb1\x96\xe2\x58\x47\x71\x3c\x4e\x1a\xb6\x92\x86\x27\x48\xc3\x93\xa4\x49\x3b\x77\x07\xe9\x70\xfc\xf2\xa7\x49\x47\x2d\xe9\xd8\x45\x3a\x76\x93\xfe\x7f\x64\xff\xfe\x82\x12\x38\x48\x09\xbc\x4c\x09\xbc\x42\x09\x1c\xa5\x38\x5e\x95\x31\xc1\x38\x5e\x93\x71\xc1\x38\x7e\x49\xfa\xff\x89\x9d\x8c\x8f\x29\x8e\x4f\x29\x8e\xcf\x28\x8e\x93\x14\xc7\xf7\x94\x60\x2a\x25\x58\x88\x12\x2c\x97\x12\xcd\xec\xe8\xb6\x94\x60\xed\x29\xc1\x3a\x91\xc1\x4a\xc8\x60\x3d\x48\x63\x95\x94\x60\x55\xa4\xb1\x9e\x94\x60\xbd\x48\x63\xbd\x29\xc1\xfa\x90\xc6\xfa\x52\x82\x45\x49\x63\xd5\x94\x60\xfd\x48\x63\x67\x51\x82\x9d\x43\x71\x36\x98\xe2\xec\x5c\x8a\x4b\x5b\x7c\x21\x69\x6c\x11\x25\xd8\x41\x8a\xb3\x97\x49\x67\x87\x48\xf7\xec\x73\x43\xe6\xa9\x23\x08\x07\x6a\x29\x1e\xd8\x45\x7a\xe0\x24\x25\xd4\xe1\x14\x57\x47\xc8\xb8\x66\x5c\x1d\x29\x63\x9b\x71\xf5\x7c\x19\xdf\x8c\xab\x63\x28\xae\x5e\x28\x63\x9c\x71\x75\xac\x8c\x73\xc6\xd5\x71\x32\xd6\x19\x57\x27\xc8\x78\x67\x5c\x9d\x28\x63\x9e\x71\xf5\x32\x19\xf7\x8c\xab\x93\x64\xec\x33\xae\x5e\x41\xfa\xff\x96\x3f\xa0\xae\x23\x4d\xbd\x8b\x12\xea\xdd\xa4\xa9\xeb\x29\xa1\xde\x43\x9a\x7a\x2f\x25\xd4\xfb\x48\x53\x37\x50\x42\xbd\x9f\x34\x75\x23\x25\xd4\x07\x48\x53\x1f\xa4\x84\xfa\x10\x69\xea\xa6\x1f\xd9\xd5\x39\xb2\x7a\xc6\x8f\x09\x19\x98\x24\x6b\x54\x52\x40\x7e\x2a\x4e\x90\x5e\x33\x63\xfb\x6a\x66\x4c\x19\xb3\x9f\x4c\x16\xbf\xc2\x8b\xdd\xbb\x75\x33\x4d\x5a\xaf\x4a\x46\xa5\xfd\xc8\x4f\x87\xac\xdf\xf1\x63\x44\x06\x46\x65\xc0\x19\x81\x1f\x63\x49\x4f\x83\x33\x1a\x3f\x6e\x48\x87\x8c\x4e\xfb\xb1\x33\x1d\x18\x2a\x63\x96\x7e\xe4\xa7\x43\xd2\xc3\x8f\x11\x19\x18\x95\x81\xd1\x64\xa6\x61\xac\xcc\x49\x34\xc1\xa1\xa5\x1f\x97\x91\x91\x86\xcb\x25\x9d\x9b\x30\x59\xd2\xbc\x09\x57\x91\x99\x86\x1b\xbc\x75\xb8\x21\xb5\x1e\xa6\x1f\x32\xb6\xe7\xc7\xce\x74\xc8\xf8\xae\x8c\xf9\xf1\x73\xc8\xe0\x23\xc8\xe0\xa3\xc8\x90\x3c\x33\x96\x0c\x87\x57\x52\x5c\x75\x35\x2a\x28\x81\x1e\x94\x40\x94\x12\xe8\x47\x09\x0c\xa0\x04\xee\xa6\x04\x36\x51\x02\x0f\x53\x02\x8f\x50\x02\x8f\x52\x02\x9b\x29\x81\x2d\x94\xc0\x31\x4a\xe0\x0d\x4a\xe0\x2d\x4a\x40\xa7\x04\x3e\xa2\x04\x3e\xa1\x04\x4c\x4a\xe0\x73\x4a\xb0\x96\x94\x60\x79\x94\x60\x05\x94\x60\x61\x4a\xb0\x2e\x94\x60\x15\x94\x60\xd7\x50\x82\x1d\xa6\x04\xfb\x40\xe6\x74\x9c\x51\x38\xb4\x89\xf3\xcb\x29\x21\x2b\xab\xae\xa0\x04\xbf\x8a\x12\x7c\xba\x8c\xc6\xe9\xfc\xa7\x64\xf1\x55\x94\xe0\xf5\x14\xe7\x07\x29\xee\xd9\x50\x8e\x3f\xa9\xf1\x13\x14\xe7\x9f\x48\x8b\x43\xe7\xdf\x51\x42\xe6\x5d\x0b\x49\x17\x11\x8a\x8b\x12\xd2\x44\x39\x25\x44\x57\x4a\x88\xc1\xa4\x8b\xe1\xa4\x8b\x8b\x49\x17\xe3\x29\x2e\xf3\xac\xae\x6d\xa5\xfb\x6c\xab\xb8\xcc\xb3\x5e\x47\x9a\x98\x2d\xfd\x4d\x4d\xcc\xa1\x84\xb8\x81\x12\x62\xbe\xf4\x3d\x35\xb1\x54\xfa\x9f\x9a\xa8\xa5\x84\x78\x56\xd6\x1a\x25\xbc\x5a\xa3\x84\x57\x6b\x14\x17\x87\x49\x57\xe7\x53\x42\x5d\x48\x09\xf5\x46\x4a\xa8\x37\x51\x42\x5d\x42\x09\xf5\x56\x4a\xa8\xb7\x53\x42\x5d\x4a\x09\x75\x39\x25\xd4\x3b\x29\xa1\xae\xa2\x84\xba\x86\x12\xd2\xe3\x93\x91\x91\x54\xe4\xe0\x03\xa9\x8b\x2a\x10\x46\x0f\x84\x11\x45\x18\xfd\x10\xc6\x00\x64\x63\x20\x19\xa8\x21\x0b\x67\x93\x85\x41\xd2\x93\x30\x65\x04\x77\xb4\xd4\x51\x09\x8c\x23\x13\xe3\xc9\xc4\x25\x64\xe2\x52\x32\xe1\x48\x80\x1f\xd3\x4b\x77\x23\x8c\x4d\x08\xe3\x61\x84\xf1\x08\xc2\x78\x14\x61\x6c\x46\x18\x5b\x10\xc6\xe3\x64\x60\x2b\x19\x78\x82\x0c\x3c\x49\x06\x9e\x92\x3a\xeb\xc7\x22\xbc\x26\x0e\x92\x89\x97\xc9\xc4\x2b\x64\x7a\x7a\xc8\xf4\xf4\x90\xe9\xe9\x21\x13\xc7\x10\xc6\x1b\x08\xe3\x2d\x84\xa1\x23\x8c\x8f\x10\xc6\xc7\x0e\xdf\x20\x8c\x4f\x1d\xde\x41\x18\x9f\x39\xfc\x83\x30\x4e\x52\x02\xdf\x93\xc9\x54\x32\x59\x88\x4c\x96\x4b\x26\x6b\x89\x30\xcb\x43\x98\x15\x20\xcc\xc2\x08\xb3\xb6\x64\xb2\xf6\x64\xb2\x2e\xc8\x66\x15\xc8\x66\x3d\xc8\x60\x95\x64\xb2\x2a\x32\x58\x4f\x32\x59\x2f\x32\x58\x6f\x32\x59\x1f\x32\x58\x5f\x32\x59\x94\x0c\x56\x4d\x26\xeb\x47\x06\x3b\x4b\xe6\x1a\x2d\x36\x90\x2c\x76\xb6\xf4\xa8\x4c\x36\x98\x4c\x76\xae\xe3\xd5\x23\xcc\x16\x92\xc1\x16\x91\xe9\xe9\x21\x37\x42\x7c\x18\x61\xf6\x01\xb2\xf9\x39\x14\xe7\x23\x28\xce\x47\x51\x9c\x8f\xa5\x38\x9f\x4a\x06\x9f\x41\x86\xcc\x3f\xce\x91\xf5\x77\x06\xbf\x91\x4c\xbe\x98\x0c\x7e\x13\x19\xfc\x16\x32\xf8\x32\x32\x64\xbd\x40\x9c\x12\x9e\x55\x9d\xe0\x6f\x51\x22\x55\x3f\x70\x92\xe2\xdc\xa2\xb8\x97\xd9\x8e\xcb\xba\x01\xd7\x12\x8e\x3b\x3a\x4f\xd6\x0f\x64\xd6\x0d\xf4\x25\x3b\x55\x2f\x70\x33\x25\xc4\x12\x8a\xa7\x59\xa4\x77\x53\x42\xdc\x43\x89\xb4\xfa\x00\xc7\xc2\x74\xac\xcb\x97\x28\x21\xe2\x14\x97\x75\x01\xaf\x52\x42\x24\x28\xee\xe9\x55\x33\x70\x92\x4c\xb5\x82\x2c\xb5\x1b\x59\x6a\x0f\xe9\x59\xc5\xbd\x28\x78\xdc\x8b\x82\xc7\xbd\x28\x78\x52\xc7\x9a\x9e\x8e\x35\x3d\x1d\x6b\x7a\x3a\xd6\xf4\x74\xac\xe9\xe9\x58\xd3\xd3\xb1\xa6\xa7\x63\x4d\x75\x3e\xc2\xea\x42\x84\xd5\x1b\x11\x56\x6f\x42\x58\x5d\x82\xb0\x7a\x2b\xc2\xea\xed\x08\xab\x4b\x11\x56\x97\x23\xac\xde\x89\xb0\xba\x0a\x61\x75\x0d\xc2\xea\x3a\x32\xd4\xbb\xc8\x54\xef\x26\x43\x5d\x4f\xa6\x7a\x0f\x19\xea\xbd\x64\xaa\xf7\x91\xa1\x6e\x20\x53\xbd\x9f\x0c\x75\x23\x99\xea\x03\x64\xa8\x0f\x92\xa9\x3e\x44\x86\xba\x89\x4c\xf5\x61\xb2\xd4\x47\xc9\x52\x1f\x23\x4b\x7d\x9c\xac\x66\xf5\x0f\xbf\x6a\x96\xe3\x74\x2c\x43\x3f\x32\x73\x9e\x35\xa4\xa7\xe1\xec\x0c\x0c\xca\xc0\x53\xe9\x90\xb5\xa6\x7e\x0c\xcc\xc0\xd9\xe9\x90\xf5\xa8\x7e\x8c\xc8\xc0\xa8\x0c\x8c\x21\x33\x0d\x63\x49\x4b\xc3\x04\x32\xd3\xe0\x48\x5f\x3f\xae\x94\x59\xf6\x26\x4c\x95\x9c\xde\x84\xab\xc9\x48\xc3\x34\xd2\xd3\x30\x83\xe2\x69\xb8\x96\xac\x34\x38\xbb\x65\x96\x57\xb1\x3a\xcb\x57\x3b\xeb\xc7\xf5\xa4\xa7\x61\x6e\x06\xe6\x65\x60\xbe\x1b\xad\x4e\x61\x21\xc5\xd3\x70\xa3\x57\x0d\x70\x63\xaa\x2a\x20\x9e\x86\x9b\x32\x70\x4b\x06\x6e\x25\x2b\x0d\xcb\x28\x9e\x86\x95\x64\xf9\x21\xeb\x7a\xfd\xe8\x96\x81\x1e\x19\x78\x38\x03\x8f\x66\xe0\xb1\x0c\x3c\x9e\x0e\x69\x31\xfa\xb1\x25\x03\x8f\x67\xe0\xdf\xe4\x89\x83\x7f\x26\xd3\x0f\x19\xfd\x97\xd5\x10\xa9\x6a\x85\x60\xaa\xf2\xf8\x0c\x55\xc7\x68\x85\x80\xe3\x89\x52\x82\x4f\x25\x9b\xcf\x68\xca\x27\xf0\x85\x64\xf3\x45\xf2\x0c\x9b\xdf\x24\xab\x42\x9c\xb3\x6c\xbe\x4c\x6a\xc1\x44\x70\x07\x25\x64\x6d\xb8\x6b\xb9\x9e\x94\x31\x06\x4b\x64\xcb\x0c\x95\x25\x96\xc8\x0c\x91\x25\x12\xbe\x1c\xf5\x50\x59\x0f\xed\x47\x1e\x59\x69\xc8\x77\xac\xe1\x26\xc8\x91\xfb\x31\x23\x03\x99\xdc\xb9\x30\x03\x8b\x33\x70\x53\x06\x6e\xc9\xc0\xb2\x74\xc8\x0a\x1a\x3f\xb6\x64\xe0\xf1\x0c\x6c\x93\x36\x5f\x13\x76\xa6\x43\xae\x8e\x9c\x59\xaa\xc2\x3b\x3f\xad\xba\xfb\xdf\x55\x76\xff\x58\xfe\x8b\xf1\x1b\x10\x86\xd2\xf4\xbb\x80\xcc\xf2\x24\x57\xe7\x06\x9f\x9f\x50\x92\xaa\xe7\x77\x35\x9d\x2e\x35\xdd\x2f\xc9\x92\xda\xee\x38\x59\xb2\x46\xcc\x22\x5d\xd6\x6f\xb5\x25\x5d\xd6\x68\x8d\x22\x2b\x55\x3f\xec\x6a\x32\x5d\xdc\x49\xba\x58\x45\xba\x58\x43\x7a\x5a\x1d\x71\x8c\x0c\x51\x4f\x86\xa7\xc1\x74\x71\x24\xa5\xc1\x9a\x2a\x56\xf2\x53\x35\xc5\x47\xc8\xe6\x86\x57\xb9\x5c\xe2\xe5\x01\xaf\xf7\xcd\xfb\x8e\x8c\x8a\xe5\xa7\x7d\x71\xf7\x4b\x53\xf6\x73\x66\x2c\xec\x3d\x32\xf9\x67\x88\xf2\xcf\x11\xe5\x27\xc9\xe0\x0d\x88\xf2\x3f\x21\xca\xff\x8c\x28\xb7\xc8\xe0\x5f\x22\xca\xbf\x42\x94\x7f\x8d\x28\xff\x2b\xa2\xfc\x1f\x88\xca\x48\xdf\x3f\x11\xe5\xdf\x23\xca\xff\x85\x28\x3f\x8d\x28\x27\x44\x85\x40\x54\xa8\x32\x03\x6b\x88\x16\x88\x8a\x5c\x44\x45\x4b\x44\x45\x1e\xa2\xa2\x90\x6c\xd1\x06\x51\xcf\x12\x30\x44\x07\x44\x45\x11\xd9\xa2\x33\xa2\x62\x10\xa2\x62\x30\xd9\x62\x28\xa2\x62\x18\xa2\x62\x38\xd9\x62\x24\xa2\xe2\x42\x44\xc5\x58\x44\xc5\xc5\x64\x8b\x89\x88\x8a\xcb\x10\x15\x93\x64\x14\xc8\x5d\xf1\xb9\x88\x36\xab\x3d\xbb\x09\x51\x2f\xae\x65\x88\x5b\x11\x15\xb7\x23\x2a\x39\x62\x39\xa2\x19\x16\x85\x5b\x71\xb8\x09\x51\xf1\x08\xa2\x92\x63\x76\x23\x2a\xf6\x20\x2a\x9e\x4d\xb3\x2e\x74\x11\x27\x43\x1c\x44\xd4\x8b\x51\x35\x79\xb0\xf9\x69\x95\x86\x27\xc9\xe4\x96\xb4\x79\x4c\xd1\x8e\x4c\xb1\x44\xd6\x35\xba\x31\xaa\x38\x99\x22\x41\xe6\x19\x2b\xcd\xba\xa6\x24\xcb\x29\xcf\x03\xf8\x96\x4c\x2f\xde\x18\x97\x9e\x40\x2b\x32\x65\xe5\x65\xa9\x8c\x1d\xba\x95\x97\x7d\xc8\x94\xf1\xc0\x09\x32\xb7\xaa\x67\xc4\xfd\x74\x31\x9b\xe2\x62\x0e\xc5\x53\x55\x96\x37\xca\x9d\xe1\xc6\xf3\xb6\x91\x29\xb6\x93\x29\x76\x92\x29\x6a\x29\x9e\x8a\xd9\xed\x97\xf9\xd4\xad\x5e\x75\xa5\x2b\xb9\x26\x49\x6e\xf1\xc3\xd9\x87\x7e\x7c\x97\x0e\xb9\x3f\xfd\x70\x56\xdc\x8f\xc1\xde\xfe\x1d\xec\xdb\xc7\x7e\x5c\x9c\x81\xd9\x19\x98\x93\x81\x1b\x32\x30\x3f\x03\x4b\x33\x70\xa7\x67\x5b\xde\xe9\xb3\x31\xfd\x58\x93\x81\x5a\x4f\x9e\xd4\xfa\xe4\x8a\x1f\xb1\x0c\xd4\x67\x60\x7f\x06\x0e\xa4\x03\x03\x7c\xd5\x0f\x96\x57\xfd\x60\xf1\x43\x64\x66\x54\x3f\x58\xbe\xea\x07\x53\xca\x9f\x13\x64\xf1\x8f\xa4\x1c\x3a\x53\xe5\x43\x66\xd5\x83\xe5\x7b\x7e\xc2\xcd\x4a\xba\x55\x0f\xe9\xd5\x0e\xcd\x2b\x1d\x2c\xf1\x84\xcc\xc9\x9b\xe2\x67\x64\x8a\x1d\x64\xfe\x0f\x55\x0e\x56\xb3\x2a\x87\x3c\x19\x2f\xa8\x27\x83\x1f\x24\x43\xe6\x4f\x4f\x90\x91\xca\x9d\x46\x64\x8e\xc0\x48\xcb\x99\x5e\x4b\x86\xcc\x0d\x1c\x22\x43\x56\x2a\x67\x49\xae\x4a\xae\x7c\x53\xd5\xb0\x95\xda\xc3\xb5\xde\x13\x1f\x6e\x9e\xdf\xdd\x45\xb6\xb7\x83\x6c\xfe\xc3\x19\x9f\xbf\x70\x76\x8e\x2d\xa6\xca\xe7\x30\x9c\x1d\x63\xa7\x62\xcb\xee\x4e\xb1\xe5\x4e\xa9\x95\xcf\x66\x24\x77\x87\x2d\x0e\xc8\xda\xe3\x26\xef\x36\x55\x5d\xe0\x7b\x72\x23\x59\x5d\x10\xc0\x20\x64\xcb\x8c\xe1\xa0\xe0\x0e\x0c\x92\xcf\x9c\x5d\x21\xcf\x70\x73\xca\x5e\x05\x69\x2a\xe7\xdb\x2a\xa9\xf3\x9a\x49\x92\x69\x88\x8a\x6b\x10\xf5\x24\x8a\x3b\xe7\xa4\x44\x49\xea\xc7\xce\xc9\x5c\x8e\xaf\x7e\x5b\xf3\xa4\x87\x5b\xa5\x51\x41\x56\xaa\x32\x23\x53\x6a\xb8\x12\x43\x13\x73\x48\xf3\x51\x58\xcb\xa8\xc1\xd6\xc4\x7e\x99\x7f\x89\xfb\xeb\xaf\x65\x45\x9d\xeb\x47\x8c\x26\x03\x57\x91\xcd\x06\x91\xcd\x86\x90\xcd\x86\x92\x2d\x6b\xaf\x5f\x92\xde\xa2\x71\xc6\xda\x6b\x57\xff\x34\xd5\x5c\xff\x58\xad\x75\xb2\xce\xda\xad\xad\x36\xce\x58\x5b\x0d\xaf\xae\x5a\x25\xe3\xbf\xae\xa9\xee\x4e\xa6\xac\xa5\xee\x49\x66\xaa\x86\xfa\xc7\xea\xa7\xfd\xb5\xd3\x99\x75\xd3\x57\x92\x99\xaa\xcb\x9f\x8b\xb0\x98\x47\x86\x58\x40\xc6\x8f\xd4\x45\x1b\xcd\xea\xa2\xef\x26\x5d\xdc\x43\x7a\x5a\x3d\xf4\x63\x64\xca\x3a\xe8\x5a\x32\xd2\x6a\xa0\x93\x76\xc4\x8f\xd5\x3c\x27\xeb\x9c\x3d\xbd\x15\x5a\x43\x46\x68\x2d\x19\xa1\x75\x64\x84\xee\x22\x23\xcd\x3a\x6d\x92\x24\x8e\x14\x59\x22\x75\x97\x9d\xb6\xa3\xdb\xa1\x15\xc5\x91\x4f\x71\x1e\x97\x32\xca\xe0\xaf\x91\xc9\xdf\x92\x7c\xdb\x64\xdb\xb6\x25\x43\xda\xb7\x37\x4b\x4d\xe8\x48\x5d\x43\xac\x22\x43\xac\x21\xc3\x67\xf7\x98\xd2\xf6\x7d\x55\xf2\xb2\xa3\x11\xe3\xc1\x9d\x14\xc7\xd0\xe4\xd3\x5b\x29\xb9\xe1\x4a\x43\x93\xff\x52\x3e\x7b\x17\xf7\x24\xa0\xc9\x0d\xf9\x84\x98\xe1\xed\xf9\xa4\xd6\x74\x64\x8b\x29\xda\x92\x29\x4a\xc8\x4c\xd5\x66\x8c\xf2\x34\xa6\x2b\x6f\x4c\x2f\x6e\xe6\x97\x86\xa6\x5b\xdd\x2e\xe5\x8f\x29\xae\x93\x2b\xe8\xd8\x58\xa6\x94\x3c\x8b\xbc\xca\xf6\x3b\xc8\xf4\xf4\x88\x29\x56\x91\x29\xd6\x90\x29\xee\x23\x53\xca\x0b\xbf\x94\x7c\x5a\xae\x94\x63\xed\x99\x52\x86\xfc\x9c\x4c\x29\x47\xf6\x79\x7a\xe0\x45\x6f\xb5\x5c\x39\x67\x8a\x23\x52\x7a\xe8\xc1\x1d\xa4\x23\xc4\xdf\xf1\xc9\x6f\xff\xb3\x69\xc9\xcc\xf7\x66\xf9\xf4\x9f\x1f\xd9\xe9\x90\xcf\x2b\xfa\xf1\x12\x66\xa6\xe1\x20\x99\x69\x78\x27\x03\x06\x25\xd2\x70\x42\xd2\xba\x09\x7f\x93\x34\x6f\xc2\x77\x32\x76\xd9\x84\x1f\x5c\x19\x9f\x84\xcc\x0b\xfb\x51\xee\xad\x4d\xb9\x6f\x8d\xfc\x18\x9f\x81\x09\xde\x53\x2f\x49\x5c\x25\xd7\xb0\x09\x53\xbd\x27\x62\x92\xb8\x3a\x03\xd3\x33\x70\xad\xac\xcb\x69\xc2\x2c\xef\x69\x9a\x24\xae\xa3\x44\x1a\x66\x4b\x19\xd9\x84\xeb\xbd\x5a\x9e\x24\xe6\x78\x99\xd6\x24\xee\xf0\xea\x7c\x92\x58\x4a\x7a\x1a\x9e\xf6\x6a\x80\x92\xa8\x25\x3d\x0d\xfb\x3c\x5e\xd9\x97\xe2\x19\x3d\x0d\x2f\x7a\x3c\xf4\x62\x8a\x97\xf4\x34\x1c\x92\x95\x71\x4d\x38\xec\x3e\xf9\x93\x84\x7c\x42\xd3\x8f\x1d\xe9\xc0\x1e\x1f\x77\x69\x3f\xc6\x65\xc8\x26\x4d\x3e\x7f\xea\xc7\xc1\x0c\xbc\x43\xb5\x69\x30\x32\x70\x42\x46\xc0\x9b\xf0\x37\x69\x21\x34\x21\xc3\xc2\xe4\x3f\xc8\x67\xa2\x52\x90\xcf\xb7\xfa\x51\x4e\xf1\x34\x74\xcd\xc0\x78\xd2\xd2\x30\x41\x4a\x84\x26\x5c\x45\xb5\x69\x98\x2a\x2d\x93\x26\x5c\x4d\x5a\x1a\xa6\x67\xe0\xda\x0c\xcc\x92\x12\xa5\x09\xd7\x51\x6d\x1a\x32\x2d\xdc\xeb\xa9\x36\x0d\xcd\x2d\x5e\x33\x0d\xf3\x3c\xbb\x28\x89\xf9\xd2\x1f\x6a\xc2\x02\x4f\xa3\x27\x71\x07\xd5\xa6\x21\xd3\x42\x7e\x9a\x6a\xd3\x90\x69\x01\xef\xa3\xc5\x69\xd8\xef\x3d\x13\xeb\xb7\x72\x5f\xa4\xc5\x69\x68\xb2\x78\x8d\xd4\xf7\x43\xa4\xa5\xe1\xb0\x94\x84\x29\x34\xe3\x50\xb7\xae\x2c\xc9\xa1\xa9\xef\xa8\xfa\xb7\x35\x57\x8e\x7e\xf3\x23\x3f\x03\x19\x4f\x7d\xc8\xe7\x93\xfd\x28\x25\xdb\x8f\x66\x35\x52\xdb\xa4\x57\xd8\x84\x8c\x9a\x29\x47\x6f\xfa\xd1\xf4\x7c\xf2\x19\x35\x57\xa6\xb5\xe6\x5a\xab\xa6\xd4\x56\xae\xb5\x6a\xa6\xec\xe1\x1b\xbd\x35\xdb\xe0\xad\x4d\x93\xb5\xea\x4a\x81\xc3\x92\x6e\xae\x56\x19\x24\x3d\x0c\x3f\x9a\xeb\x04\x2b\x0d\x99\x3a\xe1\x84\xe7\x75\x78\x90\x1a\xca\x8f\xae\x19\x18\xef\x79\x1d\xe3\x7d\xde\x87\x1f\x57\x7b\x4f\x6a\x5c\xed\x7b\x62\xc3\x8f\x6b\x3d\x0f\x25\x89\x4c\x99\x98\x29\x03\x0f\xa5\x23\xed\x19\xf9\x64\xe5\x92\xa3\xcd\xe2\xbe\xaa\x25\x5b\x6a\xa7\x02\x19\x55\x89\x4b\x4d\x54\x21\x47\x6f\xa6\xbc\x85\xa6\x2a\xa6\x44\x46\x1d\x73\xb2\x8a\x29\x2e\xbd\x87\xeb\xa5\xcf\x6d\x8b\x3b\x28\x2e\x3d\x88\xa7\xa5\xf7\x68\xff\x58\xf5\x52\xea\x19\xf9\x1e\xa9\x51\xbe\x23\x6b\xaa\x0c\xc9\x11\xdf\x92\x9d\xe2\x88\x56\x72\x74\x86\x28\x97\x15\xd6\x96\x67\xbf\x58\x9e\xfd\x62\x89\x69\x92\x5e\x8e\x2d\x6f\x7b\xb6\x8b\xe1\x49\x12\xe3\x47\x9e\xe2\x37\x24\xd7\x6c\x23\x5b\x6c\x27\x5b\xec\x94\xa3\x35\xbc\xdd\x6d\x79\xd5\xd5\x96\xac\xae\x3e\xdc\xa4\x1f\x10\x92\x75\xa1\x3e\xc8\x98\x84\x0f\x08\x9d\x31\x47\x3f\xd6\x17\xdd\x5c\x2c\x79\xdf\x8f\xec\x0c\xfc\x9b\xdd\x2a\x23\x61\x7e\xfc\xd2\xf3\x91\x93\x78\x27\x03\xc7\xd3\x21\x23\x68\x7e\xfc\x3b\x2e\x76\xfc\x67\x3f\xae\xca\xc0\xbf\xe3\xe2\x19\x5e\x4c\x70\x86\x2f\x36\xe8\xc7\x9d\xd2\xef\x6e\xc2\xaa\x0c\xac\xc9\xc0\x7d\x9e\x6f\x9e\xc4\xf3\x19\xf8\x79\x06\x5c\xd9\xdc\x84\x03\xe9\x90\xf2\xc1\x8f\x66\xd2\xcc\x95\x1f\x29\x64\x4a\xb3\x71\x32\x46\xe9\x47\x76\x3a\x9a\xc9\x99\xcc\x18\xd2\x29\xe9\xb7\x37\xc1\x4e\x87\xdc\x9d\x7e\x54\x64\xa0\x5b\x06\xfa\x64\xe0\xfc\x0c\xcc\xcc\xc0\x8d\x19\xd8\x90\x81\x17\x32\xa0\x65\xe0\xdf\xc4\x78\x64\x1c\xd6\x8f\x1d\xe9\x40\xa5\xaf\xd2\xdc\xb5\xc6\x8f\xa4\x78\xd9\xf4\x3d\xe9\x62\xa6\x22\x27\x6d\xbd\x27\x43\x92\x12\x61\x94\x94\xb0\x67\x7e\xe3\xc8\x8c\xb4\xb7\x8e\x34\x3d\xe1\x72\xa6\x27\x5b\xce\xf4\x14\x4b\xd3\x9b\x47\xdc\x48\x45\x20\x2d\x22\xe3\xc5\xdb\xe5\x93\x78\x16\x72\x91\x47\x7a\x5a\x26\x65\x91\x2f\xa7\x70\x73\xda\x7b\x5c\xf4\xe0\x16\xd2\x83\x8f\x93\x8e\x3e\xa9\x4a\xd4\x0a\x32\xd0\x83\x0c\xf4\xc4\x4a\x44\xc9\x40\x3f\x32\xbc\x0a\x0e\x03\x9b\xc8\xc0\xc3\x64\xe0\x11\x32\xf0\x28\x19\xd8\x4c\x06\xb6\x90\x81\x63\x64\xe0\x0d\x32\xf0\x16\x19\xd0\xc9\xc0\x47\x64\xe0\x13\x32\x60\x92\x81\xcf\xc9\x60\x2d\xc9\x60\x79\x64\xb0\x02\x32\x58\x98\x0c\x5f\x05\x87\xc1\x0e\x93\x21\x2b\x38\x64\x45\x16\xc5\xd5\xf9\x64\xa8\x0b\xc9\x50\x6f\x24\x43\xbd\x89\x0c\x75\x09\x19\xea\xad\x64\xa8\xb7\x93\xa1\x2e\x25\x43\x5d\x4e\x86\x7a\x27\x19\xea\x2a\x32\xd4\x35\x72\xef\xb8\x51\x90\x9c\x54\xfc\x25\xf9\x94\x70\x53\x2d\x88\xc5\xaf\x20\x43\xd6\x82\xac\xa2\x44\xea\x0c\x86\x9e\x18\x04\x05\x8f\x21\x80\x00\x80\x6c\xb4\x00\x43\x2b\xe4\x83\xa3\x0b\xba\x43\x45\x2f\xf4\x46\x0e\xa2\xe8\x87\x96\x18\x80\x21\xc8\xc7\x08\x8c\x44\x7b\x9c\x8f\xd1\xe8\x88\x31\x5e\xf5\xf7\x58\x14\x63\x1c\x2e\x41\x04\x97\xe2\x52\x74\xc1\xe5\xb8\x1c\xe5\x98\x8c\x29\xa8\xc0\x54\x4c\x45\x0f\xac\xc4\x7d\xa8\xc4\x83\x78\x10\x03\xb0\x09\x9b\x31\x10\x5b\xb0\x0d\x83\xb1\x1d\xbb\x30\x02\x7b\xf0\x3c\x2e\x40\x1d\xea\x30\x16\x7b\xb1\x1f\x17\xe3\x00\x0e\x60\x02\xe2\x88\xe3\x12\x1c\xc2\x31\x4c\xc4\x1b\x78\x03\x53\xf1\x16\xde\xc2\xd5\xd0\xa1\x63\x1a\x7e\x8b\xdf\x61\x3a\xde\xc5\x87\x98\x89\x53\x38\x85\x79\xf8\x0e\x3f\x60\x3e\x4e\xe3\x34\x6e\x04\x31\x86\xc5\x8c\x33\x8e\x25\x2c\xc4\x42\xb8\x85\xb5\x64\x2d\x71\x2b\xcb\x63\x79\xb8\x8d\x15\xb0\x02\xdc\xce\xc2\x2c\x8c\x3b\x58\x5b\xd6\x16\x4b\x59\x7b\xd6\x1e\xcb\x58\x11\x2b\xc2\x72\xd6\x85\x75\xc3\x0a\xd6\x83\xf5\xc0\x1a\x56\xc5\xaa\xb0\x96\xf5\x62\xbd\xb0\x8e\xf5\x61\x7d\x70\x17\x8b\xb2\x28\xee\x66\xfd\x58\x3f\xac\x67\xfd\xd9\x39\xb8\x87\x0d\x66\x83\xf1\x00\x3b\x97\x9d\x8b\x07\xd9\x0c\x36\x03\x0f\xb1\x45\x6c\x11\x36\xb1\x83\xec\x15\x3c\xcc\x0e\xb3\xc3\xd8\xcc\x3e\x60\x1f\xe2\x31\x7e\x0e\x3f\x07\x8f\xf3\xa1\x7c\x04\xb6\xf2\x91\x7c\x14\x7e\xc6\x47\xf3\xd1\xd8\xc1\xc7\xf0\x31\xd8\xc9\x2f\xe2\x63\xf1\x34\x9f\xc0\x27\x60\x17\x9f\xc8\x27\x62\x37\xbf\x8c\x5f\x89\x67\xf8\x55\x7c\x2a\x7e\xce\xa7\xf1\xe9\x88\xf1\x19\x7c\x06\xea\xf9\xb5\xfc\x5a\xec\xe5\xb3\xf9\x0d\xd8\xc7\xe7\xf3\xf9\xf8\x05\x5f\xc8\x17\xe2\x20\xbf\x91\xdf\x88\x97\xf9\x4d\xfc\x26\xbc\xc2\x6f\xe1\xb7\xe2\x10\xbf\x83\xdf\x81\x23\x7c\x19\x5f\x86\xa3\x7c\x25\x5f\x85\x57\x79\x3d\xdf\x8f\xd7\x78\x9c\xbf\x8c\x5f\xf1\x43\xfc\x10\x7e\xcd\x8f\xf0\xd7\xa0\xf3\x5f\xf2\x63\x78\x87\xbf\xc9\xdf\xc4\x7b\xfc\x37\xfc\x37\x38\xce\xdf\xe6\xbf\xc7\xef\xf9\xfb\xfc\x04\x3e\xe2\x1f\xf2\x8f\xf1\x09\xff\x94\x7f\x8a\xcf\xf8\x67\xfc\x8f\xf8\x9c\xff\x99\xff\x19\x7f\xe2\x7f\xe1\x7f\xc1\x9f\xf9\x5f\xf9\x5f\x61\xf1\xbf\xf1\x7f\xe0\x4b\xfe\x3d\xff\x01\xdf\xf0\xd3\x9c\xf0\xad\x60\x42\xe0\x1f\x22\x5b\xe4\xe2\x07\xd1\x4a\xb4\x02\x89\x7c\xd1\x9a\x41\xb4\x15\x45\x2c\x20\x3a\x89\x4e\x2c\x5b\x14\x8b\x62\xd6\x42\x94\x88\xbe\x2c\x47\x9c\x23\xae\x64\x9d\xc4\x55\x62\x36\x1b\x22\x7e\x2a\xe6\xb2\x0b\xc4\x3c\x31\x8f\x5d\x28\x16\x88\x05\xec\x22\xb1\x48\x2c\x61\x63\xc5\x6d\xe2\x76\x36\x51\x2c\x13\xcb\xd9\x65\xe2\x4e\xb1\x9a\x4d\x12\x6b\xc5\x5a\x36\x45\xdc\x25\x1e\x60\x57\x89\x47\xc5\x4e\x76\x9d\xd8\x25\x76\xb3\x9b\xc4\xb3\x42\x63\x4b\x44\xbd\xa8\x67\x4b\xc5\x3e\xb1\x8f\x2d\x13\x2f\x8a\x97\xd8\x72\xf1\x0b\xf1\x0b\xb6\x52\xbc\x2c\x0e\xb1\x55\xe2\x88\x38\xc2\xd6\x8a\x57\x45\x82\xad\x0b\xd4\x06\x76\xb1\xbb\xd5\x0a\xb5\x92\xdd\xa3\x0e\x57\xe7\xb0\x07\xd4\xf9\xea\x8d\xec\x25\xf5\x26\xf5\x26\xf6\x8a\xba\x44\x5d\xc2\x0e\xa9\xb7\xaa\xb7\xb2\xc3\xea\xed\xea\xed\xec\x88\xba\x4c\x5d\xc6\x8e\xaa\x2b\xd4\x15\xec\x55\x75\xa5\xba\x92\x25\xd4\xd5\xea\x6a\xf6\x9a\xba\x56\x5d\xc7\x5e\x57\xef\x55\xef\x65\xc7\xd4\x0d\xea\x06\xf6\x2b\x75\xa3\xba\x91\xbd\xa1\x3e\xa8\x3e\xc8\xde\x54\x37\xa9\x5b\xd9\x5b\xea\xe7\xea\xe7\xec\xbd\xe0\x63\xc1\xc7\xd9\xf1\xe0\x93\xc1\x6d\xec\x0f\xc1\xed\xc1\xed\xec\x83\xe0\xce\xe0\x4e\xf6\x61\xf0\xcf\xc1\x3f\xb3\x8f\xe4\xfb\xd0\xb2\x31\x0c\x13\xc1\x67\xdc\xba\x68\x2e\xc2\xd7\x2d\xba\xf6\xa7\x88\xcc\x9d\xbe\x78\x1e\xaa\xe4\x3b\xd2\x40\x24\x7b\xfd\xd8\x77\x36\x63\xc6\x0d\x0b\x10\x02\xc0\xe5\x5b\xd6\x14\x08\x64\xa3\x00\x1d\x50\x2a\xfb\x31\x44\xa0\xca\x77\xae\xdd\xeb\xfe\x1e\xf8\xce\x3d\x2f\x78\x2f\x58\x60\x0e\x02\xc8\x63\xa5\x4a\x3f\x3e\x52\x4c\x42\x47\x9c\x8d\x61\xb8\x00\x13\x70\x05\xae\xc1\x1c\x2c\xc2\x6d\x58\x89\xf5\x78\x10\x5b\xb0\x1d\x7b\x50\x87\x38\x8e\xe2\x0d\xfc\x0e\xef\xc3\xc4\x9f\xf0\x0d\xbe\x67\x60\x2a\xcb\x09\xbd\x02\xae\x3c\xab\x3c\x1b\x7a\x59\x1e\xf7\x84\x0e\xca\xe3\x33\xa1\x5f\xc8\xe3\xee\x50\x5c\x1e\x77\x85\x0e\x80\x2b\x7b\x94\x67\x43\x2f\xca\xe3\x9e\xd0\x7e\x79\x7c\x26\xb4\x4f\x1e\x77\x87\xf6\xca\xe3\xae\x50\x1d\xb8\xf2\x8c\xf2\x6c\x28\x26\x8f\x7b\x42\x9a\x3c\x3e\x13\xfa\xb9\x3c\xee\x0e\xbd\x20\x8f\xbb\x42\xcf\x81\x2b\xbb\x95\x67\x43\xcf\xca\xe3\x9e\xd0\x1e\x79\x7c\x26\xf4\x8c\x3c\xee\x0e\xed\x96\xc7\x5d\xa1\x5d\xe0\xca\x2e\xe5\xd9\x50\xad\x3c\xee\x09\x3d\x2d\x8f\xcf\x84\x76\xca\xe3\xee\xd0\x4b\x50\x94\x3d\xa1\x43\x50\x94\x67\x43\xcf\x43\x51\x76\x87\xea\xa1\x28\xcf\xfc\x5f\x50\xe4\x7d\x8f\x22\x7f\xf0\x28\x62\x78\x14\xf9\xbd\x47\x91\xe3\x1e\x45\xde\xf5\x28\xf2\x8e\x47\x91\xdf\x79\x14\x79\xdb\xa3\xc8\x6f\x3d\x8a\xe8\x1e\x45\x7e\xed\x51\xe4\x2d\x8f\x22\x6f\x7a\x14\x79\xc3\xa3\xc8\xaf\x3c\x8a\x1c\xf3\x28\xf2\x4b\x8f\x22\xaf\x7b\x94\x48\x78\x94\x78\xd5\xa3\xc4\x51\x8f\x12\x47\x3c\x4a\x1c\x96\xc7\x5d\xa1\x13\x92\x16\xbf\x71\xa8\x10\x7a\x0d\x8a\xb2\x2b\xf4\x9e\x43\xa3\xff\x0b\x8a\xd8\x1e\x45\xfe\xee\x51\xe4\x5b\x8f\x22\x7f\xf3\x28\xf2\x8d\x47\x91\xaf\x3d\x8a\xfc\xc5\xa3\xc8\x57\x1e\x45\xbe\xf4\x28\x62\x79\x14\xf9\xb3\x47\x91\x3f\x79\x14\x69\xf0\x28\xf1\x47\x8f\x12\x5f\x78\x94\x38\xe9\x51\xe2\x73\x8f\x12\x9f\x79\xbc\x61\x7a\x14\xf9\xc4\xa3\xc8\xc7\x1e\x45\x3e\xf2\x28\xf2\xa1\x47\x91\x0f\x3c\x8a\xfc\x55\xf2\xc8\x3f\x24\x5d\x3e\x95\x14\x39\x25\xdf\x2e\xfa\x5f\x53\x24\xab\xc0\xa5\x48\x56\xbe\x4b\x91\xac\x3c\x97\x22\x59\xad\x5c\x8a\x64\xb5\x74\x29\x92\x95\xeb\x52\x24\x2b\xc7\xa5\x44\x56\x0b\x97\x12\x59\xd9\x2e\x25\xb2\x42\x2e\x25\xb2\x82\x2e\x25\xb2\x54\x97\x37\xb2\x02\x2e\x45\xb2\x84\x4b\x91\x2c\xc5\xa5\x48\x16\x73\x29\x92\x05\x8f\x22\xe4\x51\xa4\xd1\xa3\xc8\xbf\x3c\x8a\xfc\xe0\x51\xe4\x7b\x8f\x22\xff\xf4\x28\xf2\x9d\x4b\x91\xac\x2c\x87\x3b\xb2\x0a\x25\x45\x4e\x3b\x14\xc9\xe2\xff\x97\x14\xe9\xed\x51\xa2\x97\x47\x89\x9e\x1e\x25\xaa\x3c\x4a\xf4\xf0\x28\xd1\xdd\xe5\x8d\xac\x6e\x1e\x45\xba\x7a\x14\xa9\xf0\x28\xd2\xc5\xa3\x48\x99\x47\x91\x52\x8f\x22\x25\x1e\x45\x22\x1e\x45\x3a\x7b\x14\xe9\xe4\x51\xa4\xa3\x4b\x91\xac\x22\x97\x22\x59\x1d\x5c\x8a\x64\xb5\x73\x29\x92\xd5\xd6\xa5\x48\x56\x1b\x97\x22\x59\xad\x5d\x8a\x64\x85\x3d\x8a\x94\x4b\x8a\x54\x3a\x9c\x92\xd5\x5e\x52\xa4\xd8\x7d\x03\x2d\x98\x73\x7e\x4a\x4a\x17\x80\xa1\xa3\x94\xc3\x1c\x0c\x1c\x17\xe2\x22\xa5\x07\x14\xb4\x54\x8e\x2a\xc7\x01\xe5\x03\xe5\x03\xb4\x56\x88\x33\xb4\xe1\x82\xab\x68\xcf\x43\x3c\x84\x8e\x3c\x87\xb7\x44\x27\x5e\xc0\xc3\x88\xf0\xf6\xbc\x3d\xca\x78\x27\xde\x09\x5d\xe4\xdb\x79\xcb\xe5\xdb\x79\xa3\x81\xc7\x02\x5b\xd0\x3f\xb0\x35\xb0\x1d\x03\x03\x3b\x03\x3b\x71\x2e\x18\x7b\x10\x1c\x39\x98\xc7\x80\x10\x0a\xd0\x11\x15\xe8\x83\xb3\x31\x02\x63\x31\x29\x6b\x00\x84\x72\x4c\x39\xae\xbc\x9a\xd5\xdf\xfb\x76\x34\xeb\x2c\xf9\xed\x3d\xe5\xd5\xac\x7e\xde\xb7\xa3\x59\xd5\x10\xca\xeb\xb2\x5f\xd4\xfb\x76\x34\xab\xaf\xfc\xe6\xf4\xeb\xe3\x7d\x3b\x8a\x1c\x74\x40\x17\xf4\xc2\x40\x0c\xc3\x85\xb8\x0c\xd3\x30\x07\x8b\xb1\x0c\x77\x65\x8d\x81\x50\xde\x50\x8e\x29\xaf\x66\x5d\xe0\x7d\x3b\x9a\x35\x5a\x7e\x7b\x5d\x79\x35\xeb\x7c\xef\xdb\xd1\xac\x73\x53\x23\x1a\x92\x1a\xd1\xe0\xd4\x88\x06\xa5\x46\x74\x4e\x6a\x44\x67\xa7\x46\x54\x93\x1a\xd1\xc0\xff\x60\x44\x17\xa7\x46\x34\x36\x35\xa2\x8b\x52\x23\xba\x30\x35\xa2\x51\xa9\x11\x8d\x4c\x8d\xe8\xbc\xd4\x88\x46\xa4\x46\x34\x3c\x35\xa2\x61\xa9\x11\xfd\x24\x35\xa2\xa1\xa9\x11\x31\x70\x3e\x83\xff\x94\x2f\x81\x82\x1c\x70\xfc\x8d\xfd\x33\x30\xd1\xc7\x09\x5c\xac\x67\x1b\x11\x80\x08\x6c\x09\x54\x03\xac\xd8\x3d\xf2\xb7\x31\x4b\x41\x48\x51\x5a\x04\x14\x11\x10\x59\x8a\xf8\x04\x0a\x0d\xc5\x2d\x04\xa0\xc4\xb1\x0a\x2e\xba\x78\xec\xc5\x60\xc8\xa5\xd3\xea\xac\xc6\x59\x40\xe8\x3e\x65\x7c\x04\xec\xa9\x8f\x7f\x0f\x88\x0b\x02\xfb\x01\x44\xd0\xce\xe3\x43\x07\x2e\x17\x82\x7f\x2b\x39\xd1\xf9\x5d\x70\x03\xc0\x37\x58\x01\x15\x8b\x00\xe4\x62\x19\x9f\xcf\x6f\xe2\xcb\xf8\x7a\x7e\x2f\xff\x19\xd7\x03\x5d\x3b\xbd\xd1\xf9\xf1\xce\x4f\x76\xfe\x67\x71\xeb\xe2\x4e\xc5\xe7\x15\x5f\x54\x7c\x79\xf1\xe4\xe2\x2b\x8b\xaf\x2a\x5e\x5a\xbc\xb7\x38\x51\xfc\x4e\xf1\x89\xe2\xbf\x14\x7f\x5b\xdc\x18\x29\x8d\x54\x44\xfa\x44\xfa\x45\xce\x8e\x0c\x8a\x0c\x89\x8c\x88\x5c\x1d\x59\x10\xb9\x35\xb2\x3c\xb2\x29\xf2\x4c\x64\x5f\x24\x1e\xf9\xba\x24\x50\x52\x58\xd2\xb6\xa4\xb4\xa4\xa2\xa4\x57\xc9\xd8\x92\x89\x25\x53\x4b\x56\x97\x3c\x5c\xb2\xbb\x54\x29\x55\x4b\x5b\x95\x16\x94\xb6\x2e\xed\x50\x5a\x5c\xda\xbd\xb4\xb2\xf4\xfc\xd2\xe9\xa5\xd7\x96\x29\x65\x79\x65\x25\xe5\x28\x57\xca\x73\xca\xf3\xca\xc3\xe5\xed\xca\x3b\x96\x77\x29\xaf\x2a\xef\x57\x3e\xa8\x7c\x6e\xf9\x8a\xf2\xd5\xe5\x77\x95\xdf\x5b\xfe\x50\xf9\xcf\xca\x9f\x2b\xaf\x2b\x8f\x97\x1f\x2c\x4f\x94\xbf\x55\xfe\x9b\xf2\x3f\x94\x7f\x51\x31\xa8\x62\x68\xc5\xb0\x8a\x69\x15\x33\x2a\x66\x55\xfc\xb4\x62\x7e\xd5\x0d\x55\x4b\x7a\xb5\xdd\x55\xb2\xeb\xde\x4f\xf0\x83\x68\x2c\x6b\x24\x3a\x4d\x24\xdf\x50\x9b\x8b\x08\xb6\xf1\xc5\xfc\x36\xbe\x9a\xdf\xcb\x37\xf0\x1d\xfc\xb7\x9d\xd0\xa9\xb1\xf3\x93\x9d\xb7\x15\xa3\xb8\x5d\x71\xa4\xf8\xfc\xe2\x71\xde\x9c\xaf\x2e\x5e\x51\xbc\xbf\xf8\xf5\xe2\xe3\xc5\x1f\x16\x7f\x53\x6c\x47\x10\xa9\x88\xf4\x88\x44\x23\x35\xde\x9c\xa7\x46\xe6\x44\x16\x47\x96\x47\x36\x46\xb6\x45\x9e\x8d\xbc\xe4\xcd\xb9\x8d\x37\xe7\x8b\x4a\x2e\x29\xb9\xb2\x64\x75\xc9\xc6\xd4\x9c\xf3\x4b\x5b\x97\xb6\x2f\xed\xec\xcd\x79\x5a\xe9\x4c\x39\xe7\xc8\x8f\xcc\x79\x5c\x6a\xce\x1b\xcb\xb7\x95\xef\x49\xcd\xf9\x8d\xf2\xdf\x94\x1b\xe5\x5f\x54\x9c\x9d\x9a\xf3\xb5\x15\x73\x2a\xe6\x57\x4d\xab\x5a\xd8\xab\xed\xae\xb6\xbb\xee\xfa\x04\x3f\xb0\xc6\x48\x23\xd1\xbf\x1c\x4b\x92\xfe\x4e\x9f\xd1\x51\x7a\x85\xe2\xb4\x8f\xf6\x52\x3d\xd5\x51\xec\xd4\x1f\x4e\xd5\x9e\xda\x79\x6a\xc7\xa9\x27\x4e\x3d\x7e\xea\xb1\x53\x8f\x9e\x7a\xf8\xd4\xa6\x53\x0f\x9d\x7a\xf0\xd4\x03\xa7\xee\x3f\xb5\xe1\xd4\x7d\xa7\xee\x39\xb5\xfe\xd4\x5d\xa7\xd6\x9d\x5a\x7b\x6a\xd5\xa9\x15\xa7\x96\x9f\xba\xfd\xd4\x6d\xa7\x6e\x3d\xb5\xf8\xd4\x95\xa7\xc6\x9f\x1a\x7b\x6a\xf4\xa9\x9a\x53\xbd\x4e\xf5\x3c\xd5\xe3\x8b\xbf\x7f\xf1\xe9\x17\xef\x7e\xf1\xbb\x2f\x8e\x7d\xf1\xda\x17\xaf\x7c\xb1\xed\x8b\xad\x5f\x3c\xf2\xc5\xc2\x2f\x66\x7d\x31\xf1\xe4\x0f\x27\xbf\x3b\xf9\xf5\xc9\xbf\x9c\xfc\xf2\xe4\x9f\x4e\x9e\x3a\xf9\xd1\xc9\x0f\x4f\x1e\x39\xb9\xe7\xe4\xee\x93\x39\x9f\xd3\xe7\x5f\x7f\x56\xf0\x59\xfe\x67\xa1\xcf\x02\x9f\x29\x26\x99\xff\x32\xff\x6e\x7e\x65\x9e\x32\x3f\x31\x7f\x6d\xc6\xcd\x17\xcd\xbd\x66\xcc\x7c\xc1\xdc\x6e\x6e\x31\x1f\x36\x37\x98\xf7\x99\x6b\xcd\x3b\xcd\xe5\xe6\x12\xf3\xa7\x66\x3b\xb3\xb5\x19\xfe\xf4\x1f\x9f\xfe\xfd\xd3\x6f\x3f\xfd\xeb\xa7\x5f\x9d\x68\x3c\xf1\xc3\xfb\x53\xa6\x5f\x35\xed\x1f\xdd\x56\xe7\xae\xce\xbe\x3e\x6b\x43\xe8\x41\xef\x3d\xc4\xff\xff\xfa\xa7\x2a\xd9\x70\x5f\x1b\x9d\x39\x7b\x26\x5f\xca\x0e\x20\x75\xfc\xb1\x7f\xee\x99\x5c\x56\x9e\xa8\x08\x22\x84\x2c\x19\x53\xc8\x41\x2e\x5a\xa2\x15\xf2\x90\x8f\x02\x14\x22\x8c\xd6\x68\x83\xb6\x68\x87\xf6\xe8\x80\x22\x74\x44\x27\x74\x46\x31\x22\x28\x41\x29\xca\xd0\x05\xe5\xa8\x40\x57\x74\x43\x77\xf4\x40\x25\xaa\xd0\x53\x46\x22\xfa\xa0\x2f\xa2\xa8\x46\x3f\x9c\x85\xfe\x18\x80\x81\xa8\xc1\xd9\x38\x07\x83\x30\x18\x43\x70\x2e\x86\xe2\x27\x18\x86\xe1\x18\x81\xf3\x30\x12\xa3\x64\x94\xe2\x02\x8c\x71\xa4\x26\xc6\xe2\x62\x8c\xc3\x78\x4c\xc0\x25\x98\x88\x4b\x71\x19\x2e\xc7\x24\x4c\xc6\x15\xb8\x12\x53\x70\x15\xa6\xe2\x6a\x4c\xc3\x74\x00\x6b\xb1\x0e\x77\xe3\x1e\x3c\x84\xcd\x78\x12\x3b\xb0\x1d\x3b\x51\x8b\xa7\xb1\x0b\xcf\xe0\x59\xec\xc1\x73\x78\x1e\x3f\xc7\x0b\xd0\x10\x43\x3d\xf6\xc9\x88\xc5\x01\xbc\x88\x83\xf8\x05\x5e\xc6\x2b\xc1\x5a\x2c\xc2\x4c\x5c\x8b\xeb\x83\xbb\x71\x0b\x7e\x86\x05\xf8\x69\xf0\x4f\xb8\x19\x73\x42\xd9\xb8\x0b\x5b\x42\x01\xdc\x18\xca\x09\xe5\xe2\x3a\x2c\x09\x9e\x0e\x21\x48\x7c\x51\x28\x84\xb9\xb8\x83\x5f\x89\xdd\x88\xe3\x4e\xcc\xc0\xbc\x90\x60\x13\x43\x59\xc1\x46\xdc\x80\xa5\xc1\x67\x70\x0d\x56\x62\x0d\x1e\x65\x61\xd6\x3a\xf8\x58\x70\x4b\x70\x7b\x70\x47\xf0\xc9\xe0\x53\x78\x29\x34\x06\x47\xd8\xd9\xc1\x03\xc1\x3f\x04\xf7\x06\xf7\x85\xd6\x84\xd6\x06\x77\xe1\xd6\xe0\xb6\xe0\xce\xa0\x86\xd5\xb8\x17\xab\x70\x1f\xd6\xe3\x7e\x6c\xc4\x03\xd8\x80\x87\xf1\x08\x80\x4d\xd8\x8a\x27\xf0\x38\xfe\xa6\xdc\xa5\x3c\x89\x85\xca\x16\xe5\x71\x65\x2b\x6e\x53\x9e\x52\x9e\x50\xee\x76\x96\x50\xea\x82\xed\x98\x85\x75\xd8\x88\x87\xf1\x04\x3e\xc3\x7e\xfc\x1e\xf7\xe3\x21\xec\xc4\x73\xd0\x50\x87\xfd\x88\xe3\x15\xbc\x8a\x7b\xb0\x06\x9b\xb1\x17\xbb\x71\x1b\xee\xc3\x0b\x78\x0a\x7b\x70\x00\x0b\xb1\x0a\xf3\x51\x8b\x2d\xb8\x05\xcb\x70\x07\xa0\xa1\x4a\x43\xe1\x18\xed\xc2\x71\x93\xb4\x0b\x6e\x9e\xac\xa1\xec\xdc\x76\x9a\x5a\x39\x69\xf0\x64\xd9\xb6\x74\x72\xe4\x5d\x8d\x15\xf6\x6a\xd7\x53\x63\x55\x91\xf7\xb5\x9c\xca\x9e\x9a\x52\x35\x66\xc2\xa4\xf3\xca\x26\x97\xf4\xd4\x78\xd5\xf5\xed\x22\xda\xd0\x71\x93\x4a\xb4\xa1\x93\x7b\x6a\xa2\xca\x39\xb5\xa4\xac\xe4\xb6\x49\x1f\x16\xfd\x7a\x72\xd1\x98\x09\x93\x26\x9d\x2e\xfa\x72\x72\x51\x59\x89\x16\xa8\x9c\xa4\x8d\xbc\x79\xb2\xfc\xc3\xe4\xc9\xed\x7a\x6a\x81\xaa\xdc\x29\x57\xf4\xd4\xd4\xaa\x58\x29\xbb\x6b\xdc\x24\x2d\x72\xd7\x94\x29\x45\x1a\x26\xf7\xd4\x82\x55\xb1\x2e\xb2\x69\x68\xaa\x29\x54\x55\x90\x1f\xa9\xe9\xdd\x53\xcb\xaa\x8a\x2c\x75\x6e\x92\x28\xfa\xf5\xe4\x88\xc6\xcb\x47\x97\x45\x34\x51\x71\x81\x86\x71\x93\xd6\x5f\xbb\x7e\x7a\xc4\xf9\x32\xb0\xa8\xa4\x64\x72\xd1\x7a\xf9\xdb\x04\xf7\x37\xe7\x86\xd9\xee\xe8\xf2\x8a\xf2\x4a\x26\xf7\xd4\x5a\x54\x45\x7e\x27\xa7\x93\x53\x15\xe9\xad\x05\x2b\xa7\x4c\x8a\x44\x46\x95\x8d\x9c\x3e\x27\x32\x29\x32\xf3\x1a\xf7\x12\x4e\xbf\x5c\xe7\xce\x91\x9a\xde\x91\xf5\x91\x51\xeb\x47\x4e\x2f\x5b\x1f\x59\x5f\x26\x6f\x57\xe6\x5c\x5c\x1b\x3a\xb0\xa8\x64\x72\x51\x99\xd3\xa0\x0d\xbd\xd6\xf9\x65\x72\x4f\xad\xa5\xbc\xd3\xe0\xe3\xed\x4a\x4a\x8a\x22\xc7\xd7\x8f\x99\x30\x29\xb2\xbe\x6c\x74\x44\xc3\xa5\xde\xd8\x4a\x64\xb7\x56\x55\x65\x91\xe3\xde\xcd\xcb\x22\x93\xc6\x5c\x52\x54\xa2\xb1\xc9\x93\xd6\x6b\xa2\x62\x74\xd9\xfa\xb2\xc8\xfa\xd1\xeb\xcb\xa6\x3b\x27\xb8\xa7\x38\x87\x9e\x5a\x9e\xb3\x0c\x05\x95\x3d\xb5\x7c\x67\x02\xce\x97\x82\x8c\x09\xac\x77\x0e\x65\xd3\xe7\x4c\xf3\xcf\xc4\x39\xb5\xb0\x2a\xb2\x3e\xb2\x7e\x9d\x43\xb6\x0b\x66\x96\xad\x0f\x6a\x91\x71\x93\x06\x15\x1d\x9e\xdc\x53\x0b\x57\xd5\x63\x28\x1b\x3a\x6c\x18\x1b\x73\x20\x0f\x33\x20\x3f\x9d\xce\x97\x4e\x72\x3e\x27\x4c\x2a\xbb\x26\xa2\xa1\x6c\x58\xd1\x35\x11\x8d\x95\x0d\x9b\x1c\xd1\x86\x4e\x98\x54\x87\x08\x86\xcf\x18\x56\xc7\x22\x6c\xf8\x8c\x61\x5a\x64\x86\xd6\xfe\xda\x8e\xc9\x7b\xb5\xae\xd2\xd8\xf0\x19\x65\x1a\x86\xcf\x28\xeb\xe9\xca\x20\x46\x84\x56\x50\x70\x04\x10\xd9\x81\xfd\xe0\x08\x02\xd5\xf9\x25\xf9\xe5\x25\xf9\x25\x47\xf8\xe8\xd3\xc5\xca\xad\xa7\xd7\x05\xf6\x7f\x7f\xc1\x6c\xf1\x05\x14\x74\xa7\xcf\x94\xea\xc0\x7e\xb4\x40\x2b\x0c\x40\x5d\xae\x82\x4a\x2d\xab\xf7\x5e\x9e\x85\x56\xa2\x92\x69\x79\xbd\x35\x1c\xdf\xab\xb6\x40\x9e\xa8\x8c\xe5\xb3\xca\x98\x8a\xfc\x82\x58\x4e\xab\x9a\x1a\xc4\x72\x79\x7e\x81\x96\x53\xd3\xa7\xef\x80\x7e\xfd\xab\xa3\x6d\x5a\x87\xd5\xb2\xd2\x8a\x22\x56\xcd\xba\x4f\x1c\xd9\xeb\xec\xf1\x23\xce\x1a\x78\xe7\x0b\x27\x1a\xbf\x9e\x30\xe6\xca\x9a\xfe\x23\xa7\x9d\xcd\x96\x8b\x0e\x3f\x7c\xe1\xc8\xd1\x8f\x79\x2d\xbf\xd0\x1b\x5b\x14\x75\xcc\xb9\x67\xa0\x7a\x2f\xb2\x10\x12\x95\x9a\x88\x32\x2d\x94\xbc\x6d\x50\x54\xc6\xb2\x92\xb7\x55\x44\x4d\x0d\xfa\xf4\x2d\x62\xd5\xbc\xba\xb0\x9a\x7f\x7c\xfe\x6b\x5b\xbe\x3c\xff\xb5\x2d\xbc\x56\xc9\x3b\xfd\xb5\x03\x28\x18\x0c\x04\xce\x09\xec\x47\x11\x8a\xd9\x60\xd4\x75\x00\x2a\xeb\x5a\xb7\x69\x5f\x5d\x5d\x5d\x17\x54\x50\x59\x17\x6a\x91\x53\x5d\x5d\xbd\x17\xac\x43\x30\xb7\xb2\x5e\xc9\xef\xd8\xa9\x4b\xdb\xea\x18\x02\x0d\xf5\xe1\xb6\xed\x8a\xba\xb4\x8d\xee\x0d\x08\xf9\x27\x9e\xd7\xb9\xd8\xf9\x53\x20\xd0\x50\xaf\x66\x65\xe7\x76\x69\x1b\x65\x5a\xa4\xb7\xd6\xe1\x78\xac\x7d\x4e\x83\xd6\x3e\x2f\x16\x64\x95\xb1\x50\x6e\x83\xd6\x3a\xaa\x85\xf2\x62\x6d\x72\x1b\xb4\x36\xbd\x9d\x6f\x2d\x58\x65\x2c\xa7\x4d\x43\xac\x84\x55\x6a\xfd\x3b\xc4\x07\x5f\xfa\xe5\x7e\xb4\xae\xcc\x8e\x0f\x7e\xe8\xab\xfb\x9c\x2f\x5a\x87\xbc\x7a\xa5\x43\xb0\xb0\xb2\x9e\xcb\x4f\xd5\xf9\xd4\xda\xe7\xd5\x67\xb5\x0f\x15\x56\x6a\x6d\xf2\xea\xb3\xdb\xb4\x28\xac\xd4\x5a\xe7\xd5\xe7\xb6\xce\x29\xac\xac\xcf\x93\x9f\xf9\xf2\x33\xec\x7c\x3a\x7d\xda\xca\x3e\xed\xf3\xea\xdb\xc9\xb3\x3a\xe4\xd5\x17\x25\xaf\xd3\x31\x79\x9d\x4e\x4e\x9f\xfa\xce\xc9\x9e\xc5\x4e\x3b\x1f\x9a\xa7\x70\x67\x42\x79\xf9\xce\x8c\x3b\x76\xea\x5c\xdc\x2b\xe3\x9f\x36\xb4\x03\xfa\xf4\x2d\x1c\x50\x52\x58\x32\xa0\xa4\xb0\x9a\x4b\x04\x4b\x24\xca\x0a\x1d\x38\x7f\x1a\x9c\xcb\x3a\xce\x68\xfc\x32\x97\x55\xde\xb6\x69\x29\xeb\xba\xfc\x9e\xdb\x99\xda\xb2\xf1\xe3\x69\xac\x28\xb7\xf1\xcd\xdb\x1f\xba\xb3\xf1\x0f\x4b\xef\xbb\xe5\x25\xd6\x75\x4a\xe3\x09\xf6\xdc\x3a\x76\xe1\x1a\x56\xd7\x38\xd6\xc1\x9a\xc6\xbd\xeb\x1a\x27\xb2\xe7\x1c\xac\x63\x17\x4a\x91\x8b\x91\x74\xb7\xa8\x56\xf3\xd0\x19\x5d\x1c\x9d\xc7\x6e\x80\xd6\xa9\x77\x4c\x04\x1b\xb4\xf2\x68\x5d\x27\x91\x5d\x59\x3f\xb4\x53\x51\x56\xa5\xd6\x31\xaa\x95\xf6\xd6\x0a\xab\x63\x2d\x82\x0d\x5a\xcb\x28\xd3\x7a\xf6\xd6\x42\xc7\x63\xc5\x2d\x1b\xb4\xe2\x3c\xad\x28\x72\x3c\x3f\xd6\xb1\x4d\x83\xd6\xb1\x77\xac\xa8\x4d\x43\x5d\xc7\x22\xe7\xc4\x8e\xc8\xaa\xd4\x8a\xf3\x62\xdd\x58\x65\xac\x6d\xab\x86\xfa\xdc\xb6\xdd\x42\x72\x89\xb4\x9c\xde\xb1\xdc\x36\x0d\xb1\x5e\xee\x4a\x0d\xb9\xf1\x1b\xe6\x2c\x90\xd0\x3a\xe6\x69\x39\x87\xb5\xa2\x3c\x2d\xf7\x70\x40\xeb\x98\x57\x2f\x3a\xe6\x14\x56\xc6\x87\x6c\xfe\x66\x0f\x5a\x57\xb6\xa8\x0f\x38\xbf\x06\xea\x5b\x38\x07\xad\x28\xaf\xbe\x65\x51\x6e\x61\x65\x7d\xa1\xf3\xd9\xd4\x29\x2c\x1b\x3b\x38\x9f\xf2\x1a\x9d\xd2\xaf\x51\xe2\x5e\xa3\x34\x79\x8d\xf2\xf4\xb3\x2b\x9d\x5f\xeb\x02\x1d\x73\x1c\xd1\x50\xa6\xb6\xcc\x2f\xa8\xd1\x4a\x6a\xea\x3a\x14\xe5\x3a\xdf\x2a\x6b\xb4\x70\x0d\xf6\x07\x72\x72\xc3\x1d\x4a\x2a\xbd\x65\x63\x43\x73\x44\xa0\x45\xcb\xc2\x70\x87\x4e\x25\xa5\xe5\x95\x19\x2b\xca\x10\x13\x9d\xf2\x0b\x34\xd4\x68\xa5\xf9\xf5\x2c\x94\xdf\xb6\x4b\xdb\x1a\xad\x45\x81\x96\xe7\xec\xe0\xb3\x3a\xb3\xb6\x85\xbd\xd8\x59\xfd\xfa\x9f\xcb\xaa\x83\x6d\xda\x06\x2b\xba\xf2\xce\xac\x75\x58\x6d\xc5\xca\x06\x54\x14\x86\xdb\x16\xb6\x64\x85\x43\xd8\x59\xfd\x2a\xba\xb2\x91\x17\xbc\x7c\xe9\xb4\xfb\x97\x7f\x70\xa4\xeb\x9a\x2e\x4f\xde\x31\xfc\x96\x65\x53\x1e\xbd\xf3\xb3\x5f\xf5\x5d\xd3\xf7\x55\xe3\xee\x71\x73\x6f\xb8\x7f\xf6\xad\x43\x2f\x62\xb3\xb5\x9d\x5d\xfb\x2a\xec\x40\xbf\x47\x16\x6f\x3b\x92\xff\x82\x96\x33\xf4\x81\x9f\x64\x35\x4e\x1c\xb8\x61\xfe\xf6\x37\xdb\x7e\xfc\x61\x4b\xbe\x62\x41\x3f\xb6\xb4\xe5\xc2\x7f\xd5\xe5\x2e\x99\xdc\x7f\x7c\x31\xaf\x76\xf8\x20\x80\x9d\x64\xa9\xd9\x81\x37\xd1\x12\x05\xe8\x8c\x9e\xa8\xc1\x76\xd4\xb5\x72\x76\x71\x25\x50\x19\xeb\x13\x68\xa8\xcb\x73\xf6\xb1\x50\x50\x19\x2b\x0a\x34\xec\xcd\x69\x5d\x29\x72\x2b\x63\x39\x81\x86\xbd\x65\xfd\xe5\xd7\xb2\x40\x03\xd3\xce\x76\x24\x48\xac\x30\xb7\x41\x2b\xcc\x8b\xb5\x67\x95\xb1\x60\x6e\x83\x16\xcc\x8b\x15\xb3\xca\x58\xaf\xdc\x06\xad\x57\x5e\xac\x1f\xab\x8c\x55\xe4\x36\xc4\xce\x61\x95\xb1\xf6\x85\xf9\x05\x75\x39\x05\xa2\xa6\xa6\x26\xd6\xaf\x57\x7e\x41\x5d\x5e\x65\x59\x8d\x23\xe4\x72\x5a\xe5\x17\xc4\x8a\x7b\xd5\xd4\x68\xad\xf3\x63\x15\xfd\x6a\x6a\x62\x65\xfd\xf3\x0b\x62\x85\xa8\xa9\xd1\x8a\xf2\x63\xc1\xf6\x35\x35\x7d\xfa\x16\xf6\x2b\x70\x25\xa0\xd2\x92\x95\x95\x56\x14\xb2\x6a\xc6\xc3\xd5\xd1\xfe\x05\x67\xf5\x2b\x2b\x6d\xc9\x58\xf2\xcf\x2d\x95\xb2\xd2\x8a\x01\xbe\xbf\xec\xbc\xee\xb9\x45\x37\xdf\x76\xee\xac\x0d\x97\x2f\xb8\x7d\xb8\x18\xb2\xed\x87\xa3\xe3\xae\x1b\x32\x6b\xf8\xec\x9f\xcc\x3a\x57\x99\x32\xeb\xf9\x1b\x6f\xbe\x7d\xf0\xac\xfb\x27\x2f\xbc\xfd\x91\x99\xe7\xce\x3c\xef\xfa\xa1\x33\xcf\xe5\x53\x77\xb1\xe8\xa6\x07\xee\x9a\xdb\x48\x3f\x9f\xbe\xf9\x74\xb5\x23\xc8\xf9\xb4\x9d\x2b\x18\xbf\x6e\xdb\xed\xf6\xe9\xc1\x7b\x58\xcf\xcd\x1b\xd7\xcd\x3d\x1d\x9b\xf9\xf0\x23\x3b\x97\x32\x75\xd6\xb6\xdb\xfe\x21\xad\xd2\x61\x64\x05\xba\x07\x7e\x8d\x4e\xe8\x86\x7e\x58\x84\xba\xb6\x0e\x4d\x8b\x1c\x9a\x96\x04\x1b\xea\x42\x0e\x39\xa3\x6a\x03\xd3\xce\x92\x84\xeb\x9c\xdf\xa0\x75\xce\x8b\x05\x58\x65\xac\x7b\xab\x06\xad\x7b\x5e\xac\x37\xab\x8c\xb5\x68\xd5\x10\xeb\xef\x34\x05\xf2\x0b\xea\x78\x51\x49\x4d\x4d\x8d\xd6\x3b\xbf\x3e\xd4\xa5\xbc\x95\xcb\x4c\xf5\x79\xad\xdb\xb6\xeb\xd2\xb6\x06\xb1\x68\x49\x7e\xc1\x7e\x04\x5a\xb4\x6e\x57\x5e\xd9\xa5\xad\xa4\x51\xff\x01\x15\x67\x79\x9a\xa2\x25\x0b\xb2\xfe\x03\xaa\xd5\x60\x61\x59\x57\x49\xb2\x01\xe1\x36\xd5\xd1\xfe\x03\x58\x4b\x85\x85\xdb\x0e\x51\xce\xea\x57\x51\x56\xaa\x0e\xab\x7b\xe7\xda\xdf\xd7\x3f\xac\x5d\xb4\xa1\x8e\xb5\x5c\x72\xe1\xde\x6b\x0f\xbc\xf9\xde\xc2\x5b\x3f\x58\xf9\xfc\x9b\x75\x2b\xaf\xbb\x6c\xfb\xac\xc6\xdf\x2f\x5e\x70\x36\xeb\x30\x76\xed\xcc\xc1\xe3\x2f\x9e\x35\x9f\x4d\x7a\xe8\xfd\x59\xdb\x1e\x78\xfa\xad\xa7\xd6\x5e\xb2\x7a\xe1\x15\x8d\xeb\x66\x1f\xfa\xa6\xae\xf1\xeb\x6d\xd7\x4c\x38\xf2\xe2\xec\xdb\x87\x5f\xc2\x9e\x1e\x34\x6d\x91\xf2\xc2\x2d\x37\x0c\xbf\xe8\xca\x81\xe7\x4f\x96\xff\x1b\x98\xa3\x8b\x98\x25\x75\x51\xa9\xab\x89\x3c\x35\xc4\x34\x21\x75\x90\xe2\xaa\xbe\x00\xab\xf4\x34\xcf\xc7\x29\x8d\x23\xcf\x9f\xd0\x78\x50\xf9\x3a\xb0\x1f\xd9\x88\xa0\x8e\x2b\xa8\x64\x5a\x0b\x49\x41\xb5\x55\x43\x2c\xc7\xd3\x5c\x5a\x96\xa3\xb7\x0a\xf3\x0a\x58\x35\xf2\xf3\x0a\xcb\x94\x09\x7f\x67\xbc\xb6\xb1\xe5\x8d\xf7\x3e\xc4\xf2\xd8\xe5\xca\x08\xd6\xe2\xf4\x07\xa7\x57\x34\xfe\xbc\xf1\x07\xc6\xa5\x1e\xa7\x6b\x1a\x0f\xb2\xc6\xe4\x75\x45\xf2\xba\xca\xf1\x58\xd0\xbb\x6e\x50\xc9\x2f\xd0\x02\xce\x75\x39\xf2\xf3\x78\x75\x41\x7e\x9e\xc2\x9e\x64\x5f\x2f\xbc\xf7\x81\xbf\x37\x9e\x6e\x3c\xa8\x74\x55\x96\xb2\xcb\x18\x1a\xff\xde\xb8\xaf\xb1\xf6\xf4\xe1\x46\x5b\x8e\xf7\x1d\x65\x96\xb8\x53\x2d\x42\x4b\xa0\x70\x40\xa0\xb0\x2d\x2f\x0f\x96\x17\x06\x5b\xb0\xae\xec\x9d\x1a\xb6\xb0\x7b\xdd\xad\x6c\x7b\xa8\xf1\xf6\xba\xe7\xe6\xff\x6b\x29\x8b\x8a\xda\x6d\x2f\xb2\x7b\xcb\x1a\x57\x85\x77\xf7\x69\x5c\xd3\x9f\x6d\x6c\x7c\x61\x29\x6b\x27\xaf\xb3\x94\xa9\xa2\xbd\xd8\x8e\x16\x98\x00\x0d\xbd\xb5\x60\x75\x8c\x05\x1b\xb4\x40\xb4\x0e\xcc\x91\xb9\xc8\xce\xaa\xac\x63\x70\xbe\x32\x9e\x55\xc9\xb4\x9c\xde\x5a\xf6\x71\x4d\x89\xc6\xb2\x72\x1b\x34\x11\xad\xcb\xca\x76\xfe\x96\x15\xcc\xaa\xac\xcb\xce\x72\xbe\x66\x23\xab\x32\x96\x2b\xe9\x5c\x78\x56\x49\x7e\x75\x7e\x49\xeb\x92\xfc\xb2\xfc\xa5\x6c\xd5\x23\x6c\x55\xe3\xd2\x47\x94\x75\x8f\xb0\x35\x8d\xb7\x3f\xd2\xb8\x9c\xdd\xe9\xd2\x68\x77\xe3\x77\xec\x5c\x7c\x05\x15\x11\x67\x0c\x7b\x95\x2c\x64\x39\x2b\x17\x94\x2b\x27\x5a\xa0\x85\xa8\x8c\x85\xe4\x15\x79\xff\xc2\xea\xb6\x2a\x9f\x34\x65\x7e\x22\x74\xcd\x73\x8d\xdf\xfd\x96\x55\xb4\x7d\xa7\xf1\x5b\xd7\x66\x3a\x8b\xbd\xad\x0c\x56\x96\x80\xa3\xc4\xb9\x4e\x8c\xf1\x06\x07\x3e\x16\x08\xa5\x58\xa0\x70\x40\x49\xf0\xac\x72\xf6\x59\x17\xf6\x76\x6d\x2d\x98\x63\x3f\xb1\x4a\x7c\x87\x16\xe8\x85\x26\xc3\x29\x65\x3f\xe5\xf8\xec\xa7\xa4\x19\xe5\xce\xd1\x6f\x34\x75\xbf\x74\x74\xcf\x01\x13\x46\x56\x0f\x18\x7b\xe1\xd4\x01\xfd\xcf\x9f\x36\xd0\x9d\xdf\x76\x80\xaf\x93\xbc\xd9\x06\x75\x70\xf6\x2b\x93\x8c\x20\x7a\x7b\x83\x29\x63\xd5\x6c\x2a\xef\x79\xe0\x5f\xef\x39\x72\x40\xfa\xa8\x37\x91\x25\x46\x06\x7e\x8d\x1c\xb4\xc7\x08\xd4\x65\x3b\x1b\x3c\x2f\xd8\xe0\xca\xcb\x36\xa1\x06\xa6\x75\x90\xec\x99\x9b\xdd\xa0\xe5\xe6\xc5\xc2\x0e\x87\x16\x36\xc4\x8a\x58\x65\x2c\x9c\x9b\x5f\x10\xcb\x76\x6c\xac\x58\x9b\xbc\xfc\x82\x98\x0a\x29\xdb\xf2\x0a\xba\x54\x47\xf2\xf3\x14\x94\x95\x2a\xee\x36\x2d\x38\x2b\xaf\xac\x54\x55\x6e\xda\xc1\x72\x35\xb6\x70\x4b\xe3\x57\x2f\xd6\xff\x62\xff\xf4\xb9\xf3\xf6\x2d\x3a\x3a\xef\xe0\xcd\xec\x43\x96\xcf\x4e\x7e\xdf\xd8\xbd\xf1\x83\xc6\x0e\x04\xa6\xfc\xa5\xb6\xee\x04\x7b\xee\x2b\x56\xf3\x59\xe3\x55\xf2\xff\xae\x2b\x07\xf8\x7d\x92\xb7\x2f\x41\x9d\x00\x2a\x35\x5e\xed\x5a\x81\x4a\xb5\x64\x73\x71\x3c\xc6\xb3\x25\x9b\x4b\xb5\xfc\xf0\x37\x5b\x1c\xb5\xdc\x52\x13\x79\x5a\xe0\x70\x40\xe3\x79\x9a\x72\x98\x43\x0b\xf4\x62\x31\x25\xe0\xda\x2b\x31\x26\xf2\x0b\xb4\xec\x9a\x3e\x7d\xb3\x58\x35\x2b\x2b\xec\x3f\x40\x6d\xc5\x58\x39\x7b\xf3\x89\xc6\x5f\xee\x3f\xda\xb3\xfb\xc0\xf1\x7b\xc5\x43\xac\xec\xfb\x0b\xf8\xdd\xc7\xd7\x9f\x1d\x5d\xe8\xac\xbb\x0a\x88\x9a\xc0\x9b\xe8\x80\x61\x2e\x7d\x63\xed\x78\x43\x5d\x2b\x87\x52\x59\x0e\xa5\x8a\x7a\x6b\xea\xf1\x58\x41\x61\x43\xac\x23\xab\x8c\x15\xa8\xf9\x05\xb1\xf6\x1d\x1c\xf2\xb4\x73\xf6\x34\xab\xd1\xb2\xf2\xeb\xd5\x9c\xdc\x02\x29\xdf\xaa\x07\xb0\xa4\xdc\x0a\x76\x6d\x92\x72\xad\x4b\x82\x6a\x09\x7b\xfb\xad\x65\xe7\x2c\xbe\xf6\xe2\x87\x26\x5d\xf6\xea\xa7\x7b\x7f\x3d\xe6\x85\xe3\x8d\xbb\x95\xad\xc5\x5b\xd8\x8e\x17\x1f\x5e\x3b\x7e\xda\xc2\xc1\xc3\x6e\x7f\x72\xdf\x63\x73\xf6\xbf\x71\xb0\xf1\xbd\x90\xfc\x7f\xe3\xd1\x93\x2c\x51\x1d\x78\x13\xdd\x30\x0d\x75\x5d\x9d\xb1\x89\x60\x43\x5d\x7b\x67\x6c\x85\xc1\x86\xbd\x39\x2d\xba\xb6\x77\xb4\x5e\xb0\x81\x69\xdd\x7b\x6b\xc1\xe3\xb1\xb2\x70\x43\x7d\x5e\x59\x30\x54\x19\xeb\x98\xdd\x10\xeb\xc1\x2a\x11\x13\x5d\x5d\x7d\xdf\x22\x3f\xc6\xca\x6a\x6a\xb4\x9c\x82\x58\x71\xa4\xa6\x46\x2b\xcc\x8f\xb5\xe9\x58\x53\xa3\xb5\x2f\xd0\xda\x7a\xca\xbf\x3a\xda\xff\xac\x7e\x15\x95\x6c\x80\xfb\xc5\x37\x09\x35\xd8\xda\x31\x04\x1c\x29\xdd\xf3\xd2\xdf\x4e\xfd\x59\xfd\xe6\xfb\x57\x15\xaf\xa9\xfd\xfd\xbc\x19\x53\x9f\xb8\x68\xe2\xab\x0d\xb1\x63\xc7\xea\x57\xdc\xb3\xec\x9b\xa7\xdf\x3d\xe7\x85\xde\x03\xb6\xae\x5b\xbe\xea\xe1\x3d\xeb\x27\xcd\xf9\x49\xff\xe5\x1b\x9f\xdb\xfc\xf8\xfb\x91\xac\x76\xcf\xdc\xb6\xe6\xcd\x45\x90\xd1\x5c\xd7\xb7\xce\x46\x21\x56\xa2\x2e\xcb\x59\xf9\x50\x75\x9d\x22\xa5\x6e\x8b\x2c\x25\xb7\x32\x26\x72\xaa\xab\x63\xe0\x0d\xb1\x60\x76\x34\xca\xb4\x70\x6f\x2d\xeb\x78\x2c\xd4\xaa\x21\xd6\xda\xe3\x85\xa7\xbf\xf9\xdc\xe5\x85\x2c\xd7\x38\x0b\xe5\x69\xe2\x70\x7d\x30\x24\x0a\x2b\xb5\xac\xbc\xfa\xec\x2c\xc7\xe8\xca\x71\x3e\x39\xb4\xdc\x5e\x6c\xaf\x08\x66\xe7\xe4\xa6\xcc\xda\x98\xd2\x22\xbf\x20\xc6\x5a\x49\xce\x1e\xe0\x38\x12\xc1\x32\x5e\x56\x58\x5e\x52\xd8\xbf\xb0\xac\x25\x0b\xe6\x14\xf3\x9a\xdf\xbc\x69\x96\x7d\x76\xfe\x0b\xe7\x37\x5e\xc4\xde\xbb\xa0\xd3\x65\xa1\x36\x53\xdb\xb1\x0b\x77\xf2\xd7\xff\xd5\x7f\x5b\xe3\x5e\x76\xe1\x36\x36\x75\x2d\xeb\xd5\x65\x79\x47\xb9\x4e\x17\x92\x25\xe7\xd4\xd1\xd1\xa9\x52\x9d\xf2\x60\x43\x5d\x4b\x67\x9d\xf2\x79\xc3\xde\x70\x56\x51\xcb\xdc\xca\x58\xd8\xd1\xac\x9d\x24\x3b\xb5\x2d\x6c\x88\xfd\x3f\xec\xfd\x7b\x78\x54\xd5\xd9\x37\x8e\xaf\xb5\x0f\xb3\x67\x26\x73\xd8\x87\x39\xe6\x3c\x99\x24\x93\x64\x48\x86\xcc\x26\x19\x46\x24\xa8\x20\x22\x82\x45\x1e\x44\x44\x40\x0e\x91\x93\x07\x84\x88\x88\x88\x88\x4a\x11\x15\x01\x41\xaa\x42\xd1\x52\xaa\x48\x15\xd7\x9e\x19\xa2\x22\xd5\x20\xf5\x54\x6a\xad\xed\x23\xbe\x3e\x96\xfa\x5a\xeb\xf3\x74\xfa\x50\x6b\xb1\xb5\x72\xc8\xe6\x77\xad\xb5\xf6\x1c\x92\x4c\x02\xd4\xbe\xd7\xef\x9f\xef\xd5\xcb\xcd\x38\x91\x66\xdd\xf7\xba\xd7\xba\x3f\xf7\xe9\xb3\xcb\x8d\xc8\x60\xd9\x97\x61\x12\x10\x38\x9a\x1c\x58\x18\x4d\x62\x4f\x38\x90\xdc\x05\x34\xbb\xdc\xd4\x04\x93\x76\x87\x24\xe7\xd0\x1b\x5b\x42\x77\xd3\x22\x25\xa0\xcd\x1b\x8f\x93\x9d\xf3\xe4\xed\x97\x82\xf1\xb9\xb1\x69\x5c\xb0\x6a\xdc\xae\x3d\xaf\xfe\xe7\xa6\xd5\x4d\x57\xcf\x1b\xf7\x36\xb3\x33\xd8\x7d\x72\xc5\xac\xab\x5e\xfe\x70\xb3\x7e\x2a\xf9\xce\xb0\xbd\x73\xf7\xef\xbe\x6b\x83\xcd\x3f\x8c\x41\xbb\xf4\x29\xee\xdf\x68\x4f\xff\x73\x39\xcd\x71\xad\x3e\x73\x8c\x9b\x41\xce\x44\x1d\x58\x08\x12\x3e\x2c\x51\xb9\x90\x4e\xf0\x58\x22\xab\x39\x9d\x92\xaa\x7d\xbc\x3d\xac\x49\x26\x6a\x79\xe0\x88\x56\x22\xa5\x51\x89\xa8\x55\xe1\x2b\x44\x22\xa6\xa7\x55\x95\x48\x72\x42\xf2\xd9\x31\x40\x70\x49\x9a\x95\xc7\xa7\xa6\xba\x5c\x92\x93\xc0\xe1\xb2\x57\x7b\xe3\x9a\x55\x92\x64\x64\x8e\x23\x5e\x42\x02\x41\x07\xc5\xb0\x5a\x8d\x7a\x85\xda\x60\x15\x60\xd5\x36\x48\xe1\x94\x29\x03\x0d\x30\xf4\x0c\x56\x39\x98\xd5\x2b\x3e\x84\xbe\x57\x16\x8d\xaf\x19\x3b\xfb\x43\xfd\x8b\x91\xe6\x61\x2f\x2c\xdc\xa6\xad\xfd\xe2\xd1\x57\xde\x49\x2c\x5b\x78\xdd\x86\x09\x1f\x5d\x74\xc7\x8c\x26\xf8\xfc\x07\xf0\x69\x58\xf5\xb0\x77\x9b\x4f\xff\x44\xff\xc3\xf8\xe9\x6f\x3e\xff\x23\xfd\xf8\xc3\xe9\xc3\xdf\xff\xc1\xc2\x03\xb7\xfc\x35\x36\x6b\x31\xbd\xf7\x9f\x01\x80\x5b\xc5\x77\x02\x13\xf6\xfd\xe4\x7e\xc5\x0e\x5c\x63\xf0\xd9\x17\x22\xc4\x73\x68\x2c\x75\xb3\x83\x9b\x55\x18\x88\x05\x04\xf8\x0c\x73\xba\x3b\x1e\x60\xef\x2b\xe9\xe6\x78\xef\x53\x1b\x4e\x7e\x0c\x58\x30\xed\xcc\x31\x6e\x0a\xff\x1e\xf0\x83\x5a\x10\xc5\x5a\xc3\xd8\x4a\x2b\x13\xd2\x09\x2b\xfe\xff\x1b\x8c\x0f\xa9\x4a\x54\x55\xac\xa4\x51\xb1\xa8\x99\x60\x58\x0b\x49\x69\x14\x12\x71\x90\xa8\x29\xd6\x74\xb2\x51\x09\x98\xc3\xf8\x56\x26\xb0\x34\x64\x92\x64\xc4\xc6\x51\x40\xea\xb4\x7a\xcb\xc4\xea\x86\xc1\x04\x54\x0d\x2e\x93\xe4\x7d\xc0\x64\x57\xaa\x1b\xb2\x98\x0a\x83\x76\x43\x5d\x26\x21\x73\x52\x73\x4a\xab\x0d\x39\xa0\xe2\xf2\x78\xc9\xe7\x60\x95\x69\xda\xfe\x77\xa7\x4e\xba\xf5\xed\x15\xe8\xcd\x1d\x2f\xdf\x79\xf3\x1d\x9f\x3d\xde\xf5\xbb\x57\xef\x5f\x34\x75\xcd\x98\xb9\x37\xbf\xf8\xf8\x2f\xc7\x4e\xf9\xc1\xf7\x17\xcd\xb8\xe5\x7e\x38\xf5\xd1\x8f\xc7\x5f\xb4\xb5\x7d\x09\xba\x7e\xef\xd6\xd5\x07\xc7\x8f\xd5\x6e\xbb\xf3\xf5\xb9\x3f\x4f\xcd\x5f\x31\x72\xf9\xd8\x39\x9b\x86\xc5\x76\x31\x8b\xc7\xaf\x6c\x1d\xba\xa1\x7d\xca\xdc\x55\xc4\x6e\x66\x9e\x39\xc6\x35\x12\xbb\x09\x81\x1b\x40\xc2\x4f\x4e\x82\x39\x8d\x00\x8e\xc8\x20\x9b\x4e\x48\x58\x15\x35\x42\x3a\x65\x2d\xf7\x4b\xf6\xb0\x66\xc5\x06\x54\x17\x41\xf6\x3e\x06\x54\x0f\xc3\x1a\x0e\x73\x34\xd6\x1f\xc7\xc1\x4a\xc2\x2a\x99\x08\x16\xaf\xc1\x06\x24\xd8\x5d\xa6\x6a\x6f\xc6\xf8\x65\x7c\x6a\x83\x55\xb5\x2d\x19\x88\x6d\x85\x5c\xb0\x4a\xc9\x4a\x1f\xac\x32\xcd\x7c\x78\xe1\x3b\xdf\x5c\x64\x55\x7f\xd4\xbe\xa7\xf3\xde\xf4\xe6\xd4\xbb\x8b\x5e\xd2\xff\xf9\xfc\x03\x4f\x2e\x5c\x30\xf5\xd1\x29\x4b\xe6\x3c\x8a\x1c\xcf\x34\x42\x19\xd6\x8c\xb9\xe6\xad\x9f\x3d\x0e\xc1\xa6\x3f\x7e\xfa\x86\x7e\x8d\x7e\xf4\x11\xf6\xb5\xe5\xab\xaf\xf9\xd1\xf2\x55\x9b\x8f\x02\x9a\x27\x81\xef\x71\x73\x41\x11\xf0\x82\x2b\xf2\x3c\x3d\x72\x47\x52\x4e\xc3\xd9\xfb\xf2\x9c\x7d\xd2\x66\x02\xe6\x70\x4a\xa6\x2e\x1f\x07\x20\x36\x80\x45\xb2\xc4\xe3\xd4\x93\x38\xdd\x24\x99\x91\x0f\x03\x94\x42\x90\x60\xe7\xa4\xcb\x1b\x87\x5e\x75\x59\x0e\x1b\xb0\x4f\x5d\x39\x63\xc8\xd0\x31\x33\x63\x58\xef\x67\xb6\xeb\xdf\x92\x75\x99\x80\x0c\x1a\x00\x12\x23\x29\xab\xb1\x1a\x05\xbb\x85\x94\x9d\x2e\x00\xfb\x79\xbb\x80\x17\x40\x73\x28\xac\x1c\xc3\x78\x28\xff\x37\xb6\xdf\x36\xf9\x4d\xf3\xec\xe7\x9f\xc9\xfc\x3e\xfd\x5b\x68\xfa\x0a\x83\x24\xee\x8d\xec\x2f\x84\x60\x19\xf8\x92\x93\xb9\xa3\xd8\x77\x2a\x2d\xd0\x6d\x81\xee\x65\xec\xb6\xee\x0a\xe6\x33\x66\xeb\x5c\xf8\xd9\x0e\xfd\x51\xfd\xc0\x53\x58\x5f\x2b\xe1\x51\xce\xcf\xbe\x49\x72\x3c\xc5\x14\x55\x09\x69\x82\x5c\xf0\x69\x30\x47\x34\x4b\x06\xe9\xb9\x61\x4b\xc0\xbd\x92\xdd\x7e\xba\x9d\xdd\x0e\x8f\x6e\xd9\x02\x27\x6d\xd9\x42\xcf\x67\xde\xef\x8a\xb5\x58\x60\x0b\x74\x2f\x63\x3e\xeb\xae\x60\xb7\x7d\xf9\x14\x1c\x05\x6f\xd9\xa1\x57\xcc\x25\xb6\xb7\xe3\xcc\xe7\xec\x4e\xfe\x30\x28\x02\xb5\x60\x31\xa0\x0e\x3c\x68\x4e\xe7\xe7\xb1\x42\x79\x5b\x83\x7c\x51\x64\x12\x35\xbf\x3d\x8d\xfc\x11\xfc\xa9\x12\x7b\x77\x6b\x9a\xe4\x07\xfc\x24\xbf\x55\x1b\x8f\x23\x93\x44\x76\x0b\x55\xca\x29\xa7\xdb\x53\x1a\x24\x27\x30\xc8\x4a\x72\x42\xf6\xd5\xe2\x8b\xcd\x29\xf5\xc9\x7e\x29\xd9\x93\xe8\x80\x42\xb0\x0d\xc6\xb2\x90\x60\xc7\x7f\x8c\x6d\x1c\x8a\xf7\xb3\x66\xea\xdb\xd7\xed\x79\x65\xd5\x33\xf7\x4c\xf0\x3e\xea\x59\x78\xeb\x1d\x13\x9b\xe6\xcc\xb8\xf2\xb1\x51\x99\xdd\xe5\x2f\x1f\x1c\xdb\xfd\xe4\x9d\x87\x57\xcc\xb8\xb1\x7d\xcd\xee\x29\x53\xaf\x9d\xd5\x76\xed\x9c\x21\x95\x44\xce\x9b\xcf\x8c\x36\x6d\xe6\x53\x20\x06\x2e\x01\x3f\x03\x68\x48\x44\x6b\xe2\xd3\x48\x8a\x20\x9b\xaa\x5d\xc0\xa7\x51\x65\x14\x8d\x88\x68\x3e\x3e\x8d\x42\x11\x8d\xc3\x51\xf0\x48\x72\xeb\x84\xed\x69\x14\xa6\x58\x6f\xa8\x23\x8d\x86\x8a\x5a\x35\x4d\x5d\x69\xa3\x0c\x47\xf4\xa7\xbf\x1e\xa2\x5e\x75\x98\x88\x86\x77\x69\xa5\xbe\x13\xa8\xa4\x0b\x0d\x13\x93\x17\x0e\x1b\xae\x84\x13\x17\x0e\x1b\x9e\x4b\x43\x80\x64\x49\xe9\x85\xc3\x49\xc2\x21\xfb\x09\x7b\x28\xad\x7a\xa8\x24\xbf\x64\x93\x7c\x5c\xa8\xa9\x79\x08\xd1\x96\xd4\x24\xc9\xa8\x39\xae\x8d\xb8\x40\x92\x3b\xcd\xc0\xe9\x72\x54\x1b\xc1\xa0\x08\xaa\x03\x51\x4e\xa6\x57\x7c\x28\x68\xca\x1d\x61\x2f\x6b\x72\xbb\xe8\xe9\xad\x0e\x56\x71\x8c\x5b\x04\x81\x68\x6b\xcc\x6d\x0a\x56\x55\x33\x35\x2e\x35\xaa\xc4\x6a\x71\xe8\x7c\x33\x38\x03\x93\xd0\x7a\x10\x7a\x36\xdf\xfa\xee\x8a\x43\x2e\xf3\x82\xce\x8e\x35\xdf\xff\xdb\x23\x23\x57\x4d\x99\x19\x98\x7d\xf9\x5d\x13\xce\x80\xaf\x3e\xd5\x7f\xf8\x16\xac\x84\xfc\xf5\x9f\xb7\x7f\xfc\xc7\x5f\xe9\x87\x77\x31\xbe\xd5\xa9\xc9\xa3\xe2\x97\x4c\xdb\x31\x15\x7e\x0b\xad\xf0\xf5\xaf\xb7\xea\x7f\xee\x4c\xea\xbf\xdf\xd5\xd9\xf9\xf8\xda\x6d\xe0\xcc\x66\x5f\xb5\xfe\xe8\x92\xb6\xc5\x77\xfe\xef\x9a\xbf\x9c\xfe\x40\x7f\xe0\x8f\xfa\x71\xfd\x68\x53\xdd\x9a\xa9\xcf\xc2\xf8\xff\x7d\x1e\xc6\x74\xef\x2d\x5d\xe4\xdc\x3d\x04\x00\x57\xc2\x77\x02\x01\x38\xc0\x72\x03\x3d\xb2\x9c\x9a\xc5\xb1\x29\x93\x19\x40\x7b\x18\x59\x54\xcd\xc4\xe2\xb8\x08\x22\x67\x16\xd8\x8a\x54\xed\x5d\xb7\x7f\x3b\x31\x0b\x6c\xad\x19\x60\x8b\xac\x62\x92\xb7\x72\x4a\x38\x69\xc1\x4f\x16\x20\x6b\x13\x4c\x32\xbc\xc5\x9a\x05\x31\xd0\x6c\x64\x5e\x83\x50\x55\x82\x6c\x80\x85\x01\xb6\xb6\xc5\x01\x97\xb2\x25\x5d\xfb\xf6\xc5\x74\xe5\x4b\x38\x1a\xde\x17\x28\xa9\x1c\x87\xe3\x02\xf8\xb6\x1e\x67\x16\xc2\xe8\xe7\x4b\xc7\x6f\x23\xb9\x80\x49\x00\x70\x9d\x7c\x27\x70\x02\x1f\x08\x80\x27\x8c\xd5\x8b\xe6\x34\x59\xbc\x16\x30\xa7\x53\x7e\x1f\x5e\xbd\xe6\xc7\x87\xb5\x2a\x82\x5c\x47\x34\x9b\x2b\x8d\x6c\x22\xe2\xf1\x7d\x5e\xe6\x4a\xa3\xb2\x88\xc6\xbb\xd2\x5a\xd0\xc0\x65\x4f\x1e\x4f\x11\x28\x03\x9a\x50\xa0\x09\x01\x51\x13\xc5\x13\x28\x20\x6a\x50\x3c\x81\x44\x31\xe9\x13\x03\x4a\x38\xe9\xc7\x4f\x76\x1f\x80\xa2\xcf\x1f\xc8\xe5\x1a\x35\x9f\x48\xe4\x41\x7e\x49\xb3\x98\xe3\x71\x14\xc8\xba\xdc\x3c\x04\xca\x05\x42\x81\x9e\x28\x35\x0c\x27\xc1\x16\xb8\xe2\xa3\x4f\x7e\xba\x63\xc9\x72\xfd\x3f\xf5\x53\xa7\x21\xb3\xf7\x67\x1b\x1e\xf8\xa2\xf2\xab\xc7\x53\x77\x3d\xf2\x3e\xdf\xb9\xe7\x99\xf5\x07\xcb\xad\x95\xdb\x6e\xf9\xed\xdf\xb7\x6f\xdb\xb8\xf8\x8e\xc7\xd7\xaf\x98\x35\x9f\xdc\x2d\x9b\xcf\x1c\xe3\x1d\xfc\x61\xe0\x05\x23\x41\xc2\x4d\xe4\x67\xd3\x48\x14\x91\x8c\x05\x54\x58\x23\x62\xb2\xe0\x30\xd0\x47\x23\x26\x77\x1a\xdf\xe3\x40\xb3\xc8\x92\x9c\x00\x02\x01\x37\x9c\x84\x4c\x99\x20\x89\xa2\x17\x8e\x71\x63\xef\x43\x0c\x16\x6c\xfe\x35\x9c\xfb\xd9\xaf\xb6\x5e\xfe\xd0\xc6\x17\xf5\xbf\x3f\xf1\xda\xee\x8d\xa9\x1f\x1f\xfc\x87\x7e\x8c\x29\x81\x10\x1e\xfc\x72\xe2\xe3\x63\xde\xd2\x37\x7d\xf8\xea\x47\x17\x3e\x3d\x1c\x86\x29\xfe\x9a\x04\x00\xef\xe5\x3b\x81\x05\x28\x60\xba\x81\x91\x81\x8a\x91\x17\xdd\x1c\x05\x83\x13\x57\x04\x39\x8f\x68\xbc\x3b\x07\x8b\x9f\x38\xfe\x62\x46\xfd\x0a\x51\xbf\x55\x3c\x81\x14\xa2\x7e\x36\x09\xa0\x55\xc9\xea\x5a\xb1\xe6\x00\x4d\x25\x90\x44\x86\x0b\x84\xd4\x68\xb5\x9c\xd5\xe7\x54\xe8\x82\x95\xbf\xd6\x97\xeb\xa7\x37\x6d\x7f\x0b\x36\x3c\xf5\xce\xc1\xbd\x7c\xa7\x7e\x44\xff\x5c\x3f\xa9\x2f\xfa\x3f\x3b\xf6\xc1\xcb\x3f\xfc\xe0\x23\xa2\x43\x6c\x47\x8b\x48\xed\x60\x81\x61\x43\x16\xd6\x58\x26\xc7\xa6\x53\x3c\x39\x01\x1a\x8f\x55\x68\x8b\xe0\xb0\xb7\xf7\x52\x39\xb2\x54\x8b\x74\x02\x71\xa2\x06\xa5\x13\x18\xc1\xf3\x16\x6c\xfa\x66\xfc\xc4\x96\xc2\xf1\x66\x4b\x7e\x56\x5a\x85\x99\x4c\x74\x40\x98\x04\x5b\x98\xff\x0e\x76\x7f\x30\x8b\x29\xaa\xe8\xfe\xfb\x62\xa6\x39\xc8\x77\xee\xd4\x87\x3e\xdd\xfd\xcd\xce\x1e\xeb\xb3\xe0\x18\x0a\xaf\x0f\x59\xd4\xdc\xf2\xcc\x3c\x59\x9e\x19\x2f\xcf\x4a\x76\xd8\x62\x4d\x6b\x45\xc6\x2a\x77\x1c\xff\x39\x5d\xa5\x88\x60\x17\x0e\x36\xb8\xae\x1e\x4b\x4b\xe2\x95\x15\x5a\x16\x59\x54\xa0\xfb\xfd\x9b\x19\x5b\x55\xf7\xd7\xf7\xf1\x9d\x3b\xbb\xbf\xdd\xd9\xbd\x35\x63\x73\x13\xf8\xc3\xa0\x1c\xdc\x0d\x12\xa5\x58\x5f\x72\xc6\xce\x8a\xd8\x74\xca\xe3\x2d\xe5\xec\x61\xe4\x53\x35\x0f\x9b\x46\xee\x28\x44\x15\x64\x59\x4e\x77\x1a\xbb\x28\xb2\xac\x75\xc7\xdb\xc9\xb2\xdc\x4d\x0e\xe4\xea\xe2\x35\x9f\x78\xc2\x81\xfc\x5d\x40\x73\xf9\xf1\x7d\xec\x72\xfb\xfc\xb9\x88\xc1\x23\x63\x9c\x01\xe2\x71\xad\xc8\x4b\xd1\x36\x67\xa0\x6d\x62\xae\x1e\xaf\xd0\x04\x73\x06\xab\x04\x62\x01\xd6\x01\x83\x95\x60\xf3\xaf\xe0\x82\xdf\x2f\x3d\x3c\x7f\xf4\xf8\xbd\x0b\x9e\xd1\xff\xfa\xc4\xdb\xa9\xf5\x8b\x66\xe8\x9f\x05\xe1\x87\xdb\x97\xbf\xbd\x50\x3f\xa1\xff\x8e\x91\xa1\x0d\xbe\x7a\xbc\xae\xe9\xe9\xaa\xe8\x3b\xfa\xb6\xa3\x3f\xfb\xb0\x06\xa2\xa7\xbb\x5b\x1a\x02\x30\x48\x7d\xf7\x64\x00\xf8\xe5\xc4\x36\x9e\x36\xb0\xb5\x60\x2e\x52\x8d\xfb\x31\xc1\xf0\x26\x55\x55\x53\xac\x35\x73\x47\xb2\x6c\x9a\x14\x7e\x48\xbe\x44\x2b\xb2\xa6\x51\x91\xa8\x41\x18\xd6\x18\x6b\x1a\x31\x22\xc6\xe2\x9a\x60\x25\x19\x5c\x1e\x86\x35\x93\x35\x9d\xb5\xa7\xa7\x8e\xbf\x4d\xca\x2b\x6d\xdb\x8f\xbf\x4a\x74\x53\x24\x26\xd9\x22\x46\x09\x23\xb3\x98\xe4\xcc\x3c\xbe\x48\xf1\x13\x7f\x6f\xc5\xdf\xb3\x49\x96\xcb\x5d\xa6\x78\xef\x48\x89\x03\x06\x95\x00\x3b\x19\xb6\xbc\x74\x3f\x73\xff\x7d\x29\xfd\xf0\xbe\x8d\xdd\x2b\x37\xf2\x9d\xdd\x5b\x99\x85\x27\xc7\x32\x7b\xba\x27\x93\x9c\xcc\x47\x00\xb0\x36\x22\xd7\x64\xc3\xe6\x21\x97\x46\xd6\x28\x0d\x90\x38\x2e\x8d\x84\x68\x0f\x73\x7f\xea\xf8\xbb\xf4\x8e\x67\x44\xc4\x76\x69\x16\xf1\x04\x32\x77\x81\x24\xc3\x52\xbb\x86\xd9\x4f\x64\xcf\x06\x37\x07\x47\x40\x25\x14\x0b\x38\x21\xeb\x15\xea\xdd\x7b\x4f\x6c\x73\x31\xc0\x85\x4e\xee\x70\xb7\xd7\x73\xdb\x43\x73\xe7\x86\x4e\xb5\xd7\xb7\x13\x1d\xeb\x07\xf5\x15\xcc\x25\x64\x2d\xd7\x82\x84\x09\xfb\x1d\x41\x45\xd6\x08\x56\x26\xd1\xa4\xe9\x08\xd6\x59\x76\x25\xdb\x8e\x77\xd2\x95\x98\x44\xc4\x77\x21\x41\xc4\x0b\xd1\xb0\x15\x43\xf2\x34\xc2\x4c\x2b\x0d\x33\x4d\x12\x82\xf1\xc1\xcd\x30\x86\x6d\x03\xaa\x90\x09\x54\xe9\x07\x4d\x97\x8e\xfb\xe5\x10\xa8\xbe\xa4\xff\x62\xa2\xbe\x73\x81\xbe\x79\x87\xeb\x1f\xfc\xae\x93\x63\xf4\x95\x99\xf3\xc6\xb7\xf0\x9d\xc0\x06\xd6\x1a\xba\x31\xdb\x8c\x1d\xd7\x18\x5e\x55\x21\xb2\x93\xed\xb5\x59\xb1\x2b\xc9\x6c\xaf\xe6\x30\xd6\xf7\xf4\xf1\xf7\xe9\x46\xd2\xb3\x57\x84\x6c\x62\x92\xb5\x31\x4a\x38\x59\x84\x9f\x89\x22\x1b\x93\x57\x0c\x61\xe3\x40\x63\x8b\xf0\xda\xf1\x93\x00\x10\x06\x92\x14\x10\xd0\x20\x30\x72\x41\x78\x6b\x63\x50\xb5\xc0\x20\x14\xf0\xc9\xec\xfc\xc1\x2a\xa6\xf9\x68\xf7\x1a\x38\xf5\x1d\xfd\xf3\x3d\x2b\xf8\xce\xee\x0b\xd6\x32\x23\xba\x57\x9e\x7e\x8f\x79\x73\x65\xf7\xcb\x54\x06\x76\x1a\xdf\x09\x78\x70\x69\xc6\xab\x1b\x77\x1a\x49\x4e\x99\x22\x08\x1e\x21\xab\x16\x7a\x5d\x14\x50\x44\xa0\x8b\x6e\x32\xab\x01\x36\xcf\xb8\x20\xb9\xa9\x3a\xf5\x63\xe4\x82\x3a\xf9\xe5\x2e\x92\x37\x06\xc0\x74\x90\xef\x04\x0a\x78\x8f\xfe\x9e\xa4\x60\x76\x28\xd5\xde\x8c\xba\x4c\x58\x5d\x2e\x5a\xc4\x70\x92\x22\x86\x71\x04\xb2\x57\x7e\x8f\x1b\xca\x81\x14\x11\xc9\x5d\xfb\xbb\x3a\xbe\x5d\x8c\xbf\xe5\x49\x4e\xc1\xd9\xa5\xb1\xbe\x13\x3c\x62\xba\xf6\xb7\x3d\x77\xfc\x04\xdd\x7d\xb3\x88\x8a\xba\x78\xbc\xfd\xa6\xae\xfd\x6d\xf7\x1c\xbf\x80\xe8\xda\x2c\x26\x2d\xe6\x22\x25\x9c\xb0\x98\x8b\xf2\xb0\x5e\x8a\xb5\x14\x39\x65\xa3\xbc\x64\x81\x0c\x6b\xb2\x14\x39\x8c\x2f\xb2\xc0\xcf\xac\x48\xb2\xc6\xd9\x49\x60\xa1\x42\x7c\x94\x02\x30\xa8\xc8\xb1\x20\x0c\xb2\x41\x93\xc0\x4e\x84\x2d\x90\x79\xc4\xcc\xac\x83\x7e\xfd\xd7\x2f\xbf\x3c\xbc\x96\xeb\x1e\xb1\x69\xbb\xd9\xa9\xee\xe7\x3b\x4f\x4d\xe6\xf6\x9c\x1c\xcb\xb6\xc3\xd2\xfb\x4f\x9e\xe6\x99\x6d\xdf\x9e\xde\x04\x0c\xfd\xf0\x09\xbe\x13\x88\xa4\xdf\x02\xef\x83\x55\xcc\xd8\x92\xd9\x82\x95\x23\x11\xe5\x88\x4e\xec\xb5\x89\x72\x2c\xce\xb4\x26\x67\x95\xf3\x66\xbe\x72\x44\x11\x39\xbb\xf6\xb7\xad\x39\x3e\x81\x7c\x6b\xa6\x79\x44\x0b\x46\x5d\xfb\xdb\x7e\xfa\x35\x47\x54\xc0\x8b\x49\x13\x6f\x56\xc2\x49\x01\x3f\x13\x26\xde\x9c\x67\x6e\x42\x1c\x24\x05\x27\x6f\x22\x9a\xd8\x07\x05\xab\xf1\x39\x73\x6c\x20\x89\xee\x6c\x71\x6a\x74\x50\x6d\x83\x31\x7c\xa5\x40\x43\xfe\x43\xb0\xcb\x64\x1f\xe4\x7c\x7e\xaf\x7e\xf8\x90\x7e\xa1\xc9\xdd\xb2\x9b\xef\x3c\x35\x66\xfa\xb7\x6d\x6c\xcd\xc9\xb1\xdc\x81\xe7\xff\x71\xfa\x0b\xea\xff\xb1\x8f\x58\xc3\xbf\x07\xec\xa0\x04\x8c\x02\x89\x22\x40\x13\x49\xd4\x4b\xf8\xf0\xc1\x2e\x25\x72\x3b\xdc\x69\xe4\x10\xb1\x31\x68\x82\x3b\xad\x95\xc1\xb0\xe6\x76\xe0\x6d\x28\x22\x09\x4a\x49\x92\x35\x20\x64\xf3\xb7\x51\xe2\xe8\x83\x95\x40\x31\x12\xb8\x24\x28\x61\x36\xbf\x0e\x27\x7c\xf8\x4f\xe8\xed\xd4\xf7\x7f\xa4\x9f\xd1\xff\x70\xe8\xb5\x5d\x5b\xbe\x5c\xf7\xd2\xce\x27\xff\xfe\x7d\x26\x08\x4d\x70\xdf\x5f\xf5\xf7\xf4\xaf\xf5\xbf\xe8\x57\x7f\x0e\x1b\xa0\x74\xe8\xa3\x37\xe0\xfc\xff\xea\xfa\xaf\xb7\xf4\x6d\x19\xac\xc2\xad\x33\xf2\x79\x1d\x86\x87\xb5\xaa\x59\x9c\x92\xb2\x14\x11\x0f\x6b\x31\x20\x0b\x38\xa2\x59\xad\x69\x64\x15\x35\x27\x0c\x6b\xbc\xd2\x8f\x29\x23\xab\x88\x94\xae\xa4\xc5\xaa\xe0\x93\x8f\x9f\x6c\x12\x5a\x8a\xf2\x10\x4c\x91\xd4\x03\x1f\x82\x40\x90\x55\xf2\x11\xe1\xd8\xff\xf3\x7b\xfd\x65\xfd\xcd\xfb\x96\x3f\xb9\xea\x83\x4f\x1e\x58\xbf\x8d\xef\x7c\xfd\xb5\x7f\xea\x27\xba\xdf\x64\x3e\x4c\xed\xb9\xf3\x26\xaa\x67\x7d\x17\xd1\xb3\x04\x2a\xc0\x78\x5a\x61\xd4\xdc\x19\x3d\x97\x62\x3d\x57\x92\x15\xcb\xee\x34\x92\x8d\x0a\xa2\x9b\xd4\xf4\x35\xbf\x2c\xc9\x49\xae\xc8\x61\x25\x31\x8e\xdb\x49\xee\x1a\x54\x2a\xf5\x56\x38\x10\x60\x90\x15\xfa\x55\xba\xfe\xe5\x31\xa8\xfc\xf9\xa8\x24\x1a\x9a\xff\xc1\xff\xf6\xd5\xfc\x4b\xba\xff\x7b\xfa\x56\x38\x96\xa1\xea\x7f\x1d\xb6\x7f\x96\x51\xbf\xa1\xff\xf5\xe4\xfe\x77\x81\x87\x8c\x53\x22\x14\x65\x4e\x89\xcb\x9c\x4e\x59\x6d\x64\x07\xac\x78\x07\xdc\xf9\xae\x55\x84\x61\x8d\x53\xd2\x9a\xc7\xd8\x81\x1f\x1d\xff\x30\x6f\x07\x8a\x44\xe4\xea\x4a\x5a\x8b\x5c\x4a\x38\x69\xc3\x4f\x36\x09\xad\x36\x97\xb1\x03\x9a\x58\x24\xc9\x9a\xc9\x1c\x37\xf0\x04\xd0\x6c\xd8\x67\x98\xe2\xc8\x25\x21\xce\x40\x96\x92\xc8\x2b\x41\xb6\xd7\xc6\x5c\x02\xdf\xd0\xb7\xfc\xed\x9d\x0f\xbe\x5a\xf5\xf4\xd3\x3f\xfb\xc5\xbd\x8f\x6d\xe3\x3b\xf5\x47\xf4\xdd\xf3\xba\x57\x30\xd3\xba\x77\x31\xdf\x3e\xf3\xc4\xd2\x1b\x01\x04\xa1\x33\xc7\xb8\x10\x7f\x18\x54\x83\xb9\x20\x11\x34\x32\x49\xa4\xec\x8b\x91\x11\x44\x35\x11\x64\x3b\xa2\xf9\xdd\xa4\x0b\xc3\x04\xc3\x5a\xa5\x2b\xad\xd5\xe2\x9d\xb1\x49\x72\xc2\xca\x06\xe3\x24\x7c\x4f\x5a\x44\x4f\x69\xb5\x17\x47\xf0\xa8\x0c\x7b\x8b\x20\xf5\x6c\x1e\x29\x09\x6d\x4a\x25\xfe\x89\x28\x23\x39\x3f\x8f\x1a\xca\x64\xd3\x28\x34\x32\xb9\x5d\x1e\x6f\x39\x83\x63\x8f\xaa\xd0\xb3\x2f\x6e\xdf\x3f\x67\xc3\xe3\x4b\xee\xfc\xf4\x81\xb7\x77\x8f\xbe\xe8\xe9\xcb\x57\xff\xf0\xca\x7b\x37\xcc\x1d\xa2\xff\xe9\x0c\xf8\x65\x63\x6a\xf2\xc6\x55\xe3\x6e\x9b\x78\xed\xf3\x4b\x56\x1e\x5c\x38\x79\x7b\xf5\xa0\xb5\x1d\x57\xce\x1d\x77\xcd\x0d\x77\x5e\xf5\xc1\xff\xe2\xfb\xec\x65\x23\xe6\x12\xc0\x58\x90\x30\x01\xd2\xf1\x42\xf7\x09\xb0\x69\x8d\x13\xa2\xb4\xeb\xc5\x74\x84\x1c\x0c\x4b\xd6\x65\xef\x23\xdb\x62\x12\x91\xd0\x85\x78\x8c\x42\x59\x8d\x13\xf2\x5a\x34\x84\x00\x0c\xc2\x97\x83\xec\x27\x95\xfa\x2d\xfa\xb1\x57\xa0\xc2\xbb\x76\xee\x3c\x79\x8c\x77\x01\x08\x76\x9e\x39\xc6\xaf\xe6\x3b\x81\x07\x2c\x03\x09\x17\xa0\x30\x93\xe6\x38\x9d\x22\xbe\x42\xbd\xc4\x24\xcc\xd6\x34\x32\x8b\x1a\x8b\x4d\xc2\x9a\xc6\x50\x1c\x9f\x4f\xd1\x9a\xd6\x7c\xc6\x32\x1e\x3a\x7e\x23\xf5\x1d\x4e\x11\x39\xba\xf0\x6d\x2a\x75\x01\xcd\x21\x61\xef\x8b\x9f\xc4\x0b\x38\x39\x49\xd6\x8a\x5c\x71\xe2\x97\x89\xa6\x07\x37\x2b\x43\x62\x8a\xca\x3a\xa0\x9b\x96\x77\x15\x95\x65\xb8\x60\x55\xed\x4e\xdf\xcf\x3a\x5f\xb3\x38\x1e\x5e\xff\xdc\xab\xe1\xc3\x9d\xef\x0d\xd5\x7f\xff\xf7\x2f\x3e\x85\xab\xc7\xdf\xce\x2e\x39\x7d\x5f\xf5\x2d\xd5\xb7\xdd\xfb\xc2\x5b\x6c\xe7\xe9\x0b\xf5\x7f\x9c\xfa\x0d\x80\xe0\x00\x00\x7c\x88\xe0\x8a\xab\x40\xc2\x86\xb1\x24\xc0\x32\x40\x4b\x0e\x52\xc0\x1c\x8e\xe8\x9a\x70\x62\x4f\xc6\x96\x6d\x5d\x0e\xec\x98\x99\x2e\x80\x98\x26\xa8\x31\xb6\xcc\x75\x0d\x6c\xc6\x1d\xa2\xa8\x8a\xc7\x2d\xa8\xad\x18\xe2\x04\x0f\xec\x9b\xa6\x40\x2e\x7e\x03\xfc\xe4\xf0\xe9\x6f\x0e\xf1\x9d\xa7\xe7\xbc\xd8\x51\xf7\xc0\xcf\xd9\x6d\x27\xc7\xe2\x3d\xfc\x04\x00\xe1\x21\xbe\x13\x94\x81\xdb\x40\xa2\x0c\xef\xa1\x4b\xa5\x4b\xb1\xc8\x78\x29\xe5\x99\xa5\xe0\xdf\xc9\x92\x40\xd9\x4e\x02\x65\xd6\x8e\xbf\x22\x97\xb5\xc3\x83\xef\x6d\x64\xc5\x3f\xf5\x79\xd2\xc8\x17\xd1\xac\x9e\x34\x69\x4b\x60\xcb\x24\x59\xe3\x4d\xf1\x38\xf2\x49\x9a\xa5\x14\x2b\x12\x94\x49\x72\x82\x77\xf8\x48\xb6\x5f\x51\x15\xaf\x4b\x50\xe5\x18\xa4\x6b\x96\xc9\x9a\xd9\xda\x96\xa0\x03\xc2\xe0\x27\xa9\x32\xc6\x6a\x6a\x6f\x85\x9b\xf6\xd7\x5b\xa1\x69\x5a\x08\xae\x7a\xa3\x7b\xc1\xab\x8d\x66\x93\x72\x99\xde\x7c\x80\xef\x3c\xbd\x66\xf2\xfc\xed\xd0\xba\x88\x9d\x76\x7a\xf7\xd3\xeb\x26\x41\x6e\x3a\x7b\xdb\xc9\xb1\xec\xde\x07\x1e\xbb\xf0\x99\xd3\x5e\x8c\x6d\xb7\x02\xc0\x7d\x4a\xee\x93\x5a\xe3\x36\x37\xaa\x33\x88\x57\x33\x98\x16\x68\x0c\xf6\x74\x9c\x15\xaf\x28\x68\x81\xaa\x42\xe0\x15\x0b\x17\x32\xff\xa1\x9f\x7e\xe5\x2d\x98\x7c\xa7\xfb\x23\xe8\x3e\xf8\x81\x5e\xc3\x9a\x18\xd4\xfd\x01\x13\xe9\x1e\xd3\xcd\x30\xcb\xbb\xd7\x12\xbf\x7e\x00\x00\xee\x7d\xbe\x13\x98\xc1\x4a\x90\x10\xf0\xef\x30\x19\x3a\x84\x2c\xd6\xa1\x85\x14\xb3\x4c\x4a\x3a\x09\x4d\x82\x39\xac\x01\x6b\x9a\x24\x0f\xad\x69\xcd\x6a\x58\xe3\xde\xaf\x65\x6a\x8d\x04\xc1\x52\x34\xbb\xff\xe0\xab\x7f\x1b\x8a\xbf\xd5\x04\xb3\x19\xef\xbc\x39\xbb\xf3\x09\x86\x04\x6a\xd0\xf8\xd3\x80\xd9\x8a\x4a\xba\x34\x82\xca\x81\x97\xf6\xc2\x4f\xdf\xef\x5e\x7f\xeb\x2b\xcb\xf8\xce\xee\x20\x73\xf4\xf4\x82\xee\xcf\x98\x1a\xac\x8f\x63\x00\x70\x5b\x49\xfc\xd8\x94\xb9\x5d\x33\x1e\x82\xa5\x51\x23\x0e\x17\x81\x26\xd0\x72\xa0\xc6\xb1\xe4\x1a\x1c\xdc\x1c\x8c\xd1\x62\x41\x40\x70\x95\xb2\x1b\xbb\xef\x0c\xb2\xb3\x4a\x4e\x2f\x66\xf6\x06\x36\x70\xf7\xed\xda\x74\x6a\xd5\x2e\x5a\xdf\xfd\x52\x3f\xc0\x7c\x43\xee\x84\x71\xc0\x88\x4b\x85\x34\xa9\x5e\xab\xf9\x69\x52\x22\x74\x26\xb8\xc9\x46\xcd\xbc\x83\x46\xcd\x0e\x12\xe0\x73\x7c\x2e\x9e\x61\x61\x40\x08\x42\x55\x90\xe1\x5d\xf0\xe1\xc0\x67\xfa\xcf\xff\x10\xd0\x0f\x98\x4e\x6e\x3e\xd9\x68\xe4\x55\x8f\x02\xc0\x4c\x25\x75\xe5\x11\x20\xc1\x02\x02\x6d\xc9\x1e\x20\xa8\x1a\x45\x6f\x0d\x3a\x88\xc9\xe2\x4b\x81\x71\xa4\x71\xd0\x45\xce\x56\xe2\x9b\x6d\x78\x19\x2c\x34\x2e\x20\x55\x09\x1e\xdd\xf5\xf1\x2e\xa3\xfc\x0c\xe0\x99\x9b\xf5\x03\x4c\x07\x91\xe9\x6a\x40\x62\x22\x64\x52\x89\x58\x6c\x34\xaf\x4d\x80\x89\xf6\x10\x2e\x83\xd6\x98\x26\x64\x6a\xc2\xe1\x9e\xe0\x38\x81\x4c\xa2\xc6\x62\xe1\x18\xd6\x24\xe4\x09\x17\x53\x61\x30\x16\x80\x9b\xcb\xff\x00\x87\x7d\x56\x09\x1f\xd6\xef\xd3\x0f\x6c\xe1\x7f\xbb\xf9\x84\x89\xc6\x20\x4c\x88\x0b\xf1\x07\x81\x09\x5c\x0e\x72\xb0\x5d\xa0\xa9\x37\x7b\x1a\x03\x45\xfc\x2b\xdf\x18\xf2\xd7\xa9\xc6\xaf\xe4\x10\xdb\xe5\xd0\x78\xe1\x04\x87\xb8\x2e\x26\xc1\x12\x55\x66\x0b\xcb\xc4\x56\xc8\x39\x83\x93\x98\xc9\x8b\xa1\xed\xc9\xb7\x74\x95\x09\xb1\x4f\x9e\x9e\xcb\x7c\xda\x1d\x20\x32\x8f\xd2\x0f\x30\x1b\xce\x8c\x01\x2c\xf0\xd2\x4c\xb7\x29\x8d\xff\xc9\x2b\xd4\xb3\xb1\x80\x70\xa0\x9c\x6d\x2c\xd7\x0f\x3c\xfc\x30\xfe\x3b\x4c\x9c\xfb\x98\x5d\x67\x0a\x00\x33\xa8\x01\xc8\x44\x7a\x17\xec\x5c\x98\xd8\x3f\x0e\x30\xdc\xc4\xdc\x81\xc6\x98\x88\x69\x0d\x6e\x86\x2d\xaa\xc7\xeb\x0e\x36\x41\x26\x7e\xb0\x7e\xee\x2d\x97\x7c\xdf\x64\x73\xaf\xdd\xed\xbf\x64\x3f\x60\x00\x61\x10\xe4\x66\x00\x19\x54\x82\xeb\x8d\x1b\x52\xc4\xe6\xea\x11\xd2\x09\x0b\x04\xe1\x04\x07\x69\x41\x0a\xa2\x00\x0d\x29\x14\x12\x52\xd8\x60\x58\x2b\xb2\xa5\x49\xe5\xc5\xa6\x60\x54\x23\x7a\xca\x48\x27\x8f\x94\xb0\x3b\x8a\x49\xd1\xa5\xcc\x23\xc9\x29\x60\x16\x1c\x76\xa3\xe4\x44\xb3\xb4\x6a\x4c\x65\x83\xb1\x60\xb6\x40\x97\x85\x37\xb3\xd7\x7f\xbb\x75\xfa\xfa\x86\xa2\x8b\xd7\xa5\x37\x14\x9b\x5f\x78\x67\xdd\xd3\xaf\x4c\x9d\x38\xe3\x67\x4b\x6e\xba\xf6\x86\x17\x66\xc3\xd9\xef\xc1\x39\xbf\x9c\x3d\x6d\xcf\xa9\xce\xc3\x9f\xfe\x7c\xef\xa2\x5b\x52\x30\xb0\x75\xf6\xf2\xe7\xf4\x3f\x60\x3c\x13\x3f\x73\x8c\x1b\x6e\x72\x01\x0f\x08\x82\x29\x46\xd6\x40\xc2\x72\x14\x0b\xe9\x84\x15\x8b\x50\x89\x45\xa8\xce\xc4\x60\xd8\x52\xca\x21\xad\x9a\xd5\x60\x43\x85\x92\x9c\x34\x09\x52\x31\x16\xa1\x5c\xd2\xac\x95\x58\x80\xca\x62\x49\x4e\x09\x76\x97\x9b\x96\x8d\x70\x48\xe8\x80\x42\x8f\x12\x63\x28\x28\x64\x31\x1a\x96\x21\x0e\xc7\xa6\xae\x94\xa3\x82\x79\xee\x4f\xaf\x7d\xe4\xa9\x07\xfe\xf1\xc4\xf5\x5b\x6a\xad\x23\xd7\xde\x38\x77\xf6\xee\xd9\x7b\xaf\x3f\xb8\xc8\xe4\xd2\x37\x5e\xdb\xe5\xb8\x6b\xce\xa1\xc4\xfb\xfa\x0f\xdf\x9d\x3d\x75\x37\x9c\x31\x7f\xe9\x2e\x18\xfc\xd1\xef\x7f\xa6\x7f\x4e\xec\x70\xf6\x99\x63\x2c\xe2\x66\x00\x1f\x18\x0e\x12\x9e\x6c\x17\x06\x16\xc2\x82\x85\xf0\xd3\x9c\xa2\x92\xd6\x8a\xf1\x3e\x8b\x1e\x49\x46\x2e\x52\xdc\x05\x82\x42\x32\x8b\xf4\x2a\x51\x86\x64\x33\x8b\x26\xc6\x70\xa3\x6e\xbc\xe6\xd9\x9b\x21\xf7\xec\xe6\x95\x6a\xc7\xfc\x5b\xf6\xb5\xaf\x5a\x72\xf9\x3d\x23\xee\x79\xf2\x8d\x23\x70\xcd\x61\x38\xe1\xb5\x96\xad\x43\x9e\xd0\xbf\x7d\x6a\xe5\xba\xba\xd2\xc7\x2f\x3e\x42\xb0\x22\xb6\x91\xb7\x4d\x2e\xe0\x02\x01\x70\x23\x48\xd8\xb1\x6e\x65\xbc\x2c\x6f\x66\x59\xe5\x46\xae\x17\x1c\xd1\xdc\x4a\x1a\xb9\x45\x7c\xdd\x6b\x36\x3b\x89\xd5\xad\xd8\x52\x24\x92\xee\xd5\xec\x6e\x6c\x29\xb2\xb7\x1c\xab\xd9\x26\x25\x1c\xce\x12\xbc\x60\x2b\x5e\x30\xd0\xca\xbd\xd8\x5e\x04\x93\xd3\x91\x67\x2f\x5e\xb5\x95\x84\x43\xb1\xa0\x51\x9d\xcc\x37\x98\x87\xff\xf9\xf8\x6b\x93\x8b\x3c\xde\x2b\x92\x7a\xe7\x16\xaf\x79\xe6\xde\xeb\x1f\x7c\xea\x95\xbd\xd3\xbb\x6e\x9d\x7f\xc3\x9c\xdd\x73\xe0\xec\x0f\x60\xfb\x9b\x07\x7e\x3a\x07\xce\x3d\x71\xec\xf0\xb2\xf9\x6f\xa0\xa3\xaf\xc2\x92\x47\x6f\x5a\xf2\xac\xfe\x7f\xa9\x5c\xec\x41\xa2\xe7\x2a\xb0\xc0\xd0\xb4\x33\x23\x52\xa5\x90\x4e\x59\xfd\x1e\x2e\x53\x6e\x0c\xe6\xa7\x1f\x70\xc8\x24\x88\x69\x52\x0b\x29\xb3\x49\x72\x8a\x2b\x72\x7a\xfc\x58\x26\x41\xd2\x64\x05\x9b\x8e\x13\xef\x8a\x12\x47\x56\x49\x03\x72\x3c\xae\x55\xfa\x25\xd9\x28\x57\x1b\xe5\x46\x2e\x10\x14\x8c\x4d\xa1\xad\x7f\xd9\x7a\xfc\xec\xcd\x27\x1f\xdf\xbe\x43\x47\xfa\xaf\xaa\xb8\xe5\x77\x8f\x5f\x7f\xd5\x9c\x2d\x93\xf6\xff\xe7\x87\xce\xff\xfa\x6a\xcc\x15\xf3\x3a\xe1\xba\x03\x70\xf2\xa1\xb5\xcb\x3b\xdf\x1b\x77\xf7\xc6\x41\x75\x4f\x36\x05\x3e\x81\xcf\xdc\xb6\xa8\x65\xd4\x41\x00\xcf\x94\xe8\x2e\xf6\x21\x53\x05\xa8\x00\xbb\x40\xc2\x83\x05\xf1\xf3\x69\x64\x8a\x92\xb3\x8c\xf1\x04\x23\xa4\x91\x1c\xd1\xec\x02\x09\x53\x32\x8d\xc6\x19\x10\xef\xc0\x40\xd1\xda\xa5\x15\x8b\x27\x90\xbb\x8b\xa7\x71\xad\x55\x09\x27\x2d\xf8\x89\x8a\xc5\xa4\xa7\xd8\xad\x84\x93\x7e\xfc\x64\x41\x92\xb7\xba\x8b\x49\x58\xfb\x12\x6f\xb2\x58\xdd\x1e\x7f\x71\x7e\x23\xb0\xc6\x94\x49\x32\xaa\x88\x23\xbf\x44\xc0\x33\xc9\x23\xca\x12\x12\xe3\xc8\x2e\x23\x67\x7c\x70\x33\x4b\xb1\x5d\x70\x04\x43\x91\x33\x96\xde\x09\x55\x21\xc8\x62\x95\x84\xbe\x68\x1b\x32\x7a\xb2\xff\xb3\xd7\x9d\xbf\xf4\x36\x3d\xfb\xf4\xac\xeb\x23\x63\x47\x4c\x99\xe2\xf7\xfd\x6f\xf1\xb1\x2f\xea\x9e\x5d\x33\x7a\xb8\x7e\xd0\x7b\xeb\x72\xae\xe9\x8a\x51\xb3\x7f\xf1\xe3\xd0\xba\xd2\xf6\xa5\xf3\xd7\x9d\x7a\xed\x67\x7b\xdd\x34\xc6\x51\x75\x17\x37\x9f\x9b\x01\xca\x41\x03\x18\x4d\xef\x36\xd2\xb0\xe8\xc5\xd7\x9a\x82\x75\x13\x12\x48\xbb\x2f\x8b\x95\x11\x26\x89\xf1\x0a\x25\xad\x0d\xc2\xa7\xca\xc6\x12\x1c\xaa\x85\x4a\x25\x39\x69\x76\xba\x3d\xd4\x24\x49\xbb\xcb\x08\x26\xbf\x72\x4c\xee\x33\xb2\x5c\xc5\x95\xbb\x07\xd4\x11\xfb\xaf\x58\xb3\xa3\x52\x55\xcc\xd7\x25\xa7\x3f\xf4\xf4\xa3\x5f\x6f\x7d\xfd\x1a\xcb\xc8\x75\x27\x22\xc7\x3f\x78\x73\xcd\x9f\xf6\x4e\x7d\xad\xe3\xdd\x1b\xf6\xcc\x3a\x03\x6a\x07\xaf\x5e\xf7\x9b\x4b\x97\x2e\xfc\x79\xe2\x23\x78\x43\xd7\x6b\x7b\x4e\x2d\xfb\xdd\x07\xa3\x59\xee\x68\x27\x0c\x6c\xfa\xfd\x73\xfa\xef\x01\x04\x71\x00\xb8\x88\xc9\x05\x4a\xc0\xe7\x99\x7a\x4b\x89\xaa\xd2\x5b\xcd\x23\x64\xc3\xfa\x12\x2b\x29\x85\xe7\x65\x3e\x5d\xf4\x82\x4b\x8a\x76\x97\x39\xac\x49\xd6\x34\x92\x22\x04\x9c\x97\x65\x9d\xe7\x21\xda\xb4\x4c\x63\xb7\x12\x91\xa4\x7b\xe8\xb7\x45\x49\xb6\x84\x51\xc2\x49\x8e\x3c\x79\xf2\x34\x91\x67\x31\x7e\x26\x8a\x4b\xf2\x53\x6a\xa6\x38\xe2\xe2\x88\x27\xb9\xb5\x4e\xc8\xb0\xa6\x62\x0a\x2b\xb0\x6d\xa4\x72\xff\x96\xcb\xb5\x09\x71\x4d\x94\x24\x59\xb3\x7a\x48\xd3\x18\x06\x86\x82\x3d\xde\xf7\x92\x15\xd8\xa0\xd2\x4a\x3b\x5e\x05\x16\x5f\xae\x53\x6c\xd5\x92\xf5\xda\x7d\x37\xdc\xbf\xd1\xb3\x31\xb5\x49\xd9\x78\xcd\xae\xbb\x2a\xdb\x4d\x2e\xfd\xe6\xb6\x35\x17\x2f\x5d\xb8\x61\xdd\xd0\x5b\xbb\xdb\x19\x74\x6d\xd3\xc6\x65\x47\x9f\xd4\x43\xc4\x37\x00\xc0\xd4\xf3\x9f\x03\x16\x38\xc0\xb5\x06\x3a\x65\xd5\x04\x84\xc4\xc3\x63\x70\x2a\x58\xd2\xa4\xc6\x06\x48\x8d\x0d\xb1\x39\x2d\x72\x18\x6c\x5b\x8a\xb2\x75\xb7\xb6\x6d\xc7\x5f\xca\xa2\x18\x8d\xc1\x71\x8b\x60\xa3\xd9\x2b\x45\xa5\x35\x71\x5a\xce\x8d\xff\x39\x95\x6e\x1f\xd9\x3a\x63\x74\x24\x1c\xe3\xc6\x9e\xea\xe4\x67\xc6\xc7\x4e\xbb\xf0\x8a\x28\x60\x74\x5d\x77\x31\x21\xfe\x73\x60\x03\x5e\xd0\x01\x12\x3c\x24\x48\x07\x43\x42\x7c\x38\xdd\x11\x4d\xb4\xd0\xca\x11\x7f\x44\x33\x49\x69\x64\xc7\x6b\x90\x8b\x48\x09\xc9\x68\x6a\xfb\x61\xf6\xb0\x72\x5d\x34\xc2\x03\x24\xb6\x83\x99\x08\x0f\x6a\x26\xbb\x24\x6b\xa2\x1b\x6b\x97\xb1\xd2\x1a\x19\x2f\x91\xc8\x0a\x1a\x69\x59\x62\xb3\x30\xb7\x64\x5d\xbf\x60\xf8\xca\x30\x34\x25\xf4\x6f\x6a\x7e\xfc\xfd\xcb\x5b\x99\x49\x23\x5b\xa7\x8d\x8e\x34\xb4\xea\x07\xbd\xef\x72\x1f\x9d\xf2\xa1\x1d\x6e\x21\x66\x88\x01\x20\x88\x01\xc0\xa9\x26\x17\x70\x80\x67\x33\x79\x36\x87\xaa\x26\x04\x08\xc2\x19\x6d\x3a\xac\x24\xd5\x94\x49\xd7\x66\x94\xb8\xef\xeb\x96\x7c\xbb\x73\xf4\xb2\x3b\x07\xb1\x3b\xf2\xb4\xe3\x67\xc2\xee\xe8\x99\xbe\x45\x5c\x1c\xa4\x20\x63\x67\x39\x6a\x61\x09\xfa\x89\xc8\x0d\x1d\x99\x50\x88\x91\x90\x2d\x4e\x21\xb6\xc6\x67\xd2\x6b\x56\x28\xa8\x34\xec\x10\xd8\x18\x1c\xdb\x39\xe5\xfa\x26\x8e\x31\x7f\xa8\xd7\xc3\x9a\xb7\xff\x67\xcb\x55\x26\x97\x3e\x57\x1f\xbd\x8e\x51\xf4\xfa\xee\xf5\x0c\xb3\x54\xef\xa0\xb8\x37\x06\x00\x13\x33\xb9\x00\x8b\xb1\xa1\x61\x41\x19\xbc\xdb\xd3\x64\x32\x78\x37\x53\xac\xca\x08\x49\x0a\xb4\x8c\x06\x99\x2c\x36\x54\xa1\x0a\x63\x70\x5c\x4a\xdf\x67\x72\x9d\x38\x46\x7f\x4f\x1c\x00\xd3\x7a\x6e\x06\x08\x83\xdf\x1b\xb9\x5d\x97\xbb\x32\x40\x72\xbb\xf8\xd6\x32\x63\x5b\x71\xa8\x5a\xad\x90\x46\x25\x51\x88\x06\xd1\x22\xbd\x95\x14\xe9\xc9\x02\xec\xe4\xe4\x07\x60\x58\xab\xb4\xa6\x51\xa5\x88\x03\x71\x7c\xf4\x93\x2e\xc9\x67\x0e\x6b\x6e\x2b\xb1\x30\x97\x35\xad\x35\x1a\xeb\xfc\xe1\xf1\xd7\xa9\x35\x05\x44\x54\xd5\x85\x2a\x45\x54\xd1\xb5\xbf\xed\xf3\xbf\x97\xd2\x6a\x91\x88\x3c\x5d\xc8\x25\x22\xa5\x0b\x24\x15\x4f\x45\x15\xad\x3c\x64\x3e\x65\x0f\x34\xe9\x0e\xd1\x2a\x03\x92\xac\x99\x6b\x69\xcb\x7b\x91\x2d\x1e\x47\x2e\x59\x73\x94\x60\x23\xac\x05\x92\x9c\x62\xb9\x22\x9b\x44\xb1\x94\xa2\x0a\x6a\x1b\x43\xf0\x60\x6b\xfe\x49\xaf\xa5\x47\x3d\xff\xd4\xff\x79\xb3\xc7\x3a\x6a\xce\xd2\x51\x8b\x57\xd8\xcc\xbb\x3f\xb8\xe7\x41\xcf\x23\x9d\x5b\xe4\x91\x63\xae\x7c\x7c\x59\xf9\x82\xd4\xa3\xf2\x9a\x89\x4f\x2e\xab\x6c\xe7\xc6\x1e\x9e\x3a\x51\x5d\xdd\xf1\xf7\x87\xee\x9b\x32\x0d\x5f\x01\x33\x9a\xdb\xc6\x76\x7c\xb8\x41\x17\x19\x34\xa3\x7e\xe3\xed\x9f\x3e\x81\x6f\x03\x90\xb9\x4f\xb9\x19\xa0\x18\x6c\x33\xec\xd6\xe1\x54\xf3\x14\xac\xb9\x05\xda\xc1\x09\x8e\x68\xc5\x56\xd2\x75\x95\xa7\x5a\x19\xc3\x19\x6b\x3a\xe9\x28\x92\xcd\x61\xcd\x69\x4d\x23\x67\x04\xdb\xb9\x56\x4a\xf5\x39\x82\xf9\xfb\x3b\xd9\x8c\x87\x48\x8c\xdb\xde\x05\x34\xbb\x88\x4f\x27\x7e\xf6\x52\x99\xc3\x89\x55\x46\xce\xa9\x1b\x48\x72\x82\xe5\x8a\x48\xc8\x9e\x53\x50\x6f\xd5\x10\x7d\x8c\xbc\x71\xe5\xe8\xd5\x9b\xf1\x15\xe8\x1e\x3d\x6e\xf2\x8f\xef\x26\x0a\x98\x3c\x59\x5d\xbf\xfa\xca\xb9\x58\xfa\x39\x0d\x23\xae\xc8\xca\x8c\xb1\xce\x57\x5c\x80\x9b\xd2\x33\x37\x9c\xc1\x3a\xbe\x9c\x13\x31\x0e\x2c\xc9\x0d\x2b\x03\xe6\x86\xb3\x73\x0b\x05\x70\xfc\x96\x7f\x3e\xf9\xfa\x27\x1b\xbf\xfd\x61\xd7\x7f\xbd\xb4\x62\x49\xfb\x8f\xaf\xbb\x63\xde\xc2\x3d\xd3\xe0\xd6\x2e\x38\x21\xf1\xf9\x9b\xaf\xe9\xc9\x7d\x7f\x7c\xf5\x9e\x07\x37\x40\xd3\x4f\x3b\x1e\xda\xa2\x9f\x02\x80\x39\xf3\x5b\xdd\xc5\x0d\xe7\xa6\x11\x8c\x79\x0b\x48\x38\x00\x5d\x16\xdd\x14\xc1\xc0\x98\x08\x44\x32\x30\xd3\x25\xa5\x91\xab\xc7\xbe\x94\xc2\xb0\x66\xb5\x52\x98\x09\x5d\x92\x8c\x51\x06\x23\x25\x58\xce\x8d\x11\x66\xa9\x9c\x14\x1c\xbe\x72\x92\x76\x2d\xf7\x61\xc4\x66\x15\x25\x96\x58\x22\x0b\xd5\x1e\x90\x3e\x14\x34\x09\x6c\x0f\x4c\xdf\x08\x27\x6c\xf6\x99\xaf\x4f\x4e\x7b\x64\xdb\xfa\xbf\x3d\xde\x75\xad\x55\x2c\x6a\x3f\x44\x11\xfd\xf4\xd7\x3b\x74\x97\xa9\xf5\xbd\xdb\x17\xbc\xf3\xe2\x87\xfa\x53\x87\x0e\xac\x6b\xd6\x6b\xd9\xb1\x06\xa2\xef\xa4\x38\x53\x77\x91\x18\xcb\x0d\xaa\xc0\x75\x20\xa1\x64\x64\xcb\x85\x57\x15\x42\x1a\xd9\x22\x19\x90\xe9\x51\xd2\xc8\x63\x44\x58\x12\x05\x99\x36\x8f\x24\x6b\x8a\x2f\x8e\xc3\xab\x24\xe7\x14\x2b\x88\x20\x15\x3e\x1a\x5f\x89\xce\xde\xf1\x15\xe9\x62\x2e\x0c\x98\x9f\x9c\xbe\xbe\xae\x68\xe4\x5a\x7d\x6f\x62\x8e\x2f\x88\xc1\xc9\xfa\x1d\xaf\xec\x9d\xfa\xea\xed\x0b\x66\xce\xda\x3d\x0f\xce\x7e\x1f\xce\x7d\x7b\xf6\xb4\x3d\x27\x7e\x01\x7f\xbb\x60\xc5\xd2\x85\x3f\xdf\x7b\x34\x01\x2b\xb7\xce\x5b\xb6\x53\x3f\x6a\x9c\x1d\x76\x11\x89\x17\xc7\x65\xfa\xca\xb1\x00\x76\x53\x9a\x1e\x1d\x3b\x9b\x46\x45\x51\xd2\x41\x06\x8e\x68\xb2\x95\x64\xc0\x8d\x5d\x22\x78\x24\x6b\xf8\x40\xb3\x03\xe3\x63\x9e\xb1\x13\x08\x98\x35\xf2\xcb\x67\xcc\x1f\x31\xba\x39\x34\xb4\x79\xea\x8e\xa5\xc5\x0b\xb9\xb1\x87\x67\x4e\x6c\x74\xec\xb4\x2d\xfd\xcd\x4a\xdd\x18\xba\xb6\x9e\x39\xc6\x8e\xe3\x66\xe4\xe5\x7b\x39\x21\x9d\x10\xb3\xd0\xa8\x86\x74\x09\xfa\xad\xd9\xa9\xbb\x4a\xab\x91\xef\xb5\x4b\x72\xa2\x88\x23\xf9\x5e\x41\x4a\x5a\x7b\xe6\x7b\xb9\xbc\x7c\xaf\xbd\x57\xbe\x37\xd3\xf1\x4c\x12\xbe\xad\x7d\xf2\xbd\xa6\x60\x95\xf5\xe2\xa7\xc6\xdf\x79\xf7\xa5\x1d\xab\x6f\xfc\xe5\x73\x7b\x76\x5e\xd0\x72\xff\xb5\x53\x16\x5c\x7e\xd3\xe2\xab\x1b\x3f\x3d\x9c\x6a\x7e\xa6\x6e\xf0\xf5\xe3\x63\xdf\xbb\x78\xcc\x86\x19\x0f\xff\x74\xdc\x06\x7f\xf8\x3f\x46\xc6\xc6\x5f\x38\xf2\x3f\x66\xb6\x3d\x95\xa0\x32\x4d\x3d\x73\x8c\x49\xf3\xa3\x40\x31\x58\x6d\xe4\x5e\x1d\x42\x9a\xc0\x04\xcd\xcc\xa7\x51\x71\x34\xc1\x9b\xad\xe1\xe4\x45\x3c\x19\x8e\x28\x89\x20\x2f\xc9\xcd\x67\x2e\xa0\xb6\xed\xc7\xf7\xd3\x59\xc1\x26\x07\xf2\x77\xf1\x9a\x59\x3a\xe1\x40\x96\x2e\xa0\x59\x48\xa1\xdf\x6c\xa1\x28\x9d\xdc\x43\xa4\xba\xcf\xc4\x81\xe6\xc0\x47\x46\x8a\x23\xb3\xa4\x89\xde\x78\x1c\xf1\x34\x77\xa0\x8c\x60\x54\x21\x20\x04\x58\x93\xd1\x9a\x62\x00\xdf\x98\x32\x55\x7c\x65\xd5\xc2\x18\x74\x95\xea\x7f\x59\x25\x47\x87\xb5\xfd\x47\xe9\x82\xd0\x3d\xdf\x97\x57\xb2\x07\xaf\xba\xf2\x8f\x27\xd7\x75\x3f\x77\x55\xfd\xe0\x8b\x4b\x1e\x74\x78\xee\x58\x76\xd1\x44\x66\x12\x80\x60\x31\xc9\x35\x8c\x05\x3e\x1c\x6d\xe1\xe0\x9c\x86\x5c\x16\x21\x9d\x60\xa9\x5f\xcb\xc4\xb6\x82\x35\x9d\x64\x05\x60\xa6\x59\x65\x41\x24\xe3\xa3\xa2\x9d\x94\xeb\x1c\x30\xac\x39\x25\x12\xfb\x92\xac\x99\x66\xf1\xc4\x0d\x2c\x49\x23\x2f\xd6\x22\xc9\x09\x80\x3f\x93\x0e\xbb\x98\xa2\x66\xda\xc2\xf0\xc7\x4c\x1c\xb9\xd8\xb3\xb1\x73\x8b\xbc\xe1\x9a\x1f\xdf\x53\xd9\x9e\x48\x6f\xf1\x5a\xa7\x76\xce\xb9\xe7\xd1\xd3\x17\xdd\xca\xec\xe8\xbe\x72\xea\xe0\xf5\xb7\x7f\xf6\x04\xfc\xf8\x54\xe7\xe1\xdb\x17\x6c\x20\x31\x39\x00\x5c\x05\x37\x16\xd8\xc0\xed\x99\x3c\x32\x1c\x20\x8f\x7c\xd5\x89\x5d\xbd\xf2\xc8\x5c\x57\x92\x81\x9c\x12\x4e\xb2\xf8\x99\x60\x20\xd7\xb3\x20\x9d\x60\x08\x84\x81\x49\xc6\x46\x51\x4d\xdf\x64\x73\x39\x74\x1b\xc9\xe6\xd9\xfb\x86\x5b\xec\xc2\xe2\x38\x1c\x79\xb0\x7b\xef\x31\x6e\x6c\xf7\x0f\xa7\x7d\x12\x3a\xbd\x80\x99\x76\xaa\x13\x40\xb0\x14\x00\x93\x97\x1b\x0b\xca\x40\x7b\x5e\xae\x19\xf6\xce\x35\x8b\x24\xd7\x4c\x00\x6e\x99\x87\xe4\x9a\x39\x4f\x1a\x31\x51\x04\x45\xcd\x8b\x23\x07\x07\xcd\x2d\x7b\x31\xc8\xb5\x94\xc6\xe3\xc8\x2e\x69\x56\x77\x36\xb7\xcc\xe5\x72\xcb\x2e\x7c\x78\xa1\xaa\x78\x49\x3a\x1c\x47\xeb\x6c\xa8\x25\xe8\x84\x30\xb8\x14\xc9\x56\x73\xd1\xf7\x46\x41\xf3\xa1\x20\xc7\x98\x87\x2c\xf8\xea\x75\x9d\xfb\xb8\x82\x31\xab\x13\xf4\xcf\x3e\xe4\xc6\x76\x4f\xb8\xf4\xa5\xf2\x43\x8f\x31\xad\xdd\xa9\x6f\x87\x35\x6e\xff\x07\x53\x72\xaa\x93\x99\xb8\xe1\xd5\x15\xaf\x76\x3f\x09\x00\x3c\x93\x02\x80\x73\x71\x63\x7b\xe5\x95\xe1\x00\x79\x65\xc8\x92\xf4\xac\x12\x64\xe1\x38\xf8\xc9\x5f\x3a\xf7\xc0\x4b\x7e\xad\x0f\x3d\xfd\xd2\x7e\x7d\x2f\xd3\xc2\xb8\xf5\x85\x70\x6b\xf7\xe7\xdd\xbf\x85\x7b\xf4\xc9\x00\x9e\x19\xa1\xbb\xc8\xbe\xfa\xc0\x74\x40\xfd\x8c\x59\x52\x55\xe4\x21\x58\x9c\x98\xa3\x40\xaa\x1c\xd8\xdc\xc8\xce\x3e\xf8\xcf\x54\x36\x83\x6c\xea\x42\x66\x91\x9c\x2c\x93\x05\x7b\x77\xfc\xa4\xdb\xc6\xe0\xe8\xdf\x47\xd2\x01\x80\x20\x4f\x12\xe8\x8e\xc0\x6b\xc3\xbb\xd8\x06\xb3\xf8\xfb\xe0\x88\x4b\x27\xde\xde\x7a\xd9\x33\xfb\x2e\x2b\x12\x4d\xc5\xf3\xcb\xe1\x88\x83\xdd\x97\x4d\x3d\x70\xdf\xf7\x46\xe8\xfb\xe5\x79\xb3\x57\x71\x53\xbb\x3f\xbb\xe2\xaf\x33\x2e\xf9\x43\x9c\x99\x7a\x52\xdf\xf3\xa0\x9b\xe6\x4a\x3f\x03\x80\xbd\x8f\x1b\x0b\x2c\x60\x50\x26\xbf\xcc\x1b\xde\x9c\xe5\xfb\xe6\x97\x11\x2b\xf5\xca\x2e\x57\xf8\x99\x3d\x7a\x7d\x29\xf3\x64\x59\xf7\x1c\xc6\x5a\xb2\x82\x1d\xb3\xf6\xd1\xd3\xef\xaf\xc5\xb6\xee\xd5\x0f\xb0\x2a\xdf\x09\x6a\xc1\x1f\x00\x9d\xee\xb3\x0a\x69\x54\x1e\xd1\x4a\x85\xb4\xd1\x8d\x4b\xba\x62\x6b\x8e\x68\x2e\x47\x3a\xe1\xaa\xc1\x97\x91\xab\xcc\x12\xc6\x30\xd1\x8f\xed\xa9\xd2\x99\x46\x95\x11\xcd\xef\x24\x8d\xb1\xc6\xa5\xf4\x33\xaa\xb7\x2a\x11\xf1\x5d\x9a\x97\x3d\x81\xec\x5d\xa8\x4a\x4c\x72\x55\xbc\x12\x46\x5e\x31\xe9\xf0\xda\x95\x70\xd2\x83\x9f\xf8\xfb\x20\xfe\x3e\x11\xac\xe2\xf3\xce\x09\x17\x4f\x78\xbc\x64\x8a\xd5\x11\x07\x2f\x71\xbc\xdd\xe1\xf1\x56\x05\x33\x29\x07\xd8\xe7\x1b\x72\xc5\xf9\x6b\x24\x59\x93\x64\x62\xb7\xa5\x92\xac\xb9\x2a\xe3\x71\x04\x25\xf2\xd5\xe0\x66\x25\x16\x6d\x8d\x29\x6d\x70\x18\x14\xaa\x4c\x02\x8e\x3c\xdd\x1e\xb7\xcb\x09\xc9\x7d\xe7\x0e\x56\xb6\x0c\x19\x01\x5b\x5b\x86\x78\xab\x6e\xdf\xe0\x19\x15\x78\x76\x6f\x4d\xc5\xdc\xe9\xae\xcb\x4a\xee\x59\xf0\x84\xdc\xe8\x1c\x33\xb1\x44\xff\xc8\xdd\xec\x80\xfa\x63\xd7\xcc\x87\x17\x3f\x75\xff\x63\x97\x5d\xa3\x1f\x5c\xbe\x42\xe2\xea\x5e\x88\x8f\xf9\xe0\xe2\xb2\x21\x83\xb7\xfe\x21\x7a\xed\x47\x57\x54\x6f\x00\x90\x71\xe9\x32\xb3\x9b\xc4\x10\xc5\x00\xc1\x48\x36\x7c\xb0\xa7\xc9\x3f\x34\xdd\x0b\x25\x55\x62\x5c\x5b\x74\xd9\xcc\xfc\x53\xa7\x7b\x9d\xd2\x0f\x30\x87\xc8\x7e\xfc\x02\x24\x14\xbc\x1f\xb2\x90\x46\xb5\x11\x0d\xd0\x6d\x29\x33\xf6\xc3\x7a\x44\x2b\x71\xa4\x91\x13\xef\x80\xc7\x91\x53\xfd\xf2\xe3\x7e\xaa\x7a\x16\x43\x51\xad\xca\x71\x02\xf9\x70\x3c\x92\xe4\x58\x32\xf1\xc2\x1a\x1a\xf7\x57\xf9\x94\x70\x32\x80\x9f\x09\x8e\xb5\xe7\xe9\xdd\x16\x4f\x04\xaa\x7c\xf8\x93\x3f\x0e\x5e\x62\x39\x9b\xdd\xe7\x0f\x54\xe5\xf4\xde\xfb\x1b\xa2\xf7\x12\x02\x6c\x05\x92\x08\x2e\x37\x3e\x22\x59\x22\x11\xff\xe0\x66\x81\xaa\x3d\xd6\x52\x6b\x68\xb8\x36\x18\x53\x2b\x0d\xcd\xab\xc6\x5e\x84\xe1\xb8\xc5\x73\x95\xcb\x4a\xee\xbe\xf1\x07\x72\xc4\x39\x71\x66\xb9\x1d\x36\xba\x9b\xc5\x0f\x02\xcb\x1e\xf1\x8c\x0c\x3e\xfb\x92\x73\xef\x98\xc9\x70\xc4\xb2\xe5\xb2\xa9\xe1\xb9\xf8\x98\xdf\x0e\xad\x1d\xd2\xfc\xd8\x67\xd1\x6b\x3f\xbe\xda\xb7\x61\xeb\xe4\xf9\xfa\x6b\x3f\xba\x17\xdb\x73\x07\x33\x8e\x6b\x66\xa7\x00\x2f\x78\x1d\x60\xb0\x0e\x44\x55\xc5\x5e\x07\x99\xa3\x49\xb7\xc5\x69\xc6\xf7\xa3\xc6\x0a\x69\x8d\xb3\x45\xa3\x38\xf0\xce\x04\xda\x7f\xb9\xeb\x0d\x62\xb4\xc8\xd5\x84\xcc\x4d\x18\x6f\x72\xc2\x09\x64\x16\x35\x51\x38\xb1\xff\x7f\x7f\x7d\xe8\x52\xd2\xfb\xc1\x89\x49\x9e\x23\xbd\x1f\xf8\x89\x5c\x62\x52\x72\x89\x4a\x38\xa9\xe0\x67\x82\xe7\x7a\xb6\x82\x24\x14\x97\x88\x3f\x49\x71\x90\xe4\x05\x49\xc9\x18\xae\x60\x16\x25\xc5\xd5\x73\xe8\x9a\xf4\x07\xd8\xe3\xc4\xa3\x51\x6f\xdc\x42\x00\x1e\x41\x20\x34\x95\x1b\x22\xd8\xa3\x63\xce\xc6\xd1\x77\x5c\x35\x7e\x72\x53\x6c\xb5\xda\xbe\x71\xf4\x8a\xf1\xe3\xaf\x6e\x6e\x5d\xcd\x8c\x7b\xfa\xa6\x8a\xaa\x80\xf7\x92\xd8\x8e\x5b\x2a\x03\x01\xef\xa5\x80\x39\x73\x4c\x7f\x08\x7e\xc3\xcd\x00\x2c\x70\xe2\x9b\x03\xdf\x78\x29\x7b\x8e\xb0\x81\x3b\x92\xb2\xe6\x08\x1b\xac\xf8\xe6\x87\x0c\xed\xfa\x87\x6a\x8f\x96\x7f\x17\x94\x97\xed\x8d\x4c\xba\x2c\xd2\x7a\xd5\xa5\x6a\x4c\x7f\x88\x2b\x39\xf5\x05\x5f\x3f\x6e\xc6\xd0\xd6\xd1\x33\x5b\x29\x8e\xf9\xe4\xcc\x31\x2e\xcc\x1f\x06\x65\xe0\x53\xca\xa6\x80\xfc\x6a\xa6\xae\x93\xf2\x29\xc5\xbc\x9d\xe0\xe0\xa4\xb5\x98\x37\x87\x53\x9c\x8d\x7c\x41\xca\x58\xd1\x8c\x93\x12\xad\xc4\xe7\x63\x5f\xef\xf7\xa4\x13\xfe\x62\x7c\xd5\xf8\x3d\x96\x30\x86\x73\xa4\x9b\x8f\x16\x40\x89\x9d\xbf\xf7\xf5\x9e\x0c\x47\x02\x57\xcc\x53\xde\x02\xc1\x6f\x52\xc2\x49\x1f\x7e\xee\x6f\x7b\xe5\xeb\xd1\x64\xc7\x08\xe1\x01\xbe\x5d\x4a\x8a\xf3\x6e\x17\x80\x4a\x9a\x60\x92\x13\x7c\x25\x59\x13\xe6\xfd\x34\x89\x6b\xa2\x99\x04\xc5\x27\xc9\xc8\x13\xd7\x6c\xc5\x38\x0c\x72\xd3\x26\x06\x8b\x81\xbc\x33\xc3\xef\xd9\x64\x7b\xcc\x4d\x26\xe0\x9b\xe0\x27\xab\xfe\x7b\x73\x60\x75\xcd\xaa\x69\xea\xe2\x85\xb7\xec\x9b\x77\xef\x92\x25\x5b\x56\xfc\xb8\xfe\xbe\xf0\xfd\x1b\x98\x2b\x5f\x81\x6d\x6f\x7b\x77\xef\x2e\xaa\xdd\xaa\xfe\x40\xff\x66\xc7\xca\x87\x2e\x7d\xa2\x8d\x7b\xeb\xa3\xaa\xf7\x00\x3c\x93\x06\x80\x7b\x9a\x7f\x17\x94\x81\x1f\x1a\x77\x7c\x09\x9b\x46\x30\x9a\x28\x62\x68\x4d\x20\xc5\x9b\x40\x91\x3d\xac\x09\x2e\x95\x90\x4d\x68\x9c\x37\x4a\x54\x97\x55\xc9\xaa\xe3\x6a\xf6\xe8\x9b\xbb\x34\x9f\xf3\x04\x52\x48\xb3\x78\x92\x63\x89\xc9\xe2\x27\xf2\x89\x49\x97\x4f\x51\xc2\x49\x2f\x7e\xb2\x20\xc9\x9a\x15\x5f\xe6\x64\x0b\x66\xc5\xe5\xf5\xf5\x48\xeb\x8a\x26\x49\x46\x0e\x1c\x8b\x20\x3b\x71\x2a\xad\x23\x60\x30\xa6\x2a\xb9\x1c\xae\xc0\x06\x84\x80\xe0\x80\x42\x40\xf0\x96\xbd\xd7\xd2\xf8\x4e\xe9\xbb\x63\x6a\x3e\x4e\xbd\xf4\xc3\xd1\x1b\xef\x5d\xb8\xd2\x3f\x0a\xde\x5c\xa6\x6f\x6e\x74\x4f\xbd\x8a\x79\x3f\xf8\x78\xd3\x57\x1f\xac\x85\x93\x5f\x78\x79\xf2\x23\x57\xde\xd6\xa1\xbf\xb1\xf6\xfd\xb9\xf7\x37\xec\x02\x0c\xd8\x05\xcb\x38\x99\x7b\x08\x94\x80\x10\xb8\x0d\x50\xe7\x56\xc3\x93\xf4\x75\x05\x4f\x27\x80\xfc\x47\x28\x65\x03\x9d\x00\x2a\xf2\xd0\x09\xa0\x52\xbf\x24\x27\xdd\xd0\x5b\x82\x71\x7b\x95\x94\x64\x4c\xa2\xcb\x18\x32\x17\x2c\x76\x27\x8d\x9d\x64\x49\x4e\x3a\x44\x97\x07\xff\xa0\x46\x4a\x5a\xec\xf4\x3f\xe7\xe4\x24\x60\x4c\x66\x1a\x50\xc5\xbc\x18\xdf\xc7\xbc\x02\x8e\xc1\xbd\x42\x08\x47\x87\x42\x28\x86\xf1\xaf\xd7\x95\x9b\x9f\xdb\x35\x73\xd5\xbc\x5b\x6f\xbd\x61\xf5\xec\xd5\xa3\x46\xad\x9a\xb9\x7a\xe6\xd2\xdb\xe6\xac\x9a\xb1\x6a\xd4\xa8\x4b\x1f\xba\x61\xde\x86\x8d\x73\xdb\x1f\xe6\xea\xf1\x8f\x56\xcf\x5c\x7d\xd3\x8d\xb7\xcd\x59\x35\x73\xd5\x25\xa3\x56\xcd\x5c\x35\x73\xe9\xe2\xf6\x0f\xe7\xac\x7f\xe8\x86\x79\xeb\x37\x92\xf3\xb2\x02\x00\xee\x4b\xd2\x73\xd1\x49\xfb\xca\x31\x6e\x13\x18\xd2\x19\x95\x02\xd0\x2d\xd8\xc3\x1a\x83\xef\x2e\xc0\xa7\x35\xc5\x13\x8d\xa6\x38\x1e\x7f\x89\x6c\xaa\xc6\xf1\x69\x8d\x75\xe2\xdd\xf7\x46\x90\x9b\x38\xe6\xa4\xd9\xe5\x36\x93\x3a\x05\x99\x48\x13\x73\x3d\x19\xcf\x1c\xff\x73\x26\xb7\xc3\x92\xdc\x8e\xb3\x0b\xb9\xc5\x24\xe3\x66\xe9\xfd\x25\xba\x9c\xe4\xfe\x72\x52\x26\x11\x0f\xfe\x9e\xdd\xc7\xb0\x4e\x51\xf1\x64\xcd\x40\x73\x99\x25\x5a\xb6\x11\x78\x32\xa6\x4e\x7a\x4a\x62\x81\x98\x4a\x01\x18\x09\x1b\x08\xeb\xc7\x8a\x0a\x58\x1e\xd0\x3f\xad\xf8\xf4\x17\xe8\x79\xf8\xd9\x9b\xdd\x7f\xfd\x63\x99\xfe\x49\x00\xd6\x94\xe9\xbf\xbf\xe0\x99\xa1\xd0\xb4\x6e\xc7\x3a\x16\x74\x07\x99\xa3\xdd\x60\xdd\x8e\x75\xfa\x49\x68\x22\x39\x8b\x3c\x7f\x29\x80\x4a\x80\xf8\x08\x69\x73\x61\x8f\x20\x2e\x4a\x82\x7e\x13\xf9\xc3\x98\x06\x82\xaa\x14\xf4\x43\xe2\x3b\xb7\x6c\x81\x15\xa7\xbf\xe6\xbe\x61\x6d\xa7\xff\x0e\x00\x03\x62\x67\xbe\x61\xff\xc7\x54\x01\xc2\x20\x06\xd6\x80\x44\x03\x89\x12\xf9\x34\xf2\x47\x34\x17\xb6\xa3\xa1\x24\x46\x1c\xe4\x48\x27\xa5\x41\x76\x73\x58\x2b\x75\xa6\xd1\x20\x51\x8b\xc2\xb0\x56\xe5\x48\x27\x43\x55\x51\xac\x46\x27\x51\x63\xc8\x99\xd6\xe2\xd8\xc4\x24\x49\x4e\x59\x8b\x38\x67\x83\x51\xf5\x89\xb4\xc4\xe3\x28\x24\x27\x5d\xfe\x8a\x1a\x62\x60\x5c\x03\x0d\x21\xfd\xd2\x3e\x28\x79\x43\x91\x16\xfc\x1f\xba\xf0\xfd\xd1\x27\x88\x34\xc8\x0d\xe8\xd1\x21\x71\x24\x74\xbb\x4c\x02\xbd\x69\xb3\x13\x78\x21\x07\x8c\x0d\xdd\x7d\xc5\xbd\xeb\xae\xba\x7d\xcd\xd2\x3f\x2f\xfd\x8d\xf6\xca\x83\xb1\x1f\x2c\x9d\x75\xfb\xb8\x3b\xd6\x2d\x5e\x76\xcb\xe2\x3f\xbd\xb7\xef\xa9\x59\x8f\x8e\xbf\x6e\xfe\xca\x2b\xe7\xb7\x3c\x59\x39\x78\xca\xc4\x41\x63\x87\x5e\xf0\xe0\xbc\x77\x16\x5c\x7e\xef\x3d\x3f\x1a\xbd\xba\xed\x7b\x23\x9b\x47\xb7\x5c\xf8\xe0\x75\x33\x9f\x89\x8d\x5d\xfa\xf8\x0b\x6c\x60\xe4\xf4\x8b\x1a\xee\x1c\xd5\x36\x7d\x88\xef\x0e\xac\x6f\x78\x88\xb7\xb1\xc7\xf9\x8f\x80\x15\x78\x40\x0b\xc0\xba\x76\xa9\x29\xd6\x02\xa2\x5c\x18\x39\xa2\xc6\xa7\x4c\xe7\x0f\xef\x4a\x23\x9e\x12\xd6\x48\x2e\x62\x5a\x78\x13\x72\xc9\xe4\x9a\x3c\x5f\x01\x0f\x5d\x10\x9d\x18\x6f\x0c\x35\xc3\x5b\x2f\x6c\x6e\xa8\x1b\x3e\xa8\xa6\x99\x9f\xad\x5e\x32\xb1\x79\xcc\xa0\x86\x21\x17\x37\xd6\x0c\xb9\x74\x10\x00\x2c\x58\x77\xe6\x98\x69\x3e\x7f\x18\x38\x41\x05\x68\x01\xf7\x1b\x15\x1b\x17\x97\xe9\xac\xe3\xd2\x29\xb5\xd1\xc6\xd9\xc3\x9a\xca\xa7\x53\xc1\x3a\x5b\x96\xb1\xa3\x95\x8c\x68\x89\x1e\x20\x71\x61\xec\x2f\x2a\x61\x58\x0b\x3b\x48\x52\xd4\x07\xc3\x29\x33\xf9\x81\x16\x83\x61\xcd\x17\x96\xe4\x97\x6c\x2e\xae\x34\x58\x13\x51\xc9\x3e\x35\xaa\x92\x8c\x06\xc7\x51\x9d\xd4\x69\x16\x7d\x95\xa0\x36\x82\x37\x2a\x28\xa3\x9a\x6c\x09\x95\x0c\x1b\x71\xc1\xaa\x6a\x26\xe6\x92\x39\x3a\xf1\xc0\x90\x09\x23\x3e\x6f\xdf\xc4\x6c\x78\xbc\xee\x1d\x38\xe3\x17\x6f\xc2\xa9\xbf\x7e\x57\x7f\xf6\xbd\xf7\xf5\x9d\x87\x6e\x7e\x1e\x86\x9f\x7f\x01\xd6\xbf\xf8\xa2\xfe\xd1\x0b\xcf\xeb\x47\x5e\x80\x8e\xdf\xbd\x71\xf7\xdd\x6d\x37\x4d\xba\xf3\x7e\x7d\xfa\x1d\x17\xcf\xbe\xe0\xb5\x23\xcc\x27\xf8\x6f\xbd\xa1\xef\xfc\xf5\x2f\xf5\x67\x7f\xf1\x3e\x9c\xfa\x16\xfe\x0f\x7f\x8a\xff\x12\xac\x7b\xfe\x79\xfd\xc3\xe7\x3f\xf8\xb6\x6d\x65\xeb\x73\xdb\xf4\x57\x1b\x57\x97\x7a\xfe\x46\xf3\x7a\xbb\x59\x91\x75\xf1\x6f\x03\x19\x54\x80\xf9\x94\xed\x01\x99\x55\xac\x2b\x24\x46\x34\x37\x97\x69\x46\x4c\x29\x54\x39\x0a\xd9\xb2\x94\x95\x6a\x24\x80\x2f\x4d\x5a\xbc\x77\x93\xf4\x87\x55\x4a\xd8\xec\x7e\x52\xbc\x77\x8b\x92\xac\x15\x59\xe3\x71\x54\x2a\x25\x80\xdd\xd6\xa3\xb0\x4c\x6e\x7a\xa3\x8e\x9f\xcd\x32\x19\x53\x93\x0e\xb8\x7b\xd2\xd6\x99\x4b\x42\xe6\x9a\x69\xeb\x67\x3a\x4c\xea\x0d\xc3\x26\xb4\x2f\x9f\x7d\xe1\xdc\x8b\x63\xf1\x61\xb3\xe2\xec\x37\x77\x7f\x7c\xe7\xbc\xa9\xdd\x73\x96\x5c\x7a\xc1\x5d\x77\xac\x9d\xfe\xe2\xc4\x0b\x2f\x9d\xbe\x93\xc8\x32\x19\x2c\x62\x0f\xb0\x6f\x02\x13\xb0\x93\x09\x41\x2f\x54\x04\xe3\x8f\xc9\x70\xdd\x14\xfd\xe3\xdd\x2b\xf7\xc2\x8e\x99\xfa\x7f\x6f\xbb\x8b\x09\x97\xc0\x55\x53\xf4\x97\xf5\x55\x2d\x70\x73\x19\xdc\x36\x5e\x7f\x4c\xdf\xd9\x92\xe1\x96\x60\xcb\x00\x0f\x06\x67\x26\x07\x33\xac\x12\x9c\x25\x4c\x9a\xb0\x69\x37\x47\x82\x63\xf1\xb7\x1c\xb0\x84\x35\x21\xcb\x1c\x11\x94\x56\xb2\xdb\xb7\x30\x6b\xb7\x76\xa7\xe1\xea\xef\xc6\xef\xc0\xf5\xb0\xe7\x46\xd0\x02\x76\x16\xb2\xe8\x41\x4d\xc4\x8c\x07\xf1\xe9\xc4\xa0\x26\xbc\xa2\x41\x95\x96\x30\xaa\x8f\xa6\xaa\x5a\xc8\x0f\xaa\xfa\xb3\xef\x46\x4f\x1a\x35\x45\x51\xa3\xa8\x35\xc3\xb0\x56\x63\x4b\xa3\x9a\x3e\xd6\xde\xdc\x28\xc9\xfb\x6c\xae\x52\x2e\x5c\x47\xdd\x1c\x6a\x88\x23\x9f\x8c\xea\xe3\x40\x6b\x1a\x24\xc9\x29\xb3\xe8\x03\xe4\x47\x2d\xd2\x39\xd9\x3b\x94\x8c\x19\x45\x25\xc8\xe2\xeb\x36\x4a\xfa\x33\xcf\xc1\xde\xd7\xfd\xef\x4f\x9e\x9a\x31\xf9\xb3\xa7\xdf\xb9\x79\xca\xc1\x99\xb3\xa6\x9c\xd5\xd8\xbb\xb7\xb3\xb7\xde\x73\xef\xf8\x55\x41\x7d\x35\x9c\xa6\xef\x82\x1f\x6d\xbe\xe2\x42\xbc\x1f\xef\x9b\x5c\x9c\xdf\xb4\x23\xd7\x2f\xc3\xa7\xf1\x3f\x79\xfd\x32\x78\x17\xde\x0f\xb0\xf5\x41\x93\xeb\xc1\x07\x89\x5d\xfd\x96\x9d\xc2\x8e\xe1\x0f\x03\x1b\xf0\x81\x2b\x29\xd3\x4a\xca\xc3\x83\x4a\x2e\x8c\xac\x91\x94\x48\x3e\x19\x99\xa7\x94\x9d\xea\xd8\x2e\x6a\x0a\x0c\xa7\x04\x0f\x68\xe7\xc2\x04\x7e\x2a\x84\xe1\x82\xcd\x32\x5c\x08\x94\xe1\x02\x9f\x7f\x72\x5b\x67\x93\xe0\x14\x12\xfc\xf6\xe5\xd5\x93\x36\x5f\xfd\xea\xea\xd5\x2f\x2f\xeb\xf8\xde\x95\x1d\x8b\x27\x4c\x58\xc2\x6d\xb8\xef\x95\xab\x37\x4f\x5a\xdd\xb9\xef\xde\x09\xb7\xde\x3a\x61\x62\x47\x07\x60\xc0\x4a\x00\x08\x17\x0a\xc6\xe3\xb3\x32\x53\x21\x64\xda\x15\x15\x91\x4e\x2e\x64\x89\x26\x38\x9e\x98\xaa\xc3\x82\xc3\x09\x92\xf9\x13\x2c\x14\xaf\x3b\x8e\x60\x2f\x68\xb7\xe3\x58\x26\x61\x77\xe0\x9f\xd9\x8b\x2c\x61\xc4\x44\x13\x0e\x3b\xfe\x37\x07\x67\x09\x23\x10\xc5\x70\x1e\x0c\x6e\x56\xe9\xc8\x6c\x8e\x20\x85\xdd\x7e\xba\x3d\x43\x92\xb2\x79\x73\x0f\x9a\x14\x08\xa6\x31\x63\x99\x93\xfc\xbb\xc0\x03\xc6\x50\x76\xb7\x94\x99\x6a\x0d\x18\x8e\xd3\x4b\x4a\x94\xa2\x8d\x5c\xff\x9a\xc8\x4b\xb2\xe6\x26\xe5\x5c\x97\x91\x75\x30\x4b\x09\xde\x2a\xe2\x9b\xc3\x2e\xa3\x22\x82\x10\x6a\x8c\x5b\x22\xcb\x11\xe1\x84\x01\x61\x9a\x1f\x9a\x7f\x30\x79\x58\xfc\xfa\xf6\x11\xab\xb6\xdd\x74\xcf\xfc\x2d\x1f\xc2\xb5\xc5\xcc\xd8\x5b\xff\x70\xdf\x3d\x97\xa8\x6d\x13\x66\xce\xeb\x98\x31\x6b\xd7\x9d\x89\x95\x34\xae\x58\xca\xc4\xc9\xba\x82\xe0\x7a\x90\xf0\xe0\x75\x49\x74\x5d\x55\x91\x14\xcb\x81\xd1\x5c\x18\x59\x22\x9a\x95\xa3\xfd\x3e\xa6\x23\x5a\x85\x2d\x8d\x1c\x38\x2a\xf6\xdb\x48\xb7\x0f\xd0\xd8\xaa\x0c\x21\x82\x06\x2b\x48\x03\x8a\x56\x52\x1a\x8f\x23\x49\xd2\x14\x7f\x9c\xb4\x2a\xb8\x48\xbc\x45\x77\x34\x8f\xdc\x22\xb3\x6e\x3a\x58\x68\x0a\x56\x2d\x5d\xb9\x64\xfe\x9c\xe7\x67\xf8\xae\x9f\xd1\x31\x32\x3e\x77\x46\x7c\xc9\x8e\xa5\xab\x3f\xb8\x6c\xdc\x2b\x3f\x5e\xc5\x2c\x5e\x33\xe6\xda\xf1\xf7\x2d\xbe\xf2\xb2\x61\x17\x8c\x9a\x33\x65\xf1\x0c\x2d\x66\x96\xda\x2f\xbd\xf7\x31\x00\x19\x91\xfb\x98\x3d\x64\x0a\x00\x0b\xa8\x23\xfc\x33\x9c\xd1\xc3\x65\xcd\x0c\x1b\x5b\xb9\x30\x71\xae\x84\x03\x88\x70\xf5\xc0\x96\x36\x18\x53\xdd\x0e\x28\x30\xa2\xfa\xfd\xc6\xf7\x22\xbf\xb8\x9c\xfb\xb8\x24\xa6\x5d\xea\x8e\xbf\xd9\x02\x00\x24\x35\x94\x0e\x6e\x2c\xf0\x83\x5f\x19\xbc\x57\x24\x79\x2c\x18\x65\x14\x8d\xb1\xa9\x2a\x02\x11\xe4\x57\x33\x4c\x2e\x7e\x91\xe4\xc5\xf3\x5a\x06\x9c\x30\xac\x39\xec\xa4\x06\x64\x83\x61\xcd\x2e\x12\x7e\x97\x7c\xd4\xb8\xbf\x6d\xeb\xf1\x1d\x24\x8c\xf2\x8b\x49\xd6\xcf\xe0\xb0\x81\x3c\x7d\xf8\x99\xf0\xf9\xf3\x4b\xb5\x5e\x9a\xdb\x64\x49\x00\x01\x8d\x3f\x69\x99\xd6\x4f\x62\x29\xc4\x48\x9a\xe0\xca\x94\xc1\x44\x09\x5b\x8f\xe0\xa4\x3f\x82\x12\xf9\x82\xc6\x9e\x7d\x53\xb8\xa1\xa0\xc0\x36\xc2\x09\xa9\x4d\xca\xc6\x49\x3b\xef\x0e\x2e\x40\x7f\xde\xec\xb1\xce\xd8\x3b\x63\x71\xb3\xb9\xfe\x12\xdd\x65\x6a\xed\xbe\x72\x4a\xd3\xa6\xa5\x9f\x6c\x87\x47\x4f\x75\x1e\xbe\xf3\x86\x19\x27\xf5\x9f\x13\xfb\x39\xa4\x9f\xe6\x3a\x4d\x2e\xe0\x04\xe3\x30\xca\x21\x1d\xe2\x66\xe2\x0d\xcc\x76\x0b\x7e\x5a\x2d\x61\x32\x75\x2b\x46\x90\xf5\x48\xca\x42\xaf\x04\x8b\x98\x02\x84\x54\x10\xab\xd0\x42\x9a\xc7\x53\x3c\xbd\x6a\xe9\xe1\x52\xc4\x56\x15\x1f\x2a\xfc\x3f\x7c\x1d\x1c\xfa\xaf\x3f\x31\xcd\xcb\x7e\xbd\xac\x6d\xd2\x91\xf7\x38\x19\x72\xfa\xb7\x7f\x32\x2d\x3f\xb1\x96\x55\xe5\x6f\x0c\x0e\x09\xe6\x32\xb8\x9b\x9d\x76\xfe\xfc\x3f\xf9\x71\xf8\x33\x99\x61\x7f\x26\x91\x23\x00\x82\x67\x26\xea\x2e\xf0\x11\x00\x40\x02\xcd\x20\x61\xc6\xb1\x84\x33\xa2\x31\xf8\x48\xc8\xc4\x03\xda\xec\x69\x7c\xc3\x69\x36\x92\xdc\xb5\x62\xb5\x9b\x19\x63\x32\x98\xf5\x90\x7b\x3d\x14\x53\x0d\x08\x1a\xda\x5b\xd9\xb0\x7b\xf8\xf8\x39\x4b\x86\xdd\xf7\xa3\x07\x62\x35\xfa\x3a\xf3\xcd\x35\x11\x6b\x6a\x69\xed\xb2\x39\xcb\x8a\xa8\x2c\xdf\x30\x63\x99\xc7\x49\x6f\xee\x2d\x79\xbd\x93\x16\xea\x6d\x6d\xb9\x06\xdc\x9d\xc7\x3f\xa2\x45\x71\xae\xc9\x81\x4c\x5d\x9c\xc6\x96\x1a\x43\x46\xb7\xfe\xed\xab\x5c\x3a\xc5\x44\x32\x27\xa6\xfc\xc9\x71\x96\x33\x26\x68\x12\x0c\xf9\x90\x69\xb0\xac\x51\xd9\xa0\x12\x73\xc2\x6f\x60\x70\xd5\xab\x9b\x6e\xba\x60\xca\x8d\xdc\xc9\x03\xa7\xb7\x30\xcc\xa7\xe3\x2e\xa5\xac\xba\xbb\x59\x91\xf9\x8a\x7f\x1b\xd8\x09\x6f\xee\x78\x60\x10\x1a\x71\x94\x13\x07\x15\x45\x34\x89\xcb\x90\x1b\xa5\x1c\x74\xb7\x1d\xa4\x7b\x06\x3b\x00\xbc\xc1\x84\xe2\x28\x57\x06\xf5\x48\x79\x0e\xc0\xa8\x1c\xe6\x51\x91\x91\xa2\xa1\xb2\x7b\xd2\x93\xed\xcb\x56\x5d\xf5\x83\xb9\xb7\x7d\x7f\xf9\xe5\x97\x4c\xbf\xf5\xbe\x59\xb7\xb9\xb9\xb2\x65\x3f\x5f\xf4\xe0\x5d\x77\xbd\xb5\xe8\x91\xfb\x26\x4d\xec\x5c\xf7\xf4\x0b\xd0\x42\x71\x9c\x0b\x2c\x62\x57\x64\xb0\x4f\x0c\xb2\x31\xc5\x0d\x6b\xe8\x1f\x2e\x58\xb2\x7d\xe5\x47\xfa\x23\xb0\x06\x86\x76\xaf\xfc\x42\x5f\xf6\x36\x9c\x0b\x67\xb7\xea\x0b\x2b\xf4\x1b\xc7\xc1\x4b\xe1\x7d\xad\xfa\xc5\x65\xfa\xf7\x29\x17\xe2\xdd\x00\xf0\x33\x48\x7f\xae\x0d\x78\x41\x19\x94\x0c\x9f\xe2\xf6\xa8\x34\xf7\xa2\x41\x93\xaa\xa6\xec\x3e\x40\x98\x58\xfc\xf8\x33\xb9\x3c\x35\x97\x37\x1a\x4d\xf8\x88\xd3\xf0\x39\x2d\x61\x24\xd2\x24\x8c\xf9\x88\x26\xd8\x48\x0d\xc6\x03\xf1\xff\x4d\x2e\xdd\x92\xdd\x4a\x73\x93\x03\x59\xbb\x38\x4d\xc0\x5b\x69\xea\xda\xdf\xf6\xe8\xf1\xf5\x34\xeb\xe0\x11\x51\x49\x17\x8f\xe3\x4c\x31\x6f\x87\xc9\xbc\x98\x55\x09\xe3\x1f\x24\x25\xb7\x48\xa8\x29\xc5\x0c\x35\x65\x89\x12\x4e\xfa\xf1\x33\x61\x31\x5b\xf3\xc7\xc9\x04\xb3\xc5\x5a\x92\x19\x27\x33\x59\xac\xa2\xe4\xf2\xfa\x4b\x7a\x8e\x93\x09\x66\x4a\x7e\xe2\x91\x92\xbc\xdd\x41\xe9\xe4\x7c\x76\x9a\xad\xe0\x29\xe7\x82\x0a\x55\xc8\x66\x8c\x06\x1a\x3c\x3e\x42\x30\x16\x52\xe5\x98\x49\xb8\x9b\x6b\xdb\x79\xea\x8d\x19\x59\x5b\x82\xff\xe9\x85\x9f\x6d\x5a\xbe\xd2\xb3\xba\x7e\x5d\xfd\xa1\xa3\x97\x49\xa5\x13\xf8\xce\x93\x63\x73\x26\x76\xba\xf1\x46\xe6\xe2\xee\xf7\x96\xbf\xf5\xd6\x72\x38\x66\xd8\x90\xe9\x80\x05\x57\x00\xc0\xbf\x6a\xec\x41\x10\x7c\x40\x3b\x26\x11\x50\xb5\x00\x9f\xce\xdb\x83\x62\x37\xde\x83\x54\xb1\x81\x3f\xaa\xf3\x75\x2d\x93\xc6\x42\xe2\xac\xce\xa2\xeb\xde\x4a\xed\xa5\xb5\x24\xd6\x1a\x3d\x36\x26\xf2\xa1\x87\x9a\x64\xa9\x13\xf2\x8c\xdd\x57\x1c\xc0\x18\xb0\x4c\xd6\xaa\x82\xd8\xbe\x03\x86\xc6\xdc\x52\x42\xf6\x96\x61\xf7\x5d\x4c\xaa\x19\x85\x35\x58\xd0\xa3\x5f\xd1\x4b\x8f\xcc\xd5\x85\x5c\x7c\x4f\x55\x9e\x9a\x57\xc8\xe1\x73\xe0\x3a\x00\xf8\xe3\xc4\xdf\x87\x40\x14\x0c\x85\x00\x24\xaa\x09\xa1\x63\xb3\xaa\x26\x6a\x18\x10\xce\x07\x01\xa9\x3a\xb5\xda\x83\x01\xf5\x10\x55\x4d\xd5\x51\xd3\x8e\x44\xa3\xd1\x84\x5a\x87\x4d\x5b\x6d\xb0\x84\x51\x38\x9a\xaa\x62\xf1\x7f\x95\xaa\x22\x70\x21\x65\xb5\x90\xbf\x43\x20\x43\xbc\x0f\x64\x40\x15\x14\x63\x0f\xf6\xa4\xb5\x0b\x8c\x0d\xc9\x9a\x78\xb3\x88\x5a\xbb\x78\x34\x58\x44\xe1\xae\xe4\xa0\xc1\x61\x25\x9c\x8c\xe0\x27\x6a\x16\x93\xd1\xe6\x56\x25\x9c\x1c\x82\x9f\x2c\x40\xad\x4d\x70\x5f\x78\x50\x24\x3a\xa4\x35\x97\x43\x69\xf6\x4b\x72\xa2\xae\x5e\x25\x11\x97\x5a\x27\x61\x68\x7e\x36\x70\x72\x6e\xb0\x44\x81\x2a\xac\xe9\x6d\xdd\xd7\xf5\x8b\x55\xe8\x7e\xc1\xdd\x7d\xac\xbd\x5f\x10\xd3\xfd\x36\xde\xbd\xb7\x7b\x59\x3f\x00\xcc\x99\x6f\xf4\xc5\xcc\x49\x6e\x0a\x28\x06\xb5\xe0\x46\x90\x28\x87\x20\x9c\xaa\xa6\x8c\x37\xbe\x88\x26\x9b\xd3\x06\xa7\x0a\x6d\x9e\x11\x09\xc0\x30\x45\x53\x01\xea\xe2\x04\x3b\x65\x53\x29\x71\x92\x2e\x0d\x56\xf6\xd1\x0c\x4b\xc2\x5d\x5e\x1d\xa7\x04\x0f\x9e\x38\xd0\x64\x9a\x8b\x45\xd5\x52\x02\x98\xdc\xa4\x10\x29\x0c\x69\x8d\x61\x88\xe4\x80\x82\x83\x35\xfa\x9d\xbd\x24\xff\x90\xe7\x2f\xad\xf7\xff\xe8\xae\x89\xde\xcd\xee\x79\x1d\xcd\x53\x47\xd5\xcf\x99\x31\x7c\xdd\xcc\x4b\x0e\xed\xdf\xbd\x9f\x61\x26\x8d\x8c\xc6\xb1\x33\x1d\xb7\xe2\x57\xb7\x5f\x77\xe3\x82\x7b\x9f\x9b\x1a\x1a\xf3\xbd\x69\x17\x4c\x99\x13\x6a\x7c\x68\xee\x33\xdc\x13\x57\x4c\x6f\x51\xbf\x37\x9d\xe4\xb6\x59\xca\xe1\x21\x74\x10\x0e\x0f\x2f\xd8\x7e\x6e\x2c\x1e\xbe\x08\x12\x8f\x68\x92\x3b\x8d\x24\x51\xe3\x60\x98\x10\x7a\xf8\xbf\x13\xa1\x87\x26\x89\x14\x6a\x73\x92\x66\x73\xc7\xe3\x88\x95\x35\x85\x0c\x52\xf5\x47\xf4\xc1\x66\xa6\x01\xfa\x32\x7e\xcc\xa0\xe3\x01\xbd\x89\x3f\xd8\x89\xc6\xb8\x80\x21\xf7\x2c\x43\x6e\x1f\x58\x7d\x6e\x72\xfb\xb3\xec\x25\xc5\xdf\x4d\x58\x96\x23\xf9\xf8\xfe\x85\x53\xb2\x18\xb9\xaf\x74\x71\x03\x34\xf7\x16\x8f\xa9\xc8\x82\x68\x2a\xdf\x68\x43\xbe\x52\x70\xdf\xb9\xc9\x57\x96\x95\xaf\xfc\xbb\xcb\x47\xda\x7c\x06\xda\xbe\xd6\x98\xea\xa9\x80\xee\x60\x6d\xc8\x54\x40\xca\xdd\x5f\x36\xef\xad\x9a\xd9\xb0\x78\xe8\x82\x55\x8b\x0b\x48\xfa\xbb\xab\xa6\x6d\xb8\xa4\x64\xf0\x83\x8b\x2f\xcf\xd9\xf1\x36\x41\x25\xf2\x56\x83\xd4\xb9\xc8\x8b\x02\x11\x4d\x12\xd2\xc8\x1f\x4d\x7a\xa4\x80\x39\x4c\xca\xc2\xce\x28\xe9\xb5\x71\x1e\x49\x55\x53\x00\x55\x9d\xb3\xf0\xda\xef\xa6\x14\xae\x5a\x92\x53\xd0\x26\xb9\x2a\xf0\x45\xc0\x52\x02\xc2\x01\x14\x24\xab\xd1\x72\x06\x9f\x7d\x95\x09\x56\x35\x31\xc1\xaa\x42\x6a\x3a\x14\x4f\x34\x7e\x6f\x74\x5b\x49\x43\x8b\xef\xa6\xd1\xcf\xd5\x8f\x1d\x3d\x32\x10\x8e\x7a\xfa\x2a\x0c\x9a\x82\x0d\x41\x75\x84\x7e\x32\x18\x0e\x5e\x10\x27\x18\x8b\xe8\x6c\xa8\x50\x4f\x74\xe6\x07\x35\x60\xdf\x39\x69\xcd\x1b\x41\x41\x35\x25\xd3\x74\x6a\x59\x14\xa2\x5a\xd2\x70\xee\x72\x91\x46\xb6\x62\x3a\x8a\x4a\xdb\x31\xb0\xd2\x42\xdf\x4d\x69\x2e\x67\xe6\x5a\x40\xb6\xb8\xc6\x16\x4b\xb2\x56\x16\x1c\x50\x6d\x85\x53\xb7\x7d\x35\x77\x53\xdf\x5c\x6e\x6f\xad\xed\xee\x93\xdb\x35\xee\x4b\x06\x48\xc0\x07\xaa\xc1\x61\x43\x63\x76\x87\xaa\xe2\x28\xcb\xa9\x6a\x32\x9b\x46\x4a\x14\x55\x45\x34\x13\x47\xfb\xb6\xd8\x23\x29\x3f\xb5\x25\x3f\xe1\x5e\x36\x02\xb1\xa4\x54\xe1\x70\xd0\xc1\x9d\x3e\x86\xe5\x10\x91\xbb\x0b\xd9\x45\x64\x23\xa8\x33\xe9\x74\x3b\x94\x70\x52\xc1\xcf\xfd\x5d\xb3\x4f\x98\x28\xb9\x36\xfe\xd7\x84\xcb\xed\xc8\x83\x49\x09\x9b\xcb\x4d\x5a\xd5\x6d\x4e\x85\x7c\xca\xf4\x0e\xb0\x54\x8d\x0e\x29\x69\xf2\x94\x56\x11\x3c\x59\x25\x4b\x72\x8a\xb5\x40\xd2\x30\x86\xf5\x98\xa5\x26\x26\x69\x31\xac\x51\x86\xdc\x45\x79\xe9\xa0\xa5\xcc\xb7\x53\x56\xce\x6c\x5f\x71\x71\xec\xf9\xac\x32\xa3\xd6\xca\x71\xc1\x0b\x5a\xd5\x8b\x2e\x52\x07\x5f\xc4\x2f\x6f\xbd\x7b\xd6\x6d\x4b\x66\x8d\x6d\xf7\x9e\xdc\x6a\x28\xf3\xbd\xef\xc7\xc6\x6f\x63\x02\x2d\x17\x5e\xd8\xd2\x72\xe1\x85\x24\x4e\x38\xb3\x0e\x00\x53\x9a\xf0\x2f\x29\xe0\x31\x9a\x4f\xc4\xc8\x32\x4b\x9e\xa3\xb0\x69\x8d\x93\xa3\xd1\x94\x43\xb4\x61\xfb\x93\x54\xcd\xc1\xa6\x91\x3d\x9a\xe2\xcd\xb6\x2c\xa5\x8e\x2b\x92\x9d\x9f\x7f\xe8\xf8\x4d\xa4\x16\x64\x23\xc3\x81\x36\x51\xb3\xf8\xc9\x70\xa0\xec\xef\x4d\xa9\x83\x6c\x62\xd2\x6e\x93\x95\x70\x52\xc2\x4f\xf6\x25\x8e\x37\x5b\x6c\x76\x49\xee\xc9\xfd\x1e\xcc\x63\xd9\x09\x28\x01\x0b\x0c\x28\xc1\x65\xec\x6e\xf6\xe5\xca\xee\xf7\xe7\x30\xf6\x8a\xee\xbf\x2f\x62\x22\xc1\x6e\xff\x4c\x7d\xac\xfe\x39\x5c\x03\x17\x6d\x9a\x94\xa5\xde\xa1\x82\x33\x7b\x0c\x3e\x03\xdd\x65\xf0\x2c\xd5\x83\x15\xb4\x22\x96\xaa\xe4\x40\x39\x17\xce\x12\x2c\xa1\x50\x44\x2b\xe6\xd2\x9a\xe2\x16\x2b\xbb\x22\xd8\x88\x20\x6a\xc8\x50\x2e\x21\x3b\xed\x0a\xad\xb6\xa7\xb5\x30\x0c\x6b\xa5\x76\x49\x4e\xfa\x2a\x2a\x43\xf8\x1e\xa9\x96\x92\x6e\x31\x40\x77\xd4\x5d\x2c\xc9\x89\x8a\x2a\x0c\x2f\x34\x59\xa1\xad\xa3\x64\x9a\xca\x1e\x8f\x0f\xc0\xd0\xa4\xf4\x89\x93\xfb\xe1\x6c\xfa\x63\x8f\xf0\xb9\x20\x83\x53\xf7\x92\xde\x31\x35\x9d\xd1\x5f\x24\x74\x90\x19\xfd\x5b\xcf\xc6\x92\xe4\x26\x45\x2c\x87\x3b\x37\x97\xff\xef\x23\x4b\xca\x0e\x10\xf6\x65\x4d\xd2\x4f\x64\x30\x83\xb1\x85\xc2\x8c\xec\x6c\x61\x6e\xfd\xee\xb3\xb3\x3c\x79\x22\x9a\xf7\xdf\xbe\x70\x36\x0b\x07\xfa\xae\xfc\xf9\x2c\x1c\x30\x56\x6e\x0a\x67\x71\x40\xfe\xda\xfd\x67\x5f\x7b\x71\x24\x9b\x24\xfb\x77\x2a\x3d\xdf\xd1\x17\xd0\xfc\xa3\x3d\x3c\x7d\x4e\x88\x3c\x17\xcf\x1a\x72\xd4\x83\x22\xe0\x01\x55\xd9\x3e\x82\x7e\x24\x41\xae\x08\xaa\x54\x53\x4e\xea\xa3\x8a\xa3\xa4\x21\xd9\x76\x44\x93\x5c\x04\xb1\x7a\x71\x50\xea\x22\x0d\xc9\xdf\x55\x56\xcd\x2b\x65\xaa\x4b\x65\x92\x26\x98\x32\xfc\x2f\x39\xe9\x0b\xbb\xa3\x02\x6a\x78\xb7\x80\x3f\xca\x28\x23\xd5\xcb\x11\x31\x94\x83\xc9\x38\x53\xf3\x07\x60\x61\xca\x1e\x27\x64\x8d\x66\x4f\xd4\x79\xf1\x31\x69\x0e\x1c\x45\x17\xc5\x7b\xf1\x32\x65\xe1\x77\x0f\x82\xa6\x67\xe9\x29\xca\xe7\x69\xca\x1e\x24\x72\xef\xe3\x75\xdf\x61\x9c\xa5\x81\xd8\xa3\xf2\x8e\xd1\x77\x61\x8f\xca\x1d\x9c\x1e\xcb\x94\x8d\x33\x93\xbf\xce\xbc\x63\x63\xac\xf3\x6a\xe3\xdc\x0c\xb4\xce\xbc\x23\xf3\xdd\xd6\x99\x7f\x48\x7a\xac\xf5\x54\xde\xf1\xe8\xb5\xde\x1e\x20\x98\x25\x6b\xbe\x22\x7b\x46\x1e\xe9\x77\xd5\xe7\x79\x3c\xce\xcf\x5a\x24\x1b\xb1\x16\xe4\x95\x90\x95\xa4\x62\x8c\x43\xd1\x43\xda\xc2\x87\xa2\x87\xd8\xaf\xf6\x39\x0e\x3d\x84\xef\x7d\x22\xb0\x9f\x19\x65\xf0\x06\xda\x41\x09\x78\x92\xce\x86\x20\x9b\xaa\x39\xcc\x06\xe1\x87\xd7\x9c\x4e\x01\x58\xc4\xda\xc3\x1a\xe3\x53\x55\x0d\x98\xd3\x9a\xbd\x24\x1a\x25\x33\x23\xca\x91\x0c\x89\x90\x31\x9a\xb6\x3d\x03\x27\xbc\x04\x4e\x38\xa4\x13\xc8\x2b\x6a\xac\x74\x02\xe3\x07\xc6\xc6\x2a\xe1\xa4\x1d\x3f\x91\x43\x4c\xfa\x1c\x5e\x25\x9c\x2c\xc1\x4f\xf6\x25\x86\xb5\xd9\x1d\x5e\x5f\x49\x8f\x56\x23\x2f\x94\x64\x4d\x50\x68\xa7\xa6\xaa\x18\xb4\x83\xf5\xb0\x04\x66\x89\x07\xf1\x8d\x31\xaa\x6a\xeb\xfa\x3c\xf6\x41\xfd\xf1\x35\x13\x33\x04\x84\x37\xc2\x4b\x82\xfa\x6b\xcc\x9a\x1d\xcc\xe6\x2c\x13\x21\xb3\x46\xf7\x53\x32\x42\xdd\xba\x83\xe8\x80\x70\x46\x09\x2a\x10\x41\x2d\xf8\xba\x20\x6b\x14\x0a\x46\x34\x85\x8c\x5d\x25\x7d\x4a\xd0\x4c\x07\x52\xa4\x68\x26\x97\x61\x90\x49\x49\x30\x9c\xaa\xa5\xa8\xb5\x36\x47\x2d\x55\xf7\xff\x1f\x6a\x29\x92\x1c\xd0\x18\x5b\x3c\xae\x99\x6b\x31\x68\x2d\x52\x4a\xc8\xe4\xb5\x45\x42\xa5\xf1\x81\x89\xa7\x60\x81\x30\xaa\x20\x19\x15\x9c\xdc\x4f\x28\xd5\x8b\xa3\xca\x14\xee\x1b\x4b\xb1\x94\xb3\x4a\xe8\x20\xb6\x57\x0d\xa6\x16\x64\xad\xaa\xc9\x67\xad\x2a\x83\x61\xad\xdc\x4d\xde\x30\x92\x21\xb0\xaa\xc5\x5f\x95\x61\x7f\x22\x91\xc1\xb3\x24\xe7\xab\xa4\xc0\xee\x1c\xb9\xac\xb2\xf8\x66\x00\x52\x2b\x38\x9e\x5e\xd1\x67\x21\xb7\xe2\xb2\xb7\x76\x4f\xd9\x6a\xc0\x84\x82\xb2\xd5\x16\x62\xe4\x0a\x19\x53\x57\x29\xae\xa8\xb4\xb2\xc6\x68\x30\x0a\x54\x9d\x07\x3b\x57\xae\x56\x38\x90\x48\x1f\x1b\xd7\xf9\x59\x64\x62\xf3\x6e\xf8\xde\x72\xd5\xf7\x23\x57\x43\x21\xb9\xc2\x85\xe4\x0a\x56\x9f\x97\x5c\xf9\xf7\xfd\x40\xb2\x71\x79\xd7\xff\xd9\xe5\xeb\x81\x99\xa8\x7c\x2a\x91\xaf\x19\x2c\x2d\x20\x1f\x6a\x8a\x90\xe3\x5f\x1b\x4d\x06\xcb\x9b\xcc\x61\xad\x5e\x48\xa3\xd2\x28\x44\xd1\x7c\xb1\x4b\x61\x38\xd5\x4c\xef\x82\xe6\x9c\x12\x54\xac\x84\x66\x49\xee\x2c\x92\x38\x5f\x79\x6d\x3d\x55\x03\x0a\x9d\xbb\x12\x94\x02\x47\x73\x00\x55\x7c\x52\xf0\x7c\x9e\x55\x27\xbd\x4f\x2b\x67\xe8\xa5\x9e\xe8\xa5\x16\x44\xc1\xcd\x85\x34\x53\x1d\x41\x83\xd5\x54\x05\xf5\x91\x0d\xd1\x0c\x7b\x7d\x4e\x25\x5a\xc0\x95\x46\x01\x91\x18\x79\xa3\x2b\x8d\x1a\x45\xcd\x5d\x44\x55\x43\xe8\xeb\x01\x61\x48\x93\x7c\xe7\x75\x80\x0b\x3b\xc6\x81\xec\xe3\x82\x3e\x7e\xf2\x6c\x1a\xe9\xeb\x3a\x01\x04\xbb\x60\x23\x7b\x9c\x5b\x01\x8a\x00\x50\x62\x16\xe8\xb5\x40\xc1\x02\x43\x70\xd7\x7c\xd8\x06\x2f\x9e\xa7\xbf\x06\x2f\xba\x41\x7f\x5d\x7f\x63\x2e\x1c\xc6\xc9\x0b\xf4\x2e\x78\xd1\x3c\xfd\x75\xbd\x6b\x2e\xbc\x48\x7f\x63\x1e\x1c\x4e\xcf\xd3\xd2\x33\xcf\xf3\x9d\x26\x0e\x78\x40\x05\xa8\x03\xb7\x18\x13\x82\x55\x6c\x9a\x34\x7f\x52\x46\xb9\xfa\x08\x62\x8f\x68\x5e\x77\x1a\x3b\x53\x7c\xe1\x39\x5d\xf4\x75\x09\x5e\x56\x92\x35\xe8\x89\xc7\x51\xad\xb4\xcf\x22\xb8\x95\x62\x32\xad\xe6\x94\x35\xab\x0d\x1f\xac\x2a\x25\xd3\xab\x5c\x2a\xed\x83\x36\xd6\xe9\x27\xfd\x3e\x82\xac\x59\x8a\xb0\x5a\x47\xc0\xda\x16\x1a\xdf\xc6\xbc\x42\x39\x74\x63\xf5\x56\x85\x04\xc5\xe5\x85\xd4\xd8\x0c\x3d\x87\x96\xae\x5d\x80\xd5\xf9\xda\xba\xd5\xcb\x36\x0f\x8e\x62\x95\x1e\x5a\xbb\xea\xc6\x10\xf3\xdb\x69\x0f\x3c\xfe\xcd\x03\xab\xa7\xad\x7d\xfc\xab\x35\x15\xd6\xdd\x0f\x7f\x41\xb4\x78\xe3\xce\x19\xa9\x11\xaf\xde\x48\x14\x39\x63\x07\xb3\x62\xd5\x14\x76\xdd\xa4\xb7\xf5\x27\xbb\x7f\x3b\xfa\x1d\x38\xf7\xc8\xcd\x93\x00\x43\x39\xc6\x84\x0e\x22\xf7\xc3\x85\x59\xc6\x2a\xfb\x61\x19\xf3\xc1\x70\x86\xc4\x2d\x43\x38\x16\x38\x1f\xc2\x31\x5f\x86\x70\x4c\x73\xfa\x25\x59\x2b\x29\x3b\x17\xea\xb1\xac\x9b\x28\xcc\x41\xf6\x17\xea\x20\xfa\xe1\x22\x33\x3d\x9d\x8d\x8b\x73\x72\x57\x82\xfb\x0a\xcb\x1d\x38\x0b\xbb\x5a\xd5\xf9\xb2\xab\xa5\x8a\x5c\xde\x12\x3a\xc7\x28\x69\xa5\xe7\x28\x6e\xc6\x87\x14\x94\x97\xd9\x60\x78\x8f\x7e\x04\xe6\x6f\xce\x8b\x0b\xf2\x64\xae\x06\x77\x16\x96\xb9\xe6\x2c\x32\xd7\x9e\xaf\xcc\xc9\x22\x97\x97\x4e\xfc\x9e\x5d\xd4\x7c\xb7\x52\x78\x7b\x9f\xcf\x73\x28\xfd\x8b\xdc\x2b\xbf\x6e\xc8\x5d\x0f\x3c\x20\x00\x1a\x71\xfc\xdd\x57\x72\x54\x11\x41\x61\x35\x55\x4c\xaf\xcc\x9a\x28\x44\x4d\xfd\x68\x02\x47\x18\xa5\xae\x6c\xbb\x7b\x9d\x2b\x8d\xea\x72\xfa\x89\x9c\x8f\x7e\xbc\xe7\xce\xb8\xd7\xcf\xe5\x5a\x58\x4b\x1f\xf7\xb9\x56\xfb\xd3\xd5\x37\xbd\x63\x73\xca\xef\x26\x74\x90\x77\xe9\x17\x66\x78\x53\xfa\x67\x78\x73\xfd\xbf\x60\x78\x2b\xc9\x9d\x81\x3c\xae\xb7\xd7\xb2\x99\xa3\x1c\xe7\x1b\x67\xca\xc7\x48\x34\x7f\x34\x99\xf0\x0e\xba\x33\xfc\x9a\xc8\x96\xab\x0e\x14\xd9\x49\xce\xa5\xc8\x9c\x4e\xb1\x6e\xf2\x91\x35\x93\x24\x58\x5f\x8e\x63\xc4\xd0\xf1\x57\x41\x49\x67\x43\xfb\x0c\xe9\x69\x4f\x96\xe3\xa4\x9d\x3c\xdd\x36\x4a\x54\x5d\x64\x77\x67\xc3\x28\xb7\xdd\x60\x1f\x52\xa1\x2a\xa8\x85\x98\x4f\x3b\x5b\xb6\x7c\xfc\xa9\xfe\x92\xfe\xc6\xea\x51\x73\x56\xff\xe6\xbf\x1e\x7c\x68\x07\xdf\xa9\xbf\xfe\xda\xb7\xfa\x49\xfd\x10\xfc\x38\xf9\xdc\x8a\x1b\x49\x5f\x11\xd0\x5d\xdc\x7c\x53\x05\x18\x0e\x7e\x46\x67\x7a\xb4\x4a\x21\x8d\x86\x51\xea\x92\x21\x11\x4a\x50\xd5\x16\x41\xf5\x47\x34\x59\x24\xc3\xdf\x41\xec\xa4\xac\xd8\x6f\x21\x5b\xe5\x11\x49\x6b\x16\xd3\xa8\x39\xa2\xd9\xc4\xb4\x36\x22\x9b\x48\x7a\x21\xcb\x67\x62\xea\xd2\x86\x96\x9d\x40\xb1\x2e\x90\xe4\x4d\xb1\xa1\x34\x52\xce\x7c\x22\xa6\x2b\xd7\x4b\x72\xb2\xb8\xb2\x76\x08\xe9\xd3\x96\x52\xa2\xc5\xd5\xd8\x84\x3f\x37\xcb\xc8\x49\x02\x68\x77\x1c\x68\xcc\x30\x49\x46\xc3\xe3\xa8\x98\x50\x0f\x55\xca\xa8\x34\x8e\x86\x48\x09\x1b\xe9\x67\xa0\x1c\x28\xad\x31\x98\x79\xe7\x06\x99\x3a\xf3\x1a\xa5\xf3\x50\xcf\xee\xfc\xfc\x57\x71\xd0\x99\xcd\x33\x60\xc8\xb0\x8b\xae\xf6\x42\x4f\xf8\x8b\xb7\x77\x1d\x98\xb4\xa4\xed\xa6\x69\xf3\x16\x1e\x7d\xf5\xc5\xeb\xc3\x6b\x47\x77\xdc\x37\xf4\xca\x6b\xc6\xd4\x5e\x34\x6d\xfc\x88\xaa\xf9\x53\x96\xdd\x5f\xac\x7f\x55\xf7\x93\x75\x97\xb5\xea\x87\xbc\xd3\x6f\xe2\x8b\x0f\xbf\xb9\x71\xf5\xf7\xd6\x5f\xd3\x34\xe1\x92\xd8\xc5\x97\xff\xf0\xba\x17\xdf\xbe\xec\x99\x60\x6c\xf1\x8c\xe1\x53\xda\x46\x2e\x1a\xde\x7a\xcd\x98\x4b\x86\xb4\x8d\xac\xbd\xe8\xf2\x55\x2b\x4f\x1e\x7f\xed\x45\x37\xbd\x43\x08\x47\x9b\x29\x40\x38\xda\xea\xc1\xb2\xb3\xb0\xb4\x35\xe4\xb3\xb4\xe1\x6b\x22\xe8\x4e\xa3\x60\x8e\xb0\x0d\x83\x70\x02\x0a\x44\x0c\x1a\x82\x92\x56\xc6\x91\xf7\x7b\xa1\x50\x1c\x15\x49\x29\xbb\xa3\xb8\xa6\x96\x5c\x9a\xe7\xcb\xde\xa6\x64\xdc\xe3\x80\x34\x6e\x1f\x18\x5e\xb2\x5f\x36\x37\xce\x96\xcb\x7b\xf5\x94\xbd\x01\xcc\x39\x8b\xec\xe1\x42\x0c\x75\x83\x0c\x86\xba\x4e\x4e\xf4\x94\x05\xaa\x1a\x28\x49\x5d\x12\x0b\xfa\x2f\xc9\x99\xbb\x13\x06\xe6\xab\x1b\x9e\xf1\x8f\xfd\x8a\xca\xe4\xb5\x6f\xf6\x92\xb5\xe9\xac\xb2\x46\x0a\xc9\x3a\xb8\x87\xac\xd5\x83\xbe\xab\xac\x4a\x0f\xc7\x38\xa0\xbc\x73\xf2\xfd\xe3\x40\x22\xf7\x88\xb5\x88\xcc\xfc\x67\x44\xe6\x56\xb0\x61\x40\x99\x91\x1a\xd1\x82\x42\x1a\x85\xa3\xc9\xba\xa0\x6a\x0e\x6b\x4d\x42\x1a\x05\xa2\x10\xc5\xf2\x55\x11\x80\xe1\x54\x2b\x8d\xba\x5a\x73\x8a\x19\x0a\xc3\x5a\x6b\x40\x92\x35\x8f\x88\xad\x5d\x4a\x72\x65\xc1\x66\x3a\x13\xb6\xcf\xee\x28\xae\xad\x6b\xa2\xfa\xb1\x51\xfd\xd8\x1d\xe7\xa8\x9f\x02\xa1\xd8\x80\x5a\xba\xb4\x60\x30\x36\x90\xbe\xfa\xc6\x61\x54\x67\x1f\x11\x9d\x85\x41\x0c\x63\xe7\x81\xb4\x56\x1f\x41\x2d\x6a\xaa\x9a\xc2\x8b\x48\x94\xcc\x3b\xf5\x50\x97\x56\xeb\x4a\xa3\x5a\x91\x1c\x94\xa8\x2b\x4d\xaf\x69\xac\xb4\x38\x8e\xd6\x8c\x7a\x58\xad\xa4\x71\x1e\x7a\x51\x94\xf5\x24\x79\x3c\x5f\x95\x15\x86\x13\x03\x6a\xed\x27\x7d\x51\x45\xbf\x1a\x63\xfb\x4c\x16\x65\x75\x66\x5a\x43\x74\x36\x08\x0c\x05\xcf\x0c\xac\xb3\x86\x88\x36\x98\x4b\xa3\xd6\x88\x56\x6d\xf4\x84\xf5\x34\xb0\x46\x6a\x60\x8d\x22\x0e\xe7\x51\x71\x34\x15\xa2\xb5\xe9\xa2\x10\xb6\x4b\x9b\x8d\xbc\x1e\x1a\xab\xf0\x02\x43\x85\xe4\xb6\xd5\x6c\x8d\x92\xbc\x8f\x2b\xab\x6e\x18\xdc\x4a\x4f\xa6\x66\x77\xf4\xd1\xa1\xd6\x3a\x58\x92\xb5\x50\x20\x7e\xce\xda\xf4\xf4\x9d\x3f\x18\x50\x9d\xff\xbd\x72\x66\xfb\x8a\xbb\xe6\xcc\xb9\xf3\xa6\x61\xb4\xfc\x7c\xf1\x00\xea\x44\xb3\x6e\x5b\x32\xab\x7d\xe9\x92\x1b\xf2\xea\xd0\xe4\xdc\x9a\x66\x73\x33\x40\x03\x18\x0a\x2e\x01\x3f\xa5\xdc\x2b\x89\x3a\x0c\x73\xca\x55\x72\x30\x7d\x51\xc2\x08\x43\x74\x8a\xec\xaa\xd6\x22\xa4\xd1\x45\xd1\x94\x12\xaf\xe3\xec\x61\x4d\x31\xe5\x5e\x31\xa5\x90\x41\xad\x20\x0c\xa7\xaa\xa8\x5a\xab\x44\x6d\x38\x06\xb5\x12\x79\xcb\x94\x16\x0c\x4b\x72\x92\xab\x6b\x6a\xa1\xe3\x9c\x89\xea\x9a\x68\x3c\x1e\x47\xc3\xe5\x4e\x93\xdd\xe5\xf6\x95\xc7\x8d\xb0\xa6\x84\xf4\x85\x28\x41\x49\xee\x04\x25\xa5\x81\x6a\xf2\xf6\x60\xad\x25\x2e\xc9\xfb\x04\x93\x18\xb5\x0e\xef\xc1\x2a\x19\x53\x05\xc3\xfb\xe7\x11\x31\x92\x91\x6a\x21\x37\xd4\x94\xaf\xea\x9a\x9c\x72\x1f\xf9\xdb\xc3\xcf\x4d\x28\x1a\xd9\x51\x16\x7b\x6e\xfe\x9d\x5b\xf5\x84\xfe\x7e\x3d\xb7\x62\xf5\xb0\x7b\x6f\xda\xf5\xcc\x4d\x3f\x6a\x28\xbb\xc3\x67\x9e\xff\x93\x19\x2b\xd6\xbf\x72\xf9\x25\xd3\x3a\x3b\xa6\x8e\x9b\xfd\xec\x2c\x66\xbf\xfc\xf1\x57\xa3\x86\x2f\xde\x0f\x67\xbe\x0f\xe7\xbe\xfb\xda\x9e\x47\xc6\x4d\x7e\xe0\x8e\x97\x7e\x39\xee\xee\x8d\xd5\x83\x77\x5c\x31\xfe\xca\xb5\x87\xef\x9e\xf5\xe6\x8b\xb7\x2e\x4a\xc0\xda\xcd\x37\xdc\xfe\x53\xfd\x8f\x37\x77\xdc\x14\x1f\xf5\x0a\xa0\xfc\x41\x06\x1f\x68\x03\x58\x4e\x79\x2a\x53\x01\xa3\x0e\x6e\x90\x82\xa2\xba\x88\x56\xc2\x65\x3d\xa0\x5d\x21\xc5\xef\x32\x18\xd6\x6a\xec\xd4\x03\xda\x81\x24\x27\xfc\x25\x0d\x71\x52\x72\x4b\x54\x06\xea\xf0\xa7\x1a\x39\xe9\x11\xab\xe8\xfb\xc9\x3c\x25\x92\x9c\xa8\x0c\xd6\xc4\xe3\x71\xcd\x12\x20\xef\x29\x72\xe5\xbf\xa7\xa8\x3f\x36\xd1\xbe\x65\xf0\xc2\xfc\xa2\x37\xf7\xa8\x82\x17\x62\x1b\xed\x7e\xbb\x57\x11\x9c\xa5\x1c\x9d\xa6\x00\xe1\xe8\x0c\x83\xfb\xcf\xc6\xd2\x39\x28\x1f\x40\x57\x63\xf1\xdd\x64\x2e\x2a\x43\xd8\xd9\x08\xc3\x5a\xb5\x0d\x87\x3e\x7e\x2c\xbd\x94\xf0\x54\x3a\x89\x46\xe4\x04\x17\xaa\xa7\x5c\x40\xff\x06\x02\xcf\x1c\x14\x1a\x90\xc9\xf3\x7a\x03\x0b\xf5\x4b\xe8\xc9\x72\xbd\xb0\x10\xfb\xad\xa1\x8b\x41\xe0\x96\xb3\xe9\xa2\xb1\x10\x63\x69\x93\xc1\x58\xfa\x12\x61\x2c\x0d\x52\x84\x20\x48\x09\x59\x09\xc5\xbf\xbb\xd4\x59\x60\x34\xa0\xd8\x5f\x64\x80\x51\xbf\x72\xc3\x0f\x72\xc0\x88\xca\xfd\x1b\x43\xee\xc1\x60\xd1\xd9\xe4\x6e\x2e\x24\x77\xb4\xa7\xdc\xb5\x4d\x54\xee\xa4\xac\x84\x06\x11\xeb\xff\x2e\x82\xf7\xac\x42\x0e\x2c\xbc\x90\x0f\x93\x06\x52\x40\x7e\x26\x81\xf8\x2f\xf6\x1d\xfe\x23\xa2\x83\x46\x10\x07\x9b\x7b\x6b\x21\x80\xb5\x50\x9c\xd1\x02\xbe\x07\x62\x6a\xaa\x96\x3a\xfd\xe6\x68\xe6\xa5\xf6\x86\x56\x82\xb9\xec\x41\x39\x0c\xa3\xa6\x28\x99\x12\x1f\x12\x25\xef\xb3\x0f\x92\xf3\x51\x1c\x8f\xa3\x3a\x49\x73\x62\x9f\x5f\x2e\x6b\x5c\x20\x6e\xe8\xab\x39\x46\xf4\x65\x75\x4a\x32\xd5\x54\xa0\xf8\x6c\x9a\x92\x85\x8c\xaa\xfa\xa9\x60\x16\x56\x99\x5e\x4f\x75\xb6\xb2\xaf\xf7\xef\xab\x38\xe6\xe2\x6d\x58\x73\xf0\x89\xde\xde\x9f\xf0\x7f\xc2\xe3\xa6\x00\xe9\xc7\x9f\xd2\x87\xff\x33\x43\xdf\xd4\x93\xc5\x31\x69\x62\xa0\x39\xac\xf1\xee\x34\xe2\x23\x9a\xc9\x9d\x7b\xd5\x50\x4f\x02\x50\x13\x7d\x6d\x10\x61\x30\x2b\xca\x26\x08\xe3\x7f\x4e\xa5\xc7\xd1\xc3\xcd\x8d\x3d\xd5\x99\xc7\xb7\x1d\x07\x80\xf9\x07\x59\x8b\x1d\x5c\x51\x60\x2d\x8e\x42\x8c\x92\xce\x82\xbf\x1a\x4a\x72\x82\xe3\xed\xf1\x1c\xfb\x68\xf6\xfc\xe1\xdf\x3f\x29\x33\x23\x36\xf6\x54\x67\xfe\x9c\x18\x5d\xc3\xaf\xc9\x1a\x24\x70\x75\x81\x35\xc8\x85\xd6\xa0\x14\x5a\x03\x0b\xc8\x1a\x24\xec\x32\x08\xb1\x9b\xe0\x8c\xe7\x94\x91\x7f\x28\xf0\x8a\x7e\x90\x67\xfa\xc6\xaa\x7a\xc4\x02\x78\x5d\xbf\xe4\x3f\x22\x3c\xad\xc5\xe0\xc6\x42\x4c\xad\xc8\xa7\xa6\x04\x6a\xd4\x72\x34\xc3\xd1\xd8\x6b\xe7\x2c\x64\xe7\x38\x17\x79\x65\xa8\xc5\x95\x1d\x6b\x73\xbb\x72\x14\x69\xf9\x52\x64\xd6\x5b\xd8\x34\xf1\xc2\xaf\xea\x63\x80\x84\xd1\xb5\x2f\xd0\x64\xc0\x94\x33\xc7\xb8\x0e\x53\x05\x89\xe0\xc6\x82\x44\x39\x3e\xa3\xd5\x38\x66\x89\x68\x5c\x2e\x6a\x0b\x58\x49\x09\xc4\x0c\xc3\x5a\xb1\x83\x46\x6d\xe6\x00\x86\x86\x0e\x97\xb7\xbc\x8e\x9c\xaf\x70\xb5\x24\x27\x81\xb9\x58\xe8\x81\xaa\x63\xd8\xd1\xf2\xa1\x58\x6d\x28\xe6\xf1\xd6\xe4\x12\xf6\x79\x2f\xed\x0d\x56\x39\xe0\x94\xef\xff\xf5\xb1\x79\x5b\xab\x4d\x97\x8e\xd5\xbf\xb9\xf0\xcf\x23\xae\x9a\x75\xd7\x28\xc8\x5c\x72\x6c\xf2\x95\x9b\xf5\x93\xda\x4b\xbf\x79\x79\xf1\x8d\xf3\x9e\x6a\x5f\xb9\x68\xe1\xf6\x49\x70\xd9\x4e\xe8\xda\x3e\xe5\x4a\x46\x5c\xfd\xce\x75\x9b\x6f\x59\x1d\x6f\x5d\xf1\x1f\x97\x6e\xbc\xf9\xbe\xc5\x27\x1e\x39\x03\xf4\xbb\x5e\x7f\xaf\xeb\xce\xbb\x6f\x3e\xba\xe4\xd6\x07\x3a\xde\x03\x86\xed\x70\x53\xf8\xcf\x40\x31\x18\x9c\xed\xe2\xec\xcb\x9e\x89\x1a\x09\x2b\x11\xaa\x89\x26\xab\xca\x1a\xcd\x61\xad\xce\xe0\x2b\x6d\x2e\x4c\xaa\x89\x06\x57\x1e\x91\x52\x25\x14\xfd\x95\x44\x52\x83\xe9\xa7\x81\xd8\x36\xa3\xff\x1a\xdb\xa6\x13\x63\xeb\xb2\x70\x3c\x8e\x1c\x52\xca\xec\xae\xac\x22\xda\x1e\x88\x6d\xb3\x50\x88\xd7\x0f\x03\xe7\xea\x82\xc1\x5d\x3f\xbc\x9c\x5c\x9f\xc8\x8e\xfa\xba\xaf\xb8\x80\x29\xd0\xbb\x1e\xde\x83\xa9\xb3\x26\x9f\xa9\xb3\x77\x3d\x5c\xc9\xd5\xc3\x93\x5c\x91\x4f\xc2\x7e\xce\x2d\x69\x95\x7d\xaa\xc7\x03\xf0\x77\xe6\xe0\x4b\x41\x22\xcf\x57\x0c\xd8\xd2\x1f\x9f\x27\xfb\x87\x5c\x0d\x3c\x5f\x9e\xbc\x1a\x78\x0f\x79\x6a\x0b\x31\x8f\x9e\x63\x0d\x7c\x00\x29\xf2\xf2\x34\x85\xf9\x48\xa3\x19\x1c\xd2\x9f\x20\xcc\x8b\xbd\xf2\x33\x39\x59\xea\xfb\x91\xa5\xa1\x90\x2c\x3d\xea\xde\xa1\x4c\xdd\xbb\xe6\xbc\x76\xa4\x07\xc2\x28\x28\xcf\xf4\x7c\x64\x31\x80\x48\xbd\xf2\x2f\x5f\x71\xc3\xf9\xcf\x7a\xd7\xba\xf3\x64\x3a\x5b\xad\xdb\xda\x5f\xad\x5b\xe9\x5d\xeb\x0e\x66\x6a\xdd\xb5\xe7\x21\x78\xa1\x04\x4b\x41\xf1\x87\x15\xce\xac\xf4\xaf\x88\x5e\xc7\x8f\xa3\xfb\xcb\x7f\x94\xad\x6f\xdf\x59\x48\x1b\xfd\xd5\xb7\xad\xbd\xeb\xdb\x86\x0e\x90\x20\xa2\xc6\xca\x23\x92\x16\x72\x91\x6e\xe5\x46\x17\xad\x73\x07\x4a\x33\x0d\x2b\x21\x49\xe3\x7c\xe7\x63\x0b\xfd\x60\xa8\x82\x5a\xd9\xd2\x17\x3b\xf5\x7b\x6c\x87\xf6\xf1\x67\x2c\x58\x09\x4e\x72\x7e\x6e\x0f\xf1\xc9\x7e\xd0\x04\x90\x2d\xa2\x99\x2c\x19\x1a\x40\xe4\x8d\x68\x92\x85\xce\xce\x72\x47\x90\x33\xaa\x59\x8a\xd2\xc8\x15\xd5\x4a\x72\x6f\xe8\x1e\x92\x5d\xa1\x94\xfb\xb8\x92\xdd\xde\xdd\xb5\xb8\x65\x78\xdb\x90\xc1\x17\x1b\x7f\x30\x6b\xb7\x6e\xd5\xbf\x5c\x31\xbc\x6d\x78\x5b\x9c\x39\x4d\xff\xa4\x77\xe2\xb0\x33\x09\x6e\x22\xb7\x19\xb8\x41\x39\x08\x81\x5b\x01\x7d\xf9\x44\xc0\x94\xa6\x84\x8d\x25\x02\xe5\x82\x62\x8f\x68\x1e\x27\x61\xce\xad\x81\xd8\x29\x51\x2e\x28\x0f\x2b\xc9\x09\xe8\x22\x24\xc0\x35\x52\x52\x90\xfd\x64\x8c\xc4\x21\x27\x2c\x56\x1b\x09\x79\x02\x32\x56\xbb\x2b\x1e\x47\x25\xd2\x3e\x68\x73\xb0\xbe\x50\x9f\x0a\x39\xcd\x19\x50\x22\x28\xc2\x11\x9c\x29\x90\x3b\x60\xb6\x40\x3e\x6c\xd1\xe8\x4d\xff\xdc\xb6\x65\x6e\xfb\xcd\x1d\x6d\x8f\x1d\x7f\x7c\xc3\x0d\xb3\x17\x4a\xf0\xdb\xf8\xb5\x0b\xf6\xce\x9c\xde\x32\xbb\xfd\xd9\x19\x76\xd3\xba\xf9\x4f\xbd\x06\x27\xa4\x2e\xbe\xeb\xaa\x55\xb3\x7e\xf4\x96\xfe\x6c\x62\xc4\x4a\xf8\xd5\x35\xb5\x4c\x47\xe3\xa6\x33\xfa\xb2\xf0\x06\x08\x76\x8c\xa9\x21\x7e\x76\xb1\x91\x0b\xf6\x81\x00\x58\xd9\x2f\x5b\x6a\x55\x61\xb6\xd4\x62\x18\xd6\x4a\xdc\xe4\x6d\x00\x05\x88\x53\x83\x3d\x88\x53\xa5\x12\xfa\x8a\x06\x11\x63\xfb\x32\xa3\x5c\x7a\x4e\x0c\xaa\x59\xb4\x5b\x98\x4a\x15\xce\xa1\x6e\xa2\x20\xa5\x2a\xbf\x29\x1b\xd8\xe6\xcb\x5a\x05\x96\xf4\x2b\x6b\xf0\x9c\x99\x61\xab\xf3\x05\x44\x92\xa4\xf9\x71\x30\x23\xca\x58\xc0\xaa\xf3\x12\x30\xe3\x40\x0a\x4b\xc8\x58\x0c\x07\x52\x50\x44\x6e\x46\x3e\xe6\xce\xc9\x58\x0b\x56\xf4\x2b\x63\xe8\x9c\x65\xac\x33\x64\x4c\x5a\x3c\x7e\xf2\xce\x1a\x49\xd2\x4a\x6b\xb3\x62\x56\x13\x1b\x97\x50\xd5\x79\x08\x9b\xef\x61\xfa\xd9\xd2\xaa\x3c\x17\xd3\x9f\xd0\xf9\x71\x2b\x4b\xe5\x26\x71\x6b\x10\x44\xc0\x63\xfd\x48\x8e\x02\x11\xd4\xa8\xa6\x4a\xe9\xad\x1a\x8a\x42\x34\xb8\xb0\x26\xfc\x18\xda\xb8\x08\xda\xe9\xab\x94\x64\x83\xd3\x61\x0e\x6b\xd5\x2e\x7c\x4b\x6b\x0d\xae\x34\x99\xda\xfd\x0e\x1c\xc1\xfd\x84\x04\xfd\x28\x67\x52\x9f\xab\xb6\xb0\x8a\xfe\xa7\x6f\x7e\x9a\xa1\x3c\xb4\xc6\x19\x28\xc8\x44\x1b\xcc\x32\xd1\x56\xff\x3f\x62\xa2\xcd\x99\x7b\xff\x9c\xb4\xcc\x3e\xc3\xe4\xfb\x21\xa7\x35\xa1\xdc\x0c\x05\xe5\x74\x37\xb9\x80\x0f\xd4\x80\x77\xe8\xce\x6b\xa5\x99\xd7\x31\x55\x11\x2e\x59\xe4\x53\x11\x13\x21\xef\x52\xa8\x8d\x20\x26\x1b\xcb\x55\x1a\xaf\x66\x32\xa6\xe0\xda\x7e\x72\xfc\x8f\xf4\x95\x5b\xe4\x4d\xb9\xac\x88\x7c\x5d\xfb\xdb\x9e\x3a\xfe\x0b\xd2\x21\x0b\xc4\x24\x04\x0c\xe5\x31\xe4\x7c\x2c\xe1\x31\x64\x95\x70\x02\x82\x3c\x2a\x92\x84\xd7\xc7\x52\x0a\x59\x90\x80\x9c\x97\x0c\x7b\x01\xc8\x19\xcc\x86\x24\x4a\x60\x19\xfa\x0e\x28\x4a\x04\x2e\x69\x56\x82\x36\xab\x4a\x7b\xbc\x03\x8a\x8d\x41\x95\x35\xf5\x7e\x07\x54\x1f\xc6\xf8\x6a\xf8\x70\xea\xca\xba\xa0\xb9\xfd\x85\xeb\xd6\xef\x58\x7f\xfc\xb1\xe9\x8f\x85\xad\x82\xdc\x7e\x68\xe1\xbc\xd9\xbb\x67\xef\x9d\xfa\xfa\xed\xba\xeb\x79\x61\x92\xfe\x68\xf2\xf6\x3b\x6f\x78\x4b\xfb\x8d\xfe\xe4\xc1\x99\xd3\x16\x5c\xa5\xd7\xb2\x63\x17\x76\x10\xea\xf8\x84\xfe\x7f\x01\x60\xa9\x5d\x64\xcf\xcf\xe6\xbe\x96\x51\xf0\xe8\x08\xd9\xee\x91\xbc\x03\x83\xaf\x45\xe3\x50\x9c\xb3\xfd\x68\xe5\x7e\x4a\x41\xda\x50\x4d\xe8\xc1\xcf\xcb\x9e\x0a\x9f\x9e\x01\x8c\xcb\xd1\xe7\x04\xf5\x63\x66\x42\xbc\xef\x19\xa2\x33\x86\x23\x4c\x07\xc8\x5c\xa6\x0c\xee\x39\xa7\xa9\x4c\x67\x44\x13\x4d\x69\xd2\x59\x62\x8c\xf0\xba\xbe\xd3\xe0\xe5\x00\x03\x96\xb1\x40\x81\x39\xd4\xbb\x2a\x98\x50\x45\xdf\xb1\xd3\x4d\x9b\xb2\xb5\xd1\x85\xa4\x66\x55\x0d\xe6\x0f\x5c\xb1\x0a\x44\xb4\x2a\x53\x36\x38\xec\x55\x16\xae\x35\xca\xc2\xfb\x68\x09\xbc\xf7\x6b\xda\xce\xb7\x82\x17\x0b\x0c\x5c\xe4\xdc\x86\x85\x1a\xa8\xa6\xb9\x69\x53\x66\xbf\xa6\x0a\x6d\xc6\xac\x75\xe7\x39\xed\x57\x71\x44\x73\x0b\xe9\x84\x9b\x10\xc1\xba\xbd\x96\x30\x69\xc1\x2f\x23\x93\xc7\x32\x8d\x3f\xe4\xec\xe4\x71\xd2\xcb\x72\xe6\x70\xca\x47\x49\x5c\xbe\xe3\x6c\x36\x27\x4b\x72\x12\xda\xdc\xc5\x04\x41\xf4\x3f\x9e\x1d\x53\xc9\x84\xa0\xca\x04\x0a\x4d\xcf\xce\x63\x6e\xbc\x7c\xea\x9e\xc0\xe2\x11\xfa\xdf\x3a\x1e\xea\x33\x68\xcf\x79\x7c\x17\x5e\xbc\x52\xff\xcb\x9d\xb9\x7e\x00\xfe\x98\xd1\x0f\xb0\x73\xe0\xfd\x1f\x14\xd1\x42\x42\x3a\x11\x1a\x84\x15\x13\xaa\xb7\x84\x51\x30\xda\xab\x49\x20\x00\xc3\x79\xd3\xd9\x86\x6d\xa0\x22\x11\xe3\xe4\x54\x03\x55\xd2\xe0\x9e\xf5\xca\x6a\x49\x4e\x72\x65\xa1\x41\x3d\x2c\x06\xd5\xcb\x9a\x60\xfe\x97\x2c\xa7\x87\x76\x06\xb4\xa1\x03\xf9\x8a\x1a\xa0\x3c\xf9\x5a\x9e\xca\xb0\x4d\xe9\xa3\xb8\x12\xf2\x0e\x49\x07\xa8\x00\xfb\x33\x36\x25\xab\x2a\xcd\x26\x72\x59\xdb\x42\x65\x91\x94\x8f\xd2\x7f\xf4\x9d\xe8\xaf\x24\xb3\xd9\x1e\x3b\x09\x27\x32\x73\xec\x81\xef\x66\x40\x1e\xa7\x24\x6b\xd0\x46\x2b\x6a\x65\x71\xc4\xca\x29\x59\xf1\x15\x97\x10\x7b\x02\x3e\x49\x46\xce\x78\xff\xc4\x06\x43\x5a\x63\xaa\x03\x62\x8c\x42\xab\x6e\x7d\x4d\xab\x66\xda\xf2\xbb\x6e\x1b\x3b\x2a\x14\x6e\xba\xf4\x9a\xeb\x7b\x9b\xd6\xc9\x4f\xc6\xdf\x33\x6e\xfa\xad\x2d\xa3\x2c\x8b\x1d\x57\x63\xdb\xd2\x47\x65\xdf\xfb\xd8\x0c\xb6\x52\x46\x15\x64\x53\x07\xb4\xb1\x48\x24\xd5\x40\x34\x96\x09\xfe\xf3\x7a\x08\xea\xec\xa4\x9c\x90\xb9\x71\xd4\x7c\x3b\x42\x75\xd9\x2e\xa3\x44\x75\x43\x24\x4e\x5e\x63\xb2\xcf\xee\x28\xae\x19\xd4\x48\xa4\xaf\x6e\x90\x64\x14\x88\x9f\x7f\x7b\x4a\x6f\xad\x0c\x68\x52\x27\xf3\x15\xd4\xbf\x49\x9d\xfe\x9f\x7c\x55\x19\xef\x55\x77\x08\x1d\xc0\x0b\x02\x60\x24\x9d\x43\xd6\x44\x16\x23\x4f\x24\xe3\xc8\x5e\xc9\xf4\xbf\x5b\xd8\xec\x6b\x10\xed\x6e\x12\x68\x01\xcd\x22\x93\x4a\xaa\x3d\xbf\x92\xda\xcf\x3c\x71\xde\xd0\x46\xe1\x39\x62\x06\x65\x06\x36\x0a\x8d\x10\xf3\xae\xbc\xf9\x55\x7c\x77\xf0\x06\x9e\x2c\xfc\x16\xc9\x60\xf6\x2d\x92\xd5\xff\xda\x5b\x24\xf3\xf2\x6b\x85\xdf\x27\xf9\x55\x26\xbf\x56\xa0\xd4\xcb\x79\x7b\xf6\x4b\xe6\x74\x5c\x73\x0e\x3a\xae\xcd\xea\x38\x74\xde\x3a\xee\x31\x40\x52\x58\xcf\xf0\xcd\xfc\xe1\x91\x7e\x74\x9d\x1f\xe7\xd0\x77\x49\xfe\xca\x88\xef\x0a\xeb\x3b\x94\xd5\x77\xdd\xbf\xa6\xef\x5e\x39\xc0\x82\x3a\xff\x3a\x3f\x07\x58\x58\xed\x3d\xd7\x4d\xf5\xde\x02\xbc\xa0\x0a\x2c\x3c\x8b\xde\x51\x65\x44\x2b\xb1\xe4\x4c\x87\x4e\xd8\xfb\x60\x58\x2b\x2b\xa2\x51\xb7\x2f\xf3\xce\x39\x54\x26\x25\x2d\x9c\x22\x93\xd3\x7d\x3e\xdb\x93\xc3\x8c\xfd\x9d\x81\xa7\x46\xb6\x5c\x3f\x3a\xd2\x30\xb4\xf0\xbe\x6c\x8b\x8f\x9d\x76\xc1\xf8\x68\xe6\xbd\xa5\x2c\xe2\x3f\x27\xd8\xb9\xbd\xc0\x9e\x60\xcc\x54\x6a\xa1\x2c\x91\xb9\xa6\x09\x82\x98\x8b\xe8\x5b\x61\xfd\xf6\xcc\x0d\x56\x2e\x25\x39\x8b\x4b\x21\xf2\xfc\x0b\x47\x25\x27\x56\x3f\x67\xe5\xef\x86\x54\x05\x37\x6d\x47\x46\xa8\xfc\x73\x52\x7b\x0e\xe7\x24\x94\x3d\x27\x75\xe7\x7d\x4e\x54\x8f\xb7\x35\xa6\xba\x05\x93\x10\xac\xed\x8f\xd8\x00\xfe\xee\xa6\x8b\x66\xdf\x7d\xc7\xd2\x4b\x7e\x72\x01\xaa\xba\xae\xe0\x8e\x98\x2e\x2e\x89\xae\xbb\xf5\x8a\x92\xe1\x5b\xa7\x5e\xff\x30\xc8\xbe\x4f\x96\x25\x67\x25\xd4\xcf\x59\xa9\xcb\x9e\x95\xfa\x7f\xf5\x6e\xea\xb1\xfc\x7e\x94\x5e\x97\xbf\xfa\x42\x9a\xe7\x47\xf5\x5c\x3c\x99\xa7\xe7\xbd\x42\x07\xb0\x00\x05\x54\x81\x79\x20\x61\x31\x18\x38\xac\xe6\x0c\x03\x87\x99\x9e\x10\xe7\x11\x8d\x77\x17\x1c\x96\x57\xc8\xb0\xbc\x55\x3c\x81\x7d\x27\x14\xc9\x4b\xb8\xad\x4a\x06\x26\xf0\x18\x26\x18\xad\x4c\x56\xe3\xe5\x3f\x2a\x34\x06\x5f\x03\xa1\xec\xd8\xab\xd2\x53\xc4\x49\xb0\x25\x6f\x00\x76\x53\x66\xfa\xd5\x9a\x2f\x22\xdf\x99\x9d\x80\xdd\x41\xc7\x5f\x99\x11\x3d\x04\xa4\x7d\x5d\x15\xc6\xbb\x7e\xc3\xe0\x91\xfe\xde\xf6\x8b\xac\x11\x54\xab\x66\xfa\x6d\xfa\x7d\xe7\x2f\x06\x97\x38\xf6\x08\x39\x69\xeb\xcd\x40\xaf\xff\xd5\x6a\x8b\x24\x59\xab\x0a\xc7\x7b\xbf\x08\x98\xbc\x86\x02\x55\x9d\xd3\x0b\x81\xf3\x7c\xd2\xc0\xaf\x06\x66\xdf\xaa\x98\xe9\xde\xe3\x7e\x70\xd8\x40\xef\x08\x66\xde\x2b\x6e\x7a\xf3\x02\x57\xcb\xcf\x2f\xf8\xff\xe6\xa4\x8d\x39\xe9\xd9\x67\x8e\xf1\x2d\x26\x17\x28\x03\x0d\xe0\x17\xf4\xec\x26\x4a\x8c\x31\x00\x6a\x1d\x21\x81\x36\x3f\xba\x54\x55\xb3\xf3\x69\xcd\x21\x45\x71\x98\x8d\x44\x35\xd3\x9d\x56\xae\x90\x7c\x04\xe1\x93\xb4\x13\xcb\x71\x1a\xdd\x7e\x83\x8c\xa2\x6e\xfd\x3f\x9e\xcf\x16\x75\x2d\x5d\x3c\xbe\xdd\x5c\x5d\xc8\x22\x26\x8b\x2c\x4e\x25\x9c\x74\xe0\x67\xf6\x45\x2b\x2c\x40\x96\x26\x98\xb2\x14\x39\x24\x57\x96\x5f\xc2\x53\x8e\xa3\x5d\xbb\xad\x84\xd6\xdb\xdc\x52\xc2\xeb\x23\xf4\x71\x4e\x19\x09\x71\xa0\x85\x0c\xa4\xe9\xf5\xf5\x42\x9a\xad\xf4\x1d\x06\x82\x2a\x04\xfb\x79\xe7\xf4\x03\x5f\x3f\x39\x7d\x73\x43\x51\x91\x10\xd0\x37\x97\xc0\x8e\xea\x64\xe8\xb1\xd2\xad\xfa\xc9\x2d\x5e\x73\xfb\x0b\xd3\x1e\xda\xf1\xca\xde\x69\xaf\x75\xdc\xd8\xde\xfe\xec\x2c\x6c\x5a\xb3\x7e\x71\xfd\x75\xd7\xb4\xfc\x64\xed\xcb\x2f\xaf\x3d\x15\x3e\x7c\xe7\x0d\x3f\xdf\x7b\xf4\x15\x58\xb2\xe5\xe6\x8e\x67\xf5\x8f\xb3\x1c\x2f\xa6\x03\xa0\x08\x38\xcf\xc6\xf1\x42\xde\x76\x85\x43\x7c\x31\xa2\x49\xff\x7e\xba\x91\x58\xa0\x10\xc9\x48\x8a\xe6\x27\xb2\xec\x22\x38\x72\xcf\xf4\x64\x7d\xcc\x2f\x24\xf8\xb2\xf6\x6c\xbd\x68\x28\x18\xd1\xaa\x4d\x59\x7f\xd4\xab\x35\xab\xce\x68\xcd\xea\x34\x5a\xd2\xb2\x1d\x69\xb5\x24\x3b\x91\x6b\x34\x3a\xaf\x5e\xb4\x58\xe0\x2c\x8d\x58\x2a\x49\x52\x0c\xd0\x81\xb5\x69\x53\x96\x07\xa6\x8d\xf0\x59\xec\x39\xcb\xfe\x78\x23\x9a\x2c\xa4\x13\xb2\x17\x87\xe0\xb2\xcb\x12\x46\x0e\xc2\x74\x81\x6c\x47\x52\x4e\x1a\x77\x3b\x29\xad\xac\x3b\x4b\x2b\xfb\x9d\x89\x54\x5c\x4e\x49\x4e\x09\xa6\x22\xab\x97\xda\x39\x62\xfb\x50\xa9\xf4\x08\xba\x0b\xec\xf1\xc7\x3d\x73\x12\x19\x22\x1f\x31\x17\x59\xd3\xfd\xfe\x27\x7f\xcc\xe8\xc1\xdb\x7b\x96\xfd\x6e\x8a\x68\xf5\x42\x3a\x51\x4f\x08\xed\xeb\xc3\x16\x3a\xd6\xd6\xdc\xab\x05\x2d\x8f\x28\xc1\xb0\x05\x24\x88\x68\x50\xe5\x11\x29\x15\xa6\x3f\x09\x47\x52\x83\xa8\xaa\xa2\xd9\xc6\x34\x3f\x19\x75\xa5\x8d\x69\x65\x72\x92\xab\xac\x6f\xea\xf1\xe2\xf5\x7f\xd1\x5e\x7a\x66\x26\x06\xb4\x9c\x2b\x7a\xa4\x26\xfa\xb5\x20\xa6\x33\xab\xc0\x8c\x1d\xf9\x08\xc7\xc8\xea\xb3\xb2\xf0\x68\x4e\x0b\xa5\x57\xb7\x1d\xd1\xa4\xa2\xdc\x8b\x5b\xbe\x8b\xa1\x48\x36\x83\x71\xa7\x37\x47\x52\x0e\x9b\xf6\xb5\x8d\x1f\x1a\xb0\x34\x77\x03\x3c\x96\xc1\xa2\x46\x6f\x2e\xc1\xd7\x55\xa0\x11\xac\x3d\x8b\x4d\x84\x23\x5a\x2d\x96\xaa\xa9\xc0\x1d\x90\xac\x13\xca\xcc\x61\x2d\x58\x44\xae\x8a\xba\x22\x32\xcc\x48\xf6\x3b\x99\x79\xb1\x7e\x99\x94\xe4\x2a\x6b\x49\x47\xb7\x50\x97\xad\xe3\xfc\x8b\x9b\x9d\x0f\xc7\x07\xda\xe9\x3f\x65\x50\x79\xff\x9b\x3c\x25\x87\xcd\x27\xe9\xa3\xb8\x45\x7c\x27\x28\x02\xa5\xe0\x41\xa3\x7b\x4d\x54\xfb\xee\x35\x2a\x89\xa4\x3c\x34\xf3\x94\xcf\x22\x55\x46\x28\x87\x5c\xf6\x2c\x8b\xe4\x77\xba\xdd\x35\xe0\x21\x99\xfb\x9e\x9b\x0d\x5a\x7a\x65\x4c\x0a\x5c\x07\x77\xe6\xa5\x49\xb2\xfb\xae\x3f\x71\x65\x2e\x2b\x42\xf2\x47\x73\xd8\x83\xa4\x27\xbd\x0a\xa8\x60\x5b\x81\xbd\x47\xcd\x91\xd4\x20\x83\x5e\x37\xaf\x3b\x77\x48\xef\x3e\xd4\x06\x7b\x1a\x35\xe4\xbc\x41\x4b\x8f\x83\xde\x90\x3d\xe8\xfb\xb8\xca\xda\x50\x53\x73\x8f\xa3\xee\x19\x24\xc9\x5a\xb0\x01\x7b\x75\x29\xa1\xd4\x86\x28\x96\xfc\x97\xec\xa1\x57\x1a\x69\x40\xab\xa8\xed\x91\x47\xea\xd7\x34\x4e\xe9\xbd\xf2\x48\xf8\x0e\xe8\x20\xdc\x48\xc5\x67\xe7\x14\x2b\x89\x64\x9b\x15\xff\xcd\x44\x6e\x3d\x62\x86\xde\x9b\x7f\xb0\x67\xbc\x90\xf1\x05\x53\x7a\xc7\x41\x38\x86\xb3\x1a\xf9\xa5\xe6\xb3\xf7\xa2\x47\x0b\x39\x7e\xb5\x67\x4f\x76\xa8\x29\xeb\xf9\xeb\xff\x0d\xbd\xe8\xbd\x02\xc0\x81\x36\xb4\xb9\x47\x1c\xd8\xff\x59\xd7\xf3\xb5\x40\x63\xf1\x09\x42\x07\x28\x07\x83\xc0\xdd\x20\x51\x8a\x35\x20\x67\xe2\xef\x22\x36\x9d\xf2\x78\x4b\x39\x7b\x18\xf9\x54\xcd\xc3\xa6\x91\x3b\x9a\xe9\xc9\x77\xba\x49\x23\x3e\xd9\xdc\x75\xc7\xdb\xe9\xbb\xb8\x9a\x1c\xc8\xd5\xc5\x6b\x3e\xf1\x84\x03\xf9\xbb\x80\xe6\x22\x2f\xeb\x75\xb9\x7d\xfe\xdc\x0b\x01\x3d\xb2\x24\x6b\x4e\x10\x8f\xd3\xf7\xf6\x9a\x49\x18\x2f\x64\xc3\x78\x0f\x7d\x15\x71\x26\x90\x57\x02\xb1\x00\xeb\x80\xc1\xca\xde\x59\xaf\x5f\xc1\x05\xbf\x5f\x7a\x78\xfe\xe8\xf1\x7b\x17\x3c\xa3\xff\xf5\x89\xb7\x53\xeb\x17\xcd\xd0\x3f\x0b\xc2\x0f\xb7\x2f\x7f\x7b\xa1\x7e\x42\xff\x1d\x7c\x3d\x3f\x01\x26\x43\x1b\x7c\xf5\x78\x5d\xd3\xd3\x55\xd1\x77\xf4\x6d\x47\x7f\xf6\x61\x0d\x44\x4f\x77\xb7\x34\x04\x60\x90\x2f\xed\x55\xef\x57\xc9\x7c\x70\x00\x94\x93\xc9\xa0\xd1\xc6\x1b\x6f\x02\x42\x3a\xe1\x85\x20\x9c\x50\x32\x11\x42\x69\x44\x63\x05\x3a\x59\xe5\x3c\xa2\x55\x28\x64\x52\x0a\x68\xb6\xff\x1f\x7b\xef\x1e\xe6\x54\x75\xee\x8f\xaf\xb5\x2f\xd9\xb9\x67\xdf\x92\xcc\x24\x33\x93\x49\x32\x17\x86\xc0\x64\x26\x61\x66\x88\xdc\xbc\xe0\x0d\xd1\x2a\xa5\x8a\x14\x51\x11\x11\xf1\x86\x22\xe2\x0d\x2d\xa2\xa5\xa8\x08\xa8\x28\x2a\xa2\xa5\xa8\x14\x15\xd7\x4e\xc2\xe0\x05\x75\xf0\x52\xb5\xe8\xb1\x9e\x16\x6c\x8f\xb5\xfe\xac\xbd\xa5\xa5\xd6\xa2\xb6\x72\x99\x3d\xbf\x67\xad\xb5\x77\xb2\x33\x93\x70\xb1\xe7\x79\xce\x3f\xdf\xd3\xe7\x6c\x42\x40\x66\xaf\x77\x7d\xd6\xbb\xde\xf5\xae\xf7\xfd\x7c\x58\xd2\x8b\xae\xb5\xd6\x49\x72\xce\xee\xf3\x07\x68\x74\x4e\xfa\x71\x27\x30\x71\x43\x7c\xd8\x6c\xe0\x61\xc9\x3d\xa3\xa2\x96\xee\x5d\xcb\x73\x64\xe9\x09\x2f\x9e\x76\xc7\xfa\xc6\xb4\x62\xff\x7e\xee\xbc\xbb\x1e\xbf\xf7\xcb\x07\x5e\x3d\xc7\x71\xc2\xf2\x7d\xc9\xbd\x1f\xbc\x79\xc7\x5f\xb6\x4c\x7f\x65\xc1\x3b\x17\x6f\xbe\xf0\x0c\xcb\x58\x07\x40\x4b\xc7\x92\xe5\xff\x7d\xe2\xc2\x79\x6f\x64\x3f\x84\x17\xf7\xbd\xb2\xf9\xc0\xa2\xdf\x7e\x70\x12\xcb\x7d\xdc\x0b\xa3\xab\x7f\xf7\x53\xfd\x77\xcc\xc7\x83\x7a\xfc\x4d\x1c\x8c\x27\x38\x78\xf3\x48\x70\x80\x86\x27\xb5\x66\xa1\x90\x6d\x1e\x8e\xe3\xa3\xe6\x56\x47\x82\xb4\x31\x16\xc1\x81\xc3\xc4\x48\x59\x3b\x54\x2b\x4c\xe4\x87\xd1\x48\xe8\x5b\x00\x47\x8b\x45\xf0\x8e\x59\x47\x8a\xcd\xf2\x2e\x2e\x10\x1c\x4e\x3b\x7e\xbe\x35\x9c\xac\xc1\xd2\x11\xc0\xe9\xa0\x35\x62\x3a\x14\x9e\x6c\xb0\x18\x33\x19\x58\xe2\xf7\x18\x58\x7a\xec\x30\x58\x42\xdd\x49\xad\x53\x28\x64\x3b\xbb\xb1\x51\x3b\xd3\x8e\x04\x1a\x99\xb2\x00\x0c\x45\x44\x2d\x01\x13\xf9\x76\x6a\xd4\x76\xd2\xba\x97\x1f\x45\x8d\x7a\x0c\x4c\x68\x89\x88\x24\x67\xdd\x75\x2c\xde\x45\xda\x25\x14\xcd\xa0\xb4\xbc\xd5\xa1\x34\xb7\xda\x49\xb3\xde\x28\x49\xf3\x07\xb1\x5b\x2a\x62\x34\x2a\xc9\x79\x87\xcf\x1f\xb0\x1f\x35\x48\xad\xe6\x3b\x32\x90\x3e\x6c\xb5\xe0\xe1\x51\xca\xbe\x66\x89\x3d\x29\x3e\xbb\x40\x03\x68\x03\x4f\x1c\x11\x3e\x5b\x93\x5a\xcc\x51\xac\x66\x2d\x21\x52\x6b\x72\x91\x6a\xd6\xa3\x06\x60\xc4\x27\xc9\x39\x39\x10\xac\xa3\xd4\xab\x9a\x8b\x08\xc0\x7f\x6b\xfc\x59\xb2\xc4\x87\x05\x1f\xf3\xb4\x99\x30\x3e\x94\x1f\xfb\x49\x31\x6f\x6c\xe2\xee\x33\x82\xbb\x2e\x70\xf5\xe1\x70\x97\x4e\x6a\xed\x0e\x2a\xd2\x55\x86\x34\xad\xc3\x55\x20\x2a\x5c\x18\x58\x39\xb6\xce\x4d\x44\x16\x3a\xa4\x9c\x43\x69\xb5\x93\xf5\xf7\x1f\x23\xc9\x62\x88\x23\x83\x11\x3c\xc5\x30\xc6\x11\x40\x68\x76\xd1\x24\x84\x8b\x77\x0c\x7f\x26\xbf\x13\x34\x80\x61\x38\xda\x3b\x92\xbd\xae\xcd\x0a\x1e\x42\x44\xe0\x23\x94\x45\x47\xef\xbd\x70\x90\x1f\x69\xa5\x6c\x05\x72\xdd\x7f\x84\x1c\x33\x3d\x18\x3f\x02\xaf\x95\x6a\x9e\x12\xda\xac\x2c\x1f\x37\xeb\x50\xc8\xe9\x3f\x79\xdc\x4f\x4f\x56\xd3\x6f\x1d\x03\xc0\xe0\xfd\x6f\x14\x8e\xf2\x0e\xb3\xff\x75\x0d\x06\xcd\x28\x5f\x41\xeb\x1e\x0c\x9a\x51\x95\x40\xf3\x2d\xb7\xc8\x52\x8a\xf4\x08\x21\x73\x46\xcd\xed\xe3\x66\x47\xcf\x53\x8e\x64\x6f\xf4\x67\x5e\x1e\x17\x1e\xf5\xca\x18\x43\xcf\x0f\xf0\x37\x18\x5c\xa0\xdb\x69\xbc\x9b\x15\xec\xae\xb4\x51\xdf\x91\x65\x78\x5b\x3a\x9d\xce\xb3\x4e\xf3\xf6\x9d\x65\x0b\x88\x4b\x99\xe2\x54\x2e\x27\xc9\x1f\x5b\x68\x50\xec\x38\x70\xa4\x85\x80\x44\xfb\xd7\x59\xb0\x90\x88\xbe\x45\xc5\xa9\xd6\xed\x7d\x89\x00\xcb\x25\xe6\x58\x17\xa3\x24\x90\x5d\xcc\x71\x76\x5e\x49\xe4\x1c\xf8\x89\xbf\x77\xba\x28\x41\x0a\x57\xba\x9b\xb7\x33\xd8\xf7\xfb\x6a\x8d\x0e\x50\x31\x98\xc9\x20\x5e\xd6\x14\xbf\x71\x5c\x4e\xb3\x51\x25\x0d\xe3\x4a\x94\x2d\x0f\xa5\xce\x86\x5d\xdb\x6e\x67\x6e\x5f\x9a\xd7\x77\x6e\x5d\xd5\xbf\x78\x15\xec\x29\x23\xe5\xed\x7f\x80\x99\xb7\x7f\x12\xb3\xb9\xff\xec\x72\xd6\x51\xda\x47\x33\x41\xd8\x4c\x3a\x09\xfe\x64\x9c\x05\xc4\x70\x3a\x4d\x8b\xe3\x02\x42\x01\xc1\x24\x69\xc6\xa2\x2e\x38\xec\x24\xd5\xbc\x16\x5b\xa8\xb4\x42\x2e\x27\x7a\x54\x7b\x42\x93\x9c\x05\x24\x25\x09\x0d\x50\xa2\xc8\x11\xf3\x3a\xb5\x08\xfd\xe0\x42\x61\x31\xc7\x86\x19\x25\x91\xe3\xc8\x93\x27\x4f\x1b\x79\x86\xf0\x33\x1b\x0a\x5b\xa5\xbb\x6c\x19\xc4\x65\x10\x4f\x04\xbc\xf2\xac\x2d\xc4\xf1\x54\x7b\xc7\xf2\xb9\xd8\x5b\x93\x15\xea\x88\x4c\x8c\x24\xa1\x36\x52\x82\xea\x0c\x44\x5a\x69\x88\x01\x24\x59\x13\x3c\x06\xc5\x24\x8b\x51\x67\x54\xce\x19\x5d\x36\x46\x93\x4d\x79\xb3\x18\x9c\x94\x9f\xe6\x6e\x92\x9c\xe7\x6e\xbd\xf8\xf6\x55\x81\x55\xf9\xd5\xca\xaa\x73\x36\xde\xdc\x38\xfb\xd7\x16\xeb\xda\x54\xfd\x8a\xf1\x77\x1c\xb7\x70\xde\xca\xe5\xa3\xe7\xf7\xcf\x66\xd0\xb9\xed\xab\x16\x7d\xfc\xb0\xde\x6a\x9b\x35\xe8\x8e\x73\x2a\x00\x36\x86\xef\x05\x0a\x08\x42\x97\x81\x43\x9f\xa8\xa4\x0d\x45\xa4\xac\xcd\xe1\xc4\x38\x54\x65\xc0\x53\xc6\x74\x95\x78\xb0\x3c\xcb\xe0\x2f\x72\xd0\x1b\x08\x36\x05\x89\x42\x78\x8e\x13\xec\xae\xa6\x20\x95\xf2\x00\xbb\x35\xc5\x49\xea\x1f\x0c\x30\x22\x9b\xa8\x89\x30\xa1\xf9\x14\xe2\xf2\x1c\x30\xa1\x39\x4b\x02\x1f\xe3\x7f\xbc\xf7\x03\x3a\x21\x3f\xd8\x9b\x31\x58\x40\x73\x10\x60\x64\x72\xf8\x89\x14\x31\x27\x28\x36\x25\x81\x44\x31\x67\x17\x1d\x4a\x02\xf9\xc4\x9c\xcb\xe7\x54\x12\x39\x2f\x7e\xe2\xef\x25\xf2\xbd\x22\xe6\x64\xfc\x37\x73\xaa\xf9\xf7\xfd\xf8\xfb\x5c\xc0\xfc\xd3\x20\xfe\x9e\x3d\xd6\x0d\xf1\xfb\x7a\x25\x59\xf5\x07\x82\xed\x96\xff\x33\xbb\xde\xe2\x3d\xe9\x9e\xb4\x60\xa4\xbb\x59\x0c\x6f\xec\x2a\xa7\x7e\xfa\x62\xe4\xc5\xae\xde\x2e\x66\x69\xf7\xf3\xe9\x17\xeb\x5f\xf9\xf4\x05\x0c\xed\x2c\xb3\xb4\xa3\x7f\x31\x37\xf2\xfe\xaf\xbf\xfe\xfa\xeb\xfb\x0f\xfc\x12\xa3\x9a\x9d\xfc\x29\x80\x04\xcb\x09\x9b\x0a\x22\xd0\x6d\x58\x57\xf5\x47\xb0\x75\xbd\x18\xcb\x21\xa1\x80\x98\xa4\x06\x9d\xe9\xb4\xc6\xf2\x05\x8d\x13\x52\x29\xc4\x27\x91\xad\x48\xef\x16\x71\x12\xef\x67\xb1\x62\x0d\x24\x90\xce\xa9\x52\x8d\x3d\xa1\xf9\x9d\x05\xe4\x4f\x6a\xaa\x85\xe4\x0d\x7d\x19\xa6\xb6\xfc\xd7\x57\x4b\xe9\x4d\x81\x5f\x44\x01\xa2\x65\xac\xf4\xf1\x83\x2d\x1b\x11\x73\x42\x04\xdb\xcb\x19\x21\x3a\xe0\xc6\x8a\xc8\xb9\xc8\x97\x0d\xf8\x99\x6d\x88\x58\xd4\xc6\x90\x2b\x03\x72\x2e\x25\xd0\x40\x45\xb0\x21\x27\x38\xcd\xdf\x15\x71\x6f\xe3\x49\xa5\x8e\xa6\xfa\x25\x39\xe7\xf0\xda\x69\x5d\x58\x08\xe3\xdd\x2d\x51\xbc\x1b\xe6\x15\xa2\x6c\xba\x7b\x28\xe6\x33\xd0\xf1\x70\x64\x4d\x6b\xbe\x0d\x4e\x6f\xd0\x37\x4f\x73\x3e\xb9\xf3\xb6\x7b\x83\x77\xe5\x57\x2a\xf7\x4e\xdd\xb8\xa4\x71\x26\xb7\x6b\xd9\xf3\xcf\x2f\xd3\xd7\x7e\xba\x6a\xc5\x31\x57\xf6\x2f\x62\xd6\x9f\x9d\x5c\x73\xdd\xa7\x6b\xf5\x9e\x22\x1f\xf4\xb3\x42\x1a\xb8\x40\xb4\x98\x4f\xac\xc0\x58\xdc\x90\xd4\xbc\x42\x01\x05\x52\x39\xc5\xdb\x60\x4f\x68\xb5\x42\x01\xb9\x53\xa4\x48\xc5\xbd\x3b\x1f\xa5\xc1\x6f\xfc\x5b\x11\x16\x47\xdd\x92\xac\xf1\xdc\x10\x92\xe2\x4a\xc4\xb1\x65\x0c\xc5\xfa\xdf\x2b\x76\xea\x94\x73\x34\x0f\xed\x8d\x23\x3e\x93\x1d\xc6\x7f\x0a\x58\x50\x6b\xde\x95\x58\xbb\x43\x03\x49\xcd\x26\x14\x90\x37\x95\x73\xd9\x02\x76\xd2\xb6\x63\xee\x26\xdc\x6e\x04\x52\x86\x9a\x04\x29\x31\x2e\x89\x1e\x16\x77\x90\xb2\xc6\x56\xc8\x16\xd5\x09\x6d\x6a\xa9\xa5\xb5\x62\x2b\x60\xbe\xf0\x5c\x95\xbe\xbf\x03\xbd\x15\x9a\xfc\xe8\xdc\x9d\x6e\xdc\xf9\x9c\x57\x7d\xee\x2a\x5c\xf7\xfc\x47\x54\xd9\x3d\xd1\xf2\x79\xf8\x45\x84\x69\x8d\x94\x5b\x7d\xf5\x6a\xb3\x3f\xf8\x67\xfc\x3c\xa2\xbb\x7d\xe6\x50\x3b\x73\x49\x8d\xc7\xef\x65\xaf\xd4\x26\xec\xa8\xd6\x26\xac\x71\x7c\xc9\x8e\x3d\x51\x62\xb7\x2b\xf1\x1b\x50\x33\xd1\x7b\x25\x6a\x9b\x79\xc6\x7d\xcb\x03\xd5\x6d\xf3\xad\xaf\x5a\x8e\x0e\xe3\x2a\x3e\xb6\x08\x4e\x97\x79\xb7\x62\x1b\xca\xe6\x6e\x3d\xca\x95\x99\xf7\x05\xeb\x89\xad\x8c\xd8\x5d\xb4\x9c\xcd\xb0\xad\x7f\xcf\xef\x21\xbd\xd8\xb7\x0d\xb5\xb5\x98\xd4\x5c\x42\x21\xeb\x12\xf1\x38\x5d\x1e\x47\x82\x90\xa7\xcb\x49\xc4\xef\x36\x74\x7e\x91\x5d\x44\x6c\xe3\x6e\xc9\xe4\xc2\x63\x69\xdd\xb7\x25\x52\xf0\xc0\x84\xa1\x6a\x58\xb9\x89\x9b\x34\xc7\xba\xc4\x62\x1b\x39\x33\x0e\x5a\x06\x85\xe7\x69\x9a\x65\x28\xa4\xf3\xf9\xbb\x97\x19\x43\xa0\x73\xa6\x4f\x64\xdd\x46\xde\x7b\xd1\xa0\xbc\x77\x85\xb9\x2b\x66\xbf\x2b\xa5\xbc\x8f\x0e\xe1\xa5\x24\xb7\x75\x52\x86\x24\xb9\xcb\xdd\xcf\x68\x4b\xfa\xd6\x3a\x2f\xe5\x29\x6e\xc0\x0e\xac\xd3\x27\x32\x6d\xfc\x67\x40\x04\x2a\x88\x80\x7b\x68\x07\x03\x9e\x1d\xc9\xd0\xe6\x97\xf1\x2c\x29\x69\xe4\x4d\xe6\x1d\x54\x77\xb6\x3e\xa9\xd5\x38\x4c\xcd\x6d\x4d\xf0\x14\xdb\x77\x54\x27\x76\x46\x48\xa5\x1d\xcd\x38\x6e\xf0\xe3\x49\x0b\xb9\x4a\x7b\x5a\xd9\xa4\xa8\x12\x0e\xff\x1d\x2e\x52\x00\xa1\xe0\xd3\x4e\x0d\x21\xed\x94\x1c\x06\x59\x23\x3b\x38\x67\x1d\x86\x69\xd6\x72\xb1\x31\xdb\x9a\xa4\x7e\xf4\xaf\xf9\xc2\xec\x13\xba\x67\x9e\x94\x4c\xf4\xe8\xd6\xf2\x46\x78\x09\x99\xcf\x0b\x32\x93\x66\x8c\x3d\x2d\x55\xd4\x47\xe8\x22\xf7\x54\x57\x1e\x8a\x09\xbf\xda\x15\xd5\xd1\xb3\xde\x6b\x4e\xd7\xa1\x98\xee\xcb\x26\x4f\x34\x8e\xaf\x65\x6e\x2b\x5b\x3c\xa8\x92\x58\x04\x7e\xc8\x4d\x02\x2c\x98\x50\x81\xd9\x80\xab\xe4\xb2\xf8\xaa\x9c\x00\x2c\x06\x3f\x36\x90\xe1\x9b\xf4\x9b\xb8\x5f\x13\x9c\x07\xc1\xfd\x15\x6c\x23\x2b\xe9\xb4\x69\xa0\x40\x52\xf3\xb1\x05\x12\x27\xca\x24\x4e\x2c\x86\x81\x15\x0d\x84\x7f\x7a\x2f\x09\x0a\x65\x11\x49\x7d\x48\x11\x91\xda\x07\xb6\x62\x5b\x19\x45\x0d\xed\xb0\xec\x77\x14\xfe\x24\x43\xee\xce\x20\x20\x0d\x59\x04\x6c\x0f\x5e\xc1\x30\x0d\x99\x68\x39\xfe\x7f\x60\x3b\x71\xf2\xbb\xa3\x60\x7a\x9b\xfe\xf3\x29\xfa\x86\x4b\xcb\x56\xc0\x7d\xeb\xd5\xaf\xf9\x8d\xfb\x4f\xd1\x17\x03\xc0\x81\x8c\xae\x72\x3d\xfc\x67\x80\x05\x22\xe9\x88\x7d\xad\xdc\xa2\x59\x86\xc4\xcd\xc8\x4b\xf7\xdd\xda\x24\x6a\x4a\x6b\xaa\xa3\x80\x22\x45\x52\xfc\x72\x4b\x23\x09\x43\x3e\xe0\x22\x5e\x89\x44\xc7\x52\x01\xd5\xe1\xef\xa2\xae\x12\x47\xbe\x31\x0d\x2f\x8e\x5f\xb3\xf7\x51\x6a\x28\x07\x61\xf2\x74\x8a\xc8\xd5\x07\x34\xbb\xab\xbd\x1d\x92\x27\x95\x11\x66\xf1\xd6\x22\x66\xf0\x56\x9d\xb3\x79\xd5\x5a\x52\x30\xe4\x90\x64\x2d\x42\x78\xc5\x71\x38\x87\x44\x62\x21\x2e\x63\xd0\x64\x18\x86\xa1\x27\xe3\x41\x4d\x2a\x25\xd2\x87\xc6\x63\xc6\x2d\x4e\x40\x5b\x56\xff\x57\xf3\x4f\x7e\x78\x6a\xf7\x44\x63\xf9\x30\xe2\x09\xdd\x33\x4e\x4a\x0e\xef\xc6\xb8\xd0\x77\x04\xdf\xe1\x3e\x3c\x50\x83\xd6\xfb\x85\x1e\xba\x86\xda\x8d\xa5\x04\x18\x7d\x87\x7e\x13\x3b\xdc\x38\xff\x5e\x04\xb2\x36\x06\x24\x90\x90\x46\xce\x24\x3e\xe8\x92\xdd\xca\x46\x5a\xdc\x2c\x21\x48\x2f\x1d\x31\x61\x2d\xa5\x0c\xa6\x40\xe3\xed\x78\xc4\xf8\x49\xb5\x3b\x6d\x92\xac\xf9\x48\x26\x92\x75\x52\xa1\x48\x9b\x84\x60\xa6\xa3\x13\x5a\xa6\xbc\xfc\x98\xaa\xef\x28\x9f\x74\xf8\x8a\xe5\x20\x65\x99\x75\x01\x95\x27\xb7\x19\x5d\xd7\x55\xe6\x6d\x5b\x14\xb8\x41\x08\x8f\x81\x87\x84\x93\x15\x8f\x81\x74\xa5\x85\x89\x02\xb8\x4d\x2a\x31\x6b\x14\x67\x8d\x17\x11\x47\xf8\x57\x85\x3e\xa0\x71\x02\x1e\x03\x7e\x16\x63\x67\x4d\x24\x4d\xcf\x8c\x93\x42\x98\x97\x88\x5b\x83\xd6\xc9\x19\x34\x08\xbd\x7c\x46\xe0\x59\xd6\x41\x94\x66\xc2\x86\x06\x9f\xff\xf4\x31\x7c\x17\xe1\x62\x0d\x80\x4d\xc6\xba\xb5\xbb\x4d\x6d\x07\x86\x4f\xa7\x89\x23\xab\xc4\xbc\x4a\x21\x4b\xb4\x1d\x92\x9a\xe4\x2b\xb9\xb9\xc7\xf7\xbe\x6f\x9e\xae\xdf\x20\xa7\xeb\x72\x2a\xd6\xac\xcb\x6d\x3d\x4b\xb3\x84\x66\x17\x9b\x80\x2d\x02\x17\x7b\x3e\x4f\x20\x93\x41\xa2\x84\xfc\x19\xc4\x10\x1e\x19\x22\xc9\x80\x9c\xc6\x69\xb9\x07\xa6\x1d\x30\x8e\x8f\xc7\xc5\xb4\xd5\x54\xd8\xd5\xfb\xe0\xad\x4c\xe7\xc7\xfd\x77\xc0\xe9\x6f\xeb\x9f\x6d\xbe\x29\x6e\x66\xa9\xf8\xde\xfe\x63\x96\x31\x13\xfa\x17\x1f\x7c\x8f\x79\x73\x71\xff\xf3\xfa\xd9\xc5\xcc\x14\x03\x7a\xf4\x31\x5c\xda\xa6\x12\xd5\x46\x64\xea\x5b\x78\xd3\x69\xd2\x4f\x66\xe6\x1a\x6a\xad\xad\xec\x10\x26\x90\x9c\xa2\xdc\x2f\xbe\xa2\x72\xe3\xf8\xad\x5f\x76\x95\xa7\x15\xbc\x62\x8e\xf5\x92\xb4\x02\x79\x7a\xf0\x33\xeb\xf1\x96\x0f\x9f\xb4\xdd\x79\x58\x8e\x50\xed\xd2\x5f\xa9\x46\x0e\x8e\x0c\x7d\x35\x99\x0c\x82\x52\xd6\xc6\x07\x33\x99\x0c\x52\x30\x1e\x80\x26\xe0\x3f\xe2\x4d\x71\x0a\x27\x14\xd2\xc4\x1a\xac\xe0\x2a\x25\xf1\x7a\xe0\xa4\xde\x69\xe7\xb7\x73\x8c\x7d\x97\xde\x06\x9b\xdf\xfa\xf3\xfd\x67\x39\x4d\x73\xd8\x54\x7d\x8e\x7e\xd2\x72\x46\xd1\xdb\xfa\x57\x30\xcc\x42\x7d\x41\xc9\x20\x10\xf4\x00\xc0\xa5\xb9\x49\xc0\x07\x56\x18\xd6\x70\x99\x2c\x26\x1a\x63\xc7\x88\x10\xad\x12\xa5\xe6\x5e\x21\x0d\xb6\xc2\x8f\xf7\xfe\x92\x58\xc1\x27\xe6\x58\x1f\x43\x8e\xea\x78\xfc\x5e\xdf\x90\xe9\xf7\x92\xe9\xf7\x5a\xb3\x26\x36\x52\x8a\x6b\xe8\x70\xd8\x68\x92\x44\x49\xb3\x36\x1f\x34\xc7\xca\xf6\xfc\xa5\x77\x9c\xe8\x8f\x5a\x47\xc8\x4d\xd2\xff\x76\xda\x49\x57\x31\xfe\xe2\xc0\x68\x8e\x83\x9d\x2d\x2c\x00\x3c\xf0\x81\xb3\xcc\xae\x17\xe3\x6e\x99\xcc\xad\x98\x44\x70\x77\xd9\x18\x4c\x12\x61\x48\x7a\x2a\xc9\x6e\xc4\x6a\x80\xa5\x09\x31\xe3\xfd\x7c\x19\x33\x01\x06\xa3\x02\xb4\xaa\x69\xf5\xea\x7b\x98\xce\xb8\x7e\x7d\x49\x54\xf3\xf3\x8d\x56\x29\x20\x8c\x39\x00\xd8\x93\x85\x67\x08\xd7\xd1\xa9\xc5\xbd\xc3\x04\xdb\x21\x99\x8e\x8c\x2b\xef\x8a\x4c\x47\x30\x6d\x91\xf9\xec\x81\x93\xf3\xfa\xd6\x4d\xc6\x5b\xd8\xd4\x7d\x7b\x6c\xb3\xad\x7d\xd7\x53\xf5\x31\xec\x0c\xbe\x97\xd8\xe5\x8c\x43\xda\x05\x39\xf0\x52\x77\xfa\x8e\xcc\x40\x25\xa3\x94\x2d\x4d\x62\x94\xfe\xa7\x4a\x4b\x72\xff\xe7\x1b\xad\xeb\x70\xe0\x31\x7d\x0c\xd3\x63\x53\x81\x03\x78\xc0\x44\x90\x75\x02\x42\x8e\x88\x5c\x49\xe4\xa6\x36\x61\x77\x23\x67\x4a\xe3\x7c\x05\xcd\x43\x49\xbf\x5d\x30\x81\xfd\x52\x45\xd3\x80\x8e\x4e\xb6\xf8\xf3\x15\x98\x86\x17\x9a\x3f\x79\x2d\xb1\x4b\xf1\x47\xc3\x37\xb1\x69\x8c\x1a\x84\x0e\x7e\x1b\xb1\xc7\x65\x83\xec\xa1\x31\xce\x74\x99\x45\x18\xa3\x90\xf7\x08\x6d\xa2\x39\x19\x49\xce\x71\xbc\xcd\x47\x5b\xe4\x58\x02\x21\x77\xc6\xd4\x97\x19\xa4\xc7\x46\x8d\x75\xb2\x51\x87\x4b\x4c\xc5\xcd\x2f\x15\xdc\x52\xfc\xdc\x63\x53\x09\x7e\x66\x58\xf1\x63\xac\xd0\x4a\x08\x32\xd3\xc4\x0e\x5f\x15\x30\xd9\x19\x1c\x30\x78\xcc\x65\x47\xa3\x02\xbc\xda\x06\x41\x0a\xce\x36\x5e\x0c\x1b\x8e\x7b\xcf\xfa\x5e\x78\xad\x2d\x25\x98\x12\xc1\xc5\x43\x31\x95\xf7\x3a\x48\x19\x87\x17\x07\xc8\x92\xd5\x98\x36\x6c\x4c\x57\x01\x1f\x01\x0e\x6f\x4c\x97\xad\x94\x5f\x31\xac\x57\x56\xa9\x45\xcd\xb7\xa2\x58\xa0\xb5\xff\xf3\x8d\xcc\x9b\x46\x24\x4c\x6c\xc7\xbc\x4f\x6c\xe7\xb5\x70\x9e\x21\x77\x52\x13\x1c\xc5\xdc\xb2\xaf\x12\x7d\x16\x47\xe8\xb3\x1c\xae\x82\x26\x56\xb2\x9f\x03\xdb\x0f\x4f\x2a\x30\xec\x56\x7a\x29\xc3\x70\x6e\xe3\x95\xb0\xe1\x98\xdf\x5a\x62\x73\x15\x00\xb2\x16\x3d\xe0\x29\x83\x59\xc5\xce\x16\xb2\x0c\x43\x5e\x8d\x4c\x27\x6d\x00\x2f\x4e\xdc\xa3\x7b\x5f\x31\xbb\xbe\x5d\xa4\xeb\x1b\x07\xca\xe6\x86\xeb\x12\x73\xb0\x94\xe0\x67\x95\x44\x4e\xc0\x4f\xfc\xbd\x1b\x7f\x9f\x75\xbb\xac\x3e\x18\x66\xb2\x82\xdd\xec\x00\xcf\x41\x4e\x70\x1b\x9a\x49\x9c\x60\x77\xb9\xad\x41\x35\x63\xc7\x86\xf7\xd0\x52\x6a\x25\xcd\xf6\x04\x79\x22\x65\x29\xa8\xef\x3d\xf9\xfc\xca\x3f\x4d\xd0\x9f\xbf\x80\x08\x58\x5e\x3e\x8f\xe9\x5c\xc8\x8a\xfd\x97\x2c\x59\xb0\x5d\xef\xda\x08\xbf\x19\x0f\x20\xb0\x01\xc0\x4c\xb3\xa9\xc0\x05\x9e\x33\x7a\x03\xec\xc5\x0e\x77\x77\x12\x39\x8a\x8d\xd9\x8c\xd1\x54\xe8\x29\x06\x14\xbf\xa0\x3b\xca\x83\x7b\x9f\x20\xe3\x73\x88\x39\xe8\xa8\x30\x3e\x87\x98\x73\xe2\xef\xb3\x4e\xc7\x21\xc7\x47\x55\xdf\x8b\x9f\xc8\xae\x63\x77\x10\x91\x31\xd2\xe9\x8e\x78\x1c\x7d\xe1\x48\x99\x77\x59\xc6\x2a\xb0\x71\x45\xb0\x7d\xf0\x4c\x7e\xe5\xa2\xcc\xae\x07\xb7\x2e\x9e\xcf\x2c\xbc\x95\x6d\xec\x3f\xf7\xc4\xf9\xb7\xf6\x8f\x63\x4e\x99\x58\xd4\xca\x5a\x00\x44\x10\x2a\x76\x58\x96\x6b\x65\x99\xcc\x6c\x86\x28\x96\xb9\x20\xeb\xfe\x8f\x64\xb0\xec\xa2\x24\x6b\x52\x20\x73\x38\xc9\xab\xa2\x0b\xa8\x28\x74\xc5\x9c\x50\xdc\xeb\x86\x48\x5b\x95\xed\x7b\x19\x00\xb8\xa4\x2d\x0a\x42\xa0\x09\x6c\xac\xca\x91\x66\xb6\x6a\x0f\x21\x43\xab\xce\x79\xd6\xf2\xad\x38\xcf\x90\x8f\x52\xe3\x22\xaf\x9c\xb3\xfb\x23\x4d\x54\xf2\x14\x48\x72\x96\xe5\x5c\x19\x23\xe8\xa8\x42\x7e\x06\x2d\x94\x82\x15\x29\xcf\xe0\x2d\x45\x9a\xc1\x2a\x2c\x67\xe5\x7d\x7e\x53\xf4\x31\x7c\x96\xef\x25\xd8\xd9\x75\x24\xd8\x51\x61\x42\xf3\xfb\x48\x97\xc0\xff\x35\x8c\x54\x51\x92\xb3\x6e\x89\x5c\x12\xfa\x25\xc4\x64\x90\x5d\xd6\x58\xd7\xe1\x60\x55\x0a\xde\x2b\xc2\xea\xd6\x52\xb0\x30\x08\x56\xa5\xc0\x81\x01\x19\x7d\x0c\x97\xe4\x66\x12\x4c\xf5\x1e\x29\xa6\x1a\x60\x42\x8b\xf8\x0a\x39\x26\xd2\x60\x4f\x68\xd0\x53\x20\x7b\xa7\x87\xdc\xb6\xfc\xef\x80\x0c\x86\x24\x59\x0b\x37\x91\xe3\x77\x96\xe5\xe2\x99\x4c\x46\xf3\xfa\x24\x59\xb3\xfb\x33\x47\x8e\xb2\x92\x85\xaa\xa0\x8c\x33\x6d\x54\x05\x65\x96\x10\xab\xcc\x3f\x45\xc0\x1b\x55\x30\xd6\x58\xc9\x3f\x45\xff\x0f\xfd\x53\x56\x0a\xd6\x61\x60\x39\x24\xad\xa6\xf6\xf0\x9e\xaa\xac\xba\xb1\xb2\x2e\xdf\xfa\xf2\x52\xce\x41\xe0\x1a\x5c\xd2\x69\xf8\xad\x13\x88\xdf\x6a\x03\x4f\x1e\x02\x63\xc3\x8f\xd6\x6f\x25\xbe\xad\xdf\xca\x86\xeb\x49\x51\x2f\xf5\x5c\x2d\x47\xe3\xb9\x06\x15\x80\x56\x01\x56\x59\xff\x62\x15\x70\xd9\x6c\x65\x96\x62\xc0\xf7\x00\xe0\xb6\x13\x8e\x81\x18\xd8\x02\xb2\x76\xd2\x2c\x1f\x4c\xa7\x49\x28\x43\x5b\xe6\x45\xb3\x65\x1e\x50\x95\x50\xfb\x6e\x2d\xe6\x2c\xa0\x98\x91\xf7\xf2\x14\x90\x93\xd2\x74\x29\xce\x42\x2e\xa0\x84\xec\x86\x46\x4a\x52\x0b\x94\x18\x7e\x4a\xf6\x0a\x8a\xa8\xa6\x0f\x05\x44\xe4\xef\x03\x9a\xbf\x06\xdb\x0b\x3f\x89\xbd\x9c\x0e\x49\xce\xb1\x9c\xcb\xdd\x14\xcc\x68\x81\xa0\x24\x6b\x22\xc9\x14\xd7\xdb\x25\x39\xeb\x72\x2b\x84\x9b\x55\x34\x22\x5d\x45\xee\x49\x07\x89\x79\xaa\xd9\xed\x7b\x3f\x3c\xf1\x0d\xfb\xb0\x7b\xa6\xd5\x54\x36\x18\xbb\x03\x0e\xdf\x19\xf8\xfe\xc0\x1d\x07\x27\x54\x31\x17\xd5\x45\x9b\xa2\x2f\x26\x7e\x3e\x64\xf2\xb0\x64\x1d\x6a\xc8\xac\xfc\x40\x02\x89\x44\x25\x5a\xe7\x4c\xc0\xe4\x23\x60\x12\x60\x42\xb3\x8b\x55\x3d\x7c\x48\x44\xb5\x7d\x00\xd5\xb6\x43\x0d\xd6\x9a\xe9\x30\xec\x81\xdc\x44\xc8\x88\x48\xa8\x7a\x49\xae\xcf\x97\x41\x50\xd6\x58\xbf\x65\xf5\x28\x46\x52\xa9\x87\x2a\xbf\xc4\x05\x9b\xc0\x1a\x0b\xc7\x3f\x42\x43\xfa\xce\x96\x0f\x73\xf3\x52\xb6\x13\xbf\x33\xe7\xb6\x80\x3e\xd2\xee\x09\x36\x6d\xe2\x7b\x0f\x9c\xfd\x83\x2f\xd9\x9e\xfd\x93\xb6\xbf\x55\xfb\xa8\x7a\xed\x15\xdc\xf6\x73\x36\x3e\x79\xf0\x8f\x00\x92\xdc\x28\xf6\xc7\x71\x70\xad\x31\xbe\xd2\x22\x21\xc2\xa0\x49\x2d\x20\x14\x5b\x8b\xe3\x4e\x22\xc1\x62\x59\x2b\x61\xba\x56\x48\x97\x31\x46\x7c\x8e\xe5\x14\xb5\x29\x98\x41\x61\x29\x67\x97\x02\x94\x87\x2d\x20\xd1\x02\x68\x20\x21\x35\x83\x1a\xc8\x34\x87\x49\xb9\x4f\x39\xee\xc9\xb8\xba\x48\xa5\x53\x69\x22\xad\x88\xd7\x9a\x7f\xb2\xec\xf8\x71\xe3\x47\xdf\x3c\x1c\x15\x5d\xaa\x31\x7b\x13\xe7\x1f\x7c\x63\xcb\x7a\xff\xda\xe0\x4e\x76\x4c\xd9\x1c\x1a\x3a\x88\xb6\xed\xa4\xdf\x31\x82\x4f\xcf\x43\xd5\xfe\xea\x92\x5a\xbd\xad\x78\xdf\x31\x48\xee\x31\x6a\xd0\x5e\xe6\x38\x57\x5d\xc3\x51\xc9\xf9\xf5\x44\x0f\xa9\xed\xd8\x14\x61\x5a\x23\x87\x15\x30\x34\x38\x74\xbe\xe0\xa2\xfc\x3c\x63\x0c\x67\x57\x62\x74\x1c\x34\x86\x72\xea\x4e\xeb\x18\xea\x8d\xe6\x83\x86\xc8\xd1\xb0\x35\xf6\x44\xab\x10\x56\xde\x47\x1a\xd0\xaa\xf3\x53\x92\xf7\xa7\x9a\x8b\xe3\x0d\xce\xd1\x1f\x55\x9a\x83\xd6\xa4\x16\x13\x0a\xd9\x58\xab\x33\x91\x3b\x36\xd6\xe4\x48\xa0\x86\xd4\x20\x01\xce\x3a\x98\xc8\x47\xe8\x75\x61\xa4\x38\x3f\xb9\x66\xc1\x6f\x2f\x31\xc2\x24\xf3\xcd\xf4\x92\x30\x81\xa3\x86\x3a\x1c\x31\xbb\x32\x19\xd4\x24\x65\x6b\x38\xca\x0d\x7f\xc4\x1a\x9d\x65\xd5\xc1\x87\x98\xc7\xd6\xb2\xb2\xe0\xc3\x08\xab\x8a\x83\xb8\x71\xf0\xbc\xee\x31\xec\xb2\xbc\xd2\xbc\x1e\xd2\x2e\xce\x6a\x76\x51\x8e\xd0\x2e\x44\x66\x36\xd6\x3a\x04\xd6\x87\x24\x71\x2d\xeb\x31\xab\x08\x8a\x8d\x65\xbd\x65\x55\xa9\x3a\xef\x2f\x19\x83\xea\x72\x6e\x2c\xea\xcc\x26\xab\x28\xb2\x76\x54\x5a\xa2\x9d\x06\xbc\x7b\x39\x57\x5d\xb4\xa5\x35\x69\x10\xb4\x0e\xff\x36\x4a\xb3\xe9\x23\xd2\x9c\x3d\xbb\x73\x55\xd3\x0b\x23\xdf\x3b\xe9\x60\xf2\xae\x11\xcf\x77\xbe\x7d\xf2\xe1\xb5\x59\xbb\xb6\x8f\xf5\x67\xde\x4e\x85\xd3\xf9\x93\xfc\x13\x5e\x4b\x99\x7a\x2e\x5f\x70\x6b\x8b\xbc\xc2\xc9\x2a\x6c\xbc\x1d\x95\x96\xf4\x11\x8e\xf9\x90\x13\x39\x74\xcc\x95\xa7\x73\xd9\xa0\xd1\x1e\x8a\x97\xb7\xc2\x38\x49\xed\xb6\xd0\xc9\xbf\x07\xfc\x20\x6a\xb2\x27\x6a\x5e\xb6\x40\x25\x42\x6b\xd9\x02\xb9\x55\x22\x5d\x44\x64\xa6\x1b\xd8\x42\xde\xe9\x51\x48\xdf\x4d\x89\x8c\x26\x40\xc9\x68\xc8\x96\x7a\xef\xde\x15\x64\x4b\xf5\xb6\x7b\x51\x9d\x88\xed\x12\x96\xf6\xf1\xa8\x8e\x76\x15\x79\xc5\x9c\xd3\xeb\x20\x69\x7c\x87\x92\x60\x81\x16\xae\xc3\x11\xab\xc3\xe9\xf1\xe2\x4f\xc5\xe6\x32\x8f\x17\x1b\x2a\x50\x02\x47\xb0\xd4\x64\x14\xb5\x99\x20\xe9\x51\x88\xb9\x08\x1c\x1e\xf8\x1e\xf3\x7e\xb4\xff\xfd\x59\x8c\x3b\xda\xff\xd5\x95\x4c\x67\xbc\xff\xec\x29\x67\x18\xe0\x38\xb9\x7b\xef\x19\x57\x3d\xfc\x95\xa9\xad\x1c\x34\xba\x8e\x54\x8a\x05\x85\xbb\x36\xf8\x33\xfd\x91\x92\xee\x0c\xe2\x66\x82\x46\x30\x12\xf4\x80\x07\xa9\x06\x1d\x6a\x48\x6b\xaa\x50\x40\x4d\x29\xaa\x36\xe3\x48\x6b\xc3\x85\x02\xea\x4a\xe5\xdb\xc5\x10\xb6\x45\x3b\xf6\xef\xa3\xad\xd4\xeb\xad\x30\xa1\x49\x5e\xa2\xdb\x9e\x82\x09\xa2\x46\x97\x81\x09\x52\x89\xad\x35\x70\x94\x36\xd4\x86\x0f\xcd\x29\x39\xe7\x50\x43\xed\x94\xb0\x40\x0b\x92\x3b\x2b\x35\x44\x39\xf0\x44\x29\x07\x82\x75\x51\x1c\x78\x0d\x6f\x97\xe4\x9c\xbb\xd5\x96\x2a\xb5\x93\x37\x06\x2b\xe9\xcb\x34\xb6\x16\xf1\x24\x4b\x74\xaf\xb6\x08\xcb\xdc\x77\xf0\x71\x68\xff\xfe\xa4\x77\x6f\x58\xf5\xa8\xde\xab\x7f\x90\xe0\x6e\xbc\x65\xf4\xd5\x3f\xd8\xb0\x49\xff\xd7\xf4\x95\xfb\x9f\xff\xf5\xb6\x1b\xe6\x6d\x7e\xe3\xda\x2b\x2e\xfd\xe9\x4c\xd6\xae\xfe\xee\xef\xc7\x4e\xb8\x61\x3b\x46\xd4\x19\xf9\x8f\xe6\x2d\x5a\x76\xc3\xf3\x3b\x27\xdf\xb2\xaa\x6e\xf4\xfa\xd3\x7e\xb3\xeb\x0f\x3f\x5b\x7e\x37\x1c\x03\xf9\x1b\x6f\xbf\x57\x3f\xe6\x86\xf9\x1d\x27\x3c\x4f\xb9\x2b\xb8\x15\xe4\x3e\x52\x05\x0d\xe0\x3e\x23\xc2\x17\x5c\xe6\xc9\x48\xb5\x17\xf2\x4e\x37\xc9\x5d\x3a\xed\x05\x88\x22\xd6\x32\x5c\x11\x26\x34\x4e\x29\x68\x8d\xc5\x6a\xc6\x5d\xa5\xd0\x0c\xb9\x44\xa4\xf6\xe5\x9c\x2e\x55\x49\xe4\xdc\xf8\xc9\xe6\xa0\xd3\xad\x9a\xe5\xb5\xa2\x4b\x92\xf3\x36\xbb\xbf\x96\x10\x3f\x70\x52\x56\x08\x85\xc9\x96\xe2\x76\x4a\x32\xb2\x65\x90\x6a\x5c\xcf\xc2\x68\xa3\x24\xf2\x4a\x9c\xb5\x88\x13\x2a\xd6\xa4\x31\x3c\x1e\xbe\xa6\xdf\xff\xcf\xb7\x3f\xf8\xe2\xd6\xc7\x1f\x7f\xf9\xe7\xb7\xad\x79\xe4\xf6\x62\x56\x46\xbf\x47\xdf\x74\x49\xff\x4d\xcc\x8c\xfe\x8d\xcc\x37\x4f\x3e\xb4\xf0\x32\xa8\x0e\xce\xcb\xb0\x4f\x11\x7d\xb5\x3a\x30\xd9\x12\xb5\x69\x1e\x5b\x81\x46\x6e\x1e\xb6\x80\x5c\x94\x4f\x0e\xec\xd6\x64\x27\x11\x30\x34\xa2\x36\x72\x9a\x2e\x1e\x4e\x00\x11\xd4\x21\x1f\x2d\xd1\x18\x61\x22\xa9\x90\x37\x39\x75\xe6\xdc\x09\x27\x75\xb6\x8e\xee\x9c\xbe\x7e\x61\x68\x1e\xb4\x95\x72\x26\x17\x4c\x19\xe9\xdd\xe0\x5e\xf8\xdf\x8b\x75\xa7\x25\x55\xc2\x82\xa9\xfa\x18\x6e\x05\xa9\x35\xf0\x83\x06\xb0\x61\xc8\x5c\x35\xe0\xb9\x0a\x54\x99\x2b\x42\xa7\x40\x8f\xb6\xa1\xc3\x4d\x5b\x03\x9e\xb6\x06\x25\x91\x0b\xe0\x27\x9e\x36\x5a\xe7\x88\xa7\xcd\xe7\x32\x62\x6b\x2d\x84\x4f\xa8\x76\x87\xcd\x60\x8e\x11\x70\x70\x6a\x4c\x5d\x43\x85\xa9\x2b\xdd\x49\x58\x14\x26\x2d\x53\xd7\x61\x9e\xe7\xe7\xd3\x39\x2c\x9b\xbb\xe2\x61\x9e\x7b\x19\x4f\x22\xad\xbd\x78\x44\x1f\xc3\x5e\xc5\xcd\x04\x0e\x50\x07\xbe\x4b\xef\x4d\xb2\x2e\x3c\x65\x41\x5b\x81\xd4\xe1\x68\x41\xa3\xed\xa0\xde\x7a\x87\x52\x67\xb9\x43\x31\xa6\xd0\x8d\x07\x45\x65\xb7\x82\x4e\xe3\xa3\xf5\x1a\x25\x0c\x07\x4f\xe6\xc5\xe6\xdb\xae\x1f\x3a\x97\x96\x1b\x96\xf2\xd9\x1c\xb4\xde\xe2\xc5\x8a\x91\xea\xeb\xad\xa9\xd2\x7a\x6b\xfe\x8f\xd6\x5b\x23\x5d\x6f\x39\x21\x4c\xa2\xd7\x23\x5b\x70\xec\x50\x66\x99\x21\xab\x2e\x32\x88\x57\x66\xf0\xd2\x63\x8e\x2b\xef\x95\xc4\x6b\xef\x15\xb2\xf6\xa2\xe0\x3b\x87\x5c\x7b\xb1\x4a\x6b\x2f\x6e\x39\x26\xf9\xc9\x40\x0e\xb9\xfc\x2a\x1d\xfe\xcb\xe7\xed\x9c\x41\x07\x7f\xcb\xcc\x0d\x39\xef\xb7\x0e\xec\xe1\x3a\x84\x05\xa0\x09\xb4\x83\xcb\xa9\xd2\x99\xc6\xda\x0b\x59\x11\x4f\x62\x80\xa5\xaa\x1e\xee\xdd\xa6\x20\xb5\x0d\x26\xb4\x46\x95\xaa\x7a\xd4\xba\x25\x39\xeb\x64\xe3\x78\xdd\xd8\xa4\xad\x0e\x31\x50\x47\xd4\x35\x51\xa3\x9c\xad\x6f\x6b\x27\x3e\x90\x8d\xd3\x2a\x8e\x80\x94\x83\x6e\x85\x6a\x34\xcb\x48\xce\x74\x74\xf6\x74\x05\xca\x74\x48\xf1\x08\xdb\x61\x3c\x66\xf3\xab\x81\x60\x03\x83\x77\x96\x58\xc9\xd3\xb4\x3e\xf5\xdc\xba\x17\x2f\x5a\xb9\xf6\x9a\x1b\x3f\xf9\xd1\x5b\x9b\x4e\x3a\xf6\xf1\x53\x97\x3c\x7a\xc6\x6d\x2b\xe7\x8c\xd2\xff\x32\x00\xde\x85\xff\x65\x38\x9d\x91\xf9\xb3\x57\xdd\x3a\xf9\xda\x29\xe7\x3e\x73\xcd\xe2\x1d\xf3\xce\x5e\xd7\x34\x62\xd9\x82\x33\xe6\x4c\x3e\xe7\xe2\x1b\xcf\xfa\xe0\x6f\xb6\x09\x16\x0e\x39\xe7\xc0\x1e\x76\x8d\x2d\x5a\x36\x6e\x4e\x28\xd0\xe4\x46\xc0\x50\x33\xf1\xec\xd6\x6a\x69\x41\x2d\x3e\xbc\x37\x3a\x8d\x71\x7b\x24\x39\xeb\x22\xf9\x40\x24\x48\x5b\x9d\x95\xc6\xcd\x59\xc6\xed\x19\x34\xee\x32\x01\xd6\xee\x21\xe3\xb6\xc5\x2d\xe3\x76\x1e\xf7\xd8\xe9\x37\xde\x72\xe2\x82\x25\x97\xbd\xfb\xd3\xcd\x1b\x8e\xe9\xba\xfd\xdc\x69\x97\x9e\x7a\xf9\xd5\xdf\x1b\xf9\xc9\xce\x3c\x3c\xd7\x18\x75\xe7\x93\xc3\x3a\xce\x3f\xbd\xe7\x3b\xc7\x9d\xb2\x72\xe6\xdd\x4f\x4f\x5e\x59\x9b\xf8\xee\x09\x3d\xa7\x8f\x3d\xe1\xbb\x17\x8c\x7f\x2c\xcb\xfd\xbd\x6c\x9f\xc0\xf3\xdd\x4a\xe6\x3b\x05\xae\xaa\x38\xdf\xe9\x4a\xf3\x3d\xca\x98\xef\xbc\x93\x8d\xd3\xc1\x1a\x33\x3e\x2c\x45\x47\x9e\xab\x6f\x6b\xef\xa0\xfc\xe3\xff\xd1\x94\x97\x37\x4b\x1c\x7a\xda\xad\x1d\x13\x87\x9b\xf9\xc1\x7d\xad\x78\xfe\x2f\x24\xf3\x9f\x02\x57\x56\x9c\xff\x74\xa5\xf9\x1f\x65\xcc\x7f\xde\xc5\x19\x76\x30\x10\x60\xda\x21\x5b\xdf\xd6\xf1\xbf\x80\x80\x72\x33\x1c\x0a\x05\xe7\x5b\x8c\x70\x38\x20\x94\xd7\x3f\x81\x56\x5d\xe5\x5a\xf9\x9d\xa0\x09\x74\x83\x55\xd4\x06\xf9\x91\x54\x7b\xcf\x84\x03\x1a\x95\xd4\x5a\xb9\x02\x91\x21\x35\x50\x91\x4c\xe5\xda\x6a\xdd\xf6\x84\xd6\xe9\x29\x83\xc8\x68\x98\xd0\xda\xdc\x92\xdc\xeb\x64\xe3\xad\x23\x46\x8e\xc2\x91\x63\x67\xad\x24\x6b\x8e\x76\xe2\x20\xb2\x62\x80\x24\x81\x1b\x65\x54\x9f\x01\x5a\xbc\x55\x92\xb3\x23\x92\x9d\x99\x4c\x46\x0b\x8c\x94\xe4\x1c\x30\xc1\x22\x1d\x31\x58\xd8\x21\xea\x7c\x87\x06\x8c\xbf\x4c\xa5\xef\x90\x90\xd1\x1f\x1d\x24\xd7\x87\x31\xa3\xab\xec\x64\x6e\x66\x45\x7b\x99\x9d\x4d\x16\x7b\x95\xd0\xd3\x06\xa9\xb5\x3a\x4b\x40\x1a\x6d\x00\xa9\xd7\xc5\x95\xac\xd5\x86\x1d\x6a\x7b\x92\x3a\x96\xc3\xda\xcb\x33\xc8\x5e\x87\x47\xd5\x50\x7b\x1d\x0a\x59\xe9\x32\x6b\x1d\x12\x5b\x83\xad\x65\xf5\x33\x69\x70\x59\x45\x3f\x33\xaa\x92\x9f\xe9\x1a\xb2\xaf\xf4\x92\x7d\xa5\xad\x93\x2e\x2f\xad\xbe\xe3\x3f\xdf\x56\x06\xed\xa0\x87\xc6\xcc\x17\xd6\xcd\xf4\x90\x90\x11\x2e\x1f\xb4\xb7\x62\x1f\xb3\x9a\xf8\x98\x34\xb8\xa2\xa2\x8f\x19\x55\xc9\xc7\x74\x55\xf0\x31\xbd\xd8\xc7\xb4\x0e\xb2\xc2\x7f\xea\x62\xca\xac\x70\x28\x24\xac\xb4\xda\xe0\x90\x40\xb0\x85\x06\xd9\xe0\x7e\x5d\xe5\x7a\xf9\x5e\x20\x81\x5a\x70\x3b\xc8\xd6\xd0\xaa\x01\xfa\x6b\x30\x9d\x55\x18\xda\x6b\xab\x05\x6a\x09\x93\x9a\xc6\x70\xb4\x7a\xb4\x66\xb7\x16\x54\x4a\xc2\xea\x9c\x87\x28\x9e\xe1\x38\xb7\x54\x50\xba\x95\x04\x8d\x35\x22\xaa\xed\xc3\x7f\x31\xd0\xc7\x6a\x81\x5a\x83\xd0\xba\x86\x76\xce\x06\x25\xcd\xe1\x24\xf9\x3d\xc6\xe0\x1e\x1e\xaa\xe8\xa9\xf4\x44\x85\x28\x8c\xc3\xfb\xcb\xf0\xde\x14\x67\x3f\x6a\xd4\xaf\xd4\xf7\xbc\x00\x15\x7d\xb9\x15\xde\xb6\xaf\x37\x6c\xd8\xbf\x87\x57\x89\x4f\x38\x5e\x57\x99\x02\x3f\x11\x48\x60\x04\x40\x20\xdb\x82\x7d\x82\x9d\xfa\x84\x20\xe9\x10\xe3\x0b\x68\x44\x2a\x1b\x24\x9c\xde\x41\xbf\x23\x51\x1c\xe4\x48\x22\x24\x5f\xef\x2c\xa0\x7a\x4a\xc3\x8c\x07\x67\x12\x20\xac\xdb\xfb\x22\x19\xdc\x88\x76\x2f\x4a\xf4\xf1\x5a\x48\xda\xe7\x45\xe1\x3e\xa0\x85\x13\xed\xed\x30\x17\x0a\x27\x46\x14\x6f\xd8\xea\xdb\x24\x39\xcf\xd8\x7d\xaa\x80\x9d\x88\x9b\x93\xe4\xbc\xc3\xe9\x6f\xa4\x37\x4a\x2d\x8c\x24\x67\x05\xa2\x06\xa3\x85\xec\x92\xac\xc5\xdb\x32\x44\x47\x5e\xa9\x6c\x8b\x09\x0c\x6d\xea\xb2\x19\x7c\x99\x46\xcb\x6d\x8f\x72\x7c\x99\x75\x6a\xc4\x17\x6e\x9d\xd7\x03\xd5\x3a\xfd\xef\xb7\xca\xa9\x31\xe3\xbf\x5b\x77\x69\xeb\x0f\x7e\x28\x2f\x2e\xb7\x14\xbf\xe1\xac\x33\xfe\xb0\x7f\x79\xff\x4f\xcf\x6a\xeb\x38\x2e\x7c\xa7\x37\x70\xfd\xa2\x63\xa7\x30\x53\xb1\xdd\x9e\x07\x80\xeb\x15\x16\x00\x01\x04\xc0\x54\x90\xb5\x61\x3c\xf0\xc6\xd9\x01\xb0\xb4\x93\x8e\x54\xae\xda\x76\x6b\xbc\x52\xaa\x4d\x35\x67\x9d\xd4\xde\xd2\x3a\x5c\xd6\xac\xbd\xd5\x78\x9b\x24\x6b\x76\x07\xa9\xdf\x31\x67\x75\x50\xc0\xff\xbc\x65\x5a\x6f\x2a\x8b\xf3\x55\x3a\xab\xcc\xc4\x21\x77\x87\xd3\x07\xf6\xb0\x8b\x6d\x2a\xb9\x9f\x7e\x06\x64\x55\x92\xa7\x12\x0a\xa4\x60\x58\xb3\xf3\x05\x14\x4a\x65\x79\x3b\x9e\x60\x9e\x75\x24\x50\x24\x49\xae\xaa\x83\xc5\xe3\x4e\x04\x2f\x6c\x5f\xf1\xf6\xb9\x38\xb9\xa1\x76\x2f\xaa\xed\xe3\x35\x3b\x9e\x5c\x47\x1f\xd0\x1c\xa4\x3f\xdc\xee\xa8\x0d\x15\x27\x97\xb4\x80\x33\x19\x14\x91\xb6\xb1\xbc\xc0\x89\x6a\xb8\x89\xfa\x00\x64\xcb\x00\xcd\xab\x12\xe5\x02\x64\x2f\xb6\xf5\x22\x88\xff\xae\xc6\x84\x49\xfa\xaa\xea\x6c\x96\x22\xcc\xe9\x55\x66\x12\x8e\x31\x6a\xc4\xd8\x1d\x15\x27\x11\xba\x2d\xfc\x91\x10\x6c\xc6\xf3\xc9\xf7\x02\x1f\xf8\x11\xc8\x7a\x69\xe5\x9f\xd1\x55\xc1\x16\x34\xd6\x9e\x4a\xe5\x21\xf0\xf2\x9e\x84\xe6\xf6\xa5\xd3\x1a\x14\x0a\x1a\xe3\xc0\x53\x2c\x26\x91\x97\xd2\xa1\x9a\x65\x78\xcb\xf6\x4e\xa7\x59\x3c\x11\xb1\x7d\xc8\x43\x0a\xe4\xbd\x62\x8e\xf1\xb2\x4a\x02\x79\xc4\x9c\xc3\x63\xc7\x27\x43\xfc\xc4\xdf\xfb\xf0\xf7\x2c\x69\x20\x70\xfb\xac\x2d\xa0\x4a\x4f\x54\x89\xf6\x98\xb9\xbb\xb8\xb2\x39\x0a\x03\x97\xea\x57\x52\x00\xcc\x85\x8d\x0d\xfa\x27\x2b\x5e\xb8\x87\x59\xbf\x06\x7e\xba\x61\x83\x1e\x59\xd3\x3f\x8b\x59\x4f\xc6\xd2\x36\xb0\x87\xac\xe9\x18\xf8\xb7\xc1\x06\x60\xd2\x85\x6b\x6e\xbe\x80\xd8\x54\xd6\xe1\xc6\xb3\xed\x10\x1c\x89\x3c\x80\x75\x82\x07\x1f\xe4\xd2\x69\x0d\xf0\x05\x4d\x8c\xa5\xe8\xb5\x68\x64\x37\x6a\x4c\x91\x6e\x18\x39\x55\x64\x4a\x7d\x60\xef\xe3\x78\x6c\x1c\x6a\x6c\xe7\x11\xdb\xc7\x69\xb2\xb8\x8f\x47\xee\x3e\xd4\x28\xe6\x98\x46\x3c\x40\x59\xcc\x79\x64\xb7\x92\xc8\x89\xf8\x89\xc1\xf2\x32\xe9\xe7\x94\xf0\x6f\xf1\x5f\x8b\xe2\xbf\xc6\xe7\x62\xf8\x97\x6c\xb4\x91\xb5\xc8\x80\x48\xb2\x5b\x92\x33\x20\x27\xc9\x8d\x51\xda\xdd\xc9\xb0\x6e\x8f\x18\x93\xa2\x65\xdd\x9d\x4a\x44\xa2\xf0\x09\xd4\x49\x32\xaa\xcd\x20\x20\x69\x35\x91\x4c\x46\x73\xb8\x0d\x4e\x56\xa5\x27\xdd\x13\x37\xc0\x23\xa4\x85\xb8\x17\x06\xcb\x00\xd4\xdd\xd3\x56\xbf\xbc\x6b\x73\x09\x3a\x5d\x7b\xc3\x5f\x45\x62\x4c\x11\x3f\xae\x14\x73\xfc\xb2\x6f\x08\x70\xbe\x59\xf6\xe0\xe3\x61\x13\x39\x8d\x67\xfe\x9b\xae\xa9\x0d\x03\x7b\xf8\x25\x42\x1a\x04\xc0\x08\xf0\xb4\xb1\xa6\x5c\xac\x41\x36\xea\x13\xd3\x69\xd4\x96\x24\x1d\x9d\xd1\x54\xae\xa1\xb6\xcd\x4e\x95\x26\x83\x45\x26\x19\xa3\xd2\x8c\x85\x44\x3e\x27\x17\xe4\x58\x7b\xc2\xe0\xd3\x43\x9c\x91\x25\x72\x96\xfc\xe9\x5d\x7b\x2f\x2b\xde\xce\x7b\xfb\x90\x28\x22\xa9\x0f\x68\x5e\xa9\xbd\x1d\x92\x27\xb1\xcb\x08\x7c\xec\x76\xa9\xf4\x76\xbe\x36\x4a\x28\x35\x45\x99\xea\x0c\xb9\x8c\xd6\x24\x85\xe8\xe9\x78\xa1\x41\xc8\xab\xa4\x59\x22\x51\x59\xa9\x7b\x72\x43\xcd\xcb\xbd\xaf\x38\xbc\x77\xaf\xf8\xe9\x4b\x89\x9d\xbd\xef\x8d\xd6\x7f\xf7\xd5\x1f\x3f\x81\xcb\x2a\x4b\xb9\x2d\x39\xfd\x3a\xf6\x9a\x83\x4b\x9b\xae\x6c\xba\xf6\xb6\x67\x7f\xc6\xf6\x1e\x1c\xab\x7f\x7d\xe0\xbf\xf9\x2b\x2a\xf5\x8a\x5e\x3d\xb0\x87\x9b\xcb\x7f\x0a\x6a\xa8\x72\x42\x65\xd5\xa1\x44\x52\x0b\x0b\x05\x14\x4f\xe5\x1a\xc3\x09\x7b\x42\x6b\x11\x0a\xa8\xb6\xa8\x9a\x50\x49\x7c\xc8\xc2\x1e\x33\x54\x7f\x08\x35\xa5\xc8\xe1\xd7\x22\xae\xd5\x2e\xc9\x5a\xb8\x2d\x63\xc8\x6b\x35\xb4\x50\xe9\x31\xd4\x88\xcd\x25\x1d\x91\x04\x51\x05\xa3\x55\xd1\x1f\xf2\x56\xb4\x5a\x15\x99\xa6\x4a\x36\x23\x78\xb3\x6d\x07\x01\x10\x02\x4b\x2a\xe2\x2d\x98\xd4\x6a\x6c\xc5\x4b\xfb\x72\x7c\x59\x21\x55\x77\x34\x90\xf2\x71\x92\x9c\x73\xa9\xc1\x5a\x7a\x34\x3e\x1c\x8a\x7a\xa2\x55\x50\xf3\x5f\xe4\x3e\xb5\x1a\x48\x48\x83\xa9\xa1\xc3\x45\x78\x4b\xeb\xc0\x75\xd5\x70\x51\x9b\xd4\x42\xb6\x82\x99\x06\x3e\x12\x39\xae\x06\x63\xda\xb3\x8e\x40\xad\x41\x84\x10\xc2\x0b\xe3\xe8\xe4\xa6\x7a\xa2\xd5\xe6\xf6\x2c\x3c\xb6\x2a\x53\x49\x78\x4a\xa9\xaf\x18\x0f\x02\xa0\x09\xbc\x50\x71\xee\x62\x44\x92\x35\x5b\x1f\xc3\x6e\xb9\x3e\xe2\x48\x10\xa8\x37\x57\x99\xc9\x20\x4c\xe4\x43\x14\xeb\xa1\xe2\xbc\xe6\x1a\x45\x9f\xbd\x74\x63\x9a\xcc\x37\xd2\x9b\xd1\x96\xa3\x99\xee\x20\x67\x78\x10\x2d\x12\x92\x8e\xd0\x73\x94\x5d\x9c\x56\x9e\xfd\x4f\xca\x2e\x4e\x2b\xa3\xc0\x36\xc5\x72\x87\x6c\x62\x61\x0f\xe1\xec\x5f\x5f\x0d\x0b\x4d\x49\x2d\x22\x14\xb2\x91\x26\x6c\xb6\x48\xd4\x91\x20\x3a\xb6\x55\x84\xda\xb0\x87\xa8\xa3\xd6\xa9\x1b\x8c\x13\x14\x4d\x61\xa8\x18\xa4\x5e\x45\x01\x37\xc3\x51\xd4\x19\x1d\x6b\x48\x94\x8e\x0e\x33\x65\xa6\xa9\x82\x9e\xf3\xac\xb6\xa9\xac\xc7\x77\x82\x85\x77\x8b\x62\xe9\x43\x10\x00\x31\xd0\x0e\xb6\x56\x44\x53\x63\x52\x6b\xe1\x88\xea\x4c\x88\x2b\xca\x1a\x57\x86\x51\x9c\x1a\x24\x4e\x75\x66\xea\xe9\xef\xea\x4b\xce\xa2\xe3\xdb\xa1\xa7\x2d\x2e\xc9\x5a\x63\x28\x53\xc2\x8f\x36\xa2\x45\x92\xb5\xfa\x60\xe6\x10\x48\xb2\x08\x51\xd1\x3b\x5d\x7a\xf1\x56\x11\x53\x8c\xba\xf8\x82\xd9\x37\xdd\x7c\xd1\x45\x37\x5e\x3e\xa6\x3b\x7d\xec\xb1\xe9\x8e\xe3\xaa\x01\x6b\xe2\x85\xd7\x5e\x73\xe1\xec\x85\xd7\x5c\xdc\x35\x76\x6c\x57\xd7\xd8\xb1\xa0\xa8\x7d\x67\xbb\x03\xd4\x80\x26\xd0\x01\xb4\x6a\x08\x8b\x25\xb5\x61\x1c\xe1\xcc\xad\xe3\x8a\xf2\xf5\x15\xa1\x45\x0b\x11\x50\x73\x45\xf1\xbb\x88\xcf\x6b\x4f\x58\x88\x73\x23\x25\xe2\x5c\x0b\xce\x9a\x25\x39\x57\x17\x1b\xd6\x4e\xb3\x22\x26\xd4\x4a\x5b\x91\xd6\x3e\x0c\x23\xb1\xf6\xf0\xba\x78\x15\xac\x58\x05\x7e\xf7\x0e\x31\x63\x65\x0c\x76\x0d\x31\x22\xc5\xe2\x72\x61\x01\x08\x80\x46\x30\x1c\x2c\xad\x84\x45\x93\x56\xbc\xfa\x76\x34\xe2\x68\xb7\xa3\x5e\x97\x1a\xac\x8b\xc6\x86\x1b\xb9\xa3\xe6\x23\xf2\x51\x43\x6b\x02\x2a\x7b\xaa\x7f\x0c\xae\x09\xa8\xb6\x65\x0d\xad\x08\xa0\x98\xda\x61\xf0\x6e\x8e\x38\x84\x32\xe8\xc8\x23\xde\xba\xda\x2b\x28\x49\xd6\xc7\x48\x58\xb7\x55\x56\x1a\x22\x71\x53\x4b\x72\xc4\xb7\x10\xce\x4c\x1f\x46\x42\x13\x4e\x1b\x64\x8c\x6a\xaa\x92\x43\x8b\x23\x18\xb0\x41\x9f\xc8\x2f\xe1\x7b\x41\x00\xb4\x82\xe7\x2c\xc8\xc0\x1f\xf2\x21\x9a\x60\x28\x79\xac\xe6\x64\xbe\xd1\xa0\x1d\x18\x56\x19\x2f\xa8\xa1\x71\xb7\xa4\x05\x3d\xa4\x0e\xb3\xc1\x53\x06\xa1\xb6\xa3\x82\x50\x83\x24\x6f\x75\xa9\xa1\x70\xac\x99\xc4\x34\x6a\xa3\x24\x6b\xc1\x86\x4c\xe6\xf0\x28\x1a\xdc\xd5\x5f\x19\x42\xb5\x65\x0c\xb4\x95\xf1\xa3\xb7\x95\xd1\xcf\xe2\xfd\x8e\x68\x3e\x4d\x02\x35\xa0\x0d\xac\x33\xd8\x0c\xea\xd2\x55\xbc\x52\x6b\x32\x1f\x33\xcc\x35\xbc\xba\x16\x67\xa3\xa7\x80\x1a\x2b\xc2\x2a\x51\xee\x77\x1a\x25\x19\xb5\xe2\xc5\xd4\x2b\x2b\x75\xf5\xb1\x26\x6a\x98\x40\x4c\x92\xb5\xda\x46\x6c\x98\x23\x15\xe4\x2c\x37\x4f\x15\x54\x3d\x69\xb5\x4f\x45\x48\xe9\x97\x5b\xad\xc3\x80\x8f\x00\x10\xee\x12\x16\x80\x7a\x90\x00\x3f\x00\xd9\x7a\x83\xe1\x01\x90\xea\x1a\x39\x5d\x94\xba\x80\xce\x02\x82\x06\xe3\x46\xbd\xa7\x80\xea\x93\x1a\xeb\xc1\x5f\x91\xf2\x22\x6f\xa0\x80\x8f\xe4\x4e\xfc\xa7\x35\x81\x02\xaa\x49\x6a\xce\x00\x95\xbe\x60\xeb\x25\x59\xe3\x6d\x99\x0c\xaa\x91\xf2\x8e\xba\x86\x48\x02\x2f\x2b\xa7\xac\x45\xdb\xb0\x0b\x06\xf5\x92\x9c\xe5\xbd\x35\x64\xfc\x4a\x5a\x09\xaa\x42\x5a\xee\x81\x69\x25\xe0\xa7\x1f\x60\x9c\x6d\xe9\x8a\x7b\x21\x8c\x97\x77\x45\x7f\x94\xaf\x67\x9c\xb6\xd9\xdd\x70\xf5\x8b\x6d\x4e\x68\x9b\xd1\x0a\x6f\x7d\xad\xff\xd2\x97\x46\xda\x6d\xca\xc9\x7a\xe7\x76\xf8\x71\x19\x21\xd9\xc1\x3b\xce\x9e\xbb\x0e\x3a\xaf\x62\x67\x1c\xdc\xf4\xf8\xf2\xa9\x90\x3b\x8f\xbd\x76\xff\x24\x76\xcb\x8f\xd6\x8c\x7d\xf2\x60\xb0\x9c\xa4\x8c\x60\x66\x21\x00\xb6\xa0\x2d\x4a\xec\x72\x99\xc5\x2e\x70\xb0\x5d\x44\x62\x17\x8e\xd8\x25\x40\xec\xc2\x05\x0a\x88\x49\x61\xd3\x04\x61\x42\xf3\x78\xa9\x1d\x82\x24\xf7\x66\x8e\xdf\x23\xe5\x9c\xfe\x68\x1b\x95\x40\xc3\x26\xe0\x4a\x26\x50\x85\xf4\x78\x06\xa6\x95\xa0\x5f\x30\x14\x3f\xd8\xd6\xae\xb8\x6f\x88\x05\x16\x22\xd9\x69\x77\x7d\x67\x22\xb4\xbf\x1e\xe7\x18\xfb\xa8\x4b\xbf\x78\x55\xe7\x7e\x13\x61\xec\xe9\x33\xf5\x4f\x77\xc1\xb9\x16\x03\x70\x93\xfa\xcf\x3c\x71\x5b\xc3\xeb\x6b\x98\xee\xfe\xfc\x37\x63\x46\xae\xfb\x9a\x09\x1f\xe8\x65\xa6\xac\x7c\xe9\xa6\x97\xfa\x1f\xe6\x7e\x53\xce\xd1\xb6\x1d\x00\xee\x7d\x61\x01\xb0\x83\x00\x58\x0e\xb2\x02\x20\xbd\xef\x14\x13\x90\x35\xba\xc6\x85\xdd\x9a\x4d\x29\xe4\xa0\x4d\xb0\x27\x4c\x0e\x16\xe8\x2c\x25\xe3\xb6\x7c\x29\x17\x55\x36\xed\x7d\xb4\xb3\xff\xc5\x1d\x2f\xfd\x73\x34\xfe\x56\x13\xec\x76\x04\xf0\x1f\x78\xb1\xf5\x98\x3e\x90\x65\x78\x3b\x69\x92\xa6\xbf\xd2\x6e\x79\x88\x0f\x16\xce\x00\xed\x7f\x55\xd2\x0a\x4c\x43\x36\xae\xb0\x65\x56\xd8\xbe\x6d\x0b\xfc\xe4\xfd\xfe\x15\xf3\x5f\x58\xd4\x5d\xce\x41\x17\x67\x3e\x3e\x78\x69\xff\xa7\x4c\x33\x67\x2b\x1b\x9f\x45\x73\xb6\x05\x5c\x52\x49\x73\xb6\xb5\xa8\x39\x3b\xec\x68\x34\x43\xed\x02\x5e\xd5\x24\x32\x3b\x1a\xf5\x59\xeb\x68\xaa\x8b\x84\x96\x53\x17\x54\x55\xa1\x2d\xc7\x31\x6b\xcc\x65\x1b\xb0\x03\x05\x44\xc0\x86\x0a\xb3\x89\xa4\x24\xaa\x4f\xe7\xdd\x54\x48\x35\x48\x45\x00\xab\xcc\x6e\xce\x41\xbe\xf0\xaa\x84\xad\x4c\x85\x09\x2d\xa4\x96\xda\x47\xfe\xf3\x29\xb7\x4c\x73\xb8\x8a\x8c\xaa\x65\xbe\x6b\x86\xc8\xa6\x96\xcd\xfa\xca\x4a\x7a\xc3\x7b\x00\xe0\x1e\x30\x74\x8c\xda\xcd\xca\x14\xb3\x8a\x90\xd0\x53\xa8\x49\xec\xd2\x68\x1f\x3e\x82\x19\xe2\xcc\x89\xe8\x52\xbc\x07\x46\x7b\xa2\x42\x59\x43\xb8\x5a\xc7\xae\xea\xbf\x31\xce\x5e\x18\x3e\x78\x35\xb3\x25\xaa\x7f\x69\x5c\xbb\xaf\xe4\x96\x6e\x5c\x7d\xe0\x56\x6b\x67\x38\x33\xf0\x29\x00\xec\x72\x5b\x94\xfc\xec\x11\xe6\xcf\xe6\x8d\xba\x4d\x96\x1f\xfa\xb3\x11\x2b\x0d\xfa\xc9\xa5\x46\xe2\x48\x2d\xb3\x59\x6f\xab\x63\x1e\xae\xef\xbf\x88\x71\x86\x7f\x6f\xfc\xe0\x9b\xd8\x53\x96\xdd\x7b\xf0\xfd\x65\x83\xfa\xcf\x8c\x71\x77\x01\x07\x50\xc1\xd8\x0a\xe3\x46\x72\x52\xf3\x38\x0a\x10\xf9\x93\xc8\xb9\x5b\xf3\xb9\x0a\x5a\xe0\x30\x56\xb0\xb4\xe5\x0e\x32\xc3\x9f\x8d\x4e\xd8\xa2\x15\x4c\xa6\x1a\x6a\x83\xa5\xfc\x67\xe4\x3d\x26\x56\xb0\x41\xe5\xf7\xd0\x7c\x4e\xbc\xa3\x32\x99\xcc\xa1\x6c\x53\x7a\x9f\x41\xc6\x79\xdb\x78\x1f\xd3\x38\x84\xf7\x87\xbe\x4f\x09\x0f\x35\x55\xf0\x50\x9b\xd4\x42\x87\xc5\x43\xd9\x3d\xc2\x60\x50\x2c\xb0\xde\x25\x98\x36\x19\xda\x87\x44\x6c\xf3\x0a\xc1\x47\x4d\x15\x7c\x0c\x7a\x97\xa1\x36\x18\xf4\x26\x83\xec\xa0\xaf\xb0\xbe\x89\x69\x8d\x41\x75\x3f\x50\xd7\x75\x95\xbd\xc2\x16\x01\x41\x30\x0b\x20\x3f\x55\x5b\xf6\x26\x35\xbb\x40\x78\x7d\x8a\x84\x3e\x1f\x7e\xf9\x71\x51\x0e\x94\xef\xd3\x64\x69\x1f\x8e\x09\x73\x1c\x2f\xc9\xb4\x05\xd7\xfc\x64\xb4\x17\xfb\x25\x19\x91\x88\x9a\xb8\x44\x64\x97\x91\xab\x48\x7c\x42\x2a\x46\xa9\x9e\x99\x40\xfd\xa2\xae\x8f\xed\xba\x63\x24\x54\xdb\x9e\x7a\xa2\xeb\xb2\x78\xc7\xa4\x71\xe7\x4e\x0f\xea\x7f\x1e\xf6\xd4\xb2\x13\x8f\xd1\x77\x04\x0b\x7c\xe4\xb5\xa7\x6b\x7c\xcb\xeb\x2e\xbe\x76\xff\x7b\x2f\x6f\xf1\xd3\x3a\xc7\x81\x3d\x44\x77\xbb\x1e\x0c\x07\x1f\x1b\xb5\x56\x35\x26\x0d\xad\x64\x32\xd0\x56\xe3\x64\x4c\x50\x4a\x17\x4a\xc4\xd8\x4c\xa9\xab\x8a\x27\xa8\xf5\x7b\x5f\x23\xf7\x0e\x3c\x6d\xc8\xb1\x89\xc8\xdd\xc7\x23\x28\xe6\x38\xc8\x2b\x09\xe4\x16\x73\x82\x9b\x10\x2d\xba\x09\xd1\xe2\xbc\x7f\xee\xa2\x44\x8b\xf8\xb7\x59\x97\xdb\x42\xb1\x08\x34\x97\xdb\xe8\xbf\x76\x5a\xfb\xaf\x09\x37\x4c\xce\xe3\xad\x21\xc4\xb7\xcd\x52\xd6\x21\x91\x16\x30\x55\x46\xf6\x0c\xd0\x5a\x01\xf9\x53\xd5\x68\x83\x29\x51\x2c\x5a\x98\x45\x0d\x4d\x6e\xa1\x4c\x91\x3b\x03\x6d\x2b\xeb\x57\xb6\xe6\x5b\xe1\xbd\xf5\xfa\x55\x4d\x23\x79\xfb\x9c\xa7\xcf\xbd\xe7\xb1\x1f\x7d\xfd\xd0\xf9\xf7\xb7\x38\x4f\x58\x76\xd9\x9c\x59\x9b\x66\x6d\x39\x7f\xc7\x55\xdc\x87\xcb\x7a\x7b\x97\x3d\xb1\xd9\x75\xf3\x45\xaf\x67\xdf\xd7\x1f\x7d\x67\xd6\xf4\x4d\x70\xe6\xdc\x85\x44\x95\xfb\x65\xfd\x33\xba\x9f\x6c\x04\x80\x9f\x42\xfa\x9b\xe2\x60\x04\x78\x15\x50\x89\xb4\xb0\x29\x05\xa6\xda\x0b\x9a\x32\x22\x95\xca\x37\xc5\x65\xd6\x43\x12\xf3\xe6\x99\x2c\xe0\x25\xa2\xb2\x11\x1c\x2e\x92\x62\x7c\x24\xe0\xa0\x69\x98\x5a\x40\xc3\x92\x9a\xa0\x96\x12\xf2\x1b\xf6\xfe\x86\x52\x42\xb5\xa3\x11\xed\x48\x16\xb5\x70\xed\x3e\x34\x42\xd4\x94\xda\x7d\x28\x2c\xe6\xe2\xe1\x11\x4a\x22\xd7\x84\x9f\xec\x56\x59\x09\xc7\x9b\x46\x94\xd4\x5e\x02\x80\x5e\x5b\x44\xa4\xac\xcb\x59\x43\xaa\x6d\xe2\x61\xda\x1e\xd5\x24\x11\x19\x18\xa4\xca\x59\x20\x18\xd1\xd6\xa8\xee\x74\x94\xec\x2c\x82\xbf\x01\xfa\x55\xae\x0d\xc2\x78\xcc\xaf\x06\xe3\x2d\x30\x6a\x54\x05\xf6\x98\xe5\x81\x1b\x9f\x7d\x14\x66\x3f\xfc\x68\xcb\xba\xf9\x37\xeb\xbf\xd2\x0f\xe8\x23\xa1\xdc\xfc\x88\xf3\x61\x2f\x8c\x43\x66\xcb\xf6\x95\xcb\xfe\x14\xfd\xe2\xc1\xfc\x4d\x2b\xdf\xe7\x56\xdf\xf3\xe0\xe6\x27\x57\xf6\xd5\x3b\x23\x0f\xcf\xff\xe5\x57\x7c\xed\xfd\xcd\x75\x75\x07\xc7\x3e\xb2\xea\xea\xeb\xd7\xde\xb5\xf8\xc2\xb9\x26\x47\xb0\xa1\x99\xa2\x80\x9b\x0c\x4d\x35\x90\xd6\xdc\x76\xab\x2c\x86\xe2\x22\xb2\x18\x76\xb2\x33\x20\xdf\x6e\xcd\xae\x14\xf0\x06\x61\xa5\x55\x2d\xa9\x63\xb8\x6b\xa9\x3a\x46\x2d\x51\x52\xe3\xdd\x9c\x92\xc8\x29\xee\xa2\x3a\x86\x5b\xb1\xd4\xb1\x2b\x6e\x72\x07\x6e\xaa\x64\xa4\x1b\x25\x95\x8b\xb6\xa6\x1b\x25\x3c\xd0\xb3\x61\x17\xf3\x87\x78\xff\xae\x0b\x56\xc2\xed\xfa\x2e\xfd\xaf\xeb\x9f\x87\x97\xdd\x7c\x3b\x22\xaa\x18\xfa\x9a\x3f\x1e\x5c\x07\x7b\xae\x9e\x67\xac\xb7\x0d\x86\xce\xfd\x18\x63\xbd\x29\xa6\xd8\xbd\xdb\x14\xbb\xe7\x92\x1a\x14\xa8\x76\x69\x23\xe1\x95\xa1\xda\xa5\x6e\x45\x92\x35\x7b\x20\x63\xbe\x83\x70\x78\x20\x4f\x62\x23\xd1\xfe\x07\xda\xe5\x94\x50\x0d\xc3\x36\xf5\xc1\xdf\x9c\xdb\xe7\xad\x8a\x60\x06\xac\x18\xd8\xc3\x4d\xe2\x7b\x81\x17\x84\xc0\x03\x06\x4b\xb5\x6c\xa0\x17\x71\xe9\x3c\x5f\xe3\x66\x4d\x9b\x87\xad\x4c\x38\x96\xf4\x0a\x3e\xf1\x38\x94\x52\xb6\x7f\xd7\x97\xbf\xa2\x8e\x90\x0a\x22\x73\x22\xaa\xed\xe3\x51\xad\x98\xe3\x6b\xf1\x1c\xd4\xd4\x12\x5d\x64\x8d\x21\x37\xb8\x0c\x5f\x64\xf8\xd6\xfc\x9c\x24\x6b\x6e\x99\xd4\x20\xc8\x92\xac\x01\x47\x29\x85\x47\x0c\x01\x2c\x89\xa6\x68\x9c\xb5\xad\xf0\x7d\xd4\xbb\xf4\x97\xbf\xfd\xa7\xfe\xdb\x2f\x3f\xd8\xb5\xed\x86\xeb\x37\x3c\xaf\xef\xfc\xa0\xc7\x0b\xd3\x13\xc6\x72\xf6\xfe\x07\xfa\x72\xbf\xd7\xbf\xde\xf4\xf4\xcc\x69\xcf\x3d\xf4\xf1\x00\x38\x05\x8f\x77\xd9\xc0\x1e\xae\x93\xe8\x1a\xc6\x8a\xab\x35\x28\x14\x68\x0d\x71\x83\x50\x40\x6c\x12\x71\x69\x53\xda\xd4\xef\x2c\xa0\x58\x0a\xf9\xcb\x86\x1b\xc6\x2b\xb6\xd4\x9d\x39\xfe\xd1\xbd\x7d\x96\xe1\x72\x78\xbc\xb1\xbe\x17\xc7\x3f\xb4\x77\x0b\x69\x08\x8e\x89\x39\x3e\x86\xc7\x1d\xc5\xcf\x6c\x34\xc6\x59\x1a\x82\xf9\x0c\xc8\x31\x7c\x34\xd6\x6e\x04\x7e\x51\xd3\xfb\x91\x4c\x8c\x60\x97\x83\xb4\x17\x50\x73\x35\x98\x7a\x88\x39\x60\xf7\x0a\x46\x77\x01\x39\x1e\x97\xc3\xc4\xa2\x51\xe7\x65\x96\xd5\x7e\x98\x3f\xb3\xb3\xd6\x31\xeb\x99\xa9\x6b\x1f\xbd\xfb\xc0\x93\xf9\x77\xf2\x3b\xe7\x3e\x79\xf1\xd4\xe9\x93\xd6\xdf\x90\x84\xf3\x4e\xbe\x86\xfd\xa7\xfe\xc3\xdd\x27\xdf\x30\xe7\xb5\x97\x77\xea\x0f\xbd\xfa\xd6\x8b\x7b\x1e\x87\x6d\x0f\x2d\xb8\xfa\x86\x9d\x1f\x02\x38\xf0\xcd\xc0\x1e\x6e\x01\xbf\x13\xd4\x80\x71\x20\x1b\x34\xd9\x4d\x48\x55\x92\x93\x46\x02\x38\x2e\x56\xfc\x05\xba\x09\xb3\x41\x5a\x62\xe3\x94\xb2\x90\xb4\x9b\x22\x91\x72\x32\x92\x56\xcb\x26\xfa\x4e\x42\x17\x7e\x59\xda\x42\x14\xb3\x4f\x5a\xbe\x1a\x41\xf7\xda\xbe\x27\x57\xe7\xa6\xfd\xe4\xd2\xaf\xa1\xfa\xbe\xfe\xd0\xa7\xef\x8f\x5b\x7b\xca\x5b\x70\xfe\xaf\x5e\xfc\x70\xcc\x63\xd1\x7a\x7d\x97\x7e\x50\x1f\xd0\x8f\xfd\x07\xed\x27\xbd\x6f\x60\x0f\xbf\xd7\xf6\x31\x68\x02\x67\x82\x6c\x0c\xbf\x53\x3d\x5b\x40\xf5\x22\x8a\x60\xe7\xd9\x68\x46\x2a\x01\x96\x34\x1d\x3b\x2d\xad\xf0\x7e\x52\x54\x00\xb4\x40\x44\x92\xb3\x40\x09\x15\xc5\x4f\x91\x8f\xbe\xa6\xd1\xc0\xd2\x43\x0a\xa1\xfc\x78\xeb\xf5\x41\x2b\x7b\x3c\xd1\x43\x25\x02\xa8\xd7\x9e\xe7\x0d\xdf\x30\xe7\xc4\xe1\x3d\xc3\xda\xbb\x7c\xc7\x9c\xfc\xc4\x59\xe5\xca\xb4\x54\xfe\x34\x3c\x71\xd1\x35\x81\x07\x94\x51\xc7\xed\x6f\x1d\x69\xd1\x41\x05\x90\x68\xe6\x6c\xb1\x45\x40\x1c\x4c\x06\xd9\x28\xd9\x2f\xcc\x6e\x25\x95\x86\x16\x8e\x52\x19\x78\x0d\xad\xfd\x06\x5a\x38\x2a\xc9\x28\x92\x41\xaa\x94\x05\x72\x03\x69\xb0\xe7\x28\x65\x9a\x43\x22\x91\x83\x21\x82\xda\xd3\x6d\xbe\xbe\xc0\x0e\xd1\x43\x25\x02\xa8\xe3\x8e\x49\x8e\x7c\x77\x62\x62\xd4\xf0\xce\x4e\xcf\xd4\xeb\x16\x96\x49\xa1\x12\xf1\x53\xe7\xa7\x7f\x0d\xae\x91\xbb\x8e\xd5\x6f\x1a\x6b\x11\x41\xfd\x7f\xda\x97\x86\xf6\x25\xde\xf3\xb3\x7c\x2f\xe9\x9e\xb9\xb5\x64\x03\xbf\x69\x03\x2f\x1e\x73\x03\x1e\x33\xed\xc6\x10\xbd\xc5\x16\x0c\xbc\xad\x37\x0e\xda\xd6\xdd\xed\xa8\x81\x0c\xdf\x5f\xbb\x0f\x35\x88\x9a\xa7\x76\x1f\x9b\x73\x7b\xfc\xc5\xf6\x0b\x11\xd0\xf6\xdf\x90\x84\x70\xbc\xe4\xf5\x13\xf5\x5e\xb9\xb4\x63\x9b\x03\x2d\xee\xd5\xc5\xf1\xe2\x3d\x7a\x35\x54\x61\xe4\x17\xfa\x4d\xfa\x01\x7d\x6d\x71\x8b\x7e\xe4\x67\x70\xf8\xe3\x6f\xbf\xb6\x05\x6f\xce\xfa\xaf\xf4\x3f\xea\xfb\xf5\xf9\xbf\x31\xb6\xe6\xf1\x39\x78\xfa\x2f\x3f\xf8\x90\xea\x7c\x02\xc0\xad\x25\x9c\x79\x2a\xb8\xd3\xe0\xa9\x72\xa4\x35\x9f\xbd\x80\xc4\x54\x56\x60\x48\x89\x9a\x21\x97\x9f\x67\x65\xa7\x40\x99\xd3\x59\x3b\xe5\x5c\xf6\x17\x05\x7c\x03\x83\x44\xac\xc4\x76\x64\x6f\xc7\x66\x21\xc4\x97\xa2\xc6\x8b\xfb\x90\x28\xe6\x38\x91\x57\x12\x39\x09\x3f\xd9\xad\x1c\x6f\x77\x88\x92\x65\x86\x65\x5f\x31\x6d\xda\x14\x4d\x2b\xd1\x9e\x28\x8c\x62\x97\x17\x4d\x2b\xf1\x98\x6d\x16\x3c\x11\x76\x2f\xbd\xb0\xff\xbe\x38\x1b\xd5\x7f\xae\x6f\xdb\xf5\xfb\x97\xa0\xba\x6e\xfe\xad\xef\xee\x82\xf3\xfe\xfa\x0d\x7c\x7b\xc3\xfe\x49\xdb\x5e\xfc\x25\x23\xfe\xc4\xd0\x1e\x7e\xcb\xa6\x82\x00\x88\x83\x0b\x41\xd6\x47\xd8\xca\x49\x2f\x9d\x55\xba\xcc\x95\xd4\xdc\xa5\xee\x6d\x5a\x64\x47\x52\xc1\x5e\x0f\x6d\xd9\xf6\x05\x25\x79\x2b\xe7\x76\xa9\xb4\xc3\xc2\x2b\x65\x45\xa9\x9e\xd6\x34\xab\x84\xf5\x4a\xcc\x64\x2c\x82\xb5\xe3\x21\x79\xe7\xca\x7a\xa2\x54\xa8\xd6\xa9\x8e\xed\x5f\x13\x65\xc3\x95\xc4\x6a\x0d\x8d\xda\xef\xdc\x0c\xe5\x07\x87\x88\xd4\xd2\x3c\xdd\xb4\x81\x3d\xdc\x52\x9b\x0a\x22\x60\x38\xb8\x14\x64\x1b\x48\x1d\xa5\x8d\x84\x94\x32\x1e\x49\x82\x94\x10\x35\x3a\x49\xba\x56\x80\x09\x2d\xec\x23\x8a\x02\x78\x30\x01\x1a\xe0\x6b\x8d\x5e\xea\x57\x04\x29\xcf\xb9\x6a\x1a\x62\x64\x0b\x92\x35\x79\x18\x19\x57\x03\xf5\xf2\xc3\xa4\x3c\xf4\x06\xc2\x31\xb2\x13\x4d\x80\x46\x0d\x65\x3b\x2c\xd6\x92\x36\x40\xbf\xc8\xe3\x20\xd2\x16\x8f\x29\x6a\x70\x3c\xa4\xe3\x9c\x76\xca\x85\xb7\x67\xe6\x9c\x17\x4e\xcf\xba\x6b\xc1\xed\x5f\x6e\xb8\xf1\xc5\x8b\xfa\xf7\x5f\x70\xe6\xce\x27\x5f\xbd\xfb\x9e\x5d\x9f\xdc\x36\xff\xe1\xde\x99\x4b\x32\x6d\xe7\x9f\x36\xec\xb8\xb1\x67\x5d\xfd\xdb\xdb\x1e\xd3\xef\xba\xe4\x85\x05\xfa\x69\xd7\x9e\x7e\xdf\x59\xf7\x3c\xcb\x31\x6f\xdc\xd8\xf6\xe9\x96\xdb\xef\xfb\x94\xec\x05\x76\x00\xb8\x38\x89\x19\x6f\x32\x98\xad\x5c\x69\x0d\xb2\x05\xc4\xa4\xb2\x0e\x8c\x4c\x67\x5a\xb3\xb3\x05\x24\xa4\xf2\x3c\x07\x1c\x9e\x04\x62\xd3\x44\x58\xd1\x96\x82\x84\x55\xdb\x80\xe4\xc3\x7b\x11\xa5\x97\x6a\x47\xce\x76\xc4\x88\x9a\x4b\xda\x87\x9c\xa2\x26\x48\xfb\x10\x23\xe6\x58\x46\x50\x12\x39\x1b\x7e\xb2\x5b\x19\xd6\x26\x38\x5d\x65\xec\xf9\xb4\x74\x8a\x4c\xac\x3d\xce\x24\xaf\xea\xff\x3a\xc2\xb8\x2f\xea\x7f\x3f\xc6\xfc\x49\xdf\xb9\x81\x71\x3e\x4e\x90\x07\x18\x30\x65\x60\x0f\xcf\xf1\xef\x81\x5a\x8a\xb9\xa0\xb1\x7b\x15\x77\xd4\x7c\x94\x0d\x8a\x9e\x84\x16\x2d\x79\xff\x90\x9f\xf0\x21\xd8\x60\x42\x53\x54\x0a\x39\x5b\x48\x92\xf3\x9c\x5b\x0c\x36\x92\x6c\x69\xb4\x9e\xde\x79\x3a\x59\x1c\x3b\x29\x94\x47\xd2\x63\x2e\x91\xee\x71\xd0\xba\xeb\xaa\xe4\x72\x81\x44\x50\xa0\x27\xde\xc8\x4d\x81\x5b\xe1\x2f\xe6\x0a\xbd\x4f\xfd\xcf\x2f\x6e\xd8\xb9\xe8\x5f\x50\x7d\x4f\x5f\xfb\xcb\x9d\x9f\xbc\xb9\xe8\xf2\x3e\x18\x3b\xf1\x2a\x1d\xe9\x5b\xe1\xf1\xfb\xfe\x30\xbc\xb5\xfe\xb5\xdf\xce\xdc\x94\x6a\xd1\x77\xeb\xff\xee\xd7\x4f\xdd\xbf\xf5\xa9\x69\x17\x42\xee\xf3\x07\xe8\x9e\x3c\x71\x60\x0f\xb7\x89\xdf\x09\x5a\xf1\xa8\x9a\x4d\x11\x60\x17\x29\x57\x15\x0a\xf9\x9a\x70\xb3\xcb\x93\xd0\x6a\xec\x45\x41\xef\x7a\x95\x14\x72\x62\xf8\xf9\x4d\x6d\xef\xc6\x66\x49\x46\x71\x12\xeb\x80\x58\x26\x83\x6a\x64\x8d\x63\x33\x19\x24\x4b\x9a\xe0\xcb\x64\x90\x0b\x9f\x59\x88\xbf\x9b\x00\x4d\x88\x05\x4a\x95\xba\x63\xa0\x10\x6f\x94\x8a\xfb\x74\xcb\xc4\xf7\x3e\x63\xe6\x2e\xb8\xfe\x93\x55\x37\xe7\x16\x4d\x3d\xef\xc1\x0b\xee\xfc\xf1\xda\xfb\x7a\x1b\x5f\xd5\x13\xf7\xad\x7a\xeb\xc3\xfc\x17\x9f\xee\x87\x33\xf3\xbf\x88\xd9\x43\x0f\x5e\x7e\xeb\x2b\x17\x1f\x33\xf5\xe6\xe3\x3b\xd6\x2c\xb9\xfc\xaa\x87\xf5\xbe\xcb\x6f\x98\xf3\xd4\xd9\xaf\xe3\x71\x0d\x8c\xd3\x55\x72\x26\x51\xc1\x42\x50\xec\xaf\x45\x52\x52\x63\xd8\x02\xf2\x24\x69\x10\xe4\x4f\x16\x5d\x1b\x2d\x3f\x73\x22\x5b\xbb\x17\xf1\x7d\x3c\xf6\x6c\x5e\xe4\xed\xe3\x87\x76\xd3\xf2\x5e\x7c\xe4\xe5\x6d\x0e\xa7\xc7\x6b\x71\x6f\x8c\x44\xf5\xcd\x3d\x94\x03\x95\xa5\x0c\x15\x66\x55\x1e\x71\x19\xad\xaf\x27\x87\x8f\x3f\xc5\x0f\xa7\x31\x7f\x8a\xf6\xbf\x7f\x05\xe3\x8e\xf5\x7f\xb9\xa9\x69\xe5\x2d\xb1\xe3\x15\xfd\xfd\xda\x33\xa6\xdb\xa6\x6d\xe8\xff\x66\xc3\xc1\x3d\x9b\xd7\x2a\x6e\x3c\x37\x40\x57\xb9\x19\xfc\x4e\xd0\x08\x5e\x00\x59\x0f\xd1\x25\x17\x0a\xa8\x81\x26\x31\x42\xf8\xa4\xaf\x05\xf9\x02\x44\xd1\xa4\x16\x2b\x2e\x87\xe7\x8a\xcc\xad\xce\x3e\x2d\x2c\xee\x43\x81\x3e\x9e\x12\xdb\x38\xf1\x69\xfe\xa9\xbd\x9f\x93\xd3\xbc\x03\xff\x96\xc7\x47\xd0\x60\x38\x40\xd4\x43\x02\x4a\x22\xeb\xe0\x9d\x96\xd3\x7d\x9e\x77\x38\x03\x74\x9b\x86\xdb\xf0\x80\x03\xc1\x90\x75\xd7\x86\x40\x63\xb0\x47\x69\x24\xdb\x1b\xc8\xa0\x20\xa9\x45\x56\x24\x24\x65\x90\x47\x46\x62\xa6\xa3\x53\xa2\x57\x63\xf1\x09\x8c\x25\x2d\xe2\x83\x69\x21\x4e\x19\x2f\xc6\xf6\x8c\x3f\x2f\xf8\xce\xcb\xee\xf7\xc2\xcd\x5b\x36\xb6\xce\x4b\x26\x27\x8d\x3b\x77\x7a\x4d\x64\x4f\xf8\xef\x3b\x87\x3d\xf9\xc3\x93\x8f\xd1\x77\x04\x17\x5c\xc7\x6a\xa7\x4e\x5c\xf1\xda\xd3\x8a\xba\xbc\x6e\xf6\xc2\xfb\x96\x1d\x1c\xf3\xea\x33\x7e\x1a\x4f\xda\xba\x6c\x1f\x83\x61\xe0\x2e\x5a\x91\xac\xd5\x99\x31\xa4\x9f\x2d\xe4\x1b\xa3\x2d\x9c\x27\x81\x62\x69\x1c\x5a\xa2\x48\xaa\x18\x54\x52\x51\xa3\x5a\xff\x50\x25\xa3\x48\xbb\x17\x35\xf4\xf1\x5a\x0c\xcf\x7e\xbc\x0f\x68\x0d\x71\x7c\xce\x69\x88\xc4\xe2\xa5\x31\x37\xd6\x49\xb2\x56\x0b\x32\x19\xcd\x1f\xa5\x9b\xfb\x61\x42\x51\x12\xcb\x0d\xd5\x31\x22\xea\x45\x2b\x97\x2a\xe1\x1b\x2f\x9e\x38\xbc\xa7\xb5\xbd\x4b\x1c\xb3\xf3\xf9\x2a\xfa\x57\x54\xbc\xa8\xf9\xcc\x85\x34\x2c\x1d\x00\xd3\x07\x6b\x18\x01\x06\xac\xd6\x55\xbe\xd5\x88\x6d\x7e\x08\xa8\x21\x78\x57\x3a\x8d\xe4\xa4\x16\x64\x8b\x0d\xa6\x7e\x5f\x81\xde\xf1\xf0\x4e\x42\xc9\x85\x63\x1b\x9f\xb7\x18\xdb\xf4\x3d\xf6\xef\x50\x31\x17\xc6\x92\xda\x63\x5b\x1f\xd0\x58\x1b\xe1\x3e\xb5\x19\x67\x1c\xde\x2f\xc9\x9a\x1c\xcc\x90\xa9\xaf\xc3\x83\xd7\xec\x84\x90\x91\xa3\xc7\x1c\x5f\x9d\x71\xcc\xe9\xee\x61\xd3\x4a\x20\xd8\xdd\x03\xd3\xb0\x58\x6e\x40\xf6\x9b\x56\x2f\x5c\x7d\xe3\xb5\xaf\x6f\x9b\x17\xb6\x1d\x33\x1b\xbe\xf8\x41\x7f\x4d\xea\x81\x5b\x67\x5c\xb5\x39\x99\xec\xf6\x9f\x3c\x5a\xff\x6a\xce\x3f\xee\xe5\x3e\xea\xf7\x6c\x79\xe0\xfe\xa7\x99\x6f\x0e\xd4\xbe\xbb\x6a\xc3\xcb\x37\x5f\x7e\xca\x2d\xe7\x4d\x9b\x7c\xe9\xa3\x94\x27\x7c\x60\x8f\xed\x43\x9b\x0a\x46\xc0\xf1\xc6\x1e\x32\x22\x4d\x6e\xb7\x70\x28\x9e\xad\x81\x20\x81\x6a\x0d\x31\x9e\xd6\x92\x18\x0f\xcd\xe0\x8c\x70\x16\xd0\x88\x32\xc6\xc9\x66\x43\x8c\x47\xf6\x34\xdb\x13\x74\x97\x4d\x92\x16\x46\x0f\xd5\x32\xa9\xb5\x94\x59\x9a\xba\x3c\x13\xa4\xaf\x1b\xa8\xad\x62\x22\x8a\xf7\x69\xa2\xb4\x8f\xd0\x4c\xad\xdc\xfb\x03\xb3\x66\x3f\xd8\x87\x6a\x45\x14\xea\x43\x23\xc4\x1c\x3b\x82\x70\xec\x92\x27\x4f\x9e\x36\xf2\x4c\xe0\x67\x36\x31\xa2\x9a\x74\xcf\xb1\x2e\xd6\xe6\x13\x83\xa1\x58\x3c\x61\xa8\xf6\x18\x74\xe2\xd5\xfe\xa0\x48\xc2\x84\x84\x0c\x6a\x94\x50\x6b\x06\xc9\x32\x72\x66\xb4\x1a\x8f\x24\x6b\x2a\xe1\x16\xaa\xa9\xaf\xae\xea\x43\xae\x6d\xbb\xe9\xed\xb6\x51\x49\x6d\x91\x3c\x31\x85\x7d\x9e\x39\xef\x96\x3b\x03\x63\x3c\xaf\x2f\xbc\x3d\x7e\x4f\xef\x8a\xf4\xef\x3e\x78\xf6\x65\xf7\xb1\xf2\xb2\x29\x0f\x5d\xdf\x38\xdb\x50\xf6\xb9\xfe\x92\xd5\xcb\x46\xcf\xd7\xff\xde\xd5\xfa\xcc\xca\x4d\xcc\xbd\xfd\xb3\xbe\xf8\xc5\x23\xab\x86\x8d\x87\xe9\x29\x5d\xab\x16\x7e\xf2\xb0\xde\x8a\xe7\x71\xee\xc0\x1e\xa6\x96\xf4\x4e\x9c\x4e\xa3\x39\x7a\x89\xcd\x80\x04\x91\x49\xa0\xf7\xd6\x48\x28\x1d\xe4\x5d\x29\x4d\x81\x09\x8d\x15\x24\x19\xf9\xc8\xf2\x73\x64\x80\xe6\xf0\xd1\xd0\x87\x95\x34\xe0\x1a\x74\x05\x6d\x54\xf4\xce\xf5\xff\x79\xeb\x5f\xc5\xb9\xdd\xe7\x44\x2f\x6d\x59\x7c\xeb\x47\xc9\x4b\xb8\x13\x0f\xe4\x4f\xe9\x58\x10\xbe\xd3\xe7\xbf\x91\xec\x1b\x84\x3b\x9f\xe8\x0c\xdd\x6b\x61\x87\x97\x69\x50\xa2\xd9\x39\xfc\xc3\x8d\x88\x44\x63\xc5\x74\x5a\xe3\xed\x05\xcd\xe6\xc1\x07\x06\x7a\xe1\x61\x25\xbd\x24\xfc\xf0\x42\x9f\x26\x89\xfb\x48\x8e\xb5\x3c\x20\x41\x92\x98\xf3\x48\xa4\x04\x1a\x3f\x59\x90\x63\x04\xb7\x64\xd6\x33\xdb\x04\xb7\xc7\x8c\x9f\xcd\x70\x25\x3e\x01\x2a\xf1\x9e\xb4\xc1\x0f\x8f\x7d\x68\x50\x68\xf3\x6f\x99\xbf\x39\xbe\x69\x2e\xe5\x86\xbf\xf4\x99\xf8\x33\x57\xae\xf7\xcf\x6e\x63\xa4\xc7\xe0\x9e\xd6\x39\x73\x5a\x75\xf5\xb1\xfe\x7f\xb4\xcd\xc6\x76\x9e\x0a\x00\xdf\xc3\xbf\x0e\x02\x45\xde\x00\x39\x90\x4e\x67\xed\xe4\xf6\x8c\x49\xa7\x35\x8f\xbd\x60\xb2\x68\x07\x9c\x24\xc3\x69\x72\xfa\x56\xa5\xcc\x0e\x88\x39\x36\x80\x31\xec\xc7\xcf\xac\x3f\x30\x84\x33\xd9\x4f\xfc\x86\xdf\x0a\x4a\xd5\xec\xfd\x25\x45\xc8\x76\xc9\x42\x96\x6d\xf1\x9a\x94\x36\x9b\x92\x65\xc3\x17\x4f\xba\xea\xb8\xce\x64\x7b\x63\xf3\xc4\x63\xf4\x6b\x0d\xd6\x6c\x42\x96\x0d\xdf\x38\x75\x82\xb2\xda\xd9\x36\x46\xbf\xd2\xe0\xcc\x26\xbe\x81\x70\x43\xdb\x22\xa0\x06\x3c\x6a\x8c\x55\xad\x49\xa7\x49\xe6\x1c\x39\x93\x1a\x67\x27\xe9\x20\xbb\x91\x0a\xc1\x67\x75\xe7\x10\x7e\x6c\xaf\xd1\xa8\x5d\x23\x22\x77\x5f\xce\x53\x83\xa7\xca\x4b\x9e\x41\xfc\xcc\x06\x6b\xdc\x96\xc1\x7a\x32\xc8\x9b\x01\x79\xe8\x0e\x1a\x71\x01\xb4\x7c\xa6\x3b\x87\x44\x98\xb2\x03\x99\x8c\xc6\x39\x0d\x19\xdc\xb4\x71\x5d\x80\x87\x2c\x30\x36\xa1\x44\x1a\x0d\x7d\xb1\x1f\x5e\x1b\x3f\x41\x4a\x4c\x38\x27\x34\xbb\x39\x6e\x65\x8f\xe6\xc1\xfa\x25\xb2\x63\x8d\xba\x48\x1f\x79\xef\x7c\x0b\x39\x36\x1d\x37\xe1\x26\x76\xe1\x1d\xc0\x88\xab\xab\x5e\x13\xb8\xad\xcd\xea\xa6\x1a\x9b\xa7\x5c\xe3\x60\xb0\x0e\x93\x4b\xcc\x09\x2e\x72\x3d\x80\x9f\xac\x95\x9b\x54\x73\xe1\xf1\x31\x6c\x26\x43\x85\x95\xec\x19\x53\xa0\x4a\x49\x13\xb4\xf6\xac\x5b\x5a\xbf\xf4\xbe\xfc\x9a\x65\xf5\xcb\x1e\x62\x76\x2d\x63\x9e\xef\x3f\x65\x59\x7f\x82\xdc\x17\xad\x30\x7a\xc8\xe2\xa0\x09\x86\x8c\x37\xaf\x49\x13\x66\x10\xcd\x6f\x2b\x20\x20\xe2\x58\x07\xb1\x49\x24\x26\x73\x8a\xe8\xf6\x26\x34\xc1\x48\x10\x71\xbb\x49\xed\x0a\x2d\x60\x45\x2d\x21\xa8\xb1\x5c\xfb\x3b\x40\xe3\xd8\xf6\x77\xa0\x26\x4a\xf8\xb3\x24\xb6\xbf\x43\x36\xb7\xc5\xdf\x44\x8a\x2b\xb3\xbe\x4f\x93\x43\xfb\x90\xd2\x87\x17\x26\x64\xea\x95\x84\xc6\xd4\xdb\x11\x2b\xe6\x18\x56\x52\x12\x2f\x2a\xcd\xaf\x91\x60\x09\x71\x62\x8e\xe7\x44\x25\x91\xf3\xe1\xa7\x26\x2b\xe4\x2f\xc9\xe4\x2f\xf5\x5d\xf4\xcd\x3e\xf2\x97\x18\x31\xd7\x80\xff\x8d\x2c\xcf\x89\x16\x58\xf8\x32\x59\xc8\xd4\x5b\xbe\x68\xc8\x80\x6d\x90\xe1\x7d\xb2\x52\x5f\x14\xa3\x82\x43\xbe\xa1\x80\x61\x83\x92\xac\x35\x36\x91\x3e\x49\xe4\xc8\x74\x74\xc6\x61\xab\xd0\xda\x83\xb1\xd2\xda\x8d\x61\xd3\x13\x14\x94\x62\xdc\xdc\xca\xb6\x74\xe1\x65\xb3\x80\xb9\x4a\xdc\xd5\xfc\x49\xd3\xb9\x63\x87\x07\x27\x9e\x7a\xf5\x6d\x8d\x3f\x6b\xfe\xe5\x42\xcf\xb8\x68\x2c\x7d\xdc\x79\xe7\xba\xda\xe4\xb1\x63\xf4\x0d\x0c\xcf\xa5\x97\x1c\x77\xd3\x89\xd3\x9c\x2b\xa5\xef\xcd\x39\x76\xf1\xf1\x07\x99\xcb\xdd\xcb\x02\x17\x5f\x01\x6f\x5f\xb3\xfe\xa1\xcb\xfa\x57\x72\xa7\x90\x75\x74\xd7\xc0\x1e\x21\xcb\xf7\x82\x56\xf0\x4f\xda\x23\x82\xc2\x69\x72\x4e\x40\x8d\x69\xcd\x69\x2f\x20\x7f\x8a\x78\xea\x3c\xe7\xf5\xd5\x86\x9a\x82\x69\xf3\x9c\x20\x28\x65\x2e\x9b\x33\xaa\x8a\x68\x02\xba\x0e\x1f\x5e\x03\xe4\xf0\x5a\x0b\x13\x5a\xc8\x52\x9c\xf5\xf7\xaf\xa6\x0e\x4a\x40\xf3\x7d\x2f\x8e\xbf\x73\xef\x5c\xb3\x57\xc6\xd3\x47\xa9\x07\xcd\x2c\xad\x13\xef\xaf\x35\x7d\x20\xcf\xf0\x1e\xb1\xc6\x58\x79\xa5\xcf\xc5\x8c\xac\xe6\x6c\xce\x90\x53\xbe\x1c\x23\x2d\x97\x3e\x59\xf3\x37\x66\x32\x5a\x18\x87\x73\xf5\x0d\xa6\x16\x43\x1e\xd4\x37\xc4\xe2\xd6\x1c\x6d\xa9\xbc\xab\xf4\x11\xc6\x7b\xe2\xb6\x78\xac\x15\x3f\x5a\xee\xf2\x7d\xd4\xfb\x91\x7b\xfa\xb4\x47\x5f\x1a\xf9\xc6\xb6\x8f\x3c\xe7\x9c\xbb\xe6\xe5\xd4\xf6\xbc\xbe\xf3\x0e\xd1\xbe\xa4\xf0\xc7\xd1\xf6\x47\xfb\xd7\x21\x38\x72\xdc\xb1\x9c\xfb\xc0\x57\xa3\x47\x4c\xbf\xf0\xd5\xf7\xd9\x47\x0f\x7c\xd5\x9d\xfa\xde\xac\x77\xff\xc6\x5e\xbb\x7f\xd2\xa6\xed\xef\xbe\xfb\x2c\x80\x03\x63\x74\x95\xe4\xa6\xea\xc0\xa7\x20\x2b\x62\x1b\xfb\xd2\xf4\xec\xe2\xf1\xa6\x49\x45\x3b\x53\xd2\x98\xf7\xfa\x4a\x82\x3b\xe5\x87\x17\x4d\x09\xe1\xa8\xbf\x44\x76\xe9\xc1\x67\x01\x7c\x92\x21\xb1\x89\x49\x76\xe9\x14\x73\x2e\xa7\x47\x49\xe4\xdc\xf8\x89\x1d\xb9\x1a\x50\x88\x23\x57\x88\x23\x57\x2c\x98\x55\x33\x59\x97\xd3\x83\x3f\xb9\x33\x60\x1b\xef\xf6\x07\x9c\x2e\x45\x2d\x85\x21\x4e\xde\xe6\xf6\x95\x7f\x59\x3c\x21\xd4\x4a\x32\x0e\x10\x45\x72\x42\xb0\xc9\x9a\x5d\xca\x94\xce\x47\x65\x9c\x98\x8c\x60\x9c\x93\xde\x4c\xb6\x4d\x38\x55\x85\xd3\x06\x11\x62\xf2\x89\xd0\x07\xd1\x7b\xae\xa5\xc7\xa5\x33\xa7\xd9\xa6\x59\xe8\x30\x5b\xf4\x83\x37\x1d\x1c\xf6\xc8\x2a\x7c\x72\x02\x16\x6e\xbf\x90\xc9\x90\x5e\x4e\x80\x89\x7c\xc9\x22\x6d\xe1\x10\x0e\x4c\x1f\xbd\x24\x40\xde\x22\x1d\x26\x01\x6c\x91\x37\x66\x30\x3b\x6a\x8e\xe5\x5c\x72\x05\x4a\xbf\x78\x15\x26\xbf\xfd\x5b\x0f\x0e\x66\xf0\x3b\x63\xce\x81\xeb\xb9\x75\x95\xb8\xfb\xf8\xf7\x80\x07\x04\x40\x04\x4c\x1b\xcc\x08\x56\xcf\x16\xf2\x41\xbf\x8b\xf3\x90\xcc\xed\x20\xfe\xbe\x90\x85\xbf\x2f\x44\xb9\xef\xd4\x20\xe5\xde\x94\x68\xd2\xa1\x3e\x68\x2a\xb1\x0f\x65\x06\x03\x3d\x51\x5b\x4f\x94\xbe\x3d\x18\xcc\x04\xb6\xe3\x95\x27\xb7\x42\x7b\xd7\x41\x64\x8b\xb2\xa7\xf2\xdb\x36\xe4\xf5\xaf\x2a\x11\x80\xed\xf8\x0d\xac\xfd\x6a\xf4\x87\xa9\x96\xbe\xff\xd1\xbf\x32\x79\xb0\x6c\x5b\x6c\x2a\x08\x82\x66\x30\x1d\x64\xfd\x24\x7b\x6e\x8e\x26\xc6\x16\x90\x33\x49\xae\xd6\xf0\x6e\xec\x2f\xa0\x1a\x7a\xc1\x2a\xf9\xc9\x2d\x9b\x16\xa9\x91\x64\x8d\xf3\x53\x5a\x27\xc1\x87\x8d\x1f\x0b\xe3\xb3\x86\x4f\x22\x0d\xa1\x4e\xce\xec\x7c\x35\xe4\x63\xc7\x43\xca\x93\x19\xf0\x57\xe2\x3c\x23\xa3\x5a\xf3\xf1\xf1\x67\x7c\x4f\x79\xd3\x1e\x7b\xec\xbe\x44\x05\xa2\x33\x63\x58\xf3\x2f\x8d\xdc\x71\x73\x60\x99\x36\xe6\xba\x1f\x55\xa2\x37\xa3\xb9\xd6\x81\x2f\xf8\xa9\xdc\x5e\xd2\xbb\x31\xd5\xa8\x63\x0d\x99\xe9\xc8\x68\xe9\x2a\x83\x30\x84\x52\x56\x5f\x51\x21\xb7\x1a\xe4\x62\x48\xe3\x54\xda\x37\x60\x23\xa4\x36\xd1\x90\x24\x67\xbd\x40\x2c\xde\x73\x14\xd3\x90\xa5\x41\x55\x22\x35\x9b\x75\xff\xbf\x1f\xfe\xf5\x95\x67\x7c\x5f\x79\xdd\x1e\xdd\xb0\x3a\x3a\x98\xc9\x8c\x32\x97\xad\x8c\x2e\x5b\x12\xbc\xfb\xb9\xee\x29\x73\x87\x30\x98\x95\xf8\xca\x76\xf1\xef\x81\x08\x18\x09\x36\x95\x3c\x11\x39\x59\xc5\x8d\xf9\x22\xfc\x5c\x06\x5b\x4f\x3b\x19\x59\xa3\x9f\xe4\x25\xf1\x54\x19\xcd\xee\x62\xc9\xe1\x2b\x30\x81\xa4\x14\xd1\x66\xf1\xa6\xb4\xa4\xe1\xb7\x9e\xd8\xfb\x67\xda\x25\x48\x4a\x70\x69\x39\x2e\x53\x2a\xc1\x6d\x6d\xc4\x86\xa9\xcf\x64\x50\xad\xa4\xd9\x82\x99\x8c\xe6\x13\x25\x59\x73\x90\x85\x37\x3c\x2e\xc9\x5b\x81\x5b\x09\xd6\xda\xa8\xb3\xc6\xb3\x5e\xa4\xeb\x2a\x8a\x34\x1a\xb3\x1f\x1b\x3c\xfb\xaf\xc3\xc9\xef\x41\xe1\x47\x53\x7e\x71\xc9\x7a\xe4\xfd\xcd\xb6\x8f\x3c\x5b\x7f\x72\xe7\xa8\x9c\xbe\xe3\x83\x01\xfd\x0f\xaf\xbf\xf4\x93\x55\x85\x25\xb9\x87\xee\xdf\x8b\x11\xe0\x82\xb9\x3d\xbd\x67\x5f\xf0\xc4\x43\x27\x8e\x3d\xb0\x97\xf3\x76\x77\xe5\xef\x58\xbc\x5e\xff\x42\x9f\xfa\x47\x98\x80\xe2\x6b\xbf\xde\x09\xe7\xfc\xf2\x95\xdf\xfe\xdc\xc4\x81\xae\xf2\x9f\x73\x33\x89\xed\x9e\x03\x86\xcd\x0c\x1c\x98\x9c\x66\xfe\x14\x12\x93\xc8\x97\x2e\x5a\xce\x59\xb2\x9c\xf3\xc8\x2c\xf7\xc8\xde\x17\x8e\xde\x72\xc8\x4f\x92\x33\x0e\xc3\x7a\x79\xb7\x12\x04\xb5\x94\x5c\xa8\x1c\x62\xd4\x84\x30\x0e\x4d\x13\x56\xc3\xda\xce\x59\xc7\x6d\x38\xf3\xb6\x3b\x3c\x03\xa0\x17\x02\xef\x1d\x8b\xce\x0e\xaf\xfe\xf2\xc1\xde\xf7\xb7\x5d\x79\xd9\x05\x8f\x9d\x7b\xe9\xb4\x22\xe4\x56\x9f\x36\xf9\xbe\xa5\xa3\x4f\x3c\x70\x2a\xf7\xdc\xd8\xee\x7b\x2f\xfa\xee\x85\xaf\xe8\x28\xfb\xfb\x97\x7f\x70\xe7\x6a\xe8\x7c\x62\xe1\x72\x82\x3c\x7a\x37\x13\xe7\x7b\x09\x5b\xd6\x1a\x90\xf5\xd0\xbb\x19\xa3\xfc\xdb\x5e\xd0\xbc\x0d\xa9\x54\xde\x15\xf0\xb0\x9e\x84\xe6\x32\x08\xb3\x3c\x54\xf0\x07\x34\xee\x96\x08\x17\x9c\xdb\x70\x7d\x16\xba\xac\x75\x7b\xb7\x9b\xdb\xa0\xb7\x0f\xb9\x09\x5d\x96\xcb\x4d\xe8\xb2\xdc\x84\x2e\xcb\xe5\x2d\xd1\x65\xe1\x63\x09\x52\x33\x9a\x9b\xd2\xb6\x52\x79\xae\x2c\x10\x94\xf2\x1a\x0b\x10\x8d\xb3\x71\xcb\x95\x4d\xa9\xaa\xe2\xd6\x5f\xff\x4e\x7f\x5e\x7f\x73\xe9\x0d\xbd\x50\x8e\x93\xfb\x9a\x87\x6e\xfd\xe0\xa3\x1f\xdd\xbd\x8e\x5b\x7d\xcf\x83\xaf\xbe\xf2\x6f\x7d\x5f\xff\x9b\xf4\xae\x46\x5f\x98\xdf\x7c\xe3\xe5\x80\x19\xf8\xa5\xae\x72\xe3\x6c\x11\x10\x05\xed\xa0\x97\xb2\xe1\x69\xcd\x42\x81\x0a\x4d\x27\x84\x02\x02\x49\x14\x4d\x0f\x3e\xb6\xd0\x76\x9d\xa8\x44\xa8\xf0\xda\x8c\x2b\x80\x8e\xf2\x82\x0a\xf3\x04\x13\xa5\x27\x98\x28\x3e\xbb\x34\xe2\x67\xb6\x31\x5a\x7e\x76\x01\x39\xe8\xf6\x34\x1a\x72\x03\xc6\x27\x02\xa5\xb6\xa8\x24\xe7\x05\x9f\x12\x8a\x91\xdd\x23\xd1\x2c\xc9\x79\x31\x50\xdf\xe0\xc3\x3e\x97\x03\xc6\x1e\xc2\x5a\x8e\x31\x3e\x68\x1b\x5c\xfd\x60\x13\xd8\xb2\xfa\x87\x91\x70\x61\xe3\x92\x1b\x8c\xc3\x8d\xbf\x2e\x69\x9f\xfd\xec\xf7\x57\xac\x5f\xb1\x77\xcd\x79\x6b\x12\x4e\x41\x9e\xfd\xfa\xbc\x4b\x66\x6d\x9a\xb5\x65\xfa\xab\xd7\xe9\xaa\x6d\xcf\x23\xb7\xe3\xc3\xce\x4d\xb3\xee\x7c\xec\xc6\x8b\x7f\xa6\xfd\xb7\xfe\xf0\x8e\x0b\x66\x5c\x7a\x96\xde\xc2\x4e\x9a\xb7\x80\xd4\x43\x64\xf5\xff\x8f\x68\x7a\x0c\xa4\xb9\x59\xe4\x7e\x33\x00\x7e\x6c\x9c\x21\x3c\x69\x53\xd2\x23\x1b\x80\x94\x9b\x23\xef\xf6\x02\x0c\x21\x77\xe9\xb4\xeb\xa1\x69\x1e\x4b\x36\x08\x6f\xfc\x36\x4b\x3f\xbe\x59\xa1\xe2\x11\x73\xac\x87\x21\x7d\xd9\x44\x29\x88\x3c\x03\x1e\x2a\x46\xed\xf6\x06\x4c\x1c\xc9\x8c\x24\x67\xed\x4e\x17\x25\xf7\x20\x6b\xce\x4b\xeb\x54\x50\x80\xae\xb6\x34\x4c\x0b\xe9\xa1\xc4\x5d\xf8\xbc\x9b\xb8\xdb\xa0\xea\xda\x3b\x75\x11\xa1\xea\x7a\x94\xef\x7d\xaf\x48\xcf\xa5\x5f\xcd\x24\x0c\x52\x35\x48\xf8\x47\xd2\xfc\x4e\x30\x0c\xc7\x07\x24\x07\x1a\xb5\x17\x28\xdd\x84\x97\x2d\xe6\x3a\x1b\x94\x02\x6a\xa0\x14\x6a\x01\x95\xa4\x3d\x35\x57\x83\x24\x6f\x15\x24\x25\x14\xa7\x04\x0a\xd1\x16\x49\x46\x4d\x38\x40\xce\x01\x31\x80\x03\x60\xa4\xc8\x48\x22\xa0\x1f\xcf\xf5\x8c\x67\x68\x09\x40\x2b\xad\x5e\xf5\x42\xc1\x6b\xb9\x5a\x6f\x69\x6d\x9d\x78\xde\x15\xd7\x8d\xdd\xfc\x83\x31\xd7\x5d\x72\xcb\x4f\x47\xe7\x77\x64\x77\xcd\x78\xa1\x77\xe7\xed\xa3\x97\x2f\xd4\xf2\x0f\x7f\xb8\xf3\x53\x78\xc6\xe9\x8b\x66\x9c\xd4\x33\x22\x30\x7e\xca\x9c\xc9\x67\xcf\x9e\xbc\x6e\xca\xab\x8f\x5c\xb3\x69\xc9\x09\x93\xce\x98\x71\xf2\xf9\x57\x4e\x7e\xfc\xb4\x97\x69\xdc\xa6\x0e\xec\x61\xe7\x71\x33\x41\x0b\xb8\x00\x64\x9b\xf0\x78\x1a\x6c\x06\x93\x88\xcb\x28\x67\x2e\x49\x69\xdb\x29\xf9\x36\xe9\xc3\xb3\x87\x25\x79\x2b\xe7\x15\x83\x0d\xa4\xd7\x45\x91\xb4\x68\x8c\x94\x5d\x34\x91\x06\x45\xe4\x92\x72\xc0\xa3\x44\x0d\xf2\x10\x7a\x1d\x31\x1e\x56\x1f\x97\x71\xe9\xae\x7e\xef\x81\x55\x37\xdf\x90\x3a\x7b\xea\x45\x4f\x25\x9f\x78\x6a\x6d\xee\xb4\x07\x9f\xbd\xf9\x82\x51\x33\xe7\x9c\x78\xcf\x85\x77\xbe\xf8\xcc\xab\x30\x78\xee\x6d\x33\xda\x62\xdd\xc7\xf6\x8c\x3f\xf9\xa4\x15\x93\x57\xdd\x32\xe3\x96\xe9\xe9\xe6\xae\x53\xd2\x27\x4e\x69\x69\x5f\x7f\xf2\x63\x24\xa7\xf4\x29\x00\xdc\x12\x72\xd7\x95\x32\x72\x11\x45\xae\x4f\x01\xcf\x11\xbd\xce\x02\x9a\xc3\xa8\x84\x14\x88\x2e\x01\x27\x23\x96\xd4\x43\x3a\x60\x4f\x54\x88\x3a\x60\x54\x88\xd4\x33\x01\xfd\xf3\x7a\x76\x56\xbc\xff\x52\xe8\xd5\x19\xe6\x83\xf8\x03\xcc\x4c\xa6\x73\xf5\x86\xfe\x0f\xfa\x5f\xde\x80\xd7\x40\x52\x57\x99\x56\x5b\x1b\xa8\x03\xc3\xc0\x73\x00\x29\x49\xcd\x43\x2f\x0b\x6a\xd3\xe4\x56\x34\x9a\x42\x2d\x86\x6c\x7d\x5b\x12\x05\x76\x23\x90\x22\x01\x6e\xbd\x97\x24\x01\xe2\xb4\xc7\xd1\x26\x16\x90\x3d\x55\x4c\x8f\x3f\xbc\x37\x47\xbd\x49\x14\x9f\xb4\x38\xcd\x2e\x12\x22\x07\x1e\xd5\x88\xb9\xda\x9a\xa8\x92\x60\x41\xd6\xee\xa8\x21\x75\x30\x0e\x52\x12\x84\x97\x40\xdc\x85\x43\x63\x8f\x62\xd0\x68\x69\x3e\x91\x50\x2e\x2a\x54\xcc\x2f\x24\xd1\x4c\x48\x0b\xde\xaa\x80\xcd\xf4\xae\x74\xe7\xb1\xe6\xec\xba\x46\xf5\xd0\xfb\xd6\xc0\x18\x68\xf4\xa8\x25\x57\xfe\xf0\xb2\xeb\xed\xfa\x47\xd2\xa5\xdd\xe7\x34\x5c\x92\xb8\xe5\x16\x3f\xb4\xf5\x5c\x7e\xf3\xc6\xce\xe6\xe3\x3c\xad\xcd\x89\x91\x7c\xd7\x82\x25\x37\xcc\xed\x88\xed\x7f\x74\xf2\x88\x05\xe1\x3b\xbd\xc1\xc5\x0b\xc6\xcf\xe0\x5e\xbb\xfa\xca\x96\xe6\x8e\x86\x61\x23\x3a\x01\x04\xd3\x0d\x3e\x93\x38\x78\x06\x94\x08\x2e\xe2\x65\x04\x17\x6a\x52\xab\x35\xae\xf3\x1a\x77\xa3\x40\xca\x24\xfb\x2e\x23\xb7\x88\xb7\x7b\x51\xac\x44\x6e\x51\x14\xcf\x43\x75\x24\xc1\x20\x35\xec\x43\x62\x1f\xd8\xea\x10\xa5\xba\xfa\x98\x79\xda\xb7\xd3\xdf\xc6\xcb\xf2\xb5\xae\x46\x49\xce\x32\x6a\x2d\xb9\x82\xae\x55\xa9\x78\xb1\x5d\xd2\xbc\x45\xc6\x8b\xa1\x4c\x17\x25\xda\x70\xe3\x6a\xad\x47\x19\x44\x74\x31\xf9\xbb\xd3\x42\x8b\x2e\x3d\x21\xd1\xd3\xda\xde\x21\x25\x6e\xbc\x45\x5e\x5c\x4e\x74\xa1\xcf\xbe\xfe\x9a\xe0\x03\x4a\xc7\x89\xef\x30\x37\x5f\x4d\x59\x4b\xf0\x3a\xc4\x7b\xb1\x8d\xe4\x64\xaf\xa0\xec\xf8\x48\x30\x76\x62\x27\x5b\xd0\x6c\x84\xd2\x82\xe6\x66\x3d\x5e\xe2\x3b\x0d\x5d\xff\xa2\x3c\xed\xda\xbd\x9b\x4d\xa5\x05\x47\x1f\x6d\x35\x60\xcd\xf6\x02\xba\xcb\x8a\x24\xf5\xe7\xcb\x00\xcd\x69\xc7\x18\xf0\x15\x77\x58\x42\x68\x42\xee\x06\x83\xf1\x96\x8d\xcf\x3e\xca\xd6\x44\xf5\xab\xf4\xbf\x3d\x0f\x95\x97\x4f\x3f\xc3\xf9\xb0\x17\x6f\xa5\x84\xc4\x64\xe2\x69\xcd\x75\x75\xe4\x7d\xa7\x0f\xec\x61\x83\xa4\x2e\xe7\x65\x23\xea\x0a\x0a\x05\x2a\x5e\x2e\x91\x89\x45\xae\xa4\x66\x2b\xce\x26\x29\x88\x35\xa7\xf2\xea\x7f\xfe\xab\x98\xc4\x67\xfb\x34\x59\xdc\x87\x3c\x7d\x28\x26\xe6\x98\x18\xab\x24\x78\x24\x8b\x39\xaf\x8c\x4f\xca\x12\x7e\xe2\x3f\x88\xe3\x3f\xc8\x32\x31\xd6\x7a\x5b\xc6\xb0\x1e\x39\xd6\x6e\xe6\x6f\x3d\x5e\x49\x2e\x9f\x60\xa0\x05\xeb\x25\x19\x85\xc8\x01\xa6\xb6\x91\x48\x22\xe0\xe5\xee\xc2\xdb\x03\xb2\xd1\x1a\x46\x85\x5e\x94\x19\x1b\x69\x45\x4e\x93\xe9\xe2\xcb\xf5\xcd\x6b\xef\x9c\x74\xfc\x84\x93\x6f\xac\x6f\x1e\xca\x68\xc2\xee\x38\xeb\xcc\x25\xcf\xac\x0a\xaf\x51\xef\xda\x52\x81\x93\x06\x82\xe7\x0d\xae\x22\x3f\x98\x0b\x2c\x4c\x34\x7e\xca\x4c\xe4\xc0\x2e\x29\x40\x24\x4f\xf1\x01\x32\x38\x48\xe7\xca\xdf\xee\x45\x6a\x1f\xaf\x71\xce\x7d\x5e\xc4\xf7\x01\x8d\x57\x69\x7d\xb4\xea\x2f\x0d\xd4\x4c\xc5\x03\x49\x73\xc9\xb4\xa6\x07\x4f\xea\xe0\x65\x6d\x92\xd4\xec\xb4\xcf\xea\x18\x1e\x38\x6b\xd8\x15\x4b\xdc\x70\x34\x21\xa8\x99\x14\x6b\xbe\xd0\xbf\xce\xed\x5b\x74\x45\x5b\x17\xff\x0a\x80\x60\xc3\xc0\x1e\xdb\x17\xa4\x1e\x3a\x07\xb2\x61\x40\x71\x68\x94\xec\xf8\xc8\x15\x17\x44\x0d\x95\xee\x0a\xca\x13\x4f\x78\x5b\x57\xfd\x05\x7c\xb0\x24\xa3\x9a\xff\xcf\xaf\xe8\xd4\x17\x13\x4b\x35\x7d\xd8\xab\x89\x35\x3e\x92\xe6\xf5\x91\x34\xaf\xcf\x12\x2a\x89\x19\x90\xf3\x88\xc1\x1a\x1a\x2a\x99\x9f\xa8\x10\x22\x27\xc9\x9a\x33\x6c\x55\xf5\x94\x25\xa4\x56\xc8\x24\x09\xdd\x0a\x95\x70\x20\x77\xfa\xa4\x3f\x30\xb8\xf2\xce\x27\x5e\x1e\xb9\xb3\x37\xf1\x64\xdb\x6b\x8e\xf8\x67\xcf\x2e\x1f\xad\x7f\xfa\xc5\x9f\xff\x00\xef\x98\x72\x05\x7b\xcd\xc1\x25\x97\x8d\xfb\xc1\x6d\xcf\xbe\xcd\xe6\xdf\x88\x41\x10\x78\xf4\xbd\x48\xff\x62\x7d\xef\x37\xbb\xe9\x5a\xbd\x7a\x60\x0f\xff\x67\x6e\x2f\x88\x9a\xd1\x63\x36\x62\xed\x04\x24\x06\x32\x39\x39\x87\x74\x00\x86\x08\x0b\x17\x39\x75\x28\x30\xa1\xf9\x2d\x34\xd3\xc6\x2d\x17\xa1\x99\xf6\xf4\xf1\x9a\xaf\x7e\x9f\xd7\x6a\x9f\xac\x68\xb5\x0c\xc8\xd2\x94\x1b\xcc\x7b\xbc\xbe\x21\xc9\x37\x47\x24\x93\xd1\x6a\x89\xd2\x4c\x5d\xa9\x33\x1e\x7f\xb6\x9a\xc7\xe8\x15\x14\xcc\x53\x6e\xb1\x69\xb0\xac\x47\x30\x74\xd6\xbc\xc0\x6b\xf6\xd8\x1f\x9f\xcb\xd3\x66\xc1\xdb\x56\x41\xe6\x18\xda\x1f\x38\x62\x35\xe9\x0f\x5c\x2c\x2e\xbf\x3b\xb8\xee\xbf\xa2\x07\xd1\xce\xeb\x2e\x5d\x8d\x6d\xb4\x76\xa0\x60\x9b\xcc\xf7\x82\x18\x8e\x2b\x78\x1c\x11\xfa\xd3\x1a\xc7\x16\x50\x30\x85\x22\x49\xcd\x83\x41\x4f\xeb\x46\x9d\x7e\x22\xec\x21\xc1\x84\x16\xf6\x93\x4a\x51\xcd\x69\x6a\x9f\x23\x49\xda\xca\xda\x54\x7f\x4d\x84\xc4\x4c\x9c\x47\x92\x73\xc0\x29\x85\xf1\x0e\xc7\x4b\x9a\xa0\x1a\x05\x43\x3d\xd1\x9e\xa8\x60\x56\xef\xc9\x5d\xa3\x98\x56\x8c\xff\x80\xec\xa7\x45\x1c\xcc\xda\xcf\xde\xd3\x9f\x6c\x64\xce\xa8\xff\xfc\xdf\xaf\x67\xef\xfb\xe3\xcd\x17\xce\xaf\x63\xc6\x47\xf5\xd5\x17\xcd\x79\x41\x7f\xe5\x9d\xa7\xf7\xdf\xce\xd4\xff\x15\xde\xb9\x74\xc3\xca\x7b\xf4\x6b\xbe\x78\x69\xd7\x13\xb0\x75\xdb\x4f\x21\x98\xbf\x72\xc3\x05\xfa\x97\x3f\xfe\xbd\x7e\xf7\x5b\xcb\x21\x43\xe7\x7e\x3b\x00\xdc\x9b\xfc\x4e\x10\x06\x37\xd0\x75\x41\x9a\xa1\x10\x4c\x67\x65\xbc\x36\xdc\x78\x5c\x75\x96\xae\x47\x22\x06\xe8\x57\x8a\x85\x7c\x7d\xdf\xd9\xd7\x6b\x72\xd2\x86\x8b\xed\x4c\x88\x69\x87\x1a\x13\x36\xd5\x49\xa0\x24\x67\xbd\x72\x88\xb2\x3d\x87\x49\x87\x9f\x1f\x07\xb6\x44\xa4\x83\xb4\x39\x05\xfc\xdd\x3d\x70\x3c\x24\xc7\xc5\x2e\x23\xf6\xf7\x32\x30\xbe\x7d\xeb\x4c\x79\xf2\x05\xd0\xd1\x33\x61\x46\x47\x7b\xe0\x3b\xb1\xf9\x37\x87\xd2\x37\xea\xd1\x37\xf9\xde\x83\xa7\xf4\xde\xbd\xf1\x61\xb8\xe1\xdc\x7b\x27\xce\xf4\xaf\xf3\x78\x97\x2c\x1a\x3d\xef\x8a\x37\xfb\x21\xdd\x7b\xb8\x6f\xf8\xf7\x80\x04\x7e\x44\xab\x9a\x91\x8b\xde\x52\xd1\xf5\x2e\x62\x2f\x2e\x13\x56\x3d\x97\x65\xc3\xd9\xb4\xd7\xf0\xe2\x6e\xb2\x94\x5d\x44\xda\x67\xc7\xcc\xbd\xbf\x36\x17\xb8\xe6\xf6\xd8\x91\xa7\xcf\xab\xd9\x22\xfb\x90\xd0\x07\xf2\x36\xc1\x59\xbc\xaa\x29\x7d\xa6\x1e\x4c\x74\xd3\x05\x6c\xa7\xb2\xbc\x4a\x17\x49\xb7\x9b\x5d\x7b\x2d\xf1\xd8\xc6\xd4\x89\x67\x7d\x5f\xbe\x01\x7e\xf8\x7e\xff\x8a\xab\x9f\x5f\xb4\x4e\x9a\x10\xe3\xe3\xab\x6b\xcf\x3a\xa7\xbf\x8f\xf9\x80\x76\x6d\x31\x6f\x90\x1c\x3a\xe9\xd1\x9b\xca\xcd\x04\x31\x70\x3d\xed\xd0\x43\xf6\x74\x56\x85\xb4\x60\x0d\x35\x1a\x8d\x7a\xf1\x62\xa3\x5e\xd3\xd1\x36\xea\xa1\x86\x0c\xd0\x18\x1c\x48\x35\xc4\xc8\x99\x3f\x0f\xdc\x9e\x20\x95\xba\xc0\x51\x44\x85\x96\x3d\x85\x52\x06\x5a\x9a\x54\x06\xb7\xeb\x7d\x7a\xfc\x79\x93\x26\x8c\x08\x37\xf8\xeb\xda\xe2\xfd\x6f\x93\xbe\xbd\xc1\xad\x7a\x70\xd3\x0d\xa7\xd7\xdc\xe1\x1c\x71\xc2\x81\x3d\x9b\xef\xf4\x93\xb1\x92\x1e\x24\x12\x37\x18\xda\xdd\x9a\x8f\x2d\xd0\x2b\x46\x81\x2d\xe4\x39\x16\xd8\x3d\xf8\x54\x46\x0a\xdb\x5c\x24\x88\xc0\x33\x08\x34\x9f\xd1\x92\x44\xc6\xe3\x2c\x36\x02\xd1\x66\xa0\xb4\x10\x85\x51\x41\xad\x83\x5b\xf4\x83\x11\x38\x0d\x5e\x45\x5b\x92\xf4\x25\x5f\x44\xf4\xed\xfa\x45\xcc\x96\xe8\x4a\x26\x7a\x2f\xfc\xc5\xc6\xd5\x7a\xfd\xbd\xfd\x5f\x6d\x04\x66\xdc\xcd\x2e\xe5\x26\x59\xdf\x85\x37\x88\x8a\x05\xfe\x48\xde\x45\xe0\x4a\xef\x12\x2f\x7f\x97\x48\x2d\xec\x7c\x3d\x02\x6b\x21\x47\x7b\x92\x06\xc0\xeb\x11\xfd\x2f\xfa\x87\x8c\x33\x7c\x13\x5c\xb4\x12\x1e\xbf\xec\x5e\xfd\x9d\x95\xfa\x9a\x65\x00\x02\xef\xc0\x1e\x6e\x26\xdf\x0b\xc2\xe0\x6c\x90\xad\x35\xd9\x11\x7d\xc6\x19\x2d\x2f\x3b\x6b\x7d\x9e\x84\x26\xf3\x74\xa9\x0a\xbb\x35\xbf\x4a\xd6\xa7\xe6\x17\x88\x32\x3e\xd0\xb8\x5a\xb3\x3c\x5b\x83\xfe\x4c\x46\xf3\xca\x74\x7f\xf5\x49\xe4\x84\x56\xa2\x41\x4c\x40\xa3\x7d\x8a\x14\xef\x61\x5f\xe3\xfd\xce\xf6\x99\xcf\xbf\xbf\x6a\xc5\x63\x75\xf0\x5f\xfd\x6f\xc6\xd8\x78\xa4\xff\xf3\xed\xbb\xee\xd1\xbf\xec\x9d\xd5\x37\xee\x99\x91\x99\x67\xd6\x5e\x75\xed\x4a\xf8\x9b\x8d\xab\x75\x91\x7b\xf9\xa9\xd5\xff\x73\x5d\xb2\x58\x17\xb6\x8c\xef\x05\x41\x70\xa6\x91\xa9\x15\x85\x02\x25\x3a\xb3\xb3\x85\x3c\xeb\xf2\xf3\x9e\x84\xc6\xda\xa8\x3c\x3a\x0e\x03\x55\x22\x8f\x0e\x34\xd1\x4f\x8b\x62\x5c\x92\x06\xe4\x4c\x06\xb1\xb2\xc6\x38\x32\x19\x8d\xb7\x9b\xfa\x45\xa3\x9a\x9a\xc9\x91\x66\x70\xd9\x17\xec\x80\x92\xbe\x3e\xc2\x9e\x18\xef\x5f\x0a\x2f\x0a\x9f\xa4\xd7\xae\x5f\xb3\xed\x43\x4d\xff\xe4\x9f\x70\xee\xae\x7f\xb8\xe0\xe7\xab\x37\xea\xe1\xa5\xfa\x2b\xd7\x2c\x98\xb3\xf9\xbb\x3f\xa3\x73\xdc\xab\xab\xec\x4e\x6e\x12\x08\x81\x49\x20\x6b\x83\x74\xdb\x43\x35\xa4\x62\x12\x1f\xac\x38\x9b\xb5\xf9\x41\xab\xc3\x6f\x28\xd7\xd0\xd8\xda\x2d\x69\xc0\x9f\xc1\x27\x2d\x8d\x75\x66\x32\x9a\xcd\x61\xd0\x82\x09\xa3\xba\x9b\x7a\xcc\x57\x8c\xd9\xac\xe7\xc1\x49\x2b\xa1\x90\xd5\x9f\x0f\x33\xfb\x23\xfd\x6f\xc1\x53\x43\x57\xff\xea\xcb\x07\x6f\x3b\xeb\xbe\xf9\x6b\x7f\xb1\xf3\xf3\xc9\x3f\xfe\x7c\x99\x03\x7e\xb5\x74\xad\xee\x5b\xfc\x5e\xef\x2d\x0f\x45\xd3\xeb\x27\xff\x1e\xc0\x81\x65\xba\xca\x3e\xcc\x4d\x02\x4d\xe0\x7c\x40\x43\x52\x7c\x26\xa3\x5c\x3e\xc5\x12\x77\x6f\xb1\x58\x50\xa5\x02\x6e\xa4\x58\xf0\x58\x07\xeb\x74\x79\xbc\x52\x30\x42\x2a\x39\x55\x89\xc8\x2a\xd7\xc7\x68\xd5\x95\x47\xca\x02\x29\x42\xc5\xb5\x48\xb5\x15\x3b\xaa\xbb\x87\x14\x6b\x96\xe3\x80\x37\x38\x0a\xe8\x10\x6e\x78\xe6\xd3\x9f\x3f\x76\xdf\x93\x97\x04\xe1\x1a\xdd\x19\x61\xfe\x12\xd6\xa7\xfe\xe4\xa5\x03\xfa\x7f\x5f\x7f\xe1\x39\xe7\x6d\x7c\x60\xd9\xb6\xc7\x5e\x18\x00\xb7\xdc\xda\x14\xb9\xf9\xaa\xf3\xcf\x5b\x0c\xcf\x58\xbb\x54\x7f\xd2\xf3\xdc\xdd\x2f\xbc\x96\x90\xba\xd2\xc3\x46\x9d\xb4\xee\xd8\x9b\x01\x1c\xf8\x04\x00\x2e\x6e\x8b\x80\x7a\x8c\x0f\x60\x64\xf2\x11\x9b\x44\x35\x74\x39\x05\x48\xc0\x2d\x61\x57\xdd\x40\xa4\xb3\x54\x85\x44\x5d\x9a\x6a\x97\xe4\x6c\xa0\x8e\x16\xda\x86\x8d\x85\xe6\xe2\xf0\x0e\xe3\x53\x49\x34\x40\x17\xbe\x59\x73\x6a\x9e\xcc\x05\xbc\xee\xfc\x51\x21\x1a\x65\xea\xf5\x47\x23\xf0\xf5\xe9\x67\x5e\x70\xe6\xe9\xab\x67\x9c\xfd\xfa\x07\x1b\x7e\xf6\xe4\x5b\x11\x7d\x4f\xff\xbf\x99\xf5\x91\x87\x99\xce\x95\x97\x65\x2f\x38\xe3\x82\x63\x4e\xbc\x69\xfd\xd3\x3f\xfc\x78\xdb\xca\xfe\x4f\xed\xd4\x1f\x90\x75\x78\x01\xe9\xf7\x5a\x68\x59\x87\x5e\x86\x12\x97\x6b\x6e\x29\x95\xc2\x8b\xd1\xeb\x21\xc5\xa8\xb2\xa1\x8d\x2e\xec\x26\x39\x13\xb3\x41\xe6\xe6\xbd\xad\x64\xbf\x74\xb5\x23\xa9\x1d\x1f\x99\xe5\xd0\x3e\x24\x89\x9a\x3b\xb4\x8f\xcd\xb9\xdc\xc5\x2e\xc1\xf2\x45\x4b\x7a\x83\xac\xcb\x54\x89\x13\xc6\x3e\xda\x19\x13\x8d\x79\xcf\x7a\xfd\xfc\xd7\x3e\x58\xb3\xf2\xfd\x1b\x1e\x8f\xb3\x27\xc4\x75\xd7\xf4\x96\x0f\xf6\xe8\xef\xe9\x7f\xfe\xc7\x98\x4d\xed\xa9\xed\x9b\x6f\x59\xce\xc4\x36\x6e\xd4\x17\xbe\xbf\xfd\x80\xfe\x37\x52\x1b\x38\xb0\x87\x5d\xc9\x4d\x02\xb5\xe0\x04\xca\x36\x8a\xcf\xf4\x59\x0f\xe1\xee\x13\x0a\xc8\x97\xca\x4b\x8e\x1a\x8f\x87\x88\xa9\x98\x32\xf5\x7e\x1f\x61\x15\x05\x1a\x5b\x43\xdf\xcc\x41\xdd\x49\x47\xe7\x38\x18\x28\x7f\x31\x81\x8a\x5e\xc4\x63\x0f\x3e\x77\xef\xd3\xf7\x2f\xbf\x6b\xea\x92\x08\xf3\x5a\x83\x3e\xbb\x2b\xfa\xf4\xeb\x7a\xff\xef\x3f\x49\x6f\x38\x7b\xc5\xa2\xef\x9e\x0b\x97\xae\x5d\xfb\x8f\x4d\xf7\xee\xf8\x2d\x30\xdf\x29\xc3\x4f\x04\x2d\xd8\xbe\x24\x77\xc3\xda\x0a\x59\x3f\x51\x72\xe1\xf1\x3b\x65\xfd\x35\xf8\x70\xed\x57\x1c\x09\x92\xc9\x71\x17\x33\x39\x18\xf7\x51\x1f\xcd\xe4\x84\xdd\x92\x9c\x67\x1d\x3e\xb9\x89\x26\x0e\x72\x8a\xbf\x86\x68\x4e\x44\x65\x4d\x25\xb2\x4d\x6c\x13\x7d\xff\x1a\x49\x83\xd1\x4c\x06\xf9\x69\xa2\xaa\x38\x0a\x52\xc7\x3c\x01\x16\x99\xfd\x28\x1d\x2c\x2d\x67\x6e\x59\xb9\x6e\xc9\x7d\x13\xbf\x77\xea\x58\x77\xab\x85\xd7\xaf\xcd\x1e\x6b\xbc\xf6\xbc\xbf\xfd\x7c\xc6\xb3\xe9\x0d\xd3\x66\x4d\xe9\x3a\xa3\x33\x31\x7d\x7c\x5b\xd7\x4b\xe4\xa4\xfc\x6a\x43\xa4\x65\x84\x72\xfc\x6d\xd3\x1f\xdb\xd6\x0a\x8c\x7c\x6d\x17\x37\x03\xf8\x40\x08\x3c\x06\xe8\xc5\x22\x69\xbc\x0f\xd2\x5c\xad\xaf\xa8\x7f\xe9\x93\x4a\xca\xe3\xf4\x6e\x51\xc5\xe1\xa4\x32\x44\x1d\x8d\x70\x91\x84\xfa\x72\x5e\x5f\x48\x49\xe4\x44\xfc\xcc\x7a\x7d\xa1\xf2\x73\x47\xd6\x2b\x86\x48\x8e\x85\xfe\x3a\x48\x69\x4f\x95\x34\x21\x48\x14\x11\xa8\xb8\x9e\x93\x2c\x26\x96\x28\x21\x18\xc9\x58\x4e\x60\x95\x6e\xa3\x99\x87\x11\x46\xc2\x33\xef\xab\xb1\x9f\xfa\xea\xac\xe5\xeb\x3e\xd6\x17\xef\x99\xbd\xf4\xa7\x30\xb6\xe9\x9c\xd3\x17\xfd\x61\xb8\xae\xda\xba\xdf\x9f\xb7\xe8\xcd\xa7\x76\xe8\x5b\x3e\x0c\xe9\xc3\x98\x85\x6a\x0e\xfa\x56\x5c\x7a\x8d\x5e\xd8\x09\x20\xdc\xa1\xab\xcc\x05\x44\x97\xb8\x1e\xe0\xf1\xc2\x24\x44\x1c\x95\x21\xf6\x16\xc8\xff\xf3\x30\x01\x3a\x3a\xa1\x94\x96\xe0\x8e\xc7\x74\xd5\x0e\xbe\x01\x80\x01\x2f\xea\x2a\x3b\x97\xfc\x77\x02\x18\x4e\xfe\x4b\x8e\x28\x89\xf3\x69\x88\xec\xe6\x7f\x8f\x58\xca\x12\x2b\x78\x0b\x9a\x83\xfc\x33\x8a\x94\x96\xa2\x52\x5a\x7a\xf1\x31\x38\xdf\xf8\xc7\xc8\x3f\x48\x30\x77\x87\xae\xb2\xeb\x6c\x2a\x50\xc0\xb9\x80\x24\x24\xb0\xf9\x35\x28\x14\x90\x27\x85\x5f\xca\x95\xd6\x78\xa1\x80\x1c\x29\x24\x24\x49\xe7\xa1\xbc\x5b\x63\x6c\xa9\x94\x26\x79\x0b\x9a\xdd\x9d\x4a\x65\x25\x19\x63\x52\xf2\x39\x12\xc8\x99\xca\xca\x12\xfe\x9d\x0c\x1c\x09\xc4\xa5\x48\x03\x3b\x0e\xfe\xa2\xf8\x7f\xf8\x35\xfc\xe4\x7f\x52\x5c\xba\x03\x8e\xd5\xdf\x80\x63\x1f\xa3\xbf\xe8\x6f\x3c\x06\xe5\xfb\xf5\xfb\x98\x8f\xfb\xe3\xf7\xe9\xf7\xf7\x33\x8c\x0e\x18\xd0\x36\xf0\x19\x93\x26\x79\x3f\x1f\xe8\xa1\x15\xbc\xc8\x91\xcc\xb3\x0e\xe0\xe3\x12\x86\x38\x7d\xde\xe6\x02\x22\x97\x20\xc7\x0d\x1b\x3e\x66\xb8\xc9\xcd\xa6\x87\x35\x2e\x33\x7b\x2c\x74\x01\x61\x98\x86\x6d\x53\x4f\x6a\x3f\xe6\xac\x89\x5d\xa3\x97\x6c\xf9\x48\xff\x62\xca\x69\xdf\xcf\x74\x9f\x74\xc1\x31\xf0\x56\x2e\x74\xe0\x4f\x00\x70\x60\x2a\x00\x8e\x3d\x06\x27\x40\x3d\x18\x01\xae\xa5\x77\x91\x08\xa4\x89\x83\x76\xa6\xb2\x35\xf4\x7c\x40\xb4\x36\x14\xca\x33\xe9\xdb\xad\xf1\xfe\x52\x75\xa3\xd9\xe6\x01\xda\x91\x42\xba\x31\x9d\xe2\x3e\xa4\x88\x1a\x14\xf7\xb1\x39\x00\x9d\x4a\xd1\xc5\x85\x55\x7a\xab\x14\x94\x34\x1f\x4f\x0a\xbf\x51\xc8\x50\xa4\x20\xf7\xc9\xd1\xd6\x62\x37\x0b\xac\xd6\xd7\x3d\x15\x76\x59\x3a\x7a\x56\x9b\xed\x3c\x6c\xfc\x50\x9d\xe7\x7c\x6f\xb1\xc7\x67\x3d\x6d\xf0\xd9\xff\xe7\x2a\xdd\xe8\xd4\x26\x8a\xc1\x55\x80\x6d\x72\xab\xc5\x26\x3c\xa5\x1a\xd2\x9c\x66\xb3\xaa\x62\xa7\xa5\xa3\xb4\xb4\xfa\x3f\x31\x4e\x8d\x2a\xc9\x1a\xef\xcb\x90\x64\x74\xdb\xf0\x4c\x06\x41\x19\xc5\xfe\xb7\xcc\x53\x33\xa8\x1d\xfe\xee\xc3\x99\xa7\x4a\x8b\x3c\xd1\xe1\xda\x63\x3f\xdf\x16\x05\x2a\x88\x82\x04\x38\x06\xac\xa4\xdd\x79\xc8\x9d\xd6\xda\xf8\x42\xa9\xcf\xb2\x05\x9b\xa5\xd9\x6c\xe2\x6f\x10\xe8\x85\xfd\x18\x5a\x54\xac\x90\x5a\x62\x0f\xe5\x77\x46\x6e\x43\x75\x5e\x2a\x68\x63\x61\x42\xf3\xf8\x25\x39\xc7\xc9\xc1\x06\x2a\xc1\x94\xf5\xfa\xc2\x38\x6a\x71\x12\x19\x13\x97\xa4\xc5\xe2\x18\xf4\x6d\x31\xda\x46\xd0\x2c\x6d\x03\x82\xcd\xe7\x0f\x7b\x87\x95\x94\x98\x52\xc1\xb4\x59\x78\x33\xb4\xff\xa6\xaa\xf5\x8c\xc6\x9c\x40\xf0\xb4\x5c\xa5\xa6\x1c\x76\xee\xa1\xac\x68\xb4\xec\x3c\x7d\x11\x9c\x33\xa4\x63\x47\x07\xd5\xec\xc9\x80\xa9\xfa\x4d\x36\x3f\xd1\x96\x97\xc0\x03\x83\xb4\xe5\xb3\x8c\xdb\x93\x4e\xa7\x91\x68\x24\xda\x64\xab\xb6\xbc\x9b\x96\x20\x17\x8f\xb4\x15\xb4\xe5\x5f\x1c\xff\xc8\xde\xde\xe2\x39\xd7\xd5\x47\x6f\x35\x81\xe6\xf2\xb6\xb7\xc3\x1c\x60\x5d\xde\x62\xde\xc5\xcd\xe0\x93\x3a\x6f\x23\x91\x96\x43\xa4\x9a\x31\x40\x32\xca\x0e\x89\x18\x7d\x0f\x21\x2c\x48\x43\x26\x1a\x2b\xaa\xd1\x3f\x61\x3b\x71\xf2\xbb\xa3\x60\x7a\x9b\xfe\xf3\x29\xfa\x86\x4b\x89\x28\xbd\x7e\xdf\x7a\xf5\x6b\x7e\xe3\xfe\x53\xf4\xc5\x44\xd7\x48\xe5\xf7\xf3\x9f\x01\x1e\xc8\xa0\x1e\x68\x43\xd5\xf3\x73\x32\x0c\x78\x13\x5a\xd8\x41\x7b\x73\x91\x9b\x8c\x97\x70\x2e\x34\x58\xc7\x4b\x24\x7d\xa4\x02\x52\x08\xd7\x92\xab\x94\x96\xab\x38\x70\x23\xb1\xee\xa5\x47\x7b\x7a\xcc\x07\x9a\xd3\x43\x07\x8e\x7f\x35\x13\xe9\xa5\x81\xd3\xd6\xec\x00\xc9\xc9\x01\xbb\x41\x76\x61\x0c\xde\x18\x3b\x65\xae\xa9\x20\xcb\x3f\xf7\x98\x71\x8b\x13\xd0\x96\xd5\xff\xd5\xfc\x93\x1f\x9e\xda\xcd\x4c\x3d\xa1\x7b\xc6\x49\xc9\xe1\xdd\xd4\x22\x3b\x82\xef\x70\x1f\x1e\xa8\x41\xeb\xfd\x42\x4f\x66\xd2\x8c\xb1\xa7\xa5\x48\xcd\x4e\x8f\xae\x72\x3d\x64\x8f\x13\x41\x18\x3c\x53\x54\xed\x27\xb4\xca\xc8\x99\x46\xde\xa4\x66\x13\x0a\xa8\x36\xa9\xa9\x25\x11\xff\xba\x0a\x22\xfe\xd8\x40\x44\x68\x56\x2a\x20\x09\x1b\x28\xe0\x2a\xb5\x5f\x1a\x5e\xc8\x62\x14\x07\xe1\xa9\x71\x62\x4c\x00\xcd\xee\x6a\x6f\x87\xe4\x49\x15\x9e\x59\x49\xd6\x38\x91\x28\x3c\x93\x0a\x13\x22\x38\xab\xa9\x44\xa3\x18\xd8\x8c\x73\x19\x36\x8b\x52\xc5\x28\x3d\x70\x72\x5e\xdf\x1a\xab\x62\x11\x9b\xba\x6f\x4f\x45\x83\x30\x60\x8a\x7e\x93\xf0\x57\xa2\x15\x5e\x07\x0e\x1a\x95\x58\x4e\xb1\xd6\x54\x91\xcd\xd9\x1d\xc1\x9a\xa6\x60\x1a\x85\x93\x9a\xca\x16\xe9\x5a\xcb\x35\x9d\x91\x83\xd2\x4f\xd5\x38\x4b\x25\x6f\x47\x23\xef\x5c\x5c\x31\x84\x3c\x9f\xa7\x4c\xfa\x47\xae\xfa\x9c\x17\x7c\x01\x43\xea\x19\x6e\x83\x82\xd3\x17\xa8\x35\x95\x9f\xcb\xb4\x9f\x55\x2a\x87\xa6\x86\x29\x57\x39\x90\x90\x4c\x15\x6c\xab\xe8\x3f\x5b\x16\x5f\x45\xf1\x67\xf6\xb2\xc1\x2b\x71\xb0\xb6\xb8\x65\x55\x62\xec\x4d\xd1\x55\xe1\x7d\xfe\x33\x20\x82\x7a\x30\x0c\x36\x54\x54\xcd\xce\xc9\x30\xea\x4d\x68\x2d\x8e\x02\xb9\x0f\x47\xd4\xf4\x4a\xa9\x2d\x66\xa8\xe9\x03\x30\xa1\x05\xa5\x02\x65\xd6\x8b\xbb\x4a\x5d\x33\x47\x33\x07\x45\x9c\x12\x01\x64\x43\x0c\xf9\x70\x96\xdf\x2a\xf8\xfc\x35\xa6\xad\xa9\xed\x4b\xbf\xb7\xd8\x5e\x93\xea\xa9\xea\xb6\x12\xce\x64\xb4\x60\x40\x92\xb5\x68\x0b\xc1\xb6\x42\xe6\x42\x6b\x09\x1b\x3a\xdc\x08\x4a\x5a\x43\xbc\xf2\x7c\x54\x81\x7e\xe5\xb9\xd9\x54\xd5\x39\x0c\x9e\xa4\x4a\xeb\x82\x05\x19\x5d\xb5\xbd\xc3\x7f\x06\x42\xa0\x15\xa4\xc0\x81\xc1\x4a\xdd\x5a\x63\x34\x9d\x2e\x55\x2b\x36\x93\x5c\x01\xea\x48\x6a\x09\x07\x95\xec\x39\x2a\xf1\x6e\x7c\x4c\x6d\xc4\x27\x2c\xa9\x80\x86\xe1\x59\x1c\xe9\x22\x12\x3f\x55\x05\xbd\x4b\xb7\x98\x8d\x22\x8a\x90\xfa\x91\x58\x1f\xc8\x79\xc4\x48\xcc\xbc\xf7\xa0\x9f\xca\xcf\x20\xa5\xc2\x48\xcd\x25\x4b\x72\x36\x5c\xdf\x8c\x7d\x70\xb4\x51\x92\xb5\x44\x87\x49\x91\x87\xc2\x19\xe4\x97\x8e\x40\xfe\xbb\xda\x8c\x54\xd1\x01\x67\xb2\x55\xe6\xa4\x9a\xe0\x7c\x45\x17\x0e\xd8\x81\xbb\x00\xe0\xee\x14\xee\x01\x02\xf0\x82\x7a\xb0\xd4\xdc\xdf\xb8\x74\xb1\x96\x24\x6f\xb3\x03\xe8\x21\x05\x5d\xb4\x7d\x9a\x6c\x6c\x1c\x71\xe1\xe6\x26\xd6\x77\xdd\x37\x53\x8a\x7d\x54\xce\x3e\xde\x28\x68\x76\x8a\x39\xde\xc9\x29\x89\x9c\xc3\x49\xa8\x34\x90\x93\x10\x69\x38\x8a\x45\xf4\x2c\x27\xc9\x9a\x9f\x30\xaf\x41\xbb\x71\x0a\x88\xc3\xb4\x12\x67\xa3\x2c\x8c\xb2\x2d\x5d\xde\xc1\x5a\x0f\x0b\xd9\x70\xdf\xd6\xad\x3d\xba\xf2\x39\x3c\x09\x2e\x8d\x86\x1b\x27\xcf\x2e\x0f\x06\xf7\x4f\x82\x6f\xe9\x19\x66\x1e\x4c\x7d\xb6\xf0\xf4\x47\xd8\x4b\xca\x02\x16\xa2\xc7\xc9\xcd\x21\xba\x6e\x8d\x20\x09\x2e\xa2\x39\x77\x52\xf6\x57\x14\x04\xa0\x21\x5f\x7d\x49\x8f\x55\x51\x0a\x38\xea\xc5\x11\x8b\xcb\x4d\xf5\x58\xf1\x56\xdb\xcb\x89\x81\xfa\x68\xf3\x48\x1c\xe7\xb9\xa4\x9c\xc7\x1b\x1a\x41\x6e\x4a\xea\x03\x92\x9c\x07\x76\xc1\xeb\xb1\x44\x74\x81\x60\xba\x87\xf0\x42\x56\x52\x67\x2d\x0f\xe3\x56\x7c\xf3\xc0\x79\x2b\x86\xbb\x8e\x5b\x5e\x58\x19\xb2\x3f\xfb\xf6\xf2\xc7\x5f\x98\x3e\x65\xe6\xcb\xd7\x5c\x7e\xee\xc5\xcf\xce\xea\x2d\x8f\xd9\xde\x83\x17\xbd\x3b\x6b\xc6\xe6\x03\xbd\x3b\x3f\x79\x63\xcb\x55\x57\xe6\x61\xf4\x81\x59\x37\xfc\x54\xff\x3d\x37\x38\x4e\x23\xbd\x3e\xab\x85\x7b\x80\x0b\x84\xc0\xd9\x96\x6e\x1f\x67\xca\x50\x74\xe0\x0a\x48\x48\xe1\xb3\x7c\xf1\xb8\x6e\x34\x45\x78\x69\x4c\x42\xfb\xdf\xfb\x40\x8e\x61\xed\x0e\xba\x30\xcc\x4f\x06\x03\x5c\x7c\x02\x34\xba\x75\x82\xc2\xa0\x59\x6b\xf3\x6f\xd9\x47\x9b\x76\xf6\xaf\xf7\xbf\x6a\x1d\xc3\xec\x36\x6e\x5d\xeb\x9c\x39\xad\x07\x66\xb7\xcd\x16\x16\x0c\xd5\xe0\xb3\xdb\xa2\x80\x05\x32\x38\xa7\x14\x5d\x60\x9f\x41\x22\x09\xa5\x42\x24\xa1\xa9\xc5\xaa\xc1\x6d\xf8\xed\x59\x48\x70\x56\xbc\xd4\x82\xa4\x7d\x91\x91\x35\xbb\x98\xa1\x2d\x1b\x69\x17\x1c\xac\xbe\x97\x2f\x9c\x5f\x2e\xb7\x77\xa0\xb7\x3c\xf2\x35\x75\xae\xef\x21\xfc\x12\xc3\xab\x28\x18\x27\x2a\x29\x18\x8f\x30\xd4\x7c\xf3\x9c\xab\x8e\xc8\x31\x23\x41\xd2\xe2\x4d\x47\xa5\x57\x5d\xf6\xba\x87\x12\x2f\xee\xb6\x0e\xe3\x70\x82\xd5\x0b\xca\x31\x43\x35\xab\x33\x86\x66\xf1\xf0\x92\x9e\x7a\x99\x62\x71\xa2\x92\x62\xb1\x75\x8c\x8d\xc6\x18\x09\x71\xfa\x11\xeb\x15\x97\xaf\x88\x8a\x52\xc5\x4f\x95\x2d\x85\xaa\xca\xd3\xbf\x2d\xc7\x14\xe5\x0a\xbf\x07\x04\x40\x73\x35\x76\xe6\x96\xc3\xb0\x33\xb7\x1e\x2d\x3b\x73\xde\xa5\x06\xeb\x63\x06\x83\x35\x15\x63\x3f\x3c\x3b\x73\x99\x05\x2a\xb3\xea\xfe\xa6\xcc\x02\x55\x98\xbe\xb7\x96\x8f\xff\x6a\xc3\xff\xd5\x80\xd6\xaa\x7a\x02\xc5\xb6\x96\x23\x60\x63\x6e\x1b\xca\xc6\x6c\x6c\x85\x48\x94\xb3\xb2\xd2\x94\x39\x1a\x6e\xf8\xb2\x41\x57\xe1\xca\x2d\x53\xc2\xac\x4c\xcc\x7d\x97\x75\xcc\x1c\x9d\x73\xbb\x13\x04\x40\x14\x34\x83\xce\xa2\xde\x4f\x39\x43\x7c\x24\x89\x92\xe9\x7c\x88\xd2\x69\xb6\xa5\x50\x2c\xa9\xc5\x6d\x05\x88\x52\xd5\xa9\xe2\xb5\x3a\xb5\x80\xea\x44\x72\x83\x31\x42\x25\x4d\xb6\x26\x48\xd2\xdf\x8a\x24\x1e\xd5\x99\xf9\x81\x23\x20\x5e\x36\x43\x04\x05\xfb\x5c\x4b\xea\xac\x8a\xde\x80\x41\xba\xd9\xd9\xc0\xb4\x36\xfc\x65\x4c\x8a\x12\x6f\x56\xe3\xf2\xde\xd1\x39\x71\x4a\xe7\x29\x23\x60\xd3\xea\xd5\xfb\x53\x27\x14\x79\x38\x39\x03\x3f\x08\xd4\x80\x38\x68\x05\x69\xf0\x54\x35\x96\xf8\x68\x12\x75\xa6\xf3\x75\xd4\x9c\x89\x14\x6a\x4a\x6a\xcd\x36\x2a\x8f\x56\x8d\x9c\xb9\x41\x25\x95\x9b\x15\xb8\xe2\xdb\x7d\x5e\x7b\xc2\xa4\x9c\x6b\x37\x34\xe5\x8a\x6c\xcd\xa8\x41\xca\xd5\x45\x09\x45\xb3\x26\x62\x0f\x33\x84\x25\xfe\x70\xdc\xf0\x95\x0d\x59\x8d\x02\xbc\xa2\x25\x2b\x13\x81\x6f\xae\x66\x47\x8a\xc9\x29\x04\x93\xc3\x41\x37\xd0\xaa\x61\x72\x54\x11\x93\xed\x29\x22\x41\x78\x38\x30\x26\x60\x02\x79\x53\x5a\xa7\x5a\x40\x52\x0a\x75\x96\x20\x39\xba\x9c\x46\x84\xb3\x42\x92\x39\x04\x18\x51\x42\x46\xc3\x33\xa8\xf3\x08\x79\xe5\x2d\x07\xe9\xae\x6e\xca\x79\x1a\x3c\x3c\x3a\xc7\xa4\xa6\x8c\x19\xd1\x92\xda\x72\xdd\xf7\xdf\x6b\xee\x9d\x32\x65\x6c\xc7\xf0\x61\xe3\x12\x87\xc0\x67\xea\x84\x29\xa9\x93\x47\xfc\x2a\xf0\xa3\xbb\xfc\x1d\x3f\x1d\xb3\xb9\x02\x46\xbf\x21\x18\x1d\x01\x46\x83\x27\x0f\x81\xd1\xee\x22\x46\x3b\x52\x10\x65\xbe\x0d\x38\xd3\x04\x9c\x23\xd5\x02\x1a\x99\xd4\xd2\x6a\x41\x3b\xa6\x0a\x38\x91\x24\xa3\x11\x78\x13\xc8\xca\x4a\xeb\xd1\xf8\xc5\xc3\x98\xb4\x1a\x4e\xab\xd8\xb4\x0a\x52\xab\x59\xd4\xc4\xea\x0a\x82\xd5\x0e\x30\xb6\x8a\x5e\x4b\x24\x89\x8e\x29\x62\x75\x54\x0a\xa2\x71\x87\xc7\x6a\x27\xc5\x6a\x0f\xc5\x6a\x4f\x09\xab\xe3\xbf\x0d\x56\x9b\x32\x19\xd4\x29\x6b\x2d\xed\x99\x0c\xea\x91\xd0\x48\x42\x53\x31\xec\x28\x9d\xa9\xb9\x07\x79\x21\xde\x83\x8e\xc0\xaf\x8e\x21\xde\x20\xd5\x71\xf9\xc4\x99\x37\xde\x7c\xed\xf2\x1b\xeb\xf1\x66\x1c\x38\x9c\x83\xdd\x9a\x3a\x01\x3b\x06\x66\x78\xa8\xfb\xf6\x2b\x4e\x0f\xdd\x7a\xdb\x88\xf3\xef\xd6\x8f\x37\x8d\x4e\x31\x3c\x5f\x98\x40\x30\x9c\x02\xe3\x0f\x89\xe1\xb1\x45\x0c\x77\xa7\x20\x9a\xf0\x6d\x30\x9c\x21\x18\x4e\xab\x05\x94\x4e\x6a\x19\xb5\xa0\x1d\x5b\x46\x87\xdf\x50\x2b\xc9\x5a\x53\x0b\x15\x0a\xea\xc0\x5b\x7b\x4e\x56\x86\x25\xa9\x00\xd2\xd1\x62\xf8\x10\x26\xae\xb6\xe5\x1f\xda\xc6\xd5\x01\x5d\xdd\xc2\x83\x7d\x70\x1b\xe8\x02\x6f\x57\xc3\x75\xba\x88\xeb\x91\x29\x88\xba\x0f\x8b\x6b\xd4\x44\xd2\x47\xce\x02\x8a\x27\xb5\x26\x27\x81\xfa\x70\x0a\xf5\x0e\x0a\xf5\x8e\x12\xd4\x7b\x8e\x12\xea\x5a\x53\x5c\x92\xb5\x50\x24\x93\x41\xc3\x25\x34\x2c\x83\x3a\x64\xad\xb5\xe5\x68\x63\x06\x3c\x07\xfe\x78\x8b\x72\xc4\x9e\xf9\xf8\xe7\x5b\x67\x5e\x79\xf3\x6f\x8f\xd0\x31\xc3\xbf\xf8\x17\xac\xaf\x59\xa2\xef\xb2\xda\xdb\xea\x97\x13\xa0\x07\xfb\x91\xaa\x98\xee\x2a\x62\x3a\x99\x82\x68\xf4\xe1\x30\x8d\x5a\xb0\xc5\x9b\x9d\x24\x7d\xd4\xe2\xac\x06\xf3\x14\x81\x39\x09\xd5\x92\x5a\x4a\x2d\x68\x99\x41\xae\x5a\xab\x8b\x66\x32\x9a\xd4\x22\x91\x2d\x8f\x88\xa0\x0d\x6b\xfb\x0f\x60\x3e\xc8\xc4\x87\xf1\xd4\x83\x6c\x7c\x48\x47\x3d\xc4\xc2\x0c\x18\x33\xb0\x87\x5d\xc1\xcd\x20\x5a\x2b\x73\x01\x35\x6b\x9d\xad\x90\xf5\x91\x92\x7f\x5b\x21\xdf\xc8\x06\x7c\x9e\x84\xd6\xc8\x17\x0b\x40\x6b\xbd\xa4\x1a\x96\x83\x09\x4d\x16\x69\x01\x68\x2d\x21\xab\x70\x93\x6e\xcc\x9c\xdd\x17\xa0\xe5\x9f\x8d\x75\xb4\x93\xd6\x8e\x8d\xe5\x92\x89\x9e\x9e\x71\x69\xdb\x14\x4d\xf7\xd0\xf2\x95\xae\x72\x82\x4f\x02\xbe\x78\xcc\x36\x06\x7e\x07\xa6\xa2\xdc\x6d\x37\x9e\x76\xf7\x99\xb3\x57\x9f\xf5\xe2\xfb\x0f\x7c\x7d\xdf\x43\x8f\x3c\x79\xea\x77\xe6\xf6\xb6\x7b\xfe\xb8\xf7\xcf\x5b\xdf\x3d\xf3\xce\x15\xed\x2d\xab\xdb\x63\x1f\xbf\xf2\x8a\xfe\xd4\x2b\x77\xdc\xd1\x75\xd2\xab\x3f\x59\x04\x00\xe0\x49\x7e\x6a\xb1\x9d\x21\xf9\xa9\x5a\x50\x0f\xda\x40\xdf\x91\xe4\xa8\x50\x30\x89\x5a\xd3\x79\x99\x42\x28\x9a\x42\xa1\xa4\x16\xc6\xe1\xe7\xff\xcf\xde\xbb\xc7\x39\x51\xdd\x7d\xc0\xe7\xcc\x4c\x32\xb9\x27\x33\x93\xdb\x6e\x36\x9b\xcd\x66\xb3\xb7\xb0\x1b\x36\x61\x77\x89\xdc\xe4\x22\xe2\x8a\x56\x2d\x45\x44\x5c\xb9\x89\x88\x20\xc2\x8a\x08\x88\x88\x48\x11\x05\x61\x01\x11\x11\x11\x51\x11\x51\xf1\x4c\x12\x16\xef\x2e\x55\x6b\x5b\xaa\xd6\x5a\xf1\xf1\xb1\x3e\x7d\xec\xe5\x69\xd3\xd2\x3e\x16\x5b\x2b\xca\x0e\xef\xe7\x9c\x33\x93\x4c\xf6\x02\xd8\xf6\x7d\xfe\x78\x3f\xef\xc7\x8f\xc3\x12\xf6\x8f\x9c\xdf\xfc\xce\x39\xbf\xdb\xf7\xfb\xad\x27\x4d\x4e\xb7\x3b\x87\xdc\x14\x99\x5a\xe5\x56\x19\x82\x58\x0b\x11\x01\xf9\x57\xca\x59\x6e\xa7\x20\xa6\x61\x69\x40\x85\xb2\xda\x52\x32\x5b\x2e\x88\x72\xb8\xe6\x8c\x05\xae\x81\x03\xd0\xbe\xc5\xae\x9b\xfa\x8d\x3d\x7b\x57\xbd\x98\x1b\xfb\x09\x3b\x0d\x6a\xed\x0b\x91\xda\x57\x0c\xc4\xc1\x30\x8d\x49\x77\x80\xfa\x17\xaa\x8b\xa3\x54\x32\x5b\x45\x8d\x98\x4c\xe0\x4d\xd3\x80\x8d\x38\x5c\x5f\x16\x0b\xc3\x98\x5c\xed\xce\xa1\x6a\x17\x11\x13\x6c\x71\xe7\xa8\xbc\xaf\xd5\x96\x93\x47\xc0\x98\x1c\x56\x41\x30\xd5\x42\x86\xf3\x0e\x22\xd5\x32\x9b\x88\x82\x29\x64\x15\xd2\x76\x07\x1d\xb4\x0d\xda\x68\xc9\xcc\xee\x38\xc7\x92\xd9\xc0\x36\x3b\x63\xf9\xec\x89\xfe\x93\xa0\x01\xeb\x68\x6c\x74\x80\xf8\x9d\xf8\xe5\x16\x53\x90\xf8\xa5\x08\x82\x79\xe6\x95\x33\x7b\x65\x20\x2e\x7b\xcd\xa4\x52\xed\x32\xd2\x06\xa1\x74\x4c\xf6\x5b\x73\x19\xce\x2f\x99\x62\xff\x8e\x8a\x2a\x27\x09\x62\xda\xe6\xa5\xed\x99\x01\x5d\xae\x35\xcc\x1b\x0a\x26\xec\xeb\x66\x75\x21\xa6\x26\xa4\x4c\xba\x60\x48\xfb\xf8\x78\xfd\xd0\x3e\x45\xd5\x55\x5b\xb6\xfc\xee\xbc\x8b\xa6\x0d\xbf\xb8\x49\xeb\xa9\xe7\xfd\xaa\x0a\xc4\xb5\x49\xe6\x82\x57\xd5\xe2\xcb\xb4\xc1\xdc\xdb\xbd\xc2\x71\xb9\xd2\xd8\xbb\xca\x1a\x85\x31\xb9\xde\x9a\xcb\xd8\xea\xa3\xa6\x42\xbd\x35\x2a\x09\x62\xc6\xe5\x0d\x57\xd2\xa6\x7a\x86\x0b\xd6\x12\x4f\xaa\x17\x65\xbb\x23\x45\x70\x25\xa5\xff\x8c\x1f\x15\x1b\xe2\x8c\xbe\xf3\x66\x91\x4d\xce\x50\x7b\x0d\x75\x76\xfe\x0f\xb1\x4e\x02\xb0\xa7\xd7\x03\x60\xcc\x19\x5f\x01\x4e\x20\x01\x1f\xd8\xa5\xce\x78\x83\x24\x81\xc5\xd1\x21\x0c\x36\x27\x73\x62\x22\x91\x75\xb8\x6c\x90\xb2\x92\x3a\xd8\x1c\xb2\x27\xb2\x06\x93\x8d\xf0\x88\xb3\x39\xc2\xb7\x64\x2c\xa6\xf1\xbf\xef\xc4\x7c\x8d\x96\x95\x23\xb4\xac\x66\xca\x23\x2e\x96\x9c\x44\x66\x57\xc6\x60\xc6\x6e\x62\xc2\x4f\x64\x73\x65\xec\x36\x51\x8a\x65\x04\xfc\x64\x0f\x73\x06\x93\xd9\x66\xa7\xe3\x7b\x3a\xc6\xa5\x3c\x83\x5f\x98\x0f\x4b\x61\x33\x0c\x4b\x11\xec\x29\x4b\xd9\xfd\xec\x0b\x15\x3d\xef\xcd\x62\xec\xa1\x9e\xbf\x2d\x64\xe2\x91\x9e\x92\xe9\x4a\x9b\xf2\x1b\xb8\x16\x2e\xec\x9c\x14\xc2\x76\x21\x1c\xe3\x7b\x7a\xbe\xdc\x4b\xfd\x84\x39\x00\x7d\x9d\x9d\xaa\x6f\x18\x67\x1a\xe6\x81\x7a\x30\x14\x0c\x07\xe3\xc1\x61\xaa\x99\x9e\xae\xc5\x66\x28\x4f\xca\x8d\x7c\x0e\xf9\x13\xa4\xfb\x43\x71\xe3\xf6\xa4\xdc\xcc\xe7\xd0\xb8\x44\x56\x1a\x51\xcb\xd9\x63\xb2\x64\xcc\xa1\x54\x5c\x3e\x0f\x2f\xff\x42\xe2\x29\x31\x29\x87\x62\x04\xbf\xa7\x8a\x13\xa2\x4a\x97\x3c\x1a\xdf\xf6\x42\x4e\x9e\x00\x63\x72\x24\x26\x88\x19\xae\xb6\xb1\x19\xbb\x48\xa5\x90\xad\x8a\x26\x52\xe7\xe1\x9f\x47\x8b\xe7\x9b\x8d\x76\xb7\xc7\x5f\x3e\x6c\xf8\x08\xb5\x20\x47\x31\x1a\x52\x44\x10\xbb\x40\x00\x67\x6a\xb1\x2a\x5f\x4a\x6e\x1e\x21\x88\x87\x78\xa3\x2b\x61\x19\x5d\x34\x97\xd1\x9a\xe4\xd5\x4b\x8e\x0b\x47\x78\xdd\xb0\x6c\x0d\x5f\x98\xd6\x28\xaa\xd6\x92\x39\x6a\x4d\x71\x6e\xe6\xfd\x7f\xdd\xf0\xf4\x65\xd6\xb1\x1d\xc1\xd6\xa7\xe7\x2e\xdf\xae\xa4\x95\xf7\xea\xb8\x15\xab\x87\xdd\x35\xff\x89\x7d\xf3\x1f\xab\x0f\xde\xe6\x37\xcd\x7d\xb2\x7d\xc5\xc6\x17\x2f\x1a\x33\xad\xab\x63\xea\xc4\x99\x4f\xcd\xa0\x3a\xa1\xca\x5b\xe2\xc7\x9f\x8f\x1b\xb1\xe8\x25\x38\xfd\x3d\x38\xe7\xc7\xaf\x1d\xb8\x7f\xe2\xe4\x7b\x6e\x3b\xfc\xd3\x89\x77\x6c\xae\x1a\xbc\xfb\xe2\x4b\x2e\x5d\x77\xf4\x8e\x19\x6f\x3d\x7f\xf3\xc2\x34\xac\xde\x7a\xdd\xad\xcf\x28\xbf\x65\x3e\xee\xec\xec\xd9\xd6\x31\x3f\x35\xee\x45\x95\x8f\xfa\x32\xc3\x51\x50\x0d\x9e\x56\xe7\x15\x45\xad\x56\x6d\x65\x73\x59\xaf\xaf\x0a\xdb\xda\x1f\x4c\x26\x65\xaf\x31\x27\x7b\x2a\x12\x89\x6c\x69\x80\x7c\x58\xca\x52\x95\x59\x0a\x47\x75\x7a\xf2\xea\x3a\x23\xef\x3a\x31\x86\x92\xd2\xa8\x38\xa9\xa0\xeb\xa4\x03\x85\xbb\x0d\xc8\xed\xca\x78\xdc\x25\x52\x2c\xe3\xc7\x4f\x14\x76\x65\x2a\xc2\x41\xc2\x28\xe9\x0e\x37\x36\xc2\x2e\xb7\xc7\x5f\x12\xac\x08\xeb\xdc\x4f\x2e\xf5\xa9\xb8\x38\xd9\x1a\x50\x39\xee\x35\x72\x0b\x5e\xc7\x6e\x3d\x0a\x86\x5b\xc9\x7f\xac\x4a\xab\xa8\x72\x0b\x2e\x39\x3a\x77\xfc\x25\x07\x6f\xd0\x28\x05\x43\xca\x9f\x43\x50\x0c\x13\x62\xc1\xb1\xab\x43\xab\xcf\x2b\x26\x17\xac\x6d\xdc\x53\x99\x50\x59\x05\x37\x6e\xe9\xdc\xa3\xbc\xb7\x45\xf9\x8a\x30\x0b\x02\xc0\x80\xa4\xe2\xe6\xe6\x72\xed\xa0\x0a\x34\x81\x49\x2a\x4b\x5b\x2d\x9f\x4b\x97\x62\x27\x25\xc8\xea\x46\x3a\xd3\xcc\xf2\x39\xc4\xc7\xb1\x1b\x9b\x8c\x39\x54\x96\x20\xc5\x42\xf1\x98\x1c\x95\x48\x01\x10\xc8\x3c\x4b\xa3\xa6\xc6\x5a\x41\xcc\xda\x44\x7f\x89\x95\x3a\x13\x99\x8d\xc5\xab\x18\x05\x23\x2a\x42\x4c\x73\x2f\x48\xa4\x99\x23\x95\x35\x45\x20\xf2\xe4\xa8\x97\x2e\xbe\x6e\x79\x54\xf9\x24\x04\x47\xa7\x3c\xa6\xab\x33\xd7\x6c\xdc\x7d\xef\x17\x3b\x5f\xbf\xd2\x3c\x76\xbd\xa2\x7c\x3f\xb8\x6b\xf4\x7f\x3e\xfc\xd6\xda\xe3\x57\x7d\x6f\x5a\xd7\x92\x1f\xcf\x79\xea\xda\xd3\xa0\x7a\x70\xbc\x75\xcb\x5f\xbe\xb3\x64\xde\xab\xe8\x67\xf0\xda\x1f\xbc\x76\xe0\x9b\x29\x5b\xbe\x7f\xeb\x78\xd6\xb1\x70\xd6\x3e\xe8\xdb\xfe\x5f\xfb\x94\xdf\xaa\xfc\x17\x86\xcb\xf8\x0e\x50\x0e\x1a\xc0\x1d\xaa\x32\x76\x2f\xcf\x28\xe3\xec\x31\xe4\x4f\x12\xae\xf2\x02\x05\x06\xf6\x83\x78\x2f\x4a\x49\x0d\x2f\xe7\xc7\x7e\x50\xd2\x0d\x64\x37\xa1\xce\xc7\x6f\xbb\x80\x36\xf1\x8a\x82\x28\x3b\x01\x7e\xd1\x3e\x0a\x12\xe7\x04\x1d\x37\x4b\xf1\xeb\xd6\x51\x48\xf6\x6e\x7b\xf4\xf3\xd6\x8b\x89\x24\xe1\x89\xa2\xee\x47\xdf\x37\x9f\xe7\x93\x34\x5e\xd4\x4b\xd3\x85\xa5\x3e\x60\x0c\x83\x72\x50\x0f\x52\x60\xbc\xaa\x38\x10\xe6\x73\x69\x1f\xf6\x02\x49\x23\x5a\x2c\x53\x01\xc6\xe7\x91\xb8\x32\x24\xe5\xe4\x61\x44\x25\x41\x7d\xf1\x35\x65\x82\x98\x31\x39\x3d\x5e\xdd\x7b\x1f\xc5\xf4\x7e\xe7\xac\xfa\xc2\x0b\xef\xbb\x57\x07\x04\xbf\xfe\xb5\xbb\x2b\x92\x12\x7e\xf3\xf7\xed\xd9\xf2\xc5\x76\xf2\xe6\x4f\xc6\x4f\xbc\xff\xd6\xda\x3f\x1c\x9c\xfa\x5a\xc7\x8f\xaf\x3b\x30\x63\xb3\x7e\xbd\xd8\x03\x56\xaf\xff\xf9\x05\x4b\xe6\xbd\x99\xfe\x08\x5e\xd7\xfd\xda\x81\x6f\x96\xfe\xf2\xfd\xf1\x2c\xf7\x69\x17\x0c\x77\xfe\xd7\xd3\xca\x7f\x71\x96\xa2\x55\x33\x84\x33\xaf\x99\xef\x00\x36\x10\x00\xf7\xa9\xf1\x8c\xc9\xa6\x4d\x54\x30\x86\x64\x7e\x7a\xc7\x66\x21\x63\x6f\x5a\xcf\x2d\x38\x10\x63\x9e\xcd\x95\x61\x6d\x8c\x14\xcb\x58\xf1\x33\x6d\xb5\xf5\x61\xcc\x23\xc3\x3b\xac\x55\xd7\x5d\x4f\x5b\xf0\x8d\x8e\xa3\x17\xa0\x22\x52\x28\x5b\x5e\x92\x72\xe4\xf5\x1d\x19\xec\x7a\x70\x15\xd3\xf4\x69\xcf\x5a\x95\x29\x0f\xc6\x8a\x1b\xc2\x3d\xe7\xad\x63\x46\xf5\xac\x54\x09\xf3\x8a\x07\x26\x19\xc2\x9d\x37\x9e\xdf\x45\xba\xdf\x8f\x6b\x53\x24\x8e\x64\x92\x62\x97\xd4\x91\xa5\x72\x7d\x93\x4b\x5b\x74\xa8\x98\x40\x4f\x83\x10\x5a\x91\xc3\x95\x61\x1d\x84\xfc\x92\x3c\xed\xf8\x99\xb6\x3b\x8a\x97\x8e\xb8\x14\x48\xdb\x59\x8e\xcc\x38\xd3\x3f\xe9\xf8\x92\x43\x93\xdd\x63\x84\xb4\xcd\xe9\x4a\x69\xd2\x49\xb2\x41\x1b\xad\xb1\xc0\x02\x73\x5e\x2f\x3f\x69\x85\x6d\x5d\x53\xae\x6d\xd4\xf3\xe7\xfd\x4a\x6f\x0d\xa3\x5b\x99\xa3\x8c\x5f\xaf\xa3\xd1\xe3\x57\xf7\xea\x6b\x2a\xe3\x54\x1e\xa6\x00\x18\x04\x16\xd2\x9e\x5f\x36\x44\xc5\x29\xb5\xd6\x26\xaa\x8f\x67\xa3\xaa\xd8\x62\x83\xbe\xc9\x59\x86\x2f\x5f\x7b\x0e\x45\x0a\xfd\xce\x46\x18\x93\x3d\x11\x41\x3c\x6c\x15\x38\x7f\xa8\xa2\xa6\x9e\xa4\x93\xd6\xa8\x20\xca\x65\x91\x54\x4a\xf6\x87\x04\x31\xcd\x03\x21\x75\xb6\xb6\xa7\xd4\x5b\x4b\xf1\x0c\x8d\xcf\x19\x7a\x3d\xc5\xb3\xf4\x3d\xbf\xf9\x7d\xb1\xee\x24\x0b\x66\x2a\xe3\xb8\x30\x37\x05\xd8\x41\x39\x18\x04\x6e\x52\x6d\x20\xa8\x36\xc0\x3b\xbf\x8e\xec\xfc\xac\xaf\xc8\x06\x21\x4b\x2e\xe3\x08\x01\x53\x4c\xf6\xd8\x73\x28\x44\xdb\x42\xbc\x44\x4d\x50\xed\xa1\x26\x10\x4b\xca\x2a\x69\x41\x01\x9f\x7e\xb2\xc3\x93\x4a\xc9\x75\x02\x31\x41\x65\xaa\x6f\x5f\xb4\xcf\xa2\xa5\x3e\xbc\x34\x6a\x67\x74\xa7\x7e\xc9\xc1\xde\x3c\x48\x6a\x67\x54\x91\x74\x6b\x65\xbe\x2c\x62\x43\xe2\xe8\xbb\x37\xbe\xa2\xbe\xfb\xc1\x60\xd9\xd9\xde\x3e\x6a\x88\xcb\x8d\xc6\xbc\x06\xf0\xc0\x4e\x90\x50\x9d\xe0\x7c\x8b\xe6\x05\x0d\xf1\x7f\x9b\x1f\xe0\x20\xfe\x5c\x7d\xe1\x0d\x1c\x4b\x7d\x1b\x87\xe0\xb7\xa8\x71\x2c\xf6\x09\xc3\x3c\xd5\x27\x06\x83\x3b\xcf\xe6\x15\xbd\x6c\x33\xa0\x73\x24\x54\xe7\x20\xa6\x21\xde\xd1\xd0\xa8\x4e\x05\xc4\xc9\x18\xd1\xbf\xc3\x4f\xb0\x89\xce\xc1\x57\x3a\x89\x22\xfd\xb9\x39\x0c\xf3\x3c\xd1\x71\x27\x78\x3f\xbe\x83\x4c\x08\x4c\x39\x1b\xe2\x2f\x96\x47\xfc\x0d\x52\x11\x7f\xb2\x9d\xd4\x46\xfe\x05\xcc\x5f\xaf\xfb\xe0\x4c\x10\x40\xf8\x7d\xfd\x59\xd8\x3f\x20\x90\x1f\x51\x74\x3f\x9c\x5e\xa6\xb8\xd9\xc7\x8c\x61\x50\x02\x6a\xc1\x05\xa0\x00\x3a\xf2\xa9\x48\xd6\x3a\xa2\x3e\x26\x59\x28\xd1\x8c\x64\x10\x44\xd9\x1a\x25\x4a\x92\x3e\x2a\x68\x65\x13\xd2\xc0\x45\x54\x66\xec\x22\x41\x10\xb3\xde\x01\x96\x52\xd3\x6b\x29\xeb\x1e\x78\x31\xf3\xee\xd3\x4f\x4e\x0c\xc0\x5f\xf5\xe4\xc2\xcc\x1f\x02\x8a\xeb\xa9\x1f\x6e\x50\x7a\x0e\xfc\xe4\x4e\xf8\x7c\xf1\x55\x3f\xe5\xe7\xf2\x86\x4d\x2b\xe0\x5f\x77\xac\x51\x80\xfd\xe3\x83\x8f\x9e\x5c\x37\x9e\x7f\xb6\xb7\x4e\x1d\xd1\x87\x73\x18\xc3\xe4\x7e\x9f\x45\x99\x40\x90\x91\x70\x2d\x91\xa5\x94\x51\x21\x35\x41\x2f\x7c\xf2\x48\x9e\x61\x9d\x23\xc2\x90\x7c\x37\x90\x39\x1e\xdf\xd9\xf8\x99\xd7\x3f\x93\x05\x32\x5e\xcb\x58\xe8\x6b\x33\x50\x5e\xf8\xe2\x99\xb6\xe2\xc5\x29\x4a\xf1\x00\x1b\x7c\x50\xbf\x22\xfd\xb8\xda\xa7\x7d\x62\x33\x82\xfb\x30\x74\xa9\x18\x87\xb3\xa3\x3e\xca\xf3\xc0\x86\xd0\xff\x0d\xea\xe3\x1c\x61\x1e\x67\x02\x76\xa8\xeb\x34\x7d\x9c\x5f\xe7\xa2\x73\x47\x72\xfc\x2b\x0b\xce\x23\x39\xfe\xd9\x45\xf6\x02\x6b\x9c\x09\x9e\x41\xe7\xf1\x4c\x51\xa2\x73\x15\x06\xb1\x6f\x89\xc6\x18\x74\x16\x34\x46\xc3\xff\x29\x1a\xe3\x5b\xc2\x2f\xce\x0d\x70\x01\x8a\x73\xb4\xda\x73\xcd\xd1\xea\xf2\x39\x5a\x6f\xda\xff\xff\x97\x73\x34\x4d\xe6\xf4\xec\xe9\x19\x73\x50\x95\x3e\x3d\x53\x66\x66\x28\xcb\xcb\xa1\x16\xe7\x64\x43\xce\x21\x27\x6b\xce\xe7\x64\x2d\xff\x8e\x9c\x4c\xa7\x12\x7f\x4e\xe9\x18\x1c\xa2\x2e\xf0\xec\xa9\x18\xf3\x69\x41\xf5\x15\x82\x49\xa7\x8f\x1b\xbf\x32\x74\x81\x72\xf0\x95\x3a\xf5\x58\x9e\xa4\xdd\x1c\x5b\x1e\x59\x63\x30\x26\x93\x49\xc2\x15\x86\x84\x64\x96\x0d\x7a\x5d\xf6\x18\x2a\x4b\x12\x49\x58\x2e\xaf\xe8\x54\x4e\x3b\x61\x3a\x94\x45\x09\x8c\xc9\x66\x0b\x99\x75\x57\x49\xb0\x91\x91\x72\x30\x0a\x96\x02\x8d\xe0\xa3\x27\xde\xa6\x39\xcd\xae\x13\x2f\xe7\x6f\x80\x80\x7a\x03\x14\x28\xff\xc9\x14\x3c\x12\x5c\x48\xec\x36\xa0\x72\x57\x86\x2d\x67\xa4\x18\x0a\xb8\x32\x5c\xc0\x20\xc5\x32\x65\xf8\x89\x3f\x0f\xe2\xcf\x59\x90\xe1\x9d\x62\x80\x8e\xb7\xb3\x1c\xfe\xb9\x2c\xa8\xab\x40\xd2\x8b\xc4\xe6\xa5\x63\x99\x30\xc9\x86\x8b\x09\x89\x1d\x8c\xca\x09\x14\x26\x3c\xe9\x6b\x98\xf3\xd6\x64\x3f\xb3\x4f\x68\xbb\x6a\x4e\xd5\xfd\x5d\xf7\x47\xe7\x3c\xbc\x72\xc7\x7e\xe7\x88\x9e\xb7\x37\x1b\xba\x7a\xb6\x33\xf3\xbe\xf9\x78\x44\xf4\x7b\x17\xdf\xfd\x14\xb3\xa5\x67\xe6\x73\xaf\x4e\x7e\x68\x63\x6a\x28\xac\xe9\x99\x0c\x00\x73\x3a\xa7\xb8\x0d\x36\xc3\x3b\x04\xa7\xf1\x28\x65\x05\x22\x0a\x51\x24\xb8\x05\x71\xe4\x4a\xe6\xb1\x19\x2e\xd2\x3e\xd4\x8d\x9d\xe3\x88\xd6\xe2\xd6\xd3\x11\xbf\x42\x0d\xe4\x72\xa1\xb2\xee\x8c\xd3\x55\x46\x64\xa1\xca\xa4\x58\xda\xe9\x2a\xd3\xa5\x7c\x42\x0a\xa4\x9d\x42\x19\xc9\xf7\xe8\x9f\xbd\x30\xad\x1e\x41\xe6\xfd\x64\x0c\x74\x20\x4c\x2b\xcf\x00\x03\x2b\x55\x01\xed\xec\xe1\x7d\x70\xcf\xb6\x80\x65\xf6\x4f\xef\x78\xf8\xb0\xed\x3c\x85\x51\x5a\x66\xdf\x07\xad\x70\xce\x0b\x73\xae\x99\xff\xd3\x87\x63\x8a\x9b\x7f\xe2\xf7\xf7\x2e\x3e\x26\x4f\x19\xae\x74\x29\xf5\xfb\x94\x5a\xe6\xde\xf9\x30\x08\x67\xbf\xbc\x60\xf9\x93\xca\xbb\x3f\x26\x67\xcb\x15\x00\x18\xd2\x7c\x07\x70\x81\x12\xf0\xf3\x7e\x51\x14\x04\x51\x5d\x00\x4b\x88\x38\xcc\xf1\x90\x52\xbd\x8a\x9b\x90\x03\xff\x04\x46\xe2\x5c\x01\x29\x19\xde\x49\x41\x10\xf0\x10\xe4\x2d\x4e\x0d\x10\x41\x6c\x27\xba\x04\x51\x66\x6c\xa9\x94\x6c\x92\x04\x31\xc3\x5a\x3d\x94\xf5\x17\x02\x61\x60\x24\x0a\xed\xca\x36\xc2\x7e\xa1\x0e\xf0\xb1\x23\x75\x73\x6e\x1a\xf3\xfd\x3e\xc8\x06\xbe\xdd\xb3\x6e\x7f\xc9\x98\x97\xa8\x5e\x2d\x00\x5c\xdc\x18\x26\x5a\xaa\xcf\xf7\x46\x33\xe4\x81\x0c\x79\x69\xa4\x3e\xd0\x05\x9c\x20\x05\x3d\x44\x5a\x68\x20\x14\x83\xc6\xd7\xd5\x2f\x62\x01\xc8\x76\x17\x0e\xc1\xf0\xb3\x17\x28\xc1\x19\x14\x44\x14\x26\xcc\x86\x26\x4f\x88\x2a\x2f\x79\xa8\x3f\x9d\x0d\x81\x20\x69\x96\x19\x00\x72\xf0\x15\x35\xcd\x00\x00\x03\xa3\x4d\x33\x10\xed\xd9\x2e\xe1\x0f\x00\x17\xf0\x01\x3f\xa8\x02\x0d\xe0\xbf\x55\x2b\xd9\xec\xc9\x24\x72\xc6\x91\x23\x29\x0b\x6c\x0e\x89\x09\xe4\x89\x23\x77\x32\x5b\x46\x53\xa6\xca\xb8\x6c\xe4\x72\xa4\xc2\xc8\x1e\xcb\x96\xd0\xda\x7e\x09\xa1\x46\x46\xf6\x44\xd6\x4c\x3e\x90\x6d\x42\xbe\xf2\xd8\x7d\xd3\x57\x3b\x34\xbe\x53\x77\xb7\x0a\x13\x24\xe5\x67\x87\xdb\x2e\xc5\x32\x22\x7e\xbe\xd4\x3d\xeb\xab\x2f\x89\x10\x90\x84\xff\x9a\x96\xdc\xf6\x22\x59\x5f\xa9\xb1\x11\x66\xad\x0e\x51\xe5\xf3\x26\x16\x2d\x61\x29\x3d\x61\x48\xe8\x32\x7a\xca\x2a\xa3\xd5\xa4\xdb\x64\xa6\xe3\x44\x65\x2a\x77\x61\xa5\x90\x36\xfb\x59\xca\xe3\x00\xab\x9b\x35\x46\x3f\xb5\xd3\x66\x85\x11\x07\x64\x7d\xaa\x0a\x28\xde\xb0\xf9\xe1\xad\x25\xcc\xcb\xb1\xe5\xb3\xe6\xac\x98\xba\x2b\xd3\xac\x08\x9f\xc3\x09\x70\x4d\x38\x50\x3a\x28\xf1\xec\x8f\x86\xb5\x24\x47\x8d\x4a\x0e\x1e\x1d\xbb\xfa\xfb\xbf\x4e\x7c\x30\xca\x60\x1b\x32\xa5\x7d\x59\xc7\xcc\x5b\x46\x7f\x13\x50\x3b\x70\x61\x58\x33\x6d\x36\x7c\xb3\xbc\x79\xf8\xf0\xe6\x96\xe1\xc3\x7f\xe1\xbe\xfc\x71\x31\xb1\xbb\x1a\x68\xfd\x5d\xfe\x00\xe9\xc3\x0d\x02\x43\xc1\x68\xf0\xcc\x99\xfb\xbb\xf5\x71\x79\x30\x97\x43\x2d\x71\xb9\x0a\x9b\x7d\x4c\xaf\xb6\x6e\xb6\x81\xbe\x81\x06\x97\x9c\x84\xb1\x6c\x0d\xfd\x5b\x8d\x0b\x59\x2b\x8e\x09\xb2\xcd\x46\x48\x47\xac\xb6\x9c\x3c\x56\x6d\xf3\xca\x2e\x6f\x2a\x25\xdb\x1a\x04\xf1\x30\x17\xac\xaa\x1f\xdc\x42\xbb\x2e\x56\x21\x6b\x77\x94\x0e\x1f\x4d\xd1\x11\xfa\x16\x9d\xdc\x32\x58\x10\xe5\x9a\x70\xea\x9c\x9b\xbe\x79\x59\x9d\x7e\xcc\x7a\xc6\xf6\xdd\x27\x77\xcc\x98\xb9\x62\xf9\xac\x39\xcb\x6e\x1a\x9a\x4a\x8c\x1a\x3d\x38\x39\x32\x71\xfd\xf2\xcf\x86\xbc\x73\xc1\x19\xba\xbf\x6b\x66\xdc\xba\x78\xd6\xac\x5b\x3a\x66\x26\x47\x8e\x1e\xdc\x32\x6c\xd8\x9f\xc4\x6b\x1f\x10\x87\xec\xa8\xd5\xfa\x7a\x7c\x07\xe9\xeb\x05\xc1\x03\xff\x64\x5f\x0f\x87\xea\xf9\x18\xfd\xff\xa4\xa1\x27\xe5\x83\x98\xb3\xb4\xf5\x3e\x55\x83\x97\x7e\x3a\x7b\x85\x58\x45\xed\xef\x19\xc3\xa4\xbf\x37\x06\x4c\x04\x07\xcf\xb1\xbf\xd7\x96\xc8\x4a\x63\xb5\xfe\x1e\x44\x97\x0c\xdc\xd8\xbb\x50\x6d\xec\x5d\xda\xb7\xb1\x97\xae\x8a\x26\x70\x34\x7f\x61\xbe\xad\x97\x1a\x39\xf6\xcc\x6d\xbd\xb1\x5a\x5b\xef\xc2\x7f\xb1\xad\x97\xb7\x23\xfb\xaf\x34\xf7\x98\x3b\x55\x33\xb7\x7e\xfb\xf6\x9e\xf6\x1a\xb4\x26\x1f\xe9\xc5\x2f\x39\xfd\xac\xa1\x8b\xef\x20\x2c\xfa\xb5\x20\x01\x96\x00\x2a\xed\x5c\xc9\xe6\x68\x8c\x53\xc6\x52\x50\x1d\x7b\x4c\xf6\x79\x08\x3f\x7b\x35\x8c\xc9\x4e\x37\x01\xc9\xc9\x3e\x56\x10\x09\x83\x0b\xaa\x16\xce\x37\x9b\x79\x8f\x54\x5a\x51\xd7\x90\xc0\x36\x75\x8a\x19\x8b\xad\x91\x96\xed\x2a\xf1\x66\x27\x7c\x42\x65\xc2\x21\x68\x63\x9d\x25\xb5\x94\x80\x4b\x36\x13\x35\xa2\x51\xb0\xba\x59\x95\x06\xf3\xf1\xe5\x90\xd2\x92\xd7\xf0\x92\xdb\x07\xe9\x56\x56\x4d\x59\x53\x30\xe3\x92\x75\x37\xbc\x0e\x2f\xfb\xf0\xb5\xf5\xab\x97\x6e\x1d\x9c\xe8\x52\x5e\xfa\xe8\x8d\x75\xab\x6e\xac\x61\x3e\x98\x76\xcf\x8e\x2f\xef\x59\x3d\x6d\xdd\x8e\xcf\xd7\x86\x94\xd5\xaa\xb9\x2c\xfb\x37\xfc\x8e\x14\xf1\x6e\xdc\xdb\x9e\x1d\xf5\xf2\x8d\xa4\x8e\xd7\xbe\x9b\x59\xb1\x6a\x0a\xbb\x7e\xd2\xdb\xca\xce\x9e\x0f\xc6\xff\x08\xce\x39\xb6\x60\x12\xfc\xb8\xe0\xae\x80\x03\xc3\x4e\xa7\xb9\x2b\x8c\x61\xc2\xbb\x5d\x03\x9a\xb0\x7d\x48\x96\x19\x36\xe6\x28\xaf\x49\x80\xa7\x33\xff\xec\x31\xd9\xeb\x24\xba\x40\x51\x18\x23\x0a\x14\x49\x18\x93\xbd\xac\x20\xa6\xa1\x9b\x30\xc2\x45\x85\x2e\x5e\x2c\x09\xd5\x0e\x6a\x22\x92\x9a\x62\xd6\x6c\xb1\x91\xda\x1d\x90\xc3\x44\x15\xda\x9d\x4a\xa1\x00\xb6\x8f\x83\xf5\xd7\xf4\xb1\x0f\xf5\xbc\x56\x9f\x46\x39\x9e\x37\x8f\x03\xf6\x63\x9e\x61\x0b\xc7\x77\xfe\xe3\xe1\x6d\x73\x66\x2f\xe8\x18\xf9\xc0\x89\x1d\x9b\xae\x9b\x39\x4f\x80\x5f\xa5\xae\xba\xe1\xe0\xf4\x6b\x9a\x67\xce\x7e\xaa\xdd\xae\xe4\x54\xdb\x18\xd7\xcf\x7d\xf4\x35\x78\x59\x76\xf4\xed\x97\xaf\x9a\xf1\xd8\x0f\x95\xa7\xd2\xa3\x56\xc2\xcf\xaf\xac\x66\x3a\x1a\x3a\x4f\x2b\x4b\x63\x9b\x20\xd8\x3d\x21\x0a\x5f\xd3\xdb\x85\xdc\xd9\x01\xbe\x03\xf0\xe4\xd6\xae\x00\x87\xfb\x9d\x67\x11\xc8\x3c\x8b\x58\x40\x02\x86\xe3\xc8\x9c\xa7\x11\xe4\x20\x19\x61\xc9\x94\xb2\x9c\x49\x25\xc6\x8f\x13\x3d\xe3\xca\x7e\x66\x5a\xa4\xfc\x4c\x8b\xe4\xca\x18\x24\x7c\xb6\x89\x12\x9d\x69\x91\xc8\x4c\x8b\xa8\xd5\x24\x08\x80\x1b\x09\x29\x54\x22\xa4\xa1\xcd\x41\x86\xab\x44\xe4\x49\xc9\x6c\xa9\x20\xca\x65\x44\xcd\x04\x0a\xa4\x4c\x53\x98\x74\xc9\x47\x33\x12\x1d\x79\xc9\xff\xbd\x30\xec\xa2\xbc\xd1\x38\x6b\xf1\x88\x75\xf5\x74\xe4\x65\xf8\x9b\x35\x73\x6e\x6e\xb9\x5b\x9b\x75\xe1\xdb\x3d\x0f\xee\x28\x19\xf1\xd2\x37\x13\xd4\x99\x97\x2b\x3c\xf7\x3c\x55\xd2\x92\x29\xcc\xbb\x84\x81\x08\x02\xa0\x0e\x24\xc0\x32\xfd\x2d\x1b\x2a\xba\x65\xab\xf9\x3c\x84\xb5\x4c\xca\x65\xdc\x65\xa4\x02\xec\xd1\x06\xf5\xe5\x41\x9e\x5c\xc6\x36\x28\xa6\x4e\xba\xe0\x1d\xe8\x71\xe3\x7b\x34\x94\x4a\xa1\x98\x20\xfb\x4a\x52\x29\x34\x48\xcc\x70\x76\x07\x65\xae\xae\x0e\x9d\x0d\x5b\x98\x5f\x28\xdb\x17\x34\x86\x3f\xee\x7b\x49\x1e\xa0\x76\x70\x16\xee\x4a\x78\x19\x35\x46\xf1\xd5\x68\x98\xa6\x9a\xe4\x7e\xfd\xb4\x8b\x4d\xb3\x0b\xc5\x92\x0e\xe1\x47\x92\x99\xa8\x00\xf8\xc1\x39\x4d\x44\x95\xc4\x09\xa0\xac\x84\x50\xd1\x94\x38\xcd\x31\x52\xbe\x28\xc3\x99\x7b\x36\x40\xef\x80\x40\xde\xb3\xb0\xc3\x78\x2a\x8e\x09\x59\x2f\xfd\x17\x6f\x3c\xeb\xa1\x31\x61\xf0\x5f\x9c\x9a\x0a\x08\x62\x06\xda\x84\x12\x9a\x3f\x0c\x34\x36\x25\x86\x13\x5e\x0f\x1f\x21\x24\xda\x7d\x87\xa6\x36\x8e\x82\xce\x8e\xfb\xd8\x79\x17\x5d\xbd\x3f\xd2\x67\x22\x2f\x04\xa5\xe5\xf3\x1b\x86\x8f\x5e\xa9\x61\x50\x0d\xc7\x49\x9c\xd6\x00\xf6\x9e\x39\x46\x8b\xc5\x89\xa6\x42\x2c\x82\x0d\x14\x0b\x9b\x63\xa8\x26\xdf\x83\xef\x37\x54\xab\xcd\x87\x6a\x19\x6b\x4d\xad\x29\xa6\x0f\xd4\xe2\xba\x79\xbc\x06\x81\xf0\xc2\x89\x19\x2e\x18\x89\xd1\x30\xed\x9f\x9f\xc7\xd3\x5b\xe6\x8c\x61\xd8\x0a\x9d\x91\x06\x8e\xbc\x98\x8f\xf3\xe6\xa2\x75\x50\x6e\x21\xdf\x01\xac\xc0\x0d\x82\x60\xa3\x8e\x57\x9c\x04\x5a\x1c\x9b\xcb\x1a\x88\x5f\x69\x21\x15\xd1\x0c\xa2\xcd\x28\x02\xe8\xef\xbf\x10\xca\x91\x42\xa8\x59\x20\x41\x16\x14\x7a\x07\x59\xec\x21\x00\x71\x5c\x55\x28\x50\x78\x1d\x78\x6b\x8a\x29\x52\x0d\xb6\x5a\xd4\x42\x45\x21\xc6\xca\xef\xb1\xa8\xf6\xc3\x24\xd8\xcc\xfc\x4f\xa4\xe7\xfd\x19\x8c\x35\xd4\xf3\xb7\x45\x4c\x53\x44\xb1\xd0\xdd\x06\x47\x6b\xe7\x8d\x1a\x5e\x69\x07\xce\xf0\xa2\x73\x86\x3d\x42\xb0\x7a\x61\x10\x03\x43\xc0\x5a\x75\xa6\xd7\xa9\x21\x30\xeb\xf8\x5c\xd6\x52\xe9\xc5\x51\x94\xc5\x48\x0b\x5e\xb4\x39\x9f\x29\xb5\xe1\x83\x26\xe0\x21\xf5\xd0\x06\x18\x93\x1b\x3d\x39\xd4\xa8\x76\x9d\x5c\xa4\x20\x26\x07\xf0\xf1\x69\xad\x4c\x61\x57\xc8\x38\xbd\xc1\x10\x76\x82\x46\x51\xae\xe3\x52\xaa\x16\x04\x92\x48\x4b\x06\x88\xa9\x14\x2d\x91\xf2\xfa\xc6\x93\x2e\x52\x22\x01\x52\xe1\xc8\xcd\x47\x44\xf9\x8f\x66\x6e\xfd\x7a\xc7\xae\xdd\x0a\x52\xde\xad\xe4\x96\xdd\x71\xc9\xc6\xcb\x67\x6d\x9b\xf4\xd2\x2f\x16\x52\x5b\x4c\x70\xfe\xe7\xe7\x13\x2e\xbe\xbe\xeb\x67\xea\xa9\xb3\xfe\x15\x38\xf9\x8d\x75\xcb\xba\xde\x99\x78\xc7\xe6\x41\xb5\x3b\x1b\xc3\x9f\x18\x2e\xa0\xc6\x39\xf5\xc8\x2d\x0b\x9b\xc7\x1d\x61\x39\xd5\x48\x8c\xea\x1b\x23\x81\x15\xf8\xc1\xd3\x67\xf6\x0c\xe4\x8d\xcb\x0e\x3e\x97\xf6\x3a\xf0\x56\xf2\xda\xcc\x31\x24\x26\x88\x24\x9e\xed\x58\xd6\x4f\xf7\x8f\x9f\x30\x03\x67\x45\x7a\xaa\x94\xfe\x1b\x9c\x46\xf2\x0b\x62\x86\xb7\x3a\x2c\xd8\xba\xa2\x80\x8c\x7d\xbc\x46\xbf\x77\xfa\x71\x98\xdd\x45\xc7\x8a\xea\x2d\xc6\x58\xf1\x79\xc2\x1e\x31\x1c\x27\x73\xdf\x71\xb0\xa7\xb7\x97\x54\x60\x2f\x29\xd1\xbc\x04\x35\xc4\x89\xe0\x46\x43\x14\x5b\xa1\x21\x62\x8e\xa1\xba\x84\x36\x83\xa9\xce\x75\xe0\x00\x3c\x4e\x0d\x12\x77\x11\x76\x4e\xde\x95\x43\xb5\x09\xc4\xbb\xb2\xf5\xf4\xf3\xfa\x38\x99\xcb\x8c\xd8\xb0\x0f\x95\xa4\x52\x72\x10\x08\x62\x96\x73\x7a\x29\x1e\xbe\x5e\x90\x25\x11\xbb\x91\xc5\x89\x23\x21\xec\x40\x15\x25\x67\x75\xa0\x82\xdf\x14\x9d\x27\xfd\xfa\xce\x87\xaa\xd3\xd8\xf5\x07\x4a\x5f\xcf\x81\xfb\x88\xc7\xc0\xf7\x0b\xf6\x22\x58\x78\x6f\xfe\x3c\xb9\xeb\x0c\x68\xf8\x33\x1e\x25\xdf\x0a\x1f\x2f\x3b\xec\x1a\x04\xdd\x2b\xa8\x87\x88\x28\x5b\xac\xe4\x10\xd1\x23\xe7\xfb\x1e\x22\x45\xe0\x79\x65\x53\xf1\xf9\x51\x84\x9f\xef\x7d\x84\x00\xf6\xf4\x4b\x00\x30\xf3\x8c\x61\x60\x02\x36\xe0\x01\x33\x40\xda\xac\x2a\xcd\x58\x20\xe1\x1a\x26\xf4\xe7\xf0\x98\xcc\x78\x72\x19\x33\x03\xf1\x75\x41\x0b\xc5\x0e\x18\x43\x96\x84\xec\xf4\x10\x09\x52\x5f\x7f\xa8\x7a\x1b\x43\x79\x96\x1c\x42\xda\xc0\xd9\x53\x64\x29\xac\xf6\xad\x03\x30\x59\x08\xc2\xc6\xd3\x2f\x3d\xe3\x8f\xd9\x5c\x8c\x7e\x6f\xa3\x8d\x7e\xd7\xaf\x07\x13\x74\x7d\x3e\x8a\xd0\xb8\x0a\xce\x53\xf7\xf4\xa3\x03\xbe\x9d\x7f\x7e\x3b\x7f\xbb\x17\xe7\xc7\x2e\x6e\xe0\x08\xb5\x59\xda\x62\x25\xf1\xa7\x28\xca\xbc\xb1\xcf\xab\x2b\x8a\x0f\x8a\xde\x5a\x4e\xe7\xa4\xfa\x37\xa6\xdb\xc6\xb4\xae\xc8\x1c\x36\x1c\x27\x7c\x4a\x6b\xfa\xf0\x1d\xa8\x6c\x4a\x69\x87\x11\xaf\xd7\xc1\x11\x0e\x3f\x88\x84\x38\xe2\x8e\x65\x5d\x74\xbd\x2e\x57\x46\x70\xb1\x8e\x98\x0c\x2c\x39\x04\xe2\x24\x66\x72\x15\xd5\xff\xad\x30\x96\xb5\x50\x73\x88\xfd\xbd\x53\x52\x4a\x24\xc2\x5c\x2a\x37\x82\x7e\x4d\xa9\x3f\x66\x73\x6b\x74\x4b\xc1\xaf\x8e\xd3\x5d\xd5\x80\x53\x79\x11\x3a\xc8\x0c\x49\x15\x68\x00\x0b\xfa\x65\x46\x68\xd4\xcf\x8b\xe0\xf3\xa5\xdc\x43\x1a\x15\xf8\x7a\xaa\xf1\xe4\x50\x4d\x61\x74\x04\x87\x2c\xd5\xe5\x82\x98\xb1\x0a\x15\x64\xfa\xbb\x46\x90\xfd\xa4\x5e\x2e\xca\x75\xb1\x6f\x41\x9b\x20\xf5\xd9\x58\x67\x18\x1a\x99\x56\xbc\xcb\xce\x46\x9d\xd0\xdf\xdd\xfd\x39\x17\x26\xdc\x09\x5e\x62\x87\x79\xaa\x1d\x8a\x75\xd2\x1a\x35\x9d\xb4\x8c\xd3\x87\x2f\x6c\x57\x21\x23\x57\xcd\x50\xae\x8e\x89\x10\x33\xb8\xb0\x19\x44\x77\xa9\x6a\x06\x2e\x9c\x4a\xa1\x72\x11\xc5\x54\x15\xb5\x7e\x99\x15\x0a\xb7\xf2\x00\xf9\x40\x61\x2c\x64\x25\x5d\x74\x99\x6e\x78\x28\xaa\x5e\xc9\xfa\x99\x10\xc3\x50\x35\x0f\x78\x5d\xcf\xb3\xf0\xeb\x7c\x1e\xa0\xfa\xc0\x48\xe2\x03\xb5\x60\x55\x3f\x1e\x80\xaa\xe3\x72\x39\x9f\x4b\x57\x97\x63\x5f\xae\x2e\x33\xc7\x50\x65\xbe\x6b\x59\x18\x23\xca\xd6\x52\xb7\xae\xed\x5d\x13\xd2\x9c\xa3\x1e\xc6\xe4\xda\x32\x41\x94\x05\x6b\x2a\x85\x22\x42\xda\x5f\xce\xa5\xbe\x0d\x95\x86\xde\xbb\xcf\x44\xa4\xa1\xbf\x65\xce\xe2\x0c\x6c\x4c\x1f\xbb\x12\x3f\x30\x1c\x57\x6d\xb1\xa4\x1f\x0e\x8d\x33\xdb\xc2\xd2\x8f\x2d\x3c\x30\x86\x22\x09\xec\x16\xaa\x49\x88\x1d\x3c\xe4\x02\xb6\x0a\x84\x3f\xf6\xdc\xa9\x36\x8a\x6e\xda\x7e\x89\x36\xe6\xea\x6f\xd8\x81\x78\x36\x98\xe7\x75\xc7\x00\xe5\xa1\xe4\x36\xe6\xef\xd8\x6a\xf0\x8c\x7a\x8e\xf3\x56\xad\xb7\x14\x34\xe5\xb2\x16\x0f\x09\xce\x2c\xa6\xbc\xda\x91\x2a\xd0\x6b\x87\x31\xcd\x0f\x42\x30\xa6\xe9\xed\x95\xc0\x98\xcc\x49\x85\xf9\xf3\xc7\x4e\x7c\x58\x68\x38\x21\xab\x0b\x05\xbb\x33\x16\x6b\x50\x8a\x65\x3c\xf8\xc9\x66\xa0\xc5\x13\xd4\x02\xb1\x90\x43\x10\xd3\x66\x7c\xf3\xa6\x50\x85\x20\x9b\x8c\xa9\x14\x2a\x11\x51\x55\x0a\xc8\x1e\x0b\xbd\xc8\x82\x82\x4a\x0e\x17\x2e\x68\x55\xf5\x0a\x6a\x63\x85\x4a\xc2\x24\xd8\x0c\xc7\xa8\xe2\x55\x9f\xaf\x6a\xa6\x9b\xe7\x12\xa2\x61\xf5\xf0\x2a\x2d\xba\xcf\x2b\x59\xf5\x3c\x91\x2f\x29\x1c\xdb\xf7\xd0\x92\x1b\x99\x0b\xd5\x0d\xc3\x12\x9e\x9b\x85\x6a\x3d\xa1\x0a\xdc\xa0\xd3\xf0\x94\xed\x46\x95\xc4\xdd\xce\x52\xda\xf6\x68\x1c\xb9\x8f\x91\x0a\x02\x91\x81\x13\x2d\xb9\x0c\xf4\xb8\x4d\xb4\xb7\xe4\xc9\x1f\xa6\xe4\x08\x21\xd3\xb4\x2c\x57\x82\x57\x1c\x14\x64\x1f\xe9\x2e\x12\x2d\x6a\x96\x2b\xea\x05\x11\x6e\x7c\x07\xe4\xad\x7d\x83\x0f\xd2\x0c\xba\xa8\x7d\xee\xa8\xf1\x4d\x35\x43\x9b\xa6\xee\x5e\x52\x3a\xef\xea\xe2\xb3\x91\x6b\x3b\x3a\xfd\x8a\x06\xc7\x5e\xdb\x92\x9f\xaf\x54\x2c\xda\xbd\xae\x8b\x41\x54\x5f\x18\x49\x7c\x21\x0c\xb2\x7d\x3c\xc1\x8d\x3d\xc1\xa6\x79\x02\x0a\xc5\xc9\xcc\x47\xc8\x87\xf7\x43\xc8\x63\x8e\xa1\x40\x42\x93\xf4\x50\xdd\xc3\x03\x63\xd9\x30\xdd\x0f\x61\xda\xbd\xe6\xa4\x1c\x2a\xab\x38\x26\x68\x45\x03\x3e\x91\x97\xf6\xe8\xe3\x25\x6e\xec\x25\x6e\x29\x96\xb1\xe1\x27\xf6\x12\x9b\x5b\xf3\x92\xb2\xb0\x20\x66\x4c\x66\x9f\x91\x6c\x22\x9b\x25\x4f\xa3\x18\xee\x2b\x5f\xc6\xf6\x8a\xdc\x75\xde\xb0\x87\xba\xc1\xe4\xa2\xd8\x5d\xe7\x0b\xcc\x57\xd8\x07\xa0\x5b\xb7\x69\x28\xdf\xd1\x42\x52\x17\x08\x69\x59\x6e\xbf\x5e\x80\x82\x71\xd9\xc3\xe7\xd2\x41\x0f\xb6\x50\x50\x32\xc7\x08\x3e\x83\x6a\xa2\x8a\x96\x1c\x12\xc9\x95\x8f\xa4\x04\xf6\x8a\x6c\x88\x5a\x84\x21\xfa\x27\x5a\x57\xcd\x92\x20\xc0\x3d\x46\xf3\x06\x54\x2a\x64\x4c\x76\x0f\xd1\x51\x28\x11\x91\xf5\x2c\x9e\xc2\x4a\xc5\x71\x41\x1f\x27\x69\x2e\x0a\x13\xf4\x1e\xc2\x15\xe5\xf6\x94\x8f\x47\xab\x57\x3f\xd2\x3f\x23\x4f\x5d\x7f\x88\x6b\x3f\xf6\xff\x12\x0f\x81\x5e\xe3\xa5\x54\x7a\x72\xf8\x6a\xd0\x60\xd5\xf5\xdf\x86\x80\xa5\xc4\xaf\xf1\x08\x84\x05\x39\x10\x4c\xa5\x64\x67\xa5\x8a\x78\x3f\x47\xae\x9e\xa2\x4d\xd3\x3f\x92\xba\xbe\x78\xdf\x0c\x44\xd8\xb3\xa7\xd7\x06\x62\x75\x9c\x3d\x61\x50\x0f\x1e\x1c\x90\xb5\x27\x36\x80\xea\x8d\x95\x56\x02\x02\xe4\x16\x95\xab\x3c\x39\x54\xe5\x42\x2e\xa2\x22\x69\xcf\x21\x21\x4e\x50\xd2\x55\x05\x4e\x9f\x41\x45\xd8\xff\x48\x40\x10\xe5\x60\x28\x95\x42\x55\x02\x61\x56\x21\x1c\x2b\x94\x57\xe1\x9c\x30\xd1\x7d\x03\xaf\xfe\x61\xd0\x5d\xc5\xf6\xe9\x9f\xda\xa7\xb3\xf7\xf1\x92\xe7\x74\x1a\x09\xbc\x20\x02\x0e\xf6\x8b\xe1\x0f\xc7\xe5\x12\x3e\x97\x0e\x97\xe0\x0d\x13\xf6\x99\x63\x28\x98\xd0\xfa\xf3\xfd\x02\xf9\xb3\x11\xba\x4d\x22\x24\x02\xcb\x06\xe9\xdf\x82\x05\xf7\x8a\x7e\x1b\xf7\x8a\xf8\x04\x51\x76\x5b\x09\xc2\x1c\x95\x9c\x8b\x4b\xe9\x77\x57\xff\xde\xd4\xa5\xbf\x95\x07\x00\xe3\x2f\xd0\xdf\xc9\x2a\xf7\x13\xa9\x13\x44\xc1\x9e\x81\xb0\xf7\x91\xb8\x1c\xe0\x73\xe9\x48\x00\x9b\x2a\x52\x62\x8e\xa1\x50\x42\xe3\xc4\xea\x0f\x80\x9f\x8d\x52\xdb\x44\xfb\x03\xdc\xa3\x0a\x7c\x24\xd3\x03\x88\x68\xbe\x16\xdc\x4a\x88\xd2\x91\x3b\xc2\x86\x12\xf8\x36\x6c\x28\x7a\xdb\x0c\x00\xa8\x6f\xd5\x19\xa7\x7f\x14\x7d\x7b\xde\x34\x0c\xa8\x51\x86\x71\x35\x86\xa3\xa0\x0a\x34\x82\x15\xb4\x7f\x29\xb3\xa6\x5c\xda\x85\xfd\xc7\xab\xea\x8f\xda\x8e\xe1\xc3\x26\x53\x5b\x62\x33\xc5\xe4\x3a\x27\x81\xcd\x1b\x71\x68\xe2\x26\x4a\xa4\x72\xad\x4d\x10\x51\x03\x69\x52\x58\x58\x22\xba\x5e\x27\x12\xad\x33\x21\xed\xf2\x96\x91\xa0\x43\x44\x41\xbc\xca\x08\x9d\x75\xf6\x0a\x19\x68\x93\x2a\x54\x91\x46\x91\x8c\x39\xeb\x39\xfd\xa9\x68\x4d\x23\xd5\x86\xf3\xfa\xca\x19\x8f\x9b\x0b\x57\x4a\x5a\x43\x28\x52\xf3\xd4\xf3\xbb\x5e\x9a\xb5\x69\xc7\xe2\xe5\xbf\xba\xe7\xed\xfd\xe3\xcf\xdf\x73\xd1\xea\x47\x2e\xbd\x6b\xd3\x9c\x21\xca\x1f\x4e\x83\x9f\x1a\xa3\x57\x94\x1e\x90\xd6\x8f\x98\xd9\x90\x9d\xbc\x79\xd5\xc4\x5b\xae\xb8\xea\xd9\xc5\x2b\x8f\xcc\x9b\xbc\xab\x6a\xd0\xba\x8e\x4b\xe7\x4c\xbc\xf2\xba\xe5\x97\xbf\xff\x27\x65\xde\x88\xa7\x2f\x74\x27\xdf\x3e\x8f\xf8\x87\x45\x19\xc6\x4e\x24\xb8\xb7\x82\x1d\x38\x5e\x55\xa4\xf4\xf2\xd4\x0e\xf6\x63\x72\x89\x05\xdb\xc1\x5e\xb0\x03\x8f\xed\x60\x51\xed\x60\xcf\xdb\xc1\xca\x69\x76\xb0\xa4\x10\xdf\xdb\x0e\x9c\xce\x0e\xf6\x5e\x76\xd0\xc6\xbd\x89\x21\x5a\xfa\xd8\xc1\x18\xa9\x64\xf3\x76\xb0\x8c\x7e\xf4\x92\xe5\x77\x5c\xd0\xb1\xfa\xc6\x9f\x3e\x7d\x60\xef\x79\xcd\x77\x5f\x35\xe5\x86\x8b\xe6\x2f\xfa\x5e\xc3\xaf\x8e\x66\x6b\x34\x2b\x34\xed\xab\x1d\x7c\xed\x25\xad\xdf\x19\x3d\x61\x53\xfb\x86\x67\x26\x6e\x2a\x89\x7d\x77\x6c\xeb\x25\xc3\xc7\x7e\x77\xfa\xc8\x47\xd3\x05\x2b\x30\xa0\x53\x19\x46\xf4\xe2\xcc\x40\x00\xdf\x2d\xe8\x41\x5b\x35\x35\x40\x87\xa0\xaa\x01\xba\x8e\xc9\x4e\x29\x87\x58\x7c\x8c\x72\xce\x02\x8f\xf5\xc3\x27\x0e\x69\xb3\x71\x9a\x58\x31\xab\x9d\x04\x60\x70\x53\xe1\xfd\x51\x99\xb8\x08\xec\xd4\xbe\x63\x8d\xaa\x10\x77\xfc\x45\x28\x29\x93\xd5\xaf\x64\xfc\x78\x2f\x51\xff\xc3\xef\xe7\x62\x65\x18\xd1\x71\x34\x83\x2a\x7c\x0b\x94\x03\x9a\x40\x50\x7e\x07\xd1\x90\x43\x55\x89\xb4\x93\x30\xfc\x3b\xed\xe6\x18\x89\x15\xc3\xc7\x64\x0f\xde\xb4\x9e\x30\xde\xb4\x4e\x12\x17\x16\x49\x3a\x56\x35\x3a\x50\xa4\xdb\x20\x8b\xc2\x49\x07\x92\xba\x81\x2c\x45\x1a\x1b\x61\x46\x94\x22\x55\xf9\x0a\x08\x1b\xa6\x33\xa0\x1e\x01\xd9\x48\xef\xad\x1c\xe7\x17\xe5\x94\xdd\x54\x14\xe4\x52\x9c\x87\x3a\x71\xd0\x50\xb4\xbe\x5e\xf2\x8d\x05\x51\xbf\x8b\xb5\x15\x3b\x8b\xe5\x1b\xf3\xaa\x7e\xf9\xd5\x1b\xbe\xaf\x97\x6f\x2c\x08\xfb\xc1\xd3\x8a\xaa\x05\x5b\x83\xe3\xe5\x6a\xcd\x53\xfd\xf8\x35\x89\x7c\x2e\x6b\xb5\x54\xfb\xed\xaa\x8c\x6a\x2d\x41\x1d\x54\xba\x71\x78\x80\x02\xf8\x7d\xe1\x17\xe7\x8c\xcb\x01\x89\xf0\xd7\x01\x99\xab\x2e\xc0\x0f\x2a\x53\x29\x64\x15\x09\x4d\x1f\x5e\x9b\x3b\x40\x87\xbe\x3d\xa9\xc1\x4d\x35\x9a\x5f\x86\x23\xad\x5a\xa9\x92\xaf\x51\xe7\x06\x8c\xbc\x47\x1b\xe4\x67\xae\xfc\xe8\xfa\xec\xcf\x94\xd7\xde\x0f\xfd\xe0\xe5\x8f\x96\x5f\xbf\xff\xe5\xb6\x1b\x3f\x5b\xfb\xfc\x4f\xde\x4e\xdf\xfd\xd0\xfd\xca\x97\x5d\x7f\x1a\x76\xb0\xa9\xf9\xc9\xfb\x4f\x3c\xb0\xf7\xfe\xeb\x66\x2c\x5d\x33\x61\x1c\xda\xfe\xd0\x2f\xaa\x38\xf7\xd3\x6b\xd7\xbe\x73\x33\x00\x90\x60\x0e\x3a\x88\x2e\xec\x14\x40\x46\x5b\x71\xbe\x88\xaa\xc8\x98\x3e\x32\xc7\x69\xad\xbf\x86\x4c\xeb\x57\x58\x72\x19\x47\x85\xc1\x14\x93\x4b\x5d\x24\x2f\x02\x32\x53\x25\x88\xa8\x9a\x50\x04\x83\x0a\x3a\xea\x1c\x24\x32\x8c\x52\x29\x29\x3a\x12\x91\x3e\x1d\x08\xa1\x9f\x95\xe4\x11\x09\xeb\x1e\x7c\xbd\xeb\xd3\xb7\x9e\x9e\x15\xda\xf7\xe4\x8f\x6e\x9b\xb9\x72\x53\xf3\xd5\xbb\xaf\x79\xf6\xc7\xcf\xee\x5b\xb2\x7a\x8b\xf2\xd7\x67\x3e\x5e\x76\x1a\x4c\x3e\x7a\x60\xdd\xee\x4d\x7b\x56\x4d\x5b\x39\x66\x7d\x2c\xfc\xea\x23\x9b\x7e\x58\x5f\xdb\xb5\x61\xd7\x9f\xee\x9c\x40\xef\x9c\xc9\x00\x18\x96\x91\x3c\xb0\x14\xbc\xa0\xc6\xb4\xbc\xc9\xaa\x71\x62\xab\x83\xac\x59\xd6\xa2\xf5\x05\xb5\x01\xd6\x80\x3e\xde\xd7\x15\xb0\x54\xed\x4d\x7c\xfb\xa8\x03\xac\x3a\xc2\xd2\xe2\xa9\x55\x64\x75\x65\x58\x2b\x23\xc5\x90\xc9\x95\xe1\x4c\x06\x29\x96\x31\xe3\x27\xfe\xdc\x62\xa5\x32\xc6\x5c\xa1\x09\x68\x62\x04\x31\x6d\x73\xf9\xf1\x19\xc5\x0b\xc8\x47\x84\x48\x45\xdd\x34\x2a\x8c\x48\xe1\xde\xf8\xc3\xc9\xb0\xf9\xf0\xdd\xcc\xdd\x6b\xb2\xca\xd1\x43\x9b\x7b\x56\x6e\x86\x8b\x7a\xa1\x0f\xb7\x33\xf3\xbe\x6e\x63\x0e\xf4\x4c\xee\x25\xd5\xa0\xce\x11\xae\xe4\x77\x11\xec\xcc\x1f\xd4\xac\xc8\x15\x48\xd2\xda\x2c\x3e\x70\x35\xfc\x61\x4c\x2f\x04\xac\xb3\x85\x9b\x72\xe8\x67\x5c\x76\x9c\x01\x0a\x16\x1a\xcc\x59\x48\x04\xa7\x57\x35\x2c\x60\x13\x03\xae\x0c\x1b\x20\xd8\x44\xf2\x34\x90\xa7\x91\x3c\x4b\xf1\x33\x5d\x1a\xd0\xe3\x14\x8d\x29\xc4\xa5\x90\x81\x60\x35\xb3\xac\xb1\x94\x33\xa8\x12\x72\x85\x9f\x0b\xb8\x4d\x9e\x08\x1d\x61\x4f\x2b\xaf\x25\xf4\x8f\x19\x8b\x97\xb0\x7f\x02\xd9\x8b\x53\x09\xde\xae\x4e\x64\xb2\x0e\x58\x98\x69\xd5\xc4\xeb\x1d\x7d\xb1\x9d\x29\xd8\x96\x9d\x62\xab\x12\x2c\x57\x1d\xba\xee\xee\xcd\xde\xcd\xd9\x4e\x69\xf3\x95\x4f\xdc\x5e\x31\x1b\x7a\x7b\x81\x1a\x17\x8c\x5c\x3b\x7a\xc9\xbc\x4d\xeb\x87\xde\xdc\x33\x9b\x41\x57\x35\x6e\x5e\xfa\xe9\x4e\xa5\xa6\x18\xdb\x08\x09\x97\xff\x64\xc3\x3b\xc0\xa7\x65\x57\xc8\x97\xd4\x4d\xff\x4a\x6c\x0e\x39\xe2\x9a\xc6\x97\xcf\x42\x4a\x71\xba\xb1\x4d\x07\xb5\x36\xb2\xd3\x48\xc7\x62\xc9\xe5\xb9\x18\x1e\x3f\xf1\x89\x8e\x75\x1d\x20\x6f\x23\x44\xde\xde\xb3\x99\x76\x07\x36\x02\xa1\x26\x94\x80\x20\x66\x58\xce\x22\x90\xf6\x6a\x52\x3f\xe3\xab\x29\xd1\x03\x9e\x9d\x04\x9b\x77\x84\x2d\xe3\x3f\xef\x7c\xf9\x27\xa2\xf2\xb3\x17\x60\x93\x70\xe2\x90\x92\x1b\xb2\xd7\xd0\xf5\xbf\xcb\x36\xbe\xf6\xea\x84\xa9\x5f\xcf\x36\xec\xfa\xce\xf9\x7f\x51\xde\xfd\xc7\xa9\x53\x54\x8f\x9f\x7b\xdb\xe8\x06\x11\x30\x18\xac\x07\xe9\x30\xa0\x03\x08\xb4\xd2\xd4\xc0\xe7\x90\x27\x2e\xbb\x54\xec\x04\x45\xa5\x55\x49\x24\xf0\xf7\xc3\x18\x2a\x4d\xc8\x0e\x81\x14\x5c\x34\xf8\x44\x02\xc6\x64\x7f\x95\x20\x66\xb8\x30\x1d\x7f\x74\x08\x72\xb0\x9c\x9c\x28\x19\xa3\xcb\x53\x4f\x7b\xc6\x2a\xd9\x62\xd8\x45\x74\x13\xf1\xe6\x91\x1b\x3c\x82\x98\x01\xbc\x31\xd8\x17\x43\x61\x2c\x20\xd4\x9a\x87\x8c\x64\xfa\x43\x54\xa8\x38\x0a\x77\xc9\xc5\x19\xe5\x01\xc7\xd4\x31\xf1\x96\xd9\x37\x77\x18\x6d\x83\xaa\x7b\x23\x2a\x54\x04\xc5\xae\xc5\x70\xce\xc9\xab\x46\x57\xce\xf4\xae\x0f\x77\x2c\x2c\x39\x6f\xf4\x7b\x8b\x8b\xd1\x14\x64\xaf\x4d\x3d\x7d\xdc\x90\x34\x74\x81\x10\x88\x81\xdf\xab\xaa\xb9\x11\x13\x55\xeb\x4b\x9b\x25\x37\x3e\x84\x9c\x75\x41\x93\x9d\xc8\xef\x6b\xd8\x12\xb5\xee\x64\x80\xa4\xa0\x60\xb3\xe4\x90\x25\x81\x6c\xb4\x40\x5b\xea\xc9\x65\xa4\xd2\x6a\x13\x15\x31\x6b\x50\x3d\x01\x7d\x11\xa4\x2c\x5e\x7c\xa3\x01\x99\xba\x39\xd9\x52\x72\xd2\x40\xb4\x92\x37\x9f\xb8\x8b\xfa\x88\xe4\x42\x62\x37\x72\x63\x4f\x41\x5e\x57\xc6\xe3\x75\x4b\xb1\xb4\xc7\xeb\xd6\x0d\xa5\x66\x78\x8b\xe8\xa1\xbd\x08\x93\x59\xf4\x14\x64\x2e\x0c\x82\x88\xd8\x14\xaa\x16\xb2\x4e\x5f\x30\x42\x81\xa4\x75\x11\x41\x94\x41\x29\xa1\x64\x92\x59\x5f\x2a\x85\x4c\x54\xda\x4d\x1a\x22\xb6\x56\x37\x0f\x19\x05\x93\xbc\x3a\x47\x8f\x7f\x64\xc8\xf1\x0e\xc2\xc5\x43\x94\x53\xdf\x3d\xfc\x90\x2d\xfa\x42\xd4\xb6\xa2\xe3\xfe\x57\xc3\xd1\xae\x9a\x11\xa7\x6e\xb8\x45\x79\x46\xf9\xf9\x2f\x4e\xbf\xb1\xe3\xfb\x6f\xfd\xe5\xd1\x7b\x5e\xfe\x5f\xb8\x2b\x03\x61\x72\xda\xcb\x83\x87\x66\xb3\xcd\xf1\x05\x37\xed\x7b\x28\xdb\xad\xbc\x3f\xa9\xf5\xd5\x25\xa7\x95\xcf\xfe\xf8\xe6\xaa\xcd\xef\xa7\x57\xee\xfc\x84\x9e\xfb\x97\x9d\x3e\x4e\x7c\xb1\x12\x34\x81\x5f\x80\x74\x85\xea\x8b\xa8\x81\xba\xa0\x39\x9e\xb6\xb8\x3d\x49\x9c\xdc\x53\x7e\xd5\x88\x9b\x00\x46\x71\x44\x6d\x17\x72\xc8\x8c\xaf\x69\x0b\xdd\x6c\xf5\x94\x57\x2d\xe3\x2e\xab\x37\xc5\x70\x38\xa3\x91\xab\x8e\xf2\xff\x7d\x6c\x1f\x41\x88\x97\x46\xee\x38\xb1\x9f\x9c\xfe\x6e\x17\x92\xba\x91\x87\xec\xc8\x8c\xc9\x2a\x79\x55\x83\xaa\x3f\x11\x83\xda\x8d\x82\x28\x73\x15\xaa\x4a\x04\xbe\x36\xeb\x05\xd9\xd5\x90\x4a\xa1\x32\x91\x64\x6a\x0d\xd5\xd8\xb8\x65\x29\x32\x53\xc8\x95\xa4\xc8\x10\xb0\x51\x53\x54\x27\xe1\x4c\x31\x4a\x01\x12\xf3\x92\x2c\x8e\xd8\x57\xd5\x76\x73\x30\x97\x7d\xef\x89\x8e\xd5\xf6\xd6\xae\x56\xd7\x35\x33\x56\xde\x5f\xd9\x7a\x78\x68\xe5\x9a\x8e\xcb\xaf\xdb\xaa\x9c\x44\x2f\xff\xc7\x6b\xb7\xde\xdc\xf1\xcc\x35\x8b\x6f\xb9\xea\xfe\x99\x09\xb8\x7a\xe5\xff\xec\xaa\xb8\x62\xff\x90\x91\xd0\xa4\x28\x6d\xad\xd3\x26\x6d\x7e\x0c\x32\xca\x57\x7b\x0e\x57\xd7\x3f\x76\xfb\x3e\xe5\xd7\x3b\x3e\xfe\xc1\xed\xf7\xde\xf2\xcb\x55\xcb\xd6\x8c\xb9\x53\x06\xf0\xf4\x71\x65\x1e\xd1\xa1\xf4\x80\xfb\xd5\x73\xcd\x93\x94\x79\x36\x87\x4c\x09\x5a\x71\xc7\x77\xaa\x4d\x55\xa8\xf3\xc6\xf3\xcd\xbc\xad\x27\x36\x15\x41\x82\x4c\xa6\x93\x0e\x64\x21\xe3\x32\x66\x8b\x49\x8a\xa5\xcd\x16\x93\x7e\x52\xda\xec\xa6\x0e\xa9\x57\x3f\x16\x70\xda\xe3\x50\xe5\x51\x11\x4f\x14\xee\x70\x92\x47\x6c\x14\xd1\xc0\x51\x45\xd2\xdd\xee\x22\x14\xdc\x78\xff\x32\xaa\xd8\xdd\xe2\x08\xaa\xe0\x37\x05\x2d\xed\xf0\x6d\x97\x86\x8c\x5e\xa7\x6a\x5b\x2a\xf3\x88\xb6\xa5\x17\x6c\x50\xd7\xe7\x4d\xca\xbc\x81\xae\x0f\x9f\x6d\xac\x81\xac\x4f\xc4\xeb\xf3\xc5\xc9\x71\x86\xd7\xf7\xee\x17\x44\xca\x1d\x79\x1b\x1d\xc8\x83\xd7\x57\x7a\x96\xf5\x79\xe8\xfa\x3c\xde\xc2\xfa\x44\xbc\x3e\x27\x59\x9f\x4b\x5d\x1f\x62\x85\x7e\x56\x57\xad\x2d\x2f\x54\x84\xf3\x4a\x95\xde\x3e\xbf\xea\x02\xb1\x7a\xc8\x90\xf3\xec\x65\x2a\xaa\x4b\xf9\xf4\xae\xdb\x5c\xe6\xed\x52\x4b\xea\xbe\x3c\x07\x7f\x80\x6f\x56\x39\xce\xb6\x9f\x23\xbf\x99\x2c\x9a\xa9\xda\x9d\xf3\x98\xec\xb6\xe6\x32\x9c\xdb\xa9\x52\x48\x05\xfe\xc5\x61\x28\x27\x8e\x83\x44\xdf\x19\x29\xa4\xa4\x33\xd1\x47\x5d\x3a\xb6\xf9\xda\xfe\x88\xa3\x98\x7d\xa9\xb6\x69\xe7\x5d\x92\xc8\xcf\x40\xfd\x46\xe5\x22\xfb\xfe\xd9\x78\xc8\xe4\x2a\x73\xfe\x50\xd6\xf3\x8e\x59\x73\xa8\xba\xef\x3c\x7a\x83\x7e\x1e\x1d\xd9\x84\x34\x17\xac\xc3\xa1\x49\xb5\x98\xb6\x3b\xaa\x52\xff\x3c\x5f\x14\x3c\x47\xae\x28\x38\x4d\xb5\xc0\x19\x86\xcb\xa7\xab\xb6\x60\x70\x5c\xc2\x2d\x24\xda\x69\x41\xd0\xa9\x7a\xb8\x3b\xd9\x77\x96\x05\x05\xe2\xb2\x83\xeb\x33\xec\xe4\x3a\x26\xfb\xed\xff\x9e\x09\x27\xbf\x4b\x10\x65\x8f\x97\xa8\x57\x38\x04\x11\xf9\x53\xbd\x66\x55\xbc\xc9\x04\x4e\xcb\x5b\x93\x3c\x1d\xc4\xaf\xe9\x3b\xb0\xd2\xb3\xad\xa2\x7e\xff\x88\x4b\x66\x2d\x1e\xb6\xe6\xb1\x7b\x5a\xa3\xf9\x91\x15\x65\xbd\x69\x41\x34\x6e\xc9\x2e\xa9\x5e\x3a\x6b\xa9\x95\xf2\x2c\xb8\xd9\x23\x5c\x3b\xf0\x13\x3c\x9f\x3a\xb7\x92\x0d\xeb\x10\xf5\x09\x9e\x30\x3e\x07\xb8\x5c\xd6\x12\xeb\x67\xce\x09\xdf\xc5\x41\x18\x93\xa3\xf6\x1c\x8a\xba\x48\x93\x54\x9b\x6e\xb2\xe1\x90\xb3\xa4\x9e\xb4\x3e\x0e\x59\x03\x15\xe1\x5a\x32\xe4\x16\x15\x33\x5e\x67\x65\x04\xff\x18\x17\x64\x2e\x91\x22\x53\xb9\x34\x86\xf1\x06\x04\x31\x5d\x11\x21\x3a\x1e\x96\x30\x3e\xf7\xa5\x54\x4a\x4e\xc4\xce\x3a\xb7\xd2\xc7\x2a\x85\x49\x96\xfe\x87\x57\x96\x15\x99\x68\x9a\x3a\xca\xd2\xcf\xf8\x4a\xcf\x0f\xf4\x46\xe3\x2e\x25\xc3\x2c\x00\x18\x68\x8f\xd5\x14\x24\x7d\xc5\x6a\xc2\x20\x7d\x7b\x7f\x7d\xd6\x2a\x42\x20\x1d\xd2\x08\xa4\x51\x4d\x5c\xae\xc5\x16\x6c\xed\x4d\xd8\x10\x76\xe7\x50\x98\xce\xa4\x36\xb9\x73\xa8\xa9\xd0\x63\x1d\x8a\xff\xb5\x8c\x34\xe0\x6b\xc8\x94\x77\x8c\x36\xe0\xcf\xbd\xc9\x3a\x30\x59\xdf\x99\x5a\xae\x43\xfb\xe5\xea\x3b\x5b\xf3\x75\x4b\xbf\x84\x7d\x06\xb5\x1f\x8f\x74\xf6\xba\xbb\xbf\x5e\xec\x59\xec\x65\xe9\x6d\x2f\x55\xf1\x00\xf1\x2e\xd4\x84\x0f\xa1\x98\x9b\x4c\x6c\x36\xb9\x75\x76\x13\xac\x79\xbb\x71\xfe\xde\x76\x3b\x53\x6b\xf6\x0c\x24\x87\xfd\x36\x6a\xd7\xf4\xcf\x6e\x38\x60\xcb\xf6\x9b\x7e\x6d\xc5\x15\xf9\x56\x13\x68\x06\xeb\xfa\xf3\xac\xba\x38\x2a\x4b\xca\x11\x43\x2e\xd3\x18\xa9\x33\xc5\xe4\x72\x43\x0e\x45\x13\x28\x11\x97\x93\xd8\x60\x2d\xbd\x5b\xf9\x4d\xb4\x4c\xac\x73\xac\x56\xec\x6b\x65\x82\x88\x12\x29\xe4\x11\x08\x3f\x4c\x79\xb4\x2e\x49\x07\xe5\xd3\xd5\x43\x9a\xbf\x4d\x27\x5f\x6a\x49\x26\xca\x99\x64\xa2\x35\x89\xb7\x64\x23\x13\xa9\x34\xf2\xec\x99\x89\x41\x3e\x1b\xf1\x5c\xfc\xc2\xe1\x43\x2b\x2e\x1e\x32\xb7\x7c\xdd\x15\x0d\xe3\x86\xa7\xc2\xb1\x84\xcf\x17\x62\x96\x9d\x8d\x21\x84\x1d\xf7\xc7\x50\x34\x74\xdd\x82\x95\xa1\xaa\x50\x53\x12\x4e\xe8\xec\x04\xda\xcc\x47\x4c\xf5\x31\x6c\xb7\x7b\x75\x1e\x56\x8e\x2f\xf2\x68\x52\x6e\x34\xe4\x32\x91\xf2\x46\x53\x4c\xae\x33\xe4\x50\x59\xa2\xe0\x7a\xbd\x2c\x67\x19\xc8\x72\x52\x0e\x55\x27\xfa\x35\x5e\x44\x33\x9e\x1c\x6d\xfe\x36\x7e\x36\x80\xe9\xfa\x77\xb2\xda\x81\xad\x36\xb0\xa7\x3d\xd7\x8f\xbd\xb4\x39\x91\x66\x75\x4f\xb6\xf7\x7f\x7e\xc9\x21\x73\x7e\x38\x40\x7f\x5e\x59\x0b\xfb\x8f\x32\xd2\xc9\x65\x38\xbf\xb6\x0a\xb4\x89\xf7\xcf\x9e\x50\x67\xf0\x17\x86\x57\x2f\xf5\xb3\x79\x47\x5a\xbd\xd9\x0b\xf3\x1f\xbf\xe9\xbd\xc6\xe2\x33\xa7\x68\x8d\x96\x7e\xd7\x28\xf5\xb3\xc6\x6f\x75\x9a\xe8\x43\x97\x7e\x5f\x2c\xbc\x4c\x8b\x59\x06\xd4\x52\x69\xd1\x16\x56\x7c\x46\x84\x40\x3d\x58\xdc\xdf\xdb\xab\x8d\xcb\x11\x33\xc1\xe3\x07\x8d\xbd\xf5\x70\x2a\xf0\xb5\x6d\x25\xd7\xb6\x5e\x1a\xa7\xc2\x41\x6e\x9a\x32\xd2\x88\x8e\xd2\xf7\x28\xf3\x1e\x41\x54\x85\x53\xce\xf5\x8d\x16\x13\x7b\x9e\xe9\x9e\x59\x5f\xc4\xeb\x79\xb6\x49\xaf\xfb\xf4\xd4\xa7\xea\x9e\x3f\x4f\xdd\xf3\x45\x76\xe0\x73\xe9\x08\xb6\x43\xad\x59\xf7\xaa\x7b\x59\xc2\xd2\xaf\x25\xa4\xfe\x2d\x81\xdf\x36\xb1\x04\x0a\x7d\x8b\xbd\xdd\x8b\xe0\xb4\xdf\x37\xff\x49\x31\xb3\xe9\x80\xaf\xff\xef\x05\x62\x53\x92\xe3\xbf\x02\x00\xf7\x9e\xf1\x15\x32\x5b\x7a\x3f\x48\xf3\x80\xf0\xc9\xa4\x01\x5e\x36\x64\x93\xc9\x7c\xad\xda\x4e\x2a\xf0\x46\x29\x97\x81\x46\xde\x94\x9f\x4e\x84\x96\x1c\x19\x33\xc5\x51\xeb\xc1\x2f\x44\x9a\xab\xf0\x24\x95\x37\xba\x90\xa1\xfb\xa5\x23\x2f\xff\x75\x28\xfe\x54\xe6\x4d\x26\x04\xf0\x3f\x38\x10\xc4\x49\x0c\x48\x33\x06\x13\x81\xd2\xd3\x3f\x29\x11\x0d\x14\x44\xd9\x4c\xc7\xf2\xa5\xa4\x04\x93\x90\x8d\x04\xb0\x23\xbc\x72\xf8\x20\xfc\xd5\x7b\x3d\x1b\x6f\x7e\x71\xa9\x91\x92\x95\xf6\x44\x98\x4f\x4f\xdd\xd0\xf3\x19\x13\xe5\x8c\xf8\x30\x62\x4e\x8f\x52\xdc\x5c\xc8\x30\x0f\xf8\x41\x19\x98\x0d\x28\x14\xcc\x24\x24\x93\x38\x5f\x66\xa8\x86\x65\xa9\x91\x6a\x36\xf2\xa4\x67\xac\x31\x00\x74\xdf\xfb\x8f\x6c\xfe\x9b\x1b\xbb\x91\xc9\x85\xcc\xdd\x40\x36\x9a\x1b\x1b\x21\x79\xd2\x3c\x92\xf1\x92\x70\x1a\xf1\x82\x0c\x08\x32\x9d\xa5\xd9\x22\x9b\x94\xca\xa1\x27\x39\x12\x16\x88\x72\x5a\xc3\xfc\x91\x51\x17\x5c\x71\x6b\xcb\x85\xfb\x0e\x5d\x68\x75\x19\x4b\xe7\x96\xc3\x51\x47\x7a\x2e\x9c\xfa\xca\x9a\xef\x8c\x82\xdf\x90\x97\xf5\x92\x78\xfd\xcc\x55\xdc\xd4\x9e\xcf\x2e\xfe\xdf\xf6\x31\xbf\x4e\x31\x53\xbf\x56\x0e\xdc\xeb\x31\xa2\xce\x4e\xc0\x9c\xde\x77\xfa\x2d\xa6\xd3\xe8\x06\x22\x28\x07\xcb\x40\xda\x8e\xfd\xd1\x63\xc8\xd1\xc4\x22\x10\x27\xa9\x33\x1b\x47\x5c\x92\xd0\x44\xb0\xc7\x64\xce\x92\xcb\xf8\x39\xd6\x14\x93\x2d\x8e\x02\x09\xc4\x83\x27\x9e\xa0\x0b\xa3\x79\x23\x87\x5f\x09\x90\x19\x03\x5e\x18\x7e\xd2\xe9\x58\x56\x10\x65\x9e\x68\x8e\x7a\xec\x14\x58\x12\x10\x08\x6b\x5f\xa4\xa5\x15\x26\xd9\x42\xcc\x52\x63\xe4\xa1\x3b\xdf\x6c\x30\x4e\x9d\xba\x0c\xda\xb2\x7f\xaa\x1f\x7a\xc3\x6d\x7b\xef\x9b\xbc\xb4\x74\x70\x0a\xda\xa7\xb4\x9e\xdf\x5a\xdd\x9a\x34\xbd\x7c\x0b\xf7\xbb\x6f\x32\xae\x3b\x66\x2d\xeb\xbc\x70\xe4\xe8\x1b\xa1\x7f\xce\x98\xe6\x86\xa6\x64\x14\x30\x20\x75\xfa\x2d\x43\x03\xd7\x0e\xea\x40\x0b\x78\x57\xed\x27\x90\x1e\x76\x83\x21\x47\x98\x51\x74\x20\xfc\x2a\x3e\x97\x4d\xba\xbc\x26\x7b\x4c\x4e\x1a\xf2\x41\x5c\x9d\x25\x87\xea\x8a\x0a\xbb\x61\x0a\xc2\x47\x56\xca\x60\x2d\x39\xf2\x5a\x29\x05\xf8\x7d\xb9\x0b\x85\xba\x65\x87\x70\x12\xd9\xbb\x41\xc6\xee\x28\x0f\xa9\xe2\x80\xea\x4f\xbd\xc8\x1c\xc2\x42\xc6\x54\x52\x46\x44\xdd\xad\x62\xc6\x5b\xdf\x40\x6e\xe6\xc1\x02\x72\xa5\x80\x9c\xc4\xa9\x89\x54\x92\x4a\xc9\x55\x2e\x41\x4c\x73\x56\xb6\x0f\x34\xdf\x09\x8b\x0c\x57\xd3\xd2\xaa\x43\xea\x47\x0b\x75\x3b\xde\xa8\x47\xeb\x0f\x6e\x6c\xbe\x7e\xf9\x13\xeb\xaf\xbc\xb5\x74\x70\xea\xa6\xab\x96\x5d\x91\x57\x0b\x7c\xb7\x21\x96\xb8\xa0\x35\xda\x9a\x34\x17\xe0\xfb\x1f\xba\xee\x98\xb5\x7c\x33\xb6\xef\xb0\x17\x6f\x85\xab\xf3\x48\xfe\x4f\x07\xb7\x0c\x1f\xd6\xd0\x94\xac\x27\xb3\xd8\xe9\xd3\x6f\x91\x9e\x63\x29\xa8\xc1\xb9\xa9\x07\x9b\xba\x5c\xf5\x25\x92\xa5\xcb\x36\xec\x4d\x89\xb4\xd9\x66\x89\x65\xce\x37\xf3\xe6\x58\xb6\xca\xe9\xe1\xed\x31\xb9\xca\x40\x9b\x6f\xe1\x63\xb2\xe8\x20\x9d\x36\xb5\x56\xfe\x4b\x92\x9f\xb2\x8d\x0e\xc4\x74\x1b\x64\x9b\x70\xd2\x41\x48\x0d\x18\x3b\x9d\xbd\xb6\x15\xd4\x6d\x45\xda\x79\x04\x72\xb9\x87\x6e\x9f\x2a\x01\x89\x29\xd9\x6c\x13\x68\x85\x33\xd2\xd2\x2a\x69\xca\xf7\xbd\x5d\x4d\x67\xa3\x4b\x2f\xbf\x65\xa3\x4e\x00\x7f\x7e\x72\xd8\xf5\x2b\xf6\x6f\x98\xbc\xa8\xb4\x61\x18\xb4\x51\xd3\x0c\x4d\x9a\xf6\x2f\x63\xf6\x90\x76\xa3\xc2\xb8\x57\xce\xbe\x6d\xcb\x85\x23\x87\xdf\x0c\xfd\xaa\x35\xa2\x00\x2a\x8a\xe2\x86\x1f\x72\x6d\xc0\x06\xae\xea\xcb\x9e\x65\xcf\xb3\x67\x39\xbe\x05\x7b\xd6\x99\x39\xb3\x7a\x93\x64\xe9\x68\xb1\x54\x2d\x43\xe3\x7b\x6a\xbd\x7f\x04\xf8\x11\xad\xf8\xa3\xd2\x24\x29\xb4\x0e\xa1\xa1\x25\x92\x92\xa4\xf4\x7f\x5e\x02\x59\xe2\x64\xde\x7f\xa4\xbe\xf2\x5f\x8f\xc3\x48\x2f\xc9\xf7\x2c\x2a\x15\x85\xd3\x6a\x31\xc5\x64\xde\x9e\x43\x7c\x5c\x76\xda\xc9\xb6\xc0\xb9\x8c\xd7\x92\x93\x47\xa9\x4b\xfb\xe0\x8b\xa3\x74\x69\x16\x7c\xda\x21\xab\x0b\xd9\xba\x81\x6c\xb6\xe1\xa5\xe1\x27\x79\x79\xf5\x55\x82\x28\x87\xf1\x6e\x68\x12\x64\x63\x30\x95\x92\xad\x16\x41\x4c\xbb\x4a\x87\xa4\x52\x29\x34\x54\x90\xa5\xf3\x52\x6a\x85\xb5\x0b\xf0\x46\x97\xd7\xd9\xb7\x61\xa0\x6f\x15\x91\xeb\xad\x86\xd0\xc0\x14\x35\x0c\x0c\x7a\xa2\xdc\x42\xf7\xe0\xd0\xa5\x65\x31\x83\x69\xf6\x33\xd3\x36\xee\xd9\xd0\xb3\x77\xe3\x7e\xdf\x77\x16\x6d\x9b\xfd\xd0\x93\x2f\x1e\x5c\x72\x68\xd6\xcd\xd7\xcc\xda\x3f\x8b\x79\x6d\xd1\xf4\x99\x4f\xcf\x7c\xfe\x9a\xee\xc5\xba\x56\x82\xb2\x79\xc5\x5e\xcb\xb2\x39\x6f\xca\xbf\x50\x1e\xfb\xd1\xdd\xb7\x2f\xbe\x3a\xd9\x9d\xfe\x74\x17\xf4\x1f\xb8\x71\xe5\x53\xca\x7f\xef\x98\xbf\xe2\x09\x58\xbd\xfb\xbf\xb2\xca\xef\x81\xca\x15\xe9\x36\xbe\xa7\x72\x05\x8f\x04\x7f\x55\xf9\xab\xc4\x24\x21\x22\x6a\x56\xdf\x81\x95\xe2\xe0\x87\x25\x50\x69\x1c\x95\x24\x35\x8d\x96\xa8\x44\x2e\xfd\x52\x18\x93\x4b\x2c\x64\x90\x02\xa7\xdf\x09\x6f\x0e\x25\x5c\x44\x99\xc2\x61\x21\x42\x2c\xc4\xe4\xcf\x7f\xe1\xa7\x26\x2f\x75\xa1\x60\x37\x2a\x71\x21\x5f\x77\xc6\x5f\xe2\x93\x62\xa8\xd4\x95\x09\x94\x06\xa5\x58\xa6\x0c\x3f\xd3\x81\xd2\xa0\xae\x85\x57\x96\x4a\xfb\x4b\x7c\x82\x98\x02\xd9\x80\xcf\xaf\x32\xee\x40\xdd\xcf\xe4\x5d\x95\x46\x05\x51\xae\xac\x49\xa5\x50\x89\x90\xe1\xca\x43\x8d\x55\x3e\x5a\xf9\x90\x79\x4f\x2a\x85\x52\x02\xd1\x7c\x00\x72\x63\x0d\x7e\x59\x0e\x8f\xb7\x3c\xc4\x17\x95\xcc\xd4\x73\x8b\xbe\xa3\x88\x03\xb2\x11\x69\x24\xec\xaf\xbd\xd3\xeb\x6d\x91\x37\x33\x61\xc9\xf6\xeb\x76\x3e\xb1\xe1\x1f\x3b\xa6\xdd\x5f\x6f\xb1\x4a\x33\x0e\x4d\x2a\x6b\x60\x4d\x73\x9e\x99\xba\x71\xcf\x8b\x07\xaf\x79\xbd\xe3\xa6\x59\xb3\x9f\x9a\xc1\x74\x2f\x6c\x9f\xbe\xef\x86\xe7\x6f\x3d\x34\x13\xce\xfc\x05\x9c\xfe\xa3\xbb\x6f\xbf\x71\x7a\xf3\x1b\xd9\x9f\x29\xbb\xde\x6a\x6f\xff\x4e\x87\x32\x08\x6e\x59\x7e\x80\xbd\x7d\xd6\x9b\x07\x3f\x4d\xc3\x92\xad\xf8\x7d\x7d\xfa\xc0\xbc\x95\x8f\xc2\xe8\x93\x9f\xee\x56\x72\xaa\xde\xe9\xe9\x39\x5c\x87\xd1\x0d\x9c\xc0\x0b\x4a\xc0\x7e\x6d\x16\xd5\xa4\xd6\x5a\xb3\x76\x17\x29\xb4\xfa\x93\x64\xd6\xd2\x9c\x40\x5c\x9c\x14\x59\x4d\x64\xfa\x29\x5f\x5a\x5d\xf5\x95\x8b\xbe\x0d\x13\x69\xe6\x90\xab\xdf\x80\x44\x57\xc6\x2c\x9a\xa4\x58\xc6\x8f\x9f\x2f\x75\xcf\xff\xea\x69\xc2\x3b\x52\x82\xff\x9a\x2e\x11\xf5\xd5\xe6\xb4\x51\x2c\x21\x6f\xc2\x68\x16\x29\xf5\x16\x7d\x13\xbc\x49\x10\x65\x86\x64\x2f\xd0\x85\xaf\x13\x37\xe5\x17\x49\xfa\x5a\x93\xac\x14\x61\x23\x30\x02\x23\x2c\x4c\x4a\xa4\x0a\x9b\x24\x82\xa8\xce\xf9\x5b\x7e\xbb\xe1\x50\xeb\x29\xe5\xc8\x36\x78\x7e\xfb\x5f\xe0\xf8\x69\x5f\x98\x2a\x26\xba\xb7\x05\x0c\x5d\x8b\x7f\xa6\x4c\xfc\x66\x0f\x7c\xbb\xe7\x51\x66\x06\x29\xc4\xbe\x7f\xc9\xfc\x4b\x1e\x56\xda\x3f\x27\xbc\x62\x73\x0c\x0e\x23\x9d\xcf\xfe\xae\x8a\x1a\x13\xd8\x1c\x12\x5c\x54\xa5\xdc\xad\xc5\xf2\x11\x16\x1f\x06\x5a\x86\x52\xae\xe6\x5b\xe5\x40\x10\x49\x15\x35\xe2\x15\xc4\x43\xc0\x61\xf3\x07\xc8\x14\x0f\x27\xa8\x28\x77\x49\xa5\x00\x48\xf2\x5e\x1f\x5f\x5d\x43\x8e\x36\x0f\x41\xba\x47\x5a\x1b\x61\x2b\x45\xbb\x73\xcc\xd6\x9f\xc1\x39\x9f\x4d\x1a\xd5\xb0\xe5\xfc\x86\xe8\x45\x95\x43\x7a\xba\xc6\x7c\x6f\x73\xf6\xf1\x23\x37\x4e\x9f\xbc\x6d\xe9\xac\xb9\x6f\xcc\x64\x86\x54\x54\x3e\xaf\xfc\xed\x21\x26\x00\x21\x3c\xf2\x17\xfb\xe4\x5b\x05\xf7\x0e\xc9\xfd\xcd\xde\xe0\xf0\x3d\x23\x2a\xf6\xfd\xfa\xc2\x3f\x3f\x7e\x64\x1e\xd7\xc4\xfd\x50\xe9\xa4\xf8\xa1\xb7\x95\xc9\xdc\x12\xa3\x1b\x94\x81\x2a\x70\x99\xca\x49\x29\xf1\x2a\xbe\x3f\xac\x36\x40\xa3\x24\xf2\x09\x4a\x74\x54\x3a\x48\xf9\x5e\x80\x2c\x95\x08\x62\x1a\xfa\x08\x49\x5c\x58\xc8\xb2\x2e\x07\x11\x40\xc1\x49\xb5\xcd\x4e\x09\x99\xaa\x9b\x87\x90\x75\x49\x49\x56\x5b\x16\x25\x8b\xa8\x61\x25\xb7\x0f\x62\xbf\x4e\x41\xdb\xa2\xad\x90\x7b\xaa\x7e\xd0\x9f\xb6\x7d\xdd\x9c\xac\xaa\x55\xda\x13\x17\x5f\x74\xe7\xa8\x3b\x77\x4e\x9f\xfc\x87\xd7\xfd\x70\x89\x65\x7e\x76\x96\x32\x19\x7e\xbd\xe8\xcd\xa3\xf0\xb2\xd7\x8c\xf0\x15\xa5\x46\xdc\x2e\xd8\x4e\x1d\x0f\xd4\x96\xed\x18\x5d\xae\x4c\x64\x9b\x26\xb6\x32\x6f\x3c\xa4\xfc\x0d\x40\x30\x0a\x00\x76\x9a\xa1\x0b\xd8\xc1\x1a\x95\xf3\xcc\xac\x4e\x37\x22\x2e\x99\x85\xc0\xc6\xda\x63\xb2\xc9\x9e\x4c\xca\xd0\x98\x93\x19\x43\x22\x01\x91\x43\x0b\xec\x64\x67\x7e\xe2\x87\x0e\x45\xb0\xf8\xb0\xc6\xd1\x9c\xb9\x1b\xd9\x5c\x19\xc6\xc6\x4a\xb1\x7e\xf9\x45\x58\x29\xc6\x1e\x62\x08\xb3\x88\x9e\x55\x44\x6a\x4d\x4a\xc9\x3c\xab\xc8\xa8\xd0\x13\xeb\xba\xd6\xc3\x31\x21\xe5\xf5\x05\x4c\x53\xa4\x27\xb0\x89\xd9\xdf\xc9\xac\xec\x59\xd3\xd9\x73\xea\x09\x66\x3f\x79\x1f\x3f\x3e\x3d\x87\xeb\x32\xba\x81\x0b\x48\xe0\x39\x90\x76\x00\x42\x03\x42\x5c\x0b\x99\xc8\xc4\x47\x9a\xb1\x48\x89\x44\x02\x19\xe3\x10\xb9\xe3\xc8\x71\x4c\xb6\x4b\x39\x82\x73\xa0\x81\xe8\x3e\xf2\xcd\x1d\x24\x0e\xb5\xbb\x90\xd4\xfd\xd2\xc8\x47\x4e\x1c\xd1\xd8\x96\xa1\x83\x91\x62\xc8\xee\xca\xd8\xec\x92\x14\xc3\x9f\x38\xb5\x4f\x04\xfc\x49\xda\x59\x44\xbe\x0c\x53\x69\x9b\x5d\x52\x39\xb9\x32\xd0\xe6\x14\x54\x7e\x29\xc6\xe6\x14\xa4\x02\xbf\x14\x18\xdc\xc4\x43\x29\xdc\x1a\x6e\x4d\xf2\x49\x3e\x82\x8f\x34\x33\x6c\x8d\xb4\xc2\xbf\x6e\x56\x6e\x8a\x30\x5f\x8e\xd8\x31\xf2\xd2\x8a\x6d\xca\x9a\x07\x5e\x3c\x4f\xf9\x5f\x66\xd1\x43\x73\x76\xb2\x56\xe6\xf1\xbd\xed\xed\x7b\x7b\x9e\xeb\x19\x05\x5d\xca\x64\xee\xd5\xbf\x02\x00\x81\x45\x71\x93\xb9\xba\x56\xf0\x7d\x95\x7b\x5f\x3f\x55\x87\xe2\x71\xb9\x1e\x47\x10\x43\xb5\xe1\x3a\xfd\x48\x1d\xbe\x06\x4a\xec\x82\x98\xb5\x72\x55\x4d\xb4\xbc\x23\x74\x59\x5c\xde\xb2\x9a\xfa\x38\xfe\x5b\x85\x98\x0e\x0e\x6a\x20\x95\xb2\xfa\x38\x9d\xbc\xab\x12\xd2\x83\x12\x49\x95\x26\xe1\x9f\x1c\xb0\x8b\xc1\x72\xe8\xc3\xbf\xa4\xb2\xa0\x34\xc2\x9a\x46\xd8\xdf\xa4\xdd\xd8\xc5\x73\xaf\x69\xfc\xd5\x51\x4b\x89\x60\xb0\x8c\x1b\x33\xfc\x82\x11\xdf\xdb\xb8\xce\x62\x1c\x94\xf4\xd4\xf5\x37\x72\x37\xa4\x6d\xcc\xb0\xef\xcd\x1a\xfd\x68\xba\xe4\x8a\xd8\xb4\xcb\x02\xdb\x82\x3b\x0e\x4c\x68\x2b\x77\x38\xb5\x3e\x9f\x9b\xf4\xf9\xfc\xa0\x11\x14\x1a\x7b\x62\x5c\xb6\x63\xf3\xe0\x0c\x0c\xc6\x80\x6c\x17\x69\x9a\xc1\x0a\x69\xa3\xd3\x43\xd9\x97\xf2\x4c\xaa\xc5\xdf\x39\xa2\xeb\xc5\x5d\x7b\xf5\x64\xc1\x3e\x76\x5c\x72\xe2\x98\xc9\x1b\xd7\x3b\x4d\x97\x5f\x49\x9b\x71\x47\x83\x6b\xef\x9b\xd9\x16\xdc\x1e\xdc\x76\x70\x7a\x1b\x80\x60\x3d\x00\xec\x6b\x86\xa3\x40\x02\xcb\xd5\x4e\x8c\x94\x4c\xdb\x09\x17\x1a\x9b\x23\xce\x59\xe8\x40\x19\x20\x41\x6c\xe5\xfd\xf4\xc9\x13\x7f\xa0\x97\x02\x45\x1a\x90\x3e\x3f\x90\xa1\x88\xa3\x22\xfc\x24\xe7\xbb\x84\x83\x7f\x8b\x35\x85\x23\x3e\xd9\x64\xc7\x2f\xce\x44\x3e\x72\xa5\x52\xc8\x2e\x90\x21\xba\xa4\x34\x92\x51\x67\xb2\x48\x50\xeb\x32\xb0\xeb\xef\x7b\xfd\x47\x33\x96\xcd\xde\xb6\x77\xec\x0b\x1f\xbe\xf0\x41\xcf\x57\xb7\x30\x5b\xc7\xac\xdc\x39\x6d\xce\x8a\xd9\x5b\x3b\xde\x3b\xa8\x6c\x78\xbe\xe7\x43\x6c\x43\xd0\x06\x00\x3b\x8a\x6b\x07\x6e\x7c\xf2\x59\x70\x90\xce\x92\x01\x32\x53\x0e\x22\x4f\x1c\x59\x8e\xc9\x66\x81\xb0\xff\x39\xd4\xe1\x29\x2f\x21\x04\xd4\xc6\xdf\x1d\x42\xda\xc4\x0a\xc4\x9d\x04\xfc\xa1\x11\x7f\xc8\xd2\xd0\x54\xa2\x71\x98\xcb\xc0\xe3\xbb\x9d\x5e\xe7\x7c\xdb\xa4\x67\x96\xa0\xf7\x95\x40\x4d\x7a\xc4\x3f\x7e\x7e\xfb\x35\x57\xde\x35\x8e\xfd\x72\xe8\xe0\x9f\x3e\xa7\xdc\xfa\xc8\x6b\xb0\x66\xd2\xb1\x7b\xe7\xdc\x15\x1b\x0c\x58\xc0\x01\x40\xe6\x2a\x25\x50\x01\xea\xc0\x31\x95\x75\xc5\x6d\x52\xa7\xb4\xeb\x4c\xb9\x2c\x80\x22\x3e\xc8\x98\x60\x32\x29\x03\x36\x27\x4b\x15\x89\x44\x36\x5c\x46\x3e\x24\x68\xb9\xfa\x38\xf2\x1f\x93\x1d\xee\x1c\x3e\x09\x78\x22\xf8\xe5\x26\x82\x5f\xbc\x3b\x2f\xdd\x34\x72\xc7\x89\xa7\xc8\x61\x21\x36\xa2\xba\x46\x24\xba\x64\xb7\x70\x12\xe7\x7b\xac\x70\x12\xdf\xcf\x8c\xc8\x4a\xb1\x8c\x84\x9f\xc8\xed\xca\x94\xb9\xeb\xa4\x58\x26\x48\x9e\x15\xe4\x19\xc6\x4f\xf6\x7c\x0b\xc3\x8a\x92\xbb\x2c\x58\x11\xae\x6b\x6c\xd4\xd3\x2a\x51\x76\x39\x87\x3f\x95\x22\xd5\x7d\xc2\x03\x80\xea\x54\x76\xcc\xd6\xa4\x14\xd6\x0d\x03\x72\x75\x50\xf2\x85\xd5\x41\x3b\x9c\xa3\xe4\xa1\x23\x5c\xf8\xa1\xa3\x70\xc5\x47\x9f\x3c\xb3\x7b\xf1\x32\xe5\x17\xca\x37\x4a\x43\xdb\x46\xc8\x1c\x7c\x75\xd3\x3d\xbf\xab\x81\xfe\x0a\xe5\xf7\x73\x3f\xdf\x91\xbd\xfd\xfe\xf7\x60\xfb\x1e\xf6\x85\x03\xfb\x36\x1e\x29\xb7\x54\x3c\x7c\xd3\x07\x7f\x83\xed\x3f\x78\x78\xf3\xa2\xdb\xd2\x7b\xe0\x1f\x37\xae\x98\x31\x97\xd6\x61\xc6\x9d\x3e\x6e\xd8\x6b\xe8\x02\x5e\x50\x09\x1d\x74\x66\x55\x2e\x55\x6f\x88\x34\x87\x63\x1b\x7c\x4b\xb8\x58\x7b\x2c\x63\xf3\x96\x87\xaa\x7c\x49\x19\xb2\xb9\x0c\x63\x30\x9a\xab\x7c\x09\x22\x05\x26\xe5\x07\x9e\x74\x73\xf0\xf8\x0c\x32\x59\x88\x2a\x18\x31\xed\xc6\x13\x1d\xf9\x82\x80\x87\x5c\x21\x15\xdd\xf9\x4f\x71\x0c\x14\x24\xe5\x0f\x7b\xb7\x01\x79\x5c\x19\xc6\x83\x6d\x5c\xe1\xca\x18\x2a\xf0\x95\x12\x74\x65\x8c\x41\x9e\x9e\xca\x66\x3b\x0e\x92\x6c\xf8\x89\x7f\xd3\x4b\x7e\x33\xe8\xca\x94\x93\x5f\xa8\x70\x65\x42\x15\xa4\x35\x9d\xb1\x7b\x82\x15\xe4\x70\x3e\xdf\x86\xbf\xad\xcd\xee\xf1\x06\xcb\x43\x15\x8d\x8d\x45\xef\x44\xe6\x39\x41\x94\x5d\xa5\xa9\x14\x32\x09\x04\xba\x02\x4a\x09\x79\x41\xfe\xb2\x92\x92\x6c\x92\x8f\xf0\x64\x2a\xa3\x79\xc8\x28\x15\x0b\x39\x0a\x86\x79\x07\x1c\x57\xb1\x7d\x65\xd7\x4a\x66\xf7\xca\xae\x15\xbb\xc2\xbb\xe3\x74\xbc\xde\x1f\x5a\x45\xe6\xed\x1b\x7a\x66\x56\x98\x1d\xcc\x87\x7b\x98\xd1\x3d\xaf\xe3\xff\xf7\xfc\x46\xf9\xfb\x37\x3f\x7f\xe3\x92\x5b\x3b\x95\x83\xb7\xdc\xf5\xdc\x0f\x3f\xdc\x55\x75\x13\x3e\xbb\xee\x03\x80\x0b\x19\xb2\xc0\x02\xc6\xeb\xfa\xf7\x10\x59\xf3\x52\xf9\xb6\x3c\x65\xdd\xf6\x7c\x57\xde\xd0\x4d\x8b\x2b\xbd\xcb\x2a\x40\xeb\xb7\x93\x54\x76\x09\x1b\xf8\xc1\xe1\x43\xf3\x25\x63\xdb\x74\xa5\xc4\x90\xfd\x7a\x22\xbb\x1b\xed\x7b\xf6\xd0\xa9\x05\x80\x05\x93\x4e\xcf\xe1\x16\x1a\xdd\x44\x5d\x28\x00\xd6\xab\x13\xcb\x80\x86\xaf\xee\x44\xda\x65\xc7\x69\xb9\x4b\x30\xc7\x08\x76\x1a\x41\x3a\x19\x12\x48\x64\xfd\x3e\xc1\x60\x27\xb9\x89\x9f\x46\xba\x6c\x1c\x92\x02\x65\xfe\x6d\xdf\xaa\xf5\x91\x03\xa4\x8f\xec\x76\x9d\x24\xf3\x87\xae\x93\x78\xe7\xf8\xdc\x01\xa2\xef\x12\xa0\x7d\x64\xb7\xcf\x1f\xd0\x47\x09\x49\xa8\x5e\x9b\x44\xa7\x25\xcc\x87\xf9\xc8\x28\xbc\x22\xbc\x43\x26\xc1\x66\xc6\x58\xb7\xb9\xee\xb2\x48\xc7\xdb\x87\x42\x1f\xff\x06\xde\x1c\x51\x16\x8c\xe9\x1c\xed\x6b\xfa\xec\xb1\x8a\xb7\xdf\x56\x3e\x30\x74\xb5\xb7\xab\x5d\xe3\x9d\x3b\xf7\x32\x96\x3d\xf0\x47\x00\x70\xa7\x77\x2b\x93\xb9\x4b\x8d\x6e\x50\x4e\xf4\x03\x07\x83\xb5\x20\x1d\x20\xa7\x88\x16\xdb\xd5\xf1\xb9\x6c\xa4\x2a\xc0\xdb\x63\x72\xc4\x98\x9f\x73\x63\x09\xfb\x3a\x0a\xb9\x08\x11\xbf\xc3\x45\x27\xdb\x42\x2a\xc3\x5f\xa3\x70\xbe\xd5\xcc\x0b\xee\x40\x50\xac\xac\xaa\x1d\x44\xa9\x9c\x32\x16\x9b\xcf\x4f\x86\xab\x22\x6e\x41\xcc\x88\xac\x2f\x8c\x13\xa2\xba\x80\x20\x66\xa1\x23\x38\x68\xb0\xaa\x69\x6e\xcb\x07\x84\x2d\x24\x20\x84\x64\xef\xb3\x85\xde\x30\x09\x09\x5b\x23\xad\xc9\x44\xab\x14\xa9\x34\x1a\x5a\x9a\x87\xd4\xcc\x84\x65\x53\xb6\x7e\xbd\xa3\xba\xf2\x4f\xdb\x4e\x83\x8e\xff\x7c\x77\xff\xb0\xd9\xb4\x2f\xbc\x74\xca\xe7\x7f\x30\x4d\x9b\x5e\xea\x1c\x3f\xba\xcb\x34\x27\x0b\xc5\x47\xbc\xca\x64\xc6\xb7\xf0\xb9\x57\xe0\xe4\x37\x38\xf8\x92\x12\x1a\xd7\xb9\xf5\xb5\xb0\xf2\x66\x9c\x34\x87\x1b\x94\x11\x6c\x6a\x58\xe4\xc0\x16\x23\x9c\xdc\xbd\x28\xb5\x2a\x16\x04\x50\x39\xa2\xac\x60\x2e\x23\xe7\xec\x43\x20\x6d\x61\x48\xf2\x89\xaf\x50\x96\x84\xf0\xb2\xd1\x99\x4c\xe2\x9b\x4c\x36\xdb\x70\x94\xe8\x26\x37\x82\xd5\x52\xb8\xc3\x1e\x3e\xd1\x95\xcf\xec\x0d\x24\xb3\x77\x75\x1b\x28\x4b\xa7\x45\x8a\x65\xcc\xf8\x89\x5c\xae\x8c\xcd\x65\x95\x62\x19\x27\x7e\xb2\x40\x36\xb8\x70\x00\x85\x77\xa8\xd3\x55\xd8\x96\x38\xdd\x47\x8e\x14\x90\x59\x91\xce\x57\xf3\x02\x82\xa9\xc1\x4d\xb0\x95\xb0\x06\x47\xc8\xde\xc4\xee\xc1\x84\x2b\x95\x23\xc6\x0b\x26\xfe\x74\xc8\xda\x87\x2b\x77\xdd\x77\x78\xc3\xce\xc8\xce\x75\x57\x28\x7b\x6f\x50\xb6\xee\x76\xff\x9d\x59\xb4\x87\xd9\xda\xb3\x60\x4f\xcf\x0a\x65\xa5\xc6\x63\xce\xd4\x18\x7e\x03\xdc\x20\x84\xe3\x49\x33\x4e\xb1\x2d\x64\x95\x0c\x9f\x43\xc6\xb8\x6c\x70\x24\x93\x32\x6f\xcc\xc9\x26\x6b\x82\xa0\xe5\xfc\xe6\x1c\xc1\xc7\x99\x8f\xc9\x16\x21\x47\x38\x84\xe4\x52\x6b\x4e\x0e\xf7\x2e\xd5\x98\x49\xa9\xc6\xe2\x42\xce\x6e\x03\xe2\x5c\x19\x03\x67\xc6\x41\x31\x7e\x22\xa7\x2b\x63\x75\x62\x23\x38\xf0\x93\x05\x32\xe7\xc4\xab\xe6\x0c\x26\xab\xc3\x59\x58\xb5\xc5\x23\x88\xb2\x3f\x48\x20\x75\x24\x67\x00\xb2\x91\x51\xe1\x3e\xb0\xd7\xc2\x69\xc1\xb7\x50\x9f\xa7\x05\x9f\xf5\x1b\xcb\xef\x6f\x4f\xb7\x6f\x0c\x6d\xdc\x48\xca\x3e\xcc\xa4\xb1\x2d\xd3\xc6\xc7\xeb\x49\xfd\x87\x59\xdf\x09\x5f\x55\xc6\x76\xf6\xcc\x41\xbb\x3d\x7c\x6b\xaa\xad\x50\x8f\xdf\xaa\xb8\x0d\x1f\x19\xde\x01\x95\x20\x01\xba\xb4\x99\x3b\x53\x2e\x6d\x66\x88\x81\x28\x79\x42\x9c\x25\x73\xa0\x4e\x36\x4f\x4c\x15\xf1\x90\xd1\x3b\x3f\x8c\xc9\x76\x37\x61\x7b\x18\x52\x7c\x97\x72\xc8\xda\x68\x40\x96\x6e\x87\x1c\x28\x39\x89\xea\xbb\x33\x75\x81\x7a\x29\x96\xae\x0b\xd4\xeb\x47\x16\xad\x81\xba\x7a\x5a\x13\xb5\xa8\x3f\xd1\x02\x71\x44\x10\x33\x86\x8a\x6a\x12\xad\xda\xe9\x04\x29\x90\x2b\x9c\x82\x28\x0b\xf8\x12\x8d\x93\x61\x51\x13\xaf\xd5\x7e\x4a\x61\x95\x2a\x84\xa4\xce\x8a\xaa\xb0\x81\x51\xb0\x85\x4c\xe4\x30\xda\xd9\xad\x0e\x58\x30\x5b\x6f\xf8\x21\x14\x76\x7f\xbd\xd6\xd4\xf6\x80\xb2\xdf\xd2\xde\x58\xef\x9d\x18\xea\x58\x65\x6f\x70\x79\xcc\xbb\xff\xf1\xfb\xd3\x6f\x3c\xfd\xd0\xf3\x5f\x0c\x6a\xf1\x1f\x7a\x68\xeb\x5f\x37\x30\x31\x04\x67\x40\xc3\x86\xdf\xbe\x73\x72\x7f\x63\xc5\x54\xcf\x2e\x9b\xf3\xb6\xf9\x8d\x83\x3f\x98\x70\xf1\xcf\x60\x1c\xba\xdf\xf8\xec\xcf\x3f\xf9\xfb\xcd\x17\x6f\xdd\xf7\xa6\xb2\x53\x9d\xa7\x9d\xc3\xb5\x83\x30\x68\x04\xf3\x40\x3a\x04\x68\x4d\x59\x37\x9c\x14\xe3\x89\x34\x9b\x53\xc5\xc6\x80\x63\x72\xa5\x44\x50\x88\x3e\x3a\xc7\x48\xea\xc9\xbe\x4a\x41\xcc\x70\xa1\xaa\x98\x6a\x01\xca\x4c\x18\x72\x0a\x62\xda\x2e\xf8\x52\xa9\x94\x1c\x73\x53\x1b\x04\x7a\x4f\x21\x15\xcf\xcb\xb6\x88\x03\xcc\xcb\xee\xbc\x66\x63\xad\x75\xec\x3a\xe5\x4b\x6d\x5c\xd6\x76\xbe\x9f\x6a\x44\xbd\x78\x70\xea\xcb\xb7\xde\x30\x7d\xc6\xfe\xeb\xe1\xcc\xf7\xe0\x9c\xb7\x67\x4e\x3b\xf0\x4d\x44\x9b\x95\x8d\x4e\x81\x8e\xb6\x25\xf3\x48\xbd\xa4\x62\xfb\xf5\x4b\xf7\x2a\x9f\x12\x3f\x8a\x03\xc0\x6d\x34\x74\x01\x27\xf0\x03\x99\xe6\x6b\xb2\xd9\x9e\x4c\xd2\x50\xcd\x4f\x42\x35\x07\x09\xd5\x5c\x38\x54\x33\xe5\x64\x9b\x33\x41\xa9\x37\x70\xe6\x46\xa7\x36\xdd\x38\xbe\x94\x72\x79\xd2\x0d\xf5\x60\xc1\xa1\x1b\x4b\x92\x38\x7f\x37\xce\xd4\x18\x07\xab\xe5\x6e\x7e\x2d\x77\x53\x3f\x71\xe1\x4f\xd8\x43\x0c\x6b\x73\xba\xfc\x85\xfd\xe5\xb6\x0b\xa2\x6c\xc2\x51\x97\x51\x40\x66\x4d\x27\xc8\x94\x42\x7e\x3a\x96\x47\x82\xb0\x3c\x58\x37\x22\xb5\x6a\x31\x57\x3c\xfc\xc4\x03\x3a\x88\x6e\xd7\xaa\x8f\x28\x48\x97\x99\xb6\x8b\x79\x4d\x8f\xcd\x9d\xb6\x6b\xdf\x43\x4b\x6e\x24\x39\x09\xf0\x01\xc0\x2e\x24\x33\x4a\xeb\x41\xda\x47\x67\x0f\x29\x56\x4e\xe5\x50\xc1\x3b\x29\x0b\x81\xcf\x62\x8f\xc9\x1e\x3f\xcd\xc1\x35\x22\x12\xdf\x31\xd9\x6b\x21\x1c\x82\x24\xaa\xb2\x17\xac\xb1\xf3\x84\x4c\xac\xe1\x23\x76\xf0\xe2\x78\x8a\x95\x3d\x7e\x95\x67\xca\x27\x88\x88\xa1\x73\x94\x69\x83\x51\x24\xe1\xb8\x13\xaa\xc2\x40\x6a\x50\xa3\xc3\xe3\x1a\xc9\x3d\x1b\x91\x7c\xe5\x9b\xdb\xf5\x40\xdc\x79\x87\x86\xfd\xae\xfc\xc4\xfc\x43\x0b\xe0\xa9\x4e\xf8\xaa\x8a\xc1\xdd\xd5\xd9\xa9\x70\xf0\x14\x7e\xcf\x0b\x00\xe0\xde\x33\x74\x01\x01\xb8\xc1\xfd\x54\xe7\x0c\x39\xe8\x5b\x46\x7c\x32\x6b\xb6\x3a\xf1\x4b\x06\x62\x92\xb0\x9a\xca\x90\x14\x16\x3c\x64\xe0\xd0\x21\xe5\x32\x9c\x43\x1d\x38\x44\x6c\x9c\x54\x1a\xbc\xbd\x7b\x79\x67\xe2\x2c\x76\xb2\x82\x28\x33\x42\x2a\x25\x3b\x70\xf4\x66\x20\xe5\x45\xab\xb3\x10\xb7\xb1\x49\x49\x8d\xdb\x70\xe6\xcd\x26\x03\x70\x41\xe5\xa2\x71\x87\x47\xc0\x27\x9e\x7d\x2f\xbd\x2c\xf2\x86\xf2\xec\xcd\x2f\x2e\x5d\x7d\xb0\xed\x28\xe7\xda\x03\x8d\xca\xd7\xf8\xff\x3d\x8a\xb3\xe7\x33\x26\x0a\xff\xa4\xfc\x18\xb6\x82\x7c\x5f\x8f\x6b\x23\x5c\xcd\x77\x83\xb4\x95\x74\x2c\x9c\xc9\x24\xf2\xd3\xdb\x42\x8a\xcb\x7c\x20\x99\x94\x05\x63\x4e\xb6\xd8\x13\x14\x15\x6a\x25\xc3\x65\x1a\xc6\xb3\x3b\xfd\xe5\x03\x2a\x9c\x04\xf1\xdd\xc8\x46\x98\xd0\x09\x84\x84\xd7\x4a\x25\x38\x08\xca\xf0\x16\x7b\x40\x73\x52\x9b\x95\x8c\xc0\x02\x99\xf1\x93\x22\x19\x92\x04\x19\x94\xeb\xfb\x7e\x91\xa2\x15\xd2\x8b\x80\x74\x02\x99\x56\xb5\xfb\x37\x75\x7f\xa8\xa3\xe5\x50\x1c\x4e\xe9\x3e\xf2\xd6\x82\xd0\x6e\x65\x1a\x69\x00\x32\x01\xc9\x66\x74\x0e\x1d\x33\x81\xf6\x00\x99\xf6\x4e\x78\xa3\xf2\x00\xfe\xbf\xf3\xd4\xd7\x07\xee\xf5\x70\xd1\x03\x47\xc7\x47\xef\xdc\x70\x6f\x01\xf3\x19\xe3\xa6\x81\x20\xa8\xc5\x1e\x4c\xb4\x03\xbc\x46\x7a\x86\xc9\x51\x63\x2e\xeb\x0c\x95\x99\xed\x31\xd9\x69\xc8\xa5\x43\x4e\x82\xb8\x67\xcd\x31\x0d\x72\x2d\x59\x72\x19\x56\x02\xa6\x58\x96\xf3\x82\xd5\x5c\x0c\x67\xbd\x95\x30\x26\xdb\xdc\x94\x7b\x83\x23\x43\x96\xe5\x29\xa2\xb2\x68\xf6\x96\x96\x45\x29\xdc\xa3\x8c\x2e\xda\x29\xc8\xa0\x24\x95\x42\x21\x32\x22\x1c\x15\xd2\x46\x9b\x41\x15\xaf\x69\x95\x92\x1e\xad\xb0\xcf\x19\xf8\x3c\x02\xd6\x67\x8c\x54\x48\xad\xf9\xf4\x72\x91\xed\xc1\x95\xe6\x09\x4f\x5e\xdf\xf9\xac\xf2\xbf\xca\xd1\x7d\x92\x61\xea\xd4\xef\x6c\xbd\xb0\xf5\xb9\x97\x95\xdd\x7f\xba\xef\x83\xcc\xcc\xef\xac\x3c\x58\x01\x2d\xc9\x91\xcc\x3b\xbb\xae\xfe\xde\xa3\xf7\xa4\x5f\x75\x18\xaf\xac\xf7\x5e\x72\xf9\xe0\x8a\x75\x53\x99\xb1\x46\xf3\x8a\xdb\x26\x5c\xf1\xc4\x76\x7c\x96\x9f\x3e\x4e\xce\x72\x11\x54\x80\x6b\xcf\x38\x6d\x4a\x48\x2d\x0b\x49\xbe\x0d\x52\x6e\x46\xb2\x6c\x09\x9f\xe4\x2e\x6f\xb0\x37\x5d\x9e\xf7\x6c\xac\x8c\xc5\x5d\xf9\x33\xcf\x8e\x0e\x38\x32\x4a\x30\x43\xa7\x8f\x73\x23\x0a\xeb\x20\x6d\x38\xbb\xb6\x0e\xd2\xfa\x34\xea\xd7\x01\x8f\xc9\x8c\x2d\xa7\x62\xff\x65\xb3\x85\xae\x43\x25\x86\x20\xaa\x34\xa5\x42\xc6\x68\x27\x2b\x52\xd7\xc1\x99\x5d\x02\x4b\x71\x29\xf8\x94\x69\xd1\xd7\xf5\xf9\xe2\x29\x8b\xd4\x1f\xf1\xd7\x7f\x7b\xc3\x23\x1b\xbf\x7c\xf0\x9a\xcd\xb5\x96\xd1\xeb\x6f\xbc\xea\xfa\xe7\x66\x4c\xbd\x62\xda\x8b\xb7\x71\x6d\x47\x7f\xf5\xa3\xe7\xdf\x55\xf6\xbc\x33\xeb\xea\x03\xb0\x7d\xd6\x6d\xcf\xc1\xe0\xa3\x0b\x6f\x3a\xa8\x7c\x06\xf2\xeb\x30\x86\x40\x08\x0c\x02\x57\xa9\xeb\x28\x25\xa0\x0c\x3e\x47\x95\x1c\xea\x48\xa1\x56\xe6\x4c\x24\x17\x25\xd5\x97\x86\x38\xaa\x21\x47\x2a\x8e\xe4\x81\x5c\x07\x04\x31\xe3\x54\x5f\x87\x24\x20\x3b\x41\x3e\xd8\x52\x32\x57\xaa\x8e\x6c\x26\x21\x71\x31\x9f\xa7\x3a\x52\xc9\xf7\x69\x25\xe9\x96\x43\x8b\xb6\xce\xca\xbb\x6e\x8d\x8c\x15\x62\xa3\xae\x2c\x1d\xec\x09\x98\xe6\x3c\x73\xd5\xfd\x8f\xde\xf3\xf7\x87\xae\xdd\x56\x6d\x19\xbb\xee\xc6\x39\x33\xf7\xcf\x3c\x78\xed\x91\x85\x9c\xb2\x7b\x8d\x68\x7e\xc0\xbd\xe2\xa3\x49\xd3\x6f\x9f\xf5\x46\xfa\x3d\xe5\x91\x1f\xcf\x9c\xba\x1f\xb6\xcf\x5d\xf2\x04\x8c\x3c\xf6\x5f\xaf\x2a\xbf\xa1\xf5\xac\x13\xa7\x8f\x93\x5a\x8c\x1f\x8c\xa0\x77\x87\xcc\x6a\x75\x3f\x0b\xad\x68\x21\x9e\x6a\x07\x91\xc2\x16\xeb\xd3\x50\x88\x69\x68\x27\xef\xc6\x85\xf7\xcd\xe0\xa6\x9a\x56\x9d\xd1\xf9\x66\xf5\x8d\x70\x91\x4a\x47\x72\xe9\xec\x05\x99\xeb\x57\x2d\xbe\x68\xf5\xa8\x3b\x1f\x7e\xe3\x17\xdb\x95\x6f\xf6\x3e\x10\x7e\x20\xf9\x20\xb4\xee\x5e\xb9\xbe\xb6\x6c\xc7\xe8\xff\x38\xf2\x8e\xf2\xdc\x8b\x80\x39\x7d\xfc\xf4\x2e\x16\x71\xed\x04\xff\xb2\x44\xcd\x9b\xb0\xa9\x29\xad\x04\x9f\xcb\xd6\x79\x02\x26\x3b\xb1\x3a\x99\xb3\xe6\xf2\x4c\x12\xd5\x30\x26\xfb\x1d\x74\xa8\x5a\xc4\x47\x35\x13\x24\xf4\xc0\x59\xbb\xc9\x13\xa0\x0c\xf3\x91\x80\x40\x40\x86\x75\x42\x9a\xf1\x13\x82\x15\x8f\x88\x38\xb5\x9c\x85\xdf\x89\x25\x35\xb8\x89\x6f\x69\xd5\x2a\xe7\xe4\xd2\x62\x82\x50\x03\x1c\x46\x2a\x6b\x8c\xbc\x54\x5e\x90\x49\x75\x8f\x98\x1a\xde\x0a\xb9\xa7\xb6\xae\x4c\x76\xcc\x5d\x90\x9d\x7b\xc9\xe3\x33\x6e\xdb\xf4\xe3\xf4\xeb\xf3\x87\xb5\xfc\xc1\x3f\xe3\xc2\xab\x6f\x39\x7f\xd8\xe8\x2d\xd1\x5b\xee\x18\xbf\xf8\x28\xbc\xec\xb5\xe6\xed\x43\x1e\x50\xfe\xf6\xa8\x7b\xc2\x25\xeb\x16\x6e\x7c\x68\xde\x65\xf3\xe0\xd8\x58\xb2\x6d\x44\x22\x75\x09\x3d\x03\xff\x7f\x5c\xd4\xc0\xb8\xa8\x99\xa7\x8f\x1b\xe6\x19\x43\xa0\x1c\xc4\xc0\xcd\xd4\x4b\xe9\x25\x11\xd6\x0c\x54\x4b\x6f\x49\xbb\x89\x22\xdf\xd8\xfc\x1c\x7e\x48\x22\x49\x35\x0e\x75\xbd\x76\xea\x1f\xbe\x10\x36\x4b\x59\x98\xcc\xbb\x7a\x85\xb4\xbf\x24\x4a\x0e\xc8\x5a\x1f\x3e\x20\x79\xa3\xbf\x04\xa7\xd1\xf6\x32\x52\xc1\xd5\x99\x60\x94\x7e\x9f\xf6\x2f\xb4\xa3\x2e\xdf\xe7\x16\xc3\x77\xdd\x16\x19\x23\xd4\x9f\x7f\x65\xa9\xf2\x97\xbe\x3a\x3b\xea\xea\x0f\x4e\x9d\xfc\xf0\xf7\xf1\x2e\x5d\xf2\xf5\x89\xa3\xfd\xac\x3b\x4a\xb4\xf2\xdb\x81\x17\x84\xc1\x1c\x95\x33\x82\x33\xe6\xa8\xc0\x57\x88\xcf\x65\xf9\x52\xb7\xdd\x1e\xc3\x59\x24\xe1\x9e\xb1\x1c\x93\x7d\x2e\x52\x20\x0b\xa8\x0c\x10\x11\xbc\x5e\x9c\xe1\x72\x29\x14\x10\x32\x76\xb7\x91\x2a\xe5\x73\x6e\x5d\xb2\x2b\x87\x4a\xf1\x0d\x69\x49\x69\x55\xf7\x0a\x29\x52\x59\xa5\x49\x05\x30\xaa\x52\xdb\x30\x48\x05\xf4\xa3\x17\x6e\xba\x1c\x96\x5c\x55\x7d\x52\x39\xfd\x93\x3d\x5d\xef\x6d\xfc\xe6\xf1\x69\x0f\x7c\x7a\x60\xf7\x28\x6e\xf9\x35\x97\xce\x19\xb1\x23\x9a\x84\xed\x8f\x3d\xb6\xe1\xd0\xf1\x9f\xbc\xa7\xbc\xf4\x54\x35\x2b\x5d\x75\xed\x85\xab\xb6\x5f\x43\xd6\xf3\xff\x3d\xed\x7f\xb2\x26\xc3\x5c\x6e\x1a\x88\x82\x46\xb0\x5c\xe5\x23\xa8\xd3\xde\x91\xd1\x98\xcb\x06\x3c\x11\xfc\x8e\x02\xa6\x7c\xfa\x55\xed\x20\x42\xf4\x83\x60\x0c\xb1\x09\x39\xe4\xcc\x21\x57\x82\x24\x61\xd5\x40\x1d\x0e\x43\x83\x84\xb4\x3d\x62\x24\x6e\x19\xa8\x13\x44\x19\x54\x13\xf1\x15\x54\x92\x42\x46\xf1\x30\x6b\x76\x09\xfe\xf2\xd0\x20\x9a\xab\x91\x83\xab\x75\x48\x55\x54\xbf\x46\x5f\xab\x8f\xea\xf7\xfa\x28\x41\xbc\x51\xbf\x64\xce\x38\x0c\x8e\x83\x33\x57\xac\xa6\xeb\x7d\xee\x5d\xcb\x3e\x8b\xa9\x31\x5e\x37\xa6\x3a\x75\xcb\x92\xeb\x16\xd8\x03\xd2\x8e\xdf\xae\x23\x06\x58\xfe\x46\x44\xf9\xf3\xef\x7e\x7f\xe0\xb7\x17\xdd\xb1\x95\x18\xe0\x0d\x14\x5b\x7e\xe5\x45\x25\xde\x55\x97\xae\x5a\x6b\x7c\x5a\xf9\x64\x0f\xb6\xc5\x3f\x8e\x0c\x7d\x04\xe7\x21\x23\x4e\x1f\x67\x0f\x70\xd3\x40\x0d\xce\x44\xa3\x84\x68\xda\x98\xa3\x09\x88\x8b\xcf\x65\xbd\x25\x51\x9c\x80\x78\x55\xbc\x3b\x38\x26\x97\x59\x72\x19\x9e\xd0\x4d\x4b\x74\xf8\x46\x96\xca\x04\x51\xe6\x58\x92\x7c\xaa\xe4\x1b\x25\x82\x0c\x2a\x53\x29\xe4\xa5\xff\x80\x5c\x02\x41\xe9\x22\x0b\xc5\xfc\x48\x43\x5a\x5a\x9b\xfb\x74\x88\x86\x41\x9e\xfe\x90\x27\xc9\x1f\xb1\xe3\x81\x89\x97\x7c\x96\x7d\xe5\x9e\x31\xb1\x35\x17\x2f\x5d\x75\xfd\xd5\x2b\xcb\x97\x3c\xb8\x6b\xfe\x0d\x13\x77\x5d\xb7\xe7\x27\x07\xde\x80\xc6\x55\x7b\x4a\xf9\x50\xc7\xc5\x9b\x9f\x6e\xbb\xaf\xa4\xe6\xda\x49\xe3\x2e\x7e\x70\xde\x8c\xcb\x26\xd7\x35\xed\xf8\xee\x03\x14\xcb\xcf\x4e\xe6\xda\x41\x0d\x8e\x68\xa2\x5a\x7f\xac\x04\xaa\x58\x7e\x9b\x35\x5a\x62\x27\xaa\x7b\x79\x2c\xbf\x33\x87\x9c\x15\xc7\x04\xbc\x48\x15\xc1\x1f\xa5\x9b\xce\xaa\x22\xf8\x6d\xa2\x1c\xaa\xa0\x08\x7e\x4f\x19\x25\xfa\xf2\xea\x11\xfc\x04\xf8\x5e\xa1\xde\xa8\x3a\x08\xbf\x3a\x40\xc4\xb4\x1d\xbc\x62\xcd\x83\xb3\x6f\x7c\x30\x32\x1b\x86\x26\x4d\x9e\xb0\xe6\xb2\xe6\xab\x9f\x9e\xfd\xd0\x73\x6b\x57\xbe\x74\xf2\x97\x93\x0e\x34\xed\x8b\x35\x2c\x9a\x36\x79\xe2\x83\xaf\x8e\x98\x10\x89\xac\x8f\xd5\xad\x5b\xb1\x70\x4b\x19\xd7\xf4\xc2\xbe\xee\x2a\xba\x1e\x03\xe0\xda\x41\x12\xcc\x02\xe9\xa6\x7e\xd6\xd3\xa4\xae\x07\xd5\xe0\x45\x84\xb1\xfb\x0e\x21\x0b\x6b\x74\xe6\xe4\x66\x18\x93\x1b\x79\x82\x3a\x03\xb2\x15\x5f\xb8\xb0\x91\xa2\x98\xa2\xb1\x41\xf8\x1a\x11\xc3\x82\x98\x75\x7a\xca\xaa\xea\xc8\x3d\x72\xa6\x35\x15\xb9\x6a\xcd\xd9\xd6\xb7\x6a\x6f\xc9\x4a\x0b\x1f\x6f\xac\x1f\x5d\x93\xba\xb5\xe3\x50\x74\xa8\xdc\xff\x6a\xaf\xbe\x32\xbc\x62\x72\x5b\xa9\x67\xd5\xa5\x1f\xdc\x55\xad\xae\x9a\xde\x25\x7f\xe1\x9a\xb8\x76\x20\x81\x3a\x70\x13\xe5\x97\x21\x4c\x5e\x06\x92\x6b\xf0\xb9\x6c\xa8\x5c\x30\xd8\xc9\xf1\x4a\x9a\x39\xe0\x98\xec\xb6\xe4\x90\x9b\x06\xa7\x0e\x67\x0e\x55\x62\x7b\x98\x9c\xa4\x9b\x23\x97\xba\x05\xb1\xcb\x60\x13\xac\xe5\x21\x9a\x56\x94\xfb\x04\x31\x0d\xdc\x84\x81\x33\x24\xd0\x73\x2a\xaa\x4a\x85\x0f\x11\x8b\x5e\x22\xa7\xd7\x08\x29\xd8\xc5\xc1\xcc\xfc\xde\x63\xff\xd3\xf9\xf8\xeb\x77\xdc\xfe\xf2\x69\xf0\xc9\xcf\x7f\x73\xe8\xce\x7b\xd6\xed\x59\xbe\x7c\x52\x68\x04\x8c\x4d\x9b\x7e\xfd\xde\xc5\xad\x70\xf7\x5a\x28\xbd\x71\xdd\x96\x3b\xe6\x6d\x28\xe1\x92\xe8\xe9\x23\xbf\x7a\xef\xfe\xfb\x16\x4d\x9f\x32\x7e\x6b\xd7\xe8\x8b\x2f\x7d\xf8\x18\x9d\x03\x63\x38\xae\x0d\xb8\x41\xe7\x59\xab\x8f\x24\x61\xa6\x65\xc7\x7c\x7e\xfc\x6f\xac\x36\x02\x99\x11\x05\x11\xb9\x49\x31\x64\xc0\x0a\x63\xff\x65\xc5\x3e\xd5\x44\x55\xfb\x9c\xc4\x03\xf5\xa0\x15\xcc\x56\xa7\x0d\x1a\xb4\x90\x7c\x08\x85\x63\xb1\x54\xfd\xbc\xcc\x44\x68\xec\x2b\x58\xda\xbb\x76\x12\xfd\x0e\x39\xa5\x49\xad\xa5\x41\xb4\x1a\xbb\xeb\x90\x06\x41\xcc\x9a\x9d\x1e\xaf\x09\xdf\xfd\x15\x92\x20\xa2\xaa\x94\x5c\x56\x4b\x06\x99\x07\xd2\x5f\xeb\x15\x11\x14\x69\xb1\x55\x6b\x82\xe8\xeb\x76\x97\x27\x25\x7a\xff\xf7\x17\x1c\xfc\xb7\x2a\xc7\xa6\x45\x06\xa7\x41\xf5\xe0\x35\xeb\x7e\x7e\xc1\xd2\xb9\x3f\xc8\xf6\x8e\x11\x32\x54\x8f\xad\x38\x46\xd0\x74\xe0\xcb\x41\xfd\x39\xa8\xcd\xc5\xf2\x6a\x73\x83\xfe\x1d\x6a\x73\xe7\xa6\x31\x77\x76\x69\x39\x00\xc9\x8c\xba\x85\x9b\x02\xca\x0b\xea\x81\xda\xae\xb4\xf0\x44\x3d\xd0\xa0\xaa\x07\x1a\xa9\x7a\x20\x15\x8f\x73\xea\x04\xe1\x9e\x3c\xf1\xdb\x62\xf5\xc0\xf2\x73\x52\x0f\xb4\xa8\xea\x81\x06\x41\x43\xd0\x51\x56\x23\x72\x44\xa9\xbc\x30\x52\xa4\x55\x45\xd0\xce\xbc\x6c\xdf\x9f\x36\xef\xeb\x1c\xb6\x6e\xd9\xf3\xff\x11\xb1\x2d\xbd\xe5\xe6\xab\x47\x7d\x1c\x82\xab\x96\x7d\x77\xef\x82\xd7\xfe\x03\xee\x5a\x01\x5d\x47\xe7\xb4\x75\x8e\xff\xe0\xbd\xb6\x61\xeb\x37\x04\x61\x43\x67\xcf\xfb\x91\x8a\xff\xa1\x31\x7e\x4a\x29\x21\x75\x1e\x1f\xa8\x04\xdf\xa7\xd3\x99\xb2\xd1\x91\x4c\xe2\xd8\x9e\x48\x7a\xd0\x98\xc7\xef\xc8\x21\x03\x3e\x64\x8c\x52\x0e\xf9\x29\xbd\xaa\xe8\xc8\xb7\x38\xbb\x3f\xfd\xfb\xda\x73\x50\x3c\xf5\x0b\xa2\xec\x09\x50\x3a\xaf\x0a\xc2\x06\x6c\x71\xe1\x6b\xd5\x10\xc0\x01\xbe\x59\xac\x50\x03\xfc\x91\xb0\x95\x4d\x4a\x5e\x5f\x72\x24\x03\x69\x6f\x48\x77\x2c\xd5\x38\x60\x2a\x76\x69\xfb\xc1\x97\xaf\xf0\x99\xcd\xce\x61\x23\xe1\xf9\xaf\xf7\xfc\x20\xb9\x75\xd9\xd5\xb7\xec\xad\xf0\x0d\x6a\x2e\x19\x75\xbe\xf2\xf9\xb0\x65\x6b\x56\xb0\xfb\x15\x71\xf3\x63\xd1\x25\x8b\x19\xe9\xd4\x94\x0f\x3a\xee\x3f\x74\xdb\x75\xd1\xc8\xd5\x63\x67\x4f\xbd\x7c\x13\x60\xc0\xb4\xd3\x7f\xe1\x5a\x09\x57\xcc\x60\x1c\xf7\x91\xb7\x5b\xaf\xd1\x79\x39\x93\xf8\xd8\x45\xee\x04\xc9\x6b\x42\xc7\xe4\x1a\x3b\x21\x95\x6d\x20\x43\x25\x34\x93\xa9\x09\x51\x4a\x81\x06\x41\x2e\xab\x24\x37\x65\xda\x64\xa6\xd8\xdf\x68\xbd\x20\x76\x99\xcc\x22\x28\x09\x91\xea\x3d\x2b\xc8\x50\x20\xe5\x1b\x9c\x83\x86\xa0\x37\xbf\x4f\xc9\x1b\xe5\xb5\x15\x36\x0f\x69\x69\x65\xab\x23\x95\x92\xb6\x52\xe3\xb4\xa6\x96\xf6\x86\x99\xb5\x02\x9f\x18\xf3\x6a\xd3\x94\xa6\xe6\x9a\x8a\xb0\x27\xd2\xa0\x3c\x31\x6e\xc3\x4d\x57\xcd\x9f\xd4\x71\xb0\xb4\xde\xf3\x1f\x95\x9e\xfa\x44\xe5\x22\xf6\xc8\x5a\xff\xcc\x0f\xaf\xba\xf0\x3b\xdf\xf9\xb8\xb5\xce\xbf\xd6\x12\x57\x56\x3c\x7a\xcb\xf2\x5d\x37\x5e\x75\xf9\xde\x5b\xe1\x8a\xe6\x53\xa7\x22\xe1\x8b\x86\xa6\xae\xbd\x03\xc7\x44\x8b\x48\x7d\xbe\x0d\x94\x02\x19\xa4\xfd\x7a\x22\x33\x22\xc7\x86\x04\x2a\xe5\x17\xe8\x9f\xbb\x4c\xa0\xba\x42\x3a\xb6\xb2\x3c\x91\x4c\x9e\x36\x85\x96\x69\xad\x48\x70\x65\xec\x82\x43\x8a\x65\x44\xfc\x4c\x8b\x82\x43\x37\x4f\x64\x4f\x01\xd9\x4e\x86\x3c\xec\xda\x90\x07\xa5\x39\xf3\xab\x5c\x79\xb2\xdb\x53\xa0\x37\x73\x7b\xfa\xa5\x37\x83\x11\xa9\x45\x4d\x7b\x8a\x38\xcd\x94\x83\xe9\x59\xb6\x38\xa5\x35\xeb\xc5\x64\x76\xf2\x27\xf0\x83\xe1\xfb\x6f\xbd\x61\x13\xb6\x05\xd5\xa4\x0b\x81\x08\xf8\x85\xda\x7f\xf6\x47\x92\xc9\xb4\x58\xd0\x4b\x2d\xaa\xa4\x50\xea\xbb\x88\x85\x74\x7e\xca\x20\xa1\x55\xc8\xf8\x3d\x65\x26\x75\x14\x35\x2e\xfb\x75\x24\x77\xaa\x3d\xb4\xc1\x96\x88\x0b\xd9\xba\x33\xf6\x88\x0d\xdf\x4e\xe4\x59\x89\x9f\xe9\xca\x88\x4d\x67\x16\x07\xb1\x4c\x16\xda\xec\x8e\x4a\x75\xe8\xb4\xf0\x33\x65\x5d\x8c\x08\x62\xda\xc2\x39\x53\x44\x47\x28\x63\x12\x79\x4a\x5d\x5b\x8e\x63\x75\xa7\x27\x95\x92\x39\x4b\x3f\x85\x1c\x27\xd3\x2f\x79\x4c\x51\xf9\xa6\x26\xd5\x87\x34\x26\x5f\xb6\x41\x9f\xf4\xa5\x8a\x21\xb5\xfe\x94\xe2\x26\x36\x1c\x04\x7e\xa8\xce\xfe\x0c\x52\x2d\x88\xcf\xf9\x40\x5c\xae\xe8\xb7\x24\x05\x8e\xc9\x83\x2c\x39\x34\x88\x2a\x05\x79\x68\x75\xaa\x3f\xbb\x0d\xa2\x76\x1b\x44\xec\x46\x9e\x31\xfc\x4c\xc7\x06\x0d\x60\xb7\x98\xce\x6e\xb1\x82\xdd\xa2\x83\x04\x31\xc3\x8b\x01\x5a\xb4\x03\x15\x82\x88\xca\x53\xa8\x46\x48\x3b\x3d\x04\xbb\xcc\x05\xce\x62\xb5\x3c\x1b\x43\xeb\xd9\xcc\x27\x47\x1f\x5f\x37\x66\xc4\xc8\xa1\xb7\xd7\xa3\x81\xcc\x78\xea\xcd\x83\xbb\x3d\x3b\x7c\x47\xd9\x61\x05\x63\x32\xc0\x0d\x00\x53\x67\xf8\x0d\xb0\x02\x2f\x78\x94\x4e\x22\x21\xb3\xda\x39\x21\x43\x8b\x16\x32\xb4\x68\xd5\x0d\x2d\x92\x4e\x9a\x99\x50\x38\x90\x39\x25\xaa\x52\xaa\xcd\xa3\xd8\x08\x5f\xa5\x35\x97\x67\x77\xd8\x7d\xe2\x87\xe4\x4a\xb2\xb8\x32\x8c\xa5\x9f\x19\x46\x8b\x2b\x63\xc5\x9f\xb3\x19\xc6\x60\xb2\xe6\xc9\x0d\x6c\xd8\xb7\xdc\x94\xa7\xc8\xc8\x53\xb0\x50\x3e\x5a\x8a\x04\x74\xcd\x58\x77\x68\x4b\x7b\x76\xfa\x83\xe5\x3b\xe6\x1d\x5a\xf0\xec\xd8\x96\xf6\xf1\xf1\x58\x2b\xe9\xa4\x28\x63\x49\x0b\x85\x9d\x9d\x6f\xbe\x42\x30\xf7\xf4\x71\xc6\xcd\xb5\x01\x01\x2c\xa2\x9d\x94\x02\xa9\x22\x97\x24\x84\x71\xbd\xcf\xa0\x3c\x63\xdc\xd7\x7f\x7b\xe8\xec\x38\x1b\x8e\xc7\x27\x8a\x13\x9f\x23\x66\x27\x45\x0c\xb0\x82\x0c\xac\xbd\xce\x12\xb5\x5d\x3a\xd7\xb3\x33\xbb\xcb\x35\xb7\xe5\xca\xf0\x0d\xd5\x2b\x57\x7d\x12\xbf\x9e\xf9\xb8\xa7\x62\xc2\xe0\x8e\xc0\xbd\x4e\xcf\x72\x52\x9b\x3c\x0a\x00\xb3\x89\x6b\x03\x56\x30\xb9\x17\xc3\x3e\xd4\xe9\x1f\xd8\xe2\xb2\x3d\x1f\xb4\x3e\x5c\x44\x9a\xef\x3c\x13\x69\x7e\x2f\x62\xfc\x66\xef\xee\x83\x9d\x5e\xf8\xa9\x77\xd7\xc1\x4d\xde\x79\x11\xb6\x21\x7a\xe3\x8d\xd1\x53\x1f\x44\xe6\xd1\x1e\x5b\x14\x00\xd6\x61\x74\x83\x12\xf0\x53\xaa\x56\x86\xc4\x24\xf2\xc6\x91\x3b\x49\x42\x6a\x2e\x91\x31\x33\x5e\x13\x51\xb4\x40\x20\x81\x0c\x71\x64\xd4\x54\x49\x75\x22\x91\x92\x35\xa6\x95\x2c\x35\x62\xb0\x40\x9e\x18\x8c\xa0\x78\x90\xe4\xca\x70\x92\x41\x8a\x69\x24\x09\x56\x24\xba\x32\xbc\x68\x94\x62\x19\x01\x3f\x0d\xf8\x37\xdc\xf8\x37\xd2\x82\x68\x2c\x16\x22\x95\x79\x01\xaf\x92\xe3\x05\x77\x01\x9e\x52\x42\x1b\x75\x44\xb9\x96\xbe\x1c\x03\x23\x68\x93\xc2\x92\x48\x87\x84\x49\x9e\x9c\x64\x22\x95\x35\x6c\x44\x22\x91\x4f\xf4\x3c\x39\x1a\x5e\x9f\x7d\x24\xec\x8e\x0d\xf1\xcf\x1f\xff\x74\x55\xd5\xa6\x43\x7b\xfd\x81\x58\xc2\xcb\x74\x42\xde\xce\xac\xef\x09\x3b\x9a\x47\x2a\x27\x85\x9e\x69\xcc\xd7\x96\xf3\x52\x80\x01\x01\x00\x98\x23\x46\x37\x10\x40\x19\xb6\x92\x9d\xaa\x38\x20\x67\x5c\xb6\xe2\x74\xc3\xcd\xe7\x64\x93\x27\x91\x40\xa5\x34\x3c\x37\xc6\x11\x4f\x55\x6c\xed\x54\x10\x46\xb4\xd9\x4d\x31\x19\x38\x08\xf0\x4e\x74\x10\xe6\x04\x23\xa5\x52\xcb\x6b\xd9\x3e\x7c\xe2\x05\x7a\xed\x3d\x78\xe2\x49\x62\x1d\xbb\x2b\x63\xb0\x13\xbb\xd8\x5c\x19\x93\x8d\x97\x62\x19\xab\x4d\x9d\xe1\x72\xe0\x7f\xc8\x78\xf0\x33\x6d\xb0\xeb\x8c\x05\x90\xa1\x11\x66\x71\x9a\xe2\x29\x1c\x59\x36\x91\x44\x19\x32\x6f\x14\x44\x64\x49\x01\x92\xdc\xa9\x0c\xa8\x74\x74\x86\xee\x3f\x89\x04\x48\xc3\xb4\xe6\x7e\xe0\xae\x85\xe7\x35\x2f\xcd\x3e\xfb\x76\xe8\xed\xd5\xd9\xd5\xd1\x79\x2b\x1f\x6f\x3b\xdf\x14\x89\x46\xa3\x6c\x6c\xce\x8a\x3a\xa6\xe9\xd4\x7f\x6f\xeb\xd9\xc3\x4c\xbf\xe9\xba\x51\x55\x42\x65\x63\x3d\x80\xc0\xa1\xb8\x99\x56\x62\xa7\x36\x80\xad\x63\xe6\x73\x64\xb0\x29\xbf\x01\xf1\xd5\xaf\x9e\x29\x78\x07\xca\xac\xb6\xb1\x10\x47\x53\xca\x7e\x36\x98\x6f\x48\x2b\x2c\x9e\x47\x70\x78\xe0\xf4\xac\xb2\x1b\x6f\xb1\xf2\xeb\x63\x77\xdc\x71\xaa\xf5\x7a\xe3\xe2\x93\x77\x5f\x9c\xe8\x08\xdc\xeb\xf0\xad\xa4\x7e\xdd\xaa\xb8\xb9\x0f\xc9\x7c\xfd\xb3\xea\x7d\x12\xa4\x27\xa0\x5c\xc6\xe7\x90\x3d\x8e\xc3\x70\x8d\xe2\xad\x9c\x7c\xbf\xa0\x85\xa8\xc2\xea\x28\xde\x3c\x6a\xdb\x26\x54\x7c\xa5\xa0\xa0\x2b\xc3\x06\x19\x29\x96\x29\xc3\x4f\x56\x66\xcb\xe8\xf9\x16\x24\x77\xa7\x2b\x95\x22\x4d\x9e\x8c\x5d\x2c\x21\x6a\x01\x1e\x01\x19\x09\x75\x51\x20\x05\x64\xd1\xae\xe7\xb4\x29\x13\xd3\x46\x33\x11\xb4\x63\x05\x02\xaa\x22\x6c\x77\x3c\xcc\x93\x00\x36\x17\xd2\x68\x18\x66\x5b\xe1\xc4\xec\x4c\x16\x04\x14\x61\xff\x9b\x1b\x94\x9e\x03\x3f\xb9\xf3\x81\x17\x33\xef\x3e\xfd\xe4\xc4\x00\xfc\x55\xcf\xfb\x3f\x32\xba\x95\x96\x35\x0a\xb0\xff\xe7\x73\x8f\x9e\x5c\x37\x7e\xdf\x94\x9f\xcb\x1b\x36\xad\x80\x7f\x3d\x75\x29\x8e\xd7\x4e\x1f\x37\xbe\xc5\xb5\x81\x7a\xb0\x99\x32\x70\x51\x95\xc8\xca\x24\x4e\x43\x90\x27\x41\x6d\xe3\x2c\x4d\x0e\xcc\x65\xac\xd2\xef\xe2\xa0\x2d\x08\x63\x72\x99\x9d\xa4\xa0\xa5\x30\x26\x07\x2c\x3a\xe2\x62\x4b\x2d\x65\xc3\xc2\x19\x28\x72\x89\x69\xc9\x53\x89\x2f\xc6\xb2\x60\x1e\x47\xcc\x5a\x04\x31\x0b\xca\x43\xd1\x6a\x12\xab\xb7\xea\x78\x9c\x28\xdd\x6c\x3f\xcc\xb3\x35\xa4\x95\xb7\xc8\xbb\xf1\xf0\x16\xf7\xd8\x09\x97\xee\x58\x5a\x7e\x63\x76\x9b\xb8\xf6\xbb\x3b\x6f\xad\x98\x7d\xe8\x8f\x5b\xbd\x96\xa9\x07\xa6\x2d\x5a\x61\x33\x3d\xf5\xf3\x3b\xef\xfd\x7a\xdc\xcd\xcc\xae\x9e\xcb\xe6\xd6\x8e\xbc\x68\xf1\x87\x9b\xe1\xe7\x3d\x97\xb5\xd7\x6f\x5a\xfa\xe9\x4e\x42\x40\xbb\xfc\xba\xd5\x8b\xbf\xb8\x0f\xa8\x31\x2c\xb1\xc9\x20\xf0\x1f\x20\x5d\x8f\xcd\x51\x55\x64\x8e\xb4\xb3\x34\x90\x4c\x26\xf1\x4e\x2e\x4b\x6a\xe1\xc6\x59\xcd\x22\x14\x99\x45\x0b\x47\x36\x9d\x58\x49\xf7\xf7\x9e\x13\xef\x92\xfd\x1d\x74\x65\x4a\x82\xa5\x52\x2c\x53\x8e\x9f\xe9\xf2\x60\xa9\xee\xcc\x2b\x49\x01\xb9\xa4\x1c\x5f\x42\xf8\x59\x08\x6b\x2d\xf5\xd4\xb6\x35\xb5\x9a\x6d\xab\xf2\xb6\xad\x08\x17\x6c\x5b\x11\xae\xa9\x3d\xab\x6d\x75\x61\xef\x00\xd6\xbd\x7c\xc7\xb2\xf0\xec\x43\xca\xc1\xf4\x4c\x1c\x06\x9f\xc5\xc0\xcb\x7e\xb7\x13\xbe\x47\xe3\x62\x9d\x8d\x53\x8a\xdb\xb8\x91\x6b\x07\x43\xf2\x3a\xc4\x75\xf5\x7a\xb5\x66\xe4\x48\xca\x71\x3e\x87\xaa\x08\xad\x52\x19\x9f\x67\x98\x19\x62\xc9\xa1\x21\x45\x50\xd1\x7a\x18\xd3\x00\xa4\x61\x55\x33\xbd\x45\xb5\xee\x23\x27\x5e\xa7\x17\x64\xbd\x0b\xc5\xba\x51\x9d\x0b\xd5\x76\xbf\x34\xf2\x37\x7f\x2b\x23\xfb\x95\xe2\x47\xdd\xae\x93\x48\xea\x06\x87\x24\x77\x79\xa8\x96\x46\x74\x8d\xb0\xe8\x6f\xbd\x38\x03\xeb\xea\x05\x51\x36\xc5\x09\x18\x25\x6d\x75\x94\x90\xbc\xac\x0c\x67\xd5\x25\x64\xff\x96\xa6\x50\x5c\xcc\xb2\x9c\xd5\x26\x14\x5a\xb6\x04\x8b\xe5\x53\x3b\xb7\xbd\xa3\x3d\x15\x43\xaa\x0f\x9c\xb1\xeb\x8e\x9b\xb5\x64\x1c\x36\xed\xfe\xf7\xef\xbc\xd7\x8b\xaa\xf6\xde\x3b\x66\xc4\xf9\xad\x2b\xea\x33\x22\x7d\x15\x37\x64\xb7\x88\x6b\xaf\xd8\xb9\xb4\x62\x36\xd7\x76\x74\xea\x15\xc9\xd5\x1d\x7f\xbb\x6f\xcd\x94\x69\xa7\xde\x7c\xe6\x31\x1a\xfb\xb5\x37\x8d\x6c\xeb\xf8\x70\x93\xe2\x62\x50\x7b\xdd\x66\x02\x24\x25\x71\x46\x1c\xc7\xd4\x5c\x3b\x88\x82\x97\x69\x97\x05\x49\x49\xd2\xa2\xa6\x55\xfc\x52\x5a\x4a\x62\x4c\x39\x19\xe0\x70\xba\x3a\x8e\x8c\xc7\x28\xf8\x90\x76\x96\x5c\x96\x5c\x46\x72\xf9\x28\xcb\x1e\x8e\x10\x25\x4b\x4e\xae\x51\x4d\xbe\xfd\xc4\x1e\x6a\x72\x02\x17\x97\xcb\x5d\x27\x51\xa8\x3b\x0f\xda\x45\x6e\x32\xa6\x4c\xc7\xf0\xb3\x06\xd1\x43\x91\xba\xf8\x72\xca\xff\x4c\x21\x57\x46\x6c\x64\x73\x2a\x25\xfb\xdc\x82\x28\xdb\x4b\xb1\x91\x4b\x2b\x05\x9c\x09\xbb\x52\xf9\xa1\x8d\x56\x38\x90\x74\x36\xf5\xdf\xf7\x1b\x46\xd6\x0f\x75\xc0\x92\xfe\xd4\xb3\x37\x85\xd7\x2d\x89\x8c\x15\x94\xb7\x3c\x2d\xa3\x0d\x91\x7e\x14\xb4\x7b\xa6\x3e\x72\x97\x68\x06\x85\x3c\x84\xd4\xc3\xd7\xe9\x54\x00\x68\xab\xb6\x92\xcf\x11\xee\xaf\x42\xa1\xbf\xc6\x42\x72\x7a\x9d\x93\x96\x16\x4e\x83\x10\x05\x75\x92\xfa\x7f\xc1\xab\x5c\xa5\x78\xc1\x95\xa4\x8c\x4a\xb8\x98\x45\x1f\x91\xcf\x44\x40\xc8\x38\xdc\xa5\x65\x44\x5d\x97\xb8\x95\x3d\xd8\xcb\xad\xf0\xd2\x8b\x9a\x95\x7a\xa7\xd2\x63\x91\x9f\xa7\x2d\xca\xc5\x1d\x0e\xa4\xc1\x90\x0b\xd8\xe3\x53\x1f\x8c\xae\x9a\xe9\x5d\x1f\x5e\xb2\x60\xcc\x08\x76\x58\x1e\x7a\xac\xe6\xb1\xfb\xb9\x36\x60\x07\xab\xd4\xbd\x6a\xb2\xab\x7b\x95\x44\x7d\x0e\xb2\x66\xbb\x93\x34\x23\x49\x00\xe3\x2c\x40\x9c\xf6\x9e\xf8\x48\x2f\x40\x6f\x77\x21\x4b\x77\xc6\x66\xb7\x48\xb1\xb4\xcd\x6e\xd1\x53\xbd\x59\x6c\x8d\x8d\x30\x0d\xf1\x1f\x6a\x4d\xc7\xae\x22\x8d\xc9\x34\x19\x4b\xd7\x0c\x09\x04\x35\x02\x8d\x3c\x9b\xfa\xc3\xfb\x70\x6a\xd0\xb2\xee\xe0\xef\xdf\x53\xf6\x97\xfa\x57\x73\x6d\xa7\xee\xfb\x71\x13\xb3\xe2\x9b\x2e\xb6\xe3\xd9\x19\x3d\x3b\xf3\x5c\x1f\xdc\x14\xa2\xf9\x53\x0e\xae\xea\xcd\xf5\x51\xc6\xe7\xb2\x3e\x8f\x95\xb3\x93\xaa\xb8\x56\x65\x53\x49\x20\xfc\x2a\xf3\x43\x05\xe9\xb6\x13\x25\x17\xb7\xaf\x8c\xea\xb7\x0b\xb4\x92\x48\xb6\x3d\x3f\x00\xe1\x43\x6b\xd8\xd8\x1a\xa6\xad\x38\x4a\xf2\xb0\xf5\xcb\x9d\xdd\xbf\x3c\xbc\x62\x71\x47\xa6\xba\xe7\x1d\x63\x25\x13\x63\x16\x2f\xb8\x15\x51\x72\x87\xff\x7c\xf5\x07\xca\xfe\xc3\xbf\x7d\x71\xd5\x7d\xaf\x3e\x55\x96\x1d\xbf\x72\x35\x52\xeb\xf7\x9f\x1b\x97\x71\x53\x80\x0f\x44\xc1\x74\x15\xa1\xe1\xe4\x73\x14\xf4\x1d\xd0\x86\xac\x2d\xda\x7a\x2a\xf9\x5c\xd6\xea\xf0\x70\x1a\xcf\x32\xe5\x88\xf7\xd3\xfd\x09\x64\xa7\x48\x05\x04\x1d\x82\x0c\xfc\xa9\x94\x6c\xb1\x92\x8a\x2f\xe2\xd5\x31\x3d\x55\xff\x56\x27\x51\xdd\xda\xcf\xa4\xcc\xb6\x7f\xec\x7c\x67\x76\x88\xd9\x1b\x52\x8c\xa3\xe0\x27\x61\x25\xda\x06\xbf\x0e\xf5\x5c\xeb\xbe\x6d\x33\xa1\xb0\xb8\x6e\xef\xd5\x1d\xf3\xe7\x1d\x98\x46\xd7\xb5\xeb\xfe\xed\xca\x07\x0f\x28\x4f\x6c\x9f\xb9\xf8\xb7\x2f\xdf\x79\xef\x66\x68\x78\x62\xe9\xfd\xdb\x94\x6f\x48\x9d\xec\xb8\x61\x07\xc1\xc5\xc4\xc0\x63\x74\x6d\xc8\x96\xc4\x2f\x02\x55\x26\xd2\x3e\xc2\x9a\xed\x0b\x98\x63\x79\x4a\x9e\x5a\x3e\xdf\xe8\xf6\x58\x88\xb4\x4a\x00\xdf\xac\x4e\x72\xb3\xe2\x44\xdf\x24\x15\x58\x3f\x37\x9f\x58\x43\x0f\xa2\x80\x0b\x95\x76\xa3\x32\x17\x0a\x76\x03\xb9\x34\x88\x6f\x4f\xfc\x24\x2e\x16\xf0\x08\xa2\xec\x10\x49\xb1\x23\xcd\x85\x6a\x89\x86\xb0\x28\xdb\x2a\xb5\x0e\x79\x06\x98\x9c\x79\x22\xba\xaa\x64\x82\x10\x49\x1a\x23\x95\x35\xba\x76\xb8\x8e\x6e\x92\x98\x88\x63\xa6\xbd\x09\x6f\x38\xbe\xef\xab\xb5\x4b\x7f\x76\xef\xaf\xcb\xcd\x4d\x5b\xe6\x6d\xdd\x9b\xdd\x3e\x6d\x69\xe9\x79\x07\x5b\xed\x97\x8e\xb9\x7b\xdb\x8f\xbb\x9e\x53\x3e\xdf\x0a\xdb\x7f\x09\xa7\xbf\x79\xd7\x5f\x1f\x39\xa0\xfc\xf7\x8e\x17\xae\xbe\xe6\x07\x07\x3e\xda\xb4\x02\xda\x95\x2f\x5a\x86\x5e\x7e\xf1\x97\x9f\xca\x6f\xee\x52\x7e\xab\xe2\x99\x0d\x0c\xc1\x13\x04\x40\x04\xbc\x45\xbb\x38\xf8\x82\xc4\x96\x2a\x4b\x10\x17\x40\x5c\x52\x8e\x10\x5d\x6f\xe4\x8a\x23\x67\x52\xcb\xc8\x68\x51\xc9\x2d\x91\x96\x8e\x0b\xc6\x64\xa7\x23\x87\x9c\x6a\x3a\xe6\xc8\x21\x23\xe5\x3a\xb1\xe8\x2a\x4b\x3b\x4f\x20\x95\x2d\x3d\xc3\xb9\x0c\xb4\xed\xc1\x3b\x8d\xa4\xed\x61\x94\x54\x41\x33\x83\x14\xcb\xf8\xc8\xd3\xaf\xfd\x4e\x19\xf9\x9d\x08\x7e\xb2\x87\x39\xde\x21\xf8\xfc\x65\x91\x22\x98\x0e\xd1\x5c\xb0\x00\x95\x20\xa5\x0a\xdb\x8d\x12\x73\xe2\xa3\xbb\x11\xb6\xba\xbd\x3e\xc9\xc1\x40\x02\xb4\xaa\x99\xb9\x13\x96\xbf\xdc\xbe\xaf\xfd\xd5\x9f\x3c\xaa\xfc\xea\xf0\xec\x7d\xb3\x5f\x79\xfb\xc5\x95\x37\xa1\x3b\x5e\x9a\x05\x3b\x57\xbd\x3c\x7b\xf9\x62\x78\xe4\x05\x38\xe8\x79\x23\x7c\x49\x19\x5f\xf2\xe7\xb7\x5e\x52\x8e\x1e\x64\x94\x2a\xf8\x9f\xfe\xcf\xdf\xdb\x78\xc0\xcc\x9e\xcf\xaf\xfb\x9d\x92\x34\xae\xff\xfd\x86\x7b\x9f\xb4\xd2\xd9\x9f\xd7\x4e\x1f\x67\xfe\x46\xea\x01\x13\xd4\xea\x07\x48\xd2\x81\x33\x96\xa5\x1b\x89\xe4\x24\x96\x63\xb2\xd9\x4e\xea\x1c\x1a\xd8\x46\xca\xe3\xb1\x48\x2e\xc2\xb3\xea\x8f\x83\x9b\xf8\x56\x6f\x32\x21\x6a\x01\x29\x13\xa9\x1c\x53\xd3\x3c\xe4\xde\x8f\xaa\xe7\x1d\xa2\xf2\x2b\x37\x8c\x1c\x6f\xdc\x6b\x87\xa6\x57\xe1\x97\xdf\x74\x1d\x9d\x7e\x45\x83\xfa\x3d\xd8\xc9\x24\x1f\x9a\x47\xbf\x87\x0c\xcc\xc9\xc2\x37\x41\x7c\x1c\x99\x92\x03\x7f\x15\xf2\x92\x5e\xff\x62\xa6\x8e\xe1\x04\x20\x63\x23\x44\x46\xea\xd3\x67\xf9\xa6\xb0\xf8\x9b\xbe\x93\x55\xb2\xc5\x5f\x95\xed\x3e\x79\x9c\x7e\x55\xfc\x5d\x15\x37\xb1\x59\x05\x8e\x15\x42\x7a\x5b\x21\x53\x32\x8f\x03\x0c\xc7\x91\xe7\x98\x6c\x15\x08\x31\x81\xf6\x55\x2b\xfb\xf9\xaa\x3e\x95\x8c\x05\xf9\x5c\x19\xa3\x0f\x27\xaf\x7e\xfc\x4c\xfb\x7d\x7c\x11\xc5\x35\xc8\x18\xcd\x3e\x3f\x2d\x62\x68\x3f\x91\xc5\x59\xf1\x86\x2d\x0d\x10\x3a\x70\xd9\x2e\x12\x62\x5d\x92\x5b\x15\x40\x88\x21\x81\x16\x2a\xc9\xe2\xf1\xaf\xea\x17\x5f\x74\x4f\x92\xf9\xf5\xa2\xb7\xa6\x7c\xe5\xd4\xc6\xb5\x83\xb6\x86\x5e\x2f\x30\x32\xbc\x86\x0e\xee\x8c\x1b\x7c\xd7\xf0\xc7\xb1\x85\xe0\xe9\xf7\x15\x37\x99\x45\x16\xc1\x7c\xd0\xbf\x30\x10\x88\x23\x31\x09\x91\xd4\x4b\x09\x08\x07\x06\xb2\xbb\x37\xc2\x43\x24\x5a\x25\x48\x68\x84\x48\xe8\x15\x77\x16\x89\xff\xb0\xb0\xb7\xf8\x4f\x1c\x5e\xd1\x5b\xf0\xe7\x03\xc5\x6d\x6c\x29\xc8\xfc\x9c\x2a\x07\x10\xd8\xd4\xef\x1b\x02\x33\x81\x9a\xdb\x69\x33\x0b\x4e\x36\x87\xec\x14\x9a\xc1\xe7\x34\xe9\xa2\x5e\xb3\xd2\x38\xc0\x66\xbd\x1a\x98\x82\x13\x32\x06\x63\x69\x80\x6a\x9b\x05\xa9\xf6\x80\x53\xc8\x00\xa3\xa1\x54\x3d\x32\x5b\xfb\x7c\x4f\xdd\x0b\xb0\x39\xa1\xa9\xf7\x77\x5e\xef\x98\x3a\x3a\xde\x32\x6b\xd1\x12\xe5\xcb\xd4\xf9\xdc\x27\x85\x6f\xdf\xb3\x4c\x0d\x4f\x68\x3c\xd6\x00\x00\xf3\x3b\xae\x1d\xd8\xc1\xd5\x6a\x1e\x6f\x4f\xd2\x4b\x82\x08\x97\xa9\x21\x89\x0e\x6a\xbd\xfb\xc4\x9b\xfa\xba\xaf\x9d\xd2\x63\x40\x42\x8f\x01\x6d\x5a\x9b\xcc\x02\xc8\x7d\x8e\x38\x7a\x21\x26\xa5\x82\xe2\x07\xcf\x36\x3c\x11\x7d\xe6\xb1\x49\xdf\xa9\xf3\x8d\x4e\xde\x55\xfb\x04\x6b\x4a\x3f\x11\x7e\xd0\xe4\x79\xf5\xd4\xd7\x00\x82\x2b\x14\x37\x13\xe2\xda\x81\x0b\xdc\x0a\xa8\x39\x0d\xa6\x1c\x32\xa8\x98\x48\x13\x36\xa8\x40\xbe\x93\x1a\x04\xb2\x94\xb8\x3c\x2f\xf8\xa8\x86\xcd\x1c\x02\x8d\x0e\x04\xbb\x39\xd9\xe5\x3a\xe9\x40\xce\x6e\x90\x01\x90\xe2\x77\xa0\x0c\x9d\xea\x26\x70\x01\x41\x4c\x1b\x78\x93\x5a\x20\xb0\x90\x82\x29\xa5\x28\xd7\x46\x11\x79\x78\x05\x74\x58\xe6\x8e\x9b\x34\x79\xc6\xaa\x55\x56\xe5\x6f\x8a\x9b\xfb\x4b\xa2\x72\x41\xf0\xa1\xd0\xea\x9b\x2f\x68\xfc\xa6\x54\xe3\xba\xaf\x23\x71\x9d\x17\xdc\xa7\xe9\xf4\x6a\x91\x9d\xec\xe5\x73\x59\x9b\x83\xb0\x9a\x92\x31\x0f\x9f\x66\x52\x1c\xe5\x89\x30\x26\x1b\x2c\x85\xc2\xaf\x2a\xdf\x59\x30\xae\x17\x07\x79\x5e\x7c\x67\xe0\x27\x9b\x81\x36\x87\xc6\xe0\x4b\x6a\x1d\x14\x2d\x60\xa0\x68\x01\x87\x8d\xb6\x24\xbd\x6a\xb1\x43\x03\x6c\x52\xd5\x78\xad\xd2\x91\xfa\x23\x4c\x3f\x96\x79\x6c\xdb\x8f\x5e\xcb\x9e\x06\xd3\x96\xff\xe5\xbe\x6d\x33\xe6\x7c\xc9\xb5\x6d\x5f\xb3\xee\x85\xa8\x92\x84\x59\x65\x22\xd3\x76\xd3\x8d\xe3\x2e\xc9\xf3\xf8\xef\xe5\xda\x80\x03\x78\x35\x06\x66\x12\x37\x91\xa5\x31\x86\x64\x32\xcb\x7a\xc9\xda\x58\x75\x6d\xf0\x98\x56\xde\x91\xd4\xfb\xd0\x9f\x47\xdc\x3c\x4d\xd6\x06\x5d\x08\x74\x23\xc6\x85\x9c\xdd\xf8\xba\x63\x9d\x8c\x14\xcb\x78\x9d\x44\xb3\x00\xb0\xce\xfc\xf2\x24\x46\x10\x65\x8e\x4f\xa5\x90\x05\xaf\x07\xc8\x5e\x27\x29\xb0\xe1\x57\xc5\xd3\x20\x96\x4d\xc2\x24\x29\xe6\x38\x60\x24\x4a\xc0\xa8\x78\x79\x5d\xd3\x3f\x82\x4b\x3e\x55\xe6\x4d\xbd\x61\xee\x1b\x6b\x95\x3f\x43\xe7\xb2\x75\x1f\xfc\x85\x6b\x53\x26\xc2\xac\x92\x2c\xbd\x67\xce\xc2\xe7\xae\xda\xbe\x74\xf6\x26\x72\x2e\x1f\x54\xf1\xeb\x49\xf0\xb9\x3a\x9f\x63\xe4\x73\xe9\x1a\x9c\x98\x88\x3a\xf6\xc2\x41\x3c\x9d\x63\x01\xc7\x10\x4c\xc8\xf5\x42\x4e\xae\xad\x4b\x24\x50\x3d\x2d\x4f\xa8\xea\x05\x66\x18\x93\x2b\x2d\x64\xca\x85\x2c\xf8\xf0\x17\xc3\xa9\x2f\xc2\x46\x07\x62\xbb\x39\xb9\xce\x79\xd2\x80\x6a\xba\x5f\x1a\xb9\xff\xc4\xdf\x49\x91\x02\xba\x32\x0c\x64\xa5\x18\x87\xea\x5c\x99\xda\xba\x1a\x29\x96\x66\x20\xab\x0b\xe6\xb3\x2c\x64\x6a\x29\x4a\x17\xa6\xd9\x1a\x46\x3b\xbe\x03\x4e\x41\x3c\x64\x37\x46\x07\x35\x26\x70\x42\x63\x16\x32\x36\x91\x88\x23\xa2\x4a\xca\xa1\x36\x28\x21\x88\x28\x4e\xc8\xd5\x40\x63\xea\xff\x21\xef\xdd\xc3\x9b\xaa\xd2\xfd\xf1\xb5\xf6\x35\xf7\x64\xe7\xda\x36\x6d\xd3\x34\xb4\xa5\x84\x36\x34\xbb\x69\x1a\xa0\x94\x56\x2e\xa5\x22\x62\x45\x6e\x32\xc8\xa5\xdc\x2f\x82\x88\x80\x88\x88\x80\x15\x51\x11\x50\xbc\x8e\x17\x64\x00\x19\x87\xd9\x3b\x09\xa0\x0c\x7a\x8a\x0e\x32\xea\xf1\xeb\xf1\x38\x03\xd3\xe3\x71\x18\xf5\x38\x9a\x19\xcf\x3c\x0e\x7a\x1c\x41\xb2\xf3\x7b\xd6\x5a\x7b\x27\x69\xb9\x8c\xce\xcc\xf9\xfe\xfe\xf8\xf2\x3c\xa4\xd9\x3b\xc9\xda\x6b\xbd\x6b\xad\x77\xbd\xd7\xcf\x1b\x93\x0b\x38\xc1\x1e\xb7\x62\x53\x91\x64\x17\x48\x9d\x8c\xfa\x06\xc7\xdf\x2e\x46\x53\x65\x81\x39\xdb\x60\x87\xa1\xe3\xf2\x15\x69\xa6\x4c\xaa\xe2\x66\xc6\xea\x3c\xd7\xd5\x7c\xae\x7c\x5b\x31\x12\xae\xbc\x42\x59\x1a\xe7\xab\xd5\xe6\x4e\xf7\x16\x8b\x03\x90\x98\x13\xda\xc2\xf9\x80\x1b\xcc\x02\x48\x0d\xa6\x88\x05\x51\xc7\xf7\x86\xbc\x7e\xee\xec\xaf\xf3\x92\x4b\x65\xa1\xf0\x9c\x64\xeb\x06\x09\x86\xb5\x11\x90\x83\xec\x3b\x15\x7c\xc8\x29\xd8\x25\x37\xce\x4a\x02\xc6\x58\x36\x54\x97\x80\x10\x61\x76\xe4\xc2\x06\x6b\x0d\x8e\x68\x68\x64\x43\x1d\x74\x0f\x7c\x6e\x73\x5b\xd3\xf0\x41\x23\x27\x15\x2a\x5f\x54\xef\xed\x1a\x3d\x58\x39\xee\x49\xb1\xfe\x93\x7b\x3c\x8f\xb8\x6f\x5b\x71\xfe\xcc\xbf\xbc\xe8\x02\xf9\x7d\x2e\x05\xcf\x02\xa9\x38\x17\x1f\x53\xa0\xc5\xc7\xb8\xc2\x61\x49\x08\x91\x2d\xef\x0b\x65\x83\x0d\xf2\x07\xa1\xef\x96\x0b\x0b\xcf\x49\xce\x8b\x03\x64\x0a\x6d\x09\x57\xa1\x13\x9d\xea\xe8\x95\x06\x09\x46\xef\xc4\x41\x08\xf0\x08\xc3\xea\xf4\x5a\x48\x42\x2e\x50\xa6\x98\xf8\xc9\x70\xa0\x8c\x2c\x90\x08\x2b\xc9\x24\xe0\x10\xeb\x5c\xd8\x4c\xde\xa8\xf3\x03\x68\xd0\xc8\x37\x6e\x2d\xbd\xff\xd6\xdc\xe0\x97\x6d\x2f\xdd\xb1\x39\x3b\x7e\x6a\xc1\x76\xaa\x4a\x25\x41\xfa\xbf\xb7\xa7\x37\x22\x2a\x40\xe0\x51\x9c\xf0\x00\x33\x1d\x94\x80\x5d\x20\x6e\x42\xbb\x85\x27\xbe\x44\x1c\xaa\x87\xad\xbe\x12\x15\xc6\xc6\x0d\x7b\x18\xc9\xcd\x48\x58\xb6\x1a\xf2\xe1\x9c\x7f\x4a\x36\x08\xa5\x6e\x10\x5c\xa9\x47\xc0\xae\x17\xc1\x4e\x98\x35\xad\x15\x1a\x73\x22\x66\xcd\xeb\x4d\xb1\x58\x4c\xb6\xb2\x82\x3d\xee\x2e\x20\xa5\xb5\xdc\x5e\x62\x32\xe2\x85\x04\xd0\x5b\x0b\xd0\x26\x30\x91\xb9\x76\xd4\xab\x4e\xc0\x2c\x37\xcf\x3f\x36\x3d\x96\xd7\xac\x53\x87\xd7\x35\x74\x2e\xbf\xd5\xf2\xba\xa6\xd1\x2b\xdf\x8c\x18\x42\x6f\x1b\xda\x7f\xb6\x67\x8b\xff\x96\x9b\xaf\x1a\x7a\x61\xc5\x88\x00\x39\x2e\x29\x65\xb9\x3a\xe7\x85\xc0\x8f\xf8\x3c\x8d\xa3\xdf\x04\x51\xc4\xbe\x53\x87\x66\x60\xcb\x2e\x5d\x52\xd5\xb1\xc8\x9a\x92\x8a\x88\xb1\xc2\xe9\x48\x65\x0b\x37\x6a\x49\x52\x4c\xad\x45\x62\xbb\x59\xb4\x9a\x2d\x68\x39\x93\x74\xd3\x5e\x4b\x19\xc7\xd9\x4a\xf9\xc1\xaa\x66\x5a\xb0\xe3\xe8\x73\x12\xc4\x09\xeb\x1b\x86\x40\xd8\x67\x72\xf3\xd4\xaa\x40\xb9\xb2\xfc\xe5\x17\x3a\x21\xc8\xcd\xef\xb9\x27\xfd\x8f\xf7\x7f\xfe\x81\x35\xdb\x5e\x9c\x3e\x7c\xa4\x67\xca\x73\xca\xd7\x9b\xee\x65\x92\xea\x14\x7f\x37\x63\xa7\xbc\x7f\xcd\x92\x8e\x69\x0b\x08\xe6\xcc\xa7\x00\x50\x2b\xd9\xc9\xa0\x08\x78\xc1\x06\x82\x39\x83\x21\x0e\xd9\x94\x4c\x39\xc3\x61\x49\x87\x8b\x55\x43\xa9\x18\xc3\x84\x09\x86\x54\x36\xcf\xfa\xc9\xb3\x18\x3f\x50\x9d\x5f\x56\x76\x6a\x95\x98\x68\x07\x71\xab\x39\x72\x0e\x27\x81\x55\x47\x09\x0a\xf1\x1b\x09\x0a\x68\xfb\xea\xec\x71\x83\x80\x21\x6b\x2c\x04\x40\xa2\x2a\xea\x57\xcd\x32\xd9\xb8\x5c\x9e\x16\xad\x54\x20\x4a\x7b\x4b\xa0\x7d\xbd\x63\xb0\x18\x9d\x5a\x36\xaf\xe2\xee\x4d\xf6\x75\x07\x84\x97\xd6\x2f\x8c\x96\x9e\xdf\x42\x4d\x1c\x1b\x6a\x8c\x79\xb7\xd8\x5c\x6b\x57\xb6\x8c\x4f\xbf\xd8\x31\xee\x93\xf3\x74\xa7\xea\x53\x21\x18\x70\x1b\xc0\x65\x30\xdf\xa4\x02\xd5\x26\xe5\xcd\x86\x0e\x69\xc1\x14\xef\x7c\xf5\xb3\xde\x78\x6f\xb6\xcb\xe3\xbd\x59\x81\x5a\x24\x1d\xc8\xf6\x02\x62\x92\x32\x09\x32\x70\x92\xb2\x0b\x2c\x71\xc5\xe4\x10\xdf\x7a\x55\x96\xb2\x38\x3e\xc9\xc3\x78\xfb\xd4\xde\xd0\xd0\x74\x43\xe1\xc2\x01\x77\x6f\xba\x30\x62\x1c\x13\xc4\xc0\x6e\xdf\xfd\xfb\x75\xd5\x91\xa1\xde\xfb\xcc\x05\x77\xa0\x73\xdb\x96\xf9\x82\x79\x8a\x69\x07\x85\xa0\x1c\x16\x93\x3c\x47\xec\x7e\x44\x2b\x94\x18\xdf\xb3\xe0\x09\x0e\xda\x1c\x8c\x1b\x0b\xcb\x44\xe2\xaf\xee\x85\x9d\xe0\x3e\x25\x79\xc2\x72\x91\x21\x95\xa0\x8b\xdc\xaa\x4d\xbe\x48\x2d\x17\x63\xc6\x12\x0c\xd6\x52\x84\x1c\x90\xc2\xe6\xb3\xd7\x91\x3d\x4d\x23\x2d\x05\xf3\x39\x7f\x77\xb6\x26\x17\x9b\x8f\x24\x89\x94\x17\xca\x43\x3b\x82\x92\xdf\x96\x60\xfd\x8c\x23\x78\x74\xd8\x0b\x67\xff\x8a\x4f\x46\x8f\x2d\x51\x80\x3e\x62\x13\x85\xda\x37\xca\xd0\x37\xe2\x05\x9e\xfc\xf3\x31\xee\xc7\x3a\x0d\x3c\x82\x3a\x5d\x58\xe6\x2f\xc8\x63\x8b\xaa\x4d\xdf\x51\xac\xd6\xa7\x89\x5b\x6d\x3e\xcc\x30\x40\x31\xbe\x70\xc7\x62\x7d\x51\x14\xb2\xee\x90\x48\x7d\x43\xd4\x83\x37\x8f\x9f\xe7\x6c\xbe\x2d\x37\x1d\x9e\x0e\x53\xd3\xe2\xd3\x76\xf8\xb6\xdf\xac\x55\xe2\xb3\x15\x3e\xb0\xed\x96\x7f\x6b\x52\xbc\x1e\x3b\xc5\xed\x80\x71\x65\x1c\xfa\xbf\x23\x7d\xfe\xed\xdb\x16\x6c\xdb\x30\x68\xfe\x2d\xdf\x3e\xf0\x7f\x8e\x2c\x9c\x4a\xe4\xec\x8e\xcc\x97\xcc\x5e\xa6\x1d\xf8\xc0\x3c\xb5\x42\x8b\x49\xb5\x35\x49\x0e\x11\xbb\x35\x5d\xd9\x32\xa7\x6a\x74\x00\x92\x2c\x0a\x1d\x44\x57\xd0\x67\x6b\x99\x5a\x85\x24\xc5\xda\x1d\x5a\x31\x53\x77\x0c\xc8\xb4\x09\x87\x66\x59\x0b\x55\x84\x2a\xce\x4e\x10\xaa\xa2\x01\xd4\x7b\x0a\x2f\x24\x3b\x06\x71\xf7\xf3\x01\xcd\xf0\x52\xd9\xf1\xe9\x2f\x4b\xe1\xc9\x92\x47\x9e\xde\x74\xdb\x0b\xff\x32\x65\x6c\x31\x3c\xe1\xfb\xac\x79\xc4\x96\x0b\x7b\x4f\x9e\x81\x07\xe0\x0d\x87\x76\x3d\x28\x2a\x7f\x7c\xf7\xde\x47\xa1\xfd\xcb\x45\xfb\xcb\x1f\xdc\xd5\xfc\x93\x1f\xbd\xac\xf4\x3c\xff\xdf\x64\x3c\x1b\x33\x5f\x30\x9d\xcc\x74\x50\x06\x12\x6a\xb5\xb6\x6c\x4c\x80\x53\x75\x04\x3a\x74\xa9\xb8\x3b\x0b\xd0\xe2\xbf\xac\x77\x47\x32\x87\x71\x60\x8e\x37\x9c\x55\x75\xbb\xce\x4e\x26\x8b\xc8\x5c\x6b\x91\x4c\xdd\x8c\xec\x45\xec\xb1\xa4\x5b\x2a\xb1\x25\x8a\x4b\xbc\x8e\x60\xbc\xb8\xc4\x9b\x9f\xa0\x6d\x32\x7b\x8b\xc9\x79\x61\x2a\xd6\xf6\x1b\x23\xd8\x13\x7a\x87\x9b\xc4\xdd\x38\xf4\x38\x3f\x05\xd3\x48\x2b\x4d\x89\xcf\x82\x86\x8b\x8e\x08\xca\x5f\x5e\xb9\xd1\xb6\xfe\xd0\x7a\xe1\xf7\x5d\xcf\x56\x0e\x37\x74\xd6\x37\x5d\x3d\x6c\x6d\x97\xa1\x79\x9e\x32\xe1\x17\x6f\xc1\x89\x57\x8d\xa7\x66\xa6\xf7\x8e\x1f\xfa\xe9\xcf\x13\xb0\xa2\xb6\xec\x66\xc7\x13\xce\x3b\x56\xd4\x87\x94\x77\x15\xe1\x28\x96\x29\x77\x02\x40\x8f\xc7\x58\x8a\xf7\xf4\xaa\x77\x41\x6a\xdd\x63\x38\x45\x15\x37\x43\x85\x53\xec\x9e\x70\xae\x2b\x2b\x15\xf0\x5a\x35\x8b\xa3\xdd\xa3\xcf\x9b\xf0\x66\xe0\x6d\x09\x96\x67\x1c\xc1\x04\x87\x5e\xe3\x1c\xcf\xe4\x29\xf9\x6c\x0c\xc4\x59\x8e\x27\x71\x0a\xe4\x8d\x2a\x01\xa9\xc9\xc3\x1a\xde\x46\x2d\x8c\x04\x38\x1e\x2e\xa1\x3a\xbe\x58\x9f\x1c\xa6\xb3\x70\xcb\x63\xca\x31\xa6\xfd\xbb\xc3\xd4\xac\x96\xdf\x0f\xbb\xb0\x20\xbd\x07\xc0\xcc\x5e\x00\xd8\x36\xa6\x1d\x94\x80\x1f\xa9\x7d\x37\x3a\xb5\xbe\xeb\x89\x2f\xd7\x73\x4a\x66\x2c\x38\x4a\x08\xe7\x0f\xda\x52\x92\x19\x57\xb4\x21\x75\x1a\x64\xc6\x23\xd8\x65\xca\x85\x11\x7f\x64\xbd\x13\x07\xac\x63\x68\x50\x88\xb5\x2d\x6b\x61\x4c\x05\x7d\x73\x78\x5c\x62\x33\xc4\x5d\xab\x8f\x06\x2c\x14\x0c\xd0\x55\x91\x68\x80\xe3\xe9\xa9\xf0\x42\x8f\x8f\xd2\x89\xe3\xa1\xef\x37\x35\x92\xc3\xa0\x33\xd6\x46\x94\x5f\xbd\x16\x60\x28\xdd\xb0\x19\x5f\x32\xed\xe9\x83\x0f\x1e\xbb\xfd\x17\xd4\xbc\xef\x0e\x53\x52\xcb\x2f\xca\x56\xac\x4d\xcf\xa2\xc6\x7e\x3b\xa4\xe6\xe8\xe9\xf4\xa7\x84\xfe\xcc\x0a\xce\x07\x3c\xd9\x31\xe0\x90\x39\x7d\x48\x66\x10\x1b\x2f\x20\x59\xbe\xb9\x12\x57\xdd\x0f\xff\x75\xd1\xdf\x4c\xea\x05\x64\x0f\xf2\x8e\x58\x56\xab\x0d\xe4\x9d\xb9\x56\x98\x4f\xe1\x97\xa7\x1c\xdb\x74\x5d\x53\xf3\x88\xeb\x6f\x8b\xb4\xed\x4d\xb6\x19\x6d\xdc\xcc\x66\xe5\x38\xf3\xe5\xde\x2d\xae\xed\xf6\xd9\x33\xd7\x7d\x77\x98\x72\xb6\xff\x65\xd2\xe7\x4b\xd3\x12\x80\x60\x2e\x00\x38\xbe\x53\x07\xa6\xe5\x21\x0d\x23\x8a\xd3\x22\x94\xf4\x04\x60\xd8\x90\x92\x0d\xea\xee\x48\x7e\x55\x73\x11\x9e\x30\x90\x59\x1d\xea\x2e\x7a\x25\x46\x7f\x5e\x45\x7d\x03\x3c\x0e\xe4\xc8\xe1\x06\x3b\xe6\xfe\xcb\x8b\x70\xdd\x7b\xe9\xaf\xa6\xbe\x34\x9d\x69\x57\x6c\xf0\xcb\xf4\x52\xa5\x0d\x9e\xe8\x83\x53\xd5\xa1\xe1\x07\xb2\xa9\x1c\x60\x95\x23\x0b\x58\xa5\x1a\xaa\xb0\x43\xc6\x48\x10\x4c\x81\x6c\x76\x10\xd3\x11\x10\xe2\x46\x8c\x5f\x75\xb9\xaa\x32\x79\xf1\x06\x88\xd5\xf6\xa9\x2b\x63\x55\xd5\x08\x43\x40\xab\x2a\xf3\xf9\xc8\x52\xac\x2e\xfc\x57\xc5\xa8\x1f\x63\x99\xe4\xa3\xcc\x58\xba\x07\xc7\xc4\xfa\xc1\x44\x35\x7b\xdd\x4e\x2a\xe7\x14\xe4\x2a\xe7\x24\x7d\x26\x0f\x63\x0e\xca\x3e\x96\xc8\x63\xc5\xa7\x64\xab\x85\xa4\x37\x59\x8b\x05\xbb\xcc\xe1\xe3\x98\xf7\x10\xb8\x14\x9f\x20\x59\x63\x98\x9b\xf6\xea\xad\xe6\x1c\xe2\x82\x90\xe3\xab\x9a\x73\x99\x7c\xf9\xbd\x7e\x72\xd9\x2d\xb7\x8c\x9a\x79\xfb\xf1\xe4\xc1\xfa\xfa\x35\xcd\xe7\x57\x4d\x9e\x3a\xd0\x27\xce\x52\xbb\xff\xcc\xca\x86\x15\x93\x37\x6c\xbe\x76\x4e\xcb\x8a\xae\xab\xc2\xbe\xe0\x04\x62\x47\x5d\xa3\x38\xe9\x27\xf0\x19\x7d\x15\x20\x2e\x43\x13\xf1\x80\x61\xd0\xd5\x22\x2c\x4d\x39\x48\xa8\x8f\xec\x60\x05\x52\xb9\x9a\x52\x1d\xa4\x26\x21\x0e\x6c\x38\x93\xd2\x8c\x84\xfd\x5e\x65\x0f\x35\xc4\x30\xad\xd2\x61\x5e\x14\x43\xca\x4f\x7d\xee\x55\x6c\xfb\xde\x20\xf1\x0d\x19\xa0\x45\x31\x3c\xb6\x51\x01\xe6\x9e\x83\xcf\x9c\xeb\x1a\x85\xe8\x3b\x4d\xed\x9b\x1f\x04\xc1\x9d\x80\xa4\x5a\x59\xf8\x94\xe4\x0b\x49\x45\x24\xf2\xb6\x5a\x8d\x0d\x27\x7e\x84\x72\x0b\xc6\x86\xe0\xd5\x28\xc1\x1a\x18\x94\xf9\x72\xc1\x7e\x84\x36\x9a\x2c\x56\xbb\xaf\x8a\x04\x6a\x24\xcc\x9e\x22\xe2\xf8\xa9\xf0\x09\x76\xb9\xb0\x18\xe3\x4b\xc9\x1e\x10\x8b\x49\xb4\x3d\xce\xf2\x2e\x22\xe8\xc9\x06\x3b\x29\xbb\x29\xc4\x06\xd5\xf1\x58\x31\xbd\x68\x68\x04\x78\x51\x15\x73\x91\xa8\x84\xa6\x64\xcf\x6b\xfb\xde\x7f\xb4\xb0\xf7\x58\xf7\x9f\x18\xd7\x34\x78\x43\x5d\xf5\xc8\xb7\xd6\xfd\xe4\x95\x3d\x73\xa6\xc7\x17\xde\xf3\xdc\xa4\x99\x9f\x6c\xdc\xbe\xfd\xaa\xb6\xdc\xd0\x3f\x38\xb8\x7b\xdd\xd5\x33\x3b\x3a\xea\x9b\x47\x3f\x70\xf7\x90\xe1\x8b\xef\x6d\x25\xe7\x1c\x00\xf4\xd3\x9c\x0f\xb8\xc0\xea\x6c\xfd\x29\x89\x57\x05\x5e\x77\xbe\x0b\x85\x81\x41\x59\x70\xa6\xb2\x15\xa8\x54\xf3\xbf\x66\x28\x73\xd9\x24\x67\x37\x90\xa1\x13\x5b\xa0\x9c\xea\x2e\x75\x65\x11\xd3\x18\x41\xe6\x2d\x78\x35\xe2\x5b\x42\x4e\xe0\x15\x73\x88\x64\x5a\x36\x0f\xc5\xd3\x1b\x9f\x7e\xf7\x2f\x4b\x26\xb5\x3c\x3c\xe2\xaa\x6b\x5e\xe9\xdc\xfb\xe6\xb9\x8f\xef\xa3\x3e\x6b\xfd\xeb\xd3\x53\x6e\x69\xa8\xed\x8a\x0c\x3b\xf2\xf8\x1b\xca\x7b\xd7\xa5\x57\xe1\x31\x1c\x04\x80\xee\xe1\x7c\xc0\x09\xe6\xa8\x3e\x0f\x1b\xc6\xf6\xc5\xd3\xe7\x22\xe6\x28\x47\x2a\x21\x98\xd1\xb9\x6c\xcb\x03\x3b\x78\xee\xec\xbf\x93\x21\x08\x18\x09\xd4\x66\x93\xac\xdd\x40\xb6\xe2\x78\x60\xab\x3d\x6b\xeb\xd3\xe0\xda\xb5\x6d\xee\xa8\xef\x27\x86\xdd\x9a\x29\xc1\xc6\x62\xa7\xc4\x41\xc8\xfe\x76\xd6\x33\xd7\x4c\x8d\xdc\x7a\xf5\xba\x3d\xd0\xfc\xc4\xe1\x2d\x9b\xee\x64\xc6\x9d\x3e\xdf\xd0\xb2\x21\x18\xfd\xf9\xfd\x19\xb0\x22\x5d\x41\x6d\xbd\xf6\x77\x00\x66\x5e\xcf\x7c\x41\xfd\x19\x63\x7c\x2f\x56\x33\x6d\x68\x5c\x56\x4d\x32\x10\xfb\x2f\x87\x81\xd2\x12\x06\x0b\xa7\x0b\x12\x61\x29\x84\x0d\x4d\xce\xbe\x3a\x76\x5e\xe9\x34\x20\xeb\x8c\xa8\xdb\xe8\x95\x74\x9b\x26\xae\x47\x49\x2f\xc8\xd0\x12\xcb\xa6\x22\x47\x6c\x15\xaa\x3b\x85\x09\x94\x37\x4d\x5d\x75\xc7\xba\x3d\xca\xd7\x4f\x1d\xde\xba\xe9\x4e\x25\xfd\xc1\x1b\xb3\x36\xcc\xfa\xf9\xfd\x20\x73\x2b\xf5\x69\x7a\xd1\xb5\xbf\xdb\xf5\x9b\xef\x10\x7d\xab\x15\x0f\xfd\x1e\x33\x1d\x14\x81\x21\x6a\x74\xbe\x91\x4f\x5d\x5a\x6b\x50\x65\x7f\x37\x4e\xb1\x07\x24\x34\x89\x25\x87\xb4\xa7\xbe\x08\x03\x63\xab\x19\xc4\x42\x5e\x0e\x5a\xf5\xcc\xc4\x5f\x1f\x6d\xdd\x16\x11\xd7\x4c\x7c\xf0\x77\x9b\x96\xdd\xd6\x76\x5b\x64\xe5\xa3\xaf\x1d\xb7\x7c\x0c\x5f\x82\xb1\xc7\x4b\x0a\x76\xd5\xff\x59\xa9\x51\xbe\xfc\xc9\xf3\x03\x8a\x9e\x68\xf9\x3a\x57\x7f\x82\x7d\x07\x63\xf7\x57\x81\x25\x97\xa8\x60\x90\xac\xf0\x19\x19\x73\x30\x59\xa1\x07\x56\x26\xa8\x79\xdc\xf3\xaa\x9a\x94\x1b\x81\x8d\x09\xa2\x5d\xad\x15\x31\xa8\x86\x41\xb9\xbc\x58\xb0\x27\x18\x63\x81\x40\xb6\x31\x9a\x7b\x0b\x88\xc5\xe4\x02\x9f\x0a\xa8\x7b\xe5\xe2\x05\xec\xf7\xac\x90\x13\xb9\x61\x4c\x4d\xb4\x63\x94\x18\xfd\x1b\x45\x0b\xc6\x8d\x9d\x1e\x6d\x68\x9b\xd1\xa8\x62\x46\x33\x85\xcc\x34\x8c\x9d\x54\x0d\x16\xa9\x5e\xde\x02\xcd\xa7\x5b\xc5\xa7\x92\xbe\x32\x3b\x3e\x0f\xb8\x6c\x96\x56\x9e\x03\xd4\x62\x4d\x49\xfd\x90\x28\xc3\x1b\x48\x96\x96\xd7\x25\xd8\x0f\x31\x46\xbb\x41\x2d\xf5\xe9\x2b\x40\x2b\xdd\x12\x8b\x49\x65\x02\xd9\xb5\x55\x59\xaf\x75\xbf\xfc\x4a\xb9\x39\xae\x84\x8f\x0a\x7f\x34\x57\x33\xe9\x21\xa8\x3b\xf8\xf3\xd7\x1e\xec\x5a\x32\x63\xe1\xaf\x1e\x78\xff\xc3\x23\x1b\x37\xae\xdd\xb2\x7e\x8b\xa2\x38\xcf\xec\x93\x67\x4e\xd9\xfe\x06\x94\xde\x80\x43\x7e\x7a\xff\x7d\x37\x6f\x2b\x61\x4a\x56\x4c\x9d\xf9\xf8\xa4\x3f\xfc\x76\xc7\xe3\x0b\x26\x5d\x7b\xcd\x8e\x79\x37\x8d\xbe\x26\x09\x28\xd0\x94\xf9\x82\x31\x61\x5f\x49\x7f\xc4\x95\x7a\x41\x3d\xc8\x25\x7c\x2a\x59\x19\xb0\xe9\xcd\x38\x0f\x1c\x83\x5d\x70\xa7\xe4\x32\x6b\x4a\x2a\x53\xa1\x6f\xd5\x0a\x05\x0e\x03\xae\xff\x88\x06\x6e\x32\x10\xc8\x0b\x6f\x99\x60\x3f\xcc\xe8\x6d\x6e\xba\x1f\xc9\x4a\xab\x74\x93\x3d\x12\x10\x88\xf2\x51\x62\x8f\x9b\xbc\x9c\x1a\xe4\xdf\x10\x8d\x54\x66\xb3\x7d\x73\x35\x01\xa9\x88\xcd\x9f\x97\x4b\xd9\xb4\x6d\xd3\xdb\x5f\xbf\xff\xeb\x2f\x1e\x53\x52\xaf\xec\x7d\xe5\xd0\xb4\x19\xb3\x76\x2f\x6b\x50\xbe\xd8\xf0\xd0\x1d\xf7\x0e\xf6\x86\xb6\xef\x51\x6e\x7e\xb4\x90\xa9\xff\xf9\xee\x97\x3e\xfe\x3f\xaf\x29\x3f\xff\xf9\xf6\x9d\x2d\xed\xe3\x7f\xfc\xeb\x85\xb0\x70\xce\xd4\x71\xd7\x3e\xbc\x08\xe0\x1c\x9f\x3f\xb3\x1c\xe7\x03\x41\x10\x07\xf1\x6a\x40\xa2\xfe\xc9\x46\xf3\xe8\x88\x13\x2d\x19\xe8\x57\xcd\x9a\x71\x15\x9a\x00\x97\x92\xca\xc3\x92\x2d\x24\x1b\x73\xc5\x2e\xbd\x79\x65\x2c\xb5\x7c\x9f\xf2\x5a\x8b\xe4\xef\x66\xe5\x8a\xd2\x73\x16\xa9\xb2\xfb\xe8\xb0\x7d\x67\xbf\x54\x75\xd4\x5a\x8b\xa4\xeb\x96\x9d\x3a\x1c\xd1\x94\xd4\x39\x9c\xfe\x4a\x62\x83\x3d\xc2\xa3\x8b\xf2\x8a\xca\x7c\x3d\x13\xc8\x81\x52\xc1\x2e\x7b\xd1\x36\xf0\xf4\xc3\xaa\xbd\x6c\x63\x05\x02\x70\xa0\xe5\x05\x45\xf3\xed\x33\x7c\x65\xa0\x2c\x57\x59\x31\x97\x24\x74\xed\xd3\xbf\xdf\x36\x79\x52\x5d\xe1\xed\xf3\xae\x0a\xd6\x0f\xa8\xab\x33\x47\xc7\xdf\x79\xbb\x72\xec\x5a\xdb\xca\x5b\x87\xdf\x38\xb8\xf9\x13\x1f\xdc\xb2\x6a\xd2\x9e\x79\xaf\x7f\x00\x9f\xbe\x1d\x3a\xdf\x9a\xef\xfc\xd3\xaa\x15\x9e\x47\xec\x91\xe1\x19\xf0\xc8\x28\xe5\xd6\x09\x57\x6d\x7c\xd8\x6c\x83\x35\xdb\xd3\xa7\x2b\x2a\x3f\x05\x5a\xee\xc4\x76\x1c\x0b\xfd\x6c\x9f\x0a\xc5\xf0\x92\x15\x8a\x79\x52\xa1\xd8\x74\x51\x85\x62\xe1\x72\x15\x8a\xcd\xbd\x1d\x43\x47\x87\x3d\x7c\xf6\x91\x1f\x5e\xa1\x18\x10\x7b\x3e\xd2\xc3\x03\x0e\x3f\x1d\xfb\x63\x7c\x3a\xc5\xcc\x4a\x7e\x76\x78\x6e\xfa\xc2\x7c\xa6\x5d\x89\xc2\x37\xbf\x3b\x0c\xbf\x50\x9c\x80\x56\x76\xa9\x18\x69\x56\x50\x00\x02\xe0\x51\xcd\x12\xc7\x8b\x22\xc6\x9c\xd5\x87\xb3\x00\xf6\x6a\x1c\xaa\x3f\x24\x17\xeb\xb3\x99\x21\x36\x2b\xf6\x1c\x21\xa6\x66\xb0\xa5\x24\x83\x3a\x14\x21\x25\x15\xa2\xed\x51\x6a\xcc\x4f\x0e\x39\x81\x87\x92\x97\x31\x45\x6b\xb9\x52\xb2\xcb\x26\xd8\x25\x33\x89\x90\x4e\xe8\xf4\xc5\x7e\x82\x0f\x63\xd7\xf0\xd0\xea\x1b\x86\x40\x62\x56\xe8\x65\x8b\xe3\xf2\x31\xd1\x76\x1d\x3d\xd0\xf2\x79\x3c\xf5\xa4\xff\xf1\xd0\x83\xeb\x56\xde\xfb\xe2\x84\xc8\x50\x77\xe8\x86\x49\x94\x4d\x43\x45\xfb\x7a\xc3\x56\xa4\xa2\xed\x7c\xf5\xc9\x35\x4b\x3a\xe6\xde\x34\x84\xab\xd5\x02\xf3\xb1\x4f\x99\x3e\x8a\x7d\x33\x3b\xd4\xb9\xa5\x70\x6a\x18\x8f\x95\x1d\xec\xfb\xb6\xe2\x04\x4d\x9d\x21\x25\xe9\x72\x31\xd1\xb6\x2c\xec\xba\xbb\x77\x2a\x10\xce\x32\xe0\x1c\xc1\x84\x01\xbd\xc6\x0d\x7a\xae\xb7\x9e\x29\xb3\x06\xac\x63\x18\x54\xe9\x45\xa7\x27\x10\x01\x9c\x06\x06\x47\x61\x1b\x17\xf6\x93\x07\xf4\x50\x74\x90\x28\x48\x7b\x34\x00\x5b\xe1\x6f\x95\x0f\xde\xf8\x7c\x67\xc7\x61\xe5\xe0\xe1\x07\x1a\xab\x99\xf4\x5f\xe1\x69\x6a\x45\x5a\xb9\x15\x3e\x78\xee\x2d\xea\x7e\x90\x59\x91\xfe\x33\x59\xaf\xd4\x19\xa6\x1d\xb0\x60\xa4\xa6\x3b\xab\xde\x26\xac\x3a\x73\x9a\x83\x09\x49\x9a\x97\xf6\x2a\xd1\xdd\xb4\x0c\xe8\x5e\x8b\x8a\x8f\xfd\x31\xf9\x36\x7c\xbf\x94\x69\xbf\x30\x76\x57\x16\x37\x03\xe7\x82\xfa\x41\x2d\x92\x32\xb2\xf8\x67\x59\xe8\xb3\x82\x90\xe4\x0c\xc9\x16\x1d\x3e\x0e\xed\x74\x5f\x10\xb4\x02\x18\x94\x3d\x2a\x08\x5a\x41\xb9\x60\x97\x7d\xfd\x62\x31\xc9\x23\x24\x18\x6f\x71\x10\x2f\x84\x60\x3f\x02\x9c\x53\xec\xed\xe7\x89\xc9\x16\x74\xec\x0b\xf9\x00\x3a\x7d\x81\x21\xb2\xc1\xa2\x97\x44\x40\xeb\x9d\xfe\xb9\x39\x3e\xdb\x14\xba\x1c\x0a\x5a\x2e\xf5\xf3\x1c\x07\xdf\x1f\xba\xbf\x0f\x0a\x1a\x04\x7e\x55\xa6\x2d\x01\x87\x48\x56\x9d\xe4\x15\xd1\x89\x50\x54\x22\x8a\x32\xe4\x53\x32\xe5\x09\x87\x91\x50\x65\x53\xed\xf8\xc5\xd9\x02\xdd\x68\x09\x39\x9c\x39\x0b\xfe\xd6\xb3\x4b\x88\xa8\x55\x8c\xa1\xcf\xbc\x36\xc9\xdd\xcd\x4a\xc5\xb6\x04\x55\x4c\x3b\x82\x92\xd7\x96\xf0\x78\xdd\xb8\x00\xb7\xdb\x11\x44\xf7\x4b\xd0\x7d\x1a\xc8\xb4\xbb\xb6\x16\x1e\xa2\x68\xb7\xa7\xa8\x24\x87\x7f\xe6\x2d\x56\x33\x0c\x24\x4e\x88\xeb\x71\xb9\x72\x20\xeb\x21\xba\xe9\xc0\x29\xfc\x92\x59\x35\xd9\x5d\x2c\x12\x5b\x21\x89\xb2\xf7\xfb\xf7\x35\xf6\x11\x8d\x03\xef\xf8\xdf\x19\x75\xb8\x0d\x8e\x7f\x04\x52\x7d\x65\xe4\x3d\x8f\x28\x12\x1c\x8f\x79\xe5\x6e\x55\x4e\x2e\x06\xfb\x09\x8a\x8c\x54\x84\xe9\x52\x58\xac\xd1\xc5\x1d\xc6\x07\x8b\x9e\x27\xd5\x72\x38\x8c\xa4\x94\xf0\x3a\x90\x20\x5a\x94\x97\x6d\xf0\xec\xd9\x7f\xcd\xc6\x4c\xd1\xdd\x52\x91\x4d\x72\x75\xb3\x88\x1a\x94\x97\x26\x45\x0d\xdc\x45\x2e\x47\x30\x51\x88\x5e\xd1\xfd\x62\xaf\x4a\x16\x17\x21\x8b\xcb\x5d\x58\x9c\x47\x16\x4e\xd5\xe5\x6d\x88\x14\x1c\xa2\x8f\x9e\xa0\x54\x38\xa2\x62\xb4\x16\x46\xfa\x08\xdc\x2a\x66\xda\x6e\xff\x5b\x81\x4d\x77\xf6\x96\xbb\xc5\x03\xfe\x03\x84\x14\x7b\xaf\xfd\xdd\xae\x7c\xf1\xfb\x1b\x95\x10\x58\x8e\xe2\x7d\x38\x67\xa5\x12\x54\x83\x7d\x5a\xb4\x1c\x9b\x22\x40\x3f\xc5\x7c\x8a\x78\x7b\xaa\x35\xcb\x40\x00\xe7\x8e\xe1\x0a\x1c\x44\xa8\x2a\x72\x60\x33\xb1\x86\x2a\x13\xbc\x64\x69\x0d\x56\x32\xda\xa4\xea\x6e\xa9\xda\x96\x30\x55\x63\xac\x4d\x49\x5f\x0b\xe3\x7a\x53\xb5\x86\x36\x59\x84\xc4\x2f\xbb\xc3\x83\xc5\x2f\xc9\x28\x60\xd8\x00\x1c\x7b\x57\x85\xf4\xc6\x23\x80\xb7\x70\x0e\x67\x51\xd9\xc5\xa5\x35\xfc\x3c\xf4\xf3\xfe\x4b\x6d\x28\x3d\xf4\xe7\xa1\xcd\xcc\xa6\x7e\x51\x92\x9e\x45\x19\xbd\x17\x1e\xb9\x08\x6d\x85\x5a\x47\xed\x53\xf4\xf9\xe5\x33\x1a\x76\x5c\x78\xb7\xab\x0f\xe2\x8a\xb2\x8e\x1e\x45\xf8\x09\x1f\xe4\x9c\xa0\x16\x0c\x01\x7f\x02\xc4\x81\x3c\x10\x51\xab\x4e\xa3\x56\x85\xc6\x5d\x1a\xf9\x94\xe4\xc6\x99\xbb\x1a\xd1\x86\x62\xa2\x85\x1c\x29\x29\x64\x93\xab\x60\x50\xae\x34\x63\xa8\x0f\x95\x7e\xe8\x0c\xc6\xc9\xbc\x86\x94\xdc\x74\x79\x52\x56\x74\x4b\x15\xb6\x84\xa9\x22\x9f\x94\x15\x2a\x29\xab\x42\x48\x6a\x1f\x58\xd7\x88\x08\x59\x29\x24\x0b\x0b\xfa\x57\x47\xd0\x7b\x83\x5d\xe2\x10\x69\x13\x6e\x2f\xa9\x1c\x5a\x4a\xc0\x19\x06\xaa\x4e\xb5\x3a\x41\x2e\xb5\xc7\x62\x72\x45\x95\x60\x3f\x02\x78\xce\xda\xbf\x3a\x84\x7f\xa8\x3a\x17\xfb\x52\xfd\x32\x99\x15\x57\x82\xbd\x21\xf3\x70\x32\x2f\xeb\xe2\xe1\xa3\x9a\xbd\x42\x31\xbf\x79\x59\x18\x1c\x32\x25\x97\x4c\xc8\xe8\x8b\x8a\xc3\x80\x59\x99\xb1\xfc\x4a\xce\x09\xaa\x40\x3d\x88\x82\x16\xf0\x47\xc2\xf3\xa5\x22\x11\x2d\x6c\xa9\x31\x4c\x9c\xff\x03\xb4\xd9\x8a\x6a\x6b\xbb\x8e\x4f\x25\x9b\x9d\x15\x48\x6b\x68\x66\xb3\x33\xd6\x8a\x67\xac\xbf\x23\x25\xf5\xef\x35\x4d\x43\xd1\xb1\x60\x49\xc9\x57\x5d\x7e\x9a\xa2\xdd\x52\xd4\x96\x30\x45\xf3\xa7\x29\xaa\xad\xf8\xfe\x68\xc5\x97\xf9\x2b\x6a\x23\x2a\x0c\x9b\xb5\xd4\x87\x74\xc4\xa1\xf6\x43\x36\xa7\xb7\xa4\x01\xcf\x9f\x47\x90\x2d\xf8\xb8\xb5\xfa\x04\xbb\x14\x89\x49\xcd\x42\xdc\xe3\xc7\xae\x7d\xa7\x5d\x06\xfd\x63\x31\x29\x2a\x24\x78\x0b\x57\x7b\xc9\x8d\xd1\xdb\x9e\x15\xbd\xdc\x2e\xc9\xd9\xb9\x2e\xda\x2f\x4f\x11\x63\x57\xf7\xa1\x83\xb1\x41\xab\x9b\x95\xd8\x65\xb7\xce\xaa\xc9\x53\x83\xfe\xba\xe9\x7d\xf7\x10\xb6\x87\xad\xef\x9a\xf4\xa3\x96\x15\x97\xd8\x4d\x17\x7e\x79\x55\xb8\xa4\x46\xc5\xb7\x9a\x0a\x00\xbb\x9c\x1d\x01\xca\x41\x3d\x38\xa1\xe6\x80\x57\x6a\xd8\x5e\x16\x4d\x0d\x08\xb3\x38\xd4\x55\x67\x31\x04\x13\xc3\x75\x18\xe4\x2f\x82\x93\xc2\xd5\x2c\xe0\x10\xc9\x67\x90\x04\x1b\xd6\x61\x0b\xf2\x52\x1b\xce\x7e\xbd\xac\x97\x36\x10\xb6\x9d\xb3\x48\x62\x37\x90\xfd\x62\x6d\x2d\x4c\xf8\xcb\xc3\x62\xd6\x9f\x14\xf0\x61\x53\xaa\x14\x12\xe2\x34\xc3\x22\x7a\x0b\x76\xb9\xa6\x0e\x1b\xb1\x92\x3a\x0b\xe7\xc4\xd0\x3a\x05\x48\x01\x00\x72\xb8\x52\xb0\x27\x84\x02\x9f\x11\x1d\xff\xac\x45\xb0\xcb\x10\x43\x25\x39\xb0\x87\xef\x52\xb1\x16\x7e\x1c\x73\xee\x85\x4e\xb7\xe8\x0f\x6b\x41\x19\x51\x3f\xcd\x4d\x25\xbe\xbf\x37\x47\xb6\xf6\x0a\xb9\xe8\x79\x4f\x29\xb9\x7b\x93\x7d\x4d\x75\x78\x08\x7c\xed\xdb\x91\x2b\x36\x2c\x0a\x29\x1f\xac\xb5\xd3\xc7\xaf\x1b\xf7\x5f\xe7\x9d\xbd\x22\x2e\x9e\xdc\xbd\x76\x65\xcb\x78\x6a\x78\xfa\xaa\x50\xeb\x63\x24\x26\xa3\xa3\x2d\xfd\xea\x04\x42\x63\xc5\xc9\xa4\x38\x1f\xa8\x04\x83\xa0\x41\xc5\xd6\x1d\xa0\x92\x56\xe2\x70\x5d\x4f\xb9\xb2\x26\x1c\x8e\xb3\xb5\x88\xbe\x2c\xad\x0f\x4a\xae\x10\xce\x6f\xb0\x86\x08\xdc\x5b\x5d\x48\x0a\xe0\x70\x7d\x39\xac\xd2\xf5\xbb\xaf\x9f\xc3\x74\xad\xac\xb5\x48\x15\xdd\xac\x5c\x8b\xe8\x1a\xea\x3e\x3a\xec\xc0\xd9\x0c\xfe\xa0\x18\x49\xd3\xb2\x5d\x38\x27\x09\x44\x64\xe0\x8a\x79\x47\xf0\xe8\xb0\x1f\x9f\x7d\x15\x17\x96\x29\x41\x97\x89\x81\xe8\x95\x4d\xd4\xa0\x3f\xf1\x92\xe2\xfc\xe8\xc6\x81\x31\x70\x84\x17\xec\xc5\x25\x15\x03\x43\x9a\x3a\x06\x87\x9b\x38\x72\xaf\x72\x60\x4d\x6d\xa8\x0f\x98\x3a\x94\xab\x02\x82\x3d\x4e\x15\x10\x0c\x80\xb2\x22\x6c\xb6\x96\x6b\x07\x10\xc4\x20\x56\x90\x60\x4c\xb2\xda\x65\xca\x9c\x9b\xa8\x9c\xde\xa6\x46\x8a\x20\xc6\xd6\x0c\x55\x2f\x21\x99\xad\x70\xd4\x91\x9b\xa5\x2a\x77\x70\x37\x76\xb3\x6f\xac\x53\xfe\x84\x43\x28\x86\x46\x36\xd4\x15\x94\x4d\x29\xbb\xeb\x1e\xfb\xba\x8a\xf0\x90\xb6\x1b\x0e\x28\x1f\xae\x57\xa7\x69\xe1\x2f\xf7\x79\x1e\x71\xa7\x70\x60\xc9\x63\x9e\xd4\x4a\xa3\xb0\x7a\xd5\xf0\x0e\x6a\x42\x3a\x34\xa8\xa5\x84\xae\x48\xbf\x70\x9d\xba\x0f\x32\x5f\x70\x06\x76\x04\x10\xc1\x30\xf0\x11\x88\xd7\x20\xde\xd5\x5f\xc4\x26\xd9\x68\x98\xb8\xd9\xbc\xda\x6e\xd0\xb1\x29\x49\x0c\xc7\xdd\x5e\x34\x5b\x6e\x5a\x1f\x4c\x36\x95\xd7\xd0\xe6\xa0\xdc\x84\xa6\xaa\x39\x24\x0d\xca\xaa\x76\x76\x52\x8a\x43\x2a\xb3\xc9\x83\x61\x50\xae\xb0\xe4\x8a\x32\xa9\x1e\x5b\x49\xac\xb5\x48\xe1\x6e\x56\xd6\x09\xe7\x2c\xb8\xfc\x9f\x3e\x4c\x4a\xc9\xe7\x6d\x0c\xe3\x20\xb2\x31\xec\x42\x92\x66\x19\x4b\x0d\xa9\xde\x91\xe0\x6d\x1c\x46\x8c\x1b\x2c\x24\xbd\xee\xf2\xfe\xf5\x58\x2e\x6e\xb2\x08\xf6\x84\xad\x62\x00\xc6\x19\x2f\x17\x64\x7b\x19\x09\xce\x29\xc4\x55\x23\x60\x41\x8e\xf4\x39\x2f\x78\x5f\x70\xbd\xac\x0d\xa9\x4a\x9b\x07\x07\xcc\x41\xec\x4d\xcd\xb9\xca\xd7\xdb\xc3\x43\x1e\xda\x27\x3c\x0c\xb9\x3d\x04\x6f\xef\xd0\xbc\x9f\xfc\x6c\xd5\xb6\x37\xe3\x9f\x2c\xd8\xf8\xd4\x42\x34\x21\xd4\xae\x82\xd9\x18\x74\x6f\x35\x99\x90\x2d\xe9\x17\xae\xab\x1e\xd4\xb2\xae\x75\xf4\xbf\xc2\xf1\xaf\x60\xf8\xbd\xaf\x9e\x36\x6c\xbd\x67\xd9\x03\x8f\xef\xbc\xb1\x51\x9d\x9c\xfe\x75\xd1\xf6\xa6\x70\x0c\xc0\x8c\x57\x71\xb2\x17\x38\x1f\x18\x0e\x4d\x20\xde\x88\x11\xe6\xd4\xe2\xde\x64\x52\x06\xb3\x29\x89\x0b\x13\x24\x9d\x61\x21\xa9\x82\xa4\xfd\x0e\x08\x4b\xc3\xcb\x4e\x09\x52\x95\x28\x03\x3e\x25\xf5\x0f\x67\x23\x80\x5b\x42\x52\xe3\x29\x39\x6a\x48\x49\x51\xc2\xb6\x7c\x86\x94\xdc\x9a\x35\x6c\xfe\x26\x8b\xe0\x61\xe8\x96\x87\xd8\xce\x49\xae\xee\xa3\xc3\xbe\xfd\xfa\x7e\x3c\x53\x03\x6d\x52\x4d\xb7\x5c\x2e\x9c\x43\x8c\xac\x2f\xae\xf9\x10\x5b\xc2\x3d\x04\xc9\x9c\x83\xd1\x2b\x0d\x8e\xb0\x06\x97\xbf\x7c\x60\xcd\x90\xbc\xad\xc3\x72\x7a\x83\xcb\x8d\xee\x0e\x1e\xd2\xb7\x0e\x41\x28\x2a\xd8\x8f\x98\xed\x9e\x82\xe2\x2a\x6b\x0c\x4f\xe4\xe0\x46\xc1\x9e\x28\x50\xf1\x33\xdc\x82\xa4\x8b\xc9\x76\x0d\xfd\x8e\x56\x2d\x1b\xcd\x54\x0e\x14\xc5\x0a\xfd\xfc\xe5\xf2\xf4\xb3\x99\x5b\x6a\x50\xd2\xa7\xc3\xea\x47\x4d\x2c\xfc\xe8\x5f\xac\xff\xea\xa9\xdd\xf7\xec\xcc\x9b\x42\xed\xcd\x93\x27\x17\x16\xc0\xed\x6e\xc3\x4c\x79\xfa\x86\x87\x3d\x5a\x1a\xd7\xed\x03\x71\x0a\xce\xde\xb5\x65\x73\x92\xef\x5c\xf8\xb4\xff\xbe\xcd\xa3\x9a\x94\xe3\x9e\x65\x6b\x98\xda\xab\x47\xcc\x7a\xeb\xf9\xaa\x2d\xc5\x9d\x2b\xe7\xbf\x7d\xc7\xec\x07\x36\xb4\x2f\xcc\xa5\x74\x2d\xf5\x35\x5f\xbd\xfa\xc3\xc7\x95\x2a\xfa\xf8\x77\xaf\xbe\x72\xd0\x45\x72\x5a\x33\x5f\x30\xef\x73\x4e\x50\x0d\xde\x57\x6d\xfd\xd5\x62\x2e\x26\x30\x1b\x0e\xa8\x66\xb5\x0e\xc0\x6e\x44\xaf\x21\x95\xa0\xbc\x56\x5d\x50\x86\x06\xf4\x11\x0e\x7e\xd4\x62\x01\x1d\x39\xd1\x97\xa4\x1d\xe7\xa9\xa9\xd5\xdd\xb9\x4c\xed\x6a\x5b\x82\xae\xa6\x1c\xc1\x44\x7f\xf4\x1a\xef\x5f\x9d\x5f\xd2\x87\x8e\x01\x99\xee\x8f\xb6\x1c\xa0\x49\x28\x20\x89\x00\xa4\x04\x7b\x9c\x33\x57\xc4\x62\x97\x0a\xff\xbb\x44\xb8\x1f\x09\x95\xfc\x5b\xe1\x7e\x95\x55\x7c\x14\x8e\x4d\x2a\x7f\x58\xfc\xd6\xa2\x5c\x9c\x5f\xac\x61\xd3\x94\x29\xf3\xda\x17\x2e\x9b\x54\x73\xe6\xed\x87\x4e\xcd\xb4\x73\xce\xf3\xbf\x89\xd5\xf5\x0e\xef\x9b\xd0\xda\x38\x6e\xf0\x55\xd7\xdf\xd4\xfc\x4c\x3c\x14\xed\x00\x14\x88\x02\xc0\x6c\xe3\x9c\x40\x07\x8c\x60\x95\xaa\xcd\x73\xac\x8a\x62\x62\x64\xb3\x94\x34\x69\x4a\x7d\x1c\x52\x88\x65\x41\xa0\x0f\x66\xcd\x4a\x2a\xe1\x2c\xb8\xda\xbf\xed\x1c\x9b\xa0\xf5\x88\x52\x46\xf4\xaa\xca\x4f\xb4\xde\xa8\x2e\x52\x0a\xaa\xd0\xc4\x46\x4e\xad\xa2\xa8\x26\xfc\xfa\xf9\x0a\xe8\xc7\xe9\xbd\xd4\xd1\xe2\xf4\x2c\xca\x50\x94\x6e\xa1\x0e\x28\x3a\xce\x49\x84\xfa\xb5\x74\x1b\xe1\xb3\x01\x00\x98\xa3\xec\x61\x60\x02\x85\x88\xcf\x9a\x54\x6c\x07\x33\x05\x82\x71\x8b\xe0\x10\x45\x2d\x3b\x5f\x86\xee\x94\x04\x6d\xa8\x9f\xb2\xc5\x9d\xab\x9e\x56\x72\x01\x3b\x67\x25\x53\x2d\x23\x81\x6e\x8b\x4c\xb1\xe7\x18\x09\x76\x67\x3f\xc0\xa9\x5b\x85\xd8\xc9\x6c\xed\x3e\xda\xdd\x78\x5e\x8d\x8b\xd1\xd7\x5a\xd0\x9e\x66\xfd\xe7\x24\x26\xff\xbe\x50\x6b\x91\xec\xdd\xb2\xc7\x7f\x4e\x72\x77\x83\xe1\x46\x00\x29\x86\x35\x58\xed\x6e\x4f\x61\xde\x0e\x85\xc3\x4d\x14\xc3\xea\x0d\x26\xab\xd0\xe7\x13\xb2\x5a\x2c\x66\xd5\x7d\x68\x36\x09\xf6\x04\xcd\xb9\x0a\x88\x68\x28\x3a\xa0\xe8\x85\x22\x0c\xd0\x30\xd0\xeb\x22\xb0\xc5\x07\x4d\x5b\x83\xdf\x3c\xac\x3c\xbf\xbd\x46\xf9\xe6\xb1\x25\xea\xf5\x4e\x65\xcf\xf6\x1a\xe5\xab\x47\x28\x29\x7d\x9e\xe2\xd2\xdf\x52\xba\xf4\x78\x8a\x4a\x2b\xec\xe1\xde\xd7\x40\x9d\xff\x67\xd9\xc3\x80\x07\x56\xf0\x5b\xd5\x42\x45\x33\xbc\x28\x8a\x1a\x6c\xbf\x6c\xc1\xb1\xf2\x71\x8b\x1e\xcd\xbb\xc5\xaa\x0f\xc6\x75\x46\x53\x38\x1c\x4e\x72\x10\xe8\xcd\x41\x89\x12\x65\x8e\x4e\x49\x6c\x18\x4a\xb6\xfc\x2c\x77\x1d\x89\x24\x94\xac\xc4\xef\x86\x81\xba\xd5\x78\x04\x43\x4a\x16\xb2\xfc\xf2\x7d\x2d\x9a\x5a\x8f\x0b\xd9\x59\xba\x35\xf9\xc2\x20\x31\x36\xc9\x8c\x4b\x94\x18\xba\x25\x60\x4b\x40\xa0\x77\x04\x25\xda\x96\xa0\x68\xc4\x2e\x71\x40\xa6\xd9\x11\x94\x78\x5b\x82\xe3\x2d\x8e\x20\x7d\x04\x52\x88\x3f\x9a\x2d\xf9\x91\x97\x38\xc8\x1a\x5b\x2c\xbd\x90\xfc\x8d\xce\xa1\xc5\x39\xc9\x56\x25\xd2\x52\xac\xbd\x6b\x85\x1f\x2a\x01\x18\x51\xde\xa6\x7b\xb4\x77\x98\xdf\x04\x15\x27\xb3\x0e\xe7\x42\xfe\x5e\x95\x6c\xcd\x2a\x9f\x91\x1c\x6a\x0c\x4d\x25\x46\x70\x95\x9c\x22\xf6\xcf\xf8\xf0\xb9\x9d\xe8\x67\xf4\xe9\xb0\xed\x15\x9d\xe0\x2e\x18\x94\x9d\x02\x4e\x4b\x42\x87\xb9\x43\xc8\x56\x23\x6d\xa6\xbe\x3e\x41\x56\x9c\xdf\x26\x95\x77\xcb\x7a\xe1\x9c\xa4\xeb\x46\x3b\xea\x79\x82\x77\x65\x4b\x08\x2e\xbb\x23\x98\x70\xa3\xd7\xb8\xdb\x65\xcf\xe3\x3a\x42\x0c\x1c\xd2\xe9\x05\xb7\xbf\x5c\xcb\xe4\xcd\xbf\x22\x11\x06\xfd\x04\xbb\x54\x8c\xf3\xef\xcd\x58\xf3\x28\x28\x44\x52\x55\xa5\x59\xb0\x27\x39\x50\x50\x88\x6b\xcb\xd9\x49\x59\x0c\x47\xef\x00\xcc\xbe\xf9\xd1\x11\x2d\x50\x33\x88\xa3\x31\xc7\x3a\x1e\x9a\xb8\xe7\x4e\xff\x9c\xb8\x72\x30\x3e\xcb\x36\xd0\x38\x35\xd9\x79\xf7\x76\xcf\x18\xeb\xd4\xe1\x74\x92\x84\x65\x2a\x4f\xdc\x14\x7c\x60\xd5\xef\x55\xa4\xa0\x09\x0f\xdd\xb6\xe0\xa1\xbb\x46\x2d\x84\x93\x87\xf6\x9f\x0d\x7a\xd1\xb6\x1e\xb2\xaa\xcf\xe0\x22\xda\x8a\x7c\x2a\x9b\xa4\x11\x09\x49\x03\x09\x71\xeb\x8c\x03\x73\xc4\x2d\x83\x41\xd9\x2d\xe0\xcc\x0d\x8d\xb8\x0d\x7d\x89\x5b\x6b\x93\x42\x17\x13\xd7\x8e\x48\x2e\x39\x6c\x92\xb3\x5b\x2a\xb7\x25\x84\x72\x44\xe8\x00\x7a\x8d\x07\xca\xfb\x10\xfa\x88\x4e\x2f\x38\xcb\x03\x39\x71\x15\x5e\x74\x87\x10\xbc\x4e\xb0\x4b\xd5\x31\xa9\x0c\x13\xdc\x6d\x27\x10\x00\x76\x01\x27\x91\x00\xb9\xba\x40\xb0\xcb\x45\x65\xb1\x98\x2c\x96\xa0\xb3\x01\x54\xa8\xdc\xff\xb2\x13\x70\x89\x24\x9e\x2b\xce\xc6\xb7\xd6\x1b\x5b\x42\x0d\xb3\x97\xdd\x6a\x2e\xb6\xf7\xbf\xe2\xac\x7c\x57\x31\xca\x37\xcb\xbd\xc5\x7f\xcb\xb2\xe1\xf5\xf7\x74\x6c\xc9\x9f\x1e\x08\xf6\xc3\x2e\xfa\x28\xe7\x04\x05\xe0\x34\x88\x3b\x55\x89\x35\xee\xd4\x21\x1e\xe0\xb4\xe8\x83\x71\x60\x2d\x08\x87\x55\x2b\xbe\x7a\x46\x14\x92\x04\x4c\x2b\x46\x36\xc3\x0e\x09\x1b\x76\x48\xd8\x61\x50\xb2\x85\x65\xa3\x15\xf1\x91\x84\xc5\x68\xd7\x05\x65\xab\x15\x2b\x26\x16\x6b\xae\x26\xc1\x33\x67\x4f\x12\x53\xf7\x7d\x67\x17\x90\xc8\xb2\xbc\x50\x9f\xa3\xc3\x76\x9e\xdd\x81\x0f\xe2\x02\x5b\x82\x2e\x40\xc7\x8b\x07\xbd\xc6\x3d\x05\x7d\x0e\xe2\x04\x6d\xb6\x79\xd4\xb8\x64\x4f\x5e\x42\xbb\xc4\xc6\x64\x8b\x55\xb0\xcb\x3a\x27\x46\xdd\xf1\x42\x91\xe6\xf8\xbe\x48\x4e\x1c\x4f\xef\xff\x46\x1a\x25\x58\x5a\x96\x0f\x9f\xb7\xda\xb4\xfc\xe0\x72\xd3\xc4\x9b\x76\xf6\x1b\x0b\xbb\x98\x07\x94\x37\x3b\x6a\x5a\xc2\x4b\x97\x0c\x8a\xa6\xbf\xa5\xb8\x41\x75\xd3\x5f\xde\xa7\x3c\x09\x20\x38\x08\xbb\xe8\xe3\x9c\x17\xf8\xc0\x39\x10\xf7\x42\xd5\x0e\xe7\xc5\x68\xf6\x5e\x17\xa2\x95\xdb\x87\x68\x65\xc6\x01\x5a\x21\x99\x61\xb3\x29\x47\x3e\x2b\xc6\x30\x2e\x24\x18\xb8\x09\x97\xbd\x50\x17\x94\xdd\x56\x6c\x7c\x72\x59\x73\x05\x62\x54\x41\x5f\x0b\x54\xf0\xd9\x24\x63\xf7\xd1\x61\x2f\x7f\x35\x06\x2f\x64\x37\x4e\x36\xc3\xd1\x0b\x92\xcf\x96\x30\xf9\x8c\x48\x1f\x33\xa3\x3f\x5a\x11\x15\x63\xa2\x14\x5d\xc6\x4b\x7d\xc6\x3c\x72\x99\x62\xe0\x10\x34\x9a\x9c\x9e\x52\x75\x51\x1f\x86\x46\x93\x39\x7b\x49\x88\xe7\xf6\x09\x76\x59\xcf\x90\xda\xac\xbc\x95\x23\x39\x50\x18\xa4\x24\x97\x3d\xe4\xcd\xc5\x59\x59\xa9\x86\x8b\x68\x7a\xf0\x4d\xf7\xf2\x69\xc3\x83\x51\x7f\x54\x28\x29\x5a\xb6\x71\xde\x1a\xc7\xc2\x17\x17\x5b\x26\xce\xdc\x11\x18\x0b\xbb\xe8\xe4\xad\x8b\x0b\xbb\xdc\x1d\x77\xce\x59\xb9\x64\x71\xed\x75\x8a\x85\xe2\x86\x56\x4c\x3f\xf2\x82\xf2\x24\x89\x6d\x7e\x11\xf8\xa9\x00\xfb\x67\x60\x02\x05\xe0\x0e\x20\x19\x43\x32\x8d\x24\x14\x23\xa2\x2f\xcd\xe9\x83\x12\x1f\x96\xdc\xa1\xa4\x8d\x06\x41\x26\x88\x97\x21\x77\x4a\xe6\xad\x6a\xcc\x9b\xc3\x95\x5b\x62\x13\xfe\xb2\x26\x2f\x61\x9f\xc4\x66\x5d\x14\x95\xc5\x9b\x05\xbb\x6c\x73\x63\x24\x09\xa3\xa0\x96\x30\xc4\x1b\x54\x95\x85\x09\x5a\x22\xcc\xf3\x92\x4f\x18\x32\x68\xb4\xef\xb5\x9f\x9d\x2c\xba\x6b\x69\x3d\x5c\x39\x24\x5c\x13\x1c\x5a\x53\xd9\x10\xbd\xcf\xb5\x99\xde\x75\x61\xea\xdd\x77\xb2\x33\x06\x35\x0d\xaa\x0c\x0d\x1d\x48\x62\x3d\x60\x17\xdd\xc4\x7c\x00\xac\x60\x88\x5a\x11\x02\xb2\x29\xfc\x46\xd2\x8b\x32\xc7\xa5\xb4\x83\xd4\x6a\xc3\xa7\x27\x34\x92\x0c\x3a\x01\x6d\x29\x2b\x4e\x0f\x27\xeb\x97\xcf\x43\x33\xa4\x0f\xc6\x77\x18\x07\x2d\x6b\x6b\x6c\x28\x1b\x52\x39\xf5\xe1\xb2\xf1\xb0\x8b\x1e\xbe\xfe\xea\x36\xd3\x0e\xf3\xd1\x87\x95\xad\xe8\xb9\x5e\xb8\x82\x3a\xc0\x9c\x04\x56\x10\x05\x92\x25\x24\xd3\xea\x93\xf2\x32\x2f\x8d\x41\x59\x67\x23\x4f\xd2\x1b\x54\x71\x84\xb6\xa8\xd0\xc5\x83\xea\x1c\x51\xb7\x9a\x03\x1c\x88\x22\x1a\x78\xcb\x86\xfb\x6f\x7c\xd8\x37\x5e\x8a\xef\x30\xd6\x2c\x1a\xdf\x08\xd7\x6f\x37\x1d\xdb\x01\x57\x5e\xe8\x5e\x3f\xe2\x5a\x3c\x56\x2f\x28\xc4\xcf\x2c\x02\xd3\x00\x56\xa0\x58\x8c\xee\x86\x1f\xed\x0d\x49\xce\x53\x98\x2d\x68\x99\x94\x36\x1c\x80\x21\x1b\x9d\x24\xba\x9c\x17\x24\x3b\x8e\x2e\x37\x5b\x6d\xb1\xfc\xb4\xc7\x42\x21\x6e\xb4\x3a\x71\x4a\x18\xfa\x62\x7e\xc7\x72\xfc\x12\xb1\x4b\x0e\xf5\x71\x98\x7f\xda\xa3\x25\xe3\xa5\x93\x06\x71\x50\x24\x76\xed\xb1\xa1\x86\xd9\x1b\x5b\x51\x4f\xff\xe5\x01\xb8\xea\xc2\xf4\x81\xc5\x2d\x05\xeb\x4a\xe3\x37\xbc\xee\xdf\x0e\x28\xb0\x07\xae\x67\x2a\x98\x93\x38\x4f\x6c\x3b\x90\xcc\x21\x09\x88\xb2\x85\xc5\x1b\x12\xaf\x3a\x37\x5e\x75\x50\x1f\x54\x0b\x9d\xaa\xe9\x54\x59\x4e\x27\x1b\x6c\xb9\x74\xaa\xfb\xd5\xda\x74\x59\x8d\xc2\x82\x8b\xce\xd0\x16\x9c\x4e\x65\x51\xd3\xa9\xf2\xb2\xc5\x28\xe2\xac\x33\x08\x32\xcb\xe3\xbc\x09\x4b\xaf\x74\x2a\xc4\xb3\xb4\x74\x2a\x2e\x50\xa5\x59\x6f\xf7\x1c\x96\xc6\xdc\x01\x3d\xef\x29\xef\x0c\xbb\xfa\xa5\xa7\x0f\xc7\xc7\x4e\x1f\xd9\xfa\x34\x5c\x4f\xb7\x29\x47\xe1\x28\xe5\xb9\xc2\x05\xa3\xee\x7d\x7c\xf3\xd5\xc3\x86\x8a\xe4\xdc\x7d\x13\xae\x67\xd1\x18\x5d\xe0\x2a\xa0\x05\x48\x41\x0b\x92\x94\x25\x1a\xed\x18\x97\x09\x43\xd2\xd3\x26\x2c\x3c\xe3\xb5\x60\xc1\x31\x53\xb2\x40\x6b\x35\x19\xf5\x82\xcc\x5b\x09\x7a\x99\xe8\xe0\x87\x41\x87\xe8\xf0\x60\x24\xf9\x00\x5d\x15\xe1\xe9\xc0\x9b\x7b\x6c\x4c\x95\xf9\xe3\x97\x8b\x18\x7b\xeb\xa1\xc3\xca\xba\x13\x05\xd4\xf0\xdf\xbc\xc6\x9c\x4c\x7f\x7d\xe3\xcc\x12\x98\x52\x9a\xf7\x46\x9e\x80\x8f\x5d\x78\x09\x9e\x18\x71\xe3\xa3\x8a\x88\xfb\x05\x80\x9d\x7e\x1b\xf7\xeb\x7a\x9c\x63\x44\xb3\x24\x7e\x4b\x77\x4a\xd6\xdb\xb2\x41\x5b\xdd\x8f\xfd\x75\x3c\x39\x1e\x74\xb5\x16\x89\xef\x66\x64\x7d\xc9\x39\x24\x97\x83\x04\xaf\x23\xbe\x6a\x28\xf3\x86\x6c\x08\x91\x06\xf4\xd4\x04\xd5\xca\x27\xa2\xc3\xed\x41\x1d\xc6\xf6\xa1\xe6\xfa\xc8\x35\x03\xc4\x2e\x29\xa6\xb7\x94\x0d\xf8\xee\x17\xe9\xaf\x46\xef\x58\x38\xac\x6a\xa3\x7d\x74\xdb\x54\x7a\x94\x32\x63\xe8\x4f\xc6\x4c\x86\xbf\xbf\x10\xd9\x34\x17\x40\xb0\x96\x3e\x4e\xd9\xb1\xac\x5c\x0e\xe2\x14\x05\x82\x49\xa0\x07\x7a\xc4\x72\x74\x18\x0b\x8c\x31\x02\x23\x13\x44\x6a\x25\x22\x8b\x3d\x2a\x7a\x2c\x90\x5f\x7b\xcf\xc8\x5f\xea\xfa\x3f\x38\x99\x3e\x0e\x07\xbc\xed\xbe\x31\xb3\x99\xe8\x30\x6b\xe9\xe3\xf4\x56\x55\xee\x2e\x25\xad\x49\x46\x51\x6d\x50\xd2\x61\x59\x1a\x91\x3e\xaf\x25\xb1\x01\xbd\xe1\x68\xad\xc5\x2f\xeb\xef\x72\x9e\xd4\x4d\x7a\x39\xdb\xf2\xad\x70\x44\x93\xfb\x0d\xe5\x33\xa0\xf6\xd5\xc6\x1e\x06\x5c\xb6\xaf\x9c\xda\x57\x1e\xf7\x95\x26\x7d\xd5\x91\x27\x34\x38\x44\x8a\x0f\xac\x9d\x92\xd8\xf2\x40\xd3\x09\xfa\xf4\x9b\xd0\xad\x1c\x3a\x00\xc0\x3f\x75\xcc\x10\x7c\x4a\x1f\x87\x49\xdc\x27\x1f\x20\xd5\xae\xd9\xfc\x3e\xc9\x8c\x31\xa5\x75\x28\x2a\xda\x3c\x81\xca\x4f\x85\x83\xb6\xf5\xc3\xd8\x67\xdd\xca\x57\x9f\x7f\x4c\xda\xf0\x31\x4f\xc0\x20\xd7\x0e\xcc\xa0\x3f\xc0\x09\x2e\x0c\xae\x2b\xa7\x63\x48\x22\x2c\x73\x2a\x69\xc4\x88\x6c\x40\xe6\x21\xe6\x5f\xa8\x31\x62\x73\x8a\x62\x6e\xed\x73\x0e\x19\x1b\xaa\xf2\xb4\xcf\xdd\xce\x3c\x31\x77\xf4\xb0\x01\xe1\x05\x4b\x26\x2e\xba\x1b\xb7\x5d\xc7\x3c\x01\x9b\xb5\xb6\x8d\x21\xd9\xc0\xa4\x24\x26\x24\xd3\x8c\x96\x64\x9b\xe4\xd5\xb6\x31\x2e\xa4\x86\x1e\xc6\x13\x30\x72\xbe\xbc\xb2\x6e\xd7\x6a\xf7\xd0\x31\x75\x15\x9e\x6b\xe6\xb0\x53\x6f\xde\x30\xaf\xad\xb9\xa6\x66\xfe\xcd\xb8\xed\x13\xf4\x61\xea\x30\xe7\x07\x76\x30\x18\x48\x86\x50\xd2\x48\x83\x91\x4c\x10\x4d\x32\x85\x9a\x77\x60\xa0\x34\xd6\x8d\x03\xe4\x00\xa9\x5c\xa7\xc3\x78\xe8\xac\x3d\x16\x93\x28\xf5\x69\xea\x89\x63\x85\x81\x68\x3f\x92\x5e\x73\x62\xc5\x9d\x2b\xb7\x3e\xfc\x63\xf7\x9a\x2a\x68\x69\x19\x3a\x61\x2e\xfb\xe1\x88\x55\xb3\x16\xef\xa8\x5e\x94\x6c\x7c\xb6\xb6\x75\x08\x7e\xf6\x31\xfa\x30\xf5\x01\x7e\x36\xe1\xfb\x66\x3a\x25\xe9\xd4\x71\x91\x54\x6d\xa3\x49\x7d\xb0\xd9\x42\x18\xac\x4e\x90\x01\x47\xd8\x2b\x9b\x05\x49\xc3\x07\x8d\xcb\xe9\xc1\xe5\xb3\x8f\xbd\xb0\xfd\xae\x39\xb1\x1b\xaf\xbf\xf6\xc6\x97\x2a\xd6\x78\xe6\x4c\x65\x0b\x57\x3f\x34\xaa\x73\xc8\xf5\x23\xba\xc2\x2f\x2e\xa9\xdc\x88\x9e\xbb\x0a\x44\x19\x3b\x53\x09\x38\x00\x1c\x11\xe8\xd2\x43\xd7\x2a\xfa\xc9\xb4\x8f\xfa\x08\x9e\x99\x0b\x3f\x7a\x5a\xd9\xa1\x1c\x7b\xa6\xcf\xf7\xa2\x11\x3d\x8c\x40\xd7\x2a\xea\xa3\xb4\x8f\x7e\x32\xfa\x0c\x1c\x01\x97\x3e\xad\xf8\xe6\xe2\x71\x8c\x07\xed\x4c\x33\x63\xc1\xdf\x43\x2a\xb0\x1e\x8e\x87\xfb\xe7\xc2\x8f\x9e\x51\x76\x2a\xaf\xb4\xd3\xbf\xbc\x30\x94\x66\x2e\x5c\x00\x7d\xbf\xeb\x10\xf5\xe8\xdb\xe3\xf7\xc0\xa5\xb0\xf5\x49\x65\xca\x22\xc6\x72\xe1\x02\xcd\x5c\x18\x0a\x00\x84\x5d\x4c\x0f\x03\x38\x3f\x30\x83\x20\x5a\x4f\x92\x4e\x4c\xd2\x7a\x60\x46\x8b\x92\x4c\xb9\xce\x08\x78\x26\x28\x5b\x71\x85\x14\xa0\x2e\x29\x18\x69\x88\x8a\x6e\x1f\x74\x05\x70\x81\xcc\xae\x3f\xd7\x1d\x2c\x9f\x31\x60\x79\xe3\x82\xf5\xcb\x99\x1e\xef\x7f\x5e\x37\x6d\x5b\xab\x77\xd0\x7d\xcb\xc7\xe0\xbe\xc0\xb7\x99\x1e\x66\x04\xe7\x07\x16\x50\x03\x24\x53\x28\x49\xe1\x07\x48\x5c\x18\xc7\x7e\xe4\x9e\x61\x43\xcf\xa0\x4c\x82\x5d\x86\x38\xf1\x1d\x46\x44\xb7\xa7\x21\x2a\xba\x78\x8e\x0f\x54\x56\xc1\xb7\x17\x0f\x9f\x75\xe7\xea\x95\xad\x3f\x19\x2c\x95\xdf\xc8\x71\xde\xf0\x96\x65\x57\x7b\x9b\x76\x4d\xbd\xe9\x7e\x32\xe6\x56\xe6\x04\x0c\x72\x4e\x40\x83\x18\x1e\x0b\x2d\x26\x21\x79\x14\x15\x86\x12\x43\x0e\x2a\x4b\x4a\x02\x88\xc9\xd3\x96\x54\x7e\x59\x6e\x1a\x12\x55\x19\x9d\x30\xad\xa3\x77\xb7\x31\x27\xe0\xb5\x8a\x4c\xfa\xbf\x93\xe9\xa1\x7b\xd8\x85\x80\x06\x7e\xb2\xe7\xb8\x14\xfa\x8f\x9b\x04\xa7\x92\x94\x11\xe8\x98\xa0\xcc\xe2\x9d\x0b\xa3\x7e\x1e\xee\xf4\x51\x55\x3e\xa6\x67\xfb\x76\xd2\x2f\x96\xe9\x81\x2f\x71\x7e\xa0\x07\xfd\xd0\xef\x93\x8c\x4a\x60\x03\xfe\x39\x67\x04\x06\x26\x28\x73\x00\x8b\xe8\x68\xf3\x47\x86\xc1\xa8\xe8\xb2\x40\x9e\x15\xef\xa9\x79\x27\xf4\xd6\x18\xa6\xc7\x1b\x95\x47\xba\x62\x27\x22\x38\x26\xfb\x1b\xa6\x07\x8e\xe2\xfc\x40\x87\xfa\xc3\x69\xf4\xc4\x51\xf8\x68\x84\xae\x14\x90\x29\xe2\x8d\x1f\x54\x47\x23\x1a\xba\x02\xb5\xd0\x70\xbc\x7a\xee\xd2\xd6\x7b\x38\x93\xab\x6b\x7f\x61\xeb\x51\x00\xa0\x92\x52\x66\x64\xfe\x3d\xf3\xf3\x7f\x88\x5e\xd0\x21\xd2\x4a\x6a\xf4\xee\x36\x65\x86\x4a\x30\xa8\x8c\x53\x7e\x0d\x1e\xce\xcc\x01\x34\x28\xb9\x3c\xbd\x54\x5a\x29\xe3\x10\xad\x94\x5f\xab\xb4\x52\x7e\xa7\xdc\x04\x6a\x33\xfb\xc8\xd8\xd8\x90\xda\x21\x3c\x36\x74\x4a\xa3\xb1\x41\x56\x65\x3e\xac\x3a\xb4\x2a\xe5\x77\x64\x70\x45\x53\xf0\xd8\xa2\x00\x2a\x9b\x94\x9b\x40\x34\xb3\x8f\xd0\x5c\x1f\xca\x2e\x6a\x43\x48\xd2\x9f\x4a\xb2\x84\xe6\x2c\x89\x0d\x42\x5d\xd1\x48\x1e\x50\x36\xa9\x44\x5f\xae\xdc\x9e\x25\x3a\x85\x0f\x95\x21\x4c\x3b\xa0\x00\x0b\x06\x69\x76\x22\x8c\x22\xc2\x69\xe7\x00\x5a\xc2\x0c\x10\xec\x32\x85\x6b\x3c\xa0\xcd\x22\x43\x16\x2d\x64\xbf\x17\xd2\x7e\x5a\xf9\xec\xec\x9a\x0d\x70\xe1\x57\xb0\x44\xf9\x84\x69\xc7\x45\x8a\x60\xe6\x24\x5d\x03\xeb\x70\xbb\xa5\x00\xe7\x53\xa0\xd9\xc4\xb1\xae\x34\x6e\x17\x1a\x81\x09\x13\x8b\xf6\xd3\x31\xb8\xf0\x6b\xf2\x43\x98\xd9\x0e\xff\x0a\x7e\x4c\xef\xfb\x21\xe7\x00\xdd\xeb\x1c\xb8\x39\x7b\x0e\xc0\xbf\xf6\x3e\x07\x32\xcf\xc3\xbf\x02\x59\x6b\xfb\xfb\x9d\x03\x74\xaf\x73\xe0\x47\xb9\x73\x80\x3a\xd2\xeb\x1c\x50\xa6\x29\x13\x41\x20\xf3\x34\xe0\xc1\x48\x80\x3a\xcc\xb2\x29\x89\x0a\xc7\x59\x3e\xeb\xb5\x63\xc2\xf8\x6c\xa5\x4f\xc9\x8c\x9b\x2c\xb9\xe7\xcf\x7e\x48\x32\x34\x55\x70\x56\x5a\x83\x65\xc5\x6b\x48\xc4\x75\x6e\x95\x69\xde\x9d\xc1\xae\xe0\x0e\xaf\x32\x71\xed\x3b\xef\xac\xc5\xcf\x7a\x4a\x99\x08\x66\xe1\x67\x8d\xc6\x34\xc2\xd1\x77\x48\xd5\x00\x10\x3d\x0d\xb0\x7a\xc2\x84\x74\x58\x61\x62\xfb\x3c\x8d\xef\x26\x21\x75\xd9\x60\x3a\x30\xa8\x8e\x8d\xfa\xf9\x00\x1f\x88\x2a\x4f\x15\xc1\x17\x8b\x76\x04\xbb\x82\x1f\xae\x5d\xfb\xce\x3b\x00\x2a\x5d\x4a\x0d\x18\x9b\x39\x09\x8c\x60\x13\x7e\x16\x41\xd6\x65\x09\xb2\xae\xf6\x40\x83\x3e\x28\xe9\xc3\x71\x08\xb0\x05\x59\x1b\xac\x49\x1b\x6c\x42\xcf\xd0\xba\xa0\x6c\x70\x63\x94\x63\xbd\xda\x9f\xed\x67\xef\x45\xfd\xf9\x01\x20\xbb\x79\x64\xc1\x9d\xed\x2a\xdc\xe9\xeb\xf2\xed\x28\xdc\xee\xeb\xf2\x29\xc7\xd6\x3e\xf4\xd0\xda\x6d\xdb\xd0\x3c\x57\x2b\xc7\xc0\xe9\x4c\x14\xd0\xa0\x14\x48\x74\x48\x06\x6c\x0a\xfd\x87\x78\xb2\x61\x10\x6d\x54\x03\x5e\x7b\xbc\xdf\xe5\x3f\x0d\x0f\x2a\x1d\x6f\xae\x45\xfc\xf0\x34\xd3\xc3\x04\xd8\x2f\x80\x19\xb4\xe0\xf5\xc1\xf1\xa9\x38\x87\xb5\x51\x4e\xa7\x27\xcc\x83\x2c\x13\x9a\x80\xc3\xd2\xd8\x16\x9a\xd4\xe3\x2b\x9c\x32\xa8\x23\xc9\xc1\xa8\xa3\x91\xa8\x88\xdd\x67\x22\xe5\x2f\xaf\x84\xa7\xa9\x45\x63\xa6\x1e\xf0\x2f\x6f\x56\xfe\xb2\x62\x2b\xfb\xaa\xbb\x60\x68\xcb\x3a\xe5\xbf\x6f\x27\x7c\x78\x04\x0b\x28\x2f\xfb\x09\x30\x80\x72\x80\x0f\x70\x7d\x0a\xfd\xc7\x45\x9e\xc1\x29\x99\x35\xa6\xf0\x7f\x13\x61\xc4\xb9\x08\x46\x38\xe2\xaa\xc8\x4d\xa3\x42\x03\x1a\xd9\x19\xb1\xf6\x69\x83\xaf\x09\x03\x8a\xaa\x60\x7a\xe8\x8f\xb8\xcd\xc0\x08\x3c\x60\x14\xe2\x10\xb2\x95\x21\x52\x3f\x43\xd2\xaf\xc0\xa9\xa4\x89\x74\xdf\x84\xf5\x9a\x24\x47\xba\x8f\x4d\x15\xe8\x8c\xd2\xe3\x5d\xee\xb2\x22\x8d\x00\xc3\x1c\xe5\x2b\xc4\xb9\xb8\xea\x72\x8e\xaa\x58\x37\xa3\x73\xed\x1d\xb3\x67\xdf\xbe\x78\x48\x83\x38\x7c\xb8\x38\xa8\x85\x95\x66\xde\x7a\xcb\xcc\xce\x95\xb7\xcc\x89\x0c\x1d\x1a\x89\x0c\x1d\x8a\xf7\xdd\x12\x65\x04\x78\x15\x00\x60\x03\x03\x48\xbc\xa8\x64\x09\x25\xf5\x0c\x18\x85\xd8\x01\x41\x14\xe1\xcd\x18\x46\x84\x80\x99\x6b\x3b\x2f\x2a\x6a\xf8\x07\x38\x62\x7d\xda\x9a\x3b\x6e\x6d\x1f\x51\x15\xac\x1d\x39\xe9\x26\xe5\xb3\x6b\xee\x1a\xfb\xa3\x65\x91\x11\xfa\xe5\x96\x1b\x10\x0d\xc7\x31\x3d\x4c\x94\xfd\x08\xb8\xd0\x59\xac\xd6\xcc\x30\x84\x13\x3c\x65\xd7\x61\xf3\xa3\x04\xc2\xaa\x4a\x94\x74\x91\x01\x7b\x08\x39\xed\x62\xb8\x94\xd2\x90\x74\x6b\x29\x8c\x4a\x30\x2e\x16\xaf\xb9\x76\xd4\x30\xef\x80\x48\xc1\xe2\x51\x2f\x54\xb7\x8f\xba\xca\x1f\x0c\xbb\x99\x1e\xc8\x05\x06\x04\xc4\x66\xe5\x7c\x20\x18\x18\x1c\x43\xf2\x3e\xdc\xc8\xf4\x30\x6b\xf1\x19\xe8\x20\xa7\xa8\x64\x10\xb3\x07\xa1\x33\x24\xbb\x70\x15\x19\xa0\x06\x24\xc3\xec\x11\x28\x66\xdf\xc1\x8d\x75\x0f\xf5\x7b\xb9\xe6\x9d\x51\x17\x42\x5b\x07\xbe\x54\xf7\xab\xd1\x4c\x8f\x37\x72\x6c\xa8\x2b\xf6\xab\xb0\x57\x4c\x8e\x72\x35\xbf\x16\x06\x50\x39\x03\xa7\xc1\x00\xed\x04\x56\xf4\x14\x63\x48\x66\x75\x9a\x35\x21\xa9\x27\xe7\x8e\xcc\x1a\x05\xbb\xa4\x47\x4f\xa9\xe8\x5d\x48\x48\x39\x03\x0d\x46\x3e\x54\x5b\xdd\x5a\x39\xf8\xb6\x5b\xe7\x2c\x31\xaf\xa0\xde\xbb\xea\xf6\x89\xed\xa4\x24\x50\x11\x9e\xa3\xf7\x98\xed\x70\x3f\x27\x02\x23\x18\x88\xda\x97\xf4\x58\x5e\x32\x30\x41\x6c\xff\x37\x69\x27\xba\x1e\x3d\x88\x36\x0a\x76\x99\xc1\x86\x03\x3a\x5a\x15\xf5\x44\x3d\xbc\x87\xaf\xe2\x43\x3b\xa7\x2f\x98\xb1\x73\xd4\xae\x99\x8b\xa6\xef\x62\x3e\x5b\xbb\x66\xf2\xda\xb5\x93\xd7\xac\x9d\xb8\x66\x0d\xd2\x8b\x24\x10\xa0\x5f\x65\x4e\x62\xfc\xaf\x55\x40\x12\x42\xb2\x9b\x25\x69\xeb\xe0\x94\xec\xb4\xa4\x24\x06\x1d\xc6\xac\x0d\x1b\xd3\x0b\x60\x50\xb6\x58\xb2\xa9\xec\xdd\x1f\xfe\xcf\x3d\x44\x33\x64\x54\xac\x02\xd6\x7a\xce\x22\x71\xdd\x20\x41\x33\x2c\xa7\xda\x04\x39\xd5\xcc\xc3\x3a\x05\xbb\x2c\xb8\x63\xb8\x70\x6b\x51\x4c\xb2\xd8\x65\xde\x84\x35\xda\x68\x7d\x43\x94\xd6\xf4\xd9\xec\x82\x16\xc3\x91\xfa\x2a\x4e\x6a\x9b\xbc\x55\x1a\x6b\x0a\xd6\x7c\x78\x4c\x99\x50\x75\xdb\xcc\x6b\x67\x3f\x5b\x54\xcb\xb7\xbc\xdb\xfa\xf8\x12\x4a\x52\x1a\xae\x9b\xd6\x06\x57\xa5\x47\x3f\x75\xfd\xb2\xfb\x67\x8c\x0f\x2e\xac\xaf\x99\x04\x20\xd8\x08\xbb\xa8\x00\x96\xcb\x46\x03\xcd\x56\x8a\x45\x01\x99\xb6\x62\x9f\x08\xb6\x95\x5a\x53\x48\x84\xc2\x2c\x6f\xcf\xd9\x8f\x54\x50\x92\x5c\xc0\x2c\xa5\x05\xcc\x42\x55\x4a\xdb\xf8\xcd\x81\xaf\x61\x17\xf3\xc0\x77\x2b\x90\x8c\xb5\x0e\xae\xa1\x2d\xcc\xfb\x20\x00\x16\x00\xe2\xd5\xb6\xb1\xa9\xb8\x05\x82\xa0\x54\xae\x5a\x1c\xfb\x61\x1d\xa3\xd0\x8a\xab\x6e\xf1\x30\x28\xfb\x6c\x38\x8a\x5a\x2e\x34\x0b\xf6\xb8\x91\xc1\x8e\x48\x5e\x48\x18\x6c\x6e\x8c\xc0\xe8\xb3\x63\x6c\x46\xa6\x5c\xb3\x81\x25\xa0\xd9\x81\x1d\x06\x36\xbb\x64\xc7\xf6\xea\x2b\xf9\x2a\xb1\x89\xa2\x7c\x5d\x74\x4b\xfd\xf8\xeb\x82\x13\xe6\x5c\xbf\x67\xf3\x96\x0d\x62\xed\xc2\xe6\x58\x6b\x70\xfc\xa2\x09\x07\x9f\xdd\x04\x93\x4f\x57\xd4\x44\xeb\xaa\xc4\x41\xb1\xc5\x6d\xcb\x37\xb6\x6e\x70\xf7\x8b\x0e\x2c\xab\x19\x34\x74\xe9\x98\xdb\x37\xe1\x9c\x1d\xd8\x45\x1f\x60\xd0\x99\x02\x1c\x90\xc6\x6e\x2f\x47\xc0\x08\xab\xe1\xfc\x64\x7c\x65\xcf\x3b\xca\x9e\x63\x87\xd7\x7c\x0a\xbb\xe0\x8b\xf0\x61\xe5\x33\x58\xa8\x4c\x53\x3a\xa1\x5f\x39\x83\x65\xce\x0f\x61\x17\x3d\x99\x2b\x01\x4e\x30\x17\xe0\x3c\x2a\x2e\x97\x47\x85\x61\x7d\x24\x1b\x06\x74\xb7\xa6\xd0\x1a\xb3\x59\x73\x09\x55\x6a\xec\x0b\xa3\x7a\xf5\x18\xd9\xe6\x53\xd1\x89\xac\x36\x0d\xf0\x22\x97\x58\x45\x1b\xd4\x4c\x44\xac\x22\x65\xe3\x3b\x9d\x1e\x9c\x50\xf5\xe1\x9b\x7b\x47\xac\xb9\xb6\x7d\xc0\xd4\xc6\x8e\x9b\x4f\xae\x38\x38\x7b\xf6\x54\x26\xfe\xfc\xaf\xaa\x06\xaf\xf3\xd5\xad\xe9\x3c\x74\x43\xfa\x0c\xfc\x70\xf8\x33\xb8\xbf\xcf\x02\x40\xbd\xc4\x6e\x00\x2c\xe2\x7d\x4c\x0e\xbd\x01\xcb\x57\xcc\x29\x99\x76\xa7\xe2\x0c\x8d\xce\x18\x06\xe8\x83\x68\xfa\xb0\xa4\xec\x17\x02\xc2\xb3\x54\x41\x17\x73\xbe\xeb\xfc\x7a\xe6\x3c\xe8\xd5\x16\x0f\x1a\x41\x9c\xcb\xb5\x95\x77\xf0\xaa\x87\xbe\x44\x85\xd1\xb9\x1f\xe7\x58\x7c\x7a\xa1\x96\xf5\xd9\x96\x45\xd4\x36\xdc\xde\xd5\x45\xef\xef\x82\x1d\xe7\xd7\xd3\xfb\xff\x17\xda\xa6\x9e\xea\xa2\xa6\x9f\x5f\x4f\x3d\xf5\xbf\xd0\x36\x9c\xd8\x45\xef\x39\xbf\x1e\x4e\xec\x45\xdf\xb0\x86\x37\xdf\xa7\x61\x2e\x24\x51\x58\x0a\x8a\x53\xb8\x55\x2a\x47\x67\x11\xb7\x8a\xdb\x64\xce\x9f\x5f\x0f\x2e\xd9\x1e\xb6\x0e\x02\xcd\x3a\xa8\xca\xc5\x78\xde\xd4\xbb\x6c\xae\x3d\x41\x14\xfc\xae\x67\xbb\xe0\x76\x76\xc3\x77\x5c\xd7\x45\x73\x86\xe3\x1a\x38\xd5\xe0\xc8\xe5\x9a\xd4\x91\x33\xd0\x8d\x45\x46\x1e\xb7\xca\xb3\xd9\xb1\x93\x56\xfd\x02\x6a\x57\xb9\x99\xdd\x90\xde\xdd\x95\xee\x44\x72\xe0\x24\x65\x01\xf8\xb7\x8c\x0c\x2c\xa0\x1a\xf1\x6c\x4d\xc9\x61\x89\xfe\x69\x39\x95\xe4\xb1\xf0\x0e\x64\x88\x18\x36\xa0\x63\xaa\x6e\x91\x55\x3d\x43\x50\x99\x94\xaf\x7b\x06\xaf\xcd\xa9\x9e\xad\x68\xcd\xd1\x19\x3d\x13\xa3\xee\xe5\xa6\x01\x1a\xf0\x40\x07\xdc\x40\x9d\x3a\x24\x4a\xb1\x68\x15\xeb\x43\x48\x86\x47\xca\x61\xd4\xcf\xd3\x7f\x2d\xa1\x6b\x4a\xd2\x3a\xf4\xba\x96\x79\x6b\xe3\x46\x68\xdd\xb8\x51\x99\xf1\x7f\xc1\x2e\xa6\x0c\x51\x9c\xe0\xd3\xcc\x07\x80\x03\x45\x58\x77\x84\x59\x0b\x14\x90\x21\x97\x55\xac\xb0\x8b\x5d\x19\xf2\xc4\xaa\xbf\xec\x57\xd6\x77\x56\x28\x7f\x86\x76\x25\x06\x00\x4c\x7f\xa2\x38\xc1\x03\x99\xd3\x80\x23\xba\x9d\xaa\x33\x1a\xb2\x4d\x00\x35\xa6\x41\x0f\x45\xc4\xab\xd2\x9f\xc0\x8d\xb3\x7f\xf9\xf8\xca\xaf\x15\x27\x7c\x5d\x69\x82\x56\xe5\x2f\x44\xcf\x1b\xaf\x38\xc1\x4e\x10\x02\x1c\x28\xd6\x74\x58\x5d\xce\x3a\x97\xa7\x22\x56\xf0\x66\xc8\x2b\xe3\x9d\x54\xa8\x4c\x79\x1c\xd6\x15\x2b\x5f\x76\x7e\xb0\x73\xe3\xba\x7b\x01\x54\xda\x51\x5f\xb4\x36\x88\x5e\x9d\xd7\x06\x9b\x6b\xa3\x06\x46\x59\x5e\x69\x2f\x83\xf3\x94\x77\x8b\xe1\x7b\x4e\xc5\xf9\xf0\xc6\x75\x5d\x1f\x74\x02\x2a\xf3\x52\xfa\x34\x5c\x9b\xd9\xf8\xcf\x94\x03\xe9\xcb\xc8\x81\x6d\xb7\xcd\x9f\x73\xd7\x5d\x73\xe6\xac\x59\xd2\x18\xab\x6b\x6e\xae\x13\x87\x29\x2f\xce\xbc\x6d\xd5\xf4\x59\x2b\x97\x77\xe6\xc4\x40\x00\x33\xf7\x51\x23\xc0\x7f\xd0\xf7\xff\x30\xfd\xfe\x36\xa2\x02\xd3\xab\x34\xfd\x9e\x52\x5e\xa6\x86\x43\x99\xbe\x17\xcb\x5c\x25\x17\xcb\x5c\x7f\x43\xde\x52\x5e\xee\x23\x6f\x51\xc3\x2f\x92\xb7\x28\xe5\x03\x6a\x38\xdc\x4a\xdf\x0b\x74\x40\x00\x43\x51\x6f\x25\x8b\xa8\x19\x78\x0c\x61\x0c\x6c\x49\xfa\x2c\x51\x6a\x10\xb2\x2b\x25\x1b\x30\x6a\x1a\x87\xb3\x71\xb4\x81\x40\x6d\x20\x15\xda\x1b\xe5\x83\xd7\x6b\x67\xdf\xd2\xd4\x05\x5b\x7e\x59\x35\x77\x59\xc3\x26\x7a\x85\xeb\xd1\xc7\x0a\x9b\x8e\x0e\x75\xdd\xbb\xaf\xb0\x21\x81\x69\x95\x4e\x2b\x77\x82\x3f\x64\xee\x01\x2e\xb4\xb7\xbf\x8f\x3c\x7b\x19\x59\x36\x9d\xbe\xa4\x2c\xab\xdc\x79\xb1\x2c\x9b\xd9\x01\xb7\xc3\x06\xce\x89\xd7\xcc\x68\xcd\xba\x60\x65\x82\x92\x2b\x94\xb4\xaa\xda\x7b\x81\x26\x09\xda\x98\x60\xc2\xc4\x01\x5d\x30\x69\xc7\x17\xb2\x09\xc3\xa4\xe8\x63\x31\xd9\xce\xa9\x75\x76\x40\xef\x45\xe3\xc8\x7b\xbf\x54\xcb\x31\xdd\x3d\x61\x4c\x4d\xe3\x75\xa3\xc5\x28\xbc\xa0\xa6\x93\xd2\xcf\x8c\x9b\x5e\xdf\xd8\x36\x23\x8a\xd6\xcc\x44\xc6\x07\x0e\xb0\x2b\x00\x0b\x42\x00\x31\x1d\xc8\xa4\xe2\x0c\xd4\xce\x4b\xcd\x4a\xc1\x62\x12\xc4\x59\xa0\x69\xdb\xe8\xc9\x82\xdf\x15\x70\x1d\x80\x13\x3e\x63\x7c\x70\xc2\x92\xcf\xc8\x1a\xec\xd5\x1e\xb1\x2f\x68\x5a\x2c\xa3\xb6\xc7\x68\x0a\x5e\xde\xc1\x8c\xda\x43\x87\x72\xe4\x00\x9c\xb0\x84\xe5\x96\x28\x2f\x6a\xed\xc1\xcf\xc0\x01\x7a\x48\xb6\x3d\x9a\xb9\xc4\x69\xa1\xb5\x97\x3b\x30\x70\xff\x44\x97\xe8\x3a\xb0\xe4\x33\xf8\x19\x9c\xf0\xd9\x92\x4b\xb4\x85\xfa\x76\xd1\x49\xa6\x8d\x35\x77\x98\xe1\xbe\x89\x11\x51\x38\xf0\xd9\x12\xf8\xd9\x92\xcf\x94\x17\x01\x4c\x1f\x53\x26\xc2\x71\x99\xfd\x80\x07\x43\x80\xc4\x87\x10\xa3\x25\x67\x83\x4c\xb1\x29\x75\xb3\x48\x90\x18\x09\xf8\x53\x49\x8a\xb0\x02\x0a\x83\x3a\xaa\xac\x00\x20\x86\xe9\xf2\x47\x44\xc1\x9f\x3e\xb6\x82\x3a\xb0\xf2\xc2\xd2\xc9\x6f\xbf\xad\x1c\xc4\xeb\x53\x6b\x1f\xf7\x95\x0d\xa1\x56\xf3\xba\x84\xfb\xca\x6a\xcd\x6a\x1f\x30\x7a\xad\x4d\x17\x6a\x91\xf6\xa1\x06\xbb\xc8\x7a\x4f\x2a\x4e\x38\x11\x3c\x01\xf4\x88\xe7\x21\x59\x40\x75\x13\x19\x42\x40\xa6\xd1\x7a\x02\x7a\x7c\x7c\x41\x17\xeb\x77\xf9\x59\x17\x4c\x27\x29\x4a\x39\x4b\x1d\x4c\x77\x40\x4b\x5a\x59\x05\x85\x35\x5b\xd7\x3e\xb8\x06\x0a\x00\xa6\xfb\x33\x3d\xca\xea\xef\x69\x47\xcc\x6e\xcf\x74\xff\x3e\x86\x44\x98\xfe\x98\xe9\xc9\x3c\xf2\xfd\xed\x9b\x39\x66\x93\xfe\xf8\x12\x06\x4e\xa8\x9c\x60\x7a\xe0\x30\x6c\x93\xae\xba\x92\x4d\xfa\xb2\xf6\x68\xe5\xc4\x15\xed\xd1\x17\x64\xa6\x27\xf3\x04\xd6\x81\xff\x31\x9e\x71\x41\xfe\xbe\xfa\x2f\xcc\x2c\x60\x7a\xe0\xcf\xb1\x0d\xf9\xca\x36\x51\x24\x22\x3c\x9a\x35\x1f\xc3\xcc\x78\x2e\x48\xad\xe3\x8e\x01\x1a\x38\xfa\xfe\x4e\xfd\xb6\xe4\xa3\x2d\x3e\x2e\x88\x0d\xa8\x30\xb3\x8f\xe9\x81\x5f\x61\xdb\x4c\xd3\xdf\x61\x9b\xc9\xd9\x65\xe8\x5e\x76\x99\x29\x97\x31\xcb\x40\x70\x0d\x0b\x60\x3f\x6c\x93\x29\xbd\x82\x4d\x06\xa8\xfa\x01\xe1\x69\xd7\xf4\x35\xc7\x00\x2a\xb3\x8f\x35\xc1\x53\xec\x69\x60\x00\x6e\x50\x87\x57\xb6\x13\xcf\x7a\x98\x09\x4a\x96\xb0\xfa\x4e\x03\x26\x65\x9d\x29\x89\xb5\xc9\x46\x82\x66\xa1\x71\x4f\xd2\x78\x45\x1e\xf3\x9c\x32\x38\xdc\x11\xab\xa9\xaa\x83\xcb\x86\xd6\x0d\xe8\xdf\x34\xb0\xa2\x8e\x9d\x25\xb6\x76\xd4\xb5\x0d\x1c\x50\xdf\x52\x53\x51\x3f\x72\x20\xd9\xa3\xcc\x4b\x99\x12\x6e\x1b\x70\x80\xeb\xb0\x7c\x68\xa2\xc1\x08\x26\x88\x56\x06\x16\x02\x9c\x21\xc9\x78\x4a\x02\xe1\xa4\x81\x90\xcc\x40\x60\xaf\x38\x53\x0a\x63\xaa\xcb\x26\x52\x91\x19\xf3\x74\x20\x9b\x88\x75\x41\xb2\x93\xb8\x10\x18\xc9\xf3\x59\xa9\x09\x81\xe9\x63\x03\xaf\x5e\x76\xfb\xb2\x99\xde\x65\xce\xa9\xd3\x9b\x44\x3f\x57\x38\xdf\x32\xf1\x9a\xeb\x6f\xf2\x2c\x3a\x64\x15\x07\xf5\x2f\x42\xf4\x48\x31\x3d\xf0\x27\xaa\x7d\xaa\xf5\x87\xc8\x25\x3f\x4c\x26\xf1\x7c\x2f\xd3\x14\xa0\x32\xc3\x98\x1e\xaa\x41\xb5\xdf\x5c\x59\x96\xa0\x2f\x21\x4b\xbc\xf6\xb7\x4d\x37\x00\x2a\x6f\x30\x3d\xb0\x19\xfb\x89\xaa\xaf\xe4\x27\xba\x92\x8f\x48\x79\xe3\xff\x17\x1f\x11\x95\x39\xc0\x9c\x80\xef\xe0\x76\x79\x70\x33\x6a\x59\x8d\x22\x55\x5b\x8f\x53\x2c\x17\x0e\x87\xb3\xee\x0c\x5d\xf6\x41\x94\x1a\x74\xa0\x96\x86\xa2\xf1\xad\x2c\x64\x3b\xb6\xf6\xf0\xbd\xbb\x71\x74\xd8\x8e\xb3\x0f\xe4\xf7\x87\x76\x88\xb4\xe8\x10\xe9\x89\x6d\xcf\x8d\x7e\xb4\x4d\xeb\x57\xb6\x6f\x17\x2c\x4c\x8f\xf2\x2a\xe6\xf3\xff\x74\x19\xed\x82\xa5\xb7\x8c\xc6\x99\x2e\x92\xd1\xa8\xcc\x7e\xa6\x07\x7e\xcd\xbd\x0a\x4c\xc0\x83\x76\x98\x21\x24\xb3\x5c\x2a\xce\x1a\xb0\x10\xc2\x63\xae\x84\x56\xb6\x4d\x9f\x5d\xd9\x39\xe6\x64\x46\x62\xb6\x11\x03\x69\xf3\x30\x98\xd4\xa9\x8b\xdc\x2c\xd8\x65\x03\x1b\xcb\x72\x2a\x8d\x51\x45\x73\x8c\x60\x32\xb5\x70\xcf\xbe\x7e\x88\x65\xad\xdc\xd2\xdd\xd2\x30\x6d\x64\xcd\x80\x28\x62\x5d\x77\xdf\xad\xfc\xf7\xda\xcf\x1a\xaf\x9e\x36\x64\x6c\x98\xc8\x26\x2b\x99\x1e\x78\x9c\xfd\x02\x98\x10\xcf\x34\xe0\xf3\x20\x6e\xc0\x51\xde\x06\xa0\xba\x08\xcc\x7d\x36\x1c\x9f\xdb\x70\xbc\x09\xe7\x95\xa0\x9e\xd8\xfd\x61\xb7\x8b\x0f\x60\xc7\xf4\xd6\x66\x68\x5d\xb1\x95\x5e\x38\xe6\xc6\xfd\x01\xa6\x07\x3a\x6e\x5f\x5c\x33\xb4\x65\x1d\x7e\xde\x1b\xf4\x71\x78\x23\x8e\x03\x28\xbd\x42\x6c\x02\x6a\x90\xc4\x25\x0c\xbe\x38\x2e\x01\xb7\xf1\x23\xac\x27\x96\x5e\x21\x2e\x01\x77\x8a\x68\x89\x83\x2f\x1d\x93\x30\x80\x3e\x0e\xce\xe1\xbe\x78\x2f\x17\x93\x90\x8b\x47\x18\x70\x51\x3c\xc2\x3f\xab\x1f\xca\x9b\xca\x4d\xa0\xf0\x07\xfb\xfd\xde\xbc\xc8\xef\xf7\x98\x72\x13\xb8\xfa\xef\xf2\xfb\x3d\x76\x09\xbf\x1f\x54\xf6\x28\xad\xa0\x35\x73\x12\xf0\x60\x01\xe6\x17\x3c\xf6\xea\x48\x54\xd6\xa7\xc3\xe9\x91\xb4\xd8\xd7\xa7\xd3\xdb\xa5\xf4\xdc\xd9\xf7\x08\x04\x67\x77\x16\xa5\x21\x41\x71\xb4\x23\x98\xe0\x39\xe2\xbc\xa1\x19\xbe\x8f\xf3\x86\x0e\x44\x95\x3d\x45\xbf\x2f\xbe\x77\xc2\x3d\x25\xca\xc9\xb5\x9b\x95\xb5\x9b\x01\xf6\x33\xb5\x82\x0a\xdc\x9f\x79\x40\x33\x91\x70\x58\xfc\xe6\xd0\x4e\x02\xe1\x3c\x83\x09\x66\x69\x2a\xa7\x71\xa7\x12\x3c\x05\x75\x41\x19\xb8\x31\x9f\xe1\xd5\xae\x6d\x3b\x7b\x27\xf1\x76\xd9\x12\x34\x4f\x61\xf8\x3e\x52\xcf\x8c\xcb\xf6\xc6\x41\x1c\x49\x4a\xd7\x84\xae\xe2\x33\xde\x33\x25\x4a\x2b\xdc\xbc\x79\x2d\x99\xb7\xcc\x72\xe6\x3d\x6a\x16\xb7\x10\xb0\xa0\x0d\xd3\x87\xed\x4b\x1f\x8d\x22\x59\x33\x9e\xea\xd4\xba\x8f\x80\x56\x74\x13\x1c\xc1\x7c\x97\x1e\x1d\xf5\xd3\x01\xc7\xb6\x22\xea\xf4\xe4\xae\x61\xec\x97\xb7\x2b\xf3\xa0\x0f\x3f\xeb\x30\xb3\x1c\xce\xe7\x9c\x80\xd7\xfc\xf0\x2c\xa9\x2d\x47\xbc\x85\x2c\x5a\x23\x34\x54\xed\x0f\x74\xb4\xc1\x81\xd6\x5b\x7b\xe1\xde\xea\xd7\x74\x95\xff\xc5\x2c\xdf\x50\x0e\x81\xfb\x85\x77\x01\x54\xfe\xa8\x44\x32\xdf\x66\x3e\xfd\x21\xfe\x4d\xd8\xcb\xbf\xa9\xfc\x31\xe7\xe0\x54\xfe\x27\xcf\xc1\x09\x95\xf9\xca\x44\x10\xfa\xdf\xf0\x6f\xce\xf7\x3e\x1c\xdc\x1c\xdc\x99\xef\xdf\xdc\xa5\x4c\x04\x53\xff\x77\xfc\x9b\xbb\x0a\xe0\x8b\x05\x0f\x07\xbb\x6a\x34\xff\xe6\x7a\xa5\x06\x8c\xc2\xfe\xcd\xbb\xfe\x0e\xff\xa6\xe1\x94\xac\x77\xa7\x12\xb4\xde\xa0\x0b\x66\x87\xad\x3a\x36\x7f\x58\x01\xd1\xbe\xbe\xcd\xf5\xde\x9d\xbe\xcd\xbe\x87\xbd\xdb\x7d\x5d\xa5\x79\xbe\x4d\x65\xa2\x72\x0c\x3c\x86\x7d\x9b\x25\xda\x5a\x21\xe6\xe4\x4b\xc5\x20\x4c\xf4\x52\x55\x5e\xe5\xd8\xda\xb5\x44\xc7\xfa\x44\x29\xcc\xec\x06\x13\x81\x19\x74\xe0\xf5\x41\xe9\x52\x71\x0a\xcb\xd0\x14\x89\xb6\xc5\xcb\x84\x3b\x95\x3d\x98\x77\x9c\xbd\x5f\xcd\x79\xbb\x4c\x4c\x2d\x90\x29\x23\x06\x62\x21\x48\xd7\x0d\x5a\x0c\x6d\x55\xfa\x93\xca\xfa\xc8\x60\x53\xeb\xfe\xd6\xa2\x3b\x16\xb7\x89\xca\x49\x47\x43\x0c\x8a\xca\xb1\x0d\xab\x0b\xc8\xfe\x6a\x52\x0a\xc1\x4e\x30\x11\xd8\xc0\x23\x38\x76\x49\xaf\xd3\xaa\x0b\x48\x30\x2c\xf3\xb6\x14\x7a\x20\xa3\x09\x2b\x74\x08\xc3\x5e\xa2\x3e\xbd\xf1\x55\x97\x06\xec\x8e\xdd\x41\xd0\x26\xb3\xf4\x39\x46\x62\x6c\x32\x4d\x9f\x3b\x3a\xec\xc0\xd9\x74\x2f\x78\xf7\x8b\x40\xdd\x19\x16\x52\x24\x28\x5a\x66\xa9\xbc\x2a\xa8\x92\x25\x06\x64\xbd\x05\x97\x68\x24\x00\xed\xf9\x41\xa7\x95\xaf\x33\x6d\x7b\x9b\xb8\x91\xf5\xb5\x91\xb1\x73\x96\x29\x3d\xd6\x12\x78\x9d\xf2\x4e\x99\x75\xb8\x63\x57\xc1\x1c\x00\x2f\xec\x55\x9e\x48\xaf\xcd\xac\x03\x46\xa4\x2f\xe8\xf3\xf4\x05\x82\xe6\xc3\x19\x53\xe8\x3f\xe8\xed\x4d\xbd\xb0\x77\x64\xfd\xa0\x81\x23\x07\xf5\x6f\x54\xce\xc7\xda\xeb\xfb\x0f\x19\x3b\x08\x00\x4a\xb9\x5a\x79\x02\xdc\x9e\x99\xf3\x77\xea\x0c\xf0\xd2\x3a\x83\x72\xf5\x45\x4a\x83\xf2\x65\x5f\xa5\x81\x52\xee\x54\x06\x81\xc1\x99\xff\xfc\x67\xc9\xe7\xec\x65\xe4\x73\xe5\xce\x8b\x04\xf4\x73\x97\x90\xcf\xa1\xd2\xad\x0c\xc9\x7c\x97\xd9\x08\xf4\xa0\xb0\xef\xb9\x87\x38\x8d\x35\xd5\xfb\xb0\xeb\xae\xe8\x28\x3a\xe0\xd8\xd2\x34\x4b\x99\xd8\xf4\xc2\x68\xa7\x78\x72\x30\x80\x99\x66\xc5\x09\x7e\x09\x00\x10\x40\x0d\x88\xeb\x00\x08\x4a\x56\x35\x3c\xcf\x8e\x99\xb7\xc9\x9c\x92\x4d\x8c\x1a\x0c\x0d\x64\x1d\xa5\xad\x01\xb7\x88\x53\xc1\xa3\x22\xaf\x66\xbc\x1e\x2f\x1b\xb0\xbf\xe9\x9a\xd9\xb7\x0c\xd9\xf8\xdc\xbd\xd1\x0a\x65\x8b\x6e\x49\x45\xc8\x90\x5c\x59\xb9\x6a\xf6\x2a\x52\x9f\x47\xf9\x50\x19\x01\x6a\xb1\xaf\xbb\xf2\x0a\xbe\xee\x3c\x3f\x37\xec\xeb\xe7\x56\x3e\xbc\xbc\xa3\xfb\x7f\x2d\xb6\x29\xfd\xae\xd2\x0a\xbe\xc4\x3c\xf7\x36\x2c\x49\xe7\xce\x3b\x0e\x6a\xa7\x70\x1c\xd0\x4c\x38\x1c\xce\xf7\x57\xf0\x6a\x0e\x98\x3b\x15\xa7\x19\x7c\x3e\x53\xfa\xde\x15\x98\x48\x62\x03\x46\x9e\xce\xdd\x24\xc7\x41\x1c\x62\xe7\xad\xd6\x29\x3f\x1d\x88\xfa\xf9\xf4\xbb\xed\xd4\xe9\xf6\xae\x3a\x25\x5a\xa7\xb4\xc2\x69\xca\x9e\x8f\x3e\x42\xfd\xfb\x46\xd9\x05\x99\xcc\x46\x50\x82\xe4\x95\xe2\x90\xe4\x11\x65\x9e\x49\x49\xd6\x70\x9c\x2f\xc6\xfe\x12\x87\x3e\x28\x53\x06\xd4\xbb\xd2\x3c\x93\x20\xda\x1a\x06\x18\x54\x83\x86\xd4\xac\xeb\xa4\x83\x2c\x59\x03\x4b\x92\xa8\x8c\xd8\x4f\x6c\xb7\xcb\x56\x0f\x06\x81\x2c\x16\xec\x52\x11\x5e\xbc\x51\x51\xc5\x29\xce\xfe\xb5\x50\x81\xf2\xca\x2a\x2e\x50\x9e\xfe\x46\x77\x33\x7f\xa3\x38\xd6\x36\x83\x9b\x26\x5e\x63\x5b\xca\x8f\xb9\x65\xf0\xd5\xe3\x1c\x23\x67\x76\x9f\xe8\x5f\x56\x58\x34\xa1\x75\xa4\xd7\x3d\xb1\x75\xe4\xc8\x45\x4d\xfd\x02\xa3\xc9\xda\xb8\x5e\x59\x00\xfe\xf5\x1f\xf4\xd7\x5c\x7f\x45\x7f\x0d\x54\x5c\xca\x3c\xf0\x60\xe6\xe7\xc4\xc6\x64\x46\x72\x5d\xd6\xfc\x65\x09\x49\xe6\xdc\x33\x28\xb3\xa0\x16\x65\xc8\x37\x31\x05\x14\x57\x9e\x8d\x69\x95\x72\x77\x1f\x1b\x93\x72\xa3\x72\x0f\xd8\x97\x79\x9c\xd8\x61\x90\xc6\xc3\xf7\xd2\x78\x60\x58\x7b\x4e\xce\xa2\x98\xa7\xdf\xf0\x14\x29\xd3\x8b\x4e\xe4\x3c\x33\x4c\x44\xb9\x31\xdf\x10\xb3\x5e\x35\xc3\x2c\xc2\x7e\x9d\x4d\xa0\x2b\xf3\xe8\x3f\xac\xc3\xc0\x7c\x1d\x46\x19\x92\xa7\xc4\x28\x9b\x72\x4a\x0c\x4c\xa7\x94\x7b\xc1\xbf\x67\x1e\xfa\xc7\xed\xee\xa9\x4b\xdb\xdd\xef\xbd\xd8\x86\xa6\x8c\x57\x7e\x0d\x76\x7d\xdf\xb8\xc2\xf1\xbd\xe2\x0a\xd3\x7b\x95\x13\xd0\x90\x69\xcb\xd9\xd1\x72\xf2\x80\xfa\x8b\xf4\x5e\x2f\x3d\xa6\x48\x39\xb1\x71\x23\x00\x74\xfa\x99\xf4\x7e\x58\x9a\x79\xfb\xca\xfe\x3c\xa8\xf9\xf3\xd2\xcf\xe4\x39\xf4\x94\x58\xd6\xa1\x07\x95\xfb\xe1\x3e\xb8\x92\xfa\xf9\x3f\x4c\x27\xe5\xfe\x4b\xd2\x09\xee\xbb\x04\x9d\x76\x43\x05\xce\xa0\x1e\xb8\x8c\xcd\x10\x53\x67\xb7\x8f\x7a\xa6\x14\x2a\x58\x56\x4a\x8f\x85\x0a\x75\xf8\x8a\xdf\x4f\x8f\xf5\xb3\x63\xca\xd4\xef\x2b\xa7\xe1\x2a\x18\xa4\x83\x80\x06\xc5\x40\xa2\x43\x59\x07\x60\x76\x1a\x78\x3c\x0c\x3d\xf4\x40\xe5\x34\xa5\x1b\x9b\xfe\x06\x9e\x85\xb1\x75\xca\x9b\x00\xa6\x7f\x93\xd9\x42\xd5\x71\x36\x40\x03\xc0\x42\x11\xa6\x7f\x43\x1f\x7b\xf6\xc2\x88\x55\x5c\xd7\xb9\x35\xb8\xef\x7f\x52\x22\x99\xbf\x6a\xb2\xf9\xf7\x8b\x6b\x84\xbd\xe2\x1a\x95\x3f\x65\x03\x1b\x95\x48\x7e\x60\x63\x3e\xef\x5e\xa5\xe9\x72\x34\x9a\xd2\x70\x9e\xc3\x21\x0e\x29\x4e\xe3\xdd\x44\x6f\xca\x4b\xf8\xce\x5a\x66\x54\x09\xf6\x85\xb3\xdf\xaa\xbc\x5b\xa6\x3d\xe7\x72\xd7\xf9\x50\x7c\x71\xa2\xda\xe5\x74\x29\x7f\x54\xa4\xd3\xef\xb6\x77\x85\xe0\xaf\x42\xf7\xb6\x23\xde\xfd\xf1\xc7\xca\x1e\x24\x53\xcc\x50\x6a\xc0\xf8\xcc\x49\xbc\xe6\x96\xaa\xa7\x16\x2e\x05\xcf\x86\x91\x36\xce\x89\x98\x1a\x59\xa5\x4e\x8d\xcf\xc3\x47\x58\x92\x26\xef\x49\x36\xfa\x6e\x22\xe0\xd7\xa2\x8e\x31\x81\x73\xb9\x5b\x5c\xad\x44\xdb\x64\xd6\x7f\x8e\x4e\x30\x39\x18\x76\xf5\x54\xa9\x10\xa3\x01\x65\xc6\x64\xf8\xd8\x64\xe5\x2f\x89\xea\x84\x52\x03\x9f\x50\xe6\x2e\xe9\x26\xfb\xe7\x8c\xb2\x0b\xfc\x39\xb3\x11\x94\xa2\x73\xc5\x1b\x92\xec\x22\x92\x74\x24\x3e\x1c\xf7\x62\xed\xd3\x0b\xf4\x41\xd9\xe4\x42\x94\xc3\x75\x35\x93\xa5\x84\xcf\x94\xda\x64\x37\x0c\xaa\x6b\x5b\x72\x61\xd3\xa9\x6a\x48\x95\xdd\xa5\x82\x5d\xa6\xbd\x31\x9c\x9e\xcb\x62\x2c\x65\x3e\x06\x64\xda\xab\xea\x70\x24\xa5\x4e\x4d\xa6\x0b\xa8\x12\x51\xee\x4d\xfa\x8c\x7b\xe7\xe2\xa5\x15\xad\xcb\x26\xcc\xd4\x2f\xe5\xca\x1b\xc5\xb1\x96\xd9\x6c\xa0\x51\x1c\x67\x51\x76\x2d\x5d\xdf\xd6\x36\x61\x42\x45\x59\xb1\xcb\x1f\x69\x1d\xe9\x75\x95\x47\x5a\x47\x62\x79\xfa\xfd\x7f\x3c\x7e\xab\x66\xe7\x8c\x05\x33\x76\x8e\x7a\x78\xe6\xa2\x19\x3b\xfb\xc4\x6f\xc1\xcc\x05\xe6\x29\xb8\x81\xfb\x33\x70\x83\x41\xd9\xf5\x6b\x0a\xc9\x46\x86\x54\x9e\x62\x4e\xc9\x4e\x53\x4a\xd2\x21\xa9\xc3\x6a\x4a\x01\xd9\x04\xd5\x8c\x4c\x2d\x3e\xb7\x0a\xe3\x95\x62\x5d\x13\xc3\x1d\x30\xee\xe1\xa3\x03\xfe\x03\x77\x7b\x9a\xc7\xb8\x7d\xc2\x4f\x99\xa7\xe6\xd7\x07\x0a\xc6\x8c\xac\x9c\xb0\x62\x5e\xd4\x67\xab\x1d\xd6\xe8\x9e\x72\x0b\xa0\x32\x4d\x5c\x09\xf5\x29\x7f\x10\xaf\x9d\x8b\xb9\x95\x2e\x3f\xfa\xe0\x75\x2f\xdd\xe1\xbd\xf0\x79\x31\xdd\x51\xcc\x95\x6c\xdc\x08\x2d\x88\xe3\xa1\xbe\x7f\xce\xf4\xc0\xc6\x1f\x1a\x57\x5e\x70\x51\x5c\x39\xd0\x33\x3d\xf0\xd8\xdf\x13\xef\xae\xbf\x74\xbc\xfb\x20\xa6\x87\x2a\xfc\x81\xfe\x1a\xfa\x12\x3c\xf4\xdf\xbe\xaf\xbb\x06\x40\x50\xcc\x2c\x85\x93\xd8\xc3\x40\x0f\xbc\x00\xc3\x11\xab\x9e\x41\x3c\x0a\xe6\x94\xcc\x62\x89\x3a\xd7\xf5\x62\x55\xa0\x66\x96\x7a\x35\x81\x1a\xc7\x85\xdc\xc1\xfc\x1b\xfc\x0f\x6e\x35\x30\x00\x07\x28\x05\x3f\xc2\x5a\x4a\x71\x56\x4b\xf1\x68\xdb\x45\x53\x4f\x9c\xa4\x9e\x86\x54\x68\x93\xac\x68\x8d\x60\xa8\xe3\x90\x6c\x75\xa5\x64\x0b\x2b\xd8\x65\xa3\x23\x16\x93\xad\x4e\xc1\x2e\x7b\x8a\x71\x90\xb9\x4e\xb0\xc7\x8d\x26\x47\x2c\x6b\xe4\x57\x75\x88\x48\x03\xe9\x97\x27\x77\x6f\x53\x53\x6d\x47\xd3\x80\x8a\xba\x8f\xe7\x85\xdf\x14\x1f\x1f\x79\x73\x53\xed\x75\x43\x82\x15\x75\x6c\x65\x7d\x4b\x47\xfd\xc8\x81\x11\xf7\xe1\xb5\xce\xd1\x3f\x6b\x36\xd6\xb7\x74\x84\x47\x0f\x04\x30\x63\x51\x9a\x80\x37\xb3\x01\x08\x40\xc4\xb5\xfc\x0d\x6c\x2a\x6e\xc0\x59\xbd\x06\xec\x03\x56\x6b\xfa\x5b\x52\x04\x0f\x9c\xb6\xa2\x1e\x19\xac\xaa\xa2\x4b\xd7\x37\x43\xd1\x02\x3d\xa4\x44\x0c\xea\xc0\x59\xae\x64\x97\xd9\x46\xf9\x0a\x1c\x15\x35\x23\x46\xdf\xa0\xbc\xeb\xf6\x6e\x18\xde\xae\x2f\x2c\x34\xae\x72\xb4\x03\xa8\x7c\xcd\x1c\xa3\xd6\x71\x85\xff\x3c\xd9\x3a\xc7\x9f\xf3\x64\x6b\x0d\x33\xe8\x0a\xb2\xb5\xf2\xf5\x18\x7a\x78\x7b\x57\x5d\xfa\x9d\x10\x73\x0c\xfe\x48\x79\xfe\xe3\x8f\x91\x4c\x70\x24\xbd\x1f\x36\x7c\x7f\x99\xe0\xc8\xa5\x65\x02\x4a\xb9\x4e\x99\x01\x6e\xc5\xba\xc9\xff\x7d\x5f\x01\x54\x7d\x05\xca\x75\xaa\xb3\x80\xe8\x36\xd9\xdc\x8d\x63\x8a\x13\x74\x64\x36\x03\x16\x0c\x07\xe8\x40\xa7\xc5\x5e\x56\xbd\xbe\x76\xbc\x9f\x7e\x45\x5d\xd6\x8e\xc7\x46\x11\x35\x95\x63\x5e\xb8\x76\xfc\x66\xf1\x9b\xb5\xca\xb6\x6f\x08\x9f\x19\xc1\x3c\x40\xd5\x70\x35\xa0\x10\xc9\xaa\x56\x9c\x61\xaa\xe7\x53\x09\xb7\xde\xaa\x0b\xe2\xcd\x6d\x0a\xab\x00\x26\xc9\x42\xf5\xb0\x77\x23\x55\x59\x70\xc6\x62\x32\xa5\x57\x2b\xee\x91\x3d\x8e\x98\xb2\x5b\xdb\xe6\x55\x7c\x15\x46\xd8\xe7\x8f\x45\x93\x83\x5b\x5a\xa7\x8d\xa8\xf2\xe1\xbd\x7e\x20\x3a\x76\xcc\x8f\xda\xcb\x4a\x06\xd6\xe1\xdd\x5e\xb1\x22\xba\xdc\x8d\xf6\x7b\x68\x5d\xe3\x6a\x2b\xda\xf1\x74\x66\x32\xf3\x34\xd5\xca\x77\x02\x17\x28\x03\x41\xb0\x0e\x48\xa5\xa1\x64\x21\xd9\xa4\x97\xe6\x38\x52\x75\x28\xd9\x4f\xb5\x30\x0c\xcc\xe3\x3d\xe8\x8c\xf3\xc3\xa0\x5c\xe9\x4c\x25\xbc\x95\x7e\x5d\x50\x76\x3b\x09\x96\xa2\x33\x25\xbb\x5d\x82\x5d\xb2\xe3\x62\xf2\x36\xaa\x34\x16\x8b\x49\x5e\x0c\x2a\x55\x29\x24\x59\xde\xdc\xaf\xba\x9f\x27\x76\x19\xde\x95\xb7\x8f\xf3\x3c\xa9\xfb\x63\x89\x81\xd7\x8e\x6e\xf2\x06\xeb\x0b\x96\xb4\xed\x57\x39\x9a\xeb\xd6\xa6\x41\x1d\xb1\xda\xca\xf0\xa2\xa6\x50\x47\xac\xa6\x32\xcc\xae\x83\x5c\x20\x18\x88\x0c\x53\x39\xdc\x96\xfa\xe1\xd7\xd5\xb5\x0d\xa4\x2a\xc5\x96\x8e\xf0\xa8\x81\xd8\x47\xd3\xce\x9c\xa6\xa6\x72\xbf\x01\x2e\x30\x00\x34\x10\x2e\xcb\xe6\x8f\x99\xc5\x63\xae\x0a\xc9\x05\x6c\x4a\x2a\x0b\x27\x4a\x0a\xaa\x74\x41\x39\xc0\xa6\x24\x77\x18\x4a\x41\x7c\xbe\x34\x88\x61\x35\xa0\x5a\xc4\x01\xd5\x24\x2f\xbb\xf7\x5d\x72\xf3\x70\x4c\x6a\xbe\x2e\x30\xbc\xb8\xaa\xae\x78\x41\xf3\x0b\x03\xc6\x56\xb4\xd5\x04\x45\x4f\x4d\x4c\x1e\x7c\x03\xba\x2b\x7a\xe7\x37\xef\x1f\x36\x1d\xdd\x74\x33\xa7\x3f\xac\xb1\xfb\x06\x34\x7c\xe8\x73\x06\x6b\x44\xe8\xfb\xb0\xc6\x51\x3a\xa0\xe1\x43\x31\x58\x1b\x46\x72\x89\xa2\x34\x83\x37\x33\x2f\x11\xbb\x87\x0e\xf7\x9a\x04\x43\x50\x3a\xa4\x1b\xe2\xf4\x1b\x58\xc1\x8b\x51\x0f\x1b\x0d\xf0\x69\x05\x56\x79\xdf\xf6\xf6\x28\xa7\x8b\xde\xf2\x2a\x17\x8e\xad\x5f\x7f\xec\x95\xf5\xeb\xb5\x75\x2f\x66\xde\x01\x1c\x18\x0b\x24\x36\x24\x31\xf9\x71\x6d\x12\x9b\x33\xd6\xaa\x2b\xde\x22\x71\xd8\x5a\x4b\x77\x03\x6c\x2b\xcf\x05\x56\x13\x47\x85\x0c\x28\xac\x96\x46\x3d\xd8\x4c\x79\xec\x0f\xdb\xd7\x88\x5d\x91\x6f\x5e\x7f\xfd\x1b\xb4\x09\x0a\xd2\x15\x00\x50\x1f\xb0\x87\x01\x0b\xf4\xc0\x0a\x0a\x41\x00\xd4\x60\xcc\xc7\xab\xc1\xf5\x60\x12\xb8\x11\xcc\x06\x8b\xc0\x4a\xb0\x0e\x74\x81\xed\xe0\x71\xb0\x1b\x1c\x00\x12\x38\x0c\x8e\x52\x5a\xb5\x98\x09\x3f\x15\xb1\x04\x26\xdf\xf0\x62\x38\x8c\x6f\x69\x6a\xf2\xc1\xb0\x04\x6d\xd2\x74\xc4\x0c\x66\x31\xa9\xb8\x91\x02\x41\x79\x4a\x5c\x14\x65\x0b\x93\x92\x27\xcb\xe1\x30\xbe\x95\x34\x90\x6f\x27\xc3\x92\xc1\x26\x75\x94\x9d\x12\xa4\x3b\x44\x79\x1c\x93\x92\x56\xe3\x3b\x0b\xd1\xef\xe7\x32\xa9\xf8\x60\x08\x82\xd2\x7d\xa2\xdc\xcc\xa4\xa4\x6d\xe1\xe4\x98\x11\x60\xb0\x39\x28\x2d\x15\xe5\x31\x4c\x4a\x5a\x11\x4e\x46\x06\xe1\x1b\x77\x89\x72\x84\x49\x49\x9b\xc3\xc9\x12\x3f\xbe\xf1\x98\x28\x97\x30\x29\xe9\xe1\x70\x92\xe7\xf0\x8d\x23\x62\x92\x27\xcf\x7c\x29\x9c\x28\xe0\x39\x5d\x50\x7a\x41\x94\xed\x4c\x4a\xfa\x49\x38\x59\x15\xc4\xdf\x79\x4e\x94\xab\x98\x94\xf4\xe3\x30\x94\x7e\x41\xec\x81\x86\x70\x58\xf5\x06\xca\x3a\x4b\x38\x9c\x64\x8d\xb8\x09\x53\x18\x09\xd9\x2e\x24\xf9\xda\xc8\xb6\xb3\x85\xd4\x0d\x98\x28\x62\x81\x2e\x28\xf5\x13\x93\x3e\xf2\x49\x75\x18\x09\xbd\xb5\x30\x28\x35\x86\x93\x61\x72\x6f\x68\x58\x0a\xdb\xe4\x09\x30\x28\x4d\x0e\x27\x27\x91\x36\xa7\x86\x13\xa3\x26\x4d\xd0\x05\x93\xad\xe4\x3b\xad\x21\x69\xac\x98\x1c\x45\x2e\xc6\x87\x13\x33\xf0\x87\xd3\xc8\xf5\xb4\x90\xd4\x29\x26\x67\x90\x8b\xf9\xe1\xc4\x62\xf4\xa1\x74\x9b\x98\x5c\x46\x6e\xdd\x1e\x96\x26\xd9\xe4\x1d\x30\x28\x3d\x11\x4e\xee\x22\xf7\x9e\x09\x27\xee\xde\xb5\x43\x17\x4c\xde\x49\xae\xef\x0c\x49\xf7\x8a\xc9\xbb\xc9\xc5\xfd\x61\x69\x87\x4d\x7a\x1e\x8d\x68\x1f\xb9\xb3\xcb\x26\xff\x0c\x06\xe5\x43\x47\xc2\xe1\xa4\x44\x48\x90\x78\x39\x1c\x96\x59\x5a\xb0\xcb\xf6\x82\x58\x0c\xa3\x7b\x27\x4a\xfc\x55\xc1\x7e\x9e\x98\xbc\x6b\x87\x60\x3f\xf4\x93\x17\x7e\xfa\xa2\x1c\x47\x97\xfb\x9e\x17\xec\x89\x87\x1f\xfb\xf1\x73\x18\xad\x02\xd2\x82\xfd\x50\xeb\xa8\x69\x33\x16\x2f\x43\x1f\x8e\xeb\x10\xec\x72\xe7\xfc\x58\x4c\x9e\xbb\x50\xb0\x27\xc6\x8e\xbf\xed\x76\x8c\xb5\xe4\xc7\xb1\x56\x50\x10\x05\x12\x15\xe6\xa8\xd7\xac\x92\x2a\xff\x09\x94\x57\x0a\xd9\x77\xe8\x53\xc2\x87\x84\xfa\x1c\x73\xea\x7d\x2f\x50\xee\x88\xf8\x5d\x30\xe2\x77\xd1\xea\x75\xf6\xfe\xc5\xdf\xbc\x6c\x7b\xe8\x57\xea\x53\x3d\xd9\x66\xc5\x88\x28\x40\x1c\x6c\x56\x08\x45\x21\x5d\xb1\xf4\x3d\xe5\xf8\xd2\xa5\xb0\xf9\xbd\x55\x8d\xde\xe2\x62\x6f\x63\x45\xb1\xb7\x91\xbc\x6b\xf4\x16\x4f\x8e\x36\xfa\x0a\x0b\x7c\xe4\x75\x47\x34\x5a\x5a\x58\x58\x1a\x8d\x46\xa3\x23\xe1\x08\xe5\x18\x1c\xd1\x13\x55\xff\x49\xb9\x8f\xb6\x37\x46\x7d\x05\x85\x3e\xf2\x3a\xa3\x31\x1a\x6d\x2c\x2e\x8e\x46\x1b\xab\xd0\x3b\xe3\xfb\x8b\x95\xe3\xb0\x79\xf1\x62\xd8\xfa\xfe\xcd\xd4\x10\xd8\xaa\xbc\x4a\x0d\x85\xcd\x4b\xdf\x53\x3a\xf1\xef\xd7\xa0\x26\x4a\xe1\x1a\xf4\xf3\x52\x65\x40\x34\x5a\x5c\x5c\x4c\x3d\x89\xff\xa4\x87\xe1\x5e\xd1\x93\xa2\xd1\xe8\x77\xaf\xde\x7c\x33\xdb\xb6\x74\xe9\x77\xbf\x89\x46\x1b\xe9\x43\xd1\x68\xe3\x85\x0f\x72\x9f\xa6\xa7\xe6\xff\x4e\x19\x18\x8d\x46\xe1\xa3\xa8\xc5\x35\xe8\xc3\x69\x37\xbf\xaf\xbc\xca\xb6\x2d\x55\x8e\xbf\x77\xe1\x2b\xd4\x01\x2c\xb7\xea\x98\x97\xe0\x64\xae\x03\x98\x48\xec\x54\x92\x53\x99\x18\x36\xfe\x48\x6c\x38\x69\xc0\x8b\x9d\x14\x3f\xa6\x89\xf8\xdd\x10\xad\xac\xc2\xe2\x3c\xc7\xeb\xaa\x76\x2d\xbd\xd6\xf3\xd1\xe4\xd5\xc7\x99\x97\x16\x14\xb5\x37\xd4\xcd\x5d\x5e\x70\x7f\xe9\x3c\x22\x13\x8f\x64\x5e\x87\xd7\x73\x2b\xfe\xfe\xfc\xf0\x91\x79\xf9\xe1\x1b\xf3\xf3\x02\xa9\xcc\x4e\xa6\x07\x9e\xe1\x5e\x05\x16\x50\x08\xae\x07\x71\x3b\x2e\x00\xa2\xc7\xba\x13\xcd\xa5\xe2\x26\xac\x64\x9a\x90\x0e\xae\xcb\x0a\x07\x16\xb2\x4f\x2c\x24\x1e\xc7\x65\xc4\x45\x32\xf4\x30\xa8\x76\x83\xd8\xd7\x69\x92\xd3\x42\x63\xa0\x9b\x12\xa8\x5a\xb6\x3c\x39\x7b\xfb\x12\xdf\xf3\xf7\xaf\xdc\x42\x2d\x1c\x73\xe3\xde\x8a\xb6\x91\x35\x03\xa2\x57\xd5\x4f\x63\x5f\xbc\xf7\xbe\x3b\x16\xb8\x3d\x43\x47\x6e\x58\x35\x64\x6c\x5d\xa8\xf1\x6a\x74\x46\xbc\xae\x44\x41\x5b\xe6\x18\x30\x82\x61\x00\x9d\x0a\x44\x77\x34\xaa\x01\x82\x58\x77\x94\x0c\x61\xd5\xe5\x2d\x71\x61\x1c\x13\x13\x67\x79\x23\xc6\xee\xa0\x79\xc1\x2e\x53\x3a\xf5\x54\x50\x75\xc9\xaa\xa8\xf2\xfa\xc4\xf9\x9d\x33\xe7\xcc\x9b\xb8\xa0\x73\x46\xe7\x13\x13\xe7\x76\xce\xe8\x5c\x30\x71\xde\x9c\x99\x9d\xc4\x8e\xd8\xa3\x38\x41\x75\xe6\x20\x30\x23\xdd\xc7\x80\x75\x32\x43\xce\x48\xa9\x23\x9c\x8b\x09\xcb\x3a\x33\x1a\x2b\x87\xc7\xca\x22\xd9\x9f\xe3\x35\x27\x79\xcf\xea\xe3\x9e\xd0\x03\xcb\xaf\xf6\xec\x58\x1d\x3a\x5d\x3a\x6f\x7e\xd9\xc8\x68\x68\xde\x18\xd1\x82\x65\x31\x0a\xcb\x7b\x07\xc9\x7a\x21\xf1\x8f\xda\x7a\xe1\x71\xd0\x13\x43\xd6\x0b\xf6\xfc\x60\x8b\x24\x4f\x56\x4a\x00\x2f\x1b\xc5\xf3\x9b\xce\x5b\x4f\x78\xaa\x77\x2e\xb8\xbe\x63\xa1\x6f\x6b\xc9\x82\x05\xc5\x6d\x62\x3d\xa0\x14\xbf\xe2\x84\xa4\xdf\x25\x48\x9b\xd4\x85\x64\x77\xb1\x28\x66\x9b\x2f\x0d\x01\x19\xa0\x13\x5a\x28\xd4\xac\xb7\xd8\x31\x81\x1b\xc5\x7e\x8a\x52\xe8\x71\x05\x2a\xab\x78\x8e\x0f\x28\x7e\xf7\xfb\xf3\xc2\xd2\x64\x37\x7a\x0c\x5c\x5c\x7e\x83\x6b\xab\x7d\xb2\x77\x7e\x6d\xac\xa0\xc6\xb7\x00\x3d\xd6\xd4\x3e\x08\x3f\x57\xf9\x53\xeb\x7f\x8c\xb8\xe6\x0f\x35\x05\xc3\x7f\x32\x74\x55\x18\xaf\x59\x91\x79\x1d\x36\x6b\x6b\xf6\xef\xc1\x4b\x10\x73\x78\x09\xaf\xf7\xce\x93\x85\x4b\x58\x40\x8d\xf8\x3e\xb1\x6f\xf9\xb9\x88\x4b\xfa\x06\xbf\x41\xe5\x01\xc5\x09\x9a\x33\x71\x60\x01\x51\x80\xbd\xa5\x9a\x4d\x02\xdb\xbb\xe9\x53\x92\x25\x2c\x33\xa6\x94\xa4\x0b\xe3\x6a\x91\x09\x8a\x35\x98\x30\x57\xc7\x65\xc0\x88\x09\xcc\x53\x25\xf2\xb9\x35\xf5\x40\xcd\xfa\xa2\x6d\xde\xf5\x35\xdb\x16\xac\x18\xde\xbc\x62\x81\xf2\x51\xd7\xc8\x6d\xdb\x46\x76\x39\x67\x4f\xdc\xb4\x69\xe2\x6c\xa4\xcb\x7c\xa4\x38\xc1\xd9\xcc\x09\xe0\x00\x3e\x10\x04\xab\x81\x24\x84\x24\xb3\x28\x7b\x98\x94\x14\x08\x4b\x25\x21\xa9\x5a\x33\xf0\x68\xe2\xad\x93\xec\x36\xa7\x4d\x2e\x82\xc1\x64\x19\xb9\x2a\xb3\xc9\x95\x39\x83\x4e\x11\x4e\x29\xa3\x49\xed\x19\x2b\x1b\x8b\x49\x95\x76\xd9\x8c\x81\x5c\x3c\x02\xa9\xf7\x5b\x22\xc8\x06\x90\x03\x56\x80\xa4\x6e\x56\x16\x2a\xb5\xaf\xff\x8b\xcd\x7b\x9f\xfe\x68\xf5\xfc\x5b\xa2\x91\x15\xf3\xd6\xac\x9e\xbf\x22\x12\xbd\x65\xfe\xea\x25\x43\x1a\xc5\xe6\x96\xba\x70\x0b\xec\x68\x16\x1b\x87\xb4\x84\xeb\x5a\x94\x3f\xcf\x5a\x39\x7e\xfc\xad\xb3\xe7\xac\xec\xe8\x58\x39\xa7\xa1\xa9\xa9\xa1\x61\xe8\xd0\x06\xf5\x2f\x80\x00\x30\x27\xe0\x66\x6e\x04\xe0\xc1\xb5\x20\x4e\x23\x2e\xc3\x33\xa9\x38\x4f\x6b\xb9\x24\x71\x9a\xef\x95\x6f\x02\xf3\x2d\xf4\x1c\x0c\xaa\xfe\x12\x82\xa8\x45\xc7\x64\x96\xc3\x30\x50\x60\x50\x9d\x40\x9c\xd2\xd1\x51\xf3\x2b\x2e\x8c\x9a\x5f\xc1\x8e\xfb\xe6\xbe\xff\xd9\x82\xf7\xf0\x79\xa5\x9a\xd9\x93\x39\x00\x4c\xa0\x44\xcb\xc5\x8a\xd3\xd8\x17\x40\xe7\x6c\xf3\x38\xe2\xd7\xed\x0f\xf7\x8b\x8a\x1c\xe3\x2f\xeb\xa7\x9c\xdf\xba\x08\x26\x7f\x05\xab\xd6\xee\x5a\xa5\xac\x54\x14\xe5\xbf\x94\x67\x26\x7e\xb9\x7c\xfd\x2f\xde\xf8\x15\x5a\xd7\x7e\x26\xce\xbe\xcd\x89\x7f\xb3\x4d\x47\x7e\x9b\xfe\x8b\x9b\xe4\xc4\x6c\x9b\x99\x4f\x98\xd3\xcc\x12\x76\xfe\x15\x62\x4d\x4b\x7c\xcc\x22\x1f\x73\x9a\xc4\x9a\x2a\x4f\x2b\xbf\xa5\xfb\x67\x16\x5c\xc9\xce\xfc\x34\xfa\x81\xf2\x5b\xf4\x03\x98\xf9\x96\xf9\x80\xfd\x80\xfd\x04\xd7\x3e\x52\x91\x85\x78\x36\x95\xb0\xf3\x66\x1d\xa9\xdc\xa7\x0f\x43\xc9\x15\xd2\xb8\xb5\x07\xfb\x3d\x2c\x90\xa8\x40\xbc\xae\xf2\xe4\xfd\x4f\x9e\x39\xf3\xf4\x5b\x43\x96\x8a\xaf\x6c\x59\x74\x34\xf1\xd2\xc2\xb7\x1a\x99\x0f\x36\xdd\x3d\xac\x79\xfd\x96\x75\x55\xa1\xaa\xf5\xc4\xfe\x16\x67\xf7\x6a\x74\xd1\x13\xba\xe8\xe9\x6c\x99\x5c\xa0\xd1\x85\x6e\xe8\xe7\x2f\x63\x3c\x81\x4a\x7f\x39\xc3\x33\xab\xe1\x7d\x90\x82\xc5\x70\x66\xf5\xd6\x9b\x95\xf1\x6f\x29\xa7\x57\x33\xf1\x57\x7e\xf9\xab\x97\xbf\xbc\xf5\x0e\x00\x95\x9d\x4a\x33\xb3\x21\xf3\x12\xe0\x80\x07\x64\xd3\xd2\xb2\xd9\x2e\x0c\xde\x7f\xfe\x88\x19\x46\x94\x9d\x5e\xe6\x7d\x08\x32\x40\x79\x75\x2d\xd2\x2c\x00\x95\x29\xa1\xaa\x61\x9c\x49\x01\x1b\x28\x01\x53\xb1\x07\xdf\xc1\xa4\xa4\xa2\x90\xcc\x30\x5a\xfd\x69\x59\x30\x61\xd4\x6f\x63\x6e\x23\x19\x05\xc1\x9e\x60\x2c\x8e\x22\x0c\x7f\x2f\xc8\x3c\x76\xb8\x39\x2c\x82\x5d\x36\x98\x62\x31\xa9\x48\x90\x40\x4c\x62\xec\x71\x5e\xa7\x57\x4d\x3f\xa4\x4e\x07\x8e\x1b\xd2\xf2\x35\xd5\x70\x53\x0b\xfc\x64\xea\xd3\x33\x5a\xae\x2d\x2e\x5d\xb1\x6d\x15\xd7\xb9\x60\xea\xd2\xed\x53\x23\x0b\x5a\x1a\x06\x35\xce\x8a\xd1\x96\xbb\xff\x73\x5d\x5d\xf5\xf8\xf4\xc4\xc9\x9d\xcb\x6f\xb9\x75\xee\x0b\x53\x1a\xae\x9a\xf9\x22\xa0\x32\xe3\xa9\x6a\xb8\x8e\xf9\x02\x78\x40\x19\x98\x01\x70\x66\x03\x03\xa6\x30\x41\xb4\xd6\x0a\x98\x94\x54\xaa\x8e\x80\x94\x4c\x35\x99\x52\x92\x89\xd4\x69\xe2\xdd\x29\xd9\x6b\x12\xec\x49\x03\x63\xc5\x08\x9e\x12\x2f\xc8\x82\x1d\x43\xc1\xab\xda\xaf\x41\x90\x81\x10\x8b\xc9\xa5\x05\x02\x29\x4d\xa5\xf6\x1e\xb1\x80\x5e\x25\x85\x1d\xda\xd6\x97\x6e\xdc\x3d\xb3\x73\xd1\x6f\x7f\xc9\xb4\xb5\x5c\x73\x7b\xcb\xec\xe8\x5d\x77\xef\x5d\xb3\xb1\xa2\xa2\x71\x36\x5d\x75\xeb\xaf\xd7\x4d\xbb\xee\xb6\xb5\x76\xcf\x55\xa3\x62\xab\x4a\x3d\x5d\xd0\x30\x72\x68\x49\xc5\x22\x24\x53\xbc\x4a\x45\xa0\x85\x7d\x0f\xd0\xc0\x0a\x66\xa3\x15\x27\xf3\xd9\x6c\x60\x8c\xee\x44\xab\xd8\x62\x26\xd5\x78\x62\xb0\x68\x21\x32\xbf\x23\xb1\x13\xa0\x56\xa2\xb0\x15\x9d\x76\x9f\x43\x0c\x00\xba\xcf\x51\x09\x00\x29\x3a\x0b\x0e\x47\x31\x82\x5d\xe6\xcd\x44\xc6\x70\x88\x74\x7e\xee\x46\xeb\x8e\x07\xb6\x15\xd5\x0d\x0c\x54\x36\x94\x07\x82\x54\x84\x3a\x90\x9e\x48\xb7\x56\x44\x02\xbe\x01\x61\xa4\xfe\x65\x42\x54\x35\x7c\x9a\xf9\x02\x98\x41\x21\x18\x8a\x25\x2a\x81\xc1\xb5\x15\x31\x65\x09\x82\xab\xc5\x8c\x8b\xbb\x38\x11\x65\xcd\x29\xd9\x89\x96\x80\x91\xd1\x38\x2a\x2e\x69\x97\x47\xbf\x3e\x35\xbd\xca\xb9\xf7\xa6\xee\x9e\x7b\xe7\xb6\xc9\xcf\x2e\xba\xe3\xa1\x1d\x57\x0d\x9b\xba\xac\x35\x36\xf5\x36\x3a\xba\xea\xed\x15\x3b\xef\xbc\xfd\xad\xa5\x0f\xdd\xde\x7e\xed\xb1\x9d\xad\xe3\x5f\x21\x76\x19\x3f\x55\x0d\x5f\x64\xce\x00\x17\xd8\x03\x24\x47\x48\xb2\x8a\xb2\x9e\x49\xc5\xf5\x0e\xbc\x7d\x68\x7d\x50\x66\xcc\x61\xcd\xd4\x8a\xc3\x4f\x4c\xd9\x4a\xb9\x66\x6c\x87\xb3\xc1\x60\xd2\x4a\xd8\xa5\xd5\x26\x9b\x8d\x18\x76\x16\x93\x74\xf7\xd9\xdf\x66\x4b\x2e\xc3\x6e\xb5\x3e\xfe\xe5\x82\x4f\xe2\x24\xf4\x24\x2f\xf0\xc4\x06\x04\xbb\xac\x77\xe0\x52\x2b\x0e\xb5\x4a\x4d\x5e\xe8\x89\x0a\xc9\x86\x88\x7e\x86\x9b\xbe\xe3\x46\x53\xdb\xb5\xb7\x97\x0d\xdf\xba\x6d\x0d\x77\xd3\x2d\x13\x3a\xa9\xd3\xc5\x21\xf8\x8a\x32\xb9\xb1\xf8\xea\x47\xb7\x41\x7f\x7a\xe2\xf4\x85\x53\xd0\x78\xc7\x51\xd5\x70\x03\xf3\x05\x70\x81\xe1\x68\xbc\x49\x0b\x0e\x3f\x90\xb8\x90\xa4\x0b\x25\x69\x16\x94\xa1\x13\xd8\xad\x01\x04\x01\xd9\x42\x9e\x2c\x71\x42\x1c\x18\x6d\xb1\x58\x0c\x9b\x5f\x49\xb8\x59\x3e\x40\x50\xd6\xe0\x19\x7f\x77\xcf\xdc\xa9\x75\x53\x1a\x3a\xef\x1c\xdd\x7a\xcd\xac\xa9\xf3\xee\xba\x97\x0e\x1d\xbf\x50\xbb\xac\x2a\xb1\x6d\xf4\xb8\xd0\xca\xd0\x56\x12\x1f\x0b\xa8\x6a\xf8\x2e\xfb\x35\xb0\x83\x62\x30\x13\x48\xb6\x90\xec\x22\x3c\x02\x4b\xd6\x25\xb8\x03\x0e\x53\x4a\x72\x60\xf4\xd8\x3c\x1f\xbd\x1e\x06\x65\x83\x29\x25\x9b\x1c\x82\x3d\x41\xdb\x5c\x45\xa4\x20\x83\xcc\x15\xe0\xf0\x12\x1b\x5a\x2b\xe6\x2c\xbb\xa0\x49\xa2\x2e\xac\xb7\x23\x4e\xd1\x4c\x69\x20\x76\xa4\xaa\x02\x06\x2a\xcc\x80\x97\x1f\x8d\x4c\x29\x36\x9a\x07\x3d\xf0\xf6\x1a\x6e\xe0\xe2\xf0\xf4\x05\xdb\x6e\xba\xfe\xbe\x25\x13\xd7\xd0\xa6\x77\xa0\x23\x5c\xd3\x3a\xf2\xf7\x17\x5a\xa6\x8b\xd1\x35\x0b\x6f\xf9\xdd\xa6\xf5\x1f\x6a\xeb\x26\x02\x5f\x64\xcf\x02\x37\xf8\x0a\x5b\x8e\x38\x26\x15\xb7\xe3\x28\x44\xbb\x49\x1f\x8c\x03\xb3\x3b\xac\x22\xc5\x81\x53\xb2\xdb\x84\xa1\x4a\x71\xca\xb7\x09\xdb\x2f\x6d\x30\x28\xeb\x4d\xd8\xd8\x64\xd2\xdb\x74\x41\xd9\x6c\xc2\x05\xea\x11\x53\x41\x4b\x67\xef\xd9\xcf\xd5\xdd\x88\xcd\xb8\x6e\x5c\x77\x58\x85\x75\x24\x50\xc5\x96\x6e\x46\x32\xd9\x24\x43\xb7\xb6\xce\x8c\x92\xdb\x96\xa0\xdd\x94\x23\x98\x60\xd0\xab\x64\xb2\x25\x8c\x26\x83\x23\x88\xee\xbb\xd0\x9d\xb8\xcb\x9d\x8f\x9b\xc9\xc4\x24\x3a\x16\x37\x9a\x0c\x68\xf9\x1d\x81\x14\xcd\x58\x5c\x06\x63\x16\xeb\x34\x89\xae\x8d\x39\x48\x48\x13\x92\xb6\x39\xbb\xb6\xeb\xad\x1a\xd8\x7b\x1e\xe2\xe3\x99\x5f\x3d\x18\xf1\x4d\x5e\x75\xc3\x1c\xfe\xa6\x87\xa6\x9a\xdb\xc6\xdd\x59\x32\x8c\x8a\xd0\xaf\x28\xab\x16\xdf\x78\xa3\xa7\x46\x19\x05\xf7\x36\x16\x8d\xfb\xf1\x7d\xca\x47\x44\xce\x9f\x4f\x45\xa8\x4e\xe6\x0b\x50\x01\xde\x05\x88\xa9\x7a\x44\x99\x65\x52\x32\x34\x84\xc3\x71\x3f\x4e\x0b\xf2\x7b\xf5\xc1\x04\xb0\x09\xc5\xb8\xee\x79\x25\x26\x66\x85\x29\x25\x55\x60\x26\x96\x27\xa5\x14\xc3\xa0\xec\x35\x61\x84\x6f\x27\x0c\x4a\xf6\x30\x26\xa8\x35\x9c\xb0\x99\x9d\xba\x20\x39\x6d\x42\xb2\x4d\xa5\xae\x5a\x69\x0e\x57\x47\x2a\xc1\xd5\x91\x8a\xb0\x91\xfc\x15\x35\x09\x3c\x57\x55\x93\x4a\x58\xed\xa4\x10\x12\x94\xd1\x5f\x02\xf1\x5d\x2c\xd8\x65\xd6\x1f\x8b\x49\x82\x20\xf1\x31\xc9\x66\x97\x0d\xf8\xb0\x62\xfd\x58\x40\x22\x3e\x4f\xb4\x39\x7a\x23\x8d\x12\xdb\x60\x8e\x5c\xca\xfc\x1d\x6b\xb8\xc9\x8b\x37\x04\x82\xb7\x0e\xbf\xe1\x46\xd3\xc4\xed\x53\x4d\x15\x81\x96\x15\x25\xcd\xdb\xa7\x1a\x46\x8d\x5e\x56\xd6\x84\xf8\xe7\xe4\x39\x6b\x06\x37\x4f\xbb\x21\x3c\x4c\x59\x08\xf7\x37\x16\x97\xf7\xdf\x79\x8f\xf2\x3e\xdc\x1f\x2e\x1d\xb7\x6b\x3b\x26\x24\xcc\x4c\xa3\x22\x70\x05\xf3\x05\xb0\x80\x3a\x2c\x17\x41\x26\x25\xb3\x7c\x58\x4b\x21\x90\x2d\x26\xcc\x4f\x73\x14\x03\x32\x34\xa8\x3d\xa5\xd5\x9e\xaa\x80\x92\x7b\x76\xac\xe6\xae\x9f\xdb\x3f\xec\xad\xae\xb8\xfa\x8e\x82\x66\xd4\x81\xa9\xf3\xcc\x2b\xf5\x4f\x2f\x57\xde\xfb\x7f\x92\x5f\xce\xa5\x22\xf0\x23\xe6\x0c\x30\x80\xe1\x40\x53\x72\x20\x59\x46\xdd\x9d\xdf\x7e\xad\x1d\x99\x16\xc9\xd0\xcd\xc8\xb0\xf8\x9c\x45\xa2\xba\x01\x3a\x2e\x55\x50\x42\xca\x90\x05\x70\xa0\x45\x87\x47\x05\x58\x7e\xe2\xc1\x6a\x93\x79\x88\xe1\xcd\x1f\x2b\x9b\x7f\xc2\x9c\x51\x1e\x3c\xe0\x5b\x6b\x83\xb7\xa4\x27\x92\x7d\xf1\x0d\x15\x81\xa7\x99\x33\xc0\x08\x80\x1e\xd2\xa2\x27\x2a\x42\x47\xa0\x8a\x57\xbe\x81\xd5\x8f\x3d\xd4\x79\x78\xaf\xf2\xd1\x13\xbb\x66\xbd\x46\x45\xe0\x74\x38\xf6\x93\x4f\x94\xbd\x8a\xf4\xc7\x3f\x22\xf9\xf8\x5b\x66\x29\x25\x62\xff\x9d\xef\x72\xfe\x3b\x24\x70\xf5\xf2\xe1\x7d\x7b\x49\x1f\x1e\xcc\x6c\x56\x9a\xc0\xf1\xcc\x66\xa0\x27\x32\x65\xef\x98\x72\x59\x97\x6d\x89\xce\xc6\xd7\xad\x75\xdd\x3b\x74\xf6\x80\xeb\x5d\x07\x94\x8e\xc6\xee\x21\xde\x51\x3f\x1b\x8c\xda\xf9\x40\x69\x02\x9f\x63\x7f\x5a\xf4\x6f\xf8\xd3\x1c\xe8\xb8\xff\x5e\x3e\xb5\x8a\x2b\xfb\xd4\x32\x67\x33\x5f\xd0\xcd\xcc\x74\x50\x00\x9a\x48\x05\x6a\x5c\xab\xce\x06\x41\x90\x14\x45\x29\xc4\x95\xbb\x1d\x06\x8c\x11\x0b\x64\xda\x43\xc0\x2e\x0c\x42\x1c\x9a\x71\xe5\x66\x1b\xc9\xea\x21\x85\x67\xd5\xd2\x3b\x5a\x1d\x7a\x8a\x09\x94\x5b\xc4\x55\x9d\x4b\x12\xf3\xd6\xdf\x32\x66\x43\xf3\x5d\x4f\xbe\xfe\xeb\x5d\xca\x77\xbb\x1f\xf1\x3f\x22\x3e\x0a\x8d\x4f\xaf\xdb\xd2\xbf\xf8\xb1\x96\xdf\x1e\x7f\x47\xf9\xd9\xcb\x80\x02\xb3\x32\x5f\xd0\x12\xee\x4b\x00\x2c\x01\x71\x37\xea\x8d\x4d\xab\x38\xa5\xe7\x53\xc9\x62\xbf\x9b\x31\x07\xf3\xeb\x20\x9a\x1d\x29\xc9\x4c\xf0\x81\xd5\x9a\x87\x18\xad\x03\xc3\xd3\x4a\xa5\x02\x86\xe5\x05\xb2\xcd\x2d\xd8\x25\x27\x76\xab\x98\x01\xea\xb5\xac\x2f\xee\x85\xce\xeb\xc8\x2f\xcd\xe1\xca\xab\x5a\x9b\xa7\x99\xcf\xda\x09\x99\x7d\xb8\x00\xc7\xd2\x43\x9d\xeb\x6f\x19\x73\x57\xf3\x5d\x4f\xbc\x76\x0a\xfe\x54\xd5\xd7\xe1\xe6\xb7\xe1\xf8\x57\x23\xbb\xea\x1f\x57\xbe\x7d\x86\x0c\xec\x14\x5c\xa8\xe1\x09\xe5\xd1\x39\x00\xe6\x5f\x82\xd2\xc9\x62\xbf\xc7\x96\x37\xb6\xc2\x53\x68\x40\x52\x29\x41\x22\x41\xf4\x47\x63\x2b\x2d\x14\xec\x09\x83\x8d\xf6\x10\xf5\x5e\x9d\x0c\xbf\x20\xc1\x98\x6c\x28\x16\xec\x71\x5e\x9d\x14\xe1\xca\x93\x92\xe7\x22\xba\xe4\xfc\xcc\x51\x07\x75\x89\x79\xa2\x86\x67\xc7\xf4\x94\xf2\x2d\x7c\x87\x99\x0b\x38\x60\x07\x03\x90\x5c\x92\x34\xa8\xd9\xcd\x0e\x9c\x0c\x6b\x26\x09\xcd\x48\x36\x35\xf3\x68\xb1\x32\xe4\x40\x24\x70\x04\xf9\x92\x70\xe7\xad\x13\x4f\xe8\x66\xbd\xb8\x57\xcb\x61\x56\xbe\x85\xdc\x97\x9e\xf7\x95\xaf\x99\xd7\xb2\x39\xcc\x14\x35\x9f\xe9\xa1\x7b\xb8\x15\x40\x0f\x0c\xa0\x42\x8b\x1c\xc0\x66\x10\x23\xd9\xb3\x4e\x02\xee\x44\x72\xcd\x0c\xbd\xf2\xd6\x1d\xd4\xfc\xea\x25\xde\xee\xc2\xe7\x46\xad\x67\x7a\x4a\xae\xf9\xaf\xb1\x25\xb1\x2f\x27\xc0\x51\x00\x00\x1a\x1e\x66\x4d\x8c\x93\x4b\xaa\x3e\xf8\x99\xff\x80\x0f\xbe\x0c\x06\xbf\x87\x1f\x1e\x5e\xd9\x0f\x0f\x0f\x5f\xc6\x11\x3f\xeb\xd2\x8e\x78\x00\x00\x93\xd9\x0a\x00\xe3\xe5\x0c\x80\x07\x02\xb0\x83\x42\xad\x52\xaa\x4c\x33\xa2\x88\xf3\x76\x24\x4a\xc4\x56\xd3\x24\xe7\xc0\x85\x52\x9d\xb9\xaa\x04\x45\x21\xc9\x74\x4a\x36\x3b\xf1\x56\x52\x4b\x11\x64\x6b\x41\xdc\xf6\x6d\x07\x39\xff\x19\x52\x00\x10\xbb\x71\x25\x97\x2d\xc1\xba\x18\x47\x30\xe1\x44\xaf\x34\x90\x5c\xb5\x30\x41\xb1\x4e\x97\x86\xd4\x6b\x36\x21\x09\xc8\x41\x8a\x82\x43\x7c\xe2\x43\x07\xae\x31\x2a\x78\xb0\x2b\x21\x00\x45\x47\x80\xf6\xd3\x39\xf6\xea\x85\x7e\xba\x32\x62\x81\x2b\x69\x6f\xf7\xa1\x43\x51\xc5\xf1\xe7\x41\xda\x94\x55\xc2\x8d\x7e\x6f\xd9\x58\xf6\xf0\xf9\x76\x78\x52\x89\x31\xcb\x72\x33\x78\x21\x09\xc3\x9f\xac\xbc\xe6\x49\x00\xc1\x5e\x6a\x34\xdc\x4f\x4f\x03\x46\x50\x9b\x97\x75\xaf\xfe\xc9\x0b\xde\xb1\x31\x41\xf5\x8f\x6c\x26\x2c\x3e\x6f\x29\xee\xcd\x16\x6d\x8e\x67\xcb\x32\x03\x1a\xb4\x02\xc0\x7c\xce\x19\x80\x1e\xb8\x80\x1b\x6c\x00\x71\x03\xa2\xae\x83\x56\x1d\x68\x16\x3a\x15\x77\x23\xea\x5a\xed\x06\xa3\x39\x28\x5b\xe9\x6c\x3c\x0f\x5a\x95\x1a\xde\x31\x29\x96\x62\x90\x0c\xb5\x92\xa5\x56\x32\xd8\x64\x87\x70\x0e\x89\x1b\x46\xe1\x9c\xe4\xb0\x25\xac\x0e\x8b\x23\x98\xb0\xa3\x57\xfa\x90\xc1\x68\xb1\xda\x1d\xb9\x32\x0d\x18\x9c\x3d\x0e\xf5\x00\xaf\xa1\x1c\xd9\x1c\xd0\xcf\xfb\x69\xf2\x1f\xb6\xaa\x14\x2b\x82\x11\xea\x0f\x81\xf4\x7b\x33\x29\xa3\x2f\xfd\xf5\x72\xaa\x2e\x90\xbe\x2b\x47\xb5\xef\x1e\x62\x0f\xef\x56\x1a\x9f\x4d\x7f\xb3\x9b\x3d\x0c\xb4\xf1\x71\x6d\xd9\xf1\xfd\x92\x8c\x2f\x2e\xd8\x5d\xa2\x28\xe2\x21\xc6\x4d\x56\x1b\x7a\x8f\x47\x69\x76\xa2\x51\x4a\x0e\x11\x63\xa5\x5a\xc2\x79\x63\xd5\xfc\x6e\xb2\xc1\x80\x61\xea\x5c\x86\x6c\x5c\xbd\xc9\x90\x52\x83\xdd\xb5\x42\x66\x56\x48\x8a\xb5\x17\xf4\x85\xb8\x57\xc3\x13\xd0\x3a\x33\xbb\x4c\x8e\xa0\x64\xb7\x25\x2c\x76\xab\x23\x98\x70\xa0\x57\x74\xdf\x89\xee\xd3\x09\xb3\xc5\xe1\xcc\x92\xc8\x68\xbe\x0c\x89\x70\x55\x5e\x18\x70\xf8\x8d\x59\x12\xdd\x02\x23\x47\x36\x51\x9b\x36\x26\x95\xb7\x0f\x3d\x94\x5e\xf7\xd0\x0b\xbd\xe9\x93\xde\x45\x2d\x3c\xdf\x8e\x74\x72\xf6\x30\xa0\xc1\x14\x00\x18\x2e\x4b\x9f\xa5\xea\xfc\x1b\x99\x94\xe4\x0c\xc7\xad\x78\x09\x30\x29\x49\x08\x63\xfa\x5c\x6a\xea\x9f\x39\xfb\x26\xd9\x47\x26\x9b\x64\xee\x96\x1d\xb6\x73\x92\xbd\x1b\x24\x4c\x66\x32\xc7\x30\xfb\x8e\xf8\x88\x2d\xc6\x4b\x8f\xa4\x19\x3a\xaa\xa2\x7e\x2b\xa4\x3d\x3c\x9c\xa2\x8e\x84\x77\x1d\x3c\xf7\xa4\x93\x02\x4e\xe9\xfc\xd3\x2e\x65\x75\xfe\x38\x3a\xab\x99\xa7\xaa\xe6\xce\xad\xfa\xae\xb3\xba\x93\x3d\x0c\x18\x30\x29\xf3\x05\xfb\x1b\x3c\x0e\x0f\x28\x00\x95\x60\x36\x88\xbb\x70\x41\x4c\x3a\x15\xb7\xa0\x61\x04\xe8\x54\xbc\x00\x8f\xa1\x0a\xe7\xe5\x14\xba\x30\xa7\x63\xd1\x94\x32\x4e\x12\xcc\xe2\xc4\x10\x59\x88\xd9\x09\xae\x94\xdc\x1f\x06\xe5\xff\x8f\xbd\x37\x8f\x8f\xa2\xca\xdb\x47\xcf\xa9\xa5\xab\xf7\xae\xa5\xb7\xac\x9d\x4e\x67\x21\x34\x49\x20\x45\x12\x9a\xcd\x5d\x31\x22\x83\x98\x01\x45\x8c\x18\xd9\x41\x01\x23\xa2\x22\x2a\x83\x88\xc0\x40\x40\x20\xac\x22\x20\x32\x80\x88\x55\xdd\x4d\x02\x88\x10\x44\xdc\x10\x19\x74\x84\x51\x5f\xb7\x19\x9d\xb1\x15\x1d\x27\xae\x2c\x29\xee\xe7\x9c\x53\xd5\xe9\x2c\x38\xcb\x9d\xdf\xf2\xde\xfb\xfe\x41\xd1\x54\x32\x63\x9f\xed\x7b\x9e\xef\xf6\x3c\x39\xac\x20\xc6\x9c\x9e\xcc\x10\xbe\x98\x42\x99\x82\x18\x87\x16\xab\x00\x88\x42\x4b\xdb\xd7\x6f\xa7\xaa\x4e\x74\xc7\x92\x7a\x7d\x23\xf4\xe1\x64\x74\x90\x54\x1f\x73\x5b\x9b\xa6\x7a\xdb\xd8\x5a\x63\x1d\x35\xd5\x99\x8d\xe7\xa7\xa7\xa8\xaa\x27\xf7\x35\xfb\x25\x1e\x2f\xb2\xee\x6b\x88\x0e\xa8\x22\x90\x3d\xad\xda\x9d\xb2\x1c\xb5\xe2\xd1\xba\x53\x36\x30\xd9\xa2\x52\x22\x66\x17\x44\x73\x98\xe8\x8c\x95\x62\x85\x71\x8f\xbe\x9a\xbb\xbe\x13\xc9\x6a\x8a\xbc\x22\x35\x23\x2f\x88\x6f\xde\x77\xe8\x85\xbf\xf7\x41\x6f\x55\x51\x32\x2b\x36\xf4\x03\x7d\xb5\x41\xd4\xc1\xa3\xb5\x85\xfa\xdf\x64\x89\x6d\x62\xd7\x4b\xdc\x0f\x4a\x50\x86\x74\x48\x32\x76\xea\xc3\xcf\x34\xed\x82\x1f\x1f\x6f\x5d\x3c\x6d\xef\xcc\x54\xd3\xd7\x1a\xa2\x3e\x3c\x3f\xb1\xf5\x53\x2a\x9f\x8c\xb5\x1a\x00\xf6\x27\x93\x15\xe4\x80\xee\x20\x0c\xa6\xeb\x3c\x49\xbc\xac\x42\x7c\x48\xa3\x66\x5d\x35\x3f\x1a\xc6\x23\xee\x81\x46\xac\xe4\x97\xa9\x99\x9e\x84\x52\x50\xa6\x64\x12\x21\x16\x9b\x07\xcb\x8c\xab\x9e\x4c\x41\x6c\x34\x53\x4e\x21\x60\x48\x97\xaa\x2e\x1e\xdb\x71\x04\x3c\xc5\x00\x26\x86\x6b\x64\x6c\x9e\xcc\x60\x6e\x77\xbc\xce\x72\x65\xb0\x40\x40\x48\x2a\x07\x08\x6e\x8a\x0b\x72\xc1\xca\xe4\xe2\x7a\xdc\xa2\x8f\x4b\xb9\x8e\xab\x73\x60\xcd\x6b\x4d\xf0\x9a\x13\x10\xc0\xec\x4f\x7e\x0f\x27\x07\x5b\x37\x67\x7e\xfb\xe3\xc1\x9d\xab\xbf\x78\xe8\xf6\x69\x99\xad\x7f\x31\xc6\xbe\xf9\x35\x78\xf5\xa7\xf0\xee\x37\xb4\xb7\xb5\x73\x09\xed\xbe\xf9\x9b\xeb\xeb\xe1\xe2\xbf\x37\x1f\x7f\x46\x7b\x7f\xcf\xf6\x0b\x60\x5a\x7d\xea\x8c\xe0\xbb\x10\x4c\xb8\x70\x9a\xfa\xc4\x14\x07\x02\xc8\x04\xf9\xa0\x27\x38\x02\xa2\x2e\x40\x20\x24\xe6\x64\x55\x18\x19\xdd\x79\x25\x72\xdc\x43\xae\xf8\xa2\x32\xac\xfe\xa7\x4b\xf3\x88\x68\xab\xfb\xdc\x49\x57\x8c\xa8\xf5\x14\xc0\xb0\x1a\x96\x12\x4a\x98\x57\x82\xe8\x17\x72\x3c\x09\x25\xa7\x54\x0d\x7a\xda\xe4\x02\xcf\x7e\xbf\x86\x6c\x0a\x72\x47\x62\x97\x0c\xe0\x82\x27\x68\x94\x3d\x41\x9c\xa1\x89\x5b\x5c\x59\xd9\xf9\x79\xbe\x88\x1a\xcc\x11\xc4\x98\xdd\x56\x54\xd2\xa6\x19\x61\x8f\x28\xb4\xa0\x02\x5b\x24\xa2\x7a\xd2\x05\x31\x9a\x95\x9d\xaf\x8b\xd5\xa7\xd0\xf7\x93\xf0\xe7\x2f\xe3\x88\x09\x9e\xb5\xf1\xf5\xfc\x84\x8a\x11\xc1\x89\x05\xb3\x1f\x4e\xef\x1a\x54\x7c\x50\x3a\x9e\x7a\xaf\x35\x67\x50\xcf\xba\x8c\x85\x2e\xcf\x03\xcc\xf9\x8b\x62\x0c\x8a\x60\x0c\xdc\xcb\xeb\x04\xf7\x77\x81\x2f\xe2\x26\xb3\xa1\xc1\x6e\x40\x0b\x17\xa9\x06\x6b\x13\xec\x6e\x87\x27\xac\x49\x3c\x61\xe5\x63\xac\x15\xe1\x09\x8b\x95\xe0\x09\x2b\xc6\x13\x6d\xd2\xea\x2a\x34\xeb\xdd\x44\x06\x70\xe8\x84\x16\xe0\xd5\xed\x51\x02\x35\x49\x47\x06\xfa\xd9\x60\x1a\xd9\x46\xac\xb7\x1e\x44\x76\x00\x7f\x7b\xde\x9c\xc0\x5f\x5e\x0d\x9a\x13\xf1\x34\x3f\xfa\xf6\x6a\x1a\x72\x7b\x72\xb1\xf4\x82\xdd\x8d\x2e\x2c\x62\xfb\xb2\xdc\x58\x69\x07\x99\xf4\x10\x34\x5a\x73\xe2\xa4\x7c\xb0\x44\x09\xe2\x28\x30\xcf\x9f\x51\x82\xbc\x0a\xf9\x33\x0a\xcf\xc7\xfc\x7c\x50\x0a\xc7\xd2\xd0\x93\xde\x0d\x20\xef\x4f\x0b\xa6\xdc\xe6\x7e\x9e\xac\x75\x9a\xa0\x5a\xcc\x91\x88\x12\x34\xb4\xbe\x82\x18\x89\x70\x9e\x6c\xe8\x71\x33\xc1\xc2\xa0\xa1\x40\x6b\x88\x19\x54\xc3\x72\x38\xeb\xd4\x07\xcf\x6e\xb8\xfb\x7e\xed\x0f\xda\xb9\xf3\x90\xda\xf5\x62\xfd\xe3\x9f\xe7\x7c\xbb\x3a\xfe\xe0\x92\xe3\x6c\xe3\x8e\xad\x8b\x0f\x65\x5b\x73\xd6\xdd\xf5\xce\xf7\xeb\xd7\x2d\x9d\x7e\xdf\xea\xc5\xb3\x6e\x9f\x80\x73\x9d\x68\x0e\xa6\xe2\x9a\x22\x5d\x97\x5c\x61\xc9\xda\xa9\x0c\x9d\x30\x08\xd9\xd8\x14\x5d\x72\x5d\x0e\x5f\x0f\xac\xe9\xdd\xa0\x90\x49\xca\x46\x21\xe4\x81\xbe\x0f\xf5\x97\x60\xeb\x71\xed\x6b\xb6\x71\xf3\xd9\xd3\x80\xba\xf0\x3a\x00\xf4\x59\x36\x0e\x58\x60\x07\x23\x0d\xcd\x34\x1a\x17\x83\x9b\x70\x21\xbd\x09\xd3\xf0\x38\x4a\x55\xa7\xbe\x29\x86\x9f\xa9\xd3\x4b\xd2\x9d\x8a\xb9\x59\x65\xf8\x33\xac\x42\x37\xd3\x40\x65\xcc\xe8\x6a\xa4\x19\xce\x9c\x9c\x38\x5c\x18\x0c\xd1\x46\xa8\x84\xb2\xc4\xe5\xa3\x6d\x60\xe2\x2a\xbd\xd4\xeb\xfb\x1b\x7c\xe7\xdf\xa1\x96\x0c\x91\xfa\xde\x31\x95\xbd\xea\xec\xde\x3b\x37\x53\x3f\xee\xdf\xb0\xea\x60\xea\xd8\x6d\x60\xa2\xfe\x8d\x2c\x74\x22\x39\xf8\x38\x8b\x77\xae\xca\xd2\xb8\xd3\x30\x29\xdc\x66\xe0\x35\x50\xa2\x30\x78\x85\x2d\xc2\x19\x85\xe1\x55\x28\x9c\xe9\xd0\x8d\x8a\x56\x98\x61\xcd\x96\x76\xb2\x5a\x29\xc8\xac\xba\x13\x20\x4b\x42\x30\x1c\x43\x38\x0d\x00\xd3\x80\xe3\x11\x25\xfa\xf7\xe3\xe8\x04\x0e\x4c\xa8\x34\x8d\x4b\xd6\x70\x10\x01\x7b\xfd\xc8\xdb\x43\x66\x04\xbb\xae\xa1\x4a\x18\xac\xc4\xea\x70\xee\x4c\x7a\x69\xeb\x03\x21\xfa\xf6\x8c\xf3\xd3\xa9\x5d\xc1\x7a\x66\xee\x96\x65\xe7\x1e\xde\x42\x6a\x33\x86\x03\xc0\xde\x8f\xc7\xaf\x7b\x06\x51\xce\x6c\x93\xf5\xb3\x1b\xa5\x58\x93\x2c\xcb\x71\xda\x6a\x9c\x5f\x9a\x4e\x18\xbd\xb9\x20\x29\xb4\x89\x63\xb2\x56\x1c\x93\x35\x13\x19\x7e\x64\x18\x71\x79\xa9\x35\x91\x9c\xb3\x4e\x18\xce\xc6\xc7\x68\x1b\x25\x85\x15\x33\x1f\x63\xcc\x2c\x3a\xe4\xe8\x89\xde\x5b\x6d\x58\xe2\x83\x66\xda\x0e\xba\x2e\x77\x47\xd0\x1a\x3d\xbc\x03\x48\x4b\xc5\x65\xf8\x5c\x2f\xbf\x70\x9a\x9d\xcf\x1e\x03\x0e\x90\x01\x02\x60\x14\x88\xda\xd0\xdc\x09\xc6\xdc\xf9\xe9\x44\x3c\x2b\xd3\xc6\x38\xc2\x6a\x96\x39\xa9\x2a\x84\x3d\x36\x72\xdb\x71\x1e\x2c\x22\xa4\x7a\x9c\x82\x18\x63\x6c\x99\xd9\xd8\x10\x67\x0a\x82\xa8\x3a\x41\x24\xa2\xfa\xb3\x04\x51\xe5\x3c\xf8\x8a\x6e\x07\x5e\xa4\x76\xd8\xc5\x57\x19\xe4\x96\x1f\x84\x37\x9c\xfc\x11\xfa\x15\xad\xe9\x7d\xed\x82\xf6\xc9\xe1\x03\x5b\x56\x7e\xb3\x70\xcf\xd3\x6b\x5b\x1e\x5f\x9f\x43\x39\x82\x54\x3e\xe4\x60\xf4\x6f\xda\x9b\x5a\x8b\xd6\xa2\xdd\xfc\x25\x0c\x43\xf1\xe5\x3f\x1e\x84\xe3\x3e\x7c\xe9\xfd\x97\xb5\x75\x13\x9e\x7c\x12\xc0\x0b\xa7\x00\xa0\xed\x78\x9d\x86\x1b\x3c\x8c\x4c\x42\xb1\x96\x45\x59\xbc\x55\xf5\x8c\x7b\xca\x16\x4d\xe2\x4a\xcc\x82\xaa\x5a\xf8\x33\x8a\xb9\x19\xc4\x28\x9a\xec\x45\x98\xfc\xa4\x47\xd6\x42\x29\x08\xb2\x28\x15\x38\xa6\x42\x45\x60\xd8\x0b\xb6\x1c\xeb\x08\xce\xd7\xbf\x8b\xd9\xae\xef\x18\x95\x62\x65\x59\xaf\x1a\x32\x70\xbd\xbe\x3d\x8c\x43\x3d\x70\x63\xcb\x71\xb2\x11\x88\x19\xb1\x29\x76\x3e\x46\xdb\xb1\xf0\x21\x7a\x46\x6d\xf6\x4e\x12\x91\x36\x5c\x28\x69\x4b\x55\xa5\xb2\xea\x88\x03\xfb\xf3\x68\x6b\x54\x42\xd9\x02\x43\x90\xa3\xab\x61\x79\xe3\xaa\x87\xa9\x5e\x1f\xb6\xce\x83\x23\x5f\xd3\xfe\xbc\x63\x16\xdb\xd8\xda\x77\x3e\x75\x49\xeb\xec\xf3\xc7\xa8\x23\xb3\x5b\xf7\x00\x88\xef\xac\x00\x8b\x7c\xfb\xab\x53\x6e\x2c\x23\x62\x80\x2e\x26\xbb\x6e\x83\xee\xfa\xb9\x21\x79\x31\x19\xe5\xca\x1d\x6f\x6f\x60\x5c\x3f\x58\xd6\x60\x06\x9d\xf1\x52\xd3\xee\x29\x92\xa9\x6a\xb4\x96\xc6\xc6\xcf\x0e\xa6\x37\x28\x5b\x77\xee\x3e\x7f\x27\x80\x60\x18\x00\xa6\x43\x6c\x23\x90\xc0\x31\xf2\xdf\x8d\x71\x66\xa7\x94\xe7\x33\xa6\xcf\x84\xbe\x84\x9b\xa4\x6e\x5c\x38\x75\xa3\x1f\xa9\x24\xc4\x6c\x67\x7c\x9d\x8a\xc4\x2b\x62\xf3\xbe\xe6\xba\x9f\xa7\x13\x4d\x45\x67\x89\x53\x71\x35\xab\xb4\xff\x0c\x8b\xf3\x1d\xdb\x5b\xce\x90\xaf\x6f\xe6\x15\x5b\x33\x6b\x54\xb3\x3f\xd2\xd2\x17\xcf\xbd\x99\x8f\x59\xcc\x36\x29\x1c\xb5\x98\x6d\xed\xda\xb8\x2d\x36\x97\xa8\xcb\x2f\x5a\x20\x45\x9b\x2c\xc8\xed\x6c\x2f\xbc\x68\x96\x04\x51\x65\x48\x0e\x53\x86\xe8\x68\x06\x61\x48\x12\x2b\x43\x30\x44\x87\x4c\x1c\x3d\x0c\x96\x43\x6a\x89\x99\x5a\x00\xd3\xb4\xdf\xef\xd9\x33\xa0\x80\x69\xbd\x64\xd9\x7a\xb3\x4b\xde\xc7\x36\x9e\x1b\xce\xec\x38\x5b\x45\x8f\x81\x99\x8f\x9e\x3d\xcf\x52\xeb\x7e\x3e\x8f\x6b\x03\xd0\xfc\xb0\x51\xb6\x11\xf0\x40\xd1\xd7\xc5\xca\x1b\x7b\xcb\x6c\x41\x93\x43\x9a\x7c\x79\x57\x42\xe1\xc9\xe4\x58\x5c\x98\xdb\x5a\x9f\x9c\x23\xa9\x93\x83\xf3\x0f\xfb\x06\xce\x6b\xc1\xca\x37\x68\x0a\xd8\x66\x56\xb1\x90\x94\xcf\xb3\xdf\x31\x78\x0a\xb0\x98\xac\x59\x0a\xc7\x38\xf4\x8c\x9a\x58\x73\xca\xf6\xe3\x22\x20\xc6\xb9\x74\x12\xe4\xdd\x90\xb3\xea\x9f\x93\x35\xbb\x40\xaf\x15\x23\x22\xa4\xb2\x1e\x9c\x86\xfa\xf8\x0f\xc3\x66\x93\xa3\x87\x6b\xe7\x2e\xed\xe8\x61\xad\xbf\xc9\x53\xbe\x8d\x6d\x3c\x37\xe8\xd6\x9f\x07\xd2\xf9\x67\xab\x98\xfd\x3b\x7f\x38\xff\x39\xe9\xf7\xf8\xb3\x7e\x0f\xd1\x80\x03\x36\x50\x64\x9c\x71\x3a\x81\xe5\x24\x55\x33\xba\x8b\x18\x60\x69\x7f\x17\xa1\x6d\xa7\xb7\x0d\xa0\x3f\x59\x41\xfa\xe1\x50\xeb\x13\x39\xd4\xa3\xc1\xd6\x6d\xb9\x74\xcf\xd0\xe6\xcd\xd4\xce\x8d\x1b\xa9\x09\x9b\x37\x63\xed\x1c\x64\x13\xe7\xe9\x36\xf1\xca\x2e\x2c\xa2\x41\x17\xdd\xc1\x0c\x66\xe9\x66\x50\x65\x6c\x08\xe6\xfb\xdb\xf2\xc7\xbf\x64\xf9\x96\x77\xf0\xd6\x0e\xb7\x39\x6b\x54\xa8\xa3\x8b\x06\x85\xf6\x0e\x1a\xb1\x31\xb3\x30\xa6\xfc\x4d\x7b\x75\x4d\x1d\x53\x26\x91\xa4\x39\x55\x3a\x13\x12\xf6\x79\x8e\x09\xc7\x68\xcc\x5a\xc2\x48\xa4\xd4\x50\x4a\xed\xf1\x50\x2d\x1d\x8e\x92\x7e\x26\x8c\x7f\xea\x64\x1a\xac\x29\xe5\xc2\x86\x21\x88\x21\x0d\xdd\xa2\x1d\xdd\x0b\xa5\xd6\xd9\x08\xd6\x9c\xad\x62\xdd\x67\x4f\xe3\xb9\x45\x38\x62\x01\xdb\x88\xbd\xc9\x3a\x1d\x45\x59\xf5\x7d\x2b\x99\x13\x71\x8b\x0d\x03\x09\x4c\xc3\x40\x8e\x37\x8e\x83\x90\x50\x07\x2b\x5d\xe4\x78\x2b\x56\xe4\x2d\xc6\x2c\x56\x09\x59\x47\xf4\xa4\x63\xd0\x62\x93\x92\xa0\x47\xb2\x09\xed\xf0\x21\x08\x86\x68\x29\x15\x11\x56\xfd\xf1\x23\x6d\x8f\x76\x64\xee\xfd\x6b\x1f\x3e\xf1\xc1\xe3\x8b\xd7\xb1\x8d\x07\x0f\xfc\xa4\x9d\x69\x3d\x42\xbd\x1b\xdf\xf1\xc0\x14\x8c\x31\x3e\x05\x80\x99\x83\xef\x96\xb2\x14\x0c\x84\x77\x05\x97\xb2\xd9\x54\x0b\xc1\x18\x0a\x27\x28\x54\x44\x61\x48\xf2\x2b\x54\x69\x41\x7b\x2f\x68\x81\x41\x2e\x90\x45\x79\xb5\x6f\xb2\xe8\xda\x50\xeb\x44\xe8\xd4\x28\xea\x44\xa8\x81\xaa\xa1\x7a\x2d\xdb\xdc\x7a\xa2\xf5\xc5\xcd\x68\x5d\xf7\xe8\x78\x9b\x03\x55\x3a\x57\xb1\x81\x35\x01\x9d\x50\x19\xae\xac\x8d\x77\x44\x4a\x24\x17\x6a\x5d\xcb\x6e\xd2\x87\xc8\x77\x49\x3f\x22\xa1\x2f\x00\x43\x70\x4f\x88\xfe\x20\x47\xbb\x4b\x3b\xbd\x17\x4a\xac\x7b\xf3\xe6\xb3\xa7\x59\x37\x80\x60\x3f\x00\xcc\x71\xb6\x11\x98\xc1\x6c\x10\xe5\x30\x47\xb0\x1c\x05\x14\x3e\x5f\xc8\xa2\x58\x70\x2e\xc3\x24\x25\x62\xd0\xc4\x99\xc3\x2a\xb0\xe2\x36\x19\x68\x4d\xa8\xd6\x8e\x7e\x3d\xa6\xe9\x20\x32\x78\x6d\x7e\x3d\x67\x36\xa3\xf5\x32\x37\x3b\x15\x88\xaf\x87\x28\xc5\x9a\xb1\x5f\x4f\xfe\xd6\xaf\x08\x2c\x42\x8b\x1c\xf8\xfd\x6d\x7e\x3b\xdb\x98\xea\xad\x13\xdc\x72\x98\x3d\x0a\x24\x90\x0e\x82\xe0\x63\x10\xe5\x31\x9f\x82\x8c\xef\x79\xc5\x24\xc7\x9d\x19\x3c\xeb\x08\x2b\x3e\x59\x75\x9a\x13\x8a\x50\x16\x67\xfc\xf8\x45\x50\x56\x19\x33\x41\x01\xb9\x84\xf4\x5d\xc2\x5c\xef\x3c\x0c\xab\x2e\x09\xeb\xe1\x65\xc3\xb0\x6a\x95\xda\xfc\x94\x97\xbe\x23\xe8\x9a\xc7\x17\x9b\x0b\x1d\x02\xe4\x9f\x30\x3c\x42\x61\x2e\x3e\xc6\xb9\x4c\x52\x38\xe6\x44\x4f\xf4\x5e\x40\xef\x63\x3e\xfc\xf4\x1b\xbf\x93\x81\x7f\x27\x88\x9e\xf4\xa5\x56\x86\x35\x71\x4e\xc1\xe7\xcf\x08\xb6\xd3\xe8\x05\x6a\x86\x93\x94\xf0\xf8\xf5\x32\x3e\x46\x54\xcc\x7a\x7e\xe5\x12\x28\x73\xc8\xa7\xa1\x18\x17\x0c\x55\x96\xc0\x4a\xb7\xd7\x27\x39\x21\xc4\x96\xa4\x70\xf9\x06\x58\xf9\x5f\x79\x2f\xe4\x9f\xfa\xe6\x59\xed\x8d\xb7\x7a\xed\xeb\xf5\xfe\xd7\x2f\xac\xaf\xdf\xf6\xd1\x0f\xf0\xaf\x1f\xfd\xb0\x76\x39\xb5\xb6\x19\xfa\x37\x70\xf1\xb8\xfd\xeb\x37\xf6\x6b\x7f\x7c\xd2\xf4\xe9\xa7\xce\x6f\x3e\x58\xbe\x85\xa5\x05\xea\x5c\xeb\x69\x07\xb8\x70\x72\xe1\x53\x26\x00\x2f\x34\x00\xc0\x7c\x8c\xf7\x78\x81\x7e\x3a\xcd\x32\x61\x49\x66\xe5\xb6\x1d\x4e\x81\x64\xe7\x66\xc8\x02\xd1\x72\x59\x60\x88\x86\x93\xa8\x1b\xb5\xf3\x7b\x5f\x81\xb1\xd7\x5a\x4f\x41\xcf\xa1\x13\x5a\x3e\x6d\xa2\x94\xd6\x13\x54\x69\xeb\xa0\x56\x8a\xba\xbf\x75\x3e\xd1\xaa\x02\xc0\x34\x94\x6d\x04\x01\xf0\x25\x88\x66\xa0\xff\x46\xba\x8c\x6b\x05\xe3\x8c\xdd\x21\xb9\xf3\x7c\x72\x3c\xcb\x9a\x41\x3b\xc2\xaa\xcd\x29\xcb\x08\x78\xaa\x69\x99\x68\xc3\x13\xf4\xc9\x49\xc9\xd0\x82\x1b\x5b\xb3\x0c\x18\x56\xd3\xad\x09\x25\x9d\xa8\xff\xea\x39\x2d\x09\x86\x55\xb7\x3b\x29\x71\x79\x89\xf8\x43\x4e\xa7\xe8\xc2\xbe\x81\x2b\x5b\xd6\x13\x90\xb5\xae\x65\x0f\x5e\x64\x8c\x13\x14\x37\x09\xd6\x67\xf0\x31\x5b\x86\x5d\x0a\x2b\xe9\x7c\xcc\x99\xee\x40\xee\x28\x7a\xa2\xf7\x99\xe8\x3d\x0d\x62\x14\x2b\x7a\x88\x5e\x2b\xc5\xda\x9c\xa2\x27\x2d\xb3\xdd\x82\xd2\x6d\x95\xda\x7a\xf8\xc1\xdb\x0f\xf7\x88\x91\x1c\x31\xc5\x04\x43\x74\x48\x0a\xe5\x16\x1c\xf1\x57\x1f\x1c\xe9\x5b\xf4\x04\xbf\x67\x6f\x93\x6b\xf7\xa9\xee\xe3\x0e\x4e\x2c\xd7\x5e\xd2\x7e\xcc\xbb\x6d\x4f\x8d\xf3\xed\x2f\xe8\x61\xb7\xdc\x0d\x57\x69\xd5\x93\xae\x9e\x3b\x9b\x1e\x75\x7e\x4b\xec\x15\xf8\x67\xcd\xa1\xfd\x78\x4e\xbb\x1c\x1e\x78\x1b\x18\x3e\x10\x5b\xcf\x1e\x03\x39\xa0\xf6\xa2\xb1\x2b\x5c\x51\xc6\x9c\xc4\x31\xab\x94\x80\x55\xae\x1e\xb0\xda\x4d\x02\x56\x17\x8d\x57\xc5\x18\x9b\x27\x93\xe4\x1f\xfe\x51\xb0\xca\xfd\xcb\x11\xaa\x7f\x18\x97\x22\xf7\x3d\xc2\xf3\xd7\x71\x45\xc0\x06\xbc\x20\x17\x2c\xb9\x28\xa6\x47\x97\x45\x8e\x1c\x77\x91\x80\x54\x7a\x19\x54\x42\x38\x2b\x23\xb8\x71\xa0\xdc\x07\xc3\x6a\x96\x3b\xa1\xe6\xfd\x3b\xa8\x5f\x15\x48\x1d\xb0\xe2\x13\x14\x6b\x44\xc9\x12\x55\x8e\x14\x82\xa7\xfa\x02\x17\xa1\xc8\x6c\xe7\x22\xbc\xd0\x89\xfa\x26\xd5\x69\x30\xc5\x3b\x71\x67\xd2\xc4\x26\x73\x45\xc0\x8c\x2b\x89\x37\x77\x61\x97\x11\xd0\xcb\x92\xe3\xf6\xb6\x6c\x5b\xce\x45\xed\x74\xcc\x82\x5f\x38\xdd\x09\xc5\x44\x12\x71\xe9\x6d\x27\xe4\x3f\x6b\xbc\x33\x2e\xc2\xff\x93\x62\xd3\xfd\x9d\xe9\x43\x53\xac\x3c\x53\xdf\x69\x3a\x00\x03\x6a\x2f\x9c\x66\x96\x99\xea\x40\x10\x94\x82\x08\xe8\x0b\xee\x02\xd1\x34\x34\x23\x01\x59\x95\x4c\x09\x25\xbf\x2c\x6a\x81\x20\x4c\x52\xde\x3d\xb8\x04\x54\xfa\x61\x9b\x91\x2b\x25\x94\x5c\x5e\xed\x0d\xc3\x6a\xb9\x3b\xa1\xf6\x87\x61\xb5\x77\xae\x20\x36\x32\x81\x8c\xfc\x1e\x3d\x23\x68\xbf\x97\x0b\xbb\x39\x93\x94\x56\xc4\x63\x0f\x56\x4a\x13\x44\xc5\x1b\x51\x7a\x08\x8d\x80\xe3\x4d\x9e\x0c\xb2\xeb\xa5\xde\x62\x85\x5c\xe6\x93\x2b\x2a\x65\x13\x85\x75\x94\x93\xd5\x94\xe5\xa1\x94\xea\x40\xe3\x24\xa4\x44\x6c\x6b\x17\x7d\xb7\xf2\x95\x6a\x5b\xef\x9e\xcb\xb3\x6f\xc9\x19\xe4\xcc\xcd\x0a\x84\xa4\xeb\xb3\xf6\x70\xb7\x6e\x1b\xb1\x68\xc3\xde\x91\xd5\x35\xbb\xa7\x4d\x1c\x39\x76\xfb\x68\x78\xab\x11\xba\x85\xb5\x6f\xc3\xda\xd7\xf6\xcf\x90\xfb\x69\xdf\xd5\x6b\x07\xfa\x94\x85\x0a\xed\x73\x6d\xae\x37\xa6\x8d\x7c\xf5\xb9\x69\x53\x63\x30\x7b\x6d\xed\xfd\xbf\xd3\xfe\x44\x9d\x6a\x9f\x8f\x05\x03\x2e\x9c\xa6\x77\x98\xea\x40\x21\xe8\x05\xca\xd0\x99\xc9\x47\x67\x26\x60\x4a\x44\xad\x90\x94\x04\xc4\xbd\x69\xf9\x56\x47\x58\xf5\xa2\x19\x92\xf1\x0c\x65\x5a\x13\x31\x2e\x13\x59\x55\xc9\x89\x4d\x43\x0f\x18\x56\x8b\xdd\x09\x3c\x67\x52\x26\xb2\xf7\x74\x04\xcd\x47\x13\x6f\xf5\xf9\x03\xf9\xdd\x7a\xa1\x49\x2b\x16\xa3\x8e\x50\x2e\xee\xbf\x08\xe4\x0b\xa2\x12\xc2\x01\x39\x90\x1b\xc1\xda\xd4\xf8\x7f\xc1\x0b\xb8\x7e\x53\xb1\x92\xf0\xa3\xd4\xbb\xa2\xb2\xbc\x93\x9c\x47\x3f\xc8\x19\xa5\x7d\x46\xe5\x40\xdb\xcc\x0d\x58\xbd\x72\xf0\xf5\x9f\xc6\xf7\x3f\x7e\x79\x78\xee\x75\x33\x1f\x1e\x7f\xcb\xec\xec\x19\xab\xd6\x4f\x99\x38\x78\xfd\xd8\x8d\x6f\xec\x38\x0c\xbf\x4e\x4e\x98\xe9\xe1\x8d\xe9\x5c\xa0\xee\xba\xa5\xdb\xab\x16\xa5\x15\xde\x56\x7d\xe5\x75\xab\x26\xdd\x3e\x74\x78\x51\xaf\xd5\x37\xae\x64\x6e\x6a\x1f\xe7\xa6\x41\x44\x73\x33\xa5\xa6\x3a\x90\x0e\xf2\x40\x7e\x12\x3f\x43\xb4\x7f\xcc\x68\xa2\x3c\x5c\x42\x71\x95\x1a\xb5\x60\xfa\x0d\x83\xbd\x74\x07\x0e\xe2\x20\x48\xea\xb4\x62\x1f\x40\x84\x7a\x9a\x83\x57\x72\x72\x4e\x0a\x6a\xc0\x9d\x50\x02\xa5\x6a\x8e\x3b\xa1\x16\x42\x52\xcd\x8e\xd3\xf7\x38\x09\x19\x37\xa3\xed\x84\xb7\x99\x07\x08\x62\x8c\x66\x6c\x22\x49\x00\x48\x32\x27\x0f\xa4\x3a\xd4\x71\x39\x21\x47\xa7\xcc\x46\xe4\xcb\xe5\x5e\xeb\x15\x93\x67\x5f\x3d\x67\xb9\xf7\xec\xee\xf3\x9e\xab\x07\x0f\x7f\xfa\xa1\x9c\x31\xf0\xf1\x64\x7e\xbe\xea\xe8\xf0\xe1\xf2\xe2\x39\x43\xc6\x9d\xbb\x8f\x59\x7f\x47\xf7\x4b\xae\xbb\xf7\xe3\x35\x5a\x61\x87\xb4\x3d\xa0\x71\x9c\x7f\xaf\xa9\x0e\x08\x20\x03\x64\x82\x85\x9d\xa3\xfc\x46\x71\x24\x67\xed\x10\xcc\xf7\xc2\xb0\xea\x73\x27\x10\x52\xfa\x17\x22\xf7\x1c\x8e\xdc\x8b\x52\x46\x9e\x2f\xa2\xfa\xbc\x82\xa8\xda\xb1\xa7\xd4\x21\x6c\xdf\x65\xa8\xbe\x6d\xfc\xed\xc3\xf2\x9f\x18\xa3\xee\x18\x88\xaf\x4b\x1d\x2d\x03\xe6\x5e\x38\xcd\x0c\x35\xc5\x71\x85\x42\x21\x28\x03\x67\x40\x54\x00\xa4\x74\x84\x28\xc1\x33\x0e\x59\x46\x7e\x5d\x4f\x39\xee\x23\xa6\x34\x5c\x66\x9c\x0d\xe4\x35\x99\xca\xda\x4f\x01\xae\x62\x20\x89\x3c\x47\x72\x1f\x28\xc5\x68\xf1\xbb\x49\x09\xa5\x5b\xa9\x5a\x2c\x25\x94\x62\x5e\x09\xa1\x57\xb9\x9e\x84\x92\x5b\xaa\x86\x3c\xf8\x3c\xe1\x39\xfb\xdb\xf7\xb7\xa6\xcc\x19\x83\x26\xcd\x94\xac\x0c\xb4\x29\x26\x3e\xc6\x9a\x18\x29\x1c\x65\x4d\x4c\x6a\x29\x1a\x85\xfd\xea\x94\x69\x4d\x73\x0b\xa2\x6a\x15\x22\x11\x25\x57\x50\x03\x85\x91\x88\x12\x12\xd5\x70\x4f\x5c\x35\x41\xc0\x87\xea\xcb\x14\xc4\x68\x20\xa7\x90\x64\xca\xd0\xe4\x5a\x49\x8d\x93\x28\xc8\x3c\x08\xb6\x2b\xd3\xe9\x2a\x13\x32\x37\x30\x6d\xf7\xa0\xeb\xe8\xbb\x6f\x7f\xe5\xcd\xb8\xf6\xae\xf6\xde\x9e\xc3\x30\xa7\xeb\x74\x08\xac\xbe\x66\x05\x95\xa1\xed\xd4\x36\x54\xdc\x33\x19\x7e\x0d\x3f\x6a\x7d\xa3\xf5\x8f\x2f\x32\x7b\x2f\x92\x15\xa1\x88\x3d\x67\x6a\xb0\x3d\xbf\xfa\x1f\xd9\xf2\x9e\x86\x2d\x57\x7b\x21\x14\xfa\x1f\xb2\xd1\xff\xb4\x61\xfe\xe7\xcc\x31\xc9\xf5\x9c\xd0\xdc\xcc\x7c\x53\x00\xf7\x7b\x3f\xaf\xef\xb5\x34\x0e\xdd\xc3\x8a\x47\x56\xb2\x4b\xd5\x1c\x2e\xa1\x14\x62\xde\x2a\xa8\x84\xf1\xb8\x3c\x56\xdc\x60\x97\x89\x76\x13\x9f\x50\xf2\xd0\xbe\x31\x5b\x13\xc8\x10\xeb\xc1\xf4\xe7\x52\x35\xda\x3d\xbc\xd2\xbd\x39\xe6\xf6\x74\x97\xc2\x31\x2f\x7a\x46\xdd\x9e\xee\x29\x11\x19\x6f\x04\xc4\xa0\xdb\xdb\x9d\xe0\x19\xe3\x13\xde\x32\x99\x1e\x41\xdc\xcd\x0a\x36\x92\x99\x04\x6a\x0e\xe1\x79\x57\x0a\x05\xec\x6d\xd0\x50\xb7\x41\x26\xec\x70\x80\x50\x6e\x41\x21\x2d\x11\x2d\x26\x3e\x18\xaa\x4c\x56\xbf\x73\xa5\x70\x58\xc1\x43\x87\x17\x3e\xff\x72\x74\xd7\xac\x79\xda\x8f\x7f\x1a\xb1\x62\xc8\xec\xd5\x72\xc3\x35\x0d\x71\xed\xc3\xcb\x83\x83\x9e\x79\xfe\xce\xd1\x75\x4f\x14\x68\x6e\x53\xef\xe7\x5e\x1e\xb7\x67\xf3\x96\xdf\x17\x64\x3e\xb7\xe0\x43\xed\xdb\xb2\xfe\xad\xfb\xa8\x43\xdd\x4a\x5e\x5c\x09\xc5\xd5\x5b\xd6\xd4\x4e\x5f\x15\x05\x10\x0c\xd3\xdc\x4c\x1a\x53\x05\x78\xd0\x0f\x10\x13\x64\x97\x15\x50\x8a\x43\x59\xf4\x49\x7c\xf0\xf8\x32\x85\xe1\x55\x20\x61\x40\x83\x8c\x2e\x8e\xe3\x53\xba\x1c\x24\xf1\x95\x2a\x24\x5a\x96\xb2\xa1\x47\xae\xa8\x84\x32\xa4\xe8\x61\xdd\x97\x6c\x6b\xba\xce\xee\x60\xae\x1c\x05\x2b\x0f\xb5\xee\x5b\x5a\xae\xb9\xff\x02\x45\x66\x60\xeb\x9e\xaa\x77\xae\xd8\x1e\xa3\x06\x9f\x7b\x47\xfb\x59\xbb\x80\xe3\x13\x83\x2e\x9c\x66\xea\x4c\x01\xdc\xb5\x35\x11\x44\x33\xd1\xba\x85\xf0\x3d\xa0\x5a\x4c\x09\xbd\x57\x4b\xcd\xb1\x26\x94\x1c\xdc\xaf\xa4\x8a\x2e\x4c\x9e\x5c\x00\xc3\xaa\xdf\x4a\x32\xbf\x58\x77\x22\x33\x14\xc1\xbc\x03\x16\x17\xed\x29\x42\x57\xa5\x1f\xed\x55\xa0\xba\x42\x82\x18\x07\x26\xbb\x1f\xbf\xb4\x08\xa4\x25\xae\x37\xa8\xec\x5a\xe2\x8a\x32\x85\x72\xb1\xaf\xa7\x0b\x61\x39\xe1\x20\x68\xd6\x46\x0f\x7d\x63\xeb\x81\xdf\x0d\xaa\x99\xd7\x7f\xec\xad\xfd\x66\x2c\x98\x31\xef\xbb\x4d\xb3\xf6\xde\xb1\x67\xd6\xcc\x86\x7d\x57\x5c\xf7\xd6\x5f\x60\xdd\x29\x58\x70\xf9\xf5\xcb\x6f\x58\xb2\xab\x6e\x4e\x9f\xee\x35\x83\xfb\xd6\xdc\x3a\xf5\xc3\xb9\x1b\xb5\xd6\xa5\xb7\x47\x7f\x3b\x7b\xf1\x5f\x1a\x6f\x7b\xf2\xb2\x5e\x7f\x47\xbe\x18\xc6\x0a\xcc\x28\x50\x08\x26\xfd\x23\x9c\xd0\xad\x33\x4e\x50\x8b\x52\xc1\xc1\x7f\x1c\x03\xfc\xa3\x8b\xff\x97\xae\x7b\x64\x5b\xb4\x5a\x26\x62\x72\x83\x1c\x10\x04\xd7\x61\xb6\x58\xb3\x9e\x9b\x04\x27\x55\xa7\x84\x2f\x6e\xe4\x3b\x7a\x5c\xd8\xd7\x57\x9d\x68\x0b\x05\x22\x4a\x86\x10\x37\x73\x82\x3f\x1b\x2d\x90\x47\x54\x45\x5c\x7d\x65\xe6\x92\x2e\xaf\xd4\x5b\x04\xf9\xa6\x30\x44\xc8\xdf\x0c\xf1\x4a\x51\x1e\x37\x17\xc2\xfd\x40\x85\x25\x90\xad\x5d\x0b\x7b\xc1\xac\xd1\x1b\x4f\x04\xa9\xa7\x32\xf7\x68\x87\xb5\xef\x86\xdd\x77\x67\x6d\xe9\xce\xfd\xe3\xaa\xaf\xbc\x77\xc3\x2c\x78\x12\xce\x5b\x01\xcb\xe0\x0d\x5f\xdb\x57\x2d\xd8\xa4\x7d\xa5\xdd\xfb\xec\xf8\xba\xf2\x92\x6b\x47\x0e\x58\xbe\x64\xc4\xcc\xbe\x3d\x06\xf6\xbc\x7c\xe7\xcd\x00\x12\x7c\xc2\xd4\x80\x74\x30\xf9\xa2\xd8\x24\xe3\x9f\xc6\x26\xd8\xb0\xb4\x07\x22\xaa\xd9\x13\xf9\x17\x40\xc8\x45\x90\xc7\x45\xf0\x06\xc1\x18\xc8\xbe\x57\x9a\x02\xc0\x0e\x3c\x20\x0b\x0c\xd3\xeb\x7e\x78\x2e\xa1\xb8\x4b\xd1\xb6\x52\x32\x4a\x55\x86\x4b\xb6\x6a\x39\xf8\x64\x3d\xaa\x49\x48\xa8\x01\xbd\x1e\x35\xc6\x58\x25\x2f\x36\x55\x6e\x9e\x5c\x69\x19\x5e\x43\x17\x8d\x17\x81\x9c\x23\xb8\x29\x60\x18\x76\x51\x0a\x9a\xa4\x60\x45\x39\x1f\xca\xa5\x6a\x1b\xa1\x70\x18\x5e\xa7\x6a\x5f\x1d\x7c\xfa\x39\xe5\xe6\x51\x73\x9a\xae\x6f\xfd\x3c\x70\x29\xe5\xcd\xda\xf5\xc8\x8b\x70\x19\xe4\xa8\x3b\x61\xba\x76\xcd\xd9\xd6\x8d\xda\x27\x27\x3e\x5f\xb5\x10\xda\xe1\xe5\xeb\x60\xef\x65\x0f\x42\xb7\x76\x16\x9d\x0f\x84\x91\xdc\x4c\x15\x10\xc0\xf4\xae\xf0\x91\xd8\x19\x1f\xa9\xd2\xbf\x0a\x8a\x54\x8b\xeb\x9f\x84\x41\xed\xb1\x4f\x07\xc8\x83\x63\x2b\x95\x00\x30\x32\x53\x05\x5c\x60\xb1\xee\x2b\xdb\x5c\xb2\x8c\x37\x8e\x4a\x99\x65\xd9\x68\xcf\x72\x59\x71\xa8\xcb\xc8\x39\x09\xfa\x77\xde\xfd\x5d\x39\x09\x87\x6c\x6a\x79\x07\xc3\x10\x17\x1f\xa3\x5d\x14\x0e\x6f\x51\x52\x38\xea\x74\x75\xca\x39\x39\x71\xce\xc9\x99\x92\x73\x8a\x9a\xd0\x61\x37\x22\x07\x26\x47\x84\xec\x2a\xda\xe4\x82\x32\x89\x14\x71\x74\xe5\x17\x8d\x03\x78\x4f\x90\xa1\xcc\xef\x6a\x45\x30\xff\xd5\xbf\xae\xb8\x81\xa9\xd2\xbe\xba\xee\xea\xa9\x94\x47\x2b\x6a\x5d\x4c\x51\x33\xb4\x3a\x40\x5d\x58\x7c\xe1\x34\xbd\xcc\x14\x04\xd9\x20\x00\x56\xe9\x51\x0d\x49\x26\x35\x57\xbc\x29\xa1\x00\x5e\x15\xd9\x84\xc2\x96\x92\x72\xeb\x9c\x52\xc3\x9b\x6d\x5e\xfc\xd3\xa6\xa4\x8b\xef\x6f\x56\x1d\xe9\x67\x14\x67\xb3\x42\xf1\x31\x48\xf9\xa5\x70\x2c\x0d\x3d\xa3\x90\xf2\xa7\x8c\x27\x2d\x02\x76\x43\xca\xe1\xf4\xa7\xe9\x7d\x29\xed\xfe\x45\x12\x19\xac\x28\x88\x51\x2e\x23\x10\x41\xe6\x8c\xdc\x97\x21\x58\x88\x6c\x18\x57\x88\x15\xfa\xa4\x64\xed\x78\x21\xce\xac\x5b\x60\x1d\x35\x55\xb2\x5f\x7b\x69\xff\xee\xbe\x2b\xaf\x5d\xb2\xc0\x3d\xc3\x31\x20\x98\x2b\x5f\x76\xeb\x4d\xf6\x22\xb1\x7f\x3f\x6d\x33\xbc\x9d\x91\x97\xde\x79\x8b\xb5\x5e\x58\xa0\x9e\xa7\xa6\xd8\xe7\x7b\xc7\x4d\x81\x8f\xae\xdc\xb0\x66\x72\x6b\x3d\x33\x08\xc0\x0b\xef\x68\x6e\xa6\x8e\xa9\x02\x69\xe0\x2d\xb2\x07\xa3\x6e\x9c\xe0\xe6\x12\xfa\xba\xda\x65\xcc\x22\x94\x26\x1b\x5d\x6d\x69\x3c\x06\xa6\x29\x09\x67\x6c\x0f\x48\xaf\x1b\x8e\x91\xf1\xc9\x0a\xd5\x81\x5b\x5b\xbe\x24\x6b\xde\xd0\xb2\x01\xaf\x79\x1a\x1f\xa3\xd3\xd0\x9a\xfb\xf0\xd3\x8f\x9e\x51\x7f\x5a\xea\xca\xfb\xf0\xe2\x47\x69\x9f\x1f\x47\x00\xc8\xdf\x78\x03\x40\x1d\x94\x51\x82\xca\xb9\x0d\x3b\xc3\x0b\x98\xd0\xd4\x45\x7e\x04\x05\xfc\x02\x01\x0d\x7d\x7b\xe3\x6c\x10\x1d\xaa\xc4\xf0\xac\x30\xc4\xd1\xc5\x70\x68\x7c\x99\xb4\xb4\x7a\xf3\x43\xa1\x89\x0a\x32\x3b\x35\xbb\x6a\xa6\xf7\x32\x17\x5d\xae\xb9\x4d\x15\xad\x43\x6e\x2a\x59\x36\xe3\x83\xf5\xf0\xc3\x73\x8d\x47\x1f\x18\x5b\x73\x56\x7b\x19\xef\xfd\x5a\x00\x18\x33\x53\x05\xec\xe0\x41\x10\xb5\xa3\x79\x02\x68\x7a\x20\xd7\x96\x6a\x85\xd6\x84\x02\x49\x4d\xb8\x59\x48\xa6\x5a\x9b\xc7\xff\x7c\xca\x48\x26\xd8\x49\x7c\x83\x6e\xee\xb2\x13\x44\xa5\x68\x34\x5e\x3b\xee\x50\xc4\xe3\xd5\xdb\xda\x81\x0a\xec\x7a\xb3\xaa\x24\xa7\x43\x5f\x85\x28\xc9\x14\xe0\x42\xb5\xbb\xc3\x65\xec\xf3\x9f\x5f\x1b\xbd\x5e\xfb\xf3\xcf\x2f\x32\x55\xda\x1c\xed\xba\xfb\x9e\x86\x87\xe0\x20\x6d\xb1\x46\xbf\x8f\x31\xc7\x30\xad\x96\x6e\x31\xb9\x41\x19\x90\xc1\x2c\xa0\xa4\x97\xaa\x3e\x53\x42\xb1\x97\x2a\xbc\xac\x3a\xd1\xae\xee\x8d\xbf\x7b\xb6\x15\xd7\xb3\x23\xd0\xe1\xe1\x31\x54\x44\x2e\x7a\xbe\x35\xa1\x96\xc3\xb0\x9a\x8d\x2e\xaf\x5e\x11\xd5\x63\x12\xc4\x98\xc3\x59\xd4\x13\xdd\x5e\x3d\x84\x28\x43\x07\xd1\x56\xcd\x17\xa3\xb9\x96\x6e\xf8\x54\xfa\xd2\x0d\x67\xde\x2e\xa8\x26\x4f\x24\xa2\x38\x89\x5e\x2b\xbe\x96\x0b\xca\x7b\x57\x54\x72\xf8\x76\xe3\x90\xd9\xf7\xb8\x83\xb2\xfe\x81\xdc\x73\x26\x72\xd1\x95\xa0\x4d\xcf\x0e\xfb\xf8\xf5\x53\xbb\x57\xf6\xba\xea\xe6\xbe\x41\xea\xce\x80\xf9\xb1\xaf\xe6\xc3\xc2\x9a\xc0\xf5\x8b\x3e\x7c\xe0\x96\x87\x6e\xbb\xbd\xe2\xba\xdb\x5e\xba\xfb\xea\x9c\xab\x6f\x59\xf1\x10\x15\x82\x53\x9f\x3d\x5d\x6c\xba\xb4\xf9\x9e\x3d\x79\x8c\x79\xd5\xa2\x1b\x96\xdd\xf6\xce\x6f\x47\x6c\x9a\x72\xcb\x24\x39\x6f\xd0\xe8\xfe\xd7\x2c\xb8\x71\xec\xe4\x8a\xdc\xb2\xee\xb9\x7d\xb7\x4f\xc3\x7e\xc1\xb7\x4c\x90\xb9\xa9\x7d\x0e\xce\xe8\x65\xf0\x73\x6d\x39\x38\x6b\x5b\x0e\x4e\xfa\xc5\x1c\x1c\xf6\x0a\xbc\x04\x51\x75\xf4\x00\x56\xfc\xb4\xf6\xe0\x07\x4b\x7f\x7e\xb2\xf9\xfd\xa6\x59\x77\x8f\x79\xfa\x96\xfb\xc6\x4f\xda\x31\x0a\x36\x34\xc3\xa1\xd1\x3f\x1f\x39\xa0\xc5\x76\x7f\xf6\xc2\x23\x0b\xeb\xa1\xe9\xd9\xba\x45\x2b\xb4\x73\x68\xaf\x0d\xb9\x70\x9a\xb5\x32\x55\x20\x1d\x3c\x4d\xbc\x16\xd5\xe9\x97\x65\x9c\x85\x50\x6d\x1c\x71\x0b\xd9\x44\x94\x42\x5f\x37\xdd\x9c\x88\xb2\x5e\x1f\x6e\xd2\xcb\xc0\xad\x09\x7e\x6b\x42\xf1\x93\x10\xb5\x99\xdc\xcc\xf8\x24\x2e\x69\x99\x85\xb7\x61\x1a\xaf\xa4\x37\x2b\x7e\x5e\xf1\x35\xef\x1b\xb8\xf3\x3b\x0e\xbf\xf4\x96\x38\x15\x4f\x33\xab\xb2\x3c\xd1\x9c\x55\x4d\x1e\x64\xa1\x58\x93\xc7\xeb\x4b\x4f\xc9\x36\x4b\x7e\x1d\x11\xa7\x3b\xd0\x0d\x2f\xe1\xc1\x5f\x02\x83\x5c\x88\x4e\xed\x9d\x2c\xef\x5d\x29\x05\xe9\x90\x34\xc4\x79\x84\x4e\x64\xbf\xfb\xb8\x3d\x37\x27\x5c\x7c\xfd\x15\x35\x63\xc4\x79\xda\x9c\x37\x9b\x8e\xd1\x4a\xd5\xd0\xb5\xad\x53\xfb\x14\x04\x42\xfc\x22\xff\xe8\xea\xe2\xd1\xd4\xdc\xf3\x43\x69\x05\x50\xd8\x1e\xc9\xcc\x28\x20\x80\x00\x50\xf4\xb5\xf1\x18\x6b\x93\x49\x9c\x1c\x41\x36\xc2\xf5\x82\x80\x23\xb0\x69\x7a\x7a\x3e\x98\x8c\xc0\xbe\x96\xea\xcd\x08\xbc\x12\x68\x8e\x39\x85\x80\x14\x8e\xb9\xf0\x93\xc7\x4f\x11\x3d\xa3\x2e\x21\x90\x62\x7c\xf8\x88\xe2\x8c\x28\x22\x32\xd6\x4e\x31\xe0\xe2\x93\xc6\x3a\xe5\x5f\xc4\x35\x16\x92\x3b\x01\xb9\x3c\xa4\x17\x5a\xd2\x1b\xe5\xf0\x3e\x28\x74\x42\xdd\xb3\x31\xba\x3c\x8a\xbf\x95\x7f\x6c\x3e\xf0\xfa\x92\xc4\xca\x9b\x96\x5e\x61\x2d\xb8\x66\x6d\xe9\x6f\xae\x9c\xf0\x74\xcd\xd4\x29\x33\x96\x87\x35\x37\x33\xfd\x87\x3f\x7d\xf8\x4e\xb3\xf6\xfc\xf3\xfd\xae\xb8\xe2\xf7\xda\x8b\xd4\xfb\xbd\x23\xcb\xa1\xf9\x89\x85\xf5\x5b\x0f\xe3\xb3\x5c\xab\x0d\xc7\x3d\x38\x01\x90\x03\x06\x83\x64\xeb\x8d\xd1\xc8\xad\xe7\x26\xd2\x11\x6c\x16\x48\xd8\xdd\x81\x0e\x6e\x76\x44\x49\x17\xa2\xbc\x2f\x0b\x9d\x55\x49\x8c\x31\x82\x85\xe0\x1d\xc6\x92\xd4\x7f\x6d\xdf\x62\x43\x04\x70\x53\x41\xe7\x3a\x48\x3d\x5d\xff\xb0\x5c\x77\xd7\xe4\x67\x27\xd7\xcc\x5d\x50\x7b\xc3\x2d\xcd\xb7\xde\x7a\xf5\x84\xa7\x1e\xa3\x28\xb8\xed\x20\x1c\xf4\x7c\x79\x43\xef\x79\x17\xc0\xe3\x33\x17\xc8\x95\xf7\xdf\x34\xa8\x7e\x58\xf5\x9c\x4b\xca\xfa\x77\xbb\xf4\xf7\xb3\xf4\xf3\x76\x0c\xfb\x5e\x99\xe0\x3a\x10\x75\xa2\x35\x75\x1b\x6b\x9a\xce\x25\x30\xe3\x01\x89\x06\xe9\xb5\xe7\x3e\x18\x56\xad\x3c\x8e\x01\x11\xf6\x09\x27\xbe\x10\x39\xb4\xf3\xdc\xe8\xd8\x19\x58\x39\x4f\x0e\x72\x41\xc3\x97\xd1\x21\x5a\x79\xef\x42\x84\xce\x9e\x80\xbe\x57\xe0\xf9\x2c\xed\xfb\x8a\x6e\x0b\x12\xab\x8f\x9c\x68\xba\x77\xc6\x06\xe5\xea\x2b\x4e\x7c\x0c\xa3\x6f\xc2\x1e\x1b\x57\x8f\xde\x30\xea\x59\xed\xbd\x86\xcf\xfe\xb4\x72\x3d\x74\xfc\xa0\xcc\x22\x98\x6c\xc8\x85\xd3\xf4\x16\xa6\x0a\xf8\xc0\x34\xdd\xb3\xb6\x71\xfa\x51\xf3\x99\x49\xb6\xdb\x8f\xeb\x0f\xd1\xd9\x4a\xd3\xf7\x5b\x43\x0b\x86\x03\x8a\xaf\xc4\xa9\x78\xdb\x1d\x23\x2f\xf2\x8f\x59\x93\xd7\xd7\x56\xb0\xe1\xd6\x8f\x90\x4d\x1f\x97\x4f\x50\x1d\xee\xe4\x41\x0a\xb6\x8b\x29\xe0\x93\x34\xc4\x79\x98\x9a\x17\xd4\xe2\xf7\xf8\xca\xfa\xf5\x1d\x91\x75\x57\xe8\x91\xc7\xd2\xeb\xc8\x11\xfa\xf4\x2e\xb9\xe7\x65\x08\xa0\xdd\x37\x33\xf2\x1b\x2a\x1d\x40\x12\x8b\x62\xaa\x80\x04\xd6\x77\x15\x85\x32\x12\xdf\x5d\x45\x9d\xf4\x50\x53\x32\x0b\xfe\x9f\x0a\x22\x39\x18\x3d\x88\xd4\x31\x63\xd5\x21\x50\xd4\x45\x24\xa8\xcb\x88\x8f\x7e\x16\xdc\xac\x9d\x19\x85\xd9\xd7\xde\x20\x3d\x5b\x8a\x1b\x73\x11\x2a\xe9\x65\x51\x09\x17\x2b\x20\x87\xc6\x81\x46\x9e\xc3\x25\x14\x6f\xa9\xe2\x91\x8d\xd6\x34\x4e\x48\x86\x1a\x3d\x42\x42\x61\xca\xd0\x8d\x97\xad\x37\x3c\xe4\x27\x6b\xa4\x8e\x91\xf1\x7b\x79\xc5\x8a\x63\x22\xa1\x66\x56\xf1\xf2\x31\x8b\xd7\x6a\xb4\x39\x84\x48\x5b\xb2\xcf\x78\x93\x8e\xde\xd0\x40\xb5\x86\x90\xd1\xb0\x58\xdd\xbe\xf4\x50\xd2\x68\xa8\x1e\x2f\xee\x56\x55\xb2\x05\xc5\x11\x01\x6a\x8e\x45\x10\xa3\x80\xe3\xd1\xb9\xa4\x05\x72\xbf\xf7\x16\x2b\x7d\x26\xca\xc3\xfb\x92\xa6\x84\xe1\xb0\x1c\x33\x3b\x10\x8a\xa4\xdf\xb6\x76\x4d\x53\xdd\xf2\x87\x3e\x9b\x57\xf4\xfc\x92\xfa\xb5\x1b\xb4\x8f\x8e\xd4\x46\xc7\x28\x47\xa8\x41\x8f\xbc\x34\xe5\xe1\x41\xd7\xfb\xe0\xe6\x97\xe0\x55\xcf\x4e\x5e\xac\x7d\xb7\x4e\xfb\x2a\x9b\x9a\xb9\x7f\xdb\x8b\x8d\xef\x69\x5b\x9b\x1d\x5a\x18\xbe\xef\xfd\x6c\xbc\x63\x0d\xf4\x6d\xff\x64\xda\x3d\x24\xaf\x97\xa6\xb9\x99\x91\xcc\x10\x10\x00\x8d\x00\xbb\xe6\x8a\x4b\x56\x59\x34\x8b\x98\xe3\xc3\x63\x6a\x0f\x7c\x1f\xfb\xe9\x8f\x49\xe0\x9b\xd5\xac\x3a\xf2\xce\x28\xa2\x0e\x7c\xb3\xa4\xb0\xe2\xe0\x63\x4e\x87\x28\x85\x63\x02\x7a\xa2\xf7\xd9\xe8\x7d\xd4\xe9\x10\x53\x6c\xac\x10\x89\x42\x2a\x0b\x7d\xca\xc6\x0d\xdb\x0e\xa7\x20\x66\x65\x27\x1b\xb6\x3b\xbd\x21\xe0\xd8\x93\x2e\x88\x8a\x3f\xa2\xb0\x84\x52\x03\xf9\xfb\x24\xa0\x44\xa7\x02\x64\x28\x43\x6c\x73\x0d\x94\x0c\xff\x4a\xd5\xf6\xb7\xc8\x25\xee\x9e\x39\x03\xaf\x1f\x3b\x55\x2a\x84\x4f\x1c\x68\x7d\xef\x4a\x47\x9f\xbe\x79\x25\x83\x2e\x99\x7c\x8f\x50\xac\x5d\xa2\xb9\xe9\xab\xe1\x3b\xbf\x1a\xe8\x9c\x97\x55\xb7\x58\xdb\x45\x0d\x39\xff\x95\x26\xdc\x7c\x8d\x7d\xbe\x6f\xde\x0a\x38\xb9\xf5\x41\x64\x17\x16\x6b\x6e\x76\xa6\x49\x04\x19\xe0\x6d\x3d\x92\xe8\x95\xd1\xd1\x52\x1c\x65\xfa\xe9\x12\x64\x19\x99\x06\x9f\x6c\xc0\x87\x4e\x91\x6d\x3f\xb2\x66\x7c\x42\xf1\xe9\x2d\x37\x3c\x2e\xcd\x13\x60\x58\x15\xa5\xa4\x10\xfc\x25\x79\x3f\x2c\xe9\x22\x97\xfc\x64\xcb\x21\xd2\xa3\xeb\xe7\x15\x5b\xb3\xe2\x43\x60\x92\x55\xfc\x7c\xcc\xea\xb7\x49\x61\xc5\xc7\xc7\x1c\x3e\xbb\x14\x8e\x79\xd1\x13\xbd\x4f\x43\xef\x71\x0e\xd9\x66\x27\x57\x18\xc5\x5a\x1d\xde\xb4\x5f\xce\x1f\xfb\xa0\x0c\x07\x42\x74\x22\x8d\x7d\xb7\x38\x6d\xca\xee\x3b\xbd\x33\xee\x83\xc5\x8a\xf6\xce\x8e\x13\xb5\x7b\x1b\xb4\x63\x5f\x8f\x55\xc6\x1d\x7a\x19\xce\x18\x3a\x87\x62\x5a\x7f\x98\x30\x64\xd6\x23\x36\xb6\xfe\xec\x0c\xf1\x5d\x38\x17\xde\xac\xdd\xad\x95\x7c\xed\xd0\xf2\xe0\x7f\x49\xaf\x92\x5a\xc5\xda\x0b\xa7\xd9\xf9\x4c\x15\x28\x04\x7b\x48\x1c\x48\x09\xc8\xaa\x99\x4b\x28\x22\x99\x3b\xc5\x2f\x1b\x11\x20\x93\x15\x67\x0f\x53\xa6\x07\x9d\xd1\x0c\x04\x69\x72\x4e\x0a\x6a\x9a\x80\xc3\x42\xf8\x78\x2e\x6e\xb9\x97\xcc\x88\xad\xc4\xa9\x58\x9a\x19\xd5\x1e\x38\xe3\x54\x1c\xcd\x8a\x85\x8f\x59\x2d\x36\x29\x1c\xb5\x5a\x52\xcb\xe9\x62\x56\x9b\xdd\x41\x9a\x99\xad\x0e\xdd\x34\xd9\x4c\x38\x3a\x91\x9b\x8f\x00\xad\x5d\x50\x5c\x11\xc5\x4f\xf2\xd1\x7a\x5b\x20\xc8\xc8\xd5\x03\xdb\x62\xa5\x0c\x04\xb7\x5c\x96\x41\xfc\x0a\x1d\xe2\x15\xca\x29\xb7\x7d\x28\xb7\xa0\x76\xfe\xec\x17\xb5\x1f\x17\x3f\xd9\xf7\x32\x75\x20\x7f\x59\xff\x9b\x16\x0c\xcb\x88\x06\xe6\x7c\xb8\xbc\x66\x66\x5a\xdf\xfa\xd1\xf3\x1b\x60\x4d\x13\x7c\xa8\x49\x9b\xaa\x6d\xff\x14\xda\x61\x2f\xed\x8b\xab\x07\xfc\xea\xc6\x8d\xf0\xd2\xed\xcf\x2f\x5b\xb6\xfd\x43\x6d\xd6\x4b\xb7\xdf\x30\x6a\xf8\xcb\x7a\xfe\x64\x1f\x7b\x0a\xf7\x49\x74\x03\x2b\xbb\xee\x92\x28\x48\x76\x49\xe4\x94\x41\xa5\xe8\x1f\x74\x49\x20\xfc\x1a\x72\x27\xd4\xee\xff\x6a\x4b\xc4\x3f\x1f\x43\x90\xba\xce\xcb\xb6\x0f\x2d\x84\x3a\xa5\x66\x3b\x35\x3a\x74\xcc\xce\xd2\xe4\x5e\x63\x4f\xe1\x1c\x4b\x77\xf0\xda\xc5\x32\x2c\xdd\x92\x19\x96\xdc\x32\x23\xf6\xfd\xcf\x65\x58\x62\xf9\x4e\x87\x39\x6c\x24\xd7\xf2\xdd\x6d\xb1\xf1\xff\x78\x32\xe5\x1f\xdc\x83\x17\x49\x6e\x77\x71\x3d\xf6\xeb\x34\x93\x17\xcb\x91\x74\x98\x50\x86\xf8\x40\x98\x5b\x2d\x03\xe4\x83\x82\xb6\xea\xec\x76\x7e\x50\x61\x17\x7e\x90\xc2\x19\x5d\x36\x6e\xd2\x65\xe3\xd6\xdb\xcc\x9c\x82\xb8\x9b\xb1\x09\xfe\xcc\x7c\x8c\x2e\xff\x49\xff\x28\x35\x8b\xdd\xb5\xab\x74\x63\x32\x05\x7b\x31\xa7\x89\x7a\x3e\x25\x21\xa7\xef\x15\x53\x1d\x56\xbb\xcc\x46\x5e\x44\x57\x38\x28\xf0\x8f\x70\x50\x2c\x0d\x6f\x08\xbf\x3b\xa1\xf8\x4b\xd1\x66\x51\x73\xfe\xc3\x1b\xc2\xcf\x08\x62\xcc\x2a\xb8\xb3\x48\xc7\xf8\x2f\xee\x89\xb6\x59\xea\x62\x1f\x7c\x94\x9c\xa1\xae\x97\xbf\x67\x6a\xbe\x92\x26\xf6\x38\x99\xc3\x7f\xfd\xe2\x36\x59\xbe\x88\x4d\xd6\xd3\xf7\x4a\x71\x17\xe6\xb9\xf7\xff\x3a\xf3\x1c\x75\x75\x2b\x42\x58\xa9\x87\x18\x15\x03\xbd\x22\xff\xb6\x91\x4e\xdd\x72\xff\xc0\x5e\x53\x07\x92\x53\xfb\x4f\x59\x6e\xa6\xa8\x43\xbd\xc4\x98\x0b\xa7\x99\x1a\x53\x00\x64\x80\x6e\x40\x06\xd3\x75\x7f\x3e\x9b\x4b\x28\x79\xa5\xaa\xc8\xe1\x36\xdc\x1e\x5c\x42\x29\xd3\x43\xd5\xbd\x8d\x44\x88\x92\x49\xb8\xa8\x3d\xd6\x44\xac\xd4\x13\x34\x87\x31\xb9\x44\x39\x0c\xab\xc1\x4c\x41\x6c\x62\xac\x62\x9a\xab\xa8\x47\x19\xde\x3a\x79\xd9\x68\x16\x3c\xae\x48\x24\xa2\xf6\xb0\x62\xbe\x09\xa5\x4c\xc0\x2e\x29\x0e\x61\x1b\x26\xa4\xd0\xc4\xa5\x3a\xa8\x95\x3c\xf6\x96\xb0\x6b\x6a\xd2\x73\x70\xe8\x5f\x63\x8e\xc0\x4b\x5e\x5d\xf8\x4c\xf3\xae\x61\x6b\x23\xe3\xba\x0f\x79\x63\xec\xd2\x4d\x73\xbe\x58\xf7\xd2\xc1\xa6\x0f\x17\xef\xbc\x65\xc4\xad\xca\xb5\xce\x1f\x8a\xee\x1f\x38\x7a\xdc\xb5\x55\x4f\xc0\x46\x08\xa9\x4a\xd8\x6b\xde\xd4\xc5\x0d\x15\x72\xe3\xb1\x1b\x6f\x6d\xdc\xf2\xac\xf6\xc5\xca\xaf\xdf\xd3\x8e\x43\x4e\x1d\x3b\xe9\xa6\x61\xb5\xd4\x57\xa1\x6e\x55\x97\x14\x63\xfd\x75\x50\x7e\xe1\x34\xf3\xae\x29\x00\xca\x40\x7f\xb0\x46\xcf\x0a\xb9\x4c\x09\xe4\xc2\x4a\xb2\x9a\xcd\x26\x94\x8a\xb2\x18\x9d\x8d\xc6\xdb\xcb\x94\x50\xfa\x96\xaa\x69\x08\x82\x0e\x28\x55\xba\xe1\x66\x86\x58\x89\xbd\x9b\x19\x07\xf0\x0d\x70\x20\x0b\x09\x45\xe6\xd5\x3e\x30\x8c\xa7\x4d\x42\x1b\x31\x68\x4d\xa8\x03\x61\x58\x35\x95\x10\xa6\x3f\xd9\x2b\x88\xaa\x2b\x1f\xf9\xbf\x82\x9a\xd6\x17\xed\x9c\x5e\x2e\x41\x8c\x9a\x40\x37\x1d\x7c\xc3\x88\xda\x37\x5b\x10\xd5\x4c\x2f\xde\x49\x95\xba\xdd\xe5\x70\x6c\x0a\x6d\xa3\xca\x1e\x24\xa7\xe4\xf5\xb8\x39\x99\x0b\x59\x21\x83\xdd\xb3\x0a\x43\x18\x18\xba\xbd\x32\xce\x0b\x98\xca\xad\xbf\xbe\x66\xc8\xf0\xa0\xdb\x1d\x18\x76\xfd\xe4\xf8\x63\x79\xda\xcf\xda\xf9\xd7\x36\x2a\x07\x99\xfa\xc0\xdc\xd0\x01\xed\xa7\x67\x1a\x76\x76\x4b\x77\x66\x64\xfb\x4a\xe0\x0b\xdb\x0f\x9a\xf6\xdf\x78\x1b\xb5\x6f\x61\xee\xcd\x83\xfa\xdd\x55\x5e\x31\xbe\xcf\xb5\x83\x9f\x86\x55\x9f\xb0\x2f\xec\xda\x7c\xe4\xc2\x57\x97\xe6\x2d\xd0\x34\x6d\xf2\x91\x27\x1e\x1b\x34\xe7\x92\x82\xaa\xdc\xcc\x2c\xf8\xf9\xcc\x7b\xb2\xab\x60\xf5\x34\xbd\xa6\x36\xc1\x1e\x06\x1e\xf0\x38\xc0\x61\x5b\x45\x92\xa3\x1c\x05\x08\xcd\xb9\x83\x57\x2d\x6c\x42\x05\x50\xa7\xb1\x71\x9f\x54\x25\x29\x11\x83\x92\xbb\x7d\x79\xad\x4f\x3f\xb0\xcf\x7d\x67\x23\x56\x0d\xd7\x27\xea\x3d\x0d\xc9\x0a\x2d\xb7\x07\x57\x68\x79\x52\x2a\xb4\x70\x6d\x22\xd4\xff\x6e\xab\xd0\xaa\x10\x31\x01\x20\x4e\xbd\x39\x21\xc5\x91\x5a\xdb\xea\x4f\x66\x8f\xbb\xa2\xf8\xb2\x02\x67\x9a\xd0\xe3\xd7\xb3\x5f\x9f\x74\x17\x29\xbb\xdd\x08\x67\x35\x44\x84\x65\x34\x77\xc3\x01\x4d\xdd\xdb\x7a\x9a\xca\x07\x34\x18\x0a\x80\xc9\x64\xe2\x70\x5f\x70\x0e\xf8\x1d\x88\x06\xd0\xd8\xb2\x65\x9d\x59\x96\xc3\xf1\x2d\x37\x9b\x50\x6d\x76\x34\xb6\x60\x6a\x77\x70\x00\x86\xd5\x6c\x29\x11\xb3\x67\x07\xda\x77\x07\xe7\x76\x1c\x66\x80\x57\x72\x9a\x95\x6c\xe4\xc7\xb4\x0d\x33\x90\x83\xbb\x83\x73\x52\xba\x83\xb3\x72\x48\x77\x30\xfe\x9b\xb8\x22\xfe\x40\xb2\x3b\x58\x15\xdd\x7a\xff\x4b\x4a\x19\x49\x65\x97\xb3\x30\xd4\x30\x25\x6b\xba\x9c\x0e\xe6\xce\x36\xd3\x41\x77\x39\x33\x46\xcd\x5e\x82\x2b\xc2\x5c\xf7\x3d\xc0\x73\xbf\xbc\xee\x4a\x76\xa9\xd2\x5d\x36\xb8\xf0\xf3\xca\xa0\x52\x7c\xd1\x7d\x10\xf3\xe2\x17\x19\x6e\xdc\xf0\x82\x2c\x4f\xa1\x3b\x81\x99\xb7\xff\xd7\x6e\x8e\x5f\xa8\xe5\xeb\x62\x92\xbc\x5d\x96\xf5\x75\x9e\xab\x2e\x0a\xfc\x68\x1c\x33\xa0\x4c\x6e\x20\x81\x0c\x10\x02\x47\x08\x2e\x50\x9c\xb2\xea\xe3\x12\x4a\x66\x59\x94\x23\xc8\x1a\xe7\xe4\xfd\x65\x0a\x5f\xaa\xb8\x64\x85\x2d\x55\x4c\xc9\xb8\x41\x6a\x3d\xb7\x13\x27\xb9\x0c\x01\x07\x13\xe9\xb9\xb7\xa6\xc4\x0f\x0c\x21\xb8\x7f\xb5\x9c\x3b\x13\xff\x4e\x08\x97\x73\x37\x31\xb8\x96\x3b\x33\xd4\xae\xf0\x37\xe4\x43\x48\x12\x18\x31\x30\x84\xc2\x49\xf5\x36\x71\xd9\x48\xf5\x36\x05\x07\x52\xe5\xbd\x0b\x0a\x6b\xd7\xc2\xec\x17\x6a\xb6\xd6\xbc\xf8\xc6\x53\xda\xc7\x4d\x63\xb6\x8e\xd9\xff\xea\xde\xd9\x77\x29\x0f\xed\xbb\x03\x2e\x7b\xf8\x85\x31\x0f\xdc\x0d\x0f\xed\x81\x3d\x9e\x37\xc1\x7d\xda\xd5\x69\x5f\x1f\xd9\xa7\x1d\xdd\x45\x69\x79\xf0\x7d\xff\xb7\xc7\x17\xef\xb0\xd0\x97\x72\xf3\x3f\xd7\x64\xd3\x82\xbf\xfe\x76\xe1\x33\x58\xff\x8f\x02\x93\x2e\x9c\x36\x6d\x61\xaa\x80\x07\x84\xc1\x36\xe2\x99\x28\x36\x19\x97\xa0\x84\xca\x48\xac\xcc\x63\x4e\xa8\x4c\x51\x19\x21\xa0\x15\x4f\xaa\x5e\x2b\x66\x8e\x2b\xd4\x03\xb5\xc5\xfa\x14\x8d\xff\xfb\x9b\x64\x5b\xa5\xf3\x4a\x66\xb3\x9a\x1d\x38\xa3\x64\x35\x2b\xe9\x7c\x2c\x23\x3d\x53\x0a\x47\x33\xd2\x33\x53\x11\x42\x46\x26\x89\x09\xc0\xe4\x27\x8c\x12\xbc\x22\x8e\xa8\x29\x85\x42\xd4\xe6\xf2\x20\x7b\xce\x61\x75\x1a\xd5\x93\x86\x59\x77\xc4\x48\x5b\x98\x5a\xbf\xfa\x0a\x49\x94\x5a\xac\xa4\x91\x71\x97\x2a\x65\x2e\x05\x2d\x04\xa9\x49\xae\x97\xd9\xf1\xc1\xaf\xd2\x67\xfd\x61\xe1\x91\xd2\xc9\x4d\x8b\xd6\x4f\x9b\x18\xbc\x76\xe0\xc6\x01\xf9\xbb\xb2\x85\xcb\xfa\xdf\xf0\xd8\x60\xa9\xf5\xca\xf7\x70\x04\xae\x6e\xee\x2b\xda\x8e\xe8\xfe\xfd\x71\xa5\x1e\xf6\x5d\xd5\xba\x79\xfc\x24\x68\x57\x56\x5e\x7d\x09\x82\x06\xf6\xd5\x73\x26\x69\x7b\x00\x04\x6e\xcd\xcd\x1c\x67\x6a\x40\x29\xb2\x65\x38\xd7\x5e\x84\x1e\x12\x24\xfd\x29\x76\x48\x12\x6e\xe8\xdc\x59\x4c\x18\x53\xe7\x9b\x49\x45\x12\x93\x4c\xa6\xf6\xc0\x91\x50\x5c\x9c\x84\x67\x6e\x47\xcb\x79\xbc\xb9\x8a\x4a\x9c\x4a\xb7\x66\x35\x33\x1b\xcd\x1c\x88\x66\x66\x75\xc3\x13\x94\x99\xd5\xad\x28\x39\x41\x2e\x86\x14\xfe\xf7\x10\xd4\xdc\x50\x24\xa2\xf8\xc4\x68\x4e\x7e\x09\xc6\x4f\x80\x14\x55\xa8\x5c\x8e\x20\xc6\x5d\xa2\x2f\xbd\x84\xe4\xe9\x2b\xd2\xc9\xad\x46\xc2\x2a\xe8\x22\x84\xb2\xce\xbe\x54\x49\xd4\x4f\xcb\xd1\x74\x5d\x02\x4b\x60\x79\xef\x4a\xe8\xbe\xf1\xf1\xaa\xcb\x7b\x77\xcf\x0b\xf7\x1b\xf5\x9b\x45\xfd\x7a\x52\xeb\x95\x59\xca\x80\xfe\xc5\xe1\x6a\xff\xfd\x13\xaf\x0c\x57\x76\x2b\xeb\x69\x0f\x0f\x9f\x30\xa5\x75\xf2\x23\xb0\x14\x66\x8f\xac\x1e\x22\xfc\x36\xbd\x61\xe5\xc8\xd3\xb5\xd4\xc1\x98\x96\xdb\x30\xa4\x9a\xd7\xee\x9c\x59\xe7\x6b\x90\x2a\x07\x1e\x77\xfd\x76\xce\x89\x8f\x5b\x2f\x07\x14\x50\x00\x60\x6f\x62\x8f\xe1\x5c\xc0\x5c\x12\x37\x56\x1c\x32\x69\x8a\xc9\xa4\x13\x71\xbb\xc7\xc9\x38\xc2\xaa\x9d\x4e\x36\x8f\x8a\x1e\x5c\x30\xe3\x84\x61\xd5\x61\x4d\x66\xfb\xcd\x9e\xb6\xd4\x80\xfa\x5d\x80\xec\x38\x27\xaf\xb8\x9a\x59\xc5\xc1\x2b\xf6\x66\x1a\x28\xae\x12\xa8\xda\x5d\x24\x4c\x97\xe6\x10\xc4\x28\xe3\xc9\x8c\x18\xc1\x7d\x15\x98\x93\xf1\xe6\xb2\x0e\x27\x2d\xc5\x95\x51\x14\xd8\xe7\xed\x95\x9f\xde\xb7\x51\xfb\x64\x77\x79\x63\x24\x7e\xec\xf0\x73\x2b\x16\x7d\xf8\xc0\xf6\xfa\x55\x1f\xdd\x4b\xbd\xf7\x5f\xb0\x66\xdf\x23\x9f\x35\x1c\xd7\x0e\xec\xe5\x34\x0d\xf2\x79\x3f\xec\x59\xb6\x73\x09\x84\x1b\xd6\x36\x2f\xd7\x5a\xf4\x98\x26\xce\x4b\xf1\x20\x1b\xdc\xa7\xc7\xf7\x33\x90\x45\x2f\x55\xec\x49\x8f\x45\xb0\x26\x62\x0e\x01\xb9\x2b\x76\x12\x2b\xf7\xeb\xe9\x29\xc3\x3b\x59\xd5\xf2\x4c\x0a\xb9\x22\xba\xc6\x6c\xcd\x40\xb5\xe1\x54\xba\xcd\x48\xa5\xfb\xed\x68\x88\xee\x0c\x3c\xc4\x0c\x34\x5e\x0e\xb8\x23\x1d\x7c\xb5\xae\xc6\x48\x7c\xb4\xc7\x3f\xad\x1f\xb7\x7b\xf2\x63\xcb\xba\xc8\x68\xed\xd5\x5e\x6c\xb4\x6b\xb9\xf0\x74\xfe\xbb\x2b\x3b\xe4\xb5\x8e\x00\xc0\x9a\xd9\xa3\xc0\x0b\x26\x01\x1c\xa2\x55\x44\x7d\x35\x2d\x3a\x25\x0f\x38\xa9\x3a\x3c\xc9\x0e\x0b\x51\x6a\xa3\x68\x89\x7e\x97\x4b\x46\x25\xf1\x8a\xbb\x59\x11\x79\x45\x68\x06\xaa\xe0\x46\xa3\x42\x4f\x72\x31\x5b\xa4\xb6\x88\x6a\x67\xfa\x30\x8c\xe5\xfa\x41\x3a\x24\x15\x50\x47\xf6\xc2\xa1\xbf\x7f\x7b\x75\xd5\xbc\x75\xab\x7f\x5c\xf0\xe9\xb1\xa2\xd1\xfb\x2e\x79\xf5\x27\x9a\x7f\x0d\x5e\x16\x1d\xb6\x7a\xd0\xe3\x7f\x5f\xb6\x29\xa6\x95\x43\xd9\x07\x69\x3d\x86\xa5\x6d\x60\xf2\x99\x1a\x50\x00\xa6\xe8\x2b\x63\xe5\xb0\x63\x98\xc5\x25\x94\x2c\x5e\xc9\x40\xb0\x33\x3d\xc5\x67\x26\x25\x40\x39\x24\xc2\x8c\x1d\x64\x27\x10\x44\x35\x3d\x03\x33\x6c\xc7\x44\x7f\x56\x1e\xa9\x01\x8a\x32\x92\x15\x2f\x83\x35\x43\x10\x63\x80\xf3\xe0\x0e\x89\x0e\xdf\x9e\xdc\x97\x1e\x77\x36\x24\xb9\x19\xe3\x00\xe2\xfc\x0c\x55\xfb\x14\xa4\x37\xbc\xbf\x5d\x9e\xb2\x61\xf0\x94\x1d\x93\xbb\x55\x4f\xfc\xed\xa4\x13\x7b\xc6\x5d\xfb\xeb\x1b\xc7\xcf\xbc\xec\xce\x99\x33\xaf\x86\x7b\x1a\xe1\x55\xcf\x0e\x59\xd9\x23\xe7\xd1\x9f\xe6\x0d\xfc\x55\x9f\x50\xaf\x7b\x6e\x59\xbe\x2b\x73\x45\xc6\x88\x6b\x7a\x96\xe5\x17\xde\x3c\x17\x80\xf6\x7d\xf8\xeb\xf4\x6a\x08\x5b\x1b\x07\x41\xdc\xca\xe2\x06\x74\x93\xac\x5a\xe9\x84\x62\x29\x8b\x5a\x31\xb5\xa5\x95\xd3\x79\xfd\xdb\xb5\xa3\xe3\x86\x59\xbe\xad\xf1\xbc\x7d\x47\x9d\x8d\x57\x98\xe6\x7d\x03\x7f\xd7\xf2\x37\xa3\x25\xd4\xa2\x4b\x3c\x29\x36\x3e\xc6\xda\x18\x29\x1c\xb3\xda\x70\xe7\x3e\x64\x58\x13\x69\x40\xef\xd0\xb9\x4f\x87\xa4\x20\x6d\xf0\x1b\xdc\x49\xd9\x6f\x52\xfa\x68\x9b\xe6\xb2\x8d\x9b\x5b\x7f\xd6\x46\x42\xa6\xb5\x81\xc4\xb7\xdf\xd1\xdc\xf4\x01\xa6\x0a\xd8\xc0\x4a\x40\x2a\x1a\x18\x92\x44\xb4\xc9\x98\x03\x90\x04\xbb\x4d\x17\x1b\x8d\xd0\x36\x1a\x57\x6a\x1b\xfd\xd1\xce\xa3\x79\xb2\xe5\xe0\xbf\x31\x1a\x3a\x39\x9a\x10\x5d\x0c\x87\x52\xeb\xb2\x35\xf7\x48\xb8\xad\x66\xd7\x25\x67\x1b\x35\xb7\xa9\xa2\x41\x1b\xa6\x5d\x09\x8b\xce\x6f\x02\x10\x4c\xbd\x70\x9a\x3e\xca\x1e\x05\x05\x60\x1c\xc1\xc4\x38\xfb\x6b\xc7\x3d\x82\xe6\x44\x5c\x04\x01\xbb\x23\xac\x8a\x34\xd9\x84\xe8\xee\x10\x12\xb1\x5c\x17\x63\x0e\xab\x3e\x2b\xd9\x83\xb9\xe4\x2a\x00\x6a\x7a\x40\x10\x95\xac\x88\x02\x84\xa8\x2f\x13\xb9\xcf\x2a\x27\x22\x93\x60\x41\x4e\xa4\x62\x17\x30\xa4\xcd\x80\x03\x3b\x5c\x03\x74\x90\xd6\x3d\x22\x23\xd3\x5b\x51\x29\x4d\x7d\x39\x2d\xbf\x28\x50\xd0\xbd\xf8\xaa\xaa\x3b\x67\x85\x16\x50\xd5\x1f\xa7\x15\x16\x85\x2a\x8b\xfa\x0d\xbb\xe3\xee\x9c\xb2\xd9\xd4\x0e\xb8\xbc\xfc\xc6\xa2\x9c\xa0\x7b\x59\x60\x72\x4d\xd9\x04\xed\x33\xad\x58\xbe\xb5\x20\x2b\x20\x35\xf8\xc7\x8f\xe8\x39\x7e\x2c\x64\xc8\xfe\x1b\xa9\xb9\xe9\x16\x53\x00\x74\x03\x0b\x81\x12\x2c\xc5\xe9\x5e\xae\x54\xb5\xa3\x53\x55\x54\xaa\xe4\xe1\xda\x93\x18\x9b\x96\x67\x0e\xab\x2e\x3e\x19\xc8\x74\x0c\x3b\x34\x3e\xc5\x36\xa8\x80\x3e\xa3\x74\x6b\x06\x31\x20\xb9\xbb\x11\xb8\x60\x7c\xc2\xa6\x8f\xcd\x13\x44\x95\xb3\x47\x22\xaa\x2b\x0d\x39\x7c\x41\x6c\xe5\x83\xa4\x3c\x8f\x13\x62\x16\x57\x36\x3e\x99\x76\x03\xd6\xe3\x49\x68\x9b\x03\x27\xa4\xf3\x3d\xb0\xd3\x2c\xc0\x91\xb0\xb8\x7c\xe0\xe5\xbd\x4a\xc3\xd7\xfe\x7a\xea\xb4\xac\x4b\xcf\x51\x1b\xb5\x35\x43\xf2\xfa\xf6\x2c\x2f\xee\x73\xe3\x5d\x8f\x06\xaf\x84\xfd\xe0\xfe\xc9\x94\x78\xeb\x82\xd2\x7e\xee\x45\x81\xb1\x23\x7b\x8e\x99\xad\x5d\x53\x5f\xd7\x3a\x76\xd9\xa8\x6e\xdd\x7a\xf2\x8b\xd3\xee\x1b\x1d\xb9\x6b\x16\x45\x34\x6e\xc1\x2e\x00\x98\x51\xec\x31\x90\x06\x7a\xe9\x7c\x5f\x98\xf0\xde\x47\x13\x76\x69\xd7\x49\xd5\xe4\xc6\x65\x36\x40\xf5\x59\x05\x51\x35\xa5\x11\x3f\x16\x07\x90\x10\xc6\xc6\x9d\x53\x21\x51\x62\x0b\xf3\xcb\x7b\x17\xb2\x85\xf9\x68\x19\x77\x8d\x3d\x34\xad\x15\x66\xcc\x59\x7c\xf4\x0f\x7d\x34\x6d\x28\xbc\x3d\xa4\x8d\x1c\x0a\xb7\xd5\x2c\x6d\x5c\xcc\x0e\xbd\xba\x52\x3b\xa8\x25\xfe\x4b\xbb\xe1\x4b\x38\x1c\x56\xad\x9d\x77\xc2\x37\x69\xfc\xf7\xf3\x7e\x1c\x3d\x09\x73\x54\x68\x6e\x7a\x90\x29\x00\xbc\x60\x2c\xe6\xe0\x13\x4b\xb1\xc1\x96\x4e\xaa\x36\x18\xc6\x22\x07\x49\xaa\x30\xa5\x20\x1d\xaa\xa2\x54\xf2\x3a\x50\x25\xb1\xe4\x75\xb4\x44\xd2\x37\x87\x4b\xff\x09\xf3\x2d\x9a\x05\x51\x65\x9c\x84\x73\x89\x01\x02\x4f\xd1\xa1\x0a\xb1\x92\x2d\xcc\xef\x5d\x80\x86\x50\x02\x87\xc3\x3b\x60\xfd\xb3\xdb\x0f\x6f\x6a\x32\x6b\x6a\x09\x7c\x38\x4b\xd4\x6e\x2f\x85\x2b\x07\xfd\xc0\xce\xdc\xf6\xab\xd6\xbf\x6a\x77\x6b\xe7\x5b\xbf\xd5\x2e\xb4\xc0\x96\x0f\xa7\x2f\x7c\xf0\xf2\x86\xd2\xc7\x7f\x3b\xaf\xfe\x65\x8c\xc1\xc6\x71\x51\xb6\x11\xf4\x04\xef\xe8\x88\xd5\x2a\xab\x99\xe6\x84\x52\x58\x16\xf5\x50\x20\x1c\xf3\xe6\x04\xc3\x79\x3e\x19\x7b\x43\x68\x92\x7b\x61\xdc\x4a\xb8\x04\x71\xe8\x53\x87\xb0\xc8\xa2\x07\xad\x09\x25\xc8\xab\x61\x18\x56\x7b\x58\xdb\x38\x86\xbe\xfe\xbe\x9a\x0c\xd2\x83\x07\xe9\x25\x35\x16\x0b\x5b\x26\x60\xbb\x90\xc3\x2b\x81\x66\x25\xc8\x2b\xb9\xcd\x20\xe6\xf6\x05\x72\xc9\xde\x34\x3e\x11\x28\x8b\xc0\x86\x2b\x13\x5f\x11\x51\xbb\x23\x2f\x82\xc9\x67\x54\x6b\x61\x24\xa2\x84\x05\xd2\x1a\xa6\x66\xba\x70\xda\x5e\xf1\x08\x51\x87\x68\x27\x97\x76\x65\xb0\x6c\x20\x34\x4a\x9c\x8c\x12\x8c\x64\x0c\xac\xfd\x47\xe8\x84\x21\x77\x88\xb9\xed\x96\x87\x6e\x0c\x99\x2f\x5d\x3d\xf5\xf3\x3e\xe6\x27\x5b\xd7\x2b\xae\x0f\x1a\x3f\xb0\x8f\xbc\xe9\xc9\x17\x8a\x5f\x6e\xfa\xc0\x31\xe2\xe6\xa5\xaf\xf5\xd8\x1f\xd7\x8e\xf7\xfc\xe9\x94\x36\x6e\xf3\x65\xbf\xdd\x36\xf4\xb2\x37\xdf\x7c\x6e\xc5\x80\x4b\x19\xfb\xb9\xef\xfb\xf4\x18\x79\xfb\xc1\xe3\xf4\x93\xe7\xbe\xaf\x28\xfb\x75\xed\x17\xc7\xe9\x7b\xce\xd6\x7c\x7a\x0c\xd9\xdb\x13\x5a\x91\xe9\x08\x53\x05\x64\xb0\x5c\xef\x9b\xb5\xca\xf8\x8e\xec\x56\x16\xf5\x22\xf3\x9b\x5b\x2c\x93\x49\xd6\xa3\x5d\x12\xae\x30\x8d\x79\xd3\x25\x62\xa6\x94\x74\x1e\x97\x2e\x84\xac\x09\x25\xc4\xe3\x9a\xe7\x12\xbd\x0c\x09\xb7\x75\xf0\x59\xa4\x1b\xc1\xe1\xc4\xdd\x08\x51\x6b\x01\x0e\xe1\x14\x0b\x51\xd6\xcc\xe1\x7b\x94\x87\xb8\x1f\x5b\xc9\x42\x57\xa8\xe2\x15\xe3\x66\xce\x29\x39\x30\xae\xa5\x2b\x83\x65\x15\x95\x15\x95\x78\x8a\x3a\x4f\x14\x29\x15\x4b\xa9\x1a\x73\x52\xa1\xd2\x00\xfd\xe6\xc6\xcd\xf9\x59\x05\xe6\x2d\xaf\x4c\x9f\x65\x37\xff\xee\xed\x47\x16\x7a\x17\x37\x3d\xe1\xbe\x62\xd0\x90\xd5\x33\xb3\x27\xc7\x57\x88\xf3\x6e\x58\x7d\x7f\x70\xcc\xee\x6f\xf2\x66\xff\x61\x97\x56\xb4\x72\xde\xc6\x07\xa7\x7c\x3c\xe7\xee\xef\x16\xcd\xbd\x72\x1a\xb5\xbe\x75\xe8\x84\x6e\x03\xaf\xbd\xfb\xdd\xa5\xf0\xdb\xd6\xa1\x35\xdd\xeb\xef\xff\x7c\x2d\x3c\x7e\x6e\xdd\xf3\x4d\xc3\xf1\x39\xdf\x0f\x00\x1b\x62\x8f\x82\x1c\x70\x50\xcf\x62\x7b\xe5\xa8\x9b\x02\x61\xc5\xd3\x86\x8d\xe2\xd9\xbc\x0f\x21\xdd\x6c\xba\x63\xb1\x87\x4f\xdf\x98\xa6\x32\xb4\x37\xdd\x24\x5e\x98\x8c\x75\xe8\x4c\x0c\x06\x26\xb4\x29\x3e\x3e\x26\xf9\xdc\xc8\xd9\x44\xcf\xa8\xdf\xe7\x4e\x49\xcb\x4a\x11\xa0\x4a\x7e\x74\x22\xd1\x13\xef\x47\x1f\xae\x8f\xb5\xf0\xb8\x5c\xd9\x2b\x44\xb9\x74\x82\x18\x2d\x3c\x86\x2a\xe9\x19\xe8\xbd\xbb\x6b\xa0\xa5\x6f\xb6\x90\x54\x41\xf6\x65\xc1\xfe\x65\xd0\xb1\x73\x61\x4d\xff\x91\xa3\xa6\xc4\xc7\xde\x39\x25\xfe\xe7\xe2\x5b\xe2\xda\xd1\xa6\x89\xe6\xa0\xed\xfa\x63\x75\xd1\xc3\x74\xe4\x25\x18\x7e\x46\xde\x50\xfa\xd0\x9f\x96\x4e\x99\xf1\xe9\xbb\x70\xdb\xd9\x2a\xf8\x6d\xe1\x84\xd1\xe3\x8f\x1a\x18\xcc\xcd\xcc\x63\x46\x81\x1c\xb0\x17\x44\xb3\x0d\x06\x5a\x37\xd4\x27\xcb\x00\x65\xbe\x52\xc5\x2b\x1b\xf3\xa4\xe7\x2e\xf0\x3c\x09\x89\xe4\x24\x09\x6d\x93\xa4\x9f\x4f\xe4\xaf\xab\xff\xde\x24\x61\x7a\x1a\xab\x31\x49\x31\x33\x99\x17\xa0\x5a\xf1\x2c\x99\x93\xb3\xc4\xb5\xc1\xeb\x64\xad\x8d\x5c\x26\xb6\x9f\xa5\xda\x27\x12\x4b\x43\xbf\xf2\x14\x15\xf5\x19\xbe\x6a\xcc\xbe\xb9\x9f\x17\x4f\x8e\x6a\xbb\xa2\x75\x69\x4e\xdb\xe0\x3d\x37\x6d\xdb\x01\xeb\x5e\x85\x53\x1a\x5d\x96\xa5\xd2\xd3\xda\xc9\xf9\x2d\xd0\x7c\x1c\xb6\x9c\x79\x83\x4a\xbf\xb7\x70\x4a\xdd\x2b\x08\xc3\x69\x80\x99\xce\x36\x82\x4c\xb4\x9f\x30\x86\xcb\x4c\xf2\x35\x28\xf6\x52\x55\xa0\x13\x8a\x13\x2b\xd8\xd2\x89\x38\xeb\x6f\x63\x56\xca\x4a\x0d\x3c\xa7\x14\x77\x7a\x74\x07\x2a\x3b\x59\x15\xf1\x56\x7b\xe6\x98\x4c\x3e\x46\x67\x52\x52\x38\x96\x81\x9e\xd1\x8c\xcc\x4e\x55\xbc\x19\xb8\x8a\x37\xc3\x68\x10\x41\x30\xd8\xe9\x8a\x44\x48\xc1\xb8\x5d\xc0\x1a\xc2\x2a\x8b\x79\xef\xfd\x40\xaf\x1c\x27\x7c\x32\x15\x72\x99\xe8\xe1\x29\xc6\x80\xbb\x46\xb4\x1a\xf3\xcb\xcc\x5b\xf0\xdc\xee\x37\xf7\x6a\x2f\xbf\x15\x1f\x73\xf7\xdc\x8d\xdf\x2f\x7b\x68\xfa\x8d\x8f\x0f\x59\xc2\x36\xb6\x2e\x5d\xa6\xfd\xed\xef\xda\x97\x5a\xaf\x6f\x7b\x6d\x29\x7f\x05\xfe\xe6\xe3\xed\x87\xaf\x18\xd2\x5a\x83\xf7\x50\x3f\xcd\x8a\xeb\x7b\x32\xc1\x4b\x29\xf3\x03\xc9\xfc\x38\x4a\x55\xd1\x9c\x88\x9b\xc8\xb4\x98\xb8\x5f\x98\x16\x2f\x0c\xab\x16\x6b\xdb\xb4\x24\x8f\xda\xba\x96\xa6\x7f\x7f\x5a\x5c\xbc\x31\x2d\x0e\x31\x82\x36\x93\x2e\x07\x20\x3a\x88\x02\x0f\x10\x14\x1e\xa7\xa8\x2d\x5e\xa3\xf0\x39\x59\x26\xd2\x36\x47\x7c\x28\xd7\xe4\x82\xfd\xbe\x68\xac\xbb\xf4\xe1\xc1\x4f\x6c\x5a\x71\x01\x6c\x9b\x5f\x3d\xe2\x9e\xbb\xe3\x77\xed\xad\xa9\xcf\xef\xc5\x54\xb5\x9e\x1d\x72\xc5\x07\xaf\x7f\xaa\xcd\x79\xb5\x7c\xeb\x80\xa7\x60\xe9\x76\x98\x13\x7b\x16\x73\xb0\xe3\xf8\xfc\xd5\xec\x51\x50\x8c\x30\x66\x18\x9d\xb1\x7c\x33\xa1\x4f\x55\x6d\x68\x9b\x94\x90\x36\x29\x0f\x6e\x79\x95\xda\x1a\x01\x10\x44\x4e\xf3\x24\xd4\x52\xf4\x4a\xd7\x5a\x30\x0b\x4d\x0c\xef\xcd\xca\xce\xef\x16\xc6\xe7\x21\x3f\x2c\x88\x4a\x51\x44\xb1\x09\x71\x20\x48\x69\xdd\xf4\x8e\xaa\x81\xb0\x12\x47\xaa\x70\x83\x86\x8f\x2b\x30\xc2\xec\x4e\xc8\x39\xe9\xd4\x96\x8d\xf2\xda\x83\xc7\xb7\x3f\x30\xa0\xee\xa6\x19\xf5\xe6\x9d\xfc\xf7\xc7\xb7\xff\xb1\xba\xf1\xe0\xcd\x4b\xc7\xf5\xb9\x7f\xda\xad\x7f\xbc\x75\xe7\x17\xaf\x7d\x02\x07\xcd\x7a\x7e\xf6\xe5\x15\x55\xe3\x87\x0c\xbf\x73\xe5\x23\xc5\xfe\x50\xc9\x25\x47\xff\xfa\xf2\xea\xfb\x9e\xbe\xb7\x7f\xa6\x3c\x68\xd2\x0d\x35\xe3\xfb\x97\x2b\xa3\xf7\x00\x78\x61\xa7\xe6\xa6\x1b\x99\x1a\xd0\x03\x8c\x07\xe4\x62\xb2\x71\x09\xa5\x7b\xa9\x1a\x42\xab\x5e\x9c\xda\x89\x83\x47\xe9\x6a\x1b\xa5\x15\x87\x45\xf1\x28\x63\x42\x76\xa8\x3b\x3a\xdd\x66\x61\x37\x1a\x6a\x01\xe9\x79\x0a\x75\x17\x44\xa5\x30\x39\xd0\x02\x3c\x50\xee\x17\x07\x6a\x58\x4c\x92\x47\xaf\x9e\xfc\xf6\x37\xcb\x26\xf5\x9c\x7c\xc3\x94\x47\x9c\x4f\x06\x3e\x7b\xf9\x99\x17\x7f\xf5\xdc\x4b\xbf\x7f\x79\x66\xdd\xe8\x5d\x93\xef\x38\x70\xe7\xfe\x13\xf3\x1e\x39\xb4\x69\xca\x65\x37\x8c\x1d\x32\x64\xea\xd2\x07\x2a\x8a\x8a\xfa\xdc\xd4\xf4\x51\xd3\x9a\x49\xeb\x1e\x1d\x79\xdb\x2b\xf3\xc6\x4d\xef\xde\x7b\x4d\xcf\xf0\x8b\x80\xf0\xbd\x31\x8b\xd8\xa3\x20\x13\x04\xc0\x34\xbd\x6a\x3f\x4b\x67\xc6\x55\x04\x59\x35\x99\x89\x0a\x68\x5b\x8d\xcf\xa1\xa6\xbf\x5f\x9b\xac\xf1\x09\x34\xab\x0e\xee\x8c\x92\xde\x0c\x62\x94\x23\x3d\xa0\xf7\xaf\xeb\x9f\x08\x68\xcb\x42\x1b\x17\x22\xb7\xd6\x24\x60\x35\x6c\xc5\x46\xe8\xeb\x31\xff\x59\x5b\xf5\xba\x6f\x20\x95\xbc\x1e\x38\xcc\x0d\x57\xe9\xa5\x96\xf8\xd2\xfa\x97\x65\xe5\x17\x5d\x72\xdd\xde\xfe\xd7\xfd\xfa\xb6\x48\xef\xfe\xc5\xe9\x81\xec\xc8\x35\xa3\xff\xea\x3d\x7f\x9c\x5a\xb4\x75\x3a\xfd\x72\xf5\xad\xd7\x39\x17\x65\x69\xf7\xde\x5c\x9a\xb5\xc0\xde\x6d\xd4\xd2\xf3\xc3\xa6\x6e\xa6\x4e\xa1\xb1\xed\x04\x80\xa1\x98\x1a\x90\x0d\x82\xe0\x0a\x7d\x6c\x01\x53\x22\x6a\x83\x38\x24\x8e\x0e\xb0\xe2\xc7\x5c\x1c\x6a\x08\x01\xe5\x00\xfe\xa6\x59\xf8\x9b\xee\xa6\xcc\x2e\x6f\x66\x10\x93\x11\x88\xaa\xc5\xd3\xe9\xeb\x7a\x03\xb0\x92\xc4\xaa\x0b\xf0\x71\x82\xe8\x1b\x57\xa7\x51\xfc\x00\xa9\x28\x14\xf0\x16\x95\xdd\x70\xd9\x88\x50\xf1\x84\x5e\x93\x06\x5d\x52\x56\xe9\x0e\xe4\x5e\x5a\x32\x0d\x52\x69\xad\x01\xaa\xdf\x9e\x59\xd4\x5d\x0b\xc3\x61\xdb\xe3\xfe\xfe\xd7\x4f\x78\xb0\x5f\xdf\xf4\xc7\x1d\xe1\x8a\xb9\xad\x0d\xb3\x16\xc3\x77\x71\xfc\x74\xf1\x85\xd3\xec\x50\xf6\x28\x48\x07\x85\xe0\x4e\x10\xf5\xe3\x8c\xa0\x39\x41\x28\x07\xac\x74\x22\x2e\xe4\xf9\x59\x07\xe6\x05\x32\xea\x62\x32\xac\x58\x13\x22\x08\xc3\xaa\xdb\x93\x50\xb8\x32\xdc\x1d\x15\xcc\x10\xc4\x38\x6b\x15\xfc\x0e\xfd\x86\x31\xeb\xc9\xc0\x18\x70\xba\xd1\x3b\xd5\x2a\xe0\xce\x35\x85\x35\x6e\x9f\x74\x98\x27\xe7\xe8\x2a\x09\x32\x1a\x1f\x43\x6c\x07\xc0\x61\x1e\xa0\xf7\xe3\x2c\x9e\xf9\x0e\xec\x16\x83\xec\xaa\x41\x2b\x0f\x2b\x3f\xdf\x64\xbe\xe9\x9d\x79\x7f\x81\xcc\x0e\xed\xf0\x3b\x3f\x69\xdf\x34\xbd\xf0\xcc\xc7\xd0\xba\x75\xdd\xda\x6f\x1e\x81\xdf\x6e\x83\xf5\xd0\xbd\x74\xe4\xea\xa1\x3b\xa3\xc3\xab\xbf\x3f\xf5\xae\xf6\xd2\xb3\x50\xf8\x72\xe3\x7e\x98\xff\xed\xca\x0d\xf7\x7e\x64\xd4\xff\x30\xbd\x98\x1a\x10\x02\x77\x81\x68\x10\x67\xfc\x52\x99\xe3\xd3\x3d\x41\x04\x6e\x70\xf0\x84\x84\xd9\xed\x52\x92\x8c\x38\x4b\x67\x57\x17\xed\x82\x18\x67\x2c\xbe\x74\xbc\x64\x59\xa4\x16\xd4\xe3\x12\xc4\x98\x1d\xf8\xb2\xd0\xbb\x74\x41\xf1\x47\x14\xcb\x45\xa8\xe3\x75\xe6\x78\xe2\xcd\x96\x57\xb4\x29\xee\xd4\x6e\x80\xdd\x0e\x45\x1b\xe4\xc7\x56\xfe\xe1\xfb\x25\x0f\xcc\xdf\x36\x6a\xc8\x23\x2b\x1f\xdd\xb4\x3e\xfe\xc0\x67\xab\x8f\xfd\x19\x36\x9c\x80\x57\x45\xfb\x35\xf4\xd5\x4e\x9c\x7f\x74\xd5\xb3\x0b\x7f\x75\xdb\xf0\x15\xc3\x9f\x7e\x62\xe1\x1f\x67\x7c\x0a\x20\xe6\x9d\x1e\xce\x36\x82\x2c\xb0\x95\x30\xf5\x2a\xee\x24\x47\x8c\x5e\x6a\xc0\xc9\xb2\xea\x33\x27\x54\xc9\x5b\x56\x66\xf4\x21\xa5\x39\x93\x3e\x85\x9e\x4f\xc0\x49\x04\x09\x27\x11\x78\x18\x56\x6d\x3c\xee\x4e\xc2\xf7\xca\x8a\x96\x55\x06\xd9\x32\xe3\x61\xa5\xb0\xe2\xe6\x63\x9c\xdb\x24\x85\x63\x12\x7a\xa2\xf7\x5e\xf4\x9e\x8e\x31\x9c\xe4\x35\x0a\x0d\x79\x13\xae\x2d\x05\xaa\xcf\x23\x88\x31\x1b\x70\x64\xe8\xb6\xb6\x42\x27\x08\x31\x54\xf9\xc3\x10\x33\x84\x78\xdc\xbe\x50\xc1\xe5\xd1\xcd\x0b\x86\xec\x1b\x3c\x6f\xc6\x9c\xca\xad\xc5\x0f\x4f\x7d\xe5\x85\x57\x67\x6c\x35\xad\xb3\xd3\xbd\xe6\xad\x80\x53\xb4\x15\xd3\x6b\x6b\x2e\xbf\x34\x32\xea\x7c\x35\xbd\x73\x73\x50\xcc\xd5\xfb\x81\xcc\x26\x37\xf0\x80\x06\xd2\x13\xa1\xd8\x52\xc7\xed\xe4\x12\xaa\xd5\x51\x56\x66\xa4\x50\x88\x1a\x8f\xe0\xc0\x51\x4b\x7b\xb2\xa9\x3d\x49\x52\x68\x24\x22\x75\xda\x14\xc5\xce\xc7\x18\xbb\x4e\x46\xc8\xd9\x4c\x38\x8a\x62\x22\x7a\x30\x0e\xbb\x3e\x64\xab\xc3\x18\xb2\x00\xb0\x8e\x00\x50\x9d\x76\x41\x54\x01\x29\x4d\xd7\xc7\x1b\xe4\x70\x80\x05\x9b\xdd\x50\x41\xe5\xa6\xa5\x2b\x6a\x1b\x6b\xe1\xf0\x80\xb6\xe3\xb5\xa6\xd7\xef\xbf\x6a\xa8\xa9\xde\x45\x5f\x39\xb3\x1e\xbe\xa1\x55\x34\x9c\x1f\x4c\xc7\xaf\xbb\x32\x3d\xa3\x90\x60\x4e\xf7\x85\xd3\x38\x76\x9f\x8f\x4e\x2a\xc6\x0b\x59\xb2\x1e\x7b\xe1\x70\x87\x50\xa6\x29\x71\xb1\x48\x3e\xee\xee\x6f\x0b\xe1\xe7\xea\x21\xfc\x42\x18\x36\x42\xf2\xaa\x2f\x57\x10\x95\x3c\x84\xa8\x33\x05\x71\x37\xe3\x12\x7d\xb9\x79\xff\x38\x02\x6f\x14\xd9\x5f\x34\xee\x7e\x49\xd5\x7d\xbf\xf9\xa5\x68\xfb\x62\xff\xca\xc5\x38\xc8\x8e\xed\x51\xb1\xe6\x66\x2a\x99\x51\x20\x04\x7a\x19\xdd\x2d\x6a\x21\x97\x20\xa9\x0a\x11\x3d\x58\x34\xb0\x12\x2e\xa1\x64\x96\x2a\xc1\x52\xd2\xb2\x59\x46\x22\xee\xa4\x45\x35\x1b\x5d\x8c\x2e\xbc\xaf\xc3\x7a\xe3\x81\x0c\xc3\x6a\xb6\x28\x88\x71\x6c\x67\xd1\x09\x4d\x13\x62\xf6\x8c\xc2\x12\xf4\x31\x4c\x32\x34\x85\x99\x04\xd7\x94\x90\x66\x27\x5f\xef\x74\x98\x52\x28\x54\x18\x32\x79\xdc\xd9\xb0\x6d\xb7\x16\x84\x72\x0b\x52\x2b\xea\x29\xba\xb8\x66\xf3\xd7\x1b\x77\xbf\xb6\xf0\xe7\xed\x63\x7f\x33\xd0\xca\x14\xfe\xfa\xd7\xf3\x66\x85\x56\x3a\x07\xfe\xea\xb9\x35\xaf\x5e\x3b\x63\xd8\xbd\xdb\x6b\xee\x19\xbf\xfa\xc8\x25\xd6\xe7\xe0\xe7\xb0\xef\xda\xbf\xbc\x71\x48\x7b\x7e\x57\x9f\xeb\x8a\x86\xdd\x5c\x1b\xbe\xaa\x5a\x2e\xf1\x64\x04\xdd\x4d\xf0\x8f\xc3\xca\xeb\xa1\x67\xd1\x92\x05\xda\x27\xda\x5b\xc4\x5e\xe9\x5a\x17\x03\xba\x50\xba\xc0\xba\x1b\xc4\x03\x23\xba\x1b\x86\x82\x85\x45\x88\x02\x0e\x4b\x3c\x30\x5d\x97\xd5\x27\x81\xcc\x45\xe4\x2a\xba\x50\xa9\x40\xeb\xa3\x69\x9a\x9b\x2a\x64\xff\x0c\xec\xc0\x07\xea\x00\x5e\x0c\xc5\x24\x2b\x56\xa2\x6d\xee\x29\x55\x79\x4b\x02\x97\xa5\xb3\x27\x71\x61\x84\x03\xe1\x7b\xd1\xd6\x56\x9f\xbe\xb2\xe5\x49\x72\xa3\x63\xd6\x2e\xc2\xe0\x05\x30\x77\x17\x34\x18\xbc\xa0\x6a\xc2\xda\x1c\xb8\x69\x93\xb2\x92\x4a\x3f\x96\xc4\x93\x20\xda\x73\x10\xc7\x0d\x72\x0b\x53\xd2\xb5\x9a\xd6\x77\xc0\xec\x30\x34\x45\xb5\x1f\xf3\x9f\x7e\xec\xda\x0a\xaa\xfa\x8a\x8a\x51\x57\x97\x76\xaf\xd0\x0e\xf9\x5e\x67\x4e\x9d\xf3\x2b\x1b\x3c\x5c\x65\xa4\x6a\x54\xff\xeb\xca\x0c\x5e\x2d\xc2\x7d\xe7\x05\x01\x70\x53\x47\xf6\xbb\x2c\x3a\x11\xf7\x79\x30\x1f\xa8\xaf\x13\x1f\x68\x7a\x0a\x1f\x68\x3a\xe1\x03\x75\x13\xa5\x0d\x8f\x40\xba\x36\xb3\x7c\x7a\x17\x46\x17\x8c\x78\xa0\x32\x68\xaa\x0c\x92\x1d\x04\x3a\xb2\xe2\x1d\x3a\xb0\x75\x37\x34\x97\x9f\x57\x4c\x41\xfa\x5a\xb6\x69\x73\x5c\xfb\xbe\x2b\x76\xbc\x43\xef\xc1\xb4\xef\xfb\x9c\x2a\x2b\x68\x7e\x5f\xfb\xde\xb8\xd7\xf0\x3e\xc9\x04\x43\x40\x34\xbd\x5d\x57\x03\xba\xd7\xec\xae\x74\x9c\x9e\x6a\x73\x23\x04\xe2\x30\x00\xd5\xad\xd7\x32\xbb\x04\x15\xf8\x22\x11\xd5\x62\xbf\xa8\xe4\x09\x17\xe4\x82\xed\x1a\x97\x6b\x57\x41\x7a\x0b\xde\x3c\xb3\x5e\x28\x85\xc7\x42\x5a\x05\x33\x77\x5a\xa4\x6e\x14\xd9\x42\xaf\xc3\x5b\x76\x97\x37\xf4\x7e\xf6\xc9\xd5\x39\x97\x3e\xb8\x30\xbd\x3b\xd9\x43\xd8\x8e\xd1\x83\x98\x51\x29\xdf\x95\xe6\x88\xe1\x52\x1d\x5c\x22\x6e\xe6\xd2\x25\x47\x98\xf4\x30\x67\x61\x69\x1c\xaf\xf1\x5d\xe9\x74\xa2\x64\xc2\xe1\x22\x19\x87\x19\xb9\x29\x5e\x5c\x49\xa3\xf0\x91\x9e\xbd\x2a\xb1\xd3\x51\x19\xac\x0c\xea\xe6\x2a\xb5\xc2\xc8\xbd\xb8\x6e\xd9\x0b\x01\xad\x28\x00\xdf\x78\x70\x66\xdd\xec\xf2\x81\x0d\x77\xbc\x7a\x62\xf1\xb9\x9d\x57\x2d\xcb\xda\xd4\xef\x85\xed\xab\x03\xeb\x96\xf4\x5d\x98\xd1\xfd\xb3\x93\xef\x68\x2f\x6e\xcc\x34\x38\xfc\x86\x63\x5e\x53\x0f\x58\xa4\x5b\x5c\x7b\x1b\x8b\xb5\xcd\x81\x5d\x33\x9b\x39\x11\xa7\x3d\xf8\x23\x8d\xb6\x8a\xb7\x0b\xae\x53\xe4\xa5\x09\x7a\x6e\xcc\xd7\x21\x0d\xd1\x9e\xed\x34\xe6\xc0\x4f\x8f\x9d\x10\xde\xda\x1c\x9e\x64\xa6\xdd\xe3\xd0\x37\x95\x0c\x65\x4e\xee\x8a\xdd\xaf\xb1\x7c\xc5\x7b\x1f\x6b\x4d\xda\x4b\x73\xae\xbc\x63\xce\xdb\xef\x2f\x5c\xb4\x81\x6d\xd4\x0e\x1e\xf8\x59\x3b\xab\x1d\x86\xef\xc5\xb6\xcf\x9a\x8c\x39\x1b\xde\xd1\xdc\xcc\x00\x93\x1b\xf8\x41\x7e\xb2\x7a\x35\x93\xd3\xbb\xe1\x73\x49\x4a\xc2\x2f\x2b\x54\xa9\x42\xcb\xf8\xde\xa0\x30\x03\xaa\x42\x93\x88\xa3\xc3\x8a\xef\x8d\x54\xd5\x2f\x04\xcf\x01\xe6\x42\xf5\x37\xef\x1b\xf8\x54\xcb\x1b\xd8\xed\x04\x7c\x0c\x02\x8a\x94\x80\x33\x7e\x5a\x0a\xc7\x7c\xe8\x19\x85\x20\xc5\xff\x8c\xfa\xfc\x34\x51\x4e\x03\x51\xc8\xf8\xb0\x4a\x1a\x80\x0c\x6e\xb4\xd4\xad\x01\x4d\x09\x62\xcc\xc4\x09\x99\xc8\x5a\xe7\x08\xaa\x35\x17\x19\x86\xdc\x4c\x41\x8c\x73\x0e\xb7\xc7\xa4\x87\xd3\xa0\x4c\xeb\x38\x32\xc5\x68\x73\x74\x92\x86\x12\x59\xbe\xe2\x3c\xf8\xdb\xf8\x90\x6e\x21\xf3\x98\xe7\x6e\x59\xbc\x61\x71\xcb\xca\x5b\x57\x86\xad\x9c\x38\xe6\xf0\xa4\xf1\xb5\xdb\x6a\x77\x8d\x3c\x78\xaf\xe6\xde\xc9\x55\x6b\x4f\xc4\xee\x7d\x60\xec\x2b\xea\xdb\xda\xda\x43\xa3\x47\x4d\xbc\x41\x2b\xa0\xab\x26\xd5\x6d\x81\xa1\x4d\x1f\x45\xb5\x4f\xd0\x1e\x46\xf6\xc3\xc9\x1e\x05\x3e\x84\xf6\x49\x97\x2e\x9d\x50\x78\x9e\xd4\x3b\x4b\x86\x1d\xc1\xc9\x44\xbf\x91\x4c\x44\x46\x10\xa8\x16\x11\x27\x06\x1d\xa9\x89\x41\x3e\x79\xc8\x98\x94\x7b\x15\x2c\xff\x3d\x1c\xf7\xe9\x5b\x0d\xd7\x2e\x5a\xfa\xbc\xf6\xfd\x9a\x03\xdb\x96\xc6\x9f\x3e\xf4\x83\x76\x9a\xca\x80\x10\x1e\xfa\x66\xd8\xea\x41\xaf\x68\xcb\xde\x7d\xe1\x54\xff\x8d\x03\x60\x18\x18\x7c\xa9\x3a\x9f\xec\xa2\x24\x7f\xb3\x94\xe4\xc9\x34\xfd\x5b\x64\xb2\x06\x67\x2c\x49\x27\xe9\x94\xb1\x34\x1a\x08\x66\xdc\x30\x59\x44\x03\xf8\xb4\x31\xc0\xe2\x9e\xe8\x28\xed\x70\x45\x92\x54\xa8\x10\x87\x96\xa4\x50\x1b\x1b\xea\xa7\x90\xb2\x50\x43\x35\xed\xf7\x7b\x0e\x7a\xae\x37\xb7\xee\x68\xd0\xce\x9a\xb3\x82\xfb\xd9\xc6\xf3\xdf\xd0\xe2\xd9\x2a\x7a\xce\x1d\x30\xf3\xfc\x69\xda\x7b\xfa\xc9\xf3\xf3\x49\xfe\x8c\x1d\x82\x7b\xb7\xa2\x6d\xfc\x60\x38\x5e\xc2\xe2\xbe\x60\xbe\x8d\x0d\x56\xc0\x6c\xb0\x1c\x42\x73\x7c\x1b\x1b\x6c\xbb\x5c\x19\x66\x83\x75\x36\xef\x1b\xb8\xb5\x25\x61\xb0\x7e\x9a\x9b\x59\x9d\x0e\x6c\xe0\xf6\x96\x73\x78\x13\xf3\x7c\xcc\xc5\x3b\xa5\x70\xd4\xc5\x3b\x53\x2b\x68\xcd\x4e\x17\xde\xab\x90\x25\x9f\x8c\x36\x59\x5e\x10\x55\x1a\xb7\xe2\x41\x4e\x10\x63\xb4\xd5\xa6\x87\x7b\x31\x7d\x20\x1d\x92\x2a\x2a\x61\x88\x76\x41\xba\x18\x0e\x7d\xe9\x04\x7c\xf5\xc4\x17\xca\xdc\x50\x40\x9b\x54\xbf\xc7\x9c\x7f\x1a\x77\xfd\x7e\x40\xe5\x9f\x6b\xa4\xea\x9e\x98\xa4\x79\xe1\xe7\xbd\x0f\x9f\xdb\x84\xce\xec\x24\xbd\x17\xd1\x0f\x0a\xc0\xfb\x20\xea\x30\xce\xac\x09\xea\xc4\x1d\x38\xd2\xa8\x80\x52\xd5\xe3\x97\x65\x2c\xa1\x4b\x89\x08\xe7\x17\x96\x2a\x39\x27\x71\x78\xa8\x9b\x3e\x0b\x5b\x5a\x3e\x49\x76\x88\xd1\xcd\xac\xea\x75\x9d\x71\x2a\x05\xcd\xac\xe2\xe3\x63\x94\x8f\x96\xc2\xfb\x06\xae\x6e\xd9\x6e\xa8\x1f\xf2\xde\x02\x29\xcc\xc6\x44\xf4\x57\xcc\x83\x9e\xe8\xf7\xfc\x9d\x7e\x2f\x0d\xfd\x28\xca\x7b\x0b\xda\xf7\x99\xc7\x68\x3e\xad\x80\xd0\x06\x5b\x29\x9a\x17\x3d\x5e\x9f\x9f\xbc\x48\xed\xa7\x09\x21\xec\x65\xc1\xa7\x58\x6e\xdf\xb7\x88\xef\x1c\x2e\x54\x09\xdb\x35\x2f\x36\x04\x96\xec\x4c\x69\x5f\xf4\xe4\xc0\x49\x01\xad\x21\x14\xcd\x87\x85\xa9\x6d\x8c\x87\xea\xe9\xf2\xb6\x3e\xc6\x47\xd6\xd6\x3f\xf7\x1c\x55\x9c\xda\xc8\x08\x2f\xfc\x7c\xe1\x34\x53\xc7\x1e\x4d\xd5\x35\xa3\x13\x51\x5e\xf7\x7e\x93\xba\x66\x9e\x2e\x74\xcd\xec\x86\xae\x99\xc3\x90\xd0\xca\x13\x75\x9f\x8e\x24\xbd\x70\xb0\xd0\x5c\xb5\x60\x99\x02\xed\xab\x9b\xb7\x2e\x8b\xdd\xf4\xf4\xc4\x1f\xa0\xfb\xb8\xb6\xe6\xd3\xe3\x03\x56\x0f\x7a\x15\x4e\xfb\xc3\xbe\x53\xfd\x9e\x0a\x66\x69\xef\x6a\xe7\xb5\x0b\xda\xa5\x7f\x03\x49\x5e\x5e\x62\x5b\x42\x60\xfa\x3f\xb0\x2e\xf1\x60\x86\x87\x71\x84\xe3\x41\x5d\xbc\x28\x2f\xb5\x70\xc1\x0f\xc3\xf1\x6c\x22\x60\x84\xfc\x56\xbf\x81\xaa\xda\x14\xcf\x82\xa2\x20\xaa\x0e\x80\xae\xfd\x8c\x76\x90\xa5\xb3\x2d\x82\x29\x05\x71\x17\xb3\x4b\x3d\x93\xa2\x48\x5d\x59\x28\xb8\xce\x50\x4a\xa2\x52\xe6\x3d\x0f\xe1\xc8\x4e\x33\x1f\xcf\xcd\xf4\xf1\x8e\x70\x3c\x57\x1f\x57\x7e\xa9\x92\x76\x32\x1e\xc0\x83\x51\x02\xba\xda\x99\x27\x81\xf9\x68\x02\x69\x82\x18\xb5\xfa\x68\x5c\x6e\x85\x90\x40\xdb\x3a\xe5\xa6\x48\x9e\xd9\x0d\xc9\xb3\x5f\x5c\xaf\x54\x8d\xa7\x8b\xac\xdd\x21\x63\x94\x5d\x2f\x22\xf5\x4a\x52\x10\x8a\x60\x88\xa9\x5c\x1d\xb0\x01\x77\x32\xe6\x75\x51\x45\x01\x4f\xa9\xe2\xc0\x28\x53\xf5\xfe\xc7\x85\x05\x60\xb9\x4c\x84\xfc\x3b\x2b\x0c\x68\x67\x0e\x15\x8d\xbb\xeb\xf2\xc7\x92\x4a\x03\x5c\x8d\x67\xfe\xb6\xb4\xcb\xf7\xe9\x7a\x18\x53\x93\xbc\x94\x4f\xfe\xf2\x08\xfe\x45\x72\xca\xff\x17\x83\x23\xaa\xc5\x36\x6b\x04\x2b\xc1\xeb\x34\x95\xed\x86\xdb\x75\x25\x67\x17\x83\x7f\xb3\x8b\x32\x4e\x7d\x1e\x3a\x31\x55\x42\xb0\xe7\xc2\x69\xe6\x04\xe6\x74\xdd\x60\xe4\x7d\xb2\x64\x99\xf4\x11\x4b\x34\x26\x2e\x10\x8c\xc9\xc1\x0c\xc6\x81\xb2\xb2\x38\x9b\xe9\x4c\xae\x71\x4e\xa9\x92\x7d\x52\xcd\xb2\x26\x94\x2c\x52\x2f\x65\x4e\x69\x16\xd7\xeb\xa5\x94\x6c\x9c\x9f\xcd\x42\x1e\x52\x8c\xcd\x42\xd3\x90\x89\x9e\x74\x8c\x61\x33\x8d\x70\x27\x91\x1c\x70\xf2\x91\x88\x62\x16\x54\x9a\x8a\x18\x7a\x04\x66\xbf\x9e\x86\x45\x13\x91\x23\xb8\x5d\xb0\xad\x48\xae\x12\xfb\x1d\x41\x1a\x73\x23\xd7\xe7\x6a\x53\x86\x43\x00\xeb\x78\x21\xaf\x69\xcb\xaf\xfb\xf6\xbd\x66\xf4\x38\x4f\xd6\x98\x89\xda\xd7\xeb\x9a\xa0\x87\x75\x6f\xde\xac\xdd\xa9\x1d\x1d\x3d\x74\x70\xd3\x73\xde\x8d\x9e\x09\x75\x6b\xfa\xfc\xfa\x86\xd6\x20\xeb\x4e\xdd\xd7\x2c\x70\x75\xad\x12\xc2\x27\x55\x42\x84\x7f\x41\x25\xc4\xd2\xd6\x0f\xd1\xa6\x17\x02\xe7\xca\x8f\x15\x1f\x2b\x7d\xe3\x5a\x2c\x1c\x62\x0a\x67\x54\xaa\x57\x79\x22\x47\xca\x53\x71\x58\x8a\xdf\x93\x6a\x1d\x0d\xbf\xa7\x2d\xab\x24\x78\x52\xfd\x1e\x1f\xf1\x7b\xbc\x5d\xf8\x3d\x29\x66\xb0\xcd\xef\x21\x31\x71\x82\xcb\xde\x5c\x7d\xed\xa2\xa5\x47\xb4\xff\xba\x94\x1a\x97\xd3\xba\xca\x8c\xac\xe0\x1d\x4f\xd7\xfc\xa4\x7d\xd3\x66\xfc\x5a\x3f\xda\x5c\x5c\xfb\xd2\x5b\xfd\x37\x86\xd2\x61\x3e\xc6\x67\x85\x17\x4e\x33\x85\xec\x51\x90\x07\xc6\x81\x68\x08\x5b\x3d\xb3\x6e\xf5\xbc\xe8\x4b\xe6\xe3\x03\x43\xc4\xb4\x30\x05\x46\x8e\x9b\x18\xb9\x34\x3b\x32\x72\x74\x28\x82\x43\xc6\x31\x0b\xef\x25\x70\x58\x54\xb2\x90\xbd\x0b\x11\x7b\xe7\x15\x62\xd0\x2e\xe1\xaa\x2d\x5e\x54\xc4\xa4\x4f\x44\x7a\xe7\xcb\x7b\xb7\x55\x3c\x9b\x0c\x9e\x0b\x26\x98\x5b\xf8\xbb\xe7\xd7\xef\xbb\xa3\x7e\xf5\xdd\x0f\x7c\xfc\xf8\xab\xdb\xae\xbe\x74\xe3\xb5\x73\x9e\x1c\xf2\x9b\xfa\x71\xbd\xb5\x2f\x2e\x80\x37\x8b\xe3\xc3\x97\x3e\x3c\xf8\x9e\x61\x37\xef\xbc\x7b\xf6\xa1\x49\xc3\xd7\xe7\xf5\x98\x5f\x37\x64\xdc\xe0\x11\x63\x1f\xb8\xe1\xc4\x57\xe0\xff\x2a\x2d\x8a\xff\xbf\xf3\xe8\x42\xed\x90\x36\x8b\xba\x1c\xaf\xc5\xcd\x20\x6a\x42\x98\x9f\xc3\xd1\x19\x9a\x10\xb7\x2b\x26\xdc\x67\x96\x5c\x89\x75\x2d\x8d\x64\x5c\x18\xf5\x12\x08\x0c\x54\xd6\x8c\x45\x80\xcd\x06\x3c\xd3\xdb\xc1\x14\x93\x80\x05\x75\x60\xa5\x1e\x84\xa1\x82\xb9\xda\x21\xd3\x55\x83\xdf\xec\x0d\xe5\x26\xed\x8d\x61\xda\xe6\x89\xda\xf2\x0d\xee\x1f\xd8\x2d\x67\x07\x69\xb3\xb1\xaf\x79\xe0\x42\xc2\x14\x65\x1b\x41\x1a\x08\x42\x8a\x54\x61\xa8\x40\x90\x65\x35\xdd\x9c\x50\x60\x99\x92\xce\x2b\x34\xc2\x34\x7e\x3a\x81\xb9\x9b\x15\x8b\x8c\xed\xa8\x58\x16\xb7\x06\xfd\x66\x47\x58\xb5\x9a\x09\x97\x59\x16\x09\x73\xe9\x64\xe5\x03\xf6\xff\x2d\x9b\xf8\x24\x25\x4e\xc5\xd4\xcc\xaa\x52\xd6\x19\xa7\xe2\xc1\x70\xfe\x34\x51\xbe\x10\x4a\x14\x4b\x09\x5a\xcc\x74\x7c\x9f\xa8\xa2\x70\x66\xdf\x80\xf9\xdf\xdc\x61\x34\xc6\x71\x26\xb3\x14\x66\x95\x74\x3e\x66\x4d\xb7\x48\xe1\x7d\x03\xea\xbe\xc9\xc4\x3f\xc3\xdd\xf4\x92\xfe\xb3\x20\xfa\x59\x94\x33\xa5\x88\x40\x44\xdd\x1e\x09\x17\x81\x9b\x38\x22\x64\x09\x2f\xb5\x9b\x2d\x56\x41\x94\xd2\x83\xc6\xab\xf6\xf8\x36\x98\xae\x0b\xef\x86\xca\x71\x69\x87\x28\x05\x69\x39\x47\x70\x33\x45\x10\x06\xad\xd8\x3e\xe7\xcb\x39\x02\x72\xe3\x2f\xef\x2d\xdf\x30\xa1\xa6\xe1\x09\x6a\xc7\x9c\x89\x70\xbf\xf6\xae\xf6\xa5\x16\x85\xa2\xd6\xd4\xb0\xfc\xde\x0d\x77\x0f\x66\x2c\xcb\xe1\xc4\x07\x1f\x5d\xb0\xd1\x33\xe2\x0d\xf8\x25\x95\xd3\xda\xa0\xad\xfa\xeb\x79\x56\x6c\x3d\xa1\xc9\xc7\x46\xc7\x60\xe5\xf4\x49\xc0\xd0\x1f\x30\xbd\xca\x36\x02\x01\xa4\x81\xf7\x88\xbf\x10\x05\x4e\x41\x96\x65\x55\xd4\xc5\xac\x92\x6a\x3e\xbc\x03\xdd\x4e\xae\x34\x19\xeb\xf9\xe8\xa4\xfb\xe9\xa9\x1c\x18\x29\x61\x0c\x3d\x42\xae\x98\x48\xd6\xc0\xea\x6e\x23\x58\xda\xd4\x72\x82\xe4\x9d\x8d\x44\x01\x8b\xab\x7e\x4d\x98\x69\x5c\xe0\x63\xb4\x40\x49\x61\xc5\xc9\xc7\x18\x27\x4b\xa4\x1a\x39\xd1\x44\xde\xb8\xf0\x1b\x81\x8f\xf1\xf8\x77\x44\x3e\x96\x26\xe2\x9e\x03\x9a\xe1\x9c\x2e\x5e\x4c\x6b\xd7\x73\xc0\x8b\x29\x3a\x2f\x41\x49\x36\xe6\x52\x0a\xd2\xc6\x34\x56\xc3\xf2\xc6\xb9\x54\xf1\xa3\x8d\x73\xa7\xc0\x17\xb4\x77\xb4\xaf\x35\x65\x69\xeb\x3b\x4b\x69\x66\x05\x9c\x30\x6b\xde\x02\xb6\xb1\x75\x35\x35\xa1\x75\xb5\xb6\xf2\x8b\x73\xd4\xce\xd6\xea\xf5\xb0\x72\xfa\x04\x43\x8f\x00\xdd\xef\x3e\xf0\x57\x12\x6f\x8d\xda\x1d\x1e\xc3\x7f\x26\x37\xba\x0f\xdd\xe8\x6e\x6f\xf2\x46\xf7\x97\x2a\xde\x24\xab\x25\x4f\x72\xf1\x29\x22\xf4\x56\x22\x42\x8f\x66\xaf\x2c\x19\x05\x35\x2e\x7a\x5c\x97\xa5\x78\x48\xd5\x26\x11\x20\xe9\x20\x45\xcf\x26\x35\x54\x0d\x82\x7e\x5b\x52\x85\x9e\x25\x5b\x95\xc1\x22\x39\xd6\x54\xef\xd4\x89\x45\xe7\xe1\x6e\x86\x75\xba\x7d\xb6\x14\xaa\x18\x3b\x8f\xbb\xd0\x80\xea\xf6\xea\x2e\x97\x0e\x14\x52\x74\xe7\x3b\x00\x04\xfb\x9e\xe7\x85\x51\x7b\x46\x49\x63\x27\x69\x7f\x6b\x03\x06\x1b\x9e\xcc\x9f\xa0\x5d\x03\xb7\x54\x5f\x36\xe2\x57\x18\x14\xe0\x3d\xc7\x56\x72\x75\xc0\x0a\xdc\x60\xa6\xa1\x4e\x65\x4d\x2a\x01\x61\x3d\x1d\x4f\xaa\xd6\x85\xc1\xca\x66\xa0\xdd\xa7\x5b\x3e\x6a\x5f\xcf\x61\xe5\x63\xb4\x95\xc2\x72\x6f\x94\x14\x8e\x5a\xac\x9d\x0a\x17\x2c\xb8\x70\xc1\x92\xbc\x2a\xd0\x8e\x20\xc2\x3f\x74\x3b\x28\xd1\xb8\x8a\x8a\x7e\xd8\x5a\x0c\x5f\x3f\xa1\x5d\xbd\x1a\x1e\x4d\x02\x8a\xd6\xbe\xd4\x2b\xad\xf9\xad\xf9\xd4\xbb\xad\xe1\x54\x64\xa1\x9f\x21\x76\x1b\x57\x87\xb5\xe0\x7e\x6f\x20\xdf\xb6\xf1\x60\x96\xb9\xb4\x52\x05\x9e\x54\x29\x57\x32\xc4\xa7\x97\xfd\x5b\x75\x21\x9a\xf4\x0e\xe0\x07\xf2\x0a\x68\xc6\xd7\x08\x9b\xa2\x30\x62\x25\x14\x0a\x16\x64\x7e\xf7\x0d\x7c\xac\xa5\xda\x10\xa2\xa1\x59\x74\x1c\xac\x7c\xcc\x66\xb5\x4b\xe1\x28\xcd\xa6\x46\xce\x6c\x56\x3b\x36\x43\x74\x92\x56\x01\xd0\xac\x99\x7c\xd6\x97\xdb\x2a\x12\x2a\x32\x8b\xa0\xba\x3d\x46\x58\x06\x5b\x22\x34\x51\x14\x87\x83\x32\x62\x45\x65\xc8\x92\xea\x1f\xec\xda\x39\x30\x93\xa1\x37\xbc\xab\x1d\xdd\xf9\x66\x6f\x33\x73\xbe\x06\x3e\x60\x78\x08\xe7\x3f\xd0\x3e\xbb\x93\xd9\x75\xb6\x8a\x7e\xe5\x73\xff\xb9\x01\x49\x4f\x01\xcd\x17\xb8\x70\x9a\xad\xe6\xc6\x01\x0f\xc8\x07\x6b\x49\x55\x3d\xf6\xe9\x70\x3b\x98\xd9\x29\xcb\x4a\xa8\x54\xcd\x62\x13\xd1\xac\x90\x35\x1c\xbb\x34\x2b\xc7\x12\xc6\x39\xf1\x02\xec\x63\x9b\xad\x09\xc5\xac\x37\xf1\x3a\x71\x86\x19\x97\x37\xba\x92\xc1\xc6\x97\xae\xfd\x9b\x33\xc9\xdb\x6e\x6a\x26\xd1\x28\xa0\x9a\xf0\x16\x30\xe9\x5b\x40\xcd\xc9\x40\x8e\x41\x28\x82\xe5\xae\x9d\x68\x8b\x48\x46\xcc\x58\x85\x98\x2a\x60\x00\xc4\x48\x18\xca\x92\xd7\x57\x61\xe4\x12\x0a\x60\xef\x4a\x59\xd7\xb4\x97\xa9\x60\x6e\xc1\xd0\xe1\x63\xd7\x8d\xd6\x8e\xed\x51\x64\xd7\x95\xe5\xb0\xfe\x78\x6b\xcd\xdc\xc4\xfa\x6e\x77\xc0\x67\xcc\x1b\x4c\xbb\xa6\x4d\x13\x77\x0e\xd0\x56\x3e\xf5\x8c\x39\x5a\x38\x63\x3d\x23\xb6\x3e\x7c\x60\xf8\xb2\x91\xd4\x8e\x73\x4d\x27\x9f\xe5\xb9\xc2\x82\xac\x5c\xdf\x9c\x5b\x6e\xd3\x8e\xcc\x26\xb5\xec\xda\xc3\x58\xbb\xc6\x06\x54\x92\x67\x88\x02\xce\x2c\xcb\x86\x7a\x5a\xd4\x46\xa3\xe9\xb0\x59\x2c\x61\x04\x52\x52\x4c\x33\xbe\xb1\xd1\xf6\x92\xd0\xf6\x52\x2c\x58\x2e\x97\xc7\x7d\xba\x16\x3e\xd5\x1a\x77\xaa\x6d\xc7\xdb\x8c\x80\x15\x23\x94\x85\x77\x99\xad\xd9\xd8\x64\x3a\x89\x47\x6a\x1a\x86\xde\x0d\x68\x86\x33\xdb\xda\xbb\x90\x32\x0c\xa2\x3f\x74\x48\xaa\x86\xe5\x7b\xb5\xaf\xa8\x79\x50\x6a\xd4\x8e\x6a\x35\x43\x95\x6a\xb6\xf1\xec\x69\xd6\x7d\xb6\x4a\x7b\x18\xce\xf9\xef\xae\xfd\x48\x81\xe1\xc9\x9e\x03\x09\xcc\x22\x2b\xa5\x00\x59\xb5\x9b\x53\x9d\x5d\xc9\x86\x0d\xbf\xae\xdb\xe3\x3a\xa9\x9a\x53\xc4\x7a\xf4\x1b\xb0\xcd\xa3\xb5\xa7\x11\x8f\x36\xed\x0c\x32\xda\xac\x1d\x7d\x7d\xc9\x9e\xf4\x68\xed\xa9\xba\xcd\x92\x5d\x67\xf6\x25\x7e\x2c\xbe\xd3\x82\x85\xfa\x7d\x36\x1c\x96\x53\x9f\x85\x5a\xdf\x1d\x5d\x4f\x40\xc1\x86\x3d\x70\xf2\x83\x8f\x2a\xd8\x55\xd5\x56\x7e\x7e\x7e\x3d\xbe\xfa\xff\x47\xbf\xf2\x7f\xa7\x7e\x65\xb5\x36\x87\x39\xcb\x36\x02\x07\x70\x83\x83\xc9\xaa\x03\xd5\x49\x27\x62\x90\x33\xbb\xf2\x7c\x65\x51\xbb\x13\x1d\x6d\xbb\xc5\x12\x8e\x02\xab\xa3\xac\xac\xcc\xa8\xc9\xc0\xc5\x8f\x7c\x99\x71\x21\x3a\x5c\x38\x60\x67\xdc\x1a\xde\xe4\x7e\x7a\x37\xe5\x8b\xe1\xfe\xb0\x7d\x03\xd7\xb7\xec\xc7\x2f\x5d\x25\x8a\xa9\x44\x71\xf1\x2a\x67\x3d\x83\xcb\x35\xac\x67\x92\x24\x97\xa9\x67\x9d\x6e\x82\x26\xce\x6c\xb3\x1b\x94\x71\x24\x7a\x60\x75\x08\x62\x8c\x62\x9d\x42\x9e\x0f\x8b\xed\x4b\xb2\x08\xa4\x20\x8e\x50\xa3\x73\x23\x85\x4c\x56\xb8\xb3\x6e\xc2\x4b\x70\xca\xb5\x54\xb5\xf6\xf5\x0b\x33\x76\x0d\x3d\x3f\x67\x18\x04\x54\x69\xcb\x8f\xdd\x0e\x24\xb4\x39\x54\x08\x3a\xa9\xcf\x60\xce\xd9\x6f\x5a\x3f\x84\x0f\xa3\x7f\x33\x53\xe6\x6b\x55\xda\x8d\xe0\xbf\x83\x8e\xe6\x5a\x00\x4c\x1a\xc6\xc7\x4f\xe9\x79\x12\x9b\xd3\x85\x70\x1e\x85\xcc\x2f\x6b\x32\x63\xf3\x2b\xe2\x13\xee\xe4\x71\xda\x97\xd5\xb3\x09\x52\x72\xd7\xbc\xd2\x1e\xad\xb8\xf8\x18\xe3\x62\x09\xa0\xe5\x9c\x26\x29\x1c\x73\xa0\x27\x7a\xcf\xa3\xf7\x51\xde\xc5\xa6\xe0\x17\x26\x12\x75\x38\x4d\x86\xa8\x1c\xc3\x39\x78\xe2\x4a\x1a\x9f\x0c\xe7\xd7\x02\x65\x28\x25\x51\x4d\x48\x82\xe3\xa8\x67\xb4\xf5\x47\xe0\xe8\xe5\xea\x0a\x6a\xc6\x7b\xad\xe3\xe0\xf4\xa3\xda\x86\xb5\xca\xda\xd6\x87\x69\x8a\x8a\xb7\x0e\xa2\xf6\xe0\x3f\xa1\xd6\x42\xea\x3d\xf2\x87\xf4\x1f\x69\x17\x4e\x33\x32\x7b\x14\x14\xa2\x35\x29\x00\xa4\xff\x08\x8b\x78\xab\x22\x97\x88\xdb\xac\x05\x7e\x07\xae\x3d\xc4\x95\x5e\xdc\x49\x35\xd7\x9d\x50\x72\xf5\x7e\x32\xac\x19\x55\xaa\x66\x48\x98\xf5\x08\xa8\x4c\x81\x11\x09\x57\x61\x2e\x29\xb4\xcb\x0e\x44\x22\x8a\x28\xa8\xee\x8c\x08\xa6\x01\xf7\x44\x7a\xf6\x2a\x2c\xd7\xb9\x1c\x52\xf8\xd4\x93\x79\x59\xfd\xf4\x9b\x98\x50\x2e\x35\xe2\xd4\xf8\xf8\xef\xb5\x03\x27\x02\x2f\xbd\x70\xea\x81\xf1\xdb\x5e\xa8\x9a\xfc\xe9\xbc\xe7\xdf\x78\x35\xfa\xe8\x9a\x25\xda\x8f\x8d\x5f\xf5\xdb\xd5\xab\xfc\x99\x25\x2d\x2b\x37\x2f\x19\x7b\xfb\xcc\xb9\x83\xae\x54\x1a\xd6\xfc\x21\x8f\x71\x6f\x9f\x37\xef\xd8\x34\x43\x1f\x6e\x1b\xb6\x7b\xbb\x2f\x82\xd4\xf8\x54\xa4\x66\x1c\xb4\x8e\xb1\xa9\xff\xbd\xf0\xec\xe2\x70\xac\x4b\x14\xd6\x09\x7d\x25\x31\xea\x38\xe0\x22\x2a\x53\x5d\x8c\x1c\x59\x73\x1f\x9b\x88\xfa\xb2\x90\x29\xf2\xa5\x5b\xc2\x8a\x48\xc4\x73\xda\xa6\x83\xc7\x74\xa2\xd8\x81\xd1\x67\x06\x39\xcc\xe9\x08\x8a\xb9\xda\xa2\x93\xff\xa7\x30\xac\x47\x10\x55\x5f\xd6\x2f\xa3\xd7\x0e\xe8\xad\x4b\x10\x1b\x6c\x07\xdd\x3a\x63\xd9\x50\x47\xdc\x86\xfc\x19\xac\xe1\x77\x31\x6f\xc6\xd6\x95\x37\x63\xff\x5f\xe2\xcd\x74\xf4\x61\xda\xbb\x2e\xf8\x7c\x1f\xb8\x90\x60\xfb\xe1\xdc\xef\x2b\x86\x56\xa6\x4d\x96\x93\xca\x91\x98\xee\x17\x97\xe3\xa4\xc4\x5a\x1c\x74\x42\xb1\x97\x61\x2c\x63\xc3\x23\x89\x5a\x6d\xb8\xf9\xd0\x62\x09\x1b\xb0\xa6\x53\xac\xc5\x91\x75\xc6\x89\x85\x34\x75\x5a\x01\x56\xb1\xe1\xab\xa9\x53\x74\x05\x99\x3e\xa7\xcb\xd1\x29\x80\xe2\x74\x39\xf4\x00\x0a\xc9\x9d\xc2\x46\xb3\xdd\x61\xfc\x23\xc5\xf4\x25\xa3\x25\x30\x64\xc4\x49\x92\xf1\x91\x53\xda\xeb\x7b\xa0\x5b\xfb\x2d\x09\x8c\x18\x01\x91\xb3\x55\x46\x30\xa4\x63\x3e\xfc\x7f\xf4\x55\xbb\xd2\x57\xfd\xff\xa6\xde\xf3\xff\x68\x9b\xfe\x8f\xb6\x69\x97\xda\xa6\xff\xd7\xd6\xed\xfc\x9f\xd0\x41\xc5\xf1\x1a\xb6\x11\x78\xc0\x6d\x5d\x45\x6b\x70\x29\x1b\x09\xcc\x18\x45\x6b\xff\x54\x08\xe6\x9f\x0e\xb9\x5c\x24\xc4\xd2\x55\x4c\x05\xfc\x8f\x16\xea\x7f\x6f\x2d\xd4\x61\xda\x1c\xb6\x06\xff\x37\xb6\x27\xf9\x1c\xf0\x76\x63\x38\x33\x72\x8b\x01\x8e\x81\x81\x5f\x88\x81\x59\x53\x81\x3b\x82\xa7\x9d\x2f\x98\xd7\x3a\xc7\xbe\x0c\x67\x39\x25\xcc\xb5\x6f\xe0\xca\x96\xb5\x9d\x9c\xe4\x5f\x88\x7d\x21\x9f\x78\x18\x2c\xdf\xa3\x7d\x43\x8d\x83\xd2\x1e\xed\x9b\x1d\x33\x77\x0d\x63\x1b\xcf\x7e\xc3\x8a\xc4\xf9\x05\x10\x7c\x0f\x00\x5b\x8c\xcf\xd2\x81\xb6\x7d\x49\xa3\x61\x30\x0e\x27\xba\x43\x25\x2b\x4f\x3b\x70\x8d\x80\x51\x22\x9a\xa2\xef\x4a\x2c\x7a\xca\x76\x34\xf8\xaf\x8d\x62\xd1\x37\xbf\xdb\xd6\x05\x11\xef\xf6\x96\xb3\x06\xab\x93\x9d\x77\x48\xe1\x98\x80\x9e\x51\x81\x77\xa4\x00\x4b\x7b\x04\xc4\x28\xd6\x2e\xe8\x79\x4a\xfd\x13\x06\x14\x3c\x66\xc3\x96\x3a\xb3\x80\x1a\xc4\xdf\xf8\xb6\x35\x85\x72\x0b\xbe\xf7\xde\xd9\x38\xc9\x33\xac\x76\xcb\x07\x2b\xf6\x68\x47\xf7\x3e\x7c\xec\xc0\xba\x2d\xb4\x7b\xd0\x28\xa8\x69\xa6\x9b\xc2\xd7\x0f\x19\x4a\xbd\x76\xb6\x8a\xaa\xbe\x69\xa9\x8e\xb9\xb8\x46\xbc\xd6\x9b\xba\x5c\x6b\xb4\xba\x71\x8a\x35\x59\xac\x79\xbe\xd4\xf5\x8d\x42\x0a\x6d\x02\x08\x2c\xe1\x0e\x99\x26\x8b\x4e\x67\xd5\x99\xc2\x43\xa5\xd3\xce\x5c\x64\x95\x8d\xfd\x80\xd7\x97\xac\x35\x1d\x6f\x5b\xe4\x0e\xf1\x4d\x28\x43\xbc\xc6\xa7\x29\x13\x5a\xe3\xaf\x29\x16\x8a\x8d\xda\x51\x63\x99\x59\xf1\x6c\x95\xbe\x8f\x39\x12\x5f\x3b\xa1\x8f\xcd\x85\xc7\x16\x47\xff\xbf\xf6\x3c\x5f\x72\x27\x3b\x2c\x61\xc5\xd9\x69\xac\x7c\xea\x5e\x4e\x19\x20\x66\x09\x22\x31\x20\x63\xac\x5d\xba\xa6\xbf\xb8\xad\xbb\x18\x70\x5b\x40\x08\x73\x0c\xe9\x14\x43\x4d\x64\xaf\xdb\x5d\xa9\x76\xa8\xfd\x5c\x24\xf7\x7c\xfb\xf9\xf8\x66\xc7\x8c\x5d\x43\x53\xe6\x84\x6c\x7f\x40\xe1\xfb\xab\x41\x8f\x9d\xce\x01\x51\x8b\xde\x6d\x6f\xc4\x4e\x11\x8a\x01\x74\x42\xb1\x95\xc5\x69\xc9\x92\xac\x95\x76\x27\xd9\x23\x0c\x48\x60\x80\x43\x6b\x89\x42\x95\x20\xcc\x60\x17\xce\xa0\xb9\xb2\x09\x67\xda\x2a\xa5\x25\x5c\x1d\xbd\x9b\xa2\xad\xb6\xce\x11\x54\x13\xc9\x69\x25\xf3\xab\xb4\x1e\x41\xdd\x13\x82\xe7\xe7\xce\x83\x2f\x6a\xef\x68\x5f\x69\xab\xa1\xd8\x6f\x27\x9c\xf4\xe0\xa3\x5b\x59\xf7\xe6\xd6\x06\x6d\xe5\x5f\xce\xb1\xee\x73\x8f\x1b\xf9\x53\x1c\x47\x35\x8d\x66\x1b\x81\x05\x08\xc0\x83\xb0\xb1\x05\xc7\xed\x45\x8f\x2c\xcb\xaa\x35\x99\x41\x95\xdc\x18\x1f\x0b\x96\xd4\xf2\xef\xb6\x15\x46\xc7\xd8\x44\x44\x68\x45\xd2\x0f\x8f\x5c\x6c\xac\xd8\x6c\xed\x5c\x09\x9e\x5c\x61\x6b\x3b\xb7\x5a\x77\x1a\x05\x2b\xc6\xc4\x80\xb6\x0a\xc9\x01\x0b\x56\x7d\xc0\x68\xc1\xda\x07\x8c\x2d\x50\x26\x49\xd0\xb9\x64\xc8\xf5\x3b\xd0\x70\x9f\xa6\xde\x83\xe5\x78\x5b\x93\x41\xaf\x87\x95\x53\xa7\xb4\x22\x63\x56\x95\xcc\x79\xd1\x9a\x3e\xee\xfb\xf5\x75\x04\x6d\x23\x56\xa8\xf6\xa3\x15\x3b\x8d\x56\x4a\x0d\x90\x75\x1a\xd7\xbf\x3d\x1c\x3c\x94\xc7\xe0\x7e\x34\x94\x65\x3b\xe1\x64\xb4\x72\xa9\x63\x40\x67\x53\xd4\x6b\x0a\x71\x2d\x50\x06\x20\xa1\x46\x4c\x60\xa0\x3a\xe9\x44\xdc\x62\xce\x70\x3b\x74\x68\x97\x55\xaa\x58\x4f\xaa\x3e\xa3\x16\x88\xc9\x20\x80\xc5\x8c\xcb\x05\x9d\x16\x41\x54\x05\x5f\x04\xb7\x31\x92\x1a\x9a\x6c\x28\x97\x01\x29\x58\x19\xac\x24\x05\xa8\x85\x15\xc9\x82\x41\xf1\xde\x27\xab\x3f\x82\xbe\x92\xd6\x55\x41\x6a\x14\x15\xdd\x72\xfb\x9a\x6b\x4a\x5f\x79\xf1\x07\xe8\x3a\xa0\x6d\x3d\x7d\xb8\x9f\xda\xa7\x10\xfa\xa0\x79\xf3\x4d\xbb\xdf\x2a\x4c\x5b\x5d\xa5\x7d\xa2\x9d\xd3\x4e\x6a\x55\xef\xa3\xb9\xbe\x70\x9a\x5b\xcb\x1e\x03\x1e\x10\x4a\xde\x8a\x1e\xbd\x96\x2c\x8d\x4e\x4e\x38\x41\x64\x39\x74\x22\x4e\xbb\x9d\x9c\x23\x4c\x6a\x39\xf2\x52\xb5\x14\x3b\xb4\x19\x78\x3d\x98\x5d\x00\x39\x33\x56\x4f\x1b\x09\xa0\xee\x81\x29\x1e\x3e\x46\x7b\xd0\x1a\xb8\xd1\x93\x56\x69\x42\x7a\xa2\x7a\x05\xac\xec\x83\x2b\xea\x9c\xe8\x52\x70\xa3\x2b\x5f\xf0\x46\x22\x6a\x0e\x8d\x6e\x8a\x2c\xa3\x17\x3e\x28\x82\xa0\x31\x7e\x20\xf4\xae\x0c\xd2\xb0\x9d\x43\x84\x57\x0b\xf6\xbd\x02\x4e\x85\x54\x02\x72\xbb\xb4\x23\x6f\x9f\xd3\xfe\x6e\xd2\x0e\x2e\xa5\x96\x3c\xb7\x79\xe9\xc7\x73\x77\xae\x7f\xe2\xaf\x8f\xa0\x05\x84\x05\xf0\x16\xed\x2d\xad\x45\xfb\xbb\x36\xec\x33\xd8\x03\xda\xae\xb8\xb2\x75\x38\x55\xf8\xf2\xc9\xfd\x70\xe2\xc7\x2f\x9f\x7c\x45\x7b\x92\xe4\x95\x14\x00\x98\x8d\x7a\x2f\xc6\x0a\x3d\xba\x61\xb6\xc8\xb2\x51\xe3\x82\x1c\x0f\x45\x2c\x8b\xdb\x78\x60\x72\xe0\x6e\x62\x9b\x39\xa1\x58\x09\xdd\x28\x9d\xe4\xa8\x40\xc6\xd5\x9c\xd2\x84\xb1\xb9\xe5\x3d\xc3\x64\x8a\x18\xce\x72\x3a\x29\x30\x16\x0e\x40\x4f\x3a\xc6\x59\x85\x64\x81\xbb\xc5\x21\x88\x18\xd3\x02\x95\x47\xee\x08\xc4\xbd\x27\x34\x4e\x39\x15\x94\xf7\xce\x2b\x82\x30\x24\x85\x2c\x10\xab\x9f\x87\x72\x4d\x43\x29\xaa\x19\x06\xa0\x19\xce\xd7\x8e\xed\x9d\xf3\xa1\x56\x0e\x83\xcb\x1e\x5b\x36\x23\xba\xbb\x91\x5a\x3f\xfe\x93\x8f\x7e\x38\x5b\x45\xd5\xb4\x6e\xa6\x5b\xee\x7b\x84\x0a\x34\x18\x3a\xa1\xe3\x98\x1a\x20\x82\x1c\x84\xca\xb1\xba\x13\x2e\x9a\xf1\x72\x89\x14\x99\xd0\xac\x36\xa9\x15\x49\xc2\x61\x0b\xdc\xc4\x68\x27\x52\x2b\x76\x49\x10\x63\x0c\xef\xcd\x22\xfa\xe6\x51\x87\x33\x1d\x53\x65\x64\x79\x05\x31\x0e\xcc\x9c\xd3\x91\x22\x20\xea\xf5\xc9\x95\x58\x93\xaa\x0b\xbd\xa0\xc5\x3f\x37\xdc\xba\xb8\xbb\xed\xb2\x05\x89\xfa\x74\xf3\x73\xaf\x2d\xd8\xb8\x77\xe4\xb0\x9a\x17\xef\x9e\x72\xf3\xd8\xe7\x6a\x61\xed\x31\x78\xc7\x9b\xb5\xa3\x76\x9c\x6b\x3c\xfa\xf1\xcb\xbb\xa6\xde\x15\x87\xc1\x86\xda\xfb\xb7\x6b\x7f\x42\xe3\x18\x73\xe1\x34\xb3\xd9\x14\x00\xe9\xa0\x1b\xb8\x46\xef\x2b\xce\x22\x4c\xc3\x82\xce\xa1\xd4\xa1\x95\x58\xc2\x24\x4a\xb8\x8f\x38\x2a\xf8\x89\xb0\x5a\x5e\x96\x20\xc6\x1c\xc0\xed\x34\xbe\xef\x40\x3a\xaf\xd2\xc7\x70\x0c\xed\xeb\x48\x1e\xac\xb3\x43\x99\x38\xd3\x98\x9e\xc3\xa7\x2f\x5a\x03\x9f\x99\xe8\xd1\xb6\x3c\xae\x9d\x99\x68\x1a\x7c\x68\xf4\xda\x75\xf3\xbe\x5c\xb7\xff\xcd\xa6\x4f\x6f\xa9\x1f\xf1\xeb\x11\x37\x35\x0f\xf2\xc2\x7d\xf7\x42\xe9\x87\xbd\x8f\x5f\x75\xa3\x73\x45\x24\x5c\xad\xd5\x51\x23\x6b\x0e\xef\x7a\x55\x3b\xf2\xe4\x57\x1f\x6a\xc7\x1e\xf8\x69\xfe\x83\xd3\xef\xbb\xe3\xb1\xa4\xb6\x5f\x1a\x33\x0a\xb8\x41\x00\x14\x81\xc9\x00\xf7\x21\xaa\x7e\xa3\xbf\xaa\x90\x4b\xc4\x03\x39\x22\xe3\xc0\x1d\xdf\x50\xe9\x9e\x7a\x32\x33\xf4\x86\x7d\xac\x72\xca\x59\x13\xb8\x25\x31\xc3\x83\xe9\xc9\x45\xab\xae\x4b\x1a\xf0\x0b\xa2\x0a\x9c\x11\xd2\xdd\x62\x8b\x44\x94\x42\xd1\x60\xe8\xc8\x4b\x8d\x94\xa7\xa8\xba\xe2\x32\x8d\x36\x89\xd2\xda\xa5\xd0\xbc\xeb\xf9\x97\x96\xcc\xbf\x73\xf4\xa4\xd7\x16\xbf\xf3\x61\xd3\xdc\xb9\xb3\x16\x3c\xbc\x40\xd3\xdc\x1f\xff\x4e\xbd\xfd\xe6\x65\xaf\x40\xe5\x15\xd8\xef\xd9\xdf\x2e\x9c\x5a\x9f\xc5\x64\xd5\x8d\xbc\x7d\xcd\x88\xbf\xfc\xf1\x89\x35\x13\x47\xfc\xea\xfa\x27\xc6\xdf\x76\xcd\xf5\x71\x00\x81\x7c\xe1\x34\x3d\x9d\x19\x45\x6a\x13\x73\xf5\x15\x8b\xf2\x3a\x97\x09\xae\x4d\x6c\xd3\x60\x34\xc3\xb0\x2a\x59\x49\x6d\x62\x3a\x09\xcb\x62\xe6\x01\x3b\xef\xcd\xca\x45\xfb\x4e\x12\xd5\x40\x0e\xde\x75\xb9\x82\xa8\xe4\x44\x14\xab\x10\x03\x76\x29\xa0\xd7\x26\x3a\x52\xf9\x16\xda\xe5\x04\x9c\xa9\x9d\xa5\xf2\xaf\x96\xd5\xcf\xbf\xbd\xe7\xca\xc7\x7e\xd7\xeb\xbe\x9d\x83\xd7\x3d\xb5\xee\xc5\x8d\xb7\x97\x8e\x1e\x3f\x3f\xfa\x54\x7c\xeb\x8b\x90\x1a\x31\xe7\x8e\xde\xe5\xfd\xaf\xee\x51\x37\xa8\xbe\x47\xee\x6f\x1e\x9c\xf2\xbb\xab\x06\xf6\xaf\x2a\xbb\xfc\xfa\xea\x0d\xd7\x3d\x01\x8c\xf3\x34\xc0\x54\x84\x39\xaf\x6f\xd7\x19\xaf\x03\x5c\x42\xc9\x2f\x55\x19\x2c\x3e\xa6\x8a\x6d\xdb\x51\xa7\xd6\x30\xeb\xd4\x35\x68\x3b\x9a\x33\x05\x31\xce\xb8\xc4\xb4\x5c\x42\x1b\x11\xc0\x31\x00\x93\x1e\x03\xf0\x60\x6a\x2e\x67\x44\x11\x05\xc5\x95\x22\xc9\x5b\x99\x92\xe7\x10\x89\x99\xd4\x05\x81\x2a\x09\x7b\x5e\xed\xa2\xcf\x97\xbc\xf1\x6b\x13\x35\x7f\xd1\xd4\x09\xc5\x65\x9b\xae\xf9\xe0\xd4\x56\xed\xaf\xea\xce\x83\x4d\xe3\x46\x3f\xf6\x76\x69\xe8\xa1\xea\x91\x9b\x6e\x85\xb3\x1a\xe1\xa5\x3b\x76\xe5\xa4\x9d\xff\x7b\xf1\x63\x69\x79\xda\xab\xda\x4b\x9a\xa6\x95\x7e\xf7\xce\x81\x99\x73\x61\xf7\x73\xd3\xef\x5d\xfa\x03\x30\xc6\x48\x1f\xc2\x3d\xa2\xb9\x60\xa2\xde\x25\x9a\xec\x6a\xcf\xe1\x12\x71\x6b\x9a\x17\xed\x4e\x2b\xda\x9d\xa1\xd4\xf6\xb4\x2c\x9d\x1a\x2f\x0f\x86\xd5\x2c\xdc\xd5\x6e\x73\x79\xd3\xd0\x0a\x71\x82\x2a\x62\xc7\xc0\xe5\x15\x44\x45\xc2\x79\x1e\x20\xa2\x9b\x20\x4d\x10\x53\xd9\x63\x3c\x6e\x26\x18\xe2\x52\x09\x23\xa4\xb6\x4d\xb9\xfc\xec\xea\xf5\x1b\x34\x45\x7b\x2b\x97\xb9\xff\xa1\xeb\x17\xdf\x70\xc7\x8a\xea\x7d\x7f\x78\xd7\xf5\xfe\xb7\x83\xae\x1b\xdf\x08\x17\xec\x87\xc3\x0f\xcf\xbf\xbf\xf1\xd8\xe0\x87\x96\xf6\xe8\xb6\xb6\x24\xf8\x01\xdc\x7a\xcf\xd4\xf2\x2b\x0f\x01\x78\xe1\xe3\x0b\xa7\x4d\xe7\x99\x1a\xd0\x1f\x7c\x00\xa2\xfd\xd0\xcd\x58\x22\xab\x34\x97\x50\x8a\xca\x48\x88\xac\x47\x79\x05\x82\x62\x90\x4b\x28\xe1\xb2\xa8\x0b\xe2\x6e\x68\xcc\xb9\x93\x5b\x86\x95\x76\xa2\x5e\x5f\x00\xfd\x86\x9d\x4b\x28\x39\x65\x71\x77\x9f\x7e\x2e\x47\x58\xed\x5d\x29\xcb\x98\xaf\xd9\xe3\x2f\x2b\xc3\x5c\xde\xdc\x49\x55\xb4\xe2\x9a\x9d\x0a\x18\x56\xcb\x9d\x09\xa5\x5c\x17\xfe\x76\x62\x79\x94\x5e\x30\xac\x16\x10\x0e\xef\x76\x39\xfe\x0a\x3e\xe6\xa9\xf0\x4a\x61\xa5\x9c\x8f\xf9\xcb\x7d\x52\x38\xd6\x1b\x3d\xd1\xfb\x4a\xf4\x9e\x8e\x79\xfc\xbd\x2b\x93\xd8\xa6\x0f\x14\x44\xb5\xa0\x57\x24\xa2\xda\xdd\x82\xa8\x72\x22\xba\x4b\xb9\xca\x36\x73\x6b\x30\x01\x70\xb2\x24\xd3\x72\x92\xa0\xa2\x63\x9f\x75\x88\x0e\x49\x21\x13\x08\xe5\x06\x33\x4a\xe5\x3b\x9e\x19\x3f\x76\x74\xf9\xc0\x11\x95\x3b\xe3\xcc\xb6\x31\x5b\xc7\x6d\x0a\xae\x3d\x3e\x6b\xe8\x80\x60\xf8\x92\x3b\x36\xdd\x31\xe6\xd6\x3e\x7d\x6f\xec\xb3\xbd\x89\xd9\x31\x6e\xcb\x84\xcd\xe5\xda\x97\x87\xaf\x61\x96\x3b\x97\x40\xe7\xaa\x79\x4b\x5c\x2b\xc4\xf7\xdf\x2c\xcc\x85\x1f\x68\xf9\x0d\x7f\xa9\x13\x9f\x70\x2c\xd6\xbe\x5f\xbd\xf8\x71\x7e\x25\x7f\xea\xad\x3e\x99\x5a\x06\xfc\x3c\xa1\x7d\xab\xe7\x0c\xe9\xe1\x4c\x0d\x28\x44\xb7\x51\xbe\x91\x33\x4c\x83\x7a\xce\xd0\x6e\xcb\x4f\x33\xfa\x4a\xf5\x9c\xa1\x2b\xa1\xb8\x90\xb1\xcb\xb4\x1a\x99\xc2\x7c\x02\xae\x6c\x7a\xa6\xd0\x4e\x0c\x83\x22\x0a\xaa\x27\x33\x12\x51\xd2\x44\xc5\x9b\x9a\x29\xc4\x45\x00\x39\xba\x35\x4f\x49\x15\xea\x15\xb2\x54\xd5\xae\x61\x73\x57\x8d\x99\xbc\x2a\x34\x06\x06\xaa\x87\x0f\x9a\x3b\xb4\xfc\x96\xed\x63\xd6\x3c\x37\x6f\xf6\xbe\x33\xff\x55\xbd\xa3\xd7\xd6\x70\xf1\xf4\x51\xc3\x07\xaf\x7a\x71\xc0\xa0\x50\x68\x41\xb8\x68\xfe\xac\xa9\x4f\x64\x32\xbd\xf6\x6c\x6d\xce\x03\x10\x4c\xc7\xf7\x6b\x15\xf0\xa3\x93\x22\xa0\x8d\xe4\x6d\x27\x66\xe2\x94\x8d\x9e\xea\x4e\x92\x39\x08\x59\xf1\x0e\xdc\x58\x86\xdc\x35\x97\x80\xab\xbb\x74\x55\x12\x04\x92\x78\x41\x10\xf5\x53\x43\x63\x39\x25\xf4\xb9\xbd\x36\x49\x3b\x01\xc8\x82\xe9\xde\xa5\x8d\x2b\xc4\xfa\x11\x4f\x3f\x92\x33\x26\x9a\x58\xe1\xb3\x8e\x6c\xbc\xe3\x91\x27\xce\x5f\x3a\x8d\xda\xd0\x3a\x64\x64\xcf\xc5\xf7\x7e\xba\x06\xbe\x77\xae\xf1\xe8\xbd\x13\xeb\xd1\x39\x47\xdf\xfd\x7e\xdc\xb7\xd9\x0d\x79\x24\x5d\x7e\x7b\xa5\xa0\x54\xcd\x61\x13\x4a\x46\xa9\x12\x92\x53\x74\x58\xda\x0f\x25\x0d\x86\xd5\x6c\x27\xe9\x56\xe8\x34\x2a\xc5\xc5\x93\xeb\x2a\xe4\x4a\x28\xa1\x52\x35\xcf\x45\x4c\x61\xdb\x40\x85\x6c\x41\x54\x73\x0a\x88\xe0\x31\x19\x70\x81\x97\x90\x08\x64\xe4\x08\xa2\x92\xf6\x4b\x83\xee\x98\xaa\xeb\x7a\x12\x60\x66\xbb\x64\x5d\x97\x73\xc2\x0e\x4f\x4d\xd8\x41\x10\x01\x80\xb9\x92\xa9\xea\x94\xaf\xfb\x7f\xd8\x7b\xf3\x30\xa9\x8a\xb3\x7d\xb8\xea\x2c\xbd\x2f\x67\xe9\x75\x7a\xb6\x9e\x9e\x85\xa1\x99\x69\xa6\x7b\x16\x9a\x65\x58\x64\x19\x46\x04\x05\x44\x44\x44\x44\x64\x53\x40\x41\x44\x45\x42\x10\x09\x2a\xa2\x2c\x82\x88\x86\x28\x22\x22\x2a\xa9\xd3\xdd\x0c\x48\x5c\xda\x5d\x63\x8c\x31\x46\x8d\xf1\x45\xe3\xeb\x9b\xc4\x36\x68\x92\x71\x89\x28\x7d\xf8\xae\xaa\x3a\xa7\x97\x99\x01\xcd\x2f\xb9\xae\xef\x7b\x7f\xd7\xf7\x07\xc7\xee\x33\x03\x9e\xba\xeb\x39\x55\x4f\x3d\xcb\x7d\xc3\x33\xe4\xeb\xc4\x7c\xbe\xee\xe1\xee\x7f\xd0\x04\x05\xe5\x02\xfd\x3f\xca\xd7\xe5\xf3\xf4\xf1\x4f\x12\x57\x33\xe0\xbf\xb3\x1f\xc1\x25\xef\xaa\x7b\x97\x71\x9d\xd9\xbf\x31\x62\xf6\xa3\xec\xdb\x4c\x28\x7b\x8c\xe6\xe3\xf7\x9d\xea\xe6\xfc\xdc\x54\x50\x9a\xd3\x3d\x76\x0a\x01\x52\x17\x66\xc8\x50\xfe\x06\x59\xeb\x81\x16\x08\x71\x43\x8e\xe0\xe9\xae\xee\x1d\x34\x1a\x24\x08\x48\x24\xd1\x49\x47\x1a\x28\x0e\x11\x3f\x0d\xbe\x52\xa6\x65\x41\x94\x14\x1b\x99\x1c\x99\x15\xa5\x04\x34\xf9\x88\x35\x6a\x49\xb5\xb6\x76\x36\x16\xf5\xb2\x21\x99\x92\xe0\x30\x78\x6e\x66\x94\xd4\x0f\x99\x7e\xde\x98\x81\x53\xaf\xfa\xe9\x75\xb7\x5c\xfb\xe7\xae\x37\x6a\xea\x27\xcc\x9a\x74\xfe\x45\x4b\x6e\xbb\x2c\x7a\x9f\x7d\xec\xbd\xaf\xdd\xfa\xcb\xf5\x23\x43\xdf\xbd\xc1\xa6\x4c\x43\xee\xfc\x52\x55\x93\x17\x00\x0d\x77\x7e\x26\xd7\x09\x5c\xe0\x16\x2d\xc7\x66\xb1\x3a\x5d\x24\xc7\x06\x49\x96\x51\xaf\x72\x71\x39\x48\xd8\xd5\x8a\xcf\x25\x8e\x7c\x95\x0b\xed\x22\xcc\x65\xd8\x5c\x02\x92\xd3\x47\xdb\xef\xe9\x3e\xa8\xa5\x89\x48\x5e\xd9\x22\x20\x73\x9a\x05\x0a\x3e\xf0\xc3\x24\x34\xdb\xf4\xc4\x80\x62\xc5\xeb\x29\xef\xcc\xe5\x87\x79\xca\x46\xa5\x85\x9a\xd9\x90\x6c\x30\xc2\x10\x5b\x5b\xc7\xc6\x3f\x7d\x7d\x89\x87\xad\xba\x10\x6e\x3a\xf6\xd7\xfb\x8f\x8a\xf3\xd4\x9b\x7f\xb2\xc8\xc5\x1e\xe5\x3a\xb3\x23\x7f\x36\xe8\x9c\x7b\x99\x83\xdf\x75\xb1\x8b\xea\x1e\xcf\x2e\x62\x76\xdc\xd6\x71\x72\xa7\x3e\x36\x6e\x0b\xe1\x6c\xed\x99\x1f\x83\x7d\xe6\xc7\x8c\xa7\xcb\x8f\x89\xdf\x97\x1f\xd3\x4e\xcb\x78\x76\xb7\xff\x9f\xe5\xc7\x64\x5a\x0c\x1d\x92\x83\x6c\xfc\xd3\xc4\x2c\x86\x9b\x93\xfa\x4b\xd7\xbc\xec\xc9\x05\x5c\xa7\xda\x06\x5f\xfd\xae\x0b\x1e\x57\x5d\xff\x0b\x34\x47\x31\xe6\x54\x0f\x5c\xe3\xfe\x55\x1c\xba\xb6\x73\x4e\x14\xfc\xf4\x8a\xe0\x9a\x0c\x78\xd2\x61\x95\x4c\x61\xca\x77\x12\x21\xb1\x54\x4d\x7d\x74\x38\xf3\xa5\xa6\xc8\xe9\x14\x90\x90\x46\x0e\xa2\xad\xa0\xd8\x05\xfc\xf6\xe0\x6b\x4e\xdf\xb9\x4f\x01\xf1\x04\x8b\x87\xff\x83\xf5\xc3\x37\xa7\xb6\xf4\xd6\x0f\xcf\xce\x65\x50\x91\x7e\xb8\xd6\x93\x4f\xce\x18\x41\xb0\x44\xd3\xa5\xf4\x69\xc2\xc7\x44\x0c\x80\xe8\xb4\x80\x48\x2e\x83\x21\x92\x57\xa9\x60\xdc\xa5\x5a\xdc\x30\x04\xc3\x0a\x74\x89\x12\x12\xe2\x88\x11\x13\x2c\x47\x68\xe8\x4b\xa5\xa4\xd1\x41\xa4\xde\x81\x52\xee\xc3\x9e\x9e\x45\x10\x59\xbd\x33\xb9\xa8\x6d\xbe\x8f\xae\x79\x78\xee\x36\x9f\xe9\x92\xe4\xcc\x3b\xee\xdd\xf4\x8f\x9d\xe9\x0b\x2d\x82\x75\xee\xf3\x57\xcc\x9b\xb3\x7f\xce\xc1\x8b\x9f\x59\xae\xba\x0c\xad\xaf\x5f\xbb\xf0\x95\x9f\xbf\xad\xfe\xec\xf9\x27\x6f\x6d\x52\x6b\xd9\xce\x05\x2b\x48\xb3\x7c\x97\xfa\xc7\xff\xcf\x71\x98\x10\xfb\x32\x6c\xe2\x66\x81\x30\xf8\x40\x5b\xaf\x5c\xee\xca\xa0\xbe\x5e\x11\x13\x43\x8e\x98\x52\x6b\xcc\xa0\x00\x55\x0d\x00\xef\x28\x61\x4b\x06\x85\x8b\x00\xc7\xa7\x56\x8d\x96\xcd\x07\xc3\x84\x0c\xdd\x25\xfa\x4c\x5a\x98\x2f\x42\x42\x7c\xba\xb8\x80\x46\xc8\xec\xa0\x9c\xab\x94\x7f\xf5\x68\xfb\xc7\x5f\x96\x6a\x01\x19\xe4\x49\xd3\x75\x0f\x24\x65\x8f\x4e\xc7\xaa\x7f\xea\x61\x90\x95\x41\x6c\x90\xb5\x94\xaa\xd0\x6a\x8b\xc7\x91\x4b\x52\x1c\x01\xb2\x0b\x03\x51\x4a\xb1\x9c\xd5\x26\xf6\x90\xb8\xf7\xc6\x5a\xfb\x30\x54\xf2\xb9\xc0\x66\x47\x5f\xb6\x62\xf4\xd5\xab\x6c\xa6\xfd\x6f\xfe\xf8\x36\xcf\x1d\x5d\x77\x49\x94\x57\x74\x61\x6a\xab\xb4\x7e\xf2\xae\x95\xc4\x84\x67\x4c\x8e\xad\x5d\xfe\xe5\xc6\x75\xd3\x67\x62\x2b\x9e\xd5\xd4\xde\xb9\xfc\xed\x3b\x55\x81\x41\xb3\xea\x37\xe7\xec\x19\x9e\x1a\xae\xba\xb8\x0a\xe2\x67\x5d\x0c\xa8\xfd\x9a\xc4\x58\x0c\x79\x08\x4f\x8c\xde\x56\x6d\xb2\xe4\x0a\xe4\xd3\xb7\xfd\x33\xf5\x03\x32\x8b\x8c\x87\x92\x95\x18\x45\x05\xd8\x88\xb4\x36\xa5\xfe\x67\x63\x72\x39\x74\xc7\xda\x61\x8e\x1b\xe6\xd9\xe1\x63\x26\x5f\xdb\x3a\x6e\xdf\xa1\x71\x56\xc1\x50\xb2\xa0\x1c\x0e\x7f\x36\x3b\x6e\xc6\x93\xeb\x26\x0d\x57\x8f\x4a\xf3\xe7\xac\xe1\x66\x64\x3f\x3a\xfb\x6f\xb3\x46\xfd\x77\x9c\x99\xf1\xad\x7a\xe0\x36\x37\xf8\xff\x75\x39\xfe\x63\xba\x1c\xf0\x54\x0a\x00\xce\x45\xf6\xcd\xc2\x9c\x22\x3c\x43\x4e\x11\xcf\x21\x8c\x41\x39\xc4\xc2\x09\xf0\xfd\xcf\xba\x0e\xc0\x51\xbf\x51\x07\x9d\x3c\x7c\x54\x3d\xc8\xb4\x30\x6e\x75\x11\xdc\x91\xfd\x38\xfb\x16\x3c\xa0\x4e\xc3\x7e\xbc\xba\x8e\xf8\xf1\x55\xe0\x69\x90\xa8\xd4\x9c\x60\xe4\x8e\x92\x1e\x50\x4a\xfc\x85\x37\x0d\xfd\xbc\xdb\xa7\x07\xec\xc3\xbb\x84\xcf\x6f\xa2\xbe\xbc\xde\xea\xb7\xba\xbb\x91\x8a\x85\xf9\x1b\x79\x54\x92\xe6\x14\x9f\x70\xc2\x41\xd8\x93\x77\x77\x3f\xaf\xa7\x52\xec\x69\xba\x7b\x80\x94\x5d\xf0\x6a\xc2\xf9\x30\x69\x17\xa8\x42\x75\x81\x5a\x21\x3e\xe8\xf8\x45\xa5\xac\x9c\x96\x44\x4a\xda\xd9\x20\x09\xa4\xb2\x72\xf2\x8e\xf6\xf2\x93\xb5\xd4\x1b\x99\xa5\x16\x12\x94\x2b\xf2\x90\x1f\x14\x6b\xfb\x05\x62\xcb\xbb\x26\xb7\xc7\x4d\xf7\xfe\xfe\xa6\x9e\xa7\x85\x93\xdf\x8e\x8d\x85\xc2\x8e\xec\x37\x70\xa9\x78\xd9\xa5\xef\xdf\x89\xd7\xbb\xdd\x00\x70\xc3\x88\x86\xf7\x77\x9a\x3d\x0b\x94\x1b\x2d\xc1\x91\x9a\xd7\x94\xcf\x22\xb2\x76\x6d\xeb\x0f\x14\x68\xd1\xd1\x72\xb1\xc2\xe3\x4f\xc1\x36\xda\xf0\x55\xba\x2f\xe5\xb9\x4d\xdd\xd7\x68\xed\x77\xa4\xf9\x4b\x10\x48\xa1\x18\x2d\x64\xce\xeb\xd1\x21\x51\x48\xda\x45\x07\x11\xbe\xc6\x57\x19\x5f\x8b\x45\xea\x12\x92\xa8\xb1\xdc\x22\x7b\x1c\x1c\x62\xec\xbc\x41\xd2\x92\x3d\xb0\x8b\xb1\x3b\x9c\xbc\xfe\x55\x6b\xba\x24\xc9\x4c\x1f\x3d\x94\xd0\x66\x17\xd6\x82\x4f\x61\xf8\x33\x79\x0b\x86\xc3\x98\x83\x4a\xd9\xb5\x0e\xc7\x8e\xa1\xce\x52\x5d\xbb\xdb\xd7\xda\x55\x17\xe6\xc6\x4e\xba\xf3\x97\x11\x5f\x2a\x73\xa4\xb1\xa9\xd6\x34\xfa\xd0\xa2\x8d\x9b\x98\x6d\xad\xeb\x4f\x1e\xfd\x55\xe5\xf8\xf1\xc7\xdf\x5b\xfe\x5d\xd7\x7b\x7f\x5b\x3a\x63\xce\x9d\x64\x0f\xb9\xfa\xd4\x71\xc2\x2d\xdd\x1f\x6c\x06\x89\x32\x6c\x73\xfd\x30\xb0\x55\x34\x04\xe1\xd6\x84\x58\x9d\x25\xd8\x04\xc3\x7d\x9b\xa0\x93\x02\x8a\x4f\x5e\xd8\xb5\x2a\xb5\x93\xe0\x53\x09\x15\xb1\x23\x22\x2b\xc4\x84\x2c\xfd\xe2\xa4\x49\xb9\x86\x9c\xb7\xa4\x84\xec\x26\x14\xf9\xa5\x65\x22\xad\xb8\xa5\xc3\x4c\x81\xf2\x8a\x9a\xda\x62\x8b\xea\x8b\x45\x5a\x3f\x85\xd5\x69\x96\xd5\x83\x3d\x7a\xca\xae\x6b\x2b\xe7\x1e\xc2\x7b\xc1\x8c\x03\x33\x75\x8a\xe9\x6f\xfb\xe2\x8e\x5e\x79\x6c\x17\x39\x87\xdd\x70\xf9\xda\x65\x5f\x6c\xa4\x98\xa8\xeb\x08\x26\xad\xe0\x2d\x90\x68\xd6\x62\x36\x16\x63\x46\xf1\x54\x45\xa3\x89\x66\x8b\x25\x9c\x1c\xd1\x5c\x6b\x0e\xa3\xba\x28\x41\x4b\xc3\x28\x80\x31\x6a\xfb\x5e\x8c\x02\x54\x54\x2d\x59\x5b\x1a\x30\x85\x95\x3a\x4b\x06\xd5\x45\x48\x60\x66\x90\xf6\xe2\xde\xd2\x3d\x8b\xbc\x9e\x75\x02\xea\x97\x76\xa0\x5a\x01\xd5\xa4\x01\xaa\x69\x84\x4a\x4d\xbf\xc2\x77\xd2\xd2\x4c\x01\x6d\x8a\x6a\x80\x7a\x1a\xb1\x93\x51\x27\x2a\xfd\x07\xc4\xe3\xa8\x56\x42\x15\x1a\xa8\x5d\xa0\xa2\x3a\x3c\xa0\x29\x7a\x7a\x58\x7b\x7c\x6e\xa5\xaf\x6d\x5d\x01\xa7\x77\x0e\xe2\x7b\x57\x94\x61\x88\x87\x75\x50\x8c\xf7\x3a\xeb\x43\x25\xfd\x1c\x2b\x52\xe7\xb6\x0f\x61\x0c\x3b\x5f\xc9\x81\x3d\x7c\x05\x73\x5f\x76\xe2\xdc\xfe\xed\xe3\x57\xfc\xee\x0e\xf8\xf7\xec\xc4\x19\x03\xc6\x74\x12\xb4\x4f\x7e\x7b\x7e\x75\x6d\x3f\x2b\xab\xbf\xdc\x14\x78\x92\x47\xe2\x26\x70\x9d\x40\x02\xe5\xf8\x94\x62\xd3\x75\xea\x35\x2a\x61\x05\xd0\xd4\x08\x1f\xb0\x91\x9a\x7b\xfc\x96\x57\x90\xc4\xab\x2c\x92\xd4\x01\x61\x21\x10\xf3\xaa\x2d\x3b\xba\x77\x13\x20\xa5\x46\x07\x12\xd3\xbc\xc2\xe0\x05\xb0\x2c\x8d\xca\x84\x24\x5b\x86\x4f\xc2\x6c\x19\x53\xd8\x6c\xc8\x8a\x65\x84\x0a\x87\x61\x45\xa9\x2c\xff\x42\xfa\x64\x7c\x2e\xb3\x11\x55\x17\x37\x76\x59\x9c\x1a\x2f\x01\x5b\x40\x79\xd9\xd2\xdc\x16\x80\xae\x5c\x65\xb8\x61\x6a\x90\x11\xe6\xad\x9b\xfe\xe8\xc3\xf3\x5e\xf8\xc9\xe3\x47\xbc\x73\xe2\xcf\x5e\xbd\x66\xc1\xc2\xa9\x2b\xbc\x2c\xda\xa5\x86\x7c\x77\xdf\xbe\xf4\x91\x59\x0f\xec\x3a\x67\x39\x7c\x35\xbb\xe1\xc8\x35\x97\x4e\x1f\xeb\x5e\x4e\xf6\xed\x35\xa7\x8e\xf3\x3b\xb9\x4e\xe0\x04\x01\x50\x01\x7e\x09\x12\xa5\x54\x47\x92\x32\xe5\x48\x5a\x80\x24\xc1\x95\x95\xe3\x05\xcf\xe8\xb3\xe3\x05\xcf\x68\xcc\x51\xbb\x09\x62\x26\xc9\x0a\xba\xe5\x09\x5a\x73\xab\x48\x02\x05\xd8\xb3\xae\x10\x33\xa8\x82\xbe\xa8\xe5\x45\xea\xfe\x2f\xf7\xa8\xcb\x28\x21\xab\xdd\x5b\x04\xc0\x12\x21\xc9\x97\x10\xf5\xcd\x92\x1e\xea\x9b\x25\x54\x91\x8c\xfc\x97\x80\xe5\xe6\x44\x29\x69\xb4\x4b\x3e\xaa\x57\x2a\x15\x6c\xde\xd8\xbc\xf2\x0d\xe2\x6d\x05\x60\x41\x39\xc6\xae\xf1\xae\xed\x9a\xbf\xfe\x82\x87\xf7\xfd\xe9\xe5\x83\x5d\x89\xa7\x16\xdf\xb4\x70\xde\xb4\xab\xbc\xcc\x6b\x7f\x39\xf4\x29\xac\xbb\x70\x3e\x73\x99\x1a\xf2\x6d\xbf\xfd\xf1\xd7\xf6\x3c\x72\xe4\xea\xb9\x17\x8e\x71\x2f\x52\x37\x71\x9d\xdf\x75\x61\xbb\x59\x43\xfc\xf2\x4e\x20\x80\x32\xf0\xb3\x02\x2d\x7c\x4d\xd5\x37\x65\x2c\x71\xe4\x50\xa2\x74\xa1\x22\x46\x49\xd4\x51\xd2\xc5\xf1\xc5\x3c\x45\x68\x6f\x3c\x4a\xd3\xa8\x54\x48\xf2\xa5\x04\x86\xd2\x1e\x30\x94\x6a\x30\x94\xea\x30\x78\x09\x0c\x0e\x57\x09\x81\x81\xe8\xeb\xf7\x86\xa1\x47\x16\xa4\xca\x68\xc0\x20\x2c\xdc\x3c\x67\x7f\xe2\xca\xd7\x6f\x3d\xf8\x6c\x62\xde\xfc\xeb\x6e\x59\xb8\xe8\xea\x65\x5e\x58\x7f\x01\x45\x60\xdb\xe6\x2b\x1f\xbd\x64\x97\x32\x6b\xc6\xd5\x73\xcf\x3b\xc7\xbd\x00\xfc\xaf\xe2\xa1\x8b\x9f\xfa\x3b\xff\x27\x6e\x3a\x70\x81\x2a\xb0\x47\xf3\xa6\x5c\xb1\xfc\x19\x91\xb8\xd7\x90\x89\xc5\x94\x0a\x63\x26\xc5\xca\x34\x49\x6c\xcc\x05\xfb\x5d\x96\xfc\x59\x51\xcc\x25\x89\xb5\x04\x95\x7e\x6c\xac\xee\x91\xb4\x77\x09\x49\xd6\x45\x8a\x2d\x5c\x34\x49\x2c\x6b\xba\xf1\x5a\x92\xb8\x54\x4f\x12\xb3\x0e\x51\x42\xee\x38\xaa\x10\x15\x4b\xa9\xce\x04\x1e\x6b\xad\xce\x8f\xb8\xa5\x2d\xd4\x23\x3f\x1c\xff\x34\x31\xeb\x8b\x91\x90\xfb\xf9\xe1\xdf\xdc\xf6\xd9\xdd\x87\x7f\xc3\x9c\x5c\xc0\xf8\x96\x5d\x71\xf1\x3d\x53\x97\xce\xb9\xfc\xde\x69\x5c\xa7\xda\xf6\xe7\x7f\x7c\xf4\xf2\x4b\xea\x91\xc4\xc7\xcf\x4f\x53\x5d\xf0\xce\x1f\xdd\xbe\x15\x9a\x1f\xba\xe6\xb6\x6d\xea\x57\xe4\xbc\xfc\xee\xa9\x2f\x39\x86\x70\xa7\x57\x03\x45\xcb\xf6\x0b\x62\x8c\x44\x60\x12\x0e\x4d\x3b\xbe\xca\x94\x41\xc1\x68\x4a\xae\x08\x38\xec\x61\x54\xa9\x27\x89\x49\x26\xcb\xfa\x8e\x52\x26\x12\x12\x16\xe2\xd8\x88\x24\x93\xa5\x05\xf8\xe9\xdb\x2b\x0a\x28\xa8\x39\x30\xd8\x5d\x91\xc4\xa0\x1c\x4e\x56\xe2\x2b\x9b\x74\x4a\x95\x41\x3d\xfe\x54\x66\xc5\x36\x6b\xf0\xe2\x57\x17\x89\x94\xf8\x98\x0d\xd0\x73\x8a\x2c\x2a\x06\x6f\x3c\x8e\x2a\x24\xc5\x68\x22\x62\x11\xc8\xaa\xc7\xe0\x5a\xdb\x5a\xdb\x1a\x89\x90\x27\x65\x84\x75\x40\xa3\x83\x09\x55\x41\x17\x4d\x1d\xd7\x7b\xca\x9a\xc7\x36\x76\x2c\xbf\x64\xf6\x27\xbf\x84\x7b\xfe\x92\xbc\xf8\x27\x6d\xe7\x0c\xad\x1f\x3c\x71\xf6\x59\x51\x38\xff\xcd\xd4\x84\xcf\x96\x5c\x7b\xa7\x61\xec\xec\x7b\xfa\x97\xdd\x74\xf1\x9e\xa3\xdf\x75\x41\x14\x1c\x7b\xfe\x75\x33\x07\x30\xdf\xee\x85\xf3\xe6\x6b\x79\x4b\xf6\x59\x43\x90\xe4\x85\xc2\x60\xdd\xf7\x65\x86\x06\x14\x66\x86\xaa\x61\x58\xa9\x71\x67\x50\x4d\x3e\x49\xd4\x00\xc3\x4a\xb5\x4d\x94\x14\xab\x3f\x1e\x47\x35\x22\x35\xf9\x32\x29\xc9\x55\xd6\xd5\xff\xc7\x72\x46\xb2\xde\x87\x7c\xe6\xe4\x51\x94\x36\x24\x9f\x3e\x87\xc4\x72\x5a\x67\x32\x47\x70\x78\x89\x7f\x97\xe0\xd0\x00\xe2\x60\x5b\x4f\x24\x82\x18\x89\x12\x1d\x09\xec\xaf\xb5\xc5\x52\xb5\x94\x1a\xa4\x29\x0a\xd1\xe0\x42\x64\x42\x30\xac\xf4\x73\x65\x50\x3f\x52\x34\x8a\x1a\xa3\x18\x1c\xd4\x1c\x55\x86\xc0\xb0\x12\x22\xf8\x94\xc4\xe3\xa8\x9f\x86\x4f\xb9\xa4\x70\x41\x42\x4c\x95\x94\xe4\xa6\x36\x2a\xc6\xe0\x14\x25\x8a\x0c\x21\x86\x38\x23\x32\x92\x51\x87\xe6\x34\x8c\x21\x7d\xe3\xa4\xd6\x53\xa0\xd6\xf4\x96\xe5\xee\x0d\x19\x33\xf2\x5e\x8c\x19\xbc\xa7\x27\xa1\x08\x03\xe2\xaa\x8b\xab\x33\xb8\x40\x7f\x10\x86\x4d\xda\xda\xd3\x3f\x86\xfc\x11\x12\x8f\xaa\x89\x28\x82\x31\x83\x98\x88\x02\x2d\xf8\xdd\xe3\x69\xa9\xb2\x7e\x20\xa6\x16\xd5\xdf\x92\x41\xfd\x8b\xaa\xdd\x42\x5a\xee\xb8\x21\x57\xf4\xf5\x14\x0d\x7d\x7e\xfa\xe5\x08\xba\x7d\x54\xe2\x77\x4f\xf1\x88\x27\x90\x3b\xcd\x53\x22\x49\x7c\xfe\xe5\xf0\x15\xf5\x17\x92\xc6\xfe\x84\x83\x19\x5f\xf5\x73\x99\x35\x69\x25\x37\x6d\xe4\x5a\x8f\xaf\x89\xfa\xfe\x86\x82\x90\xbd\x95\x14\x43\x76\xb9\x3d\x95\xc1\x7a\xbd\xc3\xa8\x11\x8e\xb0\x42\xce\x68\x29\xbe\x99\xf3\x61\xfa\xe3\x03\x2a\xc3\xc6\xe3\x8a\x81\x17\xa5\x94\xdd\xe1\x0f\x10\x69\x8d\x90\x98\x34\x99\x05\x2a\x2e\x0e\xca\x45\x09\x95\xe2\x37\x22\x61\x77\xc8\xd8\x37\x67\x04\x51\x42\x61\x52\x2b\x13\x6a\x8b\xb5\xc5\x8c\x41\x63\xd0\x01\x8d\xb9\x18\x4c\x8e\x8f\xa9\x2d\x1f\x80\x81\x71\x68\xb8\xbb\x62\x7b\x5d\xaa\x1e\xce\x28\x57\x1f\xab\xac\xf1\x5b\xb6\x1d\x5b\x7b\x97\x77\x7f\xcd\x83\x1b\xc6\x0d\x6a\x1e\x75\x63\xff\xfd\xee\xad\xd3\x1e\xfc\x51\xe5\x4c\xd6\xc5\xbd\xbd\xe1\xc8\x91\x0d\x9b\xf6\x4c\x3c\x76\xe7\xc6\xf6\x45\x27\xff\x86\x76\xbb\x77\x79\x5f\x63\x85\x25\x7e\x12\x82\x39\x97\xeb\x20\x79\xe1\xd8\xa9\xe3\xec\xeb\x86\x20\xa8\x06\x8d\xe0\xca\x3e\x33\xfa\x91\xbe\x32\xfa\x03\x8b\x32\xfa\x23\xcc\x34\xa5\x5f\x53\xdb\x48\xb3\xfa\x89\x8a\xca\xfa\xf8\xbf\x9d\xd7\xcf\x93\x33\x9c\x39\xc3\xff\x17\x8d\xa9\xe1\xcc\xa9\x7e\xee\xa2\x42\x4e\xa8\xff\x4d\x5c\xb8\x96\x53\xc7\xd9\x09\xdc\xac\x02\x3e\x28\x4e\x9f\x21\x8f\x56\x73\x61\x7f\x47\xf1\x5b\x08\x1f\x94\x91\x46\x1c\x29\x1f\x94\x5d\x94\x12\x56\x2e\x44\x49\xef\x92\x96\x62\x3e\x28\xae\x80\x0f\xca\xde\x83\x0f\x4a\x4f\xb3\xd6\xd1\xcd\xa7\x27\x1f\x94\x21\x54\x65\x19\xf9\xb3\x73\x6e\xf8\xd1\x98\xe5\x6b\xaf\xf8\xd5\x23\x07\xf6\x0c\x6e\xb9\xf9\xc2\xe9\x0b\xc7\x5f\x79\xf5\xf9\x0d\x1f\xbe\x96\x6a\xda\xd7\x6f\xe0\x25\xe7\xb4\x4d\x1a\xd9\x71\xe7\xac\xdb\x1f\x9d\x70\xa7\x3f\x3c\xe5\xac\xb6\x73\x86\x9e\x35\x65\x76\xfb\xcf\x12\xb4\x1e\x21\x0e\x00\x53\xcf\x7f\x0c\x58\xe0\x00\x17\x6a\x6b\x06\x9b\x57\x36\xb1\x45\x14\xa3\x39\x43\xfa\xfe\x41\x8e\x58\x56\xaf\x60\xe3\x2a\xdf\x11\x15\xb3\x35\xc7\x05\xa0\x69\x98\x58\x58\x88\xb7\x5a\x86\xd3\xf4\xd2\xb4\x74\x87\x9c\x5f\x12\xe3\x9f\xa6\x32\x73\xcf\x6a\x9d\x35\x36\x12\x6e\xc3\x0e\x2e\x3f\x5b\x23\x7b\x66\xc9\xf3\xfc\x8a\x7f\x97\x3c\x4f\x89\x9e\x6b\x2b\x7e\x22\xe4\x8b\xa5\x8c\x74\xc1\xc7\xfe\x41\xa0\x8f\x47\x4b\x9a\x69\x97\x8d\x8b\x74\xd9\x98\x5d\xc4\x91\xc2\xe7\x53\xb7\x2b\x17\x14\x29\x7a\x5a\xfa\x8c\xd6\xd3\x30\xd1\xe1\xe7\x3d\xaf\xd7\xe2\x4c\x9e\x7c\x4e\x2f\x5e\xa7\xff\x5b\x78\xb7\x99\x53\xfb\x4e\x1d\xe7\x1f\xe3\xa6\x82\x7a\xd0\x02\x9e\x01\x24\x0c\x40\x18\xd0\x7c\x78\x4a\xea\x62\xca\x00\xa3\x96\xfa\xc4\xde\x89\x18\xf5\xd9\xec\x61\x5a\x30\xd6\x1a\x41\x81\x77\x94\xfe\x22\xd9\x4b\x22\x30\xac\xb8\xc4\x8c\xd2\x96\xa3\xd3\xd9\x47\x07\x57\x26\xa0\xf2\xb4\xd2\x5c\x76\x02\x39\xd2\x49\x67\x33\xe1\x6d\x6d\x2e\xe4\x6d\x4d\x39\x9c\x65\xe5\xcd\x74\xe5\x2f\xf8\x4c\x17\xfb\x80\x28\x29\xb6\xca\x78\x1c\x45\x44\x45\x24\x62\x37\x51\x56\x94\x52\xae\x40\x4d\xff\x08\x75\xee\x14\x63\x75\x9c\xbc\x64\xa6\x5e\x99\xd4\xe2\x43\xad\x96\x56\xa5\x0e\x5d\xfe\xa0\x32\xc3\x3b\x60\xc8\xf4\xf3\xc6\x0c\x38\x67\xfe\xd6\xab\x56\x2e\x9b\x7d\xcb\xf9\xe4\xa0\x7b\xb0\xcb\x33\xbb\xac\x72\xf0\x84\xce\x29\x67\x5f\x73\xe7\xdc\x66\xf6\xa6\x34\x3e\xf4\x5e\x78\x95\x87\x24\x5d\x7f\xfc\xca\xad\x1d\x35\x6a\x3b\x3d\xfb\xee\xb9\x67\xf2\x12\xf8\xba\x69\xd8\xd6\xbf\x7d\xfc\xda\x2c\x38\x86\x1e\x81\x97\x68\xef\xdd\xa9\xe3\x06\x0b\xd7\x09\x3c\xa0\x0a\x02\xcd\xca\x3d\x31\xa2\x30\xa7\xf8\xf5\x5c\x92\x9e\xb2\x74\x3b\xa1\x3d\xac\xb8\x2a\xa8\xcb\xac\x70\xe6\x68\x54\x3f\x2f\x68\xea\x72\x05\xe7\x05\x89\xca\x05\x24\x79\xaf\x64\xa2\xbb\xb8\x97\x9e\x1c\x6c\x05\x27\x87\x47\xbf\x60\x8a\x13\x98\xbc\x80\x5c\x69\x42\x2d\x16\x4c\xf3\xc8\x23\x24\x59\x0f\x43\x55\x23\x38\x17\x8f\x37\xee\xf5\xdd\x93\x48\x54\x30\x28\x24\x8d\x41\x83\x1c\x26\xbf\xe4\xc6\xbf\x94\x30\x06\x0b\x76\x6e\xa0\x18\x83\x8d\x8d\xf0\x10\xcb\x19\x5d\xee\x60\xc1\xf6\x5c\x6a\x10\xa5\xa4\xd9\xe9\xaf\xa0\xec\xeb\x7e\x51\x4a\xd8\xa4\x52\x3d\x3d\x47\xb2\xa1\xf9\x37\xae\x85\xd6\xa9\xe6\x27\x23\x7e\x3c\x31\x1b\x76\xcd\x39\x34\xff\xc7\x17\x3d\xf2\xc8\x5f\x5f\x3c\x78\xc4\xa7\x76\xce\x63\xba\x30\xf8\xf3\xa7\xad\xf0\xd0\xac\xa9\x1a\xf2\xed\xdc\xf8\xf8\xab\x7b\xee\x99\xb9\x50\x75\xc1\x96\xae\x65\x97\x4d\x1f\xeb\x5e\x96\xcb\x0d\x87\x0d\x2e\x50\x01\x6d\x5a\x6e\xd8\xe5\xae\x88\xc5\x62\xe4\xfc\x41\x34\x19\x4e\xe7\x18\xd1\x98\x43\x85\x85\xc4\x14\x0a\x1c\xa3\xd3\xe6\x91\xf4\x78\x03\xfa\x22\x40\x31\xfe\xfa\xcb\x75\x39\x7d\x3f\x3d\x77\xd4\xcb\x51\xaa\x10\x92\xc6\x0a\xe2\x28\x55\x14\x3b\x4a\xe4\x66\x39\xbe\x26\xca\x2b\x8a\x5d\x24\x90\xb4\xca\x1e\x2a\x6d\x7d\x18\x3b\x46\xfa\xb7\x1c\xe6\xd8\x11\x42\xb6\xb8\xe2\x72\x63\xec\x1d\x26\xed\xa8\x0e\x34\xfd\xac\x22\xa7\x87\x2d\x4e\x3b\x69\xa9\x26\x68\xde\x95\x73\x74\x0e\x4c\xb7\xec\x7b\xed\xa6\xad\xde\x8d\xa9\x3b\xe5\xad\x53\xf7\xae\xad\x9c\x45\x9d\x1b\x75\xe7\x47\x9b\x37\x0d\x5e\x92\x5d\xc9\xec\x9e\x16\xd9\x7e\xed\x47\x3b\xd5\x36\x7d\x6f\xe1\x46\x1b\x82\x7d\x70\x4c\xc1\x33\x70\x4c\x89\xf9\x62\x83\xff\x6c\x95\x47\xde\x8d\xe9\x51\xef\x01\xe7\x69\x8e\x4b\x71\xe1\x07\xf7\x5e\xce\x51\xa1\xf5\x3c\xf3\xc8\xf9\x2c\x08\x56\x9f\xb6\x1a\xa9\xaa\xef\xc8\x28\x89\x13\xbb\x49\xf9\x6c\x1f\x85\x49\xa1\xe2\x7a\x9d\x00\x55\x14\x15\xf0\x19\xa4\x8c\x26\x81\x7f\x58\x85\x52\x8e\x15\xea\x34\x55\x3a\xd3\xe9\x31\xac\xef\xf2\x9c\x2d\x79\x6e\x28\x9a\x0f\xd4\x6a\x97\xf6\xf4\xce\x08\xf6\x2e\x5b\xf2\xbf\xa3\x94\x3b\x32\x49\x53\xb9\xdf\xa4\x95\x4c\x44\x08\x45\x54\x39\x3d\x3e\x68\x45\x49\x3f\x38\x75\xa8\x94\x9b\xa8\x47\x1b\x12\x51\x6d\x1c\x55\x4b\x48\x8c\xf7\x4a\x27\xe6\xab\x97\x4e\x9b\x56\xec\x59\xbd\x74\xfa\x34\x23\xfc\x5d\x51\x05\xd3\x69\xb2\x8e\xc6\xfd\x85\x35\x4c\x0c\xb8\x5a\x75\x69\xf5\x69\x65\x40\x39\x5d\x8d\x97\x3f\x82\xca\x62\x7a\x4c\xae\xcf\xd4\x96\xc6\x2f\xdb\x87\x65\xe8\x91\xba\x9b\xba\x47\x51\xd0\xfc\x02\x2a\x21\x5c\xb3\xa5\x69\xa0\x94\x94\x62\xd0\xf0\xb5\x20\x87\x45\x4c\xa8\x4c\x94\x50\xa0\xa0\xe0\xcb\xe3\x27\x37\x7e\xa0\x1d\x05\x60\x5b\x8c\xed\xdb\x86\x9e\x9b\xbc\xa3\xfe\xe2\x3e\x0d\x28\x7b\x0f\x5c\xd1\xa4\xce\xd0\xfb\x76\x8d\x8b\xf9\x57\x41\x1c\x20\x90\x68\xc3\x3b\x5b\x13\xe5\xd0\x29\x8d\x92\x8e\x5d\x54\x4f\xb5\xa0\x43\xb9\xe3\x7a\x41\x67\xb7\x47\xce\xc9\xa5\x0e\x70\x65\xf0\x41\x9d\x40\xb0\xb9\x7b\x3d\xcd\xf4\xb9\x1b\x1d\xc8\x95\xe6\x14\x8f\x85\x64\xfa\x40\xd2\xe5\xf6\x78\xc9\x12\xa8\xb8\xbc\x7a\x80\xd6\x21\x4a\x49\x0b\xd7\xdc\xa6\xcb\x4f\x1a\xfc\x71\xe2\x0a\x24\x4b\xeb\xea\x9b\xe8\xb1\x5e\x14\xa5\x14\x30\xd6\x0e\x68\xa6\xaa\xd9\x8a\xa1\x2e\xde\x43\x37\x5b\xaf\x5b\x18\x0e\x0b\x65\xfe\x73\x2d\x25\x1e\xb7\xcb\x02\x49\xee\x00\xa3\xc6\x6c\x4b\x41\xc7\xe1\x83\x57\x4c\x8b\x5e\xd8\x7a\xfd\xb3\x3f\xba\xe9\x86\x2b\xd7\x94\xb5\xfc\xa2\x41\xbe\xe8\xfc\x5b\xde\xbe\xfb\x8a\xd9\xad\xb3\x9a\x3b\x37\xec\x49\xa6\x97\x3d\xf9\xb7\xad\xd7\xfc\xb4\xaa\x4d\xb9\xea\xd5\x77\xe1\x87\x59\xf8\x8f\x93\x33\x36\x57\xf6\x3b\xa6\x5e\xfe\xd2\x63\xe8\xd6\xdb\xbe\x7e\xeb\xfc\xb6\x29\x17\xbc\x0f\x9f\x7d\x73\xe7\xf6\x70\xc5\x5d\xd3\xff\xfe\xe1\x61\xf5\x0a\xf5\x37\x5b\x67\x4e\xbd\xe0\x42\x08\x09\xb6\x0b\x00\xe0\xbf\xe4\x3a\x81\x17\xbc\xa5\xe9\x7e\x4a\xb1\x04\x80\x20\x9c\x84\x06\xa3\x83\xf4\xad\xd1\x56\x68\x68\xc9\x20\x48\x69\x69\x8d\x02\xb1\x35\x62\x55\x96\x9c\x97\x99\xbe\xf8\x44\x93\x5e\xca\xe5\x4d\x3b\x10\x14\x10\x93\x3e\x9a\xbe\xea\x9b\x5b\xf4\x36\x65\x17\x21\x19\x35\xa7\x69\x26\xd0\x25\x87\x91\x51\x48\x9a\x8c\x66\x39\x9c\x30\x19\xcd\x05\xd9\x3f\xde\xe0\x22\xfe\x1a\xc3\xbb\x34\x96\x1f\x78\x88\xe1\x5d\xde\x02\xca\x1f\xa8\x18\xa0\x28\x29\x9c\x87\x1c\x81\x14\xd9\x1d\x8f\x23\x07\xcd\xb1\x02\x6f\x2e\xb1\x4c\x2a\xc1\x20\x1b\x2b\x81\xde\xd6\x12\xd8\x16\x63\x80\x31\xc4\x86\x60\x68\xc1\xa1\x31\x16\x3b\x1c\xd2\x82\x06\x34\xf0\x4b\x77\x2f\x6d\x3e\x7c\xb6\x7a\xfc\xfd\xae\x18\xa7\x7e\xf9\x36\xd7\x99\x5d\x35\xe5\x43\xf8\x25\x7c\x5e\x5d\xa0\xce\x5c\x70\x0d\x34\xc0\x96\xaf\xd4\xdb\xb2\xdf\xfc\x8a\x64\x9f\xf1\x7b\x7a\x2b\x00\xdc\x6a\xbe\x0b\x48\x20\x00\x9e\xd5\x3a\x3e\x45\x12\x60\x24\x5d\x9f\x88\x8b\xa5\xcc\x01\xd2\xf1\x69\x66\x33\x29\x08\xc8\x47\x93\x14\x8b\x29\xd0\x94\x51\x18\x1e\x7b\x5b\xa5\xa4\x33\x85\xb4\xed\xd3\x48\xba\x9d\x56\x59\x11\xe3\xbc\xae\xdb\x43\x30\x63\x49\x89\x1f\x87\xf7\x77\x24\x0a\x49\x46\x64\xe5\x30\x92\x85\x24\x2f\x13\x2e\x24\x72\x35\xcb\x5a\x4a\x55\xd2\x7f\x1a\xc0\x77\xd8\xc3\x0c\x6f\x32\x8b\x92\x1c\x28\x24\x7e\xb2\x63\x68\xa8\x7a\x6f\x40\xd6\xe8\x54\xe4\xb6\x20\xdd\xb0\xa9\xae\x08\x57\x0f\x65\x56\xaf\xc5\xbd\x35\x08\x23\xb1\x27\x5a\xe1\xe2\xa0\xba\xa3\xf9\xb6\xf7\x8e\xa9\x4f\xa8\xbf\x52\xdf\xfa\xd8\xb6\xfc\x97\x7f\xd8\x78\xdb\x16\xae\xe5\xbe\x3f\xfd\xe9\xbe\xcc\x91\x64\xe6\x1b\xae\xe5\xe4\xc2\x07\x76\x2d\x9d\x43\xf0\x99\x71\xea\x38\xfb\x25\x5f\x07\xbc\xa0\x1a\xfc\x55\xd3\x18\x09\x18\x33\x28\x18\x21\xe2\x86\x20\xa2\x98\xbc\x05\x60\x24\x20\x20\xad\x9f\xac\x39\x4c\xea\xe7\x6a\x08\x2f\x99\x4f\xc8\x20\x9f\xa0\xb0\x90\xae\x6d\x1c\x6d\xd3\x76\x08\xf9\x58\xed\xfd\xdd\xaf\xe7\xf2\x0d\x1e\x02\x53\x88\xba\x9a\x8c\x07\x23\x11\x12\x92\x7c\x88\xe0\x14\x22\x04\x9a\x3b\xba\x7f\x46\x1c\x20\x33\xfe\x4a\x7e\xcf\x8b\x7f\x2f\x61\x0e\x15\x25\x26\xcc\x9e\x10\xcd\x32\xf3\x26\xb3\xc7\x1b\x2a\xf4\x7e\xf0\x8a\x88\xc4\x38\x2a\x17\x53\x06\xa3\x35\x10\x24\x2f\x7e\x10\x1f\x1c\x1c\x2e\x9a\xde\xd2\x5d\x9f\x22\xc7\x33\x00\x0b\xd3\x15\x33\x2a\x3e\x8e\xa4\x1a\x60\x45\x50\xfd\xef\x8e\x5b\x16\xa1\xfd\x5f\xfd\x5a\xf9\x85\x67\xf6\xe0\xcb\x17\xac\xdc\xb8\x70\xd1\xa2\x1b\x3d\xec\xc1\x5d\x1f\x7e\xb8\x4b\x7d\xc6\xb7\x73\xe3\x81\x5f\xed\xfe\xd9\xdc\x19\xf0\xe5\xec\xad\xb3\x66\x5c\x3d\x77\x6a\x27\xf5\xf5\x21\xe9\x1d\x1b\xcb\xbf\x06\x6a\xc0\x7e\xcd\x0b\x2a\xad\x89\xc5\x28\x23\xb9\xaf\xa0\x77\xcc\xc4\x80\xb0\x62\x67\x33\x4a\xa0\x5c\xa8\x4c\x47\x94\x12\x36\x93\x12\xe4\x72\x93\x3d\x8c\xaa\x63\x84\xfb\x80\xa5\x0c\x8c\xe0\x1d\xa5\xc6\x42\xe2\xbd\x05\xcd\x64\x41\x7a\xbc\xa5\xa7\x72\xc1\x9d\xd7\x7d\xd1\x5b\xc9\x6a\x84\x24\x5b\x83\x9d\xa7\xea\x1a\x9a\x25\xa8\xd6\x5b\x31\x4b\x44\x49\x71\x07\xe3\x71\xc5\x2e\x10\x32\x64\xad\x71\xac\xf5\x0c\xac\xda\xa4\x91\x8c\xb6\x8e\xb5\x36\xff\x0e\x36\x1e\x7e\x7d\xd7\x84\x9f\x6c\x7f\x41\xfd\xaf\x91\xcc\xfc\x60\xf6\x6e\xcb\x33\xfb\x6f\x7f\x62\xd6\x23\x97\xfc\x53\xfd\xc2\xa0\xbe\x4a\x28\x3f\x9e\x85\xc1\x9f\x4e\xde\xd9\x91\xfd\xe3\xfd\x83\xcf\x7f\xf2\x77\x43\xef\xaf\x0a\xc0\x5a\x68\x1c\xd7\x99\x9d\x46\xfc\xf3\x53\xc7\xf9\x5d\x44\x2f\x4d\xe3\xad\x47\x35\x3a\x42\xf9\xec\x28\x75\x45\x6c\xc6\x4c\xca\x29\x95\x1b\x29\x2c\x4e\xe3\xe9\x60\x11\xf3\xb0\xe8\xc1\x0a\x67\x81\x1c\x8e\x9e\x3c\x39\x2d\x2c\x12\x10\xa5\x44\xa0\x34\x18\x8f\xc7\x15\x9b\x53\x67\xb1\xd5\x13\x26\x05\x91\xa5\x32\x58\x28\x36\xda\xdc\x16\x22\x25\x9d\xdf\x0c\x86\x81\xe7\x37\xaf\x6b\x5e\xbe\x60\xd5\x51\x12\x63\x6a\x33\xdc\xbc\x6c\xe2\x0d\x43\x7f\x74\xef\x73\x6f\x1b\x68\x9d\xe7\x1f\xb3\x2d\x3b\x9a\x1f\xbf\x77\x67\xcc\xeb\xb9\x7e\x53\xbf\xd2\x9d\x23\xdf\x7e\x21\xda\xa2\xba\x74\x6e\xc6\x55\x7c\x0a\x58\x81\x08\x1e\xd5\x2a\xdf\x58\xce\x68\xaa\xf6\xc6\x90\x39\xa2\xe0\x83\xa1\x62\x63\x33\xc8\x1e\x4d\xd8\xcc\x84\xb7\x8e\x31\x87\x49\x8f\xa7\xe9\x1d\xc5\xe8\x24\x0b\x3e\x07\xc3\x84\xaa\x51\xef\xf1\xdc\xdf\xfd\x65\x5e\x1a\x46\x23\x17\x49\xbf\xf4\xb5\x3b\xc7\xdf\xe8\xc8\xf1\x37\x3a\x84\x24\xef\xe0\x08\x2b\x1a\xe5\x6f\x74\x90\x25\xdd\x60\xb6\x3b\xf2\xab\x93\xd1\x24\x4a\x8a\xc5\x46\xda\x6b\x14\x28\x50\xda\x6c\xc2\xe6\x48\x1a\x1f\xcc\x30\x58\x57\x5b\x67\x58\xc1\x4e\xdb\xfb\x75\xea\x8a\xab\xee\x38\x70\xd7\x0a\x75\x25\xfc\x0b\x94\xfd\x3e\x76\x20\x9f\xfa\x76\x02\x73\x20\x3b\x0d\xff\x61\x27\x6c\x47\xd3\xae\xa0\xb5\x95\x7b\x00\x60\x9f\x27\xb5\x48\x02\x38\x50\x3c\x6e\xdd\x0a\x52\x36\x33\x25\xa4\x23\x18\x18\x30\x06\x44\x4b\x06\x0f\xdc\x91\x1f\xb8\x98\xd7\x92\x39\xf2\xc5\xc8\xde\x03\x7f\xf1\xeb\x40\x6e\xe0\xce\xdc\xc0\x9d\x42\x92\x77\x92\x81\x3b\xe9\xc0\x9d\xfa\xc0\x9d\x7d\x0f\x1c\xc1\x5e\xc3\x8e\xd5\xd6\x19\x66\x31\x6b\x3f\x7e\x2a\x79\xce\x85\x73\xf7\x2f\x9d\xae\xfe\x09\x5e\x91\x09\x78\x46\x70\x9d\xb4\xac\x17\xff\x61\xae\xbf\xfb\xd0\x8d\x1a\xf7\xf3\x3c\xc2\x79\x14\x80\x2d\x74\xbc\x87\x48\xbb\x77\x31\xef\x51\x8a\x95\xf0\x98\x13\x66\x8b\x5d\x27\x23\x75\x47\xf5\xda\x5f\xd9\x42\x4a\x03\x0a\xd6\x02\xd2\x60\xe8\x20\x05\xcd\x3a\x45\x52\x59\x4f\x6a\x9f\xc7\xbf\xb0\x6a\x9a\x56\xc8\x9e\x46\x56\xd2\xc9\x9c\x7e\xee\xeb\x01\x39\x46\x24\x9f\xce\x88\x84\x37\x29\x56\xd6\xc4\xa1\xcc\x3e\x13\xdd\xb6\x24\xfd\x8e\x1b\xdf\x39\x9a\x3e\xfc\xf5\x4a\xb2\x5e\x7b\xf0\xd7\xa4\x17\x5f\x13\x5e\x5f\x01\x93\x14\xf2\xc4\x41\xc2\x43\xc4\xa2\xe0\x08\x0b\x6b\x30\x5b\xec\x44\x62\xa6\x47\x18\x1f\xca\x7a\x3d\x2c\x72\x92\x06\x14\x4e\x8c\x93\x86\x14\xbc\x68\x23\x93\xa4\xf0\x7e\x52\x3e\xce\x6a\xee\x3f\x59\xaa\xf2\xf0\xc3\x10\x0c\xb2\x30\x58\xd7\x08\xeb\x1c\xb4\x13\x19\xee\x87\x0b\xf7\x7d\x91\x5a\x74\xf5\xa6\xfd\xdb\x56\xaa\xd7\xa7\xe1\x16\x75\xeb\x66\x56\x86\x82\xcb\x69\x66\x2b\x3a\x08\x1d\xd1\x82\xbc\x35\x52\x8b\xdc\x32\x6b\xe6\xf9\xe3\x36\xe5\x62\xa4\xfc\x34\xae\x13\xc8\xc0\x03\xbe\xe9\x3d\x47\xf0\x34\x73\x64\xa4\x73\xe4\xfd\x81\x73\x24\x66\x14\x5f\xcf\xf2\x72\x2d\x4c\x53\x3c\x47\xe9\xaf\x87\xe4\xe6\xc8\xd3\x7b\x8e\x3c\x42\xd2\xec\x29\x9a\x23\x12\xa8\x31\x11\x6b\xf6\x34\xc2\xc3\x3a\xf2\x85\x8e\x06\x03\x29\xe8\x36\x31\xc1\x39\xc5\x38\xe5\x08\xa4\x80\x8b\x88\xd7\x43\xb8\xc5\x30\x87\x58\x18\x63\xe3\x9f\xa6\x66\xc3\x36\x68\xf9\xef\x27\x13\x13\xa6\xcd\xdb\x7f\xe5\x34\xf5\x7f\x7e\x01\x83\xea\x02\xe6\xaa\x3f\x0f\x2c\x2c\x65\xcf\xd9\xfd\x6a\xd8\x81\xdf\xf3\x83\x00\xf0\x1b\x88\x06\x6a\xa5\xbe\x2b\x26\x9d\x82\xc7\x8b\x11\x25\x3d\xd4\xba\x66\xbd\x37\x17\xe3\x12\x34\xff\xb5\x2a\x47\x40\xf9\x38\xc5\xc1\x8b\x6d\x15\x79\x04\xe4\x4e\x1f\x4d\x97\x9d\x6c\xe9\xdd\x6f\x91\x74\x88\x6e\x1f\xad\xfb\xd3\x3f\x11\x5b\xf3\x60\xff\x8a\x2f\xa7\x75\x68\x96\x8a\x78\x1c\x39\x25\x54\x19\x07\x4a\x39\x10\xa5\x24\x6f\x71\x55\x68\xb9\x52\x83\x99\xd4\x3d\xca\xed\x4c\x1b\xdb\x16\x34\xc2\x72\xc6\x2b\x87\xd8\x46\xa8\xe9\xa0\x1a\x8c\x2c\x94\xe1\xe4\xb7\x3b\xaf\xd9\xb9\xf0\x64\x29\x57\x53\xa1\x86\x2f\xbf\x61\x98\x31\x70\xc4\x6f\x3e\xff\x32\x69\xfb\xe1\xbb\xec\x0b\x57\x8d\x79\x1b\xee\x7d\x1f\xee\x84\x2f\xfe\xec\xf6\x09\x06\x98\xd9\xb8\x51\xf5\x9a\x26\x6e\xde\xae\xc6\xe1\xab\x1b\x17\x64\x47\x33\x4f\xce\xdf\xaa\x0e\xe3\x5d\x6a\x27\xec\x02\xcc\xa9\x2d\x00\x70\xfb\x48\x1d\x60\x19\xd8\xab\xe1\xe3\x70\xba\xdc\x04\x1f\x6c\x71\x01\x13\xad\xf4\x70\xe7\x5a\x35\x9c\x30\x8c\xca\xa2\x8a\xc3\x99\x3f\x38\x6a\xc9\xba\xa2\xc8\xd3\xd1\xf4\x03\xff\x74\xf4\x2e\xaa\x4f\xda\x05\xaa\x03\x0b\x73\x9f\x08\x44\x2e\x37\x86\x28\x40\xcb\xb0\x2c\xa5\xc4\x15\xc5\x1b\x23\x8f\x3f\xf7\x8d\x0d\xa4\xd8\x60\x3b\xd1\x90\x59\xfa\xfc\xa0\xcb\xd6\x5e\x74\xcc\xc5\xee\xf5\xaa\x77\x2c\xbb\xda\x35\xf0\x60\xa3\x73\xca\xcc\xa5\x0f\x2d\x99\xb9\xac\x35\x05\x17\x3c\x01\xc3\x70\xd1\x15\xf3\x86\x5a\xe0\xec\x85\x0b\xd5\xfb\x5d\x6b\x77\xaa\x8f\xc1\xc9\x0b\xcf\xcb\x7e\xc9\xd8\xce\xb9\x42\x7d\x8c\x45\xea\xbb\xb0\x5e\xe7\x3c\x30\x62\xbb\xa9\x06\x75\xe0\x18\xc5\x25\xe5\xf0\x78\xcb\xaa\x31\x30\x06\x46\x2f\xae\xa8\x61\x33\x29\x36\x04\x0c\xb4\x03\x1f\xb1\x82\xe2\x37\xe8\x7d\x84\x54\x19\xb9\xda\x92\x41\xd5\x45\x2f\x24\xd1\xfa\xa7\xa6\xe6\xd4\x28\x5d\xea\x7b\x2e\x9a\x9a\xcd\x15\x9a\x1c\xaa\x16\x92\x6c\x35\x76\x20\x42\xd5\xb4\xd3\xc3\xed\x0b\x15\xbd\x57\xe5\x71\xe4\x15\x93\xbc\x81\xf6\xda\x7a\x24\x85\xab\xa1\x70\x9a\x6b\x49\x51\x86\x9f\xb0\xbb\xa3\x1a\x12\xed\x30\x48\x0a\x6f\xca\xf5\xee\x17\x1b\x1b\xa3\x1b\x5b\x48\x6e\x87\x6d\x41\x8c\x2c\xe5\xce\x5f\xfb\xcf\x52\xae\xa6\x4c\x1d\x70\xf9\x75\x43\xcd\xfe\x2e\xaf\x71\xda\xa5\x46\x61\xfb\xe1\xbb\x9c\x0b\x6e\x18\xfd\xf6\x33\x6f\x57\x8d\x0a\xab\xb7\x6c\x66\xb9\x0f\xe0\x76\xd2\xc6\xff\x21\xb6\x3d\xf3\xc4\xcd\x77\x61\xdb\xdb\x70\x25\xb6\xbd\xcb\xb6\xaa\x71\xf8\xe2\xb8\x6b\xfa\x67\xa7\x69\x26\x48\xd7\x3d\xc3\xb9\x5c\x27\xa8\x00\x55\x90\xd5\xd6\x3d\xbb\x43\x76\xf9\x2b\x08\xd8\xb9\x4a\x96\x4a\x53\x26\xc5\x96\x53\xb0\xf1\xb1\x21\x8a\x58\x21\xe5\xe6\xc0\x58\x2d\x43\x13\x2a\x8c\xa0\x16\x00\xee\x82\x61\x45\x76\x90\x75\xd1\x01\xc3\xa8\x2a\xaa\xd8\x85\x5e\xc5\x2d\xf8\xe8\x7f\x93\x56\xe5\x82\xd1\xd6\x38\xfd\x0e\x7e\x8d\xa8\x0d\x17\x70\xa5\xf0\xa8\x42\x48\xb2\x15\x0c\x89\x97\xe2\xa9\x00\x8a\xcd\x49\x62\xd1\x36\xa7\xe4\x2e\xef\xb1\xda\x95\xc4\x91\x0b\xcf\x8a\xbf\x4c\xeb\x80\xe6\x2a\xf1\x99\x54\x54\xcc\x41\x32\x2b\x6e\x32\x2b\x8a\xa1\x52\xcc\xcd\x88\x9c\x9b\x91\x1e\x26\x1e\x92\x5b\xe9\x74\x90\xe5\x50\x3d\x26\xb1\xfb\xa8\xa1\x47\x95\x06\xe7\x94\x19\x57\x3f\xb8\xe8\xa2\x2b\x87\x24\x9e\x7a\xbe\xa1\x45\xfd\x7a\x01\x73\xd5\x13\xb0\x81\xac\x8d\x85\xd6\x7e\xe5\x44\x6c\xed\x13\x96\xa8\x07\xe1\xa2\x0b\xc2\xaa\x2b\x67\xf3\xf0\xd4\x11\x75\x1a\x17\x33\xbc\x09\xce\x06\x0f\x00\x34\x3e\x82\xc6\xc6\x94\xa1\x6c\x06\x8d\x88\x22\x6b\x84\xb4\xcc\xd6\x45\x94\x2a\x3e\x03\xd1\x04\x02\xf4\x60\x39\x83\x06\xd3\x4d\xa5\xd9\x95\x41\xcd\x02\x6a\x20\x47\x02\x39\x83\x84\x88\xd2\x20\x67\x94\x73\x60\x58\x31\x0d\x16\xa5\x11\x56\xce\x6a\x93\x3d\x15\x03\x9b\xda\xce\x1a\x4f\xf2\x8e\x22\xea\x1f\x57\x1a\x9a\x45\x29\x51\x55\x57\x4d\x32\xc7\x43\xc7\x8b\x12\x3a\x8b\x6c\xc0\xa0\x99\x76\x84\x0e\x6c\x22\x25\x98\x49\x5f\x45\x4d\x03\xfe\x5b\x55\x52\x32\x50\x56\x5a\x5d\xac\x56\x5f\xc4\x21\xdb\xda\xd6\x08\xeb\x5a\x62\x1e\xc2\x04\xe0\x75\x13\xcf\x99\xb0\xc9\x6a\x94\xd2\xbc\x03\xba\x5d\xb1\x68\x1b\xa1\x38\x20\x3f\x0e\x55\xd5\x76\x4c\x47\x8f\x3f\xfa\xd0\x8c\x42\x9e\x59\xe5\x69\x29\x32\xf5\xc6\x49\xe3\x2e\x59\x3c\xa8\xa1\xa6\xa6\xa4\x62\xe4\xa4\x6b\x6e\x7a\x39\xb1\x61\x87\xfa\x81\xfa\xeb\x47\x16\xae\x8b\x2f\x5e\x3c\x6e\xd4\xf4\xda\xcb\x96\x4c\x41\xf3\xd7\xee\x42\x17\x5f\x37\xce\xed\x1a\x7b\xc3\xa5\xdd\xdb\xef\xdf\x7c\xf9\xa5\x2b\xd7\x5d\xe3\x0a\x9e\xb3\xca\x3f\xed\x92\x6b\xc6\x0b\xcb\x4d\xcd\x0b\xfc\x7b\x6e\xd0\x78\x69\x5f\xff\x38\x20\xc6\xda\xa6\x1a\x0d\x2e\xeb\x63\x35\xa6\x95\x18\xf3\x3d\xea\x4a\x76\x0b\x3f\x19\x9c\x0d\xee\xc7\x98\x2b\xed\xc6\x0c\x1a\x19\x4d\x8c\x6f\xc7\xbe\xf6\xf8\x31\xe6\x30\xb2\x47\x14\x47\x2f\xec\x87\x3a\x32\x68\x28\x65\xbe\x6a\x76\x66\x90\x88\x81\x6f\xb0\x50\xc4\x2d\x43\x45\x69\x84\x8d\xb7\x3b\x64\x4f\xf9\xc0\xa6\x41\x23\xc7\x8d\xa7\x79\xaa\x44\xff\xd1\x63\xf0\x19\x03\xc3\xae\xd4\x11\xbd\xcc\x76\x0c\xfa\xe8\x38\xb2\x6b\xa0\x3b\x72\xa0\x27\x7c\xe5\x0d\x78\xdd\xad\x92\x12\x25\xa5\x01\x12\xc8\x33\x36\xb7\x33\x6d\xed\x6c\x4b\xb3\xd6\x8b\x4b\x01\xaf\xa5\x78\x33\x7d\xe1\x4d\x92\x5d\x24\x30\xaa\xe1\xed\x84\x55\xb5\xb3\xce\x5a\x7a\xc7\xd9\xc3\xae\xbd\x78\xf0\x1b\x3b\x82\x97\xc3\xf2\xc7\xae\xbb\xbf\xf5\xe6\x1b\xfa\x5f\xb6\xba\x73\xdc\xe8\x8e\xf1\xe1\x48\x5d\x4d\x49\x4d\x47\xfc\xa2\xcb\xd6\xaf\xbe\x70\xce\xfc\x57\xd3\x57\x4d\xae\xbf\x66\xfa\xce\x09\x4d\xd3\x1b\x2e\xbe\xe8\xde\x47\x6e\xbc\x6b\xf7\xc4\xd9\x83\x2b\x1c\xb6\xc0\xc0\x09\xed\x3b\xee\x7e\x6a\xfd\xd8\x5b\xdb\x85\x09\xb7\x06\xa6\xce\xba\x60\x54\xc8\xb1\xc2\x34\x64\x62\xc9\xaa\x8b\x97\x6e\x2d\xe5\x3c\x2b\xa7\x2d\xba\x63\x7a\xa9\x54\x16\x2e\x9b\x60\x71\xf8\xb7\xd7\x71\x1c\xe5\xfa\x7b\x11\xaf\x35\x44\xab\xeb\x53\x5a\x21\x86\x4a\x28\x27\x57\x8a\xb3\xd9\x65\x57\xb5\x37\x96\x2a\xb3\x04\x58\x3b\xf6\x99\x62\x31\xa5\xcc\x94\x51\xfc\xa5\xd1\xa8\x9e\x9e\x29\xe0\xe7\x72\x91\x23\x40\x00\x86\xf5\x5a\x09\x1b\x8d\xd6\x20\xbb\xc6\xe6\xe3\xca\xa5\x68\x86\x4b\x5f\x55\xf6\x41\xd5\xa5\x09\x89\x1f\x6d\xbf\xb7\xfb\x08\x59\x79\xc8\x9a\x43\xd7\x1f\x1e\x05\x84\xa4\x35\x60\x93\xc3\xa8\x44\x48\x3a\x4a\xec\x72\x38\xe9\xc7\x57\x7c\xbf\x14\xdf\x67\x41\x92\xe1\x25\xaa\x35\x73\x98\xe1\xad\x0e\xc9\xed\x2f\x2d\x6a\xf7\xe8\x83\xbf\x4b\x93\x57\x6f\xc5\xdf\x19\x2e\x48\x5c\xac\xaa\xda\x17\x7d\x53\x9f\x99\xe1\xdd\xb8\x55\x38\xf2\xc4\x61\xe7\xa1\x77\xfb\xcf\x7b\x66\x61\x8b\xfa\x9c\xfa\x75\xf5\x25\x47\x66\x39\x7e\xfb\x09\x3b\xf9\xa2\x65\xf0\x6e\x75\xea\xa2\xb1\xeb\x56\xb3\x33\x4f\xee\x4d\xbe\x04\x3f\x56\xed\xea\xd7\xdf\xa9\xa3\xe0\xd3\xbf\xa5\xb1\x87\x4d\xaa\x8b\x5f\x69\x90\x40\x00\xfc\x96\x32\x2a\x20\x0f\x2d\x7b\xb7\x6b\x65\xef\x9c\x18\x8b\x21\x5f\x04\x79\x63\xfa\x71\xa2\x57\x90\xda\x07\xc3\x8a\x57\x20\x79\x44\x2b\x0c\x2b\x36\x81\xd4\x56\x11\x01\x8d\x7c\x10\x6c\x78\xf5\x57\x77\xf4\x81\xa5\x26\x5d\xc0\x21\x1f\xe1\x6f\xf3\xd2\x75\xda\x27\x24\x2d\x3e\x2b\x95\xa7\xb4\x7b\x6d\x72\x38\xe9\xc1\x57\x7c\xdf\x8f\xef\x13\x0c\x75\x92\x61\x86\xb7\xd8\x3d\xfe\x33\xe3\xe7\x85\x31\xd8\x0e\x25\x31\x26\xe8\x4d\x33\x9b\xfc\x57\x1e\x5a\xec\x59\x71\x1d\x6c\x40\xea\x5b\x07\xde\x9c\xf3\xc4\x0e\xf5\xf5\xcf\x2e\x47\xf3\x9e\x7d\x01\xae\x38\x77\x2d\xc3\x65\xbf\x5a\x30\x71\xd5\x8f\xad\xfc\x9d\xdf\xae\x90\xde\x86\xeb\xe0\x85\xea\x32\xb5\xf1\x33\xbb\x5a\x0d\xff\x4b\x7e\x19\x80\xff\xfb\x74\xa7\xd9\x82\x5e\x52\x0f\x28\x07\x17\xf6\xec\x26\x2d\x35\xe6\xc7\xa3\xd5\x9d\xe7\x1b\x4b\x7d\x5a\x63\x69\x25\x0c\x2b\x3e\x07\x61\x9f\x70\x79\x4b\x8b\x06\x54\xea\xed\x59\x1f\x57\xd0\x62\x4a\x06\x44\x09\x99\x68\x97\xe9\xb6\xaf\x77\xa5\xff\xeb\xf0\xaa\x65\xcb\x93\xb5\xd9\xd7\x0d\x55\x4c\x98\x59\xb6\xf8\x5a\x44\x7b\x4d\xff\xf0\xd4\x73\xea\xfe\xc3\xff\xf3\xc4\x9a\x8d\x4f\x3d\x5c\x9a\x1a\xbb\x7a\x2d\x22\xb6\xfc\x24\x00\xfc\x62\xfe\x79\xe0\x03\x97\x50\x96\x9a\x84\x9d\x90\x6e\xc2\x58\x4c\x91\x0c\xb9\xe6\x44\x58\xd0\xa9\x76\xee\x89\x83\x7a\x8c\xdb\xa7\xc7\xb8\x01\x62\x1a\xa1\xc2\xf8\xf4\x3e\x35\xc9\x27\x4a\x09\x83\xc0\xe3\x65\xd5\xae\x71\x83\xc4\x64\x8f\xdb\xd8\xd6\xda\x06\x73\x0b\xa8\x03\x1a\x61\xe8\xc9\x43\x33\x65\x68\x18\x74\x2e\x64\x2e\xb9\xec\xaa\x29\xed\x43\xa2\x2d\xb5\x43\x87\x8f\xc8\x9e\x7c\x99\xef\x3a\x79\xe9\xe3\xcb\xfb\x33\x0f\x3f\xc4\x54\xbe\xba\x7e\xb0\xb8\x4d\xea\x3f\xeb\xc7\xdf\xbd\x4b\xdf\xc1\xd9\x00\x70\x0d\xdc\xb9\xc0\x03\x6e\xd4\x75\x8a\xa0\xfe\xdc\x22\xde\x3b\xbc\xb9\xe7\xd6\x4e\x80\xe9\xc9\x27\xee\xd6\x9f\xdb\x43\x9f\x9b\x4b\x27\x19\xc8\xc9\xe1\x24\x8b\xaf\x09\x06\x72\xc5\xa9\xcf\x04\xc3\x72\x94\x35\xd0\x43\x3e\x68\x83\x13\x3d\xa2\xa4\x18\x78\x2d\xb8\x5e\x0e\xbd\xb1\xd6\x36\xb9\x60\x17\x86\xa1\xd9\x87\x87\x99\x4c\x06\xe3\xc4\x71\xf7\x4d\x58\xb3\xa4\xb9\xbc\xa6\x22\x3c\xb2\x4e\xbd\xfe\x73\xae\x33\xbb\xe7\xa2\xf9\x0f\xbc\xb6\x13\x9e\xb3\x7f\xa9\x65\x9d\x69\xe4\x05\x27\x5f\x07\x2c\x9d\x03\xe3\x72\x92\x07\xed\x0f\x6e\xe9\x7b\x1e\xc2\xfa\x78\x92\x25\x10\xaf\x23\x01\x37\xc9\x45\x90\x5c\xa0\x9b\xb4\xcb\xfc\xc0\xc9\x51\x02\x10\x7b\x5f\x86\x78\x1c\x85\xc4\x84\xb7\xac\x82\xb8\x24\xff\xc2\x84\xb1\x7a\x4e\xb4\x46\xff\x70\xda\x29\xac\x7b\xbe\xf1\xb2\x65\xc3\x36\xc0\x91\x2f\xd4\xcd\xbb\xaa\xf5\xe6\xd3\xcc\xa8\x71\x96\xfb\xee\x9d\xfe\x61\x47\x87\xba\x6f\x79\xd8\xdf\x9a\x24\xef\x15\x99\x5f\x43\x90\xac\x12\xfd\xc0\x4f\xfb\x9e\xe3\xfa\x5c\x56\xc6\x87\x9d\x02\x3f\x85\x04\x2f\x0f\x55\xee\x7c\x7a\xf4\x3f\x34\xef\x4a\xd0\x2f\x4a\x49\x83\x3b\x50\x46\xde\xd0\xef\x37\x82\xde\x38\x9d\xc6\x2c\xa6\x17\xa3\xd4\x97\x95\x18\x6c\x3d\x21\xc2\x6b\xa9\xea\x32\xff\x8f\xc6\xf1\xdc\x0c\x0e\xe4\xd7\x52\xd4\x2f\x4a\xaa\x1d\x73\x6c\xcf\x89\x10\x06\xae\xba\x21\x16\x43\x51\x52\xb9\x0a\x51\x4b\x1f\xf4\xcf\x78\x63\x22\x06\x65\xc9\x28\xad\xc5\xc9\x65\x14\x12\x50\x55\xda\x81\xaa\xf3\x5d\x45\x55\x35\x05\xa9\x41\xd2\x14\x8f\x4f\xae\xa5\xd8\xb7\x0a\x49\x4a\x79\x14\x9b\x95\x95\xd6\x86\x2a\xa1\xa8\x28\x25\x8d\xc0\xe1\xa6\x44\x56\x67\xe0\x92\x86\xa7\xcb\x3c\x9f\x81\x64\x9a\x3d\x78\xda\x2c\xf4\xf7\xf0\x4f\x7f\xf7\x3d\xbd\xb0\xa6\xfb\x35\x9e\x80\x02\x7c\x8d\x19\x0d\x5c\x08\xc2\x89\x10\x06\x35\xa6\xf8\x8c\x99\x9e\xc8\x16\x91\x07\xfc\xe7\x91\x2d\x8f\x8a\x12\x6a\xc6\x67\x08\x8c\xaf\x4f\x14\xa5\x24\x30\xf6\xab\x2f\x24\x36\xeb\x93\x8f\xe0\xb4\xf8\xf6\x4d\x54\xc0\x3c\x7c\xfa\x04\xff\xe9\x38\x0c\x4e\x6e\x3e\x1d\xa8\x0c\xd8\x76\x6a\x1d\x7f\xd0\xd0\x04\xfc\xa0\x11\xcc\x01\xc8\x15\x49\x55\x98\x81\x8d\x0b\xa3\xfa\x48\xca\x48\x3e\xe5\xaa\x72\xdd\xc4\xd3\xac\xc1\x9e\xa6\x9b\x56\xe5\xd6\x94\xe0\x4d\x5f\xb4\xd0\x4d\xbf\xc2\x25\x4a\x49\xd1\x4b\x23\x00\xf5\x62\x12\xd8\x4b\x6a\x48\x68\x49\x4a\x72\x96\xba\x01\x3a\x12\xd5\x6d\xa4\x02\xd7\xeb\x91\x48\xf7\x2f\xed\xfe\xab\x65\xda\x5c\x1e\x2f\x71\xd5\x5b\x25\x51\xa8\xa3\x5a\xdb\xcc\xb6\x07\x61\x7d\xda\x3d\x3e\x3e\xa4\x9d\x79\xf2\xd9\xdd\xea\x3b\xcf\x7b\x3a\x5b\x87\xb4\x33\x87\x7e\xf9\xfc\xb5\x8b\x9b\x2e\x6a\x1a\x61\x7e\xf6\xf8\x1f\x1b\xe6\x44\x47\x9a\x9e\xf9\x8c\x69\xf9\x2b\xbc\xe3\xdb\xb2\xc1\xd1\xb3\x06\x0d\x54\xdf\xff\x73\xb7\x7a\xcd\x97\xde\xa1\xb1\xf1\xad\xfd\x61\xdd\x27\x7b\x7e\x5d\x33\x31\x12\x8e\xc0\xfb\xa0\x0f\x0e\xbd\x60\x52\xe3\x80\x26\x75\x21\xe1\x9d\xd8\xc2\x8d\xe5\xba\x80\x1f\x0c\xcc\x8f\xdd\xce\x85\x51\x7f\x32\x76\x3b\x1e\x7b\x53\x61\x45\x72\x8d\x96\x13\x8d\x9e\x79\xec\xfd\xc5\xa4\xbd\x04\xe4\xc7\xde\xaf\x21\x67\x05\xda\xd8\x49\xe7\xb3\x41\x1b\x3b\x6d\x7e\xd6\xc6\xde\xd2\x5c\x4b\x07\xef\x60\xe6\xac\x78\x6d\x83\x38\xba\x35\x1a\x67\x6e\xbf\xe7\x8a\x57\x6e\x11\xc7\xc4\x62\x83\xb8\xcd\x0f\x1c\x9e\x78\x76\xc3\xc4\x50\xcc\xb6\x72\xc3\xe8\x31\xfd\x27\x85\x5a\xad\x13\x6e\x1c\x0b\xf7\x3f\x08\xeb\x9f\xaa\x88\x37\xc4\x63\xc1\xb7\xf6\x3f\xaa\xbe\xff\x5c\xe5\x90\x81\x43\xa2\xfe\x0f\xf7\x5f\xb1\x49\x1e\x5b\xe3\x1b\x00\x6b\x7f\x35\x73\xbd\xf7\xac\xaa\x8a\xc0\xdd\xc7\x00\x00\x1c\xad\x5f\x30\x6d\x02\x51\x30\x1a\x4c\x05\xe7\x83\xdf\x83\xc4\x40\xec\x39\x87\x69\x12\xce\xa3\x55\x31\x84\x68\x15\x43\x59\x14\x8d\x8a\x28\x2d\x7c\x26\x39\xb8\x65\x94\x29\xac\x0c\xe3\x33\x28\x16\x85\x68\x5a\xe1\xa2\x15\x83\x61\x65\xb4\x27\x83\x46\x0b\x4a\x07\x0c\xa7\xa6\x78\xc0\x5c\x2e\x9c\xe8\x98\x82\x4f\x93\x1d\x63\xcc\xe1\x24\xe8\x98\x68\x0e\xa3\x29\xd4\x71\xac\x75\x65\x94\x0b\x60\x58\x89\x61\x47\xcb\xc2\x09\x0d\x03\x31\x5e\xa3\x45\x45\x36\xc6\xe3\xa8\x43\x4a\x79\xc2\x2d\xa3\x0c\xf8\xde\x14\x31\x51\x39\x22\x88\x37\xc2\x12\x29\x55\x16\x1a\x34\x64\x38\xad\x6e\x10\x48\x75\x83\x5c\x59\xab\x57\x37\x04\xe3\x71\x34\x4c\x4a\x8c\x99\x38\x05\xff\xf2\x60\x11\x9d\xdb\xbb\xda\x41\xc0\x7e\x5a\x91\x76\x7b\x61\x9d\x03\x2d\x73\x80\xad\xb1\x68\x39\x33\x04\x1a\x43\x55\x75\xf8\xaf\x19\xe5\xb6\x5c\x7d\x32\xf9\x5d\x76\x9b\x02\x85\x23\xb4\x10\xe2\x86\xe7\x57\x7d\x73\xde\x81\xf6\xa6\x9f\x4e\xf9\xe9\xef\xb7\xe4\x8b\x20\x56\x3c\xf5\xd5\xae\x03\x1b\xcf\x79\x60\xce\x73\xbf\x65\x3e\x19\xf8\x3f\xc3\xae\xb8\x62\xe9\x48\x5f\x89\x7c\xc3\xea\x31\xd3\xfb\xcd\x0d\xb4\x38\xaf\x71\x3b\x83\x65\xb3\xe3\xa3\x15\xf8\xe1\x77\xb0\x3b\x3b\x63\x73\x65\xbf\x8f\xd5\xcb\xd3\xea\xde\xf1\xed\xf1\x89\x9f\xc2\xe4\x6f\xf4\xea\x88\x27\xd5\xcb\xd5\xdf\x6d\x9c\xd5\xbf\x19\x72\x86\xe9\x5f\x54\xf7\xaf\x5e\x1b\xaf\x28\x59\xa6\x3e\x37\x61\xc0\x40\x51\x30\xd8\x2a\xfc\xe3\x47\xc7\x7f\xc6\x9c\xa5\xf5\xd7\xf0\x4f\x1b\x4d\xa0\x01\x8c\x00\xe7\x81\xdf\x81\x44\x58\x2b\x62\x15\x4c\xa4\x05\x18\x2f\x90\xa8\x32\xa6\x98\x4d\x19\x54\x12\x45\xed\x11\xa5\x89\xcf\x24\x5b\x9b\xda\x4d\x61\x25\xce\x67\x50\x63\x14\xa2\xc9\x94\xfb\xc2\x42\x8e\x92\x8d\x30\xac\x8c\xf0\x64\xd0\x08\x41\x19\x4d\x02\xaf\xa9\x49\x74\x52\x47\x4f\xb2\x84\x93\x60\xf4\x78\x73\x18\x4d\xa2\x7e\x73\xc8\x92\x51\xa6\xc0\xb0\xd2\x68\xc7\xaf\x85\x59\x08\xe3\x49\x19\x21\x26\x8c\x72\x3d\x9e\x8c\xd1\xd2\x21\xb7\xa1\xae\xa9\x7d\x24\xbe\x3d\x49\x54\x4a\x87\x92\xfe\xf3\x64\x49\x65\xf3\x10\x32\x9b\x66\x6d\x36\x4b\x43\xfa\x6c\x96\xc5\xe3\x28\x2e\x25\x46\x8e\x9f\x84\xff\x81\x56\x11\x4d\xc8\x13\xda\x15\x51\x6e\x78\x62\x51\x49\x6c\xee\xd1\xd6\x46\x5e\x22\x88\x6f\xf4\x9e\x49\xbd\xd0\xdc\xe3\x76\x19\xe6\xac\x7b\x7f\xeb\x95\x97\x8e\xea\x18\x77\xe1\xed\xe7\x2e\x5c\x14\xb9\xf4\xfc\x4b\x6f\xd8\xfd\xe4\x86\x09\xd3\xc3\x0d\x3f\x1e\x7e\xfb\x8e\x5b\xfe\xfa\xc0\x86\x39\x8b\xd7\xff\xfc\x69\x86\xf3\x6f\x5d\xd4\xbe\x78\xd1\x92\x91\xfe\x32\x61\xd5\xea\x31\xd3\xeb\x2f\x2d\x1d\x22\xac\xa8\xab\xf5\xc6\x1a\x86\x8c\xfe\x11\xbc\xf5\x75\x78\xd1\xa3\x43\xb6\x46\xb6\xa8\xdd\x3b\xd6\xaf\x0e\xb6\x4c\x83\x17\x41\xcb\x6f\x1b\x36\xfb\xab\x9e\x4c\x7d\xa6\xee\x7a\x7c\xf8\xf0\x77\xf9\xa9\x37\xae\xa8\xee\x5f\xbd\x86\x4c\x5f\x7a\x42\x7d\xac\xc4\x29\x96\xc9\xd5\xfd\xc6\xc6\xcf\xbe\x26\xa7\xb3\x6f\x5c\x6c\x64\x40\x1c\x74\x80\x37\xbf\xa7\xaa\x08\x8d\x8d\xa0\x91\x31\x65\x08\x97\x41\x43\x84\x54\x87\x19\xd4\x73\x61\x65\xf8\x59\xd1\x28\x44\xe3\xbf\xa7\xdc\xa8\xf3\xff\xb4\xdc\xa8\xcb\xc2\x35\xb7\x0d\x1e\x32\x8e\x56\x1c\x25\x8d\x06\xff\x58\x5a\xe2\x7f\xa8\xb4\xae\xbe\x69\xe8\x98\xde\x45\x47\xca\x90\xb1\xa2\xa4\x0c\x6e\xff\xf7\xca\x8e\x60\x5b\xd0\xe5\x84\xa1\xba\x90\x91\xfc\xf9\xd7\xab\x90\x98\x55\x06\xb6\x9d\xbf\x36\x18\x38\xda\x11\x2c\xf9\xc5\xb8\xd0\xbf\x5a\x95\xc4\x7f\x1b\xb0\x39\x1f\x9b\x3f\x7f\xfe\x7c\x32\x4f\xa4\x3e\x89\x3f\x00\xbc\xa0\x16\xc2\xbe\x2b\x94\x50\x75\x04\x55\xc4\x14\x3f\x97\x41\x7e\x21\x55\x4b\xa7\xa7\x2c\x88\xa7\xa7\xee\x7b\x4a\x97\xfa\xfd\xbf\x57\xba\x94\xe2\x3c\x3e\x7f\x35\x4d\x07\x25\x65\x77\x15\x79\x17\x1d\x52\x42\x2a\x09\x92\x43\x49\xae\x8a\x49\xf1\x57\x8b\x92\xe2\x2b\x3d\x53\x3d\x93\x5c\x3c\x6b\x67\x28\x6f\x7a\xba\x78\x76\xce\x5c\xed\xc4\xdf\x59\x30\x17\x10\xfb\xdc\x9a\x7e\xc6\x55\x20\x27\x95\x81\x5c\x11\x24\xc7\x0a\x04\x33\xf0\x62\x46\x22\xf1\x72\xbe\x01\x41\xd3\xaa\x70\x14\xc6\xdc\x81\x22\xb9\xb1\xd9\xe3\x2b\x41\x45\xa6\xc4\x45\x40\x31\xbb\x08\xd1\xa6\x70\x66\xb1\x0d\x36\x24\xd7\x82\x6d\xbf\x81\x73\x3f\x26\x62\xec\x3f\x57\xbf\xda\xf5\xcc\x43\x93\x3b\x36\xfd\x62\xfe\x1f\x4f\x01\xc6\x0f\x59\x98\xfe\xdb\xe4\x9d\x1d\x2f\xaa\x77\xbe\xf3\x8b\xb7\xca\xb2\x0b\xe0\x1f\x6c\xb0\x8e\x8c\x63\x8e\xea\x22\x3d\x42\x1e\xb0\x02\x24\x5c\xa4\x1b\xd0\x94\xef\x11\x42\x72\x04\x49\x31\xfd\x10\x5d\x10\xe8\x93\xf2\xe7\xe9\xf6\x9d\xdd\x8f\xea\x91\x3c\x57\xda\x81\x24\x01\x89\x69\x80\xc4\x46\xa8\x88\x2e\x6d\x38\x92\x2c\x4a\xc8\x89\x87\xe3\xd4\xc8\xb2\xfa\x6a\x25\x22\x61\x53\xca\x1c\x30\x67\x27\x84\x0f\x91\x26\xa2\xa5\xa9\xb9\xff\xb8\x6c\xd6\xe6\xd4\xe5\x47\x7f\x0b\x57\xff\x1a\xce\x3a\xd4\xb2\xa3\x79\x97\xda\xbd\xfb\x9b\x48\x76\x26\xfc\x3d\xf3\x26\x80\x60\xf9\xa9\x6f\xb9\x75\xbc\x05\xc8\x40\xa4\x15\x56\x10\xb9\x22\x78\x05\x22\xd2\x1f\xbc\x5c\xd3\xc6\xcb\x5e\x96\x37\xd6\x90\x3f\x75\xf2\xf2\x31\xb0\xe2\x65\xf5\xe3\x0e\x58\x7a\x78\xcd\x61\x58\xd1\xa9\xfe\xf9\x55\x58\xd6\xa1\x7e\x9c\x5a\x9b\x62\x42\xab\xf6\xc2\x19\x7b\x57\xef\x85\xf1\xf1\xea\x0b\x7b\x57\xed\x55\xf7\xed\x5b\xb5\x57\x7d\xb9\x13\x0e\x21\xf1\x06\x78\x2e\x77\x27\x37\x91\x3f\x02\x9c\x60\x10\x40\xd6\x88\xc2\x70\x99\x84\x95\xd0\xf5\x5b\xed\xe6\x70\x82\xb1\xe2\x0d\x8a\xe1\xcd\x61\xc2\x71\xcf\xbe\xa3\x98\xdc\x84\xc2\x5e\x31\xb1\xa4\xca\x05\x0c\x6c\x82\xcd\xb1\xa0\x56\x0e\x1e\x24\xbb\xc5\xb9\xb7\xc2\x84\x38\x23\xdc\xb0\x51\x9d\x24\x5f\xd8\x7f\x00\xf7\xd1\xf5\xb3\xfa\x85\x56\x71\x97\x44\x01\x84\xcb\xb9\x8f\xb9\x79\xfc\xbb\xc0\x0b\x9e\x04\x48\xc2\xe6\xa5\x18\xf9\x0c\x32\x44\x93\xd0\x28\x99\xc2\x88\x8d\x29\x5e\x3e\xa3\xd8\x3c\xf8\x15\xf7\x45\x90\xe3\x1d\xc5\xe2\xc9\x19\x9b\x98\x78\x6e\x0d\xad\x9e\x6b\x44\x72\x23\x62\x05\xc5\x53\x7b\x02\xc9\x82\x62\xa8\x3d\x71\x54\xb6\x3e\xf7\x67\x52\xf9\xcd\x0a\x49\x8e\x35\xc8\xe1\x24\x8f\xaf\xc8\x23\x24\x5d\x1e\x59\x0e\x27\xdd\xf8\x9a\xe0\xd8\xc2\xc2\x78\x3e\x9e\x70\x7b\x64\xfc\xc9\x15\x07\x49\x8e\xd7\x84\xbf\x0f\xb3\x1c\x6f\x90\x5d\x45\x89\x6f\x08\x14\xc9\xab\x95\xf6\xc0\xb6\x58\x54\xe7\x08\x0b\x51\x56\x58\x07\x13\x82\xcb\x7d\xd6\xf3\xd6\x5f\xbf\xbc\xfd\xd2\xa5\x86\xb5\x4c\x73\xbf\xf0\xd2\x9b\x76\x4c\xe6\x3e\x5e\x5b\x1d\xae\x9e\x35\xad\xb4\xca\xe7\xae\xae\xaa\x09\xd7\x60\xdc\x99\xeb\xb9\x77\xd9\x45\x86\x18\x10\x40\x2b\x40\xe6\x88\xc2\xe2\x73\xbf\x88\xcd\x32\x65\xa5\xbe\x81\x15\x60\xe8\xad\x06\x33\x9e\x0b\x87\x39\xac\x48\xa4\x43\xdd\xac\xc5\x33\xa1\xbe\xf3\xe2\x85\xdf\xeb\x6e\x84\xcc\xf5\x63\x87\x87\x1b\xaa\xdc\xe1\x6b\xaf\xbf\x8e\xef\x1a\x32\xaa\x7f\x55\x59\x89\xc9\x11\x68\x6a\xe8\xac\x24\xfb\x22\x64\xee\xe4\xde\x65\xd7\x90\xff\x67\x13\x40\x20\x92\xb2\x6a\xe7\x12\x11\x4f\x6c\xca\xe1\x01\x6b\xb9\x70\x82\x25\xca\x96\x2c\xc0\x7e\x26\x6b\xd2\xfe\xb7\x03\x9b\x60\x4b\x8f\x0d\x9f\xb9\x73\x79\x9d\xb7\x3a\xda\x38\x64\xf4\x4a\xee\xdd\x09\xfd\xa2\x01\x87\xc5\x5f\x59\x5d\x3b\x3a\x7e\xce\x72\x00\xe0\xa9\x15\x06\x17\x73\xbd\xd1\x01\x24\x80\x00\x65\x53\xc2\x43\x44\x5c\x34\x69\x62\x05\x13\x61\xf6\xb6\xf2\x19\x05\xd8\xf0\x3c\xcb\xe4\x75\x94\x3c\x19\x3c\xc7\x7f\x07\xcf\x99\x74\x1d\x4c\x23\xd1\xc1\xe4\x6a\x4e\xe0\x85\xdd\x56\x73\xe2\xe8\x5f\x3b\x9f\x5f\x46\xe6\x98\x13\x92\x3c\x67\x94\xc3\x49\x03\xbe\x22\xa7\x90\xb4\x3b\x6d\x84\x5e\xc9\x26\x87\x13\x3c\x67\x2c\x98\x63\x43\x3c\xe1\x70\xda\xf0\x27\x7b\x1c\x24\x79\x03\xad\x4b\x82\x87\x39\xde\x60\xb4\xd9\x1d\xce\xa2\x39\x1e\xd8\xc4\x16\x78\x3b\x8d\x4c\xa8\xca\xb8\xb1\x64\xc3\xe2\xf6\xc5\x57\xdd\x38\x51\x2c\x33\x4d\xdf\x78\xf5\xc5\xfd\xaf\xf0\x19\x5c\xeb\x57\xd4\x0c\xa8\x59\x13\xea\x1f\x5a\x01\x00\x30\x81\x7a\xf5\x59\xe3\xb3\xfc\x16\x72\xa6\xae\x07\x6d\x60\x34\x98\x0c\x66\x83\xc5\x70\x25\x40\xcd\x11\xa5\x81\xcb\x24\x9a\x1b\x08\x4f\x4a\x7f\x73\x18\x0d\x8c\x62\xd3\x9e\x14\x53\x44\x2e\x83\x3a\xa2\x09\x9f\x88\x7f\xe4\x73\x98\xc3\x09\xd7\x98\xb3\xa3\xd1\x28\xb2\x44\xd0\xa2\x98\xc2\x72\x19\x74\x59\x34\x61\x21\xca\x13\x16\x60\x0e\x27\x0c\x97\xce\xc3\x3f\xae\x8d\xa0\x8b\x63\x4a\x05\x97\x41\xd3\xa2\x89\xda\x0a\xfc\xe3\xda\x52\x73\x38\x51\x35\xe5\x42\xfc\xe3\x91\x11\x65\x30\x97\x49\x8c\x1c\x8c\x7f\x30\x72\x90\x39\x8c\x86\x45\x21\x5a\x42\xac\xcb\xee\x01\x22\x17\xc6\xeb\x9e\x03\x86\x51\x69\x34\x15\xa0\x37\xea\xa3\x28\x40\x3a\x11\x53\x06\x7a\x83\x0a\xc1\xa3\x50\x34\xe5\xa2\x37\xaa\xa2\xc8\x25\x90\xe8\xd3\xa0\x68\xaa\x8d\xde\x1b\x1d\x45\x6d\x84\x4a\x17\xb5\x47\x53\x03\xe9\xbd\x61\x51\x34\x50\x50\xc6\xc0\x30\x9a\x12\x4d\x4d\xa6\xf7\x66\x47\xd1\x64\x41\xb9\x14\x86\x53\x8b\xe9\x8d\xc5\x82\x32\x01\x86\xd1\x8c\x68\xea\x6c\x7a\xe3\xc2\x28\x3a\x5b\x50\xe6\xc3\x70\x6a\x1e\xb9\xa1\x2c\x25\x82\xd1\xa2\xa4\x58\x48\x9b\xae\x11\x1f\x0c\x7d\x15\xf8\x90\xa2\x34\xb5\x89\x92\xd2\x30\x38\x1e\x57\x16\x5f\x2a\x4a\xc9\x49\xd3\x2e\xee\xc0\xb7\xcf\x9e\x20\x4a\xca\x65\x8b\x48\x6d\x99\x4c\x0f\x88\x21\xe2\x25\x19\x8b\xbf\xb1\x45\xdf\x60\xf1\xcf\x5a\x4f\xff\xa3\xe2\x7f\xb2\xf0\x17\xeb\xf9\xcb\xe7\xcf\x5c\x6e\x38\x97\x1f\x3a\x7a\x62\x94\x9f\x57\xf4\x6d\x42\xd1\x37\xd8\xcd\xcf\xc5\x5f\x27\xf1\x43\xc7\x4c\x8c\xf2\x67\x5b\x5f\xbc\xf8\x6a\xa3\xf6\x05\x7e\x73\x86\xbf\xb8\xdc\xfa\x92\xfe\x25\xc6\xc3\xd7\x66\x2c\x98\x37\xb3\x21\x5c\xd7\xa4\xda\x66\x2c\x9c\x77\x31\xfe\xc4\xbe\xaf\x7f\xfa\xce\x79\xe1\xc2\x79\x33\x07\x0c\xa8\x8f\x18\x1c\xcf\x5d\x7e\x31\xfe\xf0\x9d\xa9\xf7\xaf\xa9\xfe\xe7\x16\xcc\x18\x30\xa0\xdf\x40\x6a\xbf\x6b\x8c\xab\xf9\xb7\x88\xbe\xb3\x07\x94\x83\x5a\xd0\x00\x5a\xc0\x30\xb0\x08\xa0\xd6\x88\x32\xc8\x98\x41\x30\x4a\x84\x84\xd1\xd0\x18\xe5\xa0\x68\x8f\x20\xef\x3b\xa8\x22\x9a\x2a\xa7\x13\x58\x2e\x28\x55\x30\x9c\x0a\xd1\x6f\x81\xa8\x32\x1c\x86\x95\x72\xec\xe9\xf8\x6b\xe3\x71\x25\x54\x25\x4a\x4a\x49\x0d\x76\x7f\x5a\x79\x4a\x35\xc1\x8a\x0a\x18\x12\x8f\xa3\x41\x12\x6a\xc3\x5b\x67\x8b\xc7\xeb\x36\x36\x42\xb9\xb5\xcd\xeb\x32\x18\xe5\x36\x8f\xd7\x58\xd5\x08\x61\x6b\x5b\xcc\xeb\x80\x18\xfe\xb6\x98\xc1\x18\xe2\x9b\x5b\xdb\xbc\x06\x23\xdb\xe6\x2d\x87\x5e\x63\xad\xdc\xd2\x56\x0e\xbd\xee\xda\xfa\x63\x6b\x1d\xa3\x9e\xb9\xe6\xa9\x2b\x2e\xfb\xc5\x46\xf9\xac\x55\x13\xe6\x88\x83\xce\x65\xe4\x16\x71\xa3\x55\x1c\x5b\x7d\xa9\x3c\xbe\xe2\xd2\x66\x69\x23\x7c\xf2\xe0\xce\x31\x9f\x0e\x8f\xcf\x96\x6b\x67\x78\xcf\xda\xbc\xd5\x31\xee\x95\x91\xc7\x98\x96\x4b\xe9\xaf\x65\x8f\xac\x98\x34\xdb\x3b\x2b\xc6\x37\x8c\x7d\xe9\xb2\x39\x17\xa4\x4f\x7c\x47\xfe\xcd\x49\x06\x6e\xdc\x2b\x23\xff\xeb\xa6\xd5\xde\x8b\x06\x8d\xde\xd9\x78\xf2\xe9\x39\xdc\xa8\xe7\x86\x8d\xfd\x00\x7e\xb5\xd1\x8a\xff\xdd\x16\x52\x6b\xa2\xae\x21\x7a\x9d\x32\xa8\x02\x5f\x69\x55\xa9\x8e\x42\xb5\xce\x60\x44\x09\xf0\x99\x44\x20\x88\xdf\xc9\x40\xb9\x39\x8c\x3c\xb4\xdc\x21\xaf\xd6\x89\x3d\x2b\xbf\x83\x74\x04\x97\xc3\xb0\x52\xe1\xec\xcd\xde\x51\x2c\xd1\xa9\x09\xc3\x50\xb1\x42\x21\xad\x98\x4b\x4e\xf0\x7d\xab\x74\x3a\x84\xa4\xd3\x21\xf4\x52\xe9\x74\x3a\x04\xaa\x52\xc8\x9b\x35\x15\x61\x78\x18\xb0\xbc\xc9\xec\x28\x12\x15\x86\x4a\xb9\x5f\x94\x92\x56\xbb\x2d\x88\x3d\xd9\x0a\x31\x61\x14\xa5\xb8\x4e\xcc\xaa\x58\xc4\x78\x91\x74\x67\x0c\x86\xe4\xbe\xe4\x3b\x2b\x0b\xd5\x3b\x3f\x3f\x72\x0a\xbc\xfd\x8f\x07\x35\x09\xcf\x90\xe5\x3e\xc3\xc1\x25\x57\x93\x9e\x1a\xf5\xa9\xbc\x84\xe7\xe7\xd9\xf7\xe1\x5a\x5d\xc6\xb3\xbc\xa6\xca\xbf\xe6\x82\xcb\xd4\x17\x49\x3f\xcd\x3a\x6e\x95\xc1\x05\xca\x40\x03\xd8\xa3\xf1\x84\x58\x8c\x19\x1a\x4e\x67\x29\x4f\x08\x0a\x47\x94\x1a\x3e\x83\x2a\x23\xa8\x5f\x0c\xa2\xc6\xbe\x33\x96\x18\xea\x90\x23\x83\x42\x1a\x2b\x95\x48\x64\xe3\xea\x2b\xdf\x11\x95\x7e\xce\x0c\xea\x17\x51\xea\x9d\x19\xd2\x99\x4a\x59\xa6\x02\xf1\xb8\xe2\x0c\x89\xd2\x08\xb3\x88\x1d\x04\xaf\xaf\x26\xac\x95\x43\x48\x39\xce\x2e\x51\x22\xac\x21\x4a\x65\x0d\x29\xe9\xe9\x8b\x64\x2a\xc6\x86\xe4\x33\x53\x27\x8f\xe9\xa4\x1d\x35\xaf\x3c\xf6\x49\xea\xd5\x3b\xbc\xb6\x69\x87\xe6\xdd\x7c\x07\x2c\xb5\xfe\x34\xdf\x7d\xf4\x70\xae\xbf\x66\xdc\x58\x4a\x13\x37\x31\xfb\x57\xb8\xfa\xd5\x6b\x16\x6e\xe5\xa7\xd4\x94\x6b\x0d\x48\x3f\xd2\xf4\x5f\xbe\x25\xba\xc8\x25\xe0\x19\x8d\x2d\x0e\xc4\x14\xc9\x94\xc9\xa9\xac\x59\x4b\x44\xde\x1e\x56\xac\x6c\x26\xc5\x32\xe4\x23\xed\x71\xcc\xe9\xd4\x05\x68\x17\x32\x6d\x69\xf4\xc0\xb0\xe2\x90\xf3\x1d\xd2\x7b\xbb\x3f\xd2\x9b\x43\x01\x69\x43\x96\xd2\x3d\xdb\x16\x25\x21\x69\x94\x48\xdb\x22\xb9\x5a\xc9\xb5\x44\x22\x5c\x87\x80\xf4\x24\x4a\x25\x85\x85\x86\x1e\x03\x2d\x76\x72\x50\xee\x95\x12\x49\x94\x90\x83\xd4\xd6\x14\x34\x22\x6a\x6a\x32\xba\x5c\xe0\x5f\xef\x09\xdd\x53\xd7\x55\x0b\xeb\x43\xea\xbb\x83\x6f\x81\x5d\xea\x93\xea\xab\x53\x97\xbf\xfa\xfb\x5b\x37\xde\xc9\xcd\xb9\x3f\x95\xba\x5f\xfd\x54\xdd\xfe\xc9\x89\xdd\xb4\xa1\x81\x01\xab\x4f\x1d\x67\x0f\x1a\x5c\xc0\x0d\x82\xe0\x33\xed\xc4\xe0\x33\x66\x50\x79\x84\x54\x8b\x73\x11\x85\xb5\xc5\x62\x0a\xcf\x67\x14\x83\x39\x1a\x45\xc6\x08\x32\xe5\x9a\xf7\x3c\x22\x09\x08\x18\xb1\x3b\x6c\xc9\x20\x13\x2d\x25\x10\x85\xbc\xdc\xdc\x03\xdd\xbf\xcd\xb5\xb0\x31\xa4\x85\xad\x32\xcd\x23\x46\x48\xb2\x0c\x71\x5e\xf0\x15\x55\x0a\x49\x73\xa5\x49\x0e\x27\x6d\xf8\xaa\xcb\x98\x59\x93\x76\xfc\x35\x61\xaf\x34\x15\x91\x2b\xd9\x2b\x69\x0f\x03\x6b\x30\xdb\xc8\xe7\x7c\x85\x22\x61\x5d\xe4\xe3\x71\xc5\x64\x14\xa5\x84\xcb\x57\x8e\x4f\x59\x01\x51\xb1\x3a\xe3\x71\x44\xdd\x75\x42\x12\x8b\x44\x2d\x21\x1e\x2a\xe8\x6a\xa8\x14\x5d\x86\x50\xa5\x5c\xd0\x47\xbb\xda\xbf\x65\x47\xd9\x8e\x96\x54\x0b\xb4\x94\xa9\x5f\xaf\xbc\x65\x11\x9c\xfe\xc5\x1b\xea\xf6\x83\xaf\xaf\xdc\xb8\x70\xd1\x95\xd7\x7b\x61\xfd\xf4\x79\x8c\x72\xeb\x17\x5f\xdc\x9a\x7d\xdb\xa7\x1e\x7b\xe4\x75\x78\xf6\x11\xd2\xcb\xb0\x08\x14\xe9\x49\x3a\x40\x00\x6c\xeb\xb1\x26\x06\x4c\x99\x94\xdd\x49\x6a\xb3\xed\xa6\x9e\xcc\xc4\x5e\x4d\x4f\xb2\xac\x4f\x3d\x49\x87\x80\x02\xe9\xa4\xdd\x11\x90\xc3\x49\x27\xbe\xb2\x49\x68\x77\x06\x74\xab\xf1\x62\x9f\xc1\x68\x8e\x93\x16\x77\x6c\x37\x76\x0c\x8b\xc9\x4c\xcb\xe8\x8c\x16\x0c\x49\xa1\xde\xa4\x60\xf4\x1a\xeb\x0c\x61\xc8\xca\xb1\x68\x5b\x5d\x9b\xb7\x58\x77\xb2\x73\xfd\xe4\xab\x37\xac\xbb\x7e\xd7\x9a\x99\xc3\x46\xae\xeb\xb8\x55\x53\x9f\x54\x7f\xf9\xa3\x7b\x46\xec\xf3\x66\x5f\x64\xde\x76\x6c\x1e\x7e\xf7\x85\xcf\xdc\x70\x65\x01\xd7\xaf\x1f\xf4\x07\x6b\x34\x35\x91\xb2\x22\xae\xdf\x3a\x8d\xeb\x97\x26\x3d\xfd\x22\x59\xeb\x0b\xa8\x67\x6b\x34\xd2\xa6\x01\x30\xac\x40\x3f\xe5\x5f\x22\x5c\xbf\x25\x78\x26\x6b\xa4\x2e\xa3\xdd\x21\x95\x69\xea\x22\x12\x1e\x97\x03\x4f\x6d\x99\x88\xec\x71\x54\x27\xa5\x38\x8b\xdb\xd3\x07\xf9\x2f\x19\x21\x65\xae\xd3\x18\x80\xc9\x40\x7b\xb3\x00\xff\x6c\xc3\xf8\xf5\x13\x06\x37\x5e\xbc\x75\x80\xc5\x66\x9f\xfb\xfc\x92\xcb\x02\x25\x1d\xeb\xc6\x9e\x7f\xe9\xc1\x19\xcf\x5c\x9b\xa3\x03\xfe\x40\xbd\x65\xe6\xf6\x51\xf7\xd9\x66\xcd\x5a\x1b\x57\x6b\xd9\xce\x2b\x96\x71\xf7\x0f\xdb\x32\x05\x86\xf6\x7c\x90\x20\xbc\xc0\x78\xde\xf7\x1b\x3e\x02\x46\xb0\x5a\x9b\x75\x63\x4f\xcd\xd3\x04\x34\x14\xf5\x05\x15\x29\xa0\x92\xbe\x20\x67\xa6\x97\xc4\x29\x9d\x7e\x4d\xe8\x74\x7b\xf7\xbd\x7a\x1f\x95\x5e\x41\xc2\x26\x21\xc3\x1b\x1a\x0b\x75\xe3\x49\x21\xf2\x54\xd8\xc2\x34\x8d\x38\x38\x37\xfb\x9e\xfa\x19\xdf\x05\xc3\x6a\xd3\xb7\x9f\x6b\x7d\xde\x2c\xe2\x37\xf4\x78\x4e\x8d\x5c\xcf\xc0\xff\xb0\xe7\xb4\xe4\x9f\xf3\xc1\xee\xff\xea\xfd\x9c\x6b\xba\x63\xdf\xfb\x9c\x32\x79\x4e\x36\xfe\x29\xdc\x32\xb6\x6b\x8e\xba\xe8\x97\x5c\x27\x1c\xa6\x0e\x3d\x39\x8c\xd6\x04\x74\x02\xc0\xcd\xe3\xbb\x80\x1d\x6c\xa4\x2c\x80\xc8\x4a\xeb\x9d\x30\x98\x29\x00\x6d\xac\x3d\xac\x30\xc6\x18\x61\x04\x54\x2c\x76\xbc\x56\x3b\x22\xc8\x46\x88\xca\x49\xa9\x2f\x25\x8a\xb8\x4f\xaf\x0f\x67\x49\x7d\xb8\x21\x8d\x6c\x42\x92\xb1\xb1\x94\x7b\xdc\x68\x25\x4b\x33\xbe\xe2\xfb\x76\x7c\x9f\x3d\xc4\xb0\x06\xa3\xc5\x9e\x5f\x93\xad\x36\xa2\x8e\x44\x22\x11\x31\x59\xd7\xe5\x0f\xc9\x9d\x95\x5b\x37\x31\xc7\xaa\xb2\xef\x2d\x84\xa3\x43\xea\x93\x1b\xba\x36\x30\xeb\x77\x33\xdb\xf6\xaa\xe2\xee\xec\x2a\x66\x3d\xe5\x44\x01\x80\x5d\xcc\x75\x02\x3b\x58\x57\x30\x0e\xfc\x5e\x18\x4c\x99\x14\x04\x64\x1c\x16\x7b\x2c\xa6\x40\x3e\xa3\x30\xc6\xbe\xc7\xb1\xad\x7b\xdb\xbf\x3f\x8e\x5e\xcf\x6f\x29\xdb\x3e\x9f\xe9\x0c\xaa\x8b\xc6\x41\x47\x99\xfa\xe5\xbc\x43\xf3\xe1\xc7\x1b\xe0\x1f\x77\xa9\x47\x37\xa8\x65\xf0\x63\xda\x9b\xa5\x02\x6e\x29\xa9\x43\x3f\xaa\xd9\x4b\x99\xb6\x9a\x71\x6c\x06\x39\x22\x8a\xcc\x66\x90\x80\x1d\x07\x91\xcd\xa4\x4a\x8c\x64\x75\x2b\x31\xe5\x58\xf6\xb4\xe6\x5d\xc2\xad\xe7\xca\x17\x5e\xef\xef\xfe\xaa\xc0\x6c\xca\x04\xc4\xe5\x6a\xa1\xac\x49\xbe\x8c\x93\xc3\xc9\x52\x7c\x4d\x94\x96\x71\x45\x91\x0b\xa0\xf0\xa5\x84\x34\x9f\x23\x44\x7b\x74\x13\x28\xc3\xab\x82\x20\xc6\xe3\xc8\x2b\x26\x8c\x84\xb7\x48\xeb\xe2\xb7\x78\xa9\x9b\xa6\x35\xb1\x01\xb7\x8b\xe1\x34\xbe\x22\x5d\xaa\x84\xc5\xaf\xca\x9f\x83\xd9\x37\x16\x0f\x9d\xf4\x19\xb4\xef\x55\x7f\xf7\xec\xbd\x4b\x57\xdd\xb0\xe9\xbd\x1f\x1f\x7d\x74\x66\xcd\x7a\xbe\x6b\x8f\x0a\x9c\xea\x07\xdf\xfd\x49\xdd\xfd\x4c\x64\x5f\xcb\x16\x58\x76\xa4\xeb\x35\x53\x76\x2d\xb5\xd3\xb8\x6a\x61\x57\x70\x9d\xa0\x3c\x87\x4f\x79\x8c\x2a\x5d\x91\xbe\x07\xce\x44\x28\xdb\xdd\xa6\x4c\xca\x18\x20\xd8\x18\x4d\xb9\xd2\xa1\x72\xda\x02\xee\x83\x61\xc5\x2a\xe7\x29\x2b\xf5\xa6\x06\x8a\x4d\x39\xc5\x86\x8a\x24\x5a\x93\x7c\x39\xc6\xa6\x0c\x5f\x13\x65\xe5\xbd\xb0\x29\xd3\xb0\x29\xcb\x7b\xb1\x44\xf7\x4c\x8a\xc7\x91\x4f\x4c\x18\x9d\x6e\xda\xbb\x40\xc8\x00\x80\x5b\xa4\x3c\x3a\xd4\x28\x5a\x63\x51\x9a\x5b\xc4\x00\x95\xc3\x58\x54\x07\x28\xfe\x29\x33\x39\xa8\xce\x39\x6b\x42\x7c\xf1\x81\x59\x37\x75\x3f\x7c\xcd\x45\xe1\x99\xed\x7b\x5f\xb9\x6e\x79\x47\x6c\x36\xd7\xb9\x4b\x3d\x2a\x5f\xf9\xcb\x5b\x5f\x53\x5f\x78\x3c\xb6\xbf\x24\x04\x43\x9f\x6d\xdc\x2d\xa9\x4d\x00\x9e\xda\xa5\xae\x31\xa8\x44\x47\xf4\x98\xae\x09\x21\xc9\xb1\x18\xd5\x63\x4d\xf0\x06\x53\x4c\x13\xe6\x95\xdf\x51\x24\x81\xc8\xd6\x10\xfe\x08\xa1\x50\x46\xb2\x40\x59\xf0\x25\x5a\x75\x98\xf8\x22\x44\x73\x0f\x8e\x46\x1e\x39\xd3\x9c\x62\xaf\x38\xe1\x40\x36\xd2\xe2\xc1\xc9\x45\x4e\x97\x88\xaf\xf8\xbe\x0b\xdf\x4f\xb8\x64\xbe\x00\x30\x2e\x9e\x10\x25\x03\xfe\x64\x8c\x83\x2e\xce\x68\xb3\x3b\x44\x97\xce\xa4\x75\x88\x33\xda\x9c\xfa\x57\x02\xa4\xc3\x80\xed\x49\xa0\x35\x35\xd6\x38\x25\x7c\xa6\x0c\x78\x66\x18\x83\x1a\x8f\x02\x71\x71\x21\x1b\x92\xe1\x3c\xe6\x21\xf5\xbe\x17\xe1\xec\x6d\xca\x5d\xcc\x8a\xf7\xb2\xf3\x60\xd9\xd1\x6b\x0e\x4e\x9a\xa5\xee\xde\x85\x76\x65\xd7\xb0\x0c\x93\xca\x76\x30\x47\xc8\x9f\x50\xf6\x35\xec\xf3\x33\xef\x65\xeb\xf0\x1f\x00\xe0\xa9\x0f\xd5\xf5\x54\x33\x08\x96\x80\x44\x2b\xb6\xab\x96\x58\x5f\xda\x41\x0a\x34\x66\x12\x43\x48\xb0\x64\xc8\x00\x73\x18\x35\xfc\x30\xfd\xa0\x01\xff\x96\x7e\x10\xaa\x15\x08\x83\xde\x00\xa1\x97\x94\x50\x5e\x53\xa8\x41\x40\x8d\x69\x07\x1a\x20\xa0\x70\x9a\xff\x7e\x85\x21\x80\xc2\x8d\xf0\x90\xdb\x17\x6e\xa4\x42\x43\x74\xe9\xad\x6d\x22\x5d\x4c\xff\xbe\xe4\x10\xa5\xa0\xfe\xd7\x24\x87\xc6\x9e\x7d\xd5\xcf\x27\xec\xfc\xd9\xbf\xa0\x39\xe4\xcd\x7e\x06\x17\xda\x7e\xff\x4c\x4b\x45\x4e\x76\x08\x30\xa7\x54\x75\x34\x17\xe3\x5f\x03\x75\x60\x10\xd8\x0a\x12\xb5\x00\x84\x53\x03\x39\x50\xce\x85\x13\x3e\x86\x32\xba\xa2\xb6\x48\x2a\x4c\x3a\x02\x52\x56\x4b\xad\x0f\x1f\x49\x8c\x19\x88\xe2\x11\xd4\xf8\x8e\xd2\x6c\xcb\xa0\x66\xea\x72\x57\xb9\x32\xa8\x4a\x40\x01\xd2\xac\x29\x93\xb5\x25\x20\x67\x94\xc1\x30\xac\x34\x37\x8a\x12\x6a\xa2\xe4\x7c\xbe\x72\xca\x22\x53\x1b\x16\x25\xa5\xb1\x39\x1e\x57\x2c\x03\x45\x49\x01\x55\xb4\x53\xac\xbc\x22\x1e\x47\x92\xa4\xb8\x02\xf1\x42\xb1\xa2\xa2\x92\xf4\xbc\x56\x11\x29\x8c\xe6\x42\x55\x72\x1b\x6d\xfb\xad\x8b\x91\x3b\xa1\x2a\xe6\x82\x77\xe7\xa7\x7e\x53\x58\x7f\x7e\xc5\x47\xeb\x7f\xfe\xcb\x97\x13\x37\xdf\x73\x87\xfa\x75\xd7\x5f\x83\xae\xda\xe8\xe0\x61\x0d\xab\x4a\xfa\xdd\x72\xc3\xa8\x21\x07\x9b\x5a\x1e\xba\xa3\x7b\xfb\x9e\x3b\x2e\xbf\x74\xe5\xba\x8e\xd1\x68\x87\x56\x5c\xbe\xfe\xf5\xab\xd4\x79\x57\x9b\x3b\x46\xcd\x9d\x5e\x73\x6d\xeb\xd5\x37\x00\x1d\x33\x4d\xab\x69\x10\xb8\x85\xaa\x35\xe9\x98\xe9\x82\x4d\x05\x98\x15\x4a\x37\xf5\xc6\xac\x50\xc5\xa9\x27\x52\xfe\x8a\x4a\x2a\x86\x96\x43\xca\x9a\x43\xca\x26\x6a\xe2\x4e\x12\x11\x77\xfa\xe1\xb2\x4e\xbd\x91\x3a\xb3\xce\xd3\xc0\x42\xa0\xce\x24\xfa\xa4\x8e\x2a\x06\x8a\x6a\x51\xb7\x91\xf3\xc6\x21\xad\x77\xda\xea\x88\xe9\x31\x18\xc2\x20\xe3\x2c\x3c\x65\x14\x74\x97\x68\xea\xd3\x39\x72\xb2\x07\xbb\x3f\xa0\x2f\xf0\x0e\xca\xae\xc5\x21\x4b\x23\x8f\xac\x69\x4e\x31\xe3\xf5\xd5\x44\x9a\x5e\x59\x07\x43\x9a\x5e\x19\x7c\x48\x73\xf4\x60\x97\x49\xb1\x26\xb3\xe6\x6f\xc0\x24\x6b\xb2\xda\x73\x6b\xa7\x85\x21\x62\xa8\xc8\x2c\x52\xc6\x33\x2a\x6e\x63\xd4\x22\x28\x05\xeb\xe6\x64\xd8\x72\xe4\x6e\x26\x71\x2c\xdb\x00\x2f\x7b\x6c\xc5\xc1\xc9\x63\xd5\xb1\x3b\xf9\xae\xec\x60\xe6\xa5\x6c\x4d\xf6\xd5\xec\x31\xb8\x86\x79\x3b\x1b\x26\xfb\xee\x3a\xae\x85\xeb\x04\x0e\x70\xb8\x68\xdc\xf0\x0c\xe3\x16\xfb\x1c\x77\x8e\x44\x47\xd3\xcf\x2c\x18\x77\xf5\x7f\x62\xdc\x8a\xc1\x16\x27\x23\xe7\x8c\xc5\x23\x2f\xde\x31\xe2\x9f\x24\x96\x42\xf5\xad\xec\x7f\x43\x47\xd7\xf2\x03\xe7\x4e\xa6\x3a\x4b\xdf\x30\xa6\xec\xc7\xea\x15\xd9\xbf\xc2\xd5\x39\xad\x25\x30\x19\x00\x32\xe7\x12\x38\xa9\x8f\x5d\x8a\x15\xc4\xdd\x72\xc9\x05\xba\x94\xeb\x73\xee\x88\x12\x96\x37\x0f\x5e\x35\x72\x92\xcd\x9e\x8c\xe2\xea\xd9\x50\xa4\xd1\xa9\x70\xc8\xd9\x88\x0c\x24\x1b\xe1\xa8\x3a\x81\xb7\x64\xbe\xea\x84\xfe\x6b\x56\xbc\xc9\xb2\x92\x16\x67\x33\x3a\x0c\x04\x1e\x03\x4d\x4b\x08\x4e\x6d\x17\x16\xf1\x2f\x24\x44\xa9\x18\xb0\x84\xe0\xe4\x45\x29\x9e\xb0\x3b\xf4\xdd\x77\x84\x99\xe5\x0d\x46\xbb\xc3\x29\x88\xb9\x66\x57\x98\x62\x8d\x76\xed\x3b\x01\x93\x77\xd2\x10\xaa\x41\xa4\x39\x38\x6c\x3a\x6d\x72\xcc\x48\xc5\xdb\x8d\x21\xd9\x48\xcd\x67\x43\xc7\x86\x0a\x78\xfd\x87\xd9\x2b\xe0\xb2\x97\x3e\xad\xdf\x38\x79\xf5\x2a\x6c\x41\x1b\xe1\x59\x9b\xe0\xfa\xec\x8c\x93\x7f\x87\x7f\x7f\x19\xae\x9e\x9d\x3d\x9a\xe3\xbd\x9a\xca\x75\x00\x19\x3a\x34\x2c\x6d\x32\x46\xd0\x45\xbb\x52\xc5\xa2\xae\x54\x27\x41\x50\xf0\x64\x90\x50\x84\xa0\x2e\xf8\x7c\xa0\x3b\x4b\x81\xa3\xae\x9b\x4c\xd2\xee\xed\xf7\x77\xff\x8a\xea\x62\x10\x34\x05\x41\x71\xd6\x51\x34\xeb\x4e\xe8\xa4\x0f\xd6\x7c\x7b\xea\xf7\xa9\x67\xe4\xda\x56\x13\x92\xdc\x03\x56\x51\xe0\x35\xbf\xc6\xe1\xcc\x21\x6b\x83\x0c\x4b\xe4\xfa\x9d\x02\x95\x7e\xcd\xe1\x7b\x88\xe5\x8c\x0e\xfd\x5e\x8e\x0e\x8b\x68\x76\x6a\xfd\xac\x18\xdd\x9a\x18\xa9\x13\x36\x86\xe4\x3a\x36\xfe\xe7\xd4\xd2\x95\x63\xd7\x86\x20\xf3\x56\xf6\x4b\x37\x9c\xf6\x7a\x57\xdd\xba\xce\x8e\x65\x5c\x47\xf6\x9f\xcb\xe1\xe8\x7d\xdf\xa8\xbe\xb9\x2a\x07\xcb\x9e\x87\x33\xae\xce\xbe\xaf\x71\x3b\x00\xc0\xb7\x90\xfe\xed\xd7\x34\x7c\x9d\x72\x2c\x46\xe2\x6f\x8a\xc1\x16\x8b\xa5\x58\x06\xf4\x11\x76\x73\x15\x36\x05\xeb\xea\x52\x3d\x60\xee\x19\x6a\x93\x85\xa4\x51\x26\xe7\x20\x59\x63\x08\x7b\x81\x32\x84\x91\x9b\x12\xbe\x26\x24\xb9\x07\x43\x98\x62\x95\x30\x14\x34\x12\x57\x00\x85\x5c\x44\x96\x4a\x09\x96\x48\xec\x81\xc6\x7d\xb5\x28\x52\xcc\x18\xd2\xd8\xb3\x8c\xec\xd4\xcc\x96\xd0\x96\xfa\xae\xda\x23\xc1\xa3\x13\x19\x74\x2c\xbb\x1e\xce\x78\x45\xfd\xf8\xc0\x2a\x2d\x04\x77\x07\xf3\x52\x76\xcd\xc9\xd7\x98\x17\x57\x65\xbb\x00\x04\x6d\x00\x70\x31\x83\x0b\x78\xc0\xaf\x35\x5c\x24\x4f\x2c\x46\x7d\xb7\xd3\x31\xad\x79\x0b\x19\xed\x74\x50\xf4\x0c\xfe\xa1\x2f\x5a\xfa\x02\xc5\x23\x24\x8d\x1e\x02\x8a\xa7\x98\x36\x8d\xdc\x74\xe3\x6b\xc2\xed\xe9\x05\x8a\x3b\x07\x8a\xbb\x67\xb0\x0d\x83\x82\x78\x51\xb1\x3b\xe2\x71\x64\x90\x90\x2b\x0e\x14\x27\xfe\x81\xdd\xd5\x93\x31\xcd\x60\x8c\x69\x2f\x27\xdb\x06\x4d\xf7\x54\x6c\xaf\x4f\xd5\x43\x43\xa9\xfa\xed\x88\x48\x13\xc7\x98\xde\x56\xeb\x61\xcd\xcb\x7f\xb9\xeb\x3c\xee\xed\x5b\xbb\xba\x6e\x55\xdf\xfe\x68\x2b\x23\xab\xf5\xd9\x4d\x0c\xb3\x42\x5d\x4e\xed\xe7\x08\x00\xfc\x9b\x44\x2b\xf9\x16\xad\x66\x97\x32\xa4\xe9\xfb\x1b\x51\x62\xb7\x45\x21\xb2\x13\x1a\x6c\x8b\x25\x43\x72\x7c\xf4\xf0\xbf\x2b\x2f\xba\x86\x2c\xf4\x65\xd4\x8d\xe2\x07\xd0\xa4\x25\x19\xd6\x6c\xcb\xe7\xc1\x81\xb5\x40\x90\x5d\xa3\x4c\x0b\x11\x25\xf6\x9d\x4c\xf2\xc3\x6c\x03\x7c\xf5\x4d\xf5\xac\xbb\xbb\xa0\xc4\xbb\xf6\x68\x1b\x56\x0d\xde\xac\x78\x17\x1e\xc7\x44\x00\xb8\x63\x5c\x67\xaf\x71\xc0\xdc\x38\x4c\x45\xe3\x10\xf3\xe3\xb8\xbb\x7b\x6f\xef\x71\x50\x9d\xb9\xff\xd8\x38\xe4\x89\x41\xc6\xb1\x14\x9e\x7c\x2b\xfb\x21\x5c\xf1\xba\xba\x67\x79\xe2\x65\x16\xed\xa2\xdb\x4f\xf6\x2d\xbc\xf5\xb0\x48\x8b\x07\xac\xe1\x57\xf2\x5d\xc0\x09\xfe\x5b\x3b\xd3\x59\x6d\xce\x98\x36\x23\x39\x42\x46\x07\xd1\x90\xb3\x53\x22\x06\x2e\x9a\x70\x90\x03\x8a\xc3\x62\x0e\x23\x73\x94\x54\x55\x80\x77\xa8\x9c\x59\x5f\x2e\x09\x32\xe7\xcd\x5b\xec\xd9\x61\x7c\x77\xf7\x1e\x3d\xe6\x6e\xa3\x84\x8c\xc6\x74\xee\x4c\x48\xa4\xf5\xac\x69\x07\x32\x0b\xc8\x94\xe6\xf1\x1a\xca\x3a\x19\x1a\x14\xe1\x6c\xf8\xad\xb0\xdb\xb4\xb5\xd5\xe1\xa4\x1d\xb0\x46\x13\x2d\x7d\x30\x9a\xac\x36\x9d\xbc\x23\x1f\x4c\x23\xbc\x8b\x74\x8b\x96\x35\x3e\x17\x66\xdd\xcd\x29\xf5\xb3\xc7\xae\x39\x38\x09\x6d\xce\xae\x26\xd4\x2d\xcc\x22\x9a\xb4\x61\x0e\x64\xa7\x69\xbe\xc9\x16\xa2\xdf\xf0\x87\x1e\x18\xc1\x3e\x31\xd2\x74\xf6\x7a\xa3\x52\xe0\xb0\x58\x32\x49\xde\x6c\x31\x15\x83\xd2\x4b\x66\xaf\x18\x94\xde\x8e\x9c\x48\x1c\x9a\x1f\x82\x4b\xd2\x68\xa2\x7a\x7c\xa7\xc5\x46\xe3\xa4\xd4\xb1\xd1\x55\xfa\x5e\xb9\x7b\xd9\xe1\xc9\xdb\xf3\x4a\x7d\x34\x3b\x43\xd4\xfa\xb4\xfd\xc0\xf0\x2c\x89\xeb\x3d\xac\x61\x43\xe9\x20\xe8\x8e\x40\xda\xa5\x4d\x6c\x26\xc5\xda\xf0\xae\x80\xac\xba\x05\x91\xa0\x58\xbe\xb8\xb4\xa7\xcd\x14\x84\xca\x7a\x19\x8a\x45\x40\x7c\x9a\x1a\x04\xb2\x0b\x49\xd6\x8e\xc7\x6d\x11\x92\x9c\x05\x8f\xdb\x8a\xaf\xf8\xbe\x0d\xdf\x67\x0f\xb1\x1c\x6f\xd2\xa9\xb3\x0b\x8d\x20\x68\x0c\xc2\x42\x13\x80\x6a\x50\xed\x52\x8f\x1f\xca\x9b\xc0\x9e\x6f\x8f\xeb\xf3\x0f\x00\xff\x39\x89\xf9\xf5\x1c\x63\xae\x25\xdc\x64\x2a\x1a\xa3\xf1\x74\x63\x14\xfb\x1c\x63\xaf\x79\xff\xb7\xc7\x28\x6b\x63\x2c\x14\x5c\x64\xc4\xa0\xba\xf7\xe5\x02\xd1\xc5\x5d\x27\xcf\xcd\xcf\xa3\x0a\x8c\x53\x49\x3f\xea\x27\xda\x18\x03\xa5\x15\xfa\x3a\x80\x98\x98\x52\x4e\x4b\xbf\x6d\x11\x52\x83\xea\x20\x07\x56\x36\x93\xf2\xf1\x24\x0a\xe6\xcb\x37\x04\x6a\x7d\xef\xa5\x30\x8c\x8f\xb2\x28\x40\xeb\x4e\x4d\xee\x3c\x51\x68\x71\x2c\xbc\x42\x40\xe5\xe9\xa3\xed\x5b\xbb\x6f\x23\x37\x4b\x05\x54\x96\x46\x81\x1e\xab\x7b\x00\xaf\x8a\x25\xf8\x9a\x28\x09\xf4\x5a\x15\x4b\xc8\xee\xc6\xb0\x25\x65\xe5\x05\xbb\x5b\xa0\x54\x94\x14\xa7\x83\x68\xd1\x25\x78\x9b\x48\xa2\x88\x3e\xa0\x29\x26\x92\x28\xe2\x69\x63\x88\x21\x48\x42\xee\xec\xbb\x5b\x46\x9c\xfd\x19\xb4\x3f\xa8\xfe\xee\xb9\x9d\xcb\x57\x5f\xbf\xe5\xbd\x55\xbf\x78\x78\x66\xcd\xfa\xa3\x50\xca\xee\x52\x3f\xe3\xbb\xb2\xb3\x9c\xea\x07\xdf\xfd\x8f\xba\x3b\x1d\xd9\xd7\x72\x37\x2c\x4d\x1e\x7d\xd9\x94\x5d\xcb\xbb\xbe\x3d\x4e\x63\x89\x06\x8e\xeb\x04\x95\xb9\xb5\xb5\xb4\xac\x12\x63\x6a\xd6\xe3\x89\x18\xd8\x0a\x53\x06\x95\x13\x60\x65\x53\x26\xc5\xfb\x29\xd7\x8f\x29\xa7\xa1\xaf\xc9\xf8\x95\x51\x89\x21\x54\x4a\x03\x38\xa6\x02\x62\x90\x07\xbb\x8f\x15\xe0\xa9\xe9\xf7\xed\xea\x4e\x90\x9b\x84\x75\x18\xa3\x8a\xf1\xa4\x14\xd0\xd6\x24\x5b\x8a\xf1\x0c\xe0\x6b\x22\x50\xda\x0b\xcf\x80\x86\x67\xa0\xbc\xa2\x00\x4f\xa2\xea\x24\x38\xe3\x84\x62\x90\xb7\xd1\xa8\x2c\xa0\xec\x35\x24\xe6\xc8\x16\x34\xb6\x14\x47\x1c\xa9\x15\xb2\xe3\xe6\x4d\x18\xbe\xff\xf5\xb5\xdd\x0f\x8d\x9e\x15\xee\x3f\xa3\xfd\xa1\x57\x6e\x58\x36\x21\x36\x27\xf5\xaa\x5a\xfe\x12\xd7\xa9\x56\xca\x7f\x7f\xe3\x57\xea\x0b\x8f\x05\x7c\xfb\x4b\x42\xb0\xfa\xf8\xc6\xdd\x2e\x35\xc6\xa2\x93\xe7\xd2\x7a\xe8\xc7\xf8\x55\xfc\xeb\xba\x46\x42\x98\x68\x6a\xb0\x24\xcd\x5d\x89\x6d\xb1\x46\xef\x52\x35\x63\xa3\x6c\xad\xe1\x74\xcd\xb0\xc1\x3d\xeb\x3e\x1b\x5d\x19\xd4\x48\x3b\x14\x02\x6e\x42\xb8\xa8\x34\xba\x44\x49\x91\xc2\xf1\x38\x8a\x89\x87\x39\xb3\xcf\x50\x59\xd3\x8f\x50\xe9\x07\x24\xa5\x2a\x84\x87\x29\x84\x45\x29\x51\x5e\xd5\x8f\x96\x9f\xa7\x80\xdd\x15\x18\x58\xed\x8d\x2b\x66\x5f\x51\x53\x6b\x3e\x44\x35\x04\xb6\xd5\xb6\xe4\x5a\x7d\x8c\x39\x6e\x79\x52\xc5\x0c\x6a\x5c\x5e\xcd\xd4\x1c\x70\x5b\x1a\x5e\xf0\xf6\xf5\xab\x87\x5e\x7c\xc9\x4f\xb3\x9b\xba\xf6\x55\x97\x4e\xbd\xf6\x95\x1f\xdf\xb1\xe5\xe8\xde\xfe\xa3\xc6\x8c\x1f\x31\x63\xf2\x6d\x03\xe3\x17\xb5\x7c\xab\xfe\x89\x79\x75\xc4\xfa\x7b\x5a\xe2\xc3\x96\x8e\x66\x22\xd0\x00\x1f\xfd\x2c\x72\x5f\xfd\x51\x75\xdf\x1f\x5f\xfb\x90\xd9\xf1\xc6\xd3\x70\xd4\xc1\xa7\x0f\x1f\x53\xd7\x5d\xe1\x0a\xec\x0f\x44\xfb\x8b\x56\x38\xe0\x77\xca\x95\x33\xe0\x79\xaf\xcc\x9b\xb3\x25\xab\x6b\xb1\xbf\xc8\x2d\x26\xda\x92\x2d\x60\x27\x48\xd4\x6b\x6a\x97\xa8\x06\x03\x58\x59\x48\x43\xef\x8b\xd5\xe7\x00\x6c\x2d\x5c\xc4\x30\x80\x03\x2c\x19\x34\x80\xc6\x0e\x03\x94\xe7\x5a\x71\xd9\x45\x09\xd5\xc7\xd1\x00\x31\x65\x16\x38\xa9\x0e\x63\xd7\x24\x1d\x32\xfa\xca\x2b\x6b\x48\xdf\x46\x40\xd4\x81\xac\x27\x40\xd6\xc5\x09\xd8\x04\xc8\xc6\x62\x20\x7b\x55\xf5\x63\x20\x73\x59\x40\x1d\x48\x92\x0b\xac\x71\x79\xdb\x21\x49\x00\xce\xd9\xfa\xcf\xfb\x2f\x9f\x5c\xd3\xd1\xb9\xf4\xa1\x59\x6b\x97\xd5\x96\x76\x5c\xb4\xef\xaa\x65\x37\xdf\x79\x63\x6d\x63\x4b\x7b\xdb\xb4\x9b\xe6\xcc\x9c\xfb\xd4\x7b\xcc\xcc\xe8\xcc\x25\x93\xc7\x5f\x0a\x13\x2f\xc0\x31\x0f\x96\xdc\xe5\x5f\xab\xaa\x7b\x36\xec\x36\x2c\xbe\xfb\x27\xef\xdf\x70\xfb\x8f\xee\x51\xbf\x3a\xd7\x21\x6d\x71\x8d\xab\xfc\x5b\xea\x86\x89\x43\x3e\xb8\x76\xc5\x51\x6c\x77\xea\x68\xad\xa6\xb8\x1f\xb8\x01\x24\xdc\x00\x84\x53\x41\x1a\xb7\xca\x55\x18\xd7\x45\x52\x01\x12\xb7\x52\x64\x37\x21\xb2\x93\xd8\x5c\x03\xa4\x66\x78\xe5\x44\x9f\x84\x6a\x55\x97\xdb\x45\x29\xe1\xab\x24\x10\x54\x8b\x09\xb7\x40\x0b\xaa\xdd\x01\x51\x52\xca\xab\xe3\x71\x5a\x99\x2b\x68\x22\xa3\x76\x2a\x10\xd7\xbb\xbe\x18\xa3\x00\x7a\x45\xa6\xb6\xfd\x06\xce\xfb\xe8\xd7\x3b\x48\xc1\xf1\x97\xf7\x3c\xbd\x7f\x73\xea\xc1\x67\xbf\x52\x8f\x7f\x5d\x18\x91\x62\x02\x10\xc2\x67\x3f\x9f\xbc\xb3\xe3\x25\x75\xcb\xdb\xbf\x78\x77\xe8\xfd\xc3\x60\x38\x3b\xa4\x67\xcc\x0e\xcc\x51\x47\x6b\xda\xa8\xf5\x60\x25\xed\xf2\x4c\x55\x69\x63\xd7\x8b\x91\xfb\x45\x52\xa5\x64\xec\x10\xf5\x2f\x2c\x48\xae\x80\x61\xa5\xc6\x96\x51\xc2\x30\x4c\x93\xd7\xfe\x92\x38\xa9\xba\x29\x0d\xf6\xa3\x79\xe0\x84\xe0\xa9\x22\x03\xf7\xe0\x75\xba\xa2\x26\x1e\x57\xcc\x55\xa4\xb0\xda\x15\x3f\x6d\x2d\x72\x9e\x77\xae\xd7\xc8\xfb\x16\x5a\x5d\x5c\x38\xf0\xbe\x54\x57\xb3\x9b\x7b\x8c\x1b\x82\x23\xea\x1a\xae\x8b\xef\x02\x56\x3c\x6a\x72\x32\x01\xf8\x20\x6b\x8d\x52\xf1\x64\x4a\x38\x97\xd3\x46\xde\xd9\x7d\x80\xba\xf3\x8d\x0e\x64\x49\xf3\x0a\x67\x39\xe1\x20\x95\x4d\xb9\xbc\x86\xa9\xd1\x81\xcc\x69\x4e\x31\x96\x9c\x70\x20\x43\x1a\x1c\xe2\x0d\xba\x37\x46\x32\x13\xbc\xc1\x6c\xb1\x16\x95\x6f\xca\x6d\xa4\x2e\x84\x44\x92\x8e\x84\xd8\xf7\x2b\xd5\x25\xdd\x7b\x97\x3d\x36\x09\x41\x99\x77\xed\xd9\xf3\xdd\x66\xec\x9d\xf2\x2e\xea\x9b\x1a\x8e\x70\xb3\xc0\x20\x18\xd2\xce\x9d\x0d\x8d\x1a\xd7\x62\xb1\x62\x6c\x0c\x4f\x56\x94\x84\x53\xc1\x3b\xca\x20\x4b\x06\x0d\x2a\x4a\xdb\x37\xc2\xb0\xd2\x60\xc9\xa0\x06\x81\x48\x38\x88\x96\x4c\xd2\x23\xd6\x9a\xc2\x4a\x50\x26\xcc\x98\x1e\x39\x83\x44\x01\x95\xe2\xb5\x82\x24\x01\x23\x7a\xfc\xb5\x58\x44\xb6\x51\x40\x91\x34\x6a\x10\xd0\x80\xf4\xd1\xe1\x96\x2f\xbf\xd0\xdb\x28\xab\xd3\x8a\x4b\x38\xa1\xa9\x67\x3f\x46\x81\x29\x6b\xe4\x51\x79\x9a\x53\x4a\x85\x13\x0e\x14\x48\x83\x11\x66\xd9\x15\x28\x2d\x0b\x55\x0f\x88\xe4\xc3\x1a\x87\x65\x57\xa0\xbc\xf0\x56\x0f\xc9\xd9\x86\x46\xbc\xa3\xc7\xe2\x71\x14\x14\x13\x56\x1b\xb1\x2e\x8f\x84\x1c\x71\xa0\xc4\x80\x28\x75\x11\xc9\x59\x7f\xf0\xb4\xa2\xb3\x86\xe2\x84\x42\x9e\x0b\xfc\x8c\x0a\xb4\x53\x2d\xd5\x65\x91\xc8\x55\x87\xce\x1d\x31\xc6\x39\x43\xda\x78\x1a\x29\xda\x3b\x6e\x1f\xb4\x44\xbd\x36\x5c\x5d\xd9\xcf\x95\xed\x86\x4b\xc5\x8b\xc6\x0e\x6c\x87\xbb\x2f\x1e\x70\x47\x5f\xba\xb4\xe0\x49\x00\xb8\x37\xf8\x2e\x60\x02\xab\x41\xc2\x08\x48\x45\x53\x02\x10\x3f\x9a\x8d\xc5\x20\x32\x93\x84\x8e\x41\xce\x24\xa1\xc1\x68\x0a\x2b\xc0\x42\xc8\x4a\xa1\x25\x83\x3d\x4a\x32\x0d\x07\xbf\x90\x72\xb5\x3a\x26\x52\xc2\xc4\xa7\x8f\x3e\xfb\x8b\x7f\x0c\xc2\x77\x15\xa3\xc9\x84\x9d\x04\x53\xae\xf9\x3c\xc1\xf0\x26\x4d\xe6\xcc\x54\x60\x7d\x44\xec\x94\x0d\xc9\x4f\x1e\x3e\x08\x3f\x7c\x23\xbb\xe9\xaa\x27\x56\xf2\x5d\xd9\x10\x73\xec\xe4\xc2\xec\x47\x4c\x8d\xd6\xa3\x40\x34\x74\xed\x60\x15\x20\xdd\x2e\x0a\x34\xc5\x88\x5a\x85\x35\x56\x90\xf1\x46\x00\xdb\x0b\x2c\xf0\x75\x1f\xea\xfe\x84\x3e\x61\x11\xc7\xdb\xb5\xdf\x4c\x23\x4f\x68\xb3\x93\x27\xb4\x17\x3c\x21\x89\xc4\x42\xed\xbf\xda\x91\xd7\x46\x22\x87\x5a\xbf\x49\xac\xb5\x8d\x3e\xee\x9c\x43\x23\x5d\x66\x53\xc3\x3a\xd8\xf4\x6c\x76\xe3\xbc\x43\xf3\xb9\xce\xec\x9f\x0e\xa4\xae\xf8\x8c\x09\x7e\x97\x50\x7d\xf0\x13\xfc\xdc\x8b\x34\x8c\x05\xb0\x17\x10\xf5\x01\xe4\x88\xd1\x95\x9c\x37\xc6\x62\x29\x00\x9d\x78\xe3\x63\x2c\x34\x12\xa1\xd8\x85\x28\x25\x5b\x74\xbe\xa3\x38\xe4\x4c\x92\x77\x38\xb5\xaa\x3b\x2e\xa2\xf0\x96\x3c\xe5\xe2\x9b\x5f\x3c\x4d\x0b\xbe\x35\x3a\x49\x3c\x2a\x1d\x77\x42\xb9\xc8\xa6\xf1\x69\xce\x90\xe6\x91\x43\x48\xda\x1d\x16\x3d\xb2\x4a\x4f\xad\xac\x81\x34\xe2\xb0\x06\x8b\x5d\x28\x4e\xf0\x07\xdb\xa8\xf6\xac\x91\x7a\xf3\x8b\x82\xd0\x6b\xfa\x5c\x9b\x17\x0b\x0c\x85\xd4\x8f\xc6\x3d\xd1\x09\xa7\xef\xad\x67\xb7\xd0\x19\x0a\xed\x55\xf7\xc3\xe9\x00\xc0\x53\x1f\x69\x73\x24\x83\x0d\x20\x01\xf1\xda\xc0\xd8\xf1\xb8\xf8\x8c\x22\xc8\x51\x9d\x0f\xc5\x1a\x8b\x21\x29\x82\x44\x1a\x24\x95\x88\xe2\x4c\x4e\x5c\x35\x17\xa3\x4b\x7d\xd1\x48\x75\x17\x35\xb2\x5f\x24\xe4\x67\x8d\xd6\x85\x38\x68\x61\x08\x40\x7c\x23\x4c\x32\xbc\x20\xe7\x43\x14\x2c\xd4\x36\x77\x63\x5b\x8c\xcd\x4f\x19\x1d\x51\x45\xd9\xd7\x5b\x0b\x26\x6e\x13\x64\xca\xd4\x93\xe3\x0f\x75\x6e\xd8\x80\xe7\x2f\xf9\x28\x99\xbf\xae\x0d\xea\xbd\xf0\x72\x00\x4f\xed\x50\xd7\x70\x1f\x92\x78\xc5\x3c\x2d\x3f\x6f\xa3\xf9\x67\xa2\xdd\x2b\xd0\x60\x8b\x33\x7f\xa4\xd6\x04\xd3\x38\x64\x6d\xe4\x91\x2d\xcd\x29\x96\x8a\x13\x78\x35\x06\x09\xba\xe6\x42\xc5\x6c\xd3\x83\xfb\x56\x51\x22\xc5\x56\x0c\x10\xa5\x04\x67\x72\x90\x9d\x37\x64\x86\x54\xfb\x97\xac\xc6\x2c\x5c\xc4\x4c\x51\x4f\x3e\xf1\x12\x4c\xbe\x92\x7d\xf7\xdd\x83\xd7\x1c\x3c\x6f\xf6\x9b\x6a\x0d\x6b\x60\x50\xf6\x4d\x26\x92\xed\xc8\xee\x23\x81\x83\xeb\xb3\x1b\xa8\xd6\x70\x46\x5d\xc7\x75\x90\xd8\xc1\x82\x82\xe7\x85\xa7\x7d\xde\x3b\xbb\xd7\xfe\x2b\xcf\xab\x98\xec\xf1\x5e\x4f\xac\xab\x15\x6b\x4f\xec\x85\x7f\x38\xde\xb5\x1f\x8e\x7a\x53\x8d\x77\xed\x59\x7e\x70\xea\x98\x5f\xa8\x8f\xe5\x55\x8b\x69\x32\x42\xe3\x8e\xc6\x7b\xdf\x5a\xc3\x28\x82\xef\x61\xaa\xba\x88\xec\x31\x85\x67\x33\x09\x83\xd9\x12\x8d\x46\xe9\x76\x68\x34\x69\xaf\x07\xe7\x8c\xd2\x40\x07\x7e\xdb\x05\xc2\xed\x48\x0a\x09\xe5\xfc\x80\x7e\xda\x9d\xa6\xc2\xc4\x8d\x88\x6b\x44\x0e\x41\xe1\xfd\x27\x10\x27\x28\x4e\xff\x89\x5c\xf1\x6f\x21\x39\x3e\xbe\xf9\x2a\x85\xc0\xd6\xc8\x23\x7b\x9a\x53\xac\xce\x13\x3c\xb2\xa4\x59\xa0\xe0\x53\x2e\xe9\x79\x30\x5b\x8a\x7b\x1e\x68\x4d\x0f\x13\xcf\xed\x9d\x41\x48\xc3\x3c\x41\x78\x24\xc8\x7e\x58\xa5\x5e\xf9\x77\xe6\x72\x28\x3d\xa1\x7e\xb6\x7f\x39\x9a\x7c\x32\x02\xdd\xbc\xb4\x77\xef\x77\x5b\x79\xe9\xdb\xe3\xd9\x0f\xe1\x1a\x5e\x02\x10\xcc\x50\xd7\x71\x2a\xd7\x09\xea\xc0\x9f\x40\x22\xd8\x53\xb7\x19\xea\xba\xcd\xa4\x42\x89\xab\xd3\xa8\xf5\xaa\x73\xa5\x54\x44\xb6\x59\xce\xc9\x36\x17\xd0\xe9\x6d\xe8\x9e\x41\xd5\x5f\x1b\x1d\xa8\x16\xbb\x08\xa2\xe6\x22\xe4\x76\xc2\x9c\x9e\xb3\x5f\xd3\x73\xbe\xbb\xfb\x41\xd0\x53\xcf\xb9\x8b\x27\x82\xce\xb5\xb9\x9d\x91\xc3\x37\x4a\x6a\xeb\x8a\x76\x46\xbf\x51\x94\x92\x8c\xb9\x94\x94\x39\x3b\x44\x24\xc5\x15\xa7\x8f\x94\xe1\x01\x05\x98\x45\x29\x29\x95\x95\x53\xee\x32\x8a\xd4\x69\xe4\x9d\xeb\x42\x39\xb9\x98\x19\x15\xac\xaf\x52\x7d\x73\x85\xb8\xf9\x82\xbd\xab\x83\x97\xa7\x90\xa5\xaa\xac\x21\x76\xd5\x13\x53\x87\xb7\x33\xa6\xe9\x68\xee\xcd\x77\xba\x97\xb0\x68\xd7\xae\xec\x27\xb3\x6b\xb7\xac\xfc\x70\x17\x7c\xef\xe4\xeb\x91\x60\x65\x7f\xba\xe7\x5d\x76\xe9\xb5\x97\x6f\x59\x17\xbb\x9e\xe1\xb0\x7d\x75\xab\x6b\xf9\x06\xbe\x0b\xf8\xc1\x67\x80\xd4\x7f\x25\x38\xbb\x23\x16\x8b\x21\x6f\x44\xb1\x60\xb7\xb9\xa4\x27\xbf\x15\x05\x57\xc2\x3e\x89\x93\xe8\x7a\xda\x35\xb2\xc2\x80\x86\xee\xed\xdd\xcb\xfb\x20\x62\x7a\xa4\xfb\x5b\x02\xa0\x9d\x34\x47\x3a\xa8\xd4\xb3\x16\x42\xe6\x88\x7c\xac\x9c\xe6\x14\x11\xbf\x5d\x42\x1a\xb9\x84\xa4\xcd\x65\x97\xc3\x49\x37\xbe\x26\xdc\x2e\x7b\xc1\x99\xd8\x16\x07\x23\x2c\x0c\x6f\x73\x0a\xa2\x24\xbb\xdc\x05\x29\x97\xc3\xe4\x6e\xc1\x3d\xda\x59\xc7\x69\x95\x4a\x7d\x52\x37\xc5\xa2\x6d\xb9\x10\x24\x76\x64\xbb\x85\x15\x5d\x57\x0b\x93\x67\x25\xde\xba\xeb\x88\xfa\xf9\xfe\x95\x07\x27\x2b\x6b\xde\xdb\xff\xd0\x3e\x56\x6a\x9e\xca\x94\x66\xff\x3c\xbe\x76\x5c\xc7\xb9\xcc\x2b\xdf\x7e\x4e\xb2\xa5\x53\xa7\x6f\x21\xef\xe9\x6e\x75\x1d\xd1\xcd\x2e\x87\x76\x50\xa8\x97\x8d\x4a\x23\x54\x3e\xad\xe2\x74\x5a\xd9\x7a\xab\xa0\x5e\x9e\xd4\xfd\xe5\x12\x70\x26\xad\x6c\x47\xa3\x03\xb9\xd3\xbc\xe2\x14\x08\x54\x05\x61\x48\x59\xeb\x15\x96\xb0\x39\x8b\xe9\xbc\x80\xb6\x5b\x48\xda\xdd\x0e\x39\x9c\xf4\xb8\x7b\x4b\x67\x7b\xdc\x0e\xad\x8d\x69\x84\x95\xb1\x53\x48\x3d\xb4\x94\x50\x87\x75\x84\x85\x21\xb9\x43\xfc\x83\xfc\x6d\x9a\xc7\x21\xd8\x96\xc6\xe3\x48\x12\x15\x9f\x3f\xaf\xa4\x8d\x3f\xf7\xa5\xa4\x4d\x81\x6e\xed\x53\x4d\x9b\xc4\x36\xef\x19\x59\x9e\x53\xd4\x9e\xb8\x38\xa7\xa8\xad\xc5\x39\xdb\x36\x5c\x4f\x65\xb5\xb1\xed\x02\x40\x6c\x37\x00\x07\x82\x84\xac\x75\xfa\x52\x1b\x16\xc4\x58\x2c\x96\xf2\x5b\x64\x96\xc6\x80\xfd\x94\x37\xc1\x4f\x74\xa5\xfd\x5e\x73\x18\xf9\x74\xfa\x62\xc4\x44\x09\xeb\x08\x1f\xed\x83\x75\xcc\x93\x67\x1d\xf3\x10\xd6\x31\x99\xb2\x8e\x21\x89\xf2\xc1\x8a\x05\xcc\xc6\x1a\x5b\x1b\x57\x6c\xf7\xba\x40\x72\x01\xff\x58\xee\x65\xe8\x83\x88\xec\x68\xfb\x7d\xdd\x47\xf5\x8c\xa5\x53\x16\xe4\x70\xd2\x85\xaf\x3c\xfe\x8d\x62\x92\xb2\x84\x4b\x16\x0a\xde\x0a\x67\x1c\x1c\x62\x78\xab\xcd\xe9\xd2\x0f\x32\x16\xbb\xd3\x55\x40\x5c\x06\xfb\x36\x7f\x39\xc6\xb6\xe2\x37\x20\x24\x13\x22\xc9\xaa\xda\x6e\xdb\xf5\x5d\x2b\x2d\xe7\x5f\xda\xb9\x71\xdc\xf9\xf7\xdd\x75\x44\x7d\xed\x89\x35\x9b\xe6\x8c\xba\xb5\xfd\x91\x87\x59\xef\xc0\x76\xa6\x29\xfb\x46\x63\xbf\xce\x71\x70\xba\x9a\xb2\xb7\x31\xaf\x7c\xdb\xc9\x4c\x6d\x93\xd5\xd7\x60\xdd\x16\x3c\x27\xf7\x69\xfa\xf1\x65\x70\x22\xad\x56\x46\xa2\xae\x1f\xef\x14\xf0\x9c\x04\xcc\x12\x6b\x27\xfc\xfe\x89\x00\x21\x0e\x0f\xf8\xcd\x61\x54\x12\x2d\x90\x28\x29\x7a\x3d\x4a\x60\x58\xf1\x7b\x48\x51\xb3\x05\x86\x15\xab\x87\xec\x6a\x92\x86\xbd\x5e\xef\xf8\xcc\x17\x73\xfa\x58\x73\x7e\xd2\x3d\x8d\xce\x48\x09\xf6\xff\x90\x1f\x4f\xc1\xd1\xf6\x4b\xff\xf1\x73\x0a\xbe\xa4\xc9\xb5\xe2\x05\xa7\x44\x48\x9a\x4b\x2c\x18\xff\xcd\xdd\x37\x13\xfc\xfd\x42\xd2\xe6\xb7\xd2\x3c\xbb\x43\x72\xca\xe1\xa4\x4c\xae\x2e\x7c\xc5\x3f\xf5\xe1\x9f\xf2\xf8\x6f\x06\xf0\xdf\x4c\xf8\xfc\xd6\xa2\x45\x2a\x21\x4b\x4e\xda\x04\x8a\x0f\x3f\x23\xcc\x0c\x6f\xb1\xda\x1c\x3e\xd9\x55\xf0\x62\x59\x19\xde\x6c\x73\x38\x05\x5f\xa0\xe0\x76\x6e\xb6\x88\x5c\x8a\xdb\x13\x8f\x17\xce\x98\x17\x4f\x98\xdc\xa6\x69\xd2\xe3\x39\x6b\xab\xaa\xbd\xcf\x37\xa8\xab\x5d\x5a\x3b\x7c\xcd\x90\x97\xa7\xfa\x52\x99\x23\x0d\x91\xb0\x69\xc1\x8f\xda\xd6\xc4\xd6\x6e\x67\xb6\x8c\x9d\x0b\x9d\xea\xb1\x69\x0d\x77\x18\x60\x99\xda\xdd\x01\x97\xac\xf8\xae\xeb\xed\x8f\x36\xdc\x1a\x56\xbf\xfd\xe6\x76\x5a\xef\xc0\x6d\xe2\xbb\x80\x07\xfc\x26\x97\x4f\xf1\x14\xc4\x9a\x53\xbc\x44\x83\xa0\x6c\xa6\x47\x92\xb4\x20\x4f\x80\xcf\x13\xf6\x28\x76\x35\x90\x25\x9a\xb4\x9a\xb0\x5f\x4e\x54\x50\x23\xa4\xd2\xd6\x97\x4b\x1f\xfc\xb2\x88\xc9\x96\x2b\x3a\x77\xe4\x8a\x1f\x74\x01\x30\x4d\xe1\xcb\xed\xe9\x11\x13\x4d\xb2\x16\x3b\xed\xaa\x55\x58\xbd\x1f\xdc\xc6\x88\x92\xc2\x4b\x71\xad\x8c\x9d\xc8\xae\xe1\x85\xbd\x48\x56\x8a\x54\x14\x91\x3a\x86\x1b\x3f\x78\xe0\xa1\x7d\xb6\x95\x47\x56\x5a\xa6\x5c\x3c\xe3\xe1\x9b\x76\xf0\x5d\xd9\x03\x33\xb6\x6c\x8c\x0e\xc3\x8e\x63\x63\xff\x71\xe3\x83\x91\x6c\x5c\xaf\x61\x60\xdf\xe3\x3a\x81\x1f\xbc\xaf\xd7\x59\x0a\x7e\x3d\xdf\x84\xf1\x31\xbb\x09\x3e\x66\x23\xdd\x2f\xe1\x3b\x3a\x28\x32\x95\x3d\xa3\x05\xbc\xce\x82\x3d\xf2\xc9\x2f\x2e\xc8\xf7\x5e\x21\x46\x40\xfe\xf4\xd1\xe1\xb6\x2f\x4f\xf5\xa2\x8e\xc6\x86\xc6\xfa\x31\x12\x1c\xb9\xfa\xf0\x35\xe1\xf3\x17\xe3\x81\xb8\x38\x48\x39\x44\x1f\x65\xe0\x6a\x84\x5d\xc0\x21\xfa\xfc\xda\xb7\xc2\x13\x3a\xa1\x32\x13\x44\xc5\x4c\x74\xfb\xdc\x84\x48\xd9\x60\xd3\x45\xd0\x18\x43\xae\xbe\x3f\x77\xdc\x36\x38\x61\xfc\xd3\x23\xe7\x56\xca\xa6\x99\x07\x2f\xba\x79\xb3\x67\x70\x6a\x98\xbc\x75\xeb\x1b\x8d\x1e\xae\x53\xfd\xd1\xea\x61\x8b\x2e\xd8\xf2\x93\xc1\x4b\xd4\xbf\xc3\xd0\xb4\xc8\x96\xcf\x3f\x58\x0c\x00\x03\x56\x9d\x3a\x6e\x70\xf1\xaf\x83\x3a\xd0\x04\x7e\x02\x12\x95\x44\x53\x8e\xcd\x50\x96\xb6\x08\x9b\x49\x99\x6a\x2a\xed\xf6\x30\x92\x49\x9e\x86\x44\x41\xa2\xc4\xaa\x0c\x8e\x9c\xe4\xab\xc7\x95\x41\x66\xd2\x2f\xe5\x26\x96\x36\x00\x86\x89\xa8\x44\x0c\x86\x95\x90\x41\x94\x10\x1b\x57\x06\xf4\x13\xa5\xa4\xdd\x5f\x49\x69\x00\xfd\x95\xa2\x84\xca\x88\xd8\x70\x69\x28\x1e\x57\x22\x26\xfc\xf6\x30\x82\xfe\xf6\xc4\x1c\xd0\xed\x1a\x02\x89\xa8\x04\xd5\xce\xcd\x49\x72\xea\x8a\x12\x8d\xb0\x26\x56\x59\x4d\x59\x0f\x57\x35\xed\x11\x4b\x26\x7a\x62\xbf\x87\x91\xc7\x5e\xfd\x40\x3d\x5b\x8d\x2e\x30\x1c\x3d\x38\xeb\xe1\x7b\x56\xbd\x7a\xdd\x97\xea\x5f\xad\x2b\xd6\xc0\xd7\x87\xc0\x65\xf0\xa2\xeb\x17\xa5\xd5\x3f\xb0\x73\x66\x75\xf8\x3b\xaa\xce\x7d\x19\x36\xec\x3d\xf4\xc0\x89\x3f\x0f\x19\xf8\xca\xef\xab\x86\xed\x8f\xd6\xc2\x7a\x68\x1a\x32\x82\x59\x10\xdb\xfe\xf0\xf4\xd9\xea\x37\x24\x8e\xd7\x79\xea\x38\xb7\x85\x68\x4d\x44\xc0\x46\x90\x57\x99\x20\x8c\x6d\x0d\xc6\x4c\x4a\xae\x2d\xb7\xd9\xc3\xc8\x14\x53\x64\x03\x95\x29\x1a\xd8\x13\x1f\xb7\x45\xc3\xa7\x96\x4a\x73\xf7\xd7\x24\x9b\x9a\x74\x7c\xb8\xb8\x52\x6b\x16\x25\xbc\xfa\xf4\x17\x13\xb6\x72\x1f\x4d\xb7\x68\xfa\xb3\xb2\xa8\x04\x82\xf1\xb8\xd2\x50\x8b\x41\x62\x9d\x1a\x48\xad\xa4\x67\x6c\x08\x6c\x05\xb4\xe2\x8e\x0b\x43\x63\xb1\xb6\x04\x86\x48\x97\x5f\xee\xf4\xfb\x76\x87\xcf\x91\x07\x43\xef\xe1\x5d\x0f\xdc\xa5\x7e\xf0\x5a\x15\x7f\xe3\x0d\xe7\x6c\x9e\xb8\x7f\xdf\xe1\xdf\x71\xcb\xae\x87\x47\x85\x63\x9f\x4f\x1e\x39\x3f\xc5\xec\xad\x9d\x5c\x36\x6c\xd4\xd9\x1f\x40\x71\xdd\xea\x6b\x1f\x9f\x3d\x61\xfd\xad\x91\x9a\x5d\x93\xde\x7f\x6e\x50\x29\x33\xbf\x6e\xc5\x92\xf8\x88\x67\x08\x2e\xab\xd4\xb5\xc4\x6e\xc2\xa0\x05\xbc\x0e\x12\xd5\x78\xf7\x08\xc6\x94\x12\x63\x26\x51\x5d\x82\xb7\x8a\xea\x2a\x73\x18\x85\xa2\xd4\x90\x62\xd8\x90\xea\xab\xb0\x21\xb9\xa8\x21\x0d\x88\xea\xd1\x71\x0d\xa8\x3a\xbc\x85\xeb\x86\x34\xc0\x4d\xf6\x72\x0c\x5e\x95\x25\x93\xa8\x0a\xe1\x7f\xb1\xaa\xdc\x1c\x46\x55\x02\x61\xcc\xc2\xe6\xa5\x8b\x44\x3e\xf1\xc5\xf8\x7c\xa0\x0c\x55\x09\x28\x98\x66\x95\x20\x55\xe6\x50\xea\x34\xfb\x1b\x58\x25\x4a\x89\x12\x7b\x8c\x96\xc3\x57\x53\xa6\xed\x7a\x51\x29\xab\x8b\xc7\x95\xd8\x99\xcd\xcf\x50\x6c\x7f\xf8\x75\xab\x65\x5a\xce\x64\x82\x2f\xa8\x73\xd5\x27\x46\x53\x1b\x5c\x76\xe0\xe2\xce\xae\x89\xe9\x3f\x9c\xd1\x0a\x1f\xfd\xf5\x3c\xcd\x0c\x1b\x6a\x59\x75\x1b\x5c\x51\x06\x43\x7f\xe9\x65\x8b\x24\x97\x3e\x0b\xf4\x03\x51\x7c\xc2\x24\x26\x38\x90\x92\x5a\xd4\xc6\x94\x7a\x43\x06\x99\xa2\x10\xc5\x0a\x51\xad\x2d\x34\xbf\x7a\x6a\x7e\x95\x30\xac\x54\x58\x32\x89\x8a\x4a\x8c\x6a\x45\xa9\x39\x8c\x2a\x68\x0d\x33\x36\xca\x66\x0d\xd5\x97\xbf\xb8\x9d\xae\xf9\x95\x8d\x0e\x14\x4c\x73\x4a\x05\xf6\x61\xcb\xd3\x20\x59\x5e\x41\x35\xd2\xa1\x52\x1e\xd4\xd6\xab\x5a\xcd\x8a\xeb\xa9\x15\x2b\x0d\x15\xa2\x94\xf0\xd9\x06\x12\xb4\x07\xd6\xff\x60\xbb\x35\xea\x91\xc4\x1f\x62\xba\x77\xdc\xd6\xd1\x75\xf6\xba\x8d\xdf\x6f\xbd\xa3\xcd\xea\x76\xb8\x32\xf4\xc6\x4f\x8b\x6c\x18\x9e\x7a\x17\x00\xd6\x46\x62\xd5\xd3\xb4\xf8\x2f\xe4\xf0\x8e\x48\xf3\xef\x1c\x97\x41\x46\x12\xb5\xce\x85\xab\xb5\xd3\x35\xe9\xbf\x65\xd3\x8a\x59\x38\x81\x4c\x69\x90\x64\x58\xca\x00\x03\x73\x9f\xb4\x60\x60\x68\x38\x94\xeb\xda\x82\x4e\xc8\x7a\x8d\xf5\xee\x83\x27\xee\x75\x31\xc0\x85\xbe\xdd\xed\x9e\x5b\xcf\xdd\x57\x37\x6f\x5e\xdd\x77\x73\xeb\xe7\xd2\x1a\xdf\x5d\x00\x18\x54\xe3\x3c\x20\x82\x20\xf8\xa3\xbe\xb3\x93\x53\x49\x61\x87\x00\xaa\x88\x28\x7e\x3e\x93\xf0\x93\x96\x7f\x3f\x9e\x3a\x57\x94\x74\x23\x4a\xef\x28\x5e\x47\x26\xe9\x20\x42\x9e\x4e\x81\x54\x43\x3b\x28\x0f\x6f\x41\x1f\x41\x29\x0c\x2b\x65\xce\x7c\x7b\x62\xae\x8f\x40\xdf\xcb\x9d\x42\x92\x23\x05\x8b\xa7\x29\x64\x4c\x08\xce\x1e\x6d\x03\xf9\xc2\xc5\x24\x67\xa4\x01\x38\x98\xfb\x94\xaf\xa4\xf3\x57\xc4\xe3\xa8\x54\xab\x56\x2c\x6c\x12\x20\x15\x37\xe6\x9e\x1d\xb0\xbd\x1a\x06\xae\x7e\x4d\x6b\x16\x60\xc6\x17\xc9\xef\xf5\xe8\x1d\xa8\xd3\xfb\x06\x8c\xa1\x22\xfd\xbd\x53\x1f\x9e\x3a\x6e\x38\x69\x70\x81\xa1\x60\x02\x74\x81\xbe\xba\x07\x12\x03\x5a\x5a\x63\xb1\x98\x02\x8d\x19\x14\xfe\x61\x9d\x03\x43\x7a\x75\x0e\xa0\xce\x88\x32\x9a\xcf\xa0\xe1\x11\x34\x2e\x06\xd1\x39\x85\x6d\x04\xc3\x30\xe8\x51\x65\x94\x23\x83\x5a\xa2\x68\x94\xa0\x0c\x77\x90\x5f\x1c\xd5\x57\x5b\x41\x72\x5c\x6d\x93\x29\xac\x74\x38\x33\xca\xc4\xe2\xae\x82\xef\x6f\x1f\x48\xba\x7d\xb4\x6f\x80\xb4\x43\x7a\x44\x49\x19\xdd\x19\x8f\xff\xe7\xfa\x07\xf2\xda\x45\x5a\xff\x40\xcf\xd9\xfb\x01\xfd\x04\x83\x06\x4f\x19\xf4\xc8\xe1\x82\x76\x02\xe6\xee\xa2\x79\xfd\xbe\xee\x02\x61\xbb\xf0\xee\xaf\x07\x95\x6a\xad\x05\xfc\x9f\x0a\x67\x5b\xab\xc9\x20\x75\xc1\xa5\xe0\x69\x2d\x76\x58\x5a\x50\x29\x87\xec\x24\xd1\x48\x4b\xe1\x05\x36\x27\x18\xae\x15\x09\x14\xb8\xca\x78\x66\xcc\x2e\x22\x23\x5e\xd8\xd0\x9b\x7f\x63\x4a\x85\x1f\x52\x11\x40\xae\xb4\x12\x00\x88\x92\xe2\x14\xe2\x71\xea\xe4\xd9\x25\x52\x13\xa0\x18\xfc\xf1\x38\x32\xe3\x45\x94\x96\x45\x27\xcc\x1e\x7a\x28\xa7\x45\xe1\x90\xb2\x3c\xf6\xd1\xae\xd5\x45\x4a\xc4\x67\xfc\xcf\x57\x7b\xd4\xb7\x5e\xb8\x67\xe9\xea\x95\xdb\x8e\xad\x3c\xa4\xcc\xb9\x68\xb5\x56\x2a\x3e\x5d\x54\x8f\x7f\xf6\xb1\xba\xf7\xa9\xc8\xbe\x96\x5d\xd0\xf5\x58\xf2\x85\x8a\xec\xc1\x5c\xbf\x16\xa9\x1b\x0f\x80\x97\x34\x8c\x02\xb1\x84\x25\x17\xaf\xcb\x01\x95\xef\xcf\x0d\x58\x48\x51\x4a\x41\x39\x8e\x1b\xe3\x53\xd0\xaa\xfb\xf8\x17\x76\x50\x24\xc3\x1a\x10\x7e\x48\x05\x0a\xb9\xd2\xca\x93\x3e\xf0\x71\x8b\x8a\xc1\x97\xc7\x47\xb2\x13\xf6\x25\x04\x44\x24\xc4\x11\x94\x12\x66\xb7\x2f\xa7\x0d\x0c\x63\x30\xdf\xb9\xe5\x29\x68\xdc\xa2\x35\xe5\xaa\x7f\xdf\x63\x37\xfd\x63\xdf\xaa\xd9\x97\xcf\x79\xf4\xd5\xdb\xae\x9b\x32\x76\x16\xad\x2c\x57\x3d\xa5\x1f\xa4\x5e\x56\x5f\x3d\x10\xdb\x3f\x0c\xfa\xba\x37\xee\xf1\xa9\x71\xbc\x47\x3c\xad\xae\xe5\x87\xf0\x5d\xc0\x0b\x9e\x07\x44\x74\x0d\x99\x29\x93\x9c\x10\x45\x9e\x88\xc2\xb2\x44\x9d\x5b\xe7\x27\x1a\xf6\xe4\xdf\xca\xa9\x7a\x54\xa3\x03\x19\xd2\xbc\x22\x96\x9d\x70\x90\xbc\x9d\xc6\x92\xc5\x23\xa1\xd1\x81\x9c\x69\x5e\x31\xfb\x4f\x38\xf0\x31\x6a\xd8\x86\xcf\x2f\x23\x40\x19\x84\xa4\xd1\x90\xd3\xe2\x11\xe5\x70\xc2\x68\x28\xe8\xfc\x4e\x48\xb2\x28\x4a\x71\x70\xc8\xe2\x34\x18\x25\x39\x17\xed\x31\x99\x2d\x4e\x41\xcc\xdf\x2a\x38\x92\xe2\x37\x1f\x38\xe2\x44\xdf\x1a\x5a\xe3\x79\x65\x6b\x49\x0e\x6a\xa5\xf6\x41\x0b\x21\x49\x1d\xd5\x1c\x3b\x6f\xc1\xac\x1d\x5b\x99\x77\xd5\xe3\x5d\x27\xdf\xed\x46\xd0\xa5\xde\xbe\x63\xdb\xb5\xbb\x97\xfd\x3f\xcc\xfd\x7b\x5c\x53\x57\xd6\x3f\x8e\xef\x7d\xce\xc9\x85\x00\x21\x57\xc2\x3d\x84\x08\x08\x11\x10\x02\xc4\xa8\x80\xa2\xa0\x22\xa2\x52\xa4\x78\x43\x04\x54\xc4\x0b\xde\x10\xa9\x52\x44\x8a\x8a\x8a\x88\x28\xde\x95\x52\x8a\xd4\x52\xe6\x04\x22\xde\xad\xd6\x5a\xb5\xd6\x5a\x9f\x8e\x75\xac\xb5\x9d\x4e\xdb\x69\xe9\xd0\x9b\xed\x74\x5a\x25\x9b\xdf\xeb\xec\x73\x12\xc2\x45\xdb\xe7\x79\x3e\xcf\xeb\xf7\xfd\x63\x62\x5e\x74\x72\xce\xde\x6b\xaf\xbd\xf6\x5a\x7b\xad\xf5\x7e\x27\xd7\x2b\x9f\x7f\x17\x7e\x4b\xf8\x5a\xef\x7a\x2d\x77\x90\xfe\x56\x16\x3e\x3f\x9b\x50\x39\xe5\x4e\xa5\x01\x5f\x90\xc3\xe9\x8f\x5a\x6f\x22\xf9\x9d\xb8\x8b\x9e\x75\x4f\x30\x38\xb8\x26\xcc\x56\x6e\xc3\xdd\x7f\xd1\x0a\x7c\x31\x66\x72\x91\xfe\x4e\x8b\x2f\x81\x36\xb1\x8b\x92\x25\xdc\x71\x61\xaf\x03\xd9\x09\xa8\x48\xa9\xac\x1d\x0a\x25\x5e\xf8\xc6\xb5\x2f\x2b\x37\x7b\x35\xc5\x42\x37\x13\xcc\x14\x66\x79\x04\x8d\xca\x98\x9e\x30\x3c\x6d\xc5\x91\x75\x5b\xd7\x5e\x6d\xe9\x6c\xbf\x41\xdf\xf6\x0f\x4a\xce\x9c\x3a\x63\xf6\xf2\x6d\x39\x11\x98\x72\xbb\xf2\xdd\x8a\xb1\xda\xee\x45\x96\x7f\xc1\x12\xd2\x2c\x1c\x55\xfd\x0b\x42\xed\xcf\xdb\xec\x45\x11\xee\xcf\xe3\x6a\x90\x69\x65\x9f\x3a\x4e\x5a\x14\x66\x72\x21\x3b\x69\x27\xc6\x62\x38\x93\x9d\x66\x52\x81\x6b\x16\xe5\xbd\x55\x79\xae\x78\x8b\x28\x59\x27\xcb\xce\x84\x58\xcb\x37\x55\x4f\xa9\xca\xc3\xd4\xed\x32\x8e\xba\x9d\x47\x2b\x25\xed\xa4\x92\x60\xef\x32\x28\x19\x0f\xdf\x65\xf0\xd8\x8b\x41\x85\x92\xab\xd3\x94\x71\x25\xeb\x32\x79\x6f\x57\x1e\x8e\x10\x4d\x4e\xce\xd6\x9d\x23\x72\x31\x1a\xed\xea\x36\x09\xa0\xe1\x8c\x87\x27\xb4\xaf\xde\xfc\x62\x3c\xba\x8e\xfe\xbd\x67\xdd\xd6\x17\xdf\x7b\x10\xbd\xba\xb7\x88\xb3\x0d\x5d\x41\x77\xc3\x5b\xa3\x3e\x86\x24\xa1\xe5\x78\xf7\x90\x08\xd7\x72\x2a\xc1\x87\x76\x32\x82\x7d\x65\x24\xec\x23\x1a\xc1\xd3\x44\x23\x1d\x54\x34\xfd\x8b\xf9\xfe\x2f\x45\x63\x72\xe1\x98\xf0\x81\x14\x73\x65\x5a\x8b\x38\x6d\x96\x23\xda\x60\x57\xca\xf9\xc5\xe8\xcf\xde\x5d\x9f\x3d\x77\x43\x49\x4d\xc8\x2c\x5b\x11\xe0\x93\xbb\xe8\xcb\xdf\xc3\x5b\xe2\x4e\xdf\x87\xed\xb6\x5a\x40\x6b\x4d\xf0\xdb\xd6\x1e\x0a\x97\x3f\xa8\x08\x7e\x7a\x0d\xf0\x7f\xab\xf0\xf7\xcf\x54\xb2\xd2\x02\x56\x38\x4e\xf6\xd4\x7c\x3c\x82\x39\x6e\x44\x8e\x46\x23\xee\x27\x11\x1a\x81\x49\x6c\x7f\x27\xf3\x94\xaa\xdf\x0b\xe8\xee\x4f\x6d\x83\x56\xfd\x82\x3e\x75\xbf\x7d\xe5\xf0\x3f\xaa\xfa\xed\x2f\x87\x67\xd6\xfa\xfe\xdf\xc8\xe1\x69\x15\xbe\x2d\xdf\x98\x6f\xb4\x0e\x5a\xe1\xdb\x9b\xaf\xf1\x00\x8f\xac\xf9\x1a\x36\xcf\xe0\xc6\xe5\x6b\x3c\x9f\x75\xa7\x8d\x6f\xaf\x5d\xb0\xe7\x68\x85\xb4\xf4\x7a\xe6\xed\xf5\x4b\x8f\x92\x58\xdc\x42\x6b\x6a\xc1\x05\xa7\x16\xce\xc6\xd6\x3f\x7a\xdf\x9a\x0f\x53\x72\xf9\xb0\xfe\x69\x06\x57\xa5\xd8\xee\x58\x76\x66\x93\x36\xd6\x04\x83\x5d\x76\xe1\xa4\x33\xce\x2c\xf4\x4b\x2a\xd0\x6e\x46\x5a\x86\x7d\xfb\xc1\x93\x36\xec\x9d\x35\xa9\x95\xeb\xd9\xac\x0d\xbe\xb4\x4e\xcd\xcc\x39\xb7\xa0\xee\x34\xba\xd9\x9a\xd6\xb2\xaa\x69\x0e\x4e\xdb\xd8\xee\xac\x27\x4e\x0a\x0a\x24\xae\x3f\x4e\x42\x65\x84\x16\xd2\x5c\xde\xe6\x1a\x2a\xc7\x1c\xda\x5e\x10\x58\xf3\x36\x6c\xfe\xcb\x23\x8c\xbd\xcf\xf3\x1e\xf4\x56\xda\x7a\xff\xec\x63\xbb\xcf\x4b\x1b\xe4\xfe\xf9\xe0\x23\x53\xbf\xf4\x96\x35\x67\x53\xfb\x68\x37\x7b\x74\x3b\x63\xc1\xf2\x4c\x62\x46\xb0\x2e\xfd\x13\x5f\xed\xae\x83\xa4\xbf\x5c\xd9\x0c\x98\x63\x6f\x06\xcc\xb5\x4f\xb2\x86\xf9\x0f\xce\x62\x9c\x06\x73\xed\x77\xa7\x8c\x53\x61\xb4\x07\x73\x7a\xd3\x0e\x36\x62\x77\x95\x5b\xdf\x1b\x66\x2e\x53\x83\x85\x8b\xef\x98\xb5\x7e\x01\xd7\xf0\x05\x73\xf5\xde\xf7\xc3\x5c\xdb\xbe\xde\x3f\xfd\xe4\xca\xbd\x91\x6a\x99\x70\xcf\x9d\xb2\x7d\x44\xed\xf8\x5c\xe8\x82\x3e\x9b\x39\x6c\xf7\x8f\x0f\x96\x3d\xe9\x40\xe5\x84\xf2\xdf\x05\x7a\xf3\x0e\x6b\xff\x24\xae\x47\x77\x03\x5f\x73\x11\xa8\x93\xcc\x4d\xaf\xb7\xa3\x96\xb4\xd2\x66\xb8\xb9\xd8\x68\x33\xfa\x56\x24\x8b\x69\x37\x96\x5a\x6f\xf5\x6f\x2b\xb9\x8b\x7b\x2c\x4e\x13\xe9\xf6\x3b\x0f\x97\xd1\x1e\x7f\xf4\x23\x0b\xdf\x80\xfd\x20\x93\x40\xfa\x3b\x0f\xe7\xcc\x36\x3e\x1a\x89\xdd\x20\x0c\xd9\xe0\xc2\xa6\x4e\x5c\xdd\x94\x98\x1e\x52\x89\xe9\x21\x95\x7d\xe4\xda\xe6\xec\xe4\xc2\xf8\x43\xa7\x48\x81\xb3\x8b\x5c\xd5\x2b\x3e\x38\xc6\x19\x12\x24\x5f\xe0\xe4\xec\x22\xb3\xff\xbb\x9d\x67\x04\x7b\xcd\x1b\x63\xdc\x38\x67\x48\x2e\x33\x68\x19\x2d\x15\x43\x7c\xe9\x0c\x89\x9d\x42\xa2\x12\xba\xa3\x9f\x4e\x3f\xb9\xf7\x13\x7d\x7a\x92\x07\x65\x89\xab\x39\x2c\x14\x04\x2a\xce\xf2\x3a\x9e\xa4\x53\x27\x58\x97\x88\xcc\x85\x13\x33\x1e\x77\xf3\x88\x09\xdf\xcd\xeb\xae\x61\x6d\x5f\x05\x6f\x0e\xe6\x7a\x2f\xb1\xde\x41\xcb\xdd\x6c\x77\xd0\x0e\xbd\x52\x14\xf7\x4a\x91\xed\x61\xb1\x97\xa2\xca\x5e\xf5\x5c\x58\x80\x2f\x91\xff\xef\x3c\xda\xe1\x12\x09\xda\x44\x12\x15\xde\x8f\x90\x71\xff\x54\xb6\xc9\x71\x88\x5c\x3c\x47\xce\x1d\x96\xbb\xaa\xa2\x0d\xb6\x4c\x1e\x66\x6f\x08\x08\x24\x8d\xdf\xde\x5a\xee\x4a\xfa\xcd\x84\x55\x0f\x6f\xb6\x7c\xd5\x71\xfd\xc0\x59\xe9\x42\xf4\xd2\xe6\x7c\x05\x79\x96\x4a\xb2\x8c\x3d\x36\x62\xca\x21\xa2\xb5\x3b\xc5\xf2\x1d\x5c\x4f\xe6\x07\xbe\x61\xc9\x27\xea\xb6\x4d\xec\xde\xff\xff\xad\x3b\x13\x12\xf3\xde\x5e\x15\x2c\xc4\x98\x75\x3e\x80\xe6\xc6\x43\x52\x76\xd9\x10\xbe\x10\x9f\x31\x0e\x56\xdc\x19\xda\x2b\xcc\xe4\xca\xeb\x6c\x73\xf5\x12\xe9\xda\xc7\xb8\xba\x3b\xe8\x68\x69\x04\x4e\xf8\xba\xd8\xb8\x11\x39\x2a\xdc\x76\x77\x92\x12\xea\x4c\x1e\x2e\xb6\x74\xef\xa5\xb5\xbf\xa5\xda\x6a\x92\x44\x36\x1a\x58\x91\xa4\x9d\x27\xc2\x74\xdd\x22\x96\x06\x56\x84\x8b\x78\xd8\x22\x45\xe6\x60\xa1\x14\x8c\x1f\xeb\xe4\xca\xde\x7d\x43\x21\x76\x3b\xac\x3c\xb0\x1a\x12\x6a\xc8\x80\x28\x31\x24\xfb\x05\xd1\x85\xa4\xe7\xa5\x93\x27\x0d\x48\xfe\x3d\x4c\x84\xe5\x1a\x4f\xdf\xe4\xc3\x7d\x22\x64\x5e\xc7\xe3\x24\x78\x0d\x19\x89\x7c\x18\xf1\x45\xe1\x94\x43\xa4\xaa\x6f\x0c\x8c\x71\xcc\xa9\x5d\x7c\x05\x90\x01\x5f\x30\x1c\xd4\xb1\x98\x2b\x98\xd2\xdc\xe4\x2a\xe8\x6c\x73\x80\x1c\xd9\x83\xc9\x5b\xd0\x49\x87\x86\x99\x86\xf2\x3a\x69\x6d\x18\xad\xd3\x5b\xe1\xfa\xe5\x72\xdc\x73\xa8\x81\x3a\x53\x80\x18\x23\x1d\x60\x22\x52\x27\x9c\xd6\xd3\x41\x9d\x69\x98\x0b\x0b\xe2\xaf\xe1\xaa\x6e\x03\xa4\xd8\xe2\xc9\xda\x28\xef\x50\x0c\xae\x21\x6d\x77\x16\x7b\x0c\x1d\xa2\x32\xd2\x3a\x16\x94\x09\x98\xbc\x9d\xa4\x32\x33\x10\x0a\x9c\xc5\xf6\x9c\x0e\x2a\xbd\x41\x4f\x6a\x59\xfb\xd5\x97\xd8\x41\xde\x4f\x2e\xd9\x55\xbf\xd5\xcd\xad\x0a\x76\x1c\x5b\xd9\x59\xed\x21\x7c\xe3\x7a\x65\xfd\x99\x59\xa9\x99\x17\x56\x2d\x9d\xb9\xe0\x8d\xec\xca\x3e\x22\x82\xd9\xb7\x60\xce\x7b\xd9\x73\x4e\x3c\xe9\xb8\xf9\xd9\xdb\xad\x05\xcb\xcd\x50\x53\x97\x5d\xfc\x1a\xfa\x07\x79\xa7\x8f\xb0\x28\xac\x4b\x23\x04\x41\x58\x97\xdc\x81\xbf\xad\x83\xfc\xd9\xda\xa4\x0a\xa3\xb5\x7a\xb3\xcc\x01\x44\x50\x3a\xda\x9b\x65\x96\x66\x14\x49\x81\x15\xc9\x03\xea\x4c\xbe\x56\x96\x6d\xb2\x97\x4e\xfa\x7f\xaa\x47\x0a\x17\x8c\xbd\x43\x53\x52\xda\xc9\x68\x22\x3d\xa4\x32\x93\x37\x2e\x0c\x7f\xba\x4a\x45\xeb\x23\xd8\x36\x7c\xff\xc8\x5e\xde\xf2\x81\x9a\xb5\x74\x64\x44\xaa\x31\x24\x30\x1c\xae\x18\x1d\x1e\x3c\x34\x66\x98\x7f\x78\x7f\xed\x22\x9a\xf5\xf1\xa9\xe1\x13\x87\x05\x47\x8e\x0d\xf1\x8f\x4c\x18\x06\x00\x85\xf5\x6b\x21\xef\x1e\xd6\x2f\x1d\x30\x80\x1d\xcf\xd6\xb0\xa0\x30\x3a\x4a\x6f\x1e\xc2\x0a\x2b\x2c\x02\xd2\x23\x06\x28\x99\x02\x2b\xd9\x30\xa8\x33\x45\x28\xb8\x58\xcb\xd1\xa9\xd3\x64\xec\xa3\x62\x26\xca\x15\x73\x0b\xd2\xde\x8c\x82\xb5\x39\x8b\x3d\x8c\xff\x33\xbd\x1a\x54\x38\xcf\x54\xaf\x57\x07\xc8\xe9\x19\x2a\x96\xdd\x5f\x62\x00\x10\x3d\x95\x00\xf0\x3b\x71\x7c\x20\x07\x7b\x39\x14\x24\xa0\x37\x39\x70\xd4\xee\x26\x39\xd9\x69\xa2\x64\x11\x11\x66\xb1\xc4\x89\xd1\x35\xa9\xde\x24\xc6\xd4\xdd\x66\x9e\xd0\xc9\x96\xd8\x65\xe1\xa0\xb1\x7d\xdd\xfe\x68\x29\x77\x9e\xd2\x54\x28\xed\x24\x31\x39\xb0\x35\x62\x32\xf7\xdf\x69\x07\x49\x3b\xcf\x01\xd3\xe4\x33\x9f\xec\xd1\x2a\x93\xeb\xda\xa5\xcc\x27\x79\x8a\xe2\x09\x1d\x9c\x9c\x7b\x3b\xa1\xd9\xb2\x49\x2d\xb4\xa2\x22\x69\x04\x1a\xb9\xc6\x01\x6a\xe4\xda\x22\xb2\x99\x3c\xed\x6b\xb9\x9d\x43\x38\xab\x2d\xbf\x14\x10\x61\x5a\x8b\x7b\x16\x4a\x42\x5f\xc0\x0a\x58\x50\x93\xc6\xeb\x68\x40\x23\xea\x2d\xbf\x36\xb0\x1a\x43\x9c\xb0\xd9\x1f\x7e\x36\x95\x09\x82\xc1\x08\x10\x0f\x5e\x07\x6d\x5a\x46\x3b\x86\xb2\xc0\x40\xa6\x50\x41\x27\xed\x16\x81\x6b\xac\x59\x46\x05\x67\xbd\x29\x4a\xd0\x49\x8f\x89\x30\xcb\x8d\x43\x29\x67\x9d\x49\xce\xef\x84\xf4\x38\xac\x24\x3a\x79\x27\xad\xc3\x09\x21\xb3\x1f\x87\x46\x8b\x2f\x54\x4d\x12\x69\xa7\x69\x3c\xd4\x99\xb4\x3a\xa9\xac\x9d\x1a\x1a\x1a\x85\x49\x26\xa5\x6d\x43\xfc\x23\x8c\x98\xc6\xa2\x83\xef\xac\x50\xba\xf9\x18\x59\x8c\x46\x93\x27\x66\xa5\x95\x6b\xa5\xb2\x0e\xe0\xe9\xa5\x19\x82\xc1\x1b\x4d\x51\x46\xa9\xec\xa4\x80\x2f\x89\x10\xc5\xd8\x29\x0f\xa3\x3b\x02\x2e\xc7\x4a\x69\xb4\xf6\xd9\xb5\x40\x81\x15\xbb\xb1\xaf\x52\xf5\x66\x2d\xb2\x77\xfe\xb4\xe3\xb5\x69\x8e\xe3\x56\x7b\x1b\x5e\xcb\x7b\xa1\x0e\xb5\xa1\xdb\x41\xd4\xfa\xb2\x51\x9b\x96\x36\x36\x2d\x7d\x39\xd8\x7b\x9d\x9b\x30\xef\xd5\xcc\xf5\x55\x67\x26\xc5\xcf\xe9\x58\x3d\x2b\x39\xfb\xf8\x7c\xe2\xac\xec\xfe\x8f\xe3\x63\x56\x9e\x85\x59\xb7\xe1\xc2\x1b\x17\x4f\xec\x4c\x4e\xdf\xba\xee\xd4\x7b\xc9\x2f\xee\x1a\x32\xfc\xe8\xe4\x29\x29\x5b\x6e\xbe\x38\xff\xea\x5f\x56\x14\xb4\xc1\x80\xda\x05\x6b\x5f\x47\x5f\x2e\x5b\xbd\xd4\x38\xfe\x8c\x15\x6b\xaf\x5d\xb0\x10\x38\x02\x4f\xd0\xc4\xd9\x2e\x9b\x52\x51\x64\xa7\x99\x27\xb4\xd6\x05\xd0\xee\x61\x26\x39\xaf\xb3\x4d\xee\xce\x9c\x81\x72\x57\x07\x1d\x2d\x66\x0b\x6c\x9c\x3e\x32\x49\xc5\xb8\x4e\x0c\x5f\x48\xbb\xf4\x5e\xeb\x1d\x78\xf4\x17\xd6\x3d\xc1\x5a\x06\x24\x26\x07\x29\xd6\x32\x28\xed\xaf\x65\xe4\x49\x00\x19\xc5\xea\x8d\xab\x5c\xa5\x52\x99\x59\xc0\x77\x14\xb9\x33\x6b\xa0\x92\x9a\x48\x82\xbb\x99\xe8\x55\xb4\xfe\x37\xc8\x18\x87\x4a\x6b\xb9\x33\x9f\x70\x54\x5b\x7e\x59\x49\x84\x6b\xd1\xce\x7e\xa7\x1f\xa7\x72\x7d\x2e\xfa\xd9\x33\x2f\x86\xaf\x00\x6e\xc0\x0f\x44\x80\x5a\xb6\xf3\xc2\xe4\x62\x6d\xd0\xf1\x15\x74\x9a\x45\xee\xae\x8c\x76\x89\xf8\x9d\xf4\xf0\x30\x53\x30\xaf\x93\xf6\x0f\xa3\x43\xf4\xd6\xcc\x19\x2e\x84\x60\x73\x8f\x43\xc5\x9d\xf4\x50\xb6\x7d\x4c\x20\xe9\x6c\x0f\x11\x78\x0b\x75\xa6\x50\x17\x9c\x24\x33\x69\x9d\xa4\x32\x93\xa3\xbb\xd1\x48\x0f\xc5\xa7\x9e\xb7\xcc\xec\x42\xf9\x06\x0f\xe7\x58\xa0\x65\x72\x46\xd1\x44\x18\x1f\x5e\x66\x34\x9a\x7c\xdd\xfb\x33\xde\xd9\xa9\x14\xd6\x24\xb9\x4d\x77\xfa\xbb\x02\xd9\xb5\x8f\xf7\x1f\x3e\x8a\x68\xf4\xbe\x1f\x55\xfc\xe2\x94\xaa\xe9\x39\x7b\xd2\xce\xfe\xf5\xae\xcb\xc7\x3f\x4e\x9c\xbc\xa8\xc3\xa5\xef\x99\x57\x79\x1e\xa6\x5f\xd9\x52\xdc\x71\x2b\xf9\xc5\x5d\xc3\x86\x1e\x0c\xd5\x3c\x80\x4d\x6b\x0a\xa2\xc6\x5f\x26\x6e\xf4\x39\xf3\x08\x90\xda\xd3\xc5\xa3\x78\xb7\x80\x3b\xd0\x82\xf9\x2c\xff\x82\xc9\x9b\xec\x6c\x93\x30\x3a\x23\x22\x3b\xcd\x1a\x52\x25\x71\xd6\x99\x34\xc2\x4e\x48\x0f\xb1\x27\x2f\xe2\x43\x9d\x49\xae\xe8\xc4\x78\x85\x7c\x0f\xa9\xcc\x4c\x39\x49\x54\x2c\x78\x8c\xc6\x9b\x65\xf8\x13\x91\x52\x99\xc9\x49\x8e\x4b\x18\xf0\xfd\x8a\x3c\x72\x88\x46\x1f\x1d\x03\xd9\x04\x03\xb3\xad\x80\x14\x5f\x69\xb3\x5b\x08\x18\xb4\xbe\x54\x2a\x3c\x09\x3f\xc8\x13\x74\x1c\xff\xf8\x83\xe2\x9b\x45\xbf\x42\xc5\x2d\xb4\xff\xc3\x9b\x9f\x5d\x2d\x5a\x7a\x09\xfa\x25\x14\x20\x1a\x9d\x84\xf1\xbf\x7f\x19\x1c\xe8\xfd\xd6\x27\x99\xcd\x11\x01\xe8\x23\xf4\x1f\x0b\x9a\xf4\xf8\xe4\xf1\x8c\xf9\x90\xfa\xbe\x8e\xed\xbd\x19\xd5\xd3\x45\x56\x51\x73\xb0\x0e\xe4\x71\x1a\xe0\xc5\xef\xc4\x29\x1d\x93\x90\xdf\x69\xf6\x25\x5d\x5d\x9c\x75\x26\x5f\x5e\xa7\x95\x70\x98\x83\xdd\x65\x5c\x3f\x19\xcb\x2b\x6c\x72\x67\x1c\x69\x47\x96\xb8\xbf\x5d\xe8\xe2\xca\xa2\x08\xf9\x7a\xb1\xd3\x13\x32\xd3\x73\x94\x61\x50\x49\x7c\xf4\x1a\x98\xe9\xb1\xa4\x85\xec\xec\xfa\x71\x1a\x6a\xfd\xf8\xa3\xe0\x54\x18\xa1\xa1\x36\xbd\x30\x79\xc7\xb4\xdc\x9a\xe9\x67\x6f\xd7\xfd\xbb\xf6\xc0\xa1\xa6\x49\x53\xf3\x3a\x42\x9d\xbf\x7a\xf4\xf5\xc9\xf7\xa6\x6d\xab\x0a\x0d\xa8\x09\xf5\x7b\x78\xf1\x22\x3a\x7e\xb1\xa2\x22\x2a\xf1\xcd\x57\x8a\x30\xcf\x10\x5e\x2b\x41\x10\x5e\xab\x50\x30\x12\x1c\x7d\xf6\x7a\xd1\xc3\xc2\xe8\x11\x7a\x73\x20\x7b\xd8\x46\x44\x40\x7a\x94\xfd\xfa\x31\xf3\x0b\x52\x74\xd2\x41\xb6\xa5\x6c\x8f\x92\xf3\x85\x3a\x53\x98\xa2\x93\x0e\x0b\x33\x45\x29\x3a\x4d\xa3\xa1\xce\x34\xc4\x43\x2a\x6b\x77\x56\x39\x79\xb3\x54\x54\x26\x89\xc8\x68\x34\x45\x85\x49\x59\x02\xe4\xff\xe5\x62\xc3\xc1\x0f\xe0\x3f\xa3\x03\x21\x03\xcf\xe1\x67\xa9\x05\x75\xa3\xdf\x51\x4c\xb1\x3a\xc2\xbb\x87\x75\x24\x04\x18\x99\xb3\xf8\x59\x7a\x42\xeb\xc2\x68\x83\xde\x1c\xc0\xca\x33\x3c\xc2\xda\x1b\xc9\xe9\x0d\x36\x16\x0a\x6c\x2c\x38\x15\xa2\x23\x23\x68\x99\x84\x6d\x98\xc4\x14\x26\xb8\x57\x12\x48\x65\xed\x42\x47\x17\x57\xe6\xcc\xc1\x95\xae\xe1\x06\xe3\xff\x52\xa9\x9e\xe2\xc6\xfc\x81\xae\xad\x19\x20\xc0\xa7\x69\x1f\xd9\xdd\x4f\x76\x24\x97\xab\x0e\x02\x52\xe0\x05\x86\xf6\xd6\xa1\x0d\xcc\x56\x7b\x84\xd1\x01\x7a\xb3\x92\x15\x9a\x6f\x04\xee\xeb\x73\xf9\x08\xe7\xa5\xc5\xb6\xbc\x74\xbb\x8a\xcf\x13\xea\x4c\x32\x45\x27\x2d\x0b\xa3\x29\x3d\xae\x02\x11\x44\xd0\x7c\xd6\xf0\x6a\x15\x36\xc6\x43\x6b\xba\x9a\x1a\x98\xa6\xb6\x95\x62\x3e\x33\x5f\xcd\x25\xab\xed\x32\xd5\x26\xe6\x5f\x16\x37\x91\x6f\xe5\xb3\x18\x2c\x3b\x3d\xa8\x8c\x9f\x91\xa4\xae\x1c\x20\xdf\xa7\x25\xaa\xf9\xe6\x01\xf2\xc5\xb9\x6a\xde\x3d\x30\x1a\x4c\x00\xcf\x41\xc1\xff\x61\xb6\x3a\x21\x8c\x9e\xae\x37\x8f\x61\x17\x68\x72\x04\xa4\xd3\x06\xc3\xbd\x8b\x61\xfc\xf0\x78\xc5\x20\x00\x78\xf4\xc4\x08\x53\x80\xa8\xd3\x94\xa2\xe8\x34\xcd\xf8\x5f\xa5\xa9\x03\xc2\xa5\xb2\x36\xf7\xc9\xd3\xb1\x2b\xff\x7f\x90\xa0\x1e\x74\x01\xff\x47\x79\xea\x87\x03\x96\xf6\xbf\x99\xab\x5e\x3b\x30\x2e\x20\x7b\x50\x4f\x17\xa5\x17\x04\x81\x40\x10\x01\x62\x19\x0f\x2e\x80\xb1\x46\x94\xa0\xd3\x06\x8b\x67\x07\x86\x47\x0f\x0f\xa3\x47\xeb\xcd\x3a\x76\xdd\xa2\x23\x20\x1d\x17\x46\x0f\xfd\xc8\x14\xa2\xc0\x3d\x88\x76\xe0\x78\x46\x66\xe9\xf4\x8a\x4e\x5a\x1f\x66\x32\x0e\x8e\x97\x37\x86\xf1\x6e\x42\xa4\x32\x2b\x52\x1e\xed\x27\x35\x45\x8f\xc6\xce\x0b\x63\xa1\xe0\x20\x38\x79\xb4\x9b\x94\x56\xfe\x37\xd0\xf2\x9e\x22\xfe\x3f\xc2\xcc\x1b\xc4\xcc\x3f\x0b\x39\x8f\x7f\x7d\x80\x60\xb1\x5c\xc9\x55\xbc\x7b\x9c\x5c\x0f\xb2\xe8\x79\x58\xae\x56\xe8\x3c\x3b\xc0\xbc\x3f\x23\x57\x3b\x00\x3d\x5a\x20\xa1\xf5\xcc\x77\xa3\xa2\x57\x8c\x6d\xee\x6a\x5f\x4c\xba\x2e\xa5\x47\x1b\x4d\x5e\x4c\xc8\x1e\x6d\x04\x26\x47\x9b\x2c\xfb\x21\xe9\xd1\xee\x8c\xf7\xf8\xe7\xf1\xf4\x9e\x26\xcb\x67\xa3\xea\x41\xe1\x00\x51\x3e\x0b\x5b\x8f\x97\x3a\x50\x47\x21\x10\xf7\x74\x51\x99\xbc\x0e\xe0\x09\xd2\x59\x7e\x70\x2c\x47\x17\x46\x3f\xc5\x64\xa7\x59\x26\x72\x67\x2c\x8c\x8c\xc7\x96\x0b\x08\x3e\x32\x29\x15\x38\x82\x30\x29\x05\x52\x19\xed\x6c\x04\x26\xca\x1d\x1f\x74\xb4\x48\x6a\x82\x4a\xa3\xd1\x24\x96\xb1\x29\x38\x17\x29\x86\x24\x37\xd8\xcb\x00\x6a\x0c\x1a\x01\xb4\xaa\x50\x80\x78\xea\xf9\xcc\xd3\xb7\x77\x55\x1d\xf3\x82\xbf\x5a\xae\xfa\x91\x5a\xb5\xe5\xfb\xf3\x77\x77\xa2\x9f\x3b\xb2\x2f\xc5\xb4\x84\x18\x5b\xf6\x17\xac\xa9\x86\xf7\x1b\x6b\x90\x84\xba\x70\xbc\xe6\xe3\xb5\x61\x38\x47\x5d\x8c\x14\xe4\x41\x5c\x0f\x3c\x0e\x60\xb3\x88\xd7\x59\x15\x66\x22\xb8\x02\x60\x1e\x86\xd6\xc2\xc0\xed\x72\x1e\x06\x31\x05\x26\x42\x85\x2b\x65\x68\x27\x69\x1b\x90\xc8\x31\x75\xb0\x0c\x53\x07\x93\xae\x4f\x19\x5e\xe0\x96\xbd\x67\xda\xdf\x7f\xed\xd5\x64\x4f\xf8\x99\xa5\x53\x43\x7c\xe3\x89\x24\xc7\xdf\xd9\x81\x2c\x27\xde\xdd\xd8\x03\x32\xfe\xcb\xb4\xa3\x7a\x3d\xfc\x69\x7f\x39\x02\xce\xf7\x5b\x8f\xfd\xbe\x25\x91\x8b\xd9\x78\xcd\xfc\xf3\xf8\x2e\xe0\x1d\x6b\xcc\x26\xb2\x47\xaf\xa3\x25\x61\x26\x29\x1f\x07\xfc\x76\x3c\x11\x56\xd4\x3e\xe5\x33\xc9\x21\xac\x7f\x15\xb1\x34\xea\x18\x10\x65\x10\x66\x08\x91\xa4\xdd\x51\xe4\x34\x80\x19\xc2\x51\xe4\x84\x4f\x4a\xd2\x46\xad\x0e\xc8\x3e\x48\x29\x1c\xa0\x9f\x44\x6a\x03\xf2\x73\xee\x43\x02\xc1\x11\x40\x18\x34\x02\x7b\xd6\x87\x9b\x2d\x1c\xe1\xc3\x1c\x35\x11\xa8\xee\xe5\x79\x48\x62\x39\x1e\xf8\xba\x9a\x1a\xd6\x87\x5f\x89\xef\x96\xf2\x81\x1b\xf0\x02\x6b\x59\xbe\x02\xd6\x41\x73\x10\x74\xb2\xfc\x0e\x62\x3d\x13\xc8\x7a\xf0\xed\xf3\x3e\x7d\x33\x68\x52\xa8\x33\x49\x9c\x3b\x69\x09\x97\x41\x93\xe2\x1c\x10\xa6\x71\xe0\xca\x6b\x68\xa9\x94\xf6\x30\xd2\x12\x19\x17\xae\xb1\x39\x16\xe6\xbb\x3d\x67\x83\xb5\xc5\xcb\x46\xd7\x60\xd0\x08\x58\x8a\x86\x6a\x96\xa1\xa1\x73\x8f\x4a\x34\xab\x23\x67\xe3\x6e\x38\x95\x99\x96\x8d\x94\xa1\x0a\x73\x32\x3c\xe9\xb8\xb9\x76\x71\x35\x95\x59\x53\x03\x48\x76\xcd\x05\x41\xc0\x05\x78\x80\x00\xf0\xc5\xe0\xab\xee\x16\x46\x0f\xd1\x9b\xe5\xac\x19\xf2\x61\xb9\xee\x7a\x97\x5f\xc2\xec\x28\x05\x4e\xa5\x5b\x41\xa2\xb0\x4d\xd7\x28\x6c\xa4\x77\xff\xff\x52\x09\x07\x11\x87\xc3\xf0\x2c\x95\x18\xdc\x80\x0d\xaa\x25\xcb\x06\xb9\x97\xec\xaf\x32\x03\xfc\x27\x4e\x77\x18\xdf\x5e\x0b\xc2\x18\xcf\x7e\x70\xed\xd1\x30\x51\xbf\xd9\x8b\x95\x72\xa0\xad\x70\x7b\x80\x1a\xb9\x43\x9d\xc9\x47\x81\xe1\xa9\x07\x6a\x54\x7b\xb0\x8b\x58\xa8\x33\x0d\x51\x74\xd2\x43\xc2\x4c\xc1\x0a\xb6\xaa\x1b\x33\x85\x38\xb8\x1a\x8d\x26\x89\x54\xfa\xdf\x54\xae\xc1\xc5\xf3\x14\x7d\x4b\x1b\x20\xa0\xc1\x95\xef\xeb\x81\xf6\x1c\x73\xd7\xf2\x2a\x04\x41\x98\xb3\x2a\x00\x44\x80\x65\xbd\x4c\xdb\x36\x86\x6d\x26\xee\x1f\xae\x37\xab\x59\x29\x05\xdb\xea\x8b\x39\x5a\x4c\x2f\xa8\x63\xf4\x8e\xd6\xb0\x05\xdc\xdc\x41\xa9\x74\xc4\xb4\xdb\xf8\x9a\x24\x90\x89\x79\x28\x47\xa9\x1b\x0e\x9f\xdd\xa4\x1c\x5f\xde\x1f\x90\x65\x0f\x2e\x84\x67\x50\x65\xc3\x91\x03\x24\xf1\x07\x14\xd9\x64\x7f\xc5\x01\xec\x9d\xf6\x8f\x94\x86\x77\xcf\x26\x93\x17\xec\xd8\xb1\xf1\x0d\x92\x9b\xe0\xe9\x32\x11\xf5\x97\x49\x2f\x4b\x36\x1d\xc2\x6c\xd1\x40\x45\x27\x1d\x18\xc6\x88\x09\xcb\x46\xe3\xc5\xc4\x7b\x52\xa3\x91\x0e\x94\x9a\x28\x37\x63\x3f\x01\x3d\x83\xed\xfa\x69\x97\xd7\x83\x72\x5d\xef\x1e\x18\x2d\x3f\x8d\xe2\x9a\x1c\x31\xd0\x87\x62\xf5\x04\xf3\xb1\xbb\x02\x35\xc8\xe8\xaf\x25\xde\x64\xa7\x59\xa5\x74\xa4\x9c\x75\x26\x55\x2f\x94\x15\xa7\x20\x1e\x2c\x03\x3b\xbe\xde\xf7\x10\x63\x55\x50\xb0\x54\xcf\x4a\x29\x1b\xf4\x7a\xab\xfa\xc0\x00\xf5\x51\x08\x60\xd0\xf0\x0d\x1a\xd6\xb1\x04\xfd\x57\xff\xf2\xc5\xa6\x93\x50\x18\xd5\x4d\xf3\x35\xe4\x24\xde\xa9\x06\x33\xfa\x65\xb0\x25\xbf\x7c\x1f\xba\xff\x32\xe2\x5e\x44\xc0\xa5\x8f\xd1\x2f\xdc\xbd\xf4\x8f\x94\x06\xf3\x9f\xbb\x02\x1f\x30\xb3\xff\x0a\x7b\x09\x7a\xe7\xd3\xdb\x0d\xca\x2d\xae\x1b\xbb\xa2\xb8\x88\xde\x4d\x2c\x95\x99\x99\xf9\x78\xf5\x99\x90\x97\xaa\xff\x4d\x9f\x7d\xc8\xce\x4c\x88\x8d\xe8\xd9\xc5\xaa\xfd\xf5\xe0\xa5\x4f\x4e\xad\x5f\xb5\xba\x3d\xc0\x72\x8b\xef\x47\xe8\x88\x55\xcb\xd6\xd2\xec\x02\x7d\x7c\xe1\x2d\xd4\x7c\xea\xcb\x33\xa5\xdb\x2f\x1c\xf7\x32\x27\x96\x94\xd1\x00\x00\x9e\xdd\xbe\x65\xd6\x23\x18\x44\x83\x5d\xcf\x5e\x13\x7a\x68\x18\x1d\xa9\x37\x6b\x59\x85\x0d\x8d\x80\xb4\xc1\x7e\x8d\x98\xb9\xf8\x2b\x3a\x69\x7f\x36\xa9\x17\xae\xe8\xa4\xc3\x25\x26\x0f\x6e\x13\x8f\x80\x3a\x93\xaf\x58\x2a\x33\x29\x55\x46\xa3\x49\xc7\x6d\x67\x7c\x23\x14\x2e\x35\xb9\x29\x8c\xff\x93\xb5\x7c\x8a\xfe\xfe\x89\x25\xfe\xe7\x9f\xda\xe7\x7d\x16\x9d\xd8\xdb\x5f\xa9\x79\x76\xfb\x9c\xd1\x81\x20\x10\x05\x0e\x3c\x5b\x0f\x98\x33\x58\xaf\x37\xfb\xb1\x32\x0c\xb1\xb5\xaf\x70\x7a\xa1\x86\xdc\x21\x60\x53\x11\x66\xd3\x0f\x67\x36\x7d\xb0\xa2\x93\x0e\x0e\x33\x0d\x57\xb0\x78\x4f\x6a\xab\x2c\xe9\x21\x52\x76\xf3\x07\xcb\x4c\x14\x13\x09\x0c\x97\x62\x00\xd1\xff\xae\x1e\x3d\xd3\x16\x0c\xae\x5e\x13\x9f\x62\x11\x06\x2a\x1c\x31\xb5\xbf\xec\x48\x20\xeb\xe9\xa2\x56\x0b\x82\x80\x17\x08\x04\x7a\xb0\x8d\x63\xdf\xa2\xc8\xce\x36\x85\x35\x16\x70\x10\x7a\x2a\x9c\x59\x84\x27\xff\x30\x3a\x5c\x6f\xf6\x65\xe5\xa6\x8b\x80\x74\x64\x18\xed\xfd\x11\x17\xa0\x62\x0f\x46\xa5\xec\x6c\x0f\x55\x89\x84\xdc\x1d\x5a\x98\x29\x54\xd1\x69\x8a\x62\x82\x2d\x6f\xa9\xcc\xa4\x10\x1b\x8d\x26\xd1\x50\xa9\xac\x4d\xa0\x0b\xc7\xd7\x03\x42\x0a\xe7\x41\x4d\x62\x07\xa9\xcc\x24\x65\x24\xa9\x90\x62\xee\x06\x36\x7e\x00\x72\x8d\x55\x34\x98\x05\x99\xd5\xc2\xa7\x05\xa1\xb2\xb5\x47\xd2\x3e\x85\xaa\x50\xcb\x3e\x0d\x31\x87\x68\x6b\x9c\x7f\x60\x42\xd8\x3b\x17\xfe\x0d\x5d\x2e\xa2\xa6\xae\x2b\x50\x3c\x30\x04\x35\x8d\x08\x84\x2a\x28\x6c\xc8\x38\xf9\x7e\xa0\xfb\xfe\x24\xf4\x77\xf4\x04\x7d\x84\x92\x3e\x1e\x2c\xfe\x04\x8a\x9e\x2e\x72\x22\xef\x1e\x27\xab\x1d\x00\xe3\x21\x98\x48\x41\x67\x9b\x9c\xd1\x31\x67\x41\xa7\x59\x28\xf0\x90\x3b\xeb\x4c\x42\xc1\x1f\xc9\x8a\x71\xee\xf8\x11\xf8\x4e\xd1\x35\x82\x0e\x95\x98\x1c\x44\x9d\xb4\x43\x98\x29\x48\xaf\xd7\xf7\xca\x4b\xee\x6c\x34\x9a\x42\x19\xd1\x30\xe2\x02\x26\x01\xc9\x4a\xcb\x59\x28\x95\x99\x5c\x5c\x8d\x46\x5a\x2e\xc5\xa8\x73\x06\xb6\xc8\x51\x63\xd0\xf4\x0d\xdc\xb1\x96\x3d\x45\xa9\x14\x55\xab\x6b\xce\xa9\x51\x90\x1a\xbe\xbb\xa1\x68\x75\x49\x54\x6c\x5d\xce\xb5\x3b\x55\x4f\x5a\x12\x6a\x3e\x1e\x20\x28\xef\x97\x47\x9d\x7b\x6d\xbf\xfa\xd0\xce\x91\xdb\x3c\x83\xbf\xfc\xe8\x43\x74\xa1\xde\x8b\x37\x6b\x80\x8c\x08\x00\x7a\xba\x78\x69\xfc\xf3\x40\x09\xdc\xc1\x42\xb6\x3b\xdc\x44\x92\x9d\x6d\x02\x46\x9b\x84\x62\xbd\x9e\x76\x0d\x33\xa9\xf8\x6c\xbc\x26\xf8\x08\xe3\xf7\x71\xcd\x99\x6f\x4d\xfa\x41\x6c\x03\xed\xb1\xc2\x60\x00\x13\xdf\x21\x34\x14\xe2\x4f\xae\x14\x5a\xce\xc6\x9d\x02\x6b\x21\x74\x0c\xc4\x73\x87\xd6\x02\x19\x68\x73\xec\xa7\xa5\x2f\x38\x94\x85\x6e\x9d\xa6\xf5\x2e\xe3\xa3\x60\xf5\x6d\x4b\x66\x79\xe7\xe1\xa1\x39\xf0\xbf\x18\xcf\x5e\xd8\x16\x58\x78\x98\x92\x59\x4a\x2f\xa6\xd7\xcc\x22\x4e\x3c\x39\xf5\xd1\xeb\x12\x7e\x18\x17\xb3\xf4\xc4\x21\x05\xa5\xe6\x62\x96\x5c\xc0\x32\x3e\x09\xa5\xec\xf0\x09\x41\xa7\x7d\xb8\xc2\xcd\x82\x2b\x49\xbb\xb4\xed\x3f\xe6\x3f\x31\x0b\xc2\x95\x2d\xb5\x13\x48\x4d\xc0\xc9\x68\x0d\x47\xe3\x20\xa9\x97\xfb\x40\xa5\x3e\x16\x5a\x27\x12\xc8\x4c\xe4\x72\x5c\x42\xea\xda\xe8\x09\x4d\x27\x27\x38\x4a\xf8\x1e\x79\x3e\x30\xee\xb2\x65\xc2\xac\xf3\xe5\x53\xe3\xe0\x4f\xcc\x5c\xd0\x59\xd9\xa2\xec\x52\x6a\x96\xe5\xf3\xc9\x3f\x64\xc6\xff\xc3\x48\xcc\x7a\x8c\x4e\x6c\x53\xf2\x69\x1c\xa7\xe0\x35\x11\x04\x01\x25\xf0\x05\xc3\x40\xf5\xa0\xab\xe2\x13\x46\x07\xeb\xcd\xee\xac\xb6\x0e\x89\x80\x74\x88\x75\x62\xb4\x10\xdf\x14\x32\xda\xea\xa9\xc0\x2d\x03\xcc\xf9\x1f\xa8\xe8\x34\x85\xf6\x5d\x37\x8a\x9d\xb1\xb8\xcf\x94\x69\x07\xae\x15\xc0\x95\x8b\xc7\xff\xec\xf2\x0d\xae\xb3\x4f\x5b\xd1\x81\x27\xc9\xa0\xcb\x7b\x7a\xc0\xfd\x2c\xbb\xce\xd6\xf8\xa2\x76\x90\x95\x1e\x2c\xb4\xe8\x95\x8c\x5d\x40\x31\x04\xea\xac\x41\xc3\x9f\x56\x04\x4c\xc6\x48\x3b\x1b\x4d\xc1\x43\xac\x68\xdc\x7f\x5e\x31\x06\x17\xd1\xd3\x75\x85\x18\x68\x00\x9f\xa2\x38\x02\xe3\x20\xf7\x9a\x9c\x1e\xad\x06\x4a\xa0\x06\x41\x60\xde\x60\x7a\x84\xd1\xef\xb8\x0d\xa1\xfb\x3f\xd9\xd6\x51\xb1\xd0\xa0\x57\x8a\xa1\x40\x6f\xfb\xf6\x34\xa5\xf8\x29\x7c\xd7\x90\x33\x21\xb7\x12\xbb\xc3\xb6\x0f\x3b\x1d\x7e\x7d\xc2\xe0\x3b\xde\x33\xea\xfc\x68\xa5\xf1\x7a\x84\xa7\xde\x9c\xa8\x8c\x7b\x2b\x82\xbd\xc3\x65\xf4\x62\x04\x5f\x83\x73\x4a\xc3\xc0\xdc\x81\x7a\x61\xb7\x43\xac\x1b\xe1\xff\xfd\xd6\x1f\x64\xb2\xcf\x58\x5e\xd8\x6f\xbe\x4f\xb5\x0a\x03\xa6\x4c\x82\x5f\x00\xe0\x85\xd8\x6c\xc4\x3f\x01\x2e\xfc\xa1\x5d\xf4\xf6\xd8\x34\x66\xb9\x48\x42\x3a\xe3\xba\x96\x41\xed\xc5\x60\x78\x35\xae\x50\x67\x35\x1b\x12\x26\xca\x96\x77\xb6\x6b\x5c\x24\x42\x5c\x0c\xc3\x44\x50\x2e\xbd\x38\x36\x9c\x14\x63\xdf\xfb\xb9\xf9\x19\x38\x36\x12\x49\xbb\x93\xc4\x59\xae\xa3\xda\xa5\xcc\x3f\x6d\x4e\x12\xbb\x1a\x5d\xd0\x4e\xf0\x9c\x30\xb5\x02\x6c\x23\x78\x4e\x36\x7c\x77\xc6\xc9\x90\x1b\x69\xcf\x67\xd4\x35\x73\x50\x1c\x4f\x37\x3d\xbf\xb8\x2e\xeb\xc8\x57\xa6\x66\x37\x3e\x60\xb1\x39\x6e\x5d\x3c\xd4\x08\xe7\x0c\xcc\x0d\x29\x26\xce\x81\x08\xf1\x33\x74\x53\x52\xa6\xb1\x30\x1d\x19\xbb\xa8\xa1\x83\xed\xa7\xa3\x00\x50\x31\xbc\x7b\xc0\x03\xf8\x83\x70\xe8\xc7\x31\x79\x4a\xf4\xf6\x38\x36\x66\x37\x91\x94\x64\x21\x48\x69\x6d\x18\x1d\xa6\x37\xfb\xb0\x32\x0f\xb2\x75\xef\x0f\x82\x6d\xe3\xc9\x55\xab\xf9\x72\xd7\x1c\xa2\xce\xf6\x00\x89\x54\xa8\x33\x0d\x53\xe0\x56\x7e\x46\xce\x71\x21\xff\xbe\xf4\x4c\xc0\x1b\x29\xc6\x41\x90\xb0\x88\x41\x2f\x3f\xba\x6b\xed\x6c\x62\xb1\x6d\xa4\x92\x76\x67\xa9\x58\xae\x6b\x97\xe1\x4f\xb9\x74\x20\xc2\x8d\x4c\x8a\xeb\x7b\xe5\xb8\x08\xfd\x24\xe1\xcc\xe3\xdb\x7a\x9d\x3a\x08\x67\xb1\x0b\xcf\xd6\xe7\x84\x57\xc9\xd7\x53\x2a\x33\x89\xdc\xac\x17\x2d\x0a\x65\x2f\xa8\x0d\xf3\x7d\x30\x50\x1b\x0c\xc5\xc1\x16\x5c\x0c\xbe\x68\x7d\x71\x6e\x3a\x4f\x87\x86\x73\x18\x37\x96\x81\xa1\x47\x6d\x74\x85\x0d\xf5\xe6\x49\xc7\xfd\x1f\x0a\x66\x65\x57\x93\x19\x03\x16\x0e\xf7\x85\x60\xee\x38\x07\xb0\x0a\xd8\x8a\x72\x20\x2d\x62\x21\x31\x25\x9d\x26\x47\xdb\xcd\xdd\x55\xf6\xe6\x2e\x54\x4c\x83\xbe\x78\x57\xaf\xf7\x83\xc4\x74\xe1\x20\x31\x01\xc6\xc4\xb4\x56\xe8\x03\x48\xf1\xf8\x0e\x76\xe5\xce\xd6\x4a\x1b\x3d\xa9\x95\x5b\xf9\xdd\x7e\x6c\x2e\xa4\x53\x79\x1d\x1c\x1a\x26\xdb\xaf\x81\xb9\xf9\xd8\xf1\x71\x74\x6d\xb6\xf1\x89\x7a\xc7\xc7\xf5\x1e\xf4\x8e\x4f\xc2\x8d\xcf\x46\x19\x63\x1b\x9f\xf4\x4f\x8f\x4f\x6e\x1d\x9f\xf1\x5b\x4c\xc2\xd7\xbc\x7f\x75\xc7\x34\x2a\xe9\x60\xf7\x37\x96\x7f\xc1\x12\x26\x5e\x4b\x03\x80\x9f\x25\x08\x02\x0e\x5c\xd6\x79\x18\xf8\x12\xb0\x58\xd0\x20\x68\x18\xe3\xff\x8a\x84\x9d\x5c\x97\x4d\xb0\x0e\x77\x97\x48\x1d\xa0\xb3\xce\x44\x0a\x3b\x07\xa6\xa1\x43\xec\x71\x3f\x18\x53\xc2\x57\x74\xd2\x7c\x09\xad\x62\xb6\x03\x9b\x88\xc6\x59\xe8\xde\x14\x34\x3d\x2c\x82\xd6\x4a\x70\x07\x7d\x50\x18\xf3\x2d\x18\xea\x4c\x3a\x3b\x03\xd4\xe7\xc2\x95\x26\xec\x11\x52\x44\xb4\x48\xc2\x71\x13\x48\x99\x4f\xb2\x1d\x90\x22\xa9\x35\xf1\xc9\x77\x66\xc2\x41\x0f\xa3\xd1\x14\x1c\x24\x95\x99\x7c\x03\x18\x0d\x96\x8a\x38\x5e\x02\x3d\xd4\xdb\x28\x6e\x7d\xa5\x91\x01\x3a\xf8\x14\x4b\x23\x87\x7a\x88\x9b\x73\xca\xe1\x05\xf4\x21\xfa\x57\xf5\x09\x98\xbf\xe1\xa5\x57\x60\xea\x00\x9d\x55\xc1\xa8\x0e\x74\x93\xd7\x61\xa9\x43\x7b\xff\xf9\xe4\x30\x34\x14\x2c\xa5\xf8\x7d\x35\xf6\xf7\xb5\xbc\x8e\xc7\x49\xf8\xae\xa1\xb4\xa7\x8b\xb7\x9f\x77\x0f\xb8\x70\xf7\x61\xd1\x50\x08\xda\xf4\x8c\xcd\x89\xd6\xb7\x39\x03\x36\x85\xc6\x19\x9f\xc8\x28\x46\xf0\x02\x37\x67\xc6\xf8\x08\x06\xbb\x27\x63\xaf\x1d\x24\xd2\xce\x76\x52\x62\x35\xf8\x12\xf6\x9a\x4c\x24\xed\x6c\xd7\x88\x94\x42\x9d\xc9\x4b\xd1\x49\x7b\x85\xe1\x2b\x34\x91\xfd\xb5\x22\x1d\x8d\x93\x99\x52\x9c\xcc\x8c\x96\xe2\x9b\xc6\x48\xa8\x33\x45\x89\xf0\x25\x85\x7d\x87\x94\xdd\x39\xe0\x71\xc9\x06\x64\x48\x7b\x48\xda\x79\x1e\x14\x63\x73\x3c\xa8\x3e\x9c\xba\x3c\x0f\xce\xfc\x7b\xd8\x00\xbb\x29\xa9\xac\x5d\xe0\x2c\xc3\x34\xce\xd1\x7a\xa9\xcc\x14\x3c\x1c\xdf\xcf\x31\x5f\x45\xa0\xb7\x07\xa3\x77\x09\x0c\x76\xd4\xb9\x4f\x59\x25\x4f\xa8\x27\x4b\x55\x65\x1d\x8b\x2a\x9e\x3f\xde\xf4\xd5\xb5\xd6\x8e\xb6\x0b\xcb\x36\x2d\x5e\x98\xbe\x42\x05\xbd\x07\x2c\x54\xec\xd7\x27\xbf\x85\x81\x33\x17\x11\x39\x48\xeb\xb6\x77\xc7\x1b\x37\x1b\x5e\x3b\xbd\x32\x77\x66\x82\x32\x9f\xfc\xa1\xef\x7a\x3d\xbe\x4e\x25\x3d\xe9\xc0\xb1\x94\x27\x2a\xe0\xb8\x42\x3d\xc1\x43\x36\xda\xa4\xdd\xf5\x6d\x52\xc6\xe2\x28\xc8\x4e\xda\x11\x3b\x22\x6d\x84\xa3\x48\xd7\x3e\x86\x10\x38\x30\x3e\xba\x59\xec\xe2\x21\x75\xd6\x99\x24\x4a\xbd\xde\x24\x16\x76\x9a\xdc\x3c\x23\x70\x41\xa0\xad\xfc\xcf\x4a\xb6\xea\x11\x8a\x3b\x37\x3d\x24\x26\x9e\xe4\x77\x1e\xad\x90\x98\xa4\x92\xdf\x7b\xff\xb3\x7b\xa8\x89\xa7\x10\xd2\xbc\x4b\x3c\x93\xc0\x9f\xa3\x57\xe0\x49\xda\xf9\x3c\x85\x5c\xc7\x08\x5f\xe2\x21\x95\xeb\x98\xbf\x28\x99\xbf\xb4\xbb\x59\xff\xee\xc9\xfc\x9d\x04\x26\x9e\x30\x34\x14\x8e\x71\x62\xcc\x85\x44\xaa\x50\xba\xb9\x7b\x78\xf6\x6b\xde\x00\x26\x0f\x82\x3b\x88\x55\x5c\x63\x11\x89\xdd\x9e\xbe\x6c\x9e\x9e\x86\xc0\xb0\x68\x71\xcc\xd1\xf1\x6e\x45\xf9\x09\xc1\x61\x03\xb8\x49\xbf\x92\x47\x8e\x85\xde\xe8\xe2\x9a\x42\x57\x0a\xf4\xa5\x29\x05\xb0\x07\xa1\x02\x6c\x0b\x3d\xc1\x7d\x0e\x65\xc3\x45\x88\xa3\x37\xc6\xb5\x77\x08\x33\x09\xe5\x8c\xbd\xe1\x75\x9a\x1c\x25\xfd\xe4\xb4\xff\xd1\x71\x5b\x73\x8b\xc0\x8a\xfb\xa6\xb8\x74\x36\xb6\xe4\x91\xce\xda\xa8\xc6\xbf\x64\x52\xb9\xfd\x4e\x2b\x2f\xf1\x68\x81\xa4\x5d\x28\x70\x92\xeb\xda\x1d\x99\x4f\x5a\x21\x69\x97\x28\x30\x78\x15\xf3\x79\x36\xb6\xfe\xd1\x6d\x7c\x7e\x62\x34\x31\xa5\x5c\xd7\xe6\xaa\xb2\xeb\x81\xc1\x50\xc8\xb6\xb6\x21\x4e\x6c\x8e\x4e\x03\x7a\x89\xac\x1e\x24\x13\x34\x78\x1a\x69\x07\x29\x96\x9e\x80\x3d\x0e\xb5\x72\xad\x9d\xe0\x38\x59\x12\x61\x51\xc1\x23\x1c\xbd\xdb\x17\xd5\xf5\x25\x45\x9d\x78\x78\x8c\x67\xd1\xe2\x84\xe0\xaf\xe4\x31\x23\xca\x7b\xe9\x51\xdb\xd1\x5f\x5f\x2a\x72\xc5\xf8\xa2\x05\x18\x5f\xd4\x0d\x8c\xee\xed\x0f\xe5\xf0\x45\x71\x23\x39\xe3\x01\x33\x41\x30\xd4\xf5\x6f\xe2\x26\x64\xed\x94\xd0\x41\xc5\x36\xfa\xf6\xa2\x86\xe2\xe1\x44\xb9\xea\x23\xe2\x60\x3f\xf8\xd0\xfb\x07\xc7\x78\xaf\xc9\x4f\x08\x1e\x1e\x99\xea\xe9\xd1\x0f\x46\xb4\x11\x5d\xdf\x54\xec\x5a\x27\x2f\x2c\xef\xc5\x12\x35\xa3\x02\x4a\x81\xf3\xc0\xd6\xb1\xb9\xda\xb0\x44\x6d\x63\xf3\x08\x63\xbc\xa0\xc1\xc7\xe6\xc6\x8e\xad\x17\x1f\xd4\x36\xb6\x68\x3c\xb8\x64\xf8\xe0\xbb\x8e\x13\x30\xfe\x03\x34\xe2\xf4\xe1\x31\xde\x6b\x17\x8f\x0f\x1e\x1e\x19\x3c\xc2\xd1\x2b\xf5\x2c\x6a\xb5\x83\x0c\x5d\x8c\xfe\x5a\xbe\xce\xb5\x0e\x8b\x10\x03\x87\xc2\x9e\x3a\x00\xb0\xdc\xa4\x20\xa6\x97\x25\x1b\xb3\xb2\x0b\xad\x9c\x50\xb4\x13\xdb\x2d\x2a\x8a\x80\xcc\xe1\x24\x67\x46\x89\x39\x37\x25\x46\x13\x8f\xe4\xee\x09\xb5\x50\x63\xd0\xb0\xe3\xd3\x08\x34\x2c\xe0\xaa\x0c\xfd\xe8\x07\x5d\xbe\xc4\x52\x43\x6a\x28\xd2\xa2\x6f\xbb\x2f\xdf\x41\xfe\x84\xb9\x91\xc8\xc4\xf2\x6a\x68\xb4\x24\xdb\xc9\x09\x00\x2c\xa7\xbe\x63\x81\x03\xc6\xc2\xfb\xc3\xb1\x68\x31\x5e\x2d\xd4\x43\x3d\x3b\x96\x64\xd8\x88\xbc\x1f\xdf\x66\x65\x54\x8c\xbc\xd0\x7f\xfe\x71\xea\x2c\x6a\x85\xbf\x54\xc0\x3b\x8c\x6c\x50\x58\x05\x72\xe2\xb0\x54\x09\x30\x07\x00\xaa\x96\xd7\x01\x44\x40\x06\x36\x81\x36\x21\xcb\xce\x6c\x72\x16\x76\xd2\xe2\x08\x1b\x65\x3d\x29\x11\x32\x03\x72\xd1\xe3\x73\x9e\x8a\xb0\xb2\xbd\x39\x2a\x70\x8b\x8a\xb5\x6f\xd4\xca\xea\x56\xf3\xa8\xd2\xba\x0b\xc5\x5c\x53\x31\x2d\x96\xb4\x53\x62\x1e\xa6\x12\xe7\x31\x67\x33\x25\x60\xc1\x51\xb1\xb1\x91\x38\xdb\xbc\xfe\x21\x1a\xbd\x5c\x0f\x35\x8c\x99\xd7\xe8\xe5\x5a\x3f\xfe\x1c\x18\x03\xe5\x2d\x15\x1d\xe8\x26\x7a\xf3\xb3\x7f\x5c\x80\x6e\x75\x2b\x9a\xdb\xde\x86\xa5\xf7\x7f\x21\xf2\x1f\x27\x5d\x7e\xa7\x93\x90\x1d\xb1\x72\x07\x74\x51\xd7\xf8\x0a\xa0\x00\x1a\xb0\x1c\xe0\x53\x93\x25\x07\x57\x59\xaf\x9a\x7d\x04\x9d\xb4\x28\xcc\x4a\x2b\xaf\x94\xe3\xe4\x2e\xe3\x98\x38\x39\xe3\x62\x64\x8c\xa6\x27\xc5\xb8\x2d\x26\x67\xa5\x54\xd6\x4e\xc9\x54\x98\x64\xc1\x49\xda\x26\x76\xf1\x34\x1a\x8d\xb4\x88\x71\x18\x80\xc9\x47\x25\x95\x99\x81\x80\xef\x22\xee\x53\xc8\xce\x76\x60\xda\x4a\xd6\xed\x32\x49\xd9\x3b\xfe\xb3\xff\x62\xba\xa3\xab\x6a\x72\x3b\xea\xd8\xa3\x12\x66\xb5\xce\xdb\x76\xec\x4c\xeb\xdc\x4b\x2b\xf2\x16\xe4\x34\xe7\xc0\xec\x3b\x30\xf7\xea\xf9\xd7\x73\xe0\xc2\xdf\xbb\x6e\x16\xe5\xbd\x45\x3f\x3c\x07\x3d\x77\x2f\x5d\x75\x1c\xfd\x9d\x9b\x1b\x7f\x22\xae\x09\x09\x00\xb7\xd8\xaa\x10\x5a\xc1\x12\x73\x38\xd9\xad\xd3\x10\x77\x66\x9d\xb4\x58\x89\xdb\x28\x17\x49\x44\x04\x9b\xd5\x06\x1f\x99\xbc\x94\x18\x73\x03\xaf\x95\x1c\xfb\x5c\x2e\x4c\xf8\x21\xef\x4d\x66\x1f\x7e\x74\xce\xd6\x0c\xee\x77\xc9\xca\xe8\xc3\x16\xfc\x89\x38\xe8\x35\x0c\xc3\xc6\xa3\xfd\x24\xed\x94\x1f\xb3\x9a\x5a\xe6\x93\x04\xed\x02\xb1\xd4\x2f\x94\x23\xb1\x15\x4b\xfd\xb4\x76\xed\xbe\x5e\xbd\x65\x00\x7c\xa9\xc9\x09\x27\x32\x86\xa8\xa5\x32\x13\x70\x65\x8f\x77\xc0\x2c\x79\x6f\xa8\xc7\xee\x78\xbb\xa2\x7f\x03\xa3\x06\xd9\x70\x06\x1c\xb2\xa5\xfc\xcc\xb7\xc2\xb4\xe4\x37\x42\x17\x9e\x5b\x10\xf4\x5e\xf3\x87\x49\xf1\xaf\xaf\x6e\x7e\xf3\xf2\xa2\xec\xa5\x55\xaa\xc4\x95\x7f\xfd\x18\xa6\xfc\x00\x5d\x88\xfc\x27\x67\x7c\x03\x26\x4f\xbf\x0f\xbf\x45\x6e\x6f\x9d\x7d\x75\x7a\xea\xe9\xe6\x59\x8b\xd6\x2c\x82\xf1\xb4\x4d\x4f\xf8\x29\x7c\x05\x18\x02\xc2\x41\x3d\x68\xf3\x63\x11\x39\x30\x69\xbc\x2c\xa2\x2d\xd0\x8f\x39\xb2\x03\x5d\x1d\x74\xb4\x2a\x82\x55\x9b\x50\x01\x73\xa0\x5b\x63\x3a\x7f\x39\x4e\xe1\x60\x00\x4c\x29\x56\x1b\x5c\xac\x27\xb1\x45\x6f\x1c\x85\x89\x48\x4c\xbb\xe2\x4e\x60\x95\x84\x76\xbb\x04\x4c\x4a\xb7\xd0\x50\x88\x3f\xb1\xe7\xe3\xe8\x2f\x95\x99\x29\x17\x1f\x3f\x1d\xab\x60\x26\x99\x27\x23\x99\xd0\x40\xa9\xec\x24\x10\xba\x08\x70\x91\x98\x5d\x7f\x4d\x74\xdf\x3e\x5f\x2c\xa5\x80\xc0\xc1\x34\x6d\xfb\xa3\xfd\x73\x76\x0f\x73\x54\xb8\x4f\x6e\x7f\x24\x9e\xf6\x5c\xce\x0a\x75\x3c\x1d\x1f\x7c\xf5\x54\xc5\x31\x95\x68\xee\x3b\x2b\xab\x8e\x9e\x69\xcd\xbc\xb8\x72\x49\x6e\xee\xf1\xf9\x30\xfb\xbf\x60\xce\xd5\x39\x59\x7b\x4b\x60\xf6\x93\x9d\xe3\xc3\xa6\xcf\x2b\xaa\x86\x06\x74\xf9\x83\xcb\x25\xf9\xeb\x0a\xae\xfc\xe5\xe1\x29\xe8\xb5\x97\x51\xc2\x87\x00\x82\x5f\x7a\xba\xf8\x69\xbc\x9b\x60\x18\x00\xf2\x68\xbb\xda\x33\x81\xfd\x98\x7c\xa5\x91\xd6\xe2\x2a\xab\x97\xf6\xcb\xfb\xdd\x7f\x79\xf7\xda\xeb\x65\xcb\xf9\x53\x66\x64\x2f\x55\xcf\x3b\x9d\x1b\x72\xd5\x8c\x8e\x39\x56\xd5\xdd\x54\x5f\x3b\xfb\xe1\xba\x45\xcd\xed\xbc\xf8\x4a\xba\xee\xe0\x87\x43\xf8\x9e\xeb\x8b\x0e\x65\xcd\x5c\x52\x05\x6f\x22\xb7\x9b\x26\x18\xa3\x9d\x11\xbd\x32\x0b\x97\xa1\x15\xe2\xf8\xae\xae\xa7\x8b\xb7\x1e\xf7\xba\xf4\x1f\x83\xfd\x10\x0c\x7d\x06\xc0\x17\xd4\xb5\x9d\x78\xb9\x7d\xd3\xa6\x99\x73\x89\x86\xbc\x65\x1e\xf1\x6d\xf1\xc1\xd7\x4f\xa3\x33\xc4\xf3\x79\xc7\x7c\x0a\xb6\x6f\x9f\x36\x67\x42\x45\x12\x25\x4a\xdb\xb2\x7e\x59\xad\xb7\x50\xbc\x24\x23\xad\xb6\xbc\x0c\x1a\xd1\xe5\xbf\x5e\x80\xb2\xf4\xb4\xc4\x7d\x99\xb3\x46\xa7\x04\xaa\xf1\xfb\xbb\x50\x29\x15\xc5\xbb\x09\xfc\xfb\xbd\x5f\xe1\xc2\x35\xb7\xf6\xad\xd2\xe3\x0b\xba\xee\x58\xda\x6e\x5c\x35\x97\xbd\x24\x0f\x6c\x2e\x6c\x4d\xa5\x93\x25\xe8\xfb\x47\xea\x3b\x6f\x7c\xb4\x6a\xde\x62\xd3\xf3\xbc\xb8\x1d\xa6\xbd\x87\x6f\x05\x50\xd2\x9a\x02\xdf\x05\xa7\x99\x20\x11\xe6\x26\xeb\x6e\xed\x7d\xad\x6a\xde\xfc\xb8\x11\x6c\x3d\xd8\x41\x54\x41\x16\x51\x99\x20\xa0\xff\x3b\xf9\x02\xfc\x4e\x43\x3f\x81\xf3\x05\x07\xd9\xf9\x66\x64\x4b\xe4\x07\x57\x9a\xa7\xed\xd7\x4b\xe7\x66\xbd\xec\xb3\x6c\x7b\xd5\xf4\xd9\x13\x5f\xb2\x4e\x55\x4d\x89\x97\xce\xf0\x7f\x3e\xdd\xf2\x1d\x5c\xff\x7d\xfc\xf0\xa9\x71\xfb\xe6\xcd\xb4\xce\xb3\xe7\x62\x4f\x27\xff\x26\xaf\x03\x0c\x01\xa0\x17\xcc\x84\x6b\x84\xb6\x69\x5f\x54\xa4\x41\xde\x1f\xd9\xa4\xe5\xae\x5b\x53\xce\x32\xf5\x3c\xf3\xa2\xe0\x77\x3a\x8e\xb6\x7b\xb4\xa2\x53\x7d\x01\x4e\xba\x3d\x17\xc7\x1d\x5e\xb1\x15\xde\x44\xde\xd7\xcf\x1c\xdb\x35\xa1\x94\x0c\xb7\xc7\x3a\xe9\xe9\xe2\x13\x54\x1a\x08\xb5\xbd\x97\x03\x22\x61\x4b\x38\x08\x83\xdd\xab\x9f\x8a\x4a\xb2\xcb\xa9\x71\xdc\x4c\x63\x68\xb0\x79\xe2\xb0\xf7\xcc\x47\x9a\xc5\x85\x83\xe2\x93\x58\xd2\x47\x05\x35\x44\x2c\xbe\x7f\x0d\xb5\xbc\xdf\x7a\xa8\x2a\x21\x8e\xf0\xb2\x83\x2a\x01\x10\xa4\xf5\x74\x09\x8c\x18\xdb\x08\x70\xf8\x0c\x03\x05\x10\x67\x07\xf2\x71\xfa\x33\x97\xe6\x05\xcb\xbd\x33\x3b\xf2\x82\xdf\xe9\x78\xb9\x5d\x16\x69\x03\x6d\x78\xf2\xcf\xf8\xf0\xc3\x2b\xb7\xb0\x73\xae\xaf\x4e\x9c\xf1\x0b\x86\x6f\x00\x10\x18\x7b\xba\xf8\x85\x54\x12\x7e\x87\xfc\x19\xef\xb0\x02\x21\xec\x15\xbf\x3a\x2f\x5f\x1b\x77\x6a\xa2\xee\x96\xf9\x60\xab\x54\x62\x43\x44\xb0\xc4\x8c\xf7\x69\x5c\xb6\x0f\x1a\x50\xcb\x7b\xf4\xde\xda\xb1\x13\xa6\x61\x6c\x84\xda\x9e\x2e\x5e\x3a\xef\x26\xf0\x01\xc0\xca\xcf\x12\x0a\x6d\x04\x2d\x38\x2b\x25\xe0\x13\x94\xd6\x0f\xd4\xbe\x0f\xf3\x3f\xfb\xd7\xb9\xc4\xfc\xc6\xb4\xe3\xe8\xfb\x03\x1d\xf4\xe9\xbb\xa1\xa8\x56\x43\xe8\xdc\x75\x2f\xa3\xc7\x17\x7a\xd0\x97\x84\x3f\xa4\xa0\xe9\xa7\xf4\xfa\x30\xff\x77\xd0\xd1\xbf\xdd\xf8\xf0\x83\x7f\x37\x94\x7e\x8f\x7e\xdc\x0e\x03\xf0\x5c\x98\xf3\x37\x97\xca\x64\xe6\x62\x47\x89\x22\x86\x76\xaf\xc2\xad\x09\xd9\x0d\x50\x77\xe5\xa3\x1d\xe3\xb7\xd5\xd5\x7c\xb4\xa2\xb6\xa2\x8a\xf6\x46\xd7\xd4\xf0\x67\xd7\x51\xe8\xf7\xaf\x3e\xfa\x01\xd2\x57\xe1\xa8\xd6\x69\xd5\x29\x5b\x1f\xbf\xbc\xeb\xc8\xe1\x03\x75\x39\xe8\xb7\x9f\x7e\xc4\xb8\xef\x3d\x5d\xd4\x43\xec\xf7\xea\xc6\xb8\xcb\x1c\x96\xcd\x94\xc9\x25\xce\xb4\x33\xe1\xe2\x0c\x65\xa4\x33\x05\x20\x58\x36\x13\x92\x20\x4e\x27\x05\x7a\xb7\xb0\x79\x99\x73\x57\xc6\xe9\xc2\x87\xdb\x21\x88\xf7\xd5\xdc\xd3\x5a\xf2\xa1\x1f\x5a\x7a\xd1\xa5\x39\x67\x99\x6f\x66\x5b\x6e\xc8\xb5\xb6\xfa\x0e\xc5\x19\x9e\xa2\xa1\xa1\x7b\x6b\x7c\xf8\xe1\x82\x4a\x66\xbd\xde\x3b\x59\x5f\x3d\x62\x1e\x99\x0d\x20\x48\xef\xe9\xa2\xe2\xb1\x6f\x0b\x06\xc0\x92\xdb\x9e\x9a\xae\x26\x3d\x7c\xd1\xfb\x6b\x5c\x9a\xe2\x9f\x37\x7a\x58\x17\x4a\xbe\x02\x83\x8f\xdf\x9b\xe8\xd5\x10\xb6\x60\x05\xb3\x48\xef\xb6\xed\xad\x1d\x9f\x48\xc8\x00\x04\x85\x3d\x5d\x54\x3d\xef\x26\x08\x62\xe4\x16\x6d\x88\x0a\x85\x1c\x99\x10\xbb\x56\x7c\x4c\xd5\x24\x60\xbf\xd8\x3a\xe3\x0a\xff\xfe\xce\x92\xf5\x45\xf7\xb6\xaf\x7f\x6b\x46\xe6\xf4\x5d\xcf\x95\x35\xee\xd9\x6e\xf6\xa5\xef\x7f\xb2\x6f\xeb\xf2\x33\xa9\x97\xef\x7f\xf4\x2d\xcc\x6c\xfb\x9b\x8c\xef\x77\xb8\x60\xc3\x85\x05\xe3\x93\xca\xc6\x46\xd7\x16\xaf\x59\xbb\xf7\xf0\xbe\xd5\xa5\x06\xff\x86\xe9\x6f\x03\x08\x62\x7a\xba\xc8\x13\xd4\x1c\x10\x68\xf7\xde\x68\xab\x86\x0c\xfe\xd6\x98\xfd\x7b\x93\xa7\x7c\x6e\x3e\xbf\x35\x5e\x57\x3e\xb9\xa8\x74\xd1\xec\x12\x9f\xc2\x7d\x87\x97\x2e\x4e\x3e\xbc\xa0\xfe\xdd\x13\x57\x20\xbf\xb4\xde\x43\xa0\x5e\x3d\x79\xd7\x6b\x49\xdb\xdd\x03\xe7\xa5\x8d\x9f\xbc\x2f\x7f\xfe\xb4\xf4\xa0\xf0\xfd\xcf\xed\x65\xed\x0a\x2a\xc0\x38\x4f\x1a\x7b\xbb\x02\xfb\x79\xf9\x83\xc0\x25\x7d\x7b\x34\xde\xa7\x70\xd1\x24\xff\x61\x23\x86\x1a\x1d\xdd\x3b\xa0\x2b\xda\xd6\x1f\x37\x09\x5d\xdf\x5c\xc8\x3a\xfc\x36\xf4\x24\xd8\xd3\x84\x0a\x30\x76\x52\x50\x7f\x7b\xd2\x37\xe8\x79\xba\x2d\xb9\xc6\x04\x63\x79\x89\xc1\xe1\xfa\x34\x4f\x0f\xf3\x53\x90\x8e\x16\xe0\xd0\x8c\x89\x84\xfa\xc0\x1d\xb1\x76\x54\xd0\x82\xfd\x36\xbb\xf9\xca\x59\x86\x52\xa8\x85\x64\xff\x99\xf2\xaf\xc1\xb6\x1b\x96\x7b\x50\xc9\x04\x0f\x37\x88\xb4\x77\x50\x77\xdf\x79\x72\xb1\x17\xc1\x84\x12\x24\x9f\x70\xea\x63\x3b\x1f\xf1\xf3\xa8\x34\x3b\x9b\xcd\xce\x15\x07\x52\xec\xeb\x9e\x32\xcd\xb1\xa9\xcd\x38\xa2\xea\x66\x22\x85\x3b\xf0\x41\xab\x9b\x7a\xe0\x34\xc5\x68\x39\x13\x59\x59\x3e\x64\x82\x07\x22\x0a\x96\x53\xb6\x99\xe2\x1a\x5b\xfe\x55\x1c\x5b\x79\x30\xd6\x52\x83\xbb\x06\xd8\xce\x0e\xbe\x46\x4b\xca\xad\xf5\xbc\x69\x30\x0a\x26\xfd\xed\x53\x3e\x2c\xbe\x61\x79\x0b\x06\x5d\x42\xdd\xaf\xa2\x37\xcb\x8b\x0f\x96\xde\x79\xb0\xb5\xea\x10\xaf\xe3\xcd\x8b\xc1\x43\xe1\x6d\x3c\xc1\xab\xdb\x2c\x57\x89\xbb\xe6\x13\x2f\x2c\x05\x44\xcf\x87\x48\xc1\x4f\xa3\xe6\x00\x0f\x46\x5b\x49\xa8\xe7\x40\x79\xbd\x21\x2b\x4a\xbc\x96\x5a\xbe\x80\xb4\xd5\xb7\x31\x9e\x50\x08\x9c\x56\xeb\x26\x9c\xd7\x3e\x67\xe7\x21\x98\x78\x07\x69\xa1\xa4\xe3\xda\xd8\x9e\x57\x2e\xcd\x14\x49\x1c\x73\xaf\x2c\x59\x98\xdd\x9c\xdd\x3a\xf7\xcd\xd5\x48\xc1\x8f\xbe\xb5\x76\xf1\xf5\xbf\xf8\xc0\x72\x3c\xbf\xfd\x37\xbe\x38\x5f\x19\x8e\x02\xc8\xa4\xbc\xc2\x46\xa8\x7d\xf9\xd3\x0e\xf4\x77\x40\xf4\xd0\x00\xf0\x6f\xf3\x3a\x80\x02\x78\x03\xa0\x85\x01\x51\x91\x43\x82\xa0\x5d\x0f\xaf\xd6\x01\x32\x7b\x86\xf1\x56\xa7\x11\xc4\x25\xa8\x86\x42\xb2\x43\x6b\xb9\x93\x45\x88\xd8\xe6\x4a\x3f\x8b\x47\xd9\x43\x14\x05\x35\x35\x9b\x6b\x0a\xdb\x4e\x76\x10\x87\x17\xfd\xfd\xd3\x7f\x73\x0d\x96\x44\xa6\xa5\x81\x7c\xb4\x6e\x23\xa1\xae\x03\x64\xcf\xbd\x9e\x2e\xbe\x37\x95\x09\xf4\x60\x14\x48\xe0\xd6\x33\xda\x10\x6d\x60\xf7\xa8\x46\x30\x68\x6b\x63\xa0\x40\x2b\xc7\x0b\x2c\x26\xb4\x7e\x50\xc1\x0e\x85\x67\x73\x0b\x82\x5c\xbd\x23\x13\x43\x27\xae\x9e\x97\xf5\xcd\xbb\x70\xa7\xaa\x68\xef\xe1\xa3\xa8\x0d\xdd\xd2\x52\x2f\xbc\x98\x5c\x95\x9a\xb5\xf7\xf9\x4b\xf3\x3d\x9b\xe7\x6e\x36\x4c\x19\x1d\x34\x32\x25\x6b\x5c\x04\x5c\x74\xc7\x9c\xfc\xdd\xf2\xb5\x84\xde\xe5\x93\x1f\x26\x4d\x5e\xd4\x51\xcd\x4f\xcc\x3a\x10\xec\xbd\x69\x6e\xc3\xd9\xc5\x25\x5b\x8a\x4f\xbe\xcf\xb6\x3e\x0e\xd3\x56\xaf\x87\xb4\x26\x71\xc6\xba\x39\xc3\x88\xc7\x8d\x70\xe1\xa2\x4f\x0a\x97\x47\x8d\xbf\x8c\x39\xf1\x50\x23\xae\x69\x93\x02\xb5\xf5\x04\x02\x52\x09\x60\xe9\x9d\xfb\x97\x23\x5a\xcb\x92\xd0\xf7\x5d\x50\xfe\xed\x43\xa9\x84\x2b\x3e\xdc\xf7\x2f\xb6\xf8\xd0\xbe\x02\xe9\x14\x72\x9f\x8a\xea\x60\x12\xc1\x96\x1b\xbe\x09\x73\x3f\xc7\xe5\x86\x98\x13\x4c\x41\x2d\xa4\x32\x81\x12\xf8\xe1\x93\xc8\xda\x9f\x0e\x7b\x31\xf6\xfb\x87\x66\x07\xe7\x56\x0d\x75\x1c\xb7\x05\xb5\xb6\xe5\xb8\x69\x85\xb3\xdb\xe7\x32\x4e\xf2\xac\x73\x6b\x17\x67\xcd\x6f\x5e\x04\xb3\x6f\xc3\x85\xd7\xb2\xe7\x9c\xf8\xfd\x5d\xf8\xe1\xe2\xf5\x85\xf9\x6f\xb7\x3e\x6c\x83\xbe\x75\x8b\x8a\x1a\xb0\x5f\xfc\x00\x00\xc1\x76\x5e\x07\xa3\x15\x72\xbd\x5c\xa5\x10\xe8\x65\x38\x35\xaa\x64\xbf\x40\x2d\x19\x10\xa5\x15\x43\xa8\x7d\x60\xf6\x26\x44\xfc\xdc\x68\x58\x73\x36\x48\x04\xf9\x73\x02\x61\xe9\x5b\x96\xc5\xe7\x42\x84\x7c\xf9\x04\x14\x7e\x9e\xd7\xd1\x5d\x91\x9e\x77\x18\x8a\x0a\xc8\x39\xdd\xcd\xf5\x95\x69\x90\x9a\x4b\xae\x79\x9c\x44\xb6\x6e\xdd\x3b\xba\xa9\x5b\xc5\x9c\x81\x85\x00\xf0\x55\x54\x12\xf7\x2e\x85\x40\x1f\x4b\x40\xbd\x5c\xa5\x14\x70\xa1\x27\x19\x18\xa5\x75\x81\x50\x5b\x48\xcb\x44\x42\xc7\xa9\xe3\xa1\xf0\x8a\x96\x22\x84\x91\x8b\x7f\x7c\x13\x51\xf7\xd5\x84\x50\x3f\x0d\x7d\x7e\x97\x4a\xb2\x4c\x4b\x38\xe5\x73\x65\x2f\x11\x6d\x31\xff\x36\x2a\xe4\xf0\xbf\x09\xcf\x27\x1d\x44\x6a\xf5\xb9\xf5\xe7\x2c\x07\xad\x1c\xda\x2c\xdf\x3b\xf6\x7d\x60\xa0\x41\x65\xd0\x43\x95\x20\x10\xf7\x6a\x61\x3c\x44\x58\x70\xb8\xb0\xfa\xc1\x43\xd4\x78\xb4\xa8\x1a\xfd\x04\x6f\xdc\xe1\x78\xf3\xe1\xba\x7b\x33\xaf\x7c\x8e\xea\xef\x66\x5c\x41\x3f\xb0\x7c\xc4\xc0\xc6\x7b\x3e\x9e\x4a\xc2\xcf\x94\xdb\x3f\x53\x00\x59\x32\xfa\x95\x50\x5a\x9c\x5d\xb0\xef\x1f\xe8\xeb\x92\xec\xd5\xad\x70\xf9\x3d\x96\x90\xfe\x07\xe8\x7e\x78\x72\xd5\x51\xf4\xf5\xa1\x69\xb5\xad\x96\xbb\x1c\x29\x3d\x73\x96\x00\x41\x18\xaf\x03\xe8\xfa\xf8\xa8\xcf\xa0\xcb\xec\x7f\xaa\x54\x8f\x99\x64\x47\x9c\x59\x75\x7f\xe3\x99\x13\x98\x38\x73\x00\x28\x5f\x1f\x0a\xcd\x1a\xe8\x7d\xfa\xd4\xbb\x42\x4b\x59\x2f\x48\x1f\x73\xce\x88\x78\x66\x2a\x0d\x44\xf5\x3f\x67\x9e\xc1\x37\x19\x60\xdb\xab\xb3\x3c\x82\x46\xa6\x4f\x4d\x9a\x34\x6f\x49\x6d\xce\xd6\xb5\x0b\x06\x65\xa0\xbc\xed\x1f\x34\x25\x33\x75\x7a\xda\xca\x1d\x0b\x22\x0e\x3b\xc7\xd7\xfd\xf5\xa3\xb6\xec\x30\x2d\x32\x0e\xca\x48\x69\x16\xc6\xd6\x7d\xfb\xf3\x9b\xb3\xb0\xdc\xb7\x23\x20\x68\xe6\x75\x00\x6d\xaf\x1f\xfb\x54\x21\xc9\x35\xe4\x76\x18\xcd\xb8\xb3\xe5\xe6\xed\x83\xf3\x8a\x56\x5b\x4a\xaa\x59\xb7\x76\x70\x66\x51\x3b\x6c\x32\x11\xe6\xa4\x1d\xd2\xeb\xdb\xfe\x01\xfb\x66\x5b\x26\x7c\x27\xc7\xcc\x31\x70\x36\x8d\x9f\x3b\x2c\x78\x76\x6c\xe3\xf5\x0d\x05\xc9\xfa\x1c\xf3\x22\x64\xe4\x5c\xdd\x7e\x2c\x9c\xda\xef\x76\x1e\x52\x20\x3d\x47\x13\x8b\x73\x80\x65\xbc\xf5\x18\x3b\x07\xd8\x40\x87\x38\xae\xd4\x47\xe8\xbb\xe6\xb5\xad\xd3\x69\x28\xb7\x94\xa0\xef\x78\x1d\x2c\x63\x89\x8d\x0b\xb5\x9c\x4a\xa4\x32\x19\x5f\xb9\x97\x84\x4d\xa9\x10\x90\xb6\xc8\x2e\xc0\x8e\x6a\x6d\xdc\x92\x92\xc4\xb2\x5a\xd7\x82\xc3\xab\x3b\x52\x0f\xd6\x28\x13\x93\xd3\x5f\x79\x11\xd3\xaa\xa5\xa7\xeb\xab\xca\x52\x16\x5a\xba\x2d\xff\x82\x25\x04\x9d\x13\x1c\x37\xd9\x4a\xa0\x86\xb1\x9f\xa8\xbb\x18\xab\x0c\xd8\xe3\xf0\xdb\xbf\xa1\x0f\x16\x7f\x5a\x73\x51\x6b\x2a\xdd\x0f\x8f\x7f\x4c\x18\x2a\xc4\x4c\x2b\xfd\x30\xf9\x99\xf1\xf3\x15\x8c\xa5\xd5\x63\x97\xca\x86\x5c\xcf\xef\x7d\x01\x37\x03\x98\x64\xce\x70\x1a\x22\x15\xcd\x3c\xb9\xe0\xa5\x5d\xd2\x15\xfb\xf1\x24\xe4\xbb\x9e\x6f\xdc\xe0\x9b\xcb\x57\xa0\x65\xb1\x15\x63\x0b\xf3\xab\x2b\x75\x0b\x2c\x5f\xb2\xd3\x98\x19\xba\xab\xe8\xe1\x41\x14\xc8\x62\x28\x93\x59\x54\x0a\x10\x00\x09\x73\x0e\xda\xa0\x50\x42\x61\xa0\x18\x0a\x16\x12\x2f\x34\x36\x9b\xc3\xd1\xe1\x0b\x50\x0c\x89\x21\x14\x05\x45\x1a\x21\x95\xf2\xa4\x0d\x26\xa1\x0e\xf8\x19\x94\xba\xa6\xa9\xd4\x89\x4e\x80\xe8\xa9\x06\x80\x97\x81\xb1\xeb\xe4\xcc\x73\xfa\xc0\x61\x90\xcc\x63\x57\x12\x77\x88\xdf\xd4\x28\x23\x0e\x6e\x57\xa3\xc2\x24\xd8\xe4\x63\x79\x39\x11\xdd\x7f\x00\x0d\xdf\xe6\xba\x51\x49\x7b\xd0\xed\x1a\x74\xac\x96\x7b\xee\x5d\x9c\xb7\xd7\xf5\x74\xf1\x75\x1c\x7f\xe8\x38\x00\xfa\x34\xf6\xe2\x73\xc0\xa0\xb7\x49\x85\x55\x43\xad\x40\x6b\xb0\xbf\x6c\x62\x8e\xcc\x3e\xa7\x92\x0e\xa6\xc0\xf0\x20\x6a\x7d\xd9\xe4\x9d\xd3\x58\x4c\x89\x62\x77\x16\x53\x62\xe7\x0f\x55\xd3\x37\x06\x89\xc6\xaf\xf6\x8e\x6a\x2c\x78\xa1\xae\x6d\x7c\xcc\xca\x33\xc3\x65\x1f\xff\x40\x54\x64\xa4\x64\xbd\x96\x9d\x14\x3f\xa7\x63\x75\xd7\xa9\xf7\x26\xbf\x58\x13\xae\x3d\x92\xcc\xe1\x4a\xd0\x1f\xa0\x23\xef\x66\x66\x9d\xa8\x9a\x30\x6b\xeb\x36\xe3\xf8\x8e\xa6\xd5\x4e\xd9\xc5\xc7\xa1\xcf\xcb\x2b\x0b\xda\xd0\xc7\xcc\x1c\xdc\x01\x20\x11\xe6\x44\xf3\x62\xf6\x0e\x4e\xb9\xb0\x5d\x98\x02\x2d\x4e\x70\x69\x3c\xed\x5a\xd8\x98\x2f\x3a\xe8\xee\xb5\x33\x0b\x06\x35\xbe\xb3\xbc\xc3\xfb\x88\xf1\xe7\x0f\x50\xd9\x92\xfc\xd6\x92\xcd\x73\xb3\x9a\xbc\x8f\xae\x5d\x72\xad\x08\xfe\x5a\x05\xaf\x6d\x5e\xbb\x6b\x54\x55\x54\xce\x2b\xe7\xe0\xaf\xe8\xc0\xba\xbc\xc4\xb1\x55\xe9\x59\xa5\x38\x6e\x7b\x44\xfe\x4a\x65\x00\xb7\x3e\x71\x5b\x5f\x2a\xcb\xec\x57\xa0\xbb\xe9\x2f\xeb\xc6\x6c\xc9\x2d\xba\xb2\x62\xeb\x86\xf1\x2f\x26\x95\x9e\xb8\xf1\x10\xd6\xdc\x80\x29\x74\x52\x75\xe2\x2e\xf4\xdb\xde\xca\x6d\x5e\xaa\x5a\xfd\x27\x1c\x36\x00\x00\x54\x20\xce\x73\xcb\x99\xdd\x84\xc7\x4f\x50\xda\x40\xc6\x32\xe2\x81\x8f\xfa\x06\xc6\xfc\xf5\xe7\x26\x74\xfb\xb3\x79\xcb\x0e\x7d\xbc\xa6\x61\x6f\x21\x95\xf4\xdd\xbb\x57\xd0\x7b\x87\x6b\x36\xfc\x54\x5d\x73\x10\x10\x8c\x2d\xc5\xcf\x70\x66\xbc\x67\x9b\x14\x08\x8a\x9d\x3f\xf7\x1c\x46\x5d\xa2\xd4\x79\x0b\x60\x1c\xfb\x34\xf4\x6e\xce\x1a\xf6\x81\x45\x09\x10\xa8\x7b\x00\xbc\x5b\x0b\xff\xc1\x3e\x19\xde\x45\xe7\xf1\xc3\x11\x5d\xcb\x71\x58\x54\x51\x49\xd8\x4e\xc8\x7b\xb5\xcf\xf8\x0d\xb1\xd4\x07\x4d\x1e\x0b\x0f\xf8\xa0\x85\x49\xf0\xa4\xda\xa6\x69\x00\x02\xd0\xf3\x88\x2c\xa4\x32\x40\x00\x00\x31\x90\xeb\xa2\xeb\x73\xf5\xd2\xdb\x49\xe8\x03\x95\x0a\x4a\xeb\x97\x54\x3f\x6e\x7b\xd3\xaf\xad\xea\xc6\xda\xa6\xe9\xe3\x13\x37\x16\x4c\x9c\x71\x6b\xf1\xfe\xd6\xcd\x15\x69\x73\x7b\xc0\x97\x57\xa2\x1a\x82\x87\xaf\x5d\x54\x57\xbd\x74\x7e\xec\xb8\xa1\x63\x8b\x47\x8e\xdd\xb6\x66\xe1\x2e\x7f\xd5\x8b\x69\x27\xce\xe2\x5a\xc7\xef\x51\x3e\xbc\x8b\xc7\xe8\x02\x00\xd9\x2f\xc5\x29\x4b\xd0\x0f\x0f\x49\x18\x3e\x74\xc4\xe4\x6f\xcc\x5f\xa3\x9b\xc6\xa4\xc8\xa1\xa3\xa6\x84\xc3\x05\x38\x4b\x09\x7b\xb4\xe8\x0b\x78\x0f\xcb\x0f\x08\xfa\x24\xf1\x1e\x4e\x1a\x19\x9d\xe6\xf2\xa5\xf9\x33\xbf\xa6\x97\x66\x44\x16\xb8\xcd\x48\xa4\xa2\x9f\xdc\x7d\xe5\x80\x77\xef\x39\x1d\xc5\xfe\x8e\xb1\xdb\xb1\x9c\x8f\x2d\x20\x8d\xdf\x98\xf3\x94\x7a\x78\xfc\xbe\xa5\x1b\x86\xdc\xee\xcc\x9c\x45\x25\x21\x99\x5b\x34\xac\x47\x42\x4b\x2b\xfc\xc2\xc8\xf1\xb3\x49\x00\x20\xae\xb1\xbf\x97\x33\xef\x34\xa8\x78\x78\x53\x0b\x24\xfb\xd7\x9b\x73\xcd\xa3\xd0\xf7\xf1\xf0\x8c\xda\x52\x9b\x34\x0a\x9e\x48\x27\x92\x50\x60\x6e\xe1\x3e\x74\xab\x0e\xce\xd2\xd8\xde\xcf\x63\xf9\xe8\x98\xf7\x7b\x42\x6c\xc1\x0d\xdc\x08\xfe\x55\xb4\x07\xc6\x3d\xfa\xe6\x74\x8d\x37\x1a\xb3\x7f\xb5\xdb\x36\x2a\xa9\xfb\x16\x14\x13\xfe\x4f\x3a\x88\xfa\x35\xdd\x5d\xa4\x67\x85\x25\x9f\x9b\x43\x31\x95\x04\xc4\xf8\x19\x30\x16\x33\xcd\x41\x26\x42\x30\x7e\x73\x11\x8e\x21\xa8\x46\xfa\x9b\x4b\xe8\xaa\x83\xc8\xb3\x94\x4a\xea\xfe\xd0\xd9\x8b\xa4\x9e\x74\x90\xba\xac\xd5\x96\x66\xee\x8e\xf8\x11\x35\x8b\x9a\xc5\xe9\x5e\x24\xc7\x50\xd0\x8b\xac\x80\xb5\x0f\x3b\x8f\x07\xa0\xa3\xf9\xc2\x17\x35\xe8\xd1\xa9\xcb\x9f\xbf\xf9\xc2\xea\x82\xd3\x0b\x8a\x56\xaf\x3a\x99\x07\x4f\xdc\x84\xf1\xaf\xfc\x74\xe3\x1d\xf4\x4e\x6b\xd7\xa5\xcd\x7b\x6b\xd1\xfe\xcd\x7b\xb7\xa3\xdf\x00\xec\xf9\xa2\xe7\x11\x59\xc4\xee\xb7\x40\xbb\x66\x6b\xbe\xb5\xdb\x9a\x79\x8b\xb7\xdd\x4e\xdb\xf8\xda\x8d\x87\x0d\xe8\x9b\xf6\xd6\x51\xbb\x12\x77\x41\xe1\xde\xad\xdb\xbd\x55\x7b\xf4\x9f\xbc\x7d\x1d\xb5\x9b\x18\x7b\xe1\x04\xc6\x53\x85\xd4\x44\x3c\x56\x7c\xf7\x12\xad\x8f\xa0\x58\x35\x19\xc2\x8c\x96\x62\xb5\x73\x88\xd6\x8f\x0f\x9d\xfe\xf1\xf6\x9b\x70\xea\xc9\x7f\xbc\x73\x11\xd1\xed\x75\xd5\x90\x7f\x62\x65\xd5\x6e\x64\x39\xba\x71\x1b\xe9\x47\xe4\x5d\x78\x58\xf3\x9f\x23\x17\x3e\xa9\xf9\xcf\xee\xdc\x57\x66\x17\xe6\xe7\xbf\x96\xb9\x1e\x16\x61\x79\x10\xa0\x14\xbf\x43\x05\xdc\x80\x66\x8c\x8c\x94\xcc\x9f\xa9\x74\x20\xc7\x38\x38\x4f\x24\x1d\x48\x07\x77\x37\x17\x10\x27\x33\x1a\xc3\xc2\x74\x32\xa3\x2e\x7c\x38\x3b\x04\x99\x52\x21\x08\xb4\xbe\x59\xa9\x50\x69\x03\x20\xf1\xd1\xdb\x37\xe1\xb4\x8b\xd1\x7b\xf5\xfb\xd0\xaf\x47\x4b\x2a\xc7\xed\x8b\x27\xde\x23\xf4\x6f\x7d\x54\x8b\xba\x8f\x57\x97\x86\xaf\xcc\x5f\x6e\x5e\x50\xba\x6a\xe5\xbe\x4d\xc4\x1b\x18\x2f\xec\x2e\x70\xa7\x3a\xa8\x89\xb8\x03\x63\x28\x13\xc5\x93\x06\x15\x37\x3d\x81\x4a\x80\xb3\x04\x43\x02\xa2\x22\x0d\x2a\x3c\x4d\x03\xe4\x1b\x60\x74\x54\x64\x28\xd4\xfa\xf9\xeb\xd2\x2a\x17\x1d\xbb\x04\xa7\xb7\xc5\x97\xa4\x96\xea\x2a\x53\xde\x46\xc7\xcd\x63\x52\xab\x41\xcf\xb1\x24\x3f\xcb\x6e\x5d\x23\xb1\x2a\x64\xb7\xa5\x76\x26\xbc\x46\x5e\x5e\x5a\x90\xb8\xfb\xd7\x03\xfb\x72\x72\x97\xae\xf0\xf6\xdd\xfd\xcb\xfe\xea\x05\xdd\xb9\x4d\x99\x4e\xf0\x17\x43\x39\x12\x46\xcf\x5e\xdc\x9a\xf5\x08\x90\x60\x54\x4f\x27\xbf\x92\x9a\x83\xab\x0e\x47\x0c\x76\xb6\xf4\x9e\x2b\xbe\x81\xfd\x8e\x14\x7f\x85\x0d\x23\x9b\x18\x05\x93\x61\x88\x8e\x7a\xa1\x64\xca\xf6\xe9\x47\x5f\xdf\xd4\x11\x32\xe6\xea\x4b\x1d\xf7\x6b\x9f\xbc\x8c\x7e\x9f\x9d\x74\xab\x78\xd7\x11\x53\x5c\x5c\xf1\x05\x9d\xf2\xd3\x2e\x62\x6f\xe1\xd2\xfa\x3b\xc5\xf9\xaf\xbd\xd3\x79\xe6\xe6\xe4\x17\x6b\xc2\xfc\x8f\x24\x2f\x5b\x3a\x7f\xcd\x3f\xde\xbe\x8c\xda\xda\x1f\x2c\x29\xda\xb2\x69\xf8\xb8\xb3\x0d\xc5\x9a\x0d\x9b\xe0\xc8\x1f\xb6\x56\xa1\x77\x98\xb5\x8a\xef\x79\x44\x11\x54\x12\xf0\xc1\xb7\xe4\x12\x7f\x7c\x85\xa8\x17\xd8\x50\x2c\x05\xac\x6d\xb2\x1b\x21\xab\x7f\xf1\x50\x96\x2b\x54\xb7\xa9\x85\x4d\x73\xd7\xb8\xaa\xcd\x6a\x5d\x4b\xfc\xb4\x0d\xf7\xf7\xbd\x76\xed\xfc\x92\x19\x3b\x0e\xe4\xcd\xda\xbe\x1f\x1a\xa1\x78\xde\x84\x92\x61\xbe\x7b\xf6\xf8\x06\xee\x5e\xb1\x78\xcf\x9e\x3b\xe9\x7e\x25\x19\x25\x57\x73\xdb\x8f\x64\x2c\xda\xb7\x71\xc6\xdc\x6a\x00\xc1\x32\x22\x10\xf7\xfd\xc8\x00\x90\x47\x73\x2d\x15\x02\xad\xd5\x40\x2e\xf3\xd8\xf3\x8f\x6d\x6f\x3e\x10\x9d\x73\x5a\xb7\xe8\xa5\x37\x35\x44\xe0\x2b\x10\xec\xfc\xe2\x6a\xc2\xf8\xe4\xd4\xd5\xdb\x3f\xbb\x80\xcf\xa3\x1f\x29\x15\x11\x88\x7f\xcf\x22\xf4\x60\x29\xea\xf9\xf8\xc0\xce\x76\x3c\xed\xb4\x7e\xd5\xc6\x33\xde\xe7\xdc\x6a\xbf\xa8\xba\xf4\x31\xac\x1b\x33\x3d\x29\x65\xe3\xb6\xcf\x2f\x37\x22\xcb\xae\x2f\x01\x81\xed\x7a\x3d\x95\x84\x73\x9a\xd6\xb3\x87\xd2\x41\xee\x12\x42\x07\x8d\xdf\xc0\xa0\x57\xda\xd1\xbf\x7f\xce\xc8\x58\x9b\xb4\xef\xe0\xdb\x0b\xa8\xa4\xba\xed\x17\x6f\xa2\x2c\x22\xbc\xa4\x70\x2f\x5b\x63\x7e\x1a\x00\xf2\x22\x95\x04\x9c\x80\x92\x8b\xf5\xa3\xf5\x1a\xec\x48\xca\xd9\xb8\x5a\xc0\x9f\x08\x77\xec\xff\xe1\x47\xa8\xff\xda\x3c\xa7\x16\xbd\x72\xff\xdc\xfa\x94\xc2\xef\xbc\x79\xf0\xeb\x09\x6f\xb4\x5d\x78\xd2\x01\xcf\xa2\x44\xe2\xb3\xbd\x70\x79\x93\x14\x73\x8a\x70\xcf\x73\x06\xae\xec\x6d\x1b\xa9\x97\x63\xa7\x18\x2f\x01\x1b\xa9\x27\xd5\x96\x5d\x7c\xa7\xa9\x61\x8e\xf9\x6b\x74\xab\xb1\xe3\x62\xee\xec\xf5\x53\xd6\x95\xec\x86\x9e\x5b\x5e\x1b\x02\x1f\xa0\x04\x78\xee\x49\x47\x5d\x6d\x52\x0a\x2c\x58\xcd\xda\xc9\x22\xee\x99\x02\xeb\x7d\xa4\x56\x5e\xa4\x26\x87\xfa\xa0\xeb\xd7\xcf\xdc\x20\x3b\xf6\xec\xe9\x4e\x22\x3b\x98\xff\x5f\x4f\x17\x55\x40\x25\x01\x05\x96\x67\xdf\x2c\x12\xa1\xf1\x0b\x28\x92\xec\xea\xa8\x13\xad\xc9\x59\xb5\xc7\x73\xef\xc9\xba\xe9\x68\x79\xdb\x2d\x18\x18\x3e\x8d\x68\xb0\x24\x84\x05\xce\xcc\xd9\x52\x4e\x5c\xb1\xe8\x51\xc1\x09\x66\x1e\x06\xa0\xa7\xea\xa8\x89\xc0\x0d\xb8\x83\x11\x63\x7c\x5c\x1c\x1c\x1c\x9d\x1c\xe7\xcf\x74\x76\x82\x94\x2b\x35\x7f\x26\x70\x75\x1d\xe3\x2c\x9b\xe8\xe4\xea\xe4\xea\xe1\x6e\xb3\x09\x52\xbd\x4e\x0a\xf4\xd6\xcf\xf0\xe1\x86\x28\x9e\xab\x3e\x82\xd9\xa6\x81\xfe\x51\x3c\x65\xa0\x92\xa3\xc7\x0e\x24\x0d\x04\xbd\xdc\xb7\x72\xdd\xc3\x03\x28\x90\x4a\xba\xb9\x36\xbf\xe6\xc5\xa4\xfc\xd1\xf7\xcd\x35\xca\xdd\xe9\x4d\xeb\x7d\x17\x98\xbf\xad\x55\x39\xce\x6a\xcf\xd9\x54\xab\x22\x11\xee\x23\x4c\x02\x7a\xde\x7d\x6a\x22\x10\x01\x25\x08\x03\xc3\x39\xeb\xe7\xaa\x54\x68\xfd\x02\xa4\xbd\x5f\x21\x7e\x63\xf4\x60\xaf\x4c\x1a\x16\x1c\x39\x66\x7a\x64\x02\xfe\x27\x7c\x22\x0c\x27\xe8\x25\x7e\x71\x93\xad\x63\xd8\x90\x53\x5d\x9a\x94\xff\x1b\xbc\xeb\x1f\x1e\x33\x7c\x7a\x0c\x3c\x18\x10\x11\x33\x3c\xd5\x68\xb9\x62\xc6\x3e\xff\xab\x25\x6a\x76\x54\xf3\xdb\xe6\x96\xed\x61\x46\x45\x00\x43\x0f\x45\xd5\xf1\x32\x58\x7b\xa5\xea\x33\xd7\xbe\xd3\xb6\x07\x1c\x08\x84\x06\x82\x9e\x69\xd8\xb2\xfa\xaf\xbb\x90\x84\xa0\x67\x86\x55\x17\x7d\xb6\x1f\x8f\xe0\xef\x9b\x56\xfd\xb2\xa3\x3c\x2d\xcb\x72\x20\xa3\xa3\x56\xbe\x63\xea\xfe\x42\x9f\xc5\xe6\x1a\x79\x45\xea\xe1\xb5\xea\x05\xe6\xce\x3d\x2a\xc7\x63\x97\x0b\x36\x38\x63\xce\x67\x15\x2f\x84\xd5\x8d\xf5\x00\x50\x2a\xbc\x07\xc4\x27\x29\x91\x52\x00\x5c\x40\x5c\x44\x9c\x3e\x7c\xb8\x5c\x2f\x77\x55\xe2\x9a\x6d\xed\xfa\x8e\x14\xa7\xa1\xd1\x70\xf1\x55\xcb\x91\x13\x54\x92\xa5\x68\x5b\xc2\x82\xf9\xc4\xee\x27\x1d\x38\x66\x04\x80\x77\x87\x4a\xc2\xda\xaa\x97\xab\x94\x6c\xb1\xb7\x92\xbd\x63\x08\x88\x12\x40\xed\xf6\x53\x6e\x84\x62\x06\x14\xb6\xe9\x44\x39\xff\xb9\x82\x08\x5a\x27\x1c\x8e\xfe\x62\xa2\x92\x2c\x9f\xad\x2f\x08\x3f\x43\x68\x2c\x9f\xd5\xcc\xfd\x91\x50\x3f\xe9\x20\x32\xab\x12\x97\x58\x46\xe2\x98\xfd\x0e\x00\xe4\x51\xec\x17\x02\x2d\xd7\xdb\xaf\x11\x84\xb9\x11\x4d\xc8\x53\x4d\xdc\x75\xb7\xa4\x13\x7c\x9f\x62\x72\x54\xdd\xfa\xee\x6b\x75\x00\xfb\x5b\x5d\x64\x33\x95\x04\x54\x8c\xbf\xe5\x6a\x75\xb7\xec\x40\x01\xb4\x7e\x07\x5e\xab\x3b\x8e\x2a\x3c\x61\x29\x72\xf3\x26\x1e\x7a\xa2\xb2\x9d\xfb\x9e\xfc\xf8\x69\x54\xd3\x9c\xd2\x95\x87\xca\x61\xf8\x8e\x0a\x74\x57\x7a\xa0\xe4\xd2\x35\x2c\x97\xa0\x9e\x47\x64\x3a\x95\x81\xf3\x77\x91\x4c\x90\x0e\xb9\xa6\x1c\x6b\x62\x4d\xcc\xba\xbd\xb1\x90\xf5\x7b\x83\xe2\xb6\x9b\x76\xe7\x4d\x1f\x3b\xb5\x21\xf2\xc8\x81\x9a\xe6\x83\xef\xec\x99\x3d\x34\x23\x3d\x62\xf6\xf3\xd3\xb6\x9d\x3d\x74\x06\x12\x53\xcb\x33\x63\xc2\xe7\x4f\x89\x1e\x9b\x58\x9b\xb8\x75\xed\xe6\xd7\xc7\xeb\xa3\xe2\x22\x62\x27\xbb\x78\x0e\x39\x98\x50\x0b\x60\x4f\x63\x4f\x17\x99\x4b\xcd\x02\xbe\xd6\xb3\xde\x80\x4d\x09\xf3\x2e\x31\x14\xd8\x40\x54\xf0\x71\x31\x47\x6d\xd0\x85\x6f\xc9\xa8\xf8\xd4\xb4\xe9\x95\xb1\x45\xd5\xcf\xcf\x08\x9f\x18\x99\x91\xb9\x61\xcc\x86\xa3\xb3\x9f\x17\xee\x76\xcf\x9b\xfb\xfe\xb9\xbf\x7c\xd2\x52\x3e\xa5\x76\xf7\xc6\xd3\xee\xbb\xbd\x16\xbd\xb0\x69\x1e\x9e\xd3\x28\x00\xc8\x3a\x2a\x09\xf0\xac\x7e\xec\xa8\x6f\x88\xd5\x6a\x94\x70\x9d\x4a\xaa\xeb\x4e\x66\xef\xa1\xab\x01\x20\xc3\xb0\x3e\x70\x11\x5b\x40\x14\x5f\x00\x57\x12\x0b\x4e\xd4\x74\x4c\x73\x1a\x32\x0a\xd5\x31\x4e\x23\x51\xf9\xd2\xe4\x39\x4b\x2c\x05\xc0\xfa\x5c\x8c\x03\x2d\xc0\xcf\xc5\x21\xfa\xa8\x6f\xc8\x71\x5f\x77\x5c\x47\x3a\x5c\x09\x47\x76\x74\x27\xfd\x3f\xb1\xb7\x10\xd4\x01\xc0\x63\xce\x2c\x0f\x7b\x1b\xa5\xc2\xde\x27\x6b\xa6\x30\x63\x51\x9d\x53\x4a\x47\xb2\x28\x7b\x41\x45\x47\x45\x49\x9d\x57\xca\xe9\x94\x74\x94\x32\xbe\x6d\x7c\xcb\x69\xa2\x30\x2c\x0a\xae\x44\xb5\x11\x01\x19\xd3\x84\x44\xa1\x65\x3b\xb9\xa1\x02\xae\x44\x35\x68\x31\x3a\x0f\xc7\x0b\x8e\x60\x19\xb4\xf6\xfc\x48\x8d\x62\xef\x9f\xb8\x5b\x0f\x76\x56\xec\xb5\x50\x6a\xc4\xb0\xd8\x85\xb5\x85\x44\xf9\x57\xa7\xaf\xa3\xbb\x73\xd6\x2c\xd9\x98\x33\x8a\x5f\xe5\x5a\x0b\x1b\xe0\x7e\x66\xaa\xe8\x22\x3a\x78\x3d\x9d\xb1\x81\x19\x84\x99\x6c\xe0\xd3\x18\xc3\x14\xc8\xb9\xf8\x57\xae\xc7\xe1\x6f\x06\x11\x54\x5f\xd6\xa0\x45\x37\x1b\xbe\x7d\xe8\x2d\x80\x62\x3f\xc2\x4c\x76\x77\x53\x30\x1c\xdd\x86\x1d\x4f\x9e\xf7\xd6\x4c\x64\xe3\xa3\xf1\x84\x99\x57\xcc\x6f\x61\x63\x5f\xf9\x20\xb1\xef\x78\x62\x0b\xd1\xea\x89\xca\x62\x60\xae\x1b\x3a\x90\x00\x5f\x70\xb3\x7c\x36\x06\xfd\x7c\x1e\xca\x3e\xcc\x74\x25\xcc\xe4\x6f\xe5\xe8\x61\x29\xa2\xcb\xd9\x27\xc3\x37\x01\x09\x6e\x11\x66\xf2\x11\xbf\x05\x88\x81\x0a\xa8\x01\xf0\x64\x6f\xe1\xd9\xc3\x9e\xcf\x84\x5e\x7d\x43\xc6\x5b\xf7\xa0\x62\x4f\xd3\x9a\x9c\xf8\xe7\xfe\x76\xea\xe0\xd1\x82\xb5\x99\xa9\x5b\xdc\xb7\xe7\xac\x6a\x2c\x61\x9e\x5e\xb8\x3e\xb7\xcc\x5d\x95\x3b\x7d\xcf\x89\xd2\xec\xb9\x93\x52\x8a\xe7\x4e\x2d\xc5\xf1\x75\x2b\x61\xa6\xe2\xf8\x2d\xff\xad\xd8\xb4\xd5\xbb\x6c\x16\xf3\xaa\x59\xaf\xfa\xb4\xc6\xfd\xed\x14\x6a\xc9\xce\xb0\xbe\x6e\xfe\x9a\xc6\x12\xaa\xa2\x0c\x36\x15\xae\xcf\x4f\x2e\x8b\x4b\xdb\x73\x02\xde\x41\xad\xf8\x8d\xb3\x52\x4b\x01\xc1\xcc\x89\xd2\xf3\x5b\x80\x10\x48\x99\x19\x31\x1b\x47\x02\x34\x81\xac\x2f\xc5\xcc\x01\x5d\x79\x1f\x5d\x44\xdf\x4c\x4b\xbf\xf2\xaf\x8d\x2f\xe6\x32\x43\xff\xe0\x5d\xf4\x2d\x3a\x5d\x06\xf9\xf7\xb7\xb2\x78\xe6\x8c\x5c\xae\xf0\x5b\x99\x38\xcf\xd3\x4e\xd2\xb7\xee\x11\x6a\x6f\x54\x1e\x03\x73\xdd\xd1\xe1\x64\x58\xe6\x45\x98\xc9\xc7\xe5\xe8\x01\x23\x55\xfc\xbb\x56\xbc\xce\xf8\x77\x72\x83\x46\xae\x61\xff\x47\xb6\x7a\xc3\xf5\x93\xd0\x61\x77\xb8\x70\x14\x2a\xf7\x26\xbc\xef\x11\xe6\x72\x38\xad\x14\xfa\x97\x77\xf3\x99\xdf\x41\x40\x34\x53\xb9\xfc\xd3\x8c\x2f\x0e\x07\xe4\x41\x0d\x72\xad\x41\xc3\xa6\x0b\x21\xa8\x82\xf0\x95\xd7\xb6\x19\x0e\xe5\x2c\x3f\x99\x5b\xb1\x32\x79\xca\xe8\x9b\x6a\xb8\x74\x69\xe2\x9e\xcc\x33\x1f\x51\x41\xe7\x60\xc8\xf1\xb8\x2d\x63\x5f\xfa\xae\x66\xfd\x76\x05\x94\x56\x22\xbe\xca\xf7\x26\x37\x1f\xaa\x96\xdf\xc2\xce\x87\xbd\x57\x63\xf6\xe6\xad\x7b\x0d\x19\xb0\x35\xe3\xd8\xdd\x97\xb3\x51\x6a\x36\x23\x09\x34\x0b\x36\x75\x0b\xe1\x1d\x84\x31\x5a\xc0\x4a\xc2\x4c\xdc\x64\x7f\x27\xb7\x43\x7f\x5e\x29\x5e\xdf\xb4\x44\x0e\xcb\xa5\xeb\x8f\xe7\x4b\x08\x73\xba\x37\x29\xf3\xcc\x98\xe5\xde\xfd\xbd\x3a\x8d\xf5\x85\x6e\xc2\x16\x22\x91\xdf\x02\x9c\x98\x88\x8e\x8c\xb2\xab\xd2\x91\x47\x8d\xd5\xaf\xf2\xbb\xd3\xf0\xa1\x57\xcd\x8b\xd3\x8b\xe1\x95\x2d\xca\x83\xe4\xc3\x6e\x49\xe5\x16\x28\xe4\xc6\x99\x86\x7f\x87\xc7\x69\x60\xd3\x50\x02\xf2\xd6\xbd\xc6\x05\x39\x70\xda\x45\x34\xfe\x87\x96\xf3\x73\xd2\xf0\x48\xc7\xe4\xc3\x74\x34\xc6\x72\x1d\xde\x1b\x8b\xf2\xb9\x35\xe3\xf3\x5b\x00\x0f\xc8\xc7\x38\xc0\x49\x5f\x93\x90\x1c\x0e\x52\x40\x9c\xc7\x8d\xb9\x71\xe1\xc3\xf1\xb4\x05\xb7\xee\xd5\x9f\x83\x25\x1e\xcc\xef\xbb\x6b\x2a\x81\x75\xad\x79\x19\x78\x0f\x30\xef\x94\xdb\x42\x47\x3e\x79\xeb\xde\xed\x39\xb0\xf9\xf3\x0f\x1b\xca\x02\x51\x46\x45\xa6\x78\x27\xfe\xdd\x6f\xa4\xb0\x5b\x48\xcc\x6a\xee\x46\xc4\xb7\xd3\x2c\x0b\xf1\x33\x6e\x12\x66\xaa\x9e\xdf\xc2\xcc\xd6\x13\xda\x62\x47\x31\x24\x6f\xde\xaf\x87\x7e\x42\x65\xf9\xc1\x7b\x0d\xe8\x81\x40\xbe\x99\x79\x82\x85\x8a\x2c\x20\x66\x76\x0b\x49\x22\x68\xbe\x65\xab\x75\x0c\x54\x43\xef\xfa\x08\xb8\x41\xdc\xba\x57\x5f\xac\x27\x32\xda\xee\x1d\x2e\x8a\xb2\x34\xe1\xdf\xde\xbe\x46\xfc\xd6\x2d\x24\xa2\x6e\x77\x77\x03\x02\xeb\x4d\x05\xff\x2c\x70\x06\xee\x58\x73\xfa\x37\x23\x73\xe1\x03\x04\x9b\xbe\x3b\xd4\x7e\xfd\xc5\x6f\x0e\x9e\x79\xef\xc4\xda\xc5\x7b\x2f\x14\xe6\xee\xbb\x4c\x45\x9d\x86\x41\x8d\x77\xcf\x9f\x43\x1f\xd7\x7f\x78\x7e\xe3\x0e\xa8\x7d\xb8\x71\x1b\xfa\x02\xdb\x9a\x3b\x44\x33\xc5\xac\x9f\x2f\xae\xdc\x89\xe4\x92\x48\x06\x1c\x11\xb8\xf6\x09\x09\xf8\xfd\x22\x82\x3b\x9b\x36\xea\xa2\x78\x9e\x0d\x5e\x8e\x53\x13\x66\xae\x75\xf5\x6e\xf0\xd6\x35\x8e\x4d\xf9\xf6\x83\x23\x97\x4f\xcc\x9d\x5b\xb2\x2b\x27\xbd\x78\x2f\x79\x7f\xc3\x89\x00\x75\x7a\x82\x7c\x48\xdd\x96\x40\x75\x7c\xc2\x92\x85\xe5\xd5\x37\xe2\xb5\x1b\xd2\xe9\xab\xc7\xb7\x4e\x99\xf7\xd2\x9a\x69\xd9\x3b\xd8\x7d\x4c\xde\xe1\xb7\x00\x07\xc6\xfa\x72\xfb\xd8\x3e\x2f\x78\xeb\xde\xa3\x43\xf5\xc8\x38\x29\x75\x79\xfc\x4b\xdb\x9e\x7b\x9e\x31\xb1\xbf\x55\x6d\x41\x47\x50\x29\x41\xad\xcc\x4f\xc1\x38\x3e\xcc\x33\xee\x62\x7d\x52\x5a\x9f\xa1\x10\xc8\xb5\x64\x9f\xc7\x7c\x77\xb8\xf9\xd7\xe6\xd6\x9a\xf2\xf4\x15\xb3\xd6\x6d\x4c\xcd\x4e\x65\x1e\xb4\x79\xd3\xa3\x89\x28\x09\x1e\x44\x0b\x09\xef\xbc\x9c\x09\xf1\x00\x42\x05\x61\x26\x7f\xe5\xb7\x30\x67\x1b\xe4\x7c\x67\xa8\xf0\x24\xae\x79\xa3\xef\xcf\x1d\x3b\xcd\xf7\xdf\xb2\xa5\xbb\x9a\x5c\x89\x75\x0a\x0a\x89\x66\xaa\x8c\xdf\xc2\xbc\x15\xf6\xf7\x9f\xd9\x8d\x2c\x94\x97\x1d\xab\x70\x9a\xf1\xfc\xd2\x17\x3c\x2a\x1b\xb6\x0f\xbd\xf3\x46\x53\x03\x79\x6d\x6c\x32\x91\x61\xa9\x8b\x8d\x99\xf4\xdc\xba\x17\x89\xed\x96\xdc\x73\x6f\xd4\xb1\xcf\x0b\x21\xcc\xbc\x2e\x7e\x0b\x13\xff\x43\xbd\x5c\x21\xe0\x7c\xab\x58\x08\xd9\x04\x8e\x18\x42\x2d\x0c\x69\xf2\x10\x7a\x0d\x85\x92\x06\x35\xdf\x35\x08\x82\x37\x90\xb1\x51\x4b\x04\xaa\xd0\x3f\xeb\xf9\x2d\x96\x03\xd3\xc7\xa4\x64\x10\xa9\x96\x87\x4b\x17\xc7\xe4\x13\xd3\xbb\x85\x44\x66\xc6\xec\xe5\x46\x4b\x1d\x5e\xef\xf3\xc4\x41\x72\x19\xcf\x8c\x7b\x97\x98\xf5\x8e\x83\xf8\xde\xd7\xea\xe3\x08\x48\x6d\x94\x5d\xec\x17\x07\x05\x62\x78\xfe\x9d\x4f\x72\x9c\x96\x4c\xa9\x0b\xdc\xb7\xa3\xb8\xd8\x21\xaf\xdc\x90\x93\xb0\x70\x5d\x4b\x74\x60\x4a\xa1\x42\x94\x52\x56\x40\x2e\x2c\xab\x72\xa0\x62\x5d\xb3\xc7\xae\x49\x5a\x31\x3f\x20\x10\xc9\xd2\x46\x07\x14\xe4\x0d\x0b\xcd\x59\xa0\xa7\x04\xc9\x80\x00\x5f\x13\x07\xc9\xfd\xbd\xef\x34\xc8\xf5\x4a\xeb\x45\x98\x0b\xc4\x91\xa7\x41\x85\xfb\x27\xac\x1e\x17\x5f\xf0\xb5\x43\x5e\xf9\xf0\x45\x13\x17\xae\x7b\xfb\x53\xf6\xdd\x7b\x77\x16\x17\x5f\x4b\x29\x2b\xc0\xaf\x25\xf3\x83\x87\xc0\xef\xd3\x0c\xba\x82\xcc\xd2\x9d\xec\xbb\x0b\x27\x15\xc0\x08\x4a\x90\x3c\x99\x79\x2f\x20\xc0\x43\xa2\x99\xbc\xcc\x33\x03\x09\x7b\xeb\xc1\xbc\x4f\x85\x51\xa8\x6d\x29\x3e\xeb\xbb\x1e\xe6\xd2\xcb\x5e\x18\x17\x58\x7a\xb4\x82\x1f\xba\x26\xa6\xa0\xb8\xbe\x20\x71\x59\x7c\x6c\xf4\x82\xed\x64\xf3\xae\x9f\x2b\x97\x67\x59\xc4\x0b\x22\xe2\x2a\x0b\xcb\x97\xde\x48\x8b\x9d\xf2\x2d\x73\xce\x9d\x27\x9a\x29\xc4\x33\x83\x00\x8c\x02\xca\x48\x71\x14\x34\xf4\x62\xe2\xa9\x7a\x11\x8b\xb9\xc4\xab\xc1\xb6\x77\x0c\x62\xa8\xe1\xf6\x10\x63\xf5\xcf\x7f\xff\xc0\x89\x48\x4f\x58\xb2\xea\x85\xe2\xcd\xe3\x24\x85\xc2\xb0\xbc\x89\x73\x97\x67\xbe\x9e\xb7\x72\x9c\x76\x95\x28\x63\xf5\x9c\x25\xf5\xc3\xbc\xea\xe2\x76\x56\xc3\xd3\x91\x61\xf3\xb6\xce\x89\x5b\x3e\x96\xcc\x7a\xa9\xc6\x55\x3e\x3d\x29\x61\x8b\x31\x7d\xe2\x22\x43\xec\xb6\x8d\xbb\xba\x36\xe7\x66\xc4\xa7\x64\x2f\x08\xd2\xde\x27\x92\xe2\x92\xff\xfe\x6a\xf5\xca\x6b\x78\xad\x2f\x13\xcd\x64\x13\xbf\x93\xcd\xaf\x7a\x42\xbd\x18\x0a\xa2\xed\x86\x25\xb7\xbb\xab\x12\xc3\xcb\x5f\xd4\x07\x0c\x73\x98\x7a\x20\x77\xe5\xfc\xd6\xfc\x17\xe2\x83\x32\x62\xc7\xc6\xe5\xc5\x46\x85\x8f\x5d\x3b\x81\x30\x53\x51\x27\xff\xe6\xb6\x62\x5f\x49\x65\xe7\xe6\xec\x74\x08\xe2\x52\x16\x99\x33\x27\xa4\xe4\x9f\x67\xfd\x95\x2e\xa2\x99\x52\xf0\xbf\x06\x52\x9c\x79\xe4\x64\x1d\x8d\xf1\x74\xfa\xf6\x64\x88\x61\xd7\xfc\xd6\x82\xa2\x44\x67\x2a\xe6\xd8\x17\x15\xfc\xdc\xb2\xc5\xeb\x5e\x5e\xbc\x70\xcf\xa8\xd1\x63\x96\x8e\x21\xcd\x55\x5d\x5b\xf2\xa7\xf9\xc0\xb0\x27\xb7\x16\xac\xac\x2a\xa9\xfe\xe6\x58\x5c\x4a\xfe\x29\xe6\xf9\x9d\x44\x33\x99\xc9\x33\xb3\x9e\x0b\xfb\x7c\x46\x77\x38\xce\x4a\x2b\x72\x2f\x4b\x02\xca\xef\xcc\x3b\xbd\x6a\xd5\xca\xaf\xef\xcb\xa9\xd4\xa4\x45\x2f\x44\xaf\x9e\xba\x63\xdf\x19\xa8\x0e\xd2\xc5\xad\x20\xaf\x96\xff\x73\x73\x6e\xc6\xc6\x6d\x21\x93\xa7\xc6\x94\xbb\x69\x76\xc1\x50\x5e\xb9\xaf\x6e\x0d\x9e\xc3\x4d\xa2\x99\x8c\xeb\x7d\x07\xb3\xa2\xbd\xb8\xa9\xae\x7d\x2e\x44\x0c\xd4\xcd\x7f\xdd\x95\x53\x29\x29\xec\xe3\xeb\x16\x31\x2f\x3c\x12\xa4\x1b\x53\xe0\x85\x3e\x27\x73\x37\x55\x86\x4c\x9c\x1e\x53\xee\xee\xbb\x6b\xc7\x4b\xff\xdc\x9c\x9b\xe3\x3b\x6c\xed\x5c\x1e\xb6\xfd\x8d\x44\x33\xa9\xe1\x99\x81\x06\xef\x82\x00\xae\xa0\x26\xa0\x6f\x3d\x8d\xd5\xeb\x6f\x3c\x9f\x71\x64\xc7\xb6\x85\x51\xf3\x32\xc6\x4f\x8f\x1e\xbd\xc4\x3d\x6b\x5e\x4e\xd9\xe2\x9d\xab\x0e\x96\x54\x91\xab\x9b\x0d\xc3\xe7\x2e\x58\x31\xaa\x30\x2a\x72\xb8\x36\xa4\x64\x5c\xec\xc2\x71\xa5\x31\xcb\xd8\x33\xae\x9a\x68\x26\x7e\xe5\xde\x11\xe5\x6a\xe7\x6d\xe1\xaa\x07\xdb\x36\x67\xe3\xca\xea\xf5\xeb\xd3\x66\x25\x4f\x9f\xed\x9d\x46\x67\x87\xcc\x1b\x17\xf2\xd2\xe6\xe2\xc2\xba\x82\xb6\x86\xad\xc4\x83\xca\x71\x63\x47\x0f\x1f\x59\xb2\x78\x92\x97\x77\xe1\xd8\x85\x69\x3b\x86\xe9\x17\xbd\xb0\x19\x10\xe0\x1e\xcc\x23\x6f\xe3\xbd\x1c\xc0\xbc\x01\xdf\x72\xc7\x41\x16\xeb\xd1\xba\xc9\xf0\xe9\x6f\xb7\xc3\xee\x0d\x2f\x33\x4e\x5b\xa4\xf2\x5f\x5e\xbc\xb4\x30\xf7\x2f\x4b\x36\x8c\x0b\x2c\x6d\xf0\x6d\xd9\xb3\x61\xe4\xb2\xf1\xab\xe2\x63\xc6\xcc\xdd\x0e\xeb\xb7\x78\x05\x4c\xcf\xaa\x58\xbd\x7d\x7d\xd5\x8f\x95\x4b\x33\xbb\x7f\x3c\x54\x4b\x8c\xaf\x2c\xe8\x98\x13\x97\xf6\x03\xab\x63\x95\xf0\x28\x44\xbc\x26\x26\x66\xed\x8d\xe3\xf9\x5a\x3f\xe6\x10\xad\x1c\x35\x34\x20\x22\x6a\x78\x7a\x54\x7d\x7d\x3d\xfc\x5a\x17\x1b\xe4\x3f\x74\x34\x74\x25\x1e\x59\xc4\xac\x4c\x2e\x13\x66\xf2\x28\xbf\x93\x3b\xb3\x49\x41\x9c\xd5\xd9\xb8\xfc\x45\xc3\xbc\xf0\xc5\x97\xde\x44\x6f\xdf\x69\x39\x34\x6d\x24\xa3\xe7\x28\xf9\xfa\xda\x2b\xe8\x6d\x94\x04\x53\x8d\xe8\x6b\xf6\xf7\x57\x08\x33\xcf\xc0\x33\x03\x2d\xfe\x3d\xb3\x87\x54\xd1\xfd\x48\x9f\xed\xbf\x5d\x39\x54\x29\xcc\xd9\x50\x1d\xbc\x7c\xc7\xfc\x05\x4e\x99\x0d\xd9\xce\x29\xa9\x1b\x7d\x12\xea\xb3\x9c\x26\x4d\x2f\xf7\x1b\x4f\x98\x89\x47\xb9\xab\x6a\x6b\x17\x66\xc5\xc4\xa2\xb1\xf0\xf6\xa8\xc0\xd4\x97\x77\x23\x1a\xde\x8e\x51\x67\x34\x1f\x42\x97\x98\xf1\xc2\x3c\xf2\x20\xcf\xcc\xc4\x85\xdc\xfb\xf0\xbb\x7a\xcb\xa0\x0c\xbd\xd9\xc0\xcb\xc7\x76\x38\x64\x6d\xcd\x2a\x90\xae\x72\x5b\xbb\x34\x2a\x32\x34\x60\x58\x94\xb8\x50\xac\xd3\xcd\xdc\xac\x4e\x64\x5e\xb5\xb8\x68\xc1\xfc\x61\x53\x2d\x77\x0b\x97\xc8\xcb\x95\x11\x71\x84\x76\xb2\x67\x60\x48\xf3\x5e\x74\x96\xdd\xb7\x64\x03\xcf\xcc\xfa\x14\xb6\x7d\x35\xe0\xea\xaf\x6b\xc1\xc9\xc2\xca\xa3\xd9\x6d\x85\x3b\x5e\x7e\x79\x4a\x42\x76\xe9\x84\xd8\x85\x5b\xc9\x5b\x15\x5f\x94\xd6\x57\x6e\xfd\x6c\xc3\xd1\x8a\xe9\x33\x3e\x78\x25\xe9\xf9\xbf\xb2\xb2\xaa\x27\x9a\x49\x8a\x67\x66\xce\x43\xb9\xc1\xf6\x0c\xdb\xed\xb5\xd6\xaf\xde\x7f\x6a\xea\xb2\xea\x94\x09\x33\x97\x67\x96\xec\xaa\xfd\xfb\xa9\xb5\xc4\xed\x52\xff\xf7\xea\x52\x66\xe9\x2b\xc2\x0e\xec\xbe\x87\x7e\x65\x9f\xf3\x0b\x15\x85\xc7\x26\x05\x40\x6e\xa5\xd8\xb6\x5d\x13\xfe\xe2\x79\x77\x5f\xe5\x51\x7e\x03\x7f\x42\xec\xf4\x0d\xae\x54\x54\xeb\x9d\xfa\x4a\xff\xf0\xd0\xa8\xa4\xe7\x77\xac\x03\x10\xcf\xeb\x30\x15\x85\x7f\x6b\x7f\x47\x88\x67\xd6\x25\x6c\x70\x98\x92\x30\xbd\x58\xda\xe0\xfa\x5f\x87\x76\xbc\x4c\xde\x8a\x0d\x0e\x1b\x35\x7d\xc6\xde\xf5\x27\xff\x76\x14\x10\xa0\x18\xe6\x91\x4d\xf8\xbd\x3e\xac\xf4\xfb\x58\x72\xae\x84\x88\x33\x66\xc5\x5f\x6f\x11\x1a\x96\x4c\x5c\xb0\x6e\x7e\x4b\xfe\xd6\x18\xd7\x51\x5b\xc6\xc6\xcf\x7d\x29\x4a\x1f\xb7\x76\x02\xcc\xa3\x62\x97\x8d\x1b\x51\x55\x56\xf5\x7d\xf9\xd2\x1a\xf4\x15\x91\x34\x36\xe9\xab\xc3\x71\x29\xcb\xdb\x58\x1f\xb0\x99\x38\xcd\xcf\xc2\xf1\x6c\x1c\xa1\x67\xc2\x23\x6b\x85\xbb\x92\xab\x15\x8c\x96\xdf\x72\xaa\x98\xb3\x38\xf0\xbc\xdb\x85\x54\xa1\x4e\x3d\x2c\xc1\x35\x2d\x34\x77\x01\x6f\x16\x2f\x64\x62\x4c\xeb\xd9\x62\xb4\x3e\xc4\xdd\x57\xed\xb1\xd6\x51\x31\x2d\xc3\x45\x0b\x5f\x67\x65\xf6\x39\xd1\x4c\x9e\xe5\x35\xb1\xb7\x88\x86\x3e\xd5\xa2\xdc\xb9\xf7\xb9\x4b\x76\x7d\x8e\x53\xda\xec\x72\xdf\xa4\x43\x47\xb6\x39\x0e\x5b\x91\x9a\xb9\x92\x5c\x36\x62\x04\xbc\x81\xc2\x46\x0c\x49\x7b\x65\x37\x4c\xb6\x88\x57\x8f\x98\x90\x0b\x58\xbb\x6b\x26\x3b\x79\xf5\xf8\x5e\x1f\xc8\xad\xb7\x64\x01\xec\x05\x95\xf5\x8e\x4c\xd0\x09\x6f\x4c\x53\x05\x84\x1e\xdf\x87\xce\x12\x8f\xf2\x22\xe3\x17\xcc\x0f\x4f\x9a\x4d\xea\x1b\xb3\x5d\x58\x2d\xac\xaf\xdf\x2e\x0c\x5e\x36\x2d\xab\x40\xa2\x05\x10\x7c\x45\x34\xf3\x66\xf1\x9a\x70\x7c\xd8\x6f\x8c\xfd\x47\x1b\xc8\x58\x95\xaf\x9c\x33\x1b\x72\x9c\xb8\x1d\xe4\x9c\x34\xbd\xdc\x6f\xdc\xd1\xc3\x95\xc2\xa8\xfc\x31\xbb\x86\x2e\xdf\x31\x7f\x21\x59\x10\x3f\x02\x5e\x40\xfa\xd8\x21\xa9\x2f\xef\x86\x29\x48\x3f\xd2\x2f\xa3\xf9\x10\x8c\xb5\x88\x17\xc5\x44\xd7\xd6\x2e\x62\xe4\xf2\x90\x30\x93\x87\x79\x4d\xc0\x81\xbd\xaf\x62\x8b\x61\x1e\x36\x84\x8b\x23\x7d\xff\x7e\x02\x65\xbf\xc9\x6b\x42\xf9\x6d\xab\x46\xc3\x83\xd8\x60\x40\xa0\x27\x9a\x89\xcf\x79\x66\x5c\x17\xdb\xef\x5e\xa6\xdf\xad\x8c\x5e\x15\xa5\xf1\x9d\x10\x33\xff\x70\xf9\xc2\xe2\x07\x61\x23\xb5\xfa\xe8\xf0\xf8\xd9\x41\x13\xf3\xc6\xc4\x13\xe7\x8b\x24\x61\x63\x77\x95\x16\x1f\x58\x9d\xd5\x4a\x67\x49\x56\x78\x8e\x9c\x30\x2d\x9c\xb5\x65\x25\x30\x8f\x7c\xc8\x7f\x04\x64\x60\x28\xa3\x63\x56\xf5\xe6\x92\x77\x81\xa4\xdc\xa7\x5f\x98\x8c\xb5\xad\xe4\x0b\x7f\x53\xcd\xc6\xba\x87\xfb\xcf\xbe\x1a\x37\x3f\x6c\x6a\x9e\xff\xbc\xa1\x99\x05\xf3\x72\xa3\x3c\x8d\x8b\xd7\x8d\x1b\x99\x30\x3b\x9c\x51\x3a\xfa\x70\x79\xe1\xc7\x71\x86\xb6\x83\x1d\x1e\x6a\xb4\x05\x76\xa9\xbc\xd6\xcc\x9b\x96\x55\x52\x90\x1d\x3b\x21\xfb\x73\x66\x6e\x3f\xc2\x3c\xb2\x95\xd7\x04\x5c\x00\x90\xe3\x8b\x66\x57\x55\x2c\x21\xd7\x43\xbe\xe0\x47\x9f\xf9\x45\xf5\x51\x22\xca\x31\x5a\x7e\xf7\x04\x5a\x3c\x3b\x08\xe6\xbd\xd2\x4e\x7c\x83\x0a\x53\xe7\x78\xac\x1a\x02\x2b\x2d\xde\x4d\x27\xd9\xf1\xdf\x23\x9a\xc9\xfb\xfc\x4e\xe0\x85\xcf\x80\xc8\x68\xdb\x51\x66\xad\x0d\x55\xf5\x8f\x17\x02\xa9\x7b\x7f\x79\x6d\xf9\xde\xe2\xea\xf5\x31\x33\x9e\xf7\x1f\x15\xed\x1b\xb8\x79\xce\xbb\xa6\xaa\xc6\x86\xe7\x26\xce\x5d\x9e\x8e\x7e\x24\x2f\xef\xba\x12\x9a\xb1\x66\x61\x61\xc6\x8a\x50\xcf\xa8\x40\xbf\x68\xdf\xe5\x2f\x67\xb5\x7c\x78\xb4\x32\x75\xd6\xce\xb5\xa5\x29\xe3\x38\x3f\x03\xe6\x51\x49\xbc\xcb\x18\x7f\x1d\xbf\x57\x85\xe3\x66\x95\xd5\x40\x10\x2c\x75\x35\x2f\x96\x60\x2d\x71\xd7\x0b\xa5\xf3\x73\x67\xc6\xc7\xa5\x7b\xae\x5f\x51\x50\xf8\xcd\xbd\xb8\xfa\xf1\x2f\x6c\x83\xe7\xa7\x15\xc6\x25\x0f\x0d\x71\x21\xef\xd7\x7e\x97\xb7\x68\x4e\xeb\xb2\xe7\x16\x8b\x61\x73\xc5\xf2\xad\x5b\xbf\x42\x8f\x94\xe8\x3d\x38\x42\xd9\x38\xc6\x71\x45\x4b\xee\xde\xf8\xc9\xec\xbe\x02\x30\x8f\xbc\xc8\xea\x83\x14\x97\x49\xb2\xc7\xa8\x1a\xca\xf5\x10\xaf\x15\xab\x11\x61\x10\xc2\x86\x20\x47\xbd\xca\xd7\x3b\x62\x6c\x6a\xaa\x93\xf2\x07\x1a\x6d\x0e\xe1\xab\x7d\x5d\x23\x47\x47\xa5\xa5\x39\xb9\xa1\x1f\x60\x1e\x11\x0f\x8d\x19\xa2\x65\xae\xd3\x17\x9d\x85\xb9\x96\xaf\xd0\xb9\x08\xbd\xf3\x4a\x65\xe6\x92\x2b\x88\xf5\x43\x88\x9e\x2c\x58\x44\xe6\x01\x92\x39\xe7\x54\x72\x3d\x69\xd7\x20\x4f\x34\x1c\xad\xf7\xd2\x47\xa4\xc5\x04\xf8\x87\xd7\x33\xc7\x1b\xd9\x38\x74\xf4\xe4\x61\xa3\x82\x00\x04\x54\x4f\x16\x31\x8b\xc8\x64\xd6\x55\x25\x67\xad\x16\xeb\x5a\x08\x48\xea\xe8\x16\x71\xf4\x82\x58\x63\x88\x3a\x3c\x70\x76\x99\x4f\x42\x3d\xf1\xa8\x3c\x35\x46\xbc\x5d\x7c\xb0\x0a\x99\x99\xf9\x0d\xed\x99\x41\x42\xe2\x39\xc6\x6e\x18\x06\xb7\x1b\x43\x07\xb1\x1b\x1e\x83\x9b\x0d\x00\x41\x70\xcf\x7c\xa2\x93\x78\xae\xef\x7e\x0b\xee\xdd\x6f\xc4\x73\xf6\xfb\x8d\xe8\xf9\x2b\x52\x92\x91\xe4\x31\x76\x3f\x90\xf2\x3f\xb9\x1f\x86\xfd\xd1\x7e\x40\xca\x3f\xb1\x1f\xf4\x48\x49\xfc\x44\x3c\x37\xc8\x7e\xd0\xf7\xdf\x0f\x48\x39\xf8\x7e\xe8\xb9\x81\x14\xc4\xaf\x44\x01\x1b\x6b\xd8\xc6\xcf\x75\x2a\x09\xe4\x9c\x97\xcd\xac\x85\xa1\xd9\xbf\xa5\x6a\xc7\xa1\x79\x6f\xac\x5c\xf5\x9c\x40\xa6\x5f\x36\xfa\xf9\xb1\x4b\xe3\x2a\x53\x33\x54\x48\x41\xaa\x4e\x1c\x3c\xb4\x7b\xf3\x97\x2f\x4d\x8b\x5c\xf6\x03\x21\x48\x5a\x6c\x9a\xdd\x5c\xb8\x0c\xeb\x44\x1c\x52\x93\x47\x88\x75\xac\xde\x1b\xfe\x58\xef\xe3\x9e\xa9\xf7\xbb\xfe\x84\xda\xc3\x9e\xe7\x90\x92\x94\x12\xf3\x19\x9d\x27\x9f\xad\xf3\x6f\xfc\x91\xd2\x23\xe5\x33\x95\x9e\x00\x15\x3d\x5d\xfc\x2d\xb8\x6f\x27\x72\xc0\xa9\xf0\x94\x62\x56\x36\xb4\xb6\xb9\x28\x15\xd2\x17\x4f\x95\x49\x6f\x14\xef\x08\xa8\xa0\x25\x6b\xb6\x1e\x3e\x62\xab\x5d\xdd\x39\x3d\xa7\x36\xfd\x51\xf6\x68\x53\x99\xe9\x22\x59\x2c\xfe\xe4\x87\x89\x93\x17\x9f\x84\xe9\xb1\x33\x88\xf9\x96\xa6\x69\xa3\xbf\xa2\xdb\x88\xc5\xc9\x59\x5b\x8a\x31\xc3\x0b\xa6\xea\x38\x3d\x67\xce\x39\xf8\x4e\xe1\xf2\xa8\xf1\x6f\x01\x02\x18\x39\x2e\x93\x61\xc0\x08\x80\x1e\xe2\x1d\xa5\x95\xb1\x41\x1e\xeb\x55\x10\xcc\x21\x68\x57\x4f\x65\xad\x1c\xea\x53\x6d\x6c\x84\x72\x17\xb1\x2e\x52\x91\x6f\x6c\xf3\x94\xb9\x9b\xc3\xc4\xee\x41\x91\x1e\x4b\x13\x5f\x53\xbb\x91\xb2\x08\x81\x70\xe1\xeb\x33\x77\x1e\xdb\xfa\xef\x03\xf3\xf6\x04\x88\xc6\x6d\x61\x8b\x8f\xe7\x5d\x2e\xe0\xc9\x78\xe3\x22\x21\x5f\xb8\xf6\x81\x30\x72\x1c\x7a\x2c\x12\xce\xbc\x24\xde\x90\x73\xa5\xed\x36\x3a\x72\x23\x7b\x56\x33\xcc\xe4\x4a\x90\x2f\xa0\x2f\xb8\xde\x35\x5e\x03\x5f\x01\x82\x81\xc1\x5a\xdb\xaa\xd2\xc7\x42\xc3\x53\x06\x4d\x3e\xab\x17\xd1\xc1\xcd\xcf\x45\xa6\xd3\x2b\x96\x18\xdb\xbd\x65\x6e\xed\x61\x62\xb7\xa0\x48\x8f\x65\x89\x27\xd4\x6e\xe8\xa9\x0d\x8a\x93\x0e\xed\xec\x33\x5e\xa7\x27\xa9\x03\xba\x15\x01\x80\x3d\x9e\x48\x41\x6e\xe7\xab\x41\x14\x00\x24\xeb\xce\xf6\x8e\x50\xae\x8d\x23\x7a\x8d\x97\x0b\x64\x7c\x23\xbb\x21\xe3\xc5\xff\x2a\x36\x32\x31\xdd\xbd\xd2\x49\x6e\x15\xe8\xe8\x37\x5d\xde\x53\x85\x1e\xaf\x9f\x3f\x2f\x2c\x29\x2e\x23\xc3\xdd\xed\x5f\x1e\x5d\xa9\x56\x11\x7b\x79\xad\x1d\x7a\xbc\x22\x31\x06\x5d\x56\xad\x28\x26\x36\x53\xf1\x51\x90\x2f\x84\xde\x93\xc7\x67\xbf\xfb\x4a\x60\xa5\x57\x6e\x61\x5e\x25\x7a\x91\x95\xaf\xe5\xd6\x85\x56\x25\x8b\x23\x74\x0b\x00\x41\x0c\xd6\x49\x3d\x88\x03\x80\xc4\xba\xc8\x56\xfd\xa9\xf4\xd6\x7c\x50\xb4\x41\x8f\x3d\xff\x80\x40\x52\x2b\x1f\xc2\x7c\xf0\x05\xd0\x55\xc5\x06\x02\x3c\x57\x95\xc1\x6a\xab\xf4\xa3\x2e\x64\xd6\xba\x8a\xc6\xe7\x14\x8e\x5f\xb9\xde\x09\x67\xe3\x1c\x02\x92\x03\x97\x4e\x6e\x4f\xef\x48\x7f\xf0\xd5\x3c\xf3\x02\xf4\xdb\xa9\xe5\x27\x97\x4d\xf1\x83\xa9\x26\x8b\xb6\x62\x7e\x1b\x11\xf8\xcf\xfb\x6a\xd9\xb8\x89\x09\xdb\x57\xc3\x9a\xfb\xfe\xf0\xdc\xcd\x59\xa9\xfa\xb2\xd5\xbf\x6c\x2f\x0f\x9d\xda\xa4\x4a\x7f\xa8\x45\x0b\x61\x9d\x83\x1f\x8a\x83\x0f\x02\x78\x96\xc7\xb0\xdb\x75\x06\x24\x1c\x02\x0e\x1b\x76\xbd\xfa\x37\x5f\xde\xf6\xcc\xf0\xd8\xa4\xb9\xad\x80\xe8\xb9\x06\x00\xf5\x15\x95\x09\xb4\x60\x78\xdf\x59\x30\xe3\x8f\x85\x8c\x53\xcc\xce\x20\x80\x1d\xbe\xbf\xab\xca\x55\x65\x0d\xdc\x8c\xa3\xdf\xca\xb4\x55\x33\x4a\x34\x61\xd1\xae\x4b\xb5\x25\xb9\x19\xe6\xf4\xd9\xfb\xf7\x4d\x58\x7a\x72\xd9\x0c\x5f\x98\xbe\xb8\xac\x36\x51\xc7\x4f\x4c\x5e\x70\x05\xd6\x7c\xec\x07\x2f\xb0\x25\x8e\xe1\xf9\xbb\x1c\xa2\xa3\xd7\xae\x77\x41\x0b\xe1\x41\x71\x60\x80\x23\x02\xb0\xdb\xed\x39\x24\xd5\x04\x3a\xdf\x8e\x90\xc7\x4d\x6e\x06\x44\x8f\x13\x52\x50\x31\xd4\x1c\x56\x5f\x49\xbc\xfa\x7d\x0b\xf0\x02\xb5\x7c\x17\x68\xb7\xcb\xb4\xac\x2a\x43\xfb\x9d\xf5\x0b\xa3\xa0\xdd\xd6\x52\xfe\xaa\x9f\xf6\xe3\x0a\xfe\x00\x89\x2b\xab\xaf\x1a\x37\x75\x5b\x94\x8b\x44\xa7\x57\xc0\x3b\xbd\x45\xfd\xf5\x90\x2f\xa4\x5a\x70\x5d\xff\x5d\x74\xec\xca\xf9\xca\xf0\x53\x7c\xac\x01\xfb\x11\x6f\x5c\x24\x71\xd1\xae\xb4\x1f\xc0\x9e\x26\x00\xc8\x02\xb6\xc7\xae\x77\x94\x36\xbe\x83\x3e\x3b\x8a\xd5\xe4\x59\x23\x4d\x2a\xc5\xa2\x5a\x57\xd1\xa4\xcc\xbc\xb8\xc4\xf0\xc0\x11\xe1\x65\x7f\x1b\x26\xf6\x64\xf5\xd1\x53\x3d\xf5\xe4\x22\x27\xa9\x2e\x52\x01\xf3\xa0\xc0\x01\x7e\x79\x33\x2b\x35\x44\xdc\xe0\xf4\xeb\x5b\x8c\x12\xfe\xee\x88\xb6\xc3\x07\x54\x7c\x14\x80\x3d\xfb\x01\x20\xd8\xb5\x63\xdf\x6b\x60\x37\x06\xe3\x65\x09\xc8\x81\x6f\xcd\x33\x98\x55\x0a\xad\xff\xeb\x2f\xa7\x4d\x0d\x52\x8d\xd5\xbf\x34\xd4\x20\x53\xe2\x57\x9e\x50\x7b\xa4\x98\x73\x9d\x24\xda\x28\x4f\xfc\xca\x86\xb6\x46\xcd\x3e\xa1\xf2\x02\x7a\xcc\xef\x7d\x63\x44\x02\xde\x9b\xf7\x7a\xba\xc8\x83\x54\x26\xd6\x16\xc6\x74\xf4\xf5\xec\x7c\xa0\x81\x0d\xa4\xb8\xc3\xd9\x06\x98\x8f\xc7\x14\xa4\x58\x96\xe2\xf9\xde\x6b\x27\x1a\x46\x46\xbd\x34\x33\x63\x71\xda\x7b\x93\x87\x8f\x74\x5f\xe6\x9e\x3f\xd1\xed\xb3\x9b\xe6\xd2\xb1\xc7\xa6\xbc\xf0\xe2\xfc\xd3\xcf\xcd\xf3\x83\x4d\xab\x36\x89\xa3\x27\xed\x78\x3d\xb9\xda\x5d\xf7\xdc\xb8\xd1\xe9\x0b\x89\xb0\xf1\x05\x1b\xe5\x11\x31\xc7\xda\x12\x9a\x86\x0e\x9f\x37\x65\x7c\x66\xf2\x6a\xae\x17\xbe\xa7\x8b\xe8\xe4\x8d\xc7\xe3\xb1\xda\x07\xbd\x40\x23\xd0\xd8\x09\x80\x43\x16\xea\x0d\x9e\x58\x35\x49\x36\xb6\xcb\x54\xa3\x4e\x48\xce\x94\xe6\x1b\xa0\xc2\x0b\x7d\x97\x2a\x71\xe7\x8c\x98\x97\x44\x4e\x44\x8c\x8a\x7d\xce\x6b\x71\xe0\xc6\xcd\x0e\xa1\x22\x29\xa3\x1f\x4d\x90\xcf\x87\x9e\xd3\x53\xbe\x7c\x6c\x33\x08\x53\x67\xb9\x0f\x1f\xeb\xb9\x4d\xec\xba\xae\x48\x3d\xf9\xaf\xcc\xaa\x30\x63\xfa\x1c\x00\xb2\x9c\x4a\x02\x6a\x9c\xa7\xee\xb5\x5d\x6c\xe6\xb9\x77\x5c\x50\x23\x50\xbb\xc3\x14\x6f\xb5\xff\x28\xef\xfc\x51\xe7\xe2\x92\x20\x40\x41\x5e\xc4\x41\x6f\x74\xcb\xc7\x27\xc4\xa8\x5e\x3a\xb1\x63\x6c\x12\x7a\x44\x88\x3c\xd7\xc3\x03\x0e\xfa\xf1\x90\xef\x0f\x47\x6f\xd9\x8d\xb6\x39\x46\x24\xa0\xc7\x41\xa8\x63\x0b\xeb\x5f\x5c\x45\x0a\xf2\x31\x95\x09\xd4\x40\x67\xf5\x2f\x54\x4a\xbc\x22\x2e\xc4\xc0\x53\xa7\x77\x6b\x8c\xfa\x7d\xf8\xa3\x0f\xae\x95\xc7\x9d\x9d\xbc\xf1\x65\x3f\xbd\x5c\x38\xbb\x7d\xee\x8e\x63\xbb\x7f\xae\x9b\xb3\x2b\xd8\x61\xdc\xf6\x1b\xd9\x27\x72\x5b\x67\x5d\x5c\x8d\x82\xa8\xca\x87\xb7\x13\x9a\x02\x86\x6f\xa8\xbe\x93\x50\x98\x7f\x8d\xfe\x1b\x3a\x7c\x69\x7e\xe6\x09\x98\xf5\x90\xdb\x05\x9f\x01\x5b\xee\xc3\x9b\xad\x9d\xb6\xcf\x2d\xdd\x6c\x7c\x35\x0e\x66\x8f\x69\x6a\x6c\x9a\x88\x8e\x4c\x20\xcc\x24\x81\xee\xc1\xa0\x6e\x04\x53\x51\xab\xd5\x3f\xa2\xb4\x98\xb3\xdc\x0f\x00\x41\xa4\x2c\xda\x10\x18\xc5\xca\x4a\xd5\xa7\x6e\xce\x6a\x2d\x0d\x5b\xbb\x8f\x9f\x84\xb7\x2c\xdf\x78\x90\x4a\x4f\xcb\xe3\xcf\xcf\xed\x44\xdd\xcd\x17\x3e\xed\x28\x29\x6a\x7c\xff\xc5\x65\x05\x6f\xcc\xcb\x68\x04\x3d\x7b\x44\x5b\xe3\xa0\x7c\x4b\x39\x7a\xfb\xc4\x8e\x27\x2d\xe8\xd7\x5d\x1f\xb7\xae\x2e\xb5\x5c\x2f\xdc\x58\x74\x87\x59\xa3\x96\x9e\x85\xfc\x7b\x7c\x05\x88\x01\x40\x60\xc0\xcd\x77\x36\xc5\xe1\x0b\x58\x66\x99\xde\x23\xdb\x76\x7b\xc3\x1a\x43\x68\x53\xa6\x40\x41\xda\x57\x5e\xb2\x12\x3b\x1d\x2a\x15\x53\x44\x49\x85\x39\x0d\x2e\x6e\xb0\x9c\x77\x62\x4b\xa4\x5d\x77\x99\xad\xe5\xd1\x27\xeb\x2c\x5f\xcb\x02\xb0\x62\xcd\x1a\xbd\xef\xe0\x2f\xfa\x94\x31\xa9\x44\x1a\xd6\x29\xcb\x6b\x71\xe1\x44\x13\xb1\x06\x6d\x82\x2f\x5a\xf6\x87\x15\xe6\x57\x57\x8e\x58\x61\xc9\xed\xad\x9e\x26\xae\x58\xde\x11\x31\xca\xe6\xd5\xc0\xca\x5b\x01\x00\x21\x66\x6b\x50\xe5\x06\xcc\xb2\x22\xd0\x92\x5a\xb9\x42\xbd\x3b\xd3\x9c\xb5\xcf\x67\x7f\xfe\xc9\x65\xb0\xbb\x06\x5e\x40\xe3\x6a\x10\x05\xbb\xf1\x6f\x44\x3d\x5d\x44\x90\xb5\x0f\x91\xfb\x0d\xe3\x2d\xf6\xd9\x1e\x22\x75\xcd\x5c\x73\xe6\x79\xf5\xf9\xa1\x82\xbc\xe8\xe7\x35\x8b\x03\x4a\x4a\x25\x43\xac\x8f\x3a\x37\x42\xb5\xda\x73\x9b\x8b\xf2\x85\x42\x4d\x56\x3d\x3e\x0b\x3f\x44\x0a\xea\x30\x35\x07\x78\x01\x7f\x30\x8c\xd1\x40\xad\x41\x6f\x67\xa9\x05\x7a\x01\x26\x78\xb1\xeb\xb1\xe2\x90\x71\xb5\x7e\xfc\x90\x0f\xb7\xfb\xec\xc8\xb4\x9a\x67\x2a\x47\x9d\x11\x81\xbe\x3b\x63\xeb\xb2\x2a\x68\x0f\xb1\xfc\x28\x89\x81\xdd\x54\xeb\xec\x8b\x48\x41\x7e\x5b\x0d\x2f\x60\xb3\x3c\x6c\x58\xf5\x23\xf4\x77\x5b\xa7\xd5\xcd\xb6\xe4\x07\x73\x3e\x6d\x63\xe3\x40\x49\x4f\x17\xb5\x1f\xeb\x93\xaf\x75\x96\x1a\x76\xa6\x02\x42\xc3\xce\xd0\x0a\x35\xa6\x11\xf0\x25\xea\xca\x79\x1d\x59\xf0\x87\xcc\x93\xf3\xb6\xaa\x2b\x3c\x71\x09\x93\x83\x47\x2d\x2e\x69\x72\x43\x52\x95\x08\xa2\x6a\x66\xe2\xcc\xff\xaa\xcb\x50\xc1\x89\x1a\xaf\xf8\xe2\xab\x33\x73\xb6\x94\x17\x15\x84\x71\x31\xd9\x8f\x54\x1b\x95\x04\x7c\x71\x17\xa6\x01\x73\x3c\x1b\x34\x02\xbe\x40\x13\x19\x10\x68\xd0\x08\x34\xae\x2a\x4e\x04\x5c\xb5\x21\x2b\x01\x42\xbd\xd0\xbf\x30\xf7\x17\x35\xbc\xe0\x7d\x76\x26\xa1\x9b\x16\xe7\x0d\xcf\xab\x11\x2a\x77\x58\xe5\x33\x2f\x08\x7d\xf6\xc1\x85\x87\xc2\xd6\xa2\xa2\xb2\x53\x7e\x96\xcb\x0e\x10\x55\xcf\xdd\x3d\xa2\x6e\x67\xc2\xb7\x4b\x1b\xd5\x3b\xeb\xca\x1b\xab\x7f\x42\x5f\x7c\xf3\x5e\xc4\xd0\xb4\xea\xba\xf7\x5f\x37\xb2\xf3\x36\xa2\x7c\xec\x8b\x0e\x01\xe1\x03\xaa\xf8\x09\x41\x9f\x36\xc9\xc1\x7d\xd0\x24\x73\x8a\xcd\xdb\x5c\xbb\xd8\xe0\xb1\x61\x69\x62\x54\x40\x64\xd4\x48\x27\xf5\x88\xb8\x7e\xae\x27\x5f\x81\x76\x71\xde\xe6\x5b\xc8\x9c\x87\x7e\xde\xb4\xce\xbd\x4e\x1e\x6d\xdc\x22\xe9\xef\x78\x12\x20\x1b\xe5\x63\x6c\x0d\x3f\x10\xd6\xeb\x77\xe2\xa8\xaf\x5f\xef\xe6\x1f\x61\x5f\xdc\xcd\x1a\xc3\x8e\x29\x2a\x72\xa4\x93\x3a\xe9\x59\x40\x18\x8f\x37\xa1\xf7\xcb\x8a\xf1\x90\xb6\x0f\x74\x32\x7b\x7d\xcc\xe1\x36\x1f\x73\x10\xc7\x92\xcb\xb5\x5b\xc7\xa7\x11\xd8\xb9\x97\x9f\x0f\xe2\x53\xee\x85\x2d\xe9\x5e\xeb\x97\x0c\x49\x90\x05\x44\x46\x8e\x74\x36\xa0\xee\xf0\x5e\xd7\x92\x0a\xb5\x77\x29\x2d\xa3\x50\x5e\x59\xb1\xc4\x81\x19\xe0\x6f\xdf\x33\x6e\x25\x01\xf4\x48\xc1\xcb\xa4\x32\xb9\xac\x11\x7b\x75\x4e\x68\xb9\x5d\x69\x25\xbb\xe4\x06\xd5\x6f\x4c\xf6\x66\x5d\x1f\x77\x76\x72\xc5\x51\x5f\xd6\xa0\x6f\xaf\xdf\xfd\x73\xdd\x9b\xcf\x3b\x8c\xab\xec\x60\x06\xf7\x82\x75\x45\x47\xa0\x27\x43\xc2\x1e\xdd\xb9\x5a\xf1\x0d\x63\xe3\x6f\x2c\x38\x31\xbf\x07\x04\x0c\x2f\xab\xfc\xaf\x84\xc2\xfc\xb7\xdb\xee\xc1\x05\x97\x2e\x9e\xe8\x6e\x63\xc6\x88\x65\xf8\x5b\xcb\x27\x77\x12\x49\xea\x61\x07\xd4\xd4\x7c\xfa\x1a\xfa\x14\xdb\x12\x03\xca\xa7\xf4\x7c\xdc\xd1\xa8\x87\x7a\x11\xc4\x04\x12\x36\x74\x09\x1b\xec\x8e\x80\x34\xc0\xa4\x8e\x8c\x79\xa1\x14\x21\xbc\x8b\x82\x3e\x2b\x60\x16\x51\xcb\xc9\xc8\x27\xf0\xeb\x3d\xd3\xf9\x0a\xb4\x10\x25\x56\x12\x72\x14\x84\x7c\xd1\x1d\xab\x5c\xb6\x13\x44\x21\xe2\xce\xf9\x66\x94\x4f\x18\xf8\x0a\x20\xe5\xea\xd1\xe3\xa0\x16\xda\xf4\x27\x83\x55\xd2\x05\x30\xd9\x8c\x3e\x9c\x15\x87\x75\xe4\x6b\xe6\x01\x7c\xc5\xe3\x52\x74\x67\xd3\x3a\x77\xae\xc7\x25\x9f\x5f\x45\x65\x32\xd2\xd5\x0f\xf0\xd6\x05\x64\xff\x81\xdb\x35\xed\xd8\x77\xbf\x7c\xdb\xcf\x51\x77\x2d\x48\x63\xde\xa8\x4d\xe4\x26\x94\xb5\x47\x36\x6e\x62\xca\xfe\x22\x9f\xc5\xe6\xdd\xb2\x8a\xd4\x83\x45\xb8\xb1\xc7\xea\x9d\x67\xcc\xb1\x3c\x46\xef\x6f\x5a\x67\x9d\x21\xcd\x78\xe2\xab\xef\x56\x23\x09\x41\x67\x06\xed\xe2\x9a\x7d\xf0\x58\xa9\x30\x2a\x93\xb1\x28\xfd\xfb\x89\x9e\x3a\x4a\xfb\xd6\xa2\x95\x19\x71\x1e\x25\xbd\x52\xce\x1e\xac\xc9\xe8\x31\xb3\x45\x6c\x03\xb1\xef\x35\xc2\x3d\xb3\xd8\xf7\xc6\x7b\xb6\xb7\x67\x76\x30\x43\xf2\xcc\xde\xd9\x55\x4b\xfa\x98\x91\xb1\x4f\xed\x9f\x3d\x8d\x4e\x2e\x43\x3f\x70\x56\xa4\x52\x36\xb0\x87\x16\xf6\x9c\x40\xf9\xd8\xcf\xf6\xed\xd5\x81\x3e\xae\x36\x23\x03\x4e\x23\xd2\x39\x8d\xf8\xd6\xde\xc9\x9e\x75\xb4\xd0\x23\xd9\x5e\x3d\xa8\x24\xce\xb7\x2e\xfc\xaf\x12\x54\xcf\x2c\x8b\x3b\x3e\x23\x51\x3e\x99\x4c\x65\x82\x08\x00\x7a\xd9\x8e\x02\x07\x74\xb8\xab\x7c\x08\xa5\xc2\x05\xf6\x93\x86\x08\xfb\xb1\x09\xab\xcb\x96\xf4\x7a\xba\x93\x96\xae\x9c\x11\x52\x1a\xd2\x6b\xbb\x3c\x23\xe2\xcc\xe1\xd8\x93\x35\x4c\x1d\x3b\xb1\x3a\xd3\xea\xea\x1a\xa6\x8c\x1e\xf7\x5c\x56\xec\xeb\xcf\xdf\xe3\xf6\x5d\x99\x08\x40\x84\x90\x82\x14\xf3\xd5\x4c\x7c\x81\x5d\x0f\xc8\x7a\x78\xec\xed\xdd\xa0\xe6\x00\xa1\xd1\x51\x65\xe1\xd0\x75\xd8\xcb\x15\x13\x63\xc6\x0c\x4f\x78\xde\xfd\x6d\xd6\x34\x71\x0b\xc1\x58\xa6\xa0\xa6\x2d\x13\x46\xa2\xcb\xaa\x4e\x9e\xe6\x5a\xa3\x6a\xaf\xeb\xda\xd5\xdd\x73\x7a\xf7\xfb\xf7\x6f\xb6\x28\x31\x2e\x03\xca\xa7\xd4\xff\x3f\xe6\xfe\x05\x2e\xaa\xe3\xfc\x1f\xc7\x67\xce\x6d\x51\x11\x81\x5d\x58\x11\x10\xd6\x75\x59\x01\x91\xcb\xb2\xac\x88\x80\x20\x22\xe2\x9d\x20\xc1\x6b\x94\xa0\x28\xde\x45\x62\xd4\x10\x62\x08\x51\x34\x09\x12\x2f\x31\x68\x8c\x35\x56\x8d\x31\xc6\x18\x25\x36\x31\x17\x93\x5a\x93\x58\x6b\x6d\xf4\x63\xad\xb5\x7e\xac\x4d\x93\xb4\x34\xb5\x69\x9a\x1a\x65\x0f\xff\xd7\x99\x73\xd9\x73\xdf\x03\xfa\xf9\xfe\x7f\xaf\xbe\x6c\x50\x76\x67\xde\xcf\x7b\x66\x9e\x79\x66\xe6\xb9\xa0\x3c\x6b\xc0\xcc\xe6\xb1\x45\xfe\x9f\xb2\x59\x68\xab\x38\x91\xdd\xa3\xb7\x69\x79\x26\x1c\x79\xda\xdb\xf1\xaf\x6c\x7e\x3d\x30\x63\x40\xef\x24\x8a\xbd\xaf\xcc\xb8\xe6\xec\x58\x80\xcd\xe8\x18\x45\x5f\x16\x26\x3f\x9b\xf3\xab\x9a\xcb\xf9\x05\x8c\xe5\xed\x9a\x97\x2b\x9a\x4f\x21\xf2\xbc\x5d\xbf\xe1\x26\xd0\x26\x3e\x6f\xd7\x4d\xba\x1a\xd9\xe2\xe1\x22\x9f\x51\x29\xf6\x98\x08\xec\x10\x6b\x76\x7b\x1f\xc5\x7a\x66\xf6\x7b\x62\x11\xaf\xbf\xa3\xd6\xe2\x45\xeb\x5f\xec\xb8\x40\x5f\x17\x41\xe6\xf6\xb3\x79\xe8\xdc\x95\x2a\x89\x11\xc6\xb9\x7b\x29\xbe\xb6\x5d\x86\x47\xb5\xa8\xb5\xaf\x7a\xf5\x17\x33\x86\x53\x85\xe9\x43\x86\x8e\x99\xbb\x8c\x1c\x38\x52\x51\xc9\x5a\xa8\x5b\xdd\x31\x8e\xbe\x11\xdb\x67\x84\x79\x7b\xc4\xdc\x19\xe6\xb8\x5d\xb2\x22\xd6\xff\x1f\xc6\x64\x21\xab\xa9\x18\x90\xc4\x7a\x41\x70\xfb\x7e\x2e\xfb\xa0\x81\xe6\xaf\x09\x4a\xc0\xe5\x60\x3a\x16\x80\xd5\x12\x6a\x7b\xfa\x71\x7b\x7e\x48\xc2\x88\x87\xfb\xd1\xe7\x83\xa6\xe5\x27\x67\x54\x2e\xab\xa1\x02\x07\xc7\x69\xd8\x01\x47\xa6\x95\xed\x7c\x36\xb4\xc7\x36\x4b\xcd\xdd\x99\x79\x03\x2a\xc2\x9b\x6c\x35\x4b\x23\x86\xe5\x5d\x58\xa1\xb0\x07\x10\x7f\xf8\x69\x74\x86\x4f\x11\xf8\x13\x5f\x2b\xca\x59\xa4\x24\xc5\x80\x15\xc5\x7f\xc7\x50\xa3\x58\x0e\xf1\x01\x29\xf9\xbe\x32\xc0\xb2\xc2\xbf\xf4\x1e\x9e\xc1\xa0\xa8\x9f\xf5\xe4\x6b\x00\xa3\xbd\x2a\x9b\xae\x46\xf9\x35\x32\x0c\xe5\xd7\x50\x43\xa7\x93\x6e\x63\x34\x35\xca\x8d\xd0\x11\x03\xc6\x16\xeb\x65\xde\xa0\x77\xf3\x00\x43\x06\xb6\x06\x6d\x43\xb1\xca\xd5\x78\x19\x31\x0b\xb8\x99\x93\x9a\xc7\x6c\xa8\x1e\x9e\xd3\x24\x82\x37\xad\xe7\x04\xbd\x32\x78\xb3\x2b\xa2\xf9\xe9\x77\x79\xe0\x60\x38\x43\xb3\xfe\x5d\xdf\x66\x0e\x1a\x17\x33\x48\x57\x13\x6e\x62\x06\x8a\xdd\x64\xa3\x6b\xf8\xc7\x60\xb7\x70\x0c\x91\xb2\xe4\x31\x53\x84\x7e\xe9\xdf\x80\x3d\x2f\xf2\x58\x7a\xd6\x14\xd0\x3f\xed\x95\x16\x02\x8e\x4a\x17\x6a\xb1\x66\x8e\xf0\x26\xf1\x4c\x0d\x1c\x8c\xd9\xbe\xf8\xab\xaf\x2e\x30\xb2\xcb\xb1\x78\xf2\x16\x60\xa3\x6b\xcd\x2a\x6b\x52\xf4\x88\x93\xf9\xb7\xe3\xe7\xca\x33\x85\x01\xb2\x1f\x1f\x99\x31\xab\x30\x39\xd1\x43\x14\x8b\x57\x5c\x88\xfd\x67\xe4\xec\xcc\xe2\x19\xc3\xc7\xa6\xb1\xf6\xd1\xe7\x74\x35\x9e\xcb\xde\x41\x99\xd2\x33\xcc\x1a\x91\x61\x4e\x51\xbf\x1e\x62\xdc\xca\x9a\xc5\xef\x54\xd5\xaf\x18\xb3\x2e\xf7\xa9\x9d\x9f\x5e\xda\x4e\xdf\xdb\x5b\x30\x28\x86\xeb\xf9\x72\x88\x1d\xce\xcc\x7c\x09\xf6\xda\x5d\xd7\x34\x28\x6a\x47\xde\xef\x4f\x9f\xa7\xdf\xfc\x45\xcf\x3d\xc1\x3c\xe9\xb0\x33\x99\xae\x46\xfb\x92\xdd\xd7\xa7\xc7\x2c\xde\x9b\x82\xa0\x78\xe4\x2f\x12\x05\x83\x53\x46\x95\x44\x1e\xf3\xed\x4a\x47\xe3\x5e\x79\x22\x9a\x1f\xee\x10\x3b\xf4\x58\x17\xd5\xe1\xe3\xf8\xed\xe8\x78\xdb\xa1\x80\xed\xbe\xfe\xc0\x72\xa4\xe3\x8a\x19\x9b\x48\x51\x9a\x4b\x4d\xcd\x21\x55\x22\x29\xca\xf5\xc5\xac\x4c\x13\xd7\x1d\x3e\xb0\x98\x2b\xd0\x25\xab\xc6\xc5\xd0\x1c\x1d\xca\x2f\xcb\x37\xce\x3d\xb6\xa0\x19\xe5\xcd\xac\xc6\x99\x33\xa5\xd3\x27\xab\xa2\xc6\xa0\x6c\xa6\x57\x13\x25\x2f\x1d\xd9\xb6\xef\x89\x67\xd6\x45\xc3\x26\xba\x4f\x14\xf6\xa7\x68\xba\xbe\x79\x47\xe7\xbf\xd7\x15\x45\xa1\xf1\x2d\xae\x5c\x76\x39\x64\x20\xac\x2d\x7b\x6a\xc5\xe4\xa2\x46\x98\xfc\x5c\x23\x7d\xb9\xcf\xb6\x75\x1f\x7d\x11\xda\xc4\x8e\xf3\x3c\x20\xf8\x69\xed\xe3\x7d\xd5\x14\x3e\x07\x1e\x91\xbf\xd8\xe9\x57\x1b\x03\x86\xac\xca\x5d\xb0\xe6\x91\xc3\x8b\x9e\x18\x11\x5f\x3e\x2a\xa3\x62\xfd\x92\xd1\x8b\xf3\x91\x53\x49\xda\x88\x4d\x75\x2d\xdf\x35\x56\x94\xdd\xcd\x19\xf3\x97\xd7\x1b\x17\x9d\x65\xdf\xbe\x0f\xe2\xf9\x9c\x3f\x46\x7a\xa8\xc8\xdf\x88\x97\xe2\xfa\xcd\x77\x57\x4e\x75\x4c\x7c\x88\xf7\xc9\x68\xde\x8a\x7f\xf9\x7b\xd8\xc3\x59\xef\x38\xf7\x12\xeb\x94\x81\x30\x6e\xc2\xaa\x51\x3b\xec\x9b\x2f\xeb\x26\x2a\x34\x67\x12\xdc\x71\x9c\x94\xc9\xc3\xe9\x0c\xfb\x80\x4d\xc9\xc3\x7b\x05\xdd\x7a\x7f\xe5\x43\x8e\x29\xe3\x17\xbd\x40\xcc\xa8\x9b\x59\xbd\xed\xe9\x27\x26\x0e\x89\x38\xd4\x27\x33\x2e\x37\x27\xaf\x14\xdb\x57\x56\x6c\x79\xb8\xff\xff\x42\x93\xb3\xde\xf1\xc5\xf6\x19\xb3\x27\xcc\x5d\x99\x39\x3a\xe5\x3b\x6b\xff\xb4\xd8\x5c\x96\x9b\xab\xd8\x41\xfc\x32\x45\x83\x28\x2e\x03\x12\xb3\xb3\x0c\x81\x4e\x93\xd3\x13\xe7\xf4\x84\x5b\x3d\x56\x53\x7f\x18\x16\x8c\xc9\x43\x2f\xaf\xfe\x72\x6f\xe1\xbc\x68\xdc\x36\xe4\x3d\xd7\xce\xe4\xd4\x49\xb3\x93\x4f\x64\xef\x4b\xca\xb9\xf8\xe9\x73\xaf\xed\x2d\x1a\x3d\x72\x8e\x67\x62\xfe\xa3\x8f\xe1\xa7\x8f\xdf\x1a\x3e\x28\xff\xc9\x82\x05\x73\xcb\x07\x0d\x98\x9f\x9f\x58\x55\x31\x33\xf7\xfd\x15\xf4\x8f\xf4\x57\x2f\x3f\x5d\x38\x6d\xe2\x33\xa3\x47\x4d\xdf\xfb\x7f\xef\x53\x05\x41\x4f\x58\x8e\xe7\x52\xdf\x23\xcf\x33\xb7\xe4\xb0\x1a\x2e\x3e\xad\x62\xf6\x01\x3d\x13\x06\x0f\xf6\x04\x6f\x6b\xe8\xf3\x7c\x50\x54\xdd\x13\x03\xcb\x63\xe2\x72\x53\x86\x0c\x0f\x09\xda\x1b\xb1\xf7\xa5\xf4\x2f\x86\xc2\xea\xa7\xc3\xc6\x14\x63\x9f\x16\xa7\x16\x6e\x5c\x63\x0e\xac\xb1\x16\x8c\xcb\x5b\xed\x4d\xa2\x69\x56\x87\x7c\x0b\xcb\xb1\x44\x72\x3f\xb0\x70\x9e\xda\x4c\x3f\xc2\xbd\x12\x65\x1f\x60\x1d\x92\x38\x60\x58\xd0\xac\xca\xbe\x73\xb3\xf7\x64\xcf\x8f\x9c\x3f\x23\xed\xb3\xe1\x4c\x93\xb9\xf9\xf0\xd8\x6a\x68\xa7\xaf\xaf\xa6\x73\x6e\xff\xff\xcd\x07\x0c\x82\x9b\x70\x3e\xf2\x6f\xe9\xab\xe2\xdf\x62\xce\x50\x7a\xb8\xdc\x3a\x96\x17\xe2\x74\xd7\x14\x2a\x7c\x5c\xee\x7d\x02\x43\x46\x2d\x2c\xc8\xae\x64\xe7\xd8\x3e\xec\x38\x96\x49\x9d\x01\xbd\x90\xe7\x8c\xef\xa6\x2d\x52\x94\x41\x7a\x1f\x4f\x4a\xd1\x9e\xe2\x55\xee\xd4\xd2\xcc\xf8\xb8\x34\xa2\x27\xc7\xca\x21\x58\x86\x95\xc7\x0f\x2b\x4a\xcc\x1a\xc4\xe0\xbc\x8a\x1d\xc4\x1c\xe4\x7e\xce\xff\xc8\x97\xbe\x12\xad\xb7\xab\xc1\x55\x7b\x16\xf6\x8c\x8d\x19\x9c\x3b\x7c\xe2\xf4\x79\x78\xc9\xc0\x22\xf8\x0d\x1d\x3c\x68\x70\xf4\x80\xd0\x95\x11\x0f\x21\x39\xab\xb1\xe3\x58\x2d\xb9\x5f\xee\x8b\x5f\x6d\x5e\xb4\xbc\x32\x14\x2e\x36\x57\xd7\x54\x04\x63\xc7\xcb\x23\xb1\xc0\x88\x69\x33\xac\xde\xef\x23\xca\x81\xe4\x7b\x66\xe4\x57\x64\xf7\xb8\x3c\xcc\x57\x31\x97\xc9\x6e\x42\xdf\x4e\x9b\x1b\x51\xe9\x64\x5b\x70\x56\xf7\x5b\x98\xca\xb6\x72\x6b\xf5\x51\xa6\x99\xa3\xab\xbf\x62\xdb\xc1\x3b\x77\xc1\x72\x2c\x8b\x3a\x03\x82\x40\x38\x33\xe7\xf1\xf4\x8c\x2c\xc8\x72\xc2\xbb\x73\x32\xdb\xa9\x88\x9c\xca\xe6\xfa\x88\x57\xf6\xec\x5e\x1a\x33\xcf\xf3\xd1\xac\x19\xcd\x49\x59\x91\x81\x19\x79\xb0\xcc\xed\x2a\x19\x3e\xc8\x91\x0a\xef\x54\x56\x60\xdf\x78\xfb\x3e\xfe\xdd\xd4\xf1\x89\x35\x0e\x22\x2f\x7e\x58\x51\x52\xe6\x20\x2e\xb6\x07\xce\xc7\xdc\xd4\xb7\xe8\xfd\xdd\x37\xa6\x88\xaa\xed\x41\xff\xdc\xfb\xaf\xde\xc3\x33\x5d\x05\xa3\x3e\xc6\xac\xae\x2c\xa2\xf2\xde\xd6\xcc\xe8\x02\x6b\x6d\x34\x80\x9d\x17\x60\x39\x96\x4b\x7d\x0b\x02\x65\x51\x07\xa9\x79\xce\x89\x51\x1d\x3f\xfb\x6f\xe4\xaa\x79\x05\xb0\x76\x6d\xc4\x2a\x62\xe7\xbd\x47\xd7\xd5\xf0\x7e\x80\xd8\x29\x72\x3f\x20\xb9\xfb\x6b\xd3\xe9\x9f\xed\x59\x0f\xf3\xfa\x31\xda\xd3\xfb\x7c\x3d\xeb\xeb\x07\xe7\x23\x5f\xbf\x24\xa5\xaf\x9f\xcc\xff\x4e\xcf\xeb\xaf\x36\xe2\xf1\x05\xe9\xe9\x43\xe2\x12\x33\x82\x1e\xd3\x76\xff\xf3\x5e\x5e\x5d\xc5\x7a\xe5\xc5\x2b\xbc\x00\x19\x2c\x5f\xc1\xf9\xc8\x57\xca\xa1\xeb\x2b\x95\x03\x3d\x94\xba\xb3\x54\xc9\xd3\xb1\xa3\x76\xdf\x3a\x96\x30\x24\x76\x76\xbd\xb6\xb7\xd4\x9b\xdb\x61\xce\xbd\x4f\xde\xfa\x64\xd2\x3a\xe4\x2e\x85\xf4\x51\x19\xef\x7f\xc8\xeb\x23\x9f\x17\xa2\x28\x13\x09\x43\x48\x4f\x47\x8c\x3d\x31\xf0\x24\xe7\x84\x38\x63\xdf\xa3\x41\x89\x89\xd3\x9e\x89\x9d\x1d\x55\x35\x33\x15\xce\x5f\x1d\xe4\x1e\x8e\x57\xb0\x3e\x88\x74\x1e\xfc\x7c\x6c\xa4\x33\xe9\xc0\x76\x3a\xab\xae\x02\x8d\x07\xd7\xcf\x00\xa9\x9f\xa3\x6f\x06\x30\x46\x9c\xc2\xd3\xd1\xbc\xa4\x77\x6a\xe2\x90\xa1\xa3\xde\x0a\x59\x12\x22\xf3\x73\x9c\x46\x93\x99\xb1\x23\xc3\x57\x46\x1f\x89\x2f\xc2\x88\xa2\x01\x9c\xa7\x23\xef\x03\x7a\x9b\x5d\x53\x91\xd0\x85\x52\x0f\x20\x0f\xd0\x57\x0f\x5d\x8d\x2c\xdd\xbd\xe7\xc8\x95\x88\x32\x34\x0d\xae\xee\x86\x4d\xde\x20\x2c\xac\x81\x5e\x82\x62\x9a\x7c\x3e\x92\xe1\xc8\x1f\x4c\xc5\x4b\xd2\x63\x33\xf1\xb5\xce\x44\xae\x92\xaf\x4e\x1c\x35\x66\x69\x04\xfd\x0a\x16\x09\xa7\x61\x45\xb9\x85\x4b\xa4\x2e\x93\xab\x2a\x22\xb6\x47\x17\x4d\x7d\x14\x00\x12\xb4\xc3\xd9\x44\x3e\x75\x07\x04\x83\x70\x60\x05\xd1\x6c\x3f\xa1\x0c\x44\xc6\xec\x40\xde\x1d\x03\xcd\x16\xab\x39\x08\x42\x33\xa3\x4f\x93\x61\xfb\xb7\x9f\xe7\x6e\xcf\x79\x7a\xd3\xed\x33\xb9\xbb\x0a\xe8\x1f\x5f\x5b\x57\xbb\xe2\x19\x88\x85\x2d\x5f\xdf\x10\x81\xff\xf0\x05\xc4\x7a\xc1\x24\xfa\xa2\xf5\xf5\x0d\x5f\xd0\x3f\x05\xd0\x17\xa0\x2b\x03\xf6\x3d\x62\xc7\x9c\x41\xa7\x3a\xfe\x08\xcf\x06\x9e\xda\xbc\x37\xbe\x1a\x40\xb0\x14\xce\xc3\x03\xc9\xe3\xc0\xc5\xce\x2f\xbd\x9b\x10\xce\xfc\xe1\xe3\x94\xd0\x53\xc2\xd2\x9e\x99\xee\x35\x43\xc6\x8e\x49\x1b\x3d\x67\xd4\x8b\x4f\x36\xd4\xa6\x26\x56\x0e\x4d\xcf\x49\xcf\x99\xfd\xd0\x9e\x1d\x6e\x77\x60\xef\xd8\xf0\x84\xc1\xe6\x82\xd8\x63\x58\x60\xca\x20\x48\xc5\x0c\x4a\x48\xb3\xa5\xc6\x0f\xad\x18\x39\xf7\xf1\xec\xb5\x16\xc7\xe0\xc1\xb6\x54\x7b\xc6\xc2\x82\x15\xab\x02\x87\x0e\x8b\x88\xea\x17\xb6\x2a\x30\x04\xc0\xce\x1b\xb0\x1c\xbb\x41\x7d\xcf\xd8\x2b\xdc\xba\x16\xbb\x32\x61\xf6\x01\x36\x4f\xcc\xe4\xd8\x8f\xfb\xd5\x2f\x2c\x48\x8d\x8a\x4a\x70\x0d\x0d\x3e\xe5\xfa\x3c\x13\x56\xd7\x87\xb6\xe0\x2f\x34\xac\x0e\x59\xd9\x73\xc2\x84\x8e\xba\x4e\xf6\xbd\x0a\xce\xc3\xda\xa8\xd9\x68\x1e\xcb\xfc\x2c\x71\x4a\xc8\xef\x87\x8e\x0a\xe7\x78\x6f\xcb\x09\x81\xf1\x31\x69\x79\xf9\xf6\x97\x53\x92\x13\x6d\xae\x3e\xfd\x0e\x87\x8c\xe7\x7d\x2e\x9f\x4f\x89\x8b\xb5\xf5\xa3\x2f\xec\x0f\x5b\x1b\x52\x58\xd7\xe3\xd5\xa4\x5c\xb8\x1c\xed\x1f\xbb\xb1\x83\xf8\x2d\xb4\x2f\xc9\xdf\x23\x78\xff\x29\xf6\x49\x82\x7d\x16\xd8\xdd\x77\x56\xce\x9e\x1c\x98\x38\x62\x67\x56\x65\xbf\x47\xc7\x70\xde\x54\x64\xf8\xfa\xd2\x09\xab\x1d\xf4\xd5\x08\x22\xb4\x16\xc6\xd0\x37\x99\x3f\xb5\xf4\xde\x9a\xa1\xa3\x2b\xe7\x58\x93\xe6\xbc\x5c\xba\xa6\xa6\x16\x40\xf0\x35\x76\x90\xa0\xc8\xfd\xec\x1c\xc9\x40\xef\x10\x7c\x12\x4d\x37\xfb\x1a\x61\xe7\xfc\xa6\xbe\x2e\x2a\x69\x8c\x84\xe5\x61\x55\xd5\x0f\x8d\x5e\xf8\xf8\xd0\x0c\x0b\x9c\xd6\x77\x77\xf9\x95\xb6\x17\xf6\xe3\x57\x16\xec\x1f\xb5\x76\xe9\xa0\x13\x8d\x0f\x3d\xf2\x7a\x6b\xd1\xe2\xa8\xa5\x6b\x67\xd4\x9d\xfe\xf6\xe7\x80\x6d\x1f\x3f\xcd\xed\x21\xe9\x19\x92\xd4\xcb\x98\x6d\x40\xdc\xd7\x44\xd5\x9e\x47\x03\x0a\xb3\x9a\x1d\x73\xf7\xcc\xcd\xa4\xaf\x3d\xb3\x05\xdf\x64\x76\xc2\x9b\xb4\xcb\xde\x3f\x73\xd8\x21\x78\x85\x8e\xa6\xbf\x5a\x0b\x20\xb8\x8d\x7c\x51\x79\x5f\x77\x5f\x5c\x0c\x8a\x37\xe1\x3d\x82\xc3\x2c\x7d\x20\xd3\xea\xed\xa0\xb2\xdd\xa5\x21\x45\x85\xa5\x8f\xf6\x8b\xeb\x61\x8f\x88\x8f\x1f\x9a\xdb\x16\xe0\x28\xa0\x3f\x7f\x71\x33\xbe\x3f\xa1\x00\xbe\x48\x2f\x19\x17\x95\x57\xb8\x6c\xd5\xb1\x41\x96\xe8\x7e\x81\x75\xa1\x47\xa2\x07\x7d\x40\xef\x6b\x04\x10\x14\x62\xc7\x71\x82\xf3\xed\x44\xd1\x96\xce\x20\x88\x17\xc2\x57\x3e\xaa\xd8\x9b\x1a\x14\x95\xfc\x0d\x5a\xd4\x41\x70\xfb\xb1\x9c\xd9\x74\x19\x80\x60\x35\x76\x1c\x8f\xe6\x3e\x2f\xc4\x18\xaf\x0e\x85\x67\xe8\x5f\x46\xc0\xdb\x56\xba\x00\xce\xb2\x62\xc7\x67\x61\xd1\xab\x96\x7a\xbf\xaf\x65\xf7\xa8\xd5\xb0\x0c\x7d\xc7\x2a\xfe\x8e\x58\x4b\x65\x78\xa4\x2d\x24\x07\x78\x06\x0d\x76\x17\x1c\xe9\xd5\x57\x68\xea\x46\x92\x39\x33\x7c\x65\xf4\x7e\x6b\x36\xeb\x5b\xbb\x1a\x4b\xc5\xcb\x51\x9b\x36\x5f\xab\x82\x67\x46\x22\xa4\x4c\xce\x5c\x9f\x7f\x93\xb8\xf9\x71\x13\x26\x3e\x94\x36\xe6\xe1\x8d\x4f\x2d\x8e\x48\x59\x1a\x7f\x2d\xd3\x95\xd1\xb7\x4f\x54\xa6\xd0\xd1\xa2\xf1\x71\x93\x0b\x66\xcd\xb1\xcf\x1e\x3e\xba\x76\x60\xb4\x39\x3c\x8d\x3b\x3f\xc3\xd9\x78\x32\x9a\xa3\x11\x52\x2b\x56\x72\xbe\xb1\x66\x6d\x58\xb1\xec\x89\x35\x4b\x5c\x61\xd0\x45\xef\xed\x87\x39\xc2\xe9\x53\xcb\x9e\xbc\x74\x72\xfd\x3f\xe0\xf1\x86\x51\x8d\x8b\xa6\xcc\x9a\x05\xdd\x75\x55\xf4\xe9\xb0\x2d\x35\x07\xce\x5a\x01\x0e\x7e\xc4\x0e\xe2\x1f\x52\x77\x91\xad\x80\xa2\x3f\x42\xc5\x0f\xd2\x1e\x0b\xff\x18\x88\xb6\xc9\x1f\xcb\x6a\x77\xcd\xa9\x6b\x78\xfc\xe3\x8d\x4f\x6c\xdc\x59\x5b\xb6\x34\x89\x3e\x12\x96\x02\x27\x86\x2c\xdc\x85\x9f\x7f\x03\x8e\xfb\xcd\xfc\x57\x5f\x39\x49\xcf\xfe\x70\xc7\x96\xa3\x1f\xbc\x57\xf5\xd7\x92\x19\x27\x59\x7b\x64\x3e\x19\x88\x39\xa8\xc5\xa0\x27\x30\x33\x36\x32\xee\x33\x3c\xcc\x1e\x57\xb8\xd5\x64\x1f\x02\x49\x51\xf6\x9b\x1d\xd9\x43\x4a\xb2\x06\x3b\x52\xff\x42\x1c\x21\xfb\x12\x93\x1c\x85\x30\x70\x78\x72\xc2\x20\xe6\x9f\xc8\x8a\xf4\xbc\x92\xb4\xd1\x83\xa1\xc5\x72\x72\x55\xdf\xfc\x63\x61\x69\x23\x93\x1c\x69\xa3\xd9\xba\x4e\x9d\xd3\xc8\x40\xcc\x8a\xfa\x09\x45\x7e\x6f\xbe\x7e\xac\xee\x0c\x8f\x2b\x8c\x32\x79\x44\xdd\xec\xcf\x1e\x52\x92\x9d\xe0\x48\x3d\x3b\x22\xf7\xf8\xa4\xf5\xd7\x99\x2e\x98\xbf\xa2\x2e\xd2\x47\x0d\x8e\xe9\xdb\x78\xc8\xf2\xec\x9b\x37\x98\x1e\x50\x01\x22\xac\x13\xf3\x1e\xec\xbc\xd5\x79\x08\x24\x82\xc1\x00\x98\x50\xe3\x41\x58\x98\xa5\x3f\xc6\xfe\xd7\x1a\x36\xc0\x9d\x9e\x83\xb9\xd3\x87\x60\xec\x7f\xed\x03\x4c\x66\xba\xc0\x3d\x3f\x36\x2e\x36\x7a\x60\x74\xf4\xc0\xe8\x69\xc7\x6c\x83\x6c\xb6\x41\x36\x7b\xa2\x3d\x6d\xf0\x90\xc7\x97\x47\x66\x47\x44\x9b\x7b\xf7\xa0\x4c\xbd\xcc\xa1\x21\xe6\xc0\x1e\xa6\x20\x22\x35\x37\x38\x2c\xa8\x17\x15\xd0\xa3\x67\x70\x70\x1f\x6b\x68\x70\x40\x48\x18\x3d\x09\xc0\xce\x52\xe2\x26\x56\x44\x5e\x66\xe6\x30\x9e\xee\x71\x99\xd8\x40\x76\x0c\xdd\x32\x05\x31\xc7\xa7\xc3\xd4\x3a\x2c\x7d\x50\xe2\xd2\xa7\xb7\x97\xf4\x89\xe8\x39\xb9\x71\x75\x4d\xce\xec\xe5\xe4\xf6\xc8\x01\xd6\x70\xbb\xdd\x91\xe8\x58\x37\x30\x71\xe0\x23\xec\x39\xa2\x89\xb8\x0a\x6f\x93\x3f\x30\x76\x14\xee\xb6\x79\xac\xe4\x2a\xe8\xe8\x28\xa4\x6f\x11\x57\x5b\x36\xae\x6b\x65\x3f\xb3\x98\xb8\x0a\xbf\xe4\x3e\xe3\xb1\xda\xc2\x6c\x5b\x46\x75\x40\x07\xdd\x46\xd6\xac\xdb\xd8\x02\x60\x67\x2d\x71\x06\x5e\x23\x6f\x70\x6d\x90\x26\xe7\x26\x38\x06\x46\x8f\xea\x20\x27\xb4\xbc\xbc\xae\x89\x6f\xe3\x0c\xfc\x92\xfb\x8c\xc3\x16\x66\x33\x6d\x81\x51\xb0\x98\xbe\xd6\x41\x16\xbe\xcc\xc5\x74\xd2\x77\x89\x4f\xb1\x55\xe4\x4d\x36\x56\xcf\xea\x20\x4d\x4e\x92\xbe\x3b\xea\x7b\x18\x0d\xe3\x0b\xbf\xa7\xff\x42\xce\x5a\xd7\xd0\xb8\x73\x5d\x43\xa3\xfc\xb3\x0e\xd2\x63\x25\x1d\x26\xfa\x2e\x8c\x87\x51\xdf\x17\xd2\x57\xe8\x5b\xdf\x93\x85\x3b\x1b\x1b\xd6\xed\x6c\x6c\x00\x90\xae\xa7\x2d\x20\xb8\xf3\x43\x10\x04\x00\x64\xad\x1f\xfe\x28\x46\xd7\x4f\x5b\xd0\x27\x67\x86\x33\xaa\x6f\x6c\xbf\xfc\x29\xe6\x7e\xb4\x05\xee\x99\x5d\xdd\x73\x51\x60\xf5\xf4\xb5\xac\xbe\x08\x24\x4e\xc2\x19\x54\x09\xca\x71\xc4\x4d\x9c\x70\x6b\x98\x7d\x08\x0c\x5c\xf3\x71\x78\xea\xa6\xe5\x63\xc3\x5f\x78\x8a\xcc\xdf\xd4\xbf\x6a\x41\x6c\x81\x27\xb9\x6a\x74\x06\xc0\xbc\x77\x68\x0b\x04\x9d\x47\x40\x6f\x66\x15\x91\xae\x70\x6b\x58\x10\x34\xd9\xdd\x19\x9e\x38\xa7\xc3\x15\x6e\xf5\x64\xb0\x55\xe4\xec\x43\xa0\xd3\x7b\x27\xfc\xcb\xaa\xb4\xa3\xe5\xe1\xf1\x5b\x16\x3c\x04\x17\x2d\x18\x94\xd3\x37\xc1\x3e\xdf\x3e\xb5\xcf\x73\xa1\xe5\x91\x25\xd5\x31\x9b\x02\x8b\x53\x16\x44\x15\xb9\xd2\xc7\x7a\x8e\x0c\x5f\x3e\xb4\xef\xc8\xbf\x7a\xc6\xff\x35\x09\x10\x9d\x9b\xbc\x57\x88\x48\xb2\x0d\x98\xd0\x3a\x8a\xf3\xe5\x67\x13\xc5\xd3\x48\x22\x3f\xcc\x36\x3c\xce\x1d\x04\x6b\xf1\xc8\x8f\x4f\x9c\xf0\xd0\xe6\xef\x1a\x1e\x9b\x3f\xf7\xa9\xa7\xe6\xce\x5d\xbd\x78\x68\x66\x6a\x6e\x6e\xaa\x2b\xa7\x0c\x36\xd8\x22\x63\xc7\x91\x6d\x77\x8b\xe1\x59\x3a\x93\x3e\x3c\xe7\xb1\x55\xb3\x2a\x6a\x97\x57\xba\x87\x0f\x77\xbb\x87\x0f\xc7\x9b\x60\xda\xad\xda\xf1\x3b\x51\x5d\x6f\xef\x15\x74\x87\xcd\xac\x2e\x94\x25\x47\x7c\x8f\xcd\x5d\x5b\x8b\xa1\x48\x13\x80\x8a\x42\x2f\x28\xdf\x75\xf6\xb7\xcd\xec\x15\xf6\x7a\x1e\x59\x9a\xef\x2e\x3b\x8b\x07\x29\x5c\x6a\xdf\x6b\x3b\x77\xe3\x97\xde\x0e\x0e\x23\x1e\x2e\xba\xd1\xee\x38\xcc\x21\x66\x6b\x90\x97\x02\x40\xb4\x99\xdc\xa0\x0f\xe8\x0b\x6c\xcc\x7a\x75\xf1\x11\xf3\x28\x3b\x08\x61\x73\xda\xa4\x2e\xc9\x89\x50\x74\xc9\x57\x0a\xdd\x70\xed\x95\x6b\x6f\xec\x5e\xb1\x9a\xbe\x44\xdf\xeb\x80\xd8\x91\x0f\x9a\x37\x7c\x15\x7b\x7b\xc7\xf1\x27\x5e\xb8\x70\x6c\xa4\xfb\x91\xc2\xe4\x84\xa1\x64\xdb\xa1\xfd\xcf\x9f\xee\xdf\x33\x76\xe7\x92\x2f\x7f\xd8\xb5\x73\xf3\xf2\xc7\x77\x3c\xbf\x76\xce\x7c\xf8\x72\x66\xf1\x8c\x61\xe3\xd3\x90\xfd\xc9\xfb\x9f\x86\x03\x3b\x18\xa2\x7c\xf5\x57\x7b\xe7\x17\x1d\xcc\xa4\x4f\xfe\x4a\x07\x53\xf8\x22\x07\x45\xf4\xdc\xaf\xe2\x5c\x8a\xd7\x70\x88\x08\x50\x4a\xb7\x12\x6d\x64\x1b\xe2\x65\x20\x73\x4a\xd2\xe4\x45\x9c\x90\x4c\x92\xe2\x57\x85\x98\xfc\x51\xe9\x29\x83\x47\xa5\x0c\x1a\x5a\xc1\x32\xa4\x64\xa6\xa3\x18\x65\x30\x1b\x97\x42\x3c\xc9\x70\xc4\x72\x43\xb7\x0a\xdc\x24\x1b\xe3\x46\x3c\xbd\xfc\x91\x13\xc0\x83\xd2\x27\xc7\xdb\x9b\x43\xc6\xce\x1b\xfa\x12\xc7\x8f\x19\xf9\xcb\x28\xf8\x81\xc8\x7c\x90\xcf\x1d\x19\x2f\xf4\x76\x54\x1d\x76\xb4\x74\xde\x48\x58\xa1\x2f\xb5\xb4\xc0\xcf\x84\x49\xc3\xf2\x71\x89\xe3\x03\x65\x42\xd6\xe0\x03\x67\x00\x68\xfb\x85\xf0\x3c\x24\x21\x04\xcf\xab\x39\x84\x70\x24\x30\x08\xb0\x8d\x62\x17\x64\x80\x83\x2d\xb4\x85\x0c\x32\xd5\x00\x2b\x88\x47\xe7\x8a\x60\x21\xc7\x01\x97\x56\x1e\x99\x4c\xc0\x8c\x92\xdd\xc4\x39\x3d\x2e\xde\x93\xd0\x57\x33\x73\xcb\x6f\xe1\xbc\x9b\xbf\xd9\x3e\x66\xd3\xe6\xb7\xe8\x1f\x5e\xfe\xf0\xe0\xe6\xe3\xaf\x9d\xfe\x0f\xdd\xfe\x97\xd8\x84\x83\xd9\xe3\x1f\x5d\x91\xd5\xf0\xb3\x0d\x1e\x07\xfc\xb5\xeb\xd9\xa4\xf3\xc9\x5f\x8c\xc1\x22\x21\x84\xa7\xbf\x2b\xd9\x51\xf4\x2b\xba\xe5\xf2\xfb\x57\x86\xef\xc9\x86\x89\xde\x15\x01\x8b\x1d\xc9\x3d\x8f\xd7\xc6\xad\x7a\x74\x55\xaf\x80\xc0\x48\xcf\xdb\xa3\xc2\x32\xcf\xb8\xd9\xfa\x8d\x15\xb4\x85\x20\x51\x8d\x50\xce\xe3\x5c\x23\xaf\xa1\x1e\xc8\x8a\x2d\x90\x38\xb0\xa5\xce\x55\x33\x7f\xc9\x89\xca\xfa\x15\x63\x9e\xca\x7d\xaa\xf5\x93\xff\x59\x2c\xc5\xd8\xc0\x61\x84\x8d\xe7\xe0\xa4\x0f\xdd\xdb\xd3\x5f\xa6\xef\xbc\xca\x5e\xb7\xff\x8f\xf7\xac\x18\x22\xf5\x9e\x00\x11\x47\xf9\x75\xad\x26\x37\xca\x8f\xd8\x1f\xcd\xa0\x58\x54\x3f\xdb\xe6\x74\xa5\x0d\x0c\x55\xd3\x35\xd3\xa0\x05\xc6\xfe\x96\x5e\x4d\x77\xb4\xec\xfa\x15\x4c\x78\xf5\xb3\xd3\x47\x3e\x17\x94\x0c\xfd\x3f\xf4\x2d\xfa\x2e\xbd\xf4\xf7\xbb\x4f\xc0\x31\x97\x2f\x5e\x91\xe8\x17\x71\x5d\x9c\xc1\x32\xef\x1d\x55\x7f\x1d\x91\x76\xf1\x57\xb6\x26\x9f\x83\xa0\x57\xbf\x06\x9f\xcd\x83\xc1\x19\xdd\x42\x5a\x51\x7d\x46\x33\x9b\xa7\x54\x29\xb7\x58\xa9\x68\x08\xbe\x9f\x5f\xb6\x4a\xc9\x7f\xba\xe9\x5b\xaa\x68\x1e\xb4\x0a\xb2\x27\x19\x91\x5d\xac\x3d\xfc\x08\xef\xe1\x51\xe8\x09\xdf\x71\x57\x82\xa7\x94\xbe\xc4\xc9\xdf\x9b\xb1\xd3\x7c\xf2\xa3\x25\x2b\x70\x20\x95\xfb\x2f\x68\x9d\x0e\xe6\xa5\x17\x09\x8d\x34\xc4\x17\xac\xe4\x9c\xbc\x97\x38\x79\xfb\xb2\x77\x4a\x2a\xf2\x9a\x91\x76\xf0\x57\x9b\x68\x3c\xea\x74\x94\x76\x85\x22\x3a\x8e\xd1\x0d\x92\x37\x58\x46\xbe\x2c\x61\x7c\xa3\x25\xf2\xf1\xab\xca\x6e\xd6\x90\xf2\x35\x47\x49\xbf\x43\xe6\xa6\xec\x8a\x50\x35\x41\xcb\xb2\x5f\x1f\x6d\x71\x9d\x1d\x86\x3d\xca\x49\xcb\xc8\x9a\xc5\xc9\xda\x1f\x24\x6a\xc9\xea\xeb\xd6\xaf\xc4\x1b\x79\x00\xc9\xda\x42\x7b\x0f\x72\x38\x70\xbb\x48\x72\x46\xee\x2a\x4e\x6e\x74\xda\xf3\xc9\x0d\x33\x3c\xae\xf0\x18\x18\x66\x8f\x73\x52\xda\xb2\xd3\x7f\xff\x2e\xf5\xc8\x80\xd9\x09\xcb\x87\x2e\xa8\x5f\xbe\xea\x19\x35\x02\x9e\xfe\xe3\xe4\x19\xcd\xf9\x91\x29\x1b\x97\x8f\xc1\x3c\x22\x0e\xaa\x38\x0e\x94\x9e\x79\x02\x07\x52\x08\x7e\x79\xe8\x2b\xc6\xf2\x33\x1d\x2e\x2e\x89\x20\xfd\x57\x3c\x11\x90\x7e\x23\x96\x06\xcc\x42\x79\x4b\x23\x10\x1f\x42\xde\x1d\xb4\x3b\xba\x5d\xfd\x21\xb2\x97\x51\xa5\x54\xbb\xf7\xe2\x1c\xac\x17\x9b\x24\xdf\x4e\x7f\x80\x66\x5e\xf1\x7b\xe6\xa2\x41\x4b\x32\x6a\xc8\x36\x2e\x41\x3e\x55\xdc\xd2\x82\x01\x4b\xc1\x86\x82\x88\x61\x3b\x90\xad\xd9\xd9\x8e\x7f\x6e\x0a\x44\x75\xa0\xb5\xde\xfc\xb9\xc4\x01\x3e\x73\x57\xd2\xb9\xe2\xcd\xff\xd1\xad\xa5\xbe\x97\x7e\xbb\x04\x87\xec\xdd\xbf\x75\x88\x8d\x7f\xec\x87\xb7\xc5\xc0\xa4\xb2\xf7\x55\xca\xee\x70\x73\x86\xbe\xa6\xe8\xad\x95\xf3\x2f\x24\xbd\x97\x2f\x91\xfc\x5b\x6b\xed\xab\x96\x61\x47\x93\x38\xb9\x6f\x08\x72\x27\x1b\x96\x5b\xe8\xd8\x88\xd8\x1c\x06\x7d\xa9\x05\x50\xe8\xfe\x61\x0c\x5d\x85\x6a\xef\xb2\xb1\xe6\xd2\x49\x27\xe2\x60\x8c\x78\x7a\xf5\x52\x72\x20\x9a\xe8\xf0\x65\x81\x03\x80\x83\x29\x74\x15\xf2\xef\xe8\xcd\x8d\xb6\xb4\x07\xff\x1c\x4c\x11\x77\xdc\x5b\x97\x03\x31\x08\x7c\x80\x16\x05\xc8\x67\x61\x03\x92\x39\x0c\xdd\xf1\x84\xba\xd2\xfa\x63\x7c\x6c\xc0\x10\x0c\xdd\x67\x8a\x24\xcf\xca\x3c\x96\x34\xb1\x30\x27\x32\xc1\xdd\x77\x51\xe1\xeb\xf1\xc5\x85\x23\x6d\x89\x69\xe1\x93\x95\x14\x6c\x80\x94\x3d\xc1\xee\xca\xa5\xef\xda\x13\xed\xc3\x32\xe1\xe3\x3e\x1a\x00\x0e\xe2\xe8\x0d\x88\x87\x30\x30\x04\x9d\xb0\xd4\x7a\xf5\xcf\x46\x9c\x2a\x98\x21\xfa\xb4\xc8\x80\xe1\x50\x93\x1a\xa4\x13\x2d\xc4\x52\x53\x0e\xe8\x05\xa2\x19\xfd\x2c\x59\x07\x2a\x66\x97\xc7\x85\x6c\x47\x17\x66\x43\xfb\xbe\x8c\x13\xef\x56\xa9\xdd\x35\x0a\x5b\x38\x66\xda\x21\xdb\xf2\x5c\xfa\x5f\x35\x9b\x04\x7a\xe8\x26\x89\x51\xf8\xaf\xf0\xbe\xc3\xf3\xea\xe8\x7f\xac\x41\x76\x7b\x05\x6d\xc1\xff\x4b\xb6\x73\x36\x61\xbe\xde\xba\x51\xc0\x13\xad\x24\x09\x50\xf5\xa5\xb4\x5a\x82\x75\x06\xc7\xde\x58\x31\x64\x95\x85\xe5\xfd\x44\x0c\x9e\x98\x80\x88\xc4\xda\x44\x32\x60\xac\x6e\x41\x76\xa3\x45\xcc\x28\x94\xd8\x8a\xa8\xf4\xf4\x62\x2c\x70\x80\xf7\xdf\x0d\x70\x8f\x60\x24\xee\xf5\xde\xd9\xeb\xdd\x4e\x1d\x13\x4c\x43\x80\xb1\x3e\xd4\xa6\x59\x20\x06\x24\xe8\x79\x51\xb3\x25\xef\x7d\x9d\x68\xfb\x4f\x7f\x85\xbc\xa5\xf1\x20\xae\x57\x15\xb7\xe9\x7b\x1f\x7e\x70\x24\x2c\x40\x40\x81\xa1\x1a\x55\x93\xa8\x53\xa0\x3f\xaa\xd7\x81\x4e\x13\xe1\x92\x32\x55\x1e\x94\x77\x2d\x08\xda\x63\x51\xb2\xa6\x2d\xbf\x81\x0b\xfe\x54\x7b\x6e\x7e\xe1\xf8\x23\x0b\xf6\xd3\xff\x7c\xf9\xec\xf1\xe7\x97\xce\xa2\x6f\xda\xe1\xe5\x5d\xab\xcf\x56\xd3\x3f\xd1\x7f\xc4\x02\x19\x1d\x86\x85\xc2\x40\xf8\xfe\xf7\x83\x86\xec\x19\x90\xf6\x19\xbd\xf3\xfa\x07\x97\x1d\xf0\xe8\x1e\xaf\x3b\xc1\x06\xed\x64\x54\x4b\x0b\x33\x47\x5d\xb4\x85\x98\x4f\x56\xa3\x5c\xb9\x43\x74\x3c\xb6\x15\x1e\xda\x8c\x42\xd5\xf0\xd2\xfe\x49\xea\x94\xfd\x2c\x83\x45\xe9\x99\x7d\x6f\x95\xd4\x1d\x1b\xbb\xce\x20\x62\xf8\x28\x03\x80\x5c\x6d\x72\xb3\x6f\xd5\x5c\xc5\x06\x68\x37\x4b\x46\xb9\x0c\xba\xdf\x7d\x06\x7b\xa6\xe1\x38\x7d\xee\xc4\x66\x6f\xdd\x66\x2c\x4e\x18\x66\xef\x76\xac\xfa\x6e\x31\x76\xc8\x5b\x26\x0c\x35\xca\xd1\x48\x24\x9b\xdc\xa8\x7e\xa4\xfc\xd4\x28\xf1\x8d\x96\xdd\x2c\xf8\x8a\x04\x88\x22\x60\xe0\x77\xbe\x2b\x05\xbe\x52\x80\x34\xce\x45\x34\xc9\x30\x50\x46\xb7\x92\xab\x51\x4c\x91\x55\x2a\x8f\xd8\xd6\x96\x0b\x74\xc8\x67\xe2\xfb\x04\xa2\x45\xc6\x34\x86\xee\x06\x92\x29\x0b\x88\x54\x39\x09\x4b\x64\x92\xdf\x08\xa8\x0a\x35\x43\x74\x15\xa0\x2e\x94\xaf\x77\x9c\x1b\xa3\x78\x34\x46\x03\x34\x47\xc9\xa1\x23\x20\x7c\x52\x51\x89\x5a\x32\x76\xc7\x65\xd5\xed\x71\x34\x86\xf9\xa6\x44\xae\x42\xb8\xd1\x51\x74\x18\x11\x1e\x3a\x14\x60\xb4\xc7\xb6\x4d\x51\x77\x1f\xeb\x3c\x4d\x5b\xd0\x18\xa3\xfc\x50\xb8\x52\x7d\x8a\xf8\xc9\x95\x28\xc7\x6d\x32\x5a\xa4\x1a\x1c\xde\x14\x73\x02\xb0\xce\x7d\xb4\x05\x8d\x79\x08\x73\x9a\x53\xef\x47\x8b\x93\x19\xb2\x7e\x35\xa8\x90\x03\xd0\xe4\x81\x9b\xdb\xcf\x72\x73\x3b\x42\x3a\x0b\xac\xe2\x5d\xc2\x2d\x1f\x7c\x93\x74\xf7\xf2\x89\x58\xcf\x29\xfb\x85\x68\x7e\x3f\xcb\xcd\xef\x78\xfd\xd1\x36\x49\xfa\xd2\x1c\xe4\x91\xe2\x4e\x35\xc5\xf2\x21\x60\xc6\x35\x8f\xde\x80\x07\xf2\xf6\x0d\xae\x62\x69\x88\xbd\x57\x3e\x52\x35\x29\x06\x87\x1d\xf9\x69\xa7\x05\x03\x96\xa3\x77\x77\x87\x29\x4d\x9b\xca\x78\x62\x97\x73\xde\x3c\xe7\xbd\xca\x78\xe4\xab\x83\xd3\x3f\xd1\x1b\x90\xaf\x65\x18\x88\x00\x03\x01\x80\x2a\xbd\x46\x42\x49\xd6\x0c\xfa\x27\xd5\x9e\xff\xe7\x6f\xc7\xbf\xad\xe4\x7c\x2f\x95\x1d\x13\xc5\xf7\xda\x44\x0e\x98\x44\xe7\x15\x00\xf0\x79\xc8\x6e\x0f\x67\xe3\x30\xed\x22\xd9\x44\x2f\x45\x1e\xde\x8e\xb6\x8a\x96\x56\xbc\x58\xca\x0f\xb2\xd2\x4a\xb2\x06\xc7\xa5\x1d\x79\x6c\xfa\x79\x47\x5b\x49\xc9\xf0\x94\x84\x41\xd9\x89\x8e\x54\xb1\xac\xd4\xa6\xb4\x91\x25\x69\xa3\x07\x5f\x0a\xdf\xb0\x29\x2c\xe5\xf5\xac\x43\xc2\x2b\x12\x63\xab\x64\x02\x80\x5d\xa5\xee\xa0\x1c\x21\x56\x54\xb9\xc7\xec\xea\x05\xfd\x60\xc8\xfc\xdb\xf1\x6f\xe7\x68\x74\x8d\xa4\x75\x68\x74\x89\xec\x0a\xd2\x6d\xaa\x01\x81\xfc\x9e\xe3\x61\x8b\xb7\x99\x70\xdf\x7d\x18\xaa\xfa\x54\x8f\xa5\x5e\xf7\x36\xc2\x69\x9f\xd1\xb7\x0e\xad\x85\x5f\x72\xb7\x5f\x64\x9b\x77\xd8\x7a\x2c\xd7\x5b\xd7\x71\x1e\x3b\x53\xe7\x3d\x49\x25\x0a\x77\x5d\x18\xf0\x00\x40\x4c\x35\xed\x02\x41\xec\x69\x88\x8b\x32\x62\x4b\x4a\xf8\x5a\x97\x04\x18\x41\xc7\xd9\xaf\xb7\x4e\x86\x27\xb9\xe6\x45\xc1\x45\xde\xe7\x51\x44\x11\x55\x2a\xbe\xef\xc3\xd0\xbd\x92\x9b\x6c\x03\x81\x5c\x1f\x3e\xfc\x66\xe9\x75\x92\x4c\x82\x06\xd1\x36\x23\x91\x40\xbc\xd5\x30\x32\xd0\xad\x28\x4e\x2a\x88\xab\xdc\x23\x96\x41\xf2\xb4\xa2\x94\x62\x82\x68\x63\x91\x49\x21\xdd\xcf\x4a\xe9\x4b\x9c\x0c\xc1\x52\x19\x7a\x31\x56\x8f\x12\xfb\x10\xc6\xb0\x50\xe0\xbe\xd4\xd2\x82\xf0\x5e\xe2\xf0\x86\xca\xf1\xa2\xd6\x54\x70\xce\x60\x9a\x53\xc1\x78\x89\xb7\x4b\x4a\xe9\x56\x7c\x06\xd9\x06\x48\x10\x82\xda\x84\x36\x13\x94\x91\x4b\xb7\x33\xa6\xfa\x1d\x1f\xa9\x77\xbf\xdb\x27\x12\x12\xeb\xbc\x43\xb7\xa2\x18\x30\x45\x3d\x13\x33\x74\x41\xe1\x36\x3e\x17\x8e\x3b\x4e\x9f\x10\xbe\x08\x33\x28\xcb\x4f\xed\xdc\xfd\x52\x2b\x3e\x83\xba\x02\x48\xd0\x03\x84\x09\x28\x3c\x5a\x48\xde\x46\x67\xd9\x58\x09\x1e\xaa\xb0\xa5\xe5\xce\x71\x01\x13\xce\x60\xc2\xa3\x4c\x41\x08\x93\x59\x89\x0a\xf7\xd8\x4c\x32\x64\xe1\xa8\x59\x29\x3c\xaa\xce\xc7\xd3\x25\x8e\xa7\x1e\x62\x84\x3e\x54\xe3\xd9\x81\x63\xb8\x61\xc9\xc5\x3a\x4b\xe8\x4b\x88\x17\x1c\x98\x00\x60\x7a\xec\x01\x5d\xf0\x08\xea\xe6\x43\x96\x8c\x4b\x2d\x2d\x70\x30\xc7\x03\x06\xc6\xd3\x55\xa8\x8f\xde\xc8\x8b\x43\x76\xd6\x66\x7a\x1c\x2f\x3e\xec\x9a\xf8\xae\xe5\x87\xeb\xbb\xdf\xed\x63\xcf\x01\xbd\xe9\x2a\xd4\x7f\x6f\x66\x6c\x71\x49\x7b\x0c\x92\x7f\x8b\x5b\x83\x09\x2c\x22\x49\x5b\x08\x19\x06\x4a\x00\xa0\x4e\x9b\x6a\x85\xdb\x3f\xb3\x0b\xda\xa0\xdd\x1c\xea\xb1\x43\x3b\x6e\xa7\xc4\x0b\xbe\x04\xba\x21\xf6\x42\x00\xd6\x04\x23\xe8\xdf\x9e\x3c\x99\x1d\x47\x78\x73\x5b\x76\x05\xf4\x71\xbd\x87\xf9\xd4\xca\xbd\x32\xe2\xd0\xdd\x62\xbc\x12\x46\x3d\x73\xb7\x83\xc4\x76\xde\xe9\x68\xa1\x92\x44\xba\x25\x13\x00\xea\x79\xca\xc6\xc6\x0c\xa8\x45\x04\x6a\x84\x00\xfa\x60\x28\x83\x01\x5f\x68\x53\x86\xff\x61\x1f\x72\x90\xa4\x71\x80\x95\xaa\xc1\x7f\xc4\x55\x91\x72\xe2\x39\x71\x0b\x37\xfd\x4a\x4e\x7c\x7a\x5d\x87\x94\x8f\x04\x0b\x5f\x8d\x14\xd1\x79\x0a\x71\x42\xde\x02\x89\x20\xa3\x6b\x9c\x88\x23\x18\x0c\x91\x72\x85\x83\x64\x84\x14\x72\xb6\xe8\xdc\x09\x4a\xe8\x56\xea\x34\xd9\x26\xbc\x02\xa8\x73\x12\xee\x8f\x14\x58\xea\x5b\xda\x2a\xac\x28\xce\x0b\x28\x76\x34\x91\xd9\x91\xba\xca\x4b\x78\x57\x88\x81\x4d\x3c\x2c\x23\xcc\xf8\x50\xa2\xb9\x42\x1e\x33\xb9\x41\x30\x88\x64\x75\x87\x0b\xc5\x46\x40\xb6\x76\x91\x74\xa2\x7c\x0a\x3f\xa6\x7a\x0f\xee\x73\xf8\x08\x7d\xee\x53\x7a\x38\x15\xe6\x3e\x88\x15\xf8\xe6\x48\xd1\xcc\x3b\x39\xb8\xe3\x6e\x31\x71\xea\xf0\x7f\x3a\xbe\x92\xcd\x0f\x22\x99\xbc\xc5\xe6\xea\x95\x46\xa6\x8a\x19\x90\x4f\x07\x2e\x2a\x75\xf3\x71\x21\x0e\x55\xb8\x5b\x10\x05\xa4\x56\x8a\xa2\x50\x85\x21\x47\xe3\x4d\x1e\x23\xdb\xd8\xf8\x07\x85\x5c\x66\xe9\x60\x2b\x05\xbb\x28\x1a\x66\xa9\x60\xb2\x7d\x1a\x9d\x09\x89\x59\xac\xdf\xba\xb6\x6c\x66\xf9\x90\x2a\x85\x9b\x25\x1a\x42\x35\xe1\xa4\x73\xab\x84\xbe\xc4\xc9\x67\x51\x93\xcf\x63\x33\xa9\xca\xc5\x6d\xe1\x72\x99\xd8\x3d\x3c\x93\xbe\xc4\xc9\xa2\xa8\x48\x28\x92\x05\x6d\xe7\x1a\x32\x94\x31\xcd\x6b\xe1\x17\xf6\xf5\x12\xba\x8a\xc3\xde\x5f\x89\xbd\x97\xf4\x01\x43\x55\x8a\x50\xf1\xee\xa0\x94\x46\xb4\x4f\x70\x63\x54\xc5\xc9\x35\x48\x57\x2e\x49\xc7\x1a\x12\x36\x8b\xbb\xd6\x92\x54\x02\x80\x40\xf7\x4d\x8d\x01\xb3\x50\xbd\xac\x54\x90\x25\xaa\x4b\x8b\x11\x8a\x9a\xb4\x30\x83\x3d\x7d\xb0\xa9\x45\xb9\x33\x8f\xef\x1d\x9b\xab\x58\xdb\x46\xbf\x77\x85\x2b\x56\xbb\xf5\x3b\xb6\x58\x2d\xa4\xb2\xdf\x4c\x1e\x3d\x7c\x68\xec\xd8\xf4\x05\xfd\x37\x94\x24\x15\x64\x65\xda\x9c\x69\x51\xbb\x33\x16\x24\x5d\x18\xf0\x76\x99\xb8\x96\xed\x3f\xe8\x29\xb7\xd8\x32\xb6\x9f\xc0\xf9\x7f\x40\x65\x6c\xf1\xf8\xbf\xc5\x38\x62\xe6\x2e\x79\x22\x66\x60\x4c\x7c\x16\x8c\x09\xcf\x7d\x62\x94\x65\x70\xeb\x70\xf6\xdd\xe3\x36\x31\xdc\x14\x28\xc2\xaf\xcc\x15\xef\x7b\xcf\xd4\xc5\x5f\xb1\xf5\xbf\xad\x1f\x5d\xdb\x7c\xe7\x95\x8f\xff\xf0\xee\xda\x15\x95\xaf\x4d\x7f\xbc\xaa\xfa\xd0\x8c\xd1\xba\xc8\xe1\xf6\x8f\xe1\xa4\x63\xb7\xce\x7c\x48\xbf\x73\xe2\x2f\xef\x3f\xb5\xb1\x19\x52\x6f\xd4\x6c\xda\x4a\xdf\xc3\xde\xd4\xc2\x4c\x72\x9c\xc7\x70\x98\x87\x83\xa2\x6e\xb0\xae\x7e\xa7\xd1\xf5\x21\x08\x1f\x9e\x5a\x92\x39\x24\x2e\x0d\x2e\xe7\xef\x3a\xba\x36\x18\xeb\xd2\xf3\x64\xf7\x1f\x24\x3b\x26\xd4\x79\x89\x7c\x5d\x1d\x15\x75\xf9\xba\x32\x44\x4a\xc9\x8c\x0e\x96\x52\x26\xe9\x3a\x89\x41\xb1\x59\x7a\x23\x26\x79\x58\xd3\x1b\x94\x4c\xc9\xb3\x9a\x3f\xea\x25\x8f\x7e\xec\xdc\xb7\x71\x73\x9f\xc5\xa4\xc7\xb2\xf4\xb1\x4f\x95\xc8\xf5\xd2\x47\x3e\x4d\xba\x7e\x23\xc5\x21\xe5\x66\x90\x7f\x6e\x84\xc7\x37\xff\xd4\x70\x4f\x6f\x06\x98\x11\xbf\xbf\xc9\xb9\x19\xe4\x9f\x1b\xdf\x83\xa0\x0e\x35\xfc\x43\xa0\x1e\x33\x62\x1c\xec\xfb\x67\x93\xa9\x06\xf9\xf2\x46\x0b\xde\x51\x40\x5c\xee\xc1\x2c\xbe\x54\x80\xc5\xbf\xff\x13\x7d\x92\x3e\x23\x94\x81\x5f\x22\x98\xff\x1f\x7d\xf8\x5f\xfa\x27\xbe\x0c\x3c\x0c\x95\xf8\xf8\xb0\xf9\x2d\x28\x1b\xf2\xed\x48\x94\x65\xb8\x50\xcd\x69\xe1\x33\xfa\x45\xd9\x2d\xf8\x74\x72\xa2\x84\x16\x30\x90\x03\x20\x64\xb6\xe0\x32\xc8\x49\xd3\x59\x60\xdf\x48\x7d\x8e\x58\xb9\xdd\x48\xee\xfe\x1a\x72\x4b\x7d\x7a\xe4\x82\xef\x16\xcc\x37\xa9\xe0\xbc\x37\x0f\x27\x33\x8a\x43\x46\xbe\x3c\x06\x64\xf6\xf5\xe8\x47\xe8\x22\xfe\xc9\x46\x57\x68\x7c\x29\x8f\x05\xc9\xfb\x3c\x7a\xa7\xb0\xf0\xbe\x3c\x21\xc1\xa4\xb4\x20\x87\x4c\xe0\x7c\xf8\x09\xbd\xf5\x5f\x9f\x5d\xbc\x5d\xbf\x67\xcf\x07\x5f\x3c\xbd\x6d\xe7\x41\x9f\x0b\xd3\x0b\xf4\xc1\x2a\xef\x5a\x6c\x86\x77\x1f\x76\x67\xff\xcb\xb5\x0b\xe1\x4e\xd1\x1b\x42\x26\x00\xf8\x52\xf2\x16\x08\x45\x33\x4a\x91\x32\x44\x6e\xab\x4a\xf2\x85\x54\xc3\x08\x9f\x9d\xea\x4b\x16\xd2\x93\x94\xfa\x25\x11\xcf\x73\x6f\x14\xb1\x32\x59\xb4\x9c\x1c\x7d\xc2\xac\xe3\x6d\xc5\x18\x56\x2a\x89\x34\x82\xa1\x48\x0c\x61\xc4\x62\x6d\x2e\x40\xb7\xa2\x3c\x28\xbd\x50\xc6\x61\x69\x5d\x57\x99\x6c\x7c\xdb\x2a\x82\x89\xae\x20\xa4\xa2\x71\x7e\x8a\xad\xc4\xf3\xd4\x29\x4e\xa6\x81\x06\xa4\xc2\xd9\x6b\x0a\x1d\xc9\x22\x58\x83\x55\x5b\x3c\x68\x69\x69\x01\x38\x92\x6f\x33\x59\x8d\xe4\x1b\xe0\x4f\x42\x46\x17\xe9\x48\x39\x43\x76\xdb\x22\x15\x95\xb8\xca\xda\xb1\xc8\xb7\x8a\x1b\x43\xde\xef\x82\x97\x16\xd9\xc8\x50\x7d\xec\x90\x09\x4e\x1f\x50\x1b\xb8\x4b\x2d\x2d\xc4\x40\x61\xcc\x3a\xa7\xd3\x97\xd0\x98\xe1\x20\x9c\xbd\xa3\x81\x8a\x79\xf8\x73\xd4\xd8\xbb\x2a\x23\x85\xae\x6f\xe4\x83\x84\x01\x67\x67\x3b\xe1\x34\xb9\xc1\x40\x90\x0c\x80\x87\x8f\xd9\x40\xe1\x59\xbe\x4c\x90\x42\xa6\x1a\xc2\x36\x40\x34\xd3\x9d\x07\xde\xda\xf5\xde\xa3\xcd\x3b\x56\xac\xb9\xb1\xe1\xec\xc1\xc2\x11\x7b\xc6\xac\x7b\x65\xc2\xd3\xcd\xf3\xd2\xe9\x6f\x3a\xc1\xaf\xe1\xaf\xb8\x49\x9f\x74\xbc\x6c\x73\xfd\xb8\x95\x25\x53\x0f\xaf\xa8\x3b\x5d\x5d\xb6\x6b\xe0\xe0\xf5\x35\x13\xe6\x8d\x7b\x78\xee\x9a\xc9\x17\xff\x4e\xfd\xca\x77\x2e\xec\xd9\xd9\x8e\x8f\x23\x6f\xf1\x58\xfc\x64\xcd\xa1\xec\x62\x2c\x9a\x29\x73\x6e\x9c\x3b\x0e\xa7\x72\x48\x74\xd2\xe5\xbc\x7a\x8c\x5c\x29\xbe\x1f\x70\xd2\xad\x84\x93\x3c\x07\x06\x82\x14\x63\xbc\x88\xef\xc1\xf5\x89\xa9\xe4\xa7\x9a\x2e\x31\xdf\xfb\xce\xe4\x3d\xe9\x56\x94\x4b\x88\xc3\xe2\x9f\x17\x31\x16\x3d\x62\x86\xf3\x48\x74\x89\xf9\xde\x77\xce\xc4\xd1\x7c\x59\x61\xaa\x41\x63\x94\xd9\xe5\x19\x63\x15\x36\x40\x3f\x73\x67\xe2\xf0\x94\x92\xcc\xa4\xb8\xb4\x4f\x5c\xcf\x26\xfd\x7a\xd0\xc5\x22\xfd\x39\xf4\x19\x6b\x3c\x3e\x82\xb6\x43\xd7\xaf\xd3\x01\x8e\xe6\x52\x1d\x65\xf3\xe1\xf4\xcf\x9a\x59\x0d\xa7\x1e\x7d\x4f\xc9\x40\xea\x4f\xaf\xc7\xe4\x20\x05\x3e\x8b\x03\x62\xc0\x40\x90\x06\xb2\x0d\xf2\xe9\x76\x85\x5b\x19\xc3\xc9\x44\x99\xec\x71\x66\xc3\xeb\xb1\xf7\xe2\xe9\x93\x17\x6d\xad\x4d\x3c\x9d\x7b\x74\xd0\x74\x0e\xba\x2e\xaf\xa6\x45\x91\xc5\xcb\x67\x4f\x8f\x8c\xdb\x3f\x67\x09\x0c\x61\xe1\x03\x8e\xdb\x56\xea\xbc\x0f\xb3\x01\x6e\xb5\x30\xeb\xf1\xdb\xa0\x02\x58\x97\x63\xaa\x9f\x0a\x60\x9c\x5d\xcb\x48\xc7\xa5\x30\xa7\xd5\xae\xae\x66\xc3\x1a\xaf\xd2\xe7\x8f\x6b\x44\xf5\xf1\xeb\xca\xf4\x8d\xc8\x57\x1a\xad\x75\xa4\x03\x39\xac\x5d\x5b\xed\x06\x35\xa2\xb0\xf0\x61\xb4\x11\xd5\xc8\x23\xa5\xb6\x0b\xf7\x69\x27\xb9\xd8\x15\x13\xaa\x92\xec\xb1\x99\x6c\xd0\x2e\x36\xb6\x4e\xda\xf1\x6b\xb1\xf4\x12\xba\xfd\x17\xd0\x3c\x82\xb7\xb1\x2c\x7b\xf7\xde\x6d\x27\x2d\x70\xb7\x4f\xe7\x4f\xeb\x6c\xc7\xbe\xa5\xae\x72\x75\xbb\x84\xf4\xa9\xd2\x4a\x25\x1e\x71\x96\x84\x69\xa2\x44\xa9\xa1\x42\x82\xdd\xd0\xba\x67\xb9\x5e\xf0\xd3\x5c\x2a\xd4\xc9\xf1\x7c\x5e\xdd\x11\x25\x58\x29\xb6\xcd\x87\x9d\x8b\x2f\x31\xa1\xb7\x0b\x16\x7b\x0f\xf1\x25\xab\x18\x3c\x7d\x4c\xb8\xfa\xe3\xe0\xff\xf4\x57\xdf\x7b\x12\x98\x46\xb7\xa2\xdc\xc1\x6c\x9e\x0a\x2d\xfc\x66\xf1\x9b\x8e\x96\x00\xcb\xf8\x8e\x34\x24\xb8\x97\x29\xea\xf7\x61\x2e\x06\x04\xe7\xaa\x43\xa2\x17\x1e\x66\x0c\x1e\x46\x16\xc0\x30\xb1\x04\x97\x5a\x5a\xa8\x11\x2c\x76\x64\x47\xfc\x99\xbe\x84\x30\xe3\x28\x02\x91\xf9\xae\x26\xee\xfe\xa8\xb5\xc9\x1a\x88\x91\x81\xf2\x0f\x55\xb0\x0c\xc6\x10\xba\x0a\x61\xec\x8d\x32\xc3\x48\xdf\x88\x38\xb4\x21\xe2\xeb\xb3\x03\x62\xd0\xa2\x3b\x33\xea\x4d\x1e\x3c\xd6\xf9\x73\xba\x0a\x61\xef\x8d\xea\x38\x48\xdb\xd4\x94\x62\xba\xb8\x97\x13\x5a\xc2\x88\x7a\x24\xa7\xa9\x0b\x85\x83\xbd\x74\x2b\xb9\x8e\x6c\x43\x59\x2b\x92\xf8\xb8\x63\x3e\x3a\x1a\x45\x30\x13\x7c\x84\x99\xf2\x2a\x65\x6f\xdf\x0f\xda\x3e\xec\x11\xf4\xdc\xf3\xaf\xbf\x9f\x78\xae\xed\xfc\x50\xfa\x4f\x3f\x7c\x75\x63\xa3\xc2\xf3\x05\xae\x1b\xff\x18\xbe\xa2\xa3\x61\xe0\x92\x81\x2b\x9f\x7e\xf3\x57\x78\x5b\xc7\x70\xfa\x3f\xf7\x7e\x47\xa7\x29\xfc\x5e\x70\xb0\x9c\x6e\x45\xf9\x8c\xfa\xb2\xf1\x49\x8a\x9c\x46\x82\x0f\xb6\x3a\x22\x49\x66\xa3\x6f\xb7\x72\xd9\x8c\x72\x15\x90\x64\xf9\x8d\xee\xb5\x9d\x7b\x6c\x41\x33\x5d\x2b\x07\x84\x81\xbd\xf4\x06\x8e\x9f\xc1\xda\xec\xa8\x38\x54\xa8\x52\x13\xa5\xea\x55\xa1\x41\x8f\xf7\x0b\xa9\x83\x05\x6b\xc7\x3d\x4c\x6f\x40\xfc\x84\x21\xef\x3a\x55\x4f\x55\x0d\xc6\x1e\x56\xed\x7c\x92\x2a\x61\x72\xe7\x0e\x6c\xa5\x1a\x5f\x2c\x3f\x55\x1c\x3f\x03\xb5\xf9\x91\x4c\x6b\x55\x66\x86\x4b\xde\x43\x35\x08\xf9\xa5\xec\xde\x7b\x39\x5d\xc5\xcd\x95\x38\xbd\x99\x22\xe9\x5d\x7d\x82\xf4\x12\x77\xaf\x3e\x37\x4c\xe2\xce\x71\xb0\xb7\xb3\x9d\x5c\x17\x30\x0b\xcd\x8b\x0c\x4d\xc9\xf5\x2f\xbb\x55\x99\x80\x9b\xf4\x2f\x8b\xd5\xb9\x21\x17\x6a\x5d\x15\x33\x6b\xaa\xb3\x9d\x98\x87\xfc\xdb\x91\x7f\xb3\x26\x53\xfa\x68\xd5\x99\x83\x41\xba\x70\x55\xb9\x24\x66\x68\xdf\xc5\xb3\xbc\xc6\xa0\x78\x3c\x07\x9b\xb7\x51\x9d\x59\xde\x45\xc1\xa0\x56\x82\x57\x90\xe6\xb7\x71\x66\x17\x5c\x3e\x2c\x2d\x61\x50\x76\x62\x5c\x8a\x16\xa1\xcf\xb5\xb4\xc0\xd9\xdc\x25\xae\x2b\x9f\xd3\x07\x04\xcb\x25\x75\x1e\xf4\x05\x51\xc0\x09\x5c\x7a\x6c\x6a\x23\xd4\xa0\xf2\x21\x0d\x88\xea\x24\xd6\xa9\x00\xc4\xc0\x29\x00\x48\xa7\xc9\x05\x02\x91\xef\xaf\xcb\x1c\x1e\x66\x62\xb3\x93\xda\xd5\x94\xc5\xa9\x13\x33\xcc\x90\xc8\x9c\x0b\xaf\x9d\xeb\xf8\xf1\xd3\x22\x55\x0d\x41\xb6\x75\x3c\xfa\x56\xcd\xa0\x0d\xbf\xc4\x77\xde\x2d\xa6\x12\x15\x4a\x09\x03\x15\x00\x10\x31\xe4\x4d\xa1\x4f\x21\x23\xaa\x6a\x9f\xe2\xb4\xa8\x47\xda\x03\x55\xfb\x14\x65\x47\xbd\xd7\x46\x5c\x55\xe9\xf3\x14\xdd\x4a\x3a\x79\xff\x24\x89\x9c\x62\xd3\x44\x2a\x9f\xcb\xf7\xe8\x29\x12\x49\xfa\xee\x58\x41\xb7\xa2\xdc\xae\x7c\xbb\x3e\x59\xc4\xed\x4a\x65\xe8\xe7\x7b\xd9\x14\xc1\x96\xb6\x7b\x0d\x00\xd3\x26\x53\x0d\x88\x46\x76\x95\xcb\x6c\xb5\x98\x5c\xa1\x6c\x9d\x5a\xf6\x07\x68\xc7\xe3\xdc\x76\x54\xaa\x96\x39\x5b\x84\xd9\x87\xc0\x6b\xc7\xa3\xb1\x9e\x54\x65\x06\x6c\x79\x2f\xbe\x27\xa4\x66\x38\x61\xfd\x27\xde\x05\xef\x27\x05\x50\xe6\xd1\x74\xea\x29\x6c\xe0\xe9\xf8\x79\x4b\xf2\x9f\x25\xdb\x3a\x1a\xcb\xe6\xef\x82\x3d\x97\xe2\x33\x3a\x0e\xee\x69\x2a\x85\xc4\x4c\x7c\xe5\xdd\x62\xfc\xc8\x86\x6d\xc3\xf7\x77\x58\x4d\xb3\xc2\xd6\x1f\x8c\xc8\x7f\x0f\xe1\xa8\x05\x80\xb2\x52\x36\x01\x87\xc5\xe4\xca\xc1\xa0\xcb\x6c\x45\xfc\x99\xd9\x82\xb9\xf6\x3e\x62\x18\xb5\x47\x43\x7b\x06\xf4\x9a\x58\x00\x03\x3e\xb5\x13\x58\x40\xfa\x82\xdb\x1f\xd1\xc4\xd5\x18\x2c\xc0\x35\x89\xbe\x79\x19\xbe\xc7\xa2\x20\x8a\xbd\x93\x46\xbd\xdb\xff\xd3\x6d\x58\x86\xf7\xf8\x9d\xac\xa4\x5d\xff\xc1\x22\xef\xb5\x61\x25\xcd\xef\xaf\x7d\xdf\xdb\x4a\x05\x8a\x30\xf8\xb8\x70\xfa\xe7\x82\x57\x3f\xfe\xc8\xf8\xbd\x70\xc7\xad\xcf\x86\xc8\x93\x4e\xca\x87\xd3\x2f\x1f\x3c\x14\x7d\x42\xb0\x4a\xc1\xb3\x45\x8f\x11\x89\x4f\x0b\xce\x71\x12\x0f\xa2\xc1\x20\x14\x5f\xab\xcf\x8a\xba\x5a\xf1\x47\x51\x84\x8a\x83\xb4\x1f\xb2\xe4\x4e\xd3\x08\x2b\xe2\x8c\xbc\x22\xc2\xaa\xc3\x9a\x3a\x54\x3f\x73\x6a\xaf\x02\xa9\x3e\x99\x64\x85\x12\x27\x3f\xcf\xdc\x08\xa7\x71\x46\xfd\xb1\x78\x45\xb8\x61\xf7\xc3\x9d\x38\x2e\x84\xe3\xec\x96\x80\xc5\x10\x63\x7e\x26\xda\x2c\xe1\x16\x5e\x97\x1b\x89\x9f\xd0\x35\xba\xd5\xb4\x89\x6c\x03\xd1\xe8\xad\xcf\x3f\x27\xc6\xa6\x16\xac\x14\xa9\x56\x5d\x56\xc4\xbe\x39\xb5\x74\x2b\x65\x25\x8a\x05\x2c\x7e\x38\x31\x36\x75\x12\x45\xca\x58\x87\x15\x11\x8e\xce\xed\x00\x10\x37\xf8\xf8\x10\x7b\x0f\x54\xe6\xbe\x07\xb4\xe3\x3d\x44\x43\x51\x8d\x3d\x44\x77\xfc\xe2\x57\xf0\x9d\xcf\xbc\x57\x60\xd8\xe9\x8b\xb4\x03\x73\xf0\x07\x74\x0a\x3b\xea\xbd\x88\x25\x7b\x8b\xbc\x18\xb6\xda\xbb\x5e\x1c\xab\xd1\x79\x1c\x00\xc2\x42\xde\xe2\xda\xe6\xb3\x79\x4b\xdb\x16\xa5\xf2\xee\x78\xf7\x3d\xfa\x08\xe4\x8f\xfe\xbe\x34\xde\xde\x2f\xe1\x21\xba\x4c\x18\x4a\x9c\xc3\x2c\xc4\x4b\x68\xa0\x16\x2f\x39\xa5\x04\x2a\x11\x13\x0a\x59\x94\x0a\x00\xe7\x64\xba\x22\xf4\xed\x93\x0a\x6a\x1c\xcb\xe4\x12\xfe\x4e\xd1\xb1\x42\x54\xc5\x8a\x46\xb6\x0d\x71\xc1\xe4\x06\x01\xe8\x9e\x03\xf5\x29\x4d\x38\x79\xea\xdd\x23\xf0\xc6\x05\xef\xf3\xcb\x7e\xb1\xea\x17\xbe\xf0\x1d\x3b\x76\xbd\x63\x81\xf7\x26\xe6\x20\x9e\x17\xee\x69\x3a\x73\x69\x0b\x11\x43\xde\x42\xe7\x4c\x36\x4e\x2b\x97\x11\x83\xd9\xee\x73\x20\xb3\x0c\xe4\x11\x5a\xa7\x73\x47\x95\x3c\x96\x31\x7a\xff\x89\xd1\xbd\x82\xa9\x7e\xf3\xfb\xc3\xdc\xd3\xde\xd1\xd3\x4e\x35\x4c\xcc\xc5\xde\xe6\x1f\xfa\xde\x0b\xad\xaa\xa8\x27\xa6\x79\x6f\x8e\xfd\xe7\xac\xfc\x3f\x67\x62\xd3\xee\xd2\x87\x36\x86\x99\x3c\xa2\xf9\xd0\x0e\x00\xb1\xdd\x54\x83\xe2\x9a\x7d\xd9\xd7\x4d\xd0\x2d\x3e\xa5\x58\xa2\xf0\xcd\xde\x35\x76\x7c\x4e\x64\xc7\x72\xec\x88\x8d\xce\x16\x1d\x4f\x9a\x89\x86\x7d\x2d\xf7\xea\xf7\x51\x89\x91\x92\xe3\x10\xc0\x50\x8d\xa5\x17\x29\x9b\x7e\xdb\xd2\xd4\xee\x91\xf4\x1c\x51\xdb\x5c\x6e\xf7\xf5\xc4\x55\x45\xdb\xed\x74\x2b\xb1\x1d\xc5\x63\x87\x49\xda\x16\x0d\xb2\x0c\xb5\xf7\x38\xbf\x12\x79\xc8\xe2\x35\x77\x93\x6e\x45\x39\xe8\x75\xda\x93\x23\xed\xc5\xb7\xc7\xc3\x14\xb7\xd7\x4e\x5f\xe2\xf0\xf5\x96\xb4\xe7\xb1\xc9\xd9\xec\xa0\x19\x33\x5b\xc0\x84\xbc\xb6\x18\x3c\x97\x38\x3c\x8a\xef\xcb\x70\x78\x67\x32\xdf\x17\x30\xb0\xdf\x67\x7d\xcb\x50\x6c\x49\x8c\x6e\x6c\x09\xeb\x5d\xa6\x15\x51\x32\x89\x73\x19\xd7\x88\x97\xba\xc4\xc6\xd8\x4d\xeb\x6c\xc7\x83\xa9\xf3\xc2\x09\x49\xff\x96\x4e\xb9\x1a\xb5\x2e\xec\xec\x4a\x75\xa0\x71\xf7\xf8\x92\x22\x96\x8a\xb5\xa3\x1a\x91\x2e\x77\x77\x41\x9b\x8b\x53\x27\xf9\xd1\xec\x5f\xd5\xcd\xae\x5c\xfb\xc4\xa3\x8f\xae\x59\x94\x95\xe1\x1a\x31\xc2\x95\x92\xe7\x67\xe3\x3b\x3a\x67\xe5\x8a\x39\x95\xb5\x2b\xe6\x0a\x59\x8a\x70\x76\xdd\x53\x8d\x28\x13\x4f\x8a\xbf\x95\xaf\x82\x51\x47\x0d\x24\x29\xf0\x69\x29\x84\xf5\x72\x60\x6c\x4e\x91\x79\x54\x31\x08\x05\xb1\xe8\x66\x47\x99\xe5\xc9\x23\x73\x81\x61\x11\x79\x10\x48\x65\x6e\x27\x71\x79\x82\x12\x4b\xd6\xb8\x64\xa7\xb5\x78\x5e\x8b\x34\xa9\x93\xb8\x38\x01\xd6\x3a\x6f\x74\x4e\x42\xda\x82\xc5\x65\x0b\x9f\x06\x00\x43\xf5\x35\x16\x9b\x66\x01\x2b\xa3\xe1\x7d\x15\x36\xb8\xe4\xca\x26\x85\x7a\xa4\xe9\xe1\xee\xc6\x24\x68\x89\x3f\xf0\x73\xf7\x42\x7b\x4a\x71\xf6\xd4\x69\x56\xfa\xeb\x41\x07\xd6\x8f\x1a\x86\xf7\xf6\xc5\xae\x7e\x4b\xc6\x7c\xf2\x46\xdf\x3e\x4d\x51\x73\x57\xde\x3d\x2f\x09\x5b\x05\x10\xe4\x77\xb6\x93\x16\xf2\x1c\x1b\x9d\x13\x0a\x98\xde\x50\x92\x3d\x20\x2a\x9a\x17\x97\x08\x9d\x70\x08\xb4\xc7\xf6\x82\xf9\x9f\x0d\x85\xa9\xff\x3e\x72\xcd\x41\xbf\xfd\xd2\x61\xfa\xd2\xbd\x4b\xab\x0a\x5e\x2f\x7d\xed\x37\xaf\x6c\xcc\xc7\x60\x4d\xe4\x63\x73\xe9\xb6\x92\xcf\xf0\x36\x68\x82\x41\x47\xf6\xd3\x17\xc3\xce\xec\xbc\x4e\xff\x38\xf1\xe0\x90\xb4\xa3\xdb\x97\xaf\x69\x84\x65\x13\xc7\xd3\xeb\x3b\x26\x30\x73\x62\x13\xdd\x2a\xe4\xf8\xea\xe7\xcb\xf0\x25\x9e\x02\x8a\xac\x5e\x90\xe0\xb5\x51\xbe\x2c\x9b\x17\xaf\x94\xf0\x3d\x7c\x16\x2f\x3e\x6f\x0a\x9b\xc7\x2b\xd6\x97\x33\x46\x67\x7c\x25\x69\x53\xf4\x46\xd7\xe9\x7b\xa4\xd1\x1a\x5b\x5f\xca\x14\xbc\x73\x13\x00\x84\xdd\x74\x13\x98\x40\x10\xbb\x77\x73\xb2\xb2\xf2\x99\xb9\xbc\xf8\x54\x1f\x68\xf7\x70\x69\xa8\x45\x32\x17\xb2\xa2\x8e\x1f\x3c\x76\xd9\x9a\x65\x73\x22\x97\x59\xa6\xcd\xca\x76\xd9\x78\xc9\xb1\x6a\x56\x60\xfc\x91\xf9\x41\x65\xe3\x1f\x7a\xc4\xba\xf0\x44\x1f\x57\xca\xa0\x7e\x42\xce\x9c\x79\x54\x33\x92\x3f\xdd\xc8\xfc\x56\x41\xa2\x3f\xcb\x1f\x91\xa2\xd2\xa6\x83\x88\x50\xe0\x23\x18\x5e\xc8\x85\xa6\x8b\x88\x17\x94\x83\x4a\xc6\x0c\xee\xc9\xf0\xb8\xfa\x43\xab\x09\x6d\xa2\x82\xa3\x97\x92\x9c\xbd\x01\x6f\x97\xbd\x17\xfa\x70\xb2\x69\xd4\xb4\x39\x8d\xf5\xf0\xda\x33\xa9\xc7\x06\x6f\x2e\x90\x73\x84\xc5\x44\xbe\xbc\xd0\xfd\xf2\x30\xab\x67\xe9\x82\xec\x4f\xfb\x3e\x33\xda\x3a\xb8\x36\x91\xcb\xc1\x41\x26\x52\xf5\x9c\x1e\xf0\x18\x99\x29\xea\xc8\x74\xc9\x7a\x5c\x15\xa4\x8e\x76\xb8\xaa\x0a\x97\xe5\x8d\x48\x47\xbc\xf5\x61\xef\x80\x85\xfc\x78\xe8\xf6\x20\xce\x69\x56\xe3\xcf\x47\xdb\xdf\x5a\xdc\xf9\xe5\xa5\xd3\xa6\xa9\x91\xc7\x93\x66\xba\x58\xfd\x68\xf8\xb8\xa7\xee\x1e\x55\xe1\x8e\xe3\x8c\x98\x87\x38\xeb\x07\x06\xb1\xb7\xb1\xca\x1c\x79\x3c\x1c\x1d\xee\x94\x94\xed\x66\xd1\x45\xf8\x98\x5b\x23\x65\x4e\xc2\x18\x79\x81\xc5\xf9\xa3\x16\x73\xdc\x3c\x8b\x0c\x48\xe5\xe6\x59\x8a\x9f\x79\xa6\xb6\x0a\xfc\x4e\xb9\xbf\x85\x17\x3c\x34\xfd\xa1\x31\x41\xa5\x01\x05\xa3\x92\x9c\x09\xba\x53\x0f\x1e\x29\xa1\xb2\x87\xe5\x8d\x0a\x89\x9f\xdd\x2b\xce\x11\x6d\x01\x3c\x9f\xd7\xa9\x1b\xdc\x1c\xcc\xef\xf2\x1c\xec\xf2\xda\x5d\xa3\x2b\x80\xc1\x69\xa9\x22\x0a\x37\x3f\x2f\x04\x54\x70\x7c\xa7\xfb\xe1\x1b\x47\x62\xa2\xad\xc6\xe3\x42\x0f\xe4\xe8\x71\x5a\x65\x99\xef\xa1\x4e\x8d\x7d\x2f\xf8\x61\x57\x8f\x51\xd3\x67\x6f\x58\x93\x3c\xf4\x48\xc2\xe8\x01\xf6\xdc\xe8\xf8\xb4\x7e\xf3\xb2\x0e\x25\x8c\xb1\x0f\xc8\x89\x4e\x70\x59\x55\xb8\xdf\x5b\x91\xfc\xf2\x08\xab\x67\xe9\xc2\x2c\x58\x7e\x3d\x2a\x24\x34\x66\x70\xfa\xf5\x18\x4b\x48\xbf\x24\x97\xc0\x7d\x8b\x29\x98\xe3\xbe\xb0\xcb\xdc\x6b\x49\xa0\xcb\xff\x13\x86\x84\xd1\x1d\x07\x5d\xb1\x98\x71\xa0\x5b\x89\x42\x53\x0d\xb7\xc7\x0e\xd2\xdd\x65\x71\xc9\x81\x45\x67\xcf\x3d\x28\x3a\xbb\x68\xee\xbf\x58\x8c\xf4\x30\x43\xb0\x7b\x31\x65\xe3\xf6\xe2\x61\x5d\xdc\x8d\xcd\x12\x74\xc6\xf6\x66\xf1\xf3\x96\x81\x7d\x9a\xea\x23\x3b\x7f\xb1\xf3\x78\x5a\x80\x19\xcd\xe3\x48\xb1\x9e\xe5\xe7\xb1\x0b\x15\x98\x77\xb1\x09\xd8\xb4\xb7\xa7\xd5\x4b\x03\xcb\x26\x6c\xf7\xac\xb0\xbd\xde\xb0\x66\xdb\x8f\x73\x26\x1e\x4d\xdc\x97\xa7\xd8\xc0\x9d\xf9\x59\x75\xf5\x4d\x2d\x35\xd6\xb2\x55\x61\x49\x4f\xc4\xf9\x74\xec\x69\xc4\x59\x92\x86\x8e\x95\x71\xa6\x8a\x48\x97\xaf\xd7\x55\xc0\x69\xd3\x85\xdf\x94\xc3\xe4\x78\x9a\x21\xf0\x64\xd7\xe7\x89\x4b\x85\x1c\xa7\xa4\x69\x95\x0f\xc9\xea\x2d\x15\x44\x4b\x46\x5e\xc0\xb8\xc7\x35\x78\x6a\x82\x45\xd6\x45\x33\x23\x6b\x80\x92\x27\x77\x57\x79\xe2\x11\x19\xa5\xc9\x07\xce\x2f\x4f\x22\x98\xc2\x7c\x2a\xe7\x78\x4a\xf6\xc3\x93\xa1\x6d\x48\x34\xb5\xd6\xbe\x78\xad\x7f\xf6\x84\xd9\xa5\x45\x8c\x0e\x1f\x39\x38\xce\xa1\x41\xdd\x0b\x70\x54\x49\xc0\xb0\xdc\xbc\xd1\x21\xf1\x15\xbd\x1c\x83\xa2\xcc\x3e\x0e\x4d\x14\xc7\x61\x5e\x97\x39\xec\xea\xf6\xf3\xba\x0e\x70\xbf\xb4\xaa\x89\xc0\xf1\xfb\x11\xb7\xef\xa0\xda\xb3\x72\x7e\x33\x5c\x69\x12\x35\xcd\xe5\x06\x12\xc9\xa1\x64\x78\x53\xe6\xd1\xdc\xc9\xf6\x11\x51\x8e\xd4\xfe\x0b\x72\x5f\x4f\x18\xe7\x28\x4a\x4a\x74\x59\xcb\x97\x06\x96\x4f\x78\x29\x63\x85\xed\x8d\x75\x6b\xb7\x29\x88\x5e\x75\x3d\x29\x34\x26\x6e\xd8\xf5\x18\x4b\x62\x92\xab\x34\x6f\xe8\xea\x27\x9f\x7d\x8e\xe3\xb8\x91\xdb\x67\x32\xc0\x48\x23\x1c\xfb\x47\xac\xcb\xf2\x36\xff\xe0\x75\x6c\xf6\x54\x35\x31\xb8\x7d\x65\x9a\x29\xc7\xe0\xbe\x22\xce\xeb\xa1\xb3\xaf\x54\x49\xb3\x89\x68\x6c\x2c\x38\x21\x64\x92\xe2\xf6\x14\xb2\xbd\xdb\x7b\x8a\x24\x07\x96\xa1\x3d\xe5\x25\x49\xf6\x2b\x03\x9b\xca\x0f\xbe\xc4\x57\x28\xf7\x00\xca\xb3\xc6\xe5\x10\x12\x65\x12\x93\xc6\xfd\xcb\xb3\x86\xd1\xbe\x8b\x7e\x3e\x45\xd8\x5d\xb1\x3f\x6d\x05\xdd\x8a\x72\xa9\xf5\x05\x03\x45\xf7\x18\x2a\x19\xc1\x94\xee\xf2\x6a\x35\x03\x51\xf6\xaf\x8f\xf8\x3e\xc3\xd5\x4b\x06\xb6\x0e\xb1\x5d\xa3\x5d\xfc\xe8\xbc\xc6\xe5\x4b\xe3\x73\x7b\xdd\x04\xbd\xb8\x68\x0a\x41\x46\x5c\x45\x43\x28\x65\x6d\x96\x1f\x73\x39\x81\x4d\x0b\xd5\xcf\xb7\xf8\x69\xaa\x19\xe5\x10\xcc\x30\x96\x41\x50\x4d\x4d\xe9\x66\x8b\xbb\x29\x3b\xe1\x6a\xa6\x12\xc4\x43\x64\x08\x59\x2e\x36\x99\x5c\xa0\x17\x97\x4d\xd3\x37\xde\x2a\x4f\xf4\x2a\x89\x14\x17\x68\xf8\x06\xf0\x19\x15\x95\x7e\x01\xec\x99\x3f\x8c\xbc\xc9\xfb\x9d\x68\x73\xa2\xe6\xc6\xe4\x67\x4e\x7c\xa1\x8a\xe7\x11\xed\x09\x42\x84\x4a\x11\x7a\xb7\xfa\xf2\xea\x01\x40\xce\x35\x5d\x44\x39\x87\x06\xc8\xf3\x4b\xaa\x1e\xae\x55\x08\xda\xaa\x71\xee\x17\x08\x52\x3b\x41\xb3\xe7\x7d\x40\xd5\xa3\x79\x93\x02\x32\x75\x58\x0a\x35\xf1\x94\x68\xdc\x45\xa8\x13\x45\xc7\xb3\x9c\x1c\x51\x3f\xf2\x2b\x89\xc2\xf2\x76\x32\xcc\xc0\x60\xf5\x23\x3f\x9f\x8f\x13\xf1\x65\x56\xcc\x26\xfe\x98\x2d\x81\xa8\xa2\x47\x3a\xd9\x93\xf5\x16\xd9\x81\x9f\x5f\x62\xec\x89\x9f\x5e\x2e\x39\xe9\x0b\x39\x4a\x11\x5f\xb1\x20\x41\x7f\x56\xf1\x50\x44\x39\x3b\x25\xa7\x7d\x55\xba\x96\xb3\xb8\x2a\xb8\x89\x14\x20\x65\x4d\xc9\x16\x79\x12\x21\xed\x20\xd9\x1c\x9e\x17\xa5\x80\xd9\xb9\x15\x16\x90\x8a\xe6\x56\x92\xde\xdc\x52\x3b\x34\xfb\x9f\x66\x8a\xb3\xbe\xda\x74\x53\x9e\x8c\xd9\xfd\xff\x28\x75\x83\x9b\x77\x05\x06\x73\x9e\xfa\x3d\xe5\xeb\xea\xaf\x00\xfd\x63\xbe\x76\x66\xd4\x8b\x7a\xc2\xb0\xf3\xf1\xf3\x80\x0a\xc4\x71\xaa\x1e\xc7\x5a\x87\x63\x15\x9e\xb7\x1b\x3c\xdf\xfb\xf8\xd6\x3b\x01\xb3\x7c\x57\x9a\x82\x39\xbe\x8b\xba\xc1\xb7\xe6\xc9\x5e\x97\xf3\x9e\xc6\x8e\xf6\x7a\xdc\xeb\x08\xc6\xc6\xf9\x2d\x35\xd5\x20\x3b\xc2\xa1\x6d\x49\x48\x0f\xcd\x7a\x76\xc5\x56\xc9\x99\x5e\x6e\x63\x98\xe6\x44\x4a\x73\x0f\x30\xf6\xc6\xef\x50\x5e\x7a\xc6\xde\x18\xde\x65\x8b\x43\x7a\xd7\x60\xd0\xfe\x30\x89\x8f\xf3\xfe\x6d\x11\x78\x51\x0c\x1a\x43\x79\xd1\x92\x79\xbb\x44\x92\x13\x4d\x65\x49\x49\xf2\xa0\xf5\x90\x5a\x00\xe2\xf4\x67\x0a\xab\x04\xc5\x78\x62\x87\xa9\x66\x80\x23\x1b\xcf\xec\xc2\xd5\x4c\x8e\xcc\xbf\x1d\xff\x76\xa6\xb4\x59\xa2\xf8\x5e\x1b\xa5\xb8\x24\xc7\x3a\xaf\xd0\xad\x28\x77\x1d\xb2\x19\xc5\xb8\xa1\x56\xde\x36\xba\x86\xa7\x4e\x0c\x55\x94\xf7\x11\xe5\xaf\x8a\x47\xfe\x11\x7d\x40\x3f\x69\xae\x28\x59\x4e\x3a\x21\x65\x54\x9e\x38\x0b\x9d\x38\x8a\x51\x92\x7e\x0e\xd5\x55\x68\x25\x1b\x49\x36\x87\x80\x53\x3f\xa2\xdc\x6c\x2c\x01\xc2\x7a\x1e\x83\x9f\x58\xf2\x7b\x72\x9b\x98\xb0\x11\xe5\x02\x0e\xbd\x28\x72\xbf\x89\x0a\xf2\x84\xf7\x1e\xad\x00\xf2\x8e\xdf\xfa\x72\x71\xb1\x71\xf5\xa6\x9b\xa8\xef\x64\x3f\x51\xf5\x2a\xb3\x43\x87\x0b\x2c\x50\x3a\x6b\xfc\x50\x42\xc8\xe7\x27\xce\xc6\xd7\x53\xcd\x02\x36\x1d\x5e\x54\x37\x1b\x55\x7e\xe0\x68\x99\x95\xac\x45\x13\xfe\x4f\x85\x19\xcf\xe5\x21\xb8\x6d\xba\x88\x30\xc5\x83\x34\x7f\x79\x08\x54\x0d\x31\xbd\x8c\x04\x98\xaa\x19\xe6\x2f\x35\x81\xaa\xf1\xc8\xe7\x28\x20\x03\xa9\x7a\x11\x5e\xdd\x1c\x05\xea\x86\xa3\x2a\x91\xd3\xd5\x0d\x46\xcd\xb4\x05\x6f\x69\x62\x64\xe7\x20\xcb\x29\x5b\x8b\x5f\x6f\x25\xaa\x5a\x90\x3a\x94\x2e\x50\xb3\x24\xfd\x4d\x46\x1d\xfb\x92\x99\x93\xf5\x28\xc6\x87\xc5\x2a\xe1\xd3\xd0\x33\x92\x8f\xce\x3a\x16\xdb\x50\x4d\x56\xc5\x6c\x92\x6f\x20\x50\xf7\x9c\x5a\xac\xf2\x5c\xee\x0a\x48\xe5\xc6\x3b\xdb\x0f\x97\x7e\x0d\x36\x1d\x5e\x69\x5d\x6b\xad\x2b\x33\x56\xdd\xfe\xbc\x4d\x9c\xa2\x6e\x88\xe4\x30\x3c\x6f\x8d\xeb\x82\xe9\xfa\x06\xa7\xa1\xa9\xac\x00\xcf\xe7\x2a\xa9\xe0\xb0\xe7\x75\x45\x47\x68\x19\x71\x7a\x2a\x03\x18\x32\xe1\xfc\x0f\x88\x8e\x1d\xc7\x8e\xc7\x32\x53\xb0\x48\x26\xc3\xe3\xa1\x69\x98\xaa\x8e\xc9\x4c\x63\x06\xa9\xce\xd8\xe8\xca\x81\xf6\x7c\x53\x0d\xb7\xd7\xba\x8d\xef\xfa\x52\x0b\xd5\x88\x0d\x50\x2b\xb2\x02\x8d\xda\x03\x6a\xf6\x2b\x61\xa3\x6c\x22\xbc\x06\xad\x03\xd9\x33\x94\xbe\xad\x10\x25\x36\x58\xfd\xda\x0d\xd2\xe7\x27\x64\x43\x50\x47\x50\x7d\x2a\x87\xcf\x86\x08\xb7\xe6\x40\x8f\xcb\x1a\x04\x4d\xe1\x61\xea\xd6\x84\x24\xa7\xd7\xb6\xeb\xf9\x13\xa6\x98\xcf\x04\x0c\x78\x75\x4b\xa2\xda\x24\xbf\xc8\x97\xa6\x62\x89\x5c\xb6\x20\xa6\xf1\x89\xf0\xf5\x6f\x67\x3d\xb6\x41\x63\x36\x0b\xce\xf3\xc8\x8e\x20\x4b\x29\x1b\xf2\x3f\x10\xee\x1c\x45\xf0\xd4\x0d\x0a\x71\xca\xae\xdf\x2f\x99\x30\xdd\xfc\x69\x80\x6d\x6f\x8b\x4d\x61\x4f\xa4\xf1\x05\xa9\x10\x6f\xcd\xb6\xf5\xeb\xac\xcf\xbd\x95\x51\x32\x5f\x6d\x6a\xfa\xea\x51\x89\x39\x1b\x62\x9c\x33\x2e\xe4\xc2\x10\x65\xe3\xd9\xc0\x0b\x63\x8c\x11\x42\x10\x88\x94\xaf\x24\x83\x7c\x99\x79\x68\x7e\xe8\x3a\xc8\x82\xf2\x4b\x16\xfe\x67\x1f\x1e\x96\xab\x9b\x88\xab\x4c\xe3\x5c\x69\xec\x66\x7e\x68\xd3\x30\x5b\xfd\xd1\xa7\x7e\xe7\xcb\xf0\xd8\x8c\x78\x1c\x6a\x78\xde\xa9\x6f\x5e\x7a\x33\x50\xd5\xa2\xd5\xe3\x56\x61\xd9\xf2\x1c\xbb\x10\xc7\x59\x46\x39\x56\xbb\x98\x35\xc2\xf1\x35\xd5\xcb\x59\xa3\x4b\x5b\x76\x93\xcc\xf1\x4c\xde\x44\x3c\x0f\x33\x3a\x5f\xd5\x22\xcf\xf4\x79\xce\x54\x8f\xce\xf5\xbf\xec\x95\x71\xba\xe8\xec\x49\x1d\xa1\x2c\x88\xef\x54\xc3\x7c\xcb\x4f\xa1\x7e\x78\x96\x1f\x47\xfd\x50\x7b\x4f\x54\x6f\xa1\x82\x6e\x25\x4b\x89\xef\x11\xa7\x29\x46\x39\x95\x1d\x4e\x75\xb8\x94\x9d\x52\x75\xe8\x13\x9d\x56\xd9\x78\x62\x3e\x1e\x7d\x80\x76\xec\xa7\xdf\x60\x4f\x9b\xd0\xbd\x46\xe8\xf9\x70\x71\x6c\x9e\x2f\xe6\x7c\xa0\xbf\x88\x73\xdd\x00\xce\xab\x7c\xaf\xea\x11\xc4\xf5\xe2\x3e\x51\x9c\xab\x89\x99\xd3\x09\xda\x72\xaa\xe8\x0a\x55\x79\xb1\x67\x64\x1a\x42\x5d\x6a\xea\x4d\xc5\x9d\x0e\x17\xcf\xda\x0c\xfa\x82\xc1\x7a\xb1\xac\x2a\x48\xd4\x39\xc0\x82\xa4\x50\x54\xa9\x20\x77\x2b\xee\xaa\xf6\x76\xb6\x53\xb7\x85\x98\x40\x71\xf5\x73\x8f\xd9\x65\xca\x30\xa3\x69\xc9\xd3\x22\x09\xa0\xb6\x36\x6f\xfc\xf9\x07\x49\xe7\xda\x12\xf7\xc7\x7f\xd2\xc3\x7e\xeb\xcd\xa6\xa1\xf4\xcd\xdb\x5f\xff\x05\x6b\x14\x0a\x49\x96\x2c\xc6\x57\x74\xac\x5b\x98\xfd\xd4\xd3\x6f\x7e\x86\x1f\xff\xe5\x00\x08\xc2\x5f\x39\x1f\xe3\xad\xa3\xbf\xbf\xf3\x3f\xe4\x02\x69\xde\xfb\xe5\x9d\xed\xe4\xd7\x94\x8d\xcd\x80\x67\x96\xf1\x61\xe2\xd7\x87\x88\x18\xd5\xf0\xe8\x7e\x93\xab\xc3\x3f\x09\x18\xf0\xd5\x5b\xc7\x59\x5e\x9e\xde\x0c\xff\xc3\xc3\xc1\x86\xb1\x8c\x0c\x6e\x41\x8c\xd4\x05\x37\x3d\x67\xdd\xf5\x1b\x5b\xc7\xd1\x73\x8f\x2d\x68\x21\x66\x88\x72\x71\xfb\x38\x89\xf3\xcf\x09\xb7\x3d\xeb\x51\x02\x2f\x71\x9b\xb3\x2e\x23\xd4\x2e\x21\x54\x53\xc2\x47\x82\x31\x3e\x38\x1c\xfe\xe8\x28\xe7\xa0\xe8\xb2\x41\x36\x73\x50\x78\x2e\x6e\x82\x68\x5f\x4c\xb8\x36\x17\x1a\xcb\x46\x6b\xa6\x6c\x92\xad\x1e\x7d\x7a\x5e\x57\xcc\x5d\x96\xa3\x66\x60\x63\xed\x77\xff\x1c\xf9\x59\x4c\x4a\xba\x30\x8b\x0c\xa2\x3e\x6d\xbb\x94\xeb\x9c\xe5\xcf\x05\xa2\x51\x85\x59\x7d\xfe\xb4\xd2\x59\x68\x4d\xab\xf5\xea\x1b\xa7\x9f\x75\x27\xdf\x35\x39\x1e\xc9\x9b\xc0\xc6\xfa\x3d\xfb\xe5\x51\x05\xa7\xbf\x69\x17\xa4\x0e\xd5\xcf\x9a\x54\x89\x3f\xdf\x4b\xb7\x52\xb7\x29\x0b\x17\xbb\xa8\xcf\xa7\x7c\xbb\xd2\xe2\xd1\xb7\x6b\xe9\x52\x47\x0f\x15\xe5\xcd\x59\x4e\xb7\x92\x5f\x13\xdf\x8b\xb3\xb7\xe8\x72\xa6\xb5\x89\xa9\x70\x85\x09\x70\x74\xe9\xa1\xeb\xc4\xfb\x1a\x1b\xa3\x57\x03\x02\x40\x88\x38\x46\x8f\x57\x0b\xa2\x08\xbd\x3e\x7c\xf4\xba\x2f\x40\x8f\xcc\xe4\xd7\x3b\x17\xa7\x63\x43\x95\xc4\x75\xa2\x74\xf8\x76\x75\xc2\x72\x7a\xb1\xfd\x68\xc5\xe2\xdc\xe2\xb5\x1d\xca\x29\x40\x5c\x20\xdb\x40\x00\xb0\xf8\xb0\x4b\x52\x1d\x89\xe0\x1f\x13\x15\x3a\x11\x04\xe8\xb8\x2c\xe2\x82\x95\x81\xb7\x2b\x34\x65\x10\x47\x66\xe9\x88\xf1\x37\xbe\x3f\x0d\x41\x2e\xfa\xe2\x6a\xd9\x31\xb8\x09\x02\x40\x94\x64\x0c\x94\x6a\x47\x24\xcf\x29\xb9\xb7\x8b\x68\x58\x0a\x95\x6f\x41\xec\xf8\x70\x76\x83\xce\xf8\x28\xfb\xd4\x91\xf1\x88\x14\x83\xd6\x90\xdd\x56\x9c\xc5\x78\x99\x5d\x20\x00\xf4\x17\x8f\x9d\x5a\xce\x0b\x9f\xcc\x23\x35\x9c\x5a\x44\x21\xa3\x94\x72\xed\x73\xb1\xa3\xac\x5f\x8b\x8e\xec\x2a\x7d\x6b\xcb\x0e\x0f\xaa\x62\xd1\xa0\x80\x3a\xaa\x76\xe6\x40\xbe\xe3\x54\x2a\xb0\x81\x64\x90\x2b\xae\x5d\xeb\xa2\x30\x93\x24\x3a\xd0\xcd\x17\x6a\x96\xde\x54\xe6\x40\x0f\x97\x95\x0d\x05\x95\x6d\xfa\xf7\xb6\x5f\x95\xf6\x4a\x4f\xd9\xd2\x7f\x7a\x6c\x51\xd0\x80\xe8\x18\xbb\x79\x7c\xf4\x49\xd3\xcc\x83\x0f\x6f\xda\xfd\x8b\x69\xa5\xb3\x4e\x2c\x5b\x30\x6d\xee\xeb\xb3\xe1\xaa\xe0\xdc\x1c\xca\xe1\xce\x48\x49\x1a\xb6\x0d\x56\xfc\x0e\x56\x7c\x76\xaa\xd6\x95\x45\xff\xbb\x99\xfe\x70\x68\x9a\xdd\x19\xd8\xd0\xab\xcf\x17\xcb\xa6\x9d\x7d\x73\xd9\xd2\x77\x60\xff\xd6\x8a\xd5\x07\xe8\x3f\x63\x9f\x8e\xed\x99\x11\x43\x0d\x4e\x18\x32\x74\xe4\xd0\xea\x46\x25\xfe\xbc\x6e\xe0\x4f\x17\x26\x5b\x98\x05\x15\x3c\x34\x2c\x41\x65\x61\xb6\x23\xb5\xd0\x85\x25\x27\x05\x4f\x9e\x6a\x50\x04\x7c\x75\x69\x45\x42\x42\xba\x1b\xef\xd1\x33\x26\x81\x1c\xdb\xe3\x11\x9f\xff\xbe\x30\x06\xa3\xbb\x2e\x85\x59\x36\x0a\x82\x47\xb0\x41\x59\xde\x0f\xe1\x07\x23\x73\xdb\x87\xe4\x11\xa2\x1f\x51\x32\xb9\x7b\x83\x02\xf3\xc2\x9a\x77\x45\xbc\x0c\x14\x72\xe5\x81\x31\xdd\x90\x4b\x31\x3a\x8e\x2e\x4a\xf6\x17\x6e\x90\x52\x92\x42\x26\x4d\x83\x14\x71\x84\x88\x34\x2e\x9b\x62\xb4\xae\x85\x6d\x78\x0d\x09\xf7\x7f\x30\x66\xac\xb7\x3b\x65\x32\x2a\xd9\x19\xd1\x98\x1d\x4b\x2c\x3a\x95\xdb\xda\xbd\x11\x0b\x8d\x98\x76\x31\x6c\xc1\xaf\x1e\xc8\x78\x29\x57\x93\xb5\x8b\x52\x81\x4e\xf1\x80\x7d\x93\x92\xff\x81\x61\xb9\x14\xa3\x55\x1a\xb1\xf0\x63\x24\x19\x2f\xdb\x4e\xea\x32\x92\x6d\x14\x28\xed\xc6\x78\xa9\xb9\x32\x9b\xcc\x9e\x8c\xee\xa8\xbf\x37\x32\x8f\x66\x4d\xb1\x8f\x88\x72\xa4\x45\x8b\xfc\x9a\x87\x05\x2d\x0b\x71\xa4\xa6\x24\x0c\xc9\x7e\xc1\xa8\xcc\x3f\x5c\x4f\x32\xf7\xe7\x5d\x9c\xe9\xf7\x0a\x7a\x0c\xa5\x12\xed\x8e\x64\x4f\xea\xd4\x6a\xf1\x1a\xe4\xe5\x9e\xf2\xa0\xe4\xb6\xfa\x46\x9a\x19\x68\xc3\xeb\xf1\x69\x55\xc1\x6b\xf3\x33\xed\xf1\xc3\x5d\xd8\xb0\x84\xa0\xc3\xdd\x92\xfc\x60\xde\x84\x84\xd8\x41\xc9\x78\x60\x44\x7f\xac\xa0\x0f\xe0\x62\x56\x23\xc9\x5f\x03\x13\xb0\x32\xbb\x3b\xef\xe1\x1d\x6a\x92\x2e\x3b\x45\x8c\xee\x81\xe5\xbe\x8d\xa9\xa7\x34\x4a\x97\xa8\xc0\xc4\x2b\xc7\xdb\x20\x8a\xd5\x15\xf5\x17\x01\x62\x45\x11\x8d\x8a\x15\xa1\xe8\x71\x89\x78\x1f\xf9\xbd\xb4\x4b\x32\x5c\x36\xa7\xbd\x7b\x85\x4e\x09\x50\x0e\x00\xf1\x0d\x27\x63\x0c\x57\x53\x96\xe9\xb5\x97\x7c\x57\xe6\xf7\x03\xae\xef\x72\xa1\xef\xc3\x2a\x8a\xff\x65\x99\xd4\xb3\xd5\x14\xbc\x77\xa6\x2a\x8e\x08\x60\x43\xf5\x64\x78\x1c\x9a\xfa\x5b\x81\xe4\x69\x55\x45\xbd\xc3\x0f\x1d\xac\x42\xf6\x81\xd1\xe6\x04\xc7\x64\x23\xcf\x6b\x26\x05\x92\xac\xe5\x3e\x52\xa2\x91\x62\x5d\xad\x3b\x0f\x6a\x58\x05\xea\xfd\x91\x03\xd1\x25\x3e\x34\x51\x2c\x53\xea\xc1\xc7\xfd\x90\xc1\xe9\x3b\x01\x88\x6f\x6c\xa8\x65\xc0\x04\xa2\xc1\x60\xe6\x1c\x2f\x60\x31\xa2\xcf\x14\xb0\xfc\x2a\xae\x1b\x32\x90\x2d\xda\x0a\x8a\x8e\x96\xcf\x21\x0e\x67\x12\x48\xf7\x87\x53\xae\x7f\xa0\x31\xa0\x12\x45\x63\xd1\x83\x2a\xd5\x28\x74\xb0\x8f\x53\x0c\x64\x77\xb6\xe3\x87\xa8\x54\xe0\x64\xef\x1c\x32\x3c\x6e\x45\x5e\xe2\x2c\x68\x62\x7f\x40\xbe\x84\x28\x2b\xb1\x6c\x4d\x66\xef\xd8\x36\x6e\xfc\xcd\xe3\xa7\x36\xe4\x27\x36\x8c\x5d\x55\x5f\x35\xbd\xae\x7f\xed\x4b\xbb\x16\x2d\x18\xb7\x6b\xee\x9e\x2f\x0e\x7d\x0a\xff\x2c\x36\x90\xa9\xfa\x3d\xfd\x4c\x31\x35\x63\x37\xbf\x5e\xbc\x29\xc2\xf9\x48\x69\xc1\xd8\x97\xaa\xe7\x4c\x2a\x8b\x4f\xdd\xf1\xd0\x36\xa2\x40\x6a\x16\x8b\xf1\x65\x76\x01\x9f\x62\x6e\xfa\x43\xf8\x9d\xc4\x00\xd6\x85\x78\x57\x69\xf6\x02\x5c\xc2\x63\x6e\xf7\x99\xe4\xb5\x9b\x3f\xbc\xa3\xd4\xac\xdc\x2e\x30\x2b\xb2\x6d\x71\x09\xc7\x79\xf7\xc3\xb2\xc3\x20\xfa\x25\xea\x96\x6c\x97\x68\x17\xec\x57\x16\xff\x1f\xef\x9f\x7b\xde\x6a\xf5\x87\x7e\xbc\xd2\x5a\xed\x02\xf3\x82\x8d\xca\xe2\x7e\xeb\x41\xf0\x6e\x35\x88\x7c\xba\x8a\x41\xda\x25\xd2\x79\x33\x14\x03\x8f\x01\x40\x9a\xc9\x5f\x83\x3e\x20\x12\x00\xc5\x99\x4d\xe4\x05\xfd\x98\x68\xed\x87\x28\xfc\x9e\x65\x3b\xf2\xbd\xdd\x82\xcb\x33\xc0\xc0\x01\xae\x0f\x54\x03\x5c\xc5\xfa\x10\xf5\x72\x40\xbc\x7e\x27\x2b\xba\x51\xec\x2f\xf7\x7c\xf1\x5b\xec\x1a\x78\x12\x00\x2a\x02\xc9\x83\xaa\x23\x6b\x9d\x42\xc5\x7d\x3e\xa9\xb2\x06\x9d\xfe\x24\xe4\x16\xde\xdd\x7f\xcb\xfa\x3f\xc0\xf5\x1f\x02\x22\x50\xe6\x74\x6d\x6b\x43\x45\x6a\xe9\x3a\x52\x62\xd0\xb0\x35\xa4\x20\xfc\x72\xc0\xaf\x0f\x2d\x0e\xd8\xb5\x60\xf2\xc7\x00\xb7\x00\xee\x3d\x27\xea\x1c\x07\xef\xfa\x93\xdf\xaa\xd2\xfb\xbb\xca\xf9\xdc\xc3\xbf\xf0\xdc\x24\x16\x03\xc0\x40\x26\xaa\x03\x9f\x0a\xfa\x81\x04\xdd\x1a\x96\x32\x4e\xc4\x55\x04\xef\x9e\xe8\x10\x0a\x59\x6e\x11\xcd\x7a\x5f\x15\xc1\x7b\x8f\x13\xbb\x84\x2a\x82\xc4\x19\xf9\x5e\xe7\xc3\x30\xd8\x6f\x1d\x4d\x09\x37\x5a\x28\x36\x89\x57\x85\x06\x0c\x72\xad\xea\x7e\x26\xe6\x23\x4d\xb7\xf2\xa5\xc6\x4a\xd1\xc0\x74\x4e\x65\xd1\x18\x23\x88\xdf\xb2\x70\x09\x4f\xe9\x86\xaa\x72\x2a\x56\x91\x06\xba\x1f\x54\x17\x94\x51\xe6\x84\x2d\xe9\x7e\xf8\xe3\x57\x99\x06\xc2\xeb\x8a\x05\x67\x8c\x3d\x61\xdb\xe9\x0a\x7f\xda\x3b\x8d\xd6\x8c\xeb\xab\x5c\x91\x46\xd9\xe3\xf7\x16\x16\xdf\x2b\xd4\x65\xd0\x0f\xa4\x30\xfb\xb9\x0e\x77\x46\xec\x7e\x0d\xa8\x7f\xf0\x67\xfd\x6b\xe1\xfe\x51\xe7\x9a\x82\xc5\xfe\x14\x87\x7d\x44\xd7\xb1\xcb\xcf\x02\x1a\xe0\x3f\xf0\x7b\x22\x30\x84\x5e\x7e\xd5\xc0\xee\xeb\x54\xa4\xf6\xbe\xee\xc2\x6d\x66\x17\xb4\x9b\x6d\xb8\x6c\x5f\x7f\xf7\x19\xec\x99\x86\xe3\xf4\xb9\x13\x9b\xbd\x75\x9b\x55\x76\x75\xef\x76\xac\xfa\x6e\x31\x76\xc8\x5b\xc6\x9e\x3b\x0e\x70\xfd\x68\xee\xed\xbe\x9e\xe4\x7b\xbb\xa4\x2b\xd5\x9d\x5d\xd2\x19\xda\xd7\x4c\x36\x23\x7b\xbb\xaf\x4f\x8d\xbd\x5d\x4f\x4a\xd1\xce\x2e\xeb\xff\x00\xd7\xbf\x81\xbd\x5d\x29\xb5\x62\x6f\xd7\x17\xdf\xb7\xb3\x8b\x41\xf8\xe5\xc0\xb7\xb7\xab\x73\x20\xec\xed\x7a\x0c\x88\x76\x76\x51\xe7\x68\x6f\xd7\x97\xdf\xaa\xd2\xbb\xfa\xde\xae\x2f\xbc\x68\x67\x97\xce\x37\x1c\xcc\x63\x30\x50\xcb\x40\x18\xe7\xef\x65\xe8\xc6\x40\x04\x67\x9e\x3f\x75\xf1\xac\x1c\x9c\xce\x6d\xc1\xbd\x77\x14\x73\xc4\x87\x8f\xf5\x97\x33\xa4\x1d\xfc\x03\x14\xab\x84\xf7\x75\x11\x4a\x75\xc1\xbd\xfd\x12\x84\x18\x98\xdf\xd9\x8e\xb9\xa8\x54\x10\x02\x6c\x12\x3f\x29\x3e\xb8\x50\x36\x9f\xe6\x87\xb5\x1e\xdf\x15\x3c\x3f\xe3\x61\xdb\x82\xb8\xba\xfa\x33\x22\x5d\x71\x2d\xb9\x0a\xbb\xea\x8d\x2d\x4a\xa9\x89\xdc\xd8\x27\x6c\x0d\xf1\x88\xfc\x21\x8c\xed\xcb\x82\xfa\xb2\xab\xf6\xa5\x98\x3f\xd2\xde\x2e\x8a\xf5\x85\xac\x3b\x32\x4c\x61\xed\xe0\xa8\xbf\x8d\x9c\x6c\xf1\x46\xa4\xe3\x35\x86\xb4\xdf\x01\x2a\x3a\x43\x5f\x5a\xe1\x14\xce\x62\x98\xce\xc9\x9c\x68\x4c\x6a\x87\x2a\x8a\x28\x55\xbd\xe1\x8f\x06\xce\x74\x41\x38\x70\xb2\x2b\x5c\xf0\x9a\x43\x8a\x62\xac\x42\x77\xe8\x33\xe1\x33\x4f\x38\x2e\xfe\xd0\x35\x2e\xac\xaa\x28\x54\xce\xbb\xfe\x88\xf0\x3d\xb4\xb0\x5c\xcc\xa4\x2e\x83\x10\xe0\x04\x19\xaa\x38\x8c\x68\x11\x29\xa4\x58\x7f\x7a\x44\x0e\x70\xb3\xde\xab\x08\x0e\xa6\x74\xb6\xe3\x09\xd4\x65\x10\xc6\xdd\xe0\xa9\x22\xc2\xf5\x18\x44\x9a\x64\x8a\x2a\xac\x29\x12\xe8\x5f\x88\x74\x89\xd4\x8e\xb8\xfb\x95\x6c\x70\xbf\x91\x19\x16\x18\xb3\xff\xe0\x7f\xd7\xb2\x2b\x70\x51\x2c\xed\x93\x22\x5d\x91\x29\x8e\xa5\x55\x18\x15\xe2\x90\x5a\xa4\x37\x5e\xe7\xfa\xd0\xb2\x29\x44\xbd\xbc\x2e\xd6\x11\xbd\xc5\xdd\xa8\x18\x14\xd2\x8e\xd0\x5e\x4a\x7c\xeb\xdf\x9e\x90\x48\xa5\xa2\x1b\xec\x3a\xd2\x09\xc6\x84\xbc\xef\x03\x5c\xdf\x7e\x6d\x09\x71\xef\xea\xb6\x84\x5d\x57\x6c\xde\x90\x90\x00\x40\xb2\x93\x0e\xff\x76\x84\x96\xec\x9c\x1d\xa1\x23\xb9\x60\x44\xc8\x86\x97\xb5\x23\x50\xdf\x7e\xed\x08\x71\xef\x2a\x76\x04\xa9\x2b\xb8\x60\x44\xc8\x00\xa0\x3d\x9a\xec\xd7\x55\x1b\x42\x04\xc5\xaf\x0d\xb1\x58\x02\x4c\xd7\x80\x90\xcf\x0b\x1f\xb6\xae\xd8\x0f\x7e\xc1\x89\xed\x87\xbd\xda\xe8\xe4\xc6\x83\x72\xec\xd8\xb8\x52\x36\x6e\x33\xd1\x4f\xac\xb3\xdc\x0f\x47\x3d\xce\x79\x92\xf8\x51\x41\x33\x5c\x6e\xa7\xaa\x9f\x8d\x0f\x4b\x92\x1f\x2c\x4a\x9f\x1a\x75\x34\x33\x24\x0f\x08\x9a\x31\xd7\x93\xd5\x7d\x66\xc4\xdc\xb8\xfc\xc5\x1e\x6a\xf8\xc7\xa8\xe2\xda\xae\xf6\x4e\x60\x90\x2c\x99\xff\x8b\x98\x33\xa3\x71\x7a\x4a\x5f\x17\x55\x94\x1f\xa8\xbf\x07\x18\x66\x51\xe2\xcb\x72\x9b\xc8\xeb\x2e\x97\x82\xdf\x8a\x2a\xca\xff\x51\xde\xfb\x1b\x64\x52\xe2\x97\x72\x5f\x3c\x5a\x75\x11\x5e\x54\xb9\xdf\x37\x4c\xa2\xef\xfe\xe5\xc9\xce\x76\xca\x4e\x9e\x07\x7d\x40\x34\x5a\xab\xf2\x19\xa7\x13\x51\x2a\xde\xbd\xf3\xb5\x63\x48\x65\x3a\xdf\x7b\x5a\x37\x7a\x94\x59\xb3\xef\x70\x98\x42\x40\x0c\xbb\x66\x15\xbb\xbb\x0e\xaa\x77\xc4\x8b\xf3\x49\x6d\x58\x4a\x17\x85\xe9\xfa\xc0\x08\x86\x2b\x53\x12\xe2\xca\x0a\x1c\x68\xbe\x69\xdd\x2e\xe8\xb1\xa6\xb2\x4a\x2b\x0d\xb3\xc7\xbb\x31\x84\xfb\xc3\xfa\x4e\x67\xbb\x29\x13\x71\x18\xc1\xc7\xda\x6a\xde\x44\x18\x60\x53\xba\x5a\x75\xf0\x6a\xb9\x3a\xf8\x01\x8c\xd6\x33\xc3\x6f\xa8\x1e\xbf\xc2\xcd\x85\x41\x7e\xd9\x95\x1b\x6f\x98\x5d\x6e\xed\x7a\xdf\xf2\x07\x96\xe5\x37\x50\x9f\x5f\xab\x01\xb4\xef\x28\x57\xb1\x0e\x5c\x4d\xd7\x09\x7f\x80\x31\xd0\xd0\xd9\x4e\x4c\xa2\x52\x81\x19\x59\x72\xcc\x19\xa1\x27\xb4\x32\x50\x42\x43\x5c\xc1\xc0\xa6\x7c\x21\x6d\x88\x59\x76\xa2\x68\x2c\xbe\x62\xce\xaf\x7e\x7d\x9c\xbe\x4c\x5f\x3d\xf9\x29\xfc\x4e\xbc\x0b\x97\x8e\xde\x8a\x45\xd2\x87\xe9\xdd\x19\x2b\x17\xc2\x7f\xc0\x3f\x79\xbf\xf0\xfe\xfe\x03\x22\x4a\xfe\xce\xe1\xeb\xd7\xa1\xd1\xaf\x82\x37\x95\x9e\xaf\x49\x76\x5c\xf5\xae\x7f\xa7\xfa\xb6\x21\x96\x3b\xd1\x98\xe4\xfc\x2a\x56\xc1\x91\xa2\xb6\xc5\x1a\x61\x42\xf2\x06\x2f\xe6\x24\xc9\x28\x2b\x0e\x6d\x54\x53\xd5\xb7\x54\x63\x34\x89\xde\xd6\xbb\xc1\x15\xbf\x22\x55\x50\x3d\xa4\xdc\x42\x8d\x30\x25\x7a\x33\xef\x16\x4f\x56\x6d\x44\x6b\x54\xb6\x4c\x63\x24\xf9\xf6\x4b\x06\xd3\x4b\xd4\x65\x60\x06\xf1\x6c\x1c\xb4\x0a\x26\x23\x67\x05\x15\x78\xb9\x7e\x9d\x2b\x55\xc1\x92\xe3\xf5\x7d\x29\x59\xcc\xd3\x39\xcc\x99\x5d\xc1\x2c\x3f\x43\xa8\x80\xc6\xfd\xfb\x2b\x19\x40\x2d\x7f\x9c\x40\xe7\x7b\x92\x46\xe7\xbf\x7e\xaa\x7b\x17\x1f\xf5\x20\x39\xdc\xc3\x7c\x5f\xbc\x83\x42\x57\x7e\xe7\x8b\x74\x00\x38\xd3\x3e\xf5\x57\xee\x7c\x39\x40\x6f\x77\xf4\xc8\x7b\x92\xae\xb2\xbb\x3a\x3d\xb2\x4b\xeb\x75\x45\xbf\xb7\xf5\xfa\x15\x76\x0d\xd5\x7e\xd9\x59\xfb\xa3\x4e\xa7\xdc\x54\x85\xf9\xa2\x6e\xb9\x3b\xe7\x48\xee\xcc\x38\xc4\xe8\x99\x11\xf2\x18\xfc\x1f\x18\xe1\x19\x11\x26\x9d\xf3\x22\x9c\x21\xc6\x85\xa1\x9c\xa0\xeb\x7d\x3e\x69\xa1\x1e\x17\x08\xb1\xb8\xd2\x22\xa1\x10\x63\x16\xea\x4e\x77\xba\x78\x9b\xd9\xc9\x95\x9b\x95\x9d\x1a\xd7\xd7\x7d\x40\xff\xf8\xfc\x2b\xc3\xf2\xde\xce\x09\xce\x1b\x5e\xde\x54\x12\x79\x2c\x66\xdd\xf5\x2d\xb3\x56\x45\x0c\x6b\x9e\xbd\x7e\x3b\xf6\x81\x78\xe7\x9a\xf5\x2e\x7c\xf2\x5d\x7a\x29\xfd\xfa\x4d\x18\x08\x53\xe9\x6f\x0a\xb3\x27\x3e\xb4\x07\x8e\x78\xfd\xad\x96\x96\xd7\xaf\xd3\x6b\x3f\x99\x33\x79\x46\xd9\x2f\x89\x30\xe5\x5d\xb5\x0f\x6b\x66\x17\xb0\x2a\x4f\x95\xfe\xd0\x9e\x90\xcc\x69\x63\x70\xcf\xa9\xdc\x75\x8b\xb9\xcd\xed\x3e\xbb\xc2\xa9\xd3\x1f\xee\x50\xb5\xdd\xb1\x3b\x6c\x8b\xee\xca\xc5\x9c\xe7\xdd\x0f\xeb\x0e\x83\x52\x40\x5a\x7d\x37\xed\xde\x30\x08\x77\xed\x0f\x68\x2c\x84\x53\xab\xbf\xb1\x28\x52\xee\xbe\xdd\x19\x09\xc9\x5d\xfd\x03\x1b\x0b\xab\x51\x29\x86\xab\xec\xd8\xdd\x1b\x08\xf1\x5d\x3f\x2b\xc7\x65\xe0\x04\xd9\x60\x5c\x17\xe4\x30\x14\x49\xe1\x4f\xa4\xde\x7e\x77\x79\x43\x02\x92\x85\xfa\x6f\x05\x62\x19\xc7\xdf\xaf\x8c\x8a\xa8\x09\x7f\x6b\xe8\xa2\xff\xfd\xa2\x1b\x52\x2a\x5c\x18\xd8\xb7\x06\x2a\x0f\x9d\x19\x53\x54\xde\x1a\x3c\xb6\xb8\x90\xf4\xd0\x81\xae\x58\x10\x62\xc1\x4c\x36\x93\xcd\x23\x9c\xbc\xc2\x2c\xa1\xd2\x07\x88\xc9\xb1\x70\xd6\x67\xef\xc2\xd1\x17\x21\x80\xfd\xff\xf7\xb7\x70\xa1\xcd\xbb\x37\xea\xf6\x8f\x1f\x1d\xde\xf1\xcd\x93\x73\x96\x45\x29\x9e\x24\xf6\x7e\x06\x0b\x6f\xc2\x15\x5f\xd0\xbf\xa3\xef\x7d\x4b\x3f\xbe\x7e\x6f\x73\x33\x7c\xfe\x5f\x1f\x5f\xf8\x39\xfd\x87\x93\xaf\x77\x82\x65\xcd\x08\xdf\x6e\x0e\x5f\x2c\xf2\x0c\xf2\x87\x47\xb9\x54\x76\xeb\xa3\xf2\x7e\x23\xde\x2b\xfc\x42\x52\x58\x0b\x82\xcf\xc4\x58\x8e\xc3\xa1\x6a\xb7\x1a\xfe\x50\x73\xaa\x55\x7c\xf4\xfe\x85\x1f\xdc\xbf\xe7\xfd\xc1\xba\x4c\x2b\xf9\x1a\xef\x1b\xf6\x0e\x00\xa6\x72\x74\x06\x4f\x63\x73\xe5\xc8\xc9\x83\x46\x91\x4b\xaf\x39\x30\x3f\xd8\xaf\x70\x7b\x82\xca\xf3\x91\x11\xf4\xc2\x79\x8b\xe1\x3d\xf1\x7e\x78\xe7\xd4\xa8\x98\xf7\x97\xfd\x60\x6f\x67\xfd\xc8\xba\xcc\x3a\xb1\xd2\x77\x2e\x7b\x87\xc3\xad\xc9\xbb\x61\xe4\x12\xde\x2f\xfb\x81\xfe\x57\xf6\x41\xa7\x1b\xa4\x13\x2b\x85\xf3\xdb\x3c\x00\xa8\xdf\x70\xef\x3a\xa3\x0c\xbe\xeb\xf8\x55\x23\x7e\x1f\x7b\xc6\xeb\x8b\xa6\xff\xfc\x63\x40\xd1\x88\xe5\xca\x40\x95\xb4\x34\xe4\x32\xae\x7f\x90\xa2\x57\x17\x6c\xa6\x9f\x81\xfa\xbb\xf8\xf1\x58\x22\xda\xdd\xa5\xfe\xc7\xea\x5b\x79\x4c\x1c\x17\x0b\x18\x8d\x62\x01\x87\x76\x27\xd6\x1b\x2d\xf2\x2e\x84\x48\xf7\x21\x8e\x92\xfd\x88\xb2\xa4\x5c\x83\x41\x7d\x04\x15\x76\xe0\x99\x88\x29\x3f\x97\x61\xf5\x74\x03\x6b\x17\xe3\x4e\xe1\x13\x89\x45\x1f\xb9\x0f\x18\x0d\xa1\xbd\xc2\x2c\xe2\xf2\x2b\x42\xac\x4d\x34\x70\xb2\x19\xb1\x8c\x46\x51\x70\x4c\xfa\x0b\x3e\xd8\x29\x10\xa8\x17\x72\x40\xae\xe7\x68\x93\xe0\x49\xee\x02\x1e\x83\xb1\x10\xff\x62\x49\xd2\x0d\x7f\x28\xe7\xa8\x11\x7c\xb3\xa3\x41\x3f\xb6\x3a\xab\xb6\x7f\x38\xc7\x86\x96\x83\xec\x4c\x9e\x05\x0d\x07\x4d\x2a\xc0\x27\xbf\xaf\xcf\x01\xba\x7d\xfa\xf1\xc9\x7d\x03\x49\xaa\xe5\x26\x7c\xd5\x27\x23\xeb\x77\x15\xcd\xde\xaf\xa8\x79\xfe\x70\xb2\x49\x3d\x5a\x0e\xf3\x12\xc9\x3d\x57\xf6\xf2\x92\xf0\x6d\x2f\x41\x6d\x47\xa8\xb6\xad\xea\xbf\x73\x09\x21\x97\x7b\x0e\xd5\xf0\x88\x7d\x6f\xb9\xd1\xe8\x3d\x6d\xa0\xbf\x77\x65\x7e\xcd\xab\x3f\xe1\xf6\x16\x26\xa8\xe6\x9b\xd9\x9f\x44\x6b\xda\xd7\xaf\x5d\xde\x6f\x68\x98\xb8\x63\xa8\xf7\x66\x07\x43\xd8\x79\x28\xee\x12\x96\xed\x14\x3a\x85\x87\x7c\xe3\xc3\xde\x7d\x46\x03\x33\xca\x6b\xa2\x7a\x13\xcb\x49\xa8\x72\x29\xf7\x73\x41\x3a\xf5\xbb\xb7\x47\x7c\xf3\xce\xd7\x4f\xa4\x46\x3f\x9a\xf7\xa9\x58\x30\x2b\x8e\xfa\x15\x6a\x8a\x4f\x16\xf6\x2c\x22\xe8\x1a\xa3\x27\x5f\x7e\x04\xfd\x9d\xa8\xea\x04\x69\x8d\x9d\x29\xca\xc5\x73\xd5\x87\x2d\xb9\x0b\xd8\x8c\x9e\x5f\x2f\xb0\x0c\x19\x3b\xb2\xc6\xfb\xe6\x3a\x01\x2a\xe8\x6c\x51\x4e\x83\xc9\xdd\xc9\x41\x91\x0b\x5d\x41\xec\x58\xaa\xc7\xc0\x19\xdd\x63\xb2\xa9\xe8\xed\xbd\x83\xb1\x98\xbe\x66\x47\x52\xc1\xe8\x29\x70\x58\xd7\x53\xa0\x74\x9c\x0f\x8f\x5c\x37\xa2\xb8\x47\x44\x44\xaf\x55\xe6\x62\x2a\x47\x7e\xb7\x26\x97\xf7\xa1\x07\x22\x6f\xb7\x73\xa4\xc8\x25\x76\x76\x23\x65\x8a\x4c\xe4\x1f\x14\x07\x2f\x52\x31\xc6\x53\x1f\x84\xd4\xf7\x9b\x53\x45\x26\xbb\xda\x73\xf5\x83\x18\x74\xdf\x83\x98\x9c\x87\x87\xc0\xf4\x07\xc2\xc3\x7d\xe7\x60\x91\x31\xa1\xee\x58\xf7\x60\x66\x03\xff\x08\xf7\xff\x68\x4e\x74\x35\x67\x8b\x8c\x89\x0d\xdd\x4d\xe1\xa2\x3b\x23\xf8\xab\xc6\xff\x67\xf3\xa1\xab\x39\x5e\x64\x2c\x7c\xd2\xed\x8c\x2f\x7e\x26\x83\x28\xff\x0b\xcb\x05\x9f\xff\x25\x0f\x3c\xcc\x9c\xf3\x1e\x00\x17\x0f\x32\x27\x8c\x8c\x96\x25\x0f\x28\x45\x8c\x94\x24\xd3\x52\xdd\x47\x4e\x7e\xce\xf8\x78\xaa\xfa\xbf\xe3\xa9\xbb\x39\x64\x64\x44\x8d\x7a\x50\x29\x65\xf4\x98\x92\x5d\x99\x12\x9d\x9b\x3a\xdb\xa9\x2d\x42\x7e\x19\x51\x4d\x76\xc5\xbe\xc1\x66\xa6\x80\x0a\xf3\xdd\x97\x01\x26\x43\x64\x08\xbc\xca\x26\xa5\xc0\x56\x48\x8c\x7a\x8d\x64\x2c\x74\x00\x9b\x96\xa2\xe3\x82\xd4\xdc\x97\xe0\x8b\x60\xef\x4c\xfd\x66\xa4\xd1\x43\xa8\x96\xa3\x46\x03\xa2\x66\xca\x1a\x05\x48\x34\xdf\xca\x3b\xdb\x4d\xb3\x45\xf9\x5a\x86\x1a\xce\x62\xa3\xc4\x6b\x28\xaf\x8d\x31\x66\x65\x69\x6e\xfc\x61\x67\xf3\xbc\x0c\xeb\x42\xe6\x1b\x3d\xf4\xba\xb9\x70\x8c\xd2\x2e\x4d\x8d\xa3\x22\x40\x97\xb8\xf7\x48\xf3\xd4\x18\xe5\xfe\x98\x38\x7f\x8e\x31\xe6\x43\xa5\xe9\x74\x94\xc0\xbb\xc8\xbb\xd5\x38\x72\xed\x9c\x3b\x46\x49\x97\xa5\xe0\x51\x80\xe7\xb0\x8b\xf2\xf1\x8c\xea\x5e\x46\x1e\x3d\x31\x8c\xe6\xe8\xd1\x12\xca\x40\xca\x1e\x9d\xf5\x20\xca\xe1\x53\xd8\xcd\x2c\x3e\x5d\x17\x4e\x2d\xaf\x8f\x21\xf1\xd4\xd3\xfc\x28\xc4\xc3\x41\x4f\x2e\xfe\x3b\x04\x0c\x66\x2b\x06\xca\xf7\xb8\x48\x68\x34\xff\x41\x4f\xe9\xfe\x95\x6c\x20\x1d\x02\x7d\x41\xbc\x35\xc1\xd5\x06\xd3\x23\xc8\x70\xe7\x74\x11\xb7\x62\x2d\x19\x44\x2e\x49\xa1\x60\x10\xba\x32\xa5\x02\x21\xe3\xbc\xa0\x6b\xe8\xb5\xce\x6f\xc6\x64\x50\x4b\xb9\xd0\xbd\x41\x10\x0e\x68\x84\x6c\x2c\x0a\xbb\x28\x8f\xe6\x8e\x62\x4c\x22\xf5\x34\x0d\xdd\x1d\x1d\xee\xa0\xf5\x80\xc7\x88\xdf\x65\x8c\x49\xa4\x4c\xeb\xd0\xbd\x11\x12\xf9\x66\xdc\xe7\x18\x69\xef\x3e\x06\x57\x8e\x4a\x2a\x88\xee\x8e\x90\x70\xfa\x61\x65\x7a\x05\xc5\x64\x0e\x06\xf9\xec\x1d\x58\x17\xc6\xc8\xc8\xae\x64\x4c\x3c\xbf\xe9\x23\x8c\xca\xaa\x97\x4e\x82\x93\xf7\x29\x41\xde\x92\x07\x21\xaf\x7c\xa7\x32\x26\xb0\xff\x94\x13\xdd\x92\x58\xe9\xbf\x81\x83\xc7\x3a\xdb\x4d\xff\xe2\x62\x45\x93\xf4\xb3\x50\x38\x14\xdb\xab\x6e\x5e\x8a\x97\x24\xdb\xa8\x6e\x9a\x8a\x6b\x72\xab\x00\x07\x07\x38\x5c\x21\x20\x9a\x7b\x91\xd2\xc9\x5a\xa1\x44\xa6\x9b\xc7\x42\x06\xcd\x4f\x5a\x0b\x39\x38\x14\x27\x11\xf0\x5f\x21\x2e\xd3\x6d\x2c\xcb\x85\x12\xa3\xa1\xbc\x17\xba\x2c\xaa\xa6\xc1\x50\xe2\x3d\xc0\xe1\x65\x63\x39\x3d\x46\xb3\x62\x68\xb3\xaa\x9f\x27\xc3\x1f\xbd\x6a\x69\x33\x14\x33\x00\x18\xe1\x59\x2d\x93\x86\x3e\xcf\x1a\xb9\x35\x74\x59\x56\x4d\xb5\xa1\x04\x4c\x80\x77\xfd\xf3\xac\x96\x7d\x43\x89\xd8\x40\x3e\x0e\x7f\x24\xab\xa6\xe7\x50\x80\x26\xc0\x3c\x06\xb3\x10\x67\x9b\xdf\x8d\x6c\x1d\x4a\xf8\x5d\xce\xdf\x21\x17\xc6\x70\x3a\x0f\xe5\x5c\xf7\xc9\xe3\x00\xa9\x60\x64\x77\xb2\x7b\x18\x15\x48\x2f\xdf\x87\xae\x44\x7a\xe9\x3f\x94\xf3\x0a\x07\x15\x74\xb6\xe0\xf7\x39\xa6\x2b\x7e\x9f\x7e\x5f\xa0\xfc\xf9\x11\xee\x93\x3d\xc4\x44\x74\xd9\x8f\x9b\x8e\xd1\x7b\x79\x92\xca\x36\xf6\xbe\x64\xeb\xb2\x9f\xb7\x42\xba\x90\xae\xfb\x7d\xcb\xc4\x53\xbe\x32\x71\x6f\x6b\xa2\xf1\x9b\x7c\x3f\x52\x6a\xbe\x2e\x75\x51\xd6\x25\xdd\x76\x15\xd7\x1d\x50\xfe\xd0\x42\xc8\xc6\xf5\xa1\xfb\x92\xb9\xfb\xbe\xe4\x32\xa9\xa7\xdd\x87\x6b\xb9\x9f\x91\xf6\xe5\xa3\xfb\x3f\x1d\x6f\xa3\xfe\xe7\x72\xc9\xf7\x75\xd3\x1d\x5d\x77\xb4\x7d\x07\xa0\xff\xe3\xf1\x36\xea\xaf\x2e\x97\x7a\x47\x77\xdd\xd7\xfd\x0c\xb6\xe8\x8c\xc4\xca\x7d\x19\xc9\x3d\x11\xcc\xba\x2f\xb9\x1f\x84\x7f\xbb\x9c\x82\x05\x0f\xc6\xdd\x5d\x4a\x88\xee\x6b\x90\x9c\x93\x47\x1e\x3c\x27\x5d\xf6\x87\x97\x91\x92\xf4\x80\xdc\xe3\xf5\x58\x51\x1c\xb6\x50\xac\x7f\xc0\xcf\x38\x7f\xe3\xfc\x6e\x78\xcb\xab\x98\xb6\x5d\xf0\x9f\x4f\xd0\x3f\x8f\xf9\x75\x0c\x95\x5b\x26\x38\xd8\xcd\xc9\x13\x0b\xd2\x40\x41\xb7\xbc\xeb\x95\x37\xb6\x5d\xf2\xb7\xa7\xf2\x25\x32\x75\xdd\xfd\xbe\xc3\xac\x71\xee\xe8\x71\x58\xf0\x0b\x2f\xbe\x0f\x8f\x7c\xa5\x7c\xdd\xf1\xd1\xa7\xe2\xef\x73\xe8\x38\x97\xfd\x7b\xbf\x51\xda\xff\xef\x74\xb6\xf7\x38\x29\xf8\x92\x8f\xbb\x2f\x2f\x7e\xa5\xb4\xdd\xf3\xeb\x97\xc9\x7b\x1f\x6e\xfe\x4a\x89\xf9\xf1\xdd\x74\x7f\xe3\xcb\x6d\x48\xfa\xe3\x6b\x2c\x16\x80\xfc\xe6\x3e\x47\x97\x0f\x0d\xe8\xa8\x52\x39\x93\xbe\xc3\xc9\xaa\x33\xbe\xf7\x21\x6d\x77\xe2\x07\xbe\xbb\xef\xc1\xe5\xc3\x09\x94\x02\xa3\xf3\x5f\x8f\x64\x21\xbe\xe0\xe1\x07\x15\x61\xd0\x8d\x43\xae\x9f\x98\x03\x22\xb1\x0b\x67\xde\x2e\x2b\x67\x20\xe5\x22\x03\x14\x82\xf2\x07\x16\x95\xa0\x9c\x07\xf7\x1f\xa7\x40\x8d\xd0\xa1\xa3\xeb\x61\x0b\x1d\xeb\xd4\xce\xd1\x9d\xed\x44\x0b\xd9\x8e\x7c\x54\xb2\xbb\xe1\x9f\xe2\xf6\xb8\xd0\x47\x5c\x98\x6d\x80\x61\xaf\x93\xbd\xd8\xc2\x31\xd3\x0e\xd9\x96\xe7\xd2\xff\xaa\xd9\x64\xb4\x48\xd1\xa9\xf0\xbe\xc3\xf3\xea\xe8\x7f\x88\x71\x57\x23\xdc\xae\xee\x54\x0c\xb3\x19\xf6\xb1\xda\x19\x83\x39\x63\x0c\x47\x33\xb4\xb4\x88\x7c\x47\xa3\x39\xdf\x9f\xe2\x07\xe3\x31\xd7\xc5\x98\x11\x99\x73\xcf\xef\xba\x18\x41\x22\xf3\xe1\x59\xe7\xf3\x3d\x67\x64\x23\x66\x75\xb7\x4e\xa0\x52\xb2\xee\xfa\xc0\x76\x47\x0e\xc5\xd8\x74\xab\x96\x9e\xe2\xa6\xe5\xfe\xfc\xf6\x60\x6e\x57\x42\x66\x64\xbe\x7a\x25\xd2\x78\x04\x66\x5d\xdc\xe4\x6a\x94\x75\x5d\x32\xb5\xb2\xfd\x06\x65\xd2\xa8\xdf\x6f\x74\xe1\xc8\x2b\x6a\x72\xe3\x24\xc8\xf2\xf0\x83\x91\x06\xef\xf6\xec\x53\x97\x6f\x5e\xb7\xe6\xa4\x5c\xdc\x9f\x7e\x94\xcc\x51\xb6\x06\xda\x34\x53\x0e\x30\x81\x20\x10\xe5\xf3\x38\xe3\xbc\x3a\x70\x89\xda\xf5\xf9\x96\xc1\x42\xd6\x5f\xa3\x4a\xac\x60\x79\x6f\x0d\xac\x9a\xf5\xc8\xc0\x09\x41\x93\xb2\xfd\xe4\x52\xa7\x50\x3f\xa1\xca\x7e\x3c\x36\x93\xb2\xf5\x27\x18\x85\x28\x6f\x15\x8b\x69\x69\x11\x6a\xb7\x9d\x04\x26\x10\x0c\xac\x62\x4f\x3e\x4e\x77\x29\x4a\xb6\x3d\xcd\x6b\xa5\x77\x65\x25\xa4\x5e\x63\xf5\x4d\x47\x07\x57\x2e\x4a\xdc\x76\x1f\x10\x2e\x6a\x5b\xea\x95\xe4\x6b\x7a\x0e\x5a\x54\xcd\xb2\x8a\x63\x2b\xd9\xe5\x22\x94\xf6\xc2\x39\xff\xbe\x36\xc4\x41\xac\x82\x03\x3d\x5f\x3e\x9e\x11\x0d\xff\x18\x9e\x1b\x85\x0f\x0c\x84\x31\xc4\x19\xcc\x41\xa5\x82\x3e\x00\xc8\x6f\xa0\x61\x8c\xb8\x78\x87\xdc\x0d\x05\x40\x38\x89\xce\xc6\x66\x76\xae\x03\x21\x00\xa8\xdc\xf9\x4e\x92\x4e\x48\xe9\xab\x28\xfa\x7e\x0c\x31\x15\x73\x90\x67\xfc\xf7\x3d\x55\xd9\xf7\x04\xe2\x2a\xe1\x21\x6f\x82\x30\x00\xd4\x0a\xec\xc2\x09\xaa\x8b\x84\xb8\xaa\x52\x2f\x17\xee\x21\xbe\x23\x6a\x51\xee\xe0\x58\x90\x08\x80\xaa\x5f\x53\x1f\x64\x68\xb1\xd5\x99\x1d\xbe\x1f\xe1\x1e\xce\xba\x8a\x4b\x15\x5b\x57\xa3\xb2\x52\x4b\x32\x93\x9c\xa9\x70\x59\x76\x4a\x49\x4e\xa2\x23\x95\x7d\xec\x1d\x34\x94\xb5\x99\x8e\xb9\xf2\x4a\xd2\x0a\x07\x27\xa4\x8f\x28\x49\x2f\x18\x0c\x7c\x3e\x3d\xd1\xe8\x7d\xdb\xdd\x55\x5f\x24\x6e\x4e\x1b\x74\x48\x10\x42\xef\x0c\x3e\x54\xfb\x42\xf1\x00\xc6\xe2\x24\x66\x21\x9c\x5d\x42\x69\x0c\x9c\x41\x48\x40\xc1\x59\x7a\x17\x39\xeb\x9a\x0f\x07\x1b\x3a\x68\xd4\x15\x45\x08\x25\xe4\x62\x17\xcb\xc9\x9b\xa8\x0e\x86\x5e\x15\x0c\x95\x39\xac\x11\xc7\xb8\x4e\x7d\x66\x6b\x61\x51\x4c\x78\x96\x37\x06\x13\xeb\x4b\xd1\x35\x4f\x0a\x15\x9c\xc6\x38\x54\x87\x6d\x98\x52\xe5\xba\xc5\xc0\x46\x00\x88\x3b\xe4\x49\xae\x4e\xbb\xa0\xd9\x45\x85\x91\x36\xf2\x53\xbd\x50\x59\x0e\x89\xd3\xeb\x77\x5f\x14\xd5\x5f\xc2\xc0\x02\x00\x88\xef\x90\x6e\x37\x03\x60\x56\xa9\xb5\xb4\x00\x4d\x05\x8b\xb2\xba\x13\xa7\xcf\x25\xf5\x9c\x10\x46\x0a\xa8\x60\xf4\x3d\x69\x8a\x31\x4a\xeb\x12\x88\x10\x4a\x6a\x10\x2c\x00\x80\xfc\x51\x89\xd1\xd7\xa4\x80\x51\xfa\xee\x29\x42\x28\x69\x6f\x53\x67\xbb\xa9\x91\x6c\x03\xbd\x40\x34\xf2\xee\xd4\x79\x6d\xdd\x24\x6f\x73\x87\x6c\xc3\xd1\x7e\x2d\xc5\xe0\x2d\xe2\x0c\x7e\x0b\xed\x35\x56\xa5\xc6\xe7\x5f\xcb\xe0\x2d\xb5\xca\x48\x1a\xfe\x77\xa8\x4d\xc2\xad\xd5\x26\xff\x22\x23\x69\x93\xab\x16\xa4\xe9\x2f\x86\xc1\xf3\xc4\x51\x62\x2f\xda\x0f\x06\x6a\xec\x06\xf2\x3b\x0a\x78\xde\xdf\x8d\x83\xbe\x7f\x13\x1b\x17\xfc\x7b\xb2\x1d\xe5\x75\x55\x8d\x0b\x16\x1b\x5a\xd2\xe8\xe0\x81\x62\x23\x4b\x1e\x7c\x5c\x2e\xd8\x58\x6c\x1f\xa7\xc9\x6a\x10\xc2\xec\x9a\x6a\x71\xcd\x36\x59\xdc\xb1\x99\x31\xb0\x14\x61\xc7\x2d\x2d\x80\x00\x93\x3b\xdb\xb1\x3f\x51\x99\xa0\x27\x88\x02\x71\x20\x8d\xbb\xbb\x62\x37\x45\xb3\x5a\xc8\x74\x7f\x88\x66\xbe\xf0\x3c\x60\x1f\x10\x37\x39\x7b\xc8\xe4\xac\x44\x47\xaa\x55\xd2\xe9\x11\xe2\x08\x6e\x09\x20\x27\x3b\x0a\x3b\x86\xa5\x24\x0c\x62\x3e\x40\x66\xa6\xe7\x95\xa4\x8d\x1e\x7c\xef\xd7\x32\xe9\x3e\xb2\x94\x1f\x89\xef\x9b\x7f\xec\x4d\x57\x7e\x92\x23\x6d\xf4\x60\xf6\x6e\x45\x8c\x8d\xcd\x02\xae\x8b\x0d\x4d\x92\x20\x68\xf2\xf8\x85\xf6\x49\xf4\xec\xb3\xe5\x8f\xba\xf7\xf9\xc3\x45\x3c\x17\x3e\xec\xbf\x96\x27\x9f\xc8\x1c\x2d\xc2\x85\x81\xac\xce\x76\x7c\x20\xb2\x59\x9c\x00\xa8\x9f\x09\xe4\xe0\xb2\x54\xb5\x66\xb6\xf4\x56\x52\xa6\x1c\x3b\x30\x95\xbb\xc6\x8a\xce\x76\xdc\xc3\xd5\x47\x48\x43\x37\x2c\x5d\xa9\x90\xa0\xb0\x7b\x2a\x54\xcd\x9e\x0a\x09\xae\x68\x7d\x23\x48\x51\x2c\xe1\x4f\x52\xab\x08\xeb\xbc\x02\x00\x5e\x6d\xca\x01\xbd\x40\x04\x00\x76\x51\x8e\x76\xe9\xb1\x23\x5e\x9c\x8f\xfd\x17\xe2\xc5\x20\x4e\xbf\x6e\x0a\x16\xdd\xdb\xb0\x6d\x8f\xa7\x4e\x81\x5e\x8c\xf5\x29\x69\xdb\x63\x33\x49\x5a\xfc\x2d\xb3\x08\xc4\x2d\x51\x89\xe8\x6e\x05\xe9\x76\xfc\x33\x85\x6e\x17\x27\xdd\x17\x74\x3b\x21\xc9\x19\x2f\x28\x76\x79\x7e\x78\xa4\xdb\xf1\x7f\xc9\x75\xbb\xb8\x49\x56\xb7\xe3\x92\xca\x01\x82\x62\x57\xb4\x87\x51\xc4\x19\xfc\x3a\xf2\x7d\x8d\x60\xac\x74\xad\xd7\x7a\x8c\x52\x7d\x7e\xd7\xf2\x11\x46\xed\x12\xd1\xda\xed\xf2\xaf\xc2\xd2\x76\xb9\xb2\x03\x9a\x6e\xad\x12\xdd\xeb\xd0\xd2\xbd\x8a\x08\x03\x75\xe5\x5b\xab\x59\xa6\x43\x2d\x57\x16\x8a\xf5\x27\xdb\x81\x19\xd8\xb4\x62\xfd\xc5\x73\x4e\x25\xb1\xc0\x10\xc9\x65\xa2\x7a\x72\x81\x30\xf1\x1c\xe4\xfa\xac\x06\x66\x66\xef\x52\xcf\x63\x60\x53\xcb\xd5\x1a\x8f\x2e\x02\x35\x52\x0b\x70\xf7\x7e\x6c\xee\x82\x4c\x60\x06\xfd\xc1\x20\xd6\x3a\x56\xb6\x2f\xd6\x8b\xaa\x1a\x5a\xd9\xb9\x97\x53\x8c\x67\x94\x5a\x5a\x03\xd1\x66\x56\x47\xc2\x70\x55\x5d\x2d\xc6\xe9\x64\x6f\x50\x75\x71\x5a\xd5\xb4\xb5\x36\xcc\xab\x32\x8d\xad\x8f\x31\x5a\xae\xb6\xf1\xce\x2f\x69\x0b\xc1\xd6\x7b\x8a\x01\xc9\x00\xe0\xe6\x1c\xe8\xcb\x6f\xe1\x0c\x82\xb8\x19\xcd\x4f\xee\xa6\xc7\x24\xb7\x40\x92\x6e\xbb\x7e\xfc\xf8\xc3\xcf\x5f\xf8\x76\x5b\xf9\xe6\x91\x3d\xe3\x46\xb7\x26\x3f\x5d\x30\xff\xb5\x59\x4b\x17\xd5\x6e\x49\x84\x7d\xc5\xd1\x20\x16\x62\xf9\x7f\xfe\x7c\xfd\xcb\x8f\xe9\xb7\xde\xca\x1a\x39\xf2\xb7\xf4\x07\xd8\x1f\xd2\x33\xb7\xc0\x80\x17\x37\x36\xef\xff\x14\xab\x92\xf9\x66\x49\x70\xa5\xfa\xc7\xa5\x7c\x59\xd2\x43\xd6\x21\x09\xf6\xd0\x45\x86\x47\xcb\xdd\xaa\xf8\x79\x7d\x13\xe5\xd4\x55\x1f\x4f\x95\xbd\x4f\x39\x86\x7f\x51\xbf\xc7\xd3\x98\xf7\x8a\x03\x02\x3b\xb7\x16\x71\xb9\x7d\xd3\xd9\xcc\x92\x06\xb3\xfb\x6a\x9c\xf6\x55\xd6\xa2\xc5\xd8\xf9\x5f\x2f\xd1\xaf\xc6\xad\x00\x06\x4e\x01\x40\x5c\x30\xe5\x80\x00\x10\x0e\x00\x9f\xf3\x36\x52\xaa\x88\x4e\xf9\x52\xcb\x86\x49\x2f\xdb\x7c\xb9\x64\x89\xbf\x8b\xd4\x0e\xdf\x2e\x75\x0a\x04\x80\x40\x71\xbb\x1e\x9b\x49\xd4\x1a\xc5\x5e\xae\x89\x5a\xa1\x90\x6a\x01\x18\x78\x03\x00\x92\x3d\x77\x85\x88\xf6\x3d\x21\xed\xf0\x1b\xc2\xfd\x7e\x92\x28\xef\x2d\xb7\xe7\x15\x89\x53\xdc\x02\x0c\xbc\x08\x00\xf9\x03\x77\x4f\xe7\x3b\xcb\xf0\x4d\xbd\x88\x36\xbb\x9f\x7c\xcd\xf0\x5b\x9d\x34\x85\x2f\x5b\x0f\x88\x4c\x42\xfe\xbd\x51\xea\x35\x71\xcc\xd0\xc6\xfc\x03\xb0\xd9\x71\xb3\x2b\x8d\x39\xd1\x26\x42\xb9\x27\x3a\x2c\xfe\xfd\x9f\xe8\x93\xf4\x99\x86\xd5\xad\xf5\x17\xaf\x6d\x78\x7e\xa7\xaa\xfb\xf9\x47\x1f\xfe\x97\xfe\xc9\x7b\x06\xbb\x7c\xfc\xd0\x9a\x45\x00\xe0\xf0\x30\x71\x8b\xc8\x44\xf6\xa6\x05\xc4\x72\xbb\xa1\x9e\x56\x85\x87\xb5\x95\x28\x6f\x52\x2a\xd5\xa5\xb8\x1f\x33\x73\x4a\x80\x7e\xb4\xa2\xd0\x8d\x5c\x09\xf2\x7d\x28\xd4\x1d\x80\xd8\x5a\xe2\x2a\x3e\x81\x8a\x06\x01\xcc\x69\x8a\x1b\x59\x6c\x2d\x3f\xa2\xa2\xab\x20\xc1\x3f\x34\x1a\xf9\x12\xe5\xdf\x9f\x27\x9d\xc1\x7c\x36\x72\x67\xa1\xab\x5d\x4b\x6f\x23\xf3\x09\x5a\x27\xba\xd7\x42\xb2\x10\xc5\x5d\xcd\x5f\xac\xb8\xc3\xef\xaa\x5f\x6b\x37\x70\x2b\xb8\xef\x52\xbe\x59\xcd\x17\xa3\xae\x22\x4f\xec\x42\xfe\x1e\x99\xcf\x5e\x89\x2c\xff\x11\x79\x13\xe5\x62\x35\x2e\x85\xda\xeb\x90\x3f\xfc\xef\xab\x6f\x27\x06\xf3\x0f\xa9\xdc\x1b\xb3\x63\x80\xb0\x67\x82\x89\xf7\x35\xff\xbb\x23\x8f\x6c\x3c\xac\xf7\x21\x9e\x7c\x78\x54\xee\x0c\xdf\xe8\x6c\xa7\x52\xc9\xf3\x68\x2f\x1a\x28\xbe\xc9\xd2\x29\xe0\x21\x6c\x04\xeb\x75\xca\x76\xf0\xcf\x2b\x27\xfc\xd5\x15\xc1\x41\x4d\x67\x3b\x79\x99\x3c\x0f\x4c\x20\x0c\xe5\x1a\x33\x50\x43\xa4\x06\x4d\xd2\x7e\x3a\x55\x4e\xf8\x67\x18\xbf\x75\x4d\xd0\xbe\x47\x95\x22\x0e\xe2\xc5\xe7\x3d\x7f\x2e\x1a\x02\x0d\x26\x3f\x99\x2e\x85\x63\xa1\x91\xf4\xb9\x00\x03\x65\x00\x90\x3f\x21\x1f\xbf\x41\x46\x3c\xfc\x38\xba\xca\xfc\x78\x7e\xdc\x46\x94\x19\xf4\x6c\x2a\xbf\x02\xb0\xce\xf6\xce\x76\xd3\x3f\xf9\x3c\xbe\xf6\xae\xbb\xeb\x58\xba\xe4\x1d\xd9\x1d\x7f\x1b\x88\x35\x13\x57\xf1\xd3\x54\x34\x30\x01\xc0\x13\x81\x35\xb3\x09\x01\x7d\xd7\xf5\x00\xc2\x71\xdc\x7b\x58\x88\xda\xa9\x16\x8e\x13\x1b\x0c\x2a\x15\xe3\x61\xe7\x65\xfa\x36\x48\x24\x29\x80\x03\x80\x87\xb8\x42\x12\xcb\xe8\xdb\x54\xf8\x4f\x7f\x63\xda\xee\xb4\xd1\xb7\xc1\x0d\xb2\x11\x04\x01\x80\x7b\x9c\x1e\xab\xc7\x6a\xb2\x9a\x9c\x21\xf6\x10\xd3\x8d\x83\x07\xdd\x87\x0e\xb9\x0f\x1e\x74\xd7\x97\xd5\x13\xe0\xe0\x7e\xcf\xa1\x43\x9e\xfd\x07\x3d\xf5\x77\x0f\x92\xe5\xf5\xcc\x77\xaf\xd0\xb7\xe1\x31\xb2\x11\xf4\x64\xda\xb5\x39\x3d\x56\x93\xd3\x63\x0f\x89\x87\xc5\x0d\x9e\xeb\xd7\x3d\x0d\x77\xe8\xdb\xe4\xcd\x3a\xcf\xb5\x6b\xee\xba\xbb\x4b\x01\x80\xf4\x38\xfa\x36\x88\x67\x3f\x0f\x3d\x56\x93\x2d\xc4\x1e\x62\xb7\x9a\xe8\x71\x37\x3c\x8d\x70\x5c\xe9\x9d\x46\x0f\x71\xe8\x9a\xa7\xee\x6e\x0c\xd9\x52\xe7\x06\x00\x02\x37\xbc\x88\x65\x63\xab\x18\xdc\x66\x8f\xcd\xe4\x76\xc0\x5b\x03\xe1\xc5\xfd\xfb\xfd\xfd\x6e\x35\xd6\x42\xb8\x71\x27\xc0\x41\xc0\xdb\x00\x82\x64\x57\x6a\x0a\xf3\x99\xd5\x31\xf8\x2b\xfd\xb1\x96\xed\xdb\xd9\xef\x7f\x89\x6f\xc1\x56\x03\x1c\x58\x46\x04\x42\x30\x7b\x6a\x32\x7c\x04\x36\x43\x1c\x82\xe4\x99\x89\xec\xe7\xdd\x0e\x3c\x73\x00\xfc\x92\xef\xef\x4b\x53\xb5\xbf\xcf\x9b\x82\x55\x3e\x0f\x64\xbf\xc3\x60\x3a\x1d\x8a\x37\x51\x16\x80\xa3\x91\x0f\x71\x85\xd8\x42\x5c\x21\x30\x7d\x2b\x4c\xda\x4a\x87\x06\x60\xff\xa5\x99\x3f\x00\xef\x4c\xf5\x1e\xc4\x8e\x76\x9e\x43\x9f\x0b\x60\xc6\xc7\x66\x62\x0c\x62\xfc\x42\x34\x9e\x14\xed\x0d\x60\xfe\x7f\x2d\x9d\xd9\xd0\x00\xfb\x34\x34\xd0\xb3\xd1\x5c\x01\x6b\xf1\xd3\x58\x30\xd9\x06\x28\x00\xcc\x19\x66\x17\x66\xb2\xaf\x9d\xfa\x4e\xd3\xf3\xd9\x67\xf0\x2b\x9f\xc3\x70\xfa\xc4\x21\xee\x33\xa1\xe8\x4d\x17\x98\x43\x3d\x2e\x6b\x10\x34\xad\x7d\x76\xd4\x2f\x03\x06\xbd\x50\x8e\x9f\x86\x09\xe7\xc2\xa7\x77\x36\x32\xe3\xbb\x8b\xbe\x03\x5d\xe0\x3b\xa6\x2d\x9c\xf9\x1c\x85\x57\xae\x2c\x3b\x13\x50\x71\x98\xbe\x03\xa9\xdb\xd6\x2f\xe9\x1f\xd8\x3e\xbf\xc2\x4f\xc3\xe3\x5c\x9f\x1e\x57\xb0\xd5\x1e\xf7\x55\xc8\x91\xe0\xfa\x1c\x72\x4f\x38\xfd\xef\x6f\xfe\x8c\xf4\xc2\x5a\xfc\x34\xde\x84\x3e\xd3\x5b\x40\xe6\x90\x00\x84\xcb\x27\x7d\xbc\x7e\xcb\xd0\x5f\xf2\x40\xc3\x4f\xc0\x04\xfa\xc0\x2e\xee\xbb\x9b\x10\xde\x3e\x3e\xc4\xae\x0c\x16\x12\x8f\xfc\x76\xfa\x53\x96\xb3\x01\x0f\xff\x42\x90\x60\x25\x2c\xc8\x0e\xff\x15\xfd\x35\xd2\x4b\x8c\x2c\xd8\x21\x24\x4b\x6f\x41\x1a\x97\x44\xa8\x7f\x3c\x97\x7b\x26\x60\xda\x31\x41\x36\x38\xfc\x3d\xeb\x27\xf4\x2d\x80\x31\xf2\xe1\x56\x01\x3b\x2b\xa1\xc3\xe3\xb2\x08\x82\xc2\xc9\xc1\x47\x42\x04\x79\xbd\xe1\x1d\x3f\xfd\x99\xe1\xe5\x0a\x00\xf8\x45\xca\x02\x7a\x31\xdf\x22\xcd\x2e\xdc\x61\x72\xe0\x76\x78\xc5\x01\x1d\x8e\xcb\x9b\x61\xa1\x83\x3e\xbb\xef\x32\x0c\xc2\xaf\x1f\x8f\x85\xaf\xd1\x33\x63\x8f\xc7\x74\x10\x38\xcd\x72\x9a\x0f\x00\x7e\x8b\xb2\x80\x30\xf4\xdd\x48\x48\xf2\x0d\xf4\x82\xa8\x15\x73\x7e\x1c\x1c\x1a\x5c\x45\x9f\x72\x42\x4f\xe4\x95\x46\x38\xca\x49\x9f\x0d\x5c\x08\x0b\x9d\xf4\x59\xe6\xaf\xd3\x8e\xf5\x87\x03\x61\x98\xed\x78\x2c\x5c\x43\x3f\x1b\x7b\xdc\x46\xff\x9d\xfe\x63\xff\x63\x31\xf4\x7a\xb8\x1a\xb5\x7f\x16\x7e\x87\x3d\x8f\x7f\x0b\x7a\x81\x80\xb7\x7b\xe0\xec\x1a\x11\xd9\xe9\x67\x57\x2e\x5d\x52\xbb\x6a\xd1\x92\x5a\xac\x7d\x4d\x43\xc3\x9a\x35\xcf\x34\x02\x1c\xc4\x77\xde\x22\x0b\xc1\x1d\xd0\x8b\xad\x2f\x2a\xb6\xeb\x1d\x1a\x3f\xc7\x4f\x19\x93\xe4\x29\x29\x74\x79\xb0\x20\xe1\xa7\xde\xfc\x4f\x13\xc6\xcd\xf2\x64\x14\xcd\x1e\xea\x92\xfd\x57\xd0\x2d\xc4\x45\x40\x22\xdd\x12\x66\x0b\x89\x87\xd7\xe8\xd5\x8c\x46\x99\x74\x77\x29\x80\xf4\x04\x46\x97\xa0\xdf\xf7\x3c\x46\xa0\x45\x9e\x9c\x9a\x02\xdd\x8c\x4e\xa1\x27\xc0\x6b\xa5\xc4\xba\x49\x8c\x22\x41\x3a\x2e\x94\xbe\x0d\xbe\x23\x1b\x98\xf9\x8e\x87\x20\xad\x13\xf2\x1d\xfc\xe3\xa7\x65\xf8\x45\x78\x8c\x9e\x70\x2f\x86\xb8\x09\x24\x9f\xeb\xc5\xf7\x69\x0b\xe3\x3e\x4b\xaf\x84\xcf\xb1\x9f\x9f\x44\xb7\x73\xdf\x90\x7e\xde\x6d\x0b\xb1\xb9\xf9\xb6\x9f\xa3\x57\xb2\xed\x4f\x80\x96\x49\x7c\x0f\x26\xb0\xaf\xb3\x3d\xe0\x20\x79\x0e\x79\x93\xf4\x07\x49\x20\x13\x14\x81\x29\xe2\xfc\xa4\xec\xe5\x36\x73\xcc\xb4\xb0\xf6\x82\x7d\x40\x10\x84\xfc\xaf\x83\x30\xe4\xc4\xe3\xfb\x0d\x29\xfb\x4d\xb8\xef\x57\xfb\xaa\x0e\xaf\x78\x6c\x4d\xee\xbc\x17\x1e\x5e\xb6\x76\x24\x91\xb3\xe7\xde\x27\x93\xaa\x72\xe6\x8d\x9c\x9f\x37\x2f\x17\x9b\x31\xef\xcd\x9a\xc7\xd6\x66\xcf\x6b\x9e\xba\x7c\xed\xf6\xca\xdc\xca\x51\x0b\x46\x54\xe6\x62\x01\xf3\xdf\x5c\xf1\xd8\x9a\xec\xaa\xe6\xb2\xe5\x75\xdb\x53\x32\x72\x2b\xf3\xe7\x8d\x98\x97\x8b\xcf\x3a\x00\xd3\xb6\xb6\x6c\x58\x44\x77\xbe\x35\x67\x87\xd7\x45\xb6\xdd\x2d\xc6\x67\xef\x7b\x0a\xe2\x55\x7b\xd6\xfe\xe8\xcd\x3e\x04\x93\x76\x6c\x5e\xbf\xc8\xfb\x76\xe5\xb6\xed\xfb\xea\x20\x35\x6f\xcf\x9a\xff\xae\x3e\x08\xd3\xb6\x31\xff\xf8\x4e\xc5\xb6\xed\x25\x25\xf5\xcc\x67\x9f\xf8\x17\x80\xe0\x06\xbe\x1f\xb6\x93\x6d\x8c\x4e\x64\xac\xd1\x1b\x45\x67\x5a\xf1\xfd\x58\xb0\xf7\x36\xc0\x98\xdf\xe1\xe3\xd0\xef\x4c\xec\x6f\x5d\x66\xf6\x13\xff\x10\x3e\x85\x3e\xc9\xd8\x5c\x37\xf0\xfd\xc4\x9b\xdc\x67\x7b\xf9\x3e\x2d\xfe\xc6\x77\x92\x6f\xa1\x6f\x42\x50\x06\x96\x62\x1e\xfc\x0c\xd2\x53\x6e\x68\x85\x66\x53\x19\x6c\x2a\xa7\xaf\x1e\xac\xc3\x1c\xd1\xb0\xa1\x9c\x3e\x46\x37\xba\x01\x04\x16\xb0\x14\xfe\xc0\x7e\xce\x03\x71\x8f\x39\x0c\x5a\xa0\xf3\x60\xdd\x5f\xe8\xd5\x67\xe1\x78\xb8\x36\x83\x1e\xd3\x8f\x5e\x0b\x08\x66\x3d\x10\xc1\xe8\x8d\xb2\x0f\x88\x64\xdf\xc8\x7c\x33\x3f\x12\xba\xa0\x59\xf6\xf7\xf8\xd2\xc2\x21\xc3\x26\x17\xb8\x87\xae\x3b\x72\x8d\xbe\x7d\x4b\xf2\xb7\x92\xb1\xd3\x33\x33\x0a\x67\x0f\x83\xf5\x44\xbf\x7b\x7f\xa5\xdb\x24\x7f\x65\x75\xc2\x05\xca\x42\x44\x50\xbb\xf9\x3d\xe5\x82\x0d\x8f\xb7\x53\x96\x8d\x1b\x99\xbd\xd5\x02\x00\xf6\x03\xcb\xad\x0d\xba\x20\x6d\x21\x72\xf6\xde\xfb\x84\x19\x2e\xf6\x4e\xf3\xbd\xce\x5b\xf0\x24\x79\x9e\x5b\xbb\xc9\x60\xca\x88\xcc\x48\x5b\xdd\xd4\xb0\x3e\x75\x53\x23\xc3\x22\xc3\x7a\x38\x9d\x49\x75\x53\xd7\x3a\x37\x39\x77\x3a\xf1\x52\x67\xa5\x13\x8b\x74\x26\x3a\xb3\x9c\x78\x1f\x27\xec\x85\x39\x89\x1e\x78\xdd\xd4\xd8\x1e\x29\x3d\x46\xf4\xc0\x7b\x98\x41\xee\xcc\x44\xd0\x37\xf7\x91\x59\x33\x67\xce\x9c\x99\x18\x12\x0a\x32\x33\xfb\x26\x27\x27\x26\xa6\xa6\x88\x09\x08\x31\xf0\xf3\x7b\x23\x72\xb3\xf3\x0b\xb2\xb2\xf3\xf3\x72\xd8\xff\xf2\x7f\xe7\xff\xbb\x34\x7f\x4c\xd1\xc8\x91\x63\x8a\xe1\xf5\x82\xa2\xa2\x82\x7c\xe6\x07\xe6\x5f\x84\x1f\x46\x8e\x29\x96\xae\xdd\x3e\xcc\x5a\x74\x85\xd8\xdd\xcc\xda\x75\xb1\xeb\xf7\xd3\x4f\xe1\x1f\x3f\xfd\x94\x5f\x8f\xbe\x15\xcc\xec\x0b\x3e\xdd\xd0\x0b\x44\x8e\x08\x02\x01\x80\x08\x26\x62\x09\x9c\x20\x7b\xe2\x24\xa3\x55\x82\xcf\xcf\x4c\x4b\x4b\x4d\xe1\x15\x87\xd3\x16\x62\x43\xca\xa3\x06\x0e\xa7\x7f\xe9\xd3\x20\x13\xa0\x05\xe1\x08\xa6\x6f\x83\xdb\x64\x03\xd2\x5b\x36\x3c\xc4\x1e\x72\x1b\xfe\xef\x99\x32\xb2\x81\x6e\xb9\xfb\x47\x72\x20\x10\x7d\xa6\x09\xed\xab\x91\x90\x69\xf5\xf6\xed\xdb\x67\x18\xf5\x72\x92\x2e\x42\xd0\x30\xee\x33\x8d\x80\x42\xd6\x95\xc7\x6a\x62\xfa\xb6\x7a\x9c\xe8\x93\xa5\xf5\xf5\xf5\xc4\xa1\x6b\xd7\xda\xee\x76\x90\x44\xdb\xf2\xe5\xcb\xa5\x1c\xf4\x16\x38\x10\x31\x10\x21\x10\x40\xef\xf2\xc9\x0f\x9a\x31\x37\x0e\xd0\xbc\xe8\xcb\x6b\xa2\x90\x60\x41\x9d\xe4\x40\x56\x9d\x34\x57\x1e\x5c\x7c\xe7\x37\x6f\x3d\xf6\xe4\x0b\xe9\xc3\x73\xaa\xf2\x6a\x46\x2c\x18\x86\x2f\x3d\x00\xed\x5b\xe9\xab\xf4\x6d\xfa\xd5\xdd\xbb\xa6\xcf\x5e\xf5\x43\xd3\xfe\x67\xbf\x46\x6d\x96\x63\xc5\xd8\x57\xe4\x29\xd0\x13\xdd\x9f\x79\x98\xe5\x69\xb2\x9b\xec\x1e\xa7\x2b\xd4\x43\x99\xca\xad\xf0\x66\xcb\xea\xba\xf0\x75\xf1\x4d\xf1\x9f\x5e\x1f\x1d\x12\x35\x09\x0f\x5e\x88\xe5\x79\xcf\xaf\xfe\xd5\xaf\x56\xc3\xa2\xac\xf4\x99\xcc\x5c\x6f\xc0\x32\x71\x82\x6c\x43\x59\x8e\xdd\xe1\xec\xe5\x98\x7d\x80\xc9\x69\xb6\x99\x6c\x26\x4e\xeb\x41\xfb\x80\x86\x95\x0b\xaa\x96\x4c\x1f\x3d\x3a\xc7\xb3\x16\x1e\xeb\x4b\x7f\x92\x9b\x9c\xb4\xfc\xe9\xb2\x9f\x2d\x5f\x85\x2d\x6e\x2a\x9c\xff\x70\xfe\x18\x6b\x32\xdc\x57\x7f\xa5\x77\xfd\xf2\x47\xb6\x94\x30\xd8\xf6\x60\x1e\xdc\x42\x9e\x06\x7d\x7d\x19\xa9\xad\x26\x74\x1d\xed\xe2\x6e\xab\x7d\xc9\xa9\x59\xd9\xf7\x34\xfc\x7e\xeb\xe8\x9c\xfe\x59\x45\xcb\x76\xdb\x03\x62\xe6\x0e\x9d\x5d\xf3\xf6\x8b\x35\x0d\xeb\xf3\x86\x4d\x98\x5d\x9b\x54\xe2\xc6\x27\xbc\x09\xd3\xb6\x86\xac\x36\xb7\xb6\x24\xa6\xd6\x2d\x7c\xe9\xcc\x8b\xf5\xa3\x1f\xaa\x9b\x55\x3f\x64\x1c\x5a\xb3\x87\xb0\x62\xdc\x85\x6c\x87\xb0\x11\x3d\x49\x13\x06\xb1\x14\xbc\x3f\x88\x05\xb9\xb9\xfd\x3e\x5f\x9e\x99\x9a\x62\x86\x36\xc6\xac\x3b\x04\xbf\xa4\x57\xf5\xc3\x1c\x16\x3a\x09\x2b\xc6\xfe\xbd\xba\xa2\xe3\x47\xf6\x3c\x5f\x8f\x65\xe2\x14\x79\x16\x84\x83\x01\xa8\x0e\x58\xba\xf8\x26\xdf\xd4\x1f\x4a\xf1\x32\xa7\x79\xb3\x25\xdc\xca\x8c\x1b\x23\x54\xfd\xcd\xec\xe4\x57\x36\x2c\x7d\x72\xf1\xac\x31\xb9\x6f\x37\xd7\x36\x37\x4d\xcc\x2d\x9a\x32\x2a\x6d\x56\x59\x6d\xbc\xa7\xbc\x30\x37\xad\x60\x0c\x6e\x39\x51\x3a\x64\x4a\x76\x55\xc3\x8a\x87\x4b\x1e\x8f\x4d\xae\xcc\xaf\x6d\xa9\xad\xcd\x1c\x31\x29\x2f\xad\xac\xaf\x7d\x2a\x7c\x62\x50\xbe\x3d\x66\x62\xc6\x90\x8c\x42\x80\x81\x26\x2c\x1b\xeb\x20\xcf\x02\x2b\xaa\x84\x86\x46\xc5\xc3\xf4\xee\x4e\x17\x5d\xf4\x9b\x2d\xfc\x60\x51\x4d\xd9\x0f\xd5\x1d\xed\x3b\xae\xfe\x91\xe5\x93\x5a\x66\xaf\x5a\xd7\x78\x79\x47\xe1\x86\xda\xf1\x55\x23\xb2\x26\xcc\xc6\x26\xac\x8b\x7c\xab\x79\xf1\xda\xea\x8a\x9f\x4d\x7b\xb1\xf1\x4d\xfa\xfc\x16\x6c\x68\xdd\x92\x92\xa2\x49\x75\x00\x82\x7d\x78\x34\x6e\x23\xcf\x32\xb6\x4f\x24\x74\x71\xa3\xcd\xf9\xfc\xa0\x07\xe1\x7d\x2d\x0b\xcd\xf3\x5f\x18\xfd\xb0\x75\xc2\xba\xb2\x90\x71\xe3\x9e\x8f\xce\xc6\xa3\xb1\x57\x36\xed\x98\x3c\x79\xd8\x34\xfa\x39\x58\x9f\x17\x5f\x7a\xe0\x49\xfa\x1b\x66\xbc\x23\x3b\xc7\x60\x9d\xd8\x14\x10\x0c\xa2\x18\xfd\xcc\x00\xb5\x7a\x5c\xb8\xdd\xc3\xb9\xc4\xb2\x73\x9c\x41\x1b\x59\x79\x74\xf1\x9a\x91\xce\xfa\xdd\x8d\xd4\x90\x95\xd9\x4b\x57\xef\x59\x5a\xb8\x38\x3f\x27\x63\xee\xa6\x31\x9b\xff\xdd\xb4\x64\xb6\x37\x68\x6e\x5a\x6e\x53\x6d\xc3\xa2\xcf\x4b\x73\xc6\xff\x0d\xcd\xf3\xe8\xce\x29\xd8\x8b\xd8\x1c\x94\xd5\x8e\x6b\x9b\x19\x95\x44\x68\xf2\xf9\xde\xc6\x99\x07\xb2\xcd\x47\xcf\x3f\xb9\x62\xc5\xf2\xaf\xaf\x9a\x89\x92\xe2\xaa\x35\x19\x35\x13\x9f\x7b\xe9\x17\x30\x26\x3e\x31\x77\xd9\x8a\x86\xbf\x3e\x5b\x59\xfe\xd4\xc6\xa4\xb1\x13\xb3\x1b\xfa\xda\x36\xc3\x21\x64\x43\x6c\xe2\x4a\x76\x7d\xba\x3b\xa7\x60\x7f\xc7\xe6\x80\xde\x6c\x6e\x76\xae\x0f\x91\x3f\x2f\xdb\xba\x7b\xee\x89\xda\xa6\xdd\x15\xc7\x6a\x9f\xfb\xd9\xcf\xc6\x8f\xaa\xa8\x1f\x9d\x33\x6f\xc3\x9a\xc6\x5b\xf5\x7b\x9a\x36\xdc\x78\x62\x77\xe3\xe4\x29\xbf\x7d\xad\xf8\xe1\x4b\x00\x76\x1e\xeb\x9c\x84\x7d\x8b\x95\x30\xfb\xa6\x09\xe2\x2e\xb4\x4b\xd9\x7b\xc1\x09\x70\xc2\xde\xdd\xd5\xe7\x4e\xd2\xa7\xdb\xf6\xad\xb9\x7c\x14\x6e\x82\xab\xe8\x0e\x48\xd0\x6b\xe9\x06\x18\x44\x7f\xcf\x62\x49\xeb\x9c\x82\xed\xf7\xc9\x9b\x91\x05\x3d\x68\x51\xba\x95\xa8\x3c\x44\xda\xdf\x2f\x9b\x89\x09\x13\x58\x51\xb7\x57\x31\xc2\xbf\x12\x9f\x38\x62\x69\x14\x7d\x33\xe4\xe9\xa6\xa4\xa2\xc9\xd9\x0d\x11\xb1\x9b\x9f\x7b\xe6\xaf\xcf\x56\x3e\x1a\x3b\xf8\xb1\x99\x24\xbb\xc7\x35\x01\x40\xd4\x91\xe7\xd8\xbc\xed\x39\x18\xb7\x3a\x83\x30\x54\x4f\xc0\xec\x73\x79\xb2\x99\xed\x03\xe2\x9a\x46\x6f\x3a\xbd\xbc\x61\x75\x72\xd5\xfc\xd1\x4f\x4c\x4b\x9e\xf6\x68\x64\x39\x16\x14\x4d\xb7\x0e\x87\x13\xa2\xe8\x63\x85\xb0\x2a\xda\xfb\x7d\x45\xc4\x9b\x6f\xe0\xee\xa7\x7e\x7a\xef\xd1\xa1\x9b\x86\x4d\xda\xf6\xd9\xac\xa5\x2b\xe0\xbe\xf5\xf4\xad\xf5\xf4\x7b\x4d\xf0\xc2\x07\x68\x8d\xd5\x76\x36\x11\x9f\x52\xa1\x60\x00\x18\x04\x52\x00\xb0\x9a\xe3\xdc\xe9\xa1\x03\x73\xa1\xcb\xe4\x41\xb3\xc5\x14\x6e\x35\xc5\x39\x21\x2a\x62\x60\xb2\x7b\xe2\x9c\x26\xb3\xc5\x0a\x29\xcc\x1c\x6e\x85\x8c\xfc\xb5\x75\x6b\xb7\xc2\xe0\xc3\x63\x9f\x29\xb0\x86\xa7\x0d\x2d\x6c\x28\x71\x0f\x29\x8c\x4b\xa3\x6b\x9f\xdd\xfe\xda\xbb\x45\x0d\xe3\x0a\xf3\x66\x79\xac\x30\xb3\xb5\xad\x2a\x63\x3c\xdc\x36\x20\x21\xd1\xb1\x0a\xba\xd7\xd1\xef\xc3\x89\x5f\x0f\x3a\x75\x08\x0b\x38\xfa\x1b\x73\xdf\xcd\x61\xa1\x1d\x8e\x1e\x69\x2d\xf9\xc7\x3f\xea\x35\xa0\x1d\xfb\xc5\xd2\x11\x78\xef\x31\xf4\xdb\x74\x60\x42\x1f\xfc\x7b\x82\x62\xb9\xa9\xef\x6c\x27\x18\xfb\x91\xd1\x5c\xe8\x7e\x89\xd5\x5c\x58\x58\xb0\xd5\xec\x32\xb9\x78\x55\xd6\x0b\xb2\x57\x78\x58\xfd\x27\xb0\xe8\xe2\x47\xcd\xc5\xf5\x8d\xaf\xfe\xa7\x65\xd7\xb6\xb5\x96\x80\xc7\x5a\x5d\x43\x9c\x29\x03\x2f\x4e\xc8\x5c\xb7\x7f\xfb\xb1\x3f\xfd\x07\x8b\x84\x3d\xe0\xc7\x5f\x97\xec\x28\x3a\x4d\xbf\x78\x8d\xfe\x7e\x26\xf6\xf9\xee\x23\x81\x3b\x7a\xd1\xfb\xe8\xff\x0c\xdf\x93\x0d\xe3\x50\xbf\xf1\x00\x10\x87\xc8\x36\xee\x65\x85\x1f\x04\xe6\x7f\xb8\xdd\x1c\x1f\x7d\xf8\x26\x76\xc5\xee\xbd\xba\x04\x23\xec\x5e\x3a\x15\xf6\xed\x47\x7f\x9d\x79\xc4\x03\xa9\xf5\x44\xfc\x5e\xef\x9d\xbd\xd7\xd7\xd3\x77\x21\xc5\xec\x4f\xdf\x02\x40\xec\x21\x3f\x67\xf0\xdb\x3d\x39\xd0\x63\xf7\xb8\xd0\x9f\x50\x5b\x5a\x38\x5b\x36\xa2\x0f\xe4\x1a\x0e\x82\x26\x9b\xc9\x1a\xbd\x68\x6d\xf4\x87\xfd\x4f\xc7\x9c\xb5\xfd\x32\x6d\x3c\x9c\x3b\xfd\x9d\xc2\xc2\xf4\x9d\x23\x2f\x26\x27\xc1\x45\x31\xf4\x76\x3b\x5c\x1c\x4d\x6f\x89\x9a\x3e\x1e\xbb\x60\xdf\xd1\x77\xcb\xb3\x4d\xbb\x9b\xfe\x0e\xe7\x26\xc5\xbf\x10\x3b\xe4\xeb\x2f\x9b\x76\x37\xad\x7a\x26\x61\x1f\xc2\x9f\xd9\x19\x43\x3d\x4f\x96\x82\x64\x91\xb7\xa3\x15\xba\xf0\x0c\x15\x67\x42\xbb\x19\xda\x21\xa7\xf9\x4d\x38\x72\x77\x2c\x78\xb4\xb6\xa0\x2d\x1d\x06\x36\x9f\x9a\xfc\xc8\x53\x1b\xc3\x5f\x68\xdb\x1a\x3a\xb2\x68\xc2\x8e\x55\xfd\x17\x1c\x2f\xa2\x77\xbc\x88\xe5\x5b\x1a\x4b\x5a\x57\xc5\x56\x12\xc5\xe7\xa6\x95\xb8\x0e\xc3\xbd\xf4\xd5\xd4\x4d\x0d\xe5\x33\xbc\x95\xd8\xd1\x59\xa9\x39\xc5\x35\x97\x9b\xe9\x60\x58\xe2\x3d\x8f\x37\x3c\x92\xb1\x59\xf0\x15\x25\x99\x55\x44\xec\x43\x7b\x5c\x0c\x18\x08\x06\xb1\xf9\x94\x10\x25\x66\xf4\x3f\xb4\x6d\xba\x4c\x76\x1c\xfd\xcf\xec\x71\x39\xed\xcc\x1f\x2a\x06\xba\x3c\xb8\xd5\x95\xe1\x89\x89\xda\x6a\xdf\x1a\xbd\x65\xe1\xc5\x91\x7f\xa9\xde\xb3\x70\x6b\xf4\x16\xfb\x96\xa8\xad\x4b\x2e\x14\xde\x58\xfa\xea\x92\x0f\x8e\x59\x57\x47\x4c\xb2\x05\x84\xfc\x29\xbc\xce\xde\xdc\xbf\x87\x69\x20\x16\xd4\x70\xb0\x01\xde\xa5\x29\xe6\x4f\xc3\xc1\x06\xef\xf7\x58\x10\xf3\xa7\xe1\x60\xc3\x9d\xc6\x1f\x0f\x1e\xa4\x2f\xff\x23\xeb\x18\xb3\x1e\x3c\x9d\xed\xe4\x69\xb2\x0d\xbd\xe9\x24\x21\xef\x3b\xc5\x2b\x15\xcc\xc5\x5c\x08\x1a\x1f\x67\xc0\xee\x03\x1e\xb3\x07\x0e\xbd\x72\xe9\x0f\xf4\x19\xfa\x7a\xfa\xda\xdd\xb6\xd3\x97\x9e\x7d\xd6\x05\xf7\x04\xef\x9f\xb7\x34\xf9\xf3\xc8\xcf\x4b\x83\x13\xe2\x86\xe7\x8d\x9f\x33\xb7\xba\xdf\x04\xb2\xed\xc3\xb6\x9f\xe8\xef\xbd\x67\xb0\xcb\xef\xbc\xb6\x66\xa5\xf7\x70\xc9\xf8\xf7\x2f\x36\xd1\xeb\x4b\xe3\x1d\x89\x11\x1b\x07\x54\xce\xc8\xac\x81\x8b\xd9\x3d\xd0\xdd\xd9\x4e\xcd\x27\xdb\x40\x20\x08\x03\x99\x0c\x1e\x5b\x6c\x88\x85\x32\x99\x19\x5a\x7c\x88\xdc\xe8\xc1\x94\xd9\x03\x85\x4a\x24\x71\x6c\xfd\x11\x6b\x7f\x0c\x6d\x93\x6e\xe8\x86\xbd\xe0\xca\x57\x9b\xd6\x7d\x30\xff\xdd\xfa\x3d\x75\x1b\x7e\x3e\x7d\xc1\x72\xb8\xd6\xb3\x31\xaf\xaa\x7a\xc4\x84\x79\xc5\xef\xb4\xbc\x5c\x9f\xb5\x70\xc9\xe8\xc9\xd9\x63\xa7\x8e\xb0\x9d\x3d\xba\x9b\x6c\xa3\x5f\xd8\xf5\xcf\x14\xef\x2a\x6c\x86\x77\x1f\x76\xe7\xc4\xc6\x15\x4b\xee\xf5\xdb\x3f\x28\xe5\x91\xf1\xd9\x53\x33\xc7\x3d\x3b\xbd\xe9\xc8\xe8\x17\x72\x4a\xf3\xb3\x4b\x87\xe6\x4f\x98\x95\xfd\xca\x71\xf6\x9e\x86\xdc\x4b\xb6\x81\x18\xe0\x00\xf1\x20\x09\xa4\x01\x0f\xc8\x12\x8d\xab\x70\x52\x11\xc6\x96\x11\x23\x12\x32\xcb\x81\x32\xbb\x3c\x76\x2b\xfa\x60\x86\x87\x32\x67\x70\xff\x12\x10\xdd\x1c\xb0\x32\x6a\x4e\xbf\x3d\x31\x9f\x7f\x7a\xd8\x7c\xee\xe8\xde\x5f\xcc\x8c\x5e\x9e\xd5\x14\xfd\xff\x63\xef\x5f\xe0\xa2\x2c\xd3\xc6\x71\xfc\xba\xee\xe7\x30\x80\x88\x0c\x30\x8c\x8a\x80\xc3\x08\x23\x22\x22\x8c\xc3\x88\x04\x78\x40\x44\x24\xd7\x88\x88\x88\x10\x11\x15\xf1\x80\x68\x44\x44\x34\x4b\x64\x13\x9a\x19\x92\xe6\x81\x8c\x25\xd7\x88\xd7\xc8\x35\x22\x33\xb3\x8c\x5c\x33\x73\x5d\x5f\xd7\x2f\xb1\xbe\xae\xaf\xb9\xbe\x6d\xe5\xb6\xad\xb5\x7e\x6d\x98\xb9\xe7\xff\x79\xee\x67\x66\x18\x4e\x6a\xbb\xef\xfb\xfd\xff\xbe\xbf\xcf\x0f\x7d\x78\x80\xb9\xef\xeb\xbe\xce\xd7\x75\x9f\x5f\xf9\xb0\x53\xf5\xc5\x27\x47\x46\x57\x7a\xa7\xa8\xe7\xf8\x07\x97\x26\xef\xbd\x7e\xc0\xa3\x22\x26\x93\x04\xdf\x53\x15\x32\x73\xae\x97\xef\xba\x19\xfb\xfa\xc9\x7c\x80\xdc\xe9\xd9\xd8\xae\xa4\x2f\x71\x59\x6b\x6b\x6b\xdd\xd2\xee\x23\xd6\x5d\x35\x47\x3f\xc7\x5f\xb4\xca\x3c\x1f\x41\x8f\x0a\x06\x36\x46\xa5\x61\x79\x87\x94\xa4\xc8\xdd\x4d\xb5\xde\x18\x6f\xd4\x18\x35\x46\xa6\x00\xa8\x35\x6a\x5d\xa1\xd4\x35\xa8\x3a\x22\x84\x8b\x0e\xb1\x4d\x7a\xee\x87\xdd\x8f\x34\x4e\x1a\x31\x42\xa1\xa1\x8d\x41\xb8\x61\xc2\xdb\xba\xed\xe3\x76\x50\xcb\x4b\x6a\x8f\xe2\x37\xf3\x37\xef\x7d\xaf\x3d\xff\xd8\x86\x55\xc5\xc5\xaf\x2f\xa1\x47\x9f\x7f\x9e\xec\x3f\x87\x4b\x3e\x5b\xfc\xf0\x83\x86\x5f\x9b\x0f\x1f\x36\xf7\x46\x9d\x7e\x62\xd9\x27\xed\x97\xde\xc3\xa0\x97\xd6\x6c\x78\x9d\xf6\xc8\x3e\x30\xc9\x7e\x9d\xef\x16\x4e\xb1\xd5\x6a\x12\x9b\xb4\x46\xbd\x1f\xe8\x9d\xfe\x43\x94\x7c\x07\xfb\xe6\xd2\x4a\x62\x48\x0a\xda\xe9\x11\xb8\x3d\xf8\x95\x22\x9c\xfb\xf9\x83\x2f\x66\x64\x4f\x29\x4b\xaf\xff\xd3\x3c\xfc\xd5\x58\xba\x30\x70\x04\x56\x86\xd2\xe6\xe7\xb7\x3d\xf5\xec\xd3\xbb\xbb\xff\x0b\x6f\x9a\x33\xb3\xeb\xd1\x07\x55\x91\xfa\x6d\xa1\x31\x1f\x1f\xaf\x9f\xf7\x90\xb9\xe3\x9d\xe9\x7b\x13\xd1\xd7\x22\xb7\x9f\x02\x20\x18\x84\x4e\x79\x5c\x86\xc9\xd1\x88\x7a\xc9\x6b\xa1\x16\xb5\x92\xfb\x48\x09\xdd\x67\xee\xac\x8f\x9d\x49\x62\x2f\xd9\x36\x62\x4d\x08\xbd\x88\xe3\x3f\xa5\x7f\x8d\xaa\xaf\xee\x6c\x20\x07\xcc\xa4\xce\x56\x93\x4a\x52\x6c\x35\x66\x5b\x36\x39\x50\x6c\x3b\x4c\x0e\x30\xb8\xb9\x00\x7c\xa7\xd0\xc9\x56\xdd\x84\x1b\x15\xba\x70\x7f\x29\x2f\xd4\x70\x46\xb5\xa0\x30\xaa\x05\x4e\xeb\xaf\xc8\xc5\xb4\xc8\x6f\x8c\x38\x67\x09\x5d\xab\xe5\x2e\x8e\xa7\x6b\xd3\x6e\x4e\xa7\x07\xa3\x7e\x98\x41\x0f\x16\xbc\x97\x7a\x1d\xc7\x7c\x76\xb2\x61\xf5\x29\xfc\x6d\x4b\x0b\xfd\x60\xd7\xea\x73\x27\x77\xae\xf9\x3d\x4d\xc1\xa4\x06\x26\xcf\x58\x1a\xa0\xa8\x12\x4e\xc3\x58\x98\xc2\xee\x00\x93\x42\x36\xef\xa7\x0a\x20\x7c\x14\x4a\x54\xc4\x4d\xf0\x33\x4c\x03\xb6\x5c\xc4\xdf\x3d\x9c\xeb\xb4\x0a\x1f\xe4\xfc\xfb\x32\x0d\x45\x6c\xe6\x9f\xd7\x7f\x86\xd3\xf6\x7f\x4e\x37\x7f\xf7\x8d\xf5\xe0\x45\xff\x8f\x51\xb3\x8b\xfe\xf4\x65\xce\x6f\x33\xb8\x3d\xad\xe1\xa7\x76\xed\x7a\x7d\xd9\x7b\x4f\x1a\x96\x8d\xf5\xf0\x10\x03\x16\xec\x98\x58\xb6\xb4\x2e\x23\xed\xfe\xd2\xb1\x42\x55\x78\xf4\x6e\x7a\xe5\x58\x2f\x7d\xe2\x3c\xdf\xdc\x6b\x6d\xc7\x99\xbf\xff\x5f\x60\x8f\x08\xfb\x29\x9a\x0b\x7f\xfb\xe8\x9e\xe7\xcb\x8e\xac\x8e\x1c\x17\x3b\x61\x3d\x6d\x23\x1f\xe6\x6e\x5b\x9f\x9e\x55\x22\xe7\x40\xf6\x03\x34\x80\x2f\x11\xce\x40\x18\x4c\x06\xd0\x62\x10\x4a\x06\xee\x27\x67\x9c\x0a\x3f\x66\xda\x3a\x67\x1f\x41\x87\x9c\x02\x03\xd4\x72\xc7\x45\xcc\xc6\xca\xa2\x2b\x41\xe3\x0e\xb4\xac\x36\x35\x7f\x92\xf3\x9b\x7f\x4b\xca\x98\x3d\xe7\xa1\x25\xaa\xb1\xb4\xbb\xb0\x9d\x54\x8d\x7d\xaa\x34\xef\xde\x87\x89\x1f\xfd\x12\xa3\x9f\x39\xbf\xea\x1b\x04\xf3\x9a\xa7\xe8\xe1\x1f\x69\x56\xfb\xbf\x5f\x52\xef\xd4\xec\xde\xb2\xec\x48\x03\x5d\x8b\x2a\x2b\x77\xa6\xc6\xdc\xfe\x8f\xc5\x8f\x9e\x64\x7d\xe9\x74\x00\xfe\xac\xd0\x09\x63\x98\xdf\x8e\xec\xb3\x6e\xcd\x78\x7f\xbd\x42\x2b\x4a\x76\x21\xf2\x51\xc8\x69\xfd\xd5\x52\x2e\xa4\x31\x6a\xd8\xb7\x88\x28\x4c\x1f\xbd\x4f\xb7\x4f\xbd\x2f\x09\xd3\x31\x33\x62\x87\xba\x7a\x44\xd0\x13\xa3\xb7\xcc\xa7\xb7\x7e\x5b\x51\x7c\xa8\x65\x7b\x61\xed\x81\x50\x5a\x3e\x1a\xdb\x34\x5e\x34\x4b\x8d\x8d\xa3\x7b\x9e\xe1\xa0\xac\x73\x2d\x6a\xe9\xa5\xb5\xeb\xd2\xca\xf6\x3c\x47\xb5\x1c\x6c\x5e\x30\xb3\xec\xfe\xa5\x6b\x9f\x67\x72\x6d\xb4\xe7\x0b\x8b\x44\x3f\x76\x42\x71\x04\xcb\x0b\x40\x4a\x5c\x98\x3d\xe8\x38\x0d\xe7\x83\x51\x28\xe5\x2c\xc4\x18\x10\xa8\xf6\xf7\x41\x82\x71\x46\x7f\x6d\xe3\x7b\xb8\xe8\x9c\xef\x46\xdf\x8e\xb6\xb4\xb9\x7b\x1e\xae\xc0\xb6\xa6\xaa\x93\xa5\xde\xa1\x1b\x35\x9f\xfe\xa1\xeb\xe9\x27\x6e\x35\x5c\x7b\x0a\x4d\xf5\x65\x05\x37\x88\x1f\xd8\xf1\x0d\x84\x51\xf3\xe7\x7b\x65\x34\x07\xc7\x71\xb6\x8b\x36\xc3\x24\xcd\x8b\x4d\x3a\x1c\xf3\xd5\xce\x93\x13\xf8\x8d\x41\xff\x4e\xdf\xb6\xed\x0f\xc7\x83\x8e\x3d\x48\x27\x99\x0e\x07\xc9\x7b\x85\xe4\x00\xaf\x41\x29\x67\xd0\xaa\xf5\x0a\xc9\xd7\x69\x3c\x51\xa3\xd3\x18\xf5\x11\x3a\xb1\x02\x3d\xb6\x04\x1d\xc9\xfb\xdb\x58\x0c\xc6\xc8\x8f\x53\x31\x28\xe8\x7b\x55\xe7\xd8\xe7\x93\xdf\x49\xa0\xe1\x94\x62\x3a\x9a\x55\xf4\x2f\x73\x4f\x04\x28\x16\xe2\xb5\xba\xd6\x3a\xa2\xb5\x5d\xaa\x6b\xad\xa3\x41\x78\x8d\x06\x91\x92\xd6\xba\xd7\x8f\x76\xb2\x7e\xef\x8f\xf6\xeb\xfc\x1a\xe1\xb4\x94\xbb\x71\x46\x7d\x32\x32\x86\x3b\xfa\x8b\x8e\x18\xaf\x57\x68\x59\x4a\xa1\xf1\xc1\xfe\x01\xcb\x7b\xdc\x7b\xf3\x3e\x58\x6f\xfb\x31\x98\x5c\x99\xfd\xd8\x8a\xa7\xde\x98\xde\x71\xfc\xd0\x85\xc8\xa5\xc1\x87\xee\x79\xbd\x0c\xaf\x04\xdb\x34\x93\x22\xea\x2b\x7e\xd3\xb1\xbb\xfb\xf4\x95\x68\xe2\x53\xa7\xbf\x77\x62\xdd\xec\xf2\x9c\xe2\xcc\xa6\xac\x0f\xf7\x2c\x5b\x54\x17\xbb\x30\xb2\x2e\xec\x81\x94\xc5\x6b\x33\x9b\x17\x7c\xf0\xeb\xb5\x59\x2c\x4f\x96\x64\xe2\x23\xfa\xc1\x68\x89\x0b\xfe\x8e\x54\x92\xe5\x90\x5c\xbc\xd4\x2b\x18\x85\xee\x02\x69\xfc\x10\x33\xce\xfb\x6e\xf4\x7d\xad\x72\x7e\x65\x8d\xe5\xf9\x57\xf2\x5e\x79\x20\xe4\x59\xcd\x27\x7f\xec\x7a\xe6\x89\x5b\xdb\xae\x99\x48\xd0\x3f\xf0\xd0\xcd\x51\x0b\x16\xf8\xce\xdc\x91\xec\xd1\xbb\x5c\x30\xee\xd5\x04\xe1\xb6\xdd\x21\xa8\xf9\xa6\xe9\xb3\x50\xde\x3c\xfa\x1c\x7d\x5d\xf6\x4d\x47\x1d\xf9\xc4\x58\xa6\x91\xe3\x25\x36\x4c\xc1\x28\x94\xfc\x48\x08\xaa\x65\x16\xa0\xf6\xa8\xba\x18\x53\xa6\xd3\xf4\x71\xb8\xdf\x73\xcb\xcb\xf3\xc7\x72\xe9\x41\xb4\x3a\x66\x26\x7f\x25\xf8\xdc\x04\x7a\x06\x63\x4e\x91\xa6\xa2\x9e\xba\x55\x6b\xeb\xea\x82\xd6\x67\xd6\xfd\xea\x75\x2f\x5b\x35\x20\xf8\xd9\xaf\xf3\xd9\x42\x27\x04\x03\xf8\xa7\x10\x45\x0a\xb2\xd1\x68\x41\x11\xae\x10\xb8\xb8\x78\x3f\xa3\x9e\x80\x26\x2c\x42\xe7\xef\x17\xdc\xa3\xe9\x0e\xea\x59\x74\x78\x36\x9e\x09\xa2\x71\x5a\x3c\x1b\x4c\x63\x4d\x1f\x7e\xbd\x3b\xba\x63\x16\x7d\x8a\x9e\xd3\xbf\x1a\xf7\x02\x59\xb4\x31\xed\x57\x73\x37\xa6\xe1\xa3\xf4\x74\xe3\xc6\xc6\x7d\x3b\x9e\xd9\x6e\x3b\xb4\x01\xec\x7f\xa0\xbb\xe9\xc6\x11\x9e\x64\x07\x20\xfd\x1d\xb7\x80\x3c\xa9\x00\xf0\x01\x40\xa3\xe0\xaf\xe6\xc2\x15\xe1\xfe\x8a\x11\xa8\x43\xfa\xbb\x04\x2c\x8f\x3c\x54\x85\x2d\x1e\xb4\xfa\xd0\x81\x32\x6b\x0d\xc6\x09\x9b\x9b\xdf\xc5\xe7\xb5\xb4\x2e\xa0\x75\x2a\xdd\x18\x8f\x2f\xd2\xf6\x1a\x1c\x2d\xd9\x6a\x97\xfd\x96\xd0\x26\x1c\x03\x0e\x82\x60\x22\xe8\x59\x36\x83\x9c\xdc\x0f\x74\xe4\x07\xec\x7a\x32\xc7\x2c\x78\xbf\x31\x00\xe7\xf8\x87\xd8\xc5\xcf\x6b\xee\x3d\x5a\x5a\x78\xb0\xe2\x17\x0f\xeb\x16\xa4\xae\xac\xdb\x38\x75\x7e\x68\xe8\x23\x53\x1e\x7f\x8e\xa4\x65\x37\x95\x3c\xf6\xdc\xd1\x5f\x55\x3c\xb3\xb9\x26\x31\x27\xa6\xfa\xc1\x55\x42\xa7\x25\x83\x0f\xad\x38\xb6\x3a\x6c\xa5\xe6\xad\x5f\xb6\x04\x8e\x58\x35\x2a\x70\x93\x2d\xaf\xea\xc4\xda\x86\x9a\x0f\xae\x3c\xfb\x4c\x73\xf6\x0b\xf7\xee\x6b\x97\xf4\xa4\xcc\x7e\x9d\x6b\x11\x4e\xc3\x38\x96\xd1\x1b\xe2\x8d\xce\xa1\x31\xa2\x50\xca\xab\xa9\x18\x56\x49\x28\x1a\xe3\x95\x12\x1e\xaa\xb2\x85\xeb\x77\xbd\xf0\xf8\xf3\xbf\x7b\x67\x51\x4e\x9b\xdf\x4a\x8f\xdd\x3b\x76\xb5\x2c\xba\x65\xa9\x9e\x95\x8c\xb4\x4a\x15\x81\xdf\xbc\xf8\x6a\xcb\xe6\x23\xf4\x0f\x0b\xe9\xf5\x15\x8f\x9f\x7f\xe3\x9d\x77\xdf\xfc\x2a\xe4\x42\x1d\xea\x8e\x3e\xb0\x42\xe2\x85\x11\x40\x91\x27\x74\xc2\x48\xb6\x42\x6f\x92\xcc\x0b\xa3\xd4\x05\xd4\xa2\xa8\xe0\xd8\x40\xc4\x90\x3d\x4c\x6d\x98\x68\xc4\xf8\xcf\x31\x4f\x99\x78\x60\x1f\x3d\x7d\x92\x36\x8f\x9e\xd6\xc6\x7d\x13\x82\x5f\x6a\x68\xc1\x83\x4d\xcb\x1e\xdd\x94\xb7\x67\x59\x55\xdd\xe6\xa4\xe4\xdc\x35\x35\x0f\xac\x15\x3a\x7b\x17\xe6\x63\x2c\x17\x6e\xc9\xe0\x4f\x76\xdc\xb4\x5e\x6d\x68\x20\x9a\xc7\x3e\x59\xbb\xa3\x66\xfd\xe7\xcb\xb7\x3e\xbb\xe0\xfe\x37\x9e\xda\xfb\x6f\xc0\x43\x3d\xcb\xeb\x4e\xc3\x28\x86\x4d\x9c\x6c\x2b\xce\xb0\xa4\x0d\x9b\x40\x8c\x01\x7e\xbc\x1c\x99\xc8\x04\x6d\x18\x4f\x50\xa9\x71\xf4\xb0\xc7\xa0\x3e\x8e\xa5\x7d\xf5\x9f\x62\xc1\x67\x27\x30\xef\xf7\xa7\xe8\xeb\x67\xce\xd2\x96\xae\x35\x07\x30\xea\xc0\x01\x9c\xf4\xe6\x01\x7a\xe1\xc0\x01\xfa\xbf\xde\xc4\x2a\x8c\x69\xdd\xf3\xc6\xb3\xad\x2f\xb6\xdd\xff\xd0\x0b\xe4\xa2\x54\xe1\x63\xda\xf2\xfb\xcf\xe9\xeb\x9f\x9d\xc5\xbc\xdf\x4a\x65\xdc\xea\xd8\x5e\xe2\x4c\x5b\x9e\x7f\xfa\x35\xfa\x21\x7e\xd4\x72\xdf\x7c\x49\x4e\x95\xe4\x9a\xd0\xcc\xe6\x9f\xc6\x48\x72\x92\x67\x05\x50\x29\x75\x9e\x95\x5a\xa5\x91\x65\xe7\x81\x2a\x65\x25\xf1\x38\x59\x83\xcf\x1e\xe9\xf8\xf0\x90\x89\x17\xbb\x8a\xdf\x17\x79\x21\x63\xf5\x6a\xdb\x1e\xb2\xcc\xb6\x87\x9c\xb3\x75\x93\x48\x5b\x0c\x1e\xa8\xb2\x5d\x24\xe1\xd3\xe6\xd2\x6c\xe6\xbb\xae\x03\x08\x5b\xd9\x3c\xf5\x9d\x67\xa9\xef\x30\x27\x7d\x17\x33\xf4\x04\x6a\xec\x97\xf8\x16\x3e\x5d\xee\xc3\x3b\x66\x1e\xfc\x54\x1a\xa5\xbc\xda\x50\xcd\xc4\x4e\x8c\x1a\xa5\x94\x4d\x29\x6a\x4c\x96\x5d\x3b\xff\xf1\xac\xf5\x93\xd8\xfd\x59\x1b\xdf\x5d\x34\xaf\xa8\x67\xe7\x2b\x37\xea\xbe\x26\xd9\x71\xaf\xe5\xbe\xf9\x04\xf1\xfb\x15\xd8\x77\xbc\x40\x6d\xbf\xa6\x4d\x86\xb4\x95\xb5\x91\x7b\x9e\x6c\x44\xe1\x07\x54\x19\x66\x57\xb0\x38\x99\x6a\xbf\x25\x34\x31\xbe\x8d\x00\x25\x5b\xef\x8b\x7a\x7f\xad\x4e\xab\xe0\x50\x8f\xfe\x7a\x5d\x84\x41\x01\x3a\x63\x88\x2c\x4a\x5d\x84\x3c\xac\xd5\x77\x7f\xa0\x5a\x1e\xdd\x4a\x45\x73\x5d\x41\xf5\xe8\x2f\xd7\xaa\xf8\xf4\xe6\xde\xa3\xea\x57\x03\x78\x0d\xb6\x2e\xe2\x75\xcb\xe3\x5e\x9b\x9a\xf6\xc2\x96\x27\xa6\xac\x9f\x18\x19\x96\x1f\x91\x90\x1a\x97\x72\xff\xbc\x5d\x2f\x90\x9b\xe4\x23\xdb\xcc\x4f\x3f\xb5\x79\x31\x4b\x8c\xfc\x68\x6c\xfc\xa2\xde\x51\x91\x55\x81\x63\x17\x87\x4c\x0e\x9b\x5d\xb9\xbc\x22\xc8\x6f\x8d\x32\x30\x2a\x7a\xfc\xd4\xe0\x88\x87\xe6\x2c\x5b\xcf\xe4\x70\x16\x80\x8b\xe1\x33\xc0\x93\xc9\x41\x4a\xbe\xfc\xf5\x5c\x6c\x28\x7e\x9c\x49\x73\x42\xb1\xad\xb0\xe3\xeb\x46\x5c\xdc\x88\x27\x7a\x3b\xe5\xfc\xb8\xd4\xfe\xbd\x70\x81\x8d\xb7\x7b\xb3\x5d\x74\x92\x57\x09\xd7\x4b\xbd\xb4\x51\x88\x8e\x64\x24\x0a\x8d\x7d\x03\x97\x8e\x40\xa4\x72\x0c\xd9\x95\xb2\xf1\xf9\x7b\x50\x6b\x7a\xbf\x61\xf5\x8c\xdc\x55\x64\x5e\xcd\xfa\x92\xa5\x07\x0a\x46\x2f\x2e\xd8\x30\x27\x61\x79\x41\xc2\xfa\xbd\x15\xb5\xe7\xe6\x65\xbe\xf7\x1a\xdb\x31\xcb\x5b\x8e\x5a\x5f\x22\xe4\x72\xe6\xdc\xde\x17\x36\xa6\x3f\x74\x6f\x5d\xf9\xc2\x79\x89\x33\x52\x97\xe6\x96\x17\xfc\xc6\xe8\xa1\x2c\x9e\xfb\xf4\x76\x19\xaf\x64\xfb\xf7\x62\x82\x70\x0a\x02\x61\x2c\x3b\x87\xdd\x18\xee\x18\xdf\x72\x62\x20\x4a\x7d\x6c\x4f\xd4\x63\xf8\x5d\x60\x99\x3c\x06\x3d\x5e\xce\x49\x4c\x58\x5c\x9c\x62\xda\xb3\xfa\x97\x25\x2f\x5d\x40\xf3\x58\xba\x98\xe1\x4e\x12\x87\xc5\x98\x64\xac\xfb\xb2\xee\x97\xb3\xf5\xc9\x8b\x0a\x57\x6c\x28\x58\xb2\xef\x89\x43\x35\xb6\x4e\x89\x8c\x89\xb7\xc1\x5d\x80\x02\xfb\x75\xe1\x9c\x83\xa7\x5a\x88\x91\xfa\x4d\xfd\xf9\xfa\xf3\x06\x3f\x0b\x18\x9a\x8f\xf4\xb1\x78\xed\x1d\x47\x43\xfb\xb3\xda\x1a\x7d\xb7\x63\xa3\x02\x3c\x60\xbf\x2e\x66\x08\xa7\x40\x0b\x3a\x48\x86\x0c\xc8\xe9\x1b\xb7\xbe\x1d\x83\xfd\x25\x41\xfc\x3c\xb2\x1e\x18\x96\xed\xd3\x64\xb9\x4c\xbe\x23\x99\xa4\x7c\x18\x39\xd8\x4e\x4a\x1c\x38\x79\xb7\x64\x83\x00\x8f\xd8\xaf\x8b\x59\x8e\x31\x8c\x78\x98\x0d\x0b\x6f\x3f\x5e\xff\x4f\xd0\xfb\xc8\x70\x43\xfc\x71\x32\xb9\xc9\x77\x26\x77\x88\xb9\x80\x9f\x4b\xa9\x44\x6b\x9e\xfd\xba\x70\x86\xe9\xa7\x17\x68\xd8\xfc\xad\xac\x9f\x6c\x08\xdf\xf3\x67\x6a\x67\x1e\xc3\xfe\x49\xb7\x71\xff\x09\x77\xa5\x9e\xce\xe9\x01\x5a\xf3\x33\x70\x47\xfb\x0d\xfb\x75\x2e\x85\x2f\x80\xd1\x00\x3a\xa3\xdb\x6a\x34\x85\xc1\x91\x72\xf0\xda\x30\x1f\x7d\x65\xf1\x9a\xb7\x57\x98\xd6\xcf\xaf\x4d\xf9\xe5\x9e\xae\x3f\xec\xa0\xbd\x2d\xdb\x35\xdb\xf5\x2f\xe3\x88\xbd\x35\xf5\x13\xc7\xed\x9c\xf5\xc5\xf1\x33\xf4\xcd\xf7\x00\x10\x5b\xa0\x58\x2c\x20\xa9\x30\xd2\xb1\x76\x49\x54\x68\x54\x9a\x40\xb5\x36\x02\x5b\xb6\x9a\xd2\x93\x13\xb8\x4b\x56\x6d\x42\x72\xba\x09\x67\x4f\x48\xdf\x51\x9b\x9a\x93\x5a\xbb\x83\xad\x65\xf2\xb5\x77\x91\xef\x79\x93\xab\x5e\xa0\x5a\x15\xa1\x53\x6a\x95\x22\xfa\xee\x48\x77\x14\xe5\x22\xd3\x4d\x5b\xb7\x9a\xd2\x93\x66\x58\xb5\xdc\xa5\x19\x30\xa8\x3d\x4d\x84\x4e\xaa\x28\x2a\xb4\xf1\x46\x6c\xe1\x2e\x49\x0d\x6d\x65\xcd\x62\xa4\xd4\x92\x0c\x68\x60\x7b\xe1\x86\x40\xb5\x52\xaf\x8c\x37\x4a\x15\x23\xd0\x57\xc6\x2a\x7d\x42\xfa\x39\x37\x7c\xb7\x6e\x85\x7e\xed\xa9\xfb\xe8\x73\x6b\xd4\x9d\x52\x42\xfb\x9a\xb7\x11\x37\x9a\x5d\x88\x0c\xa4\x5d\xed\xc0\x45\x62\xbe\x93\x03\x6e\x58\xb9\xd7\x73\x60\x47\xe8\x8c\x24\x27\x4f\xe4\x36\x64\x3c\x09\xfa\xda\xd3\x19\x4c\x29\xbf\x05\x41\xa3\xd2\x28\x87\x85\x8c\xff\x49\xc7\x0f\x82\x5e\xb2\x08\xeb\x87\x6f\x80\xc0\x06\xfb\x75\x3e\x43\xe8\x82\xb1\x30\xd1\x35\x5f\x66\x34\x10\x8d\xa4\x39\x52\xaa\xe8\xc7\x96\x38\xba\xa6\x0b\x8d\x52\xf0\xf6\xc1\x0d\x5b\xbe\xde\xf9\x7e\x3e\xe1\xe8\x37\xc9\x9b\xa6\x1b\x5f\x99\x75\xe1\xf2\xeb\xf4\x9b\x43\xed\x47\x8e\x2c\x79\x78\xf1\xaf\x1f\x0b\x1c\x63\x5a\xb8\xf2\x95\x42\xac\x38\x80\xf1\xaf\xec\x9e\x18\x86\xf5\x13\xc3\xf6\x8e\x8b\xa0\xdf\xd1\x7f\xd0\x7f\xd0\xc4\x6f\x4e\x1d\xa9\xa8\xdc\xd2\xbb\x3d\x7b\xdd\x13\x3f\xb0\xfe\xff\x29\x00\xce\x22\x74\x80\x00\xde\x52\x74\x46\xbd\xbf\x22\x5c\xc3\x45\x18\x44\x85\x31\x90\x9c\x3a\xba\x43\x6d\x3d\x4f\x5e\x58\xe8\x3f\x63\x69\x99\x30\xd7\xf2\xde\x9a\x16\x72\xf3\xe8\xde\x97\x3f\x94\xfb\x44\x37\x68\x80\xb0\xc8\xb1\xd6\x89\x4d\xe1\x6a\x94\x37\xf8\x82\xc3\x36\x5f\x1a\xa0\x68\xb9\x55\x20\xd2\x9f\x88\xdc\x77\xa2\x01\x42\x36\x9b\xcb\x07\x7f\x4f\x34\x68\x54\x52\x3f\x55\xa5\x39\x4a\xca\x6d\xcd\xfc\x1c\xeb\x07\x24\xd1\xd6\xce\xed\xed\x2d\xa1\x1b\xb9\x97\xb8\xa8\xf5\x2d\x36\x85\x75\x57\x33\x20\xd4\x10\x33\x3f\x86\x0b\x06\x0e\xc6\xcf\x54\x23\x3c\xf5\xd0\x78\xc4\x18\x5c\x8c\x26\x7c\x0b\xcf\xe2\xdf\xd0\x8e\x0a\x84\x98\x47\xca\xa3\x62\xa7\x4a\x99\x63\x0d\xd7\x44\xcc\x3b\x76\x30\xdc\xee\x30\x67\x8f\xb0\x9f\xcc\xc3\x56\x2e\x9f\xe1\xe4\x36\x69\xbe\xdf\xb5\x92\xe6\x90\x73\xc1\x0c\x42\x91\xfd\x86\x00\xe2\x5e\xf0\x60\x19\xaa\x3f\xcb\xe9\x8b\x50\xf7\x17\x02\x5b\x6d\x07\x37\xd2\xeb\xc4\xba\xc5\xb6\x42\x68\xff\x29\x9b\xf3\x62\x79\xc2\x0e\x6c\x10\x16\xf1\x3e\x7d\xf3\x8a\x2c\xf7\xea\xeb\xfe\xe8\xdc\x27\x73\x58\x46\x26\x38\xc7\x57\xb5\x61\xe2\x8e\x37\x4c\x0f\xbe\x9a\x3c\xe3\xb5\xfc\x8d\xcd\xaf\x3f\xf5\xe1\x93\x49\xaf\xe6\x3c\xb3\xcf\x5c\xb0\x70\xd6\x2a\x43\x5c\xe9\xbc\x8c\x42\x32\x4e\xbf\x76\x6e\x7a\xd1\xe2\x7b\x67\xad\x22\xe7\xeb\x0f\xad\x59\x57\x5c\xfe\xe6\xf3\x75\xef\xfd\x69\x79\xf9\x9b\xcf\xdf\xbf\xec\xa1\x25\x05\xf9\xab\x1e\x28\x78\xa4\xf4\xfe\x85\xa5\x0f\x49\x76\xb1\x13\x40\x2c\xe4\x4f\x82\x00\xa0\x51\xea\x95\x1a\x15\xee\x2c\xe0\x4b\xf9\x93\xbd\x2f\x17\x30\xbb\x51\xdb\x29\xdf\xc6\x7b\x80\x3f\x84\xcc\xf4\xf6\x07\xaf\x11\x30\x22\x40\x35\x02\x46\xb1\xf9\xf9\x38\xa5\x1f\x26\x24\x28\xf5\x4a\x7d\xec\x54\x41\xc9\xba\x2f\x21\xa8\x52\x6a\x95\x0c\x51\x95\x12\xd5\xeb\xcf\xd5\xd5\x9d\xaf\x5c\x7e\xa2\xb9\xe5\x23\x42\x60\xfb\xf7\x1b\x37\xde\x68\xa4\x40\xc8\xb1\x3f\x5f\xe9\xa2\x12\x9f\xb5\x34\x80\x1b\x23\x06\xb0\x1d\x2d\xcc\x59\xb3\x7e\x98\x5a\x15\xa1\x0d\x53\x29\x19\x33\xb4\xf3\x27\xe5\x15\xfc\xfa\xb5\x07\xa6\x18\x93\x0f\xb4\xb5\x66\xc5\xd2\x23\x81\x15\xeb\x84\x31\xef\xbe\xef\xd7\x18\x78\xcd\xf2\xd7\xf7\x3e\x52\x32\x5b\xc1\x6a\x3e\x96\xd7\x82\x9a\xdd\x40\xc0\x1c\xab\x63\x17\x0f\x1b\x6d\xd0\x31\x36\x72\xc3\xfc\x7d\xc3\xd2\x17\xd3\x1e\xbf\xef\xde\x9c\x29\xd3\x9f\x32\x14\xbf\x98\x56\x7d\xef\xbd\x0f\xc4\xc6\xd7\xc6\x15\x35\xa4\x3d\x7e\x5f\xea\xe2\x29\xc6\x5a\x3d\xfb\x6b\xea\x23\x71\xd3\x4c\x58\xbd\x77\x75\x68\x98\x46\x3d\xdb\xd8\xb4\x76\xbc\x46\xa3\x9e\x8b\x25\xaf\xac\x09\x09\x0b\x1e\x3b\xdb\xb8\x77\xed\x78\x4d\xf0\xd8\x59\x4c\x7f\x6a\x60\x1f\x3f\x46\xe0\xe5\x5d\x9b\x1a\x7f\x8d\x41\xe3\xaf\x56\xe8\x55\x1a\x4e\xa3\xd2\x70\x3a\x63\x0d\x26\x55\xd3\x74\xa4\x75\xf5\xa5\x56\xfa\x51\x0d\x7e\x60\xa3\xb5\xcf\xad\xc0\x23\x2f\xa1\x47\x03\x06\x27\x7e\xd9\x40\x6f\xbd\x44\xbf\x31\x5e\x66\xfa\x52\x0c\x3f\xf2\xe9\xfc\x22\xc7\x9a\x9b\x99\x33\x23\x3c\x80\x1f\xc1\x29\x78\x85\xf7\x48\x7e\x91\x80\x02\x2c\x46\x44\x0f\x01\xb9\x51\x9e\x31\x9e\x29\x9e\x65\x9e\x97\x3d\xff\xe6\x29\x7a\x42\xcc\x23\x6a\x7d\xcc\x23\xd2\x7f\x87\x9c\xf4\x4a\xbd\x3e\x76\xaa\xd1\xa0\x51\xa1\xe3\x29\xe6\xfe\x6c\x1d\x27\x3f\x3f\x36\x36\x62\xf1\x4b\x2f\x49\x8f\xd4\x57\x01\xe0\xc7\xf0\x17\x59\xbc\x05\x3d\x2b\x8d\x2a\x4f\x94\x8c\xc8\x5a\xcc\x35\xd9\xc6\x91\x3f\x37\x36\x92\xc6\x15\x78\x65\x2f\xdd\x46\x8f\xbe\x0a\x43\xd5\x09\x37\x78\x4a\xd5\x58\x1d\x72\xd5\x16\xcc\x35\x35\x36\x5e\x7f\x15\x53\x71\x75\x33\x0d\x5d\xc1\x7c\xdc\x5e\x00\xde\xc8\xd7\x02\x0f\x9e\x92\x86\x09\xc0\x8b\x20\x7a\x8d\x10\xc0\x83\x0c\xd4\x30\xbd\xd2\x13\x95\xe1\x1a\xa5\x27\xee\xc5\xcf\xf1\x8c\xf5\x5d\xf2\x13\xad\xa3\xcf\x90\x6a\x22\xda\x2c\xb6\x8d\x59\x44\xc4\x36\x9a\x03\x08\x0d\x28\xf2\xd1\x5c\xb0\xa4\xd3\xfe\x6c\x2d\x59\x03\xd7\x64\xbd\x85\x22\x51\xef\xa0\x26\x40\x22\xe9\xdc\x79\xb1\x8d\x9d\x15\xe3\xb6\x22\x46\xc7\xf6\x7a\x29\x44\x95\x92\x68\x5b\x6b\x52\x32\xf5\xe1\xa1\xde\xca\x08\x8d\x32\x6c\x84\x48\x03\xc4\xff\xf8\xe4\xe6\xcc\x98\x48\xbd\x97\x67\xa4\x4e\xa7\x5d\x79\x6b\x23\x20\xf2\x34\x80\x74\x88\x6d\x10\xe0\x58\x1b\xac\x0e\x54\xcb\x2a\xac\x57\xca\x1b\x6e\x78\xbd\x56\x3b\xc6\x2b\x24\x54\x39\x6e\x4c\x43\xcb\xc6\x84\x45\xb4\x56\x67\xf0\xe5\x23\xc3\xf5\x26\x45\xcd\x4f\xda\xae\x9b\xc9\x72\x7e\x70\x93\xec\x17\x3a\x38\x23\x70\xa0\x7c\x87\x13\x40\x5e\x52\xa7\x44\x46\x34\x67\xd0\xa8\xbc\x84\x63\x64\x3f\xdb\x6c\x85\xd8\x4d\x03\x48\x89\xe2\x94\xe4\xb7\x50\xa9\x57\x62\x77\x03\x0d\xf0\x7c\xe7\xe6\x02\x00\x24\x5b\x68\x00\x83\x23\x48\x9f\x49\x74\x93\x2d\x9c\xce\xb6\x8a\x06\x08\xda\x86\xde\xb5\x8e\xb6\x68\x00\x17\xca\xca\x8c\x9e\xe9\x09\x1c\xcf\x8b\x0a\xc7\x12\x3e\x89\xd3\x4a\x7d\x1c\x6b\x52\xa9\x55\x7a\x71\x91\xdb\xc8\xfe\x06\xcb\x25\x7e\x1b\x83\x2d\xe1\xa8\x38\x25\xc3\x96\xfc\x04\xd9\xb2\x8d\x6c\x27\xfb\x05\x6d\xef\xda\x06\x99\x06\x2e\x94\x7d\x2e\xc1\x15\x08\x11\x15\x80\x1c\xc4\xc4\xe8\xfb\xc1\xd5\x2b\xbd\xc8\xcb\x12\x5c\x7e\x9b\xe5\x92\x0b\x67\xc5\x29\xd7\x6a\x5c\x86\xf5\x36\xb2\x5d\x42\xdb\xf3\x9d\xde\xb5\x32\xe2\x0e\xbc\x59\xb9\x71\x33\x47\x80\x40\x44\xd1\xc3\x13\x50\x94\x5a\x70\x36\xd1\xd7\x86\x96\xb5\x22\x37\x73\x73\x01\xbf\x4d\xae\xcf\x78\xa3\x90\xb4\x8c\xf3\x04\x41\x02\x20\xca\xa4\xc7\x39\x69\x77\x32\x9c\xd1\x2f\x1c\xb3\xad\x92\x40\x34\xf4\xae\x95\x58\xe0\x94\x13\xc3\x21\x64\xa6\xb7\x82\x51\xe9\xe1\x09\x82\x4c\xa6\xbe\x3f\x0c\x46\x0b\xa3\x75\x3b\x43\x43\xe2\x12\x38\xf1\x50\x9c\x82\x11\x30\x71\xa6\x52\x31\x12\x04\x4f\x4f\xe2\xe5\xe5\x3d\xd2\x03\x04\xf4\x92\xa9\xd1\xc7\x39\xe8\x19\x00\x4d\xe3\xa0\x4b\x62\xce\x36\x27\x50\x19\x39\x62\xbf\x89\x37\x84\x0e\xee\x3a\xf3\x11\xf1\x33\x83\x39\x85\xc2\x13\x78\xde\x83\x5f\x2c\x20\x27\xb4\x02\x7e\x0a\x28\xc2\x41\xc4\x51\x88\x52\x4c\x7c\x44\xbf\xf8\x91\xf2\x98\xc5\x8f\xc8\x6a\xa6\x74\xa9\x1a\xca\xea\x66\x99\x2d\x1c\xc3\x1b\x0d\x0d\x58\xb2\x6d\x9b\x9c\xeb\xf4\x48\x36\xc3\xf4\xce\x21\x29\xe9\x1f\xf6\x34\x7c\xe1\xd0\xbf\xfe\x3a\x78\x5d\xea\xcb\x33\x1d\x54\xf5\xe9\xa1\x2c\x54\xe1\x8b\x6d\xdd\x0d\xd6\x30\x49\x97\x7b\x1c\x32\x71\x96\x65\x8b\xbc\xb0\x87\xbb\x48\x43\x1b\xbe\x70\x68\xad\x44\xa4\xa3\x7d\x06\x57\x90\x22\xb2\x5c\x5a\xe6\x89\x54\xde\xda\xf9\x05\x59\x4f\x43\x19\x70\xcb\x11\xbe\x4c\x86\xef\xd0\x75\x09\x97\x19\x33\x43\x79\x00\x05\xf1\xf0\xf0\x1a\x21\x79\x4b\x0e\x3d\x5a\x79\xfc\x94\x47\x91\x3f\x28\xe0\x28\xc9\x87\x3a\x79\xc2\x98\xe2\xd0\x27\x07\x57\x0c\xf2\xea\x52\x2f\xf2\xb2\x6d\x25\x17\xb9\x0d\x6f\x34\x74\x6f\xb3\x4c\xe4\xfe\xe4\x6c\xe3\x3c\xa3\x21\x6c\xa6\x0f\x28\x3c\x38\xde\x83\xf7\x1a\xc1\x7b\x88\x0e\xcd\xd2\xbb\x1c\x98\xcb\xb2\xb4\xcc\xba\x2e\x35\x7c\xd1\xe0\xb0\x2f\x97\x0c\x19\x2c\x07\x8d\x72\x59\x74\xb4\xfc\x68\x03\x0d\xe6\x2e\x35\xe0\x8d\x86\xde\x06\xee\x4f\x58\xb2\xcd\x32\x51\x48\x63\xfc\x96\xe4\xae\x38\x25\xf3\x50\xef\xe0\xb8\xc3\x82\xc8\x76\xbc\x21\x74\x5b\xb5\xdb\xba\x65\xdf\xd1\xe3\xd0\x5f\xcf\x3e\x09\x6a\x54\x4c\x86\x78\x45\xb6\x64\xa7\x9e\x12\xec\x71\xc0\x75\xf0\x9b\x95\x74\x96\xe7\x32\x6c\x2f\x34\xe0\x15\x09\xb8\xe5\x48\x03\x96\xf0\x65\x56\x2d\xb3\x31\xbc\xc1\x6c\xd4\x13\xa6\xcf\x0c\xe1\x01\x3c\x45\x42\xbc\x46\x0c\x64\xb4\x14\xac\x14\x10\xc3\x02\x13\x63\xf9\x50\xdc\xd6\xcb\xdc\x26\x2f\xcb\xdc\xe6\x2e\x59\x22\x5d\xbe\x92\xe9\xa1\xa7\xcc\x21\x99\x0a\x2f\xbc\x2a\x73\x53\xe6\xa5\xe4\x59\x1c\x36\xc1\xca\xba\xf8\xa9\x67\xfc\xd4\x2b\xbd\xb8\xcc\x06\xab\x16\xaf\x4a\xfc\x14\xd2\x2c\x91\x58\xb2\x8d\xbb\xd4\xdb\xe0\xee\x8f\x46\xb8\xf3\xd3\xe5\x93\x9c\x7e\x89\xf1\xd4\x1a\xe6\xd4\x4b\x66\x17\x23\xdc\xb9\xaa\x51\x3a\xf8\x2a\x69\xa5\x6c\x1f\x4e\x5f\xc6\xb9\xd5\xf1\x64\x67\x9d\xb9\xea\x70\x2e\x89\x48\xea\xdc\x20\x55\x67\x95\x99\x46\x0b\x69\x2e\x3e\x3b\x7c\xe1\x08\x48\x9e\xa9\x91\xf9\x2c\xb9\x10\x59\xb1\x07\xb0\xdb\x4b\x62\xb5\xbb\xbd\xcb\xcc\x1e\xc8\x6d\xad\x8b\xdf\x4e\x86\xdf\x5c\xc0\xfd\xc9\xa9\x93\xcc\xe7\xb9\x78\xc8\xc6\x5f\x19\xcf\x1b\x70\x65\x83\xcb\xc9\xf6\xae\x95\x7d\x00\xe7\xaa\x23\xc8\xa7\x69\xf4\x69\xb2\x5e\xe9\xcf\x24\x2b\x69\x33\x13\x59\x9f\x3e\x4b\xfc\xb7\x1c\x91\x21\x38\x6c\x81\xd9\xbb\xd4\xee\xec\x99\xda\x11\x1c\x37\xd2\x03\x24\xaf\xed\x3d\x92\x97\x09\x15\x5b\x3d\xf0\x53\x0f\x14\x3d\x0e\x7a\xe2\x28\x4f\xf4\xec\x67\xc1\x71\x2e\x6f\xdc\xe7\xdb\x1c\x58\xa8\x64\xcf\x6e\x5b\x29\xbb\x38\x6b\x18\x6b\xdf\x3d\x46\x30\xdf\xcc\x8d\x04\x4f\x2f\x41\xf4\x12\xbd\x47\x8a\x5e\xbc\x87\x6c\xce\xfd\xec\xd9\x1d\xae\x56\x8e\x18\x92\xe3\x6a\x70\xc6\x0c\x47\xdc\xe0\x5c\xb4\x08\xb2\xbc\x5d\xfc\x50\xc9\x7e\x4c\xe6\x87\x70\xcc\xf6\x82\x24\xf5\x3e\x96\xf4\xb9\x32\xa7\x7f\x77\xe8\xd9\xcc\x99\x61\x8a\x11\x23\x46\x82\x87\x87\x40\x88\xf7\x48\xa7\x77\x17\x1c\xee\xdd\x63\xb1\x27\x7a\x72\x2e\x0b\xeb\x33\xb1\xb8\x01\x9e\x5e\x8e\x51\x92\xb7\x67\x51\xc5\xe1\xf0\xa5\xde\x78\xff\x78\xc7\xf8\x31\x62\x24\x08\xc4\x53\x24\xa2\xf7\x48\x4f\x01\x50\xc1\x49\x39\x83\x5e\x3f\x98\x1f\x2e\x1b\x90\xad\x52\x72\x2d\x0e\xbb\x94\x7d\x0b\xe7\x46\x8b\x93\x1f\x0e\x6c\xf4\x7d\x18\x39\xea\xba\x70\xea\x6d\x90\xb5\xdf\x3d\x86\xfa\x43\xce\xcc\xe8\x11\xa3\x46\xa9\x24\x1b\x18\xa9\x54\x8a\xc4\xcf\x2f\x40\xe5\x0b\x23\x99\x7e\x78\xf3\x4e\x53\xf0\x74\xd8\x82\x9f\xd3\x16\x18\x4b\xf4\x92\x9e\xb8\x62\xad\x5e\xf6\x40\x2e\xfe\x38\xec\xc2\x69\xff\x7d\xf6\xe1\x74\x03\x4e\x3b\x71\xb8\x02\x29\x1a\xf4\xc7\x0d\xdc\x79\xe1\xd2\x11\x07\x5d\x4e\x45\x71\x31\xa6\x4f\x61\x78\x17\x0c\x81\x8d\xdd\xab\x07\x5a\x50\x9f\xa7\xe8\xb3\x24\xa7\xbf\x18\x68\x50\xfd\x3c\x87\xd4\x2f\x01\xf2\x9d\xd0\x26\xe7\x8f\x63\x50\xa3\x14\xda\xc8\x77\xfc\xc5\xde\x70\xf9\x33\x1a\x20\xfd\xde\xf7\x19\x0d\xe0\xff\xd8\x1b\xd1\xf7\x99\x7b\x3d\x67\xda\x29\x7f\x46\x2e\xf4\x7d\x46\x2e\xf4\x7d\x26\xfd\xec\xac\x87\x4a\xe9\x33\xd7\xa7\x93\x60\x39\xad\x14\xda\x14\xe1\x8e\x7e\xcd\x28\x76\xee\x49\x10\x84\xb2\x71\xdc\x28\x76\x7e\xb2\x11\x12\x21\x05\xe6\xc0\x3c\x58\x00\xbf\x80\xfb\xe1\x41\x78\x18\x16\xc3\x52\x58\x01\xab\xa0\x0c\x36\x40\x25\x54\x83\x09\xea\xc0\x0c\x9b\x61\x2b\x34\xc2\xcb\xb0\x07\x5e\x85\xd7\xe0\x75\x00\xb5\x5e\xa5\x55\x1a\xf4\x2a\x6e\xc0\xe3\x2f\xbd\x87\xf8\xcc\xff\xff\x4f\xe5\x97\xaf\xec\xfb\x1a\xee\xe7\x12\xb7\xaf\x95\xcb\xfb\xbe\x86\xfb\xb9\x64\x29\xd6\x2d\x5d\x8a\x1b\x97\x2c\xc1\x67\x0a\x0b\xb1\xb6\xa8\x08\xeb\x0a\x0b\x7f\x32\xe4\xe7\xd3\x4b\x85\x1c\x5f\x50\x80\x75\x8e\xc7\x54\x54\xf4\xd3\xce\xff\xe3\xa5\x21\x1b\xe0\x7f\x50\xf6\xff\x06\x6f\xc1\xdb\xf0\x2e\xbc\x0f\x1f\x42\x17\x9c\x84\xd3\x70\x16\xce\x43\x37\x5c\x84\xcb\x70\x15\xbe\x82\x6f\xe1\x6f\xf0\x03\xfc\x6f\xe8\x05\x3b\x72\xa8\xc0\x11\x38\x0a\xfd\x51\x8d\x41\x18\x8a\x5a\xd4\x61\x14\xc6\xa0\x1e\x8d\x98\x88\x29\x38\x07\xe7\xe1\x02\xfc\x05\x80\x6a\x18\xb9\x2a\x87\x91\xab\xf2\xff\x2b\x7f\xdb\xf2\xee\xaa\xeb\xa6\xf5\x3f\xe3\xaf\x25\x43\x7e\xfd\x93\xc0\xdc\xfe\x2a\xfe\x3f\xc5\x4c\xfe\x6f\x2d\x0d\x30\x87\xc5\x8b\x0b\x8a\x70\x98\x0f\xf7\xc2\x7d\xf0\x00\x3c\x04\x8f\xc0\x12\x58\x06\x2b\x61\x0d\x94\x43\x05\x54\x41\x0d\xd4\xc2\x46\xa8\x87\x2d\xd0\x00\xdb\x61\x17\xbc\x02\xbf\x82\x5f\xc3\x1b\xf0\x26\xfc\x06\xde\x81\xf7\xe0\x03\x38\x0e\x27\xe0\x14\x9c\x81\x73\x70\x01\x7a\xe0\x12\x5c\x81\x6b\xf0\x35\xfc\x15\xfe\x0e\xff\x80\x9f\xc0\x86\x88\x02\x7a\xe2\x48\x54\xa2\x0a\xc7\x60\x30\x6a\x30\x1c\x23\x31\x1a\x63\xd1\x80\x09\x98\x84\xb3\x70\x2e\xce\xc7\x7b\xf1\x3e\x00\x95\x52\x6f\xd0\x0e\x78\xf4\xaa\xe1\x1e\xad\x4a\xaf\x1c\xe2\x91\xfa\x9c\x49\x28\x55\x56\xe9\x0d\xdc\x00\x80\xfe\x43\xfd\xed\xff\xc5\x65\x4b\x9d\x5f\xab\xd8\xbf\x35\xd2\xb7\xd2\x55\xee\x5f\x96\xa8\xfe\xbf\x97\xf6\x7d\xfd\xdc\xbf\xaf\x71\xff\x1a\xba\x48\xbf\xca\xa5\x43\x7f\x95\xe0\xf8\xa5\x18\xb6\x44\xfa\xae\x29\x42\x4d\xa1\xfb\x57\x57\x11\xbd\x5c\x40\x2f\xca\xff\x25\x65\x5f\x8a\x9a\xa5\x45\xf9\xb4\xb6\xb0\x90\xec\x2b\xc0\x70\xf6\x5f\x53\xf4\x53\xfc\xd2\xa5\xee\x50\x2c\x39\xff\x57\x15\x91\xf7\xa9\xc3\x4d\x3e\x8f\xbf\x20\xe5\x64\x46\xa5\x46\x59\xcd\x5d\xbe\xc9\x5d\xb6\x6a\xd8\x78\xac\x08\xc0\x9f\xe5\x1d\xe3\x3c\x7a\xa5\x46\x19\xae\x51\x6a\x44\xfe\x54\x6f\x1d\x1f\xdb\x7b\x96\x3f\xd5\x6b\xcc\xe4\x63\x01\x61\x0d\x9a\x48\x09\x57\xcd\xf6\x43\x2a\x35\xca\x35\xd8\x8b\x26\xb4\x52\x5e\x82\xd1\xf7\x99\x63\xe6\x47\x82\xb1\x06\x7b\xe9\x22\x5c\x46\xf7\xc8\xe5\x32\x51\xc6\x05\xa0\xd6\x03\xc8\xd7\x12\x1c\x83\x52\xa3\xf4\x80\x5a\x52\x62\xdb\x29\xcf\x03\xee\x05\x10\x33\xf9\x76\x20\xa0\x7c\x07\x08\xc7\x06\xeb\xd8\x50\x5d\x42\xec\x54\x8d\x27\xe2\x5e\x92\x4b\x72\xf8\xf6\xde\x2c\x40\x6c\xb0\x5f\x13\xf3\xf8\x03\x40\x00\x04\x25\x62\x03\x7f\x2a\x88\x3f\x69\xdb\x2b\xc3\xb1\x5f\x13\x33\xf9\x46\xe9\x33\xd4\x20\xee\xe5\xdb\x6d\x6d\x7c\x63\x6f\x16\xf4\xaf\xe7\x89\x4a\xa9\x1e\xc9\x20\x45\xbd\x09\x6c\x2d\x21\x00\xbf\x5c\xe8\x62\xfd\x36\xf0\x47\xbd\x27\x6a\x3d\xb9\x46\xec\xca\xc4\x4f\xe8\x3d\x99\xf4\x47\xd4\xa3\x9e\x9e\x21\x97\xc9\x9f\x6d\x21\xb6\x50\x72\xc5\x66\x25\x3c\x21\xf2\x7e\x9d\x56\x68\xe1\xa3\xf9\x48\xb6\xbe\x2a\x64\xa6\xb7\x2f\x78\x8c\x86\xd1\xe3\x35\x01\xde\xe3\x78\xd6\x71\x72\x1b\xd7\xf6\x77\x4e\x9c\xb0\x59\xfa\x29\x68\x0c\x08\x41\x79\xf9\x9b\x3c\xa1\xd7\x5a\x79\xee\xf1\xea\x73\x55\x55\xe7\xaa\x1f\x3f\x57\x99\x53\xd8\x5a\xb4\xb4\xad\xa8\xf0\xc0\xd2\xc2\xb6\x42\x52\x5c\x75\xbe\xaa\xea\x7c\xd5\xe3\xe7\xaa\xaa\x7e\x57\x5d\xd4\x56\x58\xd8\x26\x7d\x58\xc4\xd6\x91\xfb\x42\x11\xe4\xf0\x05\x7c\x16\xdb\xbb\xaf\x86\x50\xd0\x41\x0c\x18\x21\x05\xe6\xc1\x2f\xe0\x41\x58\x0c\x2b\xa0\x0c\x2a\xc1\x04\xe0\x3f\x4d\x1f\xa7\x0a\xd0\x86\xa9\x1d\x6f\xa5\xe3\xed\xff\x3f\xfc\xbb\xb3\xbd\xa2\xe9\x06\xc3\x74\xad\x31\x3e\xde\x68\x8c\x9f\x96\x50\x2c\xbd\xa4\xe7\x25\x83\xd1\x68\x90\x9e\x76\x43\x7c\xbc\x41\x7a\x0e\x24\x4c\x9b\x96\x20\x3d\x3b\x8c\x7a\xbd\x51\x7a\x8a\xa4\xcf\xa5\x7f\xe1\xd2\x6f\x24\xdb\x60\x30\x54\x19\x8d\x06\x6c\x30\x18\x8c\x74\xee\xf4\xe9\x06\x72\x78\x86\x31\xde\xb6\xd0\xa8\x37\x72\x35\x46\xa3\xc1\xfa\x59\x7c\xbc\x91\x3b\x69\x30\x4c\xb7\x9e\x32\x1a\xf5\xec\x6f\xb6\x7b\xa5\x72\xef\x1b\x8d\xf1\x34\xcd\x59\xb7\xd2\x60\x60\xe7\x60\x1c\x82\x7a\x5e\xcb\x59\xd8\xe9\x03\x2e\x39\x81\x36\x0c\x0e\x95\x75\xaf\x5f\xd3\xb3\x81\xd2\x77\x3b\x29\x25\xb3\x57\x5f\xa8\xac\xe8\x29\x7d\x97\x52\x24\x4c\xfe\x91\x00\xfc\x01\xbe\x0e\x38\x79\xe6\x8c\x07\xce\x1b\xbc\x03\x54\x1e\xe0\x8b\x10\x73\x26\xe6\x4c\xbf\x79\x0d\x8d\x12\x07\xc8\x3c\x92\xaf\xb3\xf2\x95\xa7\x1f\xab\x38\x53\x59\x79\xba\xf2\xb1\x33\x15\x7c\x5d\x6f\x0d\x99\x5d\x79\xba\xb2\xf2\x4c\xc5\xa3\x67\x2a\x2b\xcf\x00\xd7\xaf\x0d\x2d\xe8\x66\xfa\x05\x00\x37\x6e\x9c\x37\x0f\xfc\x84\x70\x8f\xf1\xbe\xa3\x61\x3c\x6b\xeb\xd2\xef\x7c\x7f\xa7\xf4\x43\xf5\x6d\x9a\x53\x0f\x50\xc1\x41\xcd\x2f\x2c\x6c\x2b\x5a\xd2\x56\x54\xd4\xb6\xa4\xa8\xad\x70\x10\x2e\x8f\x16\x4a\x1f\x15\x2e\x95\x14\x90\xcd\xc5\x6d\x24\x45\x5c\x05\x78\xcb\xfb\x5a\xd9\xcc\xc8\x80\x05\x19\xda\x30\x71\x43\x63\xf1\xca\xb4\xf9\xdb\x97\x2e\x6f\x58\xb0\x74\xfe\xc2\xc5\x2b\xd2\xe6\xae\x20\x35\xcb\xb7\x65\xa4\x2f\x5f\xb5\xe5\xc5\x92\xf4\xe2\x92\xd4\xb4\xe5\xcb\x01\x40\xc0\x83\xf6\x6b\x62\x15\x7f\x80\xed\x93\x9d\x20\xaf\xa1\xc7\x69\xa0\x19\x0f\xb2\x24\x8c\x01\xa0\x8f\x03\xb6\x82\x5e\x21\xba\x9f\xab\xe6\x6f\x0c\xd4\xc7\x19\xd5\xa2\x36\x0c\xdd\x8f\x41\x3b\x88\x45\x48\x90\xc3\x22\xfa\xb2\xb5\x97\xee\xca\x45\x7d\xf7\x1f\x31\x96\x9e\xfd\x63\xcf\xcb\xbb\xcf\x47\x6b\x34\xd1\xd2\x13\x9c\x98\xd9\xb8\x2d\x33\xa9\xf0\xfd\xc3\x98\x1d\xa3\xd1\x44\x45\x69\x34\x31\x24\xdd\x82\xa5\x74\x87\x85\xd2\x3d\xb8\xc2\xda\x4d\x3f\xc7\x69\xdd\x3d\xa8\xdf\xbd\x2b\x6f\x7c\x74\xf4\xf8\xd0\x98\x18\x7a\x51\x5b\x5f\xaf\x3d\x82\xd4\xf1\x3b\xf0\x78\xce\x7e\x4d\xdc\xcd\x70\x57\xb3\x75\x2b\xfd\x30\x47\x37\x76\xf8\x4b\xb8\xea\x44\x6d\x98\xce\xfd\xaf\x78\x8e\x21\x4b\x70\x29\x7d\xd9\x4a\x69\x13\x46\x45\x6b\x42\xa6\x4e\x0d\xd1\x44\x07\x17\x1d\x7e\xaf\x28\x79\xc1\xb6\xc6\x4c\xac\x8e\xd1\x84\x4c\x99\x12\x32\x00\x41\xac\x0e\x8d\x89\x09\x1d\x1f\x1d\x4d\x9b\x8e\x1c\xd1\xd6\xd7\xa3\xc6\xf1\x3b\x1b\xdf\x4d\xb3\x6f\x10\x7d\xf8\x44\x88\x04\x49\xcd\x0d\xfa\x78\xa3\xce\xa8\x8e\x37\x1a\xf4\xaa\x10\x54\x1b\xd5\x8a\x40\xa9\xff\x2c\x2a\xd4\x0a\x9d\x0f\x2a\x54\x5a\x43\x84\x4e\xa1\x33\x46\xe8\x64\x01\xea\x64\xdc\xd2\xba\xbd\x17\x75\x44\x1e\x2d\x5b\x37\x7b\xd6\xb2\xc4\x23\xd1\x87\x73\xc4\xee\x6e\xdf\xcc\xc3\xb1\x9d\x71\x0f\xe6\xce\xae\x2a\x3e\x1a\xd5\xb9\xd0\x37\xa5\xab\x7e\xf3\x6f\xb9\x13\xf5\x9b\x8f\xe3\xe1\xe4\xda\x82\xc3\xb1\x9d\x0b\xbd\x7b\x7a\x44\x5d\x74\x67\xf4\xe1\xf2\x47\x93\x6b\x0a\x8f\x46\x75\x86\x4f\x1a\xd9\xd3\xe3\x9b\xd1\x11\x7d\xb8\xb8\x26\xd4\x7c\xe2\xd3\x67\xcc\x27\x4f\xb2\x31\x68\x58\xc4\xeb\xf8\x5a\x50\xb3\x73\xb7\x0d\x1a\x83\x73\x73\x11\x5b\xe4\xe3\x18\x97\xe1\xd8\x6a\x5d\x27\xbb\x7a\x90\x94\xd7\xb7\x97\x57\x66\xe7\x6c\x2b\x41\xb0\x43\x66\x5b\x75\x76\x4e\x62\x72\x65\x6e\x6e\x25\xe6\xa4\xed\xf7\x6b\x29\xa9\xd9\x9f\x93\x5d\xb5\xba\xc5\x67\x7f\x1a\xb5\xa0\x48\xbc\x72\xaa\x92\x93\xb2\x73\x2a\x1f\x07\x82\x59\x60\xe1\xdb\xf9\x5a\x98\x0c\xd3\x9d\x33\x7a\x46\xb6\x36\xd2\x18\xaf\x57\xb3\x56\xf4\x71\x2a\x85\xa8\x0a\x08\xc5\x80\x51\x18\x36\x05\x75\x8a\x21\xf4\x1a\xb3\x5a\xab\xe7\x66\xdf\x68\x8c\xf2\x14\x15\x1e\x9a\x39\xf7\xe4\x46\x86\x8d\xf2\xe1\x7d\xbd\x79\xde\x47\x15\xae\xf5\xf9\x36\xfb\x37\xeb\x2b\x0e\x2c\xac\xc9\xcd\xad\xae\xc9\xc9\xab\x26\xea\xc7\xdb\xa2\x6e\x44\x45\xf1\x3e\x9e\x1e\x3c\xaf\x1c\xe9\xed\x13\x94\xb8\xf4\xde\x69\xe3\x3d\x45\x71\x76\x5e\xec\x77\x59\xab\x6b\xda\xf7\xd5\x2c\x7e\x4c\x2a\x5e\x25\xf9\xa3\x44\x00\x9e\xe7\xcf\xca\xa7\xd2\xc6\x1b\x93\xd1\x18\x82\xea\x10\x54\xb3\x09\xcc\x10\x12\x8a\x1a\x63\x5c\x32\x26\xa1\x84\x55\x62\xee\xb2\xfa\x8d\x41\xa3\x97\x6c\xdf\x92\x46\x6a\x73\x9b\x8a\xf9\x45\x2d\x1b\x45\xeb\x37\x62\xf5\x81\xdc\xbc\xb6\x87\x6b\xf1\xbb\x3c\x73\x56\xe5\x91\x9a\xc2\xd6\xe7\x4d\x75\xf3\x96\x98\x3e\x6c\xde\x5f\xe0\x11\x1e\x5e\x78\x60\x9b\xcf\x87\x26\x47\x5b\x02\xcf\x9f\x94\x4f\x61\x8d\x37\xc6\xa9\x5d\x0b\x45\x55\x01\x8a\x78\x63\x9f\x5d\x4f\x41\x5d\x08\x27\x35\x9d\xcc\x19\xe4\xc5\x0b\x89\x2f\xe5\x27\x2d\x0b\xf7\x1b\xd1\x52\xfe\x68\xf3\xdc\x6c\xdf\x40\xdd\xca\x39\x19\x4d\x8f\x4e\x7f\x6c\x71\x12\x1f\x5b\x66\x5a\xe7\x69\xed\xf4\x30\x57\x16\xc4\x73\x09\x07\xf3\x36\xb4\x90\xf0\x0d\xaf\x10\xfd\x6c\xdd\x04\x5d\xd5\x8e\xe6\x55\x39\x45\x3a\xde\x63\xe1\x82\x8a\x8a\x7d\x71\xf7\xad\xac\xd9\xfd\x78\x7c\x80\x56\x3b\x76\x7a\xe5\xf6\xcc\x98\xaa\x8a\x57\x58\xce\xb0\xdc\xfe\x35\x9f\xc7\x57\xb9\xbc\x4b\xdf\xda\x09\x85\x0f\x2a\xa6\x60\x0c\x4e\xc1\xe5\xcf\x17\xe7\x6c\xd5\x69\xb6\xe6\x2e\xd9\x9a\x5b\xb6\xa5\x56\x1b\x98\x77\xf0\xe1\x05\xf1\x5c\xdd\xaa\xfa\x0d\x95\x95\x15\xe6\xa5\x39\xc7\xea\xdf\xbe\x50\x9b\xf3\xee\xb7\xd5\xcb\x6a\xd9\x99\x2f\xf6\xaf\xb8\xf3\xfc\x49\xb6\xde\x23\x1e\x8c\x81\xa0\x16\x41\x11\x01\xb3\x1f\x45\xb2\x30\x03\x3d\xaa\xd3\xe8\xd9\xec\x28\x6a\x21\xb9\xf5\x98\xfb\x42\x0d\x7d\xb9\x3e\x8d\xae\x7c\x29\x0b\xd7\x48\x75\x4f\x40\x30\x97\xc8\xd7\xca\xbb\x84\x25\xae\x28\xf5\x2a\x89\x33\x0a\x2d\x5b\x7b\x26\x4f\x06\x9f\xa8\xb9\x37\x2a\x26\x73\xf7\xea\x82\x98\x84\xf5\x33\x1b\x57\x25\x24\xd4\x2e\xdc\xe0\xcf\x65\x15\x1f\x6f\x6c\xdb\x51\x65\xaa\xaa\x6c\xf6\xa2\x62\xf5\xcb\x46\x79\x5d\xd1\x05\xfe\x7b\xde\x0c\x63\x21\x04\x20\x5c\x86\x18\xce\xa0\xc8\xea\xaf\x14\x1c\xf3\xcb\xe1\x06\x01\x7d\x2b\x33\xe2\xa7\x90\xf7\xf7\x2c\xde\x50\xbd\x30\x26\xca\xd6\x53\xbf\x21\x61\x06\x96\x11\x9d\xad\xc7\x98\x59\xe1\x4f\xbe\x3f\x64\xfd\xc0\xf4\xd2\xb2\xfb\xca\xfc\xf0\xa3\xed\xf4\xb1\x47\x9b\x0c\xe4\xcf\xdb\x2b\x76\xb2\x18\xb5\xdc\x6e\xe4\x89\x70\xc6\x71\x7e\x86\xc1\xa8\x54\x18\x8c\x4a\xbd\x32\x5c\xa9\x57\x1a\x55\x0a\xf6\x68\x95\x82\x52\xab\x34\x86\x2b\x85\xe5\xa7\x4e\x9d\x2a\xc4\x8c\xc2\x53\xd2\x9b\x76\x16\x16\x62\x06\xed\x54\xbf\x5a\x80\x37\x0b\x9b\x0b\x31\x8d\x5e\x69\xc6\x7c\x7a\xba\x60\x6f\x21\xf5\xca\x6b\xce\xa5\x4d\x98\xf4\x2a\xdd\x85\x33\x3f\x69\xc6\x9b\xcd\x80\xe0\x0b\xc0\xe5\xbb\xf6\x6e\x39\xf6\xe3\x39\x77\xb2\x6a\x14\x1a\x7f\xdf\xd0\x7d\xba\x7d\xa1\xfb\xd6\x75\xae\xc7\x94\x10\xfa\x91\x0e\x67\x86\xd2\x8f\x92\x48\xac\xd6\x16\x54\x88\x27\x1b\x3a\xb7\x91\x40\xdb\x37\xdb\x3a\x1b\xe8\xa5\x7d\x78\x52\x5e\xa3\xa3\x06\x20\x19\x62\x00\x5b\x63\xd1\xb7\xc7\xcf\xb5\xb7\x4f\x1d\xf2\x42\xc4\x96\xd0\x2d\xd5\x1d\xd5\x2f\x84\x6e\xd1\x6d\x09\xdd\xb2\xfa\x9d\x35\x68\x6d\x78\xb7\x81\xa4\xd8\x8e\x37\xbc\xdb\x40\x79\xb4\xb2\x31\xdb\xef\x1c\xb8\x8d\x03\xe0\xd8\xe6\x04\x7f\x3d\x17\xe8\x3c\x7d\x4f\xc7\xb0\x63\xcb\xf5\xfc\x02\x36\xe4\xf9\x85\xd7\x75\xee\x0a\x54\x4f\x8e\x09\x58\x6d\x68\xd3\x84\x17\x30\x04\x1b\x35\x1e\xa1\x53\xc6\x90\xcc\x5f\x3e\xeb\x41\x56\xdb\xf4\xde\xb3\xe2\xa9\xc5\x87\xa6\xef\x23\x47\x3c\xa7\xcc\x97\xf3\xc1\x6c\x00\xbe\x5e\xe8\x04\x1f\x08\x02\xd0\xfb\xb3\x1d\x4b\x83\x76\x76\x4a\xcc\xc8\x3e\xd1\xa2\x79\x6d\xe1\xa0\x93\x47\xa3\xd1\x4f\x43\xbf\xe3\x5a\x9b\x71\x6d\xbf\xf3\x46\xcf\x35\xcb\xf0\xb5\x34\x80\xdf\xc2\xf6\x9f\xb0\xdd\xdb\x46\xd4\x8c\x57\xfa\x0a\x6c\x9b\xa6\xfb\x75\x54\x11\xe8\x6c\x4b\xeb\x83\xb9\x38\x1b\x3f\xa6\x2f\xfd\xfd\xd3\x73\xdf\xb7\x78\xc4\x4f\x8c\x99\x14\xf8\x8b\xe0\x8a\x27\xd1\xdc\xfc\xc1\x67\x4f\x6f\xdf\x43\x6f\x44\xa4\x8a\x79\xf4\x05\xda\xba\xc2\x56\x4d\xf2\xad\x34\x3c\x2a\x5a\xa7\x6a\xf2\x1e\xb5\x9e\x5f\xbf\x7f\x57\xc5\x2a\x79\xcd\xb3\x48\x73\xf8\x2a\x31\x80\xb5\x1b\x05\x10\x84\x11\x06\x79\xa1\x9a\xbf\x1e\x03\xd5\x7a\xb6\xdd\x5f\x2b\x46\xa1\x8e\xf3\x0f\x60\x3b\xb6\x45\xe2\xef\x38\x06\x51\xbc\x6a\xde\x72\x6b\x47\xa6\xf1\xfa\x16\xfa\xed\x98\x80\x11\xb3\xea\xbf\xde\x3a\xd6\xe3\xcd\x4f\x03\xfd\x3f\xdf\x38\x01\x9f\x0e\x08\x59\xf6\x66\x51\x43\x50\xc1\x07\xeb\x23\x69\x0e\x9e\xc8\xff\xf6\x0c\x2e\xfd\x3c\x14\x2f\xd8\xfe\xa8\x8d\x6a\xeb\xed\x3c\x7d\x99\xd0\x12\xce\xa3\x28\x81\x03\xfe\x0d\xfa\x25\xad\xed\x40\xcd\x8e\x3c\x03\x9b\x2b\xd9\x48\x73\xb8\x9b\x62\x00\x04\x49\xf6\xc3\x21\xdb\x1b\xab\x65\x9b\x66\x25\xa4\x9c\xac\xd0\x71\xe8\xaf\xad\x46\x8f\xd1\x7e\x35\x6d\xbe\xef\x99\x4a\x8d\x07\xbe\x7a\xc1\x36\x37\x38\x39\xf9\xfe\x71\x2b\x75\x0f\x4e\xff\x23\xa6\x5f\xad\xa3\x39\xc4\x67\xda\x9c\x99\x59\x24\xfb\xbe\x85\x7f\xb6\xe0\x67\x96\x6d\xba\xa0\x4d\x3e\x81\x63\xe9\x22\x6e\x3f\x9e\x90\x74\x30\x9b\x9a\x84\x4a\xa1\x13\x46\xf5\xdd\x94\xa1\xe7\xb4\xfe\x5a\x7f\x0d\x97\x8d\x86\xce\x3a\x52\xf7\x4c\x07\xfd\xeb\x81\x47\xdb\x7f\x71\x90\xdd\xe1\x21\x5f\x88\xf1\x9d\xed\x22\xd6\xb2\xdb\x36\xd8\x1e\x69\x5a\xc7\x2f\x14\x03\x24\x2b\x94\x6a\xfb\xa0\xeb\x3c\x0c\x05\x27\x03\xeb\xdb\x14\x8d\x19\x1d\xb9\xde\x13\x94\x5e\x0f\xbd\xb3\xec\x99\x17\x03\xcb\xf6\x6d\xe8\xc8\xde\xdf\xe0\xff\xe2\x83\xfb\x9e\x1c\x5f\x2c\x06\xd0\x35\xc9\x1b\x67\x55\x94\x6e\xad\x9f\xbe\xce\x66\xb5\x7d\x8b\x35\xe4\xe0\x43\x53\x5e\xac\xbc\xb4\x9b\xea\x1c\xb8\x1a\x84\x4e\xc9\x16\xa5\x76\x8c\x52\x8f\x86\xc1\x47\x05\x43\xf6\x65\x93\xbc\x71\x52\xd5\xb0\xfe\xed\xac\x59\xf4\x6a\x5b\xb5\xd0\x69\x9b\x61\x26\x29\xb6\x1a\x5b\x99\xed\x12\xd6\x92\x13\x35\xb6\xc3\xb2\xed\x19\x69\x1d\xaf\x17\x03\xc0\x8f\xc1\xf2\x42\x85\x9e\xed\x2b\x60\x5b\x6a\x15\x9c\x11\x33\x3a\x73\x17\x4f\xe1\x89\xc7\x05\x1a\x79\x69\xc7\x86\x8e\xec\xd9\x5f\xbd\x74\x9f\x18\x40\x97\xd3\xb4\x7a\xe2\x4f\x23\x69\x38\xc3\x8e\x54\xd0\x0d\xf2\xbc\xc9\x75\x5a\xc7\xef\x60\x6b\x00\x27\xce\x0c\xf0\x0a\x13\x79\x8e\xe7\xd6\x3c\xc4\x73\xa8\x00\x50\xac\x79\x08\xfc\x20\x85\x9d\x76\x33\xda\xf9\x8a\x9d\xaa\x35\xca\xe7\x77\x68\x38\xad\x7f\xc0\x38\xee\x45\xdb\x13\x5a\x6e\x49\x90\xb5\x9c\x1c\xaa\xe8\xc8\xde\xca\xd7\xed\x6b\xe8\x35\xd9\x2e\x63\x0d\x83\x7f\x85\xd6\x71\x75\x7c\x06\x8c\x00\xed\x4c\xa5\x97\xc8\xf1\xdc\xe2\x87\xf8\x51\xa8\x00\xc5\xe2\x87\x40\x25\x01\x07\xfd\x68\xf9\x7b\x4c\x7f\xd0\xa1\x63\x48\x1b\x8d\x1c\x47\x76\x07\xdb\x96\x12\x9f\xb2\x8e\xec\x6a\x2e\xdd\xbc\xcd\x7a\xd6\x66\x65\xa0\xd9\x9e\xb3\xeb\x42\xb7\x70\x06\xfc\xd8\xd9\x1c\xbe\x7e\x13\xf4\xe3\x25\xcd\x77\x6e\xcf\x75\x1c\x41\x69\xf4\x73\x24\x08\xa4\xf1\x3d\x9c\xff\x05\xd8\x9f\xf1\xc8\xd8\x4e\x4f\x6f\x53\x7a\xe4\x9e\xa9\xbb\x48\x6d\x5d\xed\x3b\xda\xbf\x9f\x3a\xc3\xaf\x63\xc7\xee\xef\x9e\x27\x63\xd0\x13\xdf\xff\xfe\xcf\x67\x2c\x19\xa7\x1f\x5b\x89\x53\x70\xc4\x87\x17\xbf\xfe\x5f\xe8\xb9\x66\xda\x0b\x6f\x7c\x44\x1b\x64\x19\x14\x01\xf0\x8b\xf8\x02\xc7\x69\xd0\x21\xa8\xd2\xc7\x1b\xb1\x6f\x77\x95\x02\xb5\x45\xef\xcc\x12\xbd\x3d\x0d\x99\x08\xfa\xe5\x99\x0b\x26\x87\xab\xc6\x8d\x8f\x0f\xa5\xc9\x5f\xf2\x19\xb6\xea\xa9\xef\xdd\xf3\x62\x23\xfe\xbd\x28\x7d\x74\x9d\xc7\xb4\x44\xeb\x3e\x19\xe6\x45\x00\xc5\x55\xa1\x8b\xed\xac\xd4\xfb\xab\x03\x14\x7a\x3f\x23\xea\xfd\x03\x55\x7a\xa3\x03\x78\xa0\x7c\x2a\x04\x2a\x50\xcb\x45\x18\xb4\x52\x33\x17\x3b\x82\x89\x97\x58\x1c\x8f\x0d\x47\x22\x3d\xc5\xc4\x50\x1d\xea\x63\x2a\x73\xd4\xf3\x7c\xc6\x8f\x09\xd6\x4e\x9c\xe0\x6b\xbb\x7e\x3c\xda\x43\x8c\xb8\x9f\x2e\x3a\x2a\x74\x5a\x37\xe6\x94\x34\xa1\x57\x19\x97\x6f\x6d\xfd\xe2\xd7\x6f\xe5\xe7\x92\x63\x2b\x73\xbd\x15\x0d\x5e\xaa\x29\xe1\xbd\x29\x5c\xfb\x3b\x25\xa5\xef\x59\x73\x25\x5c\x2a\x00\xc4\xe5\x7c\x01\xdb\x6f\xac\xf7\x0f\x50\xe8\x93\x09\xea\xfd\xd5\x2a\x85\x3e\xde\xe8\xef\xa2\x53\xc6\xc3\xa8\x1d\x85\xa8\xad\x38\xe8\xe7\xe5\x31\xe2\x17\xa9\xe8\xd1\xa5\xe5\x89\x47\x52\xfe\x81\x49\xab\xe6\x67\x4e\x1e\x3f\x6e\xec\xbc\x68\xba\xf1\x72\x28\x87\x1e\xfa\x45\xf4\xca\x05\x3e\xc3\xb6\x68\xee\xbb\x21\x5d\xdb\x49\xbc\xad\xe3\xfd\xc7\xa3\x3b\x2f\xe0\xe6\x82\xcc\xd1\x1b\xbd\xca\xac\xfb\x48\x56\xc4\xca\xf7\xab\xdf\xb7\xed\x66\xb2\x0d\x00\xe0\xd3\xf9\x12\x18\x23\xef\x13\x8b\x33\x46\xf4\x2d\x33\x0f\x54\xeb\x93\x11\xf5\xa8\xe5\x44\xff\x00\xd7\xe2\xf2\x80\x65\x5a\xff\x17\x36\x96\x56\x35\x6f\x8e\xf4\x16\x55\xf3\xb0\xe9\xb8\xad\xfd\x66\xe6\xf4\xf7\xbc\xd2\x73\x34\xe3\xf5\xd3\xf0\xc7\x7a\x71\x7d\xea\xb6\x57\x1e\x5d\xfa\xc4\x47\xd3\x68\xd3\xd4\xcd\x9c\xd8\xdb\x89\x56\x0f\x4c\x88\xcd\x08\x79\x6c\xde\xf8\xa9\x6c\x6f\x92\x14\x2f\x38\x2a\xaf\x9d\x65\x7e\x45\xe1\xf4\x27\xb3\xb5\xb6\x0f\x99\x1b\x69\xb1\xe5\x48\xbe\x03\x80\x2b\xe2\x33\x58\x39\x39\xa2\x72\x09\xdf\x74\x14\xe1\x5f\xc7\xd3\x80\x12\x3e\x83\x1a\x77\x52\xb5\xf3\x5c\x5d\x6f\x3e\x9f\xf5\x42\xd8\xc9\xb4\x6a\x91\xa8\x02\x02\xd5\xae\x73\xe2\x79\x6d\x58\x84\x90\x8c\x7e\xf2\x31\x2f\x45\xbb\xde\xdd\xd0\xf8\xd4\xda\xc7\x36\x46\xbe\xf5\xc2\xd6\xdd\x6f\xd1\x93\x7f\xf8\xbb\x8d\xa4\xd7\x7e\xbc\xca\x34\x7b\xd1\x58\x6c\xf9\x18\xe7\xfe\xdb\xaa\x2d\xf4\x87\x3d\xcf\xbd\xec\x4b\x36\x1c\x6d\xfd\xa0\xf3\xcf\xb4\xe9\x9d\xcb\x69\x23\xf7\x60\xc0\xfe\xff\x2c\x79\x52\xb6\x0b\x0d\xec\x24\x8d\x8e\x35\x49\xe0\x8f\x6a\xe4\x50\x8d\x1a\x12\x39\xdf\xd6\x3d\x9f\x7d\x47\x1e\xab\xd7\xd0\x67\xb1\x47\x7a\x6d\x64\xbe\xfb\xa8\xa0\xc1\x06\x45\x21\x9b\x13\xf2\x7e\x5b\xa1\x40\x80\x98\x33\x09\x31\xb1\x53\x39\xb7\x2e\x9c\xa0\xd4\x2b\x53\x53\x26\x47\xa5\xcc\x98\x3a\x39\x05\x67\x6e\x17\x53\x13\x8d\xc6\xc4\xf8\xa4\xe9\x7f\x91\x42\x3b\x83\x73\x8d\xaf\x26\xc1\x62\xa7\x03\xce\x48\x05\x72\x10\x73\xe9\x93\xb8\xfe\x70\xd8\xa4\x4f\x72\xb4\x04\x27\x3a\x79\x3a\xbe\xbc\x92\x96\x8a\xa9\xf7\xc4\x33\x50\xf4\x8f\xb8\x73\x25\x5d\x29\xc1\xda\xc9\xf7\x60\xb7\xd8\x09\x9c\x6b\xb6\xda\x0d\x46\x09\x49\xa1\x15\xc9\x93\xf5\xd3\x67\xc4\x46\x27\xf1\x3d\x3b\x76\xe0\xaa\x44\x63\xf2\xb4\xf8\xa4\xe9\xcc\xef\x94\xf2\x5d\xb8\x59\x54\x83\x00\x23\x3b\x10\x7e\xc9\x01\xa4\x8c\xfd\x5c\x5e\x0a\x64\xd0\x2b\x77\xe0\x3b\xab\xf9\xae\xd5\x7f\xa1\x07\x00\x10\xf5\xfc\x01\xee\x96\x22\x11\x44\x00\x4f\xc2\x66\x7c\xf5\xb8\x14\x8b\xe8\xb7\x7b\x84\x4e\xdc\x48\xab\xe9\x4d\xf4\x92\xca\xc5\xf0\x5b\xb9\x1f\x15\xa1\x52\x39\x64\x93\xd4\x88\x31\xa8\xda\x83\x2a\xfa\x8a\x18\x80\x23\xe8\x3f\x68\x35\xe3\xff\x09\xd2\x4c\x6a\xc4\x1f\xe5\x55\x18\x03\xce\x43\xe3\x4e\xdc\x9f\x11\x3d\x3d\x2b\x4d\x6f\xdc\x58\x78\xfe\x08\xe7\x95\x59\x10\x1f\x9f\x5e\x68\xc4\x5a\xd2\x64\x2b\x66\x75\x3b\x48\x8d\xc2\x43\xa6\x39\x08\xf5\x23\xdc\x69\x3e\x71\xa4\xaa\x30\xd8\xb5\x12\xba\x43\xaa\xc2\xb5\x39\x20\x00\x81\x6a\xcc\x21\x09\xc2\xe9\xa1\xeb\x56\x7f\x54\xb5\x5c\xcd\xea\xce\xd5\x4f\xc7\x1c\x72\xd4\x96\xca\x9d\x76\xad\xa5\xb6\xef\xe5\xbb\x08\x2f\xaa\xd9\xfa\x1e\x7f\x0d\x3b\xba\x4a\xab\x28\x9a\x47\x42\x03\x3f\x8c\x5d\x13\xf7\x5c\x2c\xdf\x85\xd9\x6b\xbe\xfa\xea\x2b\x00\xa4\x55\x00\x70\x19\xb3\xc1\x13\xfc\x3a\x15\xdc\x2f\x05\x94\x94\x25\x4e\xa9\x67\x0c\xd6\x18\xf5\x46\xbd\x42\x4a\x40\x68\x55\xe0\x87\xb1\xa5\xb1\x9b\x62\x57\xcf\x93\x6a\x32\x5e\xc3\xfd\xf4\x7e\xf2\xb9\x7d\x8f\x7c\x22\xa6\x51\x1f\x18\x8a\x2a\x6d\x84\x4e\x54\x68\xef\xff\x2e\xb6\x3d\xac\x70\x52\xf9\xf4\x95\xa6\xf2\x4a\xba\xf6\x3f\xee\xcb\xdf\x3a\x3b\x68\xea\xa6\xf2\xf9\xce\x33\x76\x0f\xe2\x59\x7e\x05\xeb\xcf\xf7\xe3\xa9\xfb\xcf\x39\x4e\xde\x54\x3a\x7f\xc0\x20\x07\x89\xe4\x82\x93\x56\x02\xe9\x58\xc1\xe5\x70\xcd\x0e\xfb\x70\x9c\x30\x9a\x1e\x42\x76\x86\xda\x8e\x4b\xdf\xb1\xa2\xa1\x01\x77\x6d\xdb\xc6\xce\xb2\xc2\x26\xa2\x77\x9d\xdf\x87\x6d\xed\x17\xe9\xf7\xd8\xd4\x77\x3e\x9d\x85\x33\x90\xc8\xbe\xf3\xfd\x2c\xf9\xe7\x0f\x71\x06\x52\x6b\x33\xb1\x31\x56\xe0\x33\xf9\x4c\xe9\xb3\x58\xa5\x46\x29\xfd\xdc\xdb\x01\x9c\x3d\x88\x06\xf0\x1d\x62\x28\x9b\x75\x9d\x02\x20\xe7\xbc\x52\xa6\xd4\x17\x43\x46\xa1\x94\x4b\xb3\x74\x49\x8a\xee\x6e\x17\x6f\x5c\x4b\x9e\x96\x96\x33\xe6\xca\x87\xa3\x3e\x57\x4f\x79\xbd\x79\xc9\xe2\x98\x8c\x94\xdc\xdc\x31\xa3\xbf\x1d\x7b\xfd\xda\xc4\xd7\x37\xa6\x25\x71\x6f\x7c\xd3\xf1\x75\xf1\x9c\xf8\x82\xb4\x98\x28\x23\x3d\xae\x5e\x57\xc5\x4f\x59\x90\x5a\xf4\xd9\x6b\xba\xfa\x71\xc5\x15\x25\xf5\xbd\xc7\x3e\x68\x57\x61\x37\x9f\xd1\xdb\x29\x14\x26\x64\xe4\xdf\xb3\x20\x4e\xb2\x35\x09\xa7\x8f\x1d\x38\xdd\x09\x23\x4f\xd4\xe3\x1d\xd1\x78\x1d\x33\x3b\xe8\x3b\xc3\x23\x20\x06\xfc\x74\x5d\xe6\x85\x22\x55\x0c\x65\x73\xce\x19\xc3\xb5\xac\x31\x0e\x89\x87\x7c\x1a\x97\xbf\x66\x38\x3e\xcd\x7b\x50\x3d\x08\x41\xec\x19\x1d\xbd\xbf\xa5\x78\x71\x5c\x46\x52\xee\x43\x63\xc6\x7c\x17\x7c\xfd\xda\xc4\xfd\xcf\x2e\x88\x9f\x91\x30\x37\x47\x7d\x85\xea\x64\xec\xc5\x84\x6f\xdf\xb9\xbe\x62\x8e\xe1\x91\xb4\x98\x89\xd3\xe9\x71\xf5\x63\x1b\xfa\xd1\x50\x7a\x72\x9f\xae\x7e\xdc\xf2\x0d\x12\x31\x1f\x1e\x50\xed\x54\x57\xae\xe7\xa7\x0c\x64\xec\x8c\x7b\xe3\x64\xbe\x2a\xb2\x1c\xf4\xfd\x2b\xd4\x39\x78\xfe\xaf\x90\x84\x19\x1d\xb4\xe3\xe7\x11\xc3\x84\x24\xe9\xb9\xad\x83\x3f\x04\x9d\xa2\x1e\x14\xe0\xfd\x36\xcf\xfd\x12\x20\x66\xec\x99\xb8\xd8\xa9\x18\x3f\x41\xa3\x0a\xe3\x15\xb6\x8e\xc7\xf1\x39\x24\xa7\xe9\x17\x55\xfc\xa1\xa3\x27\x1a\x36\xd4\x00\x42\x0b\x7f\x88\xcb\x10\xf5\xf2\xd9\x93\xe3\x79\xb5\x36\xa2\x05\xc7\xe1\x92\xa8\xe7\x57\x09\x2d\x0d\xa7\x0e\x7f\x2f\xc1\x3d\xca\x5f\x84\x76\xe1\x0a\x78\x03\x38\xb2\x1c\x15\xdb\x86\x6b\x3b\xaa\xfb\xed\xf3\x2b\xdf\x7d\xe8\xe1\xf7\x57\x7d\x36\x9d\xbf\xf8\xcc\xd3\x11\xea\xfa\xd1\x3a\x93\x7c\xbe\x1c\x7f\x89\x6b\x12\xae\xb2\x31\x03\x76\x02\x8e\x7c\x05\x47\x5b\xfe\xe1\x55\xa7\x12\xcb\x8a\xe8\xd7\xa5\xef\x0a\x41\xf5\x63\x74\x26\x6a\xd1\x01\x04\x42\x36\xad\x55\x1c\x17\xbe\x63\xeb\x9e\x46\xb2\x95\x3d\x5a\xb7\xb5\x0e\x0b\xe0\x7e\xc8\x87\x42\x28\x86\x72\xa8\x74\xcd\x8e\x82\xd4\x23\x57\xe8\x55\x7a\x95\x66\x0c\xea\xd9\xba\x1f\x4e\xa9\x51\x69\x55\xee\xfe\xc6\x18\xa0\x8f\x93\xe2\xb6\x3f\xdb\x83\xa4\x51\x39\xdf\x9c\xd2\x91\xa9\x38\xb6\x3c\xea\x1c\x7b\x22\x0d\xce\x4e\xa0\xab\xa0\x24\x64\xe7\xba\x75\x7f\xbd\x41\xaf\x94\xfe\xac\xd4\x1a\xfa\xda\xd4\x2b\xb3\xcb\xca\xca\x3e\xa2\xe7\xca\xca\xca\xca\x30\xe6\xa3\x06\xb3\xe9\xa9\xe7\xcc\x26\x93\xd9\x64\x36\x9b\xcd\x91\xe8\x43\x6f\xa0\x4f\x15\xfa\xd2\xef\xd1\xf7\xf2\x81\x35\xeb\xa6\x4c\x4e\x9a\xb2\xa6\x20\x3b\x23\x36\x3c\x2f\x6d\xf6\x94\x09\x93\x62\x12\x2f\xa2\x92\xfe\x0d\x95\x3b\xa3\xc6\xe4\xd4\xac\x2c\x98\x76\xa3\x6b\x0d\xfd\x3d\x4e\x95\xe7\xf4\x74\x52\xfd\xca\x8f\xd7\x70\xd1\x0c\x42\x3d\x8e\xa2\x7f\x47\x33\x4e\x2d\x3b\x6e\x7b\x77\xdb\x9e\xdd\x8d\x0d\x4d\x4d\x0d\x27\x4e\x7c\xd2\xfb\xce\x1a\x91\x96\x95\xfd\x54\xc6\x5e\xbd\xe7\x48\xc6\x9c\xfb\x63\x67\x7b\x78\xf8\xa4\x1a\xee\x7b\x68\x79\x54\x78\x46\x51\xd8\xf8\xb0\xe0\xde\xf7\xe5\x8f\x2f\x2c\xf7\xc8\xc1\x6d\x74\xfd\xe2\xa5\xb6\x7d\x1f\xd3\x73\x22\x2d\xa3\xbf\x3f\x6e\x69\x65\xa8\x9a\xfb\xda\x61\xfd\xd8\x6c\x7a\x5c\xd1\xc6\xce\xdc\x09\x81\x49\x00\xfe\x9e\x9c\x3a\xde\x35\xa6\x14\x8c\x7a\x03\x1b\x6c\x73\x0c\xd5\xba\x8d\xf6\x65\x73\x6d\xdc\x01\x6b\x36\x6d\xcf\x6a\xce\x4b\x49\x8e\x4d\xcf\x4e\xfc\xf7\xc9\xb3\x56\xcc\x7f\xff\xd7\xbf\x38\xb2\x78\x5e\xda\xec\xf9\xe9\x73\xd2\xe7\x92\x52\xae\xcd\x9a\x63\x7d\x50\x28\x39\xb4\x68\x46\x8c\x61\x41\x7c\xea\xba\x8c\xc4\x98\xb8\x59\xb1\x59\x4f\xe5\x9a\x77\x4f\xb7\x7a\xa6\xa4\xcf\x4f\x9e\x39\x3f\x5d\x8a\xed\x79\x7c\x0f\x9f\x26\x06\xb0\x75\xa1\xd3\x8c\x7a\xc7\x11\x09\x4c\xaf\x30\xcf\x63\xaf\xd8\xbe\x6e\x9d\xdf\x81\x24\xba\xfd\xd5\x5f\x0b\xe7\x22\x82\xc3\xd4\xb5\x0f\x2f\xa6\x27\x6a\xe4\x33\xcd\x79\xfe\x0c\x37\x5b\x0c\x60\xeb\x7b\x0d\xc9\x28\xdf\x00\x42\xf8\xd0\x42\x55\x9b\x6a\x53\x22\x7f\x66\xec\x94\x13\x33\x02\x0c\x9f\xcc\x90\x74\x77\x37\x4d\xc4\x0b\xf6\x3a\xf0\x04\xaf\x43\x9e\xbf\xe4\x20\x66\xec\xe7\xb1\x53\xfd\x9d\x95\xb4\xbb\xc3\xb3\xc6\xb6\xf9\xd7\x27\x15\xd1\x9c\xa4\x37\xe6\x05\xe8\x4f\xce\x00\xc4\x1f\xf9\x1e\x2e\x56\xd4\xf4\x87\x8f\x3f\x8e\x7e\x26\xa9\x58\xf3\x88\x3f\xdf\xa3\x4a\xf8\x20\x29\x68\xda\xb1\x44\x00\x1e\xde\xb6\x5f\x57\x24\x09\x67\xd8\x7d\x60\x3a\xf9\x06\xdb\x78\xa3\xc2\x6d\x6b\xb9\xf3\x92\x92\xdb\x9f\xd7\xff\x76\x63\x9d\x6f\xad\xdf\x48\xe5\x68\xc3\xd4\xa9\xd3\xe9\x82\xf4\xae\x8a\x9d\xf7\xdd\xe6\xf0\xfe\xd3\x0f\x3f\x1d\x9c\x3d\x49\xef\xe3\xe3\xe1\x35\x76\x6c\x58\x5c\x72\x7c\x50\xdd\xc1\xb1\x4d\x3b\x6d\x1f\xdc\xe1\x30\x7f\x82\x1a\xbe\x80\xab\x10\x4e\xb8\xee\x2f\x1b\x06\x57\xd4\x0c\x46\x68\xb8\x56\x41\xf6\x2b\x87\xed\xc1\xe2\x56\xf0\x67\x7b\x19\x9d\xbb\xc0\xb5\x4e\x5d\xb2\x1d\x9d\xbc\x60\xdd\x13\xeb\x96\x04\xad\x0b\xc8\x2b\x48\xd2\x6b\xc4\x31\x25\x3e\x39\xf7\xde\xbf\x58\xbd\xea\x9d\x51\xfa\xa9\x13\xc7\x4a\x39\x87\xf5\x0a\xdf\x03\x55\xa2\x09\x46\x4a\x3d\x3d\x34\xc6\x3b\x2e\x91\x91\xd2\x95\x70\xe7\x45\x2f\xd6\x2b\x1e\xbf\xc9\x39\xe2\xf7\x60\x8c\x62\x6e\xde\x92\x8d\x26\xbc\xf8\x4c\xec\xa1\xc9\x2f\xa6\xf2\x3d\x41\xbb\x56\x19\x76\xcd\x50\x1b\xcb\x56\x26\x75\x8d\x7e\x66\x9e\x7a\x72\x45\x94\x04\x33\x93\xef\xb1\xcf\x16\x4d\xec\xee\x04\x40\x7d\xa0\x5a\x4a\x7f\xfc\xfb\xc1\xb6\x66\x36\x18\x66\xe7\x66\xe7\x35\xf6\x83\x2c\x9a\x4a\x97\x06\x66\xfe\x92\x96\xbb\x01\x76\xe0\x18\x29\x5e\x86\x91\x52\xff\xa2\x3f\x8e\x43\xd1\x3d\x10\xdd\x6f\x02\x53\xef\x7f\xf8\xfe\xf9\x3e\xd9\x1e\xa9\x73\xa3\x75\x93\xfa\xa1\x8d\xed\x59\x62\xd2\x8c\x59\x73\x95\x91\x85\x23\x22\xc2\x83\x03\x18\x4f\xae\xf2\x3d\xf6\x4b\x0a\x5f\x18\xc9\xee\x85\xeb\xd7\x1e\xe7\xb6\xc9\x4b\xdf\xb7\xc9\x4b\x61\xbd\x2a\x1e\x5d\x70\xc4\xf7\x41\xbd\xe7\xdc\x87\x0b\x9f\x7b\x22\x66\x7a\xfb\xa4\x79\x61\xda\x94\xe0\xc8\xb8\xb1\xcb\x13\xdb\x26\xcd\xd7\x86\x25\x07\x4f\xd2\xab\xf9\x9e\xa0\x96\xa2\x98\x5d\x33\xd5\xc6\xb2\x55\x89\x98\x7b\x69\x9c\xd2\x2f\x74\xf2\xb4\x4b\xa1\x01\xca\xb1\xd1\x7a\xa9\x6d\x9b\x17\xdf\x63\x2f\x11\x8f\xb3\x33\xd1\x00\xf5\xb2\xe7\x97\xf7\xec\x39\xc5\x61\xf3\x2a\xf3\xce\x59\xb8\xc3\xb8\x5e\xf3\x46\xdd\x13\xdb\x6f\x2e\xf9\xc5\xc1\xa8\x7d\xb3\x84\x2b\xb3\x13\x6b\x4c\xf5\x0d\x1b\xd4\x39\x95\xaa\xe8\x27\x23\xfa\xc3\x0a\x18\x00\xcb\x79\x01\xaa\x3b\xa8\xaa\xc6\x22\xbe\x21\x7e\x96\x47\xe6\xe3\x0e\x58\xf5\x98\xae\x5e\xfd\x48\xd0\x86\x3e\xbc\x14\x22\x78\xb3\x5b\x87\xfa\xc1\x1a\x4a\xf5\xdc\xe0\x56\x6f\xbb\x18\x92\xb4\xb0\x30\x3b\x5d\x12\xc0\x9c\xc9\x11\xe1\x0e\xf0\x2f\xe0\xdc\x2c\x8f\x19\x29\xb3\xe6\x29\x23\x8b\x46\x84\x4f\x1c\xe7\xcf\x78\x7f\x8b\xef\xb1\x9f\x51\xf8\x82\x0a\xc2\x86\xbd\x1d\xdb\xbd\x75\xeb\xad\x84\x83\x29\xf7\x69\x67\x8e\x0b\x8f\x0d\x71\xbb\x14\x2b\xb7\xcc\x3b\x77\xe1\xcb\xf1\xeb\x35\xff\x56\x5b\xbd\x5d\x8c\xbd\x14\xed\x17\xea\xbc\x91\x2f\x7b\xd6\xf4\xaa\xa7\x9e\x7d\x1e\xd0\x9e\x45\x53\xe1\x04\x9b\xcd\x06\xce\x28\xbb\x5d\x9d\xde\x61\x95\xed\x01\x11\x71\x33\x92\xa2\xab\xc7\x4e\x7c\xee\x89\xd9\x34\xab\xdc\x33\x7d\x76\x71\x6e\xf8\x63\xf1\xe5\xf2\x1d\x0f\xf6\x6e\x5a\x86\x75\xb0\x5b\xca\xf1\x15\x72\x12\xa3\x97\x93\x98\x48\xa3\x2e\x26\xde\x27\x69\x6f\xea\xe8\xca\xd2\xb9\x93\xae\xf9\x4f\x9b\x85\xc1\xf4\xd8\xa3\x15\x81\x6c\x4c\x93\x5e\xe4\xcf\xa2\x4e\xbc\x35\xc4\xbd\x4a\x2e\xf9\xba\x4f\x33\xd2\x8b\x89\x71\x59\x89\x93\x23\xe2\xda\x1f\x7b\xf8\x4c\x78\x67\x56\xd6\x3d\x53\x27\x4d\x4c\x8a\x0a\x8f\x15\xc2\xe3\xe6\x64\xc5\xcd\x9b\xfc\x87\xc0\xe7\x36\xab\xa6\xbe\x91\xd8\x16\x37\x27\x3a\x7c\xda\xdc\xc9\xce\x36\xbc\x58\x1b\x7e\x10\xd2\xff\x8e\x28\x83\x6c\x8d\xfe\x43\x35\x31\xfb\xb0\xae\x60\xed\x93\xff\x31\xb0\x05\xfc\x8b\x6a\xc3\xde\xd1\xb5\xf4\x82\xab\x85\x3b\x9c\x59\x0d\xcd\x00\x5c\xa7\x50\xcb\x56\x36\x18\x34\x28\x2f\xeb\x6f\xc6\x62\x8c\x32\x9b\xe9\x3e\xde\x62\xa6\x17\x30\xca\x62\xe2\xf6\x62\x3e\xdc\xb1\xfc\x56\xa9\x7c\x1a\x1e\xb1\x98\xc8\x05\x12\x7e\xbb\xf2\x6b\x51\x63\x36\xd3\x8d\xbc\xc5\x6c\xcb\x23\xfb\x2d\x26\x6c\xe6\xf2\xfa\x95\xf7\xe8\x2b\xef\x2a\x6e\xe2\x2d\x66\x6b\x2a\x77\xd4\x62\xe2\x2d\x52\xd9\x85\x6e\x65\x8d\x9e\xec\x20\x18\x5c\x98\x8f\x49\x98\x6e\x36\xd3\xc3\xc2\x98\x42\x7a\x01\xf5\x16\x13\x7f\x92\x7e\xce\x60\x67\xb9\xe1\x62\x44\x79\x0b\x83\x26\xab\x08\xd3\x51\x6f\x36\xd3\x97\x04\x75\x21\x3d\x8c\x59\x16\x13\xd7\x2a\xf3\xcd\x09\x9f\xf5\xca\x64\xd4\x17\x16\x90\x3a\xb3\x59\x50\x17\xd8\x76\x91\x0d\x16\x13\xc9\x70\x2f\x27\xc3\xf5\x97\x0a\x1a\x70\x61\x16\x76\x5c\x64\x78\xa8\x4b\x69\x09\x9d\xca\x95\x58\x4c\xd7\xc9\xaf\xa5\xf2\x69\xee\x78\xcb\xe5\x31\x2d\x0f\xdb\xaf\x98\xcd\x74\xbf\x10\xb4\x9c\xae\xb2\xed\xe1\x2c\x16\x13\xd7\x22\xe3\x91\x06\x40\xca\xfb\xe3\x91\x96\x87\xf3\x36\x6d\x12\x82\x8b\x69\x37\x46\x4a\xe2\x61\xf7\x5d\x0c\xc1\x0f\xc3\x2a\x9c\xc7\xf8\xd1\x21\xe8\x17\xda\x2e\x13\x8d\xc5\xc4\x57\xd9\xba\xc1\xbd\xbc\xa7\x5c\x5e\xe9\xac\x50\x88\x31\xac\x82\x21\xd3\x76\x08\xa3\x51\x23\x61\x42\x0f\xca\xb8\x2c\x1a\x8a\x87\x8b\x36\x60\x31\x7a\x98\xcd\xb4\x55\x48\x48\xb7\xb5\x90\x02\x8b\x89\x34\xc9\xe5\xa3\xfb\x95\x57\xcb\x6d\x44\x57\x62\xe3\x2d\xb3\x99\xee\x15\x12\xd3\x6c\x69\xb7\xb8\x43\x16\x13\xfa\xe0\x52\xa9\x7c\xba\xa3\xbc\xe8\xa2\x35\xfd\x31\x52\x6e\x36\x0b\x49\xa9\xbd\xbb\xf9\xe5\x16\x93\x0c\x73\x20\x3f\xa2\x37\x30\x7e\x24\xa4\xcb\x24\x92\x1c\x09\x56\xf8\x10\xfc\x08\xaf\x76\xf0\xe3\xb0\xb0\x28\xd6\x7a\x89\xd3\x5a\x4c\xfc\x18\xeb\x25\x70\x2f\xef\xe0\x87\x41\xae\x60\xc2\x5c\xa6\x1f\x5d\x42\xa6\xc1\xfa\x15\x59\x71\xc8\x62\xe2\x9a\x6d\x1b\x07\x97\x57\x3a\x1b\x58\x8f\xc1\x66\x33\x3d\x24\x35\x50\x83\x7e\xa4\x5c\xc2\xc7\xc9\x3f\xdd\x50\xfc\xd3\x55\x61\x1d\x7a\x9b\xcd\x74\x87\x54\x27\x97\x6b\xb5\x98\x30\x4b\x2e\x1f\xd3\x4f\x57\x18\xff\x30\xc6\x84\x07\x2e\x30\x12\x32\x8c\x56\xd5\x17\x7c\x97\xc5\x84\xe9\x32\x3e\x03\xf8\x62\x90\xc8\xdd\xb4\xc9\x45\xea\x8f\x0c\x66\xf0\x10\x7c\x09\xae\xc1\x7b\x1d\x7c\xc9\x8a\xb1\x46\x72\xdd\x16\x13\xd7\x6d\x8d\x74\xce\xaf\x0d\xe6\x8b\x5a\xe2\xcb\x2c\x99\x91\x31\x56\x35\x57\x5a\x6b\x31\x71\x15\xd6\xcd\xc3\xea\x95\x09\x17\x62\x34\x2b\x9f\x1d\xd5\x7b\x95\x94\xe1\x41\x8b\x89\x6c\xb5\xc9\xe7\xa6\xf7\xaf\x83\xe1\xae\x3a\x15\x28\x3a\xeb\xd4\x58\xb8\xcd\x16\x13\x1a\xe9\x29\x37\xbe\xc8\xb4\xb2\xcd\x15\x31\xb5\xf8\xd2\xb7\x66\x1a\x25\x64\x47\xf7\x8a\xbc\xc5\x62\x72\x9c\x9b\xcb\x78\xd2\xa7\x4f\x91\xb5\x98\xb4\x69\x93\x90\x1d\x2d\x53\xe9\xa6\xd3\x6c\x74\x92\x9d\x4f\x80\x8b\x70\x03\xfe\x60\xa6\x67\x68\x07\xef\x87\x65\x92\xc3\xa1\xec\x9c\x3b\xc8\x74\xc3\xd3\x41\x9a\x27\x66\xe2\x1e\xc6\xbb\x4e\xda\xc5\x7b\x60\x15\x3d\x23\xb9\x1d\xae\x01\xe3\xe9\xc5\x3b\xd6\xd9\x49\x2f\x4a\x75\x6c\xc7\x49\x8a\xc5\x44\x22\x49\x2d\xbd\x39\x74\x1d\x03\x0a\xce\x3a\x75\xf4\x3b\xa9\x8e\xf5\x3c\x17\x6d\x31\x7d\xcd\xbd\x79\x53\xe6\x61\x81\x9b\x5c\xe5\x3a\x28\x14\x60\x13\x1a\xcc\x66\xba\x85\xde\x60\x55\x92\xb8\x2e\x8b\x89\xaf\xff\xca\xd1\x86\x8b\x37\xb2\x16\x64\xe2\x9e\x4d\x9b\x64\x22\x2c\x26\xbe\x8b\x5e\x1a\xca\x27\x4b\x25\x85\x66\xcc\xc6\x44\xb3\xd9\x0e\xdc\x55\x33\xaa\x2d\x26\xfe\xc4\x97\xb7\xf3\xf7\xb2\x4b\x69\xe2\xae\x9a\x69\x17\xc9\xb6\x98\x48\x09\x56\xdf\xae\xbc\x09\x7d\x25\xff\xc0\x5d\x35\xdb\x6e\x70\xe1\x16\x13\x1a\x48\xfb\x10\xb8\xf8\x3b\xe2\xc3\x2b\x37\xcc\x66\x7a\x40\x2a\x3d\x93\x69\xee\xd5\x7e\xbe\xca\x5d\xcf\x17\x15\x62\x28\x16\x4a\x2a\xc5\x7d\x57\x44\x2f\x92\x1c\xe6\x0f\x2f\x0c\x92\xad\x4b\x6f\x33\x0b\x31\x51\x36\x0c\x9e\x2f\xa4\x27\x31\x0d\x7d\x2d\x26\xee\x20\x3d\xec\xf2\xcd\x83\xed\x39\xad\x08\xa3\x30\xdf\x6c\xa6\x2b\x78\xdf\x47\x68\xa7\xbb\x3f\xcc\x1c\x1c\x53\x32\x0b\xc8\x46\xb3\x99\xf7\x5a\x66\x7b\x82\xdb\x69\x31\xa1\xce\xbd\x9c\x7b\x8c\xc8\xcc\xc7\xf6\x1e\x86\x89\xf7\x32\x9a\x45\x8b\xf9\x3c\x8b\x89\x6c\x70\xc1\x1d\xe8\x13\x33\x0b\x24\x45\xe7\xa1\x98\x76\x11\xa9\x64\xf1\x20\x7f\xe2\xe0\x49\x4c\x05\x1a\x31\x9b\x01\x2e\x4a\xb7\xed\xe4\x52\x2c\x26\x3e\xd8\x7a\x4d\x9e\x93\x1c\xca\xf6\x13\x2a\x30\xc1\xc1\x93\x9c\x34\xdb\xaf\xc8\x8b\x1d\x52\x08\xb2\xad\x93\xcf\x66\x1d\xcc\xc3\x94\x4a\xcc\x67\x3e\xb1\x8b\x2f\x4b\xb2\x65\x63\x02\x49\x97\x30\xa7\xfb\x5c\xe7\xb9\x0e\xe6\x61\x4a\x25\x96\xa1\x17\x4b\x42\xca\x92\x6c\xb1\xdc\x3e\x8b\x09\x73\xfa\x97\x77\xf7\x89\x29\x95\xb8\xfb\xb2\x14\xb5\xf8\xb2\x24\xeb\xa5\xd3\xcc\x27\x1a\xe4\xb2\x03\xf9\x92\x52\x89\xb1\x9b\x36\x49\x50\xdb\xb8\x28\x8b\x09\xa3\x87\x8d\x9d\x35\x68\x70\xf8\x44\x8f\x58\x6b\x79\x3f\x9f\x68\x18\x8a\x2f\x86\x1a\xbc\xc7\xe1\x13\x3d\x62\xad\x8f\xfc\x1c\x9f\xe8\x15\x6d\x8d\xfa\xb9\x3e\xd1\x2b\xba\xf7\x84\xbb\x4f\x34\x0c\xf6\x89\x06\x13\x36\x5d\x36\xd3\x58\xa9\xec\x22\xa7\x4f\x34\x0c\xf2\x89\x06\x13\xea\x37\x6d\x92\x90\xa8\xe2\xce\x31\x9f\x98\x39\xd8\x27\x66\x62\xa5\xe4\x13\xaf\xd0\x36\x4e\x24\xd5\x92\x4f\xb4\x7d\x7c\x67\x9f\x78\x8e\x1e\x91\x8a\xbb\x7c\x62\x28\xf5\xbe\x63\x9d\x83\xf4\xa2\x54\xc7\xe5\x13\xb3\x69\xca\x30\x3e\xb1\xaf\x4e\x13\xfd\x9b\x54\xc7\xe9\x13\x2b\x68\x01\x0c\xb4\x23\xb9\x8e\x54\xa5\x9d\xf9\xc4\xbd\xf4\xaf\xac\x8a\xec\x13\xb3\x68\x29\x20\x94\x0c\xf2\x89\x25\x68\xda\xb4\x89\x7e\xef\xa0\xd9\x44\x13\xfb\xc1\x75\xf3\x9d\xe4\xaa\xd9\x6c\x5b\xe5\x28\x77\xd6\x76\x6e\x90\x7f\x70\xaa\x36\xa6\x61\x29\x9a\xcc\x66\xfa\x21\x3d\x42\xba\xb1\x51\xf2\x9f\xdc\x55\xba\xf3\x6e\xe2\x0b\xb9\x85\x55\xf4\x33\x92\x66\x31\x91\x5a\x34\xdc\x5d\x7c\x91\xea\xd8\x3e\xe2\x16\x59\x4c\x38\x86\xd4\xd2\x7f\x0c\xcd\x17\xe4\x32\x71\x3d\x96\x9b\xcd\x74\xe5\x7f\x91\x5b\xf8\x91\x75\x1f\x1f\x6e\x31\x71\x9d\xf4\xbf\x06\xfa\x17\x87\xb6\x3b\x82\x05\xf9\x1e\xf7\xdc\xb4\x98\xb8\x53\xf4\xa3\xa1\x63\x05\xd7\x8c\x39\x98\x60\x36\x7f\x45\x9a\xcc\x92\x2b\xe4\xf3\xe8\xec\x61\x7d\xbf\xa2\x19\x97\x63\xa4\xd9\x7c\x83\x34\x99\x31\x01\x25\x0c\x76\xd3\xe1\xe3\x44\x11\x33\x9f\xbd\xa4\xc9\x4c\x3f\xe1\x76\x5b\x4c\x18\x8e\x95\xb7\xe9\x47\xd4\x33\xcb\x69\x95\x8a\xf3\xcc\x7b\x36\x01\xbb\x93\xc8\xcd\xf6\x05\x59\x9a\x39\x05\xe8\xc5\x98\x71\x9c\x1c\x2f\xa0\x5c\xa1\xc5\xc4\x87\xdb\x7c\x65\xbb\xcc\x19\xca\xf6\x73\x0a\xd0\x1f\x4b\x24\xbb\x94\x2a\xdc\x22\x8f\xdf\xb0\x98\x38\x93\xed\x98\x7c\xae\xf4\x60\xdb\xcf\xcd\x47\xbd\xec\x5c\xc8\x91\x15\xf4\x02\xc6\x32\x1f\xbd\x86\x7e\x36\x44\x1b\x4e\xc5\xc9\x29\xc2\x4c\xd6\xd1\xda\x49\xba\xf2\xe9\x31\x77\x9f\x98\x33\x28\x6f\xce\x29\x20\xd5\x66\x33\x39\x5e\x60\x7b\x85\x3f\xc1\x6c\x3a\x7f\xb0\x2f\xcc\xcf\xc7\x98\x4d\x9b\xc8\xb1\x15\xf4\x1c\x73\x24\x7a\xb6\xa6\x63\x08\x5f\x68\x2c\x77\x84\xb4\xd3\xa4\x27\x93\x8e\xe6\x53\x2d\x26\xae\xcb\x9a\x04\xee\xe5\xfb\xf1\xc3\x58\x86\x51\x58\xc0\xe8\xeb\xc9\xa4\x5e\xdc\xca\xaf\x2d\x26\x2e\xda\x7a\x7e\x70\x79\xa5\xb3\x7c\x0a\x66\x38\xca\xdb\xbe\x22\x99\x24\xd2\x62\x72\x4c\xe3\x4a\x75\xec\x74\x88\x3a\xe5\x98\xcb\x12\x0b\x56\xe7\x30\xce\xe6\x8a\x2c\x26\xcc\xa5\xfb\xa1\x1f\x5e\x6e\xfe\xd0\x58\x8e\x9b\xad\x66\x1a\x2b\x95\x2f\x72\xfa\x43\xe3\x20\x7f\x68\x2c\xc7\x94\x4d\x9b\xa4\x42\x57\xf8\x6a\xc6\xbb\xf4\x81\xfe\x50\x8b\xe9\xb8\x0b\x2f\x98\xff\x4a\x4d\x68\x96\x7a\x6b\xbc\xc5\x9a\x3f\x38\x27\x70\xd9\x63\x1a\xee\xc1\x85\x66\x33\xbd\x4a\xdf\x92\xca\xd3\x83\xb8\xc8\x62\xe2\xaa\xd0\xd7\x7a\xe6\x36\x75\x7e\xc5\x54\xe4\x2c\xed\x92\xea\xd8\xbe\x22\x63\x2c\x26\x52\x84\x37\x6c\xa4\xaf\x4e\x5d\x7f\x7f\xe8\xac\xd3\x41\xff\x84\x66\xce\x6a\x6d\xe1\xf2\x2d\xa6\xbd\xdc\xa3\xb6\x54\x18\xd8\xf7\x74\xfa\x43\x67\x95\x03\xf4\xbf\xa4\x66\x1c\xd9\x3f\xb5\xe5\xba\xf5\x3d\xfb\xfc\x5c\x1a\xfe\x6a\xd3\x26\xfa\x47\x07\xd1\xc1\xb6\x04\x06\xb7\xb6\x1f\x5c\x66\xc9\x58\x8b\x45\x98\x69\x36\x5f\xa6\xad\xd8\x48\xde\x43\x83\x94\x52\x9e\xb6\x15\xf4\x2b\xef\xe6\x17\xb5\x58\x8b\x1b\xa4\xa4\xf2\x6b\x7a\x08\x1b\x49\xb7\xec\x16\x6d\x1b\x06\xe5\x21\x2e\xfe\x24\x60\xbb\x23\xc6\xb4\xe3\x5e\x6e\x2e\xcd\x26\x19\x16\x13\xc9\xc5\x2d\x52\x04\x1d\xaa\x8e\xa1\xaf\xce\x41\x7a\x16\xf7\x72\xf3\x6c\xa1\x5c\x8d\xc5\xd4\x41\xbe\xb7\x1d\xea\xd7\x8e\x3b\x7f\x9c\x55\x5a\x69\xb7\x54\xc5\xba\x83\x17\x2d\x26\xae\xd1\xd6\x25\x97\x1f\xe8\x17\x13\xb0\x7d\xd3\x26\x7a\x0a\x77\x70\x0b\x9a\x2d\x26\xee\xb0\xad\x19\x10\x1a\x06\xf1\x87\xc3\x06\xcc\x91\xe0\xf6\xd0\x1d\x78\x18\x73\xc8\x06\xe6\x1a\x8b\xe5\x38\xd0\xe0\xae\x6f\x32\xdc\x06\xb2\xd7\x6c\xb6\x7d\x80\x87\xc9\x9f\xaf\x59\x4c\xdc\x45\x76\x26\x74\xc3\x50\xf1\xa5\x01\xd3\x31\xc7\x6c\xa6\x97\xe9\x9f\xf0\x30\xae\x92\xf3\x4f\x7a\x04\x06\x94\x77\xf1\xd1\x81\x08\xfd\xc0\x0e\x78\x58\xea\xbf\x70\x75\x16\x13\xce\xc6\x58\x7a\x15\x06\xe1\xce\x5c\xa9\xc2\x59\x65\xef\x25\xa9\x86\xed\x3c\x5f\x63\x31\x91\xcc\x5b\x83\x72\x51\x67\x16\x2d\xc7\x0a\x3c\x82\x4d\x24\xca\x62\x22\x8d\xb4\x0b\x86\xeb\x5b\x70\xcd\x98\x85\x49\x66\xf3\x45\xcc\x31\x4b\x2e\x8e\xeb\xb6\x99\x86\x8d\x17\x5c\x33\x2e\x94\x52\xae\xef\x31\xc7\x4c\xca\x24\x1d\xe3\xc2\x69\x2c\xdc\xae\x6f\x11\xc2\xfc\xfa\x05\xcc\x31\xa3\x99\x04\xbb\x90\x19\x2e\x66\x38\x86\xb6\x30\xc7\x4c\xaf\xf3\x87\x65\x8f\x3b\x20\x3f\x77\xc4\x8c\xcc\x7c\x04\x34\x4b\xee\x08\xab\x96\x7f\xcb\x6f\xb1\x98\xb8\xf3\xd6\x68\x18\xdc\xb7\x10\x9c\x11\x34\x1f\xbd\xb0\xc6\x51\xe1\x16\xf7\xc7\x8f\x2c\x26\x2e\xc7\xda\x36\x7c\x5f\x24\x1f\x83\xb1\xd4\x51\x9e\x5a\x88\xa9\xbf\x8f\x1c\xae\x4e\x92\xec\x57\xa5\x3a\x17\x31\x9e\x6b\x90\xfc\x3c\x3d\xd3\x7f\x3c\x47\xe1\x8a\x33\x9a\x45\xf9\x58\x85\x5e\x66\x1a\x8b\x95\x25\xb4\x95\x39\x49\x56\x6e\x80\x8f\x5c\x94\x8f\x89\x9b\x36\x49\x65\x2e\x4b\xd9\x76\xff\x3e\xb9\xd1\xe1\x23\x63\xf0\x10\x5e\x30\x7f\x4b\x57\x47\x0b\xd9\x92\x8b\xec\x15\xfb\xe7\xb5\x4e\x34\xc3\xd1\x80\x87\x98\x42\x59\xe8\xe6\x68\x21\x9b\x9e\x42\xa3\xc5\xc4\x6d\xb6\xf4\x56\x0f\xca\x85\x8d\x2e\xbd\x75\xd6\xb9\x48\xdb\xa2\x85\x6c\xdb\x05\xa6\x5a\x19\xf8\xd7\xde\x53\x03\xc7\x2d\x8c\x2e\xfb\x57\xe3\xef\x59\x9d\x2e\xba\x2f\x56\x58\x64\xbd\x28\xf5\x2e\xbf\xe6\x94\x56\x0f\x18\x38\x36\x62\x74\xda\x7f\x30\x7e\x26\x47\x6a\xfa\x76\x8c\x90\xe5\x3e\x38\xd2\x6f\x7c\xc1\x28\x6b\x41\x24\x1e\x93\x54\x9d\x11\xec\xe8\x2e\xf4\xef\x77\x19\x9d\xfe\x31\x06\x0f\x4b\x70\x2f\xd0\x6c\x23\x4f\x30\x5d\x72\x8f\xdd\xd6\x80\x41\xe3\x44\x46\x97\x7f\xd4\x61\x87\xd4\x4f\xfb\x91\x2e\x8b\xe5\x13\x64\xf7\x68\x0d\x86\x81\x63\x57\x7d\xfc\x09\xc7\xa3\x8e\x98\xf3\x42\x2c\x9f\x41\x0f\x4a\xbd\x5d\x52\x8e\x7e\xd6\x9a\x61\xea\x18\xa4\x3a\xdd\x6c\xb8\xab\x9b\xee\x35\xf0\x33\x6d\xb5\x52\x5a\x70\x92\x94\x58\xcf\xf5\x6f\xc7\x9d\x3f\xe1\xf8\xb1\x83\x3f\xef\xc5\xf2\x79\xd6\x4b\xfc\x18\x8b\x89\xd3\x5a\x2f\x41\xff\x31\x29\xa3\x73\x44\x0d\x3f\xde\xb4\x49\x2a\x7a\x7c\xab\x14\x01\xad\xe6\x01\xe3\x7e\x0e\x3e\xa6\x93\xaf\xcc\x66\xdb\xd6\x54\x21\xc9\x62\xe2\x97\xf7\xee\x1e\x34\x9e\xe8\xa4\x53\x81\xd1\x52\x26\x68\x36\xdf\xa2\x6b\xd2\xc8\x67\xb8\x14\x7d\x2c\x26\xee\xd0\x2d\x5b\x5a\xff\xf1\x4a\x57\x1a\x85\x8b\xd0\x8c\xb9\x66\x33\xbd\x45\x9b\xd2\xc9\x45\xd9\x3d\xda\x8a\x6f\xa7\x67\xed\x52\x20\xa3\xe7\x68\x73\x26\xb9\x4a\x0f\x72\x2d\x16\x13\x6a\x30\xda\x11\x33\x0c\x43\xf0\xc4\x59\xe5\x30\x7d\x6f\x21\xb9\x6a\xeb\xe6\xab\x2c\x26\xa2\xb1\x5d\x86\xfe\xe3\x97\x8e\x34\x0c\xa3\xf1\x88\xc4\x93\x74\x72\x95\xc9\x48\x2a\xd8\x2f\x56\x1b\x9d\x31\x23\x0d\xb7\x62\x9e\xd9\x7c\x85\x66\x2d\xc7\x2a\x09\x0f\xce\x62\x6b\xa2\xa5\x30\x60\x1c\xda\x99\x86\x71\xb8\x10\x77\x49\xc2\xb9\x48\x33\x4b\xf1\x59\xb2\xff\x5b\x8b\x89\x2b\xa1\x53\x69\x49\xff\xf1\x6d\x27\x1e\x0b\xc9\x15\xb3\xd9\x56\x53\x4a\xce\xb0\x50\xba\xc1\xb6\xab\xff\xb8\x79\x1f\x0f\xb3\xb0\x1c\x57\x9b\xcd\xf4\x0c\x3d\x5c\x8a\x1b\xe4\x54\x94\x76\xc0\x80\x71\x79\x17\x3f\x1c\x68\xd0\xc3\xb4\xab\x04\x9f\xa5\x9f\xf3\x27\x99\x17\xba\x30\x60\x7c\xdb\x89\x87\x9c\x64\xbc\x57\x8c\x26\x6e\xaf\xc5\x84\x91\xb4\xbb\xbf\x7f\xd6\x3b\x62\x05\x36\xa3\x0f\xd6\x4a\xa1\xce\x2c\x39\x2a\xee\xa8\x35\x75\x90\xef\x97\xca\x1a\x1c\x85\x7d\x59\xbf\xeb\xb2\x99\x8f\x3c\x67\x31\x71\x3a\x6b\xcf\x10\x65\x9d\x71\x62\x1c\x6e\x30\x9b\xe9\x15\x33\xf9\x91\x88\x16\x13\x49\xb5\x1d\x1d\xbe\xac\x9e\xe5\xc6\x17\xcc\x98\xcf\xf0\x8d\xa2\x17\x40\x80\x22\xfb\x75\xbe\x41\xa4\xa0\x61\x6b\x3b\x66\xc3\x02\xd7\xe9\xad\xfa\x78\xa3\x5e\x24\x8a\x7e\x4b\xf2\x0d\x5a\xb7\xe3\x3e\x9d\xf3\xde\xfe\x46\x8d\x22\xdc\x98\x8c\x6e\xcb\x4d\x5d\x17\xcc\x17\x6d\xfe\x61\xfb\x6f\xb3\x47\x4c\x9b\xda\x18\xf2\xf0\xf8\x74\x9f\xb0\xe0\x50\xad\xff\xbd\xc1\x87\x15\x8f\xb4\x3e\xb8\x79\xef\x7b\x79\xd9\x05\xef\xac\x5b\x99\xb7\xec\x8d\xc2\x97\x43\x89\x2e\x94\xaa\x7c\x53\x92\xc5\xbc\xf8\xa9\xd1\x33\xb6\xbd\xcf\xb7\x0b\x63\xf9\xac\x89\x73\xb1\xe8\xdf\xb1\xe8\xd3\xa3\x15\xfa\x44\xfa\xc3\x56\x7a\x6c\x7a\x9c\x56\xe7\x5d\x37\x62\xd4\x67\xeb\xf2\x4e\xbe\xb9\xae\xec\x6d\x0c\xd9\x5d\x54\xf5\x3a\xfd\x92\x9c\x6c\x68\xf8\x34\xd3\x33\x3e\x54\x99\x39\x65\xfa\x9c\xe9\x25\x1b\x31\x25\xa0\xb5\x6e\x74\xfa\x5b\x43\xd0\x98\xf1\xdf\x42\xa3\xd1\x31\xcd\xfe\xf3\x48\xd4\x2b\x1d\x24\x26\x6c\x7b\x2b\x2a\xfd\x68\xca\xee\x7f\x96\x3e\xdf\xd1\x79\xe7\x02\x56\xfe\x16\x06\xd1\x37\x17\xee\xfd\xe7\xe8\x1b\x7c\x67\x7c\xb8\x63\x5a\xf7\xe7\x91\xa8\x75\xbf\x68\x1e\x45\xbe\x9d\x0f\xe2\xb3\xee\xfb\x19\x74\xa2\x29\xbb\x68\xd2\x24\xc3\x34\xde\xd3\x33\x74\x92\x90\xe9\xb5\xf8\x62\xc0\x73\xaf\x8d\xde\x05\xff\xa3\xb4\xaa\xff\x29\x71\xf6\xbb\x54\xff\xab\x9f\x2b\xd0\x41\x84\x66\x3b\x84\xea\xa0\x53\x91\xc8\xe8\xbc\x07\x32\x21\xfb\x9f\xa0\x53\xef\x9c\xea\xd6\x84\x45\xa4\x20\x3b\x74\x79\xa0\x85\xde\xb5\x68\x5b\xcb\x46\x2c\x7c\xe8\x81\x82\xb1\xeb\x67\xd1\x1f\x4c\x5b\x23\x25\x43\x0d\x37\x18\xa7\x46\x27\x6c\x3f\xf6\xf3\x04\xcc\xb5\x4f\x8f\x8b\x9b\x7e\xb3\xf6\x25\x49\x99\xc5\xc9\x93\xa6\x4c\x9f\x63\x5c\xb5\x11\x67\xa9\x9e\x7b\x6d\xcc\x2e\xe8\x93\xf1\xff\x20\xed\x3f\xd7\x72\xfb\xd3\x9e\xe5\x46\xfb\xa1\x89\x19\x1f\xdc\xb5\xc4\x87\xa6\xdc\x6f\xcc\xfd\x5f\xa8\xdc\xec\xd8\x45\xf7\x42\x76\x37\xc0\xbf\x42\xb7\xff\xbf\x6c\xd0\xfd\x29\x4f\x1f\x68\xd8\x92\x87\xce\xfb\x99\xd4\x63\x86\xa4\xf3\xd3\x0c\x9c\xa7\x57\x68\xa4\x90\xe9\x59\xf8\x47\x55\x6b\xdd\x98\xb6\xff\x33\xf4\xff\x5c\x23\xef\x4f\xff\xf2\xb4\xe4\xf0\xd8\x54\x03\x89\x89\x56\x2e\xca\xfb\xcb\xcf\x31\xf6\xfe\xc4\x4f\x9d\x41\x9c\xc4\x3f\x30\x26\xef\x1c\x93\x3e\x00\x0f\x25\xf6\xeb\xe4\x98\x48\x41\x09\x2a\x98\x20\x65\x60\xc6\x69\x46\x7f\x3d\xc7\xd6\xd5\x39\x6f\x89\xbd\x4d\xac\x2d\x51\xed\xee\x68\xf2\x2d\x89\x7f\x50\xb3\x32\xa2\xc6\xe4\x3b\x6c\x44\xbd\x18\xb3\x82\xf4\xd8\xc6\xa7\x4f\xdd\x10\xb4\x69\x94\xea\x09\x7e\xe9\x70\x91\xd3\x81\x13\x37\xc1\x85\xd3\xe4\xbb\xc4\xc9\x69\x61\x43\xa1\x34\x28\x02\xde\x09\x1f\x57\xa4\x1b\xc8\x23\x9d\xd4\x63\x19\x1a\x9f\xe1\x63\xd9\x50\x28\x0d\x1d\xb1\x86\xc0\x6b\xb8\xc8\x24\xf3\x09\xff\x19\xbc\xd4\xb7\x61\xd5\x10\xd1\xe5\x6e\x90\xca\x76\x31\x4c\xe6\xd7\x1f\x15\x89\xa0\x84\x10\x98\x02\xf1\x43\xe2\x75\x37\x71\xa2\x3f\x7a\x7e\x77\x8c\x06\x03\xf0\x14\x32\x6e\xeb\xf5\x65\xfe\x85\xfd\x0b\x78\x0e\xad\x71\x7e\x77\xf0\xdc\x77\x85\xa5\xcb\x43\x0f\xe4\xe7\x54\x98\x7e\x47\x3c\x87\xf7\xc1\xb7\xc3\x74\x68\x4f\x3b\x0c\xb6\xc3\x7a\x54\x27\xbe\xbd\xff\x12\xbe\x43\x2b\xa8\xdf\x9d\x3c\xe3\x6d\x91\x1d\xca\x03\xf2\x50\x67\xbf\xce\x2f\x12\x29\x3b\x5f\x2f\x82\x9d\x8d\x2f\xe1\xea\x85\x6a\xc9\xc5\xfb\x29\xf5\xbe\xa0\x09\x8b\xc0\xdb\x78\xc0\xba\xd0\x75\xef\xa4\x2f\xe0\xd6\x2f\xf9\xed\xe7\x1d\xf4\x02\xed\x39\xdc\x85\xba\xe1\x3b\x16\xd9\xf3\x5e\x22\x41\xf4\x00\xdd\x1b\xff\xe8\x2a\xfc\x2b\xfe\xc9\xf6\x99\xed\x8b\x0f\xf8\xf1\xc3\x79\x43\x19\xbf\x1c\x17\x7e\x53\xee\x1a\x3f\xa7\x6e\x0e\x8b\xde\xe0\x4e\xc1\xdd\xe1\xe6\xf2\x8c\xfd\x79\x17\x09\xb1\xc3\xe3\x36\xbc\x67\x1c\x16\xbd\x61\x12\xfa\x61\x71\x1c\x3e\x7f\xff\x97\xf0\x54\xdf\x89\x8d\x43\x25\xe3\x77\x8f\xa4\xd3\x6b\x3a\x70\x54\x24\x82\x3f\x8c\x97\x6d\x66\x48\x1c\xef\xc6\x6b\x0e\x81\x6a\xe8\x9d\x13\xe9\x21\x71\x16\x14\x77\xc8\x9b\xff\x3b\xf0\xbe\x8d\xa6\x86\xde\x29\x09\xfe\x19\x58\xbb\x3c\x6a\x7f\x9c\xe3\xd8\x8d\xb3\x77\xc2\x79\x78\x8f\x7a\x47\xac\x87\x49\x60\x6f\x8b\xf9\xb0\xde\xf5\xbf\x07\xf7\xdb\x28\x75\xe8\x1d\x93\xcf\xbb\x40\x7c\xe8\x5c\x53\x60\x71\xe1\xba\x62\x0b\x28\x61\x1c\x8c\x87\x89\x30\x6d\xc8\xc8\xd0\xb7\xd2\x37\x05\x35\x0a\x1c\x62\xb5\x6f\xff\xa8\x30\x36\x31\xee\xbe\x84\xe8\x88\xb8\xf0\x50\x12\x11\x42\xf3\x0f\x85\x26\x95\xe6\xd7\xca\x0b\x80\x23\xa6\x0e\x4c\x5d\x3e\x8c\x9b\x93\x15\x9b\x3e\xf9\x3f\xb7\x6d\xc3\xbd\x01\xab\x96\xa8\x73\x68\xb8\x73\x49\xf0\x40\xfc\xd8\xc9\x3f\x77\xc4\xcf\xb5\xc1\xe0\x6e\x11\x6c\x2f\x9d\xfe\xb1\xb6\x3e\xc3\xf3\xce\x18\x9e\x55\x3f\x9e\x1d\x30\x79\xc3\x54\x5a\xed\x5a\xb5\xcc\x70\xe4\x14\x0e\x1c\x27\xc3\x34\x98\x79\x07\x1c\xfd\x0d\x46\xbd\xbc\xbd\xde\xb9\xd2\xfd\x6e\xf9\x99\x40\x56\xcd\x7f\xb8\xe0\x91\x51\xe5\xa1\xcd\x5b\x9f\x78\xa6\xec\xf6\x7c\x3d\x2e\x63\x8d\x7b\x02\xd5\xf7\xe8\xe3\x13\x9e\x7d\x62\x0d\xce\x93\xf9\xab\xeb\xc7\xdf\x7f\x09\x77\xa7\xa7\xe0\x7e\x26\xee\xe7\x4a\xa7\x77\x2d\xda\xef\x71\xf7\xb8\x3f\x2e\x71\x7e\xf1\x3a\x5a\xd3\x87\xbb\x6c\x77\x5b\xc0\x1f\x42\x20\x0c\x26\x49\xd9\xe2\x90\x96\x77\x67\xed\x1d\xc2\xea\x0c\xb7\x53\xe1\x61\xc2\xc9\x93\xc3\x6b\x32\x0c\xc2\x37\x0a\x8c\x77\x85\xef\x90\xda\x7c\x47\x84\x07\xaa\xf4\x1d\x31\x1e\x42\xb3\x07\xe2\x3c\x85\xdd\xd8\x77\x27\x9c\xef\x46\xbb\x6f\x83\xfe\x6d\x55\x7c\x18\x2a\x9e\xba\xb3\xa6\xff\xf7\xd0\x32\x94\xb6\xdf\x35\x2d\x03\x54\xfe\xae\x69\x19\xa4\xf9\xf2\x19\x2e\x35\x42\x8e\x7c\x0f\xac\x1e\xf5\x6e\x87\xaf\xb0\xcd\x22\xec\x10\x39\xf9\x04\x16\x60\xe7\xa4\xec\xd4\x78\xa5\x7d\xdf\xf0\xfe\x67\x7e\x27\x23\xba\xdf\x2e\x8d\x13\xe7\xfe\xe2\x74\xcc\xa7\xca\x1b\xef\xd0\xaf\xa7\xb5\x08\x9d\x7f\xab\xda\x72\xec\x83\xf4\x3c\xeb\xa2\xa3\x27\xc7\xbc\x12\x70\x85\x3b\xf8\x8b\x99\xdf\xd1\xdf\xfd\x6f\xab\x55\x9e\x9f\xc8\xa2\x35\xc2\x21\xf9\x9e\x68\x3d\xea\x51\x9f\x8c\xfe\x7a\x74\xb5\x13\x6f\x44\xad\x42\x54\x70\x59\x68\xe8\xc2\x8f\x44\xd5\xe4\xdf\x1c\xa4\xa7\x9d\xad\x2c\x7f\x3a\x90\x46\x7b\x8c\x54\x4f\x68\x15\x3a\x7b\x73\x7e\xf9\x03\x67\xb4\x64\xb0\x46\x1e\x5d\xc3\x1f\x7d\x70\xdf\x7e\xeb\x35\x40\xd8\x6f\xbf\x2e\xa4\x09\x67\xe4\x1b\xe3\xd8\xfe\x41\x79\xe7\x8b\xe3\x04\x99\x51\xa8\xf5\x77\xa7\x90\x1d\xfb\xb0\xdf\xef\x90\xcf\xb6\xc6\xb7\x4f\x4c\xcc\xf7\xfd\x7b\xd5\x1f\x76\x04\x7b\x76\xec\x7e\x79\xbc\x4c\xa3\x7f\xc1\x0c\x7a\xe1\xa7\xeb\xd7\xb0\x76\xe1\xc2\xf4\xac\x47\x9f\xfe\xcd\xc7\x78\x30\x73\xce\x77\xcf\xdb\x76\x47\x92\x0b\x8c\xd4\x39\x8b\xe9\x6c\xfa\xc3\x4f\xff\x0e\x04\x36\xdb\xaf\xf3\xe5\x62\x28\xa8\x60\xb2\xac\x0d\xae\x63\xb9\x9c\x27\x0b\x3a\x0f\x4a\xf3\xd5\x68\x8d\x7d\xb7\xda\x73\xe2\x66\x4d\xa1\xf1\x87\x4f\xdb\x4f\x1c\x7a\xeb\xa9\xcd\x4f\x7f\xf7\xca\xc1\x73\x87\x1e\x5b\xdf\xd0\x46\x2f\xcd\xd2\xcc\xfb\xf5\x5b\xab\x96\x54\x6c\x9b\xb0\x32\x08\x37\x3c\xb3\x0d\x3f\xec\xfd\x8f\xc3\x2d\xfb\x7e\x1f\x11\xdc\x6e\xde\xfa\xe5\x93\xdd\x9f\x6e\xa9\xe9\xdc\x8d\x7e\x3b\xf7\xed\x5a\xb2\x7e\xd7\x41\x1a\xf0\x18\xbb\x5f\xc3\x8b\x3f\xc5\x49\xf9\x30\x07\x7e\x10\x04\x70\xbb\xde\x0d\x7a\x0d\xdb\x97\xe1\x4f\x0d\x3f\x86\x23\xb7\xd1\xe9\x68\x63\xec\x90\x6d\x38\xf5\xdb\xd1\xc4\xa0\xfe\xc8\x20\xf8\x6e\x63\x32\xee\x34\xa8\x20\x58\x86\x3f\x7c\x2f\xc3\xd1\xc4\xd0\x7d\x0a\xa9\x9d\xe1\x7a\x0f\x72\x3b\x8d\x77\x6a\x47\xdd\x9f\x94\x21\xfa\x04\x43\x36\xd2\x37\x66\x42\xe8\x49\xbe\x07\x13\x45\x0d\x78\xb9\x6e\xcb\x72\x6e\xac\x74\x6e\x24\xa5\x27\xef\x99\x9a\x25\x59\xfa\xc7\xfa\x67\xa3\x3f\x9f\x78\x2e\x5d\x28\x9a\x36\x4b\x32\xdf\xc5\x41\xc6\xdf\xcc\x55\xe9\x3f\x9f\x26\xc1\x39\xc2\xf7\x60\xba\x78\x06\x46\xc2\x68\x76\x6e\x61\xa0\x5a\x42\x4d\x21\x2a\xb4\xee\x91\x95\x1e\x59\xf3\xf0\x7d\xab\x5f\xaa\x88\x3a\x9e\x72\x70\xe2\xc3\x0e\xb8\xa2\x18\x94\x51\x5e\xf8\x70\x50\xc4\xfe\x25\x6b\x51\x29\xc3\x66\xfb\xbd\x2e\xf1\xb7\x30\x5b\x3c\x03\x1c\xf8\x38\x65\xe9\x86\x61\xb8\xfb\x3e\xac\x4b\x8c\x01\x1a\x07\x44\x2c\x9f\x11\x27\x3b\x20\xfe\x56\x43\x03\x16\xca\x30\x27\xe9\x67\x3b\x7d\x0b\x47\x1b\xf9\x6e\x2c\x13\xcf\x80\x0a\xc6\x4b\x56\x81\xf1\xfa\xb8\x10\xe2\xdc\x19\x37\x85\x48\xea\xef\x3f\x4c\x5b\x8d\x49\x6f\xc6\xcc\xbb\x67\xfa\xf8\x05\xd3\x56\x86\x3c\x97\x15\x9d\x9a\x98\xa0\xd1\xc5\x8d\x0b\xbc\x27\x36\x2b\x61\x8a\xd4\xf6\x3d\xb1\x93\x26\x26\x4d\x0e\x8f\xe5\xbb\xbf\x09\x0d\x0f\x5d\xb6\xf6\xc9\xd0\x09\xa1\x91\x89\x58\xeb\xc0\x62\xda\x2c\x19\x0b\x22\xe3\xa0\xf0\x76\x48\x78\x28\x0c\x1c\x61\x65\x98\x26\x8b\xdf\x0f\x7e\x60\x6d\x75\xff\x66\x88\x26\x60\x4d\xc3\xe8\x67\x98\x6c\xfb\xe0\x87\x0e\x07\xdf\x25\xe4\xa1\x5b\xd8\x1b\xbf\x32\xfa\x6c\xd8\x6f\x72\x06\x90\x12\x1a\x98\xf2\xe4\xdc\x80\xc9\xbb\xef\x61\x67\x6f\x30\x39\x69\x15\xde\xc0\xb1\x9b\x48\x8d\x2c\xfd\x08\x41\xb5\x4a\x3b\x05\x1d\x82\xc9\x38\xe2\x9f\x3e\x71\x6d\xfc\x06\x49\x1c\x04\x02\x52\x9f\x4b\x1d\x33\x63\xa7\xab\x6e\x02\xab\xeb\xed\xb0\x56\x67\x2a\xe0\xa8\xba\xbb\xb8\xe4\x6c\xf4\x91\xd9\x52\xcd\xaf\xd5\x15\xaf\x06\xcc\x38\x18\x2d\xc9\xef\x6b\xfe\x2c\x36\x28\x52\xc0\x0b\xc6\xb0\x9d\xa6\x03\xf6\xe9\x39\x60\x68\x23\x74\xee\x67\x9c\xd0\xaf\x13\xe3\xb2\x12\xa2\x75\x71\x53\x57\xa7\x16\x3c\xf1\xe4\xa3\xf5\x4f\x04\x1f\x0c\x7b\x18\x03\x13\xe3\x64\x89\xb1\x6d\x7b\xb1\xe9\x93\xc9\xa4\xb1\xf1\xcf\xac\xb9\x77\xac\xe9\xe9\xc9\x8b\x9f\xa7\xb3\xfb\x62\x12\x47\xbb\xf8\xb3\x98\x20\x1e\x04\x2f\x87\x4e\xba\xb5\x6b\xd4\x8c\xea\xd7\x58\xd7\x0c\xd6\x58\x6c\x6c\x08\xd1\x85\xfc\xa5\xaf\x8d\xd8\x54\x16\xfc\x26\x34\x34\x58\x9c\x90\x09\xdd\xcc\x77\x63\x85\x78\x10\x54\x6c\x9f\xf3\x10\xb2\xe2\x8c\x1a\x05\xdd\xec\x92\x52\x49\x88\x39\x2b\x3a\xf5\x9e\x04\x4d\x54\x9c\x5a\x1d\x4a\xaa\x42\x1d\x22\x5a\x53\x13\x3a\x21\x34\x56\x8f\xe9\xec\x5e\x3a\x89\xbf\x3d\xa8\x15\x0f\x32\x1b\x62\xfc\x15\xdc\xac\x51\xe6\x70\xf6\xdc\x69\x05\x69\x31\x93\xa6\x8b\xa1\x0d\x0d\xff\x35\x63\xbe\x7c\xe2\x07\xab\x2b\xa6\xa1\xd6\x23\xf8\x6e\xea\x2a\x36\x6f\xdb\x76\x8d\xd5\x65\x6b\xbd\x78\x8c\xe4\xcf\x71\xed\x8a\x2d\xe0\x05\x63\xe5\xdb\x34\x7f\x66\xc6\x81\x91\x77\x93\x5f\x08\xba\x3b\x67\x12\x3f\x0f\x97\xa1\x32\xb9\x61\x70\x19\x90\xb7\x0d\x81\xcb\xa0\x0c\x4d\xc2\xe5\x2c\xd7\xc8\x70\xf1\x61\xe7\x4c\xc0\xdd\x64\xc2\x2e\x04\x86\xce\x7b\x9d\x6a\x3b\x74\x86\xdb\xbf\xcd\x40\xb6\x37\xf8\xce\xbd\x85\x01\x4d\x0e\xe8\x1b\xb8\xb5\x38\xa8\x17\xc0\x61\x24\x7f\x84\x6b\x53\x24\x82\x37\x84\x40\x84\x73\xc7\xf3\x1d\x47\x05\x30\xf2\x4e\x63\x00\xc2\xc1\x3b\xf5\xf6\xe5\xb6\xeb\xef\xba\x6d\x57\xa0\x8e\xbc\x8b\xb1\x93\xfe\xcd\x0f\x39\x06\x2d\xb7\x7f\x8e\xb5\x3f\x8e\x9d\x8e\x7b\x37\x23\x50\x03\x5a\x1f\x3c\xde\xe4\x6c\x79\xd8\xb1\x7a\x77\xba\xef\xdc\xae\xff\xd0\x54\x0f\x35\x3e\x37\x74\xcb\xae\x91\x38\xc4\x36\xfe\x2a\xff\x9d\xd0\xe6\xf0\x10\x01\xa3\x50\xab\xd3\x2a\xd8\x83\x6d\x22\x97\x2c\x3c\xa6\x09\x3a\x92\xae\x19\xfb\xfe\x3c\xad\xb0\x35\xc8\x7b\xd4\x81\x15\x2b\x56\xac\x00\x76\xf6\x11\x7a\x25\x91\x93\xdb\xf8\xc5\xa3\xee\xf9\x07\x09\x65\xab\xfd\xe0\x77\xde\x1b\xdf\x74\xbe\xad\x3e\xb6\x56\xcf\xeb\x1e\x5b\x80\x80\x87\xe3\x44\x7a\xf6\xdd\x63\x8b\xed\x2d\x00\x2f\x8d\xd5\xc7\x12\xee\x79\x1d\x8a\x41\x05\x6e\x5f\x9e\x6b\xf9\x33\xc0\x96\x5f\xf2\x01\x00\x44\x7a\xd4\x10\xc9\x69\xe1\xb2\x10\x05\x49\x7c\x09\xa4\x89\xc5\xb0\x4f\x28\x82\xd9\xd8\x05\x97\x49\x16\x64\x91\x2c\x7b\x11\x5f\x02\xe7\xf9\x12\xa8\x21\xde\xf6\x56\x52\x0b\x06\xe2\x0d\x91\xa4\xc7\xde\xc2\x97\x40\x05\x5f\x82\xe1\x7c\x09\x88\x7c\x09\x44\xf3\x25\xe0\xcd\x97\x40\x26\x5f\x02\xb5\x7c\x09\xec\xe7\x4b\x20\x9f\x2f\x81\x42\x56\xde\xdb\xde\xc4\x97\x40\xa5\x04\x47\x7a\x73\xe5\xb0\x57\x3c\x05\x6b\x78\x93\x7d\x33\x7f\x06\xb2\xf9\x43\xd0\x28\xe4\x40\x36\x1f\x0c\xd9\xdc\x39\xc8\x16\xd6\x40\xa3\x50\x0e\x39\x64\xa7\xbd\x9b\xc4\xd0\xe3\xbc\x09\xb2\xb9\xf3\x90\x2d\x1e\x81\x2c\xa1\x15\xb2\x84\x13\xd0\xc8\xd7\x43\x36\x7b\xef\x80\x6c\xde\x0b\x74\x3c\x81\xc3\x42\x29\xb4\xf0\xa5\x70\x54\xec\x81\x8b\xbc\xd1\xbe\x83\xf7\x83\xa3\x7c\x8a\xfd\x3a\xc9\xb2\x7f\x47\x7a\xe0\x12\xc9\xb2\xaf\xe1\x4b\x20\x9b\x8b\xb4\xa7\xf2\x65\x24\x81\xdf\x0c\x45\x7c\x0b\x24\x70\xcd\xec\x5d\xc4\x51\x28\x22\x9b\xed\x41\x7c\x0b\xe8\xa5\xbf\x13\x5f\xe9\xa1\x94\xbb\x09\x46\xe2\x0b\x46\x05\x40\x82\xf4\x77\xbe\x56\x2a\x6f\x3f\xcf\xea\xc4\x40\x02\x57\x01\x5e\xa4\x15\xf2\xf8\x16\x28\xe7\x8e\x42\x91\x70\x0a\x2a\xb8\x4b\xf6\x0e\xee\xa8\x3d\x85\xdb\x6a\xbf\x42\xce\x80\x9a\x2f\x21\x01\xe4\x8c\xbd\x83\x2f\x81\x0d\x32\xef\xed\xd7\xf9\x12\xb8\xc8\x97\xd8\xbf\xe6\x4b\x60\x1f\x5f\x02\xd5\x52\x19\xee\x2a\x18\xf9\x32\xec\x12\x5b\xa1\x9e\x74\x42\x2b\x77\x0e\x72\x18\xff\x6b\xc1\x20\xfd\x8d\x0b\x87\xb3\xdc\x1a\x87\x4c\xce\x43\x3e\x39\x0f\x15\x7c\x19\xf1\xe5\xdb\xed\xe7\x85\x24\xe8\x22\xde\xb0\x1f\xf7\xd9\xb3\xc8\x79\xb8\xe9\xa8\x1f\x20\x7a\xc0\x53\xa2\x07\x2c\x10\xf5\xf0\x30\x57\x6e\xbf\xc9\xf8\x3e\xc4\x23\xee\xb4\xd7\x4b\xb2\x90\xe4\xe0\xfe\x30\x39\xb8\x3d\x42\x0e\xa4\x3a\xe5\x30\xf0\x91\x68\x11\x4e\x40\x85\x24\x0b\xf7\x87\xc9\xa2\x1e\xb2\xf9\x03\x76\x60\x7c\x1f\xe2\x11\xb7\x42\x91\x24\x0b\x49\x0e\xee\x8f\x2c\x87\xbe\x87\xdf\x0a\xb9\x2e\x39\x0c\x7c\x24\x1d\xab\x85\x44\x49\x16\xee\x8f\x24\x0b\x49\x66\xec\x2d\xd1\x2b\xb5\x39\xf0\x7d\x08\x1a\x99\x2e\x0c\xf3\x66\x3a\xda\xc2\xde\xa9\xd2\x9b\xe9\x2b\xbd\xf3\x5b\xd2\x67\x49\xa7\x86\x7d\x97\x43\x8e\x44\x8f\x50\xce\xe0\x27\x30\x3e\xfb\x0e\xf7\xb6\x37\x39\x7f\xe7\x4f\xd8\xbb\x79\x0d\x24\x48\x36\x22\xe9\x29\xb3\x93\x9b\x60\x64\xcf\x79\xc8\x96\x74\x56\x7e\xdb\x5f\xed\xf7\x7b\x21\x7b\x07\x10\x5f\x10\x25\x39\xb2\xb6\x07\xbe\x63\xe0\x01\xd7\xcf\x92\x5c\x6b\xa1\x68\xe0\x5b\xbc\x0c\x8d\xe2\x77\x50\x24\xd9\xa0\x64\x07\xf2\xdb\xbe\xc7\xf5\xbb\x17\xe8\x24\xdb\x18\xf6\x4d\xe0\x25\xd2\x0a\xb3\x25\xdb\x65\xf6\x43\xa0\x8d\xb4\x42\x24\xd3\x97\x16\x28\xbf\xdb\xb7\x64\xef\x92\xcd\x49\x3a\xc6\xe4\xeb\xb0\x7b\xc9\xf6\x06\xbe\x49\x2a\xa5\x8c\xa6\x7c\xd8\xc7\xd7\xcb\x7c\xe7\x8f\xc3\x16\x7e\x07\x98\xf9\x43\xf6\x5b\x6e\xb2\x4e\x15\x6e\xc0\x3e\xbe\x41\xf6\x0d\x7c\x19\xe4\xf2\xc1\xe0\x21\x64\x40\x16\xbf\x10\x52\xb9\x73\x76\xc9\x67\x02\x93\x61\x29\x34\x28\x44\x48\x20\x35\x50\x22\xc9\xc6\x29\x07\xc6\xef\xef\xec\x5b\x14\x07\x60\xb3\xd0\x6a\x4f\x74\xf2\x52\x38\x0e\x8d\x92\xbe\x79\x78\x41\xa3\x58\x08\x45\x82\x16\xf6\x31\x7f\xe2\xf0\x65\x5c\x05\x04\xf0\x31\xf6\x2b\x24\x17\x62\x18\x5f\xb2\x60\x9f\x83\x3f\x87\x85\x73\xd0\x22\x10\x28\x17\x2e\xc2\x4e\xbe\x0c\x8e\xf2\x89\xb0\x8f\xfb\xde\x9e\xe2\xa2\x33\x11\x7c\x18\x7e\x9d\xf6\x4e\xae\xd3\x6e\xe6\x93\xec\x97\xf9\x24\xf0\xe1\x0e\x01\x70\xa5\x00\x7c\xbd\xfd\x3c\xaf\xc1\xe3\xbc\x06\x8e\xf0\x1a\xd8\x28\xc5\x00\xcf\x1d\x90\xed\x71\x0d\xb2\x3d\x62\xa1\x48\x24\x90\x2d\x5c\x85\x6c\x5e\x03\x46\x45\x37\x64\x29\x0e\x43\x96\x78\x08\x12\x9c\x36\xe2\xd4\x3d\x97\x2e\xdc\xa5\x8c\xb8\x1b\x90\x38\xd0\xde\x24\x7f\x23\xd9\x3c\xe3\xa1\x57\x9f\x3d\x38\xf9\x37\x50\xdf\x24\xda\xb8\x4e\x7b\x95\xa4\xeb\xee\x38\x3b\xeb\x29\x62\x20\x5b\xf0\xb6\x7f\xed\xd4\xdb\x41\xed\x9c\x80\x0a\xe6\x1b\x06\xda\xfd\x00\x7b\x75\xd8\xd9\x91\x41\xb4\x3a\xf1\xe8\xa7\xef\x90\x30\x90\x56\x37\xfd\x6e\x20\xad\xb0\x80\x5f\x68\xa7\xdc\x79\x7b\x95\xcb\xce\x77\x3b\xfc\x48\x30\xe4\xf1\xcd\xb0\xc8\x25\xbb\x01\xf8\x0c\x67\x77\x2e\x3c\x1c\xfa\x4e\x8e\xd8\xf7\x0b\x39\x90\x40\x4e\xda\x0f\x49\xbc\x51\xe8\xa1\x48\x7a\x18\x3c\xa6\xcf\xf6\x93\xdc\x79\x48\xe1\x89\xfd\x94\x84\x17\x57\x61\xbf\xc2\xed\x80\x7a\xae\x06\x32\xf8\x33\xc0\x0b\xa5\x90\xca\xca\xb2\x76\xed\x7b\x9d\xfe\x44\x38\xc7\xf8\x2a\xd1\x1b\xc3\xc5\x80\x9a\xf7\x83\x35\xcc\xbe\x4a\xa0\xdc\xe1\xb3\x13\xe4\xf8\x69\xbf\xc1\xf5\xd8\xaf\xb3\xb2\x52\x4c\xfc\x1e\xc2\x25\x79\x0b\x25\x90\xc8\x35\x41\x12\xb7\xc5\x4e\xf9\x6e\x3b\xe5\xd7\x48\xbe\x9c\xd9\x9f\x9e\x3d\xb9\x50\xc4\x1d\x85\x04\xee\x24\xe4\x3b\xfc\x74\x82\x23\xee\x06\x30\x5b\xca\xb3\x9f\x26\xa7\x20\x9c\xb4\x41\x10\xf1\x01\x1f\xfe\x06\x8b\xc1\xe5\x8e\x27\x81\x6f\xb1\xc7\xb0\x3a\xd7\xe4\x58\x20\xd6\x40\x91\xe8\x01\xf9\x42\xa1\x14\x97\xed\xc7\xb8\x85\xf6\x63\xec\x1d\x63\x3f\xc7\xc5\x80\x37\xd9\x0c\xd1\x64\x33\x64\xf1\x8b\x20\x41\x7a\xb8\x0a\x7b\x3b\xf1\xa3\x94\x3d\xbe\xa0\x26\x7e\xb4\x9c\xb4\xda\xaf\x91\xff\x1f\x6b\xef\x03\x9f\xf5\xd8\xfe\x71\xbf\xcf\xf3\x3c\x8e\x6b\x2b\xc3\x64\x18\x2d\x2d\x2d\x16\x4b\xd1\x52\x69\x94\x4c\x26\x93\xc9\x64\x32\x4c\x26\x2b\xab\xa6\x96\x96\xd6\x1f\xb7\xd1\xd2\xd2\x68\xb2\x3b\x93\xc9\x64\x32\xdd\x93\xc9\x30\xee\xb9\xe5\x6e\xa9\x58\x5a\x2a\x15\xa3\x61\x31\x99\x4c\x86\xb5\xeb\x79\x5d\xd7\x96\x9f\xdb\xcd\xcf\xef\x79\x5e\x0f\xaf\x4f\x9f\xf3\xfb\xbd\xce\xbf\xc7\x71\x7c\xcf\xf3\x38\x8e\xef\xf5\xda\x55\xca\x71\xb2\x8a\x60\xb9\x97\xb1\xb2\x95\xfb\x5c\x95\x77\x99\x6e\xf2\xae\xf6\xb1\x5b\xc5\x44\xbf\xae\xfa\x79\x3f\xf5\xd9\xa2\x5b\xef\x4d\x76\xc3\xb9\xcf\x0d\x67\xad\x1b\xee\x7d\xdb\xbd\x45\x5f\xbf\x7e\x12\x99\x20\x53\xb8\x48\x52\x98\x20\xef\xfb\xfd\x88\xe5\xee\xb0\xf7\x4d\x37\xd6\xbf\xc6\x09\x6e\x38\xbd\xdc\x70\x56\x05\x9c\xc3\x84\x80\x38\x26\x04\x6c\x62\x82\xae\x60\xbc\x3b\xc8\x78\xcf\x40\xc6\x7b\xa6\x79\xbb\x4b\x1b\x83\xa5\x88\xc1\xae\x9d\xde\xb2\x94\xc1\x52\xc9\x39\x7e\x9c\x4a\xa9\x9c\xca\x5a\xd3\xec\x2d\xb3\xfb\x58\x6b\xf7\xd1\xdd\x07\x57\x45\x89\x6c\x67\x93\x9b\x01\x26\x95\x39\x76\x1f\x73\x7c\xdc\x89\xcf\x81\x9e\xc0\x79\xf6\x2c\xde\xb1\x67\x51\xd5\xe9\x93\xcd\x92\x65\x24\xf8\x31\xcd\x2c\x94\x69\x66\x33\x30\x52\xe2\xcc\x32\x7f\xd6\x1c\xef\x61\x68\x3f\x00\xed\x63\xa0\xfd\x63\x68\xcf\x81\xf6\x2f\xc1\xbb\x11\xbc\x0f\x83\xf7\x69\x68\x4f\x86\xf6\x22\x68\x5f\x08\xde\xbe\x32\xcd\xec\x34\x6d\x26\x56\x56\xda\x3e\x66\xb6\x77\x8a\x4c\x33\x63\x64\x9a\xb9\x0f\xda\x3f\x01\xef\x36\x37\x8d\x72\xd3\xcc\x7d\x6e\x24\x73\xdd\x52\xfa\xda\x43\xec\x73\x49\x14\xff\x19\xa0\xfd\x7a\xf0\x76\xf1\xad\x07\xda\x87\xc1\x91\xfd\xd0\x9e\x00\xed\xa3\xed\x1a\x6f\x25\x78\x1f\x84\xf6\x57\xa1\x7d\x0f\x1c\x39\x02\xde\x47\xc0\x3b\xee\x3f\x71\xa4\xaa\x13\x15\x70\x24\x12\x8e\x7c\x06\xed\xef\x40\xdb\x8b\xe0\x9d\x04\xde\x04\xf0\x3e\x0b\x5c\xd5\xc1\xbe\xba\xde\x03\xe0\xbd\x18\xda\x7d\xa1\xc4\x48\xf0\xae\x81\xb6\xe3\xc0\x5b\x0a\xde\x99\xe0\xfd\x77\x07\x38\xbb\x83\xdb\x37\x41\x7b\x21\xb4\x97\x74\xca\xe2\x2e\xf0\xae\x87\xf6\xaf\xa0\x3d\x0d\xda\x97\x43\xfb\x7c\x68\x1f\xd7\xb1\x06\xef\x45\xd0\xb6\x1a\xda\xaf\x84\xf6\x79\xd0\x5e\x0d\xde\xe1\xd0\xbe\xaf\x43\xe6\x47\xde\x87\x23\x3e\xf9\x5f\x0b\xed\x27\x41\xfb\x8d\x9d\xeb\x3f\xd0\xb1\xfe\x23\xab\xe1\xc8\x93\xd0\x9e\x07\xed\xab\xe0\x48\x3c\xb4\xef\x84\x23\x3b\xa0\xfd\xeb\x8e\xf6\xed\x29\x70\xc4\x27\xf7\xed\xe0\x6d\xeb\x18\xd3\xdb\xe8\x0b\x08\xc0\x3b\x00\x08\x03\x6f\x36\x78\x8f\x83\xf6\x16\x38\xf2\x0a\xb4\x5f\x03\xed\xbe\xf5\xc7\x82\x37\x09\xbc\xa3\xe1\x48\x7b\xc7\xbd\x23\x7d\xc0\x1f\x77\x5c\x06\xde\x65\xd0\xfe\x36\xb4\xef\x06\xaf\x85\xf6\x5e\xc0\x40\x30\x53\xa0\x7d\x09\x1c\xf9\xb4\x23\xf6\x68\xff\x19\xe8\x05\x5e\x9f\xde\x56\x82\xb7\xb5\x63\x2e\xed\xcb\xc0\xdb\xa3\x53\xf6\x6f\x82\xb7\x3f\x78\x7d\xf5\xc6\x80\x97\x8e\xb2\x4f\x6e\xde\xe4\xce\xfb\x13\xa1\xfd\xb0\x79\x87\x56\xf3\x8e\xf7\x7e\xf3\x8e\x77\x8f\x7f\xef\xf1\xf9\x8c\xc5\xde\x43\xfe\x38\x63\xbe\x4d\x93\xf9\x66\xbd\x6f\x3f\xf3\xf9\xc2\xb2\x9c\x91\x9e\xae\x8c\x74\x0f\x73\x83\x27\x84\xeb\xb5\x1f\x23\x3d\xb1\x24\xfa\xf6\x97\xa3\xf1\x87\xcf\x27\x92\xf9\xde\x4d\x7e\x7f\x77\xb8\xb7\xc9\xb7\x4f\xeb\x46\x96\x1d\x3d\xcb\xfd\xbe\x71\x67\xec\x21\xbd\xbd\xfb\xfd\x67\xb8\xcf\x57\xf3\xf9\xb3\xfd\xbd\x9f\xfa\xce\x65\xdf\x5e\xec\xb1\x2c\xf3\xc5\x1d\xda\xcc\x3b\xba\xc7\xdb\xe4\x6f\xef\xf3\x45\x96\x31\xc1\xb7\x0f\xfa\xf7\x36\xdf\xb8\x25\xdc\xe7\xbb\x27\xab\xbd\xdb\xdc\x7a\xc6\xca\x0c\xe2\xfc\xfb\x64\xc7\xfe\x39\xd4\xb7\x67\xf8\xea\xf9\xfd\xb8\x83\xde\x25\x3e\xdf\xde\x1d\x66\x82\x5b\xc6\x58\xff\xbe\xff\x29\x63\x64\xb9\x77\xbb\xbf\x7e\x19\x13\xdc\x44\xc6\xf8\xfa\xd4\x69\x4c\x90\xe3\xbc\xa7\xea\x26\x96\xe8\x97\x1d\x7d\xf8\xc7\xf2\xb5\xf1\x7d\xfe\x25\x13\x64\x2c\xa9\xb2\x9a\x41\xd2\x8b\x2a\xbd\x88\x04\x3f\xa7\x30\xc1\x73\x17\x93\xe5\x53\x42\x74\x21\xe5\xfe\xfa\x65\xbc\x23\xa7\x30\x41\x7a\x92\xe8\xee\xf3\x6e\x77\x5b\x99\x26\x83\xfc\xe7\xd5\x5a\x77\x90\x71\x01\x65\x84\x04\xe0\xdd\xa6\x3d\xa8\x92\xb7\x98\x20\xad\x24\xca\x39\x0c\x93\x61\x0c\x92\xae\xde\x32\x59\xe6\xdd\x24\xa7\x78\xcb\xb4\x9c\x25\xfe\xfe\x2c\x23\x5d\x21\x83\x7d\x63\xc8\x0a\xfa\xf9\x74\xe6\x3f\x63\xde\xe9\xf0\xb7\xdc\x1a\x42\xfc\xf2\xf4\xf9\x41\xeb\x58\xe6\x97\xb7\xcf\x57\x59\xee\x9d\x7c\xd4\x2f\xf3\x73\x67\x4c\xa2\xa9\x54\xfa\xf5\xb6\xce\xef\x3b\x9c\xf5\x6b\x7c\xd2\xbf\xfd\xad\x80\xbe\xde\x37\x03\x2e\xea\xa8\xe3\xd3\x9f\xae\x24\x51\x0a\xc1\xaf\x33\x9f\xce\x7d\x7e\x5f\xa7\xde\xb5\xab\xd7\xdf\x9f\x67\x94\x77\x85\xef\x9c\xf6\xd5\xf5\xd7\xf7\xb5\x3b\xcf\xfb\xa6\x7f\x1e\x3e\x7b\xf8\xad\xce\x7d\x63\xfa\x74\x5e\x08\xbf\xea\xfc\x66\xc6\x6a\x6f\x5a\x02\xca\x3a\x7c\x26\x0d\xa2\xd2\xe3\x8b\x17\x66\xfa\xeb\x77\x0b\xd8\x4d\xa2\x2c\xf7\x96\xfb\xcf\xcd\x64\x52\x7d\xe7\x83\x2b\x63\xa0\x2c\xec\x88\x71\x3c\x6f\x7b\x3f\xf1\x9f\x93\x47\xe3\x95\xfd\x0c\x95\xf1\xde\xd5\x5a\xc8\x50\xdf\xf9\xd1\x11\x73\xfa\xcf\xbc\xed\x3e\x79\xf9\xce\x3f\xdf\x59\xec\x3f\xeb\xf6\x79\x2b\x64\x23\x77\xc9\x6c\x56\xfa\xcf\xc6\x3e\xdc\x25\x9b\x49\xd4\xed\xcc\x97\xfe\xcc\xf7\xc9\xd6\x33\x9a\xa1\x32\xd2\xbb\xf3\x68\x4c\xe5\x3f\xb7\xcb\x18\xe8\x97\xbd\x2f\x7e\x0d\xfe\x9f\x78\xd7\x73\x8e\x77\xb5\x67\x51\xe7\xd9\xbe\xdf\xcf\x9d\xf1\x13\x77\x05\x94\xb1\x4c\xb7\x93\x26\x87\x59\x24\x33\x19\xef\xf9\x92\x44\xf5\xf9\x01\x7b\xbc\x8b\x65\x94\x77\x95\xc7\x37\xee\x6e\x86\x6a\xa2\x77\xad\xbc\xef\x7d\x38\xe0\x66\x12\x3d\x53\x18\x2a\x63\xbc\x95\x6e\x95\x77\x95\xff\xd9\xf0\xd9\xe7\x51\x1f\x66\x11\x55\x6e\x05\x29\x47\xb9\xcb\xbd\x2c\x0b\xbc\x88\x09\x7a\x90\x65\xb2\x86\x09\xbe\xf1\x3c\xbd\x3a\xd8\x3f\xee\xd1\x98\xec\x13\x66\xc8\x2c\x93\x20\xc5\x66\x86\x14\xdb\xd9\x52\x6c\x97\xfa\xf6\xe4\x80\x03\xf4\x0d\x58\x4d\x5f\x5d\xef\x8b\x35\xb9\xcb\x2f\xff\xfe\xcc\x3d\x6a\x5b\x3e\x9d\xbb\x9e\x0c\x75\x9b\x19\xed\x7a\xd2\x55\x3e\x21\xd1\xb5\x31\xd4\xb3\xda\xbb\xc2\xb3\xd9\xfb\x89\xdf\x57\xf3\xe9\x61\x1f\x63\x65\x98\xcf\x87\x64\xac\xfb\xd4\xcf\x89\xbe\xd8\x5c\x4f\xa5\x52\x16\x33\x46\xe7\x90\x28\x3b\x19\xea\x09\x22\x51\xef\x67\x68\x40\x3b\x89\x9e\x65\x9d\xbe\xe2\xd6\xdf\xc4\x8e\x96\xca\x80\x1e\x0c\xed\xf0\xd5\xfc\x3e\xdb\x64\x57\xe5\xfd\x54\x4a\xbc\xcb\x65\xb0\xf7\x80\x67\x24\x95\x3a\x8a\xf1\x7a\x0e\x87\x64\x0a\x2b\xb5\x37\x87\x64\x36\x45\xda\xbb\xc3\x87\xf5\xf4\x62\x8e\x6c\x66\xf4\x51\xf6\xd9\xb8\xcf\x56\x7d\xf6\xa2\x21\x24\xca\x79\x0c\xd5\x38\xef\x9b\x92\xe2\x5d\xed\xb7\xcf\xf7\x19\xaa\x0b\x3b\xe6\xe6\xef\xab\x84\x8d\x9e\xf7\x19\xab\x2b\x3b\xe2\xc7\x3f\xf3\xc1\x7f\xf5\x39\x47\x33\xd6\xef\xbb\x75\xf2\xd1\xb1\x7e\x95\x4b\xa7\x0f\xee\x7f\x46\x7c\x3e\xef\x51\xfe\x33\x1f\x75\x1d\xdd\xfc\xcf\x76\x21\xf8\x6d\xe8\x77\xec\x7b\x66\x7c\x76\x7b\x54\x2f\xbe\x67\xc6\x67\xb7\x6e\x33\xdd\x5d\x4f\x6f\xbb\x0c\xf2\x2e\x77\xbb\xbd\x15\xbe\x67\xcc\x6f\xe7\x8b\xfc\xbe\xe2\x04\x4f\x19\x13\x3c\xdb\x98\xe0\xa9\xa4\xc5\x03\xcb\xa5\x98\x26\xb7\x87\x15\x01\xc3\xbc\x6f\x7a\xee\xf3\xae\x0e\x58\x4d\xa2\xe7\xb0\xdf\xd7\x5e\x26\x6f\x32\x41\xc7\x50\x29\x6f\x33\x4e\xc6\x33\xd3\xb7\xd7\x6a\x3f\xef\x9b\x32\xce\xbb\x3a\x40\xbc\x6f\x7a\xce\xf3\xae\xf6\xf8\xf6\x80\x1e\xde\xed\x9e\xb9\xde\x72\xcf\x78\xef\x4e\xff\xfc\x7d\xe3\x1c\x8d\x2d\x3b\xf4\x3f\x34\x60\xb7\xf7\x4d\x4f\xac\x77\x75\xe0\x58\x16\x7b\xe6\x32\x54\x67\x93\x28\xab\x19\xaa\x17\x31\xd6\xc7\xee\x53\xef\x0a\x1d\xe5\x5d\xea\x59\xea\xf7\xd3\x4e\x75\x9f\x33\x41\x16\x32\x4c\x16\x32\xc8\xcd\xf1\x3f\x73\xd8\x6e\xde\x83\xd6\xe3\xed\xed\x36\x32\xd4\x8d\x26\xd8\x67\x3f\xb2\x9e\xa1\x52\xc5\x04\xb7\xd3\xbb\x5f\xee\x23\x48\xee\xc3\xca\x7d\xde\x1d\x9e\x03\x0c\x93\x41\x8c\x94\x7b\x99\xe2\x93\xa7\xbf\xcd\xcf\xde\x4a\xf7\x33\xa3\xdd\x14\x66\x49\x31\xb3\x64\x15\x83\xf5\x73\x46\xfb\xd8\xad\x61\x8e\xce\x65\xb1\xbb\xcf\xbb\xcd\x1f\xf3\xcd\xa7\xaf\xab\xf4\x96\xb8\xd1\x0c\x73\x6b\xbc\x4b\x65\x15\xc3\x7c\x7d\x68\x10\xcb\x65\xb6\x77\xad\xab\x22\x49\x0e\x12\xeb\xde\x67\xab\x7b\x9f\xb5\x72\x0e\x5b\x5d\x9c\x1f\x6b\xe5\x2c\x83\x0c\x63\xab\xed\xc6\x5d\x66\xbf\x77\xb3\x5b\xc2\x56\xe7\x61\xab\xc2\x56\x19\xc5\x66\x89\x63\xab\xcc\x31\xb8\x26\xb6\xb9\xd9\x6c\x75\xab\x7d\xed\x4c\x88\xf4\x34\x81\x1a\x67\xfa\xb9\xd9\x54\xb9\xd9\x7c\xe9\x96\xb0\x4f\xda\xa9\x72\xaf\xf1\x96\x5b\x43\x93\x1b\xce\x01\x37\x9c\xcd\xf6\x13\x4a\xec\x4e\x96\xba\x52\x76\x9a\xcd\x2c\x72\x17\xf1\x96\x0e\xe5\x6d\x57\xc8\x5b\x6e\x3d\x4d\x4e\x28\x76\xeb\x69\xf1\x97\x5f\x63\xb6\xf5\xcd\x6b\x19\x9f\xba\xcd\x1c\xd0\x41\x7c\xee\x84\x7d\xb6\x9c\x81\x6e\x1d\x73\x5d\x37\x9a\xdd\x62\x76\xca\xcd\xfe\xfe\x31\x9b\xb1\x76\x35\xe2\x96\x11\xe9\x84\xb3\xdd\x3a\x6f\x9d\xeb\xc6\x40\xb7\xca\xbb\x49\x6e\x66\xb8\x1b\xee\xbd\xd6\xf3\x0e\xf7\x77\xc6\x1c\xfe\xbc\x5f\x00\xde\xad\xb2\xca\xbb\x51\x56\x79\x83\x5c\x7f\xef\x6a\xbb\xd8\x5b\xe8\x66\x7a\x77\xda\x52\x6f\x85\xdf\xe7\x5f\xe5\x7d\xc7\xb5\xb1\x59\x92\xbc\x9b\x02\x46\x7b\xcb\x3a\xe3\x94\xae\xfe\x33\x6b\xa5\x3f\x5e\xb0\x47\xfb\x73\x49\xde\xee\xba\x89\x81\x1d\x79\x00\x6f\xe9\xaf\xb9\x43\xdf\x1e\xd4\xdf\xbb\xc6\x1f\x87\x0d\x6b\x6f\xf7\xed\x09\xfe\x5c\xa1\xaf\xff\xa3\xb9\xb0\xce\x5c\x64\x67\xec\xb4\x5a\x8a\x18\xe6\xdb\x9b\x5d\xb1\x77\x93\xed\xe6\x8f\x79\xee\x72\x65\xde\xe5\xae\x92\xb7\x7c\x32\x70\x7d\x58\xec\xd6\xb3\xdb\x27\x4b\x1b\x4b\x57\xb3\xd9\x7b\xc0\x27\x53\x9f\xac\xcc\x66\x4a\xec\x40\x76\x5b\x98\xec\x83\xd9\xec\x2d\x32\x9b\x58\x6e\x36\x79\xdf\xb7\xe5\x1d\xf2\xd6\xa1\x7c\xee\x0a\xe9\xea\x97\xfb\xa6\x0e\xd9\xcb\x38\x9a\xec\x7e\xa6\x99\xcd\xde\x4f\x6c\x1c\x9b\xdd\x32\x56\xba\xf5\x7c\xe9\x96\xf2\xa5\x5b\x47\xb3\x13\x46\xd9\xf7\x99\xed\x83\x8b\x63\xb6\xfd\x94\x61\xae\x98\xc3\xe0\xf5\xf9\x6b\xe3\x3b\xfc\x41\x6f\x22\x78\x17\x81\x77\x4a\xa7\xbf\x3c\xa5\xc3\x17\xf4\x63\x3e\x10\x04\x47\x5a\x7f\xdd\x93\xb6\x76\xe4\xbf\xfe\x8b\xff\x3b\xff\xf6\xbf\xf2\x1f\xe4\xe1\xae\x70\xed\x5c\x27\x3d\x18\xe6\xda\x39\xf3\xe8\x7d\xb7\x8d\x44\x9f\xde\xff\x20\x0f\xf7\x3b\xf6\xbe\x25\xab\xbc\x25\x47\xaf\x6d\xa1\xf7\x12\x1b\xdc\xfe\xd3\xaf\x79\xb8\xce\x7c\xc5\xef\xb9\x33\xf7\xd6\xfa\x3b\x1e\xeb\xb6\x73\x95\x0d\xf6\x1e\xeb\xf3\x2d\x7c\x76\xf1\x7b\xfe\xd3\x9c\xdc\x5f\xe4\xe3\x7e\x73\xa6\x76\xf8\x51\x47\xf9\x3f\xf3\x15\xfc\x27\x7b\x6f\xfc\xcb\x3c\xdd\xff\xe4\x33\x8e\xe6\xe9\x8e\xf2\xf5\xb6\xd4\xfb\x99\x58\x4e\xb0\xa5\xde\x67\x7e\x97\x07\xb9\xfe\xcf\x72\x41\x32\xb9\xf3\x2c\xec\xe4\xa3\x7b\xec\x5f\xf1\xaf\x67\xc0\x51\x3e\x9a\xef\xfb\x93\x5c\x9f\x5f\x57\xa5\x8c\xf7\xe7\xe3\x7d\xf5\x16\x33\xc1\xc6\xb6\xb7\xeb\x34\x46\xfe\x69\x0e\xf8\xff\x2f\xfe\x3f\xe6\x86\xff\x8c\x7f\x97\xf3\x6d\xfd\x2b\x9d\xff\x29\x77\xe6\x1a\xff\x92\x7f\xaf\xab\xa3\x79\xc6\xbf\xe0\xdf\xe6\x5c\xff\x90\x7d\x71\xce\xff\x86\xce\x77\x0f\x1a\x4f\xd2\x1f\xc1\xbf\x07\xfe\x01\xe4\x2d\xee\x96\xb7\x78\x56\x37\x32\x4f\x37\xfe\xca\xaf\x1c\xcd\x21\xfd\x19\x3c\x21\xdc\xed\x09\xe1\xd9\x80\xee\xcc\x0b\xe8\xfe\x2b\xbf\x12\xd0\x9d\x89\x3e\xf8\xf3\x4e\x7f\x8e\xeb\xdc\x2c\xe6\xb9\x59\x3c\x27\x33\x99\x27\x33\x79\x56\xca\x99\x27\xe5\xbc\x22\xab\x99\xe8\xc7\x1f\xbd\x93\xb8\x97\x09\x9e\x09\xcc\xf3\x4c\xe0\xa5\x80\x29\xcc\x0b\x98\xcd\x4b\x01\x63\x99\x17\x10\xcf\x4b\xfe\xf8\xec\x7f\x81\x8e\xe4\x39\x4f\x5f\x9e\xf3\x0c\xe4\x39\xcf\xcd\x4c\xf4\xc5\x70\xff\x1b\x3c\x4b\x98\xe7\x59\xc2\xca\x80\x42\xe6\x05\x94\xf0\x52\xc0\x2c\xe6\x05\xcc\xe2\xa5\xa3\xeb\x3b\x2a\xf7\x5f\xe5\x78\x34\xe7\xd6\xb9\xc6\x5f\xe7\x7c\x74\xfc\xce\x7e\xff\x4a\x8f\x9e\x36\xef\x62\x1f\x02\x36\x91\xf4\x47\x90\x55\xbe\x73\xf2\xcf\x11\x38\x9e\xbb\x03\xc7\xf3\x6c\x97\x14\xe6\x75\x49\xf9\x95\x5f\xe9\x92\xc2\x44\x1f\xfe\x6a\xdd\x5d\xba\x32\xaf\x4b\x57\x56\x76\x0d\x61\x5e\xd7\x5e\xbc\xd4\xa5\x85\x79\x5d\x5a\x78\xa9\x4b\x21\x13\x7d\xf8\xbf\xd8\xe0\xaf\xef\xc1\xda\xbc\x8b\x6d\xb0\xe9\x29\x2b\x4d\x82\x9f\x3b\xf2\x57\xc5\xbf\x9b\xf3\x50\x3f\xaf\xe6\x41\x29\x62\x92\xfe\xcc\x83\xda\xcc\xa4\x80\x83\x2c\x96\x95\x66\xbf\x1f\x6f\x9a\xad\xbf\xb1\x9d\x6b\x3a\x31\xcc\xce\xed\x7c\xbe\x0b\xbd\x3b\x5d\x22\x0f\xba\xb9\x4c\x92\x95\xd6\xe3\xc7\x9b\x66\xeb\x7f\xd9\xc1\x72\x7f\x1c\xbc\xfd\xd7\xeb\x6e\x54\xf9\xa0\xc3\x78\x5e\x07\xf3\x88\xf6\xe3\x59\x59\x69\xca\x3a\x60\xe7\xfc\xa1\x5d\xdc\xc5\xf3\x9e\x10\x66\x78\x8a\x79\xde\x33\x8a\x71\x81\x49\xde\x26\x59\x69\x97\xda\x60\x13\x2f\x9d\x09\x9d\xa3\x6c\xd7\x80\x05\xcc\x38\x90\xd9\x60\xfb\x80\x59\x01\x6c\x3d\xfa\x2e\xd9\xbb\xa3\x33\x1f\xb3\x13\xda\xe3\xfd\xef\x85\xef\x65\x90\xa4\x31\xdb\xed\x64\x50\xc0\xda\x0e\x48\x9a\x89\x76\x7d\xbd\xe7\xfd\x9a\x83\x3c\xe4\x2d\x32\xa9\x7c\x6e\xf7\x75\xe4\x26\x5d\x9a\xb7\xc8\xee\xe3\x73\xf7\x36\x3b\xdd\xdb\x8c\x74\x96\x8d\x9e\xb3\xe8\xdb\xd9\xef\x18\xf0\x76\x3b\x0a\xdf\xf8\x5d\x2c\x25\xe6\x6d\x3e\x71\xbd\xf9\x44\xee\xe3\x13\x1b\xcf\x38\x1b\x4f\x88\x6b\xa1\xaf\xeb\xc3\xfb\xa6\x6b\x7b\x88\xed\xc3\x6b\xb6\xb7\x7f\x8e\x47\xdb\x06\xff\x06\xdd\xec\x76\x96\xda\xed\x24\xd9\xed\xdc\x67\xb7\x53\x6c\xb7\xb3\xc6\x6e\x67\xbe\xdd\xce\x22\x7b\x98\x12\xb7\x84\xee\x6e\x38\x3d\xdc\x7a\x06\xb9\x78\xef\x3a\x97\xca\xf9\x92\xc6\xa2\x8e\xf7\xdd\xcc\x97\x34\xfa\x4a\x9a\xf7\x80\xdf\x9f\x4b\xa3\xa7\x7e\xce\x60\xcf\x14\x06\xc9\x61\x02\x65\x15\xc7\x48\x1a\x17\xc9\x7c\x86\x8b\x25\x29\xe0\x6d\xce\x93\x34\x6f\x99\xa4\x11\xe7\xf7\x31\x7c\xf6\xd5\xd5\xdb\xe2\xcf\x1f\xa4\xf9\xf3\xaf\xdd\xa0\xfd\x3d\xcf\x60\xde\x96\xbe\x4c\x0b\x28\x66\xb0\xa7\x94\x45\xda\xce\x2c\xdd\xe3\x6d\x92\x16\xe6\xea\x2a\x62\xdd\x64\xef\xfb\x9e\xb1\x4c\xf6\x8c\xe5\x62\x4f\x4f\x6e\xf6\x2c\xe1\x3a\xcf\x0a\x6e\xf2\x9c\xca\x78\x57\xec\x3d\x14\x88\x59\x25\x98\xe0\xdf\xb3\x1f\xab\x99\x21\xf3\xbd\x9b\xf4\x20\x87\x34\xc8\x3f\xe6\x5c\xbf\x9c\x82\x58\x2d\xa9\x4c\xd0\x52\x96\x07\xec\x30\x85\xfa\x96\x39\xc5\x9d\x4a\x6f\x49\x63\x86\xff\x1d\xea\x1a\x52\x3b\xdf\xd7\xcf\x95\x1d\xac\x94\x34\x1e\x96\x1d\xb6\xb7\xec\x30\xa2\x6b\xbc\x87\x15\xb3\x53\xd7\xd8\x25\xfe\xf2\x7f\xf1\xef\x61\x76\x77\x7c\xe6\x63\x1f\x7e\xfb\xd9\xff\xdb\xfb\xff\x17\xc0\x7f\xc2\xee\xd0\x35\x4c\xf4\x97\x77\x80\xec\x60\x8e\xec\xc0\x63\x77\x30\xc5\x07\x9f\xcd\x07\x34\x99\x95\x01\x4d\xe6\xe1\xa3\x2c\x6b\x58\x26\x3b\x28\xf5\xe7\xb6\x76\xb0\x4e\x76\xd0\xd7\x07\xbb\x83\x19\x81\xe7\x98\xf2\xc0\xc9\x66\x5b\xc0\x38\x33\xca\x83\xd9\xed\xc1\x8c\x95\xe1\x0c\xd3\xe1\x0c\x93\xb7\x98\x28\x21\x8c\x14\x78\xc7\xe3\x93\x7f\x1a\x13\xdd\x76\x82\x6d\x30\xa7\xb8\xed\xde\x83\x7e\x9f\x6c\x39\xbd\x65\x31\x1e\x5b\xea\xbd\xdf\x9f\x47\x78\x87\xa1\xb2\x93\x44\x19\xc6\xe0\xa3\xbe\x8b\x6e\x63\x99\xdb\xce\x84\x00\xcb\x1e\x3d\xc4\x4c\xf7\x39\x21\xe2\x21\xd1\xcd\x66\xa8\x4e\x63\x82\xad\xf0\xe7\x53\xab\xc0\xfb\x39\x78\x0b\xc1\x3b\xd9\xed\x37\x03\xdd\x7e\xd3\xdf\x86\xf0\x4e\x27\xe6\x80\x77\x25\xf8\x7f\x77\xec\x5a\x1b\xc4\x38\x37\x99\x38\x7b\x0a\x6b\x6c\x08\x3f\x4b\x3c\x48\x91\xb7\xbb\x0f\x01\xe7\x74\xa0\x23\x3f\xce\xaa\x8e\xfc\x37\xfe\xaf\xee\x04\x42\xa2\x0f\x32\xdf\x8c\x77\x3b\xac\xb8\x1d\xac\x70\x3b\x4c\x4b\xc0\x5c\x5e\x72\xc3\x4c\xaf\x8e\xba\x6d\x9f\x42\x5b\x7c\x27\xef\x87\x23\x5d\xff\x07\x6d\xad\xa6\xc4\x3b\xd6\x14\xfb\x9f\xeb\x3d\x3e\xf8\x9e\x57\x19\x47\xf1\xef\x30\x46\xc6\x31\xb6\x93\x7d\x18\xe5\x82\x19\x25\xe3\x18\xd4\x89\x04\x19\x47\x3f\x19\x47\x9c\x0b\xf6\x73\x9f\xdf\xe0\x2c\x19\x47\x7f\x17\xec\x2f\xf7\x90\x71\x9c\xf2\x9b\x76\xbe\xfb\x7d\x3b\xdb\xc7\xff\x06\x37\xbb\x60\x3f\xff\x7e\x1e\x47\xeb\x8d\x3a\x5a\xb7\xb3\x5e\x7f\x19\xc7\x50\x19\xc7\xf0\xa3\x70\xc1\x7e\x1e\xf4\x7b\xb8\x60\x3f\xc7\xff\x1e\x2e\x98\xb4\xdf\xf7\xfd\x9b\xfe\x7f\x3f\x8f\x71\x9d\x48\x3a\x5a\x76\xc1\x24\xcb\x38\x06\xff\x1e\x2e\xd8\xcf\x71\x9d\xfd\xfe\x8a\x4e\xf9\xdd\xdb\x89\xa1\x47\xe1\x82\xfd\xfc\xf0\xef\xf1\x27\xf3\xf8\xfd\x3a\x12\x5c\xb0\x5f\x46\xfd\x7f\xb3\x66\x9f\xbc\x7b\x74\xca\xb9\x7f\xa7\x3e\x7e\xd5\x4f\xa7\x5e\xe2\x3a\xf5\x97\xf0\x1b\x39\xf5\xeb\x9c\xeb\x98\xdf\xea\xbf\x73\xde\xff\x39\x8f\xbf\xf0\x41\xfe\xc2\x77\x4b\xfb\x2b\x5f\xeb\xaf\xea\x6b\x11\x89\xfe\xef\xbd\x2c\x66\xb5\x2c\x65\xb1\x1b\x68\xba\xfe\x16\xd0\xbe\x11\xda\x5f\xeb\x7c\x7f\xb3\xec\x37\xd8\xf7\x3f\xef\x74\xfc\xef\x4b\x16\x1f\xbd\xe7\x06\x9a\xbe\xff\x1b\x64\xa5\x59\xd3\x79\xe8\x46\xfe\x0e\x45\x40\x2b\xd8\x72\x90\x4a\xf0\x04\x43\x40\x24\x04\xa4\x41\x40\x35\x04\x86\x42\x60\x0a\x04\x36\x40\x97\x28\xe8\x92\x06\x5d\x36\x40\x97\x56\xe8\x5a\x04\xc7\x44\xc0\x31\xd5\x10\x54\x00\xc7\xa6\xc1\x71\x43\xe0\xf8\x08\x38\x3e\x1d\x82\x33\xe0\x84\x04\x38\xa1\x11\xba\x25\x41\xb7\x05\xd0\x6d\x03\x74\x6b\x82\x13\xeb\xe0\xa4\x14\x38\x39\x0c\x4e\x09\x87\x53\x2a\x21\x34\x15\x4e\x15\x38\xb5\x00\x4e\x5b\x00\xdd\x93\xa0\x7b\x03\x84\x65\x42\x8f\x21\xd0\xa3\x18\x4e\xaf\x86\x9e\x95\x10\x9e\x0a\xbd\xc2\xa1\x57\x03\x9c\x51\x05\xbd\xf3\x21\x42\x20\x62\x0b\xf4\x49\x84\x33\xa3\xe1\xcc\x42\x38\x2b\x16\xce\x2a\x81\xc8\x30\x88\xcc\x82\xc8\x56\xe8\x9b\x0e\x7d\x8b\xa1\x6f\x13\x9c\x5d\x01\xe7\x2c\x80\xa8\x60\x88\x6a\x84\x7e\x55\x70\x6e\x0d\xf4\xcf\x87\x01\xb5\x70\x5e\x0a\x9c\x1f\x09\x03\x43\x60\x60\x36\x44\xd7\xc3\xa0\x3a\xb8\x20\x13\x06\x27\xc0\x90\x30\x18\x52\x06\x43\x17\xc0\x85\x49\x30\x2c\x04\x86\x55\x43\x4c\x1e\xc4\x34\xc1\x45\x25\x70\x31\x30\x3c\x09\x86\xe7\xc3\x88\x5a\xb8\x64\x6f\x07\x46\xc6\xc1\xa5\xb9\x10\x9b\x0b\x97\x65\xc1\xa8\x5c\x18\x55\x0b\x97\xb7\x42\x5c\x16\x5c\x51\x06\xa3\xb3\x60\x74\x15\x5c\x19\x04\x57\xc6\x41\x7c\x11\xc4\xd7\xc2\x55\xe9\x30\x26\x10\xc6\x14\xc3\xd5\xa9\x70\x75\x25\x24\xd4\xc3\x35\x69\x70\xcd\x06\x18\x1b\x0d\x63\x6b\xe1\xda\x4c\xb8\xb6\x0a\xae\x1b\x01\xe3\xf2\x21\x69\x04\xdc\x10\x01\xe3\xc3\x60\x7c\x1b\xdc\xd8\x04\x37\x85\xc3\xcd\x89\x70\x4b\x11\xa4\xe4\xc2\xad\xb9\x30\x21\x0e\x6e\x13\xb8\x6d\x0b\xa4\xee\x85\xdb\x0b\x60\x62\x0c\x4c\x6c\x86\x3b\x9a\x21\xad\x05\x26\xa7\xc3\x9d\x71\x90\x1e\x0e\x53\x80\xa9\xa1\x30\x2d\x0a\xa6\x65\x40\x46\x1a\xdc\x95\x02\xd3\x13\x61\x46\x3c\x64\x66\xc1\xcc\x58\xb8\x3b\x0c\x66\xe5\x43\x56\x1e\xcc\xce\x82\x7b\xd2\x61\x4e\x31\x64\xd7\xc1\xbc\x08\x98\x9f\x0f\x0b\xf2\xe0\xde\x42\xf8\x5b\x3e\xdc\x57\x00\x39\xb5\x70\x7f\x32\xdc\x5f\x0f\x0f\x64\xc1\xc2\x18\xc8\x0d\x83\x45\xd9\xf0\x60\x3c\x2c\x0e\x85\xc5\x4d\x90\xd7\x0a\x0f\x05\xc1\x43\xf9\xb0\x34\x07\xf2\x33\xe0\xe1\x44\x78\x24\x1e\x96\x65\x42\x41\x1c\x3c\x9a\x07\xcb\x2b\xe1\xb1\x5c\x28\x4c\x83\xbf\xe7\xc2\x8a\x2a\x78\xbc\x01\x9e\x08\x86\x27\x36\xc0\xca\x4c\x78\x32\x1a\x9e\x6c\x82\xe2\x1a\x78\xaa\x08\x56\xa5\xc0\xd3\x61\xf0\x74\x1b\x3c\x13\x0a\xab\xc3\xe0\xd9\x74\x28\x8d\x80\xe7\x82\x60\x4d\x08\x3c\x9f\x08\x65\x91\xf0\xc2\x10\x58\x1b\x01\xff\x48\x82\xf2\x08\x78\x31\x12\xd6\xc5\xc0\x4b\x03\xa0\x22\x17\x5e\xae\x85\x57\x80\xca\x10\x78\x35\x06\x5e\x8b\x83\xd7\x53\xa1\xaa\x16\xde\x1c\x00\xff\x2c\x81\xea\x42\x78\x2b\x05\xfe\x05\xfc\x2b\x1b\xde\x4e\x87\x0d\x03\xe0\x9d\x40\x78\xa7\x0d\xfe\x5d\x05\x1b\x43\xa1\x26\x10\x36\xc5\xc1\xbb\x41\xf0\x6e\x2d\x6c\xae\x83\x2d\x0d\xb0\xb5\x02\xde\x8b\x83\xf7\xb6\xc0\xfb\xc9\xf0\xfe\x5e\xa8\xcd\x85\x6d\xe1\xb0\x6d\x03\x7c\x90\x04\xdb\x63\xa0\x2e\x1c\x76\x8c\x80\x0f\x93\x61\x67\x01\xec\xaa\x86\xdd\xad\xb0\x27\x1c\xf6\xc6\xc2\xbe\x08\xf8\x38\x10\x3e\xde\x02\x9f\xe4\x41\x7d\x09\x7c\x5a\x0e\x9f\x95\xc0\xfe\x3c\x68\x28\x82\xcf\x77\xc1\x17\xbb\xe0\xcb\x1c\x68\x2c\x80\x03\x71\xf0\x55\x22\x7c\x1d\x0c\x4d\x81\xf0\x0d\x70\x30\x10\xbe\x0d\x82\xe6\x18\xf8\x2e\x0d\x0e\xa5\xc3\xf7\x19\xd0\x92\x00\x3f\xe4\xc2\xe1\x68\xf8\x31\x09\x5a\x23\xe0\xa7\x5c\xf8\x79\x03\xfc\xd2\x0a\x6d\x7b\x3b\x7c\x89\xf6\xc6\x8e\xef\xb4\x9a\x38\x8c\xcd\xc3\xb8\x22\x8c\x94\x62\x74\x17\xc6\xd3\x82\x09\x0c\xc2\x74\x09\xc4\x74\x69\xc4\x74\xad\xc3\x1c\xd3\x80\x09\x4a\xc1\x04\xed\xc5\x1c\x9b\x8a\x39\xb6\x05\x73\xdc\x02\xcc\xf1\x81\x98\xe3\xab\x31\x27\x44\x60\xba\xa5\x63\x4e\x1c\x80\x39\xb1\x01\x13\x52\x87\x39\x19\xcc\xc9\x05\x98\x53\x92\x30\xa1\x21\x98\x53\x43\x31\xa7\x09\xe6\xb4\xbd\x98\xee\x15\x98\xb0\x62\x4c\x8f\x04\xcc\xe9\x91\x98\x9e\x60\x7a\x6e\xc0\x84\x37\x60\x7a\xb5\x60\xce\x68\xc0\x44\x94\x61\xfa\x0c\xc1\x9c\x19\x82\xff\x37\x0d\xce\x6a\xc5\x44\x96\x63\xce\x8e\xc3\x9c\x53\x81\xff\xef\xee\xf7\xdb\x80\x39\xb7\x00\xd3\x3f\x03\x33\x20\x06\x73\x5e\x16\xe6\xfc\x0a\xcc\xc0\x32\x4c\x74\x0b\x66\x50\x23\xe6\x82\x4a\xcc\xe0\x3c\xcc\xe0\x56\xcc\xd0\x70\xcc\x85\x23\x30\x17\x36\x63\x62\xc2\x30\x31\xb5\x98\x8b\x9a\x30\xc3\x83\x31\xc3\x1b\x31\x23\xaa\x30\x97\xe4\x61\x46\x66\x61\x2e\x15\xcc\xa5\x79\x98\xd8\x11\x98\xd8\x46\xcc\x65\x79\x98\x51\x29\x98\xcb\x43\x30\x97\xd7\x63\xe2\x32\x31\x57\x24\x63\x46\xfb\x50\x80\x19\xdd\x88\xb9\x32\x07\x73\x65\x2b\xe6\xaa\x20\xcc\x98\x28\xcc\xd5\xd9\x98\x84\x64\xcc\x35\x59\x98\xb1\xb9\x98\x6b\x5b\x30\xd7\x15\x63\xae\x8f\xc1\x24\x45\x61\x6e\x88\xc0\xdc\xb0\x0b\x33\x3e\x13\x73\x63\x12\x26\x39\x0a\x73\x53\x14\xe6\xe6\x70\xcc\x2d\xe9\x98\x94\x0a\xcc\x84\x60\xcc\x6d\x29\x98\xd4\x3a\xcc\xc4\x21\x98\x3b\x4a\x31\x93\x02\x31\x93\xf6\x62\xee\x8c\xc4\xa4\x67\x62\xa6\x2c\xc0\x4c\x2d\xc2\x4c\x2b\xc2\xdc\x15\x81\x99\x9e\x80\x99\x11\x83\xc9\x4c\xc4\xcc\x8c\xc3\xdc\x1d\x83\x99\x15\x8f\xc9\x4a\xc0\xcc\x8e\xc3\xdc\x93\x8a\x99\x93\x8d\xc9\x4e\xc6\xcc\x8d\xc4\xcc\x6d\xc6\xcc\xdb\x85\x99\x5f\x85\x59\x50\x8f\xb9\xb7\x11\xf3\xb7\x5a\x4c\xce\x00\xcc\xfd\x31\x98\x07\x32\x30\x0b\xf3\x31\x8b\x02\x31\x0f\x66\x62\x16\x67\x63\x96\x04\x61\x1e\x8a\xc2\x2c\x8d\xc5\xe4\x67\x60\x1e\xce\xc5\x3c\x52\x8e\x59\x56\x8f\x29\xd8\x85\x79\xb4\x0d\xf3\x18\x98\xc2\x01\x98\xbf\x87\x61\xfe\x5e\x8b\x59\x51\x83\x79\x3c\x0f\x53\x54\x80\x79\x22\x1f\xb3\xb2\x08\xf3\x64\x01\xa6\xb8\x1a\xf3\x54\x31\x66\x55\x0d\xe6\xe9\x2a\x4c\x49\x3d\x66\x35\x98\x67\x23\x31\xa5\x23\x30\xcf\xc5\x61\xd6\xc4\x63\xd6\x34\x62\x9e\x6f\xc1\x94\xd5\x62\x5e\x28\xc2\xac\xad\xc4\x94\x47\x62\x5e\x0c\xc4\xac\x8b\xc0\xbc\x54\x80\x79\x19\xcc\xcb\xf5\x98\xf5\xd5\x98\x57\x2a\x30\x95\xd5\x98\x57\x2b\x31\xaf\xb5\x60\xaa\x22\x30\x6f\x24\x60\xde\xcc\xc5\xfc\xb3\x12\x53\x5d\x84\x79\x2b\x13\xf3\xaf\x6c\xcc\xdb\x59\x98\x0d\xb1\x98\x77\x82\x31\xef\x34\x61\x36\x26\x63\x6a\xd2\x30\x35\xad\x98\x77\xb3\x31\x5b\xa2\x30\x5b\x87\x60\xde\x0b\xc6\xbc\x57\x8f\x79\xbf\x18\x53\x5b\x8c\xd9\x56\x83\xf9\x20\x1e\xb3\x3d\x08\xb3\xbd\x04\xb3\x03\xcc\x87\x39\x98\x0f\xdb\x30\x3b\x1b\x31\xbb\x83\x30\xbb\x9b\x31\x7b\x02\x31\x7b\x93\x30\xfb\x12\x30\x1f\x27\x63\x3e\x19\x82\xa9\x0f\xc3\x7c\x1a\x86\xf9\x2c\x02\xf3\x59\x13\x66\x7f\x05\xa6\xa1\x10\xf3\x79\x04\xe6\x8b\x70\xcc\x97\x31\x98\xc6\x68\xcc\x01\xc1\x1c\xd8\x85\xf9\xaa\x01\xf3\x75\x35\xa6\x29\x1f\xf3\x4d\x2e\xe6\x60\x06\xe6\xdb\x78\x4c\x73\x12\xe6\xbb\x70\xcc\x21\xc1\x1c\x6a\xc3\x7c\xdf\x8a\xf9\x41\x30\x87\xe3\x30\x3f\x16\x60\x5a\x73\x30\x3f\x45\x63\x7e\xaa\xc6\xfc\xdc\x80\x69\x0b\xc2\xb4\x15\x62\x8e\x94\x62\xda\xab\xb0\x84\x63\x4d\x11\xd6\xd6\x62\xdd\x16\xac\xe4\x62\x35\x0e\xeb\x89\xc0\x06\xc4\x63\x03\x0b\xb0\x5d\xc2\xb0\x5d\x6a\xb0\x5d\x1b\xb1\xc7\x14\x62\x83\x52\xb0\x41\xcd\xd8\x63\x4b\xb0\xc7\x2d\xc0\x1e\x9f\x82\x0d\x6e\xc0\x9e\x50\x88\xed\x56\x84\x3d\x31\x0f\x1b\x92\x83\x3d\x29\x05\x7b\xf2\x10\xec\x29\x35\xd8\xd0\x42\xec\xa9\x15\xd8\xd3\x32\xb0\xdd\xa3\xb1\xdd\x1b\xb0\x61\x19\xd8\x1e\xa1\xd8\x1e\x7b\xb1\xa7\x67\x61\x7b\x2e\xc0\x86\xc7\x62\xc3\x5b\xb0\xbd\x4a\xb0\x67\x0c\xc1\xf6\x8e\xc2\x46\x84\x60\xfb\x08\xf6\xcc\x11\xd8\xb3\x42\xb0\x91\x61\xd8\xc8\x66\x6c\xdf\x24\xec\xd9\x89\xd8\x73\xd2\xb1\x51\x99\xd8\x7e\xa5\xd8\xfe\x71\xd8\xf3\xc0\x9e\x9f\x8a\x8d\x0e\xc4\x0e\x2a\xc6\x0e\x4e\xc7\x0e\xa9\xc2\x0e\xcd\xc0\x5e\x58\x85\x1d\xb6\x17\x7b\xd1\x10\xec\xc5\x75\xd8\x11\x60\x2f\x49\xc1\x8e\x1c\x80\x1d\x59\x8a\xbd\x34\x0c\x7b\xe9\x16\x6c\x6c\x39\xf6\xb2\x38\xec\x65\x8d\xd8\x51\xd1\xd8\x51\x05\xd8\x51\x7b\xb1\x97\x47\x62\x2f\x4f\xc7\x5e\x5e\x83\x8d\x8b\xc0\xc6\x15\x63\xaf\x08\xc5\x5e\x31\x02\x7b\x45\x1a\xf6\x8a\x02\xec\x15\x55\xd8\xd1\xe1\xd8\xd1\xb9\xd8\xd1\xf5\xd8\x2b\xc3\xb1\x57\x66\x60\xaf\xac\xc4\xc6\x07\x63\xe3\xe3\xb1\xf1\x05\xd8\xf8\x06\xec\x55\x31\xd8\xab\x32\xb1\x57\xd5\x62\xc7\x44\x61\xc7\x14\x62\xaf\x16\xec\xd5\x95\xd8\xab\x9b\xb1\x09\x69\xd8\x84\x0a\xec\x35\x71\xd8\x6b\xca\xb0\x63\x23\xb0\x63\xf3\xb0\x63\x9b\xb0\xd7\xc6\x63\x13\xc3\xb1\x89\x39\xd8\xeb\x92\xb0\xd7\x15\x60\xc7\xc5\x62\xc7\xe5\x63\xc7\x35\x61\xaf\x8f\xc3\x5e\x5f\x82\xbd\xbe\x05\x9b\x14\x8b\x4d\x2a\xc6\xde\x20\xd8\x1b\xe2\xb1\x37\x94\x61\x6f\x68\xc2\x8e\x8f\xc6\x8e\xcf\xc2\x8e\xaf\xc2\xde\x98\x80\xbd\xb1\x10\x7b\x63\x1b\x36\x39\x1b\x9b\xdc\x8c\xbd\x29\x07\x7b\x53\x1d\xf6\xe6\x08\xec\xcd\x19\xd8\x9b\xab\xb0\xb7\x84\x61\x6f\x49\xc7\xde\x52\x89\x4d\x01\x9b\x92\x80\x4d\x29\xc7\xde\x1a\x81\xbd\x35\x19\x7b\x6b\x1e\xf6\xd6\x36\xec\x84\x58\xec\x84\x6a\xec\x6d\x89\xd8\xdb\x1a\xb0\xa9\x71\xd8\xd4\x32\xec\xed\x82\xbd\xbd\x18\x3b\x31\x1c\x3b\xb1\x1a\x7b\xc7\x00\xec\x1d\x99\xd8\x3b\xaa\xb0\x77\xb4\x61\xd3\x62\xb1\x69\x79\xd8\xb4\xbd\xd8\x49\xe9\xd8\x49\x6d\xd8\xc9\x69\xd8\xc9\xe5\xd8\x3b\x83\xb0\x77\x66\x61\xef\x6c\xc0\xa6\x17\x60\xd3\x6b\xb1\x53\x92\xb1\x53\xa3\xb0\x53\xb3\xb0\x53\x5b\xb0\xd3\x72\xb0\xd3\x6a\xb0\x19\xd1\xd8\x8c\x02\x6c\x46\x13\xf6\xae\x3c\xec\xf4\x04\xec\xf4\x0a\xec\x8c\x10\xec\x8c\x1c\xec\x8c\x16\x6c\x66\x1a\x36\xb3\x04\x9b\x59\x87\x9d\x19\x86\x9d\x99\x8f\x9d\x59\x8d\x9d\xd9\x8c\xbd\x3b\x0a\x7b\x77\x3c\xf6\xee\x52\xec\xac\x38\xec\xac\x06\x6c\x56\x19\x76\x76\x10\x76\x76\x0e\x76\x76\x0d\xf6\x9e\x60\xec\x3d\x29\xd8\x7b\xea\xb0\x73\xc2\xb0\x73\x76\x61\xb3\xe3\xb0\xd9\x8d\xd8\xb9\x03\xb0\x73\xb7\x60\xe7\x0d\xc0\xce\xdb\x80\x9d\xbf\x01\xbb\x20\x1b\xbb\x60\x03\xf6\xde\x68\xec\xfd\x79\xd8\xfb\x1b\xb1\x0f\xc4\x62\x1f\x68\xc4\x2e\x4c\xc6\x2e\xac\xc2\xe6\x86\x60\x73\x8b\xb0\xb9\xad\xd8\x45\x23\xb0\x8b\x2a\xb0\x0f\x96\x61\x17\x87\x63\x17\x67\x62\x17\xd7\x60\x17\xb7\x62\xf3\x22\xb1\x79\x79\xd8\xbc\x7a\xec\x92\x30\xec\x92\x3a\xec\x43\x85\xd8\xa5\x43\xb0\x4b\x6b\xb0\xf9\x95\xd8\x87\x47\x60\x1f\x01\xbb\x2c\x16\x5b\x90\x87\x2d\x68\xc5\x3e\xda\x88\x5d\x9e\x8c\x5d\x5e\x80\x5d\x5e\x8f\x7d\x2c\x12\xfb\x58\x11\xb6\x30\x12\xfb\x77\xc1\xfe\x7d\x17\x76\x45\x1c\x76\x45\x31\xf6\xf1\x54\x6c\x51\x1a\xb6\x68\x03\xf6\x89\x12\xec\xca\x0d\xd8\x27\xf3\xb0\xc5\xd9\xd8\xa7\xd2\xb0\xab\x32\xb0\x4f\xd7\x60\x4b\x72\xb0\xcf\xe4\x62\x9f\x69\xc6\xae\xce\xc1\x3e\x1b\x81\x7d\x36\x07\x5b\x9a\x8c\x7d\x2e\x0a\xfb\x5c\x25\x76\x4d\x36\x76\x4d\x0b\xb6\x2c\x04\xfb\x42\x10\xf6\x85\x0c\xec\xda\x30\xec\xda\x2d\xd8\x7f\xe4\x62\xff\xd1\x82\x2d\x4f\xc3\xbe\x18\x82\x5d\x97\x8e\x5d\x57\x8b\xad\x88\xc4\x56\xb4\x61\x5f\x6e\xc3\xbe\x12\x84\xad\x1c\x80\x7d\x35\x09\xfb\x5a\x12\xf6\xf5\x58\x6c\xd5\x5e\xec\x1b\x15\xd8\x37\x1b\xb1\xff\x4c\xc7\x56\x27\x63\xdf\x1a\x82\x7d\xab\x15\xfb\xaf\x2a\xec\xdb\xd9\xd8\x0d\x51\xd8\x0d\x6d\xd8\x7f\x83\xdd\x18\x89\xdd\x58\x8f\xad\x69\xc1\x6e\x2a\xc0\xbe\x9b\x8f\xdd\x5c\x86\xdd\x92\x8a\xdd\x1a\x8c\xdd\x5a\x8b\x7d\xaf\x12\x5b\x0b\x76\x5b\x24\xf6\x83\x54\xec\xf6\x42\x6c\x5d\x29\x76\x47\x2b\xf6\xc3\x3a\xec\xce\x16\xec\xee\x14\xec\x47\x19\xd8\x3d\x55\xd8\xbd\x05\xd8\x7d\xe5\xd8\x8f\x9b\xb0\xf5\xd1\xd8\x4f\x53\xb1\x9f\x15\x61\xf7\xe7\x61\x1b\xd2\xb1\x9f\x47\x62\xbf\x08\xc2\x7e\x51\x8f\xfd\xb2\x0c\xdb\x98\x87\x3d\x50\x88\xfd\x2a\x12\xfb\x55\x23\xb6\x29\x01\xfb\xcd\x02\xec\xc1\x32\xec\xb7\xb5\xd8\xe6\x66\xec\xa1\x60\xec\xa1\x56\xec\xf7\xf5\xd8\x96\x2a\xec\x0f\x99\xd8\xc3\xa9\xd8\x1f\x63\xb0\xad\x31\xd8\x9f\xc2\xb1\x3f\x0b\xf6\x97\x10\xec\x2f\x25\xd8\xb6\x74\xec\x91\x18\xec\x91\x46\x6c\x7b\x3e\xd6\x9b\x86\xa3\x0c\x67\x62\x71\x36\x1c\xe7\xc2\x70\x92\x89\xd3\x40\x9c\x36\xe1\x3c\x75\xb8\x80\x02\x5c\x60\x09\xae\x4b\x19\xae\x6b\x34\xae\x6b\x03\xee\x98\x4a\x5c\x50\x2c\xee\x58\x1f\xea\x70\xc7\xc7\xe3\x82\x73\x70\x27\x54\xe3\xba\xe5\xe3\x4e\xac\xc6\x85\xec\xc2\x9d\xb4\x01\x77\xf2\x02\xdc\x29\xb1\xb8\xd0\x38\x5c\x68\x39\xee\xd4\x2d\xb8\xd3\xd2\x71\xdd\x53\x70\x61\x31\xb8\x1e\xd1\xb8\xd3\xf3\x71\x3d\x47\xe0\xc2\x13\x71\xbd\x32\x71\x67\xc4\xe3\xce\x68\xc5\xf5\x2e\xc5\x45\xa4\xe2\x22\xda\x70\x7d\x32\x70\x67\x86\xe3\xce\xca\xc2\x9d\xb5\x17\x17\x59\x85\xeb\x5b\x83\x3b\xbb\x04\x77\x4e\x15\x2e\x2a\x0f\xd7\x2f\x07\x77\xee\x08\xdc\xb9\xcd\xb8\x01\x61\xb8\xf3\x04\x77\xde\x16\xdc\xf9\x85\xb8\x81\x0b\x70\xd1\x89\xb8\x41\x43\x70\x17\x04\xe1\x06\x17\xe0\x86\xa4\xe2\x86\x86\xe3\x2e\x1c\x81\xbb\xb0\x19\x37\xac\x12\x17\x53\x80\xbb\x28\x0d\x77\x71\x20\xee\xe2\x36\xdc\xf0\x5d\xb8\x11\x69\xb8\x4b\xb6\xe0\x46\xe6\xe0\x2e\xdd\x82\x8b\x8d\xc2\x5d\x96\x84\x1b\x55\x86\xbb\xbc\x1a\x77\xc5\x10\xdc\xe8\x18\xdc\x95\x19\xb8\xf8\x0c\xdc\x55\xa1\xb8\x31\x51\xb8\xab\x13\x70\x09\x49\xb8\x6b\x0a\x70\xd7\x26\xe0\x12\xe3\x70\x89\x2d\xb8\xeb\x6a\x70\xe3\x92\x70\xd7\x87\xe1\xae\x6f\xc0\xdd\x30\x02\x37\xbe\x1c\x97\x1c\x81\x4b\x6e\xc6\xdd\xb4\x17\x77\x8b\xe0\x52\xc2\x70\xb7\x66\xe1\x26\x94\xe1\x6e\xdb\x82\xbb\x3d\x0a\x37\x31\x01\x77\x47\x0a\x2e\x2d\x09\x37\x29\x0e\x37\xb9\x09\x97\x3e\x02\x37\x25\x05\x37\x35\x0b\x37\xad\x01\x77\x57\x3a\x6e\x7a\x3d\x2e\x33\x01\x37\xb3\x14\x77\x77\x03\x6e\x56\x05\x2e\x2b\x13\x37\x3b\x0a\x37\xbb\x15\x37\x27\x08\x97\x3d\x00\x37\x37\x1f\x37\xaf\x01\x37\xbf\x1e\xb7\x60\x2f\xee\x6f\xe5\xb8\x9c\x0c\xdc\x03\xa1\xb8\x85\x25\xb8\xdc\x74\xdc\xa2\x01\xb8\x45\x45\xb8\x07\x83\x70\x8b\x43\x70\x8b\x73\x71\x8b\x5b\x70\x79\x0d\xb8\xa5\x25\xb8\xfc\x06\xdc\x23\x89\xb8\x65\x39\xb8\x82\x22\xdc\xa3\xad\xb8\xe5\x8d\xb8\xc7\x9a\x71\x85\x85\xb8\xbf\x8f\xc0\xad\x08\xc4\xad\xa8\xc1\x3d\xde\x88\x7b\x42\x70\x2b\x47\xe0\x8a\x83\x70\x4f\x8d\xc0\xad\x4a\xc3\x3d\x9d\x82\x2b\x49\xc6\x3d\x53\x8a\x7b\x36\x10\x57\x1a\x8e\x7b\x2e\x0e\xb7\x26\x18\xb7\x66\x17\xee\xf9\x36\xdc\x0b\xa1\xb8\x17\xda\x70\x6b\xeb\x71\xe5\xd1\xb8\x17\x17\xe0\xd6\x6d\xc0\xbd\xd4\x8a\xab\x68\xc1\xbd\xdc\x84\x5b\x5f\x88\xab\x4c\xc5\xbd\x1a\x8c\x7b\xb5\x06\xf7\x5a\x05\xee\xf5\x5c\x5c\xd5\x10\x5c\x55\x23\xee\x8d\x06\xdc\x3f\xe3\x70\xd5\xf9\xb8\x7f\x09\xee\xed\x42\xdc\x3b\xf1\xb8\x7f\xa7\xe3\x36\x16\xe1\x6a\xaa\x70\x9b\xea\x70\x9b\xe3\x70\x5b\x0a\x71\x5b\x23\x70\xef\xe5\xe0\x6a\x33\x71\xdb\x0a\x71\x1f\x54\xe1\xb6\xef\xc2\xd5\x95\xe0\x76\xd4\xe0\x3e\x6c\xc2\xed\x6c\xc1\xed\x6a\xc5\x7d\x14\x87\xdb\x53\x8a\xdb\xdb\x8c\xdb\xb7\x05\xf7\x71\x12\xee\x93\x2c\x5c\x7d\x09\xee\xd3\x5d\xb8\xfd\x41\xb8\xfd\xad\xb8\xcf\x53\x71\x5f\xa4\xe3\xbe\x2c\xc4\x35\x66\xe0\x0e\xc4\xe2\xbe\x2a\xc0\x7d\x5d\x8b\xfb\x66\x00\xee\xdb\x08\x5c\x73\x36\xee\xbb\x1a\xdc\xa1\x6c\xdc\xf7\xa1\xb8\x96\x68\xdc\x0f\x41\xb8\xc3\x19\xb8\x1f\x0b\x71\xad\x65\xb8\x9f\xaa\x71\x3f\xe7\xe3\x7e\x49\xc0\xb5\x15\xe0\x8e\xd4\xe2\xda\xdb\x10\xc2\x11\x1a\x11\x53\x81\xd8\x5a\xc4\xb5\x21\xd2\x88\xe8\x2e\x24\x20\x1e\xe9\x22\x48\x97\x12\xa4\x6b\x2c\x72\x4c\x15\x72\x6c\x3a\x72\x5c\x39\x72\x7c\x23\x12\x9c\x83\x9c\x10\x8e\x9c\x50\x86\x74\x8b\x46\x4e\x04\x39\x71\x2f\x72\x52\x24\x72\x72\x0a\x72\x72\x03\x72\x4a\x2a\x72\xca\x2e\x24\x34\x1e\x09\xdd\x80\x9c\x9a\x80\x9c\x5a\x81\x9c\x16\x82\x9c\xb6\x00\x39\xad\x1e\xe9\x9e\x82\x74\xaf\x44\xc2\x06\x20\x61\x25\x48\x8f\x10\xa4\x47\x01\x72\x3a\xc8\xe9\xd9\xc8\xe9\x7b\x91\x9e\x29\x48\xcf\x2d\x48\x78\x01\xd2\x2b\x10\xe9\x95\x85\xf4\x6a\x40\xce\x88\x47\xce\x28\x46\xce\x68\x46\x7a\x67\x23\x11\xa1\x48\x44\x3e\xd2\x27\x10\xe9\x33\x02\xe9\x53\x82\x9c\x09\x72\x66\x1a\x72\x66\x39\x72\x96\x20\x67\xd5\x20\x91\x43\x90\xc8\x3c\x24\xb2\x16\xe9\x3b\x00\xe9\x9b\x8a\xf4\xad\x43\xce\x0e\x46\xce\x8e\x43\xce\xce\x45\xce\xae\x41\xce\x09\x42\xce\x89\x47\xce\x29\x45\xce\x69\x45\xa2\x92\x91\xa8\x3a\xa4\x5f\x0a\x72\x6e\x20\x72\x6e\x2e\x72\x6e\x0d\xd2\x3f\x10\xe9\x1f\x8f\xf4\x2f\x42\xfa\x37\x23\x03\x42\x91\x01\xa9\xc8\x80\x16\xe4\xbc\x5c\xe4\xfc\x20\xe4\xfc\x78\xe4\xfc\x12\xe4\xfc\x3a\x64\x60\x04\x32\xb0\x00\x19\xd8\x8a\x44\x87\x21\xd1\x09\x48\x74\x16\x12\x5d\x85\x0c\x0a\x47\x06\xa5\x21\x83\xca\x90\x0b\x40\x2e\x48\x45\x2e\xa8\x43\x06\x87\x22\x83\x13\x90\xc1\xb9\xc8\xe0\x46\x64\x48\x38\x32\x24\x09\x19\x92\x8f\x0c\xd9\x82\x0c\x15\x64\x68\x1c\x32\x34\x17\x19\x5a\x8d\x5c\x18\x8a\x5c\x58\x84\x5c\x58\x8f\x0c\x8b\x42\x86\x25\x21\xc3\x4a\x91\x98\x40\x24\x26\x1b\x89\x69\x46\x2e\x8a\x47\x2e\x6a\x41\x2e\x4e\x46\x2e\xae\x42\x86\x87\x23\xc3\x73\x90\xe1\x8d\xc8\x88\x38\x64\x44\x35\x32\xa2\x0d\xb9\x24\x06\xb9\xa4\x0c\x19\x19\x82\x8c\x4c\x43\x46\x96\x23\x23\x9b\x90\x4b\x23\x91\x4b\xf3\x90\x4b\x1b\x90\xd8\x68\x24\x36\x17\x89\x6d\x43\x2e\x8b\x42\x2e\xcb\x43\x46\x05\x22\xa3\xe2\x91\x51\x1b\x90\xcb\x63\x90\xcb\x4b\x91\xcb\xeb\x91\xb8\x30\x24\x2e\x1d\x89\x2b\x42\xae\x08\x45\xae\x48\x46\xae\xa8\x42\x46\x0f\x40\x46\x17\x21\x57\x0e\x41\xae\x6c\x40\xe2\xf3\x90\xab\x06\x20\x57\xb5\x22\x63\x0a\x90\xab\x63\x90\xab\x2b\x90\x84\x48\x24\xa1\x12\xb9\x26\x1e\xb9\xa6\x0a\x19\x1b\x8b\x8c\xcd\x46\xc6\x36\x23\xd7\x56\x20\xd7\x36\x22\x89\x31\x48\xe2\x16\xe4\xba\x18\xe4\xba\x0d\xc8\xb8\x64\x64\x5c\x33\x72\x7d\x0e\x92\x14\x8d\x24\x15\x23\x49\x0d\xc8\x0d\xf9\xc8\xf8\x60\x64\x7c\x09\x72\x63\x10\x72\x63\x11\x92\x1c\x8a\x24\x67\x21\xc9\xbb\x90\x9b\xa2\x90\x9b\xaa\x91\x9b\x13\x91\x5b\x40\x6e\xc9\x47\x52\x22\x91\x94\x6a\xe4\xd6\x64\xe4\xd6\x6a\x64\x42\x34\x32\xa1\x04\xb9\x2d\x1c\xb9\xad\x08\xb9\xad\x15\x49\x1d\x81\xa4\x56\x22\xb7\xc7\x20\xb7\x17\x21\x13\x05\x99\x18\x8f\x4c\xdc\x80\xdc\x11\x86\xdc\x91\x8e\xdc\x51\x86\xdc\xd1\x80\xa4\x45\x21\x69\x85\x48\x5a\x2d\x32\x49\x90\x49\x91\xc8\xa4\x0a\x64\x72\x14\x32\xb9\x00\xb9\x13\xe4\xce\x21\xc8\x9d\x45\x48\x7a\x08\x92\x5e\x8a\xa4\xb7\x20\x53\x92\x91\x29\x35\xc8\xd4\x48\x64\x6a\x06\x32\x75\x17\x32\x2d\x10\x99\x16\x83\x4c\xcb\x47\x32\x40\x32\x92\x90\x8c\x2a\xe4\xae\x08\xe4\xae\x1c\x64\x3a\xc8\xf4\x78\x64\x7a\x06\x32\x3d\x1f\x99\x5e\x81\x4c\xdf\x85\xcc\x10\x64\xc6\x00\x64\x46\x3a\x32\xa3\x18\xc9\x14\x24\x33\x07\x99\x39\x00\x99\x59\x89\xdc\x1d\x87\xdc\x5d\x87\xcc\x4a\x43\x66\x35\x20\x59\x69\xc8\xec\x20\x64\x76\x19\x72\x4f\x28\x72\x4f\x09\x32\x27\x04\x99\x53\x82\x64\x0b\x92\x9d\x83\x64\x37\x23\x73\xb3\x91\xb9\x2d\xc8\xbc\x3c\x64\x5e\x33\x32\x3f\x17\x99\xdf\x88\x2c\x58\x80\x2c\xa8\x47\xee\xcd\x44\xee\x6d\x44\xfe\x96\x8f\xdc\x17\x8e\xdc\xd7\x80\xe4\x44\x23\x39\x95\xc8\xfd\xd1\xc8\xfd\x35\xc8\x03\x61\xc8\x03\x85\xc8\x03\xcd\xc8\xc2\x74\x64\x61\x3d\x92\x9b\x8d\xe4\x36\x20\x8b\x32\x91\x45\xb5\xc8\x83\x89\xc8\x83\x35\xc8\xe2\x11\xc8\xe2\x2d\x48\x5e\x0c\x92\x57\x88\xe4\xb5\x21\x4b\x92\x91\x25\xd5\xc8\x43\x41\xc8\x43\x29\xc8\x43\x25\xc8\x43\x0d\xc8\xd2\x21\xc8\xd2\x5c\x64\x69\x15\xb2\xb4\x09\xc9\x8f\x41\xf2\x73\x90\xfc\x16\xe4\xe1\x42\xe4\x91\x40\xe4\x91\x32\x64\x59\x38\xb2\x6c\x03\x52\x10\x89\x14\x14\x21\x8f\x0a\xf2\x68\x36\xf2\x68\x2d\xb2\x7c\x08\xb2\xbc\x14\x79\x2c\x12\x79\xac\x11\x29\x2c\x42\xfe\x9e\x8d\xac\x48\x40\x56\x34\x20\x8f\xa7\x23\x45\x20\x45\xb9\x48\x51\x33\xf2\xc4\x02\xe4\x89\x06\x64\x65\x06\xb2\x72\x2f\xf2\x64\x0c\xf2\x64\x19\x52\x1c\x8c\x14\xe7\x21\x4f\x81\x3c\x95\x82\x3c\x55\x81\xac\x1a\x81\xac\xda\x82\x3c\x9d\x84\x3c\xdd\x80\x94\xe4\x21\xcf\x44\x23\xcf\x34\x22\xab\x0b\x91\x67\x63\x91\x67\x9b\x90\xd2\x68\xa4\xb4\x14\x29\x6d\x41\x9e\x4b\x47\x9e\x2b\x45\xd6\x04\x23\x6b\x52\x91\x35\x0d\xc8\xf3\x99\x48\x99\x20\x65\x05\xc8\x0b\x11\xc8\x0b\xc5\xc8\xda\x30\x64\x6d\x0d\xf2\x8f\x4c\xa4\x3c\x04\x29\xaf\x40\x5e\x8c\x44\x5e\x2c\x42\x5e\x6c\x41\xd6\xc5\x23\xeb\xea\x90\x97\x92\x90\x97\x1a\x90\x8a\x74\xe4\xe5\x50\xe4\xe5\x6a\x64\x7d\x3c\xb2\xbe\x0e\x79\x25\x05\x79\xa5\x11\xa9\x8c\x45\x2a\x8b\x90\x57\x43\x91\x57\xf3\x91\x57\xf7\x22\xaf\x25\x22\xaf\x95\x23\xaf\x07\x21\xaf\x27\x23\xaf\x97\x21\xaf\x37\x21\x55\x51\x48\x55\x21\xf2\x46\x14\xf2\x46\x1d\xf2\x66\x3a\xf2\x66\x1b\xf2\xcf\x0c\xe4\x9f\x8d\x48\x75\x3c\x52\x5d\x87\xbc\x15\x8f\xbc\xd5\x84\xfc\x2b\x13\x79\x3b\x02\x79\xbb\x14\xd9\x90\x88\x6c\x68\x45\xde\xd9\x80\xfc\x3b\x13\xd9\x18\x8f\x6c\xdc\x85\xd4\xe4\x21\x9b\x82\x90\x4d\x15\xc8\xbb\xd1\xc8\xbb\x7b\x91\xcd\x59\xc8\x96\x18\x64\xcb\x5e\x64\x6b\x09\xf2\x5e\x14\xf2\xde\x5e\xe4\xfd\x68\xe4\xfd\x6a\xa4\x36\x0a\xa9\xdd\x82\x6c\x1b\x81\x6c\x6b\x44\x3e\x48\x45\xb6\x87\x22\xdb\x0b\x90\xba\x58\xa4\x6e\x2f\xb2\xa3\x14\xf9\x30\x1e\xd9\x19\x81\xec\x2c\x41\x76\x25\x21\xbb\xaa\x91\xdd\xc1\xc8\xee\x54\x64\x77\x35\xf2\x51\x1c\xf2\xd1\x06\x64\x4f\x0a\xb2\xa7\x05\xd9\x5b\x82\xec\x8b\x43\xf6\xb5\x20\x1f\x17\x20\x9f\x24\x23\xf5\xa1\x48\x7d\x13\xf2\x69\x05\xf2\x59\x2a\xb2\x3f\x10\xd9\x5f\x8a\x34\xc4\x20\x0d\xbb\x90\xcf\xd3\x90\x2f\xc2\x91\x2f\xb6\x20\x5f\xe6\x22\x8d\x31\x48\xe3\x5e\xe4\x40\x26\x72\xa0\x11\xf9\x2a\x19\xf9\xaa\x01\xf9\x3a\x1d\xf9\xba\x05\x69\x5a\x80\x7c\x23\xc8\x37\x79\xc8\xc1\x48\xe4\xe0\x16\xe4\xdb\x0c\xa4\x39\x0c\x69\x2e\x41\xbe\x8b\x46\xbe\xcb\x46\xbe\x6b\x46\x0e\x8d\x40\x0e\x55\x22\xdf\x87\x21\xdf\x97\x21\x2d\xa1\x48\x4b\x39\xf2\x43\x06\x72\x38\x1a\xf9\x31\x08\xf9\xb1\x11\x69\xad\x42\x7e\x2a\x44\x7e\xce\x47\x7e\xc9\x45\x7e\x69\x45\xda\xd2\x91\xb6\x16\xe4\xc8\x02\xa4\x5d\x90\xf6\x7c\xc4\x3b\x04\xf1\x36\xa0\xe4\xa0\x26\x0a\x35\x8d\xa8\x2d\x45\x5d\x0a\x2a\x61\xa8\x2c\x40\xa5\x09\xd5\x74\x54\x9b\x51\x4f\x3a\xea\x69\x42\x03\x32\xd0\x80\x36\x34\xb0\x10\xed\x12\x83\x76\xd9\x85\x76\xcd\x42\x8f\x89\x46\x8f\x69\x41\x83\x92\xd1\xa0\x1a\xf4\xd8\x38\xf4\xd8\x2d\xe8\x71\x71\xe8\x71\x5b\xd0\xe3\xd3\xd1\xe0\x20\x34\x38\x0b\x0d\x6e\x44\x4f\x48\x47\x4f\x68\x41\xbb\x65\xa1\x27\x82\x9e\x58\x82\x86\xc4\xa3\x21\xe5\xe8\x49\xa1\xe8\x49\x05\xe8\xc9\x21\xe8\xc9\xf9\xe8\x29\xc1\xe8\x29\x65\x68\x68\x3c\x1a\xba\x0b\x3d\x35\x0d\x3d\x2d\x08\x3d\xad\x02\xed\x9e\x88\x76\x6f\x45\xc3\xf2\xd0\x1e\x11\x68\x8f\x5a\xf4\xf4\x1c\xb4\xe7\x00\xb4\x67\x3d\x1a\x9e\x84\x86\xef\x42\x7b\xa5\xa3\x67\x08\x7a\x46\x01\xda\x3b\x12\xed\xbd\x17\x8d\xc8\x47\x23\x9a\xd1\x3e\x69\x68\x9f\x7a\xf4\xcc\x2c\xf4\xac\x08\xf4\xac\x3a\x34\xb2\x10\xed\x9b\x82\x9e\x1d\x81\x9e\xdd\x84\x9e\x53\x8b\x46\x55\xa2\xfd\x92\xd0\x7e\x6d\xe8\xb9\x15\x68\xff\x4c\x74\x40\x14\x3a\xa0\x11\x3d\xaf\x1a\x3d\xbf\x08\x1d\x18\x87\x0e\x6c\x46\xa3\x17\xa0\x83\x82\xd0\x41\x3e\x6e\x46\x2f\x88\x47\x2f\x28\x41\x07\x87\xa1\x83\xf3\xd1\xc1\xad\xe8\x90\x64\x74\x48\x2b\x3a\x34\x1f\xbd\x70\x01\x3a\x2c\x13\x8d\xc9\x46\x2f\xca\x45\x2f\xce\x43\x87\x17\xa2\x23\xaa\xd1\x4b\x1a\xd1\x91\xb9\xe8\xa5\x03\xd0\x4b\x9b\xd0\xd8\x32\xf4\xb2\x54\x74\x54\x38\x3a\xaa\x0d\xbd\x7c\x17\x1a\x97\x8f\x5e\x11\x8f\x8e\x0e\x43\x47\x37\xa3\x57\x56\xa3\xf1\x05\xe8\x55\x39\xe8\x98\x2c\xf4\xea\x60\xf4\xea\x32\x34\x21\x19\xbd\x26\x04\xbd\x66\x03\x3a\x36\x0b\xbd\x36\x0e\x4d\x0c\x43\x13\x5b\xd1\xeb\xf6\xa2\xe3\x6a\xd1\xeb\xb7\xa0\x49\xd5\xe8\x0d\x95\xe8\xf8\x2d\xe8\x8d\x0d\x68\x72\x05\x7a\x53\x1e\x7a\x73\x16\x7a\x4b\x3a\x9a\x92\x84\xde\x1a\x87\x4e\x48\x44\x6f\x4b\x45\x53\xc3\xd0\xd4\x2a\xf4\xf6\x42\x74\x62\x12\x7a\x47\x34\x9a\x06\x9a\xd6\x86\x4e\x4a\x45\x27\x55\xa0\x93\x83\xd1\xc9\x69\xe8\xe4\xbd\xe8\x9d\xa1\xe8\x9d\x49\xe8\x9d\x05\xe8\x9d\xf5\x68\x7a\x2a\x3a\x25\x08\x9d\x52\x88\x4e\x8d\x41\xa7\xd6\xa2\xd3\x0a\xd1\x69\x4d\x68\x46\x0c\x9a\x91\x8f\x66\xd4\xa3\x77\xc5\xa1\x77\x15\xa1\x77\x35\xa3\xd3\x53\xd1\xe9\x35\xe8\x8c\x10\x74\x46\x39\x9a\x19\x87\x66\x6e\x40\x67\x66\xa1\x33\xeb\xd0\xbb\x43\xd1\xbb\xd3\xd1\xbb\xab\xd0\x59\x21\xe8\xac\x74\x74\x56\x03\x9a\x95\x84\x66\x55\xa0\xb3\x93\xd1\xd9\x6d\xe8\x3d\x05\xe8\x9c\x01\xe8\x9c\x4a\x34\x3b\x0b\xcd\xae\x45\xe7\x06\xa3\x73\x93\xd1\xb9\x25\xe8\xbc\x70\x74\x5e\x2e\x3a\xaf\x09\x9d\x1f\x8a\xce\x6f\x40\x17\x14\xa0\xf7\x26\xa3\x7f\x0b\x45\xef\x13\xf4\xbe\x5c\x34\x27\x10\xcd\x29\x44\xef\x0f\x47\xef\xdf\x80\xde\xdf\x84\x3e\x10\xf5\xff\x01\x71\xe8\x03\x39\xe8\x03\x15\xe8\x03\x0d\xe8\x42\xd0\x85\x61\xe8\xc2\x11\xe8\xc2\x0c\x74\x61\x31\xba\xb0\x0a\x5d\xd8\x80\xe6\x86\xa2\xb9\x31\x68\x6e\x2a\x9a\x9b\x87\xe6\x96\xa3\xb9\x4d\xe8\xa2\x01\xe8\xa2\x74\x74\x51\x09\xba\xa8\x1e\x7d\x70\x04\xfa\x60\x26\xfa\x60\x3d\xba\x18\x74\x71\x14\xba\x38\x11\x5d\x9c\x83\x2e\xae\xe8\x40\x9e\x0f\xb5\x68\x5e\x1b\xba\x24\x1a\x5d\x92\x8c\x2e\xc9\x41\x97\xb4\xa0\x0f\x05\xa3\x0f\x0d\x40\x97\x06\x77\x22\x0e\x5d\x5a\x88\x2e\xad\x42\x97\xd6\xa3\xf9\x21\x68\x7e\x1c\x9a\x5f\x84\xe6\xd7\xa3\x0f\x0f\x41\x1f\x2e\x45\x1f\x6e\x44\x1f\xc9\x44\x1f\xd9\x8b\x2e\x8b\x44\x97\xe5\xa0\xcb\x1a\xd1\x82\x21\x68\x41\x26\x5a\xb0\x0b\x7d\x34\x1e\x7d\xb4\x05\x5d\x9e\x8e\x2e\xaf\x40\x1f\x8b\x42\x1f\xdb\x80\x16\x26\xa3\x85\x4d\xe8\xdf\x0b\xd1\x15\x29\xe8\x8a\x56\xf4\xf1\x2c\xf4\xf1\x5a\xb4\x68\x00\x5a\xd4\x84\x3e\x91\x8d\xae\x0c\x44\x57\x16\xa0\x4f\x06\xa1\x4f\x16\xa1\xc5\x21\x68\x71\x06\x5a\x5c\x8f\x3e\x15\x89\x3e\xb5\x01\x5d\x15\x8d\xae\xda\x80\x3e\x9d\x8e\x3e\x5d\x83\x96\x0c\x41\x4b\x4a\xd0\x67\x12\xd0\x67\x16\xa0\xab\x43\xd1\xd5\x75\xe8\xb3\xf9\x68\x69\x2e\xfa\x5c\x26\xba\x66\x00\xba\x66\x01\xba\xa6\x12\x5d\xd3\x8c\x3e\x1f\x89\x3e\x9f\x82\x3e\x5f\x81\x96\x05\xa2\x65\x69\x68\x59\x13\xfa\x42\x24\xfa\x42\x02\xfa\x42\x2e\xfa\xc2\x06\xf4\x85\x06\x74\x6d\x30\xba\x76\x04\xba\x76\x0b\xba\xb6\x09\xfd\x47\x3c\xfa\x8f\x02\xb4\x3c\x02\x2d\xcf\x40\xcb\x1b\xd0\x17\x43\xd1\x17\xe3\xd1\x17\x8b\xd1\x17\xab\xd1\x75\x81\xe8\xba\x04\x74\x5d\x36\xba\xae\x10\x5d\x57\x85\xae\x6b\x41\x5f\x0a\x41\x5f\x8a\x47\x5f\xca\x44\x5f\xaa\x40\x5f\x6a\x45\x2b\x62\xd0\x8a\x02\xb4\xa2\x05\x7d\x39\x0c\x7d\x39\x0e\x7d\x39\x13\x7d\xb9\x14\x5d\x1f\x84\xae\x4f\x42\xd7\xe7\xa1\xeb\x2b\xd1\xf5\x0d\xe8\x2b\xa1\xe8\x2b\xd9\xe8\x2b\xa5\xe8\x2b\x7b\xd1\xca\x20\xb4\x72\x04\x5a\xb9\x00\xad\x6c\x42\x5f\x0d\x47\x5f\x4d\x45\x5f\xdd\x85\xbe\x36\x00\x7d\x2d\x13\x7d\xad\x11\x7d\x7d\x04\xfa\xfa\x02\xb4\x2a\x0c\xad\x4a\x41\xab\xaa\xd0\xaa\x5d\x68\x55\x0b\xfa\x46\x30\xfa\x46\x14\xfa\x46\x1c\xfa\xcf\x58\xf4\xed\x08\xf4\xdf\xd5\xe8\xbf\xf7\xa2\x1b\x05\xdd\x18\x8e\x6e\x8c\x47\x37\xa6\xa1\x1b\x0b\xd0\x8d\xe5\xe8\xc6\x2d\xe8\xc6\x46\xb4\x26\x02\xad\x29\x45\x37\x35\xa1\xef\x46\xa0\xef\xe6\xa2\x9b\xc3\xd1\xcd\x19\xe8\x96\x28\x74\xcb\x06\x74\x6b\x1a\xba\x75\x17\xfa\x5e\x36\xfa\x5e\x23\xfa\xfe\x02\xf4\xfd\x3a\xb4\x36\x18\xad\x4d\x41\x6b\x6b\xd0\x6d\xd1\xe8\xb6\x5c\x74\x5b\x2d\xfa\x41\x34\xfa\x41\x01\xba\x3d\x08\xdd\x5e\x8c\xd6\x05\xa1\x75\x09\x68\x5d\x25\xba\x43\xd0\x1d\x89\xe8\x8e\x0a\xf4\xc3\x60\xf4\xc3\x5c\xf4\xc3\xbd\xe8\xce\x34\x74\x67\x13\xba\x2b\x15\xdd\x95\x87\xee\xaa\x40\x77\x47\xa2\xbb\x93\xd1\xdd\x25\xe8\xee\x66\xf4\xa3\x28\xf4\xa3\x24\xf4\xa3\x05\xe8\x47\xa5\xe8\x47\x0d\xe8\x9e\x70\x74\x4f\x32\xba\x27\x17\xdd\xb3\x01\xdd\xd3\x86\xee\x8d\x43\xf7\x66\xa2\x7b\x0b\xd0\xbd\xe5\xe8\xde\x1a\x74\x5f\x32\xba\xaf\x0e\xfd\xb8\x02\xfd\x24\x1b\xfd\xa4\x1c\xfd\xa4\x0e\xad\x0f\x44\xeb\x87\x74\xe0\xd3\x3a\xf4\xb3\x64\xf4\xb3\x42\xf4\xb3\x0d\xe8\x67\xad\xe8\xfe\x08\x74\x7f\x1d\xda\x10\x85\x36\x64\xa0\x0d\x1b\xd0\xcf\x43\xd0\xcf\x73\xd0\x2f\x40\xbf\x88\x47\xbf\x28\x44\xbf\x04\xfd\x32\x1d\xfd\xb2\x14\xfd\xb2\x1e\x6d\x8c\x45\x1b\x4b\xd1\xc6\x0d\x68\x63\x0b\x7a\x20\x02\x3d\x90\x88\x1e\x58\x80\x1e\x28\x47\x0f\xd4\xa3\x5f\x05\xa2\x5f\x0d\x41\xbf\x4a\x43\xbf\xca\x47\xbf\xaa\x46\xbf\x6a\x41\xbf\x8e\x40\xbf\x4e\x44\xbf\xce\x42\xbf\x2e\x46\xbf\xae\x45\x9b\x40\x9b\xa2\xd1\xa6\x54\xb4\x29\x1f\x6d\xaa\x44\x9b\x1a\xd1\x6f\x42\xd1\x6f\xe2\xd1\x6f\xb2\xd1\x6f\x4a\xd0\x6f\x6a\xd0\x6f\x5a\xd0\x83\x91\xe8\xc1\x64\xf4\x60\x3e\x7a\xb0\x1a\x3d\xd8\x88\x7e\x1b\x82\x7e\x1b\x8b\x7e\x9b\x89\x7e\x5b\x8c\x7e\x5b\x8b\x36\x0b\xda\x1c\x8d\x36\x27\xa3\xcd\x79\x68\x73\x05\xda\xdc\x80\x7e\x17\x82\x7e\x17\x87\x7e\x97\x85\x7e\x57\x82\x7e\xb7\x05\xfd\xae\x0d\x3d\x14\x85\x1e\x4a\x41\x0f\xe5\xa3\x87\x2a\xd1\x43\x7b\xd1\xef\x03\xd1\xef\x63\xd0\xef\x33\xd0\xef\x4b\xd0\xef\xeb\xd0\xef\xdb\xd0\x96\x08\xb4\x25\x11\x6d\xc9\x45\x5b\xaa\xd0\x96\x26\xf4\x87\x10\xf4\x87\x11\xe8\x0f\xe9\xe8\x0f\x45\xe8\x0f\x35\xe8\x0f\xad\xe8\xe1\x48\xf4\x70\x32\x7a\x38\x0f\x3d\x5c\x8e\x1e\xde\x85\xfe\x18\x88\xfe\x38\x04\xfd\x31\x1d\xfd\xb1\x18\xfd\xb1\x06\xfd\xb1\x09\x6d\x0d\x45\x5b\xe3\xd1\xd6\x05\x68\x6b\x05\xda\xda\x80\xfe\x14\x84\xfe\x14\x83\xfe\x94\x8e\xfe\x54\x8c\xfe\x54\x87\xfe\x2c\xe8\xcf\x51\xe8\xcf\xc9\xe8\xcf\x39\xe8\xcf\x15\xe8\xcf\x8d\xe8\x2f\xa1\xe8\x2f\xb1\xe8\x2f\x19\xe8\x2f\xc5\xe8\x2f\xb5\xe8\x2f\x6d\x68\x5b\x14\xda\x96\x8c\xb6\xe5\xa3\x6d\x1b\xd0\xb6\x26\xf4\x48\x30\x7a\x64\x08\x7a\x24\x1d\x3d\x52\x8c\x1e\xa9\x43\xdb\x05\x6d\x8f\x42\xdb\x93\xd1\xf6\x3c\xb4\xbd\x1a\x6d\x6f\x41\xbd\x11\xa8\x37\x1e\xf5\x66\xa2\xde\x12\xd4\x5b\x87\x87\x40\x3c\x0c\xc1\x43\x0a\x1e\xf2\xf1\x50\x8d\x87\x46\x3c\x26\x14\x8f\x89\xc3\x63\x32\xf0\x98\x22\x3c\xa6\x06\x8f\x69\xc1\x63\xc3\xf1\x38\xc1\xe3\x1a\xf0\x48\x2d\x1e\xad\xc4\xe3\xa9\xc0\x13\x50\x86\x27\xb0\x0c\x4f\x97\x32\x3c\x5d\x47\xe0\xe9\x5a\x8b\xe7\x98\x34\x3c\x41\xe0\x09\x2a\xc5\x73\x6c\x02\x9e\xe3\xc0\x73\x5c\x19\x9e\xe3\xe3\xf1\x1c\xdf\x88\x27\x38\x1f\xcf\x09\xd1\x78\x4e\x68\xc2\xd3\xad\x18\xcf\x89\xc9\x78\x42\x42\xf1\x84\x54\xe2\x39\x29\x19\xcf\xc9\xa1\x78\x4e\xae\xc3\x73\x4a\x0e\x9e\xd0\x21\x78\x4e\x15\x3c\xa7\xd6\xe2\x39\x2d\x06\xcf\x69\x45\x78\xba\x87\xe2\xe9\x5e\x8c\x27\x4c\xf0\x84\xa5\xe2\x09\xdb\x82\xa7\x47\x34\x9e\x1e\xd9\x78\x7a\xd4\xe2\x39\x3d\x0a\xcf\xe9\xe5\x78\x7a\x06\xe3\xe9\x99\x85\xa7\x67\x05\x9e\x9e\x4d\x78\xc2\x53\xf1\x84\x57\xe1\xe9\x15\x82\xa7\x57\x02\x9e\x5e\x79\x78\xce\x08\xc5\x73\x46\x09\x9e\xde\xa1\x78\x7a\xe7\xe2\x89\x10\x3c\x11\x39\x78\x22\xda\xf0\xf4\xc9\xc4\xd3\xa7\x0c\x03\x5d\xa6\x9a\xb1\x24\xfa\xbf\xc3\x65\x31\x58\x4e\xc6\x47\x37\x75\x7e\xaf\xeb\x04\x3e\xc0\x61\xa4\x0b\x70\x33\x74\x96\x0d\xdd\xb8\xb9\xb3\x6c\x09\x22\xa3\xb3\xec\x18\x45\x76\x67\x59\x08\xe7\x5f\x9d\x65\x25\x94\xcf\x3a\xcb\x1e\x4e\xe7\xe7\xce\x72\x00\x25\x26\xb4\xb3\x1c\xc8\xd9\xa6\xaa\xb3\xdc\x85\x48\xf3\x45\x67\xb9\x2b\x23\xec\x71\x9d\xe5\x63\x88\xb1\x63\x3a\xcb\x41\xe4\xda\x07\x3b\xcb\xc7\x92\xec\xba\x75\x96\x8f\x23\xd1\x4d\xed\x2c\xd7\x70\xb2\x3b\x3a\x87\x4d\x0c\x70\xbb\xb8\x94\x69\x64\x30\x9b\xe9\x4c\xe2\x0e\xd2\xc8\xf4\xff\x5d\xfc\x01\x9c\xc7\xf9\x84\x73\x39\xd3\x98\xc6\x1d\xa4\x73\x3b\xe1\x5c\xc1\x54\x6e\xe3\x5c\xc2\xb9\x84\x74\xd2\x09\x67\xec\xaf\xad\x66\xf8\xaf\x6e\x67\x06\xb7\x33\x9d\xbb\xb9\x9d\x54\xce\x65\x0c\xd3\xc8\x64\x1a\xe1\x5c\xcb\xad\x4c\x65\x06\x57\x90\xc9\xad\xa4\x33\x89\xdb\xb8\x8a\x69\x4c\xf5\xd7\x98\x4d\x46\xe7\x08\x53\xb8\x95\x3b\x98\xc4\x54\xee\x20\x9c\x7e\x84\xff\x41\x1f\xe1\xff\xd1\xcb\x5f\x7d\x3e\xce\x3f\xa3\x19\x4c\xf2\x8f\x16\xce\x79\x9c\xcb\x00\xa2\x7f\x6d\x77\xb4\x55\xbf\x3f\xe9\x75\x92\xbf\xc7\x5b\x09\x27\x93\xe9\xdc\x4a\x2a\xb7\xfb\x67\x39\x9d\x3b\x09\x67\x1a\x13\xff\x17\x39\xf9\x7a\x4e\x25\xdc\x5f\x7f\x36\xe1\x4c\xf0\x7f\x3e\x9d\xdb\xfd\x6b\x9c\x41\xa6\x7f\x6e\xb7\xfb\xeb\x4c\xf2\xcf\xee\x36\xff\x1d\xdf\x3c\x3a\xae\x27\x33\xd3\xaf\x9b\x19\xa4\xfa\xe7\x95\xd9\xb9\x8e\x19\x9c\xfb\x7f\x90\xdf\xd1\x99\xfc\x77\xcd\x58\xbf\xae\x7c\xda\x9b\xea\x5f\xd9\xed\xdc\xca\x94\xff\xb8\xdb\x31\xab\x09\xfe\x79\xff\x77\xfb\xd4\x3f\x6c\xef\xb3\x84\x4c\x32\xb8\x90\xfe\xf4\xe7\x36\xa6\xf9\xeb\x9d\xcb\x1d\xbf\x91\xcf\xb9\xfe\xfb\x53\xe8\x4f\x06\xfd\x3b\x7b\x9d\x46\xff\xdf\xb5\x9d\xe5\xff\xff\x5c\xa6\xfc\x6e\xe4\x49\xff\xb1\xc2\xff\xe9\x2b\x81\xe9\xfe\xd1\x66\xfa\x65\x34\x83\x6b\x3b\xed\x70\x92\x5f\xa2\x33\xe8\x4f\x62\x67\x0f\xff\xb9\xc6\xe9\x5c\x4b\x1a\xd3\x98\xc5\x6d\xdc\xea\xb7\xde\xf8\xce\x36\x53\xfd\x57\x3e\x19\xcc\xf4\x6b\xd1\x57\xd7\xb7\xd2\x34\xff\xfa\x2f\x21\x83\x5b\xb9\xad\xf3\xea\x3f\xdb\x44\x11\xfe\x5f\x56\x77\xbe\xdf\xea\xfe\x78\x8d\xb7\xfe\xa6\xaf\x73\x99\xc6\x74\xee\xa0\x7f\xa7\x1d\x1e\xed\xd3\xb7\x82\x78\xae\xe0\x52\x2e\x63\x0c\xd7\x72\x19\xfd\x3a\xfb\xbc\x9e\xdb\x99\xc0\x44\xff\x38\x99\xbf\xda\xf7\xf5\x9d\x73\x1f\xcd\x4c\xff\x93\x7a\x1e\x83\xfd\xff\x0e\xe4\x42\x06\xfa\x7f\xf9\x62\xa0\xff\x09\xef\x78\xd6\x07\xfa\x77\x3b\xbc\x2d\xfe\xbf\xda\x31\x91\x3f\xf8\xaf\xcb\x54\x30\xd6\x38\x1c\x82\xe2\x21\x80\x40\x7c\xbb\xd1\x31\x04\x71\x2c\xc7\x71\x3c\xc1\x9c\x40\x37\x4e\x24\x84\x93\x38\x99\x53\x08\xe5\x54\x4e\xa3\x3b\x61\xf4\xe0\x74\x7a\x12\x4e\x2f\xce\xa0\x37\x11\xf4\xe1\x4c\xce\x22\x92\xbe\x9c\xcd\x39\x44\xd1\x8f\x73\xe9\xdf\xb9\xeb\x0c\x24\x9a\x41\x5c\xc0\x60\x86\x30\x94\x0b\x19\x46\x0c\x17\x71\x31\xc3\x19\xc1\x25\x8c\xe4\x52\x62\xb9\x8c\x51\x5c\x4e\x1c\x57\x30\x9a\x2b\x89\xe7\x2a\xc6\x70\x35\x09\x5c\xc3\x58\xae\x25\x91\xeb\x18\xc7\xf5\x24\x71\x03\xe3\xb9\x91\x64\x6e\xe2\x66\x6e\x21\x85\x5b\x8d\xf0\x34\x39\xdc\xcf\x1b\x2c\xa7\x91\x07\x78\x88\xc5\x3c\xc1\x73\x94\x18\xe5\x41\x3e\xe2\x3e\x96\x19\x8f\x09\x60\x89\x09\x24\x97\xb7\xf9\xd8\x74\x61\x25\x6b\xf8\x81\x16\x0e\xb3\x8a\x17\xd8\xc4\x46\xd6\x32\x81\xdb\xc8\x27\x95\xcd\xdc\x4e\x0d\xef\xf2\x3e\x5b\xd8\xca\x7b\x1c\x60\x22\xdb\xa9\x65\x1b\xff\xe0\x0e\x9a\x79\x98\x0f\xa9\x63\x07\x69\x7c\xcd\x37\x2c\x62\x32\x93\xb8\x93\x29\xa4\x33\x95\x62\xa6\x71\x17\x19\x7e\x3b\x99\x49\x26\x77\x33\x8b\xaf\xc8\xe2\x1e\x66\x33\x87\xb9\x64\x53\xc9\x53\xcc\x67\x1e\x0b\xb8\x97\x26\x0e\xf2\x9a\xe9\x6a\x8e\x31\x41\xe6\x58\x73\x9c\x39\x9e\x23\xb4\x9b\x60\x73\x82\xe9\x66\x4e\xc4\x6b\x30\x21\xe6\x24\x73\xb2\x31\xe6\x14\x13\x6a\x4e\x35\xa7\x99\xee\x26\xcc\xf4\x30\xa7\x9b\x9e\x26\xdc\xf4\x32\x67\xd0\xca\x4f\xa6\xb7\x89\x30\x7d\xcc\x99\xe6\x2c\x13\x69\xfa\x9a\xb3\xcd\x39\x26\xca\xf4\x33\xe7\x9a\xfe\x66\x80\x39\xcf\x9c\xcf\xcf\xec\x34\x03\x4d\xb4\x19\x64\x2e\x30\x83\xcd\x10\x33\xd4\x5c\x68\x86\x99\x18\x73\x91\xb9\xd8\x0c\x37\x23\xcc\x25\x7c\xc6\x7e\x33\xd2\x5c\x6a\x62\xcd\x65\x66\x94\xb9\xdc\xc4\x99\x2b\xcc\x68\x73\xa5\x89\x37\x57\x99\x31\xe6\x6a\x93\x40\x39\x2f\x9a\x6b\xcc\x58\x73\xad\x49\x34\xd7\x99\x71\xe6\x7a\x93\x64\x6e\x30\xe3\xf9\x85\x36\x1a\xf8\xdc\xdc\x68\x92\xcd\x4d\xe6\x66\x73\x8b\x49\x31\xb7\x9a\x09\xe6\x36\x93\x6a\x6e\x37\x13\xcd\x1d\x26\xcd\x4c\x32\x93\xcd\x9d\x26\xdd\x4c\x31\x53\xcd\x34\x93\xc1\xeb\xe6\x2e\x33\xdd\xcc\x30\x99\x7c\xc1\x97\x66\xa6\xb9\xdb\xcc\x32\x59\x66\xb6\xb9\xc7\xcc\x31\xd9\x66\xae\x99\x67\xe6\x9b\x05\xe6\x5e\xf3\x37\x73\x9f\xc9\x31\xf7\x9b\x07\xcc\x42\x56\x9b\x5c\xb3\xc8\x3c\x68\x16\x9b\x3c\xb3\xc4\x3c\x64\x96\x9a\x7c\xf3\xb0\x79\xc4\x2c\x33\x05\xe6\x51\xb3\xdc\x3c\x66\x0a\xcd\xdf\xcd\x0a\xf3\xb8\x29\x32\x4f\x98\x95\xe6\x49\x53\x6c\x9e\x32\xab\xcc\xd3\xa6\xc4\x3c\x63\x56\x9b\x67\x4d\xa9\x79\xce\xac\x31\xcf\x9b\x32\xf3\x82\x59\x6b\xfe\x61\xca\xcd\x8b\x66\x9d\x79\xc9\x54\x98\x97\xcd\x7a\xf3\x8a\xa9\x34\xaf\x9a\xd7\xcc\xeb\xa6\xca\xbc\x61\xde\x34\xff\x34\xd5\xe6\x2d\xf3\x2f\xf3\xb6\xd9\x60\xde\x31\xff\x36\x1b\x4d\x8d\xd9\x64\xde\x35\x9b\xcd\x16\xb3\xd5\xbc\x67\xde\x37\xb5\x66\x9b\xf9\xc0\x6c\x37\x75\x66\x87\xf9\xd0\xec\x34\xbb\xcc\x6e\xf3\x91\xd9\x63\xf6\x9a\x7d\xe6\x63\xf3\x89\xa9\x37\x9f\x9a\xcf\xcc\x7e\xd3\x60\x3e\x37\x5f\x98\x2f\x4d\xa3\x39\x60\xbe\x32\x5f\x9b\x26\xf3\x8d\x39\x68\xbe\x35\xcd\xe6\x3b\x73\xc8\x7c\x6f\x5a\xcc\x0f\xe6\xb0\xf9\xd1\xb4\x9a\x9f\xcc\xcf\xe6\x17\xd3\x66\x8e\x98\x76\xe3\xb5\x58\x63\xad\x75\x56\xac\x5a\x8f\x0d\xb0\x81\xb6\x8b\xed\x6a\x8f\xb1\x41\xf6\x58\x7b\x9c\x3d\xde\x06\xdb\x13\x6c\x37\x7b\xa2\x0d\xb1\x27\xd9\x93\xed\x29\x36\xd4\x9e\x6a\x4f\xb3\xdd\x6d\x98\xed\x61\x4f\xb7\x3d\x6d\xb8\xed\x65\xcf\xb0\xbd\x6d\x84\xed\x63\xcf\xb4\x67\xd9\x48\xdb\xd7\x9e\x6d\xcf\xb1\x51\xb6\x9f\x3d\xd7\xf6\xb7\x03\xec\x79\xf6\x7c\x3b\xd0\x46\xdb\x41\xf6\x02\x3b\xd8\x0e\xb1\x43\xed\x85\x76\x98\x8d\xb1\x17\xd9\x8b\xed\x70\x3b\xc2\x5e\x62\x47\xda\x4b\x6d\xac\xbd\xcc\x8e\xb2\x97\xdb\x38\x7b\x85\x1d\x6d\xaf\xb4\xf1\xf6\x2a\x3b\xc6\x5e\x6d\x13\xec\x35\x76\xac\xbd\xd6\x26\xda\xeb\xec\x38\x7b\xbd\x4d\xb2\x37\xd8\xf1\xf6\x46\x9b\x6c\x6f\xb2\x37\xdb\x5b\x6c\x8a\xbd\xd5\x4e\xb0\xb7\xd9\x54\x7b\xbb\x9d\x68\xef\xb0\x69\x76\x92\x9d\x6c\xef\xb4\xe9\x76\x8a\x9d\x6a\xa7\xd9\x0c\x7b\x97\x9d\x6e\x67\xd8\x4c\x3b\xd3\xde\x6d\x67\xd9\x2c\x3b\xdb\xde\x63\xe7\xd8\x6c\x3b\xd7\xce\xb3\xf3\xed\x02\x7b\xaf\xfd\x9b\xbd\xcf\xe6\xd8\xfb\xed\x03\x76\xa1\xcd\xb5\x8b\xec\x83\x76\xb1\xcd\xb3\x4b\xec\x43\x76\xa9\xcd\xb7\x0f\xdb\x47\xec\x32\x5b\x60\x1f\xb5\xcb\xed\x63\xb6\xd0\xfe\xdd\xae\xb0\x8f\xdb\x22\xfb\x84\x5d\x69\x9f\xb4\xc5\xf6\x29\xbb\xca\x3e\x6d\x4b\xec\x33\x76\xb5\x7d\xd6\x96\xda\xe7\xec\x1a\xfb\xbc\x2d\xb3\x2f\xd8\xb5\xf6\x1f\xb6\xdc\xbe\x68\xd7\xd9\x97\x6c\x85\x7d\xd9\xae\xb7\xaf\xd8\x4a\xfb\xaa\x7d\x8d\x5d\x7c\x6a\x5f\xb7\x55\xf6\x0d\xfb\xa6\xfd\xa7\xad\xb6\x6f\xd9\x7f\xd9\xb7\xed\x06\xfb\x8e\xfd\xb7\xdd\x68\x6b\xec\x26\xfb\x2e\x7b\xd8\xcb\x3e\xea\xd9\xcd\x27\x76\xb3\xdd\x62\xb7\xda\xf7\xec\xfb\xb6\xd6\x6e\xb3\x1f\xd8\xed\xb6\xce\xee\xb0\x1f\xda\x9d\x76\x97\xdd\x6d\x3f\xb2\x7b\xec\x5e\xbb\xcf\x7e\x6c\x3f\xb1\xf5\xf6\x53\xfb\x99\xdd\x6f\x1b\xec\xe7\xf6\x0b\xfb\xa5\x6d\xb4\x07\xec\x57\xf6\x6b\xdb\x64\xbf\xb1\x07\xed\xb7\xb6\xd9\x7e\x67\x0f\xd9\xef\x6d\x8b\xfd\xc1\x1e\xb6\x3f\xda\x56\xfb\x93\xfd\xd9\xfe\x62\xdb\xec\x11\xdb\x6e\xbd\x0e\x67\x9c\x75\xce\x89\x53\xe7\x71\x01\x2e\xd0\x75\x71\x5d\xdd\x31\x2e\xc8\x1d\xeb\x8e\x73\xc7\xbb\x60\x77\x82\xeb\xe6\x4e\x74\x21\xee\x24\x77\xb2\x3b\xc5\x85\xba\x53\xdd\x69\xae\xbb\x0b\x73\x3d\xdc\xe9\xae\xa7\x0b\x77\xbd\xdc\x19\xae\xb7\x8b\x70\x7d\xdc\x99\xee\x2c\x17\xe9\xfa\xba\xb3\xdd\x39\x2e\xca\xf5\x73\xe7\xba\xfe\x6e\x80\x3b\xcf\x9d\xef\x06\xba\x68\x37\xc8\x5d\xe0\x06\xbb\x21\x6e\xa8\xbb\xd0\x0d\x73\x31\xee\x22\x77\xb1\x1b\xee\x46\xb8\x4b\xdc\x48\x77\xa9\x8b\x75\x97\xb9\x51\xee\x72\x17\xe7\xae\x70\xa3\xdd\x95\x2e\xde\x5d\xe5\xc6\xb8\xab\x5d\x82\xbb\xc6\x8d\x75\xd7\xba\x44\x77\x9d\x1b\xe7\xae\x77\x49\xee\x06\x37\xde\xdd\xe8\x92\xdd\x4d\xee\x66\x77\x8b\x4b\x71\xb7\xba\x09\xee\x36\x97\xea\x6e\x77\x13\xdd\x1d\x2e\xcd\x4d\x72\x93\xdd\x9d\x2e\xdd\x4d\x71\x53\xdd\x34\x97\xe1\xee\xa2\xd4\x4d\x77\x33\x5c\xa6\x9b\xe9\xee\x76\xb3\x5c\x96\x9b\xed\xee\x71\x73\x5c\xb6\x9b\xeb\xe6\xb9\xf9\x6e\x81\xbb\xd7\xfd\xcd\xdd\xe7\x72\x78\xd2\xdd\xef\x1e\x70\x0b\x5d\xae\x5b\xe4\x1e\x74\x8b\x5d\x9e\x5b\xe2\x1e\x72\x4b\x5d\xbe\x7b\xd8\x3d\xe2\x96\xb9\x02\xf7\xa8\x5b\xce\x63\xee\x31\x57\xe8\xfe\xce\xe3\x6e\x85\x7b\xdc\x15\xb9\x27\xdc\x4a\xf7\xa4\x2b\x76\x4f\xb9\x55\xee\x69\x57\xe2\x9e\x71\xab\xdd\xb3\xae\xd4\x3d\xe7\xd6\xb8\xe7\x5d\x99\x7b\xc1\xad\x75\xff\x70\xe5\xee\x45\xb7\xce\xbd\xe4\x2a\xdc\xcb\x6e\xbd\x7b\xc5\x55\xba\x57\xdd\x6b\xee\x75\x57\xe5\xde\x70\x6f\xba\x7f\xba\x6a\xf7\x96\xfb\x97\x7b\xdb\x6d\x70\xef\xb8\x7f\xbb\x8d\xae\xc6\x6d\x72\xef\xba\xcd\x6e\x8b\xdb\xea\xde\x73\xef\xbb\x5a\xb7\xcd\x7d\xe0\xb6\xbb\x3a\xb7\xc3\x7d\xe8\x76\xba\x5d\x6e\xb7\xfb\xc8\xed\x71\x7b\xdd\x3e\xf7\xb1\xfb\xc4\xd5\xbb\x4f\xdd\x67\x6e\xbf\x6b\x70\x9f\xbb\x2f\xdc\x97\xae\xd1\x1d\x70\x5f\xb9\xaf\x5d\x93\xfb\xc6\x1d\x74\xdf\xba\x66\xf7\x9d\x3b\xe4\xbe\x77\x2d\xee\x07\x77\xd8\xfd\xe8\x5a\xdd\x4f\xee\x67\xf7\x8b\x6b\x73\x47\x5c\xbb\xf3\x0a\x62\xc4\x8a\x13\x11\x15\x8f\x04\x48\xa0\x74\x91\xae\x72\x8c\x04\xc9\xb1\x72\x9c\x1c\x2f\xc1\x72\x82\x74\x93\x13\x25\x44\x4e\x92\x93\xe5\x14\x09\x95\x53\xe5\x34\xe9\x2e\x61\xd2\x43\x4e\x97\x9e\x12\x2e\xbd\xe4\x0c\xe9\x2d\x11\xd2\x47\xce\x94\xb3\x24\x52\xfa\xca\xd9\x72\x8e\x44\x49\x3f\x39\x57\xfa\xcb\x00\x39\x4f\xce\x97\x81\x12\x2d\x83\xe4\x02\x19\x2c\x43\x64\xa8\x5c\x28\xc3\x24\x46\x2e\x92\x8b\x65\xb8\x8c\x90\x4b\x64\xa4\x5c\x2a\xb1\x72\x99\x8c\x92\xcb\x25\x4e\xae\x90\xd1\x72\xa5\xc4\xcb\x55\x32\x46\xae\x96\x04\xb9\x46\xc6\xca\xb5\x92\x28\xd7\xc9\x38\xb9\x5e\x92\xe4\x06\x19\x2f\x37\x4a\xb2\xdc\x24\x37\xcb\x2d\x92\x22\xb7\xca\x04\xb9\x4d\x52\xe5\x76\x99\x28\x77\x48\x9a\x4c\x92\xc9\x72\xa7\xa4\xcb\x14\x99\x2a\xd3\x24\x43\xee\x92\xe9\x32\x43\x32\x65\xa6\xdc\x2d\xb3\x24\x4b\x66\xcb\x3d\x32\x47\xb2\x65\xae\xcc\x93\xf9\xb2\x40\xee\x95\xbf\xc9\x7d\x92\x23\xf7\xcb\x03\xb2\x50\x72\x65\x91\x3c\x28\x8b\x25\x4f\x96\xc8\x43\xb2\x54\xf2\xe5\x61\x79\x44\x96\x49\x81\x3c\x2a\xcb\xe5\x31\x29\x94\xbf\xcb\x0a\x79\x5c\x8a\xe4\x09\x59\x29\x4f\x4a\xb1\x3c\x25\xab\xe4\x69\x29\x91\x67\x64\xb5\x3c\x2b\xa5\xf2\x9c\xac\x91\xe7\xa5\x4c\x5e\x90\xb5\xf2\x0f\x29\x97\x17\x65\x9d\xbc\x24\x15\xf2\xb2\xac\x97\x57\xa4\x52\x5e\x95\xd7\xe4\x75\xa9\x92\x37\xe4\x4d\xf9\xa7\x54\xcb\x5b\xf2\x2f\x79\x5b\x36\xc8\x3b\xf2\x6f\xd9\x28\x35\xb2\x49\xde\x95\xcd\xb2\x45\xb6\xca\x7b\xf2\xbe\xd4\xca\x36\xf9\x40\xb6\x4b\x9d\xec\x90\x0f\x65\xa7\xec\x92\xdd\xf2\x91\xec\x91\xbd\xb2\x4f\x3e\x96\x4f\xa4\x5e\x3e\x95\xcf\x64\xbf\x34\xc8\xe7\xf2\x85\x7c\x29\x8d\x72\x40\xbe\x92\xaf\xa5\x49\xbe\x91\x83\xf2\xad\x34\xcb\x77\x72\x48\xbe\x97\x16\xf9\x41\x0e\xcb\x8f\xd2\x2a\x3f\xc9\xcf\xf2\x8b\xb4\xc9\x11\x69\x17\xaf\xa2\x46\xad\x3a\x15\x55\xf5\x68\x80\x06\x6a\x17\xed\xaa\xc7\x68\x90\x1e\xab\xc7\xe9\xf1\x1a\xac\x27\x68\x37\x3d\x51\x43\xf4\x24\x3d\x59\x4f\xd1\x50\x3d\x55\x4f\xd3\xee\x1a\xa6\x3d\xf4\x74\xed\xa9\xe1\xda\x4b\xcf\xd0\xde\x1a\xa1\x7d\xf4\x4c\x3d\x4b\x23\xb5\xaf\x9e\xad\xe7\x68\x94\xf6\xd3\x73\xb5\xbf\x0e\xd0\xf3\xf4\x7c\x1d\xa8\xd1\x3a\x48\xff\x1f\xc6\xcd\x3a\xce\x8d\xe3\x6c\xc0\x17\xdb\x03\x6b\x9f\xc3\xed\x57\x4a\xeb\x94\xdb\x34\xa9\x76\x66\x76\x57\x6a\x4a\x82\x99\xc4\x21\x87\xdc\x40\xd3\xa6\xf2\x9d\x7c\xa7\x58\x27\x5d\x74\x3a\x3b\x49\x99\x99\x99\x99\xc9\xb9\x32\x33\x33\x33\x33\x33\xd3\xf7\x3b\xed\xa3\xf5\xf9\x7e\xb2\xe2\xfc\x91\x77\x56\xb3\x3b\xcf\x3b\x2b\xed\x3e\xef\x4c\x72\xa9\xc8\x44\x59\x54\xc4\x9d\xc4\xa9\xe2\xce\xe2\x2e\xe2\xae\xe2\x6e\xe2\xee\xa2\x2a\x6a\xa2\x2e\x1a\xc2\x8b\x20\x4e\x13\xa7\x8b\xed\xe2\x0c\x71\xa6\x38\x4b\x9c\x2d\xce\x11\x3b\xc4\xb9\xe2\x3c\x71\xbe\xb8\x40\x5c\x28\x76\x8a\x7b\x88\x8b\xc4\xc5\xe2\x12\x71\xa9\xb8\xa7\xb8\x4c\xdc\x4b\xdc\x5b\x5c\x2e\xee\x23\x9a\x62\x97\x98\x11\xb3\xa2\x25\x76\x8b\x39\x31\x2f\xda\xe2\x0a\xb1\x47\x74\xc4\x82\xe8\x8a\x9e\x58\x14\x57\x8a\xbe\x58\x12\x03\xb1\x2c\xf6\x8a\x7d\xe2\x2a\x71\xb5\xb8\x46\xdc\x57\xdc\x4f\xdc\x5f\x3c\x40\x3c\x50\x3c\x48\x3c\x58\x3c\x44\x3c\x54\x3c\x4c\x3c\x5c\x3c\x42\x3c\x52\x3c\x4a\x3c\x5a\x3c\x46\x3c\x56\x3c\x4e\x3c\x5e\x3c\x41\x3c\x51\x3c\x49\x3c\x59\x3c\x45\x3c\x55\x3c\x4d\x3c\x5d\x3c\x43\x3c\x53\x3c\x4b\x3c\x5b\x3c\x47\x3c\x57\x3c\x4f\x3c\x5f\xbc\x40\xbc\x50\xbc\x48\xbc\x58\xbc\x44\xbc\x54\xbc\x4c\xbc\x5c\xbc\x42\xbc\x52\xbc\x4a\xbc\x5a\xbc\x46\xbc\x56\xbc\x4e\xbc\x5e\xbc\x41\xbc\x51\xec\x17\xd7\x8a\x15\xf1\x26\xf1\x66\xf1\x16\xf1\x56\xf1\x36\xf1\x76\xf1\x0e\xf1\x4e\xf1\x2e\xf1\x6e\xf1\x1e\xf1\x5e\xf1\x3e\xf1\x7e\xf1\x01\xf1\x41\xf1\x21\xf1\x61\xf1\x11\xf1\x51\xf1\x31\xf1\x71\xf1\x09\xf1\x49\xf1\x29\xf1\x69\xf1\x19\xf1\x59\xf1\x39\xf1\x79\xf1\x05\xf1\x45\xf1\x25\xf1\x65\xf1\x15\xf1\x55\xf1\x35\xf1\x75\xf1\x0d\xf1\x4d\xf1\x2d\xf1\x6d\xf1\x1d\xf1\x5d\xf1\x3d\xf1\x7d\xf1\x03\xf1\x43\xf1\x23\xf1\x63\xf1\x13\xf1\x53\xf1\x33\xf1\x73\xf1\x0b\xf1\x4b\xf1\x2b\xf1\x6b\xf1\x1b\xf1\x5b\xf1\x3b\xf1\x7b\xf1\x07\xf1\x47\xf1\x27\xf1\x67\xf1\x17\xf1\x57\xf1\x37\xf1\x77\xf1\x0f\xf1\x4f\xf1\x2f\xf1\x6f\xf1\x1f\xf1\x5f\xf1\x3f\x39\x25\x8f\x90\x1b\xe4\x46\xb9\x49\x0a\x29\xa5\x92\x5a\x46\x72\xb3\xdc\x22\xa7\xe5\x56\x79\xa4\x3c\x4a\x1e\x2d\x8f\x91\xc7\xca\xe3\xe4\xf1\xf2\x7a\xf2\xfa\xf2\xff\xe4\x0d\xe4\x0d\xe5\x8d\xe4\x8d\xe5\x4d\xe4\x09\xf2\xa6\xf2\x66\x72\x9b\x3c\x51\xde\x5c\xde\x42\xde\x52\xde\x4a\xde\x5a\xde\x46\xde\x56\xde\x4e\xde\x5e\x9e\x24\xef\x20\x4f\x96\xa7\xc8\x3b\xca\x92\x8c\xa5\x91\x56\x3a\x99\xc8\x54\x66\xb2\x2c\x2b\xf2\x4e\xf2\x54\x79\x67\x79\x17\x79\x57\x79\x37\x79\x77\x59\x95\x35\x59\x97\x0d\xe9\x65\x90\xa7\xc9\xd3\xe5\x76\x79\x86\x3c\x53\x9e\x25\xcf\x96\xe7\xc8\x1d\xf2\x5c\x79\x9e\x3c\x5f\x5e\x20\x2f\x94\x3b\xe5\x3d\xe4\x45\xf2\x62\x79\x89\xbc\x54\xde\x53\x5e\x26\xef\x25\xef\x2d\x2f\x97\xf7\x91\x4d\xb9\x4b\xce\xc8\x59\xd9\x92\xbb\xe5\x9c\x9c\x97\x6d\x79\x85\xdc\x23\x3b\x72\x41\x76\x65\x4f\x2e\xca\x2b\x65\x5f\x2e\xc9\x81\x5c\x96\x7b\xe5\x3e\x79\x95\xbc\x5a\x5e\x23\xef\x2b\xef\x27\xef\x2f\x1f\x20\x1f\x28\x1f\x24\x1f\x2c\x1f\x22\x1f\x2a\x1f\x26\x1f\x2e\x1f\x21\x1f\x29\x1f\x25\x1f\x2d\x1f\x23\x1f\x2b\x1f\x27\x1f\x2f\x9f\x20\x9f\x28\x9f\x24\x9f\x2c\x9f\x22\x9f\x2a\x9f\x26\x9f\x2e\x9f\x21\x9f\x29\x9f\x25\x9f\x2d\x9f\x23\x9f\x2b\x9f\x27\x9f\x2f\x5f\x20\x5f\x28\x5f\x24\x5f\x2c\x5f\x22\x5f\x2a\x5f\x26\x5f\x2e\x5f\x21\x5f\x29\x5f\x25\x5f\x2d\x5f\x23\x5f\x2b\x5f\x27\x5f\x2f\xdf\x20\xdf\x28\xf7\xcb\x6b\xe5\x8a\x7c\x93\x7c\xb3\x7c\x8b\x7c\xab\x7c\x9b\x7c\xbb\x7c\x87\x7c\xa7\x7c\x97\x7c\xb7\x7c\x8f\x7c\xaf\x7c\x9f\x7c\xbf\xfc\x80\xfc\xa0\xfc\x90\xfc\xb0\xfc\x88\xfc\xa8\xfc\x98\xfc\xb8\xfc\x84\xfc\xa4\xfc\x94\xfc\xb4\xfc\x8c\xfc\xac\xfc\x9c\xfc\xbc\xfc\x82\xfc\xa2\xfc\x92\xfc\xb2\xfc\x8a\xfc\xaa\xfc\x9a\xfc\xba\xfc\x86\xfc\xa6\xfc\x96\xfc\xb6\xfc\x8e\xfc\xae\xfc\x9e\xfc\xbe\xfc\x81\xfc\xa1\xfc\x91\xfc\xb1\xfc\x89\xfc\xa9\xfc\x99\xfc\xb9\xfc\x85\xfc\xa5\xfc\x95\xfc\xb5\xfc\x8d\xfc\xad\xfc\x9d\xfc\xbd\xfc\x83\xfc\xa3\xfc\x93\xfc\xb3\xfc\x8b\xfc\xab\xfc\x9b\xfc\xbb\xfc\x87\xfc\xa7\xfc\x97\xfc\xb7\xfc\x8f\xfc\xaf\xfc\x9f\x9a\x52\x47\xa8\x0d\x6a\xa3\xda\xa4\x84\x92\x4a\x29\xad\x22\xb5\x59\x6d\x51\xd3\x6a\xab\x3a\x52\x1d\xa5\x8e\x56\xc7\xa8\x63\xd5\x71\xea\x78\x75\x3d\x75\x7d\xf5\x7f\xea\x06\xea\x86\xea\x46\xea\xc6\xea\x26\xea\x04\x75\x53\x75\x33\xb5\x4d\x9d\xa8\x6e\xae\x6e\xa1\x6e\xa9\x6e\xa5\x6e\xad\x6e\xa3\x6e\xab\x6e\xa7\x6e\xaf\x4e\x52\x77\x50\x27\xab\x53\xd4\x1d\x55\x49\xc5\xca\x28\xab\x9c\x4a\x54\xaa\x32\x55\x56\x15\x75\x27\x75\xaa\xba\xb3\xba\x8b\xba\xab\xba\x9b\xba\xbb\xaa\xaa\x9a\xaa\xab\x86\xf2\x2a\xa8\xd3\xd4\xe9\x6a\xbb\x3a\x43\x9d\xa9\xce\x52\x67\xab\x73\xd4\x0e\x75\xae\x3a\x4f\x9d\xaf\x2e\x50\x17\xaa\x9d\xea\x1e\xea\x22\x75\xb1\xba\x44\x5d\xaa\xee\xa9\x2e\x53\xf7\x52\xf7\x56\x97\xab\xfb\xa8\xa6\xda\xa5\x66\xd4\xac\x6a\xa9\xdd\x6a\x4e\xcd\xab\xb6\xba\x42\xed\x51\x1d\xb5\xa0\xba\xaa\xa7\x16\xd5\x95\xaa\xaf\x96\xd4\x40\x2d\xab\xbd\x6a\x9f\xba\x4a\x5d\xad\xae\x51\xf7\x55\xf7\x53\xf7\x57\x0f\x50\x0f\x54\x0f\x52\x0f\x56\x0f\x51\x0f\x55\x0f\x53\x0f\x57\x8f\x50\x8f\x54\x8f\x52\x8f\x56\x8f\x51\x8f\x55\x8f\x53\x8f\x57\x4f\x50\x4f\x54\x4f\x52\x4f\x56\x4f\x51\x4f\x55\x4f\x53\x4f\x57\xcf\x50\xcf\x54\xcf\x52\xcf\x56\xcf\x51\xcf\x55\xcf\x53\xcf\x57\x2f\x50\x2f\x54\x2f\x52\x2f\x56\x2f\x51\x2f\x55\x2f\x53\x2f\x57\xaf\x50\xaf\x54\xaf\x52\xaf\x56\xaf\x51\xaf\x55\xaf\x53\xaf\x57\x6f\x50\x6f\x54\xfb\xd5\xb5\x6a\x45\xbd\x49\xbd\x59\xbd\x45\xbd\x55\xbd\x4d\xbd\x5d\xbd\x43\xbd\x53\xbd\x4b\xbd\x5b\xbd\x47\xbd\x57\xbd\x6f\x6a\x65\xea\x4d\xea\xfd\xea\x03\xea\x83\x53\x6f\x9d\x7a\xdb\xd4\x87\xd5\x87\xa6\xde\x3c\xf5\x96\xa9\x8f\xa8\x0f\x4f\x3d\x64\xea\x83\x53\x8f\x9c\x7a\xad\xfa\x88\xfa\xa8\xfa\x98\xfa\xb8\xfa\x84\xfa\xe4\xd4\x47\xd5\xa7\xd4\xa7\xd5\x67\xa6\xde\x3b\xf5\x3e\xf5\x59\xf5\xb9\xa9\x77\xab\xcf\xab\x2f\xa8\x2f\xaa\x2f\xa9\x2f\xab\xaf\xa8\xaf\xaa\xaf\xa9\xaf\xab\x6f\xa8\x6f\xaa\x6f\xa9\x6f\xab\xef\xa8\xef\xaa\xef\xa9\xef\xab\x1f\xa8\x1f\xaa\x1f\xa9\x1f\xab\x9f\xa8\x9f\xaa\x9f\x4d\xfd\x4d\xfd\x5c\xfd\x42\xfd\x52\xfd\x4a\xfd\x5a\xfd\x46\xfd\x56\xfd\x4e\xfd\x5e\xfd\x41\xfd\x51\xfd\x49\xfd\x59\xfd\x45\xfd\x55\xfd\x4d\xfd\x5d\xfd\x43\xfd\x53\xfd\x4b\xfd\x5b\xfd\x47\xfd\x57\xfd\x6f\xea\x71\x7a\x4a\x1f\xa1\x37\xe8\x8d\x7a\x93\x16\x5a\x6a\xa5\xb5\x8e\xf4\x66\xbd\x45\x4f\xeb\xad\xfa\x48\x7d\x94\x3e\x5a\x1f\x33\xf5\x2c\x7d\xec\xd4\x73\xa6\x9e\x3d\xf5\x3b\x7d\x9c\x3e\x7e\xea\xe5\x53\x4f\xd1\xd7\xd3\xd7\x9f\x7a\xde\xd4\x2b\xa7\x9e\xa8\xff\x6f\xea\x69\x53\x4f\xd7\x37\xd0\x37\xd4\x37\xd2\x37\xd6\x37\xd1\x27\xe8\x9b\xea\x9b\xe9\x6d\xfa\x44\x7d\x73\x7d\x0b\x7d\x4b\x7d\x2b\x7d\x6b\x7d\x1b\x7d\x5b\x7d\x3b\x7d\x7b\x7d\x92\xbe\x83\x3e\x59\x9f\xa2\xef\xa8\x4b\x3a\xd6\x46\x5b\xed\x74\xa2\x53\x9d\xe9\xb2\xae\xe8\x3b\xe9\x53\xf5\x9d\xf5\x5d\xf4\x5d\xf5\xdd\xf4\xdd\x75\x55\xd7\x74\x5d\x37\xb4\xd7\x41\x9f\xa6\x4f\xd7\xdb\xf5\x19\xfa\x4c\x7d\x96\x3e\x5b\x9f\xa3\x77\xe8\x73\xf5\x79\xfa\x7c\x7d\x81\xbe\x70\xea\x1d\x7a\xa7\xbe\x87\xbe\x48\x5f\xac\x2f\xd1\x97\xea\x7b\xea\xcb\xf4\xbd\xf4\xbd\xf5\xe5\xfa\x3e\xba\xa9\x77\xe9\x19\x3d\xab\x5b\x7a\xb7\x9e\xd3\xf3\xba\xad\xaf\xd0\x7b\x74\x47\x2f\xe8\xae\xee\xe9\x45\x7d\xa5\xee\xeb\x25\x3d\xd0\xcb\x7a\xaf\xde\xa7\xaf\xd2\x57\xeb\x6b\xf4\x7d\xf5\xfd\xf4\xfd\xf5\x03\xf4\x03\xf5\x83\xf4\x83\xf5\x43\xf4\x43\xf5\xc3\xf4\xc3\xf5\x23\xf4\x23\xf5\xa3\xf4\xa3\xf5\x63\xf4\x63\xf5\xe3\xf4\xe3\xf5\x13\xf4\x13\xf5\x93\xf4\x93\xf5\x53\xf4\x53\xf5\xd3\xf4\xd3\xf5\x33\xf4\x33\xf5\xb3\xf4\xb3\xf5\x73\xf4\x73\xf5\xf3\xf4\xf3\xf5\x0b\xf4\x0b\xf5\x8b\xf4\x8b\xf5\x4b\xf4\x4b\xf5\xcb\xf4\xcb\xf5\x2b\xf4\x2b\xf5\xab\xf4\xab\xf5\x6b\xf4\x6b\xf5\xeb\xf4\xeb\xf5\x1b\xf4\x1b\xf5\x7e\x7d\xad\x5e\xd1\x6f\xd2\x6f\xd6\x6f\xd1\x6f\xd5\x6f\xd3\x6f\xd7\xef\xd0\xef\xd4\xef\xd2\xef\xd6\xef\xd1\xef\xd5\xef\xd3\xef\xd7\x1f\xd0\x1f\xd4\x1f\xd2\x1f\xd6\x1f\xd1\x1f\xd5\x1f\xd3\x1f\xd7\x9f\xd0\x9f\xd4\x9f\xd2\x9f\xd6\x9f\xd1\x9f\xd5\x9f\xd3\x9f\xd7\x5f\xd0\x5f\xd4\x5f\xd2\x5f\xd6\x5f\xd1\x5f\xd5\x5f\xd3\x5f\xd7\xdf\xd0\xdf\xd4\xdf\xd2\xdf\xd6\xdf\xd1\xdf\xd5\xdf\xd3\xdf\xd7\x3f\xd0\x3f\xd4\x3f\xd2\x3f\xd6\x3f\xd1\x3f\xd5\x3f\xd3\x3f\xd7\xbf\xd0\xbf\xd4\xbf\xd2\xbf\xd6\xbf\xd1\xbf\xd5\xbf\xd3\xbf\xd7\x7f\xd0\x7f\xd4\x7f\xd2\x7f\xd6\x7f\xd1\x7f\xd5\x7f\xd3\x7f\xd7\xff\xd0\xff\xd4\xff\xd2\xff\xd6\xff\xd1\xff\xd5\xff\x8b\xa6\xa2\x23\xa2\x0d\xd1\xc6\x68\x53\x24\x22\x19\xa9\x48\x47\x51\xb4\x39\xda\x12\x4d\x47\x5b\xa3\x23\xa3\xa3\xa2\xa3\xa3\x63\xa2\x63\xa3\xe3\xa2\xe3\xa3\xeb\x45\xd7\x8f\xfe\x2f\xba\x41\x74\xc3\xe8\x46\xd1\x8d\xa3\x9b\x44\x27\x44\x37\x8d\x6e\x16\x6d\x8b\x4e\x8c\x6e\x1e\xdd\x22\xba\x65\x74\xab\xe8\xd6\xd1\x6d\xa2\xdb\x46\xb7\x8b\x6e\x1f\x9d\x14\xdd\x21\x3a\x39\x3a\x25\xba\x63\x54\x8a\xe2\xc8\x44\x36\x72\x51\x12\xa5\x51\x16\x95\xa3\x4a\x74\xa7\xe8\xd4\xe8\xce\xd1\x5d\xa2\xbb\x46\x77\x8b\xee\x1e\x55\xa3\x5a\x54\x8f\x1a\x91\x8f\x42\x74\x5a\x74\x7a\xb4\x3d\x3a\x23\x3a\x33\x3a\x2b\x3a\x3b\x3a\x27\xda\x11\x9d\x1b\x9d\x17\x9d\x1f\x5d\x10\x5d\x18\xed\x8c\xee\x11\x5d\x14\x5d\x1c\x5d\x12\x5d\x1a\xdd\x33\xba\x2c\xba\x57\x74\xef\xe8\xf2\xe8\x3e\x51\x33\xda\x15\xcd\x44\xb3\x51\x2b\xda\x1d\xcd\x45\xf3\x51\x3b\xba\x22\xda\x13\x75\xa2\x85\xa8\x1b\xf5\xa2\xc5\xe8\xca\xa8\x1f\x2d\x45\x83\x68\x39\xda\x2b\xe7\x3a\x57\x2f\xce\xc7\x6a\xb9\xdb\x2e\x95\x4a\x8d\x3c\x56\x4b\x44\x8e\x6b\x86\x68\x89\x09\xb1\xa2\xaa\x0b\xcd\x99\x7e\xaf\xab\x9a\x79\x94\xd5\x5d\xfd\xd6\xde\x96\x6c\x0e\x83\xaa\xf6\xe6\x7a\xdd\xd6\x1e\xd5\xcc\xe3\x96\xfa\x4c\xbb\x3f\xb3\xbc\xb0\xbb\xd3\xba\x6a\xcb\xcc\x81\xf6\xe6\xfa\x6c\x6f\xd0\x9c\x99\x69\x75\x07\x9b\x67\x8a\xa6\x6c\xcc\x34\x57\x87\x9c\xcd\x43\x63\xa6\xdf\x6b\x0e\x94\x07\xd8\x02\xe8\x73\x60\x6b\x18\x36\xfb\x03\x03\xb5\x8a\xa6\xf2\xa4\xd1\xca\xa3\xf4\xf9\x88\xad\x61\xd8\x72\xda\x9a\xa4\xe6\xd6\x24\x75\xda\x81\xb1\xe6\x8a\xe6\xf4\x69\x33\xbd\x85\x85\x26\x07\x73\x6b\x0e\xb6\x9c\xbe\x66\x9c\xf9\x03\xed\x4d\xa7\xef\x6a\xf6\x37\xcd\xef\x6a\xf6\xe5\xf6\x41\xbb\x33\xdb\x92\xed\x61\x50\xdb\x99\x49\x9b\x99\x6c\xcf\x67\xd2\xce\x6f\xdd\x76\x72\x6e\xe7\x71\xc3\xf6\x33\x36\xb4\xaf\xd8\x72\xc6\x1a\xc6\x15\x07\xda\xd3\x67\xae\xcd\x6a\xcf\x41\x07\x73\xfd\x56\xab\xdb\x69\x76\x67\xdb\x33\xf2\xac\xe6\xcc\xf2\xa0\x25\x3b\xc3\x30\x7d\xd6\xda\xf3\x3a\x6b\x0e\xe4\x59\xf9\x0d\xea\x0c\xc3\xa6\xb3\x66\x7b\x83\x4d\x9d\xd9\xde\x40\x9e\x93\x5f\xdf\xcd\xaf\x3f\x67\xed\xf5\xdd\xb5\xd7\x9f\x93\x5f\xdf\xcd\x6f\x70\xb7\xb9\xd8\x5b\x1a\xf4\x7b\x8b\xf3\xad\x8d\xbe\x3b\xb7\xb1\xd5\x9d\x53\x3b\x98\x7c\x8f\xc9\xef\xc8\x27\xdf\x1b\x86\xad\x3b\xe6\x97\xbb\x73\xcd\xfe\xf2\x42\xa7\xb9\x3c\xd8\xda\x5b\x7b\x24\xcf\xcf\x73\xe8\xe7\x39\x9c\xbf\x36\x87\xfe\xda\x1c\xce\xcf\x73\xe8\xe7\xe1\x82\xfc\xaa\xa5\x61\xd8\x72\xc1\x9a\xdb\xb8\xb4\xe6\x36\x5e\xb8\x76\xb4\xc1\xda\xd1\x2e\xcc\x87\x19\xe4\x77\xe4\xc2\xd5\xaf\x74\xb0\xfa\x95\xee\xcc\xbf\xd2\xe5\xfc\x2b\xdd\xc9\xac\x96\x99\xd5\xce\x7c\x56\xcb\xc3\x20\x76\xf6\xdb\xdd\x39\xb1\xbc\xfa\xef\xad\x3b\x0f\x9a\xe1\xf2\xda\x23\xb5\x93\xaf\x7e\x99\xa7\xe6\xa2\x35\xd9\xee\x5b\xd3\xbe\x64\x4d\xfb\xea\x03\x6d\x79\x69\x3e\xd7\x6b\x86\x61\xf3\xa5\x07\x7e\xc6\xd7\x14\x4d\xd1\xe9\x75\xe7\x96\x86\x4f\x71\x5c\x2e\x11\x63\xa2\x21\x5a\xa2\x23\x26\xc4\x94\x98\x11\xcb\xc4\x0a\xb1\x4a\xac\x11\xeb\xc4\x06\xd1\x13\x43\x1e\x2b\xf0\x2b\xf0\x2b\x70\x2b\x70\x2b\x70\x2b\x70\x2b\x70\x2b\x70\x2b\x70\x2b\x70\x2b\x70\x2b\x70\x2b\x70\x2b\x70\x2b\x41\xec\x98\xef\xf5\xbb\xa2\xb7\xfa\xef\xfc\xb3\x2a\x73\xae\xc2\xae\xc2\xae\xc2\xae\xc2\xae\xc2\xae\xc2\xae\xc2\xae\xc2\xae\xc2\xae\xc2\xe6\x0d\x1a\x57\xbd\xd8\x39\x64\x2e\x1f\x60\xd6\x98\x2f\x6f\xd7\x98\xb7\x6b\x5c\x83\xcd\x5b\x36\xae\xc1\xae\xc1\xae\xc1\xae\xc1\xae\xc1\xae\xc1\xae\xc1\xae\xc1\xae\x31\xef\x1a\xf7\xbb\xce\xfd\xae\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\xaf\xc3\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\x6f\xc0\xf7\xf0\x3d\x7c\x0f\xdf\xc3\xf7\xf0\x7d\x22\x4f\xcb\x9f\xfa\xb9\x61\xe0\x53\xe8\x1e\xba\x87\xee\xa1\x7b\xe8\x1e\xba\x87\xee\xa1\x07\xe8\x01\x7a\x80\x1e\xa0\x07\xe8\x81\xd9\x07\x66\x1f\x98\x7d\x80\x1f\x2a\x9b\xab\xab\x6f\x92\xfc\x21\x6f\x16\x4d\x55\xf5\x79\x6c\xb6\xf2\x77\xdd\x8e\xa5\x4e\x73\x69\x3e\x6f\xf7\x0e\xb4\x87\xa3\x98\x52\x89\x18\x13\x0d\xd1\x12\x1d\x31\x21\xa6\xc4\x8c\x58\x26\x56\x88\x55\x62\x8d\x58\x27\x36\x88\x9e\x98\xdf\x0d\x13\xc3\x8f\xe1\xc7\xf0\x63\xf8\x31\xfc\x18\x7e\x0c\x3f\xce\xa6\x2f\x58\xfb\xae\x5e\x5a\x73\xc0\x19\x64\x12\x93\x49\x4c\x26\x31\x99\xc4\x64\x12\x93\x89\x21\x13\x43\x26\x86\x4c\x0c\x99\x18\x32\x31\x64\x62\xc8\xc4\x70\x27\x0c\x77\xc2\x70\x27\x0c\x7c\x03\xdf\xc0\x37\xf0\x0d\x7c\x03\xdf\xc2\xb7\xf0\x2d\x7c\x0b\xdf\xc2\xb7\xf0\x2d\x7c\x0b\xdf\xc2\xb7\xf0\x2d\x7c\x0b\xdf\xc2\xb7\xf0\x2d\x7c\x0b\xdf\xc1\x77\xf0\x1d\x7c\x07\xdf\xc1\x77\xf0\x1d\x7c\x07\xdf\xc1\x77\xf0\x1d\x7c\x07\xdf\xc1\x77\xf0\x1d\x7c\x07\x3f\x81\x9f\xc0\x4f\xe0\x27\xf0\x13\xf8\x09\xfc\x04\x7e\x02\x3f\x81\x9f\xc0\x4f\xe0\x27\xf0\x13\xf8\x09\xfc\x04\x7e\x02\x3f\x85\x9f\xc2\x4f\xe1\xa7\xf0\x53\xf8\x29\xfc\x14\x7e\x0a\x3f\x85\x9f\xc2\x4f\xe1\xa7\xf0\x53\xf8\x29\xfc\x14\x7e\x0a\x3f\x83\x9f\xc1\xcf\xe0\x67\xf0\x33\xf8\x19\xfc\x0c\x7e\x06\x3f\x83\x9f\xc1\xcf\xe0\x67\xf0\x33\xf8\x19\xfc\x0c\x7e\x06\x9f\x2a\xc0\x50\x05\x18\xaa\x00\x43\x15\x60\xa8\x02\x0c\x55\x80\xa1\x0a\x30\x54\x01\x86\x2a\xc0\x50\x05\x18\xaa\x00\x43\x15\x60\xa8\x02\x0c\x55\x80\xa1\x0a\x30\x54\x01\x86\x2a\xc0\x50\x05\x98\x0a\x7c\xaa\x01\x43\x35\x60\xa8\x06\x0c\xd5\x80\xa1\x1a\x30\x54\x03\x86\x6a\xc0\x50\x0d\x18\xaa\x01\x43\x35\x60\xa8\x06\x0c\xd5\x80\xa9\xc0\x67\xcd\x63\xaa\xf0\xa9\x08\x0c\x15\x81\xa1\x22\x30\x54\x04\x86\x8a\xc0\x50\x11\x18\x2a\x02\x43\x45\x60\xa8\x08\x0c\x15\x81\xa1\x22\x30\x54\x04\xa6\x0a\xbf\x0a\xbf\x06\x9f\xaa\xc0\x50\x15\x18\xaa\x02\x43\x55\x60\xa8\x0a\x0c\x55\x81\xa1\x2a\x30\x54\x05\x86\xaa\xc0\x50\x15\x98\x5a\x2d\x6a\xee\x6e\xb7\x93\xac\x62\x2a\xc3\x56\xea\x2a\xa3\x77\x06\x95\x81\xa1\x32\x30\x54\x06\x86\xca\xc0\x50\x19\x18\x2a\x03\x43\x65\x60\xa8\x0c\x0c\x95\x80\xa1\x12\x30\x54\x02\x86\x4a\xc0\x50\x09\x18\x2a\x01\x43\x25\x60\xa8\x04\x0c\x95\x80\xa1\x12\x30\x54\x02\x86\x4a\xc0\x50\x09\x18\x2a\x01\x43\x25\x60\xa8\x04\x0c\x66\x37\x98\xdd\x60\x76\x83\xd9\x0d\x66\x37\x98\xdd\x60\x76\xe3\x19\xcf\x33\x9e\x67\x3c\xdc\x6e\x70\xbb\xc1\xed\x06\xb7\x1b\xdc\x6e\x70\xbb\xc1\xed\x06\xb7\x1b\xdc\x6e\x70\xbb\xc1\xed\x06\xb7\x1b\xdc\x6e\x70\xbb\xc1\xed\x06\xb7\x1b\xdc\x6e\x02\xfc\x00\x3f\xc0\x0f\xf0\x03\xfc\x00\x3f\x84\x68\xae\xdf\xdc\xdb\x9a\xe9\x2d\xec\x8a\x86\x76\x5f\x6d\x0d\xfb\x6c\xc9\x44\xc3\xb5\xc9\x9a\x4f\x1c\x31\x21\xa6\xc4\x8c\x58\xde\x3a\xdf\xeb\xed\x69\xee\xea\xed\x5d\x7b\x55\x95\x58\x23\xd6\x89\x0d\xa2\x27\xe6\xf7\xc2\x62\x76\x8b\xd9\x2d\x66\xb7\x98\xdd\x62\x76\x8b\xd9\x2d\x66\xb7\x31\x59\xc4\x65\x62\x85\x08\x1f\x9f\x5b\x7c\x6e\xf1\xb9\xc5\xe7\x16\x9f\x5b\x7c\x6e\xf1\xb9\x35\x66\x7a\xb6\x37\xd8\xd5\xea\xf4\xf6\x1d\x98\x14\x52\xb7\x48\xdd\x22\x75\x8b\xd4\x2d\x52\xb7\x48\xdd\x22\x75\x8b\xd4\x2d\x52\xb7\x48\xdd\x22\x75\x8b\xd4\x2d\x52\xb7\x48\xdd\x22\x75\x8b\xd4\x2d\x52\xb7\x48\xdd\x22\x75\xcb\x03\x6a\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xba\x45\xea\x16\xa9\x5b\xa4\x6e\x91\xb6\x45\xda\x16\x29\x5b\xa4\x6c\x91\xb2\x45\xca\x36\xf3\x62\xd0\xeb\xf6\x96\xb6\xce\xb6\x5b\xfd\xd6\x52\x7b\x69\x78\xb4\xb9\xda\x59\x9c\x6f\x0e\x9b\x51\xb3\xdb\x1b\xb4\x3a\xad\x76\x73\xda\x2f\x2e\xb5\x3b\xbd\xee\xf0\x63\xed\x07\xf4\x6f\xef\xd1\x9a\xde\xb1\xd0\x9e\xe9\xd3\x3f\xbd\x73\xcd\xc9\x9b\x77\x2c\xb4\xe6\xf2\x93\x8e\x69\xf7\x06\xcd\x83\x58\x62\xc8\xda\x54\x6b\x0d\x9a\xe2\xb4\xe6\xc2\x42\x53\xc1\xd9\x74\x69\x6b\xd0\xdc\xe8\x07\x4d\x71\xe1\x7c\x6b\xd0\xdc\xb4\x0a\x12\x67\x36\x17\x17\x9b\xf2\xac\xe6\xc2\xae\xd9\xe6\x86\xb3\x97\x37\x9c\xb3\xbc\xe1\xe2\xb6\x82\xbc\xe1\xdc\xf6\xc6\xf3\xe7\x7b\xe2\x82\xf6\xdc\x42\x73\xe3\x85\xcd\x65\x45\x16\x1b\xcf\x9d\x6f\x6f\xac\xcf\xb7\x37\x9e\xbb\xd4\x9e\xde\xbe\x26\x83\xa3\x38\x61\x74\xbc\xb9\x59\x4c\x7c\xba\xb5\x76\xba\xad\xd1\x74\xdb\xa3\xe9\x1e\xbf\x7c\xf0\xa5\xf9\x64\x86\xd7\x6f\xda\xb5\x3a\x99\xb9\xd5\xc9\x88\xd9\x56\x67\xd0\x54\x8c\xb5\xe9\x9a\xd5\x29\xad\x76\x0e\x86\x53\x5a\x1d\x4c\xec\x19\x4e\xa9\x93\x4f\xa9\xbb\xbc\xe1\xaa\xb6\xea\xe5\xf3\xd9\xd8\x9f\xef\xc9\xa5\xd5\xc9\xc4\x62\x18\x36\x0e\x9a\xcb\x0a\xee\xc6\xc5\xf9\xf6\xc6\x99\xf9\xf6\xc6\xc5\xa5\xb6\xe8\xad\xde\xe0\xe9\xb5\xf7\xf6\xa8\x75\xe9\x4d\xf7\xd6\x7e\x3b\xcb\x6b\xbf\x9d\x5e\xf1\xed\xe4\xbf\x89\x46\x49\x0e\xd3\x8b\x35\x77\x87\xdf\x32\x92\xb4\x0d\xb7\x69\x71\xbe\x1d\xcb\xe1\x75\xa3\x3e\x7e\xbf\x2c\x95\x2d\x4b\x65\xcb\x52\xd9\xb2\x54\xb6\x2c\x95\x2d\x4b\x65\x8b\x50\x2d\x42\xb5\x08\xd5\x22\x54\x8b\x50\x2d\x42\xb5\x08\xd5\x22\x54\x8b\x50\x2d\x42\xb5\x08\xd5\x22\x54\x8b\x50\x2d\x42\xb5\x08\xd5\x22\x54\x8b\x50\x2d\x42\xb5\x08\xd5\x22\x54\x8b\x50\x2d\x42\xb5\x08\xd5\x22\x54\x8b\x50\x2d\x42\xb5\x08\xd5\x22\x54\x8b\x50\x2d\x42\xb5\x08\xd5\x22\x54\x8b\x50\x6d\xc8\xf9\xae\x54\x1a\x96\x4c\x71\xa9\x64\xec\xa8\x95\xc4\x45\xcb\x14\xad\x03\xbd\xae\x68\x25\x45\x2b\x2d\x5a\x59\xd1\x2a\x17\xad\xca\xa8\x95\x16\x34\xde\x57\xae\xd4\x28\x3e\x19\xb1\x62\x57\x8c\x1b\x17\xa3\xc5\xc5\x68\x71\x31\x9a\x39\x90\x7b\x91\xb1\x29\x32\x36\x45\x9e\xa6\x18\xcf\x14\x79\x9a\x62\x64\x53\x8c\x6c\x8a\x91\x6d\x31\xb2\x2d\x46\xb6\xc5\xc8\xb6\xb8\x17\xb6\x60\xd8\x82\x61\x0b\x86\x2d\x18\xb6\x60\xd8\x82\xe1\x0a\x86\x2b\x18\xae\x60\xb8\x82\xe1\x0a\xc6\x81\xfb\xe2\x0a\x86\x2b\x18\xae\x60\xb8\x03\xf7\xbb\xb8\x22\x2d\xae\x48\x8b\x2b\xd2\xe2\x8a\xb4\xb8\x22\x2b\xb2\xca\x8a\x5c\xb2\x22\x97\xac\xc8\x25\x2b\x46\xce\x8a\x91\xb3\x62\xe4\xac\x18\x39\x2b\x46\x2e\x17\x23\x97\x8b\xf9\x96\x0b\x46\xb9\x60\x94\x0b\x46\xb9\x60\x94\x0b\x46\xb9\x60\x94\x0b\x46\xb9\x60\x54\x0a\x46\xa5\x60\x54\x0a\x46\xa5\x60\x54\x0a\x46\xa5\x60\x54\x0a\x06\x0b\x2e\x97\x1c\xb8\x17\x07\x46\x1b\xb1\xe2\xe2\xc9\x89\x4b\x71\xd1\x2a\x7e\xc3\x25\x5b\xb4\x5c\xd1\x4a\x8a\x56\x5a\xb4\xb2\xa2\x55\x2e\x5a\x15\xf8\xa3\x67\x23\x8e\x0b\x16\x8b\x45\x87\xf7\x5d\x5a\xb0\x8b\xdf\xc4\x68\x5b\xd9\xa5\xa3\x98\x10\x53\x22\xf3\xc3\xfd\x0e\xf7\x3b\xdc\xef\x70\xbf\xc3\xfd\x0e\xf7\x3b\xdc\xef\x70\xbf\x63\x41\xef\xb2\x03\x39\x14\xb3\x29\xee\x6b\x5c\xfc\x2e\x47\xdb\xdb\x2e\x1b\x45\xf2\x60\x61\xef\x58\xd8\x3b\x6a\x08\x47\x0d\xe1\xa8\x21\x1c\x35\x84\x63\x61\xef\x58\xd8\x3b\x16\xf6\x8e\x85\xbd\x63\x61\xef\x58\xd8\x3b\x16\xf6\x8e\x85\xbd\x63\x61\xef\x58\xd8\x3b\x16\xf6\x8e\x85\xbd\x63\x61\xef\x58\xd8\x3b\x16\xf6\x8e\x85\xbd\x63\x61\xef\xca\xa1\x78\xc3\x1d\xf8\xdd\x31\x16\x8b\x7b\x37\xfa\xbe\x46\xdf\x09\x8b\x7b\x37\xba\x17\xa3\xdf\x5a\x71\x1d\x39\xb0\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x2c\xee\x1d\x8b\x7b\xc7\xe2\xde\xb1\xb8\x77\x6c\xf9\x3b\xb6\xfc\x1d\x5b\xfe\x8e\x85\xbd\x63\x61\xef\x58\xd8\x3b\x16\xf6\x8e\x85\xbd\x63\x61\xef\x58\xd8\x3b\x16\xf6\x8e\x2d\x7f\xc7\x96\xbf\x63\xa1\xef\x58\xe8\x3b\x16\xfa\x8e\x85\xbe\x63\xa1\xef\x58\xe8\x3b\x16\xfa\x8e\x85\xbe\x63\xa1\xef\x58\xe8\x3b\x16\xfa\x8e\x1a\xc6\xb1\xd0\x77\x2c\xf4\x1d\x0b\x7d\x47\x1d\xe3\x1a\xa3\xa7\xa4\xec\x46\x3d\x64\x40\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x8e\x4a\xc6\x51\xc9\x38\x2a\x19\x47\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x8e\x4a\xc6\x51\xc9\x38\x2a\x19\x47\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x8e\x4a\xc6\x51\xc9\x38\x2a\x19\x47\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x8e\x4a\xc6\x51\xc9\x38\x2a\x19\x47\x25\xe3\xa8\x64\x1c\x95\x8c\xa3\x92\x71\x54\x32\x09\x1b\xfd\x09\x1b\xfd\x09\x1b\xfd\x09\x1b\xfd\x09\x9b\x02\x09\x9b\x02\x09\x9b\x02\x09\x9b\x02\x09\x1b\xfd\x09\x6f\xdf\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\x80\x84\xed\xfd\x84\xed\xfd\x84\x9d\x80\x84\x9d\x80\x84\x9d\x80\x24\xdf\x09\x88\x1b\xf9\xfd\x8b\x1b\xf9\xfd\x8b\x1b\xf9\xfd\x8b\x1b\xf9\xfd\x8b\x1b\xf9\xfd\x8b\x1b\xf9\xfd\x8b\x1b\xf9\xfd\x8b\x1b\xa5\xd1\xf5\x65\x62\x85\x58\x25\xd6\x88\x75\x62\x83\xe8\x89\x21\x8f\x31\xfc\x18\x7e\x0c\x3f\x86\x1f\xc3\x8f\xe1\xc7\xf0\x63\xf8\x31\xfc\x18\x7e\x0c\x3f\x86\x1f\xc3\x8f\xe1\xc7\xf0\x63\xf8\x06\xbe\x81\x6f\xe0\x1b\xf8\x06\xbe\x81\x6f\xe0\x8f\xee\x9f\x81\x6f\xe0\x1b\xf8\x06\xbe\x81\x6f\xe0\x1b\xf8\x06\xbe\x85\x6f\xe1\x5b\xf8\x16\xbe\x85\x6f\xe1\x5b\xf8\x16\xbe\x85\x6f\xe1\x5b\xf8\x16\xbe\x85\x6f\xe1\x5b\xf8\x16\xbe\x83\xef\xe0\x3b\xf8\x0e\xbe\x83\xef\xe0\x3b\xf8\x0e\xbe\x83\xef\xe0\x3b\xf8\x0e\xbe\x83\xef\xe0\x3b\xf8\x0e\x7e\x02\x3f\x81\x9f\xc0\x4f\xe0\x27\xf0\x13\xf8\x09\xfc\x04\x7e\x02\x3f\x81\x9f\xc0\x4f\xe0\x27\xf0\x13\xf8\x09\xfc\x04\x7e\x0a\x3f\x85\x9f\xc2\x4f\xe1\xa7\xf0\x53\xf8\x29\xfc\x14\x7e\x0a\x3f\x85\x9f\xc2\x4f\xe1\xa7\xf0\x53\xf8\x29\xfc\x14\x7e\x06\x3f\x83\x9f\xc1\xcf\xe0\x67\xf0\x33\xf8\x19\xfc\x0c\x7e\x06\x3f\x83\x9f\xc1\xcf\xe0\x67\xf0\x33\xf8\x19\xfc\x0c\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x19\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x05\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x15\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x0d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x80\x93\x7b\x3a\xf6\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x7c\x16\xe4\x45\xc3\xff\x86\x27\xf7\xe5\xe1\xa2\xfc\x7f\xe2\xdb\x37\x0c\xd1\x45\xa3\x8d\xe3\x68\xdf\xa8\x95\x5f\x87\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc6\xe3\x19\x8f\x67\x3c\x9e\xf1\x78\xc5\xe3\x13\x8f\x4f\x3c\x3e\xf1\xf8\xc4\xe3\x13\x8f\x4f\x3c\x3e\xf1\xf8\xc4\xe3\x13\x8f\x4f\x3c\x3e\xf1\xf8\xc4\xe3\x13\x8f\x4f\x7c\x75\xc4\x65\x9e\xf8\xc4\xe3\x13\x8f\x4f\x3c\x3e\xf1\xf8\xc4\xe3\x13\x8f\x4f\x3c\x3e\xf1\xf8\xc4\xe3\x13\x8f\x4f\x3c\x3e\xf1\xf8\xc4\xe3\x13\x8f\x4f\x3c\x3e\xf1\xf8\xc4\xe3\x13\x8f\x4f\x3c\x3e\xf1\xf8\xc4\xe3\x13\x8f\x4f\x3c\x3e\xf1\xf8\xc4\xe3\x13\x8f\x4f\x7c\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x1d\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\x7e\x03\xbe\x87\xef\xe1\x7b\xf8\x1e\xbe\x87\xef\xe1\x7b\xf8\x1e\xbe\x87\xef\xe1\x7b\xf8\x1e\xbe\x87\xef\xe1\x7b\xf8\x1e\x7e\x80\x1f\x62\x79\x49\xfe\xc0\x5d\x3d\x0c\x7c\x0a\x3d\x40\x0f\xd0\x03\xf4\x00\x3d\x5f\x8d\xc7\x01\x6b\x07\xac\x1d\xb0\x76\xc0\xda\x01\x6b\x07\xac\x1d\xb0\x76\xc0\xda\x01\x6b\x87\xd2\x68\xbc\x2a\xb1\x46\xac\x13\x1b\x44\x4f\xcc\x67\x13\xb0\x76\xc0\xda\x01\x6b\x07\xac\x1d\xb0\x76\xc0\xda\x01\x4b\x07\x2c\x1d\xb0\x74\xc0\xd2\x01\x4b\x07\x2c\x1d\xb0\x72\xc0\xca\x01\x2b\x07\xac\x1c\xb0\x72\xc0\xca\x01\x2b\x07\xac\x1c\xb0\x72\xc0\xca\x01\x2b\x07\xac\x1c\xb0\x72\x30\x23\x1e\xf3\xc3\xca\x01\x2b\x07\xac\x1c\xb0\x72\xc0\xca\x01\x2b\x07\xac\x1c\xb0\x72\xc0\xca\x01\x2b\x07\xac\x1c\xb0\x72\xc0\xca\x01\x2b\x07\xac\x1c\xb0\x72\xc0\xca\x01\x2b\x07\xac\x1c\xb0\x72\xc0\xca\x01\x2b\x07\xac\x1c\xb0\x70\xc0\xc2\x01\x0b\x07\x2c\x1c\xb0\x70\xc0\xc2\x01\xeb\x06\xac\x1b\xb0\x6e\xc0\xba\x01\xeb\x06\xac\x1b\xb0\x6e\xc0\xba\x01\xdb\x06\x2c\x1b\x92\xd1\xb8\xe4\x8f\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\xac\xd6\x02\xab\xb5\xc0\x6a\x2d\xb0\x5a\x0b\xac\xd6\x02\xab\xb5\x80\x45\x03\x16\x0d\x58\x34\x60\xd1\x80\x45\x03\x16\x0d\x58\x34\x94\x47\x3c\xe6\x8b\x45\x03\x16\x0d\x58\x34\x60\xd1\x80\x45\x03\x16\x0d\x58\x34\x60\xd1\x80\x45\x03\x16\x0d\x58\x34\x60\xd1\x80\x45\x03\xab\xb5\xc0\x6a\x2d\x60\xd5\xc0\x6a\x2d\x60\xd7\x80\x5d\x03\x76\x0d\xd8\x35\x60\xd7\x80\x5d\x03\x76\x0d\xd8\x35\x60\xd7\x80\x5d\x03\x76\x0d\xd8\x35\x60\xd7\x80\x5d\x03\x76\x0d\xd8\x35\x60\xd7\x80\x5d\x03\x76\x0d\xd8\x35\x60\xd7\x80\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\x58\x35\x60\xd5\x80\x55\x03\x56\x0d\x58\x35\x60\xd3\x80\x4d\x03\x36\x0d\xd8\x34\x60\xd3\x80\x4d\x03\x36\x0d\xd8\x34\x60\xd3\x80\x4d\x03\x36\x0d\xd8\x34\x60\xd3\x80\x4d\x03\xf6\x0c\xd8\x33\x60\xcf\x80\x3d\x03\xf6\x0c\xd8\x33\x60\xcd\x80\x35\x03\xd6\x0c\x58\x33\x60\xcd\x80\x35\x03\xd6\x0c\x58\x33\x60\xcd\x80\x35\x03\xd6\x0c\x58\x33\x60\xcd\x80\x35\x03\xd6\x0c\x58\x33\x60\xcd\x80\x35\x03\xd6\x0c\x01\x5e\x80\x87\x27\x03\x7e\x0c\xf8\x31\xe0\xc7\x30\xf2\x63\x80\x13\xe0\x04\x38\x01\x4e\xbe\x0a\x36\xa5\xdc\xa3\xa6\x94\x7b\xd4\x94\x72\x8f\x9a\x52\xee\x51\x53\xca\x3d\x6a\x4a\xb9\x47\x4d\x29\xf7\xa8\x29\xe5\x1e\x35\xa5\xdc\xa3\xa6\x94\x7b\xd4\x94\x72\x8f\x9a\x52\x29\xff\x9f\x20\xd3\x38\x4d\x9d\x5a\x6d\xd9\x52\x3c\x8c\xa6\x52\xe1\x18\x72\x3c\x8a\xf1\xe6\xdd\xed\xb9\xe5\x7e\x6b\xb6\xb9\x34\x3f\xbc\xb8\x34\xfa\xbf\xdd\x4d\x29\x4e\xb7\x2e\x77\x67\x5b\xfd\xa5\x99\x5e\xbf\x35\xbb\xab\xb3\xf5\xca\xe5\xde\xa0\xd5\x6f\xed\x6d\xf5\x97\x5a\xb3\x9c\x13\xf2\x68\x48\xc1\x8c\x52\x48\xf8\x0f\xc6\xab\x2d\x57\xb4\x98\x90\x09\x72\xa1\xdd\x1d\xfe\xa5\x52\x6b\xa6\xd7\x65\x2c\xeb\xa2\xd6\x55\x33\x9d\xe6\xc2\xec\xae\x0e\x9f\x70\xc3\x92\x51\x84\x96\x42\xcb\x5f\xcc\xa6\x94\xbf\x98\x4d\x29\x7f\x31\x9b\x52\xca\xf9\x29\xe7\x67\x4c\x37\xe3\xc6\x8e\xf2\xc8\xb8\xb1\x19\x37\x36\x63\xe6\x19\x37\x36\xe3\xfa\x0a\xd7\x57\xf8\xc2\x2a\x7c\x61\x15\xbe\xb0\x0a\xe3\x56\x4b\x5b\x67\x7a\x9d\x5e\x77\xa1\xd7\x6d\x0d\x9a\xfd\xab\xf9\xd4\x6c\xea\xb4\xfb\x4d\x0e\x40\x57\x53\xb9\xd8\x5a\x6a\x0d\x46\x1f\x43\xae\x56\x36\xcd\xf6\xba\x73\x9b\xfc\x72\xbf\xc7\x27\xcc\xa9\xca\x9c\xaa\xe4\x54\x23\xa7\x1a\x39\xd5\xc8\xa9\x46\x4e\x35\x72\xaa\x01\xac\x31\xa7\x1a\xf7\x2e\x94\xf8\x56\x0c\xff\x71\x36\x8d\x0d\xff\x11\x3d\x8d\xf9\x5f\xd8\x4c\x9c\x6f\x78\x98\xd8\xa4\x51\x6b\x69\xd0\x5e\x68\x0e\xf8\xe6\xe3\x5c\xea\x26\x76\x5e\xaf\xce\x76\xbe\xdd\x9f\x8d\x06\xfb\x7a\xc3\xc6\x52\xd4\xeb\xb6\x5a\xed\xb9\xf9\xc1\xfc\xf4\x60\xbe\xdf\xa2\xbd\xb4\x65\x77\x7b\xef\xa8\x3d\xbd\xd4\xda\xdb\xea\x72\x90\x0f\x55\x76\x51\xb3\xdf\xef\xed\xeb\xb4\x76\x0f\xd4\xb0\xb5\xbc\xb8\x79\x18\xfb\xab\xa7\xe5\x9d\xb3\xbd\x7d\xdd\xbc\xb5\xab\x37\x98\x8f\x38\x6d\xb6\x3b\x5d\xb4\x76\x2d\x0d\xeb\x5b\xc3\x9f\x71\x18\xfe\xac\xc2\x98\xb8\xb2\xb9\xd7\x1f\xcc\xf7\xe6\x7a\xdd\x66\x67\xba\xdd\x1d\xac\xfe\x90\x67\x06\xed\x5e\x77\x4b\xeb\xca\xe5\xf6\xde\x66\xa7\xd5\x9d\x69\x89\xf9\xde\xf2\x52\x6b\x6b\xbf\xb5\xb7\xd3\x9b\x6b\xcf\x34\x3b\xdd\xde\x60\xf3\xea\xc9\x73\xfd\x66\x67\xb0\x58\x34\x77\x0d\xf4\x05\x21\x2e\xad\xfe\xb3\xda\x88\x69\x94\x8a\x86\x1d\x35\xcc\xa8\xe1\x46\x8d\xf2\xa8\x51\x19\x35\xd2\x51\x23\x1b\x35\x12\x1a\x6e\x34\x8e\x19\x5d\x9e\x8c\x10\xc9\x68\x64\x3b\x1a\xc7\x8c\x3e\x31\xa3\x73\xcc\x68\x9c\x64\x94\xaa\x1b\x9d\x6c\x47\x69\x98\xa2\x31\xa2\x9b\x51\x3e\xb6\x68\x8c\xba\xdc\x08\x11\x17\xd0\xd1\xc8\x66\x94\xaa\x2b\x4e\x1e\x8d\xec\x46\xf9\xb8\x62\x5e\xa3\x91\xdd\xe8\xf2\xa4\x98\x60\x31\xce\xf0\x13\xb5\xbc\xb8\xab\xd3\x9b\xd9\xa3\x66\xbb\xc3\x28\xf2\xa3\xce\xee\x3c\xf6\x07\x1c\x0f\x96\xe6\x9b\xb3\x2d\x31\xfc\xb7\x9a\xdd\x33\x8c\xd1\xee\x76\xa7\xd3\x9a\xdd\xd5\xbb\x4a\x9e\x6e\x4c\x29\xb3\xf2\xf4\xb8\x9c\xb8\x3c\x24\xab\xaf\xbf\xd5\xee\x7e\x6b\x66\xa0\x06\xfd\x76\x73\x6e\x79\x31\x8f\x7d\x8e\x67\xbb\x79\xec\xec\x96\x33\xed\xfe\x4c\x27\xff\x69\x25\xf5\xfa\x70\x00\x6b\xa3\x76\x77\xef\xae\xe5\x4e\xa7\x35\x58\x6d\xe5\xa7\x6c\xee\x2d\xb6\xba\x7c\xb8\xb4\xd0\xee\xb4\x76\x37\x67\x5a\xd3\xed\xee\xde\xe2\x60\xe3\xd2\x72\x57\xee\x6e\x2d\x34\x3b\xad\x4d\xab\xff\x12\x4b\x8b\xcd\xd9\xd6\xa6\x99\xce\xf2\x2e\x31\xdf\x6a\xf6\x07\x6a\xb6\xdd\x5c\xe8\x75\x67\xb7\x2c\x2c\x2f\xf1\x1b\x6c\x1d\xb9\xa6\x3d\x7a\x45\xa6\xbc\xe2\xea\x79\xed\x6b\xea\x79\xed\x6b\xea\x79\xed\x6b\xea\x79\xed\x6b\xea\x79\xed\x6b\xea\x79\xed\x6b\xea\x79\xed\x6b\xea\x79\xed\x6b\xea\x79\xed\x6b\xea\x79\xed\x6b\xea\xbc\x62\xeb\xbc\x62\xeb\xbc\x62\xeb\xbc\x62\xeb\x19\x9c\x0c\x4e\x06\x87\x57\x6c\x9d\x57\x6c\x9d\x57\x6c\x9d\x57\x2c\x3b\xa8\xd5\xac\x88\x65\x62\x85\x58\x25\xd6\x88\x75\x62\x83\xe8\x89\x21\x8f\xf9\x9a\xad\x9a\xe5\x6b\xb6\x6a\x56\x66\xbc\x32\xe3\x95\x19\xaf\xcc\x78\x79\x4d\xeb\x71\x70\xa8\xe5\x0e\x0e\xb5\xdc\xc1\xa1\x96\x3b\x38\xd4\x72\x07\x07\x76\x6a\x03\x3b\xb5\x81\x9d\xda\xc0\x4e\x6d\xf0\xf9\x8e\x76\xc0\xf5\x21\x84\x86\x1e\xfe\xad\x79\x92\xa6\xa3\x46\x79\xd4\xa8\xd0\xc8\x4a\x34\x2a\x7c\x92\x96\x62\x1a\x31\x8d\x72\xd9\x8d\x1a\xc9\xa8\x91\x8e\x1a\xd9\xa8\x51\x1e\x35\x18\xa7\x5c\x29\x8d\x1a\xa3\x71\x2a\x66\xd4\xb0\xd1\xb0\x31\x7c\xcd\x8e\x5a\x49\xd1\x4a\x6f\xb2\x9c\xff\xcd\xc0\xe5\x07\xc7\xf4\x94\x99\x99\x85\xc5\x43\x74\x66\x93\x3a\xcb\x93\x3a\x2b\xe3\x3a\xd3\xd1\x49\x93\x3a\xc7\x26\x94\x4e\x4a\x28\x9d\x94\x50\x7a\x50\x42\xc7\x1f\xc6\xe4\xb3\x49\x59\x66\x87\x73\xe5\xd8\x2c\xb3\x49\x59\x66\x93\xb2\x1c\x3b\x5c\x79\x52\x96\xe5\x49\x59\x96\x0f\x67\xd8\xb1\x59\x96\x27\x65\x39\xf6\x8a\xca\xa4\x2c\x2b\x93\xb2\xac\x4c\xca\xb2\x72\x38\xcc\xb1\x59\x1e\xf4\xbb\x4c\xd7\xfd\x68\x93\x49\x9d\xe9\xa4\xce\x6c\x52\x67\x79\x52\xe7\x41\x59\x8e\x7d\x40\xd2\x49\x4f\xcf\xfa\xce\xb1\x89\x8c\x7d\x40\xd6\x77\x8e\xbd\x33\x63\x9f\x85\xf5\x9d\x63\xef\xcc\xd8\x67\x61\x7d\xe7\xd8\x84\xc6\x3e\x0b\x13\xe7\x37\xf6\x59\x58\xdf\x39\x36\xcb\xb1\xcf\xc2\xfa\xce\xb1\x59\x8e\x7d\x16\x26\xde\xe8\xb1\xcf\xc2\xfa\xce\xb1\x59\x8e\x7d\x16\xd6\x77\x4e\x64\x8e\xcd\xf2\xa0\x6f\x3c\x9b\xf4\x2c\xac\xef\x4c\x27\x75\x66\x93\x3a\xcb\x93\x3a\x0f\xca\x72\xec\x4f\x2f\x9b\xf4\x2c\xac\xef\x1c\x9b\xe5\xd8\x1f\xd2\xfa\xce\xb1\x59\x8e\x35\xc9\xd8\x67\x20\x9b\xf4\xf4\xac\xef\x9c\x78\xe5\xd8\x44\xb2\x49\xdf\xdf\xd8\x67\x61\x7d\xe7\x58\xe6\xd8\x67\x61\x7d\xe7\xd8\x84\xc6\x3e\x0b\x13\xa7\x30\xf6\x59\x58\xdf\x39\x36\xcb\xb1\xcf\xc2\xfa\xce\x89\xcc\xb1\x59\x1e\x74\x2f\xcb\x93\x9e\x85\xf5\x9d\xe9\xa4\xce\x6c\x52\x67\x79\x52\xe7\x41\x59\x8e\xfd\x52\xcb\x93\x9e\x85\xf5\x9d\x63\xb3\x1c\xfb\x2c\xac\xef\x1c\x9b\xe5\xd8\x67\x61\xec\xaf\xab\x3c\xe9\x59\x58\xdf\x39\xf1\xca\xb1\x59\x8e\xfd\x95\xad\xef\x1c\x9b\xe5\xd8\xe1\x26\xde\xe8\x89\xf3\x3b\xac\x61\xc7\xfe\xca\xc6\x3e\x0b\xeb\x3b\xc7\x32\xc7\x3e\x0b\xeb\x3b\xc7\xde\x99\xb1\xcf\xc2\xd8\x2c\x2b\x93\x9e\x85\xf5\x9d\xe9\xa4\xce\x6c\x52\x67\x79\x52\xe7\x41\x59\x8e\xbd\x5d\x95\x49\xcf\xc2\xfa\xce\xb1\x59\x8e\x7d\x16\xd6\x77\x8e\xcd\x72\xec\xb3\x30\xf6\x7b\xab\x4c\x7a\x16\xd6\x77\x4e\xbc\x72\x6c\x96\x63\x9f\x85\xf5\x9d\x63\xb3\x1c\x3b\xdc\xd8\x67\x61\x7d\xe7\xd8\x2c\xc7\x3e\x0b\xeb\x3b\xc7\x66\x39\xd6\x24\x63\x7f\xc9\x95\x49\x4f\xcf\xfa\xce\xb1\x59\x4e\x9c\xfc\xc1\xcc\x5b\x0e\xff\x02\x73\xf8\x91\x2d\xb9\x3c\xc6\xf6\xf2\xe2\xaf\xd5\x27\x9d\x54\xfc\x21\xfb\xa1\x4f\x72\x87\x33\x92\x9b\x34\x52\x7a\x38\x39\xa5\x87\x93\x53\x7a\x38\x39\xa5\x87\xc8\xe9\x16\xed\xde\xe0\xba\x6e\xd3\xf8\x73\xae\x7b\x9c\xf5\x09\x8d\x3f\xe7\xd0\xe3\x1c\xea\x16\x8d\x3f\xe7\xba\xc7\x99\x94\xcf\xa1\xee\xcf\xad\xf9\x13\xd9\xeb\xb8\x45\x87\x3c\xed\xb0\x46\x5b\x9f\xd8\x21\x4f\x9b\x38\xda\xa1\x6e\xd7\x21\x4f\x3b\xac\xd1\xae\x23\xb7\xc3\xf9\x5d\x95\x8b\x79\x1c\xfa\xfe\x1f\x38\xe7\xba\xc7\x49\x0f\x63\x9c\x74\xf2\xec\x0e\x95\xd2\x21\x4f\x3b\xac\xd1\xd6\x27\x76\xc8\xd3\x0e\x1e\x8d\x1d\x3f\x9b\xda\xa2\xe5\x8a\x56\x52\xb4\xd2\xa2\x95\x15\xad\x72\xd1\xaa\x8c\x5a\x59\xa9\x68\xc5\x45\xcb\x14\xad\x82\x91\x15\x8c\xac\x60\x64\x05\x23\x2b\x18\x59\xc1\xc8\x0a\x46\xb9\x60\x94\x0b\x46\xb9\x60\x94\x0b\x46\xb1\xaf\x69\x8b\x7d\x4d\x5b\x2e\x18\xe5\x82\x51\x2e\x18\xe5\x82\x51\x29\x18\x95\x11\xc3\x95\xca\x53\x53\x53\x6f\x3f\xe2\x7f\x0f\xdf\x7f\xc4\xe3\xa7\xce\xdc\xaf\xcf\xbd\xf8\xda\x23\x8e\x78\xc2\x25\xd7\x06\x79\xd2\xc5\x27\xee\x3f\xfa\x92\x33\xf7\x1f\x7f\xfe\xc5\x27\xee\x7f\xd0\x25\x27\xec\x97\x27\x5d\x76\xf1\xd4\xfe\x8d\xdb\xfc\xfe\x8d\x27\x35\xf6\xeb\x6d\x7e\x65\xe3\x2f\x37\x9c\x34\x3c\x50\xdb\xfc\x8a\xbe\x9c\x03\xb9\xcd\xaf\xa8\x0a\x07\x62\x9b\x5f\x91\x27\x73\xb0\x69\x9b\x5f\x11\xc7\x71\x10\xad\x0e\x70\x6c\x7e\x70\xc4\xfe\xcd\x0c\xbb\x65\x9b\x5f\xd9\x7c\x9b\x0d\x27\x5d\xbb\x31\xec\x3d\xa9\xb1\x7f\x7a\x9b\x5f\xd9\x72\xe0\x70\xeb\x36\xbf\x32\xfd\xaa\xe2\xf0\xc8\x6d\x7e\x65\xeb\x81\xde\xa3\xb6\xf9\x95\x23\x2f\x2c\x0e\x8f\xde\xe6\x57\x8e\x3a\xb5\x38\x3c\x66\x9b\x5f\x39\xfa\x94\xe2\xf0\xd8\x6d\x7e\xe5\x98\x93\x8b\xc3\xe3\xb6\xf9\x95\x63\xef\x50\x1c\x1e\xbf\xcd\xaf\x1c\xf7\xcc\xe2\xf0\x7a\xdb\xfc\xca\xf1\xb7\x2f\x0e\xaf\xbf\xcd\xaf\x5c\xef\x84\xd1\xe1\x25\xfb\x8f\x3f\x69\x6a\x6a\xea\x88\xf3\x7e\xfa\x95\xd2\xd4\xd4\xff\x07\x00\x00\xff\xff\x85\x66\xaa\x8a\x68\x20\x08\x00") - -func resourcesAppStaticFontsNotosansItalicWebfontTtfBytes() ([]byte, error) { - return bindataRead( - _resourcesAppStaticFontsNotosansItalicWebfontTtf, - "resources/app/static/fonts/NotoSans-Italic-webfont.ttf", - ) -} - -func resourcesAppStaticFontsNotosansItalicWebfontTtf() (*asset, error) { - bytes, err := resourcesAppStaticFontsNotosansItalicWebfontTtfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/static/fonts/NotoSans-Italic-webfont.ttf", size: 532584, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _resourcesAppStaticFontsNotosansRegularWebfontTtf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7d\x58\x5b\xeb\x75\x27\xba\xf6\xde\x42\x12\x42\x08\x7d\x7f\x21\x09\x21\x24\x21\x84\xd0\x17\x02\x83\xf8\x92\x41\xa1\x84\x52\xe2\x12\x0f\x65\x1c\xe2\xe1\x50\x42\x28\xe1\x50\x42\x3c\x84\xf8\xb8\x84\x38\x8c\xc3\xf5\xf5\x50\xc6\xa1\x1e\x86\x72\x5d\x0f\x65\x7c\x19\x3f\x8c\xcb\xe5\x32\x0c\xf5\x50\xd7\x71\x89\xeb\x52\xc2\x70\x1d\xe2\x43\xb9\x84\x4b\x1d\xe2\x12\x0f\xa1\x5c\xca\x50\x1e\x2e\xe1\xdc\x67\xbf\x5b\xb6\x5e\x01\xf2\x81\x9e\x73\x9a\xde\xfb\x9c\x3f\xce\xf2\x3a\x3f\xad\xbd\xf6\xfb\xae\x77\xbd\x6b\xad\x77\x6d\x6d\x04\x04\x00\x48\x08\x00\x16\x38\x0b\x0b\xcf\xff\xda\x17\x56\x2b\x7f\x1f\x80\xc8\x06\x00\xcd\xaf\xf8\x3f\x53\xf8\xb9\x98\x5f\x29\x05\x20\x2a\x00\x88\xf9\x5f\x39\xf7\xb9\xcf\xcf\xdf\xe5\x3f\x01\xa0\x6c\x40\xa4\x2c\xfe\xca\xe7\xff\x59\xfe\xb7\xff\xc3\xf0\xef\x01\xe1\xe2\x02\x70\x95\x9f\xfb\xbc\xc3\xfd\x3f\x46\xfb\xd8\x40\x64\xea\x01\xa0\xea\x37\xdf\x7d\xa7\xe9\x7f\x7f\xe0\xf7\x02\x91\xd9\x0e\x10\x71\xf0\x9b\x2d\x97\xf4\x31\x31\xd1\xab\x40\xe4\xb5\x03\x80\xbf\xb6\xe9\xcb\xef\x7e\x7e\xcc\xf1\xbf\x02\x91\x37\x05\x40\x7e\xe9\xcb\xef\x7c\xad\x09\x00\x84\x40\xe4\xdb\x00\x80\xfb\xe5\x86\x6f\xd4\x7e\xf3\x37\x16\xe2\x80\xc8\xf7\x40\xc4\x67\x27\xeb\xbe\xf4\x4e\x0d\xf5\x5b\xff\x42\x0f\xec\xff\x79\x13\x00\xd2\xeb\xea\xbe\xf4\x8e\xa0\x83\xff\x39\x60\xdf\xb0\x00\x80\xb1\xee\xdd\x4b\xad\x6b\xc2\xcf\x3d\x00\xf6\x8d\x12\x00\xd3\x44\xc3\x6f\xff\xe6\x3b\x9a\xf7\x7e\x75\x1b\xd8\xa3\x2c\x00\xd3\xe4\xbb\xef\xb4\x36\xf1\x16\xa9\x6b\xc0\x7e\xff\x11\x00\xe8\x1b\xdf\x79\xf7\x4b\x5f\x4f\xfd\xc3\xf7\x81\xfd\xfe\x0a\x00\xeb\x71\xd3\x6f\x7f\xed\x92\xe0\x4f\xc9\xdf\x01\xf6\xd2\x20\xc0\x97\xd3\x9a\x9a\xbf\xd4\xf4\x75\x27\xf5\xbb\xc0\x29\x58\x02\x20\x2e\x7c\xfd\x4b\xd5\xb5\xf3\x5f\xfc\xf5\x97\xc0\xf9\x4c\x06\x00\xb0\x01\x90\xf5\x60\x26\x67\xe0\xbf\xd1\xff\x7e\xaf\xcf\xb3\x45\xff\x3b\xcb\xef\xf8\x2b\xf4\x89\x00\x80\xd0\x13\xf4\xd8\x48\x48\x01\x80\x7c\x20\xa0\x00\x0a\x80\x02\x3f\xfc\x16\x10\x50\x0f\xf5\x40\xc1\x57\xe0\x5f\x02\x01\x2d\xd0\x02\x14\x7c\x1d\xbe\x01\x04\x5c\x86\xcb\x40\xc1\x7b\xe4\x65\x20\xc8\xf7\xc8\x6f\x03\x45\x76\x90\xdf\x01\x82\xec\x24\xff\x3d\x50\xe4\x00\xf9\x9f\x80\x20\xef\x93\x63\x40\x91\xff\x99\xfc\xcf\x40\x90\xe3\x94\x10\x28\x4a\x44\x89\x80\xa0\xc4\x94\x07\x28\x2a\x8d\xca\x00\x82\xca\xa4\xbc\x40\x51\x59\xac\x54\x20\x58\x1e\xd6\x19\xa0\x58\x19\x11\xbd\x40\x44\xfc\xbb\x88\xff\x00\x54\xc4\x5d\x4e\x31\x10\x9c\x5f\xe5\x7c\x0e\x28\xce\x39\xce\x3f\x07\x82\x73\x81\x53\x09\x14\xe7\x8b\x9c\x5a\x20\x38\x5f\xe6\xfc\x16\x50\x9c\x7a\x4e\x0b\x10\x9c\xaf\x73\xbe\x01\x14\xe7\x32\xe7\xdb\x40\x70\x3a\x38\xff\x0a\x28\xce\x35\x6e\x07\x10\xdc\x7f\xc5\xbd\x06\x24\xf7\x3b\xdc\x4e\x20\xb8\xff\x13\xf7\x06\x50\xdc\x7f\xcd\xfd\x5d\x20\xb8\xdd\xdc\xef\x02\xc5\xed\xe1\xfe\x1e\x10\xdc\x5b\xdc\x3f\x04\x8a\x3b\x18\xf9\x79\x20\x22\xcf\x47\x36\x00\x15\xf9\x6e\xe4\xbb\x40\x00\x0b\x59\x85\xfe\x4f\x43\x3e\x26\x9f\x03\x49\x2e\x90\xff\x27\x50\xe4\x12\xb9\x04\x24\xb9\x4c\xbe\x00\x8a\xfc\x29\xb9\x06\x14\xf9\xdf\xc9\xff\x01\x14\xf9\xff\x90\x07\x40\x91\x1f\x50\x04\x90\x14\x8b\x62\x03\x49\x71\x28\x0e\x50\x14\x97\xe2\x02\x49\x45\x52\x51\x40\x51\x7c\x4a\x00\x24\x15\x83\xac\x21\xa6\xa4\x40\x52\x32\x4a\x09\x14\xa5\xa2\x54\x40\x52\xb1\x94\x06\x28\x4a\x4b\x69\x81\xa4\x4c\x94\x0b\x48\x64\x13\x32\xe2\xdf\x45\xf4\x01\x19\xf1\xfb\x11\xbf\x0f\x54\x44\x7f\xc4\x00\x90\x11\x7f\x18\xf1\x87\x40\x45\x0c\x46\x0c\x02\x19\xf1\x1f\x68\x5b\xa1\xd9\x11\x68\x4d\x79\x50\x0a\x37\x81\xfa\xcd\x6f\x34\x37\x80\xf4\xcb\xcd\x5f\xfa\x0a\x18\x1b\xde\xb9\xd4\x08\x1e\x34\x23\xf8\xe0\x03\xa0\x90\x5f\x50\x21\xff\x4f\x1e\xf7\xff\x5f\xf9\x52\x73\x23\xa8\xdf\x7d\xa7\xf9\x2b\xa0\x47\xd4\xfc\xee\x57\xde\xfd\x0a\x64\xa3\xeb\xa3\x10\xa5\xef\x18\x89\x38\x46\x43\x04\xb0\x81\x03\x5c\xa4\x21\x12\x78\xc0\x07\x35\x18\xc0\x0a\x6e\xf0\x42\x3e\x14\x43\x19\x5c\x80\x6a\xa8\x87\x66\x74\x37\xe2\xf7\xca\x99\x7f\x89\x22\xe6\x5f\xf6\x3d\xe6\x5f\x6a\x9f\xf9\xf7\x1d\x3f\xb0\x08\x00\x22\xa5\x8e\xf9\x7f\xb2\x81\xf9\x57\x62\x67\xfe\x05\x03\xb0\x49\x00\x22\x7a\x19\xd8\x14\x00\xc1\xd3\x00\x09\x5c\x20\x97\x77\x7e\xe2\x05\x02\xe6\xe0\x3e\x10\xb0\x00\x7c\x90\x82\x15\x9c\x90\x0e\xd9\x90\x0f\x45\x50\x0a\xe7\xe1\x02\x54\x41\x2d\x34\x40\x33\xb4\x42\x1b\x74\xc0\x75\xe8\x86\x5b\xd0\x0f\x04\x35\x0f\xe5\x40\x50\x7a\x9a\xb2\x72\x68\x4a\x7c\x17\x21\xf2\x83\x26\x20\x58\x25\x08\xb1\x1d\x74\x00\xc1\x52\xa3\xb1\x57\xd3\x08\xfb\x47\x48\x1e\x7d\xca\x68\x60\xe5\x1c\xcc\xbf\xfe\x94\xe2\xd3\x94\xe4\x22\xdc\x8f\x78\x84\xb3\xd6\xd1\xa7\x5f\x83\x72\x20\x21\x02\x3e\x03\xbf\x02\x00\x9f\x85\x5f\x05\x0a\x7e\x0d\x7e\x1d\xd8\xf0\x79\xb8\x00\x51\xf0\x45\xf8\x22\x48\x68\x1b\x93\x3f\x21\x57\x91\x57\xf2\x98\x38\x04\x40\x5f\x0f\x03\x68\x4c\x72\x58\x06\x82\x30\x20\x9b\x9f\x64\xa6\x03\x30\x04\xf7\x61\x0c\x1e\xc0\x23\x78\x02\x33\x40\x90\x93\x6c\x16\x10\xa4\x93\x35\x42\x5b\x9a\xe3\x04\x82\xec\xe1\x34\x00\x41\x76\x21\xbc\x81\xa6\x14\x0f\x51\x2b\x8d\x53\x7a\x84\xf7\x20\xa4\x12\xf1\x5c\xc4\x0f\x23\xfe\x09\xa2\xc9\x48\x9b\x1f\xd1\x1e\x86\xb2\x6d\xb4\x36\xc4\x73\x69\x4a\xf1\x69\x4a\x0c\x22\xe4\xef\x10\xad\x40\xb4\x34\xa0\xd3\x06\x04\xa8\x89\x5f\x27\xfe\x80\x1a\xa5\xfe\x94\xfa\x1e\xf5\x84\xfa\x0b\x6a\x9a\xfa\x6f\xd4\x3c\xb5\x44\x2d\x53\xff\x17\xb5\x42\xfd\x35\xf5\x92\xfa\x19\xf5\x8a\xfa\x5b\x6a\x9b\xda\xa7\x0e\xa8\x0f\x58\xc0\x22\x59\x31\xf4\x3e\x26\x1f\x93\x7f\x46\x3e\x21\x67\x91\xc7\x88\x01\x40\x09\x00\x3a\x3a\x1e\x03\xf1\x8b\x1e\x56\x3f\x10\xbf\xa8\xa0\x29\x40\x90\x12\xb5\x84\x0e\x08\xa2\x01\xf8\x60\x80\x42\x28\x81\x32\xa8\x80\x8b\x50\x03\xf5\xd0\x04\x2d\x70\x05\xae\x42\x27\x74\x41\x0f\xf4\xc1\x1d\xb8\x0b\xc3\x30\x0a\x13\xf0\x10\xa6\x60\x1a\xe6\xe0\x39\x2c\xc1\x0b\x58\x83\x0d\xd8\x86\x3d\x02\x08\x36\xc1\xa7\x6d\x88\xfc\xf7\x31\xa2\x15\xc8\xc7\xf5\xc8\x7b\x6c\x08\xe9\x41\xd4\x8f\xe8\x2a\xfa\x94\x8f\xe1\x5c\x24\xb9\x8d\xf8\x45\xc4\xbf\x42\x3c\x0f\xd1\x34\xe6\xda\x83\x4a\x20\xe0\x59\x50\x3e\xc0\x97\x06\x35\x33\x08\x31\x83\xe8\x60\x10\x0f\x8c\x61\x31\x48\xe1\x65\x90\x06\x46\xe5\xc7\x70\x03\x18\xc1\x0c\x16\xb0\x82\x0d\xec\xe0\x00\x17\xb8\x21\x0d\xd2\xe1\x0c\x64\x80\x1f\x0a\xa1\x08\x8a\xa1\x04\x4a\xe1\x73\xf0\xeb\x50\x06\xff\x0c\xca\xe1\x37\xa0\x02\xba\xa1\x1f\xfe\x17\xf8\x23\x18\x81\x49\xf8\x13\xd8\xa7\xa3\x07\xf9\x33\xe4\xc3\x6c\x20\x3e\x78\x01\x31\xf4\x7c\xc9\x52\x20\xc8\x3e\xe0\x43\x11\xdc\x84\x5e\xb8\x0d\x83\x70\x0f\x46\x60\x1c\x26\xe1\x31\x3c\x85\x59\x98\x87\x45\x58\x81\x97\xb0\x0e\x5b\xb0\x0b\x07\x04\x8b\xe0\x11\x42\x42\x4e\x68\x08\x03\x61\x21\xec\x84\x87\xf0\x12\x3e\xa2\x90\x28\x21\xca\x88\x0a\xe2\x22\x51\x43\xd4\x13\x4d\x44\x0b\x71\x85\xb8\x4a\x74\x12\x5d\x44\x0f\xd1\x47\xdc\x21\xee\x12\xc3\xc4\x28\x31\x41\x3c\x24\xa6\x88\x69\x62\x8e\x78\x4e\x2c\x11\x2f\x88\x35\x62\x83\xd8\x26\xf6\x48\x20\xd9\x24\x9f\x14\x93\x4a\x52\x47\x1a\x49\x2b\xe9\x24\xd3\xc9\x6c\x20\xc8\x1f\x47\x4c\x02\x41\xad\x45\xb4\x02\xc1\x6a\x8b\xb8\x0a\x04\xf5\x94\xe6\xa9\xed\x88\xf1\xd7\x94\xb5\x40\xe3\x11\xf1\x34\x4f\xac\x20\xfa\x55\x84\x97\x20\xfe\x3d\x9a\xb2\xbf\x4e\xd3\x88\x62\x84\xb7\x46\xd4\x00\x41\xf5\x22\x9d\x18\x4f\x0d\x45\x7c\x03\x08\x56\x05\x92\x8c\x45\x92\x9d\x34\xe5\x88\x11\x2f\xc4\xa8\x15\xdd\xbd\x92\x5a\xa3\x23\x0f\xa2\x95\xac\x04\x20\x58\x99\x6c\x29\x10\x54\x13\x8d\x90\x3f\x8b\xd8\x03\x82\x95\xc1\x2a\x7e\x2d\x43\x5c\xa4\x79\x86\x52\x95\x0c\x4f\xcb\xb3\x7d\x98\x9e\xae\x20\x1f\xb8\x56\xce\x2a\x03\x82\x32\xb1\xa4\x40\x10\xef\x46\x14\x02\xc1\xf2\x21\xfc\x11\x4d\x23\x36\x11\xdf\x11\x44\xa8\x2a\x9a\x32\xf3\xc2\x29\x33\x23\x86\x06\xee\x82\x51\x46\x27\x43\x03\x73\xf7\x05\xf5\x04\x64\x30\x1e\x97\xc1\x78\x12\xa2\xc0\x08\x39\x74\x25\x07\x5f\x04\x35\xf4\xc0\xef\x81\x07\xfe\x2d\xfc\x5b\x48\x87\xdf\x87\x7e\x38\x03\x63\xf0\x9f\x21\x13\xfe\x0b\xfc\x17\xc8\x82\xff\x0a\x93\x90\x4d\x58\x89\x64\xc8\x65\xff\x36\xbb\x19\x7c\xec\xef\xb0\xaf\x83\x1f\x79\xe9\x8f\xdf\x78\x69\x0a\x6b\x13\x08\xea\x0e\xa5\x03\x82\xba\x0b\x7c\xa8\x46\x91\xf3\x19\x2c\xc0\x32\xac\xc2\x2b\xd8\x84\x1d\xd8\x27\x48\x82\x4b\x08\x08\x29\xa1\x26\xf4\x84\x99\xb0\x11\x6e\x22\x83\xc8\x25\xfc\x44\x31\x71\x8e\x28\x27\x2a\x89\x6a\xa2\x8e\x68\x24\x2e\x11\x97\x89\x76\xe2\x1a\x71\x83\xb8\x49\xf4\x12\xb7\x89\x41\xe2\x1e\x31\x42\x8c\x13\x93\xc4\x63\xe2\x29\x31\x4b\xcc\x13\x8b\xc4\x0a\xf1\x92\x58\x27\xb6\x88\x5d\xe2\x80\x64\x91\x3c\x52\x48\xca\x49\x0d\x69\x20\x2d\xa4\x9d\xf4\x90\x5e\xd2\x47\x16\x92\x25\x64\x19\x59\x41\x5e\x24\x6b\xc8\x7a\xb2\x89\x6c\x21\xaf\x90\x57\xc9\x4e\xb2\x8b\xec\x21\xfb\xc8\x3b\xe4\x5d\x72\x98\x1c\x25\x27\xc8\x87\xe4\x14\x39\x4d\xce\x91\xcf\xc9\x25\xf2\x05\xb9\x46\x6e\x90\xdb\xe4\x1e\x05\x14\x9b\xa2\xa3\xd3\x5f\xd3\x9e\xcd\xaa\x62\xb5\x01\xc1\xaa\x89\xf8\x97\x40\xb0\x7e\x4e\xf3\xd4\x0f\xd1\x0a\x21\xca\x9a\x44\xf8\x22\xe6\xd9\xe7\x11\xce\x46\xfc\x6f\x20\xcf\xfe\x3c\x5a\x57\x33\xa2\x8d\x48\x5b\x3e\x4d\x71\x9e\xea\x40\xbe\x9e\x8b\xae\xdd\x41\xb4\x0d\x5d\xcb\xec\xa2\x35\x44\xf7\x31\xbe\x97\xa2\x73\xad\x90\xa6\x54\x11\x2b\x05\x08\x96\x0c\x79\xf6\x3c\x8d\x90\x3f\x66\x0b\x68\x04\xf9\x07\x92\x21\xbc\xc8\x9b\x7d\x98\x67\x7b\x91\x67\xf7\x61\x7a\xd6\x82\x3c\x73\x2d\xb9\x81\xe8\x01\xed\xd9\xe4\x35\xa4\x4d\x83\x34\x0c\x23\xaf\x7a\x8a\xf8\xda\x20\x42\x65\x23\x8a\xc6\xf6\x76\xca\x4e\x47\xfc\xfc\xf1\x34\x30\xda\x23\x94\x19\xe1\xdb\x29\x33\xc2\xa3\x34\x30\x42\x44\x89\x2c\x9a\xb2\x57\xd0\x55\xc3\x98\x86\xfd\xa0\xc5\x28\x3e\xf6\xa9\x9e\x25\xa4\xf3\x3b\xd2\xcf\x66\x70\xd6\xc5\xd7\x7a\x88\x15\x74\x15\xc2\xd9\xe7\xb1\xfb\x36\x23\xeb\x55\xa3\x5d\x27\x0b\xd9\x75\x74\x95\xe1\x81\x7b\xf0\xbf\x41\x16\x8c\xc1\x04\x14\xc0\x03\xf8\x53\x28\x82\xef\xc1\xf7\xa0\x14\xfe\x0e\xfe\x0e\x3e\x47\xc8\x08\x19\x9c\x23\xfe\x80\xf8\x03\xf8\x75\x52\x4c\x4a\xa1\x8c\x94\x93\x72\xf8\x67\xa4\x9a\x54\x43\x39\xa9\x25\x75\xf0\x1b\xa4\x9e\xd4\xc3\x3f\x27\xcd\xa4\x19\x2e\x90\x56\xd2\x0a\x5f\x20\x6d\xa4\x0d\x2a\xc9\x33\x64\x06\x7c\x91\xfc\x55\xb2\x04\xfe\x05\x59\x4a\x96\xc2\x3b\x68\xc7\xde\x79\xbd\x63\x0f\xfe\x82\xfc\x3f\x80\x20\x26\x88\x5a\x94\x2f\xf9\x90\xfc\xd1\x32\x39\x21\x26\x94\x84\x8e\x30\x12\x56\xc2\x49\xa4\x13\xd9\x44\x3e\x51\x44\x94\x12\xe7\xe9\xfb\xfd\x62\x17\xa3\x73\x6f\xa8\x34\xc0\xaf\x62\xf4\x09\x4d\xe9\x8c\xfd\x8b\xfe\x03\x0f\xe2\xe5\x87\xae\x0a\x91\x67\x64\x42\xf4\x1f\xa1\x28\xff\xc3\x41\xd1\x6b\x0d\x1f\xac\x87\x68\x9b\x44\x9f\xea\x31\xcd\xf8\x5d\x26\x31\x7e\xe8\x08\x1e\x8e\xe2\x32\x73\x40\x42\x34\x3a\x23\x01\x3a\x1d\xb1\xd0\xe9\x28\x12\x9d\x8e\xa2\xd1\xe9\x48\x89\x4e\x44\x1a\x74\x16\xd2\xa2\x53\x90\x1e\x9d\x7f\x0c\xe8\xe4\x63\x46\x27\x1c\x0b\x3a\xdb\x24\xa1\x53\x8d\xf5\x13\xd0\x98\x0c\x00\xf7\x01\x60\x0c\x00\x1e\x00\x00\x7d\xce\x7e\x42\x1f\x91\x01\x50\x75\xb4\x00\x00\xcb\x00\x40\xd7\x60\x74\x8d\x45\x9f\xe3\x77\x00\x60\x9f\x2e\x81\x00\x08\x2e\x00\x41\x9f\x9a\xa5\x00\x84\x9a\x3e\x3d\x03\x10\x66\x00\xba\x82\x22\xdc\x00\x44\x06\x00\x91\x0b\x40\xf8\x01\x88\x62\x00\xe2\x1c\x00\x51\x0e\x40\x54\x02\x10\xd5\x00\x44\x1d\x00\xd1\x08\x40\x5c\x02\x20\x2e\x03\x10\xed\x00\xc4\x35\x00\xe2\x06\x00\x71\x13\x80\xe8\x05\x20\x6e\x03\xd0\xd5\x19\x71\x8f\xb6\xeb\x07\xfd\x18\x9d\x7a\x43\xa5\x1f\xcc\x86\xf9\xf4\x12\xed\x53\x1f\xb4\x21\xbe\x0a\x51\x46\xb2\x13\xd1\x11\x44\xef\x62\x48\x3f\x86\x77\x1e\xa1\x97\x10\x2d\x47\x74\x81\xf6\x29\x9a\xbe\x91\x9f\x3d\x22\xcf\x7c\xfa\x00\xd1\x9b\x98\xe4\x14\x46\x47\xc2\xd0\xa9\x23\x9a\xfb\x81\x20\x6b\x49\x01\x10\xe4\x43\xe0\x83\xef\xe3\xda\xab\xc4\x05\xa2\x8a\xa8\x25\x1a\x88\x66\xa2\x95\x68\x23\x3a\x88\xeb\x44\x37\x71\x8b\xe8\x27\x06\x88\x21\xe2\x3e\x31\x46\x3c\x20\x1e\x11\x4f\x88\x19\xe2\x19\xb1\x40\x2c\x13\xab\xc4\x2b\x62\x93\xd8\x21\xf6\x81\xf8\x45\x2b\xbb\xfb\x35\x05\x08\xf0\x3e\xc4\xb3\x68\x4a\x9f\x99\x00\x02\xc8\x1b\xfa\x8b\x2e\x0e\x17\xf1\x2b\xaf\xaf\x3a\x4a\xdf\xe8\xdc\x46\xf4\xfc\x71\x7a\x42\x35\x70\xe8\xda\x04\xb8\xfa\x23\x32\x13\x87\xf5\x73\x6e\x07\xe5\x03\x9f\x22\x1a\x18\x15\x26\x4f\xd7\x54\xaf\x29\xa3\x0d\x47\x02\xb8\x2d\x48\x8f\x7e\x1a\xa4\xa4\x97\xad\x44\xd4\x87\x68\xf7\x6b\xfa\x66\x8e\xdb\xe1\xad\x11\x86\x92\x20\x40\xbd\x18\x40\x5d\x18\x19\xea\xb6\xc8\x51\xb7\x45\x85\xfa\x2c\x1a\xd4\x61\xd1\xa2\xde\x8a\x1e\x75\x55\x12\x50\x3f\xc5\x88\xfa\x29\x26\xd4\x4f\x71\xa3\x7e\x4a\x3a\xea\xa4\x64\xa0\x1e\x4a\xde\x27\xa6\xd7\xf7\x4b\x89\x1a\x40\x8c\x00\x10\xe3\x00\xc4\x24\x00\xf1\x18\x80\x78\x0a\x40\xcc\x02\x10\xf3\x00\xc4\x22\x00\xb1\x02\x40\xbc\x04\x20\xd6\x01\x88\x2d\x00\x62\x17\x80\x38\x00\x20\x59\x00\xf4\x99\x92\x14\x02\x90\x72\x00\x52\x03\x40\x1a\x00\x48\x0b\x00\x69\x07\x20\x3d\x00\xa4\x17\x80\xf4\x01\x90\x85\x00\x64\x09\x00\x59\x06\x40\x9f\x67\xc9\x8b\x00\x64\x0d\x00\x59\x0f\x40\x36\x01\x90\x2d\x00\xe4\x15\xda\xaf\x59\x13\xaf\x29\xc0\x61\xfe\xf5\xbe\xc1\x11\x24\xd3\x15\xe4\x3f\x18\x09\xf9\xb4\xfb\x35\xfd\xc5\xc0\xe1\xab\x00\xa8\x81\xc3\x94\x35\x88\x28\x8a\x63\x2c\x14\x0f\x23\x36\xb1\xab\xd0\x3e\x63\x8d\x60\x48\x15\x46\x19\xa4\x0f\xa3\x53\x18\x8f\x34\x13\x07\x1f\x1f\x25\xbd\x2c\x3a\xe2\x7d\x8e\xbe\x2f\x4e\x01\x58\x0b\x18\x9d\xc0\xc6\x7c\x94\xe2\x9d\x8c\x3e\x20\xd4\x4a\xd5\x2d\x20\xd4\x3a\xe0\x53\x2e\x76\x0d\xbb\x9e\xdd\xc4\x6e\x61\x5f\x61\x5f\x65\x77\xb2\xbb\xd8\x3d\xec\x3e\xf6\x1d\xf6\x5d\xf6\x30\x7b\x94\x3d\xc1\x7e\xc8\x9e\x62\x4f\xb3\xe7\xd8\xcf\xd9\x4b\xec\x17\xec\x35\xf6\x06\x7b\x9b\xbd\xc7\x01\x0e\x9b\xc3\xe7\x88\x39\x4a\x8e\x8e\x63\xe4\x58\x39\x4e\x4e\x3a\x27\x9b\x93\xcf\x29\xe2\x94\x72\xce\x73\x2e\x70\xaa\x38\xb5\x9c\x06\x4e\x33\xa7\x95\xd3\xc6\xe9\xe0\x5c\xe7\x74\x73\x6e\x71\xfa\x39\x03\x9c\x21\xce\x7d\xce\x18\xe7\x01\xe7\x11\xe7\x09\x67\x86\xf3\x8c\xb3\xc0\x59\xe6\xac\x72\x5e\x71\x36\x39\x3b\x9c\x7d\x2e\xc9\xe5\x72\x05\x5c\x29\x57\xcd\xd5\x73\xcd\x5c\x1b\xd7\xcd\xcd\xe0\xe6\x72\xfd\xdc\x62\xee\x39\x6e\x39\xb7\x92\x5b\xcd\xad\xe3\x36\x72\x2f\x71\x2f\x73\xdb\xb9\xd7\xb8\x37\xb8\x37\xb9\xbd\xdc\xdb\xdc\x41\xee\x3d\xee\x08\x77\x9c\x3b\xc9\x7d\xcc\x7d\xca\x9d\xe5\xce\x73\x17\xb9\x2b\xdc\x97\xdc\x75\xee\x16\x77\x97\x7b\x10\xc9\x8a\xe4\x45\x0a\x23\xe5\x91\x9a\x48\x43\xa4\x25\xd2\x1e\xe9\x89\xf4\x46\xfa\x22\x0b\x23\x4b\x22\xcb\x22\x2b\x22\x2f\x46\xd6\x44\xd6\x47\x36\x45\xb6\x44\x5e\x89\xbc\x1a\xd9\x19\xd9\x15\xd9\x13\xd9\x17\x79\x27\xf2\x6e\xe4\x70\xe4\x68\xe4\x44\xe4\xc3\xc8\xa9\xc8\xe9\xc8\xb9\xc8\xe7\x91\x4b\x91\x2f\x22\xd7\x22\x37\x22\xb7\x23\xf7\x78\xc0\x63\xf3\xf8\x3c\x31\x4f\xc9\xd3\xf1\x8c\x3c\x2b\xcf\xc9\x4b\xe7\x65\xf3\xf2\x79\x45\xbc\x52\xde\x79\xde\x05\x5e\x15\xaf\x96\xd7\xc0\x6b\xe6\xb5\xf2\xda\x78\x1d\xbc\xeb\xbc\x6e\xde\x2d\x5e\x3f\x6f\x80\x37\xc4\xbb\xcf\x1b\xe3\x3d\xe0\x3d\xe2\x3d\xe1\xcd\xf0\x9e\xf1\x16\x78\xcb\xbc\x55\xde\x2b\xde\x26\x6f\x87\xb7\x1f\x45\x46\x71\xa3\x04\x51\xd2\x28\x75\x94\x3e\xca\x1c\x65\x8b\x72\x47\x65\x44\xe5\x46\xf9\xa3\x8a\xa3\xce\x45\x95\x47\x55\x46\x55\x47\xd5\x45\x35\x46\x5d\x8a\xba\x1c\xd5\x1e\x75\x2d\xea\x46\xd4\xcd\xa8\xde\xa8\xdb\x51\x83\x51\xf7\xa2\x46\xa2\xc6\xa3\x26\xa3\x1e\x47\x3d\x8d\x9a\x8d\x9a\x8f\x5a\x8c\x5a\x89\x7a\x19\xb5\x1e\xb5\x15\xb5\x1b\x75\xc0\x67\xf1\x79\x7c\x21\x5f\xce\xd7\xf0\x0d\x7c\x0b\xdf\xce\xf7\xf0\xbd\x7c\x1f\xbf\x90\x5f\xc2\x2f\xe3\x57\xf0\x2f\xf2\x6b\xf8\xf5\xfc\x26\x7e\x0b\xff\x0a\xff\x2a\xbf\x93\xdf\xc5\xef\xe1\xf7\xf1\xef\xf0\xef\xf2\x87\xf9\xa3\xfc\x09\xfe\x43\xfe\x14\x7f\x9a\x3f\xc7\x7f\xce\x5f\xe2\xbf\xe0\xaf\xf1\x37\xf8\xdb\xfc\xbd\x68\x88\x66\x47\xf3\xa3\xc5\xd1\xca\x68\x5d\xb4\x31\xda\x1a\xed\x8c\x4e\x8f\xce\x8e\xce\x8f\x2e\x8a\x2e\x8d\x3e\x1f\x7d\x21\xba\x2a\xba\x36\xba\x21\xba\x39\xba\x35\xba\x2d\xba\x23\xfa\x7a\x74\x77\xf4\xad\xe8\xfe\xe8\x81\xe8\xa1\xe8\xfb\xd1\x63\xd1\x0f\xa2\x1f\x45\x3f\x89\x9e\x89\x7e\x16\xbd\x10\xbd\x1c\xbd\x1a\xfd\x2a\x7a\x33\x7a\x27\x7a\x5f\x40\x0a\xb8\x02\x81\x40\x2a\x50\x0b\xf4\x02\xb3\xc0\x26\x70\x0b\x32\x04\xb9\x02\xbf\xa0\x58\x70\x4e\x50\x2e\xa8\x14\x54\x0b\xea\x04\x8d\x82\x4b\x82\xcb\x82\x76\xc1\x35\xc1\x0d\xc1\x4d\x41\xaf\xe0\xb6\x60\x50\x70\x4f\x30\x22\x18\x17\x4c\x0a\x1e\x0b\x9e\x0a\x66\x05\xf3\x82\x45\xc1\x8a\xe0\xa5\x60\x5d\xb0\x25\xd8\x15\x1c\xc4\xb0\x62\x78\x31\xc2\x18\x79\x8c\x26\xc6\x10\x63\x89\xb1\xc7\x78\x62\xbc\x31\xbe\x98\xc2\x98\x92\x98\xb2\x98\x8a\x98\x8b\x31\x35\x31\xf5\x31\x4d\x31\x2d\x31\x57\x62\xae\xc6\x74\xc6\x74\xc5\xf4\xc4\xf4\xc5\xdc\x89\xb9\x1b\x33\x1c\x33\x1a\x33\x11\xf3\x30\x66\x2a\x66\x3a\x66\x2e\xe6\x79\xcc\x52\xcc\x8b\x98\xb5\x98\x8d\x98\xed\x98\x3d\x21\x08\xd9\x42\xbe\x50\x2c\x54\x0a\x75\x42\xa3\xd0\x2a\x74\x0a\xd3\x85\xd9\xc2\x7c\x61\x91\xb0\x54\x78\x5e\x78\x41\x58\x25\xac\x15\x36\x08\x9b\x85\xad\xc2\x36\x61\x87\xf0\xba\xb0\x5b\x78\x4b\xd8\x2f\x1c\x10\x0e\x09\xef\x0b\xc7\x84\x0f\x84\x8f\x84\x4f\x84\x33\xc2\x67\xc2\x05\xe1\xb2\x70\x55\xf8\x4a\xb8\x29\xdc\x11\xee\x8b\x48\x11\x57\x24\x10\x49\x45\x6a\x91\x5e\x64\x16\xd9\x44\x6e\x51\x86\x28\x57\xe4\x17\x15\x8b\xce\x89\xca\x45\x95\xa2\x6a\x51\x9d\xa8\x51\x74\x49\x74\x59\xd4\x2e\xba\x26\xba\x21\xba\x29\xea\x15\xdd\x16\x0d\x8a\xee\x89\x46\x44\xe3\xa2\x49\xd1\x63\xd1\x53\xd1\xac\x68\x5e\xb4\x28\x5a\x11\xbd\x14\xad\x8b\xb6\x44\xbb\xa2\x03\x31\x4b\xcc\x13\x0b\xc5\x72\xb1\x46\x6c\x10\x5b\xc4\x76\xb1\x47\xec\x15\xfb\xc4\x85\xe2\x12\x71\x99\xb8\x42\x7c\x51\x5c\x23\xae\x17\x37\x89\x5b\xc4\x57\xc4\x57\xc5\x9d\xe2\x2e\x71\x8f\xb8\x4f\x7c\x47\x7c\x57\x3c\x2c\x1e\x15\x4f\x88\x1f\x8a\xa7\xc4\xd3\xe2\x39\xf1\x73\xf1\x92\xf8\x85\x78\x4d\xbc\x21\xde\x16\xef\x49\x40\xc2\x96\xf0\x25\x62\x89\x52\xa2\x93\x18\x25\x56\x89\x53\x92\x2e\xc9\x96\xe4\x4b\x8a\x24\xa5\x92\xf3\x92\x0b\x92\x2a\x49\xad\xa4\x41\xd2\x2c\x69\x95\xb4\x49\x3a\x24\xd7\x25\xdd\x92\x5b\x92\x7e\xc9\x80\x64\x48\x72\x5f\x32\x26\x79\x20\x79\x24\x79\x22\x99\x91\x3c\x93\x2c\x48\x96\x25\xab\x92\x57\x92\x4d\xc9\x8e\x64\x5f\x4a\x4a\xb9\x52\x81\x54\x2a\x55\x4b\xf5\x52\xb3\xd4\x26\x75\x4b\x33\xa4\xb9\x52\xbf\xb4\x58\x7a\x4e\x5a\x2e\xad\x94\x56\x4b\xeb\xa4\x8d\xd2\x4b\xd2\xcb\xd2\x76\xe9\x35\xe9\x0d\xe9\x4d\x69\xaf\xf4\xb6\x74\x50\x7a\x4f\x3a\x22\x1d\x97\x4e\x4a\x1f\x4b\x9f\x4a\x67\xa5\xf3\xd2\x45\xe9\x8a\xf4\xa5\x74\x5d\xba\x25\xdd\x95\x1e\xc8\x58\x32\x9e\x4c\x28\x93\xcb\x34\x32\x83\xcc\x22\xb3\xcb\x3c\x32\xaf\xcc\x27\x2b\x94\x95\xc8\xca\x64\x15\xb2\x8b\xb2\x1a\x59\xbd\xac\x49\xd6\x22\xbb\x22\xbb\x2a\xeb\x94\x75\xc9\x7a\x64\x7d\xb2\x3b\xb2\xbb\xb2\x61\xd9\xa8\x6c\x42\xf6\x50\x36\x25\x9b\x96\xcd\xc9\x9e\xcb\x96\x64\x2f\x64\x6b\xb2\x0d\xd9\xb6\x6c\x4f\x0e\x72\xb6\x9c\x2f\x17\xcb\x95\x72\x9d\xdc\x28\xb7\xca\x9d\xf2\x74\x79\xb6\x3c\x5f\x5e\x24\x2f\x95\x9f\x97\x5f\x90\x57\xc9\x6b\xe5\x0d\xf2\x66\x79\xab\xbc\x4d\xde\x21\xbf\x2e\xef\x96\xdf\x92\xf7\xcb\x07\xe4\x43\xf2\xfb\xf2\x31\xf9\x03\xf9\x23\xf9\x13\xf9\x8c\xfc\x99\x7c\x41\xbe\x2c\x5f\x95\xbf\x92\x6f\xca\x77\xe4\xfb\x0a\x52\xc1\x55\x08\x14\x52\x85\x5a\xa1\x57\x98\x15\x36\x85\x5b\x91\xa1\xc8\x55\xf8\x15\xc5\x8a\x73\x8a\x72\x45\xa5\xa2\x5a\x51\xa7\x68\x54\x5c\x52\x5c\x56\xb4\x2b\xae\x29\x6e\x28\x6e\x2a\x7a\x15\xb7\x15\x83\x8a\x7b\x8a\x11\xc5\xb8\x62\x52\xf1\x58\xf1\x54\x31\xab\x98\x57\x2c\x2a\x56\x14\x2f\x15\xeb\x8a\x2d\xc5\xae\xe2\x40\xc9\x52\xf2\x94\x42\xa5\x5c\xa9\x51\x1a\x94\x16\xa5\x5d\xe9\x51\x7a\x95\x3e\x65\xa1\xb2\x44\x59\xa6\xac\x50\x5e\x54\xd6\x28\xeb\x95\x4d\xca\x16\xe5\x15\xe5\x55\x65\xa7\xb2\x4b\xd9\xa3\xec\x53\xde\x51\xde\x55\x0e\x2b\x47\x95\x13\xca\x87\xca\x29\xe5\xb4\x72\x4e\xf9\x5c\xb9\xa4\x7c\xa1\x5c\x53\x6e\x28\xb7\x95\x7b\x2a\x50\xb1\x55\x7c\x95\x58\xa5\x54\xe9\x54\x46\x95\x55\xe5\x54\xa5\xab\xb2\x55\xf9\xaa\x22\x55\xa9\xea\xbc\xea\x82\xaa\x4a\x55\xab\x6a\x50\x35\xab\x5a\x55\x6d\xaa\x0e\x20\x22\x62\x51\xb7\x78\x17\xf5\xb0\x2f\x23\xfe\x36\xe2\x87\x51\xa7\xf9\x9b\x88\xa7\x4f\x5d\x44\x84\x09\x21\xe3\xa8\xa3\x7c\xeb\x60\x18\x08\xd6\x76\x50\x92\xfd\x1e\x92\x41\xdd\x6b\xaa\x17\xbb\xd6\x43\x53\x56\x3f\xd6\x1d\xbf\x85\xf0\x32\xc4\x4f\xa2\xab\x9e\x22\x99\x7a\x84\xdc\x41\x3c\x7a\x16\x4a\xbd\x8f\x90\x39\xec\x5a\x86\x0e\x21\xfd\xdf\x65\x34\xd0\x27\x68\x56\x49\xe0\xc9\x0e\x3d\xb6\xa7\x08\x31\x06\x11\xf6\x8f\x90\xce\x12\xec\xda\xea\x03\x29\x7a\xe2\x23\x7d\x2d\x43\x9a\x83\x9d\x78\x16\xd3\x41\x47\x38\x6b\x07\x51\xe6\xc9\x91\x8f\xd6\xcc\xf4\xfb\x19\xbb\xbd\x9d\xb2\x3f\xc3\x58\x80\xbe\x8a\xb1\xd2\x51\xca\xd8\xf3\x28\x65\x56\x01\xb7\xe7\x87\xd0\xb2\xe3\x29\x63\xcf\xc0\x5a\xf4\x06\xad\xfa\x76\x1a\x71\x8e\xb1\x36\x9a\xef\x50\xd0\x6e\x38\x65\xec\x76\x94\x32\x9f\xe2\xd6\x7e\x3b\x65\xac\x7d\x94\x32\xd6\x66\x56\x8a\xe1\x19\xab\x06\x46\x88\xf1\xac\x85\x83\x26\x20\xa8\x79\x44\x2f\x07\xfd\xe4\x24\x3c\x63\xe7\xa3\x3c\xb3\x3a\xcc\x08\xc3\xf3\xe8\x8e\xbd\x88\xe2\xf8\xa3\xa0\x67\x86\xe3\x23\x00\x2c\x6f\x78\x53\xd0\x62\x38\x1f\xf0\x87\xea\xb7\xf3\xf4\xdd\x89\x6a\x44\x31\x9c\xaa\xa4\x77\x28\x39\x87\xfa\x4b\x68\xb7\x06\xf6\x05\xda\xb3\xcc\xee\x60\xbc\x3a\xe0\x87\xcc\x55\xf3\x18\x3f\xfc\xe1\x3c\xe3\x9f\x81\x91\x87\xe1\x59\x0b\x88\x56\xd1\x63\xa0\xe6\x91\x1d\x7a\x31\x5b\x85\xe1\xd9\xff\x12\x51\x25\xbc\x89\x1e\xcc\x1d\x5f\xf3\xe8\xd9\x2e\x86\x07\x56\xd0\x7c\x84\x1f\xa2\x25\xc9\x52\x44\x71\xfc\x3a\xf2\x6d\x2e\xa2\x28\x22\x31\x7b\x1f\x7f\x82\xc7\xec\x20\xc6\x1b\x4f\xcd\x57\xa2\x11\xfa\x69\x1a\x88\x6f\x3b\xd8\x7e\x64\x22\x09\x16\xeb\x98\xa8\x12\x8e\x0f\xcc\x71\x0e\xf3\xc0\xdd\x20\x12\xc2\x87\xf1\x70\xaa\x16\x0e\x3f\xa5\x64\x24\xf5\xcc\x68\x83\x7a\x60\x33\x68\x19\xc6\x1f\x18\x1b\x46\xd4\x20\xde\x19\xf4\x40\xdc\x97\x02\xab\x23\x44\xab\x7f\x03\xf7\x01\x7a\xff\xe2\x91\x8a\x59\x5f\xce\x5f\xa3\xf5\xd5\xd2\x9f\x92\x09\x10\x8c\xc9\x53\x1f\xa4\x86\xae\x54\xc0\x0e\x7e\x34\x2a\xff\xe1\xf5\xa2\xa2\xd1\x38\x73\x31\xcb\x77\xc0\x9b\xcc\x42\xde\x0b\x5a\x1b\xb7\x27\x59\x87\xc9\x7c\x11\xf3\x0a\x57\x70\x24\x91\x68\x35\xb9\xe8\xf9\x2a\xe7\x87\x48\xff\x0c\xca\x7a\x7f\x8b\xc6\x80\x76\x16\x7b\x82\x46\xd8\x33\x68\x17\x8f\x1d\x8e\x51\x21\xfb\x11\xf7\x73\xcc\x4f\xc8\x36\x64\x07\x0d\xb2\xd8\xbf\x80\xb7\x44\x0f\xdc\xda\x81\xc8\xc3\x67\x22\x4f\x90\xa7\x4f\xf1\xaf\xad\xc4\xec\xf7\x48\x14\xf9\xb9\x53\x68\x16\x73\x87\xf5\x47\x30\xcf\x96\xbf\x49\xcf\x37\x64\xff\x86\x89\xb4\xe1\x22\x61\xb8\xe8\x14\x6e\x77\x1f\xb7\xa3\xdf\xb6\x9b\x48\xb4\x8f\x88\x15\x6c\x17\x3b\x8f\x44\xce\x54\xe4\x3f\x0b\xc8\x6e\x7a\x6c\x47\x90\x48\xff\xf5\xc3\x73\x21\x7f\x80\xd6\xf1\x3f\x1e\x8e\x48\x21\x3b\x14\xed\x97\x08\x4e\xd0\xdf\x18\xab\x46\x2c\x21\x7c\x0f\xd3\x79\xf9\x88\x65\x18\x2f\xfd\x39\xd2\x2f\x46\xb9\x8c\xb1\xcc\x68\x70\xaf\x05\xe6\x38\x85\x5d\x85\xc6\x8c\x47\x6c\xc6\xaf\x58\x53\x88\xe2\x11\x0f\x1f\x27\xb2\x09\x2b\x07\x9b\x35\x43\xc5\x88\x36\x30\x77\x41\x1a\x72\x0e\x47\x80\x10\x6a\xc6\xe8\x5c\x70\xbe\x8c\xb7\x04\x28\xa3\xb9\x01\xf1\x8c\x66\x3f\xb2\x3c\x5a\x05\x6a\x8d\xc9\xda\xf0\xe6\x1b\x10\x81\x59\xff\x18\xa3\xdb\xc8\x26\x95\x68\x07\xfd\x00\xf9\xff\x8f\x68\x0d\xec\xba\x60\x2d\xc7\x5a\x47\x7c\x55\xd0\xaa\x11\x28\x23\xb0\x6e\xa2\xbb\xa0\xca\x8d\xb1\x00\x43\x99\x2a\x2b\x50\x2d\xfc\x34\x38\x06\x52\x1b\x1c\x1b\x33\x5a\x02\xed\x56\xc0\x28\x33\x1e\xf8\x23\xc4\xff\x98\x59\x6b\x74\x77\x3f\x66\x49\xc6\x6f\x51\x0c\x61\x27\x21\x9e\xc9\x17\xf9\x88\x17\xa2\x19\x15\x05\x77\x1f\xa3\x21\xb0\xd6\xa8\xb2\x25\xfe\x86\xd1\x86\xf9\xdb\x75\x8c\x32\x2b\x58\x1f\xb4\x39\xd5\x8b\xe6\xc8\x54\x38\x4c\xa5\xca\x68\x43\x73\x61\xaf\x20\x1a\x49\x4b\x72\x52\x91\xcc\x25\xf4\xe9\x2b\xe4\x33\xdf\x46\x16\xfb\x8f\xc1\x18\x12\x88\x1b\x68\x84\x2c\x1e\xbc\x89\xcc\xcc\x7e\xc1\x73\x07\x53\x57\xe3\x35\x73\xc0\xaa\x78\x8d\x87\x55\xcb\x81\x88\xba\x8a\xee\xf5\x2d\x72\xec\xf5\x1c\x39\x0e\x2c\x26\x6c\x07\xf5\x04\xa2\x2e\xa2\x54\x07\xf3\xbd\x2c\x9a\x12\x57\x68\x1a\x88\x7b\xbd\x08\xf1\xd1\x94\x3d\x88\xc9\xbc\xae\x06\x69\xc9\x3b\x34\x0d\xd8\xaa\x88\xe6\x19\x6d\xe4\x2a\x92\x1f\xa0\x69\x84\x14\xf1\xb3\x68\x35\x3b\x31\x3d\xc5\xe8\xd3\x54\x24\xef\x0f\xde\x1d\x9e\x06\xaf\x0a\xc8\x30\xbb\x7b\x1e\x0e\xe7\xd9\xd5\x83\x69\x34\x53\x86\xae\xbd\xa6\x8c\x1f\x92\xed\x88\xe2\xb5\xe5\x2e\x2d\x19\xd8\x7d\xab\x48\xbe\x07\xd1\x55\x54\x27\x20\x9c\x89\xe1\x01\x3e\x4c\xa4\x0d\xd4\x33\xaf\xe9\xc0\x1b\xba\x88\x90\x49\x14\x27\xbf\x19\x5c\xc7\x90\x68\x1f\xa6\xce\x3c\x09\x4f\x8c\xd3\x77\x21\xaa\x11\xc5\x22\x7c\x48\x3d\x79\x84\x27\x6f\x23\x9b\xa0\x31\x10\xcd\xb4\x05\x70\x9e\x9c\xa4\x3f\x25\xea\x90\x1d\x98\x91\xd7\xd1\x94\x39\x4b\x32\x1e\x18\x8e\x0f\x57\x6d\x52\x4d\xd8\x5a\x74\x20\x9b\x6c\x30\x55\x3a\x7c\x68\xcd\x89\xf3\x01\x1b\x32\xfe\x86\xf1\xc7\x64\xae\x62\xb4\xb2\x18\x4f\xf1\xb1\x79\xe1\x71\xb5\x1d\xcd\xda\x89\x68\xb8\x7a\xb5\x01\x93\x09\xa9\x4b\x11\xc2\x65\xae\x45\x9a\xb9\x88\xfe\x27\x64\xb7\x03\x34\xc7\xb2\x83\xca\x37\x3b\xc8\x81\xbc\x62\x8e\xa6\x94\x27\xe8\x1b\x81\x8c\xe3\x05\x08\xe5\x03\xbb\xb2\x3a\xe0\x2d\xf4\x5d\xaa\x69\x8a\xd7\xae\xa7\xe5\x99\x68\xc6\x9c\x32\x70\x1e\xcf\x5c\x47\x2b\x5e\xa6\x63\xc0\xf8\x06\xe9\x0f\xae\x66\xe0\x6c\xbe\x13\xbc\x36\x50\x65\x31\x27\x11\x6c\x9f\xfe\x53\xe0\xa9\xb5\x00\xef\x3e\xe9\x59\xf2\x04\x3c\xa3\x73\x99\x3e\x39\x1e\x3a\x03\x4e\x23\xff\x9c\x46\x91\x73\x1a\xc5\x84\xe9\xd3\xfb\x7c\x28\xff\x51\xf4\x60\xd7\x96\xa1\xdd\xf1\x0f\x3b\x43\x85\xf0\x41\x3d\xa1\x67\x28\x34\x77\xec\x3c\x75\x0c\xcf\xe4\x9a\x47\x70\xfc\x49\xf6\x9b\xc1\xbd\x1c\xa8\x0c\x51\x9d\x10\xf8\xd6\xe7\x67\xd0\x77\xa3\x43\xbf\x23\x73\x15\x7a\xc1\x03\x7d\x30\x01\xbf\x0a\x0f\x88\xcb\x50\x4f\xb4\x11\xdf\x22\x92\x89\x6b\xc4\x2d\xc2\x41\xfc\x01\xf1\x07\x84\x8f\x18\x24\xfe\x2b\x71\x96\x78\x4c\xfc\x15\xf1\xcf\x89\x25\xe2\xbf\x13\x5f\x25\x36\x89\xff\x9b\xf8\x16\xb1\x4d\x7e\x95\xf8\x76\xc4\x67\x22\xbe\x46\x12\x11\x77\xd9\x67\x49\x27\xbb\x80\xdd\x4f\xce\x70\x36\x38\x1b\x94\x99\xfb\x6b\xdc\x5f\xa3\x12\xb9\x17\xb9\x35\x94\x85\xfb\xdb\xdc\xdf\xa6\x1c\xdc\x66\x6e\x33\xe5\x44\xdf\x91\x79\x05\x81\xef\xc8\x40\x2b\x3d\xb2\xd4\x3b\xa9\x3a\x20\x53\xef\x01\x9f\x72\xf1\x9f\xf0\x67\xf8\xcf\xf8\x0b\xfc\x65\xfe\x2a\xff\x15\x7f\x93\xbf\xc3\xdf\x8f\x26\xa3\xb9\xd1\x82\x68\x69\xb4\x3a\x5a\x1f\x6d\x8e\xb6\x45\xbb\xa3\x33\xa2\x73\xa3\xfd\xd1\xc5\xd1\xe7\xa2\xcb\xa3\x2b\xa3\xab\xa3\xeb\xa2\x1b\xa3\x2f\x45\x5f\x8e\x6e\x8f\xbe\x16\x7d\x23\xfa\x66\x74\x6f\xf4\xed\xe8\xc1\xe8\x7b\xd1\x23\xd1\xe3\xd1\x93\xd1\x8f\xa3\x9f\x46\xcf\x46\xcf\x47\x2f\x46\xaf\x44\xbf\x8c\x5e\x8f\xde\x8a\xde\x8d\x3e\x10\xb0\x04\x3c\x81\x50\x20\x17\x68\x04\x06\x81\x45\x60\x17\x78\x04\x5e\x81\x4f\x50\x28\x28\x11\x94\x09\x2a\x04\x17\x05\x35\x82\x7a\x41\x93\xa0\x45\x70\x45\x70\x55\xd0\x29\xe8\x12\xf4\x08\xfa\x04\x77\x04\x77\x05\xc3\x82\x51\xc1\x84\xe0\xa1\x60\x4a\x30\x2d\x98\x13\x3c\x17\x2c\x09\x5e\x08\xd6\x04\x1b\x82\x6d\xc1\x5e\x0c\xc4\xb0\x63\xf8\x31\xe2\x18\x65\x8c\x2e\xc6\x18\x63\x8d\x71\xc6\xa4\xc7\x64\xc7\xe4\xc7\x14\xc5\x94\xc6\x9c\x8f\xb9\x10\x53\x15\x53\x1b\xd3\x10\xd3\x1c\xd3\x1a\xd3\x16\xd3\x11\x73\x3d\xa6\x3b\xe6\x56\x4c\x7f\xcc\x40\xcc\x50\xcc\xfd\x98\xb1\x98\x07\x31\x8f\x62\x9e\xc4\xcc\xc4\x3c\x8b\x59\x88\x59\x8e\x59\x8d\x79\x15\xb3\x19\xb3\x13\xb3\x2f\x24\x85\x5c\xa1\x40\x28\x15\xaa\x85\x7a\xa1\x59\x68\x13\xba\x85\x19\xc2\x5c\xa1\x5f\x58\x2c\x3c\x27\x2c\x17\x56\x0a\xab\x85\x75\xc2\x46\xe1\x25\xe1\x65\x61\xbb\xf0\x9a\xf0\x86\xf0\xa6\xb0\x57\x78\x5b\x38\x28\xbc\x27\x1c\x11\x8e\x0b\x27\x85\x8f\x85\x4f\x85\xb3\xc2\x79\xe1\xa2\x70\x45\xf8\x52\xb8\x2e\xdc\x12\xee\x0a\x0f\x44\x2c\x11\x4f\x24\x14\xc9\x45\x1a\x91\x41\x64\x11\xd9\x45\x1e\x91\x57\xe4\x13\x15\x8a\x4a\x44\x65\xa2\x0a\xd1\x45\x51\x8d\xa8\x5e\xd4\x24\x6a\x11\x5d\x11\x5d\x15\x75\x8a\xba\x44\x3d\xa2\x3e\xd1\x1d\xd1\x5d\xd1\xb0\x68\x54\x34\x21\x7a\x28\x9a\x12\x4d\x8b\xe6\x44\xcf\x45\x4b\xa2\x17\xa2\x35\xd1\x86\x68\x5b\xb4\x27\x06\x31\x5b\xcc\x17\x8b\xc5\x4a\xb1\x4e\x6c\x14\x5b\xc5\x4e\x71\xba\x38\x5b\x9c\x2f\x2e\x12\x97\x8a\xcf\x8b\x2f\x88\xab\xc4\xb5\xe2\x06\x71\xb3\xb8\x55\xdc\x26\xee\x10\x5f\x17\x77\x8b\x6f\x89\xfb\xc5\x03\xe2\x21\xf1\x7d\xf1\x98\xf8\x81\xf8\x91\xf8\x89\x78\x46\xfc\x4c\xbc\x20\x5e\x16\xaf\x8a\x5f\x89\x37\xc5\x3b\xe2\x7d\x09\x29\xe1\x4a\x04\x12\xa9\x44\x2d\xd1\x4b\xcc\x12\x9b\xc4\x2d\xc9\x90\xe4\x4a\xfc\x92\x62\xc9\x39\x49\xb9\xa4\x52\x52\x2d\xa9\x93\x34\x4a\x2e\x49\x2e\x4b\xda\x25\xd7\x24\x37\x24\x37\x25\xbd\x92\xdb\x92\x41\xc9\x3d\xc9\x88\x64\x5c\x32\x29\x79\x2c\x79\x2a\x99\x95\xcc\x4b\x16\x25\x2b\x92\x97\x92\x75\xc9\x96\x64\x57\x72\x20\x65\x49\x79\x52\xa1\x54\x2e\xd5\x48\x0d\x52\x8b\xd4\x2e\xf5\x48\xbd\x52\x9f\xb4\x50\x5a\x22\x2d\x93\x56\x48\x2f\x4a\x6b\xa4\xf5\xd2\x26\x69\x8b\xf4\x8a\xf4\xaa\xb4\x53\xda\x25\xed\x91\xf6\x49\xef\x48\xef\x4a\x87\xa5\xa3\xd2\x09\xe9\x43\xe9\x94\x74\x5a\x3a\x27\x7d\x2e\x5d\x92\xbe\x90\xae\x49\x37\xa4\xdb\xd2\x3d\x19\xc8\xd8\x32\xbe\x4c\x2c\x53\xca\x74\x32\xa3\xcc\x2a\x73\xca\xd2\x65\xd9\xb2\x7c\x59\x91\xac\x54\x76\x5e\x76\x41\x56\x25\xab\x95\x35\xc8\x9a\x65\xad\xb2\x36\x59\x87\xec\xba\xac\x5b\x76\x4b\xd6\x2f\x1b\x90\x0d\xc9\xee\xcb\xc6\x64\x0f\x64\x8f\x64\x4f\x64\x33\xb2\x67\xb2\x05\xd9\xb2\x6c\x55\xf6\x4a\xb6\x29\xdb\x91\xed\xcb\x49\x39\x57\x2e\x90\x4b\xe5\x6a\xb9\x5e\x6e\x96\xdb\xe4\x6e\x79\x86\x3c\x57\xee\x97\x17\xcb\xcf\xc9\xcb\xe5\x95\xf2\x6a\x79\x9d\xbc\x51\x7e\x49\x7e\x59\xde\x2e\xbf\x26\xbf\x21\xbf\x29\xef\x95\xdf\x96\x0f\xca\xef\xc9\x47\xe4\xe3\xf2\x49\xf9\x63\xf9\x53\xf9\xac\x7c\x5e\xbe\x28\x5f\x91\xbf\x94\xaf\xcb\xb7\xe4\xbb\xf2\x03\x05\x4b\xc1\x53\x08\x15\x72\x85\x46\x61\x50\x58\x14\x76\x85\x47\xe1\x55\xf8\x14\x85\x8a\x12\x45\x99\xa2\x42\x71\x51\x51\xa3\xa8\x57\x34\x29\x5a\x14\x57\x14\x57\x15\x9d\x8a\x2e\x45\x8f\xa2\x4f\x71\x47\x71\x57\x31\xac\x18\x55\x4c\x28\x1e\x2a\xa6\x14\xd3\x8a\x39\xc5\x73\xc5\x92\xe2\x85\x62\x4d\xb1\xa1\xd8\x56\xec\x29\x41\xc9\x56\xf2\x95\x62\xa5\x52\xa9\x53\x1a\x95\x56\xa5\x53\x99\xae\xcc\x56\xe6\x2b\x8b\x94\xa5\xca\xf3\xca\x0b\xca\x2a\x65\xad\xb2\x41\xd9\xac\x6c\x55\xb6\x29\x3b\x94\xd7\x95\xdd\xca\x5b\xca\x7e\xe5\x80\x72\x48\x79\x5f\x39\xa6\x7c\xa0\x7c\xa4\x7c\xa2\x9c\x51\x3e\x53\x2e\x28\x97\x95\xab\xca\x57\xca\x4d\xe5\x8e\x72\x5f\x45\xaa\xb8\x2a\x81\x4a\xaa\x52\xab\xf4\x2a\xb3\xca\xa6\x72\xab\x32\x54\xb9\x2a\xbf\xaa\x58\x75\x4e\x55\xae\xaa\x54\x55\xab\xea\x54\x8d\xaa\x4b\xaa\xcb\xaa\x76\xd5\x35\xd5\x0d\xd5\x4d\x55\xaf\xea\xb6\x6a\x50\x75\x4f\x35\xa2\x1a\x57\x4d\xaa\x1e\xab\x9e\xaa\x66\x55\xf3\xaa\x45\xd5\x8a\xea\xa5\x6a\x5d\xb5\xa5\xda\x55\x1d\xa8\x59\x6a\x9e\x5a\xa8\x96\xab\x35\x6a\x83\xda\xa2\xb6\xab\x3d\x6a\xaf\xda\xa7\x2e\x54\x97\xa8\xcb\xd4\x15\xea\x8b\xea\x1a\x75\xbd\xba\x49\xdd\xa2\xbe\xa2\xbe\xaa\xee\x54\x77\xa9\x7b\xd4\x7d\xea\x3b\xea\xbb\xea\x61\xf5\xa8\x7a\x42\xfd\x50\x3d\xa5\x9e\x56\xcf\xa9\x9f\xab\x97\xd4\x2f\xd4\x6b\xea\x0d\xf5\xb6\x7a\x2f\x16\x62\xd9\xb1\xfc\x58\x71\xac\x32\x56\x17\x6b\x8c\xb5\xc6\x3a\x63\xd3\x63\xb3\x63\xf3\x63\x8b\x62\x4b\x63\xcf\xc7\x5e\x88\xad\x8a\xad\x8d\x6d\x88\x6d\x8e\x6d\x8d\x6d\x8b\xed\x88\xbd\x1e\xdb\x1d\x7b\x2b\xb6\x3f\x76\x20\x76\x28\xf6\x7e\xec\x58\xec\x83\xd8\x47\xb1\x4f\x62\x67\x62\x9f\xc5\x2e\xc4\x2e\xc7\xae\xc6\xbe\x8a\xdd\x8c\xdd\x89\xdd\xd7\x90\x1a\xae\x46\xa0\x91\x6a\xd4\x1a\xbd\xc6\xac\xb1\x69\xdc\x9a\x0c\x4d\xae\xc6\xaf\x29\xd6\x9c\xd3\x94\x6b\x2a\x35\xd5\x9a\x3a\x4d\xa3\xe6\x92\xe6\xb2\xa6\x5d\x73\x4d\x73\x43\x73\x53\xd3\xab\xb9\xad\x19\xd4\xdc\xd3\x8c\x68\xc6\x35\x93\x9a\xc7\x9a\xa7\x9a\x59\xcd\xbc\x66\x51\xb3\xa2\x79\xa9\x59\xd7\x6c\x69\x76\x35\x07\x5a\x96\x96\xa7\x15\x6a\xe5\x5a\x8d\xd6\xa0\xb5\x68\xed\x5a\x8f\xd6\xab\xf5\x69\x0b\xb5\x25\xda\x32\x6d\x85\xf6\xa2\xb6\x46\x5b\xaf\x6d\xd2\xb6\x68\xaf\x68\xaf\x6a\x3b\xb5\x5d\xda\x1e\x6d\x9f\xf6\x8e\xf6\xae\x76\x58\x3b\xaa\x9d\xd0\x3e\xd4\x4e\x69\xa7\xb5\x73\xda\xe7\xda\x25\xed\x0b\xed\x9a\x76\x43\xbb\xad\xdd\xd3\x81\x8e\xad\xe3\xeb\xc4\x3a\xa5\x4e\xa7\x33\xea\xac\x3a\xa7\x2e\x5d\x97\xad\xcb\xd7\x15\xe9\x4a\x75\xe7\x75\x17\x74\x55\xba\x5a\x5d\x83\xae\x59\xd7\xaa\x6b\xd3\x75\xe8\xae\xeb\xba\x75\xb7\x74\xfd\xba\x01\xdd\x90\xee\xbe\x6e\x4c\xf7\x40\xf7\x48\xf7\x44\x37\xa3\x7b\xa6\x5b\xd0\x2d\xeb\x56\x75\xaf\x74\x9b\xba\x1d\xdd\x7e\x1c\x19\xc7\x8d\x13\xc4\x49\xe3\xd4\x71\xfa\x38\x73\x9c\x2d\xce\x1d\x97\x11\x97\x1b\xe7\x8f\x2b\x8e\x3b\x17\x57\x1e\x57\x19\x57\x1d\x57\x17\xd7\x18\x77\x29\xee\x72\x5c\x7b\xdc\xb5\xb8\x1b\x71\x37\xe3\x7a\xe3\x6e\xc7\x0d\xc6\xdd\x8b\x1b\x89\x1b\x8f\x9b\x8c\x7b\x1c\xf7\x34\x6e\x36\x6e\x3e\x6e\x31\x6e\x25\xee\x65\xdc\x7a\xdc\x56\xdc\x6e\xdc\x81\x9e\xa5\xe7\xe9\x85\x7a\xb9\x5e\xa3\x37\xe8\x2d\x7a\xbb\xde\xa3\xf7\xea\x7d\xfa\x42\x7d\x89\xbe\x4c\x5f\xa1\xbf\xa8\xaf\xd1\xd7\xeb\x9b\xf4\x2d\xfa\x2b\xfa\xab\xfa\x4e\x7d\x97\xbe\x47\xdf\xa7\xbf\xa3\xbf\xab\x1f\xd6\x8f\xea\x27\xf4\x0f\xf5\x53\xfa\x69\xfd\x9c\xfe\xb9\x7e\x49\xff\x42\xbf\xa6\xdf\xd0\x6f\xeb\xf7\xe2\x21\x9e\x1d\xcf\x8f\x17\xc7\x2b\xe3\x75\xf1\xc6\x78\x6b\xbc\x33\x3e\x3d\x3e\x3b\x3e\x3f\xbe\x28\xbe\x34\xfe\x7c\xfc\x85\xf8\xaa\xf8\xda\xf8\x86\xf8\xe6\xf8\xd6\xf8\xb6\xf8\x8e\xf8\xeb\xf1\xdd\xf1\xb7\xe2\xfb\xe3\x07\xe2\x87\xe2\xef\xc7\x8f\xc5\x3f\x88\x7f\x14\xff\x24\x7e\x26\xfe\x59\xfc\x42\xfc\x72\xfc\x6a\xfc\xab\xf8\xcd\xf8\x9d\xf8\x7d\x03\x69\xe0\x1a\x04\x06\xa9\x41\x6d\xd0\x1b\xcc\x06\x9b\xc1\x6d\xc8\x30\xe4\x1a\xfc\x86\x62\xc3\x39\x43\xb9\xa1\xd2\x50\x6d\xa8\x33\x34\x1a\x2e\x19\x2e\x1b\xda\x0d\xd7\x0c\x37\x0c\x37\x0d\xbd\x86\xdb\x86\x41\xc3\x3d\xc3\x88\x61\xdc\x30\x69\x78\x6c\x78\x6a\x98\x35\xcc\x1b\x16\x0d\x2b\x86\x97\x86\x75\xc3\x96\x61\xd7\x70\x90\xc0\x4a\xe0\x25\x08\x13\xe4\x09\x9a\x04\x43\x82\x25\xc1\x9e\xe0\x49\xf0\x26\xf8\x12\x0a\x13\x4a\x12\xca\x12\x2a\x12\x2e\x26\xd4\x24\xd4\x27\x34\x25\xb4\x24\x5c\x49\xb8\x9a\xd0\x99\xd0\x95\xd0\x93\xd0\x97\x70\x27\xe1\x6e\xc2\x70\xc2\x68\xc2\x44\xc2\xc3\x84\xa9\x84\xe9\x84\xb9\x84\xe7\x09\x4b\x09\x2f\x12\xd6\x12\x36\x12\xb6\x13\xf6\x8c\x60\x64\x1b\xf9\x46\xb1\x51\x69\xd4\x19\x8d\x46\xab\xd1\x69\x4c\x37\x66\x1b\xf3\x8d\x45\xc6\x52\xe3\x79\xe3\x05\x63\x95\xb1\xd6\xd8\x60\x6c\x36\xb6\x1a\xdb\x8c\x1d\xc6\xeb\xc6\x6e\xe3\x2d\x63\xbf\x71\xc0\x38\x64\xbc\x6f\x1c\x33\x3e\x30\x3e\x32\x3e\x31\xce\x18\x9f\x19\x17\x8c\xcb\xc6\x55\xe3\x2b\xe3\xa6\x71\xc7\xb8\x6f\x22\x4d\x5c\x93\xc0\x24\x35\xa9\x4d\x7a\x93\xd9\x64\x33\xb9\x4d\x19\xa6\x5c\x93\xdf\x54\x6c\x3a\x67\x2a\x37\x55\x9a\xaa\x4d\x75\xa6\x46\xd3\x25\xd3\x65\x53\xbb\xe9\x9a\xe9\x86\xe9\xa6\xa9\xd7\x74\xdb\x34\x68\xba\x67\x1a\x31\x8d\x9b\x26\x4d\x8f\x4d\x4f\x4d\xb3\xa6\x79\xd3\xa2\x69\xc5\xf4\xd2\xb4\x6e\xda\x32\xed\x9a\x0e\xcc\x2c\x33\xcf\x2c\x34\xcb\xcd\x1a\xb3\xc1\x6c\x31\xdb\xcd\x1e\xb3\xd7\xec\x33\x17\x9a\x4b\xcc\x65\xe6\x0a\xf3\x45\x73\x8d\xb9\xde\xdc\x64\x6e\x31\x5f\x31\x5f\x35\x77\x9a\xbb\xcc\x3d\xe6\x3e\xf3\x1d\xf3\x5d\xf3\xb0\x79\xd4\x3c\x61\x7e\x68\x9e\x32\x4f\x9b\xe7\xcc\xcf\xcd\x4b\xe6\x17\xe6\x35\xf3\x86\x79\xdb\xbc\x97\x08\x89\xec\x44\x7e\xa2\x38\x51\x99\xa8\x4b\x34\x26\x5a\x13\x9d\x89\xe9\x89\xd9\x89\xf9\x89\x45\x89\xa5\x89\xe7\x13\x2f\x24\x56\x25\xd6\x26\x36\x24\x36\x27\xb6\x26\xb6\x25\x76\x24\x5e\x4f\xec\x4e\xbc\x95\xd8\x9f\x38\x90\x38\x94\x78\x3f\x71\x2c\xf1\x41\xe2\xa3\xc4\x27\x89\x33\x89\xcf\x12\x17\x12\x97\x13\x57\x13\x5f\x25\x6e\x26\xee\x24\xee\x5b\x48\x0b\xd7\x22\xb0\x48\x2d\x6a\x8b\xde\x62\xb6\xd8\x2c\x6e\x4b\x86\x25\xd7\xe2\xb7\x14\x5b\xce\x59\xca\x2d\x95\x96\x6a\x4b\x9d\xa5\xd1\x72\xc9\x72\xd9\xd2\x6e\xb9\x66\xb9\x61\xb9\x69\xe9\xb5\xdc\xb6\x0c\x5a\xee\x59\x46\x2c\xe3\x96\x49\xcb\x63\xcb\x53\xcb\xac\x65\xde\xb2\x68\x59\xb1\xbc\xb4\xac\x5b\xb6\x2c\xbb\x96\x83\x24\x56\x12\x2f\x49\x98\x24\x4f\xd2\x24\x19\x92\x2c\x49\xf6\x24\x4f\x92\x37\xc9\x97\x54\x98\x54\x92\x54\x96\x54\x91\x74\x31\xa9\x26\xa9\x3e\xa9\x29\xa9\x25\xe9\x4a\xd2\xd5\xa4\xce\xa4\xae\xa4\x9e\xa4\xbe\xa4\x3b\x49\x77\x93\x86\x93\x46\x93\x26\x92\x1e\x26\x4d\x25\x4d\x27\xcd\x25\x3d\x4f\x5a\x4a\x7a\x91\xb4\x96\xb4\x91\xb4\x9d\xb4\x67\x05\x2b\xdb\xca\xb7\x8a\xad\x4a\xab\xce\x6a\xb4\x5a\xad\x4e\x6b\xba\x35\xdb\x9a\x6f\x2d\xb2\x96\x5a\xcf\x5b\x2f\x58\xab\xac\xb5\xd6\x06\x6b\xb3\xb5\xd5\xda\x66\xed\xb0\x5e\xb7\x76\x5b\x6f\x59\xfb\xad\x03\xd6\x21\xeb\x7d\xeb\x98\xf5\x81\xf5\x91\xf5\x89\x75\xc6\xfa\xcc\xba\x60\x5d\xb6\xae\x5a\x5f\x59\x37\xad\x3b\xd6\xfd\x64\x32\x99\x9b\x2c\x48\x96\x26\xab\x93\xf5\xc9\xe6\x64\x5b\xb2\x3b\x39\x23\x39\x37\xd9\x9f\x5c\x9c\x7c\x2e\xb9\x3c\xb9\x32\xb9\x3a\xb9\x2e\xb9\x31\xf9\x52\xf2\xe5\xe4\xf6\xe4\x6b\xc9\x37\x92\x6f\x26\xf7\x26\xdf\x4e\x1e\x4c\xbe\x97\x3c\x92\x3c\x9e\x3c\x99\xfc\x38\xf9\x69\xf2\x6c\xf2\x7c\xf2\x62\xf2\x4a\xf2\xcb\xe4\xf5\xe4\xad\xe4\xdd\xe4\x03\x1b\xcb\xc6\xb3\x09\x6d\x72\x9b\xc6\x66\xb0\x59\x6c\x76\x9b\xc7\xe6\xb5\xf9\x6c\x85\xb6\x12\x5b\x99\xad\xc2\x76\xd1\x56\x63\xab\xb7\x35\xd9\x5a\x6c\x57\x6c\x57\x6d\x9d\xb6\x2e\x5b\x8f\xad\xcf\x76\xc7\x76\xd7\x36\x6c\x1b\xb5\x4d\xd8\x1e\xda\xa6\x6c\xd3\xb6\x39\xdb\x73\xdb\x92\xed\x85\x6d\xcd\xb6\x61\xdb\xb6\xed\xa5\x40\x0a\x3b\x85\x9f\x22\x4e\x51\xa6\xe8\x52\x8c\x29\xd6\x14\x67\x4a\x7a\x4a\x76\x4a\x7e\x4a\x51\x4a\x69\xca\xf9\x94\x0b\x29\x55\x29\xb5\x29\x0d\x29\xcd\x29\xad\x29\x6d\x29\x1d\x29\xd7\x53\xba\x53\x6e\xa5\xf4\xa7\x0c\xa4\x0c\xa5\xdc\x4f\x19\x4b\x79\x90\xf2\x28\xe5\x49\xca\x4c\xca\xb3\x94\x85\x94\xe5\x94\xd5\x94\x57\x29\x9b\x29\x3b\x29\xfb\x76\xd2\xce\xb5\x0b\xec\x52\xbb\xda\xae\xb7\x9b\xed\x36\xbb\xdb\x9e\x61\xcf\xb5\xfb\xed\xc5\xf6\x73\xf6\x72\x7b\xa5\xbd\xda\x5e\x67\x6f\xb4\x5f\xb2\x5f\xb6\xb7\xdb\xaf\xd9\x6f\xd8\x6f\xda\x7b\xed\xb7\xed\x83\xf6\x7b\xf6\x11\xfb\xb8\x7d\xd2\xfe\xd8\xfe\xd4\x3e\x6b\x9f\xb7\x2f\xda\x57\xec\x2f\xed\xeb\xf6\x2d\xfb\xae\xfd\xc0\xc1\x72\xf0\x1c\x42\x87\xdc\xa1\x71\x18\x1c\x16\x87\xdd\xe1\x71\x78\x1d\x3e\x47\xa1\xa3\xc4\x51\xe6\xa8\x70\x5c\x74\xd4\x38\xea\x1d\x4d\x8e\x16\xc7\x15\xc7\x55\x47\xa7\xa3\xcb\xd1\xe3\xe8\x73\xdc\x71\xdc\x75\x0c\x3b\x46\x1d\x13\x8e\x87\x8e\x29\xc7\xb4\x63\xce\xf1\xdc\xb1\xe4\x78\xe1\x58\x73\x6c\x38\xb6\x1d\x7b\x4e\x70\xb2\x9d\x7c\xa7\xd8\xa9\x74\xea\x9c\x46\xa7\xd5\xe9\x74\xa6\x3b\xb3\x9d\xf9\xce\x22\x67\xa9\xf3\xbc\xf3\x82\xb3\xca\x59\xeb\x6c\x70\x36\x3b\x5b\x9d\x6d\xce\x0e\xe7\x75\x67\xb7\xf3\x96\xb3\xdf\x39\xe0\x1c\x72\xde\x77\x8e\x39\x1f\x38\x1f\x39\x9f\x38\x67\x9c\xcf\x9c\x0b\xce\x65\xe7\xaa\xf3\x95\x73\xd3\xb9\xe3\xdc\x77\x91\x2e\xae\x4b\xe0\x92\xba\xd4\x2e\xbd\xcb\xec\xb2\xb9\xdc\xae\x0c\x57\xae\xcb\xef\x2a\x76\x9d\x73\x95\xbb\x2a\x5d\xd5\xae\x3a\x57\xa3\xeb\x92\xeb\xb2\xab\xdd\x75\xcd\x75\xc3\x75\xd3\xd5\xeb\xba\xed\x1a\x74\xdd\x73\x8d\xb8\xc6\x5d\x93\xae\xc7\xae\xa7\xae\x59\xd7\xbc\x6b\xd1\xb5\xe2\x7a\xe9\x5a\x77\x6d\xb9\x76\x5d\x07\x6e\x96\x9b\xe7\x16\xba\xe5\x6e\x8d\xdb\xe0\xb6\xb8\xed\x6e\x8f\xdb\xeb\xf6\xb9\x0b\xdd\x25\xee\x32\x77\x85\xfb\xa2\xbb\xc6\x5d\xef\x6e\x72\xb7\xb8\xaf\xb8\xaf\xba\x3b\xdd\x5d\xee\x1e\x77\x9f\xfb\x8e\xfb\xae\x7b\xd8\x3d\xea\x9e\x70\x3f\x74\x4f\xb9\xa7\xdd\x73\xee\xe7\xee\x25\xf7\x0b\xf7\x9a\x7b\xc3\xbd\xed\xde\x4b\x85\x54\x76\x2a\x1f\x88\x08\x2d\xf3\x7d\x5c\x9a\x46\xa4\x62\xbc\x00\xe3\xdf\x0f\xf2\xac\xaf\x61\x7c\x22\x26\xf3\x43\x8c\xdf\x08\xf2\xe4\x38\xc6\x3b\xb0\x6b\xb7\x31\xde\x15\xe4\x39\xf9\x41\x9e\x2d\xc5\xf8\x3c\x4c\xfe\xfd\x30\xf8\x1e\xc6\xd7\x1c\x3f\xe6\x88\xbf\xc2\xf0\x1f\x60\xf7\xfd\x2a\x86\x8f\x60\xfc\x77\x30\xfe\xbb\x18\xff\x3b\x18\xbf\x1e\xe4\xa9\xf7\x8f\xc7\x59\xdf\xc6\xec\xf0\xbd\x30\x32\x5b\x98\x8c\xf0\x78\x9e\x55\x78\x3c\xce\x79\xef\x78\x3d\xac\x70\xe3\xc1\xc7\x5c\x8a\xf1\x3f\xc2\xf4\xff\x24\x8c\x4e\xec\xbe\xec\x62\x0c\xcf\xc2\x78\x6c\xed\xa8\x3f\xc3\xec\xaf\xfd\x78\x78\x0e\xff\x78\x5f\x0d\xf1\xcf\x13\xf0\x21\xfe\x79\x02\x1e\xdf\x0b\xe1\xfc\xf3\xa3\xf0\xb8\x7f\x9e\x84\x0f\xf1\x4f\x6c\x6c\x11\xfc\x30\xbe\xfa\x11\x78\xf6\xcf\xc2\xf8\xf9\xb7\x4f\xc7\x87\xf3\xed\xb0\x3e\xff\xfe\x09\x7c\xfb\xa3\xf0\x5b\xa7\xe4\xb1\x75\x0f\xd9\x53\xd2\xe3\x7d\x15\xb7\xe1\xa9\x71\xc1\xf1\x36\xff\xd8\xf0\x30\xf1\x21\x04\xdf\xe4\x1c\xbf\x8f\xbe\xfd\x8f\x87\xe3\xf9\x25\x64\x9c\x1f\x17\xbe\x71\xfc\x5a\x87\xc3\x43\xe2\x83\xf0\x1f\x0f\x67\xfd\x14\xe3\x31\x9f\xc1\x73\x6b\x88\x3c\x9e\x67\x0b\xc3\xf0\xae\x30\xd7\x7e\x14\xbc\xef\xc3\xe5\xf1\xf8\x89\xdb\xf6\xb4\x78\xc4\x77\x4e\x70\xed\x49\xea\x87\x13\xe0\x9c\x77\x31\xfe\xdf\x60\x32\x58\xed\x81\xe7\xd3\x53\xe3\x58\xdd\x82\xe7\xe2\x8f\x0d\xc7\x73\xdf\x4f\xfe\xe1\x78\x48\x0e\xda\xfa\xe5\xe3\x78\xfd\x16\x52\x93\xe0\xf9\x51\x1a\x06\xc7\xea\x3a\xbc\x56\x39\x2d\x4e\xf6\x73\x3e\x3c\x96\x86\xa9\xc1\x22\xf0\xb1\x61\x7b\x3c\xa4\x0e\xc7\xeb\x1c\xf6\xf1\xfa\xd9\xef\x7d\xf8\xbd\x58\x61\xfc\x21\x02\xcb\xef\xac\x31\x8c\x4f\x3c\x7e\xee\x21\xb1\xf4\x77\xb1\xb5\xf8\x06\x66\x93\xbf\xe0\x1c\x1b\xd3\xc2\xc5\xa5\x90\x78\x52\x1e\xe4\xb9\x39\x9c\x0f\xdf\xe3\xf8\xd9\x01\x8f\x6f\x58\x0c\xe7\x62\x71\x89\x8d\xd7\xa5\xe1\xec\x16\xe6\x4c\x11\xb2\xa7\xb0\xb9\x93\xf8\xdc\xf1\x7d\xd4\x1f\x06\xc7\xec\xcf\xc6\xe6\x18\x91\x75\xfc\xbc\xf0\x33\x4b\x88\x0f\x97\x9f\xc0\x6f\x87\x3f\x9c\xa7\xf0\x73\x01\xee\x03\xa3\x41\x9e\x87\xdd\x2b\x12\xb3\x27\xf7\x3e\x36\xe6\xaa\x30\xe3\x8f\xc7\xe4\xfd\x18\x6f\xc2\xfc\x87\xc4\xec\x10\xa6\x2e\x0a\x97\x1f\xc3\xc5\xed\x70\x71\x03\xaf\x31\xf0\x33\x05\x5e\xeb\x9e\xb6\x96\x08\xe7\xdb\xa7\xcd\x35\x21\xeb\xb2\x7f\xfc\x7c\x4f\xb2\x16\xe1\xc6\xc9\xf9\x16\x26\x83\xc5\xcc\xb0\x79\xf6\x94\xb5\xeb\x69\x6b\xbc\xd3\xd6\x42\xa7\xb6\xe7\x29\x73\xf1\x69\x73\x50\xd8\x1c\x3a\x76\xfc\x3a\x9e\xa8\xe6\xc4\xfd\xed\x62\x98\x79\x85\xd9\xef\xa7\x5d\x97\xb0\x76\x0b\x93\x43\x29\xfc\x0c\xbe\x83\xe1\xb1\xc7\xaf\x17\xe7\xcf\x8f\xe7\x43\xce\xf8\x61\xce\x29\x78\x0d\x89\x8f\x1f\x8f\xc3\xf8\xdc\xa9\x5b\x18\x8f\xfb\x6a\x6a\x98\x75\xfc\xf1\x09\xfc\x33\x4c\x8d\xcd\x4e\x38\x7e\xbd\xc2\xfa\x5b\xb8\x9a\x24\x4c\x4f\x29\x6c\xdf\x06\xb7\x4f\xde\x09\xae\x0d\x73\x1e\x67\x63\xeb\x45\x61\x76\xc0\x73\x01\x6e\x37\x3c\x07\x85\xe4\xeb\x70\xf7\xed\xc5\x78\x61\x18\xfe\x04\xe7\xee\x90\x98\xf0\x7d\x8c\xc7\xf2\x2f\x85\xd5\x45\x24\x3e\x4e\xbc\x8e\xc2\xf2\x11\xde\x37\x0b\xc7\x87\x1b\x4f\x48\x3d\x86\xc7\x1f\x2c\x77\xe0\xb9\x2f\xe2\x07\xc7\xfb\xc3\x69\xf9\x90\xb9\x63\x3c\xeb\x1b\xc7\xf3\x21\x3d\xbd\x53\xf6\x5e\xf0\x38\x16\xb6\x1f\x88\xfb\xe1\xdf\x1c\xbf\xbe\x21\x35\x39\x1e\x43\xfe\x92\x73\xec\xfe\xc5\xeb\x19\x3c\x66\x86\xf0\x75\x27\xe0\xb1\x5e\x6b\x48\x7c\xeb\x3f\xde\x9f\x71\x5f\x8d\x50\x85\xf1\x73\x2c\xa7\x53\x61\xea\xc6\x70\xe3\xe1\x60\x79\x99\x83\xc5\x1f\x2e\x5e\xbb\x8a\x31\x9d\x18\xcf\xfe\xe9\xf1\x7c\x44\x09\x26\xff\xc3\xe3\xaf\x65\x4d\x60\xf2\xac\xe3\xf9\x70\xfb\x17\xef\x57\x87\xdd\x17\x61\xfa\xc9\xb8\x7f\x86\xeb\x2d\x87\xac\x3b\x3e\x06\xac\x26\xc4\x7b\xf2\x9c\x70\xfe\xfc\xfd\x30\x7a\xbe\x1f\xc6\x57\x4f\x30\x5f\xbc\x26\x3f\x75\xef\xfd\x04\x3d\x76\x0a\x7f\x4e\x81\xfb\x58\x56\x18\xfb\x9c\x24\x47\x60\xb1\x9d\xc2\xc6\x13\x12\xcf\xc3\xf4\x64\xf0\x9c\x42\x86\x89\xcf\x21\x7a\xc2\xd5\x84\xa9\xc7\x8f\xed\xd4\xf8\x47\xe9\x5b\x7e\x02\xf8\x2f\xab\xff\x89\x9f\xc1\x71\xff\xfc\xb8\xfa\x99\x1f\x17\x7e\xea\x7e\x66\xb8\xfe\xe4\x69\xf1\x4f\xa2\x87\x89\xef\xf1\x70\x35\xc3\x29\xf1\x8f\xab\xe7\xf9\x49\xf7\x39\xc3\x9e\x05\xc2\xed\x8b\x70\xf8\xc7\xd5\x17\xfd\x65\xf5\x4b\x3f\xe1\x3e\xea\x3f\xb5\xfe\x6a\x48\x2d\x24\xfc\x70\x3c\x5c\xdf\xf5\x93\xc6\x43\x9e\xd1\x67\x9d\x00\x0f\x77\xe6\xfa\x98\x7a\xbf\x21\x31\xf0\x27\x61\xc6\x1c\xe6\xac\x87\xf7\x8d\x3f\xb6\xe7\x86\xff\x3f\xc5\x7f\x69\xf9\xf7\x63\xc2\x3f\xe9\x1e\xd7\x2f\x0d\x0f\xd3\x6f\xff\xa4\xf1\xd3\xc6\xb7\x90\x1e\x7b\xcd\x3f\x1e\x7e\xa2\xe7\x50\x1f\x01\xa7\xbe\x89\xe1\xf8\xf7\x8b\x4e\x50\xe7\x84\xeb\x91\x86\xc4\x28\x3c\x67\x61\x7a\xb0\x9e\xc6\x2f\xff\x8d\x1d\x32\xf0\x1b\x16\x10\xf8\x3b\xf6\x44\xe0\xef\xd8\x13\x60\xa4\xc7\xc8\x2a\x3e\x8e\x7e\xfa\x4e\xcf\xa7\xef\xf4\x7c\xfa\x4e\xcf\xa7\xef\xf4\x7c\xfa\x4e\xcf\xa7\xef\xf4\x7c\xfa\x4e\xcf\xa7\xef\xf4\x7c\xfa\x4e\xcf\xa7\xef\xf4\x7c\xfa\x4e\xcf\xa7\xef\xf4\xfc\x7f\xf9\x9d\x1e\x36\x8b\xa6\xcc\xdf\xdb\x41\x3c\xfa\xab\x3b\x11\x02\xc4\x0b\x10\xff\x3e\xe2\xdf\x47\x7f\x9f\xe7\x6b\x34\xcf\xfa\x1a\xe2\x13\x11\x9f\x88\x64\x7e\x88\x64\x7e\x88\xf8\x0d\xc4\x6f\xa0\xbf\xde\x33\x8e\x7e\x73\x6c\x1c\xf1\x0e\xc4\x3b\xd0\xb5\xdb\xe8\xda\x6d\xc4\xbb\x10\xef\xa2\x79\x4e\x3e\xcd\x73\xf2\xd1\x5f\x16\x92\xd2\x3c\x1b\xfd\xb5\x1f\x76\x1e\xe2\xf3\x90\x3c\x1a\x0f\xeb\xfd\x23\xf8\x1e\xc2\xf7\x10\x5f\x83\xf8\x9a\xc3\x63\x8e\xf8\x2b\x34\xb6\xbf\x42\xf8\x0f\x10\xfe\x03\x74\xdf\xaf\xa2\xfb\x7e\x15\xe1\x23\x08\x1f\x41\xfc\x77\x10\xff\x1d\xc4\x7f\x17\xf1\xdf\x45\xfc\xef\x20\xfe\x77\x10\xbf\x8e\xf8\x75\xf4\x37\x8e\xd0\xd8\xa8\xf7\x0f\xe3\xac\x6f\x23\xfe\xdb\xc8\x0e\xdf\x43\x76\xf8\xde\x11\x99\x2d\xc4\x6f\x21\x19\x21\x92\x11\x1e\xe6\x59\x85\x48\xa6\xf0\x30\xce\x79\x0f\x8d\xff\xbd\xc3\x7a\x70\x5b\x85\xdc\x0b\x1f\x33\xfa\x5d\x38\xaa\x14\xf1\x3f\x42\xfc\x8f\x90\xfe\x9f\x20\xfd\x3f\x39\xa2\x13\xdd\x97\x85\xee\xcb\x2e\x46\xf6\x47\x7f\x8b\x89\x95\x85\xf0\x2c\xc4\xa3\xb5\x63\xa1\xb5\xa3\xfe\x0c\xe9\xfc\x33\x64\x7f\xd4\xab\x0b\xf8\xdb\x47\xe0\x99\xef\xdf\x71\xf8\x8c\xaf\x22\x5c\xc0\xac\x35\xea\x3a\x7c\xed\xa4\x3c\xd3\x4b\x0b\xf8\xe7\x09\x78\xe6\x59\x1f\xb3\x17\x98\xe7\x2a\xaf\xfd\x93\xe9\x78\x7d\x54\x9e\xe9\x45\x31\xfe\x79\x12\x9e\xe9\xf1\x04\xfc\x13\x5b\xeb\x08\x3e\xf2\x73\xfe\x11\x5f\xfd\x08\x3c\xfb\x67\x68\xad\x7f\x76\xc4\xcf\x31\xdf\x3e\x09\x1f\xce\xb7\xc3\xfa\x3c\xee\xc3\xe1\x7c\xfb\xa3\xf0\xb8\xce\x93\xf0\x98\x6f\x87\xec\x29\x0c\xc7\x7d\x15\xb7\x61\x78\x3c\x18\x87\x43\x70\xcc\xb7\x71\x9b\x7f\x6c\x38\xe6\xcf\xf8\x5c\x42\x62\xfe\x26\xc2\x37\x8f\xec\x23\x7c\x7d\x4f\x8d\x63\x79\xe4\x04\xf2\xcc\xb3\x6b\x26\xbf\x84\x8c\xf3\xd4\x78\x30\x4f\x85\xe0\xa8\x4f\xcc\xe4\x2c\xa6\x07\xcc\xac\x35\x9e\xcb\x42\xe2\x33\x1e\x1f\x70\xbf\x3d\x35\x8e\xe5\xc7\x13\xc8\xb3\x7e\x8a\xc6\xf0\x53\xc4\x6b\xd9\x36\x9a\x22\x19\xf4\x7d\x43\x26\xb7\x86\xc8\xe3\x79\x16\xcb\x1d\x21\xbc\x8b\xe9\xf2\x32\xd7\x32\xdd\xdf\x83\x43\x79\x39\x44\xe7\x49\xf0\x3e\x84\xf7\xbd\x4d\x1e\x8f\x9f\xb8\x6d\xf1\xbc\x1f\x8a\x1f\x2f\x1f\x81\x72\x74\xc4\x77\xde\x7a\x2d\x16\x63\x43\xeb\x87\xd3\xe1\x9c\x77\x51\x9e\x7d\x17\xf1\xff\x06\xf1\xff\x06\xc9\xec\x31\x1d\xf1\x83\x43\xf9\x14\xaf\x49\x42\xf1\x30\xf2\xe8\x39\x00\x53\xb7\xe0\xb9\x38\x3c\x1e\xac\x73\x4e\x24\x8f\xed\xbb\x90\xfc\x8e\xe7\xc4\x10\xfc\x78\xf9\x90\x1c\x84\xaf\xc5\x27\x8e\xb3\x59\xc7\xe1\xcc\xb3\x5f\xa6\x7e\x0b\xa9\x49\xf0\xfc\x88\xc7\x6d\x1c\x47\xcf\x69\x99\xba\x0e\xaf\x55\x4e\x8b\x93\xfd\xc8\x3e\xfd\x6f\x8d\xa5\x61\x6a\xb0\x08\x34\xb6\xc0\xdf\xc3\xc4\xf6\x78\x48\x1d\x8e\xd7\x39\x6c\x24\xc3\x3e\xac\x9f\x8d\xea\x40\xf6\x7b\x6f\xbb\x17\x0b\xf9\x03\xeb\x88\x3f\x44\xa0\xfc\x1e\x81\xf2\x3b\x6b\x0c\xe1\x63\x07\x87\xea\x7c\xbc\x06\x0e\x89\xb1\xbf\x8b\xf0\xdf\x45\x6b\xf1\x0d\xb4\x2f\xbe\x81\x6c\xf2\x17\xc8\x26\x7f\x71\x38\xd6\x85\x8b\x4b\x21\xf1\xa4\x1c\xe1\xe5\x34\xcf\xcd\xa1\x79\x6e\xce\x5b\xf7\x38\x3a\x3b\xb0\x99\xb3\x03\xd2\xc9\x66\xe2\x1b\x8a\xe1\x2c\x14\xc3\xb9\x28\x2e\x71\x51\x5c\x62\xa3\xb5\x63\x33\x75\x29\xb2\x5b\xc4\x51\xbb\x85\x39\x53\x84\xec\x29\x6c\xee\x24\x9a\x3b\xf9\x8d\x23\xfb\x08\xf9\x06\xab\xff\x6d\xfb\x8b\x8d\xe6\xc8\x46\x73\x8c\x40\xb5\x74\x44\xd6\xe1\x79\xe1\x67\x96\x90\xb3\x09\x66\x2b\x7c\x8d\x42\xfc\x16\xfd\x8e\x34\x6b\xf8\x6d\x3c\x85\xe6\x4e\x31\xe7\x02\xe4\x03\x14\xe3\x03\xa3\x48\x66\x94\xe6\x99\xf7\x48\x78\xe8\x5e\x91\xc8\x9e\x91\xc8\x9e\xdc\xfb\xc8\xb6\xf7\xd1\x98\xab\xd0\x98\xab\x8e\x8c\x3f\x1e\xe9\x89\x47\xf2\x7e\x24\x8f\xfe\xbe\x2b\xd7\x84\x78\x13\xf2\x1f\x12\xf9\x0f\x79\xf0\x96\x7a\x29\x5c\x7e\x0c\x17\xb7\xc3\xc5\x13\xbc\xc6\xc0\xcf\x14\x78\xad\x1b\xb6\x66\x08\x53\x63\x30\xdf\x3b\x7b\xed\xdb\x88\x2f\x3c\x78\xeb\x19\xf6\xf8\x31\x33\xef\xf4\x04\xd6\x65\x1f\xad\xc5\xfe\xe1\xf9\xf2\xd0\xba\xbf\x7d\x2d\xc2\x8d\x93\xf3\x2d\x64\xe7\x6f\x21\x19\x14\x33\x23\x8a\x0f\xde\x96\x67\x4f\x59\xd3\x9e\xb6\x26\x3c\x6d\xed\x74\xda\xdc\x1d\x3e\x47\x1f\x8f\x9f\x36\x37\x85\xcd\xad\x58\x2c\xc5\xd7\xf1\x44\x35\x27\xee\x6f\x17\x11\x7e\xf1\xc8\xbc\xc2\xec\xf7\xf0\xeb\xc2\x3e\xb6\xf6\x0e\x6b\xb7\x30\x39\x94\x42\x67\x4c\x8a\x39\x83\xef\xa0\xb1\xed\x20\x3c\x16\xe1\xb1\x87\xd7\x8b\xf3\xe7\xc8\xdf\xfe\xfc\x30\x1f\xd2\x83\xc2\xf2\x5d\xc8\x19\x13\xab\x21\xf1\xf1\xe3\x71\x18\x9f\x3b\x75\x0b\xf1\xb7\x10\x8f\xe6\x4e\x31\xbe\x8a\xf7\xb8\xf0\x5a\xe2\xc7\x48\xe7\x8f\xdf\x66\x1f\xbc\x7f\x15\xe2\x87\x09\x68\x5f\x27\x1c\x89\x03\xe1\x6a\x3f\x3c\x6e\xe3\x35\x49\x98\x9e\x52\xd8\xbe\x0d\x6e\x1f\x14\x5b\x58\x79\x6f\xbd\x36\xcc\x79\x9c\x8d\xd6\x8b\x8d\xd6\x8b\x42\x76\xa0\x90\x1d\xf0\x5c\x80\xdb\x0d\xcf\x41\x21\xf9\x3a\xdc\x7d\x7b\x11\x8f\xfe\x66\x38\xde\x3b\x0a\xe1\x4f\x70\xee\x0e\x89\x09\xdf\x47\xfc\xf7\x11\x8f\xf2\x2f\x89\xf2\x2f\x85\xea\x22\x0a\xd5\x45\x24\x1a\x27\xc9\x8c\x13\xf9\x15\xc9\xd4\x51\x28\x1f\x45\xa0\x7c\x84\xf7\xcd\xc2\xf1\xe1\xc6\x83\xfb\x6a\x48\xfc\xc1\x72\x07\x9e\xfb\x22\xd0\x78\x22\x7e\x70\xd8\x1f\x4e\xcb\x87\xcc\x1d\xe3\x59\xa8\xf6\x60\x7d\xe3\x30\x1f\xd2\xd3\x3b\x65\xef\x05\x8f\x63\x61\xfb\x81\x78\xac\xf8\x1b\xc4\xff\xcd\xe1\xf5\x0d\xa9\xc9\xf1\x18\xf2\x97\x68\x6c\x7f\x79\x78\xff\xe2\xf5\x0c\x1e\x33\x43\xf8\x3a\xc4\xd7\xbd\x95\x47\xbd\x56\xea\x7b\x07\x87\xf3\x2f\x56\x8f\x85\xd4\x54\x98\xaf\x46\xa8\xd0\x7a\xa9\x8e\xf8\x39\x56\xaf\x52\xc8\x4f\xa8\x23\x75\x63\xb8\xf1\x70\x50\x5e\xe6\xa0\xbc\xcc\x41\xf1\x87\x83\xe2\x0f\x17\xf9\x09\x97\xa9\x5d\xc5\x68\x9c\x62\xa4\x13\xf1\x2c\xc4\xb3\xd1\xb9\x80\xfd\xd3\xc3\x7c\x44\x09\x1a\x67\x09\x92\x47\xb5\x0a\xeb\x87\x87\xaf\x65\x4d\x20\x7e\x02\xc9\xb3\x90\x3c\xeb\x30\x1f\x6e\xff\xe2\xfd\xea\xb0\xfb\x22\x4c\x3f\x19\xf7\xcf\x70\xbd\xe5\x90\x75\xc7\xc7\x80\x6a\x42\x16\xaa\x09\xf1\x9e\x3c\x07\xe9\xe1\x1c\xf5\x67\x7c\x2f\xe0\x7a\x10\xce\xfa\xfe\x11\x5f\x3d\xc1\x7c\xf1\x9a\xfc\xd4\xbd\xf7\x13\xf4\xd8\x29\x74\xa6\xa0\x6a\x8e\xc4\x43\xac\x97\x1e\x62\x9f\x93\xe4\x08\x2c\xb6\x53\x68\x3c\xd4\xd6\x91\x78\x8e\xf2\x69\xc4\x91\x9e\x0c\x9e\x53\x42\x7c\x1e\x9b\x57\x88\x9e\x70\x7d\x4b\xf4\x8e\x4e\x20\x5f\xe0\x35\x0c\x9e\x47\x4e\x82\x7f\x94\xbe\xe5\x27\x80\x87\xd6\xae\x88\x3f\xa6\xa6\xc5\x71\xf6\xb1\xb5\xc4\x69\xfb\x9f\xcc\x3b\x3d\xcc\x19\x9c\x79\xa7\x87\xf1\xcf\xb0\x7d\xce\x53\xf6\x33\x4f\x2f\x7f\x3c\x7e\xb2\x7e\x26\xd6\x63\x0c\x73\x56\x0a\xdb\xb7\x0c\x87\x87\xed\x49\x7e\x3c\xbd\x4d\xe6\x1d\x1d\xce\xd1\x9a\x21\x2c\xce\x66\x1d\x87\x9f\xbe\xe7\x79\x4a\x3c\xa4\x86\x47\x73\x3f\xe6\x4c\xf4\x0f\xc7\x43\x78\x7c\x5f\x84\xc3\x3f\xae\xbe\x68\x38\xf9\x8f\xab\x2f\x7a\x5a\x3c\xa4\x5f\x8a\xfc\xea\xad\xfd\xd2\xd3\xe2\xe1\xfa\x9c\xa7\xc7\xf1\xb3\x2a\xb6\xaf\xc3\xe0\xcc\xbb\x3b\x81\x5a\x08\xcf\x47\x78\x8d\x84\xe1\xe1\xfa\xae\xa7\xc7\xd9\xac\xd3\xe0\xcc\xbb\x3b\x81\x67\xf4\xf8\x73\xe7\x70\x78\xb8\x3e\x70\xd8\x1e\x2f\xfb\xd8\x33\x75\x58\x1c\x8f\x81\x98\x3f\xb0\x8b\xd9\x75\x58\xdd\x5b\x77\xdc\x59\x8f\x79\xa7\x87\xe9\x1b\x87\xcd\xa7\xa1\x67\xf9\xba\x4f\x16\x47\x36\xf9\x90\xe7\x95\x27\x91\xff\xb8\x70\xf6\x87\xf6\x2e\x3e\xe2\x73\xc9\xba\x8f\x07\x0f\x57\x0f\x04\xef\x7b\xda\xe7\x80\xa7\xed\x19\x1e\xc2\xeb\x3e\x1e\x3c\x5c\x5e\xc0\xee\x8b\x72\xf7\xd1\x7e\xfb\xc7\x87\xb3\x8f\xed\xe7\x9f\x2c\xee\x61\xf9\x11\xbd\x73\x13\xe8\xb1\xa3\x1c\x11\x51\xf3\xf1\xe2\x6c\xd6\x71\x78\xf8\xe7\x50\x88\x7f\xfb\xf3\xa9\x13\xe0\xd4\x37\x51\x2c\xfa\x26\xc2\xd1\xf9\x85\xc5\x7c\xbf\xe8\x04\x75\x4e\x68\x8f\x34\x98\x67\x43\x62\x14\x9e\xb3\xb0\xf8\x8f\xf5\x34\xfe\x49\xbc\xd3\x43\xe9\x28\x23\x00\x70\x80\x00\x1d\x00\xd0\xbc\x15\x08\x70\x02\x40\x3a\x00\x64\x03\x01\xf9\x40\x90\xbf\x45\x73\xe4\x6f\xb1\x8a\x81\x20\x86\x18\x8a\x7e\xef\x17\x21\x01\x8a\x7e\xb5\xec\x33\xad\xfe\xfb\x40\x7d\xe6\x21\xf0\xc9\x25\x91\x55\xe4\x14\xa5\x8b\xb2\x45\xf9\xa2\x22\x51\xa9\xe8\xbc\xe8\x82\xa8\x4a\x54\x2b\x6a\x10\x35\x8b\x5a\x45\x6d\xa2\x0e\xd1\x75\x51\xb7\xe8\x96\xa8\x5f\x34\x20\x1a\x12\xdd\x17\x8d\x89\x1e\x88\x1e\x89\x9e\x88\x66\x44\xcf\x44\x0b\xa2\x65\xd1\xaa\xe8\x95\x68\x53\xb4\x23\xda\x17\x93\x62\xae\x58\x20\x96\x8a\xd5\x62\xbd\xd8\x2c\xb6\x89\xdd\xe2\x0c\x71\xae\xd8\x2f\x2e\x16\x9f\x13\x97\x8b\x2b\xc5\xd5\xe2\x3a\x71\xa3\xf8\x92\xf8\xb2\xb8\x5d\x7c\x4d\x7c\x43\x7c\x53\xdc\x2b\xbe\x2d\x1e\x14\xdf\x13\x8f\x88\xc7\xc5\x93\xe2\xc7\xe2\xa7\xe2\x59\xf1\xbc\x78\x51\xbc\x22\x7e\x29\x5e\x17\x6f\x89\x77\xc5\x07\x12\x96\x84\x27\x11\x4a\xe4\x12\x8d\xc4\x20\xb1\x48\xec\x12\x8f\xc4\x2b\xf1\x49\x0a\x25\x25\x92\x32\x49\x85\xe4\xa2\xa4\x46\x52\x2f\x69\x92\xb4\x48\xae\x48\xae\x4a\x3a\x25\x5d\x92\x1e\x49\x9f\xe4\x8e\xe4\xae\x64\x58\x32\x2a\x99\x90\x3c\x94\x4c\x49\xa6\x25\x73\x92\xe7\x92\x25\xc9\x0b\xc9\x9a\x64\x43\xb2\x2d\xd9\x93\x82\x94\x2d\xe5\x4b\xc5\x52\xa5\x54\x27\x35\x4a\xad\x52\xa7\x34\x5d\x9a\x2d\xcd\x97\x16\x49\x4b\xa5\xe7\xa5\x17\xa4\x55\xd2\x5a\x69\x83\xb4\x59\xda\x2a\x6d\x93\x76\x48\xaf\x4b\xbb\xa5\xb7\xa4\xfd\xd2\x01\xe9\x90\xf4\xbe\x74\x4c\xfa\x40\xfa\x48\xfa\x44\x3a\x23\x7d\x26\x5d\x90\x2e\x4b\x57\xa5\xaf\xa4\x9b\xd2\x1d\xe9\xbe\x8c\x94\x71\x65\x02\x99\x54\xa6\x96\xe9\x65\x66\x99\x4d\xe6\x96\x65\xc8\x72\x65\x7e\x59\xb1\xec\x9c\xac\x5c\x56\x29\xab\x96\xd5\xc9\x1a\x65\x97\x64\x97\x65\xed\xb2\x6b\xb2\x1b\xb2\x9b\xb2\x5e\xd9\x6d\xd9\xa0\xec\x9e\x6c\x44\x36\x2e\x9b\x94\x3d\x96\x3d\x95\xcd\xca\xe6\x65\x8b\xb2\x15\xd9\x4b\xd9\xba\x6c\x4b\xb6\x2b\x3b\x90\xb3\xe4\x3c\xb9\x50\x2e\x97\x6b\xe4\x06\xb9\x45\x6e\x97\x7b\xe4\x5e\xb9\x4f\x5e\x28\x2f\x91\x97\xc9\x2b\xe4\x17\xe5\x35\xf2\x7a\x79\x93\xbc\x45\x7e\x45\x7e\x55\xde\x29\xef\x92\xf7\xc8\xfb\xe4\x77\xe4\x77\xe5\xc3\xf2\x51\xf9\x84\xfc\xa1\x7c\x4a\x3e\x2d\x9f\x93\x3f\x97\x2f\xc9\x5f\xc8\xd7\xe4\x1b\xf2\x6d\xf9\x9e\x02\x14\x6c\x05\x5f\x21\x56\x28\x15\x3a\x85\x51\x61\x55\x38\x15\xe9\x8a\x6c\x45\xbe\xa2\x48\x51\xaa\x38\xaf\xb8\xa0\xa8\x52\xd4\x2a\x1a\x14\xcd\x8a\x56\x45\x9b\xa2\x43\x71\x5d\xd1\xad\xb8\xa5\xe8\x57\x0c\x28\x86\x14\xf7\x15\x63\x8a\x07\x8a\x47\x8a\x27\x8a\x19\xc5\x33\xc5\x82\x62\x59\xb1\xaa\x78\xa5\xd8\x54\xec\x28\xf6\x95\xa4\x92\xab\x14\x28\xa5\x4a\xb5\x52\xaf\x34\x2b\x6d\x4a\xb7\x32\x43\x99\xab\xf4\x2b\x8b\x95\xe7\x94\xe5\xca\x4a\x65\xb5\xb2\x4e\xd9\xa8\xbc\xa4\xbc\xac\x6c\x57\x5e\x53\xde\x50\xde\x54\xf6\x2a\x6f\x2b\x07\x95\xf7\x94\x23\xca\x71\xe5\xa4\xf2\xb1\xf2\xa9\x72\x56\x39\xaf\x5c\x54\xae\x28\x5f\x2a\xd7\x95\x5b\xca\x5d\xe5\x81\x8a\xa5\xe2\xa9\x84\x2a\xb9\x4a\xa3\x32\xa8\x2c\x2a\xbb\xca\xa3\xf2\xaa\x7c\xaa\x42\x55\x89\xaa\x4c\x55\xa1\xba\xa8\xaa\x51\xd5\xab\x9a\x54\x2d\xaa\x2b\xaa\xab\xaa\x4e\x55\x97\xaa\x47\xd5\xa7\xba\xa3\xba\xab\x1a\x56\x8d\xaa\x26\x54\x0f\x55\x53\xaa\x69\xd5\x9c\xea\xb9\x6a\x49\xf5\x42\xb5\xa6\xda\x50\x6d\xab\xf6\xd4\xa0\x66\xab\xf9\x6a\xb1\x5a\xa9\xd6\xa9\x8d\x6a\xab\xda\xa9\x4e\x57\x67\xab\xf3\xd5\x45\xea\x52\xf5\x79\xf5\x05\x75\x95\xba\x56\xdd\xa0\x6e\x56\xb7\xaa\xdb\xd4\x1d\xea\xeb\xea\x6e\xf5\x2d\x75\xbf\x7a\x40\x3d\xa4\xbe\xaf\x1e\x53\x3f\x50\x3f\x52\x3f\x51\xcf\xa8\x9f\xa9\x17\xd4\xcb\xea\x55\xf5\x2b\xf5\xa6\x7a\x47\xbd\x1f\x4b\xc6\x72\x63\x05\xb1\xd2\x58\x75\xac\x3e\xd6\x1c\x6b\x8b\x75\xc7\x66\xc4\xe6\xc6\xfa\x63\x8b\x63\xcf\xc5\x96\xc7\x56\xc6\x56\xc7\xd6\xc5\x36\xc6\x5e\x8a\xbd\x1c\xdb\x1e\x7b\x2d\xf6\x46\xec\xcd\xd8\xde\xd8\xdb\xb1\x83\xb1\xf7\x62\x47\x62\xc7\x63\x27\x63\x1f\xc7\x3e\x8d\x9d\x8d\x9d\x8f\x5d\x8c\x5d\x89\x7d\x19\xbb\x1e\xbb\x15\xbb\x1b\x7b\xa0\x61\x69\x78\x1a\xa1\x46\xae\xd1\x68\x0c\x1a\x8b\xc6\xae\xf1\x68\xbc\x1a\x9f\xa6\x50\x53\xa2\x29\xd3\x54\x68\x2e\x6a\x6a\x34\xf5\x9a\x26\x4d\x8b\xe6\x8a\xe6\xaa\xa6\x53\xd3\xa5\xe9\xd1\xf4\x69\xee\x68\xee\x6a\x86\x35\xa3\x9a\x09\xcd\x43\xcd\x94\x66\x5a\x33\xa7\x79\xae\x59\xd2\xbc\xd0\xac\x69\x36\x34\xdb\x9a\x3d\x2d\x68\xd9\x5a\xbe\x56\xac\x55\x6a\x75\x5a\xa3\xd6\xaa\x75\x6a\xd3\xb5\xd9\xda\x7c\x6d\x91\xb6\x54\x7b\x5e\x7b\x41\x5b\xa5\xad\xd5\x36\x68\x9b\xb5\xad\xda\x36\x6d\x87\xf6\xba\xb6\x5b\x7b\x4b\xdb\xaf\x1d\xd0\x0e\x69\xef\x6b\xc7\xb4\x0f\xb4\x8f\xb4\x4f\xb4\x33\xda\x67\xda\x05\xed\xb2\x76\x55\xfb\x4a\xbb\xa9\xdd\xd1\xee\xeb\x48\x1d\x57\x27\xd0\x49\x75\x6a\x9d\x5e\x67\xd6\xd9\x74\x6e\x5d\x86\x2e\x57\xe7\xd7\x15\xeb\xce\xe9\xca\x75\x95\xba\x6a\x5d\x9d\xae\x51\x77\x49\x77\x59\xd7\xae\xbb\xa6\xbb\xa1\xbb\xa9\xeb\xd5\xdd\xd6\x0d\xea\xee\xe9\x46\x74\xe3\xba\x49\xdd\x63\xdd\x53\xdd\xac\x6e\x5e\xb7\xa8\x5b\xd1\xbd\xd4\xad\xeb\xb6\x74\xbb\xba\x83\x38\x56\x1c\x2f\x4e\x18\x27\x8f\xd3\xc4\x19\xe2\x2c\x71\xf6\x38\x4f\x9c\x37\xce\x17\x57\x18\x57\x12\x57\x16\x57\x11\x77\x31\xae\x26\xae\x3e\xae\x29\xae\x25\xee\x4a\xdc\xd5\xb8\xce\xb8\xae\xb8\x9e\xb8\xbe\xb8\x3b\x71\x77\xe3\x86\xe3\x46\xe3\x26\xe2\x1e\xc6\x4d\xc5\x4d\xc7\xcd\xc5\x3d\x8f\x5b\x8a\x7b\x11\xb7\x16\xb7\x11\xb7\x1d\xb7\xa7\x07\x3d\x5b\xcf\xd7\x8b\xf5\x4a\xbd\x4e\x6f\xd4\x5b\xf5\x4e\x7d\xba\x3e\x5b\x9f\xaf\x2f\xd2\x97\xea\xcf\xeb\x2f\xe8\xab\xf4\xb5\xfa\x06\x7d\xb3\xbe\x55\xdf\xa6\xef\xd0\x5f\xd7\x77\xeb\x6f\xe9\xfb\xf5\x03\xfa\x21\xfd\x7d\xfd\x98\xfe\x81\xfe\x91\xfe\x89\x7e\x46\xff\x4c\xbf\xa0\x5f\xd6\xaf\xea\x5f\xe9\x37\xf5\x3b\xfa\xfd\x78\x32\x9e\x1b\x2f\x88\x97\xc6\xab\xe3\xf5\xf1\xe6\x78\x5b\xbc\x3b\x3e\x23\x3e\x37\xde\x1f\x5f\x1c\x7f\x2e\xbe\x3c\xbe\x32\xbe\x3a\xbe\x2e\xbe\x31\xfe\x52\xfc\xe5\xf8\xf6\xf8\x6b\xf1\x37\xe2\x6f\xc6\xf7\xc6\xdf\x8e\x1f\x8c\xbf\x17\x3f\x12\x3f\x1e\x3f\x19\xff\x38\xfe\x69\xfc\x6c\xfc\x7c\xfc\x62\xfc\x4a\xfc\xcb\xf8\xf5\xf8\xad\xf8\xdd\xf8\x03\x03\xcb\xc0\x33\x08\x0d\x72\x83\xc6\x60\x30\x58\x0c\x76\x83\xc7\xe0\x35\xf8\x0c\x85\x86\x12\x43\x99\xa1\xc2\x70\xd1\x50\x63\xa8\x37\x34\x19\x5a\x0c\x57\x0c\x57\x0d\x9d\x86\x2e\x43\x8f\xa1\xcf\x70\xc7\x70\xd7\x30\x6c\x18\x35\x4c\x18\x1e\x1a\xa6\x0c\xd3\x86\x39\xc3\x73\xc3\x92\xe1\x85\x61\xcd\xb0\x61\xd8\x36\xec\x25\x40\x02\x3b\x81\x9f\x20\x4e\x50\x26\xe8\x12\x8c\x09\xd6\x04\x67\x42\x7a\x42\x76\x42\x7e\x42\x51\x42\x69\xc2\xf9\x84\x0b\x09\x55\x09\xb5\x09\x0d\x09\xcd\x09\xad\x09\x6d\x09\x1d\x09\xd7\x13\xba\x13\x6e\x25\xf4\x27\x0c\x24\x0c\x25\xdc\x4f\x18\x4b\x78\x90\xf0\x28\xe1\x49\xc2\x4c\xc2\xb3\x84\x85\x84\xe5\x84\xd5\x84\x57\x09\x9b\x09\x3b\x09\xfb\x46\xd2\xc8\x35\x0a\x8c\x52\xa3\xda\xa8\x37\x9a\x8d\x36\xa3\xdb\x98\x61\xcc\x35\xfa\x8d\xc5\xc6\x73\xc6\x72\x63\xa5\xb1\xda\x58\x67\x6c\x34\x5e\x32\x5e\x36\xb6\x1b\xaf\x19\x6f\x18\x6f\x1a\x7b\x8d\xb7\x8d\x83\xc6\x7b\xc6\x11\xe3\xb8\x71\xd2\xf8\xd8\xf8\xd4\x38\x6b\x9c\x37\x2e\x1a\x57\x8c\x2f\x8d\xeb\xc6\x2d\xe3\xae\xf1\xc0\xc4\x32\xf1\x4c\x42\x93\xdc\xa4\x31\x19\x4c\x16\x93\xdd\xe4\x31\x79\x4d\x3e\x53\xa1\xa9\xc4\x54\x66\xaa\x30\x5d\x34\xd5\x98\xea\x4d\x4d\xa6\x16\xd3\x15\xd3\x55\x53\xa7\xa9\xcb\xd4\x63\xea\x33\xdd\x31\xdd\x35\x0d\x9b\x46\x4d\x13\xa6\x87\xa6\x29\xd3\xb4\x69\xce\xf4\xdc\xb4\x64\x7a\x61\x5a\x33\x6d\x98\xb6\x4d\x7b\x66\x30\xb3\xcd\x7c\xb3\xd8\xac\x34\xeb\xcc\x46\xb3\xd5\xec\x34\xa7\x9b\xb3\xcd\xf9\xe6\x22\x73\xa9\xf9\xbc\xf9\x82\xb9\xca\x5c\x6b\x6e\x30\x37\x9b\x5b\xcd\x6d\xe6\x0e\xf3\x75\x73\xb7\xf9\x96\xb9\xdf\x3c\x60\x1e\x32\xdf\x37\x8f\x99\x1f\x98\x1f\x99\x9f\x98\x67\xcc\xcf\xcc\x0b\xe6\x65\xf3\xaa\xf9\x95\x79\xd3\xbc\x63\xde\x4f\x24\x13\xb9\x89\x82\x44\x69\xa2\x3a\x51\x9f\x68\x4e\xb4\x25\xba\x13\x33\x12\x73\x13\xfd\x89\xc5\x89\xe7\x12\xcb\x13\x2b\x13\xab\x13\xeb\x12\x1b\x13\x2f\x25\x5e\x4e\x6c\x4f\xbc\x96\x78\x23\xf1\x66\x62\x6f\xe2\xed\xc4\xc1\xc4\x7b\x89\x23\x89\xe3\x89\x93\x89\x8f\x13\x9f\x26\xce\x26\xce\x27\x2e\x26\xae\x24\xbe\x4c\x5c\x4f\xdc\x4a\xdc\x4d\x3c\xb0\xb0\x2c\x3c\x8b\xd0\x22\xb7\x68\x2c\x06\x8b\xc5\x62\xb7\x78\x2c\x5e\x8b\xcf\x52\x68\x29\xb1\x94\x59\x2a\x2c\x17\x2d\x35\x96\x7a\x4b\x93\xa5\xc5\x72\xc5\x72\xd5\xd2\x69\xe9\xb2\xf4\x58\xfa\x2c\x77\x2c\x77\x2d\xc3\x96\x51\xcb\x84\xe5\xa1\x65\xca\x32\x6d\x99\xb3\x3c\xb7\x2c\x59\x5e\x58\xd6\x2c\x1b\x96\x6d\xcb\x5e\x12\x24\xb1\x93\xf8\x49\xe2\x24\x65\x92\x2e\xc9\x98\x64\x4d\x72\x26\xa5\x27\x65\x27\xe5\x27\x15\x25\x95\x26\x9d\x4f\xba\x90\x54\x95\x54\x9b\xd4\x90\xd4\x9c\xd4\x9a\xd4\x96\xd4\x91\x74\x3d\xa9\x3b\xe9\x56\x52\x7f\xd2\x40\xd2\x50\xd2\xfd\xa4\xb1\xa4\x07\x49\x8f\x92\x9e\x24\xcd\x24\x3d\x4b\x5a\x48\x5a\x4e\x5a\x4d\x7a\x95\xb4\x99\xb4\x93\xb4\x6f\x25\xad\x5c\xab\xc0\x2a\xb5\xaa\xad\x7a\xab\xd9\x6a\xb3\xba\xad\x19\xd6\x5c\xab\xdf\x5a\x6c\x3d\x67\x2d\xb7\x56\x5a\xab\xad\x75\xd6\x46\xeb\x25\xeb\x65\x6b\xbb\xf5\x9a\xf5\x86\xf5\xa6\xb5\xd7\x7a\xdb\x3a\x68\xbd\x67\x1d\xb1\x8e\x5b\x27\xad\x8f\xad\x4f\xad\xb3\xd6\x79\xeb\xa2\x75\xc5\xfa\xd2\xba\x6e\xdd\xb2\xee\x5a\x0f\x92\x59\xc9\xbc\x64\x61\xb2\x3c\x59\x93\x6c\x48\xb6\x24\xdb\x93\x3d\xc9\xde\x64\x5f\x72\x61\x72\x49\x72\x59\x72\x45\xf2\xc5\xe4\x9a\xe4\xfa\xe4\xa6\xe4\x96\xe4\x2b\xc9\x57\x93\x3b\x93\xbb\x92\x7b\x92\xfb\x92\xef\x24\xdf\x4d\x1e\x4e\x1e\x4d\x9e\x48\x7e\x98\x3c\x95\x3c\x9d\x3c\x97\xfc\x3c\x79\x29\xf9\x45\xf2\x5a\xf2\x46\xf2\x76\xf2\x9e\x0d\x6c\x6c\x1b\xdf\x26\xb6\x29\x6d\x3a\x9b\xd1\x66\xb5\x39\x6d\xe9\xb6\x6c\x5b\xbe\xad\xc8\x56\x6a\x3b\x6f\xbb\x60\xab\xb2\xd5\xda\x1a\x6c\xcd\xb6\x56\x5b\x9b\xad\xc3\x76\xdd\xd6\x6d\xbb\x65\xeb\xb7\x0d\xd8\x86\x6c\xf7\x6d\x63\xb6\x07\xb6\x47\xb6\x27\xb6\x19\xdb\x33\xdb\x82\x6d\xd9\xb6\x6a\x7b\x65\xdb\xb4\xed\xd8\xf6\x53\xc8\x14\x6e\x8a\x20\x45\x9a\xa2\x4e\xd1\xa7\x98\x53\x6c\x29\xee\x94\x8c\x94\xdc\x14\x7f\x4a\x71\xca\xb9\x94\xf2\x94\xca\x94\xea\x94\xba\x94\xc6\x94\x4b\x29\x97\x53\xda\x53\xae\xa5\xdc\x48\xb9\x99\xd2\x9b\x72\x3b\x65\x30\xe5\x5e\xca\x48\xca\x78\xca\x64\xca\xe3\x94\xa7\x29\xb3\x29\xf3\x29\x8b\x29\x2b\x29\x2f\x53\xd6\x53\xb6\x52\x76\x53\x0e\xec\x2c\x3b\xcf\x2e\xb4\xcb\xed\x1a\xbb\xc1\x6e\xb1\xdb\xed\x1e\xbb\xd7\xee\xb3\x17\xda\x4b\xec\x65\xf6\x0a\xfb\x45\x7b\x8d\xbd\xde\xde\x64\x6f\xb1\x5f\xb1\x5f\xb5\x77\xda\xbb\xec\x3d\xf6\x3e\xfb\x1d\xfb\x5d\xfb\xb0\x7d\xd4\x3e\x61\x7f\x68\x9f\xb2\x4f\xdb\xe7\xec\xcf\xed\x4b\xf6\x17\xf6\x35\xfb\x86\x7d\xdb\xbe\xe7\x00\x07\xdb\xc1\x77\x88\x1d\x4a\x87\xce\x61\x74\x58\x1d\x4e\x47\xba\x23\xdb\x91\xef\x28\x72\x94\x3a\xce\x3b\x2e\x38\xaa\x1c\xb5\x8e\x06\x47\xb3\xa3\xd5\xd1\xe6\xe8\x70\x5c\x77\x74\x3b\x6e\x39\xfa\x1d\x03\x8e\x21\xc7\x7d\xc7\x98\xe3\x81\xe3\x91\xe3\x89\x63\xc6\xf1\xcc\xb1\xe0\x58\x76\xac\x3a\x5e\x39\x36\x1d\x3b\x8e\x7d\x27\xe9\xe4\x3a\x05\x4e\xa9\x53\xed\xd4\x3b\xcd\x4e\x9b\xd3\xed\xcc\x70\xe6\x3a\xfd\xce\x62\xe7\x39\x67\xb9\xb3\xd2\x59\xed\xac\x73\x36\x3a\x2f\x39\x2f\x3b\xdb\x9d\xd7\x9c\x37\x9c\x37\x9d\xbd\xce\xdb\xce\x41\xe7\x3d\xe7\x88\x73\xdc\x39\xe9\x7c\xec\x7c\xea\x9c\x75\xce\x3b\x17\x9d\x2b\xce\x97\xce\x75\xe7\x96\x73\xd7\x79\xe0\x62\xb9\x78\x2e\xa1\x4b\xee\xd2\xb8\x0c\x2e\x8b\xcb\xee\xf2\xb8\xbc\x2e\x9f\xab\xd0\x55\xe2\x2a\x73\x55\xb8\x2e\xba\x6a\x5c\xf5\xae\x26\x57\x8b\xeb\x8a\xeb\xaa\xab\xd3\xd5\xe5\xea\x71\xf5\xb9\xee\xb8\xee\xba\x86\x5d\xa3\xae\x09\xd7\x43\xd7\x94\x6b\xda\x35\xe7\x7a\xee\x5a\x72\xbd\x70\xad\xb9\x36\x5c\xdb\xae\x3d\x37\xb8\xd9\x6e\xbe\x5b\xec\x56\xba\x75\x6e\xa3\xdb\xea\x76\xba\xd3\xdd\xd9\xee\x7c\x77\x91\xbb\xd4\x7d\xde\x7d\xc1\x5d\xe5\xae\x75\x37\xb8\x9b\xdd\xad\xee\x36\x77\x87\xfb\xba\xbb\xdb\x7d\xcb\xdd\xef\x1e\x70\x0f\xb9\xef\xbb\xc7\xdc\x0f\xdc\x8f\xdc\x4f\xdc\x33\xee\x67\xee\x05\xf7\xb2\x7b\xd5\xfd\xca\xbd\xe9\xde\x71\xef\xa7\x92\xa9\xdc\x54\x41\xaa\x34\x55\x9d\xaa\x4f\x35\xa7\xda\x52\xdd\xa9\x19\xa9\xb9\xa9\xfe\xd4\xe2\xd4\x73\xa9\xe5\xa9\x95\xa9\xd5\xa9\x75\xa9\x8d\xa9\x97\x52\x2f\xa7\xb6\xa7\x5e\x4b\xbd\x91\x7a\x33\xb5\x37\xf5\x76\xea\x60\xea\xbd\xd4\x91\xd4\xf1\xd4\xc9\xd4\xc7\xa9\x4f\x53\x67\x53\xe7\x53\x17\x53\x57\x52\x5f\xa6\xae\xa7\x6e\xa5\xee\xa6\x1e\x78\x58\x1e\x9e\x47\xe8\x91\x7b\x34\x1e\x83\xc7\xe2\xb1\x7b\x3c\x1e\xaf\xc7\xe7\x29\xf4\x94\x78\xca\x3c\x15\x9e\x8b\x9e\x1a\x4f\xbd\xa7\xc9\xd3\xe2\xb9\xe2\xb9\xea\xe9\xf4\x74\x79\x7a\x3c\x7d\x9e\x3b\x9e\xbb\x9e\x61\xcf\xa8\x67\xc2\xf3\xd0\x33\xe5\x99\xf6\xcc\x79\x9e\x7b\x96\x3c\x2f\x3c\x6b\x9e\x0d\xcf\xb6\x67\x2f\x0d\xd2\xd8\x69\xfc\x34\x71\x9a\x32\x4d\x97\x66\x4c\xb3\xa6\x39\xd3\xd2\xd3\xb2\xd3\xf2\xd3\x8a\xd2\x4a\xd3\xce\xa7\x5d\x48\xab\x4a\xab\x4d\x6b\x48\x6b\x4e\x6b\x4d\x6b\x4b\xeb\x48\xbb\x9e\xd6\x9d\x76\x2b\xad\x3f\x6d\x20\x6d\x28\xed\x7e\xda\x58\xda\x83\xb4\x47\x69\x4f\xd2\x66\xd2\x9e\xa5\x2d\xa4\x2d\xa7\xad\xa6\xbd\x4a\xdb\x4c\xdb\x49\xdb\x4f\x27\xd3\xb9\xe9\x82\x74\x69\xba\x3a\x5d\x9f\x6e\x4e\xb7\xa5\xbb\xd3\x33\xd2\x73\xd3\xfd\xe9\xc5\xe9\xe7\xd2\xcb\xd3\x2b\xd3\xab\xd3\xeb\xd2\x1b\xd3\x2f\xa5\x5f\x4e\x6f\x4f\xbf\x96\x7e\x23\xfd\x66\x7a\x6f\xfa\xed\xf4\xc1\xf4\x7b\xe9\x23\xe9\xe3\xe9\x93\xe9\x8f\xd3\x9f\xa6\xcf\xa6\xcf\xa7\x2f\xa6\xaf\xa4\xbf\x4c\x5f\x4f\xdf\x4a\xdf\x4d\x3f\x38\xc3\x3a\xc3\x3b\x23\x3c\x23\x3f\xa3\x39\x63\x38\x63\x39\x63\x3f\xe3\x39\xe3\x3d\xe3\x3b\x53\x78\xa6\xe4\x4c\xd9\x99\x8a\x33\x17\xcf\xd4\x9c\xa9\x3f\xd3\x74\xa6\xe5\xcc\x95\x33\x57\xcf\x74\x9e\xe9\x3a\xd3\x73\xa6\xef\xcc\x9d\x33\x77\xcf\x0c\x9f\x19\x3d\x33\x71\xe6\xe1\x99\xa9\x33\xd3\x67\xe6\xce\x3c\x3f\xb3\x74\xe6\xc5\x99\xb5\x33\x1b\x67\xb6\xcf\xec\x65\x40\x06\x3b\x83\x9f\x21\xce\x50\x66\xe8\x32\x8c\x19\xd6\x0c\x67\x46\x7a\x46\x76\x46\x7e\x46\x51\x46\x69\xc6\xf9\x8c\x0b\x19\x55\x19\xb5\x19\x0d\x19\xcd\x19\xad\x19\x6d\x19\x1d\x19\xd7\x33\xba\x33\x6e\x65\xf4\x67\x0c\x64\x0c\x65\xdc\xcf\x18\xcb\x78\x90\xf1\x28\xe3\x49\xc6\x4c\xc6\xb3\x8c\x85\x8c\xe5\x8c\xd5\x8c\x57\x19\x9b\x19\x3b\x19\xfb\x99\x64\x26\x37\x53\x90\x29\xcd\x54\x67\xea\x33\xcd\x99\xb6\x4c\x77\x66\x46\x66\x6e\xa6\x3f\xb3\x38\xf3\x5c\x66\x79\x66\x65\x66\x75\x66\x5d\x66\x63\xe6\xa5\xcc\xcb\x99\xed\x99\xd7\x32\x6f\x64\xde\xcc\xec\xcd\xbc\x9d\x39\x98\x79\x2f\x73\x24\x73\x3c\x73\x32\xf3\x71\xe6\xd3\xcc\xd9\xcc\xf9\xcc\xc5\xcc\x95\xcc\x97\x99\xeb\x99\x5b\x99\xbb\x99\x07\x5e\x96\x97\xe7\x15\x7a\xe5\x5e\x8d\xd7\xe0\xb5\x78\xed\x5e\x8f\xd7\xeb\xf5\x79\x0b\xbd\x25\xde\x32\x6f\x85\xf7\xa2\xb7\xc6\x5b\xef\x6d\xf2\xb6\x78\xaf\x78\xaf\x7a\x3b\xbd\x5d\xde\x1e\x6f\x9f\xf7\x8e\xf7\xae\x77\xd8\x3b\xea\x9d\xf0\x3e\xf4\x4e\x79\xa7\xbd\x73\xde\xe7\xde\x25\xef\x0b\xef\x9a\x77\xc3\xbb\xed\xdd\xcb\x82\x2c\x76\x16\x3f\x4b\x9c\xa5\xcc\xd2\x65\x19\xb3\xac\x59\xce\xac\xf4\xac\xec\xac\xfc\xac\xa2\xac\xd2\xac\xf3\x59\x17\xb2\xaa\xb2\x6a\xb3\x1a\xb2\x9a\xb3\x5a\xb3\xda\xb2\x3a\xb2\xae\x67\x75\x67\xdd\xca\xea\xcf\x1a\xc8\x1a\xca\xba\x9f\x35\x96\xf5\x20\xeb\x51\xd6\x93\xac\x99\xac\x67\x59\x0b\x59\xcb\x59\xab\x59\xaf\xb2\x36\xb3\x76\xb2\xf6\xb3\xc9\x6c\x6e\xb6\x20\x5b\x9a\xad\xce\xd6\x67\x9b\xb3\x6d\xd9\xee\xec\x8c\xec\xdc\x6c\x7f\x76\x71\xf6\xb9\xec\xf2\xec\xca\xec\xea\xec\xba\xec\xc6\xec\x4b\xd9\x97\xb3\xdb\xb3\xaf\x65\xdf\xc8\xbe\x99\xdd\x9b\x7d\x3b\x7b\x30\xfb\x5e\xf6\x48\xf6\x78\xf6\x64\xf6\xe3\xec\xa7\xd9\xb3\xd9\xf3\xd9\x8b\xd9\x2b\xd9\x2f\xb3\xd7\xb3\xb7\xb2\x77\xb3\x0f\x72\x58\x39\xbc\x1c\x61\x8e\x3c\x47\x93\x63\xc8\xb1\xe4\xd8\x73\x3c\x39\xde\x1c\x5f\x4e\x61\x4e\x49\x4e\x59\x4e\x45\xce\xc5\x9c\x9a\x9c\xfa\x9c\xa6\x9c\x96\x9c\x2b\x39\x57\x73\x3a\x73\xba\x72\x7a\x72\xfa\x72\xee\xe4\xdc\xcd\x19\xce\x19\xcd\x99\xc8\x79\x98\x33\x95\x33\x9d\x33\x97\xf3\x3c\x67\x29\xe7\x45\xce\x5a\xce\x46\xce\x76\xce\x5e\x2e\xe4\xb2\x73\xf9\xb9\xe2\x5c\x65\xae\x2e\xd7\x98\x6b\xcd\x75\xe6\xa6\xe7\x66\xe7\xe6\xe7\x16\xe5\x96\xe6\x9e\xcf\xbd\x90\x5b\x95\x5b\x9b\xdb\x90\xdb\x9c\xdb\x9a\xdb\x96\xdb\x91\x7b\x3d\xb7\x3b\xf7\x56\x6e\x7f\xee\x40\xee\x50\xee\xfd\xdc\xb1\xdc\x07\xb9\x8f\x72\x9f\xe4\xce\xe4\x3e\xcb\x5d\xc8\x5d\xce\x5d\xcd\x7d\x95\xbb\x99\xbb\x93\xbb\x9f\x47\xe6\x71\xf3\x04\x79\xd2\x3c\x75\x9e\x3e\xcf\x9c\x67\xcb\x73\xe7\x65\xe4\xe5\xe6\xf9\xf3\x8a\xf3\xce\xe5\x95\xe7\x55\xe6\x55\xe7\xd5\xe5\x35\xe6\x5d\xca\xbb\x9c\xd7\x9e\x77\x2d\xef\x46\xde\xcd\xbc\xde\xbc\xdb\x79\x83\x79\xf7\xf2\x46\xf2\xc6\xf3\x26\xf3\x1e\xe7\x3d\xcd\x9b\xcd\x9b\xcf\x5b\xcc\x5b\xc9\x7b\x99\xb7\x9e\xb7\x95\xb7\x9b\x77\xe0\x63\xf9\x78\x3e\xa1\x4f\xee\xd3\xf8\x0c\x3e\x8b\xcf\xee\xf3\xf8\xbc\x3e\x9f\xaf\xd0\x57\xe2\x2b\xf3\x55\xf8\x2e\xfa\x6a\x7c\xf5\xbe\x26\x5f\x8b\xef\x8a\xef\xaa\xaf\xd3\xd7\xe5\xeb\xf1\xf5\xf9\xee\xf8\xee\xfa\x86\x7d\xa3\xbe\x09\xdf\x43\xdf\x94\x6f\xda\x37\xe7\x7b\xee\x5b\xf2\xbd\xf0\xad\xf9\x36\x7c\xdb\xbe\xbd\xb3\x70\x96\x7d\x96\x7f\x56\x7c\x56\x79\x56\x77\xd6\x78\xd6\x7a\xd6\x79\x36\xfd\x6c\xf6\xd9\xfc\xb3\x45\x67\x4b\xcf\x9e\x3f\x7b\xe1\x6c\xd5\xd9\xda\xb3\x0d\x67\x9b\xcf\xb6\x9e\x6d\x3b\xdb\x71\xf6\xfa\xd9\xee\xb3\xb7\xce\xf6\x9f\x1d\x38\x3b\x74\xf6\xfe\xd9\xb1\xb3\x0f\xce\x3e\x3a\xfb\xe4\xec\xcc\xd9\x67\x67\x17\xce\x2e\x9f\x5d\x3d\xfb\xea\xec\xe6\xd9\x9d\xb3\xfb\xf9\x64\x3e\x37\x5f\x90\x2f\xcd\x57\xe7\xeb\xf3\xcd\xf9\xb6\x7c\x77\x7e\x46\x7e\x6e\xbe\x3f\xbf\x38\xff\x5c\x7e\x79\x7e\x65\x7e\x75\x7e\x5d\x7e\x63\xfe\xa5\xfc\xcb\xf9\xed\xf9\xd7\xf2\x6f\xe4\xdf\xcc\xef\xcd\xbf\x9d\x3f\x98\x7f\x2f\x7f\x24\x7f\x3c\x7f\x32\xff\x71\xfe\xd3\xfc\xd9\xfc\xf9\xfc\xc5\xfc\x95\xfc\x97\xf9\xeb\xf9\x5b\xf9\xbb\xf9\x07\x05\xac\x02\x5e\x81\xb0\x40\x5e\xa0\x29\x30\x14\x58\x0a\xec\x05\x9e\x02\x6f\x81\xaf\xa0\xb0\xa0\xa4\xa0\xac\xa0\xa2\xe0\x62\x41\x4d\x41\x7d\x41\x53\x41\x4b\xc1\x95\x82\xab\x05\x9d\x05\x5d\x05\x3d\x05\x7d\x05\x77\x0a\xee\x16\x0c\x17\x8c\x16\x4c\x14\x3c\x2c\x98\x2a\x98\x2e\x98\x2b\x78\x5e\xb0\x54\xf0\xa2\x60\xad\x60\xa3\x60\xbb\x60\xcf\x0f\x7e\xb6\x9f\xef\x17\xfb\x95\x7e\x9d\xdf\xe8\xb7\xfa\x9d\xfe\x74\x7f\xb6\x3f\xdf\x5f\xe4\x2f\xf5\x9f\xf7\x5f\xf0\x57\xf9\x6b\xfd\x0d\xfe\x66\x7f\xab\xbf\xcd\xdf\xe1\xbf\xee\xef\xf6\xdf\xf2\xf7\x03\x41\x76\xa1\x6e\xd4\x1a\xea\x19\x75\x31\xbf\xad\x8e\x7a\x46\xe8\x9b\x0a\x64\x3b\xfa\xe5\x66\xf4\xed\x31\xe6\xb9\x3e\xc5\x67\x7e\x9d\x9a\x79\x6e\x84\x64\x98\x5f\xd3\xaf\xc0\xf4\x54\x1c\x8f\x50\x1e\xd4\x81\x02\x84\x33\xbf\x4d\xfe\xf7\x08\x41\xdd\x31\xf2\xef\xd1\x6f\x48\x7f\x81\x91\xa7\x29\xf1\x05\x84\x28\x11\x7f\x05\x51\xe5\x41\x21\x10\xe4\x68\x70\x3c\xe4\x28\xd2\x83\xbe\x9f\x4a\x75\x20\x84\xf9\x95\xeb\x7f\x8f\xba\x7b\xe8\x2a\xea\xdf\x23\x84\x87\xee\x75\x0e\x21\x3c\x84\xe8\x11\x92\x8d\x10\x3d\xf3\x7b\xd5\xd8\xdc\x1b\x0e\xcb\x90\xd7\x3f\xe8\x04\x82\xec\xc1\x64\x7a\xb0\xbb\xaf\x05\xef\x4e\x7a\x31\x19\xe6\x57\xe1\x7f\x8e\xcd\xf4\xe7\x08\xf9\x32\x36\x8b\x2f\xa3\x7b\xfd\x31\x7a\x82\x82\xae\xa5\xfe\x38\x68\x43\x56\x3d\x66\x55\x3f\x86\x30\xf7\xfa\x2c\xd3\xe3\x43\xc8\x67\x11\xe2\x64\x8d\xd0\xd6\xa0\x29\xe9\x44\x48\x0b\xbb\xee\x8d\x7d\x5a\x10\xa2\x41\x32\x95\x48\x46\xc3\x20\xa8\xa7\x9c\x11\x5c\x77\xd2\x8f\xe9\x41\xf7\x22\x66\x90\x1e\xf4\xad\x5f\x62\x26\xa8\x87\x95\x81\x64\xda\x0f\xa4\xc8\x86\xb4\xcc\x70\xd0\x86\x04\x97\x6d\x7b\xb3\x82\xdc\xa3\x08\xba\xca\x89\xae\x7a\x84\xae\x72\x06\x64\xba\x43\xaf\xa2\xfe\x84\xbe\x0b\x7b\x10\x8d\xea\x4f\x98\xf5\x42\x77\x2f\x41\x77\x6f\xc0\x10\x35\x86\xb4\x60\x32\x2d\xe8\x5e\xde\xc3\x63\x26\x56\x90\x4e\x3d\x4d\x89\x15\x74\xf7\xe7\x08\x29\x42\xc8\x73\xc6\x0f\x23\x9e\x02\x41\x4e\x06\x65\x42\x35\x23\x84\x8b\xae\x5a\x43\x08\x33\x66\x13\x1a\xb3\x00\xe1\xa6\xe3\x65\x42\x11\x34\x9e\x17\xc1\xd5\x21\x5e\x20\x99\x2e\x4e\xcf\x1b\x8f\xea\x3a\x05\xd2\x70\x02\xc4\x19\x8a\xb0\xda\xd0\xde\xe9\x46\x7e\x58\x76\x34\x02\x20\x1b\x56\xd0\xf7\x0a\xdd\xef\x27\x42\x1a\x42\x11\xe2\x0b\xb4\x4c\xc8\x7e\x67\x90\xa1\x23\xc8\x64\x08\xd2\x10\x8a\x1c\x8d\x48\x14\x8f\x96\x09\xdd\xef\xb4\x1e\x7c\xbf\x9f\x10\x69\xf8\x70\xe4\x48\x24\xf9\x39\xd2\x83\xef\xf7\x93\x21\x0d\x87\x10\x64\xc3\x90\x08\x10\x88\x51\xac\xf5\xe0\xef\xeb\xd3\x3b\x85\xa5\x8e\x18\x7b\x23\xe3\x64\xfb\xe8\xdd\x84\x64\x9c\xa7\x40\x94\xc8\x0f\x83\x88\x17\x21\x8c\x8c\x37\x10\x7f\x06\xe9\xdd\x1d\xd1\xfa\x26\xd2\x22\x2f\x65\xfb\x18\x8f\x3d\x1a\x5b\x90\xb7\xf8\xb1\x7b\xf9\x03\x7a\x4e\x82\x28\x43\x11\x82\x4b\xcb\x90\x5c\x1a\x79\x13\x49\x68\x64\xe8\x43\x10\x65\x28\x42\x6a\x68\x19\x96\x10\x69\xbe\x1e\x88\x90\xbe\x37\x56\x6d\x09\xd8\xd9\x87\x22\x49\xd0\xce\xff\x50\x44\x79\x18\x39\x1a\xa3\x8e\xdc\xfd\x64\x88\xf2\x10\xc2\x43\x36\x64\x56\x90\x87\x2c\x8f\x22\x7f\x48\xf4\x3b\x2a\xd3\xc5\xe1\x02\xc1\x32\x62\x31\xc1\x4f\xc7\xba\x90\xb5\x60\xe2\x46\x88\x0c\x1d\xc3\x43\x65\xf0\x5a\xe2\x20\x1b\xcb\x20\x48\xe6\xa0\x11\xfd\xba\x44\xcf\x9b\x1a\x80\x1f\x58\x0b\x5a\xcf\x3c\x92\x41\x99\x88\x92\x63\x32\xf2\x80\x1f\xd2\x32\xc3\x41\x3f\x0c\xec\x41\xc0\x76\x1c\x53\x6f\x30\x32\x15\x61\xf4\xf8\xb1\x7b\x31\x63\x1e\x42\xfb\x0b\xaf\x64\x50\x1e\x0c\xec\xc1\xf6\x30\xd5\x0e\x93\x2b\xb1\x1a\x89\xac\xa0\x6d\x18\x12\xeb\x4a\x31\x1b\x96\x1e\x1f\xfd\xc8\x52\x6c\x3c\x8c\x4c\x03\x26\xf3\x7a\x77\x07\x65\x8e\xa9\xac\x8e\xb7\x33\x59\x8d\xe6\xa5\x46\x32\xd5\x98\x9e\x35\xcc\x3e\x45\x98\x7d\x8a\x82\x32\xac\x0c\x46\x86\xf6\x0d\xaa\x12\xb3\x73\x65\x18\x99\x5a\x4c\xa6\x16\xc9\x54\x63\x32\xd5\x48\x26\xa4\xf6\x63\xc6\xcc\x3e\xff\x46\xc6\x8f\xfc\xf0\xef\xb1\x78\xf8\xf7\x01\x6b\x0c\xa1\x6f\x12\xfb\xde\x58\xe3\x48\xc5\x78\x4c\xbd\xf1\x05\x3a\xa3\x31\x31\x39\x90\x2f\x50\xbd\x41\xce\x61\x31\xe1\x0b\x68\xbd\x42\x64\x50\x7e\x0f\x95\x69\xf8\x70\x3d\x78\xbd\x4a\xcf\xeb\x50\x6d\x93\xfd\x26\x5b\xe1\x39\x0e\x65\x7c\xe2\x0a\x16\x91\x98\x4a\xcf\x18\x58\xd3\x46\xf4\x3d\x78\x7a\xbd\x9a\xd8\xcc\xb7\xe1\xe9\xaa\x40\x89\xf2\xe0\x5c\xa0\x12\x6e\x7c\x33\x9e\x06\x46\x0f\xb2\x61\x48\x6d\x8c\xec\x1c\x52\x59\x31\x08\xf2\x16\x3c\xf2\xfb\x51\xa6\xc6\xea\x67\x82\xcb\x99\x44\x19\xb6\xee\xcd\x08\x43\x6a\xec\xc0\x4c\xeb\x42\x67\x7a\xb4\x0e\x67\x64\x98\x9c\x75\x9c\x9e\xa0\x0c\xb1\x7d\x02\x19\xbc\x1a\xe4\x21\x6f\xc1\xf2\x3b\xd9\x80\xbc\x0e\xcb\x8c\xa1\x35\x3f\x1a\xe1\xeb\x8a\x11\xc9\xd0\xc8\x49\xf4\x90\xbf\x40\x57\x8d\x20\xe4\x17\xc7\x68\x6e\x3c\xa2\x59\x8a\x62\x14\xf7\xf0\xf9\x82\xf6\x31\x3c\x17\x1c\xad\x25\x02\x77\x0f\x95\xe9\x39\x56\xa6\x2a\x28\xc3\xc4\x22\xf6\x0a\x53\x1b\xa0\xab\x1e\xa1\xbc\xbc\x4d\xcb\x50\x8f\xd0\x55\x3d\x58\x7d\x88\x4e\x2e\xc4\x0a\xf2\x31\x0f\xf2\x1f\xa6\xa6\x0d\x39\xdd\xa0\x55\x7e\x5d\x1b\xaf\x23\xaf\xa3\x6d\xd8\x8e\xe9\x69\xc7\xf4\x34\x61\x7a\xfc\x58\xed\xc7\xac\xe0\x73\x24\x83\x62\x14\x53\x51\x1f\x23\xf3\x0a\xc9\xf4\x22\x99\x57\x70\xe4\x6c\x85\x76\xc1\xeb\xca\x1c\xe9\x61\xaa\x0b\x2c\xd6\x31\x7a\xb6\x91\x9e\x01\x24\xb3\x0d\x47\x4e\x64\xcc\x6e\x0a\xd4\xf3\xb4\xcc\x20\x73\x2e\xc0\xe6\x85\xb2\x0c\x23\x13\x98\xfb\xca\x51\x3d\x00\x87\xf4\xac\x04\xaa\x38\xe7\xa1\x2a\xae\x05\xf3\xa8\x96\x80\x0c\xf7\xb0\x0c\xf2\x8d\x50\x99\xc3\xd5\xe0\x71\x7a\xe6\x90\xcc\x20\x26\x33\x43\xcb\xa0\x0a\xad\x25\x4c\x9d\x79\x8c\x1e\x2c\xae\xfe\x1c\xad\x72\x0b\xe6\xcf\x2d\x68\xa7\xfc\x31\xad\x07\x3f\x9f\x52\x26\x5a\x0f\x5b\x80\x7c\xcc\x14\x5c\xd3\x90\xf3\x29\x17\xcb\x3b\xdc\xc0\x7a\x35\x1c\x3e\xc3\xa2\xab\xb0\x33\x2c\xf1\x02\xf3\x96\x17\x01\x19\xe7\xb1\x32\x95\x21\x32\xc7\xeb\xe9\x0a\xca\x10\x13\x28\x22\x21\x3f\x27\x26\x82\xd6\xc0\x4f\xc7\xc7\x74\x3c\x5a\x10\xa2\x0e\xca\x30\x39\x2e\xe0\x99\xd5\xc1\x3a\x81\x79\xef\x25\x50\x27\x30\x9a\xe7\xb1\xab\xb8\x58\x9c\x67\x62\x1d\x8a\xe7\x11\xe8\x2f\x77\x90\x73\x8c\xf7\x22\xcb\x2f\x04\x2b\xa2\x63\x4e\x37\x45\xe8\xaa\x1b\x58\xee\x66\xfa\x36\x42\xac\x26\x69\x47\xab\x6c\xc4\x10\x14\x37\x02\x23\x64\x22\x9b\x98\xa9\x9a\x10\x22\x46\x08\x3a\x55\xb1\x16\x10\x32\x19\x9c\x7b\xe0\xaa\xd7\xb5\x71\x70\x57\x06\x62\x1d\x42\x7a\x03\xf9\xeb\x0d\xc2\xae\xc3\xa2\x96\x13\x69\xae\x0a\xee\x65\x26\x2b\x05\x4e\x9a\x8f\x98\xdd\x84\xb2\x27\xba\x8a\xb8\x12\xc8\xb0\xb6\xd0\xec\x19\xc8\x71\x53\xec\x60\xff\xc7\x89\xd9\xd9\x09\xc7\xf7\x1c\x56\x82\x7a\x18\xab\x32\xab\xc9\x61\xce\x53\xea\xa3\x51\x1d\xe0\xf8\xa8\xce\x66\x1d\x7b\xfa\xdb\xc7\xe3\x33\x96\x2f\x98\x18\x8e\x6c\xc5\x61\x2c\xb9\xc6\x5c\x45\xcb\x44\xb4\xa2\xbd\xa3\xc7\xbc\xae\x2d\xc4\xeb\x6c\x6f\xa2\x4d\x4b\xa0\x9e\x0f\xc6\x9f\x16\xcc\xaa\x19\xd8\xdc\x99\x08\xf9\x75\x2c\xd2\x3a\x31\xef\x65\x64\x6c\x28\x9f\x22\xcb\x13\xe7\x8f\xc4\xc3\x6e\x74\xaf\x6a\x74\xd5\xa5\xa0\x87\x13\xdd\x68\xef\x30\xe7\xee\xee\xe3\xe3\x2a\x13\x49\xd8\x46\x3c\xda\xa0\x99\x5a\x82\xd1\x86\x42\xef\x96\x47\x2c\xa1\x99\xc6\x23\x99\x2f\x63\xbe\xf1\xe5\x60\xe4\x7f\xed\x2d\xf0\xa6\x4f\x12\xc8\x8c\x4c\x24\x39\xd2\xfb\x7a\xd3\x39\x09\xc6\x04\x0d\xe6\xab\x9a\xc0\xce\x0d\x8e\x99\xd9\xb9\x66\x24\xb3\x88\x10\x33\xd2\x33\x8d\xf4\xa4\x21\x3d\xd3\xcc\x78\x10\xf2\xc7\xc1\x7a\x95\x4b\xd2\xd1\x86\x97\x4e\xaf\x11\x97\xa4\x65\x38\x93\x74\xa5\x1a\x89\xf2\x32\x07\xed\x1d\xf6\x0f\x68\x84\xb3\x47\x23\xec\x1f\xd0\x48\x04\xfa\x7e\x24\xe7\x6f\x91\x05\x0a\x0f\x9a\x90\x2f\x29\x81\x60\x37\xd2\x32\x11\xd9\x01\x1f\xa3\x4f\xbe\xe5\x8c\x6f\xd0\x08\x07\xad\x6f\xa4\x1d\x5d\x9b\x41\x5f\xc5\xd1\xd0\x32\x1c\x3f\xba\x17\x3a\x65\xb3\x59\x48\x0f\xa0\x7b\xb1\x02\x27\x3b\x3a\x1e\x76\xb2\xf1\x53\x5b\xf0\xf4\xe7\x87\x60\x77\xe5\x5f\xb1\xf1\x2a\x97\xae\xb7\x4b\x83\xd5\x69\xa0\x02\x91\x86\x54\x20\xbe\x37\xa7\x92\x06\x2c\xcb\x84\xac\x3b\x76\x2f\xc6\x57\xc5\xd8\x39\x05\xf9\x21\xb5\x45\xe7\xc1\xc0\xbe\xd8\x42\xc8\x7b\xb4\x1f\xb2\xa3\xd0\xdc\xdf\x43\x48\x1a\xb6\xe3\xd2\xe0\x4d\x87\x81\xc5\x0e\xe4\x26\xda\x62\x9f\xc5\x6a\xa4\xcf\x06\x47\x18\x90\x69\x60\x6a\x63\x64\x8d\x05\x2c\x6e\x94\xd2\x55\x6e\x20\x6a\x95\x62\x7b\x39\x30\x53\xa6\x9f\x89\x8d\x19\xaf\xeb\x42\x64\x50\x9d\x30\x8c\xdd\xcb\x8c\xee\xf5\x79\xcc\xa3\xfe\x12\x59\x63\x13\x59\xf5\x2f\xd1\x8e\x63\xec\x8c\x55\xef\x9c\x5d\x5a\x9e\x97\x8c\x56\x79\x97\xf1\x28\xfa\xee\x91\x99\x98\x47\xcd\xd1\x08\x67\x15\xad\x32\xca\x17\x94\x07\xdd\x0b\x5d\x1b\xe8\xab\x6b\xb0\xb9\x33\x71\x03\x65\x10\xce\x2c\x42\x16\xb1\x38\xcf\x66\xe2\x3c\x9a\x17\x53\x09\xab\xf0\xe8\x87\xc6\x7c\x1f\x5b\x65\xc6\xa3\xd8\x28\x96\x76\x05\x32\x9a\x2f\xb8\x2f\x20\xd8\x2b\x60\xb3\x0f\xf7\x0a\xc6\x31\x19\xa6\xaf\x35\xc5\xc4\xe4\x40\x8c\xa2\xf5\xfc\x21\x7e\xce\x45\x7a\x98\x38\x8f\x9f\x7c\x07\x82\x32\x01\xef\xed\x41\xd1\x1e\xf7\xde\x9e\xc3\xe7\xb8\x40\xc6\xc7\xcf\x71\x98\x0c\xb9\x1b\xf0\x1f\xdb\x1b\x0f\xc7\x7b\x05\x6f\xad\xd5\x5f\xfb\x06\x83\xa0\x79\xcd\x22\xfd\x43\x81\x7a\x83\x9e\x17\x1f\xdd\x8b\xa9\x37\x7a\xd0\xbc\x66\x83\xd9\x3c\x50\x3f\xf3\xb1\x1a\x72\x12\x8d\xc7\x82\xf4\x30\xbb\xa9\x14\xe9\xd9\x3a\x52\x1f\x5a\x0e\xd7\x75\x21\x32\x4c\x7c\xbe\x13\x88\xcf\xb9\x6f\xe2\x3c\x73\xaf\xc7\x34\x42\x1a\xd0\x8c\x2a\x91\x8c\x01\x8d\x67\x0c\xf5\x8b\xee\x22\x99\x31\xec\x6c\xce\xdc\x8b\x39\x77\x8f\x62\xd5\x3b\xb3\x9b\x50\x4c\x63\xa1\xf8\x4f\xfe\x2d\xbc\xe9\x93\x04\x64\x18\x3f\xfc\x23\x2c\x53\xff\x11\x04\xcf\xef\xef\x60\x35\x09\x13\xd5\xbf\xc9\x44\x75\x3a\xd6\x05\xa2\x7a\xa0\x1a\xa4\x91\x63\x7c\xac\x00\xc5\x4c\x66\x2d\x0a\x82\xde\x12\x38\x0b\x57\x30\x95\x27\xb6\x97\xab\x03\x7b\xf9\xe8\x9a\x2a\x0f\xad\xa9\x1f\xab\xd5\x03\x99\x08\xed\xf7\xf9\x60\x26\x0a\x9c\x4f\x7d\xc8\xc7\x1a\x3e\x58\x78\x13\x37\x02\xfe\x43\x23\x8c\xe5\x89\x19\x44\xaf\x20\xe4\x75\x1f\x60\xe4\x75\x04\xa0\x7e\x82\xba\x4f\xaf\xd0\x78\x7e\x82\xbc\xee\x27\xe8\x1c\x87\xa2\x3a\xf5\x13\x26\xaa\xa3\x4f\xff\x35\x33\xf7\x0f\x3a\x5f\x57\x0e\x11\x5f\x65\x2a\x07\x1a\x61\x4e\xd3\x4c\xee\x26\xb6\x91\xc5\x8e\x9c\xa9\x19\xdf\x08\x44\x6c\xef\x07\xfd\xc7\x9d\xad\x42\xf3\x29\x42\x98\x6a\x6d\x3e\x58\x03\x10\xdd\xc8\x5b\x16\x99\xca\x01\x69\xae\xc1\x72\xee\xe4\xd1\xf3\x05\x42\x1a\xb1\x2c\xdc\x88\xad\x17\xe3\x3f\x15\xe8\x59\x1b\xca\xdd\x81\x28\xaa\x41\x9e\x80\x9e\x06\x32\x5d\x11\x42\x89\x10\xd4\xdd\x0d\x58\x9e\xa9\x0a\x96\xd1\xbd\x98\xbf\x01\xb1\x1c\xcc\x17\x81\x7d\xc1\xd4\x00\x3d\x98\x6f\x04\xf6\x20\x9a\x45\x05\x7e\x86\xc5\xc6\x8c\x55\x20\xf8\xba\x93\x15\x18\x12\x88\x63\x81\xa7\x4b\xc1\x58\xd7\x12\x78\xbe\x83\x77\x6e\x6d\xa1\x08\x81\x9e\x6a\x05\x3a\x4b\x83\xd8\x98\x2f\x63\x63\xd6\x30\x5d\x35\xf6\x9b\xfa\x39\x60\x9f\x7e\x6c\x84\xcc\x55\xc3\xf8\x55\xc7\x23\x11\x35\x41\x84\x38\xc0\xce\xf8\x07\x4c\xd4\x42\xe3\xd9\x0d\x46\x2d\x06\x61\xb5\x61\x71\xcc\x8f\xcd\x3d\xd0\xa5\xc1\xfb\x5a\x47\x46\xc8\x3c\x0b\xd0\x60\xf6\xd1\x1c\xd9\x95\x81\xf3\x7b\x50\x33\xb1\x8d\xbc\xee\x20\x68\x43\x66\x84\x87\xce\xa7\xd2\x37\xd1\x18\xaf\x49\x42\x90\xc0\x3e\x65\x1d\x3a\x17\xb0\xd0\x98\xcf\x23\xcd\x2c\x84\xfc\xbf\xe4\xbd\x79\x7c\x14\x55\xf6\x07\x7a\x6e\xdd\xdb\xd5\xdd\x21\x09\xe9\x2c\x84\xb0\x24\x9d\x84\x04\x24\x81\x40\xc2\x22\x88\x18\x11\x59\x15\x21\xa2\x04\x04\x44\xb6\x41\x5c\x40\x44\x71\x41\x44\x76\x10\x1d\x44\x54\x04\xdc\x00\x01\x71\x99\xea\x04\x10\x6b\x50\x16\xcb\x65\x10\xcb\x51\x14\xcb\x41\x1d\x2d\x84\x4c\xc6\x1a\x75\x5c\x6a\x1c\x94\x9c\xf7\xb9\xb7\xaa\x3b\xd5\x9d\xa0\xce\xcc\xef\xf3\xde\x1f\x8f\xfe\x7c\xbb\x2a\xd5\xb7\xaa\xce\x3d\xf7\xdc\xb3\xdd\x53\xc5\x60\x67\xe5\x54\x1c\x19\x2c\x8e\x2c\x16\xf6\x45\x64\x57\xc8\xe2\xb3\x1c\x69\xba\xa6\xb9\xc3\x89\xbf\xc4\xdd\x77\x88\xd9\xed\xac\x60\x1e\x11\x73\x59\xac\x60\x9e\xf5\xc8\xde\xc6\x23\x4d\x63\x90\x66\x8e\x2c\xf7\x1c\x59\xde\x78\x96\x2b\x63\x8e\xfd\x72\x56\x6a\xc4\xe8\x38\xb9\xdc\xa6\x31\x88\x74\x4a\xd0\xec\xf8\x48\xa7\x9c\xf9\x2e\xb8\xb1\xae\x71\x76\x93\x35\x8e\xf5\x6c\xa2\x01\xd6\x35\xc6\x0e\x71\x59\xa3\xcf\xce\x72\xc4\x91\xf9\x1d\x8d\x32\x4f\x46\x8b\xb1\x10\x39\x2b\x27\x2a\x89\xad\x65\x37\xe6\x2a\x9b\xcc\xb8\x66\xb4\x96\x13\xa7\x38\x31\xe3\x9a\xe6\x8f\xc0\xc7\xe2\x5e\x95\xfc\x2c\xf8\xd8\xd3\x66\xa0\xe7\xac\x4a\xa1\xab\x3f\x13\xdf\x95\x90\x98\xed\x99\xef\x44\x64\x5e\x39\xf4\x8c\xd7\x4c\x8f\x1c\x56\x7b\x22\x97\x6a\x8f\x84\xf7\x68\xcc\x50\x39\x2b\xc5\xee\x58\xb8\x2b\xc5\xc2\x32\x3a\xb6\xd2\x91\xd5\x93\xe2\x2c\x27\x3f\x76\xb2\x69\xbc\xd3\x54\x63\xe3\x95\xb1\x23\xb3\x9b\xb4\x99\x1d\xa7\xd5\x67\xc4\x72\xdd\xce\x98\x1e\xf1\x1c\x39\xe2\x8c\x8e\x27\xfa\x1b\xdd\x54\x47\x35\x1f\x1d\x37\x33\x82\xed\x1a\x29\x74\xf5\x8f\xe0\x86\x2f\xd3\xc3\xb1\xd5\x1e\x2d\xb1\xda\x9d\x5f\x2c\x7e\x7e\x91\x23\x1e\xaf\xe0\x88\x47\xc6\xbc\x7e\x94\xa3\x7f\xac\x46\x9d\xf9\x5b\x7a\xea\x13\x77\x77\x62\x2b\xdf\xea\xa6\x47\xf8\x75\xe2\x8f\x70\x3e\xd3\x9f\x1b\xf5\x2a\xfd\xd9\xf5\xeb\x62\x99\x13\x47\xe6\x99\x22\xda\xbc\xc9\xdb\x30\x85\xb7\x61\x13\xc4\x91\x5d\xe2\xc8\x04\x27\x96\x69\xcc\x1e\x38\xb1\x0c\xf5\x8b\x23\x73\xc5\x11\xbf\xe8\x57\xb0\xd1\x0a\x4b\x41\x71\x64\xbc\xe7\x88\xb3\x52\x13\xa7\x13\x9a\x6a\x09\x4f\xb5\xc6\x12\x8f\xf7\xe5\xad\x03\xb9\x15\x9a\xad\xfa\x88\x55\x62\x9c\x45\x47\x35\xaf\xb5\xe2\x35\x80\xc7\xea\xed\xf3\x68\x80\xb8\xb9\xdc\x74\xc6\x35\x95\x79\x8f\x25\x7a\xd7\x63\x0b\xd2\x3d\xde\x4e\xba\xb4\x2e\x26\x75\xaf\x7b\x64\xf5\x6f\x22\x7b\x39\x47\x8e\xe5\x64\x9a\xae\xcb\xc4\x1d\x39\x4b\xbf\xa4\xc9\x9e\xd9\x3d\xd9\x63\x9b\x16\x78\x75\x82\x97\xcf\xc2\x1f\x8b\xe3\xb3\xf0\x64\xbc\x7c\xae\x74\xda\x78\x66\xc1\xf5\x4d\xeb\x64\x5c\xff\xc7\xbb\x0a\x33\x3b\x71\x74\x1a\xd6\x37\xa1\x79\xf6\xaf\x8f\x8e\xb8\x72\xbc\x5e\xe5\x47\x26\x08\x0d\x20\xb2\x49\x44\xc8\x6a\x82\x47\x34\x3b\xd1\xdf\xf0\x78\xef\xe3\x3d\xde\x7b\xfc\x7a\xe5\xfa\x58\x4f\xa3\xf4\xac\x8f\xf1\xe7\x27\x39\x96\x63\x8c\x3b\x4b\x70\xcc\xbd\xfb\x10\xf7\x3a\xb3\xa3\x5e\x8a\x4b\xf3\x67\x0d\x43\x62\x6d\x9c\xb3\xaa\xf9\x95\x13\x2c\xf5\x90\xa8\xfd\x72\xfb\xbe\x46\x1c\x99\xef\xe9\xe9\x7c\x71\x9d\x78\x7f\x63\x76\x4c\xff\x8c\x77\xf5\xcf\x90\xc4\x15\xf0\x33\x76\x62\x4f\xc5\x91\xd5\x9e\x0a\x9c\xd5\xae\x37\x98\x58\x9d\xb5\xca\xe3\x1b\xaf\x12\xdc\x70\xda\x6c\x76\xa5\x65\xfd\x59\xda\x8c\x4e\x68\xb3\x4f\xdc\xcb\xf2\xf8\xe1\x5e\xa9\x6b\x26\xb7\xec\xe1\xbc\xdb\x46\x1c\xf9\xcf\xdb\xf4\x6f\xd2\xa6\x7f\x93\x36\x89\xb3\x40\x48\x4b\xc2\xea\x76\x53\x69\xf9\xad\x6d\x26\x7b\x56\xd2\x9d\xec\xe5\x5f\x45\xc4\xea\xcc\xaf\xbf\x82\xb3\x02\x1e\x48\x58\x01\xaf\x12\xab\x30\xce\x8c\xab\x72\x23\xdf\xeb\x9b\xac\x4a\x5f\x1f\xbf\xe2\x1c\xbf\x2a\xed\xcc\x38\xef\xaa\xb4\x38\x72\x96\xeb\x78\xab\x0d\x13\xae\xd3\xa4\x9a\xce\xa1\xe7\xd7\xef\x95\xb0\x2a\x3d\xbb\x89\xf5\x9c\x1d\xcb\x86\x79\xab\x28\xbb\xf9\xf7\x89\x2c\x71\x65\xcc\x52\xc7\xaf\x26\xaf\x6f\xa2\x7f\xd6\xff\xc6\x36\xf1\x6b\xc7\xeb\x9b\x68\x2d\x7e\xa4\x40\xac\xc8\x2f\x71\xc7\x54\xb4\xf1\x57\xc7\x2a\xc1\x02\x4d\xae\x53\xdd\xfc\x75\x12\xda\x34\xaf\x21\x9f\xe2\x7d\x8f\xab\x0e\x7d\x85\xf7\xda\xf5\xba\x5f\x11\x47\x9e\xe2\xa3\x13\xd7\xe6\x65\x61\x2f\xe6\x7b\x7c\xf5\xb8\x2a\x53\x7e\x77\x57\xf7\xce\x6f\xd4\xbd\x4d\xeb\xd0\x7e\x75\x9d\xba\xa9\xc6\x5e\xff\x5f\xb5\x69\xaa\xe7\x67\xc7\x32\x54\x5e\xa9\x8b\xab\x2c\x72\xa4\xae\x89\x64\xc6\xad\x18\x8a\x36\xeb\x3c\x6d\xa2\xab\xc9\xad\x13\x56\x4b\xe3\x57\x93\xd7\x37\x59\x4d\x5e\xff\x1b\xdb\x0c\xf4\xcc\xe5\xe8\x6a\x72\xeb\x78\x3f\x21\x6e\xa5\x58\x68\xa4\x04\xfb\xb5\xbe\xd9\x95\xe2\x63\x22\xab\xb6\xde\x7b\x9d\x40\x0f\xd1\xe6\x88\x67\x35\xf9\x7b\xde\xc6\xb7\x3a\xb6\x9a\xec\xac\x60\xb6\xf1\xdc\xcb\x59\xb9\x76\xee\xf5\x77\x71\xaf\xbe\x1e\xfe\x38\x2b\xc5\xa5\x5c\xc2\xa5\x7d\x22\x9a\xd8\x0b\x4d\x57\x4f\xf8\x75\x4a\x3d\xde\xce\x11\xe7\x3a\xff\x71\x9b\xd9\x09\x6d\xf6\x8a\x71\x8f\x5f\xe1\x5d\xdf\xc4\xa2\xad\x6f\xd2\x66\x76\x73\x56\xef\x37\xb5\xf9\x9d\xe8\xbb\xa7\xb6\x59\x0a\x78\x6a\x0b\x9d\x8c\x6b\x5c\xfd\xb3\xb8\x7b\xc0\x13\xb1\x8a\xb9\xdc\xec\x8a\x73\x65\xfc\x8a\xf3\x6f\x6c\x73\x7d\x93\x36\xad\xff\x9b\x36\xb2\xa7\x42\x5b\x50\x18\xad\xef\x15\x6d\x44\x2f\xaa\x3d\xab\xdb\x4e\x46\xa8\xbd\xa7\xef\xed\x01\x7e\x63\x9b\xa6\xab\xe4\x71\x3c\x74\xd6\xbf\x44\x1b\xef\xfa\x97\xe5\x91\x67\x0b\x20\x71\x8d\x4c\xc8\x4f\xbc\x3f\xb6\xfe\x37\xb6\x69\x6a\x65\x86\x39\xf2\x2c\xc7\x56\xd2\x69\x91\xbc\x95\x73\xc3\x37\xd5\x13\xc3\x6e\xe5\x34\xf3\x23\x2e\xcd\x85\xf2\x9a\x98\xa5\x2e\x14\x34\xeb\x9e\xfa\x5e\x5d\x9c\x15\x5f\x49\xb8\xbe\x59\x8f\xf1\xfe\x40\xb2\x68\xb3\xd5\xb3\xca\xb0\x97\xb7\xf1\x8d\x6c\x5c\x65\x88\xf3\x13\x9a\xbf\x4e\xb5\xe7\x3a\xd5\x67\xbb\x8e\x67\x2e\x47\xdb\x34\x56\x75\xba\xeb\x68\xfc\x3a\xd2\x42\x7e\x9d\xd8\x2a\xc3\x5e\x20\x52\x0f\x7e\x9d\x66\xab\xc5\xd6\x37\xb1\xcb\xeb\x13\x23\x68\x8f\x9e\x6f\xe3\xd1\xf3\x61\x7e\x2f\x5f\x3f\xc1\xdb\x68\xd6\x7a\xaf\xa8\x01\x1e\xd9\xb8\x1e\xf7\x5b\xe6\xbb\xb8\x4e\x7c\xf5\xc8\x5e\x51\x3d\x32\x32\xe6\x8b\x36\x57\xd1\x51\x99\x58\xd1\x21\x7b\x9e\x4a\x68\x66\x2e\x8b\x36\xfc\x5e\x6c\xa6\xb8\x57\xf4\x3a\x7b\x85\x6c\x8c\xfc\x85\xca\x90\x26\x32\xef\xe6\x9a\xc4\x2a\x98\x9b\x6d\xae\x66\x8d\xf5\xf3\x9e\xa7\x24\x7e\xb9\x7e\xac\x99\x7c\x78\x93\xa7\x3f\x12\x6c\x53\x63\x3e\xf3\x92\xc6\x28\xd2\xcd\x48\xbf\xef\x5a\xab\xc6\x38\xc5\xb3\xc6\xea\x50\xcb\x9c\x35\xb2\x3f\x03\x80\x04\xf9\xbf\xfa\x06\x96\xbb\x49\x09\xb9\x87\xdc\x43\xba\x88\xf7\xb0\x74\x15\xef\x61\xb9\x40\xbc\x87\xa5\x52\xbc\x87\xa5\x5a\xbc\x87\x65\xb6\x78\x0f\xcb\x42\xf1\x1e\x96\x45\xe2\x3d\x2c\xe0\xdb\xe6\x7b\x5e\x2a\xf3\x29\xbe\x97\xa4\xde\xbe\x57\x7c\x07\xa5\x0b\x7d\x9a\xef\xa8\x74\xb1\xef\x98\xef\x9f\xd2\x15\xbe\xd3\x32\x91\x6e\x92\x99\xdc\x5e\xba\x5d\x2e\x90\x2f\x94\x1e\x94\x2f\x92\x07\x49\xb5\xf2\x55\xf2\x24\xe9\x45\xf9\x3a\x79\x8e\xf4\xb2\xbc\x5c\x5e\x25\xbd\x26\x3f\x24\x6f\x92\xfe\xe4\xff\xca\xff\x95\xf4\x6e\xe0\xd2\xc0\xa5\xd2\x7b\x81\x89\x81\xa9\xd2\xd1\xc0\xac\xc0\x2c\xe9\x2f\x81\x39\x81\x39\xd2\x71\x90\xa0\x85\x74\x48\xfa\x18\x40\xfa\x54\x32\xa1\xad\x74\x52\xfa\x1b\x84\xa5\x2f\xa5\x1f\xa0\x83\xf4\x13\x25\x50\x46\x19\x4d\x83\x5e\x34\x9d\xe6\xc0\x45\xb4\x2d\x6d\x0f\xc3\x69\x11\xed\x0e\x23\x58\x0f\xd6\x1b\xae\xf2\x3d\xea\x7b\x1a\xae\x86\xeb\x01\x48\x0d\x00\xd7\x22\xe4\x15\x00\xa2\x01\x90\xc3\x00\xe4\xcf\x00\xdc\x2a\x93\x8f\x01\x78\xa4\x4f\xfe\x06\x40\xbe\x02\xe0\x56\x98\x9c\xe6\x6c\x04\x90\x64\x00\x29\x19\x40\x4a\x07\x90\x5a\x03\x48\xb9\x00\x52\x07\x00\xa9\xb3\xf0\x62\x25\xa9\x17\x48\x52\x3f\x90\xa4\x01\x20\x49\x43\x00\xa4\x11\x20\x49\xa3\x41\x92\xc6\x81\x24\x4d\x02\x49\x9a\x0e\x92\x74\x3d\x48\xd2\x1c\x90\xa4\xdb\x40\x92\x16\x80\x24\x2d\x01\x49\x5a\x05\x92\xb4\x06\x24\xe9\x61\x90\xa4\x4d\x20\x49\x9b\x41\x92\x76\x80\x24\xbd\x00\x92\xb4\x0b\x24\x49\x05\x49\x3a\x00\x92\xf4\x3a\x48\xd2\x11\x90\xa4\xf7\x40\x92\x0c\x90\xa4\x4f\x01\xa4\x2f\x00\xa4\xbf\x03\x48\xdf\x00\x48\x36\x80\xf4\x33\x00\x95\x40\xa2\x01\x00\x9a\x0a\x12\xcd\x04\x89\xb6\x01\x89\xcf\x5d\x5a\x0c\x40\x4b\x01\x68\x39\x48\xf4\x5c\x90\x68\x7f\x00\x3a\x10\x80\x0e\x03\xa0\x23\x41\xa2\x57\x82\x44\xc7\x83\x44\x27\x83\x44\x67\x00\xd0\x1b\x41\xa2\x73\x41\xa2\x77\x00\xd0\x85\x00\x74\x19\x00\x5d\x0d\x40\xd7\x02\xd0\xf5\x00\xf4\x71\x00\xba\x15\x80\xee\x04\xa0\x0a\x00\xdd\x03\x40\xf7\x01\xd0\x43\x00\xf4\x4d\x00\xaa\x03\xd0\xf7\x01\xe8\x5f\x00\xe8\x67\x00\xf4\x14\x00\xb5\x00\xe8\xb7\x20\xd1\x1f\x01\x68\x03\x00\x63\x00\x2c\x09\x80\xa5\x01\xb0\x56\x00\xac\x1d\x00\x2b\x00\x89\x75\x02\x60\x5d\x41\x62\x3d\x80\x9c\xb9\x97\xcb\xb4\xf3\x0d\x90\xb8\x0f\x22\xa6\x8a\xee\x33\x3d\xd6\x66\x5d\x63\x1b\x54\xbc\xed\xd9\x8a\xe8\x77\xfc\x75\x9c\x6f\xba\x24\xfe\x1b\xa7\xd3\x47\xf9\x3e\x9f\x5d\xcd\x7d\x8b\xb3\x32\xcf\xf6\x2b\xff\x3e\x73\xef\x2f\xfd\xfa\x5f\x7f\x4f\x05\x82\xd6\x59\xa9\x9a\xdb\xf8\x1d\xc7\x9f\x4b\xc4\xb7\xe6\x69\xa9\x45\xaf\xd6\x4c\xbf\x80\x2d\x68\xdc\x8f\xfb\x75\xc1\x2f\xfd\x1a\xd7\x72\x53\xf3\xe7\x92\xcf\xfe\xef\xbe\xa5\xbe\xfc\x9a\xce\xd3\x56\xd2\x65\x8d\xdf\x00\xcc\x6c\xfc\x8e\xeb\xd7\xaf\x7e\xa3\xe9\xa5\x96\xef\xb3\x62\xf1\xff\xc2\xa7\x40\x07\xd8\x00\xef\xc3\x5f\x48\x26\xe9\x4b\x86\x90\x5b\xc9\x5e\xf2\xad\xd4\x43\xd2\xe9\x6d\xd0\x1e\x5a\xa2\x06\x21\xd4\xa0\x00\x32\xa1\x03\x5a\xb0\x08\x2d\x58\x8c\x16\x2c\x41\x0b\x96\xa2\x05\xcb\xd0\x82\xe5\x68\xc1\x21\xb4\x40\x43\x0b\x5e\x47\x8b\xec\x43\xcb\xb7\x0d\x2d\xf9\x22\xb4\xe4\x8b\xd1\x92\x07\xa3\x25\x0f\x45\x4b\x1e\x8e\x96\x7c\x29\x5a\xf2\x65\x68\xc9\xa3\xd0\x92\x2f\x47\x4b\xbe\x02\x2d\x79\x0c\x5a\xf2\x58\xb4\xfc\x4f\xa2\xe6\xdf\x8a\x1a\xa4\x82\x0f\x3a\x41\x12\x74\x82\x64\x18\x04\x05\x30\x12\x2a\x61\x10\x5c\x0c\xb9\x30\x1c\x72\x61\x04\xe4\xc2\x65\x90\x0b\x93\x60\x10\xd4\x41\x2e\xd4\x43\x3f\xff\x13\xd0\xc9\xbf\x05\x3a\x01\x81\x2e\x50\xde\xe4\xfc\x41\xbf\x72\xfe\xa0\xd8\xf9\x41\x68\x89\x06\x84\xd0\xa0\xe7\xa1\x45\x07\xa2\x45\x07\xa3\x45\x47\xa0\x45\x1d\xfa\x0c\xff\x56\x34\x80\xd2\xe1\x68\xd3\x2a\xb4\x69\x35\x9a\xd0\x02\x5a\xe2\x02\x08\xe1\x02\x7a\x1e\xea\x74\x20\xea\x74\x30\xea\x74\x28\xda\x74\x04\xea\xfc\x3c\x7a\x83\x38\x77\x81\x7f\x2b\x2e\x80\x34\x68\x89\x3a\x84\x50\x8f\xbb\xc3\x50\x34\xc5\x5d\xae\x40\x9b\x5e\x89\x06\x1d\x83\x26\x1d\x8b\x36\x9d\x80\x26\xbd\x01\x6d\xba\x18\x4d\xff\x93\xa8\xfb\xb7\xa2\x0e\xa9\x90\x86\x3a\x9d\x88\x16\x9d\x82\x16\x9d\x8e\x16\xbd\x09\x2d\x3a\x07\x2d\x3a\x17\x2d\x7a\x0b\x5a\xf4\x56\xb4\xe8\x6d\x68\xd1\x05\x68\xf9\x1f\x45\xdd\xbf\x01\x75\xff\x46\xd4\xc5\xbd\x4d\x48\x43\x0b\x42\x68\x36\xb9\x42\xf4\xec\xc6\x33\x2d\xff\x06\xb4\xfc\x1b\x05\xf5\xa6\x7f\x2b\x9a\x50\x0c\x3e\x34\x21\x09\x4d\x5a\x8b\x26\x7d\x09\xca\xe9\x3e\x34\xe9\x51\x34\xa9\x81\x06\x3d\x8e\x26\xfd\x0e\x2d\xfa\x23\x5a\xf4\x27\xb4\x58\x3e\x1a\xac\x08\x4d\xd6\x11\x4d\x36\x0a\x4d\x56\x85\x16\x9b\x80\x26\x9b\x88\x16\xbb\x1a\x2d\x76\x0d\x5a\x6c\x1a\x9a\x6c\x3a\x5a\xec\x77\x68\xb0\x19\x68\xb1\x6b\xd1\x60\x33\xd1\x62\xf3\xd1\x60\x77\xa1\xc5\x9e\x46\x83\x6d\x43\x8b\xed\x46\x8b\xed\x41\x93\xbd\x88\x16\xdb\x8b\x26\xdb\x8f\x26\x3b\x80\x96\xff\x09\x34\xfd\x5b\xd0\x84\xce\xe0\x43\x05\x92\x50\xa1\xb5\xa8\xbb\x94\xe9\xf4\x28\x6e\xa3\x06\x6a\xf4\x38\xea\xf4\x3b\x34\x5c\xca\x0c\x96\x8f\x1a\x2b\x42\x95\x75\x44\x95\x8d\x42\x9d\x55\xa1\xc1\x26\xe0\x36\x36\x11\x0d\x76\x35\xea\xec\x1a\xd4\xd9\x34\xd4\xd9\x74\x34\xd8\xef\x50\x73\x29\xd3\x04\x65\x37\xa0\xc9\x6e\x44\x8b\xcd\x42\x93\xcd\x16\x94\x6a\x2e\xa5\x9a\x4b\xe9\x36\xb6\x07\x0d\xf6\x22\x6e\x63\x7b\xd1\x60\xfb\x51\x67\x07\xd0\xf0\x3f\x81\x8a\x7f\x0b\x2a\x50\x12\xe3\x21\xa7\xf2\x28\x5a\xf4\x03\xb4\x04\xff\xbe\x43\xd3\xa5\xd0\x64\xe9\x68\xbb\xfc\xb3\x58\x31\xda\xac\x23\x5a\xac\x13\xda\xac\x1b\xda\xac\x0a\x4d\x36\x01\x2d\x36\x11\x4d\xc1\xc7\x49\x68\x0b\x5e\x4e\x46\x9b\x4d\x47\xb3\x09\x2f\x9b\x52\xfc\xcb\xbc\x3d\x80\x66\x8c\xaf\x04\x52\xe0\x1c\x78\x17\xbe\x21\x40\x2f\xa6\x43\xe9\x68\x5a\x4d\x67\xd0\xdb\xd9\xc5\x6c\x0c\xd7\xc6\x83\xca\xb9\x0e\x21\x75\xd4\xa0\x86\x7f\xba\xff\xfa\xe0\x2a\xff\xf5\x41\x23\xe9\x70\x8b\x4d\x49\x87\x93\xcb\x93\xcf\x6d\xb1\x29\x35\x29\xe9\x70\xcb\x81\x49\x87\x5b\x1e\x4e\xff\x3e\x63\x7a\xc6\xf4\x16\x9b\x5a\xf5\xcb\x29\xf0\x4f\xcf\xd9\x9b\x73\xb8\x4d\x5a\xce\xe1\x36\x05\x39\x7b\xdb\xf4\xc8\xd9\xcb\xff\xce\x39\xdc\x56\x6e\x93\xd6\x6e\x7c\xbb\xf1\x6d\x7a\xb4\x1b\xef\x9f\x1e\x34\x1a\x3f\xc9\xe5\x2d\x36\x25\x97\x3b\x9f\xa4\xc3\xde\x4f\xfa\xf7\xce\xa7\x55\xbf\x96\x03\xc5\x75\xa2\x9f\xc3\xf1\x9f\x76\x8b\x72\x0e\xb7\x1b\xcf\x11\x34\x72\xf6\x46\xd1\x62\x93\xf3\x49\x3a\xdc\x6e\x1d\xa7\x39\xa7\x09\x78\x9b\x36\x3d\xda\xf4\x48\x4d\xe2\x9f\xf6\xb7\xf2\xef\x9c\xbd\xce\xbd\x93\xcb\xdb\xca\xfc\xd3\xf2\x70\x9b\x34\x07\x51\x6a\xf8\x27\x63\x7a\xbb\xf1\xad\xfa\x71\xe4\x14\xf0\x4f\x6e\x75\xee\x66\x7e\x4f\xde\x03\xde\x3a\xd7\xca\xcb\xcd\x9b\x9a\x77\xba\xdd\xa2\x5c\x2b\x9c\x1c\x7e\x3c\xd7\xca\x1f\x9d\x97\x9b\xbf\x8c\x1f\xcf\xdf\x14\x7e\x3c\x6f\x6a\xc1\x88\xfc\x65\x85\x23\xf3\x4e\xe7\x4d\x2d\xbc\x23\x67\x6f\xe1\xc2\xc2\x3b\x0a\x37\x14\x2a\x39\x7b\x3b\xac\x2d\x5c\xd8\x61\x6b\x87\x43\x85\x1b\x8a\xa0\x08\x8a\xda\x14\x41\x51\x69\xbb\x45\x45\x50\xdc\x35\x6f\x6a\x71\x65\xc7\x36\xe7\xac\xe9\x2c\x15\x57\xf2\x4f\xe7\xe4\xce\x1b\x4a\xde\x2f\x5d\x5b\x6a\x74\x6c\xd3\x45\xea\x9c\x5c\x6a\x74\x4e\xee\x92\xd9\x35\xe9\x9c\x35\x1d\xdb\x74\xde\xd0\x75\x4d\xe7\xe4\x2e\x52\x17\xd1\xb6\x4b\x66\x97\xcc\x9c\xbd\x65\x37\x96\xcd\xe5\xdc\xeb\x96\x54\x76\x63\xb7\xa4\x6e\x0b\xbb\x2d\x2c\x9b\xdb\xed\x74\xb7\x85\xdd\x92\xf8\xd1\xee\x9d\xba\x77\xe2\xc7\xc4\xfe\xeb\x65\x73\xf9\xdf\xdd\x5f\xef\x96\xd4\xed\x74\x97\xcc\x6e\xa7\xbb\x7f\xd6\xbd\xd3\x39\x6b\x4a\xde\x2f\x1f\xc7\x51\xd1\xad\xa2\x5b\xa9\x51\xd1\xb7\xdb\xc2\x2e\x99\xdd\x16\x76\xde\xd0\xed\x34\x07\xff\xf0\xbf\x5d\x9c\x3e\x67\x4d\x17\x29\x67\x2f\x3f\xb3\x6b\x52\xb7\x85\x1d\xdb\x94\xcd\xad\xd8\xd4\xf3\xab\x5e\x73\xcf\x3d\x76\xee\x37\x7d\x96\x95\x1a\x65\x37\xf2\x6d\xe7\xe4\x6e\x49\x51\xf0\xf6\x15\x9b\xca\xe6\xf6\xf9\xb9\xdf\xe3\xe7\xb3\x6e\x0b\x79\x4f\xca\xe6\x9e\xdf\xff\x82\x4b\x38\x78\x6b\xde\x82\xe3\x82\x3b\x2a\x3b\x54\xce\xc9\xd9\xcb\xc1\xcf\xac\x5c\x77\xd1\xa0\xe8\x6f\x1c\x25\xef\x3b\xe0\x9f\x28\x4d\xbc\x1d\xbf\x6b\xf7\xd7\x3d\x54\xc6\xf5\x80\x23\x4a\xa7\x43\x5b\x9f\x65\x17\x8d\x1f\x38\x91\x83\x5f\x35\xba\x3f\xd0\xb8\xb8\xd7\xc5\x4b\x06\x4e\x74\xee\xc9\xc7\x9d\xcb\x43\x14\x5e\x19\xfc\x2d\x68\x4e\x32\xbd\x48\x3a\x1c\x45\xf4\x93\x5b\x1d\xfd\xa4\x7f\x9f\xbb\x39\xfa\x71\xe4\xb1\x11\x79\xb9\xc1\x55\xfc\x23\x66\xf0\xf5\x1c\x79\xa7\xe1\x04\x74\x40\x15\x7a\x43\x26\xf4\x81\x4c\xe8\x0b\x99\xd0\x0f\x92\x60\x20\x1a\x30\x08\x35\x18\x8c\x1a\x0c\x41\x0d\x86\xa1\x09\x23\xd1\x84\x51\x68\x42\x15\x6a\x70\x39\x9a\x30\x1a\x35\xb8\x02\x4d\xb8\x12\x4d\xe0\xd6\x71\x11\xaa\xb0\x18\x55\x58\x82\x2a\x2c\x45\x15\x96\xa1\x0a\xcb\x51\x85\x27\x20\x09\x36\xa3\x06\x5b\xd0\x00\x6e\x53\x9f\x46\x03\xb6\xa1\x01\xdb\xd1\x80\x1d\x68\xc0\x33\xa8\xc1\x4e\xd4\xe0\x59\xd4\xe0\x39\xd4\xe0\x79\xd4\x60\x17\x6a\xb0\x1b\x35\xd8\x83\x1a\xbc\x88\x1a\xec\x45\x0d\x54\xd4\xe0\x8f\x68\xc2\x3e\x34\xe1\x65\x34\xe1\x15\x34\xe1\x10\xaa\xf0\x2a\x1a\xa0\xa1\x0a\xaf\xa1\x01\xaf\xa3\x0a\x6f\xa0\x01\x7f\x42\x0d\xde\x42\x0d\xde\x46\x0d\xde\x41\x0d\xde\x45\x0d\x8e\xa2\x06\x1f\xa0\x06\x1f\xa2\x06\x1f\xa1\x06\xc7\x51\x83\x4f\x50\x83\xbf\xa2\x09\x9f\xa3\x09\x27\xd0\x84\x93\x68\xc2\x69\x34\x89\x8c\x26\x09\xa0\x49\x52\xd0\x24\x2d\x51\x23\x21\xd4\x48\x06\x6a\x24\x0b\x35\x92\x8d\x26\xc9\x41\x93\xb4\x47\x93\xe4\xa3\x49\x3a\x40\x26\x29\x86\x4c\x52\x82\x26\xe9\x82\x26\x29\x43\x93\x74\x47\x93\x54\xa0\x49\x7a\xa2\x49\x7a\x41\x26\x39\x17\x92\x48\x5f\x48\x22\x53\x50\x23\x73\xd0\x24\xfb\x50\x25\x2f\xa3\x41\xf6\xa3\x41\x0e\xa2\x46\x8e\xa3\x49\x3e\x86\x4c\x7a\x1e\xaa\x74\x20\xaa\x74\x30\xaa\x74\x04\xaa\x74\x22\x1a\xf4\x6a\xb4\xe8\x24\x61\xc1\x0d\x3a\x1d\x4d\xfa\x3b\xb4\xe8\x0c\xb4\xe8\xb5\x68\xd1\xeb\xd1\xa2\x37\x0a\xab\x6e\xd0\x9b\xd1\xa4\x73\xd1\xa0\xb7\xa0\x41\x6f\x43\x83\x2e\x40\x83\xaa\xa8\xd1\x83\xa8\xd2\xd7\x50\xa3\x47\x50\xa3\x9f\xa3\x45\x4f\xa2\x4a\x4f\xa1\x46\x2d\x54\xe9\xd7\xa8\xd1\x6f\x51\xa3\x3f\xa0\xc6\x08\x6a\x4c\x42\x8d\xf9\x50\x63\x32\x9a\x2c\x09\x55\x96\x8d\x2a\x6b\x8d\x2a\x2b\x40\x9b\x75\x40\x8d\x75\x46\x8d\x95\xa2\xc6\xba\xa2\xc6\xca\x51\x63\xe3\x50\x63\xe3\x51\x63\xb7\xa2\xc6\xe6\xa1\xca\xee\x41\x95\x2d\x42\x8b\x2d\x46\x95\x2d\x41\x8b\x2d\x45\x95\x2d\x43\x8b\xad\x40\x8d\xad\x42\x8b\xad\x46\x8b\xad\x47\x8d\x6d\x40\x8d\x6d\x42\x8d\x45\x50\x65\x35\xa8\xb1\x5a\x54\xd9\x2e\xd4\xd8\x4b\xa8\x31\x15\x55\xf6\x0a\x6a\xec\x10\x6a\xec\x55\xd4\x98\x86\xaa\x6f\x1b\xaa\xbe\xed\x68\xf8\x4e\xa2\x29\x17\x43\xa6\xdc\x09\x32\xe5\xce\x90\x29\x5f\x84\xaa\x3c\x10\x0d\xf9\x62\x54\xe5\x41\x68\xc8\x83\x51\x95\x87\xa0\x21\x0f\x45\x55\x1e\x8e\xaa\x7c\x09\x1a\xf2\xa5\xa8\xca\x23\xd0\x90\x2f\x43\x55\x1e\x89\x86\x3c\x0a\x55\xb9\x0a\x0d\xf9\x72\x54\xe5\xd1\x68\xc8\x57\xa0\x2a\x5f\x89\x86\x3c\x06\x55\xb9\x1a\x0d\x79\x2c\xaa\xf2\x38\x34\xe4\xf1\xa8\xc9\x13\x51\x93\x27\xa1\x26\x4f\x46\x4d\x9e\x8e\x9a\x3c\x03\x35\x79\x26\x6a\xf2\x6c\xd4\xe4\x39\xa8\xc9\x73\x51\x93\x6f\x43\x4d\xbe\x03\x35\x79\x3e\x6a\xf2\x02\xd4\xe4\x85\xa8\xc9\x8b\x50\x93\x97\xa0\x26\x2f\x43\x4d\x5e\x81\xa6\xbc\x0a\x4d\x79\x35\x9a\xf2\xfd\x68\xca\x6b\xd0\x94\xd7\xa2\x29\xaf\x43\x53\x7e\x08\x92\xe4\x47\x20\x49\x7e\x14\x92\xe4\x8d\x90\x24\xbc\xda\x71\xb0\x1c\x8a\x51\x87\xce\xa8\x43\x39\xea\xd0\x03\x75\xe8\x8d\x2a\x9c\x8b\x16\xf4\x41\x0d\xfa\xa2\x06\xfd\x50\x83\x95\xa8\xc3\x3a\xd4\xe1\x21\xd4\xe1\x61\xd4\xe1\x11\xd4\x61\x3d\xea\xb0\x01\x75\xd8\x88\x16\x6c\x42\x0b\x1e\x43\x0b\x1e\x47\x0b\x9e\x40\x0d\xde\x44\x1d\x0e\xa3\x0e\x47\x50\x07\x1d\x75\xf8\x14\x75\xf8\x0c\x75\x30\x51\x87\x2f\x50\x27\xa9\xa8\x93\x34\xd4\x49\x3a\xea\x24\x13\x75\xd2\x01\x55\x52\x8c\x2a\xe9\x8c\x16\x29\x45\x8b\x74\x45\x8b\x74\x43\x8b\x94\xa3\x45\x7a\xa0\x45\x7a\xa1\x46\xce\x45\x8d\xf4\x45\x8d\x4c\x46\x9d\xdc\x84\x16\x39\x80\x3a\xf9\x18\x55\x3a\x1c\x0d\x5a\x85\x06\xbd\x12\x55\x3a\x06\x35\x5a\x8d\x3a\x1d\x87\x1a\x9d\x80\x1a\x9d\x89\x16\x5d\x8c\x1a\xad\x45\x95\xee\x46\x9d\xee\x43\x95\xbe\x83\x3a\x7d\x4f\x78\x71\x2a\xfd\x00\x0d\x6a\xa0\x42\x8f\xa3\x4a\xbf\x43\x9d\xfe\x88\x1a\xfd\x09\x75\x16\x42\x9d\xe5\xa3\xc2\x0a\x51\x67\x45\xa8\xb1\x8e\xa8\xb1\x73\x50\x67\x25\xa8\xb3\x2e\xa8\xb3\x32\xd4\x59\x77\xd4\xd9\x28\x54\x59\x15\xea\x6c\x2c\xea\xec\x2a\xd4\xd9\x04\x54\xd9\x44\xd4\xd9\xd5\xa8\xb1\x6b\x50\x63\xd3\x50\x65\xd3\x51\x67\xbf\x43\x85\xcd\x40\x8d\x5d\x8b\x0a\x9b\x89\x1a\xbb\x01\x35\x36\x0b\x35\x36\x1f\x15\x76\x17\x6a\xec\x11\xd4\xd9\xa3\xa8\xb3\x8d\xa8\xb3\xa7\x51\x61\xdb\x50\x63\xbb\x51\x63\x7b\x50\x67\x2f\xa2\xc6\xf6\xa2\xce\x5e\x46\x9d\xed\x47\x95\x1d\x40\x5d\x2e\x46\x4d\xee\x84\x9a\xdc\x19\x35\x79\x16\xea\xf2\x4d\xa8\xcb\x37\xa3\x2e\xdf\x82\xba\x3c\x0f\x75\xf9\x76\xd4\xe5\x3b\x51\x97\xef\x42\x5d\xbe\x1b\x75\xf9\x1e\xd4\xe5\xc5\xa8\xcb\x4b\x51\x97\x97\xa3\x25\xaf\x44\x4b\xbe\x17\x2d\xf9\x3e\xb4\xe4\xdf\xa3\x25\x3f\x80\x96\xfc\x20\x5a\xf2\x43\xa8\xc9\x8f\xa0\x26\x3f\x8a\x9a\xbc\x11\x35\xc8\x80\xde\x68\x90\x0e\x68\x90\x62\x34\xc8\xc7\x82\xcb\x06\xad\x45\x83\xee\x43\x83\x1e\x15\xde\xb9\x21\xbc\x73\xee\x99\x8f\x42\xc3\xf5\xc6\x0d\xe1\x8d\x4f\x43\x43\x78\xe1\xfb\xd1\xe0\x5e\x35\xf4\x03\x1f\xaa\x90\x84\x2a\x14\xa3\x05\x9d\xd1\x82\x2e\xb0\x08\xca\xd1\x82\x1e\x68\x09\xb9\xeb\x83\x06\xf4\x45\xc3\x95\x39\x0b\xd6\xa1\x05\x0f\xa1\x05\x0f\xa3\x05\x8f\xa0\x05\xeb\xd1\x82\x0d\x31\x19\xb3\xe0\x30\x5a\x70\x04\x2d\xd0\xd1\x82\x4f\xd1\x82\xcf\xd0\x02\x13\x2d\xf8\x02\x2d\x92\x8a\x16\x49\x43\x8b\xa4\xa3\x45\x32\xd1\x8a\xc9\x58\x2f\x34\x3c\xb2\xc4\xe5\xc8\xe2\x72\x24\x17\xa3\x21\x77\x42\x43\xee\x8c\x86\x3c\x0b\x2d\xf9\x26\xb4\xe4\x9b\xd1\x92\x6f\x41\x4b\x9e\x87\x96\x7c\x3b\x5a\xf2\x9d\x68\xc9\x77\xa1\x25\xdf\x8d\x96\x7c\x0f\x5a\xf2\x62\xb4\xe4\xa5\x4d\xf9\xe6\x7f\x02\x55\xff\x16\x54\xa1\x47\x34\xf2\x13\x51\x6e\x6f\x34\xa1\x0f\xda\xd0\x17\x6d\x38\x8f\xf3\x03\x6d\x38\x1f\xed\xb3\x46\xbf\x4f\xa0\x1d\x17\x01\x77\x40\x93\x14\x73\x2d\x8f\x36\x39\x17\x6d\xd2\x17\x6d\x72\x1e\xda\xe4\x7c\xb4\xc9\x05\x68\xf3\x08\x99\x7c\x8c\x26\xdd\x83\xb6\x88\x94\x8b\xd1\x96\x3b\xa1\x2d\x77\x46\xfb\x3f\x8d\x9a\xe5\x87\xd0\x96\x1f\x41\x5b\x7e\x14\x6d\x79\x23\xda\xb1\x28\xb5\x28\x36\x76\xd1\x71\xfb\xa5\x71\xfa\x4f\xc7\xc8\x1d\x8f\xff\x94\xff\x42\x97\xf5\x83\xb9\x22\xaf\xe0\x45\x28\x01\x05\x90\x19\x07\x3e\x2a\x5e\x2c\x4a\xc0\xe2\x04\x2c\x49\xc0\xd2\x04\x2c\x4b\xc0\xf2\x04\x1c\x4a\x80\x96\x80\xd7\xe3\x21\x46\xd4\x03\x3e\xaa\x5e\x88\x51\xf5\xe2\xe2\x04\x0c\x4e\xc0\xd0\x04\x0c\x4f\xc0\xa5\x09\xb8\x2c\x01\xa3\x12\x70\x79\x02\xae\x48\xc0\x98\x04\x8c\x8d\x87\xc8\xcd\x78\xb1\x35\x1e\x30\x22\x1a\x7f\x37\x91\xba\xde\x68\xc1\xb9\x68\x43\x1f\xb4\xa0\xaf\x98\x4b\xe6\x2f\x4a\xe2\x46\xb4\x61\x13\xda\xf0\x18\xda\xf0\x38\xda\xf0\x04\x9a\xff\x85\x06\xb1\x48\x31\x5a\xa4\x33\xda\xa4\x14\x6d\xd2\x15\x6d\xd2\x0d\x6d\x52\x8e\x36\xe9\x81\x36\xe9\x85\x16\x39\x17\x4d\xd2\x17\x4d\x21\xc9\x37\xa1\xed\x6a\x17\x3e\x17\x2d\xb9\x13\x5a\x72\xe7\xff\x5c\xba\xe5\xe5\x68\xcb\x2b\xd1\x96\xef\x45\x5b\xbe\x0f\x6d\xf9\xf7\x68\xcb\x0f\xa0\x2d\x3f\x88\xb6\xfc\x10\x9a\xf2\x23\x68\xca\x8f\xa2\x29\x6f\x14\x11\xb6\x93\x0f\xc8\x8f\xe6\x8f\xa0\x03\xea\x42\xdb\x38\x9a\x46\x87\xc5\xa8\xc3\x12\xd4\x61\x29\xea\xb0\x0c\x75\x58\x8e\x3a\x1c\x42\x1d\x34\xd4\xe1\x75\xd4\x13\x34\x8a\xee\xdb\x86\xba\x7c\x11\xea\xf2\xc5\xa8\xcb\x83\x51\x97\x87\xa2\x2e\x0f\x47\x5d\xbe\x14\x75\xf9\x32\xd4\xe5\x51\xa8\xcb\x97\xa3\x2e\x5f\x81\xba\x3c\x06\x75\x79\x2c\xea\xb1\xbc\xd4\x61\x31\x0b\xd3\x84\x0e\x8c\x66\xfb\xd4\xa6\x63\x09\x99\x30\x10\x15\x18\x84\x2a\x0c\x46\x15\x86\xa0\x0a\xc3\x50\x85\x91\xa8\xc3\x28\xd4\xa1\x0a\x55\xb8\x1c\x75\x18\x8d\x2a\x5c\x81\x3a\x5c\x89\x1a\x54\xa3\x0e\x63\xd1\x82\x71\x68\xc1\x55\x68\xc1\x78\xb4\x60\x02\x1a\x67\x8d\x0c\x7e\x49\x36\x36\xa3\x0a\x9c\x67\x5b\x51\x81\xa7\x51\x81\x6d\xa8\xc0\x76\x54\x60\x07\x2a\xf0\x0c\xaa\xb0\x13\x55\x78\x16\x55\x78\x0e\x55\x78\x1e\x55\xd8\x85\x2a\xec\x46\x15\xf6\xa0\x0a\x2f\xa2\x0a\x7b\x51\x05\x15\x55\xf8\x23\xea\xb0\x0f\x75\x78\x19\x75\x78\x05\x75\xd8\x2f\x66\x39\x8f\x1a\x14\x37\x6a\x50\xdc\xa8\x41\x11\xb2\xf7\x27\x54\x85\xfc\xbd\x85\xaa\x90\xc1\xb7\x51\x15\x72\xf8\x0e\xaa\xf0\x2e\xaa\x70\x14\x55\xf8\x00\x55\xf8\x10\x55\xf8\x08\x55\x38\x8e\x2a\x7c\x82\xaa\x90\xd3\xbf\xa2\x2a\x64\xf5\x73\x54\x85\xbc\x9e\x40\x95\xcb\x2c\x9c\x44\x15\x4e\xa3\x4e\x64\xd4\x49\x00\x75\x92\x22\xbc\x2d\x8b\xb4\x44\x55\xc8\x72\x08\x55\x21\xcf\x19\xa8\x0a\x99\xce\x42\x95\x64\xa3\x4e\x72\x50\x27\xed\x51\x23\xf9\xa8\x79\xa2\x0c\x9d\x74\x41\x9d\x94\xa1\x4e\xba\xa3\x4e\x2a\x50\x27\x3d\x51\x27\xbd\xd1\x22\xfd\xd0\x20\xfd\xd1\x20\x95\x68\x08\x59\x9f\x82\x2a\x99\x83\xba\x1b\x6d\x28\x64\x3f\x2a\x42\xf6\x0f\xa2\x4a\x8e\xa3\xc6\x23\x0e\xd7\xb3\x56\x7c\x27\x51\x97\x3b\xa2\x25\x9f\x23\xb4\x16\xf7\xaa\x15\xd7\xab\x56\x5c\xaf\x5a\xf1\x78\xd5\x8a\xeb\x55\x2b\xae\x57\xad\xb8\x5e\xb5\xe2\x7a\xd5\x8a\xeb\x55\x2b\xae\x57\xad\xb8\x5e\xb5\x22\x8f\x47\x55\x9e\x88\xaa\x3c\x09\x55\x79\x32\xaa\xf2\x74\x54\xe5\x19\xa8\xca\x33\x51\x15\x73\x70\x36\xaa\x62\x1e\xce\x41\x55\xcc\xc5\xb9\xa8\xc6\xe6\xe3\x6d\xa8\x8a\x39\x79\x07\xaa\x62\x5e\xce\x47\x55\xcc\xcd\x05\xa8\x8a\xf9\xb9\x10\x55\x31\x47\x17\xa1\x2a\xe6\xe9\x12\x54\xc5\x5c\x5d\x86\xaa\xbc\x02\x75\x79\x15\xea\xf2\x6a\xd4\xe5\xfb\x51\x97\xd7\xa0\x2e\xaf\x45\x5d\x5e\x87\xba\xbc\x5e\xe4\x40\x0d\xff\x06\x34\xfc\x1b\xd1\x88\x65\xa7\xdb\x41\x4b\x91\x41\xe5\x76\x88\xcf\x53\x1b\x16\xa3\x0d\x4b\xd0\x86\xa5\x68\xc3\x32\xb4\x61\xb9\xf0\x06\x6c\xd0\xd0\x86\xd7\xc5\xdc\xe4\x56\x9e\x5b\x76\x5b\xbe\x18\x6d\x79\x30\xda\xf2\x50\xb4\xe5\xe1\x68\xcb\x97\xa2\x2d\x5f\x86\xb6\x3c\x0a\x6d\xf9\x72\xb4\xe5\x2b\xd0\x96\xc7\xa0\x2d\x8f\x15\x96\xdc\xf2\x6f\x45\x0b\x76\x47\x73\xc6\xee\xbc\x34\xa0\x18\x6d\xe8\x8c\x36\x94\xa3\x0d\x3d\xd0\x86\x81\x68\xc1\x20\xb4\x60\x30\x5a\x30\x04\x2d\x18\x86\x36\x8c\x44\x1b\x46\xa1\x0d\x55\x68\xc1\xe5\x68\xc3\x68\xb4\xe0\x0a\xb4\xe1\x4a\xb4\xa1\x5a\x50\x6e\xc0\x62\x34\x60\x09\x1a\xb0\x14\x0d\x58\x86\x06\x2c\x47\x03\x56\xa2\x0d\xeb\xd0\x86\x87\xd0\x86\x87\xd1\x86\x47\xd0\x86\xf5\x68\xc3\x06\xb4\x61\x33\x5a\xb0\x05\x2d\xe0\x54\x3d\x8d\x16\x6c\x43\x0b\xb6\xa3\x05\x3b\xd0\x82\x67\xd0\x82\x9d\x68\xc1\xb3\x68\xc1\x73\x68\xc1\xf3\x68\xc1\x2e\x4e\x3d\x5a\xb0\x07\x2d\x78\x11\x2d\xd8\x8b\x16\xa8\x68\xc1\x1f\xd1\x86\x7d\x68\xc3\xcb\x68\xc3\x2b\x82\x5b\x06\xbc\x2a\x2c\xab\x01\xaf\x09\x8b\x6a\xc0\x1b\xc2\x2b\xb1\xe1\x4f\x42\xf7\xdb\xf0\x96\xd0\xff\x36\xbc\x2d\x6c\x80\x0d\xef\xa0\x05\xef\xa2\x05\x47\xd1\x82\x0f\xd0\x82\x0f\xd1\x82\x8f\xd0\x82\xe3\x68\xc1\x27\xc2\x46\xd8\xf0\x57\xb4\xe1\x33\xb4\xe1\x73\xb4\xc1\x44\x1b\x4e\xa0\x0d\x5f\xa0\x0d\x27\xd1\x86\xd3\x68\x13\x19\x6d\x12\x40\x9b\xa4\xa0\x4d\x52\xd1\x26\x2d\x85\x1d\xb1\x49\x48\xd8\x12\x9b\x64\x08\x7b\x62\x93\x2c\xb4\x48\x36\xda\x24\x07\x6d\xd2\x1e\x6d\x92\x8f\x36\x29\x41\x9b\x74\x41\x9b\x94\xa1\x4d\xba\xa3\x4d\x2a\xd0\x26\x3d\xd1\x26\x93\xd1\x26\x53\xd0\x22\x73\xc4\xc8\x1b\xe4\x65\xb4\xc8\x7e\xe1\x2d\xd9\xe4\x20\x5a\xe4\xb8\x90\x06\xc3\xb7\x1d\x2d\xdf\x49\x21\x15\x86\x3c\x50\x78\x01\x86\x3c\x48\x58\x7f\x43\x1e\x22\xac\xbe\x21\x0f\x47\x43\xbe\x44\x58\x78\x43\x1e\x21\x2c\xbb\x21\x8f\x14\x16\xdd\x90\xab\x84\x25\x37\xe4\xd1\xc2\x82\x1b\xf2\x95\xc2\x72\x1b\x72\xb5\xb0\xd8\x86\x3c\x0e\x2d\x79\x3c\x5a\xf2\x44\xb4\xe4\x49\x68\xc9\x93\xd1\x92\xa7\xa3\x25\xcf\x40\x4b\x9e\x29\x6c\x9b\x2d\xcf\x16\xf6\xcd\x96\xe7\x08\x1b\x67\xcb\x73\x85\x9d\xb3\xe5\x79\x68\xcb\xb7\x09\x5b\x67\xcb\x77\x08\x7b\x67\xcb\xf3\x85\xcd\xb3\xe5\x05\xc2\xee\xd9\xf2\x42\x61\xfb\x6c\x79\x91\xb0\x7f\xb6\xbc\x44\xd8\x40\x5b\x5e\x86\x96\xbc\x02\x6d\x79\x15\xda\xf2\x6a\xb4\xe5\xfb\xd1\x96\xd7\xa0\x2d\xaf\x45\x5b\x5e\x27\xa4\xda\x59\xc7\x78\x29\x61\x6d\x49\x6b\x62\x6d\x06\xa2\x0e\x83\x50\x87\xc1\xa8\xc3\x10\xd4\x61\x18\x5a\x9e\x7c\x93\xee\xe6\x9b\x74\x37\xdf\x64\x88\x7c\xd3\x04\xe1\x0f\x6a\xb0\x18\x35\x58\x82\x1a\x2c\x45\x0d\x96\xa1\x06\xcb\x7f\x25\x4e\xd9\x8c\x3a\x6c\x41\x1d\x38\x65\x4f\xa3\x0e\xdb\x50\x87\xed\xa8\xc3\x0e\xd4\xe1\x19\xd4\x61\x27\xea\xf0\x2c\xea\xf0\x1c\xea\xf0\x3c\xea\xb0\x0b\x75\xd8\x8d\x3a\xec\x41\x1d\x5e\x44\x1d\xf6\xa2\x0e\x2a\xea\xcd\xe4\xa2\x34\x78\x55\xd8\x6c\x0d\x5e\x13\x76\x5b\x83\x37\x50\x77\xad\x8a\xee\x5a\x15\xdd\xb5\x2a\xba\x6b\x55\x74\x78\x17\x75\x38\x8a\x3a\x7c\x80\x3a\x7c\x88\x3a\x7c\x84\x3a\x1c\x47\x1d\x3e\x11\x31\x3a\xb7\x2a\x96\x6b\x55\x2c\xd7\xaa\x58\xae\x55\xb1\x9a\xe4\xaa\x1c\xab\xa2\xbb\x56\x45\x77\xad\x8a\xee\x5a\x15\xdd\x93\xbb\x32\x48\x3e\x1a\x67\xcd\x59\xf5\x43\x8b\xf4\x47\x8b\x54\xba\xfe\xff\x14\xd4\xdd\xbc\x95\x46\x5e\x46\x9d\xec\x47\xdd\xb5\x24\x3a\x39\x8e\x86\x6f\x1b\x6a\xbe\xed\xa8\x8b\xfc\xcc\x45\xa8\xc9\x03\x85\x6f\xa2\xc9\x83\x84\x7f\xa2\xc9\x43\x84\x8f\xa2\xc9\xc3\x51\x93\x2f\x11\x7e\x8a\x26\x8f\x10\xbe\x8a\x26\x8f\x14\xfe\x8a\x26\x57\x09\x9f\x45\x93\x47\x0b\xbf\x45\x93\xaf\x14\xbe\x8b\x26\x57\x0b\xff\x45\x93\xc7\xa1\x2e\x8f\x47\x5d\x9e\x88\xba\x3c\x09\x75\x79\x32\xea\xf2\x74\xd4\xe5\x19\xa8\xcb\x33\x51\x77\xad\x87\xee\x5a\x0f\xdd\xb5\x1e\xba\xc7\x7a\xe8\xae\xf5\xd0\x5d\xeb\xa1\xbb\xd6\x43\x77\xad\x87\xee\x5a\x0f\xdd\xb5\x1e\xba\x6b\x3d\xf4\x5f\xca\xe1\xc4\xac\x45\x51\x13\x5d\xfd\x4b\xfa\x95\xeb\x3b\xae\xeb\xb8\x9e\xe3\x3a\xee\x53\x57\x7f\x99\x8e\xde\x12\x3a\x8a\xeb\x27\xae\x9b\x32\x5d\x5d\x73\x00\x6d\x31\x97\xf9\x3c\xe6\x73\x38\x3a\x7f\xf9\xdc\xe5\xf3\x96\xcf\x59\x3e\x5f\xf9\x5c\xe5\xf3\x94\x5b\x29\x06\x3e\xb4\x21\x09\x6d\xff\x13\x68\xfb\xb7\xa0\x0d\xa1\xe8\x91\x66\x7c\x35\x9b\xfb\x47\xae\x2f\x61\x93\xfe\x68\x93\x4a\xb4\x63\x7e\xc1\x7a\xb1\x0a\xe7\x5c\x85\x81\x0f\x32\x21\x09\x32\xfd\x4f\x40\xa6\x7f\x0b\x64\x8a\x23\xfd\x20\x49\xac\xd1\xf6\xf3\x6f\x81\x7e\xd0\x23\xce\x52\x71\xeb\x34\x5a\xcc\xbf\xff\xcc\x82\xfc\x49\xcc\x1b\x4b\x58\x83\x5f\xb1\x04\x42\xab\x87\x84\xcc\x5b\x42\x93\x4f\x11\x32\xfa\xcb\xda\x71\xb6\x90\x17\x4b\x68\xc4\xdb\x84\x7c\x58\x42\x03\x2e\x10\x32\x61\x09\xad\xb7\x44\xc8\x81\x05\x57\xc4\xd6\x9b\x9b\xb3\xc3\xde\x1e\xfe\x5f\xd8\x4e\x6e\x27\xb9\x8d\x7c\xe3\x3f\xe3\x82\xb0\x85\x9f\xbb\x36\xf0\xa4\x6b\xeb\x12\xb9\x12\xb5\x55\x07\xd1\xe2\xf6\x49\xd8\x25\x6e\x93\xb8\x3d\xe2\x76\x88\xdb\x20\x6e\x7f\xb8\xed\xe1\x76\x87\xdb\x1c\x6e\x6f\x7e\xcd\xd6\xfc\x07\xdc\xf4\xac\xc5\x47\xb9\x1a\xcd\xcc\x14\x08\xb9\xea\x24\x32\x1c\x5b\xa0\x93\xc8\x72\x70\x49\xb6\x20\x49\xc8\xa0\xe5\xe7\xfc\x3d\x57\x9c\xe7\x45\x52\x02\x92\x61\x50\x1c\x0a\x60\x64\x1c\x2a\xdd\x8a\x81\x4a\x4f\xe5\x80\x17\xc3\x13\x30\x22\x01\x97\x25\x60\x12\x0c\x8a\x43\x1d\xe4\xc6\xa1\x1e\xfa\x79\x21\xfa\xe8\xc5\x96\x78\xfc\x57\x3d\x8c\xc7\xff\xfb\x3d\x1c\xe4\xc5\xaf\xf6\x30\x1d\x86\x42\x27\x18\x03\x9d\x60\x2c\x94\xc3\x38\x28\x87\xab\xa0\x1c\xc6\x43\x39\xec\x87\x72\x52\x04\x9d\x48\x47\xe8\x44\x7a\x43\x39\xf9\x04\x3a\xc9\x1d\xa1\x5c\x3e\x07\xca\xe5\xf5\x50\x1e\x58\x0a\x9d\x02\xcb\xa0\x53\x60\x39\x74\x0a\xac\x70\xaf\x54\x0e\x63\xa0\xfc\x2c\x57\x2a\x27\x1d\xa1\xdc\xbd\x52\x79\xc2\x95\xca\x03\xcb\xa0\x3c\xb0\x1c\xca\x03\x2b\xa0\x1c\x92\xa3\x39\x51\x3a\x1c\x2d\x5a\x85\x96\x27\x8f\x6d\xd1\x71\x68\x88\x3c\xf6\x62\x4f\x4e\x31\xd4\x6c\x35\x89\x53\x19\x12\xad\xf5\x30\xe9\x18\xb4\x45\x95\xc8\x38\x51\xef\x61\xbb\xf5\x1e\xde\x3c\x9e\xeb\x27\xd1\xf3\x50\xa3\x03\x51\xa3\x83\x51\x13\x34\x8c\x40\x4d\xd0\x51\x8d\x26\xbd\x0a\x6d\x3a\x11\x75\x7a\x35\x1a\x74\x12\x9a\xf4\x1a\x34\xe9\x64\x34\xe9\x14\xd4\xdd\xf5\x21\x83\x5e\x8b\x26\xbd\x0e\x4d\x7a\x3d\x9a\xf4\x46\x34\xe9\x4d\xa8\xd3\x9b\x51\xa7\x73\x51\xa7\xb7\xa0\x4e\xe7\xa1\x49\x6f\x43\x9d\xde\x81\x26\xbd\x13\x4d\x7a\x17\x9a\x74\x01\xea\xf4\x6e\x34\xe9\xc2\x46\x9b\xe6\xff\x92\x6b\x7a\x7a\x25\x5a\x82\xf6\x09\x0e\xbd\xd0\x41\xf4\xd6\x8b\x50\x3c\x04\x17\xbc\x18\x98\x80\xc1\x09\x18\x91\x80\xb1\xf1\x10\x1c\xf2\x62\x6b\x3c\xa0\x8b\x37\xa7\x41\xcf\x43\x85\x0e\x44\x85\x0e\x46\x85\x0e\x17\xf5\x36\x0a\xad\x42\x53\xac\x42\x5c\x25\xea\x61\x54\x7a\x35\xea\x74\x12\xea\xf4\x1a\x34\xe8\x64\xd4\xe9\x14\x54\xe9\x34\x51\x23\xc3\x39\xa8\xd3\x6b\x51\xa7\xd7\xa1\x41\xaf\x47\x9d\xde\x88\x3a\x9d\x25\x56\xd9\x54\x97\x8b\x2a\xbd\x05\x55\x3a\x0f\x75\x7a\x1b\xaa\xf4\x76\xb4\xe8\x1d\xa8\xd3\x3b\x51\xa7\x77\xa1\x4e\x17\xa0\x4a\xef\x46\x9d\x2e\x44\x9d\x2e\x6a\x3e\xb6\xf4\x7f\x89\x26\x24\x8b\xea\x22\x2f\xaa\x12\x50\x2d\xa8\x8e\x01\x7c\x31\x89\xe4\x47\xe6\xa0\x4d\x6f\x45\x1b\x4a\x45\x5e\xc9\x8b\x50\x3c\x44\xbd\x92\x17\x03\x13\x30\x38\x01\x5c\x72\xbd\x18\x81\x7a\x1c\x12\xc6\x87\xde\x10\x0f\x91\x6b\xf2\x62\x6b\x3c\xa0\x52\xc4\xb9\x5e\x84\xe2\xf1\x1f\x4b\xd0\x50\x34\xe3\x90\x28\x51\x7c\x0e\x7a\x71\xa5\xbb\x6e\x12\xc5\x18\x31\x3f\x1b\x31\x56\xcc\xd5\x46\x4c\x40\x33\x0e\x37\xb8\xf3\xf7\x86\xd8\x3c\x36\xbd\x10\xb1\x8f\x17\x5b\xe3\x01\x49\x9e\xb9\x6e\xd0\x81\x68\xd0\xc1\x68\x08\x19\x18\x21\xd6\xce\xec\x98\x5f\x49\xe8\x0d\x90\x09\x32\xf8\xd0\x80\x24\x34\xa2\xa3\xee\x7f\x82\xdb\x46\x34\xc0\x17\xd3\x3d\x37\x78\x74\xc9\xb9\x90\x86\xba\x17\xa2\x0a\xcc\x8b\x29\x09\x98\x9e\x80\x9b\x12\x30\x27\x01\x73\x13\x70\x4b\x02\x6e\x4d\xc0\x6d\x09\x58\x10\x0f\x51\xbf\xe6\xc5\x86\x04\x6c\x8c\x07\xb0\x68\x76\x26\x96\x3d\xf1\xc7\xfa\xd5\x4c\x95\x1b\xb4\x04\x1f\x6a\x90\x84\x1a\x9d\x88\x36\x9d\x82\xb6\x98\xef\xce\xbc\xb6\xdd\x1e\xd9\xf4\x16\xc1\x5d\x7e\x96\x4d\x17\x08\x2e\x6b\xfe\x2d\xa8\x09\xfe\x0b\xaf\x39\x7a\x96\xc7\x13\x6e\xc9\xbd\x6a\xc1\x7b\xdb\xbf\x15\x6d\x21\xdd\x66\x1c\xd2\xd0\x8a\x43\x08\x4d\x2f\xfe\xe7\xb1\xf9\xb5\xb1\xf8\x75\xde\xc7\x63\x43\x02\x36\x26\xe0\x49\x21\xe1\x8d\xd8\x1a\x0f\xc1\x13\xd1\xb3\x58\x3d\x61\xaf\x98\xfc\xd6\xa2\x46\xf7\xa1\x46\xf7\xa3\x45\x8f\xa2\x4e\xdf\x17\x35\x71\x3a\x3d\x8e\x9a\x58\xb5\xfc\xde\x53\x57\xd8\x12\x2d\x96\x21\xaa\xf8\x74\x56\x84\x06\xeb\x88\x06\x3b\x1f\x0d\x76\x11\x1a\xec\x32\x34\xd8\x28\xd4\xdc\xd5\x4d\xdd\xad\x35\xd4\xd9\x24\x51\x6f\xa8\xb3\xc9\x62\xb5\x53\x73\x6b\x0e\x75\xb7\x4e\x4e\x77\x6b\x0e\x75\x51\x17\xf7\x04\x5a\xec\x49\xb4\xd8\x53\x68\xb1\xcd\x68\xb1\x2d\x68\xb1\xad\xa2\x5e\x4e\x17\xf5\x72\xcf\xa2\xc1\x76\xa3\xee\xd6\xcc\xe9\x6e\x3d\xa2\xe6\xd6\x23\x3a\xf3\xef\xb1\x38\xdb\xb3\x1b\x2d\xaa\xa2\xee\x56\x5d\xe8\xf4\x08\xea\xf4\x1d\xb4\xe8\x7b\xbc\xb7\x90\x29\x56\xb7\x4f\xa0\x4e\xbf\x40\x9d\x9e\x44\x8d\x9e\x42\x95\xd6\xa1\x45\xff\x86\x16\xad\x47\x9d\xfe\x1d\x75\xfa\x25\xea\xd4\x42\x8d\xfe\x03\x75\xfa\x15\xea\xf4\x6b\x54\xe9\x37\xa8\xd3\x7f\xa2\x4e\xbf\x15\xab\xe2\x06\xfd\x1e\x0d\xfa\x03\xaa\xd4\x46\x8b\xfe\x4b\xac\x92\xeb\xf4\xdf\xa8\xd3\xd3\xa8\xd3\x9f\xd0\xa0\x3f\xa3\x4e\xcf\xa0\x4e\x1b\xd0\xa2\x88\x3a\x03\x34\x19\x41\x95\x49\xa8\x32\x86\x3a\xf3\xa1\xca\x64\xd4\x58\x12\x6a\xac\x05\xea\x2c\x05\x75\x96\x8a\x3a\x6b\x89\x06\x4b\x13\xab\xed\x16\x4b\x47\x8b\xb5\x42\xdd\xad\x02\xd1\x58\x1b\xd4\x59\x3b\xd4\x59\x2e\xea\xac\x00\x75\x56\x88\x16\xeb\x80\x2a\x2b\x16\x15\x8b\x16\x3b\x07\x2d\xd6\x19\x55\x56\x82\x16\x2b\x45\x95\x75\x41\x8b\x75\x45\x95\x95\xa1\xc5\xba\xa1\xc5\xba\xa3\xc5\xca\x51\x65\xfd\x50\x67\x95\xa8\xb3\x01\xa8\xb3\x41\xa8\xb3\x21\x68\xb1\x61\x68\xb1\x4b\x50\x67\x23\xdc\x1a\xcd\xd1\xa8\xb3\x2b\x51\x67\xd5\x62\x25\xdf\x62\xe3\x50\x65\x57\xa1\xc5\xc6\xa3\xca\x26\x40\xa6\xa8\xdf\x9c\x84\x06\x9b\x8c\x06\x9b\x8a\x96\xa8\xdf\x9c\x21\x46\x57\x67\xd7\xa3\xce\x6e\x40\x9d\xdd\x88\x2a\x9b\x85\x3a\x9b\x8d\x2a\xbb\x19\x2d\x76\x0b\xea\xec\x56\xd4\xd9\x3c\xd4\xd8\xed\xa8\xb3\x3b\x85\x14\xe8\xec\x6e\xd4\x45\xe5\xca\x62\x54\x45\xc5\xca\x0a\x54\xd9\xfd\x68\xb1\x35\x68\xb1\xb5\x68\xb2\x75\xa8\xb3\x87\x51\x67\x8f\x88\xea\x15\x95\x3d\x8a\x16\xdb\x80\x2a\xdb\x88\x16\xdb\x84\x2a\x7b\x5c\x48\x91\xc1\x36\xa3\xc1\xb6\x8a\x4a\x4b\x9d\xed\x40\x9d\xed\x44\x9d\xbd\x80\x16\x53\xd0\x72\x2b\x5d\x54\xb7\xd2\x45\x15\x55\x04\x7b\x51\x67\x2f\xa1\xce\x54\xd4\xd8\x3e\x51\x4d\x60\xb1\x57\x44\x35\x81\xc1\x0e\xa1\xca\x5e\x45\x9d\x69\xa8\x35\x9f\x9b\x16\x92\x16\x95\xac\x0f\x9c\x39\x23\x46\xad\xd0\x1d\x09\x3e\x0a\x7c\x04\xca\x5c\xce\x73\x2e\x72\x0e\xf2\x79\xe0\xd4\x8a\x5a\x6c\x16\x5a\x62\x1e\xf0\x9e\xf1\x5e\xf1\x1e\x6d\x13\xd4\x5a\xac\x56\xd4\x8a\x5a\x6c\x2f\x5a\x9c\x32\x90\xa2\x7f\x41\x61\x93\x7b\x1b\x9e\xfb\xe7\xff\x06\x1a\x7e\xe7\xd2\x71\x6d\x8c\x16\x5d\x8c\xd4\xfc\x66\xe8\x79\xfa\xec\x34\xb1\x83\x68\xc3\x88\x98\x25\xdd\x8d\x76\x33\x73\xcf\xa6\xef\xa1\x4d\x3f\x40\x93\x7e\x86\x36\x3d\x89\x06\x3d\x85\x16\xb5\xd0\xa0\x5f\xa3\x45\xbf\x45\x8b\xfe\xe0\x52\x4f\xd0\x62\x12\x5a\x8c\x42\x39\xf3\xa1\xc5\x64\xb4\x59\x12\x1a\x2c\x19\xca\x59\x08\x6d\x77\x1e\x18\xac\x50\x54\x43\xf1\x1e\xda\xac\xb3\xe8\xa5\xcd\x4a\x45\x4f\x6d\xd6\x55\xf4\xd6\x66\xdd\xd1\x66\xe5\x68\xb1\xfe\x50\xce\x46\x42\x39\x1b\x8b\x36\x1b\x27\x7a\x6f\xb3\xf1\x09\xa3\x70\x23\x9a\x62\x24\x66\xa3\xe9\xca\xa7\x53\xb5\x1b\x2f\x93\x9c\x2b\x36\x5b\x2f\x38\x63\xb3\x0d\x82\x3b\x36\xdb\x14\xe3\x0e\x97\x2f\xcb\x95\x2f\xcb\x95\x2b\x83\xbd\x8c\x36\x7b\x05\x2d\x76\x08\x2d\x57\x9e\x1a\x65\xa8\x2c\x16\xe7\xd4\x8a\x3a\x9c\x68\xfd\x4d\x54\x1f\xeb\x71\x35\xde\x19\x62\x6c\xbd\x7a\xd8\x62\x17\xa1\xc5\x2e\x13\x55\x26\xba\xab\x87\x55\x57\x0f\x47\x6b\x6d\xf4\x66\xf5\x6f\xe3\x78\x3b\x7a\x78\x25\x5a\xec\xde\x38\xbd\x6b\xb1\xdd\x62\x96\x58\xec\x45\x54\xc5\x78\x3b\xd5\xd5\x96\x27\xe6\x72\xf3\x01\xf4\x20\xda\x5c\x02\x59\xb6\xa8\xa4\x76\xa4\xeb\x5a\x8f\x84\xcf\x17\xbc\xb4\xd9\x62\xb4\xd9\x52\xb4\xb9\x44\xc5\x72\x08\x49\x51\xef\x89\x15\x89\xda\x6b\x9b\x5d\x2d\x6a\xac\x6d\x51\x2b\xfd\xa2\xe7\x59\x00\x46\x5f\x82\x1b\xd9\x5a\xc8\x8c\xcd\x83\xf3\x63\x9e\x57\xad\x90\x3c\x8b\xee\x43\x5b\xd8\xb5\x83\x68\xd1\xd7\xd0\xa2\x6f\xa0\x45\xdf\x44\x9b\x1e\x11\xb6\xce\x14\xb6\xee\x98\x3b\x5f\x8e\xa3\x4d\x3f\x15\x12\x69\x53\x4b\x48\x1a\x97\x30\x8b\xb5\x46\x9b\xe5\xb9\x3d\x89\xd2\x34\x18\x2d\x36\x14\x6d\x36\x0a\x6d\x51\x57\x1f\xa5\x71\x8a\xb0\x71\x76\xac\xc7\x73\xd0\x62\xb7\xa2\xc5\xe6\xa1\xed\xf6\xda\x62\x8b\x45\x1d\x9e\xc5\xee\x43\x8b\xfd\x1e\x6d\xf6\x18\xda\xc2\xee\x3d\xe5\xda\x3b\x3e\xbf\x9e\x47\x8b\xfd\xc1\xad\x0f\x7f\x51\x48\x8f\xc5\x54\xb4\xd9\x7e\xb4\xd9\xab\x68\x31\xcd\xe3\x59\xc6\x56\xb1\xdd\xea\x42\x5d\x54\x17\xf2\x9e\x1e\x41\x4d\xf4\xee\xa4\xb0\x5f\x3a\x4b\x12\xb6\x43\x67\xad\x51\x67\x6d\xdd\x5e\x4c\x89\x51\xa9\xb1\x79\x42\xef\xea\x6c\x31\xea\x6c\x29\xea\x82\xc2\x28\x25\x11\x34\x58\x2d\x1a\x6e\x45\xa0\xee\x56\x02\x36\xae\x62\xf7\xf6\xf0\xde\x72\x79\x6f\xd1\xfd\x68\x26\xf0\xde\xf2\xf0\xde\x14\xd4\x1d\x47\x8b\x7e\x2a\xa8\x6c\x8e\xef\x89\x3c\xe7\xb2\x6d\xb9\x3c\x37\xd9\x35\x68\xba\x3c\x8f\xe7\x75\x53\x3e\x5b\xec\x31\xe1\x5f\x98\xec\x29\x34\xd9\x16\x34\x7f\x81\xc7\x56\x13\x1e\x13\x06\x90\x29\xf2\x01\xba\xeb\x2f\x72\x6f\xc1\xa4\xa7\x04\xcd\x26\xfd\x1a\x6d\xfa\x2d\xda\xf4\x07\xb4\x19\x41\x9b\x49\x68\x33\x9f\xe8\x8b\xc9\x5a\xa3\xc9\x3a\x08\xcd\xc4\xb5\x12\xd7\x48\x5c\x13\x71\xed\xc3\x35\x8f\xcd\xe6\xa1\xc9\x56\x08\x4d\xc2\xb5\x08\xd7\x20\x36\xab\x41\x9b\xed\x42\x9b\xa9\x68\xb2\x57\xd0\x66\x87\xd0\x66\x1a\x9a\x09\x4f\x86\x38\x91\x4b\x7b\xa1\x3f\xcf\xa6\x3b\x7d\xc2\x27\xb0\x84\x5e\x2c\x15\xf6\xdf\x12\x7a\x70\x9c\xb0\xdd\x8d\x7a\xef\x46\xa1\xef\x1c\x6d\xbf\x42\xd8\x55\x4b\xe8\xb4\xa8\x3e\xe3\xba\x6c\x97\xb0\x87\x42\x77\x41\x6e\xcc\xff\xe6\xde\xd2\x77\x68\xd3\xef\xd1\x16\xde\xcf\x8f\x68\xd3\x9f\xd0\x66\x2d\xd1\x16\x9e\x44\x15\xda\x6c\x22\xda\xae\x57\x60\xb3\x19\x68\xb3\x99\x68\x0b\x0f\xe0\x2e\xb4\x85\x65\x7f\x12\x6d\xb6\x19\x6d\xb6\x15\x6d\xb6\x0d\xed\x98\x95\xde\x83\x36\xdb\x8b\x36\x3b\xe0\xc9\x97\xb7\x88\x49\xda\x49\x61\x37\x2c\x96\x24\xa4\x85\x8f\x3c\x1f\x41\x3e\x72\x8d\x5a\xa2\x63\x2c\xca\x70\xe8\xd4\xe9\xf7\x68\xba\x74\x1a\xa2\x8e\xb1\xa5\x78\xe6\xc3\x8a\x79\x4d\xdc\x33\x72\xe8\xd6\x45\x9d\xe2\x24\x34\xd9\x64\x34\x5d\xfa\xb9\xde\x34\xd8\x4c\x34\x62\x1c\x73\xfa\x61\x88\x7e\xac\x15\x7d\x31\xd9\x66\x34\xd9\x56\x34\xd9\x36\x34\x3c\x7d\x71\x3c\x8c\x03\xa8\x37\x8d\x62\xa2\x3a\x2c\xd6\xcb\x5c\x8f\x7f\xee\xcc\xa5\xa3\xa2\x0e\xd3\x10\xf3\xe5\xbb\x66\x9f\xf3\xb1\xe2\x2a\x0b\xa3\xf3\x63\x9a\xa0\xdb\x79\xce\xe7\x5a\x34\xc4\x33\x28\x4f\xbb\x7e\xf4\x8b\xa2\x5e\xd2\x8a\xf3\x9f\x7b\xc6\xac\x90\x57\xae\xa2\x9c\x73\xe4\xcb\x14\x9c\xf3\xca\x58\x94\x8b\x05\xae\x2d\x8e\x72\xd3\x2b\x77\xdd\x5c\xd9\xe3\x9c\x8d\xca\xdf\x44\x37\x42\x98\x1c\xe3\xae\xc9\x66\xba\x4f\xcd\x38\xf2\x68\x36\x91\xc7\x78\x0e\x9b\x31\xd9\xdc\x23\xaa\x40\x35\x21\xa3\x07\x50\xe7\x72\x1a\xb3\x4e\x12\xdb\x8d\x36\x7b\x11\x6d\x68\x0d\x2d\xb9\xb5\x42\x95\xaa\x42\x3b\x19\xf4\x35\x34\xe9\x11\x34\xe3\xe4\x29\x1b\x0d\x21\x53\xb7\xa2\x29\xe4\xea\x1e\x34\xd8\x62\x34\xd8\x52\x34\x3c\xba\xd0\x14\xf2\xf6\x2a\x9a\xae\xcc\xa9\xfe\xad\xa8\xc2\xba\x38\x3d\x51\x0b\x99\x6e\x14\x62\xd0\x7d\x90\x49\x0f\xa2\x46\x5f\x43\x83\x1e\x41\x23\x21\x12\x31\xe9\x71\xc8\xa4\x27\xd0\xa4\x5f\x08\x6a\x74\x7a\x0a\x0d\x4f\x34\x62\xd2\xbf\xa3\x49\xbf\x44\x93\x6b\x73\xfa\x0f\x34\xe9\x57\x42\xf7\x18\xf4\x1b\x34\xe9\x3f\xd1\xa4\xdf\x8a\x28\xc4\x70\xa3\x10\xd3\x8d\x42\x4c\x7a\x1a\x4d\xfa\x33\x9a\xf4\x0c\x9a\x6e\x04\xc2\xa3\x0f\x83\x49\x68\x30\x0a\x99\x8c\xa1\xc9\x7c\x68\xb8\x75\xe6\x3a\x6b\x81\x26\x4b\x86\x4c\x96\x82\x26\x4b\x45\x93\xa5\xa1\x29\x7c\xc9\x56\x68\xb2\x6c\xd4\x84\x05\x69\x83\x26\x6b\x87\x16\xcb\x45\x93\x15\xa0\xe9\x46\x1f\x86\x1b\x75\x18\x6e\xd4\x61\xb8\x51\x87\x11\xf3\x39\xcb\xd1\x60\xfd\xd0\x64\xfd\x21\x93\x55\xa2\xc9\x06\xa0\xc9\x06\xa1\xe9\x89\x3a\x4c\x36\x02\x4d\x36\x12\x32\xd9\x28\xc8\x64\xa3\xd1\x64\x57\xa2\xc9\xaa\xd1\x74\x23\x0f\xc3\x8d\x3c\x0c\x11\x79\xf0\x79\x39\x0d\x32\x3d\xd1\x86\xd9\xc4\x8b\x73\xa2\x0d\xee\xcd\x19\xc2\xca\xdd\x8e\x26\xbb\x13\x4d\x37\xda\x30\xd9\x3d\xa8\xb1\xc5\xa8\xb1\xa5\xa8\xb1\x15\xee\x5c\xe6\xd1\xc6\x3a\x34\xd9\xc3\x68\xba\x91\x86\xe1\x46\x1a\x86\x1b\x69\x18\x22\xd2\x70\xa2\x0b\x93\xed\x44\xd3\x13\x5d\xe8\xac\x46\x48\x89\xce\x76\xa1\x11\xf3\x91\x5f\x42\x43\x58\xcf\x7d\x68\xba\xd1\x85\xc1\xf6\x43\x26\x3b\x84\x06\x7b\x15\x0d\x61\x51\x9b\xd3\xf1\xf9\xd1\xf8\xdd\xb5\x3a\x96\x6b\x75\x62\x3a\x3f\x6e\x2e\x36\x5a\x9d\xb3\xeb\xfd\x79\xcd\xcc\xab\xe8\x3c\x72\xac\x8e\xe3\xa3\x6a\x9e\x9c\xc1\x7a\xf1\xfc\x9c\x17\x49\xf1\x10\xcf\x26\x7a\xf1\x12\x94\xc7\x61\x1f\x9a\x71\x38\x9a\x00\xc3\xd5\x71\x46\x4c\xd7\x99\x71\xf8\xce\xd5\x7d\x51\xfc\x98\x80\x9f\xe2\x21\xf4\xa3\x17\x5c\x57\x7a\xd1\x31\x01\xa3\x12\x50\xe5\xea\xd4\xaa\x98\x6e\x35\xe3\x30\x51\x68\xb0\x46\x5c\x9d\x80\x6b\x12\x30\x4d\xe8\xe3\x46\x4c\x77\x75\xf3\x74\x8f\x8e\xf6\x62\x86\x6b\xa1\x67\xc4\xe2\x33\x23\x0e\x33\x5d\xeb\x1d\xc5\x7c\x57\xbf\x47\x71\x97\x6b\xd1\xa3\x78\xda\xd5\xfd\x51\x6c\x73\xad\x7b\x14\xbb\x13\xb0\x07\xcd\x38\xbc\xe8\xfa\x4a\x51\xec\x45\x33\x0e\xfb\x13\x70\xc0\xb1\x2d\x51\x88\x67\x1b\xbd\xd8\x12\x0f\x61\x0f\x85\x24\x79\xec\xa1\xf3\x4b\x91\xd0\xa1\x2f\xc1\x8d\x9e\x38\x37\xfa\xcc\xab\x21\xc6\x9a\xeb\xa7\x30\xe4\x0a\x0b\x74\xb6\x78\xb7\xca\x13\xf3\x4e\x74\x79\x1e\xb5\xe7\x89\xcf\x6a\x72\x9b\x1e\x1f\x87\x1b\x71\xb1\xee\x01\xb4\x84\xef\x65\x7b\xbd\x3f\xee\xfd\xc4\x79\x80\xbf\xe4\xf9\x45\x3d\x21\xee\x05\x25\x7a\x80\xdb\x3c\x5e\x60\xf4\xae\xae\x27\x08\x3b\x44\xc5\xaf\x17\x49\xf1\x10\xf1\xa3\x17\x4d\xe7\xa1\x1e\x87\xa3\xb8\x2d\x0e\x06\x6a\x71\x38\xee\xc6\x9f\xc7\x63\x71\xa8\x11\x87\xa6\xf3\xd0\xf0\x42\x3c\xf5\xeb\x45\x11\xaa\x71\xe8\x98\x80\x51\xe2\xb9\x91\x46\x54\x89\xa7\x26\x1a\x31\x01\xb7\xc5\x61\xa2\xf0\x79\x1a\x71\xb5\x78\xbe\xa4\x11\xd7\x24\x60\x5a\x02\xa6\x8b\xa7\x30\x1a\xf1\x3b\xd4\xe2\xd0\x74\x1e\x6a\x71\x48\x9c\x87\x37\x08\x1b\xd4\x88\x1b\x5d\x0f\x3b\x8a\x59\xc2\x36\x35\x62\xb6\xeb\xed\x44\x31\x5f\x3c\xf7\xd2\x88\xa6\xf3\x58\x8b\x43\xd3\x79\xbc\x2d\x0e\x7b\x84\xec\x36\xe2\x45\xdc\x16\x87\xbd\x68\xc4\x61\xbf\xf0\x0b\x1b\x71\x40\x3c\x9d\x12\x83\xa8\xa0\xf6\x62\x4b\x3c\x20\x27\xe6\x43\x3a\x4f\x0c\x59\xc2\x5f\x4c\xf4\xb2\x1b\x3d\x6c\xaf\xff\xd7\x34\x1e\xd9\x26\x34\x91\xca\xf6\x3a\x4f\xf6\xc4\x7c\xba\x54\x8f\x6f\xcc\xed\x43\x63\xac\xd8\x18\x23\x3a\x71\xf9\x34\x4f\x9c\xb7\x1f\x2d\x58\xec\xc9\x51\x39\x9e\x59\x73\x5e\x19\xd7\x30\x9f\x8b\xfc\xb0\xd7\x23\xd3\x7f\xc1\x13\xd3\x3d\x9e\x98\x4e\x7f\x40\xdd\xf5\xc2\x8c\x26\x5e\x18\xf7\xc0\x40\xd8\x6d\x9d\x49\xa8\x7b\xbc\x30\x9d\xc9\x68\xfc\x97\x5e\x98\xe5\x7a\x61\xba\xeb\x85\xe9\xae\x17\xa6\xbb\x5e\x98\xee\xf1\xc2\xf4\x66\xbd\x30\xaf\xf7\xd5\xd4\xf3\xd2\x5d\xcf\xab\x31\x0a\xba\x5e\x48\xb7\xc1\x66\xa3\x71\x16\x0f\xcb\x88\x79\x58\x8b\x84\x0f\xad\xb1\x25\xc2\x8f\xd6\xd8\x32\x34\xd8\x0a\xd4\xd9\x4a\xb4\xd9\x2a\x34\xd8\xbd\x68\xb3\xd5\x68\x24\x78\x5d\xba\xeb\x75\xe9\xae\xd7\xa5\x0b\x4d\x1c\xf5\xb8\xb8\x2f\x5e\x83\xba\xf0\xc7\x77\x89\x95\x81\xb3\x79\x5a\x3a\x3b\x28\xf4\xa7\x1e\xf3\xb4\xa2\x79\x37\x6f\x44\xd9\x98\x83\x68\x2d\x62\x73\x5b\xe4\x04\xbc\xb9\x80\xce\x9e\x37\x31\x44\xa5\x4f\x8b\x8b\xcc\xbe\x77\xec\x80\xbb\x62\x62\x9f\x25\x4a\xd3\x62\x2b\x24\x8e\x46\xb2\x3c\x6f\x63\xb0\x5d\xeb\x6e\xbb\x56\xdc\x8e\x8b\x90\x1d\xcb\x6d\xb3\xdd\xae\x45\x7a\x51\xcc\x5a\xcb\x13\xc9\x39\x36\x33\x03\x7c\xa8\x43\x92\x9b\x37\xfc\xde\xb3\x86\x53\xe5\xda\xbf\xc6\x99\xe7\xac\xbb\x6c\x76\xd7\x5b\xf6\xb8\x7a\xc0\xb9\x9a\xee\xdf\x82\x3a\x04\xe8\x51\xcf\x0c\x9b\x20\x68\x8f\x66\xe6\x9c\xc8\xea\xb9\x5f\xf5\x0f\x13\xed\xd0\x51\xc1\xbd\x46\x7c\x90\x80\x44\x7f\xf0\x3b\x61\xf3\x1b\xd1\xd4\xee\x98\x5e\x88\x77\x39\x78\xd1\xd4\x1f\xb4\xe2\x50\x8c\x76\x1c\x3a\xa2\x15\x87\x4e\x68\xc7\xa1\x5b\x02\xaa\x84\xcf\xd8\x88\x09\x62\xa4\x1b\x31\x51\xf8\x8c\x8d\x48\xf4\x17\x27\xa1\x1d\x87\x44\xff\x71\x32\xda\x71\x98\x2e\x7c\xc8\x46\xfc\xaf\xfe\xe3\xff\x6e\xb7\xfe\xbf\xf5\x3f\x0f\xc4\xe3\x57\xfd\x4d\x9f\xc8\x95\x45\x6d\x8e\x6b\x6b\xa0\x32\x36\x6f\xa2\x4f\x71\x3a\x79\x4c\x93\xbe\x21\xe2\x14\xd5\xcd\x5d\xf2\x78\xc5\x14\x4f\x77\x3a\xb9\xa5\x68\x5e\xc9\x79\x8f\x48\x36\x9a\xac\xad\x88\x41\x1a\x63\x8d\xc1\x6e\x9c\xeb\x3c\x05\x6a\xba\xf9\x79\x6f\x2e\xd3\xc9\x33\x39\x4f\x85\xf2\xf1\x34\xdd\x71\x33\x05\x85\x73\xdc\x58\x76\xbe\xd0\xac\x16\xbb\x07\x4d\xb6\x18\x4d\xb6\x14\x4d\x76\x1f\x9a\x22\x6e\xf5\xe6\x38\x9f\x16\x19\x12\x8b\x3d\xef\xc6\xa6\x7f\x40\x53\xc4\xa7\xbb\xdd\x75\x9b\x17\x5d\x6d\xe9\x3c\x7d\x6a\xc6\xe6\x7a\x6e\x8c\x03\xd1\x9e\x71\xed\xe1\xed\x5d\xcb\x58\x96\xcc\x91\x64\x27\x3b\x66\xc6\x78\x79\xb3\xcb\xcf\xfb\x13\x34\x0b\xa7\xa6\x69\x46\xac\xf1\xce\xd9\x31\x5d\x7c\x10\x6d\x91\x33\x3e\xea\xe4\xe8\xc5\x6a\x82\x37\x17\xec\xd5\x40\xd1\x2c\xb6\x77\x55\xc1\x93\xbd\x8e\xe9\xee\x8c\xd8\x1a\x45\x5d\x2c\x63\x19\xcd\x54\xda\x6c\xaa\xc8\x4a\xda\xec\xfe\x04\x7d\xfb\x02\xda\x4c\x89\xcb\xd1\x39\x6b\x15\x25\x9e\x1c\x9d\x13\xcf\x1e\x74\xf3\xdc\x47\xdd\xdc\xb6\xb3\xae\x60\xc6\xf2\x75\xd9\xee\x7a\x5c\x91\xab\x4f\x06\x0b\x59\x68\xfe\xfd\x3c\x53\xe2\xde\xd1\xd3\xb8\x9e\xd0\xdc\x3a\x42\x73\x6b\x06\x8d\xef\xe9\x71\xf2\x7a\x12\x3c\x00\x3e\xf0\x01\x40\x12\xb4\x00\x02\x2d\x21\x04\x14\x3a\xc0\x39\x20\x43\x57\x28\x83\x64\x28\x87\x1e\x90\x0a\xbd\xa1\x3f\x84\x60\x20\x0c\x82\x1c\x18\x02\x43\xa1\x1d\x0c\x77\x2b\x11\x47\x40\x1e\x8c\x84\xcb\x21\x0c\x57\xc0\x15\xd0\x01\xc6\xc0\x18\x28\x82\xb1\x30\x1e\x8a\x61\x22\x4c\x84\xce\xb0\x08\xee\x83\x12\x58\x0b\x6b\xa1\x37\xac\x83\xf5\x70\x2e\x6c\x80\x27\xe1\x7c\xd8\x0c\xdb\x61\x20\xec\x84\xe7\x61\x18\xd4\x40\x0d\x8c\x80\x5d\xb0\x07\x2e\x83\xbd\xb0\x17\xaa\x40\x05\x15\x2e\x87\xfd\xf0\x26\x8c\x86\xc3\x70\x18\x26\xc2\x11\x38\x02\x57\x83\x0e\x3a\x4c\x82\x3f\xc3\x7b\x70\x0d\xbc\x0f\x9f\xc0\x54\xa8\x83\x3a\xb8\x11\x7e\x84\x9f\x60\x16\x9c\x81\x33\x70\x33\x20\x21\x30\x97\x50\x42\x61\x1e\x09\x90\x00\xdc\x46\x52\x49\x2a\xdc\x4e\xd2\x48\x1a\xdc\x41\xd2\x49\x3a\xdc\x49\x32\x49\x26\xcc\x27\xd9\x24\x1b\xee\x22\x39\x24\x07\x16\x90\xb6\xa4\x2d\xdc\x4d\x3a\x90\x4e\xb0\x90\x74\x26\x9d\x61\x29\x29\x25\xa5\xb0\x8c\x74\x25\x5d\x61\x39\xe9\x46\xba\xc1\x0a\x52\x4e\xca\x61\x25\xe9\x41\x7a\xc0\x2a\xd2\x8b\x9c\x07\xf7\x92\xf3\xc9\xf9\xf0\x00\xb9\x80\x5c\x00\x6b\xc9\x14\x32\x05\x1e\x24\x73\xc8\x1c\x58\x47\xf6\x91\x57\xe0\x21\x72\x80\x1c\x80\xf5\xe4\x63\xf2\x09\x3c\x4a\xcf\xa3\xe7\xc1\x46\x5a\x49\x07\xc3\x26\x3a\x94\x0e\x85\xad\x74\x38\x1d\x0e\x4f\xd3\x4b\xe9\x08\xd8\x46\xab\x68\x15\xec\xa0\xa3\xe9\x68\x78\x86\x5e\x49\xaf\x82\x9d\x74\x02\x9d\x08\x0a\x9d\x44\xaf\x81\x1a\x3a\x85\x4e\x81\x5d\x74\x1a\x9d\x06\xbb\xe9\x0c\x7a\x03\xec\xa1\xb3\xe8\x2c\xd8\x47\x6f\xa2\x37\xc1\xcb\xf4\x66\x7a\x33\xbc\x42\x6f\xa1\xb7\xc0\x7e\x7a\x1b\xbd\x1d\x0e\xd0\xf9\x74\x3e\x1c\xa2\x0b\xe8\x02\x78\x95\x2e\xa2\x8b\x41\xa3\xb5\x74\x0f\xbc\x4e\x55\xfa\x32\x1c\xa6\xfb\xe9\x7e\xd0\xe9\x41\xfa\x1a\xbc\x43\xdf\xa0\x6f\xc2\xfb\xf4\x2d\xfa\x16\x1c\xa3\xef\xd0\x77\xe0\x43\xfa\x2e\xfd\x10\x0c\xfa\x17\x7a\x1c\xfe\x4a\x3f\xa1\x7f\x85\xcf\xe9\xe7\xf4\x73\xf8\x82\x9e\xa0\x7f\x83\x93\xf4\x4b\xfa\x25\x7c\x49\xbf\xa6\x5f\x83\x45\xff\x49\xff\x09\xff\xa0\xdf\xd1\x7f\xc1\x57\xf4\x34\xfd\x09\xbe\xa3\x67\x28\xc2\x0f\x8c\x30\x06\x3f\xb2\x24\x96\x02\x3f\xb3\x96\xac\x25\x01\x16\x62\x59\x84\xb0\x6c\xd6\x96\xc8\xac\x3d\x6b\x4f\x5a\xb0\x3c\x96\x47\x92\x59\x3e\xeb\x4e\x52\xd8\x79\xec\x2a\x92\xcb\x26\xb0\x19\xe4\x02\x76\x1d\x9b\x4d\x86\xb3\x39\x6c\x1e\x19\xc5\xee\x60\x77\x92\x31\x6c\x01\xbb\x9b\x8c\x65\xf7\xb0\x25\xe4\x2a\xb6\x8c\x2d\x23\x57\xb3\x15\xec\x01\x32\x89\x3d\xc2\xb6\x92\x99\x6c\x3b\xdb\x41\x6e\x63\xcf\x32\x85\xdc\xc1\x6a\xd9\x41\xb2\x90\xbd\xca\x34\xf2\x7b\xdf\x36\xdf\x76\xf2\x80\x5c\x2c\x97\x90\x07\xe5\x8b\xe4\x99\xe4\x51\x79\x96\x7c\x33\x39\x28\xdf\x22\xdf\x42\x5e\x97\xe7\xc9\xf3\xc8\x1b\xf2\xed\xf2\xed\xe4\x4d\xf9\x4e\xf9\x4e\xf2\x27\x79\x81\xbc\x80\x1c\x96\x17\xca\x0b\xc9\x5b\xf2\x22\x79\x11\x39\x22\x2f\x91\x97\x90\xb7\xe5\x65\xf2\x72\xa2\xcb\xab\xe5\xd5\xe4\xcf\xf2\xfd\xf2\xfd\xe4\x5d\x79\x8d\xbc\x86\xbc\x27\xaf\x95\xd7\x92\xa3\xf2\x3a\x79\x13\x79\x5f\xfe\x42\xfe\x82\x7c\xe2\x7f\xd4\xbf\x91\x7c\xea\x7f\xdc\xff\x24\xf9\xdc\xbf\xd9\xbf\x99\x7c\xe1\xdf\xea\xdf\x4a\x4e\xfa\xbf\xf4\x7f\x49\x4e\xb9\x6f\xa8\x4b\x82\x01\x30\x1a\xe8\x94\xdb\xe7\x5c\x0f\x99\xbf\x9b\x33\xed\x3a\x08\x5f\x7f\xcd\xdc\x1b\xa1\x54\xbc\xfb\x0d\x10\x45\xab\xb3\xed\x93\x29\x53\x6e\x98\x0d\x01\x00\xa0\xe2\x7a\x12\x30\x48\x82\x74\x68\x03\x05\xa2\x1d\x81\x30\xc8\x20\xfe\x97\x0f\xe7\x6f\xdf\x8f\xce\x79\xfe\xd5\x40\x7c\x33\xc1\x07\x69\xa4\x40\xea\x41\x07\xb1\x6a\x68\x07\x7d\x61\x00\x0c\x83\x2a\x18\x07\x93\x61\x26\xcc\x81\x3b\x60\x11\xac\x82\xb5\xb0\x01\x36\xc3\x4e\xa8\x01\x15\x0e\xc1\x61\x78\x0f\xfe\x02\x26\xfc\x1d\xbe\x85\xd3\x04\x88\x4c\x92\x03\xaf\x00\x95\x9e\x95\x9e\x0d\xbc\x2c\xb6\x3b\x03\xfb\xc4\xf6\x99\xc0\x1f\xc5\x76\x47\x40\x15\xdb\xed\x81\xbd\x40\xa5\x9d\xd2\xb3\x81\x17\xc5\x76\x67\x60\x8f\xd8\x3e\x13\xd8\x2d\xb6\x3b\x02\xbb\xc4\x76\x7b\xa0\x06\xa8\xf4\x8c\xf4\x6c\x20\x22\xb6\x3b\x03\x8a\xd8\x3e\x13\xf8\x83\xd8\xee\x08\xbc\x20\xb6\xdb\x03\xcf\x01\x95\x76\x48\xcf\x06\x9e\x15\xdb\x9d\x81\x9d\x62\xfb\x4c\xe0\x19\xb1\xdd\x11\xd8\x21\xb6\xdb\x03\xdb\x81\x4a\xdb\xa5\x67\x03\xdb\xc4\x76\x67\xe0\x69\xb1\x7d\x26\xb0\x55\x6c\x77\x04\x5e\x02\x49\xda\x19\xd8\x0f\x92\xf4\x6c\xe0\x79\x90\xa4\x1d\x81\x5a\x90\xa4\x67\xfe\x07\x8e\xfc\xc5\xe5\xc8\x47\x2e\x47\x0c\x97\x23\x1f\xba\x1c\x39\xe6\x72\xe4\x7d\x97\x23\x47\x5d\x8e\xbc\xe7\x72\xe4\x5d\x97\x23\x7f\x76\x39\xa2\xbb\x1c\x79\xdb\xe5\xc8\x11\x97\x23\x6f\xb9\x1c\x39\xec\x72\xe4\x4f\x2e\x47\xde\x74\x39\xf2\x86\xcb\x91\xd7\x5d\x4e\x68\x2e\x27\x5e\x75\x39\x71\xc8\xe5\xc4\x41\x97\x13\x07\xc4\x76\x7b\xe0\xb8\xe0\xc5\x3b\x9c\x0b\x81\xd7\x40\x92\xb6\x07\x3e\xe0\x3c\xfa\x1f\x38\x62\xbb\x1c\xf9\xc1\xe5\xc8\xf7\x2e\x47\xbe\x73\x39\xf2\xad\xcb\x91\x6f\x5c\x8e\x7c\xed\x72\xe4\x2b\x97\x23\xff\x70\x39\x62\xb9\x1c\xf9\xd2\xe5\xc8\xdf\x5d\x8e\xd4\xbb\x9c\xf8\x9b\xcb\x89\x53\x2e\x27\x4e\xba\x9c\xf8\xc2\xe5\xc4\x09\x57\x36\x4c\x97\x23\x9f\xb9\x1c\xf9\xab\xcb\x91\x4f\x5d\x8e\x7c\xe2\x72\xe4\x63\x97\x23\xff\x14\x32\xf2\x2f\xc1\x97\xcf\x05\x47\xea\xc4\x5b\x53\xff\x6b\x8e\x04\xd3\x1d\x8e\x04\x43\x0e\x47\x82\x69\x0e\x47\x82\x2d\x1d\x8e\x04\x53\x1d\x8e\x04\x53\x1c\x8e\x04\x93\x1d\x4e\x04\x5b\x38\x9c\x08\x26\x39\x9c\x08\x06\x1c\x4e\x04\xfd\x0e\x27\x82\xb2\x23\x1b\x41\x9f\xc3\x91\x20\x73\x38\x12\x94\x1c\x8e\x04\x89\xc3\x91\x20\xb8\x1c\x41\x97\x23\x0d\x2e\x47\x7e\x76\x39\xf2\x93\xcb\x91\xd3\x2e\x47\xfe\xed\x72\xe4\x47\x87\x23\xc1\x20\x97\x8e\x60\x86\xe0\xc8\x19\xce\x91\x20\xfd\x1f\x39\x52\xe6\x72\xa2\xab\xcb\x89\x2e\x2e\x27\x4a\x5d\x4e\x74\x76\x39\x71\x8e\x23\x1b\xc1\x4e\x2e\x47\x3a\xba\x1c\x29\x76\x39\xd2\xc1\xe5\x48\xa1\xcb\x91\x02\x97\x23\xf9\x2e\x47\xc2\x2e\x47\x72\x5d\x8e\xb4\x77\x39\xd2\xce\xe1\x48\xb0\xad\xc3\x91\x60\x1b\x87\x23\xc1\xd6\x0e\x47\x82\xd9\x0e\x47\x82\xad\x1c\x8e\x04\xb3\x1c\x8e\x04\x33\x5d\x8e\x14\x09\x8e\x94\x70\x49\x09\xe6\x08\x8e\xe4\x39\x6f\xd6\x05\xc2\xcf\x8f\x69\xe9\x74\x20\xd0\x4e\xe8\x61\x0a\x04\x28\x5c\x02\x97\x4a\x9d\x41\x82\x54\xe9\x90\x74\x0c\x40\xfa\x58\xfa\x18\xb2\x24\xa4\x04\x5a\x51\x46\x65\xc8\xa1\x01\x1a\x80\x76\x34\x99\xa6\x42\x7b\x9a\x4e\x33\x21\x4c\x73\x68\x0e\x14\xd2\xf6\xb4\x3d\x74\x10\x6f\x1d\x2e\x12\x6f\x1d\x2e\xf7\x3d\xea\xdb\x00\xbd\x7c\x9b\x7c\x9b\xe1\x5c\xdf\x56\xdf\x56\xb8\x00\x08\x59\x0b\x14\x92\xe1\x46\x02\x10\x80\x74\x68\x07\xc5\xd0\x0d\xfa\xc2\x40\x18\x01\xd5\xc1\xde\xc0\xa4\x37\xa5\x63\xd2\xab\xc1\x5e\xee\xde\xa1\x60\x4f\xb1\xf7\x81\xf4\x6a\xb0\x87\xbb\x77\x28\x58\x01\x4c\x7a\x5d\xb4\x2b\x77\xf7\x0e\x05\xbb\x8b\x3d\xde\xae\x9b\xbb\x77\x08\x92\xa1\x0d\x74\x80\xae\x70\x2e\x0c\x80\x4b\xe0\x4a\x98\x04\x33\x61\x2e\x2c\x80\x15\xc1\xe1\xc0\xa4\xc3\xd2\x9b\xd2\xab\xc1\x61\xee\xde\xa1\xe0\x50\xb1\xf7\xba\xf4\x6a\x70\x88\xbb\x77\x28\x78\x41\x8c\xa2\xfe\x31\x8a\xce\x8f\x51\xd4\x2f\x46\xd1\x79\x31\x8a\xfa\xc6\x28\xea\x13\xa3\xe8\xdc\xdf\x40\xd1\x65\x31\x8a\x46\xc4\x28\xba\x34\x46\xd1\x25\x31\x8a\x06\xc7\x28\x1a\x14\xa3\xe8\xe2\x18\x45\x03\x63\x14\x5d\x14\xa3\x68\x40\x8c\xa2\x0b\x63\x14\x55\xc6\x28\x22\x40\xe9\x14\x7a\x1d\x9d\x07\x12\x24\x03\x85\xef\xc8\xbf\x7d\xa3\x3d\x92\x40\xd9\xfb\x64\x0d\xf8\x80\xf9\x36\xf8\x2a\x00\x48\x9e\xb3\xa5\xef\xc2\x74\x09\x02\x92\xd4\xc2\x27\x31\x1f\x93\x24\xf6\x19\x48\x58\x09\xb7\x21\x00\xe4\x73\xaf\xe0\xd2\xcb\x46\x5c\x06\x95\x90\x82\x67\xe4\xe9\x0d\xd3\x01\x02\x93\xa5\x31\x61\x20\x4f\xfc\xf5\x43\x00\x36\xcc\xb7\x07\x00\xc2\xd0\xda\x95\x43\x0e\x47\x0a\x81\x7e\x2f\x24\x91\xff\xcd\xa8\x01\x00\xdf\xc2\x42\x90\x61\x8e\x78\xfb\xec\x02\x3a\x8b\xde\x42\x17\xd0\x55\x74\x35\x7d\x8a\xea\xbe\x8e\xed\x0f\xe7\x6e\xcc\x7d\x3c\xf7\xdf\x79\x59\x79\xed\xf3\x2e\xce\xbb\x34\x6f\x4c\xde\xd8\xbc\xab\xf2\x26\xe4\xdd\x95\xb7\x2b\x4f\xcb\x3b\x9a\x77\x3c\xef\xeb\xbc\xef\xf3\x1a\xc2\x05\xe1\xe2\x70\xb7\x70\x8f\x70\xdf\x70\xbf\x70\xff\xf0\xc0\xf0\xd5\xe1\xd9\xe1\xdb\xc3\x77\x87\xd7\x85\x9f\x09\xef\x0e\xab\xe1\x6f\xf2\x7d\xf9\x19\xf9\xd9\xf9\x05\xf9\xc5\xf9\x5d\xf3\x47\xe4\x8f\xce\x9f\x98\xbf\x24\xff\xa1\xfc\x1d\x05\x52\x81\x5c\xd0\xb2\x20\xbd\x20\xab\xa0\x4d\x41\x5e\xc1\x39\x05\x25\x05\x43\x0a\xae\x29\x98\x56\x28\x15\xa6\x15\xe6\x17\x41\x91\x54\x94\x5c\x94\x56\x94\x59\xd4\xba\xa8\x5d\x51\x87\xa2\xd2\xa2\x1e\x45\xfd\x8a\xae\x2f\x5a\x58\xb4\xa4\x68\x45\xd1\xea\xa2\x07\x8b\x9e\x2a\x7a\xae\xa8\xa6\x48\x2d\xda\x57\xa4\x15\x1d\x29\x7a\xa7\xe8\xa3\xa2\x53\xc5\xfd\x8a\x2b\x8b\x07\x14\x4f\x2a\x9e\x52\x3c\xbd\xf8\xba\xe2\x59\xa5\x37\x94\xce\xeb\x9a\xbd\x3d\x7f\xfb\xea\xcf\xe0\x27\xd6\x50\xd8\x80\x78\x06\x51\xbc\x79\x37\x05\xc2\xf0\x24\x9d\x4b\xef\xa0\x4b\xe8\x6a\x7a\x3f\xdd\x42\xff\xdc\x1e\xda\x37\xe4\x3e\x9e\xfb\x64\x1e\xe4\xb5\xce\x0b\xe7\x0d\xc9\x1b\xe9\xf6\xf9\xea\xbc\x85\x79\x7b\xf2\x5e\xcf\x3b\x96\xf7\x49\xde\xb7\x79\x76\x18\xc2\xc5\xe1\xce\xe1\xf2\x70\x1f\xb7\xcf\x13\xc3\x33\xc3\x73\xc3\x77\x87\xd7\x84\x9f\x0c\x3f\x1b\x7e\xc9\xed\x73\x2b\xb7\xcf\x97\xe6\x5f\x9e\x7f\x55\xfe\x92\xfc\x35\xb1\x3e\x87\x0a\xb2\x0a\x72\x0a\x72\xdd\x3e\x4f\x2a\x98\x2a\xfa\x1c\x3e\x4b\x9f\x47\xc6\xfa\xbc\xa6\xe8\xc9\xa2\x9d\xb1\x3e\x1f\x2e\x7a\xa7\xc8\x28\x3a\x55\xdc\x37\xd6\xe7\x69\xc5\x33\x8b\x67\x95\x4e\x2a\xbd\xa9\x6b\xf6\xf6\xec\xed\x2b\x3e\x83\x9f\x48\x43\xb8\x01\xf1\x67\xee\x49\xe2\x0f\x78\x02\x0f\xe1\x2b\xa8\xe2\x6e\xdc\x85\xb5\x58\x83\x91\xba\x8f\xea\xb6\xd5\x6d\xad\xdb\x52\xf7\x58\xdd\xc6\xba\x47\xeb\x1e\xa9\x7b\xa8\x6e\x5d\xdd\x83\x75\x6b\xeb\x1e\xa8\xfb\x7d\xdd\xfd\x75\xf7\xd5\xdd\x5b\xb7\xaa\x6e\x45\xdd\xf2\xba\x65\x75\x8b\xeb\x16\xd6\xdd\x5d\x77\x67\xdd\x1d\x75\xb7\xd7\xcd\xad\xbb\xaa\x6e\x54\xdd\x88\xba\xa1\x75\x7d\xea\xba\xd6\x75\xa9\xeb\x7c\xea\x87\x53\x9f\x9f\x7a\xff\xd4\x7b\xa7\xde\x3c\xf5\xda\xa9\x57\x4e\x3d\x79\x6a\xd3\xa9\x87\x4f\xdd\x74\x6a\xfa\xa9\xd1\x27\x7f\x3a\xf9\xe3\xc9\x6f\x4e\x7e\x7d\xf2\x1f\x27\xff\x7e\xb2\xee\xe4\xa7\x27\x3f\x39\x79\xf0\xe4\xce\x93\x3b\x4e\x26\x7f\x81\x5f\x7c\x73\x22\xfd\x44\xe8\x44\xe0\x84\xef\x84\x64\xa2\xf9\xb3\xf9\x83\xf9\x95\x59\x67\x7e\x66\xbe\x6d\xaa\xe6\x8b\xe6\x2e\x33\x62\xbe\x60\x6e\x36\x37\x98\x0f\x99\xf7\x9b\xf7\x99\xcb\xcc\x7b\xcc\xbb\xcd\x79\xe6\x75\x66\x6b\x33\xcb\xcc\xfc\xfc\x5f\x9f\xff\xf0\xf9\xf7\x9f\xff\xf3\xf3\xaf\x8e\x37\x1c\xff\xe9\x2f\xe3\xaf\x99\x30\xe9\x5f\x9d\x96\xa4\x2c\x49\xba\x36\x78\x7f\x60\xad\xfb\x7e\xe5\xff\x7f\xfd\x93\xa5\x24\x70\x42\x8e\xc4\xde\x13\xf1\xb2\x79\x00\x88\x6d\xcf\xf6\xcf\x39\x93\x8a\x67\x86\x65\xf0\x43\x00\x82\x22\x4b\x90\x0c\x29\x90\x0a\x2d\x21\x0d\x42\x90\x0e\x19\x90\x09\x59\xd0\x0a\xb2\xa1\x35\xe4\x40\x1b\x68\x0b\xed\xa0\x3d\xe4\x42\x1e\x84\x21\x1f\x0a\xa0\x10\x3a\x40\x11\x14\x43\x47\xe8\x04\xe7\x40\x67\x28\x81\x52\xe8\x22\x72\x0b\xdd\xa0\x3b\x94\x43\x05\xf4\x80\x9e\xd0\x0b\x7a\xc3\xb9\xd0\x07\xfa\xc2\x79\xd0\x0f\xce\x87\xfe\x70\x01\x54\xc2\x85\x30\x00\x2e\x82\x81\x70\x31\x0c\x82\xc1\x22\xef\x30\x0c\x86\x73\xad\x09\x23\xe0\x32\x18\x09\xa3\xa0\x0a\x2e\x87\xd1\x70\x05\x5c\x09\x63\xa0\x1a\xc6\xc2\x38\xb8\x0a\xc6\xc3\x04\x98\x08\x57\xc3\x24\xb8\x06\x00\x96\xc1\x72\x58\x09\xf7\xc2\x83\xb0\x1e\x1e\x87\x2d\xb0\x19\xb6\xc2\x36\x78\x1a\xb6\xc3\x33\xf0\x2c\xec\x84\xe7\xe0\x79\xf8\x03\xbc\x00\x0a\x44\xa0\x16\x76\x8b\x1c\xc4\x5e\x78\x11\xf6\xc1\x1f\xe1\x65\x78\xc5\xbf\x0d\xe6\xc0\x54\x98\x06\xd7\xfa\x77\xc0\x6d\xf0\x14\xcc\x86\xeb\xfc\x7f\x87\x5b\x61\x66\x20\x09\x56\xc0\x86\x80\x0f\x6e\x0e\x24\x07\x52\xe0\x77\x30\xcf\x7f\x26\x00\x7e\xa4\x73\x02\x01\xb8\x1e\xe6\xd3\xab\x60\x07\xa8\x70\x0f\x4c\x81\x1b\x03\x8c\x8c\x0e\x04\xfd\x0d\x70\x03\xdc\xe5\x7f\x06\x26\xc3\x22\x58\x0a\x8f\x90\x4c\x92\xe5\x7f\xd4\xbf\xc1\xbf\xd9\xbf\xc5\xff\xb8\xff\x09\x78\x29\x30\x1c\x0e\x92\xbe\xfe\xbd\xfe\x8f\xfc\xbb\xfc\xbb\x03\x4b\x03\xcb\xfc\xdb\xe1\x76\xff\x93\xfe\xad\x7e\x05\x96\xc0\x6a\x58\x0c\xf7\xc1\x2a\xf8\x3d\xac\x81\x07\xe0\x7e\x78\x08\x1e\x06\x80\x75\xb0\x09\x1e\x83\x8d\xf0\x9d\xb4\x42\x7a\x1c\x6e\x92\x36\x48\x1b\xa5\x4d\x70\x87\xf4\x84\xf4\x98\xb4\x92\x0f\xa1\xb0\x05\x9b\xe1\x24\xcc\x84\xbb\x60\x35\x3c\x00\x0f\xc1\x06\x78\x0c\x46\xc3\x2e\x38\x0a\xf7\xc0\xef\x61\x1d\xec\x84\x17\x60\x17\xec\x85\x57\xe0\x10\x5c\x07\xdb\x40\x85\x25\x50\x03\xab\x60\x1e\xdc\x09\xcf\x81\xa2\x40\xa9\x02\x19\xc3\x95\x4b\x46\x56\x2b\xc3\x6e\x1d\xab\x40\xe1\x05\xad\x15\xb9\xa4\xfa\xfc\xb1\xe2\xd8\x5d\x63\xc3\xef\x2b\x24\xa3\x6b\xeb\x2e\x0a\x29\x0d\xff\x45\x49\x2e\xe9\xa2\x48\xa5\xc3\xab\xaa\x2f\x2e\x1c\x9b\xdf\x45\xa1\xa5\xd7\xb6\x0e\x2b\x95\x23\xab\xf3\x95\xca\xb1\x5d\x14\x56\xca\x4f\xcd\x2f\xcc\xbf\xa3\xfa\x93\xb6\x6f\x8f\x6d\x3b\xbc\xaa\xba\xfa\x4c\xdb\x7f\x8c\x6d\x5b\x98\xaf\xf8\x4a\xaa\x95\x41\xb7\x8e\x15\x3f\x8c\x1d\xdb\xba\x8b\xe2\x2b\x4d\x19\x3f\xae\x8b\x22\x97\x46\x0a\xc8\x8a\x91\xd5\x4a\x78\xc5\xf8\xf1\x6d\x15\x18\xdb\x45\xf1\x97\x46\x3a\x88\x43\x95\xb1\x43\x81\xd2\xf4\x50\xb8\x4f\x59\x17\x25\x58\x1a\xbe\x8b\xdf\x44\x6b\xfb\xf6\xd8\xb0\x42\x8b\x86\x16\x86\x15\x56\x3c\x4c\x81\x91\xd5\xab\xa6\xad\xba\x26\xcc\x77\xce\x6d\x9b\x9f\x3f\xb6\xed\x2a\xf1\x57\x95\xf3\x17\xbf\x61\x92\x43\x5d\x5a\xdb\xb4\xfc\xb1\x5d\x94\x16\xa5\xe1\xf7\x44\x77\x92\x4b\xc3\x65\x8a\xbf\x64\x7c\x75\x38\x3c\xb8\x70\xd0\x35\x33\xc3\xd5\xe1\xa9\x93\x9d\x4b\xf0\x76\x29\xfc\xce\xe1\x3e\x65\xe1\x55\xe1\xc1\xab\x06\x5d\x53\xb8\x2a\xbc\xaa\x50\xdc\xae\x90\x5f\x5c\xa9\x3c\xb7\x6d\xfe\xd8\xb6\x85\xfc\x80\x52\x39\x8d\xff\x31\xb6\x8b\x92\x2a\xee\x74\xfe\xb1\xd6\xf9\xf9\x6d\xc3\xc7\x56\x0d\xaf\xaa\x0e\xaf\x2a\x1c\x1a\x56\xe0\x0a\x97\xb6\x7c\xd1\xac\x65\x69\x61\xf8\x98\x7b\xf3\xc2\x70\xf5\xf0\xcb\xdb\xe6\x2b\x64\x6c\xf5\x2a\x85\x15\x0f\x2d\x5c\x55\x18\x5e\x35\x74\x55\xe1\x35\xfc\x04\xe7\x14\xbe\xe9\xa2\xa4\xf1\x61\x48\x2f\xe9\xa2\x84\x78\x07\xf8\x4e\x7a\x42\x07\x56\xf1\x4d\xe1\x35\x33\x27\x79\x7b\xc2\x4f\xcd\x28\x0d\xaf\x0a\xaf\x5a\xce\xd9\x36\x6c\x6a\xe1\x2a\xbf\x12\x1e\x59\xdd\xaf\xed\x81\xb1\x5d\x94\xcc\xd2\x5a\xa8\x24\x95\x03\x06\x90\xe1\x7b\xd3\x60\x0a\x88\x6f\xde\xf8\x8a\x6a\xfe\x5d\x55\x5d\x38\x39\xac\x40\xe1\x80\xb6\x93\xc3\x0a\x29\x1c\x30\x36\xac\x54\x56\x55\xd7\x40\x18\x2e\x9a\x32\xa0\x86\x84\xc9\x45\x53\x06\x28\xe1\x29\x4a\xce\xb4\x76\xd1\x7b\x65\x95\x2a\xe4\xa2\x29\x85\x0a\x5c\x34\xa5\xb0\x8b\xa3\x73\x08\x22\xb4\x04\x09\x0e\x02\xb0\x24\xdf\x1e\xa0\xe0\x07\xa8\x08\xe5\x87\x8a\xf2\x43\xf9\x07\xe9\xd0\x33\x79\xd2\xed\x67\x96\xfb\xf6\x9c\x1e\x36\x83\x9d\x02\x09\x1e\xc4\x13\xe4\x01\xdf\x1e\x68\x01\x2d\x61\x2c\xd4\x24\x4b\x50\xa2\x04\xcb\x76\x51\x06\x2d\x59\x09\x51\xd2\xca\x14\x38\xb6\x4b\x4e\x85\x1c\x56\xe2\x6e\x6a\x53\x65\x08\x94\x44\x5a\xb6\xae\x57\x5a\x96\x45\x52\x5b\xd7\xd7\x86\x5a\x26\xa7\x96\x44\x52\x52\xeb\x23\x21\x52\x12\x49\x6d\x19\x4a\x8f\x04\x69\x9f\x3e\x10\x49\xa6\xa1\x74\x25\xb5\x4f\xb7\xee\xbd\x7b\xf4\xaa\x28\x6f\x95\x95\x29\x17\x16\x14\x67\x54\xd0\xc2\x07\x2f\xec\xdf\xff\xc2\x8b\xfa\x9d\x3f\x20\xe3\x78\xc5\x2d\xb3\x06\x0c\x1e\x5a\x59\x79\xc9\x30\xdf\xca\x9f\x4e\x09\xbd\xba\x94\x6e\x93\x5e\x71\x69\xef\x0b\x35\xc0\x69\x62\x15\x9c\xa6\x00\x2b\x51\xe4\x72\xa2\x04\xca\x14\x7a\x2c\x22\xb5\xae\x57\xa4\xb4\x88\x9f\x94\x44\xe4\xd6\xf5\x91\x20\x29\x89\xf8\xa5\x50\x7a\x84\xb0\x3e\x7d\xa0\x5b\x77\x7e\x23\x52\x41\x0b\x97\xbe\x7a\xce\x4d\x64\xc4\xa1\x4e\x37\xf9\xf6\x9c\xf9\x46\x4a\x3b\xf3\x0d\xbf\x47\x05\x00\xb3\x7d\x7b\xa0\x2d\xe4\x91\x51\x50\xd3\x06\xa0\xa4\x26\xab\x55\x4e\x45\x45\x45\x8d\x5f\x82\x92\x9a\x40\x8b\xe4\x8a\x8a\x8a\x5d\x40\xda\xf8\x53\x4a\x6a\xa5\x50\xbb\xf6\x1d\xb2\x2b\x22\xe0\xaf\xaf\xcd\xcc\x6e\xdd\xb6\x43\x76\xf9\x2e\x1f\x13\x3f\xd1\xb4\xdc\x3c\xfe\x93\xcf\x5f\x5f\x2b\x07\x93\x52\x3a\x64\x97\x13\x25\x5c\xa6\xb4\x39\x16\xc9\x49\xab\x57\x72\x1c\xfa\x02\xa1\xfa\x1a\x7f\x20\xa9\xa4\xb6\xd2\xcf\x82\x25\x4a\x20\x2d\xd2\x8a\x94\x44\xb2\xd2\xea\x6b\xb2\x5a\xf1\xa3\x59\x19\xc1\x12\x25\x2b\x2d\xd2\x82\x94\x44\x92\xd3\xea\x23\xf9\xa4\x44\xe9\xd5\x46\xed\xff\xc6\x77\xbf\x87\xac\x92\x24\xb5\xff\x89\xef\x73\xf9\x8e\xd2\x26\xad\x56\x6a\xe3\xcf\x28\xa9\xa5\xe2\x5b\xe6\xdf\x4a\x4e\x5a\x6d\x30\x27\x90\x51\xa2\xb4\x4a\xab\x4d\x6a\xd5\x22\x83\x5f\xaa\x36\x25\x2b\x39\xa3\xa4\x36\x4d\x7c\x87\xc4\x77\x26\xff\xe6\x6d\xb2\x45\x9b\x9c\xb4\xda\xd6\xe2\xac\x36\x69\xb5\x6d\xa3\xd7\x69\x17\xbd\x4e\x7b\xde\xa6\x36\x37\xda\x32\x8f\x1f\xa7\x95\x69\x12\xe5\x9d\x4c\x0b\x71\x2e\xb4\x6b\x9f\x9b\xd7\x35\xe1\x9f\x52\xd9\x86\xb3\xbe\x67\x7e\x46\x7e\xcf\xfc\x8c\x0a\x2a\x90\x95\x2f\x50\x98\xc1\xd1\x3b\x3f\x23\xbf\x82\xb4\xbf\xb0\xe1\x2b\x52\x52\xf5\x60\x15\xe9\x58\x75\x7f\x15\x61\x0d\x9f\x5f\x40\x5a\x37\xbc\x3d\xfa\x81\xd1\x0d\xc7\x47\xae\x19\xf1\x1c\x29\xaa\x6c\x38\x4e\x9e\x5b\x49\x86\x2c\x27\x35\x0d\x23\x38\x96\x37\xec\x5d\xd9\x30\x9a\x3c\xc7\xb1\x92\x0c\x71\xac\xeb\xdd\xb8\x92\xa5\xc9\xe9\x10\x86\x8e\xd0\x05\x56\x83\x92\x5b\xa6\xb4\xad\x88\xb0\x60\xbd\xd2\xa9\xbc\x26\x97\x71\xe6\xe6\xb6\x0f\x96\x28\x19\x65\x4a\x51\x45\x24\x35\x50\xaf\xb4\x28\xaf\x49\xcd\xe0\xc7\x53\x93\x83\x25\x44\xe9\x5a\xa6\x04\x8e\x45\xf2\xb3\xea\x95\xfc\xb4\x48\x7b\x52\x52\xc3\x5a\x74\x28\x2f\x2f\x8f\xb4\x6b\x59\x5f\x93\x92\xd1\xa9\xbc\xbc\x5c\x69\x97\x16\xe9\x4c\x4a\x22\xad\x53\xea\x23\x65\x7c\xdb\x39\x94\x1e\x09\xa5\x71\x09\x67\xb9\xa1\x74\x05\xfa\x28\x19\xa1\xdd\x24\x10\x6a\xdd\xa1\x4b\x87\xec\x3e\x4a\x6a\xba\x92\xc6\x85\xbe\x67\x2e\xc9\x0e\x75\x25\x3d\x7b\xf4\xea\xdd\xb3\x22\xab\x55\xb6\xbf\xb8\x63\x28\x57\xca\xca\x94\xfd\x59\x85\x3d\xbb\x92\x8c\xcc\x56\xd9\xa1\x54\x42\x7a\xf5\xec\x51\xdc\xf1\xee\xe1\x1f\x4d\x79\x7b\xe7\xe1\xe7\x17\xbf\xf2\xec\xb9\x1b\x1f\x7e\xf2\xb1\x61\x6f\xed\x5b\x3c\xe7\xdd\xc5\x57\xce\x9c\x38\x99\x5c\xf4\xee\xc4\x9b\x77\xec\x28\xac\x90\xc8\x73\x17\xfe\x61\xe5\x92\x9d\x19\xbb\x6a\x7c\x83\xef\x3b\xbf\x45\xc3\xb8\x5e\x93\xee\x1c\xb3\x72\x57\xf6\x17\xc7\xa5\x42\xfa\xf0\xd0\x71\xc5\xe4\x96\xb4\x71\x3f\x3f\x15\x5e\x3b\xe4\x8a\x4e\xe0\x83\xa9\x68\xc9\x03\x7c\x6f\x41\x0b\xc8\x82\x1c\x28\x82\x6e\xb0\x01\x6a\x5a\x71\x49\x2f\x04\x28\x89\x9c\x23\xd7\xd7\x64\x73\x59\xa7\x12\x94\x44\x32\xe4\xfa\x5d\xc1\x96\x85\x34\xa5\x24\x12\x94\xeb\x77\xb5\xef\x2a\x76\xdb\xcb\xf5\x44\xe9\xce\x95\x40\x24\x39\x54\xaf\x24\xa7\x89\x29\x2e\x87\xea\x15\x39\x2d\xd2\x86\x94\x44\x8a\x43\xf5\x4a\x71\x5a\xa4\x94\x94\x44\xc2\xa1\xfa\x48\x39\x29\x89\x84\x92\x43\xe9\xb5\x41\xda\x2a\xa7\x43\x76\x9f\x48\x69\x71\x28\xbd\x36\xbb\x7d\x61\xeb\x0e\xd9\x7d\x20\x12\x6c\x15\x4a\xaf\x6d\x13\x2e\x2e\xe5\x3f\x65\xb4\x0f\xa5\xd7\xca\xc9\x21\xe8\x90\xdd\xa7\x5b\xf7\x0c\x8f\x8a\xe8\x9d\xd9\xaa\xa2\x3c\x94\x56\x58\x20\x67\x90\x8a\x20\x49\xfc\xa5\x57\x4f\xfe\xd3\xd4\x47\xd7\x3e\xf8\xd4\x63\x8f\xdc\xff\xd8\xc3\x83\x47\x3c\xfe\xf8\x88\xc1\xb7\xd0\x92\xc7\x7e\xfe\x80\x7c\xb8\xfe\xc1\x07\x9f\x7a\xfc\x61\x71\x78\xd4\xa5\x8f\x8f\x18\xcc\xa4\x93\x5f\xfc\xe3\xe3\x2f\xea\xbf\xfe\xf4\xe9\xed\xe4\x12\x32\xec\xe9\x9f\xc6\x72\xf5\x47\xf6\xf2\xc3\x27\xea\xbf\xfe\x64\xfb\xd6\x2d\x3b\xc8\x90\x2d\x8e\x3c\xdd\x80\x96\xef\x43\xdf\xdb\x90\x0b\x1d\xa1\x02\x6e\x87\x9a\xd6\x9c\x5f\xed\x38\xbf\x0a\x5a\xd4\xd7\x24\x71\x56\x75\x0f\xd6\x13\xa5\x87\x60\x4a\x5e\xab\xfa\x5a\x7f\x1e\xd7\x87\x9d\x32\xea\x95\xbc\xb4\x48\x57\x52\x12\x49\x49\xa9\x57\x52\xd2\x22\x19\xa4\x24\x92\x99\x52\x1f\xe9\x49\x4a\x22\x5d\x3b\x85\xd2\x77\x27\xd1\x76\x05\x45\x69\x5c\x42\x52\x42\x4a\x87\x3e\x4a\x46\x7a\x4d\xa8\x55\x4e\x1f\x2e\x47\xdd\x0b\x42\xe9\x7b\xc0\x9f\xd2\x2a\xa7\xa8\x24\xca\x8e\xde\x5d\xa5\x9e\xd1\xae\xfb\x49\xaf\xde\x15\x92\x9f\x14\x76\x4c\x25\x51\x36\xf4\x26\xa9\x42\x86\xfa\x93\x9e\x3d\x8a\x0b\x0b\xe4\x1b\x96\xed\xbe\xf4\xc2\x0e\xaf\xd7\x3e\xfd\xf2\xca\x4d\xe4\xde\x09\x15\x7b\x2e\x5e\x4d\x4a\xbe\xaf\x99\xf3\xdd\x83\x1f\xfe\xb0\x6f\xc3\xfc\x13\x9b\x1a\xae\x5c\x75\xcd\x5d\x83\x47\xce\x9f\x3e\x7d\xd4\xd8\x6b\xc9\x5d\x8b\xb4\x19\x63\xa6\x5d\x77\xde\xba\xe7\x76\xac\xbb\x61\xcf\xf8\x86\x25\xd7\x7f\xd4\x70\x62\x63\xc3\x27\xcf\x4d\x1f\xf7\xde\x6b\x37\x2d\x5f\x4b\x1e\xbb\x7c\x85\xa4\x5c\xb8\xe8\xb2\x8b\x17\x8c\xba\x64\xfc\x44\x20\x5c\x2f\x93\x21\x42\x2f\xe7\x39\x5a\xd9\x55\xc9\x44\x61\x51\x7d\x1c\xf1\x91\x12\x57\xf5\x72\xb5\xcb\x35\xae\x63\x97\xaa\x1a\xf6\x49\xe7\xf8\xf6\x40\x0a\xb4\x06\x21\x70\x44\x49\x15\x1c\xf4\xa7\xd4\x47\x5a\x3a\x27\xa5\xa5\xf7\xae\x90\xa5\xac\xcc\xf4\xec\xc2\x62\xa9\x6a\xe3\xda\x9d\x6b\x1e\x58\x77\xef\x8e\x07\x37\x48\xdd\x49\x90\xe8\x2f\x1c\x6c\x28\xff\xfe\x9b\x86\x5e\x2f\xef\x24\xaf\x3b\xd7\x3c\xbf\x61\x9f\x94\x19\xbd\x26\x44\xaf\xd9\xe2\x58\x84\x35\x5e\xb3\xa2\x55\x7a\x28\x4d\xf2\x17\xf6\x4a\xef\xd9\x43\x3a\x7f\xe7\x83\x1b\x36\xae\xdd\x71\xef\xba\x07\x7c\x7b\xfe\xd0\xd0\xbd\xe1\xdf\x0d\xff\x6e\xe8\xbb\x63\x1f\x79\xeb\x9b\xef\xc5\x7f\x38\x07\x04\x46\x4b\x77\xb2\x34\x39\x53\x78\xe8\x0a\x2d\x23\xdc\xc6\xa5\x39\x97\xea\xed\xa3\x15\xb4\x28\xdb\x97\xe1\x6f\x41\x3a\x66\x8c\x6e\x4f\x96\x96\xbc\x79\x0e\x59\xd5\xae\x61\xc5\x77\xca\x0b\x8f\xef\xf9\x86\x9d\xff\xf2\x2c\xb2\xb2\x61\xde\xac\x97\x73\x1b\xf6\x4d\x22\xd3\x1b\x36\x4c\x22\x03\xf9\x35\xa7\xc3\x09\x76\x0e\x7b\x15\x5a\x40\x15\x28\x50\xa6\xf8\x2b\x22\x24\x50\xaf\xf8\xca\x6b\x80\x70\x3d\x04\x49\xc1\x92\x1a\x02\x7c\x97\x50\xae\x92\x92\xcb\x94\xa4\x63\x8a\x54\x1e\x09\x86\xea\x15\x56\x5e\x13\x4c\xe2\xbf\x05\xfd\xc1\x92\x9a\xa4\x20\xdf\x4d\x82\x60\x49\x24\xc5\x21\xab\x67\x7e\xa8\x22\x94\x9f\x95\x1f\x2a\x0c\x4d\x27\xeb\x1f\x24\xeb\x1b\x66\x3c\x28\xad\x5c\x4b\x76\x34\x54\xaf\x6d\x18\x47\xb6\xb9\xfd\x6a\xf8\x91\xac\x84\xaf\x40\x86\x22\x4e\xc3\x2e\x89\x41\x90\x8f\x9c\xbf\x4c\x91\x8e\x45\x58\x6a\x7d\x24\x40\x4a\x22\x4c\x0a\xa5\x2b\xb2\x30\x9e\xbd\x7a\x57\x64\xcb\x74\xf4\x85\x45\x07\x53\x7b\xdf\xde\xf0\xe3\xe9\x9f\xb3\x8f\x35\xfc\xcb\x1d\x4b\xf2\x81\x34\x40\xba\x05\x28\x14\xf0\x6b\x45\x08\xad\xe7\xe0\x62\x10\x01\x52\xb2\x8b\xa6\xf2\x6b\x47\x45\xa1\x67\x7e\x56\x15\xf9\x86\x7c\xf0\xe4\x93\xfc\x5c\xe1\x6f\xc0\x8f\xd0\x02\xba\x42\xa3\xa3\x11\xf3\x37\x92\x9b\xfa\x1b\x6e\x3f\xbd\x2e\xc4\x83\x17\xf6\x3b\x7f\xe0\xc0\xf3\xcf\x1b\x30\x6b\xc0\xe0\xc1\x03\x2e\x1c\x3e\xcc\xa1\x2b\x13\x40\x3a\x29\xe4\xb3\x15\xd4\x00\x9f\xb7\x44\x08\x05\x2b\x73\x69\xa9\x20\x15\x24\x53\xca\x57\xce\x7c\xc6\x35\x80\xf0\x35\xa6\xa2\xc5\xca\x7c\x6f\x43\x0b\xc8\x86\x81\x50\x13\xe4\x13\xbd\x65\x52\xbd\xa3\x13\xb3\x92\xea\x89\xd2\xda\xd1\x7e\x29\x42\xfb\xa5\x73\xed\x97\x52\x1f\xc9\x21\x25\x91\xf4\xe4\x98\xa3\x93\xc5\x7d\x1e\x19\xfa\xf4\x11\x52\x5c\x51\xce\x65\xae\xb0\x40\xf2\xee\x4f\xfd\xc7\xbf\xbe\xfa\xf7\x3f\xed\xaf\xec\xdd\x0f\x3c\xfe\xe4\x03\x0f\x3c\xf9\xe4\xef\xa5\x4f\xc8\x02\x32\xa7\x61\x61\xc3\x9a\x86\xc5\x0d\xab\xc9\xdd\x64\x4e\xc3\xa1\x86\x53\x24\x9f\xf4\x26\x3d\x48\x41\xc3\x17\xa2\x4f\x7b\x00\xa4\x0f\x85\x7f\xd6\x11\x6a\x58\x63\x9f\x92\xcb\x14\x76\x2c\x42\x33\xea\x39\x7b\x22\x94\x71\xb7\xc7\xef\xb8\x3d\xa4\x22\x54\x18\xea\xd1\x5b\xf6\xcb\xfe\x3d\x64\xf5\x43\x4a\xa0\x5d\x78\xfa\xed\x6c\x31\xa9\x38\x3d\x8c\x36\xac\x98\x9b\xdb\xe6\x8a\x29\x0e\xbf\x26\x03\xb0\x73\x7c\x6f\x41\x1b\x18\xe1\xf0\x2b\xd2\x9a\xd6\xd7\xb4\xe4\x3d\x0f\xf2\x9e\xb7\x2d\x53\xe4\x63\x91\xf4\xac\xfa\x9a\x74\x99\x4b\x5d\x7a\x9b\x60\x49\x8d\x9c\xce\x77\x65\x2e\x80\xed\x48\x09\x44\x5a\x43\x28\x5d\x21\x7d\x94\x60\xa8\x56\x4e\x4e\x49\x17\xca\xab\xa2\x27\xe9\x2f\x39\x4a\xc9\xdf\xd1\x19\xb6\x54\xe2\x27\x59\xf9\x59\x93\xc9\xdd\xcf\xcf\xee\xbd\xea\xb6\x71\x4f\x4d\x9b\xf4\xf6\x77\x47\xbe\x1e\xb4\xfa\xe9\x86\x77\xa4\x13\x0f\x93\xc5\x7f\x78\x78\xf5\xa8\xb9\x8b\xfa\x5d\x76\xfb\x73\xef\xee\x9a\x54\xfb\xd2\x53\x0d\x47\x03\x5b\x81\xc0\x78\xb4\x58\x9e\xef\x2d\xe8\x08\xd3\xa1\xa6\x88\xd3\xc8\x82\xf5\x35\xad\x39\x8d\xa1\xa4\xfa\x5d\x49\xc1\xa2\xd6\x29\x25\x91\x24\x4e\x6e\x27\x41\x6e\x41\xab\x7a\x25\x35\x7c\x2c\x14\x69\x9b\x55\x5f\x93\xda\x56\xd8\xf9\x60\xb0\x24\x72\x0e\x27\x96\x15\x39\xe6\x3a\x18\x8a\x90\x82\x3e\x7d\x94\xa4\xf4\x48\x6e\x5e\x9f\x3e\x4a\x28\x54\x93\x99\xd5\xb6\x4f\x1f\xd7\x6a\x57\x84\x43\x69\xf9\x85\x3d\xb9\xa5\x71\x3b\xd1\x9f\xb8\x7a\x38\x2b\x97\x64\x65\xb2\xfc\x82\xe2\xf1\x13\xde\x9f\x42\xe6\x34\xfc\xee\xfe\x35\xcf\x1d\xba\xef\xae\x6b\x9e\xbe\x6e\xdc\xb8\x2f\x97\x1c\xfb\xfa\xb1\xb5\x7f\x78\xbe\xe1\xd3\x86\x7f\xce\x7d\xf5\xbc\x1d\x5d\xcb\x49\x3e\x91\x1e\x7d\x70\xd1\xb5\xb7\xf6\x1c\x74\xe7\xe0\x51\xaf\xee\x58\xbd\x2b\x37\xd0\x6a\xd7\x9a\x77\x4f\x14\x70\xd9\x2b\x01\x60\x33\x7d\xaf\x40\x12\x64\xc0\x24\x47\xf6\x6a\x24\xae\x56\xa1\x45\x50\x4a\xe1\x3e\x6f\x04\x68\xbd\x70\x78\x33\xcb\x94\xe0\x31\x25\xb9\x3c\x12\xc8\xa8\x57\x68\x79\x4d\x40\xa8\x81\x80\x1c\x2c\xa9\x09\x0a\xb7\x32\xc8\x07\x24\x8b\x7b\x9a\xc1\x10\x77\x3f\x20\xd2\xc2\x1d\x18\x29\xa4\xb4\xe4\x72\xd9\x93\x54\x84\x2a\xb2\x0a\x43\x85\x3c\x14\xe8\xd1\xbb\x30\x95\xf8\x4b\x24\xe5\x8f\xef\xbf\xff\x87\x33\xdf\x4b\xc9\x2d\x82\x2d\x7a\xb7\x22\x97\x3c\x4a\x3f\xfa\xb9\xdb\xe6\x86\x5d\xe4\x92\xcd\xe4\xc8\xca\x3f\xb6\x99\x91\x0b\x04\xee\x11\x63\xb0\x07\xda\xc0\x7c\xa8\xc9\x11\x63\x90\x54\x5f\x93\xc2\xc7\x20\x8d\xd6\xef\xca\x08\xe6\xa4\xa4\x94\x44\x32\x5c\x91\xf1\x1f\x8b\xb4\xca\xaa\xe7\xc2\xc1\x3d\xd8\x0b\xde\x3c\xbd\x4f\x38\xae\x29\x5d\x53\x95\xe4\x03\xbe\x48\x5a\xce\xbf\x53\x95\xd0\x01\x88\x24\x87\xba\x76\x25\xb5\xc9\x29\x69\x21\xd7\x6f\x24\x91\x56\xfe\x50\x7a\x24\xb5\xa5\x70\xac\x72\xa2\x23\x55\x43\x5a\xb4\x6a\x1c\x19\x6e\xfc\xf3\x0b\xfc\x1d\x33\xb8\x43\xd9\xab\xa2\x9c\x65\x65\x42\x7e\xc1\x3d\xc3\xfe\x3c\xe5\xb9\x7d\x0d\x6b\x6f\x5d\x32\xae\xb7\xf4\xc9\x99\x97\x0b\x6f\xbe\xf1\x24\xf1\x37\x7c\xda\x80\x3f\x9c\xb7\xb3\xb4\xc7\xd6\xf5\xa4\x53\x6e\x1f\xa9\x66\x6b\x43\x75\xf6\xa9\x37\xbf\x68\x38\xe3\xe4\x6f\x6e\x42\x8b\x55\xf8\xde\x82\x56\xd0\x01\xae\x83\x9a\x0c\xde\xb3\xb6\xc1\x7a\x31\x06\x11\x7f\xb0\xbe\x86\xf1\x1d\x5f\x52\xfd\xae\x94\xfc\x0c\x29\xa5\x24\x92\xe2\xaf\x27\x4a\x91\xd0\x07\xd9\x29\xf5\x4a\x52\xb9\x92\x9d\x16\xc9\x25\x25\x91\xb4\x94\xfa\x48\x31\x29\x89\xe4\x66\x87\xd2\x77\xfb\x83\x2d\xa4\x94\x0c\x6e\xe6\xd3\x42\x11\x1f\x8f\x45\x22\xf9\x6d\x43\xe9\xb5\xd0\x22\x2d\xc9\xb1\xed\x69\xf9\xe5\xd9\x59\xc5\x85\x05\x12\xad\x70\x66\x87\x54\x58\x50\x2c\xf5\xce\x74\xfa\xc7\x45\x2e\x95\xdc\x24\x3d\x36\xf7\xc2\x4b\xa6\xd5\xff\x2b\x25\xf9\x46\xeb\x75\xf3\xf4\x87\x0f\x7f\x7e\xc7\x9e\x91\xf7\x5f\x75\xef\xc3\x6b\x57\x8e\x79\x60\x8c\x74\x13\x1d\x97\xf1\x68\xeb\x86\x2f\x1a\x8e\x3c\xf7\xcd\x91\x13\x0d\x3f\xae\x27\x45\xa3\xa6\xfe\x61\x6a\xcd\xe6\xb5\x8f\x0d\x59\xe8\xcc\xef\x71\x00\xac\xcc\xb7\x07\x64\x28\x80\x1a\x5f\x54\x77\x70\x99\xe2\x7a\x9f\x2b\x7c\x88\x10\x2e\x25\xb4\x8f\xa3\xa7\x49\x21\x19\x47\x3f\x38\xf3\xc2\xeb\x52\xb5\x2f\x7d\xeb\xbd\xa7\x3f\xf0\xa5\x73\x9f\x88\xeb\xc8\x2e\x82\x4f\x05\x50\x06\x33\xa1\x26\x93\x73\xaa\x4d\xa0\xbe\x26\xc0\xaf\xd7\x25\x50\x4f\x94\x6e\x0e\x57\x32\xea\x15\x1f\x9f\x7c\x85\x29\xf5\x9c\x37\xed\xb9\x3b\x98\x51\xaf\x84\xd2\x94\x16\xfc\x70\xe7\x94\x7a\xa5\x73\x59\xa4\x45\x4a\x7d\xa4\x3b\x29\x89\x74\x2e\x0c\xa5\xef\x0e\x48\x99\x6d\xc2\xa9\xc2\x3d\xec\xd2\x26\x94\xbe\x1b\x7c\x2d\x42\xe1\x8e\xae\x13\x54\x24\xdc\x67\x77\xee\x89\xa9\x57\x58\xd0\xc1\x75\x02\x7b\x14\x77\xe4\x0e\x50\x2e\x89\x79\x40\x53\x49\xd9\x8a\xdb\xbe\x7e\xfd\xcd\xaf\x96\xae\x8d\x3c\xd4\xd0\xf0\xc9\xdf\x11\x94\xa7\x1f\xf8\xfd\xd6\x4d\x7b\x1f\x58\xd2\xad\xd7\xf4\xd9\x2b\x6f\xbe\xff\xb6\x5b\x57\x93\x5b\x4e\xdf\x37\x62\xd7\x4d\x4f\xbc\xac\x6e\xbd\xf1\x85\xe1\x57\xfe\xf1\x8e\x3d\x1f\x1d\xf9\xe3\xdc\x25\xcb\xe7\x4d\x7a\xf8\xa2\xfe\xeb\xa5\x55\x17\x4c\xba\xa4\xac\xcf\x8a\xb1\x53\x67\xcd\x06\x09\xa6\xa3\x25\x74\x64\x36\x14\xc1\x0c\xd7\x3e\xa4\x06\x5c\xfb\x50\x98\x54\xbf\x2b\xab\x6d\x90\x3b\xca\x59\x9c\x09\xc5\x82\x09\xad\x53\xea\x95\xd6\xc2\x54\x28\x79\xe5\xc2\xbf\xe9\xc8\x83\x06\x08\xa5\x47\x5a\x24\xf7\xe9\xa3\xa4\x87\x6a\x83\xa9\x34\x4b\xf4\x38\x2b\x35\x94\xae\x24\xf7\x89\x14\x72\x01\xf1\x43\x46\xba\xdb\xef\xf4\x8a\xf2\x56\xe9\x59\x69\xf9\x05\x1d\x7b\xb6\xaa\x28\xef\x4f\x7a\x17\xc6\xbc\x5f\xde\xd9\xae\xa4\xb0\x40\x9e\xde\xf0\xc1\xc3\x9f\xdf\x7e\x66\xd2\xdc\x81\x97\xfe\x6e\xcb\xfb\xb3\x02\x29\xb3\xad\x83\x27\x6a\x7f\xbf\x72\xdc\xba\xd1\x97\xdd\x3f\x61\xc5\x7a\xfa\x89\x49\x92\x1f\x6d\x38\xfe\xc6\xcf\xdb\x32\x37\xb4\x5d\xfc\xd3\x9f\x77\x7e\xf9\xee\xda\x8d\x43\xe7\x5f\x3c\xf5\x85\x69\x35\x10\x8d\xfd\xd9\x74\x61\xfb\x7a\x7b\xac\xb1\x92\x55\xb6\xab\xa5\x6b\x90\x85\xf5\x53\x92\xcb\x5d\x63\xac\xa4\x47\xf7\xb8\x09\x4c\x30\xcb\xa1\xe6\x4c\xf4\x05\xfd\x2f\x18\xe0\x35\xd5\xf4\x85\x01\x43\x87\x5c\x54\xe9\xd8\x6c\x09\x2e\x68\xf8\x91\xdc\xc7\xa6\x83\x1f\xd2\xe1\x7c\x50\xd2\xca\x76\xb5\x70\xef\x9c\xc1\xe3\xb2\x5d\x29\x4e\xce\xc1\x97\x12\x08\x94\x44\x68\x6a\xbd\x42\xcb\x22\xbe\xd4\xfa\x48\x26\x29\x89\xf8\x68\x28\xbd\xc6\xdf\x22\xad\x8f\x63\xf7\x7a\xa5\x73\x97\xa5\x85\x08\x17\x1c\x22\x2e\x68\x7b\x61\xca\x81\x96\x3d\xe6\x9f\x7b\x41\xff\x7b\x38\x0d\x0d\x3f\xce\x20\xe5\xe3\xb3\xdf\x68\xf8\x1b\x3b\x31\x60\xe8\xbd\x03\x86\x0e\x03\xc7\x3f\xfb\x8a\x95\xb0\x4f\x40\x06\xc8\xe8\xf9\xff\x70\xf7\xef\x71\x4e\x55\xe7\xfe\x38\xbe\xd6\xbe\x25\x7b\x72\xdd\x3b\xf7\xc9\x64\x66\x32\x99\x1b\x04\x88\x24\x0c\x43\x84\x01\x41\xe5\x32\x5a\x44\x8a\x14\xa9\x22\x22\xa2\xa2\xa0\x88\x88\x48\x11\x75\x6a\xf1\x82\x45\x40\x11\xef\xa8\x88\xd6\x22\x67\xed\x4c\x18\x11\x29\x5e\x10\xf1\x7a\xa8\x5a\x86\x63\xd5\x7a\x3c\xd6\xda\xdd\x52\x6b\x2f\x1f\x8f\xc2\x64\xf3\x7b\xad\xb5\xf6\x4e\x76\x32\x09\x83\xed\xe7\xf7\xf9\xe3\xfb\x6a\x61\x46\xd0\xc9\x7a\x9e\xf5\xac\xe7\xfe\xbc\x1f\xe8\x13\xa1\x6f\x01\xbb\xbf\xaf\x8f\xe5\x98\x4d\x0b\xe0\x67\x5b\xb4\x7b\xb5\x3d\x8f\xe1\xb3\x2e\x85\x7b\xb8\x08\xfb\x05\xc9\x4b\x54\x53\xcf\xc7\xaa\x12\xef\x02\x5f\xbe\x35\xa1\x88\x79\x8f\x07\xb6\x45\x7d\x4b\xd9\x67\xfb\x66\xb2\xcf\xc2\x3d\x1b\x36\xc0\xcd\xeb\xd7\x83\xd2\xcf\x6a\x6f\x13\x61\x1b\xfe\x2c\xae\xaf\x8f\xdd\xff\xd5\x63\x70\x02\x5c\xbc\x45\xab\x5b\x40\xf8\x12\x3a\xfe\x39\x7b\x06\xff\x36\xa8\x01\x2d\x60\x11\xa0\x2a\x29\x64\x53\x51\x53\x22\x5b\xa7\x33\xa8\x35\x81\x22\xbd\xd9\x06\x3d\x29\xd3\x10\xb1\xc6\x15\x87\x5b\x45\x0d\x34\xb7\xc0\xcb\x2a\xb6\x79\x8a\xc3\x29\xc9\xdd\x4c\xa8\xae\x09\x2b\xa4\x06\x09\xc9\x69\xe4\x97\x33\x55\x1e\x91\xc4\x1d\xa1\x3a\x49\xce\xf0\x8e\x9a\x74\x9a\x18\x0a\x80\x85\x2f\x6f\xb0\x9d\x30\x02\x63\x38\x7a\xcd\x1b\x73\xcf\x88\xfc\x05\x87\xf6\x1e\xda\xfb\xdb\xd6\x73\x57\x5c\x32\x7e\xdd\xd9\x73\x17\x9d\x51\x73\xf3\x0d\xd3\x1e\xb8\x68\xf3\xea\x53\x4f\x3f\x23\x3d\x6a\x12\xbf\xe0\xd2\x5f\x3d\xdb\x79\xed\x82\x4b\xcf\xbb\xfa\xc7\x0d\xed\xcb\xef\x9b\x76\xc1\xb4\x69\x6d\x97\x2c\x6c\x1d\x76\x6c\xf3\x1d\x67\x9e\x71\xfa\x94\x09\x84\xc6\xe5\xc7\x3b\x85\xdd\x7c\x0f\x18\x09\x4e\x03\x8f\x01\xaa\x6d\x5b\x2d\x2a\x1a\x91\x50\x12\x16\x15\x0b\x80\x3d\xa5\xa4\x05\x15\x45\x93\x68\x6c\x42\xa9\xc6\xb1\xe8\x78\xf2\xc4\x86\x48\x2a\x1a\x42\xe9\x6c\x97\x55\xd4\xee\x56\x46\x63\xed\x2b\xa9\x4a\x44\x56\x51\xad\x5b\x69\xc4\x96\xd0\xad\x2a\x13\x60\x5c\x19\xdd\x2e\xc9\x3d\x5c\x75\xab\x67\x44\x62\x2c\x66\x42\xad\xa4\xb8\x5d\xe9\xb4\xd2\x88\xe3\x4f\x7b\x74\x78\x92\xbc\x44\x4f\x42\x92\xd1\xf0\xb4\x32\x36\x2d\xc9\x3d\x56\xe0\xf6\xbb\x1a\x71\x94\x8a\xaa\x25\x14\xa1\x6e\x5d\x63\x34\xc9\xc9\x98\x31\xb1\x86\xe6\x96\x18\xf9\xd2\x36\x82\x38\x06\x01\xd6\xe7\x25\x1a\x89\x69\x8c\x35\x70\x8c\xcf\x0d\xa2\xc9\x76\x9f\x10\xab\x07\xd0\x9b\x4a\x86\x21\xe6\xdd\xf2\xc3\x70\x2d\x84\x87\xe1\xb9\xcf\x9f\xbf\xe5\x8a\xf3\xae\x73\x56\xb5\x6c\x9a\xbf\x79\xc7\x95\x6f\xdc\x7c\xa6\x72\x7a\x60\xf5\xf9\x8b\x37\x6a\x7f\xdb\xf1\xb1\xf6\xc2\x0e\x38\x16\x26\x7e\xf3\xfb\x37\xbe\xd6\xee\xd5\xae\x62\xd2\xaf\xbc\x2b\xdb\xa7\x4c\xbd\xe5\x5e\xa6\x03\xb2\xf0\xfe\x4f\x7b\xb4\xcc\xe1\xb5\x47\x7e\x7a\xc9\x39\x3f\xbc\xe8\xed\xcc\x6d\x1f\x2c\x0b\x05\xb5\x21\x7e\xf4\xfe\x73\xdd\xd0\xb9\xfe\x79\xed\xb9\xcf\xb4\xf7\xb5\x17\x67\xdd\x35\x03\xae\x83\xab\x8f\xc2\x36\x08\x7c\x19\xbd\x4e\xc1\x87\xf9\x3d\xc0\x02\x1c\x60\x08\xf5\xf4\x10\x9b\x22\xc6\x20\x2b\x58\x01\x74\xc4\x15\x01\xdb\x04\x67\x82\x44\x4d\x0a\xb4\x4a\x32\xb2\xa5\x4f\x19\x3e\x1c\xa6\x60\x8c\x8d\xb2\x9e\x28\xdb\x22\x58\x98\xd1\xdb\x98\x53\x5f\x42\xb9\x3d\x3b\x8e\xc0\x83\x5b\x27\xd6\x46\xf9\x3d\x47\xcf\x80\xfb\xb5\xd1\xcc\xe5\xf0\xc5\x8f\x6e\xb8\x84\xc4\xcf\x07\x00\xe0\xf6\xf3\x3d\xc0\x05\x82\x20\x0a\x2e\xd3\xfd\x4a\xb7\x4d\xa5\xb6\x27\x6a\x53\xb3\xa1\x20\xf9\xc8\x10\xf6\x17\x1a\xc8\x75\xba\x7d\x2a\x0a\x25\x91\xdb\x4d\x9e\xb5\x3d\xa0\xa2\x08\xb6\x16\xbc\x5f\x55\x62\x30\xae\x44\xdc\xd8\xd1\xb6\x62\x79\x0d\xba\x89\xbe\x44\x21\x49\xb1\x8a\xe9\x34\x8a\xca\x88\xc7\x0e\xa7\x14\xad\xe7\x0a\xee\x59\xac\x29\x4a\xed\x68\xb4\x8d\x7e\x13\x87\x07\xe0\xe3\xb0\x19\xf2\x3f\xbf\xfd\x17\x8f\x69\xff\xfc\x5a\xeb\x81\x2d\xe8\xd9\x6c\x56\xfb\x12\x3a\xb7\x3f\xfc\xcb\x17\xfe\xce\xf7\xfc\xc7\x8b\xb7\xfe\x22\x54\x15\x41\xeb\x5f\xfb\xf8\xe1\xdb\xef\xec\x5a\xf5\xe0\xe2\x5b\x6e\x58\x48\xdf\xec\xaa\xe3\x47\xb8\x83\xc4\x06\x74\x80\x8c\x8f\x44\x08\xac\xee\x1c\x88\x6c\x21\x42\x08\x90\xb0\x00\x28\x2e\x9f\x24\xe3\x67\x26\x4a\x19\x60\x91\xf0\xcb\xe2\x70\x50\x45\xd4\x7a\x63\x2a\x19\xb0\x34\xc7\x1a\x80\xe4\x06\xa9\x64\xbb\xcf\x09\x63\xf5\x60\xd5\xd3\x70\xdc\x7f\xfd\x71\x7b\xe7\x7f\x3c\x72\x44\xfb\x3b\x14\xfe\xfe\xf0\xbe\x0b\xb7\x5f\xa3\xfd\x4a\x7b\x92\xf9\xe4\x7f\xe0\x8c\x5d\x33\x1f\x9e\xa6\xbd\xa6\x7d\xa5\x7d\xa1\xbd\x7b\xea\x96\x86\x10\xbc\x03\xdf\xe9\x01\x00\xf8\xd9\x7c\x0f\xb0\x02\x37\x18\xa5\x73\x59\x34\xb8\xec\xb6\xa9\x10\x49\xe4\x54\xa2\x4f\x45\xa2\x5b\xb1\x63\x8d\x10\x50\xb1\x51\x02\x8a\x1b\xbb\x88\x06\xdb\xf0\x49\xa2\x2d\xd8\xe3\x05\xd1\xd8\x01\xf8\x2a\x3c\x0f\xfe\x44\x5b\xa6\xad\xfb\xf4\x00\x33\x5d\xfb\x8b\xf6\xa7\xaf\xf9\x1e\xed\x0e\xed\x59\x6d\x93\x76\xcb\xa3\xcc\x99\x30\x00\xeb\x08\x4f\x0e\x00\xc0\x7e\x4b\xe2\x92\x49\xc6\xa7\xb3\xfa\xa7\x73\xac\x9a\xe5\xa9\x58\xf1\x98\x3d\xf6\xfc\x41\x70\x28\x4b\xc2\x5c\xd1\x26\xc6\x11\x93\xa4\x31\xad\x1e\xe0\xd1\x20\x96\xfe\x3a\xc0\x0e\xcf\xad\x61\x66\xe4\xb6\x33\x2b\xf8\x9e\x27\xb4\x51\x5b\x72\xdf\x3c\x01\x8a\x3e\x57\x04\xa7\x99\x62\x3c\xf2\x99\x56\x9e\x7c\xa6\x15\x7f\x66\x55\x99\xcf\x64\x45\x3d\x88\x56\x6c\x25\x1f\x48\x3f\x6e\x7a\x6e\x07\xdf\xf3\x44\xee\xe8\xe3\xb9\x8d\xf9\x7b\xe7\x47\xf3\x6f\x83\x30\xb8\x41\xf7\x7b\x5d\xb6\xc2\xbd\x67\x3d\xde\x10\x87\xfd\x5e\xfc\x79\x35\x54\x04\xfc\xf9\x14\x99\xdf\xa7\x66\x24\x92\xda\x95\x3c\x62\x9c\x3a\x42\x76\x49\xce\x70\x62\x08\x4b\x84\x5f\x52\x2c\x02\x16\x68\x17\xf6\x73\xfd\x69\xc5\xeb\x91\x64\xc5\x0e\xd2\x58\x6c\x90\xa5\x8c\xc8\xd0\x8b\x4a\xb6\x4b\xd1\xb6\xa8\x44\xc5\xa6\x07\xfe\x48\xfd\xd3\x5b\x13\x5f\xd9\xa5\x1d\xd3\x7e\x0b\xab\xa1\x63\xe3\x5a\xed\x25\xf8\xdd\x75\x5f\x3f\xaa\x65\xb4\x0d\xcc\x47\x5f\xc0\x99\x3b\x67\x6e\x99\x41\x84\xe7\x77\xda\xfb\x31\x98\xd9\x9a\x4b\x35\x35\xc3\xb5\x94\x8f\x7c\x13\xb9\xbf\x71\xba\x46\xb0\x50\x8d\x80\xf8\x54\x96\xad\x22\x9c\x64\x0b\xb7\x67\xf3\xa9\x88\x49\x22\x9b\x1b\x7b\x8d\x88\x4b\x2a\x16\x9f\x9a\xbf\xb7\x94\x14\x95\x70\xcc\x19\x95\x0e\xec\x62\xbe\xda\xb5\x2b\x27\xf3\x3d\xb9\x4d\xcc\xc2\xa3\x9d\xcc\xb3\xb9\x99\x7a\xce\x00\x00\x66\x5e\x91\xbc\x40\x1e\x7b\xd0\x19\x9e\x5c\x1f\xaf\x22\x4b\x92\x7c\x18\x43\xae\x2d\x23\x32\x79\x39\x11\x92\x19\x86\x84\x3b\x0c\x10\xc9\x67\xeb\x9f\xdb\xd6\x2e\xb5\xb4\x45\x7d\x16\x29\xe0\x9b\xbe\x7d\x3b\xe3\xde\xbe\x7d\x61\x0b\xb7\x61\xd0\xc2\x85\x83\x8e\x2d\x6e\x59\x08\xe0\xf1\xb9\xda\x4a\xb8\x8c\xe4\x87\x86\x82\x8c\x80\x69\xb3\x25\x14\x86\x6a\x3a\xc4\xf7\x2a\x56\x1f\x4d\x13\x29\x8c\x4d\x92\x91\x23\x8d\x04\x6a\x01\x2d\xc4\xbd\x94\x52\x12\x36\x74\x2d\x5b\x26\xfd\x60\xfe\xfc\x17\xf6\xef\x9a\x73\xea\x41\xef\x8a\x6b\xf9\x1d\x47\x2f\x7e\xbd\x37\x6c\xc8\x22\xf7\x4f\xbe\x07\xd8\xc1\x29\x3a\x0f\xad\x79\x1e\x42\xe4\xa0\x22\x41\x18\xa7\x38\x0d\x5f\x5b\x61\xab\xd2\x69\xca\xb4\x76\x98\x12\x61\x0c\x5a\xa4\x03\xbb\x6e\x62\xc4\xc3\xb9\x5f\x31\xb3\x3f\xcc\x7d\x77\x1f\xdf\x93\x4b\xdc\xc5\x4c\xcc\x75\xf5\x1d\x60\x76\x77\xe5\xde\x2c\xc8\xbd\xc6\xf7\x00\xde\xd0\xe0\xf8\x76\xf4\x5c\x80\x40\x3e\x89\xf5\xa9\x19\x96\x48\x3a\xcb\x8b\x71\xc5\x52\xb8\x1c\xdf\x81\x5d\xcc\x6a\xbe\xe7\xe8\x57\x5b\xf3\x3f\x4b\x58\xc9\xf7\x00\x0f\x38\x5f\xff\x59\x16\x47\xca\x74\x72\x2f\xf9\x79\x1e\x59\x45\x1e\x72\xdf\xc4\x87\xc5\xb1\xa5\x07\x13\xe0\x72\xa7\xd3\xc8\x2a\x75\x33\xbc\x03\x7b\xed\xc8\x42\xdd\x5a\x4a\x5e\x86\xb5\xb9\xd2\x94\xc0\x28\x4c\xc1\x28\xc9\x44\xc4\x60\x0c\xc6\xfc\x3e\xe9\x00\x74\xc3\x7d\x56\xf8\x36\x74\xf6\x38\xad\x5a\xf0\x7e\xad\xd6\xea\xe2\x7b\x8e\x4d\xe7\x76\x1c\xed\x64\xbb\x36\x7d\x79\x0c\xf0\xcc\x96\x3f\xf7\xdd\xa1\x9f\x91\x9f\x4a\xce\x38\x5d\xe7\xad\x5d\x3f\x61\x55\xe9\x09\x45\x6c\x33\x64\xd3\x09\x71\x04\x89\x43\x7c\xc6\x91\x4e\x23\xbb\xac\xf0\x82\x71\x3c\x85\x77\xea\xdc\x0f\x88\x30\xd5\xcc\xe0\x4b\x8e\xc1\x58\x00\x1f\xee\xd0\x50\xf8\xdf\xe0\xb8\x95\xb1\x6f\x3f\xdc\xf7\x37\x2b\x6f\xe7\x7b\x26\xe5\xaa\xb5\xa5\x41\xd8\x32\x81\x4d\x1f\xed\xe4\xf6\x9e\xdb\xf3\xb3\xbe\x83\x58\xf7\x62\xbd\xb0\xaf\x34\x67\x64\x33\x72\x46\x45\x16\x21\x9f\x33\x0a\x98\x72\x46\xac\x98\xcf\x19\x01\x81\xe6\x8c\x80\xae\x88\xeb\x81\x39\x67\xb4\x0a\x5e\x04\x27\xc1\xb1\x70\x9e\xf6\x88\xf6\x8a\xf6\x2b\xed\xb1\x57\xbf\x39\xf2\xe7\x7f\xfe\xfd\xcf\x5f\x7d\xc3\x7c\x0a\x2f\x85\x77\x68\x4b\xb4\xc7\xb4\xc7\xb5\xc5\xf0\x2e\xb8\x40\xfb\x9d\xf6\x6b\x38\x04\x36\xc3\x26\x38\x48\xfb\x00\xe8\x36\x82\xbb\x9a\xe8\x4a\x19\x4c\x30\x6b\x4b\xd9\xa6\x66\xad\xf4\x8d\x5b\xb1\xa9\xf0\xe4\xb5\x65\x55\x12\x5b\x0b\x27\x8c\x2b\x9c\x9f\x38\xd9\x40\x91\xab\x24\x19\x71\xba\xb5\x90\xbc\x5c\x34\x16\xd2\xc3\x54\x6c\x55\xbb\x98\x26\xed\x3f\xb5\x3f\x3d\xb3\xf1\xb7\xaf\xf5\xbc\xb2\x9b\xef\xd1\xa6\xff\xf7\x5f\x73\x07\x98\xc3\x77\x3f\x7c\xf7\x5a\xc2\x2b\x6d\x2b\xe1\x95\x0b\x84\xc1\x0f\x41\xc6\x81\x79\xe5\x31\x78\x15\x2a\xa8\x4e\x77\x40\xc5\xf6\xdf\xaf\xf3\x0a\xeb\x4b\xbf\x5b\x92\xbb\x59\x9b\x43\xc4\x52\x26\x48\xa8\x0a\x7b\x69\x0e\x49\x46\x22\xb1\xff\xc5\xac\x63\x2c\x30\x0a\x2d\x15\xd8\xf7\xbb\x77\xe0\x1c\xed\x5b\xed\x8b\x54\x25\x1e\xfe\x59\xfb\xf9\x44\xed\x5e\xd8\xc9\x94\xe1\x24\xe5\xe3\x47\xe4\x9d\xfb\xc0\x8f\x8b\x5f\xba\xe2\xb3\xa9\x59\x9b\x83\xb0\xd2\x86\x59\xe9\xcf\xbf\x7a\x47\xd2\xb0\x05\xd8\x8f\x09\xe8\x06\x40\xa9\xb2\xa4\xd3\x88\x97\x90\x98\x06\x8a\x03\xeb\x1d\x4b\x1a\xf9\x24\x93\x17\xe3\xe6\x61\x0c\x46\xcd\x3c\xde\x08\xdd\x90\xd7\x3e\x82\xeb\x0f\x6b\x8f\x6a\x9f\x7c\x94\xd9\xba\x6d\xf7\x7b\x7c\xcf\xc1\x5f\x6b\x9f\x5c\x9a\x5b\xc2\x5c\x90\xdb\xca\x7c\xbb\xf6\xce\x3b\x57\x93\xb7\x7d\xf9\xf1\x23\x1c\xc7\xbf\x0d\x9a\xc0\x02\x90\x69\x24\xb9\x1a\x9b\x9a\x91\xf0\x51\xfd\x2c\x0d\x51\x9d\xbd\x4a\xc8\x97\xaf\x4c\x46\x7d\x34\x3e\x0d\xd1\x48\x14\x59\xa4\x9d\x9c\x4d\xf2\xd7\x36\x62\xae\x47\x65\xc5\xe3\x25\xe9\x98\x46\x9a\x8e\xf1\x4b\xdd\xd0\xe9\x8d\xe2\xbf\x93\x64\xe4\x31\x65\x65\x46\x0c\x83\x2d\x38\x58\x37\x3c\x1c\xc1\x87\x23\xf3\x5a\x06\xbb\x63\xf5\x97\x5f\xf8\xc9\xdc\xad\xdb\xc6\xdc\xbd\xee\xed\x1d\x10\xbe\xff\xd1\xae\xf4\x9e\x27\x6e\xdd\x98\x5e\x7d\xfb\x93\x5b\xce\xd6\x8e\x7c\xa3\xf5\x0d\x47\xad\xc3\x6e\x5a\x3c\x65\xce\xf4\x11\x9d\x6f\x3e\xf6\xcb\xb7\xa6\x3f\x3a\xf5\x9a\x4b\x27\x5f\x34\x35\x39\x66\xc9\xc6\x05\x2f\x7d\xac\xe7\x76\xb9\x0b\xf8\x1e\x5a\x11\x16\xcc\xb9\x0c\xc4\xd2\x82\xb0\xd0\xab\xf0\x3e\x35\xc3\x93\x54\x25\xcf\x8a\xf1\x8c\xc0\xe7\x53\x95\x85\xc8\x0c\xab\x24\x2f\x37\x59\x3b\xf5\x05\xde\xfb\xc4\x13\x47\x8f\xf0\x5e\xc2\xb7\x5d\xc7\x8f\xf0\x75\x7c\x0f\x90\x40\x3b\xc8\xb8\x30\xdf\x04\xdd\x9b\x22\x0a\x47\x36\x54\x2c\x62\x75\x85\xe3\x53\x49\x81\x47\x64\x25\x19\xb9\x48\xfc\x89\x0d\x46\xde\x72\x60\xa9\xdc\xf5\xc2\x4b\x2f\xef\xdc\xf7\xbc\xf6\xbe\xf6\x4f\xed\x7f\xb5\x8f\x19\x2b\xbb\xa3\xef\xec\xee\xd7\x5e\x7d\x9e\xcd\xf4\x4d\x3d\xaa\xfd\x0f\x8c\xe6\xfb\x84\xb8\x77\xf9\x1e\x50\x05\xa2\x20\x53\x85\x69\x23\x25\x6f\x4b\x0a\x62\x83\x65\xc7\x8f\x10\x18\x8f\x50\x4a\x41\x7f\x60\x64\x3b\x76\xcc\x5f\x81\x53\xc6\x45\x42\x67\xc0\x49\xfb\x72\xdf\xbc\xc0\xf7\xf4\xcd\xcc\xdc\x7d\xd3\x7e\x76\xdb\xd1\x4e\xfc\x33\x43\x00\x58\x66\xf2\x3d\x20\x88\xa3\xc7\x20\x96\x58\x77\x8a\xfc\xd8\x0c\xb4\x38\x53\xa9\x14\x44\x21\x42\x12\xf4\xab\x08\xd2\x17\xef\xf2\xab\x4a\x35\xcd\xda\xbd\xf2\xdd\xd7\x63\x48\xd6\x0e\xb8\x51\xf0\x65\x27\x82\x6e\xc4\xbc\x0c\x10\x33\x0c\x2a\x4c\x50\x4f\xd6\x39\xa1\x9e\x68\x04\x41\xec\xd7\xd8\xbc\x44\xef\x7b\x52\x1e\xfd\x7c\xf8\x8b\x27\x05\x63\xb0\xb9\x45\xb0\xc0\x58\xe8\xe5\xcf\x87\x05\xfd\xa3\x20\xb3\x17\x3a\x46\xd4\xb8\xdb\xff\xe7\x65\x6d\xe5\x6e\xed\xf3\x71\x36\xf7\x48\xed\xc8\x6e\xbe\xa7\xaf\xeb\x3f\x9e\xdb\xba\x8f\xbd\xb6\x6f\xcd\x73\xdd\x77\xfe\x86\x5d\x79\xb4\x93\xdd\xdb\x7b\xd6\xd2\x6c\xdf\x64\xc2\x23\x2b\x00\xdc\x33\xc4\x7f\x68\x2e\xbc\x40\xc6\xb0\x58\xf6\x04\x71\x0a\x14\x06\xeb\x78\x8e\x5a\x58\x11\xd2\xff\xc7\x44\x68\x85\x7f\xd0\xd2\xef\xc2\x05\xf0\x8a\x57\xb5\x31\xf0\xcb\xf7\xb4\x55\xda\x72\xe6\x28\xb3\x27\xb7\x8f\xe9\xc8\x4d\xce\x31\xcc\xca\xdc\x6d\xfa\x3d\xac\x21\x3e\xf5\x29\x20\x63\xc9\xdf\x03\x9b\x82\x48\x24\x79\x4d\xc1\xa7\x2a\x55\x58\x43\x59\x24\x19\x31\x98\x74\xfa\x0d\xbe\x16\x11\xa6\xa0\x14\x93\xde\x84\x2b\xe1\xaa\xd7\xb5\xd0\x0b\x7c\x4f\x6e\x38\x73\xb0\xef\x96\xdc\x9b\x4c\x02\x40\x30\x15\x00\xee\x0c\xa2\x8b\x87\x19\x36\xd7\x88\x21\x58\xea\xb0\x12\xaf\x54\xb1\xd0\xac\xad\xc2\xb1\x12\xf5\x00\x53\x6d\x30\xda\x16\xf5\xc1\xa8\x6f\x2a\xcb\xe4\xfc\xec\x9b\x7d\x1a\x1b\xb8\x8b\x5b\xb3\xf5\xae\x63\x2b\x74\x7b\xbe\x55\xdb\xc3\x5c\x4d\xde\x46\x3b\xd0\xdd\x61\xab\x8a\x40\x42\xe1\x45\x92\x97\x40\xa0\x37\x6b\x21\x35\x19\xec\x8a\xf0\x1e\xd5\xf8\x27\x36\x69\x3c\x0c\xdd\x15\xde\x0a\xdf\xd6\xbe\x80\x61\x6d\x8f\x70\x74\xe3\xd1\xa1\xf7\xea\x35\x95\x2f\x8d\x9a\x0a\x6b\xf0\xc4\x54\x53\xc1\x57\xec\x55\x98\x86\x8c\x5e\x52\x01\x10\xa4\xb4\x3d\x50\x23\xe7\x39\x4d\x8f\xea\x59\xab\x8a\x2c\x09\x05\xe8\xe7\xb1\xf4\x22\x96\xe4\x91\xf0\x21\x04\xb7\x02\x3d\x2a\x82\x09\x24\xb8\x8d\x83\x59\x8c\x5c\x4a\x20\x4a\xfc\xdd\x68\x0a\x86\xb5\x2f\xe0\xdb\x5a\x1b\xe2\x3f\xd8\xf8\x9d\x40\x3f\x67\x2a\x13\xe3\x26\xf2\xaf\x00\x01\x48\x40\x77\x85\xf4\xb4\x26\xa9\x82\xe0\x9b\x9f\x0a\x33\x0b\xe0\x7f\x6f\xd1\xd6\x69\x2f\x30\x31\xf6\xd1\xbe\x79\xcc\xa7\xb9\x28\x00\xf0\x78\x9f\xb6\x9f\x5d\x7f\x7c\x32\x60\x41\x00\x20\x36\xa1\x00\x41\xc5\xbf\x4c\x84\x59\xa2\xbe\x28\xc7\xde\xd7\x77\xe5\xae\x2e\x00\x61\x17\xf7\x21\x5b\x27\x44\x81\x08\x5a\x01\xb2\x90\xfa\x99\x83\x8b\xeb\x81\x46\x96\x77\x82\x2a\x8e\xc6\x15\x0a\x63\x21\x37\x78\xca\x70\xd8\x96\xaa\x85\x01\x5f\x6c\x18\x84\x5d\x87\xeb\xaf\x4f\xac\x38\xab\x5b\xb0\xfb\x26\x3c\x3f\x32\x34\xe6\x25\x62\x9f\xe7\x1c\x3f\xc2\x1e\xe6\x2e\x00\xd5\xa0\x09\xac\xa4\xf9\x67\xf2\x54\x95\x5a\xab\x9a\x71\x42\x2c\x23\x56\x35\xcb\xc4\x82\x4e\x47\x5c\x61\x84\x7c\x82\x31\xec\x53\x51\xd8\x4d\x7a\x44\xd8\xa4\x22\x39\x54\x24\xb9\x15\x8f\x4b\x45\x9e\x04\x51\xe5\x61\xfc\x0a\xaa\x6c\x38\x3c\x96\x32\xce\xa0\x05\x07\x1c\x1e\x19\xf9\xd2\x40\x61\x82\x92\x8c\xbc\x58\xcb\xa3\x2a\xd2\xa8\x60\x23\x36\xb4\xa9\xbd\xb8\xd0\x21\xc5\xf4\x04\x07\x4d\xb5\x76\x40\x8b\x13\xce\x61\x5c\xbb\xaf\x5a\xfe\xa3\x87\xce\x68\xff\xe1\x6b\x73\x0f\xbc\xda\x15\xb3\x4e\x7f\xf2\x27\x4f\xec\x7a\xf1\x8a\x8b\xee\x7f\xee\x89\x5f\x3d\x07\x87\xc3\xa9\x6e\xcb\xf8\x55\xcb\x47\xd4\xaf\x19\x92\x44\x2f\xe7\xbc\x0f\x5f\x36\xe5\xd9\x07\x66\x5e\xf0\xe4\xa6\x4b\x2c\x96\x85\x98\xde\x1d\xc7\x8f\x70\x2b\x05\x2f\xf0\x82\x28\xb8\x42\xf7\x47\x9c\xa4\xec\x24\xaa\x19\x2b\xa6\xb7\x16\x7f\x53\x4b\x4a\x1b\x50\x8c\x1b\xe9\x01\x9f\x83\xf8\xd0\x5e\x97\x8a\x7c\x6e\x25\x0c\xe3\x38\x1c\x21\x99\x01\x9f\x57\x92\x33\xbc\x40\x82\xec\xb0\xa4\x58\x9d\xd8\x56\xd5\x06\x25\x39\x2b\xd8\x24\x99\xa7\xc5\x28\xac\x8e\x2d\xa9\x91\x86\x5b\xd0\xdc\x12\x13\x2c\x1e\x23\x85\x8c\x0d\xd5\x8e\x6c\x55\xd5\xd5\x5f\x7c\x78\xe4\xeb\x43\x57\xef\x68\x77\xd6\x09\xa9\x8d\x4f\xdf\xbb\x7e\xc3\xfd\xdb\xee\x11\xbc\xda\xcf\x96\x2c\xd9\xaa\x1d\xd2\xfe\xa9\x7d\xad\x1d\x9e\x76\xce\x0d\x1e\x26\xf6\xd9\x2b\x1f\xbe\xfb\xeb\x5f\xef\xf9\x6f\x2a\x83\x4b\x8e\x1f\x61\x37\x72\x73\x80\x1f\x74\xe8\x79\x71\x52\x3d\x84\x34\x1c\x87\x28\x60\xf8\x03\x4a\x90\xe4\x06\xbc\xa5\xb9\x01\x56\x0f\xf4\xdc\x20\x95\xf4\x1b\x96\xd3\x9f\x22\xf9\xa3\x06\xb0\x04\xda\xfe\x77\xda\x23\xa9\xf6\xbb\xe6\x6d\x7b\xf4\xd1\x87\xd6\xaf\xbd\xf6\x17\x7f\xd1\xbe\x65\xea\xa0\x17\xc6\xa3\xd5\x9b\x46\xbc\x77\xf0\xc0\x07\xa7\x6d\x19\x0d\x63\xf9\x7a\x46\x87\xe0\x05\x1e\x50\x0f\x2e\xa5\xbe\x56\x46\xc2\x47\x0a\x88\xfa\x91\x6a\xf1\x03\x8c\x92\x23\x79\x7d\x2a\xf2\x12\x5b\x86\xaa\x93\x8a\xcd\xa1\xe2\xe0\xce\xe1\x56\x91\x23\xa1\x34\x60\xc3\xe6\x95\xe4\x9d\x3c\xeb\x92\x02\xb5\x7a\xc7\x82\x80\x79\x1b\x90\xe4\x2c\x10\x78\x97\x53\xaf\x64\xc8\xa9\x64\x20\x35\x0c\x12\x47\xba\x25\x26\xc4\x1a\x18\x8f\x2e\x32\x84\xb7\x4b\xfe\x72\xf8\x93\xe5\x0e\xb6\x2a\xbb\x3e\x6c\x5d\xfa\x79\xef\x91\xdd\xf7\xff\x7c\xeb\xfd\x0f\x6c\xbd\x6b\x33\x13\x83\x0e\x38\xec\x09\xef\x0a\x1f\xec\xf9\xee\xc8\xc6\xa7\x61\x2b\xb4\xbd\xf3\x7e\xf7\x3b\xd1\x2f\xf6\x7d\x62\xd0\x12\xe6\xe6\x00\x2f\x08\x63\x4f\x46\xc6\x64\xd8\x0c\xce\x86\xac\x6a\xd6\x67\x95\xf3\x79\x77\xea\x42\x5a\x7d\x2a\xf2\x25\x8d\xde\x2a\xc1\xaf\x7b\x91\x56\x12\x95\xc8\x98\xd7\x82\xa4\x57\x97\x6c\x32\xb1\xda\xc8\x2a\x21\x67\x1a\xf9\x64\x9a\xf8\xc4\x57\x20\x47\x60\x94\x38\x34\x24\x37\xd3\x00\x3c\x51\x92\x6b\x5f\x02\x85\x4f\x0f\x7e\x93\x73\xf3\xd9\xa7\x66\x3d\xba\xf0\xc7\x5b\x16\xfd\xaf\xf6\xe5\x5e\x26\xc1\xdc\x79\xd3\x2d\x9b\x98\x08\xb4\xc2\xb4\xf6\x7f\x7e\xbf\xe8\xc5\x57\xeb\x86\x3e\xda\x52\x0f\xe3\xf0\xc6\x07\xb7\x6c\x23\xf2\x51\x07\x00\x1b\x12\xea\x80\x0f\x5c\x4c\xe5\x23\xe3\xc2\x14\xc8\x16\x15\x81\x24\x92\xdd\x0a\xb4\xab\x19\x06\xd2\xd8\x54\x10\xa9\x07\xe9\x25\xc5\x7f\x8f\x43\x45\xce\x64\xc6\xe3\xc5\xef\xc1\x23\x89\xf1\x8c\x97\xb4\x2d\x79\xb1\x43\x13\xc0\xd2\x64\x73\x51\x6f\x58\x90\x90\x95\x94\x70\xda\x49\xb1\x84\x4a\x51\x04\x52\x67\xa7\xee\xe5\xff\xe8\xb9\xe2\xaa\x53\x2e\x9c\xf8\xe3\x59\xd0\xa7\xfd\x39\xcb\xee\x9d\x31\x76\xdc\x1b\x6f\x34\xdd\x5d\x7b\xc3\xad\x93\xd6\xf6\x4d\x60\xf7\x12\x7e\x6b\x5e\xae\x83\x9b\x03\xc2\xa0\x15\xac\xd0\xb3\x1d\x75\x56\x35\x63\x81\x20\x4e\x99\xde\x2c\xaa\xd8\xce\x4a\xf8\x8c\x83\x08\xc3\x6b\x7c\x2a\xaa\xa1\x39\x3b\xa1\x21\x99\x54\x44\x07\xc9\x35\x59\xdc\x44\xd9\x0f\x86\x71\xa5\x26\x1f\x8e\x79\xa5\xe7\x79\xd6\x2e\x05\x42\x75\xcd\x24\xdd\x1a\x92\xc8\x0d\x28\xcd\x76\x49\xee\x06\x02\xef\x37\xcb\x53\xbb\x1e\x7a\xb7\x51\x49\x6a\x2f\x23\x57\x7f\x7b\xef\xd3\x15\xb6\xe0\xba\xbf\xf6\x7d\xfd\xd0\x96\xff\xb3\xf6\x49\xc1\x7a\xf5\x17\x87\xfe\xba\x7b\xe3\x86\x6d\xf7\x6f\xfe\xc5\x9d\xf7\x33\x31\x28\xc2\xe4\xb6\x0d\xc7\xb6\x1e\xf9\x6a\xe2\xb6\x99\x5b\xd7\xc7\xd7\x3c\x05\x07\x41\xfb\x3b\xbd\xdd\xaf\xc7\x3f\x7e\xe3\x23\xfa\x76\x77\x00\xc0\x9d\x2d\x78\x81\x1f\xfc\x48\xf7\x29\x1c\xa9\x8c\x48\xae\x47\x54\x33\x22\x29\x74\x8b\x44\x0f\xd1\x57\xec\x27\x7a\x08\xf9\xa9\xbb\xe4\x70\x90\x37\xad\xf8\x01\xc9\xa6\x21\xa7\xa4\x08\x24\xb0\x93\x49\xa0\x29\xa4\x0b\xba\xc7\x50\xaa\x12\xd5\x37\xd2\x8e\x6c\x95\x7d\x78\x76\xc9\x1b\x6f\x65\x96\xaf\x7e\xfa\x21\xc1\xab\x8d\x9a\x7d\xda\xb4\xd9\x2f\xbd\x9f\x6b\x63\xf6\xfe\xac\x6b\x77\x2f\x09\xfa\x19\xb0\x05\x00\xb8\x94\xff\x82\xf4\x66\xa6\x41\xc6\x8e\xa5\xc7\x01\x49\x83\xa6\xc2\x72\xaa\xde\x9d\x89\xec\x49\x45\x70\xaa\x8a\xcb\xa1\x92\xaf\x38\xe2\x70\x01\x23\xcc\x2c\x6e\xac\xc2\x3e\xea\x96\x8e\xa1\x83\xc7\x8d\x1b\x3c\xb4\xc3\x99\xe5\x97\x8e\x19\x39\x72\xcc\xe8\x51\xa3\x8e\xbe\xc1\x75\x1e\xeb\x01\x80\x39\xbe\x4e\xf3\x92\xcf\x74\x80\x10\x38\x13\x64\x04\x5d\x32\x19\x51\x45\x81\x84\x22\xe1\x4f\xad\x4e\x20\xbe\x17\x39\x93\x8a\xd5\xa1\x2a\x5e\xa7\x4a\x34\xb2\x95\x97\x64\x45\x0a\x60\xfa\x4b\xb2\x29\x6c\x51\x36\xc5\xdc\xcc\xb5\xe4\xcc\xd3\xa7\x4e\xc9\x3e\xb2\x79\xce\x69\x50\x32\x0e\xa5\xed\xf5\x9e\xf7\x23\xee\x9f\xc7\xe4\xad\x5b\x43\x96\x89\xfa\xf1\xf4\xbb\x4a\x09\x5e\xe0\x02\x6d\xfa\x5d\xd9\x52\xc4\x66\xe8\x5c\xc0\xe4\xe3\x47\x63\x50\x8f\xf8\x34\x50\xac\xc4\x1d\x74\x18\x37\x61\x49\x8d\x83\x46\xce\x65\x47\xc6\x6a\xed\x98\x08\x2f\x7a\x5f\x3b\x03\x7e\xf4\xa1\xd6\xb5\x4a\xf0\xf6\x7d\x90\x99\x3a\x03\x2e\xd5\xe2\xb9\xbb\x18\xb0\x48\x5b\x64\xc8\x08\x9c\x27\x78\x01\x0b\x6a\xe8\xe7\x92\x66\x27\x1c\x0b\x38\x54\xf2\x8b\xcf\xe7\x59\x76\x64\x05\xef\x77\x47\xe8\x7f\x23\x1c\xe2\xe6\x80\x06\xb0\x58\xf7\xf5\xa4\x50\x2a\x95\x81\xf8\x29\xe1\xf7\x84\x1c\x29\xac\x89\x91\x2f\x09\x51\x8c\xfc\xb0\x06\x87\xaa\x30\xb4\x76\x53\x8d\x63\x31\x07\x09\xcf\x64\x1c\x33\x3a\x54\x52\xcc\x68\x60\x48\x9d\x56\x09\x61\xda\xaa\xd2\x48\x96\x90\x03\xeb\x63\x80\x63\x64\x4e\xac\x32\x4c\x5d\x00\x0b\x5b\x7d\xa0\x20\x72\x6e\x22\x71\x05\xd1\x5b\x1f\xae\x4a\xfc\x72\x21\x64\xa6\x56\xb5\x3d\x7f\xdd\xee\x17\x32\x9f\x3e\x70\x4f\xf7\xa2\xeb\x36\xdf\xcd\x75\x6e\x9a\x36\x7b\xd7\xac\xb9\x2f\x7f\x90\x6b\x63\xf6\x41\x2e\xf3\x7c\xee\x09\x66\xdf\xad\xb7\xee\xfe\x4d\xee\x80\xf1\x56\x88\x3e\x9e\x5e\xe0\x7f\x9e\x22\xc5\x8d\xb5\x82\x8f\x1a\x16\x9d\x16\x2f\xcd\x3a\xdb\x1c\x2a\xd1\xc7\x5e\x4a\x00\xb2\x4b\x0a\x67\xc1\x62\xe2\x26\x32\xca\xa5\x4d\xe7\x2e\x7e\x24\xeb\xc3\x55\xa9\x5d\x57\xbf\xf5\x5a\x66\xf9\xea\x5f\x3c\xc0\x75\x6e\x3a\xf7\xfc\xd7\x0e\xd2\x17\xf2\xe2\x07\xb9\x03\xba\x8d\xb8\x9c\x9b\x03\xec\xa6\x3c\x8c\xdb\x30\x75\x7e\x31\x9f\x87\x71\xf8\xf2\xfd\x78\xd8\x83\x0f\xc1\x38\xc9\x23\xe8\xbd\x3b\x7e\xb7\xa9\x77\x07\xa4\x92\x40\x72\x03\x5a\x8e\x37\x5c\x84\xfa\x25\xd0\xfe\xf7\x3f\x42\x49\xfb\xfa\xeb\xfb\xfe\xf0\x93\xdd\x4f\x3e\xf6\xc8\xd6\xa7\x1e\xd3\x5e\x61\x5a\xa0\x1d\xc6\xb5\x83\xda\x51\xed\x1f\xda\xfb\x77\x41\x6e\xfb\xc1\xc3\x87\x0f\x1e\x7c\x8f\xbc\xdd\x1d\x9a\x97\x5b\x49\xf8\x15\xc5\x9a\xdf\x61\xb8\x39\x05\x96\x61\x09\x00\x09\xc3\xc7\xf1\x3a\xb0\x3c\x28\x8c\x44\x18\x87\x5f\x54\x95\xee\xe3\x60\xc6\x65\x38\x97\x5b\xf7\x71\x2c\x8e\xbc\x8f\xc3\x55\xb9\xdc\x2c\xd5\x9b\x06\x03\xa9\x8b\xd3\x12\x0b\xf8\x7d\x21\x68\xf2\x71\x2c\x3b\xee\x0d\x5a\x4f\x7b\x66\x71\xef\x5f\xbe\x3a\xfc\xc9\x72\x3b\x67\xbd\x77\xdb\x9d\x0f\x3d\xf4\xf3\x27\xd7\x33\x9a\x57\x18\xb9\x69\xf6\x34\xed\xb0\xf6\x77\x4c\xc6\x63\x83\xa6\x76\x68\x1d\x9c\xe7\xd3\x03\xff\xfd\xc6\x9b\x87\x76\xed\x37\xdb\x06\x19\xd4\x81\xcb\x41\xc6\x0d\x28\x7b\x4d\xb6\x21\x22\xaa\xa8\x2a\x41\xfa\x9e\x41\xaf\xe2\xf1\x91\xbc\x5c\x15\x8c\xa3\x50\xa9\x55\x88\x62\xca\x3c\x58\x68\x9d\xee\x08\x49\x1f\x4a\x0a\x4f\x48\x8a\xf8\x89\x6b\xe1\x70\xf2\x25\xa6\x80\xa4\x10\x0b\x16\x40\x77\x55\x97\xfc\xf5\xd0\x67\xcb\xac\xe1\x75\xd9\x2a\xfb\xd2\x2f\x7e\xf3\xa7\xdd\xf7\x6d\x78\xfc\x5e\x6e\xf3\x53\x77\x6f\x62\x62\xd0\x0e\x13\xcf\x6e\xfa\xee\x2d\x78\x68\xf1\x98\xa7\xe1\x10\x68\x79\xf3\x10\x7a\xbb\xe9\xf3\xfd\xbf\xa3\x72\xcc\x26\xb8\x39\x40\x02\x63\x8c\x8c\x58\xfe\x46\xec\x38\x10\xa3\x91\x3e\x7e\x76\x8c\x44\x43\x7c\x89\x21\xb1\x37\x50\xec\x65\x24\x96\xd8\x5a\x27\xf4\x49\x3b\xee\xf5\x5a\xc7\x6d\xbf\x74\xca\x28\x7f\xc7\xa9\x3f\xba\x6f\x06\xd7\xf9\xe6\xa2\x6b\xec\xdb\x9c\x73\x7f\x71\x59\xae\x87\xe6\x65\xd8\x15\xdc\x1c\x10\x03\x97\xe8\x35\xa4\x6a\xab\x2e\xa9\x56\xec\xc2\x34\x12\x55\x1e\x48\x2a\x36\x99\x78\x62\xd8\x75\x91\x3d\xaa\xd2\x04\xe3\x4a\xc4\x26\xc9\x3b\x59\xab\xcb\x57\x4d\x12\x2f\xb2\xa4\x08\x3c\xe6\x58\xb5\x4f\x92\x51\x80\x24\x63\x81\x20\x07\xf1\xdf\xb1\xb4\xb0\xe3\x29\xb8\x01\x3e\xaf\x9f\x64\x61\xf2\xf6\xb4\x6d\x44\x73\xcb\x30\xe6\xf2\x8f\x5f\x7e\xf1\xc9\x8e\xa7\x7f\x76\xcd\x75\xf3\x9f\xbf\xa3\x6b\xec\x1f\x7e\xfd\xe1\xcd\x3b\x9f\xb9\xfd\x27\xcb\x37\x3f\x74\xd3\x68\x76\xf4\x9a\x87\x3b\xd7\x4d\x9c\x34\x76\xcc\x39\x13\x53\xb3\x16\xff\xe0\xc1\x5f\x9c\xb9\x75\xd6\xac\xce\xf1\xb3\x4f\x1d\x73\xde\x42\x00\x41\xf4\xf8\x11\xa6\x87\x9f\x08\xfc\xe0\x46\xbd\x6b\xc6\x6e\x55\x33\x3c\xa1\x85\xf8\x35\x19\x9e\xf4\x24\xf1\x9c\x18\x27\xbe\x0d\x31\xa0\xbe\x5e\x22\x0a\x5c\x32\x23\xfa\x8c\x76\x46\xe4\x4a\x66\x7c\x24\xb7\xef\x03\x62\x1c\x8b\x09\x1b\x24\x25\x7e\x6c\x58\x59\x9f\x1e\x65\xdb\x3d\x24\xd3\x80\xbd\x35\x57\x1a\xf1\x34\xba\xf2\xb4\x8d\x83\x29\x1f\x76\x71\xa8\x54\x90\x52\x5a\x08\x46\x1f\x99\x7c\x25\xec\xd0\xf6\xfd\xf8\xdc\xd8\x9c\x60\xe8\x8a\x91\xda\x5e\x76\xef\xcc\xc9\x7f\xea\x5b\x9b\xfb\xd9\x45\x0b\x9c\xe2\x9d\x36\x1f\xfc\x21\xb3\x9a\xda\xff\x27\x8e\x1f\xe1\xce\xe0\x3a\x81\x17\xcc\xd2\xbd\x65\xe2\x66\x0a\xfa\x33\x25\x89\x1f\x9f\xa1\xec\xf3\x89\x1f\xda\x08\xe8\x90\x88\xa7\xec\xd7\x53\x40\x8a\x4b\x4e\x13\x27\xd9\x99\x06\x0a\x14\x74\xaf\xa7\x24\x29\x64\x04\x55\x4f\xf4\x2c\x5f\xf5\x8b\x07\x77\xde\x5b\x2d\x0e\xcf\x2e\x7f\xfd\x4d\xb8\x92\x39\x98\xeb\xb8\xed\x96\x3d\xef\x31\x63\x8e\xf5\xac\x3f\x67\xe6\x5e\x3d\x17\xe1\xe6\x3a\x81\x03\x44\xf5\xb3\x01\xe3\x48\x46\x99\x16\x38\xf2\x39\x21\x8f\x3f\x90\x1a\xcb\x90\x74\xcb\x2b\xea\x99\x1e\x2b\x2b\xda\xcf\xf8\xd3\xcb\xda\x45\x07\xb9\xce\xdc\x8a\x7d\x73\x1d\xd1\x96\xff\x64\xd6\x1c\xc3\x72\x18\x00\x40\x48\x71\x9d\xa0\x0e\xfc\x1a\x64\xea\xb0\x1e\x0f\xa4\xc8\x8f\xce\x40\xd1\x4b\xf2\x42\xf4\x0d\x43\x1f\xc9\x0b\x61\xdf\xce\xe7\xcb\xcf\x23\xbc\xca\x7d\x2d\x1b\x79\xa1\x3a\x9a\x17\x62\x5f\xde\xfd\xea\x5b\x7f\x99\x86\xff\x94\x47\x81\x61\x4e\x14\x7c\x59\x71\xb2\xdf\x21\xdb\xcb\x08\xba\xbb\x19\xc8\x7a\xe2\xc8\xe6\xee\xb6\xdb\x9c\x9e\x78\xb7\x03\xff\x9e\x61\x20\x5b\x7f\x67\xfd\x9d\x31\xc1\x29\xc9\xe9\x8c\xdd\x86\xbf\x60\x6b\xd6\x63\x0b\x32\xac\xdd\xe1\xd4\x47\x09\xe0\x69\xa2\x2d\x10\xac\x33\xff\x91\x9e\x7a\xf2\x42\x52\x34\x03\x0a\xa8\xc3\xba\xd1\x5d\xad\xa7\x9e\xaa\x61\x20\xd5\x3e\xb2\xdd\x93\xf2\xd4\xb2\x81\x14\x4d\x3f\xb1\x24\xde\x63\x63\x81\xdd\x97\x2f\xaa\xb2\x3a\xeb\x22\xfb\x5e\xfb\x55\x55\xc0\xeb\xe6\x44\xf1\xb4\x07\x77\x69\x07\x3f\xd8\x53\x9d\xb4\x0e\xae\xdf\xff\x0e\xd7\xa9\x5d\xa9\xcd\xfe\xd1\xd8\x75\xb3\x99\x2b\x73\xf7\xc5\xce\xf9\xc1\x94\xc8\xd9\x47\x99\xce\x63\x3d\xcc\xc2\x1f\xf4\xee\x9b\x97\xdb\x4c\x64\xa6\x09\x00\x2e\xc0\x75\x96\xe4\xa1\xe0\xc9\xe5\xa1\x9a\xe0\xdd\xda\x6d\xef\xc2\x30\x0c\xbe\xad\xdd\x06\xef\x79\x57\x3b\xa4\xbd\xc7\x0c\x67\x42\xda\x3c\xf8\x68\xee\xcb\xdc\x41\xd8\xa3\x75\x02\x08\x18\xcd\xcb\x79\xb9\x4e\x10\x00\x71\x40\xaf\x5d\x4c\xe1\x5b\xf7\x50\x93\x46\xab\xcc\x1e\x27\x7d\x14\x40\x52\x38\x29\x9f\x79\x4b\x8d\x85\x98\x6a\x2c\x66\xf4\xb5\x8f\x83\xcc\x2b\x7f\x39\x4b\xb2\x8a\xa7\xf9\x3f\x7d\x55\x6b\x39\x73\xef\xda\xb3\x3a\x93\x13\x67\xde\xd0\x9c\xe6\x3a\x73\xeb\xde\xb9\xa8\xe9\xed\x0e\xe6\xea\x63\xb5\x3d\x8f\x4a\xeb\xec\x17\x5d\xb2\x81\xd0\x38\x0d\x00\x76\x29\xd7\x69\xce\x55\x59\xd4\x0c\x87\xdf\x37\x6b\x39\xb9\x5c\xd5\x34\x66\x6a\xee\x10\xf3\xb7\xdc\x8b\xcc\x8c\xe5\xec\xa4\xb5\x6b\xfa\xde\xb8\x8b\xbe\xb9\xb4\xb6\x87\x79\x93\xef\x01\xb5\x58\x0f\x92\xf6\x31\xd1\xaa\x62\xa2\x02\xc4\x1c\x2a\x10\xd3\x58\x97\x40\xe1\x5e\xc4\x25\x89\x55\xb4\x27\x33\x5e\xd2\xc6\xe9\x0d\x8a\x71\x64\x4d\x66\xc2\x24\x20\x0a\x43\x31\xae\xd4\x93\x77\x10\x90\x64\xc5\x13\x4e\xa7\x11\x94\x68\x75\x4a\x94\x89\x4d\xc1\x4a\x62\x2c\x6c\x93\x46\x8c\x4c\xf9\xb0\x8a\xf6\x92\xf6\x00\xc9\xeb\x0f\xf8\x70\xc4\x3a\xa2\x39\xfd\xd3\xeb\x0f\xbf\x74\xdd\x35\x9f\x2e\xbd\xea\xfa\xc5\x6f\xfc\xe7\x2d\xf0\xeb\xfb\x98\x0b\xe7\xc2\xc4\x43\xcf\x6c\xe4\xe6\x5c\xa4\x7d\xf8\x7e\x8b\xc3\xfb\x93\x85\xda\x07\xf3\x67\x31\xf7\x32\xcf\x3c\x0c\x87\x5e\x7e\x3e\xa6\x01\xaa\x9a\xcc\xac\x26\x3e\x61\x35\x40\x30\x91\xf7\x08\x25\x95\xfc\xa2\x1e\x21\x94\x52\x12\x54\x37\x69\xb2\x95\xf9\x5f\x8d\xd2\x3e\x41\xdb\xc3\xbc\xc7\xf7\x80\x1a\x4c\x3b\x69\x9f\xb4\x5b\x55\x54\x43\xf2\x62\xc8\x97\x50\xbc\x98\xf6\x48\x02\x31\xbd\xc8\x9a\x24\x4e\xa0\x3b\x99\x09\x91\x42\x68\xc8\x8b\x55\x69\x88\x54\x41\x6b\xc4\x38\xf6\xf9\x6b\x31\xed\x3e\x62\x92\x42\x24\xc0\x22\x31\x07\xb2\xcb\x8a\xd5\x8d\x69\x0f\x8c\x6c\x93\x46\xb4\xb7\x35\x63\x42\x5b\xda\x28\xe1\x3a\x1f\x84\xd8\x84\xcf\x3f\xfd\xf4\xfa\x45\xaf\x1f\xbc\xf9\xc6\x1b\x6f\x3e\xf4\x32\xe2\xf6\xc0\x41\x1f\xb4\xd8\x5b\x3e\x80\xf1\xf9\xe7\x33\x1b\x99\xa7\x1e\xd5\x0e\x5d\x31\xeb\x3e\x66\xe6\x65\xda\xc1\x07\x9f\x25\x7d\x4b\xcc\xd9\x5c\x9c\x9d\x05\x02\xe0\x25\x80\x5c\x09\x05\xb8\x53\x29\x72\x75\xd6\x64\xb7\x4f\x74\x59\xe3\xc8\x9b\x52\x58\xab\xaa\x70\xf6\x64\xd2\x90\x52\xac\x32\xfe\x32\xef\xd5\xfd\x44\x65\x78\x87\x21\xeb\x30\xec\xdc\x70\xe2\x77\x38\x48\x77\x8b\xdf\xed\xfe\xf3\x37\xfb\x46\x01\x5f\xdc\x86\x38\x77\x37\xcf\x59\x3d\xf1\x6e\x0b\xfe\x1d\x79\xdd\xdd\x92\xd7\xed\x89\x77\x7b\xf0\xef\x19\x9e\xb3\x16\x14\x06\xb2\xa4\x33\x1e\xaf\x1b\x7f\x27\xa5\x41\x37\x6f\x91\x3c\x44\x5b\x3c\xcf\xf1\x16\xab\x5b\xf2\x78\xcd\xaa\x82\x96\xd9\x90\x23\xad\xb0\xa2\x64\x18\x0e\x1c\x81\x04\xf4\x20\x1f\xc7\x21\x2d\xb4\x9d\x6e\xfe\x86\x89\xcb\xcf\x9d\x32\x67\xd8\xc8\x9b\x47\x2e\xb8\x67\xf2\x4d\x93\xa7\xcc\x39\xa5\x6d\x35\x73\xf6\x96\xab\xea\x1a\xea\x42\xa7\xa5\x1f\x5d\x1c\xad\xaf\x0f\x9e\x0e\x18\xb0\x51\xbb\x0b\xae\xe7\xe6\x90\xb8\x6c\x12\x20\x46\x3c\x2b\x9e\x60\x60\xce\x41\x06\xe6\x9c\x2e\xb5\x3b\xe2\xb0\x3b\xe3\x8a\xcb\x98\x94\xcb\x3b\xa1\xc5\x51\x5a\x18\xa6\x3c\x1b\xcf\x18\x3d\xfa\x8c\xf1\x63\xc7\x8e\x77\xa5\x96\xa7\xd8\x0f\x26\x4c\x99\x7c\xfa\xe9\x13\xcf\x3c\xda\xc7\x85\x8e\x7d\x89\xef\x63\xf7\xf1\x23\xec\x67\xa4\x37\xe1\x26\x7d\x46\x85\x25\x63\x6b\x90\xb6\xae\x66\xfd\xee\xa0\xc5\x11\x57\xfc\x36\x15\x85\x92\xdd\xd6\xa0\xc5\x1a\x37\xf2\x24\xba\x3b\x1c\x84\x24\x1d\x1c\x70\x13\x9b\x1c\x08\x62\xd9\x0a\x78\xf5\x5e\x85\x40\x50\x92\x95\x2a\x32\xe2\xe4\xf6\xd3\x94\xa1\x55\xca\x00\x87\x07\x7b\xa1\x16\x12\x81\xb0\x12\xc9\x7c\x7b\xdc\x4d\xfa\x70\x93\x91\xb9\xc2\x5c\xb5\xf8\x62\x6d\xcd\xcc\x6e\xf8\xf3\xbb\x36\x5f\xdf\xb6\xee\xd2\xa7\x1f\xdd\xf2\xc8\xf9\x6b\xc6\x2d\xb9\xfb\x8e\x77\x5e\x65\xbe\x80\x7d\x63\xb7\x6f\x15\xda\x36\xb5\xfd\xfa\x37\x87\x5e\x8d\x55\x3f\x92\xe6\x5f\x7f\xa7\x0e\xfa\xe8\x1b\x01\x80\x9b\xcc\xbf\x09\x22\x60\x89\xae\x7b\xc2\xac\x8a\x60\x32\x63\x63\xa8\x77\x9f\xe5\x05\x60\x73\x10\x71\xe3\x2d\x2a\xf2\x27\x21\xaa\x4d\x20\xb6\x17\x59\x92\xa4\xf3\xd2\x93\xcc\x04\x59\x4c\x4b\x30\x22\xe2\xdf\xfd\x62\x3c\xc3\x12\xe2\x58\x20\xc6\x95\x3a\x18\x57\x82\x58\x5f\x85\x31\x69\x02\x99\x4f\x44\x36\x1c\x4c\x61\xf5\x35\xb2\x03\xc6\xda\x52\x92\xc9\x7b\x92\xa2\xbe\xa8\xcf\x2b\x58\xa2\xbe\x09\x6f\xbd\xf6\xda\x67\x2f\xed\x7d\xee\xb4\xa7\x6f\x5e\x76\x23\x7c\x5c\xbb\x68\xfc\x59\xac\x67\x73\xe2\x6f\x87\x6f\x87\x89\x9d\xff\x39\xe3\x9e\xa9\x2b\xd6\x68\xbf\xbf\xfd\xd0\xdc\x3b\x86\x6e\x05\x0c\x58\x01\x05\x2e\xc0\x6d\x01\x61\xd0\x02\xae\x05\x48\x4e\x28\x75\x16\x15\x35\x25\x14\xce\x42\x5b\xd5\x43\xbd\x4a\x8d\x9b\xe4\x4f\x1a\x70\x94\xe4\xa2\xdd\x7a\x35\x21\x49\xee\xf6\xc1\x40\x98\x76\xeb\x75\x33\x82\xdb\x8b\xbf\xb5\xc9\xdd\x16\xd1\xe1\x22\xa9\x93\x3a\x59\x92\xbb\x9d\x6e\xaf\x1f\xff\x45\x93\xd4\x2d\x3a\xe8\xbf\xce\xc9\xdd\x80\x11\xac\xd4\x7b\x6e\x0f\x60\x1a\xda\x03\x16\xbf\xcf\x6b\x09\x58\x5a\xb0\xfb\x67\x69\x69\x6f\x6e\x1b\xd1\x1e\x30\xc5\x05\x2b\xe6\xaf\x99\x7f\xeb\x8a\xcb\xef\xb8\xe4\xa7\x93\x27\xdf\x32\xf7\x8e\xcb\x6e\xfc\xe9\xbc\x35\xf3\x6e\x9b\x3c\x79\xc2\x03\x57\x5f\xfd\xd0\x43\x57\x2f\x7e\x90\x1b\x77\x71\xd7\xa4\x49\x5d\x17\xdf\x71\xf5\x75\xb7\x5e\x72\xfb\xdc\xae\x33\x27\x75\xcd\xbd\xfd\xaa\xe5\xcb\xae\xfa\xec\xea\x07\x36\x5f\x73\xed\x83\x0f\x01\x08\x22\x00\x70\x4b\xf9\x1e\xe0\x07\xd7\x01\x92\xd0\x35\xea\x26\x59\xb7\xe4\x04\x0e\x6c\xbe\x14\xb7\xa0\x22\x5b\x32\xeb\xf5\x91\x3f\xe0\x53\x8a\x57\xa0\x2d\x1f\x81\x04\x72\xf6\x22\x39\xa9\x38\x3c\x58\x99\x64\x1c\x4e\x7c\x57\x0e\xbd\xf1\xc3\xe9\x20\x0d\xfc\x6e\x31\x8e\xbc\x49\xe2\x15\x3a\x9c\x46\xed\xc5\xa7\xd7\x5e\x3c\xa4\xf6\x42\x7c\x41\x92\xf0\x8a\xb6\xe1\xff\xa5\x22\x7b\xe1\x22\xb8\xf8\x57\xda\x7c\x4d\x7b\x1b\xb6\x69\x6f\x23\xed\x2d\x38\x52\x7b\xeb\x28\xdf\x93\x1b\xc9\xbc\x95\x03\x5d\xcf\x74\x69\xdf\x42\x6b\xd7\x33\x5d\x00\x30\x26\x9d\x6e\x01\xf5\x00\xf1\x09\x7d\xc8\x14\x5b\x21\x1c\x94\x09\xe4\x8b\x5e\x95\x80\x29\x29\x16\x82\x44\xbf\x6f\xda\x04\xeb\xfa\xfe\xc1\x7d\xc3\xda\xfb\xfe\x89\x63\xa5\x15\xc7\xbf\x61\x37\x0a\x75\x60\x18\x38\x15\xac\x01\x99\xa1\xa4\x02\x6b\x51\x51\x24\xa1\xf8\xf1\xcd\x8f\x4e\x20\x47\x2f\xf2\x24\x95\x84\xa4\x2a\xf5\xb2\x8a\x12\x6e\x32\x20\xd6\x2c\xa9\x68\x70\x12\x35\xbb\x15\x8b\x4c\x02\xa5\x31\x30\xae\x24\x1c\xa4\x11\x0f\xd5\x4b\xd8\xd2\x5b\xe4\xe7\xb9\x2a\x7f\x24\x36\x34\x35\xaa\x31\x90\x56\x9a\xdb\x24\xb9\xbb\xba\xb1\x35\x44\x84\x82\x1b\x4a\x0b\xb4\x11\x69\x27\xf4\x54\x0f\x26\xff\x0a\xf2\xcb\x28\x64\x2e\xd1\x36\xb7\xd0\x69\x44\xa3\xa9\x3a\x60\x21\x9a\x8f\x84\x08\xd0\xe7\xb5\x50\xfd\x43\x5a\xaa\xf5\xf6\xea\x15\x3f\xda\xfb\x83\x9b\xef\x5c\xf8\xe8\xfe\x75\x33\xcf\xee\x9c\xfe\xeb\xd7\x2e\xb8\xff\xca\xf6\x8b\x6f\xef\x5c\xba\xe8\xba\x87\x7a\xee\x7f\xe0\xfe\x23\xef\xbf\xdf\x30\x72\xc5\x93\x5d\x6b\x7b\xc6\x4f\x4f\x3f\xd8\x32\xb4\x73\x52\xc7\x39\x1d\x53\x36\x2d\xf9\xd1\x9a\xc6\xd6\x6b\x66\xac\xbc\xbb\x66\xf0\x1d\x2d\x35\xa3\x3b\x46\xcd\x68\x3f\xfd\x81\xab\xb2\x17\x4c\x5b\xff\xf3\x87\xd8\x49\xa9\xb3\x26\x8e\x3d\xfb\xea\x73\x17\x9d\x2a\x93\x39\x14\x06\x0e\xe7\xed\xec\x12\xfe\x30\xe9\xa7\x68\x03\x48\x4c\x20\x1f\x99\xf6\x4d\x72\x38\x40\xd0\xbf\x33\x82\x79\x21\x40\x66\x0f\xed\x38\x3e\xf2\xab\x7a\x17\xb2\x39\xab\xd4\x64\xfa\x1e\x0e\x1f\xd5\xda\x72\xea\xa9\x2d\xad\xa3\xe0\x2d\xa3\x9a\xf1\x77\xcd\xa3\xf8\xa5\x6d\x89\x44\x5b\x5b\x32\xd9\xa6\x7f\x05\x7a\x8f\xbb\x70\x06\xff\x36\x70\x81\x3a\x30\x12\xeb\x54\x3b\xbe\x39\x2f\xaf\xd7\xe8\x6a\x78\x35\x3b\x62\x98\x9d\x73\xc4\x95\x11\x16\x35\x1b\x6b\x25\xdf\xc6\xf0\x8d\xb6\xd3\xfe\x85\x20\xe9\x5f\xa8\x87\x71\x25\x2e\xab\x28\x4e\xf4\xab\x62\x0d\xaa\xca\x28\xac\x71\xe2\x92\xfc\xbc\xdd\xcb\xd5\xc4\x9a\x4e\x19\x41\xee\x6b\xd8\x08\xd2\x6e\x8a\x5a\xa5\x1e\xab\x3b\x58\x0f\x9a\x4f\xc1\x17\x16\x93\x51\x53\xbe\xeb\x8b\x93\x7d\x5e\x86\x8b\x35\x34\x32\xed\x5e\x99\x4b\x25\x1b\x65\xa3\xc1\x94\x2f\x0a\xef\xf4\x3e\xc2\x86\xe6\xf9\x6f\xc0\x39\x6f\xe1\x5f\xaf\x6a\x4f\xfc\xfa\xa0\xf6\xc4\xbe\x45\xdb\x61\x7c\xfb\x76\x38\xf8\xb9\xed\xda\xa1\xed\xdb\xb5\xde\xe7\xa0\xf3\x77\x7b\x6f\xbd\x71\xcc\xc2\x19\xcb\xd7\x2c\x5b\x73\xd1\x0d\x63\xe6\x8d\x7f\xe5\x03\xe6\x23\xf2\x9f\x69\x4f\xbc\xb5\x5f\xdb\xf6\xeb\x83\x70\xf6\xeb\xf8\xdf\x34\xff\x97\xef\x7d\x3b\x76\xd5\xc8\x5f\x3e\xf0\xc8\x33\x89\xae\x70\xe0\x6b\xda\xb7\x3d\x81\x75\x33\xcb\xf9\x03\xa4\xcb\x73\x35\xc8\x38\x31\x93\xac\xbc\x9a\xa9\x23\x5e\xa2\x5d\x45\xfe\x84\x12\xe6\xf3\x1d\x9e\x21\x17\xc9\x68\x45\x68\xf3\x98\xe4\x52\x91\xe4\xce\x7a\x82\xe0\x3e\x2e\x8e\x3c\x09\x92\xe7\x08\x91\xaa\x95\x3d\x8d\x65\x38\x63\x75\xfa\xf5\xaa\x95\x37\x0d\x94\xb0\x5f\x92\x15\xd9\x9b\x4e\xa3\x3a\x09\x81\xb4\x62\x65\x69\x12\xcc\x29\x21\x3b\x8d\x76\xc7\xd1\x09\x00\x4b\x33\x1d\x37\x92\x62\x2d\xb4\x5f\x3e\x95\x24\xb5\xab\x09\x8f\x3e\xb5\x74\xea\x19\xf3\x17\x56\x7b\x6f\xfc\xd9\xcf\xd6\xcc\x0d\xcd\x59\x7b\xf1\x92\xae\xc5\xfb\xe7\x5d\x3d\x8f\xfd\xe8\xb2\x85\x02\x37\xb4\x63\x4c\xdb\xd8\xe6\x31\x8b\x6f\xd4\xc6\xce\xbc\x64\xfe\x65\xf3\x32\x09\x8e\x4b\x13\x3a\xa7\x83\xa5\xec\x3e\x76\x3f\x10\x80\x83\x74\x87\x07\x44\x68\xd1\xbf\x4c\x87\xb3\x6e\xd1\x3e\x83\x75\xb7\x74\xc0\x0b\x57\xe3\x6f\x56\x33\xce\x30\x7c\xb8\x53\x7b\x42\x7b\xfc\x2c\xf8\x50\xfe\x5b\xda\xf7\x0d\x05\x6e\x10\x1b\x06\x3c\x38\xc5\xe8\x1c\x37\xa6\xff\x38\x91\xf6\x70\x71\xbd\x0a\xeb\x56\x33\x1c\xb1\x5e\x1c\xc8\xf7\x70\x79\xda\xc8\x6c\x1f\xbb\x6f\x3d\x73\xc7\x86\xdc\x9f\x61\xd7\xbf\x37\x83\xc7\x15\xc9\xfa\x50\x30\x12\x3c\x5c\x4e\xda\x87\x50\x69\x1f\x22\xa8\x99\x21\xc3\xf0\x89\x86\xd4\x8b\x71\x34\x28\x99\x6d\x18\x49\xfe\xa2\x41\x28\x27\xfb\x43\x25\x15\x0d\x4b\xa2\xa1\x6e\x32\x09\xdc\x24\xa9\xa8\xa9\xf8\x25\x24\x87\x4a\xf2\x4e\xbb\xb7\x86\x8b\xb7\x52\xf3\x85\x06\xa7\x51\x50\x46\x83\xf0\x9b\x18\x22\xc9\x59\xab\x3b\x08\xc8\x5f\x8d\x94\x4e\xea\x2d\x40\x29\x4a\xa7\x43\x3c\x31\xd6\xd4\x99\x74\x12\x6f\x61\x21\xb4\x3c\xf3\xd0\xcc\xce\xaf\xd0\xbb\xab\x17\x9c\x7b\xfe\xf4\xd9\xf3\x07\x7c\x09\xb9\x7b\xd9\xd5\x5d\x3f\xfb\xe1\x8a\x88\xb6\x14\xce\xd3\x1e\x85\x9f\x4d\x1b\x3f\x65\x3c\xf1\xed\x8f\x1f\x15\xbc\x9c\x20\x3c\x4c\xeb\xc9\xf8\x3e\x2c\x2a\xfe\x65\xaa\x27\xb3\x6d\x51\x9f\xc0\xd9\x05\xef\xed\xb7\x03\x06\xac\x64\x67\x32\x7f\x27\xb3\xd9\x01\x30\x01\xe8\xad\x63\x82\x8a\xc4\x84\xe2\x12\x0a\x1d\x64\xae\x42\x07\x99\xeb\x84\x53\x87\xfd\x67\xa4\x89\x7d\x5f\xb9\xab\xeb\xb6\xe7\x77\xfd\xf4\xd6\x17\x56\x2e\x3d\xe7\xdc\xc5\x8b\xcf\x9d\x76\x2d\xb7\x6e\xcd\xce\x5d\x3f\xed\xea\xe9\xfe\xd9\x39\x4b\xae\x9d\x3a\x6d\xc9\x35\xf4\x3d\x2f\x00\x80\x1b\xc4\xbd\x09\x58\xe0\x02\x17\x1b\x1d\x9a\x64\xba\x01\xd9\x52\x0a\x6f\x55\x91\x98\xcc\x70\xa4\xa1\x86\x73\x8a\xd8\x25\x27\x19\x1e\x8b\x48\x7d\x5e\x67\x2f\xb6\x90\x0e\xa9\xd4\x84\x33\x79\x13\xce\x89\x71\x04\x48\x7e\x9e\xf4\x6e\x92\x11\x89\xc2\xe0\x2a\xbb\xaf\xaf\xc3\x18\x5e\x5d\xbf\x9e\x59\x67\x1a\x5f\x85\x60\x38\xd3\xc9\x2c\xe3\xdf\x04\x41\x30\xd6\xd0\x34\x02\x09\x16\xfd\x98\x53\x21\xd2\xcb\x29\x49\x2a\x0a\x24\x95\x6a\x1c\x14\xf9\xf5\xc9\x37\xab\x94\xe1\x6d\xa4\xc8\xea\x94\xa9\xa2\x68\x6b\x37\x46\x85\xf2\x73\x89\x8c\x25\xea\x1b\x7e\x64\xf5\xa4\xb3\xc6\x8e\x9d\xdf\x36\xf9\xb6\x87\x7f\x7a\x5f\x68\xc4\x0f\xff\x0e\xef\x61\x3a\x17\xff\x61\xe5\x92\x33\xc7\x4f\x38\xa5\x75\xce\x92\xae\xab\x87\x9d\x73\xee\x05\xbf\xd7\xf3\x46\x31\x26\xcd\xac\xe7\xdf\x04\x51\x70\x15\xc8\xf8\x89\x5f\x2a\xa8\xa8\x3e\xa1\xb0\x82\x4a\xc6\x40\x74\xbd\xc7\xf7\x2a\x11\x49\x45\x11\x37\x0a\xd5\xf7\x4a\x46\xca\x28\x24\xa9\x19\x07\x89\xe4\x1c\x56\x31\x8e\x55\x1f\x50\xd8\x7a\x6a\xbd\xad\x92\x02\x23\x24\x80\x45\x61\x32\x3e\x26\xe3\xd0\xce\x4f\x3b\xad\x3c\x38\xa0\x6f\x1b\x11\x87\xf9\xc1\xc4\xfc\x5c\xa2\x6e\xb9\x63\x3f\xbf\xf9\xdd\xcf\x96\x2d\xbb\xec\xa2\x1f\x4c\xb8\x7c\x65\x67\xe7\x3d\xe7\xde\xfe\xc8\xe6\xcc\xae\x67\x37\x33\x4b\x6f\x99\xf8\xf0\xdd\x4b\xa6\x8e\x1f\x3d\x61\xea\x9c\xf6\x61\x2b\xae\xb8\x3f\x3d\xe4\xa9\xd5\x3f\x07\xa5\x7d\x0d\x20\x91\xe5\x8a\xfa\x1a\x84\x7c\x5f\x83\x22\xe8\x45\x95\x53\x86\xc3\xb6\xb1\xb0\x1d\x47\x92\x16\xd8\xd5\xbc\xac\xf5\xc3\x21\xbb\xc7\x71\x1f\x86\x4e\x51\xa6\xfa\x4e\x7b\x75\x38\xa9\x99\x68\x5e\x6e\x2a\xd7\x09\xfc\x60\xb1\x5e\xb5\x22\x29\x63\xde\xc8\xab\x89\x29\x92\xf8\x2e\x2d\xaa\x59\x69\xb5\x00\xd9\xdc\x14\x6b\x20\x91\x2f\xaf\x29\xb2\x87\xf4\x9c\x2a\x4e\x37\x89\x70\x49\xe9\x83\xb7\x1b\x7f\x01\x25\xc5\xe1\x34\xb2\x6d\xee\x42\xb2\x0d\xfb\xbc\x31\xbf\x4f\xda\x91\xfd\xe6\x17\x0f\x64\x37\xd4\x54\x2d\xfa\x64\xc3\x6c\x6b\x95\xe6\x15\x46\xe6\x46\x6b\x7d\x2f\xbe\xcf\x8c\x39\xd6\xb3\xf1\xe9\x0b\x3a\x9f\xd5\x5e\x26\xb5\x7c\xad\x8f\x9b\x4f\x6a\x4c\x13\x01\xbe\x47\x96\x57\x33\x56\xa2\x8d\xad\x0e\x1c\x4b\x58\xab\xc4\x38\xe2\x93\x44\xe0\xab\x7a\x15\xd1\xa5\x22\xd1\x9d\x05\x4e\x60\xe1\xe2\x08\x24\x90\xe8\x56\x04\x18\x57\x78\x97\xaa\x8b\xb9\xc7\x3d\x32\x85\xc5\x1b\xff\x8f\x14\xbc\x7e\xfb\x47\x66\xf8\xf5\xef\x2d\x1f\x3b\xe3\xbf\xde\xe6\x64\xc8\x69\xdf\xfe\x51\xd8\xf6\xdd\x6c\x36\x25\x1f\x25\xb3\xd1\xcc\x64\xb8\x9e\x9d\xf3\xfd\x67\xa3\x3d\xc5\x83\x57\x63\x4f\x3f\xa3\x63\xf4\x04\xe6\x83\xf1\x9d\x67\x9d\x46\x07\xad\x20\x88\x68\x5e\x88\x5f\xb5\x04\x12\x20\x63\x05\x20\x8e\x83\x78\x86\xa7\x09\x6f\xbe\x97\x80\x8e\x78\x60\x5c\xb1\xf3\xa4\xa4\x0c\x14\x2b\x23\xe9\x8f\x86\x6a\x93\x96\xf6\x94\x2e\x65\x2d\x91\xc6\xc9\x67\xfd\xe0\xc5\x59\xcb\xdb\x32\xf7\x6f\x1e\xdf\xa4\xad\xab\x6a\x49\x9d\x1f\x44\x8b\x9a\xef\xbc\xe4\x2a\x1b\xfe\xac\xb3\x99\x4e\x78\x84\xf4\xb3\xd5\x1b\x7d\x39\x36\x6a\xde\x24\x95\x38\x6e\x2c\x47\xfa\x1e\xf1\xc9\x9b\x68\x7e\xdf\x09\x2d\x67\xc3\xaa\x4d\x1b\xac\x75\xc3\x6e\xe5\x8e\xee\xe9\xbb\x97\x69\x3b\x7d\x69\x4d\xf3\x85\x79\x5f\x63\x1f\x7f\xa0\x58\x57\xf2\x54\x57\xf2\xff\xf7\x74\xe5\x84\x67\x1e\xb8\xef\x97\xcf\xdd\xbf\x7e\xfb\x2d\xb3\x16\xcc\x9f\x3d\x7b\xfe\xfc\xd9\xdc\xa2\xa7\x76\xf6\x6c\x7d\x72\xf7\x0b\x5b\x57\x2c\x5f\xbe\x62\xc5\x75\xd7\x51\x5d\x39\x0d\x2c\x25\xe8\xcf\xc4\x27\x68\x17\x61\x3b\xf4\xc1\x26\xfa\x65\x1a\xac\xd3\x3e\x5b\x0d\x67\x6b\xdb\xa0\x9f\x7e\x7b\xa1\xf6\xe4\x5e\x78\x11\x9c\xd3\xa9\xcd\x0f\x6b\x97\x9e\x55\xf8\x96\xa4\x78\xc1\x24\x00\xf8\xcf\x09\xaf\x9c\x20\x04\xea\xc1\x3d\x20\x63\xd3\xb3\xb2\xa4\xf9\xd0\x9e\xca\xba\xaa\x6d\xd0\x11\x47\x9e\x14\xb6\x0c\xc8\x97\xcc\x54\xbb\xb0\x4c\x56\xcb\x58\xf7\x46\x0d\xc6\x22\x96\x86\xf4\xe1\xa4\x12\x90\x54\x24\xe7\x43\x7a\x9f\x18\xcf\x04\x03\x24\x22\x76\x89\x71\x12\x6d\x92\x71\x71\x8b\x33\x9d\x46\x41\x49\xb1\x57\xa7\xd3\x28\x20\x2b\x12\xa9\xc2\x54\xbb\x68\x5a\x11\x4a\x0a\x5b\x4b\xb8\x55\xb8\x21\x0f\x4c\xc1\x26\x7d\x8c\xd8\x17\x6b\x6b\x8a\xb6\x8d\x68\x17\x2c\x93\x8c\x7b\xbb\x8e\x5d\xf5\x40\x5f\x17\x7c\x02\xde\x7b\xdf\xaa\x55\x0f\x1c\x07\x10\x08\xd6\xd9\xe6\xcb\x3c\xb6\x90\xef\x39\xda\xb9\xff\x4a\xe6\xf4\xdc\xbb\x2b\x5f\x7b\x6d\xe5\x4b\x57\xce\x97\xd7\x02\x16\x0c\x03\x80\xff\x40\xe7\x41\x0b\x58\x41\xfb\x2f\xb1\xd9\x69\x12\xd4\x3c\x17\x22\x01\xcc\x05\x0a\x48\xd2\x6a\x26\xda\x4b\xa1\x47\x50\x73\x92\x44\xd0\x05\xda\xbc\xd2\x4e\xbb\xc3\x15\x8e\x34\x11\x87\xbb\x49\x27\x2c\x20\x65\x39\x2f\x5b\x5d\x8f\x5d\x8c\x08\x51\xb3\x50\x52\x2c\x55\x65\x49\x2d\x6f\x2d\x86\x19\x04\x4f\x23\x04\x33\xe5\xac\x47\x7f\xb2\x61\x39\x73\xc2\x81\x7a\x00\x84\xa1\xc4\x96\x34\x81\x53\x40\x3b\x38\x02\x32\x0d\x98\xfa\x61\xa9\x4c\x0c\x53\xee\x4d\x15\x2c\x4c\xcc\xad\xc8\xac\x9a\x6d\x1e\xde\xe0\x77\xc4\xd1\xe0\x94\xd2\x2c\xa8\x68\x48\x32\x33\xbc\x19\xdf\xee\xf0\x41\x62\x3c\x5b\xcf\xe2\xbf\x53\xea\x05\x35\x2b\x5a\xc9\xb7\xc4\x18\x8d\x3a\x39\x63\x84\x22\x6e\x25\x01\xe3\x28\x99\x54\x86\x49\x2a\x1a\x94\xcc\x0c\x4b\xe0\xbf\x1b\x36\x44\x8c\x67\x12\xc4\x0b\x4c\x34\x8b\x71\x25\x8d\xb5\x1c\x8e\x4d\x9b\xd2\x4a\x22\x22\xc9\x4a\x6c\x78\x3a\x8d\x86\x49\x4a\x6b\x23\x01\x33\x69\x96\x64\xd4\x92\x36\x59\xb5\x0c\x8c\xb4\xa5\xf3\x76\x4d\x96\x14\x47\x28\x7d\x52\x16\xad\xbc\xc8\xd5\x57\xb0\x73\x6f\x50\x09\xdc\x50\x24\x81\x15\x8c\x5f\xee\x40\x39\x61\x24\xef\x3b\xa5\x2d\x67\xe7\x72\x73\x48\x5f\xde\x75\x20\x53\x0b\x41\x3c\x1b\xa3\x93\xb1\xc1\x04\x9d\x73\xa7\x8d\x78\x6e\x0f\x71\x7c\xc3\x30\x9e\x8d\xd2\x54\x5f\x55\x34\x6c\x8d\x1b\xb5\xce\x2a\x37\x6d\xad\x0e\xbb\x25\x39\xc3\x3b\x39\x92\x3b\x93\x90\x23\x8d\xaa\xe4\x6e\x4f\xb0\x36\x46\x07\x0f\x83\xa4\x98\x81\x62\x52\x06\x58\x7d\xa4\x92\x11\x18\x31\x16\xb6\x8f\x85\x1d\x30\x85\x1d\x5b\x27\xa4\x41\x5e\x80\x44\xb4\xba\xf2\x8a\x35\x34\xa7\x5a\xa7\xdf\x70\x59\xc7\xfa\xce\xf9\xb7\x4d\x5c\xbd\xfc\xb1\x5f\x8e\x7b\xfd\xcd\x57\x3f\x86\xb3\xa7\x8c\x18\x39\x65\xf5\xd8\x71\x4d\x53\x96\x2c\xb8\x6c\xf6\xd5\xb3\xa2\x6d\xcb\x36\xcd\xb8\x7a\xf1\x8c\xb9\x8b\x66\xad\x9f\xf7\x22\xf7\xf8\x94\x09\x13\xa6\xdc\x31\x09\xe8\x88\xa6\x80\x0f\x5b\x96\x02\x0b\x90\x40\xa0\xff\x64\xa0\x5c\x98\x0c\x34\x8a\x0e\x50\x96\x64\xe4\x33\x4f\x06\xe6\x7b\x1c\x4b\x67\x04\x37\xea\x2d\x8f\x23\x8a\x67\x05\x2d\x73\xf4\x0e\xc8\x63\x13\xf4\xa1\x41\xf3\x39\x1c\xe5\xce\x61\x2d\x73\x8e\xf2\x13\x8a\x6c\xde\x33\xe9\x37\xab\x38\x56\xf7\x54\x4a\x66\x16\x19\x6b\xde\x71\x31\x9f\xc3\x07\xc2\xfd\xcf\xe1\x2f\x9c\xa3\x26\x81\x43\x59\xa0\x40\xbf\x44\x53\x2c\x05\x7e\xe0\x13\xf8\x03\xbe\x58\x73\x8b\x60\x91\x4a\x78\xb2\x64\xd5\x65\xc1\x5d\x23\xde\x59\x3d\xfb\xb6\xae\x59\xc5\x6c\x11\xe2\x81\x9f\xdd\x1c\xbf\xf4\x9d\x40\x5b\xd7\xcd\xa3\xfa\x3a\x0a\xf3\x94\xf4\x4c\x29\x60\x01\x75\xa0\x09\x5c\x53\x7a\xa6\x7a\xe3\x4c\xf8\x48\x36\xab\x8a\x3c\xc9\x6e\xb7\xad\xc6\x1a\x57\x02\x24\x37\x4f\x24\xd5\xda\xab\xd4\x05\x09\x3a\x11\x81\x24\x0a\x52\xa9\xac\xb3\x92\xaa\x0d\xf2\x48\x3b\x19\x1b\x0c\xd4\x93\xda\xb2\x97\x36\xce\x40\xfc\x72\x63\x66\xba\xf0\xb3\xac\x65\x52\xc9\x91\xed\x29\x27\x8c\x35\x0c\x63\xc8\x38\x70\x09\x7d\x33\xec\xd7\x5d\x3c\xf4\xbc\xa9\x93\xeb\x4f\x19\xee\xba\xcc\x7e\xdd\xdc\xf8\xf4\x73\xa6\x34\x0c\x4f\x3a\x4f\x29\x25\xf6\xc6\xb5\x4d\xf1\xa6\xd1\x63\x96\xaf\x23\x5f\x0a\xf4\x72\x3a\xbd\x83\x80\x05\x78\x08\x66\xd5\x82\x52\x8a\xbd\x79\x8a\xa5\x04\x8a\xa5\xb2\x36\x9a\x27\x8a\xe4\x49\x75\x06\x54\xe4\xa4\x7d\x34\xf5\x7e\x4a\xaa\xd3\x4a\x53\xd8\xd5\x52\x86\x81\x01\xfc\x0c\xeb\x69\x3b\x2c\xf4\x92\x0a\xba\x89\x4e\x73\xb3\x14\xa1\xce\xfc\x27\x05\x4a\x91\x91\x57\x1a\x43\x49\x7b\x2c\x9f\x5d\x32\x68\xdc\xaf\x67\x97\x8e\xfd\x17\x15\xb4\x27\x8c\x6c\x93\x71\xa7\x02\x90\x41\x10\x34\x82\xf3\x74\x0a\x9d\x29\x24\x25\x14\x0f\xab\xa2\x86\x84\x62\xe1\x29\xd2\x04\xd7\xab\x84\x82\x24\x75\x52\x07\xe3\x4a\x55\x90\xc2\x4c\xd4\x85\x24\x39\x63\xf1\x43\x4c\x49\x15\x6d\x04\x6a\xf0\x48\xf2\x4e\xae\xca\x01\xfd\x35\x8d\x94\x20\x33\x72\x82\xf9\x8d\x98\x3c\x1e\x26\xdc\x36\xe6\x86\xcb\x16\xdc\x34\x26\xc5\x44\xcc\x8f\xa5\xed\xd4\x51\xa9\xd3\xc6\x27\x87\x8f\xe7\x17\x86\xe6\x4f\x9e\xb7\xec\xfa\x8b\xce\xbc\x24\x78\x74\x9d\xf9\xdd\xd8\x47\x76\x74\x8c\x1c\xd9\xd1\x01\x00\x73\x5c\x03\x40\x58\x4f\x66\x7e\x3d\xe0\xc7\xd4\xe3\x47\x20\x55\x34\x10\x8a\xe4\x64\xd6\xe9\xb6\xe3\xab\x73\x92\xf1\x50\x7b\x7e\x3c\xd4\x9b\x40\xf6\x5e\x24\x25\xf3\xd3\x9a\x76\xd2\x1d\xc0\x88\x71\x54\x65\x4c\x88\xfa\x88\x9b\x1b\x83\x85\x09\xd1\xa8\x14\x65\x61\x54\x8a\x31\x4c\x0f\xfb\x49\xee\x25\xa6\x3a\xf7\x07\x66\x7c\xce\xa2\x81\x8f\x61\x0c\xbe\xb0\x3c\x3f\x35\x4a\xcf\xcc\x3c\x4b\x67\x91\xbc\xfa\x1c\xef\x20\x70\x2d\xed\xc2\xc8\xd6\xdb\x41\x35\x17\xcf\x0f\x75\xa2\x96\x84\x52\x8d\x79\x3f\xd8\x3c\xc1\x15\x81\x71\xa5\xd1\xad\x2a\x71\x18\x57\x22\x76\x49\xde\xe9\x0b\xd6\xd5\x37\xb4\xe0\x07\xd3\x28\x75\x8b\x2e\x2e\x4a\xc1\x1c\xaa\x25\x39\x53\xd7\xd0\x98\x4e\xa7\x15\xb1\x5e\x92\x33\xc0\x42\xda\x4e\x39\xe9\x84\xe3\xbf\xb0\x9f\x83\x5d\x71\x20\x18\x6e\x2d\x72\xbd\x2b\xcc\x07\xe7\xaa\x8b\x3d\x72\x7d\x16\x8c\xfd\xd6\xb2\x94\x60\xc1\x9d\x3b\xd0\xc4\xae\x7f\xa0\x89\xdd\x00\x8c\x2b\x22\x0e\xcc\xec\x0e\x52\xbd\x32\xcf\xee\x16\xda\xde\x4d\x53\xbc\xb9\x09\xba\x39\xc8\x5f\x4c\xde\x10\xf4\x3f\xdf\x80\x13\xc5\x27\x73\xbe\x7e\xa7\x32\x4c\x83\xf9\x54\xef\x1a\x56\xc1\x38\x95\x10\xcf\xdb\x03\xf3\x99\x42\xe0\x87\x03\x9d\xa9\x7a\xa0\x33\x85\x75\x9e\x65\xec\x8e\x50\xba\x0c\xd7\xcc\x86\xc3\x7c\x46\x8b\xc9\x68\x98\xce\x69\xb2\x17\xfa\xdc\x3d\xfb\xad\x65\x10\x89\x91\x62\xe0\xfa\x13\x9f\x16\xf9\x12\x28\x9a\xca\xba\xa8\xea\x0c\x27\xf5\xf6\xa3\x13\x9c\xbe\xdb\x2e\x02\x6b\x5c\x91\x03\xa4\x97\x0b\xc7\xe5\xb5\x7e\xda\x9c\x24\x8b\x92\xac\xb8\x7c\xfd\x09\xaa\x90\x92\x37\x93\x36\xa9\x4c\x76\x3e\x4f\xe1\xfe\xfe\x69\x7a\xc0\x80\x31\x00\x30\xf3\x2c\x4b\x81\x48\xe5\xb8\x8a\xf4\x85\xf3\x2a\xf2\x26\x29\x70\x95\x93\x57\x91\x94\x24\x22\x62\x27\x9d\x68\x19\x0f\xd1\x27\x1e\x9f\x18\x47\xee\x64\xc6\x4e\x5a\xa8\xed\x38\x92\x77\x26\x89\x1c\x7b\x70\x90\xc8\xe8\xd8\x59\x79\xd9\x65\x4d\xd3\xc5\x63\x74\xd9\x75\xd1\x29\xe3\xbc\xe4\x7e\xfb\xdb\xa2\x81\x63\x3d\x5f\x0c\x98\xdb\x4b\xde\x59\xb9\x49\x67\xff\x49\x4d\x3a\x93\x77\xc6\x48\xb2\xe2\xd6\x19\x6c\x3a\x55\x41\xa2\xf5\xe9\x67\xed\x4e\x5d\x9a\xcd\xa7\x32\x09\x34\x3e\xdf\xf1\x1c\x00\x8c\x62\x59\x4a\xfa\x7b\xcf\xa5\xd5\x3a\x1c\x44\xa3\x60\x32\xe3\x21\xa3\xa1\x3c\xed\x4b\xad\x4e\x20\x77\xaf\x12\xf0\xa9\x99\x80\x9b\x84\x91\x21\x52\x82\xcb\xb8\x49\x24\xe9\x76\x8a\x71\x24\x27\x89\x4c\x07\xdc\x92\xac\xf0\x36\x72\x3e\xb6\x48\x8a\xcd\x3c\x64\x4d\x52\xdc\x4c\xcf\x5b\x24\xc3\xdf\x1d\x2a\xe5\x25\x4b\xee\xfa\x27\x79\x99\x5e\xa4\x67\xa9\x1d\xbc\x8a\xfc\x49\x3a\xd2\xe8\xe6\xb1\xc7\x83\x44\x22\xce\x6c\xa9\x38\xeb\xa5\x22\xa7\x8d\xf4\x30\x65\x7c\x24\x2d\xe9\x0b\x90\xa3\x67\x9c\x3e\x03\x02\x14\xb9\x93\xc8\x57\x24\xd4\xa5\x5d\xd3\x66\x3a\x4c\x7f\x3e\xc6\x10\x5f\x3f\x25\xe8\x29\x43\x88\xf3\xb2\xfb\xdd\x35\x45\x77\x61\xfc\x31\x60\x40\x87\x8e\xdf\x60\x07\x41\x70\x19\x8d\xf9\x15\x87\x31\x17\xeb\xb5\xa9\x59\x00\x6d\xac\x23\x8e\x7c\x14\x03\x2c\x90\x24\x89\x4e\x1b\x19\x0c\x70\xf8\x88\xbc\x3b\x6c\x24\x6e\x0b\x88\xf1\x8c\x8d\xe4\x58\x6d\x58\x6a\x1c\x6e\xc5\x0d\xe3\x8a\x25\xa0\xd2\x64\x28\x19\x7b\xb6\xb8\x69\xb8\x65\x00\x3e\x0c\x82\x92\x47\x87\x7c\xc0\xcf\xb5\x63\x33\xcc\x12\xdc\x87\xe5\xda\x5d\xda\x8a\x5d\x2f\x30\xd3\xb5\x3f\x69\x7f\xf9\x1f\xb8\x48\xdb\xc8\x74\x6d\x61\x36\x6a\x6b\xb4\xed\xda\x03\xda\x4d\x4c\x97\x16\x66\xce\x84\x41\x58\xab\x55\x6d\xc9\xeb\x6d\x7e\xaa\x25\x05\x3c\x20\x0e\x56\xf5\x9b\xd4\x46\xad\x09\xe2\x88\xd6\x25\xbb\x6b\x02\xad\xd6\xb8\x12\xb3\xe2\xa3\x43\x34\xc4\x3c\xc0\x8d\x23\xf8\x78\x90\x14\xcd\xb0\x97\x53\x1f\x54\x51\x7d\x61\xac\x7b\x28\xf6\x59\x3d\xa4\xd6\xab\xd4\xc5\x25\x59\x09\xc4\xd2\xa4\x24\xea\x18\x78\xa8\xbb\xbc\xdb\xda\x6f\xd4\x3b\x5e\xc1\x6f\x2d\x3f\x02\x5e\xea\xbe\x12\x59\x25\x33\xe1\xe4\xdd\x07\x40\x14\x5b\xb0\x32\x53\xe1\x0d\xe5\xa6\xc2\x63\x7a\x9e\xaa\x9b\x15\x83\x11\xea\x46\x0c\x3c\x18\x5e\xd0\x53\x95\x47\xc4\x5f\xd4\xb5\xd6\x40\xa3\xe2\xec\xdc\x82\x21\xfe\x7f\x4d\x47\x41\x87\x55\xa6\x03\x4e\xd7\xd5\xda\x40\x84\x30\x43\x4d\xb1\x9c\x99\x8e\xa6\x0a\x74\x34\x97\xa3\xa3\xc5\x44\x47\xdd\xc9\xdf\x87\x59\xef\x55\xa6\x65\x85\x49\x0b\x0e\x4c\x4e\x91\x89\xcf\xd3\x94\x22\x34\x25\xb0\x8d\xef\x47\x13\x1a\x92\x50\xc2\x56\x15\xc5\x92\xdd\xf5\xe1\x21\xd6\xb8\xd2\x62\xc5\xaa\xdd\x80\x67\xd3\x49\xc5\x9a\x2e\x11\x24\xad\x07\xf8\xd6\x1a\x83\x2a\x6a\x2c\x30\x60\x38\x8c\x2b\xb1\x84\x24\xef\x64\x5d\xbe\xb0\xd8\x72\xd2\x2c\x28\xfb\xd4\x2a\xb3\xe2\xe2\x0a\x6f\x6e\x60\xb6\x94\xbc\x3e\x4e\xe7\x8b\x61\x27\x12\xd8\x52\xf4\xe7\x4c\x34\x81\x86\xa6\xb2\x61\x6a\x23\x5a\xca\xb1\xa4\x36\x90\x87\x8e\x1a\xec\x57\xd1\xe0\x62\x96\x34\xd6\x4a\x72\xb7\xe8\xf2\xb1\x27\xcd\x90\x0a\x0e\x50\x65\x96\xec\xef\xef\x0e\x0d\xc8\x8d\x03\xfd\xbc\x24\x08\xba\xa0\x93\xb3\x73\x9b\x81\x13\x00\x4f\xbb\x08\x03\x10\x04\x2c\xcd\x2d\xb0\x65\x64\x7b\xd7\x95\x70\x36\x9c\xb3\x40\xdb\x0a\xeb\x4f\x5d\xf0\xe5\x72\xed\xd9\x2b\xbb\x0e\x73\x43\xaf\xd4\x1e\x87\x17\x5d\xa1\x6d\xd5\x3e\x1e\x75\xc5\x97\x4b\xb5\x6d\x57\xdc\xf2\x91\x2e\x6f\xaf\xf0\xfb\xf8\x6f\x81\x07\x84\x41\x0c\x2c\xd6\xa7\x18\x6a\x8b\xd0\x1b\xa8\xa5\xf5\x06\xc8\xd8\x02\x69\xee\x0f\x50\xbf\xd0\x8b\x35\xb3\x24\x93\x21\xd4\x9d\x02\xeb\x76\x04\x70\x60\x8a\xaa\x64\xc5\x4a\xc6\x3f\x6a\x1d\xd8\x6f\x94\xd2\x69\x14\x92\x76\x5a\x81\x5c\xe5\x8f\xd1\x06\x76\x85\xb7\x18\x6c\xa5\x0d\x4c\x98\xb5\xb4\x79\xc9\xe3\x0e\xc0\x66\xcc\x5a\x3f\xe1\x72\x0b\x61\xe5\x3b\x5b\x2e\xfa\xc9\xe5\xaf\x60\x66\xfe\x71\xe3\xbc\x55\x0b\xb3\xaf\x5e\xcc\xdc\xbd\xe8\x91\xaf\xbe\x79\xf3\xda\xa7\xff\xfc\xcf\xcb\x29\x03\x2f\x58\x33\x63\xc3\xdb\xda\x26\xcc\xc3\xb9\x77\x9d\xbb\xf9\x75\xb8\x48\xcb\x6d\x60\x1f\x9a\xac\x7d\xd0\xf7\xd1\x54\xc2\x4d\xeb\x26\x6a\xcf\x08\x0e\x80\x65\x29\x90\x40\x18\x8c\x2e\x87\x04\x50\x53\x0e\x09\x20\xa2\xb7\x81\x67\x5c\x72\x40\x47\xa3\xeb\x87\x06\x50\x88\x8b\x4a\x70\x01\xa0\xc3\xd0\xd4\xfd\x01\x02\x84\x73\xf3\xca\xf9\xff\xbf\x67\x33\xf4\x70\xe9\xd9\xb6\x18\xca\xb7\xff\xd9\xf8\x5a\x53\xac\x54\x38\x5b\x5d\xf9\xb3\xd5\x97\x3b\x5b\xb4\x70\xb6\x50\xa5\xb3\x15\xeb\xd6\x92\xf3\xbd\x6d\x56\xa8\xe5\x8e\x58\xaa\x43\xe9\x39\x07\x01\x09\x44\xc0\x20\x70\x51\xff\x93\xa2\x70\x02\xb5\xa4\xb2\x3e\xaa\x28\xa2\x49\x23\x15\xa0\x9f\x1c\xab\x84\x60\x80\x00\x3c\xd6\x62\xad\xe0\x27\xba\xd3\xa0\x27\x8e\xd5\x48\x50\x92\x15\xc1\x55\x89\xd3\x15\xb4\x42\x29\xdf\xa5\x32\xba\xa0\x0c\x7d\xbb\xfa\x07\x49\x0c\xc5\x31\xb0\x2c\x25\xfb\xcb\x46\x94\x22\x19\x78\xf2\x48\x06\x5e\x1d\xc9\x20\xc3\x38\x64\x02\x06\xd8\x1f\xcd\xa0\x90\x50\xcd\xe3\x1a\x0c\xcd\x87\xcc\x05\x7c\x03\xb6\xcf\x14\x64\x14\x70\x67\xec\xc0\x07\xce\x32\xe1\xce\x98\x80\x52\xb2\xac\x8f\x42\x4c\x15\x61\xa6\x28\x8c\x23\x99\x47\x4d\xb1\x50\xd4\x14\xa0\xf8\x1c\xa4\x5a\x48\x3c\x3c\x5f\xaa\x9e\xf3\x95\x60\xd0\xec\xda\x0f\x43\x50\xd6\x3e\xd0\x3e\xdf\xb6\xf1\x93\x57\x7a\xf6\xf7\xf0\x3d\xda\x07\x87\xff\xe7\xaf\xda\x3e\xf8\xe1\xcf\x1f\xb9\x67\x0d\x9d\xe3\x3b\x7e\x84\x43\x42\x1d\x48\x80\x3b\xf5\x13\x91\x21\x1c\x6c\x2c\x87\x24\x14\x4e\xcc\x43\x98\x26\x1c\x79\xc3\x68\xf7\xe4\xb3\x3f\xb2\x47\xed\xb6\xc8\x11\x6b\x5c\x19\xe4\x50\xd1\xa0\x04\x81\x44\x32\x2c\xa5\x12\x0c\xa4\xd3\xc8\x2e\x75\x73\x51\x82\x6c\x8f\x06\xc9\xd9\x2a\x5f\x98\x80\x98\x22\x8b\xa4\x88\x64\xe6\x38\x0c\xe8\xb4\xce\x10\x29\x63\x91\x83\x3a\x48\x92\x2e\x01\x34\xc7\x4f\x9a\xf0\xc8\x9c\x4e\x2d\x4c\x25\x0b\xed\x7a\xb4\x0a\x55\xef\x93\x76\xfc\xfe\xb3\xf7\xff\xb8\xee\x9c\xf1\xa7\x2d\xbb\x63\xfe\xfe\x5d\x2f\x2e\x3e\xed\xb1\x33\x3e\x38\xf7\x9a\xeb\xaf\x38\x63\x72\xe7\xf8\xdb\x56\x6b\x7f\xe5\xb6\xef\xdc\xbb\x65\xdd\x5d\xd7\x8c\x9d\xd2\xd0\x3a\xe1\xec\x0b\x1e\x99\xff\xf8\xf6\x33\x9f\x68\x1d\x86\x26\x5d\x3e\xe9\xac\x55\x3f\x1a\x77\x45\x5b\xfb\x05\xa9\xa9\x33\x3f\x39\x36\x83\xc6\x57\x04\x7f\x40\x88\x92\x8d\x6f\x09\x70\x8b\x19\x81\xa0\xb5\x08\x81\x60\x68\x01\x81\x80\x32\xa9\xc9\x47\x1a\x7b\xe2\xe5\x10\x08\x30\x57\x9a\x80\x24\x77\x57\xd9\xc2\x44\xe5\xc7\xa5\x9d\xce\x60\xc4\xd2\x40\x4a\x6e\xff\x22\x0e\x81\x29\x30\x1f\x10\x91\x60\xa7\xae\x4e\xeb\x4e\x88\x4c\xc0\x5f\x6f\x14\x22\x7e\x5c\xc0\x28\x30\xf3\xa4\x09\x24\xc0\xad\x27\x85\xca\x70\xca\x80\xa8\x0c\xc3\x4b\x50\x19\x76\x3a\x83\x96\xe6\xc1\x09\xca\x90\x8c\x2f\x3e\x84\xbc\xbf\x7f\x03\x9c\xc1\x93\x7f\xa8\x03\xc0\x34\x3c\xa4\x3f\xdf\x01\xe0\x1a\xd8\x51\x26\x5f\xba\xc0\x93\x56\x90\xc2\xef\xa7\xc0\x93\x21\x45\x3c\x19\x5e\xe0\x09\x5d\x8f\x30\xc8\xa7\xa2\x41\xb4\xa6\xd8\x8f\x27\x6d\x30\xae\x0c\x32\xcb\x49\x42\xea\x71\x06\xeb\xea\x1b\x2d\xad\x79\x41\x41\x92\xa4\x34\xc4\xfe\x15\xde\x14\x5b\x8d\x81\x85\xe6\x56\x93\x21\x99\x70\x42\xc1\xe1\x4e\x37\x97\x6a\x66\xe6\x85\x47\xe7\x13\xff\x19\xa8\x06\x49\xd0\x01\x5e\x35\xf3\x69\x64\x11\x9f\x46\x1b\x7c\x42\x89\x04\x16\x2b\xd4\x9c\xec\x8e\xd5\x26\xac\x71\x65\xb0\x55\x25\x09\x8c\xb1\x84\x7d\x29\x9f\x8a\x52\x6e\x94\x24\x70\xe6\x41\x15\x85\x13\x4a\x32\x88\xff\x48\x49\xe7\x39\xda\xdd\x22\xa5\xad\x71\xa5\x39\xa8\xa2\xe6\x84\xd2\x12\x34\xb3\x78\x1c\x8c\x2b\xc9\xb0\x21\x76\x69\xcc\xdf\xda\xd8\x60\xcb\x48\xd2\x3e\x0c\x24\xda\x5c\x39\xda\x23\xc9\x19\xe0\xf5\xa5\xd3\x69\xb2\x3e\x47\x6f\xac\x1c\x88\xbf\x65\xdd\xfd\x81\xf9\xbc\xb0\x82\xdb\x1f\x18\x80\xe7\x25\x15\xa3\x02\xdb\x01\xa7\xf3\xfd\x30\xa8\x06\xcd\x60\x38\xe8\x00\x19\x33\xe7\x07\x17\x71\x3e\x91\xe7\x7c\x63\x02\x8d\x4e\x65\x6b\xa9\x99\x6f\xcb\xb3\xbc\xc5\xa7\x76\x87\x5b\x80\x35\xae\x44\x03\x2a\x6a\x71\x2b\x43\x0b\x9c\x1e\x25\x0d\xb5\xc6\x95\xa4\x5f\x45\xc9\x84\x32\xca\x5f\xca\xe9\x68\x8b\x24\x67\x82\xb5\x24\xfd\x3f\x14\x48\x72\xd6\x62\x73\xb6\x8d\xc6\xb2\x3c\x4a\x22\x4a\x2f\xf1\xaf\x71\xda\x9c\x89\x2a\xf0\xd7\xec\x48\x54\xe0\xf5\x0b\x86\x0f\xc1\x18\xcc\x5d\x6d\xf8\x12\x15\xd8\xfc\x89\x51\xb4\xfa\x5b\x5e\x11\xbc\x6f\x78\x16\x3a\x9f\x85\x3b\x88\x6e\xc4\x7c\xfe\xd5\x49\x68\x47\x2c\xe1\x6d\xbc\x8a\x46\x27\x94\x41\xbc\x6a\x70\x59\xd7\x95\xcd\x58\x3e\x83\x2a\x4a\x9a\xd5\x66\xf7\x10\x29\x6a\x8d\x2b\xa3\x82\x2a\x1a\x95\x50\x86\xf4\x17\xe8\x66\x49\x46\x41\xcc\xd4\xac\xb3\xd6\x92\x18\x84\x19\x3c\x04\x2b\x0b\x45\x02\xa4\x2a\x0c\x94\x58\x25\x46\x2b\xa3\xdb\x24\x59\x19\xd2\x9c\x3e\x79\xc5\x5a\xa1\x59\x68\x00\x35\x7b\xee\x0d\x97\x5d\x7a\xd3\xaa\x05\x97\xdd\x70\xd5\xe8\x51\xa9\x71\xe3\x87\x27\xc7\x0f\xa0\x70\x39\x69\xde\xb2\xeb\x2f\xba\xf4\xfa\x65\xf3\x8d\xc2\x1a\xd1\x27\xc2\x2d\xdc\x1c\xa2\x75\x4f\x05\xdb\x41\xa6\x19\x80\x38\x8a\xa6\xb0\xd6\x45\xd5\x49\x8a\x05\xe1\x49\x61\x8e\xa3\x51\xc9\x2c\x33\xbc\xd9\xa1\x33\x7d\x44\x92\x4c\x1a\xf4\xd3\xc0\x41\x3f\xfe\x3b\xec\xbc\x62\xed\xeb\xf7\xab\x64\xcc\x00\x6b\x61\x45\xac\x4a\x63\x15\x9c\x71\x34\x13\xbc\xa0\xa0\xac\xb8\x63\xe9\x34\x6a\x93\x32\x9e\xea\x28\x81\x2c\x95\x95\x48\x2d\x56\xc5\x43\xf0\x05\xd4\xa6\xd1\x70\xa9\x1b\x04\x22\x38\x6a\xa3\x6b\xb7\x44\x37\x1d\x81\xad\x32\x33\x57\xe7\x6d\x80\x0c\xa7\x47\x60\x54\x8e\x1a\xb3\xba\x2d\xa5\xac\x6e\x8a\x52\xce\xc2\x7f\xee\x5a\x72\xdd\x5d\xcf\x8c\x9a\xf4\xf6\x65\x37\x3f\x15\x1f\xf9\xec\x35\xfb\xd5\xdc\x04\x2b\x6c\x9b\xf5\xe0\x9c\x59\x9b\x17\x68\x9f\xac\x9a\xfe\xfa\xed\x5b\x77\xbd\x78\xf9\xcc\xb5\x4f\x3e\xa0\x3c\xc9\xec\x80\x7d\xab\x96\x2d\xbf\x9d\xf2\xf7\xcc\x1b\xaf\x9f\xb1\xa6\x75\xe4\x0f\x2f\x3c\xef\x42\xed\xef\x9f\x5c\xad\xdd\x12\x8d\x3f\xda\x52\xff\xe5\x4f\xae\xfc\xe5\xe6\x0b\x66\x52\x4e\x7f\xbd\xf9\x89\xc7\x75\xfc\x7f\xcd\xab\x63\xf7\xb4\x82\x6b\x29\x3a\x4b\xb6\x8e\xd6\x03\x0d\x00\x1f\xac\x53\x43\x7c\x1e\xf1\xc4\xee\x23\x1e\x61\x0d\x76\xfc\xdc\x2a\x85\x38\xb1\x4b\x72\x8f\xcb\x1b\xa8\xad\x8b\x36\x93\x16\x7e\x29\x23\xb2\xf5\xc4\x9e\x7b\x43\x92\x9c\xa9\x8d\xc6\x48\x3d\xb0\xae\x50\x0f\x64\xa5\x13\x41\xfe\xf4\xef\xb7\x2b\x0b\x02\xf4\x6d\x71\x25\xb0\x3f\x24\x50\xee\xe6\xe2\x2a\x20\x4b\x31\x75\x84\x28\xc1\xd4\x21\x68\xf6\x27\x46\xd5\x69\xae\x80\xaa\xd3\xa2\xa3\xea\x64\x59\x9b\x5c\x13\xa5\xe0\x8c\xff\x2a\xae\x0e\x9b\xf7\xeb\x4e\x84\xb0\xc3\x1b\x01\x72\x05\xa4\x1d\xe6\x4b\x53\x2d\xb1\x94\xce\xab\xfe\x5d\x3a\x77\x62\x3a\xeb\x9b\x28\xa1\xdd\x4e\x57\xb4\x81\xa4\x80\xbe\x37\xad\x05\x1f\xed\x44\xb4\x6e\x32\x02\xee\x0a\xb4\xc2\xac\x29\xd6\x32\xd3\xda\x00\x06\x81\x65\xa5\xb4\xb6\x58\xd5\x6c\x8c\xd2\x1a\xb3\xe6\xcb\xda\x98\xd6\x18\xa1\xb5\x51\xa7\x15\x07\xae\x04\x2d\xc5\xe7\x4f\xa7\x51\xa3\xd4\xc3\xda\xe4\x50\x75\x6d\x03\x21\x5a\xee\x76\xba\x6a\x22\x65\x88\x8e\x9d\x88\xe8\x62\x07\xac\x32\x8c\xd2\x5a\x93\xe7\x35\xa5\x32\xa4\x12\xfb\xaa\xc9\xed\xca\xed\xa2\xf8\x4a\x1c\xa5\x9f\x3f\x4c\xee\xba\x05\xa4\xc0\x6d\x27\xbe\x6d\xd4\x94\x40\xc3\x53\xd9\x3a\x6a\xf6\xe3\x49\xc3\x51\x2d\xdc\x3e\x7e\xdb\x0d\x81\x3c\x8c\xbe\xe0\x57\xbb\x87\x09\x7e\x6b\x5c\x69\xf5\xab\xa8\x35\xa1\x0c\xf3\xd3\x8d\x5e\xad\x0d\x92\xdc\x6d\x93\x43\x34\x1f\x68\xb5\xd1\x49\x42\x9f\x34\xb0\xc8\x57\xc8\x00\x9c\x10\x62\xaa\x4c\x36\xa0\xd2\x5b\x98\x5a\xae\x6e\x7a\xfc\x37\x00\xc0\x6b\x48\x9f\xb7\x03\x34\xe9\x28\x93\x36\xa8\xaf\xcc\xaa\xea\x25\x68\x46\x2e\x18\x57\x1c\x55\x46\x6b\x6e\xe1\x69\x7a\xa4\x94\x34\x44\x7f\x82\x3b\xb3\x79\x0c\xbb\xa3\x43\x08\x68\x10\x03\x9e\x06\x80\x39\x5d\xff\xd9\xad\xfd\x7f\x36\x02\xc9\xe2\x1f\x2f\xd2\x52\xab\xf1\x1a\x58\x29\x25\x3d\xad\x4b\xfd\x35\xd9\x42\x2b\xf9\xb1\x16\xfa\xf3\x8f\xff\x07\x00\xcc\x25\x42\x14\x38\x80\x84\xcf\xee\x34\x50\xb4\x48\xef\xb2\x93\x82\x75\x10\xa0\x0e\x27\xb5\xff\xa5\x75\x48\x7c\xfe\x73\x4d\x52\xf6\xd3\x2c\xf7\xa1\x49\x98\xf4\xcf\x61\x8f\xff\x09\x00\x66\x30\x99\x43\x73\x81\x30\x38\xbd\x18\x71\x09\x85\xf2\x15\x46\x4f\xd2\x48\xb5\x19\xc3\x68\xb6\x38\xc1\x1f\x72\xd1\xda\x9b\x9f\x42\x8f\xe1\x73\x94\x60\x2f\x99\xbd\x09\xbf\x71\xa7\xaf\x65\xc5\x7e\xb3\x69\x47\x5f\xc5\x67\xca\xff\x63\x61\x5f\xcd\xe5\x42\x1d\x91\xf4\x4b\x0a\x18\x5d\xa8\x29\x41\x00\x16\xa5\x04\xe9\x8c\x05\xbd\x4a\x8d\x23\x3f\x58\xea\x77\xd0\xc1\xd2\x86\x1a\xac\xb0\xab\x24\x4f\x88\x0c\x06\x4a\x48\x4e\x03\xa5\xa9\x4e\x92\x15\x3f\x20\x26\x89\x4e\x8f\x4b\x72\xd6\x2a\x3a\xdc\x1e\x7d\x0d\x09\x48\x25\x03\xed\xcd\x2d\x7c\x4b\x7b\x73\x4b\xbb\x9f\x64\x63\x65\x9f\x1b\xc4\x1a\x80\xd9\x17\x5a\x02\xd9\xdf\x7d\x36\x47\x1c\xbd\x4f\xfb\x3f\x3f\xf8\x62\xe6\xbc\x29\x0f\x2f\x38\x32\xf5\xed\xfb\xb7\x69\xdf\x7c\xf3\x99\xf6\xa7\x9e\x67\x1e\xfd\xc5\xc3\xff\xb1\x69\xdb\x16\xf8\xc9\x17\xd0\xb2\x9c\xeb\x55\x1e\xb8\xa6\xeb\xd4\xd4\xca\x29\x67\xdd\xb1\x78\xd9\x5a\x6d\xd9\x97\xda\x1f\xb4\x0f\xa0\xeb\xe3\xa7\xba\x5f\xff\xd5\xba\x6d\xcf\x11\xec\x1c\x00\xb8\xb3\xf9\xcf\x80\x17\x0c\xc1\xef\xb9\x2c\xda\x10\x1a\x94\x50\x82\x56\x15\xd5\x27\xbb\x23\xc1\x41\xd6\xb8\xd2\x68\xa5\x85\xeb\xa1\x25\x20\x44\x68\x08\x8e\x9e\x7c\x41\x32\x61\x8f\xbd\x49\x8a\x4b\x84\xea\x09\xe8\x9d\x12\x0d\xaa\x64\x67\x9f\x0e\x4f\xa4\x0c\xf1\x11\x50\x0d\x64\x97\xb2\x16\x77\x30\xd2\x88\x5f\x77\x05\x80\x22\xb6\x6c\x08\x54\x0c\x5b\x34\xad\x42\xb8\xd3\x0f\xce\x88\xfb\xb0\xb4\xa8\xc8\xea\xf7\x1d\x25\xf8\x46\x85\x5a\x5c\x31\xc2\x51\x43\x39\x84\xa3\x98\x8e\x70\xd4\x2d\xb2\x7a\x2d\xee\x24\x40\x8e\x3c\x26\x53\x5c\x0e\xee\xa8\xd5\x30\xc2\x15\x60\x8f\x98\x33\xcd\x75\xc4\xff\xd7\x67\x2f\x98\xd6\x72\x67\xcf\x18\x46\xb5\xc2\xd9\xa1\x5c\x30\xaa\xe6\xb3\xe3\x48\xe7\x7c\xfd\xec\xb5\xc6\xd9\x1b\xc5\x32\x48\x9c\xe4\xec\x79\xf0\x4d\x87\x93\xa6\x79\x44\x49\xf6\x57\xb3\xd4\x88\x2a\x38\x1e\x01\xa4\x8e\x54\x8e\x9a\x72\x09\x8b\xfe\xe0\x53\x8f\x99\xd4\xd8\xdc\x8a\x40\x54\xec\x1c\xb3\xad\x9c\x9a\x87\xa5\x32\x68\xe3\x3f\x03\x76\x92\xf3\xfb\x89\x4e\x5b\xab\x41\xdb\x30\x51\x45\xd1\x84\xe2\x26\x65\xc3\x6e\x9f\x1b\x47\x62\x35\x56\x15\x39\x92\xc5\xa9\x3f\xd4\x48\x9a\xc8\x83\xa4\x89\xbc\x31\x68\x64\x03\x31\x17\x50\x10\xff\x55\x28\x48\xf3\xa3\xc1\x46\x49\xde\x29\xba\xd9\x9a\xd6\x61\x74\xee\xb5\xb5\x02\xf9\x27\xc8\x27\xf4\x67\xc3\xcf\x2a\x3c\xab\x11\x27\x60\x49\xf1\xfb\x2a\x70\x85\xd3\x79\x72\x98\xc8\xaa\xb9\x7e\x68\x96\xd6\x4a\xf5\xc3\x02\x98\x42\x99\xfa\xa1\x21\xd3\xf9\xfa\x21\x2b\xba\xfd\x27\x2d\xd3\x15\xfd\x84\x72\x12\x5e\x57\xc6\x43\xa8\x24\xec\xdb\xfb\x79\x08\x2c\x58\x00\xbe\xe5\xe2\xdc\xb3\x80\x25\x3d\xd8\xc3\x00\x81\xa3\xe4\x54\x63\xc9\x91\x2f\xa1\xb8\x39\x3a\x6a\xc3\x51\xec\x3f\xa7\x8a\xe4\xa4\x3e\x7e\x4d\x36\x1e\x8d\x30\xb6\x2e\x49\xf9\xef\x16\xb0\xfb\x73\xcf\x2e\xbd\x66\xc2\xb0\x53\x4e\xa7\xbf\x33\x77\x6c\xd8\xa0\x1d\x59\xb9\x72\xc2\xe8\xd1\x4c\x1f\xf9\x42\x65\x72\x0f\x77\x39\xb7\x06\x78\x40\x35\x68\x00\x0b\xf5\x3a\x63\xc4\xe0\x7e\x08\xbf\xb7\x98\x19\xb4\xb4\x5e\x87\x47\x6b\xd4\xeb\x8c\xc8\x9d\x46\xf5\xd2\x4e\xde\xe1\x62\x29\x14\x42\x15\xd9\x62\xa9\x44\x8a\x6a\x8c\x55\x32\xf0\x37\x94\xd6\x18\x0d\x90\x04\xcc\x7e\x5a\x63\xf4\x06\x20\xe6\xbe\x1e\x85\x61\x6e\xdf\xbf\x6c\xda\x8a\x0b\x6f\xd1\xbe\xfe\xfa\xfe\x25\xd3\xaf\xbf\xa0\x6b\xf7\x70\xb8\x6f\xca\x55\xda\x2b\xeb\xcf\xbc\xea\x91\xad\x09\xca\xe5\xce\xa5\x53\x6f\x79\xe8\x1b\xcc\xe7\xd3\x97\x4e\x5b\xfd\x30\x04\xdb\xe6\x32\xd7\x8e\xe8\x53\x13\x87\x0f\x6e\x9e\x8f\x6d\x1a\xc1\x9a\x22\x7e\x7a\x2d\x98\x5f\x11\x6d\xaa\xee\xc4\x68\x53\x98\x6e\x36\xef\xa5\x8b\x52\xd6\x25\x07\xaa\x49\xee\xd4\x21\x9f\x14\xf2\x54\x41\xc7\x97\x60\x50\x3d\xa9\x2b\xf7\xfe\x58\x54\xfc\xbc\xa2\x3e\x4d\x33\x1d\x73\xff\x1d\x3a\x44\x56\x92\xb3\x2e\xd9\x17\xd2\xe1\x65\x33\xce\xea\x30\x89\x9a\x07\xa2\xa1\x50\xab\x2c\xc5\xd1\x9a\x69\xe4\xb6\xfb\x11\xc1\x25\x0a\xfa\xdd\x4c\x43\x03\x7e\xeb\x15\x68\x88\x9d\x98\x86\xc6\x92\xbb\xd8\xe9\xca\x07\x4c\xe4\x32\x90\x5d\x52\x6a\x22\x27\x43\x50\xb1\xe6\x2f\x21\xea\x7a\xf3\xc8\x40\x19\xba\x4a\xeb\x9b\x84\x36\x12\x0f\xd5\x83\x21\xa0\xab\x02\x75\xa8\x36\x81\x06\xa7\xb2\x41\xaa\xcd\x1a\xf3\x6e\x13\xeb\x50\xbb\x7d\x2c\xb0\xc6\x95\x70\xc0\x4c\x77\x77\x8b\x5d\xb4\xc6\x95\xa8\x9f\x58\x87\x16\xbf\x99\x11\xd8\x7b\x8a\x86\x25\x59\x91\xb1\x03\xd9\x22\x21\xd7\xc9\xd0\x5c\x41\xb9\x95\x50\x8f\xfa\x6b\xb5\x32\x4c\x78\xb3\x9f\x3e\x63\x28\x86\x96\x10\x25\xde\x47\x19\x14\xad\x86\x04\x1d\xbc\x3d\x69\x14\x2d\xd3\x68\x49\x05\x3c\xad\x06\x63\x16\xb6\x1c\xae\x16\xf7\x89\xa9\x56\x4e\xb0\x21\x05\x2f\xf0\x81\x28\xb8\x50\xaf\x40\x87\x44\x95\x42\xcf\x52\x58\x48\x02\x2b\x95\x47\xbf\x56\x18\x7f\x32\x69\x60\x5f\xdb\x0d\xec\xeb\x7c\x83\x45\x58\xca\x08\xa2\x8b\x3c\x9e\xda\x90\x24\x67\x05\xbb\x81\x7d\xed\x29\xe0\xcf\x1a\xc8\x90\x3a\x30\x64\xbd\xa4\xe3\x42\x66\x05\xeb\xe9\x4f\x2f\x3c\xf4\xd5\x57\x87\x7e\x77\x83\xdd\x7e\xef\x36\xd8\xb4\x6e\xf3\xe3\xf7\x31\x9a\xd7\x0a\xb4\x91\x13\xa7\xfe\xf8\x07\x04\xfd\xfa\x1f\xda\xfb\x8f\xfd\xb4\x55\x6b\xe3\x3c\x9f\x1e\x80\xcf\xfc\xfa\x3f\xbb\x5f\x07\x2c\xe5\x31\x7f\x58\xb7\x9a\xe7\x97\x72\xb9\xac\xc9\x0c\xf6\x96\xd8\xc9\xbc\x71\xcc\xf0\x1c\xe9\x4f\xf8\x1e\x77\x52\x41\x88\x2a\xdd\xd0\xfb\xfd\xa5\xa9\xec\x65\xf1\xcb\x4b\x05\x4a\x9f\xd9\x10\xf6\x00\x0b\xb0\x01\x09\xa4\x4a\xa7\x52\xec\xf9\xa9\x14\x6b\x42\x11\xad\x64\xac\x16\x9b\x7f\xa0\x40\x3b\xc9\x98\x98\x47\x84\xa2\x3e\x58\x32\x38\xd3\xcd\xcc\xcd\x7d\x58\x3a\x24\xb3\x7e\x7d\x7e\x30\xc6\xa8\x2d\x2d\x24\x1e\xe9\x20\xb0\xe1\x64\x32\xef\xcd\x09\xa5\xa5\x90\xf3\x39\x51\x79\x32\x5e\x52\x9e\xcc\x3a\x83\x96\xe6\x96\xa2\x2a\x5c\xeb\xa0\xf4\x89\x12\xeb\x27\x5f\xa7\x8c\xfa\x06\x48\x9d\xdb\x98\xb9\x03\x16\x27\xd7\xaf\x2f\xcc\x46\x8d\xd5\xe7\xb5\xae\xad\x38\xaf\x85\x49\xb4\x5b\x55\xa3\xf7\xdb\x4d\x60\xe4\x48\x08\x6f\xed\x55\xc4\x20\x69\x69\x77\xc1\xb8\xe2\x0e\xea\xdd\x32\x56\x49\xce\xf8\x04\x82\x40\xe2\x92\xba\x19\x48\x83\x66\xb7\xac\xf0\x04\xe0\xb8\xff\xd4\x57\x8a\xe6\x79\x52\x54\xb7\x95\x5c\xee\xbd\x8b\xad\x33\x96\x5e\x3a\xcf\xba\xc4\xb1\xfd\xae\xbb\x9f\x3c\xa7\x64\x1e\x6e\xec\xa4\xd1\xe3\x4e\xef\xba\xe7\xce\x63\xdd\x25\x77\x7d\x44\xaf\xb7\x3e\x77\x12\xf5\x56\x7c\xd7\x75\x56\x35\x53\x47\x26\x41\xeb\x62\x22\x6d\x83\xce\x17\x61\xbb\xc3\x83\xb0\x52\xaf\x09\x96\x96\x63\x1b\xc8\xb2\xd6\x60\x69\x5d\xb6\x06\xeb\xf3\xd6\xaa\x74\x1a\x35\x50\x61\x20\x0b\xfb\x63\x46\x7d\x65\xf8\xbf\x56\xc8\x2a\xe6\xd2\x80\xa5\xc2\x5f\x14\xf1\x4d\x3c\x71\x35\x7f\xa6\xc1\xc6\x77\x0a\x95\x41\x22\x23\x5a\x47\x7e\xf7\x61\x24\x8f\x5d\xec\x4e\x15\xc9\x0a\xaa\x49\x28\x01\x41\x2d\x1a\x35\xac\x25\xa9\x25\xaf\xa4\x2a\x75\xf8\x19\x07\x6a\x24\x19\x55\x13\xa5\xe4\x0c\xa5\xd3\x95\x26\x10\xe1\x08\x4c\x5e\x21\x9b\xdf\x6f\x0e\x11\x2e\xdd\xb2\x7a\xe2\xc4\xe1\xf1\x21\xed\x67\x9e\xfa\x41\xc9\x30\xe2\xd1\x8f\xee\x5a\x3e\x61\xd1\xb8\x61\xc3\x1c\x4b\x3d\x44\x0e\xb4\x0e\x4e\xd0\xf7\x43\xb4\x01\x04\x32\xad\x58\x0e\xca\x3f\x7c\xb2\x34\x53\x28\xee\x4b\x18\x59\xe1\xe1\x0f\x4a\xea\x35\xb6\x66\x89\x48\xce\x10\xc9\x7c\xff\xed\x30\xae\x34\x87\x25\xb9\xdb\x69\x09\x62\xdf\x4c\x89\xd2\x6b\x47\x1e\x49\xf1\xb5\x92\x1c\x91\x92\x18\x81\xdf\x41\x6b\x42\x92\x95\xe6\xe1\xe9\xb4\x12\xc3\xfa\x1b\xf8\xbc\x26\x81\x38\x59\x8d\x50\xca\xb1\x81\xd6\x4c\x3c\x64\xe2\xdf\x00\x7a\x22\x77\xa1\x99\x9f\x0c\xdd\xe3\x68\x59\x4a\x7c\x82\xf2\x9b\x1c\xf3\x9d\xcd\xd4\x3b\xf8\xde\x9b\x1c\x4d\xfd\xcc\x15\x77\x3a\x3a\x8d\x5c\x44\xf9\xe1\x2d\xae\xa7\xa8\x97\x8a\xec\x97\x10\xa2\xc0\x0f\xea\x2b\x6c\x98\x88\xe6\xbb\xa7\x1a\xfe\x95\x0d\x13\xd0\x94\x3a\x29\x53\x66\x82\xb3\x8d\xe3\xf6\xaf\x30\xb1\x6f\x15\xcd\x96\x98\xf8\xdb\x54\x81\xbf\xf9\x8e\x6b\xa5\xe5\xdf\xe0\x6f\xbe\xcf\xba\xe2\x98\xdc\x99\xe6\xb6\xc0\x4a\x7c\x2e\x76\x9d\x75\x5e\x3f\x45\x78\xdd\x08\x26\x95\xe5\x75\x53\x9e\xd7\xcd\xd8\x13\xc3\x26\x33\x10\x24\x6b\x1c\xbf\x27\xd7\x8b\x7d\xfe\xb2\x9c\xbf\xd9\x4c\x43\x39\xe6\xf7\x3b\x3f\xe5\x7f\x3b\xf1\xc7\x2e\x28\xc3\x7f\xec\xbb\x87\xb9\x7c\xd3\xae\xb9\xf5\xd9\x49\x9b\x76\x6b\x83\x92\xdc\xcd\x89\x2e\xba\x9c\xfa\xfb\x5f\x8f\xb9\xcd\xb9\xe2\x03\x68\x33\xb0\xfe\x2b\xdc\x0c\x3f\xcd\x80\xfd\x37\xe4\x9f\xff\x82\xec\x1e\xbf\xa0\xcc\x9d\xa0\xfa\x84\x52\xcd\xe5\x13\x04\x7a\x81\x36\x00\xe3\x4a\xc4\x49\x13\x04\x91\x00\x49\xbc\x78\x29\x78\xe2\xf7\x7e\x1e\x45\x99\x97\x72\x0f\x64\x55\x9e\x9c\xfe\x97\xc4\xcd\xcf\x93\x52\xf4\x3e\x1a\x2b\xbc\x8f\xa6\xfc\xfb\x68\xfe\x17\xdf\x47\xca\x1f\x18\xd9\x9e\xf2\x09\x96\x58\xe5\x1b\x80\x67\xae\xbc\xf6\x8a\x9b\x2e\x5e\xfd\x6e\x6a\xd7\x98\x4a\x77\xf0\x79\xb8\x73\xe9\x4d\xe3\xc2\xef\xce\x5d\x50\x78\x1b\xcf\x91\xb7\x11\xab\xf0\x36\x1a\xf3\x6f\xa3\xe9\xdf\x7d\x1b\x26\x22\xca\xf2\xfc\x76\xd3\xf9\xcb\x30\xfd\x7f\x8b\xce\xce\xd2\x5d\xb9\xa4\x1f\xd6\x07\x22\xe0\x6c\x7d\x2a\xcf\x6f\x6c\xcb\x8d\xd8\xa8\xb9\x07\xbd\x8a\xdf\xa7\x22\xbf\x9b\x60\xc7\xf0\x01\x62\xf9\x29\xfe\x10\x69\x8e\x08\x49\x19\x9b\x97\x2c\x1b\x27\x58\xf5\xc5\x1b\x74\x8b\x38\xcf\xf6\x5f\xa7\xab\x69\x85\x33\x3f\xd2\x7f\xb5\xae\x65\x56\xfe\xcc\x47\x1d\xf9\x35\xbb\x34\x5f\xcb\xaf\xd3\x77\xfa\x0c\x06\x6b\x2b\x6d\xf5\x41\x55\x09\xd4\x94\x82\x28\x3e\xd0\x6e\x1f\xfc\x1d\xbe\x9f\x66\x87\xaa\x0c\xe9\xb7\xe6\x47\x71\x00\x0a\x0a\xd0\x24\xa1\x68\x1a\x35\xcb\x68\x70\xe9\xd2\x1f\xa5\x8a\x95\x64\x14\x3d\x99\xe5\x3f\x26\xd3\x52\x69\x0d\x10\xbb\x38\xd0\x22\x64\x1c\x33\x87\x9f\x68\x1f\x10\xfc\x2c\x38\x61\x77\x4a\x6e\xdb\x35\x99\xca\xe2\xff\x57\x66\xe7\x96\x1c\x3f\xc2\x7d\x28\x78\xc9\xce\x9d\x0d\x54\x1f\xe8\x45\x3d\xe3\x66\x9b\x45\x15\xd9\x12\x48\x4e\x29\x76\x8b\x8a\xdc\x49\xe4\x4c\xe4\x97\xef\xf8\x49\x8d\x4f\x84\xf1\x8c\xc3\xdf\x90\x4c\xd2\x7d\x41\xae\x64\xc6\x43\x26\x48\x3d\xb2\x18\xcf\x88\x9e\xfc\x68\xa9\xc7\xad\xf8\x24\x92\xc7\x1d\x8c\x6f\xbd\x86\xdc\xba\xbe\x8d\x07\xf9\xe8\x72\xa7\x66\x1f\xbd\x67\x7f\xa0\x78\xb9\x53\x07\x24\x80\xaa\xbe\x94\x2f\x56\x7e\xc9\xd3\x9f\x0f\x7f\x8a\x6f\x57\x3b\x1b\x66\xb3\x0f\x3f\xbc\x31\x6c\x5d\xfa\x59\xef\x91\x3d\xf7\xdc\xf7\xe4\xa6\xcd\x4f\xad\xbd\x8f\xa9\x83\x2e\x38\xf8\x09\xe7\xe2\xd6\x55\x6b\x7a\x7a\xd6\x1c\x1b\xb4\xf1\x69\xd8\x0c\x6d\xfb\x0f\x2b\x6f\xc5\xfe\xb0\xb7\xd7\x34\xff\x2d\xec\x21\xb5\xd7\x59\x03\x4c\x2f\xdb\x13\x8a\xc3\x6a\xac\xbf\x39\xd1\xc8\xb5\x74\xc2\x31\xf5\xa2\x35\xd3\xb9\x76\x66\xae\x69\xba\x7a\xfd\x7a\xa3\xb7\x82\x5f\x48\x7a\x0b\xea\x06\xea\x23\x21\x98\x20\xf8\x54\xf5\x15\xda\x49\xa2\xe6\xb6\x99\x48\xbe\x9b\xa4\xb6\xee\x7b\x37\x10\xb4\x45\x7d\x27\x6a\x16\xa8\x62\xe6\x56\x6e\x1e\xc1\x91\x73\x61\xde\x7e\x2c\x99\x6d\xbf\x73\x00\x7e\x07\x48\x41\xc8\x18\xfd\xf5\x12\xf8\xf1\x81\x07\xde\x91\xe8\x46\x0e\x1c\x5e\xda\x83\xf4\xca\x68\xa0\x6d\x40\x90\x90\x71\x78\x3b\x09\xa4\xe9\x56\xd7\x40\xbf\x1b\x2a\x8a\x17\xcd\x77\x95\x2a\x8a\x0c\x0b\x90\x02\x46\x2c\x9d\xbf\xbb\x23\x7a\x5f\xcc\xed\x27\xee\x8b\xc1\x4e\x44\xc8\xaa\x66\x42\xf5\x04\x6b\x3d\x22\xc6\x49\x29\xd9\xdc\x2c\xd3\xed\xb3\xe2\x08\xda\x1f\x54\x4d\x6d\x33\xa8\x06\xd3\x17\x09\xd2\xfe\x19\x3f\xb6\xd6\x0d\x69\x54\x23\x65\x6d\x32\x5b\xdf\x52\x74\xaf\xb1\x13\xdd\x6b\x49\xfa\xa0\x62\xab\xcc\x2f\x8b\xe8\xae\xaa\xdc\x2c\xc3\x1d\xd2\x39\x91\x1b\x46\x1a\x65\x8c\xfb\xae\x26\x33\x72\xe7\x0f\x88\x0e\xa0\xb8\xb8\x3c\xae\xda\x09\x6f\x98\xe2\xf0\x3a\x0d\x1c\xde\x4a\x00\x00\xa6\xcb\xd3\x9c\x86\xbf\x54\x78\x6e\xcf\x18\x5e\x92\x71\x6f\x5f\xe8\xfd\x3c\xfd\xfa\x99\xfa\x75\xf3\x28\x75\x9c\x6a\xb4\x3d\x94\x34\xf1\x38\xcd\x4d\x3c\xf9\x26\x08\xa3\x67\x47\x11\xfc\x7a\x8a\xfa\x7b\x3d\x3e\xcf\x49\x76\xec\xec\xcc\x7b\x85\x15\xfb\x74\x0a\xae\x21\xbe\x1f\xad\x43\xdf\xa7\x1f\x06\x97\x1b\x28\xda\xa5\x97\x84\xaa\x13\x8a\x4f\xc0\x77\xe5\xcc\xe3\x4e\xd4\x9c\xec\x25\x49\xb4\x29\x45\x71\xfa\xb0\x42\x0c\xe8\x4b\xba\x4d\xd7\x55\x1c\x87\x9b\xaf\x6c\xb3\x39\x67\x61\xdc\x9a\xa6\x99\xa3\x6b\xe2\xab\x68\xb3\xf3\x3b\xfb\xe2\xe0\x81\x32\x77\x87\x06\x27\x94\x26\xa1\xb8\xfd\x6e\x48\xb9\xbb\x93\x8a\xee\x6e\x28\x8c\x2b\x35\x64\x8f\x1f\x19\x13\x43\x0d\x12\xb2\x91\x86\xd4\xda\xc1\x64\xab\xdf\x4e\xa7\xab\xae\xa9\xa5\x95\x3c\x38\xb9\x49\x92\x33\x35\x0d\x2d\xf8\xdf\xb3\x49\x19\x57\x6d\x1d\xfe\xce\x7a\xb2\xf7\x5b\xca\x86\x13\xdd\x31\x9c\x6c\xe2\x4b\xa5\x7b\x3e\xf6\x8d\x89\x4d\x66\x4c\x91\xe0\xc0\x38\x2c\xa1\x81\x0c\x5c\xf5\x89\x71\x58\x0a\x1e\xa9\x59\x7b\x06\x0b\x9e\x68\x41\x75\xce\x2a\xf1\x99\x0b\x7d\x85\x51\xd0\xda\xff\x1d\x36\x5b\xd5\x6c\x03\xbd\xc4\x06\x6b\xbe\x3d\x16\x5f\x62\x03\xb9\xc4\x98\x7e\x73\x83\x8b\xfa\x0a\x63\xa4\xaf\x30\x10\xae\xab\x3f\x71\x5f\x61\xc3\x09\xfb\x0a\xcd\x8e\x76\x65\x5d\x79\x4f\x81\xca\x0d\x27\x50\x94\x7f\xcd\xd3\x9d\x9b\x4e\x7b\x0a\xe9\x7e\xf7\xd1\x96\xa5\x20\x0c\x06\x81\x9b\xf4\x3e\x2b\x97\xad\x10\xa7\x65\x3d\xde\x10\xe7\x88\x2b\x1e\xb6\x00\x14\x44\x4b\x62\x12\x31\x03\x6a\x46\xf2\xe3\xbb\x92\x3c\x62\x9c\x58\x06\xc9\x2e\xc9\x3b\x39\x31\x54\x13\x6d\xa2\xdd\x57\xdd\x16\x21\xd6\x48\xe3\xd1\x10\x41\x7f\x23\x08\x07\x8a\x1d\x90\x52\x22\xb2\x94\x09\xf4\x68\x98\x91\x6c\x27\xfb\x70\xcb\x25\x43\x7a\xe0\x8f\xd4\x3f\xbd\x35\xf1\x95\x5d\xda\x31\xed\xb7\xb0\x1a\x3a\x36\xae\xd5\x5e\x82\xdf\x5d\xf7\xf5\xa3\x5a\x46\xdb\x00\x57\x9b\xd3\x09\x1f\x7d\x01\x67\xee\x9c\xb9\x65\x06\x09\xfa\x7e\xa7\xbd\x1f\x83\x99\xad\xb9\x54\x53\x33\x5c\xcb\x75\x9b\xd3\x0a\x2c\xdd\xfd\x25\x44\x09\x2f\x46\x82\xbb\x74\x6e\x0c\x2d\xda\x0c\x39\xc2\xb4\x19\x92\x22\x42\x0f\xf6\x91\xfe\x07\x32\x61\x78\x4a\xbf\xcd\x90\xa3\x60\x5c\x19\x0c\xa4\xfc\xf5\x23\xaf\x74\x9a\x9d\x6e\x87\xac\x8f\x36\x0d\x1a\x3a\x02\xab\x67\xd1\x22\xc9\x4a\x8c\xe0\x09\x1a\xbb\x22\x47\x9c\xfc\xae\xc8\xb2\xd3\x3f\x27\xd8\x1c\xf9\x88\x89\x3b\x73\x4e\xbc\x45\x92\x7d\xcd\xdc\x5c\x33\x39\xbf\x52\xd2\x90\x9b\xb1\x84\x57\x8f\x9f\x58\x6e\x50\x4b\x42\xa9\xb7\xaa\x99\xfa\x16\x2c\x28\xf5\x8d\x62\x1c\xd5\x24\x4b\x84\x09\x2b\xc2\x48\x50\x45\x91\x72\x72\xd5\xdd\xe8\x97\xac\x71\x92\xba\x8f\x91\x0e\x1c\x0a\x4e\x55\x23\xc9\x68\x10\x7e\x68\x59\x4e\x74\x85\xa8\x0b\xf2\xaf\x88\x56\x91\x47\x32\x90\x68\x3d\x58\xe4\x96\x9c\x40\xb8\xf8\xd7\x0d\x07\x4d\xb7\x17\x5e\xae\x83\x3f\x42\xe2\x9f\x91\xe0\xd9\x01\xb6\x8e\xa2\x11\x09\x22\x77\x43\x47\x60\x1e\x0c\x1d\x4e\xd0\xc8\x0d\x81\xd3\x57\x91\x0e\xb2\xc5\x95\xc1\xc1\x82\xec\xe9\x5b\x49\xbb\x87\x8b\x5e\x6b\x5c\x39\x25\xa8\xa2\x53\x12\xca\xf0\x60\x3f\x61\xc4\x6c\x1b\x99\x26\xbd\x24\x3d\xbc\xdd\x19\xa8\x6b\x1e\x51\xbc\xa5\xb4\x8e\x46\x46\x81\xef\xb9\xa6\xb4\xd8\xb3\x1b\x68\x69\x69\x31\x1b\x07\x58\x61\xca\x02\x13\x2f\x0d\xd9\x6b\x27\x5e\xd3\x6d\x03\xc8\x5e\xb1\xd7\x64\x92\x36\xdd\x65\x2a\xa3\xc5\xf2\xde\x13\x16\x2b\xfc\x3c\xfd\x12\x0e\x8d\x85\xf4\xbf\x28\x5f\xe6\x44\xe1\x89\xa5\x8b\x59\x99\xf7\xa4\x4e\x20\x58\x3f\x28\x38\x53\x86\x5c\x7d\x41\xe4\x6a\x04\xb8\x75\x20\xb9\x4a\x26\x94\x21\x98\x1d\x6d\x45\x92\x04\xe3\x4a\xc2\x49\x46\x81\x2b\xec\xb7\x1d\xa9\x37\x1f\xed\xa4\x02\xf3\x7f\x47\x5e\xcc\xde\xe5\x89\xa5\xe5\x60\x9e\x2d\x03\x08\x0a\xb3\xa6\x28\x07\xa9\x8d\xe6\x47\x93\xbd\x41\x4d\x60\xdd\x40\xb6\xad\xd9\x2c\x20\x04\x9a\xc7\x41\xa0\x79\xca\x08\x08\x41\x94\xb4\x4b\xb2\x52\xd3\x44\xd0\x79\x88\xfe\x69\x2c\x91\x94\x7f\xc7\xd8\x19\xa9\xa4\xd8\x40\xf2\x12\xf0\x8f\xb4\x66\xdc\x17\xa7\xe6\x9d\x40\x5e\xfa\x3e\x4e\xed\x9e\x20\x8f\x7b\x71\x4c\x41\x5e\x88\x8d\x6b\x05\x49\xb0\x72\xc0\xed\xc7\xa9\x52\x41\x49\x3a\xc8\x0c\x5b\x05\x41\x19\xa1\x0b\x8a\xae\x59\x86\xfd\xdf\xd8\x7f\x6c\x6a\x78\x3d\xb1\x98\x1c\x72\x5d\x92\x9c\x1f\x1e\x61\x19\x48\x4a\xe0\x5f\x3c\xa3\x5e\xee\x08\x8d\xde\x7d\x6a\x01\xd7\xa9\x49\xc7\xbe\x9b\xa2\x57\x4d\x2d\x7a\xb5\x94\x4f\x65\xd9\x2a\x3a\xbe\x5f\x40\xbe\xb3\xf9\x08\x8e\xbb\x8d\xe0\xb8\x23\x2e\xa9\x58\x7c\xfa\x66\x60\x1b\xbe\x6c\x8f\xee\x9f\xa6\xa4\xa8\x94\x92\x62\x52\x54\x2a\xb6\xd1\x07\x76\x31\x5f\xed\xda\x95\x93\xc3\x45\x68\x77\xb9\x4d\xcc\xc2\xa3\x9d\xcc\xb3\xb9\x99\xc5\x80\x77\x7a\x8f\xb8\xe5\x59\x52\xab\x99\xdb\x7f\x7b\x33\xe9\x9f\x69\xaa\xb0\xb5\xb9\x59\x4f\xeb\x66\xf8\x40\x90\x6c\x07\x90\x76\x0a\x62\xb8\xa6\xbe\x91\x36\x6f\x29\x38\x64\x38\x99\x35\xce\xc5\x53\x06\xc5\x4b\x9d\x3b\x4c\x74\x94\x5b\xf0\x2c\xcc\x2b\xa6\x07\x00\xc0\x1f\xe1\x7b\x80\x07\x04\xc0\x75\xd4\xdb\xc6\xf4\xb0\x0c\xe1\x7b\xd6\xeb\x26\xbe\xb6\x97\x55\xb3\x10\x90\x6f\x6d\xfe\x54\x4a\x81\xa2\xaa\xf0\x22\x5d\xb8\x86\x64\x92\xe0\x94\x7c\xaa\xc2\x79\x93\xc9\x8c\x2c\xe1\xc7\x29\x03\x31\x8e\x24\x4a\xbb\xe0\x4b\xd2\x04\x68\xd1\x8e\x06\x3d\x74\x97\xda\x52\x6d\x29\x5f\x3e\xcd\x27\x45\xa5\x98\x14\x88\xb6\x45\xc9\xc5\x1c\x38\xb0\x2b\x27\xef\xda\xc5\x7c\x95\x93\xb9\xc4\xbd\xff\xf8\xc7\x3f\xfe\x71\xef\xb1\xf7\xf0\xb5\x70\x89\xcf\x3f\x27\xf8\x0a\xb2\xbe\x4b\xbb\x16\xc7\x0a\x11\x40\x06\x13\x51\x30\xa1\xb8\x68\x3b\x93\x25\xa5\x40\x8b\x8a\xf8\x24\x62\x13\xa4\x3d\x30\x42\x0e\x5b\xe3\x50\x15\xce\x9a\x4c\x66\x6a\x22\xf8\x38\x35\x16\x31\x9e\x89\xd4\xe0\x6f\x23\xf8\xdc\xfa\x72\x71\x8f\x43\x25\x2d\x83\x35\x11\x5a\x88\xf6\x4a\x8a\x9d\xc4\xed\xc1\x08\x16\x2d\x9b\x9e\x9f\x6d\xa3\x2b\xa0\xca\x5c\x54\x4c\x92\x1f\xce\xc2\x8c\x36\xb5\xca\xde\xf6\xfc\x55\x07\xde\x24\xad\xf9\x59\xee\xd0\x9a\x5d\xbb\xd6\x64\x66\x9d\x76\xde\x79\xaf\xbc\x9f\x9b\xc3\x6c\xba\xad\xeb\x85\x43\xb9\xaf\xb9\x43\x00\x30\xc7\x7f\x0f\x00\xf3\x1b\x4b\x8a\xd4\xd2\x7e\x4e\x37\xac\x29\x21\x1e\x87\x37\x99\x88\xbe\x22\x05\xd5\x25\x91\x97\x8e\x5e\xd8\x92\xdd\x56\x16\xbb\x18\x2e\xab\x8a\x40\x1e\x80\x2e\x10\x54\x51\x80\x42\xd1\x46\x7d\x6a\x26\x5a\x8d\x29\x8b\xc6\xc4\x38\xaa\x4d\x66\xaa\xa3\x04\xc5\x3d\x48\x5c\x3f\x14\x75\x93\x2d\x0b\xf6\x20\x2d\x9f\x54\x07\x24\x59\x61\xbd\xa4\x1b\x47\x11\x64\x1c\xcb\xca\x8a\x95\x82\x8a\x94\x9f\x3b\x30\x83\xd4\xd5\x54\x68\x8f\x16\x0c\xe0\xbd\xe2\x5e\xe8\xfe\xd8\x7b\xcc\xf1\x0d\x00\x30\xb7\xf2\x9f\x81\x00\x08\x83\xf9\xfa\x86\xb9\x10\x04\xf1\x8a\x14\xd7\x98\x29\x0e\xc2\xb8\x12\x76\x90\xbe\x03\x83\xaa\x08\x01\x4e\x31\xa8\x0a\x9f\x2c\x55\x52\x4a\x5a\x5c\x81\x9a\x6c\xb6\x74\x68\x42\x9f\xe4\xc1\xfa\x6b\x08\x00\xcc\x5a\x61\x0f\xd9\x67\x32\x15\x64\x38\xb2\x80\x82\x27\x0b\xf5\x45\x7d\x57\x11\xb2\x25\xf5\xf6\x66\x92\x4a\x16\x48\x33\x77\xc6\x21\x90\x87\xe1\x22\xf0\xb3\x19\x81\x14\x07\x04\x8e\xb4\x0c\x19\x5b\x1d\xc8\xf2\x92\x02\xb7\x87\x30\x73\x73\xaf\x1b\x9c\x5d\xbf\xbe\x94\x9b\xcc\xf1\x8f\x01\x60\xc6\xf0\x0b\xc9\x6e\xb1\x46\x7a\x16\xb2\x2d\x37\xff\xe9\x56\x02\xf4\x6b\x71\x18\xfb\xc5\x58\xfc\x09\x52\x4a\x6a\x64\xe6\x6a\xd7\x66\xb9\x0f\xd7\xaf\x37\x66\xa1\x40\x2d\x00\xcc\x43\x96\xb1\x04\xbf\xf1\xa7\x15\xf1\x1b\x91\x2d\xa1\x70\x56\x35\xc3\x91\x32\x07\x67\x25\xbb\x57\x0c\x4d\x0d\x83\x64\xb5\xab\x1b\xc6\x07\xc2\x77\xc4\x57\x69\xd1\x97\xf7\x60\x55\x0e\x01\xdd\xa5\x48\x20\x1f\x6d\x1c\x85\xb8\x29\x4e\x5e\x9a\xf8\x52\x5b\xe4\xcf\xc6\x75\xf0\x4c\x23\x47\xfb\xdd\x59\x25\x42\xc7\x1c\x7f\x0b\x00\x66\x12\x7f\x84\xcc\x79\xcd\x36\xcd\x79\x55\xa0\x46\x36\x53\xe3\xa4\xbb\xd2\xb1\xaa\x33\x4e\xec\x31\x9d\x58\x72\x16\x4e\xcc\x16\x9f\x58\x4a\x49\x23\x8b\x4e\xfa\x51\x96\x3f\xa2\x1f\xf2\xe8\x23\xfa\x5e\x7c\x30\x5d\xeb\x60\xe6\xe9\xf9\xb9\x9b\xcd\xf9\xb9\xfe\xe0\x9e\x7a\x96\x8e\x3c\x89\x81\x31\x3e\xbb\x65\x91\xb1\xc6\x8d\x8d\x27\x7a\x96\x4e\x11\x65\x49\xce\x38\x7d\xd5\xa4\xda\xe8\xab\xa6\x13\xef\x4e\xc9\xc8\xdb\x99\x61\x40\x4b\x12\x56\x06\x18\xe8\x74\x53\x6e\xca\xcc\xe9\xa2\xb4\x1d\x0b\x52\x5a\x07\xbc\x8d\xff\x82\x4c\xbc\xd5\x81\x85\x20\xc3\x60\xca\x6a\xf0\x6f\x11\xcc\x7a\x67\x42\x11\x05\x15\x85\x12\x8a\x87\xa3\xc5\x8d\x9a\x5e\xe4\x4e\x2a\x75\x0e\xb5\x5b\xa8\xab\xb1\xc6\x15\x20\x91\x29\x01\x41\x22\xee\x90\xdf\x49\x2b\x1d\x75\x82\x24\xef\x64\x58\xd1\xe9\xa1\xfb\xe9\x44\x27\x59\x27\x82\x18\x49\x01\x54\x61\x97\x9c\xdb\x53\x32\x2a\x97\x32\x9d\x7f\x91\xe1\xeb\x3a\xb3\xe6\xe3\x5b\x46\xea\x9e\xed\xd1\x37\xf2\xef\x7e\x3a\xc1\x87\x6d\x27\x79\xee\x39\x15\xf1\x57\xcd\x29\x6e\xa6\x17\xd9\x29\xf8\xb4\x9c\x3c\x21\x18\x6b\xc8\x00\x63\x75\x95\x01\x63\x35\x9d\xde\xb8\x81\x9f\x1b\xa7\x2e\xc6\x00\x35\xbc\x71\xb2\x8b\x1c\xce\xe3\x3a\x01\x0b\xa2\xa6\x5d\xe4\xf9\x75\xb2\x0e\x95\xfc\xe2\xf5\xcc\x7a\x4a\xda\x91\xd5\xc9\x24\xf2\xb8\x92\x8b\x13\x79\x0c\x61\x7f\xa1\x94\x4e\x24\xa7\x0c\x52\x03\x09\xc5\xa9\xbb\x69\x03\x4b\x23\x76\x5b\xb1\x77\xef\xd5\x9d\x37\x49\xd4\x93\xc5\x40\x71\x06\x48\xb1\x06\x01\xba\x74\xcd\x4c\xbd\x25\x0f\x71\x85\xbd\x56\x9d\xfe\xb3\x27\xfd\x60\xfe\xfc\x17\xf6\xef\x9a\x73\xaa\x99\xfe\x83\xde\x15\xd7\xf2\x3b\x8e\x5e\xfc\x7a\x6f\x98\xcc\xef\x6e\xd1\xbc\xec\x6a\xfe\x0b\x52\xf7\x8b\x80\x41\x60\x85\x79\xea\xd2\x9f\x42\xe1\x04\x71\xe7\xc4\x04\x6a\x49\x29\x2c\xa7\x1a\x88\x5c\x76\x32\x56\xea\x72\xa8\x8a\xe0\x24\x83\x97\x3e\x88\xad\xaa\x12\x74\xa8\x4a\xa3\x93\x66\x43\x5c\x38\x1e\x61\xc5\x74\x5a\xf1\x09\x92\x9c\x71\xcb\xe1\x34\x5d\x79\x12\x6d\x21\x0e\x5e\x58\x92\x51\x24\x8d\xec\x12\x72\x97\xac\x85\x21\xb3\x9a\x45\x44\x99\x2f\x78\x4b\x41\x1c\xd3\x67\x9e\x3e\x75\x4a\xf6\x91\xcd\x73\x4e\x83\x52\xbe\xae\xb1\xb4\x48\x2c\xb5\xbd\xde\xf3\x7e\xc4\xfd\xf3\x98\xbc\x75\x6b\xc8\x32\xd1\x14\x8b\x1d\x9f\xab\xad\x64\x96\x11\x2c\xde\x30\x48\x83\x8c\xc0\x50\x55\xc7\xe8\x69\x7d\x9e\x24\x54\x89\x3a\xb0\xf2\x92\x9c\x91\x3d\x21\x0a\x13\x64\x23\x3a\x0d\x09\x34\x9b\x5d\xcc\xfc\x62\xaf\x7a\x4b\xfe\x0e\x2e\x36\xf9\xa3\xa6\x3b\xb0\xdc\x57\xd4\x45\xc4\x1c\x5f\xa7\x79\x99\x0b\xc9\xac\x6d\x18\xb4\x83\x8c\xa0\xab\x5f\x46\x2c\x9c\xc9\x51\x38\x93\x82\x8f\xd4\xef\x44\xec\x09\x4e\xb4\x24\xcf\xb0\x6a\xd3\x89\xcc\x3c\x12\xb6\x17\x37\x36\x31\xe0\x80\x36\x9a\xfb\x27\xa9\xf7\xfb\xc1\x39\x85\xad\xdb\x7a\x2c\x62\x2c\x92\xb2\xd3\x00\xc4\x4e\x2d\x9b\xe4\x50\x89\x17\xe2\xb6\x4b\x72\xa6\xca\x41\x7a\x79\x25\x49\xb1\x90\x19\x3c\x52\xd7\x67\xab\x0c\xd7\xbe\x9d\xac\xe7\x86\x16\xc9\x93\x0f\x32\x0f\xec\xba\x89\x11\x0f\xe7\x7e\xc5\xcc\xfe\x30\xf7\xdd\x7d\x2b\x8c\x90\x92\xef\xc9\x25\xee\x62\x26\xe6\xba\xfa\x0e\x30\xbb\xbb\x72\x6f\x6a\x33\x0a\x71\x24\x03\x76\x68\xa3\xb9\x14\xd9\x1f\x15\xca\xa3\xfa\xdb\x52\x64\x27\x2f\x89\x47\xa8\xf9\x75\xd1\x78\xc4\xa5\x97\x42\x1d\xf4\xa1\xb9\xe8\x7a\x2d\xe4\x91\x32\x0e\x37\x29\x72\x78\x65\xa5\x8a\xf4\xcf\x90\xfc\x39\xe7\x30\x4e\x6b\x49\x8d\x83\xfd\x0f\xbc\x23\x63\xb5\x76\x4c\x84\x17\xbd\xaf\x9d\x01\x3f\xfa\x50\xeb\x5a\x75\x9a\x71\x66\xc1\xdb\xf7\x41\x66\xea\x0c\xb8\x54\x8b\xe7\xee\x62\xc0\x22\x6d\x51\xe1\xd4\x44\x07\x71\x29\xae\x13\x38\xc1\x28\xfd\xc4\x55\x74\xd2\x16\x59\x52\x10\xb9\xc8\x89\x9d\x7e\x7c\x62\xc2\x56\xa7\xbe\x05\x4c\x07\xde\xb5\x17\xa2\xa3\x3c\x13\x77\xbc\xe4\x98\x01\x6f\xfb\x50\xbb\x18\xbe\x7c\x58\xdb\xbc\x86\xeb\xd4\x3e\xbf\xeb\x8e\x05\xf0\x6d\xad\x3a\xf7\x30\xfc\xfa\x6a\x6d\x75\xbe\xfe\xac\x59\x96\x02\x1e\xb8\x8c\x4f\xc6\xd1\xa4\xbe\x2e\xca\x6d\x40\xee\x65\x58\x52\xf5\x60\x79\xbd\x9a\xcf\xe2\xb0\x4d\xb0\xb8\xd2\x85\x70\xd2\x0c\xed\xbe\x8b\x59\xdd\xf7\x8f\x3c\x40\xdd\xd1\xaf\xb6\x16\xe1\xb9\x3f\x05\x00\x33\xde\xb2\x9d\xcc\xa9\xc7\xe8\x9c\x3a\xb2\x25\xca\x4e\xc0\x97\x19\x51\x7f\x4a\xff\xb9\x8b\xb3\xc2\x7c\xe3\x87\x7e\xf7\xb0\xe0\xfd\xee\x88\x2e\xa3\xac\xc6\xf7\x10\x7a\x26\x9d\x14\x3d\xc6\x78\x4d\x95\x83\x6e\x83\x16\x59\x1d\x37\x10\x55\x49\xc8\x69\x22\xcf\x24\x94\xcc\xea\xdc\xd6\x82\x2c\x1e\xfd\x6a\xab\x49\x00\x19\x70\x81\x36\x1a\xce\x13\xbc\x84\xbe\x41\xa5\xf4\x21\x96\x4c\xe1\x63\x43\x96\xa7\xd2\x4a\xa8\xcc\xff\x7c\xac\xf5\x2e\x30\x7e\xfc\xf4\x6c\xfe\x67\xc3\xfd\x94\xca\xfc\xbd\xf1\xcf\x13\x3a\x67\x94\xd0\x49\xc6\xa6\x2a\x91\x5a\x45\xb7\xbb\x11\x52\xab\xe8\xc2\x78\x64\xd3\x87\x85\xd8\xfc\xa5\x96\xbf\x53\x6d\xbb\xde\x25\x44\x68\xe6\xae\xc9\xb7\x03\x91\x3c\x00\xd3\x43\xf6\xf6\x3a\xc0\x38\x5d\x82\x61\x02\x59\x53\x84\xec\xc2\x00\x97\x15\x73\x58\xbf\x61\xb2\x3e\x94\x23\xc9\x27\x03\x43\x1a\x71\xfa\x47\x17\xee\x7c\x47\x76\x8e\xfe\xa9\x98\x7a\xee\xdd\xe2\x1e\x24\xca\x07\x7c\xdf\x12\x98\x50\xc2\x87\xac\xe8\x22\xd9\x11\x91\x53\x0d\x2f\xb5\x3f\x3f\x04\x1c\x17\x39\x89\x97\x5a\xb8\x6a\x73\xc9\x1c\xd3\xfd\x6c\xa1\x56\x7e\xf4\xab\xad\xcc\xc7\x86\xf5\xa0\x74\xbf\x44\xe8\x76\x81\xa1\x46\xfe\x23\xa1\x58\x38\x9a\xfa\x70\x9b\x69\xe7\x30\xcb\x9d\xc6\x52\xba\x54\x09\x0e\xc1\x8e\xec\x9d\xc6\xa7\x60\x42\x99\x5f\x9a\xea\xd2\x10\x84\x75\x3a\x1d\x60\x8c\xde\x69\x65\x65\xd5\x0c\xc3\xe8\xe8\x0e\xb6\x5e\x04\x93\xa4\xee\xc7\x26\x33\x56\xe2\x9f\x5b\xab\xc4\x38\x66\x33\x50\x18\xab\x5e\x99\x3c\x65\xb8\xa7\x5d\x4a\x49\x4d\x01\x9e\xd4\x26\x2d\xe1\xed\xbb\x60\x68\x8a\xf6\x28\xb3\xba\xef\xcd\x4b\x99\xd1\x97\xb1\xde\xdc\xac\x6d\xb7\xbc\xab\x8d\xdd\x0a\x8f\xa6\xe9\x3e\xcd\xaf\x00\x60\x62\x82\x17\xd8\xb0\x6f\x24\x62\xea\x98\x04\x59\x81\x27\xd2\x4f\xc4\x94\x25\xf5\xf5\x77\x2c\xfe\xe1\xed\x01\x8b\x14\x93\x2c\x72\x26\xdb\x75\xf6\xc1\xec\x15\xcc\xea\xa5\x6c\x43\x6e\xfa\x8f\x57\xac\xcd\x9d\xc1\x4c\x9e\x60\xc2\x2a\x5f\x0a\x3c\x20\x92\xd7\xcf\x05\xac\x72\xa3\x07\x50\x07\x25\x37\xe0\xc7\xeb\x60\x5c\xf1\x00\xbd\x55\x00\x89\x52\x37\xe3\xf0\x92\x71\x10\x3b\xcd\x0e\x0d\x88\x41\x6e\x12\xe5\x52\xdc\x71\x58\x9d\xd7\x55\xe5\x81\xc6\x8b\xfb\xab\x49\xce\x4b\x9f\xbd\x9c\x53\x01\x17\xc1\x98\xbd\x2c\x00\x20\x90\xea\xbf\x4d\x4f\xa1\xe8\x30\x07\xc8\x2e\x65\x39\x8b\x3e\x7b\x69\x93\x95\xea\x30\xd9\xf4\x4e\xcc\x22\x67\x10\xd2\x2f\x8d\x62\x7a\x1b\x45\x20\x07\x8f\xe6\x27\xdf\xfa\x81\x1a\x14\xe3\x82\x6a\xa3\xf9\xa9\x24\xc7\x15\x01\x57\x0e\xc4\xff\x00\x8c\x93\x7d\xee\xc1\x4a\x57\x11\x90\x32\x8c\x37\x42\xb1\xaa\x50\x8d\xfe\x9a\x4f\xfa\x56\x4c\xa6\xbe\xf4\x56\x0e\x16\x34\x6c\xb9\x5b\xe9\x6f\xf3\xcf\x26\x3d\x0f\xb5\xc6\xde\xd4\x93\xb9\x13\xec\x9a\x84\x1c\x64\xb1\x4f\x99\xeb\x21\xbb\x90\x33\x16\xb7\x2f\x7d\x52\xd7\x52\x70\x02\x8a\xae\xe5\x52\x83\x8e\x7e\xf7\x62\x26\xa1\xe8\x5d\xd4\x97\x7d\x17\xd1\x72\xef\xa2\xa1\xcc\xbb\x08\x7f\x9f\x77\x51\x54\xc8\xef\x77\x09\xe3\xcc\x4d\x0a\xe5\xae\xa1\xa8\x63\xc1\xfc\x36\xa2\xe0\xb2\x8a\xf7\xd0\x50\xe9\x6d\xc4\x60\x5c\x61\xf2\x7d\x0a\x5e\x89\xbc\x11\x79\x27\x67\x31\x9a\x15\x6c\xc6\x34\xef\x40\xb7\xc1\x9a\xc9\x2a\xbe\x90\xd1\x05\x9a\xfa\x5d\x89\x20\x98\x1b\x30\x18\xc0\x02\xc0\x7d\xc2\xf7\x00\x01\x84\xc1\xd5\x14\xc3\x17\xc9\x29\xa2\x78\x89\x43\x49\x07\x7f\x02\x62\x3e\xf9\xc6\xf4\x2a\x9c\x53\x45\x1c\xcd\x7f\x84\x1d\xaa\x22\xba\x49\x02\x0e\x7b\x99\xb2\xee\xb3\x87\x71\xf8\x2a\x54\xa5\xc9\x30\x8f\xcd\x89\xe9\x09\x58\xf4\xb9\x3f\x85\x71\xea\x76\xd0\x23\xb7\xa7\x02\x02\xeb\x29\x4b\xde\xc4\xfa\x97\x5d\x23\x7e\xf2\x7c\x11\x61\xec\x2b\x30\xf2\x5f\xfe\x03\xda\x1f\xfb\xfa\xeb\x00\x00\xc1\x01\x6d\x25\x79\xf7\x21\xb0\x50\x8f\x73\xbd\x06\x24\x30\xb2\xa4\x48\x59\xa5\x50\x47\x08\xc9\xe4\x55\x78\x69\x11\x41\x94\xa9\x7b\x1c\x32\xdd\x4d\x86\xb1\x3b\xf5\x65\x82\x6c\x1a\x90\xe6\x0a\xe4\x24\x71\xa9\x2b\x8d\xa0\xac\xb0\x3e\xfd\x72\x60\xaa\x39\x04\xcd\xa5\x94\x76\x18\xf3\xfb\xa4\x03\x87\x58\xbb\xd5\xb9\xfd\xc0\xee\x79\xa7\x4e\x3a\x6f\xc1\x22\xa6\xef\x75\xab\xc4\xf7\x1c\x5b\xf4\x20\x38\xce\x1c\x3d\x3a\xf3\xb5\x77\xc3\x0f\x79\x97\x2d\xe6\xf6\x1e\xdf\xd6\xf7\x25\x28\xec\xb3\x9d\x03\x22\xe0\x52\x53\x9c\x4e\xc5\x2a\x24\xaa\xf9\xa1\x62\xaa\xbf\x22\xba\x74\x45\x48\x4c\x4a\xa4\x0b\x2b\xae\x88\xae\x79\x7d\x52\x37\xe7\xb4\xb8\xe9\xea\xbf\xfc\xa4\x2b\x92\xd2\x28\x54\x4e\xae\xf2\x87\x6f\x33\x6e\x60\xc7\xfa\x48\xd5\x88\xec\xe2\xb7\xde\x58\xb7\x79\xe6\xe8\x31\x63\xef\x5c\xbe\xea\xd9\x07\xb9\xce\x4d\xd3\x67\xbd\xf4\x7e\xdf\xba\x07\x77\x84\xd6\x7b\xb7\xb3\x57\xde\x76\xcb\x8b\xef\xe5\xf6\x1b\x3b\x03\x48\x5f\x6d\x00\x84\xc1\xd4\x72\xc8\xf8\x41\xd2\xfc\x68\x64\x70\x4b\xd6\x21\x44\x4c\xeb\x10\xaa\x4f\x7e\x1d\x42\xd4\x57\x19\xe6\x5e\x61\xe6\x0e\x0c\xf2\x4f\xfb\x54\x0d\xbc\x92\x85\x04\x9b\xa3\x70\xfe\x22\x64\x8e\xe2\xf3\x97\xc0\xc9\x44\x4c\x70\x32\xd5\x27\x0f\x27\x13\xf5\x95\x87\xd9\x70\x33\x73\x2b\x63\xc8\x18\x67\xa6\xfb\x08\xc6\xea\xbb\x27\x56\x94\xe3\x79\x2c\xa1\xd4\x58\xd5\x4c\x4d\x8c\x94\x3d\xea\xc5\x38\xd9\xd2\xd0\x5c\x3a\x97\x63\xda\xfd\xa6\x6f\x45\x31\xaf\xa9\x08\x05\xc9\x0a\x4e\x54\x27\x65\x59\x97\x4f\x8c\x9d\xf4\xf5\x14\x77\x77\x54\xbc\xa8\xc7\x8b\x1b\x12\x06\xda\x23\x72\x5a\xa1\x21\xc1\xb8\xb7\x23\xe4\xde\x9a\xc0\x8d\xe5\xee\xed\x44\x3c\x30\x60\x55\x6c\xe5\x78\xe0\x31\xc1\xed\x84\xf4\x35\xa4\xf5\xe0\x7b\xc2\xab\x48\xc5\xad\x19\x65\x6f\xbb\x98\xfe\x4a\xb8\x47\x4d\x05\xba\xb9\x92\xfd\x29\xf1\xb2\xbb\x28\x8c\x9e\x47\xfd\xa2\x49\x9f\x4f\x80\x28\x8c\x66\x18\x57\x5a\x28\xee\xac\x71\xd1\x43\x75\x8c\x49\x25\x18\x4d\xa7\x51\x44\xda\x89\xaf\xba\x81\xec\x4a\x68\x96\x51\xfc\xfb\xec\x27\xc1\x3e\x42\xf4\x24\x36\xae\xbc\x10\xbb\xbc\x65\x7f\xf4\xb9\x09\x90\x49\x2c\x0c\xbd\x16\x7d\x6e\xc2\x49\x6c\x5e\x19\xa6\x4c\xf3\x8d\x7a\xad\x3d\x34\xbe\x67\x14\xfe\x9a\xc7\xe6\x2b\x60\x40\xc5\xc1\xb2\xb2\x28\x50\x43\xcc\x17\x6e\xe2\x85\x7e\xcb\x48\x70\xa3\x96\xfa\x5e\x49\x69\x0e\xd0\x91\x76\x83\x27\x0e\x33\x4f\xdc\xfe\x62\x9e\x7c\x2f\xcc\xa8\xe8\x00\xe8\x51\xee\x7e\xfc\xa8\x0c\x23\xd5\x9f\x0f\xa4\x37\x47\xf8\x3b\xff\x2e\xf0\x82\x3a\xb0\x0a\xd0\x65\xe8\x0e\x56\xa5\x2d\x95\x41\x9b\x4a\x33\xd3\x38\xae\xfa\xff\x71\xf7\xe6\x71\x52\x54\xe7\xfa\xf8\x39\x55\xdd\xd5\xfb\x52\xd5\x5d\xbd\xce\x4c\x4f\x4f\xcf\x06\x0d\xd3\x4c\x37\x33\x43\x03\xc3\xe2\x82\x3a\x2a\x1a\x17\x42\x14\x11\x71\x23\x28\x2a\xe2\x46\x14\x15\x89\xa2\x2c\x22\xa0\x88\xa2\x88\x38\x22\x18\x82\x55\x3d\x0d\x02\xe2\x82\x1b\x41\x25\xa0\x46\x08\x21\x46\x8d\xd7\x24\x9d\x4b\x8c\x31\x26\x41\xa0\x8b\xdf\xe7\xbc\xa7\xaa\xbb\xba\xa7\x07\xf0\xde\xfb\xfd\xe7\x77\xef\x27\x82\x63\x0c\xe7\xbc\xe7\xad\x73\xde\xe5\x79\x9f\x07\x3c\xa4\x9a\xcd\x65\x2d\x76\x68\xf2\xc2\x50\x18\x1d\x28\x10\x7d\x39\x49\xa4\xbd\x44\x92\xc6\x9b\x93\x19\x47\xa8\xd0\xc2\x8d\xe2\xb8\x1c\x12\xa1\xc6\xc9\x42\xcc\x68\x77\xd0\x71\x65\x0b\x2f\x23\x91\xe2\x5f\xc3\x05\x51\x0d\x9d\x8a\x22\x17\x53\x1d\xa5\x83\x6f\x8c\xd5\x31\xb3\xf0\x4f\xf0\xe8\xa9\x97\xb0\xfe\x7c\x96\x69\xc8\x1f\x60\xce\x39\xfa\xaf\x6b\x26\x29\xaf\x28\xcf\xbe\x71\xe8\x9b\x5b\xc7\x5d\x7c\xcb\xb7\x87\x98\xcf\xf0\xb5\x78\xae\x5f\x85\x8d\x7a\xf1\x3c\x7c\xad\xf2\x99\xb2\x3b\x66\x98\x10\x55\x3e\x42\x2c\xba\xf1\xd8\x41\x53\x93\x61\x02\xaa\x41\xfd\x51\x2b\x7a\x02\x65\xfc\x24\x72\xa9\x4a\xc9\x6e\x2b\x34\x4f\x59\x4a\x11\x21\x37\x5b\x72\x52\x22\x99\x8d\x3b\xfd\x64\x9f\x71\x72\x7f\x27\x61\x9f\x11\x1f\x28\x95\x36\xe0\xb8\xec\x14\x73\x52\x3c\x29\x39\xdd\x30\xa9\x64\xf7\xe5\xe4\x14\x8e\x53\xd2\x3a\xb6\x0a\xfa\xf6\x32\x17\x4c\xa7\xa5\x01\x42\xc6\xe2\x06\x59\x4f\x3b\x2f\x7b\xbc\x10\xa5\xf9\x29\x5d\xb8\x93\x87\x12\xa5\x14\x17\x32\x28\xd2\x40\xfe\x2b\xcd\x25\xe4\xab\x7d\xd0\xd2\x22\x8f\x8e\xde\xce\x48\x79\x69\x6f\xc4\xe6\xbf\xdd\xf7\xc1\x88\xe1\x6f\xdc\xbd\xeb\x9b\x7c\x93\x19\x9f\x76\xc9\x93\x53\x2e\x7b\xf2\x5a\xe5\x0f\xf7\x8e\xfc\xf0\xc1\x3f\x2a\xff\xdc\xb6\xe4\xb9\x55\x4b\x1f\x5b\xfd\xec\x23\x6c\x13\xe3\x9b\x7d\xcf\x9d\x8b\x98\x26\x6c\xc5\xf1\x9b\x6f\x9c\x76\x8b\xf2\x9f\xff\x9a\xa6\xcc\x89\x0c\x5c\xd9\x1c\xf9\x72\xfa\xcd\x78\x30\x36\xed\xd9\xfb\xe1\xae\xbd\x1f\x7d\x7c\xe5\xe3\xcf\x3e\x53\x98\x51\x33\x1c\x30\xcd\x00\xcd\x84\x48\x21\xbb\x53\xab\x9c\xb2\x68\xcb\xe9\xc4\x13\x34\x97\xb0\x93\x6f\xa6\xa0\x97\x60\x54\x67\x4c\x48\x3c\xd4\x63\x35\xf9\x20\x18\x37\xf2\x20\xe6\xee\xb0\x01\xab\xa3\x24\xf2\x85\xa9\x35\x83\xe8\x36\xe2\x18\x8e\x16\x85\x14\x8a\x1f\xc4\x0e\xbc\x14\xbb\xb1\x51\x39\x80\x17\xef\x53\x56\x2a\x9f\x1e\xc8\x74\xaf\xd9\xfa\xe1\x3d\x85\x64\x75\xf7\x1e\xe5\xd3\xab\xf3\xd3\x99\x09\xf9\x6e\xe6\xd0\x82\x79\xf3\xee\xc1\x5e\x3d\xbf\xce\x06\x84\xd8\x04\x17\x05\x9d\x92\xe1\xbd\x22\x26\x7b\x11\xb5\xce\x93\x50\x49\xed\x78\xf1\x0c\x44\x9f\x88\x4e\x0e\x96\x05\x42\x30\x23\xe8\xc4\x25\x29\xe8\xa3\x5e\xf3\xc8\xf5\x57\x9f\x35\xc4\xd7\x39\xf4\xc7\x8f\x5d\xc4\x16\x72\xd0\x9d\xd3\x6e\xb2\xaf\x71\x4e\x5a\x77\x6d\x7e\x53\x49\xfe\xc9\x42\x1d\xf9\x80\xaa\x4b\x11\xd1\xba\x26\x27\x6d\xe3\x20\xf9\xc6\x1c\x39\x29\x54\x6a\xee\x20\xb9\x9b\x7d\x91\x74\x5a\x0a\xf1\xb2\xb5\x06\xe6\xe3\x89\xa9\x7f\x90\xe5\x8b\xc9\x68\x45\xcb\x4f\x2f\x66\xa4\xbd\x4c\xff\x7d\x67\x49\x2e\x37\x59\x19\xc6\x26\x0c\x13\x91\x05\x85\xd1\x99\x3a\x2e\xce\x0c\x0f\x17\xae\x6a\x7b\x5a\x0e\x0c\xd3\x72\xa0\x5d\x3d\x01\x3b\x2d\x09\x4a\x61\x28\x3f\xca\x3e\xab\x4a\x64\x57\x56\x22\x2c\x3b\x91\xc9\xda\xda\xce\x29\x3d\x10\x5d\xf5\xb0\xe4\x4c\x4a\x7c\x3d\x88\xea\xd0\xf5\x65\xe7\x50\x47\xce\x21\x54\x3c\x87\xe2\x60\x6f\x08\xce\xa1\x46\x35\x7e\xbd\x36\x65\x0a\x64\x7b\x35\xfc\x46\xab\xc9\xe5\xf1\x07\xc0\xeb\x85\x8c\xc5\x4b\x93\xe7\x90\x6a\xff\xba\xde\xf6\x2f\x4d\xd5\xd8\x82\x9e\x48\xd9\x11\x4c\x2c\x66\x6d\x93\xe9\x71\x94\x9c\x82\x2e\x0f\x3d\x7a\x2d\x39\x10\x7a\x0e\x77\x23\xc4\x26\xe1\xed\xab\x41\xa7\xa8\x53\x9b\x24\x65\xcb\x78\xb1\x26\x9d\x14\x49\x48\x8e\xbd\x72\x8d\x23\x27\xbb\x78\x9a\xfe\xbb\x1c\x20\xc0\x22\xd5\x90\x7c\x00\x41\x6c\x23\xbb\x79\x15\xde\xa2\x5b\x6a\xaf\x43\xb8\xbb\xb8\xc6\x47\x4a\x8f\x41\x97\x57\x1e\xde\x5e\x7a\x10\xb0\xce\x29\xc7\x0e\x1a\x0c\xa6\x19\xa0\x76\x31\x0d\x65\xea\xc9\x93\x64\xb0\xe5\xa8\xbc\x22\xb8\xcb\x20\x20\xc2\x08\x8a\x10\x85\x99\x28\x94\x05\x48\x7b\x82\x6a\x4b\xd7\xc4\x8f\xb2\x18\x6c\xbc\xaf\xa6\x5e\x95\xb4\x88\x0a\x3d\x1e\x6f\x7c\x00\x44\x62\x86\x7a\xaa\x01\xef\xe3\x7b\xb0\xd3\x0b\x6c\xd1\xbc\x20\x79\xd2\x83\x5a\x3b\x40\xe5\xa4\xbd\x6d\x70\x0b\x06\x9d\x13\x6d\xa0\x99\x13\xbd\x35\xd8\x5f\xc3\x88\x5e\x83\xfe\x91\x9e\x72\xd9\xa7\x93\xba\xd7\x0c\x5f\xb8\xe8\xfd\x0d\x18\x7f\x74\x60\x73\x7a\xdb\xea\xfb\x96\xa6\xef\x79\xf0\xb9\x55\xe7\x28\x07\xff\xad\x1c\x3d\xa0\x5e\x00\xad\x52\x73\xcb\xdd\x37\x9c\x35\xf1\x82\xc1\x5d\x3b\x9f\xf9\xc5\x7b\x17\xac\x1c\x7b\xd3\xd5\x67\x5e\x3e\x36\x39\x7c\xfa\xd2\x6b\x5e\xff\x3d\x37\x52\xd7\x0f\x98\x72\xec\x20\x3b\x93\x8b\xa2\x18\x1a\x48\x32\x53\x98\xc7\x0e\x99\xd5\xd8\xc4\x4c\x9e\xa4\x16\xe2\x7b\x92\x3f\x29\xdb\x04\x98\xa1\x55\xa5\x60\xe4\x04\x09\x53\x6c\xbc\x30\xca\xc2\x9a\x5d\x62\x28\x5a\xdf\x3c\x90\xec\x4c\xe0\x7b\x38\x63\xbf\xfe\xb0\x71\xf2\x1c\x4b\xfe\xb4\x64\xe6\x7b\x10\x27\x04\x28\xef\x1c\xf8\x20\x14\x5f\x0b\x53\xcf\xb0\xd3\x42\x86\x0a\xa2\x2f\x3a\x59\xbc\x29\xbf\x7f\xe3\x95\xe7\x3a\x5f\x78\xe0\xa6\x5b\xae\x7a\xf9\xa1\x39\x23\xfe\xb4\x67\xff\xbd\x1b\xd7\x3e\x78\xd7\xed\xcb\x57\xdc\x3d\x0c\x5b\xd5\x2d\xb3\xc3\xe6\x3e\xd5\xb5\x68\xcc\x19\x23\x86\x9f\x37\x26\x35\xfe\x86\x73\x9f\x5c\x77\x7a\xf7\xf8\xf1\x5d\xa3\x2f\x19\x3a\xfc\xe2\xa9\xf8\xaf\x25\x35\xb8\xe2\x79\xa7\xd0\xcd\x15\xcf\x7b\x70\xa5\xf3\x6e\x53\xcf\x3b\x63\x6f\x6c\xa2\x32\xf6\xa3\xac\xf4\xcc\xfb\xc7\x13\xa9\xc2\xa1\x0f\x6c\xf9\xbf\x38\xf4\x52\x5c\xdd\x89\x0e\xde\xac\xeb\x23\x9e\xe8\xf0\x4b\x31\x77\xc5\xf3\x6f\x45\x33\x2a\x9e\x7f\xb2\x8f\xf3\x27\x71\x88\x8d\xdc\x3d\xf5\x0d\x10\x80\x8e\xb2\x52\x3f\x68\xee\x97\x68\x05\x47\x10\x7a\x38\x63\x7c\xe0\xff\xda\x11\x4a\x7b\xa7\xc7\x73\x86\x36\x9d\x15\x4e\xe0\x0f\xbd\x78\x23\xa6\x28\x5e\x83\xc1\xf8\x3e\x6a\x40\x1d\xe8\x31\xea\x13\xd9\x16\xca\x83\xaf\xb9\x85\xd4\x96\x90\x9b\x8d\x39\x2c\x0d\xd1\x7b\x47\x1c\xc7\xe5\xa4\x1b\xb0\xaf\x9a\xa3\xa4\x75\x17\x43\x9c\x5c\x0c\x3e\x5b\x7d\xe3\xc0\x96\x41\x6d\x64\xdf\x49\x21\xc3\x57\x27\xa8\xff\x48\x35\xc4\x67\xd4\x70\xad\xbe\x99\x17\x32\x03\x07\x25\xd3\xe9\xb4\xec\x6b\xe1\x85\x1e\xa4\xb9\x0d\xff\x03\xee\x8a\x5e\xc4\xf9\x27\x72\x9d\x0b\x4a\x38\xf4\x8f\xef\x3c\xca\x73\x65\xa2\xda\x60\x37\x76\xa6\x61\x22\x8a\xa1\x36\xb4\x42\xd5\x13\x1f\xa0\xd3\x0f\x30\x9b\x73\x52\x2a\x21\x37\x1a\x35\x2e\x1e\x9d\x27\xf5\xc3\x71\x79\x90\x3b\x27\x0d\x2a\x3a\x55\x47\xc1\xa9\xda\xd2\x69\xa9\x1f\x3f\xca\x6a\x16\x43\xb5\xd1\xc6\xf8\x80\x16\xf8\xc2\x06\x09\x19\xd6\x39\x30\x0d\x0e\x27\xb9\x88\x93\xc9\x9c\x11\xf0\x41\x8d\xbc\x90\x89\xb7\x0c\x22\xd6\x33\x0f\x00\x3c\xb1\xe0\x07\x3f\xe3\x4f\xd6\xcf\x7a\x9b\xee\x38\xbe\xb6\xa4\xc4\x6c\xc7\xf5\xb6\x23\xab\x4a\xac\xa6\xbf\x7f\x92\x7d\xdc\x3f\xa9\x4a\xf7\xcf\xe0\x3e\xef\x9f\xe6\x01\x83\x5a\xff\xcf\xef\x1f\xdd\x63\x7b\x22\x1f\xb2\x17\x9f\xde\xe3\x3b\x90\xe9\xfa\x62\x85\x57\x7f\xf7\x0c\x22\x91\x68\x85\xbb\xa7\xb5\x8f\xbb\x27\xd9\xc7\xdd\xd3\xd8\xdc\x92\xa0\x77\x4f\x96\x33\xf6\x57\x9f\xdf\xff\xdd\xe5\xa3\x37\xc3\x71\xfc\x61\x74\xd1\x04\xc7\x75\x06\xd6\x5f\x5a\xe3\xf6\x2a\x5e\xc3\x04\xe3\x26\x64\x42\x41\x34\x85\xe6\xc5\x19\x4e\xab\x0c\x03\x75\x03\x0b\xf0\x25\xab\x91\x56\x87\xb9\xbd\xb2\x51\xcc\x65\x8c\x80\xd0\x34\xb2\x96\x78\x86\x33\x02\x3c\x13\x59\xe2\x3d\x0e\x23\x67\x8e\xcb\x5e\x37\xad\x17\x3b\x38\x12\x3a\x09\x69\x88\xc3\x49\x2c\xe5\xb6\x42\x42\x48\xd1\x9b\x51\x3e\xc6\xb3\xbd\x5c\xde\x6b\x38\x53\x19\xba\xe5\x67\x25\xce\x6d\xf4\xae\x5e\x7d\xf8\xa0\xd1\xfb\xfd\x9d\x65\x7e\x1c\x55\xbc\xcc\x26\xe3\x18\xd0\x0e\x79\x9b\x32\xb4\x01\xc7\x9c\x47\x27\x22\x62\x84\xb3\x34\xe5\x24\x94\xcc\x18\xcd\xb0\x68\x83\x25\x9e\x61\x48\x0a\xac\xd3\x15\x11\xf7\xc2\xc0\x80\x21\x99\xb1\x80\x26\x35\x4c\xed\xba\x92\x19\x11\x80\x59\x22\xa2\x33\xbc\x6c\x20\x27\xb1\x09\xf2\x3b\xbd\xfa\x08\x4b\x92\x7e\xc6\xdf\x0c\xf5\x70\x3e\x13\xac\x69\x24\xbf\xab\x12\xe4\x48\x14\xe6\x2d\x33\x1e\x3b\xd5\x22\xf1\xe8\xb4\x48\xec\x8d\xb4\xec\x6c\x86\x6b\xc4\x28\x48\x18\xec\x32\x12\x03\x80\x9a\x92\x75\xd2\x64\x38\x88\x7b\xdf\x0c\xd1\xa7\xcf\xbc\x0e\x77\x2a\x6f\x5d\xfa\xa3\xd8\xc4\x40\xf0\xa7\xed\xca\x6b\x2d\xa5\xf7\xc1\x6b\xe3\xce\xfc\xeb\xd1\x05\xf9\x07\x2e\xbf\xc6\x69\x99\x67\x13\xf1\x85\xcc\x3d\x87\x3f\x2c\xbd\x3c\x19\xe4\x45\xc8\x30\xc1\x34\x03\x99\x90\x17\x8d\x41\xbd\x8e\x1d\x4b\xe2\xf1\xcf\x1b\x66\x83\x8d\x1c\xb9\x11\x04\x8f\x2a\x1d\xa9\x9d\xac\xde\x6f\xe9\xa1\x1e\xd1\x75\x93\xd4\x13\x65\x4e\x2b\xe9\x1f\x45\x8f\x1d\x64\xbe\xe6\xbc\xc0\xb3\xb5\x4a\x77\x9e\xc7\x3b\xc3\x70\x02\x7a\x63\x3f\xf4\xfc\xc2\x50\xbd\xa2\x1d\x34\x72\x7e\x12\x93\x96\xc3\x16\xb2\x13\x0f\x14\x31\xaa\x78\xa9\x96\xe4\xc1\x9e\x5e\xa7\x44\x52\x33\x7f\xdf\x67\x55\x0c\x1b\x7b\x9f\x11\x1e\xae\x82\x19\x2a\x1d\x0f\x76\xe9\xc0\x0d\x98\x9e\x8d\x71\x13\x72\xa1\xcb\xd4\x0c\x52\x77\x32\x59\x87\xdd\x8a\x1d\x71\xc9\x94\x92\x1d\x96\x9c\x64\x4c\x02\xd8\xc0\x0a\xa4\xd0\xda\xa4\xb2\x15\xcc\xc0\x5a\x54\x63\x64\xac\x60\x09\x2b\xf9\x4c\x47\x59\xed\x14\xca\x53\x38\x30\x7a\x68\xd1\xb6\x28\x4f\xce\xaa\x03\x0f\x52\xf6\x6c\x56\x76\xe3\x56\xa3\xd0\xdd\xad\x44\x1e\xcf\x5f\xc3\x3c\xf9\x38\xfe\x82\xac\x8b\x9c\x11\xf9\xe6\xaa\xd1\x4a\x94\xf1\x41\x25\xb1\xf2\x09\xb1\xea\x09\x65\x43\x61\x1f\xeb\x80\x7a\x53\xc8\x94\x93\x6c\x49\xe8\xd1\x04\xf6\x4a\x55\x54\x91\x02\x46\x0f\x1c\x01\x28\xa3\x99\x00\xf1\x4c\xeb\x69\x99\x00\xc0\xbe\x03\xb0\xe0\x40\x88\x32\xc3\xd0\x03\x84\x3a\x34\x1b\x80\x53\x43\xb2\xdb\x07\xef\x8a\x14\xe2\x25\x21\x2d\x1b\xcd\x7c\xd9\xb7\x44\x07\x12\x7c\x1a\x3f\x13\xdf\x16\x6b\x4b\xb5\x69\x87\x83\xe3\xca\x27\x17\x5f\x7a\xf1\xa8\xd0\x75\x69\xe5\xed\xf9\xf3\xd5\x83\xf9\xfe\xc1\xdc\xd4\xeb\xfc\xf3\xec\x5e\x3c\xf1\x9f\x0f\x7e\xaf\xd3\xa4\x4d\x21\x1e\xf5\x43\x3f\xad\xa0\x58\xda\x98\x00\x32\x84\xea\x64\x4f\x48\x6c\x34\xc7\xe5\xa8\x39\x27\x09\xbd\x84\x4b\x6d\x71\xb9\x1f\xe5\x7f\xac\x06\xa6\x2f\x20\x61\xb5\xd8\x8a\xc2\xa5\xd5\xfd\x78\xa1\xc7\x25\x72\x51\xaa\x79\x50\x41\x89\xb5\x22\x44\xbf\x4c\xb9\xf4\xd5\xbe\x74\x9d\x2b\xa9\xb3\x96\x6b\x1e\xa8\xdc\xcc\xaa\xf6\xc3\xdc\xbe\xd8\x8b\x8f\xaf\xfd\x40\x51\x2f\xbd\x74\x1f\x58\xe0\x0d\x97\x2c\x49\x39\x1a\xc8\xa9\xcc\x24\x3c\x15\x7f\xa8\x25\x41\x93\x10\xe0\x60\x00\x28\xaa\x82\x92\x1c\x27\x60\x30\xae\x68\x8c\x32\xfe\xe2\xcb\xfa\x30\x46\x25\x26\xe7\xde\xb6\x80\x73\xe7\xb6\x21\x1e\x89\xe8\x94\x0a\xe7\x2e\x24\x64\x8f\xb9\xa0\x9f\x5a\x26\xad\xeb\x2f\x4a\xeb\x7a\xfb\x96\xfd\x8d\x8a\xe5\xc2\xb3\x06\x66\x52\xc5\xa3\x82\xe6\x96\x76\x3e\x53\x91\x17\x05\xd0\x75\x7d\x9d\x8f\x98\x90\x7d\xe6\x02\x7f\x41\x9f\x14\xda\xa1\x32\x0a\x6d\xd9\x45\x1e\x6c\x87\x90\x71\xc2\x5c\xd6\xc9\x30\x67\x47\xc5\x32\x8b\x77\x33\x93\x2a\x19\x77\xf1\xe2\xc2\x77\x34\x02\x34\x8a\xaf\xaf\x60\xcf\x6a\x58\x76\xc6\x07\xb3\x48\xbe\x10\x5c\x08\x65\xc2\xc5\x02\x8e\xcb\x9e\x00\x00\x21\xa0\x1e\x18\x80\x7a\xa0\x5e\xce\xd8\x23\xf0\x82\x14\x01\xb6\x30\xce\x55\xdd\xa7\xa8\x71\x49\xf7\xa9\xec\x0c\xbe\x2d\xed\x3b\x55\x50\x85\x6e\x2d\x99\xfd\xa5\x67\x42\xb9\x6e\x1e\xe9\xeb\x4c\x2a\x53\xdc\xc4\xca\x68\xbf\x7d\x81\x12\xda\xef\x6a\xa0\xfd\xae\x0a\x50\x76\xa3\x40\x39\xff\x79\x91\xf1\x26\x23\x70\xb5\x90\x99\x08\x27\x47\xff\x5d\xb2\xfd\xb2\x23\x5c\x5c\xb2\xfd\x0a\x8c\xf4\xa7\x14\x76\xaf\xe9\x39\x1f\x50\xf5\x9c\xa7\x56\xd4\x73\x96\xa3\x46\x18\xb8\x17\x8d\xb9\x0a\x6a\xce\xea\x4d\x48\xf6\x13\x08\x14\xf1\x46\xea\xa5\x08\xb2\x0d\x9c\x2b\x4c\x19\x11\x9b\xa2\xbc\x20\x07\x84\x5e\xfb\xea\x25\xed\xac\x97\xc7\x29\xff\xc2\x2e\xec\xa5\x0d\x58\xe9\x83\xfb\x4f\x6f\x3d\x40\xca\x5b\xff\x90\xca\xed\x3e\xbf\x6f\x6e\x77\xb9\xde\x08\x54\x2b\x01\xb2\x61\xfd\xa5\x08\x88\x04\x72\xfd\x45\xdd\x54\xac\x24\x00\x10\x91\xde\x9f\x26\xb9\x15\xc9\x66\x7b\x04\xae\x26\x00\x74\x0c\x61\x5e\x28\xbd\x17\xe5\xfe\xf5\xbc\x20\x87\xc5\x93\xe2\x78\xd7\xdb\xa3\xec\xb8\xbf\xed\x2d\x95\xd8\xfb\xc8\xcd\xe5\xd6\x28\x9e\x3d\xd5\x43\x6f\x40\xd7\x54\x52\x1d\x6f\xd4\x9f\x36\x09\x19\xfd\x7e\x18\x50\x53\x8f\xb8\x27\x0a\x0e\x5e\xeb\x07\x0a\xa8\xa8\xda\x57\xf7\xb1\xbc\x20\x0b\x61\xc0\x98\xf5\x70\x2a\x47\x45\xad\x20\x35\x9c\x48\x3c\x3d\xda\xa7\x8c\xba\xbd\x57\x0b\xb1\xa2\x9e\x7a\x79\xf7\x90\x2d\xd1\x5b\x68\x46\x0b\xfb\x54\x2b\xe8\xa7\x3f\x65\xb8\x9a\xfc\xc5\xab\x09\x8e\x96\x4a\xb6\xc4\xfc\x94\x30\xc2\xaf\x3f\x6d\x92\x49\x04\x59\xaa\xea\x18\xe2\x7b\x04\x8e\x62\x9e\x62\x82\xd4\x0c\xb8\x3a\x57\x5a\xae\x47\x3c\x55\x6e\x3e\x39\x35\x83\x52\x6b\x94\x9d\xf8\x86\x72\x63\x54\x14\x6c\x28\xb7\x05\x83\x36\x2b\x9d\xc6\x88\x71\x13\xe2\x51\x14\x4d\xa3\xa7\x9d\xf5\xd2\x54\x4b\xfb\xd8\x6b\x13\x72\x98\x2b\x00\xbd\xf4\x9a\xed\x7c\xc9\xa7\x1d\x23\xaf\x63\x80\x17\x36\x72\x2e\xaf\x58\x5d\x0b\x1f\x77\xb8\x96\x5a\xc0\xc5\x67\x84\x00\xb9\xb9\x65\xec\xe5\xd5\xc9\xf4\x0a\x1f\x7b\xe9\xf8\x52\xf9\x81\x3f\xac\xa7\x06\xea\x7d\xd6\xf9\x7f\x94\x90\x27\x31\x68\xb5\xd2\x69\xf8\xa9\xa1\x0b\x79\x51\x3d\x7a\x92\x76\x4d\xfb\xf8\xbc\x63\x09\xb9\x86\x2b\x70\x85\x96\x3e\xae\x3d\x61\xf0\x67\x95\xe9\x2f\xcc\xeb\x0f\xb9\x11\xc7\x65\x11\x30\xe6\x42\x3a\x0d\xac\x41\x24\xaf\x70\x00\xe1\x8e\x5d\xe8\xf1\x07\x6a\x28\x80\xa4\x26\x06\xfc\x8e\x92\xc0\x67\xc4\x70\x2d\x98\xe1\x44\x8a\x1c\x65\xb6\x28\x3b\x6e\xe6\x56\x3d\x65\x73\xaf\xa3\x56\x2e\x2a\xe5\x91\x62\x50\x10\x21\xd3\x38\xd3\x0c\x14\x40\x8d\x68\x3a\x9d\x3d\x05\xc6\x6e\x86\x64\x22\x26\x67\x2a\x95\xc2\x52\x13\x1d\xfe\xf3\x15\x86\xff\x5c\xbe\x9c\xdc\x8c\xe3\x52\x7b\x68\xeb\xf6\xef\xbf\x19\x8e\xc4\xb8\x55\x42\x6e\x29\xf0\x86\x53\xc2\x6e\x89\x79\x03\x49\x4c\x0b\x96\x99\x40\x4b\x8b\x34\x2a\x84\x65\x27\xe6\x85\x8c\x3b\x48\x93\x63\x14\xe0\x85\x8c\xc1\xe6\x4d\x17\xd4\x06\xda\x3b\x70\x0a\x93\x5f\x3c\x29\x1c\xc3\x8d\x4d\x9c\x09\xc7\x4a\x8b\xb1\xc1\x37\xbe\x6c\x09\xf8\x86\x60\xe6\x35\xec\x18\x5c\xe5\xee\xf8\xe3\x1b\xca\x9d\x5b\x95\x2f\x47\xda\xdc\xed\xca\xc1\xad\xaf\x95\x8c\xb1\x1f\x9d\xf3\xd2\x2f\xbb\xdf\x62\x6f\x3e\x3a\xf7\x97\x3d\xf3\x7e\xc3\xde\x79\xb8\x8b\x7d\x6d\xef\xd9\x33\xb2\x47\xcf\x2c\x1d\x6b\x47\x0c\xf2\x23\xc4\xa5\xb8\x28\x8a\xa0\x81\xe8\x37\x28\x13\x21\x7b\xf7\xa7\x40\x59\x21\x83\x2d\x5e\xd8\x7b\x0b\xdd\xbb\x08\x7b\xf7\x92\x63\x15\xa1\x25\x41\xf6\xfe\xa6\xe1\x1b\x41\xdb\x7b\x84\xee\x9d\x7d\x63\xeb\x9b\xef\xfd\xed\x7c\xf2\x53\xa3\xe4\x6f\x71\x4a\x81\x37\x64\x27\xfb\xbd\x64\x7b\x43\xc2\xee\x1e\x06\xb3\x9e\xb8\x64\x73\xf7\xd8\x6d\x4e\x4f\xbc\xc7\x41\xfe\x9a\x61\x30\x5b\x3b\xaf\x76\x5e\x8c\x73\xf2\x42\x3a\x63\xb7\x91\x5f\x24\x47\x1a\x6d\xb2\x05\x18\xd6\xee\x70\xb6\xd0\xff\xc3\xa3\x2c\x36\x7f\x20\xa2\xff\x91\x6a\x5e\x2f\x31\xaf\xaf\xb6\x89\x9a\x37\x42\xcc\xeb\x0e\xa9\xe6\x0d\x61\x7f\xaa\x83\x58\xd6\x53\xc3\xfa\x53\xd4\xc4\x6c\x63\x53\x8c\x33\xb1\x65\x36\xf6\x6f\x9d\x32\xcd\x6a\x76\x46\xaa\xdf\x7a\xfb\x55\xab\xdf\xeb\x36\x58\x2c\xa3\x9e\xdc\xac\xec\xfe\x78\x5b\x28\x69\xee\x5f\xfb\xce\x07\x73\x75\x66\x36\x74\x29\xd7\x29\x97\xfc\x78\xc4\xa2\x4b\x98\xeb\xf2\x8f\xc5\xce\x3b\xf7\xac\xea\x73\x0e\x33\x5d\x47\x36\x31\x53\xcf\xdd\xfb\xd6\xe4\xfc\xf2\x12\xd1\x3f\x44\x67\xee\x0d\x73\x81\x17\xd6\x87\x06\x53\x8c\x25\x38\x99\xc4\xd2\xa1\x22\xd3\x5e\x80\x19\x05\x70\x5c\xe6\x4c\xbc\x90\x61\x9c\x5e\xba\x1f\x13\xa4\x7f\x83\x5a\xf9\x94\x05\xa7\x30\x94\x1c\xf4\xcb\xde\x89\xef\xc4\xb3\xde\x55\x82\x5b\xf2\xa5\x64\x06\xad\xcc\xee\xa3\xb3\xf3\x3b\x99\x04\x7b\xb4\x57\x0d\xbe\xa8\x57\xd2\x50\x49\xaf\xa4\x31\x41\x19\xb3\x4f\x5a\x1b\xa3\x94\x1c\xaa\x2f\x45\x0c\xe5\x48\x89\x01\x2b\x0a\x97\x94\xf2\x41\x51\x9b\xf5\x43\x66\x88\x42\xc6\x95\x5a\x4d\x12\x12\x52\x4d\x2a\x6b\xa7\x8a\x1f\x81\x24\x94\x47\x2c\x7b\x65\x97\x1f\x46\xf4\x4c\x36\x0d\xd1\x03\x71\x48\xd8\x47\x6b\x20\x9c\x4b\xcd\xa6\x2b\xd8\xb5\x0f\x85\x8f\x82\x85\xb7\xf7\x96\xf4\xd0\x1b\xda\xb0\xac\xb7\x18\x26\x83\xc6\x22\x64\x38\xcd\x34\x03\x59\x90\x07\xb5\xa8\xb3\x1b\x26\x8d\x87\x19\x28\x2d\xbc\x09\xb2\x42\x24\x9b\x10\x64\xf4\xb2\x81\x55\x1f\x82\x54\x1b\x8e\x82\x7e\x87\x6e\x42\x65\x2c\xcb\xe4\x7d\xec\xce\xa3\x0a\xeb\xcf\xcf\x56\x5b\x72\xf3\x0d\x73\xbb\xe7\x1f\x99\x59\x3a\x7f\x74\x3e\x42\xec\x0c\xd0\xc9\xd4\xfd\xb9\xa6\x5c\xc6\x80\xc9\x9f\x6b\xfa\xa1\x7f\xee\xf9\xcc\xd8\xfc\x27\xcc\x3f\xf2\xaf\x30\x17\xe5\x8f\xa9\x7f\xee\xed\xec\x19\x0b\xe6\x1e\xfd\xd5\x7c\x1d\xf2\x41\xdb\x6f\x07\xb2\x20\x51\xc3\x63\x94\xec\x57\xf2\x24\x64\x87\x81\x26\x92\xd6\xbd\xb2\xdb\x09\xd9\xe3\xf1\x57\xa1\x3b\x0c\xfd\xfe\x9f\xd0\x46\x49\x0a\x06\x78\xa7\x38\xb3\x02\xfb\x37\x7e\x55\xba\x0e\xdd\xfe\xff\x97\xeb\xd0\xd9\x43\x31\x6b\xeb\xd0\x0c\x52\x18\xca\x2c\x39\x7f\x5f\x1f\xe7\xef\x4f\x90\xaf\xfe\x04\xe7\xa0\xab\x32\xea\x4c\x70\xf4\xa5\x62\xad\x51\x33\x42\x19\x56\xbd\xe8\x07\xbe\x3e\xfc\xe0\x87\xfe\xf9\x7a\x57\x08\x16\xff\x7c\x6d\xf3\x25\xe0\x72\x98\xf9\x63\xbe\xe2\x22\xc8\x5e\x98\x1c\x32\x27\x64\x96\x5c\x33\x0e\x8a\xb5\x70\xe4\xc8\x93\x4a\x27\x0f\x25\xae\xd0\x47\x4a\xf1\xee\xa8\xd6\x32\xe0\x37\xe0\xeb\xae\x9a\x92\xb8\xe4\xf4\x89\x3f\x36\xac\xc4\xb3\x9b\x1e\x8e\xdc\x7a\xdb\x91\xc9\xf4\x2e\x13\x8e\x1d\x04\x7d\xa3\x2a\xd4\x8f\x64\x29\x61\x0d\xf1\x2d\xd7\x5a\x54\xc1\x8a\xc6\x4a\xac\x20\xfd\x13\x52\x18\x58\x41\xaa\xb5\xd2\x5c\x18\x32\xf1\x30\xb2\xc4\x49\x96\x12\x72\xe5\x32\xa1\x30\x90\x66\x98\x2c\x71\xa9\x9a\xb2\x0c\xf2\x5a\xf5\x2a\xc4\x0b\x19\x9b\x1d\x2a\xa8\x31\x5e\x76\x42\x5f\x11\x74\x2c\xec\xbc\x4d\x25\x34\xd6\x73\x84\xb4\x6b\xe0\x48\x78\x79\x62\xbc\x1e\xf1\x25\x0a\x4f\x65\xf1\x46\xe5\x6c\xab\xf5\xc6\xaf\xf6\x1f\xfc\xe6\x93\x1b\x37\x74\x38\x23\xdc\xec\xec\xd2\x17\x1e\x5d\xbc\xe4\xf1\x35\x8f\x18\xf6\xcd\xdd\xb4\x69\x6e\xe7\xf4\xe9\xdd\x20\x8e\xf4\x8d\xb2\xef\xfc\xf3\xee\xf0\x18\xf6\xe5\xcf\xf9\x62\xfb\xfe\x5d\x7b\xf6\x6c\xfb\x1c\xf2\x13\x2f\x42\xc6\x29\xc6\x4d\x28\x8c\xea\xd1\x40\x34\x5b\xe5\x50\xac\xd2\x31\x55\x4b\x03\x92\xd9\x86\x7a\x80\xfa\x35\x58\x35\xbc\x81\xec\x13\x80\x85\x9c\x84\xad\x55\x62\x4e\x6a\x48\x4a\x55\x54\xf3\xce\xe9\xcf\x49\xfd\x48\x14\x6f\xf2\x51\x0c\x82\xe0\x03\x66\x00\xb9\x5f\x15\x2f\xc8\x36\x2b\xb4\x52\xab\x28\x1c\xbe\x81\xa7\x6a\x3e\x5e\x21\x83\x4c\x01\xfa\xf4\x0e\x6e\x4f\x45\x6b\x0d\xa2\x97\x33\x89\x35\x58\xf4\x1a\x62\x51\x3e\x56\x27\x7a\xfd\xb1\x16\x8c\xa3\x74\xf3\xd1\xb6\xa8\x8a\x83\xf1\x2e\x7c\x14\xef\xc3\x8d\xd8\xf8\xf0\x83\x2f\xac\x52\xfe\xf9\x75\x3e\xdf\x36\x4b\x5c\x6d\x71\x32\x2e\xdc\x24\xbd\x98\xdd\xa8\xfc\x05\x3b\xd7\x3f\xf5\x8b\xad\xff\x30\x64\xef\x9f\xf5\xd2\x2b\xf7\xad\x0b\x5a\xab\x5f\x5a\xf2\xce\x01\x63\xf0\xda\xce\x56\xf1\x94\xa3\xf8\xc1\x79\x73\x66\x3d\x79\xc3\xec\x3b\xa6\xaa\x33\x26\x86\x39\x2a\xf6\x4a\xe3\xbd\x74\xd8\xf4\xbc\x97\x62\x91\xf7\xd2\x57\x80\x84\x1a\x92\x19\x07\x8c\xcd\x39\x58\x5a\x85\x85\x49\x49\x9f\x7a\x31\x88\x0e\x18\xd5\xd4\x78\x2f\x53\x64\x6f\x86\x68\x53\x01\xc9\xc3\x5e\x95\xbf\x68\x3f\x0e\x60\x8f\x72\x54\xf9\xee\xbb\x2f\xb6\xad\x93\x3e\x7e\x0b\x28\x2f\xdf\xfd\xdd\x6f\x7f\xb3\xf2\x9e\x45\x0b\x6e\xa1\x33\x3c\xaa\xbf\xfa\x50\x4c\x43\x23\x51\x90\x66\xc8\x92\xcb\x58\x31\x75\x5c\xc9\x90\x90\xb1\xa5\xc0\x73\xef\xa7\xd8\x29\x9f\x2b\x97\xf1\xc1\x02\x7d\x64\x81\x7e\x5a\x5c\x75\xa8\x24\xf8\x7e\x1f\x2f\x64\x4c\x66\x0f\xed\xd9\xca\x56\x37\x39\x20\xab\x9b\x17\x64\x93\xa7\xc0\xbf\xda\xdb\x19\x4b\x5c\x71\x03\x3b\x31\x3f\xae\xd4\x11\x53\x9a\x1f\x72\xde\xc7\xbf\x2c\x73\x42\x26\xa6\x73\x41\x5a\xf3\x32\xac\x07\x9e\x00\x1f\xea\xa2\xd5\x7c\xc0\x22\xc3\x9c\x22\xeb\xb3\x16\x58\x9c\xca\x87\xa8\x89\xf7\x11\x37\x0b\xa8\x03\x00\x92\x35\x8d\x64\x9f\x0b\xd0\x54\x34\x0f\x00\x57\x32\xc4\x6a\x0b\xcb\x8d\xe3\xcd\x5b\xb0\x80\x2d\xb8\x56\x39\xf2\xb7\xbc\xb2\xe5\x89\x0d\xcf\x2d\x7d\x67\xdb\x51\xbc\xc1\x60\xce\x2f\xdb\xbf\x7b\x77\x0e\xbf\xb9\x72\xee\x92\x87\x16\xde\x89\x18\xb4\xf6\xd8\x41\xc3\xad\x9c\x17\xb9\xa9\x2a\x0f\xf0\x98\x78\x2d\x39\x98\x6d\x21\x76\x87\x29\xc6\x1a\x0d\x25\x48\xd6\xc4\xd3\x99\x30\x9b\x48\xe7\x29\x78\xf5\x6e\xf2\xf3\xb2\x19\x06\x59\x42\x5e\x5e\xc8\x70\x36\x63\x3a\x5d\x14\x3e\x2b\xd8\xb5\x04\xd0\x29\xae\xcd\x52\x83\x1e\xf9\xf3\x7f\x1f\x43\xd9\x17\x96\x2e\x5d\xbc\x78\xf9\xf3\x8f\x30\x31\xf6\x1f\xca\x03\x9a\x3d\xbf\x56\xf6\xe3\x66\x6c\x7b\xfb\x77\xbf\xfb\x60\xcf\x9e\x57\x3f\x23\xf7\xe6\xc8\x63\x07\x0d\x8b\x8d\xef\x23\x3f\xea\xd4\x50\xdd\xea\x2c\x24\x45\x75\x03\x07\x13\x08\x07\x04\x41\xbd\xc1\x42\x61\x10\x22\x9f\x31\x3a\xe0\x5e\x62\x54\x5e\xd3\xf6\x68\x2d\xe2\xbd\x8c\x81\x9c\x37\x89\xd7\x28\x3a\xd9\x34\x72\x3d\x36\xe1\xd3\xf0\xa5\xab\x95\x5d\xef\x4d\x97\x7f\xbc\x7d\xc5\x41\xec\x54\x8e\xfc\xeb\xe9\x97\x8c\xb7\x8e\x53\x6e\x53\x96\x7f\xa1\xfc\x72\x4b\x28\xba\x6a\x28\x1e\x8e\x05\x1c\xc4\x6d\xe7\x23\x0c\x78\xf3\xc5\xdc\xa7\xa8\x1e\xdd\x82\x32\x75\x70\xbf\x68\x2f\x99\x8f\xcd\x49\xae\x84\x6c\xb5\x16\x92\xc5\xa0\x1f\x9a\xea\x1c\x31\x1f\x4f\x79\xb0\xb8\x20\x2f\xf4\x18\x7c\x55\x75\x14\x6d\x91\xf1\x00\x5f\x2e\x92\xab\xea\x68\x19\xd3\xc7\x67\x90\xa7\x86\x4a\x4f\x50\xca\x1e\x17\xcc\xd9\x59\x05\x60\x81\x50\x29\xdb\xda\xa0\x99\x2c\x36\xc6\xea\xaa\xb1\xa9\x05\x97\xa9\x52\x80\x10\xc5\x5d\xb7\xdc\x70\x77\x67\x67\x6b\x7a\x52\xd7\x69\x2b\x27\x97\x4b\x82\x80\x08\x45\x75\xf5\xcf\x1f\x0e\x3d\x2a\x5e\x39\x65\x55\xa4\xb5\x54\x8d\x02\x61\xc0\x92\x4f\xe4\x22\x28\x8a\x6e\xa6\x59\x91\x1c\xd2\xb8\x68\xc9\x3d\xea\x4c\x50\x11\x0a\x9a\xf7\xfb\x45\x28\xf2\x18\xd5\x7d\xc6\x40\xce\x81\x17\x7a\x58\x6f\x28\xa2\xee\x53\xa8\xaa\xa6\xf8\xc0\x08\x25\x81\xf0\xf2\x19\x24\x54\xa9\xe2\x14\x3c\xc8\x59\xd9\x61\xc4\xc8\x56\xd0\x09\x2d\xd9\x64\x99\x66\xc5\x74\x6c\xfb\xcf\x90\x73\xa7\xdd\x3d\x7c\x64\x62\xd8\x15\xa5\x62\x15\x54\xa1\xc2\xbe\xf5\xe7\x8b\xc2\x8f\x79\x27\x2b\x3a\xa1\x8a\xff\x3f\x69\x19\x90\xb7\x4e\x31\x6e\x42\xe4\xd5\x1f\xaf\xee\x43\xd4\xf6\xe1\xb0\xe5\x40\x8f\xac\x9a\x12\x20\x08\x90\x0d\xd8\x68\xe2\x2a\x89\x74\xd4\x85\x2c\xb4\x46\x23\x42\x10\x60\x36\x9c\x4f\x23\xd9\x21\xf2\x82\x2a\x1b\xa2\x3d\x60\xea\xc2\x0b\x2f\x97\xba\x01\xf2\x5e\x1d\xc2\xe3\xf1\x4c\x90\xdb\x98\xa2\x3d\x56\xef\x52\xad\x8d\xbf\x93\x57\x4a\xb9\x5f\xd9\xa0\x2c\x53\x66\x6b\x4f\x14\xab\x29\x6d\x30\x68\x0a\x42\x86\x06\xb8\x27\xbd\xe4\x7d\x2a\xdc\x93\x26\xb2\x7e\x8e\xcd\x65\x59\xc1\x6a\x22\x77\x25\xf1\x32\x51\xcf\x8b\xe8\x56\x27\xd5\xc4\x5c\xc6\x0d\x7d\x4e\x37\x47\xdb\xd3\x48\x16\x5c\xbc\xfa\xc5\x0f\xae\x8f\xa6\xa0\xc7\x19\x25\xd7\xe5\x30\xb2\x7a\x6e\x0a\x6e\xc1\xa1\x57\xf3\x17\xb1\x57\x29\x53\xf2\x07\x5e\xdf\xf8\xe6\xee\xb5\xfb\xdf\xc1\xcb\x3e\xfa\x2f\xfc\xab\xd5\x87\xbb\xf0\xca\xd9\xf7\x30\xee\xfb\x34\x9d\x88\x4e\xd0\x8b\xac\x43\xb7\xd2\xba\x17\x6d\x50\x07\xb5\x41\x8a\x5a\xd0\x89\x90\xed\x45\xa5\x5c\x55\xc9\xc4\x82\xe3\x6a\xb3\x33\x63\x71\x14\x58\x5f\x1c\x6e\xd9\xe5\x86\xcb\xa1\x1e\x9e\x53\x10\x83\xe0\x3d\x41\xa8\xfa\xb9\xa8\x18\x04\xeb\xe1\x85\x8c\x91\x73\x53\xc3\x17\xa5\x3e\xc8\x26\x2a\x8a\x40\xa8\x12\x1f\xf9\x71\xec\xc4\x72\x95\x0f\x9d\xb8\x47\xe4\xf1\x72\x75\x0f\xea\x3f\x37\x1e\x3b\x68\xb8\x06\xf8\xe3\xfa\x6b\xb5\x3d\xd9\x67\xce\x49\xcd\x6a\x64\x4a\x85\x4d\x22\x62\x61\x38\x80\xf3\xe5\x7a\xec\x5c\x83\x59\x9d\xa3\x4d\x40\xd4\x3a\x00\xc7\xe5\x08\x02\xae\x14\x98\x0c\x0e\xf2\x9b\x58\x97\xcf\x52\x55\x47\xb9\xc1\xe1\xf9\x12\xd2\x52\x33\x9f\xe5\x90\xdd\x53\x57\x54\xb9\x37\x88\x5e\xc6\x44\x62\x22\x92\x48\x34\x75\xa8\x20\xa1\xc6\xa6\x16\xdc\xe1\xf5\xf9\x47\xe0\x36\x75\x04\xc0\xf9\xed\x57\x58\xf8\xc3\xaf\x1f\xbc\xed\xed\xf5\x53\x5e\xbb\x77\xec\x39\xeb\xa7\x5c\x30\x69\xda\xf3\x9f\xac\xdf\x7a\xe7\xdc\x57\xdf\x7c\x71\xf1\xca\xb5\x86\xea\x83\xd8\x76\xe8\xa3\x9e\x63\xa8\xf3\xdc\x55\x57\xfe\xfc\xc9\x96\x51\x0b\xe3\x9d\xe7\x8c\x3e\xfd\xba\x4b\x6f\xfd\xee\x99\xbb\xb3\xa7\x0f\xdc\xfb\xec\xbc\x75\x1b\xe9\x6c\xfd\x9d\x08\xb1\xf4\x6d\xd6\x18\x23\x30\x9b\x53\xe9\xc9\x48\x44\x64\x40\x16\x2d\x22\xb2\x03\x4f\x11\x97\x24\xcf\x5f\x86\xb1\x15\x18\x7b\xcc\xc9\x9e\x51\x8c\xc1\x12\x57\x27\xe1\x53\xc4\xc3\xd4\xff\xdc\xc9\xcc\xcc\xaf\x67\x2e\xca\xcf\x65\x5b\x57\x33\xd6\x55\xe0\x54\xd4\xd6\x33\x8f\x1d\x34\x4e\x35\xee\x02\xbd\xe5\x6b\x90\x2a\x26\xc3\xe6\x32\x36\xf2\x27\x1b\xd9\x5c\xd6\x8b\x79\x1b\x65\x1b\xc4\x52\x98\x8e\xcc\xfa\x61\x5c\x36\x84\xe3\xe4\xe2\x71\xfa\x73\x80\x42\xf1\xc2\x9d\x62\x06\xec\x7b\xc6\x68\xe3\x69\xd3\xce\x4b\x03\x50\x23\x50\x7b\xda\x04\xc9\x4c\x51\x37\x0c\x79\xe2\xda\x46\xe0\x54\x61\x40\x89\xb8\x8f\xd0\x31\xd3\x90\xe0\x15\xe5\x6f\x5f\x7c\x3b\xeb\x77\xf7\xe2\x73\xf0\xcd\xca\xf3\xca\xaf\x94\x8f\x95\xdd\x6f\xef\xfc\x70\xd7\x77\x6e\xe6\xc0\x18\xcc\x62\xd3\x45\x6b\x07\xd4\x29\x37\x29\x4f\x29\xab\x95\xe9\x78\x26\x0e\x1d\xfb\x27\x36\xfe\x8d\xd8\x10\xfc\xc6\xf8\x3e\x6a\x42\x37\xa1\x4c\x83\x96\x64\x58\xc9\x4e\x78\x6b\x2e\xeb\x0f\x35\x58\x1d\x71\xd9\x6f\x2d\xd0\xdd\x56\xfb\x72\x52\xb5\x5b\xf2\xaa\x61\xb4\x64\x4a\xc8\x5e\x5f\x2e\xe3\x35\x11\x9b\x7a\x03\x94\xeb\x16\xc9\xb5\x0d\xbc\x20\xc5\x00\xd4\x8f\xea\xd2\x69\xc9\x2f\xc8\x06\x16\x38\x64\x32\x0e\x93\x53\xbb\x8d\x3a\xda\x5a\x30\x3c\x0b\x3e\x3f\x3c\x7b\xe4\x49\x18\x86\x45\xdd\xdb\x10\xad\xad\xbf\xf1\xf5\x2d\x4b\x57\x7f\xff\xdb\x9f\xff\xeb\xaa\xf1\xd7\xad\x9f\x7a\xdf\xa3\xef\xbc\xbb\xe3\xc3\x2f\xfe\xf8\xee\x2b\xfb\x3e\xdb\xac\x1c\x52\x0e\x2a\x9f\xe2\x45\x4f\x6d\x0e\x9a\x83\x1b\x1f\x7e\xe1\xed\x73\xcf\x9e\x75\xd6\xe0\x59\x53\xee\x5c\xfc\xe4\xdc\x39\x0f\x2d\xb9\x6e\xed\x25\xbf\x41\xf8\x58\x4e\xf1\x82\x36\x80\x80\xce\xa1\x2c\x41\x20\xe6\xe5\x06\xa6\x20\xc9\x91\x90\xad\xe4\x9c\x3c\x40\xce\xe3\x14\x73\x92\x25\x99\x71\x02\x4e\xc6\x69\xb6\x90\xbf\xda\x2d\x71\xd9\x0b\x7c\x0c\x6e\xea\xfe\x8e\x12\x9a\x1e\x0d\x83\xe1\x8e\xd6\x35\xf9\xfb\xa7\xce\x4c\x03\x55\xfc\x05\xf9\x0d\xca\xa7\xa7\xb4\x2a\xef\x8b\x17\x5e\xcc\x8d\x5f\x9d\x3f\xfc\xec\xd1\x9c\xf2\x5a\x18\xfc\xf6\x35\xd0\x7d\x7d\x1f\x45\xd0\xd5\x28\xe3\x60\x54\xc6\xcd\x6a\x60\x09\x22\xaf\x13\x97\x92\x7d\xa6\x9c\x6c\xb6\xd3\x29\x0a\xe3\x5e\xc9\x92\x94\x43\x40\xf0\x9f\x09\x19\x35\xd6\xc3\x8c\x11\xe6\x97\x8c\x26\x3a\xbf\x84\xe4\x20\x03\xb7\x25\x24\x35\xb2\xc5\x9d\x86\x85\xba\x88\xa1\xe9\x42\x63\x6d\x1d\x6d\x45\xd0\x5a\x35\x06\xfc\x0b\x17\xab\x6b\x7a\x6d\xcc\xb0\x09\xe7\xec\xdb\xb7\x7a\xcb\x65\xb7\x0e\xbc\x26\x3d\x71\x2c\xf6\x2a\xdf\x74\x67\xce\x3a\x55\xd9\x26\x4c\x9a\xc1\xbe\x79\xd1\x88\xfb\xb7\x67\xe3\x0b\xa2\x57\xcd\x5c\xb8\xe0\xe8\x88\x57\x36\x78\x90\x1a\x37\x7d\xcb\x7d\x8a\x9a\xd0\x5c\xd5\x6f\xc2\x1a\x0b\xae\xc8\xe6\xb2\x91\xda\x06\x83\x23\x2e\x47\x74\x21\x14\x75\x9f\x80\x0f\xfa\x08\xd5\x38\x4e\xbe\xc6\x3a\x31\x97\xa9\xae\x03\xbe\xca\x08\x4d\x49\x05\x9e\x4a\x4d\x54\x43\x49\x59\x84\x91\x23\x81\x97\x3c\x69\x24\xd7\x46\x78\x41\x0e\xa0\x34\x0c\x83\x78\xca\x02\xaa\xca\xa1\x54\x25\x26\x5c\xe0\xbf\x5d\xf2\xc0\x0d\x77\x0f\x1b\xd5\x3a\x74\x52\x9f\x34\xb8\x40\x7e\x1b\x8b\xd1\x90\xea\xfa\x4a\x24\xb8\x70\x17\x20\xc5\x6b\x58\x04\xef\x76\x04\xd4\x31\xd5\x99\x6c\x57\x42\x0e\xa8\xb3\x67\xc2\x5e\x59\x14\x0a\xb3\x67\x76\x81\xb6\xb9\x45\x81\x0e\x58\x85\xf8\x0c\xeb\x32\xc0\xec\x15\xb0\xe6\x40\x2d\xbd\xc7\x60\x17\xaa\xe1\x72\xe5\x53\x21\x4c\x8b\xe9\xda\xe5\xda\x36\x38\x8c\xc9\xb7\x41\x6e\x57\x27\xde\xfe\xf2\x76\x97\xf7\x02\x1c\x79\x53\xa9\x3e\xed\xf4\x39\x53\x6f\xb8\xf7\xa1\x48\x53\xe4\xf4\x58\x5d\x53\xc4\xb8\x49\x09\x29\xe8\xe2\x29\x07\x98\x43\x47\x9a\x1e\xf8\xea\xdc\x99\xcb\x57\xdc\xf6\x0c\xf6\x2b\x17\x8c\x1c\x7a\x6b\xfb\xd2\xd1\xe7\x2e\xa0\x77\xe8\x86\x63\x07\xb9\x8f\x39\x2f\xaa\x47\x37\xaa\x99\x5b\x50\x1b\x31\xf4\x62\x14\xa7\x84\xb0\xb5\x25\x84\xb0\xf5\x34\x9f\xa8\xa7\x48\x3a\x87\xa3\x30\x2f\xec\x53\xb9\x61\xeb\x55\x2e\xa6\x2a\x5e\xe6\x2c\x69\x55\x9e\x26\x98\x46\xb2\x37\x08\x6f\xa2\x3d\xdd\x9b\x14\xd6\xab\xe7\xbc\x6a\x2c\x0e\x6b\x67\xad\xf6\xe4\x2f\xae\xdc\xfa\xea\xac\xfb\x1f\x9a\x99\xdd\xf3\xa7\x3f\x7e\x72\xdd\x2d\xcb\x17\x52\x42\xd8\x8b\x2f\x7e\xfd\x23\xe5\xb5\xfb\xe7\x2c\x5d\xc9\x2c\xcf\x4f\xfe\xeb\xde\x1d\xef\xe1\xd1\x0f\xcc\x79\xe5\x93\xfc\x4e\x84\x49\xde\xc6\x64\x01\x83\x95\x50\xf5\xf0\xb9\xde\x6c\x42\x80\xa3\x92\x39\x07\x55\x60\xc5\x3c\xe4\xc2\x85\x16\x0d\x15\x4c\x68\xdc\xfc\x72\xd7\x85\x03\x26\xd6\x84\x6e\x1a\xd2\xbd\x0c\x9f\x62\xb8\xe5\xc8\x53\x57\x4e\x76\x5a\x96\xdb\xbd\xeb\x88\xfd\xc6\x20\xc4\xdc\x08\x9c\x1c\x3f\x51\x27\x13\x79\xca\x92\xa9\x63\xcb\xcb\x62\xe4\x36\x3a\xe2\x92\x2d\x25\x63\x1b\xb9\x5f\xb0\xe4\xd5\xe8\x66\x29\x9d\x6c\x8f\x59\x70\x3b\xe3\x32\x32\xa4\x52\x59\x97\x13\x99\x0d\x71\x99\xb3\x26\x93\x50\xcc\xa4\xf1\x26\xa5\x8a\x4b\x89\x31\xde\x2f\x46\xdb\x3a\xf8\x31\x9b\xd7\x33\xee\xf5\x5b\xb6\xac\xcf\x7f\xb3\x9e\x59\xf9\x0c\xfe\x53\xbf\xa9\x53\xfb\x29\xa1\x67\xf2\xff\x6c\x9a\x3a\xb5\x89\x71\x90\xb5\xed\x40\xc8\xf0\x9d\xf1\x2d\x14\x46\x23\xd4\x3a\x95\x37\x05\x57\xbb\x84\x53\xb2\xcb\x5a\x18\x23\x0b\x43\xd2\x4a\xd5\x4d\x48\xf8\x98\x61\x39\x60\xd0\xb2\xf2\xb2\xa9\xc0\x50\xd5\xde\xd1\x8e\x61\x66\x46\x04\x45\x52\x0b\x8e\x35\xb2\x8d\x4d\x26\x7e\xc7\xe6\xf4\x29\x03\xf0\x79\xc3\x7e\x7a\xd1\x88\xe6\xfe\x83\xea\x86\x0f\x54\x24\x66\xdc\xfe\xce\x57\x96\xdc\xb4\xda\xb8\x29\x1f\x39\xf3\x9c\x24\x7e\xf2\xdc\xd1\xfc\x22\xae\xb9\x5d\xb9\xf9\xe8\x5b\x3f\xc2\xee\x8f\x1f\x7c\x3a\xff\x05\xd2\xb8\xb3\xb8\x08\x0a\xa0\x33\x8b\xeb\xe3\xb1\x5a\x4f\xb3\x15\x00\x30\x01\x47\x4e\xb2\x25\xe1\xf3\x09\x20\x9e\x2a\xf5\xf3\x30\xb9\xe4\x4b\x03\xbe\x8f\x2b\xa0\x72\x53\xbc\x5b\x5b\xa2\x58\xc2\xf4\xb5\xe1\xd0\xa9\xa7\x24\x86\x25\x92\x65\x2c\x5f\x46\x84\x23\xe1\xc7\xbc\xed\xa3\xf3\x07\x4a\x39\xbe\xc8\xfa\x22\x08\xe1\x6f\x81\x43\xe7\x34\x95\x0d\xaa\x57\xcd\xcd\x0e\xd0\x3d\x26\x59\x40\x30\x5a\xad\xbd\x41\x7b\x6a\x70\x41\x8e\x31\xc5\x53\x76\xe0\xc8\xa2\xec\x23\x8f\x64\x99\x4f\xe6\x32\x9b\xf3\x67\xce\xcd\xc7\x99\x4f\x10\x3e\xf6\xdd\xb1\x83\x86\x71\x5c\x14\x35\xa2\xb7\xd4\x6f\xb1\x0a\x42\x0b\x33\x20\x1f\xf9\x44\x4f\x15\xef\x70\xc6\x65\x33\x89\xe7\x9a\x80\xf2\x54\xc0\x71\xb5\x69\x27\x35\x86\xb0\xcc\x1a\x5a\x76\x22\xd9\xc0\xb6\xec\xc4\x32\x2f\x90\xdf\x0b\x7c\xcb\x4e\xa9\x3d\xb4\x55\x58\xf3\xe6\x0e\x24\xc6\x6d\x12\xeb\xee\x61\x58\xc1\x13\x97\x0c\xee\x1e\xa3\x81\xf7\xc4\x7b\xdc\xe4\xaf\xe4\xe7\x1e\xf2\xf3\x8c\xd1\xc0\x17\x5b\x57\x92\x3b\x9d\x61\x58\x81\xfc\xce\x93\x46\x3d\x8c\xd1\xed\x81\xbe\x55\xe1\x77\xd2\xa8\x10\x46\xb2\xb9\x8a\x17\x32\xd6\x60\x5d\x3a\x9d\x96\x1d\xbc\x2a\xec\x1b\xc3\x4d\xa6\xa6\x0e\xf2\xaa\x9b\xda\xe0\x85\xef\xf0\x9b\x30\x09\x0c\x21\xe3\x6b\x6c\x52\x5b\x56\x76\xbc\x3f\xb1\xbf\xe9\xbd\xd0\x69\xc3\x46\xb4\x9d\x76\xea\xb4\xf9\xa9\xcf\x1b\xf7\xe0\x1b\xbc\x89\xfa\x40\x43\xf2\xd4\xae\x4b\x6a\x97\x5d\xcc\x9b\xa3\xe7\x1f\x36\xb4\xcd\x19\x3d\xbb\xb3\xa5\xd9\xbe\x98\x1f\x77\xe5\x69\xb3\x4f\x39\x6a\x4c\xb7\x5b\xef\x0f\x74\x5d\x8a\xbb\xff\x79\xe1\xdd\xaf\xe5\xb7\xd3\x6f\xde\x74\xab\x71\x13\xcd\xe5\x7d\xc4\x7e\x24\xa1\x97\xc2\x29\x99\xb3\x81\xb4\x1b\x14\xcb\xac\x9e\x54\xaa\xd0\xfd\x2d\xc1\x7c\x69\x65\x1b\x35\xab\xf2\xf1\x39\xc9\x47\xfb\xbe\x16\x16\x80\x3a\xc0\x69\x2d\x05\x48\x56\x2f\xf9\xd5\x5e\x7e\x8f\x3f\x00\x12\x64\xe5\x4d\xee\xf2\x26\xaf\xfa\xcb\xe6\x2d\xb7\xcd\xfe\xe5\xf3\x5b\x6e\xbf\x7f\xfd\xb3\x5b\x96\xd4\xd8\x52\xbf\xba\x7d\xfe\x4b\x03\xad\x43\x3f\xbe\xfb\xe3\xed\xf8\x45\x83\xfd\xc8\x77\x8b\x1e\xd9\xbe\x8b\x7d\x9a\xfc\xfa\xc1\x7f\xb3\xb7\x1c\xee\x5a\xfb\xe3\xab\xaf\x9a\x32\x79\xea\x6f\x69\x1c\x03\x3c\x20\xd5\xe8\x2a\x5a\x0b\xa5\x94\x87\x2e\xc0\xe8\x30\xaa\xe8\xb2\x71\xaf\x1c\x10\xe0\x8d\x05\x4a\x57\x95\xf6\x27\x00\x64\x83\x5e\x3a\xf4\x6b\x12\xa8\x0a\xb1\xd5\x06\xe4\x83\x2a\x8d\xa3\x40\xa2\x1a\x89\x13\x32\x56\x0f\x6d\xe4\x6a\x34\x84\xbd\x98\x67\x20\x68\x80\x50\xa7\x9c\x75\x66\xfe\xbc\x42\xc8\x53\x81\x73\xa6\x61\xdd\x13\x61\x8d\x0f\x84\x72\xfe\x5c\xd0\x6b\xba\xd5\x0d\x3c\xf1\x5a\x8a\x58\x81\x69\xc6\x57\xc2\xc2\x24\x1b\x4c\x27\x43\x2a\x53\xe4\x91\xb9\xed\xde\x75\x4f\xa8\x1c\x2b\x47\xce\x32\xbc\xf8\xf3\xfb\x5f\xdf\x9d\xdf\xa1\x71\x4e\x18\x77\x21\x1b\x12\x28\xfb\x60\x29\xeb\x80\x9f\xcd\x65\x3d\x76\x0b\xeb\x88\xcb\x1e\x5b\x81\x6b\xc5\xee\xcf\x49\x1e\xad\xda\x27\x79\x93\x40\x38\x10\x56\x0b\x7e\xc0\x9c\x89\x64\x8f\x5d\x3f\x49\x5f\x64\x17\x08\xe1\x54\x52\xf0\x34\x50\x01\x9e\x5e\x5c\x02\xef\x38\xfe\xf9\xd9\x1f\xfe\x69\x3f\x7a\x1a\xbb\xd5\xf3\xf7\x7d\xbf\xfb\xae\x17\x83\x40\x4c\x39\xaa\xfc\x0b\xdb\xb0\xe1\x99\x43\x87\x8f\xa8\x33\xf2\xd3\x39\x2f\x74\x15\x27\xa0\xe2\x68\x3c\xac\xbe\x06\x74\xf5\x35\x22\x22\xd1\x0f\xee\x0d\xac\x89\x7e\xda\x42\x0c\x8b\x64\xbd\x34\x98\xca\x18\xcd\x0e\x48\x44\x40\xcc\x16\x39\x5c\xc6\x7a\x7f\x9a\x72\xbe\x59\xb5\x4d\x90\x8c\x2e\xe5\x77\x62\x93\x4f\xec\xc5\x95\x30\x0b\x5f\x81\x4f\xc7\xa7\x6f\x3c\x6d\xe4\x9b\xae\xc8\x03\x53\x2e\x53\x9e\x56\xde\x02\x7a\x84\xef\xbe\xfe\xdb\x37\x7f\x3f\xf8\x8f\x7f\x32\x9f\xe1\x29\xf8\x81\x4f\x3c\x77\x2d\xf4\xad\xda\xd0\xb4\x41\x51\x56\x2a\xd3\xf1\x43\x78\x8a\xf2\xa9\xf2\x21\x8e\xe3\x26\x5c\x8f\xfb\x2b\x1f\xd1\xbc\xdd\x18\x37\x7c\x0b\x1c\xe2\xe3\x54\xcd\xd4\xb0\x96\xb2\x47\x8b\xb5\xe4\x80\x08\xfe\x5e\xa3\x76\x33\x34\x21\x5e\xd9\xab\x26\x1c\x9c\x15\xf8\x0e\xe5\x68\x98\x17\x32\x2e\x1e\x41\x95\xaa\x74\x8c\x9d\x29\x6e\xa7\x94\xe6\xa0\x8e\x9b\x8e\xed\xdf\x5e\xbf\xe9\x94\xe4\xb0\xaa\xed\xce\xda\xbb\xa7\x9e\xae\x92\x1b\xac\xec\x5e\xb7\x7c\xc5\xba\x75\xcb\x28\x97\xc1\x59\xa7\xb9\x4e\xbd\x7a\xaa\xff\xd9\x97\x9a\x16\xc8\x1a\xa7\xc1\x6f\x7f\xbd\x77\xcf\xae\x8f\x3f\x2e\xe8\x8b\x98\xbe\x30\xee\x02\x7d\x91\x69\x2a\x0a\x89\xca\x24\xa8\x87\x24\x99\x53\x72\x03\x9b\x93\xf8\xa4\x16\x2a\x57\xf9\x81\x11\x98\x9c\x8f\xcf\x0f\xd5\x08\x87\x8a\xbe\xd1\xd4\x44\x64\x36\x98\x26\x97\x91\x6c\xf4\x02\xf0\x53\x36\xf3\x64\x9f\x0d\x11\x72\x70\x5e\x9f\x51\xd5\x44\xa0\x07\xa6\xff\x22\x4c\xbe\xde\x1c\x17\xb3\xf0\x79\xb8\x1d\xc7\xd6\xa6\x77\xdd\xf9\xe1\x9b\x9b\x6f\xbb\xef\xfa\x79\x4d\xd3\x94\x0d\xca\x87\xca\x2e\x45\x7a\xf3\xab\xdf\x1f\xf8\xf2\x8b\x03\x7f\xf8\x8a\xfa\xe1\x2b\xe3\xaf\xfc\xed\x9f\x8f\x7c\x6b\x70\x3e\xb2\x68\xc4\xc8\x57\x95\xbf\xc2\x09\xce\xc3\xd7\x96\xb2\x5a\x50\x8d\x4e\xc5\xcb\x55\x1b\x26\x82\x06\xfb\x0d\x14\x97\x23\xd7\xa8\x67\x48\xb6\x5c\x6f\x01\x5d\x4e\x47\x42\xc3\x9a\x15\xe5\xd6\x35\x19\x56\x07\xc5\xe6\x00\xb4\x8c\x1c\xa1\xec\x67\x81\xc7\x48\x36\x0a\xea\xae\xa1\x2f\x50\x5f\xc3\x0b\x32\xf2\xa6\x8b\x63\x5b\x50\x75\x2c\x6c\xdc\x1d\xab\xab\x70\xbe\xb5\xd3\xd1\xb1\xff\xda\x3f\xbb\x6d\xc5\x8f\xbb\xbb\x7b\xb6\xdd\x37\xe2\x0c\x25\xff\xc7\x87\x0f\xdc\xb6\x75\xd9\xe2\xc5\xcb\x1f\x5f\xa2\xec\x67\x9a\xb0\x0d\x0f\x58\x7a\xf6\x99\x6f\x7c\x7c\xe4\x2c\xc3\x4b\xd8\x70\xc9\x7d\x6f\x2b\xdf\x2a\x1f\xcf\xc7\xdc\x8b\xbb\xf7\xed\xdd\xf3\xeb\x8f\x8a\xf5\x3b\xc1\xb8\x09\x89\xa8\x06\x4d\x56\x39\x78\xe1\xdb\x73\xda\x72\x52\x75\x32\x6b\xf5\xd9\xc9\xe5\x61\xb5\x15\xd8\xcc\xdc\x42\x4e\x72\xab\xf7\x9a\x98\x93\x7c\xa0\xfd\x10\x52\x75\xbf\x6a\x71\x1c\x2e\x35\x92\xe7\xd8\x79\x49\x48\x23\xd9\xe9\xe3\x85\x0c\x22\x19\x4f\xa1\x92\xc7\x7b\x0d\x51\x12\x4d\x14\x4b\x79\xba\xde\xd3\x16\xa6\x5e\xd9\xa3\xe4\xd6\x6e\xd1\x2a\x79\x4b\x7f\xf7\xf6\xa6\xed\x5b\xa1\x8e\x77\xc1\x67\xdf\xe4\x77\xa8\x55\x3c\x65\xf8\xc2\xa7\x16\x2e\xa0\x5c\x6c\x5e\xc3\x9d\x5c\x04\xd5\xa2\x81\xe8\x26\x55\xc5\xa3\xde\x92\xcb\x78\xc8\xf7\xd6\x9f\xb6\x1c\xb5\xc8\x8c\x76\xda\x6a\x1d\xb9\x8c\xad\x2a\x9a\x4c\x26\xa5\x5a\x8a\x88\xf4\x51\x28\x0d\xf0\xc9\x64\x5c\x6e\x60\x0c\x6e\xe2\x7b\x58\xa3\xca\x63\x0d\x94\x67\xae\x30\xc4\x6d\x32\xc9\x04\xb4\xc8\x2d\x8c\x0b\x91\x5b\x35\xf6\xba\x30\xdc\xe1\xd4\x35\x9b\xc8\xab\x13\xc4\xba\x6f\xd2\xb4\x81\xd1\xe2\x39\x83\x7d\xd4\xda\x1b\xf6\xfe\xed\xeb\x7d\x9f\xde\x6e\x37\x98\x1f\x5d\x33\x6f\xc5\x8a\x87\x9f\x5b\xcc\x28\x5e\xee\xa0\x1a\xda\x75\x77\x8e\xed\x77\xc9\xf9\xca\x3e\xe5\x5b\xf2\x65\x3e\xd3\x6f\x6c\xa7\xd2\x69\xf0\x7c\xb6\xe3\xf3\x5f\xed\xfc\x64\xf3\x3b\x88\x41\x3b\x8e\xa5\x80\xd7\xc0\x89\xfc\xe8\x72\xed\x45\x62\x50\x3c\xe3\x87\x86\xb2\x2d\x97\x75\xb8\x10\x39\x3d\x87\xad\xa0\xea\xe8\x14\x73\x32\xe3\x4a\x02\xbb\x86\x47\x6d\xf5\x04\x71\x1c\x00\x26\xb2\xc5\x4e\x47\x34\x6d\x69\x44\x67\xd2\x2d\x69\xc9\xcf\x43\xe3\x87\x04\x80\xa9\x0a\x14\x06\x3b\x36\x1f\xa8\x40\x5c\x60\xdc\xb4\x6b\xf7\x1e\xe5\x0f\x57\xe7\x6f\x62\x26\x28\xd3\x99\xf8\x82\xf9\xf3\xee\xa6\x79\xdb\xa4\x63\x07\x59\x05\x66\x4e\xaf\x44\x99\x18\xa2\x32\xcc\x19\x37\xf1\x38\x5b\x51\x7a\x26\x24\x02\x88\xd1\x4c\x16\x26\xe6\xa4\x48\x12\xce\x28\x54\x98\xfa\x37\xf3\x1b\x0d\x36\xb7\xaf\x9a\x22\xd7\xaa\x63\xbc\x20\xd5\xa6\x25\x1b\xdf\x83\x1c\x1e\xa8\xf4\xbb\x49\xb4\x4d\xdc\x6d\x04\xee\x18\xc1\x80\xf1\x4d\x4d\xed\x50\xef\xe3\x4c\x4e\xa6\x38\x9b\x51\x57\x3f\xe9\x82\xb5\x2f\x2e\x98\xd5\xb1\xf4\xbe\xa5\x6b\x87\xbe\xf4\xe6\x87\x98\x79\x71\xf7\x33\x8b\x46\x3c\xdf\xbd\xf5\xf3\xd3\x3f\xba\xf3\x5f\xca\x7f\xe3\xb9\x57\x2e\xb9\x79\xe4\xe0\x73\x2f\x3f\xe3\xea\x9b\xc6\xae\xbc\xe0\xbd\x5f\x3c\xf5\xfe\xd9\x43\x2f\x98\x78\xea\x0d\x77\x5f\x21\xd7\x0d\xfc\x3d\xc2\x68\xc2\xb1\x83\xec\x34\x98\x07\xbd\x52\xed\xc5\x54\x9b\x73\xc0\x60\x2f\x5b\xcd\x85\xdb\x3e\xe4\x81\x3d\x99\xc8\x33\x2b\xc0\x9e\x1a\xb4\x3d\xd9\x1d\x60\xf7\x8d\x06\xab\xcb\x57\x5d\x47\xf7\x54\x47\xf7\x64\xe5\x7b\x90\x5d\x80\x3d\xb9\x04\xb5\x5e\x40\xf6\x84\x8b\x7b\xf2\x89\x5e\x27\x2e\x6e\x8a\x8b\xd5\x4e\x18\x31\x7b\xfe\xc6\x6b\x6e\xb9\xe9\xda\x17\x46\x3c\xbf\x62\xe7\xc7\xc3\xee\x5e\x71\xfd\x8c\x41\x73\x66\xaf\x97\xee\xfd\xad\xd2\x85\x13\xe7\xdc\x30\x7e\xf0\xe9\xe7\x75\x8e\x38\x63\xcc\xa2\xae\x65\x0b\xcf\x99\x7a\xf1\xf0\x7e\xa3\x46\x0e\x3c\xff\x82\xf1\xdd\xa7\xc3\x19\x75\x21\x64\x98\x08\xdc\x9f\x83\xd5\x1c\xd4\xa6\xf5\x96\x4c\xe4\x8c\x9c\x09\xca\xf3\x69\x73\x00\x4a\x41\x32\xf1\x32\x63\xa1\x22\xe5\x2c\x60\x15\x2c\xb8\x2d\x2a\x46\x9b\x2c\xb8\x21\x2a\x76\xe1\xcf\x94\x81\xec\xae\xfc\x35\x93\xf0\x2e\xa5\x06\x8f\xc5\x47\x97\x33\x57\x31\xd1\x27\xba\x99\xfc\x5f\xf3\xab\x99\xd5\x88\x39\xb6\x50\xf1\x32\x9f\x42\x3e\x55\x87\x2e\x41\x19\x1f\x31\x5c\xd8\x9c\x93\xf8\x84\x6c\xb5\x00\x42\x97\x2d\x16\xb8\x75\x3c\x71\x55\x49\xd0\x4e\xa8\x27\x57\x6e\x90\xa7\xac\x70\x56\x9e\x56\x21\x7d\xbc\x6c\x72\xa4\xd3\x72\x6d\xb8\x10\xc6\xa8\xa0\xa2\x92\x24\xb9\x8d\x07\x90\xf2\x30\xb5\xd0\x3b\xe3\x81\x9f\xdd\xf7\x50\xd7\x85\x4d\x57\x57\x45\xa6\x0d\x7e\xee\xb1\x09\x77\xce\xee\xbe\xfa\xbc\x64\x72\x40\xbd\x71\xd8\x0d\xb7\x3d\xba\xf0\xf0\x8d\x57\x5d\xe1\xb0\x3c\xe4\xf4\xac\xfb\xa5\xe1\xe0\x1d\xd3\x2e\x08\x9f\x39\xb2\x15\xe1\xc2\x4c\x60\x0d\x5a\x45\x51\x0f\x27\x9c\x20\x13\x12\xb2\x5f\xbd\x51\xab\x0b\x53\x64\xd5\x96\x82\x00\x4a\xc9\xdc\x18\xf9\x3c\xdd\x02\xbd\x5b\xd9\x6a\xca\x14\x61\xe1\x65\xaf\x98\x06\xee\x38\xc1\x9f\x4e\x4b\x6e\x3e\x63\xb2\x73\x10\x2d\xf8\xd5\x0a\x4d\x98\x97\xc4\xb4\x6c\xb6\x53\xbc\xa7\x91\xaf\x38\xed\x47\x5e\x17\x68\x45\x76\xc2\x24\x59\xc9\xfc\xd8\xdf\x87\x8f\x6c\x19\x32\xd9\xa7\xbc\x56\x32\x3a\xa6\x2c\x52\xfe\x1e\x5c\xe6\xb9\xee\x43\x7c\x21\x73\x0f\x2a\xcc\x8d\xdd\x0f\xf8\xdc\x0b\x50\xc6\x5c\x78\x41\xac\x2c\x1d\x13\xa3\x4c\xb8\x76\x01\xf2\x14\xf2\x49\x9b\xc4\x5c\xc6\x04\x16\x31\x19\x2d\x71\xb8\x86\xec\x48\xa7\x03\x89\x64\xab\x99\xbc\x89\xce\xc2\x8b\x01\xa3\x62\xda\x6b\xe1\x5d\xf8\x28\x7b\xbe\x92\xde\xfc\x21\xbc\x0f\xe4\x5d\x80\xc1\xbe\xc9\xe4\x51\x40\x85\x79\x31\x78\x0f\x66\x50\x4d\x1a\x18\xef\x80\xef\x51\xa0\xe7\xc1\xa8\xf4\xe6\x46\x72\x08\xd1\x84\x14\x81\x5c\xd8\xe3\x80\x0a\x88\x27\x02\x42\xda\xbc\x25\x2e\x05\x93\x99\x08\x68\x69\x47\x48\x3a\x5c\x47\x9c\xde\x57\x4d\x19\x96\x04\x5e\x0a\xc2\x37\x89\xa1\x67\x65\x86\x51\x3d\x68\x91\xb7\x75\xb4\xb9\xa3\x49\xbf\x08\x11\xb2\x5a\xae\xd4\x8f\xeb\x45\x9f\xc6\x2d\xe7\x8d\xf5\x5f\xde\x34\x7a\x68\xe9\xac\x1e\xb1\xf3\x5c\x3c\x3c\xfc\x98\xd9\x3e\xe6\xf4\x0d\xa5\xa3\x7a\x60\x67\x75\x6e\x96\x47\x5d\xa8\x64\x56\xd6\x91\x90\xcd\x2c\xe5\x1c\x76\xab\xb3\x93\xee\xc2\x40\x9c\x1b\x2a\xaf\x6e\x44\x2d\x8d\x64\xb3\x83\xaa\xe9\x20\x9e\xc6\xc5\x6d\xda\x02\x69\x7e\xdb\x06\xe3\x78\x43\x87\x9e\x91\xec\xdf\x7a\xfe\xfc\x79\x30\x36\xd9\xf5\xe3\x1f\x89\x4f\x85\x9f\x58\x67\x7c\x0d\xec\xbb\xf9\xd8\x41\x6e\x3e\xe7\x45\x21\x74\xbe\xaa\x90\xa3\xc3\xde\x67\xed\xde\x00\x76\xc4\x65\x3b\x97\x93\x5c\x09\xad\x8f\xa0\x4b\x58\x49\x96\x6a\x4b\x42\x0d\x0e\xd2\xd3\x00\x79\x6c\x30\x2f\x48\x7c\x59\x2e\x2a\x6a\xc1\x3a\x8d\xf9\x36\x6f\x79\xf3\x9d\xec\xb6\x97\x2f\x38\xf7\x75\x67\x54\x5a\xa1\x7c\xa6\xfc\x5b\xf9\x46\xf9\x0d\x60\xac\xbb\xe4\xb7\x5f\xdb\xc2\x66\xdf\xb5\xcd\x5e\xee\xdb\xb2\x35\x94\x5f\x7a\x0c\x29\x7f\xc1\xb5\x64\xad\xab\x8f\x1d\x34\xbe\x68\xf8\x0e\x55\xa3\xb3\xd4\xdc\x3a\xac\x02\xab\x35\x98\x81\x0e\x49\xed\x85\x82\x0d\x89\xdd\xd4\x1c\x3a\xa2\xf1\x73\x07\xc2\x69\x2d\x7b\xee\x6b\x91\x5a\xc2\xac\xa2\xa0\xcf\x3f\xeb\x75\x67\xad\xfc\xd8\xa3\x21\x4b\x32\x73\xcb\xce\xf7\xf0\x9d\xcc\xae\xfc\x48\xc0\x3f\x0f\x9d\xe9\xb8\x77\xb9\xff\xf5\x57\xf9\xa3\xd2\xe2\xf3\xc6\xbd\x46\xbf\xa1\x73\x8e\xe5\x8c\xdf\x19\x37\xa1\x08\x9a\x4d\xcf\x56\x72\xd3\xce\xaf\x90\x94\x82\x89\x02\x21\x58\xd5\x5e\x92\xab\x65\x38\xd0\x4a\xe2\xc8\xf1\x56\xc1\x94\x6c\x15\xb9\x35\x38\x1a\x95\xf9\xfc\xb9\x8c\xcf\x0e\xd8\x14\xc1\x12\xcf\xd8\x41\xac\xcd\xee\x52\xe9\xc2\xec\x1c\x2f\x64\x3c\x41\xda\xed\x47\x16\x5e\xe8\xe1\xec\xbe\x2a\xf2\xbe\x60\x5e\x66\x29\xd8\xbb\x2d\x2a\x72\x8c\xe8\x25\x31\x76\xdb\x60\xa6\x89\x78\x88\x4f\xa0\x19\x13\x3f\x58\xe8\x38\x87\x19\xdb\xf3\xfc\x3f\x0f\xfe\xf5\x1f\x6b\x24\x66\xac\xb2\xf4\xf1\x55\xca\xd3\xca\xbb\xca\x9b\xca\xca\x55\x8f\x19\xbd\xab\x97\xde\xab\x6c\xfd\xfd\xbf\x8f\x21\x74\xec\x3f\x5f\xe0\x53\xef\x5e\xba\xfa\x16\x65\xed\x2e\xe5\x03\x65\x35\x9e\x80\x07\xef\xc2\x13\x6e\x86\xfd\x22\x84\x00\x53\x11\x44\x43\x68\xc4\x46\x61\xde\xa0\x65\xa3\xc9\x56\xd8\xf6\x02\xc2\x39\x0c\xea\xc5\x41\xc0\x12\x8b\x24\x2e\x03\xda\xcc\x41\xad\x3c\x45\x6a\xb7\x77\x78\x68\x74\x65\x6a\x6b\x4f\xd5\xf2\x5e\x13\x8e\x6d\xc7\x67\x8f\xac\xe6\x1b\xe3\xfe\x0d\x5d\xa7\x8c\x4c\xf6\x6f\xb9\x10\x7b\x27\x28\x0f\x6f\x31\x6e\x3a\x3a\x26\xbb\xa0\x73\xfc\x35\xa3\xf1\xaa\x8d\x67\x9f\x3f\x5a\x7c\x2a\xac\xec\x9f\xf6\xc9\xd1\x95\xea\x7a\xe6\x1a\x77\x21\x1e\x8d\x51\xa3\x60\xcc\xe8\xc8\x89\x90\x45\x4d\x49\xdd\x36\xfa\x9d\xd9\x41\xf9\x0c\xee\x2e\x9b\x1d\xc0\x31\x48\x46\x76\x5e\xc8\x98\xac\x0e\x88\x74\x79\x5a\x3c\x52\x01\xad\xb8\x31\x56\x37\x74\xf4\xd9\x13\x1a\x31\x87\x67\xbc\xab\xc4\x36\x2b\xd9\xfa\x64\xdc\x18\x7d\xcc\x7f\xc6\x85\xf9\xac\x06\x5b\x65\xb6\x9e\x49\x6c\xc3\x28\x5e\xc3\x38\xc3\x44\x14\x01\xb4\x24\x56\x99\x9c\x64\xb7\x19\x24\xd9\xab\x2c\xe0\x0a\xb4\x77\x52\xa5\x8a\x73\xb8\xf9\x8d\x46\x83\x53\xa4\x30\x07\xa4\x06\x0a\x00\x11\x6e\xef\xf0\xe8\xca\x9f\x45\xac\xf0\x48\x4c\xc1\xc1\xfc\x05\x2b\x9a\x2e\x3d\xf7\xd4\x64\x43\xa0\x7e\xa0\x4f\x79\x68\xf4\xf6\x85\x67\x77\x25\xc7\x6c\xe8\x6a\xa3\xb0\xe0\xb3\xfe\x0b\xbf\x7a\xe3\x8f\x03\xf7\x5b\xdb\xd3\x47\xed\x3d\xcf\xf2\x8b\xec\x6f\x2e\x21\x6b\x04\x2c\x25\xdc\x45\x2a\xfb\x3a\x60\x62\xcc\x6a\x8c\x90\x35\xb0\xc8\xec\x88\x4b\x8e\x94\x6c\x30\xd3\x01\x5c\x21\x41\xaf\x1f\x97\x0a\x6d\x34\x9b\xd4\xc4\x9c\x42\x1b\x29\xbc\x31\x25\x46\x71\x54\x1c\x8b\xaf\x57\xfe\x82\x67\xe2\xb6\xbc\x8f\xdd\xa9\x6c\x3d\xac\xac\x51\xba\x59\xff\x7c\xa6\x61\x09\xde\xd3\x3d\x5f\xf1\x2f\xc9\x7f\xd7\x4d\xd6\x00\x78\x4a\x43\x97\x7e\x0d\x26\x15\x49\x64\x32\xfd\xd0\x35\xc4\xda\xa2\x1e\xb2\x06\x36\x25\x46\xd9\xa8\x78\x3e\xb6\x7e\x85\xcf\xfa\x3c\xff\x09\xf3\x8f\x2f\x77\x2b\xef\x1f\x65\x2e\xba\x1d\xdf\xb9\x08\x77\x2e\x98\xab\xbc\xb6\x48\x79\x62\x3e\xf9\xf3\xcf\x3c\x76\xd0\x30\xcc\xb8\x09\x85\xd0\x78\x35\xeb\x30\x58\x72\x19\x97\xea\xc2\x59\xc1\x1a\x74\x39\xa0\x47\x06\xb7\xa0\x69\xaf\xec\xf3\xd1\xfe\xa9\xcf\xa4\x12\x3c\x21\xd9\x10\xa4\x94\x15\x56\x5e\xc6\xbe\x74\x5a\x12\x04\xc9\x9e\x96\x5d\x4e\xf5\x3e\x2c\xf0\x56\x34\xc6\xb1\x0a\x01\x05\xb2\x8a\x68\xed\x99\x57\xfd\x71\xf2\x8e\xb7\xdf\xdb\x7e\x0f\x5e\x93\xbf\x84\x5d\xa8\x8c\x9b\xff\xf9\x5d\xca\x7b\x4a\x4e\xc9\x0f\x5b\x3b\x68\xd0\xda\xa7\x1e\x5e\x71\x3f\x7e\xba\x7b\xb1\x32\xc9\x70\xf3\x8e\x39\x9f\x7f\x8f\x54\x2c\xcd\x55\xc6\x4d\x14\xa9\x01\xeb\x15\x2c\xb9\x42\x63\x31\x6b\xb0\x07\x39\x07\xec\xa1\x80\xd8\xf0\x15\xb1\x19\x2a\xb9\xb3\x40\xa5\x1c\x25\xbb\x4a\x30\x68\x20\x06\x94\x39\x0b\xaf\xb1\x4b\x8c\xc0\x1d\x10\xfd\x15\xbb\xa1\x6a\xac\xd5\x82\xa7\xdf\xf9\x87\x87\x95\x71\xec\xc2\xfc\x65\xf8\xb9\x67\x7e\xf9\xda\x7b\xdb\xaf\xfa\xe2\xca\x09\xbf\x7b\xb0\x47\xf9\x39\x96\xe6\x7f\x78\xab\x01\xaf\x5a\xdc\xad\x5c\x79\xff\x9a\x65\x8b\x57\x0d\x1a\xb4\x76\x40\xec\xc6\x0f\xe8\xdd\x38\x46\xf1\xb2\x9f\x19\xba\x50\x80\xbc\x37\x34\xac\xb2\xc2\xf5\x0c\xaa\x8c\xb4\xd6\xee\x74\xe4\x32\x4e\x00\xe4\x39\xad\xaa\x40\xb6\x13\xf4\x33\x80\x29\x85\xf7\xd1\x98\xc8\xcc\x67\x10\x0b\xb0\x3c\x23\xa5\x3c\xf6\x0f\x46\xe5\xcb\xed\x10\xb9\x68\x1d\x1a\x83\x4d\xdf\x28\xa3\xd8\x31\xf9\x85\xf8\x8d\x3b\x7e\xbd\x67\xfb\xb3\x1f\xbc\xbc\x40\x39\xf2\x17\xe5\x73\xff\x6f\x31\xe6\xf1\x77\x73\x96\x2b\xae\x59\x1b\xd6\x2e\xc9\x8c\xeb\x3e\x13\xb3\x74\x9d\x69\xc5\xcb\x2e\x37\x74\xa1\x7a\x74\x1f\xca\xb0\x88\xf2\x34\x53\xe0\xab\xc3\x9a\x93\xea\x12\x72\xb5\x25\x97\xe5\x2d\x7e\xa7\x23\x2e\xf3\x66\x0d\x9e\x25\x39\x92\x72\x48\xc8\x65\x42\xb0\xfc\x90\xdb\x12\x27\x79\x02\xa7\x8a\x84\x00\x58\x2b\xc4\x0b\x9b\x58\xab\x9d\xf7\x43\x76\x20\x79\x79\x39\x52\x0b\xb1\x5e\x35\x89\x93\x22\xe9\x34\x7d\x4a\xbd\xa0\x75\x62\x83\x39\x45\x3f\x89\x76\x4b\x1d\x87\x76\xe2\x74\xf0\xa5\xc6\xf4\x6b\xaf\x3c\xf7\xf0\xa6\x9d\x77\xe0\xdb\xf2\xfb\xd8\x26\x65\xf6\x6f\xbe\xfc\xee\xeb\xeb\xaf\x9d\x36\x75\xfd\x53\x3f\xdb\xb3\xe5\xdd\x43\xf7\xde\x71\xd3\xbc\x9f\xcd\x98\x85\xc7\x2e\x9f\xa3\x48\xd6\xd7\x33\x6f\xed\xee\x3f\x24\x9e\xea\xea\x1e\x7e\x2f\xec\x77\x32\x42\x86\x7e\x80\xcd\x52\xf9\x9d\xe5\x88\x39\x27\x19\x12\x52\x28\x25\x1b\xcd\x39\x29\x90\x04\x69\x2b\x15\x9f\x65\x81\xdb\x5c\x63\x47\x88\x5a\xe2\x1a\x6d\x02\x4c\xdb\x5b\x0c\x96\x38\x00\xb6\x44\x8b\xfa\xdc\x22\xd9\x10\xa1\x9f\xa9\xdd\x08\x39\xb9\x48\xdb\x6f\x6d\xb8\x23\xda\x16\xd5\xa0\x19\x5a\x06\xc4\x99\x52\x62\xd4\x89\xb1\x18\x15\x27\xe3\x6b\x27\x29\xb7\xe3\xbf\x0d\x69\xfd\xd9\xf5\x97\x3d\x76\xf6\xa4\xd7\xff\xf8\xc6\xef\xe3\xa9\x5d\xca\x7e\xdf\x60\x65\x16\xa3\x2c\xc3\x9b\x67\x2d\xba\x64\xc5\x4f\xae\xbd\xf9\xb4\x53\x67\xae\xdf\xb1\x7e\xdc\xb3\x97\x2e\x8a\x9e\xaa\xb4\x5a\x16\xe9\xbf\xe9\x30\xba\x01\x65\x42\xda\x37\xed\x64\x28\x75\xa7\xe4\x4e\x66\x05\x6b\xc8\xa9\x7d\xd6\x55\xf0\x48\x09\x62\x2e\x23\x00\x36\x43\x70\x5b\xe2\x19\x9b\x00\x60\x2c\x87\x25\x2e\x09\x34\xdf\xf3\xfb\x28\xd3\x9e\x49\x20\x1e\x19\x82\xbd\x85\x8a\xdf\x3d\x68\x7b\xe9\xbf\x74\x3e\x06\x41\x59\x2a\x09\x68\x5d\xed\x5b\x7f\xe3\x17\xca\xb3\xec\xc2\xfc\xae\x71\x2b\xff\xfd\x80\xfe\x4b\x9f\xbf\x92\xa9\xeb\xee\x56\x6e\xbd\xe1\x83\x07\xe9\x77\x7e\xda\xb1\x83\xec\x22\x43\x17\x0a\x92\x3d\x40\x7c\xc6\x9a\x73\xa0\xac\x24\xdb\xad\x39\xc9\x95\xcc\xf2\x96\x80\x83\xf8\xa0\x85\x3e\xb4\x56\x00\x5b\x66\x78\x68\x02\xf1\x2e\x4b\x3c\x63\x05\x11\x49\xab\x9d\x8a\x48\x12\x5f\x14\x55\xc1\x1a\x8e\xe7\x05\x99\x05\x81\x1a\xa0\x43\x40\x90\x8c\x60\x91\xee\xc1\x57\xba\x05\x51\x03\xe9\x9f\xf6\xf2\xab\x0b\x97\x3f\xf9\xcc\x5b\xf7\x30\x7f\x55\xba\x12\x07\xfe\x7e\xe8\xd3\x6f\x53\xab\xc7\x4d\xbb\x7e\xda\x54\x3c\x67\xf9\xf2\xbf\xbf\xf6\xf2\x0b\xaf\xd0\x6f\xa8\xeb\xd8\x41\x76\xbc\x71\x0c\x8a\xa2\xc5\x28\x53\xab\xad\x1d\x2a\x39\x3e\x53\x4e\x72\x24\x33\x6e\xd0\xca\xaa\x83\x27\xd8\xef\x00\xf5\x2e\x3f\x44\x3b\x7e\x91\x44\x3b\xa0\x63\x67\x77\x52\x50\x2e\x1f\x20\x59\x24\xf9\x1d\xd9\x42\xb5\x87\x62\x02\x79\x3b\x2f\x00\x28\x57\xf2\xf3\x19\x0b\x0b\x03\xcc\x1c\x04\xf5\xd5\xbc\x14\x26\x1b\xab\xd5\x78\x84\x64\x5c\x9d\x4e\x4b\x1e\x01\xf0\x08\x1d\x45\x92\x1c\xdc\x89\x63\x05\xb2\x07\xaf\xcf\xaf\x7e\x5b\x5d\xd2\xfa\x07\xef\xba\xf2\x81\x2b\xce\x7a\xe5\xd5\x33\x20\x91\xea\xdf\xbe\xee\xe7\x7f\xda\xf3\xdb\xd6\xee\xf1\xe3\xbb\x86\x5f\xd4\xde\xef\xe7\xb7\x6c\x86\x5c\x6a\xdb\xe9\xa3\x85\x91\x4b\xa6\x3e\xb9\x4e\xab\x5f\x9d\x6f\x98\x88\x9c\x28\x80\x7e\xa2\x66\xdc\x2e\x33\x9d\xfc\x03\x25\x26\x59\x84\x22\x96\xee\xae\x93\x5c\x49\x99\xe1\x73\x92\x93\x76\x7e\x2c\x62\x8e\x5e\x79\x94\x4c\x93\x24\x27\x9c\xca\x10\x9c\x31\x58\x58\x0d\x1a\xeb\x4f\xd1\x8f\x85\x31\x98\x82\xb8\x1e\x69\x48\xe3\x47\x03\xe6\x9b\x7e\xf3\xf6\x9f\x5e\x51\x5e\xf8\x1d\xb6\xe3\xe6\x47\x67\x3f\x36\x4f\xf1\x72\xed\xcb\x5e\xfc\x76\xef\x2b\xca\xc7\x1b\x1d\x4a\x33\x73\x5d\x0c\x07\xf6\x3d\xbc\x36\xbb\x13\x21\x8c\xb7\x2b\x5e\x66\x12\x68\x90\x54\x23\x09\x25\xa0\xc5\xae\x6a\x97\xf1\x39\xf8\x0f\xd5\x2e\xc3\x7c\x8a\xc7\xdb\x9f\x51\xbc\x66\x74\x88\xec\x73\xab\xe2\x65\xa7\xc0\xbf\x67\x42\xfd\xe1\xdf\x34\xa4\x24\x9c\x00\x2d\x27\xb3\xf6\xef\x6b\xc2\x25\x26\x5e\x53\x45\xf4\xa8\xe2\xb1\x5b\x9f\xc1\x37\xa9\xff\x63\xf0\x3f\x08\xfe\x72\xbf\xe2\x65\x9f\xe2\xbc\xd0\xc7\x86\x4c\x33\x21\xb9\x40\x1f\x55\x72\x24\xc9\xa2\x6c\xf4\x2a\xb2\x24\x25\x53\x42\x6d\x5f\xcb\x0c\x97\x4c\x02\x40\xd4\x6c\x4f\x26\x33\xbc\xa0\x79\xbd\x64\x2d\x51\x4f\x35\x14\xfb\xd8\x51\xf2\xff\x3c\x85\x6d\xd3\x64\xf4\x7e\x3c\x5c\x79\x1b\x0f\x7f\x86\xfe\xa2\xbc\xfd\x0c\x16\x1e\x55\x96\x32\x9f\xe6\x63\x4b\x95\x47\xf3\x0c\xa3\x20\x06\x2d\x3d\xf6\x25\x5e\x0c\x38\x2f\x17\x39\x57\x3b\x09\x28\x2d\x89\x2c\x6b\x40\x2e\x83\xd6\xce\xcf\x72\x4e\x14\x34\xc4\xd5\x5f\x7a\x9c\x1c\x32\xc7\x65\x57\x00\xe0\x27\xce\x40\xae\x87\x77\xd9\x9d\x71\xd9\x41\x55\x5c\x64\xa7\x8b\x17\x64\x72\x9e\x48\xb6\xb3\x3c\xad\x71\x75\xe8\xf5\xcb\x52\x6c\x6c\xe9\xe8\x11\x23\x46\x9f\x3a\xbc\xf3\x14\xcf\x81\xd4\xad\x37\x9e\x72\xc6\x59\xa3\x46\x9d\xd3\x65\x7c\xe8\xc8\x9f\x80\x9b\x79\x07\x42\x56\x13\xcc\xbe\xb9\x51\x08\x35\x91\x8c\x9d\x87\x0e\x71\x4a\x0e\xb0\x80\x21\x12\xd5\x46\xbb\x97\x25\x5e\xa6\x15\xf5\x2d\x22\x48\x1b\xdb\x01\x52\x9b\xa3\x58\xa9\x00\x4f\x71\x45\x5e\x1e\x14\xa1\x24\x51\x00\x96\x1a\x0d\x64\x1a\x6d\x52\x11\x9a\xb8\xf2\xf0\xca\x0e\xfc\x26\x80\x4e\x6f\x55\x16\x7d\xb6\x83\xa2\x35\xbf\x31\x2c\xd1\x4d\xd4\x3c\xae\xd7\x82\x50\x1e\x52\x5e\x54\x96\x29\xb3\x57\x52\xec\xe6\xe1\x3f\x57\x1a\xb2\x81\xfd\x59\xba\xb8\x68\x61\x7f\x97\xe9\xf6\x67\xca\x51\xcc\x9b\x45\x9b\x3f\x70\xdb\x72\x19\x11\xa0\xc4\xa6\xdc\xf1\x36\x2a\xf2\xaa\xe8\x95\xe4\xe6\xe5\x86\xc6\x74\x5a\xc2\x82\x14\xf9\xdf\x6e\x75\xad\x6e\x78\xa7\xea\xb8\x5b\xad\x38\xcf\x03\x3c\xdb\xe6\xcb\xb9\x28\xe8\x77\xf4\x47\x1d\xe8\x7e\x94\x89\x52\x0d\x0f\xb9\x59\xdb\x2b\x89\x40\x1a\xc8\x16\xeb\x4d\x6a\x03\xaa\xc6\x92\x93\xac\x09\x60\xf4\x43\x7b\xb5\x5e\x85\x05\xc7\xa5\x50\x52\xb6\x39\x80\x72\xcc\xe1\x06\x7c\x59\x9a\xdc\x2c\x5e\x00\x89\xba\x78\x3f\x68\xc6\x38\xe8\xc5\xd2\x1c\xa5\x04\x10\xf5\xfc\x46\xc4\x19\x5d\x5e\x27\xf9\x67\x0d\x82\xd4\x54\x8a\x19\x4d\x55\x44\x8c\xf6\x61\x23\x0d\x48\x9a\x2d\x47\x91\x1a\x78\x9d\xa1\x6a\x8b\x86\xd2\xa1\x4b\x37\x95\x83\x4b\xf3\xde\x8a\x36\x63\x40\x93\x62\x0d\xe8\x37\x01\xf2\xa5\x54\xc7\xca\x9e\x92\x78\xb5\x94\xe2\xed\x43\xbe\xc9\x46\xf9\xa9\xa9\xc4\x03\x4c\x55\x43\x18\x6f\xe6\x69\xcf\x03\xd1\xf6\x1c\x95\x75\x2a\x55\xe8\xdb\xb1\x99\xb9\x67\x5a\x41\x97\x0f\x84\x9d\x4a\x44\x11\x59\xb4\x43\xf1\x1a\xbb\x8d\x5f\xc1\xda\x22\xe8\xa6\xb2\xd5\xf5\x08\xd8\xef\x8c\xcb\xd5\x86\x5c\xc6\x8e\x51\x1c\x56\x6a\xc9\xe9\x78\x4a\x7a\xaf\x54\xf2\x26\xc9\x63\x21\x87\x54\x71\x4e\x1b\x08\x6e\x99\x79\x2a\x7e\x2d\xfb\x41\xd8\x04\x99\xb5\x19\x33\x58\x34\xdb\xa7\xfc\x21\xd9\xc0\x88\x4a\xba\x87\x20\x48\x56\x51\xed\x90\x25\x6f\x1b\x3b\x07\xee\x7c\x1e\x55\xa3\x09\x6a\x97\xc2\x4a\x36\xe0\x4a\xc8\x9c\x25\x27\x85\x13\xb2\x68\xd0\xcf\x7d\x14\x0b\x32\x92\x90\x84\x0e\x5a\xc0\x99\x2b\x94\x62\x32\x06\xce\xa5\x52\x7e\x8b\x10\x25\x22\x4e\x2f\xe3\xd5\xe7\xea\x37\x64\x3b\x2b\xac\x9d\xf3\x7e\x7f\xb0\x0f\xa1\x46\xf0\x15\xd3\x43\x80\x91\x8a\xa2\x9f\x95\xea\xe3\xc8\xd6\x50\x2a\x25\x45\x12\x94\xba\xb0\xae\x82\x50\x8e\x46\x1d\x5d\xa5\xb2\x0e\xe8\x35\x73\x64\xc6\x91\x2e\x08\xe6\x48\x41\x5e\xf6\x82\xf2\xb8\x2f\x42\x27\xf0\x11\x4f\x22\x79\x7c\x3c\x11\x1d\x63\xa9\x6b\x95\xe3\x19\x0c\xac\xce\xd1\x2a\xa9\xe8\x94\xca\x71\x52\xdf\x33\xcd\x35\x7e\x05\x7b\x1d\x88\x96\xf4\x52\x03\xea\x11\x70\x83\x33\x2e\xc7\x0d\xb9\x4c\x88\x1c\x1e\xd9\xba\xa5\xd0\x4f\xab\xb8\x75\xa9\x8e\x0a\x7d\x37\x3b\x69\x6b\xcd\xe2\xe1\x05\xd8\x39\xa8\xba\x64\x39\x97\xd7\x07\xe5\x8a\x2a\x5e\x6e\x88\xc3\x49\xd2\x2c\x4d\x8e\x47\x00\x6e\x07\x62\x2f\x98\x97\xeb\x9a\xfb\x94\xd8\xea\xdb\x57\x7b\x59\x24\x59\xd1\x73\x2b\x0a\x3d\x55\xf6\x07\xf0\x65\xee\x6a\xe3\x57\xc0\xb7\xd3\x82\xe6\x96\xaa\x0d\x49\xe1\x54\x11\x09\x52\x9b\x00\x89\x9e\x01\x09\xb9\xd1\x90\xc3\x52\xa2\x0f\x50\x88\xda\x39\x95\x62\x74\xf6\xb1\x9f\x33\x27\x0f\xea\x0d\x13\x01\x2e\xeb\x8c\xe8\x57\x39\x0b\xfc\x40\xc8\x41\x5e\xa2\xe3\x00\x47\xfa\xb6\x4c\xa9\x34\x11\x1b\xa9\x60\x96\xde\xba\x51\x7d\x48\x99\xd2\xb9\x70\x63\xd8\xf4\x30\xf0\xf9\x85\xd0\x00\xd5\x26\x2c\xf5\x9b\x2c\x47\x87\xfb\x38\x0a\x28\x97\xab\x60\x20\x45\x84\xa2\xef\xa0\xd6\x56\x9c\xc2\x31\x36\xca\x96\x72\x5c\x47\xd9\x26\xce\xc4\x0c\x5b\xc3\x0c\x7d\x5d\xca\x6f\xdb\x30\xb3\x78\xdf\x9f\x8b\x77\x77\x8f\xa9\x89\x1a\xb7\x1d\x3e\x0d\xbf\xa3\x0c\x33\xcd\x28\x5c\xec\x47\xb6\xe1\x57\x0e\xdc\x71\x25\x59\xcf\xc4\x63\x07\xd9\x7d\x5c\x14\xde\xfe\x24\x9a\x47\x19\xfd\x68\x12\x14\x37\xab\xc9\xb8\xc9\x9c\xcb\x32\x83\x02\x24\x8b\x63\x38\xca\x3c\x8a\xf6\xca\xcd\x62\x4e\x6a\x76\xcb\x2d\x38\x2e\xb1\x49\x4d\x53\xda\xe3\x82\xe9\xe4\xc1\x38\x2e\x37\x23\x5e\xe8\xb1\xda\xc2\x50\x2b\x6d\xe1\x37\x39\x03\xd5\xa6\x68\x43\x23\xf9\x3b\x0f\x9c\x08\xcf\xcb\x75\x31\x40\x26\x05\x68\x2e\x6e\xe2\x25\x6b\x5a\x72\x6a\xb3\x44\x0d\x1d\x5a\xca\xaa\x9d\x56\x81\x3a\x45\x6f\x00\xf5\xa9\x34\x39\xf1\x44\xc6\xb5\xf5\xfa\xdb\x7f\xbc\xe2\xb4\x8e\x0b\xdf\x9e\xb4\xe3\xcd\x39\x31\xf3\x05\xcf\xdd\xb5\x7a\xf3\x83\x45\x93\x2c\xfc\xe9\xe5\x8f\xff\x72\xf5\xab\xbf\xc4\xad\x78\xac\xdb\x34\x7a\xd6\xed\x83\x6b\xe7\x0e\x48\x4a\x6f\xe4\xbd\x4f\x5d\x7b\xd6\x8b\xc6\x9b\x8a\x16\xfa\x66\xdc\x84\xe7\x96\x5d\x69\x32\x4d\xa5\x1a\x53\xcc\xcb\xa6\x87\x61\xf6\xe8\x47\x6a\xbe\xe1\x34\xe6\x24\x7f\x32\x23\x30\x2a\x12\xd4\x4b\x07\x8e\x5c\x30\x51\x92\xf1\xb9\xa0\x9c\x1c\xb0\xc4\x25\x4f\x32\xe3\x82\x8a\xb2\x8b\x24\xb8\x3c\x85\x37\xfa\x5c\x3a\x61\xf0\x92\xdd\xe8\xd4\x82\xd9\xe2\xba\xa7\xab\xa2\xe0\xc5\x23\xfc\xfe\xa2\xde\x5a\xf4\x2f\x21\xc4\x5c\x09\x5c\xea\x6e\xd4\xa0\xe3\x52\xc7\x24\xa7\x73\xec\x95\xdd\x8e\x1c\x64\x3f\x6e\x07\x95\x10\x18\xd4\x5a\x42\x01\x49\xf2\x86\x1f\x15\xff\xcc\x91\xd9\x32\x4e\xf4\x23\x9b\x0a\x9a\x3d\x0f\x83\x6e\x4b\x3d\x3a\xa3\xa2\x6a\x4b\x43\x25\x81\xa4\x46\x9d\x40\x52\xe4\xe4\x05\x92\x74\xeb\xeb\x5b\x88\xe5\x01\x5d\x90\x73\x22\xf5\x9d\x5b\xf5\xdc\xaa\xac\x4e\x7b\x25\x88\xea\x49\x84\x03\xfb\xa9\xd6\xd0\x47\x31\x4b\x61\x3f\x6a\x8f\xbd\x56\x15\xd5\x69\x2c\x69\xb0\xd7\xf2\x1b\x2d\x2e\x8f\x3f\xc0\x12\xf7\xe6\x04\x68\x36\x22\x39\x56\x5d\x59\x5d\xa5\x82\x03\x53\x8c\x8a\x5e\x56\xe5\x99\xe2\xa6\x9e\xd7\x14\x56\x7a\x09\xaa\x18\xe6\x17\x59\xf5\xff\x42\xc5\x55\x90\x8e\x0b\xf1\x61\xc4\xa3\x1a\x34\xac\x12\xe3\x53\xa4\x12\x19\x5e\x6d\x91\x0c\x2f\xd8\x27\x25\x9b\x7e\xf1\x65\x74\x3e\xfb\x75\x07\x51\x81\x8e\xed\x9a\x52\x5e\xdb\x22\x67\x53\xb4\x80\x95\xea\xcd\xd8\x54\x77\x7c\x72\xbc\x58\x19\x39\xde\x46\x97\xa0\x69\xd1\x39\xa0\xb3\x6d\xd7\x14\xe9\x4e\xcc\xc8\xa4\xdb\x58\x19\x37\xcf\xac\xe2\xc6\x2a\xb0\x6e\x4d\xd0\xef\xcb\x40\x6d\x6f\x66\x80\x8f\x90\x44\x07\x3f\xab\xc0\xb6\x16\x49\x48\xf1\x54\x36\x48\x19\x40\x1a\x92\x05\x8e\xc2\x96\x72\x22\xae\x2a\x5f\x01\x1d\xd6\xec\x87\x1b\x57\x3b\xac\x44\x81\x82\xcb\x93\x4e\x53\x9c\x98\x8b\x4b\xa7\x65\x4b\x33\xaf\x3a\x60\x5f\x5c\x86\xc6\x3e\xe8\x42\xca\xc9\x99\x2c\xcc\xa4\xbc\x34\xb4\xb1\x69\xc8\x90\xa6\x96\x24\xbe\x67\x68\x63\xbf\x21\xa9\x96\x96\x64\xa5\xa3\xbd\x6a\xf1\xe2\x83\x94\x3f\xa4\xbd\x85\xfc\x3a\x68\x70\x3b\xd8\x82\x9e\xb1\x04\x3c\x88\xf5\x68\x10\x7a\xaa\x2f\x36\xb6\xba\x84\xd4\x92\xca\x56\x51\x83\x34\x27\x0b\xdc\x88\xad\x05\xe6\xbd\x20\x30\xef\x45\x7c\x25\x44\x4e\x71\x20\x72\x6a\xf0\xe7\xa4\x86\x84\x1c\x2f\x61\xeb\x4a\xe2\xb8\x1c\x21\xf6\xa9\xaa\x4b\xc3\x9c\xbf\xc0\x81\xc2\x8d\xe4\x4a\x53\x41\x0c\x11\xf4\xda\x4f\x48\x60\x79\x1c\x83\x95\x79\xc9\xea\xca\xf6\xaa\xe0\x31\xb7\x56\x34\x57\xc1\x77\xba\x20\xfa\x6f\x40\xad\xe8\x96\x8a\x4c\x7d\x52\x22\x95\x15\xa9\xa9\xfa\x25\x35\x45\x20\x3d\x8b\x17\x9d\xbe\x21\x77\xd4\x00\x7f\x4e\x1a\x50\x74\x9a\x14\xf9\xa7\x02\x2f\xc8\x35\x91\x74\x5a\x6a\xe4\x7b\x38\x57\xb4\x01\x88\xeb\x06\xf0\x02\x7d\x8f\x4f\xc8\xd9\xd7\x46\x3f\x12\xff\x71\x3c\x87\xd3\xac\x90\x79\x6c\xd0\xbe\xf4\x5f\x2f\x3a\x8e\xeb\x18\xef\x50\x0d\xf1\x5e\xe0\x97\x57\x89\x3f\x79\xe5\xa9\x12\x7b\x50\xff\x39\x04\x78\xd7\x66\x34\x18\x2d\xeb\x9b\xcd\x4f\x4a\xa6\xb2\x01\x6a\x94\x01\x49\x2c\xb5\x95\x51\x36\x86\x4b\x1d\x27\x01\x8e\xd3\xcf\x9f\x93\xfa\x25\xe4\x44\x89\xe3\xb4\x6b\x48\xd9\x68\x1d\x10\xcc\xf7\x08\x5c\x7d\x33\xb9\x50\x12\x05\xdf\x91\x1a\x4e\xe6\x42\x39\x81\xd1\xca\xbc\x47\xea\xc3\x66\x15\x58\xdf\x1e\xea\xc3\x64\x9a\xff\x4c\x44\x3c\xc4\xdc\x43\xd1\x3d\x15\xfc\x67\x40\x42\x1a\x92\xca\x36\x52\x53\x25\x93\x58\x1a\xa6\xf7\x1f\x72\xa1\xf6\xf3\x01\x01\x2e\xb9\x61\xda\xfc\x39\xa9\xad\xe8\x3f\xc3\x71\x5c\x8e\x69\x97\x8e\xd4\x0f\x32\xaf\x84\x90\xe5\xfc\x91\x5a\x17\x31\x51\x1b\x0f\x72\x5a\x82\x1c\xae\xea\xfb\xfd\xa8\xc1\x7e\x20\xe7\x31\x91\x9b\xb6\xa9\x2f\xf2\xa2\x32\x9f\xda\x77\x67\xdb\x8c\xd4\x90\xe9\xed\xf7\x9c\xb2\xac\x79\xf3\x80\x47\x4c\x27\x75\x2f\x99\x3a\x42\xb1\xb1\x1d\x43\xce\x8d\x85\x46\x3d\x7c\x76\xd7\x22\x65\x76\x9f\x77\x94\xc9\x8e\xbc\xf0\xc5\x75\xa2\xa5\x7d\xf9\x58\x22\x21\x0d\x4b\x65\xfb\x51\xc3\xb5\x25\xb1\x34\xa2\xe0\x63\x8d\xe0\x63\x03\xa8\x8f\x91\x9b\x67\x88\x3f\x27\x0d\x51\x89\x83\x4b\x1e\xac\x91\xe4\xa3\x6c\xa4\x74\xf3\x49\x3e\x2b\x70\x75\xb1\x10\xb1\xdc\x10\x41\x76\x55\xa7\xb5\xab\xa9\xe6\x24\x5f\xac\x93\x33\x65\x99\xa7\xcd\x38\xa1\x29\x7b\xfb\x1c\x77\xe6\x09\x2c\xa9\xbf\xbb\x82\x7d\xde\x5d\x31\xb8\xbb\xaa\xfb\xb8\xbb\x48\x6c\x5c\xeb\x03\xf1\xc2\x3e\xee\xae\x50\xe1\xc1\x6b\xac\xe5\x85\x1e\xce\x1b\x00\xb7\x1b\xc0\xcb\x7e\xdf\xf1\x02\x16\x31\xd6\x78\x92\x7e\x76\x74\xdf\xa0\xc7\x66\xfe\x75\xe0\xc9\xb9\x57\xb3\x78\xd5\x2f\x03\xaf\x28\xeb\x2a\xde\xe5\xc5\xbb\xab\x0a\xee\xae\x27\xfb\xf2\xab\x46\xb8\xbb\x6a\x2b\xdd\x5d\xd5\xe0\x57\xb1\x1f\x74\x77\xc1\xf7\x59\xdb\xa8\xde\x5d\x7e\x2e\x4c\xef\xae\x8c\x2b\x18\x4a\xab\x0e\x76\x92\x14\x95\xc7\x37\x5c\x99\x57\xad\xe9\xcb\x70\x15\x9c\x29\xdd\xb7\xdd\xa8\xf6\x85\x00\x73\x23\x61\x74\x8d\x36\xe3\x60\xa6\x65\x3c\xd9\x68\xcd\x65\x45\x2c\xd8\x1d\x71\x59\x2c\xaa\x99\xaa\xaa\x7f\x61\x3a\x77\xed\x52\xfb\x87\x22\xf9\x94\xcc\x96\x74\x5a\x0a\xf3\x19\xa3\x5d\xa0\x73\xd7\x62\x01\xe1\x67\x56\xa7\x31\xa1\x65\x01\xf0\x33\x18\xbc\x56\xe3\x74\x86\x8e\xb7\x77\x4c\x61\xbe\x31\x66\x9f\x1f\xbf\x72\xea\xa5\xab\xa6\x1d\xc2\x01\xe5\xf0\x67\xbb\xff\xfd\x2a\xf3\xe0\xbd\xb3\x97\x39\xf1\x81\x69\x5b\xdf\x8a\x0c\x5c\xd9\x54\xab\x7c\xa2\x1c\x56\x0e\x29\x3b\xb0\x6d\xfb\xe3\xab\xd7\x2c\x25\x69\x3e\xcd\xf5\xcd\x0c\x32\x41\xb6\x54\x8d\xfa\x69\xb3\x97\xc5\x7c\x3f\xa0\xe5\xfb\x92\x98\x90\x9a\x52\x59\x17\xf5\x81\x68\x52\x32\x27\x64\x8b\x99\xf2\xf0\xda\xf7\xca\x82\x2f\x27\x09\x74\xf4\xa1\xde\x4f\x89\x9c\x80\x6c\x26\x90\x96\x6a\xf8\x0c\x83\x01\x7f\x5d\x2f\xc8\xc6\x20\x6c\x91\x24\xd4\xe1\x92\x92\x41\x69\x0c\xe3\x81\xaa\x81\xfe\x7d\x2a\x56\x10\xba\xf5\x41\xcc\x10\x5a\x43\x78\x56\x3b\xca\x42\x31\x61\x7a\x31\x80\x39\xca\x43\x35\x81\x99\x5c\x3c\x44\xa3\x5a\x57\x90\x60\x1e\xa0\x1f\x6a\x43\xa3\xd1\x07\xfa\xda\x42\x4d\x49\x6d\x21\xa6\xd5\x16\xa4\x54\x42\x1a\x99\xca\x0e\xa4\x56\x48\x27\x81\xcf\x8f\x58\xe1\x14\xfd\xcc\x40\x7f\x1c\x97\x07\xf9\x40\x13\x26\x5a\xa8\x3e\xf4\x0c\xe7\xa3\xe6\xb8\xdc\xee\xcf\x49\xed\x09\x79\xb8\x5f\x5f\x8e\x38\x15\xc7\xe5\xfe\x61\x5e\x90\x1b\x9b\xd2\x69\x69\x10\x2f\xd7\x04\xd2\x69\xa9\x5d\x90\x9d\xa6\x74\x5a\x8a\xf2\x72\x7a\x64\x3a\x2d\x0f\x47\x14\xe8\xc7\xf3\x72\x73\x3f\x48\xdf\x3c\xbc\x90\x41\x20\x90\x26\x9b\x18\x3a\x3c\xea\xe4\x4f\x54\x9d\xe8\x28\x16\x24\xf8\xe3\x84\x8e\x7d\x14\x2b\x5e\x51\x2b\x14\x7d\x44\x92\x15\xeb\x16\x4f\x68\xb5\x0a\xc3\xdd\x15\xc2\x4a\x43\x89\x1f\x92\xb8\xf2\xdc\x72\x2f\xb4\x17\xbc\x50\x2d\x2e\x6b\xce\x57\x03\xfd\x3f\xad\x9c\x4c\xe2\xc6\x0c\x66\xe8\x90\x0d\xa6\x40\xd9\x52\x1f\xc3\xe0\x57\x6c\x9f\x7e\xf5\x17\xea\x4e\x0d\x9d\x03\x07\x0d\x19\xda\x32\xb0\x53\xef\x4e\x87\xff\x43\xdd\x68\xe6\xf0\xf6\xce\xb6\xf6\xce\x21\xf4\x0e\xa5\x7e\x94\x29\xf8\xd1\xba\x72\x2f\x1a\xc8\xa0\xb8\x9c\x32\x54\x76\x27\xcd\x7d\xda\x7b\xb9\x8f\xb3\xcc\x7d\x74\xde\xd2\xa1\x7a\x4b\x4f\xa0\xa6\xb1\x89\x84\xc6\x51\x50\x99\xb7\x41\x7d\xd5\xc3\x43\xe9\x4a\xf8\x7f\xe5\x22\x27\x74\x0b\xe5\xa7\x9a\xf1\x4e\xe4\x0c\xf7\x2e\x5e\xfc\x89\xce\x96\xec\x31\x05\x21\x6e\x31\xb7\x0d\xb9\x90\x07\xf9\xb5\xe9\x15\x09\xa5\x64\x0b\x5b\x24\x18\x93\x84\x64\xd6\xe9\xb6\x13\x87\x70\xb2\xb9\xac\xd1\x6c\x57\xe9\xc6\x80\x74\xd1\x4c\x07\x23\xec\x7b\x25\xbe\x28\x63\x01\x68\x02\x0b\x03\x0d\x61\x3a\x14\x0b\xc4\x4e\x83\x5a\x63\x58\x27\xa1\xca\x47\x59\x1c\xe5\x63\x6c\x5b\x54\x64\x98\x4d\xec\xa7\xf9\xd7\x99\x50\xfe\x4f\xcc\xe8\xbc\x49\x41\xbf\xc7\x31\xbc\xe5\xf6\x4b\x98\x49\xc0\x3a\xb6\x2a\xff\xef\xd5\xc4\x2b\x98\x29\xcc\x8b\x38\xb8\x78\xb1\xea\x07\xdc\x6c\xe3\x54\xd4\x8c\x52\xa8\x03\x8d\x40\x32\xca\x34\x92\xd5\x47\x53\xf2\x00\x73\x4e\x0a\x25\x01\xaf\x21\x79\x52\xc4\x05\xa4\xe1\xc9\x2c\xd3\xda\xe8\x50\xbd\x60\x48\x52\x1a\x9c\x90\xdb\xc8\xda\x47\x82\x23\xf4\x13\xb5\xf0\x96\x9c\x3e\x49\x96\x86\x24\x49\xbe\x94\x26\x19\xb5\x2f\x27\x8f\x22\x21\x30\x79\x3b\x2c\xd6\x74\x5a\x4a\xf0\x59\x47\xa3\x69\x30\x28\x73\x05\x04\xd9\x1d\x4b\xa7\xa5\x34\x9f\xf5\x84\xa2\xed\x1d\xe4\x67\x3e\x41\xae\x86\x70\xad\x15\x34\xa5\xfc\x30\x65\x01\xde\x50\x60\x67\xb0\xea\xfd\x41\x75\x87\xbe\x34\x55\xf5\xde\x41\x92\x75\x96\xca\xaa\x4e\xc4\xdf\x6d\x9e\x7e\xcb\xfc\xb5\x43\xce\x78\xff\xda\x7b\x9f\x8f\xb7\xbf\x78\xd3\x3b\xb9\xfc\x29\x66\xdc\x36\xfe\xc9\x89\xe3\x97\x5f\xa3\x7c\x3a\xeb\x82\x77\x1f\xec\xde\xfc\xca\x94\x71\x0b\x9e\x7b\x42\x7e\x0e\xc7\x99\x49\x9f\xe2\xa3\xb3\x6e\xbd\xfd\x41\xea\x27\xa7\xff\xec\xb6\x8b\xe6\x36\xb7\x5f\x78\xd9\xc5\x97\x29\xdf\x7e\x7a\xa3\x32\x3b\x1a\x5f\xd9\x54\xfb\xe7\xbb\xae\xfb\xc5\xf2\x09\xe3\xa8\xc7\xb0\x43\x16\x2f\xce\x6f\x5e\xbe\xfa\x59\x95\xf7\xe1\x35\xe3\xfb\x28\x86\x96\xd0\x2e\x29\xd4\xf8\x0c\x1a\xf6\xcd\xe3\x8d\x1a\x1c\x71\x29\x94\x92\x3d\xe6\x9c\x54\x95\xcc\xfa\x03\xe4\x07\xb2\x9f\x2d\xcc\x6f\xa8\xb4\x3f\x3c\x8e\x4b\x62\x52\xae\x11\x73\x52\x30\x99\xa9\x01\xb8\x40\x4d\x95\x25\x9e\xe1\x6b\x00\x47\xe0\xb1\x90\xbf\xfa\x2d\x71\x18\xef\xe0\xed\x80\xc0\x88\xa6\x41\xaa\x52\x36\x01\x86\x2e\xe0\xe7\x05\xd9\x8e\xa0\xbc\x43\x21\xe3\x94\x02\x42\x47\xfb\x40\x11\x07\x6d\x51\x18\xbb\x2e\xd2\x3f\xfc\xf5\xbd\x52\xde\x87\x8f\xf1\x40\xe5\x75\xfc\xfd\x9c\x39\x25\xec\x0f\xe3\x74\xac\x0f\x8b\x97\x2c\xea\x56\x76\x2d\x51\x0e\x01\xf3\x03\xcc\xb5\x19\x36\x18\x26\x42\x36\xf5\x82\x8a\xb0\x69\x30\xe7\xa0\x75\x41\x4b\x84\x03\x2c\xc0\x31\x22\x82\xc2\xba\xe4\x48\xc9\x41\x15\x3d\x49\xbb\x18\x31\x31\x27\xc5\xe8\x14\x26\xd7\x9c\x84\x01\xf2\x8c\x05\xd8\x19\x2d\x0e\x4b\x3c\x13\x06\x78\x57\x38\x40\x87\x18\x4c\x6e\x20\x5a\x19\x44\x82\x38\xa4\x25\x59\x61\x7e\x94\xc5\xc8\xba\x45\x7f\x4d\x6d\xc3\x00\x48\xd5\x4d\xea\x70\x7c\x40\x84\x2e\xaa\x3c\xa0\x81\x17\xb2\x88\x33\xd6\x54\xab\x93\x80\xd0\x51\xee\x00\xde\x05\x31\xc6\x45\x29\x82\xb5\x23\xda\x16\xed\x68\xeb\xa0\x0d\x66\x77\xb4\xc8\x48\xf4\xf5\x6f\x3e\x9b\x69\x0b\x2c\x32\xdc\xba\xf4\x0a\x65\xf9\x37\x2b\x56\xfd\xeb\xe9\x0b\x95\xdd\xf8\x7a\x03\x67\xbe\xf1\xab\x7d\x7f\xdb\x8a\x1b\x7e\xb1\x64\xf9\xba\x05\x8f\x31\x03\xb1\x09\xf7\x5f\xb3\xe4\x48\x77\x73\xfd\x92\xa3\x63\xd6\x8c\xbb\x66\x49\xe7\xa8\xb9\x6b\x70\x1d\xb6\x28\x53\x5e\x7a\x23\xfa\xfb\x5f\xed\x29\xcc\x40\x1a\x87\x99\x66\xa0\x30\x6a\x46\x77\xab\xc8\xc9\x32\xef\x09\x12\x67\xf1\xb0\x39\x8d\x90\xbd\xe8\x2c\x50\x3f\xe7\x7d\x9a\x6f\xc0\x6d\x4d\xbc\x62\xa3\xc1\x12\xac\xaa\x83\xf6\x81\x8f\xef\x31\x71\xb1\x7a\x28\x22\xbb\x28\xbe\x52\xf6\x7a\x4a\x7c\x44\x32\xa8\x84\xe4\xbd\x3c\xa5\x48\x10\x52\xd2\x4d\xaf\xe8\x2e\x45\x9a\x10\x7c\x8f\xae\xb2\xd9\xcb\x69\x0a\x54\x21\xc6\xcf\x8b\x95\x40\x16\x7c\xa7\x93\x8b\x82\x1d\xda\xd0\x7c\xd5\x12\x03\x4a\xbc\x27\x05\x73\xd0\x14\x59\xd6\xae\xbf\x9c\xbc\xc4\x61\x12\xd4\x61\x74\xae\xd1\xa1\x5e\x4d\x3d\x4e\x95\x6f\xdf\xcb\x8f\xb2\x1b\x59\x3b\xef\x0f\xd6\xd4\x35\x36\x0d\x48\x69\x0e\x22\xc7\xea\xc9\xb7\x13\xe4\xe1\x99\x96\x53\x76\xd0\xbb\x33\xfa\xca\x3d\xa4\x20\x66\xd6\x89\x55\xd7\xa8\xd4\x5d\xa1\x8e\xf2\x8f\x0f\xc1\x51\xfe\x7e\x94\x38\xc9\x82\xe7\x88\x7f\x7c\xf2\xf7\x17\x8b\x96\x91\x96\x2e\x59\xf3\xf8\xf2\x75\xf3\x1e\x67\x62\xd8\x82\x93\xc4\x55\x0e\x7e\x3d\x66\xcd\xb8\xee\xc5\xf1\xb9\xcf\xe3\x7e\x86\x7f\x14\x8b\xd5\x7f\xfc\x60\x6f\xcf\xbb\xf1\xdf\xff\xea\x80\xca\x79\xf9\x9d\xaa\x73\x3b\xb4\x54\xe5\x16\xb0\x4e\x21\x1d\xe5\x22\x7c\x48\x05\x39\x5b\x95\xae\x8d\xb5\x6a\xec\x15\x1d\x1a\x0f\x44\x49\x67\x63\xc7\xe6\xbb\x19\xcb\xbe\xfc\xab\xcc\x25\xfb\xf3\xdf\x3f\x96\xd0\x63\x47\xf2\x89\xf9\xcc\x98\xfc\x9c\xa3\x3b\x98\xad\x73\xf2\x3b\xf5\xd8\x18\x86\xf2\x56\x98\x9e\x42\x2e\x54\xa5\xf1\xf0\x4a\xb6\x14\x00\xa6\xa1\xfd\xae\x82\x7e\x81\x26\xa5\x80\xfb\xcd\x18\xdd\x94\xdf\xc9\x0c\x70\x5a\x87\xb6\x32\x3d\x49\x45\xc9\xe2\x36\x64\xca\xb8\x2a\x2e\x29\xae\x8f\xf3\x1e\xfd\xb8\x94\xaf\xc2\x34\xbb\xb4\x7f\x31\x4b\xe9\x54\xe7\xd9\xfd\xa8\x09\xdd\xa5\xeb\xc7\x90\xdf\x64\x43\xaa\xcc\xa2\xda\x9b\x21\x01\x51\x94\x2b\x60\x77\xd4\x16\x4d\x00\xc7\xe5\x1a\x1e\xd4\x3d\xb4\x6e\x4d\x3f\x75\xb6\xba\x87\x75\x89\x16\x55\xb2\x35\x14\x8e\x35\xc2\x37\x67\x89\xf2\x42\x26\x50\x03\x1a\x69\x27\xd1\xc4\x29\xa7\xbd\xef\xbb\x8f\x83\xaf\xd0\xab\x01\x9c\xa0\x93\x73\x04\x95\xf2\xe1\x93\xef\xad\xd3\x30\xc5\x30\x11\x74\xf4\x9b\xd0\xcf\x50\xa9\x09\x54\x21\xfd\x32\x13\xa8\x7a\xfa\x3a\x13\xa8\x7a\xfa\x05\x13\xc8\x3e\x0b\xc4\x7d\x1b\xdd\x6c\xc1\x02\xd1\x46\x5e\x90\xea\x41\x4a\x4e\xb5\x83\x2f\xc4\x0b\x19\x0e\x69\x34\x70\x7d\x48\xe9\x97\x59\xa2\xb2\x8c\xfe\x7a\xbd\x11\xfa\x50\xd0\x3f\xd2\x51\xb2\x79\x03\xf5\x03\x6e\x1b\xf8\x41\x18\xc5\xd1\xc2\x72\x4f\xa8\x29\xf3\x84\xfe\x09\xb9\x81\x23\x4f\x16\x79\xaf\xb0\x34\x40\xef\x10\x55\x38\x2e\xd7\xf1\x39\xa9\xae\xe8\x10\x03\x71\x5c\xae\xb2\xf3\x82\x1c\x08\xa6\xd3\x52\x1d\x5f\x74\x0c\x61\x63\x28\x5c\x13\x69\xa2\x6a\xbe\x96\x06\x5e\xc8\x54\xd5\x35\x9d\xa4\x6b\x40\xce\x70\xd2\xee\x21\x33\x93\x94\xf3\x7f\x80\x87\x30\x03\x17\x2f\x3e\xf4\xb1\xde\x50\x06\xea\x23\xc6\xa9\xe0\x23\xc4\x4e\xf7\xa3\x52\xf3\x68\x5e\x52\xd1\x3c\xaa\xb3\xe8\xcc\xa3\x39\x0b\x98\xc7\x51\x34\x8f\xea\x34\xc2\xcb\xc4\x69\x2a\x5a\xc7\x57\x73\x32\x0e\x53\xc1\x3e\x95\x9d\xc6\xcd\x4c\x52\x86\x9f\x84\xe3\x60\x61\xf1\xe2\xc3\x0d\x7a\x9b\x30\x14\xc3\x6d\x9a\x01\x18\x80\x4b\x4f\x34\x99\xd1\x5c\x98\xcc\xe8\xa7\x4e\x66\xf4\xb8\xf9\x3a\x3a\x58\xfc\x3f\x1e\xce\x28\xb9\x10\xfb\x9e\xd4\xd0\x51\x76\x57\x1c\xda\xd0\x4b\x87\x22\x06\x55\x2b\x5e\x76\x13\x17\x45\x41\xd4\x88\x2e\x44\x45\x40\xb7\x1f\x18\xd8\x80\x5b\xc7\xb8\x57\xf6\x38\x72\x19\x23\x0c\x2d\x1a\x2d\x16\xa0\xd9\x91\x3d\x46\x78\x60\xa3\x74\xb4\x98\x51\x67\x86\xec\x7c\x06\xb9\x61\x18\xc2\x21\xe8\xf8\xd6\x74\xbb\xf1\x19\x44\x2f\x0c\x0c\x95\xbc\xa1\xd5\x2f\x7f\xb0\xfa\x8d\x3d\xbf\xbe\x03\xbf\x91\x5f\xc8\x8e\x51\x46\xfe\x37\x76\x3c\xf0\xfd\x33\x7f\x5f\xf0\x93\xe2\x6e\x8e\xa1\x71\x5b\x56\x3c\xbd\x6e\x16\xfe\xc7\xf2\x39\x8a\xdd\x7d\x68\xe7\x23\x7f\xbc\xeb\x4c\xd3\x8b\xfa\xab\x1e\x31\xc7\x16\x29\x5e\xe8\xef\x3b\x50\x08\xb5\x21\x40\x3a\x4b\x36\x75\x2f\x61\xd8\x8b\xd9\x41\x07\x66\xcc\x46\x40\x9a\x22\x99\xb1\xf1\x82\xe4\x48\x4b\x5c\x09\x95\x9d\xfa\xec\x97\xac\x72\x7a\x01\xd8\xa2\x83\x0c\x96\x00\x59\xf6\xeb\x63\x1b\xc0\xc5\x1a\x37\xa9\xb8\xd1\x13\xa3\x62\xc3\x95\xc0\xa2\x55\xff\x33\x54\xec\x89\x80\xb0\xc7\x01\xbf\x52\xec\x16\x42\x96\xae\xc2\xda\xcf\x3b\x79\xc4\x6b\xdf\x9b\x28\x20\x5e\x7f\xf8\xc2\x75\xb0\xd6\xe3\x40\x59\x55\xac\x82\xf9\x72\xc0\x6e\xd7\xa2\xfe\x3f\x10\xbd\x1a\x3f\x21\x7a\x75\xc0\xff\x6b\xf4\xea\x49\x01\x56\x4f\x0e\xa4\x5a\x9e\x67\x34\x90\xc8\xe7\xf8\x79\x46\xe3\x09\xf2\x8c\x26\x35\xcf\xc8\x92\x3c\x23\x4a\xd3\x8c\x8c\x89\xab\x83\x58\xee\x7f\x95\x65\x68\x3a\x14\x27\x48\x31\x98\xa9\xaa\x36\xc5\x71\xf2\x0b\x43\x4f\x51\xa4\xbe\x34\xbf\x48\x16\x2c\x10\x29\xc9\x2f\x1a\x75\xf9\x05\xc5\x6d\x55\x89\x00\x28\x80\xfc\xa2\xae\x57\x7e\x31\x98\x3c\x64\x05\xe8\xa5\x97\x1f\x65\xa5\xc9\x45\xa4\xb1\x1f\xd5\x8c\xd6\x12\x8a\xc6\x93\x4f\x28\xf4\xee\x50\x94\xbd\xaa\x9c\x4d\x6c\xd5\x52\x88\xd5\x9a\x35\x2a\xa6\x12\xd8\xae\xe5\x0f\xf8\x6f\x3a\xdd\x7e\x8c\x76\x1c\xfb\x9a\xdb\x69\xdc\x84\x82\xe8\x32\x15\x3b\x0b\x0c\xc0\x56\xad\x05\x65\x4c\x41\xa1\x30\xcb\x06\x3c\x4e\x8d\xd2\x9d\xe6\x17\x41\x4a\xe9\x1e\x04\xd8\x85\x64\x48\xca\x26\x31\x27\x99\x28\x2d\x8d\x5b\x54\xe5\x92\x4d\x90\x70\x23\x15\xfc\x5b\xd2\x6a\xa2\xc3\xe0\x51\x7e\xc7\x66\x66\xe2\x96\x89\x93\x2e\xbd\x62\xcb\xaf\x7a\x36\xbc\x95\x5f\x6d\xdc\x94\x5f\xc6\x4c\x3d\xf2\xe4\x65\xd7\x5c\x3b\x91\x39\x94\x37\x3f\xff\xfa\xb6\x17\xf1\xb8\xfc\x38\xea\xc3\x3b\x14\xaf\x61\xbf\x71\x17\xcc\xb2\x5c\x48\x27\x99\x29\x97\x32\x89\xd1\x74\x23\x2c\x22\x1d\x61\x71\x17\x46\x58\xac\xfa\x11\x16\x96\x04\xe8\x2a\x47\x96\x48\xb2\x43\xd6\x60\x75\x69\x64\x65\x14\xed\x28\x88\x6e\x64\x0c\xe2\x7a\xa4\x42\x1e\x77\x2c\x8e\x58\xcf\x79\xff\xfe\x8f\xfe\xaa\x9c\xad\x5c\x8a\xbb\xf0\xf8\xe5\x0b\xb7\x6f\x53\xbc\xa6\xee\x77\xa7\x4f\x55\x0e\x1f\x54\x36\x29\xdc\x2f\x94\x66\xe6\xe7\xf3\xf0\x8b\xd8\xb1\x66\xc3\x97\xdf\xaa\xeb\x45\xc8\x38\xd6\x34\x03\x79\x50\x35\xba\xb8\x17\xea\x55\x83\x24\x97\xe2\x5b\xa1\x78\xac\xc7\xf3\xf6\x30\x0e\x6f\x90\x7c\x62\x76\x6d\x4c\x12\xd2\xb8\xbe\xe1\xbb\xb4\xd1\x29\xc6\x5a\x70\x2f\xa0\xea\x1d\xfb\x6a\x6f\x4b\xcc\x3c\xbb\xa7\x32\x36\xd5\x34\x51\x3c\xe5\xe5\xf6\xe0\xf0\xd7\x91\x9a\xcf\x9d\xa3\x6a\xc4\x5d\x5c\x8a\x46\x2d\x40\x51\x35\x60\x54\x05\x46\xb2\xda\x12\xa8\x69\x8f\xc1\x24\x86\xe0\x8b\x38\x11\x29\x59\x71\xf1\xa5\x58\x52\x9b\xba\xf2\x5e\xf0\x51\xce\xae\x2d\x9a\xd6\xee\x23\xa6\x17\x11\x0f\xf8\x99\x16\xcd\xab\x25\x47\x4a\x72\x27\x64\x81\x85\x31\x49\xce\x48\x41\xb3\xec\x5e\x39\x18\x00\xba\x0f\x40\x7f\x07\x28\x3c\x16\x14\xeb\x70\x5a\x8a\xf0\x59\x1f\xd7\x00\x9f\xb1\x64\x21\x91\x19\x92\xeb\x04\x5e\xd8\xc8\x5a\xec\x18\x26\xda\x07\xb5\xb6\xe2\xc6\x36\xad\x18\x6d\xa2\x55\xfd\x28\xdb\xd8\xc4\x99\x58\x1d\x29\x4f\x47\xe1\x13\x66\xdc\x57\xdd\x71\xed\xb5\xf7\xb4\x0f\x64\xf8\xd7\xd7\xe6\xbb\x57\x7d\x8e\xff\xbc\x3e\x9c\x88\x34\x0f\x1c\xd6\x91\x1a\x35\x2a\xd5\x3a\x5a\x48\x5f\xee\xdb\x5f\x23\x8f\x34\x7c\xda\x3e\x67\xf2\xed\x77\x5c\x3e\x7a\x62\xe8\x48\x14\x3f\xa4\xdc\xce\x0c\xc4\x6b\x3b\x97\x5c\x37\x05\xbf\xd3\xde\x39\x6c\x48\xc7\xb0\x61\x9f\x08\xa7\x2e\x68\x72\xf7\xef\xee\xaf\xf5\x8e\x4c\x2f\x42\xcd\xbf\x15\x75\xa2\x33\xd0\x9b\x27\xd3\x3b\x4a\x24\xe4\x36\x63\x4e\x1a\x96\x90\xfb\x11\x7b\x9c\xa9\xaf\xf9\x37\xe2\xb8\x9c\x0c\xe4\xa4\x64\x49\xcb\x68\x00\xb4\x8c\x86\x04\x72\xd2\x10\xaa\x7d\x5b\x6c\x02\x9c\x45\xfe\x85\x46\xda\x61\x1b\xc2\xbf\xec\xac\x31\x25\xfa\x8d\x38\xe5\x0c\xe8\x35\x0b\x92\x98\xa6\xc4\x94\xb6\x53\x8f\xdb\x04\x90\x87\xb5\xf1\x82\x3c\xa0\x31\x7d\xd2\xed\x80\xbe\xb4\x20\xc1\xe6\x51\x62\xf3\x13\x34\x08\xce\xbb\x63\x0a\xa8\x44\xce\x9c\x56\x10\xcd\x6c\x99\xea\xc3\x76\xb1\xfb\xde\x13\xf5\x0b\xf8\x2b\x6e\xbb\xed\xf2\xab\x6f\xbb\xed\x4a\x55\x3b\xf2\x1f\xee\xfe\x77\x44\xec\x81\x9f\x9e\x56\xe8\x1d\x98\x66\x40\xef\xa0\x1a\x5d\xfb\x03\x7b\x07\x70\x2f\x9c\xb0\x69\x00\x4e\x6b\xe7\x85\x8c\x57\x54\x05\x61\x2b\x35\x10\x8a\x2f\x48\x1f\x6d\x84\x4d\xea\xcb\x51\xa1\x97\xa0\x7b\x2a\xb4\x9e\x02\x17\x85\x9e\x42\x27\x3a\x0d\xf5\x1c\xb7\xa7\x70\x4a\x49\x4f\x61\x44\x12\x4b\xa7\xf7\xd1\x4c\x18\x01\xcd\x84\x91\x6a\x33\x61\x4c\x59\x33\x21\xe3\x68\x34\x91\x24\x22\x20\x64\xdd\xb1\xc1\x6d\x9d\xc4\xa5\x46\xf2\x1b\x3d\xa1\xe8\x90\xf4\xd0\x92\x7e\x02\xa0\x44\x6a\xd2\x52\x2b\xff\x7f\xdd\x55\xd0\x2c\xe8\xf9\x9f\xf5\x16\xfe\xa5\x5a\xf8\x94\x1f\xdc\x60\xd0\x0e\x80\xb6\x19\x90\x01\xcd\x3a\xb6\xdd\xf8\x16\xbc\x27\x61\x14\xa3\x7c\x64\x80\xaf\xae\xd1\x10\xc5\x41\xb6\x80\x8a\x54\xc9\xd5\xa3\xe4\xf5\xf3\x53\xfc\x23\x30\xab\xf3\x02\x74\x71\x5f\xe6\x58\xb7\xc3\x5f\x55\xdf\x8f\x18\xd1\x2a\xc8\x66\x78\x0e\x6b\x48\x56\xee\xe2\x61\x6e\x64\xa3\x19\x09\x56\x1f\x31\xa4\xc4\x0a\xb2\xd1\xa4\x95\x26\x92\xfe\x0e\x3f\xa5\xca\xab\x6b\x32\x35\x75\x34\x7a\xdc\x7e\xdc\x48\x22\x17\x1f\x54\x2a\x9a\x74\x31\x1c\xbe\x1c\x9f\xf1\xc1\xaa\xcb\xef\x9a\xb2\x5d\x79\x5a\xd9\xfe\x97\xa5\x93\x67\x4d\xcd\xbe\x79\x05\xb3\x70\xda\xd3\x5f\xff\x7b\xe7\xcd\x2f\xfc\xf7\x77\x53\x14\x4e\x8b\x5c\xa0\x3c\x31\x61\xee\x45\x4b\xde\x57\x96\x29\xcf\x2a\x37\x4c\x9a\xff\xa3\xe5\xef\xe2\x69\x4a\x7e\x09\xbb\xe2\x4c\xe5\xe3\xa3\x07\xc6\x42\xad\xc2\xbc\x0c\x4b\x3a\xc7\x34\xa0\xe9\xc7\xb6\x01\x26\xd9\x83\x42\xa8\x0e\x0d\x40\xd7\xab\x36\x29\xa0\x92\x83\x96\x82\x5e\xad\x1a\xd1\xd7\xaa\x11\x41\x8b\x6a\x13\xc9\x9d\x96\x6a\xf9\x97\x8d\x0e\x17\xeb\x0f\xc7\x9a\xa9\x45\x20\x98\xaf\x2e\xb1\x87\x55\x40\xbe\xba\x72\x7b\xa4\xa8\x3d\x80\x43\x8f\xda\xc3\x4b\xec\x51\xab\xe6\xbb\x3a\x73\x4c\xc7\xf6\x6f\x1f\xbf\xf5\xfc\x99\x97\xcd\x56\xbe\xf9\xe6\xf1\xe9\x17\xdc\x36\x61\xce\xd6\x56\xfc\xd6\x59\xd7\x2b\xdb\x17\x9f\x7e\xfd\xd3\xdd\x09\x65\x82\x66\x0c\xa8\x47\x74\xcd\x18\x3b\x7b\xc5\xbf\x95\x7f\x2a\x1f\x9d\x3a\xe3\xfc\x7b\x9e\xc2\x68\xcd\x24\xe6\xe6\xc1\x47\x73\x89\x7d\xbb\x97\x5f\x85\x37\x15\xac\xa0\xf6\xac\x4d\x33\x90\x09\xf1\xc8\x8f\xa2\xda\x24\x54\xb1\x67\x2d\x14\x27\x25\xe8\xb0\xbc\xd5\x9f\x93\xac\x05\x4d\x57\x80\xb1\x59\x2d\xbc\x00\x3d\x24\x29\xa8\x8a\x66\x87\x84\x2c\x83\x9d\xa2\x03\x1e\x6e\x2c\x00\x10\xa6\xd0\xc2\xb6\xe1\xc2\x4b\x4d\x01\x12\x6c\xe1\xef\x8b\x6d\x6c\x66\x47\xd5\x95\xad\xd7\x8c\x7e\x69\x17\x6d\x65\xc7\xdf\x25\x7f\x3b\x5c\x2a\x74\xb2\x27\x8a\x9d\x1b\x4e\x0b\x0e\xfe\xd5\x91\xd1\xd0\xce\x66\x87\xc1\xdf\x0f\xda\x51\xe8\x65\x47\x51\x08\xd5\xa3\x04\x4a\xa3\x67\xf5\xaf\x5a\x73\xc9\xab\x36\xb0\x38\x6d\x31\x14\xce\xb9\x81\x44\xed\xb5\x7b\x79\xb9\xda\x9f\x93\x1a\xdc\x72\x2b\x79\x9f\xfc\xf0\xa0\xc5\x2b\x35\xb1\x87\xe1\xb8\x5c\x5d\xa5\x92\xbf\x4a\xad\xbc\x1c\xa8\x4b\xa7\xa5\xa4\x90\x75\x9a\xa2\xcd\x80\x8e\x8e\xf3\x52\x07\x7d\xc6\xa4\xb6\xff\xd9\x10\x86\x66\x2b\xdd\xf3\x55\xf8\x61\x1f\xcf\x94\xa8\x5a\xef\x7e\xf5\xb9\x7a\x4b\x35\x5f\x1f\x03\x19\xb7\x69\xc6\xbc\xa4\xf0\x4a\x5d\xa7\xd9\x53\x9b\xa5\x19\x81\x4c\x48\x44\x61\x74\x4b\xb9\x87\xf8\x0a\xa8\x06\x21\x21\xdb\xcc\x05\xce\x01\xb3\x25\x2e\x39\x93\x80\x1c\x32\xef\xa5\xca\xf7\x6e\xd9\x45\x42\xe9\x80\x0a\x1b\x32\xf3\x42\x86\xb3\xf8\xd2\xc0\x93\xda\x83\x19\x1b\x04\xab\x4e\x21\xe3\x30\xfa\x29\xf8\xc1\x07\x25\x21\x1d\xf8\x81\x5e\xbe\x31\x0a\x22\x2a\x1f\xca\x59\x66\x5b\xbf\x60\xe1\x73\x96\x1b\x2c\x17\x4f\xbf\x76\x92\x39\x54\x3a\x97\xc3\xc5\x67\x2f\x99\xf7\xd0\x59\x43\x46\x8d\x3e\xda\xa9\x8e\xe5\x68\x73\x39\xc6\x83\x28\x04\xaf\x53\x89\xa7\x0c\x28\xf1\x94\xd6\x42\xfc\xd3\x90\x80\xd0\xa8\x01\xfa\xaa\x0d\x61\x4b\x5c\x8a\x26\xb1\x34\x58\x7b\xa4\x7a\xc2\xfd\x90\x39\x2e\x37\x07\xe0\xb9\xaa\xc3\x71\x99\x4d\x24\xa9\xc8\xbf\x87\x38\x96\xe0\xca\xc9\x6d\x38\x2e\x37\xf7\xe3\x05\xa9\x2a\x0d\x01\x7b\xc6\xe6\x04\x4d\xa3\x28\x2f\xd5\xa6\x91\xdc\xfa\x3f\x42\x3b\x94\xd9\xe6\x84\xf3\x3a\x2f\x97\x58\xeb\xfa\xe3\x8e\xec\x18\x4e\x2d\x18\x6f\x5c\x61\x62\x87\xd8\x6f\x15\x42\xec\x21\xd0\x2e\x14\x51\x04\xdd\xaa\x2a\xd5\x78\x34\xf5\x0e\x12\x9e\xb8\x04\xab\xcd\x01\x3c\x3c\x30\x14\x6a\xdd\x0b\xdc\x89\xce\x64\xc6\x03\xbc\x0e\x1e\xd1\x12\x97\xec\x49\x95\xd9\xcc\xe3\x96\x18\x62\x25\xec\xcf\x49\x38\x21\x33\x7e\x48\x70\xfc\x38\x2e\x07\xfc\x74\x58\xd4\xef\x01\x5a\x23\x29\xc0\xcb\x9c\x51\x9b\xec\xd1\x3e\x91\x62\x0c\x23\x16\x2f\x99\x55\xea\xc7\xc0\x81\x92\xc4\x45\xf9\xf5\xcc\x4c\x85\x57\x3f\x88\xc2\x3d\x72\x68\x7f\x21\x8e\x51\x7f\x06\x77\xc9\xf4\x63\x07\x0d\x61\x35\x97\x69\x40\x89\x82\x6a\x9e\x4d\x53\x7b\x8a\x99\x73\xd9\x88\x19\x24\xf3\x22\xe6\x1c\x96\x06\x81\x1f\x98\x81\x1d\x52\xf2\x91\xad\xf8\xfd\x39\xc9\x4c\xd9\x3c\xd5\xc9\x82\x5a\x95\x95\x94\x5c\x2e\x4d\x7e\x70\x03\xa9\x99\xdf\x68\x13\xd8\x30\xc5\xa8\xd6\x0a\xd2\xc0\x34\x92\x6d\x82\x8e\x7d\x4e\x8a\xa8\xda\x3d\xe4\xe1\x20\x91\x07\x45\xcd\x01\x87\x0d\xd2\x99\x80\x02\xec\x8a\x3f\x98\x8e\xb9\xcf\x76\xff\x3b\xef\x2e\x60\xeb\xfe\xa3\xfc\xb9\x4e\xb5\xc8\x9d\x4c\x82\x99\x77\xf7\xec\x65\xaf\xab\xd6\x60\xaa\xb1\x19\xa7\x95\x7f\xfd\xd7\xb4\x57\xde\x04\xb8\x1d\x8e\x1b\xfe\xa5\x1a\xe8\xe8\xb6\x27\x57\xad\x61\xfe\xac\x99\x86\xe6\xa8\xec\x21\xd3\x08\x64\x43\x41\xf4\x88\x3a\x15\xac\x0f\x53\xb3\x46\xb3\xa6\xa1\x27\xf9\x12\x40\x1d\xa1\x0e\x6c\xd9\x2d\x71\x49\x48\x6a\x15\x01\x2d\x54\x45\x05\x41\x20\x46\x0d\x55\x25\x8b\x5b\x0a\x12\x1b\xda\x03\x50\x5e\x21\x59\x97\x85\x76\x03\x84\x00\x2d\x15\x90\x40\x56\x72\xa4\x65\x4f\x90\xda\x4a\x00\x9d\x26\x4d\x82\x4f\x75\x85\x92\x2f\x63\x47\xd1\x0d\xf2\xf1\x92\x6f\xa0\xe0\x01\xc5\xbb\x42\x9b\x5d\x0a\x1b\x0f\xc2\x7c\x65\x3f\xb4\xac\xdc\x03\x9a\xcc\xb9\x6c\x8c\x7a\x40\xcc\x9c\x93\x22\x09\x00\x51\x46\x02\xc0\xcf\x47\x9c\x3b\x9c\xd4\x64\xfe\x89\x5b\xc4\x92\x3d\xa2\x99\xdc\x10\x75\x01\xf0\x8b\x7a\x55\x3c\x28\xcc\xd5\x9b\xe3\x72\x55\x20\x27\x55\x25\xe4\x70\x80\x82\x0f\xeb\x44\x4a\x6b\x54\xc5\x67\x6d\x42\x80\x6d\x22\xce\x11\x16\xa4\x50\x1a\xc9\x66\x1b\x65\x94\x8c\xf1\xc7\x71\x8b\xb2\xeb\x12\x7e\xad\xe4\x10\x6b\x4a\xec\x30\x5e\x75\x8b\x0a\xee\xc0\xbe\xa9\x59\x26\xbf\xf9\xc9\x55\x6b\x00\xef\x74\x3f\x42\xcc\x55\x85\x3b\x60\xba\x7a\x07\xd8\x60\x5a\x4f\x6d\x6e\x18\x29\x11\x73\x6d\x42\xc2\x7b\xe1\xa3\x66\x68\xbe\x4f\x6e\x82\x40\x32\xe3\xb1\x6b\x37\x81\xec\x0e\x27\x93\xf0\xc9\xfb\x73\x92\x3f\x91\xf1\x43\xc7\xc0\x6f\x85\xb7\x84\x7e\xff\x0c\xfd\xfe\xed\x85\xef\xbf\x18\x3e\x78\x74\x63\x7d\xc5\xef\xff\x4e\xd5\xdb\xd7\xd3\xe9\x3e\x65\x41\xef\x6f\x5f\x3f\xe4\x57\xfc\xfc\x11\x7b\xac\x15\x21\xc6\xad\x6a\xe4\xfa\xd1\xe9\x94\x35\x1b\x4a\xd5\x00\xd0\x2a\xee\xc6\x4b\x96\xe6\xc8\x49\xf6\xa4\xe4\x77\xcb\x36\x3f\x08\x60\x91\x20\xc9\xa6\xae\xd7\x5b\x61\xbd\x0d\x85\xdf\xb1\x7c\x8a\xdf\xad\xae\x13\x9f\xa9\x2e\xd0\x9d\xe5\xec\xea\x12\x3b\xd4\x35\x1d\x1e\x04\x03\x82\x50\x23\xaa\x46\x88\x79\xc2\x34\x02\x39\x50\x10\x2d\x50\x35\x0b\x5d\x46\x6a\x50\x50\xc1\x31\xe6\x24\x31\x29\x59\x13\xc0\x55\x63\x65\x35\xfd\x04\x89\x2b\x7c\x7a\x8e\x40\x4e\x53\x66\xf3\x8b\xb9\x8c\x1f\xe8\x19\xfd\x41\x4b\x9c\x1c\x9d\x1b\x38\x6b\xdc\x4e\xf8\x58\xc9\xae\x4c\xc4\x55\xd5\xef\xce\xa1\x72\x95\xf9\xdd\x2a\x30\x00\x34\xa9\x25\x23\x5c\xc8\xa5\x6e\xa7\x3b\x94\xea\x12\x3f\x1b\x46\x0f\xa4\xf8\xb5\x7d\xff\x49\xe9\xb4\x25\x73\x6c\x27\x42\xcc\xe9\xc6\x83\xc8\x81\x78\x34\x99\xee\x11\x18\x33\xfb\xd8\x95\xa0\xdf\x15\x10\xf6\xd3\x68\x4d\x5b\xb9\x47\xb7\x72\xde\xd9\x7b\xe5\x6c\xc9\xca\x3d\x7c\x8a\xef\x28\x59\xf1\xad\x59\xc3\x7e\x6d\xb1\x47\x9a\xe0\x28\x0c\xea\xac\xe6\x0c\xe8\x09\x47\x51\x1c\x4d\xab\x38\xad\x59\xd2\xf9\x55\xa3\x67\x29\x44\xe7\x40\xea\xfd\x39\xa9\xbe\xb4\x09\x1c\x0b\x51\xc1\xc3\x7a\x7e\x23\xeb\x12\x2d\x00\x39\x92\x04\x41\x6e\x02\x3c\xe4\xc9\xcd\x74\xf6\xf2\xb2\xbe\x7b\xbe\x8e\x72\xdf\x3b\xe1\x80\xe7\xa4\x32\xcf\x44\x6a\x4e\xa5\xcd\x79\xfa\xc0\x16\xd7\xa9\xb6\x08\xe9\xa4\xe1\x34\x5b\xf8\xc5\x9c\xe4\x22\xb7\xbb\xdb\x0f\xfa\x88\x3a\x4b\x54\xeb\xfa\xbd\x31\x37\x9d\x2c\xaf\xe7\x37\x5a\x58\x6f\xa8\xd6\x43\x2c\x51\xad\x59\xa2\x36\x54\x79\xf6\x53\x68\x52\x77\xad\x1f\xfc\xd4\xbf\x8a\xba\xee\xee\x05\x51\xba\xfb\x33\xb4\x2e\xef\xe7\x9a\x11\x7a\xcd\x81\x5e\x42\xb7\x3b\x38\x1f\xa2\x7d\x5e\xe6\xf4\x62\x9c\x4c\xfd\x60\x04\xf8\x41\x03\xba\xa7\x82\x17\x48\x75\x09\x39\x6c\xce\x65\xea\x00\x98\x56\x17\xb0\xc4\xa5\x9a\x64\xa1\x67\x52\x44\x89\x34\x04\x20\xf9\x88\x00\x34\xa2\x04\x30\xd2\x04\xff\x94\x36\x4a\x23\x7c\x96\x75\x89\x61\x80\x07\xd4\x08\x52\xf5\x49\xfa\x45\x89\x8b\xf7\xed\x11\xcf\x95\x38\xfe\x89\x31\x00\xc5\x17\xb3\x30\xef\x6b\x3c\x08\xfd\xff\xa2\x2d\xdc\x9a\x17\xf8\x2c\xc7\xb7\x85\x06\x17\xb1\x55\xb2\x85\x87\xea\xb6\x53\x5b\x38\x0a\xb6\xb0\xb0\xbe\xb0\x5b\x67\x0b\x9f\xbb\xb2\x67\xe8\xfb\xfe\x25\xb6\xa8\xdc\xf1\x67\x4b\xed\xd0\x67\xbf\x5f\xbf\x7f\x03\x5a\x83\x90\xe1\x80\xaa\xe9\x1d\x41\xfd\xd0\xfd\xaa\xe2\x8d\x90\xa2\x81\x71\xc4\x96\xcb\x8a\x7e\x08\x8c\x45\x1b\x1d\x3f\xb0\x52\x95\x44\x7f\x52\xf2\xf5\x0e\x82\x7d\xb4\x1e\x53\xe7\x07\x38\x04\x68\x4d\xf8\x68\x88\x10\xf5\xd1\xf7\xa5\x8e\xcf\x70\x5e\x23\xc9\x22\xc2\x42\x86\x6f\x68\xa2\xa4\xcb\x22\x60\x02\xa4\x88\xaa\x5c\x56\xf0\xff\x20\x8e\x56\x60\x4d\x2f\xfe\xf3\x35\xda\x7d\xb0\xb4\x02\x8d\xfa\x23\x95\x82\xe7\xdd\x7b\x94\x4f\xaf\xce\x4f\x67\x26\xe4\xbb\x99\x43\x0b\xe6\xcd\xbb\x87\x39\xa3\xf8\x8e\xa2\x18\x42\x6c\x02\xde\xd1\x30\x6a\x40\xd7\x52\x6b\x00\x7f\x28\x28\x14\x51\xbe\x92\x46\x30\x42\xd8\x91\xeb\x61\xc2\x56\x73\x5c\xbf\x7f\xab\x5b\xb6\xf3\x50\x62\x26\x57\x43\x8d\xfa\x25\x84\x31\x2f\xc8\x26\x67\x3a\x2d\xd7\xc0\x08\x38\x90\x2a\xfa\xac\x2a\x6a\xad\x34\x33\x50\x3b\x06\xa0\xd6\xe6\xc4\xfa\x76\x41\x4c\xdd\xeb\xd4\x47\xbd\xe6\x91\xeb\xaf\x3e\x6b\x88\xaf\x73\xe8\x8f\x1f\xbb\xa8\xbf\xba\xcb\xc2\x1b\x7c\x38\x6e\xe8\xda\x39\xed\x26\xfb\x1a\xe7\xa4\x75\xd7\xe6\x37\xa9\x3f\xa7\xfb\xdb\x01\xe7\x3d\x02\xd9\x51\x08\xc5\x48\x8c\xa8\x47\xd7\xc9\x31\x5b\x2e\x6b\x0b\x43\x30\x6c\xb3\x01\x30\xc2\x6d\x2e\xbc\xb6\x0e\x60\x2f\x28\xc0\x79\xc5\x9c\x14\x4e\x4a\x76\xb7\x14\x22\x2e\x00\x4f\x59\x42\x0e\x05\xe0\x6e\x20\x1f\x81\xd1\x97\xeb\xf1\x18\x23\xe6\xb8\xec\x0d\x00\x58\xdc\x13\xa0\x1a\x1d\x21\x07\x0d\x08\xbd\x7c\xc6\xea\x86\xd2\xa7\x87\x82\x13\xc2\x36\x55\x25\x99\x6a\x24\xd3\x43\xe7\x4b\x9f\x3a\xb6\x40\x9c\x5f\x76\xe2\xa3\x4b\xdc\x3f\xa1\xf1\xe8\xeb\x4e\x5b\x97\x58\xef\x22\xe7\x8e\xd4\x1e\x10\x9b\x30\x1e\x44\x3c\x65\x0e\x2e\x53\xa5\xb1\xb3\x10\xe5\x8a\xe6\x5c\xa6\x0a\xc8\x16\xab\x04\x4b\x5c\x0a\x24\x55\xd6\x20\x49\x80\x32\x8b\xcc\xf0\x39\x39\x42\xdb\x05\xe4\xc1\x0c\x90\xe8\x9f\x06\x81\x11\xaa\xe5\x20\xf3\x2a\xb1\x5c\x90\xef\x31\xd9\xc5\x2a\x15\x3a\xee\x07\xe5\x71\x7b\x85\x7e\x51\xe1\xf4\x4b\x77\xbf\xa1\xf4\xe4\xe5\x92\x3d\x97\x1c\x7a\xf1\xf9\xa7\xf7\x1c\x9d\xff\x9f\x81\x78\xf0\xeb\xcb\x2b\x31\x00\x34\x6a\x93\x77\x3d\x1e\x18\x32\xf3\xfa\x61\xc8\x4c\xf5\x63\x72\xa1\x69\x83\x77\xc4\xa5\xab\xbd\xf4\x42\xab\xe1\x7b\x5c\x5c\xc0\x4f\x9b\x48\x72\xb4\xaf\x81\xe1\x4a\xaf\x7c\xd9\xa0\xdd\x9d\xbd\x9e\xf6\x0a\x73\xe5\x3f\xea\xf5\x9a\xb3\x3a\xde\x80\x1a\xd4\x8c\x6e\xef\x93\x39\x00\xa0\xc5\x92\x98\x94\x59\x47\x0e\xe2\x76\x96\xa6\xb8\x51\x7f\x4e\x8a\x56\xe2\x12\xe8\x8f\xe3\x72\xad\x9a\xf7\x46\xf9\x1e\x81\x0b\x87\xe8\x3e\x33\xae\xfa\xc6\xf4\xc9\x4c\x64\xf2\x15\xb6\x5d\x36\x26\x57\xbe\xeb\x0a\xd3\xe1\x93\xcb\x37\xad\xf1\x39\x8c\x00\xbf\xbd\xb9\xc2\x5c\xe5\x71\xbc\x56\x3f\x18\x4e\xbc\x36\x52\xf4\xda\x40\xf1\x8c\xc1\x7b\x05\xca\xca\x15\xe4\x33\x2e\x91\xa3\x4d\x8a\xde\x14\xde\xea\x01\x97\x38\x6a\xd9\xd1\xfe\xa7\xf4\x6d\xaa\x30\xf4\x5d\x53\x70\x57\x95\x07\x42\xcd\x63\x1f\xe9\x6b\x46\xb2\x72\xfa\x1a\x2b\x1b\xf2\x26\xb9\xab\x6e\x50\x32\x0c\x83\x92\xc5\xdc\x55\x77\xd6\xf5\x25\x59\x6c\x46\xe0\x02\x64\xbf\x16\x92\xab\x9f\xc4\x64\x64\xc9\xe6\xcb\x0e\x78\x79\xc9\xe6\x2b\x4c\x6f\x27\x74\x7b\x9f\xa2\x0c\x33\x18\x40\xdf\x23\x81\xee\x45\x99\x7a\xc0\xde\xd9\x72\x19\x9e\xd1\x1e\x9f\x41\x09\xc9\x49\xd1\x09\x41\x37\x60\xee\xfa\x3b\x72\x52\x7f\x9a\x3a\x44\x45\x5a\xac\x09\x3a\xa9\x84\x7a\x3f\x5e\x6e\x4c\xa4\xd3\x52\x7f\x61\x93\xcd\xc0\x57\xd7\xfb\xa0\xd9\x6b\xe2\xa5\x9a\xb4\x14\xa5\xc2\x60\x48\x36\xd4\x6b\x6c\x9d\x3d\xd8\xe9\x05\xa8\x0b\x1c\xbb\x0e\xa0\xd7\x82\x9b\x5a\x70\xdb\xe0\x7a\x4d\x44\x54\xf4\xd6\x60\x3f\x60\xf5\x20\x36\xa1\xc5\xff\xd8\x94\xcb\x3e\x9d\xd4\xbd\x66\xf8\xc2\x45\xef\x6f\xc0\xf8\xa3\x03\x9b\xd3\xdb\x56\xdf\xb7\x34\x7d\xcf\x83\xcf\xad\x3a\x47\x39\xf8\x6f\xe5\xe8\x23\xbe\x76\x73\xc6\x7d\x45\x6a\x72\xab\xd4\xdc\x72\xf7\x0d\x67\x4d\xbc\x60\x70\xd7\xce\x67\x7e\xf1\xde\x05\x2b\xc7\xde\x74\xf5\x99\x97\x8f\x4d\x0e\x9f\xbe\xf4\x9a\xd7\x7f\xaf\x4c\x49\x6d\x3d\x45\x18\xf9\xca\x70\x44\xed\xc1\xce\x04\x6d\x90\x81\x24\x3a\x13\x21\x46\x37\xab\xd1\x99\xb9\xc0\x90\x21\xf9\x93\xb2\x4d\x00\xf8\x12\xd4\xaf\x1c\x50\xbf\x22\x57\x97\xe0\xa1\x9d\xa1\x26\x1b\x2f\x64\xa2\xf5\x03\xc9\xa9\x36\xf3\x9b\x58\xa7\x18\xaa\x35\x0f\xa0\x21\x3a\xad\xc7\xa8\xcf\x72\x48\xa4\xb3\xd8\x66\xbe\x07\x71\x42\x80\x36\x43\x54\x72\xe6\xf6\xa2\x01\x7c\xb0\xff\x02\xb8\x05\x58\x4d\x19\x9d\x2d\x7e\xff\xc6\x2b\xcf\x75\xbe\xf0\xc0\x4d\xb7\x5c\xf5\xf2\x43\x73\x46\xfc\x69\xcf\xfe\x7b\x37\xae\x7d\xf0\xae\xdb\x97\xaf\xb8\x7b\xd8\x97\x9a\x1d\xd8\x61\x73\x9f\xea\x5a\x34\xe6\x8c\x11\xc3\xcf\x1b\x93\x1a\x7f\xc3\xb9\x4f\xae\x3b\xbd\x7b\xfc\xf8\xae\xd1\x97\x0c\x1d\x7e\xf1\xd4\x23\x57\x17\xcc\x80\x18\xe4\x55\x86\x81\x76\x81\x09\xf1\xe8\x4c\x94\xe1\x34\x86\x75\x55\xc2\x00\x32\x4a\x6e\xaf\x64\x4b\xca\x46\x91\x24\xf7\x19\x23\x57\x50\x30\xe0\x40\xc1\x80\x53\x15\x0c\x64\x23\x07\xfd\x20\xa4\x69\x17\xc4\xc8\x23\xa3\x2e\x1b\xb4\x0b\xb6\x5c\xac\x2d\x10\xd4\x0b\x0e\x1a\xbd\xdf\x8f\xd2\xaf\x25\xaa\x0c\x03\xbd\x0e\x1f\xaa\x45\x4f\xd0\x4a\xf4\x89\x14\x3b\x40\x25\x42\x2c\x48\x75\xa8\xcc\xc5\x26\x4b\x5c\x72\x25\x35\x4a\xe3\x5e\xc2\x1d\x21\x12\x39\x39\xa8\x52\x19\x2b\x16\x84\x3b\xfc\xb5\xe9\xb4\x1c\x0e\xf1\x42\xc6\xee\xa1\x34\xfc\x76\x0f\xed\x70\x99\x79\x18\xe4\x15\x2a\x4a\x75\xa8\xea\x11\xc5\x23\x2a\x11\xeb\x00\x01\x89\x6b\x0a\x07\xa3\x57\xec\x50\x15\x24\x0e\x2f\x2b\xda\x00\xa3\xb1\xc7\x0e\x1a\xc6\x80\x7e\xf2\x35\xb4\x4b\x0c\x08\xd9\x20\x39\x11\x8f\x35\x97\xb5\xdb\x1a\x83\x0e\x40\x97\x6a\x08\xd9\x98\x3f\x27\xb9\x49\xa4\x54\xe5\xcb\x65\xdc\xa0\x3f\xe0\xb6\x69\xaa\xc9\x86\x46\xfa\x09\xda\x78\x19\xc7\x28\xb5\x5d\xa4\x16\x50\xe6\x19\x9f\xbf\x2a\x5d\xce\x6f\xdc\x56\x14\x44\x6a\x6a\x8f\x52\x51\x1e\x51\xe5\x3a\x1e\x7b\xe5\x97\x93\xdf\xdd\xf9\xc7\xcf\x3f\x7c\x77\xff\xbe\x67\xe6\xde\xfc\xf2\xb4\xf1\x1f\xe3\xea\x2f\x30\xb3\xa9\x7b\xeb\xeb\xca\x7b\xca\x5f\x94\xef\x87\xad\x4d\xb4\x2e\x79\x68\xce\xdc\x27\x17\xdf\x39\xf5\xce\xf6\x33\x66\x2d\x7f\xfb\x85\x87\x37\x06\xcd\xc1\xec\xe2\x5d\x5f\x21\x55\x27\x83\xdd\x64\x98\x88\x9a\xd1\x64\x94\x09\x82\xec\x87\x19\x70\xf2\x2c\x80\x07\x65\x9b\x99\xce\xe9\x70\x7b\xe5\x3a\x87\x9a\x1a\x57\x09\xb9\x8c\x0b\x76\xe5\xb2\xd2\x29\x1d\x24\xb3\x64\x57\xcd\x00\xff\x05\x2d\x68\x1b\x14\x0a\x04\x5e\x16\xab\x40\x7a\x45\xf2\xa5\x07\xb5\xfa\x2b\x6f\x8b\xf6\x0c\xbc\x1c\x88\x8b\x03\x86\xd6\x7b\xe9\x9e\x2b\x56\xbf\xb1\xe7\xd7\xcf\xfe\xea\x91\x17\x57\xde\xdf\x79\xf7\xb8\xce\x4b\x9e\xb9\xfc\xe3\x6f\xef\xbb\xef\xf9\xee\x07\xbe\x7f\xe6\xeb\x65\x47\xe3\x89\x2d\x2b\x9e\x5e\xb7\x68\xd1\xf4\xe9\x73\x6b\x9a\x17\xc5\x23\xef\xfc\x72\x56\x76\x40\xff\x5d\xcb\x1e\xf9\xe3\x5d\xe7\x14\xb0\x4a\x0d\x50\xff\x08\xa0\xb3\xd4\xc8\xd7\x54\x98\x2b\xc9\xb2\x56\x08\x7c\x01\x02\x46\x51\x56\x36\x0a\x01\xb3\x81\xec\x8a\x0a\x01\x03\xaf\x34\xdb\x78\x41\xb6\x7b\xd2\x7a\xe4\x57\x8c\x8f\xf2\x9e\xd2\x29\x13\xe6\xeb\xcd\x9b\xf3\x42\x75\xc9\x7c\xc9\x32\x66\xea\xe1\x2e\xe6\xc5\xfc\xb8\xde\xb3\x25\xe7\x98\x9e\x42\x3e\x14\x43\x93\x0a\x98\x1e\x2a\xc3\x2b\xa8\x32\xbc\x34\xf0\xf6\x51\x19\x5e\x1f\xad\x1b\x39\x1c\x34\xa8\xf6\xc1\xa8\x89\x3f\x40\xa9\x29\x37\x72\x96\x60\x35\xc0\x95\x25\x07\xa5\x76\x41\xa0\x61\x09\xe8\xaa\x72\x09\xde\x02\x30\xa9\x74\x0c\x25\x6b\xb5\xb7\x66\xa7\xff\xea\xbd\xcc\xed\xf7\xbc\xb0\xc2\xad\x9f\x41\x51\x86\x5c\x32\xea\xfc\x4b\x5e\xff\x88\x22\x94\xb6\xee\xcd\xef\xd4\x4f\xa1\x60\xe0\xe1\x4c\x19\x77\x21\xa1\xa8\xf3\x58\x80\xb1\xb9\xd8\x9c\x64\x4b\x80\xec\x36\x02\xe6\x6f\x40\x55\x09\x94\x18\xd4\x2a\xe6\xa0\x3e\x29\xa8\xa8\x2a\x9b\x86\x61\x73\xf5\x0e\x91\x6b\x83\x18\x16\x5e\x1b\xc4\x3b\x16\x47\xac\xa7\x7c\x3f\x0b\x1f\xde\xbc\x56\x52\x26\x18\x37\x6f\xbb\xec\x96\xfc\x97\x87\xaf\x32\x3e\xb5\x63\x93\xd2\x76\x74\xa5\xa6\x47\x67\x6c\xe2\xbc\x28\x82\x06\xa0\xeb\x54\x55\x9b\x98\x96\xe5\xf7\xb7\x40\x82\xe2\x52\xb1\xb1\xb4\x93\x5e\x2b\x02\xef\x84\x0f\xc7\x33\x9c\xa5\x31\x99\xa4\x54\x9a\x2d\xc4\xd6\xb5\x80\x8a\x0d\x57\xc7\xfa\x03\x68\x8d\x87\x3a\x77\xb5\x0b\x52\x58\xb9\xbf\x97\x02\x21\x43\x7a\x20\x24\xc5\xc3\x16\x04\xa6\xf8\xb6\xc1\xed\x15\xc0\x90\x05\x44\x6c\xeb\x69\x67\x0d\x48\x4c\x53\x14\x2b\xeb\xb8\xed\x0f\xfb\xfe\x56\x40\xc6\x96\xa0\x61\x7f\x32\xf5\x52\xdf\x43\x51\x3c\xee\xbe\xc0\xed\xc2\xb3\xb8\x3f\xb6\x68\xb8\x58\xb2\xdf\xdb\x8f\x1d\x34\xfc\x19\x78\xd8\x1b\xd0\x6d\x2a\x8b\x79\xc4\x96\x03\x79\x62\xc9\x99\xca\x5a\xeb\x03\x46\x4d\x97\xae\x51\x27\x3b\x28\x99\xc8\xd7\x6c\x10\x73\x92\x21\x01\x88\x47\x95\x6b\x4a\xf4\xe7\x24\x07\xd4\xc0\xd4\xf8\xdf\x61\xe2\x85\x2c\x23\x04\x22\x74\xee\xae\x3e\xc2\x0b\xb2\x88\xa8\x7a\x30\x23\xa8\x08\x27\x12\xff\x8a\xea\x0e\x53\xa2\x1b\x3e\x66\x14\xad\xab\xd7\xb0\x4c\xee\x68\xed\xed\xb8\xf5\xcf\x9b\x57\x3d\xf6\xf8\xaa\x2d\x07\x1f\x5f\xa9\xec\x56\xbe\x7b\x5e\x39\xb6\xf0\xcd\x6d\x5b\xb6\xbc\xa6\xcc\x55\x16\xe2\x03\x78\xf4\x65\x97\xe3\xfe\xd9\xec\xe3\x6b\xd7\x3e\x9e\xcd\x2a\xbf\xbd\x72\xd0\x87\x2b\xbe\x52\xfe\x3d\xf3\xcb\xa5\x2f\xac\x7b\x71\x0d\xee\xa2\x7a\x91\x86\x29\x1c\x65\xd5\xb8\x49\x65\x9d\xaf\xa5\x93\x3d\x36\x4b\x4e\xe2\x12\x92\x8b\x46\xff\x14\x11\x2f\x99\xdd\x52\x35\xd9\x0a\x12\x73\x12\x4a\xc8\xd5\x22\xf4\x37\xb4\x2a\x6c\x0c\x7a\x61\x62\x0e\xa2\x7f\xa7\x99\xec\xd2\xfb\xff\x91\xf7\x2f\xe0\x51\x94\xe7\xff\x30\xfe\x3c\x33\xb3\xe7\xe3\xcc\xce\x9e\xb2\x39\x6d\x96\x9c\xd8\x90\x85\x5d\x92\xb0\x84\xb3\x88\x10\x10\x91\x22\x22\x62\xa4\x80\x08\x28\xa0\xa2\x22\x22\xa2\x22\x22\xa2\x20\xa2\x88\x11\x31\x22\x45\x44\xc4\x99\xcd\x1a\x90\x7a\xc0\x23\xe2\xa1\x8a\x56\x28\x5f\x6b\xd5\xb6\xd6\x6e\x4b\xd5\xda\xf6\xaf\x42\x32\xf9\x5f\xcf\xfd\x3c\xb3\xbb\x09\x41\x7d\xbf\x6f\x7f\xd7\xf5\x5e\xef\x6b\x9b\xb0\x40\x98\x79\x8e\xf7\xf1\x73\x7f\xee\x82\x52\x5a\xe7\x53\x51\x2a\x4a\xaa\x9f\xcc\xd2\x26\xaa\x9c\xcc\x66\x99\xdb\x5c\x86\xfc\xa4\xf3\x8c\x94\xa1\xee\xfd\x24\xad\xf3\x67\xa4\x97\xdd\xb5\x76\x59\xba\x79\xfe\x1d\x77\x68\x5f\x7f\xfd\x67\xed\x1f\x07\xb6\xb7\x3e\xb2\xe3\x89\x47\x1e\xd9\x8e\x33\x78\xfc\xac\xca\xf6\x87\xb0\x59\xd3\xb6\x6d\xda\xb4\x0d\x73\xda\xf7\xdb\xd2\x95\x89\xe3\xdb\xbe\xd6\xbe\xc5\xde\xbf\x2a\xfb\xdb\x53\x29\x35\x05\x67\x79\xa2\xb6\x00\x7a\x87\x58\x90\x17\xcd\x66\xf9\x2c\x13\xe0\xea\x29\xd4\x99\xe7\x21\xe5\x6f\x27\x7b\xeb\x03\x6b\x51\x94\x32\x8a\x39\x9e\x72\x42\xb5\xad\x93\x18\x02\x7e\x32\x5b\x67\x36\x16\x01\x1a\xd4\xcb\x9a\x1a\x29\x26\x88\x3b\x0b\xbc\x4e\x6c\x9b\x85\x6c\x1b\x7c\x89\x38\x99\xa2\x3b\x52\x56\x39\x31\x07\xb0\xd7\x36\xd7\x0e\x9a\xb5\xfd\x9b\xc6\xe1\x3a\xac\xfe\x4b\xcf\x15\x38\xa1\x1d\xd3\xbe\x0e\x42\x9f\x11\x6d\x01\xf4\x19\xf1\xe8\x68\x45\xd5\x64\xca\xa4\x04\x68\xb2\x67\x82\xfc\x03\x74\x85\xa1\xe4\xe2\x16\x29\x93\x92\x2c\x3a\x89\x38\xf0\x04\x5b\xa4\xec\x38\xdd\xac\x7e\x01\x41\xa6\xf1\x4c\xe3\xcc\xeb\xca\x35\x29\x07\x25\xff\x66\xc8\xf0\xda\xe4\x2c\x06\x19\xd7\xbe\xa1\x6d\xb8\x36\x64\x71\x03\x0d\xc8\x04\x19\x8a\x31\x3d\x71\x03\xe6\x2c\x6e\xc0\x1f\x53\x45\x81\x02\x84\x9d\x47\x55\xd9\x49\x33\x0c\xb2\x13\x68\x10\x6c\xd4\x21\x34\xb3\x36\xc8\x59\x24\xc0\x8f\x50\x20\x9c\xa0\x99\xff\xca\x2c\x9f\x2a\x83\x00\x70\xf3\x28\xf5\xc1\xf6\x1c\x0f\x30\xcd\xff\x7f\xc1\x30\x90\x9b\x7e\x26\xfe\xb1\x9a\x8c\x36\xde\x13\xf8\x58\xe3\x04\x1a\x9d\x5e\xc9\x0e\x12\x38\xaa\x56\x84\x00\xe7\x78\x3a\xcf\xc1\x7f\x81\xdf\xc0\xf3\xf3\xb9\x0d\x9e\xd7\x97\xe5\x27\x80\x8a\xfc\x07\xdd\x38\x87\x65\xfe\x7b\xe0\x8c\x2f\x42\x37\xb2\x2c\xd8\x69\x09\x5f\x25\x14\x53\x9d\x86\x4c\xda\x60\x96\xf3\x01\x89\x3f\x95\xe2\x85\x32\x81\x80\x9b\xe2\x97\x45\x8b\x28\xa5\xed\x1e\xd9\x07\x6c\x3a\x01\xba\x3c\xe4\x28\x00\x37\x6b\xb7\xac\x2e\x83\x49\x35\x24\x4c\x74\xe2\x95\xf9\x99\xdd\xd6\x3e\x63\xc7\x9f\xfb\xeb\x69\x4b\xeb\x52\x0f\x6e\x19\x59\x9e\xcd\xec\x6a\x1b\xac\x95\x89\x8b\x02\xca\xc2\x8a\xbb\x66\x5f\x69\xd3\xeb\x19\x65\x21\xc4\x78\x70\xfa\x11\xcf\x98\x38\xc5\xe9\x3e\x79\x95\x6a\x41\x73\x46\x89\xc6\xd4\x62\x43\x26\xed\xa5\x99\x5e\x6f\x8e\x44\xd0\xec\x85\x34\x9b\x99\x46\x68\xab\xdc\xe0\x22\xf9\x58\x8a\x9f\xb8\x48\x61\xb3\x28\x8d\xb0\xf0\x36\x29\x58\x18\xe9\x53\x11\x25\xf3\xaa\x12\x95\xf2\xa4\x6a\xf4\x31\xf7\x17\xa9\x52\xb1\x28\xa5\x22\x15\x55\xe4\x00\x98\xfb\xd0\x54\xb6\xf7\xc7\x32\xbb\x2c\xcd\x7f\xda\x1a\xf4\x96\xdd\x7d\x91\xe5\x73\xcf\xeb\xb6\x26\xbd\x64\x77\xf1\x8d\x2d\xad\x3b\x4f\x2d\xe8\xb6\x44\x06\x9a\xd7\x30\x17\xb1\x9a\xc7\x4a\x94\x40\x77\xf6\x96\xdb\x28\x8f\x29\x03\x12\xe9\x12\xca\x29\x13\x8d\x67\x6b\xfa\x06\x9e\x56\xf2\xe8\x83\x20\x76\x15\x8e\xaa\xb5\xfe\x8c\x52\x9b\xcb\x6e\xd4\xe5\x57\x3f\xaa\x55\x65\xb9\xc2\x58\x55\xaa\x15\x25\xb5\x20\xf4\xb3\x93\x5f\x67\x66\x84\xf9\xd1\xc2\xc7\x5e\x79\x18\x7f\x2a\x15\xb6\xbe\x37\x96\x41\x03\xd3\x9f\x0a\xab\x81\xcc\x5f\xb7\x6e\x79\x90\x1f\x5f\xb7\xfc\x5a\xc8\xd3\xd6\x4d\x2f\x8b\xac\xcb\x2f\x8b\x64\xeb\x66\x71\xfb\xc8\xba\x79\x72\xeb\xf6\x73\x12\x22\x3f\xb2\x6e\xbd\xa7\x47\xc4\x33\xac\xd9\x19\xf2\x24\xdc\xb4\xde\xd6\x4a\xe8\x76\xc6\x62\x28\x81\xbe\xec\xed\x84\xd5\xc4\x94\x68\x42\x0d\x99\x32\x6a\x61\x24\x1e\x6f\x2b\x0d\xd5\x98\xa3\x6a\xa5\x29\xa3\x06\xaa\xe2\x71\xa5\x7f\x4c\x1d\x70\xda\x79\xcb\x3b\x59\x4a\x7d\xc1\x81\x7f\x6c\x79\x25\x8d\xbc\x51\xab\x12\xad\x75\x2a\xc5\x6e\x83\x12\x75\xab\x85\xa1\x1f\x94\x62\xb7\x5a\x15\xfa\xe1\xc0\x5f\xb8\xd7\x6f\x87\xb6\xfe\x85\xee\xb6\xa2\xc2\x62\x4f\x54\x89\xba\xdb\xaa\xa3\x55\x9e\x68\x5b\x5f\xf2\x3d\x55\x54\x58\x9c\xeb\xe6\x9f\xea\x1b\xad\x12\xa5\xa4\x52\x9d\x44\x6d\x45\xc5\xd5\x7d\xa1\x95\x7f\x7b\x61\x51\x71\x55\x75\xdf\x68\x2d\xfd\x4f\x19\x51\x80\x81\x42\xea\x59\xde\x12\xe8\xd3\x3f\xfe\xb3\x19\x79\x89\xa8\x2f\xe6\xc8\x85\x4f\x40\x97\x2a\x8e\xa6\xd2\xc3\xde\x33\x1f\xdf\x3b\xad\xf3\x2e\xe8\x3b\x69\xdc\x59\xc5\xd1\x0a\xe7\x5c\xdb\x65\x17\x56\x9e\x3b\x6e\x4c\x49\x45\x5f\xd7\x48\x6e\xe6\x4f\xa6\xef\xc6\x5c\x75\x63\x49\x79\x49\x7d\xec\xaa\x1b\x4b\xfa\x94\xd4\x0c\xc2\x63\x37\x6e\xcc\xcb\xe7\x92\x33\xdc\x07\xf6\xe5\x3b\xb6\x2f\x55\x16\xd6\x1d\x57\x0c\x24\x12\x6a\xd8\x94\x51\x4a\xe3\x6d\x5e\x77\xd8\x1c\x55\x0b\x4d\x19\xd5\x51\x14\x8f\xd3\x13\x5e\x6b\xc9\xf4\xd8\x99\x72\x2f\x24\xf4\xa2\xb9\xb3\xdb\x6d\x67\x4a\x6b\x9d\x8a\xc7\x6d\x20\x3e\x82\x18\xfa\x41\xf1\xb8\xd5\xa2\xfc\x9d\x11\xdd\x6d\x92\xe8\xf1\x44\x95\x52\x77\x5b\x71\x69\x91\x27\xda\x56\x42\xbe\xa7\x24\xd1\x93\xb7\x33\x25\xa5\x45\x64\x67\x8a\x93\xa8\x4d\xf2\x14\x97\xd0\x9d\x11\x25\x4f\x51\x71\x49\x69\xfe\xce\x94\x23\x6a\xf7\x44\xc5\x7d\x16\x37\x1f\x28\xa4\x3b\xa4\x18\x25\x25\x98\x44\x6a\x6d\xd5\x19\x78\x85\x7b\xdf\x9c\xee\xd7\xa8\xdb\x75\x79\xec\x0c\x5b\x73\x9e\x7e\x8d\x9c\xdc\xcc\xd3\xae\x0c\x3f\xa3\xfb\xa6\x74\x4e\xca\xdd\x21\x94\xcd\x37\x37\xc0\x9d\x89\x64\x39\x95\xbb\xdd\x98\x70\x4c\x0d\x09\x39\xaa\x98\x3c\x1e\x02\x67\xb7\xb4\x72\x79\x0f\x1e\x82\x9f\x75\x46\xf1\xcf\x12\xaa\xf8\x06\xdd\xde\xf8\xc9\x43\x78\x28\x67\x97\xd1\xfc\xf1\x17\x20\x3b\x73\x73\xeb\x26\x37\xbb\xcf\x2d\x9f\x60\xc0\xd9\x8d\x60\x20\x3b\x37\x0b\xef\x73\xc3\xdc\x7e\x8e\x20\xfc\x49\xc1\x77\x2c\x3b\xad\x33\xa5\x84\xf7\x64\xed\x27\x5d\xbe\x71\x59\x1d\x7a\x55\xef\x1a\x54\x2d\x11\x72\xc5\xf0\x55\xa7\x29\x4e\x67\x37\xae\x80\xea\x33\x73\x05\xfc\xef\x35\xe5\x99\x37\xf2\x99\x7c\x52\xac\x9f\xd4\x89\x4b\xf2\x59\xb1\x74\x39\x92\xca\xea\xc2\x6b\xf2\x76\xb4\x84\xcc\xbf\x5c\xc8\xdb\xda\xee\x2b\x90\xaf\x02\x9d\xdd\xe8\x00\xaa\x7b\xd0\x01\xb4\x59\xdc\x3e\x9e\x32\xdf\xff\xef\x75\xde\x19\xf5\x5c\xde\xec\xcf\xa4\xdd\xa6\x77\xe7\x02\xe3\x68\xff\x4e\xe3\xf3\xc8\x8c\xec\xa8\x01\xa5\x4c\x7a\x47\x51\x85\x4f\x28\x96\x18\xed\xc3\xed\x80\x40\x26\x99\x0f\xf1\x95\x01\x8c\xc4\x25\x91\x8a\xe8\x87\xfe\x03\xc4\x04\xeb\xd6\x49\xc4\xff\x61\xbc\x1c\xaf\x78\x43\x0b\x3e\xf7\x01\x37\xd3\xd0\xde\x39\x40\xef\xd1\xc9\x77\x6c\xdc\x88\x38\xe8\xd1\x29\x1b\x16\xc0\x2a\xc7\x69\x97\x4e\xc5\x92\x50\x9c\x31\xd5\x93\xb7\xae\x85\x31\xb5\x08\x47\x11\x74\x57\x57\xdc\xc4\xed\x53\x05\x31\x99\xed\xcd\x39\x0c\x37\x78\x12\xb9\x96\x9c\xf5\xc3\x31\xb0\x89\x41\x5f\x4e\xcb\x08\xdf\xa7\xaf\x68\x95\x67\xbf\x78\xf7\xf8\xa6\xf8\x98\xa9\x37\x54\x24\x3f\xe3\x66\xd2\x9e\x9c\xe5\x6f\x0f\xe5\x16\x9f\x2a\x6e\xdf\x26\x6e\xb0\x5f\x3a\xfb\x3e\xe1\x13\xd0\x21\x1c\x72\x76\xbd\xca\x7d\x6f\x94\x91\x84\x0a\xd1\xa5\xac\xc6\xc2\x6b\xca\x50\x77\x30\x14\x23\x5e\xab\xc2\x53\x9e\x17\xee\xa8\x6a\x70\x64\x14\x4f\x5c\x31\xd0\xbb\x6c\x95\x68\xab\x47\x03\x47\x47\x1a\xa0\xfd\xb3\x91\xea\x75\xd0\x3f\x08\x89\x2a\x67\x4d\x82\xcf\x6a\x20\x0e\x42\x7d\x83\x98\x10\x73\x9b\x59\x69\x34\x79\xb2\xb1\x02\x67\xd3\xd4\xf4\xf0\x73\x6f\x5a\xbf\x7e\x55\xf3\x1d\x15\xc5\x95\x6f\x99\x6e\x1a\x92\x18\x5e\x3f\xec\xcd\x85\xc2\xa7\xa7\x76\x07\xd7\x2e\xbc\x66\xd5\x39\x43\x86\x2e\xc6\xd3\x76\x0c\xed\x57\xc7\x38\x32\xf7\x76\xbd\x6a\xf8\x1c\x78\xa9\x6a\x74\x8c\x2b\x0d\xcc\x97\x9b\x32\xe0\x26\xe6\x65\xb5\x8b\x2d\x99\x74\xd4\xe1\x31\x39\xa2\x6a\xd4\x94\xad\x1c\x29\x63\x15\x8e\x65\x34\xf0\x6e\x73\x64\x94\x08\xc4\x3e\xab\x58\xff\xec\x5a\x72\xae\x69\x64\x4e\xb5\x01\x29\x6d\x00\x72\x29\xaa\xc3\x43\x26\x1a\x25\xde\xa2\xdb\x5b\x90\xa4\xc5\x48\xb6\xa4\x52\x2c\xa9\x02\xdf\xb3\x0c\x32\x3b\xe5\x4a\xa3\xa9\xb2\xbe\xa1\x7b\xc3\x0d\xf2\x9b\x6c\x51\xe4\xf0\x09\x37\xad\x5f\xb7\xfa\xd9\x5f\x14\x57\xad\x6d\x9a\xba\x74\xe5\x93\x0f\x71\x7f\x33\xdd\x34\x70\xf0\xb0\xfa\x61\xac\x42\x52\xfb\x17\xac\xc5\xaa\xe4\x92\xa1\x6f\x2e\xc4\x6b\x69\xb1\x24\x0e\xed\xa8\xab\x23\xab\xc2\xa1\xa2\xae\x57\x79\xa3\x61\x0c\xd4\x57\x3c\xca\x72\x47\x45\x6c\x3f\x69\x64\xd5\x4e\x76\x34\x0e\xcc\x09\xe9\x88\xcb\x6b\x71\x44\xd5\x88\x89\x32\xfc\x73\x47\x21\xb6\x6a\x0e\xc5\xe3\x29\x07\x47\xdc\x41\x87\xcd\x12\x4d\x71\x0e\xf2\x91\x13\x2c\x51\x72\xd5\x4d\x81\x8c\x62\x8a\x91\x4f\xa5\xb4\x2d\x3d\xf8\xd7\x50\x94\x65\x0c\x24\x93\x6a\x29\x14\xd7\x00\xf7\x7f\x11\x6d\xdb\xa1\x44\x68\x78\x8c\x76\xa3\xa7\xa8\x60\xfd\x3c\x64\x3b\xe2\x9d\xe9\x5c\x14\x8d\x9f\xf2\x30\x4b\x5a\xd0\xc5\x21\xc7\xa3\xea\x6d\xb6\x2a\x6f\x2f\xe0\xd6\x42\xda\x42\x43\xec\x8c\x24\x97\xe0\x69\x6c\x35\x10\xc2\x5d\x1b\x34\x19\xcf\x12\x9a\x90\x03\xf5\xeb\xc1\x16\xe1\xcc\xb2\x45\x40\x63\xfa\x1f\x65\x89\xc8\x11\x43\xe4\xb3\x41\x30\x2c\x95\x69\xaa\x51\x06\x66\xd3\x04\xba\x85\xf6\x72\x57\xfc\x09\x35\x6c\xc9\x28\x35\xd4\xce\x52\xc4\x84\x5a\x69\xc9\x28\x03\xe2\x10\x6a\xa5\x96\x56\xb1\x17\x14\x61\x1f\x1c\x55\x2c\x71\xc8\x67\xda\xe2\x4a\x5f\x37\xad\x5e\x62\x6e\x43\x1f\xe2\x78\x1a\x78\x20\x36\xed\x2b\xa6\x4d\x46\xa7\x0b\xaa\x30\x6a\x25\x55\x04\xde\xf6\xca\xb0\x28\xb5\x53\x3e\x82\x60\x2f\xa1\x57\x53\xa2\x9e\xe9\x92\x52\x9e\x0b\xeb\x81\x57\x1a\xb0\x30\xb8\xc3\xa5\x62\x5e\x04\x56\xb0\xa4\xad\xd6\xc5\x5f\x1c\x3f\xd1\x79\x42\xfb\xcb\x35\xd7\x68\x5f\xfe\xfd\xe4\x81\x87\x37\x6f\xdc\xf6\xe0\xce\x75\x5b\x78\x09\xc7\x71\xbf\xfb\x1e\xdc\x79\x2f\x0b\xc6\x16\xdc\x9e\xc4\xb7\x6a\x77\x5c\x7d\xf5\x0e\xed\x23\xed\xdf\xda\x09\xed\x63\x8c\xba\x10\x2e\xc3\xe2\x3b\x1f\x7c\x7e\xf8\x8f\xcf\x7f\xf2\xb2\x36\x15\xef\x7c\xff\xfd\xe7\x75\x1f\xde\x34\x55\x68\x06\xa4\xc2\x40\x74\x2b\x4a\x15\x22\x08\xc8\xaa\x65\x79\x6b\x64\xa6\x6b\x14\x8f\x2b\xbe\x98\x4e\xfe\x5b\xe2\x85\x4c\x7d\x39\x8e\x2a\xbe\xb8\x5a\xed\xc8\xa8\xa2\x1c\x8f\xeb\xac\xdc\x36\x6f\x06\xa8\x7e\xcb\x4b\x44\x29\xc5\x17\x14\x26\x29\x19\xb7\x01\x78\x7e\x9d\x6e\x33\xc4\xa6\x2a\xcb\x88\x7f\x8f\x6c\x6e\x31\x58\x60\xa8\x8e\x65\x17\x89\xc2\xcb\xa8\x9e\xad\x84\xfa\xea\x88\x38\x30\x3f\x3c\x5d\xe7\x0e\x97\xe2\xfc\x50\x66\xe7\x09\x1c\xbc\x66\xf0\x6f\x6e\xff\xfb\xc9\x7f\xfc\xee\x0f\xd7\xdb\x05\x73\xda\x6a\xbd\x22\x73\xec\x1f\x07\x36\x6e\xf9\xd5\xbd\xda\x7b\xda\x87\xbc\xfb\x81\x27\xd7\x6d\x79\xf8\xc1\x7b\x1f\xe5\xca\xb1\x8c\xcb\xbb\xd0\xed\x37\x69\x7f\xd0\xfe\x4e\xd4\xd0\x63\x91\xf1\xf3\xb5\x66\xbc\xf5\xaa\xab\x1f\xc7\x7d\xb1\xed\xc8\x7b\x2f\x7c\x8a\x77\x6b\x53\x3f\x7d\xe9\x93\x77\xdf\xf9\xe0\x33\xc4\x23\xd4\x35\xd7\x10\x32\xca\xc8\x85\x7c\x79\x0c\x60\x2c\x53\x93\x76\xba\x11\x76\xc0\xb1\x72\x02\xb5\x88\x22\xc4\xb0\x52\x10\xa3\x6d\xae\xb1\x9b\xd8\x86\x46\x39\xc8\xca\x97\x13\xfe\x86\x04\x0f\x71\xb8\x88\x27\xc2\x7b\x12\x1e\xb8\x50\x09\x9e\x6b\xdc\x39\x6c\xea\xda\x2d\xf8\xd9\x97\x14\xed\xc8\x91\xb5\x1f\xae\xdf\x7b\x62\xed\xb6\xaa\x82\xe2\xf0\x82\x97\x66\x1b\x9e\x7f\xf4\x3b\x6d\xe2\xa9\x6d\xf8\xf5\xce\xc7\xb8\x4b\x21\x1a\x77\xe8\xea\xe6\x1b\x66\x6b\x67\x63\x0b\xe3\x99\x98\x2b\xbc\x67\x94\x51\x31\xaa\x40\x63\x50\xca\x4f\xe4\x8a\xc8\x33\x9e\x89\x3e\x7c\x06\x5a\x25\x56\xd2\x5d\xf3\x67\x88\xfc\x44\xaa\xe8\x17\x25\x55\x2e\x4c\x26\x95\x3e\x62\x1a\x39\xed\x1e\xc8\xb3\x0b\x92\x6a\xb1\x25\x73\x8c\x11\x0d\x09\x93\xcf\x6f\xaa\xa8\xc4\x90\x28\x00\xc5\x66\x8a\x34\x54\x70\x0d\xb4\x00\x11\xad\x78\x02\x0f\xff\xdd\xc4\xa6\xa2\xb5\x95\x43\x47\x34\x8d\x8b\x68\x37\x8e\xbb\x78\xeb\xab\x97\xec\xb9\xea\xd2\x59\x75\x6b\xcf\x7a\xe6\xd9\x57\xfe\x80\x57\x56\x35\x9e\xd0\xbe\xe5\x3e\xf9\x23\x9e\xb2\xdf\xfa\x8b\xab\xdc\x25\x5b\x4b\x6d\xa7\xb6\x79\x07\xb7\x96\x05\xe5\x96\x57\x27\xe3\x59\x9a\xb6\xf6\x1e\xa1\xc9\xac\xbd\x86\x58\x5e\x64\x2a\xff\x91\x51\x46\x21\x54\x86\x26\x33\x19\xe9\xd6\x2b\x06\x4a\x6d\x19\xc5\x18\xd3\x51\x15\x85\xde\x0c\xa0\x24\x80\x0e\x22\x00\xc4\xc2\x6e\xaf\x28\xa5\x3c\x7e\x90\xf9\xa5\x62\x1a\x39\x6c\x52\x31\xab\x1e\x34\x5b\x99\x2d\xd3\x88\xfd\x9e\x04\x9f\x37\x2d\x22\x44\xf8\x88\x07\xaa\x08\x21\x2e\x6e\xfb\xae\xb8\x68\xdb\xda\x9d\xc9\x68\xc3\xf0\x88\x96\x49\x8e\xdd\x78\xf7\x35\x4f\x5e\x72\x49\xcb\xda\xbd\x6f\x1c\x98\x80\x91\x79\xe7\x36\xae\x04\xcb\x38\xca\xe1\xfd\x5a\xdc\xed\xd9\xec\x37\x77\x7c\xeb\x1f\xd1\xda\x58\xa0\x4d\xc2\x99\x7b\xf1\xe4\x37\x2e\xe7\xde\x3d\x02\x79\x4b\x84\x78\xcd\xd0\x8e\x1c\x68\x0a\xad\x47\x86\xa0\x1f\xb1\x5a\xd3\x18\xd9\x79\x07\x39\x43\x2a\x36\x67\x14\x43\x1c\x44\x9e\xfd\xa8\xc2\xf5\x2c\x40\x36\x59\x58\xe0\x2f\x65\x87\x20\xb4\x1d\x59\xa2\x20\x14\x01\xa4\x27\xe6\xe2\x7a\x72\xdb\x7e\x3c\x43\xdb\xc1\xad\xec\x38\xcc\xed\xda\xc8\xad\xe8\x5c\xb5\xb1\xb3\x63\x07\xb7\x0b\x71\x48\xee\x9a\x2b\xcc\x30\xca\xc8\x8d\x3c\x64\x24\xb6\x6c\x37\x74\x03\xb4\xa4\x57\x4d\x52\x3c\x0e\x86\x84\x1c\x53\x6c\x47\x15\x57\x5c\xb5\x7a\x33\x8a\x18\x4f\x59\xa1\x20\xcd\x6a\xb2\x44\x53\x36\xa8\x39\xb2\xb1\x10\x38\x52\x91\x4d\x94\x52\x76\x97\x98\x64\x0d\xe6\x1b\x12\xa6\x84\x37\x02\xc6\x56\x04\x8b\x21\x1c\x91\xf9\x8b\xfa\x6d\xe8\x37\x73\xb7\xf6\xe7\xe7\xde\xdb\x80\x9b\x9f\xbb\xe7\x1e\x83\xbc\xbd\xb9\x79\x7b\xe7\xd6\xce\x49\x38\xa2\x9d\xc5\x7d\xcb\x3d\xaf\x1d\xc1\x31\x84\xd1\x3c\x4d\xe6\xd7\x08\xcd\x28\x8e\xee\x60\x3b\x5e\x6d\xce\x28\x7d\x4a\x8f\x8a\x6a\xa5\x90\x83\x56\x28\x25\x31\x5a\x59\x0a\x3c\x21\x4a\x45\x16\x61\x51\xc3\x60\x15\x03\x89\xe0\x41\x94\xf9\xac\x46\x1c\x61\xe1\xcd\x2e\xaf\xbf\x2c\x52\xdd\x9f\xda\xf6\x6d\x46\x43\x90\x75\xf6\x09\x02\xcf\x55\x84\x49\xa5\x8a\xa4\x6a\xae\x84\x24\x99\x54\x43\x85\x50\x2f\xc0\x0a\x93\xcf\x4f\xd3\xf6\xa0\x05\xc9\xff\xf2\x70\x16\x3d\xd0\x15\x1f\xbc\x51\xee\x2f\x7b\xb6\xf2\x22\xcf\x98\x99\x8f\xef\x2e\x09\xad\x3c\xbb\x26\x8b\xb5\xe8\x09\xb1\xd8\xf4\x84\xa9\x7e\xd6\x1e\xc9\x72\x7f\xd1\xe6\x3d\xeb\xcb\xa4\x60\x0e\x6f\x41\xfb\xa1\x4e\xd2\x64\x7e\x0f\xf4\xca\x1e\x88\x72\x29\x0a\x29\xa6\x3a\x68\xaf\x6c\x62\x1b\x21\xd5\x21\x51\xa3\x8e\x17\x53\x26\x17\xf4\xd4\x17\xba\xa7\x20\x8a\x31\xe4\xb5\xd9\xe8\x6b\x71\x24\x9b\x87\xb8\xea\xf6\x3e\xfe\x25\x73\xc6\x8c\x6c\x9c\xf6\xc4\xfe\x01\x05\x0b\x17\xb0\x7c\x84\xbc\x69\xfd\xc5\xe7\xfb\xef\x0f\xde\x9b\xfa\xe5\x38\x32\x0e\x01\x21\x7e\x82\xe1\x6d\xe4\x25\x12\x06\x4e\x10\x78\x5f\x12\x4f\x73\x3a\xb6\xa3\x70\x66\xac\xb4\x50\x91\x38\x59\x7e\x62\x84\xda\x44\x49\xe5\x25\x88\xd3\x92\x8f\x46\x6f\x92\x8c\x91\x46\x67\x59\x46\x9d\x33\x89\x11\x31\xdb\xfd\x59\x18\xff\x9b\x05\x1f\x7e\xfb\xfe\x1b\xfb\xd3\xc7\xee\xba\xa5\x29\xd5\x68\x98\x56\x3f\xf4\x48\xfb\x2e\xed\xef\x33\x3a\x3f\xe2\x36\x35\xfc\x71\xe3\x92\x65\x83\x6a\xc8\x78\x88\x82\x4f\x08\xcd\xc8\x43\xc6\x03\x98\x58\x2e\xcb\x90\x21\x03\x1c\x96\xf1\xc6\x10\xd7\xc0\xc0\x1a\x3c\x5a\xac\xa2\xa4\x72\x6e\x90\x14\xe4\xa3\xc1\x93\x4c\x2a\x1c\x1b\x0f\x6b\xa5\x6b\xf2\xd2\xe1\x90\xd1\x04\xb7\xbd\xff\xce\x67\x6f\x3e\x97\x6e\x7b\xab\x63\xcc\xd6\x91\xfc\x89\x6b\xde\x7e\x7e\xa7\xf6\xd5\xd4\xc3\xb8\xb2\xe1\xf3\xfb\xbe\xaf\xeb\x8f\x78\x54\x82\x90\xf0\x3a\xf4\x14\x2c\x45\xd5\xe8\x41\x56\xe3\x24\xeb\xde\x69\xb5\x2d\x93\x46\x58\x22\x77\xbd\x08\x2e\x9b\x52\x12\x4f\x87\x0b\x21\x14\x1e\xb6\x52\xfc\xb2\x04\xd7\x9e\xd8\x15\x85\xe1\x78\x3c\x25\x43\xff\x5a\xb9\xc4\x12\x4d\x49\x72\xb6\x79\xad\x4c\xcd\x7a\xa7\x3f\xa3\x94\x93\x8b\x61\x62\x28\xe6\x72\x59\x94\x54\x9b\x35\xcb\x51\xe2\x24\x66\x5e\x38\x5b\x58\x5b\xcd\x08\x69\xeb\x28\x84\x35\x8b\xcb\x88\x84\x45\x7f\x98\xaa\x4f\xda\x01\x37\xcc\x30\x0f\x25\xbb\xf0\x63\xb8\x02\x1b\xd6\xdf\xf9\xe4\xa3\xda\xbf\xbf\xe9\xd4\xf6\xe3\x4a\x65\x77\x3a\xad\x7d\x89\x63\xda\x11\xec\xdc\xb3\xf5\xa9\xe7\xbe\xc5\xcd\xad\xfc\xfe\x67\x7e\x7d\xdb\x93\x41\x6b\x91\xb2\xf1\xb5\xdf\xe3\xe6\x57\xee\xbc\x6b\xd5\x0a\xa5\x15\xff\x6d\xd1\xad\x37\x2c\x00\x7c\x50\xd7\x09\x03\x59\x17\x62\x7d\x2d\x42\x29\x37\x70\xe4\xb3\x55\x51\x4c\x89\x34\x46\x6e\xb2\x06\xb6\xc2\x44\x42\xc5\x7c\x46\x35\x58\xe2\x71\x48\x7a\x78\x60\x35\xbc\x54\x08\x7a\x00\x97\xe3\x21\x0b\xc0\xd8\xf3\x8d\x71\x70\x6b\xcd\xf1\x94\x23\xa4\x1b\xc1\x90\xff\x08\x79\x73\x28\x22\x1d\x02\x91\xf0\x46\xbc\x00\x06\x1c\x8a\xfd\x2c\xe5\x13\x96\x77\x3c\xc7\x7d\xb7\x6f\xe7\x4e\x1d\x0a\x08\xc0\xc0\x4e\x0b\xf7\x51\x2b\x37\xb2\xf3\x25\xf2\xd5\x7a\x04\x20\x80\xa7\xde\xfd\xb0\xed\xb5\x57\xf6\x1d\xa1\xf7\x90\xf8\xa3\x1f\x1b\xda\x91\x15\x85\xbb\xe7\xe3\x30\x31\x5a\xed\xa0\xeb\x11\x83\x0b\x43\xaa\x0d\x13\xcd\x8e\x39\xfb\xcb\x9c\xf3\x15\xed\xf9\x71\x65\xf2\x64\xed\x25\x43\xfb\xc9\x26\xbe\xe5\xbd\xd5\xb3\xbf\xee\x98\x83\x78\x74\xa8\x6b\x2e\xff\x3d\xf0\x65\xf9\x51\x08\x8b\x34\x87\xa6\xb8\x81\x94\x4c\x75\x78\xe3\xf1\x94\x07\x0e\x00\x14\x78\x4a\x71\x9a\x2e\xe2\x0c\x89\x84\x1a\xe2\x33\xaa\xb9\x20\x1e\x4f\x07\xfc\x22\x76\x44\x55\xbb\x2f\x01\xcc\x66\xaa\x25\x08\xa2\x5c\x11\x12\x7a\xe7\x01\x99\x56\x8a\xc9\x90\x41\x92\x6d\x96\x68\x9b\x24\x23\x73\x54\x15\x5d\x99\xfc\x56\xc9\xc6\x38\xf1\x6c\x95\xfa\x82\x03\x43\xff\xe7\xeb\x7b\x20\xa0\x28\xb9\x15\xfe\xa0\x22\xba\x15\xe1\xa0\x22\xb9\xdb\x38\x89\xf7\x44\x15\xd1\xdd\x66\x10\x05\x4f\xb4\xcd\x0c\xdf\x2d\xf0\xdd\x0e\xdf\x1d\xf0\xdd\x4d\xbe\x93\x9f\xf7\x90\x9f\x6f\xf3\xc2\x77\x1f\x7c\x0f\xc2\xf7\x02\xf2\x9d\x1f\xe1\xe4\x78\xc1\x60\xb6\xd8\x1d\x6e\x8f\xd7\x17\x2c\xa8\xed\xf6\x9f\x32\xa2\x80\x96\x22\x52\xb5\xc2\x27\xbc\x61\x3e\xec\x0d\x9b\x22\x0d\x95\x09\x4f\xa4\x2e\xe1\x09\x1f\xe2\xce\x09\xae\x0e\x5e\xb6\xfe\xda\x4f\xb4\x93\xab\xf0\x5e\xad\xba\x72\x75\x65\xd1\x98\xd5\x6f\xff\xfb\x1a\xad\xc5\xd0\xde\xdc\xcc\xd2\x56\x2d\x2d\xdb\x39\x6b\x2b\x7e\x93\xc6\x64\xb5\xa9\x42\x08\xfc\x81\x30\xaa\x44\x51\xf4\x2b\x66\x2b\xb9\xad\x19\xc5\xed\x56\x9c\xa5\x47\x45\x45\x4a\xa8\x41\x6b\x46\xf1\xb2\x28\x6c\xb9\x39\x93\x2e\x2b\xf6\x93\xfb\x6b\x4f\xa8\x65\xe6\x8c\x52\x15\x07\x13\xa4\x26\xeb\x28\x94\xc5\x89\xaf\x50\x4d\x74\x8f\x8f\x16\xde\x14\x23\x96\x3a\x50\xaa\xc5\x11\x76\x23\xef\x30\xbb\xfd\xc1\x42\x67\x98\x36\xe9\xb1\x49\x29\x93\x47\x06\x03\xd8\x19\xd4\x8d\xb0\x62\x51\xf5\x94\x26\x93\x4a\x19\xc0\xae\xca\x45\x25\x0a\x28\x3f\x73\x96\xf0\xc0\x93\xe0\x8b\x71\x11\x0e\xf3\x59\xec\x18\x33\x5a\x7c\x7e\x4f\x65\xc2\x53\x59\x66\x34\x24\x2a\x20\x89\x55\xd2\xb8\x75\xed\xae\xab\x57\x68\x93\x97\x0f\xbb\x88\x66\xb2\xae\x98\xfe\xc0\xda\xdd\xc7\x0e\x08\x53\x66\xa6\xbf\xb8\x22\x7a\xeb\x66\xfc\xcb\x83\xc2\x2c\x9a\xc5\x32\xe3\x17\xb5\x50\xf2\xaf\x8f\x2e\xd4\xb6\x85\x20\x97\x55\xa8\x4d\xc4\x27\x36\xe0\x01\xe9\x99\x58\xde\x80\xeb\x85\x9d\xf7\xef\x3f\x8f\xf8\x6a\x33\xb5\xe5\x5c\xc8\xd0\x8e\xbc\x68\x2a\x4a\x59\xc9\x25\xf6\xc4\x54\x0e\x6c\x4b\xe2\x2d\x98\xf9\x8c\x62\x8f\x83\x2a\x30\x1c\x25\x4e\x93\xdb\x4b\x9c\xa6\x94\xdb\xa0\x97\xc2\xa5\x0c\x80\xda\x37\x98\x68\xb2\x1f\xa9\x1c\x4b\xf1\x9b\xa8\xfc\x65\xcd\x75\x23\x70\x79\x13\xde\x08\x75\xee\x5a\xcf\x39\x77\xce\x9c\x5d\xbb\x9e\xdb\xb9\xf3\xf5\xfd\xcd\x83\xdf\x93\x97\x5d\xc3\x2d\x6f\xe5\x36\x75\x2e\x6c\xed\xbc\x9f\xf5\x3a\x05\xde\x41\xdc\x61\xf8\x02\xba\x99\x2d\x40\xb4\x19\xad\x07\x3c\x49\x7d\x74\x66\xa8\x2f\x24\xf6\x83\x40\xf9\x18\x0c\x47\x55\x8b\x2f\x1e\x57\xdd\x8e\x33\x0f\x53\x31\xb8\xd5\x42\x27\x65\x6a\x70\x1b\x44\x49\x0d\x02\x6e\x09\xd2\xcc\x79\x6e\x68\x8f\x11\xe7\x07\x77\xc1\x35\x6d\x69\x49\xb7\xb4\x74\x6f\xc8\x09\x8e\x2a\xb7\x73\x23\x7e\x41\x3b\x6b\x63\xe7\xcc\x9e\x7d\x6a\x57\x68\xb2\xb1\xc1\xf0\x36\x2a\x46\xfd\xd0\x12\xea\xb5\xaa\x65\xb6\x4c\xca\xcc\xe9\x6a\x37\x4a\x49\x03\x1c\x39\xee\x91\x12\x1f\xb8\x63\x32\x71\xf7\x2b\xe2\x71\x5d\x1b\x9b\xdd\xd0\x2c\x01\xa8\x48\x4a\x44\xa9\xcd\xc8\x07\x20\x3f\x6c\x16\x15\x62\x08\x85\x1c\x94\x2c\x2d\x2a\x11\xf3\xc7\x64\xf4\x33\x1f\x0c\x85\xe3\x3e\xca\x96\x96\x87\x10\x6a\x80\xe4\x79\x1f\xae\x81\xf8\xb1\xc3\x70\x9d\x38\xb0\x16\x47\xca\xb8\x15\xf8\x1c\x1c\xb9\xf7\xab\x46\x6b\xc9\xc6\xc1\xe7\xc4\xfb\xc6\xce\xd2\x3e\x31\x5b\x93\x5f\xfc\xea\xd7\xda\x89\x8d\x07\xff\xf0\xd6\xb6\xd7\x2e\x9e\xf1\xc6\x23\x87\x3e\xe5\x3e\xc1\xbf\xc4\xf7\x2c\x9a\xfd\xfc\x0f\xbb\x2e\x3c\xdf\xbb\x35\x84\x47\x7d\x58\x7f\xc9\xcc\xab\xda\xf1\xd4\x3f\x69\x7f\xd7\x5e\x9f\xd1\xde\x8a\x87\x3c\xd6\x7e\xb1\x76\x18\x65\xf1\x51\x66\xa1\x19\xb8\xe3\xae\xd7\x99\xe3\x2c\x3d\x99\xe3\xc4\x98\x6a\xb7\x64\x49\xba\x19\x73\x9c\xa7\x77\xe6\xb8\xbe\x38\xaa\x7a\x0a\x45\x29\xcd\xfb\x83\xe1\x0a\x8a\x3b\x56\x0d\x3e\x20\xa1\xb6\x43\x05\x88\x5a\x21\x9e\x81\x33\x4e\xf7\x13\x60\x15\x72\x7e\x28\xc3\x17\x5c\xfd\xf5\x47\x9f\x5f\x67\x0e\x6d\xe8\x37\x68\x44\x45\xdf\xcb\xbe\xb1\xda\x97\x7c\xf1\xdb\xbf\x1d\x78\xe0\xbe\xc7\xee\x17\xb6\xfc\xea\x9e\xcd\x5c\x04\xdb\x71\x6c\xf7\xe6\x53\x91\xab\x2e\x00\x80\xd4\xca\x45\x43\x9e\xc0\x35\xd8\x74\xf8\x23\xe5\xed\xf2\x3f\xbd\xfe\x07\xd0\x97\x4c\xbf\xb8\x51\x10\xcd\xa1\xf8\x79\xc5\x9a\x60\x14\x33\x60\x44\xb8\x88\x10\x12\x13\x2a\xb2\xd1\xab\x56\x10\x53\x5c\xa0\x2b\x9d\x60\xac\x2b\x4e\x37\xd8\x38\xc4\x30\x08\xe1\xa8\xea\x75\x8a\x92\x6a\xb7\x24\xe1\x82\xd9\x98\x79\xa0\x58\x92\x4a\xb0\xbb\x49\xc0\xaa\x5a\x22\x62\x83\x0e\x7b\x94\xdb\x7a\x94\xb2\xec\xdf\x4f\xab\x57\xb8\x19\x5b\xb9\x17\xf3\xcb\x95\x66\x6c\x65\x75\x2b\xd4\xd7\x89\x09\xcd\xc8\x8f\xae\x44\x29\x1f\x62\x9b\x44\xa3\x5a\x4e\x3e\x93\xc6\xc8\x67\x71\x00\x57\x11\x71\x78\xc4\x38\x54\x01\xfb\xa8\xae\x77\x80\xb3\xe1\x03\x5d\xef\x23\xba\xde\xe7\x56\x05\x31\x93\x12\x80\xfd\x50\xf0\xd0\x7e\x0d\xaa\x57\x10\x29\x45\x8c\x13\x67\x91\x83\xa0\xeb\xf3\x4a\x54\x8c\xa6\x04\x20\x88\xe5\x96\xbc\xca\x94\xeb\xda\x64\x4d\xd3\xd2\xb8\x63\x23\x7e\x81\x96\xa4\xec\x5c\xb3\x51\x13\x70\x87\x1e\x67\x36\xb4\x23\x11\xc9\xe8\x62\xea\xa5\xd1\x38\xb3\x90\x48\xbb\x5d\x76\xe4\x88\xaa\x66\x29\x91\x50\xdd\x7c\x46\xe5\x8c\xc4\x46\xf1\x42\xc3\x1b\x9b\x37\x93\xb2\x81\x8b\x66\x33\x13\xe7\x0c\x3c\x25\xbb\xcb\x12\x05\x04\x83\xcd\x4e\x79\xf8\x54\x97\x9d\x41\xd7\xc5\x84\x27\xec\x49\xf0\xcc\x47\xc2\x91\xba\x84\x21\x84\x0f\xaf\xc5\x7f\xba\xfb\x8d\x0d\xcb\x8f\x68\xda\x73\x5a\xc7\x7b\xcb\x70\x70\xdb\x23\x86\x76\xed\x24\x36\x6a\x27\x5b\xb5\xca\xce\xc3\x5c\x0c\x7f\xde\xda\xaa\x1d\xc3\xd5\x48\x8f\x51\x0b\x4d\xa8\x00\x85\x81\xef\x1b\xc3\x30\x15\x47\x0c\x10\x99\x81\x98\x6a\x0e\x25\x80\xde\x9f\x8d\xb4\x0c\xba\x4f\x22\x55\xa2\xb7\x5c\x09\x88\xaa\xbb\x98\x45\xab\xf5\xc1\x74\x0b\x56\x47\xea\x12\xfe\x62\xec\x4f\xd4\x7b\xb8\x97\xd7\xe2\x55\xab\x5e\x59\x7b\xdd\x1e\xed\xcb\xbc\x90\xf5\xd7\xcf\xad\xfc\x66\xf8\x50\x87\x39\xb8\x58\x68\xd2\x1e\xc0\x57\x68\x0f\x6c\xec\x2c\xd0\xe3\xd6\xdc\xe4\x8d\x1b\x7f\x95\x1a\xb7\x00\xd7\x23\x0e\xed\xec\x3a\x21\x94\x08\x33\x00\x1f\x74\x33\xc3\xfb\x89\x8c\xf9\x91\xe8\xd1\xb4\xbd\x30\x60\x22\x96\x8b\x31\x0b\xf8\x0b\x39\x32\x8a\x23\xae\x72\x2e\x00\x06\x95\x30\xfc\x25\x94\xab\xb1\x6a\xa5\x12\x31\x65\x0a\x40\xb7\x73\xab\xde\xc2\x54\x0c\x50\x2d\x62\x17\x15\x99\x36\x99\x4c\x09\x56\x3e\x09\xc7\x5e\xe5\x70\x32\x9f\x62\xd0\xe7\x75\x1b\x4c\x14\xfe\xd7\xe0\xa7\x75\x12\x0d\xba\xe7\xe1\xdd\xa9\xc3\x7d\x3a\xff\x99\x0f\x02\x4a\x6d\x7f\xe1\xe9\xf9\x97\x3e\xf8\x34\x9e\xc1\x9d\xd8\x7a\xf9\xb8\xdd\x0f\x6b\xa9\x3c\xe8\x0f\xde\x64\x32\x2d\xb8\x66\xea\x8c\xc7\x37\x23\x86\xfb\x1b\x2a\x34\x23\x37\x2a\x02\x3d\x04\xfd\x6d\xc1\x1d\xe8\x26\xb8\x42\x96\x2c\xbc\x47\xf4\x02\xd6\x89\xf8\x4a\x4c\x58\x59\xdd\x19\xc5\x1a\x53\x4c\x09\x58\x00\x3f\x11\x48\x06\xbb\x13\x72\x33\x56\x51\x35\xda\xc8\x9c\x43\x32\x6d\xa7\x60\xb7\xf5\x90\x53\xbd\xf1\x9b\x42\x04\xd1\x5c\xb4\xa1\x27\xa9\x29\x8b\x16\xae\x3f\xd5\xde\x9d\xc4\x14\x71\xe8\x99\xae\x13\xc2\x72\x36\x8f\x39\x2c\x76\x6f\xd7\xe7\x01\x61\x7b\x23\xa6\xa5\xc9\x30\x0f\x7c\x14\x8a\xce\xdc\x6e\xc0\x01\xeb\xd3\xf1\x32\x58\x12\x94\xb9\xbb\x92\x49\xc5\x2f\xb6\x09\x46\xa7\x1d\x1c\xf0\x02\x19\x88\x4c\x9d\x2e\xbe\x8f\x5f\x8f\xc7\xd7\xe7\x42\x7e\xa6\xfc\x60\xa8\xf7\x19\x36\x74\x3a\x91\x08\x19\x3c\x99\x84\xd0\xb4\xe9\x09\xed\x77\xda\x3f\xb5\x7f\x69\x1f\x6c\x5f\xcf\x55\x7f\xf1\xea\x27\xef\x92\x49\xe8\xf9\x87\x13\xc2\x72\x63\x09\x2a\x42\x7d\xd1\x35\x6c\x0e\x60\xec\x85\x2d\x19\x5a\x39\x59\x69\x01\xd5\xc8\xdb\x32\x3a\xfb\x6c\x31\x18\x03\x6a\x91\x4b\x8f\xfe\x82\x53\x56\x43\x2c\xba\x22\x51\x4a\x39\x5d\x10\x57\xea\x23\xb6\xf1\x06\xd1\x0f\xf3\x80\x28\x9a\xb3\x20\x49\x14\xaa\x6a\xb4\x27\xb3\xa5\x19\x09\xd1\x9d\x88\xfb\xbd\x64\xfc\x45\x38\x2f\xd6\x5b\x56\x51\x19\x31\x76\x9f\xde\xde\xef\xcf\x1e\x15\x6b\x8c\xc5\x69\x84\xf7\x9b\x8f\x16\xef\x6d\x70\x96\x18\x13\x9b\x9e\xb8\x7f\xe3\x7d\x0f\xee\xbc\xd7\x80\x70\x49\xe8\x01\xb9\x7e\xe4\x35\x7a\x44\xf7\x1b\xed\xd8\xa4\xf3\x6e\xf0\x70\x91\xcf\x5f\x3e\xfe\xee\xfb\xef\x3f\xff\x19\x91\xbf\xa3\xbb\x4e\xf0\x73\x41\xfe\x0e\x65\x19\x42\xa7\x1e\x35\x93\xad\xb4\x29\x8e\x48\x73\x65\x41\x22\x12\x9c\x16\xda\x4b\x4a\x16\x53\x46\xbb\x3f\x49\x07\x9e\x75\xcb\x69\xb2\x2f\x1b\xe0\x20\x62\x75\xf4\x80\xd6\xe6\x7f\x60\xa3\xf6\x9f\x7f\x6e\xbf\xe6\xee\x75\xbf\x6a\x69\xdd\xde\x70\x47\x5c\x88\x04\xcb\xb4\x8f\xb5\x6f\xb5\x8c\xf6\xbb\xc6\xd6\x11\x1f\xbe\xf7\xc6\x6f\x8b\x82\x74\xfd\x67\x75\x6d\xe5\x33\x42\x33\x2a\x42\x95\x68\x25\xd3\xdf\xa5\xec\x1a\xa8\x0e\x5b\x26\x5d\xe1\x09\x92\xfb\x5f\xc1\x38\xbb\x85\xa3\xaa\xcb\x9b\x51\x5c\xb4\x9a\xdd\x27\xd1\x1c\xa5\x4b\x10\xa5\x14\x17\x2a\x22\x03\x8c\x88\x69\x93\xc3\x13\x2c\x66\x14\x74\xd4\xe7\x2d\x0d\x42\x27\x31\xa5\x42\x4c\x71\x3e\x22\x19\x54\x87\x87\x88\x00\x9b\x8b\x8a\x00\xe0\xa0\xf3\xd7\x37\x54\xd4\x11\x2b\xda\x07\x14\xb8\xa2\xec\xcf\x4f\xfa\xe4\xd2\x19\xb3\xa2\x23\x26\x62\xdb\x77\x53\x1e\x8e\x0f\x5a\x37\x4b\x7b\xde\xdb\xfa\xca\xfa\xa7\x0e\x3d\xf6\xee\x8a\x68\xe9\xee\xc9\x0f\x5e\x38\xff\xfc\xa6\x07\xcb\x6f\x5e\xb4\xfa\x43\x2c\xe3\x68\x59\x70\xf3\x40\x6d\xe6\xfc\x89\xdb\xd6\x2c\x59\xfd\xc8\xac\xf3\x7f\x89\xcf\x6a\x3e\x77\x48\xff\x24\xfa\xff\x24\xb6\xfb\xea\xae\x13\x06\xb3\xb1\x04\x15\xa2\x6a\x74\x03\xd3\xfe\x3a\xe8\x99\x51\xbd\x30\x5b\x8d\x55\x6c\xa3\xa3\x00\x72\x2e\xa2\x9b\x6d\xf1\xc7\xa9\x11\xe0\x75\xab\x3e\x37\x50\xde\x44\x71\x14\x9a\x53\xb7\x19\xf8\x40\x01\xe5\x3a\x66\xbd\x76\xf8\x02\x51\x4a\x19\x8c\x70\x64\x45\x28\xaf\xb1\x13\xd3\x2d\x6f\xf2\x43\x71\xf6\xea\x79\xcf\x2c\x11\x1d\xbc\xf5\xfb\xb1\xc3\xc9\xbd\x3b\x83\x60\x94\x97\x79\xb7\xb3\x9b\x77\xf2\xdf\x3d\x44\x64\x8f\x1e\x80\xd3\x69\x44\x4c\x15\xac\x4c\xb4\x04\x58\xe3\x3f\x39\xdb\xf8\x0f\xe3\xa8\x12\x02\x53\x8d\x32\x78\xc9\x22\xe5\xff\x53\xb0\x98\x12\x6c\xb4\x21\x87\x60\x13\x89\xc7\xa7\x04\xc4\x36\x64\x72\x7a\xe9\x96\x86\x41\x4f\x55\x7a\x8b\x73\x6d\xff\xbc\x0d\xb4\xba\x2f\xbf\xef\xdf\x77\x38\xc8\xfa\xfe\xdd\x75\xf3\xad\x9b\x9d\x1c\x97\x83\x26\x1a\x19\x5a\xb1\xac\xa5\x75\xe7\xfd\xff\x2f\xea\x5f\x08\xf3\x30\x86\xa0\x16\x2f\x8a\x76\xb1\x2e\x50\x95\xf9\xf3\x08\xca\x61\x32\x8f\xa0\x8d\x52\x67\x44\xc1\xdc\x2c\xf6\x66\x54\x97\x27\x93\x8a\x02\xa5\x52\x14\x5b\xa2\xc4\x69\x57\xea\x0b\x0e\xb8\x95\x57\x1a\x90\x37\x6a\x15\x14\x5c\xeb\x54\x42\x6e\x05\xbb\xd5\x3e\xee\x1f\x04\x62\x8e\xb8\xdc\x3f\x28\xd8\xdd\xc6\x61\x97\x27\xaa\xf4\x71\xb7\x45\xfb\x84\x3c\x51\xee\x59\xcc\xb9\x42\x7d\x18\x66\x0d\xab\xa1\x3e\x14\x1e\x85\x54\x39\x48\x8b\xf6\x0c\x62\x9b\xd9\x0d\xe4\xb5\xb9\x95\x28\xcf\x5b\x09\xc1\xdf\x40\x03\xb3\x7e\x63\xa4\x8c\x37\xf9\xbd\xb9\x85\x19\x86\xeb\xe6\x71\x7f\x2e\x7c\x6a\x1d\x5d\x99\xd7\xb0\xb5\x66\x6f\xc4\x3f\xac\x76\xf2\x94\xf2\x25\xcb\xf7\x8d\x0f\x71\xb0\x50\x2f\xd9\xd6\x5c\x3f\x63\xcd\x18\xfc\xb1\xf8\xe6\xea\xbb\x61\xa5\x5e\x4f\xc7\x6e\xbc\x60\x7c\xc3\x9a\x89\x98\x33\x7a\x7d\x74\xcd\x36\xdf\x76\xf7\x45\x4f\xee\x20\x7a\x62\x5a\xd7\x09\x7e\x8b\xd0\x8c\xca\xd1\x65\x28\x15\x81\x0c\xb4\x39\x03\x2e\xb3\x2a\x5a\x32\x69\x6f\x20\x62\xa5\x3b\xdf\xe6\x8c\x58\xcd\x51\xdd\x36\x2b\x70\x64\x94\x02\x37\x25\x62\x33\x49\xe0\x4f\x79\x24\x30\xce\x90\x1a\x28\x12\x25\x15\x95\x26\x93\xaa\x33\x22\x4a\xaa\xc9\x93\x4c\xaa\x56\x11\x32\xb6\x10\x4a\x6f\xa8\xab\xc5\x94\xb5\xd7\x6f\x22\x53\xf7\xca\xe1\x84\x37\x52\xca\x0c\x31\x88\x48\x4f\xbb\x7a\xd5\xec\x05\x5f\xbe\xb4\xf8\xe9\x0b\x47\xcf\xbe\xbd\xe9\x7b\x9c\x5c\xf2\x80\xf6\xd6\xfd\x1b\x2e\x78\x6a\xce\xba\x3f\xfd\xfe\x9f\x38\x3a\x7b\x55\x85\xad\xf0\x96\x4b\xd6\x6c\x2d\xaf\xde\x50\x53\xb8\x75\xd7\xa6\x17\x2e\xba\xa4\x32\xb6\x6d\xfc\x53\x48\xd7\x7d\x1b\xe0\x1c\x2c\x40\xa9\x32\x32\x27\xde\x9c\x49\xf9\x58\x3c\x38\x6d\xb3\x96\xf9\x1c\x51\x5a\x25\xd6\x07\xaa\xc4\x4a\x1c\x19\x88\xf6\xa8\x41\x29\x93\x72\x06\xa1\x08\xc1\x46\x3b\x7c\x21\x95\x2f\xcb\x35\x89\x28\x81\x2a\x31\xe8\x15\xac\xb8\x45\xd5\x13\x4c\x12\xdd\xa3\xc8\x50\xff\x96\xeb\xae\x90\x28\xa5\xf1\xe2\x4a\xaa\x57\x68\x8c\xd5\x18\x29\x1b\xbd\xef\x85\x7b\xb6\xb4\x3c\x7a\xff\x52\xdc\xf0\xc3\x79\x77\x5e\x3a\xfc\xa9\xdf\xbe\xfc\x3f\xbf\x59\x71\xfd\xc9\x8f\xbf\x4d\x6c\x9f\xda\x3c\xa3\xf9\xe2\x4d\xbb\xb6\x16\x57\x6d\x98\xd0\xb2\xe6\xd7\x83\xcc\x7d\xee\xbc\xfc\xc1\x3d\xfa\x7c\x0c\x09\xa1\x19\xf5\x27\x7b\x14\xeb\x65\x3e\x31\x36\x1f\x9a\x23\x29\xb6\xd1\x36\xe4\xc6\xa3\x6a\x8d\x23\x03\xcd\x7d\x6b\x8c\xa2\xa4\x06\x2b\xc8\x75\xb4\xf2\xa2\xa4\xe2\x1a\x28\x11\x49\x85\xab\xaa\x89\x8e\x74\x17\x8b\x52\xda\xe9\x09\x42\x15\xc9\x8f\x4c\x25\x7b\x38\xc1\x4b\x30\xfe\xc8\xbc\x36\xbe\xd9\x77\x71\x99\x7f\x58\xed\x79\x17\x56\x0e\x58\x31\x7c\xd7\x84\xd8\x9a\x5e\xa6\x79\xf1\x05\x25\xcb\x2f\x18\xdf\xb0\xba\xac\xf6\xb9\x4b\xfb\x64\xe7\x4b\xed\xe6\xab\x85\x66\x24\xa2\x08\xf1\xf5\xa1\x76\xdc\xab\xab\x8e\xb0\x25\x93\x2e\x0c\x11\xe7\x57\x2d\x34\x67\x51\x6b\x92\x17\x8a\xb4\xfc\xac\x44\xbe\x84\xac\x83\x51\xca\xa4\x4a\xa0\xca\xb4\xa4\x90\xb5\x6b\x2b\x91\x88\xbf\x6f\x71\x99\xbd\x60\xae\x41\x8c\xd8\x9e\x54\x0a\xc5\x36\x64\x96\x00\xf2\x15\x66\x0c\xf9\x10\xf2\xc8\x6d\x5d\x29\x22\x2a\xa3\x34\xb7\x26\xe1\x32\xe3\xd5\xb8\x14\x9b\xde\xf9\xeb\x7b\x2b\xaf\xd3\xfe\xa8\x75\x6a\x7f\x3a\xb0\xf7\x05\x5c\xd5\xf2\xe8\xd4\x24\x1e\xa4\xfd\x6b\x9f\xca\x55\x62\x17\xae\x7a\xe8\xce\x03\x49\x32\xb5\xcd\x4f\xe3\x2a\xec\x39\xfa\xfe\x7e\x32\xfb\x96\xf7\xb3\x78\x87\x0e\xa1\x89\xc5\xd0\xce\x10\xa5\xca\x8f\xa1\xfd\x48\x70\xaa\xd7\x18\x5a\xef\x11\xa9\xee\x51\xa8\xd3\x63\x4f\xb0\x07\x8b\x35\x19\x74\x78\x39\x8a\xa3\x5b\x99\x64\xa8\x36\x67\x68\x59\x07\x6c\x44\x7f\x0b\xa8\xe6\x10\x6d\x27\x67\xb3\x65\x09\xfb\x2b\xbc\x19\xa5\x82\xf6\x7e\x35\xd6\xc4\xe3\xaa\xc7\x41\x53\x71\x15\x7a\x5e\x56\x29\x16\xf7\x19\x78\x5f\x28\x4c\x53\x71\x48\x8d\x84\x80\xab\x41\xed\x5f\x4d\x1d\x99\x70\x69\x1f\x7f\x52\x75\x93\x93\xea\x64\xa5\x5a\xa0\xcc\x2b\x72\xba\xdc\xfb\x53\xc4\xfd\x8b\xff\x79\xe4\xd3\x65\x0e\xc7\xc9\x31\xc3\x63\x8d\xb3\xcf\xc0\xd9\xcf\xb8\xfa\xaf\x1b\xb1\x09\x34\xfb\xd2\x93\x7f\xec\x9d\xb3\x9f\xf5\xd5\x1b\xca\xe2\x4f\xcb\x7e\xb2\x73\x41\xf5\xcf\xe8\x5c\xd0\xb7\x47\xe7\x82\x7d\x7a\xe3\x82\xff\x46\xdb\x82\x9f\x68\x56\xf0\x53\x4d\x0a\x68\x8e\x83\xdc\x43\x41\x68\x46\x41\x62\xc5\x81\xb3\xe4\xd0\x7d\x08\xb3\x2d\x93\x16\x25\x3f\xb9\x85\xa2\x39\xdb\x92\x20\x2f\xe5\x27\x3b\x32\x29\x17\x64\x2b\x5c\xa2\x25\x4a\x89\x76\xac\xa2\x94\x32\xf3\x60\xaa\xe9\x24\x6e\xaa\xc3\x0f\x34\xae\xaa\x24\x8a\x92\x6a\x45\xe0\x39\x29\xc6\x5c\x49\x3b\xb0\x1d\x53\x2b\x9d\x18\xb0\x62\x84\xf6\xa9\x28\x43\x57\xe3\x08\xe6\xfe\xb4\x7c\xd4\x7d\xb7\x68\xeb\xb6\x3d\xbc\x6a\xfe\x09\xdc\x7a\xc3\xf3\x0b\xfe\xa1\x7d\x4f\x93\xf1\x4d\x0f\x8f\xd5\x66\x1e\xfa\xb0\x08\xf7\xdb\xd8\x79\x2c\x5a\x86\x23\x88\x43\x48\x0b\x0a\x6e\xc8\x9d\xf6\x81\xca\x4f\xc6\xd4\x20\xc5\xd4\x42\x0b\x05\x55\x79\x8f\xaa\x41\x31\x4b\x48\xef\x62\x78\xa9\x20\x83\x46\x95\x88\x29\xa3\x41\x4a\x52\x70\x94\x3d\x89\x54\x54\x48\x4c\x52\x97\xb7\x0c\x36\x47\x4c\x78\x8a\xb1\x3f\x31\x8c\xf3\x24\x30\x13\x8c\x15\xc4\xd6\xce\x7a\x77\x95\x4e\xfc\xf2\xfb\x43\xfa\xda\xcc\x96\x3e\xd1\xaf\x0e\x6a\x97\x9c\x3f\x70\xf5\xe5\x0b\x6e\x4d\x4e\x28\xe8\x57\x52\xd2\xaf\x3a\xd2\xa7\x4a\x68\xd2\xa4\x7b\xae\xaf\x0d\x37\x2f\xe2\xe2\x1d\xd3\x1e\x7d\xe2\xec\xc5\x1b\x36\x2c\x3e\x4f\xb9\x5b\x5b\xde\x38\x30\xde\x18\x5f\x35\x78\xc8\x4a\x84\xb8\xae\x93\x5d\x5f\x09\xb2\xd0\x8c\x2a\xd1\x00\x62\xaf\x81\x3f\x11\x65\xf2\x51\x71\x27\xd4\x0a\x73\x46\xf1\xd2\x56\xe5\xa5\x47\xd5\x2a\x11\x0a\x69\x88\xf3\x50\x20\xd1\xa6\xe4\x55\xa5\xa2\xa4\x44\x92\x4a\xad\x98\xb2\x5a\xc0\x99\x2a\x20\x13\x44\x6a\x45\x54\x94\xda\x2d\x56\x0f\x2a\x28\x85\x24\x39\x2f\xaa\x18\x2e\x20\x5f\x07\xf2\x5f\xf2\xf9\x13\xf5\xc3\x81\x06\x12\x6e\xa1\x09\xfb\x72\xf3\xc4\x15\x91\x32\x1d\x85\x53\x69\x34\xd6\x0e\x1e\x78\x4e\xe5\xab\xb5\x0e\x73\x78\xf4\xc3\x95\xe3\xe2\x8d\xfd\xca\x03\xb5\x65\xda\xa7\x77\xdf\x72\xe5\x95\x2b\x07\xfd\x42\xfb\xa2\xa2\x36\x80\x1f\x26\x33\x9f\x30\x81\x7f\x79\x75\xa0\xba\x41\xfb\xd7\xb8\xf0\x90\x39\xc7\xea\xfb\x06\x56\x5b\x63\xda\xf2\x97\x56\x5f\x7e\xf3\xcd\xf3\xc7\xae\x5b\x8c\x57\xd6\x75\xca\x03\xa2\xd5\x03\xa6\x5d\x7e\x05\x9c\xcb\x9d\x9a\x2c\x8c\x16\x9a\x90\x0f\x9d\x47\x2b\xa8\xba\x11\x6f\x38\x62\x58\xf1\xeb\x34\x1b\x0a\x0f\x0d\x31\x88\xf4\x24\x1e\x54\x00\x47\x55\x07\x11\x2b\xa2\x9c\x04\xe7\xc9\xad\x93\x67\xb8\xc5\xd3\xc9\x33\x44\x16\xe2\xae\xd8\x99\x5a\xba\xf2\x89\x96\x67\x9f\xb5\x39\xe2\x6d\x57\xbf\xfb\x1a\x5e\xc9\xbd\xdd\x39\x72\xf5\xaa\xfd\xc7\xb8\x41\x3f\xbc\x85\xff\x36\x65\xcc\xf9\x17\xbd\x8a\x30\xeb\xd7\x50\x82\x4a\x88\x97\x07\x39\x41\x5f\x22\x25\xb1\x10\x0f\x58\xa1\xd9\x00\x03\x25\x3a\x29\xa1\x48\xb2\x12\xaa\xb8\x7c\x8e\x4c\x8e\x93\xc7\x09\x01\x12\xde\xe0\x92\xa8\xa6\xd2\x05\x85\x6a\x86\x62\x43\x1b\x4d\x9c\xf7\x16\x5a\xe8\x59\x35\xbd\xf7\xe4\x59\x34\x9e\x90\x57\x2e\x9d\x0d\x22\x1c\xec\x59\x29\x4d\xd6\x77\xaf\x26\xc3\x3c\xaa\xd0\x75\x2c\x52\x02\x93\xe8\xa3\x4f\x22\x10\x53\x8b\x6c\xb9\x60\x09\x15\x76\x55\x74\x2e\x8c\x95\x95\xcc\x85\x08\xb8\x2a\x36\x97\x52\xf1\x59\x32\x97\x00\xed\x40\x81\x8a\xc0\x4b\x57\xa5\x00\xfd\x5b\xb3\xc8\x66\xd4\x7b\xb0\x84\xcd\xc8\x9d\x0d\x41\x9c\x61\x6a\xdf\x9f\x35\xaa\xef\x88\x58\xbc\xb7\x09\x76\xcc\xd3\x3e\x0f\x6d\xf6\xd6\x8f\xe4\x1f\xd4\xe7\x09\x31\x76\xc8\x13\xd9\x90\x1f\xcd\x61\xf1\x39\x72\x87\xd2\x18\x59\xbb\xa1\x71\x14\x6f\x4c\x75\x09\x34\x6a\x62\x3d\xaa\x72\x76\x26\xcc\x85\x78\xca\x62\xd5\x61\x39\x29\xab\x25\x4b\xa1\x68\x75\xab\x92\x13\x42\x2b\x14\x63\x00\x10\x4b\x3d\x13\x4d\x14\x71\x44\xcc\xaf\xb8\x94\x89\x32\x4e\x3b\xb3\xf5\x84\x1d\x54\x1b\x6b\x02\xee\xe0\x97\xea\x89\x20\x8c\x76\x75\x9d\xe0\x5a\x85\x26\xe4\x42\x31\x86\xfe\x35\x9a\xe9\xb9\xc7\x8a\x5b\x3f\xf1\xaa\x48\x0c\x01\xa3\x83\xd6\x3e\x62\x91\x3a\x19\xfa\xb9\xa6\x99\xc2\x8a\x5d\xa9\xa6\x29\x35\xb3\x0a\x42\x57\xd5\xef\xd8\x84\x47\xf1\xe6\x8e\x93\xb3\x67\xb9\xcc\x77\xd9\xe5\xdd\x64\xff\x9b\x10\xe2\xc6\x08\x4d\xc8\x86\xce\x61\xf5\xb0\xd8\x90\x51\xac\x71\x4a\xa0\x21\x18\x32\x8a\x29\x8e\x15\x3b\x60\x50\xa1\x3d\x2c\x97\x65\xcb\xb0\xc6\x53\x9c\x25\x8b\x40\x45\x71\x72\xf9\x50\xff\x01\x89\x3c\xea\xca\xa6\x1d\x3b\x70\xc7\x8e\x1d\x0b\x22\x7c\xbf\xf2\x2b\xae\x28\xef\xf8\x30\xb2\x00\x61\x64\x45\x88\xeb\x00\x9c\xd7\xa5\x14\xf3\xa3\x88\x31\x05\x25\x54\xab\x39\xd3\x16\xb0\x8a\x66\xb0\x79\x15\x07\x4d\xb6\x52\x1f\x34\x14\x80\xc0\xb0\x17\x47\x15\x43\x9c\x28\x1c\xc5\x14\xa7\x6e\x68\x08\x40\xc0\xb4\x55\x97\xea\xf1\x25\x93\x2a\x0f\xf0\x0e\x73\x52\x8f\x68\xf9\xc5\x84\xe8\xcb\xd6\x9d\x54\x8a\x11\x11\xa2\x5a\x56\xc7\x92\x59\x05\x91\x74\xb4\xa8\xff\x00\xf7\x5c\xfb\x75\xcd\x45\x91\x74\x34\x34\x60\x80\x93\xdb\x78\xe3\x3d\x36\x6e\x4d\x67\x58\x6a\x1c\xb2\xfc\x6e\x5b\xe7\x2c\xee\xff\x27\x35\x0e\x21\xb2\xf8\x04\x42\xdc\x7e\xa3\x8c\x44\x54\x80\x66\xd3\x5d\x51\x5c\x31\xc5\x9a\x50\x65\x4b\x46\x31\x43\x15\x1a\x19\x39\x19\x36\x6d\xc7\x25\x49\x60\xaa\x3a\x00\x87\x42\x23\x3b\x8a\x29\x9e\xb2\x03\x70\xd7\x6e\xb1\x44\x01\xa0\x0f\x08\x1e\x98\x83\x4c\xdd\x0f\x76\xdb\xe1\xd8\xf8\xb3\xa7\x08\x8a\x57\x1b\x29\x3c\x45\x5e\x32\x6f\x64\x65\xfa\xa3\x8f\xd2\x53\xaf\x5d\xf6\xf8\xb4\xb1\xd3\xaa\x4a\xf9\x86\xd9\xd7\x94\x73\xfd\x3a\x3e\xbb\xbf\xb3\x95\x9b\xb9\x78\xde\x59\xbe\xc5\xd5\xf4\x7e\x73\x6b\x8d\x32\x72\xa0\x28\x52\x6c\x31\x22\x3d\x81\xbf\xc1\x99\x3d\x43\x80\xb2\x35\xda\x68\x82\x08\x8b\x90\x77\xf6\xe7\x05\x91\xca\x2a\xf6\xa6\x9a\xa6\x8c\x1f\x31\x7a\xe6\x8e\x4d\x9b\x8d\xbb\x7f\xb8\x68\xce\x2f\x7d\x6b\xc3\xbb\x99\xec\xe8\x80\x9c\xfa\xed\x3a\x93\xb1\x37\x91\xa0\x46\x43\xa1\x35\xa3\x27\x27\xc8\xeb\x68\xc8\xbb\x08\xe8\x22\x52\x45\x80\x47\x28\x32\x58\xa2\x4a\x11\x4d\x5c\x91\x93\xc5\x98\x57\x82\x0c\xd3\x51\x44\xa4\xa0\xcb\x9d\x4c\x2a\x5e\x31\x65\x74\x84\x20\xbe\xa0\x67\x33\x10\x91\xe6\x4a\x21\x45\x36\xe7\x84\x63\x42\xcc\x6f\x74\x57\x97\xdf\x02\x4f\xdc\x9b\xe6\x67\xb3\xfe\x76\xad\x5f\xdf\xbd\xef\x9d\xed\x2f\xbf\xff\x9b\x65\xf8\xe5\xce\xab\x8c\xb2\x56\xcf\x1a\xdb\x7d\xbe\x62\xec\x8e\xa9\x07\x5a\xa0\xd9\x5d\xc7\x44\xaa\x7f\xba\x4e\x18\xdf\x15\x9a\x50\x19\xba\x96\x9e\x55\x68\xb3\xac\x14\x24\x54\x83\x05\x08\xb9\xc9\x95\x54\x2d\x52\x22\x91\x47\xf8\x44\x34\x91\x99\xe1\xd6\x6d\xb4\x54\x97\x1c\x59\xd9\xad\x7a\xdd\x19\x22\x60\xfa\xe0\xa8\x6a\xe6\x45\x49\x29\x65\x2c\xf7\x7e\xa8\x5c\xf5\x11\x0d\x65\x10\xa5\x36\x9f\xbf\xb0\x48\x6f\x91\x44\x04\x64\x7d\xdd\xe9\x4c\x4f\xa5\x95\xba\xc2\xfa\xf4\xa1\x7b\xdb\x16\x5e\xbb\xe5\x9e\xf4\xc6\x90\x35\xf6\xd4\x02\x4d\x9b\x68\xad\xdb\x77\xed\x81\xe7\x40\x77\x0d\xd5\x3a\x52\xfb\xb8\xe6\xce\xa1\xb7\xdd\x76\xe0\xb7\x5c\xf2\x54\xfb\xe6\x49\xd3\xf7\x4f\x9b\x79\x90\xea\x56\x98\x5b\x39\x5a\x42\xad\x7e\xa5\xe8\xf4\x69\x29\xde\x58\x96\x8e\xed\xb4\x99\x91\xfb\x28\xc2\x7d\x84\x5c\x0d\x4c\x29\x02\x84\x04\x40\x19\xe3\x95\xd4\x82\x22\xb0\x00\xa1\x34\x0c\xa6\x16\x2c\x28\x29\xfd\x91\xa9\x89\x03\xeb\x1b\x7a\xcc\x6e\xcb\xc6\xd4\x22\x32\xbb\xb4\x85\x77\xc6\x77\xcf\x3b\x6d\x7a\xcf\x1c\xa0\xd3\xfb\xf5\x07\xdc\xe0\x1f\xde\xc2\x9f\xb9\xd6\x99\x7f\x71\xe1\xfe\x69\x33\x5f\x62\xfa\xcd\xf8\x91\xd0\x8c\xfa\xa2\x55\x4c\x4f\x87\xf3\xba\x2a\x29\x8e\x04\xd8\xf2\x45\x71\xe2\x8e\x05\x72\xe9\x80\xbe\xac\x00\xa1\x2f\x65\x9c\x08\x3b\x80\x95\xad\x80\xd2\x32\x40\x5a\xa0\x2f\xab\x3e\x08\x23\x2a\x7d\x0b\xc4\x94\xc7\xe1\x85\x53\x1a\xc8\x11\x18\xf8\x92\x4a\x85\xd4\xc6\x0b\x16\x6b\x2e\xd9\x31\x0c\x27\x4a\xfd\x3d\x15\x5d\x1d\xf9\x64\xcc\x57\xe5\x74\x33\x31\xc7\x66\x4b\x14\xde\xc8\x99\xfa\x56\x0b\x4d\x6c\x1b\x3f\x64\xda\x6e\x29\xbf\x15\x0b\xa9\x7d\x9d\xdb\xb9\x57\xc9\x46\x77\x1e\x42\xb8\xeb\x75\xa2\xdb\x21\x0e\x3f\x9b\xf6\x11\x84\xdc\x0d\x0d\x91\x79\x2d\x50\x79\xce\xb1\x3c\x8e\xe1\xa8\x1a\x74\x10\x19\x06\x1e\x4b\x90\x9e\x59\xb7\x83\xe5\x71\x82\xa2\xa4\x5a\xec\x64\x6a\x1c\x11\xb7\x45\x49\x45\x14\x55\x14\x84\x1d\x4e\x59\xcc\x01\x00\x82\xea\xc8\xfc\xd3\x9b\x4c\xb9\xc3\x65\x95\x8d\xb1\xc6\xb1\x0d\xdd\x5a\x4c\x69\xdf\x5e\x12\xd7\x5e\xf4\x5d\x74\xa5\xf0\x49\xf7\x1e\x53\x03\xb4\xdd\x61\xc4\xf6\xce\x50\x27\x34\xa3\x52\x34\xff\x34\x36\xc4\x42\x0b\x5c\x24\x27\x19\x7f\x98\xc6\xd1\xd9\x96\x95\x52\xb4\x9c\x8d\x91\x35\x95\x32\xfe\x96\x80\xce\xdf\xe2\xf4\xd2\x9e\x8e\x48\x4c\xd9\x44\xe0\xa8\x29\x84\x9e\x64\xc1\x6e\x3b\x44\x26\x90\xaf\x45\xeb\xf2\xf7\x05\x26\x51\x37\xb6\x70\xb8\xe8\x3d\x2f\xba\x76\x15\x99\x0d\x2b\x03\xe9\xd8\xbe\xe0\x62\xa7\x79\xad\xd3\xf3\xf4\x93\xfc\x14\x5a\x04\x42\xfd\x2b\x62\x2f\xce\x14\x9a\x90\x13\x8d\x65\xe7\xd0\x42\xcf\xa1\x62\x4a\x60\xa2\x45\xd0\x51\xd5\x29\x41\x07\x35\x23\xd0\x4c\x64\x80\x60\xda\xe8\x14\x25\x5a\xab\x63\x11\x41\x45\xd0\x9e\xd2\x36\x56\xc9\x82\x59\x6f\x43\xec\xf3\x8a\x7b\x3f\xe1\x06\x71\xb6\xdd\x9f\x76\xbe\x67\x16\x9a\x3a\xd6\x15\x3c\x57\xc9\x2d\x3f\xd5\xce\x2f\x69\x5d\xdc\xb9\x35\x8f\x5f\x16\x7a\x10\x4b\x28\x80\x2e\xd0\xab\xe9\xf2\xea\x03\xd3\x1e\x87\x85\xf8\x79\x1e\x4b\x96\x77\xc8\xe1\x85\xd2\x22\x07\x94\xd0\x29\x72\x1c\x2a\xf4\xc9\x45\x20\xb2\x58\xb5\xf0\x64\x49\x3d\x8e\x33\x14\x8c\x41\xa3\x9f\xf2\x30\x07\x11\x94\xfc\x0a\x31\x09\xf7\xdf\xba\xc5\xd6\x79\x2b\xb7\xb2\x58\xfb\xfd\x96\x07\x4f\xab\x0d\x5b\xa4\x6d\xd9\xaf\x6c\xc6\x63\x77\xb2\x18\x91\x71\x25\xe4\xb7\x22\x68\x03\x3d\xc9\x64\xe3\xa9\x3b\x40\xcc\x6d\x48\x49\x5a\xf2\xa3\x46\x56\x87\x4c\xe6\x61\xb5\x64\xa3\x46\x01\x2f\x50\x0a\x42\x5d\x94\x18\x8f\xc3\x62\x5b\xe2\x29\x27\x74\xa4\x70\xba\x2c\x51\xc5\x14\x6f\x1b\xe1\xb4\xb3\xe8\x11\x74\x57\xe6\x81\x93\xce\x49\x9b\x80\xaa\x56\x87\x28\xa5\x50\xa0\x38\x99\x4c\xaa\x46\x8b\x98\x75\x5a\x13\x71\x7f\x5d\x5e\x2b\xa8\x3a\x63\xf7\x5a\x39\x3a\xf5\x83\x2b\xb9\x23\x9d\xc7\x39\x63\xe7\x49\xae\xb2\x33\x76\xeb\xeb\xb9\x32\xb9\x8d\x7b\xe9\xec\x57\x5f\xbd\x59\xfb\xf0\x01\x6d\xc7\xe6\xc5\xab\x72\xc5\x71\x7f\x24\xf3\x5f\xd2\x75\xc2\xf0\x1e\xe4\x64\xcb\xd1\x35\x94\xcf\x5b\xb1\x50\xa3\xa3\x28\x9e\x92\x9d\x80\xee\x0b\x58\x58\x6c\x22\x62\xc9\x66\xd5\x19\x9d\x86\x9f\xba\x83\x4a\x01\xeb\xa2\xc0\xa4\xb5\x5f\xa4\x16\x79\x81\xd8\x66\xb3\xf3\x11\xd6\x43\xc1\x92\x44\x6a\x44\x16\xa5\x36\x23\xca\xe6\x98\xa1\x0a\x52\x86\xf4\xac\x31\x52\xa6\xcf\x2d\x2b\xb7\x07\xa2\x48\x19\x5a\x82\x2f\xc7\xe3\xf1\x28\x3c\xef\xbd\xfd\x7f\x38\xdb\x3a\xf2\xb3\x7d\xef\xa7\xaf\x9f\x7f\xe9\xdc\x3d\x97\x5d\x32\xef\x46\xed\xd4\x3f\xff\xa5\xfd\x07\x1f\xc1\x75\x78\x9a\xf6\x2b\xed\x37\x7f\xd4\x3a\xf7\xef\xc7\xfc\x5f\x1e\x6b\x5b\x7f\x13\x76\x68\xff\xba\xe5\xae\x3d\xbb\xbe\xc1\x82\x76\x8a\x9e\xd3\xc5\x9a\x6c\x98\x01\x76\x96\x1f\x15\xa2\xc5\x0c\x11\x63\x4f\xa8\xb2\x19\xf0\x8c\xe0\xfb\x1a\x13\x20\xc3\x0a\xe3\xc4\x94\x11\xb2\x1d\xcf\x25\x1f\x58\x5c\x32\x8e\xaa\xbc\x33\x1e\x57\x03\x52\x46\x35\xd8\xe3\xd0\xf5\xaa\x80\xe5\xa6\x8b\x89\xc5\x23\xbb\x44\x49\xb5\x51\xfb\x42\xb5\x20\xea\x91\x70\x10\xb5\x46\xe5\xc4\x62\x44\x5e\x19\x19\x88\xb1\x88\x1a\xdc\x06\xd1\x89\x71\x1f\xd1\x5d\xbe\x18\x97\x62\x61\x77\x27\x2e\xd3\x3e\xef\x42\x4a\x87\xf6\x87\xe7\xf1\xbc\xe7\xf7\x70\x12\xbe\x4c\x7b\x98\x2b\x3f\x89\x2b\x65\x7c\x40\x1b\x13\xd4\x7e\xfb\xcd\x7f\xb4\xdf\xca\x5a\x1f\xfc\x7b\x2f\xae\xf9\xb7\xb6\xaa\x9c\x1f\xe5\xf9\xb0\x73\x47\x25\x5e\x8e\x97\x56\x12\x79\x50\xc2\xec\x7b\x11\x8d\x62\x98\x6a\x80\xc9\xf2\x7c\x06\x7a\xb8\x03\x87\x9e\xe9\xa8\x6a\x75\x40\x94\xc5\x26\x02\x35\x8d\x87\xc8\x35\x13\x44\xd7\x11\x28\x5b\xd5\x0e\x3d\xdc\xfd\x0d\x3e\x8a\xca\xca\xb2\x40\x96\x50\x52\xd6\x34\x43\xc2\x98\x81\x89\x95\x6b\x3a\xd5\x7e\x78\xe1\x55\x28\xfb\x7e\x58\xe3\x9e\xef\x57\xcc\xb1\x9f\xf9\xf6\x14\x26\xaf\x3f\xc3\xfb\x47\xd6\x5f\x78\xff\x05\xe4\xfd\xc3\xf6\xce\x19\x67\xde\xe9\x9a\xb9\xfb\x72\x41\xfe\xe1\xc4\xe1\x2b\xae\xa1\xef\xd7\x64\x7e\xad\xd0\x84\x8a\x88\x5f\x5f\x98\x3f\xf5\x2c\xc0\xbd\x38\xa6\xc8\x47\x89\x9d\x6f\x65\x7a\xc8\x2a\x67\x8b\x3d\x74\xd0\x7b\xa1\xa8\xb8\x92\x6c\x30\xe4\x6f\xba\x0f\xa6\x47\x1e\x34\x7f\x60\x89\x91\x13\xaa\x63\x8b\xba\x90\x85\xcf\x1b\x20\xd7\x74\x2a\x72\xe5\x45\x90\xec\x7c\xc1\xb5\xce\x0c\x43\xa5\x7a\x08\xf0\x4d\x22\x1a\x8c\x7a\x10\xf2\xa2\x98\xce\x9f\xaf\x73\xef\x92\x55\x62\x0c\xbb\xdd\xe8\x74\x4f\x27\x53\xee\x41\xa0\xab\xc9\xc6\xfa\x2c\x69\xee\xa9\xb7\xf2\xde\x1b\x42\xe3\x7a\xbe\x37\x18\x23\xd7\x5f\xf7\x8e\xc8\x3d\xe7\xe3\xf0\xfa\xa2\xfc\xd7\xeb\x99\x28\xbb\x98\x12\x78\x1f\x5d\x9d\xd3\x86\x91\x67\xe7\x77\x1f\xd0\xd8\x29\x43\x47\x8c\x9e\xbc\x63\xd3\x66\xe1\xb3\x1c\x99\x6f\x84\x59\xff\x64\x5d\x76\x21\xc4\xb5\x0a\xcd\xc8\x49\x7c\x54\xd0\xcf\x50\xa4\x60\xb5\x66\xb2\x1a\xcd\x01\x6a\x0c\xa9\x56\x8a\x8f\x56\x04\x91\x96\x26\x88\xb4\xca\x02\xb2\x61\x5e\x71\x57\xcb\xde\xc9\xcd\xfe\x82\x89\x83\xc6\x9e\xc3\x9b\x9f\x79\x22\xfc\x90\xd9\x3f\x7d\x76\xc7\x49\xf2\x8e\x72\x4d\xe6\x8a\xe0\x1d\xfd\x10\x85\xf9\xdb\xac\xb4\xa8\xc9\x45\x2b\x80\xf5\x37\xc0\xc9\x74\xf6\x80\xf4\xeb\x36\x88\xa9\xbc\x79\xf2\xd3\x0f\xb7\x9d\x33\x76\xd0\xc4\x02\x61\x68\xf8\x89\x67\x4e\xd9\x85\x6f\x67\x4f\xf7\x9b\x75\xde\x65\x61\x1a\xd4\x22\x7a\xd1\xc5\xdd\xb5\x33\x91\x31\x69\xbb\x13\x58\x97\x00\x6d\xe8\xa3\x4a\xd1\x41\x8c\x64\xa2\x14\x89\x9d\x64\xf0\xd0\x92\x07\x91\xa8\x41\x9b\x39\x09\xf9\x4f\x2b\xd1\x1c\x76\x9a\xd5\xf5\xea\x0e\x4a\x58\xef\x5e\x89\xc3\x41\x1c\x2e\x05\x08\xfe\x5e\x7c\x62\xdf\x6f\x6e\xbb\x19\x27\x8f\x68\x7f\xd1\xfe\x83\x39\xec\xb8\xfe\x5a\xed\x63\xa1\x69\xcf\x96\x1b\x1e\x2b\xd5\x12\x38\xad\x4d\xe0\x9a\x0e\x5c\x70\x31\x3a\x6d\xac\x7d\x98\xd7\xe5\x64\x03\x93\x8e\xaa\x02\x1b\x8a\x20\x81\x3f\x47\xdc\x71\x8a\xee\xaf\xa4\x48\x3f\x8f\x18\x2e\xf5\xca\xc6\x48\xf7\x97\xa6\xd3\xf4\xb5\xf0\x4a\xfc\xae\x36\x01\xa7\x3b\x26\xe0\x05\xf4\xa5\xb4\x46\x67\x99\xd0\x8c\x62\x68\x19\xab\xd1\xa9\xc8\x63\x3d\x55\x4a\x63\x14\xd6\xd4\x3f\xa6\x44\x8e\x2a\x28\xae\x06\x68\x78\x28\x40\x91\xd1\x92\x87\xf2\xc0\x56\x07\x80\xd1\xc7\xe9\xf2\x9a\x8b\x4a\x2b\xfa\x41\x5d\x8e\x1e\x19\x0e\x95\xd2\x6e\x82\x5e\x51\x29\x4a\xaa\xe6\x0a\x5a\x90\xd3\x87\x86\x25\x7f\x8c\xef\x34\xd7\x7a\xbe\xa2\x4e\x3c\x63\x4d\xce\x5f\xde\x6f\x1e\x33\xf6\x17\x43\x47\x8c\x3e\xff\xf1\x07\xce\x58\x8d\xd3\xf2\xa4\x7d\x1d\x1c\xee\x27\x9f\xc6\x57\xe4\x55\xe2\x80\x1d\xcd\x4d\x30\x96\x20\x1f\x1a\x8c\x14\x99\xa6\x6d\x9c\x31\xd5\x4c\x26\xed\x07\xdb\x59\xa2\xf1\x46\xa4\x72\x32\x65\xed\x75\x8a\x6d\xc8\x68\x93\x00\x6e\x2b\x01\x10\x85\x99\xc7\xee\x70\xdc\xef\x65\xc7\x3e\x6b\x17\x63\xe7\x8c\x81\xe2\xb0\xc2\xb1\x0d\x59\x9b\xd8\x30\x03\x4f\x0d\xaf\x35\x3b\x2f\xba\xe2\xe4\xe3\xd4\x1c\xce\x1b\x47\x31\x9a\x8b\x94\xc2\x6c\xfa\x28\x40\xd3\x47\xbe\x38\x91\x9c\x76\xd6\x26\x96\x66\x91\x0a\x1c\x00\x67\x2f\x80\x2c\x52\x01\x31\x11\x0c\x05\xd9\x2c\x52\x29\x0c\xb8\x90\xae\x3c\x64\x91\x54\xc9\x4c\xfd\x6b\xbb\x08\xb8\x8a\xbc\x9c\x52\xfe\xb8\x13\xde\x48\x6e\xec\x2d\x2d\xd9\xd1\xb7\xb4\x64\xc7\xcf\x6d\xd8\xc8\x0d\xd1\xa7\xd0\xf9\xc6\xc6\xce\x45\x30\x0b\xdc\xf5\x27\x32\x07\xb0\xe5\x86\x20\x66\x76\x9a\x21\xa9\x04\xa6\x5a\x00\x0e\xb1\xc9\xc1\x90\x4a\x56\x37\xbd\xd3\x3e\xb1\xcd\x88\x1c\x12\xa3\xbf\xc5\xd9\x18\x75\xd6\x44\x37\x46\x4a\x83\x90\x0c\x29\x8a\x4d\x5d\xb1\xa2\x7e\x5c\xe1\x30\x71\xe0\x0c\xed\xdb\x41\x0d\xb5\x7c\x7a\x6d\xf8\xf1\x6d\x1d\x93\xae\xbc\xc8\x69\x26\x72\x9d\xdf\x3d\xe7\x17\x08\x71\x5d\x25\x6c\x2d\x83\x14\x37\xce\x23\x5a\x0e\x5c\x6a\x06\x6b\xd7\x0f\x69\x02\xc5\x11\x53\x4d\x16\x0a\x1a\x47\x47\x75\x13\xaa\x84\xd2\x6f\x12\x87\xde\x1d\x4f\xc9\x25\x60\x7d\x79\x2c\x51\xc0\xb3\x94\x14\x80\xc4\x45\x6a\x69\x21\x84\x72\x20\x02\x0d\x34\x76\x34\x38\x67\x1a\x58\xdf\x88\x7b\x2e\x26\xe3\x25\x23\x33\x89\x94\x7d\xbe\x79\xd3\xdc\xbc\x15\xe5\xef\xde\x70\xfb\x63\xbb\xaf\x1c\x55\xc7\x4d\x5f\x77\x72\xf9\x4a\xe1\xb0\xbe\xa8\xa7\x92\x9b\x9e\xda\xbb\x66\xf1\xac\x0b\xa8\x3e\xef\x87\x10\xf7\xaa\x61\x3a\xf2\xa2\x45\xac\xff\xa9\x33\xa6\xba\x4c\x19\xc5\x14\x27\x47\x56\x30\x53\x11\xe1\x3e\xaa\xd8\xe3\x64\x81\x53\x6e\x53\xb6\x51\x0d\x8a\x2b\x6e\xb7\x6a\x0b\x64\x52\x36\xc8\x31\xda\x2c\x8c\x94\xcf\x64\x83\xc1\x33\x41\x66\x4d\x2a\x2e\x32\x0b\x45\x86\x20\x95\x20\x32\x6a\x5b\x4a\x80\x99\xf0\xba\x70\xa4\x2e\x5c\x17\x06\x89\xdb\xaf\x64\x7e\x7f\x3c\x6a\xeb\xb6\xb1\x0b\xb4\x57\xf0\xb0\xe9\x93\xcf\x13\x94\xb5\x4e\x8f\xb6\xa7\xf3\xd6\xa9\x63\x33\x1d\xeb\xb8\xe5\x33\xe6\x53\xdd\x1a\xd6\x64\xe0\xef\xf5\xa2\x1b\xd0\x8f\x91\xf6\x66\xcf\xb6\x0f\xa0\x35\x7a\x44\x56\xce\x46\x23\x9d\xf1\x94\x0c\x11\x24\xb9\x1b\x77\x2f\xcc\x83\x97\x19\x3d\x84\xbd\x5b\x73\xb0\x5e\xc9\x79\x75\x6e\xde\x1c\x23\xef\xcc\x64\xd1\xdc\x3a\xed\x45\xc6\xc3\x7b\xea\x99\x4b\xe7\xfa\xd6\x3a\x64\x3c\x45\x98\x4a\x6b\x9d\x84\x4f\x84\x26\xe4\x47\x25\x68\x1d\xeb\xb5\xe3\xd1\xfd\x12\x1e\xeb\x05\x4f\x1e\x28\x78\x2a\x4e\x40\x94\x99\x15\x3c\x95\xea\x20\xe8\x00\x9d\x8c\x2f\x90\x05\x41\x33\x47\xc5\xe8\x62\x31\x43\x73\x3c\x65\x07\x47\xc5\x6e\xb3\x44\x15\xbb\x5b\x75\x8a\x20\x82\xc2\xba\xa7\xe2\x06\xda\x03\x14\x62\x31\xb3\x1e\x85\x50\x59\xf2\x3b\xbd\x16\xaa\x21\x2c\xaf\x6f\xe7\x1a\x9e\x7d\xe8\x21\x9d\x18\xbc\x7d\xe9\x8a\x1d\x8f\x70\x9d\x87\x39\xe3\x7d\x38\xa5\x4d\x24\x5f\xf7\x75\x9e\xdc\x78\xde\xd4\x17\x8f\xac\x5b\xb9\xfa\xd6\xf6\xf7\x10\x46\x43\xbb\x4e\x08\x2d\x42\x13\x2a\x41\x6b\x19\xaa\xd7\xa2\xe7\x62\xdc\x09\x15\x91\x09\xbb\xa4\x38\x9b\x5a\x21\x20\x0e\x53\x46\xe0\xe1\x35\xf2\x96\x68\xaa\x10\xf2\xf3\x85\xd0\x76\x88\x76\xb2\xf2\x7a\x33\x8a\xd7\xdd\x66\xf1\x4a\xce\x68\xda\xe5\x44\x16\x21\xaa\xb8\x62\x69\x09\x3e\xc1\xe4\x5c\x46\x51\x4a\x59\x02\x25\x49\x9a\xc2\xf1\x90\x49\x5a\x88\x73\x42\x1b\x17\x50\xda\x68\x27\xf6\x32\x47\x84\xab\x24\x9e\x98\x4f\x94\x51\xa4\x0c\x80\x27\x0d\x43\xf1\x9f\x17\xaf\xf9\xd5\x23\x2d\x4f\xdc\x3b\x0f\xff\x59\xfb\xcf\x71\xed\xab\xaf\xee\xfb\xcb\xca\x85\x0b\xf8\xf4\xe6\xf5\xf1\x8e\x6d\xca\x4b\x2f\xa5\x1e\xc0\xe6\x7e\xeb\x37\xef\xd1\xfe\xf6\x4f\xed\xef\x2b\xff\xde\xb2\xe5\xf7\x93\x68\xdc\x4f\x18\x0b\xb6\xd7\xb9\x2c\x03\x6c\xcc\xcd\x95\x9a\x06\x2e\x6b\x86\x26\x4b\x1c\xd6\xac\x25\xc6\x42\x64\x16\x96\x16\x21\xd6\x98\x85\x18\xa7\x2e\x29\x98\xec\xd9\x8d\x00\x3a\xe3\xea\x72\x8c\x68\xb0\x9d\xe9\x55\x2d\x2d\xb7\x0d\x9d\x34\xb8\x71\x4c\xe3\x13\x1b\xbe\x38\xf1\xed\xa7\xf8\x63\x6e\x71\xe7\x83\x2f\x6e\xdf\x79\x00\x97\x5f\x79\xbe\xa7\x45\x7e\x4c\xd5\xde\xfb\xfe\xbb\xaf\x73\x75\x69\x6e\xa1\x09\xd9\xbb\xd5\xa5\x81\xf7\xe0\x88\xa9\xce\xd3\xeb\xd2\xf8\x8a\xca\x88\x93\xe3\xf1\xf6\xf7\xf0\xa3\x07\xff\x36\x46\x32\x1b\x8a\xab\x7f\x10\x9a\x4e\xb5\x73\x6b\x0e\xcd\x08\xcd\x5c\xde\x39\x01\x9e\xeb\x47\xc8\x98\x10\x9a\x50\x21\xfa\x1d\x7d\x6e\x9b\xcd\x2e\x17\xf6\xf1\x27\x72\xed\x0b\x8a\xf2\x93\xde\x76\x56\xf4\x5f\xcc\x8a\xc8\xbe\xfe\xfa\x0f\x50\x44\x86\xdc\x0a\x3e\xe8\x54\x0a\xdd\x4a\xc1\xc1\x03\xaf\x38\xbe\xfe\x8a\xfc\xa9\x53\xb1\xbb\x15\xd7\x41\x83\x62\x73\x2b\xd6\x83\x07\x5e\xfe\xeb\x37\x2b\x81\xa3\xca\xe5\x6e\x73\xb8\xec\x9e\x68\x9b\x93\x7c\x3f\x30\xcc\xf4\xcd\x60\x9d\x55\x2c\x54\x58\xe0\x89\xa6\x42\x85\x05\x79\x64\x55\x4e\x97\x3d\xf7\x3b\xe2\x91\xa4\x1d\x4e\x57\x41\x88\x82\xb1\xda\xb1\x35\xf7\x3b\x1d\x96\x85\x81\x95\xd8\x4d\x83\x55\x09\x0c\xa4\x2d\xf5\x0d\x1e\xb2\x2c\xb5\xb8\x32\x62\x34\xf1\x11\x2b\x26\xf7\x84\xf7\xe3\x01\x1f\x3e\x5f\xd2\xcf\x5c\x55\xf6\xda\xbb\xb8\xdf\x81\x2d\xfd\xbc\x06\x4b\x51\xcd\xab\xaf\xad\x58\x69\x33\x1b\x2a\xf6\x0b\x4d\x9d\x0f\x5c\xf6\xe2\xf3\xf3\xb9\xf9\xa7\xda\xb9\xa6\xf6\xf9\x55\xf7\x3d\xd0\xb9\x19\x3f\x84\x1f\xbd\xb0\x62\x77\xe7\x48\xb6\x2f\x12\xd8\x0b\x51\xb6\x2f\x4e\x20\xae\x11\xa8\xc1\x40\x2d\x05\x0b\x71\x0d\x4c\x52\x32\x6b\x13\x0f\xc8\xa5\x5a\x8d\x2e\x4c\x37\xcb\x68\xe2\xf1\xf1\xb3\x5e\x5c\x7f\xe1\xf0\xba\xd1\xcd\xd7\x96\x25\xf1\x81\x83\x5f\x8d\x95\xcd\x05\xa3\x3f\x15\xde\x4b\x6d\x13\x37\xd8\xe7\x4e\xbb\xf7\xd4\xab\xdc\xdc\x17\xe6\x2d\x78\xa1\x73\x2b\x3b\x13\xfc\xdb\x42\x13\x32\xa3\xfe\x3a\x73\x0e\x86\x83\x81\x15\x4b\xd6\x60\xb6\xfe\x38\x65\xce\xbb\xb8\x00\x07\xdf\xd6\x96\x3e\x2b\x34\x69\x6e\xfc\x4d\xe7\x72\xad\x11\xbf\x4e\xeb\x91\x85\x19\x20\xeb\x7a\xe5\x4e\xf5\x30\x09\x0d\xc5\x1d\xc0\x9d\xea\xb3\xe8\x12\x8d\xa6\xc7\x7c\xdd\x39\x5e\x81\x44\x87\x88\xe3\x33\x72\xa7\xe6\x47\xe0\xba\xf1\xa7\xd6\x8d\xf5\x9f\x25\xf9\x26\x46\xd7\xac\xd0\x39\x54\xff\xb8\xe0\x62\x87\x65\xad\xd3\xf3\xd4\x53\x80\xc7\x9f\xd4\x35\x51\x18\x05\x78\x9b\x62\x34\x81\x65\x99\xdc\x09\xa0\xcd\xf1\xc5\xb3\x63\x4e\x17\xda\xbc\x82\x03\xe8\xd7\xc0\x6a\x0a\x42\x10\x8e\x5a\x46\x26\x2f\x6d\x4d\x5f\x48\x74\xc5\xe9\x83\x63\x41\x42\x39\x1c\x31\x9a\x2a\x87\xe3\x44\x9c\xc6\x7a\xb2\x63\xdc\x7d\xd1\xfe\xeb\xe7\xaf\xd5\xf6\x1e\x2a\xae\x59\x3b\xe0\x2f\xf7\x6c\xab\xe9\xd7\x70\x19\x1b\xab\xb2\x79\xc5\xb4\x8e\x21\xd7\x27\x97\xad\x5b\x58\x34\x60\x3a\xbd\xcb\x45\xc0\x73\xde\x84\x82\x68\x12\x82\xd6\xde\xaa\xdd\x0a\x24\xaf\x10\xa1\x2d\x00\x2b\xd3\xe3\xc8\xa4\x0c\xd0\xdb\xcf\x60\x61\x38\x0b\x8f\x21\xcb\x86\xc9\xf9\x69\x13\x14\xbb\x98\x42\x44\x1d\x24\x15\x87\x44\x1b\x18\xe5\xe7\x41\xea\xf2\x33\x24\x45\xfb\xde\xd9\x7e\xf0\xfd\xdf\xdc\x80\x0f\x76\xde\xc3\x8f\x61\xd9\x91\x47\xbf\xbe\xbb\x0b\x4d\x7d\xee\x61\xc8\x82\x6c\x61\x99\x91\x3f\xde\x34\x96\xd6\xdb\x1d\xd3\x64\xa1\x44\x68\x82\x3e\x65\x1b\x11\xb4\x95\x53\x9d\xd6\x0c\x71\xd6\x0b\x12\x6a\xb9\x25\xa3\x54\x03\x37\xbb\x5e\x25\x59\x26\x01\x8b\x8f\x89\x48\x7b\x47\x26\x65\x82\x42\x1f\x93\x8d\x02\x2f\xd5\xb2\x2c\x26\xc6\x24\xa6\x79\x87\x54\x0c\xcd\x1a\xbd\x52\xda\x2d\xfa\x0b\x0a\x21\x7f\x5c\x5e\x2c\x4a\x6a\xb0\x10\x0a\x2a\x53\xc8\x6f\xa0\x78\x75\xd5\xe4\x05\x72\xf1\x94\x55\xf2\x30\x90\x86\x48\xcd\xab\x44\xdc\x7f\xda\x64\x29\x91\x85\x31\x5c\x56\x8b\x21\x76\xd5\x40\x76\xaa\xfa\xb9\x87\x4f\x7c\xe2\xec\x3e\xfb\xc4\xdc\xfa\xeb\xce\x1b\xf6\xa4\xf6\xd5\xe2\x67\x2f\xdf\x7d\xd3\x65\x6f\x5e\xfb\xec\x81\x5f\x5c\x7c\xf8\x9a\x3b\x1f\xa8\xaf\xc9\x5f\x8e\xeb\xe6\xcc\x19\xb5\x78\xfa\xe0\xfb\xc7\xac\x9a\x3a\x6c\xfc\x82\x3b\x93\x7a\x4d\xba\xb1\x04\x79\xd0\x68\xd6\xb5\xca\xcd\xf6\xee\xff\x5e\x45\xba\x98\x57\x91\xbe\xf5\x83\x77\x3f\x3d\x74\x20\xfd\xcc\x6f\x3a\xce\x79\x64\xb8\x61\xcf\x92\x77\x7e\xfd\x84\xf6\xf5\x85\x9d\x4b\xb9\x2f\xeb\x3f\xbb\xff\xfb\xfa\x5a\x72\x8e\xea\x10\xe2\xcf\x83\x71\x94\x41\xbe\x4f\x64\x43\xa0\x7c\xb2\x94\xbf\x41\xb4\x89\xec\x64\xc8\x92\x5f\x4c\x88\x44\x53\x02\xe2\x8f\x2c\x4b\x5d\xf6\x0d\x67\x91\xf7\x09\x5b\xba\xbf\x63\xcd\x92\x77\xe0\xbc\x06\xbb\x4e\xf0\x09\xa8\x5f\x1e\xcd\x50\xc4\x02\x43\xb5\xcb\xd0\xf1\x9a\x35\xaf\x31\x12\x1d\xce\xe6\x6b\xb7\x88\x92\x2a\x00\x23\x00\xb8\xa7\x0c\x67\x09\x9d\x4c\x86\xe3\x62\x7a\x85\x2a\xc5\x84\xe8\x93\xc0\xb9\x0b\x9e\x35\xec\xd1\x31\x1d\x87\xd3\xe9\xe7\xde\xfc\xec\x9d\xf7\x9b\xd7\xd4\xd6\x7f\x7f\xdf\xa7\x49\xee\x9f\x9d\x0b\xa7\x6a\x5f\xed\x7c\xe1\x2d\x8a\x5b\xd2\xfc\xfc\x26\xa1\x19\xf9\x50\x23\xf3\x27\x2c\x36\x0a\xb2\xb7\x66\x74\x6c\x88\xdd\xcb\xbc\x33\x97\x4c\x43\xff\x16\x31\x85\x4c\x22\xab\x7c\xc8\x41\x00\xc1\xbd\xe4\x44\xb7\xc4\x5c\x4a\xee\x6a\x8c\x30\x37\xe9\x91\x44\xc3\xba\x59\x3b\xb7\x6d\xda\xb9\xf1\xee\x6b\x9e\xd4\xbe\xc3\x03\xf0\x7d\xf8\xe1\x70\xc1\xe6\x81\xda\x0b\xda\x3e\xed\x59\xed\xcd\x11\xad\x8d\xf8\x36\x9d\x5b\xd0\xf0\x2e\xe3\x16\x9c\xdb\x0b\x5b\x5d\x3a\x1c\xb2\xf0\x8e\x68\x3a\x2c\x20\x97\x10\x3d\x9d\x62\x30\x5d\xec\x44\x41\x21\xfa\xe3\x2c\x83\xa1\x30\x71\x8f\xed\x92\x31\x3f\x3a\xfb\xbf\x25\x1a\x9c\x35\x72\xc8\xb0\xb3\x46\x0f\x6d\x1c\xf5\x53\xe4\x74\xda\x47\x23\x9b\xc6\x8f\x18\x31\xbe\x89\xc6\x68\xf5\x38\x84\x13\x7a\xb5\x5d\xce\xf4\x81\x8b\x61\x14\xd4\x12\x4b\x26\xed\xa7\x4d\xae\xfd\x96\x2c\x06\xc6\xe5\x80\x56\x6d\x2e\x3a\x3b\x9b\x23\xa3\x84\x80\xe1\xdd\x43\xc1\x30\x21\x97\xa8\x77\xc6\xf7\xb9\x68\x8d\x8a\x5f\x54\x4d\xe6\x24\xf4\xf1\x15\x58\x33\x2e\x51\xce\x82\x51\xcb\x59\x08\xa5\x4e\xa7\x33\xd8\x8b\x4f\xe0\x87\x6f\x58\xbc\x6e\xe5\x17\xc7\xb4\x37\x70\x14\xfb\xef\x5d\xa7\x1d\xc7\x9e\x4d\x2b\x96\xde\xa0\xbd\x23\x34\x69\x7f\x5f\xb0\x58\xb6\x78\x56\x5e\xb1\x75\xe7\xc6\x5f\xcf\x68\x7a\x60\xdc\x05\xe7\x8e\x42\x1c\x9a\xd1\x75\x42\x98\x01\xf1\xbd\x32\x74\x0b\xc3\xa0\xca\x96\x0c\x2d\x60\x2c\xb0\x64\xd2\xc5\x61\x97\xc5\x01\xe4\xd6\x7a\x92\x57\x72\x64\x14\xc9\x4d\xbb\x9e\x1b\xa5\x8c\x62\x8c\x41\xd7\x09\x66\xe2\x96\x58\xa2\x59\x84\x2a\x23\xaa\xf1\x17\x42\xd5\x93\x4b\xe6\x61\x0f\xc3\x2c\xd3\x5f\x2c\xb6\x09\x76\x3f\x94\x78\x15\xb0\xa3\x38\xb0\xbe\xa1\xae\xa2\x6e\x60\x7d\x82\xee\x2a\xf1\x0c\xd9\xf4\x4a\x19\x7a\x7a\xc6\x75\x2b\xdf\xfb\xeb\x3b\xd8\x8c\x4b\xb4\xcf\x35\xed\x73\x2d\x85\xab\x5f\xd8\xab\xee\xd7\xfe\x8d\x1b\x06\x4f\xd5\xde\xc0\xb1\xcb\xd7\x94\x9b\x93\x07\xee\x7c\x48\x3b\xa6\x7d\xab\xfd\x43\xfb\xdd\xd3\xad\xfb\xdf\x3f\xfa\xfe\xfb\x2d\xbb\x36\x65\xb1\x7e\x2f\x02\xde\x73\x35\x43\x7b\x06\xb3\xf5\x42\xb6\x4c\xba\xa8\x38\x42\xbc\x95\x22\x33\xb8\x18\x96\x1c\x2b\xbf\xcf\x0b\x3d\xf5\x42\x14\x84\x51\xea\xc8\xa4\x42\xa5\x64\xbe\xa1\x22\x4b\x54\x09\xb9\x55\x51\x64\x25\x7b\x3e\x51\x4a\xc9\x7c\x84\xd5\x69\x48\x49\x44\x5b\xcd\xf9\x10\xcd\x05\x4b\x70\xef\x44\x60\xeb\xb6\x67\x81\x7f\x00\x13\x67\x78\xcf\x33\x82\x00\xaf\x9c\xba\xe8\xe6\xc6\xe1\xb1\xc6\x99\x67\xc2\x02\x4a\x07\x6f\xdf\x10\x7a\x40\x9e\xa5\xfd\xeb\x34\x50\x60\x36\x0f\xb7\x00\xf0\x2e\xc3\xf3\xb8\x9c\x70\xf7\xae\x1b\x44\x74\xd8\x69\xd7\x0d\x47\xcf\xae\x1b\x8e\x8c\x8e\x73\xc9\xeb\xb5\xb1\x37\xcd\x4d\x49\xa7\x3b\xf7\x08\x4d\x5a\x03\x3e\x7c\xaa\x1d\x67\x34\x3f\xdc\x93\xae\xa1\xac\x3e\xdd\x05\x32\xe1\x5a\x16\x69\x30\x25\x20\xec\x61\xa1\x30\x1b\x1d\x28\xd1\x9d\x9c\xd3\x2d\x65\x88\x5b\x4e\x24\xa7\x10\x88\x43\x14\x5c\x31\xc6\x53\x56\xd0\xa0\x56\x0b\xa5\xc5\x28\x76\x52\x09\xe1\x75\x8b\x92\xea\x90\x68\xcb\x83\x50\x18\xae\x90\xc4\x6a\xd5\x69\xcc\x21\x71\x5a\xa4\x21\x9f\xae\xf3\xd5\x0d\x77\x4d\x4b\xb7\xb4\xf0\x77\xac\xb9\xf1\xe1\xdd\x97\x26\xfb\x71\x13\x97\x3d\xa7\x43\x94\x4e\xde\x78\x0b\xf1\x11\x36\xed\x7d\x6a\xf5\xd5\xb3\xa6\x2e\x36\x1a\xb3\xe5\xea\x08\x23\x49\x93\xf9\x2d\x80\x53\x1a\xc4\xbc\x5f\xbd\x34\xd5\x14\x03\xa4\x92\xe9\xa8\xc2\xc7\xc1\xea\x14\x75\xab\xd3\x4a\xac\x4e\x48\x6c\x5a\x68\x45\x2a\x6e\x80\x75\x6c\x88\x40\x68\x54\xfa\x1f\x7c\xd3\x8a\xb6\x36\x8b\xe5\xbc\x81\xda\xf6\x0f\xf1\x0b\x42\x93\x86\xae\xc4\xf7\xff\xf0\x16\x3f\x31\x35\x7f\x90\x76\x0f\xfe\x88\xee\x23\x3f\x55\x68\x42\x06\x54\xc3\x64\x0f\x6f\xd1\xf1\x51\x46\xdd\x15\x4b\xf1\x80\x34\xe1\x0d\x96\x28\xb1\x40\xf4\x4d\xf3\xee\x4d\xe3\x7f\x0b\x4d\x1d\x13\x36\xe7\xd7\x6c\x95\x40\xcd\xd6\xa2\xde\x6a\xb6\x7c\xb1\x6c\xb5\xf9\x69\x35\x5b\x96\x02\xa8\xd9\xf2\xf6\x5e\xb3\xe5\x15\xa1\x6a\x99\xf7\x41\xe5\x52\xc1\x8f\x56\x2e\x85\x73\x95\x4b\xe2\x8f\x96\x6d\x61\x6e\x61\xac\x66\xdc\xe8\x01\xe9\x33\x97\x6d\x5d\x81\xa7\x86\xd7\xfa\x2e\x9e\xff\xc3\xb9\xf8\x77\xa7\x97\x6d\xe5\xd9\x2b\x21\xb4\x90\x65\x14\xdd\x31\xc5\x96\x20\xf6\x82\x62\x01\x24\x13\xc7\xf2\x0b\x4e\x68\x2d\xe8\xa0\x51\x08\x87\x33\xcb\x3e\xe8\x04\x10\x93\xd3\x4d\xd9\x07\x7d\xcc\xb0\x21\x1e\xaf\x03\xf6\x36\x90\xd4\x51\x59\x86\x50\x6f\x54\x3b\x0c\xd4\x54\x97\xe8\x6e\xe0\xbc\xf4\xf4\x27\x9f\x3c\x7b\xe0\xc0\xce\x57\xb3\x46\xce\x76\xed\x6f\x17\xee\x78\x40\x53\xf0\xa4\x07\x30\x37\xe8\x8f\xf7\x82\xa5\xa3\xdb\x3a\x93\xf4\x39\xc8\x80\xc1\x8c\x29\x62\x82\x68\x1c\xc5\x15\x27\x1e\x17\x9f\xcb\x91\xd8\xbc\x80\x58\x91\x71\x54\x09\x00\x4e\x1d\xba\xe9\x67\x39\x56\x52\x32\x18\xd6\xb2\xcf\x12\x85\x39\x78\x64\x51\x52\x79\x0b\x99\x83\xc5\xcf\x08\x61\x7b\xc4\xa2\x69\x3d\x8b\xcf\x2f\x66\x67\x52\x57\xc1\xd5\x7d\xf6\xce\x87\x5b\x47\x0f\x7b\x74\xcc\xa9\xd7\x1f\x3f\x70\x20\xfd\xc9\x27\xcf\xbc\x28\x6c\xf9\xf5\x3b\x4b\x88\xf5\xb2\xf1\x8f\x0d\x9a\x46\x27\xb2\xe3\x22\x2c\xeb\x39\x79\x53\xb3\x51\x46\x01\x54\x8e\xaa\xd0\x5d\xcc\x96\x72\x99\x32\x50\x4a\xa7\x16\x32\x1c\xa6\x5a\x65\xca\x64\xd3\xbb\x60\x66\x51\x24\x26\x6b\xbd\x56\x42\xcc\x49\x4f\x3c\xae\x56\xd0\xb2\x81\x0a\x88\x4a\x56\x38\x69\xf7\x23\xb5\x24\x08\xe5\x74\xb2\x8f\x1c\xc9\x0a\x31\x65\x32\xd2\x72\x2d\x17\x11\x11\x15\xd0\x47\x1f\x19\x0d\x1e\x60\xaa\x3b\xed\x64\xd6\x51\x58\x55\xd8\x1b\xee\xa5\x9e\xce\x82\xc3\xd9\x62\x42\xde\xd3\x79\x80\x9b\xd2\x31\xb1\x47\x4d\x1d\x2f\x71\x13\x3a\xd3\xf9\x15\x85\x5a\xfd\x9a\x8e\x37\xd7\x75\xaf\xab\xeb\xbc\x87\x3f\x9b\xdd\x45\xd3\x26\xa3\x8c\xfa\xa1\xc1\xe8\x65\x94\xaa\x24\x8b\x20\x15\x27\x12\xa9\x28\xf9\x34\x40\x5f\x8e\x72\x5d\x61\x0d\xca\x55\x26\x90\x55\x69\x84\x55\xa9\xf5\x02\xd3\xfb\x40\xb2\x2a\x55\xf1\xb8\x5a\x4e\x57\xa5\x7c\x20\x59\x95\x72\xa7\x25\xaa\x94\xbb\xd5\x4a\x77\x46\xa9\x8c\x91\x4f\xc5\x80\x66\xc8\xa4\x8a\x81\x12\xa7\xb8\xcc\x12\x55\x87\xe0\xa8\x3a\xb0\x16\x56\xad\x3a\xda\xc7\x9f\x54\x2b\x11\xf8\x7f\xd0\x62\xd2\x17\xa0\x7d\x66\xa2\xac\x94\xa1\xbc\x52\x94\x9e\x45\xae\x70\x55\x75\x2d\xad\xd3\x4c\x19\x0d\xce\x64\xb2\x97\x45\x3c\x03\x36\xed\xc7\x2a\x15\xd3\x7c\x89\x36\xe2\xef\xd8\x0e\x8e\x19\xf8\x6b\xef\x2e\xc3\x07\x3b\xd3\x67\x2e\x5d\x24\x0b\x9c\x73\xdb\x76\xe8\xae\x5c\xc7\xc4\x9e\x95\x8c\x94\x63\x78\xa2\xb9\x9f\x51\x86\xda\x8f\x3a\x34\x0c\xbd\x88\x52\xc5\xe4\x26\x05\x12\x10\x3d\xae\x8f\xb3\x72\x10\x7d\xe1\xeb\xf4\x73\xd8\xdf\x92\x49\x0f\xf1\x80\xa5\x30\xc4\x44\x17\x7f\x78\x7e\x49\x48\x0d\x59\xfc\xd2\x78\x5c\x4d\xd0\xc5\x4f\xd4\x90\xc5\x4d\x90\xc5\x4f\xb8\xd5\x24\x2b\xf4\x1d\x81\xa3\x6a\x4d\x05\xac\x73\x18\x10\x08\x09\x72\x3a\x21\xdc\x97\x94\xda\x5d\x9e\x60\x61\xf1\xc0\x7a\x58\x6c\x57\xb1\x28\x29\x89\xa4\x32\x44\x4c\xf9\x4a\xc3\xc9\x64\x52\xad\xf3\xd0\x72\x89\x0a\x56\x1c\xdb\xdb\xa9\xed\xe6\xa5\xd7\x37\x9c\xe1\x08\x67\xbd\xf7\x6e\x67\x79\xf7\x85\xcf\x2d\x05\x0f\xbe\x2a\xbc\xb6\xd8\xa3\x25\x7b\x3f\xd7\xa1\x7b\xb6\xd5\xd4\x0c\xba\xec\xb4\xf3\xbd\xa7\x65\xc5\xb4\x8e\x29\xcd\xc9\x49\xd5\xa7\x1f\xf4\x8e\x77\x99\xe3\xcf\xa1\x30\x42\x86\x76\xc3\x18\x54\x84\x62\xa8\x85\xf5\x0b\x0a\x9b\x69\x26\x5c\x75\xe8\x8d\xec\x62\x34\x26\x6e\x06\x91\x6b\xce\x35\xb2\xeb\x0f\x71\xd6\x62\x88\x1f\x13\xa7\x81\xf5\xab\x2b\xa6\xcb\xcf\x2c\x08\x68\xc9\xc5\x92\x70\xee\x42\x22\x9a\x6b\x93\x49\xa5\x5c\x6c\x33\x3b\x3c\xd5\xb4\xa2\x3a\x65\x93\xad\x20\x11\x62\xc4\xb7\xb0\xb9\x7d\x45\xe4\xcc\x1b\x1c\xa2\xa4\x62\xca\x9d\x48\x63\xe4\xdd\x73\x70\x60\x83\x87\x4b\x83\x98\xac\x67\x58\xcf\xbd\xd5\x0d\x6c\x08\x87\x1f\x19\x7b\x05\x57\x3e\x65\xda\x73\xbf\x1a\xf6\xc4\x1d\x8b\xaf\x9d\xb3\xef\xc5\x75\x9f\x1d\xed\xd4\xb4\x17\x9f\x9d\x39\x01\x7f\xb9\x76\xf9\xb5\x2d\x0f\xdf\xdc\x18\xd6\x76\xd3\x98\xba\xac\xa7\xe1\xce\xb9\x77\xf1\xe6\x87\xf0\x14\x6e\x41\x67\xcb\x9c\x5f\x8e\x1c\x3f\x62\x7a\xe3\x90\x0b\x16\x4c\x38\x67\x08\xf4\xf9\x93\x85\x89\xc6\x12\xd4\x07\xd5\x64\xeb\x3d\xab\xcc\x19\xa5\xca\xad\xf4\x85\x42\x38\x13\x5b\xaa\x1a\x96\x3e\xa8\xe9\x9e\x3e\xf0\xc6\x88\x25\xaf\xb8\x62\xaa\x85\xa9\xf1\xc8\x51\x90\x0b\x42\x3c\x15\x29\x27\x3f\x1b\x41\x54\x2e\xb0\x35\x2c\x67\x0d\xd5\xfb\xb2\xaa\x26\xa2\xdc\xf9\x08\x84\xca\xd4\xa2\x72\x51\x4a\x79\xfd\x61\x58\xb2\x70\x81\x28\xa9\x9e\x40\x32\xa9\x1a\x6a\x68\xc4\xc8\x25\xaa\x76\x29\x6f\xd5\xea\x7a\x26\xfd\x58\x2d\x0f\x6b\x02\x48\xed\x5c\x58\x33\x3c\xbc\x5b\x2a\x30\xd6\x38\xb6\x21\x38\x37\xa1\xbd\xf8\xec\xc5\xe7\x5f\x30\x4c\x7b\x99\x2e\xd7\xca\x6e\xa9\xc1\xb5\xbe\x8b\xae\x7c\xd8\x2a\xe1\x5f\x70\x2b\x3b\xef\xb8\x74\xae\xcc\x47\xe9\xb9\xea\x3a\x61\xdc\x60\x18\x83\x62\x68\x30\x7a\x07\xa5\x6a\xc8\x9d\xae\x4c\xa8\x76\x73\x46\x89\xc7\x53\x32\x78\x36\xb6\xee\x6d\x12\x65\x48\x0d\xca\xfa\x92\xa5\x07\x85\x6b\x04\x07\x48\x58\x90\xab\xb5\xb9\xac\x4b\x6d\x16\x07\x5f\x0b\x11\xbe\xda\xd3\xda\x25\x12\x5b\x8f\x45\x87\x81\x30\x57\xca\x80\x48\x2d\xac\x15\xa5\x14\xe7\xaa\x26\xf7\xbb\x4e\x4c\xcb\x05\xe1\x4a\xa8\x3d\xe9\x23\xa9\x01\x20\xce\x1d\x64\x17\xa5\x94\xab\x0f\x54\x2a\x9a\x6b\x44\xa9\x4d\x0c\x14\x42\xd5\xbf\x41\x54\xb1\x3f\xd9\x4b\x2b\xc5\x1e\xd5\xfd\x7a\xaf\xbe\x48\x69\x25\x5d\xde\x1c\x99\xb3\x51\x4f\xe9\x4c\x3e\x6b\xfc\xfd\x0b\xfb\xe5\x55\xfb\xbb\x2e\xdd\x73\xc9\xfa\xa7\x0e\x3d\xa6\xfd\xe7\xb6\x65\x07\x67\x6b\x2f\xf2\xf3\x27\xef\xbd\x70\xfe\xf9\x4d\xc3\x6e\xcb\x36\x5f\x9c\xb6\xb0\x71\xf2\x55\x8f\xe7\xca\xff\xcf\x1b\x3f\xa6\x71\xcd\x92\xd5\x8f\x3c\x3e\x7d\x1c\x2c\xfd\xb0\xe5\xe7\x0e\xe9\x9f\xec\xaf\x63\x5b\x8c\xc3\x8d\x25\x68\x00\x6a\x45\xa9\xfe\x64\xe5\xa3\x89\x94\x97\xd5\xc2\xab\xa8\x5f\x3c\x4e\xe3\x66\xb5\xa6\x8c\x52\xe9\x56\xb1\x3d\x43\xcf\x68\x61\x0c\xd8\x89\x29\x4a\x1b\x4a\x7a\xfa\x43\x7e\x28\x46\xd1\x06\x31\x7a\xab\xa3\x8e\x8c\x12\xa5\xd5\xf3\x41\x07\xad\xf1\xa9\x89\x89\x92\x6a\x23\x16\x4a\x54\x6c\xb3\xb8\x45\x33\x59\xb1\x88\xd4\x26\x15\x7a\x8b\x41\x78\xf6\x0f\x8b\xd0\xef\xb0\x52\x54\x45\x29\x99\x54\x6d\x5e\x51\xaf\x48\x6e\xa8\xcb\x65\xd6\x8b\x70\x38\x07\x7e\x34\x66\x91\xa9\x03\x75\xab\x34\x2c\x46\xc4\x92\x83\xcf\xb4\xcf\xbf\xb2\xff\x25\x63\x2e\x9e\x86\x5b\x8b\xac\xf5\xe9\x05\x87\xdf\xdc\xf0\xe0\x85\x8d\xc3\x86\xae\xbd\x7e\xc5\x13\x0f\xa7\xb5\x7f\xa6\xf9\x17\xa7\x0c\x1b\xfe\xe6\x9b\xe5\xf7\x14\xdf\x70\xdb\x39\x9b\xa7\x4e\x79\xe9\x83\x8e\x0d\x2d\x7b\x83\x1b\xe5\x3d\xfc\x15\xab\x6f\xdd\xff\xdb\xce\xd7\xf9\x17\x3b\x46\xf1\x2f\x82\x3f\xd6\x75\x42\xf8\xc6\x28\xa3\x0a\x74\x3d\xc3\x90\x80\xbe\x31\x98\x59\x39\x3d\x71\x93\x70\x96\xc2\xb6\x82\xba\x63\x15\x34\x90\x16\x94\xc0\xf8\x31\xe1\xa8\x5a\xea\x01\x6e\x5b\xd5\x14\x24\xe6\xb7\x4d\xf4\x15\x51\x3c\x9b\xc8\xfa\xca\x1a\x88\xfa\x2e\x87\x4c\x32\xef\x94\x4b\xf3\xfa\xca\x26\xa0\x3a\xa0\x54\x97\x5d\xa7\xa1\x0c\x84\x48\x59\xa5\x77\x6f\xfa\x37\x1f\xe0\x11\x00\x1b\x00\x64\xc1\x93\xb7\x33\x64\x81\xd6\xf9\x9f\xbf\xed\x31\xca\x27\x3f\xba\x72\x3b\xc5\x0b\x4c\xe8\x0e\x2a\xd8\xf6\xab\xa9\xa3\xb2\xb8\x8d\x55\x46\x19\x99\x91\x4d\xef\xf7\xa8\x1a\x75\x5d\x6a\x33\xd1\x49\x52\x9f\xd3\x42\x51\xf2\xac\xef\x93\xd9\x02\x7e\xa7\x03\x50\xfa\x94\xc6\x49\xe5\x6d\x3a\x53\xb7\x6e\x9b\x95\xe3\xf0\x5e\xdd\x00\xfb\x94\xe8\x25\xa3\x4c\xad\xac\x65\xc4\xac\x62\x5c\x47\x92\xa1\x1d\xd9\x51\x10\x57\x30\x46\x5a\xb3\x25\x91\x48\x39\x38\x14\x6d\x73\x8a\x1e\xb9\x8f\x3f\xc1\x6a\xfb\x14\x47\x5c\xc5\x6e\x38\x73\x18\x42\x78\x8a\x87\xe2\x82\xe5\x38\x38\xff\xf5\x05\x07\x5e\x09\x7e\xfd\x12\xe4\x78\xec\xb5\x82\x82\x0e\x3a\x55\xae\xe8\x07\x41\xc1\x07\xb3\x7f\xe1\x54\x1c\x6e\x25\x78\x50\x71\xba\x15\xd7\xc1\x03\xaf\x7c\x77\xe2\x20\xf9\x53\x83\x62\xa9\x75\x2a\xd6\x83\xaa\xa1\xf8\x07\x45\xc8\xff\x73\xb1\xd6\xa9\x48\x07\x55\x7f\xf1\x0f\x8a\xef\xe0\x81\xa1\xed\x5f\x9b\x69\x35\xbe\xb1\x56\x15\x0c\x66\xc5\x70\x50\x50\x4d\x25\x3f\x18\x14\x73\xee\x2f\x55\x51\x32\x2b\x1e\xb7\x22\x1d\x74\x2a\xb2\x5b\xf1\x1e\x44\x23\x9c\x08\x73\x82\xc1\x68\xb2\xba\x24\xaf\xcf\x1f\xec\x4e\x2c\x88\x47\x38\x39\xc1\x60\xb6\x58\xed\x2e\xb1\x97\xbf\xa6\x59\x22\x87\x9d\xd8\xfd\x81\x24\xe4\x43\x42\x98\xfc\x9f\x8f\xd8\x70\x84\xcf\xff\xcd\x86\x3b\xf7\x6c\xd8\xb1\xe1\x9e\xb7\x5a\x76\xee\x7e\xe0\x70\xfe\x6f\x38\xa5\xf3\x24\x67\xec\xfc\x9e\x33\x77\x4e\xe2\xb8\x4e\xcd\xd0\xde\xfd\xf7\x39\x0c\x8f\x15\xfa\xe7\xba\xd0\xb4\x6c\xe6\x2e\x8d\x05\x48\x80\x92\x25\xe7\x33\x29\x0b\x47\xd9\xb3\xe0\x43\xda\x4c\xff\xce\x16\x67\xd5\x3f\x80\xd4\xa6\x62\xc1\xe4\x56\x05\x1c\x55\xec\xd0\x4a\x5c\xb1\xc6\xa1\x28\x08\x42\x65\x70\x63\x79\xf6\xeb\x5e\x7e\x46\x5a\xb3\xa7\xe1\x3b\xfe\x44\x8b\xe0\x3a\xed\x6d\xfe\xb8\xfe\x09\xf0\x25\xc7\x34\x59\x98\x0a\x78\xeb\x4b\x59\x7e\xd7\x6a\xa1\xed\xdc\xe8\x31\x2d\x31\x67\x14\x31\x06\x78\xeb\x10\xa0\x34\xc8\xbb\x45\x1c\x25\xe7\xc5\xcd\xe0\xd6\xa2\x49\x27\xe3\x77\x8b\x8a\x9c\x44\x6a\x89\x55\x94\xd2\x46\x24\x7b\x81\x7b\xce\x29\x9e\x0e\xdf\xe8\x5e\x7f\x47\xc5\x4d\x75\xcd\xa5\xb7\xdc\xb9\x74\xe5\xce\xad\x69\xda\xfa\xf3\xfd\x57\x86\x0c\x1e\xca\xef\x5f\x1f\xd8\xb0\x5a\x1b\xb9\x7a\xd5\xbe\xdf\xd1\x6a\xbc\xe9\x23\x26\x4d\x7f\xe3\x6d\x7c\x78\x6c\x23\x1b\xbf\x21\x2c\x34\xa3\x6a\x34\x9f\x59\x08\xdd\xc7\x4f\xec\x85\x40\x8c\x82\x9b\xfb\xc6\x94\x3e\xd9\x39\x14\xe4\xe6\x10\xc5\x51\xb5\x80\xcc\xa1\x38\x4c\xe7\x50\x44\x54\x3c\x05\xf4\xab\x55\x01\x51\x4a\x19\x51\x11\x6d\x6c\xda\xfb\x4c\xba\xf3\xc5\xf5\x3a\xa5\x68\x72\x64\x45\xbf\xd9\x5f\x9f\x69\x62\xa7\x22\x8b\x2e\x04\x0c\xe2\xfd\xf9\xd3\x43\x18\x6d\xc3\x6b\xf8\x95\x46\x19\xc9\x68\x22\x4a\xb9\x99\xe6\x4e\xb9\x01\x28\xe1\x26\x2a\xd8\xce\xe2\x49\x44\x96\x78\x29\x03\x28\x15\x98\x32\xad\x41\xb2\x7b\x32\xe0\xa8\xcb\x08\xe4\x87\xe2\x10\x15\x73\x36\x29\x6d\xca\xc1\xf6\x41\xdc\x6f\x4b\x99\x2b\x56\x4d\x68\xdd\xae\x6c\xbf\x76\x3e\x5e\x23\xdc\xa3\xed\x18\xd2\x7f\xc8\xf8\xfb\x1e\xeb\xfc\x92\x13\x53\xb7\x6f\xd4\x26\xe7\x8d\xa9\x08\x15\xa2\x2b\x51\x2a\x00\x34\x05\xa6\x4c\x2a\x00\x38\x92\x80\x17\xc0\x25\x90\xce\x82\x0a\x42\x73\x26\x9b\x39\x86\xa3\x4a\xcc\x03\x2f\x19\x8f\x87\x36\xac\x28\x64\x9d\x85\xbc\x62\x8a\x37\xb8\xc1\xba\x72\x07\x68\x20\xd8\x2c\xaa\x46\x6b\xae\x6c\xd0\x23\x0e\x64\xc1\xc2\x22\x7c\xfa\xc8\x8f\xc4\xc7\x36\x46\x13\xe6\xaa\xd5\x63\xf5\xe1\xf3\xed\x9f\x05\x37\x16\x9c\xb3\x7e\x48\x55\x72\x4c\xf7\x29\x20\xae\xeb\x10\x0a\xe3\x19\x86\x7f\x23\x3b\x0a\xa0\x73\x21\x6b\xc2\x13\xc9\x0c\xb4\x6e\xbc\xc9\x12\x55\x7c\xb1\xb4\x5b\x40\xd5\x42\x14\x40\xf1\x46\x10\x90\x16\x68\xb9\x41\x31\xc5\x50\x54\x0a\x6c\x82\x20\x99\xa1\x7f\x39\x9c\x0e\xbd\x86\x31\x21\xca\xdd\xe3\x6d\xc9\x71\xf1\x78\xdf\x54\xc7\xb8\x3b\x87\x44\x6b\xea\xeb\xfa\x45\x87\x34\xdc\xed\x6f\x18\xc4\xef\xe9\x98\xa6\x19\x16\xd5\xf5\xaf\x8f\xd5\xd4\x0f\xd0\xd7\x97\xdb\x23\x7c\x84\x5c\x28\x8e\xb2\x96\x81\x5b\x8f\xa6\x03\xe4\x93\xd8\x5a\x2e\x8e\x95\x90\x19\x6d\xc4\xc2\xc2\xe6\xa4\x8e\x39\xcd\xd1\xe3\x79\xc5\x6d\x0f\xd9\xfa\x2f\x9e\xdc\x38\x4c\x1e\x16\xbb\xe4\x66\xbc\x86\x1f\xb1\xf7\xf2\x0b\xec\x2d\xee\x8d\x57\x6a\x67\x93\x77\x0d\xc0\xcb\xb8\xe1\xc2\x21\x88\xe5\x29\x4e\x16\x3d\x71\x03\xb9\x84\xce\x50\x26\x42\xd3\x65\xf2\x46\xab\x11\x36\x06\xa9\xbc\x53\x94\x52\xc8\x62\xa5\x6f\x6c\xc8\x15\x29\x91\xb3\x3f\xc0\x3b\xaa\xef\x25\x37\xa7\x1e\xb2\xf6\xbf\x76\x62\x23\x5e\xdd\x22\xde\x77\x25\xfe\x75\xc7\xc1\xbd\x97\x5d\x48\xde\x87\xc2\xdc\x57\xc2\x21\x14\x42\xe3\x11\xe0\x7b\x4c\x19\xa5\x00\x5e\x9b\xe2\xc1\x16\xe5\xcd\x96\x28\x23\xd3\x51\x8c\xb0\xe4\x14\x51\x21\x33\x90\x95\x9d\xa1\x80\x0b\x20\xa4\xa6\xb3\x58\x35\x74\x43\xa7\x67\xef\x62\xde\x70\x42\x95\xc1\xe1\xde\xd8\x25\x1f\xb9\x06\x5f\x71\x6e\x6e\x54\x73\x46\x0d\xf7\xd8\xd7\x84\xb1\x79\xed\xc8\x51\xf3\xa6\x20\x0e\xce\xf6\x16\xe1\x10\xc3\x85\x2a\x28\xa6\x3a\x4d\x50\x75\x02\xc7\x03\xe2\xb0\x3c\xb6\x44\x81\xc2\xdd\xa7\xe3\x5d\xc9\x75\x73\xd2\x04\x87\x95\x81\x31\x25\xa7\x28\x41\xf1\x89\x62\x15\x15\x43\x12\x01\x3f\xa3\x62\x85\x78\x92\x89\x55\x42\x25\x80\xe4\x95\x1c\x8e\x4a\xb0\x57\xa3\x78\x5b\x6a\xe7\x87\xef\x7d\x33\x7d\xc6\x13\xf7\x7d\x74\x68\xf2\x39\xe9\x3d\x64\xbf\xb4\x57\xf0\x30\x6d\x77\x68\xf9\xb4\xeb\xef\x58\x37\x62\xc0\x72\x84\x51\x25\x5e\x23\x7c\x2b\x1c\x42\x01\x74\x21\xd2\x4b\x36\xb0\x37\x43\xb4\x88\x93\xe5\xde\x0a\x98\xca\xae\xfe\x7a\x35\xd5\xa9\xa8\xd6\xa9\x04\x0e\x0a\x2a\x76\xfc\xe0\x54\xb8\x83\xa8\x0d\x61\x2e\x40\x59\x6c\xc8\xaf\xd0\xe4\xcb\x89\xb3\x94\xca\x09\x8f\xcf\x5f\xdf\x00\xbf\x0c\xc7\x9e\x04\x1f\xe1\x2b\x2a\x8d\x26\x3e\x52\x79\xe0\x3a\xaf\xdb\x54\xbc\xa9\xfd\xde\x62\x93\xe4\xbd\x7e\xdf\x57\x07\xef\x2d\xb2\xbb\x02\x0f\xbc\x20\x1c\xd2\xc6\x8d\xbb\xb4\xe1\x22\xfc\x9e\x36\xe0\xf2\xca\xc9\x53\xf0\xbe\x8e\x83\xf8\xbd\xe6\x31\x73\x47\x68\x09\xca\x17\x19\xe6\x67\x08\x87\x90\x07\x85\xe0\x4c\xbb\x4d\x90\xa3\xa4\xc9\x49\xd6\x55\x95\xbd\xb7\x5b\x4f\x9d\xe1\x58\x7e\x39\xdd\x47\xac\xdf\xfd\xa2\xb6\xb9\x7e\xeb\xa2\xf3\x07\x8e\xab\xba\x3a\x51\x21\x1c\xd2\xfa\x5d\x7a\xf6\x4e\x7c\xa4\x63\xfa\xda\xa5\xee\x35\xce\xd5\x73\x20\xbe\xc9\xbf\x8c\x27\x1a\xda\x91\x11\x55\xa2\x14\x47\x54\x28\x02\x15\x8a\x15\x13\xd4\xb2\x0a\xce\x0c\x14\xb2\x09\x1c\x25\x96\xec\x3f\xc0\x23\x35\x24\xfc\x46\x3e\x38\xa6\xf4\xa0\x6b\xe0\x4d\xfc\xcb\xb8\xe8\x77\xbe\x43\xda\x5f\x11\x47\x9e\xc5\x1d\x82\x67\x39\xd1\x68\x44\x69\xac\xad\x89\xb4\x89\xea\x64\x14\x07\x2c\x32\x7d\xa6\x22\xb8\x01\x5d\x61\x77\xd2\xfa\x1d\xf6\x78\xb2\xf1\x26\x16\x5a\xcb\xbd\x2a\x51\xcf\x5e\x39\x32\x72\xd0\x35\x60\xe5\xbf\x0a\x46\x39\xc8\xaf\xfc\xcb\xd8\xfc\x0f\xdf\x2b\xda\x9f\xe6\xe0\x81\x97\x90\x5f\xf3\xe7\x63\x22\xf3\x81\x36\x02\x26\x36\x1f\x33\xec\xb9\xd1\x99\x01\xd4\x11\x98\x88\x3c\xbc\x84\x3c\xdd\x68\x8a\x04\x7d\xb3\x06\xad\x1e\x55\xfe\x0a\x7f\x6c\x3a\xb6\x2f\xd3\xbe\xa3\xb1\xd3\xff\xde\xfa\xd0\x67\x4d\xd2\xc7\x06\xcf\x32\x74\x1b\x1b\xc7\xc6\xc6\x51\xb5\x43\x9e\xd5\x90\xf0\xf9\x23\x15\x5c\xd0\xf9\x4a\xf9\xa8\xd5\xfd\x16\x1a\x5a\x7d\xa7\x4e\x36\xe3\x42\x8a\x73\xdd\x24\xb4\xa0\x25\xc6\x26\xe4\x40\x09\xb8\x75\xd8\x00\x24\x1a\x66\x03\xed\x0e\x23\x1c\x05\xac\xa2\x00\xf2\x59\x30\x83\x8e\x41\xaa\x09\xb3\x66\xb7\x7c\x1d\xf5\xf7\xea\x40\xd6\x2e\x8c\x8f\x6c\x1c\x34\xef\x86\x1b\x85\x96\xb9\x8d\xf5\xf5\x83\xe7\x5f\x37\xe7\xb2\x6b\x4e\x7b\x87\x2d\xa6\x5a\x0d\xd0\x65\x9a\x67\xef\x40\x47\x55\x53\x20\x93\x32\x21\x1d\xae\xa0\xf0\x71\xa4\x0a\x56\x9d\xfe\x77\x60\x7d\xc2\x0b\x3e\x42\xc2\x5b\x56\xb1\xf0\x86\x79\xe4\x2d\x73\x6f\x34\x2c\xf9\xe5\xf5\x97\x0f\xae\xaf\x6f\x9c\x77\x2d\x59\x63\x37\xdf\xce\x55\x1a\xc3\x48\x42\x13\x10\x34\xae\xe2\x21\x00\xc1\x91\x77\x78\x20\x4b\x6e\x76\x41\xbb\x67\x3b\x8e\xaa\x06\x37\xed\x37\x6e\xb6\x88\x92\xca\x01\xa2\xc3\x6a\xa1\xa0\x79\x97\xa8\x1a\xa4\x64\x52\xe1\xa4\xfc\x10\xba\xc9\x1b\xa9\xd3\x19\xfa\xdc\x8b\xee\x5c\xbd\x55\x5b\xfd\xfd\xe4\xb1\xb1\x2b\xfb\x1a\x3e\x19\xbd\x6a\xf1\xcb\xe7\x5e\xb1\x67\xd0\xa6\xc6\xa6\xb2\x22\x86\xb3\xe4\xdb\xb9\x41\x30\x96\x06\x44\x26\x6a\xe0\x41\x92\xbb\xd9\x58\xc8\x7c\xe9\x00\x90\x6a\x10\x20\xca\x01\xad\xf2\x1d\xc4\x08\x62\x01\x61\xd9\xef\x4d\xd0\xcc\xa4\x8e\x15\x08\xeb\xaf\xec\x47\xde\x6f\x88\xe5\x5e\xba\x60\xf4\x2a\xfa\xde\xb9\xa8\x41\x88\x0a\x15\xc8\x88\x90\xa7\x0e\x7b\x2d\xd8\x3b\x97\x7f\xbd\xa3\x83\x17\xf0\xa7\x73\xf1\xe7\xad\xda\xfd\xda\xf3\x8f\xf6\xf8\xb9\x86\x3a\x0b\xae\x23\x3f\x27\x74\x74\xf0\xaf\x37\x3c\x8a\x47\xe1\x45\xad\x5a\xc9\x5c\xda\x13\x01\x35\x09\xc3\x05\x27\xfc\x1c\x4e\x60\x93\x05\x4f\xc2\xbb\xe6\xe2\xcf\x1f\xd5\x36\x69\x2f\x34\xf1\xaf\x75\x0c\xe3\xc8\xbf\xeb\xf9\xb3\x9e\x06\x0b\x4e\xe0\xc8\xa4\x47\xf1\x42\x7c\x56\xab\x36\x6d\xae\x60\xe7\xc8\x28\x3a\x86\x20\x8c\x05\xe1\x38\xbf\xdf\x18\x46\x0e\x14\x26\xe7\x4d\x31\x27\xd2\x82\x80\x1c\xe4\x00\x3b\x63\xb4\x3e\x5a\x40\xec\x74\xe1\xba\x61\x98\x1c\x5e\x6f\x04\x38\xde\x85\x15\x97\x07\xf6\x0f\x7c\x67\xe5\xf4\xd5\xab\xa6\x09\xc7\xfd\x77\xdc\x12\xbd\xec\x1d\x7f\xdd\xaa\x5b\x06\xa1\xbc\xe7\xda\x51\x84\x9c\xb1\x34\x07\x0f\x55\x8c\xf1\x1c\x3e\x8f\xb3\x89\x92\x8a\xa1\x40\x04\xe7\x77\xbc\xc7\x42\x5e\x93\x7b\x63\xae\xa1\x3d\xdc\x8f\xbd\xc2\xeb\x68\xb2\x51\x46\x3c\x2a\x22\xe3\x25\x8e\x03\x0c\x56\xa0\x79\x2f\x29\x43\xbe\x50\xff\x01\xbc\x98\x10\x27\xef\x10\x5e\xc7\xe7\x69\x2a\x19\x4f\x54\x38\xce\xaf\x33\x2c\x40\x3c\x2a\xa3\xf7\xca\x9c\x21\x5f\xe4\x1f\xaa\x08\x47\xd3\xbc\x13\x99\x84\xa8\x6a\x00\xff\x01\xd7\x85\xbd\x38\xca\xcd\x14\x8e\x6f\xdc\x88\x70\xd7\x33\xc2\x71\x3c\xde\x18\x46\x16\xd4\x07\xde\xa9\x2f\x90\x95\xbc\x33\x6d\x74\x22\xab\xc0\x84\x0f\x5c\x70\x1e\x96\xc9\xeb\xc4\xa6\xf3\x2b\xae\xab\x3a\x5e\x73\x60\xb8\x70\x3c\xd8\x5f\x9d\xe8\x1d\xf1\x0a\xd8\x35\xda\x3e\xe1\x38\xfa\x85\xfe\x3c\x93\xbe\x36\xfa\xf3\x0c\xf0\x3c\xa4\x72\x26\x91\x62\x74\x71\x5d\xa2\x18\xfb\xbd\x91\x5a\xac\xed\x3b\x56\x7a\x7d\x6c\xd9\xf8\x36\xa3\xdd\x3b\x6a\x5f\x7d\x70\xc8\x4b\x74\x4d\xb4\x99\x68\x72\xd7\x33\x74\x4d\xf8\x18\x91\x66\xfa\x9a\xf0\x47\x55\x4e\xca\x90\x2f\xd4\x7f\x80\x29\x21\x46\x26\xef\xd8\x71\x3e\x59\x11\x32\x8e\x0f\xb4\xdf\xe2\x78\xd7\x65\x88\x47\xc5\xe4\xdf\xa9\xc8\x9c\x21\x5f\xb0\x26\x3c\x8e\xa6\x39\x58\x13\xd4\x7f\x80\x21\xec\x0d\x6b\x1f\x70\x33\x3b\x5b\x1f\x26\xeb\x91\xd0\x9a\xd1\x7b\x5d\x3b\xe9\xf8\x8d\xb9\x3d\xb0\x92\x7b\x9d\x16\xd8\xf8\xb1\x51\xcf\xc1\xea\xc3\xaf\x7c\xf7\x58\xe1\xf5\x89\x65\xe3\xdb\xca\xa7\x27\x0f\x0c\x09\x0e\x79\x69\x10\xdd\xd3\x6e\xcf\xb3\xc4\xd2\x7c\xb7\xe7\xd1\xf5\x50\x0d\x16\x5a\xd8\xd3\x7f\x00\xaf\x2f\x6f\xe4\xdd\xba\x85\x61\xb2\xbe\x4b\xb5\xa5\xa3\xf7\x0c\x67\xeb\xcb\x75\x35\x21\x84\xda\x85\x26\xc4\xe5\x32\xa4\xe0\x04\xb1\xec\xa8\xc2\xc7\xc9\xd4\xec\x42\x54\x11\xe2\x48\xe5\x11\x39\x86\x06\x72\x0c\x23\x21\x8c\xc3\x7c\x7b\x7b\xbb\x76\x3f\xbe\xb2\x1d\x17\x69\x7f\x12\x9a\x88\x0a\x42\xb8\xab\x89\xef\xc7\x9e\x59\x4c\x19\x75\xc8\xae\x01\x8e\x85\x87\x5d\xc3\xf0\x40\x32\xba\x30\xdf\x8e\xaf\x6c\xa7\xff\x10\x77\x6d\xc2\xdf\xa1\x25\xfc\x13\xff\x55\x79\x8e\xbf\xeb\x21\xcf\xf3\xdf\xf1\xdf\x92\xe7\xdc\xfb\xf9\xf2\xbc\xab\x5a\x9b\x8a\x8e\x75\x6d\x43\x26\x34\x98\x9c\x59\x15\x19\x21\x1c\x8a\x00\x49\x8f\x38\x0b\x55\x78\xf8\xa8\x2a\xb8\x32\x29\x01\xc3\x74\x8c\x96\x68\x0a\x0b\xe4\x23\x36\x59\x60\x6d\x12\x75\x09\x6f\xc2\x1b\x3e\xb6\xe9\xce\x4d\xda\x64\xed\xc8\xbb\xef\x2e\xef\xe5\xd9\x0a\x97\x20\x8f\xd7\x07\x6c\x60\xcf\x36\xb0\x67\x43\x3d\x87\xc0\x59\xa2\x29\x83\xa0\xd7\x73\x90\xc3\x1d\xf6\x46\xbc\x91\xba\xc8\x31\xbc\x77\xd3\x9d\x9b\x66\x2d\x7f\xf7\x5d\x44\x9f\xdd\x0f\x1d\xeb\x3a\x84\x6c\x68\x22\x59\x1b\xc5\x98\xd0\x87\x6e\x43\x3a\xde\x3f\x85\x6c\xb9\x59\xd8\xc9\xa1\x53\x70\x1c\xf4\x13\x1f\x4f\x99\x21\xca\x6b\x26\x73\xb1\x98\xf5\x6e\xe4\x70\x99\x60\x2e\xf4\x9d\x9b\xee\xdc\xb4\xe9\xce\x4d\x87\xef\xbd\x77\xf9\x86\x0d\x88\xbd\xf7\x79\x74\xac\xab\x21\x77\xb7\x8c\x19\xf2\x95\x7f\xb7\xac\x02\x1b\x77\xf8\x18\xde\xab\x4d\x3e\x4c\xd6\x02\x97\x08\xc7\xf9\xad\x86\x13\xc8\x81\x46\xc2\x5e\x0a\xe6\x1e\xa7\x43\xdf\x52\x1c\x00\x43\xd7\x44\xd4\x66\x00\x98\x2c\x28\xe0\xd9\xa1\x13\x9f\xf7\x1f\x80\x13\x94\x68\x12\xb8\x3f\x2a\x70\xc9\x22\xf3\x94\x25\x97\xcd\x32\x5f\xed\xd8\xb3\xee\x9e\xc7\x0d\x27\xce\x69\x1c\x7e\xd6\xaa\x7b\xef\xa2\xba\xaa\xd5\x80\xf0\x12\xe0\x88\x29\x03\x7d\xcd\x0b\x19\xf2\xa5\xc7\xe5\x88\x89\x45\xbe\x28\xfc\x23\xdf\x9b\x6b\xcd\x36\xcd\x5f\x92\xc3\x46\x70\x78\xa1\x70\x9c\x8f\x19\xd7\x02\x1e\x6c\x04\x3c\xd1\x65\xa0\xfe\x83\x81\xc2\x64\xd1\x51\xd5\x1e\xc8\xb5\x5c\x0e\x50\x16\x19\xc9\x9e\x2d\xac\x86\x5e\xa4\xb4\xb0\x3a\x1f\xcf\x95\x5f\x5c\x8c\x17\xde\x70\xf9\x65\x37\xaf\x98\x7b\xf9\x0d\x57\x36\x0e\x4a\x0c\x1f\x39\x20\x3e\xd2\x90\x9a\x75\xdd\xf5\x97\x5e\x76\xfd\x75\x73\xea\x87\x0e\xad\xaf\x1f\x3a\x14\x61\x14\xd1\x86\xe2\xeb\x10\xa2\x7c\x32\x1c\xab\x0f\xb1\x18\xb3\xce\xa4\x51\x64\x6c\x32\x16\x27\xe5\xc9\xe3\x44\x15\xb1\x76\x60\x64\xf1\x72\x85\x56\x91\xd6\x95\x63\xc6\x0c\x88\xd6\x34\x9c\x3d\xf8\x43\x4d\x5b\xb7\x74\xd4\xc2\xe1\xb5\xb5\x8e\x25\x1e\x58\x43\xcc\x09\xc7\xf9\x6f\x0d\x9f\x23\x3f\x1a\x0e\xb5\x52\xbc\x39\xa3\xd8\xe2\x6d\x66\x5e\x36\x03\x3c\x0c\x76\x8f\x4e\xdd\x1f\xc8\x28\x7e\xb7\x6a\x23\xe6\x32\x9b\xba\xcd\xcf\x18\xa3\xc9\xce\xf5\xda\x30\x18\x73\xf6\x6b\x7f\xd9\xef\x82\x89\x63\x4b\xfb\x0f\x70\x5d\x6e\xbf\x76\x66\x74\xf2\x79\xe3\xca\x06\xc4\x9d\xc2\xf1\x1b\xef\x2e\x8f\x96\x37\x0e\x59\xba\x01\x7e\x41\x1c\xfa\x54\x38\xce\xbf\x08\x3a\xc6\x83\x86\x81\x66\xb7\xea\x9a\x5d\x71\xc6\x01\xa9\x28\x1c\x55\x0d\xfe\x8c\x62\x60\xde\x92\x9f\x22\x15\x89\x05\x44\x7b\xe8\x38\xa1\xe6\x80\x56\xb9\x50\x81\x1b\xce\x7e\xfa\x34\x32\xaf\xf2\xf5\xf0\xd3\xa3\x30\x17\x5b\x10\x7c\x2d\xfc\xf4\x28\xe1\x78\xb0\x56\x9d\xe4\x1d\xf4\x5a\x43\x70\x64\xfb\x20\xf2\x2b\xd5\x31\x87\xf1\x0c\xdc\xc0\xcb\xd4\xbe\xb0\xc6\x54\x83\x4d\x17\x4a\x69\x33\x55\x2f\xaa\xc1\x2a\xd2\x8e\x1f\xb8\x1b\x27\xa8\x76\x58\x2b\xf3\x0f\x8b\x9d\x3f\xa5\xfc\xaa\x15\xfb\xc6\x4f\xe7\x8e\x9c\xa5\xd3\x7b\x06\x10\xee\x8a\x09\x1b\xd1\x11\x63\x02\xd9\xd0\x10\xb8\xd7\x96\x04\x51\x1b\x56\x81\x7a\xa4\x70\x68\x15\x2e\x4e\xde\x61\x05\xb3\x43\x35\x83\x98\x37\xe9\x81\x0a\x55\x80\xdc\x1e\xdf\x50\xd9\xe0\x6f\xf0\x9b\xfc\xa6\x4a\xd3\x91\x65\xcb\xa6\x2e\x5f\x36\x6d\xf9\xf2\x69\xcb\x96\x0b\x5f\xea\x9f\xa6\x2e\x5b\x46\x39\x94\x22\xfc\x74\xe1\x10\x92\x51\x29\x6a\x84\x08\x41\xc0\x44\xe9\x17\xc4\xa3\xaa\x57\xd4\x59\x62\x55\x9b\x48\x63\x81\x5e\x11\xf8\xde\x94\x90\xa8\xf2\x4e\x60\xd3\x64\xe1\xa6\x84\xc7\x3f\x0c\xff\x08\x73\x9a\xfc\xc2\x1b\x61\xab\xff\xf5\xe7\xb5\x97\x6b\x07\x2e\x9e\x36\x6d\x51\xed\xc0\x01\xa5\x1e\x5f\x51\xb0\xa0\x20\x28\x1c\xd2\x1a\x26\x17\x0d\xc5\x2f\x77\x9e\x3d\x6d\xed\xf0\xa9\x4b\xae\xba\x68\xe8\xed\x97\x6a\x7f\x2e\xac\xa8\x0c\x05\xa6\xf4\xeb\x37\x85\xc5\x4c\xf0\x24\xb0\x8f\x0a\x10\xc4\xc2\x84\x2c\xd9\x0d\xf9\xa2\xf6\x0d\x71\xba\xb7\xa5\xf0\x1a\xe1\x9e\x53\x4b\x10\x46\x0b\xf0\x32\xee\x73\xe1\x23\x14\x46\x8b\x10\x4d\xbe\x12\x27\x1f\x80\x61\x72\x4c\x0d\x9a\xf4\x2a\x30\xc5\x17\x57\x6d\x1e\x80\x92\x90\xa9\x8a\x1e\xda\x23\x04\x5a\x8f\x95\x90\xa9\x3e\xcb\x9b\x9d\x32\x65\xaa\x16\xa5\x94\xd1\x65\x80\x30\x56\x90\xd5\x05\x9a\xc5\x36\x64\x04\x02\xf1\x6c\x24\x6b\x60\x2f\x49\x55\x96\x79\x81\x9c\xc4\x82\xd4\x96\xcd\xeb\x1a\xd7\x5e\xd6\x34\x7e\xd4\xed\xf7\x5f\xf5\xec\x93\xbb\x16\x6d\xbf\x61\xcf\xb9\x8b\x57\x5e\x1a\xe3\xbf\x5d\xb0\x6c\xe8\x1d\x83\x6b\x2a\xca\x07\xc6\x07\x2d\x39\x7f\xe9\xaa\xe4\xd6\x89\xf3\xfa\x36\x56\xf7\x1f\x71\x3e\xc8\xb3\x28\x5e\xc3\xcf\x11\x88\xdc\x47\x1e\x0b\x44\xaf\x2d\x38\x62\xc3\x51\x5c\xa7\x1d\x3f\x7c\xe8\xb5\x43\xda\x71\xdc\xf0\xe6\x87\x1f\xe1\x35\x78\x17\xde\xa2\x7d\x81\x43\xda\x3c\x6d\x1a\x8e\x6a\x1f\x21\x8c\x46\xe3\x35\xdc\x21\x63\x11\xf2\x10\x7f\xc1\x02\x21\x0f\x1d\x47\xcc\xb8\x5f\x88\x7b\xeb\x72\xd0\x0b\xe3\x72\x67\xd1\x32\x7c\x96\x19\xa1\x07\x4a\x26\x22\xd6\xe2\xd1\x7b\x77\x3f\x7e\xe7\xa8\x41\x37\x0e\xd8\x75\xff\xda\xb6\x75\x0f\x08\xdf\xdc\xd3\xfa\xcb\x95\x95\xfd\x7e\x75\xf9\x23\x7d\x3b\x0f\xe3\xcf\xcf\x7e\x9b\xca\x61\x84\xb8\xfd\x86\x5b\x91\x01\xf5\x45\x29\x81\xc8\x2a\x62\x34\x90\x01\x18\xe1\xc6\xf2\x44\x05\xf2\xa0\x0f\x50\x16\xd9\xe5\xa9\x0b\x8b\x11\xb1\x95\x0b\xac\x11\x4e\xae\x39\xb9\x52\x38\x89\xba\x3d\xcb\x84\x06\xa1\x94\x31\xf7\xac\x14\x06\xd5\x87\x79\xa6\x59\x8d\x90\x69\x33\xb8\x32\x29\x23\x28\x57\x23\x79\xb2\x25\xfb\xe4\x04\x79\x36\xde\xb8\x66\x0d\xbf\x6b\x0d\x9e\x7c\x72\x25\xbf\xeb\xff\xc0\xb3\xb9\xad\x6b\xb8\xe6\x93\x2b\xb9\xad\xff\x07\x9e\x8d\xa7\xae\xe1\x77\x9c\x5c\x89\xa7\x76\x5b\xdf\xb8\xce\xf9\xd5\xe3\xc1\x46\xda\x55\xd8\x95\x49\x71\xf0\x54\x2e\xb7\xce\x09\x78\x2a\x3c\x53\x38\x79\x72\x25\xea\xf5\x79\x10\x20\x43\x7a\x80\x2c\x8b\xc8\x73\x9d\x11\x91\xd7\xba\x06\x6f\x34\xdc\x7a\xca\xb8\xe6\xb4\x3d\x83\xec\x88\x91\xc5\xdc\x8c\xb9\x47\xd2\xd0\x82\xc9\x05\xb9\xb2\x9c\x99\xc4\xe6\xae\x77\x47\x24\xcf\xd5\x16\x1b\x6e\xed\xdc\xbe\xa6\x73\x0e\x91\xc5\x4f\x68\xf3\xf1\xc5\x5d\x2a\xb2\xa3\x12\x22\x8b\x99\xdd\x0e\x02\xd3\x11\x43\x2a\xb6\x8a\x92\x8a\xa0\x51\xb0\x21\xcf\x1d\xab\xd4\x9e\xc8\xf9\x63\x07\xcf\xd3\xdd\x31\xe0\x76\xe1\xb4\x8b\x84\xb7\xf0\x53\xc6\x19\x88\x47\x26\xe4\xa3\x16\xae\x11\xac\x4f\x03\xd1\xaf\xe6\x98\xee\x4d\xd5\x85\xbd\xda\x45\xfc\xe4\x8e\xbd\xfc\x64\xe1\xad\x55\xab\xb0\x6b\xd5\x2a\xc8\x07\xfd\x3f\x20\xbe\xa4\xed\xd6\x64\x3c\xb5\xeb\x63\x64\x24\xeb\x42\xfd\x19\xf2\x72\x3e\x8e\x15\x53\x8c\xf1\x26\x22\x8e\xae\x4b\x88\xb8\xd2\xda\xee\xed\xe9\xf6\x56\xed\x93\x39\xe5\xda\x57\x58\xd2\x92\xd9\x67\x1c\x43\x46\xea\x97\xb2\x9c\x96\x95\x06\x95\x58\x2d\x1a\x91\x0c\xe0\x8a\xdb\xb0\xb6\x1b\x47\xe6\xe0\xf2\xed\xe9\x76\x4d\xc6\xaf\x6a\x43\xb1\x4b\xfb\x27\xd8\x8d\x48\x93\x31\x87\x62\xc8\x88\xaa\x91\x62\x80\xb1\x98\x59\x64\xca\x08\xbe\x95\x59\x00\x2a\x72\x81\x0c\x0a\xf3\x60\x2d\x18\xca\xbd\x0e\xec\x2d\xef\x42\x1c\xa7\xa5\xf0\xc4\x4e\x6d\xcf\xc7\xf7\xac\xbc\x75\xfd\xef\xbb\x3f\xaf\x52\xf7\x0d\xf5\xe7\xf1\x47\x15\x04\x9e\x90\x59\x88\xaa\x1c\xaf\xbb\xaf\xe5\x06\xaf\xa1\xae\x1f\x26\x4f\xeb\xd4\xf0\x44\x2d\x15\xfb\x78\xce\xef\xd7\xaf\xbc\x95\xe6\xef\x96\x74\x1e\xe1\x1a\xba\x56\xfd\x77\xec\x3a\xcf\x19\xec\xba\x25\x37\x5e\x36\xfb\xb6\x15\xf3\x2e\xbf\xe1\xca\xc1\xc9\xc4\x88\x51\x03\x12\x23\xb4\xdd\x73\xae\xbb\x6e\xd6\xec\x1b\xa8\x59\x37\xa8\x11\x72\x5e\x8d\xdc\x68\xf4\x3a\xbf\xee\xcc\x7e\xb4\xad\x9b\x1f\xcd\x67\xfd\xe8\xd7\x7f\x1f\x9c\xd7\x6f\xe9\x59\x29\x7e\xa9\x5c\xff\xdc\xb0\x82\x81\x6f\xd2\xb3\xbc\x89\x1b\x8e\x17\xf2\x6b\x90\x19\x49\x64\xf5\x91\x6e\x55\x90\x4b\xe2\x88\x43\xac\x88\xa7\xd1\x41\x81\x27\xd3\xb1\x52\x5b\xad\xae\x9e\xda\x44\x89\xac\x75\xa4\x6d\xfa\xc5\x8c\x8f\xc3\x7b\x47\x1d\xab\x98\x57\xfa\xfb\xe2\xa7\xc7\x70\xc3\x43\x0b\x5e\x95\x1b\xdf\x48\x84\xfa\xb7\x9f\x23\xd7\xbf\x31\xa8\xfb\xfb\x2c\xd0\x45\x91\x6c\x89\x3b\xa1\x07\x4a\x6c\x60\xa3\xf5\x1a\x05\x28\xcf\xc5\x03\x36\xfd\x3e\xb2\x20\xbc\x6c\x78\x1a\xc7\x3f\xae\x98\x5d\xb1\x6c\xa4\xc2\x2f\x91\xcf\xdd\x5f\x15\xea\xff\x9b\x7a\x79\xd2\x33\xb5\xa1\xc4\x9b\xe4\x7c\xb7\x68\x2b\xf0\xbc\xae\xd5\xc8\x8f\x6a\x7b\xb1\x4b\x2d\x3d\xec\x52\xd5\x8f\xe0\x95\x67\x34\x43\xb5\x16\xf3\xd5\xd3\xab\xcf\x3f\xf7\xec\xa2\x9a\x7e\xe2\x3c\xc7\xa2\x0b\xab\xce\x9b\x70\x4e\x49\xbf\xb8\x53\x5b\x71\xd3\x5d\x91\xea\x48\x62\xd8\x4d\x77\x45\xa2\x91\xba\x61\xc4\x17\xbf\x0d\x6f\x44\xb7\x18\x65\x38\x2f\x09\xdd\xbb\x77\x09\x51\xc5\x1b\x4b\xbb\x98\x07\x0d\xaf\x56\xec\xf1\xb4\x91\x56\x80\x48\xfa\x27\xc4\x78\x00\xd9\x11\x11\xf3\x3e\xdf\x3c\x72\xc8\xd0\xd1\xa3\x87\x36\x8e\x1a\x3e\x6c\xf8\x28\xa8\xe1\x28\x1a\x75\xce\x39\xa3\x46\x8e\x6f\xe2\xf7\x8e\x1a\x37\xf6\x2c\x5a\xac\x81\xbb\xa6\x0a\x25\x68\xb7\x61\x09\x44\x02\x88\x58\xc2\x86\xac\x7b\x8a\x72\xd2\xd9\x10\xc8\xa4\x0c\x20\x47\x0d\x3c\xf5\x54\x45\xe2\x4e\xee\xc6\x53\xbe\x14\x4a\xf0\x94\x85\x5f\x9e\xfe\x2c\xea\xcb\xa7\x10\x3c\x0b\x09\xec\x59\x44\x43\x07\xf2\x35\x34\xc4\x83\xc2\x62\xa4\x6e\x37\x9e\xb2\xd0\x60\x5c\xa8\xed\x61\xcf\xc2\x5f\xa2\xdd\x7c\x63\xf6\x59\xbc\xa1\x57\xad\x11\xc8\xd7\x1a\x34\xac\xe5\x4d\x78\x77\x2f\xfc\x12\x7f\x89\xa7\x7c\xb9\x10\xf5\xfa\x2c\x32\xae\x5e\x34\x5a\x20\x5f\xa3\xc1\xb8\x12\x75\x09\x71\xf7\x97\x0b\xf1\x97\x0b\xbf\xd4\xf6\x50\x7b\xbd\x41\x9b\x8a\x0f\x77\xed\x42\x26\x54\x07\x77\x0a\xe9\x3a\x42\xe5\x4c\x19\xdd\x81\xc0\x71\xd0\x41\xa6\xa3\x2a\x17\xc8\x28\x9c\x9b\x78\xb4\xe4\xaa\x13\x59\x94\xf0\x86\xeb\x12\x62\x58\x6b\x58\xc2\xed\xbe\xae\x63\xd1\xb4\xb7\xdf\xd6\xf6\xe6\x3d\x17\xc6\x68\x88\x91\xa7\xe5\x8d\x06\xc6\x68\x80\xc7\xe9\x7f\x2a\xc0\x18\x0d\x00\x77\xd2\x1a\x96\xf0\x25\xe4\x59\x6b\x60\x8c\x31\x4d\xc6\x47\x50\x0b\xb2\xa0\x42\x04\x76\x40\x4c\xe5\x89\xb6\xb1\xc6\x90\xca\x83\xb0\x06\x6c\xbd\x01\x7b\x0d\x61\x6f\xd8\xe0\xc5\x5a\x8c\xe3\xb4\x6f\xb9\xbd\x9d\x93\xb1\xb3\x53\x5b\x8a\xc5\x65\xeb\x96\xaf\x5f\x86\x45\x84\x3b\xce\x15\x8e\x77\x66\xfe\x37\xb1\xb8\x8e\x73\x7b\x8b\xc5\x75\x9a\x84\xe3\xda\xe3\x3f\x3f\x56\x88\xb3\x32\xa3\xd3\xd4\x4b\xb0\x10\x6b\x4f\x08\xc7\xf1\xc5\x10\x9f\x2d\x3a\x3d\x3e\x7b\xc6\xd8\xac\xf6\xc4\x8f\xc4\x66\x3b\x3c\xc2\xf1\x2e\x1e\xfc\xd4\xc6\xff\x8b\x7e\xea\x4f\xfb\xa8\x1d\x9e\x9f\xeb\xa3\x62\xed\x03\xe1\x38\x8e\x43\x4c\xb6\xf8\x47\x62\xb2\xcc\x82\xd0\x3e\xd0\xe3\xb1\xff\x7f\xf6\xfe\x3c\x3e\x8a\x2a\xdf\x1f\x87\xcf\xa9\xad\xf7\xa5\xaa\xf7\xec\x9d\xce\x4a\x43\x1a\xba\xb3\x35\x04\x10\x44\xc4\xc8\x20\x32\x88\xa0\xc8\x28\xbb\xa8\x40\x44\x04\x44\x44\x45\x44\x44\x44\x40\x90\x41\x54\x44\x44\xc4\x88\x55\x9d\x36\x22\x20\x82\xc8\x30\x8a\x88\x8a\xc2\xe0\x8e\xce\x8c\x53\x9a\x71\x18\x75\x18\x85\xe4\xe4\x79\x9d\x73\xaa\xba\x3b\x21\xa8\x77\xee\xdc\xdf\xeb\xfb\xc7\x73\xef\x98\x74\x3a\xa4\xfa\xac\x9f\xfd\xf3\x7e\xa3\x51\x42\x18\x36\x0a\xbb\x01\x0b\x5c\x9d\xff\x4e\xff\xc7\xa3\xd8\x51\x42\x78\xe5\x4a\x7a\xa6\x5f\xe3\x4e\xc0\xfe\x24\xa6\xd2\xf7\x7f\x14\x53\xf9\xf9\x78\x0a\x7a\xed\x67\xe2\x29\xed\x8f\xf0\x00\x4c\x23\xf1\x94\xbc\x9f\x89\xa7\x74\x12\x70\xd7\x77\x19\x4b\x41\x9f\xf3\x56\x58\xc0\x1f\x27\x32\xb4\x17\x7e\x9a\xec\x21\x7a\x29\xca\x85\x65\x47\x54\x7b\xa5\xef\x98\xe0\x53\x75\x88\x01\xc9\x8b\x3f\x20\x33\x78\x52\x9c\xf1\x1a\x7d\x5e\x5b\x56\xda\xbb\x77\x69\x59\x2d\xbc\xab\xb6\x04\xbf\x2a\xa9\xe5\x67\x55\x45\x22\x55\x55\xd1\x68\x95\xf6\x9d\x9c\x69\x8e\xdb\x81\xe6\x08\x2b\x81\x13\x7f\xba\x43\x53\xf5\x22\x4d\xe2\xf8\x49\x12\xc7\xa6\x25\x71\x48\x02\x87\xb0\x5e\xd9\xb0\x51\x46\xb5\x63\xac\xc0\xe3\x76\xc0\x50\x29\x6d\x75\x68\xe3\x8a\x87\x42\x66\x8b\x79\x86\xbd\x7e\xf4\xbd\x55\x42\xf6\x34\xeb\xce\x07\x4a\x6e\xda\x6e\xab\xe8\x39\x02\xeb\x8b\x02\xee\x04\xf8\x42\x8b\x1b\xd5\xfd\x3a\xfb\xa2\x6b\xdb\x82\x3d\x8f\x6d\xf1\xf9\xaf\x08\x19\x01\x06\x3d\xc4\x9d\x80\x33\xb4\xf8\x49\xef\x5f\x1b\x3f\x39\x37\x76\x02\xbb\x88\x9d\xa0\x87\x7e\x55\xf0\x24\x7d\xf7\x89\xbd\xde\x39\x87\x72\xfe\xfc\x49\xa6\xbd\xfe\x5f\xca\x9f\x30\xed\x66\xee\x00\x38\x4d\xfe\xce\x80\x4f\x01\x88\xc8\x5c\x2c\xed\x40\xa4\x1e\x63\xd4\x1f\x23\xb3\xa4\x34\x4b\x31\xa4\x9e\x86\xff\xff\xf4\xe6\xcd\xda\x33\xb5\xe7\x9e\xfd\x88\x3b\x81\x76\x6a\xeb\x3c\xb0\x4b\x1b\x48\x86\xc7\x14\xc6\x47\xd4\x0c\x11\x43\x3e\x55\xb1\x30\x34\x39\x68\xd5\x31\x94\x7e\xd6\x4a\x3a\xfb\xd1\xc1\x9c\x09\xbd\x26\x0f\x78\x01\x0e\xf9\x03\x7e\x51\x27\x0b\x56\x4f\xdf\xed\x83\x02\x95\x7f\xac\x21\xdf\x7b\x6a\xbe\xcc\x3e\xee\x04\xec\x2b\xec\x03\x36\x10\x00\x57\x77\x2d\x29\x64\x5f\x44\x11\xb9\x14\x11\x80\x26\x30\xf0\xfe\xbb\xed\x04\xe4\xb6\x93\xec\x50\xdc\x76\x51\x52\x2c\x5c\x3c\xae\x18\x0d\x3a\x2c\x55\x47\x39\x52\x93\x79\x27\xf7\x4d\x37\x8c\xbc\x65\xe2\x75\xe6\x99\xe6\xc6\xe5\xcb\x9f\x7a\xbb\x6f\x8f\x9e\xb5\xbd\x2b\x7a\xf4\xe5\x5b\x06\xd7\xf5\x1b\x74\xd7\xaa\xfb\xbf\xa9\xab\xe9\x57\x55\xdd\x97\xf4\x9f\xd1\xf1\x12\xb9\x76\x21\x89\xad\xb1\x46\x35\x61\x66\x53\xe0\xdc\x42\x4a\xae\xd9\xfc\xaa\x6c\xa3\x63\xc3\x17\xc6\x46\x0d\x3c\x2c\xd7\xd8\xb8\x2c\xe8\xaa\x88\xb2\x2b\x85\x28\x4b\x0f\xda\x67\x69\x7c\x60\xf9\x53\xa6\xe9\xa6\x2b\x1a\xa6\x5c\x6b\xe4\x4e\xdc\xb5\xea\xfe\xa5\x97\xd4\x5e\x30\x00\xc0\xf6\x89\xec\x3e\xb0\x9e\xf8\x6c\x21\x2d\xe7\x2d\xa4\xf3\xe7\xd8\x9a\xb2\xab\xb4\xe8\x94\x21\xe9\x9a\x6a\x57\x4c\x30\x84\x36\x54\xde\x7e\x2f\xc9\xc4\x1f\x84\x7e\x92\x88\x87\xed\x93\xd9\x7d\x60\x43\x87\xe7\x9c\x9b\x87\x4f\xe7\xe0\xd9\x6a\xe2\xd0\xad\x1f\x58\xfc\x9a\xad\xf2\x76\x76\x1f\xfa\x37\x49\xc1\x77\x39\x1e\xbe\xc3\x78\x18\xbb\x9a\x91\x7f\x67\x49\xfe\x9d\xd9\x60\x7b\xad\x78\xe0\xbd\xb7\xf3\x1b\xbd\xff\x46\xd0\xff\x5f\x1d\xcf\xff\xdb\xf9\x31\xd8\x3e\x14\x0d\x04\xc9\xf6\x83\x99\xb9\x9c\x8c\x28\x42\xe7\x9c\x0e\x4f\xb2\x21\x9c\x43\xed\x94\x6f\xc1\xc6\x63\xa8\x2a\x94\x3c\xb9\x64\xc9\xc9\x3d\x8b\xd1\xfc\xc5\xe7\x3e\x1b\xdb\x79\x82\x9a\xe0\x19\xfd\xef\x3a\x98\x7c\xd4\x82\x14\x1c\xaa\x0c\xa3\x09\x81\x7c\xa8\xc0\x69\xcf\xa6\x99\x95\xe4\x92\x93\x27\x97\xc4\x17\x93\x47\x03\x88\x56\x73\xef\xc2\x9b\x84\x69\x69\x3b\x57\xe8\xd2\xfe\x76\x74\xb2\xbf\x21\x89\x8e\xa1\xd5\xcc\x87\xf7\xf1\xa7\x6e\x43\x53\x60\x3e\x80\xed\x3d\xb8\x06\xf0\x09\xa9\x49\x2e\xca\x88\x5a\x10\xa0\x90\x94\x9d\x06\x14\x0e\x6a\xc8\x17\x6c\x55\x3f\x58\x15\xf3\xd9\xe1\xd1\x99\xb3\x5e\xb5\x17\xbe\xcd\x35\x2c\x74\xac\x5d\xe8\xdd\xb5\x9b\xe4\xdf\x50\x0c\xcc\x6a\xff\xf2\x3f\xcc\xbf\x19\xba\xca\xbf\x4d\x99\xf7\xc3\x75\xb7\xd2\x2c\xdf\xad\xe0\xff\x9f\x7f\xfb\x1f\xe7\xdf\xfe\xd3\xdc\x36\x5a\x8b\x02\x00\x80\x51\xc0\x02\xca\x89\xf5\xc1\x98\x55\x1d\xe9\x9f\xd7\x86\xc7\x1d\x23\x5a\x4d\x61\x4c\xba\xed\x4d\x3a\x05\x62\x04\xcf\x1a\xad\xad\xa8\x1d\xbf\xe9\x54\xbf\x3a\x74\xd0\x75\x03\xac\x41\x47\xd1\x29\x3f\xc1\xa6\x41\x01\x38\x2d\xe3\xb9\x9c\x59\x4d\x70\xe4\xb9\x1c\xd4\x9e\x6b\x21\xb9\x7a\xa0\x70\x26\x0d\xb7\xa8\x2a\x26\xba\xf5\x82\xda\x4d\xe3\x6b\x2b\xea\xfa\x9d\x1a\x85\xde\xb8\xc1\xb5\xd6\x0f\x9d\xd8\x2e\xeb\x85\xd6\x21\xa1\x7d\xc1\x2f\xdb\x98\x7c\x86\x8a\x69\xeb\xd5\xbf\x7b\xb8\x7f\x9f\x48\xcf\x3e\xa7\xeb\x6a\x6a\xea\xaa\xfa\xd6\x51\x1b\x13\xad\x87\x05\xed\x93\xfe\x43\x1b\x93\xff\x1f\xd8\x98\xed\xe7\x9a\x98\xd8\xee\x43\x3d\xc1\x17\xed\x9f\xff\xef\xed\x3e\xc3\xaf\xb6\xfb\xfe\x7d\x8e\xd9\x07\x60\xfb\x1d\xa8\x0f\xb8\xa7\x7d\x11\x30\x81\x60\x67\x59\xcb\x1e\x53\x38\x1b\x8d\xfd\xd0\x5c\x4e\x5a\xd0\xde\xed\xad\x36\x26\x9c\xd7\xc5\xc6\xa3\x91\xb1\x9d\x03\xa5\xfe\xbb\xea\xf0\xb3\xe2\xc8\x0d\xde\x06\x00\x88\x20\x0c\x12\x46\xca\x98\x40\x2b\xa0\x24\x72\x9d\xac\x4e\x55\xb1\xf2\xd4\x2a\x50\x8c\x0c\xc9\x3d\xea\xc0\x83\x95\xa5\x35\x31\x83\xc6\xd5\x79\xb0\x68\xc8\xa5\xbf\xd9\x35\x7a\x4e\x55\xe2\x91\x75\x03\x8a\xd1\x0a\x73\x69\x6c\x8c\x5f\xbe\xa9\xe4\xfe\x09\x37\x5a\xf0\xe7\x8c\x41\x7d\xc1\x73\x24\xbf\x19\x3e\x5f\x7e\xb3\x8b\xdc\x26\xdb\x29\xb7\xf9\xcc\xcf\xe5\x36\xff\xe3\x1a\x93\xd5\x68\x20\xbc\x89\xc8\x96\x2a\x4d\xb6\xe0\x3f\xb5\x72\x61\x19\x38\x15\x5e\x50\x93\x06\xf2\x53\xa6\x36\x10\x68\x3c\x81\x71\x90\x93\x15\x14\x43\x55\x41\x4f\x88\x88\x6f\x54\x7d\xdf\x78\xb4\xf9\xe4\x49\x00\xd1\x02\xb4\x16\x2e\x6e\x5f\x04\xbc\x60\x1c\xf6\x61\x65\x67\x0c\x9f\x14\xd9\x14\x4d\xb0\xa4\xaf\x99\x05\xa6\xb0\x22\x58\xa3\x51\x1d\x08\x45\x33\xd5\x04\x6c\x93\xfa\x49\xe5\x3b\x3e\xbe\x36\xbf\xaa\x08\x90\xa6\xea\x0c\x04\x9d\xc1\x4a\x4a\x3f\x29\x6c\x9e\x44\x42\xbe\x6e\xbc\x1f\xfa\x57\xc2\x9d\x8a\x4f\xf6\x82\x19\x33\x63\x17\x8c\x9f\x15\xbb\x60\xfa\x9c\x69\x33\xaa\xaa\x66\x4c\x9d\xb3\x60\xc9\xc0\x8b\x96\x0c\xbc\xa8\xe1\xf6\x8b\x2f\xbe\x0d\xfc\xdf\xc4\xdb\xf1\x33\xa7\xc0\xab\xdb\x5f\xa0\xf1\x00\x5b\x44\x36\xc4\x52\x47\xd4\x1e\x01\x0a\x4b\xf9\x50\x88\x35\x97\x0e\x07\x84\x3a\xc4\x03\xe6\xa3\x3b\x3a\xc4\x03\xd0\x6b\xe8\x5e\xd8\xbf\xfd\xf7\xff\x6b\xff\x98\xff\x39\xff\x78\x8a\xee\x1e\x43\xb4\x0f\xdd\x03\xfb\xb6\x3f\xf2\xff\x85\xdd\x8a\xee\x49\xdb\xad\xe8\x3e\x74\x1f\x9c\xdb\xfe\xd0\xff\x49\xdc\x03\xdd\x77\x9e\xb8\x07\xba\xef\xdc\xb8\xc7\x7f\xa8\x9b\xaa\xd0\x01\x78\xa8\x7d\x08\x8d\x7b\x74\xac\x29\xd1\xff\x71\x15\xbb\xb6\x75\xda\x8e\x45\x5a\x6e\x06\xc5\xe1\x73\xed\x87\xf4\xdc\x8c\x21\xa2\x70\x82\xaa\xfd\xa1\x96\x9b\xc1\x7f\x44\x22\x6c\x5a\x6e\xa6\x75\x7b\xd5\xa2\x07\x16\x01\x88\x1a\xe1\x16\x38\x8c\xd9\xfe\x7f\xb3\x56\x8d\x96\x49\x57\x94\x5d\x7a\x51\xff\xdc\x6e\xdd\xec\x53\x2c\x13\x47\x95\x0c\xb9\x68\x40\x5e\xf7\x6e\x36\xb8\x45\x5b\xab\xb9\x0f\xea\x6b\xb5\x1a\x22\x38\x83\x59\xfe\x73\xb1\x9e\xd5\xcc\xc7\x10\x69\x7a\xbf\x2d\x1f\x22\xe6\x24\xb3\xe2\x67\xfe\x7d\x5b\x3e\xff\x1a\x44\x7a\x6c\xe8\x38\x9c\x03\xc3\x6c\x18\xb0\x20\x87\xc8\x35\x3d\x69\x43\xfc\xe1\xf4\x4e\x98\xa0\x0f\xa2\xe3\x8c\x71\x68\xdb\x69\xf8\x1d\x8c\x2f\x40\x6f\x00\x88\xa6\xb5\x2f\x85\x6b\x05\x27\x60\x01\xe0\x61\x0c\xa2\x69\xcc\x43\x1b\xda\x66\xce\x11\x96\xfc\x34\x0f\x9c\x63\x17\x0a\x11\xc5\xc0\x13\x58\x55\xa0\xd9\x85\x66\x1a\xdf\xed\x70\xf2\x81\x62\x33\x90\x22\xe6\x9e\xbd\x0c\x54\x8b\x69\x15\x60\x37\x4d\x9d\x4b\x2d\xc3\xdc\xd9\x13\xc7\xcf\x26\x85\x59\x5d\xc9\x57\x5d\xb8\xf2\x51\x6c\x79\xeb\x3f\x71\xe9\x78\xad\x23\x1d\xaf\x75\x74\x88\xd7\xae\xbe\x0f\xbe\x79\x5f\x5b\xc9\xf8\x2f\xbe\x40\x9b\x01\xd3\x5e\x85\x7a\x80\x23\xed\x07\xc9\xd9\x29\x23\xa7\x8d\xa7\x56\x2d\x19\xbd\x91\x48\x7d\xde\x4f\xa2\x1f\x58\xa4\x32\x24\xf8\x6b\x08\x8a\x41\x97\x27\x56\x75\x08\xae\x47\x93\x67\x25\xe3\x68\x32\xec\xb1\x77\x2f\x19\x67\x07\x79\xed\x8a\xc8\x36\x2a\xaf\x0d\xd1\x84\x8b\xcc\xdf\x85\xe5\xb5\xd9\x99\x96\xd7\x5e\x3f\x01\xdc\x21\x5c\x1c\x7e\xd2\xcb\x8d\x0f\x98\xd9\xaf\x2a\xa2\x97\xb2\x5a\x38\x45\x99\x27\x85\x15\x06\x2c\xaf\x5d\x5a\x82\x0d\x52\x18\x34\x6c\x03\x84\x48\x4b\x0c\xfd\x8a\x16\x60\x31\x5d\x3d\x7d\xea\x9c\xe9\x0d\x44\x6e\xf7\x47\x6b\x1b\x6e\x1f\x32\xe4\xb6\x59\x54\x6a\x83\xff\xcf\x6b\x4a\x60\xfb\x02\x6e\x03\x58\x24\x7c\x0b\x7c\xb4\x42\x87\xd4\x06\xda\x22\x8a\x55\xb3\x78\xb8\x63\x84\x32\xc7\x1a\x6d\x72\x7a\x38\x63\x58\x31\x39\x55\xe2\x9e\xc4\x14\xa7\x53\x05\x8a\x0d\x62\xf3\xc7\x13\x4f\x95\x09\xd2\x16\x4e\xe2\x4a\x10\x88\xe8\x45\x75\x7d\x8a\xc3\xc5\xab\x6e\x26\xdf\x1e\xe2\x36\x4c\xed\x9e\x13\xa8\xed\x77\x51\xc9\xa5\xd7\x4c\xa9\xc8\xf1\x54\xf5\xbb\xb8\x6c\xe8\x38\x22\x27\xae\x14\x72\xe0\xb3\x86\xed\xbf\x2a\x87\x7b\x25\x95\x13\x42\x4e\x2a\x87\xfb\xdf\xaf\x67\xfd\x6f\xd7\xdb\xde\xc7\x9d\x80\x73\xff\x8f\xe2\xdd\xe7\x95\xfb\xe7\xc6\xbb\xdb\xef\xe0\xa6\x83\x7b\xf8\x66\x60\x02\x21\x90\xe0\xb4\xf8\x82\x3e\x33\xee\x98\xc2\xdb\x68\x08\x91\x46\x89\xd2\xd3\xd2\xad\x4b\x6e\x7a\x20\x65\x5d\x02\xc0\xa2\x7d\xdc\x3b\xb0\x9f\x30\x17\x98\x81\x0b\xe4\x81\xab\x49\x2e\x24\x87\x44\xcf\xb0\xd5\xee\x8d\x12\x58\x47\x70\x4c\xe1\xbd\xe4\x9e\xba\x61\x58\x09\x78\xd5\x26\x47\x00\xcf\xdb\xee\x23\x10\x57\x0e\x9f\xaa\xd8\x79\x51\x52\x2c\xae\x78\x5c\x09\x60\x3b\xda\x9b\x43\x42\x6a\x46\x51\x4a\x58\xac\xae\x38\x2d\xc0\x4b\xdb\xd4\x7a\xba\xb3\xa6\x32\x23\x6c\xf5\xbb\x92\xda\xda\x92\xf2\xea\x6f\x6b\x8b\x0e\xe4\x36\xf4\x5d\x30\xae\x38\x1e\xed\xde\xad\x92\xaf\x99\x48\x4c\xfc\x88\x7f\xc5\x46\x77\x9f\xe7\x2f\x15\x26\x46\xaa\x7a\xf4\x8e\xe2\x3d\x56\x50\x5f\xf0\x4e\xfb\x5d\xc0\x86\xfd\x21\x33\x39\x6a\x09\x9e\x70\xcc\xf1\xc4\x1f\xb2\x47\x64\xdb\x31\x85\xc1\x96\x6b\xaa\x3e\xcc\x10\xcb\x84\x3c\xbf\x6c\x7d\x5e\x91\xaf\x7b\xf5\xc5\xf5\xa3\x17\xce\xe8\x51\x6e\x99\xe3\x1a\x37\x09\x40\x34\x90\xdb\x0d\xf7\x08\x01\x2a\x0f\x53\x79\x78\xab\xd6\x5b\x9a\x12\x89\x99\x35\x14\xb4\x89\x54\x61\x89\x3c\x84\x22\x35\x38\xd1\x40\xf6\xf6\x25\x6d\xab\xb8\xdd\xf0\x1a\xf4\xd4\x17\x5f\xd0\x7b\x82\xe2\xf0\xd9\x5f\xa9\x4f\xaf\xec\xa0\x4f\x99\x76\x33\xba\x16\x9c\x26\xf6\x33\x89\x9f\xb2\xd8\x13\xd6\x93\x6b\x5c\x34\x75\x10\x8c\xba\x39\x8d\xa5\x34\xb1\x7b\x52\x56\x35\x8c\x89\xa1\xd3\x9b\x37\xc3\x21\xc4\xba\xd6\xea\xda\xdb\x07\x22\x37\xd8\xd3\xbe\x38\x95\x57\xc3\x8e\x7b\x3a\x93\x49\x62\x22\x2c\x11\xfb\x09\x96\xc9\xc8\x23\x1a\xf0\x2c\x43\x7b\xe0\xed\x4b\xfe\x35\x1f\xad\x38\x4d\x75\xe1\x12\x6e\x39\x9c\x23\xf4\x00\xd9\xe0\x32\x70\x1e\x5a\xba\x4e\x9c\x74\x36\x18\x56\xec\xd8\x32\xcb\xc6\xf7\x44\x8c\x9f\x8f\x8b\x8e\xc2\xbb\xd6\xf8\x0c\x19\x5c\x74\x86\x52\xd2\x47\x61\x40\x4b\x6c\xb3\xae\xeb\x3d\xf4\xa2\xb1\x17\xf6\x2c\x22\x77\xe8\xd6\x6b\xe2\x57\x0f\x1d\x5b\xdf\x23\xd0\xab\x17\xb9\x45\xa5\xb3\x6b\x66\x05\xfa\xd4\xcd\x5f\x16\x59\x50\x3b\xd7\xd5\xa7\x8e\x9c\xfd\x25\xdc\xe3\x70\x8e\x61\x22\x41\x16\x8b\x80\x99\x40\x0e\x46\x92\xd9\xf4\xe0\x77\x7d\xc3\xe5\x1e\x91\x64\xa9\xe6\xc5\xf6\xcc\xbc\xeb\x7e\x18\x96\x8b\xa2\x4a\x9e\x57\x95\xbb\x11\x20\x11\xfd\xf2\xfb\x7d\x1a\x0d\x8e\x9c\x27\x2a\x82\x44\x29\xb1\x8d\x3f\x27\x0c\x7c\x19\xbe\x67\x66\x6d\x03\x99\x62\x4a\x48\xd8\x1a\xae\x0b\xff\x16\x0b\x89\x5e\x76\xb9\xb6\xac\x22\xda\xbb\xa4\xac\x96\xa9\x2d\xc1\x2f\x4a\x6a\xf9\x05\x1d\x4d\xa0\x79\xd5\x15\xd5\x15\x55\xbd\x7a\x31\xbd\xb4\x17\x80\x41\x5b\xb9\xe3\x70\xb4\x80\xe5\x59\x04\xe6\xd1\x9a\x19\x85\xb3\xc4\x62\x8a\xdb\xa0\xca\xae\xd4\xb4\x0d\xaa\x02\x9c\xd1\x28\x61\x80\x8f\x29\xd9\x06\x55\xc9\x09\x45\xa3\x4d\x05\xd9\xdd\x8d\x61\xa5\xd4\xa0\x2a\xfe\x32\xac\x6e\x7b\x46\xe4\xea\xac\x9d\x7f\x5f\xf7\x5a\x92\x34\xb5\xbb\x2a\xec\xb2\xe0\xe4\x65\x97\x53\xe1\xb2\x7f\xc2\xce\x98\x33\xfb\xa7\xf4\xaf\xc3\x15\x76\x39\xcf\xc9\xcb\x61\xa7\x92\x93\xfd\x13\x5e\xae\xb2\xec\x9f\x76\xfe\x95\x39\x70\x0f\x41\x2c\xe6\x9c\x4d\x3c\x27\xb8\xc2\xb2\xcb\xd9\x24\xba\x9c\xae\x70\x93\x84\xbf\xca\x39\xce\xa6\xdc\x9c\x3c\x57\x58\x0e\x3b\x9b\xca\xc3\x65\xae\x70\x53\x37\xfc\x35\xc1\x73\x42\x06\xb0\xb1\xe4\x72\x8a\x52\x5c\x16\xe3\x89\xdc\x9c\x3c\xfc\x46\xb7\x70\x19\x7e\xa3\x3c\x0e\x5e\xe2\x05\x51\xca\xcd\x2b\xef\x96\xd1\xd1\xce\xf1\x82\x53\x94\x5c\x39\xb9\x79\x65\xe5\xdd\xc2\x5d\x74\xb4\x9f\x6f\x9f\xd8\xae\x45\xf9\x56\xf3\xd4\x2b\xba\x0d\xbf\xe4\xc2\xbc\x70\x89\x7d\xb2\x65\xd2\x95\xa5\xbf\xb9\x64\x70\x7e\x49\x37\xc7\x54\xf3\xc4\x31\xa9\xf7\xcd\x93\x53\xef\x73\xc7\x67\xde\x96\x5f\x9c\x5f\x1d\x99\x79\x5b\x7e\x51\x7e\xf7\x5a\x98\x7f\xc3\x1d\xf9\x45\xf9\xd5\x15\xd3\xe7\x93\x9f\x69\xed\x45\x7f\x38\xb9\x7d\x07\x30\x81\x00\x96\xcf\xd8\x2a\xa3\x89\x6a\x2c\x5f\x15\x40\xda\x0e\x60\xb1\x27\x56\x65\x83\x55\x21\x0f\x5a\x0f\xc1\x5b\x10\xb4\x83\xb7\x50\xeb\xee\x85\x0b\x77\xbf\xb2\x70\x21\x80\xed\x83\xc9\x1d\x3f\x0c\x04\x10\xd4\x6b\x82\xb4\xc2\x22\x2d\x28\xa7\x70\xbc\x5e\xb2\x61\xa8\xf1\x85\x3c\xa1\xaa\x9d\xbb\x77\xcf\xbd\xef\xf4\xfe\xfd\xa7\x4f\x03\x7f\x5b\x31\x00\xcc\x47\x7c\x33\xe0\x81\x09\x38\x40\x00\x84\x40\x0f\x50\x03\x06\x80\x4b\xc1\x6f\xc1\x95\xe0\x6a\x30\x01\xdc\x00\x66\x83\x05\x60\x09\x58\x09\x7e\x0f\x36\x81\x6d\x40\x06\xcd\x60\x27\xd3\x53\xab\x68\x1b\xf9\x5c\x8c\x58\x6b\xca\x15\x8d\xd1\x28\x79\x4b\x77\x65\xb7\x47\x65\xe8\x94\xc7\x15\x1c\x13\x95\xf1\xbc\x9a\xb0\xe0\x93\x38\x26\x11\x8b\x29\x76\x5e\x55\x46\x2b\xd1\x28\x79\x2b\x69\xa6\xff\x3a\x19\x95\xcd\x4e\x79\x44\xc1\x31\x51\xbe\x3d\xa6\x0c\xe3\x55\x79\x2e\x79\x67\x1a\xfe\xfb\xc9\xbc\x9a\xe8\x0d\x41\x58\xbe\x3f\xa6\xf4\xe7\x55\x79\x45\x34\x79\xc9\x20\xd0\xdb\x16\x96\xa7\xc7\x94\x4b\x78\x55\x9e\x15\x4d\x56\xf5\x24\x6f\xdc\x19\x53\xaa\x78\x55\x5e\x1c\x4d\xe6\x06\xc9\x1b\xeb\x62\x4a\x2e\xaf\xca\x0f\x47\x93\x06\x81\xbc\xf1\x12\xa9\x20\xc3\x9f\xb9\x23\xda\xe4\x37\x08\xc6\xb0\xfc\x6c\x4c\x91\x78\x55\x7e\x3a\x9a\x2c\x0d\x93\x7f\xf3\x64\x4c\x29\xe5\x55\xf9\xb1\x28\x94\x77\xd1\x30\x89\x39\x1a\xc5\x16\xb9\x62\xb4\x47\xa3\xd8\x6c\xc1\x7f\x6f\x8d\xca\xbc\x53\xf6\xe0\x11\x12\x33\x34\xa2\x78\xfc\x6a\x53\x16\x0f\x8c\x61\xb9\x28\xa6\xe4\xfb\x55\xb9\x3c\x2a\xb3\x84\x77\x58\xae\x8d\x2a\x51\xbf\x2a\xd7\x45\xe5\xa8\x53\x19\x09\xc3\xf2\xe8\x68\xf2\x4a\xfa\x9c\xab\xa2\x4d\x83\xaf\x1c\x69\x0c\x2b\x03\xfd\xaa\x3c\x30\x22\x0f\x8d\x29\x83\xfd\xaa\x3c\x3c\xda\x74\x2d\x79\x7b\xac\x5f\x95\xc7\x46\xe4\x89\x31\xe5\x5a\xbf\x2a\x4f\x8d\x36\xdd\x88\xdf\x96\x6f\x8d\x29\x33\xfd\xaa\x7c\x5b\x54\xbe\xd2\xa9\xac\x82\x61\x79\x7d\x54\x59\xeb\x57\xe5\x27\xa2\x4d\x77\xaf\x5d\x65\x0c\x2b\x77\xf8\x55\xf9\x8e\x88\x7c\x5f\x4c\xb9\xdb\xaf\xca\x0f\x44\xe5\x55\x4e\xf9\x29\x3c\xda\x67\xfc\xaa\xbc\xd6\xa9\x3c\x0f\xc3\xca\x8b\x2f\x45\xa3\x8a\xec\x57\x95\xa6\x97\xa3\x51\x85\x67\x45\x49\x91\xfc\xf1\x38\x01\x4e\x6c\xca\x0d\x96\x12\x90\xaf\xb5\xab\x44\xe9\xc5\xa7\x9f\x7d\xae\x51\x49\xe0\x1f\x9f\x79\x4a\x94\x9a\x1e\x5e\xf7\xd8\x93\x04\x43\x05\xb2\xa2\xf4\xe2\xc0\xc1\x63\xaf\xbd\x71\x26\xfe\xe5\xb0\x11\xa2\xa4\x4c\x9c\x1a\x8f\x2b\x93\xa7\x89\x52\xd3\xd0\xe1\xb7\xde\x46\xf0\x58\x83\xa4\x3a\x05\x8a\x31\x91\xd6\xcf\xb8\x52\x26\x02\x91\x8c\x1e\xb7\x5e\xc4\x43\x5e\xe1\xdf\xea\x85\x3d\xfa\xab\xce\xef\x85\x0a\x5d\x9a\xe5\xc9\x6a\x3f\xa7\xde\x3f\xf7\x5f\x9e\xf7\x79\xf8\xaf\xb4\x4f\xf5\xa5\x1e\x1b\xab\x8a\x89\x24\x35\x50\x15\x80\x31\xb1\xad\x78\xfa\xbb\x68\xdf\xf4\xe9\xb0\xff\xbb\x73\x6a\xb3\x73\x72\xb2\x6b\x8b\x73\xb2\x6b\xe9\xab\xda\xec\x9c\xd1\x35\xb5\xf9\x01\x7f\x3e\xfd\xba\xaa\xa6\x26\x2f\x10\xc8\xab\xa9\xa9\xa9\xb9\x08\x0e\x42\xbb\xe1\xa0\x13\x35\xda\xff\xc9\xe9\x5f\xad\xac\xad\xc9\xf7\x07\xf2\xe9\xd7\x6b\x6b\x6b\x6a\x6a\x73\x72\x6a\x6a\x6a\x4b\xf1\x2b\xcb\xd1\x1b\xd1\x3e\xd8\xff\xc6\x1b\xe1\xc0\xa3\x33\x98\x3e\x70\x20\xda\xc3\xd4\xc1\xfe\xd3\xdf\x45\x13\xc9\xdf\xcf\xc3\x8f\xc8\x83\xf3\xf0\x9f\xe7\xa1\x6e\x35\x35\x39\x39\x39\xcc\xa3\xe4\x5b\x5b\x3f\x32\x2a\xf6\xca\x9a\x9a\x9a\xb3\x7b\x66\xcc\xe0\x87\x4c\x9f\x7e\xf6\x83\x9a\x9a\x5a\xf6\xc5\x9a\x9a\xda\xd6\x8f\xd2\xbf\x6d\xbb\x2a\xf3\xef\x50\xf7\x9a\x9a\x1a\xf8\x08\x7e\xe2\x3c\xfc\xcb\xb1\x33\x8e\xa2\x3d\xfc\x90\xe9\x68\xdf\xbb\xad\xdf\xe3\x01\xd0\x38\xdf\x48\x6e\x07\xd8\x2c\x8c\x00\x56\x50\x4a\x6c\x6f\x41\x93\x35\x36\xe2\xfd\xf0\xd1\xa4\x99\x9c\x67\x4a\x6a\xc4\x52\x3b\xb5\xba\xa6\xa4\xb4\x2a\xe6\xf5\x79\x04\x43\x63\xf9\xea\xeb\x7f\xeb\xfd\xfc\xaa\xdb\xf6\x72\x3b\xae\xcf\x19\x12\xab\x9c\x3c\x33\xf0\x40\xde\x14\xfa\xec\x20\xb7\x1f\x40\x61\xd6\x7f\xa5\x4f\xe9\xb3\x54\xdf\xe9\x86\x8c\x3e\x25\x3d\x87\xbb\x83\xe4\x70\xaf\x01\x09\x11\x4b\x24\x1f\xa7\x9e\x27\xcc\x94\x95\x19\x66\xea\x94\xc5\xcd\x88\x38\xd1\x2c\x2e\x6b\x8e\xc7\x29\x88\x67\x17\x71\x27\x5f\x87\x2c\xae\xa5\xf1\x81\x87\x36\x92\x18\xd4\xf8\x89\xa6\x49\xa9\x2c\xee\x96\x3b\x57\x2d\x5b\x72\x49\x6d\xdf\x41\x57\xd5\x55\xf7\xd5\xd2\xb8\x00\xb6\xf7\x45\x35\x60\x7f\xfb\x6e\x60\xc1\x7e\xa0\x41\xf7\x3b\x2d\x5a\xa1\x15\xf5\x3b\xcd\xd1\x24\x47\x0a\x1a\xb1\xdf\xc9\x11\x38\x7f\x83\x85\x94\xd7\xb3\x06\x51\x52\x18\x62\x66\x19\x52\x7e\x67\x69\xcd\xfe\x51\xd7\x4f\xbc\x6e\xd2\x14\xf2\x75\xfd\xa8\xc9\x13\xaf\x9d\x78\xfd\xa8\x29\x93\xae\x9b\x88\xf7\x18\xb9\xc1\xe6\xf6\xed\xc0\x4a\x6d\x6f\xec\x30\xe8\x7b\x6c\x25\x6d\x19\xd4\x28\x55\x8c\x04\x0f\x46\x20\x06\x8f\x81\x86\x27\x69\x44\xb1\x71\xee\x3e\x5f\xf7\x95\xb3\x87\xf8\x3e\xfc\xdd\xf1\xbc\x29\x53\xf3\x2e\xee\xdd\x7d\xca\x4d\xb9\xf4\xfc\x68\xcf\xb6\xe1\xf3\x63\x24\xf1\x08\x33\x0d\x4e\xca\x46\x52\x6f\xca\xd1\xf3\xc3\x19\x29\x84\x02\xb6\x6d\xbd\x3e\x12\x44\x27\xe7\xa8\xd1\x7b\x74\x4a\xa5\x3c\xca\x8b\xcf\xd1\x88\x69\xf9\xcb\x6c\x97\x56\x90\x73\x84\xf7\x76\x09\x72\xc3\x15\xe4\xd9\xb9\x58\x13\x1a\x23\x8a\x37\x27\x16\x4b\x7d\x44\x5e\x04\x28\x00\x6b\x55\x31\xa0\xc7\x54\xd3\xcf\x25\xf1\x50\xe2\x76\x96\x94\x1a\x04\x43\x08\x2d\xf1\x7d\x30\x31\xf2\xdc\xef\x7c\xa5\x6b\xa7\x5f\x06\x6f\xca\x1d\xe3\x59\xe6\x19\x91\x37\xb5\x7b\x6f\x7f\xf7\xe0\x54\xfc\xc1\xd6\x21\xd1\xeb\xb3\xea\xab\x7b\xa1\x6f\xe2\x7f\xbe\x70\xe4\x87\x51\x7f\xdf\xad\x75\xb3\xaa\x29\xf7\x04\xb7\x1f\x7c\xae\x9f\xe3\xff\x71\x4f\x9f\xd8\xa1\xa7\x4f\x6f\xd1\xde\x9f\xd9\xd2\x07\x20\x14\x78\x00\x4f\xfc\x9a\xfa\xa1\xcc\xf2\x1e\x28\x74\x51\x40\x04\xdb\x4b\x91\x1b\x9c\x68\x4f\x00\x3b\xde\x13\x2b\xa9\x64\x61\xb5\x35\x23\x54\x65\x49\x83\xe6\xa2\xb3\x56\xbd\xef\xb0\xc6\x57\x1a\x33\xa4\xce\xd2\x89\x1e\x0b\xb3\x1f\xca\x5e\xd8\x63\xc5\xd4\x59\xfd\xfb\xcf\x9a\x8a\x4e\x2e\xb9\x68\xc5\x8a\x8b\x96\xb8\x27\x8c\xba\xe7\x9e\x51\x13\x88\x3d\x3e\x07\xb9\xe1\x92\xf6\x03\xc0\x05\xf2\x41\x18\xcc\x20\xfe\x83\x2d\xa6\xf8\x78\x55\x0e\x45\xe5\xdc\x88\x5c\xae\x07\x7c\x74\x74\x7c\xb7\x9f\x5c\xb5\x2c\x18\x56\x0a\xfc\x04\x52\xb6\x44\x0b\xf0\x64\xb9\xf1\x26\xb2\x71\x82\x61\xe5\xe0\xe3\x71\xb9\x44\x52\x6c\x24\xcc\x42\x78\x1b\x1d\x71\x39\x57\x54\xcc\x20\x0d\x89\x92\x11\xf4\x49\x45\xe8\x33\x93\x3f\x7c\xc6\x6b\x34\x67\xee\x94\x59\x35\x55\xb3\xa6\xcc\x9d\x3b\x65\x56\x55\xbc\x81\x66\x84\x2e\x18\x10\x8d\x0e\x80\x23\x2e\x88\xd5\xf6\x19\xd8\x2b\x3a\x00\x7d\x3b\x7e\xf6\xf0\xe1\xb3\xc7\x4f\x9a\x3d\x62\xc4\xec\x49\x24\x41\x54\x57\x57\xad\x7d\x27\x77\x96\x3b\x00\xf6\x0b\x83\x80\x01\x5c\xa2\x59\xe0\x06\x5e\x4d\x18\xd8\x54\x16\x9d\x35\x74\xa8\xd7\x87\xa9\x5a\x49\x01\x86\x15\xde\xaf\x2a\x0c\xa4\x24\xba\xd8\xb0\xa5\xb5\x52\x6c\x4d\xcc\x10\x33\x84\x6a\xf6\x0f\xbe\xbe\xb8\x75\xf0\xf5\xc5\xfc\xb0\xd3\xf7\xff\x6b\xa9\x26\x97\x51\x39\xbf\xb0\x7d\x1b\xb0\x02\x87\x1e\x33\x27\x59\x04\x72\x7f\x82\xd1\xa2\x9a\x98\xc0\x05\x0b\x8a\x1a\x57\x6c\x80\xa7\xfe\x06\xeb\x2f\x5b\x71\x1d\xba\x19\x9d\x44\xef\xa2\x29\xa3\xbe\xbd\xed\x96\x3d\xfb\xff\x40\x64\x7b\x82\x5f\x28\xc4\xba\x78\x06\xfb\x0b\xcf\x10\x62\xda\x43\xc8\x58\x06\x72\xc7\x39\x3b\x3f\xf5\x3c\x31\x56\xb6\x2a\xe8\xd9\xc3\xbd\xc5\x1d\x27\xbd\xd3\x03\xd1\x7b\x9c\xbd\x7d\x42\x3a\x66\x9d\x8e\x75\x6b\xcd\x8f\x7b\xb8\xb7\xce\x56\x3e\xb6\x92\x8c\xef\x23\x7e\x21\xff\x25\x70\x03\x05\x90\x40\xa9\x3d\x46\x59\x2b\x84\x68\x93\x64\xb0\x19\xc3\x0a\x63\x50\x15\x96\x10\x08\x79\x32\xcf\x90\x89\x1e\x1c\xec\xc7\x7c\x7f\x6a\x5f\x09\x71\x54\xec\x15\x32\x5b\x41\x28\x65\x73\x7f\xb2\x63\x03\xcd\x99\xfb\x93\xcc\x3a\x9b\x38\x56\x70\x85\x9b\x78\xfc\x55\x76\x3a\x9b\x1c\x4e\xbb\x2b\x9c\xe0\xd8\x0c\x37\x44\xe6\xe3\x09\x87\x13\xbf\x02\x4d\x1c\xef\x70\x52\x5a\x15\x96\xe3\x05\x3b\xfd\x41\x73\x2f\x08\x16\x8b\xc2\xd8\x88\x7c\x64\xa5\x20\xf1\x28\xd2\x0e\x85\xa1\xb1\x02\xd6\xcd\x7a\xf7\xf0\xfb\xb7\x7e\x96\x3f\xd5\xfb\xe2\x63\xb3\x8f\x1e\x3e\x3a\xfb\xb3\x7c\xee\x23\x28\x94\x44\x4a\x16\xdc\xb5\x18\x7f\xd5\x74\x6e\xc6\xbe\x98\x3a\xec\x4b\x75\x51\xb0\x80\xf3\x85\x4a\x82\x85\x9c\xa1\xf1\x3a\xf8\x20\xcc\x87\x11\xf8\xfb\x2b\x56\x6c\x40\xce\xbf\xa1\xe6\xcb\xb8\xc4\x9e\xfd\x7f\xd8\xf5\xed\x6d\xb7\x68\x67\xa4\x3f\xbf\xb0\x7d\x07\x10\x80\x8f\xc4\x9b\x49\x58\xc2\x80\xa5\xa2\xa0\xc7\x94\x83\xd8\xcf\x08\x36\xf2\x61\xec\x64\x9c\xf9\xe0\x20\x76\x31\x48\x6c\xe3\x13\xa6\x1c\x16\x73\x2a\xf0\x83\x10\xb8\x15\xc8\xde\x88\x92\xc3\x13\x54\x6e\x86\x0a\x37\x1b\x9f\x02\xe7\x0e\x88\x3a\xee\xae\xcc\x46\x15\xa7\x48\x82\xb3\x92\x5f\x95\xa5\x88\x12\x00\x7a\x05\x5c\xbe\x98\x30\xd8\xbc\xf1\x78\x5c\x96\x24\xc2\x5d\x94\xe3\xc5\x76\xa7\x18\x8f\xcb\x41\x51\x01\xae\x78\x5c\x31\x30\x14\x0a\xc6\x26\xd2\x34\x7a\x65\x71\x8d\x86\xe9\x50\xaa\x31\x18\x96\x6a\xa0\xdd\x14\x33\xd2\x60\x87\xe8\x13\x38\xea\xda\xfe\xf1\xe8\x94\x9e\xe1\x39\x8b\x16\xdd\x35\xcb\x59\x35\x79\xe0\x8c\x79\x6b\xeb\x2a\x46\x4c\xbc\xfc\xc6\x09\xcc\x8f\xef\x5a\xb9\xec\x4b\xeb\x8a\x3c\x53\xfb\x4f\x9f\x87\x62\x93\x06\xf4\x9c\xfe\xbb\x9e\x15\x57\x8d\x8a\x70\x5c\x6f\x9a\x13\x39\xc2\x94\xc3\x18\xd7\x02\x5c\x20\x0b\x0c\xc6\x52\x4a\x31\x0b\x2a\x56\x25\x6e\x9e\x00\x64\x11\x63\x24\x9b\xd6\x9f\x1a\x28\x26\x80\x01\xcf\xc9\xed\x21\xa8\x14\x1a\x6d\xac\x51\x94\x6d\x1a\x17\x98\x2e\x81\x73\x61\x30\x83\xb0\xa5\x26\x48\xcc\x02\x74\xe4\xd9\x55\xf7\x3f\x81\x7a\xd9\x5f\xae\x9c\x78\x79\xed\xf4\x4b\x36\x25\x7f\x0f\x2b\xf9\x8b\x87\x0c\xba\x9c\x5d\xbc\xe9\xc0\xd6\x07\x87\xbd\xe9\x0d\x2e\x08\x78\x77\xfe\x50\x7f\xd5\x95\x34\x0f\xbe\x9d\xa9\x02\x23\xf8\x0f\x80\x05\x38\x40\x09\x3d\x0d\x2c\x4d\xe4\x5a\x09\xbf\xa0\x43\xc4\xd7\x41\x71\xa4\x72\xdf\x1d\x2b\x1d\x5d\x62\x4c\x1c\xd1\x2b\x54\xd0\xb3\x67\x41\xa8\x97\x71\x15\xbf\x28\x5c\x5a\x1a\x2e\x2b\x2b\x6b\xfd\x90\xd9\xd6\x36\x0a\x30\xa8\x99\x29\x87\xf5\x5c\x0b\xb0\x00\x8f\x96\x67\xb7\xf3\x84\x33\x82\x4c\x9c\x22\xf9\x58\x45\x92\x67\x27\x98\xe5\xa2\xaa\x88\xe9\x3c\x3b\xb1\x83\xba\xea\xc9\xd5\xa5\x2b\x6a\x4e\xac\x7f\x38\xf9\xc2\x63\x8f\x28\x6b\x93\xd7\x5c\x39\x7a\x6c\x92\x5d\xf6\xcc\xce\x57\x36\x6f\xde\xb3\xef\xc9\x7f\x2c\x9c\x39\x63\x21\x89\x33\xbd\xcb\x94\xc3\x08\xf7\x19\x90\xc0\xe5\x00\x7b\x54\x3c\xaf\x26\x78\x82\x9a\xc5\x33\xa6\xb0\x6c\x8a\xea\xb0\x1c\xac\x98\x26\x5d\x77\x92\xc6\x3b\xab\x43\x95\xad\x11\x4a\xb6\xee\x24\xc8\xb7\xb6\x38\x50\x78\xa7\x28\x29\x16\x42\x07\x8b\x9d\x0f\x77\x07\x18\xa6\x12\xf4\xee\xea\x45\xe3\xc6\xac\x5c\x60\x2d\xb9\xa1\x6e\xf1\x22\x36\x04\x77\xa3\x61\x2b\x6f\x9c\x0d\xc7\xb7\x8d\x9a\x10\xed\x3b\x87\xc6\xbe\x7e\x64\xca\xa1\x99\x6b\x01\x6e\xd0\x17\x50\x4e\x65\x9e\x57\x65\x23\xf6\xa4\x58\x81\x1c\x6d\x9b\xa0\xca\x42\x0a\x5c\xcc\x2c\xaa\x69\x26\x56\x41\x4c\x00\xb3\x23\x9e\x5a\x16\xd2\xd2\x98\x11\xab\x44\x3f\x6e\xdf\x78\xe3\xe8\xf2\xeb\x2b\x5f\x1a\x3d\x6a\xcc\xb4\x61\xb3\x1e\xdd\xc6\x2e\xd9\xb6\x2b\xdc\x10\x6a\x99\x39\x27\x32\x3f\xfc\x32\x60\xd0\x01\xa6\x1c\xf6\xe5\xbf\x03\x22\xc8\x05\xd7\x93\x2a\x5b\x7c\x20\xb3\xb5\xc6\x80\xec\x34\x22\x54\x1e\xe5\x60\x10\x09\xd5\xaf\x01\x86\x65\x5f\x94\x66\x06\x9c\x8a\xc5\x41\x00\x34\x0d\x12\x61\xcc\x70\x13\xd0\x39\x8b\x28\x5b\xe3\x1a\xe3\xaf\xd9\x1a\x8f\xcb\xd9\xa2\x0c\x3a\xe9\xcd\x92\x8c\xc5\x22\x5b\xa9\xa1\x03\xa3\x03\x8f\x2f\x9d\x7d\x19\xb7\xf2\x36\x5b\xd1\xe4\x0b\x96\x6d\x58\xb3\xf9\xba\xcb\xae\xb8\x66\xc4\x70\x76\xe9\x73\x3b\x26\x15\xd4\x41\x47\xeb\x85\x93\x62\xfd\x76\x6c\xf9\xe6\x86\xe9\xd2\x5d\x0d\x14\xf3\x04\x1d\x65\xaa\x60\x84\xff\x0e\xb8\xc1\x6f\xc8\xde\x1a\xf9\xce\x28\x6d\x46\xb2\xd3\x46\xa2\x18\x35\x29\xee\xec\x00\xd4\xe6\x54\x15\x9b\x9b\xd6\x58\x28\x46\xa7\x9e\xd6\xe9\x0a\xa6\x0d\x1d\x5d\x29\x84\x66\xc4\xef\xbe\x67\xc5\xe2\x71\x63\x98\x2a\xf6\x15\xf4\x6e\xb7\xbc\xea\xda\x39\xf7\xa0\x8b\x61\x62\xd5\xf5\xb7\xa1\x27\xc8\x98\xcc\x4c\x15\x3c\xcd\xb5\x80\x7c\x30\x0a\xc8\xd9\x11\xd9\x15\x53\x04\x5e\x25\xe5\xa5\x94\x9b\x23\x5f\x54\x49\x66\x2c\x9f\xd2\xa7\xfb\x44\x12\x18\x24\x4d\x9e\x4e\x55\xc9\xd7\xd8\xee\x49\x5f\x8c\x91\xe4\x9d\x2c\x71\xa0\x08\xd9\x5a\x07\x16\x19\x1c\xc5\x1a\xeb\x34\xbe\xd4\x38\xcd\x0b\xac\xe5\xbf\x8b\xaf\xed\x1b\xba\x75\xe0\x6d\xb7\x3d\x74\xeb\x55\x43\x57\xcd\x1b\x79\x19\x53\xc5\x6c\x9b\xd8\x3f\x3a\xaf\xae\xef\xdc\x7b\xe9\x80\x27\xa2\xa5\x30\xb1\xea\x86\xb9\x74\xdc\xed\xe5\x4c\x15\x38\xc1\xb5\x00\x07\xa8\xa0\xf8\x67\xe9\x92\x0e\x3c\x2e\xc6\xa1\x9e\x07\xfb\x8c\xed\x84\x7d\x76\x7c\xa1\xb1\xf4\xaa\xc1\xe5\x71\xe7\x80\xc0\xa5\xd3\xf0\xc7\xae\x18\x39\xc4\xb2\xd0\x71\xcb\x35\x68\xcd\xff\xab\xf7\x71\x2b\x53\x05\x47\x73\x9f\x01\x33\x00\x50\x07\xe1\x82\x21\xb4\x75\xc3\xea\x3c\x93\x98\xb5\x7a\x03\xfa\x61\x3d\xf7\x19\x9a\x75\xe5\x80\xb1\x75\x70\x79\xdb\x28\xf2\x37\xdb\x99\x2a\x38\x92\xfb\x0c\x58\x80\x04\x34\x43\x59\x6f\x32\xef\xd9\x0b\xba\xd8\x98\xaf\x26\xc6\xc2\x50\xa9\x01\x6d\x47\xdf\x6d\xde\xbc\x69\xd3\x77\x10\x6c\x69\xc4\x7f\x35\x16\x0e\xfb\xea\x2b\x94\x40\x9b\x4f\x9f\x06\x10\x94\x73\x33\xe0\x06\xbe\x19\x18\x41\xbe\x86\x37\xa5\x87\xe7\x4d\xa9\x0e\x30\xb3\xd6\x66\xaa\x25\x43\xca\x47\x0d\x3a\xd1\x67\x69\x2d\x37\xc3\xbf\x78\x9b\x7b\xd2\xe6\x6e\xc4\x4f\x28\x47\x7d\xe1\x86\xf6\xc5\xc0\x08\x72\x89\x2f\xc4\xa4\x9f\x62\x3c\xa6\x18\xd2\x4f\xd1\x1e\x12\x2a\x9f\xb7\x68\x4e\xf7\xd1\xde\x13\x68\xc4\xe1\xc9\xfe\x0b\x13\x7d\x00\x04\x8f\xa3\xbe\xf0\x15\x92\x27\xe9\xf1\xf3\x79\x12\x8a\xd5\x93\xca\x95\xf8\x3a\xe4\x4a\x1e\xef\x2a\x57\x02\x06\xb5\xb7\xb0\x93\x09\x1f\x69\x5f\x8d\xaf\xc7\x9e\xe2\x42\x31\xd3\x1c\xa4\x48\x98\x0c\x29\x23\xa9\x9d\xd6\xbb\xc9\x6e\x31\x21\x58\x7d\x1a\x83\x10\x01\x65\xc2\x67\x8d\xf2\xde\xa7\xc0\xdd\xb1\x16\x1f\xd4\x6b\xe3\xb8\xbf\x43\x01\xfd\xeb\x9f\x9b\x6e\x7e\x60\xd9\xd3\xeb\x37\x6e\xaa\xb9\x37\xca\x85\x02\x85\xe8\x23\xf4\x1d\x52\xd1\x9f\xfa\x6c\xbc\xe0\xe8\x91\x3f\xbc\x9f\x1b\xd0\xb8\x28\xda\x5b\x34\x3e\xa3\x42\x30\x8d\xb2\x1a\x10\xa2\x41\x9d\xda\x28\x99\x55\x40\x98\xed\xb3\xb8\x14\x17\x8d\xd5\x43\x54\x95\x0f\x86\x95\x5c\x3b\x65\x9b\xc9\xf5\x51\xf1\x47\x09\x83\x74\xda\xa3\x02\x51\x16\xe3\x72\x96\xa4\x00\x2c\x04\x4d\xa4\x65\x34\x4d\x80\xa4\x81\x28\xd3\xe8\x02\x5d\x34\x90\xa9\xe0\x1a\xa0\xe5\xdf\x3a\x17\xd2\xe3\x8f\xae\x7c\xe0\xe6\x67\xff\x8e\x7e\x84\x2b\x75\x6f\x8b\xd2\xaf\x04\xb3\xd6\x56\xbe\x7b\xe4\xe0\xd1\x0b\x36\xf6\x81\x21\xd8\x53\x77\xc0\x98\x8c\x75\x0e\xe1\x79\x9d\xb3\xd2\xc9\xec\xa0\x09\xcf\x4b\x27\x40\xf1\x1f\x53\xf2\xec\xaa\x9c\xa7\xa9\x60\x4f\x26\x11\x92\xc9\x6d\x27\xf3\xd2\x37\x23\x88\xe5\xbb\x9c\x2d\x29\xa2\x40\x09\x66\x7c\xbf\xb8\x2d\x99\x99\x89\x2e\xb7\x68\xa9\x3e\xaf\x2e\xf7\x0a\x25\x32\x7a\x53\x40\x7f\xf4\x23\x5c\xce\x4d\x06\x06\x20\x81\xbe\x58\x7a\x24\x2d\x5a\x57\x9f\x0b\x9f\xf2\xa4\x8d\x34\xf2\x35\xf1\x36\xa3\x31\xac\xb0\x76\x92\x2e\xe3\xed\x14\xee\x8b\x67\x45\x29\x61\xb0\x38\x35\x76\x48\xda\xb1\x6b\x81\x34\x54\x87\x47\xd7\x3f\x7b\x80\x6d\xaf\xa3\xf2\xf6\xda\xfe\xfd\xee\x1a\xd4\xb7\xcf\x40\xf4\xe3\x54\x18\x1d\xeb\x3b\x88\xfe\xc6\x7d\x39\xf0\x92\x65\x03\x2f\x21\x3d\x7e\xf0\x47\xee\x04\xeb\x16\x1a\x80\x09\x14\xeb\xf9\x62\x73\x46\x56\xd5\xab\x92\x94\x4e\x3a\xb3\x9a\x6e\xca\x80\x3f\xe6\x56\x99\xf7\x3a\xae\xaf\xe5\x4e\xe4\x5e\xfa\xd5\x25\xbe\xfe\x5f\x8f\x06\x2c\x74\xf2\x56\x76\xb9\x90\xd4\xf2\xaa\xbf\xfb\x8f\xf3\xaa\x05\x30\xfc\xbf\xcf\xad\x42\xe7\x79\x72\xab\xb3\xce\x93\x5b\x65\xf1\x65\xe2\xb3\x05\x23\x30\x00\x11\xf8\xc0\xc0\x0c\x7e\x4c\x52\xab\x2f\x11\xa2\x1f\x81\xa5\x37\xdc\x7a\x4c\xb1\x79\x69\x93\x2e\xc1\xff\x35\x90\x2c\x1e\xc4\x36\x84\xd1\x24\x7a\x48\x5c\x97\x12\x68\x06\x2d\x19\x0b\x17\x64\x4b\x05\x03\xd3\x67\x0b\xd3\xfb\x55\xb9\x6d\xf7\xf6\x2d\xda\x3a\xc2\x12\x78\x64\xf3\xe0\xbc\x20\xbf\xfb\xcc\x20\x78\x00\xf5\xe1\x66\xea\xeb\xda\xf6\x23\xdc\xf5\xd1\xdc\x09\x58\x2e\xae\x66\x86\xc0\x95\xec\x38\x60\xc1\x7a\x2d\xd5\x11\xaa\x7d\xd3\x05\x37\xed\x00\xd5\xbe\x75\x81\x3b\xb3\x3a\x45\xde\x75\x34\x4d\xce\xc5\xb4\xbf\x03\x00\x37\x5b\x30\x02\x13\xf0\x80\xc9\x94\x8d\x4e\x71\xb1\x5a\x6a\xc2\xce\xaa\x49\x87\x64\xb6\xd8\xc2\x8a\x83\xa5\xe6\x2e\x97\xda\x46\x33\x0c\x2b\x2e\x0f\xa5\x46\x21\x02\xd6\xe5\x21\x06\x0b\xe5\x48\x21\x22\x46\x3f\x42\x8a\xdd\x21\x4a\x09\x68\x02\x54\xdb\xa6\x57\x85\xf4\xdd\xd3\xff\x7a\xea\x2b\x62\x64\x7b\xb5\x2d\x61\x46\xb6\x35\x32\xf3\xd2\xab\x71\xf6\x21\xbe\x79\x13\xaa\xdd\xd8\x76\x7a\x13\xd0\xc7\xcd\xef\xd0\xc6\x3d\x4e\x63\xd1\x13\x63\x64\xd8\xb2\x23\x96\xb4\xb9\xc9\xa8\x6d\x5d\x8e\xda\x83\x85\x60\x54\xf6\x90\xd2\x58\xd9\x1e\x55\x44\x8f\xda\x71\xbc\x16\xdb\x79\xc6\x9b\xa6\x71\x4a\x8d\x37\x6f\x07\xf3\xed\x8e\x1d\x6d\x52\xc7\xc1\xb6\xad\x65\xa6\x9d\xa9\x27\x4e\x04\x19\xef\xa7\x84\x7f\xa6\xe3\x3a\x5b\xb0\x27\x11\x4d\x38\xc8\x52\xf3\xaa\x2c\x46\x3b\x0d\xd6\x4a\x97\x38\xe1\xb2\xa6\xd6\xd7\x19\x4d\x58\x09\xfb\x8c\xd5\x4c\x88\x8c\x3b\xad\xb3\xa5\xcb\x71\xbb\xaa\x6a\xc4\xd2\xaa\xa0\xc7\x20\xfa\x3c\x85\xda\xb8\x4f\x37\x36\x32\xce\xc6\xc6\xcc\x51\x4f\x2b\xe5\x56\x95\x4f\x9b\x56\x7e\x76\x7a\xe9\x34\x00\xd8\xf6\x2f\xda\x5b\x04\x83\x36\xe6\x20\xb8\x0e\x50\xb2\xe2\x80\x45\x25\x40\xe0\x4a\x3e\x4b\x81\x4e\xcc\xc7\x14\xaf\x4f\x6d\xe2\xbd\x66\x63\x58\xe1\xbc\xb4\x12\xc6\x4b\xaa\x91\x72\x60\x58\x71\xfa\x28\xec\x89\x99\x0e\x92\xfa\xb5\x36\xc2\x41\x9c\x1f\x10\xa5\x24\x34\x99\x9d\x80\x5c\x9b\x8c\x01\x9f\x87\xa8\x2e\x4f\x1b\xfc\xac\xf3\x92\xd4\xa5\xe7\x83\x66\xfc\x3c\x49\x1d\xdd\x97\xb7\x01\xe0\x57\x93\x39\x4a\x60\x18\x48\x88\x00\x84\x13\x66\x7c\x88\x6c\x31\x22\x92\xd3\x9b\x41\x2a\xab\x3c\x9a\x24\xa6\x73\x91\x45\x91\x3a\xef\x4e\x89\x78\x0d\xd8\xdd\x6d\x82\x26\x60\xed\x3c\x1d\x9d\x2d\x35\xaa\x8d\xff\xbd\x37\xe0\x7c\xb8\xe0\x0f\x28\xf0\x72\x7a\xbc\x70\x70\x5b\x2f\xe6\x48\xeb\x5d\x6d\x6f\x30\x11\x3a\xb6\x2f\x00\x10\x6a\xc9\xd8\xca\xc1\x13\xda\x19\xcf\x8a\x29\x16\x56\x95\xfd\xd1\x84\x84\xf7\xa0\x90\xa5\xf8\xd4\x8e\x63\x4a\xb1\x4f\x4d\x14\x3b\x08\x6b\x4d\xb9\x29\x9c\x70\x10\xa2\x0a\x87\xd9\x14\x6e\xe2\x8b\x1d\x1d\x77\xa6\x98\xb2\x00\x79\x7c\x6a\xc2\x43\xd8\x7f\x3c\x59\xa6\x70\x22\x9f\xa0\xd4\xe6\x67\x9b\xc2\x04\xd9\xda\xa1\xed\x57\x7e\xb1\x28\x25\x24\xab\x9f\x04\xcf\x2d\x66\x51\x52\x72\xca\xe2\x71\xb9\x50\x6c\x86\x26\xe0\xf0\xe4\x17\x77\x9e\x6c\x55\xb0\x84\xa9\xa2\x1b\xe8\x66\x0c\x41\x4f\xb0\xaa\x5a\xaa\xaa\x64\x88\xb5\x20\xf9\x3c\xfa\x1e\x0e\x84\x37\x3e\xb2\x11\x4e\x84\xbd\xf1\x3e\x3e\xb9\x06\xde\xd0\x96\x50\x9e\xf9\xbe\xe5\xeb\x7f\x3e\xad\x64\x1e\xca\x4d\xb7\xc0\xd1\x87\x61\x25\x1c\x87\x36\xa3\xb7\xde\x46\x5b\x66\x6d\x5a\xbd\x10\x5e\xfc\xf1\x69\x08\xda\xff\xfd\x39\xda\x73\xe7\x6a\x02\x57\xdf\xfe\xd7\xf6\x16\x66\x23\xd1\x41\x59\x20\x04\x2a\xc0\x02\x0d\x95\x5c\x34\x52\x32\x1a\xac\x93\xba\xa7\x74\x52\x49\x14\xca\x91\x4c\x9d\x84\x15\x9e\xdd\xa6\x36\xe5\xd9\x2d\xc6\xb0\x92\x8f\x75\x92\x93\x58\x47\xe5\x5e\x55\xe9\x89\x7f\x69\x11\x25\x25\x3b\x14\x8f\x2b\xf9\x79\xa2\x24\xfb\xe3\x40\x11\xfd\x04\xe9\x1b\x1b\xf1\xee\x38\xd5\x51\xd9\x39\x21\x7a\xf5\x2a\x3b\x44\x18\x32\xa9\x69\x5d\x5d\xe8\xac\x2c\x4d\x65\xbd\x96\xa8\x1f\xd9\x7d\x7c\x56\xf6\xcc\xea\xcd\xab\xbb\x77\xad\xbe\x5a\x39\xd6\xd8\x7a\x66\xc2\x78\x87\xf1\x7e\xab\x7b\x1b\x77\xbc\xb3\x36\xd3\xf0\xfb\xf9\x6c\x7e\x37\x30\x00\x9b\x8e\xe7\x97\xd6\x66\xc6\xb4\x36\xd3\x01\x2b\xa1\x51\x0b\x63\x6b\x7a\x8b\x75\x75\xd2\x56\x2d\x1d\x95\x14\x33\x55\x53\x4d\x80\x05\x07\x01\xe0\x0e\xf0\xcd\xc0\x01\xfc\x20\x98\xe2\x76\x74\x5a\x54\xf2\x71\x4a\xd0\xa2\x26\x03\x7e\xf2\x91\x01\x73\x8a\x1d\xdf\xe9\x51\xe5\x00\x21\x92\x77\xd3\x0e\x45\x39\xb7\xe0\x98\x48\x2c\x0f\x2c\x29\x72\xb1\x3b\x64\x32\x92\xea\x18\x27\xad\xc2\x0f\x88\x8a\xd1\x14\x8f\xcb\x41\x9d\xcb\x20\x58\xc0\x79\x74\x72\x47\x2e\x54\xac\x93\x3a\x6a\xec\x8e\x61\x78\x10\x3e\x09\x4b\x20\xff\xe0\x7d\xcf\x3e\x81\x7e\x38\x85\x9a\x61\xa9\xbc\x2d\x99\x44\x5f\x41\x7b\xe3\x86\xe7\x5e\xfe\x8e\x6f\x7e\x61\xd7\xdd\xcf\x06\xcc\xb9\xf2\xca\xd7\x3f\xde\x70\xdf\xfd\x8b\x16\xac\x9f\x7e\xd7\xdc\x69\x14\x07\x08\xcf\x09\x90\xfc\xbf\x8e\x86\x48\xe6\xc2\xb1\x6a\x0a\xff\xc0\x93\x59\x35\x94\x42\xa7\xc1\x9a\xec\x20\x1b\x6f\x5b\xc8\x37\x6f\x3e\xf3\x2d\xd9\x8b\x72\x00\xb8\x05\xe4\x59\x56\xd0\x4d\xe7\x72\x60\x55\xd2\x2e\x97\x86\xf6\x14\x80\xd6\x9a\x2a\x33\x22\x29\x47\x8f\x55\xc1\x18\xf4\x14\x07\x61\x49\xa9\x60\x28\x87\x87\x77\xc0\x23\xad\x0d\xcc\xeb\xed\xe0\xc2\xfc\x58\xb8\x81\xbf\xe8\xcc\xcb\x33\x36\x31\x67\xde\x58\xfa\xc7\xbb\xe9\x78\xd9\x1f\xf9\x66\x60\x01\x17\x6b\x9f\x60\x62\xd5\xd4\x98\x93\x3c\xdd\x72\x9e\x4d\x65\x43\x4c\x1e\xca\xcd\x02\xf4\xfe\x20\x99\x89\x52\x92\x96\x14\x5f\x61\x5a\x31\x1f\x4c\xeb\xe3\x0e\x3a\x18\x82\x61\x00\x70\x83\x48\x7d\x5e\x85\xce\xf1\xcc\xaa\xa4\x50\x8f\x06\xe1\xcc\x11\x7c\xaf\x00\x09\x08\x76\x4d\xda\xec\x19\xc6\x32\x6d\x5e\xf6\x8d\x56\xc4\xfa\x96\x71\x4b\x36\x2f\x3b\x3b\x6f\x73\x6a\x0f\xf8\x62\x32\xa7\x4c\xee\x45\xa6\x23\xf7\x62\x7a\x46\x16\x4f\x67\xee\x45\x4f\x57\xdc\x8b\x07\x35\x5d\xdd\x59\x3f\xb3\x60\x7e\x06\x1f\x6b\x36\xb8\xa2\x2b\x3e\xd6\x80\x9f\x78\x1d\x01\x4b\x8a\x27\x4e\x23\x63\xd5\xe9\x57\x73\x35\xe0\x96\x26\xd6\xe4\xcf\x22\x5e\x47\xc0\x4f\xf8\xe7\x25\xf0\xb3\xf4\xab\xae\xaa\xa0\x67\x3e\xd1\x68\x7d\xe1\x24\xf4\x28\xda\x87\x76\xa1\x27\x5f\x3b\xdd\xf2\x8f\xef\x7e\xf8\xe6\xef\xff\x6e\x64\x6e\xd0\xf8\x56\x67\xa1\xc7\x88\x2a\xbb\x1f\x4e\x41\x1f\xa3\xf7\x60\x0f\x58\x0c\x8b\x61\x29\xfa\x13\x7a\xe4\x89\x27\x00\x04\x23\x00\x60\xc6\x77\x38\x07\x90\x57\x65\x73\x34\xc1\x93\xa3\xa0\x65\x93\xac\xa4\x37\xd3\xe4\x51\x13\x26\x26\xb5\xff\x42\x54\xef\xda\x02\x69\x0e\x11\xbc\x51\x69\xc3\x61\x04\x35\x18\x3a\x18\x09\xf4\xae\xfc\x40\xb8\x42\xb4\xea\x17\xd9\x98\xda\x27\x2d\x0b\x4e\x9c\x4e\x26\x9a\x26\x99\x27\x99\x61\xba\x31\x35\x04\x67\x0c\x1a\xc4\x83\x3b\xee\x60\x4c\xc7\xdb\x5e\x61\xae\x3a\xd1\xf6\xd3\x1a\xbe\xb9\x2d\xb2\x8c\x19\xdc\xb6\xa8\xf5\x20\xb3\x73\x51\xdb\x1b\x69\x0e\xfb\x8f\xf8\x66\x60\xee\xc0\x61\x4f\x2e\x92\x25\x82\x8d\xa5\xce\x1c\xf6\xe4\xf6\x40\xc6\xba\x8f\xb1\xbf\x86\x76\x5f\x52\xe8\x1e\x81\x5e\xe5\x9b\xcf\xd4\xb3\xeb\x8f\x2c\x9e\xf0\x8f\xd6\x89\x74\xfc\xc2\x7c\xbe\x19\xb8\xc0\x18\xfd\x0c\xdb\x62\x19\x33\xa0\x30\x66\x2e\x49\x95\x5d\x34\x90\x63\xd0\x60\xcc\x5c\x78\x22\x0e\x67\x9c\xe0\xb4\x31\xbc\x0d\xbb\x99\xb2\x41\x52\x2c\x56\xe2\x0f\x00\x51\x4a\xb0\x16\x1a\xe3\x8c\x89\x41\x18\x83\x41\x4a\x5c\x01\x43\x30\xe4\xf5\x88\x07\xa1\x13\xee\x37\xc2\x43\xd0\xde\x6c\x37\x22\xff\x23\x28\xcf\xe8\xe0\x9b\xcf\x8e\xe0\xb6\x9f\xa9\x67\x17\xad\xfd\xea\x2c\xe0\x99\x8d\xdf\xb4\x2e\xd5\xef\xc2\x30\x32\xc6\x11\xda\xbc\xad\xda\x08\xcd\x9d\x47\x68\xc2\xf2\x54\xca\x18\x21\x21\xcc\x36\x89\x24\xed\x22\x5b\x25\x85\x17\xf4\xe1\x29\xbc\x5d\xdb\x05\x9f\x09\xc6\x4a\x18\x12\x71\x82\x21\x1f\x1e\xdc\x07\x3d\xe0\xe7\xa0\xdd\xc8\x58\x1b\x8f\xb7\xfe\xd3\xc8\x5b\xf9\xe6\x8b\xdb\xb2\xd0\x2c\x3f\x2c\x1d\xc8\xc6\xcf\xd4\x73\x7b\x2e\x6f\xbe\xb7\xf5\x08\xbe\x37\x43\x00\xe0\x4a\xf9\x66\x52\xa7\x69\x01\xe5\xfa\xb9\x63\x55\xed\xd0\xb1\x6a\xd2\x64\x04\xbc\x8d\xc8\x24\x7c\xf8\x52\x27\x8b\x96\xa9\xe0\xff\x86\xb0\x9f\xb5\xd6\xb3\xcb\x5b\x0f\x30\xea\xa6\x4d\xbc\x7b\xd3\xa6\xb6\x75\x1b\x37\x02\xa6\x03\x47\xf2\xa0\x2e\x6e\x64\xaa\xcf\xad\xe3\x35\x4c\xe1\x27\x51\x90\x39\xd2\xeb\x06\x84\xf8\xcf\x5c\xc0\xf3\x73\x1e\xff\x12\xd3\x71\x4a\x56\x39\x09\xa6\x79\xa4\xe3\xb9\xa4\x6a\x56\xab\x9c\xf5\xa4\x2b\x67\x6d\x6a\x0a\x7a\x8c\x12\xae\x1c\xe4\x2e\x69\x6e\x2b\xc6\x47\x93\x77\x9f\x69\xc1\x7a\x03\xdf\xab\x19\x44\xb6\x4a\xba\x47\x4a\x1f\x29\x59\xd4\xa4\x91\xca\x3f\xa3\x25\x05\xc8\x8d\x25\xba\x39\xaa\xb3\x86\x73\x5e\x0d\x9e\x5b\x32\x8b\x99\x64\xc8\x5c\x30\x14\x80\xb1\x94\x86\x5c\xc4\x14\xa3\xb7\xd1\xd7\x5b\x57\x7f\xf8\x7a\xf3\xbe\x9d\x7c\x33\x1a\xf1\xf9\x3f\xda\x0e\x32\xc7\x97\x6f\x58\xfe\x00\x9e\x57\x3d\x00\xdc\x38\xbe\x19\xd8\x40\x25\x48\xd8\x88\xc7\xa2\xcb\x77\x43\xa6\xfd\x80\xbd\x25\xda\x67\x44\x58\x5a\x65\x8e\x26\xcf\x62\x55\x26\xbc\xbb\xc1\x52\x13\x2c\x0e\x7a\xea\xe1\x67\xa8\x07\x7b\xb8\x6d\xf2\xb5\xf0\x30\xca\x83\xc3\x60\xeb\x3a\x66\x22\x13\xfc\xfd\x66\xa6\xed\xeb\xb6\x4d\xcc\x26\x82\xf5\x0f\xb8\xb1\x64\x1d\x7b\x53\x1c\x3b\x3a\x63\xc0\xaa\x04\x5b\x8c\x20\xd8\x51\xd5\x2b\xe8\xaa\xb7\x4b\x24\x3b\x0f\x5e\x54\x37\x37\x04\xf5\x7e\x19\x9f\xa6\x33\x2d\xbc\x3b\x25\x3f\x96\x90\x38\x65\x4f\x90\x30\x10\xfe\x59\x86\x6c\x16\x09\x31\x1a\x68\xe8\xce\xac\x33\xcf\x32\x71\xa0\x00\xfa\xa2\x67\x2f\x51\xb7\xe0\x53\x86\x3b\xdf\x9c\x61\xae\xb3\x60\x6a\x7b\x8b\xc0\xf1\x87\x40\x00\x14\x82\x30\xb8\x9e\x46\xe3\x12\x02\x36\xb9\xbc\xb9\x6e\xc1\x16\x96\x43\x31\xc5\x6b\xc2\x4e\x5e\x92\x2b\x20\x6f\x74\x8b\x29\x9c\x45\x95\x8d\xa9\x0c\x7f\x96\x47\x95\xb3\xa8\x4d\xc4\xe7\x69\x54\x72\x86\x50\x34\x8a\x2f\x76\x29\x0c\x2b\x36\x8f\xaa\xf4\xc0\x0b\x5e\x90\x8b\x5d\x28\x0d\x12\xac\x1f\xec\x03\xab\x62\x9e\x58\x14\x9b\x42\x0c\x17\x86\x9e\x50\x55\xa8\xb0\x88\xa9\x71\x7b\xfb\x40\x31\x54\x28\xa4\x76\x7c\xea\x7d\xa8\x71\x40\xf3\xa0\xed\x6d\xf7\x3c\x8c\xce\x24\x4a\x9b\xc3\x09\xd4\xba\x6a\xd7\x87\x7f\xf4\xd6\xbc\xf8\x16\x33\x3d\x70\xe0\xa3\x43\xcd\xb5\xcc\xe9\x47\x7f\x5a\x9e\x4c\x2e\xfb\xf1\xf1\xa7\x11\xba\xfb\xe4\xc9\xc5\x90\xd9\xfc\xca\x71\xd6\xf7\x6e\xdb\xce\xe3\xaf\x24\x8f\x90\x75\x34\x02\xc0\x6d\x25\x7a\xa6\x24\x2d\xf3\x19\x5d\x62\x6a\x57\x9c\x20\x08\x68\x1d\x1e\x78\xf1\xc8\xff\x42\x26\x68\x84\x7f\x45\xf1\xc3\x70\x32\xbc\xfe\x35\x54\x07\xbf\x7a\x17\x2d\x40\x73\x98\x33\xcc\xee\xb6\xfd\x4c\xdf\xb6\x21\x6d\x0c\x33\xbf\x6d\x31\x80\xe0\x26\x00\x04\x86\x6f\x26\xb5\xd5\x84\xde\x94\x9e\x05\x2c\x9c\x93\x7e\xde\x0b\x6d\x61\xd9\x14\x53\xfc\x16\x55\x76\xa5\x8a\xac\x59\x0f\x09\xb7\x7b\x21\x29\xfa\xf1\x10\x16\x5a\xec\xe5\x63\x37\xda\xe1\x25\xfa\x59\x03\xf3\x74\x06\x09\xbe\x46\x41\x00\xc6\x44\xb7\xc0\x85\xf1\xce\x86\x0a\x8b\x4a\x6e\xda\x01\x37\x64\x25\x73\xe1\xfa\xdd\x0f\xa2\xb6\xa6\x48\xb2\xc7\x4e\xd4\x7e\x2f\x7b\x14\x7e\x89\x82\x68\x11\x3b\xb6\x75\x33\x9c\x07\xbf\x44\xf9\x5b\xfe\x7d\x3b\x1a\x04\x77\x2f\x3a\x95\xb2\x83\xf8\xd3\xfc\x61\x90\x0f\x16\x69\xeb\xe1\x8c\x61\x11\x28\xdb\xa3\x09\x23\x1e\xb5\x9f\xa5\xb4\xe6\xfc\x31\x25\xdb\xa7\x26\xb2\xc9\x99\xcd\xce\x37\x85\x13\x3c\xc9\x54\xf1\x80\x92\x62\x7b\x08\xac\xad\x9a\xb0\x10\x4f\xcc\xe2\x34\x85\x13\x1e\x52\x15\xe3\x11\x4d\x61\x42\x7b\xee\xc9\x16\xa5\x84\x91\xb1\xc7\x53\x52\x5c\xca\x8b\xc7\x65\xbf\xd8\xc4\x5b\x08\x6b\x12\x91\xac\x3f\xeb\x7f\x0d\x3b\xbf\xdf\xf5\xab\x7c\x2d\x16\xd4\x01\xc0\xdc\x6e\x28\xd7\xb8\xeb\x6f\xd2\x18\xc2\x6c\xbc\x2a\x7b\xa3\xb4\x82\xcc\xc9\xe3\x7d\xc1\xb7\x2a\x98\xea\x8a\xce\x8e\xea\x09\x71\xad\x1d\xda\x6e\x21\xa1\x98\x84\x87\xf0\x04\x7b\x7c\xa6\xb0\x2c\x45\x13\x76\x32\x77\xbb\x95\xc4\x3a\xf0\xee\xf9\x61\x58\xc9\xf3\x92\x98\x6e\xa7\x90\x56\x66\x58\x23\x33\xa9\x5b\xa7\x37\x51\x7b\xa9\xc9\xf2\xb4\xde\x4a\x2d\x1c\xd0\x7a\xa8\x7f\x9a\x99\x69\xc6\xa4\xde\xa6\xb1\x40\x6e\x89\xa1\x1c\x18\x09\x72\xed\xa8\x8e\x72\x42\x96\x22\x72\x5e\x2c\x69\xa5\x13\xf2\x47\x09\x9e\xad\xe9\x98\xe2\xf0\xa9\xb2\xc3\xa9\x18\x2c\x24\xfa\x8c\xe7\xe6\x21\xd4\xe6\x14\xda\x56\x70\x9c\x57\x9a\xb0\xe7\xe9\x03\x4f\x49\x99\xfd\x5d\x60\x0e\x65\x08\x1e\x6e\xed\xb9\xcd\xe1\x84\x27\x98\x3b\x2c\x34\x80\x02\xd0\x1d\x54\x83\x3b\x34\x96\x56\x5f\x4c\x29\x22\xf2\x87\x70\xd5\xd3\x60\x7a\xd8\xa4\x42\xb9\x86\x6c\x4a\xd0\xa3\xca\x41\x27\x21\xfe\x8c\x7a\x55\x39\x4a\x45\x8e\xdd\xa6\x2a\xb5\x30\xac\xf4\x0a\x8a\x52\x92\xcd\x2b\x0a\xf7\xc0\x66\x4e\x54\x94\xab\xe3\x72\xa9\x24\x67\xc7\x65\xbb\x98\x10\x4c\x59\xe4\x3c\x16\xe5\xd1\xc6\xe0\xb0\x98\x04\x06\x21\x2b\x5b\x33\x7a\xa5\x58\xd4\xeb\x8b\x55\xd7\xc4\x04\xc6\xa3\x51\x5e\x11\x4f\xb8\x94\x30\x5e\x65\x12\xac\x16\xa4\xa1\x93\x1b\x7e\xf8\x6c\xde\xc6\x6a\x9b\xbf\xfc\x41\x7f\x4e\xaf\x50\x41\x9e\x73\x40\xe1\x95\x57\x89\x8e\xba\xa7\x67\xbf\xff\xed\xce\xe5\xeb\x9f\x5e\xb5\x66\x33\xfa\xa8\x45\x0b\x25\x30\x41\x28\xc1\xf0\xc8\x91\x63\x6b\x2f\x42\x6d\x93\xd1\xa8\xfe\x95\xe6\x45\x26\x71\xd4\xe5\x57\x0e\x87\xdd\xa0\xe9\xed\x77\xf6\xfc\xc9\x7a\x72\x3f\x94\x52\x21\x6b\xc0\x80\xd1\xed\x2d\xec\x3a\xa1\x01\x14\x83\x08\xb8\x5f\x63\xb6\xcf\x35\xaa\x09\x33\x5e\x16\xd1\xa4\x26\x3d\xfe\x90\xd9\x16\x56\x3c\x46\xb5\xc9\x1e\x32\x1b\x53\x5d\x10\x59\x36\x2c\xa4\x65\x17\x76\x58\x0d\x12\xa9\xf5\xc0\xb6\x57\x96\x93\xb0\x27\x87\xbd\x94\x3b\xb5\x9b\x4b\x94\x5e\xe4\xcc\x22\x1b\x22\x8c\xb3\x61\xb1\xc9\x97\xeb\x8d\x10\x9f\xc0\x8f\x85\x37\x28\x88\xc7\x15\x7b\x48\x94\x14\x83\x2b\x1e\xa7\x75\x12\x36\x9d\xd1\xbf\x02\x6a\xc4\x19\x1a\x20\x2e\x21\xf2\xf7\xa4\x19\x8a\x4a\xd2\x71\xe5\xd1\x0d\x8b\x26\x4c\xfb\xea\xd5\x19\xcf\x5f\x39\x68\xc2\x3d\xf5\x3f\xc2\xf8\xac\x35\xe8\xcd\x87\x57\x5c\xf1\xdc\xc4\x65\x5f\x7e\xfc\x4f\x78\xb3\x1e\xa4\x0c\x4f\x58\x54\x62\xc9\xb9\xf3\x9a\x25\x1b\x8a\xcb\x57\x74\xcf\xd9\xb0\x75\xf5\x2b\x63\xae\x29\x8d\x3c\x7e\xe9\x73\xdc\xc0\xf4\xb2\x00\x06\x6c\x47\x6e\x6e\xa8\xd0\x00\xdc\x20\x0f\x5c\xa7\xdb\x1d\xf8\xbc\x18\x08\x5f\x97\x49\x95\xad\x11\x3d\x9e\xef\xb6\xa9\x0a\xe3\x24\x15\x45\xd8\xe6\xca\xf2\x92\x65\xc0\xd2\xd6\x62\xa3\xd1\x7c\xb7\x96\x0a\xce\xc2\xe6\xb0\xc1\xe9\xa1\x34\x5d\xc4\x05\xe0\x74\xe3\x33\x96\x4e\x02\xd3\xec\x6b\xfa\x10\x6c\x5f\x99\x6d\x8e\xed\x98\xf1\xe6\xeb\x89\x5b\xef\x7c\xf6\xf7\x1f\xe8\xb9\x87\xfa\xb5\x97\x8f\x79\xfd\xc8\xd9\x4b\xb8\x6d\xf7\x2c\x7e\xf5\x48\xdb\xc1\x8c\x64\x04\x99\xc3\x56\x12\x0b\x6a\x20\xb5\xfb\xbf\xd1\x2c\x17\xc1\xa8\x33\xbe\x67\xe9\x00\xcf\x4d\x6e\x16\x18\xc3\x8a\xc7\xab\x12\x78\x66\x42\x74\xe6\x24\x44\x4b\x81\xb8\xec\x91\x48\x66\x56\xa0\xfd\xe1\x32\x14\x29\x05\xe6\x39\xc1\x1c\x7d\xa8\x5b\x33\x42\x37\x39\xfa\xaa\x0f\xec\x10\xab\xb9\x30\x3d\x4a\x0e\x6c\x6a\x6f\xe1\xe6\x09\x49\xe0\x06\xf9\xa0\x0c\xc4\xc0\x2a\x8d\xcd\x9b\xd7\xc6\x29\x5b\x62\x72\x6e\x44\xee\x15\x4b\xfa\xa8\xb4\x09\x47\xa1\x5c\x99\x1a\xba\x87\x0c\x1d\xaf\x38\x4b\xe9\x3d\x8b\x7c\xaa\x5c\x44\x3d\x14\x87\x4d\x6d\xaa\x70\x18\x8d\x24\x78\x25\x97\x47\x94\x0a\xaf\x2a\x1b\x9d\xb2\x05\x1f\x59\xab\x4d\x25\x2c\xab\xa1\x2c\x51\x6a\xe2\xa5\x82\x32\x5a\xaf\xce\x93\x32\x41\xc5\x97\x2b\x4a\x89\x82\x60\x99\xce\x08\x26\x3a\x35\xaa\xde\x58\x1e\xf4\x38\x81\x56\x20\xfe\x33\xd9\x97\x4d\x49\xd8\xe3\xa9\xc7\xb2\x8b\x93\xa5\xd9\xe8\x6c\xfb\xd7\xea\xb3\x5d\x27\x63\xe0\x77\xcc\xe8\xb6\xed\x68\xc9\xd7\xff\xba\xf3\xdd\x47\xd7\x7c\x79\x3b\x7a\x0d\xbd\x7f\x96\x7b\xe0\x3c\x19\x1a\x2d\xd7\xc9\x1d\x26\x7c\x83\xdd\xc1\xa4\x5f\x92\x68\x3d\x32\x25\x9a\x2e\xc6\x2a\x60\x58\x29\x0d\x8a\x52\x22\x3b\x8f\xa5\xa4\x7c\xff\x45\xc1\xf5\xab\xc4\xd5\xaf\x12\x53\xda\x1d\x94\x85\x7c\xe0\x06\x65\x60\x21\x48\x38\xf1\xb9\xf0\x1b\x55\x19\x44\xe4\xbc\x88\x92\x6f\x56\xe5\x92\x88\xc2\xe1\x89\x96\xa7\x88\xfb\x3c\x51\xbd\x38\xd4\x66\x53\x65\x9b\x53\x36\xe0\xdd\x0e\x79\x54\x39\x14\xc1\xbe\x47\x22\x44\xea\x2b\x43\x79\x1a\xcd\x7b\xc8\x2d\x4a\x49\xce\xec\x34\xf9\xa9\x50\x72\x12\x8a\x53\x25\x1f\x68\x4d\xb2\x72\x89\xce\x37\x46\xd5\x92\x93\xd7\x42\x6d\x85\x25\xa5\x01\x98\x07\x63\x05\x22\x61\x24\xd7\xd2\xa4\x05\xe2\x76\xd4\xf2\xc9\x19\xf4\xc7\x5d\x7b\xd0\xd9\x7f\xcc\x78\xb2\xfe\xe2\x47\xa7\xc2\xe1\x3b\x1a\x6f\x1a\xbd\xe6\xf1\x75\xcb\xd0\x11\xe4\x16\x2a\x3f\xff\xf7\x3b\x2f\xa1\x0f\x63\x46\xcf\xc1\x5d\xef\xfc\x39\x58\xd4\xf6\x25\xf3\x6a\x71\x04\xf6\x58\xf7\xc4\xba\x07\xef\x9d\x77\x17\x6a\x26\xb6\x94\x19\xb9\xb9\x6c\xae\x1e\xb8\x48\x3c\x01\x12\x1f\x57\x76\x46\x88\x9b\xeb\x3c\x96\x42\xdd\x27\x20\xe2\x3c\x49\x22\x00\xbd\xe4\xc5\x15\x73\xe5\x41\x2c\x4e\x6a\x5c\x31\x28\x30\x9e\x50\xa5\x54\x63\xde\xf5\x55\xf1\x00\x93\x51\x18\x90\x7b\x62\x17\x9a\xd6\xa3\x66\x7f\x5d\x0f\xae\xbe\x6d\xef\x35\x07\x7b\x96\x1d\xff\x0d\x33\xe4\xec\xbb\xb3\xd1\x9f\xa6\x5d\x0d\x0b\xe7\xe3\x33\x36\xa3\xbd\x85\x9b\x2c\x60\xc9\xd7\x0d\x4c\x06\x89\x1c\xbc\xee\x85\x26\xd2\xc4\x62\x32\xaa\x50\x0e\xd3\xe2\x17\xaf\xda\x24\xe4\xe3\xeb\xe7\xb2\x91\x12\x98\x62\x18\x56\x02\x1e\x95\x10\xee\x16\xbb\x44\xa9\xd9\xe4\x64\xbd\x39\x85\xf8\x66\xc9\x01\x31\x61\xf3\x59\xa9\xd8\x2b\x14\xa5\x24\x10\x6c\x01\xf2\x0b\x93\x48\xc0\x4b\x5c\x95\x52\x4d\x47\x71\x9f\x42\x76\x07\xa1\xc2\xa2\x9a\x0c\xa0\xfb\x19\x9f\xbf\xb5\x6c\xd6\xc1\x67\xa7\xee\xb9\x73\xd8\xa4\xcd\x57\x8e\xb8\xf6\xa6\xa7\x3f\x68\x44\xdf\x7d\xf7\x17\xf4\xed\xee\x6d\x2b\x1f\xdf\x3a\x67\xd9\x2b\xaf\xc1\xe6\x26\x08\xeb\x2e\x7b\x62\xfc\x3d\xeb\x2b\x2e\x58\x5e\xdb\x73\xe8\x80\x8b\x6e\xb8\x7a\xf6\x0f\x8f\xb5\xa0\x7f\xfd\xf8\xce\xfd\xcf\xbe\xf8\xdc\xed\x89\x4b\x7a\x1c\x23\xeb\x4c\xf4\x1f\x37\x0e\x14\xe3\xdb\xf4\x6b\xb4\x5f\xc9\xcf\x68\x3f\x7c\xc7\xfe\x2b\x8a\xed\x17\xd4\xd9\xf9\xb5\x18\x99\x53\x03\x6a\x60\xb7\x0a\x6e\x50\x04\x7e\x4b\xea\x7f\xac\xf8\x8a\x14\xd3\xfa\x2f\x0f\xa9\xff\xca\xa3\x44\xc8\xb2\x2d\x9a\xc8\x0b\x10\x02\x7f\x8b\x29\x4c\xea\xa8\xf3\x24\x51\x4a\x9a\x05\x6f\x4e\x88\x6e\x9b\xe2\xcb\xc6\x9b\x66\xb5\x88\x92\x22\xd8\x35\x4f\x8b\xad\xb1\x33\x86\x50\x55\xd0\x23\x00\xc6\xe3\xce\x83\x64\x9f\x0c\xa1\xea\xaa\xca\x0a\x58\x5a\x01\x1b\x2a\x46\xce\x7b\xec\x4d\x43\x7c\xe4\xa3\xa7\x99\x33\xc7\xd1\xc9\x25\x7d\xe6\x6f\x59\xb7\xf4\xae\xc4\xc2\x5e\xd3\xc7\xbc\xb9\x0f\x1e\x9a\xd2\xbc\xe5\x89\xcd\xcd\x90\x61\x99\x35\x4b\x92\xe8\x15\xf4\xe7\xa7\xae\xbd\xf5\xe2\xc2\xfc\x86\xab\x56\x36\x3e\x3b\xa9\xac\x47\x89\x33\xf4\x27\x32\x0f\xa2\x83\xb9\x71\xc0\xad\xc7\x7b\xba\xd0\xc0\x9e\xce\x1a\x58\x57\xbb\xde\xb4\xda\x95\xad\x22\xa1\x12\xfc\x65\x95\xdb\x51\xd1\x9e\xa3\x60\x35\x9b\x72\x84\x90\x4f\x6a\x85\x02\xd8\x27\xa3\xd1\x18\x23\x29\x67\x72\x99\x54\xd9\xa7\x71\x40\x52\xf5\x6a\x25\x8c\x97\x5a\x54\x46\x76\x47\x15\xc1\x46\xb5\x6c\x06\x08\x91\xcb\x9a\x06\xb6\xce\x8c\x86\x66\xc1\x58\x54\x72\x15\x07\xcd\x58\xc8\x36\x9c\xfe\xf7\xbf\xdb\x7e\x3a\xfb\xc3\x4f\xcd\xdc\x23\x1b\x36\x3e\x62\x68\x5b\xc6\xcc\xb2\xad\x5f\xb3\xf6\x11\x96\x83\x6b\xe1\x62\x74\x23\x9a\x87\xa6\xa3\xdb\xe0\x6a\x38\x1c\x1d\x41\x27\x61\x19\x2c\x5b\x03\x0b\xa0\x01\xfd\x8b\xfa\x66\xc4\x16\xe0\xea\x29\x97\x49\x27\x4b\xc0\x99\xa2\x7a\x20\x6c\x26\xbf\xa0\xeb\x33\x35\x7c\x47\xcd\x4e\xf6\x0c\x00\x2e\xc6\xd5\x03\x7b\x0a\x87\xde\x1c\xa3\x8a\xdc\x10\xd3\xda\x06\x14\xbb\x97\xc4\x41\x9d\x58\x21\x69\xdd\xf8\x5a\x24\xce\xaa\xc7\x43\xdd\x86\x54\x44\x74\xfb\xab\xb6\x91\x70\xf1\x09\x74\x1d\xdc\x7b\x1c\xad\x5b\xc2\xd5\xa3\x2f\x97\x2d\x9d\x0c\x0f\xa1\xac\xb6\x0d\xf0\xd4\x0c\x44\x6a\x43\xdb\x7f\x68\x6f\xe1\x46\x09\x41\x50\x08\xea\xb4\xb3\x42\xd2\x5e\x2e\xa3\x2a\x0b\x11\xc5\x62\x22\x95\x3f\x4a\x11\x9e\x9f\x0b\x50\x5e\x09\x41\x7c\x11\x1a\x1d\x9e\xbc\x7c\x52\xef\x48\xb9\xbd\x43\xb0\x94\xd4\x60\x57\x55\xc7\xa2\x79\xd0\x07\x09\xaf\x08\xb9\x92\xa5\x6c\x49\x69\x48\x30\xb0\x56\x78\xa2\xa6\xb0\xd7\x85\xbd\xfa\x55\x0d\xba\x70\xdc\xed\x57\xd7\xc2\xf1\xee\x48\x91\xbf\x38\x7a\x61\xfd\x55\x05\x6b\xaf\x10\x8d\xc1\xe1\x67\xb8\xaa\xf5\x63\x06\x06\xad\x2b\xc5\xba\xbb\x1e\x6d\x2d\x8e\x57\x9b\x17\xfb\xeb\xaf\x86\x9b\xbf\xff\xed\x1d\x7b\xda\xf6\x69\xe7\x7a\x18\x57\x0f\xbc\x60\x3a\xf5\x19\xa9\x6a\xe3\x4d\x9a\xc9\x63\x8a\xc9\x20\x92\xc2\xb3\xa0\xf4\x98\x5e\xad\x7c\x8e\xf2\x48\x90\x4a\xdb\x08\x71\x09\xbd\xc4\xf9\x75\x91\xf8\xab\x62\x77\x92\xe8\x26\x2d\xa6\xb3\xea\xbf\x80\xa2\x62\xb3\xa7\x2c\x99\x54\x51\x5d\x48\x08\x15\x96\x86\xbc\x1e\x71\x7b\xf2\xf4\xb3\xbf\x4f\xae\xca\x31\xdf\xf4\xc9\xaa\xab\x8c\x66\xe4\x16\xaa\xdb\xfa\xa0\xd6\x5d\xef\x31\x75\x67\x9b\x57\x3f\x33\xb6\x7e\x1b\xda\xab\xc7\x8d\xac\x5c\x3d\x70\x82\x22\x90\x70\x90\x18\xb1\x59\xa5\xca\xc9\x12\x23\xc8\xae\x16\x72\xe2\xf1\x59\x07\xd8\xbb\x73\xe5\xb1\xbe\x58\xb5\x24\xc6\x9c\x8c\x21\xb4\xf3\x63\x5b\xa8\x30\xc7\x68\x6c\x5c\x9f\x38\x72\xf2\x35\xae\xbe\x4d\x2e\xbe\x6e\xc2\xd5\x79\x32\x7c\x11\xfe\x06\x3d\x8c\xb8\x2f\xc8\x39\x9d\xa1\xc9\xae\x9e\x60\x19\x90\xb3\x22\x8a\xcf\x80\x67\x2a\x3b\x62\x8a\x0d\xef\x61\x2f\xb2\x26\xb9\x5e\x55\xce\x75\xca\x6e\x2c\x7d\x05\x17\xde\x61\xd9\x1a\x53\xdc\x2e\x35\xe1\x26\x11\x31\xb7\xdd\x84\xbf\xfa\x4d\x61\x39\xd7\x49\x92\xb8\xc5\x92\xaa\x44\xb1\x44\xc8\x15\x25\x39\x82\x2d\x9c\x17\x39\xd6\x54\x58\x56\x81\xf7\xbe\x58\x52\x42\xa5\xa4\x4b\x24\x4b\x13\x0f\x04\x21\xd4\x1d\x8f\xcb\x36\x8d\xf2\x1d\x4b\x6d\x42\xb9\x22\x84\x61\x55\xd0\x13\x2a\x24\x08\x58\x7d\xa0\x27\x44\x61\x33\x34\x09\xd8\x0f\x12\xfe\x11\x38\xe3\xd1\x45\x27\x1e\x78\xea\xa1\x29\xfd\x98\x03\xd5\x77\x7f\xbc\x60\x53\xe3\x36\x79\xfb\xbb\xd1\xb1\xf7\x8c\x58\x73\xcf\xfc\x6d\x35\x03\xe7\x2c\xfa\xe3\x21\xb8\x65\xe9\x3b\xdd\xac\xfd\x4e\xcc\x7a\x2c\x62\x5d\xb3\x6c\xd8\x83\xd7\xcc\xbc\x7e\xe9\xb6\x87\x86\x5d\xd7\x27\x24\x06\xa7\x8f\xb9\xbf\xa9\xfe\xe1\x68\x75\x1f\x7f\xe1\x1b\x9a\xcd\x37\x95\x1b\x07\xac\x19\xf1\x5f\xa7\x49\xab\x03\xf3\x9a\x52\xf1\x5f\x9b\x87\xf4\xa3\xb9\xb4\xe2\x2f\xec\x8b\xb8\x6c\x29\x31\xe3\x75\x66\x88\x19\xa0\x57\x78\x95\x30\xe9\x7e\x97\x82\x06\x68\xfd\xee\x6f\x50\x44\xa7\x4e\xad\xf9\xeb\xed\x3b\x9f\x7a\xe2\xb1\xcd\x4f\x3f\x81\xf6\x31\xa5\xd0\x0a\xc3\xe8\x08\x3a\x83\xbe\x47\xef\x2d\x83\x5c\xe3\x91\xe3\xc7\x8f\x1c\x79\x97\x72\x62\xb6\xb7\xf0\x1c\x57\x0f\xdc\x60\x1c\xad\x8b\xa0\xc2\xc5\x68\xa4\xfc\xfc\x8a\xdb\xa4\x2a\x9c\x53\xeb\xbc\x70\x1d\x53\x24\x9b\x9a\x70\x49\x3a\x72\x0b\xd6\x45\x0e\x3c\x5c\x9b\x9a\x10\x1c\x3a\x92\x23\x96\xdd\x40\x31\xba\xf4\xb2\x41\x92\x09\x74\x55\xd5\x04\x3d\xa1\x14\xb0\x5d\x80\xe4\x11\x02\xab\xb9\xd1\xc7\xc7\x55\x15\xf7\x1a\xf5\x25\x8a\x24\xd8\xe4\xb0\x21\x6b\xdb\xea\x17\xba\x97\x67\x41\x81\x79\xad\x75\x28\x9b\x24\x36\xf3\x26\xe4\xe6\x26\x73\xe3\x80\x13\xe4\x80\x51\x7a\x6d\x8f\x49\x4d\x70\x78\x80\x01\x93\x4a\x6e\x1b\xe5\x58\x76\xda\xb0\x1d\x2d\x3b\x49\xf4\x8c\x24\xcf\xb0\xaa\xc4\x6a\x43\xb6\xc6\x65\xaf\x48\x02\x79\x40\x71\x99\x45\x49\xb1\xda\xe2\x58\x43\x6a\xe6\x21\x96\xdc\x80\x48\x6e\x7c\xa7\x02\x30\x5d\x38\xe7\xd9\xd4\xd6\xf2\x11\x04\xe8\x2b\x79\x9e\xd9\x7c\x4b\xd3\x93\x0f\x2e\x7f\xfc\xf7\xab\x90\x9b\xcb\x87\x16\x58\x80\xde\x41\xff\x46\xa7\xd0\xf1\xb1\x83\x0e\xa3\x4f\x98\x77\x27\xbe\xff\xce\x7b\xef\xbc\xf9\x16\x48\xe9\xf1\x6d\xdc\x38\x90\x0f\xea\x41\xaa\x98\x51\xaf\x3d\xd6\x2a\x18\xc9\x26\x4b\xa4\xb6\x3f\x88\x95\xba\x55\x94\x92\xac\xc9\xe9\x25\x64\x3a\x2e\x31\x21\x1a\xa8\xb3\x49\x28\x66\xb4\xaa\xc5\x60\xba\x6a\x31\xa5\xbb\xf1\xc9\xa5\xca\x1b\x8a\xa0\x7d\xc4\xe3\xf1\xf8\x03\x37\x6e\xdb\x1c\xbf\xff\x89\x95\xf7\xcf\xdf\x56\x79\x71\xa4\xe1\xaa\x77\xf6\x33\x02\xcc\x87\xf1\xc2\xc0\xda\xca\x0f\xfe\x7c\xe7\x9d\xc3\x0a\xf3\x67\x8c\x7d\xe8\xf9\x8b\x1e\xa9\x2c\xe9\x51\xe6\x2c\x6b\x4d\xfb\x27\x7b\xb8\x7a\xd2\x47\x79\x29\x48\x58\x00\x35\xa4\xe8\x61\xf0\x99\x54\x82\x29\x44\x75\xa3\xdd\x43\xaa\x0b\xdc\xda\x42\x13\xdf\xd3\x4e\xf7\xdc\x40\x39\x7f\x7d\x22\xb6\xa4\x0c\xf4\xc8\x96\x43\x4f\xd0\x2b\xba\xb1\x0e\x02\x1a\xf1\x91\xb3\x34\x54\x28\x34\x30\x23\xe1\x4f\xe8\x74\x62\xfe\x57\x1b\xfe\x8e\x4e\xef\x7c\xfa\xb1\x47\xb7\x6c\xeb\xff\xe1\x5e\xc6\xca\xf4\x5b\xfb\x0c\xfa\x66\xc3\x3f\xee\x82\x41\xd0\xbe\xef\xcd\xbd\x4d\x90\xdf\x75\x88\x70\xe9\xb6\xab\xec\xe3\x5c\x3d\x90\xf0\xba\x92\x81\x49\x66\x3c\x30\xd9\x1e\xc1\x07\x97\xe4\x12\x68\x01\x6b\x42\x10\xf5\x43\x99\x10\x89\x68\x11\x81\x29\x4c\x73\x0a\x46\x6d\xac\x52\xc6\xf9\x0c\xd2\xf3\xa9\x31\x98\xbb\xd7\x32\x3f\xa0\x91\xaf\x4f\x1d\x5c\xda\xd0\xf3\xa5\x6d\x6c\x62\xf8\x90\x75\x6d\x8f\x7f\xe0\x5d\xe2\x90\x9e\x7b\x96\x99\x4d\xf7\x98\xf8\xbf\xe4\xfe\xd4\x9f\xeb\xf9\xea\xe6\x0d\x6b\x4b\xd5\x4f\x3b\xb0\x02\xd0\x1d\x58\x7c\x46\x2d\x2c\x56\x9c\x52\x3c\xed\xbd\x9e\xc7\x63\xed\xec\x92\x76\xe9\x7b\xd2\x3d\x44\x6e\x7e\x2c\x37\x0e\xf8\x41\x21\x68\xa0\x51\x67\xd9\x15\xc3\x4b\x23\x07\xa2\xb4\x8a\x84\x89\x29\xf9\x26\x55\xf6\x44\xf4\x82\x5a\xc1\xa6\xc7\xfb\x64\x63\x14\x8b\x62\x39\x40\x3c\xb1\x1c\x8d\xf1\xa8\x08\x86\x15\x8f\x20\x4a\x0a\xc3\xc6\xe3\x4a\x8e\x5b\xa4\x95\x42\xf9\x46\x51\x4a\x00\xc1\x11\x27\x32\x97\xa4\x4b\x5c\x4e\x97\xcf\x0e\x3d\x4e\x9e\x78\x5c\x92\xc7\xcd\x08\x06\x31\x24\x16\x01\x9e\x48\x57\x7c\x6c\x1b\xde\x5d\x36\xe6\x32\x38\x6e\xdb\xfa\x97\x3f\xbe\xef\xcc\x33\x32\x3a\x8b\xbe\x67\x5e\x7b\xe1\xf5\xb9\x93\x2e\xbe\x8c\x09\xc3\x6e\xa0\xfd\xda\xd9\x9f\xcd\x47\x0b\x43\xcc\xf8\xe6\x03\xe8\xc3\x9f\x14\xd4\xba\xda\x84\x4a\xe0\x87\x76\x18\xdc\xe0\xfc\xdb\xeb\x3b\xde\xbf\x99\xf0\x1f\xaa\xc8\xcd\x8d\xe5\x86\x83\x02\xd0\x17\x10\x93\x5f\x76\xc6\xf0\xf2\xcb\xd9\x04\xc3\x84\x48\xd6\x60\x44\x29\xc4\xbb\xed\xcd\x16\x25\x39\x10\x97\x79\xf1\x45\x68\x70\x48\x7e\x62\x34\x98\x69\xcd\x34\x0b\x59\x6c\xc7\xeb\x46\x83\x0b\xc6\xa0\x2b\xd3\x70\x80\x3e\x78\x74\x6b\xde\x45\x95\x65\x39\x55\xf5\xbd\x87\xf7\xef\xb1\x0c\xf6\xde\x8b\x46\xbc\x5a\x7e\xf9\xc0\xee\x3d\x07\xf4\x9b\xf5\x60\xdd\x2a\xb4\x01\xb9\xd9\x21\x30\x39\x62\xac\x75\xb9\xd8\x63\xcc\x2d\x68\x23\x33\xb2\x15\xa1\x9c\x1b\x2e\x37\x2e\x13\x6f\x7d\x12\x2e\x68\xbb\x11\x9f\x15\xe4\xe6\xd7\x0b\xd8\xee\x9c\x06\x12\x3e\xbc\x2b\xee\x18\xb6\x1a\x64\x63\x34\xc1\xfb\x48\x00\x9d\x40\xb7\xe2\x99\xd8\x63\xb2\x37\x92\x11\xe4\xd1\x13\x02\x7c\x54\xf1\xb8\x54\xd9\x40\x42\xca\x16\x18\x56\x44\xcd\x20\xb5\x78\x68\x8b\x92\x28\xca\x0e\xfd\x2c\x89\xfa\x59\xe2\xc5\x98\x48\x75\x5b\x4c\xf2\x38\x01\x4f\xf6\x63\x53\x02\x4e\x94\x5f\x7d\x2d\xb7\x28\x71\x01\xfa\x02\xb5\xc8\xe8\x34\xfa\x81\x29\x67\x82\x6d\x27\xd0\xbc\x00\xbf\xe2\xcc\x2c\xe9\xd3\x3f\x2e\xfa\xcb\xd3\xa8\xe5\x3b\xf4\x0d\x7a\x47\xc4\x1b\x60\x82\x05\x00\x82\x59\xed\x2d\xfc\x11\xae\x1e\x94\x82\x3b\x40\xa2\x18\xcf\xa3\x20\xa6\x98\x4d\xd8\x52\x4e\x98\x49\xb9\x96\xd9\x6e\xa2\x71\x0c\x39\x10\x83\x72\x19\x4d\x1c\xda\x48\xe2\xd0\x86\xe5\xb1\xa4\xea\x22\x3a\xd7\xa6\x2a\xe5\x90\x36\x5b\x61\x53\xdf\x26\x2a\x5c\x31\xa9\x44\x53\x0a\x43\x71\x22\xb2\x03\x05\xf1\xb8\x9c\x2b\xc9\x59\x58\x0c\x9a\x45\xa9\x09\xe4\x16\x86\x68\x68\xa3\x52\x22\x41\x0d\x77\x07\xf6\xf3\xaa\x4a\xa6\x34\xe6\x95\x3c\x54\x96\x0b\xa1\x42\x66\x56\x9f\x7e\x3b\x06\xf6\x99\x3d\xed\x77\x93\x1b\x27\x5d\x33\xf5\xb6\x3e\x03\x77\x0c\xac\x79\xe7\xa5\x4f\x2f\x32\x0f\xf8\xfc\xa5\x77\x18\xf7\x93\xd0\xf4\xc0\x1a\xd4\xfa\xc4\x2b\xef\x3f\x78\x3b\xac\x46\x6f\xde\x79\xff\x9b\x07\x1f\x83\xc6\xd5\xeb\x11\x5a\x8f\xda\xd1\x89\x1d\x3b\x60\x19\x00\x6c\xfb\xd7\xd8\x06\x27\x78\xfc\xd9\xa0\x14\xfb\x9b\x01\x7c\xdf\x25\xa3\x4a\xd9\xfe\x4d\x11\xb9\x38\x95\x25\xc8\x8f\x92\x79\x5b\x09\x65\x7d\x93\xe0\xb0\x1a\xc3\x0a\xf0\x61\x55\x45\xd2\x06\x0e\x7a\xb3\x0a\xbd\x74\xf6\x85\x39\xd8\xd6\x0b\x60\x21\x20\x05\xa8\x75\x6b\x13\x65\x4f\xfc\xdc\x26\xaf\x0e\x51\xbb\x8c\xdf\x79\xf5\x00\xfb\x9e\x0c\xf3\x7e\xff\x39\xf8\xfe\x9d\xca\xae\x3e\xc9\xc0\x62\x65\xa9\x2c\xe3\x8f\x93\x8c\x41\x77\x30\xb3\x8b\x48\x5e\x5e\x44\xee\x16\x4b\xfa\xe9\x14\x8b\xa2\x7a\x84\x4a\x3b\x9f\x24\x59\xe0\x23\x00\x41\x58\x97\x95\x7a\x55\xb9\xb4\x0b\xa9\x57\x01\xc3\x4a\x30\x1b\x4f\x98\xff\x65\xa9\xe7\x3a\x4f\x66\xa1\xb3\x34\xfc\xc3\xb9\x09\x86\xf3\x04\xe7\x3a\x67\x1a\xa8\x4f\x38\x55\x68\x20\xf6\x59\x10\x8c\xe9\xd2\x42\x2b\xcc\xb4\xd0\xf0\xd6\x51\x1b\x36\x65\xac\x85\x60\x58\xc9\xb1\x69\xca\xdb\x8f\x85\x4b\xae\x28\x07\x7f\x9d\xd9\x96\x91\x2d\xe8\xd2\x80\x3b\xa5\xa7\x07\xce\x63\xc8\x65\x66\x04\x88\xbd\x44\x62\xb2\x34\xf6\x7d\x4d\x57\x5a\x29\x3f\x73\xd7\x32\x42\xde\xe7\x6c\x55\x01\x36\x49\x08\x6e\x88\x27\x1e\x97\xb3\x44\x85\xcf\xfb\xe5\x2d\x4b\x47\xf5\xcf\x51\x59\x0b\xf5\x88\x72\x57\x5b\xc3\x7e\x97\x9a\x06\x43\x65\x8c\xd0\x00\x4a\x41\x2f\xb0\xf8\x57\x49\x99\x68\x27\x29\x23\x97\x45\xb1\xa0\x69\xea\xee\xb4\x19\xc3\x4a\x0f\x6f\x07\x91\x13\x83\x61\x82\xb8\xa8\x09\x1b\x31\x51\x18\xea\x15\x8f\xc7\x15\x6f\x0f\x51\x4a\xb8\xb0\xc4\xf9\x8f\x85\x4d\x7a\xfa\x3f\x2f\x76\x46\xeb\xbb\xfa\xab\xe4\x0f\x7b\x20\x73\x8f\x59\x30\xb9\xbd\x85\xab\x17\xf2\x41\x0e\x89\xba\xdf\x0c\x12\x59\x78\x97\x0b\x4c\x24\xa6\x2a\x59\x48\x43\x60\x77\x93\x2a\x47\xb5\x08\x2b\x0d\xb9\x3b\x3c\xaa\x9c\x1b\xc5\xd2\x07\x9f\x57\xaf\x47\x95\x23\x5a\x04\x8c\x04\xd3\x23\x0e\x51\x6a\xe6\x2c\x52\x56\x41\x49\x39\x09\xa7\x96\x14\x60\xf5\xee\xc5\xea\x5d\xe9\x6e\xa1\xa8\xaf\x51\xcd\x62\xae\x94\xe8\x6d\x24\xa0\x5e\x02\x69\xd1\xc3\xa6\x28\x0d\x29\xe7\xc1\x94\xf9\x9c\xf1\x7a\xf2\x7d\x67\x9e\xda\xf2\xea\xb8\xa7\x27\x37\xdd\x1d\xe1\x62\xc9\x05\x0b\xdf\xbb\xf5\x8e\x3f\x3f\x7c\xe6\x87\x5d\xb6\x47\x56\xac\x7d\x7a\xfd\xbd\xb7\x3c\x1b\x0b\x3f\x74\xd1\xd5\x93\x27\x5e\xfd\x14\xd3\x72\x1a\xce\xfe\xe3\xb2\x05\x23\xe7\x0f\x9a\x71\xdf\xdf\x2f\x1e\x33\xe3\xc0\x1d\x8f\xff\xed\x36\x38\x0f\xb2\x67\x5b\x5e\x7c\xf6\xbe\xdf\x8f\x60\xfa\x15\x55\xf4\x8f\xf5\x19\x04\x18\x60\x6d\x6f\xe1\xbe\x13\xf2\x41\x37\x50\x09\x56\x82\x44\x3e\x5e\x09\xb3\x51\x95\xed\x11\x39\x10\x53\x2a\x0c\xaa\xec\x8b\x36\x31\x15\x76\x63\x58\x29\x33\x92\x25\x71\xe3\x25\xa9\x8a\xc8\x85\xc7\x14\xa3\x4b\x95\x4b\xf0\x22\x70\x2e\x55\xe6\x9c\x72\x18\xbf\x16\x5d\xaa\x2c\x46\x94\xb0\x4b\xa7\xaa\x97\x2b\xa2\x4a\x8e\x07\x3f\x48\xa9\x86\x61\xc5\x1a\x16\xa5\x84\xd9\x9d\x4f\x8e\x49\x99\x59\x94\x12\x5c\x61\xb7\x38\x29\x7b\x4c\x00\x6b\x0e\x5e\xae\x68\x85\xae\x80\x49\x5b\x8b\x41\xf0\xb8\x63\x05\x62\x65\x69\x77\x1a\x3b\x04\xae\x98\x27\xe4\xf5\x38\x41\xb0\xb0\xa4\xaa\xb2\xa6\xba\xaa\x32\x54\x68\x80\x6e\xce\x47\x30\xa9\xac\xe3\xae\x6b\xb6\x3b\xfe\x0a\xa7\x73\xe8\x45\xb4\x66\xd7\xb3\xef\x41\x36\xfc\xd0\x7d\x3c\xfa\x18\xfd\x74\xe0\x0d\x87\x7d\x50\xf7\x9e\x70\x1e\x74\xfc\xd3\x75\xed\x92\x61\x63\x7e\xc7\xf6\x0a\xef\x0c\xcf\x99\x73\xe1\x1b\xcc\xf8\x3e\xdd\xd9\x4f\x0f\xae\xdc\x88\xde\x47\x9f\x2e\x8b\x57\xa2\x27\xd0\x2d\xcf\xbc\xd0\x77\xc6\x8c\xbc\x11\xd9\x4c\xef\x7b\x1f\x86\xf7\x1c\xba\xe1\x4a\x2d\x0e\xb0\x94\xdf\x4f\x3a\x81\x69\x7d\x87\x91\x01\x61\x6c\x32\xd9\xcc\xb4\xcf\xc0\x7d\x4c\x71\x69\xbd\x04\x2e\xb7\x96\xf5\xb5\x91\xae\x77\x0f\x09\x54\x10\x8b\x59\x8c\xc1\x9a\x6a\x89\xf4\x1b\x7a\xf0\x46\x9b\xa1\x81\x14\x96\xdc\x7a\x51\x7c\xf1\xd0\x6b\x2e\xe8\x5d\xe4\x0f\xf5\xb8\x68\xf3\x82\xd0\x2e\xbe\xb9\xad\xf8\x89\xa5\xb0\xf0\xc6\xa8\xb8\x42\xb8\x14\xed\x42\x5f\x5d\xd7\x76\x92\x14\x87\xd3\xba\xf5\xdf\x93\xda\xf0\x7c\x2c\x79\xf3\xf0\x68\x24\x5a\x12\xa6\xf8\xcc\xd4\x5b\x4a\xd7\xae\x63\x67\x2e\xd7\xa3\x12\xf5\xa2\xd7\xae\xe7\x69\xb5\xeb\xb9\xd4\x22\xf5\xe5\x91\x5a\x7c\x60\x25\x16\x9e\x24\xca\xee\x4e\x25\xec\x5d\x0d\x5a\xaf\x67\x3f\xd6\xc5\xe8\x3b\x54\xb6\x9f\x67\x1e\x34\xdf\xbe\xd4\x50\x4e\x3a\x0c\x7a\xe0\xfb\xd8\x79\x5d\xb1\xd0\x0d\xc7\x92\x01\xaa\x3b\x8b\xa3\x50\xae\xd0\xd7\xb9\x29\xc7\xe5\x36\x86\x15\xaf\x4f\x25\xfd\xf7\x3e\x52\x01\x57\x08\xc3\x4a\x99\x57\x55\x22\xd8\xad\xf2\x8a\x92\x12\xc8\x8f\xc7\x15\x57\xce\xff\x6c\x37\xce\x9f\x98\x3f\x67\x9e\x2f\x77\x99\xa2\xef\x6a\xc2\xe7\x66\xeb\x59\x30\x03\xfb\x1c\x82\x9b\x74\x1e\xe5\x80\x19\x34\xbe\x44\xa2\x3a\x46\x52\xe5\x4f\xc4\xb4\x10\x53\x3c\x26\x55\xce\x89\x12\xb8\x94\x94\xd3\x2e\x79\x49\x50\x1b\x3b\x92\xac\x3d\x1a\x55\xfc\x92\xaa\xf0\xd6\x68\x54\xf6\xd3\x4c\x90\x89\xba\xf1\x5a\x37\xb3\xc5\x19\x8f\xcb\x1e\x51\x31\x69\x38\x20\x0c\x11\x46\xa0\x58\x8c\x89\x5e\xe0\x71\x13\xe3\xb6\x04\xd4\x38\x79\xd1\x0e\x61\x91\xe8\x2c\x9e\x01\x0b\x20\xb7\xad\x0d\x16\xa2\x93\xed\x40\x6e\x45\x9f\xee\x86\x53\x77\x37\x32\x12\x9c\x84\x1e\x65\x8a\xcf\xc0\x52\x37\xdc\x89\x06\x07\xd0\xfb\xa7\xfe\x85\xde\x77\xa3\x22\xf8\xb1\x07\x76\xff\x01\x2d\x2a\x66\x07\xba\x8e\xb6\x6d\x2e\x85\xf3\xe1\x9c\x52\xac\x57\x7d\xed\x2d\xc2\x7a\xe2\xeb\x95\x81\x87\xb4\x19\x9a\x63\x8a\xdf\xa4\xca\xc1\x68\x46\xb8\xa4\x24\x1a\x25\x29\x2d\xe9\x98\xe2\xb1\xa9\x09\x89\x54\x82\x48\xc0\x14\xd6\xc9\x82\xf3\x5c\xa4\xcb\xaf\x88\x96\x61\x26\x0c\x45\x04\x3d\x84\xd3\x52\x5a\x1e\x29\x45\x21\xec\x28\x8d\xc7\xe5\x3c\x49\xb1\x59\xe3\x71\xb9\x48\x54\xcc\x25\xf1\xb8\x6c\xa0\x11\x57\xb7\x5f\x94\x92\x06\xab\x4d\xca\xa1\xea\x89\xc4\x57\x34\x1c\x94\x10\x65\x18\xce\x86\x5a\x6a\x2f\xa6\x69\xad\xca\xd2\x20\xe3\x5b\xc1\xff\xd0\x3a\xf3\xd0\x9e\x4f\x2f\x32\x5e\xfc\xf1\x2b\x6f\x2e\xac\xba\xf1\x96\xb1\x53\xb7\x4f\xbb\xfa\x96\xeb\xa7\xb5\xfe\x73\x3e\x89\xc1\x9c\xfd\xee\xd4\x37\x3b\x76\x7c\x73\xea\xaf\xd0\x80\x72\x9f\x7f\x6a\xf9\x82\x97\x5e\xba\xf3\xfe\xad\x5b\xcf\xa8\xe8\x1b\xec\x77\x9d\x46\x6e\x3e\x9f\x1b\x07\xca\xc1\x0a\x90\x08\xe2\x73\x9e\x0d\xb4\xb8\xbe\x0c\x62\x74\x21\x4a\xb1\xa2\x8e\x28\x7e\x0b\xed\xeb\x28\x22\x18\xfa\x32\xe7\x24\xc5\xc5\x5a\x14\x14\xef\xad\x28\xa9\x24\xc0\xc7\x15\x61\x33\xa9\x20\x1e\x57\x2c\xb9\xa2\xd4\x64\xf0\x78\xc9\xfd\xcd\x12\x15\x97\x3f\x1e\x97\x45\x49\xb1\xd3\x42\x7a\x17\x6d\x56\x08\x8a\xd8\x48\x2e\x95\x5e\xe2\x2c\x76\x67\x6e\xbe\x50\x4e\xbb\x37\xaa\x63\x05\xa2\xdb\x00\x75\x3d\x5d\x43\xb8\x19\xaa\xbc\xb1\x68\x5f\x58\x24\x56\xd6\xc0\x50\xb5\x44\x34\x91\xc1\xdc\x77\x1c\x1c\x56\xcc\xd4\x26\x07\x8d\x1c\x33\x2e\x12\x3e\x55\xd7\xbf\x22\x3e\x1e\x7d\x52\xdc\x76\x64\xc7\x90\xdf\x8c\x1b\x55\x51\xc8\x0d\xf6\xa3\xf2\x55\x73\x99\xc3\x8b\xd1\x86\x67\x1e\x7f\xd4\x89\x1e\x46\xff\x08\xac\x75\xdd\x70\xd4\x03\xf7\xae\x99\xdd\x16\x5b\x07\x47\x3d\xf9\xc8\x53\x22\x3e\x17\x0b\x00\xe0\x1f\xe7\x0f\x01\x07\xc8\x06\x13\xb4\x88\x30\xa9\xed\x0c\xb0\x6a\xd2\xe6\xb2\xb2\xb6\xb0\x62\xb3\xa8\xb2\x39\x55\xe1\xe5\xf4\x11\x6b\x84\xe4\x3a\x3c\x64\x2d\x48\xb8\x4a\xab\xbd\xb6\x58\x45\x29\xc1\xba\x02\x44\xbb\xd0\x08\xa0\x9d\x84\xaa\x52\xb1\x14\x10\x8c\x72\x69\x47\xce\x95\x81\x72\xb3\x00\x8e\x85\x35\x6f\xc0\xb2\xc7\xd0\xfb\xe8\xf4\x0e\x74\x1a\x1d\x7f\xed\xd4\x67\x9f\xfe\xe3\xef\x9f\x9e\x3c\xc5\x4e\x83\x05\x70\xc0\x1a\xf4\xcd\xcb\xa8\x15\xed\xf2\xa1\x1f\xa1\xd1\x0b\x07\x40\xd3\xf1\xbf\xab\x1f\x9d\xf8\xdb\xd7\x40\x8f\x1d\x90\x58\xa5\x1d\xf8\xc1\x95\x74\x2e\xb2\x29\x46\x9c\x1c\x56\x0f\x01\x59\x22\x50\x0e\xa4\xec\x09\x87\x86\xd0\x6c\x53\x65\x33\xf5\x01\xb0\x3d\x8c\xf7\xd6\x6c\xc1\xf3\x90\x7c\x64\x1e\x3e\xa9\xb3\x1d\xec\x66\xb0\x84\x4a\x59\xc2\xce\x60\x41\x03\xb4\xfd\xf3\x6f\x50\xfc\xf0\xe0\x8b\xaf\x7e\xb1\xf3\xc9\x27\x1f\x7f\x0a\xed\x46\xfb\x98\x08\xb4\xc1\x42\xf4\x27\xf4\xd3\x3f\xd0\x27\xb9\xc8\x0d\x5b\xb2\x61\xc9\xb7\x87\x8f\x1e\x3d\x0c\xd7\xd1\x18\xcc\x02\x00\xb8\x23\xfc\x21\xe0\x06\x83\xb5\xce\x27\xb2\xfa\x46\x56\xd5\x03\x30\x16\x1f\x59\x64\xbd\xf5\x09\x2f\xb6\x53\x14\x25\xc5\x48\x22\xab\x46\x51\xab\xac\x95\x59\x91\x66\x60\xf1\x02\xeb\x21\x36\xae\x0f\x24\xab\xbc\x00\x4e\x83\xfd\xfe\xfa\xfa\x20\xa5\xe9\x6b\x04\xf9\xef\x2f\x78\x19\x7d\x85\xfe\xc4\xce\x87\x3e\x18\x1f\xb5\x71\xe4\x17\x6f\xbf\xfd\x39\xaa\x82\x31\x1f\x0c\x6b\xb1\xbf\xc7\xb9\x41\xdc\x38\x10\x04\xbf\xd3\x62\x7f\x46\x0b\xc1\xdb\x08\x98\x54\xd9\x8b\x6d\x0c\x5f\xba\x8f\x44\x3b\x03\x39\xda\x7d\x20\xbe\x84\x45\x94\x08\xad\xb6\xb7\x80\xd0\x6a\x53\xaf\xde\xe8\xc3\x16\xa9\x20\xe6\x10\x32\xed\x2e\x06\xdb\x91\x4c\x9b\xd8\xe5\x25\x4c\x03\xcc\x83\xd9\x27\xf6\xf5\xdb\xf5\xf4\xde\x5d\xb7\x3d\xb9\x67\xd3\x1b\xdb\x6e\x1e\x36\x7a\xec\x94\xe9\x57\x4c\x3a\x75\x92\x19\x0c\x0d\x50\x1c\xfe\xe8\x30\x79\xff\xae\x8d\x92\x7b\xf1\x82\xfb\x9e\x76\xaf\xf3\x0d\x1f\x58\xd3\xdb\xe4\x03\xed\xa9\x1e\x06\xf6\x4b\x52\x27\x39\xbc\x53\x1f\x49\xd2\xcc\x93\x0a\x5e\x33\xab\x26\xcc\xa4\x1a\xd0\x6c\x34\x85\x33\x9b\x19\x38\xbd\x99\x41\x31\xb8\xd4\x84\x81\x20\x42\x18\xd8\xce\x0d\x1a\xb4\x78\x98\xcd\x69\xdb\xc0\xc4\x64\xb4\x80\x6f\xde\xd4\x76\x06\x8d\x86\x86\xb6\xd5\xf8\xf3\x65\xe4\x66\xa7\x71\xf5\xc0\x02\xea\x01\x71\x62\xb0\x49\x4b\xa8\xd9\x22\xc4\xaf\xe9\xe2\x93\x6d\xbf\xf8\xc9\xae\x8c\x4f\x96\x99\x9d\x6d\x67\xe0\xab\x32\xfa\x27\x72\x0b\xd5\x6b\xd1\x08\x34\x08\x96\xb7\x3e\x49\x64\x5d\x7b\x0b\x7b\x98\x3f\x04\x42\xe0\xd1\x8c\xce\x74\x46\xef\x09\x32\x66\xbb\x19\x1b\xe9\x66\x33\xb2\x2a\x41\x4c\x28\x8a\xc8\x79\x04\xd2\x19\xdb\x2b\xd8\x80\xc2\x7e\x54\x31\x0c\xcb\xd5\x59\x3b\xfb\x5e\xff\xf7\x56\x02\x52\x94\x55\x61\x97\x03\x7b\x79\xc5\x64\xfb\xc9\x2e\x9b\xf7\x02\xc5\x1c\xa8\xa8\x80\x4d\x26\x73\x20\x2b\x85\x32\xc4\xe7\x69\x58\x18\x7a\x2b\x7b\xb6\xa8\x88\xbe\x78\x5c\x09\x1a\x45\x29\xc1\xe7\x85\xa8\xbd\x49\x31\xf2\xa8\x66\x77\xc0\x20\x2b\x64\xf6\xff\x57\xd6\xb8\x82\xae\x6a\x4d\xe2\x5d\x38\xfc\xce\x7b\x8a\xe3\xcc\xfc\xa5\xb9\x55\x3d\xe2\x15\x75\xfd\xe7\x3e\x50\x7c\x69\xdb\xbd\xb7\xe6\x56\x76\xeb\x59\xc4\x37\xe6\x2f\x6c\xb8\xfc\xb6\xd7\x51\x8f\xab\x6a\x7b\x45\x5c\x6b\xfd\x0b\x67\x5e\x7e\x1b\xe4\xe0\x6a\xfc\xa3\x17\x40\x30\x1e\xb9\x39\xa7\x90\x0f\xca\xc0\x3b\x40\x0e\x46\x94\x1c\x13\x49\x9a\x5b\xb5\xea\x0d\x8e\xc4\x39\xb0\x2c\x28\x82\xd8\xba\x21\xd9\x69\x7f\x14\xeb\x33\x3c\x71\x5b\xfe\xbe\xb1\x78\xe2\x76\xd9\xe5\x94\xdd\x7b\x15\x20\xfd\x24\x97\xed\xdd\x59\xf7\x6e\x8b\x88\xdf\xe6\xe4\xe2\x0a\xbb\x5c\xba\x97\x53\xfc\xd2\x4f\x76\xd9\xbb\xb7\xc9\xe7\xf7\xba\xc2\x72\xb1\xb3\xa9\xa4\xb8\xd4\x15\x4e\x94\x14\x97\x66\xc0\xc5\xfa\xfc\x5e\x51\x8a\x83\x0b\xcc\x58\xf2\x95\x96\xf9\xfc\xc5\x25\x69\x00\x58\xf8\x92\xf6\x6e\x49\x07\x48\x58\x25\x27\x48\xd9\xea\x0d\x62\x93\xc9\x91\x57\x84\x2f\x90\x55\xd2\x22\xbf\x59\xb0\x94\x2c\x51\xa9\x66\x20\x19\xd8\x62\x0f\x9b\xc9\x91\x42\xd9\xfa\xc7\x2f\xb9\x8f\xe9\x11\xee\x51\xd9\xeb\xb2\x2b\x6f\xbe\xb7\xac\x64\x25\xf3\xd6\xdf\x2b\x9c\x03\x2e\xe9\x57\x76\xc1\x85\xcb\x1f\xce\xcf\x7d\x1b\x36\x37\xc0\xb1\xf0\xba\xdf\x74\xab\xf0\x2e\xcf\x6f\x98\xdc\x6f\xcd\x24\xb4\x68\xed\x9c\xb6\x49\x4b\x2f\x29\xac\xeb\xeb\x5c\x1e\xb8\xfb\x8e\xda\xd9\x97\x31\x03\x49\xbe\xb3\x05\x00\x2e\xc6\x1f\x06\x59\x20\x4e\xe3\x0d\x54\x66\xf9\x58\x02\x43\x24\x5b\x48\x75\x29\x91\x08\x82\x45\x3b\x07\x3e\x13\x96\xa0\x59\x54\x4c\x91\x5d\xef\x07\x63\x05\x40\x74\xb2\x21\x49\xac\x2c\xe5\x4b\x61\x49\x29\x2c\x85\xa4\xd7\xdf\x7d\xf5\xdb\x77\xc0\x41\x70\xec\xbc\x3f\x2c\x30\xa0\xf9\x97\xc1\x3d\xb9\x55\x28\x7b\x04\xfc\xc3\x8d\xab\xc6\x36\xf7\xe7\x87\x0f\x8a\xa3\xee\xe8\xb7\xe8\x43\xf4\x21\x8c\xc0\xe0\x88\x3e\x7f\x59\x0a\x85\x65\xa3\xd0\x9f\x97\x41\x73\x7d\x75\x25\xe1\x44\x43\x6e\xb6\x51\xc8\x07\x3e\xd0\x40\xfa\xe0\x6d\x11\xd9\x17\x51\x80\xd6\xac\x60\x3f\x46\xea\xcb\x39\x1b\xc9\x52\xc9\xd5\x59\x72\x49\x16\x54\x6c\xf6\x8a\x37\x80\x62\xb7\x55\xbc\x81\xf7\xdc\xf5\xd3\xfe\x28\xdd\x73\xbb\x53\x76\xec\x95\x6d\x4e\xd9\xba\x17\x28\x56\x47\x45\x05\x24\x5f\xc9\x29\x27\x30\x8f\x06\x6c\xd0\x1a\xd3\x40\xfa\x9c\x11\x62\xed\xa0\x4d\xab\xb8\x84\x7c\x29\x2a\x5d\x0f\x87\xc2\x7f\x42\xd3\xa8\xa1\x3b\xb6\xb8\x50\x7e\x0f\x78\xaa\xdb\x6f\x50\x38\x02\xb7\xcf\x41\x7f\x7c\x4e\xc8\xef\x8f\x1e\x6e\x3b\x8a\x9e\x7b\x03\xdd\xb1\x1a\x5e\x0d\x97\x5e\x73\xe7\xe3\x4b\x36\xad\xbc\x73\xfd\xb2\x07\x1f\x3e\x54\x46\xe5\xd8\x0e\x34\xd9\x30\x9b\x6f\x06\x15\xe0\x1e\x1a\x15\x91\x2d\x31\x25\xdb\xa2\xca\x45\xd1\x84\x97\x74\x02\x97\xc5\x62\x72\x85\x36\xcd\x48\x44\xf6\x10\xe8\x25\xbf\x47\xc5\x96\x28\xf6\x3d\xd2\xa5\x58\x32\x17\x55\xba\x79\x68\x4f\x65\x9e\x9f\x5e\xd0\xa0\xa8\x38\xb0\xa2\x2e\x95\x14\x23\xf6\x48\xba\x89\x8a\x40\xca\x16\xb2\x89\xee\xe3\x48\x38\xb3\xc9\x68\x70\xd8\x89\xb1\xe2\x23\x81\x93\xea\x9a\x50\x46\x31\x56\x49\x3a\xb0\xd0\xe1\x85\x10\x0a\xee\xe0\xce\xdc\xf6\xa0\x91\xb5\xc4\xfe\x38\x67\xd9\x0b\x3d\xcc\xbd\x8f\xde\x71\x74\xdf\xcb\xb7\xde\xf5\xfc\xd3\x2f\xcf\x59\xdc\xf8\xe4\xcb\xdf\x7c\x7c\xd6\xfc\xe3\xea\x3b\xba\x0d\x0c\x5d\x39\x69\xe2\xd4\xf1\xd3\xfe\xf4\x57\xce\x7a\xf6\x87\x15\x0f\xed\x3b\xcc\x3e\x86\xbf\xbf\xf5\x0d\x7b\xcb\x99\x09\x47\xfe\x0c\x20\xd8\x82\xca\x85\xc3\x5c\x3d\xe8\x0e\x16\x53\x7d\x89\xd7\x01\xeb\xa5\xc2\x68\x82\xc3\x47\xd1\x83\x65\x6c\x6e\x49\x2c\x26\x77\x8f\x28\x40\xab\x44\x73\x93\xc5\xf0\xd9\x08\x46\x0e\x3e\x98\xf9\xa9\xb2\x21\xbc\x18\x65\x5a\x64\x2f\xc7\x47\xfc\x5e\x39\x5f\x54\xec\xb6\x38\x49\xce\x92\xc5\x28\x23\xc4\xa0\x4a\x40\x24\x05\x03\xb2\x07\x2f\x84\xdd\x46\x4d\xd7\x20\x29\x3f\x23\x0b\x51\x90\xb1\x0e\xce\xae\x96\x61\x0b\x37\x78\xd5\x63\x82\x39\xba\x6d\x2a\x42\xc3\xcc\x55\x2f\xdd\xb2\xf3\xe5\xc4\x67\xeb\x56\x26\xa6\xdf\xb2\x6e\x79\xf2\x54\xeb\xd9\x03\x68\xcf\x93\x6b\xb2\x06\x0e\xfe\xed\x95\x3b\x46\x5f\xfb\xea\xfb\xcc\xa1\xb6\xbe\xa8\xf5\x85\x9d\xcc\xb8\xb6\xbe\x77\xdf\xbd\xeb\x3d\xa6\xf7\xd9\x1d\xdf\x7c\x4b\xcf\xc3\x2c\x00\xb8\x0d\xfc\x21\x90\x07\x26\x83\x84\x47\xf7\x3c\x53\xc6\x43\x32\xc7\xee\xc1\xa6\x5b\x0e\x3e\x0d\xf9\x99\x76\x84\x07\x86\x65\x31\xaa\xb8\x3d\x34\x42\xe6\xb1\x88\x52\x92\xe5\xed\x01\xa2\x96\xdd\x22\xe9\xaa\x35\xda\x89\xaa\xf6\x07\x34\x37\x94\xa7\x6e\x4a\x2c\x9a\x01\x38\x42\x13\xf9\x22\x9d\x79\x21\x33\x0b\x3a\xbe\x79\x70\x6e\xed\x84\xe9\xab\x37\xad\x5a\x73\x78\xe7\xcb\xbb\x2c\x96\xbe\x7f\xba\xfb\xe4\x69\x76\x7f\x0b\xcc\xe9\xb5\x31\xb2\x67\xdb\x73\x7b\xde\x6c\x81\x5b\xcf\xd4\xc3\x53\x91\x6b\xc7\xde\x00\x45\x3d\xcf\xe8\xe6\xfa\x73\xd7\x82\x7c\x70\x2d\x48\xe4\x12\x1d\x65\x52\x13\x2e\xcd\xe3\x32\x18\xb1\x83\xc9\xda\xc3\x8a\x09\x9b\x1e\x91\x4e\x09\x48\x2f\x0c\xcb\x12\xe9\x32\x20\x5e\xb5\x97\xf4\xfd\x09\x59\xb9\x78\xd8\x1e\x51\x0e\xc4\x81\x62\xc2\xee\x27\x08\xc4\xd3\xc5\x84\xe7\x9d\x42\xc3\xe7\xef\xe4\x8e\x09\x45\x7a\xc5\xe7\x2d\x58\xb5\x7c\xcb\xa3\xc9\xa4\xc5\x16\x6d\x6a\xf8\xe0\xef\x4c\x31\xf4\xc0\x12\x9b\xed\x21\xcf\x87\x6f\x1f\xfa\x60\xc7\x71\xa6\xf6\xa7\x37\xe1\xd7\x23\x07\x5f\x3e\x06\x96\x51\x1b\x03\x01\xae\x85\x6f\x06\x39\x60\x52\x86\x8d\x21\xdb\x22\x8a\x8b\x55\x93\x82\x3f\xdd\xed\x4b\x7d\xc6\x1c\xda\x28\x99\x43\x2d\x4e\xb3\x8f\x26\x7a\x3d\x39\xa2\x94\x10\x6c\xce\x94\xe5\x2c\x3b\xe3\x32\x20\x10\x30\x7e\x49\x31\x63\x77\x59\xa0\x59\xaa\x18\xc9\x88\xc4\xa2\x5e\x89\xc6\x60\xb0\xbd\x54\x40\xd2\xbf\x82\x41\x3c\xb8\xe3\xe2\xe4\x35\x4f\x7c\xbf\x08\x7d\x89\x5a\xaf\xb8\x73\xf0\xfc\xa5\x70\xce\x2b\xcf\x8f\x5b\x37\x94\x6f\x6e\xdb\xd2\xaf\xef\x56\xf4\xea\x71\x74\x37\x9a\xe2\xc9\xd9\xdc\x8b\x99\x05\x19\x98\x55\x7d\x51\xdb\x10\x52\x17\x62\xe6\x42\x5c\x3d\xc8\x06\x37\x65\xd4\x3b\xe1\x39\x48\x96\xf4\x1c\xd2\x6d\x97\xd9\xb4\x34\x44\x6b\x98\x30\x7b\xa8\xf5\x9f\x9d\x6a\xc8\xf3\x88\x09\xc1\x26\x91\xb9\x48\x36\x8a\x7f\x09\x44\x3c\xa3\x9f\x99\x0b\xd3\x01\xf4\xc5\x20\x6e\x4f\xd6\xdd\xf1\xdb\x7b\x5e\xbf\xf1\x87\x93\x0f\x4c\x9b\x7e\xc7\x9a\x15\xcb\x97\xdf\x37\x91\xab\x47\xb1\x8a\xe8\x72\xf4\xdd\x3e\x74\x14\x35\xd7\x3d\xd1\xf7\xcb\x1f\xdf\xff\xdb\x78\x14\xc2\xfb\x70\x6d\x7b\x0b\x8b\xf8\x43\x34\x86\x11\xc6\x67\xa9\xd8\xa2\x26\xfc\x0c\x6d\x9a\x22\x41\x0b\x8f\x9e\xfa\x95\x0b\xb1\x1d\x0b\x3c\x24\xab\x51\x48\xb3\xc1\xd8\xde\xca\xf6\xa8\x72\x59\x94\x44\x2e\x0a\x3d\x44\x34\x92\xdb\xd0\xcc\x89\xfe\xbc\xfc\xe2\x30\x89\x2c\x16\x87\x45\x49\x2e\x8f\xcb\x16\x31\x09\x24\x4f\x76\x99\x16\x62\xed\x07\x6b\xfa\x31\x5a\x96\xd0\x4d\xea\xeb\xaa\xf4\xa8\x85\xc1\xce\x64\x94\xd8\x15\x5d\x3b\x62\xeb\xb6\x07\x16\xd4\xdc\x33\x77\xfe\x7c\x97\x73\x8b\x37\xff\x2f\x07\xde\x3c\xb5\xed\xc8\x13\x2b\xfa\x3d\xbd\xf9\xba\x63\x13\xe4\x6f\x7f\x40\xa7\xe1\x92\x09\xab\x6e\xee\x5f\xf9\x9b\xdf\x5d\x3c\x65\xfa\x84\x9b\x73\x87\xe6\x5c\x90\x73\xd3\xc0\xc6\x03\x6f\x34\x6e\x38\x74\x69\xef\x11\xe3\x2e\x9c\x7e\x47\x5d\x5c\x9e\x78\x82\x9c\xbf\x5e\xc8\xcd\xee\xe3\xc6\x81\x6e\x60\x0a\xa0\xf2\xcf\x6c\x54\xe5\xb2\x88\x52\x68\x4a\x57\x4c\x7a\xd4\x26\x89\x54\x4c\xda\xa8\xe8\x33\xc0\x30\xd1\x0e\x45\x51\x52\x34\x99\x4f\x61\xe1\x14\x83\x0d\x4f\xd6\xe1\xc9\xa6\xc5\x93\x40\x29\x2c\x13\x25\xb9\x38\x2e\x9b\xc5\x24\x70\x4a\xfe\x22\x2a\xfe\xc9\x64\xf5\x94\xa8\xdb\x67\x28\x39\x67\xaa\x34\xcf\x53\xd4\x6b\x4c\xf3\x9b\xcb\x66\xcd\x99\x3c\x73\x56\x78\x63\xdf\x0f\x77\xed\xfa\x68\xf7\x1f\xee\x79\xa8\xff\x93\xeb\x3e\x7c\x6d\xcc\xae\x7b\xbf\x45\x3f\x86\xa7\x6f\xb9\xff\xaa\xba\xa5\x37\xfe\x6e\xfa\xf4\x1b\x46\x0c\xe9\x3f\xfe\xae\xa7\x5e\x7d\xf5\xa9\x0d\x7f\xba\xa2\xcf\x84\x9b\x2e\x7f\xe8\xb1\x71\xbf\xaf\xe8\xf1\x75\x46\x0f\xf7\x21\x90\x0b\x0a\xc0\x85\x5a\x87\x63\x9e\x86\x91\x22\x4b\x31\x45\x30\xab\xb2\x2f\x9a\xce\x99\xe6\x91\x6e\xee\x1c\x72\xd0\x5e\x64\x8c\x76\x4f\x76\x01\x2d\xb5\x52\x4c\xee\x38\x6d\x7f\x26\xc5\x56\xc4\x6c\xf2\xf5\x63\x74\xd9\xe6\x80\xa4\xe5\xbb\x1c\xbe\x7b\x45\xa4\x67\x28\x14\x8c\x0c\xea\x3f\xfa\x8e\x8b\x6b\xeb\xaf\xaa\xbb\x60\x50\xcf\x60\x61\x74\x60\x45\x2f\x78\xbc\x75\x3e\x23\xa3\xad\x0d\x6c\x52\xbe\x30\x60\x5f\x96\x3b\x61\xf5\x8c\x31\x15\xb9\xcb\xec\x17\x5d\x33\xb1\x75\xd0\x8c\x4d\xcc\x67\x80\x01\x41\x52\x8b\x36\x0e\xe4\x83\x42\xbd\x77\x50\x29\x30\x68\x38\x08\xee\x98\x22\x98\x54\x39\x10\x4d\x17\x86\x15\x90\xf1\xe6\x91\xf1\x26\x19\xa7\x2f\xb7\x90\x5a\x79\x8a\xc9\xab\x0d\xb7\x94\xe4\x79\x4b\xc9\x65\xc9\xc7\xab\xdf\x69\xc8\x41\x28\x4f\x2c\x8a\x16\xfb\x0b\x7a\x04\x7a\x85\x07\x5f\x5b\x3e\x6e\x6c\xc9\xb5\x17\xd7\x5e\xd8\xc3\x9d\x5f\x51\x53\xf8\x3b\xb8\xa5\x75\x3f\x33\x11\x7d\x30\x9f\x99\xbc\x2a\x16\xb2\xdd\x6f\x72\xf4\xed\xbd\x78\x49\xbc\xce\x7f\xbf\xad\x2c\x7a\x7f\xdb\xda\xf9\xcb\xe1\x07\x40\xeb\xf7\x7c\x9c\x3f\x44\xb2\x49\xd3\xa8\x66\xc1\x66\x46\x5a\xb1\x38\xf2\x89\x62\x71\xb0\x29\x0f\xd0\xef\x23\x36\x06\xe9\xbc\xd6\x70\x46\x72\xfd\xa2\x94\x14\x58\x87\xc7\x92\xd2\x20\x40\xc9\xcf\xc6\x5a\xc5\x2a\xe1\xf7\x14\xa3\x83\xd4\x84\x64\x3a\x82\x05\x74\x3a\x86\x98\x66\x1a\x92\x0e\x51\x37\x11\x6d\xc1\x42\x61\x01\x9c\x01\x2f\x84\xa5\x8d\xf5\x2f\x7c\xb8\xf7\x93\x6a\xe3\xc8\x8f\xd6\xc1\x52\x38\x14\x3d\x87\x0e\xa0\x3d\x48\x79\xed\xbb\x4f\xe0\x61\x34\xf0\xcf\x67\x98\x6d\x70\x36\x6c\x1c\xb5\x61\xf8\xd6\xc4\xe8\x61\xe8\x2d\x74\x0a\x9d\x42\x87\xe0\x44\xc8\x7c\xfc\x0d\xdc\x02\x37\x91\x1a\x8c\x86\xf6\x16\x6e\x3c\x37\x0e\x84\xc0\x4c\x1a\x03\x52\xec\x7a\xbe\xcc\x64\x52\x93\x59\xae\x20\x41\xec\x32\xa5\xd0\x43\x35\x1f\x57\xd4\x22\xb8\xc5\xd8\xd7\x25\x7a\xd3\xe4\xcd\x0a\xd2\x7c\x99\x46\xea\xec\xc2\x9a\xd3\x02\xbc\xb9\x34\x00\x24\xfb\xe2\xb2\xa9\xf3\x3c\xa3\xa4\xf4\xb6\x40\xcf\xc1\x04\x0b\x05\x43\x15\x2d\x06\xa5\x05\x26\x0d\xb0\x27\xe4\x5f\x57\xaa\x2f\x69\x1c\x8a\x96\x3c\xf5\xc4\xaa\x67\xd1\x77\x43\x37\xc6\x7a\x3c\x76\xfd\x5b\x7f\xbb\xe3\xcf\xab\xbf\x45\xdf\x31\x12\x14\x61\x9f\x3e\xeb\x73\x83\x68\xf8\xfe\xa3\x0f\xdc\x7a\xb2\xa2\x6c\x5d\x28\xb2\xf7\x99\xb9\xfb\xa7\xc1\x12\x00\xc9\x5d\xa9\xe7\x9b\x41\x01\x68\xa0\xb9\x7a\xd2\x07\x4c\xc3\x98\x86\x98\x12\xc0\xce\x3c\xed\x9b\xc2\xca\x48\x52\xb1\x26\xf2\x51\x4b\xc8\xeb\x51\x65\x21\xaa\x93\x58\x59\x24\xda\x3d\x95\x03\xa8\xff\xe1\x13\xe5\xbc\x38\xe5\xb2\xb2\x13\x98\x46\x1b\xb6\x8a\x7c\x64\xca\xb6\x3c\x4d\x0c\x56\xf7\x81\x62\x4c\x24\xd3\xd1\x8a\xd2\xb4\xd6\x3e\x2c\x28\x42\x25\xe5\x0f\xac\x59\xfd\xf2\xea\x35\x0f\xf8\x36\x19\xec\x75\x03\x56\xbf\xbc\x7a\x40\x9d\x7b\x93\x97\x1d\xb2\x78\x01\xbc\x11\x3d\xbc\x60\x71\xbc\xd6\xde\xbf\xb0\xa2\xb6\x75\x24\xdb\x58\x5b\x71\x41\xa4\x1a\x40\x90\x0f\x00\xab\x0a\x6e\xc2\xc3\x45\xaa\x7a\x48\x98\x0e\xdb\x07\x36\x52\x80\x40\xc2\xb1\xb4\x62\x51\x43\x76\xb5\x50\x9c\x57\x33\xf6\x64\xa3\x09\xb3\x45\xf7\xb1\x49\xd5\x22\xa9\xa8\x72\x93\xf1\xbb\xb0\xf1\x6e\xc1\x16\x82\x8b\x96\x17\x93\x9e\x44\xda\xbc\xaa\x89\xf1\x50\x05\xcc\x87\xe6\xf5\x49\x78\x33\x7a\x30\xb9\xa1\xb6\xca\x21\xac\x37\xd9\xd8\xc9\x7f\x86\x6f\xa2\xea\xb5\xad\x43\xd9\x64\x2c\x9c\xdf\xc7\x2a\x0d\xa6\xfe\x36\x89\x2d\x16\x82\xeb\x69\x4e\x4b\x16\x63\x14\xaf\xc7\x6e\x22\x39\x4a\xa7\x41\xed\x18\x69\x2c\xa0\xb5\xa1\x72\x6e\x2a\xc4\xe8\xd5\x4a\x88\x8b\xb0\x8b\x92\x8b\x4d\xef\x40\x3c\xae\x58\xb0\x15\x63\xf0\xe3\x13\x56\xe0\x12\xa5\x24\x67\x11\xfc\x85\x5d\x47\x0d\x75\xe7\xf9\xbc\xe1\xc2\xbe\x83\xd7\x6f\x3d\x7f\xa8\x70\xb9\xff\xcf\xdf\x77\x08\x11\x6a\x71\xb5\xc9\x24\x1e\x54\x01\x66\x69\x19\xe6\x62\xfd\xc6\x84\x4d\xaa\x9c\x17\x51\x44\x93\xaa\xc3\xb9\x14\xda\x54\xb9\x90\x46\x48\x3d\x92\x2a\x7b\x9c\x4a\x99\x16\x58\xc3\x0e\x47\x56\xa1\x28\xbd\xc4\x9a\x44\xbf\x2d\x8f\xa8\x53\x6c\xa8\x61\x3d\x23\xe6\x91\xe0\xa8\x52\x6c\xd2\xcb\xdb\xc2\x62\x46\xcb\xb8\x56\xdf\x56\x52\x1a\xca\x63\x68\xb2\x4e\xab\xf9\x26\xf9\xe8\x74\x9a\x8e\x61\x1b\xa0\x0b\x1a\x48\xcd\xdb\x8d\xf7\x0f\x37\x3b\xfa\xdf\x7c\xd3\xbd\x4b\xfb\x78\x1e\x33\x06\xaf\x18\xd4\xf4\xfa\xd8\xe6\xab\xd7\x4f\x78\xf2\xc1\xe5\x8f\x37\xbe\x00\xe1\x4d\x70\x26\xbc\x4b\x2f\x82\x8b\x0e\x5d\xb6\xf2\x82\x40\xdd\x05\x65\x7d\xbd\x59\xd9\x2e\xc3\x6a\x38\x68\xc7\xd0\x3e\xef\xbf\xf3\xde\x7b\xe8\x10\xfa\x48\xb3\x55\x53\x58\x7f\x7d\xbb\x40\xfa\xd3\x8f\xa0\xd5\xa3\xe2\x63\x96\x8e\x7d\x98\xc4\x04\x30\x88\x1a\xf6\xe0\xcf\x80\xf7\x75\x09\xd8\xd7\x05\x4c\x1f\xc9\x3d\xad\x40\x6e\x38\x8b\xff\x0b\xa9\x75\xbb\x88\xa2\xbf\xca\x96\x88\xc2\xd0\x2a\x70\x9d\xee\x9d\x3f\x26\xdb\xa3\x8a\xd1\xa6\x2a\x6e\x3b\x2d\xb5\x31\xf2\xa2\x44\x42\x31\x94\x8b\x5f\xb6\x11\x4b\x0c\xa4\x38\x5c\xa9\xa7\x52\x58\xda\x01\x49\xf0\xa2\x0b\x87\x5d\x92\x7c\x6c\xdd\xb8\x0b\xa0\xa8\xc3\xec\xa1\x3d\xee\x2b\xae\xe4\x7e\x38\x2b\x6d\xde\x1c\x30\x0c\xd6\xd1\xf5\xd8\x0c\xbc\x00\x09\x04\xce\xc5\xf0\xf0\xb1\x6a\xd2\x65\x25\x18\x1e\x2e\x4b\xba\x52\xdd\xd7\xb9\x52\xdd\x97\x51\xa9\x4e\x21\x04\x3a\x54\xaa\x67\x40\x08\xe8\x95\xea\xa4\x6f\xe3\x1c\x10\x81\x03\xb6\xef\x3f\xfb\xf4\x7b\x6b\xeb\x20\x76\xa7\xeb\x1f\xc7\x3f\xfc\xe1\x1c\x2c\x81\x10\x6a\x45\xff\x82\x16\xc8\x3d\xf1\xe3\x99\xb3\xda\x1e\xcb\xdc\x38\x90\x85\x65\x0d\x29\xe3\x96\x52\x7b\x6c\x56\x93\x56\x87\x1f\x8f\xdd\x6a\xa4\xa1\x0e\x2d\x8c\x6c\x8d\x26\x1c\x04\xc7\xc5\x61\x37\x85\xb1\x7f\x09\x14\xc9\x4f\x4b\x61\x1c\x22\x81\x27\x92\x64\xf0\x33\x08\x8e\x86\xa0\x27\x48\x69\x48\xb5\x83\xe0\x6a\x1b\xb9\xb1\x4f\xd5\xd2\xd9\x8f\x3f\x25\x32\xd9\x6d\x5f\x9a\x36\x3f\x79\xcd\x83\xfd\xe6\x3e\x7f\x06\x9d\x62\xf2\xa1\x0f\x96\x05\xb3\x1e\xae\xdc\xb8\x79\xf5\x8e\x17\x8a\x03\x1b\xfa\xc0\x20\x80\xa0\x4f\x7b\x0b\xbb\x88\xd4\xcd\x8d\xa3\x32\x5f\x61\xcd\x6a\x42\xc4\xe3\xb6\x98\xd5\xa4\x41\xf0\x89\xb6\x30\xf6\xa7\x48\xf8\x9b\x3f\x46\x2a\xe5\x3c\x6a\x82\x77\xeb\xb5\x5b\xf8\xc2\x02\x85\xf5\x11\xea\x0a\x7c\x28\x20\x49\xd7\xb8\x35\x41\x2f\x13\xa1\xdf\xb3\x57\x0d\x76\x36\x5c\xc1\xaa\x60\xca\x1c\xa1\x5b\x51\xd8\x67\xfd\x72\x38\xdc\xd7\xf6\x25\x93\x6d\xdf\xb4\xe1\xfa\x47\x62\x17\x3c\x3d\x14\x42\x68\x42\x27\xd1\x99\x67\x4b\x37\xf4\x83\x53\x56\x6f\xdd\x50\xbd\x2a\xb7\x10\x7d\x82\xbe\x46\xff\x44\xc7\x68\xcc\x5e\xc7\x58\xb0\x02\x0f\xb8\x34\xc3\x7b\x4a\x5a\x6c\xc4\xe5\xb0\x58\xd4\x24\xeb\xa1\x50\x33\x96\x34\xda\xb3\x47\x55\x18\x5b\x34\xaa\x43\x3e\x1b\xbc\x24\xe1\x0b\x14\x8f\x4d\xc3\x1e\x89\x89\x31\x4f\xac\x80\xf3\x74\xc2\x5b\xd8\x71\x00\x06\xa0\x84\x8e\xa2\x2f\xb7\xac\xfe\x64\x5f\xf3\x81\x66\xbe\x19\x1d\x3d\xfe\xc5\x3f\xd0\x7e\x78\xe2\xc1\xc7\x1e\x5a\x92\xea\xbf\x9c\x2f\xb8\x49\x3e\xf4\x1a\xad\xda\x3c\x60\x52\x49\x87\x9b\x92\x47\xc3\xb7\x30\xa2\x9b\x3f\xd8\xfb\x64\xbc\xd1\xa8\x9e\x20\xb3\x6a\x15\x35\x1e\x6c\xd1\x89\x12\x81\x2f\x4e\x08\x26\x07\xf1\x85\xf2\x02\xd8\x30\xb2\x8a\x12\x4f\xb5\x25\x69\x37\x20\xad\x20\x52\x46\xfd\x2e\x31\x7a\x28\xf0\xe5\xf6\xa4\x60\xbc\xf0\x99\x69\x1f\x7c\xfb\xed\x07\x9f\xce\xb5\x5a\x1f\xde\x02\x8b\x57\xac\x7b\x72\x0d\x83\xdc\x46\x80\xaa\x07\x0f\xbb\xfa\x37\xe8\x03\xf4\x03\xfa\x1e\xbd\xf7\xc4\x3d\x65\xa8\x8a\x73\x7d\x76\x10\x6e\x7d\xe7\xed\xa6\x3f\x00\x88\xef\x22\xc9\x2d\x10\xac\x54\x62\xc9\x39\x74\xec\x08\x53\x07\xe4\x0e\x8a\x95\xea\xf0\x74\x96\x57\x9c\x76\x54\x2b\xa5\x22\xcd\xd8\xc4\x5b\xad\xd9\xf6\x05\x60\xc1\x33\xb0\xff\x9f\xfe\xd6\x58\xff\xc2\x63\x2d\xe8\x3b\x28\x7c\xb7\x61\xff\x35\x8d\x33\xd1\x2b\xe8\x29\xe6\x93\x2f\xe0\xc8\x1d\xa3\x36\x0c\x47\xaf\xa3\x6f\xd1\x5f\xd0\xe1\xde\x1b\x0b\x03\x50\xc7\x51\xd1\xb0\x5e\xae\x38\x07\x53\xe8\x7f\x85\xf4\x42\x28\x0f\xc9\xbe\xc3\x18\x8c\x75\xc4\x79\x39\x03\x4f\x18\xe1\xc9\x1f\x33\x51\x5e\x5a\x4f\xb1\x4e\x8a\xf2\xd2\xda\xc2\x7a\x29\xca\x8b\xd6\xf7\xc3\x07\x49\xaf\xca\x10\xad\xef\x9c\xf8\xc1\x1c\x6d\x8b\xd0\x80\x8c\x25\xda\x6a\x4e\xa9\xee\xe8\x01\x74\x88\x52\x13\xc3\x99\x2d\xb4\x95\xd3\x40\x00\x88\xcc\x56\x7d\x93\x4d\x64\x44\x35\x30\x04\xbd\x1e\x71\xfb\x07\x70\x22\x9c\x71\xa8\x91\x43\xc9\xd5\x68\x37\x47\x5a\x1e\x3e\x62\x8a\xcf\x36\x33\xc9\x97\x91\x1f\xfe\x65\xf8\xcc\xb3\xd3\xc8\x39\x34\x6a\x7a\xd7\x07\x42\xe0\x76\xad\x9e\x39\xcb\xa4\x26\x78\xcd\x74\x90\x3d\x11\xac\x73\xa4\x98\x02\x8c\xaa\xec\xa4\x01\x7c\x0f\x21\xa2\x77\xdb\x54\xc5\xee\x8f\x46\x13\x6e\x92\xc0\x75\x4b\xa6\x70\xc2\xe3\x4e\xf5\xf8\xbb\xa9\xb9\x6e\xd4\x8c\x59\xb7\x87\x6a\x82\x5c\x51\xe1\x2d\x78\x41\xb3\xb4\x37\x0a\x44\x0d\x98\xb7\x63\x89\xb9\x2f\xe8\x09\x7a\x42\x55\xa1\xcc\x42\x73\xe3\xfa\x74\xa5\x39\xcf\xc3\x65\x68\x76\xf3\x7a\x38\x5c\x2f\x39\x97\x99\x2f\x3b\x54\x9c\xe7\x9f\x58\xf1\xfc\xf3\x4c\x91\x5e\x72\x0e\x41\xff\xf6\x16\x6e\xa5\x7e\x56\x4d\xfa\x59\x65\x32\x51\x66\xa4\x63\x0a\x9f\x3a\xab\x26\x5a\x15\xef\x11\x13\xbc\x8d\xe0\xfa\x32\x1a\x80\x6c\x35\xc5\x5c\x20\x4d\x92\x55\x5e\xbd\x66\xcd\xd0\xbf\x11\x1a\xe0\x20\x78\xf5\x26\x74\xf8\xcd\x06\xe5\xca\x7d\x8f\xb6\x40\x3b\x3a\xfb\xaf\xc7\x5e\xe0\x67\x8f\x42\xb7\xa2\x75\x27\xd1\xf3\x2f\x67\x05\x37\xf6\x86\x75\x50\x82\x01\x58\x35\x9c\xfa\x42\xda\xfd\x21\x9e\xc2\x39\x37\x28\x19\xcc\xf6\x70\xb6\x70\x32\xa8\x81\x80\x16\x65\x22\xe1\xf8\x61\x38\x99\x47\x81\x40\x53\x48\xb8\x9c\xc9\xe1\xa1\x08\xbf\x1e\x3d\xea\x2a\x8b\x04\x09\x37\x03\xe1\xf7\x17\x2e\x5d\xa6\x62\x3e\xff\x05\x2c\x4a\x21\x8d\x76\x7d\x15\xe1\xb8\x14\x00\x29\x93\xb1\xf6\x64\x9e\xe7\xac\x7e\x32\x98\x6d\x62\x3a\xce\xd3\x7f\x4c\x9b\x9c\x9c\x47\x41\x7f\xf0\xce\xa4\xe6\x69\x72\x78\x18\x3a\x4f\x6d\x9b\x82\x44\x83\x64\xd3\xb2\x49\x6a\xf1\xfd\xd2\x86\x65\x16\x4f\x9e\x77\xf3\xfe\xa2\x4f\xf3\x7c\xbb\xd8\x76\x26\x63\x9e\x04\xa3\xcd\x30\x8b\xf0\x08\x5c\xfe\x4b\x28\x6d\xde\x5f\x42\x69\xf3\xc1\xb0\x62\x02\x9a\xb1\xda\x09\xaf\x2d\x4d\x17\x9b\x81\xdc\xd6\x76\xb5\xc6\x1c\x9b\x82\x70\x33\x8c\x4b\x53\xc8\x52\x1c\x3f\xf6\xc7\x14\xa6\xc7\xad\x3f\x3f\x42\x7c\xf9\x83\xb1\xa4\xa3\x33\xb0\xc7\xf9\x47\xdc\x64\x35\x01\x23\xf1\xd1\x65\x53\x07\x48\x0f\x45\xc2\x36\xb7\xc3\x73\xee\x34\xce\x53\x81\x93\x39\xa9\xab\xba\x2a\xbd\xd1\xe6\x97\x02\xf5\xc8\x80\xc6\x20\x3d\x10\x2d\xfc\x48\xbe\x19\xe4\xe2\xd3\x96\x03\x08\x5a\x2c\x6d\xdd\x91\x58\xe2\x8c\x3a\xf5\x29\x53\xd8\xa1\x24\x9f\x65\x4b\xed\x4b\x5e\x44\xce\x39\x46\xc2\x74\x5c\x34\x91\x9d\x43\x50\x5c\x58\x53\x38\x91\x43\x50\x5c\x72\x32\x50\x5c\xcc\x36\x95\x42\x6c\x66\x8b\x92\x62\xa3\x1c\x98\x14\x99\x28\x18\xf5\xe6\xc2\x74\xa6\x99\xb4\x8f\x13\xbc\x22\xf6\x20\x1a\x04\x97\xbc\xf3\xe9\x01\x79\x4a\x65\x9f\xd1\x13\x26\x2e\x5c\x82\x96\xbc\xc4\xbb\x37\x6d\x42\x37\xed\x4b\xac\xd8\xf3\x81\x7f\xa3\xe7\xd6\xe9\x8b\x6e\xbf\xa9\x2d\x48\xe0\x8c\x34\xfb\x05\x18\x66\x01\x1e\x38\xba\x40\x2a\x74\x76\x85\x54\x28\x66\x64\x8f\xd3\xe5\xb3\x04\xb3\x70\xbc\x46\x06\x4c\xb0\x0b\x85\x70\x8a\x11\x98\xea\x72\x95\x3f\x4c\xed\x3b\x2f\xe9\x6c\x61\x33\xa2\x32\x16\xbb\x17\xdb\xa5\x24\xcc\x49\xcb\x1b\xec\x3e\x55\xb6\x44\x13\x76\xf2\xb9\x76\x9b\x6e\xdf\x11\xe7\xdd\x1d\x97\xed\xd8\xf9\x95\x2d\xc4\xd6\x33\x8a\x24\x42\x21\x75\x4a\xc9\x73\xd8\x2c\x95\x00\x75\x4f\x0a\xc0\x02\x38\x17\x5e\xfe\xcd\x8e\x4b\x5f\x78\xfe\xe3\xff\x1f\x7b\x5f\x1e\x1f\x55\x75\xf6\x7f\xce\xdd\x66\x9f\xb9\xcb\x2c\x99\x6c\x93\xc9\x64\x21\x0c\xc9\x90\x99\x2c\x0c\x61\x97\xcd\x88\x88\x88\x88\xc8\x0e\x45\x44\x01\x51\x11\x2d\x46\xa4\x91\x22\xa2\xa2\x15\x11\x95\x22\x45\x44\x4a\x69\x7a\xef\x64\x88\x11\x50\x59\x8a\x88\xd4\x05\x29\xa0\x62\x6a\xa9\xaf\xd5\x69\xd1\xfa\x5a\xb5\x02\x99\xc3\xef\x73\xcf\xb9\x77\x96\x10\xc4\xf6\xf3\xfe\xde\xed\xf3\xfe\x11\x9c\x4c\x62\xe6\x39\xcf\x79\xee\x39\xcf\xfa\xfd\xa2\xef\x72\xa9\xd7\x93\x11\x2b\x64\xbf\xda\xfc\xc6\x86\x04\x6a\x45\xbf\xa0\x3a\xe0\x64\xf8\xf8\xc4\x0d\xe3\xbe\xf9\xcb\x46\xf4\x0d\xfa\xa2\xef\xc6\x06\x78\x3f\x80\x60\xce\xf9\xd3\x0c\xc3\x1e\x06\xa5\x60\x36\x88\x95\x00\xcc\xfa\x99\x20\x00\x35\x6e\x55\xd8\x32\x5c\x90\xf3\xba\x30\x3d\x8b\x81\x94\xa9\x30\x5c\x80\xd7\x4e\x8e\x0e\x83\xb0\x83\xb1\x08\x6e\x52\xf5\xf4\x8b\x8a\xe4\x54\x2f\x28\xa6\x84\xb8\xa9\x6e\xa1\x15\xda\x9d\x38\x07\x83\x87\xe7\x55\xff\x54\x0b\x06\xf1\x44\x51\x6d\x4d\x49\xba\x6a\x51\x08\x3d\x85\x94\xcb\xc9\x04\x8a\xe6\x4c\xee\x98\xb6\x79\x4b\xbf\x87\x57\x1f\x6e\x81\xf0\xdd\x93\xed\xd1\xdd\x9b\x7e\xf2\x78\x74\xe9\x03\xcf\x6d\x1c\x85\x4e\x7f\x8b\x3a\xab\xe5\x1e\x55\xf7\xce\xbf\x7c\xca\xd8\x9a\xc6\x43\xcf\xfe\xea\x8d\xb1\x1b\x46\xdf\xfa\xa3\x91\x53\x47\x87\xfb\x2d\x7c\x7c\xf6\xab\x1f\x82\xff\x12\x9c\xbf\xff\xcd\x98\x3f\xf0\xfc\x34\xb4\x04\x2e\xc2\x38\x67\x95\x00\x43\x76\xe1\x68\x96\x20\x9c\xc9\xec\x71\xec\xaa\x60\xa0\xb3\x2e\x51\xab\x21\x2b\x6a\xdd\x38\xe2\xca\x59\xb3\x5e\x3a\xd0\x3e\xa5\xef\xdb\xce\xbb\x6f\x63\x5b\xce\x4e\x7f\xed\x78\x1e\x7e\x4e\xa9\xf3\x09\x43\x88\x6d\xc3\xc8\xb4\x71\xad\x72\x08\x48\x05\x15\x86\x65\x2f\xe6\x4c\x31\x27\x08\x54\x94\x93\x4e\xc4\xcd\x01\xc1\x48\x9a\x43\xb0\xf6\x44\x72\xe4\x98\x70\xc5\x43\x3d\x54\xec\xee\x54\x67\xc4\xc0\xb9\xff\x98\x8a\x3b\x23\x8c\x55\x76\x99\xdb\xc3\x2a\x4e\x09\x37\x02\xc8\x1c\xdf\x6a\xe0\x8c\x52\x50\x76\xf3\xad\x2e\xb7\x53\x0a\xc6\x0c\x9c\x31\xa3\x17\xc0\xe5\x76\x62\xc2\x26\xce\xe0\x72\xe3\xf2\xff\x0e\xa3\x53\x7f\xad\x97\xfe\x03\x79\x19\x71\x57\x78\x00\x14\x25\xbf\x40\xe2\x9a\x0a\x28\xf8\xcd\xd0\x0e\x03\xc5\xa5\x7a\x78\x43\xd5\xf4\xef\x7b\x75\x9f\x11\x23\xa9\xf6\xbb\x61\x0e\xf4\xa3\xd3\xe8\x0c\x52\xd0\x33\x7d\xae\xbd\xe6\xa1\x79\xc3\x98\x86\x65\xaf\xec\xd8\xf9\xde\x0c\xea\x69\xef\x2d\x5f\xc1\x03\x14\x9f\x5c\xfb\xf6\x91\xb7\x3b\x58\x27\xba\x2e\xf9\x65\x72\xd1\x8e\xe5\x2b\x7f\xfa\xe3\xd4\x99\x66\x98\xc4\xb6\x01\x11\xe4\x81\xe9\x20\x66\xd7\x74\x25\x69\x80\xb2\x18\xfd\x53\xb0\x43\xd2\x3b\x42\xd3\xc4\xd4\xf3\x53\x33\xfe\x54\x58\x1b\xad\x54\x6d\x5b\x22\x09\x45\x89\xf4\x93\x58\x34\x04\x30\x45\x90\x04\x51\xb1\x78\xf4\x91\x6b\x3f\x46\x02\xd3\x57\x25\x94\xa6\xe3\x35\xea\xf6\x9d\x8b\xf1\x5a\xfe\x8a\x92\xa8\x25\xf9\x30\x5d\xb9\xec\x95\xd6\x9d\xc7\x67\x10\xf4\x50\x75\x09\x47\x4e\x52\xdb\x92\xe3\x37\x60\xf1\x31\x7e\x1d\xbe\x5b\x24\x30\x5e\xab\x93\x9b\x23\xd9\x77\x09\x2f\xa6\xee\x12\x27\xde\x58\x81\xdc\x25\x02\x9e\x0c\x15\xd4\xbb\x44\x14\x52\x5d\x8f\x82\xd6\x21\xe6\xc2\x71\x48\xe6\x0d\xa2\x8d\xee\x13\x9c\x3b\x80\x2c\xf0\xe1\x37\x4f\xb6\x2f\x5e\x8e\x96\xbe\xc4\x8a\x9b\x37\xa3\x79\xbb\x5f\x4c\x7e\x0d\xbf\x5d\x72\x4b\x32\xc0\x8a\xe9\xbb\xe2\x2b\xc3\xed\xc0\x0c\x9c\x29\xa4\x4e\x3d\xfa\x61\x52\x03\x77\x66\x82\xd4\xe9\x4e\x23\x75\x9a\x74\x35\x91\xb1\xf4\xcc\x4b\xa3\x9d\x5a\x7e\x24\xb9\x9c\x5a\xf7\x87\xe4\xcd\x2d\xa9\xbb\x23\xd9\x8f\xfa\x6d\xb2\x6f\x92\xa7\x3e\x49\xe6\x65\x5c\x22\x58\x86\x43\x00\xb0\xd3\x0c\xb7\x03\x81\x20\xac\x82\x0c\x0d\xc9\xc6\x48\x0a\xc5\x4d\xc4\xe3\x15\x78\xe5\x22\x29\xed\xd1\xaa\x28\x9c\x21\x1a\x95\x2d\x42\xab\x51\x10\x3d\x64\x08\x0d\x07\x65\x9a\xa0\x9c\x23\x35\x42\x4f\x19\xb4\x20\x4c\xac\x0f\x40\x29\xe5\x0d\x1d\xda\x6e\x66\x4d\x74\xc9\x9b\xdb\xed\xb4\xa9\xf3\x83\x6b\x52\xfe\x50\x67\xc7\xb5\xe8\xb3\x9e\xcc\xce\xb3\x8d\x74\xde\x1c\xe8\xaa\x38\x37\x30\xed\x1a\xe1\xde\x55\x06\x19\x66\x00\x37\x28\x01\x37\x13\x7b\xc4\xf8\xf8\x80\x08\x2d\x17\x87\x94\x3c\x2e\x11\xcb\x2b\xd6\x21\xdd\x70\x25\xa8\x34\x24\x7b\x8e\x2b\x39\x62\xaa\x01\xc2\x27\x26\x30\xcc\x44\x8e\x47\x10\x63\x52\x89\x3d\x8a\x59\xb2\x5b\x59\xc6\x5d\x8c\x9d\x55\xc9\xae\xd7\x5c\x15\x46\xc0\x79\xa6\x08\x74\x7b\x22\x03\x21\x8c\x40\x7b\xaa\x36\x59\x0f\x23\x24\x55\x83\x49\xd3\xca\x3c\x6f\xc0\x4d\x5e\xd1\x68\xf4\xc1\x29\xfb\x51\xe5\x35\x0f\xfc\xe6\x9e\x85\xe3\x6f\x98\x7d\x73\x73\x7f\x74\x78\xab\xe9\x86\x85\x37\xce\xb4\x6c\x73\xec\x6e\xdf\xf3\x1b\xb6\xad\xf3\x68\x28\x9a\x33\x96\x0e\x9e\xfb\xcb\xce\x6d\x63\x0a\x5b\x2a\x66\xdd\xcf\xfe\x75\xce\xd8\x09\x33\x36\x3d\xf1\x33\x5c\x43\x5e\x8a\xf1\x2b\x2d\x6a\xdc\xa9\x59\x86\xfa\x6c\xc5\x00\xa6\xe7\x03\x66\x53\x30\x1d\x26\x5b\x33\xa1\xf6\xcc\xaa\x1f\xea\xc6\x3e\x1d\xa3\x45\xcc\xd9\xa0\xbb\xaa\x85\x1e\x6c\xa7\x4e\xb6\xa1\x9a\x97\xd9\xb6\xb3\x5f\xb0\xe2\xd9\x46\xb4\x14\x2e\xfb\x4f\xc6\xa9\x26\xf6\xdf\xac\xe5\x7a\x74\xff\xdb\x66\xc9\xf4\x6e\x5d\x5d\xfd\x6f\x1b\x79\x36\x6d\xd8\x8b\xb1\xd1\xa6\xa0\x6c\x23\x19\x1f\x53\x56\xc6\xc7\x14\xd5\x1d\x2a\x2d\xe7\x53\x9e\x3a\x41\xe8\x59\xc9\x71\xef\xc3\x1c\x28\xa1\x4e\xf4\xf5\xd7\xa7\x76\xff\x52\x3e\xba\x1f\x3b\xa8\xaf\x7d\xf0\xde\xef\x37\x2c\x5d\xfd\xd0\x1d\xff\x87\xa1\xfd\x03\x30\xb4\xad\x68\x29\x3b\x11\xdf\xcf\x12\x98\xa6\xe5\x22\xec\x74\x42\x01\x5c\x38\x1c\xb3\x60\x4f\xc2\x62\x33\x05\x65\x63\x98\x84\xc7\x82\x76\xbe\xda\x8e\x2b\x56\x09\x07\xc4\x0e\x98\x42\xe6\x33\xc1\xa0\x62\x94\x48\x66\xc7\xaa\x01\x97\x3a\x84\x18\xcd\xd8\x09\xad\x4a\x7d\xa4\x0e\xdf\x73\xb8\xc1\x31\x00\xfd\x82\x9f\xa3\xac\x0b\xd7\xbc\x27\x51\x9b\x77\xca\x9d\xa2\x0c\x23\xd4\x36\xb4\x43\x7a\x73\x73\x27\xf5\x16\x1c\x79\xf6\x8b\xe4\x49\xb8\x0c\x2d\xa5\x4a\x99\x5b\xce\x24\xe7\xa4\xfb\x3e\xff\x2b\xf0\xb8\x29\x00\xb8\x23\x6c\x1b\x10\x40\x5f\xed\x73\x2d\xf6\x08\x41\xe6\x54\x58\x63\x24\x02\x65\x31\x24\x3b\x8e\xab\x57\xa3\xdd\x86\x47\xe7\x25\x1d\xa8\xb3\x95\x31\xd8\x78\x02\x1f\x89\xa1\x09\x53\xe7\x7d\x40\x80\x14\x35\x2a\x79\xe8\x77\x54\x48\xa1\x42\xbf\x4b\x1e\xa2\x1a\x8f\x26\x0f\x28\xc9\xfd\xd4\x97\xd4\x6b\xf8\xb0\xc7\x5f\x49\xbb\x7a\xe0\xab\x5f\x00\x82\xd1\xe7\x4f\x33\xc3\xd9\xc3\xa0\x5c\xf5\xbb\xcb\x00\xe9\x3b\x8d\x79\x55\x31\x24\x73\x22\x6e\xb5\x94\x79\x6d\x41\xc5\xaa\xda\x72\x0f\x8c\xbb\x1a\xf0\x24\x64\x5e\xb5\xde\x7c\x77\x22\xc6\xe3\xb8\x8a\xb7\x98\x82\x4a\x85\x2a\x1e\x53\x46\xdc\x6d\x8b\xa0\xc0\x00\x01\x31\xf6\x15\x45\xf1\x90\xbf\xdb\x93\x8f\x91\xca\x52\x7e\x77\x06\x22\x15\x66\x45\xf4\x87\x33\x2c\xdc\x5f\x34\x7a\xe6\xc7\x33\x5e\x3b\xf4\xa7\x3f\x1e\x79\xed\xfd\x13\xcf\xae\xb8\xed\xc5\x79\x13\x8e\xc2\x82\x53\x90\x6a\xdb\xbc\xf3\x55\xf4\x06\xfa\x0c\x9d\x69\xd8\x1a\xaa\xfe\xd9\xca\xe6\x15\x4f\x3f\xb6\x64\xee\x92\xba\x11\x4d\xeb\x7e\xfb\xc2\x23\x3b\xbc\x46\x6f\xfc\xb1\x37\x3f\xc1\x3a\xc6\x77\x18\xd6\xf1\xd8\x6e\x6e\x30\xb1\xbb\x1b\x4c\xea\x72\x83\x29\x46\x21\xfa\x43\xaf\xaf\xec\x4b\xab\xbb\xcb\x2a\x75\xaf\xce\x00\x02\xf0\x81\xa6\x0b\xa4\x92\x0b\x42\x8a\x9b\x4b\xc4\xdc\x05\xaa\x5e\xdd\xb9\xd8\xe5\xd6\x9b\x99\x34\x51\x45\x0d\x4d\x41\xd2\xc6\x1a\x09\xa0\xa1\xbe\x00\xbf\x1a\xa6\xd3\xa4\x3d\x4d\x12\x64\x5f\x54\xf6\x8a\x72\x01\xae\x31\x1b\x2f\x79\xff\x66\xdd\x58\xd9\xcb\xc9\xef\x7a\x4b\x5d\x78\x13\xcf\xd0\x6f\x29\xfd\x4c\xf9\x0a\xe3\x7f\x77\xe7\xc1\x58\x32\x3d\x18\xeb\xc5\x3d\x98\x4c\xbf\x25\xdb\x5f\xc1\xcf\xd0\xf9\x04\xf3\x31\xf6\x3f\x1f\xd5\x18\x37\x40\xa4\x35\xcf\x2c\xd8\x71\x51\x43\x36\xf3\x0a\x34\x27\x62\x06\xd5\x96\xad\x34\x81\x4c\x30\xe3\x07\x58\x3d\x86\xb1\x47\xbe\xf8\x1f\xbb\xb1\x47\x6e\xa8\xb2\xcb\xec\x1e\x56\xb1\x16\x9d\xb1\xcb\xf6\x3d\x32\xcb\xb7\x72\xac\x41\x0a\xca\x76\xbe\xd5\x66\xb7\x4a\xc1\x18\xc7\x1a\x32\x3c\x72\x9b\xdd\xaa\x7a\xe4\x31\x1b\xcb\xa9\xfe\x78\xdc\x60\x25\xaf\x34\x6f\x5c\xf3\xc2\xf1\xe1\x14\x10\xfc\x06\x33\xe4\x02\xc5\x54\x4d\xff\xab\x26\xcf\xab\xa7\x8b\xda\x51\xb5\x6f\xe0\x94\x27\x7f\xd2\x48\x3d\xed\x3d\x48\xbd\x02\x5b\xce\x36\xb2\xce\x2f\x90\x13\x8d\x7f\x21\x75\x26\xfd\x8f\xc0\x39\xff\xcf\xc3\xfc\xff\x3f\x7c\xf1\xff\x6a\x7c\xf1\xff\x8e\x35\xa2\xff\xdf\x18\xe4\x38\x9e\x60\xdb\x80\x1b\x54\x5e\x18\x4d\x40\xd9\x13\x22\xf5\xfb\x1f\x18\x0f\x5c\x34\x02\xe8\xce\xe5\xc7\xbe\xe6\xff\xe1\x94\xff\xc7\xe2\x94\xab\xb1\xd3\x7e\xfc\x19\xfd\xb5\x73\x95\x24\x25\x2e\x12\x30\x69\x51\x92\xfa\xa4\x9a\x2d\x41\xc5\x74\x41\xc0\x14\xd1\x03\xa6\x56\x45\x8b\x97\x4e\x27\x3b\x70\xbc\x04\xc1\x66\x3c\xaf\xa5\x9e\xe1\x97\x13\x2c\x3b\x9d\x04\x22\x2e\x70\x38\x49\xad\x3b\xbe\xe9\xcf\xb3\xc1\xa0\x6c\x0a\xe3\xba\xb0\x7a\x98\xdb\xc8\x2d\x0e\x14\x4e\xd0\x52\x3b\x69\x6c\x0c\xfc\xd1\xf8\x96\xde\xdc\x7e\xcf\x43\x53\x95\xe7\xda\xdb\x9f\x78\x7d\xce\x3b\x7f\xa0\x17\x50\x23\x92\x47\xef\x5c\x54\x58\x47\xfd\xf6\x6c\x23\x35\xa1\xb6\x7c\x2f\x39\x93\x0c\xcd\x99\x67\x75\xe6\xba\x15\xd6\x14\xe9\x76\xe5\xe4\x8c\x32\x92\xf1\xbd\x0b\x42\xc5\x88\xba\xf2\x91\xed\x54\xe3\x4e\x6d\xe9\x38\x5c\xd4\xee\x2f\xb4\xd4\xe8\xc1\x31\xd2\xa8\xf4\xe7\x29\x06\x4b\x38\xeb\x13\xf9\xef\xff\x44\xf5\xae\xb0\x5b\x70\x1b\x6a\x2a\x13\x9e\xfe\x70\x4d\xf5\xd1\x5d\x54\x43\xbb\xa2\x64\x88\x40\x76\x80\x02\x3c\x00\xac\x3f\x1d\x43\x5a\xb2\x62\x48\x40\x27\xe2\xb4\xcb\x92\xba\xa3\xdc\x78\x18\xc5\x86\xef\xa8\x98\xc5\x86\x83\x14\x90\x8e\x21\x2f\xec\x1a\x90\x6a\xf5\x08\x32\xe0\x17\x24\xfd\x59\xe0\x29\xcb\xa7\xd0\x0c\x5d\xe8\x1f\x49\x74\xf9\x8b\x9f\xc7\xb6\xfe\xe6\xe0\x11\xd6\xb9\x29\xb9\xf6\xc8\xdb\xef\x7c\xc8\x3a\xcf\x3d\x88\x73\x4f\x38\x86\xe4\x3c\xd8\x37\x92\x80\x07\x5c\xa3\xd9\xbb\x33\xa2\x58\xf4\xcc\x99\x2b\x12\xa7\xa5\xf4\x1d\x9a\xd3\xe5\x0e\x75\x10\xa1\x54\x6d\xa9\x0f\xb6\x47\x67\x31\x95\x2c\xe9\xae\x06\x5d\xbe\x54\x84\x0b\xf1\x9e\x9d\x82\x26\xe8\x44\x67\xce\x7f\xf7\x69\x6c\xcb\xf6\xd7\xde\xa4\x3f\x7a\x49\xbd\x6b\xdf\x7d\xeb\xed\x8e\xf5\x2b\x56\xfe\xf4\xae\xe4\x78\xf5\xe2\xd1\xee\x9c\x9d\x58\xc6\xd4\x9d\x93\x12\x2f\x4e\x8b\x69\xd9\xa4\x2e\xb2\xd9\x35\x85\x91\x3b\x27\x53\x20\x3f\x11\xa8\xd4\x4f\xe0\x68\x0f\xb6\x43\x11\xda\x60\x3e\x3a\x8d\xd0\x09\xe8\x81\xb3\x5f\x7c\xa3\x53\x95\xe5\xd8\xe1\xb7\xfe\xb0\x01\xda\x97\x2f\xc1\xb6\xd4\x5f\xab\x39\xe6\x81\x09\x3a\x66\x09\x9d\x90\x79\x5e\xb6\x61\xfc\x0e\xbd\xfa\xe8\xa5\x13\x71\x97\xd3\x44\xd9\x34\x67\x20\x3f\x24\x4b\xc7\x65\x37\xee\x10\x8a\x49\xf8\xf8\x97\x9c\xa6\x20\x49\x2a\xba\x9c\xa4\xa7\xd4\x2b\xc8\x79\x1a\x78\x01\x93\x6a\x91\x2f\x84\x91\x22\x20\xf9\x6b\xfd\x65\x25\x81\x62\x43\xff\x96\xaf\xde\x87\xd1\x4d\xe8\x71\xf4\xab\x85\xbf\xf9\xd1\xf8\xdf\xcc\x84\x46\x68\x33\x26\xa3\xd4\x01\x27\x3a\x73\xe2\x85\x5f\xb1\x8b\xc6\xcb\x68\xe7\x29\xf4\x20\x9a\x9f\x13\xd8\xe8\x09\xc0\x1c\x68\xd8\xf4\x87\xe4\x68\x92\xc7\x38\x7f\xda\x70\x9a\x7d\x13\x88\xa0\x10\xdc\xa1\xdd\xdb\xb8\x7c\xe5\xd6\x14\x49\x7c\xd3\x7c\xd5\x1a\x05\x9b\x41\xd7\xa8\xaf\x4b\x86\x94\xd7\x32\xa4\x9e\x94\xcf\x6f\xd6\x08\x38\x25\x8c\xac\xeb\x20\x73\xb3\x36\x3c\x86\x43\x0b\x82\x18\x33\xe3\xb9\x5a\x4d\xeb\x62\xda\xcf\xa1\xfd\x02\xcc\x70\x75\x0e\xb6\xc3\x29\x1e\x38\x06\x16\xc2\x30\x9c\x80\xb6\xa3\xb7\xd0\xef\xd1\xaf\xac\x68\x0b\x95\xf7\xc9\xa9\x3f\x25\x3e\xf9\xd3\xc7\x9f\xaa\xfb\x01\x6b\xe1\x28\x74\x1b\xda\x80\x36\xa0\x85\x70\x3e\x1c\x93\x1c\x4f\x75\x74\x75\x7c\x28\x50\x09\x00\x33\x1e\xc7\xfd\x2e\x70\x83\x66\xd1\xa6\x08\x59\xa0\x64\x49\xc4\xad\x3c\x50\x17\x68\xb5\xa4\x48\x1e\xed\x6e\xdc\x4c\x6f\x26\x73\x26\x26\x0d\x8a\xc1\xce\x90\xb4\xbd\x59\x50\x20\xf6\x5a\x79\x2b\x89\xfb\x25\x81\x38\x2f\x10\x17\x6b\x2a\xd4\x68\xd7\x0f\x25\xde\x1f\x51\xaf\xa3\x4a\xf8\xf4\x33\x3f\x83\x02\x14\xe0\xd3\xed\xe8\x14\x5a\x3e\x0e\x2e\x3c\xd6\xf1\x62\x8c\x5a\x1a\x7e\x6b\xc3\x6b\x47\xcf\x36\x52\x53\x92\x9b\x18\x27\xfa\x33\xe5\xbb\x0f\x50\x60\xca\xf9\xd3\xf4\x09\x66\x12\xc8\x05\xa5\x60\x89\x86\x08\x88\x5b\xb8\x0a\x8d\x89\x98\x1d\x02\xdc\xff\x14\xa7\x02\x39\x76\x5b\x50\xa1\xb8\x84\x0e\xa8\x9b\xe7\xd2\x71\x7f\x64\x3a\xac\x08\xb6\x84\x2c\xf0\x8a\xe4\xc0\x43\xe0\xe5\xfa\x54\x03\xc6\x69\xf0\x0b\x31\x7b\x8e\x41\x75\x7b\x24\x51\x76\x45\x81\x42\xe5\x90\x72\x9a\x41\x90\xcd\x51\xd9\x4e\x52\x63\x12\x5f\x5a\xaf\x87\xbf\x3a\xca\xab\x36\x1a\x54\xaf\x0d\xb5\x1b\xec\x70\x0a\xe5\xd8\x79\xcb\xe2\xeb\x9e\x19\x5a\x7f\xcd\x6f\xa7\x1d\xdc\xd7\x1c\x30\x8e\x7d\xee\x9e\x4d\xed\xbb\x6e\x9a\xfa\xe4\xaf\x37\xbd\xfc\x6b\x58\x0d\x47\xf3\x86\xc1\x4d\x8b\x6b\x8a\x56\xf4\x0a\xcb\x7b\x92\xce\xf5\x37\x5e\xbe\xed\xa9\xf1\x93\x9e\x5b\x3b\xd3\x60\x98\xab\xee\xcd\xa2\xf3\xa7\x99\x49\x9c\x0f\x63\xa5\x8d\xd5\xaa\x82\x79\xa6\x84\xec\x0b\x29\xbc\x29\x45\x37\xec\x25\x4c\x9b\x5e\xd2\xf2\x21\xb9\x35\xc6\x61\xaf\x20\xc6\x2c\xbc\x1b\xaf\x45\xd0\x28\x89\x48\x87\xb6\x4d\xb2\xea\xe0\xdb\xf5\x75\xa5\x1e\x03\x67\xb0\x43\xad\x47\x09\x83\xe4\x00\x89\xf7\xe3\x9e\x6c\x3b\x5c\xd4\xf1\xf9\x47\x50\xf2\x2d\xfe\xec\xe1\x47\x1f\x33\xdb\xfa\xee\x9d\xf7\xc6\xbf\xa1\x6f\x4f\xff\x05\x9d\x69\x87\x23\x61\x05\xfa\xfb\xe5\x2b\x17\x50\x8f\xc3\x05\xf0\xe1\x9a\xca\xd0\x06\xa9\xac\xa0\xe8\x93\x0f\xae\x9e\x8e\x3a\xff\x82\xce\xa1\x53\x70\x36\xec\x9f\xfc\x0a\x36\xc1\xb9\xfd\x66\x90\xfa\x77\x0b\x00\xcc\x04\x8c\xdf\xea\x06\xbe\x54\x0e\xce\xa1\xa1\xff\x28\x3e\x53\x22\xee\x71\xe3\x13\xca\x63\x4a\x61\x11\x3a\x6c\x09\xd9\x83\x61\x61\x44\x6d\x3a\x3f\x4f\x43\x44\xc1\x31\x73\x9e\x1a\x19\x18\xf1\x23\xe4\x76\x10\xd0\x3c\x8f\xa0\x18\x8c\xd1\xa8\xec\xcb\x74\x9b\xb5\x04\x05\xa7\x1e\x63\x99\x19\xb8\x80\xbf\x05\x9e\x86\xcf\xdc\xb5\x60\xd5\xd2\x4f\x4e\xa0\xd7\x60\x10\x7a\x1e\x5d\x85\xde\x87\xd2\xe3\x4d\x8b\xef\x42\xbf\x63\x1a\xd1\x5f\xe7\x2e\x70\x9a\xa4\xa5\x37\xaf\xdf\xf2\xd8\xae\x49\x8d\x4f\x5c\x7e\xed\x95\x43\x08\x16\x2d\x3d\x8a\x69\xcc\xcc\xbd\xe1\xe1\x5f\x73\x3a\xf7\x66\xbb\x68\xee\xad\x85\xda\x80\xdc\x4c\xe3\xba\x4e\x72\xde\x94\xa3\x66\xa6\x09\xe3\x1a\x4a\x60\xaa\x9e\x7b\x33\x67\xe7\xde\x4c\x84\xa8\x1e\xc3\x4a\x0a\x86\x74\xee\x4d\x4c\xe7\xde\xa4\x44\xab\x89\x73\x18\xff\xc9\xd4\x5b\x80\xa3\xca\x27\x2c\x5f\xc3\x50\x83\x37\xb6\x24\x99\xed\x50\x84\xdf\x7e\xed\x78\x78\xdd\x4b\xf0\x53\x28\x76\x8e\x4e\xfe\x15\x36\xa1\x66\xca\x45\x97\x74\xa0\xcb\x74\x0c\xc6\x3c\x8c\x9b\x9c\x07\x66\x6b\xf8\x4d\x16\xbd\x83\xd2\x6b\x4c\xc4\x5d\x46\x91\x26\xa8\xd6\x7a\xb1\xc1\xe8\xc2\xd0\xe9\x46\xd2\xfc\xcc\x91\x12\x91\xe2\x36\xe2\xa8\x56\x8c\xe2\x91\x08\xcc\xa1\x05\x14\x8b\x48\x46\x89\x8c\x82\x6c\xc7\xfc\x00\x40\xef\xa4\x14\x0b\xa0\xde\x42\x49\x50\x1a\x49\x43\xe8\x42\xc8\x7d\xf4\xf6\xb7\x49\x9e\x8d\x3f\x3f\x61\xc3\xdc\x1b\x36\xce\xfb\x07\xfa\xf4\x15\x2a\x44\x3d\x78\xef\xb2\xb5\x54\x01\x34\xc2\x28\xfa\xe6\xdf\xe6\xed\xda\xe7\xab\xdc\x50\x5e\x04\x83\xf0\xc7\x4f\x6f\xdc\xa2\xe7\xf1\xd8\xb3\x18\xa7\x51\xcf\xe3\x59\x1d\x91\x08\x59\x06\x87\xfd\x1c\x29\x24\xf3\xc7\x65\x36\x8c\xdb\xc1\x0c\x61\x72\x31\xd2\x40\x10\x5b\x59\xa3\x5d\x20\x79\x3c\x08\xca\xbb\x26\xf2\xe0\x69\xf4\xc6\xea\x03\x70\xf7\x56\xf8\xca\x7e\xd4\x00\x4f\xbf\x89\x4a\xb7\xa2\x52\xaa\x16\xde\xfa\x7c\xf2\xaf\x94\x8b\x7c\x25\x0f\x53\x95\xc9\xa3\xea\x17\xd0\x38\xcf\x57\xe3\x79\x85\xb9\x20\x56\x8c\xfd\x2e\x63\x22\xe6\xd6\xa0\xa8\xe3\x16\x73\xb1\xdb\x16\x54\x2c\x46\x52\xaa\xe4\x8e\xe3\xe9\x46\xbb\xfa\x14\x78\xc5\x44\xcc\x8e\x41\xb6\xed\x16\x13\x6e\x44\x02\x0a\x5d\x4c\x72\x79\xea\x49\xec\x8b\xe2\x91\x98\xbc\x7c\x0c\x24\xa5\xa8\xd7\x8b\xec\x16\x31\xec\x4c\xbd\x3e\x89\x15\x84\xb5\x91\xa2\xda\x1a\x92\xcc\x23\x6d\xfd\xda\xa3\x52\x3c\xf4\xc5\x97\x1f\x5e\xf7\xf4\xb3\x6b\x16\xc3\xfa\x33\x57\x3d\x30\x75\xe0\xaf\x7e\xbf\xf7\x83\xb7\x9a\xee\x3c\x7b\xf2\xab\xc8\xa6\xf1\x53\x26\x4d\xb9\xe1\xf1\xad\xeb\x0b\x7b\xac\x1e\xf5\xf4\x8a\x5d\x7d\x8c\x25\x0f\xdc\xf8\xe4\x76\xa0\xe3\x34\x2f\xc2\xf6\x3c\x32\x83\xaf\x8e\xb4\xf4\xe3\x7a\x6f\x3a\x29\x86\x33\xc5\x22\x2e\xfd\x62\xdd\xca\x2c\x66\x52\xe3\x6c\xd1\x0b\x71\x9b\x1d\x10\xa7\xbc\x06\x42\xd8\xb2\xcd\xc8\x50\xa3\x3a\xb6\xd2\x6c\xb2\x9d\x69\x4c\xce\xd8\xd7\x87\x5e\x77\xae\x8d\x5a\xb1\xea\xfe\xce\xb9\x80\x22\x9f\xcf\xf1\xc0\x06\xf2\xc0\x7d\x17\x48\x20\x7b\x43\x8a\xc8\x25\x62\x22\xd6\x9b\xe8\xc6\x14\xbf\x19\x85\xb1\x56\x3b\xe6\x7d\x70\x64\x09\xd8\xea\x36\x9a\x8c\x5a\xbf\x7b\x48\x71\x6b\x35\x33\x87\x5d\x10\x63\xac\x2d\x2f\x1a\xd5\xe6\x11\x55\xe5\x72\xdf\x27\x39\x9d\x95\xaa\xcb\x5c\xc7\x5d\x59\x89\xba\xae\xab\xe2\xf8\x54\x92\x8e\xe8\x37\xc0\x34\x76\xc9\xd1\xc1\xec\x1c\x9d\xed\x52\x39\xba\x96\x38\x3c\x76\x00\x05\x61\xe7\x11\xc4\x33\x8d\xd8\x2e\xff\x96\x3c\xa8\xdb\xa4\xfd\xfc\x57\xf4\x57\x18\x8f\xb9\x87\x86\x26\x63\x8c\x28\xb4\x21\x81\x3b\xd1\x09\xe6\xb5\x80\x79\x79\x8c\x2e\x1d\x93\x39\xa2\x5a\x94\x96\x3a\xc3\x99\x33\xbb\x2b\x30\xbf\xb9\x94\x5a\xfb\x22\x7a\x39\x7f\xea\x53\x8b\x07\xaf\x30\xc2\x77\xe0\xb9\x73\x6d\x74\x1c\xad\x43\x3f\x7a\x55\xb7\x15\x76\x24\xd3\x08\x5c\x60\xb8\xf6\x1c\x9a\xd5\xe7\x10\xaf\x46\x0d\xd6\x49\x99\x48\x9b\x33\xd0\x93\xa5\x1e\x0d\x53\x52\xa1\x8c\xa9\x04\x19\x6b\x75\xea\xbe\x13\x74\x7b\xea\xea\xb1\xc6\x39\x03\x0c\xc0\x2a\x58\x2e\xb4\x9c\x82\xae\xd2\xca\xc2\x2a\x58\xf8\xd9\xa6\x40\x08\x7d\xf1\x33\xf4\x85\xb3\x5c\x62\x1a\x93\x53\xa6\x6c\x98\x77\x07\xf5\xf2\xb9\x36\x7a\xe5\xbc\xbb\x92\x93\xa8\xad\xbd\x6f\x1b\xd8\xb9\x18\xa4\xec\x98\x60\x3b\x0c\xec\xa2\xe7\x8c\x5c\x99\x39\x91\x09\xec\x90\x9d\x2b\xbb\x20\xf2\x54\x0f\xdd\x96\x38\x35\x2e\x1e\x4f\x6e\x67\x1a\x51\x3d\x3c\x74\xae\x0d\x26\x90\x27\x8d\x6f\xfb\xdf\x15\x8b\x59\xd5\xc5\x68\xa6\xb1\x4b\x7e\x0c\x9f\x96\xe6\x74\x7e\xcc\xf6\x3d\xf9\xb1\x16\x7a\x63\x3c\xf9\x3a\xd3\x78\xae\x8d\x96\x3b\xc7\xa4\xfa\xb0\xf1\x5d\x82\x99\xaf\xb1\x8b\x9d\xa3\x01\x95\x13\x24\xfe\x42\x0d\x40\xb9\x38\x83\x83\x43\xa1\x04\x0c\xc6\x9f\xa7\x95\xed\x03\x1a\x18\x7f\x8c\x71\xf0\x51\xdc\x8d\xad\x18\xf0\xf1\x51\x98\x83\xe9\x37\x1c\x3c\xad\xb7\xe9\x7a\xb2\x3a\xb1\x3d\x5a\x2b\x76\xaa\x96\xd1\xb2\x26\xc7\x38\x68\xeb\xfc\xe3\x9f\x7f\x71\xa2\x63\xb1\x95\x31\xae\xd9\xf2\xe0\x33\xcf\x3c\xf2\xdc\x63\x14\x46\xde\x98\x38\x06\x9d\x40\x5f\xe1\x4e\xec\x8a\xd1\xfd\x51\x7f\x46\xfa\xe8\xe0\x1f\x5f\x3f\x74\xac\xfd\xc0\x7f\xaf\xd9\x11\x3c\x1f\x46\x6f\xc6\x7b\x95\xca\xaf\xa9\x72\x00\x73\x56\x7e\xcd\xf6\xc3\xf2\x6b\x15\xf4\x12\xf4\x54\x8c\x8e\xad\x5b\xd7\x39\x9a\x8e\x91\xbb\x13\x39\x19\x27\xd3\x08\x3c\x20\xa8\xf1\x87\x98\x22\xb2\x1d\x53\x14\xa8\x26\xaa\xc5\xb4\x17\x66\xd7\x24\xb7\xce\x1c\x82\x71\xf9\xf0\x05\x34\x10\x52\x7b\x3f\xbf\x42\x30\x9a\x06\xb9\x3f\xda\x87\xca\x87\xbd\xf2\xd0\x15\x8d\xe1\xe1\xe3\xef\x2a\x8b\x32\x8d\xc9\xd5\xbf\x9b\x5a\x7a\xb8\x3f\xb5\xe0\x5c\x61\xdb\x06\x61\xb5\x75\xea\xcc\x9f\x61\x3f\xf2\x7f\x3f\x9e\x17\x04\xa5\x00\x30\x1e\x7c\xf6\x64\xe6\xd5\xe0\x0f\xcb\xab\x95\xc2\x87\xd1\xf2\x37\x61\x1e\xcc\x39\x8c\x96\xc3\x47\xdf\x44\xc7\xd0\x11\xaa\x9a\xf2\xa2\x19\x70\x43\xf2\xd3\xe4\xdb\xb0\x0d\x35\xe2\x5e\xf8\x66\x26\x81\x3f\x43\xaf\xa1\xd2\x66\x9c\x5f\xca\xec\x49\x80\xd9\x29\x36\x5b\x66\x8a\xad\xd5\x6c\x60\x8c\x41\xc5\x24\x75\x97\x61\x6b\x89\x53\x7d\xe2\xcf\xc8\x4c\xa3\x6a\x37\x9d\xa3\x92\x9f\xc3\x26\x00\xc1\x3a\x00\x98\x28\xf6\xbb\x2e\xd7\xd0\xa8\x34\x5a\x82\x38\xcf\x5a\xd5\x03\x15\x47\x36\x52\xe6\x87\x59\x09\xee\xb3\xc5\x46\x78\xe1\xad\x34\x36\x2c\xa0\xb0\xbc\xce\x7b\x22\x44\x04\x67\x76\x7a\x6d\x5d\xfc\xe8\xa4\xe7\x7f\x14\x8f\xcf\x57\x6e\xd9\xfc\x0a\xd5\x02\xd7\xa3\x5b\x77\xd7\x0f\x80\x27\xd4\xe3\x76\x44\x9f\xed\xa9\xf3\x9d\x5b\x9a\x79\xbe\xeb\xeb\xc7\x8f\x4b\x56\x7e\xcd\xd6\x35\xb3\xa8\x11\x26\x74\x93\x5f\x6b\x89\xc3\xf7\x77\xc0\x93\x71\x6d\xe1\xa3\xe9\xd8\xb9\x36\x7d\xf6\x60\xb9\xa1\x00\xcf\x1e\x8c\x4f\x7f\x1e\xc9\xaf\x69\x1a\xb7\x6b\x1a\xcf\x4e\xb5\x5d\xec\xc3\x5b\xed\x16\xa3\xf1\xfb\x32\x6d\x9a\x28\xb1\x8d\x3b\xd2\xc2\x74\x8e\x4a\xfe\x0d\x2e\xc1\xf7\x4d\x29\x00\x2c\xf1\x23\x44\x70\xb5\x76\xdf\x58\xf4\x68\x0c\x98\x13\x71\x5a\x34\xe1\x3b\x4e\xdb\x12\x93\x7e\xc7\xc5\x4c\x78\xe2\xd2\x04\x4c\x41\x3d\x75\xc4\xd9\x32\x53\x47\x9c\x96\x6b\x53\xe3\xc8\x0a\x28\x48\x5a\xcc\x55\x4a\x89\x30\x04\x5f\x46\x83\x91\x2f\x0e\x43\xd0\x72\xf7\x3a\x74\x82\x8e\xad\x43\xfd\xd1\x21\x24\xd3\xb1\xce\x8f\x76\x4c\x1c\x43\xe2\x44\x76\x95\x26\x97\x3b\x95\x67\x93\x22\x29\xe1\x64\x67\x24\x95\xcb\x32\xa5\x0e\xd7\xf4\xfd\x6b\x4f\xab\x4a\xbd\x24\xdd\x36\xed\xd4\xcd\x4e\x6b\x91\xb6\x46\x3d\x1e\x84\x64\xeb\x0a\x8e\xff\xee\xbd\x77\xd1\x5f\x21\x03\x4d\x8b\x1f\x45\x67\xe9\x45\x71\xa6\x11\xf5\x5f\xff\xcc\x0b\xbf\x7c\x6c\xc7\xf5\xd7\x20\xbb\x7a\x7f\x01\xcd\xc7\x1c\xc7\x34\x66\xd6\x76\x14\xb3\x26\x5e\x96\x6c\x52\x86\x3b\x26\x9b\xbb\x2a\xcb\xac\xb3\x75\x0b\x5a\x98\x9a\x6e\x11\x69\x89\xc3\xe1\x70\xfb\x1f\x8e\xa3\x7d\xb0\x6e\xe9\xca\x7b\x1e\x43\x6f\xab\x92\xa0\x43\x9b\xb7\x3f\x36\xe9\xfa\x09\xe3\xfe\x07\xcf\x84\xb5\x9c\x3f\xcd\x0d\x64\xa6\xe0\xfc\xda\x6d\x59\xf9\xb5\xac\xcb\x3f\xdf\x94\xce\xaf\x99\xd3\xf9\x35\x5b\xd7\xfc\x9a\x2b\x9d\x5f\x73\xa5\xf3\x6b\x6a\x18\xe9\xd5\x5d\x81\x0b\xb3\x6b\xaa\x23\x40\x3c\x23\xaa\xdc\x2f\x64\xba\x01\x2d\x71\xe8\x75\x77\x1e\xf9\x03\xa4\x51\xf2\x4f\xc7\x93\x76\x94\x80\x6f\x3f\xf2\xf3\x9f\x3f\xf4\xc8\x33\x3f\x7f\x44\xf5\xd9\x3e\xf9\x0e\xbd\x85\xce\xa1\xaf\xd0\x51\x68\xf9\x0a\x79\xa8\xf2\x77\x8e\x1f\x7f\xe7\xcd\xa3\x47\xc9\xda\xfc\x00\xd0\x87\x71\xec\x93\x9d\x4f\x83\x84\x17\x22\x95\x4f\x33\xa5\xf3\x69\x52\x56\x3e\xcd\xf6\xcf\xe4\xd3\xea\x22\x7e\x92\x4f\x73\x56\x40\xc1\x5f\xcc\xf9\x61\xf4\xde\x9f\xbc\xf5\x22\x3c\x1d\x47\xdf\xa0\x3f\xbb\xa1\x15\xd2\xe8\xe4\xed\x8b\xe1\x9b\x45\x9b\x16\xaf\xdb\x7e\xae\x0d\xc6\xd1\x28\x9a\xd9\x09\xe7\x4e\xd4\x39\x2c\xf3\x38\x3f\x8e\xe5\x4b\xc1\x9c\x4b\x45\xf3\x65\x17\x89\xe6\xcb\xb5\x68\x3e\x4e\x5b\xc4\x7c\xdc\xaa\xfd\xaf\xc7\xf3\x74\xaa\x95\xf0\xfb\x22\x7b\x5a\x6b\x2c\xbc\x58\x84\x4f\x7d\x9a\x31\x77\xc1\x90\x75\x62\xec\xf0\x3c\x50\x0e\x22\x60\xf9\xf7\xaf\x54\x2e\xc5\x9c\x80\xbe\xae\x9c\x80\xe9\x95\x63\x78\x74\x0f\x9e\x82\xd6\x94\xd0\x5a\xc5\xb9\x8d\x18\x14\x55\xee\x81\xc9\x00\x31\x66\x71\x8f\x62\x41\x6c\xb5\x88\x5e\x1a\xf7\x1f\x1a\x2d\x64\xae\xde\x25\x5c\x5a\x0d\x17\x19\xcc\xf8\x3e\xa5\x70\x17\x0e\x6a\x5c\x54\x3f\xa3\xbb\x9d\xdb\x10\x91\x93\x19\xcd\x39\x41\x39\xf8\x09\xe9\x29\x92\xdd\x21\x25\xcf\x9c\x90\xfd\x21\xc5\x41\xc6\x22\x0d\x11\x05\x1a\x12\x32\x1b\x96\xe9\x10\xee\x2c\x2a\x3f\xae\x86\x99\xaa\xd5\x32\x25\xe1\x70\xcc\x54\x8e\x2f\x06\x83\x29\x18\x2b\xc7\x3d\xf0\xe5\xea\x1d\x61\xd2\x72\x93\x1a\x9e\xbe\xa9\x9c\x24\xea\x0a\x84\x56\xab\xc3\x4d\xc8\xf1\xca\x34\x0e\x04\xbf\xa0\x58\x2d\xd8\x5d\xac\x8d\xd4\x46\x5c\x7e\x97\xdf\xa5\x0d\x50\xba\x5d\x42\x6a\xa4\xa3\x56\x27\xd5\x0a\x08\xe2\xfa\x38\x7c\x10\xdd\x69\x34\x57\xc7\x6f\x7f\xfd\x8d\x47\x1f\x1e\x13\xad\xef\xbb\x6c\x71\xd3\x2f\x9f\x6a\x63\x4e\x2c\x6f\x6f\x5f\x1e\xef\x7f\xc3\xe8\x49\xaf\xbe\xdb\xb9\x73\xe3\x36\xef\x1a\xd7\x36\x7a\xc8\xf2\x65\xbb\x8e\x26\xbf\x64\x4e\x68\x67\x11\x00\xf4\x28\xce\x9f\x3d\xdf\x91\xca\xe4\xf1\xdd\x65\xf2\xba\x9f\xef\xc0\x39\xbd\x1c\xad\x47\x17\xe7\xf6\x98\xf7\x33\xe6\x3b\xfe\xa7\xce\x1d\xcf\x39\x7f\x9a\xbe\x1b\xe7\xa6\x66\x6a\xfd\x03\xb9\x3a\xdc\xa6\xd1\xa8\x03\x68\xc8\x9e\xb0\x62\x11\x71\xe9\x0f\xa3\x84\x48\x64\xec\xa8\x80\xe0\x44\x3a\x5c\x04\x44\x43\xd4\x41\x34\xf0\xf4\xa1\x07\x37\xbb\x00\x4e\xc4\x80\xf4\xfa\x70\x8a\x6a\xeb\x19\x78\x91\x54\x17\xbc\xc8\x2a\x6a\xce\x87\x7b\x76\x3d\xd7\xff\x85\x9f\xde\x7a\xc7\xac\x17\x57\x36\x0f\xf8\xf3\x3b\xef\xdf\xb7\x63\xeb\x03\xf7\x2c\x5e\xf7\xcc\xbd\x0d\x74\xc3\x8a\xf5\x8d\xab\x87\x8f\x18\xd0\xef\xaa\xe1\x91\x09\xf3\xaf\x7c\xfa\x97\xc3\x36\x4f\x98\xd0\x38\x78\x62\xdf\x7e\xd7\xce\x05\x14\xd8\x08\x00\x9e\xa9\xb7\x00\x07\x88\x6a\xde\xa7\xc6\x8e\xa0\xd0\x8c\xbe\xdd\xb2\x35\xac\x70\xf6\x04\x66\x16\x51\xff\x2b\xc0\xa0\xe2\xd0\x33\x28\x5d\x27\x25\x84\x88\xb0\x51\x1f\x99\xb7\xc7\xd9\xdb\xb5\x41\xf9\xb3\xaf\x13\x3f\x81\x3e\x7f\x1a\x00\xaa\x17\xe6\x65\x70\x80\x3c\x70\x59\xf6\xa7\xca\xde\xd4\x14\x47\x9a\x61\x5b\x9b\xe2\xb0\x5a\x82\x3a\x6c\x21\xaf\x1e\xb0\x29\x6e\xed\xae\xac\x0b\x99\xf2\x38\xf5\x33\x60\x5f\xdc\x72\x01\xbf\xc2\xd9\x7d\xaa\x50\xa9\x6f\xc1\x7f\x63\x9c\x01\x0a\xd8\xcf\x7f\xc5\x8d\xc1\x79\xa1\x42\x70\x95\xd6\xc5\xe1\x36\x26\x48\x68\x9d\xca\x43\xf1\xe6\x44\xdc\x58\xe8\xe4\x6c\x41\xc5\x68\x22\x2e\x82\x9d\xd0\x9a\x19\x30\xc8\x49\x6e\x9a\x27\x17\x28\x85\x6e\xad\xb5\x39\x95\xa8\x8a\x10\xf7\x94\x64\xab\x52\x43\x09\xf6\x02\xef\xcd\x0f\x94\x52\x63\x10\xdc\x82\x86\xa3\x69\xe7\x41\xde\xb4\xb5\x77\x5e\x46\xdf\xf7\xf1\xfd\x2b\x9b\xd6\x76\x2c\x37\xc2\x43\x14\xa3\xbb\xac\xe8\x19\x34\xf3\x95\x67\x27\x5d\x7f\xfd\xd5\xe4\x2c\xe1\xb6\x32\x8d\x40\x00\xde\xcc\xb9\x0a\x51\xf7\x5a\xd9\x48\x9c\xe6\xf1\x5c\x45\x4e\x44\x0b\x35\x74\x84\x04\x81\x54\x0d\x05\xec\x1f\xaa\x5e\x8d\x88\x9b\x47\x55\x37\xc7\xa5\xad\x21\x4f\x5d\x03\x2f\xaa\x51\xa9\x2b\x6b\xae\x22\xec\x76\xf1\xda\x58\x45\x11\x5e\x40\x4b\x3b\x3c\xdd\xf6\xed\x87\x6f\xa1\x46\x34\x09\xe5\x50\x1b\x3e\x81\xb6\xa6\x35\xa7\x48\xbe\x09\x35\x3c\xf3\x34\x92\x61\x02\x79\x1e\x53\x9d\x6d\x72\xee\x03\xc0\x8c\xc2\x9c\x9c\x8b\x08\x46\x9b\x2c\x45\xd4\x38\xbe\xdb\x33\xdf\x17\x92\x0b\xf0\x99\x9f\xaf\x9e\xf9\xc6\x70\x38\x96\x8f\x9b\x1e\xf3\xd5\x33\xbf\x00\xf7\x95\x16\xa8\x67\x7e\x3e\x09\xb2\x25\x8d\xa9\x21\xbf\x40\x67\xdc\x52\xac\xd8\x35\xc0\x4c\x96\x17\x3f\xea\x03\xd9\x27\x7c\x0c\x8d\x36\x5b\x6b\x5f\xbc\xe5\xe0\xa1\xd8\xe2\xa5\xbf\x7c\x2a\xce\x1c\x5b\xd1\xde\xbe\x22\x36\x61\xd0\xb5\xd7\xee\x7d\x37\x39\x85\x5a\xbb\xbc\xf9\xa5\x63\xc9\x2f\x99\x63\xba\x6f\x1e\xe0\xfc\x17\xcc\x61\xc0\xec\x39\x0c\xdb\x0f\x9f\xc3\xc8\xcc\x95\x4e\x4b\x9d\xf1\x99\x39\xd3\x8c\xc3\x5e\xbf\x57\x98\x45\x9c\x1f\xd8\x80\x47\xc7\x3d\xc8\xca\x82\xe7\x74\x97\x05\xf7\x66\x65\xc1\x5b\x39\x9b\x5d\x22\xf3\xe6\x17\x4d\x27\xa7\xdc\xa5\xcc\x54\x72\x0f\xcd\x3d\xba\x20\x89\x6c\x4d\xcf\x5c\xe0\x1c\x0e\xc7\x03\x0f\x28\x05\xb7\x76\xcd\xe2\xc8\x81\x90\x92\xcf\x25\x62\xf9\x01\xbc\xb3\x45\x26\x42\xc4\x5e\x16\x92\x73\x8e\x2b\x5e\x11\xcf\xf2\xf9\x60\x50\x29\x12\xb5\x59\xbe\x1c\x41\x6c\xb5\x4b\xa5\x50\x3d\xca\x7d\x42\x2b\xcb\x78\x30\xc5\x67\x91\x28\x9b\xba\x1f\xbc\xe8\x3e\x15\x94\x3d\x7a\x71\xb1\xc4\x10\x7a\xb7\x6b\xaa\xfc\xc2\x3c\x11\xe7\xcc\xcc\x97\xa3\xe5\xcc\x58\x1c\xe7\x67\xce\x5e\x98\x13\x97\xce\x73\xe0\xd9\x0b\xe9\x12\xb3\x17\x2d\x71\xaa\x5f\x1c\xad\xd2\x32\x1d\xe7\xda\xd0\x72\x48\x7a\x20\x9a\xcf\x9f\x36\x6c\x62\x0f\x81\x30\x58\x06\x62\xbd\xd5\xcf\xad\x88\x28\x0e\x4b\x42\xf6\x84\x71\xff\xa3\x1c\x88\x28\x26\x3a\x21\x17\x84\xa1\x1c\xe9\xda\x05\xe9\x72\xe1\x94\xb7\x7a\x82\x95\x79\x12\x4a\x8d\xd6\x10\x19\xa3\xd9\xde\xa4\xdc\xa0\xf4\xaa\x8c\x46\xe5\x5c\x31\xe6\x0f\x54\x60\xec\x09\x47\x6f\x41\x94\x7b\xa9\x96\x13\x07\x9c\x54\x54\x46\xee\x55\x85\xf5\xa7\x52\xc1\x84\x13\x96\xc2\xc3\xfe\x38\x5b\xe2\xd6\xb3\xa1\xa4\xf6\x43\x82\x3a\x02\xf7\x59\x04\x9a\x21\x9d\x58\x7f\x4f\x63\xaf\x29\xfd\x7e\xf6\x8b\xc3\x3b\x07\xdc\x53\xfd\xd2\x8c\x55\x2f\xfd\xee\xb9\x47\xfb\x4d\xed\x75\xf9\xbd\x4f\x27\x20\x8b\x4e\xa1\xce\x3b\x5a\xae\xe0\x2e\xdf\x76\x3b\x3a\x8b\x3e\xa6\x10\xbc\x06\xde\x35\x6e\x5d\x41\x10\x7d\x88\xce\xa1\xf7\x51\x5b\x79\x29\xdc\x8f\xfa\x8f\x82\xc3\x60\x2f\x68\x84\xfe\x60\xc1\xba\x71\xe8\x41\xf4\x2b\xf4\x30\x9a\x1e\x0e\x87\xc3\xf0\xe7\xe4\xfc\x01\x00\x70\x95\x4c\x23\x28\x06\x0d\x1a\xae\x92\x3f\x82\xdd\x23\x80\x43\x59\x77\x24\x82\x6b\xdd\xee\xe3\x8a\x87\x20\x27\x01\x45\xcc\x15\x44\xec\x4d\xa8\x46\x65\x2c\x8c\x62\x92\x01\x4f\x2e\xf4\x44\xea\xea\xeb\xea\xe9\x6c\x76\x48\xba\xac\x9c\x73\xc0\xc0\xce\x09\xb3\xe6\xba\x8d\x05\x57\x4c\xcf\xdf\xb2\xff\x90\xb5\xa8\x28\xcf\x60\xdc\xb2\x26\x7e\xe0\xfd\x57\x9a\x0a\xcc\xc5\x8b\xea\x3e\x62\x1a\xbf\x43\x9f\xa1\x1d\xb7\x8c\x5f\xff\xc6\x20\x78\x38\xd9\x52\x3a\x7d\xe6\xf5\x85\x71\xf8\x1b\x78\x15\x7a\x0c\x71\xa7\xe0\x98\x2b\xca\x6e\x4a\x2c\x00\x14\x3e\x2f\x3b\x71\x7f\x7a\x2e\x98\xaf\x71\x47\x8b\x5a\x4f\x6b\xdc\x94\xcb\xab\x9e\x9c\x89\x4e\xc4\x21\x50\x5f\xe2\xf3\xd3\xa2\x9e\x9f\xd8\xb5\xe3\xf1\xe1\x29\xba\xb4\xc3\x53\xe4\x71\x15\x4a\x3d\x3c\x79\x3c\xa0\xc6\x6b\xd4\x85\x6a\x60\x61\x75\x27\x88\xd7\x97\x2b\xe2\xf1\x12\x9c\x54\xd1\x8e\xca\x48\x91\x80\xa7\xe9\x52\x5d\x4c\x22\xec\xbb\x13\x6e\x40\x33\xf6\x52\xb5\xe8\x4b\x74\x06\xdd\xb8\xf3\xf0\x9e\xed\xed\x47\xb7\x33\xb5\xeb\x3f\xf9\x64\x7d\x02\x4d\xfb\xfd\x7b\x4c\x6d\xe7\x8d\x2b\x56\xae\x5c\xa4\xad\x61\x0b\x5b\x8e\xd7\x70\x9b\xbe\x86\xf4\x45\xa5\x00\x13\xc9\x84\x61\xf7\x13\xd2\xa6\x60\x3c\xd7\xc4\xa7\x60\xd3\xd2\xeb\xb0\xfd\xa0\x75\xd8\x2e\x5c\x87\x76\xe4\x6b\x59\x0f\xbf\x20\xe9\x79\x0f\xf1\xcb\x18\x9c\x88\xb6\xc0\x5a\xf8\xf2\xa9\x3f\xa2\x82\x18\xac\x78\x60\xf5\x7d\xcf\xa0\x93\x74\x7c\x6d\x47\xc7\x5a\x74\x04\x1d\x7e\xfe\x57\x74\xbc\xb3\x03\x5f\xba\xa4\x6f\xed\xfc\x69\x43\x29\x7b\x18\xf8\xc1\xdd\x9a\x07\x8f\x69\xa5\xdd\x74\x66\xb7\x8e\x8d\x4e\xc4\x79\x29\xdf\x60\x0b\xca\xbe\x08\x6e\x46\xa2\xc3\x7a\x61\xc1\x4f\x6e\x5f\x3f\x3e\xd5\xf4\x9e\x1d\x3e\x1c\x93\x7c\xb8\x01\x49\x34\x05\x71\x95\x41\xf2\x09\xa2\x5c\x18\x25\x2c\xaf\x4a\x8e\x37\x1a\x55\x6c\xbc\x40\x80\x9a\xb5\x96\x9d\x52\xed\x19\xe3\xd2\xb3\xd5\xf8\x59\xa2\xfd\xc2\xc1\x76\x38\xbe\x08\x2e\x80\xe1\x0f\x76\x34\xde\xf4\xf3\xe1\x1d\xe7\x0b\xa8\x78\x72\x84\x19\x72\xa7\xd7\x1f\x98\xfc\xeb\x85\x68\x2f\x7a\xde\x8c\x64\xdc\xb9\x13\x82\xa3\xa9\x29\xeb\x23\xa5\x5f\x27\x36\xa2\x6f\xd0\x69\xdc\x39\x3b\x0f\x5e\x4d\x7a\xaa\x21\x68\x39\x7f\x9a\xdd\x8a\xf1\xba\xb2\xd6\xeb\x32\x67\x66\x4f\xac\xe6\x44\x9c\x2e\xc2\xeb\x15\x88\xb7\xe1\x48\xaf\xd7\xd6\x65\xbd\xa2\x4b\xfd\x71\x4c\xc4\xeb\x15\x05\x6d\xbd\xa2\xbe\xde\xa2\xd4\x7a\x71\xf2\x35\xb5\xde\xba\xd4\xf0\x75\x46\xa4\x81\xe3\xd8\x72\xbf\xd0\x12\x87\x79\x39\xd0\x72\xea\xb9\xfb\x6b\xef\xbb\xed\xe7\xcf\xf2\x94\x2d\xf9\xef\xa6\xcd\xcf\x5e\xff\xd3\x7e\xfd\xef\x9b\xf2\x39\xfa\xd6\x86\x3e\x55\x5d\x92\xcf\xbe\x69\x58\x53\xb3\x61\xf3\xba\xb6\x96\x52\xef\x7a\x5f\x3e\x34\x7e\x83\x3c\xda\xdc\xda\x62\xdc\xfb\x28\x82\x41\x7a\xb6\xd4\xa0\x75\xd3\xc7\xad\xb8\xf8\xa6\xda\xa9\x55\xeb\x9f\x36\x1e\xc7\x4c\x41\x98\xf0\xd1\xa8\x25\x88\xa1\x15\xbf\xd0\x66\xd9\x60\x40\x08\x08\x01\x13\xf4\x97\x97\x95\xdb\x21\x35\x23\x46\xcd\xdc\x8f\xfe\xf2\xe8\xd6\xd5\xe8\x53\x78\x3d\xbc\x7c\x4c\xdf\x7c\x73\x15\xdb\x76\xb6\x91\xda\x9c\x9c\xa4\x7e\xd1\x43\x5e\x5b\x3b\xab\x7c\x25\xa0\x70\x8f\xeb\x4a\x7c\x7f\x88\x60\x40\x96\x2c\xd8\x07\xe5\x12\x71\xab\x29\x25\x8f\xa9\x5b\x79\xc8\x1c\x4a\xef\xea\x08\x9e\xaa\xc3\x92\xd0\xd0\x8f\x4f\x5a\x23\x3c\xd2\x01\x8f\xb6\x1f\xbe\x65\xd3\xc2\xd7\x20\x80\xf6\x99\x45\x46\x4b\x8e\xea\xa9\xc3\x53\xc8\xa7\x7e\x51\x8b\xbe\xb9\x31\x30\x54\x9b\xdb\x5d\x80\x7b\x53\x73\xc1\x34\x6d\xe7\x0d\x16\x47\x24\x92\xd1\xc1\x4f\x32\x8f\x26\x5b\x84\x4c\xee\x3a\xc3\x7a\x3c\x29\x11\x1b\x97\x34\x66\x07\x91\x00\x78\x5b\x25\xd5\xb3\x70\xe2\x99\x19\x0c\x0d\x0c\xd5\x0d\xce\xd1\x37\x38\xad\x37\x18\x80\x7e\x01\xeb\x8e\x33\x1c\x6c\x87\xef\x43\x2a\x4e\x4d\x3f\x84\xfe\xba\x6a\xcb\xc3\x28\xf1\x5b\x98\x8f\x6e\xa6\x1e\x87\x03\x1a\xfb\xe5\x78\x06\x67\x0e\x01\xe8\x5f\x74\xe3\x6f\xd7\x4d\x9a\xb2\x29\xe5\x1b\x71\xd5\x98\x7f\x3e\x4f\x8d\x86\x33\xd7\xc1\xaa\xc7\x0f\x8c\x28\x5e\x2e\xa1\xae\x85\x4d\xad\xc5\x44\xd6\x42\x42\x24\x49\xea\xba\x96\x82\x2e\x6b\xc1\xd6\xaa\xdf\xd3\x52\x5a\xe7\x01\x49\x5b\x45\x80\x33\xb4\xc8\x70\xe6\xbe\x0e\x78\xa4\xed\xcd\x5b\x36\xdd\xfc\x66\xfb\xdb\xe8\x23\xca\x0a\x2d\x7d\x03\xc5\xc6\x1e\x25\x4c\x23\xaa\x85\x87\x49\x71\x56\xff\xa2\x9a\x1e\xbb\x7e\xee\x7d\xd7\x90\x35\x78\x00\x60\x77\xb3\x6d\x18\xff\xf3\x23\xb2\x86\x56\x07\xef\xf1\x95\x78\xb4\xe6\xb9\x22\x3a\xd5\xa1\xe5\xf3\x60\x44\xd6\x1c\xd2\xf2\x29\x7b\x48\x44\xe7\x20\x9d\x5a\x18\x7b\x7f\xfc\xe7\x2f\x11\x38\x72\xc0\xcb\x70\x8f\xec\xe3\xe5\xc2\x3d\x3b\xf7\xb5\x7c\xfe\x6b\xf2\x2e\xcf\xcb\xc2\x1e\xd9\xc1\xcb\xb6\x3d\xb2\x8d\x6f\xb5\xdb\x1c\x52\x30\x66\xb7\x39\xd2\x93\x2d\x20\x0e\x85\x42\x9b\x9d\xa0\xcc\x67\xbc\xc6\x38\xe6\xbe\xd4\x60\x54\x8e\xa0\xb0\x45\xd1\xa8\xec\x11\x65\x3f\xee\x08\x31\x17\x47\xa3\xb2\x43\x9f\x62\x54\x9f\xf3\x38\x6b\x76\x79\x71\xbc\x6e\x10\x14\x8e\xb8\xc4\xd2\x00\xaa\x1e\xd6\xfa\x5d\xb0\x90\x12\xa5\x00\x5d\x45\x69\x88\x8f\x76\x68\xa0\x25\x13\xf4\xac\xa8\x9a\xf1\xe4\x6d\xe8\x46\xe6\x29\x34\xf5\xf6\xa7\x66\x4f\xbe\x6e\xf7\x8a\xa2\x21\x33\xc7\xe6\xbf\x94\x7b\xf5\xf4\x81\xc5\xcb\x37\xc2\xf9\x70\x01\x3c\xf0\xcc\xea\x2b\x8d\xf0\xaf\x2b\x56\x20\x97\xe1\xca\x27\xd0\xeb\xa8\x03\xee\xbd\x69\x7a\x30\xd9\x48\xb5\x55\x4c\x5e\x80\x06\xb2\x3c\x1a\x09\xdb\xc9\x2c\x22\x00\xac\x9d\x69\x04\x45\x20\x00\x86\xea\x93\x9a\x39\x11\x2d\x8b\xea\xd7\x70\x3b\xbd\x78\xf8\x17\x27\x1a\x72\xbc\x82\x28\x17\x47\x81\xe2\x27\x0b\x70\xe7\x16\x5f\x6c\x01\xb4\xa7\x9b\x05\x58\x97\xd5\x8d\x5e\x78\x3d\x8a\xd3\x9d\x28\x7e\xcd\x2d\x23\x43\x39\xcb\xe2\xcb\xfc\xf5\x57\x0d\xb7\x6c\xb1\x0f\xb9\xaa\x3e\x70\xff\x0e\x98\x0b\xf3\xe0\x98\x07\x67\x44\xcd\x70\xc6\x4d\x37\xa1\x0d\xc6\xf0\xe8\x9b\x06\x20\x19\x8e\xba\x76\x68\x41\x12\x51\x54\xfe\x90\x09\x28\x4e\xb7\xa1\xc3\xb0\x56\x7b\x4e\x8f\xb1\x6d\xa0\x04\x94\x43\x2f\x91\x3f\x6e\x77\xb8\x0b\x0a\x55\xe3\xc0\xd8\x07\x30\xa2\x94\xd2\x89\x38\xe3\x05\x9c\x2d\x28\x17\x47\x48\xb6\x89\x70\x51\x96\x90\x07\xb5\x84\x4c\xd4\xbb\x5d\x09\x35\x90\x75\xc0\xa0\x62\x27\xe9\x33\x6c\x30\x93\x3f\x3f\x8a\x07\xa0\x0a\xab\xec\xb2\x7f\x0f\xab\x14\xf8\xcf\xd8\xe5\xfc\x3d\x3b\xf7\xbd\xfc\xf9\xdd\xc4\x66\x1c\xbc\xcc\xef\x91\xed\xaa\xcd\xec\xec\xf7\xfb\xd3\xb9\xc0\x15\xb4\xc8\x85\x7c\xab\xaf\xd0\x2f\x05\x5b\x8b\xd4\x7f\x63\xbe\x42\x7f\xda\x84\xe4\xa2\x28\xd8\x61\xe3\xf3\x7d\x45\x7e\x9d\xad\xc0\xc6\xe7\x17\x14\xa6\xbe\xd7\xac\xc9\x53\x22\x88\x71\x86\xe5\x8a\x4b\x55\x1d\xbb\x05\xb9\x8c\x58\x50\x79\x34\x2a\xdb\x05\xad\x17\xcf\xab\x9a\x9c\x33\x27\x1a\x95\x19\x21\x66\x32\xbb\xa2\x18\x6d\x5d\xfd\x55\x4e\x50\x58\x63\x2a\x7e\xd5\xac\x2a\x6b\x53\x38\x03\x1d\xa8\x17\xeb\xea\xfd\x82\x89\x3a\xd8\x4e\x1d\x44\xf3\x99\xa7\xd1\xb4\xdb\x9f\x9a\x55\xb5\xb2\x6d\x65\xc9\x90\x1f\x8d\xf7\xec\x74\xdd\x7b\x7b\x70\xf9\xde\xf2\x1b\xae\x0e\xa0\x49\x94\x13\x2e\x80\xf3\xf0\xbd\xf9\xf1\x8a\x15\x48\x32\x5c\xf9\xc8\x33\xa8\x01\xee\x9d\x3f\xb9\x47\x72\x14\x15\x9f\xf1\x18\x1a\x78\x1f\x6c\x78\xa3\x34\x39\x9e\xe5\xd1\x70\xb8\x33\x7d\x06\xbd\xc2\x34\x82\x52\xd0\x43\x47\xe2\x89\x39\x3c\x3e\xf5\x0c\xe2\xb4\x33\xa8\xcc\x94\x88\xd3\x25\xea\x0e\xe1\xe3\xa7\x3c\xac\x46\x04\xb9\x5c\x42\x76\x11\x0a\x25\x70\x5c\x29\x25\x07\x51\xa9\xf6\x70\x8b\x09\x4c\x92\x94\x53\x2a\x88\xad\x0c\xcb\x61\x0f\xdc\x23\xc8\xe5\x51\xa0\xd0\xb9\x78\x8c\x59\xe1\xca\xd4\x43\xaa\xab\x02\x2e\xb4\xca\x80\x44\x14\xd0\x22\x53\x41\xd4\x46\x77\xa2\x1d\xd7\xdc\xac\x19\x66\x9f\xab\x2f\xb3\x3c\x6f\x19\x7a\x75\x9f\xe2\xe6\xd6\x65\x95\xa5\xe8\x6d\x78\x40\xb5\x4f\x1c\xdf\x4f\xbb\xe9\x26\xb4\xde\x58\x3d\x7a\x0e\xb6\xce\x71\x43\xf3\x11\xa0\x40\xfe\x90\xf1\x28\x0e\xc7\xdc\xd1\x03\x39\xe9\x36\x74\x04\x86\x00\x04\xfd\x51\x23\x33\x84\x3b\x0a\xae\x00\x32\x88\xd5\xea\xb5\x23\xa8\x3a\xdf\x97\x87\xe4\x61\x11\xa5\x9f\x25\x21\x0f\x0a\xcb\xa6\x90\x62\x36\x27\xe4\xd2\x90\x52\xc4\x25\xa0\x3c\x0a\x2f\x3b\xea\x4e\xc8\x51\x5e\xe1\x60\x50\x09\x7b\xb4\x56\xb4\xa0\x3b\x11\xb3\x07\x71\x2b\x9a\xc9\x14\x54\xae\x84\x41\x25\x0a\x04\xb1\xd5\xe9\xf2\xe6\xaa\x7a\xb0\x0b\x83\x6c\x0c\x2d\x78\xf2\x8a\x7a\x54\x85\x6a\x07\x0d\xbb\x1c\x17\x0a\x30\xf4\x74\x50\x68\x2d\x0e\x0c\xb9\x0c\x87\xba\xb5\xfd\x70\x2d\x4a\x31\xa9\xf7\x50\x18\xd7\x3f\xaa\x42\xd8\x78\x62\x9e\x82\x20\xae\xdf\x78\x6a\xea\xea\x07\xc0\x5a\xde\x1f\xc8\x9a\x43\xad\x2f\x2b\xaf\x8d\xb8\x3d\x69\x96\x31\x03\xee\x62\xd3\x06\x53\x59\x1d\xb6\xba\x4e\xfb\xb1\x81\x0b\x14\x97\xf5\xff\x30\x71\x60\x27\xea\xff\xce\xeb\x27\x4e\x3c\xfb\xc0\xbc\xfd\x33\x27\xbe\xb0\x37\xb2\xbd\x79\x52\xf3\xe4\xe6\xc1\xf5\xbd\x7d\xe5\xbd\x16\xf4\xfe\xf5\x6f\x5f\xdd\xba\xeb\x30\xfa\x08\x7d\x32\xed\xce\xba\x71\x13\xa6\xdd\x75\xd7\xe0\xa7\x86\x0e\xff\xc5\x90\x5b\xe6\xcd\x69\x7b\x71\x79\x73\xb3\x99\x6b\x7e\x04\x72\x78\x94\xb5\xdf\xe0\xa6\xdb\xf2\xfb\xee\xc8\x6b\x78\x60\xd1\x78\xfb\x22\xeb\xd8\x11\x9e\x57\x1e\x79\xe4\x45\xaf\x31\x27\xfe\xc8\xdb\xef\x19\xe8\xbc\xaa\xca\xda\xb0\x81\x2b\x6f\x89\xb0\xec\x4f\x08\xbf\x39\xba\x9d\x5e\xcd\x8e\x01\xc3\xc1\x4b\x20\x16\xd6\xfb\xfe\xf0\x1e\x0c\x0d\x29\x7d\x4c\x09\xb9\x21\x2c\x9b\x43\x8a\xc5\x88\x23\xf2\x42\x75\x03\x46\xe0\x0d\xa8\x15\x13\x72\x2d\xd9\x80\x90\xde\x0b\x58\x21\x26\xe4\xa2\x70\xac\x02\xf7\x8b\x56\x0c\x30\x05\x63\xf6\x8a\x54\x67\xe0\x48\x18\x54\x6a\xd5\xed\x10\x25\x4f\x8e\xb6\x1d\x56\x86\xe6\x5d\xde\xbc\xb2\x60\xaf\x70\x9f\xa1\x64\x37\x94\x86\xc1\xd1\xa8\x5c\x21\x28\x85\x01\xf5\x29\x0e\xf7\x21\x9b\x61\xa6\x09\xb3\xbd\x45\x50\x82\xbd\xa2\x51\x39\x20\xc6\x5c\x79\x15\x99\x9b\x91\xd1\x46\x78\xd1\xad\xd0\xda\x0a\x0d\x1a\x79\x09\xde\x88\x2a\x18\xc0\x1b\xe1\xdd\xbb\xfb\x85\x8d\xeb\x7f\xf1\xe8\x62\x58\x7f\xe6\xe1\x5f\x0e\xbc\xff\xce\x9b\xc7\x37\x8f\x7c\xf8\xfa\x07\x86\xf4\xed\x99\x13\x0c\xfd\xa8\xf2\xc7\x0f\xbd\xfb\x93\x45\xe7\xfe\xd4\x7c\xfb\x95\xd7\xcd\x7f\xe5\x8a\x25\x15\x79\x13\x83\xca\x6d\x73\x9f\xd8\xd8\xf4\xe3\xfb\x18\x6a\xf2\x0d\xd3\xae\x7b\x7c\xeb\xfa\xe1\xab\xeb\xf8\xe6\xb1\x79\xe1\x55\xb7\x5e\x6b\x5f\x64\xbe\xb2\x5f\xfe\x83\x37\xef\xea\x63\x2c\xfd\xe9\xac\xa7\xb6\x50\x74\x55\xbf\x70\x4f\x73\xc5\x93\x1e\x27\xcb\x2d\x51\x75\x3f\x0f\x00\x8e\x62\xdb\x40\x1e\xb8\x8a\x74\x56\x93\x09\x13\x83\x2d\x12\x89\xe7\xb0\x6e\xd5\x9b\x33\x45\x94\x1c\x4b\x22\x23\x33\xab\xcd\xbc\xb8\x61\x50\xe6\x30\x2b\x81\x6c\xc4\x48\x3a\x56\xed\x36\x2f\xd0\xc8\x7b\x22\x02\xef\x27\x93\x1c\x5e\x18\x11\x9c\x1c\xa3\x3d\xd7\x25\x65\xf3\xda\xe1\xfa\xdc\x78\x01\x7c\x7a\xf7\x23\x28\xd9\x1a\x8a\x57\xee\x44\xe7\x7f\x4a\x1f\x85\x1f\x23\x3f\x6a\xa6\x27\x75\x6e\x86\x77\xc3\x8f\x91\x6f\xcb\x3f\xee\x41\x43\xe1\xee\xe6\x2f\x35\x1e\xef\xff\x15\xdc\xcc\xff\xd3\xb1\x63\xe9\x8c\xfe\x3c\x11\xe4\xa4\xe5\xcf\xe8\xd0\x8b\x4b\x36\x22\xbf\x29\x85\xd3\x65\x73\x61\xf9\x6d\x69\xf9\xdd\x84\x81\x4c\x4c\xb7\xec\xe1\xee\xbd\xee\x5a\xf6\x44\x7f\xb8\xae\xbe\xd4\x4f\xf9\x8b\xb9\xec\x9e\x3d\x11\xf6\x5e\xbf\xce\x92\x5c\x46\x2d\x2d\x44\x1f\xae\x7b\xf2\x82\xd6\xbd\xf9\x68\x5d\xbb\xbc\x16\x8e\xdc\xa2\xe5\x57\xd8\xb1\x98\x53\x73\x1a\xa9\xe1\xc8\xce\x08\x01\xd6\x07\x11\x85\x27\xb4\x9a\x18\x20\x5c\xf5\x2c\xa6\x7e\xfe\x01\xf6\x2c\x9c\x55\x76\x59\xda\xa3\x70\xde\x33\xb2\x61\x0f\x88\x71\x06\x49\x75\x09\x5a\x39\x83\xe4\x4c\xa3\x17\xf1\x2e\x41\x54\xec\x4c\x54\xeb\x17\xc0\x4c\x8f\x6e\x4f\x5d\xbd\x84\x01\xf7\xc9\xa3\x0f\x03\x7b\xe1\x95\xc3\xfd\x05\xc3\x36\x37\x8c\x9b\x7f\x7d\xcf\xeb\xfa\x54\xf5\x1f\x5d\x83\xe2\x47\xd9\xb6\xce\x09\x7b\x1f\x5b\xf5\x07\x8a\x7b\x65\xdd\x10\xd7\x93\xce\x39\xdb\xce\x7d\x9a\xca\x07\x31\xa3\x98\x71\xc0\x0d\x26\x64\xc8\x0b\x35\x79\x0d\x09\x7d\x84\x13\xcb\x3b\xed\xf3\x93\x99\xf2\x1a\x2c\x67\x64\xe3\x1e\x10\x33\x18\x89\xbc\x06\x63\x57\x79\x71\xf9\x1c\xcb\x19\x51\x05\x4d\x9f\x51\x74\x80\xda\x0d\xd9\x21\x26\xa3\xcf\xbf\xba\x6e\xc1\xad\x65\x55\x05\x15\x55\xd1\xfc\xce\xbf\x3d\xc4\x34\x26\x2b\x5e\xad\x7d\x7e\x2a\x7c\xf5\x85\x9b\xad\x0f\x59\xc6\x8e\xef\x3c\x05\x6f\x23\xbc\x9a\xec\x58\xc3\xed\xc0\x05\x7c\xa0\x02\x3c\x74\x11\xdd\xf6\x24\x38\x35\x04\x44\xdf\x4f\x2a\xc7\x4a\xf0\x9f\xd7\x36\xc6\xb5\x91\x21\x2e\x91\xba\x0a\xa2\x51\xb9\x58\x8c\x31\x79\xf9\x38\xf5\xf7\xc3\xf6\x21\x8d\x5a\x58\x9a\x7a\xd5\xfd\xde\xa0\x6d\x07\xf3\x67\x56\xcf\x1e\xfc\x1b\x38\xf2\x35\xf5\x45\x3f\xb9\xbb\xdd\x32\x4c\x71\xf5\x6f\x19\xea\xad\x79\xbd\x1e\xff\xb7\xf7\x41\x8d\x6b\x74\x14\xe7\x07\x6e\x50\x04\x7a\x82\xfb\x2f\xb2\x7f\x41\x92\x49\xf6\xe0\x4c\x72\x31\x0c\x2a\x01\x4f\x42\xe9\xf5\xcf\xef\x28\xce\x3c\xab\x3a\x29\x16\x14\x57\x21\xb9\x99\x98\x82\xb4\x4e\xbe\x6f\xaf\xe9\x6e\xb4\xd1\xfd\xfe\xef\xeb\xaa\x8c\x6e\x0d\x82\x79\xba\xab\x36\x80\x7a\xe6\x21\xa7\xa9\x5d\x9b\x7f\xaf\x02\x73\x32\xce\xbc\xaa\x14\xb1\x96\x8b\x4e\xc4\x72\x20\x26\x91\x26\x87\x78\x69\x48\xe9\x99\xc6\x5b\xb7\xba\xb3\x46\xe3\x7b\x67\x9f\x7d\xa6\x9e\x82\x28\xf7\x88\x12\xa7\x93\xb3\xea\x8c\x9b\x17\x99\x92\x2f\xc5\x99\xf7\xba\xae\x89\xf7\x26\x9c\xa2\x2d\x87\xc3\x50\x3b\xfa\x00\x1d\x47\xbb\xf6\x9c\xfc\xfd\xef\xdf\x7b\xef\xdd\xa3\x7f\x60\xe6\xbd\xf2\xf5\xd0\x1c\x13\x3f\xfa\xe4\x2b\x28\x38\xec\xd5\x55\xa3\x1b\xeb\x87\x5c\xbb\xb8\x67\x94\xfa\x08\xce\x85\xf7\xa3\xdb\xd1\xcf\xd1\xcf\xd1\x6d\x70\x05\x9c\x8b\x3e\x44\xef\xc2\x9e\xb0\x07\x2c\x87\xe5\xe8\xbd\x11\xc9\x55\xca\x5d\x57\x7f\x40\xdd\xae\xe5\xe4\x27\xcd\x26\xbd\x9b\x0b\x91\xd3\xb8\x4a\xeb\x71\x0e\x81\x99\x19\x5d\xce\x21\x3c\xce\x05\x71\xf6\x37\x75\xa0\xca\x65\x21\x25\xa8\xaa\xa2\x77\x77\x9d\xcf\xd5\xd9\x9d\xcf\x26\xc2\xdb\xa2\xb8\xcb\x54\x55\x80\xfc\x02\x5d\x15\xdd\x36\x41\x97\x5e\xa4\x08\xd1\x7d\x73\x34\x3d\xfa\x22\xd5\x88\x8b\x75\x4d\x37\x77\xd7\xbd\x4a\x81\xa6\xf3\x2b\x38\x27\x57\x09\x24\xd0\x03\xcc\x00\xb2\x23\x14\xcf\x65\x80\x95\x09\xca\x25\xa1\x38\x8b\x5f\xe9\xb1\x85\xd3\x8d\xdb\x9c\x7d\xda\xdc\xa0\x1a\x58\xf8\x9c\x82\xd8\x4a\x1b\x6c\x02\x76\x95\x73\x1d\x82\xd8\x6a\x13\x3c\x98\xd9\xa9\x44\x68\x05\x4e\x33\xe6\x25\x65\xd5\xdf\x29\x2e\xd3\x17\x5f\xaa\x3a\x5a\x8c\xaa\x00\x96\x0b\x14\x97\x97\x00\xc9\x29\x12\xd7\xac\x4e\xac\xad\xa1\xca\xd5\x37\x39\xaa\x09\x56\x42\xde\x79\xcf\x9d\x5e\x68\x83\x55\xe8\x1d\xf4\x8f\xdc\xc5\xf7\x38\xd1\x37\xe8\xad\x3d\xfb\x77\x0a\x97\xd7\xdd\x54\xb2\x6b\xcf\xbe\x97\x7c\xf3\x17\xfa\x76\xee\xa7\x3e\x82\xb5\xf0\x27\xc1\x5b\x6e\xe9\x85\x16\xa1\xa3\xe8\x6d\xb4\x28\xb8\x60\x41\x0f\xf8\x00\xac\xff\x02\x1d\xeb\xd9\xbb\x6c\x7c\x4f\x18\xfc\xe2\x4b\xd8\xa3\xc7\x84\xf1\x3d\xd0\x71\xdc\xd7\xfe\x38\x73\x8c\x89\xe3\x7e\xe1\x19\x40\x16\x43\xf1\x02\x06\xd8\x98\xa0\x5c\x16\x8a\x73\xf8\x95\x3e\xf5\xae\xd1\x99\xf9\x35\x98\xed\x4a\x18\x54\xfc\x39\x18\x6b\x59\x03\xd6\x2d\x10\x05\xb1\xd5\xe1\xca\xc5\x0b\x2d\x13\x5a\xad\x39\x80\x74\x1c\xa9\xbf\x13\xa8\x48\x91\xa1\xe3\x2a\xa2\xc7\x2d\xba\x9c\x94\x81\x50\x98\x95\x51\xf5\xbc\xb6\x6c\x81\x2f\x27\xef\xd9\xe1\xc2\x8f\x8f\x18\x07\x44\xeb\x86\x98\xde\xfc\xf8\x0f\xef\x9a\x06\xf5\x89\x0e\x34\xbd\xf9\xc9\xce\x4e\x6b\xbf\xda\xd9\xde\xef\xbe\xb3\xf7\xaf\xa9\xeb\x6f\x6d\x5e\x4c\x95\x7f\x06\xfd\x25\x75\x3d\x7b\xf6\x29\x43\x1f\x7c\xf4\x19\xea\x28\xab\xad\xaa\xec\x53\x02\x7b\x7c\x8c\x7e\xd1\xd0\xb3\xb8\xb1\x1f\x9c\x04\xaf\x1d\xd0\xd3\x5f\x1c\xf4\xfd\x0e\xd0\x60\xc9\xf9\xd3\x86\xc7\x8c\x43\x41\x35\x18\x06\xae\x83\xe3\x01\x36\x6d\xb9\x22\xa2\xf0\x16\x0c\xe5\xa8\xd7\x7e\xcc\x34\xee\x4f\xbe\x2c\x24\x0f\x89\x28\x75\x86\x84\x5c\x1f\x6e\x6d\xa8\xbb\xcc\x18\x94\xfb\x46\x94\x01\x5c\x42\x09\x0f\x0c\x87\xa1\x3c\x81\x98\xbe\x1b\x9b\x7e\x18\x06\x95\x61\x8e\x84\x3c\x8c\x57\x1a\x61\x50\xb9\xd6\x91\x88\x35\x5e\xab\xba\x80\x8d\xc3\x4d\xc1\x56\xd0\x78\x95\x29\x28\x5f\x4b\xba\xe1\xca\xdc\x09\xe5\x7a\x72\xa6\x7e\x19\xda\x4b\xc8\x1d\x87\x54\xc9\x7d\xab\xe4\x21\xbc\x52\x9f\x77\x46\xee\xcb\x2b\x03\xf3\xce\xec\x3c\x5d\xb0\x3f\x88\xb3\x03\xf5\x7c\x6b\x9f\xfa\xbe\x52\xb0\x35\xaa\xfe\x2b\x0f\xe1\x5b\x07\x0d\x19\x28\x05\x5b\x07\xab\xff\xc6\xfa\xd4\xf7\xcd\x48\x16\x44\xa3\xb1\xc1\x43\x06\xaa\xaf\x06\x45\x41\x6b\x9f\xe8\xa0\xc1\x24\x65\x50\xdf\x27\xda\x77\xe0\xa0\xc1\x43\xb2\x52\x06\x61\x9b\x20\xb6\x9a\x69\x3e\xa4\x6e\xd5\x30\xdc\xad\xd2\x28\xb6\x4a\xbd\xea\xd8\x12\x4f\x54\xf1\x5e\x2b\x88\x71\xb7\x3f\x50\xd1\x0f\x6f\xb1\x99\x17\xc4\x38\x30\x48\x3e\x52\xc0\x12\x70\x01\x4b\x1e\x20\xc6\x86\x5f\x75\x6d\x34\x1a\x95\x1b\x04\x79\x6c\xaa\xa0\xc5\x65\x55\xb4\x0a\x61\xba\x9e\x55\x96\x59\xd0\x22\xc8\xca\x98\xc3\xa8\x90\x6a\x80\xae\x40\x71\x15\x15\x28\x76\x49\xb5\xaa\x73\x5b\x45\xa5\xc8\x8d\x96\x40\xf6\xb3\xf5\x77\xe7\x55\x56\x4c\xed\xf7\xf8\x73\x6f\xed\x9c\xb2\xad\x61\xc0\xaf\xaf\x7f\xe9\xad\xe7\x1e\xed\x37\xbd\x67\x65\xde\xdd\xeb\xff\x02\x69\x74\x12\x9d\x5d\xb8\xe5\xf2\x2b\x5e\xb8\x15\xfd\x03\xfd\x91\x1a\x79\xcf\xbc\xbe\x0b\x17\xdf\x3f\xda\xca\x5f\xf7\xe8\x5d\x33\x7b\xce\x1d\xd7\x77\x80\xaf\xcc\x57\x5b\x19\x1d\xba\x84\x42\xf0\x5a\x78\xe7\xf8\x01\x13\x0b\x2a\xd1\x1f\xd0\x19\xf4\x3e\x6a\x6b\x1c\x38\xe8\x72\xd8\x08\xcb\xa1\x11\xfa\x2b\x0b\x26\x0e\x18\x8f\x56\xa0\x16\xf4\x10\x9a\x11\x0a\xf5\xae\x82\xeb\xd9\x7d\x85\xf3\xe7\x97\x56\x96\x2e\x0d\xf4\x0c\xdc\x81\x76\x36\x8a\xe1\x5c\xa7\x28\xe4\xe6\x97\x95\x0f\x6f\x18\xb3\x88\xf4\xbe\x9f\x3f\xcd\x79\x0c\x56\xd0\x13\x0c\x04\xa3\xe1\x0c\x10\xeb\x01\x88\x31\xd9\xcd\xaa\x9f\x49\x7a\xdf\x0b\x22\x8a\x09\xf3\x25\xb5\x7a\x7b\xd0\xc6\xa0\x6c\x88\xc8\xfd\x42\x72\x43\x44\x09\x71\x09\xb9\x77\xb8\xb5\x26\xd4\xcf\x18\x94\x23\x11\xa5\x9e\x4b\x28\xc1\x3e\xaa\x91\x5d\x95\xc9\xbb\x16\x84\x41\x65\xa0\x23\x21\x0f\xe4\x95\xcb\x60\x50\x19\xe5\x48\xc4\x2e\x1b\xa5\x1a\xd9\x65\x83\x54\x23\xbb\x6c\x84\x29\x28\x8f\x22\x9d\x09\x45\xae\x84\x32\x46\x33\xb2\xa6\xbd\x09\x6c\x64\x0d\x55\x72\xa4\x4a\x6e\xe0\x95\xde\x79\x67\xe4\x08\xaf\xf4\x51\x8d\xec\xae\xfd\x36\x6c\x64\xbd\xf9\xd6\xea\xde\x11\x29\xd8\x1a\x56\xff\x95\x1b\xf8\xd6\x68\x43\x1f\x29\xd8\xda\x57\xfd\x37\x56\xdd\x3b\x92\x61\x64\xe1\x68\xac\x6f\x43\x1f\x62\x6e\xa0\xb5\x3a\x1c\xed\x4b\x8c\xac\x77\x75\x38\xd2\x27\xda\xb7\x21\xcb\xc8\x06\x06\xd5\x83\xc2\xde\xc3\xa4\x9a\xcd\x65\x42\xcc\x10\xe2\x54\x73\x19\x25\xc6\x84\xd2\x5c\x52\x32\x8d\x4b\xde\x82\x40\x2d\xb6\x32\xaf\x5d\xb5\x32\xab\xe0\x2a\x52\x4d\x90\x4e\xd1\x57\xd6\x0b\xb1\x41\x23\x46\xa9\xbf\x5e\x23\xca\x97\x77\x65\x95\xe3\x55\x7f\x1c\x33\x16\xe9\x54\x4d\xda\x30\x09\x26\x98\xbb\xc0\xc0\x38\x97\x54\x5b\x57\x5b\x53\x5e\x56\x5b\x43\xec\x6b\xc1\x91\x7d\x03\xef\xea\xd9\x70\xc3\xb0\xdb\xe6\xc1\x8a\xe8\x6d\x23\xee\x68\x82\xe5\x1d\x23\x6e\x68\xa8\x58\x32\x70\xef\x91\xce\x7f\x5b\x33\x3d\x74\xeb\x35\x7f\x3e\x07\x6f\xfd\xf1\xad\x7d\x6f\x5d\xdc\x7c\xa5\x43\xb8\xee\xd1\xbb\x66\xf4\xac\xad\x1b\xb7\xb8\xba\x7a\x46\x74\x68\x13\x99\xf8\x28\xf2\xae\xa9\x39\x72\x14\xcd\x2a\x0d\x8d\x83\xeb\xe1\xe6\x9a\x35\xde\x22\xf4\x7b\xf4\x39\xfa\x3b\xfa\x60\x58\x51\x29\x2c\x67\xa1\x6f\xfe\xcd\x25\xbd\x4a\x96\x95\xf4\x2c\xa9\x1f\x80\x76\x8d\xec\xd1\xb7\x40\xe0\x7b\x8d\x1e\xde\x70\xf5\x1d\x00\x50\xa4\x2e\x6d\x30\x83\x30\x18\x04\xb6\x5c\xa2\x32\x2d\x0f\x08\xc9\xd1\x88\x52\xc3\x26\xe4\x1a\x3e\x3e\x08\x37\x2b\x29\xf5\x0d\xaa\xc9\x0c\xbe\x44\xc9\x7a\x88\xe6\xa8\xec\xa0\xd9\xde\x91\x9a\x01\x84\x0b\xa6\xb5\x57\x65\xdf\xfe\x98\x3c\x49\x8c\xfb\x03\x15\xb5\x51\xbc\x1b\x26\x87\xba\x1b\x5a\xd1\x5a\x19\x44\x0a\xd9\x4a\xcd\x00\x41\x54\x22\x75\xff\x62\xf9\x1a\xd6\xfa\x5d\x86\x40\x79\x80\x7c\xfd\xb3\xc5\x6c\xf8\x05\xdd\x6f\xac\xbf\x7a\x57\xb5\xbf\xba\xbd\xda\xff\x2f\x94\xb6\xd9\x69\x7e\xff\xf6\xd9\xb3\x67\xcf\x06\x3a\x0e\x23\x57\xc9\x6e\x06\xc5\xa0\x37\x98\x72\x91\x2a\xb7\x5c\x15\x52\xf7\xa1\x84\x4d\xc8\x25\x7c\xbc\x37\xd1\x75\x79\x50\xd5\x75\x75\xaa\xfc\x1d\xee\xb6\xfc\xad\x94\x54\x09\xa2\x12\x28\xfb\x41\x85\x70\x29\x4b\x33\x97\x2a\x8b\x53\x99\x8a\xf8\x61\x35\x72\xb6\x39\x63\xed\x10\x2c\x41\x4e\x26\xc1\x1e\x06\x6e\x30\x51\x9f\x8d\xa2\x13\x31\x07\xee\x42\x77\x08\xa6\x60\x0a\x8e\x48\x96\x52\x44\x4f\x9a\x59\xa9\x9e\x9e\x48\x86\xa6\x14\x51\x12\xc4\x98\xc9\xc1\x60\xef\xde\x84\x11\xa1\x0c\x38\xc1\xdc\x1d\x40\x91\x3f\x5c\x2f\x04\x84\x22\xb0\x44\x86\x23\x3e\xf8\xf3\x8b\x57\x6c\xdf\xf6\x77\xf4\x17\xc8\x80\xf3\x0b\x46\xbc\x84\xb6\xa0\xb5\xd4\xc9\x53\x70\xc2\x8b\xe3\x37\x8c\x41\xfb\xd1\xdf\xd0\x47\xe8\x7d\x6f\x72\x2e\x7c\x0f\x2e\xd3\x38\x2b\xe9\x6d\xb8\xaf\x7e\x86\x36\x75\xef\x30\x27\x62\x6e\x07\xc6\x76\x93\x4c\xc1\x98\xc3\x8d\x45\x17\x4d\xc1\x8c\x09\x2f\x6f\xe6\x09\xaa\xb7\x3e\xa9\xcf\x82\x13\xb7\x6d\x68\x04\x21\x69\xb9\x69\xa1\xfb\x81\xaf\x3a\x55\xf0\x40\x19\x58\x08\x45\x74\xe5\xb3\xfd\x6b\xd7\xce\xda\xb6\x65\xeb\xe6\x21\xd7\x57\xc4\x9d\x08\x75\x52\x3e\xe8\x82\x3d\x7d\xf9\x6b\x6b\xde\x38\x7e\xe2\x80\x57\x4c\xce\x82\xef\x51\xd0\x87\xf5\x3c\xe7\x7c\x27\xb3\x88\xe5\x80\x04\x04\x82\x80\x0c\x65\x67\x48\x87\xb5\xad\x67\xa5\xd2\x7a\x56\xf2\xd0\xac\xa1\x14\x7f\x95\x4b\x73\x86\x42\xff\x61\xf4\xd1\x30\xe8\x6b\xbf\xbb\x1d\xfa\x87\xa3\x8f\x7f\x07\x0b\x2f\x43\xa7\xda\x96\xb4\x51\xa5\x8b\xb6\xc2\x19\x5b\x16\x6f\x85\xfd\x87\xa1\x7d\x5b\x16\x6d\x41\x1b\xb7\x2e\xda\x82\x0e\x5c\x06\x07\x91\x3d\x3d\xc4\xac\xa6\x5b\x70\x2d\xb2\x02\xc8\xf6\x90\x42\xb3\x89\x98\x1d\xb7\xd3\xd8\xd5\x1d\xa5\xed\xe6\x60\x2b\xa0\x0d\xa6\x2c\x19\x6a\xea\x22\x7e\x8d\x09\x8d\x0b\xf8\x09\x5a\x5d\xcf\x3a\xb8\x9f\xeb\xd5\x3b\x52\xd9\xab\x0e\x35\x70\x3d\x7b\xd7\x56\x30\xdf\xd5\x06\x43\xa1\xea\xda\x3e\x3d\x2b\xc3\x35\xea\x67\x7d\xc7\x7c\x4c\x7f\xc4\x76\x00\x09\x94\xe3\xcf\xe2\xb8\x44\x2b\xe4\xec\xc6\xa0\x02\x38\xc2\x5c\xef\xc4\x40\x30\x66\x47\x1a\xc4\x97\x64\x7a\xdd\x05\x30\x50\x5b\x13\x28\xb6\x53\x81\xef\xac\x77\xad\x7d\xe2\xea\x79\x3f\x5e\x36\x37\x38\xeb\xae\xd5\xe3\x99\x4f\x97\x35\xf4\xbd\x79\xbe\x5f\x9a\x55\x12\x2c\x01\x10\x76\x30\xc7\xa8\xa3\x5c\x14\x38\x40\x95\xfa\x19\x71\x5a\xf3\xc5\x49\x07\xb0\xc5\x91\x88\x59\x80\xba\x24\x0b\x67\x0a\xb6\x0e\xb2\xd8\x53\x7d\xc0\x7a\x83\xa3\x9d\x72\x39\x3d\xae\x32\xd8\x31\x3c\x1a\x8a\xf8\x4a\x7c\x8b\xbf\x65\xdb\xa3\x23\x2b\xca\xf3\xbc\xbc\xe8\xec\x5b\x32\xaa\x2f\xd6\x1b\xfc\x28\xf3\x73\x40\x28\x6e\x49\x7f\x0e\x7d\x5c\xb1\x3b\x12\x44\x75\x83\x68\xa0\xde\xb4\xb4\x31\xfd\x39\xea\x4d\x92\x76\x55\xe0\x47\x8b\x7d\x25\xbe\x9a\xaa\xe8\x50\xe6\xd8\xa8\xd2\xa8\x53\xe4\xbd\x79\xe5\x15\x23\xa3\xbf\x04\x10\xad\xe0\x9c\x70\xa1\xc1\x0e\x24\x20\x03\x59\x08\xc9\x7c\x44\x61\x70\x03\x5f\xab\x89\x11\x8c\x78\x92\xd7\xca\x25\x14\x60\x0b\x87\x53\xa0\x74\x8e\x04\xbe\xc2\x5d\xfb\x68\x7c\x85\xf3\x55\xb2\xb1\x4a\xe6\x79\x85\xcd\x3b\x23\x1b\x79\xc5\xa6\x5e\xe1\xf5\xfb\x03\xf8\x0a\xc7\x28\x7b\x46\x29\xd8\x6a\x50\xff\x95\x79\xbe\xd5\xce\xdb\xa4\x60\xab\x43\xfd\x37\xc6\xb1\x19\x18\xd8\xb2\x21\x1a\x73\xf0\x36\xf5\x95\x1d\x23\x61\xdb\x1d\xe4\x0a\x67\x39\x83\xd1\x66\x77\xf0\x59\x44\xd8\xea\x2a\xbb\xfa\x68\x68\xc5\x3d\xf3\xfb\xde\xba\xf8\xfe\xd1\x36\xe1\xba\xd5\x77\xcd\xec\x79\x33\xe7\xf4\xcd\x9f\x57\xda\x0b\x3b\x49\xaa\x4f\x64\x04\x15\x68\xaf\x61\x2f\xfb\x18\x9e\xf7\xae\x00\xf5\x60\x28\x18\x0b\xa6\x81\x79\x70\x31\x90\x6b\x42\x4a\x25\x9b\x88\xd5\x54\xaa\x3a\xad\xe9\x69\x0a\xca\xbd\xc3\x72\x4e\x48\xbe\x2a\xa2\x08\x6c\x42\x1e\x19\x8e\xe5\x60\x2c\xe8\x1c\xbb\x29\x18\x73\x0e\xbb\x22\x1c\x0e\xcb\xe6\x90\x3c\x37\xa2\x1a\xb4\x3c\x33\x1c\x33\x63\x9b\x36\x03\x53\x30\xc6\x4d\x9f\xad\xfe\xb8\x2c\x24\x4f\x8e\x28\x3e\x36\x21\x8f\x0f\xc7\xca\x70\xc7\x44\x59\xbe\x29\x18\x2b\xbe\xe6\x7a\xf5\xc7\x83\x43\x4a\x5f\x36\x11\x1b\xdc\x57\xfd\xc1\xe0\x3e\xa6\xa0\xdc\x3f\x0c\xe5\xf9\xaa\x96\xe3\xb6\x1c\x50\xcb\x60\x78\x22\x3b\x0c\xca\xf9\xe1\x78\x1e\x79\xa3\x02\xc3\x8e\x1b\x60\x30\xce\xe5\x80\x91\x4c\x50\xe6\x08\x8f\x6f\x20\x1c\x77\x92\x37\x8a\xc3\x6a\x2c\xd8\x13\x06\xe5\x3e\xe1\x78\x3d\xf9\xbf\x86\x86\xe5\x7a\x5e\x8d\x81\xe5\x01\xe1\x78\x6f\xf2\x7b\xfd\xc3\x72\x6f\x5e\x19\x06\x83\xf2\x35\xe1\xf8\x58\xf2\x7b\xd3\xc2\xf2\x58\x5e\x99\x0e\x83\xf1\x79\xe4\x8d\x79\xbc\x32\x0a\x06\xe5\x89\xe1\xf8\x15\xe4\xff\xba\x3e\x2c\x5f\xc1\x2b\x37\xc2\x60\x7c\x36\x7e\x43\x59\x00\x83\x4a\x9e\x5d\x10\x15\x33\x1d\x8d\x2a\x9c\x41\x10\x5b\x85\x1c\xec\x90\x2b\xd5\xf5\x82\xa8\x54\xf6\x8d\x46\x95\x79\xd3\x05\xb1\xf5\xaa\xf1\x93\x47\xaa\x6f\x5f\x31\x4a\x10\x95\x99\x73\x49\x87\x34\x89\xbe\x02\xa4\x11\x26\xfb\x3b\x3a\xeb\x3b\x98\xfd\xb3\xba\x8b\xff\x28\xfb\x4f\x66\xfe\x62\x05\xfb\xa3\x1b\x27\xdd\xce\x8d\x61\xfb\x0d\x1d\x1d\x66\x67\x67\x7d\x37\x2a\xeb\x3b\xf8\x15\x3b\x4b\xfd\xf6\x2a\xb6\xdf\xb0\xd1\x61\xf6\x0a\xcb\x81\xc9\x0b\x0d\xda\x37\xf0\xbb\xef\xf9\x1f\x6f\xb7\xbc\xa6\x7f\x13\x61\xe1\xe1\x89\x73\x66\x4f\xaa\x0c\x96\x57\x23\xeb\xc4\x9b\x66\x4f\x56\x5f\xd1\x27\xf5\x57\xe7\x1c\xd7\xdf\x34\x7b\x52\xaf\x5e\x15\x21\xce\xbe\xef\x47\x93\xd5\x17\xe7\x8c\x17\xfe\x1a\xf2\xee\x9b\x33\xb1\x57\xaf\x1e\xbd\x89\xfd\x2e\x35\x34\xb1\x47\x81\x01\x23\xa3\x14\x82\x32\x50\x09\x6a\x41\x7f\x30\x0b\xc8\x75\xa4\x0e\x04\xc3\x32\x5b\x74\x5c\x90\xfb\x45\xc8\x50\xd9\x80\x90\xec\xc3\x5d\xf7\xa5\x42\x82\x80\xdb\xe7\x09\x09\x39\x10\x56\x06\xc2\xa0\xe2\xf5\x09\xb8\xd2\x5a\x2a\x28\x85\xc5\xd1\xa8\x9c\x27\xca\xb9\x51\xa0\xd4\xb1\x38\x1f\xa6\x46\x54\xa0\x21\x1a\x95\xfb\x88\x72\x3d\xee\xc4\x72\x7b\x5c\x86\x2a\x28\xd5\xd5\x7b\x9c\x9c\x41\xaa\x77\x7b\x0c\xc5\x55\x10\xd6\xd5\x47\x3c\x76\xa8\x2a\xbe\x3e\xc2\x19\x02\x6c\x4d\x5d\xbd\x87\x33\xd0\xf5\x9e\x42\xe8\x31\x94\x49\xb5\xf5\x85\xd0\xe3\x2a\xab\xe8\x58\x66\x1f\xf2\xea\x1d\x2f\xdf\x3c\x73\xd7\x2a\xe9\xb2\x25\xa3\x66\x08\x7d\xc6\x50\x52\xad\xb0\xca\x22\x0c\x2f\x99\x2e\x5d\xee\x9b\x5e\x23\xae\x82\xbb\x5b\xd6\x0d\xfb\xcb\xc0\xe8\x34\xa9\x6c\xa2\xe7\xb2\x47\x7f\x66\x1f\xf1\xfa\xe0\x0e\xaa\x76\x3a\xf9\xb5\x64\xfb\xa2\xab\xa6\x79\xa6\x44\xd8\xca\xe1\xaf\xcd\x9c\x71\xdd\x9e\x33\xe7\xf0\xdf\xbc\x8a\x63\x46\xbc\x3e\xf8\xc3\x9f\x34\x79\x6e\xe8\x33\x74\x5d\x55\xe7\x2b\x33\x98\x21\xfb\xfa\x0f\xff\x03\xfc\x66\x95\x45\xfd\xbb\xb5\x1a\xe6\x3a\x5a\xca\x95\x1a\x66\x00\x27\x28\x06\x0f\x69\xdd\x9d\xf6\x34\x2e\x6b\x51\x48\xf1\x72\x89\x98\xb7\x48\x7d\x1a\xbd\x05\xa6\x20\x2e\xde\x06\xf4\xe6\x5b\x85\x13\x70\x85\x44\x8d\x64\xdc\x22\xae\xb4\xe7\xc3\xa0\x52\x20\x26\xe4\x02\x52\x74\x37\x8b\x04\x4f\x87\xe6\xf0\xe8\xa0\xec\x12\x64\x27\x86\x79\x28\x8e\xca\xf9\x82\x5c\x14\x95\x0b\x44\xec\x81\x91\x2e\xdd\x56\xce\x6c\x11\x09\x36\x88\x10\x11\x9c\x0e\xcc\x55\x15\xa1\x03\x12\xc1\xeb\xcc\x46\x6a\x3d\xb8\xdd\xc2\x98\xe8\x92\xc3\x87\xd6\x1c\xdd\xb0\x4d\x32\x75\x9e\x30\x3c\x6f\x9e\x3c\xff\xa6\x99\xa6\x6d\xb6\x57\x5f\x7c\xe5\xd7\x6c\x5b\xe7\xc9\x27\x94\xab\x99\xdd\x04\x1c\x8d\xce\xfb\xe5\xd9\x73\x43\x0c\x33\x6e\x19\x3d\x79\xf2\x73\x6b\x56\xe3\xf9\xf9\xe5\x6c\x35\xc7\x63\x4c\xda\x95\xda\xda\xad\x69\x9c\x8b\x4b\x60\xd2\xb6\x8a\x18\xe7\x42\x12\x75\x10\x3b\xc5\x28\x26\x64\x23\x2f\xe7\x6a\xc8\x22\xb2\x37\xa4\xe4\x6a\xd0\xb4\x92\x28\x88\x31\x56\xf0\x45\x31\x66\x15\x06\xa6\x15\x63\x9c\x25\x2f\x9a\x5a\x38\x6b\x34\xf1\xe9\x85\x1b\x52\xcb\xee\x06\xf4\xc2\x4a\x8d\xea\xd8\xbd\xac\xbd\x69\x2b\xcd\x26\xdb\xa6\x6d\x31\x4e\x5a\xa8\xae\xd9\xfa\xca\x4b\xaf\xb4\x30\x8d\xc9\x65\x53\x77\xd2\xeb\x3a\x47\x27\x3f\x87\x4b\xa8\x95\xab\xef\xeb\x9c\xc3\xf1\x37\x5e\x33\x79\xf2\xc6\x27\x1f\x55\xf7\x3b\xa4\x61\x8c\x0b\x20\x17\xdc\xd2\xa5\xf7\x92\x74\x31\x1b\x22\x0a\xa4\xd5\xdb\x2e\x6e\xca\xe5\xa1\x4d\xc3\xb9\xfc\x0f\xe8\xbc\xd4\x3b\x16\x2f\xe8\xbc\x0c\xad\x6b\x87\x63\x90\xdc\x4e\x8d\x42\x7f\x41\x9f\xa3\x79\xed\x47\x5e\x6e\x7b\xf1\xb7\x87\x98\x29\x1b\xdb\xdb\x37\xa2\x2f\xd0\xb4\x23\x27\x99\x29\x9d\x03\x56\xac\x6c\x26\x73\xb7\x22\x00\xcc\x38\x3c\xbf\x9e\x0b\x66\xa5\x7b\x2f\xe5\xdc\x10\xa6\x41\xbf\xa0\xe5\xfe\xff\x6b\xb7\xe5\xfa\x38\x0c\xa1\x23\xb0\x06\xbe\xf2\xa7\x53\xa8\x20\x0e\xcb\x71\xb7\x65\x07\xb3\x6e\xe5\xdf\xff\xbe\x32\xf9\x37\x74\x68\xf3\x76\x66\xdd\xb9\x33\x37\x4c\xbc\xfe\x6a\x1d\xd3\xb4\x09\x63\x04\xe6\xab\xde\x71\x1a\xd3\x34\xdf\x92\x88\xdb\x79\xdc\x7d\x66\xb7\xa4\xa8\xd0\x1d\xae\x84\xcc\x63\xf4\x26\xd5\x83\x67\xdd\x84\x0a\x3d\x47\x75\x82\xcd\xc6\x68\x54\x66\x05\xdc\x21\x6e\x07\x82\xa8\x98\xcc\x04\xa5\x06\x53\xf2\xe7\x77\x01\x50\xf7\x18\xca\xb9\x20\xf4\xc2\x48\xb8\xbe\xbc\xde\xa3\xa3\x9f\x3e\x06\x1d\xd0\x7d\xdb\x4d\x8b\x6e\x7a\x6c\xc6\x83\xb1\x4d\x53\xfb\xcc\x5e\xb8\xfc\xce\x5d\x7b\xf7\xb3\x6d\xef\x1d\x5f\xf6\x7a\x9f\xa7\x26\xbc\x92\x97\x3c\x48\x9d\x30\xae\x18\xbf\x6d\xf8\xd6\x87\x1f\xca\xc4\x9c\xf0\x80\x1e\xa0\x89\x78\xc9\x4a\x5e\xd6\xd8\x69\xa9\x86\x39\x41\xb2\xb0\x1e\x5b\x42\xce\x21\x98\x13\x1e\x52\xaa\x30\xbb\x48\x32\xd6\x43\xa9\x6e\xbd\xe4\x54\x1f\x89\x62\x21\xc6\x38\x30\x6e\x98\x59\x8c\x59\x6d\x18\x6b\x49\x11\xd4\x45\xa9\xaf\xe5\x3c\x32\xf4\x20\x97\x8a\x71\xc6\x2c\x39\x2f\xc4\xa3\xc0\xcb\xcb\x60\x07\x4c\x2d\x92\xc0\x52\xe4\x1a\x07\x6d\x99\x7f\xfc\xf3\xd8\xad\x73\x97\x0d\x1d\xd7\xb1\xd8\x6a\x5d\xb3\xa5\x57\xd9\xe2\x5b\x9b\x26\x3f\xb6\x4e\x47\xa7\xb8\xfe\x6a\x8c\x4e\xf1\x9b\x47\x9f\x1e\xb7\x3d\xe7\xd9\x35\x45\x04\x9f\xc2\xfa\xf4\xb8\x4d\x37\x26\xde\x79\x8b\x60\x54\xa8\x7b\x27\x72\x1f\x03\x03\xa8\xcf\xdc\x39\x8e\x4e\xc4\x20\xa7\xf7\xf9\x76\xc1\xba\xa5\xd4\x6d\x13\x33\xb1\x3c\xd4\xaf\x83\xd4\xb3\xdb\x93\xf3\xd8\x36\x58\x89\x42\x67\xbf\xd0\x66\xe9\xe9\x31\xec\xca\xcc\xbf\x8d\xc1\x41\x0c\xdd\xfe\x6d\x5b\xfa\x6f\x4b\x5d\xff\x76\x0b\xfc\x4a\x46\x22\xd3\x08\x07\xa2\xda\xce\x21\xea\xdf\x56\x9f\x79\x3b\xc6\xa8\x1b\xa7\xcd\x4f\xd1\x9a\xdc\x71\x00\xad\x5a\x8b\x35\xa0\x13\xb2\x29\x8c\xe1\x85\xac\xf8\x61\xb1\x60\x66\x92\x98\xc5\xaa\xe3\x67\xb5\x0e\xb2\xb0\xa6\x60\xcc\x8a\x67\xd7\xad\xc0\x14\xc4\x8c\x07\xf8\xe9\x48\x41\xbf\x07\x84\xd0\x3a\x7a\x44\x72\x21\xdc\x82\x26\xb6\x53\xcd\x1b\xa9\xc7\x37\x23\x61\x63\xb2\x89\x6a\x06\x10\xf0\x00\xd0\xa3\xf1\x6c\x6f\x4a\x0e\x0d\x00\x25\x53\x0e\x43\x57\x39\x6c\xff\x92\x1c\xfc\x7a\x6a\x13\x12\xe1\x04\xb4\x35\x0e\x3b\x56\xc1\x3f\xad\x43\x6d\xab\x50\x00\x76\x60\x9c\x4e\xc0\x9c\xc6\xbd\x0b\xd3\xba\xe0\xfe\xcb\xb6\x90\x22\xd1\x89\x78\x8e\x01\x3f\x88\x39\x74\x9a\xcf\x5f\x23\xd4\x02\x3a\xa1\x56\x8a\x45\xcb\x43\xba\x27\x5d\x79\x82\x18\x33\xd8\x78\x6c\xba\x40\xd2\xba\x00\x88\x44\x75\xfa\xbc\x37\x66\x70\x2b\x12\x6a\x4a\x02\xc5\x06\xe1\x20\x3d\x36\x39\x7b\xea\x5d\x70\x00\x9c\x80\x3e\x3a\x0f\xae\xbd\x6f\xf8\x92\x95\x70\x31\x3a\xff\xf7\x29\x13\xd9\xb6\xcd\xc8\x64\x46\xdb\xd0\x41\x74\x00\x3d\xef\xca\xdf\x5c\x0d\xbf\xfa\x1b\xb2\x26\x57\x6a\x38\x08\x66\xc6\xc8\x34\x82\x5c\x30\xa7\xcb\xc4\xa5\x2a\xbf\x68\x49\xc4\x0d\x1e\x2c\xbf\xc1\x92\x1a\x87\xcc\xb5\x61\xf9\x73\xb1\xfc\xb9\xaa\xfc\x1a\x3a\xae\xfa\x38\xaa\x77\x76\x6e\x0a\x43\xdb\x29\xc4\x0c\x36\x91\xac\x43\xd4\x3a\x80\x33\xd7\xa1\x41\xfb\x12\x06\x4e\x83\xd0\x42\x6d\x43\xe6\xb1\xfd\xa0\x0d\x5a\xfe\xf2\xce\x43\x73\xe7\xdf\x0b\xcd\xbf\xde\x31\xba\x1f\xd3\xb8\x0e\xbd\x6a\x45\xa7\x50\x07\xfa\x1a\x9d\xec\xf7\x6c\x7f\xf8\xc4\x89\xc3\x76\x14\xc2\xf8\x27\x4b\x0d\x4e\xb6\x0d\xb8\x52\x38\xdf\x0e\x31\x9b\x03\xc0\x8d\x61\x2c\xb3\xc6\xb8\xec\x30\xa8\xd8\x24\x6d\xb8\x5b\xbd\x4d\x8d\x66\x8b\x7a\x60\xd8\xc8\x09\x48\x01\x41\xdc\xc1\x18\x2c\x56\xc1\x79\x01\x45\x40\x04\x37\xe0\x5e\x48\x13\x00\x0f\xef\x93\x67\x77\x47\x14\x10\x4b\x9e\x84\xcb\x52\x64\x01\x1a\x66\xcb\x72\xae\x3f\x9e\xa7\xcb\x96\x19\x76\x23\xb3\xf8\x1f\x2b\x33\x3c\x8d\x1a\xd2\x80\x68\x37\xbe\xde\x32\x43\x83\x44\xd3\xd1\xd0\xd4\x2f\x34\x3d\xf9\x37\xb8\x24\x8d\x8a\xa6\x9e\xd5\xa3\x51\x7f\x8d\xe3\xa0\x1e\x3c\x42\x26\x92\xe3\xbd\xad\x20\x97\x09\xa6\x88\x0e\xe4\xda\x90\xd2\x93\xcb\xe6\x3b\xe8\x13\x92\x2b\x8f\x2b\x61\x21\x21\xfb\xc2\xb1\xca\xb0\x6a\x30\x95\x16\x53\x50\x0e\x13\x02\xb2\x4c\x22\x04\x25\x0a\x83\x4a\xb8\x52\x10\x31\x34\x1a\x50\xca\x7a\x0a\x62\xac\x47\x65\x38\x1a\x8d\x2a\x96\xde\x82\xa8\x00\xcc\x86\x20\x68\x6c\x08\xe2\x3f\xcd\x86\x20\x91\x72\x63\x79\x84\x8c\x40\x96\x5f\x9a\x1d\xe1\xe9\x40\x6d\x69\x64\xd5\xd2\x8d\x37\xcd\x1a\x54\xff\x7d\x4c\x09\xe8\x98\x25\x54\x79\xe3\x8a\xc5\x2b\x6e\x98\x2b\x00\x0a\x0c\x45\xfd\x35\x0c\xb9\x88\xea\x0b\x16\xab\xba\xea\x45\x74\xa5\x03\xc9\xc9\xd5\x21\xa5\x8c\xcb\xc6\x93\xab\x09\xc9\x15\xc7\x95\x2a\x21\x21\x57\x91\x76\xb2\x8b\x41\xcb\xd5\xaa\x26\x50\x25\x10\x2c\x39\xa0\x14\x97\x09\x62\xac\xa4\xa2\x4a\x55\x94\xb9\x97\xaa\x28\x1f\xe9\xbb\x26\x50\x73\x44\x9f\x3f\x0c\x64\xae\xab\x8a\x2e\x0e\x3a\xb7\x30\x43\x35\x17\x03\xa0\xcb\x52\x8b\x86\x1d\xdd\x1f\xfb\x8b\x63\x34\x0f\xd9\x96\x81\xc8\x2f\x76\x19\xbe\xc4\xed\xe4\x12\xa1\x93\xb0\x0a\xaa\xcb\x6b\x34\x45\x49\x57\x85\x0e\xeb\xd6\x4a\x9b\xcc\x8e\x94\xa3\x5b\x0f\x23\x40\x37\x76\x83\x70\xb0\xfd\x5e\xca\x74\x02\x1d\x41\xa7\xe1\xa7\xbb\xe5\x5b\x93\xff\x78\x82\x6d\x4b\x86\x56\x51\xc3\x91\x8c\x8e\x26\x6f\xc6\x4f\xe5\xce\xe6\xe4\x21\x0d\x7b\x67\x3c\xc6\xc2\xd4\xe5\xb2\x64\x4c\x28\x3a\x08\xc5\x1f\x19\xd3\xb0\x6b\x73\x68\x62\x02\xf7\x8d\x9b\xed\x82\x18\x63\x38\xec\x6d\x98\x04\x99\x4d\xc9\x65\x30\xda\x52\x72\x65\x3c\x82\xfa\xec\xe2\xe2\xf6\xed\x13\xd2\x48\x6f\x68\x6a\xf2\xaf\xb0\x49\x7f\xd6\x88\x6f\xf0\x35\xce\xe7\x0d\xce\x88\x24\x74\xc8\x74\x67\x97\x11\x02\x0d\x7a\xc3\xe1\xc0\x0c\x27\xae\xf4\x08\xa5\xa0\x37\xb6\xd6\x0b\x11\x17\xd6\x0d\x3e\x04\x54\xd5\x34\x35\xc1\x87\xb1\x6e\xa8\x89\xef\xa3\x29\x4d\x4d\x6c\x5b\x32\xf8\x08\x9c\x72\x14\xee\x56\xb5\xd3\x79\x90\x1a\x8e\xde\x87\xcd\x37\x27\x0f\xa5\xf0\xc6\x46\x32\x8d\xc0\x09\x2e\xeb\x12\xd9\x18\x53\x13\x9c\x4e\xa2\x1f\x67\xa6\x3c\x0a\x67\x0e\x67\x0d\x75\x4a\xd9\x12\x41\x17\x0c\x40\x57\x40\x28\x2b\x17\x5a\xe2\xb7\x37\x43\xe6\x00\xaa\x87\x5f\x1e\x41\xa7\x9a\x47\x97\x32\x8d\xc9\xc4\xdd\xb0\xf1\x00\xf4\xa2\xc2\x5b\x10\x03\x23\x27\xe0\x84\xd1\x15\xc9\x63\xba\x0f\xf2\x35\xc6\x94\x9f\xa2\xf5\xb4\xd8\x23\xa4\x54\x62\x8e\xc4\x21\x70\xe9\x83\x5e\x34\x19\xf4\xf2\x60\xa2\x5e\x0a\xe3\xad\x10\x97\x5d\x23\xea\x35\xa4\x89\x7a\xd5\x9b\x1f\xc3\xd2\x00\x97\x20\xc6\x4c\xf8\xca\xd2\x7d\xf5\x88\x2b\x20\x10\xf5\x95\x51\xe5\x06\xec\x96\xb4\x1f\x3b\x46\xad\xd0\x14\xd8\xd1\x9c\x6c\x7e\xa2\x9d\x99\xbd\xa9\xa5\x65\x13\x5a\x42\x1d\x23\x1a\x6c\x81\x53\x5a\x96\x25\x0f\x32\xb3\xb5\x99\xde\x6a\xce\x09\x72\xc0\x04\xad\x67\x50\x8c\xc4\x1c\xb8\x07\xa7\x6b\x78\xe1\x0d\xc9\x1e\x2c\xab\x5b\x0f\x2f\xdc\xb8\xa9\xd0\xad\xca\xea\xc1\xa9\x6e\x0f\xd0\xb1\x62\x1c\x1e\xd5\x75\x77\x66\x8d\xed\x0a\x86\x48\x7d\x5d\x3d\x19\x9a\x35\xe0\x81\xdd\x18\x5c\x8c\x56\x72\x46\x69\x50\x2f\x38\xe5\x18\x1a\x0a\xdf\x3f\x81\x9a\x9b\x62\x04\x90\x21\xd9\xb9\xc1\x7b\x43\x15\xbc\x1d\x05\x93\xab\x20\xba\x19\xcd\x63\x4e\x00\x08\xec\x00\xb0\xab\xb0\x8f\x37\x98\xf8\x56\x19\xbc\x23\xaa\x6f\xa7\x39\x54\x1a\x60\x75\x57\xe7\x49\x01\x38\xc7\xce\x99\x34\x15\xfa\x85\xb4\x34\x76\xca\x44\xad\x78\x3f\xb9\x9b\x9a\x70\x22\x79\xf6\xc9\x17\x59\x71\x73\x32\x48\x1d\x4b\x36\x77\x1e\xc4\xcf\x22\x26\x6f\x23\x78\x5b\x5f\x33\x8d\xc0\xaa\x7e\xbe\x25\x7b\x62\x58\x01\xa6\x04\x94\x6d\x24\xc7\x2c\x11\xb0\x71\xb3\x0e\x36\xae\x5e\x92\x40\x01\x96\x6e\x3f\x5f\x08\x08\xa5\x94\x1d\x9e\xd8\x8f\x82\xb0\xf3\x6d\x64\x97\xe9\xb6\x35\xf8\xf9\xfb\x3c\x79\x48\x7d\xf6\xe8\x36\xfd\x8c\x3a\x86\x63\xaa\x71\x19\x67\x81\x3e\xd1\x63\x4f\x63\x76\xf3\xa9\x98\x8a\xc2\x31\x95\x35\x85\x33\x98\x02\xbb\x97\x08\x16\x14\x89\xa8\x0c\xc6\xac\x41\x71\xf5\x3c\x20\x64\x1d\x5f\xb6\xc9\x72\x5b\x92\xd7\x26\x75\x30\xbf\x12\xa6\xec\xc0\xb3\xb2\xac\x15\x63\x54\x4d\xe9\x72\x2e\x65\xc8\x62\x4e\xe5\xfa\xcd\xa6\x54\x8e\xdc\x61\xbb\x50\xac\x56\xb3\xc1\x6a\x24\x10\xfc\x97\x92\x0a\xc3\x22\x6e\x8a\x6d\xd6\x81\x11\x49\x06\x40\x03\x47\x24\xdc\x2a\x84\x3f\x72\x74\x1a\x55\x87\xd5\x66\x29\x8c\x74\x22\x4e\x5b\xf1\xb4\x10\xad\x99\x0a\xd0\x71\xe1\x65\x1b\xee\x77\x55\x05\x32\xba\x12\x31\x23\x36\x1c\xa3\x21\xe5\x75\x13\x39\x88\xcf\x4d\x88\x4c\x28\x23\x92\x53\x5c\x26\x9b\xcf\x7e\xa1\x91\x99\x10\xac\xca\x43\xd8\xff\xcf\x94\x41\x9b\x16\x30\x9a\xd2\x32\x98\xd3\x32\xd8\xba\xca\x60\xbb\xa4\x0c\xaa\x26\x28\x09\xfd\x22\x85\x11\xb9\xa6\xb3\x31\xad\x07\x04\x8c\x15\x6c\x1b\x28\x02\xb3\x35\x19\xf2\x35\x9e\x12\x1f\x9d\x90\xad\x21\x45\x54\xdd\x7f\x56\x77\xff\x31\x3b\xa8\x1f\x8b\x52\xe4\x4a\xc8\x45\x04\xa0\x23\x9f\x48\x95\x4f\x22\x00\xa3\x27\x81\x03\x5b\x57\x3e\x86\xd1\x74\x5c\xe0\x39\x13\xbf\xd9\x49\x71\x3a\x85\xb3\xee\xee\x68\xbc\x27\xee\x51\x4b\x61\x35\x1c\xb3\xec\xeb\xad\x57\xad\x18\xfe\xd3\x7b\x5f\x7c\xf9\x6f\x1d\xc1\x26\x4f\x5b\x72\x02\xdb\x96\x9c\x6e\x45\x9b\xd1\x1b\x6f\xa2\x13\xcf\xa8\x51\x40\xf2\xab\x6f\xbf\x33\x18\x92\x0f\xb3\xfc\xd9\x2f\x75\x4c\x34\x33\xb7\x9d\x69\x04\xf9\xe0\x66\x6d\x3d\x39\xda\x5c\x5d\x9e\x39\x21\x5b\x42\x0a\x6f\x49\xf3\xc6\xa5\xf3\x0a\xea\x0a\xf2\x49\x9b\x4b\x0e\x59\x4c\x0e\xa9\x41\x1b\x09\x7e\x1f\xc6\x49\x89\xb1\x16\x1b\x59\x0c\x8f\x7b\x9c\x15\xd6\x22\x88\x32\x9d\x5a\x54\x38\x1d\x0c\x84\xb5\x60\x80\x00\x55\xde\x7d\x65\xdf\x6f\xa1\xf1\xc4\xfe\xfb\x67\xce\x5d\xf0\xe5\xe6\x6d\x23\xfa\xc4\x93\x7f\x63\x1a\x51\xb9\x15\x1d\x43\x09\xf4\x15\xea\xd0\xc2\x01\x11\x45\xe8\x58\xe7\x68\xc2\x73\xb3\x9d\xfd\x98\x7d\x13\x54\x80\x5a\xb0\x06\xc4\xca\x31\x86\xb3\x25\x21\xdb\x79\xb9\x50\x75\xa7\x02\x3a\x9b\xaf\x89\x4e\xc4\xdd\x91\x00\x6d\x0b\x2a\x6e\xd5\x4e\xea\x48\x81\xc9\x8d\xd1\x53\x54\xbf\xa3\xa7\x3b\x21\xf7\xe4\x71\x9b\x9f\xd7\x95\x50\xea\xd5\xb7\x24\x41\x8c\x9b\x68\x3b\x5f\x5e\xe2\x89\xca\xbd\x85\x38\xe7\xce\x2f\x65\xd5\xd7\x5e\x51\x6b\xd5\xb7\x97\x0b\x62\x2c\xbf\xa8\x54\xf5\x0a\x22\x42\xdc\x02\x24\x6f\x65\x89\x27\xaa\x98\xdc\x42\x0a\x17\xc6\x4f\x2a\xe8\x45\xb8\x80\x5e\x5f\x46\xd5\xd6\x88\x91\x30\x6e\x91\xd2\x71\x26\xcb\xb9\x40\x11\x80\x4e\xb7\x07\x37\x7d\xe3\xa6\xe9\x91\xb0\x61\xd9\xa4\x6a\xf7\xec\x30\x1a\x78\xf6\xcf\xe1\x9e\x63\xa6\x1c\x94\x77\xec\x5f\x71\xdb\x90\x6b\x47\xf7\xef\x33\x39\xb6\x66\xf6\xa3\xe8\x0d\xf4\x0b\xda\x3c\x71\xf4\xf4\x5b\x67\x4d\xb8\x7e\x16\x75\x18\xde\x0d\x57\x06\xd6\x9b\x9c\xc9\xad\xe8\xcf\xe8\x5d\xcb\x54\x98\xfb\xec\x57\x90\x43\x67\xce\xfc\x06\xbd\x35\xde\xe7\xfe\x85\x77\x56\x09\x5c\x09\x43\x0f\xfe\x63\xec\xe0\x33\x4f\xfc\xe6\xd5\x57\x75\xec\xd3\x03\xcc\x09\x66\x0a\xa8\x00\x35\xe0\x49\x8d\xd1\xcc\x6e\x4a\xc8\xc5\xaa\xf2\x0a\x52\x90\x33\x26\x9c\xa1\xe4\x30\x0b\x9f\x31\x11\x77\x85\xcb\x30\x68\x93\x21\x01\xe5\xda\x14\xa1\x81\x85\x98\x42\x4f\x1b\xbe\xe2\x34\x5d\xe6\x48\x09\xa5\x4e\x7d\x57\xc4\xa0\x34\x9c\x9d\x2f\x23\xca\x8c\xb9\xf2\x4a\x54\xad\xe5\x88\x4a\x41\x31\x56\xa5\xea\xdb\xe6\xf9\xf0\x9b\x61\x21\x0e\x2c\x62\x4e\xa5\x0e\x98\x9e\x81\x4e\xa3\xaa\x30\xd5\x38\x94\xa9\xc1\xe2\x32\xaa\x54\x53\x61\xa0\x98\x5b\xd8\xf9\xf1\xd4\x2b\xcb\x87\x0f\x7e\xf2\x91\xe7\x9f\x1d\x90\xbf\xfc\x85\xa7\x9f\xd8\x70\xd3\x0d\xe1\x01\x43\x22\xbd\xae\x5b\x7b\xcf\x9c\x3b\x9f\xfc\xd3\x8f\xa9\xe5\x97\xf5\x1d\x72\x75\xf3\xb0\x91\x54\x1e\x74\xc2\x50\xce\xcf\xa4\x77\xfe\xf8\xfa\x5b\xd6\x47\x4f\x6e\xdf\xb3\x5b\xbe\xf7\xad\xfe\x5e\xfb\x6a\xfe\xaa\x1e\x0f\x41\xea\xae\x49\x1b\x42\x3d\xd7\xdd\x7c\xea\x2e\xd5\xde\x50\x7f\x8d\xd7\xa7\x1c\xdc\x49\x3c\x92\x78\x11\xf1\xf7\x53\xd5\xf4\xd2\x90\x92\xcb\xa5\xe6\xca\xb4\x8a\xba\xfa\xfc\x17\x0b\x04\x88\xa9\xc0\x2a\x88\xad\x39\xbe\x22\x3c\xc9\x55\x2c\xb4\x9a\x1c\x2e\x86\xb4\x16\x96\x0a\xa2\x5c\x8e\xe9\xf7\x73\x54\xa5\x44\x15\x53\x91\x20\xc6\x80\x01\xc3\x75\x77\x5f\x71\x4f\x33\xd8\x77\x71\xe8\x2f\x4a\x11\x04\x4f\x64\x38\xf4\x17\xe1\x0b\x4a\x8e\xca\xf4\xe7\x29\xb0\x10\xf5\xd7\x70\x56\xcb\xd4\x75\x3b\xd5\x75\xfb\xc8\xba\xf5\x52\xbc\x5c\x82\x93\xfe\x50\x2e\xcf\xac\xc8\xe7\xc3\xa0\xe2\x17\x12\x4a\x0f\xf5\xfc\x53\xd7\xed\x29\xf4\x11\xce\x69\x75\xdd\x4e\x02\xd1\xe5\x2d\x21\xa5\x13\xa7\x10\xf3\xe4\xfb\xf1\xba\x7d\xe9\x75\x5f\xac\x62\x4f\xd0\x95\xba\x2e\xbb\x5b\xc8\x56\x38\x38\x73\xc9\x17\xe2\xb7\x26\x63\x99\xcb\xc5\x98\x5c\x4b\x31\x57\x92\x05\x0c\x02\xd9\x34\x49\x56\xcc\x8a\xc6\xba\x12\x31\x33\xab\xd7\x28\x65\x96\x57\x8c\x16\x0c\x54\x11\x33\x18\xd5\x77\x0d\x74\x8a\xe0\x90\x20\xba\x92\xfb\x56\x54\x6f\x16\x45\x69\x67\xf9\x2d\x5b\xce\xad\x51\xef\x7f\x96\x27\xd8\xb1\x68\x39\xbd\x09\xcf\x3a\x37\x02\x0d\x08\xd2\xa4\x7e\x5e\x0c\x40\x8c\x95\x61\x54\x2f\x7c\xed\xa3\x6d\x99\x1f\xdd\x6a\x64\xcd\xc6\xa0\x62\x90\x2e\xf1\xc9\x15\xf4\xdd\xe8\x99\x4d\xf2\x66\x3a\xbe\x76\x6d\xe7\x9f\xd4\xa0\x9f\x8e\x6b\x3d\xff\x2b\xd8\x36\x60\x04\xbd\x41\xcc\x00\x40\x90\xf0\x35\xd1\x11\x28\x9b\x30\x7f\x21\xe7\x4a\xe0\x30\x88\x33\x08\xa2\x4c\xa9\x87\x3a\x79\xd1\xbb\x5a\x20\x79\x87\x80\x70\x08\x2e\x81\x4d\xaf\x21\xef\x4b\x6c\x5b\xb2\x9a\x7a\xbb\x73\x59\xf2\x10\x15\x52\xff\x36\x72\x32\x3c\x8e\xb5\x7a\xa7\x91\x4e\x6c\x21\x1c\x66\xd9\x8e\xe3\x7c\x39\xaf\xc1\xe5\x2b\x2c\x83\x2f\x0c\x5b\xaa\x77\x3c\xdd\x24\x2c\x04\x84\xdd\x7f\xbe\x4a\x32\xdb\xfb\xe7\x7c\xbc\x1b\x8d\x8d\x33\x8d\xc9\x2d\x1d\x53\xa3\xfb\x07\x51\x13\xcf\xc5\x50\x0e\xfc\x0c\x64\xac\x83\x07\x93\x89\x1f\xa9\xaf\x23\x6e\xb3\x5b\x80\x0d\xe3\xd2\xda\x68\xc2\xf4\x24\xa8\x1e\xa5\xec\x08\x63\x42\x3d\x36\x1c\x33\x63\xbf\xc0\x6c\x34\x05\x75\xff\xd2\x66\x0a\xe2\xa3\xcc\x6c\xd1\x17\x6d\xcf\x5a\xb4\x4b\xf3\x19\x6a\xfd\xb5\xfa\xe2\x61\x25\x3a\xfa\x12\x3a\x02\x43\xba\x12\xa2\x9b\xd0\x66\x38\x69\x53\xb5\x36\x5b\xa1\xe9\x02\xa3\x13\x3a\x35\xdc\x5c\xc9\x90\x90\xed\xe1\x94\x6a\x84\x10\xce\x06\x09\xc7\x65\x57\x58\xe1\x6d\x18\x87\x8c\xc7\x65\x72\xde\x6e\x0a\xc6\x04\x5c\x7c\x10\x24\x53\x10\x27\x86\x78\x41\xeb\x45\x02\x0a\x70\x0a\x24\x6d\x2f\x44\x3c\xa2\xdb\x13\xa9\x93\xea\x23\x16\x98\x92\x71\x77\xbf\x17\xae\x11\x8d\xe5\x07\x26\xed\x3e\x76\x02\x4a\xe8\xaf\x71\xf4\x19\x74\x33\x8d\x1b\xd0\xb5\x67\xc6\x6d\x87\xff\xf8\x7b\xf2\x83\xe4\x87\x2b\xd1\xcf\xe1\xcc\x95\x44\x56\x23\x5a\xca\x7c\x81\xfd\xe2\xbe\xe9\x18\x30\xc5\x2d\xc5\x13\x7f\x9c\xb8\x96\x58\x43\x8a\x11\xb3\x5c\x10\xae\x4d\xa3\xc9\x9e\x4a\x4a\x99\x52\xe1\x70\x57\xce\xa9\x7b\x14\x65\x76\x17\xd6\xa9\x2d\xd8\x1b\x5e\x92\x5c\x4e\xe2\x02\xd4\xcc\x8c\xc2\xfe\x70\xa6\x0c\x30\x5b\x06\xe9\x9f\x94\x21\x1b\x9f\xb7\x74\xa3\x3c\x36\x1b\xa1\x17\xdd\xa8\x06\xe7\x18\xa5\x57\x3b\x03\xb8\x36\xac\x87\x1f\x69\x48\x58\x2c\x4e\x76\xc7\xec\xac\xce\xe9\x4e\xc2\x05\x2d\x0d\xae\x9e\x0e\x3c\x46\xc2\xc2\x24\x6a\xf6\x14\xc8\xb3\xf6\xfb\xda\x41\xc1\x11\xb8\x63\xd9\x94\xce\x7b\x08\x99\x14\xd8\x9a\x73\xee\x17\x44\xa6\x37\xaa\xa4\xde\x6f\x6f\x6b\x39\xd7\x42\x0e\x0c\x56\x24\x41\x83\x7a\x68\xe0\x33\x83\xdd\x82\x75\x34\x4b\x97\xcf\x7c\x81\x7c\x5a\x69\x8e\x9c\x26\x29\xf9\x6c\x97\x92\xcf\x96\x68\xb5\x9a\x38\xe3\xf7\x89\x57\x41\x8f\x41\x1b\xa8\xda\xf8\x16\xb9\x73\x3e\x3e\x55\xfe\x4d\x47\xb9\xa5\xe3\x84\xd3\x0b\x2d\x65\x97\xb2\x6d\x04\x89\x49\xa3\xf3\x92\x5d\x21\xc2\xec\x97\x93\x39\xda\x27\xa4\xa8\xbc\x30\xab\x86\x25\xa8\xd8\x25\x02\xcb\x24\xd0\x02\x61\x84\xe1\x08\x43\x5e\x17\x56\x2f\x72\xb6\x65\x31\x7b\xc9\x72\x37\xdc\x5e\x24\xd4\xd2\xf8\xbd\xd6\xa1\x66\xe6\x24\xd3\x08\xdc\xe0\x5a\xa0\xc3\x20\xcb\xce\x90\xc2\x9a\x12\x31\x27\x56\x85\xd3\xae\x1e\xb7\x9e\xcc\x61\x3e\x3e\x85\x86\xdc\x6a\xb7\xf0\x1a\xfc\x6f\x8e\xfa\x1c\xd2\x98\xaa\x06\x28\xac\x33\x63\x84\xcf\x79\xa1\x80\x1a\x36\xf2\xa6\xd8\xe6\xae\xe8\xc8\x84\xef\x43\x43\x48\x4e\x73\xa1\xb9\xc1\x7c\x82\xb1\x4d\x94\x67\x8d\xc4\x5d\x9c\x43\x9b\x90\x74\xd1\x09\x59\x0c\xc7\x5c\xb8\xc6\xe3\x72\x9a\x82\x31\x0e\x27\x3a\x38\x43\x86\xe4\x44\xb9\x4e\x32\x37\x29\x39\xf0\xdc\xa4\x44\x28\xe4\x2d\x61\xc5\xae\x83\xa2\x63\xd5\xf2\x69\xd5\x0a\x11\x41\xc3\x74\xc6\xa1\x46\xd1\xe6\xf6\x95\x8f\x36\xad\x7a\x72\xd7\xae\x96\x3b\x9a\x50\x88\xe8\xf5\xc7\x0b\xe1\x44\xd4\x62\xef\x4b\xbd\x7e\xb6\x91\x1a\x37\x88\x47\x6f\xc2\x20\xd0\x70\xa6\x2b\x98\x46\x90\x03\x7e\x4c\x6c\x92\x28\xd8\x12\x89\xbb\x59\x0c\xc1\x66\xc4\x14\x7c\x31\x37\x9b\xea\xea\x63\xdd\xfa\x28\xa5\x6a\x7d\x82\x31\xd5\xd3\xa7\x69\x5e\x22\x63\x94\xa2\x03\x8f\x51\x92\xf4\xb8\x6c\x0e\xe3\x0d\xc8\x85\x41\x45\xd2\x4d\x84\x15\x30\xea\xa9\xb6\x0e\x4f\xe6\x32\x5c\x81\x5a\x03\xde\x82\x7d\x77\xdf\x7a\x6f\x3c\x7e\xdf\xfc\xbb\xad\xf6\xcd\xed\xd4\x76\xb8\x01\xcd\x6f\xe3\x60\x05\xfa\xd8\x33\x8e\xa0\x54\x5f\xe7\xfd\x2e\x41\xfd\x3a\x8b\x93\x15\x63\x66\xeb\x71\x27\xc6\x41\x61\xed\x69\x9a\x63\xa9\x0b\xfd\x94\x59\x43\x33\xc7\x45\x12\x11\x1f\xcc\x40\x61\xed\xa9\x08\x28\x22\x94\x64\x22\xad\x19\x84\x83\xed\x90\xda\xff\xf6\x47\x2f\xdd\xf3\xd0\xec\x1d\x4f\xb2\x6d\xc9\xad\x93\xf6\x2a\xc9\x76\xaa\xf2\xce\x3b\x8b\xc3\xc9\x86\x0c\x0e\x80\xb4\x1c\x66\x12\xab\xc5\x39\x22\x07\x67\x4c\xcb\x91\x82\xe9\xc5\xa4\x0d\x1a\x76\x37\xc6\x83\xe5\xd4\xa7\x28\x53\x8e\x34\xe4\x1b\x96\xa3\x25\x3e\x73\xd7\x2d\x2f\xec\x8a\x1f\x99\xba\x71\x0e\xd3\x88\x9c\x43\x1b\x7e\xb5\x0e\xcd\x86\xab\x77\xd5\x0e\x42\x41\xd5\x07\xac\x3f\x7f\x9a\x1b\xc3\xbe\x09\x7c\xa0\x14\xac\x22\xbd\xb4\x8a\x44\x27\x64\x8f\x1a\x16\xb8\xe9\x04\x9e\xbf\x53\x23\xae\xb8\xa1\x20\xd7\x62\x0b\xca\x8e\x88\x62\xb0\x24\xe4\xa2\xb0\x0e\x62\xcb\x8a\x09\x75\x8f\x0b\xc8\xb3\xc4\x7b\xd4\x9f\xc9\x3c\x19\x3c\xb1\x7b\x08\xa8\x19\x0b\xf0\x55\x2b\x17\x08\x32\x1d\x95\x79\x51\xce\xc7\xfc\x50\x16\x09\x37\x93\xdb\x45\xc5\x8d\xd1\x0f\x03\x06\x41\x54\x00\x45\xf8\x17\xeb\x23\x9c\xcb\xd9\x00\x09\x75\x17\x01\x00\xaa\xd3\x11\x80\x8a\xcb\x4a\xfd\xbc\xbf\x98\xab\x2f\x78\xda\xb5\xa0\xb8\x02\x8e\x84\x5e\xd8\x03\xd6\x9c\x3b\x69\x87\xf0\xdf\x1f\xfc\xe3\xd4\x85\x1d\xab\xd1\x6b\x68\xa3\xeb\x67\xcf\xc2\xaf\xe9\x69\xe8\xc6\x43\xa7\xe9\xe5\x57\xf6\xad\xbc\xec\x47\x70\x04\xbc\x0a\xfd\x0c\xfd\x62\x0e\x3a\x8f\xbe\x0d\x17\x6d\xad\x28\x86\xd3\xe1\x15\x77\x56\xc0\xaf\xce\x93\xd8\xa9\xf2\xfc\x69\x26\xc1\x4c\x02\x05\xa0\x04\x3c\x0a\x62\x5e\x1d\x5d\xd4\xa2\xba\x6f\xc5\xc6\x44\xdc\x90\xef\xd5\xd5\x60\x48\xc8\x85\x84\x3c\x5f\x55\x83\x80\xd5\x90\xaf\xa9\xc1\xa5\xfe\x4c\x55\x83\x4f\x55\x83\x9b\xb0\xe9\xeb\x6a\xc8\xd7\xd5\x90\x17\x95\x7d\x42\xcc\x22\x7a\x35\x35\xb8\xdc\xaa\x1a\x44\x2f\xc1\x25\xcd\x17\x64\x57\x54\x29\xee\x46\x29\xb8\xd4\x5d\x00\xfd\x78\xa6\x95\xa0\x04\xd1\x25\xa5\x7e\x6c\x7c\x95\x79\x8f\x3b\xe7\xb8\x72\x3b\x0f\xbd\xf3\x6d\xd2\x61\x84\x63\x66\x6d\x9c\x75\xc3\xc6\x79\x7f\x47\x9f\x19\xd1\x97\xf0\x6d\xaa\xfa\xc1\xfb\xef\x7b\x92\xfa\x78\x44\x4d\xe9\xb0\x1f\x75\x7c\x89\xbe\xfd\x78\x1e\x6a\x2e\xea\xb9\xbe\xbc\x08\x7a\xc0\x79\x66\xe5\xba\x4d\xcf\x62\x3d\xd4\xa3\xa5\xd8\x2e\xfc\xa0\x07\x78\x8e\xe8\x41\xce\x8f\x28\x92\x25\x11\xf3\x4a\xb8\x01\x28\x4f\x75\xad\x54\xe3\x28\x53\x8d\xc3\x97\x97\x61\x1c\xc5\x29\x50\x07\xcd\x38\x7c\x69\xe3\x28\xc6\x5a\xc9\x83\x41\x5c\x86\xcc\xe5\x31\x3a\x92\x5d\x1f\xca\x62\xb1\x29\xcb\xbc\x20\x17\x46\xe5\x3c\x51\x11\x7a\x44\xa3\x72\xae\x10\x93\x2c\x65\x38\xfb\x20\x79\x09\xdc\xa9\x4f\x90\xdd\x51\xa5\xec\xd2\xf6\x82\x4f\xbb\x12\xcd\x62\x54\xf5\x10\x93\xf1\xc1\x31\x30\x0f\x96\xc3\xda\x94\xc9\xb4\xfd\x25\x86\xce\xa1\x0e\x91\x98\xcc\xc1\x77\xd3\x26\x33\x10\x5e\x87\xd6\xa0\xe7\xe7\x6b\x26\x33\x84\x45\xab\xe1\xe2\x02\x38\x19\xf6\xb8\xb3\x02\x9c\xff\xfb\x79\x62\x37\x68\x39\xb6\x9b\x22\x50\x0e\x36\x01\x0c\x22\x25\x7b\x23\x8a\x68\x48\xc4\xf2\x71\x57\x49\x3e\xd6\x17\x6e\x8a\x50\xad\xc8\x97\x69\x45\xfe\xb0\x1e\x58\x6a\x56\xe4\x4b\x5b\x91\x3f\xad\x2f\x29\x11\xcb\xcd\xc3\x35\x5b\x37\xa9\xd9\x16\x6b\xb6\x55\x91\x56\x9d\x92\xc7\x93\x70\x33\x57\x88\x89\x96\x52\xac\x34\x43\xbe\x40\x4c\x4b\x2e\x15\x2e\x65\x49\xaa\xba\xca\xa8\xf2\x6c\x63\x2a\x3c\xf7\x5a\xda\x98\x46\x3e\x7a\x83\xbc\xf7\x08\x77\x81\x31\x7d\xf8\xef\x29\x63\x2a\x2e\xa4\xd1\x13\xf0\x76\x1f\x14\xdf\x27\x16\x05\xc1\x58\x00\xa8\x19\x59\x1c\xf3\x90\x4d\xc8\xe6\x30\xce\x3b\x2a\x0c\x4b\x00\x3c\xad\x21\x99\xc2\xe4\xbd\x31\x13\x95\xe2\x96\xe7\xc2\x31\x0a\xe3\x1f\x53\xaa\x33\xc3\x84\x75\xd8\xc0\xda\x7a\xa1\xbc\xd6\xef\x32\x08\x1e\xd7\xd8\xed\xdb\x29\x7e\xfb\xf6\xb9\xe5\xcc\xcf\x2a\xe6\xce\xad\x38\x37\xbf\x7c\x2e\xa0\x08\xbf\xbc\xc6\x33\xbe\xbc\x5b\x86\xf9\x8b\xf7\x75\x89\x29\x72\x69\x07\x49\x36\x12\x06\x7a\xd9\x9e\x62\x1c\x4f\xf5\x72\x29\x3e\x18\xc5\x20\xc2\x4e\x72\x94\x15\x44\xa3\x4a\xae\x17\x63\x7b\x5d\x92\xac\xde\xd4\x05\xa6\xb1\x5b\xea\x7a\x28\x65\x81\x34\x5e\x8c\xc9\x3e\x83\x7c\x9c\x22\x9c\x5c\x1c\x0f\x44\x50\x94\x5a\x7b\x36\x2b\x97\x5c\x18\x52\x3c\x5c\x22\xe6\x29\xc4\x55\x89\x3c\x13\x01\xce\xf5\x87\x64\xe9\xb8\xe2\x14\x13\x7a\x2d\x28\xc5\xda\x25\x3b\xc8\x3c\x4a\x9e\x48\x72\x9c\x4e\x49\x10\x95\x22\x88\x1b\x8d\x64\x17\x06\xae\xf1\x14\x46\xa3\x4a\x5e\x2e\x86\x27\xfd\x01\x04\x5f\xd9\x2d\x7c\x17\xa1\xfb\x92\xb3\x17\x7f\x31\xf2\xaf\x0c\x56\x27\x2d\xb7\xcb\x96\xb3\x6d\xa0\x10\x2c\xc8\xe8\xeb\x90\xd9\x88\xec\x08\xa9\x8e\x56\x3c\xcf\x88\xaf\xd9\xbc\x34\x1a\x7e\x21\xb9\xee\x0b\x49\x7f\x95\xc5\x4d\xc0\x56\x73\x0a\xd5\x45\x18\x1c\x62\x89\x27\x55\xbb\x74\x39\x08\xe3\x0c\x10\x64\x09\x1f\x53\x96\x1c\xcc\x37\x9e\xba\x85\xeb\x61\x04\xd6\x67\xe7\x79\xc5\x5a\xad\xd3\xa3\xfd\x08\xdc\x7e\x32\xb9\xca\x0b\x2f\x87\x33\x57\x74\x6e\xbf\xe6\xde\xc6\x25\xeb\x62\xaf\xa3\xbf\x7d\xf3\xd3\xa9\x6c\x5b\xb2\xdf\xa7\xb0\x23\x39\x96\x42\xbb\xd1\x9b\x6f\xa3\x13\xcf\x38\x0b\x36\x57\x43\xfa\xf4\x27\x67\x7c\xc9\x96\x54\xbf\x47\x2d\xce\xf1\x2e\xc8\xe8\xf7\x90\x99\x08\x6e\x57\x31\x27\xe2\x5e\x0e\xaf\xcb\x6b\xca\xca\xef\x92\x0c\xb5\x9b\x44\x01\x38\xa9\xeb\xce\x57\x0d\x93\xb3\x39\xd4\x75\x69\xb5\x4f\xc9\x46\x20\xe6\x81\x20\xf3\x38\x1f\x6a\x72\x63\x46\xb9\xd4\xba\x60\x04\xba\x81\xe0\x24\x23\xbe\x7a\xd5\x1e\x37\x7e\xc4\xe0\x47\x07\x51\xed\x59\x08\x16\x1c\x7e\x60\xc5\xcc\xd0\x2d\x43\x7f\xfa\xc4\xab\xf1\xab\xa7\x32\x8d\xc9\x4e\x8a\x41\xf9\x0c\xfa\x0c\xfd\xbb\x9c\xbc\xbf\xdf\x33\x39\xa5\xc7\xf6\xfd\x7e\x9f\x17\x8d\xd4\x7b\x29\x96\xb2\xdb\xb0\x5f\xbc\x01\x10\xb0\x2f\x9e\xc6\xbc\x60\x38\xf1\xef\xc1\x91\x8d\x89\x38\xb5\xdd\xb2\xd5\xf3\x45\x67\xec\xb2\x98\xc1\x56\x2f\xf2\xad\x82\xc8\x5f\xc0\x56\x2f\x88\x3c\x66\xab\x17\x74\xb6\x7a\x5e\xc8\x60\xab\x57\x4c\x76\x41\x54\xac\x84\xdf\xc0\x25\x88\x31\x80\xfb\xce\x64\x5e\x88\x41\x93\x39\x9a\x2e\xbf\x63\xa4\x63\xdc\x8b\xd9\x95\xd1\xfe\xe0\xe3\x47\x9f\xbd\x90\xd5\x9e\x44\x76\x29\x66\x7b\x08\xec\x68\x39\xb3\x1d\xd7\x62\x07\x10\xd6\x4d\x8c\x53\x83\x1b\xa0\x30\x0a\xb3\x43\xdd\x37\x17\xce\xa5\x18\x6d\x09\xbc\x63\x46\x9b\xa0\xd3\xd7\x3b\x68\x35\x2a\x26\x38\x5c\x29\xe0\x65\x22\x0e\x61\x09\xf3\xfa\x6e\x59\x1e\xa0\xd6\xee\x6e\x6e\x6b\xda\x81\x76\xe5\x4e\x7b\xea\xce\xfe\x2b\x39\xf8\x3b\x78\x8e\x94\x80\xe8\x38\xda\x80\xa6\xbf\xaa\x3d\x1f\xa5\xb8\xef\xe6\x86\x2e\xcf\x87\x39\xa4\x6e\x41\x9c\x76\x82\x4c\x6e\x60\x70\x1c\x8f\xa4\x51\x18\xf3\x44\x4c\x73\x72\x79\xf0\x50\x91\x20\x2a\x66\xac\x3c\xde\x4c\xf0\xab\x81\x80\xc9\x2e\xf4\xc2\x54\xba\xdf\xc9\x0b\xb5\xa2\x19\xfa\x37\x94\x1c\xd7\x34\x6a\xc9\x43\x70\x69\xaa\x78\xf6\x3e\xda\x8f\x5a\x9c\x05\x9b\xaa\x61\x82\xf2\x25\xc7\xeb\xf6\x3e\x57\xcf\xb1\xa4\xed\x9d\xc8\xe9\xb0\xa4\xe5\x34\xa7\xe5\xb4\x7d\xaf\x9c\x44\x91\x66\xdc\xce\xa9\xca\x69\xcb\x94\x33\x45\x55\x5e\x4b\x8a\x47\x63\xdb\x8e\xef\xff\xe9\xd4\xf9\x37\x35\xdd\x91\x6c\xd1\x48\xc6\x3e\x45\x5f\xa3\x4f\xfa\x3e\xdb\xf0\xdb\x03\xb0\x1d\x79\xf4\x9a\x23\xc9\xad\x5c\xf3\xaf\xd6\x1c\x09\xc7\xb2\x55\xe3\x4e\xed\xbe\xb8\x47\xf6\x99\x68\xef\xd0\xda\xa3\x1b\xbb\x2b\x3a\xea\xdc\x38\x6c\x39\xce\x21\x5c\xf3\x7d\x75\xc7\xef\x2b\x36\xfe\x13\xf2\xe0\x62\xe3\xcb\xcd\xed\xf7\xc6\xbb\x2d\x37\x92\x9c\x01\x8e\x7d\x31\xcf\xf3\x0f\xcc\x19\xb4\xda\xad\x82\x31\xa8\x38\xa4\x84\x7a\x60\xeb\x99\x03\x6c\xff\x9c\x2b\x7a\xd1\xdc\x81\x1a\x98\x47\xb2\x73\x07\x31\x79\x5b\x37\xbc\xe0\x68\x29\x55\x0a\xe3\xe9\xdc\x41\x14\xe7\x0e\xae\xe9\x9a\x3b\xb8\x78\xc2\xc0\x86\x13\x06\xaa\x57\x60\x0f\xa5\xf2\x06\x76\x5a\x83\x4d\xbc\x48\xe6\x20\x43\x3c\x2d\x73\xf0\x0b\x65\xc3\x85\xbc\x4a\xa8\x99\x72\xc1\xab\x53\xdc\x4a\x07\xd1\x52\xc3\x10\xb6\x8d\x70\xd3\x10\x2f\x46\x88\x64\x74\xde\x90\xc8\x3a\x47\xc4\xf3\xfe\x56\x0d\x5b\x59\xbd\xa9\x73\xd4\x5d\x93\x9c\xb8\xed\xaa\x95\x62\x05\x7c\x87\x19\xc4\x56\xb3\xc5\xc1\xa7\xc0\xb0\xe3\xb4\xc1\xe8\x90\xb4\x6e\x17\x3f\x8c\x40\x7f\x46\x93\x7d\x00\x06\x3c\x6e\x97\x70\x10\xf2\xf0\x80\x11\x1e\x82\xf6\x83\x6b\x8e\x6d\x6a\xb3\x1b\x51\xce\x93\xa8\xd0\x68\x30\xb2\x6d\xe7\xc6\x32\xda\x31\x47\xaf\x6d\xfe\xf4\x1c\x60\xa9\xfb\xd7\x4d\xee\x5c\xac\xd9\x21\xc7\x30\x8d\xc0\xab\xf7\xe5\x28\x76\x29\x93\x8f\x90\x80\x12\x69\x18\xd8\xfa\x80\x80\xea\xe9\x3a\xbc\x1a\x1f\xa1\x6c\x16\x70\xd7\xaf\x26\x29\x6b\xb6\xf0\x39\x7a\x5f\x8e\xce\x4c\x48\x84\x75\xc0\x34\x3b\xa1\xaf\x34\x80\xd9\x09\x77\x37\xb7\x2f\xdd\x24\x0d\xc4\x0c\x85\x52\x8d\x81\x69\x4c\x5e\x36\xf9\xfe\x79\x77\x50\x2f\x6b\x87\xe1\xca\x86\xed\xc9\x29\xd4\x96\xca\xa7\xf3\x89\xbc\xff\xf9\x3e\x2a\xc1\xbd\xc9\x33\xcc\x00\x06\xe0\x02\x79\x3a\x83\x0f\xe6\x03\xa4\x40\x30\xce\x11\x0a\x5f\x0e\x8f\x73\x2a\x56\x2e\x11\xb3\xe2\xe0\xcb\xca\x9b\x82\x38\xed\x9d\x8f\xd1\x51\x4d\x22\xce\x3c\xaa\x2a\xe4\x35\x00\x4f\x93\x51\x10\x63\x2e\x0e\x73\x16\x3b\x84\x56\x0a\x4a\x5e\x75\xf3\x79\x51\x61\x71\xa8\x0d\xdd\x98\x23\x44\xc3\x73\xa5\xfd\x74\xb6\x2f\x26\xf9\xe9\x72\xce\x40\x35\x6c\xa1\xfa\xbe\x2a\x27\x77\xb7\x8c\xcd\x72\xc2\x1e\x85\x6f\x6f\x1e\x5e\xe8\x67\x77\x9f\x1d\x0a\x0f\xa0\x86\x94\xe3\x79\xee\x57\x70\xd7\xc9\xbb\x66\x02\x40\x13\x7e\x69\x8e\x07\xb9\xa0\x07\x88\x00\x39\x93\x61\xba\x57\x16\xc3\x74\xb5\xce\x30\x2d\x97\x85\x14\x1f\x97\x88\xf9\xca\xd4\x15\xfa\x02\xa6\x20\x2e\xb8\x13\xbe\x98\x0a\x57\x42\xae\xe0\xe5\x7c\x3c\x9e\x23\x26\xe4\xbc\x90\x92\x2f\xaa\x6f\x29\xa1\x34\x13\x35\xae\x6f\x06\xc4\x4c\x4a\xea\x5a\x18\x54\xf2\xf3\x04\x31\x66\xee\x61\x21\xcd\xe5\x71\x7b\x8e\xa1\xac\x17\xb6\xfe\x6a\x49\xbd\xe9\x9d\xae\x68\x34\xaa\x18\x28\xec\xb0\xcb\x76\xe1\x52\xb4\xd4\x5d\x14\x75\x49\x92\xea\x19\x59\xaa\xbb\xea\x7b\x29\xab\xd9\x1f\xeb\x9a\xfc\x6d\x8a\xbc\x9a\xd1\x6c\xa4\x02\x18\x80\x04\xbc\x84\x5d\x28\xdb\x4a\x9c\x29\x2b\x11\x42\x72\x20\x12\xb7\x10\x1e\x8c\x02\x92\xa3\x31\x1e\x57\xe3\x6b\x35\x72\x51\xcf\x84\x22\x8d\x65\xc8\x6e\x24\x6c\xdc\xb9\x42\x0c\x52\x1e\x55\x37\x45\xa2\xc2\xe2\xa3\x15\x3a\x71\x90\x9d\x61\x1b\x99\x34\x19\xd8\x32\x32\xdf\x49\x5b\x49\x9b\x4e\x99\x51\x47\x0c\xe4\xf9\x14\x6f\x86\x66\x29\xdc\x01\x8d\x30\xe3\xdc\x7b\xd8\x52\xa8\x4d\x69\x02\x0d\x86\xd8\x0c\x7b\x02\x73\x92\x57\x83\xfe\x60\xc7\x0f\xe0\x25\x97\x43\x21\xb9\x21\x12\xaf\x20\x2b\xae\x0d\xe3\x79\xae\x34\x4f\x79\x19\x0c\x2a\xbd\x3c\x09\xb9\x57\x26\x65\x79\x6b\x1f\xc1\x6f\x0c\x2a\x61\x77\x42\x0e\x87\x94\x3e\xee\x4c\x83\x19\xa8\xfe\x0f\x65\x82\xa8\x14\xe6\xe0\x92\xb5\x62\x37\x44\xa3\xb2\x5f\x54\x6a\x1b\xa2\x51\xa5\x0f\xd0\x42\x9b\xc0\xbf\x64\x3a\x19\x8c\xe6\xd2\x45\x58\x89\x2e\xc1\x74\x6e\xbb\x90\x98\xe8\x12\xe4\xe7\xf4\xbb\xdd\xf0\x13\x51\xe7\x11\x00\xdc\x63\xd8\x67\x91\x54\xcf\xca\xaa\xf1\x6b\x98\x34\x9c\x6f\xdc\x00\x2f\x86\xe3\x76\x1e\x13\x09\xda\xe9\x44\x9c\x35\x5a\x53\xf9\x51\x27\x6e\xc8\x27\x94\xf5\x32\x13\x8e\x99\x70\x43\xbe\x89\x32\x05\x65\x73\x98\x70\x16\x69\xd3\xc3\x01\xa8\xb7\xe1\xe3\x2f\x1a\xfa\x85\x00\x45\xb5\xd1\x1d\xc9\x57\xa9\xdc\xe4\x9f\xa9\xc1\x49\x03\x02\x1f\xc2\x00\x7c\x69\x31\xdb\xb6\x09\xf5\xd9\x98\xfc\x76\x93\x6a\x29\xd4\x1c\x6a\x9b\x76\x8e\x70\xcb\x98\x29\xf8\x14\xe9\x0b\xb6\x6b\x5c\x4a\xfe\x88\x7a\x8a\xc8\xb9\x61\xc2\xfe\x22\x45\x54\xab\x90\xfb\x84\xe3\x54\x75\x99\x4d\x33\x8c\x9a\x30\x94\x1b\x32\x0e\x0f\xfd\xa4\xc8\x71\xab\x3f\x53\xaf\xca\x5a\x8d\x0b\xa6\x1f\x0c\x2a\x15\xa9\xa9\x99\x90\x10\xb3\x95\x19\xb4\x2e\x06\x3e\x10\x8d\xca\xb5\x42\x4c\xca\xf5\x47\x31\xdf\xb3\x52\x80\xe7\xd3\x54\x13\x91\x0b\xa3\x72\xb5\xd0\x0a\x3c\x05\x81\x12\x0f\x31\x03\xc5\xc4\x93\x96\x6e\x73\xa6\x21\x68\x76\xe0\xb9\x20\x6b\x57\x54\xde\xd5\x2c\xb4\xb4\xcb\x14\xf8\x75\xfb\xc2\x3b\x56\x6d\xed\x33\xe2\xf0\x8d\xf7\x3d\x1f\xac\xdb\x76\xeb\x81\x44\x72\x88\x11\xd6\x4e\x78\x7a\xca\x84\x75\xb3\x51\x47\xd3\xd8\xd7\x1e\xd8\xdc\xbe\x6b\xce\xf8\x87\x9e\x7b\x4a\x79\x8e\x6a\x81\x9d\x4d\x8b\x16\x3f\x40\x4c\x61\xd8\x8f\xef\x1c\xb7\xa2\x47\xdd\x35\x93\xaf\x9d\x8c\xbe\xea\x58\x80\x96\xf9\x83\x1b\xca\x8b\x3e\xbd\xe7\xe6\x5f\xad\x9b\x34\x9e\x18\xc5\x97\xeb\x36\xfd\x42\x9b\xf9\x03\x80\xfe\xce\x30\x03\x58\x80\x17\xdc\xab\xdd\x7a\x99\x46\x10\x67\x8d\x7a\x5a\x5c\xf6\x84\x14\x9e\x4b\xc4\x78\xdc\xd1\xc8\x3b\x31\x8b\xba\x7e\x8b\xab\x31\x1a\x63\x0b\x87\x63\x26\x90\xba\x14\xa9\x30\xae\x87\x89\x09\xf5\xce\x34\x91\x8e\x1c\x27\x6e\x88\xc7\xb7\xbc\xc9\x4a\x68\xaa\x24\x41\xf6\x44\x53\x2c\x50\xe4\x2b\x3b\x2d\x72\x90\xae\x4e\xae\xa0\xc6\x25\xb7\x53\x77\x77\x7e\x92\x75\x9c\xa6\x6c\x26\x9d\xfc\xd0\xb9\xd8\x78\x3c\xc7\x58\x01\x1e\xe8\xca\x50\x56\x6e\x4c\xc4\x03\x84\xa1\x2c\x60\x4c\x5c\x64\xac\xb1\x67\x8a\xa6\x2c\x10\x6e\x75\x19\x81\x91\x0c\x35\x1a\x79\x3c\xc1\xc8\xb9\x13\xe4\x2e\x2a\x10\x31\xfe\x9c\xe2\x76\x09\xda\x18\x63\xdc\x22\xd2\x45\xe5\x59\x24\x65\x81\xef\x23\x29\xeb\x72\xed\x5e\x94\x89\x7d\x6e\xd6\xba\x1b\x2f\xce\xcb\xce\x9c\xd1\x34\x91\x2c\xc3\x04\xed\x14\xb8\xfb\xfc\x69\x76\x2e\xfb\x26\xc6\x3a\x9f\xad\xcd\x69\x79\xf4\xd4\x3e\x4b\x27\xe2\x4e\x28\x58\x6c\x41\xc5\x49\xa7\x46\x44\x9c\x1e\x9c\xff\xc9\x85\xea\x2e\xe2\xf4\x6c\xbe\xba\x79\x7a\x14\xa0\xde\x1a\xac\x45\x88\xa6\x6e\x0b\x3b\x1e\x3f\x33\x44\x65\x8b\x28\x1b\x49\xdb\x26\x05\x02\xc5\x86\xda\x14\xbf\x61\x11\xc0\x57\xa5\x58\x7f\x37\x13\x12\x10\xfa\xfc\xd4\xff\x63\xef\xcd\xc3\x9a\xba\xd2\xc7\xf1\x73\xee\xbd\x59\x58\x4d\x42\x42\x58\x64\x09\x11\x22\x44\x40\x08\x21\x20\x20\x6a\x15\x29\x2a\xb5\x56\x11\x50\x29\x82\x0b\xa2\xa8\x88\xa8\xa8\x48\x91\x2a\x22\xa2\xc5\x05\x15\x37\x4a\x11\xa9\xa5\x18\x30\xa2\xc5\x5d\xdc\xad\xc5\xa5\xca\xd8\x8e\x5d\xa7\x63\xb1\xb4\xb5\x4e\xdb\x71\x90\x1c\x7e\xcf\x3d\xf7\x66\x63\x71\xfa\x5d\x3e\xcf\xf7\x9f\xdf\xf3\x4c\x87\x3e\x7d\x72\xcf\x79\xb7\xf3\x9e\xf7\xbc\xeb\xf3\xfc\x2f\xde\x81\x13\xe1\x32\x74\x18\x5d\x47\xf7\x51\xdb\xe5\x1b\x77\x6f\xff\x2e\x20\xbe\x8c\x81\x24\xe4\x4d\xad\x1b\xe6\x85\x96\xa2\xfd\xa8\x1a\x65\xc3\x3c\xe8\xd2\xf3\x2f\xc8\xf9\x99\xc6\x25\xa3\xa7\x93\x12\xf5\x9a\x99\xef\x44\xbf\xa0\x21\x13\x2a\xd5\x49\xa0\xc8\xd6\x72\x66\xbe\xc4\x11\xb7\x52\x71\x65\x70\x61\x9b\x8b\x36\x4a\x00\xfb\x94\xd6\xba\x0a\x9b\x38\xb6\x4c\x8d\x0b\x94\x30\x0e\x10\x8e\x50\xcb\xc7\x13\xc1\xac\x18\x5c\x98\xea\x68\xb5\xd9\xa0\x43\x0d\xc3\xb6\x0c\xe2\x99\x91\x49\x2f\xa0\x13\xea\xfa\xba\xed\xcf\xb3\xc4\xa6\x77\x0a\x2b\xec\xe1\x97\x59\x2d\xad\x98\x27\xe8\x01\xea\x42\x2f\xd0\x35\x68\x73\x71\x77\x75\xed\x0e\x7c\xd7\x61\x9e\xf0\x7c\x31\x4f\x7c\x40\x30\xd8\xf6\x6a\xbe\x68\x87\x04\x6a\x87\xab\x74\xee\xcc\x35\xe7\x67\x1c\x72\xc2\xf2\x89\x3e\x4e\x32\x69\x87\x56\x26\xc0\x77\xbb\xbf\x63\x87\xd6\xdf\x82\x7b\x21\x50\xd9\xa8\x90\x09\x45\xc7\x39\x36\x52\x21\xad\xad\x5c\xfc\x85\xa2\x46\xd2\xf9\x7f\x87\x81\x70\x80\xab\xeb\xd5\x8c\xed\xee\xee\x67\xa6\xde\x2b\x98\x4d\xc5\xf4\x73\x6f\x51\x0c\xff\xf1\xfc\x41\x4f\x3c\x7f\xf0\x5d\x56\x06\x86\x98\xcb\x80\x8c\x91\x01\x19\xbf\x43\xeb\x8e\xe7\x0f\x3a\xf5\x9e\x3f\x28\x73\xec\x38\x2e\x91\xd1\xa7\xda\x95\x21\xdb\x50\xa8\x6c\x0c\x70\xc4\xa5\x1b\x0a\x93\xa0\xe0\xc1\x83\xae\x34\xd9\x44\xb6\x43\x98\x17\x93\xec\xaf\x4a\x88\x85\xd1\xc4\x48\x8b\xf9\xb8\xb1\xfe\x24\xa7\xcc\x40\xa2\xe1\x8c\x08\x7d\x65\xbc\xe3\xfb\x91\x25\x6a\x2d\x4b\x98\xee\xd5\xb4\x54\x91\xa7\xcd\xe8\x44\xb2\xbe\x6f\x5f\x20\x04\x6e\xc0\xd7\x90\xdf\xda\xdb\xfb\xed\x1a\xa8\x55\xa8\x74\x12\x86\x38\x32\x46\xeb\x89\x1e\x6a\x61\xb0\xa1\xc5\x66\x1f\xdf\xb7\x3b\x54\x36\x0e\x71\xa4\x1f\x45\xb4\xda\xfb\x0b\xee\xed\x01\x64\x65\x00\x47\x77\x4e\x3f\x32\x32\x80\xb7\xdb\x68\x4a\xaa\x7b\xe3\xcd\xe9\xe2\xb4\xe3\x79\xa8\x7e\x78\x1a\x53\x3f\x9e\xef\xc1\x81\xda\xa1\x2a\x9d\x23\x83\xb7\x57\x30\xee\xa1\xe9\x60\xec\xa1\xd9\xc7\xe9\xed\x01\x95\x8d\xde\x8e\xb8\xa9\x66\xa3\xb3\x03\x6e\x92\xd9\xe8\xed\xf1\x17\x9d\xdc\x03\x93\xa0\x7f\x77\x37\xb4\xef\x87\x06\x03\x39\xbd\x8d\x03\xe8\xcc\x88\x40\x82\xf8\x9e\x4e\x2a\x86\xe7\x8b\xcf\x47\x34\x38\xc0\x66\x80\x52\x56\x1d\xc6\x52\x2f\xb3\x1a\x2f\x6d\x50\xa0\x36\x4a\xa5\x53\x32\xc4\xd0\x04\x43\xed\xa8\x40\xed\xd0\x87\x8d\x01\x52\x7c\x18\x68\xc5\x31\xc2\xb1\x43\x3b\xa2\x6f\xc1\x57\x93\x00\x4f\x28\x13\xd8\x58\x29\x1b\x47\x43\x65\x63\x48\x00\x2d\x0b\x0e\x3e\xce\xd8\x1a\x1a\x2a\x14\xe1\x4a\x2f\xd0\x68\x43\x09\x45\x8d\xf0\xff\xb4\xf8\x6b\x00\x2a\xfe\xf7\x22\xb0\xf0\xbe\xf4\x7c\x55\x2d\x18\xf7\x51\xbf\x72\x35\xb6\xa7\x93\xdc\xc6\x69\x07\x72\x10\x08\x22\x40\x1d\x53\x15\x86\x7d\xb7\x86\x92\x30\xb3\x5a\x30\xad\x7f\xa0\x36\x5c\xa5\x53\x30\x34\x55\x05\x43\x6d\x64\xa0\x76\xc8\xc3\x46\x3f\x29\x4e\x47\x66\x6b\xc3\x8e\x87\x7a\x70\xf9\xca\xc6\xe1\x8e\x1d\xda\xe1\x81\x8d\xa1\x8e\x1d\x5a\xae\xa0\xdf\x7a\xb1\x28\xa8\x6c\x1c\xee\x27\x14\x1d\x27\x05\x5e\x8e\xf4\x2b\x3e\x54\xc8\x96\x8e\x59\x93\x34\x69\xfb\x29\x17\xd3\x3a\x0a\xb5\xe2\xbf\x58\x34\x36\xd0\x80\xd4\x81\x8b\xc7\xac\xfa\x92\x74\xa0\x1a\x32\x4e\x71\x6f\x72\x42\x10\xdb\xd3\x49\x45\x60\x7f\x56\x32\x3b\x6b\x99\x96\x4d\x7b\xc3\x64\x21\xa1\x95\x94\x7e\xdc\x09\xd9\xbe\xcf\x3c\xdc\xbe\x93\xe9\xfe\xc4\x33\x4c\x7f\x69\xa4\xd8\x39\xcb\x56\xc2\x46\x28\x0e\x0f\xd7\x0a\x45\x8d\x36\xa2\xf0\xf0\x46\x7b\x3b\x36\xef\xc5\x20\x58\x02\x99\x5c\x0d\x65\x6a\x99\x04\xda\x32\x92\x14\x3b\xe7\xbb\xb4\x6b\x97\xd1\xe8\x12\xf8\xad\x7e\x16\x59\x86\xac\xa1\x18\x7a\xa0\x9b\xa8\x03\xe9\x23\xea\x86\x0f\xaf\x28\x85\xfc\x0a\x78\xa7\xa6\x1c\xb9\xd9\x7c\x7e\xb1\xed\x09\x80\xc0\x0d\x89\xc9\x66\x83\x1f\xcb\x8e\x1d\x08\x44\x5b\xc3\x84\x95\x61\xa4\x63\xa3\x83\x5d\x47\x13\x07\xfb\x66\x38\x56\x56\x4a\x7c\x21\x3b\x70\x84\x22\x76\x76\x2f\x21\x65\x4c\x5d\x5b\x61\x13\x10\x38\xe0\xb2\x4f\x36\xab\xc5\xc4\x1e\x06\x48\x47\x4a\xc2\x84\x57\xdc\x4e\x7e\x5a\x7d\xe1\xce\x67\xab\xe0\x05\x7d\x19\x19\x83\xa2\x7f\x82\x76\x1b\xff\x73\xe8\xd7\x2d\x3d\x20\xe1\x93\x7d\x07\x3e\xcc\x87\xbf\xed\x29\x42\xb6\x82\x17\x37\xde\xfb\x6e\x6d\x2c\x63\xcb\xdf\x00\x80\x93\xca\x3d\x03\x84\x40\x02\x66\x9a\x65\x95\xb0\xfd\x3b\x44\x81\x8d\x0e\x7c\xa3\x97\x9c\x1d\x97\x67\xc3\xba\xdd\xa4\xec\xb8\x3c\x66\xb6\x89\x8d\xf0\x38\x5f\x28\x12\xd3\xb2\x66\x6d\xa0\x38\x2e\x01\xe3\x0e\x32\xb8\x80\xc5\x04\x4f\x85\x73\xf0\x42\x44\x1a\x39\x74\x50\xcb\x24\x37\xea\xad\x39\x56\xe4\x90\xdb\xf5\xf6\xa4\x55\xf7\x17\x13\x88\x54\x4e\x73\xf7\xe3\x69\xe8\x47\x3f\xaa\xa5\x2b\x8e\x74\xcd\x80\x12\xdf\x97\xd1\x5c\x65\x79\xb9\x71\xa6\x1f\x27\x13\xd8\x01\x21\x98\xd2\x67\xa6\x9f\xd6\x3e\xb0\x71\x10\x0d\xab\xa8\xbf\xd1\x7e\x0e\x7d\x46\xfb\x09\xfe\xdb\x68\x3f\x99\xc4\x7c\xa8\x9f\x92\x48\xed\x3d\xcf\x8f\x7a\x44\xc3\x45\x32\x34\x34\xde\x9b\x8b\xfb\x52\xb1\xbf\x3b\xd3\x04\xa2\x08\x2a\x0d\x77\xa7\xe1\xaa\x1c\x62\x22\x32\xfd\x52\x10\x91\xd8\x2f\xdc\x68\x33\x44\x48\x5b\x5a\xff\x8d\xae\x03\x9c\x4d\x4b\x5a\xcf\xec\x7b\x1e\xfb\xa5\x7d\x9f\x2b\x93\x64\xf9\xd0\x8e\x67\x96\x7a\x1b\xf1\x35\xe3\x84\x14\x7b\x94\x84\x16\x1e\x25\x13\xbe\xf6\xf4\xa9\x34\xbe\x15\x1a\x3d\x1d\x71\x5d\x8c\x81\x51\xb4\x2d\x2a\xb6\xc7\x11\xa1\x46\x4f\x17\x36\x5d\x69\x60\x2e\x0d\x80\xab\x39\xe7\x5c\xfa\x62\xda\x9b\x93\xfd\xdd\x89\x14\xd3\x2f\x9f\xe7\x8b\x7b\x47\xd3\x3a\x3c\xab\x77\xc7\x7c\x09\xd9\xa1\x95\x05\x6a\xfd\x55\x3a\x57\x06\x57\x45\xb0\xa1\x53\x32\x9b\xed\xef\x04\x95\x8d\xee\xd2\x0e\xad\x3b\xf3\x06\x64\x6b\x4b\x0c\xad\xa4\x83\x68\x76\xbb\xd3\x4a\x7a\x90\xc4\x0a\x8b\xa3\x04\xb7\xa7\xe3\xf6\xe9\xa4\x6f\xd6\x42\x7a\x20\xf6\xf6\xe9\xaf\x7f\xe9\xcf\xce\x9f\x7e\x7f\xfe\xd3\x2f\x7f\x5e\xec\xc7\x3a\xe8\xdd\x6b\x7f\x1e\xfa\x0a\xdd\x81\xc3\xa0\x0f\xf4\x86\xbe\xe8\x3e\x71\xad\x0f\x41\x98\x39\xde\x19\x9c\x76\xdc\x3b\xda\x9c\x1e\x02\xb3\x0e\xfc\x03\xd1\x83\xed\x1c\xdd\x3f\x3d\xcc\xfb\x49\x63\x7a\x58\x91\x8e\xcc\xf1\x74\x14\x0c\xd0\x99\xdf\xd4\x47\x7a\x20\x7a\xf4\xdf\x47\x5a\xd6\x0f\x2d\x06\xe8\x20\x0d\xeb\xfb\xd0\xe0\xff\x9f\xa1\xf0\xff\x66\x86\x02\xc7\xec\x2c\x8a\xb0\xd6\x09\x02\xdb\x5f\x4d\x7b\xad\x3c\x50\x1b\xa8\xd2\xb9\x31\x82\xe8\x1b\x0c\xb5\xc1\xbd\x78\x81\x95\x8f\x14\x2b\x1f\xec\xf2\x75\xc4\x2e\x5f\x33\x0e\xa9\xa0\xb2\xd1\x85\x66\x8b\x9d\x73\x78\x78\xa3\x8f\x27\x3e\xa8\x52\xfa\xa0\x36\x8a\x86\x09\x45\x8d\x42\xc9\x5f\x66\xdc\x5f\x3e\xb4\xbd\x19\xfa\xd1\x5f\x38\xbb\x16\x3c\x26\x76\xf5\x63\x8b\x72\xcc\xce\x2e\xcd\xf7\x21\x60\x38\xd8\xfa\x6a\xde\x6b\xbd\x02\xb5\x01\x2a\xdd\x60\x86\x7e\x43\x99\x1e\xa8\x16\xb2\xe0\x4c\x9b\xa4\xcc\x68\x35\x6f\xa8\x6c\x54\x3a\x76\x68\x95\x16\x12\x12\x4c\xbf\x7d\xec\xf0\x3c\x3b\xfc\xf6\x39\x4e\x5a\x0d\x72\xc4\xd4\x53\xe2\xfb\xec\xaf\x09\xcd\x5f\x3b\xdf\xbd\x84\x69\xd0\x5f\x38\xe6\x46\xf9\x22\xa6\xf4\xbd\xe3\xa2\x7a\x3a\xa9\x72\x9e\x2f\x70\xc5\x2f\xa2\xdd\x06\x4d\x47\x76\x68\x05\x02\xad\x1d\x6d\x70\xdb\x92\x1d\xcc\xb3\xd8\x99\xec\xd0\x49\xc4\x56\x84\x1d\x73\x21\x78\x63\xef\x81\x87\x85\xf7\x60\xf0\xc3\x46\x2f\x69\x87\xd6\xcb\xc2\x67\xe0\x00\x95\x5a\x47\x46\xd2\xd4\x50\xd9\xe8\x35\x58\x28\x6a\x12\x48\x70\x3f\xa3\xa1\xc2\x26\x2b\x67\x22\x3c\x3c\xbc\xd1\x21\x00\x87\xac\x41\xa3\x44\x8c\xef\x42\xad\xb3\x50\xeb\x1a\xae\x25\x44\x8c\x7b\x30\x54\x15\x4c\x89\x24\x6c\xaa\x84\x3b\x54\x79\x02\x07\x99\x5a\xe6\x33\x44\xee\xc5\x1b\x88\x6e\x51\x0d\xcf\x1f\xc1\xf0\x6a\xb4\x03\x7d\x94\x7d\x6c\x6e\xc2\xb1\x74\xc8\x87\x76\x7c\x7d\x38\x71\x45\x8c\xfe\xd3\x7e\xe4\xa3\x65\xfd\x18\x06\xb9\x09\x5a\xd4\xf2\x2d\xda\x8c\x16\x3b\xc9\xab\xa4\x72\xe8\x04\x79\xd5\x5f\xe9\xe3\xe1\xd3\x7e\xdf\x3d\x11\x3d\x9d\x64\x11\xa7\x9d\x95\xb3\x72\xd6\x5e\x27\xad\x3b\x9a\x84\x90\x71\xaa\xea\x78\x5c\xa9\xd0\x0e\xc7\x65\xfa\x95\x33\xe7\x87\xfd\x48\x16\x87\x09\xa4\x8b\x25\x1d\x4d\x1c\xb1\x21\x55\x1c\x0b\x19\x23\x5c\x42\xa9\x0d\x6d\x7c\x2a\x99\xe6\x28\x5c\x92\x99\x4c\xc1\xc3\x39\x76\x36\x38\xc3\x44\xc8\x64\x98\xd0\x0f\x1c\x4f\x9a\x4e\xf4\xd1\xc4\x8e\x76\xb6\xbd\xce\x40\xd6\x44\x44\x65\x19\x9c\x2c\xd5\x7f\x4f\xb8\xda\x57\xef\x5f\xb0\x5b\x35\xea\xf0\x44\x08\xa1\x15\xfa\x16\x75\x7d\x18\xd4\x97\x5c\x8a\xfd\x23\xe1\xfc\x1d\x75\xfb\x43\xb7\xbb\x79\xa1\xc7\xe8\x29\xfa\x0d\x3d\xec\xfb\xa6\x21\x80\xb4\xa7\x93\x42\xdc\x33\xc0\x11\xb8\x80\x10\xb6\x72\xc3\x81\xec\x60\x2a\x96\xf8\x2a\x3c\x65\x85\x8f\xdd\xab\x4c\x3f\xb1\x7e\xe6\x38\x43\x47\xa9\x2a\x1a\x42\x15\xb4\x37\x66\xa1\x68\x68\xcb\x55\x7a\x13\x56\x3b\x8b\xf8\x7c\x0f\x98\xd2\x8a\xfc\xdf\xda\x74\x6c\x6d\x76\xc2\x8c\x79\x0b\x8b\xa2\x9e\x61\x13\xfb\x7e\x60\xb8\xd3\x14\x52\xf9\xf2\x69\xcb\xd1\xc9\xee\x0d\xbe\x73\xde\xa5\x74\xb4\x29\x6b\x98\x4b\xcd\xc9\x04\x52\xe0\x0a\x82\xfb\xcc\xa5\x76\x0a\x6c\x74\x66\x9c\xa4\x78\xd8\xd2\x5f\x9f\x2c\x4d\xc3\x34\xd0\x3c\xe9\xaf\xb0\x65\xdd\x77\x5a\x03\xf5\x18\xc3\x44\x32\x74\xe2\xf9\x02\x47\xe0\x05\x02\xc0\x8c\x7e\x28\xe5\x19\xa8\x1d\xa6\xd2\xb9\x30\x32\xe4\x13\x8c\x27\x77\x48\x1f\x36\xba\x49\x71\x1f\x41\x39\x54\x36\xfa\x3a\x32\x93\x3b\xe4\x6e\x42\x51\x13\x87\x72\x64\x32\x83\xff\x22\x41\x07\x10\x8b\x01\x89\xfc\x4d\xbf\xb6\x75\x1f\xa2\x73\xe2\xfb\xea\x1d\x86\xfe\xed\xac\x85\x95\xd4\x87\x03\xfd\x99\x57\x4e\x0f\x7b\xd9\x54\x46\x43\xaa\x89\x43\x49\x07\xc2\x74\x00\x46\x0d\xe4\x79\x1a\x80\x79\x77\xfa\x35\xae\xfb\x32\x93\xb3\xb2\x2f\xae\x0c\x5f\x73\xd8\x59\x35\x49\x7d\xf9\x8a\x9d\x6c\xae\x0f\x1b\x07\x4b\x71\xb5\xb9\x37\xdb\xd8\x7c\x18\x1b\xa0\xd7\x71\x28\x47\x19\x9e\x34\xe9\x2d\xd4\xfa\x85\x6b\x7d\x98\xc7\xd1\x5f\x3e\x26\x86\xe9\xf2\x32\xe3\xbf\x0d\xc8\xd1\x2f\xe4\x19\x8a\x2b\xb2\x8f\xc7\x40\x22\x30\xd3\xf9\xb2\xec\xe3\x31\xfd\x1f\x22\xe7\x80\xc6\xc9\x92\xb0\xcb\x1a\xe7\xd1\xcd\x61\xf4\x5f\xd6\xbf\x88\x67\xbd\xcb\x80\x14\xc8\x80\x12\x4c\xef\xcd\x53\x3c\x7c\x63\xb0\x51\x5a\x69\x5b\x44\x21\x65\x86\x6f\xb8\x0d\xc6\x58\x4a\xbd\xe4\xcc\xbc\x0d\xad\x32\x5c\xab\xf8\x5f\x1c\xea\xde\x1f\x9e\x03\x71\xf3\x7e\x6f\x34\x07\x38\x98\xfd\xe3\x89\xeb\x95\x70\x7c\xc2\x03\x28\x41\x2e\x68\xb2\x33\xe6\x08\x5a\xab\x74\x42\xae\x1d\xb4\x53\x36\x0a\xc9\x0e\xad\x5b\xa0\xd6\x57\xa5\x93\x32\x42\x2c\x0f\x36\x4c\x1f\x31\xd5\x29\x35\xba\x48\x71\x9e\xbf\x27\x33\x46\x43\xeb\x83\x1b\x64\xb2\x69\x5e\x98\x32\x2e\x4c\xaa\x94\xd6\x93\xc9\xae\xe5\x0a\x71\x3c\xa2\x4f\x66\x17\x13\x21\x1b\x40\xa6\x0d\xd9\x5e\x4c\x9d\xd8\x1f\x7d\x25\xd9\x32\xfd\x0b\x97\x8d\x51\xfc\xbe\x72\xbc\x07\x00\x2a\xdc\xe8\x3f\x5e\xc7\xf6\xa6\x63\x93\xc2\x74\x02\x0e\x8e\x81\x0b\xac\x3a\xfa\xf5\x21\x33\x89\x62\xc7\x1d\x70\x33\x50\x67\x29\xa6\x80\xad\x29\x65\xcc\xdb\xc6\x96\xaf\x6c\xf4\x70\xec\xd0\x7a\x04\x9a\x1c\xca\x24\x6d\x2a\x38\x0e\xa6\x4d\x05\x0f\x26\x0d\x97\x23\xc0\x4f\xe6\xde\xa9\x63\xaf\xc4\x9f\x4d\x27\xd3\xe1\x64\x32\x6d\x3f\x16\x93\x79\x7e\x19\xae\x4a\x23\x67\xf5\xbd\xf0\x71\xae\x19\xee\x0f\x68\x45\xdf\x18\x86\x20\x30\xd4\x5a\x33\xd5\x09\x92\x0e\x63\x55\xb4\x65\x6d\xb2\x8d\xa1\xed\x20\x5b\x9b\x7c\x8d\x1c\xaf\xcf\x6e\x68\xe0\x34\xd7\xbc\xdc\xae\xff\x12\x16\x1a\xf2\x12\xc9\x38\x2a\x0e\x58\x81\x48\xb6\x1e\x9a\xb2\xea\x68\xa2\x70\x31\x34\x85\x8b\xa1\xd9\x6d\xec\x3a\x8e\xf3\x39\x34\x0d\x7b\xd5\x5e\xf7\xde\xa5\x81\xd8\x8f\x9c\xaa\x9b\xa8\x38\xb6\xfa\x19\x70\x70\x6f\x13\x29\xcf\x17\x58\xb3\x92\x1b\x08\x0a\x59\x9f\xc6\x30\x55\xa3\x8d\x0d\x13\xd8\xa6\xd5\x2e\xe9\x60\xc8\xcb\xec\x2b\xc2\xc3\x8d\xed\x0f\x88\x60\xad\x8d\x85\x14\x0f\x82\xca\x46\x9e\x63\x87\xd6\x93\x36\x1b\x69\x71\xe6\x09\x30\x1b\x03\xd9\x27\x2f\x8f\x7e\xf4\xcb\x7d\xb1\x9e\xb6\xc1\x6d\x6e\x19\x37\x87\xca\x93\x92\x88\x29\xb9\xc2\xe0\xee\x1b\x88\x8f\x50\xa8\x12\x5e\x3b\xf5\x2d\xb4\x82\x62\xf4\x9f\x9e\x17\x4f\x9a\x6a\xeb\xaf\xde\x6e\xeb\x27\xeb\x63\xdb\x27\x9c\x66\x7d\xc5\xbd\xcf\xda\x1e\xef\x2f\x2e\xd9\xb8\x8a\x72\xed\xc5\xcd\xff\x2c\xe5\x34\x77\xc5\xe1\xf7\x42\x03\xee\x07\xd4\x0e\xac\x59\xa9\x0e\x00\x05\x2c\x4d\x94\xaa\x46\x1b\xc3\xa0\xfa\x61\xc6\x89\xd7\x64\x7f\xe2\xcd\xcc\xcf\xb2\xb1\x33\xd0\x84\x7e\xe7\xb3\x01\x13\x7b\xa8\xd4\x7a\x30\x69\xa3\xde\x0c\x45\x94\xb4\x65\x6c\xc7\xdc\xd2\x3c\x7b\xa1\xa8\xd1\x6b\x28\x2e\x6c\x32\xa7\x88\x8c\x41\xd9\x5b\xe6\x89\x9b\xa7\xbe\x8a\x20\x0d\x3a\xe8\xf6\xf0\xd3\xbf\xdd\x43\x3f\x41\x0a\x5a\xad\x7c\x0f\x75\xed\xe9\x87\x22\x33\x75\x54\x1c\x8a\xda\xbf\xef\xc8\x87\xe5\x27\x92\xde\x22\x0b\x7b\x11\xa4\xeb\x12\x15\xf7\xb2\x19\xf7\xbd\x45\x99\x6c\x0f\x4c\x67\xb0\xa9\x57\x17\x4c\x9c\xe4\x60\xd3\x5f\x33\x4c\x97\x40\xad\x1d\x6e\xed\x64\xcd\x34\xc3\xb4\xc3\x65\xe5\x76\xc0\x4a\xa9\xb5\x16\xe8\x44\x4e\xc0\x8b\x52\x6a\x45\x81\x4d\xd6\xb8\xdc\xc7\x1a\x37\xa7\xb4\xe6\xe0\xff\x97\xb0\x1e\x61\x6b\xfa\x89\x24\xc0\xf9\x77\xb6\x6c\x1b\x15\x28\x15\x8a\xb4\x0e\xe1\xbd\x3b\x56\x92\x8e\xaa\x60\xb5\x50\x25\x14\xc8\xbd\x14\x66\x5d\x34\x45\x01\x61\x69\xd5\xcf\x22\xa2\x2d\xba\x69\x76\x57\x38\x2c\x84\x2a\xd4\x8e\x7e\x75\x66\xf2\x45\x05\x28\x13\xf7\xd6\x74\x06\xab\x80\xb1\xad\xa6\x76\x50\x60\xa3\xd8\x06\x77\xc4\xb5\x62\x5a\x56\xf1\x18\xa4\x9c\xcc\x3b\x6b\x3a\xe1\xb2\x79\x27\x60\xa5\x3c\xee\x68\xe3\xc4\x57\x36\xda\x89\x3a\x9a\xec\x70\x31\xa7\x1d\xc6\xc8\x8e\xc3\xe2\x62\xe3\x24\x14\x35\x0e\xc2\xa9\xae\xe2\x41\x8c\xfe\x06\xc2\x26\x1b\x5b\x63\xe7\x2d\x23\x36\x0c\x16\xf4\x0d\x16\x05\xcd\x7b\x71\x1e\x7c\x16\x19\x1d\x10\x9e\xa6\x35\xb5\xe4\x6c\x40\xcf\xd0\xaf\xce\x15\x0e\x0b\xb7\xe1\xde\x9c\x7c\x94\x49\x7d\x8d\xf3\x86\x27\xb1\xf2\x2a\x36\xd6\xac\x6b\x6d\x03\x1b\x85\x36\x4c\xfe\xb0\xc3\x43\xec\x5d\xa5\xdf\xb0\xd6\x0e\xc6\xb2\x71\xa1\x2d\x13\xd6\x06\x42\xed\x20\xfa\x91\x75\x9c\xe2\x5b\x39\xf6\x2e\x21\x37\x83\xac\x77\x39\xfb\xba\xaa\x5f\x23\xa3\x03\xc2\xd2\xfa\xd4\xb4\x63\x4a\xd3\x40\x32\x85\xed\x10\x78\xa3\x4c\xdc\x5f\xcd\x12\x4e\xf8\x3f\x06\xa7\x65\xc9\xbb\xb2\xe2\x59\xd4\xc8\x80\xf0\xb4\x99\xbd\xea\xde\x93\x4d\xc4\xc4\xc5\xef\x10\x70\x01\xa0\xea\x70\xff\xbe\x28\x53\x77\x6f\x0e\x63\x9e\xe9\x48\x02\x70\xec\x70\x07\x03\x5a\x25\x5a\x07\x43\x1c\x2f\x30\xc4\x78\xb5\x82\xf0\x46\x0e\x69\x38\xbd\x50\xa6\x96\x61\xb8\xa0\x4c\x22\xa3\x21\xe2\xc2\x53\xe8\x3c\x54\xa1\x95\x34\xf5\xe6\x5f\x46\xb9\x30\x1c\x9d\x85\xa7\xee\x62\xd2\xe9\xaa\x89\x54\xfd\x45\x22\x5a\x5f\x55\xad\x9f\x68\xa4\x19\x00\x94\x94\x8a\xeb\x05\x0b\xec\x03\x0b\xef\x7f\x19\x16\x6f\x98\x8a\x7e\x81\xb6\xe8\x14\x4b\xa1\x66\xe8\x80\x3a\x60\xfa\x6d\x9a\x3c\xf0\x59\x29\x6c\xa3\xe9\x83\x82\x4a\x91\x80\xa1\x0b\x01\x0a\x00\xc0\xf1\x28\x2b\x20\x02\x63\x98\x8e\x19\x8d\x76\x36\x1d\xb8\xf9\x8b\x8e\x10\xf0\x28\x3b\x65\x23\x61\x2a\x0b\xb6\x76\xec\xd0\x5a\x33\x5a\x8f\x0c\xc6\xbe\x4e\x31\x0d\x9a\xc0\x4e\xc8\x3e\xe4\x99\x89\xb5\x32\xcf\x21\x1a\xb1\x63\x04\x14\xca\xbd\xb8\x05\x44\xcc\xb9\x53\x68\x36\xfa\x03\xfd\x72\xee\xe4\xa5\xdb\xda\x47\x67\x61\x1d\xac\x21\x32\xbb\xe2\x3e\x7f\x58\x56\x40\xd8\xe7\xb1\x7d\x7b\x3a\xa9\x28\xae\x18\x38\x00\x4f\x90\xc1\x5a\x5c\x4c\x52\x88\xc1\xad\xe3\x6e\xd5\xa1\xb5\x0e\x34\x74\xa1\x12\x4b\xb0\xe3\xdd\x0a\x2a\xb5\x2e\xcc\x09\xb6\x11\x34\xda\x09\x70\xe7\x57\x2f\xa8\x6c\xb4\x12\x0b\x45\x27\x38\xe4\x20\xa1\xd4\x9d\x36\x39\xed\x18\xf3\xca\x5d\x8a\xe7\x03\x71\x06\xd9\x9b\x35\xe2\x51\x05\x40\x5a\xdd\xc8\x15\x72\xae\xdc\x8b\x30\x24\xb5\xe2\x58\x6c\xf6\xcf\xed\x8f\x57\xda\x91\xd6\xba\x72\x57\x7e\xce\xf7\x0f\x3b\x5b\x76\x6f\xad\xd9\xbd\xb7\xa6\x74\x0f\x21\x87\x76\x30\xa0\x5a\x9c\x27\x81\xcd\xff\xe9\xdc\x71\x04\x0e\x85\x36\x9f\xde\x3b\xfe\xa9\xec\x87\xd6\xc7\x18\x9f\x82\x9e\x4e\x6e\x3e\x8e\xf3\x79\x81\x45\xcc\xf4\x17\xad\x48\xd5\xe8\x6a\x83\x1b\x1a\xd0\x82\xa7\x23\x3d\x1d\xd9\x4e\x63\x5a\x3b\x63\x33\x79\x67\x47\x7c\xad\xb8\xb3\xd5\x08\x4c\xf3\x64\x3c\x18\xd8\x8e\x69\x20\xef\xce\x16\xc8\x32\xfe\x00\x5b\xc6\xa9\xe2\xe9\x2a\x14\x35\x02\xa6\x9b\x5e\xc8\x10\xcc\x02\x31\x2e\xe4\x50\x09\xc5\x86\x66\x42\x1a\x81\x8c\xfe\x2f\x34\x47\xe0\x50\xe8\x55\x76\xea\x9b\x79\x39\xcd\x0f\x3f\xf9\x31\x6d\xe9\x8f\xdf\x3f\x3d\x07\xa5\xab\x37\x6d\x6b\x3b\x0d\x77\x3c\xfa\x86\xc8\x7c\x79\xf2\xbb\x35\x59\xf0\x31\x72\x69\xfa\xf4\xc8\xe1\xfb\x77\x50\xd7\xf2\x05\x70\x4c\x31\xc6\x6b\x49\x4f\x27\xb7\x8c\x2b\x06\x9e\x60\x18\x58\x0a\x9a\xdc\x99\x4e\x5b\x8d\x43\xac\x3a\xb4\x83\x98\xa9\x61\x8d\x4a\x96\x51\xfe\x4c\xb6\x89\x04\xe7\x98\xd0\x8c\x52\x18\x19\x85\xa7\x3c\xd9\x75\x34\x06\xd0\x9c\x92\x09\x45\x3a\x2e\xe9\xee\xa3\x64\xab\xcc\x5c\xc3\xb5\x22\x91\xd6\x29\x1c\x34\x2a\x87\x08\x45\x27\x00\x8f\xeb\x20\x76\x35\xf1\xcb\x51\xaa\x0a\x84\x06\xeb\xd8\x80\xa1\x0f\x33\x39\x8b\x61\x1e\xce\x3c\xf4\x5c\xf2\xe4\xf6\x82\xaa\x48\x3b\x1e\x75\x7c\xc1\x8a\x65\x0b\x9a\x6f\x5f\x58\xbf\x3f\xe0\xad\x13\xf9\x0f\x7e\x6a\xd9\x54\x5e\xb9\x95\xdc\x76\x08\x3d\x25\x64\xd0\x0e\x0e\x9f\x34\x2d\x7e\x2a\x6c\x7e\xb9\x69\xf7\xbb\xeb\x37\x42\x15\x3a\x7b\xe3\xd2\xf4\x85\x8b\x13\xa0\x2f\xb4\xbe\xf3\x99\xf6\xb6\xfc\xbb\xcb\x80\x89\xdb\x72\x8b\x38\xb7\x80\x1f\x00\x0e\x86\xd1\x33\x3c\x09\xc5\x24\xb7\x98\xa0\x08\x80\x16\xa1\xfc\xd8\xd9\xff\x2a\x7a\xf4\x67\xe3\x3e\x98\xc6\x25\x32\x56\x2f\xcf\xd2\x3d\xb8\x70\xf3\x21\x41\xb4\xdd\xbf\x76\xfe\xec\xbd\x1d\x85\xe9\xc7\x67\x73\x54\x71\xf1\x97\x0f\x97\xb5\x38\xf3\x55\xe8\xfe\x7b\xf9\xab\xde\x85\xd7\x90\xef\xf5\x2b\x77\x3f\xdd\xb1\x65\xd7\xb6\xf5\x99\x6b\xc2\xc7\x30\xf7\x5a\x7c\x4f\x27\xe7\x3e\x95\x42\xeb\x0e\xc3\xfe\x3c\x89\x3b\x94\x3a\xaa\x82\x99\xe1\xd0\x72\x4f\x92\xd9\x9c\x8d\x74\xc7\x4f\x39\xba\xf8\x74\x7b\x6b\xe6\x0a\x2e\xf5\xa8\xbd\xe9\xc2\x35\xb4\xce\x9e\xb3\x6d\xfb\xd6\x1c\x28\x7b\x1a\xbf\xe5\x0d\x4a\xa4\xf0\xde\xb7\xb1\x25\x9c\x2f\xc9\x9f\x73\x03\x72\x69\xb4\x6f\xb6\xc2\xd7\xe7\x24\xed\xa8\xdb\x3f\xc4\x8b\xc6\x17\x15\x50\xdf\x72\x6e\x81\x21\x16\xf8\xba\x43\x37\xa6\xf7\x88\xb0\x77\xce\x42\xec\xdc\x97\xc5\x5f\xa3\x96\xea\x93\x97\x4e\x69\x5b\xfe\xf9\xe4\x56\xdb\x8d\xaf\xab\x36\xcc\x3f\xbd\xd0\x9f\xa3\x9a\x30\xe9\xf2\xe1\xb2\x93\x2e\x7c\xe7\xe3\xdb\xbb\x68\x7b\x18\x1e\x2c\x2a\xc6\xb8\x85\xbd\x16\xcd\xe0\x86\x36\x50\x4a\x6a\x26\x70\x07\xc0\xc1\x14\x9f\x37\xee\x24\x93\x63\xa4\x7c\xe4\x5e\xbc\xf8\xa3\x6d\x17\x1e\xdd\x7c\x27\xab\x4e\x5b\x83\x6e\xed\xc9\x83\xe1\xeb\x73\xf6\x1e\xa2\x04\x13\xf7\x6d\x6a\x0e\xb7\xf1\x29\x49\xdf\x4d\x5b\xc2\x30\xf0\xe2\xae\xda\xf8\xc9\xb1\x4c\x9f\x9a\x9e\x0e\x9e\x12\xf7\xb9\x03\x51\xb8\xb3\x92\x0b\x74\x90\x61\xd9\x31\x32\x4d\x2d\x94\x59\xe3\x97\x66\x48\x54\xc4\x9b\x23\xa7\x86\x10\x2f\x17\x2d\x7d\xac\x6b\xbb\x74\xed\x36\x9a\x1a\x1e\xff\x66\xd9\xe2\x71\x44\xa5\x6b\x16\x94\x12\x5e\x70\xdb\xcb\xdb\x45\x39\xdd\x34\x8b\x2e\xdc\xbe\x75\x99\xdc\x8d\x42\x91\xa8\x0b\xd7\x4f\xd8\xf7\x74\x72\x23\xa8\x38\xe0\x06\x80\xb1\x3a\x4d\x6c\x62\x0e\xbb\x8b\xa9\x4c\x6d\xc3\xbc\x9c\x36\xdd\xc5\x0b\x57\x6e\xa2\x5b\x66\x95\x6a\x7a\xcd\xfa\xb5\x90\x82\x6a\x9a\x1b\xd7\xaf\x11\xe1\x4c\xc5\x1a\x7e\x9b\xf4\x74\xf2\xe6\x71\x9a\x81\x33\x00\x86\x22\x24\xcb\x03\xa0\x66\xca\xa3\xae\x35\x2f\x5a\xb2\x38\x4b\x77\xfb\xd2\xb5\x9b\xfa\x70\xa6\x44\xea\x65\x5b\x51\x2e\x23\x57\x17\x6e\xdf\xba\x0a\xfd\x99\xfe\x8c\x3d\x9d\x5c\x2d\xee\x6b\x61\xb1\x9e\x11\xdc\x28\x88\xab\x9b\x46\xea\x32\x72\xda\x9a\x2e\x5c\xbc\x7c\x4b\x7f\x89\x29\x70\xd2\x87\x17\xe5\x1b\x04\xe6\xf6\xa5\xc5\x86\x3a\xa7\xfc\x9e\x4e\x4e\x35\xe7\x16\x8d\x3f\xd3\xcf\xcb\x91\xe9\x11\xc7\x74\xf4\x0a\x55\xcb\xd4\x32\x09\x8e\x27\xe4\x1f\x87\x53\x3b\xf2\x7e\x9c\x15\x93\xd4\x36\x1b\xe9\xd1\x3f\xa0\xf5\xb3\x7b\x7f\x43\x85\xc4\x28\xf4\x29\xba\x82\x3e\x41\xe5\xc4\xe3\x1f\xe0\x34\xdd\x70\xbf\x83\x8a\x40\x74\x1d\x3d\x45\xff\x40\x9f\xfe\xe3\x87\xea\x44\xf4\x01\xfa\x08\xbe\x87\xf7\xa2\xef\x8a\x66\x2a\x85\xa6\x05\xdb\x8d\xce\x34\xf4\x8a\xd9\x48\xe6\x09\xb2\xe1\x18\xe8\xf5\xf8\x68\x54\x5d\xed\xa7\x5f\x5c\x3d\x5b\x5b\x8f\xb4\x04\x57\xff\x02\x75\xa2\x76\x42\x0e\x07\xc1\x61\x93\xcb\xe2\x1e\xdf\xfa\xec\xe1\xfe\xdd\x15\x31\xfa\xa7\xd0\x17\xf7\xc7\xe9\xe9\xa4\x10\xa7\x19\x88\xc1\xa8\x51\x5e\xa4\x35\xc7\xc1\xce\xda\xda\x01\x90\x12\x47\x60\xb3\xd4\x86\x18\x4c\xda\x50\x00\x82\xcc\x24\x48\x0a\xf8\x0b\x92\x04\x0e\x20\x5a\x09\x9c\xa2\x95\x42\xa0\x72\x0a\x7c\x3b\x65\x96\x50\x04\xa5\xe1\xb8\x43\x8a\x2a\x68\x38\xd3\x5b\xa6\x97\x98\x89\xa8\x91\x48\x9d\xb3\xf4\x9b\xe6\xfb\xad\x37\xee\x71\x04\xb5\xb5\xdd\x39\x45\xb9\xdd\xf0\x06\x2b\x4d\xbb\x70\x0f\x9c\x9e\x4e\xaa\x12\xd7\x48\x02\xd3\x1a\x98\xcb\x02\x19\xbd\x86\x2f\x99\x89\x6a\x32\x73\x32\x16\x1e\x47\xab\x5b\x3f\x23\x9b\x77\xee\xd4\xdf\x2e\xca\x5f\xbd\x91\x36\x3a\x50\xce\xcd\x2b\x44\x04\xc3\x8f\xac\x9e\x4e\x6a\x0e\xee\x79\x0d\x1c\x42\x42\x35\xea\x00\xa8\x0e\x31\x72\x05\x13\x0b\x8f\x46\x32\x36\x1e\x93\x79\x0e\xc9\x6a\x6b\x39\xda\x04\x6d\xbf\x2f\xf9\x6e\x69\xda\x7c\x5d\x66\x59\xe5\x9d\xcf\xda\x6e\x7f\xfd\xf4\x5a\xf3\xcf\xd7\x8e\xa1\x3f\xd0\xbf\xd0\x43\xb8\xad\xe2\xbc\x23\xdf\xb9\x69\xdb\x87\x57\xc7\x4d\x28\x1a\xa3\xce\x5b\xb4\xa6\x6c\x4f\xe9\x86\xd2\x4d\x33\x8f\x4e\xfa\x3b\xb3\x6f\x62\x4f\x27\xb9\x87\xd5\x53\x86\x7d\x43\x8d\xfb\x4a\xc4\x32\x95\x44\xee\xc9\xce\x27\x93\xd0\x64\x49\xcc\x2e\x4a\xcf\x7c\x72\x7e\xc9\xc7\xd3\xc7\xa6\xbf\x1b\xf7\x02\x86\xe7\xec\x42\x37\x77\x6e\x9b\xf6\xd1\x9c\xd2\xef\xff\xfe\x1b\x54\xa6\x17\xf9\xd8\x0c\x7e\x67\x56\xf1\x7e\x6f\xdf\x6d\xc3\x06\xef\xaf\xdb\x71\x36\x69\x96\x22\xf0\xe0\x84\x8f\x0c\x35\xb4\x99\x9c\x22\x5c\xeb\x0c\xcc\xaa\x54\x2d\xac\xee\xde\xd5\xaa\x55\xcf\x22\x68\xdb\xb6\xb9\x6f\xc1\xaa\xd1\xba\x35\x55\xad\x32\x75\xab\x99\x54\x39\xae\x3b\x36\x9d\xed\x5e\x5b\x30\x47\x5b\x22\x5f\x5c\xe4\x4d\x54\x1c\xc2\xc6\x73\xfa\x09\x74\x76\xf0\xdb\x7b\x57\x8e\x2e\xe6\xc3\x3b\xf0\x65\xf7\x68\xa3\x4d\x4a\xea\xd0\x1e\x34\xf7\xbc\x51\x3f\x95\xe0\x1e\xfc\x66\xfa\x09\x1b\xbe\x72\xfc\xbf\x5e\xaa\x49\x64\xb0\xd0\x9f\x60\xfb\xb2\x15\xfe\x13\xd5\xa0\x27\xbd\xb5\x14\x6b\xad\x13\xb4\xc1\x49\x74\x11\x4e\x06\x35\x85\xf5\xd4\xef\xdc\xa9\xec\xb9\x67\x71\x31\xdb\x4d\x6e\xa6\xa2\xe0\x8f\xd0\x05\x3a\xdf\x44\x1b\xe1\x36\x6c\x3f\xde\x82\x5b\xd1\xaf\x1d\x2e\x6f\x57\x1a\x94\x15\x63\x6b\xeb\xdb\x68\x53\x92\x08\x82\x85\xe8\x20\x4a\x3f\xcf\xe6\xd5\x73\x33\x71\xef\x32\xac\xad\x64\x9e\x42\x09\x8f\xc9\x09\xe4\xca\xe4\xce\xc6\x94\xb7\x6b\xb0\x88\xf0\x26\xa0\x4f\x2b\xf2\x87\x4f\xee\xa0\x49\xbb\xd0\x83\xba\x1d\x5f\x5c\x6e\xbe\xd8\xc2\x69\x46\x53\x44\x42\x78\x17\xe3\x70\x71\x93\xfe\x1a\xd1\x5e\xb6\xdf\x38\x77\x83\x3b\x8f\x4a\x01\x2e\x58\xb2\x0d\xa3\x2f\x1c\xa5\xcc\xfa\xd8\x5f\x28\x97\x1a\xa6\x5f\x98\x26\x5f\x38\xf1\x47\xd5\x2d\x6e\xfe\xa7\x1b\x74\xa4\x9f\x0d\xdb\x3e\x45\x8f\x9c\x3b\x4e\x3f\x5e\x69\x4b\xf1\x77\xd6\x6e\xde\xb7\x6f\xab\x61\xfc\x45\xf2\xe4\xbf\xdf\x83\x95\x18\xab\x86\x47\x1d\x87\x7c\xe3\xa3\x98\x01\x18\xdf\x5c\xbf\xf1\xe0\xd4\x15\x40\x00\x7f\x00\xb8\x37\x70\xed\x30\xad\xe9\x21\x3e\x56\xbe\xd0\xbc\xcc\x03\x62\x1b\x58\xee\xc5\xf5\x87\x95\xfb\xb6\x43\x21\x14\x52\x76\xc6\x0c\xfe\x07\xe8\x5b\xb4\x61\x2a\xcc\x7e\xf0\xf8\x64\x13\x51\x10\xfc\xd9\xc1\xab\xf7\xd9\x24\x7e\x22\x45\x5f\x4d\x89\xd1\x3f\x09\x8f\x77\x00\x20\x81\xac\xa7\x93\x5b\x4d\xa5\x00\x0f\xa0\x00\x01\x86\x9d\x42\x55\x32\x49\x68\x9f\x3c\xfa\x21\x0a\x19\x74\x10\xcb\x54\x42\x99\x17\x97\xc3\x84\x69\x65\x30\x7c\xdd\xfa\xcf\x4e\xc2\xdb\x2b\x4e\x1b\x72\xe9\xf7\x67\x25\x56\x2f\xf9\x12\xbd\x70\xee\x01\xe8\x9f\x8e\xd0\xf6\x17\xf4\x2c\x67\x25\xd1\xc0\xe6\xd2\xc3\xdb\x9e\xd5\x2b\xf7\xd4\xaf\x2c\x35\xa6\xd3\xfb\xc8\x7e\x7d\x84\x26\x92\x54\x0b\xcc\x4c\xbe\x51\x59\x55\x8b\x7b\x45\xd6\xe0\x9c\x81\x41\xb4\xb4\x1a\x62\xc4\x04\x0f\xca\x20\xcf\x32\xb5\xc3\x18\x0d\xfe\xea\x53\x98\x82\x5e\xa0\x1f\x54\x16\x79\x1c\x66\x81\xdf\x9f\xd0\xd6\x18\xb4\x13\xc6\x11\x7d\x53\x37\xd8\x7e\x9e\x48\x4c\x45\x51\x29\x40\x04\x3c\x00\x60\xed\x75\x0d\x4e\x11\xd2\x98\x99\xeb\x6c\xd1\x51\xf6\xaf\x0f\xbe\xcd\xe5\xbb\x6e\xd3\x59\xdb\xe6\xfc\xf0\xf9\xd3\x96\x5d\xdb\xdf\xdf\x49\xed\x39\x5c\x56\x41\xc8\xa1\x2d\x0c\x3c\x5a\xf1\x9f\x9b\xf0\xc1\xe2\xc8\x23\x70\x18\xe4\xdd\x78\xa0\xbd\xe5\xfd\xfd\x95\xaf\x00\xa4\xa5\x94\x97\x80\x6d\x75\x80\x9d\xcf\xa1\x1a\xc8\x8e\xbd\x57\x41\x39\xf4\x51\x70\x79\x50\xee\x7c\xe1\xfb\x00\x27\xc7\x30\x48\x9c\x83\x76\x21\x83\x05\x9a\xef\x2e\xa0\x35\x2d\xe8\xfb\x68\x1b\x41\x28\xea\x6c\xe1\x34\x77\x17\x1d\xfb\xb8\xa6\x95\x5c\xd6\x5d\xfc\xf1\xf1\xcd\x9f\x93\x6b\xba\xe2\xc8\x73\x0f\x27\xe4\xe8\xba\xd9\x5a\x7f\x29\x00\x5c\x15\x15\x87\xb1\x50\xb9\x40\xa9\x4a\x43\x2f\xcf\x4c\xd5\xc4\xfb\x90\x3e\x0a\x39\x97\x47\xca\xa5\x2d\x19\x59\xd6\x7c\x7b\x0f\xb7\xd6\xcb\x67\xad\xa5\x62\x01\x65\x65\x35\xaa\xf2\x14\x6a\xbb\x7f\xc6\x25\x98\xef\xe7\x79\xe5\x53\x2a\x0e\x2d\x44\xc9\xd3\x47\x6e\x4b\x26\x16\xea\x77\xc9\xdf\x98\xf4\xba\xdb\xc4\x2e\x22\xee\x65\x33\x91\x39\xe9\x61\x6b\x9a\x7e\x4f\xaf\x5e\x4f\xf8\x7e\x87\x0a\x8d\x54\xa3\x82\x52\x9e\x02\xa7\xe6\x5e\x3b\x05\x33\xb5\xf3\x1b\x9a\xef\xa2\xce\x53\x0b\x9a\x50\x37\xb1\xe7\x2b\xfd\x42\x4e\xb3\x3e\x12\x96\xd5\x67\xd5\x5d\x45\xb7\xb4\x59\xf5\xe8\x1b\xbd\xc0\x34\xf7\xa1\x01\x00\x4a\x8e\x7b\x36\xe1\xf5\x1c\xf0\x7a\x3c\x29\x4f\xc1\x83\xb8\x37\x3c\x2a\x4b\x2e\x2e\xba\xf2\xed\xa1\x84\x7d\xd5\xb0\xfb\x2e\xd3\x1f\x1e\xca\xca\x12\x8b\x2b\xba\x0f\x26\x57\x9e\xd4\x5f\xc3\x2d\xe2\x69\x7d\x0d\x78\xf4\xf9\x19\xc6\xea\xeb\x91\x90\xd6\xa6\xaf\x6a\x0c\xcc\x28\x40\x22\x24\x6a\xc4\x9b\x61\xe3\x63\x89\x53\xc6\x26\xc1\x93\x36\xc6\x6d\x5c\x77\xea\xec\xb3\xc7\xca\xd5\xce\xa7\xd0\xbe\xb0\x69\x6f\x6d\xc9\x1a\x47\x54\x3a\x2f\x7a\x0e\xaf\x10\x82\x81\x3a\x06\x8b\xd1\x74\xfd\x33\x7d\x2e\xa3\xd7\xad\xb9\x93\xa9\x38\xda\xc6\x35\xea\xf5\x50\x95\x67\x9f\xc9\x1e\x46\xfd\xee\xe6\xbc\x70\x93\x37\x11\x3f\x25\x82\x70\x7e\x7a\x67\x4b\xe6\xa2\x02\x68\xd3\x70\x22\x3e\x42\xd7\x03\x5c\x53\x2b\x56\xbc\xb6\x81\x0f\x6f\x10\x14\x52\xd8\xea\xcf\x59\xce\xfa\x20\x9b\xd0\x3e\x94\x7e\xce\xd0\x77\x39\x9b\xd3\x8c\xf7\x64\xed\xae\x57\x77\x45\x3e\x45\xfc\x32\x00\xca\x86\xd6\xd2\x03\x60\x6a\x5e\x13\x6f\xcd\x3d\x43\xc5\xd1\x36\xb0\xc5\x9e\xfd\xe0\x49\xdb\x7c\xe0\xc4\x94\x08\xcb\x29\x26\x93\x22\x4f\x20\xc0\x98\x7f\x48\xd1\xcf\x2c\x13\x5c\xee\xce\xf4\x02\xb8\x88\x6b\x88\x01\xb3\x0b\xdb\x27\x9c\x7a\xbd\xb1\xb1\x59\xef\xcd\x69\x36\xb4\x84\xe8\xea\x34\xf8\xc4\xa9\x67\xb8\x47\xa8\xc5\xef\x1b\xc8\xaa\xea\xe3\x1f\xe8\xaf\x53\x71\x6c\xad\xb2\xb6\x7b\xb2\xc1\x3f\xcf\xa9\xc2\xfd\x32\x80\xb1\xed\x18\x69\x78\x8e\x98\x5a\x8f\x7d\xf6\x0d\xa1\xd5\x9e\x34\x75\x1f\x3b\xff\x31\x4a\xc0\x4d\x02\x0c\x1d\xc8\x0c\x7b\xff\xc2\x15\x03\x17\x66\x2d\x31\x4f\xc5\xd6\x2b\x9a\xad\x27\x11\x36\xe8\xac\x6d\x83\x74\xd9\xd7\x6f\x56\x1f\x7f\x7f\x65\xc1\x91\x7d\x5c\x31\x0a\x4b\x1e\x35\x39\xf9\xfc\x3d\xfd\x6d\x3c\x58\xec\xdc\xc6\xa2\x96\x87\x78\xd4\x00\x20\x68\x9b\x8d\x92\x51\xf1\x78\xfe\x1e\x50\x19\xea\x47\x65\x24\xad\x41\xc4\xf0\x93\x03\xf0\xe4\xe9\x0d\x68\x49\x61\x0b\xf4\xce\x95\x58\xd9\x88\xa8\xf8\x97\x4d\x30\x0e\x35\xc3\xaf\x61\x60\x48\x78\x74\x00\x5e\x43\x00\x00\x47\x85\xfb\x17\x38\xd0\x6b\x58\x16\x10\x3a\xc8\x84\x72\x01\xe1\x4c\x5a\xa3\xc9\x70\x27\x5a\x04\xb5\xfa\x4a\x54\x5b\xd3\x01\x25\x2a\x2a\x6e\x27\x6a\x2b\x47\x87\x76\xb0\x0b\x3e\xa0\xef\x90\x8c\x9e\x4e\x6e\x29\xae\x1f\x0c\x04\x23\xb0\x3d\x49\xc8\xd8\x42\x0d\x4f\x29\x83\xae\x80\xc3\x63\x2c\x40\xa9\x61\x92\xbd\xdc\x8b\x4d\x4a\x8b\x26\x0c\xcd\x9b\x25\x19\xc4\x79\x6b\xf4\x69\xe2\xde\x94\x37\xf7\x65\x42\xcf\x82\xe9\x97\x37\xd4\x9c\x42\x76\x9f\x2c\x5d\x51\x5a\xa7\x19\x7f\x6b\xfe\x3b\x35\xc3\x42\x8f\x2e\xb9\xda\x71\x7e\xdd\xf2\x15\x25\x36\x17\x2a\x1b\x3f\x98\x9d\x52\x56\x0d\xdb\x97\xc0\x02\xcf\x61\x07\xbd\xbd\x9e\xbc\x33\xff\xa3\x4a\xd4\x28\xe0\x8e\x5b\x93\x6b\xa8\xce\x83\xb6\x17\xf6\xbc\xff\xfe\x9e\x3c\x2e\x2f\x33\x27\x61\x66\xed\x4e\x1a\x5e\x9a\x7e\x6a\x2a\x0e\xd7\x05\xc9\x69\x78\x59\x47\x39\x4f\x25\x91\x33\xa3\x5e\x85\x0e\xaa\x60\x75\x88\xf1\xe5\xa9\x84\xe2\xfd\x70\xf2\x3f\xee\x25\x3c\x68\x98\x7a\xff\x02\xca\x68\xbe\xf6\xac\xeb\xec\x89\xbc\x8c\x15\xef\x54\xc1\x3f\xcb\xe0\xb5\xe2\xed\x8b\xc6\x94\x8d\x5f\xb6\xab\x0e\xfe\x89\xf6\x9e\xae\x2f\x9b\x30\x6d\xf2\x38\x00\x41\x5e\xcf\x73\xf2\x09\x95\x48\xcb\x51\xef\xf7\x03\x5b\x99\x96\x07\x7d\x40\xcf\x89\x9d\xe3\x2a\x96\xd6\x9d\x3d\xf5\xf1\xb2\xba\xb8\x92\x99\x7a\xf4\x2b\xa1\x80\x14\xf4\x8f\x2d\x1b\xf3\xcd\x85\x1b\xed\x41\x3b\x06\x4b\xa0\x02\xf3\x4c\x0b\x00\x15\x47\xc5\x01\x3e\xcd\x3d\xda\xde\x01\xf4\x53\x47\x81\xcf\x95\x12\x6a\xe1\x02\x5a\x83\xa1\xdb\xe8\xdb\xed\x05\xb0\xee\xda\xa5\x83\x54\x1c\xfa\x4e\x8f\x7e\x45\xdf\x95\xc3\xca\x2b\xd7\x19\xd9\x89\x63\xd7\xb0\xc5\xb7\x90\xda\xb0\x0a\x1e\x0f\xc7\xac\x43\xcb\x40\xdc\x32\x38\x0b\xda\x40\x1f\x74\x1b\x7d\x8d\xae\x9e\x58\x4e\x2f\xb7\x03\x8a\xd0\x2f\xf0\xc1\x0e\xf8\x1d\xfa\x1e\xd1\xab\xc2\x07\xe8\x0c\xbd\x30\xd2\xee\x60\xce\xbf\x16\x00\x72\x8c\xf1\x9c\x19\x25\x4a\x4b\x6c\x47\x43\xe0\x79\x34\x1a\xfe\xdd\x28\x3e\xf8\xf7\x09\x3d\xcf\xc9\x35\x54\x22\xad\xa3\x8c\x25\x0a\xf4\x23\xdc\xac\x42\xc1\xd0\xad\x1a\xc7\x29\x12\xde\x38\x31\xb9\x64\x2b\xba\xd4\x74\x74\x6f\xc5\xc2\x99\x13\x37\xcf\x9e\xfa\xd1\x37\x8d\x77\x72\xe7\x3c\xfb\xd7\xdf\xdb\x54\x07\xbd\x03\xe7\xcc\x3c\xbe\x6d\xf6\x5b\xb1\x53\x86\x46\xe5\xae\xd9\x55\x38\x77\xfd\xe0\x90\xcf\xf6\x1f\xa3\xe9\x86\xe6\xc0\x22\x0c\xd7\x20\xfc\x5a\x30\x95\x0c\x09\x55\x42\x6d\xb4\x9f\x7f\x54\x94\xbf\x5f\xb4\x50\x87\xda\x23\xc2\xc2\x22\x22\x35\x1a\x38\x97\x09\x63\x00\xd8\x53\x83\xbe\x87\x29\x98\x5e\x80\x67\xf6\xca\x52\xcc\x8c\x89\x2a\xd2\x55\xed\x88\x19\x9d\xed\xb8\x8f\x0a\x7d\xf9\x60\xef\x07\xae\x06\x1a\x50\xb6\xb8\xe7\x3e\x60\xfa\x41\x1a\x06\x3b\x68\x9b\xfd\x3c\xe1\x9a\xfb\x28\x1a\xb6\xdd\x47\x1b\x12\xa9\x38\x64\xad\x96\xc3\x83\xc8\x5d\xbf\x07\xfe\x3e\x11\x25\x02\x08\x94\x00\x90\x31\xcc\xb7\x0e\x1a\xa1\x4a\xa8\x91\x72\x30\x09\x79\xca\x0d\xcd\x57\xe2\xd0\x6f\xf0\x1b\x7d\x66\x14\xd4\xc5\x13\xb1\xc8\x33\x7b\xcd\x6e\x74\xbb\x02\xa6\xca\x99\x3d\x39\x72\xec\xe7\xa5\xf7\x84\xae\x4c\x6a\xb3\x06\xca\xa1\xa3\x44\xa8\xfd\x1d\xbe\x56\x5b\xf3\x5c\x47\xa1\x96\x1d\xe8\x1c\x45\xc5\x75\x9f\x82\x1f\xc0\xc3\x2f\x9b\x89\xaa\x84\xf8\xee\x33\xe4\x98\x29\xc9\xfa\x4c\x23\xff\x28\x9a\x7f\x58\xba\x54\xee\x10\x48\x7d\xb0\xc3\x12\x2f\x73\x85\x3b\x16\x4e\xdf\xc8\xad\xbf\xa2\x7f\x60\x4d\xc5\xd9\x2c\xd0\xff\xe7\x46\x6c\x39\xb1\xf0\x65\x33\x19\x73\x24\x42\xbf\x9f\xa9\x81\x7c\x4e\x55\x52\xc9\x38\xff\x17\x98\xe5\xa7\x31\x45\x6d\x2c\x53\xf3\xa0\x18\x75\x41\x09\x7a\xfa\xb2\x07\xfd\x7a\xae\xbe\xb6\xb6\xfe\x68\x6d\x6d\x03\x4e\x36\x53\xa0\xfb\xa8\x0b\xfd\x07\xdd\x83\xbe\xd0\xf6\xd6\xa3\x87\x9f\xdd\xbe\x7f\x9f\xf1\x89\x3d\x27\x75\xcc\x39\x8a\x86\xc6\x95\xcc\x0b\xc1\x62\x5f\xab\x58\x5a\x7f\xfa\x7c\xdd\xb2\xba\xb1\x9b\x67\xff\x06\xdd\xd0\xaf\xfa\x3b\xe1\x5b\xc7\xfc\xed\xfa\x85\x6f\x82\x77\xba\x48\xd1\x5d\x84\xd0\x73\xf4\x08\x10\x40\x05\x7c\xa9\x5a\x4a\x86\x73\x72\x69\x59\x18\xa2\xf2\x04\x12\x31\x6d\x62\xb2\x29\xb2\x02\x99\x17\x57\xb5\x19\x52\x0d\xd0\x1a\xfa\xa3\xcf\xd0\x4b\xf4\x3b\xba\x53\xf1\xf0\xce\xa7\xf7\xd1\xec\xdb\x8f\x08\xdf\x5d\x3f\xac\x43\xff\xfa\xed\x47\xf4\x0b\x14\x74\x1e\x38\x5c\x53\x05\xa3\xdf\xa7\x61\x54\x81\x1d\x54\x2d\x49\xdf\x19\xca\x51\x0e\xd6\xb6\x62\x91\x08\x70\x6d\x81\xad\xd4\xc9\x4a\x42\x0e\x4a\x4b\x22\x41\xa0\x12\x38\x05\x5e\x15\x8a\x60\x38\xfb\x78\xc7\xcf\xf7\x10\x7a\x67\x5a\xc2\x15\x2c\x79\x24\x62\xa9\xdc\x87\x36\x07\x05\x50\x0c\x87\x79\x0e\xde\xa5\xba\x73\xe7\xda\xbd\xe8\x43\x91\xf0\xe2\xcf\x90\x8f\xfe\x7c\xf1\xc6\x9e\x11\x61\x9b\xe6\x1e\x3e\x74\x70\xdf\x8e\xcd\xcb\x99\x3c\x02\x2e\xf0\xa6\xee\x52\x6e\xc0\x01\xb8\x02\x2f\x5a\x76\xa4\xa1\x78\x55\x66\x4a\x9f\x27\x50\x87\x68\x30\x07\x34\x90\xab\x81\x0c\x86\x93\x0b\x2a\x21\x41\x63\x18\x97\x13\x5f\xb8\xef\x4f\x1a\xc7\xb1\x53\x1e\xdc\xad\x98\xa7\x2f\x0b\x3c\x44\xe4\xa8\xd0\xec\x23\x64\xc1\xca\x99\x45\xe8\x5f\xbf\xed\x5a\xf1\x46\x5e\x72\x21\x14\x3c\xdb\x95\x83\x7e\xdf\x77\x24\x10\xb6\x8e\x3b\x8c\x46\x8e\xcf\x82\xd1\xf4\xde\x99\x3d\x9d\x3c\x39\x35\x13\x78\xe0\x0a\xcb\xfe\x74\xbf\x48\x82\x73\x14\x2d\x54\xbe\xf9\xab\x29\x93\xf8\xc2\x1a\x9d\x9b\x79\x20\x7d\xf2\xa1\x25\x50\x56\x18\x7d\x67\xd3\x8e\xef\x57\xa3\x7f\xff\xbc\xfe\xd6\xc8\xc8\x0b\x05\xb7\x9f\x9d\x2f\xca\x5f\xbb\xd5\xf6\xfc\xae\xea\xf7\xdf\xdb\xfe\x41\xd5\x0e\xf8\x28\x0b\xe6\x7b\x0e\x3b\xe0\x2d\xff\x7e\x69\x4e\x29\x42\x0d\xe8\x77\xd4\x9e\xbd\x74\x71\x0e\xb4\xba\xb8\xbb\xea\xd0\x9e\x9c\xf6\xbb\xf7\x3e\x6b\x6b\xbf\x07\x08\x90\xdb\xf3\x9c\xfc\x1d\xcf\x6d\xa3\xb5\x7c\x88\xc6\x27\x0a\xaa\x24\xac\xdb\x5d\x65\x52\x2b\x3e\x1a\x31\x9e\x2e\x29\xf3\xcc\x6d\xdb\xd3\x9c\x35\x67\xfe\x62\x5d\xec\x5b\xf7\x9f\xdf\xbd\xfe\xfb\x19\x48\x6c\x5c\x87\xba\x11\x82\x99\xdf\x4c\x99\x7a\x75\xe7\xce\xf9\xcb\xb2\x33\x76\xee\x9c\x53\xa6\x7c\xeb\xb1\xf6\xfa\x67\x47\x9f\xac\xce\xfa\x8e\xd6\xf3\x84\x02\xcb\xbd\x9d\x51\xea\xe5\x0c\x2f\x59\x59\x3f\x6f\x29\xe1\xb7\xef\xdf\xbf\x8d\xcf\x1b\x3e\x2f\x84\x02\x7f\xa7\x62\x28\xa2\xc2\xe7\x25\x0f\x9f\x8b\xf3\xcc\x19\x21\x14\xf4\x51\x60\x8e\x05\x30\xdc\x03\x64\x25\x8e\xf1\x8b\xd8\x77\xaf\x98\x9d\x35\xc9\x5c\x56\x5a\x18\x0e\x1b\x7f\xfe\x6a\x41\x62\x65\xf1\xda\x8d\x2b\xa9\x38\xd4\x7c\xb4\x19\xa5\x12\x41\xa9\x0b\x52\x53\xe8\xef\x83\x00\x20\x8b\xb1\x9e\x91\x98\xbd\xf8\xf0\xf4\x25\x07\x31\x13\x4c\x09\x82\xe1\x39\x19\xed\x8f\x60\xac\x4e\x87\xbe\x8f\x45\xa5\xe5\xab\xd7\xc1\x2f\xfd\xf6\x2d\xdd\x53\xfd\xb2\x19\xb6\xa0\x18\xd2\xfa\x02\x5c\xfc\x66\xef\xb5\x1c\xf0\xf4\x58\xa1\xcc\xcb\x47\x1d\x12\xaa\x21\xd9\xc8\x4c\xd0\x5d\xe8\xa6\xd3\xa1\x53\x8f\xda\x33\x72\x3c\xd7\xad\x2e\x2f\x45\x54\x1c\x1a\x07\x4f\xbf\x6c\xae\xde\xbd\x74\xbf\x1f\xba\x33\x73\x0a\x5c\x02\x58\xfd\x57\x4a\xc5\x01\x9e\xc1\x27\x25\x17\x2a\xc9\x54\x54\xdf\x4c\x36\xef\xdc\xd9\x1d\x47\x36\x03\x08\x6a\x7b\x9e\x53\x1e\x8c\xae\x73\xe8\xe3\x9b\xac\x6d\x5e\xbf\xb1\xa0\xf8\xc4\xcf\x9f\xdf\x7d\x02\x4b\x89\xf3\xfa\xa8\xfc\xe2\x8d\xeb\x88\x56\x7d\xd4\xe9\x2f\xda\x01\x04\xf1\x20\x95\xaa\x27\x11\x7d\xff\x6b\xd4\x86\x81\xa2\x6a\x99\xc4\x50\xa5\x15\x4f\x9c\xdb\x50\x74\xfa\x9e\xfe\x1a\x15\x57\xf1\x66\xd2\xe5\xb6\xd4\xa6\x95\x05\x1f\xee\xd5\x95\xbb\x5a\xab\x4e\x2d\xb9\x79\x99\xa9\xfb\x03\xa9\x5c\x2e\x89\xb0\x8e\x1b\x66\x79\x9b\x08\xcd\x23\xea\xfd\xae\x1f\x1c\x12\x1a\x18\x18\x1a\x12\x6c\xf8\x0b\x93\x69\xc3\xee\xec\x5d\xbc\xe3\x94\xc4\x2b\x9f\xc1\x25\x3e\x61\x38\xd6\x0e\x6b\x87\x86\xe1\xf0\xbb\x7e\x6f\x53\x5e\x41\xdd\x1e\x1a\x88\x90\x93\x59\x37\xaf\x32\x3e\x7a\x57\xaa\x9e\x33\x06\x78\x81\x15\xa3\xc6\x3a\xb8\x8b\x25\xae\xae\x94\x80\xef\xe5\xe4\xee\x6e\x4b\x79\x51\xf2\x21\x62\x81\x0b\xdf\xca\x8a\x9f\x96\x64\x65\x05\x84\x5e\x20\x2d\x09\x78\x41\x3b\xd2\x4b\x28\x48\x4b\x1a\x24\x0c\x14\x46\x0b\xc9\x25\xc2\x43\xc2\xf3\xc2\x1e\x21\x25\x10\x7a\x0a\x09\x21\x08\x9c\x35\x2b\x9b\xd6\x4f\x6f\xa7\xcc\x52\x0a\x45\x20\xdc\x29\x10\xff\x11\xaa\x58\x7d\x85\xd5\x95\xe1\xff\x82\x86\x4b\x4d\xc8\x79\x5a\x20\x29\x30\xa0\x2a\x8b\x27\x2e\xad\x5f\x7f\xec\x13\x7d\x35\x71\x09\x52\x2d\xf7\x31\x86\x93\x93\x4f\x25\xa6\x5e\xb8\xaf\x57\xab\x16\xe5\xec\x29\x6f\xfa\x76\xef\x96\x13\xdb\x5d\x6c\x02\x3f\x5a\x80\x50\xbc\x75\xc8\xc9\xe5\xa7\x3f\x61\xee\x21\x31\x00\xe4\x13\x2a\x0e\x58\x03\x97\x51\x36\x80\x6f\x63\x4b\x59\xf3\xc0\x20\x6b\x09\x88\x8e\x0e\x16\x86\x63\x90\x82\x86\xb3\x2f\x68\xfa\x49\x2b\x3e\xdf\x25\xb7\x17\x7a\x76\x9d\x43\x0b\x8f\x52\x71\xfa\xf1\x73\x62\x12\x92\x08\xdd\x4b\x3c\xab\xc8\x17\x00\xce\x6d\xc6\x0f\x65\xfc\xc2\xf8\x21\xb6\x98\x49\xb9\xef\xb9\x7a\xa1\xc0\xda\xf5\x8a\xf6\xb6\xa3\x90\xef\x54\x7f\x1e\xdd\x6f\x78\xe4\xca\xe5\xbb\xde\x6f\xa0\xe2\xf4\x19\xa3\x92\x26\x24\x10\xef\xe9\x17\x8d\x9f\x35\x2a\x95\xd8\xf3\xb2\x99\xb8\x36\x2d\xc4\x3f\x55\x1f\xc5\xc0\x9a\x00\x00\x99\x87\xcf\x22\x50\xb1\xe5\x65\x32\x49\x02\xa1\xd2\x7f\x4d\x12\xfa\xdb\xc4\x98\x3c\x32\xa2\x22\xaf\xfb\x4a\x05\xfd\x5b\x5c\xdf\x88\x63\xd8\xc0\xbc\x66\x90\xf9\x8a\xc2\x22\x3c\xf6\xe4\xd9\x6d\x15\x95\x87\x76\xc2\x64\xfd\x2f\xa4\x2d\xaa\x83\x45\xff\xfe\xea\xb9\xaa\x3a\x61\xfe\x9c\x79\xc9\x1b\x60\xe0\x96\x62\xd4\x2e\x43\x57\x0f\x31\x7d\xc2\xe7\xf4\x3c\x27\x63\xa8\x44\x20\x07\x51\xa3\xdc\xed\x80\x87\xc8\x09\x88\x78\x80\x37\xc4\x5b\xe2\x24\xa2\x00\x6f\x90\xf5\xac\xa4\x41\x02\x99\x6b\x4a\x92\xcc\xd1\xe0\x43\xa6\x99\x2a\x0a\xef\x73\x0b\x8d\x84\x1a\xd6\x08\x37\xd9\x5c\xf6\xd0\xdc\x7d\x3a\x27\xfa\x9d\x92\x92\xe4\x59\xb3\xd2\xf6\x68\x76\x57\x7c\xf8\xe9\x86\x9a\x03\xf3\x97\x65\x8f\x6d\x48\x28\xf9\xe4\xd2\xdf\xa1\x7f\xdc\xe2\xe9\xaa\xe1\x53\x62\xa2\xdf\x18\x53\x3e\xb6\x72\x43\xee\xde\x88\xb0\xe9\xa3\x26\xbc\x35\xcc\xa7\x7a\x74\x1d\x80\x40\xd6\xd3\x49\x76\x50\xc9\x40\x66\xb4\xf3\x34\x06\x77\xad\x44\x4c\xd2\xff\x81\xd9\x03\x5f\x11\x32\xfb\x38\xc7\xf0\x35\x71\x6b\x73\xae\x57\xbf\x7f\xfd\xf9\xd8\x77\x87\x69\xa2\x83\xa7\xcd\x38\x92\x38\xf3\xc3\xa4\xb7\xb8\xef\xf1\xec\x67\xcd\x29\xfa\x72\x4e\xc5\x85\xf3\xbb\x2f\xa2\x9e\x99\x73\x25\xef\xb9\xac\xc8\x59\x91\x63\xb2\x3f\x63\xa9\x38\xc0\x31\xd8\x9f\x5a\x62\x0f\x72\xa7\xe2\x2a\xba\x27\xf6\x92\x2b\xf6\xd5\x84\xd9\x2f\x86\x15\x47\xe1\x8e\x73\x5d\x43\xec\x84\x9e\x5d\xb4\xdd\x47\x9c\xca\x1c\x35\x35\x59\x3f\xd1\x68\x13\x89\x18\x9d\x44\xbf\x1d\xe9\x77\xa3\x96\x4c\x6b\x42\x5c\xfa\x97\x64\x73\x77\xdc\xff\xb1\x3e\x86\x20\x0b\x00\xea\x06\xce\x25\xc1\x3a\x4d\x40\x3f\x51\x3d\x71\x84\xc4\x1e\x2a\x21\xad\x97\xbd\x02\x60\x56\x33\x1c\x7c\x1c\xba\x7f\x92\x79\x6b\xa7\xfd\x71\xdb\xed\xb7\x16\x10\x8f\x60\x36\xda\x81\x5e\x10\xb9\xfa\x52\x48\xc1\x6c\x54\xbe\xb6\x79\x2e\x3a\x03\xc7\xce\xa5\xf5\xa4\x5b\xcf\x33\xf2\x39\x7e\xe3\x18\xfd\x1f\x1a\x0c\x3e\xe3\xa4\x76\x1b\xe5\xe7\xa7\x1a\xfe\xba\x88\x28\x3a\x89\x6e\x39\x06\x8f\x5f\xb1\x60\x24\x7f\xa7\xc7\x9b\xed\x84\x74\x2b\x8d\xd6\x47\x68\x11\x7a\xb6\x12\xcf\x7e\x26\x74\xe4\x5d\xae\x96\x79\x6b\x3a\x58\xbe\x35\x45\x70\x4f\x39\xac\xa8\x5f\x83\xca\xf2\x8e\x41\xfb\x2c\x91\xb5\xbd\x1d\xa1\x23\xbb\xbb\x29\x18\x84\xda\xe0\x69\xe8\x14\x14\x32\xce\x13\x10\xc0\x9e\xd0\x51\x6d\xdc\x7a\xe6\xad\xe9\xd0\xcf\x5b\xd3\x1e\x3e\x27\xda\xd0\x52\x98\x8b\x4a\xe1\x7b\xfa\x1b\xe8\xdc\x9e\x2f\x20\x18\x4e\xe8\xc8\x17\x25\xe8\x87\x0d\xa8\xa5\x84\x5d\xb0\x89\xcd\x9b\x24\x74\x64\x39\xb7\x1e\xd8\x01\x31\x8e\x03\xb1\x69\x4e\xcc\x75\xae\xe8\xf5\x72\xab\x81\xea\x07\x17\xa7\x4e\xbe\x7a\xe5\xd8\xdd\x53\x8f\x9f\x34\xd4\x2e\x9d\x9d\xb5\x72\x07\xbd\xf4\xba\x8d\x53\x96\x49\xc3\x4f\x97\xec\xdf\x50\x5f\x55\x18\x33\x39\x2e\x1a\xaf\x4d\xe3\xfb\x03\xb7\xfe\x7f\xe5\x6d\x28\xda\x4e\x6f\x31\xf9\xea\xfb\x93\xae\x1c\x43\xc5\x75\xa6\x5d\xa8\x0d\x85\xb0\x76\xdd\xc6\xd9\xa3\x0b\xc7\x66\x94\xec\x87\x77\x91\xce\xb0\x13\x81\x71\x78\xc1\xad\x67\xde\x72\x34\x06\xd8\x0a\x35\xbc\xe5\x6a\xe0\xc4\x17\x50\x80\x7e\x40\x7f\x16\xe7\xc2\x92\xf3\x0d\xe5\xf4\xaf\xd1\x7f\x7e\xea\x46\x7f\x16\xc3\x35\x67\x9b\xd8\x9e\x7f\x84\x8e\x24\xb8\xf5\xf4\x7b\xcb\xc1\xec\xbd\x55\x43\xa4\xa0\x38\x78\x00\xa5\xc3\x66\x33\x12\x02\x08\x96\x10\x3a\xa2\x8d\xfd\xbd\x5a\x26\x94\xb1\xff\x2c\x81\xcd\x68\x0e\xdc\x8f\xe2\x88\x54\x42\x57\x02\x63\x36\x40\xd7\x92\x6e\x3e\x80\x20\x9b\xa8\x23\xbf\xe7\x9e\xc2\x72\x19\x02\x2c\x47\x09\x09\xe5\x6a\x99\x90\x2b\xf7\x02\xd9\xd0\xfb\xe5\x47\xfb\x22\xde\x2b\xac\xbf\xf0\xc9\xb1\x71\x4b\xbe\x86\xc5\x47\xee\xfd\x8a\xfe\xa4\xb4\xbf\x43\xf1\xe8\xe2\xd1\xb7\x75\xe7\x2f\x8b\xa0\xb0\x04\x51\x6a\x28\x62\x61\xbe\x6f\x80\xd9\xe0\x8d\x91\x09\x6b\xea\xe0\xd7\x75\x75\x48\x86\xf1\x9c\x09\x6b\xba\xf9\xf0\x36\x52\x01\x08\xa6\x12\x3a\xd8\x61\x80\xd9\xd4\xe8\x6d\xea\xca\x95\x70\xd7\xaa\x55\x84\x2e\xd5\x95\x04\x6e\xa9\xa9\x6e\x7a\xe0\x9a\x4a\xbf\xd7\x8e\xc2\x7a\x38\x16\xcb\x06\x20\xd5\xe6\xc6\x41\xc2\xf8\x90\xc8\xa8\xda\xed\xa5\x51\xf0\x4a\xb1\x24\x2e\x86\xfc\xa1\xdb\xbb\x6c\x8f\x89\x8e\xe7\x98\x6f\x1c\x70\x7b\x77\xc3\x9b\xad\xa6\x4e\x2c\x87\x0b\x2f\xa3\x54\x58\x7f\x09\x55\x4f\xc1\xc0\x05\xba\x28\xe1\x16\x34\x46\x7f\x15\xb6\xc5\xa2\x3c\xe3\xf7\x5c\x6e\x3d\xe0\xd0\xf7\x15\x09\x00\x87\xcb\x83\xaf\xd3\xa6\x42\x74\x70\x34\xab\x6a\x83\x86\x63\x6c\x25\x35\x75\xb0\x85\x5e\xa6\x7b\x47\xa9\x71\x6f\xea\x22\xb7\x9e\x91\x02\x76\xe2\x86\xe1\xe9\x56\xf3\x2d\x54\xc2\xa0\x6f\xea\x28\x74\x7f\x13\x7a\xc0\xc1\xdf\xbd\x20\xf9\xdd\x7c\x22\xeb\xcd\x98\xee\x6e\x92\x98\x39\x5a\xbf\x8f\xdd\xff\x99\x11\x7e\xc8\x3e\xda\x3c\xa0\xb0\x46\x07\x11\xb7\xea\x24\x02\x5c\x12\x7f\xdc\x95\xbc\x84\x88\xea\xe6\x93\xdc\xb4\x45\xfa\xeb\x26\xdc\x91\x09\x77\x3c\x08\x1f\x43\x50\x53\xc5\x23\x84\xda\x2a\xae\xfe\x19\xfd\xa9\xfe\xfe\x86\xa9\x24\xb7\x9b\x4f\x28\x2a\xc7\x75\x77\x01\x82\x96\x0d\x6a\x0c\xb7\x85\x7d\xeb\xd1\xd2\x41\x0b\xb0\xd1\xc2\x67\xfd\xe4\x10\x74\xfc\x08\x01\xea\xfe\xe7\x53\xbd\xf6\xfd\x8a\xca\x43\x07\x2a\xf7\x56\x51\x4d\x5d\xd0\x1e\x75\xfe\xfe\x6f\xf4\x33\x14\x74\x5d\xbc\x7c\xf9\xe2\xd9\xcb\x97\xb0\x5d\x9b\x45\xd4\x91\x75\xdc\x7a\x30\x18\x67\x03\x84\x68\x02\x60\x6f\x83\x9d\xad\xa6\xf7\xd1\x88\xe9\x33\x28\xf7\xca\x3a\x37\x2e\xa6\x6e\x5e\xf2\xdb\x19\xb5\x63\xe2\x93\x17\x7c\xdd\xfa\xc9\x37\x0d\x3f\x3f\x7f\xfe\x33\x45\x7d\x36\xc9\x67\x63\x62\x49\xc9\xec\x8c\xcc\xb7\x4b\x4a\x66\x15\x0e\x95\x6f\xc9\xac\x6e\x39\x7f\xa0\xbd\xbd\x8d\x3d\x7b\x53\xb9\xf5\x8c\xbe\x76\xe8\xab\xaf\x6b\xa0\x0c\x6e\xfb\xea\x66\xea\x94\xe2\xa2\x65\x6b\x17\x63\xae\xb7\x1d\xac\x43\x05\x04\x37\x61\x6e\x62\x22\x63\x83\xd3\x6b\x34\x70\xeb\x81\x2d\xb6\x7b\x59\x1d\x01\xe5\xa4\xdc\x7c\x19\xff\x6b\x67\xae\x40\x8f\x2b\x7f\xd4\x6d\x58\x3a\x7f\x71\x76\x3e\xbd\x52\xf9\x9e\x0b\x13\x51\x14\xdc\x83\x32\x08\xb7\xe9\xd3\x93\x26\xd0\x3c\x50\x10\x3a\x32\x96\x5b\x6f\x6e\xf7\x2a\x48\x19\xba\x5c\xc7\x95\x97\x94\x74\x97\x93\x4b\x00\x04\x95\x44\x1d\xd9\x66\x94\x13\x8b\xac\x1b\x9f\xca\xba\x3f\x96\xaf\xab\x7d\x74\xe5\xd2\x03\x4a\x4e\x94\xe8\x73\x9e\xe7\xe7\x12\x65\xfa\x9c\x86\x1b\x2c\x8f\xbd\x09\x1d\x27\x85\x5b\xdf\xdb\x06\x8a\x86\xac\x0d\x64\x0f\x49\xb9\x77\xd3\x41\x2b\x89\x9d\xa3\xae\xe6\xfc\x20\xb1\x3d\xbf\x4e\x8b\x9e\x56\xdf\x70\xe2\x91\xfc\xbf\x55\x71\xeb\xf5\x95\x5e\x8b\xa6\x8e\x21\x52\xf4\x07\x43\xd3\xe2\x86\x12\x9b\xba\xf9\xc4\xf6\x29\xfe\x52\x1f\xfd\x30\x86\x16\xc9\x44\x1d\xd1\xc9\xb9\x08\x9c\x98\x77\x96\xa9\x35\x5b\x28\xdb\x99\xad\x77\x07\xae\x64\x58\xb8\xe4\xf5\xd7\x34\xcb\x43\x83\xb6\x96\xed\x2c\x5f\x2f\x0a\xc8\x9e\xb1\xa6\xe4\xe8\x18\x75\x6a\xd6\xcc\xbc\x25\xe4\xb6\x5f\x6c\x29\x8f\x84\x31\xbe\xd2\xdc\xd8\xfc\xcd\xfa\xae\x84\x90\x80\xd5\x0b\x43\x83\x17\xa4\xa8\x28\xce\x18\xbc\x5f\x29\x71\x84\x74\x33\xee\x27\x54\xb1\x3e\x46\x31\xeb\x63\x0c\xd5\x48\xb1\x73\x47\x63\xf4\x2b\x96\x16\x4a\x54\x39\x53\x57\x6f\x42\x85\x4b\x5e\x1f\x13\xb6\x2c\x2c\x68\xcb\xb6\x9d\x3b\x6a\x93\x57\x2f\xa5\xb7\x24\x3f\x26\xb8\x53\x35\xca\xb5\x59\xf4\xb6\xd3\xc6\x0c\x75\x5e\x39\x7e\x2d\xf4\xa6\xb8\xa3\xc7\x87\x86\x64\xe2\xf7\x52\x06\x51\x47\xaa\x38\xad\x60\x10\x18\xcc\x5a\xfc\x52\x8d\xaa\x37\x5a\x78\xa7\x8c\xc6\x03\xef\xa6\xda\x97\x96\xda\xfb\x2e\x7a\xf3\x60\x43\xdd\xcc\x59\x59\x49\xa9\x19\x09\xb3\x29\xd5\xf9\xbb\xb9\x19\xdd\x68\x41\x58\xd4\x9d\x4f\x0a\x4a\xd7\xac\x11\xef\xcc\xdf\xca\xdc\x65\x69\x44\x1d\x75\x8b\xd3\x0a\x7c\xc0\x30\xa0\xc1\xfc\xf7\x31\x36\xb9\x71\x94\x86\x1a\xf1\x32\xb8\x4e\xd9\x4d\x69\xa3\xc9\xcc\x71\x9a\x06\x7f\x14\x7c\x32\x6e\xc5\xe8\xd1\x2b\x5e\x4f\xad\x50\xa6\x5e\xcc\x2b\x45\xe5\x8b\xca\x66\xad\x57\x85\xed\x8f\xad\x8d\xf5\xc9\x8d\x2b\xff\xf8\x28\x35\x71\xec\x36\x69\x43\xc2\xd2\x05\x23\x55\x49\x73\x29\x90\xf8\xc4\xd3\xad\xc4\xd3\x69\x4a\xdc\xfe\x55\xcb\x9e\x59\x53\xb2\x5d\xa3\x97\x7b\xfa\xad\x0c\x8b\xfe\x64\x6d\x42\xda\xa9\x25\x14\x35\x3a\x26\x54\x9d\x39\x0b\xd3\xbb\x9c\xa8\x23\x53\xb8\x1d\xb8\x5e\x9f\xd5\x12\x86\x54\x1d\xb9\x97\x82\x87\x7d\x0b\xac\x27\xbb\xbc\x96\x1f\x38\x2f\xee\xc0\xf1\xe3\x07\x76\x4d\x95\xfa\xbe\x9d\xd1\x9c\x9c\x3a\x6f\x16\xa1\xa3\xd4\xe8\xf7\x69\x91\x11\x23\x6e\x9f\x3f\x7b\x27\x67\x3e\x5c\xf3\xde\x2a\x28\xd8\xb0\x71\xc5\x26\x46\x7e\x30\x7d\xb9\x1d\x38\x73\x9a\x7d\x51\xb1\x9e\x27\x33\x12\x9b\x28\x1c\xbf\xc0\xd7\xaa\xb6\xd4\x3e\x74\xe1\x38\x4c\xe2\xab\x06\x0a\x47\x85\x4d\x8a\x85\xdc\x97\xb7\x16\x8c\x52\xd3\x54\x7e\xa0\x66\x88\xcc\xac\xef\xca\x69\xc5\x77\x3a\xbb\xbe\x29\xb2\xc9\x35\xb5\x04\xcb\xb8\x70\x78\xdf\x71\xfd\x1f\xfc\xec\xf9\xe3\xd6\xc4\xe6\xee\x6e\xfe\xac\x1e\xce\xa0\xde\x78\x33\x7e\x26\x15\x78\xf2\xf1\xf9\x83\x89\x4b\x73\x3d\x3d\xca\x54\x77\xa0\xc3\xd4\xb9\xb3\xe9\x75\xd3\x88\x3a\x52\xcc\x69\xc5\x15\xa2\x80\xed\x4f\xc4\x53\x9b\x1e\x81\x98\x4b\x9a\x34\x82\xcf\x5d\x36\x7f\xf9\xf6\xa5\xfb\x75\x6d\x97\xaa\xf7\x1d\x3f\x4a\x4d\x9f\xb0\xc7\x9d\xa2\x12\xb2\x97\x47\x95\x86\xde\x39\x75\xea\xcb\x33\x79\x89\xa9\xa7\x00\x04\x89\x44\x1d\x71\x85\xd3\x0a\x3c\x59\xed\x67\xc8\x68\xf0\x91\x7b\x49\xc4\x38\x8d\x02\xcb\x01\x93\xce\xa0\x1d\x33\xad\xbe\xec\xf5\xc2\x37\x47\x2e\x5f\xb8\xe7\xca\x9c\x35\x97\x9a\x73\x77\x2d\xaa\xad\x6a\x22\x4b\x37\x07\x89\xa7\x47\xcf\x5e\xe6\xec\xbd\x26\x6c\x46\x5a\x61\xf6\xe2\xd8\xad\x9a\xd5\x8c\x1e\x88\x25\xea\x88\x53\x9c\x56\x1c\x1b\xa4\xef\x46\xd6\x8a\xb1\xec\x58\xc2\xc0\x1e\xbb\xab\xf0\x93\x2b\x6b\xe6\x5c\xab\x8c\x98\x1f\x1d\xbe\x71\xdf\xd6\x0f\xf6\x68\x8f\x1f\xae\x27\x1e\x97\x8d\xcb\x5e\x5c\x98\x36\x63\xb0\xcb\x9a\xc8\xa5\xb3\xf3\x7d\xfd\xb7\x67\xae\x61\x78\x38\x0f\x66\x90\x41\x9c\x56\xe0\x0a\x86\x9a\x9d\x11\x2c\x20\x6a\xf6\x80\x68\xfa\x9e\x97\x79\x4d\xfb\xb7\xcc\xb4\x2d\xd1\x9e\x6a\x5c\xbe\xe9\x70\xe2\x1c\x4a\x99\x19\x7b\x50\x5b\x97\x32\x23\x23\x35\x35\x73\x7a\x2a\xa5\xfa\xa4\x3d\x37\x43\x0f\x6a\xeb\x42\x77\xc4\xce\x9b\xe5\xa6\x76\x0d\x0f\x6b\x6b\x59\xbf\x79\xf9\xba\xc1\x5b\x0b\xb7\x32\xfb\x96\xc0\x83\x70\x0c\x8e\x05\xf5\xf2\xed\x6a\x84\x2a\x61\x89\x46\xee\x1b\x1a\xea\xeb\x1b\x64\x5d\x0b\xbb\x87\x05\xf8\xfb\x07\x0f\x53\x7d\x4f\x12\xdd\x88\xa1\x07\x6d\x55\x69\xb8\x1d\xd8\xb2\xc5\x52\x1d\x6d\xb8\xf8\xcb\x6b\xa9\xc8\x7f\x5f\x44\xe7\xe0\x94\x4b\x3d\x60\x24\x2d\xbf\xfa\xbf\x0f\x1f\x32\x1e\x21\x1d\x8a\x83\x93\xbd\xd1\x03\xc3\xf7\x14\xe2\xb4\x62\xa9\x65\xb5\x90\x34\xd4\x6c\x34\x8c\xe9\x6f\xf9\x56\xdb\x80\x45\xa3\x3f\x1e\x9d\x70\xa8\x74\x73\x75\xf1\xdc\x69\x35\x25\x29\x49\xb4\xf1\xb6\x6c\x7c\xd8\xe6\xcd\x9b\x76\x23\x01\xec\xac\x5e\xb5\x14\x25\xd3\x7f\x36\xa1\x65\xf4\xda\x30\x83\x8c\xe2\xb4\x62\x89\x15\xaa\xd8\x65\x8d\xe4\x54\x9b\xd6\x4d\xdb\x5e\x56\xbe\x28\x27\x7c\xd4\xe8\xa1\x13\x2b\x16\xa6\xd1\x8b\x66\xae\xdc\xb4\x4b\xdf\x90\x55\x20\x2d\x90\xcc\x27\xe2\x6b\x56\x16\xa3\xa5\xa6\x73\x36\x99\xd3\x0a\x6c\x70\x44\xc2\x9c\x56\xa6\x13\x9c\x71\x45\x7b\xf4\xc6\x35\x6d\xed\xad\xba\xf4\x8c\xdb\xe9\x99\x73\xe7\x51\x9a\x96\x7b\x0f\x9b\xcf\xdc\x7f\xd0\xf2\xce\x7b\x50\x90\xbf\x95\x9d\x75\x16\x43\xd4\x11\x07\x39\xad\x38\x7f\x08\xcb\xb9\x50\x60\x21\xfc\x31\x41\x7e\xe9\xde\xb7\x6e\xa4\xe5\x24\xe4\x9f\xb8\x70\xb6\x69\x23\xd1\x5e\x28\x76\x86\x7c\x68\xad\x2e\x1d\x7e\xff\x7c\x4b\x1b\xbd\x46\x06\xa5\xc6\xf0\xd8\x1a\xa1\xc1\x7e\x33\x61\xc6\xd5\x63\x1f\xde\xac\xcb\x98\x7b\x8b\x52\xb7\x7c\xfe\xb7\xe6\x77\x4b\xd0\xbf\xf0\x9e\x18\x7e\x4a\x8d\x6d\x41\x95\x40\x15\x2c\x54\x31\x5d\xbe\xea\x6e\xdd\xae\xbb\xda\x78\xe4\x26\xa5\x46\xcf\xa1\x7d\xcb\xfd\xcf\x69\x9d\x05\x33\xc8\x14\x7c\x36\xdd\x2d\xee\x08\xfc\xce\x74\x94\x08\x49\x93\x99\x22\x29\xdf\x62\x1f\xb4\x38\xe6\x40\xe3\xf1\x03\x93\x32\x87\xf2\x89\xd4\x05\x33\x66\xcd\x9a\x75\x0d\x66\x50\xf1\x19\x51\x61\x9f\x9d\xbb\xd0\x16\x15\x16\x1b\x8f\xbe\x25\xee\xee\x5c\xb7\x73\x5d\xc1\xe6\x4e\x1a\x96\x20\xa2\x8e\x90\x73\x53\xb1\xf5\xa3\x8e\x86\xcc\x04\x6c\xf6\xbd\x8c\xe5\x5c\x2d\x0c\xca\x56\x65\x3d\x7e\x1c\x3a\xcc\x75\x92\xd4\x65\xaa\xcf\xda\x5c\x4e\x44\xbc\xaa\xe6\xe8\x1a\x94\x3e\x32\x42\xc0\x5f\x6d\x3b\x68\xf5\x2a\xf8\x3e\xc6\xab\x94\xa8\x23\xd5\x78\x96\xb9\xa5\x4f\x8b\x55\x7f\xa5\xb5\xb1\x13\x17\xce\xae\x29\xb5\xf5\xcf\x1b\xbb\xa3\x82\xbc\x08\xff\x40\x92\xa9\x93\x57\xbf\x0b\xcb\xbb\x51\x76\xf8\x58\x66\xee\x5b\x22\xf1\x88\x9c\xc7\x29\xc2\x6b\x58\xf8\x9e\x18\x93\x29\x11\x76\xbe\x35\x39\x6f\x03\x5a\x42\x12\xf4\x27\x3b\x88\x47\xb5\xb1\x13\x16\xa6\x31\x8b\xee\xdc\x05\x0c\x70\x50\x5d\x9c\x66\xac\x1f\xcc\x6d\x0c\x0b\x70\x58\x98\x6a\x8a\xe7\x4c\xff\x60\xd3\xdb\x49\xb5\x65\x76\x01\x8b\x46\x1f\x7d\xcd\xf7\xdd\x09\x25\x5b\xc8\x2b\xf0\x37\x24\xa9\x59\xb9\x14\xd6\xd1\x7f\x4a\xe0\xb6\x6e\x94\x3d\x3e\xb4\x78\xec\x6b\x1b\x71\xde\x1b\xa1\x23\x5d\x39\xcd\xf4\xfb\xdb\xcc\x09\x23\x3a\x76\xc4\xc9\x51\xe0\x71\xb8\x11\xdd\x3d\xc6\x69\x46\xa3\x46\x2e\x9e\xf5\x06\xbc\x60\x38\xa3\xf6\x44\x1d\x41\xdf\x8f\x32\x56\x67\x8d\x84\xfd\x4d\x31\x0d\x80\x18\x2c\xfb\x20\x5f\x9f\x00\xb5\x6b\xcd\xf6\xdc\xe5\xdb\x93\x26\xc5\x4d\x0d\x1e\x36\x64\x5c\x44\xec\xeb\x8a\xf0\xc5\x6f\xc4\x10\x67\xf2\xec\xc5\xc3\x86\xec\xda\x9f\xb3\x73\x67\xee\xb8\x23\xaf\xcd\xb1\x5d\x29\x76\x0e\x1b\x3e\x26\x9a\x39\x1b\xb4\xbc\x14\x72\x9f\x03\x21\xb6\x3d\x0d\xae\x3c\x56\x1b\x2a\x9c\x21\x56\x97\xe6\xb9\xa8\x92\xf2\xb3\xf5\xef\x7f\xd2\xfa\xec\xc2\xc7\x39\x99\x19\x0b\x1e\xac\x5a\x98\x32\x79\xe6\xbc\xf4\xb7\x2e\xc2\x0c\x6a\xe4\xc1\x86\xed\x1b\x4e\x06\x07\x3e\xdd\x79\x40\x8d\x4a\xe1\x33\xd5\xb9\xb4\xf4\xc2\xc4\xa9\xf1\xf1\x77\x19\x9c\x9c\x61\x06\xe9\x81\xf3\x96\xcc\xe8\x60\x0f\x25\xf2\x90\x50\x8d\x73\xfd\x61\xff\x41\x83\x7c\xf6\xd7\xa1\x6f\x65\xde\x0d\x0a\x19\xa7\x19\x65\x2f\x8b\x89\x5d\x04\x77\xe8\x9d\x13\xae\xbf\x3e\xe2\x5a\x2a\xab\x6f\x89\x3a\x32\x9e\xdb\x81\x3b\xe8\xe0\x0c\x38\x8b\xeb\x82\x7e\xa4\x49\x4d\xc6\x32\x2b\xea\x0a\x7b\x38\xaf\x7c\xe3\x5b\x13\x76\xad\x9b\x50\x91\x12\xbb\x25\x5b\x3d\xfc\xb5\x25\x15\x05\xd7\xb4\x47\x6e\x1e\xcd\x4a\x9e\xb3\x30\x61\xe2\xaa\xb5\x64\xe7\xf2\x63\xc3\x54\x19\xe3\xd2\x16\xc9\x87\xe5\x4f\xf2\xf7\xf2\x1b\x3b\xe2\xcd\xba\x65\x87\x4f\x6b\xcb\x93\x16\x2c\x5b\x92\xb8\xd8\xc7\x65\x0b\xab\x4b\x60\x06\xd9\xc5\xb9\x02\xa4\xec\x6d\x25\xb5\x87\x12\xb1\xd4\xe8\x02\xe5\x09\xe5\xc2\x00\xc8\x61\x0d\x14\x49\x46\x55\x41\xf8\x98\x5b\xef\x2e\xdb\xfc\xc1\x9d\x63\x35\xba\xd3\x84\xc3\x9c\x9c\xb8\xf0\xa9\x54\x78\xdb\xd9\x84\x98\x8a\x94\x4e\x2f\xb8\xed\xdd\x92\x7b\x1f\x35\xfd\x5d\x80\x2e\xc0\x51\x0e\x6d\xb3\x45\x15\xb9\xf9\x05\x9b\x71\xde\x1d\xcc\x20\x63\x39\xa7\xf0\x2e\x90\x34\xde\xb0\xee\xd0\x83\xb6\x5e\x1d\x4c\xce\xa3\x40\x48\x12\x70\x62\x8e\xd8\xd7\xc3\xd5\x2b\x30\xca\x3f\x32\xc0\x7b\xf2\x2d\x2d\x6a\x2b\x70\x1b\x3e\x64\xc8\xf0\xc0\x91\x49\x99\xc3\xa6\xfe\x08\x33\x88\x18\x28\x53\x69\xf8\x79\xf6\x83\x47\x24\x5f\x85\xcb\xf5\x4f\xd1\xb9\xf1\xc3\x6d\xf2\x84\x53\xb2\x1f\xa3\x54\x7c\x9f\xf4\xa4\xc2\x31\x64\x5e\xff\xb1\xc2\x92\xd0\xa1\x43\x34\x9a\x21\x43\x43\xf9\xb5\xa4\x6b\x90\xbf\x7f\x90\xbf\xbf\x7f\xf7\x32\xf6\x42\x81\xa0\xbc\x27\x95\xc8\x23\x96\xd0\x5f\x4a\x0d\xf7\x01\xc3\x0d\x61\xf9\x7b\xfc\xc0\xf4\x49\xc1\xd1\x0e\xaa\xa0\x84\xdc\x2a\x92\x78\x3f\x7d\x82\x5d\x99\xfd\xbb\x73\xd1\x3c\xfa\xdc\xf5\x4c\x23\xd5\x44\x3a\xf6\xd5\xfc\xd7\xf3\xbf\xb8\x9f\xe3\x8f\x73\x4a\x67\x93\xae\x44\xfa\x2b\xce\x16\x91\x6e\x79\xb6\x08\x50\x8e\x24\x64\x21\x79\xe8\xff\x5c\xe6\x91\xe4\xbf\xcb\x3c\x92\x90\x1e\x44\xfa\x5f\x92\x79\x22\xbd\x7f\x99\x2f\x45\x62\x32\x1e\xd3\xd7\x15\x00\x8d\x89\x37\x0a\x47\x37\x28\x77\x30\x3d\x3b\x25\xa5\x2d\x1f\x1f\x3a\xdb\x52\xb7\xf8\x2d\x6e\x6d\x6d\xec\xd2\xb9\xc9\x49\xe9\xa9\x33\x3a\xce\xde\xf8\xbc\xe5\xfc\x67\x81\x61\x73\xee\xc3\xae\x88\x92\x0d\x25\xef\x16\x6e\xa4\xe5\x18\x49\xc8\x2e\x62\x19\x23\xc7\x9a\xff\x3d\x39\xfe\xe7\x7f\x13\x63\x9c\x8f\x24\x21\x63\x89\xb9\xff\x77\xe4\x18\x49\xfe\xab\x1c\xd7\xf6\x74\xf2\xf8\x38\x3f\x76\x98\xe5\xad\xd2\x4f\x62\x1f\xe3\x78\xf5\x81\x8c\x15\x5c\xab\x7b\x77\x63\x7e\xf1\x89\xdc\xa6\xb6\x3f\xf4\x42\x8e\xee\x70\xe2\xbe\xac\xc4\xea\xc5\x9b\x6e\xc6\x86\x5c\x5c\x7f\xf7\x09\xb9\x92\xc9\xe4\xdb\x6d\x08\xb0\xbc\xfb\x0e\xd1\x9a\x53\x8c\xfe\xf5\x9d\x21\x9d\x2f\x25\xf3\xed\xf4\x76\x78\x9d\xe9\x8b\xdb\x73\xa6\xa7\x93\x5a\xc3\x15\x83\x61\x20\x1c\x00\x12\x1f\x09\xb5\x4a\xe2\x68\x6c\xc7\xab\x90\x88\x79\xaa\x50\x43\x46\x1f\xce\x4d\x93\x0b\xf1\x13\xc8\x3c\x46\x28\x19\x6b\x33\x77\x9a\xd4\x51\xe7\xee\xe8\xab\xb4\x9f\x67\x3d\x6f\xea\xe0\xc1\xd6\xd6\x4b\x7e\x78\xd4\xf9\xec\xc1\x92\x06\x8d\xbd\x07\xb7\x50\xc6\x55\x2a\x6d\x61\xd4\x8e\x23\x3b\xcb\xb7\xef\xae\x7d\x8f\xaa\x5a\xbd\x85\xbb\xfc\x81\x7d\x44\xe4\xea\x2d\xd6\xa2\xec\xec\x1a\xf4\x00\xfd\x8e\x9e\xa1\xf6\xc9\x6f\xac\x72\xe0\xd8\x5b\x45\x44\xea\x8b\xbe\xbd\xf8\xe8\xf6\x9d\x3b\x67\xbe\x31\xd4\x05\x71\xfc\xb9\x62\xa0\x04\x61\xc6\xfc\xbf\x00\x18\x05\x31\x28\xf2\x7e\xe0\x7e\x65\x1d\x8f\x5c\xa0\x54\xda\x2e\xb0\x99\x3b\xcd\x6d\xb0\x4e\x20\xf5\xc3\x30\x4f\x93\x38\x0e\x5c\xdd\x73\x74\x10\x86\x74\xd5\x97\x7c\xfa\x2f\xf7\x65\x62\x9f\x52\x1f\x00\x7b\x9e\x03\x40\x3a\x73\x3d\x80\xbf\x81\x92\x42\xb9\x5a\x83\xb5\x3e\xa3\x66\xdc\xb0\x6b\xd5\x02\x46\x86\x94\xf6\x36\x73\xa6\x89\x25\x17\x2e\x1c\x6b\x5e\xb0\x68\xf8\xac\x98\x19\x89\x50\x82\x7e\x72\x77\xf1\xf3\xb3\x9f\x67\x9d\x31\xc5\x73\xb0\x4e\x24\xa4\xa9\x57\xbb\x7a\x0b\x17\x3a\x4d\x1d\x19\x7d\xfd\xba\x77\x99\xfb\xaa\xf5\xe3\xb7\xa0\x4d\x83\x22\x22\xd7\x6d\xb2\x45\x13\x09\x29\x37\x22\x12\x90\x3d\xdf\x02\xc0\xab\xa6\x52\x80\x12\x84\x80\x28\x0c\x87\x86\x4d\x8e\xf5\x64\x53\x64\xdd\xe0\x48\x48\xef\x4f\x1f\x1d\x2f\x6f\xa1\x5c\x38\x44\x81\x0b\xab\x79\xd0\x91\xc3\x70\x93\x43\x49\xd5\x02\x9a\xab\x1e\x82\xd4\x59\xe5\xae\xd6\x81\x1f\x65\x42\x22\xde\x5a\x7d\x72\x79\xcb\x27\xc1\x4a\xab\xf9\x36\xb3\x67\x37\x9d\x42\xda\xe3\xe8\xbb\x1f\x75\xfe\x81\x7c\xe8\x72\x11\xbe\x96\xb5\xbc\xb8\x8c\xa8\x83\x63\xae\x7e\xbd\xf7\x3d\x58\x9e\xba\xca\x05\x5e\x33\xc4\x93\x0e\xda\xaa\x87\xcd\x5e\xed\x8c\x92\xe1\x0e\x25\x1a\x03\xdb\xfd\x38\xfa\x2e\xd8\x6d\x13\x10\x0c\x79\xa4\xff\x8c\xf5\xeb\xb7\xff\xe0\x4b\x55\x41\xaa\xe9\x24\x2d\x8f\xdf\x02\xc0\x71\xa6\x52\x80\x27\x8e\x36\x9a\xa0\x37\xc0\x8d\x4f\xbc\x8f\xc2\x47\x81\xc7\x5f\x42\x47\xa9\xa3\x94\x01\xda\xc3\x3e\x7d\xa6\x21\x12\x38\x3c\x80\x3f\x7f\xd0\xb9\xa6\xd9\x2d\x17\x66\xe9\x92\xad\xa1\xcb\xac\xe3\x57\x53\x57\x16\x54\xec\x83\xe5\x4b\x57\x89\xe1\x59\x1c\x3c\xac\xe5\x8e\x50\xff\xcd\x07\xcd\x81\x7b\xf8\xbe\xbe\xb6\x88\x20\x28\x41\x3a\x04\x56\x3e\x4a\xdb\x1d\x1b\x8b\x76\xe0\xfe\xf0\xcd\x48\x4c\xad\xa1\x52\xcc\xcf\x86\x01\x1a\xe6\x38\x28\xe4\x52\x47\x37\x68\x7e\x58\xe4\xea\x3e\x67\x83\x17\x67\x33\x77\x9a\xa7\x03\x93\x7a\xfc\xf0\xe7\x5f\xda\x71\xba\xb1\xa3\x41\xea\xec\xe5\x3a\x17\x07\x9a\xbb\xaf\x99\x32\x90\xab\x56\x6f\xe1\x53\xf5\x15\xc9\x93\x51\x3b\x7a\x8e\xfe\x85\xee\x1d\xf2\x8d\x8f\xaa\xb4\xa5\x45\x8f\x5f\xf1\xc2\x26\x22\x92\x2c\x36\xa6\x22\x03\xd8\x73\x0a\x00\x32\x10\xcf\xba\xef\x05\x25\x16\x3b\x7b\x68\x01\xa2\x41\xe6\x62\x6d\xe6\x4e\xb3\x1b\xb2\x53\xcc\x8f\xae\x9f\xfb\x7a\x98\x63\xd4\x88\xe9\xbb\xa6\x3a\x3b\x32\x40\x4d\x75\x75\xd6\x49\xc5\x34\x50\x19\xab\xcb\xac\xe0\x3f\x6e\x64\x2d\xb5\xad\xb5\x4f\xfd\x70\xfe\x58\xdb\x88\xc8\xbc\xad\x56\xa8\x0c\x3e\xb0\x8e\x88\x64\xf7\x26\xaa\xa8\x14\xe0\x63\xd4\x1e\x8c\xbc\x63\x55\x35\xe0\xc6\x52\x71\x65\xc3\x94\x14\xa9\x4b\x7c\x58\xec\x78\x99\x61\x53\x37\x8f\x26\x27\x3b\x76\x53\x5e\xd5\xb1\x23\xb2\xbd\x7c\x69\x72\x3a\xb2\xa7\xb7\xb4\x43\x25\xb0\x9d\x4f\x6f\x09\x60\xcf\xef\x3d\x9d\xe4\x63\x2a\x05\x04\x03\x40\x86\xb2\xe6\xa6\xc9\xac\x72\x94\x32\x9b\x1a\xd2\x07\x8c\xb9\x94\x81\x8c\xb2\xb0\x75\xd8\xa2\xfc\xfb\x85\xd3\x1f\x44\x1d\xd9\xb8\x74\xf9\x9c\x93\x49\xc3\x7c\x7c\x86\x87\x0a\xe7\x39\x2c\x97\xff\xf3\xce\xa3\x77\x4e\xd4\x6d\x5a\xbb\x72\x0f\x77\xdb\x44\xcd\x08\x7b\x58\xfb\x37\x9f\xe8\xc4\xe2\xfd\x71\xdb\x62\xc6\x8f\x8c\x7c\x23\xc6\xcb\x89\x0a\x8a\xb9\x1a\x1c\xf6\x46\xe5\x87\xe3\x6a\x12\x13\xe3\x46\x27\x8f\x20\x14\x41\x31\x18\xa6\x07\x3d\x9d\x44\x33\x27\x86\xd6\xe6\x34\x1d\xe8\xa3\x4f\xbf\x3a\x7a\x1d\x78\x89\xe9\x05\xe2\x29\x54\x2b\xbc\xb8\x3c\xa5\xcd\xdc\x69\x5e\xfb\x0e\xc4\x2e\x84\x51\xa8\x75\x88\xb3\x9f\x9f\xfd\x7c\x9b\x39\x09\xee\xf2\x19\x6f\xca\x53\x9c\x9c\x17\x84\xa2\x73\x83\x87\xf9\xd9\xd1\x47\x9f\x82\x8e\x09\xb1\x4f\xbb\xb7\xa0\x2d\x0e\x11\x91\xab\xb6\xda\x2f\x7b\x7b\x9e\xbd\xd5\x66\x1b\x09\x7c\xeb\x0b\x0a\xf3\x02\xc4\x00\x40\xe6\x50\x71\xd8\x16\xc7\xbc\x70\x60\xda\x69\x9a\xf6\x27\x65\x12\x99\x9a\x21\x43\x8c\xcd\x9c\x69\xaf\x2d\xf9\x4e\xff\x80\xf8\x0d\x3d\xf7\xf3\x61\x37\x1e\x3d\xf7\x07\x62\x6a\xf7\x63\xe8\x36\xdc\x9f\xd5\x38\x81\x70\xf4\x96\x62\x54\x60\x43\xef\xe9\x8b\x5a\x4a\x57\xc2\x5d\x42\xcc\x07\x02\x68\x91\x98\xca\xa7\x52\x58\x9f\x02\xbe\x93\xa5\x12\x46\xd1\x99\xdd\x19\x0a\x39\xcf\x3c\xbf\x48\xa2\x7d\xd6\xfd\xeb\xfe\xea\xdf\xcb\xaa\xb9\xfc\x25\x3f\xdc\x7f\xfe\xec\xfe\xd7\x79\xd6\xce\xb2\xca\xba\x2d\xbb\x76\x96\x1f\xde\x8b\x7c\xa9\x99\x3f\xfd\x32\xae\x36\xa1\xf6\x3d\x65\x71\x2d\x7a\x84\x9e\xa1\x3f\xd1\x67\xb5\xe5\x84\xe2\xf1\xb5\xaf\xaf\x7d\xfa\xb0\xd1\xcc\x2f\x5e\xc8\xe4\x98\xf6\x8a\x53\x94\xd5\xd5\xa1\x1c\xfa\x9d\x8d\xda\xa1\x6f\x37\x82\x53\x50\x03\x20\x40\x02\x12\xe3\x59\xb3\x0e\xc0\x1d\xcc\x1f\x15\xca\x75\xb1\xb6\xa7\xc4\x3c\x31\xb0\x77\x71\xb1\x21\x01\xe5\xe1\x49\x71\x6c\x6c\x84\x7c\x5b\x37\x92\x74\x7b\x3b\x09\x90\xd0\x86\x24\x49\xa1\x35\x8f\xcf\xe7\xcd\x4a\xe2\x0f\x12\x4a\x67\x25\x09\x5d\xcd\xa2\xb4\xa2\x70\x53\x34\x5e\x28\xc2\x21\x78\x43\xdd\x8f\x31\x6e\xab\x09\x09\xd5\x28\xd8\xf0\x31\xc7\x51\x28\x06\x72\x2f\x60\xd6\xe8\x2f\xe1\xe7\x2f\x6e\xc0\x1d\xfa\xe3\xe4\x62\x24\x83\x09\x6d\xe8\xb7\xdf\x7e\x40\x3f\xb7\xd4\x1c\x3c\x50\x73\xf8\x20\xba\x60\xfd\xd9\x0b\xe9\xe6\x68\x48\xec\x29\x42\x57\xbf\xdd\x84\xfe\xd9\x81\xfe\x05\x45\xff\xf8\xf8\xf8\xf1\x8f\xeb\x1b\x70\xcc\x76\x1e\x2f\x90\x2b\x06\x6a\xc3\xfb\x16\xd7\x08\x49\x99\xb6\xcb\x30\xd4\x7c\x12\x2f\xfd\x2f\xd0\xf4\xf2\x55\xf0\xe4\x1a\x1f\xb5\x50\xc6\xca\x9c\x2d\x21\x3e\x01\x27\x1d\x44\xc9\x4b\x3f\xb8\x76\xb3\x69\x65\x41\xdd\xde\x13\x68\x94\x87\x3f\x23\x7d\x49\xa3\xf3\x0f\x34\x8f\x25\xcf\x61\xc1\xd3\x6f\x0c\x19\x42\x1c\x22\x4a\xd0\x0c\x78\x58\xdf\x39\xf3\xfc\x3d\xbd\xda\x90\xf7\x4a\xb4\xea\x6f\xda\x63\x69\x74\xa9\xfa\xf1\xcd\x2a\xa2\xc0\x10\xcf\x85\xdd\x4c\xbe\xa1\x83\x1a\xd3\x44\x22\x17\xca\x85\xe2\x4a\x5d\x65\xa5\x0e\x76\x97\xc3\xb3\xe8\xb5\x72\x44\xc1\x6e\x00\x81\x75\x4f\x27\x51\xc5\xc4\xde\x8d\xbf\x95\x98\xbf\xd7\xa3\xa0\xf5\xc1\xa6\xdb\xb7\xe3\xa6\x0e\x4b\x73\x71\x5d\x1a\x5a\xb3\xc3\xb0\xc0\xa9\xf4\xb4\x41\xfc\xcd\xb6\xe2\xa3\xf5\x2d\x80\x04\x62\x24\xa6\xda\xb1\x4c\x7a\xe1\x97\x17\xbd\x96\xa1\x36\x44\x25\x91\x73\x59\xad\x4d\xd3\x84\x9d\x3a\xc0\x76\xb4\x13\x57\x32\x1a\xfa\xfc\x13\x69\xda\x4c\xeb\x5f\x3f\xc5\x5a\x5a\xa7\xe3\xed\x3a\x58\xb4\x9b\xaf\xaf\x25\x12\x84\x15\x6b\xb6\xef\x80\x68\x1b\x3c\x5b\x91\x3c\xf9\xd7\xef\xb6\xe9\xd1\x4f\x4c\x5d\x08\xf9\xf4\x86\xee\xfa\x89\x6d\x7b\xdf\xdf\x0d\x08\x20\xee\x79\x4e\x69\x71\xdd\x96\x9b\x01\x13\x99\x01\x1b\xa6\x9e\x4e\xca\x1a\x24\x32\xf1\xf6\x66\xc2\xfe\x44\x79\xf9\xcf\x9f\xdf\x7d\x82\x13\x63\xf4\xcf\xf1\xf2\xe8\x35\xfa\x9f\x6d\x2b\x4f\x7f\xd1\x7e\x29\x67\x65\x7e\xf1\xc6\x75\x2b\xd9\xbc\xe2\x9e\x4e\xaa\x15\x9f\x6f\x3f\xbc\x76\xa8\x86\x16\x2d\x7b\xc8\x93\x05\x40\x85\x5a\x26\x91\x61\x14\x71\x98\x87\x36\x8d\x4c\x1b\x2d\xf1\xdd\x8f\xfe\x80\xff\x98\xb8\x76\x30\x31\xc3\x7d\x75\x1c\xfc\x07\xfa\xa3\x22\x70\xc9\x0c\xf4\xcb\x2f\xdb\xff\x59\xd0\x72\xf8\x40\xe5\x11\x7d\x3e\x44\xdb\x1a\xf2\x2a\xb6\x7a\x55\xe6\x2c\xaa\xf1\xd8\x5a\xb1\xfa\xe3\x6d\xb6\xbf\xa1\x9f\x0a\x7e\xaa\xb4\xb7\xd7\x9e\x3f\xdf\x64\x8b\x6b\x6e\x32\xb1\xad\xe8\x49\x5b\x38\x6c\xb6\x34\x73\xcc\x79\x12\x53\x15\x14\x97\x35\x13\x2d\x0e\x7d\x83\x8e\xb1\x07\xb7\x33\x25\x51\x13\x63\x18\xb3\x50\x65\xb0\x07\xb9\x62\xb4\xd1\x60\x05\xde\xaf\x78\xc2\x16\x48\x89\x69\x6b\x90\x90\x9b\x0c\x41\x02\x64\xa3\x4c\x6a\x0f\x57\x0c\x3c\xb0\xdd\x6c\x5e\xb7\x6d\x51\x89\xf5\xaa\x1a\xee\x19\xcf\x30\x0c\x71\xaf\x28\xe5\xee\x5a\x8f\x7e\x60\x61\xe8\x63\xe8\x41\xe0\x81\x32\xb1\x9d\x87\x7d\x1e\x7d\x0d\x3c\xcb\x92\x30\x0f\x4b\xab\x6e\xc6\xb3\xa8\x91\x01\x61\xe9\x59\xe4\x39\x73\x3b\xae\xfb\x6f\xc6\xfd\xc8\x73\x4c\x7d\x35\x12\x73\x6d\xf1\x9d\x1e\x6a\x5e\xef\x22\x33\x5b\x5b\x26\x31\x77\xdf\x6a\xfa\x62\xbc\xe4\xb7\xbb\xb4\x6e\xdd\x06\xef\x32\x5d\x1c\xd0\xdd\x5f\xbb\x9f\xed\xab\xfa\x63\xcb\x07\xb4\xea\x7d\xf0\x6b\xcb\x8e\xed\xb5\xbb\xf7\x7c\xb8\x79\x37\x21\x87\x56\x30\xb8\x76\x7b\x77\x13\x2a\x60\xc0\xe8\x2e\xe8\xfc\x25\xa6\x36\xa1\xa6\x5c\x59\x7c\x18\xfa\x42\xdb\x4f\x1f\x1e\xbf\xaa\xfc\xfb\xf5\x2f\xd9\x9c\xf9\x4c\xca\x8d\x2b\xa6\x5f\x79\x34\xd9\x79\xb8\x15\x55\xaf\x0e\x0d\x90\x27\x6c\x68\xe2\xf3\xa3\x62\xe0\xdb\xf7\xd0\x58\xb8\x30\x99\x69\x74\x21\x43\x45\xf9\x5c\x71\xf7\xfd\xa6\xf8\xa9\x30\x07\x29\x91\x3b\xfa\xd1\xd0\x48\x02\x64\xa1\x2c\x46\xb7\x4f\x41\x99\xf0\x0c\x57\x8c\xdf\xe9\x2c\x15\x0d\xec\x9d\x42\xd3\x4e\x97\xfc\x6b\x64\xf4\x13\x87\x85\xdb\xb8\xe2\xae\x02\xbc\x80\xa1\xbe\x21\x93\x47\xdb\x41\x01\x18\x2e\x0b\xa3\x57\xd2\xbb\x03\x87\xc1\xfd\xcb\xe6\xf7\xf7\xb2\x72\x93\x99\xd2\xc0\xcc\xaf\xf7\xbe\x77\x3c\x6b\xf9\x9e\x32\xb3\xe4\xa8\xeb\x26\x88\x5b\x69\xa3\x55\x5f\x4d\xb4\xae\x5f\xdf\xf2\xb9\xfe\x9a\x91\x36\xb5\xd8\x7e\x05\x26\xcd\xd3\x7b\x77\xb3\x5d\xb1\xbd\xca\x12\x27\x73\x65\xc1\x87\x7b\xd9\xdc\x36\xf3\x7d\xce\x6d\x2c\x3a\x7d\x1f\xaf\x8f\xeb\xde\xb0\x4d\x8a\xcf\xa0\x83\x99\x39\xda\xeb\x08\x0e\x5c\xfd\xf6\xf0\x67\xe3\x21\xec\xb7\xf0\x0d\xdb\x9c\xf7\x2b\x3a\x0c\x67\xb0\x4f\xf1\x9b\x81\x47\xd8\xe6\x74\x33\xe3\x91\x85\xd1\x29\x31\xe7\x98\xa5\x99\x69\x60\x1f\x15\x67\x34\x2c\xd1\xeb\x66\x7c\xcc\x40\x99\x64\x1e\x95\x02\x02\x0d\x91\x0a\x93\xcb\x8c\x90\x88\x7b\x23\x6a\x30\xef\x14\x01\x44\x86\x99\x5d\x57\x52\x34\x32\x9b\x11\xfb\xb8\x24\x83\x59\xb7\x6f\x5d\x04\x19\x61\xb2\xe7\x54\x89\x8b\x27\xed\x9d\x7a\x8d\x41\xb4\x54\x60\xb0\xe9\x22\xa7\x31\xf9\xd6\x3d\x57\x90\x98\x54\x71\x3d\xc0\x10\x00\x48\xe6\x75\x2e\x90\x05\x4b\x25\x4c\xe1\xac\xe5\x51\x14\x0a\x64\x5e\x8a\x88\xc0\x88\x58\x0d\xb4\x9f\x19\x22\x1c\x39\x38\x56\x63\x3a\x75\xe8\xf9\xac\x60\x74\xce\x31\x69\x11\x67\x26\x4c\x90\x95\xf0\xed\x93\x16\x76\xab\x8d\x27\x0d\xe9\xd1\x51\x19\x53\x03\x8a\x32\x29\x01\xce\x33\x8a\x1e\xe5\x69\xe3\x0a\x44\xb6\xb6\x1c\x7b\xa9\x94\x43\x91\x2e\xae\x94\xb3\x35\x18\xe4\x6c\x9b\x92\xe4\x2c\x11\x48\x66\x27\x09\xe4\xac\x2d\x02\x9c\xa2\x55\x38\x61\xcc\x50\x73\x1c\x4c\x5b\x1e\x42\xa6\x77\x1a\xa1\x71\x50\x41\x0b\x38\x2f\x76\x8c\x73\xe0\x93\x56\xb6\x63\x9f\x5e\x40\x3b\xa1\x07\xa3\x09\x51\x01\x15\xa7\xcf\x6b\x4d\xb5\x93\x29\x3e\x23\x8a\xbb\xc7\xa1\x4e\x96\xf7\x6c\x5f\x17\x2e\x73\x2f\xff\xb5\x56\x2c\xde\xc9\xbf\xd2\x1a\x2e\xcd\xa5\x57\x2b\x96\xb9\x46\x0d\xc7\xb4\x1c\x01\x10\x4c\x46\x99\xd8\x5e\x75\x30\xcb\xcd\x33\x5b\x7a\x32\x11\x4f\x5b\xa7\xfa\xd3\xc4\x54\xe6\x7c\xac\x24\xc7\x6f\x29\xee\xbe\x6e\xac\x9f\xa5\xcf\x43\x0a\xca\xa4\xba\xa8\x99\x78\x36\x16\xe8\x67\xec\x18\xe3\x58\x61\x5c\x37\xf8\x5e\xe8\x1d\xeb\xee\x35\x6c\x2c\x39\x54\x1d\x30\xdc\x2f\x29\x37\x27\xa2\xd7\xd4\xb1\x3e\x23\xc6\x8e\xa2\x9f\x62\x23\x44\x65\xce\x5b\x8b\x0b\x2d\x86\x8d\x19\xea\x15\x33\x39\xa9\xf8\x7c\xf8\x99\xeb\x6f\x33\x70\x84\xea\x01\x6f\x29\xbe\xdb\xb6\x19\x6a\x75\x90\xbf\x5f\xd2\x93\x01\x6e\xa9\xad\xdd\x13\xd9\xed\xa1\xa4\xb0\xaf\x2f\x02\xd7\x4b\x72\xf8\x5c\x0f\x30\x14\x5b\x88\x26\x7f\x89\xc0\x60\xa3\x4b\xcc\x21\x09\x09\xed\xe7\xfa\x30\x5c\x98\x2f\x62\xa3\x03\x23\x02\x83\xfd\xc3\x46\xf9\xf8\xcd\x7d\x66\x4d\xda\xad\xf8\xaa\xfd\xe7\x7e\xae\xcd\x6a\xe8\xe1\xba\x4b\x1c\x3a\xba\x6b\xf6\xd2\x69\x8e\x25\x32\x98\xb0\xde\x69\xa5\xe8\x7d\xe8\x07\xad\x8c\xa0\x31\xf7\x77\x13\x95\x02\xdc\x71\x65\xb8\xe5\x34\x28\x73\x88\xb8\x72\x2f\xd0\xef\x24\xa8\x50\x86\x2e\xc9\x59\xff\x46\x4f\xce\xf5\x3b\x01\x0a\x69\x59\xc2\x14\x88\xa0\x12\xae\xae\xac\xaa\x05\x10\x24\xa2\x4c\x6a\x26\x95\x02\x86\xff\x85\x7a\xf4\x5e\x70\xbc\xa2\x34\xdd\x00\x4c\xce\xc0\x15\xea\xa8\xde\x08\xcd\x47\x00\x82\xb1\x28\x93\xdc\xc6\xdc\x51\x52\xe1\x7f\x9f\x4b\xa1\x90\x18\x61\x19\x70\x14\x45\x6e\x2a\x0b\x46\x21\x4c\xe8\x7f\x00\x85\x28\x1f\xc3\x80\xe3\x02\x28\x93\x93\x4b\xa5\x00\x19\x7e\xb3\x59\xce\xec\x91\x9a\x49\xa7\x33\x53\x6d\xd9\xcf\x88\xa7\x5f\xa1\x0b\xaf\x92\x39\x25\x3f\xba\xf7\x5c\xe8\x6f\xd6\xd3\x0f\x2f\xf5\xe1\x2c\xd6\x84\xfa\x6f\xcf\x4c\x33\x9f\x08\x50\x85\x32\x89\x0d\x9c\x1f\x80\x8d\x31\x57\xc3\xcc\x7f\x6f\x71\x3a\xaa\xa2\xfc\xfd\xa2\xa3\xfd\xfc\xa3\xec\x75\xc9\x2c\x82\x9c\x9c\xc8\xd0\xd0\xc8\x88\xb0\xb0\xae\xeb\x54\x9c\xf9\x09\x60\xee\x0d\x9a\xb6\xf3\xa8\x14\x5c\x63\x61\xaa\x3d\x31\x23\xa1\x33\x34\xbb\x0e\xc7\x06\x55\xa5\xfc\x0c\xb9\xe8\x8f\xdf\x62\xfd\x42\x43\x02\x87\xfb\x25\x3f\xd9\x52\x7a\xb8\xb2\xaa\x5a\xb3\x31\x98\x92\x3b\x7b\xa1\x2f\xd1\x73\xd4\x81\xfe\xc6\xcf\x61\x77\x81\xb1\xa3\xee\xb7\x5d\xfd\xdc\xcd\x99\xb9\x1b\x32\x89\x89\x5c\x0f\xfa\x9e\xe7\x09\xfb\x5e\x0e\x62\x2e\xcf\xb4\x6d\x44\x50\xb8\xd9\xbd\xb0\x6e\x9d\x91\x5d\x52\x69\xd2\x22\x72\x83\xf1\x4e\x58\x73\xa8\x81\x97\xc5\x72\x8a\xc6\xa7\x1a\x65\x72\xe6\xb1\xef\x79\xf3\xb8\x43\x6f\x25\x82\x55\x5a\x75\xf3\xca\xfc\x0f\x2b\x4f\x24\x87\x86\xe0\xc5\x27\xba\x58\x05\xe9\x56\x5e\xbd\x01\xd7\x10\x6d\xfa\xa8\x0d\x85\x67\xee\x12\x91\xe6\x14\x2b\x7f\x23\xe1\x1c\x30\xca\x63\x1c\x4d\x33\x73\x79\x34\xcf\x79\xb6\x94\xc1\x3e\xe9\xcf\x16\xe2\xd7\x3b\x0f\xda\x28\x79\x86\x3c\x95\x99\xc6\x3c\x1d\x8b\x98\xaf\xc2\xf2\xb9\x50\xbe\xc5\x7e\xe8\xa2\x37\x0f\x1c\x6b\xa8\x2a\x9e\x69\xef\x94\xba\x60\xc6\x8c\x19\xb3\x32\xde\xa6\x1f\xf5\x19\x61\x51\x77\xce\x9c\xbd\x97\xbb\x00\x6e\x60\xa2\xbd\xcb\xdf\x31\xc4\x9e\x89\x73\x9c\x56\x9c\xed\x65\x8a\xb3\x99\x29\xff\x8c\x4b\x27\x23\x57\xfa\x05\x2e\x79\xed\xf6\x9c\xd9\x73\x57\x4c\x7b\xb7\xf1\x1c\x15\x74\xe1\xde\x60\x71\x81\x02\xfd\x59\x50\xac\x2e\x09\x6c\x63\x73\xa5\x32\x88\x17\x9c\x56\xe0\x86\xfb\x0a\xf4\xf6\x2e\x49\x4d\x31\x0d\x2e\x4f\x63\x04\x38\xd9\xcf\x4b\x7d\xa5\x39\x37\x33\x68\xc9\xd8\x05\xe9\xfc\x8c\x82\xac\xc2\x8a\x15\xa5\xd3\x04\x1e\x85\x9a\xa9\xc1\xd1\x3e\xc3\x67\x10\x35\x99\x23\xd2\x8a\x2f\xde\x1d\x5e\xa0\xd8\xb0\xc1\x5b\x9d\x98\xfe\x56\x6a\xb6\xda\x7d\xfa\x73\x95\x52\x2e\x19\x62\x16\xfb\xe7\x76\x01\x57\xe0\x63\xca\xb1\x51\xf0\x14\x1a\x1f\x85\xc6\x51\xaa\x91\xf2\x1c\x45\x66\xd1\x42\x86\x4c\x19\xe7\x6b\xc2\xdf\x0e\x50\xa5\x5d\x1c\xbf\x6f\xa9\xcd\xd8\xcc\x29\x47\x63\x4b\xe7\x2f\xbe\xd8\x5c\x7b\xab\x76\xf1\xdb\x6d\x4b\xdf\x5e\x34\x9b\xa2\xaa\x4f\xb9\x78\xe7\xa7\x64\xcd\x4f\x8c\xe4\x64\x0d\xd7\xa4\xcf\x9f\x94\x8e\xfe\xbd\xf7\x6a\xdb\xb9\xca\xcc\xec\xae\xa4\xf9\xcb\xfe\xa7\xf3\x4e\x20\x08\x24\x74\x44\x26\xf7\x39\xd3\xc7\x44\xa3\x16\xc8\x8c\x4f\x25\xc6\x19\x10\xb8\x01\x5a\x4f\x4c\x1d\x3a\x7e\x84\x3a\xa4\xb5\xb5\x86\x13\x31\xd9\x57\x06\xdd\x64\x79\xae\x13\xde\x94\xad\xd1\xe7\x11\xc5\xf4\x59\xbb\x05\x33\x60\x35\xee\xb5\x60\xcc\x19\x95\x1b\xfd\x09\x34\x54\xea\x09\x0a\x85\x7f\x66\x66\xed\xc2\x85\x4b\xf3\xa2\x61\x7e\xa1\x44\x19\x09\x5b\xf2\x61\x20\xba\x9b\x8f\xe2\xb2\x0a\xfe\xdf\xe5\xbf\x40\x50\x06\x33\x48\x0d\xee\x25\x63\x11\xb3\x97\x0b\xd9\xed\xca\x6a\x2a\x16\xa4\xd7\xd4\x58\x0d\xcd\x8f\xde\x55\x81\xe3\xf3\xd2\xda\x55\x9b\xe0\xb6\x97\x4d\x30\x49\x15\x14\x39\x7a\x13\x20\x80\x82\xd0\xc1\x6a\xee\x6d\x36\x97\xd3\xcc\x93\x62\xde\xdc\x58\x41\xa3\x5f\xcb\x37\x44\x40\x29\x6b\x16\xff\xa3\x30\x81\x98\x8b\x63\xa1\x01\x01\x34\x3c\x44\x1d\x21\xc6\x7d\x1f\x8d\xf0\x30\xe7\xa3\xac\x26\xd9\x63\xaa\x63\x74\xf2\x3b\x8b\xc9\xfd\x84\x8b\xfe\xc7\x3c\x01\x7f\xb5\xeb\x6a\xa6\x2f\x13\xa1\x83\x0f\x58\x5f\x9b\x59\x8e\x6f\xfc\xd2\xa5\xb0\x38\x3b\x9b\xd0\xa5\x3a\x13\xf6\xae\xa9\x69\xce\xfa\xe7\xce\xa9\xe6\xbf\x77\x60\x78\x2e\x57\xab\xd4\xf8\x1b\x89\x4a\x22\x97\xd0\xdf\x65\x64\xd0\x5f\x66\x65\xe1\x6f\x1f\xe7\xeb\xe8\x8f\x75\xf9\x8f\x9d\x71\x1c\x91\xec\x29\xa7\xf9\xcd\xbd\x0d\x06\xe1\x8e\xeb\x80\x0c\x09\x8d\x80\x0c\xce\x66\x1c\x52\xcb\xbd\xcc\xaf\x8f\x25\x99\x4b\x14\xb5\x0b\x17\x92\x99\x73\xe6\x2d\xa9\x72\x71\x70\x76\xf1\x1c\x95\x68\xa0\x05\xc1\x4f\x7a\x8b\x24\xba\xd1\xe2\x45\xcb\xa6\x4e\x76\x71\x0b\x8e\xa6\x7c\x0d\x04\x61\xe2\xc2\x30\x83\xa0\xb8\x1d\x38\xcf\x85\xa1\x09\x43\x92\xf2\xda\x44\xef\xc9\xd1\x31\x6b\x97\x11\x33\xa9\xb2\x97\xb9\x2b\xa5\x79\x6e\xab\x69\x79\xbc\x08\x33\xa0\x8a\xdb\xd1\x37\x87\x39\x3a\xde\x27\xd0\xb7\x36\x67\x75\x0c\xdc\x90\x27\x8d\x8c\xa0\x4a\x5f\xe6\xac\x5e\x6d\xcc\x65\x22\xca\x39\xcd\x80\xc3\xfa\x2b\x25\xe5\xb5\x30\x99\x56\x68\xfa\x82\x42\x16\x06\x9c\xab\xa4\xe8\x93\xab\x24\xa6\x45\x94\xbe\x86\xd5\xaf\x48\x5a\x3a\x1f\x3a\x62\xd0\x48\x61\x60\xdf\xd4\x25\xfd\x8e\x36\x69\x31\x4f\x38\x9a\xc8\xb6\x48\x60\x62\xf2\x49\x60\x06\xce\x27\xf1\x1c\x20\x9f\x84\x95\x51\xdc\x35\xce\x94\x50\x52\x6b\x8b\x13\x4a\x12\xab\xfa\xcb\x27\x79\xd9\x04\x47\x8c\x1b\x39\x3e\xb4\xb8\x78\x23\x1b\x13\x83\x19\x64\x04\x93\x27\x65\xa4\x15\x8d\x9d\xa7\x33\x34\xe0\x21\x96\x7b\xd9\x47\x7a\xfa\xb8\x6d\xb5\xf5\x79\x77\x0a\x14\xbf\x5f\x91\x99\xde\x36\x06\x16\xaf\x71\x0d\x79\x8d\x4c\x5c\x1e\x35\x16\x7d\x8b\x04\xf0\x69\x4d\x5e\x31\x72\xf9\xdd\xc0\x2f\xf2\x6b\x4e\xab\xe1\x16\x61\xc9\x64\xf2\x15\x9a\x65\x5f\xcd\xdd\xb6\x79\xbb\x9b\xaf\x30\x42\x24\x7e\xcd\xeb\xd3\x8a\xcc\x74\x9a\x32\x4b\xf3\x37\xed\xd6\xb7\x44\x87\x89\xac\xd6\xd8\x3a\xfc\x4e\x8c\xa1\x57\x5e\x66\xc8\x37\x9b\x68\x3c\x1b\xd0\x54\x5c\x5b\x7e\x16\x66\xf0\x0f\x9e\x45\x95\x7c\xcc\xb1\xf6\xe0\x69\xb0\xba\x1b\x11\xbe\x91\xd3\x50\x06\x20\xcd\xf2\xb6\x84\x6c\xd5\xaa\x29\x73\xcb\x91\x71\x31\x5a\xa4\x6e\x1d\x15\x9f\x98\xfd\xb6\x15\x5a\x0a\xb7\x4a\xb5\x29\x33\x8d\x09\x5c\x85\xed\x59\x99\x85\xad\x69\x34\xdd\xb8\x58\x5f\x75\x71\x5f\x00\x21\x70\x04\x52\xe0\x04\x9c\x99\x3c\x0e\xdc\x06\x19\xdb\x86\x4c\xe4\x5b\x23\x96\x0a\xb9\xae\x24\x8e\x7f\x2b\xe6\x5d\xfe\xe4\x60\xe3\xf5\xd6\xe6\xea\x86\x5b\x47\xef\xdf\x2f\x86\x87\xe2\xe6\x2d\x48\x5d\x42\x8d\x69\xf8\x54\x08\x95\xe8\x81\xf3\xfd\x43\x1f\xdd\x16\xa1\xf3\x70\xb4\xe4\xde\x07\x4f\x3d\x08\xa1\x07\x3c\xd7\x55\x40\xcd\xd0\xaf\x10\x17\x2f\xce\xd9\x20\xc0\xb4\x4d\x83\x19\xc4\x51\x4e\xab\xb1\x76\xae\x57\xba\x8a\x12\x2a\x4c\x39\x8e\x6a\x21\x73\x15\x29\x02\x88\xb4\x9a\xb2\x6d\x6b\x43\x0b\x67\x8e\x1d\xf7\xfa\x92\xb2\xf4\xa3\x95\x41\xfe\x89\x2e\x6f\x46\x47\xae\x5e\x56\xb1\xf4\xe0\xe4\x94\x15\xd3\x95\xd4\xb3\xb4\xec\x11\x6b\x42\x7d\xe5\x43\x42\x7c\xd5\x8b\x5e\x5f\xb2\x82\x98\x48\x9f\xa7\x55\x6b\xa1\x30\x36\xd5\x37\xcc\x6b\x58\xc4\x24\x83\xbc\xc0\x47\xdc\xe7\xc0\xd1\x24\x2f\x21\x2a\x33\xbb\x8a\x95\x95\xbb\x13\x86\x39\x69\x06\xf9\xb8\x1b\x05\xa5\xea\x77\x8f\x35\xb6\x83\x42\x47\x77\xa7\x32\x32\x12\x04\x57\x12\x72\x6e\x16\xe3\x85\x35\xcf\xff\xd2\x98\x94\x7e\x14\xf4\x32\x65\x81\x05\xbc\x39\x3d\x4d\xa5\x09\xf6\x0b\xfc\x99\x13\x17\xaf\xaa\x3e\x9a\x87\x52\x47\x86\x4b\xd1\xbf\x52\xe7\x39\x16\x89\xc3\x0b\x9e\xc3\x1a\x7c\x4f\x2b\x88\x3a\xb2\x1a\xf7\x9e\x70\xef\xe5\xdf\x35\xa4\x83\x18\x1c\xaf\x1a\x99\x62\x4e\x2d\x4c\xad\xc9\xca\x62\x33\x43\x6a\x63\x27\xce\x9b\xcd\x41\x55\x94\x28\x1f\x2a\xd0\x23\xfa\x9f\x7c\x54\x9d\x1d\x3e\x76\xc3\xce\x37\xc7\x4f\x9d\xbc\xa8\x00\xdb\x63\x44\x1d\x99\xc3\xe6\x78\x61\xe7\xae\xc4\x98\x1d\xa4\x96\x49\xe4\x86\x9c\x21\xfa\xc5\x36\x16\x66\xbe\x3e\x2d\x23\x3d\x6d\xe1\xac\x71\x30\xeb\xfc\x84\x37\xaf\x69\x3f\xba\x3a\x25\x8e\xa3\x2e\x5c\xee\x79\x38\x6b\xc9\xea\xd5\xd9\x73\x8f\x0d\x5e\x5e\xe8\x7f\x20\xa9\xee\xd2\xf1\x7d\xd9\xbb\x35\xc6\x5c\xb6\x70\xdc\xff\xb4\x9f\xfa\xcc\xd2\xda\xe9\x33\x66\x4e\xff\xe0\xfd\x13\x27\x3e\xa0\x28\xd8\x84\xa6\xac\x5a\xb0\x60\x15\x6c\x40\xf1\xcd\xb5\x75\xc6\x6f\x5b\x71\xd7\x1f\xc3\xb7\xcc\x45\xc9\x24\x16\xba\x41\x76\x95\xc9\x69\xb3\xa7\x78\x0d\x0b\x51\x8d\x89\xc8\x9d\x77\xe4\xd8\xf1\xc3\xcc\x62\x2b\x16\x66\xe4\x5d\x19\x13\x60\x5f\xe8\xb0\x62\xed\x6d\x6d\xfd\x11\xd0\x3b\xe7\xcc\x54\xf3\x25\x82\xfe\xc7\xa0\x7f\xe3\x61\x0f\x7b\xf1\xe0\x23\xf4\x99\xeb\x46\xf0\xfc\xf4\x69\x33\x27\xa3\xd1\x00\x82\x29\x84\x8e\xa8\xc5\xbd\x4a\x81\x83\xb1\xa6\x6f\x0a\x2c\x43\xa5\x44\x08\x5a\x01\xb7\x13\xba\x54\x42\xb1\x66\x91\xfe\xfb\x3c\xd6\x57\x85\x73\x94\x70\xbf\x10\xd3\xef\xcd\x6a\xe7\xa2\xa0\xd9\xc7\x6e\x3e\xc2\xd1\x76\x21\xe3\xd2\x53\x8c\xab\xb4\xbd\x16\x22\xe6\xad\xf1\x58\xb5\x36\x11\x10\x60\x0a\xa1\xc6\xb9\x80\x12\x86\xff\xcc\x6a\xac\x97\x4f\xac\x84\x3c\x45\x34\x61\xb0\x0a\x8d\x8b\x4e\x19\xf7\x4e\xf2\xa4\x74\xb4\x2c\x74\xd5\xa0\x41\xad\xe3\xd4\xc3\x5c\x24\xd1\xc6\xc5\x0b\x66\x26\xbe\xf6\x49\x41\x90\xdf\x90\x3c\x99\x58\xcc\xda\xfd\xfe\x30\x83\x78\xc0\xf4\xf8\x73\x30\x1f\x0d\xc9\x6c\xc6\x8a\x80\x7f\xe4\x81\xd8\xf9\x6b\x37\xaf\x5f\x00\x7d\xd1\x2c\x62\x11\x7a\x74\xa0\xf1\x91\xee\x23\x78\xa0\xdc\xdd\x77\x55\x7a\x7a\xe6\x3c\x18\xf5\xee\x42\x74\x5e\xd4\xb0\x71\xdf\x45\x3c\x33\x96\xa8\x23\xc7\x70\xbb\xd8\x79\x43\x2e\xc0\xa2\x4f\x93\xc6\x22\x12\x02\x33\x4e\x34\x9f\x68\x39\x79\x4a\x77\xb2\x96\x9a\x39\x37\xfd\x6d\x1e\x5a\x06\xb7\x58\xcf\x4a\x9d\x9d\x0c\xbf\xa0\xee\x42\x17\x38\x08\x3d\x45\x3f\xa3\x1f\xd0\x73\xe8\xf4\xd5\x99\xb3\x67\xce\x16\x7e\xd4\xd8\x08\x87\xe2\xbb\x1b\x55\x73\x6c\x61\x0a\x37\x0b\xd8\x00\x09\xad\xb1\xcc\x07\x7f\x3a\xa8\x55\xee\x50\x2a\x91\x07\x40\x4e\x88\xf1\x3f\xa2\xea\xd0\xa1\x3e\x61\x61\x3e\x43\x43\x4f\x5d\xb1\x0b\x93\x26\x44\x67\x43\xff\x14\xef\xf0\x70\x6f\xbf\x10\x4e\x4e\x68\x00\xee\x5a\x0d\xed\xc5\xd1\xba\x48\xa7\xf8\x06\xbb\xb9\xb8\x3a\x97\xde\x27\x9f\x63\x0b\x8b\xf0\x3e\x0e\x34\x27\xcc\xf7\x91\xaa\x43\x35\x2a\x09\x97\xa7\x31\xdb\x25\xdf\xb0\xcb\x8b\x51\x83\xaf\x24\xe4\x76\xf7\xde\xc2\xdb\x49\xb7\x46\x5c\x5d\xfe\x2b\xbb\x01\xec\xd9\x80\xe2\xc1\xbc\x9e\xa3\x40\x09\x00\x2f\x54\x15\x2c\x11\xdb\x13\x12\xb1\x3b\xc1\xfc\x95\x4a\xbc\xd4\x21\x23\x09\x75\x48\x00\xc1\xfc\x95\x7b\xf1\xd6\xbc\x16\x9a\xe1\xe9\xe3\xe9\x36\xc4\xcd\x6d\x88\x5b\x72\x93\x6c\xa8\x4c\x36\x54\x26\x57\xca\x83\x87\x05\x64\xbb\x46\x39\xbb\x39\xd8\x59\x71\x79\x36\x0e\x22\xa1\x83\xad\x15\xcf\x9e\x0a\x8a\x16\x48\xec\x6d\xb8\x7c\x2b\x6b\x81\x60\x90\x54\x24\xe0\x0b\x25\x34\xef\x51\x31\xf5\x18\x66\x73\xda\x69\xdb\x09\xaa\x55\x62\x55\xf0\x48\x02\x67\x96\xdb\x13\x34\x1a\xc5\x45\x0b\xfd\xd2\x57\x6d\x9b\x2e\xb4\x8b\x7f\x77\xe5\xd2\x11\x8b\xd7\x72\x4e\x79\xe4\xca\x95\xf2\x02\x6f\x7f\xef\xc5\xf8\xfb\xbb\xd4\x23\xa8\xe1\xfc\x4e\xdb\x19\x50\x2d\xd3\x48\x39\xe8\x2e\xf4\xee\x1e\x87\xfe\x41\x3d\x2a\xdf\x5c\x58\x89\x7f\x73\x83\x7a\x04\x03\xd9\xdf\x68\xa4\x32\x89\x0c\xdd\x18\xd7\x0d\xbd\x51\x33\x27\xa7\x70\x73\x39\x60\xd7\xb9\x02\x35\x9c\xaf\xd9\x75\x38\x3c\x05\xba\x0b\xe3\xe0\xe0\x71\xdd\x9c\xf8\xf2\xbd\x85\x25\xec\x3a\x57\x60\x20\xfb\x1b\x6f\x99\x44\xc6\x43\x37\xe0\x60\x18\x87\xbe\xec\xe6\xc4\xec\x2d\x67\x7e\x33\x86\x6a\x85\xe7\x38\xdf\x02\x1e\xde\xcb\x9b\xc3\x53\x70\xd0\x98\x71\xcf\xa1\x1b\x1c\x3a\xee\x39\xfa\x9e\x93\x52\x58\xb4\x61\x5f\x61\xd1\x86\xde\xbf\xf5\xe6\x68\xa4\x1c\x6f\x1e\x1a\x03\x87\x42\xb7\xe7\xe3\xd0\xdf\xd0\xf7\xcf\x39\x31\xfb\x36\x14\x15\xee\xdb\x50\x04\x60\x4f\x32\x12\x03\x6d\xcf\x39\x60\x0f\x00\x0f\x9b\x00\x86\x67\x85\xbc\x76\x01\x7f\x74\xa2\xc2\xdb\x7e\xb0\x4f\xdc\x6b\x79\x13\x27\x27\xf3\x17\xdb\x26\xcd\xd8\x42\xdf\x2d\x53\xa9\x53\xa0\x86\x3b\x85\xb6\xf3\x48\x56\x46\x1c\xa5\x12\xb9\x4f\xfd\xaa\x8b\x52\xff\xf7\x72\x63\xa5\x5f\x70\xc6\x94\xba\xcf\x5f\xe0\x36\x7e\xc4\xb0\xf9\x38\x16\x41\xa0\x62\x24\x86\xdb\x7a\x1a\x80\x1d\x7d\x93\x70\x54\x8e\x52\x89\x3d\xe4\xc9\xd5\xa1\x1a\x1f\x85\xb7\xca\x51\xaa\x09\x65\x06\x50\xc8\x03\xa0\x02\x15\x4b\x1f\xcc\x09\xfc\xe8\x6d\xa9\xa2\x62\xf1\x1b\x30\x2b\xc3\x2f\x4a\xea\x27\xcf\xf0\x8c\x77\x2b\x95\x4c\x71\x9f\x92\xe9\x51\x6a\x1b\x1b\xbc\xc0\x25\x2e\x34\x68\xc2\x88\x8f\x22\xb3\xc3\x9c\xa2\xae\xcf\x98\xfa\x45\x30\xa0\x00\xd0\xdf\xe5\xb8\x72\xce\x00\x1e\x3b\x81\x10\x04\x99\xea\x38\x69\x6d\xd8\x3b\x13\x9c\x7d\x25\x13\x11\xb5\xc4\x88\xf3\x5a\xfd\x99\x86\x4e\xd8\x56\x13\xe3\x2e\x3b\xb8\x7a\x6e\xfa\xfa\xfc\x8c\xf9\xab\x16\x8d\x08\x57\x8d\x1a\x13\xa4\x1a\xc5\x39\xd3\x35\x16\x5e\x41\x11\x44\x06\x3c\xfd\xe5\xaa\xf4\xae\xe2\x39\xb9\xb9\x69\xe9\xab\x72\xe7\x84\x46\x45\x85\x86\x45\x44\x30\xf3\xa4\x53\xf4\x77\xc9\x76\x6a\x26\x70\xc1\x73\xc8\xa2\xfa\xf5\xa3\xf6\xe3\x39\xed\x93\xa1\xce\xc2\xd5\xcb\xa3\x5a\xd4\xcb\x91\xea\xdd\x07\xca\x3e\xae\x55\xb1\x85\x43\x55\x6f\xd5\x07\x6a\x0a\xf7\x35\xbb\xc2\xd3\xe0\x37\x82\x8c\x89\x47\xca\x3c\xcd\xa6\xe5\xca\xbd\x4d\x49\xd6\xfd\x8c\x1b\xb8\x06\xdf\x87\x3e\x90\xb3\x75\xd3\x87\x87\xd0\xef\xcf\x50\x33\x54\x68\x8f\xea\x74\xe8\x09\xb4\xaf\xdf\xff\xd1\x27\xcf\xf7\x1b\x7c\x4f\x9c\xe6\x63\xa7\xd7\x7f\xe8\x6c\xed\xa6\x2d\xbf\xfc\xf7\xfd\x9b\x36\x17\xe5\x57\x2e\x2e\x5c\x95\x09\xeb\x59\x47\x14\xae\x11\x6a\x60\x73\xe8\xc4\x06\x48\xcc\x22\xa3\x44\x7f\xd1\x50\x73\x48\x0c\x91\x51\x43\xa6\x9c\x31\x24\xfa\xb9\x01\x06\xf3\xd8\x28\x9b\x21\x67\x8a\x89\x92\xb1\x06\x48\x28\x70\x0d\xed\xa1\xae\x70\x9a\xff\x87\x68\xb2\x21\x7a\x98\x32\x3a\x22\x70\x78\xc4\x00\x34\xf9\xcf\x6f\x91\x1a\x4d\xa4\x3a\x2a\x92\xa1\x09\xda\xf3\x3f\x40\x93\x76\x03\x0c\xaf\xa4\x49\xf7\xd7\x06\x48\x68\x9a\x7c\xce\xd2\xc4\x01\x0c\xa6\xcf\x56\x6f\x9a\x70\x64\x12\x99\x43\x1f\xba\xf4\xa2\xc5\x0a\x22\x55\x5f\x35\xaa\x17\x41\x2c\xe8\xb0\xaf\x1c\x5e\x37\x92\x02\xe3\xff\x39\x8b\xbf\x13\xb3\x6b\x3f\xf8\xd3\xaa\xb7\xdf\x28\xb9\x01\x6f\x25\xbd\x2d\xbf\xbf\x18\x39\x8b\xf3\xbe\x72\xf2\x0d\xb3\x34\x49\x40\x82\x7c\x24\xa6\xda\x78\x39\x40\x0a\x7c\x71\x44\x04\xf7\xe0\xc5\xba\x91\xe9\xc0\xcb\xe4\x1e\x01\xd6\x11\xaa\xd0\xa8\x0c\x59\x52\x0e\xc6\x61\x3a\xf9\x47\x60\xf4\xdf\x7e\xac\x8f\x3b\x76\xa0\x13\x3d\x87\xdc\xe7\xfb\x5b\x67\xd5\x2f\x45\x67\xd1\x07\xb0\x66\x48\xec\x84\x49\xa7\x13\x57\xaa\x9b\x76\xef\x19\xed\x9d\xe7\x93\x3b\xf4\xd1\xb0\x96\x68\xe2\xf1\x77\x70\xea\xa9\x84\xfd\x93\xd1\x65\xf4\x0b\xfa\x01\xdd\x1e\x51\xe5\xe5\x0c\x4b\xf4\x2e\xd6\x0a\x55\x92\x93\x36\xcb\x67\x73\xfa\x22\x1b\xbe\xad\xf3\xf0\xc6\x78\xc9\xa8\x4b\x41\x0c\x9c\xd9\x48\x4c\xee\xe0\xca\x80\x23\x18\x8a\xfb\xd2\xd0\xb0\x39\x5a\x34\xe0\xc2\x11\x80\x57\x80\x99\x0d\x6d\xfe\x3d\xf9\x80\x4a\x53\x9a\x56\x7b\xf0\xe0\xbe\xf2\x2d\xcb\x3e\xfc\x19\xbd\x78\x61\x01\x61\x92\x01\x42\x0f\x28\x86\x4a\x99\x4b\x45\xc8\xdd\xb6\x6b\xf7\x47\x55\x45\x40\xb9\xfe\x1d\x73\xe8\xb8\x2d\x26\xe8\x48\x5a\xb7\x70\x92\x79\x1a\x5c\xfb\x3d\x98\xed\xe4\x25\x64\x3b\x79\x09\x80\x4c\x6e\x79\x68\x2e\xc1\x69\x70\x2d\xca\x45\xdb\xbe\xbe\x46\x4c\x41\x3f\xa3\xa7\xcf\xae\x98\xb4\x07\x2a\x41\x47\x51\x05\x2a\x3c\x48\x8c\x83\x52\xe8\x61\xa9\x37\xcc\x7b\xdd\xf7\xce\x66\xe8\x2f\x36\x64\xbe\xef\x80\x1d\xe9\xdf\x33\x6c\xfe\xaa\xd6\xf4\x44\xb1\x39\x1c\xd7\xd0\x1e\x4e\x32\xa7\xf9\x7f\x1b\xdf\xab\x26\xcd\xd0\x0b\x5f\x4b\x9d\x90\x8d\xf6\xfc\xdf\xc7\xb7\xc1\xb0\xf9\xab\xf0\xed\x76\x37\x87\xe3\x1a\xfa\x9c\xc5\xd7\x16\x88\xcd\xf0\xe5\xd1\xe7\x91\xc5\xd9\x0c\xcf\x3f\xe9\x53\x28\x35\x20\x6b\xc2\x71\x5f\x39\xbc\xc9\xa0\x89\x71\xfb\x9c\xc5\x4d\x8a\xb3\xf5\xfb\xc3\xcd\x78\xdc\x07\x98\x2a\xf0\x31\xbd\x91\xdd\xc0\xa3\x05\xd0\x9b\xe5\xe4\x04\x63\x2c\x8d\xc6\x23\xc2\xc8\x37\x97\xfe\xf8\x66\x38\x2a\xf2\xfe\xb8\xb6\xc7\x31\x94\xdf\x24\x98\xad\x4a\xeb\xcb\xb5\x08\x55\xcb\x18\x51\xf4\xe9\x48\x8c\x57\x84\x91\x67\x7e\x7f\x85\x67\xc6\x3d\x07\xe4\xd8\x76\xc3\xc6\xaf\xe2\xd8\xcb\x0c\x13\x0c\xd7\xd0\x7c\x16\x4f\xfc\xea\x36\xe2\x89\x13\x82\xb1\x05\xa7\xe0\xf2\xe4\xfd\x70\xae\x07\xe4\xcf\x77\x3a\x15\xf2\x69\x41\xf2\x86\xa2\xc4\x35\xb2\xbe\x2c\x44\xeb\x36\xbe\xa3\x9c\xfb\xa9\x54\x5d\xf4\x4e\x18\xa1\x61\x99\xc9\xca\xea\x7c\x16\x6f\x19\x08\x18\x00\x6f\xcb\xed\x5f\xc5\xd9\xf5\xe6\x70\x84\x0d\xcc\x61\x7d\xa6\x09\x1e\xf2\x94\x29\xa2\x8b\x75\x12\xf9\x82\x9f\x82\xeb\x5e\xa4\x96\xfd\xfb\x20\xfd\x2a\x54\x33\x90\x5c\x23\x83\x0c\x3d\x86\xf5\xe1\x44\xaa\xfe\x74\x7b\xd0\x8e\xbc\x9f\x38\xcd\x6c\x73\x61\x6e\x5c\x79\x39\x01\xc4\x73\xea\x9d\xcf\xb0\xf3\x8f\x5d\x79\xb6\xf8\x8e\xf2\xc0\x9e\x47\xcb\x78\x2c\xd3\x03\xd1\x01\xbf\x97\x99\xa9\xaf\xec\x2e\x96\x11\xd9\x19\x55\x59\xff\x46\x4f\x74\x44\xaa\xfe\x28\x1b\x8f\x25\xf1\xae\x96\x51\xd9\x83\x0a\x4f\xa8\x24\xbf\x2d\x2f\xd7\xef\xad\xac\xaa\x25\xef\x33\x40\x80\xde\xb8\x39\xf7\xc5\xcd\xdb\xa8\xf2\x7b\x61\x87\xe2\x72\xa2\x44\x5f\x78\xd6\xcc\xb6\xc0\xef\x27\xe7\xed\x33\xe4\xe2\x80\xfd\x13\x00\xe8\x83\xa3\xef\x5f\xc1\xd1\x74\xc1\xbc\x1a\xcb\xed\xec\xee\xaf\xc2\x93\x38\x67\x84\x86\xa0\xe5\x98\x7c\x81\xfd\xe8\xbd\xb1\xb4\x90\x24\x73\x2c\x05\xe6\x82\x63\x44\xd3\x5c\x6c\x59\x59\x75\xa5\x52\x80\x98\xcd\x79\xec\x17\x43\x4b\x61\xed\x2f\xb2\xce\x60\x78\xc8\x7c\x47\x8f\x7e\x03\xec\x18\x45\xfd\x7c\x13\x0c\x94\x1f\xae\x26\xc1\x3d\xbf\xd1\x26\x16\x47\x79\x1f\x1c\x55\xc1\xee\x84\x31\x17\x39\x80\xa0\x9f\x17\x66\xb8\x76\x77\xda\x2e\x9f\xed\x3f\x2d\x3e\xd6\x73\x78\xd0\xa0\xf9\xb6\xcb\x53\x95\x53\xde\x78\xdd\x2b\x28\xd8\xde\x84\xf6\xa6\xd5\x5b\xbc\x95\xde\x11\x91\x2b\xb7\xe1\x3f\xcc\x39\xdd\xc4\xe2\x3e\x8c\xc9\x00\xe9\x1f\xf7\x7e\xb6\x26\x07\xa6\x41\xd2\x00\x90\x90\xaf\x20\x47\xb6\x25\x6c\x94\x15\x4d\x12\x5a\x77\x89\xc9\x17\xbc\x91\x98\xe7\xca\x5e\x14\x61\x13\x50\x55\xcc\x50\xbb\x3e\xa6\x8e\xb9\x1c\xa8\x16\xf3\xa7\xe6\xcc\x4d\xe3\x67\xdb\xd5\x97\x96\x7d\x30\xc7\xc2\xca\x31\xd2\x87\x37\x72\x7c\x44\xf4\x6b\x45\xef\x6d\xfe\xf7\x17\xe6\xc6\x0d\x73\x0e\x90\x98\x72\xe5\x74\xb2\x32\x12\x31\x10\xa5\x2c\x41\x62\x4f\x44\x1f\xc8\xfa\xa3\xd9\x47\x16\x10\x5a\xb3\x94\x7a\xc3\x02\xd2\x7e\xe8\x46\x3d\x60\x61\xd6\x07\x54\x56\xd5\xbe\xcc\xb4\x04\x9c\x60\x74\x03\x4f\x03\xac\x70\x2f\x3c\x23\xf5\x2c\x4c\x12\x4c\xa7\x29\xfa\x86\x7c\x93\xdd\x55\xad\xef\x7a\x5f\xbf\x83\x7b\xc5\x64\xe6\x00\x02\x78\x00\x40\x3a\xf3\x52\x81\x64\xa0\xcc\x4d\xb9\xc5\xba\xbd\x32\x37\x75\x6d\x86\xe5\x7b\xe5\x6e\x8e\x21\xcf\x91\xc3\x4d\x1b\x11\x78\x06\x46\x04\xf7\x0c\x70\xc5\x5e\x5c\xa3\x05\xce\x5c\x5a\xc1\x1a\xdc\xd4\x87\xb1\xc2\xd5\x32\x49\x7e\x33\x9c\xde\xf1\xf4\x66\xcc\xc5\x53\xe8\x25\xfa\x02\xba\x40\xbb\x1d\x5b\xd0\x79\xf8\x9f\xe5\xcf\x0e\xa2\x26\xb4\x1d\xd6\x12\xa9\xc4\x97\x3f\xc0\x84\x13\x09\x55\x53\xb1\x81\xfd\x15\xba\x27\x87\x4d\x35\x7a\x95\xb7\x0f\xdc\x42\x1d\x67\x67\xca\xe2\xfe\xe8\x9c\x4c\x1c\xdf\x1c\x66\x9e\x71\xf4\x5f\x72\x44\x69\xcd\x97\xfd\xdb\xdd\xaf\xf3\x6c\x9c\xb6\x0d\x90\x1d\x4a\x11\xa9\x86\x04\xd1\x97\x35\xfd\xa7\x85\xc2\x9f\x31\x18\x0c\xbf\x38\xde\x3c\x0d\x13\xab\x54\x99\x65\xe6\x9b\x7b\xe8\x70\x33\xeb\x53\x7a\x11\x1c\x64\xe2\x98\xbe\x82\xc8\xec\x8a\x23\xfe\x3f\xda\xae\x05\x2c\xca\x2a\xfd\x9f\xf3\xdd\x86\x9b\xc0\xc0\x8c\xa3\xa2\xe2\x30\xc2\x88\x04\x04\xc3\x30\x22\x82\x88\xa8\x88\x2e\xa2\x19\xa9\x29\x9a\x79\x41\xf2\x12\x92\x99\x99\xb1\x46\x64\xe6\x2d\x44\x0d\xd3\xbc\x90\x1a\xb9\x66\x66\x46\xe6\x5a\x79\xc9\xcc\xcc\xec\xa2\x99\x6b\x6e\x99\xdb\xb6\xb5\x6c\xb9\x6e\xeb\x1a\x30\x87\xff\xf3\x9d\xef\xfe\xcd\xf7\xcd\x85\xfa\x3f\xfb\xb0\xa6\xcc\x9c\xf3\x7b\x7f\xe7\x3d\xef\x7b\x2e\xef\xfb\x9e\xbd\xee\x52\xd9\xa8\x11\xb8\xde\xf8\x68\x83\x0b\xbf\x95\xab\xaa\xd0\x2c\xc6\x51\xaa\xb6\x8e\x5c\xa5\xe6\x83\x8b\xab\x5f\xda\xf2\xa3\x6c\x0f\x2d\x14\x6c\x16\x83\xd6\x15\xfd\xb0\x6b\xe0\x78\x6c\xb7\x54\xb8\x69\x2d\xdc\x61\xd2\x8a\x57\xc2\x7d\x4b\x5a\x63\x12\x78\xff\x3b\x9a\x31\x79\xc5\x6d\xd1\xc5\xbd\x4f\xb6\xcf\xf5\xc0\x7d\x4b\xb1\x96\xc5\x7c\x27\x62\xdc\x36\x25\x72\xbd\xd7\x04\x05\x29\x26\x68\xbd\xea\x2b\x1f\x06\xcf\xb7\x31\x49\x7e\x3c\x92\xf8\xb7\x8b\xfd\x19\x91\x78\x5d\x29\x1d\x9e\x00\x34\xc7\xe9\xb4\x07\x10\x02\x4c\x42\x26\x3c\x5e\x5c\xcd\x13\xcf\x6d\xa2\x8c\x87\x49\x0a\x1b\x34\x8f\x97\x1e\xad\x93\x9b\x1a\x78\x4d\x2e\x3a\x20\x40\x2e\x32\xe1\xf1\x33\xe2\x78\x01\xcd\xf6\x35\xe4\xce\x55\x74\xf5\xa0\x42\x5a\x75\x87\x5a\xa2\x0a\x3e\xf4\x29\x5e\x17\xbb\x2b\x47\xd4\xa2\x30\xcf\xc2\x38\x0e\x54\x58\x5e\xb9\x1c\xb3\x79\xdb\x8a\xf5\xf1\x29\x5e\x1f\xfb\xea\x8e\x9a\x41\xd1\xbc\x72\xac\xfa\x29\x3a\xd1\xc2\x2e\x76\x86\x73\xe7\xfe\x86\x9e\x26\x2e\xe0\x77\x0b\x6d\x7c\x66\x98\x87\x03\x96\xc7\x12\xf4\xd4\xf1\xb8\xcc\xbe\x7d\x44\xe4\xbe\x7d\x6a\xcf\x0f\x1f\xa9\xb0\x53\xeb\x13\x2b\x2a\x12\xdb\xe6\xdb\x2b\x00\x20\x3b\x9e\x45\x4f\x13\x7f\xa4\xbf\xc3\xfd\xd9\x75\x7b\x54\xc5\x9b\x3d\xa8\xd3\x6b\x93\x14\x7a\xa6\xee\x99\xf9\xa7\x2c\x04\x0d\xd7\xa0\xa6\xd8\x35\x17\xb1\x38\xa8\x08\xcf\xc1\x58\xd6\xcb\x2b\xfa\x91\x49\x09\xf9\x53\x67\xf9\xc4\x4f\x1c\x98\x60\x1f\x30\xc0\x9e\x92\x9e\xc8\x8b\xba\x64\xe3\x9d\x97\xb2\x7e\x1c\x3f\x30\x21\x71\x80\x23\x25\x25\x9d\xa9\xe5\x34\x3f\xf3\xd7\x97\xe5\x32\x1b\xac\xdd\x5e\x99\x61\x9e\xf8\xe7\xad\xec\x6f\xef\xcc\xc8\x04\x80\xea\xb8\x05\x00\x51\xc0\xdc\xc6\x77\x22\x1c\xef\xf2\x13\x5a\xbe\x6f\xd2\xe8\x50\x4c\xcf\x10\xa1\xff\x83\xb8\xdf\xaa\x43\xd1\x42\xcf\xb4\x83\xef\xf9\x43\xae\xab\xd6\x34\x56\x62\xee\x5f\x71\x8f\xbc\xbd\xa7\x7e\x31\x54\x81\x30\xa1\x1a\xbf\x58\x50\x5b\x5a\x48\x9f\x3e\xfc\x38\x11\x7c\xc9\xfd\x36\x31\xe9\xb2\xfb\xd7\x8d\x4d\xfc\xa1\x0c\xdd\xec\x4e\x5d\x45\x0c\x77\xd7\xb4\x9f\x26\x8e\xd4\xb8\xcf\x30\x49\xd2\x19\x0c\x67\xf7\x1d\x86\xad\xc2\x8e\x40\xca\x32\x50\x36\x2d\xcf\x31\xb8\x72\x19\xd5\x2c\xdb\xc6\xb7\x2e\x4b\x32\x70\xaf\xc2\xb9\x05\xcc\x78\x79\xfb\xa7\x51\x03\xf5\x0b\xdd\xcc\xd5\x59\x57\xe0\xb6\x28\x4c\xa5\x1c\xf9\x09\x99\xd5\x57\x40\x17\x2d\x32\x67\xf7\x1d\x38\x77\x21\xc6\x13\xb7\xc2\xe0\xab\x91\x2f\x96\x6c\xbe\x1a\xba\xac\xfd\xd3\xe8\x02\x8f\x3b\x52\x8d\xdb\x6a\xb6\x2a\xf1\xf6\x22\xa6\xb9\x77\xa8\xb1\x6e\xa9\xe3\xfd\xd3\x05\x1e\x67\xb4\x27\x4e\x83\xd5\x6c\xf5\xc0\x97\xc6\xb6\xe6\x89\x8d\x6f\xef\x34\x6a\x20\x11\x8e\x6f\x31\xf2\x36\xcb\xac\xf2\x9c\xd5\xee\x7f\x49\xfc\xb5\xfe\xb4\x4b\xe6\xc6\x00\x01\xb6\xa1\x06\x58\xc5\x98\xb8\xba\x0e\x16\xd5\x3c\xdd\x26\x7c\x31\xf2\x90\xf0\x2d\x78\x07\x63\xfa\xb5\x85\x8b\x17\xfa\x2f\xdb\x37\x73\x14\x90\xdc\x2a\x91\x64\x37\x73\x1e\x08\x42\x89\x69\x68\xa1\x02\x05\x93\x54\x57\xf7\xeb\x45\x0f\x2c\x64\xc7\x5f\x50\x03\x31\xd0\x10\x0e\x48\x8e\x1d\xdc\x9e\x0a\x51\x02\x31\x0d\xcd\x90\x50\x31\xcb\xea\xea\x6e\xaf\x51\x42\xc3\x63\xc5\x73\x12\x2c\x72\x82\x07\x89\xa8\x76\xa7\x71\x63\xd3\xfa\xd3\x2e\x96\x40\xa2\xe3\x4b\x74\x81\x18\xc0\x98\x00\x09\x0c\x00\xe0\x83\x28\xa3\xc3\xd8\x8f\xfd\xd0\x17\x87\xb6\xd4\x09\xd2\x72\x7b\x48\xae\xcd\x68\xa1\x4d\xd5\xee\x91\x6d\x9d\x56\x6e\x1b\x5b\x7f\xda\xa5\xd8\x32\x02\xa2\xe3\x55\x34\x9b\xb8\x9f\x31\x81\x2e\xec\x78\x91\x8a\x16\x58\xee\xc6\xca\x1b\x00\x1d\x87\xe4\x5f\x87\x9b\x05\xf9\x00\x60\x96\x1a\x16\x81\x68\xfc\x06\x92\xd1\x0a\x1d\xd0\xca\xbd\xc8\x03\x6d\xd0\xd6\xd5\x6c\x84\x92\x09\x80\x91\xf0\x64\x10\x3c\x0b\xc3\x9b\xc3\x83\x50\xb7\xe7\x50\xef\xa0\x08\x78\x40\xb4\x04\x6d\xe3\xa8\xfd\xad\x45\x64\xcd\xa6\xef\xdb\x00\x4d\xec\xf8\x67\xfb\x4a\x26\x59\x7e\x5e\x8c\xed\x01\x73\x91\xb1\x82\x38\x76\x75\xeb\x99\xdd\xe3\x91\xd1\x23\x75\xad\xce\xed\x39\x28\x24\xf5\xc0\x1b\x7c\xff\xf2\xd2\xc7\xea\xa4\x1e\xea\xb2\x12\x07\x27\xb3\x0b\xbf\xac\xad\x2d\xb3\xe2\xb0\x54\x43\xea\xd3\xd2\x9a\x57\x43\x6c\xd5\xda\x97\xb9\x48\x7f\x27\xae\xb4\x7c\xca\x2c\x37\x2f\xba\x52\xdf\x14\xfa\xf7\x26\xb6\x18\x69\xcd\xcf\x6d\x66\x29\x8e\xe7\xd3\x91\x99\xf6\x25\xf3\x7b\xd2\xcc\xf7\x94\x59\xbd\x6e\x66\x2e\xe2\x18\x6e\xff\x64\xa6\xfd\x92\xf9\x86\xd0\xbf\x37\x99\x15\x38\xd8\x75\x75\xb1\x34\xce\x0e\x4b\x30\x74\x24\x10\x5c\x44\x18\xce\x1f\x55\x8c\xf3\xc5\x64\xf8\x0d\xe8\x08\x22\xc2\xf6\x5d\x6a\xff\x77\x10\x1d\x06\x53\xa5\x41\x1e\xe1\xee\x81\xaa\xba\x41\x7b\x3e\x99\xd5\x5a\x44\xbd\x33\xb6\xf9\xa9\xf6\xf3\xf2\x8d\x29\xbf\xc7\xa1\xbf\x03\x26\x75\xd6\x98\xf6\x0e\x47\xc8\x1a\xc3\xd5\xcf\xcf\xca\x46\x13\xe7\x8d\x39\x85\x74\x31\xd9\x10\xf2\xfb\x9b\x62\x69\x0c\x3d\xe5\xa1\xbd\xcb\x23\x0d\xa0\x96\x3c\x4a\x5b\x8e\xf7\x3e\xf8\x4c\x46\x4f\x1e\x8b\xae\x3c\xfb\x64\x23\xa5\x94\x47\xd9\xc7\x69\x74\x81\x97\xc7\xa2\x2d\x0f\x76\x87\x6a\x39\xca\x39\xab\xab\x25\x82\xcc\x2f\x72\xd8\xbb\xe9\x60\xc7\xce\x51\x81\xb9\x07\xdb\xaa\x07\x5e\x6c\xd7\xf1\xd9\x35\x87\xd3\xaa\x8d\x53\x79\x30\xe7\x81\x78\xb0\xd2\x92\x6b\x21\x57\x9a\x76\x2c\xc3\x6c\x5e\x86\x38\x1d\x19\x94\x06\x5f\x29\xcd\x50\x79\x8f\x1e\x52\x29\x3b\xa3\xf0\x59\xc7\x49\x7c\x76\x6b\x01\xa9\x5c\x6d\x16\xc0\x1f\xcf\x2b\xdf\x82\xd3\x3e\x84\x8b\x76\xba\xb8\x65\xa9\xf8\x54\x1c\x7a\x01\x1d\x57\xbc\x12\xf7\x74\x48\xf9\xdd\xfd\x4b\x46\x0e\xed\x9d\x94\x10\x3e\x2b\x74\xe6\x3d\xf6\x3f\x8c\x1c\x1e\x9b\xd0\x3f\xe2\x81\xb4\xf9\xb6\xbf\xb8\x7e\x92\x3d\x22\xb7\x13\xcd\xf7\x7c\x3e\x8e\x48\x7a\xf0\xd1\xd8\xf8\xd8\xcc\xd4\x07\x1f\x8d\xed\x1b\x7b\xc7\x00\x18\xdb\x2d\xfb\xf1\x61\xa6\x31\xaf\x03\xf1\x7c\xb8\xdc\x10\x06\xc2\x40\x5f\x11\xbf\x90\x39\x92\xa0\x03\x5a\xaa\x4d\xd7\x47\xc4\x5f\x09\xc3\x6e\xfe\x03\x1a\xd1\x8d\x1b\x1b\xff\xfe\xd8\x4e\x1d\xc8\x63\x5e\xdc\xfe\xc2\xae\xdd\xdb\xd1\xf1\x23\x3c\x76\x3b\x0c\x83\x49\xe8\x3c\x6a\x45\xff\x41\x9f\xad\x82\x14\x39\x59\x09\xd6\x5d\x72\xfe\xd2\xa5\xf3\xe7\x3f\x25\x52\x25\xd0\x34\xcf\x79\x2c\xcf\x79\x36\x18\x11\x28\xeb\xa4\xce\xf6\x5c\x7f\x10\xaa\xc2\x16\x4c\xc6\x3b\xa5\xd4\xf4\x88\x29\x5d\xe6\x4f\x4a\xba\x8b\xdd\x29\xa5\x85\x47\x7b\x6e\xe1\xfd\x1e\x90\x85\x8f\xc4\xf6\x8d\xcd\x4c\x81\x75\xca\x47\x17\xd2\xb1\x8c\x78\x5c\x98\x73\xfc\xb8\x08\x32\x06\x32\x32\x3a\x32\x2a\x06\x6a\xb5\x8e\x58\x69\xc2\x40\xf5\xd6\x90\x4f\x77\xd0\x78\x81\xc4\x41\xdb\xe9\x21\x98\x72\xbe\xc4\xe0\xfa\xb8\x7a\x23\x27\xbb\xd5\xd1\x1f\x97\xd7\xc4\x3b\x1e\x9f\xb4\x8f\x96\xae\x7e\x14\x7a\x2f\xe1\x90\xd8\x75\xc9\x35\x5c\xc2\xa1\xe0\xee\x88\xc0\x51\xa4\x84\x41\x4d\xcd\x3e\x8e\x09\x98\xa6\xe8\x5b\xc9\x41\xbc\x77\x0e\xa4\xdb\x1f\xaf\x2c\x88\x77\x41\xfe\xf0\x20\xbf\x22\xf2\xe0\x22\xde\x3b\x17\xf1\xb2\xfb\x21\x1d\x36\x24\x2c\x5e\xf8\x50\x60\xc0\xe7\x78\xd4\x02\x43\x15\xae\x79\xdd\x53\x78\xa5\x80\x92\x3f\x93\x2a\xdb\x4f\xc3\x1a\x22\x1e\x7d\x8c\x7e\xe4\x9f\x49\x9d\x2c\xae\xa3\xd1\xb8\x6f\x7e\x16\x5e\x49\x85\x51\xf2\x98\x06\x9c\x37\xce\x58\x71\x3c\x4e\x92\x32\x73\x9c\xd0\xcc\x16\x97\xed\xb1\x55\xa5\x8b\xc4\x84\xf1\x46\xbe\x5f\x79\xe2\x38\x5f\xac\x48\x9e\x30\x4e\xac\x13\x81\x08\x72\xba\xb0\x9c\xbd\xb5\xe5\x54\x2c\x26\x95\x92\xd6\xc8\x22\x2b\xe4\xa2\xca\xc2\x2a\x04\x59\xf1\x7a\xca\xaa\xce\x92\xd7\x91\x55\xbe\x1c\xd1\x93\xf6\x5d\xa1\x6f\x1f\xe2\x92\x89\x8a\xd8\x0a\x00\xa8\x2b\x06\x17\xae\x43\x6e\x15\xa2\x8f\x22\x69\x68\x83\x56\x3d\x91\xeb\x61\x24\xa4\xd1\x15\x58\x77\x09\x6d\x43\x57\xaf\x1c\xdc\xb5\xe7\xc8\xa7\x1b\x24\xc1\xcf\x7f\x82\xae\xce\x74\x57\x12\x93\xdd\xbb\x88\xdb\xab\x9f\x79\xa6\x1a\xee\x57\xee\x19\xc8\x54\xfa\x3b\xee\x5c\xd4\xe1\x91\x93\xaf\x94\x54\x59\xfc\x49\x5a\x49\x8a\x69\xf9\xee\x66\x69\x15\x89\xe3\x44\xa8\x2b\xf8\xec\xe1\x37\xc9\xd2\x24\xad\x25\x3d\x64\xf9\xf5\x3f\xe2\x2a\x0f\x9f\x09\xe0\x1a\x03\xa1\xb8\xca\x80\x72\x07\xae\x92\x4b\x3a\x21\x50\x0a\x25\x1d\x17\x28\xa4\xe2\xe6\x3d\x96\x87\x39\x8a\xcf\x52\xba\x4b\xb1\x61\x9c\x44\x46\xbc\xed\xf7\x47\x2a\x07\x31\xcd\xfd\xb9\x37\xd1\x98\xa4\xba\xba\xf6\x73\x2a\xf1\x00\xc9\xc9\x47\x57\x60\xf9\xac\xbe\x24\x64\xe1\xe8\x49\xf9\x0a\x31\x4d\x47\x50\xea\x32\x7f\x3f\x74\x1a\x5d\xe0\xc7\x4e\x7c\x8d\x59\x94\x94\x8b\x7b\x11\x23\xdf\x94\xd2\x85\xb0\x8b\xdb\x10\x4e\x3c\x85\x54\x5b\xea\xa8\xbe\xac\x4c\xdc\x79\xef\x57\xe8\x02\x1e\x2b\x12\x98\xc5\xf3\x0b\x95\x04\x7d\xd9\x96\x3e\x53\x22\xdf\x52\xe7\x31\x32\x04\x28\xef\x68\xa1\x28\x83\x0b\x47\xa3\x4a\x2f\x0f\xa6\x40\x3b\xff\x78\xb9\x10\x26\xd6\x1b\xe2\x82\x10\x94\xd2\xd9\x97\x4f\xb9\x3a\x6d\xd7\x9e\x41\x6b\xd6\x9d\xdd\x0f\xe1\x67\x57\x0e\x67\x1d\x6d\x7c\xa2\x3e\xab\xfa\xe9\x17\x77\x8c\x46\x2d\xb7\x50\xfb\xf7\x82\x9e\xa7\x1d\xe8\x97\xf2\xf8\xfc\x91\x65\xe3\x32\x8a\xce\x6c\xff\xd3\x87\xe3\xb6\x15\x3f\x38\xb3\x70\x6a\x71\xfa\xa0\xca\xfa\x59\xef\x7e\xc5\x5c\x56\xdc\x1d\x96\x77\xb4\x90\x4b\xe8\xef\x80\x4d\xa7\x2a\x85\xaa\x12\x85\x7c\x77\xa8\xaa\x4a\x21\x55\x19\xdb\xf2\x78\x36\x14\x67\x9d\xba\x30\x85\x54\x63\x6c\xd0\xdd\x15\xc4\x93\xf2\xbd\x5c\x39\x6a\xa0\x28\xfa\x6c\x00\xfc\x58\x02\xe0\xe7\xa8\xa0\x64\xde\xf9\xf9\x56\x3a\x93\x2c\x47\x0d\xb8\x5e\xc7\xef\xcd\x0d\x21\x20\xf1\xca\x4d\x7b\x8c\x7c\x4e\x71\xba\x53\x85\xb9\xc9\xee\x84\xf6\x58\x44\xb7\xe7\x8b\xa7\xf1\x03\xfa\xa5\xa4\x0f\x4c\xe8\x37\xe0\x72\xd2\xc2\xf8\xcb\x89\xcd\xc3\x7c\xe9\x93\x33\x35\x33\xc5\x99\x9e\x3e\xb3\xbb\xeb\xd5\x91\xe6\x9c\x63\x99\x02\x5e\x72\x09\x63\xc5\xdc\x65\xf9\xc3\x9e\x0e\x58\x2f\x3c\x56\xaa\x81\xfa\x50\x35\x3d\x9c\x14\x15\x14\x0b\xe2\x41\x3a\xc8\xf5\x93\x57\x92\x5d\x36\x72\xdb\x23\x5b\x42\x20\x53\x34\x64\xe9\xc2\x39\x8f\xdf\x57\x7d\xce\x71\x78\xd0\xc0\x01\xfd\x52\xd3\x58\xf0\xde\xd9\x35\xcc\x8d\x29\xaa\x7a\x7c\x70\xcc\xb9\x69\xb3\x60\x62\x66\xea\x80\xe4\x0c\xfe\xbe\x92\xe3\xf7\x1c\xb0\x81\x3b\xc1\x20\xbf\xf8\xd5\x05\xed\x85\xe2\x01\x1a\x80\xbd\xb2\x4c\x5a\xf4\xf0\xb2\x73\x9b\xb7\x7d\x39\x9d\x98\xdd\x81\xd0\x2c\xce\xf4\x24\xff\x4c\xa2\x30\xe5\x0d\xff\x96\xd6\x04\x78\xee\xf3\x76\x31\x3b\xd0\xd9\xef\x2f\xbd\x92\x25\xb0\xf8\x65\x2e\x45\x93\xc0\x6c\x97\xdb\x4d\x13\x00\xd4\x64\x83\x0b\x18\xf8\x2a\xec\x38\xe2\x43\xbe\x17\x36\x51\x85\x68\xe0\x5b\xe1\xe2\x5a\xcb\xd4\xd8\xd8\xda\x42\x9b\xe0\x6b\x42\x2b\x04\xb0\x76\xb4\x10\xcd\xcc\x15\xee\x5e\x5f\x56\x79\x4f\xaa\xeb\xd8\x5d\xb1\x58\x10\xca\xec\x49\xf5\x1c\x23\xa4\x30\x12\xbe\xac\x9e\x58\xc8\x91\xa8\x26\xfe\x24\x5b\xcb\x99\x50\x03\x35\x99\x6e\xf6\x89\x57\x5c\x74\xf0\x78\x7f\x95\xdd\x17\x59\x51\x03\xae\x4b\xd9\x79\xbc\xbb\x44\x2b\xac\x81\xb7\x6d\xb4\x6c\xbd\x66\x42\x17\x78\xbc\xa1\x32\xbc\x56\xb3\x95\xc3\x79\x01\x1f\xbe\xf1\x18\x5b\xc7\x72\xe7\x6d\x56\x74\x81\xf8\x07\xc6\xd7\x43\x17\x1f\xdb\x84\x27\xae\x0c\xb6\x39\x4d\x4c\x2f\xf1\xb1\x28\x26\x34\x9b\xc7\x63\x96\xe1\x51\x1c\x7d\x71\xc8\xdc\x8a\x43\x36\x81\xc5\x0a\xc5\xb1\x1a\xc6\x3a\x9b\x0c\xc6\x58\xfb\xea\x63\x55\x34\xef\x89\x7a\xb6\xbc\x2b\x2d\xf4\xad\xc7\x14\xb1\x7d\x87\xd1\xf3\x74\x2c\x1f\xe7\x90\xa8\xce\xd9\x64\xf7\xcb\x50\xe7\x9c\xe3\xf0\x5b\xef\x1e\x7b\xe3\xe4\x9b\xe8\x33\xf4\x0b\xfa\x1f\xfa\x0a\x9a\x35\x4e\x32\x82\xc8\xfd\xed\xa3\x5f\x7f\xef\xc4\x9b\xe4\xc1\xf6\xe2\x56\xf4\x2d\xb4\xba\x7f\xf1\x88\xb5\x20\x41\x23\x7a\x9e\x2a\xc0\x35\x0d\xfb\xa8\xab\x55\x8b\x79\x41\x7a\xc7\x2d\x7c\x59\x92\x0d\x7c\x39\x92\x9d\x9e\x28\xe4\x15\x4a\xda\x9a\xeb\xc6\x94\xbe\x83\xee\x51\x83\x20\xc0\x61\xf4\x34\xcf\x83\x26\x0b\xda\xc7\x41\x2a\x0e\xde\xd6\xb9\xee\xd7\xe2\x61\xa9\x3a\xd4\x10\x10\xa0\x11\x3d\xcd\xf3\xa0\xcb\x82\x26\x0c\x15\x07\x45\x3a\x30\x3c\x89\x70\xff\x55\x85\x82\xe5\x61\x36\xcf\x43\xac\x0e\x0f\x32\xf5\x53\xc9\x7f\x59\xae\x7b\x5a\x42\x57\x2a\xee\x08\x41\x23\x9a\xcd\xcb\x1b\xa7\x2f\xaf\xac\x3b\x95\x9c\xe5\xf2\xee\x34\x84\xbb\xa0\x9c\x5f\x24\x38\xdc\xd1\x42\xc7\x06\x95\xe1\x31\x4e\xf7\x7f\x94\xc5\x33\x58\x95\xb8\x5f\xf9\x38\x38\xf6\x24\x80\xee\xe9\xe5\xac\x98\x04\x8d\x1d\x2d\x54\x01\x8e\x25\xbe\x03\x57\xd5\xf2\x5f\x03\x44\x88\x2a\x8a\xaa\xbd\x43\xf4\x24\x8d\x4a\xd6\x45\x48\xf1\xfc\xc5\x02\x23\xde\x9f\x27\x6b\x5a\x0b\xd5\x5d\xb6\x37\x8b\x41\x13\xd3\xdc\xfb\xfd\xb2\x1a\x74\x4e\x5d\x1d\x7c\xd0\xf3\x18\x17\x50\x1c\x67\xcc\x39\x7c\x9f\xd2\x17\x57\xdf\xd2\x64\xcd\x0b\x2c\x15\x65\x7b\xb4\x51\x69\x50\x55\xac\x0d\x8a\xc0\xc0\xce\x19\x1c\x20\x84\xd5\x6b\xa3\x03\xb2\xeb\x3d\xe8\x80\x36\xed\x10\xe5\xe3\x70\xe4\xe0\x5e\xdd\x0b\xe0\x88\x93\xee\x5b\x6f\xa1\xef\x75\x83\x94\xdb\x4b\x0f\xae\x79\xfc\x14\xb9\xa7\xb5\x88\x49\x52\x1b\x0f\xae\xcf\x48\xfa\x1a\xe8\x02\xe2\xd9\x3e\xa5\xf2\x7c\x7a\xbd\xca\x0a\xf5\x4d\x3d\x8f\x6e\xea\x74\x2b\x2f\xdc\xd7\xd6\x4c\x5d\xf6\xb0\x17\x00\x35\x50\xe7\x70\x7e\x7d\x57\x85\xac\x06\x19\xc3\x0a\x09\xa5\xd5\x84\x4c\x22\xe5\xdd\x1b\xdb\x66\x24\x7e\x53\xba\xbb\x4a\x16\x45\xab\x0a\x09\x08\xe9\x5e\x4f\x8e\x58\x71\xe7\xda\x1d\x00\x43\xa9\xa1\x0a\x74\xc3\xf6\x86\x7b\x85\x02\x72\x90\x31\x51\xac\x91\x81\x36\x29\x8d\xbc\xfb\xb1\xeb\x29\xdd\xba\x0e\x80\xc4\x3b\xb0\x4b\x46\xcf\x48\xd7\xb7\xc7\xd0\xd2\x23\xe8\xfa\xe0\xd0\xc8\x4c\xd4\x72\xe4\xd7\x4b\x7d\x1e\x4e\x5d\x32\xea\x75\xba\xb9\xbd\xe6\xd5\x57\x76\x9d\x24\x17\xb6\xaf\x78\xe5\xf5\x67\x2e\x90\x4b\x5b\x8b\xc8\x77\xbe\x18\x55\x75\xa8\xbd\xd0\x50\x66\xce\x7f\x33\xb3\xfb\xa0\x77\x71\xff\x16\x00\x18\x07\x63\xe5\xf3\x04\x1c\x3d\xa0\xc5\xe1\xc2\x6f\xf1\xf5\x26\x2d\x0e\xf1\x45\x62\x1b\x63\x20\x65\x20\x2c\x47\xca\xe7\x85\x04\x85\xc7\xf6\x3a\xf9\xde\xdb\x21\x16\x53\x24\x15\x1c\x9c\xf7\xfc\x61\x74\xfe\xf3\xa3\x3d\xd2\x83\xfa\xf7\x39\xf5\xd1\x21\x1e\x07\x55\x84\x1e\x40\x93\xee\xc9\x5d\x37\x89\x78\xc0\xbd\xd1\x36\xe6\x0f\x23\x7b\x8d\x6e\x25\x8a\xda\x9a\x89\x8a\x3f\x7c\x71\x72\xba\xbb\x81\x09\x13\xc1\xf8\xcb\x85\x14\xe5\xe0\x9d\x0b\xf8\x9c\x78\x44\xac\x4f\x86\x2c\x00\x2b\x20\x2e\x24\x10\x3e\xb9\x80\xd3\xc4\x90\x0b\x1f\x64\x28\xe3\x2e\x48\x9e\x8f\x44\xd1\x8a\xe8\x6a\x87\x8e\x15\xf1\xa1\x2b\x5a\xa1\xb0\x5e\x98\xd2\x08\x8d\x05\x24\xc7\x19\x7d\x09\xc7\x00\xba\x7c\x6a\x90\x0e\x50\x9f\x1c\x1e\xf3\xc4\xea\x93\x4d\xba\xca\x13\xb0\xa0\x63\x2e\xae\xca\x92\xbe\x8e\xf9\xcd\x22\x3c\x28\x9d\x52\x7b\x23\x4f\xbe\x27\xe3\x38\xfb\x8e\x8f\x9b\xf4\xae\x67\x81\xb0\x04\x17\x4b\xc7\xd9\x3e\xc9\x91\xed\xb9\xba\xa3\x06\x43\x29\xdd\xec\x83\x13\x3a\x00\x4e\x64\xf6\x54\x97\x13\xa5\x7d\xb5\xa0\x06\xc6\x41\x15\xf9\xc3\x09\x1d\x10\x27\x0f\x4b\x46\xd8\x07\x27\x0a\xbb\x1c\x04\x00\xd5\x24\xc6\xf4\x0b\x55\x60\x6d\xc1\x84\xac\xf3\x20\xf8\x77\x94\x75\x0e\xce\x82\x73\x4e\xa0\x41\xf0\xfb\x4f\xd1\x32\xb4\x18\xda\xc4\x5c\xd4\x56\xe2\xa8\xfb\x24\x91\xe3\x2e\x74\x13\xc4\x52\x77\xad\x52\x07\xe2\x01\xa0\x2c\xb8\x26\xa4\xb2\x7d\xc5\xc6\x54\x59\x65\xf6\xd9\x73\xe8\x22\xfa\xf4\x3d\xb1\x7d\xb1\xce\xac\xfb\x3c\x6c\x46\x45\xf2\xd8\x17\x92\xc7\x2f\xc5\xc8\xeb\xf5\xe0\x43\x9c\xb9\x1a\x6b\x21\x0f\xb9\xb4\x62\xe6\x39\xf9\x2e\x05\xd2\xbf\x96\xb4\x11\x1a\xfd\x7b\xc8\xad\x35\xcf\xd9\xb5\xc7\x0a\x9c\xcf\x6c\x62\xfd\x75\x30\x74\x40\xd5\x41\xc2\x19\xb8\x14\x2e\x7b\x1f\x75\x97\x9d\x7d\x34\xbb\xd3\x88\xf3\xed\xcb\xdd\x67\x88\x54\x6a\x93\x74\xfe\x41\x20\x13\x65\xe2\xe3\xac\xb9\xf9\xe1\xc8\x85\xdc\x5b\x51\xc2\x39\xcf\x60\x28\x6f\x9a\x38\xfe\xaf\x51\xc6\xa0\xe0\xbc\xae\x5f\x9f\x40\xf6\x61\xef\xac\x1e\x55\x94\x3e\xbc\xf4\x91\x84\xac\x9e\xd2\xfc\x74\xaf\xfb\x68\x6a\xfc\xd9\x1c\x62\x41\x5b\xef\xe6\x6d\xc6\x75\x61\x53\xef\x5f\x4f\x2f\x96\xcd\xc9\x62\x00\xa8\x02\x7c\x37\x6a\x91\xbf\xe2\xcf\xf9\x1d\x61\xf7\x51\x4c\x12\xee\xae\xe4\x99\x76\x44\x5a\xda\x5f\x91\xed\x3c\x56\x51\x2b\x76\xad\x6a\x5b\xb2\x8b\x49\xb2\xa8\xf7\xf3\x25\x00\x90\x55\x8c\xd5\x7b\xbb\xb2\x2a\xc4\xee\xfe\xb2\x76\xf9\x62\xc4\xab\xa8\xcb\x1e\xed\x16\xa3\x06\xaa\x00\xd7\x27\x32\xcb\xdb\x95\xcf\x55\x19\x5a\xf7\x16\x61\x56\x0a\x50\x6f\xc9\xce\x54\x4a\x50\x03\xae\x91\xec\xa5\x2d\x19\x42\x44\x09\x6d\x09\xf0\xe4\x6d\x15\xa3\x0b\x3c\xae\x2e\x8a\xb6\xac\x66\xab\x9c\xbd\x2f\x88\x69\xee\x1d\x02\x96\x2d\xfc\x59\x4a\x09\xba\xc0\xe3\xf0\xf8\xae\x9c\xa1\x5c\xf6\xbb\x42\xdf\xc2\x77\x71\x4c\x15\xce\x3d\xe8\xa1\x9f\x7b\x60\x35\x5b\x95\x19\x07\x3d\xb8\x78\x63\xcf\x44\x83\x2d\x75\x80\xe4\xcf\xe1\xce\x09\x79\x28\x7a\xa7\x31\x3a\xd3\xcb\xf3\x5c\x66\xbd\xe7\xe4\xd2\x3e\x9f\xd3\x38\x1f\xe1\xd6\x4a\x2b\xfd\xf3\xfb\x50\xa7\x6a\x8a\x6f\xeb\x0d\x1e\x99\x3d\xf3\xf1\x65\xb3\x66\x3f\x32\x37\x7b\x80\x63\xf0\x90\xb4\xf4\x21\xbe\x5d\xdb\xc1\xe9\x8b\x1e\x9e\x3a\xf3\x61\xae\x74\x4a\x66\x4e\x0e\xb6\x47\x78\x0e\x33\x2b\xf1\x1c\x4e\xf5\x6f\x16\x2b\xea\xce\xe8\xcc\xe8\x55\x1a\xf8\xb4\xa6\x76\xb3\x16\xa6\xb2\x8e\x16\xf2\x12\x53\x84\x6b\xd0\x68\x57\xf2\xd6\xaa\x40\xe3\xe4\x30\x39\x31\x4c\x1f\x75\x67\xbe\x49\x1f\x92\x3d\xa0\xfc\x91\x47\x7d\x54\x9b\x21\x7e\x9d\x95\x9d\x99\x39\x70\xce\xa2\x19\x33\x17\x72\xf7\xe9\xc4\x77\x86\x69\x42\x9e\x80\x58\xbf\x54\x75\x95\x0e\x1f\x98\x51\x9e\x3a\x69\x58\xd9\x3d\x46\xd1\xac\x6d\x83\xcb\xed\x6b\x63\x17\x3d\xdc\x36\x9d\xf9\x49\x30\x66\x10\xef\xd1\x67\xd0\x67\xb9\xc8\xbc\x0c\x60\xed\x13\x0d\xb9\x3a\x24\x7c\x91\xc7\x4c\x67\xa4\xd5\xe6\x84\x7c\xb9\xbb\xc3\x30\x01\x92\xf0\xf1\xb9\xe8\xea\xb9\x9f\xd1\xed\x5b\x3f\xd6\xdf\xfd\xde\xe4\x97\xb6\xa3\x1d\xd5\x70\x70\xc2\xb3\x8b\x5f\x7d\x8b\x3c\xd8\x06\x7b\xa3\x43\xe8\x2c\xf3\xdd\x5b\x97\xae\x8f\x69\x4a\x49\xaf\x5f\x0f\xc3\x6a\x61\xc9\x98\xbb\x4e\x1d\x6a\x2f\x06\x24\xbb\x57\x93\xd5\x16\xf2\x52\x59\xc8\xa3\x9a\x50\xa2\xb8\x70\x51\x15\x11\xfa\x5e\x7e\xdf\x56\x86\x1a\x64\xb5\x83\x3a\x51\x39\xc8\xc7\xa8\x3d\x22\xa0\xf0\x55\x24\x68\x8e\x80\x8a\x64\x8d\x0e\x1d\x63\xb8\x8e\x65\xee\xed\x21\xb3\x33\xd3\xd1\xc7\x6c\x8a\x80\x36\x7b\x2e\x74\x66\xd8\xe2\x3c\x04\x2f\x8a\x1f\x0d\x89\x3d\x21\x0b\xc2\x8b\x26\x3c\xe5\x54\x09\x4f\x16\x55\x84\x1d\x59\x9d\x30\x6f\x7f\x97\x94\x3b\xc7\x49\x7a\x5b\x87\xe5\xcf\xf4\x5f\x6f\x55\x18\x7c\x90\x50\x2f\x47\xe4\x83\x08\xea\x51\x05\x42\x00\x28\x9e\x8f\x4f\xf1\x39\x38\x8e\xf5\x12\x19\x51\x78\x3a\x12\xf3\x23\xe4\x28\x49\xb4\x6c\x76\x2c\xbe\xf3\xe8\x88\xf5\x33\x1e\xbc\x7f\xe1\x7d\x51\x1c\x45\x30\x61\x64\xe6\xa1\xb1\x4b\x05\x72\x98\xa4\xee\x03\x57\x0c\x9b\xbd\xbd\xfb\xa8\x7b\x67\x0e\x69\xcf\xc1\x4c\x11\x67\xbb\xdd\xfb\xa0\x79\xee\x74\x40\xb1\x1c\x51\xe3\x99\x6a\xd0\x03\x57\xe9\xcf\xf6\xca\x92\x0a\x92\xc4\x99\x80\x4b\x87\xaa\x5d\x32\x90\xc5\x3c\x6d\x44\x10\x46\xa9\x4d\x18\x35\x54\x8e\xb9\x54\xa0\x8f\x6c\xe3\x61\x2b\x78\x8b\x00\xbd\x64\xbc\x85\x0a\xf1\x70\xdc\xb1\x9e\x92\x3f\x89\xb7\xa2\x83\x59\xc3\xa7\x2f\x59\xed\xac\x74\xbc\x93\xbb\x65\xd6\x7d\x0b\x2b\xe6\x44\x72\xec\x09\xb4\x19\x8e\x9a\x17\x4d\xe8\x7a\x2f\xfa\xd6\x92\x53\x5d\x34\xf1\x15\xcb\x90\x99\xd3\x86\xf3\xec\xe1\x71\x8b\xc7\xba\x55\x0d\x0c\x20\x0e\xdc\x89\x79\xe3\xfb\x25\xbd\xf1\xa7\x80\x24\xf1\x17\x8f\xd1\xf4\xd2\x66\xef\x65\x19\xc8\x71\x3c\x7b\x4c\x05\x46\xd7\x36\x50\x9b\x3d\x39\xe6\x52\xf9\xdb\x07\x3c\x6f\x41\x45\xbc\xbe\xdd\xe1\x53\xdf\x1c\xe9\xda\xf3\x71\x9d\x6c\x4c\x83\x78\xc5\xa3\xba\x0d\x78\xaf\x9a\x19\x1f\x92\x9d\x7b\x7f\xaa\x37\xf5\x23\xcf\x8d\x67\xd6\xce\xea\x35\x66\x79\x70\x6c\x7c\x2e\xaf\x83\xf1\xcc\x6d\x5e\x07\x0b\x3a\xad\x83\x4a\xac\x3a\xca\xb8\x4f\x06\xbc\x54\x78\x3f\xe2\xb6\x0c\x79\x40\x2a\x49\xb9\xe5\xa2\x88\xfc\x4e\x07\x06\x10\x0b\x52\x40\x86\x8c\x5f\xed\xa0\x58\xac\x12\xf8\xb8\x4a\x4b\x4d\x37\x76\x99\x31\x3a\x7e\xe4\xb0\xdc\x98\x7e\xfd\xc3\x26\x87\xce\x1c\xdd\x77\xc4\xd0\xbc\x9e\xfd\xfa\x87\x8f\xcf\x5c\x90\x79\xf8\xce\xc5\x19\xd3\x67\x2d\x98\xbc\xc4\xa4\xd2\xdc\x9a\x8a\xaa\x5e\x7d\x7b\xa5\xa6\xe1\x3f\x52\xd2\x51\x93\x65\xd0\x92\x31\xc3\x6a\x07\x5a\xf2\xa7\xdf\x35\x56\xae\xc3\xd8\x3e\x1a\x22\x41\x0f\x90\x0e\x86\x80\xd1\xde\x79\xf7\x0b\xbe\xee\xd3\x1d\x02\xfb\xdb\xfc\x11\xa8\x58\xef\x59\x0f\x3c\x12\xf4\x16\xaf\xf2\xa9\xf5\x9d\xf5\xb1\x86\x2a\x5e\xdf\xed\xde\xf5\x5d\xdb\xe7\x2e\x91\xed\x2c\x82\x74\xfc\xaf\x62\x07\xc3\x73\x2c\x73\xc6\x14\xe7\x8b\x19\x2b\xaf\xe3\x83\x3b\xa7\xe3\x7e\xf8\xe6\xc7\x65\x60\x73\x79\x1e\x37\x7b\xf7\xd3\xd4\x50\x39\xf6\x52\x4f\xaf\x2d\xe9\x75\xb4\x86\x9f\x52\x95\xa5\x60\x79\x34\x7a\xf8\xa9\x97\xe7\x1a\xc6\xce\x99\x32\x25\x68\x5e\x97\xed\xb5\xeb\xd7\x0f\xe2\x58\x1c\x9f\x74\x70\xe2\x43\xa2\xda\xba\x46\xe4\x0e\xcd\xaf\x59\xb9\xb6\xed\x55\xce\x48\x84\x59\x16\x94\x99\x17\x4d\x12\xf4\x94\x39\xee\x9f\x8f\x52\xc2\x51\xf8\x75\x6f\x3e\xea\x35\x05\x40\x92\x67\xee\x6b\x0c\x51\x47\x0f\xc7\x08\x80\x3f\x10\xad\xc1\x20\x11\xb3\xc4\x97\x09\xf4\x64\x57\x94\x5a\x7c\xf5\x11\x9d\x86\x6a\xde\xbf\xc4\xa2\x99\x36\x29\x68\x5e\x97\x17\x56\xa0\x7f\xc4\x1d\x4c\x19\x33\x7d\xf1\x70\xd5\x34\x77\x8d\xc8\x1d\x52\xf0\xe4\xd3\xf0\x73\xf3\xcc\x72\x4b\x59\xeb\x15\xd5\xbc\xc6\x7c\xd9\x41\x3a\x18\xe8\x37\x5f\x7d\xe4\xaa\xc6\x23\xd3\xa1\xeb\x55\x05\x40\x03\x4f\x57\x22\x06\xaa\x4f\x17\x8b\x57\x52\x30\x3a\x14\x23\x97\xfb\xa5\x09\x98\xaf\x1e\x20\x49\x8f\x2f\x71\x99\xa8\xe3\x96\x94\xc4\xa5\x73\x94\x0d\xee\x9a\x7b\x6c\x19\x33\x3e\x24\x2b\xf7\xbe\x78\x35\x7d\x82\x4b\xba\x5a\x12\xb4\xe6\xfe\xde\x89\x93\x83\xfb\xd8\x72\x24\xdb\xc8\xf0\x1c\x0e\xed\x24\x87\xfe\xb9\xa4\x37\x15\xa0\x23\x78\x32\x9b\x64\xa8\xfd\xa6\xb4\x8b\x42\x0c\x91\xd7\x32\xec\x8f\xee\x00\xe9\x3e\xfc\x51\x04\xf4\x64\xdb\xb7\x37\x1a\x37\xd7\x30\xe6\x81\xe9\x13\x82\xe6\x75\xd9\xfa\x34\xfa\x47\x96\xda\x1d\x95\x57\x62\x73\x3d\x7b\x21\x36\xd7\x25\xc3\x06\xe5\x0d\x79\xe2\x29\x4f\x3f\x14\x86\xfd\xd0\x60\x50\x14\xb8\x1f\x52\xc2\xf6\xed\x85\x76\xf9\x25\x88\xc1\x87\x1b\xd2\x96\x4b\xd3\xff\x14\x6b\xf8\x1f\x0d\xbb\xa9\xed\x7f\x36\x29\xca\x3b\xfc\x41\xc7\x03\x19\x8a\xf9\x1a\x0f\x6d\x2f\x7a\x6c\x05\x05\xff\x43\xb7\xf8\xe7\x7f\x74\x6d\xa8\x6f\xff\xf3\x82\x02\xac\x99\xa7\xf0\x39\xef\x1e\x88\x2e\x15\xb0\x7f\xe4\xe9\x7d\xb8\xfc\xf5\xdb\x52\xfd\x17\xa9\x4a\x13\xed\x51\x69\x88\xab\xc8\xd4\x2e\x9d\xeb\xf3\xe5\x97\x6e\xa9\x6b\x1d\x72\x75\xa9\x62\xf4\x2b\xab\xf1\xf5\x95\x14\xd9\x49\x9e\x95\x95\x84\x57\xae\xa4\x4a\x87\x9e\x65\x94\xf0\x33\x57\x6d\xdf\xc9\xe4\xc1\x75\x93\xae\x73\xef\x2c\x29\x2b\xaa\xa9\xf6\x9e\x72\xa1\xae\x28\xb6\xbe\x62\x5d\xa9\x79\xf2\x2d\x25\x57\xb7\x32\x86\xa9\xc3\xb2\xdd\xe1\x43\x36\x75\x6f\xde\x04\x7c\x56\xde\xbb\x9e\x90\xc4\x2d\xd5\xfe\x56\x90\xd5\xd1\x99\x9a\x63\x37\x7c\xd5\x1c\xf3\xbc\xcb\xe7\xe5\xa7\xaf\xfd\xbe\x35\xc7\x66\xeb\x20\x31\xea\xd7\x1c\x23\x4f\x28\xb1\xb9\x0f\xf3\x35\xc7\x00\xa0\x1e\x35\x7c\x8a\xeb\xc7\x58\xd5\xa3\x2f\x5f\xf6\xc5\xf3\xeb\x15\xb9\x0a\xdc\x29\xdb\xbb\xc0\x23\xdc\x36\x5f\x22\x43\xb6\x41\x39\x29\xee\xef\x59\x3e\xe6\x32\xd5\x7c\x6d\xb1\x34\xdd\x1a\x7b\xca\xc5\x30\x57\x6b\xde\x29\xa4\x4f\x7a\x32\xf2\xb2\x0c\x49\x09\xcf\x02\x6c\xc7\x88\x34\xc9\x90\x61\xc3\x4c\x10\x8b\x85\xad\x3c\x20\x41\x31\xd6\x91\x4f\x71\x2c\xa5\x55\xda\x49\x47\x2b\xb8\x91\x6f\x9d\x8b\xf1\x7e\xd9\x26\x63\x66\x80\x6c\x93\xcc\x6f\xdd\x6f\xbf\x29\xe3\x46\xb6\x23\xe6\xec\xe1\x60\x3c\x4f\xd8\xfd\x7b\x4f\xd0\x1f\xf3\x22\xee\xdf\x35\xf9\x51\x1e\x26\x60\x7e\x06\x63\x14\x7d\x35\xd8\x39\x20\x43\x53\xca\xb3\xc3\x6f\xd9\xdb\x13\x34\xd8\x91\xa1\x93\xeb\xc9\x10\x5c\xb7\xa6\x3b\xe8\xef\x4d\x4f\x3c\xf6\xbd\x72\x85\x49\x91\x2b\x4c\xa3\x7c\x7b\xae\xa9\x36\xf0\x94\x62\x37\x2b\xe4\xdf\x25\x31\xb7\x79\xfd\x19\x18\xa0\xfe\x28\x91\x69\x96\x34\x94\x21\x1c\x2e\x28\xd2\x5f\x64\x48\xfd\x52\x27\x72\x89\x12\xb8\x50\xb7\x72\x3a\xb6\x3b\xe9\xfe\x58\x1e\xd5\x56\x56\xce\x62\x82\x3f\x9b\x56\xc9\x22\x7b\xdd\x7f\x4b\x75\x2f\x23\xb1\x8d\xca\x06\xf9\x81\x59\x29\xf5\x81\x81\xae\xd1\xda\xe2\x0f\xea\x42\x7d\x0b\x46\xf7\xf0\x26\x87\xa8\xa7\xac\x6f\x36\x54\x61\x3d\x8d\xf7\xa6\xa7\x9e\x55\x01\x39\x72\xc3\x64\x1b\xd6\x2a\x0f\xbf\xad\xd8\x57\xdf\x96\xd5\x0e\xc7\x3e\x1c\xe7\x4c\xb2\x7a\xe9\x0c\x44\x2f\x7d\xf9\xf4\xa7\x64\x88\x86\xf2\xfc\x34\x79\xf1\xef\xe4\x09\x19\x46\xcc\x8b\xe4\xec\xb1\x0f\x1c\x07\x00\x31\x5d\xf4\xf7\xca\x9a\x53\x4a\x0f\x3c\x8e\xaf\x33\x35\x4f\xee\x6d\x15\xa5\xa5\x14\xee\x1e\x10\x60\x29\x00\xf0\x27\xa6\x0e\x44\x72\xaf\xb8\xa9\xda\x8b\x36\x3a\x8c\x4b\xe5\x6d\x31\x87\x98\x18\x59\x0b\xbf\x5e\xe5\x0a\x65\x11\x60\x1c\x6a\x20\xa6\x8b\x6b\x2c\x19\x46\xf9\x1a\x4b\x80\xb7\x4a\x60\x43\x0e\x4d\x51\xa7\x07\x6c\x41\x0d\xb0\x8a\x8f\x1b\x88\x51\xe5\xcf\xa9\xea\xf5\x88\x77\xac\xb4\x54\xda\xeb\x96\x3a\x49\x40\x2c\xe9\x85\xeb\xa8\x37\xd0\x27\xe9\x73\xc2\x9d\xbd\x5e\x86\x32\xf4\x2b\x7b\x1e\x2e\x12\x87\xd6\x47\x76\x72\x5b\x98\x28\x21\xb7\x86\x2c\xa7\xca\x70\x5e\xb2\xb7\x0c\x6d\xbd\xec\x76\x31\x27\xf9\x73\xb1\x7b\x9d\x84\xe4\xb6\xa1\xf2\xb5\x2b\xce\xcf\xc6\xba\x64\xc1\xd5\xef\xf4\x64\x57\x6b\x82\x17\x02\xc6\x2b\x96\x76\x3e\x48\x20\x17\x78\xae\x37\xcb\x99\x3a\xcc\x43\x3f\x6f\xd9\xd9\x1e\x6b\x4d\x2d\x32\x0e\x2a\xa0\xe8\x10\x42\x8c\x57\xcc\x01\x3e\x67\x1d\xaf\xa9\x2c\x20\x1e\xc7\xd6\xea\xe6\xac\x6b\xad\xb0\xf4\xa9\x69\xf2\x5c\x6f\xf9\x4c\x61\x4f\xd6\x58\x86\xf1\x36\xbf\x86\xa9\xc6\x3c\x09\x18\x75\x98\xd2\xc2\xa8\x4d\x17\xa3\x81\x4f\x2f\xad\x3d\x4a\x1b\x97\xc4\x5d\x34\x88\xf5\xe0\x4e\x5c\x13\xc9\x39\x94\x2f\x85\x3c\xb8\x5b\x83\x17\x45\x56\x81\xc1\x57\x64\x2b\x21\x35\x75\xcc\x30\xee\x12\x63\x83\x9a\x41\xe5\x62\x8d\x02\xe3\xb1\x8e\x55\xe3\xb3\x21\x0e\xa3\x7c\xad\xa6\xc9\xa1\x1c\xe3\x78\x0c\x29\x4b\x93\xc1\x50\x19\x3e\x61\x85\x76\xa7\x1e\x83\x6a\x5c\x5c\xad\x84\x22\x5e\xef\x32\xfd\xd5\x3b\x8f\x75\x91\xbe\x02\xee\xd1\x5b\xbf\x05\xa4\x86\xca\x65\x1d\x5f\x53\x81\xb9\xcd\xeb\x62\xa6\xbf\xba\xa8\xb1\x9e\xf3\xa9\x94\x0a\xcc\xfe\xa8\xa6\x1a\x2b\xc7\xf1\x74\xbe\x9e\x4a\x6e\xc0\xd5\x54\x94\xcb\x25\x7d\xa6\x77\xf8\xb3\x5a\xf2\x69\x1c\x6b\xbd\x2f\xfd\xc4\x7a\x16\x91\x98\x7b\x41\x1e\x4d\xee\x8d\xfe\xc8\xa3\x3d\x02\x7e\x89\xa2\x67\x5c\x2b\x7c\x88\xc0\x8e\x09\xeb\x7f\xf1\x9a\xcf\x22\x44\x16\xf8\xa3\xf7\xd1\x7e\xf9\x63\xf9\xea\xeb\x21\x7f\x5d\x33\x91\xac\xb9\x4c\xe4\xd7\x89\xe5\x8c\x15\x84\x49\x51\x10\xf2\x4a\x35\x1a\x37\x2d\xde\xfd\xb6\xbc\x04\xfb\x34\x81\xf0\x4b\xba\x3e\x9c\x2c\x93\xaf\x0d\x8b\xd5\x1e\x1d\xfb\x73\xa6\xd2\x50\x85\xf3\xb7\xfa\xf3\x4c\x5a\x72\xa1\xd3\x61\x09\x87\x86\xae\x66\x0d\xc7\x2e\x95\x5c\xb9\x0f\x0e\x83\xc3\xde\x28\x18\x7c\x22\x22\xf6\xa9\xf2\x29\xe8\x05\x74\x12\x33\xf9\xcb\x4f\xff\xba\xf1\x73\xcb\xbf\xff\x03\xe7\x09\x4f\xac\x7c\x0d\xcb\xe1\x53\x17\xa3\x1f\x5b\xd3\x75\xc7\x7e\xfb\x7e\x84\xb6\xa1\x4a\xb8\x12\x96\xa3\xab\xe8\x53\x98\x04\xed\xb0\x2f\xec\x8f\x3e\x23\x52\xe4\x35\x49\x2a\x3b\x5a\xe8\x24\xc6\x8a\x57\x37\xc9\xe2\x1b\x30\xb9\x84\x04\x4c\xa9\xaf\xca\xe2\xfc\x61\x37\xe7\x36\xe7\xa7\x67\xf7\x3c\x1e\xde\xe7\xf1\x8a\x61\xbc\x7a\x6e\xdb\xf5\x72\xc3\x96\x97\x5f\xde\x74\x4a\x80\x85\xc9\x1a\x59\x10\x31\x74\x66\x85\x65\xe7\xab\xf6\xd5\xaf\x09\xaa\xf8\xe5\xc7\x5f\x7c\x72\xee\xf3\xcf\xe1\x77\xca\x38\xf3\x40\xb9\x92\x12\x01\x7c\x72\x75\x9a\x4f\x04\xf0\x8f\x2a\xf2\x3e\x29\x35\xa1\x93\x5c\x09\xc8\x7c\x70\xd5\x4f\xc0\xe5\x8b\x2b\xb2\x9b\x00\x49\xe0\xe9\x3a\xe6\x29\xcd\x2f\x9d\xf2\x58\x2c\xfa\x52\xad\x52\xd5\x9a\xd1\x1f\xd2\x1e\x54\x1e\x0e\x0a\xbc\xd5\x61\xde\x32\xfc\xe4\x4d\x63\x19\xe9\x85\x3e\x8d\xf5\xa4\x37\x0e\xed\xca\xb5\x2d\xc7\xa3\x03\xf3\x38\xc0\x1f\x7d\xd3\x34\xd9\x3e\xc9\xd4\x3b\x5d\xf4\x77\xda\xaa\x0e\x41\x79\x5e\xe9\x6b\x7c\x05\x32\x3d\x5e\x7d\x55\xe9\x8a\x63\xb4\xc9\x7d\x46\x07\xee\x00\x81\x74\x5d\x9e\xc9\x32\xd5\x99\x68\x31\x4f\x3c\xb7\xa7\x63\x2a\xf1\x9b\x5c\xfc\xfb\x43\xbe\x74\x56\xe1\x4c\x7c\xa9\x6b\xa5\xcc\x91\xf8\xc1\x69\x5b\x17\xc5\x5e\xb6\x12\x35\xd0\x49\xd4\x4d\x31\x26\xd3\x0f\x3d\x55\xb9\x0f\x2f\x2a\xaa\xda\xff\x79\x51\xcf\xf6\xae\xb2\x78\xe1\xc3\xa8\x41\xcc\x3d\xf6\x91\x79\xac\xce\x1d\x3c\x23\xf6\xa8\x91\x66\xea\x96\xf5\xd1\x88\x1a\xc4\xdc\x62\xed\xdc\x40\xa8\x9f\x0b\x08\xc7\x89\x77\x3e\x9e\x49\xc4\xd3\x14\xe7\x23\x38\x37\xd2\x70\x1d\x18\x3d\x72\x59\xf9\xbc\x48\xd5\xa4\x57\x0b\xb4\x43\x31\xcb\x3d\x85\x62\xa6\xc9\xe7\x35\xc1\xe7\x3d\xd6\x01\x13\xae\x27\xa6\x29\x97\xba\x4b\xb5\x70\x59\x8a\xa8\x3f\x0f\x01\xe9\x4a\xa5\xad\xc3\x32\x32\xab\x0c\x55\xa0\x07\xce\x5d\x91\xf5\x69\x16\x94\x9c\x5b\x3e\x49\xfe\xfd\xf0\x5b\x27\x4e\x1d\x3a\xfa\xe6\xb8\x3f\xbc\x1b\x6e\x3d\xb0\x05\x7d\x8d\x6e\xa1\x1b\xe8\x02\x7c\x5b\xf0\x9e\xac\x9c\x45\xaf\xbd\xf7\xce\x5b\xe4\xa1\xf7\x43\x97\x37\x74\x7d\xeb\x48\x0f\x77\x7d\x07\x40\xff\x80\x7d\xe8\x58\x99\xe3\xc4\xf2\xd2\x7b\x19\x2b\xe8\xc5\xbf\x60\xae\xd1\xb7\x24\xb8\xd0\x3d\x2f\x71\xc9\xc8\x77\xc3\xfb\xbc\xb6\x71\x43\x8f\xe0\xf4\x83\x0f\x9d\xf9\x10\x96\xf1\xdd\xc3\xa5\xc4\x39\xf7\x60\x2c\xf3\xc0\x25\x5d\xfe\xd8\x60\x79\xf7\x6d\x63\xfb\x01\x9c\xdb\x99\x2a\xaf\xe5\xed\xbf\xdc\x82\x47\xd4\x91\xbb\x97\xe0\x09\xbd\xc8\xcd\x8c\x93\xf9\xe5\x80\xe4\x96\x1c\xb2\xb6\xdc\xcf\xf3\xbd\xeb\x8b\x4d\x4f\x57\xf4\xcd\xc9\x7d\x9d\x8b\x65\xf0\x2a\xb7\x87\x72\x6b\x8a\xbf\xcf\x43\xc7\xf5\x38\xb8\xcf\xe3\x0e\x8e\xe3\xa1\x0e\xf4\xc2\xd1\xf8\x3e\xc6\x5f\x5b\xf1\xd5\x6a\x30\x58\xa5\xff\x7a\xa4\xe8\xcc\x03\x07\xbe\xeb\xf7\xc6\x8b\x5e\xd1\x00\x2d\x72\xce\x7a\xab\x1d\xa0\x3b\x45\x3c\xf3\x80\x31\x4f\xf4\x35\xd0\x4b\x9d\x41\xae\xa1\x2f\xde\x8a\x09\xa8\xc8\x9a\xae\x5f\x53\x40\x77\x0a\x69\xd4\x16\x68\x60\x56\x31\x26\xd0\x03\x24\x78\xd7\x27\x85\xe1\xd7\x54\x25\xa5\xfd\xd7\xe1\xc7\x8d\xa4\xfb\xea\x46\xd4\x40\xef\xa5\x7e\xf1\xac\x72\xa1\xa1\x3f\x9e\x0e\x41\xad\x3a\x23\x65\x7e\x41\x47\x7e\x95\x7f\xe0\x72\xa4\xaa\x40\x10\x88\x92\xe7\x48\x89\x53\x56\xcc\x90\xfa\x4c\x4c\x2b\x96\x12\xa4\xe8\x54\xc5\xbc\xe4\xf2\x2b\xd8\xb5\xba\xd5\x4b\x76\x85\xd8\xb4\x5e\x3e\xc5\x97\x62\xe2\xb0\x46\x16\x05\x13\x29\x74\xc9\xe5\x63\xaf\xc0\xef\xe3\xf9\xcc\xef\x8a\x92\x3d\x61\x20\xc2\x6f\xbf\x22\x8d\x03\xc6\x4e\x15\x79\xcf\xef\xa2\xfd\xc8\xef\x82\xf1\xb2\x8c\x6f\x4f\xfc\xf2\x3a\x7f\x1c\xf7\xd7\x41\x10\x97\x4f\x2e\x72\xaf\x32\x13\xa2\x10\x4e\x65\x94\x82\x6c\x1c\x72\x3d\xec\x12\x37\x16\x75\xfc\xc9\xb1\xee\x58\xa8\x73\x02\x74\x84\x1a\x29\xef\x59\x7b\x5c\x62\x95\xeb\x00\x4e\x36\x07\x08\x62\xd7\x37\xa2\x6c\xda\xd7\x83\xa2\x80\xe8\x3b\xdd\xb0\x04\x49\x58\xb2\xdd\xa3\x44\x89\x98\x9f\xc7\xad\xcb\x75\xe5\xd5\xee\x5e\x4f\x68\xf4\x17\xfd\xe2\x03\x9e\x04\x50\x57\xb5\xf6\x0a\xd4\x39\x26\x0d\xaf\xba\xb3\xf9\xb7\xa9\xba\x5a\x1c\x99\x2e\x07\x43\x98\x8d\xdc\x6b\xaf\x78\x66\x73\x13\x5c\xfe\x40\x55\x1f\x97\x33\xd3\x19\x97\xe0\x14\x14\xae\xf2\x97\xaf\x97\xec\xc8\xec\xd2\x2d\x71\x6d\xb7\x9e\x69\xb6\x3e\xbd\x23\x87\xc4\xdd\x33\xc9\x18\x31\x68\xf7\xa2\x0b\x3f\x1d\x59\xf3\xfc\xee\xf5\x1b\x77\xa1\x2b\x97\x97\x24\xe7\xe4\x24\xa7\xbb\x2a\x08\x2b\x8c\x82\x49\xe3\xc7\x4f\x1e\x30\x0c\xb9\x67\xa1\xd2\xc1\x19\x21\x35\xc1\xc6\xd2\xb1\xf7\x94\xc0\xfe\x30\xf8\xe3\x4f\xde\xf9\x32\xec\xda\x49\x34\x2a\xe4\xee\x94\xf4\x8c\x94\x02\xe7\xbc\x47\xc5\xbd\x76\xa7\xf1\x4a\xab\x72\x93\xc5\x9c\x02\xfd\xc2\xfb\x67\x57\x5a\x72\x6e\x6e\xf2\x92\x47\xe6\xf8\x05\x18\xfe\xdb\x59\x90\x92\x91\x9e\x72\x77\xc8\xa8\xb0\x47\x85\xf3\x3e\x09\xef\xd0\xdf\xc6\xb0\xf8\xc6\xa3\x3f\xc8\x7b\x08\x4c\xaf\x7a\xaf\x5b\x41\x69\x6d\xc0\x7c\x43\x97\xb9\xe2\x78\xf7\xdd\xbf\x59\x06\x15\xeb\xae\x40\x64\x30\xf1\xec\x2f\xae\xb8\xfd\x5e\x6c\x6e\xe9\xd3\x81\x8f\xc1\xdb\xe6\x67\x76\x76\x7f\x59\x8a\x65\xf8\xdd\xc6\x42\x78\xb3\xc7\x2f\x39\x46\x0a\x63\xb1\xb1\xa0\xdb\xa9\x92\xa5\x01\x8f\x45\x50\xf7\xe3\x15\xe6\x4d\x9b\x7f\xef\xb1\xa0\x03\x91\x21\xd3\x95\xce\x0a\xb1\xe4\x91\x0a\xd8\xc5\x7f\x29\x14\x83\xb1\x90\x17\x43\x94\xe3\x1a\x3e\x59\x29\x00\x63\xfd\x91\xc3\xcb\x79\x85\x6c\x84\xf0\x00\xf9\xb0\x46\x0d\x61\x15\xac\xd1\x1c\xd1\x27\x35\x3d\x72\x72\x97\x79\xf7\x26\xdd\x55\x3c\x32\x2e\x3d\x2d\x7c\x90\x20\xeb\xf9\x25\x15\x99\x19\x73\x2a\xbd\x49\x48\x7d\x33\x77\x19\x2e\x29\x5e\xc9\x55\x16\x6f\x4f\xe4\x25\xfe\xa1\x80\xce\x2c\xed\x9f\x52\x31\x65\x8a\xa7\x9c\x25\xbf\x8b\x9c\xd1\x19\xac\x84\xbe\x8d\xd8\xa3\x3a\x62\xf6\x16\xc4\x3c\x52\x5e\x51\xb1\x64\xe1\x82\x4e\x89\x09\xf7\x55\x4c\x28\xcd\xa4\x0b\x82\xcb\xb0\x5d\xc6\x71\xc6\xf4\x47\xc0\x00\xba\x82\x9e\x52\x94\x2b\x61\x50\xcc\x1a\x75\x44\xb1\xfd\x11\x7e\x62\xbc\xac\x0c\x1a\xa6\xe6\x86\x49\xda\xef\x7e\x42\x08\x15\xf6\xd2\x8f\x53\xae\xd9\x09\x50\xd5\xcf\x7a\xc1\x8a\x43\xb3\xaa\xa3\xbf\xcf\x93\xf4\xd3\xdd\x2e\xc5\x24\x43\x00\xe8\x1f\xe9\x8f\x40\x38\x7e\xd7\x18\xd7\x94\x53\x9a\x62\x55\xba\x19\xd7\x23\x14\xe6\x79\xa9\xd4\x77\x2d\x36\xbf\xf0\x0e\xae\x63\x6a\x9a\x6c\x5a\xb7\x6d\x10\x70\xd0\x2f\x62\x63\xeb\x1e\xc3\x21\xe0\xfa\x47\x8a\xfe\x95\x53\x57\xa7\x7f\xd1\x5e\x7e\x2b\x01\xd8\x85\x4d\x27\xe4\x03\x87\xe9\xbb\x64\x13\xb2\xad\x87\x0c\x00\x6b\x28\xdd\xa3\x44\xae\x39\x0c\xc7\xfd\xe2\x80\x33\x23\xd1\x4a\x0e\x92\x25\x08\xe3\xb0\xc1\xf8\x87\x57\x0a\xa8\x87\x38\xeb\xe0\xfe\x45\xce\xc1\x71\xbf\x38\x50\xf4\x2f\xda\xa9\xdd\x3a\x00\x74\x28\x50\x03\x60\x39\xe8\xf8\x18\x00\xfa\x0c\xf3\x18\x7e\x3d\x0e\xc7\xcf\xeb\xbc\x5e\x27\x41\x91\x4c\x10\x37\x26\xe9\x3a\xb3\xf0\x09\x59\x76\x0c\x67\x6e\x60\x5f\x1e\x5f\x9d\x72\xce\xb5\x2e\x10\x21\x8e\x12\x8d\x0b\x32\xf1\x28\x95\x18\x93\x40\x9a\x4f\x8c\x32\xf3\xe1\x37\xc4\x1d\x9c\xa9\x80\xab\x7d\x41\xa4\xc3\x05\xbb\xe0\x6e\x16\x79\x24\xc0\x84\x8e\x16\xb2\x81\x49\x03\xf1\xf8\xa4\x3f\x23\xd3\xe5\x4c\x81\x9c\x22\x59\x0c\x29\xd0\x16\x67\x36\x59\x1d\x66\x5b\x1f\x33\x5f\x22\x80\xe1\xce\x22\xe4\xda\x36\xa1\xb2\xe6\xfe\x8a\xef\xdf\x5d\xf0\xca\x3d\x05\xf7\x3f\x59\x74\x1b\x66\x55\x6d\x44\x1f\x6e\x58\x77\xf7\x9f\x66\xac\xba\xfe\xd5\xbf\xe1\x74\x41\xed\x60\xd2\xfd\x35\x09\xa1\x3d\xff\x38\x65\xc5\xd6\xf8\xc4\x75\x77\xf4\xdc\xda\x54\xff\xf6\xc4\x29\xf6\xd4\x6d\xa3\xfe\x44\xa5\xa8\xd6\x93\x9d\xc3\xa5\xd4\x42\x1f\xb8\x8a\xc5\x05\xa4\x17\x60\xb4\x55\xb1\x6c\x04\xa4\x02\xd7\x20\x7f\x91\xa9\xe7\x27\x6f\x1b\xbc\x23\x7c\x4b\xb9\x4e\xf4\x97\x3e\x61\x79\xd8\x69\xac\xda\xcb\x42\xef\x58\x77\xaa\xd6\x83\xfe\x52\x2a\xac\x02\x7f\x1f\x5e\x85\xa5\x9f\x77\xac\xdf\x28\xd7\x7c\xfe\xf2\x2a\x2c\xf5\x7e\x27\x5e\x69\xbf\xb0\x9e\x55\xaf\xed\xfc\x25\x56\x5c\xd1\xb1\x73\x09\x02\x40\xed\xc5\xf6\xba\x87\x87\xaf\x80\xf2\xc0\x50\x71\xaa\x02\x29\x10\x54\xed\x15\x84\x08\x50\xbe\xdd\x6d\x62\xbb\x4a\xf9\x14\xed\x4a\x53\x6d\xae\xd4\xb0\xda\xda\x8b\x0d\xe3\x79\xc6\xfa\x98\x2b\xbc\x8f\x89\xf3\xf4\x70\x82\x77\xd5\x42\xcf\xcf\x97\xfb\x74\x64\xe0\x27\x48\xeb\xf7\xb2\x1e\xb9\xfe\x3e\x95\xf5\xa7\x3d\x0b\xb4\xa4\x12\x75\x7e\x86\x8e\x6c\x9c\x92\xb7\x5e\xf7\xe8\xaf\x49\x57\x3e\x41\x93\x35\xe5\xe3\xf5\x36\x5a\x47\x3e\x5e\x51\xdb\x56\x7b\xed\x4f\x5b\x1b\x95\xf2\xa9\x75\x2f\x5a\x47\xc0\x85\x1a\x3d\x72\x35\x6c\x4c\xd4\x68\x26\x0d\x98\xf8\x57\x96\x35\xde\x68\x53\x8a\x2d\x3d\xaa\xf5\xf0\x1f\x5f\xde\x7c\x5d\x10\x98\x7f\x50\xab\x6d\x24\xb5\xf7\xc9\xda\x77\xcf\xbb\x4f\x53\xa7\x3c\xfc\x85\x1f\x7d\x29\x45\x56\xf6\x25\x1d\x27\x78\x74\x46\x1f\x56\xfb\x00\x79\x5f\x49\xfe\x49\x26\x28\xac\xb2\x57\x4a\xa9\xb2\xde\xe5\x14\x0c\xbb\x9f\xfd\x6b\x2b\xb0\xb2\xff\x50\x95\x0a\x7b\x97\x9d\x37\xd6\x9d\x92\x5f\x50\x68\x65\xff\x39\x4a\x95\xf6\x2e\xbf\x60\x80\x3b\x25\x3f\xad\xd9\x7f\x92\x5a\xc5\xbd\x13\x20\x19\x55\x01\x03\x97\xcf\x94\xa5\xff\x62\x9c\x66\x5d\x5b\xd9\x52\x54\x89\x27\x45\x67\xbd\x57\xcf\xad\x43\x3d\xd1\xdd\x52\xae\xf6\xd0\x11\xd9\x1e\x57\x89\x71\x40\x40\x18\x2d\xb2\xa5\xa8\x7f\x10\xb7\x72\xeb\x50\x9f\x10\x6b\xc4\xdd\x29\xf6\x1f\xf4\x25\x5d\xbf\x24\x7b\x06\x5f\xf2\x4b\xfc\xf3\xdd\x1e\x4e\x49\xf1\x0e\x39\xdb\xee\x59\x5d\xbf\x24\x6b\x57\xe6\x97\xf8\x86\x3d\x9c\x92\xac\x61\xc1\x2f\x19\x82\xfc\xf0\x4b\x1a\xe8\x05\xbf\xa4\x25\x83\xcc\x29\xc9\x7b\xc4\xfd\x31\xc8\x0f\xbf\xe4\x29\x95\xe4\x97\xb4\x64\x93\x9c\x92\x67\x7f\x3f\xfa\xe1\x97\x34\xe4\xe3\xfd\x52\x3f\x2d\xf9\x64\x4e\xc9\x7b\x7f\x7a\x7e\x49\x2e\x9f\xda\x2f\xf5\xd3\x12\x70\xa1\x76\x8f\x00\x90\xec\xbe\xcc\x60\xc4\xfb\x32\x5c\x17\xd5\x8f\x69\x2a\xef\x5f\x6f\x53\xc6\x4f\x52\x58\x23\xa0\xa9\xd3\x9d\x9c\x6d\xfb\x54\xa0\x30\x26\xa6\x1d\x63\xc2\xb1\x2c\xbe\xa7\xa5\x3f\x90\xf8\x49\x09\xbf\xd0\x81\x24\x4e\xc6\xb6\x62\x25\x20\x02\x6c\xef\x68\x21\x76\x30\x69\x20\x1c\xf4\xf6\xd0\x02\x52\xb8\x6a\xe4\x0f\xc8\xb6\x0b\x1a\xb0\xe0\x60\xd1\xf8\x3b\xa6\xf7\x88\x79\x30\x73\x57\xbd\xc2\x76\xb7\x57\x92\x41\xed\xad\xf7\x4f\x8f\x08\x7a\x26\xcc\xb4\x97\x6d\x7f\xa3\xa2\x7d\xd5\xf9\x81\xaa\xfd\x8d\xe2\x3c\x8d\x96\x75\xa0\x30\xcd\x6d\xff\x53\x74\x40\x76\x20\x59\xfb\x09\x00\x90\xaa\x79\xaa\xea\x41\x98\xb7\x84\x20\x49\xba\xac\xa3\x89\x9c\x73\xd6\x97\x87\x5e\xc8\x6f\xb9\x00\xd9\xd1\xa6\xea\xd7\xbb\x64\x42\xbf\xb4\x38\x67\x5f\x91\x75\x3c\x0a\xcf\x5f\x2f\x72\xd2\x0b\xc5\xfd\xd3\x00\x65\xbf\x3e\x46\x4c\x28\xba\x31\x40\x90\x37\x48\xd6\xed\x0b\x9c\x2b\xd4\x97\x97\x1a\x2a\xed\x85\x22\x54\xfd\xfa\x92\x97\xeb\x37\x42\x9c\xc3\x9b\x65\x1d\x3f\x84\x3b\xf6\x22\xaf\xd8\x31\xd9\xf1\x2a\xee\xf7\x1a\x9e\xc3\x19\x7e\xcd\x61\x35\x07\x63\xbd\xcf\xe3\x39\x72\x55\xd3\xf7\xb3\xed\x2b\x95\x9a\xcd\xea\x40\xbd\x88\xcd\x06\x1c\xfe\xcc\x65\x35\x4d\xf3\xbc\xcf\xe7\x18\x2f\xd0\xc4\x29\xdd\x9e\xa4\x02\x86\xfd\x22\x39\x4e\xc7\xdf\x46\xcb\xd3\xdf\x04\xad\x38\xc3\xe5\x95\xa9\xbc\xad\x3c\xb9\x4c\x6c\x77\x98\x9e\xbf\x95\xb7\x2b\xf9\xdb\x0c\xae\x65\x95\xbb\x55\xb4\x8c\x7d\x03\x35\xc3\xb7\xaf\xd5\x42\xce\xfb\xda\x50\x0d\x01\x44\x57\xab\x92\x83\xeb\x6f\x92\x6f\x5f\xab\x21\x91\xe8\x6b\xc3\x35\xe4\x12\x5c\xad\x66\x7f\xcf\xf9\xf6\xb5\x5a\xf2\xf1\xbe\xd6\xa6\x21\x9f\xe8\x6a\x7d\xf6\xa7\xe3\x6b\x15\xf2\xa9\x7d\xad\x4d\x43\xc0\x85\x9a\x3d\x62\x9f\x46\x6d\x0f\xcc\xcf\xca\xfa\xf6\xe5\x67\xa7\xf2\x48\xbc\xb9\x59\x15\x05\x0a\x4c\xfe\xfa\x59\x3f\x20\x09\x7e\xf6\xb4\x36\x24\x99\x9b\xf5\x18\x13\x2e\xe7\x27\x0d\xe7\x9d\x24\xe8\x67\x9d\xa8\xaf\xf4\x35\xf3\x4b\x3e\x16\xef\xf0\x75\x92\x48\x14\xd7\xf6\x7e\xf7\xad\xbe\x9e\xd7\xec\xfb\xbc\x74\x1f\xaf\x97\x4e\xa4\xbc\x82\x17\xf3\x9d\x84\xfe\x53\xfc\x96\x3e\xda\xeb\xd3\xba\xa9\xaa\xfb\x75\x3f\xb8\x10\xcf\x4c\x03\xc0\xa4\x77\x7d\xae\x89\xc9\xa1\xbe\x2f\xf7\x87\x23\x7e\xbf\xdd\x79\x9e\x5c\x5e\x93\x14\xc7\xab\xee\xbe\xfd\xe0\x29\x48\x79\x4f\xdc\x19\x9e\x68\xaf\x98\x46\x7a\xdc\x65\xfb\x43\x94\x7c\x5f\x0e\x3b\x5a\x98\x01\xf4\x39\xec\x8b\x3c\xd7\x41\xba\x69\xb9\x02\x17\x4b\x74\xf3\x9f\x14\x36\x16\x55\x79\xcf\x7b\x02\x22\x96\x22\x19\x16\x95\x67\xd4\xc3\x22\x79\x49\x52\x17\x8d\xc2\xfe\xba\x7f\xf5\x85\x86\x62\xb1\x18\x96\x61\x2c\x62\xf5\x67\xcd\x39\xe5\x93\x21\x6e\x56\xfd\xe4\x1f\x4f\xfc\xc4\x72\xbf\xef\x03\x20\x87\xaf\x4a\x81\x4f\x7b\x7e\xe9\xe2\x53\xcd\xb0\x7f\xfb\x47\x1d\x37\xc7\xdc\x27\xfc\xc2\x97\xe9\x85\x3f\x61\xae\xf9\xe4\x8f\x9b\x6d\xab\xfd\xe3\x8f\x9f\x70\xe8\x81\x4e\xe0\xd3\x9e\x77\xfa\xfc\xa9\x66\x9e\x3e\x42\x2d\xdf\xef\x13\x21\x1f\xc7\x4b\x2d\x11\xce\x68\xd9\x35\x6f\xa4\x95\x7b\xe1\xd0\xd1\x1b\x72\xc9\x1a\xaa\xab\xc5\xc6\x43\x30\xf9\xc5\x17\x62\xe2\x0f\xd9\x63\x50\x5b\xc7\x8f\x3f\xc0\x0a\xf1\x24\xe8\x26\x31\xc1\xbd\x1f\xad\xf8\xf1\xbf\x7f\xfc\x74\xcb\xc6\xeb\x8f\xa1\x13\xe8\x42\x1b\xf9\x57\xb9\x7f\xf3\xab\x3f\x25\x49\x1e\xfd\x4d\x93\xe6\xa2\x56\x87\xd4\xa7\x4a\x97\xc6\xbf\x77\xb5\x44\x3a\x9b\xd4\xec\x55\x67\xea\xa9\x7b\x3f\xa6\x5a\xcc\xfa\x14\x59\x74\x63\xfe\xe2\xd0\x9e\x62\x6a\x1c\xef\xa9\x17\xb9\x3e\xa9\x10\x83\xbb\x3a\xc5\x87\x30\x95\xd4\x38\xbe\x53\x2d\x7e\x7d\xf2\x11\x24\xf3\x0b\x9d\xe0\x83\xd6\xc1\xf1\x89\xc7\xa2\xd8\x27\x21\x0b\xc5\xb3\x6b\x0e\x87\x78\x6e\xac\x8d\xc3\xf7\x42\x59\x8d\xa9\xc6\xc7\x62\x59\x0b\x21\x1d\xe1\xe5\xf4\x18\xa8\xb0\x0e\x08\x08\xab\x7c\x01\xad\x86\x3a\xc3\xc7\x22\xda\x1f\xa8\x35\xb2\x18\x27\xee\xbc\xf7\x28\xde\xd7\x58\x3c\xec\x5e\xbc\x18\x3e\x2c\xdb\x7c\x8a\x41\xc3\x0a\x53\xf6\x89\x14\x27\x2c\x9e\xf5\x32\xef\xf3\xfb\xa5\x58\x5d\x8f\xe4\xd1\x83\x38\x4f\x48\xed\x7e\xb8\xd9\xb1\x59\xde\x1b\xd7\xd7\x15\xdd\xbe\x44\xeb\x2d\xf5\xa5\xd2\xc1\x1b\xda\x7d\xf1\x8a\x07\xf3\x55\xb2\xe1\x33\xd0\xae\xfc\x3e\xe8\x0e\xbf\xf6\x41\x42\xd7\x3e\x37\x41\x12\x12\xbd\x7d\x10\xa4\x64\x70\x08\x50\xd5\xd1\x42\x9f\x67\xd2\x80\x1d\xd7\x3c\xc8\x88\xc2\x11\x78\x52\xae\x19\xb7\x94\x24\xec\x8e\xae\x51\x66\xd6\x57\xd9\x6d\x0c\x97\x1c\x2b\x37\x1a\x55\xd9\xb9\x87\xf3\xb3\x17\x55\x4c\x9d\xb5\x6f\xe6\x94\xf2\x47\xb3\xf3\x0f\xe7\xbb\x3e\x79\xf3\xaf\xc3\x42\x86\x7c\xf3\xe6\x27\x84\x78\xd1\x44\x98\x76\xc2\xe0\xd5\x1b\x51\xfb\xf6\xb7\x2f\xac\x7d\x0c\x66\xa2\x0f\xff\xf8\xcc\x87\xa7\x5f\x80\x41\xf5\xcf\x23\xf4\x3c\xea\x40\x97\x0f\x1f\x86\xfd\xc8\xd7\x3c\xee\x17\x3b\x87\x51\x39\x8a\x3e\x30\x4a\x3b\x28\xbf\x40\x52\xbb\xd4\xf7\x92\x72\x8c\xb9\x9d\x66\x52\x70\x47\x5e\xd1\xc2\x2d\xaa\x5d\x56\xe0\xbc\x4a\xf7\x99\x9d\xc5\xad\x3d\x1f\xbd\xe3\x56\x47\xaa\x74\x82\x6b\xf1\x1e\xf4\xf7\xe1\x5b\x70\x77\xde\x71\x1f\x53\xed\xd6\x02\xe7\x5b\xba\x3f\xfd\x7d\xf8\xa6\xfd\xc2\xfd\x27\x8f\x1d\x5d\xe0\x84\xcb\xf7\x77\x1c\xf6\x6b\xc0\x0e\x06\xe3\xca\xe8\xfe\x62\xf7\xed\x52\xbd\xcb\x91\xe7\xdd\xc1\xfa\x29\xd5\xb7\x5e\xef\x6b\xe5\xb2\x8d\xfa\xad\xb2\xc9\x6d\x77\xe7\x44\xe3\x0d\x7a\xe7\x44\x53\xdd\xf3\x32\x0f\xe0\xbd\x89\xd6\xbe\xd3\x9a\x40\x38\xb9\x4d\x89\x89\x30\x58\xcd\x56\x67\x66\x94\x33\x83\xc0\x8f\xa1\x47\xc9\x4e\x3c\x8b\xe0\xdc\xe7\x76\xc0\x19\x70\x20\xbb\x27\xd9\xb9\x11\x3e\xe0\x3e\xf8\xda\x4b\xff\x69\xf9\xf1\xdf\xbb\x5f\x53\x9d\x4f\x37\x3e\x04\x27\x9c\x83\x19\xb0\x0c\xed\x42\x1f\x7d\x8c\xf6\x54\x35\xd6\x57\xc3\x11\x5f\xdd\x82\xa0\xe3\x7f\xdf\xa0\x77\xfe\x58\xcf\xaf\x19\x98\x15\x22\x26\xd5\xad\x85\x2f\x4c\xa2\xa5\xfe\xab\x3e\x28\xd5\xd1\xb6\x6f\x50\xdc\xdd\xf2\x1e\x7e\x0f\x97\xa9\xbf\x43\xf7\x97\x31\xce\x32\xbf\xe1\x27\x6f\xe2\xb1\xb8\x1f\xf4\x69\x60\xd5\xd9\xad\xfb\xc9\xa4\x60\x8d\x4f\xf8\xc9\xa7\x70\xa4\xee\x3f\xd6\x2a\x5d\x5e\xc5\x9d\xbb\xbf\xbc\x72\x16\x78\xb6\x9f\xbc\x8a\xc7\xf1\xfe\x63\x5d\xa6\xcb\x2b\xed\x2f\x56\xb5\xd5\xad\xf4\x93\xd8\x85\xfe\xa3\xe5\xd6\x90\xb3\xf9\xf3\xfd\x02\xbf\xce\xf7\x7d\xe1\xf6\x71\xe6\xbf\xce\x8b\x14\xde\xae\x01\xfc\xa1\x5e\x21\x8f\x0d\x0c\xf5\xeb\xde\xae\x93\xe2\xf0\x96\xf5\x7f\xfe\x8b\x23\xbb\x42\xf0\x4f\x8f\xb8\xfc\x96\x5e\x38\x1f\x29\x23\xd0\x6c\xa4\x40\x52\xc1\xca\x4f\x75\x2b\xf0\x33\x01\x8c\x18\xc2\x9a\x98\x97\x7f\x07\x7c\x01\xa4\x47\xfd\x39\x37\xf6\xbd\xa1\x7e\x26\xa8\x45\x75\xdf\xf9\x8c\xf9\xa9\x97\xa5\xf8\xf3\x5e\x7c\x4d\x40\x3f\xe3\xe2\xfd\x09\x95\x86\x06\x4c\x98\xb7\x40\xde\x4a\x81\xa6\xce\xe2\xf0\x27\xb4\x18\x4e\xc4\xc4\x78\x0b\x7f\xce\x17\xe8\x10\xe3\x2b\x7b\xe1\x57\x33\xf4\x22\xfe\xb4\x42\x0c\x27\x63\x69\x3d\xc2\xc2\x98\x20\x99\x8c\xfe\xb4\xad\x15\xbe\x77\x1e\x4b\xe0\x19\x35\x78\x59\x86\xbb\x00\xdf\xc5\xf7\x02\x06\x7c\x36\x20\x56\xb0\x56\xde\xb7\x17\x60\x90\x56\xd9\xb5\x3a\x8f\xaf\xed\x98\x3a\x6e\x65\x87\xb2\x3d\x0e\x96\x3a\xb4\x60\x07\x06\x56\x2c\x8f\x86\xe1\x31\xb5\xcf\x51\xc6\xa9\xf0\xf7\x28\xbd\xf0\x3d\x4a\xac\xb7\x8a\x7f\xde\xae\x97\x1e\xe3\xe6\xa0\x5e\xe9\x38\x71\xda\x05\xd2\x9f\xb7\x6b\x9a\xeb\xdc\x9c\xd2\xaf\x1b\x28\xf1\xcf\x9d\x21\xf1\x63\xab\x73\xe6\xab\x7d\xec\x08\x49\x6e\xa2\x68\x9e\x07\x59\x39\x91\xfc\x6b\x5f\xfb\x18\x0f\x3e\xc4\x4d\x00\xcd\x63\xc4\x9b\xa2\x08\xe2\xde\xbf\x17\xb0\xe3\xfc\x70\xbf\x77\x79\xfe\x6c\x47\x7f\xe6\x46\xce\xbf\x25\xf6\x2f\xb2\x39\xd3\x49\x4c\x7e\x6c\xd9\x88\x51\xdc\xe8\xfa\xb7\xc3\x3c\x25\x12\x45\x81\x4a\x94\x23\xe6\xc0\x0e\x04\x23\x03\xb5\xea\x0e\x33\xf7\x01\xd6\x86\x39\xa3\x3b\x91\xc3\xfe\xfe\xf3\xbd\xfb\x5a\xee\xc8\x1c\x51\x34\x21\x3a\xa0\x6c\xf6\xb6\x23\x0b\x92\x13\x43\x17\x47\x97\xcd\xa4\x55\x81\xe5\x4a\x99\xb2\x03\x97\x49\xb5\xb1\x50\x88\x18\x60\x9e\x7b\xa8\x28\x5d\xe0\x09\xbe\xad\x99\x82\x84\x00\xd0\x1e\x32\xf9\x95\xe5\xeb\x25\xfb\x5d\x35\x70\x9d\xc9\x85\xcf\x10\x85\xbb\xa7\x73\x59\xf1\xad\x07\x04\x09\x0d\x41\xdc\xb9\xd2\x6f\x97\xd3\xeb\xe8\x05\x24\xa7\x94\x2f\x7f\x50\x14\x74\x78\x27\x33\xe7\xa5\xb1\x34\x04\x09\xf7\x2c\xff\xef\x63\xda\x99\x9c\x7a\x5a\x14\xf5\xd9\xce\x65\xd7\x4b\x63\x4a\x5f\x96\xf2\x99\xfe\xdf\xc7\xb5\x53\xb9\xf7\xcf\x8a\xc2\x2e\xeb\x64\x12\xbe\x34\xae\x92\xb4\x82\xac\x42\x9e\xfa\x38\x30\xf5\xf7\xc9\x54\xf7\xb4\xb5\xbf\x4b\x7e\xbe\x64\x81\x83\x7f\x43\xa6\xbe\xcc\x1e\x1f\x90\x0e\xc8\xd4\x5c\x94\x80\xb2\xdf\x3d\x6b\xdf\x7f\x03\xed\x6f\x0e\x7f\x98\x5f\x56\xdb\x8f\x6c\xfe\xd6\x0a\xc9\x84\x03\x0a\x80\x8e\x16\xc3\xdb\x62\xbe\xfd\x1d\xf2\x77\x56\x95\x79\x14\x5c\xee\xb5\x6a\x81\x2a\xe5\x0f\x8b\xb1\xdb\x30\x9a\xcb\x20\x26\x97\xc8\xa3\x4b\x85\xfc\x66\xf9\x89\x06\x9f\x8e\xef\x8e\x55\xae\x8d\xbd\x61\x52\x45\xbe\xf8\xc0\xb4\x5e\xba\xaa\x7b\xdc\x0b\x28\x65\x0c\xcc\x13\x5a\xa0\x68\x00\x3b\x5a\x82\x56\xcb\x72\xd5\x33\xfc\xad\x18\xa0\x42\xe7\xbb\x82\x80\x02\xa3\x5f\xe5\x04\xd4\x0c\x02\x1e\xef\x0e\x15\x5e\xbf\x2a\x0c\xa8\xf1\xfa\xae\x38\xa0\x24\xd5\x9f\xf2\x03\x1e\x80\x39\xbc\xf7\xfb\xc9\xaf\xa2\x1a\x80\x1e\xbf\x7a\xd5\x09\xfc\xa1\x57\x55\x29\x40\x8f\x5f\x35\x5e\xbf\xaa\x17\x78\xf0\xeb\xab\x9a\x81\x3f\xf4\xfa\x02\x4c\x77\x7c\xdc\xd1\x12\xf4\x80\xac\xce\x41\x7e\x27\x2a\x1d\xa8\xb1\x07\x5e\xf9\x40\x29\x4b\x00\x65\x10\xd4\xf3\x51\x21\x4f\x12\x48\x03\x43\x02\xaf\x8a\xd0\x09\x71\x54\x55\x12\xfc\x14\xc7\xa3\x64\x82\xc7\xf8\xc8\x73\x11\xe3\x40\x9a\xce\xe9\x85\x41\xe1\x55\xa0\xb7\x9c\xd7\x97\x44\x77\x01\x9f\xd1\x4d\x7f\xad\xd6\xdb\xae\x74\x0e\x8f\xb7\xbc\x58\x19\x9e\xe9\xfa\x29\xb2\x22\x20\xe6\xb0\x3a\xc6\x57\x89\x47\x2f\x53\xd2\xe0\x6d\xef\xa7\x7d\xb0\x24\x21\xfb\x93\x8f\x2c\x5a\x6d\xba\x64\x31\xbf\x9d\xc2\xe8\x4f\x7e\xad\x84\xf1\xa0\xaf\x4c\x5b\x6d\x0a\x85\x40\xaa\xdf\x85\x47\xed\x1c\x5c\x09\xe3\xdf\x7c\x64\xe3\x6a\xf3\x28\x8b\x09\xfe\x1d\x78\xd4\xce\xd3\x95\x30\x7e\xe6\x33\x63\x57\x9b\x48\x59\x3d\x04\x4a\x96\x17\x1b\x07\x06\x82\x11\xfe\xe1\x0c\x34\x97\x57\xc2\xbc\x24\xc0\xac\x5e\x49\x02\x6f\xe9\xbd\x1e\x72\x0c\xff\x0d\x72\xe8\xe7\xfb\xfa\x16\x43\x2f\xf3\x57\x57\x0c\x59\xf0\x16\x8e\x91\x0e\xce\xe3\x73\x87\xfa\x7b\xcf\x02\xd6\x5b\x31\x88\x59\xc1\xb4\xc5\xcb\x12\x41\x96\xdf\x08\xf3\x3d\x72\xb6\x30\x0e\x87\x0c\x87\x97\xac\x61\x9d\x95\x96\x3c\x8b\xb8\xab\x17\xd7\xef\x0d\x08\x8e\xe3\x0d\xa9\x14\x73\x74\xd2\xfd\xcb\x30\xd6\x63\x46\x95\x71\xac\xcf\x8f\x66\xfa\xb1\x0a\x1d\x87\x6d\xb6\x02\x9b\x1f\xd9\xc8\xba\xeb\x52\x75\x76\xb2\x45\x8f\x33\xad\x54\x65\x4d\x6c\xe3\xbc\xf0\xa6\x99\xb9\xac\xc7\x9b\x2a\x93\x59\x31\x9c\xbe\xd3\x9a\xfd\xc0\xe6\x47\x96\xb3\xee\x7a\xd3\x23\xeb\x59\x57\xd9\x34\x53\xa0\x3d\x75\x8e\x5d\x93\x85\x2c\x11\xf3\xb4\xf2\x02\xce\x88\xf6\x77\x41\xe6\x91\x21\xdd\xd5\xcb\x32\x4c\x37\x5d\x5a\x2d\x00\x87\x7f\xa6\x98\xd3\x35\x38\xd0\xec\x69\x7f\xe1\x7b\x64\x53\x5b\xbc\xc0\xd7\x49\xad\x56\x81\x27\x41\x15\xca\x11\x63\xb1\x0a\x3a\x1d\x43\x46\x2a\x6c\xbc\x9f\xb1\x90\x65\xd2\xd1\x44\xe0\xd1\x64\xd2\xd9\x1c\x67\x3f\x3b\x2b\x87\xb7\xa3\x38\x7f\xe3\x25\x7b\x04\x28\x88\x22\xb8\x4c\x7e\x34\x0e\x28\x95\x1c\x81\x44\x98\xf9\x73\x28\xee\x67\x4c\x65\x81\x28\xd0\x88\xce\x46\x57\x7a\x9e\x87\xff\x16\xd9\xfc\x39\x08\xf7\x37\xee\xb2\x59\x14\x2e\xbf\xb3\x11\x98\x5a\x47\xe0\xff\x8f\x63\x17\x50\x7c\x66\xac\x28\xde\xc3\x9d\x8d\xd4\xd4\x3e\xf7\xfe\xff\x1b\xbf\xc0\xe2\x38\xf7\x89\x02\xde\xd7\xd9\x80\x4e\xad\xa3\x6e\x51\x3e\x21\xb6\x73\xd2\xef\x1a\xdd\x19\x80\x85\xf4\x15\xeb\x39\x2a\x50\x73\xa3\x1f\xf5\xd9\xfa\x81\x64\x7c\x94\xf2\x8f\x02\x13\x7f\xcf\x08\xd0\x00\x0c\xab\xaf\x78\xd0\x5e\xbf\x51\xfc\x1a\x8d\x13\x6d\x6e\xfd\x5d\xca\xc7\x63\xe6\x06\x1e\x25\xaa\xb7\x92\xf3\x16\x35\xfa\x07\xfd\xdd\x82\xcf\x18\x2b\x0f\x3f\xce\xe2\xaf\x92\xe1\x0f\x30\xa2\x54\x77\x4f\xe1\x25\xc2\x94\x2a\xd6\xdf\x65\x04\x2a\x80\xb8\xf7\x58\x2f\xc6\x1e\x0e\xef\x7c\x04\xaa\xf7\xfd\x88\xb7\x88\xd4\x62\x9f\x3b\x94\x80\x25\xd3\x92\xab\x93\xd1\xaa\x3e\xf6\x32\x5e\xa2\x57\xf5\xc7\xca\xef\x50\x56\x6d\xb9\xca\xbc\x8c\x97\xdf\x91\xad\xde\xf7\x41\xde\x22\x5d\x75\xe7\x90\xff\x61\xaf\xda\x72\xcd\xf1\x32\x5e\x7e\x47\xc1\xfa\xda\x43\x79\x89\x8a\xd5\x1f\x30\xff\x43\x64\x35\xe6\x18\xde\xab\x8c\x13\x63\x66\xc7\xff\x2e\x51\xb3\x01\xee\xbf\xbc\x44\xd1\x2a\xc6\xf3\xb7\x85\xd4\xea\xec\x33\xc7\x89\xf1\xb5\x77\xfd\x1e\x11\xb6\x01\xee\xdd\xbc\x44\xdc\x7a\x15\x3d\x90\xf0\x5b\xb5\xe0\x7c\xac\x2b\xdd\xc2\xc7\x45\x05\x1a\x15\xc5\xbd\x9b\x8f\xf9\xf1\x2f\xd8\x84\x98\x1f\x34\xbe\x6a\xe6\xf4\xa0\xca\x2e\xfb\x56\xad\x79\xd1\xbf\xc8\xdc\xf8\x11\xd9\x83\x87\xd6\x3c\xfb\x8c\x14\x9b\x4b\x57\x80\x3e\x5c\xdd\x16\xdf\x78\x9d\x56\x33\x94\x61\xf6\x86\xf2\x4d\x62\x9a\xfb\x45\x11\xa9\x17\x6c\xe4\xc9\xba\x3a\xf7\x70\x1e\x1f\x90\xc5\x62\x09\x31\xc3\xf9\x9d\x8c\x6a\xee\x44\x10\x16\x17\xe3\x1c\x13\x58\x00\x16\x1f\x76\xf9\x6b\x87\x6c\x7f\x49\x72\x32\x50\x65\x9d\xd4\x85\x80\x91\xbf\x1f\x18\x66\x29\xf2\xe2\xf7\xe0\x9b\x0f\x8e\xed\x44\xd0\x1b\x8e\x40\x1c\x15\x60\xc0\x1b\x1f\x76\xda\xda\x24\xc9\x20\xe8\xb2\x10\x33\xf2\x7b\xc4\x8b\x78\x93\x60\x89\xce\xab\x3f\x76\xff\x34\x5e\xf5\x0c\xa7\xa4\xfd\xfc\x58\xd0\x52\x1c\xd0\xef\x1f\x05\xf4\x9b\xe4\xf2\x4f\xcf\x74\x25\x94\xeb\x1d\xff\x96\x84\x21\x17\x18\x80\x19\xc4\x48\x6f\x49\x28\x4d\xa1\xfa\xc9\x8a\x0d\x0a\xab\x37\x46\xf9\x9c\x84\x21\x97\xb7\x6f\x6d\xaf\xab\xdf\xac\x60\x8e\x02\x03\x08\x05\x46\x59\x3f\xac\x39\x53\xb5\xfe\x3a\x31\xcd\x7d\x59\xd9\x26\x93\x54\x57\xd7\x9e\xc3\x35\x27\xbc\x7f\xc1\xb6\x15\x01\xcc\xf2\x68\x1c\x79\x90\x86\xd4\xde\xb3\x5c\x6c\x73\x96\xb2\x49\x2e\x3c\x44\xf6\xd8\x83\x97\x76\xf9\x23\x63\x55\xbb\x8f\x70\x31\xcd\xe1\xaa\xd7\x34\x1e\xe2\xa6\x86\xf8\x82\x02\xc9\xc7\xea\xb0\xed\x76\x01\xbd\x64\xb2\xfb\x08\xcd\x69\xf1\x12\x8f\x43\x94\x6b\x5e\x92\x43\x50\x47\x9d\x82\x55\xb8\x46\xa0\x7a\x85\x5a\x27\xde\x71\x2b\x6f\xb2\x21\xfc\x1e\xe5\x90\x4c\xc7\x72\xd0\x05\x00\x5a\x79\x5d\xfd\xbd\xa8\x6a\xe2\x0d\x13\xee\x63\x22\xac\xa2\x4f\x79\xed\x63\xa2\xb2\x0f\xf0\x0f\xea\x32\xf9\x25\x7e\xf7\x4b\xe7\x59\xc3\x7f\xe8\x3d\xe2\x75\xd9\xe3\xbd\xae\x9b\xd4\x4f\xe4\x39\xbe\xe6\x5f\xaa\x4e\x7b\x11\xf2\x57\xf8\xe2\x65\xff\x7d\x53\x67\xd5\x12\x3b\xa0\x9f\x7d\xe0\x40\x7b\xbf\x01\x70\xf9\x80\x04\xf6\xbf\x12\x06\xa8\xeb\xfd\x35\x66\xa6\xa4\x64\x3a\xd3\xd2\x9c\xfc\x9f\x52\x0c\x40\x2f\x7c\x2f\xd8\xdf\xcf\x98\x04\xef\xd7\xd7\x7c\x2c\xbe\xfe\x1d\x9f\xc1\x23\x9f\x83\x2a\xc3\xfd\xfb\xd3\xbb\x5e\xaf\xfa\xdd\xc9\x63\x1d\x02\x93\xd3\xfb\xf5\x32\x7c\x58\x3b\xa5\xa4\x5a\x76\x5e\xa5\xca\x89\xa1\xb9\xfa\x18\x81\x54\x57\x56\xf6\x5e\xac\xfb\x52\x9c\x47\x5e\x8b\xc7\xe3\x75\xa4\x0c\x43\x1c\xbb\x9e\xe8\xf4\x0d\xb0\x1e\x23\x13\xfd\x45\x27\xa3\x48\xe3\x8d\xbd\x8e\x73\x00\x50\x7b\xe8\xc3\xc0\x00\xa2\x01\x20\x35\xca\xe9\x3b\x38\x8b\x38\x53\x56\x63\x9e\xb3\x86\xf2\xc2\xf9\x5c\x3b\x0d\x52\x3b\x9e\x65\xeb\x1d\x9c\x05\x2c\x90\x55\xc7\xe7\xad\x9f\xba\x3e\x3d\xdb\x16\xfd\xb9\x27\x26\xe9\x66\x48\xc0\x24\x5c\xf8\x48\x80\xe4\xf5\xa6\x71\x3b\xa7\x3c\x31\xc9\xda\xe1\x31\x09\x95\x91\x65\x80\x94\xb5\x89\x09\x70\xba\xa3\x25\x68\x2d\xdd\x0c\x42\x59\xcf\xe7\xf0\x72\x4b\x75\x5a\xf3\x16\xca\xcb\x3d\x19\x01\x07\x53\xa7\xc8\xe9\xd8\x0e\x77\x05\x40\xa7\xea\x03\x1c\xac\x8a\xa6\xd1\x8c\x99\x21\x60\x39\x75\x8a\xdc\xa4\xd3\x96\x78\xd7\x5a\xae\x8a\x28\xd1\x8c\x1b\x21\xc0\x4d\xea\x00\x6f\x3b\xfb\xea\x59\x62\xc5\x7e\x58\xcf\x5c\xf2\xfb\x5b\xaf\x55\xd1\xd9\x71\xbf\xd0\xd1\x42\xec\xa0\x5b\x38\xcf\x47\x2a\x57\x15\x2a\x96\xef\x50\xac\x2a\xce\xca\xa9\x6e\x11\x96\x14\x5f\xab\x78\xee\xf8\x06\xb7\x5f\x01\x48\x4e\x1f\xac\x1e\xbb\xd4\x3e\xc4\x34\x54\xae\xc8\x0e\xab\xab\x53\x65\x86\xb1\xfb\xe5\x63\x38\xd7\x2c\x0b\x84\x02\x13\xe8\x8b\xab\x55\xca\x7c\x06\x3f\x60\x9e\xc5\x63\x61\x86\xf8\x99\xbc\xcc\x7e\x09\x03\x06\x24\xf4\xcb\x7c\xee\x54\xcf\xbc\xd2\xc1\x95\x99\xb2\x3e\x21\x9c\x1a\x9f\x95\x7e\x47\x7f\x27\x5d\x94\x99\x92\xea\x74\xa6\xa7\xc3\x48\xd3\xd2\x43\xdd\x8a\xf7\xb7\x8d\x57\xd4\xdc\x3d\x34\x23\xd5\x99\x3c\x30\x1d\x50\x1d\xef\x8b\x78\x62\x34\xf0\x68\x96\xfa\x0d\x87\x06\x97\x84\x67\xa0\x80\xe7\x5b\x19\x90\xd0\x81\xb6\xf7\x7a\x55\xe6\xec\x51\xc3\x69\x4f\x56\xc0\x98\xdc\x6d\xd3\x66\x53\xf6\x2b\xa3\x26\xf0\x70\x00\xd1\xb1\x05\xf3\xcc\xea\x8d\x5d\xf7\x1c\x45\x85\x6a\xa6\x8e\x39\xdb\xad\x18\x0d\xa5\x01\x53\x8d\x0c\xd5\xb1\x5b\x51\xdf\x57\xef\xbe\x59\xe1\xed\x3d\xd8\x91\xfd\xee\x5e\x5f\xde\xff\x3d\x19\xb8\xb7\x7d\x2d\x04\xda\x6d\x0a\xda\xde\x11\xd7\x05\x04\xe8\x0d\x00\xb1\xc5\x90\x0b\xba\x80\xee\x00\xa8\x56\xd3\xb2\x2a\xa7\xbd\x15\x3a\x9f\xc4\xd5\x34\x15\x57\xd0\xbf\x8e\xf2\xa8\xff\x7b\x07\x00\xc4\x6a\xe6\x28\x20\x41\x04\xbb\xfa\xb2\x9a\xe5\x35\x53\xef\x20\xa6\xb9\xdf\xe7\xda\x60\x57\xcc\xbf\x5e\x54\xd7\x64\xc5\xf6\x93\x4c\xf5\xb0\xc3\xb2\x36\x78\x3b\x1c\xc1\x97\x57\x15\xcc\xb0\xb2\x25\xae\x9d\xf1\x1e\x76\x58\xde\x0e\x67\x87\xad\x7c\xd5\x5c\xd1\x0c\x2b\x1a\x22\x60\x12\x75\x8a\x2c\x10\x6d\x9b\x4e\x8c\x4b\x92\xea\xf0\x57\xeb\xa9\x0c\x0f\x3b\xa9\x13\xf7\x51\xae\x3e\x98\xd4\x79\x76\x42\x61\x2b\x6d\x7a\xb6\x52\x7e\x7e\xa6\x67\x2a\xf9\xf3\x30\xfd\xd7\x19\xc4\xdc\x4d\xba\x85\x5b\xc7\x69\x57\xff\x52\x28\x91\x3a\xc3\xb2\x49\xa1\x48\xda\x89\x9c\xb4\x78\xf0\x24\xf4\x57\x01\x4c\xa0\x9b\x6e\xa5\x38\xab\x59\xdd\x4b\x33\x31\x4d\x27\x87\xb3\xae\x8e\x3b\x37\xe2\x72\x44\xb3\x80\x09\xf4\x01\x89\x38\xe2\xdb\x7b\xf5\x37\x99\x71\xa5\x25\xe3\xa5\xee\xb7\x5a\x65\x5c\xa1\x8b\xb7\x60\xda\xe5\xe0\xee\x57\x59\xd9\x5d\x82\x1d\xeb\x0c\x3e\x8b\x86\x71\xd5\xc5\xf7\x2f\xa5\x81\xf5\x0e\xcf\xa6\x36\xb3\x80\x04\x8d\xc8\x44\xcd\x62\xd2\x40\x24\xe8\xc9\xd5\xce\x8b\x8c\xc2\x49\xc3\xf8\xfe\xb1\xab\xb9\x3b\x14\xd2\x86\xe3\x18\xb3\x6a\xf3\xd5\xe8\x6e\xb9\x02\x01\xfa\xfe\xc0\x92\x90\x90\x87\x5e\xdf\xb9\x76\xcd\xb6\xcd\xeb\x3f\x14\x56\x05\xc8\x44\xc5\xc2\x50\xd8\x07\x7d\x82\xfe\x87\x6e\xa0\x4b\x93\x0b\xce\xa1\xab\xc4\xa7\x33\x2e\x7c\xf2\xd9\x27\x1f\x7e\x44\x6c\x50\x06\x37\x07\x88\x43\x55\xd9\x51\x03\x47\xa3\x78\xc9\xe6\x1d\x08\xb9\x42\x11\xd4\x2c\xe8\x29\xbf\xee\x0f\xa0\x2a\x9e\x7a\x84\xee\xd5\x7b\x80\x5e\x5b\x9d\x55\xcb\x6a\x4a\x55\x9f\xaf\x20\x10\x2c\xba\x5b\x51\x7f\xab\xf5\x69\x6c\x4d\xfd\xaa\xdc\xe7\xb9\x5f\x15\xde\xfb\xce\x05\x41\xac\x8d\x94\xde\x32\x57\xd8\x16\xb1\xa8\xdc\x37\x0a\xa3\xa2\x78\xc9\x3c\x42\x66\x4b\x70\x9b\xcc\x51\x10\x04\xc2\x14\xef\xa3\x5b\xcd\x62\x4b\x17\x88\x69\xca\xb7\xc1\x39\x7b\xc1\xad\xe7\x0f\x60\x3f\x12\x29\xf9\x23\xb1\xcc\x1f\xef\x8c\xba\x4b\x65\xee\x38\x7f\x24\x2f\xe8\xc7\xb5\xb1\x4f\x6a\x83\x37\xf4\x62\x1b\x9c\x23\x22\xc4\x36\x04\x5f\xa4\x2a\xd4\xc7\xbd\xdb\x15\x8b\x63\x07\xbb\xe1\x97\xf1\xd5\x71\xa9\xd6\x3e\x46\x13\x65\xb5\x75\x87\x9c\xea\x27\x41\x59\x38\xea\xc3\xb0\x86\x88\x47\x1f\xa3\x1f\x9b\xea\xff\xf2\x5e\xf3\xf1\x23\x1e\x91\xa8\x68\xdc\x37\x3f\xbb\x4f\x13\x97\xd6\x6c\x5d\xb3\x1a\x90\xa0\x9d\xba\x4e\x36\xf2\xeb\x4d\x45\x0d\x42\x6d\x83\xd8\xae\x67\x00\x3d\x56\x94\xa2\xad\xf3\xda\x87\x96\x51\x6b\xd7\x31\x62\x62\x17\x9e\xf6\x0a\xc2\x7a\xea\x32\x71\x08\xd7\x68\x00\xe2\xf9\x5b\x3d\x1e\x35\xa1\xec\x84\x10\xaf\xc6\xe5\xcf\xe7\x04\x9e\xd5\x1f\x48\x3c\x05\x97\xe3\x1f\x1f\x68\xd8\xc4\x2f\x9e\xd7\x07\x80\xe0\x70\x53\x45\xc0\x0e\x9c\x01\xa0\x0e\x20\xac\xee\x9e\x00\x71\xa2\x79\x8a\xfb\x8d\x4e\xf3\xaa\x75\x59\xe0\x4f\x9d\x82\xa2\x40\xa3\x18\x4f\x79\x5e\x13\x08\xf5\x14\x68\x2e\xf6\xe6\x37\xc6\xdd\x78\xd7\x06\xa7\x8e\xd1\xf7\x17\xbd\xc6\x19\x10\xe6\x9c\xc7\xfe\x87\xdf\x1c\x35\x15\x80\x66\xeb\xc9\x72\x24\xe0\x31\x51\x4a\xa5\x18\x1b\xb2\xe3\x5c\x47\x0b\x33\x8e\x3e\x87\xd7\xf5\xb1\x92\x45\xd6\x2b\x65\xcd\x19\xe8\x76\xfd\xfa\xd5\xfc\x29\xbb\xaf\xa2\xdf\x62\xdf\x06\x79\xdf\xde\xcb\x68\x73\x86\x7d\x9b\x7e\x75\x6f\xde\xce\xfb\x53\x2f\x9b\xf5\x21\x4c\x2d\xee\xdb\x2e\x93\xda\xc7\x8d\x38\x27\xfd\x39\x2f\xa5\xa5\x84\xed\x93\x3f\x75\xf2\x30\x86\x81\x12\x06\xff\x02\x2f\x38\x16\x16\x78\xb9\x6c\x17\xb7\x5e\xbe\x41\x10\xa0\xb8\xa3\x25\xe8\x5b\xfa\x1c\x88\x05\xa9\x00\x38\x02\x8c\x08\x28\xf6\x33\xc6\x23\xe0\x7b\x7d\x08\x7f\xa0\x2e\x93\x21\x82\x9f\xe1\x3d\xfc\x0f\xdc\x01\xb2\x74\x4c\x0c\x20\xd8\x46\x9d\x82\xd5\xfc\xfd\x87\xd2\x7f\x6f\x13\x9d\xb5\xf2\x95\x49\xd8\x71\x11\xdd\x00\x49\x34\x03\x48\x00\x48\xa3\xc3\x98\x54\x8a\x6e\x30\x5d\x7f\xfd\x91\x6d\xaf\xc3\x8a\x6e\x80\xaf\xe9\x5a\xb6\x3d\xd2\x65\x77\x59\x5c\x16\x83\xc5\x60\x37\xda\x8c\x86\xaf\x9b\x9a\x9c\x7b\xf7\x3a\x9b\x9a\x9c\xd5\xa5\xd5\x14\x68\xda\xe3\xda\xbb\xd7\xb5\xa7\xc9\x55\xdd\xda\x44\x4f\xa8\x66\xbf\x7b\x09\xdd\x80\x07\xe9\x5a\x10\xc2\xb6\x6b\xb5\xbb\x2c\x06\xbb\xcb\x66\x4c\x84\x45\x35\xae\xab\x57\x5d\x35\xb7\xd1\x0d\xfa\xda\x32\xd7\x95\x2b\xce\x65\xad\x0b\x00\x80\x68\x34\xba\x01\x12\xb9\xcf\x43\x97\xc5\x60\x35\xda\x8c\x36\x8b\x01\x8d\xfe\xda\x55\x0b\x47\x8f\xbf\x5d\xeb\xa2\xf6\x5e\x71\x2d\x6b\x8d\xa5\xeb\x96\x39\x59\x59\xc7\xc1\x8b\x44\x3e\xb1\x88\xc5\xcd\x6e\xd6\xc6\xc1\x1b\xf0\xe2\x8e\x1d\x1c\x0f\x5e\x7f\x47\xd4\x51\xf9\xa4\x1d\x90\xc0\xf8\x06\x20\x29\x1a\x40\x90\xea\x30\x46\xc1\xac\xac\xb4\x3b\xf1\x87\xc9\x1b\x44\xdd\xa6\x4d\x42\x3b\xe4\x7e\xdc\x4e\xbf\xbc\xee\xf8\xc3\x6f\x40\xf8\x0c\x84\xa9\x70\x2a\x7c\x17\x9e\x87\x3f\xc3\x0e\xc8\x40\x90\x3a\x65\xca\x14\x65\x13\x93\x15\x58\x0c\x9d\x69\xc3\xf0\xbb\xb6\x41\xc0\x60\x14\x45\x4e\x63\x4c\x80\xc4\x5a\xc4\x9f\xf7\xc2\xe0\x4d\x30\x69\x13\x8a\x0a\x22\xfe\x87\xd8\x1f\x40\x74\xb4\xa3\x2c\xb2\xb8\xe3\x2c\xf7\x39\x56\xeb\xd9\xff\x51\xe4\xb8\xf6\xfd\xec\x8f\xb3\x66\x75\x0d\x87\xa9\x3b\x79\x1c\x16\xd3\xcd\xec\xa7\xa2\x33\x59\x3f\x60\xb0\x75\xef\x3a\x7d\x40\x6d\x7e\xfc\x09\xf2\xd2\x24\x18\xb6\x04\xfd\x4f\xf1\x39\x06\x80\xe8\x28\x97\xc3\xc2\x90\xdd\x87\xf7\x39\x16\x91\xf1\x18\x79\x1c\xf6\xfa\xb2\xeb\x69\xf4\x0f\xae\xbd\xc1\xe8\x36\x5c\x04\x7e\x92\x7d\x6e\xf0\xd0\xbe\xc7\x22\xee\xfc\x23\xba\x0d\xc9\xff\x58\x8e\xa0\x2b\x52\xbf\x25\x7c\xbf\x2e\x47\x57\x8b\x2d\x81\xe8\x1e\x7e\x22\x3e\xbf\x36\x79\x1e\xbd\xa3\x6b\x5b\x6b\x19\xec\x89\xfd\x6c\x77\xf2\x38\x71\x1a\x7f\x2e\x82\x47\x48\x18\x6c\xf1\xfc\x9f\xdd\x4d\xb3\x32\x6b\x86\xf6\x3d\x06\x2b\x62\x2a\x52\x6a\x87\xf6\x3d\x41\x5e\xba\x0b\xf6\x58\x88\xfe\xd7\xd2\xb5\x02\x9a\xa7\xa1\xff\xb5\x28\xda\x60\xf0\x8c\xe2\x50\x39\x32\x79\x29\x86\xd8\x8e\x45\xa4\x55\xff\xa7\x47\x7e\x17\xf6\x4f\xf2\x38\x0c\xfa\x57\xd7\x13\xe8\xfa\x0c\x98\x31\x85\xfd\x93\xfd\x7e\x0c\xba\x4d\x9c\xc5\x32\xb1\xdf\xcf\x54\x7c\x3f\x66\x48\xfc\xf1\xf0\x3b\xff\xf8\x9f\x98\xdc\x48\x4e\xca\xd6\x76\x56\xc8\x72\x98\x50\xce\x0b\xab\x96\xc1\xe5\xe8\x1a\x6d\x4b\x20\xe2\xf9\x3f\xbb\x87\x1d\xeb\x3b\xb4\x26\x73\x26\xbc\x2f\xe2\x44\xdf\xa1\xb5\xc9\x15\xf4\x8e\xae\x2d\xe8\x7f\x0b\xa1\x69\x22\xfb\x67\x19\x34\x61\xbe\x6a\x01\x20\x37\x31\x26\x10\xca\xce\x05\x9a\x74\x90\xf1\xe6\xf8\x68\x5b\x74\x2d\x2c\x4a\xfb\xc8\x01\xa7\xa2\x9d\x8e\x8f\xd2\xc8\xaf\x0f\xf6\x86\x3b\xd1\xd4\xde\x07\x63\xdb\x09\x12\xe1\xef\x2d\x05\x80\xdc\xc6\x98\x80\x99\xfb\x5e\x34\x2d\x7e\x99\x6f\x61\x29\x9c\x90\x94\x84\x9a\xe0\x84\xb4\xf3\xe9\x6c\x3b\x49\x49\xec\xff\xa7\x9f\x4f\x83\x65\xfb\x7b\xc3\xbe\xd0\x1c\xbb\xbf\x37\x7c\x0c\x3d\xd9\x7b\x7f\x2c\xfa\x27\xfa\xaa\xf7\xfe\x5e\xa8\x16\x2e\xe5\xec\x14\xfc\x89\x98\x41\xfe\x00\x42\xd9\x39\xc8\x84\x75\x21\x83\x41\xea\x39\x41\x71\x65\x0b\xf5\x6d\x0f\x2d\x98\xbf\x68\xf1\xdc\xf9\x8b\x88\x96\x47\x6b\x6a\x1e\x7d\xf4\xc9\x5a\xee\x3e\xae\xbe\xe3\x3a\x7d\x1c\xdc\x06\xa1\x38\xcf\x29\x21\xcf\xd4\xcb\x62\x0c\x63\x00\x63\xeb\xdb\x23\x9c\x0c\x26\x97\x4d\xec\x63\x0a\x8e\x06\x83\x1d\x8e\x24\x23\x70\xb0\x33\xc2\x92\x95\x76\xa7\x4b\xb1\x11\xd5\xdc\x93\xd6\x0f\x19\x94\x53\x50\x90\x93\x9d\x4f\x74\x5f\x36\x68\x68\x41\x76\xe6\x08\xc2\x92\x3f\x30\x67\xd8\xf0\x41\x19\x85\x0b\xf2\x47\x8c\xc8\x1f\x32\xaa\x28\x7f\xe5\xb0\x82\xa1\x23\xf3\x8b\x86\x15\x0c\x2b\x28\x28\xcc\x07\xa2\xad\xa3\x3e\x05\x34\xb6\x75\x66\xab\x31\x11\x5e\x41\x4b\x58\x0b\x57\xd2\xba\x00\x40\x54\xcc\xda\x36\xfc\xfb\x90\x83\x14\x36\x38\xa9\x69\x77\x42\x27\x6b\xe3\x50\x31\xbc\x32\x9e\x5a\x5e\xc2\x1a\x36\xdc\x56\x14\xba\x01\x7e\xa2\x6b\x58\xfd\x26\x8d\xd8\x0a\x1a\x7f\x82\x5f\x9d\x2c\x25\x3f\x85\x07\x51\x71\x5b\x2c\x75\x0d\x28\x3e\x17\x2a\xf4\x69\x35\xf3\x9f\x45\x0f\xc1\xd5\xdc\xe7\x4b\x50\x0b\xff\x0d\xe5\xe7\x9d\x56\xa3\xd5\x29\xb4\xbd\x1a\x3d\xc4\xb5\x5f\x0c\x4d\x25\x42\x0f\x06\x30\xa3\xa3\x25\x98\xa1\xcf\x82\x50\x60\x06\xdd\x41\x3c\xb8\x13\x0c\x52\x46\x48\xc6\x25\xe0\x32\x6e\xc6\x48\x5b\x1c\x13\xcd\x6e\x38\xd5\xbf\xc9\x74\xb2\xbf\xa2\x35\xbf\x30\x63\xf3\xfa\xfa\x9d\x2f\x3c\xb7\xf6\x85\x4d\x23\x8a\xb7\x6d\x2b\x1e\xb1\x88\x4c\x7a\xa1\xfd\x22\xbc\xd4\x50\x5f\xbf\x73\xdb\x26\xfc\xcf\x63\xff\xb0\xad\x78\x04\x91\xda\x50\xbf\x7e\xe7\x96\x86\x67\xb7\x6c\x1c\x31\x66\xdb\xb6\x31\x23\x28\xe2\xbb\xbf\xfd\xeb\xab\xbf\xfd\xf0\xf3\x5f\x77\xbf\x04\x47\xc3\xa2\xdd\x6d\x13\xe9\xe6\xd6\x22\x78\x98\xfd\xe7\xeb\x3f\xfc\x7c\xf5\xa5\x5d\x2f\x36\xc1\xc2\x17\x77\xb3\x7f\xff\xf6\xc7\x1b\x5f\xbd\xb4\x0b\x8e\x82\x85\x2f\x72\x73\x81\xdc\x03\x0b\xe9\x66\xec\x17\x1c\xa4\xad\xf6\x64\x62\x25\xdd\xec\xbe\x81\xe7\x5a\x2d\xb9\x87\x78\x07\xff\xce\xc0\xfd\x16\xf2\x9f\x80\xc5\x27\xfa\xe1\x8f\x11\x91\xf8\xa3\x80\x64\x3f\x4b\x65\xf2\x9f\x0d\x95\x3e\xad\xf8\x06\x2c\xe6\x5b\x67\xbf\x86\xbf\x0a\xc1\x38\x50\x45\x24\x91\xa7\xb0\x8d\x73\x42\x4b\x30\x34\x8c\x83\x13\x96\xa3\x6b\x30\x76\x39\x11\x1e\x03\xb7\x16\xa1\x46\xb4\x73\x14\x67\xe7\x4a\x40\x15\x91\xc8\x7d\xd6\x15\x0c\x5d\xd0\x0c\x4b\x60\x2c\xba\x56\x0d\x27\xa1\x3d\xef\xc0\xa9\xb0\xac\x08\xcd\x88\x41\x5c\x2e\x51\x7d\xc7\x75\xb2\x1c\xdf\xe5\x45\x80\x18\x76\xf5\x28\xd7\x75\x8c\x4e\xf5\xf7\xfa\x21\xb9\xb9\x43\x86\x0e\xca\xc9\x8f\xbe\xe2\x58\x04\xeb\xe4\x7f\x5b\x90\x3f\x62\x64\x5e\xde\xe8\x22\x7a\x65\xdb\xdf\xd1\xe7\xb2\xbf\x00\xd8\xd1\xca\x98\x28\x86\xd9\x8a\xd7\x0a\x4e\xab\x99\xa1\xc2\x18\xd3\xd3\x4f\x63\xbc\x68\x09\x00\xc4\x3a\x8e\x5b\x2b\x74\x40\xb4\x84\x5c\xb6\xb9\xbd\x86\x1d\x1b\x20\x60\x84\x75\xf4\x39\x10\xca\x47\x2e\x9c\xca\x4b\x0f\xeb\xd6\x97\x04\x51\xbd\xfb\x93\x0c\x60\xee\x4c\xeb\x6f\x86\x64\x84\x39\xd6\x4c\x44\xd1\xe6\x3e\xa1\xe1\x85\x11\xe6\x65\x13\x23\x22\x82\xed\xf1\x31\x90\x04\x31\x91\x31\x44\x14\x1d\x73\xb8\xe3\x9b\xbc\xc1\xa1\xe1\x85\xd6\x98\x65\x13\x4b\xac\xd3\xac\xc4\x34\xeb\x31\x2b\x11\x61\x8d\xb5\x8e\xb1\x92\x61\x56\x6b\xb0\xbd\x7f\x32\x24\x23\x92\x63\x93\x89\x28\x3a\x99\x6d\xc5\x9e\xbc\x6c\xa2\x9d\x8a\x27\x21\x09\xc8\x48\x92\x88\xa2\x49\xb6\x8d\xe0\xd0\xf0\x42\xd6\x4e\xb0\x56\x22\x09\x24\x4d\x2d\x9b\x32\x75\x4a\x37\xf1\xbf\x8c\x51\x59\xdd\x52\xcb\xa6\x4c\xa9\x54\xfc\x83\xf4\x17\x98\x95\x65\xb4\x38\x8c\x16\x87\xd2\xa8\x18\xfd\xf8\xef\xfa\xbc\xc1\x39\xf9\x05\xd9\x39\xf9\x43\x72\xb9\x3f\x85\xbf\x0b\x7f\x2e\xc8\x1f\x59\x38\x74\xe8\xc8\x22\x78\xb5\xa0\xb0\xb0\x20\x9f\xfd\x0f\xf6\x5f\xc4\xff\x18\x3a\xb2\x48\x39\xff\x23\xf0\x8a\xdd\x68\x73\xb2\xf3\xdf\xc1\xd9\x80\x93\x27\xe1\x57\x27\x4f\x0a\x73\x5a\xb2\x02\xec\x3a\x5b\xb2\x2f\xa1\x20\x26\x2f\x1c\x04\x01\x2a\x92\xea\x43\x91\x14\x1d\x42\xd2\xac\x65\x8a\x3c\x37\x25\x3d\x3d\xed\x4e\xc1\xf8\xd8\xad\x46\x2b\x36\x40\x55\x70\x10\x7a\x4f\xb2\x42\xc5\x9c\x7f\xe9\x88\x44\x37\xc0\x0d\xba\x06\xdb\x3e\x2b\x69\xb4\x19\x6f\xc0\x6f\x4e\x95\xd2\x35\xa8\xae\xf5\x2b\xba\x2f\x90\x7d\x66\x25\xab\xcb\x64\x0c\x64\x5b\xbd\x71\xe3\xc6\x29\xd6\x44\x1d\x46\x85\x18\x1a\xc1\x7f\xa6\x16\x30\x78\xc5\xe8\xb2\x18\xd8\xbe\x2d\x2e\x3b\xfe\xe4\xf8\xea\xea\x6a\x6a\xef\x95\x2b\xcd\xad\xed\x34\xd5\x5c\x59\x59\xa9\xe4\xa0\x8b\xc8\x81\x8c\x81\xee\x22\x01\x68\xab\x24\x3f\xb0\x13\x59\xc4\x2e\xfa\x34\x08\xc6\x9e\x2d\xd2\x9a\xde\xd5\x1c\x69\x15\x2d\x16\x3e\xd3\xb5\xc3\x9c\xed\x3b\xd1\xb1\x6d\xdb\x37\x8e\x99\x38\x69\xdc\xb8\x49\x13\xc7\x50\x04\x3c\xf5\x8f\xab\xc8\xd5\x72\x65\x57\xe3\xce\x97\x76\xef\xdc\xc9\xb5\x65\x22\x8a\x88\x23\xf4\x51\x10\x02\x8c\x78\x46\x3b\xd8\xee\xcd\x36\x67\xbc\xd5\x99\xe1\x62\x0c\x26\xb8\x61\xe3\xb2\x65\x9b\x3b\x00\x04\x4c\xd0\x24\x32\xfc\x01\x62\xa8\xfb\xdc\xd2\xf7\xde\x5b\xfa\xee\x03\x33\xa2\x56\x03\x08\x72\x08\x17\x9e\x33\xf8\xe5\xdb\xde\x50\x04\x60\x48\xb0\x47\x5b\xcd\x56\x83\xa4\x37\x39\x03\x56\x67\x4e\x9e\x37\xf7\xfe\xcc\x51\xb1\xbd\xe2\xac\xf0\xdf\xa8\x36\x6a\x48\x66\xdd\x81\x3f\xbd\x5c\xb4\x8a\x98\xb7\x32\x2e\x61\xec\xc4\x31\x77\x1b\x83\xba\x19\xe1\xde\x07\xbf\xe9\xb2\x61\xe9\xba\x6d\xb1\x2c\xbe\x44\x22\x8b\x68\xa2\x4f\xf3\xaf\x30\x46\x5a\xd3\x2d\x66\xdc\x3c\x1f\xb8\x21\x37\xd5\xb8\xdf\x44\x78\xa4\x28\xcd\x35\x7a\xf5\x86\xd0\xa0\x9e\x0b\xee\x5e\xba\xf1\xa5\xb5\x5b\x5e\x5d\x33\xa7\xa4\x78\xda\xdd\x77\x8d\x79\x90\x3c\x49\x50\x11\x4b\xa2\x37\xbd\x98\x94\x5d\x5f\xbd\x76\xcf\xe7\x95\x93\x16\x4d\x2e\x2b\x9e\x70\x37\x80\x20\x8b\x28\x22\x36\xf1\x6b\x3c\xa7\xd5\x0c\x6d\x30\x8b\x98\x82\x5e\x7c\x0e\x4e\xa6\xb3\x97\xce\x68\xbf\x4d\xfc\x9b\xb3\x9b\x0e\x22\x8b\x78\x9e\x3e\x0d\xcc\x20\x4e\xa8\x32\x2b\x14\x99\x35\x9b\x0c\x6a\x40\xa9\x30\x1c\x46\x9b\x2c\xb9\x90\x03\xe7\x28\x1a\x3f\x62\xd0\xf6\xa5\x8f\x3f\xb7\xe1\xb5\x97\x57\x6e\xdc\xb1\x6a\xec\xdd\xf7\x8c\xbd\x77\x4c\x8f\x82\xe1\xbd\xd6\x0d\x1a\x3d\x6a\x48\xfe\x48\x32\x75\x58\x55\xf2\x1d\x53\x86\xcf\x5e\xf6\x70\xf9\x13\xa3\x8b\xb6\x56\xae\xaa\xa9\xca\x2e\x2c\xcc\x1e\x54\xdc\x23\xa4\xcf\x5d\x70\xe9\xa4\x2c\x4b\xc1\x80\xcc\xec\x6c\x6e\xec\x6c\x44\x16\xd1\x48\x9f\x01\x66\xd9\x69\x67\x24\x63\x8b\xb3\x3b\xbb\x3a\xfa\x44\xdb\xd4\xd4\xd8\xf6\xad\xdc\xfc\xda\x5f\xbf\x28\x49\xbb\x63\x0a\x8c\x32\x87\x8e\x58\x5b\xf3\xdc\xaa\x71\xe3\xc7\xcf\x9d\x79\x4f\xf1\x64\x6a\xeb\x8a\x3d\xe7\x0e\xa3\x5f\x3a\x22\x96\x9a\x61\xee\xcc\xfa\xa7\x8b\x27\x97\x66\x4d\x9b\x37\x0d\xdb\xf1\x79\x64\x2f\xe2\x0c\x7d\x1a\x44\xe1\x53\x73\x8b\x23\xd3\xd1\x47\x16\x31\x33\x6f\x56\x78\x97\x91\xcf\x42\x62\xd9\xe8\xe2\x05\x93\xc8\x5e\xc4\x0b\x13\x66\xb6\xa2\x12\xb8\xf3\xee\x61\x33\x1f\x43\x7b\x58\x9c\x93\x3a\xee\x26\x5a\x88\xf9\xa0\x1b\xb0\xb1\x76\x3d\xde\xc5\xab\x88\x3d\x93\x8b\xbd\xb1\xe3\xcd\xa7\x8b\x8f\xb6\x34\x84\xc3\x49\x70\xf9\x82\x91\x43\x5d\x0f\x65\xa6\xad\x5d\xb3\xa1\xee\x89\xa8\x94\xca\x7b\x97\xae\xdc\x9b\xef\x9c\x36\x6f\xf2\x92\x05\x83\x7e\x0a\xa3\x62\x4b\xf3\x13\x2d\x8b\x0a\x97\x3d\xe3\x6e\x2d\xcd\x48\x79\xf4\x81\xcc\xf4\x39\x65\x0e\x8a\xce\xe7\x78\x29\xef\xb8\x9b\x8c\x21\x1e\x04\xd1\xa0\x87\xe0\x47\x7a\x41\x2b\x77\x42\x8e\x8f\x6a\xa2\xad\x29\xd0\x16\xc7\x94\x1f\xdb\xbd\xe5\x75\xf7\x7f\x83\x2a\x67\x0f\x5b\x5a\xb8\xe8\xb9\xe6\x8f\xf7\xc1\x7b\xa9\x31\x63\x8b\x27\x7f\xf5\xe6\xd5\x77\xb7\x4d\x78\x70\x51\x9f\xd8\x35\x8e\x4f\x60\xf4\xf8\x99\xf7\x89\xed\x96\x10\x0f\xe2\x35\x9b\xc2\x3f\x71\x8b\x02\x2c\x54\xf9\xa9\x03\x7b\xcf\x9c\x3e\xb0\xe7\x6c\xd3\xfd\xe5\xe7\xee\xaf\x98\x39\xeb\x6f\x47\x3e\xfb\xa2\xf9\xe8\xe7\x17\x8f\xfc\xf1\x59\x18\xb9\x6c\xed\x4a\x00\x81\xbd\x63\x1a\x69\x23\xa6\xb3\x7e\xd7\x12\x0c\x1d\x31\xec\xca\xc3\x16\x0a\xed\x30\x16\xfd\xfc\xe7\xe6\xe6\xc3\xe8\x06\x8c\x7d\xeb\xbd\x53\x3b\xe0\x0a\xb8\x14\xb5\x42\x06\xd5\xa2\x25\xd0\x8c\xfe\xc9\x62\x98\xde\x71\x37\x69\x22\x1e\x04\x51\xa0\x1b\x00\x2e\x27\x16\xc4\xe0\x94\x41\x61\xc5\x74\x4d\x27\x82\x98\x85\xb3\x1f\x5a\xff\xe0\xd6\x43\xe7\x4f\x34\x6e\x79\x7d\x2f\x75\xcf\xa8\x86\xde\xaf\x95\x56\x3e\x94\xb3\x2a\xf3\x93\xc3\x87\xaf\x1c\x5d\x32\x61\xda\x61\x76\x6c\x8b\x00\xa0\x86\xd3\x67\xb9\xf3\xe5\x28\x47\xba\xc5\x80\x47\xd5\xd4\x35\x5b\x1e\x28\x64\x35\xda\xe2\x88\xa2\xef\xcf\x6c\x7f\x3c\x7f\xc1\xac\x47\x9f\x59\xfd\x74\x2f\xa2\x3b\x5a\x07\x4b\xd1\x5e\x58\xe9\xfe\xde\x7e\xf5\x6b\xf2\xe4\xcf\xb0\x7b\x5e\xcd\xc0\xf3\x07\x0f\xbd\x09\x77\xad\x40\xd7\x57\xa0\x23\x2b\xe1\x79\x48\xb0\x73\x66\x46\xc7\x4a\xaa\x9c\x89\x02\x71\xa0\x1f\x8e\x91\xcf\x88\x1a\x0c\x1d\x06\x97\x23\xdd\xe2\x72\x18\xba\x5a\x0c\x09\x76\x92\x8b\xc7\x35\xd8\x5c\x09\x76\x83\x2d\x3a\x21\xda\x64\x89\x0e\x87\xd1\x5d\x2d\xd1\x09\xb6\x38\xc3\x8c\x5f\xae\xd9\x97\xdb\x2c\xdd\x0b\x53\xe2\x97\x27\x0e\x1f\x32\x22\x3b\xfe\x74\xed\x81\xb1\x9b\x2b\xe2\x97\xdb\x27\x8e\x48\x5d\x3e\xe8\x6f\x6f\x4c\xda\xf9\x48\xcd\xfb\x05\x13\xce\x26\x26\x25\xdb\x89\x8b\xed\xf0\xae\x8c\x23\x7b\x89\xa0\x03\x1f\x58\x62\xeb\x7b\x76\x69\x4f\xce\x7a\xce\x1a\x73\xe8\xcf\x61\xb1\x7f\x87\xf1\x2f\xc3\xc7\xce\x2d\x27\x7b\x65\xfd\xe4\x6e\xbc\x23\x92\xfc\x91\x61\x00\x04\x55\x1d\x2d\xd4\x68\xfa\x2c\xff\xae\xa7\x35\x9d\xab\x16\x4d\x18\x4d\x51\x16\xa3\xc3\x92\x29\x92\x62\xcc\x85\x18\x66\x1f\x50\x05\xf3\x60\x8f\xcb\x7b\x8a\xb2\x37\x4d\x3f\xfe\xfd\xea\xc7\xd7\x87\x4c\x5d\x9f\x9d\x6b\xca\x4f\x9a\xf2\x78\xd1\xda\xa9\xa5\x9b\xa7\xa3\x6f\xd0\x67\xc4\x55\x38\x19\xae\x2f\xdd\x10\x9b\x86\xde\x46\xff\xfa\x2b\xfa\xcc\x41\x5c\xab\xac\x0e\x7b\xde\xb8\x7e\x2e\x5a\x03\xbb\xf5\x79\xce\xd6\x0d\xd6\xe2\xf9\x35\x19\x00\xca\x46\x37\x73\x16\xd8\x21\x50\x6e\xc6\xb4\x1b\x27\xef\x27\xbb\xbb\x37\x13\x79\xee\x63\x30\x13\x7d\x78\x10\x86\xd4\x52\xf6\x46\x37\xda\xf9\x6d\x2d\xba\x05\x43\xf0\xf7\x0b\x00\xa0\x8a\xe8\x33\xac\x15\x70\x38\x33\x8d\x36\xa7\xc3\xc9\xfe\xb0\xc6\x92\x05\xde\x0b\xf2\xad\x99\x18\x83\xd5\x5c\xf0\xd1\xfb\xef\xbf\xff\x3e\xdc\xf1\xfe\xee\xbc\x4d\xf5\xff\x82\x2f\xa0\xfb\xe1\x0b\xe8\xbe\xc1\x7f\x20\xa3\x1b\x92\x60\xe4\x8a\x1d\xb5\x2b\xe0\xc9\x92\x35\xc3\xd0\xa1\xda\x1d\x2b\x2a\xeb\x92\x77\x01\x08\xf6\x77\xc4\x32\x17\xe9\xf1\xc0\x2e\x8b\x99\xb3\x44\x3b\x48\x7e\xfa\xe2\xd5\x30\xfb\x27\xb4\xf1\x76\xce\x6c\xdc\x5f\x17\x13\x92\xfa\xa7\x8a\x96\xbb\xdf\x5e\x57\x33\xae\xec\xc8\x5b\x07\xbf\xde\xfc\xec\xeb\xe8\xc7\x75\x70\xf7\xbc\x87\x1a\xd6\x50\x45\x9b\x4a\x26\x6d\x81\x75\xe8\x07\xeb\xb1\xcf\xdd\x4e\xe2\x24\xa4\x0e\xbe\xe9\x6e\x84\x8b\xdc\x7b\xc9\x55\xdd\x9f\x78\xe2\xc8\x05\xf7\x69\x40\x03\x13\x00\x54\x35\xdd\x0c\x7a\xb1\x3b\x24\xd0\x1f\xc7\x8a\x72\xb2\x19\x1d\xbd\x61\xb4\xc3\xc8\x39\x2b\xec\x2f\x49\xd6\x67\x46\x77\xb5\x38\xec\xd1\x0e\xbb\xcd\x6a\x71\x38\x49\xf6\x2f\xa6\x1d\x3b\x76\x5c\x0c\xce\x78\xea\xdf\x8d\x3b\x76\xec\xd8\x71\xe9\xc4\xcd\x1d\xcf\x06\x93\xa5\x93\x82\x8e\xe5\xd4\x40\x7b\x4e\xed\xf8\x11\xa6\xa0\x2e\x44\x78\x4d\x53\x0d\x6c\x8d\x78\x0a\x6d\x81\xad\x88\xa9\x69\xaa\x71\xdf\x24\xc2\xd9\x1f\x62\x4f\xfd\xcc\xdb\xee\xab\x4d\x4d\x4d\xe8\xe2\xbb\x7d\xbe\x66\x75\x79\x6b\x47\x0b\xfd\x13\xdd\x0c\x82\x41\x14\x48\x64\xf9\xf0\xbc\x54\x72\x0e\x86\x0e\x0c\xca\x24\xd5\x19\x77\x1a\xb7\xc2\x28\x82\x40\x3f\xa0\x5f\x06\x3b\x4f\xbc\xf1\xd2\x6b\xe3\x89\xc9\x3b\x06\xcf\xb9\x76\xcd\x39\x38\x7e\x6c\xd4\xd0\x07\x1f\x5e\x46\x37\xa3\x71\x7f\xfb\x27\x77\xc3\xb4\x76\x95\x7b\xdf\xb8\x91\x27\x2f\xae\x44\xa5\xa3\xc7\x85\x33\xb5\x7d\xd6\xad\x84\xc7\x39\xff\xb3\xb7\xa3\x85\x99\x40\x37\x83\x2e\xa0\x2b\x18\x84\xfb\xc7\x33\xdf\x00\x6d\x50\x81\x81\x35\x03\xce\x8c\x04\x7b\x0a\x21\xaf\x80\xce\x4e\x6c\x4b\x6f\x02\x9b\x8a\xbd\x30\xe9\x9b\x2f\xe7\x3f\x00\xad\x27\x3b\xc0\x91\x15\x2b\xaa\x1e\x7b\xa2\x86\x68\x70\x36\x64\x1d\x1a\xb1\x60\x6e\x59\xca\xc1\x0d\xf7\x3c\x91\x9d\x9f\x35\x33\x6b\x44\xf1\xc8\xca\x8a\xb2\x94\x37\x5e\x69\xa2\x9b\xcf\x7f\xb2\xee\x74\xba\xbb\x92\x98\xec\xde\x45\xdc\x5e\xfd\xcc\xba\xc7\xdb\xa2\xf6\xc4\xa7\x35\xe6\x8c\xcb\x1b\x34\x69\xfe\xc8\x27\xb7\xdf\x11\xb7\xb2\x4f\xdf\x91\x83\xb2\xc7\xe5\x65\x4f\x9a\x57\xb4\x65\x0f\x30\xb0\x63\x48\xb3\xfb\x95\x58\x60\x03\x89\x20\x19\xa4\x83\x4c\x90\x8d\xc7\xd1\x6e\x73\x3a\x48\x47\x34\xff\x3f\xd2\x61\xb6\x19\x1c\x66\x1b\xc9\xfd\x2f\xda\xe2\x70\x91\x5d\x2d\xb9\x70\x30\x74\xd8\x6d\x2e\x47\x82\x9d\xe1\xff\x29\xd3\x65\xda\xda\xab\x7a\xce\x84\x5d\x25\x57\xca\x8e\xde\x77\x65\xf4\xce\xf1\x33\x97\xc6\x6c\xda\x57\xfa\xd6\xf4\x5f\x26\x37\x4f\x9e\x15\xb3\x30\x76\x59\x1f\x03\x8c\x0a\xdf\x7b\xa2\xf7\x8a\xae\x13\x62\x43\xba\x7c\x6b\x5d\xdc\xed\xe1\x38\x86\xee\xc9\x8f\x33\x62\x84\x1f\xd9\x48\xc3\x24\x76\x8c\xff\xfc\x70\xef\x3f\x4f\xa8\x69\xaa\x69\x6c\xa8\x41\xef\xb3\xff\x70\xa5\xec\xfe\x2f\xf8\x5a\xe0\xe8\x14\x75\x99\x31\xe1\xbd\xc9\x1d\x7c\x46\x81\xc5\x91\x02\x73\xa0\xd5\x69\x75\x72\xe3\x6d\xe3\xee\x0a\xd8\x75\x8f\x2c\xb9\x23\x8e\xa9\xfc\xe7\xa5\xaf\x17\x77\x21\x43\xd0\x68\x78\xe8\xd0\xd6\xad\xf5\x31\x41\x55\xd7\xbe\x68\x19\x42\x6e\x6c\x7f\x60\xe9\xb3\x1b\x5f\xdc\xd4\xb0\x7b\xf5\x46\x22\x16\x46\xc0\xfe\x8d\xe1\xf3\xfb\x2d\x5b\xd1\xdc\xbc\xa2\x2d\xb1\xfe\x25\x98\x80\x32\x6b\xc8\x09\xa7\x2e\xbd\xf6\xa1\xed\xef\xef\x7c\xc1\xed\xa9\x52\xf1\x7d\xfa\x19\xee\xbd\x56\x87\xdd\xe9\xb2\x39\x1d\x51\x80\x33\x51\x7d\x48\x76\xc5\x65\xb6\x58\xcd\xd8\xd9\x61\xcd\x03\x64\xea\x06\x82\xd8\xd0\xd8\x0f\xf6\xfb\xe1\x5c\xe3\xe8\xc6\xe5\xe8\x83\x51\xf0\x17\x37\x22\x08\xf8\x1e\x1a\x6d\x3b\xdd\xd4\xb0\x79\xfd\xde\x16\x74\x35\x05\xde\xae\xed\xdf\xbf\xb8\x16\x06\xc1\x5e\x53\xeb\xc7\xa3\x25\xb5\x03\x72\xef\xa8\xdd\xff\x6e\xfe\x8e\x21\x30\x14\x42\xdc\x77\x2c\x00\x54\x3d\xdd\xcc\x9d\xa7\xe0\xd9\x07\x1d\x90\xed\x8d\x55\x3e\x76\xb1\x1b\x7b\x70\xbf\x93\x00\x67\xdc\x88\x81\xcf\xa3\xa3\xf0\xe8\xc7\xa8\x34\xb1\x6a\x3f\xb1\x6f\x05\x51\xe3\x5e\x46\xd4\xb8\x57\x84\xac\x70\x8f\x27\xf6\x55\xbb\x3f\x27\xf6\xb1\x7e\x10\x00\x6a\x01\xdd\xcc\x55\x87\x67\xad\x9d\xcb\x42\x9b\x5d\x16\xda\x68\x33\x1a\xec\xf1\x4e\x83\x3d\xde\x68\xa7\x0a\x51\xd6\x8d\x91\xe8\x34\xfb\x73\xf8\x46\x11\x1c\xc8\xfe\xd0\xa6\xc6\x46\xf4\xda\xee\xb9\x97\xce\xef\x99\x77\x09\x0d\x87\x25\xbb\xe6\x5d\xfa\xe8\xc5\xb9\x97\xe0\x61\x3c\x56\x69\xc8\x64\x58\x42\x9f\x05\x3d\x40\x32\x7e\x37\x90\xb5\x57\x54\x94\xd9\x44\x50\x49\x90\xd5\xb4\xf4\xbe\x51\xce\x0c\xc0\xae\x40\x60\x34\xbf\x8c\x14\x93\x41\xc8\x68\x69\xc1\x64\x48\x1b\xfd\xb7\x85\x1f\xc2\x8c\x3d\x1f\xa1\x55\x3f\xfd\xd8\x7e\xe0\x4a\xf4\x09\x68\xdd\x8c\x7e\xfd\xb6\xf4\xfd\x22\x72\x4b\x53\xfc\x99\xcd\x9b\x5f\x9a\xf9\xd6\x63\xce\x99\x3d\x82\x22\xcd\x85\x9b\xfa\x2d\xb8\xbf\xa6\x68\xf8\x5d\x15\x3d\xe8\x25\xf1\xc9\xcf\xa3\x6b\xef\xb4\xa1\x47\x3f\xa7\x76\xb4\xb5\xef\x87\x79\x9f\x7c\x01\x3a\x12\xe2\x7e\x4d\x26\xe3\x5f\x3f\xba\x65\xf5\x82\x23\x73\x13\x7b\x96\x3d\x8e\xde\x25\xde\x9d\xb0\x7e\x61\xe1\xb8\xf2\x87\xb8\xb3\x32\x64\xa2\xac\xf4\x39\x10\x07\x92\x00\x70\xc0\x18\x98\x40\x08\x2b\x4b\xc2\xd0\x03\xe2\x59\xcb\xae\xed\x58\x7c\xa1\x84\x01\x9a\xa2\x2c\x99\xce\x0c\x5b\x5c\x77\x98\xb0\x6b\x7f\xc9\xdd\x9b\x9e\x5a\xbe\xe1\xe1\xb9\x35\xf7\xbf\xf8\x6c\xe1\xb8\x71\x85\x39\x25\x4d\x3f\xee\x7d\x1c\x7e\x92\x9d\xb2\xac\x72\x11\x11\x8b\x2e\xc2\xe4\xdd\x30\xeb\x91\x5d\x07\x5f\x58\xfd\x24\x7a\x7d\x1f\xba\x80\x8e\x57\x6c\xd8\x6b\x7e\xde\x3a\xf1\x9e\xdd\xf0\x19\x34\x0b\x46\xb7\x52\x4b\xc7\x21\xf7\xd4\x5f\xbe\xdc\x07\x28\xd1\xf6\xf6\x00\x7d\x80\x1d\x6b\x3c\x6f\x79\xad\x7d\xa2\x1d\x66\x9b\xc5\xc4\x4e\x56\x86\x4a\x82\x46\x9b\xd1\xc2\x9a\x39\xab\xd3\x9a\xe9\xcc\xb0\x5b\x9d\xd6\x84\x24\x68\x7a\xfd\xf5\xd7\xe1\x60\xf8\xcc\xdd\xcf\xd7\x52\x41\x2b\xf7\xb8\x3a\xc0\xbb\x0b\xf7\xee\x2d\x5f\xb2\xbd\x3f\x2a\x85\x9f\x06\x31\x28\x19\x1e\x28\xba\xb4\x8e\x04\x0b\x9a\xe7\x43\x1b\xba\x3a\xbf\xc8\x3e\x6c\x41\xdd\x7a\x64\x23\xc1\xaa\x21\x45\x0b\x72\xec\x89\x89\xf3\x57\xe3\xb1\x5c\xd6\x31\x99\xce\x66\xa2\x80\x19\xf4\xc4\xab\xdc\x48\x10\xef\x74\x98\xf1\xa2\xc1\x68\x35\x32\x06\xb3\xcd\xd9\x97\x9d\x8d\x16\x23\x43\xc0\x4c\x97\xd1\xba\x0c\x8e\x83\xc9\x35\x5f\x9f\x19\xde\xbc\x0f\x1e\xfd\xf8\xa7\x1a\xf4\x31\x7a\xfd\xd8\xf5\xaf\x2e\xfc\x93\xc8\x5f\xfb\x30\x6a\x27\xae\xc0\xc1\x70\x45\xdc\x98\x11\xd4\xb8\x1d\x63\x68\xf7\x15\xb7\x63\x28\xb3\x7e\x7d\x14\x7c\x1a\xde\x85\x5a\xd1\xa5\x18\xea\xd9\x3e\xe8\x5c\xfb\xdb\x64\x1f\x78\x50\xc8\x29\xa1\xae\x60\x1d\x8d\x61\x77\x20\x69\xd1\x36\xa7\x83\x95\x35\xda\xc1\x4e\x73\x8b\xc3\x6c\x8b\xe6\x72\x41\xec\x56\x97\xc3\x9e\x60\x0f\x87\xfb\x9f\x3f\x33\x08\xb5\xc1\x8c\xf7\x8e\xbf\x07\x07\xa0\xdb\x39\x67\xb7\xee\x3f\xb1\xd7\xdd\xf6\xd2\x25\xb8\x3b\x1b\x9d\x4f\xbe\x44\x8c\x8c\x8b\x2c\x81\xdf\xd5\x34\xd5\x10\x36\xf7\xd5\x9a\xa6\x1a\x14\x03\xbf\x43\x31\x44\x79\x53\x8d\xe1\x7c\xed\x98\xff\x72\xf3\xdc\xd4\xd1\x42\x95\xd0\x67\xf1\x7a\xc9\xe9\xc8\x85\x3c\xbf\xec\x72\x88\x5d\x36\x53\x66\x6e\x00\x22\x58\xdf\xce\x98\xa5\x8c\xa6\xbe\xce\x0c\x97\xe9\x64\xd6\x96\x47\xdd\x3f\x13\xad\x99\xf5\x4f\xd4\x37\x0d\x7c\xf5\xc4\xa7\x90\xe8\xfe\xc0\xf1\x49\x07\x1c\x10\xb9\x83\x06\xef\xde\x75\xe4\x9b\x61\x9f\x2d\xfd\x2f\xfa\xa7\x85\x08\xaf\x49\x1d\x9d\x5c\x93\x35\x75\xe6\x83\xc5\xdb\xc6\x7d\xf8\xa7\x09\xf9\x35\xa5\x83\xa3\x6b\xb2\xca\xe6\x3f\x7e\xdf\x6b\x71\xc9\x5f\xbd\x3b\x7c\x08\x20\xd8\x31\xa0\xce\x33\x51\xa0\x2b\xe8\xa5\x1a\x01\xd6\xbb\xf1\x43\x60\xc2\x43\xb0\x0c\xe6\xc3\xde\x35\x17\xb6\x14\x6d\x79\x66\xe5\x2b\x1b\x1a\x6b\xd0\x5f\xd0\xfb\x27\x2e\x9e\x39\xf1\x15\x71\x15\xe6\xc1\x55\xbd\xfe\x30\x22\x64\xf4\xd6\xe1\x41\x6d\xb3\x68\xe7\x8e\x4c\x72\xfd\xfa\x68\xb8\x02\xde\xd5\x81\x3e\x8b\xa1\x9e\xed\x8d\xce\x02\x08\x1a\x01\x20\x6f\xd2\xcd\x38\xea\xd2\xc9\xeb\x55\x0a\x4c\x82\xac\x7d\xe8\xca\xda\x1a\x82\x86\xb6\xc6\xe4\xfd\xbb\xbb\xa0\x2a\xb8\xaa\xeb\x2b\x5b\x92\xc9\x12\xb4\x6c\x7a\x14\x8c\x40\xff\xed\x85\x76\xc3\x15\x9f\x12\xbb\x26\xcd\x58\x54\xb3\x70\x76\x4d\x4d\xf1\xaa\x1a\xf4\x75\x9a\x7b\x29\xcb\x67\x62\x47\x0b\x55\x4a\x37\xe3\x97\x0f\x9c\x2e\xa7\xc1\xe9\x32\x3a\x8c\xf1\x66\xda\x1c\x6f\xa6\x8d\xe9\x51\x46\x87\x89\xa0\x6c\x71\x76\x63\xe2\x95\x2b\x57\x0e\xc0\x3d\x68\x12\xfb\xf3\x5f\xf7\x81\x17\xd1\xa5\x8f\x1f\x2a\x20\x4a\x6a\x8b\x1a\x8b\x6a\x8b\xe0\x83\xe8\x5c\x5d\x6d\x5d\xe3\xfa\x27\xeb\xdd\x4d\x30\x01\xf6\xfb\x17\x3a\xb0\xcb\x44\x6c\xe5\xce\x8f\xe2\xc8\x69\xf0\xaf\xcc\xaf\x20\x1c\x00\xe8\xc2\x47\xcd\x16\x3a\xda\x10\x0a\xed\xd1\x28\xae\x17\xac\x4d\xfa\x20\x11\x3e\xd3\x13\x3d\xfd\x9f\x03\xfb\xb7\x35\xdf\xa0\xe3\xde\x5e\x00\x57\xa2\xc5\x0b\xde\xee\x8d\x8e\x4e\x83\xb3\xd0\xf3\xd3\x60\x01\x77\xce\x54\xdb\x71\x8b\x09\xa3\x8f\xe3\xd8\xbe\xbe\xe2\x9b\x5b\x78\x2d\x67\x36\x89\xa9\x6b\x3a\x07\x96\x19\xb6\xb8\xda\x23\xaf\xcc\xbe\xd7\x76\xd7\x98\x4b\x9f\xcf\x9e\x10\x3b\x27\x6b\xf7\x5b\x9f\x92\x49\xdb\xda\x2f\xc2\xc6\x97\x37\xac\xda\xdf\xf4\xdc\xda\x97\xd7\x4c\x28\xbd\x6b\xe2\xbe\xfd\xd4\x8c\xa6\x37\xe2\x1f\x88\xfd\xf1\x7b\xdb\x03\x11\xdd\x0e\xb6\xe7\xe2\x53\xc8\xe2\x17\xdf\x78\x6b\xfb\xf6\xb7\xfe\xfc\x42\xd5\xe2\xc5\x55\x3f\x60\xbb\xb4\xa0\xa3\x85\x6c\xa4\xcf\x82\x9e\x38\xe6\xdc\x99\xe9\x32\x8a\x56\x89\xcb\xa5\xe3\xc2\x8e\x72\x20\xe3\xca\x34\x66\xb0\xab\x8c\x05\xc5\x0b\x37\xaf\x7d\x64\xf5\xc7\x6f\x94\x94\xee\x8d\x9a\x13\xf4\xfc\xa6\xcd\x8d\x25\xb7\x5b\x97\x0e\xc9\x85\x68\x89\x39\x01\xfe\xf8\xec\xf6\xc6\x55\x47\xd0\x85\x62\xd4\x32\xfb\x91\xcf\x5f\x7e\xe3\xcd\x57\xbe\xef\x7d\xb1\x06\xda\x8f\xde\x3d\x9b\x95\xff\x24\x00\x86\xd3\x74\x33\x7f\x12\x98\x84\x57\x9d\xd0\x91\xe0\x34\x3a\x8c\x36\x68\x8b\x32\x1b\x15\x67\x81\x62\x42\x2d\x67\xb4\x4f\x7e\x4c\x3c\x1f\x14\xde\x78\xc6\x5d\x16\x14\x49\xb6\x37\x6e\x78\xe6\xa5\x17\x37\xae\x7e\x31\x91\x88\x40\x63\x4b\x26\x4d\x2a\x2e\x9e\x34\x71\x2c\xdd\xdc\x36\xfa\xbf\xab\x49\x47\x6b\x11\x75\x18\x7d\x33\xaf\xfd\x22\xb1\x60\x57\xf3\x5b\x3b\x77\xbd\x75\x14\xa5\xaf\x59\x43\x2c\xa8\x5c\xb4\xa8\x72\xe1\xbc\x79\x78\x2c\x66\x74\xb4\x30\x05\xf4\x59\x10\x01\x62\x41\x7f\xae\x1e\x59\x54\x5f\xc1\x9d\xd8\xe2\xfa\x12\x2e\x53\x14\xc5\x79\x14\xa2\xaf\x2d\x8e\x22\x20\xbf\x22\x4b\x82\xdd\xb9\x25\x58\x12\x9c\xf1\x01\x2c\xfb\x90\xfd\x39\x81\x1a\x3f\x39\x8f\x1a\x4f\xce\xdb\x07\x93\xf6\xed\x83\xfd\x5f\xd9\x87\x2e\xee\xdb\x87\xbe\x78\x05\x2e\x81\xa9\x4d\x5b\x5e\x7e\xaa\xe9\xd9\xbd\x77\x4d\x5c\x4b\x5c\xc1\x5f\x40\x8d\x1f\x9e\x42\x7b\x3e\x39\x0f\x27\xbd\xcf\x7e\x46\xf6\x1d\xf7\x06\xb2\x7a\xcd\xea\x27\x5e\x44\xef\xc2\x63\x8d\x63\x47\x72\x67\x01\xdf\xd1\x2b\xf0\x3d\x4b\x37\xce\x9b\xb2\xeb\x61\x68\x64\x37\x97\x46\x9b\xd1\x85\x57\x55\x16\xa3\x8d\xb0\x7e\xba\x1c\xd6\x1f\x3f\x76\xfa\x48\x0d\x13\x74\x7e\xee\xa9\x20\x86\x2e\x9c\x3f\xdf\xfd\x02\x71\xbf\xfb\x05\xe2\x53\xf7\x45\x22\xc9\x9d\x0a\x1b\x57\xb2\xff\x51\x8d\xc6\x03\x08\x8a\x01\xa0\x6f\xe1\xfb\x64\x9f\xb7\xc9\x5e\x6e\x8f\xfd\x79\x87\x89\x00\xb3\x3a\xae\x52\xab\xa8\x42\xfe\xb5\x95\x8c\x28\x76\x90\xa3\xcc\x56\x23\xb7\x73\xb7\x70\xe9\x75\x2e\xab\x11\xef\x79\x67\x3d\xf3\xcb\xc6\x86\xff\xac\x68\x3f\x95\xb6\x67\x5c\xcd\x9b\x63\x0b\xa7\x5f\x6e\x78\xe1\xdf\xb5\x3f\x12\xe3\xd3\x5f\x9c\xf0\xca\xa3\x44\xd4\x9f\x40\xc7\xea\xb5\xc8\xbd\x1b\x6d\x75\x0e\x9f\xb3\x3c\x71\xcb\x63\xf5\x90\xfe\x0f\x34\x3b\xf3\x17\xe1\x71\x0d\xe9\xb8\x4d\x6f\xc2\x7c\x85\x81\x48\xfc\x7a\x18\x74\x40\x9b\xdd\x66\x88\x76\xa4\x42\x83\x11\x3a\x60\x3c\xbf\x86\x4e\x81\x76\xe5\x33\x42\xdc\x22\x9a\x73\xc7\x09\x21\xd0\xb8\x1c\x46\xae\x29\xbc\x3d\x72\xee\xc1\x61\xe6\x28\x32\x6e\x53\xfb\x55\xd8\x6c\x7f\xc2\xb1\x25\x66\xf0\xe0\x39\x93\x6b\x16\x67\x2f\x49\xb2\x25\xcc\x49\xce\xca\x1c\x30\xb9\x72\xd2\x8b\x2b\x73\x1f\x22\x6e\x11\xc7\xdc\x79\x1f\x7c\x00\x1d\x27\x87\x0e\x6f\xb3\xb0\x93\x2e\x76\x99\xa9\x77\x71\x9c\xd5\x66\xee\x3b\xb5\xe4\xde\xf2\x18\xd3\x3c\x63\xb7\xd8\xc4\xa4\xe4\x9e\x09\xf7\xdd\x73\xef\x1c\x33\xf6\x07\x39\x00\x10\xe7\xa9\x22\x10\x8c\xc7\x01\xdf\x7d\x38\x8c\x39\xf0\x2b\x34\x14\xbe\xdd\x5c\x0f\xa7\xd6\xc3\x53\x6d\xcd\x80\x04\x29\x1d\x37\x98\x6e\x74\x33\x08\x01\xe1\xd8\x77\xc4\xb3\xc3\x9f\xe1\x0a\x87\xb8\x48\x70\x3c\xbb\x7a\x70\x66\x24\x41\xa7\x30\x5f\x0c\x76\x7e\x05\xc4\x9f\x5d\xa5\xc0\x90\x4d\xeb\x83\x62\x53\x9e\x98\x81\x0f\xbf\x89\x01\x6b\xff\x78\xee\xda\xa2\x45\xb3\xa7\xfe\x21\xbf\x7c\x69\x51\xd1\xb3\x63\x9f\x7e\xa1\xe1\xe0\xe1\xbd\x0d\x54\xeb\xd1\xf6\x0d\x84\x73\x68\x55\xcf\x84\x29\x6d\x15\xac\x10\xfd\x97\x0f\xdf\xba\xa6\xb2\x78\x48\x76\x7e\x71\x99\x2b\x65\xc9\x9c\xe7\xb2\xee\xd8\x5d\xbd\x16\xaf\xc7\x3a\x6e\x30\xc9\xf4\x19\xd0\x0d\xf4\xe4\xea\xd5\xb8\x84\x03\x31\xfe\x08\xc8\x14\xce\xaa\x53\xb0\x5f\x00\xd3\x5a\xaa\x47\x8c\xca\xcd\x9d\xe1\x2c\xac\xdd\xfa\xe4\xc6\xee\x19\x77\xdd\x84\xcf\xa2\x5d\x1c\xd8\x08\x1d\xb0\x44\xd1\xfc\xbf\x2f\xad\x1c\x36\x24\xff\xce\x7e\x65\x95\x35\x0b\x52\xc6\x8c\x9d\xfc\xb7\x6a\x77\xb3\x37\xd4\x00\xd0\x60\x58\x47\x0b\x43\xf1\x5c\xf6\x05\x69\xec\x7e\x4b\xcd\x67\x40\xc7\x7f\xc3\x04\x6e\xc7\x72\x70\xed\xbe\x8e\x03\x3d\x49\xfe\xd6\xff\xf3\x41\x1a\xd8\x3a\x5a\x98\x18\x7c\x2e\x10\x0f\xb2\x41\x21\xb8\x8b\xe5\xde\x17\xbf\x81\x8b\x65\xd3\x61\x7d\x35\x96\x12\xde\xf6\x25\x25\x51\xa5\x39\x06\xee\xd3\x81\x09\x4c\x83\x11\x1d\x2d\x8c\x05\x9f\x45\xc7\x81\x01\x60\x18\x28\xf1\x79\x26\x1d\xb8\xb0\x23\xf4\x4f\xb1\x5f\xe1\xe4\x6d\xf5\x29\xaf\xf6\x69\xb7\x7b\x6f\xa0\xf2\xce\xea\x68\x61\x22\xf0\x99\x75\x08\xe8\x03\x92\xf1\xbb\xe3\xf8\xec\x3a\x98\x08\x54\xac\x59\xfc\x61\x37\xda\xca\xa9\x66\xa1\x2f\x21\x84\x53\xf1\xd6\x53\x81\xa0\x86\x60\x78\xc7\x4d\xf2\x10\x35\x01\x74\x05\x20\x3a\x53\x7c\x4e\x4b\xd8\xd5\xb0\xfa\x38\x7c\xc3\x1b\x08\xda\xd1\xcf\xee\xe9\x2b\x0b\x9a\x16\xbe\x72\xf8\x9d\x97\x1e\xdc\x44\x45\x16\xa2\x0b\xa8\x0d\xdd\x44\x97\x2d\x3d\xea\xd3\xbe\xfc\xe0\xf8\xd7\xf8\xac\x17\xc2\x46\x30\x83\x29\x23\x0a\x40\x17\x3e\xae\x88\x31\xe0\x85\xa2\x2d\x01\x36\xae\xab\x2e\xcc\xcd\x22\xaf\xb6\xdb\xb2\x72\x0b\xab\x61\x7e\xdf\xc2\x4d\xcb\x0b\x4a\x0b\x96\xe3\xb8\x18\x18\xd9\x71\x92\xb8\x41\x55\x8b\xdf\xeb\x6a\x31\x27\xd8\x8d\x36\x23\x03\x23\x37\x15\xf2\x1f\x25\x13\x0b\xab\xd7\xad\xab\x2e\xcc\x19\xd8\x6e\x23\xaf\x0e\xf4\xec\xcf\x9a\x60\x67\xbf\xc8\x18\x6c\x99\x2e\xd8\x48\x5e\x65\x3b\x5a\x87\xbb\x85\x89\x6c\x4f\x5c\x43\xea\xfe\xe2\x9d\x5d\x2d\x46\x07\xb7\x76\xb6\x25\xc0\x48\x0e\x55\x61\xdf\xc2\x4f\x65\x78\xd7\xad\x53\xca\x67\x91\xe4\x93\x75\x2a\x97\x94\x40\x52\xf7\x6e\x42\x26\xb3\x08\x44\x2d\xbb\x85\xc7\xc2\x18\x24\x06\x64\xa8\xe4\xdf\xe3\xd1\x11\x68\x60\x8e\xc0\x09\xd7\x07\x87\x93\x80\x91\x1d\x85\xb8\x4d\x12\xc4\x00\x40\xb3\x9b\x79\xdd\x96\xe1\x37\xa8\x8f\x47\xeb\xe5\x25\x70\xa5\x7e\x07\x04\x98\xde\xd1\x42\x65\xd1\xa7\x41\x0f\x60\x17\xd7\x06\x16\x17\x61\x8d\x63\x0c\x4e\xd6\x80\x45\x19\x23\xd9\xf5\x18\xa7\xe0\x51\x2e\xd6\x4f\x87\xc3\xe9\x2b\x7f\x6c\x98\xb8\x26\x85\xa2\xd0\xcd\x81\x6b\xb2\x73\x9e\x1f\xfa\xd9\x57\x2f\xa1\x96\xd7\x0e\xfc\xf9\xcf\xf7\x4d\x5c\xfb\x17\x9b\x69\x59\xc9\xfd\x3b\xee\x83\x8b\xf7\xc2\x8c\xed\x63\x87\x8d\x86\xb5\xfd\xfb\xed\xeb\x65\x45\xff\x42\x37\xd0\xaf\xc8\xf5\x8f\xb3\xef\x3c\xf4\x38\x1c\xf8\x43\xe9\xdc\x27\x6e\x71\xf7\x0a\x89\x00\x50\xcb\xe8\x66\x40\x83\x30\xd6\x0b\x43\x07\x34\xc7\x5b\x61\x82\x9d\x31\x24\xc2\x73\x87\xe1\xf9\xf6\x4a\xe2\xbd\x0e\x30\x34\xd6\x91\x54\x49\x0f\x6b\x7d\x6b\x41\x23\xd1\x7a\x66\xe5\x07\x4f\x60\xff\x7d\x0a\x99\xe8\x78\x3e\xe6\x07\x5f\x4b\x5a\x8d\xa7\xa8\x69\x87\xdd\x91\xc8\x64\x68\xbc\x5d\xc6\xa0\x5f\x09\xfc\xb9\x42\x64\xa2\xae\xe1\x7b\x70\x10\x1d\x8c\x77\x3d\xc1\xec\x16\xaf\x90\x58\xe8\xde\x46\x15\xb6\x1f\x21\xb2\xdc\xaf\x92\xdb\xdb\x66\xa3\x5a\x72\x03\x99\xb4\xb0\xd1\x1d\xdc\xbe\xb9\x11\x40\x30\x8b\x58\x49\x25\x91\x31\x80\x04\x71\x79\x66\x1c\x5f\x95\x0a\xa7\xc2\x6a\xf8\x2a\x1f\x5b\x65\x80\x20\x55\x11\x59\x35\x8b\x3c\x45\xac\x5c\xbf\xde\xf7\xbd\x37\x04\xf5\x44\x21\xac\x23\xcb\x30\x26\x65\xa8\x49\xee\x50\x1c\x6a\xf2\xf9\x90\xa2\x51\x79\x79\xa3\x8a\x00\x04\xf1\x1d\x37\xa9\x93\xcc\x36\x10\x84\x6d\x11\x5e\x54\xc1\x78\x18\xff\x3d\x01\xd6\xbb\x0f\xd4\xa2\x7f\x12\xed\xeb\xdc\x65\xf4\x1b\xbf\x8e\x27\x43\xf0\xfe\x7a\x31\xac\xa3\x93\xa9\x70\x1c\x31\x9a\x24\xec\x74\xc4\x3e\xec\x92\xcd\xc2\x43\xca\xd0\x32\x73\xbe\xf8\xe5\x27\x0f\x2d\x79\xec\xcd\x27\x77\x37\x2d\x7f\xeb\xb1\x65\xfb\x9f\xde\xbd\xa2\xac\x64\xf0\xdc\x8c\xb4\x07\x86\xfd\x61\x2a\x11\x93\x36\xb7\x60\xf4\xb4\xa9\x63\x06\x3f\x40\x7c\xbe\xf2\xe0\xa5\xcf\xf7\xaf\x79\xea\xf0\xe5\x0b\x07\x56\x8d\x9d\x79\xcf\x7d\x65\x93\xe6\xdc\x55\x36\xa9\xbc\xa4\xb8\x62\x22\x9e\x0f\x0d\x00\x30\xd3\xa8\xd3\x80\x06\x80\x5d\x55\x59\xcd\xb0\xa1\x8c\xaa\xa0\x4e\xb7\x3d\x57\x86\x7f\x6f\xe9\x40\xd4\x5e\x2a\x08\x44\x83\xde\x79\x61\xd1\x20\x24\x14\x84\x9a\xcc\xa1\x20\x02\xdf\x35\xa7\x73\x97\xe9\x0e\xa3\x23\xed\x4e\xda\x98\x81\xe3\x84\xa1\xec\x7a\x0c\x5a\x16\x7e\x5a\x53\xf3\xf9\xe2\x59\xa7\x76\x34\x1e\x23\x08\xb0\xf1\x46\x6d\xed\xcd\x7a\x04\x08\xe2\x9d\xbf\x5d\x3b\x89\x58\x7e\x43\x90\x89\x04\x8c\x09\x98\x00\x88\x66\xdd\xb3\x51\xb8\xe6\x34\x1b\x31\x09\x21\x39\xb9\x07\x60\xd1\x5d\x29\xd9\x03\xf6\x36\xed\x1e\x93\x83\x8e\x76\xfb\x81\x8e\x81\x73\xa3\x36\x76\xfb\xa1\xf5\xbb\x43\x6f\x99\x59\xdd\x9c\x06\x6b\xa8\x54\xca\x06\x2c\xdc\x29\x39\x9e\x1e\xb2\x1b\x2f\x3b\x66\x8f\xd4\xf9\xf7\x69\x73\x37\x14\x3c\x7c\xd7\xc8\xa9\xa9\xce\x65\x59\x73\x9e\x1b\xba\x60\xc2\xa8\xc9\x77\x66\x56\x67\x55\x6c\x1a\x3c\x77\xfa\x90\xfb\x9c\x83\x1e\x73\x94\x37\x0c\x7b\x78\xcc\xc4\x7b\xec\x99\xcb\x61\xcd\xb6\xf9\xbd\x6d\xb1\x31\xf9\x59\xdb\xe7\xf5\x8a\x8f\xed\x96\x07\xa7\xbc\x30\xaf\x7b\x62\x4c\xcf\xe1\x8e\x6d\xf3\xfb\x58\xe3\x4d\x43\xb0\xce\xcc\x02\x8d\x54\x22\x4d\x81\x68\x4e\x0f\xac\x4e\x6b\xb4\x85\x35\xcd\x24\xfb\x63\x77\xcd\x82\xe3\x97\x20\x07\x61\x5c\x51\x3b\x17\x46\xa1\x7d\xcb\xe0\xa7\xee\x7f\xd6\xd4\xcc\x81\x47\xd7\x43\xa6\x0e\xc6\xe6\x7c\x5b\x87\x5a\xd7\xa3\xbf\x67\xe3\x33\xf7\x19\xe0\x17\xaa\x90\x2a\xe1\x63\x55\xf2\xf2\x12\x82\x00\x15\x4a\x1a\x28\x43\x58\x17\xaa\x84\x86\x34\x98\x0a\x21\x0c\xa2\x21\x19\x11\x9c\x1a\x3c\x38\x78\x41\xf0\xd7\xc1\x3f\x07\x33\xc1\x20\x75\x8a\xc5\x91\x3a\xc5\x21\xe8\xbd\xd1\xe1\x30\x3a\x1c\x69\x77\xba\x70\xd6\x25\xf7\x33\x83\xfc\x5b\x7b\x4f\xee\xe7\x97\xfa\x7a\x38\x63\xc3\x06\xf6\x87\xdd\x8b\x00\x40\x25\x51\xd7\x01\x09\x42\xf0\x8a\xdb\x0c\x9d\xd0\x1c\x0c\xd9\x69\xd3\x9e\x4d\x9e\x6a\x6f\x27\xa9\xba\x3a\x62\xeb\x2c\x78\x6d\x3b\xaa\x47\x47\xb7\x03\xad\xef\xc4\x3b\x83\xd9\xaf\x71\xdf\xa1\xda\xdb\xc9\x53\x75\x75\xbf\x6c\x87\xf9\x70\xc1\x76\x14\x3b\x0b\xdb\x94\x6d\x00\x50\x2e\x6a\x39\xa0\x40\x30\xab\x5d\x34\xa0\x18\xc0\x84\x84\xd2\x20\x88\x50\x6b\x97\xc3\x18\x0c\x8d\xf1\x56\x63\x30\xdc\x06\x3f\x82\xe7\xda\xdf\x24\x7e\x45\x35\xe8\x49\x62\x29\xc1\xb8\x5b\xdd\xb5\xe3\x08\x06\xee\x45\xa5\x00\x82\x0a\xc8\x50\xc9\x64\x0c\xab\xcf\xd1\x0e\x76\xab\x50\x51\x47\xa6\xb7\xe7\x40\x06\xd6\xb0\xf3\x9d\xb0\x21\x13\xf9\x39\xb3\x17\x98\x01\x80\xb2\xc8\x0e\x7b\x82\x9d\xf5\xbf\x8c\xd9\x48\xd8\x9a\x96\x0d\x1e\xed\x88\x8f\x0d\x33\x26\x58\x8d\x71\xa1\x0c\x32\x31\x5f\xbd\x77\x2b\x2f\x35\xd1\x11\x12\x9c\x68\xb7\xdb\xe6\xdc\xae\x05\x10\x52\xc8\x44\x1c\x62\xf6\xb2\x7a\x8b\x77\xe4\x96\xae\x16\x31\x8c\x1e\x3f\xae\x4a\x39\x6c\xb6\xee\x21\xbd\x63\x8d\x3d\xbb\xd7\x35\xd6\x66\x95\xa0\xe5\x76\x67\x24\x95\x18\xef\xa8\x36\x2c\xfb\xd5\x76\xf2\x56\x2e\x17\x03\x71\x8b\xd8\x43\x1f\x22\x5d\x38\x9e\x95\xa4\x01\x17\x5e\x66\x84\x58\x68\xd2\x69\x35\x87\xd0\xef\x10\x7b\x70\xc2\x11\x84\x97\x90\x89\x28\x37\x9c\x61\x6d\x15\x34\x3a\x8c\xf0\x52\x1d\x32\x05\xbf\x71\x6b\x14\x2b\xd7\x1a\x64\xc2\xed\xd0\xec\xef\x58\x17\x44\xac\x21\xed\xee\x07\x90\x89\xb6\xd5\xb5\xcd\xe7\xfb\x42\x26\x32\x16\x7f\xa6\x5b\x5e\x30\x20\x29\x8a\x31\xf0\xe1\x6c\x2c\xd3\x46\x47\x3a\xee\xd2\x68\x33\x86\x90\x89\xeb\x89\x3d\x75\xad\x57\x29\xcc\xd9\x1a\x16\xa3\xe1\x0c\xd7\x36\x6b\x23\x88\x35\xeb\x89\x8d\xc4\x1e\xda\xd6\x36\xbf\x8e\x93\x81\x8c\xc5\xbf\x67\xdb\xa5\x09\x82\x31\x00\x48\x82\x54\x2e\x30\x57\x6c\xd7\x61\x0c\x21\x9e\x63\xdb\xa5\xd6\xb7\x5e\x15\x31\x1b\xce\x88\x11\xad\x18\xf5\x7a\x62\x23\x0b\x3b\xf8\x8d\xb6\xf9\x1c\x70\x1e\x37\xfe\x5c\xcf\xbc\x50\x40\x13\x0c\x13\x14\x0c\x20\xc3\xf6\x20\x74\x21\xf5\x61\xc3\xbd\x70\xdd\xdc\x1a\x45\xad\xe7\xbe\x8f\xb9\x31\xb0\x5a\x46\x06\x03\x9a\x6d\x80\xe1\x44\x4f\x17\x64\x17\x08\xc7\xf2\xd3\xef\xb8\x1f\x60\x9b\xa8\x6b\x9b\xcf\x52\x20\x8c\x13\xc6\xd0\x3b\x2f\xcc\x80\xa5\x0c\x0a\x06\x34\x27\xa6\x43\xd9\x06\x96\x05\xcb\xba\x11\xc3\x60\x59\x02\x02\x0e\xc3\x19\x10\x0a\xfa\xe5\x19\x0d\x5d\x00\x1d\x1c\x4c\x84\x84\x84\x75\x09\x02\x34\x0c\xe1\xa4\x71\xa4\xf3\xf2\xa8\x5a\xb3\xf2\x72\xb1\xe4\xac\x17\x1a\xe5\xc0\x11\x1d\xb7\xe0\x4d\xfa\x10\xd9\x82\x6d\x44\x66\x5e\x2f\xd2\x60\x08\x06\x14\x15\x44\x4d\xa5\x21\x49\x37\x01\xf8\x01\x80\x0c\x38\x00\x61\x04\x84\x38\xca\xd8\x31\x75\x4a\x65\xea\xd4\x29\x9c\x9a\x19\x45\x55\x83\x9c\xba\xb5\xe6\xd3\xef\xc0\x9b\x75\x75\xb0\x9c\xf5\x90\xec\xfa\xe6\x32\x3b\x67\xb0\xde\xf1\x23\xc5\xfe\x0f\x5e\xae\xfb\x92\xd7\x3f\xa5\x0e\xb6\xb0\xfb\x74\x28\xde\xe2\x72\x7a\xc8\x0d\x2a\xfd\xe5\xfa\x4b\x75\xed\x71\xac\x2e\x5f\xe6\xc7\x44\xf8\x2c\x0e\x56\x82\x97\xc9\x2b\x28\xb6\xee\x4b\x5e\x6b\x59\x21\xf9\xfe\x71\xbb\x34\xeb\x85\xb9\x4f\x73\x9c\xb0\x9f\x6f\x6f\xfe\x92\x58\x88\x62\x71\xe3\xad\x47\xa8\x05\x5c\xfb\xbc\xae\xb3\x58\x06\xe6\xc5\x52\x00\x18\x88\xa0\xa0\x90\x50\xd6\x5a\x92\x30\xa8\x89\x82\x1f\x50\x90\xa1\x0e\xd0\x30\x82\xb5\xa1\x02\x27\x98\x14\x5e\x9f\x78\x56\x9c\x5c\xa4\x65\x08\xf1\x9c\x7b\x0e\x99\xb8\x1e\xde\xac\xbb\xb4\xbe\xb5\x1f\xf9\x57\xa1\x8f\xcf\xb1\x0c\x71\x79\xe1\xc0\x10\x44\x52\x41\x54\x48\x28\x15\xc4\xf0\x9a\xe5\x10\x0d\x98\x38\xb3\x6c\x78\x76\x5d\xad\xfb\xb2\x8e\x9f\x5f\xe2\x18\xe2\xb6\x78\x19\xb9\xcf\x42\xbe\xe7\x87\xea\x50\x2f\xf2\x6a\x1d\xbc\x59\xd7\x56\x47\xfe\x15\x96\xaf\x6f\xed\x47\x0f\xc7\x7c\xb3\xe3\x6e\x38\xc3\x71\xe8\xe0\x19\xe7\x67\x10\xb1\x11\xde\xa4\x2f\xb5\xdb\xd6\x5f\xe2\x6c\xc7\x65\x5e\x7f\x83\xa5\x11\xb4\x9a\xf1\x18\xc2\x6b\xdc\x4c\x16\xf4\x94\x80\x97\xf9\x76\x79\xbe\xf1\x27\x85\xcf\x93\x45\xee\xb5\x75\xf0\x1a\xdb\x78\xeb\x91\x3a\x58\x4e\x2d\x68\xb7\xe1\x39\x06\x6f\xe2\x39\x1a\x0c\x06\xe4\xf5\xa6\x00\x08\x66\x08\x22\x24\x54\x4d\x34\xeb\xac\x0c\x20\x15\x3b\x26\x4c\xb9\x16\xdb\x0e\x8e\x6d\xe2\x39\x8e\x6d\xf2\x6a\x6b\xa2\x68\x2b\xb1\x1e\x06\x73\x0c\x71\x52\x84\xc0\xeb\x1c\x9b\x1c\x97\xac\x65\xe1\xe7\x04\xfe\xac\xc8\xa7\x03\xf3\xe9\x30\x86\x90\xa3\xeb\xda\x6d\xf0\x3a\xcb\x27\x3d\xbc\x35\x11\x96\xaf\x27\xaf\xb6\xd5\xc9\xed\x51\xa8\x9c\x4f\xd1\x26\x09\x76\x09\x73\xda\x1e\x27\xe8\x25\x9e\x17\xa1\x72\x56\xad\x46\x9e\x57\x56\x2b\xb9\xf9\x21\xd8\x32\x52\xf6\x9d\x60\x10\x21\x7c\x8b\xfd\x0e\x29\x8e\x08\xab\xce\x75\xec\xd7\xf1\x97\xb1\x46\xd3\xc3\x45\x9e\x79\x5b\x18\x0a\x72\xf3\xac\x1c\xcf\xac\x09\xe1\x14\x5b\x45\x77\x08\x4b\xb5\x7c\xbe\x73\x64\xab\xd9\xb6\x89\x7c\x0b\x84\xdf\x1a\x45\xfe\x55\xd0\x49\x6c\xf3\x44\x0e\xf1\xb9\x2a\xe6\xbc\x0e\xce\xa9\x13\x8d\x6c\xdb\x7c\xce\x06\x90\xe2\x77\x68\x1c\xcd\x2a\xd3\x64\x87\x31\x1a\x8f\x2c\xab\xcd\x78\xc8\x24\x7d\x66\xf9\x6f\x3d\xc2\xb5\xc0\xcf\x05\x3c\xdf\xd9\x7e\xf3\xf3\x6c\xa1\x24\xd9\x25\x08\xb0\x56\x3b\xac\x0b\xc5\x09\xca\x34\x05\xc1\x0f\x82\x20\x13\x74\x20\x18\x46\x04\xc3\x60\xc5\x0c\x4e\x17\xad\xb1\x64\xdb\x78\x14\x66\xce\xb2\xbb\xe7\x70\x26\xae\x3d\x0e\xf7\x2f\xf7\x11\xd8\x36\x93\x5d\x40\x70\x08\xcd\x84\x30\x61\x5d\x98\x10\x2a\x88\x9b\xce\x8a\xf9\x2c\x6f\xd7\xc6\x79\x0c\xd6\x70\xd5\x09\x3e\x83\xf7\x1b\xa4\x28\x0b\xcd\x8d\xb7\xc8\x87\x99\xb3\x63\x1c\x1f\xf4\x3b\xee\xb5\xec\xa8\x4b\x94\x48\xa6\x4c\xb0\xef\xbc\x9e\xe5\xe5\xc5\x19\x42\x43\xbb\x80\xa0\x20\x9a\x20\xc2\xba\x08\xd6\x9d\xe6\xcd\x7b\xd0\xd4\x60\x18\x4c\x8a\x33\x4c\x9a\x62\xe9\x2a\x4b\xcf\xf9\x28\xd6\xda\x63\xaf\xc2\x1b\x7c\x76\x07\xae\xf4\x77\x98\x8f\xd0\x2e\x80\x26\x82\x19\x82\x09\xeb\x12\x4c\x03\x68\x20\xd9\x35\x83\xc3\xe1\xc9\x87\x38\x07\xb8\x59\xc9\x9a\x16\x7e\x5e\x72\xb6\x85\x94\xc9\x22\xf0\xc1\xa3\x71\x48\x88\xf8\xef\x8a\x98\xda\xea\x38\xed\x97\xfb\xd0\x68\x50\x9a\x97\x1c\x1a\x11\x61\x66\xe7\x40\x17\xa3\x91\x21\xa2\xa2\x4c\xe6\x48\xd0\x05\xeb\x47\x18\x25\x4c\x85\x60\x7e\x2e\x44\x09\x73\x01\x53\xe2\x60\xf5\x44\xf4\xb5\x0e\xce\x02\x89\xfc\xf0\xf3\x42\x8a\x43\x12\xe6\x87\x60\x06\x84\x79\xc2\x9b\x02\xd6\x1b\x28\xb1\x01\x39\x17\xa2\x8e\xf0\x72\x09\x8a\x22\x12\x23\x29\x0c\x25\xb6\x41\xe3\x5a\x83\x16\xf5\x0c\x92\x2c\x85\x34\x93\x04\x7b\xa1\x9e\x50\x0a\xcb\xc1\xee\x4b\x00\xf1\x13\xbd\x97\x5b\x3f\x76\x87\x56\x23\xbd\x97\xf8\x89\xba\xd2\x16\xcf\xfd\x0e\x99\xd8\xbf\x4b\xbf\x43\x26\xea\x2f\x6d\x09\xd2\xef\xe4\xdf\x13\x96\x9d\xdc\xef\x88\x8b\xd2\xef\x88\x8b\xff\xc7\xde\xdf\xc0\x45\x75\x5d\xfb\xe3\xf0\x77\x9d\xb3\xcf\x19\x44\x25\x03\x0e\x22\x31\x8a\xe3\x88\x84\x20\x22\x8e\xc3\x60\x10\x31\xc4\x10\x62\x08\x1a\x4a\x09\x31\x84\x10\x24\x88\x24\x96\x10\x62\x09\x21\x74\xe2\xb5\x76\xaa\xc6\x1a\x42\x62\x8d\xb1\x96\x7a\xa9\xb5\x5e\x4b\xa8\xb5\x84\x1a\x6b\xb5\x86\x12\x6b\x88\xf1\x26\x94\x1a\x6b\x6d\x6a\x52\x93\x86\xe6\x7a\xbd\x36\xd7\x8c\x33\x67\x9e\xcf\xde\xe7\x0c\x0e\x6f\x6a\xfa\x6b\x9f\xe7\xf9\xfd\x3f\xff\xd1\xc5\x9e\x39\x67\xed\xbd\xd7\x5e\x7b\xed\xb5\xd7\x5e\xfb\xed\xca\x3b\xfe\x3d\x10\x8f\xc2\xf9\xbb\xfe\xb7\xb7\xa0\x5c\xab\x55\x76\x9b\x62\x8d\x71\xcd\x0d\x18\x27\x66\x99\x63\x60\x43\x1c\x12\x90\x04\x3b\x9c\x48\x43\x06\x6e\xc7\x9d\xb8\x1b\x8b\xf1\x15\xdc\x87\x07\xf0\x10\x96\x61\x39\x1e\x45\x15\x6a\x50\x8b\x7a\xb8\xb0\x06\x6e\x6c\xc0\x26\x34\xe1\xbb\x78\x05\xdf\xc7\xbf\xe3\x47\x40\x94\x3d\xd2\x16\xee\xb0\x47\xca\x83\x60\x1c\x0f\x87\x79\x37\xee\xff\x47\xf8\xe5\x2b\xae\x7c\x46\xfa\x5e\x11\xf4\x59\x51\x7e\xe5\x33\xd2\xf7\x8a\x65\xb4\x66\xd9\x32\x5a\xfb\xf0\xc3\xf4\xcd\x92\x12\x5a\x5d\x5a\x4a\x6b\x4a\x4a\xbe\x70\x14\x15\x69\xa7\x4b\x64\x56\x5c\x4c\x6b\x0c\x70\x95\x96\x7e\xb1\xe5\xff\xeb\xd8\xc8\x07\xfe\x85\x75\xff\x1f\x78\x15\x3f\xc3\x6b\x78\x1d\xbf\xc2\x11\x74\xe1\x18\x8e\xe3\x5d\xf4\xe2\x14\xce\xe0\x2c\xce\xe1\x53\xfc\x17\xfe\x07\xff\x8b\xcb\xf0\x93\x4c\x26\x1a\x4d\x37\xd0\x38\x8a\xa2\x89\x14\x43\x36\x8a\xa3\x04\x4a\x22\x3b\x39\x29\x8d\x32\xe8\x76\xba\x93\xee\xa6\xc5\x40\xe4\x08\xf5\x1a\x3e\x42\xbd\x86\xff\xbf\xf8\x57\xc5\x0f\x16\xdd\x20\xa9\xff\x12\x4f\x2b\x86\xfd\xfc\x83\x89\x05\x3d\x55\xff\xff\xa5\x99\xfc\xdf\x8a\x0d\xdc\x2e\xfa\x8b\x1e\x53\x2c\xee\xc2\x3d\xb8\x17\x5f\xc5\xfd\x78\x10\x0f\xe3\x11\xac\xc0\x4a\x54\x63\x15\xea\xd0\x80\xd5\x58\x8b\x75\xd8\x88\x46\xbc\x84\x97\xf1\x3d\xfc\x00\x3f\xc4\x8f\xf1\x13\xfc\x14\x3f\xc7\x2f\xf0\x4b\x1c\x46\x27\x8e\xa2\x1b\x27\xd0\x83\x93\x38\x8d\x0f\xf0\x11\x3e\xc1\xdf\xf0\xdf\xf8\x3b\xbe\x80\x8f\x88\x14\x1a\x45\x63\x29\x9c\x22\x29\x9a\x26\x91\x95\x62\x29\x9e\x12\x29\x99\x1c\x34\x97\xd2\xe9\x36\xba\x83\xee\xa2\x7b\xe8\x5e\x20\x32\xdc\xee\xb0\x0d\x02\x7b\xe4\x48\x60\x8b\xb4\x87\x0f\x03\x7c\xcc\x99\x4e\x3c\x72\xa4\xdd\x21\x0f\x4a\x70\xdc\x70\xcf\xfe\x1f\x8c\x5b\x19\xf8\x3c\x2a\xfe\xad\xe4\x7f\x2a\x1f\x0d\xfe\x78\x12\x06\xfe\xae\xbc\xf2\xf9\xb2\xcf\x57\x06\x7f\x86\x47\x19\x10\xb9\x72\xf8\x4f\x05\x4d\x59\x46\x53\x1f\xe6\x7f\xad\xa5\x64\x2d\x09\xfe\x1c\x29\xd5\xce\x14\x6b\xa7\xf4\xff\x5c\xd8\x97\x91\x75\x59\x69\x91\xb6\xba\xa4\x44\x6a\x29\xa6\x58\xf1\xdf\x5a\xfa\x45\xca\xb2\x65\xc1\xa9\x78\x0a\xfe\xaf\x42\x31\xf6\x05\x7f\xce\x96\xb2\x1e\x6e\x93\x39\xc3\xad\xe1\xf5\xf2\x99\xcf\xe5\x33\x5e\xab\xf0\xc7\xaa\x00\x3b\xce\x0c\x3f\x8f\x3d\xdc\x1a\x1e\x6b\x0d\xb7\xaa\xec\xe8\xe5\x35\x2c\xf9\xf2\x71\x76\xf4\xb2\x33\x87\x25\x83\xb0\x92\x5c\x52\x85\x5c\x2f\xf6\x61\x86\x5b\xc3\x57\xd2\x65\x72\x91\x57\x63\x3c\x8d\x2b\xef\x8c\xd9\x1e\x9e\xc6\x4a\xba\xac\x2d\xa1\x47\xb4\x57\x74\xbc\x1c\xd2\x69\x01\x56\x87\x40\xfa\x84\xa7\xe3\x08\xb7\x86\x87\x60\xb5\x54\xe1\xdb\xa2\xcf\xfd\x6d\x07\xd4\x1c\xd6\x0a\x09\xe1\x3f\x87\x24\x0b\x67\x5d\x92\x31\x85\x63\x1d\x45\xb4\x5d\x2a\x94\x0a\x58\xeb\xe5\x3c\x10\x35\xfa\x3f\x52\x97\xb2\x3d\x90\x00\x25\x9c\xa8\x91\x1d\x9d\xc8\xba\x7c\xdb\xf5\x74\xfc\x1f\xa9\x39\xac\x89\xbf\x23\x2b\xd1\x76\xd6\xea\xdb\xcd\x9a\x2e\xe7\x61\x60\xbc\x51\x14\xce\xe3\x49\x8b\xa4\xd2\xcb\x73\x79\x39\x2a\x01\x96\xae\x1c\x16\xe3\x36\x88\xe5\x66\xb6\x51\x72\x25\x1d\xc9\xa5\x5f\x6b\xf3\x73\xb5\x0b\xe4\x20\xa7\x76\x54\x3a\x23\xfd\xd9\x37\xd9\x67\x95\xce\xf8\x2e\x49\x21\x52\x88\x3e\x57\xb6\x0b\x3b\x58\x22\x8b\x17\xeb\xa6\x26\x2f\x18\x63\x46\xc8\x04\x4c\x98\x62\xb5\x8c\xb9\x89\x89\x81\x53\x90\x5f\x7b\x5c\x60\xd2\x44\xac\xc2\x9d\x49\x4e\xcb\x64\xb2\xcf\x9e\x4f\x8e\x39\xfa\x2c\xde\xae\xda\x13\x4f\xd5\x9f\xa8\xab\x3b\x51\xff\xd4\x89\xda\x82\x92\x5d\xa5\xcb\x76\x97\x96\xec\x59\x56\xb2\xbb\x44\x2a\xab\x7b\xb7\xae\xee\xdd\xba\xa7\x4e\xd4\xd5\xbd\x5d\x5f\xba\xbb\xa4\x64\x37\x7f\x59\xba\x8b\xd3\x60\x46\x29\x0a\x58\x31\xcb\x13\x7b\xcf\xa3\x10\x23\xce\xd9\x71\x22\x03\x77\x62\x31\xee\xc3\x43\x58\x8e\x2a\xd4\xc2\x05\x8c\xd3\x4f\x01\x9c\x6a\x9c\x06\x38\x35\xdc\x08\xc7\xfd\x8b\x7f\x07\xf2\x2b\x4d\x75\x38\x52\x6d\xce\x94\x14\xa7\x33\x65\xce\xdc\x32\x1e\x70\x78\xd1\xe1\x74\x3a\x38\xb4\x3a\x52\x52\x1c\x1c\xf6\xcc\x9d\x33\x67\x2e\x87\xcd\x4e\xbb\xdd\xc9\xa1\x94\xbf\xe7\xff\x62\xf9\x2f\x29\xdf\xe1\x70\xd4\x39\x9d\x0e\x6a\x74\x38\x9c\xda\x1d\xa9\xa9\x0e\xa9\xe3\x56\x67\x8a\x2f\xd7\x69\x77\xca\x0d\x4e\xa7\xc3\xfb\xdb\x94\x14\xa7\xdc\xe5\x70\xa4\x7a\x8f\x3a\x9d\x76\xf1\xcc\x77\x0f\xc7\x7b\xdd\xe9\x4c\xd1\xb2\x02\x71\x6b\x1d\x0e\x71\x46\xc5\x5e\xac\x63\x36\xd9\x83\xb1\x9c\x4b\x81\x7a\x82\x6d\x2a\xf6\x56\xf5\x3e\xb1\xf2\x64\x8d\xa6\xbd\xd6\xae\x69\x52\xe6\x63\x3d\xb5\xab\x4e\x56\xbe\xa6\x69\x24\xf5\xcf\x95\xee\x61\x6b\xc4\xb9\xae\x93\x17\x8c\x61\x90\xc7\x60\x8c\x25\x32\x04\x66\x42\x52\xb7\xb1\x55\x3e\x30\xaf\x61\x0d\xa7\x41\x75\x1e\xcf\xd6\x78\x59\xed\xb1\xaf\xaf\xea\xae\xad\x3d\x56\xfb\xf5\xee\x55\x6c\xcd\xe5\x06\x29\xb3\xf6\x58\x6d\x6d\xf7\xaa\x27\xbb\x6b\x6b\xbb\x21\x0f\xc8\xc3\x86\xb8\x05\x11\x16\xc8\x37\xdd\x34\x86\x81\x4d\x8b\x0d\x99\x62\x9e\x80\x29\x22\xaf\xd3\x6f\x9b\xdf\x16\x1b\xe8\x47\xce\x2e\x6a\x90\x08\x0e\xc9\x3e\xb7\x64\x77\xe9\xc3\xbb\x4b\x4b\x77\x3f\x5c\xba\xbb\x64\x08\x2d\x4f\x96\xf0\x57\x25\xcb\xb8\x00\x42\x42\x0d\xad\x95\x4a\xe5\x55\x18\x23\xd6\xe2\xe9\x33\x23\x43\x77\x2a\xd6\x34\x95\xad\xc8\xba\xeb\xa5\x65\xe5\x8d\x77\x2f\xbb\x2b\xf7\xa1\xe5\x59\x77\x2c\x97\x1a\xca\x5f\x58\x94\x5d\xfe\xe8\xc6\xe7\x2b\xb2\xcb\x2a\x16\x66\x95\x97\x03\x50\xa8\xcd\xff\x91\x5a\xc7\xf6\x60\xb4\xb1\x1e\xf4\x56\x80\xe6\xc0\x3a\x05\x7a\x4d\x38\x2d\xb0\xcf\x86\x58\xd1\x6e\x52\xa3\x82\x97\x46\x3a\xc7\xdb\x67\x3b\xa3\x54\xdb\xd4\xe0\x05\x93\xd4\x46\xa5\x24\x91\x4c\xa5\xda\x77\xbd\x97\xb5\x97\x0b\xc9\xde\xfb\x3e\x25\x6b\xc7\xdf\x3f\xf9\xdd\xad\xef\x26\x5a\xad\x89\x1c\x26\xa5\xe5\x34\xbd\x90\x93\x5e\xf2\x7a\x07\xe5\x27\x59\xad\x09\x09\x56\x6b\x92\x94\xed\xa1\x4a\x6d\xb3\x47\xd3\x5e\xa1\xe5\xde\x5e\xed\x2d\x9a\xd3\x7b\x92\xec\x5b\x5f\x5e\x3a\x25\x31\x71\x4a\x4c\x52\x92\x76\xca\xb6\x6e\x9d\x6d\x3f\x69\xc6\x6f\x30\x3a\xe1\xff\x48\xdd\x2a\x68\x8f\x82\x15\x89\x03\x29\x0f\x5e\xb7\x39\x8e\xd3\x1a\xa7\xda\xa6\xc6\x05\x3f\xa5\x13\x82\x58\x89\x96\x69\xdf\xf5\x6a\xda\x36\x4a\x48\xb4\x4e\x9e\x35\x6b\xb2\x35\x71\x52\x69\xc7\x2f\x4a\xe7\xdf\xfd\x42\x53\x0e\xd5\x27\x59\x27\xcf\x9c\x39\x79\x10\x81\x54\x1f\x93\x94\x14\x33\x25\x31\x51\xdb\xb6\x7f\xbf\x6d\xdd\x3a\xb2\x1a\xbf\x85\x7f\x37\xcb\x5f\xa3\x86\xb1\x34\xc4\xc3\x21\x4e\x3e\x4b\x71\xc6\x39\xa3\x52\x9c\x0e\x7b\xe4\x64\x8a\x72\x46\x99\xc6\xf3\xf1\xb3\x6a\x8a\x32\xc5\x85\x91\x29\xd2\xe6\x98\x1e\x67\x8a\x73\x4e\x8f\xd3\x2b\x30\x4e\xa7\x2d\xab\x77\xcc\x92\x7d\xf1\x07\xaa\x1e\xcf\xbc\xed\x91\xb4\xfd\x89\x1d\x05\x6a\x6f\xaf\x39\xa7\x23\xb9\x7d\xf6\x7d\x85\x99\x75\x65\x07\x12\xda\x73\xcd\x19\x47\xd6\x6d\xf8\x8d\xdc\xb9\x6e\xc3\x61\xea\x98\xbf\xba\xb8\x23\xb9\x3d\x77\xcc\xc9\x93\x6a\x5c\x62\x7b\x62\x47\xf5\x93\xf3\x1b\x4a\x0e\x24\xb4\xc7\xde\x32\xf6\xe4\x49\xf3\xa2\x7d\x89\x1d\x65\x0d\x31\xee\xce\x37\xbf\xe9\xee\xea\x12\x3e\x68\x2c\x61\x71\x6c\xb5\x7e\xd6\x33\x39\xac\x0e\x63\x3d\x8f\x90\x26\x93\xe1\x97\x11\x97\x54\x38\x03\xec\x3a\x49\x52\xf5\xba\xd6\xea\xda\xfc\x82\x17\x2a\x08\x7e\xe4\xec\xae\xcf\x2f\x48\x9b\x5f\x5b\x58\x58\x4b\x05\x59\x3b\x23\x76\x54\x34\xec\x2c\xc8\xaf\x7b\x6c\x47\xd8\xce\x2c\xcd\x43\xaa\x14\x5a\x50\x37\x3f\x3d\xbf\xa0\xf6\x29\x48\x94\x07\x0f\x6b\x65\xab\xc5\x09\x89\xc6\x8c\x9e\x73\x7a\xdc\x74\xc7\x1c\x67\x8a\x3d\x4a\xe4\x62\x9f\x1d\x69\x52\x23\x2d\x31\x64\xb9\x81\xa6\xce\xa4\xb8\x21\xcb\x8a\x38\x0d\x79\xbb\xea\xef\xc8\xbf\xd0\x94\x30\x4a\x35\x85\x58\x6f\x9f\x57\x18\x3f\xf5\x86\x30\x66\x1e\xc3\x58\x58\x64\xac\x2d\xec\xd3\xfc\x9f\x3e\xb1\x6a\x4f\x6e\x43\x61\x61\x7d\x43\xc1\xd2\x7a\x29\xea\xa9\xdd\x09\x17\x12\x12\x58\xd8\xa8\x10\xc6\xc2\xc7\x8e\x09\x9b\x98\xb6\xec\x9e\x39\x53\x46\xa9\x6a\xe6\xd2\xe4\xcf\xf2\x1e\x6b\x68\x6d\x69\x78\xe8\xeb\x1c\xbd\x8e\xeb\xa3\x34\x80\x31\x76\xdc\xd8\xf1\xea\x9c\x4f\xce\xc9\x14\x35\x99\xa2\xc4\x04\xe6\x64\x29\x86\xac\xce\xd9\xf3\x29\x9d\x38\x55\x69\x85\x8f\xac\x5b\x3b\x71\xc2\xc3\x2f\x6d\xcc\x92\x56\x17\x6e\x2b\x63\x4b\x76\xac\x55\xbd\x7f\x55\xeb\xf7\x14\x2e\xdd\xfd\xc0\x6a\xfa\x6c\xa9\x3b\xaf\x76\x7f\x43\xc9\xae\xe7\x5c\x6b\xee\x7c\xd8\xf5\xab\xe6\x9d\xc5\x21\xb1\xb1\x25\x7b\x5e\x08\xfb\x95\xcb\xc8\x4b\x61\xac\x0b\x76\x3d\xaf\xd9\x51\x82\x19\xc6\x82\xaa\x14\xe7\x95\x76\x3d\x93\xe2\x26\xcb\x3c\xeb\xf9\xb2\x43\xdf\xcc\x9a\xf6\x62\x51\xfa\x23\xb1\x11\xa3\x77\x54\x3f\xd9\x7c\x47\xbe\x79\x7c\xdc\x8a\xdb\x17\x6d\x7b\x32\xf5\xeb\x0f\xa5\xb3\xe4\x2a\xd7\xe3\xa3\xbc\xed\x21\xee\xda\xe2\x14\x79\x6e\xdb\xd2\x9a\x1d\x52\x6c\xcd\xf7\x24\x7b\x66\xdc\xb4\xb8\xba\xcd\xcd\x8f\x16\x94\xc6\xb1\x90\xdc\xbb\x57\xad\x6a\x99\x7d\xef\x8a\x86\xad\x4f\xa5\x58\x6c\xb6\x1b\x53\x6b\x5f\xca\x49\xaa\x5b\xf5\x3d\x7d\x6e\xdd\xff\x09\x5b\xca\xea\xfa\xb5\xcb\xf8\xa8\xc0\x66\x68\x53\x18\x99\x66\x52\x12\xcd\xa4\xf2\xe7\xca\x0a\x36\xc5\x59\x37\x15\x3e\xbc\xa9\xb0\x6a\xe3\x6a\xdb\xf8\xa5\x6d\x0f\xdc\x9d\x22\xaf\x79\x74\x5d\x4d\x6d\xed\x2a\xf7\xb2\x82\x83\xeb\x7e\xd6\xb3\xba\xe0\xb5\x4f\xeb\x1f\x59\xcd\xd3\xcc\xf4\x9f\x93\xdf\x65\x5d\x62\x8d\x47\x0a\x9c\xe3\x11\xa5\xc2\x34\x1d\x99\x4f\x92\x94\xbb\x88\x42\xea\xb3\xb4\xe3\xf9\x09\x9a\x47\x2a\x5c\x47\x85\xdf\x69\xd0\xbe\xbb\x2e\x4b\x5b\xf1\x62\x1e\xad\x14\x6b\x5b\x30\x49\x4e\x63\xab\x11\x6d\xec\x8a\x8d\x0a\xb7\x47\x72\xce\x98\x6c\xe2\x74\x4d\x7d\x32\xb8\xb3\xe1\x9e\x84\xa4\x9c\xad\x8f\x15\x27\xcd\x7d\x62\x41\xd3\xa3\x73\xe7\xae\xce\xad\x19\x27\xe7\x95\x1d\x6e\xda\xbd\xb9\xce\x55\x57\xdb\x1c\xaa\xa9\xf5\xdf\x75\xea\x6b\x89\x7a\xd8\x79\xe6\xc6\x8d\x98\x0c\xc4\xea\x29\xc6\x8a\x54\x74\xf1\x0f\x57\x8c\xf9\xe5\x58\x87\x42\xe6\xda\x45\x29\x33\xa5\xd7\x5f\x79\xa8\xa6\x3e\x37\x29\xc1\x77\x72\x5d\xcd\xdc\x5b\xa9\x4a\x8a\xf3\x9d\x74\xe6\xac\x1a\x27\x9d\xdf\xeb\xfd\xa5\xeb\xc5\x47\xee\xad\x8a\xa0\x43\x2f\x69\x5f\x7f\x72\x9b\x43\xfa\xf0\xa5\x55\x5b\x8c\xf5\xc6\x4e\x26\x29\xdd\xc6\x79\x13\x0e\x67\xb8\xb1\x2b\x20\xdc\x1e\xee\x8c\x34\x09\xb0\x85\x2b\xe1\xb6\x70\x67\x6c\xb8\x52\x7e\xf4\xe8\xd1\x12\x5a\x54\x72\x94\x87\x5a\x7b\x49\x09\x2d\xd2\xda\xa3\xbe\x5f\x4c\x9f\x97\x34\x97\x50\x96\xf6\x41\x33\x15\x69\xc7\x8a\xb7\x97\x68\xa1\x4b\x9b\x0b\xb5\x6d\x94\xfe\x7d\xed\x65\x5a\xf0\x46\x33\x7d\xde\x0c\x82\x05\x90\xb5\xfe\xbd\x53\xfa\x1e\xc6\x7e\xef\x2a\x07\xcb\xcf\x7e\xf6\xb3\x0e\x2a\xd2\x5a\x38\x48\x2e\xef\x51\xea\x6a\x6c\x7f\x41\x1a\xef\xfb\xeb\x0b\xed\x8d\xda\xe9\x16\xea\xd2\xf7\x85\x00\xe4\x55\x2d\xfa\xba\x8a\x40\x3a\xfd\xbb\x20\xc3\x2d\x5b\xb7\x6e\xdd\xb7\x95\xff\x21\x6f\xe3\x6b\x8d\x52\x86\xef\x70\xe3\x6b\x8d\x1a\x23\x2f\xc8\xef\x31\x68\x98\x64\x9c\xc2\x1d\x15\x6e\x0f\x1f\xdf\x7f\xa4\x5d\x9c\x20\x43\xac\x93\x54\x47\x97\x7d\xf5\x06\x5b\x47\xd4\xf8\x5b\x6e\x09\x5b\x3e\xba\xac\x20\x26\x42\x2a\xf0\x5e\x98\x30\x6e\xc6\x2d\x63\xa5\x9c\xa7\x9f\x0b\x91\x1e\xf3\x25\x87\xa6\xcd\x7b\xea\x3b\x21\x5a\x6e\x8b\xd4\x31\x5a\x9c\xad\x27\x89\x3d\x43\x55\x62\x6f\xe2\x8d\xc6\x4e\x56\x7d\x6f\xa4\xb1\x45\x48\xac\x85\x17\xfb\x50\x7f\xd6\x7f\xd8\x66\x47\x87\x7e\xdc\x26\x25\x68\x3d\xf2\xae\x66\xfa\x9a\x7e\xcc\xa6\xbc\xeb\xc4\xc6\x6d\x1b\x9f\x3b\xd1\xac\x9f\xf3\xaf\x59\xc4\x1e\x9c\x48\x2e\x0f\x51\xe1\xd6\x29\x2c\xd2\xac\x90\x8d\xac\xe1\x81\xd3\xf7\xa6\x8c\x0b\xa4\xdf\x45\x4d\x64\x26\x45\x3b\x45\x8d\xbd\xda\x76\xed\xf4\xad\x77\xce\xbe\x25\x39\x53\xfb\x63\xc7\xa9\xbd\x2d\x3b\xf7\x9f\xd8\xad\x96\x1c\x7f\x47\x3b\xfd\x88\xd8\xc4\x28\xdd\x77\x6f\xe4\xb6\x89\xec\xc3\xe7\xd6\xaf\x77\x01\x0c\xc5\x5a\x81\xdc\xab\x5a\x30\x05\xd3\x31\x53\xb4\x7a\x73\xec\xb8\x38\xb1\x4c\x39\xb0\xe5\x55\x2c\xed\x11\x97\x06\xc9\xb6\x71\xdc\x54\x15\xfb\x94\xb9\xc2\x31\xd9\x4c\x19\xe4\x98\x13\x57\x4c\x2d\xe5\x11\x11\xf7\xbd\xb2\xd0\xf9\x95\x37\x4a\xa6\x4f\xdd\xb0\x6e\x73\xd9\x43\x6b\x6c\x21\x79\xff\xfe\x8c\x6b\xdd\xda\x47\x1f\x7b\xfd\x9e\xea\xe2\x92\xb7\x37\xef\xda\x71\x43\x58\xdc\xd6\x85\x94\x4c\x09\x09\x94\x29\xcd\x99\xe2\x9e\x31\x9b\xd1\x01\x2d\x3e\xb6\xe5\xdb\x3e\xcb\xb6\xe5\x77\x69\x95\xb4\x2b\xa6\xf9\x89\x47\x67\x50\x79\xe4\x32\xed\x7f\xa5\x9d\x8d\xcb\x4c\x92\xcb\x74\xdb\x7a\x63\xef\xbf\x55\x2b\x90\xb3\x54\x0b\x26\x61\x0a\xe7\xb5\xd8\x72\x3a\xce\x2e\x47\xda\xe4\x2b\xe7\xb9\xc5\xc9\xb6\x71\xd3\x1d\xe1\x13\xc9\x66\xfd\x5e\xf6\xa3\xfb\x1b\xd7\x6f\x89\xfd\x9f\x19\x0f\xd8\x8a\x27\x44\xaf\x48\x79\xe8\xb6\x75\xeb\x76\xa6\xfc\x7c\xd3\x26\xf9\x60\x41\xf6\x5f\xbd\xf4\x5b\x2d\x66\x95\xd7\x9b\x16\x36\x6a\xfd\xe8\xc8\x9b\xb4\x5c\x29\xec\xde\xf5\x92\x4b\xbb\x95\x7e\x03\x42\x97\xe6\x52\x7a\xc4\x7e\x8c\xfe\x5b\x16\xec\xc2\x9b\x6f\x0d\xef\xea\x90\xce\xb7\xb7\xb5\xb5\xfb\xcc\xc6\x75\x0a\x9f\xf9\x4e\xd1\x6a\x71\x45\x03\xa1\x55\x5b\xc3\x3e\x53\x2d\x5c\x1a\x78\x0c\x4b\xe0\xd0\x06\x23\x76\x60\xab\xf0\xbe\xd0\x31\xc9\xfb\xaa\xdf\xfc\xed\x8e\x9f\xfd\xa0\xd6\xf5\xa3\x57\x54\x8b\x96\xba\x74\xc1\x92\xa5\xbf\xfa\x4f\x5f\xb7\xef\x53\x6a\x90\x0e\x7e\x6b\xcd\xfe\xdf\xf9\x8e\xea\x6b\xd1\x38\x2d\x51\x4a\x3b\xcc\x7a\x9a\x4e\x71\x4c\x2c\x4f\x8e\x4c\xe1\x5d\x1d\xdf\x90\x46\xf5\xfa\x7e\x49\x1f\x6c\xfb\xe9\xdd\xbe\x2f\x5e\x52\xda\x7d\x49\x1b\xa4\x2c\xdf\x1a\xdf\xa3\x82\xaa\xfd\x6b\x78\x2a\x3a\x5d\x25\x7a\x1b\xe2\x69\x98\xec\x19\x14\x9c\x4c\xeb\xde\x90\x90\xf4\x2c\x7a\xe8\x3f\xb5\x85\x54\xbe\x63\x6f\xbe\xb6\xa6\x41\xb5\x78\xdf\xdd\x9b\x9b\x4f\x35\x5a\x82\x66\x13\x44\x61\xa5\x26\x74\x5f\xae\xe6\x62\x0b\xc5\x7a\xbd\xdb\x17\x4c\x95\x42\xd5\x51\x32\x46\x85\x86\x9a\x20\x8f\x19\x1b\x3a\x55\x95\x19\x93\x57\xdc\xcf\x64\x32\x01\xa6\x15\xf7\x23\x02\x19\x09\xe1\x11\x98\x3b\x21\x10\xf4\xdb\xa5\x86\x6d\xea\x20\xab\xb8\x51\x29\xdc\x16\x9e\x2b\x4b\xbe\xf1\xf2\x51\xaf\x26\x47\xfd\x74\x03\x73\xb7\x6c\xb8\x5c\xc7\x4b\x01\xc2\x12\x6d\x8d\x5c\xc3\x16\x61\x34\xd2\x17\x4c\x51\xa5\x51\xa1\xa1\x92\x49\x86\xd2\x9f\x63\xd9\xfd\xec\x06\x91\x63\xd9\xfd\x88\x1c\x31\xc7\x81\xb9\x2d\x91\x72\x7d\x3d\xd2\x7f\xfb\x5e\x97\xf2\xf7\xd6\xca\x77\x3e\xe7\xf6\xbe\xe9\xbb\x44\x0d\x42\xd6\x1a\xfc\x7d\xca\x52\xe5\x18\xc6\xe9\x67\x70\xc0\x3a\x7b\x7c\x94\xdd\x69\x37\x1a\xc2\xd4\x69\x92\xd3\x1c\x21\xac\xe9\x70\x61\x4e\x4b\x0d\x74\x27\xd9\x9e\xff\x2c\x2d\x34\xa6\xb1\x31\x26\x74\xee\x47\x3f\x7c\x5d\xeb\x6b\x3c\xf4\xc7\xdf\x6e\x7f\xe3\x81\xa2\xdf\x7c\xaf\xeb\x8c\x74\x9a\x1e\xa6\x8d\x5f\x5b\x76\xc0\xb3\xe8\x40\xc9\xe3\xed\x54\x70\x56\xfb\x54\xeb\x2c\x6a\x6f\xa6\x79\x3f\x68\x7f\x40\x3b\xaa\x8f\x8b\xc1\x92\x59\x31\xef\xe3\xc2\xed\xe3\x26\xcb\x51\xf6\x14\xa7\xd8\xac\x69\x9c\xff\x41\xb6\xc3\x67\x46\x4f\x8c\xb6\x28\x21\xa3\xe7\xfc\x62\xf2\xd2\x9c\xdb\x67\xc7\x4e\xb0\xcd\xb2\x68\xbd\x6f\xb3\x45\xbe\xba\xa9\xf7\x2e\xce\x8e\x4e\xdd\x21\xcd\x7f\xf0\xae\x09\x6b\x43\x53\xe6\x7a\x5b\xc4\xb9\x6b\x80\x69\x97\x72\x44\x9c\x06\x6f\x1f\x37\x3e\x2a\xc5\x49\x76\xe2\xc1\x95\x84\xc3\xc8\x44\x36\xb1\xa4\x93\x6c\xd1\x87\xce\xce\x9c\x30\x3e\x95\xa4\x83\x24\xa5\xdc\x38\xce\xb1\x77\xe2\x13\x0f\xdf\x3a\x6d\x82\x2d\x36\x6e\x52\xa8\xd6\xfd\xba\xf6\x59\xc6\x68\x73\x8a\xd6\xb7\x5f\x69\xf7\xae\x79\xf5\x27\x2d\x47\xe4\x27\xbc\xee\xfd\x3b\x9f\x7f\x5b\xea\x5a\xbe\x34\xbc\x29\x34\x72\x46\xdc\xe5\x0c\xf9\xe0\xef\xee\xae\xd9\xe7\xcd\x16\xb2\x1b\x05\xa8\xf5\xac\x18\x37\xf3\xfc\x6f\xa4\x28\xbb\x33\xc5\x39\xce\x28\xdc\x44\xea\xa7\xc1\x24\xdb\xe4\xe9\x71\x36\xd5\x24\xdb\xa2\xf6\x57\xac\x0c\x0d\x09\x8b\x99\x74\xe4\x8d\x5f\x86\x46\x59\xcc\x6c\x54\x48\xda\xf2\x88\x92\xbc\xdb\x67\xc7\x46\xe7\xdc\xd8\xf3\xee\x81\x1b\x67\x87\xdc\x32\xa5\xf3\x2d\xb6\x48\x7b\x54\x5b\x7a\xdf\xfc\x4d\x4b\xa5\x47\x7d\x2f\xd9\x16\xdf\x73\xd7\xa4\x3b\xe1\xa7\x8e\xfc\xbc\x09\x6b\x43\xab\xbc\x2d\x52\xe5\x3d\xbf\x3b\x52\xaa\xfb\x15\x74\x3d\x6d\x66\x15\x88\xd6\xf7\x73\xcd\x76\x5e\x39\x83\xdc\x14\x21\x18\x6d\x27\x9b\xac\x8e\xb3\x8c\x8f\x32\x6c\x3a\xcb\xa3\xf1\xf6\xef\x3c\x51\xbd\xc1\x55\x5b\x16\x1d\x12\x7e\xf7\xc5\x43\x5a\xfe\xdb\xaf\x2f\xde\x38\x6e\xf2\x9a\xd9\x37\xc7\xd9\xe9\x93\xcd\xea\xf3\x4b\x1f\x5f\xf7\xec\x8a\x27\xf7\xce\xd1\x3e\xaf\xcf\x3f\x2e\xb9\x2f\xb7\xd3\xa5\x1b\x68\x73\xdc\x7d\x8b\x17\xb8\x13\xe6\xce\xd5\xdb\xae\xb1\xb7\xcf\x64\xe8\x91\x48\xa1\x3f\x6a\x7c\x1b\xb9\xee\xd8\xe1\x2b\x10\x6d\x13\x90\xeb\xd8\xa2\x60\x9c\xd6\x7d\x52\x94\xef\x13\xb6\x48\x73\x6e\xd1\xa2\x38\xfd\xd5\xfe\x3e\xa5\x88\x15\x63\x9c\xbe\x1f\x71\x5c\x54\x18\x45\x9a\x15\xb1\x92\x2d\x22\xd2\x0c\xeb\x94\xd8\xc0\xb2\xf6\xc8\xea\x13\x1b\xee\x5f\x4c\xc5\xbb\xb7\xfe\xe2\x0f\xda\x1e\xed\xb8\x6f\xab\xf4\xeb\xb6\x23\x4f\x3d\x72\xe7\x62\x29\x81\x6e\x81\xbf\x64\xd5\x99\x7a\x6d\x8d\x4d\x2a\x6e\xef\xd4\xde\xff\x42\xfb\x50\x3b\xfa\xb2\xf9\x2f\xbf\xee\x78\xef\x89\x27\x84\x8e\xc5\x16\xa9\xc9\x58\x53\x84\x71\x14\x45\x32\x45\x91\x55\x8a\xbf\xcb\xd7\x7b\x97\xf8\x4b\x8c\xea\x57\x6a\xdf\xa2\x93\x3c\x58\x2b\xe6\xa9\x9b\x14\x2b\x55\x98\x4a\xc4\x9c\x4e\xe2\x02\xab\x29\x66\x6c\xd2\xd8\xc5\x63\x1f\x1a\x7b\x7c\xac\x7f\xac\x3a\x76\x01\x11\xc5\x20\x09\x8b\xf1\x10\x8e\xc3\x0f\x15\x48\x7a\xb0\xfb\xc1\xa4\x07\xed\xc9\xb3\x82\x2f\x08\x51\xc2\xed\xe1\x2b\x33\x66\x24\x64\xdc\x3a\x6b\x46\x06\x2d\x78\x49\x5d\x98\xe6\x74\xa6\xa5\xa4\xa7\x7e\xcc\x7b\x74\x91\x0f\xab\xa7\x63\xaa\x7e\x5e\x56\xec\x82\xe8\x41\xf9\xd0\xa1\x24\x79\xb1\x7c\x5c\x96\x65\x24\x3d\x78\x63\xf7\x90\xf4\x79\x61\xfa\xd3\x4f\xa5\xef\xae\xd0\x2a\xfb\xb3\xd0\xde\xa7\x2d\x2b\xb4\x15\x90\xb4\x33\xec\x24\xc5\xa8\xed\xfa\x5d\x15\x62\xbe\x3e\x28\x09\xed\x8c\xb4\x40\x7b\x32\x90\x06\x3b\xb9\x79\x33\x3d\x6a\xa4\x00\x90\x76\x9e\x1d\x21\xb3\x1a\x05\x05\xe6\xd7\x64\xba\x01\x0f\x41\xe2\x65\x9d\x3d\x5b\x9c\x1a\xe7\xb0\x87\x6b\xe7\x69\xdf\x63\xec\xc8\x63\x1f\x6b\x7b\x78\xbd\x6f\x62\x7b\xe4\x7c\x53\x9a\x38\x7f\x67\x94\xd0\x48\x9b\x68\x19\x95\x6a\x9f\xbe\xa2\xb4\xd3\x5a\xad\x5e\x3f\xec\x82\xe3\x6d\x92\xf3\x4d\x31\x02\x4f\x4c\x50\xd3\x26\x8a\x7c\x85\x22\xb5\xed\xaa\x85\x46\x6b\x7f\xd7\xea\x75\x19\x6f\x92\x9a\xa9\x51\xbd\xa8\xaf\xc0\x18\x37\xdc\xd9\x61\x99\xe9\xfa\x69\x61\x72\x42\xe6\x9d\x77\x2d\xc8\xc8\x59\xc4\x42\x7d\x65\x46\xdc\x7d\xd4\x68\x0a\x19\x1a\x77\x22\xd9\xc7\x35\x2d\x4c\x4b\xb9\xeb\xf6\x79\xf3\x6e\x0f\xb7\xaf\xb2\xab\x0d\x0b\xee\xce\xbc\x2b\xeb\xf6\x6c\xef\x53\xd2\x36\x5f\x19\x8f\x4b\x85\xd4\x28\xce\x9c\xbb\x56\x5c\x25\xe3\xb6\xbb\x33\x17\xf1\xb8\x4b\xa5\xfd\xbe\xac\x20\x9e\x19\xeb\xc1\x6c\x91\x36\x87\x2d\x52\x3b\x2f\x4d\x39\xb8\x72\x1d\x3b\x42\xf9\x2b\xcf\x9d\x3b\x27\x78\x0b\x90\x99\xf2\x31\x0a\x11\xed\x72\x88\x42\x21\x04\x24\xcd\x9e\x1d\x6e\x4f\xb2\x27\xcf\xb2\x3a\x0c\x2f\x7e\xb8\x76\xfe\xe0\xca\x75\x8f\xf1\x48\x9c\xc5\x20\x7c\xa1\x7d\x45\xfe\x89\xff\x15\xe1\xcb\x99\x4f\x4e\xfd\x8c\xdc\x38\xd5\x64\xfb\xa2\x61\xf9\x84\x8e\x39\x6f\xb9\x96\xae\x5d\x53\x58\xaf\x55\x7e\xeb\xd9\x84\x47\xde\x8a\x72\xac\x79\x36\xd5\xe0\x25\xda\xa8\x91\x95\x8b\x31\xfc\xf4\x05\x11\x63\x10\xa1\x42\x9d\x10\x2d\x4e\x1f\x13\x47\x9c\x21\x29\x01\x13\x92\x12\x06\xf8\xf4\x46\x38\x3c\x2c\x70\x3c\x61\xc6\xfc\x8c\x4c\x1e\x52\x5a\x66\x76\x76\xe6\x82\xbb\x17\x49\x1f\x64\xde\x95\x7d\xfb\x82\xbb\x17\xe9\x79\x96\xd3\x2a\x39\x51\x6e\x36\xda\x9e\xb1\x32\xaf\x5c\xea\xf2\xcd\x95\xba\x68\x55\x63\x23\xbd\x2c\xd6\xae\x63\x27\x6d\xa3\xd5\x57\xce\xc3\xdb\x79\xca\xbe\x4a\x69\xbf\xfc\x17\x51\xde\x9d\xb2\x63\xe8\x3b\x9f\x0b\x81\xfe\x25\x87\xe5\xf0\x77\xc9\xe1\xd6\x70\xfe\xfd\xf2\x3e\xc8\xe2\x8c\x83\x39\x6a\x8c\x38\x53\x29\x56\xdf\x2b\xdc\xbf\xf9\x56\x15\x27\xa9\x84\xdb\xc2\x07\xdf\x56\x13\x73\xe8\xd5\xf6\x15\x8f\xcd\x7a\x30\xeb\x81\x42\x8a\xd4\x3e\xdd\x27\xfd\x5b\x7a\xe2\x2d\x19\x19\xb7\x24\xa6\x87\xed\x93\x0f\xe6\xcf\xcf\x78\xf3\xcd\xd8\x8d\x93\x9f\xfa\xb7\x3b\x9f\xf3\x66\xca\x07\xe9\xe7\xf3\x52\x52\xe6\xa5\xa5\xa6\x7a\xde\x64\x8b\x2e\xb7\xeb\xe5\xe5\xf9\xda\x44\xbe\xd1\x23\xe6\x3a\x5c\x4e\xcf\x0f\x93\x81\x37\x53\xb5\x7c\xd1\xa7\xef\x25\x8e\x01\xd4\x8b\x22\xdd\x04\x31\xa3\x3c\x42\xda\xd6\x7f\xac\x9c\x34\xf8\xc1\xea\xab\x15\xfc\xda\x8c\x10\xfc\x57\xcf\x1a\xf4\x26\x7d\x49\x6a\xaf\x8b\xc2\x4d\xd7\x41\x58\x3f\x03\xc9\xfb\x11\xdb\x8b\x50\xd5\x2e\xda\x64\xca\x34\xab\x3d\xd2\x36\x95\x99\xbc\x1f\x95\xd0\xcb\x34\x35\x34\xf4\x53\xad\x35\x97\xed\xfd\xe5\x1b\x4d\x4f\x3f\x09\xf2\x7f\xce\xf6\xca\x13\x75\x5c\xd9\x61\x9f\xc2\xa2\x6c\xd3\xa7\xd9\x42\x43\xc9\x46\x9b\x4b\x9f\x5f\xac\xbd\xfa\xa9\xd2\xdc\xf4\xc6\x2f\x9f\x7c\x9a\xa7\xdb\xc7\x4e\x01\xca\x07\x62\xd5\x5c\x04\x37\xa8\x22\xc5\xae\x56\x6f\xdf\x4c\x9a\xf7\xe4\xf1\xe5\x3f\xdf\xbd\xf8\x4c\x0c\x3b\x45\xea\xf4\xa8\x75\x71\xe3\x1b\x74\xdb\x17\xec\xb4\x6c\x51\xce\x22\x14\x08\x17\xfb\xda\x9c\x76\xc9\x3a\x75\xf9\x7f\xae\x3a\x13\x53\x31\x53\xfb\x4d\x8b\x32\x71\x5d\x54\x5c\x83\xe6\x01\xc6\x23\x5f\x5b\x6d\x3a\xac\x7c\x26\xd6\x18\x8d\x15\xab\x68\x6c\x41\xeb\x0a\xee\xc6\x57\x50\x84\x12\x94\xa1\x1a\xb5\xfd\x33\x91\x70\x0a\x6b\x38\xd2\x1e\x69\x8d\x26\xbb\x58\x63\x23\x0b\x3d\x34\xf0\xc4\x4c\xfb\x6c\xc7\x1c\xdb\xd4\x71\x62\x8f\x8f\x35\x32\x10\xca\xe1\x86\x05\x11\xa9\x6f\x8d\x8d\x13\x23\xb2\xfe\x8d\x86\x09\xd4\x8f\x28\xb6\x20\x1a\x6b\xc4\xc7\x71\x45\xc5\x1f\x87\xdb\x1c\x57\xf2\xb4\x87\xe7\x57\x55\x55\x1d\xd2\x4e\x54\x55\x55\x55\x51\xd2\xa1\x46\xb7\xeb\x1b\xdf\x76\xbb\x5c\x6e\x97\xdb\xed\x76\xc7\x53\x98\x76\x81\xc2\xea\xc8\xac\x9d\x27\xf3\x99\x3d\x2b\x1f\x9f\x39\x23\x7d\xe6\xca\xe2\xfc\x45\xc9\xb1\x4b\xb3\x32\x67\x4e\xbb\x25\x29\xed\x14\x85\x6b\xff\x45\xe1\x5b\x12\xa2\x0b\x1a\x56\x14\xcf\xb9\x70\x64\xa5\xf6\x0e\xcd\xd2\xe7\xcf\xe2\x78\xfc\xda\x5f\xaf\x94\x13\x45\x0a\xeb\xe8\x06\xed\xbf\xc9\x4d\xb3\xaa\x0e\xfb\x5e\x7b\xe1\x95\xad\x4d\x8d\xdb\xb6\x35\x76\x76\xbe\x71\xf9\xe7\x2b\x55\xad\xaa\xea\x8b\x2a\x11\x5c\x3e\x21\x2d\xba\xfd\x2b\xc9\x99\x21\x21\x61\x0b\x1d\xf7\xde\x5f\x9e\x10\xbb\xa8\x74\xea\x94\xa9\x93\x2e\xbf\xae\xbf\xee\x29\x0f\x29\xa0\x17\xb4\x27\x1e\x5a\xe6\x6b\xf9\xb5\x76\x42\xd5\xaa\xb4\x77\x0e\x7b\x76\x09\x52\xdd\x57\xf2\x11\x32\x9e\xaf\x1d\x36\xed\x16\xe7\x18\x4f\xc6\x2d\xbc\xbf\x93\x03\x3b\x5e\x4c\x61\x34\x89\xec\x0e\xe1\xd8\x32\xdc\xa2\x41\x9e\xb5\x7c\x79\xb7\xbc\xc7\x9b\xaf\xb5\xe6\x35\x2f\xcd\x98\x9f\x9c\x9d\x9f\xf6\x9f\x33\x6e\x5b\x7e\xd7\xeb\x3f\x5c\xbc\xff\xa1\x3b\xb3\xb8\xfa\xcc\xbe\x43\xaa\x94\x77\x7b\x0b\xbc\xf7\x29\x15\x7b\x97\xdc\x9a\xe4\xb8\x3b\x65\xe1\xe3\x8b\xd2\x92\x66\xdf\x96\x9c\xf7\x8d\x42\xf7\xd6\x54\xef\xa8\x8c\xec\xbb\xe6\x2f\xb8\x2b\x9b\xcb\xd3\x71\x76\x52\x3e\xa6\x9a\x45\x7f\x30\xe0\x02\x91\xe3\xbb\x46\x3d\x50\xbd\x7c\xd9\xe8\xdd\x37\x1c\xe8\x38\xf4\xaa\x6a\xae\xc8\x2b\x2c\xdd\xf1\x12\xd7\xb7\xb4\x96\x75\x4b\xf5\xaa\x45\xb4\x07\x07\xef\x44\x22\xb9\xc9\xbc\x36\x2a\x4e\xdd\x3b\xb6\x20\x99\x75\x4f\xc8\xdc\x6f\x8f\x70\x74\xf0\xf4\xa9\x4a\x4b\x93\x56\xf9\xd7\x60\x14\x6e\x5a\x30\x76\x94\x12\x3a\xba\x64\x14\x8d\x7a\xf6\x06\x99\x84\x55\xf2\xd6\x83\xc6\x54\x16\x05\x92\xb1\x51\xd5\xf8\x94\x90\xbd\xe6\x87\xed\xa5\x5a\xbe\x7d\x7f\x66\x44\xc6\xeb\xf3\x78\x3a\xf5\xec\xa4\xb4\x46\xb5\x0e\xca\xb3\xfe\x86\x65\xb3\xcb\x26\xce\x31\xb1\x93\xe3\x52\x0f\xa5\x47\xa7\xed\xbf\xd5\xb8\x0f\xdf\x34\x5a\xe9\xc6\x0d\xe2\xc4\xd7\x64\xdd\x73\x17\xa9\x46\x5a\x26\x4b\x91\x16\x6e\x59\xf5\x27\x30\xd2\xb1\xf4\xf4\xd4\x33\xf5\x53\x62\xa7\x3c\xec\xcc\x22\xab\x25\x63\xec\x91\xa9\x4f\xdb\x17\x8f\x7c\x46\xfd\xb9\xdc\x9a\x49\xd9\xf1\x0e\xcb\x38\xf3\x8d\x37\x2d\xba\x63\xfe\x04\xc7\xaf\xd2\x2c\x0b\xf7\xa6\x6b\x8f\x5f\xfb\xcc\x7a\x34\xb1\x0a\xa9\x57\xe9\x14\xb4\x8e\x4c\x67\xd3\x50\x7a\x46\xca\x15\xe4\x63\xac\x43\xab\x55\x1b\xf9\xf8\x98\x1c\x29\xf6\x29\x91\x96\x1b\xc8\x16\xc7\xa5\xc9\x36\xd5\xc7\x62\x73\x48\xda\x19\x5a\x15\xb6\xa8\xf0\x5b\x0e\x75\x62\xe5\x98\xfd\xcf\x4d\x5f\xd9\x3a\x76\xe6\xac\x3c\x4e\x8f\xb7\x92\x9d\xf4\x1f\x50\x5d\x18\x2b\x76\x86\x38\x82\x4d\x84\x58\xe3\xcc\x76\x6f\xa5\xbd\x76\xd6\x81\x3b\x5f\x28\x7b\x7c\xd9\x13\x0f\xd3\xfe\xbb\x52\xf6\xdd\x5b\xcf\x4e\x46\xdf\xea\xbe\x63\xf9\xf7\xa3\xef\x7e\xe0\x91\xdb\x8e\x4c\x78\xe0\xf1\xc8\xc7\x4a\x79\x7a\x97\x37\xb2\x93\xda\x19\xd5\x25\xee\x26\xee\xbf\x5d\x64\x9c\xc3\x99\x72\x25\xdd\xcb\x1b\xf7\xce\xcd\x2a\xad\x7b\xce\x51\x6d\x3f\x38\xff\x95\xf2\x87\x9f\xa8\x5c\xa1\x56\x46\xae\x2a\x1c\xff\x80\xf6\xe7\xa8\x74\xd7\xa2\xfb\x7f\x12\x75\xdb\x23\x25\x59\xe8\xa7\x6f\xad\x7a\x09\x63\x31\x79\x30\x7d\xbc\xac\xb3\x83\xcb\x3a\x90\xd0\x1d\x13\x52\xdf\x70\xa9\xf9\xa1\x69\xf3\x97\x25\x0d\x20\x97\x3a\xf3\xd5\xef\x94\x4f\x5a\xbc\x7a\x54\x4c\xec\x7c\x9e\x47\x39\x3b\xa9\x7d\x62\x32\x73\x4b\x07\x18\xfe\xd6\x07\x59\x94\x60\x32\x19\x59\x7b\xcb\xc7\x96\xe5\xc4\xde\x75\xc7\xfc\x89\x37\xdf\x32\xa6\x68\xf4\x23\x39\xd3\xee\xbc\x7d\xc1\x4d\x37\xdf\x12\x96\x9f\x52\x95\xd2\x31\xab\x76\x4e\x69\x79\x55\x51\x9d\x9a\x5c\x59\x33\x69\xda\xa4\x24\x3d\x98\x39\x5b\xdb\x15\x35\xaf\x6e\xf1\x1d\x6b\x6f\x8d\xca\x2c\xfd\xca\xbd\x7a\xf9\xaa\xd9\x49\xad\x5b\x3d\x6c\xf0\x7f\x40\x8b\x0c\x5c\x13\xe9\xad\x7e\xcc\x74\xef\x8a\x07\x1f\x0c\x59\x39\xf6\xfb\x6b\x5f\x78\xe1\xcf\xf9\x09\x7b\xef\x7f\x52\xf9\xe8\xce\xf9\xb7\x67\xae\x59\xf7\x9d\xaf\x47\x55\x15\x47\xae\x5a\x1a\x9c\xd6\x18\xe1\x31\x0c\x4a\xab\xff\x6e\x77\x3d\xa9\x92\xa5\x21\x2b\xc7\x7e\xcf\xad\x7d\x3c\x75\xef\xcc\xc5\xa5\xb5\x3c\xa9\xdb\x16\x7e\xf3\xdb\xf4\x6e\xe4\x23\x15\x51\xc5\x41\x74\x99\x54\x8c\xe1\xe3\xad\x41\x69\x0d\x66\xfb\xc0\x44\x5f\x1e\x3f\xff\x50\x83\x9a\x1f\x3a\x77\xfe\xc3\xb1\xfd\x49\xf7\x2c\x09\xd9\xb8\x6c\x72\x7c\xd1\xa8\x29\xb6\x74\x5c\xe1\xf9\x18\x63\x9e\x63\xf8\x2b\x98\x82\x73\x1d\x91\xe3\x79\x8f\x99\x16\x3f\x5a\x5a\x18\xb2\x72\xec\xb6\x6f\x6b\x1f\xab\xc9\x15\xd5\x82\xe5\xcb\x9f\x10\x2c\x5f\x72\xc7\xbc\x05\xb7\xfd\xdb\xb7\xf4\xbe\x34\x51\x4b\xa7\x6a\x40\x58\xe9\xba\x86\x8d\xb3\x1b\xdb\xa0\x12\x6d\x8e\x58\xfb\x06\x57\xf3\x8a\xb2\x05\x4e\xed\xf0\xe8\xa4\xc4\xe5\xee\x5a\xf7\x03\x95\xe1\xfa\xd9\xed\x5a\x25\xad\x41\x8b\x38\xbb\xd1\xe8\xc7\xcc\xb6\xa9\x71\xd1\x33\x53\x4b\x77\x9c\x4f\xcb\x38\x37\xee\x51\xb2\x6b\xbd\xda\x7f\x45\x43\xd6\xce\xb0\xe3\x94\xa8\x5e\xc2\x68\xfd\x3e\x8c\x01\x87\xb5\x18\xf5\x19\x35\x60\x44\x75\xeb\xf4\xb8\xd4\xd4\xb8\x99\xb3\xf7\xbe\x34\xab\x77\xee\x5f\xf3\x6f\x9d\x1e\x9f\x6a\x9f\x39\x73\xb6\x62\x77\xcc\x9e\xed\x70\x24\xa5\xfc\x76\xc2\x4f\xca\x22\xef\x7f\x7d\x1b\xff\x39\x6b\x4e\x0a\x20\x6b\xef\xb2\xe3\x14\xa3\x5e\x0a\xdc\xb9\x11\x68\x65\xf2\x08\x57\x56\x69\xef\xf6\xce\x7a\xa9\xee\xaf\x89\x81\x9c\xc8\x15\xc8\x44\x3d\x1b\x59\xf6\x93\x09\xaf\x6b\x3f\x36\xf2\x9a\x19\xc8\xe4\xaa\x67\x26\xa3\x19\x90\xdb\x95\xd5\x62\x85\x80\xc3\x4a\xfa\xf2\xf8\x66\x2a\xa3\x04\xb7\x5b\x6b\x61\x1e\xb7\xd6\x43\x09\x1e\x97\xbc\x9d\x8a\xae\x8d\xbf\x89\xe3\x67\xd1\x7e\x8f\x4b\xea\x91\x62\xaf\x86\xff\x35\xb2\xba\xdd\xda\x5a\xe6\x71\xfb\x96\x4a\x3b\x3d\x2e\x6a\x96\x97\x0e\xc0\x0f\xb9\x82\xdf\x8f\xee\x62\x1e\xb7\x77\xa1\x7c\xc0\xe3\x62\x1e\xe8\x67\x9b\xf4\xe3\x3a\x75\xff\x1f\xe5\x16\x51\x3a\x65\xbb\xdd\x5a\x87\x12\x5d\xa2\xf5\x90\xdd\xe3\x62\x5d\xda\x5b\xfa\x1d\x06\x41\xb4\x38\xc9\xb8\x6c\x36\xaf\x94\xb2\xc9\xee\x76\x6b\x2f\x2a\x51\x25\x5a\x07\xe5\x79\x5c\xf2\x2e\x9d\x37\x81\xf4\xc5\x39\xff\x3a\xe9\xb9\xc5\xd2\x1a\xb7\x5b\x89\x2a\xf6\xbd\x2c\xd5\x78\x5c\xd2\xa2\x60\x3c\x3d\x5d\x6e\x68\xdb\x1c\x94\x9b\x47\xfb\x4e\x09\x3a\xa2\x2a\xb5\x0a\x6d\x96\x5c\xe1\x71\xf5\x49\x3f\xe4\xf8\x59\xc1\x74\xeb\xf8\x94\xb5\x94\x5a\x3f\x70\xbb\xb5\x9d\xca\xc4\x72\xed\x51\xdf\x2b\xb2\xc7\xe3\x92\x77\xe8\x74\x64\x01\x52\xf5\x40\x3a\xb2\x96\xd2\x9d\xeb\xd7\x2b\x93\xca\xb4\x5e\x8a\xe7\xd5\xc3\xf1\x1c\xc3\xf0\xc3\xf1\x28\xdd\x29\xf8\xb1\x4f\xb1\xe7\xfa\xce\x48\x56\x8f\x8b\xd5\xf9\x7a\x11\x8c\x3f\x4a\xc7\x0f\x0f\x44\x28\xa1\x24\x11\xc1\x91\xe3\xdb\x4b\x89\x64\xe5\x94\x68\x6d\x81\x33\xc1\x87\xe1\xe1\x92\x1a\x2a\xa3\x10\xb7\x5b\xdb\xa5\xcc\xcd\xf6\xed\x90\x8a\x3d\x2e\xe3\x4c\x25\x24\x0e\xc0\x8f\xd2\xf3\x48\xac\xa5\xa6\x4b\x6e\xb7\xb6\x5d\x49\xcb\xf2\x65\x5d\x92\xf7\x7a\x5c\x14\x46\xcb\xc4\xfe\x69\x03\x5f\xed\x2f\x6b\xf6\xd7\xa5\x6a\xb7\x5b\x49\x5f\x78\x79\x2b\x2b\xf7\xb8\xf4\x34\x07\xf3\x23\xb1\x46\xf0\x63\x6e\xb6\x5e\x44\x49\xf8\xa2\x62\x87\xe1\x47\x6c\xbd\xc1\x8f\x0e\x65\x49\xb2\xf7\xb4\x6c\xf3\xb8\x58\xb4\xf7\x34\x82\xf1\x0d\x7e\x38\xf4\x08\x2e\x2a\x14\xf2\x71\x44\xc9\x71\x78\xcf\x49\xcb\xf7\x7a\x5c\x72\xb3\x6f\xed\x50\xfc\xf0\x40\x06\x4f\xd0\x24\xb7\x5b\xdb\xcb\x33\x68\xa0\x08\xa9\x9a\xd3\x13\xe0\x5f\xdc\x70\xfc\x8b\xab\xa3\x35\x34\xc6\xed\xd6\x36\xf3\x38\x85\xf2\x2e\x8f\x8b\xf2\x8c\xf3\x02\x07\xc8\x8a\xe0\x1f\x25\xb9\x68\x4f\x8f\x28\xc2\x22\xa7\x37\xf2\xf7\xec\x88\xc7\x45\xd9\x3a\x3d\x83\xf8\xe2\xe0\xc5\x5d\xbf\xbe\xbf\xa8\x17\x45\x9a\x93\x86\xe1\xcb\xa4\x06\xba\xc7\xe0\x4b\x5e\x92\x37\x5e\xee\xf5\xb8\xe4\x5e\x6f\x7c\xc0\xef\x39\x94\x2f\x51\x9c\x2f\xb7\xe9\x8c\x4c\xf2\x46\xc9\x95\xab\x3d\x2e\x79\x95\x77\xc3\x88\x72\xe5\xa2\x5c\x4a\x14\xf8\xf9\x09\x97\xcf\x4a\x55\xd4\xe6\x71\x49\x9b\x7c\xfa\x39\xda\x03\xe3\x50\x6c\x7f\x9c\x55\xa4\x06\xe2\x34\x78\xe4\x0d\x1e\x17\x39\xb5\xa3\x41\x7c\xd1\xcb\x2a\x5c\x8d\x49\xab\xe9\xc5\x4f\xdd\x5a\x82\x92\x9f\x78\x59\x65\x1e\x8f\x98\x03\x8e\x37\x78\x72\x45\x9e\xe2\x57\x53\xfa\xfa\xf5\x4a\x7e\xa2\x5e\xca\x20\x99\x16\x5e\x42\x31\x3e\xa5\x25\x54\x43\xff\xe3\xd6\xba\xb5\x7d\x2c\x82\xaa\xb8\xc2\xd1\xda\x05\x9d\x39\x41\x74\x1a\x45\x1b\x45\x39\xf4\x8a\xe0\x5d\xbb\x76\x84\x85\x50\x9d\xd6\xcd\xd5\x8e\xdc\x48\x29\xda\xa9\x6b\xc6\xd9\xa2\x9d\xe2\x71\x7c\x87\xa5\x0c\x8f\x4b\x8a\x97\x56\x6b\x9f\x0f\x1f\xc7\x41\x4a\x20\xce\x1a\xed\x33\x1e\xc7\xfb\xae\x9c\xe8\x71\x7d\x22\xff\xe4\x73\x9d\x87\xc5\x41\xf5\xaa\xc7\x21\xa5\x98\xb6\x91\xc3\xed\xd6\x36\x6a\x17\x44\x94\x74\xf9\x88\xc7\xc5\xd6\x9d\x33\xf2\xe8\xe7\x8d\x2e\x05\x39\xf4\xca\xfa\xf5\x7a\x21\x3c\x2e\x76\x44\x3b\x3d\x9c\x4e\xe6\x98\x4a\x33\xe5\x53\x9a\xdb\xed\x87\x7c\xd6\x4d\x51\x1e\x17\xeb\xfc\xf3\xd5\xf4\xbd\xae\x52\xb6\xc9\x67\xdd\xda\x11\x29\xdf\xe3\x92\x2a\x8c\x7b\x38\x46\xc0\x77\x91\x99\xeb\x07\xf9\xac\xdb\x77\x41\x8e\xf5\xb8\xc8\x21\xb5\x0e\x43\xcb\x38\xa3\x7f\xf8\xde\x05\xb7\x5b\xdb\xc3\xb1\x17\x08\xc9\x3d\x3b\x40\x57\x05\xcb\xf9\x92\x12\x8a\xa1\x12\x2e\x52\xf2\x67\xa5\xda\x29\xa9\x40\xe8\xc3\x9e\x21\x75\xdb\x2f\xb7\x39\x25\x94\xa6\x37\x0c\xc6\x4a\xb4\x2e\xca\x22\xb3\xc7\x25\xb7\x69\x1d\xfd\xba\x79\x68\x7b\xce\x2a\xa5\x04\x2a\x72\xbb\xb5\xe5\xcc\xfc\xa0\xd6\x1e\xac\x0f\x73\x86\xf6\x29\x39\xc5\xd2\x5a\xb7\x9b\x85\x3e\xe2\x7b\x5a\xde\xe2\x71\x51\x5c\x30\x5e\x70\x1f\x91\x53\x44\xad\x27\x05\x25\x63\x1e\xd1\xf2\xb4\x32\xb6\xd4\xe3\x92\x6a\xfa\xd3\x1d\xac\x13\x73\x8a\xb9\xa0\x33\x94\x69\x47\x24\x8e\x59\x36\x44\x9f\x18\x3c\x49\x5a\x45\x4e\xca\x17\x09\x97\x66\xfb\xb6\xc8\x19\x1e\x17\x9b\xe4\xfd\x48\xa4\x3b\x77\xb8\xb6\x3f\x77\x15\xcd\x35\x78\x52\x90\xe5\xfb\x81\xf4\xfc\x3e\xde\x05\xf9\x1e\x07\x89\x1b\xa2\x87\xf0\x30\xa3\x96\x8a\x84\x4e\x3c\xc2\xaa\xd2\x7d\xf9\x34\x57\xca\xe6\x94\x6b\x2d\xc6\xbd\x3b\xc3\xf1\x30\xa3\x96\xaa\x28\x54\x18\x21\x55\xe9\xbe\x64\xb9\xc5\xe3\xa2\x82\x81\xf8\xc1\x3a\x31\xa3\x96\xb6\x9e\xe1\xbd\x16\xab\x4a\xf7\x9e\x3e\x26\x74\xa2\x43\xc7\x1d\xcc\x97\x8c\x5a\x4a\x5e\xbf\x9e\xa7\xba\x5b\x4e\xf0\xb8\x28\x71\xc4\xbe\xb3\x81\x1c\x86\x4e\x0c\x49\xf6\x56\x0f\xd0\x89\x8e\xe1\xf8\xe2\x68\xa0\x79\x86\x4e\x0c\x49\xf6\x3e\xf8\x65\x74\x62\x68\xa2\x37\xe1\xcb\xea\xc4\xd0\xc4\xcb\x9d\xc1\x3a\xd1\x31\x54\x27\x3a\x5c\xb4\xed\x8c\x5b\x4b\xe6\xb8\x4b\x02\x3a\xd1\x31\x44\x27\x3a\x5c\x64\x5f\xbf\x9e\x13\x51\x27\x9f\x10\x3a\x31\x67\xa8\x4e\xcc\xa1\x5a\xae\x13\x3f\xd0\x76\xcb\xaa\x54\xcf\x75\xa2\xef\xd7\xd7\xd6\x89\x27\xb4\xfd\x1c\xbd\x5f\x27\xc6\x68\x63\xae\x19\xa7\x4d\x3b\xc5\xe3\xf4\xeb\xc4\x7c\x2d\x63\x04\x9d\x78\x25\xce\x36\xed\xbf\x78\x9c\x80\x4e\x5c\xa5\x15\x63\x70\x3b\xd2\xe3\xf0\x28\xad\x42\x27\x6e\xd7\xfe\x26\xa2\xe8\x3a\x31\x4f\xab\x04\xa1\x62\x88\x4e\xac\x20\xd7\xfa\xf5\xda\x79\xa3\xcc\x2e\x2d\x6d\x40\xba\x41\xba\x53\x3a\xeb\x76\xfb\x1e\x35\xf0\x8e\xfb\x4e\x0c\xd1\x0f\x01\xd1\xa6\x2c\xaa\x24\x97\xdb\xad\xfd\x4a\xdb\x2f\xf5\x52\x13\xd7\x9f\xf2\x59\x6d\xcb\xf5\xf4\x2f\xd2\x25\xaa\xd3\x7e\x2b\x65\x79\x5c\xd2\x6a\x72\x5c\x5f\xff\xc2\xe3\xf8\x0e\xc9\x4b\x3c\x2e\x8a\x96\x56\x6b\x7f\x1f\x9e\x2f\x24\xe7\xd0\x13\x54\xed\x76\x6b\x2b\xfe\x22\x5d\xa2\x43\xde\x16\x16\xeb\x71\xc9\xed\xda\x5f\x06\xeb\x17\x43\xda\x8d\xce\x42\x3a\x4f\xaf\x7c\xee\x71\xc9\x47\xb5\x43\xc3\xf7\x15\x72\x33\x15\xd0\x5c\xb7\xfb\x9c\xb4\xcd\xcd\x55\x21\x5b\xaa\x65\x8e\xa8\xfb\x4d\xcd\x54\x4e\xf1\x6e\xf7\x05\x69\x9b\x9b\xe6\x12\xa7\x60\xab\x36\x72\x3f\x51\x2a\x9a\xcf\x76\x69\x9b\x5b\x7b\x43\xde\xea\x71\x51\x2c\xd5\x5e\x65\x1c\xb1\x4e\xb4\x9c\x5d\x1c\x9d\x09\xed\xb9\x8d\xe3\x16\x04\xb7\x7d\x45\xaf\xcd\x82\x62\x0a\x15\xcc\x38\x2c\x1d\x2e\xd6\xe4\x12\x8f\x8b\xc5\xfa\xcc\x7a\xbb\x2c\x18\xae\xed\x17\x14\xd3\x38\xaa\xe0\xed\x92\x47\xb8\x24\x3d\x75\xc1\xe3\x92\x5d\xbe\x83\x20\x14\x0e\xd7\xf6\x0b\x8b\xc8\xae\x2b\x17\x69\xff\x72\xad\x87\x92\x85\x8e\x5e\xa9\xfd\x76\x98\x3c\x02\x82\x53\x50\x4a\x39\x62\xa0\xb5\x45\x3a\x52\xa4\x1d\x0c\xd6\x89\x05\x43\xec\xe6\x82\x62\xa9\xde\xed\x96\x0e\x17\xfb\xbe\xc7\x3a\x45\x9b\x2e\x1a\xaa\x0b\x8b\x8a\x28\x69\xfd\x7a\xe9\xe0\x72\xed\x84\x50\x24\x76\x9e\x96\x73\x18\x5d\xe8\xac\x36\xba\xb4\x63\xd2\xc9\x1c\x6d\x02\x5b\xe8\x71\xc9\x47\xbc\xe9\x08\xc6\x1f\xc0\x0f\x67\x15\x25\x50\xb1\x28\xdf\xc9\x1c\x2d\x54\x5e\xf1\x89\xc7\x25\x27\x7a\xdf\x1d\x8a\x1f\x1e\xc0\xcf\xa0\x45\x06\xbe\xef\x9c\x94\x23\xc5\x7b\x5c\xfa\x6c\xa9\xc8\xc3\xaf\x0d\x13\xa7\x9a\x0a\x85\x61\x21\xe2\x74\x50\xa6\x5c\xea\x71\x51\xa1\xb6\x13\x03\xe8\x0a\xd2\x87\xce\x6a\xda\xe0\x75\x6b\xc9\x1c\xbf\x34\xa0\x0f\x9d\x43\xf4\xa1\xb3\x9a\x32\xd6\xaf\xe7\x48\x1f\xb0\x7a\xc1\xbb\xec\xc1\xfa\xd0\x46\xd9\xf4\x32\xf5\xb8\xff\xa6\xb9\xc8\xcd\x47\x6b\xcc\xe3\x2d\x1a\x6a\x13\xf4\xb7\xc7\x2c\x7a\x85\x72\xdd\x6e\xed\xac\xf6\x2a\xc7\xd7\xda\x68\x89\xc7\x25\xd7\x91\xd9\xdb\x7d\x95\x38\x3f\x10\x22\x72\x5c\x3b\xc2\xe3\xf8\xce\x49\xd1\x1e\x97\x54\x4a\x17\x7c\xd2\x95\x38\x6b\x06\xea\xc3\x40\x9c\x7d\xda\x1f\xc9\x2d\x7b\xbd\x3b\xe4\x22\x8f\x6b\xbb\xfc\xa4\x6f\x21\x06\x8f\x3d\x03\xfa\x30\x10\x65\x8f\xf6\x17\x9e\x8d\x61\xfd\x6b\xbe\xc2\xa0\xb1\xe7\x15\x3d\x97\x45\x3f\x58\xbf\x5e\x7b\xdf\x28\xf4\x24\x9f\xbe\x36\x60\xf5\x80\x74\x45\x4b\xa6\xd5\x54\x4a\x39\x6e\xf7\x19\x6d\x17\x35\x49\xbf\x20\x07\x37\x29\x8f\xf9\x8a\x07\xe0\x07\xe9\x45\x1b\xad\xa6\x1a\x6e\x54\x7e\xa2\xed\xa5\x26\xa9\x57\x57\x8b\xbe\x9a\x21\x76\x48\x3f\x7f\xe6\x52\xab\xd1\xc7\xb4\xd2\x76\xf9\x0e\x2d\x5f\x5a\xe4\x71\x49\x85\xb4\x91\xf7\xa0\xc3\xc5\x71\x5c\x89\xd3\xa6\x1d\xa7\xed\xf2\x9d\xbe\x18\xb9\xc1\xe3\xda\x27\x9d\xf7\xed\x1d\x90\x4f\x30\x7f\x02\x51\x76\x69\xbd\x3c\x8a\x77\x33\x53\x3d\x2e\xb9\xc9\x77\x44\xc7\x1f\xac\x17\xe7\x52\xeb\xfa\xf5\xda\x51\xda\x2c\xdf\xdd\xec\x71\xc9\x1d\xbe\x66\x10\x1a\x87\xf0\x47\xa6\x46\x2a\xe0\xe9\x9e\xd4\x36\x53\x07\x15\x48\x35\x42\x35\x96\xe9\xfd\x40\x63\xb0\xbc\xe9\xe9\x36\x4a\xdb\xdd\x6e\xdf\x2f\xa9\x43\xfa\xf0\x23\x8f\x4b\x3e\xe5\xab\x0f\xc2\x1b\xd0\xbf\x34\x52\x36\x15\xb8\xdd\xda\x19\xed\x8f\xd4\x41\x8f\xea\xf6\xa7\xb6\x1f\x83\xf0\xfb\xf9\x68\x10\xa2\xfd\xd2\x0f\xea\xe0\xe3\x17\x79\x8d\xc7\x45\x99\x94\xac\x9d\xc5\x10\xda\x85\x2a\x35\x05\xa2\x6c\x3f\xcd\x63\xf8\xde\x65\x0d\x1e\x97\x94\x73\x69\x88\x2d\x1a\xb0\xa2\xf5\xbe\x82\xf6\xd3\x36\x29\xc1\xe3\x92\x9a\xb4\x23\x18\x69\x6c\x21\x37\x53\x1e\xa5\xbb\xdd\xa7\xa8\xc0\xcd\x55\x9c\xdc\x6b\xcc\xf9\x0e\xd7\x07\xc8\xcd\x94\xcb\x4d\xae\xf3\x54\xe0\x96\xaa\xb8\x8c\xc9\xb1\x5a\xf2\x55\x7d\x5b\x93\x85\x5e\xef\xa1\x02\x37\xb9\xa5\x49\xfd\xc4\x8c\xd4\x67\x18\xae\x2d\x2a\x70\x6b\x7d\xac\x43\xd7\xb8\x83\xec\x73\xa3\xcf\xc8\x29\x22\x90\x9b\xab\x23\xaa\x2b\xff\x94\x6d\xf4\xb8\xe4\x77\xbd\x89\x18\x3a\xb6\x50\x02\x3d\x68\x11\x85\x52\x83\x11\xe1\x92\xfc\xfe\x21\x8f\x4b\x2e\xf0\xee\x1e\x79\x2c\x52\x44\x93\xa8\xd2\xc0\xd7\x3c\x92\x6b\xa0\x8e\x1c\x29\x4e\xba\xae\x57\x79\x9c\x53\x94\x22\x37\x72\x3d\xaf\x75\x0f\xf4\xe7\x98\xfa\xfb\x19\xeb\x92\x22\xaa\xa3\x50\xb7\x96\x4c\xb5\x15\xda\x2e\xa1\x24\x05\xde\x20\x1d\xb9\xa4\x88\xd2\xd6\xaf\xe7\x38\x67\xb8\xb5\x3d\x70\x4c\xee\x34\x74\x64\x12\xed\xa5\x1e\xf7\xa7\xda\x63\x89\x4a\x3e\x57\x91\x97\xd5\x81\x76\x6d\x80\xcc\x58\x72\xd0\x5e\x21\x50\x1e\x6d\x43\xa2\x92\xaf\x1d\x25\xa7\xc7\x25\x6f\xf0\x5c\xae\x1f\x62\x0b\x3b\xfb\xe5\x36\x10\xe7\x94\xb6\x3b\x51\xc9\xf7\xf5\x08\xd1\x5a\x44\x7f\xbb\x7c\x74\xb0\xdf\xc2\xd9\xdf\xfe\xa3\xe8\x1d\x11\xe7\x88\xd6\x92\xac\x2c\xf1\x9e\xe2\xa3\xcb\x4f\xe4\x70\x6f\x08\x06\xfb\x46\x9c\x81\xf6\x3f\x89\x7e\xab\xf7\xd4\xda\xcf\x92\x94\xbc\x60\xe7\xc8\x00\xff\x82\x53\x97\x82\x78\x3a\xc8\x45\x5d\x14\xd8\x18\x2e\x0c\x1c\x77\x39\x03\xfa\x31\x89\x3a\x78\xba\x3d\x5a\xbe\x93\x49\x94\xcd\xd5\x63\xaf\xd7\x32\xc4\x4f\xe4\xec\xd7\x8f\x71\xb4\x8f\x8f\xd3\x2e\x6a\x8f\x24\xb3\xb9\xba\x7a\xf4\x4e\xc2\x60\xdf\xd5\x15\xfe\xc4\xd2\x01\xa3\xcf\xf9\x4e\x32\x5b\xa4\xb5\xf1\xd1\xae\x54\x4d\x11\xde\x86\x11\xe2\x38\x78\x9c\x5e\xe1\xee\xea\xd5\xb6\x3b\xd8\x02\xdf\x6a\x6e\x16\x74\x49\x15\xde\x13\x03\xf3\x09\xe6\x4f\x2c\xfd\xda\xe0\xcf\x2f\x92\xd9\x52\xef\x69\x16\xed\x71\xc9\x36\xef\x69\x0c\xf4\x49\x39\x03\x1e\x35\xfa\xf5\xfa\xf5\x1c\xf5\xf0\x26\xde\x03\x7a\xdd\x83\xfc\x7e\x06\x1f\xb3\xa5\x73\x6e\xb7\x6f\xd3\x42\x25\xdd\xe3\x62\xe5\x97\xb7\x0e\xf1\x27\x06\xca\x69\xa2\x44\x6e\x09\xba\xdd\x97\xb4\x95\x59\xd2\x6f\x69\x19\x85\x79\x5c\xf2\xde\x4b\xbe\xac\x81\xfe\xca\x7e\x33\x8a\x96\x90\x9b\x0a\xdd\x6e\xed\x92\xb6\x2d\x5b\x3a\xa5\xab\x47\xb1\x76\x68\x44\x39\x6b\xe5\x1d\x99\x76\x42\x6b\xce\x91\xce\x6a\x6d\xf2\x0e\x8f\x8b\xac\x94\x68\xf4\x19\x8e\x61\x78\x12\x88\xd2\xa1\xfd\x22\x57\x3a\xeb\xeb\x65\x75\x1e\x97\x64\xf5\x9d\xc1\x40\xff\xa5\x61\x86\x51\x22\xed\xe7\x3c\xc9\x96\xce\x8a\x3a\xe2\x88\x03\xfa\x6a\x67\xa0\xcf\xc8\xa2\x4d\xb4\xd4\xed\xfe\x40\xcb\x2b\xa7\x3a\x4e\x87\xec\xf1\x6d\xd3\x2a\x31\xc8\x0f\x1d\x30\xc3\x64\xca\xa5\x97\x79\xe5\x9c\xd2\x72\x2a\xe9\x5b\xd2\xce\x4f\x3d\x2e\xb9\x42\x9b\xa5\x55\x0c\xf4\x6f\x07\xe8\xc8\x95\x3e\x70\xbb\x7d\x0d\x95\x52\xb7\xe8\x4a\x6b\x7c\x2f\x0f\xf4\x9b\x5f\xe1\x61\x1e\x55\xd3\x63\x6e\xb7\xd6\xad\x75\x54\x52\x8d\x6e\x8a\x6a\xfb\x30\xc8\x2f\xdf\xcf\x0f\x83\x0c\xad\x43\x3b\x52\x41\xdf\xd2\xde\x62\x5d\x42\x0b\xf5\x0c\xf2\x6f\x07\xe8\xd0\x8d\x8c\x5f\x94\x91\x4b\xde\xee\x71\x51\xbc\xd6\x3b\x50\x3f\xdb\x8d\xbe\x82\x9a\x29\x8c\x56\xf3\xae\xce\xcd\x15\x95\x7c\xc0\xbb\x70\x88\xee\xe7\xb8\x0e\x03\xd9\x2c\xc6\x5d\x67\xdc\x2c\xfe\x84\xc7\x25\xc7\x79\x4f\x0e\x83\x1b\xe8\x27\x6e\xa2\x1a\xb7\x5b\xfb\xc0\x2d\x5d\x94\x54\x8f\x4b\x5a\xe8\x3b\x30\x32\xae\x5d\xd8\xc6\x3d\x6e\x2a\x12\xf4\x26\x68\x3d\x50\x50\xed\xef\x63\xdd\xaa\x86\x29\x98\x81\x59\x58\xc0\x65\x5c\x4c\x54\x8f\x8f\xb2\xa7\x88\x5b\xeb\xc3\xaf\xdc\xfb\x30\x5d\x5f\x8b\x2b\x05\x5d\x3c\x33\x65\x9c\x38\x82\x70\x3e\x39\xa6\x5e\x59\xe0\x19\x98\xfd\xab\xbe\x78\xa6\xae\x39\x65\xec\x84\xf8\xef\x4c\xb8\x29\xd9\x36\x65\xb2\xf9\xb6\xa9\xf7\x2d\x0d\xbf\x61\xde\x0f\x57\xbd\xf7\xd9\xfe\x8d\x5b\x7f\xf8\xc2\x4b\x2d\xda\x29\x55\x7a\xc8\xf7\x9b\xd4\xdb\x12\xd3\xd3\x13\x67\x3b\x2b\xd7\x77\x46\xdf\x5e\xf0\x6d\xc9\x4a\x11\x94\x90\x9f\x5f\x94\x7a\x87\xe6\x2b\xd7\x0a\x32\xe6\x84\xae\x19\x15\x5e\x70\xef\x7d\x4b\xe8\x16\x1a\xf5\xf6\x3b\x07\x7f\x3f\xe6\x83\x23\x24\x35\x36\xbe\x99\x23\xcf\x4a\x48\x9a\x3d\x67\xe6\x42\xc7\xca\xa7\xc9\x69\x71\xed\x99\xf0\x63\xfd\x5c\xea\x7f\x45\xb9\x02\x13\x6a\xd7\x55\x2e\x26\x3d\xe4\x3b\x99\x7a\x5b\xe2\xfc\xf9\x89\xc9\xce\x15\x2f\xde\x3a\xb5\xf3\xf6\x7f\xb0\x5c\x21\x13\x5e\xda\x6c\xf9\xd6\x3f\xb1\x5c\x57\x26\x09\x2d\x62\x4d\x90\xf3\xcb\xd6\xd7\xaf\x9d\xb3\x79\x7d\xdd\x96\xfa\x54\xe5\xa5\x2f\x57\x61\x74\x40\x5c\xab\x9e\x94\x30\x4b\xce\x19\xfb\xf4\x2f\x03\x15\xf6\xaf\x29\x97\xf2\x65\xeb\xab\x57\xbf\xfe\xfd\xb6\xd4\xa7\x56\xd0\x98\x2f\x57\x63\x03\x0b\xf6\x84\x51\x65\x46\xb9\x4c\x69\x98\x22\xf6\x54\x2e\xe2\x7a\xea\xda\xe5\x1a\x30\x2d\x2f\x0f\x28\xe5\x97\x6f\x69\xfb\xaa\x47\x2f\xf9\xda\x83\x0f\x86\xad\x1a\xb7\x7b\xed\xb7\xb7\x8d\x0e\x94\x37\x81\xb7\xb9\xf9\x33\xae\xab\xcd\xb1\xad\x8e\xa4\xd9\xb3\xbf\xfe\xec\x37\xbc\xe7\x8c\x22\x4b\x21\x42\x42\x93\xe7\xcc\x5c\x38\xe7\x6b\x4f\x93\x33\xd2\xb5\x27\xfa\xc7\xf8\x97\x97\xf7\x7a\x5a\xe0\x08\xe5\x9d\xff\x25\xda\xe2\xc8\xe5\x75\x24\xf2\xf2\x86\x44\xbf\xb4\x39\xf2\x5b\xff\x8a\xf2\xfe\x03\x2d\x73\x84\xf2\xc6\x39\x67\xcf\x98\x7f\xbd\x6d\x74\x98\x02\x7b\xe7\x2c\x9c\x39\x27\x59\xc8\xf3\x98\xa7\x7f\xf9\xaf\xaa\xdf\x7f\xa0\xc5\x8e\x50\xde\x79\x5f\xaa\xed\x0e\x5f\xe0\x44\x47\xa0\xc0\x4f\x04\x6a\x18\x60\xfe\x3f\xfb\xfb\xa4\x66\x55\x33\xf6\x80\x27\xe8\x2b\x14\x86\x74\x7a\xe1\xf6\xc0\x65\x7c\xfa\xd5\x39\x46\xd5\x4d\x1e\xd0\xbf\xc5\xef\x5d\x94\x3f\xa3\xf4\xc6\x89\x8f\xa7\xb4\x34\x3d\x2c\xaa\x85\x1d\x1d\xa4\xee\x2f\xb7\xc8\x21\x5e\xcf\xb2\xd2\x1b\x42\xd6\x8f\xb1\xec\x56\x33\x02\x3a\xf2\x1f\xa6\x43\x67\xe9\xe4\x01\xfd\xd1\xf8\x20\x3a\xbe\x21\xb8\x75\x0d\x3a\x14\x73\xa0\x17\x1a\x81\x8e\xc1\xca\xf7\x6a\xfc\x08\xea\x3f\x7e\x18\x44\xc8\x57\xfa\x19\x32\x50\x9b\x5e\xbe\x65\x38\x8e\xfc\xc3\x74\x5c\xe1\x47\x90\xbe\x7f\x3e\x88\x8e\x67\xfa\x19\x72\x35\x3a\xae\x70\x84\xf3\xe4\x77\x9c\x16\x53\x1a\xc6\x62\x12\x12\x85\xb5\x3d\x68\x6d\xd5\xf5\x49\xcb\x2d\x03\x84\x7b\x4a\xbf\x8e\x1e\x2a\x37\x4a\x9b\x21\xc1\xdf\x0d\xd6\xc4\x97\x97\x0f\x60\xd5\x33\x46\xbb\xfd\x27\xd0\xa7\x73\x6d\x20\x7d\xf6\xab\xc8\xd3\x60\xfa\x74\xcd\x39\x90\x3e\xe5\x1e\xa3\x99\x5d\x93\xbe\xc1\x8a\xe2\xfa\xf8\x77\xd3\x15\x1d\x38\x54\xce\xfa\x09\xa4\x0d\xc1\xaa\xce\xf3\xb7\x61\x39\x78\x1d\x3c\xbc\x36\x8d\xc3\xf1\x30\xf9\x6a\x32\x38\x80\xc6\x2b\xda\x69\x20\x8d\xfd\x5c\x04\x18\x76\xf8\xfb\x58\x9d\xaa\x89\x7b\xbd\xf4\x9b\x70\xc3\xed\xe1\x66\xab\x58\xde\x1b\x67\x9f\x4c\x91\xe2\x2e\x8c\xab\x59\xed\x3b\xf6\x51\xe2\xbf\x7f\x6f\x62\xec\xbe\xb8\x89\xda\x65\xff\x5f\x3f\xf9\xc1\x30\x06\x3a\x5d\x90\x0a\x7d\xad\x9a\xfb\xaf\x7f\x7f\xf6\xc4\x2b\x2f\x9d\x7d\x46\xfb\xb5\xf6\xde\x65\xf9\xcf\x23\x1a\xe4\xff\x27\x74\x05\xfa\xfc\xc1\x74\x7d\x7f\x18\x03\xfb\xfa\xe8\xba\x62\x50\x7f\x19\xba\x46\xb2\x9a\x87\xe3\xd7\x10\x03\x79\x44\xc2\x86\x37\x88\xff\x4f\xe8\x52\xae\xc2\xaf\xa1\x06\xee\x75\x12\xf6\x44\x90\xae\xd3\x69\x33\xa5\xc1\x82\xa9\x98\x8d\x5b\x47\xa2\xed\xea\x0a\x66\x04\xee\xbd\x34\x82\x02\xbc\x8a\xdc\xb1\xa3\xc3\x69\xc2\x7e\x9b\xf4\x9f\x43\xef\x48\x52\xf8\xd2\x08\x0a\xf1\x2a\xf2\x38\x98\xde\x41\x36\xe5\x3f\x46\xef\x48\x96\xe3\xd5\xe9\xbd\x69\xb0\x91\x78\x75\x82\x07\x6a\x4a\xc3\x28\xfc\xe7\xd0\x3b\x92\xd4\xbe\x34\x92\xb2\xbc\x9a\xfc\x0e\x20\x78\x38\xa3\x4e\xd1\x6d\x07\xd3\x46\xb1\xef\x30\x0a\x71\xb0\xeb\xd6\x83\x32\xe0\xd6\x3f\x63\x35\xf9\x60\x3d\x1e\x84\xc3\xad\x88\xbd\xa9\x37\x27\x25\xdf\x3a\xfd\xe6\xd4\xac\xbd\xf6\x9c\x47\xaa\x2d\x41\x5a\xfc\xb7\xa9\xd3\xf9\xab\xe9\xa9\xca\xa9\x17\x5e\x68\x49\x49\x4a\x4d\x9c\x33\x7b\xb6\xf4\x75\xcb\xca\x87\xa2\x0a\x3d\x0b\x82\x95\x38\xfb\x81\xf1\x76\x10\x6d\x31\x23\xd0\x36\x42\xdf\x32\x22\x6d\x3f\x0f\xa2\x8a\xf2\x12\xf7\x3e\x50\x5d\x36\x1c\x6d\xde\x8c\x01\xbd\x9f\x25\xea\xb1\x12\x4b\x6d\xa1\xb6\x31\x40\x9c\xe0\xdd\xef\x0c\xfa\xc6\x60\x02\xa6\x60\x16\xe6\x05\x7a\xc2\x21\x75\x7b\x7d\x4c\xbc\xa5\x7a\x4c\xc1\xf2\x5d\x53\x56\x8d\xfb\x8f\x6f\x7e\x6b\xfb\x98\xeb\xe0\xa6\xda\x39\x37\xa5\xea\xa9\x6f\x7f\x4b\xeb\xbb\x3e\x96\x0e\xa2\xf9\xe6\x6b\xd1\x7c\x1d\xcc\x1d\x9e\xe6\xab\x70\x79\x08\xcd\xd7\x62\xb5\x62\xb4\xab\x8d\xc6\x1d\x9d\xe2\xc4\x9c\x11\x7b\x81\x61\x05\x37\xe8\xd9\x70\xbd\xd4\x20\xc1\xfd\x63\x80\xd4\xe1\xdb\xd4\xc5\x21\x12\xac\x39\xfe\x19\xb4\x0e\xe5\xed\x55\x69\x6d\x1f\xc8\xd6\x6b\xd2\x4a\x3f\x1a\x4e\x86\x83\xe8\xb5\x0a\x5b\xee\xb6\xab\x6a\xad\xab\x09\xf6\x55\x08\x7f\xe9\x2a\x82\x7d\x75\x6e\x2b\x7f\x1c\x5e\xc2\xaf\xb0\xfc\x9f\x53\x86\x6b\x33\x7f\xf8\x32\x5c\x4f\x2d\x0c\x29\xc3\xd0\xaa\x20\x1c\xd5\xea\x95\x50\xe5\x18\x26\x07\xdd\xfb\xcf\x8c\x3b\x89\xf4\x0b\xdb\x02\x67\x78\x1c\x6d\x8c\x09\x4d\xf9\xb0\xe6\xef\xa4\x1c\x3f\x58\x7a\xeb\x9d\x5f\x2d\xaf\xfa\xfe\xcf\x0f\x1f\x50\xda\x0f\x14\xad\xf2\x7d\xea\x8d\x3f\xfc\xce\xc4\x57\x2c\xab\xbe\x26\x77\x1f\x6c\x7e\xfb\x43\x7d\xbe\xa6\x4b\xab\x57\x72\xf5\x7b\x7e\xf5\xdb\x5d\xa3\xc9\x1e\x94\xb2\x93\x6c\xe3\x23\xc3\xbb\x7a\xe4\x31\x21\x61\x7b\xba\xf6\x8b\x34\x57\x4a\xde\xdf\x84\x84\x2b\xed\x97\x57\x6e\x85\x5f\xf2\x78\x0a\xde\xe8\x16\xc9\xb2\x83\xfe\x9d\xde\x73\x20\xec\xf7\xf7\x31\xaf\x72\x4c\x9c\x52\xe1\xb0\x47\x5a\x82\x48\x9c\x44\xb6\xe0\x12\xc0\x3a\x15\xfb\x7f\xd1\xde\xde\xfa\x5a\xf3\xbe\xc3\x07\x7e\xf1\xc2\xe4\xd1\x8e\xb3\xab\xfe\x4e\x8a\x76\x5a\xf3\x6a\xda\x59\x29\x24\x72\xe2\xcf\xde\x78\xe3\xe7\x74\x94\x13\xbc\x45\xea\x39\xf0\xc0\xd7\x7d\x9f\x6a\xd6\x2f\xb4\x0f\x68\x92\xbe\x5f\xb7\xd5\xdf\xc7\xda\xd4\x18\x44\x88\x9b\xd8\x8d\x2d\xce\x66\x45\x6c\x7e\x64\xb6\xa9\xd3\x9c\x46\x4d\x5f\xb9\x69\x71\x4a\x78\xab\xd6\x77\xda\xa3\xbd\xf9\xfa\x41\xed\x7f\xfe\x7e\x51\xbb\xb8\x8f\x96\xfc\xf8\x07\x1d\x7b\x56\x16\xbe\xb4\x7d\xcb\x06\xed\x38\x35\x4b\xbb\xfe\xf4\xbf\xef\xbc\xa6\xbd\x6f\x0f\x89\xec\x7a\xfd\x9d\x0f\x3f\xfc\x83\xf6\xee\xf7\x9e\xdf\xf2\xfd\x2d\xdf\xf9\x56\xdd\x6a\xb1\x7c\x18\x32\x2a\xd9\x51\xe9\xa8\x31\xae\x9e\xa8\xef\x8c\x1e\x69\xb0\x50\x39\xcc\xe0\x60\x88\x27\xe1\xca\x38\x40\x4f\xfb\xf8\xd5\xd3\x0e\x98\x5a\x95\xc3\x18\xf8\x43\xd2\xbe\x62\xcb\x0f\x4b\xf7\x48\x46\x7b\xe5\x70\x46\xfa\xd0\x11\x7f\xc0\x1e\xd7\xd3\xee\xbe\x7a\xda\x4a\x10\xdd\x43\x0d\xed\xa1\x89\x07\xd9\xd4\x92\x76\x91\x9d\xa4\x0a\xd5\x8a\xd1\x62\x5f\x56\x50\x7b\x8c\xea\xdf\xa4\xa7\x5d\x4c\xbd\x79\xe6\x6c\xde\xfa\x4e\x26\x3c\x11\x7b\x32\xbe\xfd\x0e\xa5\xc6\xd8\x44\xf3\x48\xb4\xf3\xd5\xbb\x22\xd3\x0f\xa5\x88\xb4\x76\xb2\x93\xb4\x54\xed\xd6\xcf\x06\x14\xbb\x75\x74\xc2\x06\x2a\x2b\x6d\x67\xfd\x13\x2b\xbe\xf1\xb0\xab\xdb\xde\x31\xef\xd6\x40\xbb\x56\xd5\x89\x8b\x6a\xbe\x91\x31\xb1\xbb\xa4\x9c\xe2\xaf\x28\x4c\x59\x3b\xc1\x2e\x51\xb2\xda\x2d\x6c\x92\x89\x43\x4f\x6a\x18\xb0\xff\xe7\x84\x54\xe2\x6b\x4d\xbd\x39\xee\xd6\x5b\xe3\x6e\x4e\xa5\xd5\xa9\xd3\xf9\xb7\xe9\xa9\xec\x52\x63\x23\x3d\x9e\x92\x94\x94\x32\x67\xf6\xec\x39\x46\xc8\xd3\x6e\x62\xbd\x54\xa5\x76\x8b\xfd\xc3\x49\x23\xee\x88\x1b\x29\xb7\xa6\x31\x55\x45\x89\x5f\xcd\xcd\x9e\x92\x34\xfb\x86\x07\xc7\x7e\x6d\x69\xc2\x57\x16\xdf\x35\x35\x39\x39\x6c\xdc\x30\x14\xf4\x3e\xfe\x74\x4c\x6c\x4c\x4a\xd2\x13\x4f\xc5\x4c\x8b\x49\x99\x49\x8d\x43\xa8\xe1\xfc\xdb\xc5\x7a\xa9\x50\xec\x15\x9b\x32\xf2\xfe\x3c\xfb\xf8\x18\x8a\xb4\x4d\xd7\x76\x85\x56\x7c\xf5\x96\x25\x77\xdd\x3e\x39\x61\x7a\x58\xf9\xe8\x47\xee\x8b\xbb\xe7\xae\xac\x98\xe9\xb7\xdc\x10\xf7\xbe\xad\x6a\x56\xed\xc5\xfe\x2c\x1f\x7f\x3a\x66\x5a\xcc\x8c\x54\xc9\x6a\xb9\xe3\x1b\x69\x13\x5e\xbb\xce\x7c\xf4\x9d\x8c\x91\xaa\x69\xc4\x7c\x1e\x4d\xfe\x9a\xed\x7d\xe7\x67\x83\xf3\xa1\x98\x09\x69\xdf\xb8\xc3\xb2\xf8\x67\x90\xf4\xba\x33\x8d\x31\xee\x4f\x11\xe7\x1c\xe8\xad\x40\xd4\xd4\xeb\xbd\xc9\x4d\x75\x9f\xf2\xca\x91\x60\x29\xdb\x13\x7d\x40\xf0\xe0\x4a\x1c\xfd\x16\x4a\xd1\x4a\x0d\x39\x3c\x21\x95\x68\x8b\x6a\xd2\x23\xde\x9f\xd2\xf2\x30\x8f\xf7\x69\xf4\x0b\x0f\xd8\x2c\x33\xb7\xdd\x0d\x59\xdb\xc9\x8e\xd3\x52\xd3\x18\x98\x71\x13\x6e\x16\xd2\x37\x99\xa2\x44\x4c\x13\x17\xc0\x38\xc9\x71\xa5\xee\x62\x07\x4a\xa3\xa3\xc6\x9e\x5a\x9d\xe2\xca\xdc\x7c\x73\xc7\x8c\xe7\x4d\xc6\xee\x31\xba\xa7\x7f\xf3\xd8\x85\x1b\x6d\xb9\xce\xd4\x7b\x6c\x37\x2e\xf8\xce\xdd\x8b\x36\x69\x5f\x99\xa9\xef\x22\x2b\xeb\xdf\xa9\xc6\x65\xe9\x38\x3b\x4e\x49\x6a\x5b\xb0\x9c\x2a\x23\x49\xce\x71\xa9\xc4\xd7\x36\xcc\x2e\xb5\x98\xc6\xc6\xbe\xc1\x3b\xd4\xfa\xeb\x4b\x6d\x13\xa7\xe8\x8f\x28\x17\xd6\xc8\x11\xab\xea\x36\xa9\x64\x48\x35\x65\x8b\x3b\xc7\x24\xed\x38\x3b\x49\x49\xea\xde\x2b\xe7\xa0\x28\x83\x28\xd5\x56\xa4\x27\xce\x4a\xbd\x75\x66\x62\xba\x6a\x6d\x6c\xec\x99\x97\x92\xee\x10\xc7\xa0\xf0\xb8\x6a\x3c\x25\x85\x48\xd7\x13\xd7\x54\x3d\x20\x2e\x43\x31\x3b\x21\xf5\xf4\xdb\xf2\x33\x02\xbb\xb4\xaf\xd3\x58\x28\xbe\x1e\xe3\x60\x88\xe5\x3b\xd4\x0e\xf8\x72\x74\x0c\x35\xbc\x86\xa7\x63\x90\xa1\x35\xd2\xa8\x21\xc8\xa6\x62\xa8\x64\x27\xa4\xa3\xfd\xe3\x42\x9b\xae\xe9\xaf\x65\xb0\x56\x5e\xc5\x40\x0d\x1e\x5d\x0d\x6b\x8b\x5e\x57\x9e\x43\x8b\x5c\x79\x15\x03\x7e\x98\xd1\xe6\x95\x42\xca\x28\x66\xfb\xa5\x1e\xc3\x8f\x19\x3b\x78\x5f\xfe\x48\x03\xf3\xe2\x6b\x0c\xc4\x47\x70\x55\x5e\x19\x73\x7f\xc9\x7c\x03\x3d\x75\xf1\xd5\x1d\x16\x23\x78\x71\x0d\xdf\xc4\x35\xf2\x1c\xc9\xc9\x53\x7c\x55\xa7\xce\xf0\x9e\xed\x7e\xff\xcd\x97\xcc\x73\xdc\xb0\xe5\x1c\xec\xf8\x1a\xde\xdb\xdf\xef\xe3\x22\xb4\xb1\x5e\xb9\x4f\x69\x11\xe7\x2c\x38\xac\x91\x26\x5b\x9c\x4d\x87\x36\x79\x5e\x9e\x35\xf9\xf5\x64\x6b\x72\x47\xb2\x55\x59\x63\xb5\xee\x29\x2f\x17\x67\xfe\x12\x87\xd0\xf4\xc7\x0e\xde\xfd\x9d\x87\x6e\x98\xf7\x77\x29\x46\xac\x2e\xc3\xdb\x63\xbe\x79\x32\x10\x5e\xde\xe8\x3b\x11\xfa\x42\x48\x29\x80\x90\xc0\x89\x36\xfc\x6f\x48\xa9\xef\xc7\x40\x68\xfb\xe5\x8d\x9e\xd5\xa1\x2f\x18\xcf\xfb\x3f\xa3\xbe\xc6\xba\x21\x96\xfb\x31\x0b\x20\x71\x88\x43\x93\xbc\x10\x6b\x95\x04\xd8\x59\x13\x5c\xea\x4e\x94\x29\xa7\xb0\x92\xba\xb1\x56\x2a\x47\x9e\x54\x8e\x74\x56\x81\x7c\xd6\x84\x72\x29\x16\xf9\x52\x13\xf2\xa4\x58\x34\x49\x1e\x58\x58\x13\xca\x58\x13\xda\x59\x13\x4a\x59\x13\x8a\x58\x13\x12\x58\x13\x56\xb3\x26\x54\xb3\x26\x2c\x35\xde\x97\x0b\xfc\x58\x64\xf0\xef\xac\x09\x35\x3c\x94\xeb\x10\x6d\x4a\x46\xad\x32\x09\x50\xec\xe8\x52\xc2\xd0\xa0\xf4\xa2\x8b\xd5\xa0\x8b\xc5\xa1\x4b\x79\x17\x0d\xca\x67\xe8\x92\xda\x91\x27\x25\xf9\x4b\xd8\x45\x74\xb1\x64\x74\x99\x32\xd1\xa5\x5a\xd0\xa5\x66\xa0\x81\xf5\x1a\xa1\x07\x5d\xac\x0c\x15\xac\x06\x16\xe5\x24\x3a\x58\x37\x60\xaa\x46\x34\x6b\x43\x08\x73\x03\xac\x09\xb9\xd2\x0e\xb4\x70\x9a\xa5\x1d\xa2\x9c\xb9\xf2\x46\xbf\x97\xb5\xd0\x1a\xd6\x80\x62\xd6\x87\x56\xb9\x17\xd5\xac\x0f\xd5\x6c\x0d\xaa\xa5\xc3\x88\x11\xdf\x2f\xa0\x55\x32\xa3\x59\x32\xfb\x37\xb1\x2c\xf1\xbd\xd5\x54\x8f\x56\xfe\x9c\xe9\xf8\xad\x1c\x4f\xce\x45\xab\xdc\x83\x0a\xe9\x2c\xac\xec\x02\x76\x30\x33\xa0\x2e\x42\x14\x4b\x43\x2c\xb3\x40\x92\x8f\x60\x89\x1c\x8a\xb9\xac\x82\x3e\x91\x43\x91\x29\x78\x62\xf0\x9e\x35\x61\x3f\x6b\x12\xcf\xea\x58\x13\x26\x71\x1c\x36\x11\x75\xac\x85\x92\xd5\x5d\x28\x93\x4e\x21\x93\x45\x20\x4f\xc4\x69\x42\x1e\x7f\xc6\xe0\xf7\xc8\x2b\x51\x2f\x9e\x75\x23\x59\xea\x86\x4d\x94\xc5\x8b\x56\x25\x1d\xd5\x9c\xdf\xd4\x8d\x49\x52\x37\x72\x64\x49\xc4\x5f\xa2\xe6\xe1\x4e\x35\x0f\x33\xd5\x3c\x4c\x91\xeb\x60\x17\x7c\x1f\x06\x4c\x63\xfc\x1a\xaf\x0b\x51\x0f\x41\x20\xb5\x63\x9e\xa8\x8b\x76\xbf\x8f\x7f\x57\x7a\x91\x1e\xa8\x87\xc1\xc0\x9a\xb0\x86\x87\xbc\x2e\x82\x41\xd4\x45\x2f\xba\x94\x31\x68\x15\x7c\x1f\x06\xd4\x4f\x50\x2c\xea\x62\xcd\x40\x90\xcc\xfe\xf7\x24\x33\x7e\x24\x99\xfd\xaf\x4a\x66\xff\x5f\x05\xff\x03\xf5\x30\x18\xb8\x9c\xe9\xef\x77\x0c\x00\x0b\x24\x51\x67\x16\x48\xbc\xac\x3c\xbf\x21\x61\x18\x1a\x78\xfe\x23\x86\x5c\x46\xfb\x44\x98\xce\xce\xa3\x5a\xf0\x67\xcd\xb5\x43\x2e\xcf\x22\xde\x48\xe1\x67\xe8\xe2\xe5\x51\x3e\x03\xd8\x05\x44\x48\xed\xfe\x0f\x25\xb3\xff\x05\xa9\x1d\x33\x24\xb3\xff\x0f\x52\x3b\x26\x4b\x66\xff\x6f\x45\x1d\x98\x61\x37\xc2\x56\xf6\x11\xf2\xd8\x24\x34\xf3\x36\x22\xe4\x94\xb7\x93\x2c\xb4\x0a\x48\x46\x97\x64\xc6\x0f\x8d\xb0\xc8\x08\xf5\xe7\x5b\x45\x38\x51\x32\xfb\x3f\xe3\xf5\xc8\xf3\x1e\x1c\x2a\x6e\xc8\xfd\xcf\xf4\xf6\x56\x3d\x38\x34\xad\x44\x83\xa9\x11\x55\xbc\x0d\xf2\x76\x60\x84\xa5\x46\xf8\x0d\xde\x2e\x79\xdb\x18\x31\xac\x81\x45\xb4\x9b\x41\xa1\x90\x97\x0b\xd8\x71\xbd\x21\x6f\xef\xa2\xcd\xb9\x85\x6e\x93\x02\xed\x9e\xb7\xbd\xc1\xa1\xb4\x4d\xb4\xdb\x08\xa5\x17\x16\xd6\x27\xea\xb3\x55\xb1\xa0\x83\x7d\x84\x5d\x4a\x18\x32\x84\xfc\xab\x7a\x1d\xab\xf5\x02\xa7\x42\xe8\x83\x1e\x54\xb1\x1a\xd4\x2b\x9f\xa0\x8e\xed\x43\x15\x8b\xf3\x7f\xc2\x9a\x70\x50\xd4\xe1\x26\xc0\x54\x87\x56\xe9\x28\x3a\xa4\x76\x64\x05\xea\x41\x32\x23\x86\x15\xf8\x2f\x86\xa4\xa3\x43\xb5\xf8\x3f\x11\xbc\xcc\x44\x83\x9a\x85\x06\xf6\x19\xaa\x43\xb6\xa2\x41\x3d\x82\x6a\x45\xcf\xa7\xd5\xd0\x65\x25\x72\x0f\x8a\xd8\x26\x2c\x92\xea\xfc\x1b\x05\x5f\xb6\x5d\xe1\x8f\x9a\x8e\x0e\xa5\x0c\x3b\xd4\x4c\xe4\x70\x5d\x27\xca\x5a\x00\xa9\xbf\x9c\x7b\x90\xcd\xf6\xa0\x5a\xf6\x22\x4b\xf6\x62\x2e\xdb\x84\x52\xfe\x4c\xee\xc3\x42\x79\x1f\x16\xb1\xbd\x68\x65\x56\x3a\xcc\xac\xd8\xcf\xac\x58\xcb\xf5\x50\x68\x01\xba\x46\x6d\x45\x57\x48\x2b\xaa\xd5\x12\x74\xa9\x99\xe8\x62\x56\xb4\x86\x2c\x44\x57\x48\x2c\xba\x4c\x12\x5a\x03\x6d\x44\x6a\x87\xcc\xdb\x61\x40\x06\xae\xb7\x8e\xd8\x1a\x54\x0c\x6e\x6f\x5c\xdf\xf0\x36\x3f\xb8\x3d\x04\xf8\x37\x58\xde\x44\x39\xbc\x98\xc4\x65\x3d\x98\xe6\x40\x3c\xd3\x6a\x74\x29\x8b\xf4\x3e\x42\xc8\x70\xcc\xc0\x7c\xfa\x69\x1e\x44\x07\xab\x41\x73\x70\x7b\x95\xda\xfd\x6b\x25\xb3\x3f\x59\x6a\x17\x79\x1d\x1d\x42\x87\x07\x3b\xe5\x5c\xd8\x02\x72\x3f\xa4\xac\x83\xe5\x7b\x1f\x72\x65\x2f\x2c\x41\xed\x5c\xd7\x23\xc5\xa8\x35\x74\x96\xa8\xbb\x20\x7a\x04\x1d\x23\xb5\xbb\x7e\x3a\x0c\x79\x97\xc7\x20\x4c\xf9\x1c\xad\xf2\x44\x9d\x37\xa6\x2e\x54\x73\x10\x7a\xdd\xd0\x5d\x2c\x19\x16\x4e\x0f\xa7\x4b\xf4\x49\x9b\xc1\xe4\x06\x44\x2b\x76\xc4\x28\x27\x61\x61\xa7\x81\xfe\xf2\x1b\xfa\x44\xb5\x19\xf5\xe1\x81\x45\xce\x85\xa5\xbf\x7d\x35\x60\xa7\x78\xde\x87\x57\x8d\xfe\x73\x21\xcb\x40\xa9\xf1\x8c\xeb\xec\x0a\x0e\xea\x44\x54\xc8\xa7\x51\xc8\x65\x4f\xb1\x63\x21\xeb\x16\xba\x7c\x13\xeb\x43\x95\xc0\xdb\x82\x6a\xde\x5f\x32\xb3\xdf\xc3\x2e\x60\xa7\xd0\xe9\x7a\xbf\x6b\x91\x3a\xb1\x4b\xda\x84\x45\xb2\x8a\x50\xa9\xdb\xdf\x27\x85\xa1\x55\xc9\x14\x7d\xf0\x4e\x03\x5a\xd9\x05\x7f\xa7\xe0\x67\x98\xde\x17\xa8\x9f\xa0\x5a\xcd\x44\x8d\xd2\x8d\x2a\x39\x17\x31\x41\xd0\xca\x41\xa4\xd9\x89\x58\x56\x87\x56\x0e\xa2\xdf\x36\xfb\x3b\x0d\x38\x2b\x99\xfd\x31\xd2\x59\x24\x1a\x7d\xb9\x85\x71\x3d\x7f\x0e\x3b\xfb\xfb\x74\x0b\x20\x1f\x03\x44\x3b\x2b\xc0\x12\x2e\x8b\xb2\xd7\xdf\x2b\x57\x20\x5a\xae\x80\x43\x84\x87\x8d\xfa\xe1\x7a\xa6\x1b\x45\xbc\x8c\x4a\x34\x2f\x93\x3f\x9d\x65\x21\x42\xae\x37\xec\x06\x23\x8e\xa9\x15\xd5\xa6\x93\xa8\x0e\xc9\x44\xb5\x1a\x01\x2b\x8b\x80\x55\xfd\x48\x40\x8c\x92\x83\x56\xf6\x2e\x5a\x59\x04\xc0\x3a\xd0\xaa\x30\x7f\x2f\x07\x16\x8d\xed\x1c\xe8\xbc\xbf\x4b\x3a\x8d\xed\xd2\x69\x24\x73\x90\x0f\x60\xbb\x32\x11\x71\x72\x0d\x2c\x54\x8e\x68\xe9\x0c\xa2\x79\x18\x00\xc0\xdf\xc4\x41\x5a\x02\xb3\xb4\x04\x56\xc3\x26\xe3\xb0\x44\xc0\x41\x62\x1c\x00\x7f\x2b\x6b\xa7\x04\xc0\xff\x2a\xa0\xbd\xc6\x7f\x03\xda\x7f\x02\x7e\xbb\x01\x8b\x0c\x68\x32\x20\x3e\x18\xd8\x41\x8a\xe1\xb6\x13\xdb\x4e\x2b\x69\x33\x6c\xec\x20\x49\xac\x19\x67\x00\xed\x28\xe0\x4f\x92\xab\x60\xa1\xf3\xd8\x2e\x67\xa2\x52\xde\x84\x04\xe9\x02\x16\xca\x85\x68\x1e\x09\x00\xed\x47\x80\x76\x3f\x2f\x0f\xa0\xed\xd6\xc1\x0f\x0e\xd2\x6e\xd4\x00\xfe\x34\x40\x6b\x32\x60\x2b\xe0\xff\x37\xc0\x5f\x30\x10\x34\xa7\x01\x49\x80\xf7\x1e\xc0\x67\xd2\xd3\xf5\x8e\xd3\xcb\xa6\x71\x9c\x5f\x03\xfe\xef\x02\xda\x9f\x00\x1f\xe7\xc3\x14\x40\x7b\x5e\xc7\xe3\x3c\xf0\x87\x02\x97\x4f\x01\xda\x61\x1d\xfc\x65\x80\xbf\x3c\x28\x0c\xf0\x27\x47\x07\x4e\x8f\x3f\x71\x28\x8f\x44\x7e\x9b\x75\xbb\xdc\x97\xac\xe7\xc7\xf3\xf2\x7f\x03\xf0\xcf\x05\xfc\xf7\x1b\x3c\xe7\xe5\x69\x30\xca\xff\x23\x9d\x3e\x91\xf7\xb7\x8d\x34\x1c\x9c\x2f\x80\xb6\x47\xc7\xf5\xc5\x00\x5a\x2f\xa0\x55\xea\x79\x8a\xfc\x1d\x7a\x1a\xfe\x24\xc0\xcf\xd3\xba\xcf\xa8\xd3\x57\xf5\x74\x78\x9e\xa2\x2c\x3f\x05\xb4\x4c\xfd\x3d\x2f\xa7\x9f\x7f\x77\x1b\xb0\xcb\xe0\x6b\x16\xe0\x8b\x05\xfc\xf9\x80\xdf\x6a\xc4\x4b\x37\x7e\xe7\xeb\xb8\x62\x30\xa2\x02\xfe\x38\x40\xab\x1d\xf8\x9e\xa7\x29\x20\x3f\x28\xce\x69\x40\x3b\x6e\x94\xb7\x1d\xd0\x4e\x00\xda\x25\x40\xeb\x04\xb4\x77\x01\x2d\xd4\xe0\xd9\x09\x83\x8e\x56\xea\x44\xbc\x01\xdb\xb9\xee\xe1\xfa\x8d\x87\x62\x9c\xb1\x9d\x2e\xb1\xed\x64\xe6\xba\x8f\xdb\xc2\xec\xbc\xff\x1d\x75\xb5\xff\x1d\xb9\xc5\xff\x47\x75\x8d\xff\xcf\x4a\x93\xff\x6d\x1e\x4a\x9d\xfe\xbf\x04\xc6\x1f\xdc\x26\x62\x3b\x11\x2f\xf4\x5f\x13\x72\xb9\x7e\x56\x33\x50\xcf\xed\x2c\xd1\x17\x9d\x06\x02\x63\x0f\x56\x8d\x6c\xc3\xbe\xed\xe2\xf6\x2c\xef\xa7\xb9\x5e\xe5\xba\x51\xad\x42\x05\x1f\x77\xa8\x55\x58\xa9\x66\x22\x97\xdb\xca\x42\x67\xf2\xf6\x7e\x1a\x85\x42\xb7\x75\x62\x17\x3b\x87\x1d\x42\xff\x73\x5b\x38\x16\xa1\xdc\xb6\x10\x7a\xf2\x8c\x61\xd7\x1e\x41\xb5\xc0\xe3\x76\x5c\x81\xff\x22\xb7\xed\x59\x09\x20\x9f\x40\x95\xe8\xbf\xb2\x10\xcd\x7a\xb1\x43\xe0\x9f\x47\xb5\xdc\x03\x0b\x4f\x53\xe9\x46\x35\xab\xf0\x7f\xa2\x46\x09\xfb\xa0\x46\xea\xf4\xff\x55\xe4\xc5\xf5\xff\x39\xfd\x19\xeb\x40\xb9\x62\xc6\x18\xd6\x04\x28\x2d\xfe\xb7\x45\xd8\x8d\x2a\xf5\x24\xa2\x14\xbb\xff\x73\x75\xa2\xd1\xb7\x9c\x43\x03\xab\x46\x35\xcb\x42\x97\xbc\x07\x6d\xf2\xe7\xfe\xcf\x59\x0d\x4a\xd9\x41\x7f\x1f\x4b\xf0\x97\x73\x9b\x86\xeb\x61\xa5\x0c\x35\xdc\x96\x51\x1c\xe8\x62\xc5\x68\xe5\xf6\x0b\xb3\x23\x59\xf0\x33\x1f\xd6\xfe\xf4\x6a\x10\x2f\x6b\x88\xe1\x79\x30\xbd\xbe\x44\x5f\xc0\xed\x21\xf9\x73\x54\xcb\x17\x91\xc6\x7a\x0d\x7b\x2c\x0c\x0d\x9c\xdf\xca\x71\xa1\xd7\x43\x02\x76\x19\x0f\x03\x63\x12\xe5\x33\x58\x78\xbd\x29\xb1\x68\xe0\xfd\xad\x3e\x3e\xc1\x3c\xde\x77\x99\x1a\x20\x99\x76\x1b\x38\x17\xd0\xa5\xc6\xe2\x28\xd3\x10\xc5\xeb\x4c\xf4\xb1\x7d\xe8\x0a\xd4\xbb\xe2\xc6\x18\x9e\x9e\xda\x03\x89\xf7\xd3\x1c\x57\xe0\x5f\x40\x97\xb2\x1b\x92\xa0\x43\x97\x87\xfe\x3a\x37\xc6\x48\x16\x9e\x66\xa0\xce\x39\x8e\xb2\x19\x2d\x21\x39\xe8\x0a\xc9\x47\x97\xb2\x0e\x66\xf5\x34\xba\x14\x1b\xba\x14\x33\xd2\x43\x2a\x45\xde\x89\xa2\x7f\x3f\x86\x55\xbc\x7f\x90\x6b\xd1\xca\x76\x22\x4e\xf4\xf5\x80\x24\xfa\xc9\x58\xb4\x72\x60\x69\x68\x65\xcd\x08\x53\x2e\xa1\x95\xf7\x1f\x82\x87\x9a\xe8\x3b\xc4\x78\x55\x3e\x8e\x78\x31\x96\xe9\x46\x15\x1f\x6b\x8a\x3e\xf0\x1c\xb6\x98\x92\xd0\x6a\xca\x40\xab\xd2\x88\x58\x75\x2e\x5a\xd9\x61\xb4\x72\xde\xaa\x6d\xa2\xcf\xb3\xf6\x8f\xab\x2e\x20\x82\xe7\x2f\x78\x2f\xfa\x41\x31\xd6\xed\x13\x75\x72\x00\x61\xa6\x28\xd1\x17\x47\x70\x3a\x04\x3d\x3c\x2f\x09\xad\x21\x71\x58\xa3\x6e\x03\x94\x72\x44\x28\x16\x44\x98\x4a\xd0\xa5\x9c\x47\xab\x52\x2b\x6c\xee\x10\x53\x15\xba\xd4\x74\xb4\x2a\x3d\x88\x52\x62\x30\xc6\x74\x06\x5d\xea\x31\xb4\xb2\xbd\x48\x97\xfb\x10\x2d\xda\x86\x2e\x9f\xba\x2d\x66\x01\x98\x15\x08\x84\xa3\x8e\xa0\x21\x64\x23\xaa\xd5\x46\x34\x28\x59\xa8\x0e\x31\xa3\x5e\x75\xa3\xaa\x3f\xdf\x58\xd4\xcb\x7c\xec\x75\x06\x15\x6c\x15\x8e\xb2\xed\xe0\xed\xfd\x34\xdb\x4e\xbc\x7f\x71\x9b\x3e\x41\xbc\x69\x27\xe2\xd5\x6c\x74\x29\x59\x82\x27\x49\xec\x30\x22\xd8\x39\x5d\xb6\x58\x26\xba\xe4\x06\xb4\xb2\x74\x24\xc9\x75\x30\x0b\xb9\x5d\x88\x56\x53\x1a\x24\xb5\x58\x97\x01\x51\x0f\x45\xe8\x62\xab\xd0\x2a\xda\x7f\x9e\x08\x93\x78\xff\xad\x6c\x40\x18\xf3\x22\x56\x0d\x45\x17\xb7\x47\xd4\xb5\xe8\x52\xce\xa1\x35\x64\x33\xba\xd4\xf3\x68\x55\xd3\xd0\xa0\xd8\xae\x8c\x19\x59\x0d\x22\xe4\x6e\xc4\x0b\x3d\x60\x36\xec\x75\x33\xa0\x8c\x41\x08\xab\x44\xac\xfa\x11\x22\x94\x63\x88\x57\x9a\xd1\xc2\x2e\x61\x0b\x97\x21\x76\x52\x84\x5d\xec\x20\x5a\xd5\x63\x70\x2a\x79\x48\x0c\x84\x5c\xce\xb9\xac\x72\x79\x51\x1a\xd1\xc5\xea\xd1\xaa\x1c\x86\xc4\xf6\x22\x4c\xc8\xe7\x25\xb4\xaa\x63\xd0\xc5\x6d\x07\x91\x16\x97\x89\x02\x74\xa9\xa1\x68\xe5\x71\x47\xb2\xc1\xfb\xc7\xaa\x7c\x7c\xc3\x6d\x75\x23\x0c\xe4\x15\xe0\x4b\xc0\x06\xe7\x6d\x84\xcb\x45\x7f\x18\xb0\x4d\x33\x07\x86\x5c\xf6\x45\xdb\xd6\x84\xfd\x24\x0d\x0e\x03\x34\xb2\x74\x74\x71\x79\xe4\x6d\x46\xc8\x6d\xa0\x7e\xc2\x10\xc2\xca\x11\xcb\xda\xa0\x0a\x9f\x4a\x1f\x5c\xc2\xd6\x77\xc2\x65\x4a\x46\x95\x29\x1d\xd9\x6a\x1d\x72\x15\x33\xb2\x59\x0e\x72\x4d\x67\x01\xf5\x0c\xc2\x42\x62\xd0\x65\x2a\x10\xe3\x59\xbd\x3e\x3a\x10\xa1\x64\x20\x9e\xb5\x63\x25\xd7\xb5\xca\x5e\x48\xac\x0d\x61\xa6\x46\x40\xad\x43\x98\xca\x75\xc0\x06\xb4\x9a\x16\x22\xd1\x14\x0a\xab\x28\x0f\xcf\x27\x30\xb6\xbc\x80\x2e\xde\x16\x42\x22\x20\xa9\x4d\x08\x0b\xd9\x8f\x2e\x13\xd0\xaa\x7c\x2e\x74\x10\x97\x77\xde\xd6\x5b\x99\x13\x16\x65\x0f\xcc\xea\x27\xa8\x60\x8b\x60\x61\x89\xa8\x63\x9d\x68\x63\x9d\x58\x24\x77\xa0\x4d\xfe\x04\x05\x92\x1d\x6d\x92\xea\x6f\x61\xd1\x68\x93\xdd\x48\x50\xde\x45\x1b\xbb\x80\x36\x25\x02\x75\x2c\x11\xd9\xec\x24\xec\x06\xa8\xa6\x46\x54\xb2\x0a\xac\xe2\xef\xc4\x7b\x86\x36\xe6\x44\x32\x07\xb9\x03\x09\xac\x53\xd8\xcd\xb9\x6a\x0e\x72\x79\x28\xc6\x19\x97\x10\x2f\x9f\x40\x81\x18\xf3\xb5\xa2\x8c\x85\xc2\x2a\xbb\xd1\xc6\xdf\x09\x5a\x18\xda\x14\x07\x56\xb2\x1d\x98\x24\x7f\x24\xf8\x12\x26\x5f\x42\x8b\x7c\x09\x11\xac\x02\x2d\x72\xb5\x80\x2a\x56\x86\x6a\x56\x87\x16\x29\x0d\xf9\x74\xc6\xbf\x5b\x3e\x86\x16\x79\x21\x5a\x94\x52\xb4\xb0\x26\xb4\xb0\xed\x68\x61\x6d\xa8\x66\x16\xac\x94\xdb\xd1\x22\x1f\x17\xf1\xe2\x58\x05\xb6\x2a\x6b\x11\x2b\xd7\x61\xa9\x5c\x87\x0d\x72\x27\x2a\x94\x38\x94\xca\x9d\x68\xe4\xdf\xe5\x06\x01\xa5\x72\x08\x0a\x65\x0b\xb2\xe5\x4e\x94\xd3\x31\xac\x93\xf3\xd0\xa8\x6c\x40\xa3\x7c\x0c\x8d\x72\x3b\x2a\x64\x86\x2c\x11\x72\xe8\x44\xa3\x54\x84\x64\xf9\x18\x36\xc8\xc7\x50\xa8\x6c\xc0\x06\x39\x11\x11\xd2\x49\x84\xc9\xa7\xd0\x28\xa7\x21\x5a\xde\x87\x72\x56\x8a\x0a\xb9\x02\x12\x4f\x4f\xda\x29\xd2\x12\x78\xfd\x38\xed\xd8\x10\xc0\x31\x55\xf3\x71\x8c\xff\x00\xaf\x67\xe9\xb0\xff\x82\xa9\xde\xff\x01\xbb\xe0\xff\x80\xf5\xf9\xdb\xe5\x5c\x7f\x87\xd4\xe9\xef\x90\x7b\xfc\x17\xa5\xb3\xfe\x1e\xf9\x08\xb2\x58\x1f\xda\x58\xac\x28\x73\x81\xa9\x07\x56\x63\x9c\x12\xca\xfa\x04\x5f\xf9\x78\xc1\x12\xf0\x0b\x4a\x87\x11\xa3\xa6\xa3\xca\xf0\x03\xe4\xf5\xfb\x0e\xfb\xc4\x58\x24\x4f\x8c\xc3\xca\xfc\x9d\x42\x27\xa4\x21\x56\x8c\x29\x74\x7f\x64\xbf\x2f\x52\xbe\x60\x8c\x9d\x92\x75\xfd\x2c\x6c\x1c\xb3\x18\xf3\xec\x10\x75\xcb\xf9\xc9\x50\x21\xe7\x62\xa9\xe0\x91\x05\xd9\xd2\x42\x24\xd1\x31\xff\x31\xce\x53\xf9\x18\x36\xd2\x31\xc4\x49\xd9\xd8\x28\x59\x91\xcb\x81\x8e\xf9\x1b\xe9\x28\x1a\xe9\xa8\xff\xb0\xd4\xa9\xf3\x5b\xf0\xf2\x98\xff\x82\xe0\xfb\x69\x9d\xf7\xac\x14\xe5\xb2\x84\x52\x3a\xe6\xbf\x60\xf0\x3d\x4e\x6e\xc7\x42\xb9\x0b\x1b\xe4\x23\x06\xef\x2f\x21\x8f\x83\x5c\x8c\x3c\x39\x06\x89\xf2\x2e\x54\x00\xda\x0e\xc3\xde\x5c\x6b\xd8\x8e\x27\x74\xbb\xbf\x3f\xcc\xd4\xc1\xbf\x34\x60\x33\xf6\xeb\x24\xbb\xd1\xff\x0f\x0e\x87\xfa\xdf\xae\x1a\x5e\xaf\x5f\x8e\xc5\xa1\x8b\xd7\xd3\x30\x7e\xb8\xc1\xe1\x52\x76\x01\xf3\x03\xbf\x0d\xff\xdc\xf3\x52\x3b\xe2\x25\xb3\xff\xf3\x7e\xbf\xdb\xe0\x50\xf7\xb9\x6d\x67\xc9\xfe\xbf\x4b\x66\xff\xfb\xfa\x6f\xff\xef\x8d\xf0\x55\x6e\x5b\x70\xb9\x18\x1c\x8e\xe4\x93\xbb\x96\x3f\xae\xdf\x2f\x60\xd8\x51\xfd\xe1\x40\xff\xdc\xf6\x81\xa1\xff\x0f\xd7\xf4\xd3\x5d\xc3\x5f\xf7\x65\xfd\x76\xc2\x6f\xc5\xe5\xde\x08\x03\x3a\xf6\x5a\xa1\xf0\xe9\xa7\x89\xbe\x40\x0f\x03\xfe\x88\x11\x7c\x7d\xa2\xae\xce\xc2\x6a\x8c\xdd\x25\xe1\xbf\xda\x86\x56\x65\x0f\x3a\x46\xf4\x01\xeb\x61\xec\x35\xde\x5f\x33\xbc\x0e\x19\xcc\x65\x6b\x0c\x7b\x76\x98\xf7\x86\x8f\xb7\xde\x08\x5f\xb9\x46\x9d\xe7\x8f\xf8\xde\xf0\x35\x5e\x2b\x1c\x5c\x47\xfd\x7e\xc6\x6b\x84\x03\x7c\xae\xc3\x85\x01\x7d\x36\x02\xf4\xcf\x3f\xf4\x89\x41\x23\x29\x47\x0c\x38\xe6\x7f\x9b\x83\x18\x17\x0d\x03\x4a\x2c\x48\x89\x06\xa9\x05\x20\x35\x07\xa4\xda\x74\x08\xf8\x90\x46\x02\xb5\x19\xa4\x36\x81\x4c\x27\x40\xa6\x2e\x90\x69\xaf\x01\x27\xfd\x6f\x9b\x3a\xfd\x6f\x4b\x9d\xf8\xbe\xd4\x89\x97\xa4\x4e\xbf\x26\x75\xfa\x2f\x4b\x9d\x48\x95\x3a\x71\x83\xd4\xe9\x7f\x55\xea\xf4\x37\xc9\x3b\x41\xf2\x56\x10\xeb\x00\xb1\x56\x10\xeb\x33\xe0\xa2\xff\x6d\x01\xc3\xcd\x49\xf0\x7a\xd8\x07\x52\x79\x7e\x1e\x90\xe9\xfc\x95\x7c\xc5\xf8\xec\x2a\xa0\x1c\xd0\xe3\xa9\xa7\x40\xa6\x28\xff\xdb\x7c\x0c\x77\x55\x68\x07\xa9\xef\x82\x4c\x17\x0c\x38\x08\x32\x1d\xe5\x79\xf9\xdf\xe6\x10\xe0\x7b\x80\x8f\xfd\x3e\xb7\x4e\x2c\x94\x3a\xd1\xdc\x4f\xb3\x91\x7f\x20\xdd\x6b\xd5\xa3\xe9\x03\x80\x43\x48\x1b\x28\xa4\x13\x14\xe2\x36\x60\x93\xff\x6d\x0e\xd7\xaa\x97\x51\x65\xa0\x51\x85\xa0\xd0\xcd\xa0\xd0\x0d\xa0\xd0\x5a\x03\xb6\xfb\xdf\x0e\x5d\x77\xed\x72\x8f\xaa\x07\x8d\xda\x02\x0a\x6d\x37\x60\x0d\x28\x74\x23\x4f\xc3\xff\x36\x87\xeb\x92\xc1\xc0\x3c\xd8\x07\x80\x64\x46\x23\xdb\x4e\xe7\x44\x78\x10\x1f\xb3\x16\x5c\x18\x8e\x6e\xc5\xea\xef\x56\x22\xfc\xdd\xea\x36\x7f\xb7\xba\xd1\xdf\x1d\xb2\x17\x5d\x6c\x3b\x65\xb0\xed\x54\xc1\x0e\xe2\x82\xd4\xe9\x7f\x4f\xea\xf4\xff\x49\xea\xf4\x1f\x92\x3a\xfd\xbf\x91\x3a\xfd\xaf\x48\x9d\xfe\x1f\x8a\x39\x9d\x76\xcc\x90\xd7\xf8\xbb\xe5\x5d\xfe\x6e\xb6\x9d\x12\x02\x71\x86\xc8\x41\xaf\x01\x81\xdf\x6e\x7d\x1c\xa1\xb4\xf9\xbb\x95\x3d\xfe\x6e\xc5\x0d\x62\xdb\xe1\xd5\x81\x9a\x86\xe5\xd1\x71\x7f\xb7\xba\xc6\xdf\xad\x9e\xf0\x77\xab\x6b\xfd\xdd\xa3\x54\xe4\xb2\xed\xf4\x89\xe8\x9f\x8c\x89\xe4\x40\x28\xed\x06\x24\x00\x54\x00\xb0\x3a\xe1\x47\x01\x6d\x05\xd0\x1d\x98\x4b\xf6\xf7\xe8\xfe\x1f\x7f\x2f\xa0\xe5\x88\x79\xe1\x26\x31\x4f\x99\xc7\x80\xbc\x10\x03\x58\x05\x8d\x92\x17\xf9\xbd\x01\xff\xa3\x04\x64\x04\xfc\x92\x1c\xe4\x7c\x4c\xe4\x21\x8b\xc6\x5a\x16\x8d\x7a\x59\xc2\x76\x35\x1f\x4d\x46\xba\xb9\x80\x3f\x22\x00\x3c\xff\x51\x95\x28\xa3\x6e\xac\x95\x17\x62\x2d\xdb\x8f\xb5\x52\x3d\xf2\xa4\x7a\x2c\x91\x35\x34\x31\xf8\x3d\x14\xaa\xd5\x89\xf9\xe6\x09\x82\xc6\x40\x5c\x73\x10\x44\x48\xdd\x88\x93\xba\x61\x91\xba\x91\x2e\x75\x23\x5e\xea\xc6\x5c\xa9\x1b\x76\xa9\x1b\x36\x39\x11\x2b\x85\xcd\xda\x60\xd8\x9c\x39\x88\xe3\x76\x2a\x6b\xc2\x22\x63\x3e\xbb\xc6\x98\xeb\x5e\x28\xec\xb9\x26\x58\x54\x07\xb6\xa9\xbb\xb1\x5b\x29\x82\x45\xcc\x09\x36\x21\x89\x35\x21\x86\x35\x21\xce\x74\x04\xc9\xac\x09\xd1\x1c\x4f\xd8\x18\xa7\x01\x56\x06\x8b\xf0\x1f\x34\x61\x07\x6b\x42\x3c\xa0\x4d\x55\x1b\xb1\x96\xc5\xa3\x2a\x24\x1e\x47\xd4\x5d\x28\x53\x93\x60\x53\x33\x91\xcb\x2e\xa2\x5c\x39\x83\x50\xd9\x85\x74\x63\xfe\x36\x59\xcd\xc3\x1d\x6a\x1e\x6c\xc6\x9c\x6e\x39\x4b\x44\x56\x08\x68\x07\x03\x99\x07\x87\x02\x76\xa2\x94\xed\x44\xbc\xf2\x09\x3a\x95\x31\xc8\x66\x4d\x28\x0f\xf0\x89\x95\x21\x56\x69\x41\xad\xa9\x87\xb6\x28\x87\x29\x4a\x8e\x46\x28\x6b\x42\x89\xf0\x09\xef\xd6\xe7\xef\x05\xf4\x60\x3b\x6b\x42\x25\xeb\x91\x6c\xac\x87\x98\xb2\xdb\xff\xb9\x02\xea\x55\x76\x4b\x1b\xc5\xf7\x21\xe1\x60\xa0\x93\xfa\x3b\x1e\x72\x08\x7e\xf7\x65\x9f\x5f\x0f\x00\x03\x41\xea\x51\x76\xa3\x5c\x7c\xef\x01\x58\x0f\xea\x59\x0f\x54\xa9\x07\x2b\x39\x70\x99\x37\xf5\xd1\x76\x53\x1f\x35\x06\x42\xb6\x9b\x97\x17\xbb\xd8\x61\x94\xb2\x1e\xec\x65\x3d\x88\xe7\x20\xf5\xa0\x26\x24\x81\xda\x42\x2a\xe9\x84\xa9\x80\xb2\x54\xd0\x49\x15\x94\xc7\x32\x90\xa6\x64\x20\x8d\x1d\x46\x39\xb3\x20\x93\x01\x9d\x2a\xe7\x7f\x05\xca\x59\x32\x2c\x7c\xac\xc0\x92\xfd\x1e\x31\x46\xf0\xa0\x4b\xd8\x22\xdc\x36\x09\x45\x97\x12\x8a\x56\xc5\x89\x2e\x31\x2f\x61\xd8\x2e\x62\xee\x25\x16\x30\x6d\x13\x3e\x93\x28\xc6\xe3\x2f\x44\x97\xdc\x8e\x56\xa5\x1b\xd5\xd2\x3e\x58\xaf\xf8\xdf\xb5\x33\x80\x76\x5e\x3e\x8b\x4d\x1c\xa4\x38\x34\x05\x80\x3f\xd7\x01\x5f\xf0\x3a\x97\x9b\x50\x2e\xc5\x61\x27\x07\x96\x03\xb0\x13\x88\xe1\x60\x6a\xd4\x01\xf0\x7e\x04\xf8\x3f\x07\xbc\x7d\x81\xd6\x1e\x02\xe4\x73\x60\xdb\x71\x9c\x81\xd6\x32\x50\x15\x03\xd5\x9b\xdc\x20\xd9\xc2\xf3\xf0\x31\xc0\x5b\x09\x5c\xde\xa8\x87\xde\x72\xc0\x5b\x1d\x04\xe5\xd4\x82\x44\x12\x6b\xbe\x05\xad\xef\xf2\xf6\xca\x0a\xd0\x3c\x08\x72\x59\x01\xf2\x8c\x90\x43\x96\x6c\x46\x16\x2b\x80\xc3\x80\x25\xac\x00\x89\xac\x00\xd9\xb2\x59\x84\xb1\x41\x10\xc7\x0a\x90\x24\x9b\xc5\xf7\x49\xac\x00\x51\x41\xf1\xf8\xf3\x78\x23\x7e\x4e\x10\x14\xcb\x66\x11\x0e\xa6\x23\x80\x97\x15\xc0\x35\xf0\x92\x58\x01\xe6\xb2\x02\x64\x04\x40\x36\x8b\xd0\x31\x18\x64\xb3\x08\x73\x06\x83\x6c\x46\xc5\xe0\xb4\x83\xd2\x1f\x4c\x47\x81\x01\x85\x81\xef\xb2\x19\x45\xac\x00\xce\xc1\x20\x9b\x45\x98\x6d\xa4\xdb\x0f\x06\xff\x56\x1b\x30\x37\x00\xb2\x59\x84\x8d\x83\x61\x04\x3a\x06\x97\x63\x89\x6c\x16\x3c\x4a\x0a\x2a\x33\xe7\xf7\x24\x83\xcf\x49\x46\x7d\xf4\xd7\x8f\x51\x2f\xd9\x46\xfd\x2d\x09\xe2\x53\xa2\x41\x6b\x6e\x70\xfd\x1b\x74\x0f\xa4\xe3\x1a\x36\x88\xd4\x29\xfc\xfa\xc1\xf0\xbb\x60\xb8\x96\xad\x35\x38\xde\x10\x5b\xac\x13\x47\xf9\x18\x4c\x69\xc5\x7e\x65\x0c\x5a\x65\x3b\x2a\x83\x01\xd0\x2e\x02\xda\x4e\x63\xac\xdb\x64\xcc\x57\xec\x32\x7e\x9f\x30\xde\x1d\x37\x9e\xf1\xf0\xb8\x6c\x47\xb1\x01\x81\x74\x8a\x83\x81\x6d\x47\x9b\xd1\x0c\x6f\x1e\x04\x07\x00\x9a\x02\x48\x1f\x03\x8c\x01\x4a\x2a\xa0\xe6\x03\xea\xf3\x80\xfa\x21\x60\x4a\x05\x4c\xcf\x01\x21\x66\x20\xa4\x08\x08\xd9\x02\x84\x5c\x04\x46\xdd\x0c\x8c\x7a\x13\x08\x9d\x06\x84\xbe\x09\x8c\x6e\x01\xc6\xe4\x00\x63\xa7\x01\x61\x0c\x08\xcb\x01\x6e\xc8\x06\xcc\xd3\x00\xf3\x2e\x20\x7c\x06\x10\x9e\x0f\x84\x6f\x01\xc2\x0f\x01\x11\x2d\x80\x65\x0c\x60\x79\x0a\x88\xcc\x01\x22\xff\x04\x8c\x2f\x01\xc6\xff\x1e\x88\x5a\x08\x4c\x98\x02\x4c\x78\x1e\x88\x66\x40\x74\x19\x10\xfd\x0e\x70\xe3\x4d\xc0\x8d\x87\x80\x89\x45\xc0\x4d\x0c\xb8\xe9\xdb\xc0\xa4\x1c\x60\xd2\x25\x60\xf2\x3b\x40\xcc\x2c\x20\x66\x0f\x30\x05\xc0\x94\x77\x00\xeb\x1c\xc0\xfa\x3c\x60\xed\x03\xa6\x66\x03\x53\x9f\x01\xa6\x7e\x08\xd8\xa6\x00\xb6\x25\x80\xad\x05\x98\xf6\x22\x10\x5b\x01\xc4\x5e\x04\xa6\x1f\x02\xe2\xbe\x0d\xdc\x3c\x0b\x88\x9f\x06\xc4\xbf\x01\xdc\x92\x0a\xdc\xf2\x0e\x90\x90\x0d\x24\x3c\x03\xcc\x58\x02\xcc\xf8\x10\x48\x7c\x16\x98\x99\x03\x24\x4d\x00\x92\x9e\x07\x66\x15\x01\xc9\xd3\x80\xe4\x43\xc0\xec\x09\x80\xbd\x10\xb0\x1f\x00\xe6\xcc\x03\xe6\x6c\x01\x1c\x45\x80\xe3\x45\x20\x65\x09\xe0\x2c\x32\xe0\x4f\x40\x6a\x07\x30\xf7\x59\xe0\xd6\xc7\x80\xb4\x59\x40\xda\x53\xc0\xbc\x3d\x40\xfa\x2c\x60\x7e\x09\x90\x91\x0d\x64\x3c\x0f\x64\xfc\x09\x58\x70\x13\x70\xdb\xe3\xc0\x6d\xcd\x40\xe6\x2c\x20\xf3\x2d\xe0\xf6\x22\x60\xe1\xcd\xc0\xc2\x67\x80\x3b\xe6\x00\x77\xec\x03\xb2\xcc\x40\xd6\x33\x40\xd6\x5b\xc0\x9d\x45\xc0\x9d\xbb\x80\xec\x3d\xc0\x5d\xbb\x80\xbb\xe7\x01\x39\xd3\x80\x9c\x3d\xc0\x3d\x73\x80\x7b\xde\x04\x72\x3b\x80\xc5\xdb\x80\x25\x8f\x01\xf7\x5a\x80\x3c\x33\x90\xd7\x06\x7c\x65\x21\xf0\x95\xf3\x40\xfe\xef\x81\xaf\x3e\x05\x14\x4c\x00\x0a\xde\x00\xee\x6b\x06\x0a\x2b\x80\xfb\x1f\x07\x96\xa6\x02\x0f\x00\x78\xe0\x3d\xa0\xa8\x0f\x78\xd0\x0b\x14\x2f\x04\x1e\x4a\x05\x1e\x7a\x0f\x28\x79\x1c\x78\x78\x02\xf0\xb0\x17\x28\x7d\x06\x58\x66\x06\xca\xa6\x01\x8f\xa4\x02\xe5\x39\xc0\xf2\x27\x81\x8a\x3e\xa0\x32\x1f\x78\xf4\x0d\x60\xe5\x34\xe0\x6b\x16\xe0\x6b\x5e\xa0\xea\x63\xe0\xf1\x8f\x81\x27\xcc\xc0\x13\x8f\x01\x4f\xbc\x05\xd4\xcc\x01\x6a\xde\x03\x9e\x3c\x00\xac\x7a\x03\xf8\xfa\xb3\x40\xed\x3c\xe0\xa9\x09\x40\xdd\x0c\xe0\xe9\x59\xc0\xd3\x7b\x80\xfa\xe7\x81\x67\x0a\x81\x86\x9b\x80\x86\x4b\x80\x0b\x80\x6b\x1b\xf0\x6c\x19\xb0\x7a\x09\xb0\xfa\x1d\xe0\xdf\x3e\x04\xd6\x1c\x00\xd6\x86\x00\x6b\xdf\x00\xdc\x16\xc0\xfd\x26\xf0\xed\x27\x81\x75\x73\x80\x75\x17\x81\xf5\x6f\x02\x1b\x5e\x04\x9e\x5b\x02\x6c\x1c\x03\x6c\x7c\x13\xf8\xce\x1f\x80\x4d\x2d\xc0\xf3\x6d\x40\xe3\x42\xe0\x85\x29\xe0\xdd\x17\x5e\x34\x03\x2f\x76\x00\x2f\xb5\x01\x9b\x9f\x04\xbe\xbb\x05\xd8\xb2\x00\x78\x79\x1e\xb0\x35\x1b\x78\xe5\x49\x60\x5b\x0b\xf0\xbd\xf3\xc0\x76\x2f\xd0\x3c\x01\xf8\xc1\x0c\x60\xc7\x02\x60\xc7\x9f\x80\x7f\x6f\x03\x5a\x1e\x07\x7e\xb8\x00\xd8\xb9\x00\xf8\x11\x80\x1f\x3d\x07\xfc\xe8\xf7\xc0\xae\x7d\xc0\x8f\x97\x00\xbb\x6f\x06\x76\x5f\x02\xfe\xa3\x05\xf8\x8f\x3f\x01\x7b\x76\x01\x3f\x69\x01\x5a\x53\x81\xd6\xb7\x80\x57\x9f\x04\xda\x6e\x06\xda\x9a\x81\x9f\x5a\x80\x9f\x3e\x0e\xfc\xf4\x22\xb0\xb7\x10\xd8\xfb\x31\xf0\xb3\x12\xe0\x67\x7f\x02\xf6\x65\x03\xfb\x0e\x01\x3f\xb7\x00\x3f\x7f\x0f\x68\x7f\x11\x78\xad\x02\xe8\x98\x01\x74\x9c\x07\x7e\x71\x08\xd8\xff\x1c\xf0\x7a\x0e\x70\x20\x04\x38\xf0\x26\xf0\xcb\x67\x80\x83\xcf\x02\xbf\x7a\x0a\x38\xf4\x4d\xe0\xf0\x73\xc0\xaf\x9f\x02\x8e\xb4\x01\x6f\x3c\x03\x74\x5a\x80\xce\x4b\xc0\x6f\xb6\x01\x5d\xcf\x02\x6f\xde\x0c\x1c\x9d\x06\xfc\x76\x02\x70\x6c\x1a\xf0\xd6\x0c\xa0\xbb\x0c\x78\x7b\x0b\x70\xbc\x19\x78\xa7\x05\x38\x51\x02\xfc\x67\x33\xf0\xee\x2c\xe0\xbd\x79\xc0\x7b\xef\x01\x3d\x6f\x01\xbf\xeb\x00\x7a\xdf\x00\x7e\x5f\x08\x9c\xb4\x00\x27\xfb\x80\xf7\x3f\x06\x4e\xbd\x07\xfc\xe1\x43\xe0\xf4\x9b\xc0\x1f\xdf\x03\xce\xb4\x01\x7f\x3a\x00\x7c\xd0\x01\x9c\x9d\x06\x9c\x6d\x03\x3e\x2c\x04\x3e\xba\x09\xf8\xe8\x45\xe0\x2f\x63\x80\xbf\xbc\x08\x9c\xbb\x09\x38\xb7\x0d\xf8\xf8\x26\xe0\xe3\x67\x80\x4f\xbe\x09\xfc\xf5\x79\xe0\xd3\x19\x40\x5f\x08\xd0\xd7\x0c\xfc\x2d\x1f\xf8\xdb\xc7\xc0\x67\xef\x00\xff\xb5\x0b\x38\xff\x38\xf0\xdf\xb3\x80\xff\x7e\x0b\xb8\xd0\x06\xfc\x4f\x0b\x70\xf1\x26\xe0\xe2\xc7\xc0\xdf\xdf\x02\x3e\x2f\x02\xfe\x77\x0a\x70\xe9\x66\xe0\xd2\xc7\xc0\x17\x87\x00\xcf\xcd\x80\xe7\x0d\xe0\x72\x19\xe0\xe5\xf6\xcc\x93\x80\x6f\x1f\xa0\xbd\x08\xf8\x8b\x00\xff\x79\x10\xda\x40\xf4\x4d\x90\xb4\x04\x24\x67\x83\xd8\x2c\x3e\xf2\x07\x09\xef\x45\x33\xc8\xf4\x24\x28\x64\x21\x28\x64\x1f\x68\xd4\x93\xa0\xd0\x27\x41\xa3\x19\x68\xf4\x1f\x40\x63\xca\x40\x63\xcd\xa0\xb1\x1d\xa0\xb0\x5d\xa0\x1b\x52\x41\x37\xbc\x01\x32\x57\x80\xcc\x7d\xa0\xf0\xc7\x40\x11\x37\x81\x22\xde\x03\x8d\x7b\x06\x64\x79\x0c\x14\xb9\x00\x34\x9e\x81\xc6\x1f\x02\x45\xed\x03\x4d\x28\x03\x4d\xd8\x06\x9a\x70\x1e\x14\xfd\x1c\xe8\xc6\x29\xa0\x89\x00\x4d\xec\x03\x4d\x9a\x02\x9a\x74\x00\x34\xf9\x79\x50\x4c\x0e\x68\x4a\x2a\xc8\x5a\x04\x9a\xfa\x38\xc8\x06\xd0\xb4\x69\xa0\x69\x6f\x81\x62\x67\x81\xa6\x03\x34\xfd\xf7\xa0\xb8\x67\x40\x37\xe7\x83\xe2\x4b\x40\xb7\x3c\x0f\x4a\x68\x06\xcd\x78\x07\x34\x93\x81\x92\x72\x40\xb3\x8a\x40\xc9\x2f\x82\x66\x17\x81\xec\x85\xa0\x39\x1f\x82\x1c\xcd\xa0\x94\x3e\x90\x73\x17\x68\xee\x04\xd0\xad\x53\x40\x69\xf9\xa0\x79\x45\xa0\xf4\x6f\x82\xe6\xdf\x04\x9a\x7f\x08\x94\xf1\x16\x68\xc1\x9b\xa0\xdb\xce\x83\x6e\x67\xa0\xdb\xff\x00\x5a\xb8\x07\x74\x47\x2a\xe8\x8e\x8b\xa0\xac\x3d\xa0\x3b\x0f\x80\xb2\x0f\x80\xee\x7a\x07\xb4\xe8\x59\xd0\xdd\xb3\x40\x77\xf7\x81\x72\x9a\x41\xf7\xbc\x08\x5a\x7c\x33\x68\xb1\x17\x74\xef\xb3\xa0\xbc\x17\x41\x5f\xd9\x02\xca\x7f\x0c\xf4\xd5\x03\xa0\x82\x2d\xa0\xfb\x7e\x0f\x2a\xec\x00\xdd\xff\x1e\x68\xe9\x01\xd0\x03\x7f\x00\x15\x75\x80\x1e\xcc\x07\x15\xa7\x82\x8a\xff\x00\x7a\xe8\x63\x50\xc9\x87\xa0\x87\xcf\x83\x4a\xcf\x83\xca\x00\x2a\xfb\x13\xe8\x91\xf3\xa0\xf2\xdf\x83\x96\xef\x03\x55\xec\x02\xad\xf8\x26\xa8\xf2\x59\xd0\xa3\xcf\x83\x1e\xdb\x02\x5a\x39\x0d\xf4\xb5\x9b\x75\x53\xb7\xea\x0f\xf8\xff\x50\xf2\x3e\xe0\x75\x4c\xdb\x1f\xf7\x77\xef\xb5\xf6\xcc\x9c\x36\x6d\xd3\x36\xad\x94\xd0\x20\x34\x88\x36\x39\x33\x27\x7f\x08\xf2\xe7\x4c\x9a\x12\x94\xa6\x14\x41\xd3\x26\x9a\x90\x36\x91\xa6\x6d\xea\x16\x41\x11\x14\x45\x11\x04\x41\x10\xb4\x04\x41\x50\x14\x41\x10\x04\x41\x10\x14\x41\x51\x04\x41\x11\xbc\x4f\x93\xd5\xa3\xf7\xf7\xfb\x3d\xef\xf3\xbe\xf7\x3e\xa7\x6b\xcf\x39\x67\xf6\x67\xef\x3d\x73\xe6\xb3\xd6\xbe\xbd\x55\x55\xb5\x50\x67\x86\xa1\xce\xec\x85\xaa\xee\x84\x5a\xda\x06\x55\xd3\x0c\xb5\xac\x10\x6a\xd9\x20\xd4\xf2\x06\xa8\x15\x9b\xa0\x6a\x1b\xa1\x56\x6e\x84\x3a\x6b\x10\x6a\x55\x3c\xd4\xd9\xed\x50\xe7\x16\x42\xd5\x25\x43\x9d\x07\xa8\xf3\xb7\xbf\xb6\x41\x5d\x50\x06\x75\xc1\x10\xd4\xea\x76\xa8\x0b\xbb\xa0\x2e\xea\x83\xba\x38\x13\xaa\x7e\x3e\xd4\x25\xab\xa1\x2e\x4d\x80\xba\x74\x00\xea\xb2\x8d\x50\x6b\xc2\x50\x6b\xfa\xa1\xae\x00\xd4\x15\xf5\x50\x57\xc6\x42\x5d\xd9\x04\xb5\xb6\x1d\xea\xaa\x7a\xa8\xab\xfa\xa0\xae\x29\x80\x5a\x57\x0f\x75\x6d\x02\xd4\xb5\x83\x50\xd7\x6d\x83\xba\x7e\x0b\x54\x43\x0b\xd4\x0d\xf3\xa1\x6e\x8c\x82\xba\xb1\x1d\xea\xa6\xf5\x50\x8d\x35\x50\x37\xa7\x43\xdd\x92\x08\x75\x4b\x3b\xd4\xad\x6d\x50\x4d\xcd\x50\xb7\x35\x40\xdd\x5e\x08\x75\x47\x1c\x54\xf3\x6c\xa8\x3b\x13\xa0\xee\x1c\x84\xba\xab\x1f\xea\xee\x2e\xa8\x96\x32\xa8\x7b\x6a\xa1\xee\xad\x80\xba\x2f\x13\x6a\x3d\x43\x6d\xd8\xfe\x6a\x84\xba\xbf\x04\xea\x81\x02\xa8\x07\x86\xa0\x5a\x4b\xa0\x5a\x7b\xa1\x1e\x5c\x0b\xf5\x50\x18\xea\xa1\x26\xa8\x87\x57\x43\xb5\xcd\x87\x7a\x24\x0c\xf5\x68\x16\xd4\x63\x80\x7a\xac\x0b\xaa\x7d\x36\xd4\xe3\x0e\xd4\x13\xdb\x5f\xdb\xa0\x9e\xec\x83\xda\x58\x04\xb5\xb1\x0f\xea\xa9\x7a\xa8\xa7\x01\xf5\x74\x13\xd4\x33\x0c\xf5\x4c\x19\xd4\xa6\x18\xa8\x4d\xf5\x50\xcf\xd6\x43\x3d\x17\x0d\xf5\x5c\x0f\xd4\xf3\x45\x50\x1d\x49\x50\x1d\xfd\x50\x2f\x34\x43\xbd\xb8\x16\xea\xa5\x55\x50\x9d\xf1\x50\x9d\xb5\x50\x2f\xb7\x43\xbd\xe2\x41\xbd\xb2\x16\xea\xd5\x4c\xa8\x57\xb7\x42\x75\xad\x83\x7a\x6d\x3d\xd4\xeb\x1e\xd4\xeb\x8d\x50\x6f\x24\x40\xbd\xd1\x0a\xd5\xdd\x08\xf5\x66\x19\xd4\x5b\xf3\xa0\xde\x2e\x84\x7a\xbb\x03\xaa\xa7\x19\xea\x9d\x38\xa8\x77\xca\xa0\xde\x2d\x82\x7a\x2f\x1e\xea\xbd\x7e\xa8\xde\x41\xa8\x0f\x4a\xa0\x3e\xec\x87\xfa\x28\x0a\xea\xe3\x4c\xa8\x4f\xda\xa1\x36\xf7\x43\x7d\xda\x05\xf5\x59\x01\xd4\xe7\xbd\x50\xfd\x55\x50\x5f\x24\x43\x7d\x19\x0d\xf5\x65\x33\xd4\x57\x65\x50\x5b\x18\x6a\x4b\x15\xd4\x96\xcd\x50\x5f\xd7\x41\x7d\x93\x00\xf5\x4d\x2f\xd4\xb7\x99\x50\xdf\xd6\x43\x6d\x8d\x82\xda\x5a\x04\xb5\xb5\x05\x6a\xeb\x36\xa8\xef\x8a\xa0\xbe\xdb\x04\xf5\x7d\x01\xd4\xf7\x1d\x50\xdf\x6f\x85\xfa\x21\x06\xea\x87\x2c\xa8\x1f\xca\xa0\x7e\xd8\x04\x35\x10\x0b\x35\x30\x1b\x6a\x60\x0d\xd4\x40\x1f\xd4\x8f\x49\x50\x3f\x96\x40\xfd\xd8\x08\xf5\xe3\x56\xa8\x9f\x32\xa1\x7e\x5a\x0b\xf5\x53\x27\xd4\xcf\x49\x50\x3f\xaf\x85\xfa\x79\x2b\xd4\x60\x3e\xd4\xe0\x26\xa8\xc1\x6d\x50\xbf\x54\x41\xfd\xb2\x09\xea\xd7\x02\xa8\x5f\xdb\xa0\x7e\xcb\x82\xfa\xad\x13\x6a\x5b\x3c\xd4\xb6\xb5\x50\xbf\xa7\x43\xfd\x5e\x01\xf5\x47\x16\xd4\x1f\xab\xa0\xfe\xd8\x06\xf5\x67\x18\xea\xcf\x26\xa8\x3f\x87\xa0\x86\xe6\x41\x0d\xb5\x40\x0d\x6d\x83\xfa\xab\x10\xea\xaf\x16\xa8\xbf\xb6\x40\xfd\x5d\x01\xf5\x77\x2b\xd4\xdf\xdb\xa0\xfe\xc9\x87\xfa\xa7\x01\x1a\x09\xd0\xa8\x81\x46\x3f\xb4\x2a\x80\x56\x9d\xd0\x3a\x1f\x5a\xaf\x83\xd6\x9b\xa1\x29\x09\x9a\x6a\xa1\xa9\x1b\x9a\xe3\xa0\xb9\x0c\x9a\xdb\xa1\x8d\x03\x6d\x8a\xa0\x4d\x3f\xb4\x15\x07\x6d\x15\x40\x5b\x9b\xa0\xed\x28\x68\x7b\x0d\xb4\xbd\x0d\xda\xa9\x83\x0e\x30\x74\x60\x1e\x74\x60\x2d\x74\x60\x0b\xf4\xa8\x1a\xe8\xd1\x09\xd0\xa3\x1b\xa1\x47\xf7\x43\x47\x25\x41\x47\xd5\x40\x47\x6d\x84\x1e\x13\x05\x3d\xa6\x08\x7a\x4c\x3b\xf4\xd8\x18\xe8\xb1\xf3\xa1\xc7\xae\x87\x1e\x17\x0d\x3d\xae\x02\x7a\x5c\x27\x74\x74\x16\x74\x74\x2d\x74\x74\x37\xf4\xf8\x04\xe8\xf1\x55\xd0\xe3\x07\xa0\x27\xd4\x42\x4f\xe8\x80\x9e\x98\x04\x3d\x71\x2d\xf4\xc4\x4e\xe8\x98\x78\xe8\x98\x0e\xe8\x49\xb1\xd0\x93\x2a\xa0\x27\xf5\x41\x4f\x2e\x84\x9e\xdc\x07\xbd\x4b\x0c\xf4\x2e\x61\xe8\x5d\xea\xa0\x63\x1d\xe8\xd8\x74\xe8\xd8\x32\xe8\xd8\x66\xe8\xd8\x0e\xe8\x29\x89\xd0\x53\xea\xa0\xa7\x74\x43\xef\x5a\x03\xbd\x6b\x3f\xf4\x6e\x15\xd0\xbb\xad\x87\xde\x6d\x08\x3a\xae\x00\x3a\xae\x07\x7a\xf7\x04\xe8\xdd\x37\x43\xef\x91\x0e\xbd\xc7\x3a\xe8\x3d\xba\xa1\xa7\x26\x42\x4f\xad\x81\x8e\x8f\x87\xde\x33\x0e\x7a\xaf\x4e\xe8\xbd\xa3\xa0\xf7\x2e\x80\x9e\x56\x0b\x3d\xad\x07\x3a\x31\x1d\x3a\x71\x2b\xf4\x7e\x45\xd0\xfb\xb5\x43\xef\x1f\x03\xbd\x7f\x23\xf4\x01\x80\x3e\xa0\x00\xfa\x80\x56\xe8\xa4\x26\xe8\x03\xa3\xa1\x0f\x2c\x84\x3e\xb0\x11\xfa\xc0\x4e\xe8\x03\x07\xa1\xa7\x6f\x85\x9e\xe1\x41\xcf\xa8\x82\x4e\x9e\x07\x9d\xbc\x0d\x3a\x65\x1e\x74\x4a\x1f\x74\xb0\x0a\x3a\x38\x00\xed\xb6\x43\x7b\x05\xd0\x21\x86\x0e\x55\x40\xa7\x02\x3a\xd5\x83\x4e\x5d\x05\x9d\xda\x01\x9d\xe6\x40\xa7\x95\x40\xa7\x0d\x42\xa7\x77\x41\x67\xb4\x40\x1f\x94\x04\x7d\xd0\x2a\xe8\x83\x33\xa1\x0f\xee\x83\xce\x4c\x87\xce\x1c\x80\x3e\xa4\x09\xfa\xd0\x42\xe8\xc3\xd2\xa1\x0f\xeb\x81\xce\x06\x74\x4e\x14\x74\x4e\x2d\x74\x6e\x01\x74\x6e\x03\x74\xee\x10\x74\xb8\x06\x3a\xdc\x0d\xed\x67\x41\xe7\x31\x74\x5e\x2d\x74\x5e\x3f\xf4\xcc\x74\xe8\x99\x7d\xd0\xf9\xb5\xd0\xf9\x3d\xd0\xb3\x56\x41\xcf\xea\x86\x3e\xbc\x10\xfa\xf0\x0e\xe8\x23\x12\xa0\x8f\xa8\x83\x2e\xa8\x80\x2e\xe8\x86\x3e\x72\x15\xf4\x51\x15\xd0\x47\xe7\x43\xcf\x8e\x82\x3e\x26\x19\xfa\xd8\x7c\xe8\x39\x51\xd0\x73\x5a\xa1\x0b\x37\x43\xcf\xed\x82\x3e\xae\x13\xfa\xf8\x30\xf4\xbc\x64\xe8\x13\x18\xfa\x84\x2e\xe8\x13\xe7\x43\x9f\x14\x0b\x7d\x52\x1d\xf4\x49\xdb\xa0\x8b\x9a\xa1\x4f\x2e\x82\x3e\x79\x13\xf4\x29\x3d\xd0\xa7\x56\x41\xcf\x8f\x81\x9e\xdf\x05\x5d\x5c\x07\xbd\x20\x01\x7a\x41\x2b\xf4\xc2\x30\x74\x49\x12\x74\x49\x1f\x74\x69\x33\xf4\x69\x8d\xd0\x8b\x56\x41\x97\xd5\x40\x97\x87\xa1\x4f\x77\xa0\xcf\x48\x84\xae\xf0\xa0\x17\x97\x40\x2f\x1e\x80\x5e\xd2\x0e\x5d\xd9\x0e\x5d\xd5\x08\x7d\x66\x33\x74\x75\x1b\xf4\xd2\x3a\xe8\x1a\x0f\xba\xa6\x13\x7a\xd9\x3a\xe8\xe5\x31\xd0\xcb\xd7\x42\xaf\x68\x80\xae\xdd\x02\xbd\xb2\x1e\xfa\xac\x22\xe8\xff\x94\x40\xaf\xaa\x80\x3e\xdb\x83\x3e\x7b\x1b\xf4\x39\x1b\xa1\xcf\xad\x83\xae\xab\x85\x3e\xaf\x08\xfa\xfc\x28\xe8\xf3\x3b\xa0\x2f\x68\x81\x5e\x5d\x0f\x7d\xe1\x3c\xe8\x8b\x00\x7d\x51\x2f\xf4\xc5\x9b\xa1\xeb\x2b\xa0\x2f\x61\xe8\x4b\x3a\xa0\x2f\x5d\x05\x7d\x99\x07\x7d\x59\x27\xf4\x9a\xb5\xd0\x97\x27\x40\x5f\xde\x01\x7d\xc5\x6c\xe8\x2b\x33\xa1\xaf\xec\x86\x5e\xdb\x0e\x7d\x55\x13\xf4\xd5\x59\xd0\xd7\x24\x42\x5f\x33\x08\xbd\xae\x08\xfa\xda\x18\xe8\x6b\xb7\x42\x5f\x37\x1f\xfa\xfa\x4c\xe8\xeb\x1b\xa1\x1b\x3a\xa1\x6f\x58\x0d\x7d\x63\x3c\xf4\x8d\xcd\xd0\x37\xcd\x83\x6e\xcc\x84\x6e\x6c\x83\xbe\x39\x1e\xfa\xe6\x8d\xd0\xb7\xac\x85\xbe\xa5\x0f\xfa\xd6\x35\xd0\x4d\x0c\xdd\xb4\x06\xfa\xb6\x32\xe8\xdb\x86\xa0\x6f\xef\x87\xbe\x23\x1f\xba\x39\x1e\xba\xb9\x03\xfa\x4e\x0f\xfa\xce\x3e\xe8\xbb\x92\xa1\xef\x6a\x83\xbe\x3b\x1f\xfa\xee\x16\xe8\x96\x44\xe8\x7b\x62\xa0\xef\xa9\x85\xbe\xa7\x1f\xfa\xde\x2a\xe8\x7b\x37\x43\xdf\x57\x02\xbd\x1e\xd0\xeb\x9b\xa1\x37\x24\x41\x6f\xd8\x02\x7d\x7f\x0f\xf4\x03\x75\xd0\xad\x55\xd0\x0f\x66\x41\x3f\x14\x05\xfd\xd0\x3c\xe8\x87\x19\xfa\xe1\x2e\xe8\xb6\x79\xd0\x8f\x24\x42\x3f\xd2\x02\xfd\x68\x3d\xf4\xa3\x5b\xa1\x1f\x2b\x84\x7e\x6c\x00\xba\x7d\x3e\x74\xfb\x10\xf4\xe3\xb3\xa1\x9f\x88\x83\x7e\xa2\x05\xfa\x49\x07\xfa\xc9\x7a\xe8\x8d\x15\xd0\x1b\xbb\xa1\x9f\x0a\x43\x3f\xd5\x0d\xfd\x74\x16\xf4\xd3\xdd\xd0\xcf\x94\x41\x6f\x8a\x82\xde\xb4\x16\xfa\xd9\x7c\xe8\xe7\x12\xa0\x9f\xeb\x86\x7e\xbe\x1d\xba\x63\x33\xf4\x0b\x3d\xd0\x2f\x66\x42\xbf\x38\x08\xfd\xd2\x26\xe8\x4e\x0f\xba\xb3\x07\xfa\xe5\x0a\xe8\x57\xe2\xa1\x5f\xe9\x85\x7e\xb5\x05\xba\x2b\x09\xba\xab\x0b\xfa\xb5\x76\xe8\xd7\x93\xa1\xdf\x98\x07\xdd\xed\x40\x77\x77\x41\xbf\xd9\x00\xfd\x56\x3d\xf4\xdb\x15\xd0\x6f\x6f\x83\xee\xa9\x83\x7e\x27\x1f\xfa\xdd\x28\xe8\xf7\xca\xa0\x7b\x13\xa1\xdf\xef\x82\xfe\xa0\x0b\xba\x6f\x36\xf4\x47\x5d\xd0\x1f\xd7\x42\x7f\x92\x05\xbd\x19\xd0\x9b\xdb\xa1\x3f\x2d\x83\xfe\x2c\x1a\xfa\xf3\x04\xe8\x7e\x0f\xfa\x8b\x30\xf4\x97\x61\xe8\xaf\xd2\xa1\xb7\x24\x42\x7f\xb3\x1a\x7a\x6b\x27\xf4\xf7\x99\xd0\x3f\xa4\x43\xff\xb0\x05\x7a\xa0\x09\xfa\xc7\x28\xe8\x1f\x6b\xa1\x7f\xec\x83\xfe\x29\x0c\xfd\x53\x0b\xf4\xcf\x0d\xd0\xbf\xce\x83\xfe\x6d\x1d\xf4\xb6\xb5\xd0\xbf\xaf\x86\xfe\x23\x1f\xfa\x4f\x86\xfe\xb3\x03\x7a\x68\x13\xf4\x5f\x71\xd0\x7f\xd5\x42\xff\x0d\xe8\xbf\xeb\xa1\xff\xc9\x07\xc1\x01\x61\x23\x48\x55\x81\x74\x23\x88\xda\x40\x5c\x00\xe2\x3e\x90\xa9\x00\x99\x21\x90\xb5\x1e\x64\x17\x81\xec\x3e\x90\x33\x0f\xe4\xf4\x83\x02\xab\x40\xa3\x00\x1a\xb5\x1a\x34\xba\x10\x14\x15\x07\x1a\x53\x04\x1a\xbb\x06\x34\x6e\x35\x28\xba\x06\x14\xdd\x0f\x1a\x5f\x04\x1a\xdf\x0e\x9a\x90\x00\x9a\xd0\x01\x9a\x58\x05\x9a\x38\x08\x8a\xa9\x05\x4d\x8a\x05\x4d\x6a\x07\x4d\x9e\x0d\x9a\x3c\x00\xda\x65\x3d\x28\xb6\x16\x34\x05\xa0\x29\xf5\xa0\x5d\x1b\x40\xbb\x35\x81\xe2\xba\x41\xbb\x0f\x80\xf6\x28\x01\x4d\x9d\x0f\x8a\x9f\x0f\xda\x33\x1d\xb4\x97\x03\xda\x6b\x1b\x68\xef\x3a\x50\x42\x22\x28\xa1\x0b\xb4\x4f\x11\x68\x9f\xad\xa0\x7d\xd7\x80\xa6\x25\x81\xa6\xf5\x83\x12\xd7\x81\xf6\x73\x40\xfb\x6d\x06\x1d\x90\x04\x4a\x8a\x01\x1d\x58\x07\x9a\x9e\x08\x9a\x51\x0f\x4a\x2e\x02\xa5\x54\x80\x82\xe9\x20\x17\x20\x2f\x1d\x14\x9a\x0f\x4a\x9d\x07\x4a\x2b\x02\xa5\xb7\x82\x32\x86\x40\x07\xad\x07\x1d\x5c\x08\xca\x04\x28\xb3\x01\x74\x48\x3d\xe8\xd0\x2a\xd0\x61\x75\xa0\xac\xd5\xa0\xec\x30\x28\x7b\x08\x94\x9b\x09\x0a\x57\x80\xfc\x16\x50\x5e\x37\x68\x66\x09\x68\xe6\x36\x50\x7e\x3f\x68\x56\x37\xe8\xf0\x76\xd0\x11\x4d\xa0\x82\x06\xd0\x91\xdb\x5f\x83\xa0\xa3\xe6\x81\x8e\xae\x00\xcd\x5e\x05\x3a\xa6\x08\x74\x6c\x02\xe8\xd8\x2e\xd0\x9c\x1a\x50\x21\x40\x85\x6b\x40\x73\x63\x40\x73\xfb\x41\xc7\x6d\x04\x1d\xdf\x06\x9a\xe7\x81\xe6\x35\x83\x4e\x88\x06\x9d\x50\x01\x3a\xa1\x07\x74\xa2\x07\x3a\x71\x35\xe8\xc4\x1e\xd0\x49\x59\xa0\x93\x1a\x40\x45\x71\xa0\xa2\x12\x50\x51\x1f\xe8\xe4\x02\xd0\xc9\xad\xa0\x53\xa2\x40\xa7\xac\x02\x9d\xb2\x19\x74\x6a\x26\xe8\xd4\x8d\xa0\xf9\x09\xa0\xf9\xed\xa0\xe2\x24\x50\xf1\x5a\x50\xf1\x20\x68\x41\x09\x68\x41\x1b\x68\xc1\x10\x68\x61\x3d\x68\xe1\x10\xa8\xa4\x0a\x54\xd2\x0b\x2a\x75\x40\xa5\xe9\xa0\xd2\xd5\xa0\xd2\x5e\xd0\x69\x71\xa0\xd3\xca\x40\x8b\x62\x41\x8b\xea\x40\x8b\xba\x41\x65\x31\xa0\xb2\x2a\x50\x59\x13\xa8\xdc\x01\x95\x87\x41\xe5\x35\xa0\xf2\x56\x50\xf9\x16\xd0\xe9\xc9\xa0\xd3\xab\x40\xa7\x77\x82\xce\x88\x01\x9d\x51\x01\x3a\x63\x0b\xa8\xa2\x04\xb4\x18\xa0\xc5\x65\xa0\xc5\x4d\xa0\xc5\xbd\xa0\x25\xb1\xa0\x25\x25\xa0\x25\xad\xa0\x25\x3d\xa0\xca\x68\x50\x65\x21\xa8\xb2\x17\x54\xd5\x0e\x3a\x93\x41\x67\x96\x80\xce\x5c\x0b\x3a\x73\x33\xa8\xba\x1e\x54\x3d\x00\x5a\x1a\x0d\x5a\x1a\x06\x2d\x2d\x03\x2d\x6d\x01\x2d\x1d\x02\xd5\x84\x41\x35\xf5\xa0\x9a\x5e\xd0\x32\x0f\xb4\xac\x11\xb4\x6c\x33\x68\x79\x34\x68\x79\x16\x68\xf9\x3a\xd0\xf2\x0e\xd0\xf2\x41\xd0\x8a\x44\xd0\x8a\x32\xd0\x8a\x66\xd0\x8a\x2d\xa0\xda\x04\x50\x6d\x11\xa8\xb6\x15\xb4\x32\x16\xb4\xb2\x08\xb4\xb2\x05\xb4\xb2\x0b\x74\x96\x03\x3a\xab\x0c\x74\x56\x2f\xe8\x3f\xf9\xa0\xff\x34\x83\x56\xe5\x83\x56\xb5\x80\xce\x76\x40\x67\xcf\x07\x9d\xdd\x0a\x3a\x27\x1a\x74\x4e\x05\xe8\x9c\x7e\xd0\xb9\xf1\xa0\x73\xe7\x83\xce\xdd\x08\xaa\x8b\x06\xd5\x15\x81\xea\x9a\x40\x75\xdd\xa0\xba\x21\xd0\x79\x45\xa0\xf3\x5a\x40\xe7\x6d\x05\x9d\x9f\x0c\x3a\x7f\x2d\xe8\xfc\x0e\xd0\x05\x49\xa0\x0b\x1a\x40\x17\xf4\x81\x56\x17\x81\x56\x77\x80\x2e\xf4\x40\x17\x56\x81\x2e\x6c\x01\x5d\xb8\x15\x74\x51\x3c\xe8\xa2\x35\xa0\x8b\xba\x41\x17\x27\x80\x2e\x5e\x03\xba\x78\x08\x54\xbf\x1a\x74\x49\x12\xe8\x92\x6e\xd0\xa5\x85\xa0\xcb\x62\x40\x97\x35\x81\xd6\xe4\x83\xd6\x74\x80\x2e\x4f\x07\x5d\xde\x05\xba\x62\x36\xe8\x8a\x4d\xa0\x2b\x33\x41\x57\x56\x80\xd6\x66\x82\xd6\x6e\x06\x5d\x15\x05\xba\xaa\x10\x74\x55\x0f\xe8\xea\x64\xd0\xd5\xad\xa0\x6b\x3c\xd0\x35\xed\xa0\x75\x71\xa0\x75\xed\xa0\x6b\x63\x41\xd7\xce\x06\x5d\xdb\x03\xba\xce\x03\x5d\xb7\x11\x74\x7d\x2c\xe8\xfa\x26\x50\x43\x34\xa8\xa1\x19\x74\x03\x40\x37\x84\x41\x37\xf4\x81\x6e\x2c\x02\xdd\x38\x08\xba\xa9\x02\x74\xd3\x20\xa8\xb1\x06\xd4\x38\x08\xba\x79\x36\xe8\xe6\x8d\xa0\x5b\xe2\x41\xb7\xac\x06\xdd\x32\x00\xba\xb5\x00\x74\xeb\x3a\x50\x53\x14\xa8\xa9\x1e\xd4\xd4\x0f\xba\x2d\x11\x74\x5b\x05\xe8\xb6\x7e\xd0\xed\x89\xa0\xdb\x6b\x40\xb7\xb7\x80\x6e\xef\x05\xdd\x11\x0b\xba\xa3\x1e\x74\x47\x3b\xe8\x8e\xad\xa0\xe6\x28\x50\x73\x1d\xa8\xb9\x1f\x74\x67\x3a\xe8\xce\xb5\xa0\x3b\x3b\x41\x77\xc5\x81\xee\x5a\x07\xba\x3b\x06\x74\x77\x11\xe8\xee\x36\x50\x4b\x0c\xa8\xa5\x06\xd4\xd2\x0a\xba\x87\x41\xf7\xa4\x83\xee\x29\x03\xdd\xd3\x06\xba\x37\x16\x74\x6f\x05\xe8\xde\x1e\xd0\x7d\x99\xa0\xfb\x1a\x41\xeb\x63\x40\xeb\x0b\x41\xeb\x6b\x41\xeb\xb7\x1f\x6f\x02\xad\xef\x07\x6d\x88\x06\x6d\xc8\x04\x6d\xa8\x02\x6d\x68\x06\xdd\xef\x80\xee\xaf\x07\x3d\x90\x09\x7a\xa0\x13\xd4\x3a\x1b\xd4\xda\x07\x7a\xb0\x04\xf4\x60\x1f\xe8\xa1\x42\xd0\x43\x43\xa0\x87\x1b\x40\x6d\x00\xb5\xd5\x83\xda\x06\x40\x8f\xd4\x82\x1e\xe9\x02\x3d\x9a\x05\x7a\xb4\x19\xf4\x58\x22\xe8\xb1\x46\x50\x7b\x12\xa8\xbd\x0e\xf4\xb8\x03\x7a\xbc\x04\xf4\xf8\x00\xe8\x89\x7c\xd0\x13\x3d\xa0\x27\xc3\xa0\x27\xfb\x41\x1b\x2b\x40\x4f\x25\x80\x9e\xaa\x02\x3d\xd5\x0b\x7a\xba\x00\xf4\x74\x0f\xe8\x99\x04\xd0\x33\x6b\x40\xcf\xf4\x81\x36\x85\x41\x9b\xda\x40\xcf\x66\x82\x9e\x6d\x04\x3d\x17\x0b\x7a\xae\x02\xf4\x5c\x1f\xe8\xf9\x02\xd0\xf3\x9d\xa0\x8e\xd9\xa0\x8e\x0e\xd0\x0b\x71\xa0\x17\x56\x81\x5e\xe8\x01\xbd\xe8\x81\x5e\x5c\x05\x7a\xb1\x0b\xf4\x52\x14\xe8\xa5\x7c\xd0\x4b\x0d\xa0\x97\x36\x83\x3a\xa3\x40\x9d\x1e\xa8\x73\x15\xa8\x73\x13\xe8\xe5\x24\xd0\xcb\x6d\xa0\x57\xe2\x41\xaf\xb4\x80\x5e\x8d\x01\xbd\xda\x08\xea\x72\x40\x5d\x15\xa0\xae\x5e\xd0\x6b\x99\xa0\xd7\xd6\x81\x5e\xeb\x07\xbd\x3e\x0f\xf4\x7a\x07\xe8\x8d\xd5\xa0\xee\x74\xd0\x9b\x71\xa0\x37\x07\x41\x6f\xad\x02\xbd\xb5\x0d\xf4\x76\x3d\xa8\x27\x0a\xd4\x53\x01\xea\x19\x04\xbd\x33\x0f\xf4\x4e\x3f\xe8\xdd\x42\xd0\xbb\xad\xa0\xf7\xe2\x41\xef\xd5\x81\x7a\x01\xea\xad\x00\xf5\x76\x81\xde\x8f\x05\xbd\xbf\x1e\xf4\x41\x3a\xe8\x83\x4e\xd0\x87\x85\xa0\x3e\x06\xf5\xad\x07\x7d\x54\x02\xfa\x38\x06\xf4\x71\x07\xe8\x93\x2a\xd0\x27\x6d\xa0\xcd\xf1\xa0\xcd\x25\xa0\xcd\xdd\xa0\x4f\x19\xf4\xe9\x7c\xd0\xa7\xad\xa0\xcf\x12\x40\x9f\xb5\x80\x3e\x4f\x02\x7d\xde\x0a\xea\xf7\x40\xfd\x4d\xa0\x2f\xa2\x41\x5f\xb4\x82\xbe\x9c\x0d\xfa\xb2\x1f\xf4\x55\x2d\xe8\xab\xad\xa0\x2d\x25\xa0\x2d\xed\xa0\xaf\xa3\x41\x5f\xaf\x05\x7d\x13\x07\xfa\xa6\x11\xf4\x6d\x12\xe8\xdb\x6e\xd0\xd6\x3a\xd0\x77\x0c\xfa\x6e\x1d\xe8\xfb\x58\xd0\xf7\x2d\xa0\x1f\x1c\xd0\x0f\x65\xa0\x1f\xb6\x80\x06\xca\x40\x03\x6d\xa0\x1f\x13\x41\x3f\xd6\x81\x7e\xec\x05\xfd\x94\x00\xfa\xa9\x0a\xf4\xd3\x7a\xd0\x4f\x5b\x40\x3f\x67\x82\x7e\xee\x04\x0d\xd6\x82\x7e\x89\x02\xfd\xd2\x0c\xfa\x65\x10\xf4\x6b\x09\xe8\xd7\x0e\xd0\x6f\xf3\x40\xbf\x75\x80\xb6\x95\x81\xb6\x6d\x01\xfd\xde\x04\xfa\x23\x1e\xf4\x47\x2f\xe8\xcf\x0a\xd0\x50\x3a\x68\xa8\x1f\xf4\x57\x27\xe8\xef\xd9\xa0\x7f\xa2\x41\xff\xac\x01\x23\x0b\x8c\x8d\x60\x55\x05\xd6\x00\xeb\x4e\x30\x55\x80\x39\x1f\xcc\xdd\x60\xb3\x06\x6c\xfa\xc0\x56\x11\xd8\x6a\x07\xdb\xf9\x60\xbb\x1d\xec\xcc\x03\x3b\x9d\xe0\x40\x05\x38\xb0\x19\x3c\xaa\x0e\x3c\xda\x01\x8f\xde\x04\x8e\x2a\x02\x8f\x49\x04\x8f\x69\x02\x8f\x2d\x00\x8f\x6d\x01\x8f\x1d\x00\x8f\xcb\x02\x8f\x6b\x04\x47\xc7\x83\xa3\x1b\xc0\xe3\x13\xc1\xe3\xd7\x83\x27\xcc\x06\x4f\xd8\x02\x9e\xb8\x06\x1c\x93\x00\x8e\xe9\x03\x4f\xaa\x07\x4f\x9e\x07\xde\x25\x0e\xbc\x4b\x27\x38\xb6\x0c\x3c\x05\xe0\x29\xeb\xc0\xbb\x26\x81\x77\xdd\x08\xde\xad\x04\x1c\xc7\xe0\xb8\x8d\xe0\xdd\xab\xc0\x7b\x44\x81\xf7\x68\x02\x4f\x65\xf0\xd4\x0a\xf0\xd4\x3e\x70\xfc\x6c\x70\x7c\x17\x78\xcf\x7c\xf0\x9e\x1d\xe0\xbd\xb2\xc0\x7b\x75\x81\xf7\x9e\x07\xde\x7b\x10\x9c\xb0\x16\xbc\x4f\x14\x78\x9f\x35\xe0\x7d\x7a\xc1\xfb\xe6\x83\xf7\x5d\x07\x9e\xe6\x80\xa7\x95\x80\xa7\xf5\x83\x13\x0b\xc1\x89\x5b\xc0\xfb\x35\x80\xf7\xcf\x07\x1f\x10\x05\x3e\xa0\x07\x9c\xd4\x00\x3e\x70\x3e\x78\x7a\x3e\x78\x46\x32\x78\x46\x03\x38\x19\xe0\xe4\x3a\x70\x0a\x83\x53\x56\x83\x83\x0e\x38\xb8\x1e\xec\xce\x06\xbb\x5b\xc0\x5e\x1d\x38\x94\x04\x0e\xf5\x82\x53\x57\x83\xd3\x3c\x70\xda\x1a\x70\xda\x16\x70\xfa\x3c\x70\x7a\x27\x38\x23\x1d\x9c\xb1\x1e\x7c\x50\x2c\xf8\xa0\xd5\xe0\x83\x19\x7c\xf0\x6a\x70\x26\x83\x33\xeb\xc1\x87\x24\x81\x0f\xe9\x02\x1f\x9a\x00\x3e\xb4\x0e\x7c\xe8\x00\xf8\xb0\xf9\xe0\xc3\xba\xc1\x59\x61\x70\x56\x2f\x38\xbb\x0c\x9c\xdd\x09\xce\x49\x04\xe7\x34\x81\x73\x63\xc1\xb9\x6b\xc1\x61\x07\x1c\x6e\x06\xfb\x99\x60\x7f\x1d\xd8\xdf\x0a\xce\x2b\x02\xe7\x75\x81\x67\x66\x82\x67\xae\x07\xe7\x67\x81\xf3\xbb\xc1\xb3\x0a\xc0\xb3\xba\xc0\x87\xcf\x07\x1f\x3e\x08\x3e\xa2\x1e\x5c\x10\x0f\x2e\x58\x0f\x3e\x32\x1d\x7c\x64\x2f\xf8\xa8\x5a\xf0\xd1\xb1\xe0\xa3\x37\x82\x67\x27\x81\x67\x37\x81\x8f\x49\x04\x1f\xd3\x0a\x3e\x36\x1d\x7c\xec\x26\xf0\x9c\x0a\x70\x61\x0c\xb8\x70\x7b\xec\x05\xcf\xcd\x07\xcf\xed\x01\x1f\x57\x0b\x3e\x3e\x0e\x7c\x7c\x0f\x78\xde\x1a\xf0\x09\x61\xf0\x89\x00\x9f\xd8\x07\x3e\xa9\x0d\x5c\x94\x0f\x2e\xea\x03\x9f\x5c\x0f\x3e\xc5\x03\x9f\xb2\x19\x7c\xea\x1a\xf0\xfc\x22\x70\x71\x22\xb8\xb8\x13\xbc\xa0\x0c\xbc\x60\x00\xbc\xb0\x16\xbc\xb0\x07\x5c\x92\x0c\x2e\xa9\x03\x97\x74\x83\x4b\xb3\xc0\xa5\xad\xe0\xd3\xa2\xc1\xa7\xd5\x80\x17\x39\xe0\x45\x8d\xe0\xb2\x2a\x70\x79\x18\x7c\x7a\x12\xf8\x8c\x58\x70\x05\x83\x2b\x06\xc0\x8b\x87\xc0\x95\x0e\xb8\xb2\x11\x5c\x95\x0c\xae\xda\x0c\x3e\x73\x2d\xb8\x3a\x0b\x5c\x3d\x00\x5e\xba\x09\x5c\xb3\x16\xbc\x2c\x1e\xbc\xac\x15\xbc\xbc\x10\xbc\x7c\x1b\x78\x45\x23\xb8\x36\x0c\x5e\x19\x05\x5e\xd9\x0d\x3e\x6b\x1e\xf8\xac\xcd\xe0\xff\xac\x02\xaf\x8a\x05\xaf\x6a\x03\x9f\x5d\x08\x3e\x27\x06\x7c\x4e\x37\xf8\xdc\x06\x70\xdd\x7c\xf0\x79\x99\xe0\xf3\xe3\xc0\xe7\x0f\x81\x2f\xe8\x03\xaf\xee\x03\x5f\xd8\x0b\xbe\xa8\x01\x7c\x71\x11\xb8\xde\x03\x5f\x12\x05\xbe\xa4\x1f\x7c\xe9\x26\xf0\x65\x1b\xc1\x6b\xda\xc0\x97\x97\x80\x2f\x1f\x02\x5f\xb1\x09\x7c\x65\x05\x78\x6d\x32\x78\xed\x36\xf0\x55\xfd\xe0\xab\x0b\xc0\x57\x37\x80\xaf\x1e\x00\x5f\x93\x0f\xbe\xa6\x0d\x7c\xcd\x16\xf0\xba\x58\xf0\xba\x02\xf0\xba\x06\xf0\xb5\x09\xe0\x6b\x9b\xc1\xd7\x45\x81\xaf\x5b\x03\xbe\x3e\x1a\x7c\x7d\x3b\xb8\x01\xe0\x86\x02\x70\xc3\x3a\x70\xc3\x66\xf0\x0d\x99\xe0\x1b\xea\xc1\x37\xf4\x80\x6f\x0c\x83\x6f\x6c\x06\xdf\xb8\x15\x7c\xd3\x2a\x70\x63\x14\xb8\x71\x35\xf8\xe6\x4c\xf0\xcd\xeb\xc0\x37\xf7\x80\x6f\x89\x03\xdf\x52\x02\xbe\xa5\x15\x7c\x2b\xc0\xb7\x56\x80\x6f\xed\x03\x37\x79\xe0\xa6\x1e\xf0\x6d\x35\xe0\xdb\x86\xc0\xb7\xaf\x06\xdf\x11\x05\xbe\xa3\x07\xdc\x9c\x08\x6e\x2e\x01\x37\xb7\x80\x9b\x07\xc0\x77\x16\x81\xef\xdc\x04\xbe\x2b\x01\x7c\x57\x3e\xf8\x6e\x80\xef\x6e\x02\xb7\xcc\x03\xdf\x13\x03\xbe\x67\x10\x7c\x6f\x15\xf8\xde\xad\xe0\xfb\xaa\xc0\xf7\x0d\x82\xd7\xaf\x01\xaf\x6f\x03\xaf\xdf\xf2\xff\xff\xb5\x81\xc1\x1b\xb2\xc0\x1b\xaa\xc0\x1b\x9a\xc0\x1b\x36\x82\x37\xf4\x82\xef\x67\xf0\xfd\xf9\xe0\xfb\xd7\x80\xef\xef\x06\xdf\xbf\x0d\xfc\x40\x3c\xf8\x81\x7c\xf0\x03\x55\xe0\x07\x1a\xc0\x0f\x6c\x02\xb7\x32\xb8\x35\x0c\x6e\x5d\x0d\x6e\xed\x04\x3f\x08\xf0\x83\x45\xe0\x07\x1b\xc1\x0f\x25\x81\x1f\x2a\x00\x3f\x54\x0b\x7e\xa8\x09\xfc\x50\x37\xf8\x61\xc8\xab\x07\xfc\xf0\x00\xb8\x2d\x0e\xdc\x56\x08\x6e\xab\x03\xb7\xad\x07\x3f\x12\x03\x7e\x24\x19\xfc\xc8\x6c\xf0\xa3\x4d\xf2\xea\x05\x3f\x96\x08\x7e\xac\x00\xfc\x58\x15\xf8\xb1\x66\xf0\x63\xbd\xe0\xf6\x04\x70\x7b\x09\xb8\xbd\x03\xfc\x78\x12\xf8\xf1\x42\xf0\xe3\x9b\xc1\x4f\xe4\x83\x9f\xa8\x07\x3f\xb1\x0d\xfc\xe4\x6c\xf0\x93\x0d\xe0\x27\x7b\xc0\x1b\x13\xc0\x1b\xeb\xc1\x4f\x25\x82\x9f\x6a\x01\x3f\xb5\x05\xfc\x74\x3e\xf8\xe9\x4d\xe0\x67\x0a\xc1\xcf\xf4\x80\x37\xad\x06\x3f\x5b\x00\x7e\xb6\x07\xfc\xdc\x6c\xf0\x73\x4d\xe0\xe7\xb6\x81\x9f\x6f\x05\x77\x64\x82\x3b\x3a\xc0\x2f\x84\xc1\x2f\x6c\x04\xbf\x98\x0f\x7e\xb1\x0d\xfc\x52\x14\xf8\xa5\x2a\xf0\x4b\xed\xe0\xce\x7c\x70\x67\x3b\xf8\xe5\x30\xf8\xe5\xad\xe0\x57\xc2\xe0\x57\x5a\xc1\xaf\xc6\x81\x5f\xed\x02\xbf\x3a\x08\xee\xaa\x07\xbf\x96\x05\x7e\x1d\xe0\xd7\x07\xc0\x6f\x6c\x06\x77\xaf\x03\x77\xf7\x83\xdf\x8c\x03\xbf\x59\x08\x7e\x73\x0d\xf8\xcd\x0e\xf0\x5b\xb1\xe0\xb7\x2a\xc0\x6f\x75\x81\xdf\x9e\x0d\x7e\x7b\x0d\xf8\xed\x36\xf0\xdb\x5b\xc1\x3d\x89\xe0\x9e\x7c\x70\x4f\x0d\xb8\xa7\x19\xfc\x4e\x22\xf8\x9d\x7c\xf0\x3b\x2d\xe0\x77\xb6\x82\xdf\x5d\x05\x7e\xb7\x13\xfc\x5e\x26\xf8\xbd\x2a\xf0\x7b\xcd\xe0\xf7\xb6\x81\x7b\x63\xc1\xbd\xf3\xc1\xbd\x2d\xe0\xde\x1e\x70\xef\x00\xf8\xfd\x18\xf0\xfb\x05\xe0\xf7\x2b\xc0\xef\x37\x83\xdf\xef\x02\x7f\x10\x05\xfe\x60\x36\xf8\x83\x75\xe0\x0f\xb6\x82\x3f\x2c\x00\x7f\x58\x03\xfe\xb0\x09\xfc\x61\x17\xb8\x0f\xe0\xbe\x12\x70\x5f\x2b\xb8\xaf\x1f\xfc\x51\x34\xf8\xa3\x4c\xf0\x47\x55\xe0\x8f\x7a\xc0\x1f\x03\xfc\xb1\x07\xfe\xb8\x04\xfc\x71\x03\xf8\xe3\x5e\xf0\x27\x61\xf0\x27\xb5\xe0\x4f\x36\x82\x37\x27\x83\x37\xd7\x83\x37\x77\x81\x3f\xcd\x02\x7f\xda\x00\xfe\xb4\x17\xfc\x59\x0d\xf8\xb3\x76\xf0\xe7\x31\xe0\xcf\x93\xc1\x9f\x17\x80\x3f\x2f\x03\x7f\xbe\x1a\xfc\x79\x13\xf8\x8b\x46\xf0\xd7\xab\xc0\xdf\xc5\x82\xbf\xf3\xc0\xdf\x15\x81\xbf\xab\x05\x7f\xd7\x0c\xfe\x6e\x13\xf8\xbb\xad\xe0\xef\x1d\xf0\xf7\x09\xe0\xef\xb3\xc0\xdf\xaf\x02\xff\x00\xf0\x40\x18\x3c\xb0\x0a\x3c\xb0\x19\xfc\x63\x2d\xf8\xc7\x4e\xf0\x4f\xab\xc1\x3f\xc7\x81\x7f\xde\x04\x1e\x4c\x06\x0f\xf6\x80\x7f\xc9\x02\xff\xd2\x0b\xfe\x35\x09\xfc\x6b\x19\xf8\xd7\x76\xf0\x6f\xf1\xe0\xdf\xd6\x80\x7f\xeb\x01\x6f\x8b\x06\x6f\xab\x02\x6f\xeb\x04\xff\x9e\x0c\xfe\xbd\x0f\xfc\x47\x3e\xf8\x8f\x3a\xf0\x1f\x3d\xe0\x3f\x63\xc1\x7f\x96\x80\xff\xec\x05\x0f\xe5\x83\x87\x36\x82\xff\x8a\x06\xff\xb5\x16\xfc\x77\x2c\xf8\xef\xed\xb1\x0d\xfc\x77\x2f\xf8\x9f\x2c\xf0\x3f\x35\xe0\x7f\xfa\x60\x90\x05\x83\x55\x30\x58\x0f\x83\x1e\x18\x0c\xc1\xa8\x74\x18\x55\x03\xa3\x5a\x61\x54\x2f\x8c\x8e\x86\xd1\xf9\x30\x7a\x23\x8c\xee\x87\x21\xc0\x50\x1c\x0c\x79\x30\xb4\x1e\x86\x19\x86\xdb\x60\x4c\x18\xc6\x54\xc1\x98\x46\x18\xd3\x0d\x63\x86\x46\x5e\x76\x03\x8c\x13\x0f\xe3\x14\xc2\x38\x75\x30\x4e\x27\x8c\x33\x08\x13\x68\x82\x09\x0c\xc2\x8c\x4a\x86\x19\x55\x07\x33\xaa\x1b\x66\xb4\x07\x33\xba\x15\x66\xf4\x10\x4c\x54\x3e\x4c\x54\x0b\xcc\x98\x38\x98\x31\x85\x30\x63\xea\x60\xc6\xf4\xc3\x8c\xcd\x87\x19\x5b\x02\x33\x76\x1d\xcc\xd8\x0e\x98\xb1\x83\x30\xe3\xe2\x61\xc6\xcd\x86\x19\x57\x07\x33\xae\x05\x66\x5c\x2f\x4c\xb4\x03\x13\x9d\x0c\x13\x3d\x1f\x26\x7a\x1d\x4c\x74\x07\x4c\xf4\x20\xcc\xf8\x58\x98\xf1\x59\x30\xe3\xab\x60\xc6\x37\xc1\x8c\xef\x81\x99\xc0\x30\x13\x92\x61\x26\xcc\x83\x99\x50\x0f\x33\xa1\x1d\x66\xc2\x56\x98\x89\x71\x30\x13\xc3\x30\x13\xcb\x60\x26\xae\x83\x99\xd8\x09\x33\x71\x08\x26\x26\x19\x26\x66\x3e\x4c\x4c\x3d\x4c\x4c\x1b\x4c\x4c\x3f\xcc\xa4\x18\x98\x49\x59\x30\x93\xaa\x60\x26\x35\xc3\x4c\xea\x81\x99\x34\x04\x33\x39\x09\x66\x72\x21\xcc\xe4\xd5\x30\x93\xdb\x60\x26\x6f\x81\xd9\x25\x16\x66\x97\x30\xcc\x2e\x15\x30\xbb\x34\xc2\xec\xd2\x05\x13\x0b\x98\xd8\x64\x98\xd8\x79\x30\xb1\xab\x60\x62\x5b\x60\x62\xfb\x60\xa6\x44\xc3\x4c\x09\xc3\x4c\xa9\x81\x99\xd2\x08\x33\xa5\x03\x66\xca\x20\xcc\xae\x89\x30\xbb\x16\xc1\xec\xba\x06\x66\xd7\x36\x98\x5d\x37\xc3\xec\x16\x05\xb3\x5b\x26\xcc\x6e\x65\x30\xbb\x35\xc0\xec\xd6\x09\xb3\xdb\x10\x4c\x5c\x12\x4c\xdc\x6c\x98\xb8\x5a\x98\xb8\x16\x98\xb8\x5e\x98\xdd\xa3\x60\x76\xcf\x82\xd9\xbd\x0c\x66\xf7\x35\x30\xbb\xb7\xc3\xec\xbe\x15\x66\x8f\x78\x98\x3d\x0a\x61\xf6\x58\x0d\xb3\xc7\x7a\x98\x3d\xfa\x60\xa6\x46\xc1\x4c\xcd\x82\x99\x5a\x03\x33\xb5\x19\x66\x6a\x17\xcc\xd4\x21\x98\xf8\x04\x98\xf8\x42\x98\xf8\x7a\x98\xf8\x76\x98\xf8\x7e\x98\x3d\xa3\x61\xf6\xcc\x82\xd9\xb3\x0a\x66\xcf\x46\x98\x3d\xbb\x60\xf6\x1c\x82\xd9\x2b\x19\x66\xaf\x12\x98\xbd\xd6\xc0\xec\xd5\x0a\xb3\x57\x2f\xcc\xde\x51\x30\x7b\x67\xc1\xec\x5d\x03\xb3\x77\x33\xcc\xde\x5d\x30\x7b\x0f\xc1\x24\x24\xc1\x24\xcc\x87\x49\x58\x07\x93\xd0\x01\x93\xb0\x15\x66\x9f\x18\x98\x7d\xc2\x30\xfb\xd4\xc0\xec\xd3\x02\xb3\x4f\x2f\xcc\xbe\x80\xd9\x37\x19\x66\xdf\xf9\x30\xfb\xd6\xc3\xec\xdb\x0e\xb3\xef\x16\x98\x69\xd1\x30\xd3\x32\x61\xa6\x95\xc1\x4c\x5b\x07\x33\x6d\x13\x4c\x62\x03\xcc\x7e\x55\x30\xfb\xe7\xc3\x1c\x10\x0f\x93\x14\x0d\x73\x20\x60\x0e\x1c\x80\x99\xde\x0f\x33\xa3\x02\x66\xc6\x20\x4c\xf2\x2a\x98\x14\x07\x26\xa5\x05\x26\x98\x0f\x13\xdc\x0a\xe3\xae\x85\xf1\x12\x61\xbc\x4d\x30\xa1\x79\x30\xa1\x41\x98\xd4\x66\x98\xb4\x42\x98\x74\x86\x49\x6f\x87\xc9\x28\x84\xc9\x18\x84\x39\xa8\x05\xe6\xe0\x22\x98\x4c\x07\x26\xb3\x1d\xe6\x90\x55\x30\x87\x66\xc1\x1c\xda\x08\x73\xe8\x00\xcc\x61\x45\x30\x87\xf5\xc0\x64\x25\xc3\x64\xad\x81\xc9\xda\x02\x93\x9d\x0f\x93\xbd\x0e\x26\x7b\x0b\x4c\x4e\x18\x26\xa7\x07\x26\x37\x13\x26\xb7\x19\x26\xb7\x17\x26\x1c\x0d\x13\x5e\x0b\x13\xde\x0a\xe3\xe7\xc3\xf8\xab\x61\xfc\x4d\x30\x79\xf9\x30\x79\xdd\x30\x33\xc3\x30\x33\xdb\x60\xf2\x93\x60\xf2\x9b\x60\x66\xc5\xc0\xcc\xaa\x87\x99\xb5\x11\x0a\x08\x2c\x51\xc7\xa2\x10\x23\xff\x7a\xac\x82\xc6\x64\x6c\x0f\xc9\xf2\xf7\xba\xc6\xe3\x2d\x10\x14\x07\x00\x9c\x32\xfc\x2f\xb2\x6d\x6f\x2b\x4c\xc0\x29\xd2\xd6\x18\x8b\x2a\x69\x13\xd2\x71\x8e\xb4\x19\x7b\xe1\x51\x69\x1b\xc4\xa2\x57\xda\x16\xa2\x31\x20\x6d\x1b\xcd\x6a\x47\x9f\x0e\xf6\x57\xcd\xd2\x0e\x20\x51\xbd\x2e\xed\x51\xc8\x52\xbf\x4a\x7b\x34\x32\x75\xaa\xb4\xa3\x50\xaf\xab\xa5\x3d\x06\x45\xfa\x0f\x69\x8f\x45\x21\x1d\x27\xed\x4e\x4c\xa6\x7b\xa5\xfd\x32\x92\x69\x13\x72\x51\x89\x2a\xac\x44\x35\xca\xb1\x08\x65\xa8\x41\x3c\x82\x48\x46\x0a\x82\x88\xc7\x4c\x54\xa2\x12\x8b\x50\x81\x52\xc4\x63\x16\x96\x60\x21\xa6\x23\x1e\xd9\xa8\x40\x05\xe2\x71\x6c\xe4\xac\xa5\xc3\x47\xa5\x58\x8a\x52\x54\x63\x39\x4a\x51\x82\xe9\x38\x0a\x95\xa8\x41\x25\xe2\x31\x07\xc5\x58\x82\xa5\xc3\xdf\x59\x84\x65\xa8\x40\x31\xaa\x71\x24\x2a\xb1\x64\xf8\x3b\x2b\x51\x25\x8c\xc5\x28\xc6\x22\x94\x63\x09\x16\x21\x1e\x07\x22\xfe\xff\xe8\xe5\x7f\xbf\x13\xff\x3f\x7a\x3e\x6e\x78\x1c\x4b\x51\x3e\x4c\x88\x47\x0a\xa6\x23\x19\x5e\xe4\xcc\xff\xdd\x53\xf9\x70\x2f\xc5\x88\x47\x0d\xaa\x51\x8c\x12\x94\x0e\x8f\xa5\x1a\x67\x20\x1e\x95\x38\xed\xff\x65\x3d\xb6\xf7\x55\x82\xf8\xe1\xef\xaf\x44\x3c\x16\x0c\x7f\x5e\x3d\x3c\xa2\xed\xfd\xd6\x0c\x8f\xa6\x74\xf8\x3b\xe5\xc3\xe3\x59\x38\xfc\x4e\x0d\x8a\xe5\xf8\x74\x2c\x1b\xbe\x06\x4b\x51\x82\x72\x2c\x44\x8d\x8c\x7c\x29\xa6\xff\x7f\x58\xa5\x1d\x23\xf9\xdf\xdf\x0c\x0f\x5f\x93\xed\x57\x69\xc9\xf0\xcc\x4a\x51\x8c\xc5\xff\xf5\xee\xc8\xa8\x16\x0c\x8f\xfb\x7f\x9f\x5f\xf2\x7f\x9e\xbf\xfd\x8a\xd7\xa0\x0a\x07\x61\x06\x66\x60\x21\x2a\x87\xbf\x37\x1d\x8b\x76\x5a\x9f\xe9\xc3\xef\x2f\xc6\x0c\x54\x61\x86\xf4\x5a\x89\x19\xff\xe3\xdc\x15\xc3\xff\x9d\x8e\xc5\xff\x83\x5c\xfe\x5f\x33\xfc\xb7\xaf\xd9\xa8\x1e\xa6\x2d\x1b\x5e\xa3\xa5\x98\x23\xf7\x5b\xf9\xf0\x8a\x2e\xc5\x0c\x14\x4a\x0f\xff\x3d\xc7\x6a\xcc\x41\x19\x2a\xb1\x02\x0b\x51\x3c\x7c\x97\x16\xc8\x39\x4b\x86\x8f\xb6\xaf\xc1\xb2\xe1\xab\xb8\xfd\xbb\xdb\x67\x5a\x36\x3c\xff\x6c\x54\xa1\x18\x0b\xe5\xe8\xbf\xcf\x49\x42\xfc\xff\xba\xcf\x82\xc3\xf7\xd9\xff\x3d\xc7\xe2\x9d\xfa\x9a\x8e\x4a\x54\x63\x11\x66\xa0\xe2\xbf\xfa\xdc\x3e\x83\x02\xcc\x42\x2e\x7c\x1c\x85\x39\xf0\x71\xa0\xf4\x79\x3c\x4a\xb1\x00\xa7\x0d\x73\x6a\x22\x77\xf4\xf1\x32\xf6\xc3\x87\xef\xfc\xed\xef\xa6\x0d\xff\xe9\xe2\x20\x04\x91\x81\x83\x90\x8c\xe4\xc8\x6f\xda\xc5\xc8\xff\x59\x04\xc3\xff\x02\xca\x69\xf8\x3f\xfe\x13\x58\x02\x28\xad\x08\x04\x86\x81\x05\x1b\x0e\xb6\x3f\x75\x46\x23\x0a\x63\x30\x16\xe3\x10\x8d\xf1\x98\x80\x89\x88\xc1\x24\x4c\xc6\x2e\x88\xc5\x14\xec\x8a\xdd\x10\x87\xdd\xb1\x07\xa6\x22\x1e\x7b\x62\x2f\xec\x8d\x04\xec\x83\x7d\x31\x0d\x89\xd8\x0f\xfb\xe3\x00\x24\xe1\x40\x4c\xc7\x0c\x79\xba\xb8\xf0\x10\x42\x2a\xd2\x90\x3e\x3c\xce\x83\x91\x89\x43\x70\x28\x0e\x43\x16\xb2\x91\x83\x5c\x84\xe1\x23\x0f\x33\x91\x8f\x59\x38\x1c\x47\xa0\x00\x47\xe2\x28\x1c\x8d\xd9\x38\x06\xc7\x62\x0e\x0a\x31\x17\xc7\xe1\x78\xcc\xc3\x09\x38\x11\x27\xa1\x08\x27\xe3\x14\x9c\x8a\xf9\x28\x56\x8c\x3b\xb0\x1a\x17\xe2\x29\x5c\x87\x2d\xb8\x08\x57\xe0\x32\xdc\x8c\x7b\xd0\xac\x0c\x2e\xc5\x07\xb8\x00\xd7\x28\x4b\xd9\xb8\x5c\x39\xa8\xc7\xf3\xf8\x58\x05\x70\x0b\xee\xc5\x2f\x18\xc4\xaf\xb8\x1d\x1b\xf0\x32\x5e\xc2\xfd\x58\x80\x85\x58\x8b\x12\xbc\x8a\x52\x74\xe2\x15\xbc\x81\x2e\xbc\x86\xd7\xf1\x35\x4e\xc3\xdb\xe8\xc6\x9b\x78\x00\x8b\x30\x80\xab\xf0\x2e\x7a\xf0\x0e\xca\xf0\x2d\xbe\xc3\x25\x38\x1d\xe5\x38\x03\x8b\x51\x81\x25\x68\x42\x25\xce\x44\xd5\xf0\x7d\xb2\x0c\x35\x58\x8e\x15\xf8\x06\xb5\x38\x0b\x2b\xf1\x1f\x9c\x8d\x55\x68\xc7\x6d\x38\x17\xe7\xa0\x0e\xe7\x61\x2b\xbe\xc7\x13\x6a\x94\x1a\xad\xa2\xd4\x18\x35\x56\x8d\xc3\x5f\xf8\x5b\x45\xab\xf1\x6a\x82\x9a\x88\x7f\x14\x54\x8c\x9a\xa4\x26\x2b\xa5\x76\x51\xb1\x6a\x8a\xda\x55\xed\xa6\xe2\xd4\xee\x6a\x0f\x35\x55\xc5\xab\x3d\xd5\x5e\xd8\x86\xdf\xd5\xde\x2a\x41\xed\xa3\xf6\x55\xd3\x54\xa2\xda\x4f\xed\xaf\x0e\x50\x49\xea\x40\x35\x5d\xcd\x50\xc9\x2a\x45\x05\xf1\x07\xde\x53\xae\xf2\x54\x48\xa5\xaa\x34\x95\xae\x32\xd4\x41\xea\x60\x95\xa9\x0e\x51\x87\xaa\xc3\x54\x96\xca\xc6\x67\xf8\x5c\xe5\xa8\x5c\x15\x56\xbe\xca\x53\x33\x55\xbe\x9a\xa5\x0e\x57\x47\xa8\x02\x75\xa4\x3a\x4a\x1d\xad\x66\xa3\x15\x0f\xaa\x63\xd4\xb1\x6a\x8e\x2a\x54\x73\xd5\x71\xea\x78\x35\x4f\x9d\xa0\x4e\xc4\x9f\x18\x42\x3f\xbe\x50\x27\xa9\x22\x75\xb2\x3a\x45\x9d\xaa\xe6\xab\x62\xb5\x40\x2d\x54\x25\xaa\x54\x9d\xa6\x16\xa9\x32\x55\xae\x4e\x57\x67\xa8\x0a\xb5\x58\x2d\x51\x95\xaa\x0a\x4f\xaa\x33\x55\xb5\x5a\xaa\x6a\xf0\x25\xbe\x52\xcb\xd4\x72\xb5\x42\xd5\xaa\x95\xea\x2c\xf5\x1f\xb5\x4a\x9d\xad\xce\x51\xe7\xaa\x3a\x75\x9e\x3a\x5f\x5d\xa0\x56\xab\x0b\xd5\x45\xea\x62\xdc\xa5\xea\xd5\x25\xea\x52\x75\x99\x5a\xa3\x2e\x57\x57\xa8\x2b\xd5\x5a\x75\x95\xba\x5a\x5d\xa3\xd6\xa9\x6b\xd5\x75\xea\x7a\xd5\xa0\x6e\x50\x37\xaa\x9b\x54\xa3\xba\x59\xdd\xa2\x6e\x55\x4d\xea\x36\x75\xbb\xba\x43\x35\xab\x3b\xd5\x5d\xea\x6e\xd5\xa2\xee\x51\xf7\xaa\xfb\xd4\x7a\xb5\x41\xdd\xaf\x1e\x50\xad\xea\x41\xf5\x90\x7a\x58\xb5\xa9\x47\xd4\xa3\xea\x31\xd5\xae\x1e\x57\x4f\xa8\x27\xd5\x46\xf5\x94\x7a\x5a\x3d\xa3\x36\xa9\x67\xd5\x73\xea\x79\xd5\xa1\x5e\x50\x2f\xaa\x97\x54\xa7\x7a\x59\xbd\xa2\x5e\x55\x5d\xea\x35\xf5\xba\x7a\x43\x75\xab\x37\xd5\x5b\xea\x6d\xd5\xa3\xde\x51\xef\xaa\xf7\x54\xaf\x7a\x5f\x7d\xa0\x3e\x54\x7d\xea\x23\xf5\xb1\xfa\x44\x6d\x56\x9f\xaa\xcf\xd4\xe7\xaa\x5f\x7d\xa1\xbe\x54\x5f\xa9\x2d\xea\x6b\xf5\x8d\xfa\x56\x6d\x55\xdf\xa9\xef\xd5\x0f\x6a\x40\xfd\xa8\x7e\x52\x3f\xab\x41\xf5\x8b\xfa\x55\xfd\xa6\xb6\xa9\xdf\xd5\x1f\xea\x4f\x35\xa4\xfe\x52\x7f\xab\x7f\x34\xb4\xd2\x5a\x93\x66\x6d\xb4\xa5\x6d\xed\xe8\x80\x1e\xa5\x47\xeb\x28\x3d\x46\x8f\xd5\xe3\x74\xb4\x1e\xaf\x27\xe8\x89\x3a\x46\x4f\xd2\x93\xf5\x2e\x3a\x56\x4f\xd1\xbb\xea\xdd\x74\x9c\xde\x5d\xef\xa1\xa7\xea\x78\xbd\xa7\xde\x4b\xef\xad\x13\xf4\x3e\x7a\x5f\x3d\x4d\x27\xea\xfd\xf4\xfe\xfa\x00\x9d\xa4\x0f\xd4\xd3\xf5\x0c\x9d\xac\x53\x74\x50\xbb\xda\xd3\x21\x9d\xaa\xd3\x74\xba\xce\xd0\x07\xe9\x83\x75\xa6\x3e\x44\x1f\xaa\x0f\xd3\x59\x3a\x5b\xe7\xe8\x5c\x1d\xd6\xbe\xce\xd3\x33\x75\xbe\x9e\xa5\x0f\xd7\x47\xe8\x02\x7d\xa4\x3e\x4a\x1f\xad\x67\xeb\x63\xf4\xb1\x7a\x8e\x2e\xd4\x73\xf5\x71\xfa\x78\x3d\x4f\x9f\xa0\x4f\xd4\x27\xe9\x22\x7d\xb2\x3e\x45\x9f\xaa\xe7\xeb\x62\xbd\x40\x2f\xd4\x25\xba\x54\x9f\xa6\x17\xe9\x32\x5d\xae\x4f\xd7\x67\xe8\x0a\xbd\x58\x2f\xd1\x95\xba\x4a\x9f\xa9\xab\xf5\x52\x5d\xa3\x97\xe9\xe5\x7a\x85\xae\xd5\x2b\xf5\x59\xfa\x3f\x7a\x95\x3e\x5b\x9f\xa3\xcf\xd5\x75\xfa\x3c\x7d\xbe\xbe\x40\xaf\xd6\x17\xea\x8b\xf4\xc5\xba\x5e\x5f\xa2\x2f\xd5\x97\xe9\x35\xfa\x72\x7d\x85\xbe\x52\xaf\xd5\x57\xe9\xab\xf5\x35\x7a\x9d\xbe\x56\x5f\xa7\xaf\xd7\x0d\xfa\x06\x7d\xa3\xbe\x49\x37\xea\x9b\xf5\x2d\xfa\x56\xdd\xa4\x6f\xd3\xb7\xeb\x3b\x74\xb3\xbe\x53\xdf\xa5\xef\xd6\x2d\xfa\x1e\x7d\xaf\xbe\x4f\xaf\xd7\x1b\xf4\xfd\xfa\x01\xdd\xaa\x1f\xd4\x0f\xe9\x87\x75\x9b\x7e\x44\x3f\xaa\x1f\xd3\xed\xfa\x71\xfd\x04\x7a\xf1\xa9\x7e\x52\x6f\xd4\x4f\xe9\xa7\xf5\x33\x7a\x93\x7e\x56\x3f\xa7\x9f\xd7\x1d\xfa\x05\xfd\xa2\x7e\x49\x77\xea\x97\xf5\x2b\xf8\x10\x7d\xf8\x08\x9b\xf1\x3e\x3e\xd1\xaf\xea\x2e\xfd\x9a\x7e\x5d\xbf\xa1\xbb\xf5\x9b\xfa\x2d\xfd\xb6\xee\xd1\xef\xe8\x77\xf5\x7b\xba\x57\xbf\xaf\x3f\xd0\x1f\xea\x3e\xfd\x91\xfe\x58\x7f\xa2\x37\xeb\x4f\xf5\x67\xfa\x73\xdd\xaf\xbf\xd0\x5f\xea\xaf\xf4\x16\xfd\xb5\xfe\x46\x7f\xab\xb7\xea\xef\xf4\xf7\xfa\x07\x3d\xa0\x7f\xd4\x3f\xe9\x9f\xf5\xa0\xfe\x45\xff\xaa\x7f\xd3\xdb\xf4\xef\xfa\x0f\xfd\xa7\x1e\xd2\x7f\xe9\xbf\xf5\x3f\x04\x52\xa4\x89\x88\xc9\x90\x45\x36\x39\x14\xa0\x51\x34\x9a\xa2\x68\x0c\x8d\xa5\x71\x14\x4d\xe3\x69\x02\x4d\xa4\x18\x9a\x44\x93\x69\x17\x8a\xa5\x29\xb4\x2b\xed\x46\x71\xb4\x3b\xed\x41\x53\x29\x9e\xf6\xa4\xbd\x68\x6f\x4a\xa0\x7d\x68\x5f\x9a\x46\x89\xb4\x1f\xed\x4f\x07\x50\x12\x1d\x48\xd3\x69\x06\x25\x53\x0a\x05\xc9\x25\x8f\x42\x94\x4a\x69\x94\x4e\x19\x74\x10\x1d\x4c\x99\x74\x08\x1d\x4a\x87\x51\x16\x65\x53\x0e\xe5\x52\x98\x7c\xca\xa3\x99\x94\x4f\xb3\xe8\x70\x3a\x82\x0a\xe8\x48\x3a\x8a\x8e\xa6\xd9\x74\x0c\x1d\x4b\x73\xa8\x90\xe6\xd2\x71\x74\x3c\xcd\xa3\x13\xe8\x44\x3a\x89\x8a\xe8\x64\x3a\x85\x4e\xa5\xf9\x54\x4c\x0b\x68\x21\x95\x50\x29\x9d\x46\x8b\xa8\x8c\xca\xe9\x74\x3a\x83\x2a\x68\x31\x2d\xa1\x4a\xaa\xa2\x33\xd1\x42\xd5\xb4\x94\x6a\x68\x19\x2d\xa7\x15\x54\x4b\x2b\xe9\x2c\xfa\x0f\xad\xa2\xb3\xe9\x1c\x3a\x97\xea\xe8\x3c\x3a\x9f\x2e\xa0\xd5\xb8\x95\x2e\xa4\x8b\xe8\x62\xaa\xa7\x4b\xe8\x52\xba\x8c\xd6\xd0\xe5\x74\x05\x5d\x49\x6b\xe9\x2a\xba\x9a\xae\xa1\x75\x74\x2d\x5d\x87\xeb\xe9\x7a\x6a\xa0\x1b\x70\x13\xdd\x48\x37\x51\x23\xdd\x4c\xb7\xd0\xad\xd4\x44\xb7\xd1\xed\x74\x07\x35\xd3\x9d\x74\x17\xdd\x4d\x2d\x74\x0f\xdd\x4b\xf7\xd1\x7a\xda\x40\xf7\xd3\x03\xd4\x4a\x0f\xd2\x43\xf4\x30\xb5\xd1\x23\xf4\x28\x3d\x46\xed\xf4\x38\x3d\x41\x4f\xd2\x46\x7a\x8a\x9e\xa6\x67\x68\x13\x3d\x4b\xcf\xd1\xf3\xd4\x41\x2f\xd0\x8b\xf4\x12\x75\xd2\xcb\xf4\x0a\xbd\x4a\x5d\xf4\x1a\xbd\x4e\x6f\x50\x37\xbd\x49\x6f\xd1\xdb\xd4\x43\xef\xd0\xbb\xf4\x1e\xf5\xd2\xfb\xf4\x01\x7d\x48\x7d\xf4\x11\x7d\x4c\x9f\xd0\x66\xfa\x94\x3e\xa3\xcf\xa9\x9f\xbe\xa0\x2f\xe9\x2b\xda\x42\x5f\xd3\x37\xf4\x2d\x6d\xa5\xef\xe8\x7b\xfa\x81\x06\xe8\x47\xfa\x89\x7e\xa6\x41\xfa\x85\x7e\xa5\xdf\x68\x1b\xfd\x4e\x7f\xd0\x9f\x34\x44\x7f\xd1\xdf\xf4\x0f\x83\x15\x6b\x26\x66\x36\x6c\xb1\xcd\x0e\x07\x78\x14\x8f\xe6\x28\x1e\xc3\x63\x79\x1c\x47\xf3\x78\x9e\xc0\x13\x39\x86\x27\xf1\x64\xde\x85\x63\x79\x0a\xef\xca\xbb\x71\x1c\xef\xce\x7b\xf0\x54\x8e\xe7\x3d\x79\x2f\xde\x9b\x13\x78\x1f\xde\x97\xa7\x71\x22\xef\xc7\xfb\xf3\x01\x9c\xc4\x07\xf2\x74\x9e\xc1\xc9\x9c\xc2\x41\x76\xd9\xe3\x10\xa7\x72\x1a\xa7\x73\x06\x1f\xc4\x07\x73\x26\x1f\xc2\x87\xf2\x61\x9c\xc5\xd9\x9c\xc3\xb9\x1c\x66\x9f\xf3\x78\x26\xe7\xf3\x2c\x3e\x9c\x8f\xe0\x02\x3e\x92\x8f\xe2\xa3\x79\x36\x1f\xc3\xc7\xf2\x1c\x2e\xe4\xb9\x7c\x1c\x1f\xcf\xf3\xf8\x04\x3e\x91\x4f\xe2\x22\x3e\x99\x4f\xe1\x53\x79\x3e\x17\xf3\x02\x5e\xc8\x25\x5c\xca\xa7\xf1\x22\x2e\xe3\x72\x3e\x9d\xcf\xe0\x0a\x5e\xcc\x4b\xb8\x92\xab\xf8\x4c\xae\xe6\xa5\x5c\xc3\xcb\x78\x39\xaf\xe0\x5a\x5e\xc9\x67\xf1\x7f\x78\x15\x9f\xcd\xe7\xf0\xb9\x5c\xc7\xe7\xf1\xf9\x7c\x01\xaf\xe6\x0b\xf9\x22\xbe\x98\xeb\xf9\x12\xbe\x94\x2f\xe3\x35\x7c\x39\x5f\xc1\x57\xf2\x5a\xbe\x8a\xaf\xe6\x6b\x78\x1d\x5f\xcb\xd7\xf1\xf5\xdc\xc0\x37\xf0\x8d\x7c\x13\x37\xf2\xcd\x7c\x0b\xdf\xca\x4d\x7c\x1b\xdf\xce\x77\x70\x33\xdf\xc9\x77\xf1\xdd\xdc\xc2\xf7\xf0\xbd\x7c\x1f\xaf\xe7\x0d\x7c\x3f\x3f\xc0\xad\xfc\x20\x3f\xc4\x0f\x73\x1b\x3f\xc2\x8f\xf2\x63\xdc\xce\x8f\xf3\x13\xfc\x24\x6f\xe4\xa7\xf8\x69\x7e\x86\x37\xf1\xb3\xfc\x1c\x3f\xcf\x1d\xfc\x02\xbf\xc8\x2f\x71\x27\xbf\xcc\xaf\xf0\xab\xdc\xc5\xaf\xf1\xeb\xfc\x06\x77\xf3\x9b\xfc\x16\xbf\xcd\x3d\xfc\x0e\xbf\xcb\xef\x71\x2f\xbf\xcf\x1f\xf0\x87\xdc\xc7\x1f\xf1\xc7\xfc\x09\x6f\xe6\x4f\xf9\x33\xfe\x9c\xfb\xf9\x0b\xfe\x92\xbf\xe2\x2d\xfc\x35\x7f\xc3\xdf\xf2\x56\xfe\x8e\xbf\xe7\x1f\x78\x80\x7f\xe4\x9f\xf8\x67\x1e\xe4\x5f\xf8\x57\xfe\x8d\xb7\xf1\xef\xfc\x07\xff\xc9\x43\xfc\x17\xff\xcd\xff\x18\x18\x65\xb4\x21\xc3\xc6\x18\xcb\xd8\xc6\x31\x01\x33\xca\x8c\x36\x51\x66\x8c\x19\x6b\xc6\x99\x68\x33\xde\x4c\x30\x13\x4d\x8c\x99\x64\x26\x9b\x5d\x4c\xac\x99\x62\x76\x35\xbb\x99\x38\xb3\xbb\xd9\xc3\x4c\x35\xf1\x66\x4f\xb3\x97\xd9\xdb\x24\x98\x7d\xcc\xbe\x66\x9a\x49\x34\xfb\x99\xfd\xcd\x01\x26\xc9\x1c\x68\xa6\x9b\x19\x26\xd9\xa4\x98\xa0\x71\x8d\x67\x42\x26\xd5\xa4\x99\x74\x93\x61\x0e\x32\x07\x9b\x4c\x73\x88\x39\xd4\x1c\x66\xb2\x4c\xb6\xc9\x31\xb9\x26\x6c\x7c\x93\x67\x66\x9a\x7c\x33\xcb\x1c\x6e\x8e\x30\x05\xe6\x48\x73\x94\x39\xda\xcc\x36\xc7\x98\x63\xcd\x1c\x53\x68\xe6\x9a\xe3\xcc\xf1\x66\x9e\x39\xc1\x9c\x68\x4e\x32\x45\xe6\x64\x73\x8a\x39\xd5\xcc\x37\xc5\x66\x81\x59\x68\x4a\x4c\xa9\x39\xcd\x2c\x32\x65\xa6\xdc\x9c\x6e\xce\x30\x15\x66\xb1\x59\x62\x2a\x4d\x95\x39\xd3\x54\x9b\xa5\xa6\xc6\x2c\x33\xcb\xcd\x0a\x53\x6b\x56\x9a\xb3\xcc\x7f\xcc\x2a\x73\xb6\x39\xc7\x9c\x6b\xea\xcc\x79\xe6\x7c\x73\x81\x59\x6d\x2e\x34\x17\x99\x8b\x4d\xbd\xb9\xc4\x5c\x6a\x2e\x33\x6b\xcc\xe5\xe6\x0a\x73\xa5\x59\x6b\xae\x32\x57\x9b\x6b\xcc\x3a\x73\xad\xb9\xce\x5c\x6f\x1a\xcc\x0d\xe6\x46\x73\x93\x69\x34\x37\x9b\x5b\xcc\xad\xa6\xc9\xdc\x66\x6e\x37\x77\x98\x66\x73\xa7\xb9\xcb\xdc\x6d\x5a\xcc\x3d\xe6\x5e\x73\x9f\x59\x6f\x36\x98\xfb\xcd\x03\xa6\xd5\x3c\x68\x1e\x32\x0f\x9b\x36\xf3\x88\x79\xd4\x3c\x66\xda\xcd\xe3\xe6\x09\xf3\xa4\xd9\x68\x9e\x32\x4f\x9b\x67\xcc\x26\xf3\xac\x79\xce\x3c\x6f\x3a\xcc\x0b\xe6\x45\xf3\x92\xe9\x34\x2f\x9b\x57\xcc\xab\xa6\xcb\xbc\x66\x5e\x37\x6f\x98\x6e\xf3\xa6\x79\xcb\xbc\x6d\x7a\xcc\x3b\xe6\x5d\xf3\x9e\xe9\x35\xef\x9b\x0f\xcc\x87\xa6\xcf\x7c\x64\x3e\x36\x9f\x98\xcd\xe6\x53\xf3\x99\xf9\xdc\xf4\x9b\x2f\xcc\x97\xe6\x2b\xb3\xc5\x7c\x6d\xbe\x31\xdf\x9a\xad\xe6\x3b\xf3\xbd\xf9\xc1\x0c\x98\x1f\xcd\x4f\xe6\x67\x33\x68\x7e\x31\xbf\x9a\xdf\xcc\x36\xf3\xbb\xf9\xc3\xfc\x69\x86\xcc\x5f\xe6\x6f\xf3\x8f\x05\x4b\x59\xda\x22\x8b\x2d\x63\x59\x96\x6d\x39\x56\xc0\x1a\x65\x8d\xb6\xa2\xac\x31\xd6\x58\x6b\x9c\x15\x6d\x8d\xb7\x26\x58\x13\xad\x18\x6b\x92\x35\xd9\xda\xc5\x8a\xb5\xa6\x58\xbb\x5a\xbb\x59\x71\xd6\xee\xd6\x1e\xd6\x54\x2b\xde\xda\xd3\xda\xcb\xda\xdb\x4a\xb0\xf6\xb1\xf6\xb5\xa6\x59\x89\xd6\x7e\xd6\xfe\xd6\x01\x56\x92\x75\xa0\x35\xdd\x9a\x61\x25\x5b\x29\x56\xd0\x72\x2d\xcf\x0a\x59\xa9\x56\x9a\x95\x6e\x65\x58\x07\x59\x07\x5b\x99\xd6\x21\xd6\xa1\xd6\x61\x56\x96\x95\x6d\xe5\x58\xb9\x56\xd8\xf2\xad\x3c\x6b\xa6\x95\x6f\xcd\xb2\x0e\xb7\x8e\xb0\x0a\xac\x23\xad\xa3\xac\xa3\xad\xd9\xd6\x31\xd6\xb1\xd6\x1c\xab\xd0\x9a\x6b\x1d\x67\x1d\x6f\xcd\xb3\x4e\xb0\x4e\xb4\x4e\xb2\x8a\xac\x93\xad\x53\xac\x53\xad\xf9\x56\xb1\xb5\xc0\x5a\x68\x95\x58\xa5\xd6\x69\xd6\x22\xab\xcc\x2a\xb7\x4e\xb7\xce\xb0\x2a\xac\xc5\xd6\x12\xab\xd2\xaa\xb2\xce\xb4\xaa\xad\xa5\x56\x8d\xb5\xcc\x5a\x6e\xad\xb0\x6a\xad\x95\xd6\x59\xd6\x7f\xac\x55\xd6\xd9\xd6\x39\xd6\xb9\x56\x9d\x75\x9e\x75\xbe\x75\x81\xb5\xda\xba\xd0\xba\xc8\xba\xd8\xaa\xb7\x2e\xb1\x2e\xb5\x2e\xb3\xd6\x58\x97\x5b\x57\x58\x57\x5a\x6b\xad\xab\xac\xab\xad\x6b\xac\x75\xd6\xb5\xd6\x75\xd6\xf5\x56\x83\x75\x83\x75\xa3\x75\x93\xd5\x68\xdd\x6c\xdd\x62\xdd\x6a\x35\x59\xb7\x59\xb7\x5b\x77\x58\xcd\xd6\x9d\xd6\x5d\xd6\xdd\x56\x8b\x75\x8f\x75\xaf\x75\x9f\xb5\xde\xda\x60\xdd\x6f\x3d\x60\xb5\x5a\x0f\x5a\x0f\x59\x0f\x5b\x6d\xd6\x23\xd6\xa3\xd6\x63\x56\xbb\xf5\xb8\xf5\x84\xf5\xa4\xb5\xd1\x7a\xca\x7a\xda\x7a\xc6\xda\x64\x3d\x6b\x3d\x67\x3d\x6f\x75\x58\x2f\x58\x2f\x5a\x2f\x59\x9d\xd6\xcb\xd6\x2b\xd6\xab\x56\x97\xf5\x9a\xf5\xba\xf5\x86\xd5\x6d\xbd\x69\xbd\x65\xbd\x6d\xf5\x58\xef\x58\xef\x5a\xef\x59\xbd\xd6\xfb\xd6\x07\xd6\x87\x56\x9f\xf5\x91\xf5\xb1\xf5\x89\xb5\xd9\xfa\xd4\xfa\xcc\xfa\xdc\xea\xb7\xbe\xb0\xbe\xb4\xbe\xb2\xb6\x58\x5f\x5b\xdf\x58\xdf\x5a\x5b\xad\xef\xac\xef\xad\x1f\xac\x01\xeb\x47\xeb\x27\xeb\x67\x6b\xd0\xfa\xc5\xfa\xd5\xfa\xcd\xda\x66\xfd\x6e\xfd\x61\xfd\x69\x0d\x59\x7f\x59\x7f\x5b\xff\xd8\xb0\x95\xad\x6d\xb2\xd9\x36\xb6\x65\xdb\xb6\x63\x07\xec\x51\xf6\x68\x3b\xca\x1e\x63\x8f\xb5\xc7\xd9\xd1\xf6\x78\x7b\x82\x3d\xd1\x8e\xb1\x27\xd9\x93\xed\x5d\xec\x58\x7b\x8a\xbd\xab\xbd\x9b\x1d\x67\xef\x6e\xef\x61\x4f\xb5\xe3\xed\x3d\xed\xbd\xec\xbd\xed\x04\x7b\x1f\x7b\x5f\x7b\x9a\x9d\x68\xef\x67\xef\x6f\x1f\x60\x27\xd9\x07\xda\xd3\xed\x19\x76\xb2\x9d\x62\x07\x6d\xd7\xf6\xec\x90\x9d\x6a\xa7\xd9\xe9\x76\x86\x7d\x90\x7d\xb0\x9d\x69\x1f\x62\x1f\x6a\x1f\x66\x67\xd9\xd9\x76\x8e\x9d\x6b\x87\x6d\xdf\xce\xb3\x67\xda\xf9\xf6\x2c\xfb\x70\xfb\x08\xbb\xc0\x3e\xd2\x3e\xca\x3e\xda\x9e\x6d\x1f\x63\x1f\x6b\xcf\xb1\x0b\xed\xb9\xf6\x71\xf6\xf1\xf6\x3c\xfb\x04\xfb\x44\xfb\x24\xbb\xc8\x3e\xd9\x3e\xc5\x3e\xd5\x9e\x6f\x17\xdb\x0b\xec\x85\x76\x89\x5d\x6a\x9f\x66\x2f\xb2\xcb\xec\x72\xfb\x74\xfb\x0c\xbb\xc2\x5e\x6c\x2f\xb1\x2b\xed\x2a\xfb\x4c\xbb\xda\x5e\x6a\xd7\xd8\xcb\xec\xe5\xf6\x0a\xbb\xd6\x5e\x69\x9f\x65\xff\xc7\x5e\x65\x9f\x6d\x9f\x63\x9f\x6b\xd7\xd9\xe7\xd9\xe7\xdb\x17\xd8\xab\xed\x0b\xed\x8b\xec\x8b\xed\x7a\xfb\x12\xfb\x52\xfb\x32\x7b\x8d\x7d\xb9\x7d\x85\x7d\xa5\xbd\xd6\xbe\xca\xbe\xda\xbe\xc6\x5e\x67\x5f\x6b\x5f\x67\x5f\x6f\x37\xd8\x37\xd8\x37\xda\x37\xd9\x8d\xf6\xcd\xf6\x2d\xf6\xad\x76\x93\x7d\x9b\x7d\xbb\x7d\x87\xdd\x6c\xdf\x69\xdf\x65\xdf\x6d\xb7\xd8\xf7\xd8\xf7\xda\xf7\xd9\xeb\xed\x0d\xf6\xfd\xf6\x03\x76\xab\xfd\xa0\xfd\x90\xfd\xb0\xdd\x66\x3f\x62\x3f\x6a\x3f\x66\xb7\xdb\x8f\xdb\x4f\xd8\x4f\xda\x1b\xed\xa7\xec\xa7\xed\x67\xf0\x10\x1e\xb6\x37\xd9\xcf\xda\xcf\xe1\x51\x3c\x86\x0e\xfb\x79\xb4\xe1\x11\xbc\x60\x77\xe0\x7c\x3c\x87\x8b\x71\x9f\xfd\x82\xfd\xa2\xfd\x92\xdd\x69\xbf\x6c\xbf\x82\x17\xed\x57\xed\x2e\xfb\x35\x3c\x8d\x67\xec\xd7\xed\x37\xb0\xd1\xee\xb6\xdf\xb4\xdf\xb2\xdf\xb6\x7b\xec\x77\xec\x77\xed\xf7\xec\x5e\xfb\x7d\xfb\x03\xfb\x43\xbb\xcf\xfe\xc8\xfe\xd8\xfe\xc4\xde\x6c\x7f\x6a\x7f\x66\x7f\x6e\xf7\xdb\x5f\xd8\x5f\xda\x5f\xe1\x37\x7b\x8b\xfd\xb5\xfd\x8d\xfd\xad\xbd\xd5\xfe\xce\xfe\xde\xfe\xc1\x1e\xb0\x7f\xb4\x7f\xb2\x7f\xb6\x07\xed\x5f\xec\x5f\xed\xdf\xec\x6d\xf6\xef\xf6\x1f\xf6\x9f\xf6\x90\xfd\x97\xfd\xb7\xfd\x0f\xd6\x38\x70\x94\xa3\x1d\x72\xd8\x31\x8e\xe5\xd8\x8e\xe3\x04\x9c\x51\xce\x68\x27\xca\x19\xe3\x8c\x75\xc6\x39\xd1\xce\x78\x34\x38\x13\x70\x23\x6e\xc0\x0f\xce\x44\x27\x06\x77\xe2\x6a\x67\x92\x33\x19\x8d\xb8\x1b\x57\x3a\xbb\x60\x1d\xae\x75\x62\x9d\x29\xce\xae\xce\x6e\x4e\x9c\xb3\xbb\xb3\x87\x33\xd5\x89\x77\xf6\x74\xf6\x72\xf6\x76\x12\x9c\x7d\x9c\x7d\x9d\x69\x4e\xa2\xb3\x9f\xb3\xbf\x73\x80\x93\xe4\x1c\xe8\x4c\x77\x66\x38\xc9\x4e\x8a\x13\x74\x5c\xc7\x73\x42\x4e\xaa\x93\xe6\xa4\x3b\x19\xce\x41\xce\xc1\x4e\xa6\x73\x88\x73\xa8\x73\x98\x93\xe5\x64\x3b\x39\x4e\xae\x13\x76\x7c\x27\xcf\x99\xe9\xe4\x3b\xb3\x9c\xc3\x9d\x23\x9c\x02\xe7\x48\xe7\x28\xe7\x68\x67\xb6\x73\x8c\x73\xac\x33\xc7\x29\xc4\xe3\xce\x5c\xe7\x38\xe7\x78\x67\x9e\x73\x82\x73\xa2\x73\x92\x53\xe4\x9c\xec\x9c\xe2\x9c\xea\xcc\x77\x8a\x9d\x05\xce\x42\xa7\xc4\x29\x75\x4e\x73\x16\x39\x65\x4e\xb9\x73\xba\x73\x86\x53\xe1\x2c\x76\x96\x38\x95\x4e\x95\x73\xa6\x53\xed\x2c\x75\x6a\x9c\x65\xce\x72\x67\x85\x53\xeb\xac\x74\xce\x72\xfe\xe3\xac\x72\xce\x76\xce\x71\xce\x75\xea\x9c\xf3\x9c\xf3\x9d\x0b\x9c\xd5\xce\x85\xce\x45\xce\xc5\x4e\xbd\x73\x89\x73\xa9\x73\x99\xb3\xc6\xb9\xdc\xb9\xc2\xb9\xd2\x59\xeb\x5c\xe5\x5c\xed\x5c\xe3\xac\x73\xae\x75\xae\x73\xae\x77\x1a\x9c\x1b\x9c\x1b\x9d\x9b\x9c\x46\xe7\x66\xe7\x16\xe7\x56\xa7\xc9\xb9\xcd\xb9\xdd\xb9\xc3\x69\x76\xee\x74\xee\x72\xee\x76\x5a\x9c\x7b\x9c\x7b\x9d\xfb\x9c\xf5\xce\x06\xe7\x7e\xe7\x01\xa7\xd5\x79\xd0\x79\xc8\x79\xd8\x69\x73\x1e\x71\x1e\x75\x1e\x73\xda\x9d\xc7\x9d\x27\x9c\x27\x9d\x8d\xce\x53\xce\xd3\xce\x33\xce\x26\xe7\x59\xe7\x39\xe7\x79\xa7\xc3\x79\xc1\x79\xd1\x79\xc9\xe9\x74\x5e\x76\x5e\x71\x5e\x75\xba\x9c\xd7\x9c\xd7\x9d\x37\x9c\x6e\xe7\x4d\xe7\x2d\xe7\x6d\xa7\xc7\x79\xc7\x79\xd7\x79\xcf\xe9\x75\xde\x77\x3e\x70\x3e\x74\xfa\x9c\x8f\x9c\x8f\x9d\x4f\x9c\xcd\xce\xa7\xce\x67\xce\xe7\x4e\xbf\xf3\x85\xf3\xa5\xf3\x95\xb3\xc5\xf9\xda\xf9\xc6\xf9\xd6\xd9\xea\x7c\xe7\x7c\xef\xfc\xe0\x0c\x38\x3f\x3a\x3f\x39\x3f\x3b\x83\xce\x2f\xce\xaf\xce\x6f\xce\x36\xe7\x77\xe7\x0f\xe7\x4f\x67\xc8\xf9\xcb\xf9\xdb\xf9\x27\x80\x80\x0a\xe8\x00\x05\x38\x60\x02\x56\xc0\x0e\x38\x81\x40\x60\x54\x60\x74\x20\x2a\x30\x26\x30\x36\x30\x2e\x10\x1d\x18\x1f\x98\x10\x98\x18\x88\x09\x4c\x0a\x4c\x0e\xec\x12\x88\x0d\x4c\x09\xec\x1a\xd8\x2d\x10\x17\xd8\x3d\xb0\x47\x60\x6a\x20\x3e\xb0\x67\x60\xaf\xc0\xde\x81\x84\xc0\x3e\x81\x7d\x03\xd3\x02\x89\x81\xfd\x02\xfb\x07\x0e\x08\x24\x05\x0e\x0c\x4c\x0f\xcc\x08\x24\x07\x52\x02\xc1\x80\x1b\xf0\x02\xa1\x40\x6a\x20\x2d\x90\x1e\xc8\x08\x1c\x14\x38\x38\x90\x19\x38\x24\x70\x68\xe0\xb0\x40\x56\x20\x3b\x90\x13\xc8\x0d\x84\x03\x7e\x20\x2f\x30\x33\x90\x1f\x98\x15\x38\x3c\x70\x44\xa0\x20\x70\x64\xe0\xa8\xc0\xd1\x81\xd9\x81\x63\x02\xc7\x06\xe6\x04\x0a\x03\x73\x03\xc7\x05\x8e\x0f\xcc\x0b\x9c\x10\x38\x31\x70\x52\xa0\x28\x70\x72\xe0\x94\xc0\xa9\x81\xf9\x81\xe2\xc0\x82\xc0\xc2\x40\x49\xa0\x34\x70\x5a\x60\x51\xa0\x2c\x50\x1e\x38\x3d\x70\x46\xa0\x22\xb0\x38\xb0\x24\x50\x19\xa8\x0a\x9c\x19\xa8\x0e\x2c\x0d\xd4\x04\x96\x05\x96\x5b\x8b\x2a\x56\x56\x95\xa5\xd8\xcb\x96\x94\x27\x27\x27\x87\x47\x62\x76\xb2\x44\x39\xce\x09\x4a\x74\x25\x86\x24\x66\xd8\xd9\x8b\x8b\x17\x56\x57\x2e\xb1\x8b\x47\xa2\x95\xbd\xa0\xba\x74\x79\xa9\x55\x3c\x1c\xec\xec\xca\x45\x95\x4b\x4a\xcf\xb0\x8b\x47\xe2\xe8\xdc\x85\xe5\xd5\x0b\x97\x2d\x3e\xad\xa2\xb4\x76\xf4\xc2\x7f\xdb\xa3\x72\x4b\x2a\x6b\x8a\x17\x2e\x2c\x5d\x52\x33\x6a\x61\xa4\x69\x85\x17\x16\x6f\xef\xb2\x64\x24\x84\x17\x56\x57\x16\xd7\xd8\xbe\x00\x4b\x05\xe8\x8f\x00\x4b\x87\xc3\x28\xff\xdf\x8e\x4a\x23\x4d\xdb\x97\x61\x94\x8e\x44\xcb\x1f\xe9\xb1\x74\x38\x8c\x9e\xb9\xd3\xa0\x16\xed\x34\xa8\x99\xff\xf6\xb5\x28\xd2\x8c\x9a\xb9\xb0\x72\xf1\xe2\x62\x39\x58\xb4\xd3\xc1\xe8\xfc\x9d\xfa\x29\xfb\xb7\xcd\xf9\x0b\x8a\xab\xb9\x6c\x41\x71\xb5\x35\xab\xa6\xbc\xa2\xa4\xd4\x2a\x1f\x0e\xf6\x2c\x99\x49\xb9\xcc\x64\xd6\xc8\x4c\xca\x47\x96\x6e\x96\x8c\xb9\x7c\x24\xea\x59\x87\xeb\xf2\xd3\x47\x1f\xbe\x13\xe3\xf4\x7f\xdb\x51\x47\xec\x3c\xaa\x33\xfe\xeb\x60\x51\x75\x69\xe9\x92\x8a\xe2\x25\x25\xe5\x0b\xad\x82\xe2\x85\xcb\x6a\x4a\xad\x8a\xe1\x10\x55\xb0\xf3\xf7\x2a\x76\x3a\xb0\x0a\x46\x16\xa8\x62\x38\x70\x41\x49\x65\x0d\x57\x94\x54\xd6\x58\x47\x8d\x9c\xbf\x64\xe4\xfc\xa3\x76\x3e\x7f\xc9\xce\xe7\x1f\x35\x72\xfe\x92\x91\x05\x5e\x52\x5c\x55\xb9\xb4\xa6\xba\xb2\xaa\xac\x94\xfc\x25\x8b\xa8\x74\xc9\x22\xfb\x68\x99\x7c\xa5\x4c\xfe\xe8\x91\xc9\x57\x0e\x87\x31\x47\x97\x2d\x5b\xb2\xa8\xb8\x7a\xd9\xe2\x8a\xe2\x65\x35\x63\x2a\x77\x3e\xb2\x8e\x1d\x19\x43\xf5\xc8\x18\x8e\xdd\x79\x0c\xd5\x3b\x8f\xe1\xd8\x91\x31\x54\x8f\x84\x39\x23\x67\x2d\x1d\x0e\xa3\xe7\xec\xb4\x8c\x4b\x77\x5a\xc6\xc2\x9d\x7b\xab\xd9\xb9\xb7\xc2\x91\x6e\x6a\x46\x56\xa4\x70\xfb\x25\xad\xd9\x7e\x49\xe7\x8e\x5c\xd2\x65\x23\x97\x74\xae\xcc\x6a\x99\xcc\x6a\xee\xc8\xac\x96\x0d\x07\x33\xb7\xba\x7c\xc9\x22\xb3\x6c\xfb\x9f\x63\xe6\xfe\xd7\x0c\x97\xed\x7c\x64\xcf\x95\x4b\xbf\x4c\x7e\x35\xc7\xef\x34\xda\x15\x3b\xb5\x4f\xd8\xa9\xbd\xf2\xdf\xb6\x75\xe2\xc8\x5c\xcf\x1a\x0e\xa3\x4e\xfc\xf7\x36\x3e\x2b\xd2\x34\x15\x95\x4b\x16\x2d\x1d\xfe\x15\xa7\xa4\x27\x4b\x4c\x91\x18\x94\xe8\x4a\xf4\x24\x86\x24\xa6\x4a\x4c\x93\x98\x2e\x31\x43\x62\xb6\xc4\x1c\x89\xb9\x12\xc3\x12\x7d\x89\x79\x23\x31\x43\xf8\x19\xc2\xcf\x10\x6e\x86\x70\x33\x84\x9b\x21\xdc\x0c\xe1\x66\x08\x37\x43\xb8\x19\xc2\xcd\x10\x6e\x86\x70\x33\x84\x9b\x21\xdc\x8c\x3c\x73\x74\x59\x65\xf5\x12\x53\xb9\xfd\xcf\x91\xf7\xb2\x65\xce\xd9\xc2\xce\x16\x76\xb6\xb0\xb3\x85\x9d\x2d\xec\x6c\x61\x67\x0b\x3b\x5b\xd8\xd9\xc2\xce\x16\xb6\x3c\x41\x53\xb2\x7d\x33\x77\x98\xb9\xec\x5f\x66\x8e\xcc\x57\x9e\xae\x29\xf2\x74\x4d\xc9\x11\xb6\x3c\x65\x53\x72\x84\x9d\x23\xec\x1c\x61\xe7\x08\x3b\x47\xd8\x39\xc2\xce\x11\x76\x8e\xb0\x73\x64\xde\x39\xb2\xde\xb9\xb2\xde\xb9\xc2\xcf\x15\x7e\xae\xf0\x73\x85\x9f\x2b\xfc\x5c\xe1\xe7\x0a\x3f\x57\xf8\xb9\xc2\xcf\x15\x7e\xae\xf0\x73\x85\x9f\x2b\xfc\x5c\xe1\xe7\x0a\x3f\x2c\xfc\xb0\xf0\xc3\xc2\x0f\x0b\x3f\x2c\xfc\xb0\xf0\xc3\xc2\x0f\x0b\x3f\x2c\xfc\xb0\xf0\xc3\xc2\x0f\x0b\x3f\x2c\xfc\xb0\xf0\xc3\xc2\x0f\x0b\xdf\x17\xbe\x2f\x7c\x5f\xf8\xbe\xf0\x7d\xe1\xfb\x21\x6b\xe6\xc8\xaf\x7e\xd1\x70\x90\x77\x85\xee\x0b\xdd\x17\xba\x2f\x74\x5f\xe8\xbe\xd0\x7d\xa1\xfb\x42\xcf\x13\x7a\x9e\xd0\xf3\x84\x9e\x27\xf4\x3c\xa1\xe7\xc9\xec\xf3\x64\xf6\x79\x32\xfb\x3c\xe1\xe7\x65\x8c\xca\xde\xfe\x24\x19\xf9\x91\x17\x47\x9a\x76\xb6\x3f\x12\x8b\x4b\x47\x9e\x75\x47\x2f\xad\x28\x5e\x5a\x36\xd2\xae\xfc\xb7\x3d\xdc\x4b\x30\x39\x59\x62\x8a\xc4\xa0\x44\x57\xa2\x27\x31\x24\x31\x55\x62\x9a\xc4\x74\x89\x19\x12\xb3\x25\xe6\x48\xcc\x95\x18\x96\xe8\x4b\x1c\x59\x8d\x60\x8a\xf0\x53\x84\x9f\x22\xfc\x14\xe1\xa7\x08\x3f\x45\xf8\x29\xc2\x4f\x49\x8b\x9a\xb3\xf3\xb3\x7a\xe9\x4e\x07\xf2\x0d\x19\x49\x8a\x8c\x24\x45\x46\x92\x22\x23\x49\x91\x91\xa4\xc8\x48\x82\x32\x92\xa0\x8c\x24\x28\x23\x09\xca\x48\x82\x32\x92\xa0\x8c\x24\x28\x23\x09\xca\x4a\x04\x65\x25\x82\xb2\x12\x41\xe1\x07\x85\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\xef\x0a\xdf\x15\xbe\x2b\x7c\x57\xf8\xae\xf0\x5d\xe1\xbb\xc2\x77\x85\xef\x0a\xdf\x15\xbe\x2b\x7c\x57\xf8\xae\xf0\x5d\xe1\xbb\xc2\x77\x85\xef\x09\xdf\x13\xbe\x27\x7c\x4f\xf8\x9e\xf0\x3d\xe1\x7b\xc2\xf7\x84\xef\x09\xdf\x13\xbe\x27\x7c\x4f\xf8\x9e\xf0\x3d\xe1\x7b\xc2\xf7\x84\x1f\x12\x7e\x48\xf8\x21\xe1\x87\x84\x1f\x12\x7e\x48\xf8\x21\xe1\x87\x84\x1f\x12\x7e\x48\xf8\x21\xe1\x87\x84\x1f\x12\x7e\x48\xf8\x21\xe1\x87\x84\x9f\x2a\xfc\x54\xe1\xa7\x0a\x3f\x55\xf8\xa9\xc2\x4f\x15\x7e\xaa\xf0\x53\x85\x9f\x2a\xfc\x54\xe1\xa7\x0a\x3f\x55\xf8\xa9\xc2\x4f\x15\x7e\xaa\xf0\x53\x85\x9f\x26\xfc\x34\xe1\xa7\x09\x3f\x4d\xf8\x69\xc2\x4f\x13\x7e\x9a\xf0\xd3\x84\x9f\x26\xfc\x34\xe1\xa7\x09\x3f\x4d\xf8\x69\xc2\x4f\x13\x7e\x9a\xf0\xd3\x84\x2f\x59\x40\x50\xb2\x80\xa0\x64\x01\x41\xc9\x02\x82\x92\x05\x04\x25\x0b\x08\x4a\x16\x10\x94\x2c\x20\x28\x59\x40\x50\xb2\x80\xa0\x64\x01\x41\xc9\x02\x82\x92\x05\x04\x25\x0b\x08\x4a\x16\x10\x94\x2c\x20\x28\x59\x40\x50\xb2\x80\x60\x86\xf0\x25\x1b\x08\x4a\x36\x10\x94\x6c\x20\x28\xd9\x40\x50\xb2\x81\xa0\x64\x03\x41\xc9\x06\x82\x92\x0d\x04\x25\x1b\x08\x4a\x36\x10\x94\x6c\x20\x28\xd9\x40\x30\x43\xf8\x52\xf3\x04\xb3\x85\x2f\x19\x41\x50\x32\x82\xa0\x64\x04\x41\xc9\x08\x82\x92\x11\x04\x25\x23\x08\x4a\x46\x10\x94\x8c\x20\x28\x19\x41\x50\x32\x82\xa0\x64\x04\x41\xc9\x08\x82\xd9\xc2\xcf\x16\x7e\x8e\xf0\x25\x2b\x08\x4a\x56\x10\x94\xac\x20\x28\x59\x41\x50\xb2\x82\xa0\x64\x05\x41\xc9\x0a\x82\x92\x15\x04\x25\x2b\x08\x4a\x56\x10\xcc\xc9\x09\x14\x9f\x56\x5e\x1e\x4a\xcb\x08\x66\x0c\xb7\x52\xbd\x8c\x1d\xcf\x0c\xc9\x0c\x82\x92\x19\x04\x25\x33\x08\x4a\x66\x10\x94\xcc\x20\x28\x99\x41\x50\x32\x83\xa0\x64\x06\x41\xc9\x04\x82\x92\x09\x04\x25\x13\x08\x4a\x26\x10\x94\x4c\x20\x28\x99\x40\x50\x32\x81\xa0\x64\x02\x41\xc9\x04\x82\x92\x09\x04\x25\x13\x08\x4a\x26\x10\x94\x4c\x20\x28\x99\x40\x50\x32\x81\xa0\x64\x02\x41\x31\x7b\x50\xcc\x1e\x14\xb3\x07\xc5\xec\x41\x31\x7b\x50\xcc\x1e\x14\xb3\x07\x7d\xe9\xcf\x97\xfe\x7c\xe9\x4f\xdc\x1e\x14\xb7\x07\xc5\xed\x41\x71\x7b\x50\xdc\x1e\x14\xb7\x07\xc5\xed\x41\x71\x7b\x50\xdc\x1e\x14\xb7\x07\xc5\xed\x41\x71\x7b\x50\xdc\x1e\x14\xb7\x07\xc5\xed\x41\x71\x7b\x50\xdc\x1e\xcc\x13\x7e\x9e\xf0\xf3\x84\x9f\x27\xfc\x3c\xe1\xe7\x09\x3f\x2f\x2f\xb0\xa8\xba\x78\x79\xe9\xc2\xca\xc5\x0b\x02\xc3\x76\xdf\xde\x1a\xfe\xcc\x4d\x0e\x06\x86\x6b\x93\x9d\xde\xf1\x24\x86\x24\xa6\x4a\x4c\x93\x98\x3e\xa6\xac\xb2\xf2\x8c\xe2\x05\x95\xcb\x77\x3e\x2b\x5b\x62\x8e\xc4\x5c\x89\x61\x89\xbe\xc4\x91\xb5\x70\xc5\xec\xae\x98\xdd\x15\xb3\xbb\x62\x76\x57\xcc\xee\x8a\xd9\x5d\x31\xbb\x9b\x22\xa3\x48\x49\x97\x98\x21\x51\xf8\xe2\x73\x57\x7c\xee\x8a\xcf\x5d\xf1\xb9\x2b\x3e\x77\xc5\xe7\xae\xf8\xdc\x0d\x06\xa3\x4a\x2a\x6b\x16\x94\x56\x54\xae\xf8\x77\x52\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\xf9\x81\xba\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x75\x57\xa4\xee\x8a\xd4\x5d\x91\xba\x2b\x52\x77\x45\xea\xae\x48\xdd\x15\xa9\xbb\x22\x6d\x57\xa4\xed\x8a\x94\x5d\x91\xb2\x2b\x52\x76\x45\xca\x6e\x9a\x6f\x6a\x2a\x97\x54\x2e\x1d\x53\x52\x5e\x5a\x5d\xba\xb4\x7c\xe9\xf0\xd1\xa8\xec\x8a\xaa\xb2\xe2\xe1\x66\xa0\x78\x49\x65\x4d\x69\x45\x69\x79\x71\x94\x5f\xb5\xb4\xbc\xa2\x72\xc9\xf0\xdb\x8e\x5f\x23\x9f\xcf\xaa\x94\x56\xd4\xd1\x8b\xcb\x17\x56\xcb\xe7\x51\x73\x77\xfa\xf2\xa8\xa3\x17\x97\x2e\x1a\xf9\xd2\xf8\xf2\xca\x9a\xe2\xff\x62\x99\x61\x16\xe7\x94\xd6\x14\x9b\x99\xc5\x8b\x17\x17\xdb\xc2\xe1\x13\x4b\x6b\x8a\xc9\xaf\x29\x36\x85\x65\xa5\x35\xc5\xbc\x1d\x64\x8e\x28\xae\xaa\x2a\xb6\x0a\x8a\x17\x2f\x28\x29\xd6\x47\x2e\xd3\x47\x2d\xd3\xf3\xca\x6d\x21\xeb\xd9\xe5\x74\x6c\x59\xa5\x99\x53\xbe\x68\x71\x31\x15\x16\x2f\xb3\x65\x14\x34\xbb\xac\x9c\x72\xcb\xca\x69\xf6\xd2\xf2\xa8\x59\x3b\x8d\x60\x9c\x7c\x61\xc7\xf1\xa8\xe2\xc8\xc4\xa3\x4a\x77\x9e\x6e\xe9\x8e\xe9\x96\xef\x98\x6e\xcc\xb2\xff\x3e\x75\x64\x32\xc3\xe7\xf3\x82\xed\x93\x59\xb4\x7d\x32\xa6\xa4\xb4\xa2\xa6\xd8\x96\xbe\xf8\xac\xed\x53\xda\xfe\x61\xcd\xf0\x94\xb6\x77\x66\xce\x18\x9e\x52\xc5\xc8\x94\x96\x2c\xd3\xb5\xe5\x76\xe5\xc8\x7c\xa8\xba\xac\xd2\x5a\xba\x7d\x32\x29\x66\x38\x50\x4d\xf1\x32\x5b\xb8\x54\x55\x56\x4e\x0b\xcb\xca\xa9\x6a\x69\xb9\xa9\xdc\xbe\xc0\x51\x3b\xaf\xed\xb8\xff\x31\xbc\xa8\xca\x9d\xaf\xce\xb2\x9d\xaf\x4e\x65\xe4\xea\x8c\xdc\x13\xe1\x64\x6b\x78\x78\x29\x8e\xac\x8e\xdc\xcb\x22\x49\x37\xec\x71\x55\x59\x79\x8a\x35\x7c\xde\x8e\xcf\xe4\xfe\x95\x52\xd9\x95\x52\xd9\x95\x52\xd9\x95\x52\xd9\x95\x52\xd9\x95\x52\xd9\x15\xa1\xba\x22\x54\x57\x84\xea\x8a\x50\x5d\x11\xaa\x2b\x42\x75\x45\xa8\xae\x08\xd5\x15\xa1\xba\x22\x54\x57\x84\xea\x8a\x50\x5d\x11\xaa\x2b\x42\x75\x45\xa8\xae\x08\xd5\x15\xa1\xba\x22\x54\x57\x84\xea\x8a\x50\x5d\x11\xaa\x2b\x42\x75\x45\xa8\xae\x08\xd5\x15\xa1\xba\x22\x54\x57\x84\xea\x8a\x50\x5d\x11\xaa\x2b\x42\x75\x45\xa8\xae\x08\xd5\x15\xa1\xba\x79\x23\x7c\x2f\x39\x79\x38\x65\x4a\x49\x4e\x0e\xba\x3b\x5a\xa1\x94\x48\x2b\x18\x69\xfd\xfb\xa9\x17\x69\x85\x22\xad\xd4\x48\x2b\x2d\xd2\x4a\x8f\xb4\x32\x76\xb4\x52\x23\x34\x79\x5e\x79\xc9\xe1\xc8\x3b\x3b\x58\x29\x5e\xa4\xdf\x94\x48\x6f\x29\x91\xde\x52\x22\xbd\x05\xff\x1d\x7b\x64\xc4\xc1\xc8\x88\x83\x91\x71\x06\x23\xfd\x05\x23\xe3\x0c\x46\x7a\x0e\x46\x7a\x0e\x46\x7a\x76\x23\x3d\xbb\x91\x9e\xdd\x48\xcf\x6e\x64\x2d\xdc\x08\xc3\x8d\x30\xdc\x08\xc3\x8d\x30\xdc\x08\xc3\x8d\x30\xbc\x08\xc3\x8b\x30\xbc\x08\xc3\x8b\x30\xbc\x08\xe3\xdf\x75\xf1\x22\x0c\x2f\xc2\xf0\x22\x0c\xef\xdf\xf5\x8e\x9c\x91\x1a\x39\x23\x35\x72\x46\x6a\xe4\x8c\xd4\xc8\x19\x69\x91\x51\xa5\x45\xc6\x92\x16\x19\x4b\x5a\x64\x2c\x69\x91\x9e\xd3\x22\x3d\xa7\x45\x7a\x4e\x8b\xf4\x9c\x16\xe9\x39\x3d\xd2\x73\x7a\x64\xbe\xe9\x11\x46\x7a\x84\x91\x1e\x61\xa4\x47\x18\xe9\x11\x46\x7a\x84\x91\x1e\x61\xa4\x47\x18\x19\x11\x46\x46\x84\x91\x11\x61\x64\x44\x18\x19\x11\x46\x46\x84\x91\x11\x61\x48\xc1\xe5\x85\xfe\x5d\x8b\x7f\x7b\xdb\xc1\x4a\x89\xfc\x72\x52\x92\x53\x22\xad\xc8\x3d\x9c\xec\x46\x5a\x5e\xa4\x15\x8a\xb4\x52\x23\xad\xb4\x48\x2b\x3d\xd2\xca\x10\xfe\x8e\xdf\x46\x4a\x4a\x84\x25\xc5\xa2\x27\xde\xf7\x52\x23\xec\xc8\x3d\xb1\x63\x5b\xd9\x4b\xdd\x11\x43\x12\x53\x25\xca\xfc\xc4\xfd\x9e\xb8\xdf\x13\xf7\x7b\xe2\x7e\x4f\xdc\xef\x89\xfb\x3d\x71\xbf\x27\xee\xf7\xa4\xa0\xf7\xd2\xfe\x1d\x43\x64\x36\x91\x75\x4d\x89\xdc\x97\x3b\xb6\xb7\xbd\xb4\x1d\x51\xc6\x21\x85\xbd\x27\x85\xbd\x27\x39\x84\x27\x39\x84\x27\x39\x84\x27\x39\x84\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x27\x85\xbd\x97\x9e\x17\x79\xc2\xfd\x7b\xdf\x49\x5f\x52\xdc\x7b\x3b\xae\xd7\x8e\x6b\x22\xc5\xbd\xb7\x63\x2d\x76\xdc\x6b\x91\xf3\x64\x0c\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\x52\xdc\x7b\xb2\xe5\xef\xc9\x96\xbf\x27\x5b\xfe\x9e\x14\xf6\x9e\x14\xf6\x9e\x14\xf6\x9e\x14\xf6\x9e\x14\xf6\x9e\x14\xf6\x9e\x14\xf6\x9e\x14\xf6\x9e\x6c\xf9\x7b\xb2\xe5\xef\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\x0e\xe3\x49\xa1\xef\x49\xa1\xef\x49\xa1\xef\x49\x1e\xe3\x85\x77\xfc\x4a\xd2\xbd\x1d\x9f\xc8\x08\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\xf1\x24\x93\x09\xc9\x46\x7f\x48\x36\xfa\x43\xb2\xd1\x1f\x92\x8d\xfe\x90\x6c\x0a\x84\x64\x53\x20\x24\x9b\x02\x21\xd9\x14\x08\xc9\x46\x7f\x48\x9e\xbe\x21\xd9\x0e\x08\xc9\x76\x40\x48\xb6\x03\x42\xb2\x1d\x10\x92\xed\x80\x90\x6c\x07\x84\x64\x3b\x20\x24\xdb\x01\x21\xd9\x0e\x08\xc9\x76\x40\x48\xb6\x03\x42\xb2\x1d\x10\x92\xed\x80\x90\x6c\x07\x84\x64\x3b\x20\x24\xdb\x01\x21\xd9\x0e\x08\xc9\x76\x40\x48\xb6\x03\x42\xb2\x1d\x10\x92\xed\x80\x90\x6c\x07\x84\x64\x3b\x20\x24\xdb\x01\x21\xd9\xde\x0f\xc9\xf6\x7e\x48\x76\x02\x42\xb2\x13\x10\x92\x9d\x80\xd0\xc8\x4e\x40\x4a\x78\x64\xfd\x52\xc2\x23\xeb\x97\x12\x1e\x59\xbf\x94\xf0\xc8\xfa\xa5\x84\x47\xd6\x2f\x25\x3c\xb2\x7e\x29\xe1\x91\xf5\x4b\x09\x27\xef\x38\x3f\x5d\x62\x86\xc4\x6c\x89\x39\x12\x73\x25\x86\x25\xfa\x12\xf3\x46\x62\x8a\xf0\x53\x84\x9f\x22\xfc\x14\xe1\xa7\x08\x3f\x45\xf8\x29\xc2\x4f\x11\x7e\x8a\xf0\x53\x84\x9f\x22\xfc\x14\xe1\xa7\x08\x3f\x45\xf8\x29\xc2\x4f\x11\x7e\x50\xf8\x41\xe1\x07\x85\x1f\x14\x7e\x50\xf8\x41\xe1\x07\x85\xbf\x63\xfd\x82\xc2\x0f\x0a\x3f\x28\xfc\xa0\xf0\x83\xc2\x0f\x0a\x3f\x28\xfc\xa0\xf0\x5d\xe1\xbb\xc2\x77\x85\xef\x0a\xdf\x15\xbe\x2b\x7c\x57\xf8\xae\xf0\x5d\xe1\xbb\xc2\x77\x85\xef\x0a\xdf\x15\xbe\x2b\x7c\x57\xf8\xae\xf0\x3d\xe1\x7b\xc2\xf7\x84\xef\x09\xdf\x13\xbe\x27\x7c\x4f\xf8\x9e\xf0\x3d\xe1\x7b\xc2\xf7\x84\xef\x09\xdf\x13\xbe\x27\x7c\x4f\xf8\x9e\xf0\x43\xc2\x0f\x09\x3f\x24\xfc\x90\xf0\x43\xc2\x0f\x09\x3f\x24\xfc\x90\xf0\x43\xc2\x0f\x09\x3f\x24\xfc\x90\xf0\x43\xc2\x0f\x09\x3f\x24\xfc\x90\xf0\x53\x85\x9f\x2a\xfc\x54\xe1\xa7\x0a\x3f\x55\xf8\xa9\xc2\x4f\x15\x7e\xaa\xf0\x53\x85\x9f\x2a\xfc\x54\xe1\xa7\x0a\x3f\x55\xf8\xa9\xc2\x4f\x15\x7e\xaa\xf0\xd3\x84\x9f\x26\xfc\x34\xe1\xa7\x09\x3f\x4d\xf8\x69\xc2\x4f\x13\x7e\x9a\xf0\xd3\x84\x9f\x26\xfc\x34\xe1\xa7\x09\x3f\x4d\xf8\x69\xc2\x4f\x13\x7e\x9a\xf0\xd3\x85\x9f\x2e\xfc\x74\xe1\xa7\x0b\x3f\x5d\xf8\xe9\xc2\x4f\x17\x7e\xba\xf0\xd3\x85\x9f\x2e\xfc\x74\xe1\xa7\x0b\x3f\x5d\xf8\xe9\xc2\x4f\x17\x7e\xba\xf0\x33\x84\x9f\x21\xfc\x0c\xe1\x67\x08\x3f\x43\xf8\x19\xc2\xcf\x10\x7e\x86\xf0\x33\x84\x9f\x21\xfc\x0c\xe1\x67\x08\x3f\x43\xf8\x19\xc2\xcf\x10\x7e\x86\xf0\xb3\x85\x9f\x2d\xfc\x6c\xe1\x67\x0b\x3f\x5b\xf8\xd9\xc2\xcf\x16\x7e\xb6\xf0\xb3\x85\x9f\x2d\xfc\x6c\xe1\x67\x0b\x3f\x5b\xf8\xd9\xc2\xcf\x16\x7e\xb6\xf0\x73\x84\x9f\x23\xfc\x1c\xe1\xe7\x08\x3f\x47\xf8\x39\xc2\xcf\x11\x7e\x8e\xf0\x73\x84\x9f\x23\xfc\x1c\xe1\xe7\x08\x3f\x47\xf8\x39\xc2\xcf\x11\x7e\x8e\xf0\x73\x85\x9f\x2b\xfc\x5c\xe1\xe7\x0a\x3f\x57\xf8\xb9\xc2\xcf\x15\x7e\xae\xf0\x73\x85\x9f\x2b\xfc\x5c\xe1\xe7\x09\x67\xc4\xd3\x29\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xd3\xf2\xac\xe3\x87\xff\x37\x3c\x6b\xc5\x48\x38\x7e\xe4\x2f\xf1\xad\x18\x0e\x81\xe3\x77\x6c\x1c\x07\x56\xec\x68\x8d\x9c\x27\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x67\x7c\xf1\x8c\x2f\x9e\xf1\xc5\x33\xbe\x78\xc6\x17\xcf\xf8\xe2\x19\x5f\x3c\xe3\x8b\x57\x7c\xf1\x89\x2f\x3e\xf1\xc5\x27\xbe\xf8\xc4\x17\x9f\xf8\xe2\x13\x5f\x7c\xe2\x8b\x4f\x7c\xf1\x89\x2f\x3e\xf1\xc5\x27\xbe\xf8\xc4\x17\x9f\xf8\xe2\x13\x3f\x7b\x07\x57\xe6\x29\x3e\xf1\xc5\x27\xbe\xf8\xc4\x17\x9f\xf8\xe2\x13\x5f\x7c\xe2\x8b\x4f\x7c\xf1\x89\x2f\x3e\xf1\xc5\x27\xbe\xf8\xc4\x17\x9f\xf8\xe2\x13\x5f\x7c\xe2\x8b\x4f\x7c\xf1\x89\x2f\x3e\xf1\xc5\x27\xbe\xf8\xc4\x17\x9f\xf8\xe2\x13\x5f\x7c\xe2\x8b\x4f\x7c\xf1\x89\x2f\x3e\xf1\xc5\x27\xbe\xf8\xc4\xcf\x15\x7e\xae\xf0\x73\x85\x9f\x2b\xfc\x5c\xe1\x87\x85\x1f\x16\x7e\x58\xf8\x61\xe1\x87\x85\x1f\x16\x7e\x58\xf8\x61\xe1\x87\x85\x1f\x16\x7e\x58\xf8\x61\xe1\x87\x85\x1f\x16\x7e\x58\xf8\x61\xe1\xfb\xc2\xf7\x85\xef\x0b\xdf\x17\xbe\x2f\x7c\x5f\xf8\xbe\xf0\x7d\xe1\xfb\xc2\xf7\x85\xef\x0b\xdf\x17\xbe\x2f\x7c\x5f\xf8\xbe\xf0\x7d\xe1\xe7\x09\x3f\x2f\xc5\x3a\x61\xe4\x07\xb7\x72\x38\xc8\xbb\x42\xcf\x13\x7a\x9e\xd0\xf3\x84\x9e\x27\xf4\x91\x6a\x3c\x25\x4f\xac\x9d\x27\xd6\xce\x13\x6b\xe7\x89\xb5\xf3\xc4\xda\x79\x62\xed\x3c\xb1\x76\x9e\x58\x3b\x4f\xac\x9d\x97\xbc\xa3\xbf\x6c\x89\x39\x12\x73\x25\x86\x25\xfa\x12\x47\x66\x93\x27\xd6\xce\x13\x6b\xe7\x89\xb5\xf3\xc4\xda\x79\x62\xed\x3c\xb1\x76\x9e\x58\x3a\x4f\x2c\x9d\x27\x96\xce\x13\x4b\xe7\x89\xa5\xf3\xc4\xd2\x79\x62\xe5\x3c\xb1\x72\x9e\x58\x39\x4f\xac\x9c\x27\x56\xce\x13\x2b\xe7\x89\x95\xf3\xc4\xca\x79\x62\xe5\x3c\xb1\x72\x9e\x58\xf9\xff\x61\xdc\xec\x76\x1b\x37\xae\x38\x2e\x67\x6d\xd9\xf2\xc7\x66\x77\xe3\x24\x45\x9b\x00\xdc\x26\x6d\x81\xba\x28\xc8\x11\xc5\x8f\x4b\x8b\xcb\x3f\x02\xe4\xa6\x1f\x37\xbb\x40\x80\x40\x96\x68\x8b\x08\x4d\x3a\x14\xe5\x4d\xef\x7a\xd3\xcb\xf6\x59\xb4\xbc\xea\x83\xf4\x19\xfa\x1a\x2d\xa4\xf9\xcf\xb4\x22\x46\x63\xed\xc5\xce\x19\x9e\xe1\x39\xff\x19\xf2\xf0\x47\xd2\x22\x48\x65\x90\xca\x10\x2a\x1f\xe7\x47\x2a\x83\x54\x06\xa9\x0c\x52\x19\xa4\x32\x48\x65\x90\xca\x20\x95\x41\x2a\x83\x54\x06\xa9\x0c\x52\x19\xa4\x32\x48\x65\x90\xca\x20\x95\x41\x2a\x83\x54\x06\xa9\x0c\x52\x19\xa4\x32\x48\x65\x90\xca\x20\x85\x41\x0a\x83\x14\x06\x29\x0c\x52\x18\xa4\x30\x48\x5d\x90\xba\x20\x75\x41\xea\x82\xd4\x05\xa9\x0b\x52\x17\xa4\x2e\x48\x5b\x90\xb2\x18\xa9\xb8\xd4\x4f\xaa\x82\x54\x05\xa9\x0a\x52\x15\xa4\x2a\x48\x55\x90\xaa\x20\x55\x41\xaa\x82\x54\x05\xa9\x0a\x52\x15\xa4\x2a\x48\x55\x90\xaa\x20\x55\x41\xaa\x82\x54\x05\xa9\x0a\x52\x15\xa4\x2a\x48\x55\x90\xaa\x20\x55\x41\xaa\x82\x54\x05\xa9\x0a\x52\x15\xa4\x2a\x48\x55\xf0\x69\x0d\x7c\x5a\x03\x9f\xd6\xc0\xa7\x35\xf0\x69\x0d\x7c\x5a\x03\x29\x0a\x52\x14\xa4\x28\x48\x51\x90\xa2\x20\x45\x41\x8a\x22\x52\xf9\x38\x5f\x52\x14\xa4\x28\x48\x51\x90\xa2\x20\x45\x41\x8a\x82\x14\x05\x29\x0a\x52\x14\xa4\x28\x48\x51\x90\xa2\x20\x45\xc1\xa7\x35\xf0\x69\x0d\xa4\x2a\xf8\xb4\x06\xd2\x15\xa4\x2b\x48\x57\x90\xae\x20\x5d\x41\xba\x82\x74\x05\xe9\x0a\xd2\x15\xa4\x2b\x48\x57\x90\xae\x20\x5d\x41\xba\x82\x74\x05\xe9\x0a\xd2\x15\xa4\x2b\x48\x57\x90\xae\x20\x5d\x41\xaa\x82\x54\x05\xa9\x0a\x52\x15\xa4\x2a\x48\x55\x90\xaa\x20\x55\x41\xaa\x82\x54\x05\xa9\x0a\x52\x15\xa4\x2a\x48\x55\x90\xaa\x20\x4d\x41\x9a\x82\x34\x05\x69\x0a\xd2\x14\xa4\x29\x48\x53\x90\xa6\x20\x4d\x41\x9a\x82\x34\x05\x69\x0a\xd2\x14\xa4\x29\x48\x4f\x90\x9e\x20\x3d\x41\x7a\x82\xf4\x04\xe9\x09\x52\x13\xa4\x26\x48\x4d\x90\x9a\x20\x35\x41\x6a\x82\xd4\x04\xa9\x09\x52\x13\xa4\x26\x48\x4d\x90\x9a\x20\x35\x41\x6a\x82\xd4\x04\xa9\x09\x52\x13\xa4\x26\x48\x4d\x80\xf9\xc0\x7c\xe4\x24\xc8\x47\x90\x8f\x20\x1f\xa1\xf8\x08\xe6\x01\xf3\x80\x79\xc0\x3c\xf2\x29\x58\xb8\x92\xa3\xc2\x95\x1c\x15\xae\xe4\xa8\x70\x25\x47\x85\x2b\x39\x2a\x5c\xc9\x51\xe1\x4a\x8e\x0a\x57\x72\x54\xb8\x92\xa3\xc2\x95\x1c\x15\xae\xe4\xa8\x70\x5d\xf9\x23\xc8\xc0\x0b\x02\xff\x78\x6d\x0d\x5d\x6f\xd3\x8a\x38\x66\x9f\x99\x3d\xd5\x7a\xa7\xb7\xf9\xdd\xb2\xce\x66\x93\xc5\x7c\xb3\xb3\xab\x7e\xed\x2e\x5c\x2f\xb8\x58\x96\xb3\xac\x5e\x4c\xab\x3a\x9b\xdd\x14\x17\x3f\x2e\xab\x26\xab\xb3\xc7\xac\x5e\x64\x33\x8e\x81\x6c\x05\x25\x08\x25\x61\xc4\x3f\x18\xaf\x2d\x5f\x5b\x9c\x90\x40\xff\x3e\x2f\x37\x5f\x2a\x65\xd3\xaa\x64\xac\xa1\x3f\xc8\x7e\x9a\x16\x93\xfb\xd9\x4d\xc1\x2d\x5c\xb0\x91\x6a\x99\x2d\x60\x36\x79\x61\x16\xae\xbc\x30\x0b\x57\x5e\x98\x85\x1b\x70\x7c\xc0\xf1\x21\xa7\x1b\x72\x61\x95\x8e\x90\x0b\x1b\x72\x61\x43\xce\x3c\xe4\xc2\x86\xdc\x3f\xe6\xfe\x31\x0f\x58\xcc\x03\x16\xf3\x80\xc5\x8c\x7b\xed\x5e\x4c\xab\xa2\x2a\xef\xab\x32\x6b\x26\xf5\x5f\xb8\x55\x1c\x16\x79\x3d\x61\x87\xa9\xaf\x83\xfe\x43\xb6\xc8\x1a\xb5\x99\x99\xaf\xe3\xc3\x59\x55\xde\x1d\xa6\xcb\xba\xe2\x16\xce\xe9\x9a\x73\xba\xa6\xa6\x31\x35\x8d\xa9\x69\x4c\x4d\x63\x6a\x1a\x53\xd3\x98\x09\xc7\x9c\xd3\x98\x6b\x07\x97\x47\x45\xf0\x8f\xb3\x81\x27\xf8\x47\xf4\xc0\xe3\x4f\xd8\x84\x27\x5f\x78\x08\x4f\x04\x83\x6c\xd1\xe4\xf7\x93\x86\x47\xde\x93\x50\x17\x9e\x9f\x9e\xac\x67\x3b\xcf\xeb\xd9\xa0\x79\x5f\x6d\x8c\xc5\xa0\x2a\xb3\x2c\xbf\x9b\x37\xf3\xf3\x66\x5e\x67\xb4\x17\x67\xb7\xf9\xa3\xb2\xcf\x17\xd9\x63\x56\xb2\x23\x43\x45\xfe\x60\x52\xd7\xd5\xfb\x22\xbb\x6d\x8e\x37\xd6\xf2\xe1\x74\xd3\xd6\xeb\x61\xd2\x39\xab\xde\x97\xd2\xba\xa9\x9a\xf9\x80\xc3\x66\xe5\xb9\xb6\x6e\x16\x9b\xfb\x5b\xc1\xcf\x38\x04\x3f\xab\x10\xc2\x8b\x4f\xab\xba\x99\x57\x77\x55\x39\x29\xce\xf3\xb2\x59\x9f\xc8\xd3\x26\xaf\xca\xb3\xec\xc7\x65\xfe\x38\x29\xb2\x72\x9a\x1d\xcd\xab\xe5\x22\xbb\xa8\xb3\xc7\xa2\xba\xcb\xa7\x93\xa2\xac\x9a\xd3\xf5\xe0\xbb\x7a\x52\x34\x0f\xda\xbc\x69\x4e\xfe\x0c\xcf\x5d\xff\x5b\x1b\x1e\x0d\x57\x1b\x43\x65\x08\x65\xf8\xca\x88\x94\x11\x2b\x23\x50\x46\xa8\x8c\x11\x0d\x5f\xc5\x11\x6a\xf7\x91\x4a\x31\x52\x91\x87\x2a\x8e\x50\x5b\x84\x1a\x23\x54\x9c\x91\x92\xea\xab\xc1\x43\x25\x43\x68\x43\x65\x17\x4a\xcf\x50\x1b\xca\xe5\xab\x14\x9e\x4e\xaa\x22\x0b\x25\xd5\xd7\x83\x55\x64\x5f\xe9\xf1\xf5\xbc\x54\x64\x5f\xed\x3e\xd2\x13\xd4\x71\x36\x5b\x8e\x97\x0f\x37\x45\x35\xfd\xe1\x78\x56\x6e\xda\x23\xd9\x2b\x6e\x65\x5b\x37\xec\x37\x8b\xf9\x64\x96\x1d\x6d\xfe\x3f\x9e\xfd\xb0\x69\x07\xb7\x79\x51\x64\xb3\x9b\xea\xa7\xfe\x37\x42\xb8\xe1\xb0\xff\x8d\x17\x8d\x7c\xd9\x8c\xd6\x97\xbf\xb5\xbb\xce\xa6\xcd\x71\x53\xe7\x93\xbb\xe5\x83\x6c\x6b\xf6\x67\xa5\x6c\x8b\xdb\xfe\x34\xaf\xa7\x85\x3c\xb5\x46\x49\xb2\x09\x30\x1c\x0e\xf2\xf2\xf1\x66\x59\x14\x59\xb3\xb6\xe4\x90\xd3\xea\x21\x2b\xb9\x71\x71\x9f\x17\xd9\xed\x64\x9a\x9d\xe7\xe5\xa3\xee\x3c\x5b\x2c\xcb\xfe\x6d\x76\x3f\x29\xb2\xc3\xf5\x7f\x47\x8b\x87\xc9\x2c\x3b\x9c\x16\xcb\x9b\xa3\x79\x36\xa9\x9b\xe3\x59\x3e\xb9\xaf\xca\xd9\xd9\xfd\x72\xc1\x73\x30\x7b\xfe\x7f\xb6\xba\x44\x06\xbc\xc4\x25\xf2\xde\x57\x24\xf2\xde\x57\x24\xf2\xde\x57\x24\xf2\xde\x57\x24\xf2\xde\x57\x24\xf2\xde\x57\x24\xf2\xde\x57\x24\xf2\xde\x57\x24\xf2\xde\x57\x24\xf2\xde\x57\x24\xbc\xc4\x26\xbc\xc4\x26\xbc\xc4\x26\xbc\xc4\x26\x21\xf3\x84\xcc\x13\x32\x0f\x2f\xb1\x09\x2f\xb1\x09\x2f\xb1\x09\x2f\xb1\x7c\x83\x7a\x1d\xea\x36\x62\x1b\xb3\xbd\x66\x3b\x66\x9b\xb0\x7d\xc3\x36\x65\x0b\xd9\xca\x67\xb6\xeb\x50\x3e\xb3\x5d\x87\x11\xe3\x45\x8c\x17\x31\x5e\xc4\x78\xf2\x9e\x36\x25\x83\x31\x96\x0c\xc6\x58\x32\x18\x63\xc9\x60\x8c\x25\x83\xc1\x37\xb5\xe0\x9b\x5a\xf0\x4d\x2d\xf8\xa6\x16\xa9\x7c\xa3\x0d\xb2\x1e\xc0\x9b\x93\xcd\xb7\xe6\xa3\x20\x50\x46\xa4\x8c\x98\x46\xe8\xd2\x88\xb9\x25\x70\x3d\x1a\x1e\x8d\x28\xf2\x95\x31\x52\x46\xa0\x8c\x50\x19\x91\x32\x18\x27\x8a\x5d\x65\xa8\x38\xb1\x50\xc6\x70\xb0\x31\x36\x97\x59\x65\x8d\xb4\x15\x7c\xb1\x94\xdf\x0c\x7c\xbf\xdd\x06\xbf\x9f\x4e\xef\x1f\x76\x38\x43\x9b\x33\xb2\x39\x63\x93\x33\x50\x83\x6c\x4e\xa3\xa0\xc0\x26\x28\xb0\x09\x0a\xb6\x04\x5d\xee\x31\xf9\xd0\xa6\x32\xdc\x67\x4f\xa3\xca\xd0\xa6\x32\xb4\xa9\x34\x86\x8b\x6c\x2a\x23\x9b\xca\x68\x9f\xb0\x46\x95\x91\x4d\xa5\x71\x8f\xd8\xa6\x32\xb6\xa9\x8c\x6d\x2a\xe3\x7d\x72\x1a\x55\x6e\x9d\x97\x41\xe7\xa4\x1d\xd9\x9c\x81\xcd\x19\xda\x9c\x91\xcd\xb9\xa5\xd2\x58\x20\x81\xad\x7a\xba\x4e\xa3\x10\x63\x81\x74\x9d\xc6\x95\x31\xd6\x42\xd7\x69\x5c\x19\x63\x2d\x74\x9d\x46\x41\xc6\x5a\xb0\xce\xcf\x58\x0b\x5d\xa7\x51\xa5\xb1\x16\xba\x4e\xa3\x4a\x63\x2d\x58\x17\xda\x58\x0b\x5d\xa7\x51\xa5\xb1\x16\xba\x4e\x6b\x4e\xa3\xca\xad\x23\x1e\xda\x6a\xa1\xeb\x0c\x6c\xce\xd0\xe6\x8c\x6c\xce\x2d\x95\xc6\x53\x2f\xb4\xd5\x42\xd7\x69\x54\x69\x3c\x91\xba\x4e\xa3\x4a\x23\x49\x8c\x35\x10\xda\xaa\xa7\xeb\xb4\xee\x69\x14\x12\xda\x8e\x9f\xb1\x16\xba\x4e\x63\x4e\x63\x2d\x74\x9d\x46\x41\xc6\x5a\xb0\x4e\xc1\x58\x0b\x5d\xa7\x51\xa5\xb1\x16\xba\x4e\x6b\x4e\xa3\xca\xad\xb5\x8c\x6c\xb5\xd0\x75\x06\x36\x67\x68\x73\x46\x36\xe7\x96\x4a\xe3\x41\x8d\x6c\xb5\xd0\x75\x1a\x55\x1a\x6b\xa1\xeb\x34\xaa\x34\xd6\x82\xf1\xec\x8a\x6c\xb5\xd0\x75\x5a\xf7\x34\xaa\x34\x9e\x65\x5d\xa7\x51\xa5\x31\x9c\x75\xa1\xad\xf3\xdb\x2b\xac\xf1\x2c\x33\xd6\x42\xd7\x69\xcc\x69\xac\x85\xae\xd3\xb8\x32\xc6\x5a\x30\xaa\x8c\x6d\xb5\xd0\x75\x06\x36\x67\x68\x73\x46\x36\xe7\x96\x4a\xe3\x72\xc5\xb6\x5a\xe8\x3a\x8d\x2a\x8d\xb5\xd0\x75\x1a\x55\x1a\x6b\xc1\x78\xdc\x62\x5b\x2d\x74\x9d\xd6\x3d\x8d\x2a\x8d\xb5\xd0\x75\x1a\x55\x1a\xc3\x19\x6b\xa1\xeb\x34\xaa\x34\xd6\x42\xd7\x69\x54\x69\x24\x89\xf1\x4c\x8e\x6d\xd5\xd3\x75\x1a\x55\x5a\x27\xbf\x9d\xf3\xeb\xcd\x17\x98\x9b\x4d\x43\xd7\x97\xad\x37\xfc\x5e\x7f\xad\x6e\x1b\xa4\x3f\x64\xdf\x3d\xc8\xdf\x27\x92\x6f\x8b\x14\xec\xa3\x29\xd8\x47\x53\xb0\x8f\xa6\x60\x87\xa6\xaf\xf2\xaa\x79\x6a\x99\xcc\x63\x9e\x8e\xd3\x15\x64\x1e\xb3\x3b\xce\xae\x25\x32\x8f\x79\x3a\x8e\x4d\xcf\xae\xf5\xf9\x35\x3f\x91\x7d\x62\x89\x76\x0e\xdb\x2b\x5a\x57\xd8\xce\x61\xd6\x68\xbb\x96\x6b\xe7\xb0\xbd\xa2\x3d\xa1\x6d\x9f\xf3\x2a\xd2\xf3\xd8\xbd\xfe\xff\x1b\xf3\x74\x9c\x60\x8f\x38\x81\x7d\x76\xbb\x24\xed\x1c\xb6\x57\xb4\xae\xb0\x9d\xc3\xb6\xa3\xf1\x8d\xdf\x30\x18\x6a\xcb\xd7\xd6\x48\x5b\x81\xb6\x42\x6d\x45\xda\x8a\x95\x15\xba\xda\xf2\xb4\x25\xb4\xa5\x73\x84\x3a\x47\xa8\x73\x84\x3a\x47\xa8\x73\x84\x3a\x47\xa8\x73\x44\x3a\x47\xa4\x73\x44\x3a\x47\xa4\x73\xe8\xf7\x9a\x43\xfd\x5e\x73\x18\xe9\x1c\x91\xce\x11\xe9\x1c\x91\xce\x11\xeb\x1c\xb1\xca\xe1\xbb\x51\xaf\xd7\xfb\xe7\xc1\x7f\xfe\xb6\x3a\xf8\x7b\xef\xdb\xd5\xc9\x1f\xde\x7e\x38\x38\xf8\xc7\xbb\x0f\xe8\x5f\xbd\x7d\xbd\x7a\xf1\xee\xdb\xd5\xe5\x9f\xde\xbe\x5e\xfd\xf5\xdd\x97\xab\xfe\xd5\x77\x6f\x7b\xab\x67\x4e\xba\x7a\x76\xf5\x66\x75\xe8\xa4\xed\xb3\x57\x1f\x5d\x6d\x3a\x47\x4e\xda\x1e\xaa\x4e\xdf\x49\xdb\xa3\x31\x3b\xc7\x4e\xda\xf6\x7f\xc7\xce\x89\x93\xb6\xc7\x57\xec\x0c\x9c\xb4\x3d\xf9\x82\x9d\x53\x27\x6d\x07\xbf\x60\xe7\xcc\x49\xdb\xd3\x9f\xb3\x73\xee\xa4\xed\xd9\x6b\xd9\x39\x58\x5d\x30\xfb\x73\x27\x6d\x2f\x7e\xf3\xd1\xd5\x87\x67\x78\xbc\x7a\xb3\xfa\xd8\x49\xdb\xe7\x5f\xea\xee\x0b\x27\x6d\x3f\xbe\xd2\xdd\x97\x4e\xda\xbe\xf8\xad\xee\xbe\x72\xd2\xf6\xe5\xaf\x74\xf7\x13\x27\x6d\x5f\x7d\xad\xbb\x97\x4e\xda\x7e\xf2\x95\xee\x7e\xea\xa4\xed\xe5\x2f\x75\xf7\x33\x27\x6d\x3f\x7d\xad\xbb\x9f\x3b\x69\xfb\x99\xa3\xbb\x3f\x73\xd2\xf6\xf3\x97\xaa\xfb\x6e\x75\x79\xd5\xeb\xf5\x0e\xfe\xf8\xef\x7f\x7d\xd7\xeb\xfd\x37\x00\x00\xff\xff\xde\x13\x8e\xba\x40\x45\x07\x00") - -func resourcesAppStaticFontsNotosansRegularWebfontTtfBytes() ([]byte, error) { - return bindataRead( - _resourcesAppStaticFontsNotosansRegularWebfontTtf, - "resources/app/static/fonts/NotoSans-Regular-webfont.ttf", - ) -} - -func resourcesAppStaticFontsNotosansRegularWebfontTtf() (*asset, error) { - bytes, err := resourcesAppStaticFontsNotosansRegularWebfontTtfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "resources/app/static/fonts/NotoSans-Regular-webfont.ttf", size: 476480, mode: os.FileMode(436), modTime: time.Unix(1501694025, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "resources/app/block.png": resourcesAppBlockPng, - "resources/app/caution.png": resourcesAppCautionPng, - "resources/app/icon.png": resourcesAppIconPng, - "resources/app/index.html": resourcesAppIndexHtml, - "resources/app/js/qrcode.min.js": resourcesAppJsQrcodeMinJs, - "resources/app/list.png": resourcesAppListPng, - "resources/app/minimize.jpg": resourcesAppMinimizeJpg, - "resources/app/minimize.png": resourcesAppMinimizePng, - "resources/app/settings.png": resourcesAppSettingsPng, - "resources/app/static/css/base.css": resourcesAppStaticCssBaseCss, - "resources/app/static/fonts/NotoSans-Bold-webfont.ttf": resourcesAppStaticFontsNotosansBoldWebfontTtf, - "resources/app/static/fonts/NotoSans-BoldItalic-webfont.ttf": resourcesAppStaticFontsNotosansBolditalicWebfontTtf, - "resources/app/static/fonts/NotoSans-Italic-webfont.ttf": resourcesAppStaticFontsNotosansItalicWebfontTtf, - "resources/app/static/fonts/NotoSans-Regular-webfont.ttf": resourcesAppStaticFontsNotosansRegularWebfontTtf, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "resources": &bintree{nil, map[string]*bintree{ - "app": &bintree{nil, map[string]*bintree{ - "block.png": &bintree{resourcesAppBlockPng, map[string]*bintree{}}, - "caution.png": &bintree{resourcesAppCautionPng, map[string]*bintree{}}, - "icon.png": &bintree{resourcesAppIconPng, map[string]*bintree{}}, - "index.html": &bintree{resourcesAppIndexHtml, map[string]*bintree{}}, - "js": &bintree{nil, map[string]*bintree{ - "qrcode.min.js": &bintree{resourcesAppJsQrcodeMinJs, map[string]*bintree{}}, - }}, - "list.png": &bintree{resourcesAppListPng, map[string]*bintree{}}, - "minimize.jpg": &bintree{resourcesAppMinimizeJpg, map[string]*bintree{}}, - "minimize.png": &bintree{resourcesAppMinimizePng, map[string]*bintree{}}, - "settings.png": &bintree{resourcesAppSettingsPng, map[string]*bintree{}}, - "static": &bintree{nil, map[string]*bintree{ - "css": &bintree{nil, map[string]*bintree{ - "base.css": &bintree{resourcesAppStaticCssBaseCss, map[string]*bintree{}}, - }}, - "fonts": &bintree{nil, map[string]*bintree{ - "NotoSans-Bold-webfont.ttf": &bintree{resourcesAppStaticFontsNotosansBoldWebfontTtf, map[string]*bintree{}}, - "NotoSans-BoldItalic-webfont.ttf": &bintree{resourcesAppStaticFontsNotosansBolditalicWebfontTtf, map[string]*bintree{}}, - "NotoSans-Italic-webfont.ttf": &bintree{resourcesAppStaticFontsNotosansItalicWebfontTtf, map[string]*bintree{}}, - "NotoSans-Regular-webfont.ttf": &bintree{resourcesAppStaticFontsNotosansRegularWebfontTtf, map[string]*bintree{}}, - }}, - }}, - }}, - }}, -}} - -// RestoreAsset restores an asset under the given directory -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil -} - -// RestoreAssets restores an asset under the given directory recursively -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/block.png b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/block.png deleted file mode 100644 index 00672252c0..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/block.png and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/caution.png b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/caution.png deleted file mode 100644 index 6367cdb43f..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/caution.png and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/icon.png b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/icon.png deleted file mode 100644 index 4f6d1f204f..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/icon.png and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/index.html b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/index.html deleted file mode 100644 index 703521130c..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/index.html +++ /dev/null @@ -1,886 +0,0 @@ - - - - - - - -
-
- -
-
-
- -
-
-
-
- -
-
- -
- -
-
-
-
Funds
-
-
Bitcoin
-
-
-
-
Transactions
- -
-
-
-
Send Money
- - -
-
-
To
*
- -
-
- -
-
-
Amount
*
- - -
-
-
-
-
Note
- -
-
-
-
Clear
- -
-
- -
-
-
Transactions
-
You have no transactions.
-
-
-
-
Settings
-
-
Fiat Currency
- -
-
-
BitcoinUnit
- -
-
-
Transaction Fee
- -
-
-
Decimal Places
- -
-
-
-
Show mnemonic seed
- -
-
-
-
-
Resync Blockchain
-
- -
Are you sure?
-
Clicking yes will re-download the blockchain and scan for any missing payments.
-
-
-
Cancel
- -
-
- -
-
-
-
-
-
Set trusted peer:
- -
- -
Set trusted peer?
-
You will need to restart for this to take effect.
-
-
-
Cancel
- -
-
- -
-
-
-
-
-
Set socks5 proxy:
- -
- -
Set socks5 proxy?
-
You will need to restart for this to take effect.
-
-
-
Cancel
- -
-
- -
-
-
-
-
- -
- -
Are you sure?
-
Clicking yes will delete your existing wallet, including any coins in it, and restore from the seed you entered.
-
-
-
Cancel
- -
-
- -
-
-
-
- - - - - \ No newline at end of file diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/js/qrcode.min.js b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/js/qrcode.min.js deleted file mode 100644 index 993e88f396..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/js/qrcode.min.js +++ /dev/null @@ -1 +0,0 @@ -var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j=0?p.get(q):0}}for(var r=0,m=0;mm;m++)for(var j=0;jm;m++)for(var j=0;j=0;)b^=f.G15<=0;)b^=f.G18<>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;cf;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=[''],h=0;d>h;h++){g.push("");for(var i=0;d>i;i++)g.push('');g.push("")}g.push("
"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}(); \ No newline at end of file diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/list.png b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/list.png deleted file mode 100644 index 2a3b4d1d1f..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/list.png and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/minimize.jpg b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/minimize.jpg deleted file mode 100644 index 851a5cc920..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/minimize.jpg and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/minimize.png b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/minimize.png deleted file mode 100644 index c649d6bb9b..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/minimize.png and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/settings.png b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/settings.png deleted file mode 100644 index c1c32eea66..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/settings.png and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/css/base.css b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/css/base.css deleted file mode 100644 index 62380e2f10..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/css/base.css +++ /dev/null @@ -1,908 +0,0 @@ -@font-face { - font-family: 'noto_sans'; - src: url('../fonts/NotoSans-Regular-webfont.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'noto_sans'; - src: url('../fonts/NotoSans-Bold-webfont.ttf') format('truetype'); - font-weight: bold; - font-style: normal; -} - -@font-face { - font-family: 'noto_sans'; - src: url('../fonts/NotoSans-Italic-webfont.ttf') format('truetype'); - font-weight: normal; - font-style: italic; -} - -@font-face { - font-family: 'noto_sans'; - src: url('../fonts/NotoSans-BoldItalic-webfont.ttf') format('truetype'); - font-weight: bold; - font-style: italic; -} - -html { - color: #262626; - font-family: "noto_sans"; - font-size: 10px; - font-weight: 400; - -webkit-font-smoothing: antialiased; - letter-spacing: 0; - line-height: 1.2; -} - -.flex { - display: -webkit-flex; - display: flex; -} - -.Wallet { - width: 602.2px; - height: 285px; - margin-left: 1px; - border-radius: 2px; - background-color: #ffffff; - box-shadow: 0 1px 2px 0 #cfcfcf; - border: solid 1px #d2d3d9; - display: -webkit-flex; - display: flex; -} - -.Stats { - width: 162px; - height: 285px; - padding-right: 13.5px; -} - -.Line { - margin-top: 44.5px; - width: 2px; - height: 235.7px; - border-left: solid 1px #dbdbdb; -} - -.Funds { - width: 43.2px; - height: 18px; - font-family: "noto_sans"; - font-size: 14px; - font-weight: bold; - line-height: 1.13; - color: #252525; - padding-top: 13.5px; - padding-left: 13.5px; -} - -.Stat { - font-family: "noto_sans"; - font-size: 18px; - font-weight: bold; - letter-spacing: 0.4px; - padding-left: 15px; - color: #2bad23; - margin-bottom: -8px; -} - -.pad { - padding-top: 11px; -} - -.label { - opacity: 0.75; - font-family: "noto_sans"; - font-size: 11.5px; - line-height: 2.43; - text-align: left; - color: #000000; - padding-left: 15px; -} - -.btc-total { - padding-top: 11px; -} - -.ToggleButton { - width: 136.8px; - height: 31.3px; - border-radius: 2px; - background-color: #ffffff; - box-shadow: 0 1px 0 0 rgba(219, 219, 219, 0.5); - border: solid 1px #dbdbdb; - font-family: "noto_sans"; - font-size: 11.7px; - font-weight: bold; - color: #252525; - margin-left: 13.5px; - margin-top: 56px; - cursor: pointer; -} - -.WalletAction { - width: 100%; -} - -.Center { - text-align: center; -} - -.SendMoney { - padding-top: 36.4px; - height: 16.2px; - font-family: "noto_sans"; - font-size: 18px; - font-weight: bold; - line-height: 1; - color: #252525; - margin-bottom: -5px; -} - -.Hidden { - display: none; -} - -.sndMarg { - margin-top: 8px; -} - -.SendField { - display: -webkit-flex; - display: flex; - align-content: center; - width: 100%; - margin-top: 10px; -} - -.Description { - font-family: "noto_sans"; - font-size: 12.6px; - color: #252525; -} - -.Description .asterisk { - font-weight: bold; - color: #2bad23; -} - -.fieldlabel { - margin-top: 13px; - margin-right: 12px; - display: -webkit-flex; - display: flex; -} - -.to { - margin-left: 53px; -} - -.amount { - margin-left: 20px; -} - -.note { - margin-left: 46px; -} - -input::-webkit-outer-spin-button, -input::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; -} - -.input { - width: 296px; - height: 32.4px; - font-family: "noto_sans"; - font-size: 12.6px; - color: #252525; - padding-left: 5.85px; -} - -.Clear { - width: 36px; - height: 17.1px; - opacity: 0.5; - font-family: "noto_sans"; - font-size: 12.6px; - letter-spacing: 0.3px; - color: #252525; - margin-top: 10px; - cursor: pointer; -} - -.sendActions { - margin-top: 13.5px; - margin-left: 265.4px; -} - -.SendBtn { - width: 81.9px; - height: 28.3px; - border-radius: 2px; - background-image: linear-gradient(to bottom, #54d547, #2bad23); - box-shadow: 0 0 3px 0 rgba(149, 149, 149, 0.5); - border: solid 2px #ffffff; - font-family: "noto_sans"; - font-size: 12.6px; - font-weight: bold; - color: #ffffff; - margin-left:8.4px; - margin-right: -20px; - cursor: pointer; -} - -.actionBar { - margin-left: 2px; - height: 38.8px; - width: 100% -} - -.tab { - height: 28.3px; - margin-top: 3px; - margin-right: 10px; - border-radius: 2px; - background-color: #ffffff; - box-shadow: 0 1px 2px 0 #cfcfcf; - border: solid 1px #d2d3d9; -} - -.icon { - width: 16.2px; - height: 16.2px; - margin-top: 6px; - margin-left: 10px; -} - -.controldiv { - cursor: pointer; -} - -.controlIcon { - margin-right:10px; - cursor: pointer; -} - -.tabText { - margin-top: 0px; - margin-left: 5px; - font-family: "noto_sans"; - font-size: 12.6px; - font-weight: bold; - line-height: 2.43; - text-align: left; - margin-right: 10px; -} - -.controlSpace { - width: 350px; -} - -.minimize { - margin-right: 5px; -} - -.qrcode { - width: 180px; - margin-top:8px; - margin-left:141px; - height: 162px; -} - -.display-address { - text-align: center; - line-height: 33px; - width: 287.55px; - height: 32.4px; - border-radius: 2px; - background-color: #ffffff; - box-shadow: 0 1px 0 0 rgba(219, 219, 219, 0.5); - border: solid 1px #dbdbdb; - font-family: "noto_sans"; - font-size: 12.6px; - color: #252525; - margin-left: 75px; - cursor: pointer; -} - -.need { - padding-left: 162px; - padding-top: 10px; -} - -.need-icon { - width: 16.2px; - height: 16.2px; - padding-right: 2.7px; -} - -.need-bitcoin { - font-family: "noto_sans"; - font-size: 13.5px; - font-weight: bold; - color: #252525; - text-decoration:underline; - cursor: pointer; -} - -.popup { - position: relative; - display: inline-block; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.popup .popuptext { - visibility: hidden; - color: #fff; - text-align: center; - padding: 7.2px 0; - position: absolute; - z-index: 1; - bottom: 125%; - left: 50%; - margin-left: -115px; - - width: 200.5px; - height: 115.9px; - border-radius: 2px; - background-color: #ffffff; - box-shadow: 0 -2px 2px 0 #e8e7e7; - border: solid 1px #d2d3d9; -} - -.popup .popuptext:before { - content: ""; - position: absolute; - top: 100%; - left: 60%; - margin-left: 0px; - border-width: 10px; - border-style: solid; - border-color: #d2d3d9 transparent transparent transparent; -} - -.popup .popuptext::after { - content: ""; - position: absolute; - top: 100%; - left: 60%; - margin-left: 1px; - border-width: 9px; - border-style: solid; - border-color: #ffffff transparent transparent transparent; -} - -.popup .show { - visibility: visible; - -webkit-animation: fadeIn .7s; - animation: fadeIn .7s; -} - -@-webkit-keyframes fadeIn { - from {opacity: 0;} - to {opacity: 1;} -} - -@keyframes fadeIn { - from {opacity: 0;} - to {opacity:1 ;} -} - -.sure { - width: 100%; - text-align: center; - font-family: "noto_sans"; - margin-top:9px; - font-size: 13.5px; - font-weight: bold; - color: #252525; -} - -.warning { - width: 75%; - text-align: center; - margin-left: 25px; - font-family: "noto_sans"; - margin-top:10px; - font-size: 9px; - color: #252525; - text-wrap:normal; - height:50px; -} - -.separator { - width: 99.8%; - height: 0px; - margin-top: -9px; - background-color: #d2d3d9; - border: solid .1px #d2d3d9; -} - -.confirmationActions { - margin-top: 8.5px; - margin-left: 60px; -} - -.cancelPad { - margin-right: 5.4px; - margin-top: 6.5px; -} - -.caution { - color: red; - font-family: "noto_sans"; - font-size: 12px; - margin-top: 1px; - margin-bottom: -3px; - margin-left: 10px; - line-height: 2.43; - text-align: left; - margin-right: 10px; -} - -.invalid-field { - margin-left: 83px; - margin-bottom: -20px; -} - -.currencySelect { - margin-left: -65px; - width: 65px; - opacity: 0.75; - font-family: "noto_sans"; - background-color: #ffffff; - font-size: 12.6px; - color: #252525; - text-align-last:center; -} - -.Transactions { - width: 602.2px; - height: 285px; - margin-top: 10px; - margin-left: 1px; - display: none; - border-radius: 2px; - background-color: #ffffff; - box-shadow: 0 1px 2px 0 #cfcfcf; - border: solid 1px #d2d3d9; - padding-bottom: 12px; - overflow-y: scroll; -} - -.Transactions::-webkit-scrollbar-track -{ - background-color: #F5F5F5; -} - -.Transactions::-webkit-scrollbar -{ - width: 8px; - background-color: #F5F5F5; -} - -.Transactions::-webkit-scrollbar-thumb -{ - background-color: #cfcfcf; - border: 2px solid #cfcfcf; -} - -.transactions-label { - margin-top: 12px; - margin-left:12px; - height: 15.2px; - font-family: "noto_sans"; - font-size: 18px; - font-weight: bold; - line-height: 1; - color: #252525; - margin-bottom: 12px; -} - -.tx { - width: 562.2px; - height: 52px; - border-radius: 2px; - background-color: #ffffff; - border: solid 1px #dbdbdb; - margin-top: -2px; - margin-left: 12px; - padding-top: 25px; - padding-left: 12px; -} - -.tx-text { - font-family: "noto_sans"; - font-size: 14px; - color: #252525; -} - -.tx-text2 { - font-family: "noto_sans"; - font-size: 12px; - color: #252525; -} - -.bold { - font-weight: bold; -} - -.tx-margin { - margin-left: 4px; -} - -.time-margin { - margin-left: 15px; -} - -.checkmark { - color: #2bad23; -} - -.caution { - color: yellow; -} - -.cross { - color: red; -} - -.details-width { - width: 440px; -} - -.viewdetails { - width: 97px; - height: 28px; - border-radius: 2px; - background-color: #ffffff; - box-shadow: 0 1px 0 0 rgba(219, 219, 219, 0.5); - border: solid 1px #dbdbdb; - font-family: "noto_sans"; - font-size: 12.5px; - font-weight: bold; - color: #252525; - cursor: pointer; -} - -.setting { - width: 97%; - height: 50px; - background-color: #ffffff; - border: solid 1px #dbdbdb; - margin-top: -2px; - padding-left: 12px; - margin-left: -1px; -} - -.noTransactions { - width: 100%; - margin-top: 130px; - text-align: center; -} - -.settingSelect { - width: 120px; - height: 99%; - opacity: 0.75; - font-family: "noto_sans"; - background-color: #ffffff; - font-size: 12.6px; - color: #252525; - margin-left: 300px; - text-align-last:center; -} - -.settingLabel{ - width: 200px; - height: 100%; - line-height: 3.5; - text-align: left; - padding-left: 15px; - font-family: "noto_sans"; - font-size: 14px; - color: #252525; -} - -input[type=checkbox]{ - height: 0; - width: 0; - visibility: hidden; -} - -label { - cursor: pointer; - text-indent: -9999px; - width: 50px; - height: 25px; - background: grey; - display: block; - border-radius: 25px; - position: relative; -} - -label:after { - content: ''; - position: absolute; - top: 2px; - left: 5px; - width: 20px; - height: 20px; - background: #fff; - border-radius: 20px; - transition: 0.3s; -} - -input:checked + label { - background: #2bad23; -} - -input:checked + label:after { - left: calc(100% - 5px); - transform: translateX(-100%); -} - -label:active:after { - width: 30px; -} - -.checkLabel{ - height: 100%; - width: 485px; - text-align: left; - line-height: 1.8; - padding-left: 15px; - font-family: "noto_sans"; - font-size: 14px; - color: #252525; -} - -.checkMargin { - margin-top: 13px; - height: 50px; -} - -.mnemonic { - margin-top: -10px; - margin-left: 12px; - padding: 8px; - width: 530px; - font-family: "noto_sans"; - font-size: 22px; - background: #dbdbdb; - border-radius: 2px; -} - -.mnDesc { - margin-top: 2px; - margin-left: 12px; - width: 530px; - font-family: "noto_sans"; - font-size: 10px; -} - -.restore-margin { - margin-top: 7px; - margin-left: 12px; -} - -.RestoreBtn { - width: 140px; - height: 28.3px; - margin-top: 5px; - margin-left: 19px; - border-radius: 2px; - background-image: linear-gradient(to bottom, #54d547, #2bad23); - box-shadow: 0 0 3px 0 rgba(149, 149, 149, 0.5); - border: solid 2px #ffffff; - font-family: "noto_sans"; - font-size: 12.6px; - font-weight: bold; - color: #ffffff; - cursor: pointer; -} - -.mninput { - width: 400px; - height: 32.4px; - font-family: "noto_sans"; - font-size: 12.6px; - color: #252525; -} - -.restoreWarning { - width: 75%; - text-align: center; - margin-left: 25px; - font-family: "noto_sans"; - margin-top:10px; - font-size: 9px; - color: #252525; - text-wrap:normal; - height:65px; -} - -.restorePopup { - position: relative; - display: inline-block; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.restorePopup .restorePopuptext { - visibility: hidden; - color: #fff; - text-align: center; - padding: 7.2px 0; - position: absolute; - z-index: 1; - bottom: 125%; - left: 50%; - margin-left: -120px; - - width: 200.5px; - height: 130.9px; - border-radius: 2px; - background-color: #ffffff; - box-shadow: 0 -2px 2px 0 #e8e7e7; - border: solid 1px #d2d3d9; -} - -.restorePopup .restorePopuptext:before { - content: ""; - position: absolute; - top: 100%; - left: 60%; - margin-left: 0px; - border-width: 10px; - border-style: solid; - border-color: #d2d3d9 transparent transparent transparent; -} - -.restorePopup .restorePopuptext::after { - content: ""; - position: absolute; - top: 100%; - left: 60%; - margin-left: 1px; - border-width: 9px; - border-style: solid; - border-color: #ffffff transparent transparent transparent; -} - -.restorePopup .show { - visibility: visible; - -webkit-animation: fadeIn .7s; - animation: fadeIn .7s; -} - -.ResyncBtn { - width: 85px; - height: 28.3px; - margin-top: 9px; - margin-left: 273px; - border-radius: 2px; - background-image: linear-gradient(to bottom, #54d547, #2bad23); - box-shadow: 0 0 3px 0 rgba(149, 149, 149, 0.5); - border: solid 2px #ffffff; - font-family: "noto_sans"; - font-size: 12.6px; - font-weight: bold; - color: #ffffff; - cursor: pointer; -} - -.resyncLabel{ - width: 200px; - height: 100%; - line-height: 3.5; - text-align: left; - padding-left: 15px; - font-family: "noto_sans"; - font-size: 14px; - color: #252525; -} - -.resyncPopup { - position: relative; - display: inline-block; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.resyncPopup .resyncPopuptext { - visibility: hidden; - color: #fff; - text-align: center; - padding: 7.2px 0; - position: absolute; - z-index: 1; - bottom: 125%; - left: 50%; - margin-left: -18px; - - width: 200.5px; - height: 115.9px; - border-radius: 2px; - background-color: #ffffff; - box-shadow: 0 -2px 2px 0 #e8e7e7; - border: solid 1px #d2d3d9; -} - -.resyncPopup .resyncPopuptext:before { - content: ""; - position: absolute; - top: 100%; - left: 71%; - margin-left: 0px; - border-width: 10px; - border-style: solid; - border-color: #d2d3d9 transparent transparent transparent; -} - -.resyncPopup .resyncPopuptext::after { - content: ""; - position: absolute; - top: 100%; - left: 71%; - margin-left: 1px; - border-width: 9px; - border-style: solid; - border-color: #ffffff transparent transparent transparent; -} - -.resyncPopup .show { - visibility: visible; - -webkit-animation: fadeIn .7s; - animation: fadeIn .7s; -} - -.shortinput { - width: 200px; - height: 32.4px; - margin-top: 7px; - font-family: "noto_sans"; - font-size: 12.6px; - color: #252525; -} -.shortInputLabel{ - width: 125px; - height: 100%; - line-height: 3.8; - text-align: left; - padding-left: 15px; - font-family: "noto_sans"; - font-size: 14px; - color: #252525; -} - -.SetBtn { - width: 85px; - height: 28.3px; - margin-top: 11px; - margin-left: 145px; - margin-right: -130px; - border-radius: 2px; - background-image: linear-gradient(to bottom, #54d547, #2bad23); - box-shadow: 0 0 3px 0 rgba(149, 149, 149, 0.5); - border: solid 2px #ffffff; - font-family: "noto_sans"; - font-size: 12.6px; - font-weight: bold; - color: #ffffff; - cursor: pointer; -} \ No newline at end of file diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-Bold-webfont.ttf b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-Bold-webfont.ttf deleted file mode 100644 index dc4bddc4e2..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-Bold-webfont.ttf and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-BoldItalic-webfont.ttf b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-BoldItalic-webfont.ttf deleted file mode 100644 index 82f7457f75..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-BoldItalic-webfont.ttf and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-Italic-webfont.ttf b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-Italic-webfont.ttf deleted file mode 100644 index 418ac29d2a..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-Italic-webfont.ttf and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-Regular-webfont.ttf b/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-Regular-webfont.ttf deleted file mode 100644 index d8fe19372e..0000000000 Binary files a/vendor/github.com/OpenBazaar/spvwallet/gui/resources/app/static/fonts/NotoSans-Regular-webfont.ttf and /dev/null differ diff --git a/vendor/github.com/OpenBazaar/spvwallet/gui/utils.go b/vendor/github.com/OpenBazaar/spvwallet/gui/utils.go deleted file mode 100644 index c4794a63a1..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/gui/utils.go +++ /dev/null @@ -1,5 +0,0 @@ -package gui - -func AppIconPngBytes() ([]byte, error) { - return resourcesAppIconPngBytes() -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/headers.go b/vendor/github.com/OpenBazaar/spvwallet/headers.go index 66c3578a28..a6b9832df8 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/headers.go +++ b/vendor/github.com/OpenBazaar/spvwallet/headers.go @@ -9,13 +9,13 @@ import ( "math/big" "path" "sort" + "strings" "sync" "github.com/boltdb/bolt" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/cevaris/ordered_map" - "strings" ) const ( @@ -116,7 +116,7 @@ func (h *HeaderDB) Put(sh StoredHeader, newBestHeader bool) error { go func() { err := h.putToDB(sh, newBestHeader) if err != nil { - log.Error(err) + log.Error(err.Error()) } }() return nil @@ -131,7 +131,7 @@ func (h *HeaderDB) put(sh StoredHeader, newBestHeader bool) error { h.lock.Unlock() err := h.putToDB(sh, newBestHeader) if err != nil { - log.Error(err) + log.Error(err.Error()) } return nil } diff --git a/vendor/github.com/OpenBazaar/spvwallet/headers_test.go b/vendor/github.com/OpenBazaar/spvwallet/headers_test.go deleted file mode 100644 index 81508f6124..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/headers_test.go +++ /dev/null @@ -1,421 +0,0 @@ -package spvwallet - -import ( - "bytes" - "crypto/rand" - "github.com/boltdb/bolt" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "math/big" - "os" - "strings" - "testing" - "time" -) - -var ( - header1Bytes []byte = []byte{0x00, 0x00, 0x00, 0x20, 0x02, 0x59, 0x46, 0xb0, 0x8b, 0x8d, 0x8a, 0xf9, - 0xb8, 0x2c, 0x16, 0xb6, 0xf0, 0x6e, 0x50, 0x12, 0xaa, 0x48, 0xdd, 0x18, 0x6a, 0x35, 0xcf, 0x1c, - 0x47, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x81, 0x10, 0x30, 0x0d, 0x39, 0x6b, 0xb0, - 0x5b, 0x53, 0x8f, 0x9b, 0x0c, 0xac, 0x81, 0x4e, 0xa6, 0x55, 0x3c, 0x59, 0xdf, 0x00, 0xbc, 0xa7, - 0xb1, 0x8e, 0xc6, 0x9a, 0x5d, 0x97, 0xbd, 0xa2, 0x4a, 0x96, 0x4d, 0x58, 0x8b, 0xf9, 0x09, 0x1a, - 0xd0, 0xcb, 0x4e, 0xb6} - header2Bytes []byte = []byte{0x00, 0x00, 0x00, 0x20, 0x41, 0x81, 0xef, 0x59, 0x0c, 0x87, 0x8a, 0x97, - 0x7b, 0xba, 0x99, 0xad, 0x50, 0x98, 0x17, 0xd1, 0xf3, 0x09, 0x3b, 0x1d, 0xcd, 0xbc, 0xb8, 0x8a, - 0x2a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x15, 0x97, 0x0b, 0xdc, 0xc8, 0x35, 0x29, - 0x3a, 0x11, 0x0e, 0xe2, 0x38, 0x79, 0x74, 0x4b, 0x3e, 0x15, 0x38, 0xf5, 0x19, 0xa3, 0xf6, 0xf9, - 0x09, 0x8d, 0xa2, 0xda, 0x02, 0xa9, 0xd4, 0x33, 0xaa, 0x09, 0x4d, 0x58, 0x85, 0x8b, 0x03, 0x18, - 0xc6, 0xdd, 0xfe, 0x0e} - header3Bytes []byte = []byte{0x00, 0x00, 0x00, 0x20, 0x44, 0x88, 0xea, 0x55, 0x00, 0x77, 0xaa, 0x90, - 0xbb, 0xba, 0x96, 0xa5, 0x52, 0x91, 0x27, 0xd4, 0xff, 0x99, 0x31, 0x1a, 0xad, 0xcc, 0x88, 0x8c, - 0x22, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x15, 0x97, 0x0b, 0xdc, 0xc8, 0x35, 0x29, - 0x3a, 0x11, 0x0e, 0xe2, 0x38, 0x79, 0x74, 0x4b, 0x3e, 0x15, 0x38, 0xf5, 0x19, 0xa3, 0xf6, 0xf9, - 0x09, 0x8d, 0xa2, 0xda, 0x02, 0xa9, 0xd4, 0x33, 0xaa, 0x09, 0x4d, 0x58, 0x85, 0x8b, 0x03, 0x18, - 0xc6, 0xdd, 0xfe, 0x00} - testHdr1 wire.BlockHeader = wire.BlockHeader{} - testHdr2 wire.BlockHeader = wire.BlockHeader{} - testHdr3 wire.BlockHeader = wire.BlockHeader{} - testSh1 StoredHeader - testSh2 StoredHeader - testSh3 StoredHeader -) - -func init() { - var buf bytes.Buffer - buf.Write(header1Bytes) - testHdr1.Deserialize(&buf) - buf.Write(header2Bytes) - testHdr2.Deserialize(&buf) - buf.Write(header3Bytes) - testHdr3.Deserialize(&buf) - testSh1 = StoredHeader{ - header: testHdr1, - height: 100, - totalWork: big.NewInt(500), - } - testSh2 = StoredHeader{ - header: testHdr2, - height: 200, - totalWork: big.NewInt(1000), - } - testSh3 = StoredHeader{ - header: testHdr3, - height: 200, - totalWork: big.NewInt(1000), - } -} - -func TestSerializeHeader(t *testing.T) { - b, err := serializeHeader(testSh1) - if err != nil { - t.Error(err) - } - var buf bytes.Buffer - testHdr1.Serialize(&buf) - if !bytes.Equal(buf.Bytes(), b[:80]) { - t.Error("Failed to serialize header") - } - if !bytes.Equal([]byte{0x00, 0x00, 0x00, 0x64}, b[80:84]) { - t.Error("Failed to serialize height") - } - if !bytes.Equal([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF4}, b[84:116]) { - t.Error("Failed to serialize big int") - } -} - -func TestDeserializeHeader(t *testing.T) { - height := []byte{0x00, 0x00, 0x00, 0x64} - work := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf4} - sh, err := deserializeHeader(append(header1Bytes, append(height, work...)...)) - if err != nil { - t.Error(err) - } - shHash := sh.header.BlockHash() - testHdrHash := testHdr1.BlockHash() - if !testHdrHash.IsEqual(&shHash) { - t.Error("Failed to serialize block header") - } - if sh.height != 100 { - t.Error("Failed to serialize height") - } - if sh.totalWork.Cmp(big.NewInt(500)) != 0 { - t.Error("Failed to serialize total work") - } -} - -func TestHeaderDB_put(t *testing.T) { - headers, err := NewHeaderDB("") - if err != nil { - t.Error(err) - } - // Test put with new tip - err = headers.put(testSh1, true) - if err != nil { - t.Error(err) - } - err = headers.db.View(func(btx *bolt.Tx) error { - hdrs := btx.Bucket(BKTHeaders) - testHash := testSh1.header.BlockHash() - b := hdrs.Get(testHash.CloneBytes()) - if b == nil { - t.Error("Header doesn't exist in db") - } - ser, err := serializeHeader(testSh1) - if err != nil { - return err - } - if !bytes.Equal(ser, b) { - t.Error("Failed to PUT header correctly") - } - tip := btx.Bucket(BKTChainTip) - if err != nil { - return err - } - b = tip.Get(KEYChainTip) - if b == nil { - t.Error("Best tip doesn't exist in db") - } - ser, err = serializeHeader(testSh1) - if err != nil { - return err - } - if !bytes.Equal(ser, b) { - t.Error("Best tip failed to PUT header correctly") - } - return nil - }) - if err != nil { - t.Error(err) - } - - // Test header without new tip - err = headers.put(testSh2, false) - if err != nil { - t.Error(err) - } - err = headers.db.View(func(btx *bolt.Tx) error { - hdrs := btx.Bucket(BKTHeaders) - testHash := testSh2.header.BlockHash() - b := hdrs.Get(testHash.CloneBytes()) - if b == nil { - t.Error("Header doesn't exist in db") - } - ser, err := serializeHeader(testSh2) - if err != nil { - return err - } - if !bytes.Equal(ser, b) { - t.Error("Failed to PUT header correctly") - } - tip := btx.Bucket(BKTChainTip) - if err != nil { - return err - } - b = tip.Get(KEYChainTip) - if b == nil { - t.Error("Best tip doesn't exist in db") - } - ser, err = serializeHeader(testSh1) - if err != nil { - return err - } - if !bytes.Equal(ser, b) { - t.Error("Best tip failed to PUT header correctly") - } - return nil - }) - if err != nil { - t.Error(err) - } - // Test put duplicate - err = headers.put(testSh2, true) - if err != nil { - t.Error(err) - } - os.RemoveAll("headers.bin") -} - -func TestHeaderDB_GetPreviousHeader(t *testing.T) { - headers, err := NewHeaderDB("") - if err != nil { - t.Error(err) - } - err = headers.put(testSh1, false) - if err != nil { - t.Error(err) - } - hdr, err := headers.GetPreviousHeader(testSh2.header) - if err != nil { - t.Error(err) - } - shHash := testSh1.header.BlockHash() - testHdrHash := hdr.header.BlockHash() - if !testHdrHash.IsEqual(&shHash) { - t.Error("Get previous header returned incorrect header") - } - os.RemoveAll("headers.bin") -} - -func TestHeaderDB_GetBestHeader(t *testing.T) { - headers, err := NewHeaderDB("") - if err != nil { - t.Error(err) - } - err = headers.put(testSh1, false) - if err != nil { - t.Error(err) - } - hdr, err := headers.GetBestHeader() - if err == nil { - t.Error("Didn't receive error when fetching best header without one set") - } - - err = headers.put(testSh1, true) - if err != nil { - t.Error(err) - } - err = headers.put(testSh2, false) - if err != nil { - t.Error(err) - } - hdr, err = headers.GetBestHeader() - if err != nil { - t.Error(err) - } - testSer, err := serializeHeader(testSh1) - if err != nil { - t.Error(err) - } - ser, err := serializeHeader(hdr) - if err != nil { - t.Error(err) - } - if !bytes.Equal(testSer, ser) { - t.Error("Failed to fetch best header from the db") - } - os.RemoveAll("headers.bin") -} - -func TestHeaderDB_Height(t *testing.T) { - headers, err := NewHeaderDB("") - if err != nil { - t.Error(err) - } - err = headers.put(testSh1, true) - if err != nil { - t.Error(err) - } - height, err := headers.Height() - if err != nil { - t.Error(err) - } - if height != testSh1.height { - t.Error("Returned incorrect height") - } - os.RemoveAll("headers.bin") -} - -func TestHeaderDB_Prune(t *testing.T) { - headers, err := NewHeaderDB("") - if err != nil { - t.Error(err) - } - var toDelete []chainhash.Hash - var toStay []chainhash.Hash - for i := 0; i < 2500; i++ { - hdr := testSh1 - hdr.height = uint32(i) - prev := make([]byte, 32) - rand.Read(prev) - prevHash, err := chainhash.NewHash(prev) - if err != nil { - t.Error(err) - } - hdr.header.PrevBlock = *prevHash - err = headers.put(hdr, true) - if err != nil { - t.Error(err) - } - if i < 500 { - toDelete = append(toDelete, hdr.header.BlockHash()) - } else { - toStay = append(toStay, hdr.header.BlockHash()) - } - } - - err = headers.Prune() - if err != nil { - t.Error(err) - } - err = headers.db.View(func(btx *bolt.Tx) error { - hdrs := btx.Bucket(BKTHeaders) - for _, hash := range toStay { - b := hdrs.Get(hash.CloneBytes()) - if b == nil { - t.Error("Pruned a header that should have stayed") - } - } - for _, hash := range toDelete { - b := hdrs.Get(hash.CloneBytes()) - if b != nil { - t.Error("Failed to prune a header") - } - } - - return nil - }) - if err != nil { - t.Error(err) - } - os.RemoveAll("headers.bin") -} - -func TestHeaderDB_Print(t *testing.T) { - headers, err := NewHeaderDB("") - if err != nil { - t.Error(err) - } - // Test put with new tip - err = headers.put(testSh1, true) - if err != nil { - t.Error(err) - } - err = headers.put(testSh2, true) - if err != nil { - t.Error(err) - } - err = headers.put(testSh3, true) - if err != nil { - t.Error(err) - } - var b bytes.Buffer - headers.Print(&b) - out := strings.Split(b.String(), "\n") - if out[0] != `Height: 100.0, Hash: 000000000000012a8ab8bccd1d3b09f3d1179850ad99ba7b978a870c59ef8141, Parent: 00000000000008471ccf356a18dd48aa12506ef0b6162cb8f98a8d8bb0465902` { - t.Error("Print function had incorrect return") - } - if out[1] != `Height: 200.0, Hash: 5f9e2cdf4dee12120f50f1b0e3086441a637fd09ff395dcf4e46735599633c4b, Parent: 00000000000011228c88ccad1a3199ffd4279152a596babb90aa770055ea8844` { - t.Error("Print function had incorrect return") - } - if out[2] != `Height: 200.1, Hash: abe7bc6da630b6e0be7167ce23a4cf42d614543206e3725d21ebe829618a94af, Parent: 000000000000012a8ab8bccd1d3b09f3d1179850ad99ba7b978a870c59ef8141` { - t.Error("Print function had incorrect return") - } - os.RemoveAll("headers.bin") -} - -func TestHeaderDB_DeleteAfter(t *testing.T) { - headers, err := NewHeaderDB("") - if err != nil { - t.Error(err) - } - var toDelete []chainhash.Hash - var toStay []chainhash.Hash - for i := 0; i < 2500; i++ { - hdr := testSh1 - hdr.height = uint32(i) - prev := make([]byte, 32) - rand.Read(prev) - prevHash, err := chainhash.NewHash(prev) - if err != nil { - t.Error(err) - } - hdr.header.PrevBlock = *prevHash - hdr.header.Timestamp = time.Now().Add(time.Minute * time.Duration(i)) - err = headers.put(hdr, true) - if err != nil { - t.Error(err) - } - if i > 500 { - toDelete = append(toDelete, hdr.header.BlockHash()) - } else { - toStay = append(toStay, hdr.header.BlockHash()) - } - } - - err = headers.DeleteAfter(500) - if err != nil { - t.Error(err) - } - err = headers.db.View(func(btx *bolt.Tx) error { - hdrs := btx.Bucket(BKTHeaders) - for _, hash := range toStay { - b := hdrs.Get(hash.CloneBytes()) - if b == nil { - t.Error("Pruned a header that should have stayed") - } - } - for _, hash := range toDelete { - b := hdrs.Get(hash.CloneBytes()) - if b != nil { - t.Error("Failed to prune a header") - } - } - return nil - }) - if err != nil { - t.Error(err) - } - os.RemoveAll("headers.bin") -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/keys_test.go b/vendor/github.com/OpenBazaar/spvwallet/keys_test.go deleted file mode 100644 index cea748ca2d..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/keys_test.go +++ /dev/null @@ -1,286 +0,0 @@ -package spvwallet - -import ( - "bytes" - "encoding/hex" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/hdkeychain" - "testing" -) - -func createKeyManager() (*KeyManager, error) { - masterPrivKey, err := hdkeychain.NewKeyFromString("xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6") - if err != nil { - return nil, err - } - return NewKeyManager(&mockKeyStore{make(map[string]*keyStoreEntry)}, &chaincfg.MainNetParams, masterPrivKey) -} - -func TestNewKeyManager(t *testing.T) { - km, err := createKeyManager() - if err != nil { - t.Error(err) - } - keys, err := km.datastore.GetAll() - if err != nil { - t.Error(err) - } - if len(keys) != LOOKAHEADWINDOW*2 { - t.Error("Failed to generate lookahead windows when creating a new KeyManager") - } -} - -func TestBip44Derivation(t *testing.T) { - masterPrivKey, err := hdkeychain.NewKeyFromString("xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6") - if err != nil { - t.Error(err) - } - internal, external, err := Bip44Derivation(masterPrivKey) - if err != nil { - t.Error(err) - } - externalKey, err := external.Child(0) - if err != nil { - t.Error(err) - } - externalAddr, err := externalKey.Address(&chaincfg.MainNetParams) - if err != nil { - t.Error(err) - } - if externalAddr.String() != "17rxURoF96VhmkcEGCj5LNQkmN9HVhWb7F" { - t.Error("Incorrect Bip44 key derivation") - } - - internalKey, err := internal.Child(0) - if err != nil { - t.Error(err) - } - internalAddr, err := internalKey.Address(&chaincfg.MainNetParams) - if err != nil { - t.Error(err) - } - if internalAddr.String() != "16wbbYdecq9QzXdxa58q2dYXJRc8sfkE4J" { - t.Error("Incorrect Bip44 key derivation") - } -} - -func TestKeys_generateChildKey(t *testing.T) { - km, err := createKeyManager() - if err != nil { - t.Error(err) - } - internalKey, err := km.generateChildKey(wallet.INTERNAL, 0) - internalAddr, err := internalKey.Address(&chaincfg.MainNetParams) - if err != nil { - t.Error(err) - } - if internalAddr.String() != "16wbbYdecq9QzXdxa58q2dYXJRc8sfkE4J" { - t.Error("generateChildKey returned incorrect key") - } - externalKey, err := km.generateChildKey(wallet.EXTERNAL, 0) - externalAddr, err := externalKey.Address(&chaincfg.MainNetParams) - if err != nil { - t.Error(err) - } - if externalAddr.String() != "17rxURoF96VhmkcEGCj5LNQkmN9HVhWb7F" { - t.Error("generateChildKey returned incorrect key") - } -} - -func TestKeyManager_lookahead(t *testing.T) { - masterPrivKey, err := hdkeychain.NewKeyFromString("xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6") - if err != nil { - t.Error(err) - } - mock := &mockKeyStore{make(map[string]*keyStoreEntry)} - km, err := NewKeyManager(mock, &chaincfg.MainNetParams, masterPrivKey) - if err != nil { - t.Error(err) - } - for _, key := range mock.keys { - key.used = true - } - n := len(mock.keys) - err = km.lookahead() - if err != nil { - t.Error(err) - } - if len(mock.keys) != n+(LOOKAHEADWINDOW*2) { - t.Error("Failed to generated a correct lookahead window") - } - unused := 0 - for _, k := range mock.keys { - if !k.used { - unused++ - } - } - if unused != LOOKAHEADWINDOW*2 { - t.Error("Failed to generated unused keys in lookahead window") - } -} - -func TestKeyManager_MarkKeyAsUsed(t *testing.T) { - km, err := createKeyManager() - if err != nil { - t.Error(err) - } - i, err := km.datastore.GetUnused(wallet.EXTERNAL) - if err != nil { - t.Error(err) - } - if len(i) == 0 { - t.Error("No unused keys in database") - } - key, err := km.generateChildKey(wallet.EXTERNAL, uint32(i[0])) - if err != nil { - t.Error(err) - } - addr, err := key.Address(&chaincfg.MainNetParams) - if err != nil { - t.Error(err) - } - err = km.MarkKeyAsUsed(addr.ScriptAddress()) - if err != nil { - t.Error(err) - } - if len(km.GetKeys()) != (LOOKAHEADWINDOW*2)+1 { - t.Error("Failed to extend lookahead window when marking as read") - } - unused, err := km.datastore.GetUnused(wallet.EXTERNAL) - if err != nil { - t.Error(err) - } - for _, i := range unused { - if i == 0 { - t.Error("Failed to mark key as used") - } - } -} - -func TestKeyManager_GetCurrentKey(t *testing.T) { - masterPrivKey, err := hdkeychain.NewKeyFromString("xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6") - if err != nil { - t.Error(err) - } - mock := &mockKeyStore{make(map[string]*keyStoreEntry)} - km, err := NewKeyManager(mock, &chaincfg.MainNetParams, masterPrivKey) - if err != nil { - t.Error(err) - } - var scriptAddress string - for script, key := range mock.keys { - if key.path.Purpose == wallet.EXTERNAL && key.path.Index == 0 { - scriptAddress = script - break - } - } - key, err := km.GetCurrentKey(wallet.EXTERNAL) - if err != nil { - t.Error(err) - } - addr, err := key.Address(&chaincfg.Params{}) - if err != nil { - t.Error(err) - } - if hex.EncodeToString(addr.ScriptAddress()) != scriptAddress { - t.Error("CurrentKey returned wrong key") - } -} - -func TestKeyManager_GetFreshKey(t *testing.T) { - km, err := createKeyManager() - if err != nil { - t.Error(err) - } - key, err := km.GetFreshKey(wallet.EXTERNAL) - if err != nil { - t.Error(err) - } - if len(km.GetKeys()) != LOOKAHEADWINDOW*2+1 { - t.Error("Failed to create additional key") - } - key2, err := km.generateChildKey(wallet.EXTERNAL, 100) - if err != nil { - t.Error(err) - } - if key.String() != key2.String() { - t.Error("GetFreshKey returned incorrect key") - } -} - -func TestKeyManager_GetKeys(t *testing.T) { - km, err := createKeyManager() - if err != nil { - t.Error(err) - } - keys := km.GetKeys() - if len(keys) != LOOKAHEADWINDOW*2 { - t.Error("Returned incorrect number of keys") - } - for _, key := range keys { - if key == nil { - t.Error("Incorrectly returned nil key") - } - } -} - -func TestKeyManager_GetKeyForScript(t *testing.T) { - masterPrivKey, err := hdkeychain.NewKeyFromString("xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6") - if err != nil { - t.Error(err) - } - mock := &mockKeyStore{make(map[string]*keyStoreEntry)} - km, err := NewKeyManager(mock, &chaincfg.MainNetParams, masterPrivKey) - if err != nil { - t.Error(err) - } - addr, err := btcutil.DecodeAddress("17rxURoF96VhmkcEGCj5LNQkmN9HVhWb7F", &chaincfg.MainNetParams) - if err != nil { - t.Error(err) - } - key, err := km.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - t.Error(err) - } - if key == nil { - t.Error("Returned key is nil") - } - testAddr, err := key.Address(&chaincfg.MainNetParams) - if err != nil { - t.Error(err) - } - if testAddr.String() != addr.String() { - t.Error("Returned incorrect key") - } - importKey, err := btcec.NewPrivateKey(btcec.S256()) - if err != nil { - t.Error(err) - } - importAddr, err := key.Address(&chaincfg.MainNetParams) - if err != nil { - t.Error(err) - } - importScript, err := txscript.PayToAddrScript(importAddr) - if err != nil { - t.Error(err) - } - err = km.datastore.ImportKey(importScript, importKey) - if err != nil { - t.Error(err) - } - retKey, err := km.GetKeyForScript(importScript) - if err != nil { - t.Error(err) - } - retECKey, err := retKey.ECPrivKey() - if err != nil { - t.Error(err) - } - if !bytes.Equal(retECKey.Serialize(), importKey.Serialize()) { - t.Error("Failed to return imported key") - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/mblock_test.go b/vendor/github.com/OpenBazaar/spvwallet/mblock_test.go deleted file mode 100644 index 0b24a83bbd..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/mblock_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package spvwallet - -import ( - "bytes" - "crypto/sha256" - "encoding/hex" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "testing" -) - -func TestMakeMerkleParent(t *testing.T) { - // Test same hash - left, err := chainhash.NewHashFromStr("35be3035ce615f40af9b04124d05c64ecf14c96f37e7de02a57e4211972df04d") - if err != nil { - t.Error(err) - } - h, err := MakeMerkleParent(left, left) - if err == nil { - t.Error("Checking for duplicate hashes failed") - } - - // Check left child nil - h, err = MakeMerkleParent(nil, left) - if err == nil { - t.Error("Checking for nil left failed") - } - - // Check right child nil - h, err = MakeMerkleParent(left, nil) - if err != nil { - t.Error(err) - } - var sha [64]byte - copy(sha[:32], left.CloneBytes()[:]) - copy(sha[32:], left.CloneBytes()[:]) - sgl := sha256.Sum256(sha[:]) - dbl := sha256.Sum256(sgl[:]) - if !bytes.Equal(dbl[:], h.CloneBytes()) { - t.Error("Invalid hash returned when right is nil") - } - - // Check valid hash return - right, err := chainhash.NewHashFromStr("051b2338a496800ac09d130aee71096e13c73ccc28e83dc92d9439491d8be449") - if err != nil { - t.Error(err) - } - h, err = MakeMerkleParent(left, right) - if err != nil { - t.Error(err) - } - copy(sha[:32], left.CloneBytes()[:]) - copy(sha[32:], right.CloneBytes()[:]) - sgl = sha256.Sum256(sha[:]) - dbl = sha256.Sum256(sgl[:]) - if !bytes.Equal(dbl[:], h.CloneBytes()) { - t.Error("Invalid hash returned") - } -} - -func TestMBolck_treeDepth(t *testing.T) { - if treeDepth(8) != 3 { - t.Error("treeDepth returned incorrect value") - } - if treeDepth(16) != 4 { - t.Error("treeDepth returned incorrect value") - } - if treeDepth(64) != 6 { - t.Error("treeDepth returned incorrect value") - } -} - -func TestMBolck_nextPowerOfTwo(t *testing.T) { - if nextPowerOfTwo(5) != 8 { - t.Error("treeDepth returned incorrect value") - } - if nextPowerOfTwo(15) != 16 { - t.Error("treeDepth returned incorrect value") - } - if nextPowerOfTwo(57) != 64 { - t.Error("treeDepth returned incorrect value") - } -} - -func TestMBlock_inDeadZone(t *testing.T) { - // Test greater than root - if !inDeadZone(127, 57) { - t.Error("Failed to detect position greater than root") - } - // Test not in dead zone - if inDeadZone(126, 57) { - t.Error("Incorrectly returned in dead zone") - } -} - -func TestMBlockCheckMBlock(t *testing.T) { - rawBlock, err := hex.DecodeString("0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b852907000000043612262624047ee87660be1a707519a443b1c1ce3d248cbfc6c15870f6c5daa2019f5b01d4195ecbc9398fbf3c3b1fa9bb3183301d7a1fb3bd174fcfa40a2b6541ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d06820d2a7bc994987302e5b1ac80fc425fe25f8b63169ea78e68fbaaefa59379bbf011d") - if err != nil { - t.Error(err) - } - merkleBlock := &wire.MsgMerkleBlock{} - r := bytes.NewReader(rawBlock) - merkleBlock.BtcDecode(r, 70002, wire.WitnessEncoding) - hashes, err := checkMBlock(merkleBlock) - if err != nil { - t.Error(err) - } - if len(hashes) != 1 { - t.Error("Returned incorrect number of hashes") - } - if hashes[0].String() != "652b0aa4cf4f17bdb31f7a1d308331bba91f3b3cbf8f39c9cb5e19d4015b9f01" { - t.Error("Returned incorrect hash") - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/mock.go b/vendor/github.com/OpenBazaar/spvwallet/mock.go index 7c84b49e39..df6d7554e5 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/mock.go +++ b/vendor/github.com/OpenBazaar/spvwallet/mock.go @@ -229,10 +229,10 @@ type mockTxnStore struct { txns map[string]*wallet.Txn } -func (m *mockTxnStore) Put(raw []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error { +func (m *mockTxnStore) Put(raw []byte, txid, value string, height int, timestamp time.Time, watchOnly bool) error { m.txns[txid] = &wallet.Txn{ Txid: txid, - Value: int64(value), + Value: value, Height: int32(height), Timestamp: timestamp, WatchOnly: watchOnly, @@ -288,6 +288,13 @@ func (m *mockWatchedScriptsStore) Put(scriptPubKey []byte) error { return nil } +func (m *mockWatchedScriptsStore) PutAll(ss [][]byte) error { + for _, s := range ss { + m.Put(s) + } + return nil +} + func (m *mockWatchedScriptsStore) GetAll() ([][]byte, error) { var ret [][]byte for _, b := range m.scripts { @@ -315,7 +322,7 @@ func TestUtxo_IsEqual(t *testing.T) { Op: *wire.NewOutPoint(h, 0), ScriptPubkey: make([]byte, 32), AtHeight: 400000, - Value: 1000000, + Value: "1000000", } if !u.IsEqual(u) { t.Error("Failed to return utxos as equal") @@ -331,7 +338,7 @@ func TestUtxo_IsEqual(t *testing.T) { t.Error("Failed to return utxos as not equal") } testUtxo = *u - testUtxo.Value = 4 + testUtxo.Value = "4" if u.IsEqual(&testUtxo) { t.Error("Failed to return utxos as not equal") } @@ -363,7 +370,7 @@ func TestStxo_IsEqual(t *testing.T) { Op: *wire.NewOutPoint(h, 0), ScriptPubkey: make([]byte, 32), AtHeight: 400000, - Value: 1000000, + Value: "1000000", } h2, err := chainhash.NewHashFromStr("1f64249abbf2fcc83fc060a64f69a91391e9f5d98c5d3135fe9716838283aa4c") s := &wallet.Stxo{ diff --git a/vendor/github.com/OpenBazaar/spvwallet/sortsignsend.go b/vendor/github.com/OpenBazaar/spvwallet/sortsignsend.go index e5cc550d0b..1947afcc3d 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/sortsignsend.go +++ b/vendor/github.com/OpenBazaar/spvwallet/sortsignsend.go @@ -9,6 +9,8 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" "time" "github.com/OpenBazaar/wallet-interface" @@ -55,16 +57,20 @@ func (c *Coin) PkScript() []byte { return c.ScriptPubKey } func (c *Coin) NumConfs() int64 { return c.TxNumConfs } func (c *Coin) ValueAge() int64 { return int64(c.TxValue) * c.TxNumConfs } -func NewCoin(txid []byte, index uint32, value btc.Amount, numConfs int64, scriptPubKey []byte) coinset.Coin { +func newCoin(txid []byte, index uint32, value string, numConfs int64, scriptPubKey []byte) (coinset.Coin, error) { + iVal, err := strconv.Atoi(value) + if err != nil { + return nil, fmt.Errorf("coin value (%s) is invalid", value) + } shaTxid, _ := chainhash.NewHash(txid) c := &Coin{ TxHash: shaTxid, TxIndex: index, - TxValue: value, + TxValue: btc.Amount(iVal), TxNumConfs: numConfs, ScriptPubKey: scriptPubKey, } - return coinset.Coin(c) + return coinset.Coin(c), nil } func (w *SPVWallet) gatherCoins() map[coinset.Coin]*hd.ExtendedKey { @@ -79,7 +85,10 @@ func (w *SPVWallet) gatherCoins() map[coinset.Coin]*hd.ExtendedKey { if u.AtHeight > 0 { confirmations = int32(height) - u.AtHeight } - c := NewCoin(u.Op.Hash.CloneBytes(), u.Op.Index, btc.Amount(u.Value), int64(confirmations), u.ScriptPubkey) + c, err := newCoin(u.Op.Hash.CloneBytes(), u.Op.Index, u.Value, int64(confirmations), u.ScriptPubkey) + if err != nil { + continue + } addr, err := w.ScriptToAddress(u.ScriptPubkey) if err != nil { continue @@ -93,7 +102,7 @@ func (w *SPVWallet) gatherCoins() map[coinset.Coin]*hd.ExtendedKey { return m } -func (w *SPVWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *SPVWallet) Spend(amount big.Int, addr btc.Address, feeLevel wallet.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -104,7 +113,7 @@ func (w *SPVWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLev return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -143,7 +152,7 @@ func (w *SPVWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { key, err := w.txstore.GetKeyForScript(output.PkScript) if key != nil && err == nil { // This is our change output // Calculate change - additional fee - feePerByte := w.GetFeePerByte(PRIOIRTY) + feePerByte := w.GetFeePerByte(PRIORITY) estimatedSize := EstimateSerializeSize(len(msgTx.TxIn), msgTx.TxOut, false) fee := estimatedSize * int(feePerByte) newValue := output.Value - int64(fee) @@ -200,11 +209,12 @@ func (w *SPVWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { if err != nil { return nil, err } + val0, _ := new(big.Int).SetString(u.Value, 10) in := wallet.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: u.Value, + Value: *val0, } transactionID, err := w.SweepAddress([]wallet.TransactionInput{in}, nil, key, nil, wallet.FEE_BUMP) if err != nil { @@ -216,28 +226,28 @@ func (w *SPVWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { return nil, BumpFeeNotFoundError } -func (w *SPVWallet) EstimateFee(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, feePerByte uint64) uint64 { +func (w *SPVWallet) EstimateFee(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := txscript.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Uint64()) + return *big.NewInt(int64(fee)) } // Build a spend transaction for the amount and return the transaction fee -func (w *SPVWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (uint64, error) { +func (w *SPVWallet) EstimateSpendFee(amount big.Int, feeLevel wallet.FeeLevel) (big.Int, error) { // Since this is an estimate we can use a dummy output address. Let's use a long one so we don't under estimate. addr, err := btc.DecodeAddress("bc1qxtq7ha2l5qg70atpwp3fus84fx3w0v2w4r2my7gt89ll3w0vnlgspu349h", w.params) if err != nil { - return 0, err + return *big.NewInt(0), err } - tx, err := w.buildTx(amount, addr, feeLevel, nil) + tx, err := w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { - return 0, err + return *big.NewInt(0), err } var outval int64 for _, output := range tx.TxOut { @@ -246,20 +256,21 @@ func (w *SPVWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (ui var inval int64 utxos, err := w.txstore.Utxos().GetAll() if err != nil { - return 0, err + return *big.NewInt(0), err } for _, input := range tx.TxIn { for _, utxo := range utxos { if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + val0, _ := new(big.Int).SetString(utxo.Value, 10) + inval += val0.Int64() break } } } if inval < outval { - return 0, errors.New("Error building transaction: inputs less than outputs") + return *big.NewInt(0), errors.New("Error building transaction: inputs less than outputs") } - return uint64(inval - outval), err + return *big.NewInt(inval - outval), err } func (w *SPVWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) { @@ -327,7 +338,7 @@ func (w *SPVWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, return addr, redeemScript, nil } -func (w *SPVWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wallet.Signature, error) { +func (w *SPVWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wallet.Signature, error) { var sigs []wallet.Signature tx := wire.NewMsgTx(1) for _, in := range ins { @@ -344,7 +355,7 @@ func (w *SPVWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs if err != nil { return sigs, err } - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } @@ -355,7 +366,7 @@ func (w *SPVWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs txType = P2SH_Multisig_Timelock_2Sigs } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, txType) - fee := estimatedSize * int(feePerByte) + fee := estimatedSize * int(feePerByte.Uint64()) if len(tx.TxOut) > 0 { feePerOutput := fee / len(tx.TxOut) for _, output := range tx.TxOut { @@ -373,7 +384,7 @@ func (w *SPVWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs hashes := txscript.NewTxSigHashes(tx) for i := range tx.TxIn { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, redeemScript, txscript.SigHashAll, signingKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), redeemScript, txscript.SigHashAll, signingKey) if err != nil { continue } @@ -383,7 +394,7 @@ func (w *SPVWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs return sigs, nil } -func (w *SPVWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, sigs1 []wallet.Signature, sigs2 []wallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { +func (w *SPVWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, sigs1 []wallet.Signature, sigs2 []wallet.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { tx := wire.NewMsgTx(1) for _, in := range ins { ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) @@ -399,7 +410,7 @@ func (w *SPVWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.Trans if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } @@ -410,7 +421,7 @@ func (w *SPVWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.Trans txType = P2SH_Multisig_Timelock_2Sigs } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, txType) - fee := estimatedSize * int(feePerByte) + fee := estimatedSize * int(feePerByte.Uint64()) if len(tx.TxOut) > 0 { feePerOutput := fee / len(tx.TxOut) for _, output := range tx.TxOut { @@ -476,7 +487,7 @@ func (w *SPVWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Add var inputs []*wire.TxIn additionalPrevScripts := make(map[wire.OutPoint][]byte) for _, in := range ins { - val += in.Value + val += in.Value.Int64() ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -503,7 +514,8 @@ func (w *SPVWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Add estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -576,7 +588,7 @@ func (w *SPVWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Add } txIn.SignatureScript = script } else { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, *redeemScript, txscript.SigHashAll, privKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), *redeemScript, txscript.SigHashAll, privKey) if err != nil { return nil, err } @@ -600,7 +612,7 @@ func (w *SPVWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Add func (w *SPVWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, optionalOutput *wire.TxOut) (*wire.MsgTx, error) { // Check for dust script, _ := txscript.PayToAddrScript(addr) - if txrules.IsDustAmount(btc.Amount(amount), len(script), txrules.DefaultRelayFeePerKb) { + if isTxSizeDust(*big.NewInt(amount), len(script)) { return nil, wallet.ErrorDustAmount } @@ -618,7 +630,7 @@ func (w *SPVWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeL coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)} coins, err := coinSelector.CoinSelect(target, coins) if err != nil { - return total, inputs, []btc.Amount{}, scripts, wallet.ErrorInsuffientFunds + return total, inputs, []btc.Amount{}, scripts, wallet.ErrInsufficientFunds } additionalPrevScripts = make(map[wire.OutPoint][]byte) additionalKeysByAddress = make(map[string]*btc.WIF) @@ -645,7 +657,8 @@ func (w *SPVWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeL } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -698,7 +711,6 @@ func (w *SPVWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeL func (w *SPVWallet) buildSpendAllTx(addr btc.Address, feeLevel wallet.FeeLevel) (*wire.MsgTx, error) { tx := wire.NewMsgTx(1) - coinMap := w.gatherCoins() inVals := make(map[wire.OutPoint]int64) totalIn := int64(0) @@ -733,12 +745,12 @@ func (w *SPVWallet) buildSpendAllTx(addr btc.Address, feeLevel wallet.FeeLevel) } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + feePerByte := w.GetFeePerByte(feeLevel) estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) - fee := int64(estimatedSize) * feePerByte + fee := int64(estimatedSize) * feePerByte.Int64() // Check for dust output - if txrules.IsDustAmount(btc.Amount(totalIn-fee), len(script), txrules.DefaultRelayFeePerKb) { + if isTxSizeDust(*big.NewInt(totalIn - fee), len(script)) { return nil, wallet.ErrorDustAmount } @@ -810,8 +822,7 @@ func NewUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInp } changeIndex := -1 changeAmount := inputAmount - targetAmount - maxRequiredFee - if changeAmount != 0 && !txrules.IsDustAmount(changeAmount, - P2PKHOutputSize, txrules.DefaultRelayFeePerKb) { + if changeAmount != 0 && !isTxSizeDust(*big.NewInt(int64(changeAmount)), P2PKHOutputSize) { changeScript, err := fetchChange() if err != nil { return nil, err @@ -835,8 +846,8 @@ func NewUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInp } } -func (w *SPVWallet) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 { - return w.feeProvider.GetFeePerByte(feeLevel) +func (w *SPVWallet) GetFeePerByte(feeLevel wallet.FeeLevel) big.Int { + return *big.NewInt(int64(w.feeProvider.GetFeePerByte(feeLevel))) } func LockTimeFromRedeemScript(redeemScript []byte) (uint32, error) { diff --git a/vendor/github.com/OpenBazaar/spvwallet/sortsignsend_test.go b/vendor/github.com/OpenBazaar/spvwallet/sortsignsend_test.go deleted file mode 100644 index 491d79cf24..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/sortsignsend_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package spvwallet - -import ( - "bytes" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "os" - "testing" -) - -func MockWallet() *SPVWallet { - txstore, _ := createTxStore() - - peerCfg := &PeerManagerConfig{ - UserAgentVersion: WALLET_VERSION, - Params: &chaincfg.TestNet3Params, - } - - bc, _ := NewBlockchain("", MockCreationTime, &chaincfg.TestNet3Params) - createBlockChain(bc) - - peerManager, _ := NewPeerManager(peerCfg) - return &SPVWallet{txstore: txstore, peerManager: peerManager, blockchain: bc, keyManager: txstore.keyManager, params: &chaincfg.TestNet3Params} -} - -func Test_gatherCoins(t *testing.T) { - w := MockWallet() - h1, err := chainhash.NewHashFromStr("6f7a58ad92702601fcbaac0e039943a384f5274a205c16bb8bbab54f9ea2fbad") - if err != nil { - t.Error(err) - } - key1, err := w.keyManager.GetFreshKey(wallet.EXTERNAL) - if err != nil { - t.Error(err) - } - addr1, err := key1.Address(&chaincfg.TestNet3Params) - if err != nil { - t.Error(err) - } - script1, err := w.AddressToScript(addr1) - if err != nil { - t.Error(err) - } - op := wire.NewOutPoint(h1, 0) - err = w.txstore.Utxos().Put(wallet.Utxo{Op: *op, ScriptPubkey: script1, AtHeight: 5, Value: 10000}) - if err != nil { - t.Error(err) - } - coinmap := w.gatherCoins() - for coin, key := range coinmap { - if !bytes.Equal(coin.PkScript(), script1) { - t.Error("Pubkey script in coin is incorrect") - } - if coin.Index() != 0 { - t.Error("Returned incorrect index") - } - if !coin.Hash().IsEqual(h1) { - t.Error("Returned incorrect hash") - } - height, _ := w.blockchain.db.Height() - if coin.NumConfs() != int64(height-5) { - t.Error("Returned incorrect number of confirmations") - } - if coin.Value() != 10000 { - t.Error("Returned incorrect coin value") - } - addr2, err := key.Address(&chaincfg.TestNet3Params) - if err != nil { - t.Error(err) - } - if addr2.EncodeAddress() != addr1.EncodeAddress() { - t.Error("Returned incorrect key") - } - } - os.Remove("headers.bin") -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/timesorter_test.go b/vendor/github.com/OpenBazaar/spvwallet/timesorter_test.go deleted file mode 100644 index b7e65aa31d..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/timesorter_test.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2013-2017 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package spvwallet - -import ( - "reflect" - "sort" - "testing" -) - -func TstTimeSorter(times []int64) sort.Interface { - return timeSorter(times) -} - -// TestTimeSorter tests the timeSorter implementation. -func TestTimeSorter(t *testing.T) { - tests := []struct { - in []int64 - want []int64 - }{ - { - in: []int64{ - 1351228575, // Fri Oct 26 05:16:15 UTC 2012 (Block #205000) - 1348310759, // Sat Sep 22 10:45:59 UTC 2012 (Block #200000) - 1305758502, // Wed May 18 22:41:42 UTC 2011 (Block #125000) - 1347777156, // Sun Sep 16 06:32:36 UTC 2012 (Block #199000) - 1349492104, // Sat Oct 6 02:55:04 UTC 2012 (Block #202000) - }, - want: []int64{ - 1305758502, // Wed May 18 22:41:42 UTC 2011 (Block #125000) - 1347777156, // Sun Sep 16 06:32:36 UTC 2012 (Block #199000) - 1348310759, // Sat Sep 22 10:45:59 UTC 2012 (Block #200000) - 1349492104, // Sat Oct 6 02:55:04 UTC 2012 (Block #202000) - 1351228575, // Fri Oct 26 05:16:15 UTC 2012 (Block #205000) - }, - }, - } - - for i, test := range tests { - result := make([]int64, len(test.in)) - copy(result, test.in) - sort.Sort(TstTimeSorter(result)) - if !reflect.DeepEqual(result, test.want) { - t.Errorf("timeSorter #%d got %v want %v", i, result, - test.want) - continue - } - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/txsizes_test.go b/vendor/github.com/OpenBazaar/spvwallet/txsizes_test.go deleted file mode 100644 index 22297d0e29..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/txsizes_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package spvwallet - -// Copyright (c) 2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -/* Copied here from a btcd internal package*/ - -import ( - "bytes" - "encoding/hex" - "github.com/btcsuite/btcd/wire" - "testing" -) - -const ( - p2pkhScriptSize = P2PKHPkScriptSize - p2shScriptSize = 23 -) - -func makeInts(value int, n int) []int { - v := make([]int, n) - for i := range v { - v[i] = value - } - return v -} - -func TestEstimateSerializeSize(t *testing.T) { - tests := []struct { - InputCount int - OutputScriptLengths []int - AddChangeOutput bool - ExpectedSizeEstimate int - }{ - 0: {1, []int{}, false, 161}, - 1: {1, []int{p2pkhScriptSize}, false, 195}, - 2: {1, []int{}, true, 195}, - 3: {1, []int{p2pkhScriptSize}, true, 229}, - 4: {1, []int{p2shScriptSize}, false, 193}, - 5: {1, []int{p2shScriptSize}, true, 227}, - - 6: {2, []int{}, false, 310}, - 7: {2, []int{p2pkhScriptSize}, false, 344}, - 8: {2, []int{}, true, 344}, - 9: {2, []int{p2pkhScriptSize}, true, 378}, - 10: {2, []int{p2shScriptSize}, false, 342}, - 11: {2, []int{p2shScriptSize}, true, 376}, - - // 0xfd is discriminant for 16-bit compact ints, compact int - // total size increases from 1 byte to 3. - 12: {1, makeInts(p2pkhScriptSize, 0xfc), false, 8729}, - 13: {1, makeInts(p2pkhScriptSize, 0xfd), false, 8729 + P2PKHOutputSize + 2}, - 14: {1, makeInts(p2pkhScriptSize, 0xfc), true, 8729 + P2PKHOutputSize + 2}, - 15: {0xfc, []int{}, false, 37560}, - 16: {0xfd, []int{}, false, 37560 + RedeemP2PKHInputSize + 2}, - } - for i, test := range tests { - outputs := make([]*wire.TxOut, 0, len(test.OutputScriptLengths)) - for _, l := range test.OutputScriptLengths { - outputs = append(outputs, &wire.TxOut{PkScript: make([]byte, l)}) - } - actualEstimate := EstimateSerializeSize(test.InputCount, outputs, test.AddChangeOutput, P2PKH) - if actualEstimate != test.ExpectedSizeEstimate { - t.Errorf("Test %d: Got %v: Expected %v", i, actualEstimate, test.ExpectedSizeEstimate) - } - } -} - -func TestSumOutputSerializeSizes(t *testing.T) { - testTx := "0100000001066b78efa7d66d271cae6d6eb799e1d10953fb1a4a760226cc93186d52b55613010000006a47304402204e6c32cc214c496546c3277191ca734494fe49fed0af1d800db92fed2021e61802206a14d063b67f2f1c8fc18f9e9a5963fe33e18c549e56e3045e88b4fc6219be11012103f72d0a11727219bff66b8838c3c5e1c74a5257a325b0c84247bd10bdb9069e88ffffffff0200c2eb0b000000001976a914426e80ad778792e3e19c20977fb93ec0591e1a3988ac35b7cb59000000001976a914e5b6dc0b297acdd99d1a89937474df77db5743c788ac00000000" - txBytes, err := hex.DecodeString(testTx) - if err != nil { - t.Error(err) - return - } - r := bytes.NewReader(txBytes) - msgTx := wire.NewMsgTx(1) - msgTx.BtcDecode(r, 1, wire.WitnessEncoding) - if SumOutputSerializeSizes(msgTx.TxOut) != 68 { - t.Error("SumOutputSerializeSizes returned incorrect value") - } - -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/txstore.go b/vendor/github.com/OpenBazaar/spvwallet/txstore.go index a0044c450f..1fde4b6cf9 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/txstore.go +++ b/vendor/github.com/OpenBazaar/spvwallet/txstore.go @@ -6,6 +6,11 @@ package spvwallet import ( "bytes" "errors" + "math/big" + "strconv" + "sync" + "time" + "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg" @@ -14,8 +19,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/bloom" - "sync" - "time" ) type TxStore struct { @@ -94,7 +97,7 @@ func (ts *TxStore) GimmeFilter() (*bloom.Filter, error) { return f, nil } -// GetDoubleSpends takes a transaction and compares it with +// CheckDoubleSpends takes a transaction and compares it with // all transactions in the db. It returns a slice of all txids in the db // which are double spent by the received tx. func (ts *TxStore) CheckDoubleSpends(argTx *wire.MsgTx) ([]*chainhash.Hash, error) { @@ -254,7 +257,7 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (ui // Ignore the error here because the sender could have used and exotic script // for his change and we don't want to fail in that case. addr, _ := scriptToAddress(txout.PkScript, ts.params) - out := wallet.TransactionOutput{Address: addr, Value: txout.Value, Index: uint32(i)} + out := wallet.TransactionOutput{Address: addr, Value: *big.NewInt(txout.Value), Index: uint32(i)} for _, script := range PKscripts { if bytes.Equal(txout.PkScript, script) { // new utxo found scriptAddress, _ := ts.extractScriptAddress(txout.PkScript) @@ -265,12 +268,12 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (ui } newu := wallet.Utxo{ AtHeight: height, - Value: txout.Value, + Value: strconv.FormatInt(txout.Value, 10), ScriptPubkey: txout.PkScript, Op: newop, WatchOnly: false, } - value += newu.Value + value += txout.Value ts.Utxos().Put(newu) hits++ break @@ -285,7 +288,7 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (ui } newu := wallet.Utxo{ AtHeight: height, - Value: txout.Value, + Value: strconv.FormatInt(txout.Value, 10), ScriptPubkey: txout.PkScript, Op: newop, WatchOnly: true, @@ -311,8 +314,9 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (ui ts.Stxos().Put(st) ts.Utxos().Delete(u) utxos = append(utxos[:i], utxos[i+1:]...) + val0, _ := new(big.Int).SetString(u.Value, 10) if !u.WatchOnly { - value -= u.Value + value -= val0.Int64() hits++ } else { matchesWatchOnly = true @@ -326,7 +330,7 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (ui OutpointHash: u.Op.Hash.CloneBytes(), OutpointIndex: u.Op.Index, LinkedAddress: addr, - Value: u.Value, + Value: *val0, } cb.Inputs = append(cb.Inputs, in) break @@ -361,12 +365,12 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (ui txn, err := ts.Txns().Get(tx.TxHash()) shouldCallback := false if err != nil { - cb.Value = value + cb.Value = *big.NewInt(value) txn.Timestamp = timestamp shouldCallback = true var buf bytes.Buffer tx.BtcEncode(&buf, wire.ProtocolVersion, wire.WitnessEncoding) - ts.Txns().Put(buf.Bytes(), tx.TxHash().String(), int(value), int(height), txn.Timestamp, hits == 0) + ts.Txns().Put(buf.Bytes(), tx.TxHash().String(), strconv.FormatInt(value, 10), int(height), txn.Timestamp, hits == 0) ts.txids[tx.TxHash().String()] = height } // Let's check the height before committing so we don't allow rogue peers to send us a lose @@ -375,7 +379,8 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (ui ts.Txns().UpdateHeight(tx.TxHash(), int(height), txn.Timestamp) ts.txids[tx.TxHash().String()] = height if height > 0 { - cb.Value = txn.Value + val0, _ := new(big.Int).SetString(txn.Value, 10) + cb.Value = *val0 shouldCallback = true } } @@ -456,12 +461,12 @@ func (ts *TxStore) processReorg(lastGoodHeight uint32) error { if txns[i].Height > int32(lastGoodHeight) { txid, err := chainhash.NewHashFromStr(txns[i].Txid) if err != nil { - log.Error(err) + log.Error(err.Error()) continue } err = ts.markAsDead(*txid) if err != nil { - log.Error(err) + log.Error(err.Error()) continue } } diff --git a/vendor/github.com/OpenBazaar/spvwallet/txstore_test.go b/vendor/github.com/OpenBazaar/spvwallet/txstore_test.go deleted file mode 100644 index 087ccf1b72..0000000000 --- a/vendor/github.com/OpenBazaar/spvwallet/txstore_test.go +++ /dev/null @@ -1,762 +0,0 @@ -package spvwallet - -import ( - "bytes" - "crypto/rand" - "encoding/hex" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil/hdkeychain" - "testing" - "time" -) - -var zeroHash chainhash.Hash - -func createTxStore() (*TxStore, error) { - mockDb := MockDatastore{ - &mockKeyStore{make(map[string]*keyStoreEntry)}, - &mockUtxoStore{make(map[string]*wallet.Utxo)}, - &mockStxoStore{make(map[string]*wallet.Stxo)}, - &mockTxnStore{make(map[string]*wallet.Txn)}, - &mockWatchedScriptsStore{make(map[string][]byte)}, - } - seed := make([]byte, 32) - rand.Read(seed) - key, _ := hdkeychain.NewMaster(seed, &chaincfg.TestNet3Params) - km, _ := NewKeyManager(mockDb.Keys(), &chaincfg.TestNet3Params, key) - return NewTxStore(&chaincfg.TestNet3Params, &mockDb, km) -} - -func TestNewTxStore(t *testing.T) { - ts, err := createTxStore() - if err != nil { - t.Error(err) - } - if len(ts.adrs) != LOOKAHEADWINDOW*2 { - t.Error("Failed to populate addresses for new TxStore") - } -} - -func TestTxStore_PopulateAdrs(t *testing.T) { - txStore, err := createTxStore() - if err != nil { - t.Error(err) - } - err = txStore.PopulateAdrs() - if err != nil { - t.Error(err) - } - if len(txStore.adrs) != LOOKAHEADWINDOW*2 { - t.Error("Failed to load addresses into memory") - } - b, err := hex.DecodeString("a91446cc55cee35873e0ebe0a90f66f942919b84d63e87") - if err != nil { - t.Error(err) - } - err = txStore.WatchedScripts().Put(b) - if err != nil { - t.Error(err) - } - err = txStore.PopulateAdrs() - if err != nil { - t.Error(err) - } - if len(txStore.watchedScripts) != 1 { - t.Error("Failed to load watched scripts into memory") - } - tx1Hex := "0100000001f0c1a0d39f0f1357fcead5897f1eed424d9835d30d2543f3d804138ba825939b010000006b483045022100ed5c193377e4fb7d8df067c18e4982f55f2443cd9b41548347f646448cc5ad9f02202ad6ad5041246a23868bc52675c4c1a4018e1cfd180dcd63897fb9040df14d85012102e2606d87535c7b15855a854c09225ba025230f8b79332a6d1d06b39cd711f821ffffffff0264f3cc03000000001976a9148f83a59ebdf80b8cc965a28da3a825c126a4cefb88ac204e0000000000001976a9140706d0505002aa3ef07a822b9c143b0047b07bdf88ac00000000" - tx1Bytes, err := hex.DecodeString(tx1Hex) - r := bytes.NewReader(tx1Bytes) - tx := wire.NewMsgTx(1) - tx.BtcDecode(r, 1, wire.WitnessEncoding) - - err = txStore.Txns().Put(tx1Bytes, tx.TxHash().String(), 100000, 0, time.Now(), false) - err = txStore.PopulateAdrs() - if err != nil { - t.Error(err) - } - if len(txStore.txids) != 1 { - t.Error("Failed to load txids into memory") - } - -} - -func TestTxStore_GimmeFilter(t *testing.T) { - txStore, err := createTxStore() - if err != nil { - t.Error(err) - } - b, err := hex.DecodeString("a91446cc55cee35873e0ebe0a90f66f942919b84d63e87") - if err != nil { - t.Error(err) - } - err = txStore.WatchedScripts().Put(b) - if err != nil { - t.Error(err) - } - op := wire.NewOutPoint(&zeroHash, 0) - err = txStore.Utxos().Put(wallet.Utxo{Op: *op}) - if err != nil { - t.Error(err) - } - op2 := wire.NewOutPoint(&zeroHash, 1) - err = txStore.Stxos().Put(wallet.Stxo{Utxo: wallet.Utxo{Op: *op2}}) - if err != nil { - t.Error(err) - } - err = txStore.PopulateAdrs() - if err != nil { - t.Error(err) - } - filter, err := txStore.GimmeFilter() - if err != nil { - t.Error(err) - } - for _, addr := range txStore.adrs { - if !filter.Matches(addr.ScriptAddress()) { - t.Error("Filter does not match address") - } - } - for _, script := range txStore.watchedScripts { - _, addrs, _, err := txscript.ExtractPkScriptAddrs(script, txStore.params) - if err != nil { - t.Error(err) - } - if !filter.Matches(addrs[0].ScriptAddress()) { - t.Error("Filter does not match watched script") - } - } - if !filter.MatchesOutPoint(op) { - t.Error("Failed to match utxo") - } - if !filter.MatchesOutPoint(op2) { - t.Error("Failed to match stxo") - } -} - -func TestTxStore_CheckDoubleSpends(t *testing.T) { - txStore, err := createTxStore() - if err != nil { - t.Error(err) - } - tx1Hex := "0100000001f0c1a0d39f0f1357fcead5897f1eed424d9835d30d2543f3d804138ba825939b010000006b483045022100ed5c193377e4fb7d8df067c18e4982f55f2443cd9b41548347f646448cc5ad9f02202ad6ad5041246a23868bc52675c4c1a4018e1cfd180dcd63897fb9040df14d85012102e2606d87535c7b15855a854c09225ba025230f8b79332a6d1d06b39cd711f821ffffffff0264f3cc03000000001976a9148f83a59ebdf80b8cc965a28da3a825c126a4cefb88ac204e0000000000001976a9140706d0505002aa3ef07a822b9c143b0047b07bdf88ac00000000" - tx1Bytes, err := hex.DecodeString(tx1Hex) - r := bytes.NewReader(tx1Bytes) - tx1 := wire.NewMsgTx(1) - tx1.BtcDecode(r, 1, wire.WitnessEncoding) - txStore.Txns().Put(tx1Bytes, tx1.TxHash().String(), 100, 400000, time.Now(), false) - doubles, err := txStore.CheckDoubleSpends(tx1) - if err != nil { - t.Error(err) - } - if len(doubles) > 0 { - t.Error("Incorrect returned double spend") - } - tx2 := tx1.Copy() - b, err := hex.DecodeString("a91446cc55cee35873e0ebe0a90f66f942919b84d63e87") - if err != nil { - t.Error(err) - } - tx2.TxOut[0].PkScript = b - - doubles, err = txStore.CheckDoubleSpends(tx2) - if err != nil { - t.Error(err) - } - - if len(doubles) < 1 { - t.Error("Failed to detect double spends") - } -} - -func TestTxStore_GetPendingInv(t *testing.T) { - txStore, err := createTxStore() - if err != nil { - t.Error(err) - } - h1, err := chainhash.NewHashFromStr("6f7a58ad92702601fcbaac0e039943a384f5274a205c16bb8bbab54f9ea2fbad") - op := wire.NewOutPoint(h1, 0) - err = txStore.Utxos().Put(wallet.Utxo{Op: *op}) - if err != nil { - t.Error(err) - } - h2, err := chainhash.NewHashFromStr("a0d4cbcd8d0694e1132400b5e114b31bc3e0d8a2ac26e054f78727c95485b528") - err = txStore.Stxos().Put(wallet.Stxo{SpendTxid: *h2}) - if err != nil { - t.Error(err) - } - inv, err := txStore.GetPendingInv() - if err != nil { - t.Error(err) - } - invMap := make(map[string]struct{}) - for _, i := range inv.InvList { - invMap[i.Hash.String()] = struct{}{} - if i.Type != wire.InvTypeTx { - t.Error("Got invalid inventory type") - } - } - if _, ok := invMap[h1.String()]; !ok { - t.Error("Failed to return correct inventory packet") - } - if _, ok := invMap[h2.String()]; !ok { - t.Error("Failed to return correct inventory packet") - } -} - -func TestTxStore_outpointsEqual(t *testing.T) { - h1, err := chainhash.NewHashFromStr("6f7a58ad92702601fcbaac0e039943a384f5274a205c16bb8bbab54f9ea2fbad") - if err != nil { - t.Error(err) - } - op := wire.NewOutPoint(h1, 0) - h2, err := chainhash.NewHashFromStr("a0d4cbcd8d0694e1132400b5e114b31bc3e0d8a2ac26e054f78727c95485b528") - op2 := wire.NewOutPoint(h2, 0) - if err != nil { - t.Error(err) - } - if !outPointsEqual(*op, *op) { - t.Error("Failed to detect equal outpoints") - } - if outPointsEqual(*op, *op2) { - t.Error("Incorrectly returned equal outpoints") - } -} - -func TestTxStore_markAsDead(t *testing.T) { - // Test marking single UTXO as dead - txStore, err := createTxStore() - if err != nil { - t.Error(err) - } - tx1Hex := "0100000001f0c1a0d39f0f1357fcead5897f1eed424d9835d30d2543f3d804138ba825939b010000006b483045022100ed5c193377e4fb7d8df067c18e4982f55f2443cd9b41548347f646448cc5ad9f02202ad6ad5041246a23868bc52675c4c1a4018e1cfd180dcd63897fb9040df14d85012102e2606d87535c7b15855a854c09225ba025230f8b79332a6d1d06b39cd711f821ffffffff0264f3cc03000000001976a9148f83a59ebdf80b8cc965a28da3a825c126a4cefb88ac204e0000000000001976a9140706d0505002aa3ef07a822b9c143b0047b07bdf88ac00000000" - tx1Bytes, err := hex.DecodeString(tx1Hex) - r := bytes.NewReader(tx1Bytes) - tx1 := wire.NewMsgTx(1) - tx1.BtcDecode(r, 1, wire.WitnessEncoding) - txStore.Txns().Put(tx1Bytes, tx1.TxHash().String(), 100, 0, time.Now(), false) - - h1 := tx1.TxHash() - op := wire.NewOutPoint(&h1, 0) - err = txStore.Utxos().Put(wallet.Utxo{Op: *op}) - if err != nil { - t.Error(err) - } - - err = txStore.markAsDead(tx1.TxHash()) - if err != nil { - t.Error(err) - } - checkTx, err := txStore.Txns().Get(tx1.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - - utxos, err := txStore.Utxos().GetAll() - if err != nil { - t.Error(err) - } - if len(utxos) > 0 { - t.Error("Failed to delete dead utxo") - } - - // Test marking STXO as dead - txStore, err = createTxStore() - if err != nil { - t.Error(err) - } - - txStore.Txns().Put(tx1Bytes, tx1.TxHash().String(), 100, 400000, time.Now(), false) - - tx2Hex := "01000000018dce6a1748a0b35475903ae654bb0c000fa004a8a83f16a18464de473da42b1c010000006a473044022001c7c890110c94a22bbb004b75364b03b157cb0f71a97c419a4ed80f0155649b0220257f54fbda579e0c4063f980ddd2ea9bfa591c42e759cc0cd78370bd1d24afba01210245a1619fc1feb837ed54a9dfa71d7abea445ef193fd1f9fa0d5b4141980bff11ffffffff0280a4bf070000000017a9143cb6156a7f8b5c8e72b764e00fbdfe31e77fe86187084cd600010000001976a914a4cf57fd8d825995d5fd5104675ccedd39cf924988ac00000000" - tx2Bytes, err := hex.DecodeString(tx2Hex) - r = bytes.NewReader(tx2Bytes) - tx2 := wire.NewMsgTx(1) - tx2.BtcDecode(r, 1, wire.WitnessEncoding) - txStore.Txns().Put(tx2Bytes, tx2.TxHash().String(), 100, 0, time.Now(), false) - - op = wire.NewOutPoint(&h1, 0) - st := wallet.Stxo{ - Utxo: wallet.Utxo{Op: *op}, - SpendHeight: 0, - SpendTxid: tx2.TxHash(), - } - err = txStore.Stxos().Put(st) - - err = txStore.markAsDead(tx2.TxHash()) - if err != nil { - t.Error(err) - } - - checkTx, err = txStore.Txns().Get(tx2.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - - utxos, err = txStore.Utxos().GetAll() - if err != nil { - t.Error(err) - } - if len(utxos) > 1 { - t.Error("Failed to move stxo back into utxo db") - } - - stxos, err := txStore.Stxos().GetAll() - if err != nil { - t.Error(err) - } - if len(stxos) > 0 { - t.Error("Failed to delete dead stxo") - } - - // Test marking STXO dependency as dead - txStore, err = createTxStore() - if err != nil { - t.Error(err) - } - - txStore.Txns().Put(tx1Bytes, tx1.TxHash().String(), 100, 0, time.Now(), false) - txStore.Txns().Put(tx2Bytes, tx2.TxHash().String(), 100, 0, time.Now(), false) - - op = wire.NewOutPoint(&h1, 0) - st = wallet.Stxo{ - Utxo: wallet.Utxo{Op: *op}, - SpendHeight: 0, - SpendTxid: tx2.TxHash(), - } - err = txStore.Stxos().Put(st) - - err = txStore.markAsDead(tx1.TxHash()) - if err != nil { - t.Error(err) - } - - checkTx, err = txStore.Txns().Get(tx1.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - - checkTx, err = txStore.Txns().Get(tx2.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - - utxos, err = txStore.Utxos().GetAll() - if err != nil { - t.Error(err) - } - if len(utxos) > 0 { - t.Error("Failed to move stxo back into utxo db") - } - - stxos, err = txStore.Stxos().GetAll() - if err != nil { - t.Error(err) - } - if len(stxos) > 0 { - t.Error("Failed to delete dead stxo") - } - - // Test marking STXO and UXTO change as dead - txStore, err = createTxStore() - if err != nil { - t.Error(err) - } - - txStore.Txns().Put(tx1Bytes, tx1.TxHash().String(), 100, 0, time.Now(), false) - txStore.Txns().Put(tx2Bytes, tx2.TxHash().String(), 100, 0, time.Now(), false) - - op = wire.NewOutPoint(&h1, 0) - st = wallet.Stxo{ - Utxo: wallet.Utxo{Op: *op}, - SpendHeight: 0, - SpendTxid: tx2.TxHash(), - } - err = txStore.Stxos().Put(st) - - h2 := tx2.TxHash() - op2 := wire.NewOutPoint(&h2, 0) - err = txStore.Utxos().Put(wallet.Utxo{Op: *op2}) - if err != nil { - t.Error(err) - } - - tx3Hex := "0100000001dc8910ef79c4bc690cdf3e335c0f88757ba176e00057cb63ccbae6a13205d4cf010000006a47304402203c5203c53b463ac459c93954513ffb32c7056c5f2a6c825362afba21f5d1c88202207a121f13fa0f2cfe1392d2b2a4139485cc4251058a6cccc1e3c25970104df5cd012102530f811d7da235aad895cba33e2d42d1092140d1c6e6b4d965db861f5988d64affffffff02fc2f0600000000001976a9145d9e4978b7998369cda5ce3ae79c6db25957e91d88ac29dc6a16000000001976a9145cd1285c75daa5adc4c5b979b0f96c01dd08dfec88ac00000000" - tx3Bytes, err := hex.DecodeString(tx3Hex) - r = bytes.NewReader(tx3Bytes) - tx3 := wire.NewMsgTx(1) - tx3.BtcDecode(r, 1, wire.WitnessEncoding) - txStore.Txns().Put(tx3Bytes, tx3.TxHash().String(), 100, 0, time.Now(), false) - - op = wire.NewOutPoint(&h2, 0) - st = wallet.Stxo{ - Utxo: wallet.Utxo{Op: *op}, - SpendHeight: 0, - SpendTxid: tx3.TxHash(), - } - err = txStore.Stxos().Put(st) - - err = txStore.markAsDead(tx1.TxHash()) - if err != nil { - t.Error(err) - } - - checkTx, err = txStore.Txns().Get(tx1.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - - checkTx, err = txStore.Txns().Get(tx2.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - - checkTx, err = txStore.Txns().Get(tx3.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - - utxos, err = txStore.Utxos().GetAll() - if err != nil { - t.Error(err) - } - if len(utxos) > 0 { - t.Error("Failed to move stxo back into utxo db") - } - - stxos, err = txStore.Stxos().GetAll() - if err != nil { - t.Error(err) - } - if len(stxos) > 0 { - t.Error("Failed to delete dead stxo") - } -} - -func TestTxStore_processReorg(t *testing.T) { - // Receive utxo1 (tx1) - // Spend utxo1 and create change utxo2 (tx2) - // Spend utxo2 (tx3) - // tx2 and tx3 get reorged away - // Should only have utxo1 left and two dead txs - - txStore, err := createTxStore() - if err != nil { - t.Error(err) - } - - tx1Hex := "0100000001f0c1a0d39f0f1357fcead5897f1eed424d9835d30d2543f3d804138ba825939b010000006b483045022100ed5c193377e4fb7d8df067c18e4982f55f2443cd9b41548347f646448cc5ad9f02202ad6ad5041246a23868bc52675c4c1a4018e1cfd180dcd63897fb9040df14d85012102e2606d87535c7b15855a854c09225ba025230f8b79332a6d1d06b39cd711f821ffffffff0264f3cc03000000001976a9148f83a59ebdf80b8cc965a28da3a825c126a4cefb88ac204e0000000000001976a9140706d0505002aa3ef07a822b9c143b0047b07bdf88ac00000000" - tx1Bytes, err := hex.DecodeString(tx1Hex) - r := bytes.NewReader(tx1Bytes) - tx1 := wire.NewMsgTx(1) - tx1.BtcDecode(r, 1, wire.WitnessEncoding) - txStore.Txns().Put(tx1Bytes, tx1.TxHash().String(), 100, 400000, time.Now(), false) - - tx2Hex := "01000000018dce6a1748a0b35475903ae654bb0c000fa004a8a83f16a18464de473da42b1c010000006a473044022001c7c890110c94a22bbb004b75364b03b157cb0f71a97c419a4ed80f0155649b0220257f54fbda579e0c4063f980ddd2ea9bfa591c42e759cc0cd78370bd1d24afba01210245a1619fc1feb837ed54a9dfa71d7abea445ef193fd1f9fa0d5b4141980bff11ffffffff0280a4bf070000000017a9143cb6156a7f8b5c8e72b764e00fbdfe31e77fe86187084cd600010000001976a914a4cf57fd8d825995d5fd5104675ccedd39cf924988ac00000000" - tx2Bytes, err := hex.DecodeString(tx2Hex) - r = bytes.NewReader(tx2Bytes) - tx2 := wire.NewMsgTx(1) - tx2.BtcDecode(r, 1, wire.WitnessEncoding) - txStore.Txns().Put(tx2Bytes, tx2.TxHash().String(), 100, 400001, time.Now(), false) - - tx3Hex := "0100000001dc8910ef79c4bc690cdf3e335c0f88757ba176e00057cb63ccbae6a13205d4cf010000006a47304402203c5203c53b463ac459c93954513ffb32c7056c5f2a6c825362afba21f5d1c88202207a121f13fa0f2cfe1392d2b2a4139485cc4251058a6cccc1e3c25970104df5cd012102530f811d7da235aad895cba33e2d42d1092140d1c6e6b4d965db861f5988d64affffffff02fc2f0600000000001976a9145d9e4978b7998369cda5ce3ae79c6db25957e91d88ac29dc6a16000000001976a9145cd1285c75daa5adc4c5b979b0f96c01dd08dfec88ac00000000" - tx3Bytes, err := hex.DecodeString(tx3Hex) - r = bytes.NewReader(tx3Bytes) - tx3 := wire.NewMsgTx(1) - tx3.BtcDecode(r, 1, wire.WitnessEncoding) - txStore.Txns().Put(tx3Bytes, tx3.TxHash().String(), 100, 400002, time.Now(), false) - - h1 := tx1.TxHash() - op := wire.NewOutPoint(&h1, 0) - st := wallet.Stxo{ - Utxo: wallet.Utxo{Op: *op}, - SpendHeight: 0, - SpendTxid: tx2.TxHash(), - } - err = txStore.Stxos().Put(st) - - h2 := tx2.TxHash() - op2 := wire.NewOutPoint(&h2, 0) - txStore.Utxos().Put(wallet.Utxo{Op: *op2}) - - op = wire.NewOutPoint(&h2, 0) - st = wallet.Stxo{ - Utxo: wallet.Utxo{Op: *op}, - SpendHeight: 0, - SpendTxid: tx3.TxHash(), - } - err = txStore.Stxos().Put(st) - - err = txStore.processReorg(400000) - if err != nil { - t.Error(err) - } - - utxos, err := txStore.Utxos().GetAll() - if err != nil { - t.Error(err) - } - if len(utxos) != 1 { - t.Error("Failed to move stxo back into utxo db") - } - - stxos, err := txStore.Stxos().GetAll() - if err != nil { - t.Error(err) - } - if len(stxos) > 0 { - t.Error("Failed to delete dead stxo") - } - - checkTx, err := txStore.Txns().Get(tx1.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height != 400000 { - t.Error("Failed to mark tx as dead") - } - - checkTx, err = txStore.Txns().Get(tx2.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - - checkTx, err = txStore.Txns().Get(tx3.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - -} - -func TestTxStore_Ingest(t *testing.T) { - txStore, err := createTxStore() - if err != nil { - t.Error(err) - } - - tx1Hex := "0100000001f0c1a0d39f0f1357fcead5897f1eed424d9835d30d2543f3d804138ba825939b010000006b483045022100ed5c193377e4fb7d8df067c18e4982f55f2443cd9b41548347f646448cc5ad9f02202ad6ad5041246a23868bc52675c4c1a4018e1cfd180dcd63897fb9040df14d85012102e2606d87535c7b15855a854c09225ba025230f8b79332a6d1d06b39cd711f821ffffffff0264f3cc03000000001976a9148f83a59ebdf80b8cc965a28da3a825c126a4cefb88ac204e0000000000001976a9140706d0505002aa3ef07a822b9c143b0047b07bdf88ac00000000" - tx1Bytes, err := hex.DecodeString(tx1Hex) - r := bytes.NewReader(tx1Bytes) - tx1 := wire.NewMsgTx(1) - tx1.BtcDecode(r, 1, wire.WitnessEncoding) - - // Ingest no hits - hits, err := txStore.Ingest(tx1, 0, time.Now()) - if err != nil { - t.Error(err) - } - if hits != 0 { - t.Error("Failed to correctly ingest tx") - } - - // Ingest output hit - key, err := txStore.keyManager.GetCurrentKey(wallet.EXTERNAL) - if err != nil { - t.Error(err) - } - addr, err := key.Address(&chaincfg.TestNet3Params) - if err != nil { - t.Error(err) - } - script, err := txscript.PayToAddrScript(addr) - if err != nil { - t.Error(err) - } - out := wire.NewTxOut(100000, script) - tx1.AddTxOut(out) - - hits, err = txStore.Ingest(tx1, 0, time.Now()) - if err != nil { - t.Error(err) - } - if hits < 1 { - t.Error("Failed to correctly ingest tx") - } - txns, err := txStore.Txns().GetAll(true) - if err != nil { - t.Error(err) - } - if len(txns) != 1 { - t.Error("Failed to record tx in database") - } - - // Ingest duplicate - hits, err = txStore.Ingest(tx1, 0, time.Now()) - if err != nil { - t.Error(err) - } - if hits != 1 { - t.Error("Failed to correctly ingest tx") - } - - // Ingest double spend with height zero - tx2Hex := "01000000017a00467fc0a1ef040bbc544a66a5d4c7badd35efe18c343cf403f63937dfd9b1000000006b483045022100a08ea162b0591d3438bdab3ef8a80c6a7ce62dd593e01b96165ea7a6d72cb5ca02202e9db6dfd216a40cf0c0a466218decaf0f5c52c00f389be3e96a32d35559e150012102257118cc606883162804ce7ee371b97a9f58ee759ed819120b9c640e0d3ca8e4ffffffff01e4ab7c000000000017a914ac66e5ca929ded3d146c77ae988886050b1a8e528700000000" - tx2Bytes, err := hex.DecodeString(tx2Hex) - r = bytes.NewReader(tx2Bytes) - tx2 := wire.NewMsgTx(1) - tx2.BtcDecode(r, 1, wire.WitnessEncoding) - tx2.AddTxIn(tx1.TxIn[0]) - hits, err = txStore.Ingest(tx2, 0, time.Now()) - if err != nil { - t.Error(err) - } - if hits != 0 { - t.Error("Failed to correctly ingest tx") - } - - // Ingest double spend that supersedes a previous committed tx - hits, err = txStore.Ingest(tx2, 50, time.Now()) - if err != nil { - t.Error(err) - } - checkTx, err := txStore.Txns().Get(tx1.TxHash()) - if err != nil { - t.Error(err) - } - if checkTx.Height >= 0 { - t.Error("Failed to mark tx as dead") - } - utxos, err := txStore.Utxos().GetAll() - if err != nil { - t.Error(err) - } - if len(utxos) > 0 { - t.Error("Failed to move stxo back into utxo db") - } - - // Ingest watched script hit - tx3Hex := "010000000140f831600eac0c1741c89f61134cb65142a4d95e0d53deb313872b2c5c675a82010000006a47304402203e002a46d94e917c99ecbea7dc5744f65d9f5c78c97802c85aa424f5521f024002206c315f5ae183bb4f007190f1f9c61dbfa3c6127ac45a381956f8de3894196afd012102fe6d4e37bb5956b51b62e87e3163530f20a33a8aba13ff973e84d7061b53ca5effffffff02bc733400000000001976a914fcd6edaae418f8ba77112965d7a1e997a660893a88ac41fe1c14010000001976a9145c069b3af330230523d378824e366ab9a4a1731188ac00000000" - tx3Bytes, err := hex.DecodeString(tx3Hex) - r = bytes.NewReader(tx3Bytes) - tx3 := wire.NewMsgTx(1) - tx3.BtcDecode(r, 1, wire.WitnessEncoding) - script, err = hex.DecodeString("a914ac66e5ca929ded3d146c77ae988886050b1a8e5287") - if err != nil { - t.Error(err) - } - txStore.WatchedScripts().Put(script) - txStore.PopulateAdrs() - tx3.AddTxOut(wire.NewTxOut(400000, script)) - - _, err = txStore.Ingest(tx3, 0, time.Now()) - if err != nil { - t.Error(err) - } - checkTx, err = txStore.Txns().Get(tx3.TxHash()) - if err != nil { - t.Error(err) - } - if !checkTx.WatchOnly { - t.Error("Incorrectly set watch only transaction") - } - - // Test input match - tx4Hex := "0100000001473cc2e9e542f64361d9faba24316a8d4de19a00c0c4763d944dac6d00f5f641000000006b483045022100d3cf0dcec644d7964e350c3d5e25bf63be6e04b1cb8004b84cd880836fb668cf02207919d75ee5ba66a49456430f90eebda05f6284ec8831ff9f82f101893e77f7a7012103238c6886300c26ac580f37e4df1e710e74854bd9b183dfce48c5c1ab204d99b1feffffff02de6b0300000000001976a9147acf80f880c32c742b3331dbcb1a6ed51d76fc6188ace50f0f01000000001976a914827b6495bfac61449ab852d94e0abad0eb90bca388acf22e1100" - tx4Bytes, err := hex.DecodeString(tx4Hex) - r = bytes.NewReader(tx4Bytes) - tx4 := wire.NewMsgTx(1) - tx4.BtcDecode(r, 1, wire.WitnessEncoding) - txStore.Ingest(tx1, 0, time.Now()) - - h := tx1.TxHash() - op := wire.NewOutPoint(&h, 2) - tx4.AddTxIn(wire.NewTxIn(op, []byte{}, [][]byte{})) - - hits, err = txStore.Ingest(tx4, 0, time.Now()) - if err != nil { - t.Error(err) - } - if hits < 1 { - t.Error("Failed to ingest matching input") - } - - utxos, err = txStore.Utxos().GetAll() - if err != nil { - t.Error(err) - } - for _, u := range utxos { - if outPointsEqual(*op, u.Op) { - t.Error("Failed to move utxo to stxo") - } - } - - // Spend the watch only utxo - tx5Hex := "01000000010bfec1c7b63fb4d9165a4ea763858ea651e1d71d2bd75f03dd4dadda2198cd8c01000000da00473044022022360ce1b5619dd13e2d0bf81f0913faf395779c170d399a3e8af9ac89f7bb8202203ef78b426f90bc05018593730a0a842b621556ddc20d38af5375cd35ce84387e01483045022100b14db9ef3357c07b2b09ce10d95b7da0d64644e2178d1aa01fc679ddf3d1ae6c0220109d732f4609cb37b06fa42888931080789ee37a314a370cef01f17aaac0851b0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9142384d7645fc56018b44e98afd4cb689e5d5e0b35877d12297a0000000017a9148ce5408cfeaddb7ccb2545ded41ef478109454848700000000" - tx5Bytes, err := hex.DecodeString(tx5Hex) - r = bytes.NewReader(tx5Bytes) - tx5 := wire.NewMsgTx(1) - tx5.BtcDecode(r, 1, wire.WitnessEncoding) - - h3 := tx3.TxHash() - op3 := wire.NewOutPoint(&h3, 2) - tx5.AddTxIn(wire.NewTxIn(op3, []byte{}, [][]byte{})) - - hits, err = txStore.Ingest(tx5, 0, time.Now()) - if err != nil { - t.Error(err) - } - - utxos, err = txStore.Utxos().GetAll() - if err != nil { - t.Error(err) - } - for _, u := range utxos { - if outPointsEqual(*op3, u.Op) { - t.Error("Failed to move utxo to stxo") - } - } - - // Update stxo height - _, err = txStore.Ingest(tx5, 1000, time.Now()) - if err != nil { - t.Error(err) - } - stxos, err := txStore.Stxos().GetAll() - if err != nil { - t.Error(err) - } - found := false - for _, s := range stxos { - if outPointsEqual(*op3, s.Utxo.Op) { - found = true - if s.SpendHeight != 1000 { - t.Error("Failed to set stxo height correctly") - } - break - } - } - if !found { - t.Error("Utxo failed to move to the stxo table") - } -} diff --git a/vendor/github.com/OpenBazaar/spvwallet/wallet.go b/vendor/github.com/OpenBazaar/spvwallet/wallet.go index 23fb65c28e..25f19e1fae 100644 --- a/vendor/github.com/OpenBazaar/spvwallet/wallet.go +++ b/vendor/github.com/OpenBazaar/spvwallet/wallet.go @@ -1,7 +1,13 @@ package spvwallet import ( + "bytes" "errors" + "io" + "math/big" + "sync" + "time" + "github.com/OpenBazaar/spvwallet/exchangerates" "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/btcec" @@ -9,14 +15,12 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" btc "github.com/btcsuite/btcutil" hd "github.com/btcsuite/btcutil/hdkeychain" "github.com/btcsuite/btcwallet/wallet/txrules" "github.com/op/go-logging" b39 "github.com/tyler-smith/go-bip39" - "io" - "sync" - "time" ) type SPVWallet struct { @@ -50,10 +54,19 @@ type SPVWallet struct { exchangeRates wallet.ExchangeRates } +var _ = wallet.Wallet(&SPVWallet{}) + var log = logging.MustGetLogger("bitcoin") const WALLET_VERSION = "0.1.0" +var ( + BitcoinCurrencyDefinition = wallet.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + } +) + func NewSPVWallet(config *Config) (*SPVWallet, error) { log.SetBackend(logging.AddModuleLevel(config.Logger)) @@ -92,6 +105,7 @@ func NewSPVWallet(config *Config) (*SPVWallet, error) { config.HighFee, config.MediumFee, config.LowFee, + config.SuperLowFee, config.FeeAPI.String(), config.Proxy, ), @@ -183,8 +197,15 @@ func (w *SPVWallet) CurrencyCode() string { } } -func (w *SPVWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btc.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *SPVWallet) IsDust(amount big.Int) bool { + return isTxSizeDust(amount, 25) +} + +func isTxSizeDust(amount big.Int, size int) bool { + if !amount.IsInt64() || amount.Cmp(big.NewInt(0)) <= 0 { + return false + } + return txrules.IsDustAmount(btc.Amount(amount.Int64()), size, txrules.DefaultRelayFeePerKb) } func (w *SPVWallet) MasterPrivateKey() *hd.ExtendedKey { @@ -302,23 +323,26 @@ func (w *SPVWallet) ListKeys() []btcec.PrivateKey { return list } -func (w *SPVWallet) Balance() (confirmed, unconfirmed int64) { +func (w *SPVWallet) Balance() (wallet.CurrencyValue, wallet.CurrencyValue) { utxos, _ := w.txstore.Utxos().GetAll() stxos, _ := w.txstore.Stxos().GetAll() + var confirmed, unconfirmed int64 for _, utxo := range utxos { if !utxo.WatchOnly { + val0, _ := new(big.Int).SetString(utxo.Value, 10) if utxo.AtHeight > 0 { - confirmed += utxo.Value + confirmed += val0.Int64() } else { if w.checkIfStxoIsConfirmed(utxo, stxos) { - confirmed += utxo.Value + confirmed += val0.Int64() } else { - unconfirmed += utxo.Value + unconfirmed += val0.Int64() } } } } - return confirmed, unconfirmed + return wallet.CurrencyValue{Value: *big.NewInt(confirmed), Currency: BitcoinCurrencyDefinition}, + wallet.CurrencyValue{Value: *big.NewInt(unconfirmed), Currency: BitcoinCurrencyDefinition} } func (w *SPVWallet) Transactions() ([]wallet.Txn, error) { @@ -357,6 +381,32 @@ func (w *SPVWallet) Transactions() ([]wallet.Txn, error) { func (w *SPVWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) { txn, err := w.txstore.Txns().Get(txid) + if err == nil { + tx := wire.NewMsgTx(1) + rbuf := bytes.NewReader(txn.Bytes) + err := tx.BtcDecode(rbuf, wire.ProtocolVersion, wire.WitnessEncoding) + if err != nil { + return txn, err + } + outs := []wallet.TransactionOutput{} + for i, out := range tx.TxOut { + var addr btc.Address + _, addrs, _, err := txscript.ExtractPkScriptAddrs(out.PkScript, w.params) + if err != nil { + log.Warningf("error extracting address from txn pkscript: %v\n", err) + } + if len(addrs) != 0 { + addr = addrs[0] + } + tout := wallet.TransactionOutput{ + Address: addr, + Value: *big.NewInt(out.Value), + Index: uint32(i), + } + outs = append(outs, tout) + } + txn.Outputs = outs + } return txn, err } @@ -410,15 +460,24 @@ func (w *SPVWallet) ChainTip() (uint32, chainhash.Hash) { return sh.height, sh.header.BlockHash() } -func (w *SPVWallet) AddWatchedAddress(addr btc.Address) error { - script, err := w.AddressToScript(addr) - if err != nil { - return err +func (w *SPVWallet) AddWatchedAddresses(addrs ...btc.Address) error { + + var err error + var watchedScripts [][]byte + + for _, addr := range addrs { + script, err := w.AddressToScript(addr) + if err != nil { + return err + } + watchedScripts = append(watchedScripts, script) } - err = w.txstore.WatchedScripts().Put(script) + + err = w.txstore.WatchedScripts().PutAll(watchedScripts) w.txstore.PopulateAdrs() w.wireService.MsgChan() <- updateFiltersMsg{} + return err } @@ -445,3 +504,10 @@ func (w *SPVWallet) ReSyncBlockchain(fromDate time.Time) { func (w *SPVWallet) ExchangeRates() wallet.ExchangeRates { return w.exchangeRates } + +// AssociateTransactionWithOrder used for ORDER_PAYMENT message +func (w *SPVWallet) AssociateTransactionWithOrder(cb wallet.TransactionCallback) { + for _, l := range w.txstore.listeners { + go l(cb) + } +} diff --git a/vendor/github.com/OpenBazaar/wallet-interface/datastore.go b/vendor/github.com/OpenBazaar/wallet-interface/datastore.go index 1853506d44..4d91b9e0c6 100644 --- a/vendor/github.com/OpenBazaar/wallet-interface/datastore.go +++ b/vendor/github.com/OpenBazaar/wallet-interface/datastore.go @@ -2,6 +2,8 @@ package wallet import ( "bytes" + "encoding/json" + "math/big" "time" "github.com/btcsuite/btcd/btcec" @@ -119,7 +121,7 @@ type Stxos interface { type Txns interface { // Put a new transaction to the database - Put(raw []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error + Put(raw []byte, txid, value string, height int, timestamp time.Time, watchOnly bool) error // Fetch a tx and it's metadata given a hash Get(txid chainhash.Hash) (Txn, error) @@ -171,6 +173,10 @@ type Keys interface { } type WatchedScripts interface { + + // Add scripts to watch + PutAll(scriptPubkeys [][]byte) error + // Add a script to watch Put(scriptPubKey []byte) error @@ -189,7 +195,7 @@ type Utxo struct { AtHeight int32 // The higher the better - Value int64 + Value string // Output script ScriptPubkey []byte @@ -221,7 +227,7 @@ func (utxo *Utxo) IsEqual(alt *Utxo) bool { return false } - if bytes.Compare(utxo.ScriptPubkey, alt.ScriptPubkey) != 0 { + if !bytes.Equal(utxo.ScriptPubkey, alt.ScriptPubkey) { return false } @@ -264,7 +270,7 @@ type Txn struct { Txid string // The value relevant to the wallet - Value int64 + Value string // The height at which it was mined Height int32 @@ -311,3 +317,13 @@ type KeyPath struct { Purpose KeyPurpose Index int } + +type CurrencyDefinition struct { + Code string + Divisibility int64 +} +type CurrencyValue struct { + Currency CurrencyDefinition + Value big.Int + ValueSerialization json.Number +} diff --git a/vendor/github.com/OpenBazaar/wallet-interface/exchange_rates.go b/vendor/github.com/OpenBazaar/wallet-interface/exchange_rates.go index 20a0295186..7c02051bd5 100644 --- a/vendor/github.com/OpenBazaar/wallet-interface/exchange_rates.go +++ b/vendor/github.com/OpenBazaar/wallet-interface/exchange_rates.go @@ -15,5 +15,5 @@ type ExchangeRates interface { /* Return the number of currency units per coin. For example, in bitcoin this is 100m satoshi per BTC. This is used when converting from fiat to the smaller currency unit. */ - UnitsPerCoin() int + UnitsPerCoin() int64 } diff --git a/vendor/github.com/OpenBazaar/wallet-interface/wallet.go b/vendor/github.com/OpenBazaar/wallet-interface/wallet.go index e411b1e942..a60985c715 100644 --- a/vendor/github.com/OpenBazaar/wallet-interface/wallet.go +++ b/vendor/github.com/OpenBazaar/wallet-interface/wallet.go @@ -2,6 +2,7 @@ package wallet import ( "errors" + "math/big" "time" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -50,6 +51,11 @@ type Wallet interface { walletCanBumpFee } +var ( + // ErrInsufficientFunds is returned when the wallet is unable to send the amount specified due to the balance being too low + ErrInsufficientFunds = errors.New("ERROR_INSUFFICIENT_FUNDS") +) + // WalletMustManuallyAssociateTransactionToOrder MUST be checked for by openbazaar-go to ensure // that wallets which require manual association between transactions and orders are properly // associated. If the interface is supported, AssociateTransactionToOrder must be called as @@ -80,11 +86,11 @@ type walletMustManager interface { // fiat exchange rate data for this coin. ExchangeRates() ExchangeRates - // AddWatchedAddress adds an address to the wallet to get notifications back when coins + // AddWatchedAddresses adds an address to the wallet to get notifications back when coins // are received or spent from it. These watch only addresses should be persisted between // sessions and upon each startup the wallet should be made to listen for transactions // involving them. - AddWatchedAddress(addr btc.Address) error + AddWatchedAddresses(addrs ...btc.Address) error // AddTransactionListener is how openbazaar-go registers to receive a callback whenever // a transaction is received that is relevant to this wallet or any of its watch only @@ -97,7 +103,7 @@ type walletMustManager interface { // participants. If the amount that is supposed to be sent to a given party is below // the dust threshold, openbazaar-go will not pay that party to avoid building a transaction // that never confirms. - IsDust(amount int64) bool + IsDust(amount big.Int) bool // CurrentAddress returns an address suitable for receiving payments. `purpose` specifies // whether the address should be internal or external. External addresses are typically @@ -128,7 +134,7 @@ type walletMustManager interface { // The reason for this that if the spend never confirms, no coins will be lost to the wallet. // // The returned balances should be in the coin's base unit (for example: satoshis) - Balance() (confirmed, unconfirmed int64) + Balance() (confirmed, unconfirmed CurrencyValue) // Transactions returns a list of transactions for this wallet. Transactions() ([]Txn, error) @@ -202,7 +208,7 @@ type walletMustKeysmither interface { // do so. The caller will then take the signature and share it with the other parties. Once all parties have shared // their signatures, the person who wants to release the funds collects them and uses them as an input to the // `Multisign` method. - CreateMultisigSignature(ins []TransactionInput, outs []TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]Signature, error) + CreateMultisigSignature(ins []TransactionInput, outs []TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]Signature, error) // Multisign collects all of the signatures generated by the `CreateMultisigSignature` function and builds a final // transaction that can then be broadcast to the blockchain. The []byte return is the raw transaction. It should be @@ -211,7 +217,7 @@ type walletMustKeysmither interface { // // This method is called by openbazaar-go by whichever party to the escrow is trying to release the funds only after // all needed parties have signed using `CreateMultisigSignature` and have shared their signatures with each other. - Multisign(ins []TransactionInput, outs []TransactionOutput, sigs1 []Signature, sigs2 []Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) + Multisign(ins []TransactionInput, outs []TransactionOutput, sigs1 []Signature, sigs2 []Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) } type walletMustBanker interface { @@ -219,7 +225,7 @@ type walletMustBanker interface { // are three fee levels ― priority, normal, and economic. // //The returned value should be in the coin's base unit (for example: satoshis). - GetFeePerByte(feeLevel FeeLevel) uint64 + GetFeePerByte(feeLevel FeeLevel) big.Int // Spend transfers the given amount of coins (in the coin's base unit. For example: in // satoshis) to the given address using the provided fee level. Openbazaar-go calls @@ -232,12 +238,12 @@ type walletMustBanker interface { // be swept to the provided payment address. For most coins this entails subtracting the // transaction fee from the total amount being sent rather than adding it on as is normally // the case when spendAll is false. - Spend(amount int64, addr btc.Address, feeLevel FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) + Spend(amount big.Int, addr btc.Address, feeLevel FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) // EstimateFee should return the estimate fee that will be required to make a transaction // spending from the given inputs to the given outputs. FeePerByte is denominated in // the coin's base unit (for example: satoshis). - EstimateFee(ins []TransactionInput, outs []TransactionOutput, feePerByte uint64) uint64 + EstimateFee(ins []TransactionInput, outs []TransactionOutput, feePerByte big.Int) big.Int // EstimateSpendFee should return the anticipated fee to transfer a given amount of coins // out of the wallet at the provided fee level. Typically this involves building a @@ -246,7 +252,7 @@ type walletMustBanker interface { // that changes the estimated fee as it's only intended to be an estimate. // // All amounts should be in the coin's base unit (for example: satoshis). - EstimateSpendFee(amount int64, feeLevel FeeLevel) (uint64, error) + EstimateSpendFee(amount big.Int, feeLevel FeeLevel) (big.Int, error) // SweepAddress should sweep all the funds from the provided inputs into the provided `address` using the given // `key`. If `address` is nil, the funds should be swept into an internal address own by this wallet. @@ -277,10 +283,11 @@ type walletCanBumpFee interface { type FeeLevel int const ( - PRIOIRTY FeeLevel = 0 - NORMAL = 1 - ECONOMIC = 2 - FEE_BUMP = 3 + PRIORITY FeeLevel = 0 + NORMAL = 1 + ECONOMIC = 2 + FEE_BUMP = 3 + SUPER_ECONOMIC = 4 ) // The end leaves on the HD wallet have only two possible values. External keys are those given @@ -302,14 +309,14 @@ type TransactionCallback struct { Inputs []TransactionInput Height int32 Timestamp time.Time - Value int64 + Value big.Int WatchOnly bool BlockTime time.Time } type TransactionOutput struct { Address btc.Address - Value int64 + Value big.Int Index uint32 OrderID string } @@ -318,7 +325,7 @@ type TransactionInput struct { OutpointHash []byte OutpointIndex uint32 LinkedAddress btc.Address - Value int64 + Value big.Int OrderID string } @@ -329,7 +336,7 @@ type TransactionInput struct { type TransactionRecord struct { Txid string Index uint32 - Value int64 + Value big.Int Address string Spent bool Timestamp time.Time @@ -344,6 +351,5 @@ type Signature struct { // Errors var ( - ErrorInsuffientFunds error = errors.New("Insuffient funds") - ErrorDustAmount error = errors.New("Amount is below network dust treshold") + ErrorDustAmount error = errors.New("amount is below network dust treshold") ) diff --git a/vendor/github.com/btcsuite/btcutil/certgen.go b/vendor/github.com/btcsuite/btcutil/certgen.go index 26d16293a0..bbc45a412f 100644 --- a/vendor/github.com/btcsuite/btcutil/certgen.go +++ b/vendor/github.com/btcsuite/btcutil/certgen.go @@ -110,7 +110,7 @@ func NewTLSCertPair(organization string, validUntil time.Time, extraHosts []stri KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - IsCA: true, // so can sign self. + IsCA: true, // so can sign self. BasicConstraintsValid: true, DNSNames: dnsNames, diff --git a/vendor/github.com/cenkalti/backoff/LICENSE b/vendor/github.com/cenkalti/backoff/LICENSE new file mode 100644 index 0000000000..89b8179965 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Cenk Altı + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/cenkalti/backoff/README.md b/vendor/github.com/cenkalti/backoff/README.md new file mode 100644 index 0000000000..cabfc9c701 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/README.md @@ -0,0 +1,33 @@ +# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls] + +This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. + +[Exponential backoff][exponential backoff wiki] +is an algorithm that uses feedback to multiplicatively decrease the rate of some process, +in order to gradually find an acceptable rate. +The retries exponentially increase and stop increasing when a certain threshold is met. + +## Usage + +Import path is `github.com/cenkalti/backoff/v4`. Please note the version part at the end. + +godoc.org does not support modules yet, +so you can use https://godoc.org/gopkg.in/cenkalti/backoff.v4 to view the documentation. + +## Contributing + +* I would like to keep this library as small as possible. +* Please don't send a PR without opening an issue and discussing it first. +* If proposed change is not a common use case, I will probably not accept it. + +[godoc]: https://godoc.org/github.com/cenkalti/backoff +[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png +[travis]: https://travis-ci.org/cenkalti/backoff +[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master +[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master +[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master + +[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java +[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff + +[advanced example]: https://godoc.org/github.com/cenkalti/backoff#example_ diff --git a/vendor/github.com/cenkalti/backoff/backoff.go b/vendor/github.com/cenkalti/backoff/backoff.go new file mode 100644 index 0000000000..3676ee405d --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/backoff.go @@ -0,0 +1,66 @@ +// Package backoff implements backoff algorithms for retrying operations. +// +// Use Retry function for retrying operations that may fail. +// If Retry does not meet your needs, +// copy/paste the function into your project and modify as you wish. +// +// There is also Ticker type similar to time.Ticker. +// You can use it if you need to work with channels. +// +// See Examples section below for usage examples. +package backoff + +import "time" + +// BackOff is a backoff policy for retrying an operation. +type BackOff interface { + // NextBackOff returns the duration to wait before retrying the operation, + // or backoff. Stop to indicate that no more retries should be made. + // + // Example usage: + // + // duration := backoff.NextBackOff(); + // if (duration == backoff.Stop) { + // // Do not retry operation. + // } else { + // // Sleep for duration and retry operation. + // } + // + NextBackOff() time.Duration + + // Reset to initial state. + Reset() +} + +// Stop indicates that no more retries should be made for use in NextBackOff(). +const Stop time.Duration = -1 + +// ZeroBackOff is a fixed backoff policy whose backoff time is always zero, +// meaning that the operation is retried immediately without waiting, indefinitely. +type ZeroBackOff struct{} + +func (b *ZeroBackOff) Reset() {} + +func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } + +// StopBackOff is a fixed backoff policy that always returns backoff.Stop for +// NextBackOff(), meaning that the operation should never be retried. +type StopBackOff struct{} + +func (b *StopBackOff) Reset() {} + +func (b *StopBackOff) NextBackOff() time.Duration { return Stop } + +// ConstantBackOff is a backoff policy that always returns the same backoff delay. +// This is in contrast to an exponential backoff policy, +// which returns a delay that grows longer as you call NextBackOff() over and over again. +type ConstantBackOff struct { + Interval time.Duration +} + +func (b *ConstantBackOff) Reset() {} +func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } + +func NewConstantBackOff(d time.Duration) *ConstantBackOff { + return &ConstantBackOff{Interval: d} +} diff --git a/vendor/github.com/cenkalti/backoff/backoff_test.go b/vendor/github.com/cenkalti/backoff/backoff_test.go new file mode 100644 index 0000000000..91f27c4f19 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/backoff_test.go @@ -0,0 +1,27 @@ +package backoff + +import ( + "testing" + "time" +) + +func TestNextBackOffMillis(t *testing.T) { + subtestNextBackOff(t, 0, new(ZeroBackOff)) + subtestNextBackOff(t, Stop, new(StopBackOff)) +} + +func subtestNextBackOff(t *testing.T, expectedValue time.Duration, backOffPolicy BackOff) { + for i := 0; i < 10; i++ { + next := backOffPolicy.NextBackOff() + if next != expectedValue { + t.Errorf("got: %d expected: %d", next, expectedValue) + } + } +} + +func TestConstantBackOff(t *testing.T) { + backoff := NewConstantBackOff(time.Second) + if backoff.NextBackOff() != time.Second { + t.Error("invalid interval") + } +} diff --git a/vendor/github.com/cenkalti/backoff/context.go b/vendor/github.com/cenkalti/backoff/context.go new file mode 100644 index 0000000000..fcff86c1b3 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/context.go @@ -0,0 +1,66 @@ +package backoff + +import ( + "context" + "time" +) + +// BackOffContext is a backoff policy that stops retrying after the context +// is canceled. +type BackOffContext interface { // nolint: golint + BackOff + Context() context.Context +} + +type backOffContext struct { + BackOff + ctx context.Context +} + +// WithContext returns a BackOffContext with context ctx +// +// ctx must not be nil +func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint + if ctx == nil { + panic("nil context") + } + + if b, ok := b.(*backOffContext); ok { + return &backOffContext{ + BackOff: b.BackOff, + ctx: ctx, + } + } + + return &backOffContext{ + BackOff: b, + ctx: ctx, + } +} + +func getContext(b BackOff) context.Context { + if cb, ok := b.(BackOffContext); ok { + return cb.Context() + } + if tb, ok := b.(*backOffTries); ok { + return getContext(tb.delegate) + } + return context.Background() +} + +func (b *backOffContext) Context() context.Context { + return b.ctx +} + +func (b *backOffContext) NextBackOff() time.Duration { + select { + case <-b.ctx.Done(): + return Stop + default: + } + next := b.BackOff.NextBackOff() + if deadline, ok := b.ctx.Deadline(); ok && deadline.Sub(time.Now()) < next { // nolint: gosimple + return Stop + } + return next +} diff --git a/vendor/github.com/cenkalti/backoff/context_test.go b/vendor/github.com/cenkalti/backoff/context_test.go new file mode 100644 index 0000000000..806432c438 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/context_test.go @@ -0,0 +1,25 @@ +package backoff + +import ( + "context" + "testing" + "time" +) + +func TestContext(t *testing.T) { + b := NewConstantBackOff(time.Millisecond) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cb := WithContext(b, ctx) + + if cb.Context() != ctx { + t.Error("invalid context") + } + + cancel() + + if cb.NextBackOff() != Stop { + t.Error("invalid next back off") + } +} diff --git a/vendor/github.com/cenkalti/backoff/example_test.go b/vendor/github.com/cenkalti/backoff/example_test.go new file mode 100644 index 0000000000..19d0451504 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/example_test.go @@ -0,0 +1,71 @@ +package backoff + +import ( + "context" + "log" +) + +func ExampleRetry() { + // An operation that may fail. + operation := func() error { + return nil // or an error + } + + err := Retry(operation, NewExponentialBackOff()) + if err != nil { + // Handle error. + return + } + + // Operation is successful. +} + +func ExampleRetryContext() { // nolint: govet + // A context + ctx := context.Background() + + // An operation that may fail. + operation := func() error { + return nil // or an error + } + + b := WithContext(NewExponentialBackOff(), ctx) + + err := Retry(operation, b) + if err != nil { + // Handle error. + return + } + + // Operation is successful. +} + +func ExampleTicker() { + // An operation that may fail. + operation := func() error { + return nil // or an error + } + + ticker := NewTicker(NewExponentialBackOff()) + + var err error + + // Ticks will continue to arrive when the previous operation is still running, + // so operations that take a while to fail could run in quick succession. + for range ticker.C { + if err = operation(); err != nil { + log.Println(err, "will retry...") + continue + } + + ticker.Stop() + break + } + + if err != nil { + // Operation has failed. + return + } + + // Operation is successful. +} diff --git a/vendor/github.com/cenkalti/backoff/exponential.go b/vendor/github.com/cenkalti/backoff/exponential.go new file mode 100644 index 0000000000..4155b30aec --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/exponential.go @@ -0,0 +1,156 @@ +package backoff + +import ( + "math/rand" + "time" +) + +/* +ExponentialBackOff is a backoff implementation that increases the backoff +period for each retry attempt using a randomization function that grows exponentially. + +NextBackOff() is calculated using the following formula: + + randomized interval = + RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor]) + +In other words NextBackOff() will range between the randomization factor +percentage below and above the retry interval. + +For example, given the following parameters: + + RetryInterval = 2 + RandomizationFactor = 0.5 + Multiplier = 2 + +the actual backoff period used in the next retry attempt will range between 1 and 3 seconds, +multiplied by the exponential, that is, between 2 and 6 seconds. + +Note: MaxInterval caps the RetryInterval and not the randomized interval. + +If the time elapsed since an ExponentialBackOff instance is created goes past the +MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop. + +The elapsed time can be reset by calling Reset(). + +Example: Given the following default arguments, for 10 tries the sequence will be, +and assuming we go over the MaxElapsedTime on the 10th try: + + Request # RetryInterval (seconds) Randomized Interval (seconds) + + 1 0.5 [0.25, 0.75] + 2 0.75 [0.375, 1.125] + 3 1.125 [0.562, 1.687] + 4 1.687 [0.8435, 2.53] + 5 2.53 [1.265, 3.795] + 6 3.795 [1.897, 5.692] + 7 5.692 [2.846, 8.538] + 8 8.538 [4.269, 12.807] + 9 12.807 [6.403, 19.210] + 10 19.210 backoff.Stop + +Note: Implementation is not thread-safe. +*/ +type ExponentialBackOff struct { + InitialInterval time.Duration + RandomizationFactor float64 + Multiplier float64 + MaxInterval time.Duration + // After MaxElapsedTime the ExponentialBackOff returns Stop. + // It never stops if MaxElapsedTime == 0. + MaxElapsedTime time.Duration + Stop time.Duration + Clock Clock + + currentInterval time.Duration + startTime time.Time +} + +// Clock is an interface that returns current time for BackOff. +type Clock interface { + Now() time.Time +} + +// Default values for ExponentialBackOff. +const ( + DefaultInitialInterval = 500 * time.Millisecond + DefaultRandomizationFactor = 0.5 + DefaultMultiplier = 1.5 + DefaultMaxInterval = 60 * time.Second + DefaultMaxElapsedTime = 15 * time.Minute +) + +// NewExponentialBackOff creates an instance of ExponentialBackOff using default values. +func NewExponentialBackOff() *ExponentialBackOff { + b := &ExponentialBackOff{ + InitialInterval: DefaultInitialInterval, + RandomizationFactor: DefaultRandomizationFactor, + Multiplier: DefaultMultiplier, + MaxInterval: DefaultMaxInterval, + MaxElapsedTime: DefaultMaxElapsedTime, + Stop: Stop, + Clock: SystemClock, + } + b.Reset() + return b +} + +type systemClock struct{} + +func (t systemClock) Now() time.Time { + return time.Now() +} + +// SystemClock implements Clock interface that uses time.Now(). +var SystemClock = systemClock{} + +// Reset the interval back to the initial retry interval and restarts the timer. +// Reset must be called before using b. +func (b *ExponentialBackOff) Reset() { + b.currentInterval = b.InitialInterval + b.startTime = b.Clock.Now() +} + +// NextBackOff calculates the next backoff interval using the formula: +// Randomized interval = RetryInterval * (1 ± RandomizationFactor) +func (b *ExponentialBackOff) NextBackOff() time.Duration { + // Make sure we have not gone over the maximum elapsed time. + if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime { + return b.Stop + } + defer b.incrementCurrentInterval() + return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval) +} + +// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance +// is created and is reset when Reset() is called. +// +// The elapsed time is computed using time.Now().UnixNano(). It is +// safe to call even while the backoff policy is used by a running +// ticker. +func (b *ExponentialBackOff) GetElapsedTime() time.Duration { + return b.Clock.Now().Sub(b.startTime) +} + +// Increments the current interval by multiplying it with the multiplier. +func (b *ExponentialBackOff) incrementCurrentInterval() { + // Check for overflow, if overflow is detected set the current interval to the max interval. + if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier { + b.currentInterval = b.MaxInterval + } else { + b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier) + } +} + +// Returns a random value from the following interval: +// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval]. +func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration { + var delta = randomizationFactor * float64(currentInterval) + var minInterval = float64(currentInterval) - delta + var maxInterval = float64(currentInterval) + delta + + // Get a random value from the range [minInterval, maxInterval]. + // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then + // we want a 33% chance for selecting either 1, 2 or 3. + return time.Duration(minInterval + (random * (maxInterval - minInterval + 1))) +} diff --git a/vendor/github.com/cenkalti/backoff/exponential_test.go b/vendor/github.com/cenkalti/backoff/exponential_test.go new file mode 100644 index 0000000000..1673dc4511 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/exponential_test.go @@ -0,0 +1,119 @@ +package backoff + +import ( + "math" + "testing" + "time" +) + +func TestBackOff(t *testing.T) { + var ( + testInitialInterval = 500 * time.Millisecond + testRandomizationFactor = 0.1 + testMultiplier = 2.0 + testMaxInterval = 5 * time.Second + testMaxElapsedTime = 15 * time.Minute + ) + + exp := NewExponentialBackOff() + exp.InitialInterval = testInitialInterval + exp.RandomizationFactor = testRandomizationFactor + exp.Multiplier = testMultiplier + exp.MaxInterval = testMaxInterval + exp.MaxElapsedTime = testMaxElapsedTime + exp.Reset() + + var expectedResults = []time.Duration{500, 1000, 2000, 4000, 5000, 5000, 5000, 5000, 5000, 5000} + for i, d := range expectedResults { + expectedResults[i] = d * time.Millisecond + } + + for _, expected := range expectedResults { + assertEquals(t, expected, exp.currentInterval) + // Assert that the next backoff falls in the expected range. + var minInterval = expected - time.Duration(testRandomizationFactor*float64(expected)) + var maxInterval = expected + time.Duration(testRandomizationFactor*float64(expected)) + var actualInterval = exp.NextBackOff() + if !(minInterval <= actualInterval && actualInterval <= maxInterval) { + t.Error("error") + } + } +} + +func TestGetRandomizedInterval(t *testing.T) { + // 33% chance of being 1. + assertEquals(t, 1, getRandomValueFromInterval(0.5, 0, 2)) + assertEquals(t, 1, getRandomValueFromInterval(0.5, 0.33, 2)) + // 33% chance of being 2. + assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.34, 2)) + assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.66, 2)) + // 33% chance of being 3. + assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.67, 2)) + assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.99, 2)) +} + +type TestClock struct { + i time.Duration + start time.Time +} + +func (c *TestClock) Now() time.Time { + t := c.start.Add(c.i) + c.i += time.Second + return t +} + +func TestGetElapsedTime(t *testing.T) { + var exp = NewExponentialBackOff() + exp.Clock = &TestClock{} + exp.Reset() + + var elapsedTime = exp.GetElapsedTime() + if elapsedTime != time.Second { + t.Errorf("elapsedTime=%d", elapsedTime) + } +} + +func TestMaxElapsedTime(t *testing.T) { + var exp = NewExponentialBackOff() + exp.Clock = &TestClock{start: time.Time{}.Add(10000 * time.Second)} + // Change the currentElapsedTime to be 0 ensuring that the elapsed time will be greater + // than the max elapsed time. + exp.startTime = time.Time{} + assertEquals(t, Stop, exp.NextBackOff()) +} + +func TestCustomStop(t *testing.T) { + var exp = NewExponentialBackOff() + customStop := time.Minute + exp.Stop = customStop + exp.Clock = &TestClock{start: time.Time{}.Add(10000 * time.Second)} + // Change the currentElapsedTime to be 0 ensuring that the elapsed time will be greater + // than the max elapsed time. + exp.startTime = time.Time{} + assertEquals(t, customStop, exp.NextBackOff()) +} + +func TestBackOffOverflow(t *testing.T) { + var ( + testInitialInterval time.Duration = math.MaxInt64 / 2 + testMaxInterval time.Duration = math.MaxInt64 + testMultiplier = 2.1 + ) + + exp := NewExponentialBackOff() + exp.InitialInterval = testInitialInterval + exp.Multiplier = testMultiplier + exp.MaxInterval = testMaxInterval + exp.Reset() + + exp.NextBackOff() + // Assert that when an overflow is possible the current varerval time.Duration is set to the max varerval time.Duration . + assertEquals(t, testMaxInterval, exp.currentInterval) +} + +func assertEquals(t *testing.T, expected, value time.Duration) { + if expected != value { + t.Errorf("got: %d, expected: %d", value, expected) + } +} diff --git a/vendor/github.com/cenkalti/backoff/go.mod b/vendor/github.com/cenkalti/backoff/go.mod new file mode 100644 index 0000000000..cef50ea672 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/go.mod @@ -0,0 +1,3 @@ +module github.com/cenkalti/backoff/v4 + +go 1.12 diff --git a/vendor/github.com/cenkalti/backoff/retry.go b/vendor/github.com/cenkalti/backoff/retry.go new file mode 100644 index 0000000000..6c776ccf8e --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/retry.go @@ -0,0 +1,96 @@ +package backoff + +import "time" + +// An Operation is executing by Retry() or RetryNotify(). +// The operation will be retried using a backoff policy if it returns an error. +type Operation func() error + +// Notify is a notify-on-error function. It receives an operation error and +// backoff delay if the operation failed (with an error). +// +// NOTE that if the backoff policy stated to stop retrying, +// the notify function isn't called. +type Notify func(error, time.Duration) + +// Retry the operation o until it does not return error or BackOff stops. +// o is guaranteed to be run at least once. +// +// If o returns a *PermanentError, the operation is not retried, and the +// wrapped error is returned. +// +// Retry sleeps the goroutine for the duration returned by BackOff after a +// failed operation returns. +func Retry(o Operation, b BackOff) error { + return RetryNotify(o, b, nil) +} + +// RetryNotify calls notify function with the error and wait duration +// for each failed attempt before sleep. +func RetryNotify(operation Operation, b BackOff, notify Notify) error { + return RetryNotifyWithTimer(operation, b, notify, nil) +} + +// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer +// for each failed attempt before sleep. +// A default timer that uses system timer is used when nil is passed. +func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error { + var err error + var next time.Duration + if t == nil { + t = &defaultTimer{} + } + + defer func() { + t.Stop() + }() + + ctx := getContext(b) + + b.Reset() + for { + if err = operation(); err == nil { + return nil + } + + if permanent, ok := err.(*PermanentError); ok { + return permanent.Err + } + + if next = b.NextBackOff(); next == Stop { + return err + } + + if notify != nil { + notify(err, next) + } + + t.Start(next) + + select { + case <-ctx.Done(): + return ctx.Err() + case <-t.C(): + } + } +} + +// PermanentError signals that the operation should not be retried. +type PermanentError struct { + Err error +} + +func (e *PermanentError) Error() string { + return e.Err.Error() +} + +func (e *PermanentError) Unwrap() error { + return e.Err +} + +// Permanent wraps the given err in a *PermanentError. +func Permanent(err error) *PermanentError { + return &PermanentError{ + Err: err, + } +} diff --git a/vendor/github.com/cenkalti/backoff/retry_test.go b/vendor/github.com/cenkalti/backoff/retry_test.go new file mode 100644 index 0000000000..9b003584eb --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/retry_test.go @@ -0,0 +1,116 @@ +package backoff + +import ( + "context" + "errors" + "fmt" + "log" + "testing" + "time" +) + +type testTimer struct { + timer *time.Timer +} + +func (t *testTimer) Start(duration time.Duration) { + t.timer = time.NewTimer(0) +} + +func (t *testTimer) Stop() { + if t.timer != nil { + t.timer.Stop() + } +} + +func (t *testTimer) C() <-chan time.Time { + return t.timer.C +} + +func TestRetry(t *testing.T) { + const successOn = 3 + var i = 0 + + // This function is successful on "successOn" calls. + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + + if i == successOn { + log.Println("OK") + return nil + } + + log.Println("error") + return errors.New("error") + } + + err := RetryNotifyWithTimer(f, NewExponentialBackOff(), nil, &testTimer{}) + if err != nil { + t.Errorf("unexpected error: %s", err.Error()) + } + if i != successOn { + t.Errorf("invalid number of retries: %d", i) + } +} + +func TestRetryContext(t *testing.T) { + var cancelOn = 3 + var i = 0 + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // This function cancels context on "cancelOn" calls. + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + + // cancelling the context in the operation function is not a typical + // use-case, however it allows to get predictable test results. + if i == cancelOn { + cancel() + } + + log.Println("error") + return fmt.Errorf("error (%d)", i) + } + + err := RetryNotifyWithTimer(f, WithContext(NewConstantBackOff(time.Millisecond), ctx), nil, &testTimer{}) + if err == nil { + t.Errorf("error is unexpectedly nil") + } + if err.Error() != "error (3)" { + t.Errorf("unexpected error: %s", err.Error()) + } + if i != cancelOn { + t.Errorf("invalid number of retries: %d", i) + } +} + +func TestRetryPermenent(t *testing.T) { + const permanentOn = 3 + var i = 0 + + // This function fails permanently after permanentOn tries + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + + if i == permanentOn { + log.Println("permanent error") + return Permanent(errors.New("permanent error")) + } + + log.Println("error") + return errors.New("error") + } + + err := RetryNotifyWithTimer(f, NewExponentialBackOff(), nil, &testTimer{}) + if err == nil || err.Error() != "permanent error" { + t.Errorf("unexpected error: %s", err) + } + if i != permanentOn { + t.Errorf("invalid number of retries: %d", i) + } +} diff --git a/vendor/github.com/cenkalti/backoff/ticker.go b/vendor/github.com/cenkalti/backoff/ticker.go new file mode 100644 index 0000000000..ed699e0e30 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/ticker.go @@ -0,0 +1,94 @@ +package backoff + +import ( + "context" + "sync" + "time" +) + +// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. +// +// Ticks will continue to arrive when the previous operation is still running, +// so operations that take a while to fail could run in quick succession. +type Ticker struct { + C <-chan time.Time + c chan time.Time + b BackOff + ctx context.Context + timer Timer + stop chan struct{} + stopOnce sync.Once +} + +// NewTicker returns a new Ticker containing a channel that will send +// the time at times specified by the BackOff argument. Ticker is +// guaranteed to tick at least once. The channel is closed when Stop +// method is called or BackOff stops. It is not safe to manipulate the +// provided backoff policy (notably calling NextBackOff or Reset) +// while the ticker is running. +func NewTicker(b BackOff) *Ticker { + return NewTickerWithTimer(b, &defaultTimer{}) +} + +// NewTickerWithTimer returns a new Ticker with a custom timer. +// A default timer that uses system timer is used when nil is passed. +func NewTickerWithTimer(b BackOff, timer Timer) *Ticker { + c := make(chan time.Time) + t := &Ticker{ + C: c, + c: c, + b: b, + ctx: getContext(b), + timer: timer, + stop: make(chan struct{}), + } + t.b.Reset() + go t.run() + return t +} + +// Stop turns off a ticker. After Stop, no more ticks will be sent. +func (t *Ticker) Stop() { + t.stopOnce.Do(func() { close(t.stop) }) +} + +func (t *Ticker) run() { + c := t.c + defer close(c) + + // Ticker is guaranteed to tick at least once. + afterC := t.send(time.Now()) + + for { + if afterC == nil { + return + } + + select { + case tick := <-afterC: + afterC = t.send(tick) + case <-t.stop: + t.c = nil // Prevent future ticks from being sent to the channel. + return + case <-t.ctx.Done(): + return + } + } +} + +func (t *Ticker) send(tick time.Time) <-chan time.Time { + select { + case t.c <- tick: + case <-t.stop: + return nil + } + + next := t.b.NextBackOff() + if next == Stop { + t.Stop() + return nil + } + + t.timer.Start(next) + return t.timer.C() +} diff --git a/vendor/github.com/cenkalti/backoff/ticker_test.go b/vendor/github.com/cenkalti/backoff/ticker_test.go new file mode 100644 index 0000000000..e16a1c2894 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/ticker_test.go @@ -0,0 +1,89 @@ +package backoff + +import ( + "context" + "errors" + "fmt" + "log" + "testing" +) + +func TestTicker(t *testing.T) { + const successOn = 3 + var i = 0 + + // This function is successful on "successOn" calls. + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + + if i == successOn { + log.Println("OK") + return nil + } + + log.Println("error") + return errors.New("error") + } + + b := NewExponentialBackOff() + ticker := NewTickerWithTimer(b, &testTimer{}) + + var err error + for range ticker.C { + if err = f(); err != nil { + t.Log(err) + continue + } + + break + } + if err != nil { + t.Errorf("unexpected error: %s", err.Error()) + } + if i != successOn { + t.Errorf("invalid number of retries: %d", i) + } +} + +func TestTickerContext(t *testing.T) { + var i = 0 + + ctx, cancel := context.WithCancel(context.Background()) + + // Cancel context as soon as it is created. + // Ticker must stop after first tick. + cancel() + + // This function cancels context on "cancelOn" calls. + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + log.Println("error") + return fmt.Errorf("error (%d)", i) + } + + b := WithContext(NewConstantBackOff(0), ctx) + ticker := NewTickerWithTimer(b, &testTimer{}) + + var err error + for range ticker.C { + if err = f(); err != nil { + t.Log(err) + continue + } + + ticker.Stop() + break + } + // Ticker is guaranteed to tick at least once. + if err == nil { + t.Errorf("error is unexpectedly nil") + } + if err.Error() != "error (1)" { + t.Errorf("unexpected error: %s", err) + } + if i != 1 { + t.Errorf("invalid number of retries: %d", i) + } +} diff --git a/vendor/github.com/cenkalti/backoff/timer.go b/vendor/github.com/cenkalti/backoff/timer.go new file mode 100644 index 0000000000..8120d0213c --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/timer.go @@ -0,0 +1,35 @@ +package backoff + +import "time" + +type Timer interface { + Start(duration time.Duration) + Stop() + C() <-chan time.Time +} + +// defaultTimer implements Timer interface using time.Timer +type defaultTimer struct { + timer *time.Timer +} + +// C returns the timers channel which receives the current time when the timer fires. +func (t *defaultTimer) C() <-chan time.Time { + return t.timer.C +} + +// Start starts the timer to fire after the given duration +func (t *defaultTimer) Start(duration time.Duration) { + if t.timer == nil { + t.timer = time.NewTimer(duration) + } else { + t.timer.Reset(duration) + } +} + +// Stop is called when the timer is not used anymore and resources may be freed. +func (t *defaultTimer) Stop() { + if t.timer != nil { + t.timer.Stop() + } +} diff --git a/vendor/github.com/cenkalti/backoff/tries.go b/vendor/github.com/cenkalti/backoff/tries.go new file mode 100644 index 0000000000..28d58ca37c --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/tries.go @@ -0,0 +1,38 @@ +package backoff + +import "time" + +/* +WithMaxRetries creates a wrapper around another BackOff, which will +return Stop if NextBackOff() has been called too many times since +the last time Reset() was called + +Note: Implementation is not thread-safe. +*/ +func WithMaxRetries(b BackOff, max uint64) BackOff { + return &backOffTries{delegate: b, maxTries: max} +} + +type backOffTries struct { + delegate BackOff + maxTries uint64 + numTries uint64 +} + +func (b *backOffTries) NextBackOff() time.Duration { + if b.maxTries == 0 { + return Stop + } + if b.maxTries > 0 { + if b.maxTries <= b.numTries { + return Stop + } + b.numTries++ + } + return b.delegate.NextBackOff() +} + +func (b *backOffTries) Reset() { + b.numTries = 0 + b.delegate.Reset() +} diff --git a/vendor/github.com/cenkalti/backoff/tries_test.go b/vendor/github.com/cenkalti/backoff/tries_test.go new file mode 100644 index 0000000000..ee55b68e50 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/tries_test.go @@ -0,0 +1,63 @@ +package backoff + +import ( + "errors" + "math/rand" + "testing" + "time" +) + +func TestMaxTriesHappy(t *testing.T) { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + max := 17 + r.Intn(13) + bo := WithMaxRetries(&ZeroBackOff{}, uint64(max)) + + // Load up the tries count, but reset should clear the record + for ix := 0; ix < max/2; ix++ { + bo.NextBackOff() + } + bo.Reset() + + // Now fill the tries count all the way up + for ix := 0; ix < max; ix++ { + d := bo.NextBackOff() + if d == Stop { + t.Errorf("returned Stop on try %d", ix) + } + } + + // We have now called the BackOff max number of times, we expect + // the next result to be Stop, even if we try it multiple times + for ix := 0; ix < 7; ix++ { + d := bo.NextBackOff() + if d != Stop { + t.Error("invalid next back off") + } + } + + // Reset makes it all work again + bo.Reset() + d := bo.NextBackOff() + if d == Stop { + t.Error("returned Stop after reset") + } +} + +// https://github.com/cenkalti/backoff/issues/80 +func TestMaxTriesZero(t *testing.T) { + var called int + + b := WithMaxRetries(&ZeroBackOff{}, 0) + + err := Retry(func() error { + called++ + return errors.New("err") + }, b) + + if err == nil { + t.Errorf("error expected, nil founc") + } + if called != 1 { + t.Errorf("operation is called %d times", called) + } +} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/README.md b/vendor/github.com/cpacia/BitcoinCash-Wallet/README.md deleted file mode 100644 index 3429b6bfca..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Bitcoin Cash Wallet - - - -This is a fork of https://github.com/OpenBazaar/spvwallet modfied for Bitcoin Cash. It includes a fully functional GUI wallet and CLI. - -It uses stock btcd plus a few cash specific modifications found in the [bchutil](https://github.com/cpacia/bchutil) package. - -To compile and run: -```bash -go get github.com/cpacia/BitcoinCash-Wallet -make install -bitcoincash -``` -Or download a pre-compiled version from [releases](https://github.com/cpacia/BitcoinCash-Wallet/releases). diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/blockchain.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/blockchain.go deleted file mode 100644 index adaa0aaad5..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/blockchain.go +++ /dev/null @@ -1,488 +0,0 @@ -// Copyright (C) 2015-2016 The Lightning Network Developers -// Copyright (c) 2016-2017 The OpenBazaar Developers - -package bitcoincash - -import ( - "errors" - "fmt" - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "math/big" - "sort" - "sync" - "time" -) - -// Blockchain settings. These are kindof Bitcoin specific, but not contained in -// chaincfg.Params so they'll go here. If you're into the [ANN]altcoin scene, -// you may want to paramaterize these constants. -const ( - targetSpacing = 600 - medianTimeBlocks = 11 -) - -var OrphanHeaderError = errors.New("header does not extend any known headers") - -// Wrapper around Headers implementation that handles all blockchain operations -type Blockchain struct { - lock *sync.Mutex - params *chaincfg.Params - db Headers - crationDate time.Time - checkpoint Checkpoint -} - -func NewBlockchain(filePath string, walletCreationDate time.Time, params *chaincfg.Params) (*Blockchain, error) { - hdb, err := NewHeaderDB(filePath) - if err != nil { - return nil, err - } - b := &Blockchain{ - lock: new(sync.Mutex), - params: params, - db: hdb, - crationDate: walletCreationDate, - } - b.checkpoint = GetCheckpoint(walletCreationDate, params) - - h, err := b.db.Height() - if h == 0 || err != nil { - log.Info("Initializing headers db with checkpoints") - // Put the checkpoint to the db - sh := StoredHeader{ - header: b.checkpoint.Header, - height: b.checkpoint.Height, - totalWork: big.NewInt(0), - } - err := b.db.Put(sh, true) - if err != nil { - return nil, err - } - } - return b, nil -} - -func (b *Blockchain) CommitHeader(header wire.BlockHeader) (bool, *StoredHeader, uint32, error) { - b.lock.Lock() - defer b.lock.Unlock() - newTip := false - var commonAncestor *StoredHeader - // Fetch our current best header from the db - bestHeader, err := b.db.GetBestHeader() - if err != nil { - return false, nil, 0, err - } - tipHash := bestHeader.header.BlockHash() - var parentHeader StoredHeader - - // If the tip is also the parent of this header, then we can save a database read by skipping - // the lookup of the parent header. Otherwise (ophan?) we need to fetch the parent. - if header.PrevBlock.IsEqual(&tipHash) { - parentHeader = bestHeader - } else { - parentHeader, err = b.db.GetPreviousHeader(header) - if err != nil { - return false, nil, 0, fmt.Errorf("Header %s does not extend any known headers", header.BlockHash().String()) - } - } - valid := b.CheckHeader(header, parentHeader) - if !valid { - return false, nil, 0, nil - } - // If this block is already the tip, return - headerHash := header.BlockHash() - if tipHash.IsEqual(&headerHash) { - return newTip, nil, 0, nil - } - // Add the work of this header to the total work stored at the previous header - cumulativeWork := new(big.Int).Add(parentHeader.totalWork, blockchain.CalcWork(header.Bits)) - - // If the cumulative work is greater than the total work of our best header - // then we have a new best header. Update the chain tip and check for a reorg. - if cumulativeWork.Cmp(bestHeader.totalWork) == 1 { - newTip = true - prevHash := parentHeader.header.BlockHash() - // If this header is not extending the previous best header then we have a reorg. - if !tipHash.IsEqual(&prevHash) { - commonAncestor, err = b.GetCommonAncestor(StoredHeader{header: header, height: parentHeader.height + 1}, bestHeader) - if err != nil { - log.Errorf("Error calculating common ancestor: %s", err.Error()) - return newTip, commonAncestor, 0, err - } - log.Warningf("REORG!!! REORG!!! REORG!!! At block %d, Wiped out %d blocks", int(bestHeader.height), int(bestHeader.height-commonAncestor.height)) - } - } - newHeight := parentHeader.height + 1 - // Put the header to the database - err = b.db.Put(StoredHeader{ - header: header, - height: newHeight, - totalWork: cumulativeWork, - }, newTip) - if err != nil { - return newTip, commonAncestor, 0, err - } - return newTip, commonAncestor, newHeight, nil -} - -func (b *Blockchain) CheckHeader(header wire.BlockHeader, prevHeader StoredHeader) bool { - height := prevHeader.height - - // Due to the rolling difficulty period our checkpoint block consists of a block and a hash of a block 146 blocks later - // During this period we can skip the validity checks as long as block checkpoint + 146 matches the hardcoded hash. - if height+1 <= b.checkpoint.Height+147 { - h := header.BlockHash() - if b.checkpoint.Check2 != nil && height+1 == b.checkpoint.Height+147 && !b.checkpoint.Check2.IsEqual(&h) { - return false - } - return true - } - - // Get hash of n-1 header - prevHash := prevHeader.header.BlockHash() - - // Check if headers link together. That whole 'blockchain' thing. - if prevHash.IsEqual(&header.PrevBlock) == false { - log.Errorf("Headers %d and %d don't link.\n", height, height+1) - return false - } - - // Check the header meets the difficulty requirement - if b.params.Name != chaincfg.RegressionNetParams.Name { // Don't need to check difficulty on regtest - diffTarget, err := b.calcRequiredWork(header, int32(height+1), prevHeader) - if err != nil { - log.Errorf("Error calclating difficulty", err) - return false - } - if header.Bits != diffTarget && b.params.Name == chaincfg.MainNetParams.Name { - log.Warningf("Block %d %s incorrect difficulty. Read %d, expect %d\n", - height+1, header.BlockHash().String(), header.Bits, diffTarget) - return false - } else if diffTarget == b.params.PowLimitBits && header.Bits > diffTarget && b.params.Name == chaincfg.TestNet3Params.Name { - log.Warningf("Block %d %s incorrect difficulty. Read %d, expect %d\n", - height+1, header.BlockHash().String(), header.Bits, diffTarget) - return false - } - } - - // Check if there's a valid proof of work. That whole "Bitcoin" thing. - if !checkProofOfWork(header, b.params) { - log.Debugf("Block %d bad proof of work.\n", height+1) - return false - } - - return true // it must have worked if there's no errors and got to the end. -} - -// Get the PoW target this block should meet. We may need to handle a difficulty adjustment -// or testnet difficulty rules. -func (b *Blockchain) calcRequiredWork(header wire.BlockHeader, height int32, prevHeader StoredHeader) (uint32, error) { - // Special difficulty rule for testnet - if b.params.ReduceMinDifficulty && header.Timestamp.After(prevHeader.header.Timestamp.Add(targetSpacing*2)) { - return b.params.PowLimitBits, nil - } - - suitableHeader, err := b.GetSuitableBlock(prevHeader) - if err != nil { - log.Error(err) - return 0, err - } - epoch, err := b.GetEpoch(prevHeader.header) - if err != nil { - log.Error(err) - return 0, err - } - return calcDiffAdjust(epoch, suitableHeader, b.params), nil -} - -func (b *Blockchain) CalcMedianTimePast(header wire.BlockHeader) (time.Time, error) { - timestamps := make([]int64, medianTimeBlocks) - numNodes := 0 - iterNode := StoredHeader{header: header} - var err error - - for i := 0; i < medianTimeBlocks; i++ { - numNodes++ - timestamps[i] = iterNode.header.Timestamp.Unix() - iterNode, err = b.db.GetPreviousHeader(iterNode.header) - if err != nil { - return time.Time{}, err - } - } - timestamps = timestamps[:numNodes] - sort.Sort(timeSorter(timestamps)) - medianTimestamp := timestamps[numNodes/2] - return time.Unix(medianTimestamp, 0), nil -} - -// Rollsback and grabs block n-144, n-145, and n-146, sorts them by timestamps and returns the middle header. -func (b *Blockchain) GetEpoch(hdr wire.BlockHeader) (StoredHeader, error) { - sh := StoredHeader{header: hdr} - var err error - for i := 0; i < 144; i++ { - sh, err = b.db.GetPreviousHeader(sh.header) - if err != nil { - return sh, err - } - } - oneFourtyFour := sh - sh, err = b.db.GetPreviousHeader(oneFourtyFour.header) - if err != nil { - return sh, err - } - oneFourtyFive := sh - sh, err = b.db.GetPreviousHeader(oneFourtyFive.header) - if err != nil { - return sh, err - } - oneFourtySix := sh - headers := []StoredHeader{oneFourtyFour, oneFourtyFive, oneFourtySix} - sort.Sort(blockSorter(headers)) - return headers[1], nil -} - -// Rollsback grabs the last two headers before this one. Sorts the three and returns the mid. -func (b *Blockchain) GetSuitableBlock(hdr StoredHeader) (StoredHeader, error) { - n := hdr - sh, err := b.db.GetPreviousHeader(hdr.header) - if err != nil { - return sh, err - } - n1 := sh - sh, err = b.db.GetPreviousHeader(n1.header) - if err != nil { - return sh, err - } - n2 := sh - headers := []StoredHeader{n, n1, n2} - sort.Sort(blockSorter(headers)) - return headers[1], nil -} - -func (b *Blockchain) GetNPrevBlockHashes(n int) []*chainhash.Hash { - var ret []*chainhash.Hash - hdr, err := b.db.GetBestHeader() - if err != nil { - return ret - } - tipSha := hdr.header.BlockHash() - ret = append(ret, &tipSha) - for i := 0; i < n-1; i++ { - hdr, err = b.db.GetPreviousHeader(hdr.header) - if err != nil { - return ret - } - shaHash := hdr.header.BlockHash() - ret = append(ret, &shaHash) - } - return ret -} - -func (b *Blockchain) GetBlockLocator() blockchain.BlockLocator { - var ret []*chainhash.Hash - parent, err := b.db.GetBestHeader() - if err != nil { - return ret - } - - rollback := func(parent StoredHeader, n int) (StoredHeader, error) { - for i := 0; i < n; i++ { - parent, err = b.db.GetPreviousHeader(parent.header) - if err != nil { - return parent, err - } - } - return parent, nil - } - - step := 1 - start := 0 - for { - if start >= 9 { - step *= 2 - start = 0 - } - hash := parent.header.BlockHash() - ret = append(ret, &hash) - if len(ret) == 500 { - break - } - parent, err = rollback(parent, step) - if err != nil { - break - } - start += 1 - } - return blockchain.BlockLocator(ret) -} - -// Returns last header before reorg point -func (b *Blockchain) GetCommonAncestor(bestHeader, prevBestHeader StoredHeader) (*StoredHeader, error) { - var err error - rollback := func(parent StoredHeader, n int) (StoredHeader, error) { - for i := 0; i < n; i++ { - parent, err = b.db.GetPreviousHeader(parent.header) - if err != nil { - return parent, err - } - } - return parent, nil - } - - majority := bestHeader - minority := prevBestHeader - if bestHeader.height > prevBestHeader.height { - majority, err = rollback(majority, int(bestHeader.height-prevBestHeader.height)) - if err != nil { - return nil, err - } - } else if prevBestHeader.height > bestHeader.height { - minority, err = rollback(minority, int(prevBestHeader.height-bestHeader.height)) - if err != nil { - return nil, err - } - } - - for { - majorityHash := majority.header.BlockHash() - minorityHash := minority.header.BlockHash() - if majorityHash.IsEqual(&minorityHash) { - return &majority, nil - } - majority, err = b.db.GetPreviousHeader(majority.header) - if err != nil { - return nil, err - } - minority, err = b.db.GetPreviousHeader(minority.header) - if err != nil { - return nil, err - } - } -} - -// Rollback the header database to the last header before time t. -// We shouldn't go back further than the checkpoint -func (b *Blockchain) Rollback(t time.Time) error { - b.lock.Lock() - defer b.lock.Unlock() - checkpoint := GetCheckpoint(b.crationDate, b.params) - checkPointHash := checkpoint.Header.BlockHash() - sh, err := b.db.GetBestHeader() - if err != nil { - return err - } - // If t is greater than the timestamp at the tip then do nothing - if sh.header.Timestamp.Before(t) { - return nil - } - // If the tip is our checkpoint then do nothing - checkHash := sh.header.BlockHash() - if checkHash.IsEqual(&checkPointHash) { - return nil - } - rollbackHeight := uint32(0) - for i := 0; i < 1000000000; i++ { - sh, err = b.db.GetPreviousHeader(sh.header) - if err != nil { - return err - } - checkHash := sh.header.BlockHash() - // If we rolled back to the checkpoint then stop here and set the checkpoint as the tip - if checkHash.IsEqual(&checkPointHash) { - rollbackHeight = checkpoint.Height - break - } - // If we hit a header created before t then stop here and set this header as the tip - if sh.header.Timestamp.Before(t) { - rollbackHeight = sh.height - break - } - } - err = b.db.DeleteAfter(rollbackHeight) - if err != nil { - return err - } - return b.db.Put(sh, true) -} - -func (b *Blockchain) BestBlock() (StoredHeader, error) { - sh, err := b.db.GetBestHeader() - if err != nil { - return StoredHeader{}, err - } - return sh, nil -} - -func (b *Blockchain) GetHeader(hash *chainhash.Hash) (StoredHeader, error) { - sh, err := b.db.GetHeader(*hash) - if err != nil { - return sh, err - } - return sh, nil -} - -func (b *Blockchain) Close() { - b.lock.Lock() - b.db.Close() -} - -// Verifies the header hashes into something lower than specified by the 4-byte bits field. -func checkProofOfWork(header wire.BlockHeader, p *chaincfg.Params) bool { - target := blockchain.CompactToBig(header.Bits) - - // The target must more than 0. Why can you even encode negative... - if target.Sign() <= 0 { - log.Debugf("Block target %064x is neagtive(??)\n", target.Bytes()) - return false - } - // The target must be less than the maximum allowed (difficulty 1) - if target.Cmp(p.PowLimit) > 0 { - log.Debugf("Block target %064x is "+ - "higher than max of %064x", target, p.PowLimit.Bytes()) - return false - } - // The header hash must be less than the claimed target in the header. - blockHash := header.BlockHash() - hashNum := blockchain.HashToBig(&blockHash) - if hashNum.Cmp(target) > 0 { - log.Debugf("Block hash %064x is higher than "+ - "required target of %064x", hashNum, target) - return false - } - return true -} - -// This function takes in a start and end block header and uses the timestamps in each -// to calculate how much of a difficulty adjustment is needed. It returns a new compact -// difficulty target. -func calcDiffAdjust(start, end StoredHeader, p *chaincfg.Params) uint32 { - work := new(big.Int).Sub(end.totalWork, start.totalWork) - - // In order to avoid difficulty cliffs, we bound the amplitude of the - // adjustement we are going to do. - duration := end.header.Timestamp.Unix() - start.header.Timestamp.Unix() - if duration > 288*int64(targetSpacing) { - duration = 288 * int64(targetSpacing) - } else if duration < 72*int64(targetSpacing) { - duration = 72 * int64(targetSpacing) - } - - projectedWork := new(big.Int).Mul(work, big.NewInt(int64(targetSpacing))) - - pw := new(big.Int).Div(projectedWork, big.NewInt(duration)) - - e := new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil) - - nt := new(big.Int).Sub(e, pw) - - newTarget := new(big.Int).Div(nt, pw) - - // clip again if above minimum target (too easy) - if newTarget.Cmp(p.PowLimit) > 0 { - newTarget.Set(p.PowLimit) - } - return blockchain.BigToCompact(newTarget) -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/checkpoints.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/checkpoints.go deleted file mode 100644 index 67322f1af2..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/checkpoints.go +++ /dev/null @@ -1,85 +0,0 @@ -package bitcoincash - -import ( - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "time" -) - -type Checkpoint struct { - Height uint32 - Header wire.BlockHeader - Check2 *chainhash.Hash -} - -var mainnetCheckpoints []Checkpoint -var testnet3Checkpoints []Checkpoint -var regtestCheckpoint Checkpoint - -func init() { - // Mainnet - mainnetPrev, _ := chainhash.NewHashFromStr("0000000000000000011ebf65b60d0a3de80b8175be709d653b4c1a1beeb6ab9c") - mainnetMerk, _ := chainhash.NewHashFromStr("8ebf2179d8b1ba0aaf5f15357f963b56f53a8c6207e0156b4b6def119be61bee") - check2, _ := chainhash.NewHashFromStr("000000000000000001250f09f253d22d6ef14e924eccb7c1bbaa0695269cef59") - mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{ - Height: 504032, - Header: wire.BlockHeader{ - Version: 536870912, - PrevBlock: *mainnetPrev, - MerkleRoot: *mainnetMerk, - Timestamp: time.Unix(1510606995, 0), - Bits: 403026987, - Nonce: 273755974, - }, - Check2: check2, - }) - if mainnetCheckpoints[0].Header.BlockHash().String() != "00000000000000000343e9875012f2062554c8752929892c82a0c0743ac7dcfd" { - panic("Invalid checkpoint") - } - - // Testnet3 - testnet3Prev, _ := chainhash.NewHashFromStr("00000000824633a21bc41dccbd7a6d159a4deebaece6f6dcf2093301aea040a5") - testnet3Merk, _ := chainhash.NewHashFromStr("d69264d97d77da1b9bf0ae031512a89e0607e8200be29a74163a39b8558f5714") - testnetCheck2, _ := chainhash.NewHashFromStr("00000000000044040acf28b1bab8706f09f7862275b65a03580b6db136ad2dbd") - testnet3Checkpoints = append(testnet3Checkpoints, Checkpoint{ - Height: 1189213, - Header: wire.BlockHeader{ - Version: 536870912, - PrevBlock: *testnet3Prev, - MerkleRoot: *testnet3Merk, - Timestamp: time.Unix(1510739152, 0), - Bits: 486604799, - Nonce: 2325788686, - }, - Check2: testnetCheck2, - }) - if testnet3Checkpoints[0].Header.BlockHash().String() != "000000001f734385476b82be8eb10512c9fb5bd1534cf3ceb4af2d47a7b20ff7" { - panic("Invalid checkpoint") - } - - // Regtest - regtestCheckpoint = Checkpoint{0, chaincfg.RegressionNetParams.GenesisBlock.Header, nil} -} - -func GetCheckpoint(walletCreationDate time.Time, params *chaincfg.Params) Checkpoint { - switch params.Name { - case chaincfg.MainNetParams.Name: - for i := len(mainnetCheckpoints) - 1; i >= 0; i-- { - if walletCreationDate.After(mainnetCheckpoints[i].Header.Timestamp) { - return mainnetCheckpoints[i] - } - } - return mainnetCheckpoints[0] - case chaincfg.TestNet3Params.Name: - for i := len(testnet3Checkpoints) - 1; i >= 0; i-- { - if walletCreationDate.After(testnet3Checkpoints[i].Header.Timestamp) { - return testnet3Checkpoints[i] - } - } - return testnet3Checkpoints[0] - - default: - return regtestCheckpoint - } -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/config.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/config.go deleted file mode 100644 index bb8eaccaee..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/config.go +++ /dev/null @@ -1,108 +0,0 @@ -package bitcoincash - -import ( - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg" - "github.com/mitchellh/go-homedir" - "github.com/op/go-logging" - "golang.org/x/net/proxy" - "net" - "net/url" - "os" - "path/filepath" - "runtime" - "time" -) - -type Config struct { - // Network parameters. Set mainnet, testnet, or regtest using this. - Params *chaincfg.Params - - // Bip39 mnemonic string. If empty a new mnemonic will be created. - Mnemonic string - - // The date the wallet was created. - // If before the earliest checkpoint the chain will be synced using the earliest checkpoint. - CreationDate time.Time - - // The user-agent that shall be visible to peers - UserAgent string - - // Location of the data directory - RepoPath string - - // An implementation of the Datastore interface - DB wallet.Datastore - - // If you wish to connect to a single trusted peer set this. Otherwise leave nil. - TrustedPeer net.Addr - - // A Tor proxy can be set here causing the wallet will use Tor - Proxy proxy.Dialer - - // The default fee-per-byte for each level - LowFee uint64 - MediumFee uint64 - HighFee uint64 - - // The highest allowable fee-per-byte - MaxFee uint64 - - // External API to query to look up fees. If this field is nil then the default fees will be used. - // If the API is unreachable then the default fees will likewise be used. If the API returns a fee - // greater than MaxFee then the MaxFee will be used in place. The API response must be formatted as - // { "fastestFee": 40, "halfHourFee": 20, "hourFee": 10 } - FeeAPI url.URL - - // A logger. You can write the logs to file or stdout or however else you want. - Logger logging.Backend - - // A slice of additional items to add to the bloom filter - AdditionalFilters [][]byte - - // Disable exchange rate provider - DisableExchangeRates bool -} - -func NewDefaultConfig() *Config { - repoPath, _ := getRepoPath() - _, ferr := os.Stat(repoPath) - if os.IsNotExist(ferr) { - os.Mkdir(repoPath, os.ModePerm) - } - feeApi, _ := url.Parse("https://bitcoinfees.21.co/api/v1/fees/recommended") - return &Config{ - Params: &chaincfg.MainNetParams, - UserAgent: "spvwallet", - RepoPath: repoPath, - LowFee: 140, - MediumFee: 160, - HighFee: 180, - MaxFee: 2000, - FeeAPI: *feeApi, - Logger: logging.NewLogBackend(os.Stdout, "", 0), - } -} - -func getRepoPath() (string, error) { - // Set default base path and directory name - path := "~" - directoryName := "bitcoincash" - - // Override OS-specific names - switch runtime.GOOS { - case "linux": - directoryName = ".bitcoincash" - case "darwin": - path = "~/Library/Application Support" - } - - // Join the path and directory name, then expand the home path - fullPath, err := homedir.Expand(filepath.Join(path, directoryName)) - if err != nil { - return "", err - } - - // Return the shortest lexical representation of the path - return filepath.Clean(fullPath), nil -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/eight333.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/eight333.go deleted file mode 100644 index 93e7109bde..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/eight333.go +++ /dev/null @@ -1,777 +0,0 @@ -package bitcoincash - -import ( - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - peerpkg "github.com/btcsuite/btcd/peer" - "github.com/btcsuite/btcd/wire" - "net" - "time" -) - -const ( - maxRequestedTxns = wire.MaxInvPerMsg - maxFalsePositives = 7 -) - -// newPeerMsg signifies a newly connected peer to the block handler. -type newPeerMsg struct { - peer *peerpkg.Peer -} - -// donePeerMsg signifies a newly disconnected peer to the block handler. -type donePeerMsg struct { - peer *peerpkg.Peer -} - -// headersMsg packages a bitcoin headers message and the peer it came from -// together so the handler has access to that information. -type headersMsg struct { - headers *wire.MsgHeaders - peer *peerpkg.Peer -} - -// merkleBlockMsg packages a merkle block message and the peer it came from -// together so the handler has access to that information. -type merkleBlockMsg struct { - merkleBlock *wire.MsgMerkleBlock - peer *peerpkg.Peer -} - -// invMsg packages a bitcoin inv message and the peer it came from together -// so the handler has access to that information. -type invMsg struct { - inv *wire.MsgInv - peer *peerpkg.Peer -} - -type heightAndTime struct { - height uint32 - timestamp time.Time -} - -// txMsg packages a bitcoin tx message and the peer it came from together -// so the handler has access to that information. -type txMsg struct { - tx *wire.MsgTx - peer *peerpkg.Peer - reply chan struct{} -} - -type updateFiltersMsg struct{} - -type WireServiceConfig struct { - params *chaincfg.Params - chain *Blockchain - txStore *TxStore - walletCreationDate time.Time - minPeersForSync int -} - -// peerSyncState stores additional information that the WireService tracks -// about a peer. -type peerSyncState struct { - syncCandidate bool - requestQueue []*wire.InvVect - requestedTxns map[chainhash.Hash]heightAndTime - requestedBlocks map[chainhash.Hash]struct{} - falsePositives uint32 - blockScore int32 -} - -type WireService struct { - params *chaincfg.Params - chain *Blockchain - txStore *TxStore - walletCreationDate time.Time - syncPeer *peerpkg.Peer - peerStates map[*peerpkg.Peer]*peerSyncState - requestedTxns map[chainhash.Hash]heightAndTime - requestedBlocks map[chainhash.Hash]struct{} - mempool map[chainhash.Hash]struct{} - msgChan chan interface{} - quit chan struct{} - minPeersForSync int - zeroHash chainhash.Hash -} - -func NewWireService(config *WireServiceConfig) *WireService { - return &WireService{ - params: config.params, - chain: config.chain, - walletCreationDate: config.walletCreationDate, - minPeersForSync: config.minPeersForSync, - txStore: config.txStore, - peerStates: make(map[*peerpkg.Peer]*peerSyncState), - requestedTxns: make(map[chainhash.Hash]heightAndTime), - requestedBlocks: make(map[chainhash.Hash]struct{}), - mempool: make(map[chainhash.Hash]struct{}), - msgChan: make(chan interface{}), - } -} - -func (ws *WireService) MsgChan() chan interface{} { - return ws.msgChan -} - -// The start function must be run in its own goroutine. The entire WireService is single -// threaded which means all messages are processed sequentially removing the need for complex -// locking. -func (ws *WireService) Start() { - ws.quit = make(chan struct{}) - best, err := ws.chain.BestBlock() - if err != nil { - log.Error(err) - } - log.Infof("Starting wire service at height %d", int(best.height)) -out: - for { - select { - case m := <-ws.msgChan: - switch msg := m.(type) { - case newPeerMsg: - ws.handleNewPeerMsg(msg.peer) - case donePeerMsg: - ws.handleDonePeerMsg(msg.peer) - case headersMsg: - ws.handleHeadersMsg(&msg) - case merkleBlockMsg: - ws.handleMerkleBlockMsg(&msg) - case invMsg: - ws.handleInvMsg(&msg) - case txMsg: - ws.handleTxMsg(&msg) - case updateFiltersMsg: - ws.handleUpdateFiltersMsg() - default: - log.Warningf("Unknown message type sent to WireService message chan: %T", msg) - } - case <-ws.quit: - break out - } - } -} - -func (ws *WireService) Stop() { - ws.syncPeer = nil - close(ws.quit) -} - -func (ws *WireService) Resync() { - ws.startSync(ws.syncPeer) -} - -func (ws *WireService) handleNewPeerMsg(peer *peerpkg.Peer) { - // Initialize the peer state - ws.peerStates[peer] = &peerSyncState{ - syncCandidate: ws.isSyncCandidate(peer), - requestedTxns: make(map[chainhash.Hash]heightAndTime), - requestedBlocks: make(map[chainhash.Hash]struct{}), - } - - ws.updateFilterAndSend(peer) - - // If we don't have a sync peer and we are not current we should start a sync - if ws.syncPeer == nil && !ws.Current() { - ws.startSync(nil) - } -} - -// isSyncCandidate returns whether or not the peer is a candidate to consider -// syncing from. -func (ws *WireService) isSyncCandidate(peer *peerpkg.Peer) bool { - // Typically a peer is not a candidate for sync if it's not a full node, - // however regression test is special in that the regression tool is - // not a full node and still needs to be considered a sync candidate. - if ws.params.Name == chaincfg.RegressionNetParams.Name { - // The peer is not a candidate if it's not coming from localhost - // or the hostname can't be determined for some reason. - host, _, err := net.SplitHostPort(peer.Addr()) - if err != nil { - return false - } - - if host != "127.0.0.1" && host != "localhost" { - return false - } - } else { - // The peer is not a candidate for sync if it's not a full node - nodeServices := peer.Services() - if nodeServices&wire.SFNodeNetwork != wire.SFNodeNetwork { - return false - } - } - - // Candidate if all checks passed. - return true -} - -func (ws *WireService) startSync(syncPeer *peerpkg.Peer) { - // Wait for a minimum number of peers to connect. This makes sure we have a good - // selection to choose from before starting the sync. - if len(ws.peerStates) < ws.minPeersForSync { - return - } - ws.Rebroadcast() - bestBlock, err := ws.chain.BestBlock() - if err != nil { - log.Error(err) - return - } - var bestPeer *peerpkg.Peer - if syncPeer == nil { - var bestPeerHeight int32 - for peer, state := range ws.peerStates { - if !state.syncCandidate { - continue - } - - // Remove sync candidate peers that are no longer candidates due - // to passing their latest known block. NOTE: The < is - // intentional as opposed to <=. While technically the peer - // doesn't have a later block when it's equal, it will likely - // have one soon so it is a reasonable choice. It also allows - // the case where both are at 0 such as during regression test. - if peer.LastBlock() < int32(bestBlock.height) { - state.syncCandidate = false - continue - } - - // Select peer which is reporting the greatest height - if peer.LastBlock() > bestPeerHeight { - bestPeer = peer - bestPeerHeight = peer.LastBlock() - } - } - } else { - bestPeer = syncPeer - } - - // Start syncing this bitch - if bestPeer != nil { - // TODO: use checkpoints here - ws.syncPeer = bestPeer - - // Clear the requestedBlocks if the sync peer changes, otherwise - // we may ignore blocks we need that the last sync peer failed - // to send. - ws.requestedBlocks = make(map[chainhash.Hash]struct{}) - - locator := ws.chain.GetBlockLocator() - - // If the best header we have was created before this wallet then we can sync just headers - // up to the wallet creation date since we know there wont be any transactions in those - // blocks we're interested in. However, if we're past the wallet creation date we need to - // start downloading merkle blocks so we learn of the wallet's transactions. We'll use a - // buffer of one week to make sure we don't miss anything. - log.Infof("Starting chain download from %s", bestPeer) - if bestBlock.header.Timestamp.Before(ws.walletCreationDate.Add(-time.Hour * 24 * 7)) { - bestPeer.PushGetHeadersMsg(locator, &ws.zeroHash) - } else { - bestPeer.PushGetBlocksMsg(locator, &ws.zeroHash) - } - } else { - log.Warning("No sync candidates available") - } -} - -func (ws *WireService) Current() bool { - best, err := ws.chain.BestBlock() - if err != nil { - return false - } - - // If our best header's timestamp was more than 24 hours ago, we're probably not current - if best.header.Timestamp.Before(time.Now().Add(-24 * time.Hour)) { - return false - } - - // Check our other peers to see if any are reporting a greater height than we have - for peer := range ws.peerStates { - if int32(best.height) < peer.LastBlock() { - return false - } - } - return true -} - -func (ws *WireService) handleDonePeerMsg(peer *peerpkg.Peer) { - state, exists := ws.peerStates[peer] - if !exists { - return - } - - // Remove the peer from the list of candidate peers. - delete(ws.peerStates, peer) - - // Remove requested transactions from the global map so that they will - // be fetched from elsewhere next time we get an inv. - for txHash := range state.requestedTxns { - delete(ws.requestedTxns, txHash) - } - - // Remove requested blocks from the global map so that they will be - // fetched from elsewhere next time we get an inv. - // TODO: we could possibly here check which peers have these blocks - // and request them now to speed things up a little. - for blockHash := range state.requestedBlocks { - delete(ws.requestedBlocks, blockHash) - } - - // Attempt to find a new peer to sync from if the quitting peer is the - // sync peer. - if ws.syncPeer == peer && !ws.Current() { - log.Info("Sync peer disconnected") - ws.syncPeer = nil - ws.startSync(nil) - } -} - -// handleHeadersMsg handles block header messages from all peers. Headers are -// requested when performing a headers-first sync. -func (ws *WireService) handleHeadersMsg(hmsg *headersMsg) { - peer := hmsg.peer - if peer != ws.syncPeer { - log.Warning("Received header message from a peer that isn't our sync peer") - peer.Disconnect() - return - } - _, exists := ws.peerStates[peer] - if !exists { - log.Warningf("Received headers message from unknown peer %s", peer) - peer.Disconnect() - return - } - - msg := hmsg.headers - numHeaders := len(msg.Headers) - - // Nothing to do for an empty headers message - if numHeaders == 0 { - return - } - - // Process each header we received. Make sure when check that each one is before our - // wallet creation date (minus the buffer). If we pass the creation date we will exit - // request merkle blocks from this point forward and exit the function. - badHeaders := 0 - for _, blockHeader := range msg.Headers { - if blockHeader.Timestamp.Before(ws.walletCreationDate.Add(-time.Hour * 24 * 7)) { - _, _, height, err := ws.chain.CommitHeader(*blockHeader) - if err != nil { - badHeaders++ - log.Errorf("Commit header error: %s", err.Error()) - } - log.Infof("Received header %s at height %d", blockHeader.BlockHash().String(), height) - } else { - log.Info("Switching to downloading merkle blocks") - locator := ws.chain.GetBlockLocator() - peer.PushGetBlocksMsg(locator, &ws.zeroHash) - return - } - } - // Usually the peer will send the header at the tip of the chain in each batch. This will trigger - // one commit error so we'll consider that acceptable, but anything more than that suggests misbehavior - // so we'll dump this peer. - if badHeaders > 1 { - log.Warningf("Disconnecting from peer %s because he sent us too many bad headers", peer) - peer.Disconnect() - return - } - - // Request the next batch of headers - locator := ws.chain.GetBlockLocator() - err := peer.PushGetHeadersMsg(locator, &ws.zeroHash) - if err != nil { - log.Warningf("Failed to send getheaders message to peer %s: %v", peer.Addr(), err) - return - } -} - -// handleMerkleBlockMsg handles merkle block messages from all peers. Merkle blocks are -// requested in response to inv packets both during initial sync and after. -func (ws *WireService) handleMerkleBlockMsg(bmsg *merkleBlockMsg) { - peer := bmsg.peer - - // We don't need to process blocks when we're syncing. They wont connect anyway - if peer != ws.syncPeer && !ws.Current() { - log.Warningf("Received block from %s when we aren't current", peer) - return - } - state, exists := ws.peerStates[peer] - if !exists { - log.Warningf("Received merkle block message from unknown peer %s", peer) - peer.Disconnect() - return - } - - // If we didn't ask for this block then the peer is misbehaving. - merkleBlock := bmsg.merkleBlock - header := merkleBlock.Header - blockHash := header.BlockHash() - if _, exists = state.requestedBlocks[blockHash]; !exists { - // The regression test intentionally sends some blocks twice - // to test duplicate block insertion fails. Don't disconnect - // the peer or ignore the block when we're in regression test - // mode in this case so the chain code is actually fed the - // duplicate blocks. - if ws.params.Name != chaincfg.RegressionNetParams.Name { - log.Warningf("Got unrequested block %v from %s -- "+ - "disconnecting", blockHash, peer.Addr()) - peer.Disconnect() - return - } - } - - // Remove block from request maps. Either chain will know about it and - // so we shouldn't have any more instances of trying to fetch it, or we - // will fail the insert and thus we'll retry next time we get an inv. - delete(state.requestedBlocks, blockHash) - delete(ws.requestedBlocks, blockHash) - - txids, err := checkMBlock(merkleBlock) - if err != nil { - log.Warningf("Peer %s sent an invalid MerkleBlock", peer) - peer.Disconnect() - return - } - - newBlock, reorg, newHeight, err := ws.chain.CommitHeader(header) - // If this is an orphan block which doesn't connect to the chain, it's possible - // that we might be synced on the longest chain, but not the most-work chain like - // we should be. To make sure this isn't the case, let's sync from the peer who - // sent us this orphan block. - if err == OrphanHeaderError && ws.Current() { - log.Debug("Received orphan header, checking peer for more blocks") - state.requestQueue = []*wire.InvVect{} - state.requestedBlocks = make(map[chainhash.Hash]struct{}) - ws.requestedBlocks = make(map[chainhash.Hash]struct{}) - ws.startSync(peer) - return - } else if err == OrphanHeaderError && !ws.Current() { - // The sync peer sent us an orphan header in the middle of a sync. This could - // just be the last block in the batch which represents the tip of the chain. - // In either case let's adjust the score for this peer downwards. If it goes - // negative it means he's slamming us with blocks that don't fit in our chain - // so disconnect. - state.blockScore-- - if state.blockScore < 0 { - log.Warningf("Disconnecting from peer %s because he sent us too many bad blocks", peer) - peer.Disconnect() - return - } - log.Warningf("Received unrequested block from peer %s", peer) - return - } else if err != nil { - log.Error(err) - return - } - state.blockScore++ - - if ws.Current() { - peer.UpdateLastBlockHeight(int32(newHeight)) - } - - // Request the transactions in this block - for _, txid := range txids { - ws.requestedTxns[*txid] = heightAndTime{newHeight, header.Timestamp} - limitMap(ws.requestedTxns, maxRequestedTxns) - state.requestedTxns[*txid] = heightAndTime{newHeight, header.Timestamp} - } - - // We can exit here if the block is already known - if !newBlock { - log.Debugf("Received duplicate block %s", blockHash.String()) - return - } - - log.Infof("Received merkle block %s at height %d", blockHash.String(), newHeight) - - // Check reorg - if reorg != nil && ws.Current() { - // Rollback the appropriate transactions in our database - err := ws.txStore.processReorg(reorg.height) - if err != nil { - log.Error(err) - } - // Set the reorg block as current best block in the header db - // This will cause a new chain sync from the reorg point - err = ws.chain.db.Put(*reorg, true) - if err != nil { - log.Error(err) - } - - // Clear request state for new sync - state.requestQueue = []*wire.InvVect{} - state.requestedBlocks = make(map[chainhash.Hash]struct{}) - ws.requestedBlocks = make(map[chainhash.Hash]struct{}) - } - - // Clear mempool - ws.mempool = make(map[chainhash.Hash]struct{}) - - // If we're not current and we've downloaded everything we've requested send another getblocks message. - // Otherwise we'll request the next block in the queue. - if !ws.Current() && len(state.requestQueue) == 0 { - locator := ws.chain.GetBlockLocator() - peer.PushGetBlocksMsg(locator, &ws.zeroHash) - log.Debug("Request queue at zero. Pushing new locator") - } else if !ws.Current() && len(state.requestQueue) > 0 { - iv := state.requestQueue[0] - iv.Type = wire.InvTypeFilteredBlock - state.requestQueue = state.requestQueue[1:] - state.requestedBlocks[iv.Hash] = struct{}{} - gdmsg2 := wire.NewMsgGetData() - gdmsg2.AddInvVect(iv) - peer.QueueMessage(gdmsg2, nil) - log.Debugf("Requesting block %s, len request queue: %d", iv.Hash.String(), len(state.requestQueue)) - } -} - -// handleInvMsg handles inv messages from all peers. -// We examine the inventory advertised by the remote peer and act accordingly. -func (ws *WireService) handleInvMsg(imsg *invMsg) { - peer := imsg.peer - state, exists := ws.peerStates[peer] - if !exists { - log.Warningf("Received inv message from unknown peer %s", peer) - return - } - - // Attempt to find the final block in the inventory list. There may - // not be one. - lastBlock := -1 - invVects := imsg.inv.InvList - for i := len(invVects) - 1; i >= 0; i-- { - if invVects[i].Type == wire.InvTypeBlock { - lastBlock = i - break - } - } - - // If this inv contains a block announcement, and this isn't coming from - // our current sync peer or we're current, then update the last - // announced block for this peer. We'll use this information later to - // update the heights of peers based on blocks we've accepted that they - // previously announced. - if lastBlock != -1 && (peer != ws.syncPeer || ws.Current()) { - peer.UpdateLastAnnouncedBlock(&invVects[lastBlock].Hash) - } - - // Ignore invs from peers that aren't the sync if we are not current. - // Helps prevent fetching a mass of orphans. - if peer != ws.syncPeer && !ws.Current() { - return - } - - // If our chain is current and a peer announces a block we already - // know of, then update their current block height. - if lastBlock != -1 && ws.Current() { - sh, err := ws.chain.GetHeader(&invVects[lastBlock].Hash) - if err == nil { - peer.UpdateLastBlockHeight(int32(sh.height)) - } - } - - // Request the advertised inventory if we don't already have it - gdmsg := wire.NewMsgGetData() - numRequested := 0 - shouldSendGetData := false - if len(state.requestQueue) == 0 { - shouldSendGetData = true - } - for _, iv := range invVects { - - // Add the inventory to the cache of known inventory - // for the peer. - peer.AddKnownInventory(iv) - - // Request the inventory if we don't already have it. - haveInv, err := ws.haveInventory(iv) - if err != nil { - log.Warningf("Unexpected failure when checking for "+ - "existing inventory during inv message "+ - "processing: %v", err) - continue - } - - switch iv.Type { - case wire.InvTypeFilteredBlock: - fallthrough - case wire.InvTypeBlock: - // Block inventory goes into a request queue to be downloaded - // one at a time. Sadly we can't batch these because the remote - // peer will not update the bloom filter until he's done processing - // the batch which means we will have a super high false positive rate. - if _, exists := ws.requestedBlocks[iv.Hash]; (!ws.Current() && !exists && !haveInv && shouldSendGetData) || ws.Current() { - iv.Type = wire.InvTypeFilteredBlock - state.requestQueue = append(state.requestQueue, iv) - } - case wire.InvTypeTx: - // Transaction inventory can be requested in batches - if _, exists := ws.requestedTxns[iv.Hash]; !exists && numRequested < wire.MaxInvPerMsg && !haveInv { - ws.requestedTxns[iv.Hash] = heightAndTime{0, time.Now()} // unconfirmed tx - limitMap(ws.requestedTxns, maxRequestedTxns) - state.requestedTxns[iv.Hash] = heightAndTime{0, time.Now()} - - gdmsg.AddInvVect(iv) - numRequested++ - } - default: - continue - } - } - - // Pop the first block off the queue and request it - if len(state.requestQueue) > 0 && (shouldSendGetData || ws.Current()) { - iv := state.requestQueue[0] - gdmsg.AddInvVect(iv) - if len(state.requestQueue) > 1 { - state.requestQueue = state.requestQueue[1:] - } else { - state.requestQueue = []*wire.InvVect{} - } - log.Debugf("Requesting block %s, len request queue: %d", iv.Hash.String(), len(state.requestQueue)) - state.requestedBlocks[iv.Hash] = struct{}{} - } - if len(gdmsg.InvList) > 0 { - peer.QueueMessage(gdmsg, nil) - } -} - -func (ws *WireService) handleTxMsg(tmsg *txMsg) { - tx := tmsg.tx - peer := tmsg.peer - txHash := tx.TxHash() - - state, exists := ws.peerStates[peer] - if !exists { - log.Warningf("Received tx message from unknown peer %s", peer) - return - } - ht, ok := state.requestedTxns[tx.TxHash()] - if !ok { - log.Warningf("Peer %s is sending us transactions we didn't request", peer) - peer.Disconnect() - return - } - ws.mempool[txHash] = struct{}{} - hits, err := ws.txStore.Ingest(tx, int32(ht.height), ht.timestamp) - if err != nil { - log.Errorf("Error ingesting tx: %s\n", err.Error()) - } - - // Remove transaction from request maps. Either the mempool/chain - // already knows about it and as such we shouldn't have any more - // instances of trying to fetch it, or we failed to insert and thus - // we'll retry next time we get an inv. - delete(state.requestedTxns, txHash) - delete(ws.requestedTxns, txHash) - - // If this transaction had no hits, update the peer's false positive counter - if hits == 0 { - log.Debugf("Tx %s from Peer%d had no hits, filter false positive.", txHash.String(), peer.ID()) - state.falsePositives++ - } else { - log.Noticef("Ingested new tx %s at height %d", txHash.String(), ht.height) - } - - // Check to see if false positives exceeds the maximum allowed. If so, reset and resend the filter. - if state.falsePositives > maxFalsePositives { - state.falsePositives = 0 - ws.updateFilterAndSend(peer) - } -} - -func (ws *WireService) Rebroadcast() { - // get all unconfirmed txs - invMsg, err := ws.txStore.GetPendingInv() - if err != nil { - log.Errorf("Rebroadcast error: %s", err.Error()) - } - // Nothing to broadcast, so don't - if len(invMsg.InvList) == 0 { - return - } - for peer := range ws.peerStates { - peer.QueueMessage(invMsg, nil) - } -} - -func (ws *WireService) updateFilterAndSend(peer *peerpkg.Peer) { - if ws.txStore != nil { - filter, err := ws.txStore.GimmeFilter() - if err == nil { - peer.QueueMessage(filter.MsgFilterLoad(), nil) - } else { - log.Errorf("Error loading bloom filter: %s", err.Error()) - } - } -} - -// handleUpdateFiltersMsg sends a filter update message to all peers -func (ws *WireService) handleUpdateFiltersMsg() { - for peer := range ws.peerStates { - ws.updateFilterAndSend(peer) - } -} - -// haveInventory returns whether or not the inventory represented by the passed -// inventory vector is known. This includes checking all of the various places -// inventory can be when it is in different states such as blocks that are part -// of the main chain, on a side chain, in the orphan pool, and transactions that -// are in the memory pool (either the main pool or orphan pool). -func (ws *WireService) haveInventory(invVect *wire.InvVect) (bool, error) { - switch invVect.Type { - case wire.InvTypeWitnessBlock: - fallthrough - case wire.InvTypeBlock: - // Ask chain if the block is known to it in any form (main - // chain, side chain, or orphan). - _, err := ws.chain.GetHeader(&invVect.Hash) - if err != nil { - return false, nil - } - return true, nil - case wire.InvTypeTx: - // Is transaction already in mempool - if _, ok := ws.mempool[invVect.Hash]; ok { - return true, nil - } - return false, nil - } - // The requested inventory is is an unsupported type, so just claim - // it is known to avoid requesting it. - return true, nil -} - -// limitMap is a helper function for maps that require a maximum limit by -// evicting a random transaction if adding a new value would cause it to -// overflow the maximum allowed. -func limitMap(i interface{}, limit int) { - m, ok := i.(map[chainhash.Hash]struct{}) - if ok { - if len(m)+1 > limit { - // Remove a random entry from the map. For most compilers, Go's - // range statement iterates starting at a random item although - // that is not 100% guaranteed by the spec. The iteration order - // is not important here because an adversary would have to be - // able to pull off preimage attacks on the hashing function in - // order to target eviction of specific entries anyways. - for txHash := range m { - delete(m, txHash) - return - } - } - return - } - n, ok := i.(map[chainhash.Hash]uint32) - if ok { - if len(n)+1 > limit { - for txHash := range n { - delete(n, txHash) - return - } - } - } -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/exchangerates/exchangerates.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/exchangerates/exchangerates.go deleted file mode 100644 index cc458e6662..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/exchangerates/exchangerates.go +++ /dev/null @@ -1,241 +0,0 @@ -package exchangerates - -import ( - "encoding/json" - "errors" - "fmt" - "golang.org/x/net/proxy" - "net" - "net/http" - "reflect" - "strconv" - "sync" - "time" -) - -type ExchangeRateProvider struct { - fetchUrl string - cache map[string]float64 - client *http.Client - decoder ExchangeRateDecoder -} - -type ExchangeRateDecoder interface { - decode(dat interface{}, cache map[string]float64) (err error) -} - -type OpenBazaarDecoder struct{} -type KrakenDecoder struct{} -type BitfinexDecoder struct{} -type BittrexDecoder struct{} -type PoloniexDecoder struct{} - -type BitcoinCashPriceFetcher struct { - sync.Mutex - cache map[string]float64 - providers []*ExchangeRateProvider -} - -func NewBitcoinCashPriceFetcher(dialer proxy.Dialer) *BitcoinCashPriceFetcher { - b := BitcoinCashPriceFetcher{ - cache: make(map[string]float64), - } - dial := net.Dial - if dialer != nil { - dial = dialer.Dial - } - tbTransport := &http.Transport{Dial: dial} - client := &http.Client{Transport: tbTransport, Timeout: time.Minute} - - b.providers = []*ExchangeRateProvider{ - {"https://ticker.openbazaar.org/api", b.cache, client, OpenBazaarDecoder{}}, - {"https://poloniex.com/public?command=returnTicker", b.cache, client, PoloniexDecoder{}}, - {"https://api.kraken.com/0/public/Ticker?pair=BCHUSD", b.cache, client, KrakenDecoder{}}, - } - return &b -} - -func (b *BitcoinCashPriceFetcher) GetExchangeRate(currencyCode string) (float64, error) { - b.Lock() - defer b.Unlock() - price, ok := b.cache[currencyCode] - if !ok { - return 0, errors.New("Currency not tracked") - } - return price, nil -} - -func (b *BitcoinCashPriceFetcher) GetLatestRate(currencyCode string) (float64, error) { - b.fetchCurrentRates() - b.Lock() - defer b.Unlock() - price, ok := b.cache[currencyCode] - if !ok { - return 0, errors.New("Currency not tracked") - } - return price, nil -} - -func (b *BitcoinCashPriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, error) { - if !cacheOK { - err := b.fetchCurrentRates() - if err != nil { - return nil, err - } - } - b.Lock() - defer b.Unlock() - return b.cache, nil -} - -func (b *BitcoinCashPriceFetcher) UnitsPerCoin() int { - return 100000000 -} - -func (b *BitcoinCashPriceFetcher) fetchCurrentRates() error { - b.Lock() - defer b.Unlock() - for _, provider := range b.providers { - err := provider.fetch() - if err == nil { - return nil - } - fmt.Println(err) - } - return errors.New("All exchange rate API queries failed") -} - -func (b *BitcoinCashPriceFetcher) Run() { - b.fetchCurrentRates() - ticker := time.NewTicker(time.Minute * 15) - for range ticker.C { - b.fetchCurrentRates() - } -} - -func (provider *ExchangeRateProvider) fetch() (err error) { - if len(provider.fetchUrl) == 0 { - err = errors.New("Provider has no fetchUrl") - return err - } - resp, err := provider.client.Get(provider.fetchUrl) - if err != nil { - return err - } - decoder := json.NewDecoder(resp.Body) - var dataMap interface{} - err = decoder.Decode(&dataMap) - if err != nil { - return err - } - return provider.decoder.decode(dataMap, provider.cache) -} - -func (b OpenBazaarDecoder) decode(dat interface{}, cache map[string]float64) (err error) { - data, ok := dat.(map[string]interface{}) - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed") - } - bch, ok := data["BCH"] - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed, missing 'BCH' field") - } - val, ok := bch.(map[string]interface{}) - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed") - } - bchRate, ok := val["last"].(float64) - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed, missing 'last' (float) field") - } - for k, v := range data { - if k != "timestamp" { - val, ok := v.(map[string]interface{}) - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed") - } - price, ok := val["last"].(float64) - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed, missing 'last' (float) field") - } - cache[k] = price * (1 / bchRate) - } - } - return nil -} - -func (b KrakenDecoder) decode(dat interface{}, cache map[string]float64) (err error) { - obj, ok := dat.(map[string]interface{}) - if !ok { - return errors.New("KrackenDecoder type assertion failure") - } - result, ok := obj["result"] - if !ok { - return errors.New("KrakenDecoder: field `result` not found") - } - resultMap, ok := result.(map[string]interface{}) - if !ok { - return errors.New("KrackenDecoder type assertion failure") - } - pair, ok := resultMap["BCHUSD"] - if !ok { - return errors.New("KrakenDecoder: field `BCHUSD` not found") - } - pairMap, ok := pair.(map[string]interface{}) - if !ok { - return errors.New("KrackenDecoder type assertion failure") - } - c, ok := pairMap["c"] - if !ok { - return errors.New("KrakenDecoder: field `c` not found") - } - cList, ok := c.([]interface{}) - if !ok { - return errors.New("KrackenDecoder type assertion failure") - } - rateStr, ok := cList[0].(string) - if !ok { - return errors.New("KrackenDecoder type assertion failure") - } - price, err := strconv.ParseFloat(rateStr, 64) - if err != nil { - return err - } - rate := price - - if rate == 0 { - return errors.New("Bitcoin-BitcoinCash price data not available") - } - cache["USD"] = rate - return nil -} - -func (b PoloniexDecoder) decode(dat interface{}, cache map[string]float64) (err error) { - data, ok := dat.(map[string]interface{}) - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed") - } - var rate float64 - v, ok := data["USDT_BCH"] - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed") - } - val, ok := v.(map[string]interface{}) - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed") - } - s, ok := val["last"].(string) - if !ok { - return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed, missing 'last' (string) field") - } - price, err := strconv.ParseFloat(s, 64) - if err != nil { - return err - } - rate = price - if rate == 0 { - return errors.New("BitcoinCash price data not available") - } - cache["USD"] = rate - return nil -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/fees.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/fees.go deleted file mode 100644 index c9e06fe8e3..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/fees.go +++ /dev/null @@ -1,103 +0,0 @@ -package bitcoincash - -import ( - "github.com/OpenBazaar/wallet-interface" - "net/http" - "time" -) - -type httpClient interface { - Get(string) (*http.Response, error) -} - -type feeCache struct { - fees *Fees - lastUpdated time.Time -} - -type Fees struct { - FastestFee uint64 - HalfHourFee uint64 - HourFee uint64 -} - -type FeeProvider struct { - maxFee uint64 - priorityFee uint64 - normalFee uint64 - economicFee uint64 - - exchangeRates wallet.ExchangeRates - - cache *feeCache -} - -// We will target a fee per byte such that it would equal -// 1 USD cent for economic, 5 USD cents for normal and -// 10 USD cents for priority for a median (226 byte) transaction. -type FeeTarget int - -const ( - EconomicTarget FeeTarget = 1 - NormalTarget FeeTarget = 5 - PriorityTarget FeeTarget = 10 -) - -func NewFeeProvider(maxFee, priorityFee, normalFee, economicFee uint64, exchangeRates wallet.ExchangeRates) *FeeProvider { - return &FeeProvider{ - maxFee: maxFee, - priorityFee: priorityFee, - normalFee: normalFee, - economicFee: economicFee, - exchangeRates: exchangeRates, - cache: new(feeCache), - } -} - -func (fp *FeeProvider) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 { - defaultFee := func() uint64 { - switch feeLevel { - case wallet.PRIOIRTY: - return fp.priorityFee - case wallet.NORMAL: - return fp.normalFee - case wallet.ECONOMIC: - return fp.economicFee - case wallet.FEE_BUMP: - return fp.priorityFee * 2 - default: - return fp.normalFee - } - } - if fp.exchangeRates == nil { - return defaultFee() - } - - rate, err := fp.exchangeRates.GetLatestRate("USD") - if err != nil || rate == 0 { - log.Errorf("Error using exchange rate to calculate fee: %s\n", err.Error()) - return defaultFee() - } - - var target FeeTarget - switch feeLevel { - case wallet.PRIOIRTY: - target = PriorityTarget - case wallet.NORMAL: - target = NormalTarget - case wallet.ECONOMIC: - target = EconomicTarget - case wallet.FEE_BUMP: - target = PriorityTarget * 2 - default: - target = NormalTarget - } - - feePerByte := (((float64(target) / 100) / rate) * 100000000) / 226 - - if uint64(feePerByte) > fp.maxFee { - return fp.maxFee - } - - return uint64(feePerByte) -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/headers.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/headers.go deleted file mode 100644 index 7b8a949943..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/headers.go +++ /dev/null @@ -1,456 +0,0 @@ -package bitcoincash - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "math/big" - "path" - "sort" - "sync" - - "github.com/boltdb/bolt" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "github.com/cevaris/ordered_map" - "strings" -) - -const ( - MAX_HEADERS = 2000 - CACHE_SIZE = 200 -) - -// Database interface for storing block headers -type Headers interface { - // Put a block header to the database - // Total work and height are required to be calculated prior to insertion - // If this is the new best header, the chain tip should also be updated - Put(header StoredHeader, newBestHeader bool) error - - // Delete all headers after the MAX_HEADERS most recent - Prune() error - - // Delete all headers after the given height - DeleteAfter(height uint32) error - - // Returns all information about the previous header - GetPreviousHeader(header wire.BlockHeader) (StoredHeader, error) - - // Grab a header given hash - GetHeader(hash chainhash.Hash) (StoredHeader, error) - - // Retrieve the best header from the database - GetBestHeader() (StoredHeader, error) - - // Get the height of chain - Height() (uint32, error) - - // Cleanly close the db - Close() - - // Print all headers - Print(io.Writer) -} - -type StoredHeader struct { - header wire.BlockHeader - height uint32 - totalWork *big.Int -} - -// HeaderDB implements Headers using bolt DB -type HeaderDB struct { - lock *sync.Mutex - db *bolt.DB - filePath string - bestCache *StoredHeader - cache *HeaderCache -} - -var ( - BKTHeaders = []byte("Headers") - BKTChainTip = []byte("ChainTip") - KEYChainTip = []byte("ChainTip") -) - -func NewHeaderDB(filePath string) (*HeaderDB, error) { - if !strings.Contains(filePath, ".bin") { - filePath = path.Join(filePath, "headers.bin") - } - h := new(HeaderDB) - db, err := bolt.Open(filePath, 0644, &bolt.Options{InitialMmapSize: 5000000}) - if err != nil { - return nil, err - } - h.db = db - h.lock = new(sync.Mutex) - h.filePath = filePath - h.cache = &HeaderCache{ordered_map.NewOrderedMap(), sync.RWMutex{}, CACHE_SIZE} - - db.Update(func(btx *bolt.Tx) error { - _, err := btx.CreateBucketIfNotExists(BKTHeaders) - if err != nil { - return err - } - _, err = btx.CreateBucketIfNotExists(BKTChainTip) - if err != nil { - return err - } - return nil - }) - - h.initializeCache() - return h, nil -} - -func (h *HeaderDB) Put(sh StoredHeader, newBestHeader bool) error { - h.lock.Lock() - h.cache.Set(sh) - if newBestHeader { - h.bestCache = &sh - } - h.lock.Unlock() - go func() { - err := h.putToDB(sh, newBestHeader) - if err != nil { - log.Error(err) - } - }() - return nil -} - -func (h *HeaderDB) put(sh StoredHeader, newBestHeader bool) error { - h.lock.Lock() - h.cache.Set(sh) - if newBestHeader { - h.bestCache = &sh - } - h.lock.Unlock() - err := h.putToDB(sh, newBestHeader) - if err != nil { - log.Error(err) - } - return nil -} - -func (h *HeaderDB) putToDB(sh StoredHeader, newBestHeader bool) error { - h.lock.Lock() - defer h.lock.Unlock() - return h.db.Update(func(btx *bolt.Tx) error { - hdrs := btx.Bucket(BKTHeaders) - ser, err := serializeHeader(sh) - if err != nil { - return err - } - hash := sh.header.BlockHash() - err = hdrs.Put(hash.CloneBytes(), ser) - if err != nil { - return err - } - if newBestHeader { - tip := btx.Bucket(BKTChainTip) - err = tip.Put(KEYChainTip, ser) - if err != nil { - return err - } - } - return nil - }) -} - -func (h *HeaderDB) Prune() error { - h.lock.Lock() - defer h.lock.Unlock() - return h.db.Update(func(btx *bolt.Tx) error { - hdrs := btx.Bucket(BKTHeaders) - numHeaders := hdrs.Stats().KeyN - tip := btx.Bucket(BKTChainTip) - b := tip.Get(KEYChainTip) - if b == nil { - return errors.New("ChainTip not set") - } - sh, err := deserializeHeader(b) - if err != nil { - return err - } - height := sh.height - if numHeaders > MAX_HEADERS { - var toDelete [][]byte - pruneHeight := height - 2000 - err := hdrs.ForEach(func(k, v []byte) error { - sh, err := deserializeHeader(v) - if err != nil { - return err - } - if sh.height <= pruneHeight { - toDelete = append(toDelete, k) - } - return nil - }) - if err != nil { - return err - } - for _, k := range toDelete { - err := hdrs.Delete(k) - if err != nil { - return err - } - } - - } - return nil - }) -} - -func (h *HeaderDB) DeleteAfter(height uint32) error { - h.lock.Lock() - defer h.lock.Unlock() - return h.db.Update(func(btx *bolt.Tx) error { - hdrs := btx.Bucket(BKTHeaders) - var toDelete [][]byte - err := hdrs.ForEach(func(k, v []byte) error { - sh, err := deserializeHeader(v) - if err != nil { - return err - } - if sh.height > height { - toDelete = append(toDelete, k) - } - return nil - }) - if err != nil { - return err - } - for _, k := range toDelete { - err := hdrs.Delete(k) - if err != nil { - return err - } - } - return nil - }) -} - -func (h *HeaderDB) GetPreviousHeader(header wire.BlockHeader) (sh StoredHeader, err error) { - hash := header.PrevBlock - return h.GetHeader(hash) -} - -func (h *HeaderDB) GetHeader(hash chainhash.Hash) (sh StoredHeader, err error) { - h.lock.Lock() - defer h.lock.Unlock() - cachedHeader, cerr := h.cache.Get(hash) - if cerr == nil { - return cachedHeader, nil - } - err = h.db.View(func(btx *bolt.Tx) error { - hdrs := btx.Bucket(BKTHeaders) - b := hdrs.Get(hash.CloneBytes()) - if b == nil { - return errors.New("Header does not exist in database") - } - sh, err = deserializeHeader(b) - if err != nil { - return err - } - return nil - }) - if err != nil { - return sh, err - } - return sh, nil -} - -func (h *HeaderDB) GetBestHeader() (sh StoredHeader, err error) { - h.lock.Lock() - defer h.lock.Unlock() - if h.bestCache != nil { - best := h.bestCache - return *best, nil - } - err = h.db.View(func(btx *bolt.Tx) error { - tip := btx.Bucket(BKTChainTip) - b := tip.Get(KEYChainTip) - if b == nil { - return errors.New("ChainTip not set") - } - sh, err = deserializeHeader(b) - if err != nil { - return err - } - return nil - }) - if err != nil { - return sh, err - } - return sh, nil -} - -func (h *HeaderDB) Height() (uint32, error) { - h.lock.Lock() - defer h.lock.Unlock() - if h.bestCache != nil { - return h.bestCache.height, nil - } - var height uint32 - err := h.db.View(func(btx *bolt.Tx) error { - tip := btx.Bucket(BKTChainTip) - sh, err := deserializeHeader(tip.Get(KEYChainTip)) - if err != nil { - return err - } - height = sh.height - return nil - }) - if err != nil { - return height, err - } - return height, nil -} - -func (h *HeaderDB) Print(w io.Writer) { - h.lock.Lock() - defer h.lock.Unlock() - m := make(map[float64][]string) - h.db.View(func(tx *bolt.Tx) error { - // Assume bucket exists and has keys - bkt := tx.Bucket(BKTHeaders) - bkt.ForEach(func(k, v []byte) error { - sh, _ := deserializeHeader(v) - h := float64(sh.height) - _, ok := m[h] - if ok { - for { - h += .1 - _, ok := m[h] - if !ok { - break - } - } - } - m[h] = []string{sh.header.BlockHash().String(), sh.header.PrevBlock.String()} - return nil - }) - - return nil - }) - var keys []float64 - for k := range m { - keys = append(keys, float64(k)) - } - sort.Float64s(keys) - for _, k := range keys { - fmt.Fprintf(w, "Height: %.1f, Hash: %s, Parent: %s\n", k, m[k][0], m[k][1]) - } -} - -func (h *HeaderDB) initializeCache() { - best, err := h.GetBestHeader() - if err != nil { - return - } - h.bestCache = &best - headers := []StoredHeader{best} - for i := 0; i < 99; i++ { - sh, err := h.GetPreviousHeader(best.header) - if err != nil { - break - } - headers = append(headers, sh) - } - for i := len(headers) - 1; i >= 0; i-- { - h.cache.Set(headers[i]) - } -} - -func (h *HeaderDB) Close() { - h.lock.Lock() - h.db.Close() -} - -/*----- header serialization ------- */ -/* byteLength desc at offset - 80 header 0 - 4 height 80 - 32 total work 84 -*/ -func serializeHeader(sh StoredHeader) ([]byte, error) { - var buf bytes.Buffer - err := sh.header.Serialize(&buf) - if err != nil { - return nil, err - } - err = binary.Write(&buf, binary.BigEndian, sh.height) - if err != nil { - return nil, err - } - biBytes := sh.totalWork.Bytes() - pad := make([]byte, 32-len(biBytes)) - serializedBI := append(pad, biBytes...) - buf.Write(serializedBI) - return buf.Bytes(), nil -} - -func deserializeHeader(b []byte) (sh StoredHeader, err error) { - r := bytes.NewReader(b) - hdr := new(wire.BlockHeader) - err = hdr.Deserialize(r) - if err != nil { - return sh, err - } - var height uint32 - err = binary.Read(r, binary.BigEndian, &height) - if err != nil { - return sh, err - } - biBytes := make([]byte, 32) - _, err = r.Read(biBytes) - if err != nil { - return sh, err - } - bi := new(big.Int) - bi.SetBytes(biBytes) - sh = StoredHeader{ - header: *hdr, - height: height, - totalWork: bi, - } - return sh, nil -} - -type HeaderCache struct { - headers *ordered_map.OrderedMap - sync.RWMutex - cacheSize int -} - -func (h *HeaderCache) pop() { - iter := h.headers.IterFunc() - k, ok := iter() - if ok { - h.headers.Delete(k.Key) - } -} - -func (h *HeaderCache) Set(sh StoredHeader) { - h.Lock() - defer h.Unlock() - if h.headers.Len() > h.cacheSize { - h.pop() - } - hash := sh.header.BlockHash() - h.headers.Set(hash.String(), sh) -} - -func (h *HeaderCache) Get(hash chainhash.Hash) (StoredHeader, error) { - h.RLock() - defer h.RUnlock() - sh, ok := h.headers.Get(hash.String()) - if !ok { - return StoredHeader{}, errors.New("Not found") - } - return sh.(StoredHeader), nil -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/keys.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/keys.go deleted file mode 100644 index 14f5af1c79..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/keys.go +++ /dev/null @@ -1,189 +0,0 @@ -package bitcoincash - -import ( - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/chaincfg" - hd "github.com/btcsuite/btcutil/hdkeychain" - "github.com/btcsuite/goleveldb/leveldb/errors" -) - -const LOOKAHEADWINDOW = 100 - -type KeyManager struct { - datastore wallet.Keys - params *chaincfg.Params - - internalKey *hd.ExtendedKey - externalKey *hd.ExtendedKey -} - -func NewKeyManager(db wallet.Keys, params *chaincfg.Params, masterPrivKey *hd.ExtendedKey) (*KeyManager, error) { - internal, external, err := Bip44Derivation(masterPrivKey) - if err != nil { - return nil, err - } - km := &KeyManager{ - datastore: db, - params: params, - internalKey: internal, - externalKey: external, - } - if err := km.lookahead(); err != nil { - return nil, err - } - return km, nil -} - -// m / purpose' / coin_type' / account' / change / address_index -func Bip44Derivation(masterPrivKey *hd.ExtendedKey) (internal, external *hd.ExtendedKey, err error) { - // Purpose = bip44 - fourtyFour, err := masterPrivKey.Child(hd.HardenedKeyStart + 44) - if err != nil { - return nil, nil, err - } - // Cointype = bitcoin - bitcoin, err := fourtyFour.Child(hd.HardenedKeyStart + 145) - if err != nil { - return nil, nil, err - } - // Account = 0 - account, err := bitcoin.Child(hd.HardenedKeyStart + 0) - if err != nil { - return nil, nil, err - } - // Change(0) = external - external, err = account.Child(0) - if err != nil { - return nil, nil, err - } - // Change(1) = internal - internal, err = account.Child(1) - if err != nil { - return nil, nil, err - } - return internal, external, nil -} - -func (km *KeyManager) GetCurrentKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, error) { - i, err := km.datastore.GetUnused(purpose) - if err != nil { - return nil, err - } - if len(i) == 0 { - return nil, errors.New("No unused keys in database") - } - return km.generateChildKey(purpose, uint32(i[0])) -} - -func (km *KeyManager) GetFreshKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, error) { - index, _, err := km.datastore.GetLastKeyIndex(purpose) - var childKey *hd.ExtendedKey - if err != nil { - index = 0 - } else { - index += 1 - } - for { - // There is a small possibility bip32 keys can be invalid. The procedure in such cases - // is to discard the key and derive the next one. This loop will continue until a valid key - // is derived. - childKey, err = km.generateChildKey(purpose, uint32(index)) - if err == nil { - break - } - index += 1 - } - addr, err := childKey.Address(km.params) - if err != nil { - return nil, err - } - p := wallet.KeyPath{wallet.KeyPurpose(purpose), index} - err = km.datastore.Put(addr.ScriptAddress(), p) - if err != nil { - return nil, err - } - return childKey, nil -} - -func (km *KeyManager) GetKeys() []*hd.ExtendedKey { - var keys []*hd.ExtendedKey - keyPaths, err := km.datastore.GetAll() - if err != nil { - return keys - } - for _, path := range keyPaths { - k, err := km.generateChildKey(path.Purpose, uint32(path.Index)) - if err != nil { - continue - } - keys = append(keys, k) - } - imported, err := km.datastore.GetImported() - if err != nil { - return keys - } - for _, key := range imported { - hdKey := hd.NewExtendedKey( - km.params.HDPrivateKeyID[:], - key.Serialize(), - make([]byte, 32), - []byte{0x00, 0x00, 0x00, 0x00}, - 0, - 0, - true) - keys = append(keys, hdKey) - } - return keys -} - -func (km *KeyManager) GetKeyForScript(scriptAddress []byte) (*hd.ExtendedKey, error) { - keyPath, err := km.datastore.GetPathForKey(scriptAddress) - if err != nil { - key, err := km.datastore.GetKey(scriptAddress) - if err != nil { - return nil, err - } - hdKey := hd.NewExtendedKey( - km.params.HDPrivateKeyID[:], - key.Serialize(), - make([]byte, 32), - []byte{0x00, 0x00, 0x00, 0x00}, - 0, - 0, - true) - return hdKey, nil - } - return km.generateChildKey(keyPath.Purpose, uint32(keyPath.Index)) -} - -// Mark the given key as used and extend the lookahead window -func (km *KeyManager) MarkKeyAsUsed(scriptAddress []byte) error { - if err := km.datastore.MarkKeyAsUsed(scriptAddress); err != nil { - return err - } - return km.lookahead() -} - -func (km *KeyManager) generateChildKey(purpose wallet.KeyPurpose, index uint32) (*hd.ExtendedKey, error) { - if purpose == wallet.EXTERNAL { - return km.externalKey.Child(index) - } else if purpose == wallet.INTERNAL { - return km.internalKey.Child(index) - } - return nil, errors.New("Unknown key purpose") -} - -func (km *KeyManager) lookahead() error { - lookaheadWindows := km.datastore.GetLookaheadWindows() - for purpose, size := range lookaheadWindows { - if size < LOOKAHEADWINDOW { - for i := 0; i < (LOOKAHEADWINDOW - size); i++ { - _, err := km.GetFreshKey(purpose) - if err != nil { - return err - } - } - } - } - return nil -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/makefile b/vendor/github.com/cpacia/BitcoinCash-Wallet/makefile deleted file mode 100644 index 30265908dc..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/makefile +++ /dev/null @@ -1,8 +0,0 @@ -install: - cd cmd/bitcoincash && go install - -protos: - cd api/pb && protoc --go_out=plugins=grpc:. api.proto - -resources: - cd gui && go-bindata -o resources.go -pkg gui resources/... diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/mblock.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/mblock.go deleted file mode 100644 index ac60997196..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/mblock.go +++ /dev/null @@ -1,176 +0,0 @@ -package bitcoincash - -import ( - "fmt" - - "errors" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" -) - -func MakeMerkleParent(left *chainhash.Hash, right *chainhash.Hash) (*chainhash.Hash, error) { - // dupes can screw things up; CVE-2012-2459. check for them - if left != nil && right != nil && left.IsEqual(right) { - return nil, errors.New("DUP HASH CRASH") - } - // if left child is nil, output nil. Need this for hard mode. - if left == nil { - return nil, errors.New("Left child is nil") - } - // if right is nil, hash left with itself - if right == nil { - right = left - } - - // Concatenate the left and right nodes - var sha [64]byte - copy(sha[:32], left[:]) - copy(sha[32:], right[:]) - - newSha := chainhash.DoubleHashH(sha[:]) - return &newSha, nil -} - -type merkleNode struct { - p uint32 // position in the binary tree - h *chainhash.Hash // hash -} - -// given n merkle leaves, how deep is the tree? -// iterate shifting left until greater than n -func treeDepth(n uint32) (e uint8) { - for ; (1 << e) < n; e++ { - } - return -} - -// smallest power of 2 that can contain n -func nextPowerOfTwo(n uint32) uint32 { - return 1 << treeDepth(n) // 2^exponent -} - -// check if a node is populated based on node position and size of tree -func inDeadZone(pos, size uint32) bool { - msb := nextPowerOfTwo(size) - last := size - 1 // last valid position is 1 less than size - if pos > (msb<<1)-2 { // greater than root; not even in the tree - log.Debug(" ?? greater than root ") - return true - } - h := msb - for pos >= h { - h = h>>1 | msb - last = last>>1 | msb - } - return pos > last -} - -// take in a merkle block, parse through it, and return txids indicated -// If there's any problem return an error. Checks self-consistency only. -// doing it with a stack instead of recursion. Because... -// OK I don't know why I'm just not in to recursion OK? -func checkMBlock(m *wire.MsgMerkleBlock) ([]*chainhash.Hash, error) { - if m.Transactions == 0 { - return nil, fmt.Errorf("No transactions in merkleblock") - } - if len(m.Flags) == 0 { - return nil, fmt.Errorf("No flag bits") - } - var s []merkleNode // the stack - var r []*chainhash.Hash // slice to return; txids we care about - - // set initial position to root of merkle tree - msb := nextPowerOfTwo(m.Transactions) // most significant bit possible - pos := (msb << 1) - 2 // current position in tree - - var i uint8 // position in the current flag byte - var tip int - // main loop - for { - tip = len(s) - 1 // slice position of stack tip - // First check if stack operations can be performed - // is stack one filled item? that's complete. - if tip == 0 && s[0].h != nil { - if s[0].h.IsEqual(&m.Header.MerkleRoot) { - return r, nil - } - return nil, fmt.Errorf("computed root %s but expect %s\n", - s[0].h.String(), m.Header.MerkleRoot.String()) - } - // is current position in the tree's dead zone? partial parent - if inDeadZone(pos, m.Transactions) { - // create merkle parent from single side (left) - h, err := MakeMerkleParent(s[tip].h, nil) - if err != nil { - return r, err - } - s[tip-1].h = h - s = s[:tip] // remove 1 from stack - pos = s[tip-1].p | 1 // move position to parent's sibling - continue - } - // does stack have 3+ items? and are last 2 items filled? - if tip > 1 && s[tip-1].h != nil && s[tip].h != nil { - //fmt.Printf("nodes %d and %d combine into %d\n", - // s[tip-1].p, s[tip].p, s[tip-2].p) - // combine two filled nodes into parent node - h, err := MakeMerkleParent(s[tip-1].h, s[tip].h) - if err != nil { - return r, err - } - s[tip-2].h = h - // remove children - s = s[:tip-1] - // move position to parent's sibling - pos = s[tip-2].p | 1 - continue - } - - // no stack ops to perform, so make new node from message hashes - if len(m.Hashes) == 0 { - return nil, fmt.Errorf("Ran out of hashes at position %d.", pos) - } - if len(m.Flags) == 0 { - return nil, fmt.Errorf("Ran out of flag bits.") - } - var n merkleNode // make new node - n.p = pos // set current position for new node - - if pos&msb != 0 { // upper non-txid hash - if m.Flags[0]&(1<>1 | msb - } else { // left side, go to sibling - pos |= 1 - } - } else { // flag bit says skip; put empty on stack and descend - pos = (pos ^ msb) << 1 // descend to left - } - s = append(s, n) // push new node on stack - } else { // bottom row txid; flag bit indicates tx of interest - if pos >= m.Transactions { - // this can't happen because we check deadzone above... - return nil, fmt.Errorf("got into an invalid txid node") - } - n.h = m.Hashes[0] // copy hash from message - m.Hashes = m.Hashes[1:] // pop off message - if m.Flags[0]&(1< i { - i = key.path.Index - used = key.used - } - } - if i == -1 { - return i, used, errors.New("No saved keys") - } - return i, used, nil -} - -func (m *mockKeyStore) GetPathForKey(scriptAddress []byte) (wallet.KeyPath, error) { - key, ok := m.keys[hex.EncodeToString(scriptAddress)] - if !ok || key.path.Index == -1 { - return wallet.KeyPath{}, errors.New("key does not exist") - } - return key.path, nil -} - -func (m *mockKeyStore) GetKey(scriptAddress []byte) (*btcec.PrivateKey, error) { - for _, k := range m.keys { - if k.path.Index == -1 && bytes.Equal(scriptAddress, k.scriptAddress) { - return k.key, nil - } - } - return nil, errors.New("Not found") -} - -func (m *mockKeyStore) GetImported() ([]*btcec.PrivateKey, error) { - var keys []*btcec.PrivateKey - for _, k := range m.keys { - if k.path.Index == -1 { - keys = append(keys, k.key) - } - } - return keys, nil -} - -func (m *mockKeyStore) GetUnused(purpose wallet.KeyPurpose) ([]int, error) { - var i []int - for _, key := range m.keys { - if !key.used && key.path.Purpose == purpose { - i = append(i, key.path.Index) - } - } - sort.Ints(i) - return i, nil -} - -func (m *mockKeyStore) GetAll() ([]wallet.KeyPath, error) { - var kp []wallet.KeyPath - for _, key := range m.keys { - kp = append(kp, key.path) - } - return kp, nil -} - -func (m *mockKeyStore) GetLookaheadWindows() map[wallet.KeyPurpose]int { - internalLastUsed := -1 - externalLastUsed := -1 - for _, key := range m.keys { - if key.path.Purpose == wallet.INTERNAL && key.used && key.path.Index > internalLastUsed { - internalLastUsed = key.path.Index - } - if key.path.Purpose == wallet.EXTERNAL && key.used && key.path.Index > externalLastUsed { - externalLastUsed = key.path.Index - } - } - internalUnused := 0 - externalUnused := 0 - for _, key := range m.keys { - if key.path.Purpose == wallet.INTERNAL && !key.used && key.path.Index > internalLastUsed { - internalUnused++ - } - if key.path.Purpose == wallet.EXTERNAL && !key.used && key.path.Index > externalLastUsed { - externalUnused++ - } - } - mp := make(map[wallet.KeyPurpose]int) - mp[wallet.INTERNAL] = internalUnused - mp[wallet.EXTERNAL] = externalUnused - return mp -} - -type mockUtxoStore struct { - utxos map[string]*wallet.Utxo -} - -func (m *mockUtxoStore) Put(utxo wallet.Utxo) error { - key := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) - m.utxos[key] = &utxo - return nil -} - -func (m *mockUtxoStore) GetAll() ([]wallet.Utxo, error) { - var utxos []wallet.Utxo - for _, v := range m.utxos { - utxos = append(utxos, *v) - } - return utxos, nil -} - -func (m *mockUtxoStore) SetWatchOnly(utxo wallet.Utxo) error { - key := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) - u, ok := m.utxos[key] - if !ok { - return errors.New("Not found") - } - u.WatchOnly = true - return nil -} - -func (m *mockUtxoStore) Delete(utxo wallet.Utxo) error { - key := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index)) - _, ok := m.utxos[key] - if !ok { - return errors.New("Not found") - } - delete(m.utxos, key) - return nil -} - -type mockStxoStore struct { - stxos map[string]*wallet.Stxo -} - -func (m *mockStxoStore) Put(stxo wallet.Stxo) error { - m.stxos[stxo.SpendTxid.String()] = &stxo - return nil -} - -func (m *mockStxoStore) GetAll() ([]wallet.Stxo, error) { - var stxos []wallet.Stxo - for _, v := range m.stxos { - stxos = append(stxos, *v) - } - return stxos, nil -} - -func (m *mockStxoStore) Delete(stxo wallet.Stxo) error { - _, ok := m.stxos[stxo.SpendTxid.String()] - if !ok { - return errors.New("Not found") - } - delete(m.stxos, stxo.SpendTxid.String()) - return nil -} - -type txnStoreEntry struct { - txn []byte - txid string - value int - height int - timestamp time.Time - watchOnly bool -} - -type mockTxnStore struct { - txns map[string]*txnStoreEntry -} - -func (m *mockTxnStore) Put(txn []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error { - m.txns[txid] = &txnStoreEntry{ - txn: txn, - txid: txid, - value: value, - height: height, - timestamp: timestamp, - watchOnly: watchOnly, - } - return nil -} - -func (m *mockTxnStore) Get(txid chainhash.Hash) (wallet.Txn, error) { - t, ok := m.txns[txid.String()] - if !ok { - return wallet.Txn{}, errors.New("Not found") - } - return wallet.Txn{ - Txid: t.txid, - Value: int64(t.value), - Height: int32(t.height), - Timestamp: t.timestamp, - WatchOnly: t.watchOnly, - Bytes: t.txn, - }, nil -} - -func (m *mockTxnStore) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) { - var txns []wallet.Txn - for _, t := range m.txns { - txn := wallet.Txn{ - Txid: t.txid, - Value: int64(t.value), - Height: int32(t.height), - Timestamp: t.timestamp, - WatchOnly: t.watchOnly, - Bytes: t.txn, - } - txns = append(txns, txn) - } - return txns, nil -} - -func (m *mockTxnStore) UpdateHeight(txid chainhash.Hash, height int, timestamp time.Time) error { - txn, ok := m.txns[txid.String()] - if !ok { - return errors.New("Not found") - } - txn.height = height - txn.timestamp = timestamp - return nil -} - -func (m *mockTxnStore) Delete(txid *chainhash.Hash) error { - _, ok := m.txns[txid.String()] - if !ok { - return errors.New("Not found") - } - delete(m.txns, txid.String()) - return nil -} - -type mockWatchedScriptsStore struct { - scripts map[string][]byte -} - -func (m *mockWatchedScriptsStore) Put(scriptPubKey []byte) error { - m.scripts[hex.EncodeToString(scriptPubKey)] = scriptPubKey - return nil -} - -func (m *mockWatchedScriptsStore) GetAll() ([][]byte, error) { - var ret [][]byte - for _, b := range m.scripts { - ret = append(ret, b) - } - return ret, nil -} - -func (m *mockWatchedScriptsStore) Delete(scriptPubKey []byte) error { - enc := hex.EncodeToString(scriptPubKey) - _, ok := m.scripts[enc] - if !ok { - return errors.New("Not found") - } - delete(m.scripts, enc) - return nil -} - -func TestUtxo_IsEqual(t *testing.T) { - h, err := chainhash.NewHashFromStr("16bed6368b8b1542cd6eb87f5bc20dc830b41a2258dde40438a75fa701d24e9a") - if err != nil { - t.Error(err) - } - u := &wallet.Utxo{ - Op: *wire.NewOutPoint(h, 0), - ScriptPubkey: make([]byte, 32), - AtHeight: 400000, - Value: 1000000, - } - if !u.IsEqual(u) { - t.Error("Failed to return utxos as equal") - } - testUtxo := *u - testUtxo.Op.Index = 3 - if u.IsEqual(&testUtxo) { - t.Error("Failed to return utxos as not equal") - } - testUtxo = *u - testUtxo.AtHeight = 1 - if u.IsEqual(&testUtxo) { - t.Error("Failed to return utxos as not equal") - } - testUtxo = *u - testUtxo.Value = 4 - if u.IsEqual(&testUtxo) { - t.Error("Failed to return utxos as not equal") - } - testUtxo = *u - ch2, err := chainhash.NewHashFromStr("1f64249abbf2fcc83fc060a64f69a91391e9f5d98c5d3135fe9716838283aa4c") - if err != nil { - t.Error(err) - } - testUtxo.Op.Hash = *ch2 - if u.IsEqual(&testUtxo) { - t.Error("Failed to return utxos as not equal") - } - testUtxo = *u - testUtxo.ScriptPubkey = make([]byte, 4) - if u.IsEqual(&testUtxo) { - t.Error("Failed to return utxos as not equal") - } - if u.IsEqual(nil) { - t.Error("Failed to return utxos as not equal") - } -} - -func TestStxo_IsEqual(t *testing.T) { - h, err := chainhash.NewHashFromStr("16bed6368b8b1542cd6eb87f5bc20dc830b41a2258dde40438a75fa701d24e9a") - if err != nil { - t.Error(err) - } - u := &wallet.Utxo{ - Op: *wire.NewOutPoint(h, 0), - ScriptPubkey: make([]byte, 32), - AtHeight: 400000, - Value: 1000000, - } - h2, err := chainhash.NewHashFromStr("1f64249abbf2fcc83fc060a64f69a91391e9f5d98c5d3135fe9716838283aa4c") - s := &wallet.Stxo{ - Utxo: *u, - SpendHeight: 400001, - SpendTxid: *h2, - } - if !s.IsEqual(s) { - t.Error("Failed to return stxos as equal") - } - - testStxo := *s - testStxo.SpendHeight = 5 - if s.IsEqual(&testStxo) { - t.Error("Failed to return stxos as not equal") - } - h3, err := chainhash.NewHashFromStr("3c5cea030a432ba9c8cf138a93f7b2e5b28263ea416894ee0bdf91bc31bb04f2") - testStxo = *s - testStxo.SpendTxid = *h3 - if s.IsEqual(&testStxo) { - t.Error("Failed to return stxos as not equal") - } - if s.IsEqual(nil) { - t.Error("Failed to return stxos as not equal") - } - testStxo = *s - testStxo.Utxo.AtHeight = 7 - if s.IsEqual(&testStxo) { - t.Error("Failed to return stxos as not equal") - } -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/peers.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/peers.go deleted file mode 100644 index 5dc120000b..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/peers.go +++ /dev/null @@ -1,409 +0,0 @@ -package bitcoincash - -import ( - "errors" - "net" - "strconv" - "sync" - "time" - - "fmt" - "github.com/btcsuite/btcd/addrmgr" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/connmgr" - "github.com/btcsuite/btcd/peer" - "github.com/btcsuite/btcd/wire" - "github.com/cpacia/bchutil" - "golang.org/x/net/proxy" -) - -var ( - // Default number of outbound peers - defaultTargetOutbound = uint32(12) - - // Default duration of time for retrying a connection - defaultRetryDuration = time.Second * 5 - - // Default port per chain params - defaultPort uint16 -) - -const MaxGetAddressAttempts = 10 - -var SFNodeBitcoinCash wire.ServiceFlag = 1 << 5 - -type PeerManagerConfig struct { - - // The network parameters to use - Params *chaincfg.Params - - // The target number of outbound peers. Defaults to 10. - TargetOutbound uint32 - - // Duration of time to retry a connection. Defaults to 5 seconds. - RetryDuration time.Duration - - // UserAgentName specifies the user agent name to advertise. It is - // highly recommended to specify this value. - UserAgentName string - - // UserAgentVersion specifies the user agent version to advertise. It - // is highly recommended to specify this value and that it follows the - // form "major.minor.revision" e.g. "2.6.41". - UserAgentVersion string - - // The directory to store cached peers - AddressCacheDir string - - // If this field is not nil the PeerManager will only connect to this address - TrustedPeer net.Addr - - // Listeners to handle messages from peers. If nil, no messages will be handled. - Listeners *peer.MessageListeners - - // An optional proxy dialer. Will use net.Dial if nil. - Proxy proxy.Dialer - - // Function to return current block hash and height - GetNewestBlock func() (hash *chainhash.Hash, height int32, err error) - - // The main channel over which to send outgoing events - MsgChan chan interface{} -} - -type PeerManager struct { - addrManager *addrmgr.AddrManager - connManager *connmgr.ConnManager - sourceAddr *wire.NetAddress - peerConfig *peer.Config - peerMutex *sync.RWMutex - trustedPeer net.Addr - targetOutbound uint32 - proxy proxy.Dialer - recentlyTriedAddresses map[string]bool - connectedPeers map[uint64]*peer.Peer - msgChan chan interface{} -} - -func NewPeerManager(config *PeerManagerConfig) (*PeerManager, error) { - port, err := strconv.Atoi(config.Params.DefaultPort) - defaultPort = uint16(port) - if err != nil { - return nil, err - } - - pm := &PeerManager{ - addrManager: addrmgr.New(config.AddressCacheDir, nil), - peerMutex: new(sync.RWMutex), - sourceAddr: wire.NewNetAddressIPPort(net.ParseIP("0.0.0.0"), defaultPort, 0), - trustedPeer: config.TrustedPeer, - proxy: config.Proxy, - recentlyTriedAddresses: make(map[string]bool), - connectedPeers: make(map[uint64]*peer.Peer), - msgChan: config.MsgChan, - } - - targetOutbound := config.TargetOutbound - if config.TargetOutbound == 0 { - targetOutbound = defaultTargetOutbound - } - - if config.TrustedPeer != nil { - targetOutbound = 1 - } - pm.targetOutbound = targetOutbound - - retryDuration := config.RetryDuration - if config.RetryDuration <= 0 { - retryDuration = defaultRetryDuration - } - - dial := net.Dial - if config.Proxy != nil { - dial = config.Proxy.Dial - } - - connMgrConfig := &connmgr.Config{ - TargetOutbound: targetOutbound, - RetryDuration: retryDuration, - OnConnection: pm.onConnection, - OnDisconnection: pm.onDisconnection, - GetNewAddress: pm.getNewAddress, - Dial: func(addr net.Addr) (net.Conn, error) { - return dial("tcp", addr.String()) - }, - } - - connMgr, err := connmgr.New(connMgrConfig) - if err != nil { - return nil, err - } - pm.connManager = connMgr - - var listeners *peer.MessageListeners = config.Listeners - if listeners == nil { - listeners = &peer.MessageListeners{} - } - listeners.OnVerAck = pm.onVerack - listeners.OnAddr = pm.onAddr - listeners.OnHeaders = pm.onHeaders - listeners.OnMerkleBlock = pm.onMerkleBlock - listeners.OnInv = pm.onInv - listeners.OnTx = pm.onTx - listeners.OnReject = pm.onReject - - pm.peerConfig = &peer.Config{ - UserAgentName: config.UserAgentName, - UserAgentVersion: config.UserAgentVersion, - ChainParams: config.Params, - DisableRelayTx: true, - NewestBlock: config.GetNewestBlock, - Listeners: *listeners, - } - if config.Proxy != nil { - pm.peerConfig.Proxy = "0.0.0.0" - } - return pm, nil -} - -func (pm *PeerManager) ConnectedPeers() []*peer.Peer { - pm.peerMutex.RLock() - defer pm.peerMutex.RUnlock() - var ret []*peer.Peer - for _, p := range pm.connectedPeers { - ret = append(ret, p) - } - return ret -} - -func (pm *PeerManager) onConnection(req *connmgr.ConnReq, conn net.Conn) { - pm.peerMutex.Lock() - defer pm.peerMutex.Unlock() - - // Create a new peer for this connection - p, err := peer.NewOutboundPeer(pm.peerConfig, conn.RemoteAddr().String()) - if err != nil { - pm.connManager.Disconnect(req.ID()) - return - } - - // Associate the connection with the peer - p.AssociateConnection(conn) - - pm.connectedPeers[req.ID()] = p - - // Tell the addr manager we made a connection - pm.addrManager.Connected(p.NA()) - - // Handle disconnect - go func() { - p.WaitForDisconnect() - pm.connManager.Disconnect(req.ID()) - }() -} - -func (pm *PeerManager) onVerack(p *peer.Peer, msg *wire.MsgVerAck) { - // Check this peer offers bloom filtering services. If not dump them. - p.NA().Services = p.Services() - if !(p.NA().HasService(wire.SFNodeBloom) && p.NA().HasService(wire.SFNodeNetwork) && p.NA().HasService(bchutil.SFNodeBitcoinCash)) { - // onDisconnection will be called - // which will remove the peer from openPeers - log.Warningf("Peer %s does not support bloom filtering, diconnecting", p) - p.Disconnect() - return - } - log.Debugf("Connected to %s - %s\n", p.Addr(), p.UserAgent()) - // Tell the addr manager this is a good address - pm.addrManager.Good(p.NA()) - if pm.msgChan != nil { - pm.msgChan <- newPeerMsg{p} - } -} - -func (pm *PeerManager) onDisconnection(req *connmgr.ConnReq) { - // Remove from connected peers - pm.peerMutex.Lock() - defer pm.peerMutex.Unlock() - peer, ok := pm.connectedPeers[req.ID()] - if !ok { - return - } - log.Debugf("Peer %s disconnected", peer) - delete(pm.connectedPeers, req.ID()) - if pm.msgChan != nil { - pm.msgChan <- donePeerMsg{peer} - } -} - -// Called by connManager when it adds a new connection -func (pm *PeerManager) getNewAddress() (net.Addr, error) { - // If we have a trusted peer we'll just return it - if pm.trustedPeer == nil { - pm.peerMutex.Lock() - defer pm.peerMutex.Unlock() - // We're going to loop here and pull addresses from the addrManager until we get one that we - // are not currently connect to or haven't recently tried. - loop: - for tries := 0; tries < 100; tries++ { - ka := pm.addrManager.GetAddress() - if ka == nil { - continue - } - - // only allow recent nodes (10mins) after we failed 30 - // times - if tries < 30 && time.Since(ka.LastAttempt()) < 10*time.Minute { - continue - } - - // allow nondefault ports after 50 failed tries. - if tries < 50 && fmt.Sprintf("%d", ka.NetAddress().Port) != pm.peerConfig.ChainParams.DefaultPort { - continue - } - - knownAddress := ka.NetAddress() - - // Don't return addresses we're still connected to - for _, p := range pm.connectedPeers { - if p.NA().IP.String() == knownAddress.IP.String() { - continue loop - } - } - addr := &net.TCPAddr{ - Port: int(knownAddress.Port), - IP: knownAddress.IP, - } - pm.addrManager.Attempt(knownAddress) - return addr, nil - } - return nil, errors.New("failed to find appropriate address to return") - } else { - return pm.trustedPeer, nil - } -} - -// Query the DNS seeds and pass the addresses into the address manager. -func (pm *PeerManager) queryDNSSeeds() { - wg := new(sync.WaitGroup) - for _, seed := range bchutil.GetDNSSeed(pm.peerConfig.ChainParams) { - wg.Add(1) - go func(host string) { - returnedAddresses := 0 - var addrs []string - var err error - if pm.proxy != nil { - for i := 0; i < 5; i++ { - ips, err := TorLookupIP(host) - if err != nil { - wg.Done() - return - } - for _, ip := range ips { - addrs = append(addrs, ip.String()) - } - } - } else { - addrs, err = net.LookupHost(host) - if err != nil { - wg.Done() - return - } - } - for _, addr := range addrs { - netAddr := wire.NewNetAddressIPPort(net.ParseIP(addr), defaultPort, 0) - pm.addrManager.AddAddress(netAddr, pm.sourceAddr) - returnedAddresses++ - } - log.Debugf("%s returned %s addresses\n", host, strconv.Itoa(returnedAddresses)) - wg.Done() - }(seed.Host) - } - wg.Wait() -} - -// If we have connected peers let's use them to get more addresses. If not, use the DNS seeds -func (pm *PeerManager) getMoreAddresses() { - if pm.addrManager.NeedMoreAddresses() { - pm.peerMutex.RLock() - defer pm.peerMutex.RUnlock() - if len(pm.connectedPeers) > 0 { - log.Debug("Querying peers for more addresses") - for _, p := range pm.connectedPeers { - p.QueueMessage(wire.NewMsgGetAddr(), nil) - } - } else { - pm.queryDNSSeeds() - } - } -} - -func (pm *PeerManager) onAddr(p *peer.Peer, msg *wire.MsgAddr) { - pm.addrManager.AddAddresses(msg.AddrList, pm.sourceAddr) -} - -func (pm *PeerManager) onHeaders(p *peer.Peer, msg *wire.MsgHeaders) { - if pm.msgChan != nil { - pm.msgChan <- headersMsg{msg, p} - } -} - -func (pm *PeerManager) onMerkleBlock(p *peer.Peer, msg *wire.MsgMerkleBlock) { - if pm.msgChan != nil { - pm.msgChan <- merkleBlockMsg{msg, p} - } -} - -func (pm *PeerManager) onInv(p *peer.Peer, msg *wire.MsgInv) { - if pm.msgChan != nil { - pm.msgChan <- invMsg{msg, p} - } -} - -func (pm *PeerManager) onTx(p *peer.Peer, msg *wire.MsgTx) { - if pm.msgChan != nil { - pm.msgChan <- txMsg{msg, p, nil} - } -} - -func (pm *PeerManager) onReject(p *peer.Peer, msg *wire.MsgReject) { - log.Warningf("Received reject message from peer %d: Code: %s, Hash %s, Reason: %s", int(p.ID()), msg.Code.String(), msg.Hash.String(), msg.Reason) -} - -func (pm *PeerManager) Start() { - pm.addrManager.Start() - log.Infof("Loaded %d peers from cache\n", pm.addrManager.NumAddresses()) - if pm.trustedPeer == nil && pm.addrManager.NeedMoreAddresses() { - log.Info("Querying DNS seeds") - pm.queryDNSSeeds() - } - pm.connManager.Start() - go func() { - tick := time.NewTicker(time.Minute) - defer tick.Stop() - for { - select { - case <-tick.C: - pm.getMoreAddresses() - } - } - }() -} - -func (pm *PeerManager) Stop() { - pm.peerMutex.Lock() - defer pm.peerMutex.Unlock() - wg := new(sync.WaitGroup) - for _, peer := range pm.connectedPeers { - wg.Add(1) - go func() { - // onDisconnection will be called. - peer.Disconnect() - peer.WaitForDisconnect() - wg.Done() - }() - } - pm.addrManager.Stop() - pm.connectedPeers = make(map[uint64]*peer.Peer) - wg.Wait() -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/sortsignsend.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/sortsignsend.go deleted file mode 100644 index 8fe3d85ea0..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/sortsignsend.go +++ /dev/null @@ -1,887 +0,0 @@ -// Copyright (C) 2015-2016 The Lightning Network Developers -// Copyright (c) 2016-2017 The OpenBazaar Developers - -package bitcoincash - -import ( - "bytes" - "encoding/hex" - "errors" - "fmt" - "time" - - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - btc "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/coinset" - hd "github.com/btcsuite/btcutil/hdkeychain" - "github.com/btcsuite/btcutil/txsort" - "github.com/btcsuite/btcwallet/wallet/txauthor" - "github.com/btcsuite/btcwallet/wallet/txrules" - "github.com/cpacia/bchutil" -) - -func (s *SPVWallet) Broadcast(tx *wire.MsgTx) error { - - // Our own tx; don't keep track of false positives - _, err := s.txstore.Ingest(tx, 0, time.Now()) - if err != nil { - return err - } - - // make an inv message instead of a tx message to be polite - txid := tx.TxHash() - iv1 := wire.NewInvVect(wire.InvTypeTx, &txid) - invMsg := wire.NewMsgInv() - err = invMsg.AddInvVect(iv1) - if err != nil { - return err - } - - s.wireService.MsgChan() <- updateFiltersMsg{} - log.Debugf("Broadcasting tx %s to peers", tx.TxHash().String()) - for _, peer := range s.peerManager.ConnectedPeers() { - peer.QueueMessage(tx, nil) - } - return nil -} - -type Coin struct { - TxHash *chainhash.Hash - TxIndex uint32 - TxValue btc.Amount - TxNumConfs int64 - ScriptPubKey []byte -} - -func (c *Coin) Hash() *chainhash.Hash { return c.TxHash } -func (c *Coin) Index() uint32 { return c.TxIndex } -func (c *Coin) Value() btc.Amount { return c.TxValue } -func (c *Coin) PkScript() []byte { return c.ScriptPubKey } -func (c *Coin) NumConfs() int64 { return c.TxNumConfs } -func (c *Coin) ValueAge() int64 { return int64(c.TxValue) * c.TxNumConfs } - -func NewCoin(txid []byte, index uint32, value btc.Amount, numConfs int64, scriptPubKey []byte) coinset.Coin { - shaTxid, _ := chainhash.NewHash(txid) - c := &Coin{ - TxHash: shaTxid, - TxIndex: index, - TxValue: value, - TxNumConfs: numConfs, - ScriptPubKey: scriptPubKey, - } - return coinset.Coin(c) -} - -func (w *SPVWallet) gatherCoins() map[coinset.Coin]*hd.ExtendedKey { - height, _ := w.blockchain.db.Height() - utxos, _ := w.txstore.Utxos().GetAll() - m := make(map[coinset.Coin]*hd.ExtendedKey) - for _, u := range utxos { - if u.WatchOnly { - continue - } - var confirmations int32 - if u.AtHeight > 0 { - confirmations = int32(height) - u.AtHeight - } - c := NewCoin(u.Op.Hash.CloneBytes(), u.Op.Index, btc.Amount(u.Value), int64(confirmations), u.ScriptPubkey) - addr, err := w.ScriptToAddress(u.ScriptPubkey) - if err != nil { - continue - } - key, err := w.keyManager.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - continue - } - m[c] = key - } - return m -} - -func (w *SPVWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { - var ( - tx *wire.MsgTx - err error - ) - if spendAll { - tx, err = w.buildSpendAllTx(addr, feeLevel) - if err != nil { - return nil, err - } - } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) - if err != nil { - return nil, err - } - } - - // Broadcast - if err := w.Broadcast(tx); err != nil { - return nil, err - } - - ch := tx.TxHash() - return &ch, nil -} - -var BumpFeeAlreadyConfirmedError = errors.New("Transaction is confirmed, cannot bump fee") -var BumpFeeTransactionDeadError = errors.New("Cannot bump fee of dead transaction") -var BumpFeeNotFoundError = errors.New("Transaction either doesn't exist or has already been spent") - -func (w *SPVWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { - txn, err := w.txstore.Txns().Get(txid) - if err != nil { - return nil, err - } - if txn.Height > 0 { - return nil, BumpFeeAlreadyConfirmedError - } - if txn.Height < 0 { - return nil, BumpFeeTransactionDeadError - } - // Check stxos for RBF opportunity - /*stxos, _ := w.txstore.Stxos().GetAll() - for _, s := range stxos { - if s.SpendTxid.IsEqual(&txid) { - r := bytes.NewReader(txn.Bytes) - msgTx := wire.NewMsgTx(1) - msgTx.BtcDecode(r, 1) - for i, output := range msgTx.TxOut { - key, err := w.txstore.GetKeyForScript(output.PkScript) - if key != nil && err == nil { // This is our change output - // Calculate change - additional fee - feePerByte := w.GetFeePerByte(PRIOIRTY) - estimatedSize := EstimateSerializeSize(len(msgTx.TxIn), msgTx.TxOut, false) - fee := estimatedSize * int(feePerByte) - newValue := output.Value - int64(fee) - - // Check if still above dust value - if newValue <= 0 || txrules.IsDustAmount(btc.Amount(newValue), len(output.PkScript), txrules.DefaultRelayFeePerKb) { - msgTx.TxOut = append(msgTx.TxOut[:i], msgTx.TxOut[i+1:]...) - } else { - output.Value = newValue - } - - // Bump sequence number - optInRBF := false - for _, input := range msgTx.TxIn { - if input.Sequence < 4294967294 { - input.Sequence++ - optInRBF = true - } - } - if !optInRBF { - break - } - - //TODO: Re-sign transaction - - // Mark original tx as dead - if err = w.txstore.markAsDead(txid); err != nil { - return nil, err - } - - // Broadcast new tx - if err := w.Broadcast(msgTx); err != nil { - return nil, err - } - newTxid := msgTx.TxHash() - return &newTxid, nil - } - } - } - }*/ - // Check utxos for CPFP - utxos, _ := w.txstore.Utxos().GetAll() - for _, u := range utxos { - if u.Op.Hash.IsEqual(&txid) && u.AtHeight == 0 { - addr, err := w.ScriptToAddress(u.ScriptPubkey) - if err != nil { - return nil, err - } - key, err := w.keyManager.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - return nil, err - } - h, err := hex.DecodeString(u.Op.Hash.String()) - if err != nil { - return nil, err - } - in := wallet.TransactionInput{ - LinkedAddress: addr, - OutpointIndex: u.Op.Index, - OutpointHash: h, - Value: u.Value, - } - transactionID, err := w.SweepAddress([]wallet.TransactionInput{in}, nil, key, nil, wallet.FEE_BUMP) - if err != nil { - return nil, err - } - return transactionID, nil - } - } - return nil, BumpFeeNotFoundError -} - -func (w *SPVWallet) EstimateFee(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, feePerByte uint64) uint64 { - tx := wire.NewMsgTx(1) - for _, out := range outs { - scriptPubKey, _ := bchutil.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) - tx.TxOut = append(tx.TxOut, output) - } - estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) -} - -// Build a spend transaction for the amount and return the transaction fee -func (w *SPVWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (uint64, error) { - // Since this is an estimate we can use a dummy output address. Let's use a long one so we don't under estimate. - addr, err := btc.DecodeAddress("114K8nZhYcG1rsxcc1YGujFwWj5NLByc5v", w.params) - if err != nil { - return 0, err - } - tx, err := w.buildTx(amount, addr, feeLevel, nil) - if err != nil { - return 0, err - } - var outval int64 - for _, output := range tx.TxOut { - outval += output.Value - } - var inval int64 - utxos, err := w.txstore.Utxos().GetAll() - if err != nil { - return 0, err - } - for _, input := range tx.TxIn { - for _, utxo := range utxos { - if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value - break - } - } - } - if inval < outval { - return 0, errors.New("Error building transaction: inputs less than outputs") - } - return uint64(inval - outval), err -} - -func (w *SPVWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) { - if uint32(timeout.Hours()) > 0 && timeoutKey == nil { - return nil, nil, errors.New("Timeout key must be non nil when using an escrow timeout") - } - - if len(keys) < threshold { - return nil, nil, fmt.Errorf("unable to generate multisig script with "+ - "%d required signatures when there are only %d public "+ - "keys available", threshold, len(keys)) - } - - var ecKeys []*btcec.PublicKey - for _, key := range keys { - ecKey, err := key.ECPubKey() - if err != nil { - return nil, nil, err - } - ecKeys = append(ecKeys, ecKey) - } - - builder := txscript.NewScriptBuilder() - if uint32(timeout.Hours()) == 0 { - - builder.AddInt64(int64(threshold)) - for _, key := range ecKeys { - builder.AddData(key.SerializeCompressed()) - } - builder.AddInt64(int64(len(ecKeys))) - builder.AddOp(txscript.OP_CHECKMULTISIG) - - } else { - ecKey, err := timeoutKey.ECPubKey() - if err != nil { - return nil, nil, err - } - sequenceLock := blockchain.LockTimeToSequence(false, uint32(timeout.Hours()*6)) - builder.AddOp(txscript.OP_IF) - builder.AddInt64(int64(threshold)) - for _, key := range ecKeys { - builder.AddData(key.SerializeCompressed()) - } - builder.AddInt64(int64(len(ecKeys))) - builder.AddOp(txscript.OP_CHECKMULTISIG) - builder.AddOp(txscript.OP_ELSE). - AddInt64(int64(sequenceLock)). - AddOp(txscript.OP_CHECKSEQUENCEVERIFY). - AddOp(txscript.OP_DROP). - AddData(ecKey.SerializeCompressed()). - AddOp(txscript.OP_CHECKSIG). - AddOp(txscript.OP_ENDIF) - } - redeemScript, err = builder.Script() - if err != nil { - return nil, nil, err - } - addr, err = bchutil.NewCashAddressScriptHash(redeemScript, w.params) - if err != nil { - return nil, nil, err - } - return addr, redeemScript, nil -} - -func (w *SPVWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wallet.Signature, error) { - var sigs []wallet.Signature - tx := wire.NewMsgTx(1) - for _, in := range ins { - ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) - if err != nil { - return sigs, err - } - outpoint := wire.NewOutPoint(ch, in.OutpointIndex) - input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) - tx.TxIn = append(tx.TxIn, input) - } - for _, out := range outs { - scriptPubkey, err := bchutil.PayToAddrScript(out.Address) - if err != nil { - return sigs, err - } - output := wire.NewTxOut(out.Value, scriptPubkey) - tx.TxOut = append(tx.TxOut, output) - } - - // Subtract fee - txType := P2SH_2of3_Multisig - _, err := LockTimeFromRedeemScript(redeemScript) - if err == nil { - txType = P2SH_Multisig_Timelock_2Sigs - } - estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, txType) - fee := estimatedSize * int(feePerByte) - if len(tx.TxOut) > 0 { - feePerOutput := fee / len(tx.TxOut) - for _, output := range tx.TxOut { - output.Value -= int64(feePerOutput) - } - } - - // BIP 69 sorting - txsort.InPlaceSort(tx) - - signingKey, err := key.ECPrivKey() - if err != nil { - return sigs, err - } - - for i := range tx.TxIn { - sig, err := bchutil.RawTxInSignature(tx, i, redeemScript, txscript.SigHashAll, signingKey, ins[i].Value) - if err != nil { - continue - } - bs := wallet.Signature{InputIndex: uint32(i), Signature: sig} - sigs = append(sigs, bs) - } - return sigs, nil -} - -func (w *SPVWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, sigs1 []wallet.Signature, sigs2 []wallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - tx := wire.NewMsgTx(1) - for _, in := range ins { - ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) - if err != nil { - return nil, err - } - outpoint := wire.NewOutPoint(ch, in.OutpointIndex) - input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) - tx.TxIn = append(tx.TxIn, input) - } - for _, out := range outs { - scriptPubkey, err := bchutil.PayToAddrScript(out.Address) - if err != nil { - return nil, err - } - output := wire.NewTxOut(out.Value, scriptPubkey) - tx.TxOut = append(tx.TxOut, output) - } - - // Subtract fee - txType := P2SH_2of3_Multisig - _, err := LockTimeFromRedeemScript(redeemScript) - if err == nil { - txType = P2SH_Multisig_Timelock_2Sigs - } - estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, txType) - fee := estimatedSize * int(feePerByte) - if len(tx.TxOut) > 0 { - feePerOutput := fee / len(tx.TxOut) - for _, output := range tx.TxOut { - output.Value -= int64(feePerOutput) - } - } - - // BIP 69 sorting - txsort.InPlaceSort(tx) - - // Check if time locked - var timeLocked bool - if redeemScript[0] == txscript.OP_IF { - timeLocked = true - } - - for i, input := range tx.TxIn { - var sig1 []byte - var sig2 []byte - for _, sig := range sigs1 { - if int(sig.InputIndex) == i { - sig1 = sig.Signature - } - } - for _, sig := range sigs2 { - if int(sig.InputIndex) == i { - sig2 = sig.Signature - } - } - builder := txscript.NewScriptBuilder() - builder.AddOp(txscript.OP_0) - builder.AddData(sig1) - builder.AddData(sig2) - - if timeLocked { - builder.AddOp(txscript.OP_1) - } - - builder.AddData(redeemScript) - scriptSig, err := builder.Script() - if err != nil { - return nil, err - } - input.SignatureScript = scriptSig - } - // broadcast - if broadcast { - w.Broadcast(tx) - } - var buf bytes.Buffer - tx.BtcEncode(&buf, 1, wire.BaseEncoding) - return buf.Bytes(), nil -} - -func (w *SPVWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wallet.FeeLevel) (*chainhash.Hash, error) { - var internalAddr btc.Address - if address != nil { - internalAddr = *address - } else { - internalAddr = w.CurrentAddress(wallet.INTERNAL) - } - script, err := bchutil.PayToAddrScript(internalAddr) - if err != nil { - return nil, err - } - - var val int64 - var inputs []*wire.TxIn - additionalPrevScripts := make(map[wire.OutPoint][]byte) - for _, in := range ins { - val += in.Value - ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) - if err != nil { - return nil, err - } - script, err := bchutil.PayToAddrScript(in.LinkedAddress) - if err != nil { - return nil, err - } - outpoint := wire.NewOutPoint(ch, in.OutpointIndex) - input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) - inputs = append(inputs, input) - additionalPrevScripts[*outpoint] = script - } - out := wire.NewTxOut(val, script) - - txType := P2PKH - if redeemScript != nil { - txType = P2SH_1of2_Multisig - _, err := LockTimeFromRedeemScript(*redeemScript) - if err == nil { - txType = P2SH_Multisig_Timelock_1Sig - } - } - estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) - - // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) - fee := estimatedSize * feePerByte - - outVal := val - int64(fee) - if outVal < 0 { - outVal = 0 - } - out.Value = outVal - - tx := &wire.MsgTx{ - Version: wire.TxVersion, - TxIn: inputs, - TxOut: []*wire.TxOut{out}, - LockTime: 0, - } - - // BIP 69 sorting - txsort.InPlaceSort(tx) - - // Sign tx - privKey, err := key.ECPrivKey() - if err != nil { - return nil, err - } - pk := privKey.PubKey().SerializeCompressed() - addressPub, err := btc.NewAddressPubKey(pk, w.params) - - getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { - if addressPub.EncodeAddress() == addr.EncodeAddress() { - wif, err := btc.NewWIF(privKey, w.params, true) - if err != nil { - return nil, false, err - } - return wif.PrivKey, wif.CompressPubKey, nil - } - return nil, false, errors.New("Not found") - }) - getScript := txscript.ScriptClosure(func(addr btc.Address) ([]byte, error) { - if redeemScript == nil { - return []byte{}, nil - } - return *redeemScript, nil - }) - - // Check if time locked - var timeLocked bool - if redeemScript != nil { - rs := *redeemScript - if rs[0] == txscript.OP_IF { - timeLocked = true - tx.Version = 2 - for _, txIn := range tx.TxIn { - locktime, err := LockTimeFromRedeemScript(*redeemScript) - if err != nil { - return nil, err - } - txIn.Sequence = locktime - } - } - } - - for i, txIn := range tx.TxIn { - if !timeLocked { - prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] - script, err := bchutil.SignTxOutput(w.params, - tx, i, prevOutScript, txscript.SigHashAll, getKey, - getScript, txIn.SignatureScript, ins[i].Value) - if err != nil { - return nil, errors.New("Failed to sign transaction") - } - txIn.SignatureScript = script - } else { - priv, err := key.ECPrivKey() - if err != nil { - return nil, err - } - script, err := bchutil.RawTxInSignature(tx, i, *redeemScript, txscript.SigHashAll, priv, ins[i].Value) - if err != nil { - return nil, err - } - builder := txscript.NewScriptBuilder(). - AddData(script). - AddOp(txscript.OP_0). - AddData(*redeemScript) - scriptSig, _ := builder.Script() - txIn.SignatureScript = scriptSig - } - } - - // broadcast - w.Broadcast(tx) - txid := tx.TxHash() - return &txid, nil -} - -func (w *SPVWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, optionalOutput *wire.TxOut) (*wire.MsgTx, error) { - // Check for dust - script, _ := bchutil.PayToAddrScript(addr) - if txrules.IsDustAmount(btc.Amount(amount), len(script), txrules.DefaultRelayFeePerKb) { - return nil, errors.New("Amount is below dust threshold") - } - - var additionalPrevScripts map[wire.OutPoint][]byte - var additionalKeysByAddress map[string]*btc.WIF - var inVals map[wire.OutPoint]int64 - - // Create input source - coinMap := w.gatherCoins() - coins := make([]coinset.Coin, 0, len(coinMap)) - for k := range coinMap { - coins = append(coins, k) - } - inputSource := func(target btc.Amount) (total btc.Amount, inputs []*wire.TxIn, amounts []btc.Amount, scripts [][]byte, err error) { - coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)} - coins, err := coinSelector.CoinSelect(target, coins) - if err != nil { - return total, inputs, []btc.Amount{}, scripts, errors.New("insuffient funds") - } - additionalPrevScripts = make(map[wire.OutPoint][]byte) - inVals = make(map[wire.OutPoint]int64) - additionalKeysByAddress = make(map[string]*btc.WIF) - for _, c := range coins.Coins() { - total += c.Value() - outpoint := wire.NewOutPoint(c.Hash(), c.Index()) - in := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) - inputs = append(inputs, in) - additionalPrevScripts[*outpoint] = c.PkScript() - key := coinMap[c] - addr, err := key.Address(w.params) - if err != nil { - continue - } - privKey, err := key.ECPrivKey() - if err != nil { - continue - } - wif, _ := btc.NewWIF(privKey, w.params, true) - additionalKeysByAddress[addr.EncodeAddress()] = wif - val := c.Value() - sat := val.ToUnit(btc.AmountSatoshi) - inVals[*outpoint] = int64(sat) - } - return total, inputs, []btc.Amount{}, scripts, nil - } - - // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 - - // outputs - out := wire.NewTxOut(amount, script) - - // Create change source - changeSource := func() ([]byte, error) { - addr := w.CurrentAddress(wallet.INTERNAL) - script, err := bchutil.PayToAddrScript(addr) - if err != nil { - return []byte{}, err - } - return script, nil - } - - outputs := []*wire.TxOut{out} - if optionalOutput != nil { - outputs = append(outputs, optionalOutput) - } - authoredTx, err := NewUnsignedTransaction(outputs, btc.Amount(feePerKB), inputSource, changeSource) - if err != nil { - return nil, err - } - - // BIP 69 sorting - txsort.InPlaceSort(authoredTx.Tx) - - // Sign tx - getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { - addrStr := addr.EncodeAddress() - wif := additionalKeysByAddress[addrStr] - return wif.PrivKey, wif.CompressPubKey, nil - }) - getScript := txscript.ScriptClosure(func( - addr btc.Address) ([]byte, error) { - return []byte{}, nil - }) - for i, txIn := range authoredTx.Tx.TxIn { - prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] - script, err := bchutil.SignTxOutput(w.params, - authoredTx.Tx, i, prevOutScript, txscript.SigHashAll, getKey, - getScript, txIn.SignatureScript, inVals[txIn.PreviousOutPoint]) - if err != nil { - return nil, errors.New("Failed to sign transaction") - } - txIn.SignatureScript = script - } - return authoredTx.Tx, nil -} - -func (w *SPVWallet) buildSpendAllTx(addr btc.Address, feeLevel wallet.FeeLevel) (*wire.MsgTx, error) { - tx := wire.NewMsgTx(1) - - coinMap := w.gatherCoins() - - inVals := make(map[wire.OutPoint]int64) - totalIn := int64(0) - additionalPrevScripts := make(map[wire.OutPoint][]byte) - additionalKeysByAddress := make(map[string]*btc.WIF) - - for coin, key := range coinMap { - outpoint := wire.NewOutPoint(coin.Hash(), coin.Index()) - in := wire.NewTxIn(outpoint, nil, nil) - additionalPrevScripts[*outpoint] = coin.PkScript() - tx.TxIn = append(tx.TxIn, in) - val := int64(coin.Value().ToUnit(btc.AmountSatoshi)) - totalIn += val - inVals[*outpoint] = val - - addr, err := key.Address(w.params) - if err != nil { - continue - } - privKey, err := key.ECPrivKey() - if err != nil { - continue - } - wif, _ := btc.NewWIF(privKey, w.params, true) - additionalKeysByAddress[addr.EncodeAddress()] = wif - } - - // outputs - script, err := bchutil.PayToAddrScript(addr) - if err != nil { - return nil, err - } - - // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) - estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) - fee := int64(estimatedSize) * feePerByte - - // Check for dust output - if txrules.IsDustAmount(btc.Amount(totalIn-fee), len(script), txrules.DefaultRelayFeePerKb) { - return nil, wallet.ErrorDustAmount - } - - // Build the output - out := wire.NewTxOut(totalIn-fee, script) - tx.TxOut = append(tx.TxOut, out) - - // BIP 69 sorting - txsort.InPlaceSort(tx) - - // Sign - getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { - addrStr := addr.EncodeAddress() - wif, ok := additionalKeysByAddress[addrStr] - if !ok { - return nil, false, errors.New("key not found") - } - return wif.PrivKey, wif.CompressPubKey, nil - }) - getScript := txscript.ScriptClosure(func( - addr btc.Address) ([]byte, error) { - return []byte{}, nil - }) - for i, txIn := range tx.TxIn { - prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] - script, err := bchutil.SignTxOutput(w.params, - tx, i, prevOutScript, txscript.SigHashAll, getKey, - getScript, txIn.SignatureScript, inVals[txIn.PreviousOutPoint]) - if err != nil { - return nil, errors.New("failed to sign transaction") - } - txIn.SignatureScript = script - } - return tx, nil -} - -func NewUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInputs txauthor.InputSource, fetchChange txauthor.ChangeSource) (*txauthor.AuthoredTx, error) { - - var targetAmount btc.Amount - for _, txOut := range outputs { - targetAmount += btc.Amount(txOut.Value) - } - - estimatedSize := EstimateSerializeSize(1, outputs, true, P2PKH) - targetFee := txrules.FeeForSerializeSize(feePerKb, estimatedSize) - - for { - inputAmount, inputs, _, scripts, err := fetchInputs(targetAmount + targetFee) - if err != nil { - return nil, err - } - if inputAmount < targetAmount+targetFee { - return nil, errors.New("insufficient funds available to construct transaction") - } - - maxSignedSize := EstimateSerializeSize(len(inputs), outputs, true, P2PKH) - maxRequiredFee := txrules.FeeForSerializeSize(feePerKb, maxSignedSize) - remainingAmount := inputAmount - targetAmount - if remainingAmount < maxRequiredFee { - targetFee = maxRequiredFee - continue - } - - unsignedTransaction := &wire.MsgTx{ - Version: wire.TxVersion, - TxIn: inputs, - TxOut: outputs, - LockTime: 0, - } - changeIndex := -1 - changeAmount := inputAmount - targetAmount - maxRequiredFee - if changeAmount != 0 && !txrules.IsDustAmount(changeAmount, - P2PKHOutputSize, txrules.DefaultRelayFeePerKb) { - changeScript, err := fetchChange() - if err != nil { - return nil, err - } - if len(changeScript) > P2PKHPkScriptSize { - return nil, errors.New("fee estimation requires change " + - "scripts no larger than P2PKH output scripts") - } - change := wire.NewTxOut(int64(changeAmount), changeScript) - l := len(outputs) - unsignedTransaction.TxOut = append(outputs[:l:l], change) - changeIndex = l - } - - return &txauthor.AuthoredTx{ - Tx: unsignedTransaction, - PrevScripts: scripts, - TotalInput: inputAmount, - ChangeIndex: changeIndex, - }, nil - } -} - -func (w *SPVWallet) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 { - return w.feeProvider.GetFeePerByte(feeLevel) -} - -func LockTimeFromRedeemScript(redeemScript []byte) (uint32, error) { - if len(redeemScript) < 113 { - return 0, errors.New("Redeem script invalid length") - } - if redeemScript[106] != 103 { - return 0, errors.New("Invalid redeem script") - } - if redeemScript[107] == 0 { - return 0, nil - } - if 81 <= redeemScript[107] && redeemScript[107] <= 96 { - return uint32((redeemScript[107] - 81) + 1), nil - } - var v []byte - op := redeemScript[107] - if 1 <= op && op <= 75 { - for i := 0; i < int(op); i++ { - v = append(v, []byte{redeemScript[108+i]}...) - } - } else { - return 0, errors.New("Too many bytes pushed for sequence") - } - var result int64 - for i, val := range v { - result |= int64(val) << uint8(8*i) - } - - return uint32(result), nil -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/test_compile.sh b/vendor/github.com/cpacia/BitcoinCash-Wallet/test_compile.sh deleted file mode 100755 index 878211bd62..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/test_compile.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -set -e -pwd -go get github.com/cpacia/BitcoinCash-Wallet -go get github.com/mattn/go-sqlite3 -go test -coverprofile=bitcoincash.cover.out ./ -echo "mode: set" > coverage.out && cat *.cover.out | grep -v mode: | sort -r | \ -awk '{if($1 != last) {print $0;last=$1}}' >> coverage.out -rm -rf *.cover.out diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/timesorter.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/timesorter.go deleted file mode 100644 index f3139ec0fe..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/timesorter.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2013-2017 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package bitcoincash - -// timeSorter implements sort.Interface to allow a slice of timestamps to -// be sorted. -type timeSorter []int64 - -// Len returns the number of timestamps in the slice. It is part of the -// sort.Interface implementation. -func (s timeSorter) Len() int { - return len(s) -} - -// Swap swaps the timestamps at the passed indices. It is part of the -// sort.Interface implementation. -func (s timeSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -// Less returns whether the timstamp with index i should sort before the -// timestamp with index j. It is part of the sort.Interface implementation. -func (s timeSorter) Less(i, j int) bool { - return s[i] < s[j] -} - -// timeSorter implements sort.Interface to allow a slice of block headers to -// be sorted by timestamp. -type blockSorter []StoredHeader - -// Len returns the number of timestamps in the slice. It is part of the -// sort.Interface implementation. -func (s blockSorter) Len() int { - return len(s) -} - -// Swap swaps the timestamps at the passed indices. It is part of the -// sort.Interface implementation. -func (s blockSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -// Less returns whether the timstamp with index i should sort before the -// timestamp with index j. It is part of the sort.Interface implementation. -func (s blockSorter) Less(i, j int) bool { - if s[i].header.Timestamp.Before(s[j].header.Timestamp) || s[i].header.Timestamp.Equal(s[j].header.Timestamp) { - return true - } - return false -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/tor.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/tor.go deleted file mode 100644 index 189bd3c86f..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/tor.go +++ /dev/null @@ -1,135 +0,0 @@ -package bitcoincash - -// Copyright (c) 2013-2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -import ( - "encoding/binary" - "errors" - "net" -) - -const ( - torSucceeded = 0x00 - torGeneralError = 0x01 - torNotAllowed = 0x02 - torNetUnreachable = 0x03 - torHostUnreachable = 0x04 - torConnectionRefused = 0x05 - torTTLExpired = 0x06 - torCmdNotSupported = 0x07 - torAddrNotSupported = 0x08 -) - -var ( - // ErrTorInvalidAddressResponse indicates an invalid address was - // returned by the Tor DNS resolver. - ErrTorInvalidAddressResponse = errors.New("invalid address response") - - // ErrTorInvalidProxyResponse indicates the Tor proxy returned a - // response in an unexpected format. - ErrTorInvalidProxyResponse = errors.New("invalid proxy response") - - // ErrTorUnrecognizedAuthMethod indicates the authentication method - // provided is not recognized. - ErrTorUnrecognizedAuthMethod = errors.New("invalid proxy authentication method") - - torStatusErrors = map[byte]error{ - torSucceeded: errors.New("tor succeeded"), - torGeneralError: errors.New("tor general error"), - torNotAllowed: errors.New("tor not allowed"), - torNetUnreachable: errors.New("tor network is unreachable"), - torHostUnreachable: errors.New("tor host is unreachable"), - torConnectionRefused: errors.New("tor connection refused"), - torTTLExpired: errors.New("tor TTL expired"), - torCmdNotSupported: errors.New("tor command not supported"), - torAddrNotSupported: errors.New("tor address type not supported"), - } -) - -// TorLookupIP uses Tor to resolve DNS via the SOCKS extension they provide for -// resolution over the Tor network. Tor itself doesn't support ipv6 so this -// doesn't either. -func TorLookupIP(host string) ([]net.IP, error) { - conn, err := net.Dial("tcp", "127.0.0.1:9150") - if err != nil { - conn, err = net.Dial("tcp", "127.0.0.1:9050") - if err != nil { - return nil, err - } - } - defer conn.Close() - - buf := []byte{'\x05', '\x01', '\x00'} - _, err = conn.Write(buf) - if err != nil { - return nil, err - } - - buf = make([]byte, 2) - _, err = conn.Read(buf) - if err != nil { - return nil, err - } - if buf[0] != '\x05' { - return nil, ErrTorInvalidProxyResponse - } - if buf[1] != '\x00' { - return nil, ErrTorUnrecognizedAuthMethod - } - - buf = make([]byte, 7+len(host)) - buf[0] = 5 // protocol version - buf[1] = '\xF0' // Tor Resolve - buf[2] = 0 // reserved - buf[3] = 3 // Tor Resolve - buf[4] = byte(len(host)) - copy(buf[5:], host) - buf[5+len(host)] = 0 // Port 0 - - _, err = conn.Write(buf) - if err != nil { - return nil, err - } - - buf = make([]byte, 4) - _, err = conn.Read(buf) - if err != nil { - return nil, err - } - if buf[0] != 5 { - return nil, ErrTorInvalidProxyResponse - } - if buf[1] != 0 { - if int(buf[1]) > len(torStatusErrors) { - err = ErrTorInvalidProxyResponse - } else { - err = torStatusErrors[buf[1]] - if err == nil { - err = ErrTorInvalidProxyResponse - } - } - return nil, err - } - if buf[3] != 1 { - err := torStatusErrors[torGeneralError] - return nil, err - } - - buf = make([]byte, 4) - bytes, err := conn.Read(buf) - if err != nil { - return nil, err - } - if bytes != 4 { - return nil, ErrTorInvalidAddressResponse - } - - r := binary.BigEndian.Uint32(buf) - - addr := make([]net.IP, 1) - addr[0] = net.IPv4(byte(r>>24), byte(r>>16), byte(r>>8), byte(r)) - - return addr, nil -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/txsizes.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/txsizes.go deleted file mode 100644 index 0db2af0eb2..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/txsizes.go +++ /dev/null @@ -1,249 +0,0 @@ -package bitcoincash - -// Copyright (c) 2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -/* Copied here from a btcd internal package*/ - -import ( - "github.com/btcsuite/btcd/wire" -) - -// Worst case script and input/output size estimates. -const ( - // RedeemP2PKHSigScriptSize is the worst case (largest) serialize size - // of a transaction input script that redeems a compressed P2PKH output. - // It is calculated as: - // - // - OP_DATA_73 - // - 72 bytes DER signature + 1 byte sighash - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - RedeemP2PKHSigScriptSize = 1 + 73 + 1 + 33 - - // RedeemP2SHMultisigSigScriptSize is the worst case (largest) serialize size - // of a transaction input script that redeems a 2 of 3 P2SH multisig output with compressed keys. - // It is calculated as: - // - // - OP_0 - // - OP_DATA_72 - // - 72 bytes DER signature - // - OP_DATA_72 - // - 72 bytes DER signature - // - OP_PUSHDATA - // - OP_2 - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP3 - // - OP_CHECKMULTISIG - RedeemP2SH2of3MultisigSigScriptSize = 1 + 1 + 72 + 1 + 72 + 1 + 1 + 1 + 33 + 1 + 33 + 1 + 33 + 1 + 1 - - // RedeemP2SH1of2MultisigSigScriptSize is the worst case (largest) serialize size - // of a transaction input script that redeems a 1 of 2 P2SH multisig output with compressed keys. - // It is calculated as: - // - // - OP_0 - // - OP_DATA_72 - // - 72 bytes DER signature - // - OP_PUSHDATA - // - OP_1 - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP2 - // - OP_CHECKMULTISIG - RedeemP2SH1of2MultisigSigScriptSize = 1 + 1 + 72 + 1 + 1 + 1 + 33 + 1 + 33 + 1 + 1 - - // RedeemP2SHMultisigTimelock1SigScriptSize is the worst case (largest) serialize size - // of a transaction input script that redeems a compressed P2SH timelocked multisig using the timeout. - // It is calculated as: - // - // - OP_DATA_72 - // - 72 bytes DER signature - // - OP_0 - // - OP_PUSHDATA - // - OP_IF - // - OP_2 - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP3 - // - OP_CHECKMULTISIG - // - OP_ELSE - // - OP_PUSHDATA - // - 2 byte block height - // - OP_CHECKSEQUENCEVERIFY - // - OP_DROP - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP_CHECKSIG - // - OP_ENDIF - RedeemP2SHMultisigTimelock1SigScriptSize = 1 + 72 + 1 + 1 + 1 + 1 + 1 + 33 + 1 + 33 + 1 + 33 + 1 + 1 + 1 + 1 + 2 + 1 + 1 + 1 + 33 + 1 + 1 - - // RedeemP2SHMultisigTimelock2SigScriptSize is the worst case (largest) serialize size - // of a transaction input script that redeems a compressed P2SH timelocked multisig without using the timeout. - // It is calculated as: - // - // - OP_0 - // - OP_DATA_72 - // - 72 bytes DER signature - // - OP_DATA_72 - // - 72 bytes DER signature - // - OP_1 - // - OP_PUSHDATA - // - OP_IF - // - OP_2 - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP3 - // - OP_CHECKMULTISIG - // - OP_ELSE - // - OP_PUSHDATA - // - 2 byte block height - // - OP_CHECKSEQUENCEVERIFY - // - OP_DROP - // - OP_DATA_33 - // - 33 bytes serialized compressed pubkey - // - OP_CHECKSIG - // - OP_ENDIF - RedeemP2SHMultisigTimelock2SigScriptSize = 1 + 1 + 72 + +1 + 72 + 1 + 1 + 1 + 1 + 1 + 33 + 1 + 33 + 1 + 33 + 1 + 1 + 1 + 1 + 2 + 1 + 1 + 1 + 33 + 1 + 1 - - // P2PKHPkScriptSize is the size of a transaction output script that - // pays to a compressed pubkey hash. It is calculated as: - // - // - OP_DUP - // - OP_HASH160 - // - OP_DATA_20 - // - 20 bytes pubkey hash - // - OP_EQUALVERIFY - // - OP_CHECKSIG - P2PKHPkScriptSize = 1 + 1 + 1 + 20 + 1 + 1 - - // RedeemP2PKHInputSize is the worst case (largest) serialize size of a - // transaction input redeeming a compressed P2PKH output. It is - // calculated as: - // - // - 32 bytes previous tx - // - 4 bytes output index - // - 1 byte script len - // - signature script - // - 4 bytes sequence - RedeemP2PKHInputSize = 32 + 4 + 1 + RedeemP2PKHSigScriptSize + 4 - - // RedeemP2SH2of3MultisigInputSize is the worst case (largest) serialize size of a - // transaction input redeeming a compressed P2SH 2 of 3 multisig output. It is - // calculated as: - // - // - 32 bytes previous tx - // - 4 bytes output index - // - 1 byte script len - // - 4 bytes sequence - /// - witness discounted signature script - RedeemP2SH2of3MultisigInputSize = 32 + 4 + 1 + 4 + (RedeemP2SH2of3MultisigSigScriptSize / 4) - - // RedeemP2SH1of2MultisigInputSize is the worst case (largest) serialize size of a - // transaction input redeeming a compressed P2SH 2 of 3 multisig output. It is - // calculated as: - // - // - 32 bytes previous tx - // - 4 bytes output index - // - 1 byte script len - // - 4 bytes sequence - /// - witness discounted signature script - RedeemP2SH1of2MultisigInputSize = 32 + 4 + 1 + 4 + (RedeemP2SH1of2MultisigSigScriptSize / 4) - - // RedeemP2SHMultisigTimelock1InputSize is the worst case (largest) serialize size of a - // transaction input redeeming a compressed p2sh timelocked multig output with using the timeout. It is - // calculated as: - // - // - 32 bytes previous tx - // - 4 bytes output index - // - 1 byte script len - // - 4 bytes sequence - /// - witness discounted signature script - RedeemP2SHMultisigTimelock1InputSize = 32 + 4 + 1 + 4 + (RedeemP2SHMultisigTimelock1SigScriptSize / 4) - - // RedeemP2SHMultisigTimelock2InputSize is the worst case (largest) serialize size of a - // transaction input redeeming a compressed P2SH timelocked multisig output without using the timeout. It is - // calculated as: - // - // - 32 bytes previous tx - // - 4 bytes output index - // - 1 byte script len - // - 4 bytes sequence - /// - witness discounted signature script - RedeemP2SHMultisigTimelock2InputSize = 32 + 4 + 1 + 4 + (RedeemP2SHMultisigTimelock2SigScriptSize / 4) - - // P2PKHOutputSize is the serialize size of a transaction output with a - // P2PKH output script. It is calculated as: - // - // - 8 bytes output value - // - 1 byte compact int encoding value 25 - // - 25 bytes P2PKH output script - P2PKHOutputSize = 8 + 1 + P2PKHPkScriptSize -) - -type InputType int - -const ( - P2PKH InputType = iota - P2SH_1of2_Multisig - P2SH_2of3_Multisig - P2SH_Multisig_Timelock_1Sig - P2SH_Multisig_Timelock_2Sigs -) - -// EstimateSerializeSize returns a worst case serialize size estimate for a -// signed transaction that spends inputCount number of compressed P2PKH outputs -// and contains each transaction output from txOuts. The estimated size is -// incremented for an additional P2PKH change output if addChangeOutput is true. -func EstimateSerializeSize(inputCount int, txOuts []*wire.TxOut, addChangeOutput bool, inputType InputType) int { - changeSize := 0 - outputCount := len(txOuts) - if addChangeOutput { - changeSize = P2PKHOutputSize - outputCount++ - } - - var redeemScriptSize int - switch inputType { - case P2PKH: - redeemScriptSize = RedeemP2PKHInputSize - case P2SH_1of2_Multisig: - redeemScriptSize = RedeemP2SH1of2MultisigInputSize - case P2SH_2of3_Multisig: - redeemScriptSize = RedeemP2SH2of3MultisigInputSize - case P2SH_Multisig_Timelock_1Sig: - redeemScriptSize = RedeemP2SHMultisigTimelock1InputSize - case P2SH_Multisig_Timelock_2Sigs: - redeemScriptSize = RedeemP2SHMultisigTimelock2InputSize - } - - // 10 additional bytes are for version, locktime, and segwit flags - return 10 + wire.VarIntSerializeSize(uint64(inputCount)) + - wire.VarIntSerializeSize(uint64(outputCount)) + - inputCount*redeemScriptSize + - SumOutputSerializeSizes(txOuts) + - changeSize -} - -// SumOutputSerializeSizes sums up the serialized size of the supplied outputs. -func SumOutputSerializeSizes(outputs []*wire.TxOut) (serializeSize int) { - for _, txOut := range outputs { - serializeSize += txOut.SerializeSize() - } - return serializeSize -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/txstore.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/txstore.go deleted file mode 100644 index 46fe6bc79d..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/txstore.go +++ /dev/null @@ -1,498 +0,0 @@ -// Copyright (C) 2015-2016 The Lightning Network Developers -// Copyright (c) 2016-2017 The OpenBazaar Developers - -package bitcoincash - -import ( - "bytes" - "errors" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/bloom" - "sync" - "time" -) - -type TxStore struct { - adrs []btcutil.Address - watchedScripts [][]byte - txids map[string]int32 - addrMutex *sync.Mutex - txidsMutex *sync.RWMutex - cbMutex *sync.Mutex - - keyManager *KeyManager - - params *chaincfg.Params - - listeners []func(wallet.TransactionCallback) - - additionalFilters [][]byte - - wallet.Datastore -} - -func NewTxStore(p *chaincfg.Params, db wallet.Datastore, keyManager *KeyManager, additionalFilters ...[]byte) (*TxStore, error) { - txs := &TxStore{ - params: p, - keyManager: keyManager, - addrMutex: new(sync.Mutex), - cbMutex: new(sync.Mutex), - txidsMutex: new(sync.RWMutex), - txids: make(map[string]int32), - Datastore: db, - additionalFilters: additionalFilters, - } - err := txs.PopulateAdrs() - if err != nil { - return nil, err - } - return txs, nil -} - -// ... or I'm gonna fade away -func (ts *TxStore) GimmeFilter() (*bloom.Filter, error) { - ts.PopulateAdrs() - - // get all utxos to add outpoints to filter - allUtxos, err := ts.Utxos().GetAll() - if err != nil { - return nil, err - } - - allStxos, err := ts.Stxos().GetAll() - if err != nil { - return nil, err - } - ts.addrMutex.Lock() - elem := uint32(len(ts.adrs)+len(allUtxos)+len(allStxos)) + uint32(len(ts.watchedScripts)) - f := bloom.NewFilter(elem, 0, 0.00003, wire.BloomUpdateAll) - - // note there could be false positives since we're just looking - // for the 20 byte PKH without the opcodes. - for _, a := range ts.adrs { // add 20-byte pubkeyhash - f.Add(a.ScriptAddress()) - } - ts.addrMutex.Unlock() - for _, u := range allUtxos { - f.AddOutPoint(&u.Op) - } - - for _, s := range allStxos { - f.AddOutPoint(&s.Utxo.Op) - } - for _, w := range ts.watchedScripts { - _, addrs, _, err := txscript.ExtractPkScriptAddrs(w, ts.params) - if err != nil { - continue - } - f.Add(addrs[0].ScriptAddress()) - } - for _, toAdd := range ts.additionalFilters { - f.Add(toAdd) - } - return f, nil -} - -// GetDoubleSpends takes a transaction and compares it with -// all transactions in the db. It returns a slice of all txids in the db -// which are double spent by the received tx. -func (ts *TxStore) CheckDoubleSpends(argTx *wire.MsgTx) ([]*chainhash.Hash, error) { - var dubs []*chainhash.Hash // slice of all double-spent txs - argTxid := argTx.TxHash() - txs, err := ts.Txns().GetAll(true) - if err != nil { - return dubs, err - } - for _, compTx := range txs { - if compTx.Height < 0 { - continue - } - r := bytes.NewReader(compTx.Bytes) - msgTx := wire.NewMsgTx(1) - msgTx.BtcDecode(r, 1, wire.WitnessEncoding) - compTxid := msgTx.TxHash() - for _, argIn := range argTx.TxIn { - // iterate through inputs of compTx - for _, compIn := range msgTx.TxIn { - if outPointsEqual(argIn.PreviousOutPoint, compIn.PreviousOutPoint) && !compTxid.IsEqual(&argTxid) { - // found double spend - dubs = append(dubs, &compTxid) - break // back to argIn loop - } - } - } - } - return dubs, nil -} - -// GetPendingInv returns an inv message containing all txs known to the -// db which are at height 0 (not known to be confirmed). -// This can be useful on startup or to rebroadcast unconfirmed txs. -func (ts *TxStore) GetPendingInv() (*wire.MsgInv, error) { - // use a map (really a set) do avoid dupes - txidMap := make(map[chainhash.Hash]struct{}) - - utxos, err := ts.Utxos().GetAll() // get utxos from db - if err != nil { - return nil, err - } - stxos, err := ts.Stxos().GetAll() // get stxos from db - if err != nil { - return nil, err - } - - // iterate through utxos, adding txids of anything with height 0 - for _, utxo := range utxos { - if utxo.AtHeight == 0 { - txidMap[utxo.Op.Hash] = struct{}{} // adds to map - } - } - // do the same with stxos based on height at which spent - for _, stxo := range stxos { - if stxo.SpendHeight == 0 { - txidMap[stxo.SpendTxid] = struct{}{} - } - } - - invMsg := wire.NewMsgInv() - for txid := range txidMap { - item := wire.NewInvVect(wire.InvTypeTx, &txid) - err = invMsg.AddInvVect(item) - if err != nil { - return nil, err - } - } - - // return inv message with all txids (maybe none) - return invMsg, nil -} - -// PopulateAdrs just puts a bunch of adrs in ram; it doesn't touch the DB -func (ts *TxStore) PopulateAdrs() error { - keys := ts.keyManager.GetKeys() - ts.addrMutex.Lock() - ts.adrs = []btcutil.Address{} - for _, k := range keys { - addr, err := k.Address(ts.params) - if err != nil { - continue - } - ts.adrs = append(ts.adrs, addr) - } - ts.addrMutex.Unlock() - ts.watchedScripts, _ = ts.WatchedScripts().GetAll() - txns, _ := ts.Txns().GetAll(true) - ts.txidsMutex.Lock() - for _, t := range txns { - ts.txids[t.Txid] = t.Height - } - ts.txidsMutex.Unlock() - return nil -} - -// Ingest puts a tx into the DB atomically. This can result in a -// gain, a loss, or no result. Gain or loss in satoshis is returned. -func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (uint32, error) { - var hits uint32 - var err error - // Tx has been OK'd by SPV; check tx sanity - utilTx := btcutil.NewTx(tx) // convert for validation - // Checks basic stuff like there are inputs and ouputs - err = blockchain.CheckTransactionSanity(utilTx) - if err != nil { - return hits, err - } - - // Check to see if we've already processed this tx. If so, return. - - ts.txidsMutex.RLock() - sh, ok := ts.txids[tx.TxHash().String()] - ts.txidsMutex.RUnlock() - if ok && (sh > 0 || (sh == 0 && height == 0)) { - return 1, nil - } - - // Check to see if this is a double spend - doubleSpends, err := ts.CheckDoubleSpends(tx) - if err != nil { - return hits, err - } - if len(doubleSpends) > 0 { - // First seen rule - if height == 0 { - return 0, nil - } else { - // Mark any unconfirmed doubles as dead - for _, double := range doubleSpends { - ts.markAsDead(*double) - } - } - } - - // Generate PKscripts for all addresses - ts.addrMutex.Lock() - PKscripts := make([][]byte, len(ts.adrs)) - for i := range ts.adrs { - // Iterate through all our addresses - // TODO: This will need to test both segwit and legacy once segwit activates - PKscripts[i], err = txscript.PayToAddrScript(ts.adrs[i]) - if err != nil { - ts.addrMutex.Unlock() - return hits, err - } - } - ts.addrMutex.Unlock() - - // Iterate through all outputs of this tx, see if we gain - cachedSha := tx.TxHash() - cb := wallet.TransactionCallback{Txid: cachedSha.String(), Height: height} - value := int64(0) - matchesWatchOnly := false - for i, txout := range tx.TxOut { - // Ignore the error here because the sender could have used and exotic script - // for his change and we don't want to fail in that case. - addr, _ := scriptToAddress(txout.PkScript, ts.params) - out := wallet.TransactionOutput{Address: addr, Value: txout.Value, Index: uint32(i)} - for _, script := range PKscripts { - if bytes.Equal(txout.PkScript, script) { // new utxo found - scriptAddress, _ := ts.extractScriptAddress(txout.PkScript) - ts.keyManager.MarkKeyAsUsed(scriptAddress) - newop := wire.OutPoint{ - Hash: cachedSha, - Index: uint32(i), - } - newu := wallet.Utxo{ - AtHeight: height, - Value: txout.Value, - ScriptPubkey: txout.PkScript, - Op: newop, - WatchOnly: false, - } - value += newu.Value - ts.Utxos().Put(newu) - hits++ - break - } - } - // Now check watched scripts - for _, script := range ts.watchedScripts { - if bytes.Equal(txout.PkScript, script) { - newop := wire.OutPoint{ - Hash: cachedSha, - Index: uint32(i), - } - newu := wallet.Utxo{ - AtHeight: height, - Value: txout.Value, - ScriptPubkey: txout.PkScript, - Op: newop, - WatchOnly: true, - } - ts.Utxos().Put(newu) - matchesWatchOnly = true - } - } - for _, f := range ts.additionalFilters { - if bytes.Contains(txout.PkScript, f) { - matchesWatchOnly = true - break - } - } - cb.Outputs = append(cb.Outputs, out) - } - utxos, err := ts.Utxos().GetAll() - if err != nil { - return 0, err - } - for _, txin := range tx.TxIn { - for i, u := range utxos { - if outPointsEqual(txin.PreviousOutPoint, u.Op) { - st := wallet.Stxo{ - Utxo: u, - SpendHeight: height, - SpendTxid: cachedSha, - } - ts.Stxos().Put(st) - ts.Utxos().Delete(u) - utxos = append(utxos[:i], utxos[i+1:]...) - if !u.WatchOnly { - value -= u.Value - hits++ - } else { - matchesWatchOnly = true - } - - // Ignore the error here because the sender could have used and exotic script - // for his change and we don't want to fail in that case. - addr, _ := scriptToAddress(u.ScriptPubkey, ts.params) - - in := wallet.TransactionInput{ - OutpointHash: u.Op.Hash.CloneBytes(), - OutpointIndex: u.Op.Index, - LinkedAddress: addr, - Value: u.Value, - } - cb.Inputs = append(cb.Inputs, in) - break - } - } - } - - // Update height of any stxos - if height > 0 { - stxos, err := ts.Stxos().GetAll() - if err != nil { - return 0, err - } - for _, stxo := range stxos { - if stxo.SpendTxid.IsEqual(&cachedSha) { - stxo.SpendHeight = height - ts.Stxos().Put(stxo) - if !stxo.Utxo.WatchOnly { - hits++ - } else { - matchesWatchOnly = true - } - break - } - } - } - - // If hits is nonzero it's a relevant tx and we should store it - if hits > 0 || matchesWatchOnly { - ts.cbMutex.Lock() - ts.txidsMutex.Lock() - txn, err := ts.Txns().Get(tx.TxHash()) - shouldCallback := false - if err != nil { - cb.Value = value - txn.Timestamp = timestamp - shouldCallback = true - var buf bytes.Buffer - tx.BtcEncode(&buf, 1, wire.BaseEncoding) - ts.Txns().Put(buf.Bytes(), tx.TxHash().String(), int(value), int(height), txn.Timestamp, hits == 0) - ts.txids[tx.TxHash().String()] = height - } - // Let's check the height before committing so we don't allow rogue peers to send us a lose - // tx that resets our height to zero. - if txn.Height <= 0 { - ts.Txns().UpdateHeight(tx.TxHash(), int(height), timestamp) - ts.txids[tx.TxHash().String()] = height - if height > 0 { - cb.Value = txn.Value - shouldCallback = true - } - } - cb.BlockTime = timestamp - ts.txidsMutex.Unlock() - if shouldCallback { - // Callback on listeners - for _, listener := range ts.listeners { - listener(cb) - } - } - ts.cbMutex.Unlock() - ts.PopulateAdrs() - hits++ - } - return hits, err -} - -func (ts *TxStore) markAsDead(txid chainhash.Hash) error { - stxos, err := ts.Stxos().GetAll() - if err != nil { - return err - } - markStxoAsDead := func(s wallet.Stxo) error { - err := ts.Stxos().Delete(s) - if err != nil { - return err - } - err = ts.Txns().UpdateHeight(s.SpendTxid, -1, time.Now()) - if err != nil { - return err - } - return nil - } - for _, s := range stxos { - // If an stxo is marked dead, move it back into the utxo table - if txid.IsEqual(&s.SpendTxid) { - if err := markStxoAsDead(s); err != nil { - return err - } - if err := ts.Utxos().Put(s.Utxo); err != nil { - return err - } - } - // If a dependency of the spend is dead then mark the spend as dead - if txid.IsEqual(&s.Utxo.Op.Hash) { - if err := markStxoAsDead(s); err != nil { - return err - } - if err := ts.markAsDead(s.SpendTxid); err != nil { - return err - } - } - } - utxos, err := ts.Utxos().GetAll() - if err != nil { - return err - } - // Dead utxos should just be deleted - for _, u := range utxos { - if txid.IsEqual(&u.Op.Hash) { - err := ts.Utxos().Delete(u) - if err != nil { - return err - } - } - } - ts.Txns().UpdateHeight(txid, -1, time.Now()) - return nil -} - -func (ts *TxStore) processReorg(lastGoodHeight uint32) error { - txns, err := ts.Txns().GetAll(true) - if err != nil { - return err - } - for i := len(txns) - 1; i >= 0; i-- { - if txns[i].Height > int32(lastGoodHeight) { - txid, err := chainhash.NewHashFromStr(txns[i].Txid) - if err != nil { - log.Error(err) - continue - } - err = ts.markAsDead(*txid) - if err != nil { - log.Error(err) - continue - } - } - } - return nil -} - -func (ts *TxStore) extractScriptAddress(script []byte) ([]byte, error) { - _, addrs, _, err := txscript.ExtractPkScriptAddrs(script, ts.params) - if err != nil { - return nil, err - } - if len(addrs) == 0 { - return nil, errors.New("unknown script") - } - return addrs[0].ScriptAddress(), nil -} - -func outPointsEqual(a, b wire.OutPoint) bool { - if !a.Hash.IsEqual(&b.Hash) { - return false - } - return a.Index == b.Index -} diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/wallet.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/wallet.go deleted file mode 100644 index 0ee4ce01c6..0000000000 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/wallet.go +++ /dev/null @@ -1,500 +0,0 @@ -package bitcoincash - -import ( - "errors" - "github.com/OpenBazaar/wallet-interface" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/peer" - btc "github.com/btcsuite/btcutil" - hd "github.com/btcsuite/btcutil/hdkeychain" - "github.com/btcsuite/btcwallet/wallet/txrules" - "github.com/cpacia/BitcoinCash-Wallet/exchangerates" - "github.com/cpacia/bchutil" - "github.com/op/go-logging" - b39 "github.com/tyler-smith/go-bip39" - "io" - "sync" - "time" -) - -func setupNetworkParams(params *chaincfg.Params) { - switch params.Name { - case chaincfg.MainNetParams.Name: - params.Net = bchutil.MainnetMagic - case chaincfg.TestNet3Params.Name: - params.Net = bchutil.TestnetMagic - case chaincfg.RegressionNetParams.Name: - params.Net = bchutil.Regtestmagic - } -} - -type SPVWallet struct { - params *chaincfg.Params - - masterPrivateKey *hd.ExtendedKey - masterPublicKey *hd.ExtendedKey - - mnemonic string - - feeProvider *FeeProvider - - repoPath string - - blockchain *Blockchain - txstore *TxStore - peerManager *PeerManager - keyManager *KeyManager - wireService *WireService - - fPositives chan *peer.Peer - stopChan chan int - fpAccumulator map[int32]int32 - mutex *sync.RWMutex - - creationDate time.Time - - running bool - - config *PeerManagerConfig - - exchangeRates wallet.ExchangeRates -} - -var log = logging.MustGetLogger("bitcoin") - -const WALLET_VERSION = "0.1.0" - -func NewSPVWallet(config *Config) (*SPVWallet, error) { - setupNetworkParams(config.Params) - - log.SetBackend(logging.AddModuleLevel(config.Logger)) - - if config.Mnemonic == "" { - ent, err := b39.NewEntropy(128) - if err != nil { - return nil, err - } - mnemonic, err := b39.NewMnemonic(ent) - if err != nil { - return nil, err - } - config.Mnemonic = mnemonic - config.CreationDate = time.Now() - } - seed := b39.NewSeed(config.Mnemonic, "") - - mPrivKey, err := hd.NewMaster(seed, config.Params) - if err != nil { - return nil, err - } - mPubKey, err := mPrivKey.Neuter() - if err != nil { - return nil, err - } - w := &SPVWallet{ - repoPath: config.RepoPath, - masterPrivateKey: mPrivKey, - masterPublicKey: mPubKey, - mnemonic: config.Mnemonic, - params: config.Params, - creationDate: config.CreationDate, - feeProvider: NewFeeProvider( - config.MaxFee, - config.HighFee, - config.MediumFee, - config.LowFee, - nil, - ), - fPositives: make(chan *peer.Peer), - stopChan: make(chan int), - fpAccumulator: make(map[int32]int32), - mutex: new(sync.RWMutex), - } - - er := exchangerates.NewBitcoinCashPriceFetcher(config.Proxy) - w.exchangeRates = er - if !config.DisableExchangeRates { - go er.Run() - w.feeProvider.exchangeRates = er - } - - w.keyManager, err = NewKeyManager(config.DB.Keys(), w.params, w.masterPrivateKey) - - w.txstore, err = NewTxStore(w.params, config.DB, w.keyManager, config.AdditionalFilters...) - if err != nil { - return nil, err - } - - w.blockchain, err = NewBlockchain(w.repoPath, w.creationDate, w.params) - if err != nil { - return nil, err - } - - minSync := 5 - if config.TrustedPeer != nil { - minSync = 1 - } - wireConfig := &WireServiceConfig{ - txStore: w.txstore, - chain: w.blockchain, - walletCreationDate: w.creationDate, - minPeersForSync: minSync, - params: w.params, - } - - ws := NewWireService(wireConfig) - w.wireService = ws - - getNewestBlock := func() (*chainhash.Hash, int32, error) { - sh, err := w.blockchain.BestBlock() - if err != nil { - return nil, 0, err - } - h := sh.header.BlockHash() - return &h, int32(sh.height), nil - } - - w.config = &PeerManagerConfig{ - UserAgentName: config.UserAgent, - UserAgentVersion: WALLET_VERSION, - Params: w.params, - AddressCacheDir: config.RepoPath, - Proxy: config.Proxy, - GetNewestBlock: getNewestBlock, - MsgChan: ws.MsgChan(), - } - - if config.TrustedPeer != nil { - w.config.TrustedPeer = config.TrustedPeer - } - - w.peerManager, err = NewPeerManager(w.config) - if err != nil { - return nil, err - } - - return w, nil -} - -func (w *SPVWallet) Start() { - w.running = true - go w.wireService.Start() - go w.peerManager.Start() -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// API -// -////////////// - -func (w *SPVWallet) CurrencyCode() string { - if w.params.Name == chaincfg.MainNetParams.Name { - return "bch" - } else { - return "tbch" - } -} - -func (w *SPVWallet) CreationDate() time.Time { - return w.creationDate -} - -func (w *SPVWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btc.Amount(amount), 25, txrules.DefaultRelayFeePerKb) -} - -func (w *SPVWallet) MasterPrivateKey() *hd.ExtendedKey { - return w.masterPrivateKey -} - -func (w *SPVWallet) MasterPublicKey() *hd.ExtendedKey { - return w.masterPublicKey -} - -func (w *SPVWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) { - parentFP := []byte{0x00, 0x00, 0x00, 0x00} - var id []byte - if isPrivateKey { - id = w.params.HDPrivateKeyID[:] - } else { - id = w.params.HDPublicKeyID[:] - } - hdKey := hd.NewExtendedKey( - id, - keyBytes, - chaincode, - parentFP, - 0, - 0, - isPrivateKey) - return hdKey.Child(0) -} - -func (w *SPVWallet) Mnemonic() string { - return w.mnemonic -} - -func (w *SPVWallet) ConnectedPeers() []*peer.Peer { - return w.peerManager.ConnectedPeers() -} - -func (w *SPVWallet) CurrentAddress(purpose wallet.KeyPurpose) btc.Address { - key, _ := w.keyManager.GetCurrentKey(purpose) - addr, _ := key.Address(w.params) - cashaddr, _ := bchutil.NewCashAddressPubKeyHash(addr.ScriptAddress(), w.params) - return btc.Address(cashaddr) -} - -func (w *SPVWallet) NewAddress(purpose wallet.KeyPurpose) btc.Address { - i, _ := w.txstore.Keys().GetUnused(purpose) - key, _ := w.keyManager.generateChildKey(purpose, uint32(i[1])) - addr, _ := key.Address(w.params) - w.txstore.Keys().MarkKeyAsUsed(addr.ScriptAddress()) - w.txstore.PopulateAdrs() - cashaddr, _ := bchutil.NewCashAddressPubKeyHash(addr.ScriptAddress(), w.params) - return btc.Address(cashaddr) -} - -func (w *SPVWallet) DecodeAddress(addr string) (btc.Address, error) { - // Legacy - decoded, err := btc.DecodeAddress(addr, w.params) - if err == nil { - return decoded, nil - } - // Cashaddr - decoded, err = bchutil.DecodeAddress(addr, w.params) - if err == nil { - return decoded, nil - } - // Bitpay - decoded, err = bchutil.DecodeBitpay(addr, w.params) - if err == nil { - return decoded, nil - } - return nil, errors.New("Unrecognized address format") -} - -func (w *SPVWallet) ScriptToAddress(script []byte) (btc.Address, error) { - return scriptToAddress(script, w.params) -} - -func scriptToAddress(script []byte, params *chaincfg.Params) (btc.Address, error) { - addr, err := bchutil.ExtractPkScriptAddrs(script, params) - if err != nil { - return nil, err - } - return btc.Address(addr), nil -} - -func (w *SPVWallet) AddressToScript(addr btc.Address) ([]byte, error) { - return bchutil.PayToAddrScript(addr) -} - -func (w *SPVWallet) HasKey(addr btc.Address) bool { - _, err := w.keyManager.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - return false - } - return true -} - -func (w *SPVWallet) GetKey(addr btc.Address) (*btcec.PrivateKey, error) { - key, err := w.keyManager.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - return nil, err - } - return key.ECPrivKey() -} - -func (w *SPVWallet) ListAddresses() []btc.Address { - keys := w.keyManager.GetKeys() - addrs := []btc.Address{} - for _, k := range keys { - addr, err := k.Address(w.params) - if err != nil { - continue - } - cashaddr, err := bchutil.NewCashAddressPubKeyHash(addr.ScriptAddress(), w.params) - if err != nil { - continue - } - addrs = append(addrs, cashaddr) - } - return addrs -} - -func (w *SPVWallet) ListKeys() []btcec.PrivateKey { - keys := w.keyManager.GetKeys() - list := []btcec.PrivateKey{} - for _, k := range keys { - priv, err := k.ECPrivKey() - if err != nil { - continue - } - list = append(list, *priv) - } - return list -} - -func (w *SPVWallet) ImportKey(privKey *btcec.PrivateKey, compress bool) error { - pub := privKey.PubKey() - var pubKeyBytes []byte - if compress { - pubKeyBytes = pub.SerializeCompressed() - } else { - pubKeyBytes = pub.SerializeUncompressed() - } - pkHash := btc.Hash160(pubKeyBytes) - addr, err := btc.NewAddressPubKeyHash(pkHash, w.params) - if err != nil { - return err - } - return w.keyManager.datastore.ImportKey(addr.ScriptAddress(), privKey) -} - -func (w *SPVWallet) Balance() (confirmed, unconfirmed int64) { - utxos, _ := w.txstore.Utxos().GetAll() - stxos, _ := w.txstore.Stxos().GetAll() - for _, utxo := range utxos { - if !utxo.WatchOnly { - if utxo.AtHeight > 0 { - confirmed += utxo.Value - } else { - if w.checkIfStxoIsConfirmed(utxo, stxos) { - confirmed += utxo.Value - } else { - unconfirmed += utxo.Value - } - } - } - } - return confirmed, unconfirmed -} - -func (w *SPVWallet) Transactions() ([]wallet.Txn, error) { - height, _ := w.ChainTip() - txns, err := w.txstore.Txns().GetAll(false) - if err != nil { - return txns, err - } - for i, tx := range txns { - var confirmations int32 - var status wallet.StatusCode - confs := int32(height) - tx.Height + 1 - if tx.Height <= 0 { - confs = tx.Height - } - switch { - case confs < 0: - status = wallet.StatusDead - case confs == 0 && time.Since(tx.Timestamp) <= time.Hour*6: - status = wallet.StatusUnconfirmed - case confs == 0 && time.Since(tx.Timestamp) > time.Hour*6: - status = wallet.StatusStuck - case confs > 0 && confs < 6: - status = wallet.StatusPending - confirmations = confs - case confs > 5: - status = wallet.StatusConfirmed - confirmations = confs - } - tx.Confirmations = int64(confirmations) - tx.Status = status - txns[i] = tx - } - return txns, nil -} - -func (w *SPVWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) { - txn, err := w.txstore.Txns().Get(txid) - return txn, err -} - -func (w *SPVWallet) GetConfirmations(txid chainhash.Hash) (uint32, uint32, error) { - txn, err := w.txstore.Txns().Get(txid) - if err != nil { - return 0, 0, err - } - if txn.Height == 0 { - return 0, 0, nil - } - chainTip, _ := w.ChainTip() - return chainTip - uint32(txn.Height) + 1, uint32(txn.Height), nil -} - -func (w *SPVWallet) checkIfStxoIsConfirmed(utxo wallet.Utxo, stxos []wallet.Stxo) bool { - for _, stxo := range stxos { - if !stxo.Utxo.WatchOnly { - if stxo.SpendTxid.IsEqual(&utxo.Op.Hash) { - if stxo.SpendHeight > 0 { - return true - } else { - return w.checkIfStxoIsConfirmed(stxo.Utxo, stxos) - } - } else if stxo.Utxo.IsEqual(&utxo) { - if stxo.Utxo.AtHeight > 0 { - return true - } else { - return false - } - } - } - } - return false -} - -func (w *SPVWallet) Params() *chaincfg.Params { - return w.params -} - -func (w *SPVWallet) AddTransactionListener(callback func(wallet.TransactionCallback)) { - w.txstore.listeners = append(w.txstore.listeners, callback) -} - -func (w *SPVWallet) ChainTip() (uint32, chainhash.Hash) { - var ch chainhash.Hash - sh, err := w.blockchain.db.GetBestHeader() - if err != nil { - return 0, ch - } - return sh.height, sh.header.BlockHash() -} - -func (w *SPVWallet) AddWatchedAddress(addr btc.Address) error { - script, err := w.AddressToScript(addr) - if err != nil { - return err - } - err = w.txstore.WatchedScripts().Put(script) - w.txstore.PopulateAdrs() - - w.wireService.MsgChan() <- updateFiltersMsg{} - return err -} - -func (w *SPVWallet) DumpHeaders(writer io.Writer) { - w.blockchain.db.Print(writer) -} - -func (w *SPVWallet) ExchangeRates() wallet.ExchangeRates { - return w.exchangeRates -} - -func (w *SPVWallet) Close() { - if w.running { - log.Info("Disconnecting from peers and shutting down") - w.peerManager.Stop() - w.blockchain.Close() - w.wireService.Stop() - w.running = false - } -} - -func (w *SPVWallet) ReSyncBlockchain(fromDate time.Time) { - w.blockchain.Rollback(fromDate) - w.txstore.PopulateAdrs() - w.wireService.Resync() -} diff --git a/vendor/github.com/disintegration/imaging/.travis.yml b/vendor/github.com/disintegration/imaging/.travis.yml new file mode 100644 index 0000000000..1d4bdd5c03 --- /dev/null +++ b/vendor/github.com/disintegration/imaging/.travis.yml @@ -0,0 +1,14 @@ +language: go +go: + - "1.7.x" + - "1.8.x" + - "1.9.x" + - "1.10.x" + - "1.11.x" + +before_install: + - go get github.com/mattn/goveralls + +script: + - go test -v -race -cover + - $GOPATH/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/LICENSE b/vendor/github.com/disintegration/imaging/LICENSE similarity index 90% rename from vendor/github.com/cpacia/BitcoinCash-Wallet/LICENSE rename to vendor/github.com/disintegration/imaging/LICENSE index 1992900d2e..a4144a9d2f 100644 --- a/vendor/github.com/cpacia/BitcoinCash-Wallet/LICENSE +++ b/vendor/github.com/disintegration/imaging/LICENSE @@ -1,7 +1,6 @@ The MIT License (MIT) -Copyright (C) 2015-2016 The Lightning Network Developers -Copyright (c) 2016-2017 The OpenBazaar Developers +Copyright (c) 2012 Grigory Dryapak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/disintegration/imaging/README.md b/vendor/github.com/disintegration/imaging/README.md new file mode 100644 index 0000000000..a1fd764d2c --- /dev/null +++ b/vendor/github.com/disintegration/imaging/README.md @@ -0,0 +1,226 @@ +# Imaging + +[![GoDoc](https://godoc.org/github.com/disintegration/imaging?status.svg)](https://godoc.org/github.com/disintegration/imaging) +[![Build Status](https://travis-ci.org/disintegration/imaging.svg?branch=master)](https://travis-ci.org/disintegration/imaging) +[![Coverage Status](https://coveralls.io/repos/github/disintegration/imaging/badge.svg?branch=master&service=github)](https://coveralls.io/github/disintegration/imaging?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/disintegration/imaging)](https://goreportcard.com/report/github.com/disintegration/imaging) + +Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.). + +All the image processing functions provided by the package accept any image type that implements `image.Image` interface +as an input, and return a new image of `*image.NRGBA` type (32bit RGBA colors, non-premultiplied alpha). + +## Installation + + go get -u github.com/disintegration/imaging + +## Documentation + +http://godoc.org/github.com/disintegration/imaging + +## Usage examples + +A few usage examples can be found below. See the documentation for the full list of supported functions. + +### Image resizing + +```go +// Resize srcImage to size = 128x128px using the Lanczos filter. +dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos) + +// Resize srcImage to width = 800px preserving the aspect ratio. +dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos) + +// Scale down srcImage to fit the 800x600px bounding box. +dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos) + +// Resize and crop the srcImage to fill the 100x100px area. +dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos) +``` + +Imaging supports image resizing using various resampling filters. The most notable ones: +- `Lanczos` - A high-quality resampling filter for photographic images yielding sharp results. +- `CatmullRom` - A sharp cubic filter that is faster than Lanczos filter while providing similar results. +- `MitchellNetravali` - A cubic filter that produces smoother results with less ringing artifacts than CatmullRom. +- `Linear` - Bilinear resampling filter, produces smooth output. Faster than cubic filters. +- `Box` - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor. +- `NearestNeighbor` - Fastest resampling filter, no antialiasing. + +The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. Custom filters can be created using ResampleFilter struct. + +**Resampling filters comparison** + +Original image: + +![srcImage](testdata/branches.png) + +The same image resized from 600x400px to 150x100px using different resampling filters. +From faster (lower quality) to slower (higher quality): + +Filter | Resize result +--------------------------|--------------------------------------------- +`imaging.NearestNeighbor` | ![dstImage](testdata/out_resize_nearest.png) +`imaging.Linear` | ![dstImage](testdata/out_resize_linear.png) +`imaging.CatmullRom` | ![dstImage](testdata/out_resize_catrom.png) +`imaging.Lanczos` | ![dstImage](testdata/out_resize_lanczos.png) + + +### Gaussian Blur + +```go +dstImage := imaging.Blur(srcImage, 0.5) +``` + +Sigma parameter allows to control the strength of the blurring effect. + +Original image | Sigma = 0.5 | Sigma = 1.5 +-----------------------------------|----------------------------------------|--------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png) + +### Sharpening + +```go +dstImage := imaging.Sharpen(srcImage, 0.5) +``` + +`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect. + +Original image | Sigma = 0.5 | Sigma = 1.5 +-----------------------------------|-------------------------------------------|------------------------------------------ +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png) + +### Gamma correction + +```go +dstImage := imaging.AdjustGamma(srcImage, 0.75) +``` + +Original image | Gamma = 0.75 | Gamma = 1.25 +-----------------------------------|------------------------------------------|----------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png) + +### Contrast adjustment + +```go +dstImage := imaging.AdjustContrast(srcImage, 20) +``` + +Original image | Contrast = 15 | Contrast = -15 +-----------------------------------|--------------------------------------------|------------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_contrast_p15.png) | ![dstImage](testdata/out_contrast_m15.png) + +### Brightness adjustment + +```go +dstImage := imaging.AdjustBrightness(srcImage, 20) +``` + +Original image | Brightness = 10 | Brightness = -10 +-----------------------------------|----------------------------------------------|--------------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png) + +### Saturation adjustment + +```go +dstImage := imaging.AdjustSaturation(srcImage, 20) +``` + +Original image | Saturation = 30 | Saturation = -30 +-----------------------------------|----------------------------------------------|--------------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_saturation_p30.png) | ![dstImage](testdata/out_saturation_m30.png) + +## FAQ + +### Incorrect image orientation after processing (e.g. an image appears rotated after resizing) + +Most probably, the given image contains the EXIF orientation tag. +The stadard `image/*` packages do not support loading and saving +this kind of information. To fix the issue, try opening images with +the `AutoOrientation` decode option. If this option is set to `true`, +the image orientation is changed after decoding, according to the +orientation tag (if present). Here's the example: + +```go +img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true)) +``` + +### What's the difference between `imaging` and `gift` packages? + +[imaging](https://github.com/disintegration/imaging) +is designed to be a lightweight and simple image manipulation package. +It provides basic image processing functions and a few helper functions +such as `Open` and `Save`. It consistently returns *image.NRGBA image +type (8 bits per channel, RGBA). + +[gift](https://github.com/disintegration/gift) +supports more advanced image processing, for example, sRGB/Linear color +space conversions. It also supports different output image types +(e.g. 16 bits per channel) and provides easy-to-use API for chaining +multiple processing steps together. + +## Example code + +```go +package main + +import ( + "image" + "image/color" + "log" + + "github.com/disintegration/imaging" +) + +func main() { + // Open a test image. + src, err := imaging.Open("testdata/flowers.png") + if err != nil { + log.Fatalf("failed to open image: %v", err) + } + + // Crop the original image to 300x300px size using the center anchor. + src = imaging.CropAnchor(src, 300, 300, imaging.Center) + + // Resize the cropped image to width = 200px preserving the aspect ratio. + src = imaging.Resize(src, 200, 0, imaging.Lanczos) + + // Create a blurred version of the image. + img1 := imaging.Blur(src, 5) + + // Create a grayscale version of the image with higher contrast and sharpness. + img2 := imaging.Grayscale(src) + img2 = imaging.AdjustContrast(img2, 20) + img2 = imaging.Sharpen(img2, 2) + + // Create an inverted version of the image. + img3 := imaging.Invert(src) + + // Create an embossed version of the image using a convolution filter. + img4 := imaging.Convolve3x3( + src, + [9]float64{ + -1, -1, 0, + -1, 1, 1, + 0, 1, 1, + }, + nil, + ) + + // Create a new image and paste the four produced images into it. + dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0}) + dst = imaging.Paste(dst, img1, image.Pt(0, 0)) + dst = imaging.Paste(dst, img2, image.Pt(0, 200)) + dst = imaging.Paste(dst, img3, image.Pt(200, 0)) + dst = imaging.Paste(dst, img4, image.Pt(200, 200)) + + // Save the resulting image as JPEG. + err = imaging.Save(dst, "testdata/out_example.jpg") + if err != nil { + log.Fatalf("failed to save image: %v", err) + } +} +``` + +Output: + +![dstImage](testdata/out_example.jpg) diff --git a/vendor/github.com/disintegration/imaging/adjust.go b/vendor/github.com/disintegration/imaging/adjust.go new file mode 100644 index 0000000000..daaf1de860 --- /dev/null +++ b/vendor/github.com/disintegration/imaging/adjust.go @@ -0,0 +1,253 @@ +package imaging + +import ( + "image" + "image/color" + "math" +) + +// Grayscale produces a grayscale version of the image. +func Grayscale(img image.Image) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4]) + for x := 0; x < src.w; x++ { + d := dst.Pix[i : i+3 : i+3] + r := d[0] + g := d[1] + b := d[2] + f := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b) + y := uint8(f + 0.5) + d[0] = y + d[1] = y + d[2] = y + i += 4 + } + } + }) + return dst +} + +// Invert produces an inverted (negated) version of the image. +func Invert(img image.Image) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4]) + for x := 0; x < src.w; x++ { + d := dst.Pix[i : i+3 : i+3] + d[0] = 255 - d[0] + d[1] = 255 - d[1] + d[2] = 255 - d[2] + i += 4 + } + } + }) + return dst +} + +// AdjustSaturation changes the saturation of the image using the percentage parameter and returns the adjusted image. +// The percentage must be in the range (-100, 100). +// The percentage = 0 gives the original image. +// The percentage = 100 gives the image with the saturation value doubled for each pixel. +// The percentage = -100 gives the image with the saturation value zeroed for each pixel (grayscale). +// +// Examples: +// dstImage = imaging.AdjustSaturation(srcImage, 25) // Increase image saturation by 25%. +// dstImage = imaging.AdjustSaturation(srcImage, -10) // Decrease image saturation by 10%. +// +func AdjustSaturation(img image.Image, percentage float64) *image.NRGBA { + percentage = math.Min(math.Max(percentage, -100), 100) + multiplier := 1 + percentage/100 + + return AdjustFunc(img, func(c color.NRGBA) color.NRGBA { + h, s, l := rgbToHSL(c.R, c.G, c.B) + s *= multiplier + if s > 1 { + s = 1 + } + r, g, b := hslToRGB(h, s, l) + return color.NRGBA{r, g, b, c.A} + }) +} + +// AdjustContrast changes the contrast of the image using the percentage parameter and returns the adjusted image. +// The percentage must be in range (-100, 100). The percentage = 0 gives the original image. +// The percentage = -100 gives solid gray image. +// +// Examples: +// +// dstImage = imaging.AdjustContrast(srcImage, -10) // Decrease image contrast by 10%. +// dstImage = imaging.AdjustContrast(srcImage, 20) // Increase image contrast by 20%. +// +func AdjustContrast(img image.Image, percentage float64) *image.NRGBA { + percentage = math.Min(math.Max(percentage, -100.0), 100.0) + lut := make([]uint8, 256) + + v := (100.0 + percentage) / 100.0 + for i := 0; i < 256; i++ { + switch { + case 0 <= v && v <= 1: + lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*v) * 255.0) + case 1 < v && v < 2: + lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*(1/(2.0-v))) * 255.0) + default: + lut[i] = uint8(float64(i)/255.0+0.5) * 255 + } + } + + return adjustLUT(img, lut) +} + +// AdjustBrightness changes the brightness of the image using the percentage parameter and returns the adjusted image. +// The percentage must be in range (-100, 100). The percentage = 0 gives the original image. +// The percentage = -100 gives solid black image. The percentage = 100 gives solid white image. +// +// Examples: +// +// dstImage = imaging.AdjustBrightness(srcImage, -15) // Decrease image brightness by 15%. +// dstImage = imaging.AdjustBrightness(srcImage, 10) // Increase image brightness by 10%. +// +func AdjustBrightness(img image.Image, percentage float64) *image.NRGBA { + percentage = math.Min(math.Max(percentage, -100.0), 100.0) + lut := make([]uint8, 256) + + shift := 255.0 * percentage / 100.0 + for i := 0; i < 256; i++ { + lut[i] = clamp(float64(i) + shift) + } + + return adjustLUT(img, lut) +} + +// AdjustGamma performs a gamma correction on the image and returns the adjusted image. +// Gamma parameter must be positive. Gamma = 1.0 gives the original image. +// Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it. +// +// Example: +// +// dstImage = imaging.AdjustGamma(srcImage, 0.7) +// +func AdjustGamma(img image.Image, gamma float64) *image.NRGBA { + e := 1.0 / math.Max(gamma, 0.0001) + lut := make([]uint8, 256) + + for i := 0; i < 256; i++ { + lut[i] = clamp(math.Pow(float64(i)/255.0, e) * 255.0) + } + + return adjustLUT(img, lut) +} + +// AdjustSigmoid changes the contrast of the image using a sigmoidal function and returns the adjusted image. +// It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail. +// The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5. +// The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10). +// If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased. +// +// Examples: +// +// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, 3.0) // Increase the contrast. +// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, -3.0) // Decrease the contrast. +// +func AdjustSigmoid(img image.Image, midpoint, factor float64) *image.NRGBA { + if factor == 0 { + return Clone(img) + } + + lut := make([]uint8, 256) + a := math.Min(math.Max(midpoint, 0.0), 1.0) + b := math.Abs(factor) + sig0 := sigmoid(a, b, 0) + sig1 := sigmoid(a, b, 1) + e := 1.0e-6 + + if factor > 0 { + for i := 0; i < 256; i++ { + x := float64(i) / 255.0 + sigX := sigmoid(a, b, x) + f := (sigX - sig0) / (sig1 - sig0) + lut[i] = clamp(f * 255.0) + } + } else { + for i := 0; i < 256; i++ { + x := float64(i) / 255.0 + arg := math.Min(math.Max((sig1-sig0)*x+sig0, e), 1.0-e) + f := a - math.Log(1.0/arg-1.0)/b + lut[i] = clamp(f * 255.0) + } + } + + return adjustLUT(img, lut) +} + +func sigmoid(a, b, x float64) float64 { + return 1 / (1 + math.Exp(b*(a-x))) +} + +// adjustLUT applies the given lookup table to the colors of the image. +func adjustLUT(img image.Image, lut []uint8) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + lut = lut[0:256] + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4]) + for x := 0; x < src.w; x++ { + d := dst.Pix[i : i+3 : i+3] + d[0] = lut[d[0]] + d[1] = lut[d[1]] + d[2] = lut[d[2]] + i += 4 + } + } + }) + return dst +} + +// AdjustFunc applies the fn function to each pixel of the img image and returns the adjusted image. +// +// Example: +// +// dstImage = imaging.AdjustFunc( +// srcImage, +// func(c color.NRGBA) color.NRGBA { +// // Shift the red channel by 16. +// r := int(c.R) + 16 +// if r > 255 { +// r = 255 +// } +// return color.NRGBA{uint8(r), c.G, c.B, c.A} +// } +// ) +// +func AdjustFunc(img image.Image, fn func(c color.NRGBA) color.NRGBA) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4]) + for x := 0; x < src.w; x++ { + d := dst.Pix[i : i+4 : i+4] + r := d[0] + g := d[1] + b := d[2] + a := d[3] + c := fn(color.NRGBA{r, g, b, a}) + d[0] = c.R + d[1] = c.G + d[2] = c.B + d[3] = c.A + i += 4 + } + } + }) + return dst +} diff --git a/vendor/github.com/disintegration/imaging/convolution.go b/vendor/github.com/disintegration/imaging/convolution.go new file mode 100644 index 0000000000..11eddc1623 --- /dev/null +++ b/vendor/github.com/disintegration/imaging/convolution.go @@ -0,0 +1,148 @@ +package imaging + +import ( + "image" +) + +// ConvolveOptions are convolution parameters. +type ConvolveOptions struct { + // If Normalize is true the kernel is normalized before convolution. + Normalize bool + + // If Abs is true the absolute value of each color channel is taken after convolution. + Abs bool + + // Bias is added to each color channel value after convolution. + Bias int +} + +// Convolve3x3 convolves the image with the specified 3x3 convolution kernel. +// Default parameters are used if a nil *ConvolveOptions is passed. +func Convolve3x3(img image.Image, kernel [9]float64, options *ConvolveOptions) *image.NRGBA { + return convolve(img, kernel[:], options) +} + +// Convolve5x5 convolves the image with the specified 5x5 convolution kernel. +// Default parameters are used if a nil *ConvolveOptions is passed. +func Convolve5x5(img image.Image, kernel [25]float64, options *ConvolveOptions) *image.NRGBA { + return convolve(img, kernel[:], options) +} + +func convolve(img image.Image, kernel []float64, options *ConvolveOptions) *image.NRGBA { + src := toNRGBA(img) + w := src.Bounds().Max.X + h := src.Bounds().Max.Y + dst := image.NewNRGBA(image.Rect(0, 0, w, h)) + + if w < 1 || h < 1 { + return dst + } + + if options == nil { + options = &ConvolveOptions{} + } + + if options.Normalize { + normalizeKernel(kernel) + } + + type coef struct { + x, y int + k float64 + } + var coefs []coef + var m int + + switch len(kernel) { + case 9: + m = 1 + case 25: + m = 2 + } + + i := 0 + for y := -m; y <= m; y++ { + for x := -m; x <= m; x++ { + if kernel[i] != 0 { + coefs = append(coefs, coef{x: x, y: y, k: kernel[i]}) + } + i++ + } + } + + parallel(0, h, func(ys <-chan int) { + for y := range ys { + for x := 0; x < w; x++ { + var r, g, b float64 + for _, c := range coefs { + ix := x + c.x + if ix < 0 { + ix = 0 + } else if ix >= w { + ix = w - 1 + } + + iy := y + c.y + if iy < 0 { + iy = 0 + } else if iy >= h { + iy = h - 1 + } + + off := iy*src.Stride + ix*4 + s := src.Pix[off : off+3 : off+3] + r += float64(s[0]) * c.k + g += float64(s[1]) * c.k + b += float64(s[2]) * c.k + } + + if options.Abs { + if r < 0 { + r = -r + } + if g < 0 { + g = -g + } + if b < 0 { + b = -b + } + } + + if options.Bias != 0 { + r += float64(options.Bias) + g += float64(options.Bias) + b += float64(options.Bias) + } + + srcOff := y*src.Stride + x*4 + dstOff := y*dst.Stride + x*4 + d := dst.Pix[dstOff : dstOff+4 : dstOff+4] + d[0] = clamp(r) + d[1] = clamp(g) + d[2] = clamp(b) + d[3] = src.Pix[srcOff+3] + } + } + }) + + return dst +} + +func normalizeKernel(kernel []float64) { + var sum, sumpos float64 + for i := range kernel { + sum += kernel[i] + if kernel[i] > 0 { + sumpos += kernel[i] + } + } + if sum != 0 { + for i := range kernel { + kernel[i] /= sum + } + } else if sumpos != 0 { + for i := range kernel { + kernel[i] /= sumpos + } + } +} diff --git a/vendor/github.com/disintegration/imaging/doc.go b/vendor/github.com/disintegration/imaging/doc.go new file mode 100644 index 0000000000..c98c91250d --- /dev/null +++ b/vendor/github.com/disintegration/imaging/doc.go @@ -0,0 +1,7 @@ +/* +Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.). + +All the image processing functions provided by the package accept any image type that implements image.Image interface +as an input, and return a new image of *image.NRGBA type (32bit RGBA colors, non-premultiplied alpha). +*/ +package imaging diff --git a/vendor/github.com/disintegration/imaging/effects.go b/vendor/github.com/disintegration/imaging/effects.go new file mode 100644 index 0000000000..47316b701c --- /dev/null +++ b/vendor/github.com/disintegration/imaging/effects.go @@ -0,0 +1,169 @@ +package imaging + +import ( + "image" + "math" +) + +func gaussianBlurKernel(x, sigma float64) float64 { + return math.Exp(-(x*x)/(2*sigma*sigma)) / (sigma * math.Sqrt(2*math.Pi)) +} + +// Blur produces a blurred version of the image using a Gaussian function. +// Sigma parameter must be positive and indicates how much the image will be blurred. +// +// Example: +// +// dstImage := imaging.Blur(srcImage, 3.5) +// +func Blur(img image.Image, sigma float64) *image.NRGBA { + if sigma <= 0 { + return Clone(img) + } + + radius := int(math.Ceil(sigma * 3.0)) + kernel := make([]float64, radius+1) + + for i := 0; i <= radius; i++ { + kernel[i] = gaussianBlurKernel(float64(i), sigma) + } + + return blurVertical(blurHorizontal(img, kernel), kernel) +} + +func blurHorizontal(img image.Image, kernel []float64) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + radius := len(kernel) - 1 + + parallel(0, src.h, func(ys <-chan int) { + scanLine := make([]uint8, src.w*4) + scanLineF := make([]float64, len(scanLine)) + for y := range ys { + src.scan(0, y, src.w, y+1, scanLine) + for i, v := range scanLine { + scanLineF[i] = float64(v) + } + for x := 0; x < src.w; x++ { + min := x - radius + if min < 0 { + min = 0 + } + max := x + radius + if max > src.w-1 { + max = src.w - 1 + } + var r, g, b, a, wsum float64 + for ix := min; ix <= max; ix++ { + i := ix * 4 + weight := kernel[absint(x-ix)] + wsum += weight + s := scanLineF[i : i+4 : i+4] + wa := s[3] * weight + r += s[0] * wa + g += s[1] * wa + b += s[2] * wa + a += wa + } + if a != 0 { + aInv := 1 / a + j := y*dst.Stride + x*4 + d := dst.Pix[j : j+4 : j+4] + d[0] = clamp(r * aInv) + d[1] = clamp(g * aInv) + d[2] = clamp(b * aInv) + d[3] = clamp(a / wsum) + } + } + } + }) + + return dst +} + +func blurVertical(img image.Image, kernel []float64) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + radius := len(kernel) - 1 + + parallel(0, src.w, func(xs <-chan int) { + scanLine := make([]uint8, src.h*4) + scanLineF := make([]float64, len(scanLine)) + for x := range xs { + src.scan(x, 0, x+1, src.h, scanLine) + for i, v := range scanLine { + scanLineF[i] = float64(v) + } + for y := 0; y < src.h; y++ { + min := y - radius + if min < 0 { + min = 0 + } + max := y + radius + if max > src.h-1 { + max = src.h - 1 + } + var r, g, b, a, wsum float64 + for iy := min; iy <= max; iy++ { + i := iy * 4 + weight := kernel[absint(y-iy)] + wsum += weight + s := scanLineF[i : i+4 : i+4] + wa := s[3] * weight + r += s[0] * wa + g += s[1] * wa + b += s[2] * wa + a += wa + } + if a != 0 { + aInv := 1 / a + j := y*dst.Stride + x*4 + d := dst.Pix[j : j+4 : j+4] + d[0] = clamp(r * aInv) + d[1] = clamp(g * aInv) + d[2] = clamp(b * aInv) + d[3] = clamp(a / wsum) + } + } + } + }) + + return dst +} + +// Sharpen produces a sharpened version of the image. +// Sigma parameter must be positive and indicates how much the image will be sharpened. +// +// Example: +// +// dstImage := imaging.Sharpen(srcImage, 3.5) +// +func Sharpen(img image.Image, sigma float64) *image.NRGBA { + if sigma <= 0 { + return Clone(img) + } + + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + blurred := Blur(img, sigma) + + parallel(0, src.h, func(ys <-chan int) { + scanLine := make([]uint8, src.w*4) + for y := range ys { + src.scan(0, y, src.w, y+1, scanLine) + j := y * dst.Stride + for i := 0; i < src.w*4; i++ { + val := int(scanLine[i])<<1 - int(blurred.Pix[j]) + if val < 0 { + val = 0 + } else if val > 0xff { + val = 0xff + } + dst.Pix[j] = uint8(val) + j++ + } + } + }) + + return dst +} diff --git a/vendor/github.com/disintegration/imaging/go.mod b/vendor/github.com/disintegration/imaging/go.mod new file mode 100644 index 0000000000..126e8cc66b --- /dev/null +++ b/vendor/github.com/disintegration/imaging/go.mod @@ -0,0 +1,3 @@ +module github.com/disintegration/imaging + +require golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81 diff --git a/vendor/github.com/disintegration/imaging/go.sum b/vendor/github.com/disintegration/imaging/go.sum new file mode 100644 index 0000000000..20c92e460a --- /dev/null +++ b/vendor/github.com/disintegration/imaging/go.sum @@ -0,0 +1,2 @@ +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81 h1:00VmoueYNlNz/aHIilyyQz/MHSqGoWJzpFv/HW8xpzI= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= diff --git a/vendor/github.com/disintegration/imaging/histogram.go b/vendor/github.com/disintegration/imaging/histogram.go new file mode 100644 index 0000000000..c547fe8222 --- /dev/null +++ b/vendor/github.com/disintegration/imaging/histogram.go @@ -0,0 +1,52 @@ +package imaging + +import ( + "image" + "sync" +) + +// Histogram returns a normalized histogram of an image. +// +// Resulting histogram is represented as an array of 256 floats, where +// histogram[i] is a probability of a pixel being of a particular luminance i. +func Histogram(img image.Image) [256]float64 { + var mu sync.Mutex + var histogram [256]float64 + var total float64 + + src := newScanner(img) + if src.w == 0 || src.h == 0 { + return histogram + } + + parallel(0, src.h, func(ys <-chan int) { + var tmpHistogram [256]float64 + var tmpTotal float64 + scanLine := make([]uint8, src.w*4) + for y := range ys { + src.scan(0, y, src.w, y+1, scanLine) + i := 0 + for x := 0; x < src.w; x++ { + s := scanLine[i : i+3 : i+3] + r := s[0] + g := s[1] + b := s[2] + y := 0.299*float32(r) + 0.587*float32(g) + 0.114*float32(b) + tmpHistogram[int(y+0.5)]++ + tmpTotal++ + i += 4 + } + } + mu.Lock() + for i := 0; i < 256; i++ { + histogram[i] += tmpHistogram[i] + } + total += tmpTotal + mu.Unlock() + }) + + for i := 0; i < 256; i++ { + histogram[i] = histogram[i] / total + } + return histogram +} diff --git a/vendor/github.com/disintegration/imaging/io.go b/vendor/github.com/disintegration/imaging/io.go new file mode 100644 index 0000000000..f6c6da86ba --- /dev/null +++ b/vendor/github.com/disintegration/imaging/io.go @@ -0,0 +1,444 @@ +package imaging + +import ( + "encoding/binary" + "errors" + "image" + "image/draw" + "image/gif" + "image/jpeg" + "image/png" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "golang.org/x/image/bmp" + "golang.org/x/image/tiff" +) + +type fileSystem interface { + Create(string) (io.WriteCloser, error) + Open(string) (io.ReadCloser, error) +} + +type localFS struct{} + +func (localFS) Create(name string) (io.WriteCloser, error) { return os.Create(name) } +func (localFS) Open(name string) (io.ReadCloser, error) { return os.Open(name) } + +var fs fileSystem = localFS{} + +type decodeConfig struct { + autoOrientation bool +} + +var defaultDecodeConfig = decodeConfig{ + autoOrientation: false, +} + +// DecodeOption sets an optional parameter for the Decode and Open functions. +type DecodeOption func(*decodeConfig) + +// AutoOrientation returns a DecodeOption that sets the auto-orientation mode. +// If auto-orientation is enabled, the image will be transformed after decoding +// according to the EXIF orientation tag (if present). By default it's disabled. +func AutoOrientation(enabled bool) DecodeOption { + return func(c *decodeConfig) { + c.autoOrientation = enabled + } +} + +// Decode reads an image from r. +func Decode(r io.Reader, opts ...DecodeOption) (image.Image, error) { + cfg := defaultDecodeConfig + for _, option := range opts { + option(&cfg) + } + + if !cfg.autoOrientation { + img, _, err := image.Decode(r) + return img, err + } + + var orient orientation + pr, pw := io.Pipe() + r = io.TeeReader(r, pw) + done := make(chan struct{}) + go func() { + defer close(done) + orient = readOrientation(pr) + io.Copy(ioutil.Discard, pr) + }() + + img, _, err := image.Decode(r) + pw.Close() + <-done + if err != nil { + return nil, err + } + + return fixOrientation(img, orient), nil +} + +// Open loads an image from file. +// +// Examples: +// +// // Load an image from file. +// img, err := imaging.Open("test.jpg") +// +// // Load an image and transform it depending on the EXIF orientation tag (if present). +// img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true)) +// +func Open(filename string, opts ...DecodeOption) (image.Image, error) { + file, err := fs.Open(filename) + if err != nil { + return nil, err + } + defer file.Close() + return Decode(file, opts...) +} + +// Format is an image file format. +type Format int + +// Image file formats. +const ( + JPEG Format = iota + PNG + GIF + TIFF + BMP +) + +var formatExts = map[string]Format{ + "jpg": JPEG, + "jpeg": JPEG, + "png": PNG, + "gif": GIF, + "tif": TIFF, + "tiff": TIFF, + "bmp": BMP, +} + +var formatNames = map[Format]string{ + JPEG: "JPEG", + PNG: "PNG", + GIF: "GIF", + TIFF: "TIFF", + BMP: "BMP", +} + +func (f Format) String() string { + return formatNames[f] +} + +// ErrUnsupportedFormat means the given image format is not supported. +var ErrUnsupportedFormat = errors.New("imaging: unsupported image format") + +// FormatFromExtension parses image format from filename extension: +// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported. +func FormatFromExtension(ext string) (Format, error) { + if f, ok := formatExts[strings.ToLower(strings.TrimPrefix(ext, "."))]; ok { + return f, nil + } + return -1, ErrUnsupportedFormat +} + +// FormatFromFilename parses image format from filename: +// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported. +func FormatFromFilename(filename string) (Format, error) { + ext := filepath.Ext(filename) + return FormatFromExtension(ext) +} + +type encodeConfig struct { + jpegQuality int + gifNumColors int + gifQuantizer draw.Quantizer + gifDrawer draw.Drawer + pngCompressionLevel png.CompressionLevel +} + +var defaultEncodeConfig = encodeConfig{ + jpegQuality: 95, + gifNumColors: 256, + gifQuantizer: nil, + gifDrawer: nil, + pngCompressionLevel: png.DefaultCompression, +} + +// EncodeOption sets an optional parameter for the Encode and Save functions. +type EncodeOption func(*encodeConfig) + +// JPEGQuality returns an EncodeOption that sets the output JPEG quality. +// Quality ranges from 1 to 100 inclusive, higher is better. Default is 95. +func JPEGQuality(quality int) EncodeOption { + return func(c *encodeConfig) { + c.jpegQuality = quality + } +} + +// GIFNumColors returns an EncodeOption that sets the maximum number of colors +// used in the GIF-encoded image. It ranges from 1 to 256. Default is 256. +func GIFNumColors(numColors int) EncodeOption { + return func(c *encodeConfig) { + c.gifNumColors = numColors + } +} + +// GIFQuantizer returns an EncodeOption that sets the quantizer that is used to produce +// a palette of the GIF-encoded image. +func GIFQuantizer(quantizer draw.Quantizer) EncodeOption { + return func(c *encodeConfig) { + c.gifQuantizer = quantizer + } +} + +// GIFDrawer returns an EncodeOption that sets the drawer that is used to convert +// the source image to the desired palette of the GIF-encoded image. +func GIFDrawer(drawer draw.Drawer) EncodeOption { + return func(c *encodeConfig) { + c.gifDrawer = drawer + } +} + +// PNGCompressionLevel returns an EncodeOption that sets the compression level +// of the PNG-encoded image. Default is png.DefaultCompression. +func PNGCompressionLevel(level png.CompressionLevel) EncodeOption { + return func(c *encodeConfig) { + c.pngCompressionLevel = level + } +} + +// Encode writes the image img to w in the specified format (JPEG, PNG, GIF, TIFF or BMP). +func Encode(w io.Writer, img image.Image, format Format, opts ...EncodeOption) error { + cfg := defaultEncodeConfig + for _, option := range opts { + option(&cfg) + } + + switch format { + case JPEG: + if nrgba, ok := img.(*image.NRGBA); ok && nrgba.Opaque() { + rgba := &image.RGBA{ + Pix: nrgba.Pix, + Stride: nrgba.Stride, + Rect: nrgba.Rect, + } + return jpeg.Encode(w, rgba, &jpeg.Options{Quality: cfg.jpegQuality}) + } + return jpeg.Encode(w, img, &jpeg.Options{Quality: cfg.jpegQuality}) + + case PNG: + encoder := png.Encoder{CompressionLevel: cfg.pngCompressionLevel} + return encoder.Encode(w, img) + + case GIF: + return gif.Encode(w, img, &gif.Options{ + NumColors: cfg.gifNumColors, + Quantizer: cfg.gifQuantizer, + Drawer: cfg.gifDrawer, + }) + + case TIFF: + return tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true}) + + case BMP: + return bmp.Encode(w, img) + } + + return ErrUnsupportedFormat +} + +// Save saves the image to file with the specified filename. +// The format is determined from the filename extension: +// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported. +// +// Examples: +// +// // Save the image as PNG. +// err := imaging.Save(img, "out.png") +// +// // Save the image as JPEG with optional quality parameter set to 80. +// err := imaging.Save(img, "out.jpg", imaging.JPEGQuality(80)) +// +func Save(img image.Image, filename string, opts ...EncodeOption) (err error) { + f, err := FormatFromFilename(filename) + if err != nil { + return err + } + file, err := fs.Create(filename) + if err != nil { + return err + } + err = Encode(file, img, f, opts...) + errc := file.Close() + if err == nil { + err = errc + } + return err +} + +// orientation is an EXIF flag that specifies the transformation +// that should be applied to image to display it correctly. +type orientation int + +const ( + orientationUnspecified = 0 + orientationNormal = 1 + orientationFlipH = 2 + orientationRotate180 = 3 + orientationFlipV = 4 + orientationTranspose = 5 + orientationRotate270 = 6 + orientationTransverse = 7 + orientationRotate90 = 8 +) + +// readOrientation tries to read the orientation EXIF flag from image data in r. +// If the EXIF data block is not found or the orientation flag is not found +// or any other error occures while reading the data, it returns the +// orientationUnspecified (0) value. +func readOrientation(r io.Reader) orientation { + const ( + markerSOI = 0xffd8 + markerAPP1 = 0xffe1 + exifHeader = 0x45786966 + byteOrderBE = 0x4d4d + byteOrderLE = 0x4949 + orientationTag = 0x0112 + ) + + // Check if JPEG SOI marker is present. + var soi uint16 + if err := binary.Read(r, binary.BigEndian, &soi); err != nil { + return orientationUnspecified + } + if soi != markerSOI { + return orientationUnspecified // Missing JPEG SOI marker. + } + + // Find JPEG APP1 marker. + for { + var marker, size uint16 + if err := binary.Read(r, binary.BigEndian, &marker); err != nil { + return orientationUnspecified + } + if err := binary.Read(r, binary.BigEndian, &size); err != nil { + return orientationUnspecified + } + if marker>>8 != 0xff { + return orientationUnspecified // Invalid JPEG marker. + } + if marker == markerAPP1 { + break + } + if size < 2 { + return orientationUnspecified // Invalid block size. + } + if _, err := io.CopyN(ioutil.Discard, r, int64(size-2)); err != nil { + return orientationUnspecified + } + } + + // Check if EXIF header is present. + var header uint32 + if err := binary.Read(r, binary.BigEndian, &header); err != nil { + return orientationUnspecified + } + if header != exifHeader { + return orientationUnspecified + } + if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil { + return orientationUnspecified + } + + // Read byte order information. + var ( + byteOrderTag uint16 + byteOrder binary.ByteOrder + ) + if err := binary.Read(r, binary.BigEndian, &byteOrderTag); err != nil { + return orientationUnspecified + } + switch byteOrderTag { + case byteOrderBE: + byteOrder = binary.BigEndian + case byteOrderLE: + byteOrder = binary.LittleEndian + default: + return orientationUnspecified // Invalid byte order flag. + } + if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil { + return orientationUnspecified + } + + // Skip the EXIF offset. + var offset uint32 + if err := binary.Read(r, byteOrder, &offset); err != nil { + return orientationUnspecified + } + if offset < 8 { + return orientationUnspecified // Invalid offset value. + } + if _, err := io.CopyN(ioutil.Discard, r, int64(offset-8)); err != nil { + return orientationUnspecified + } + + // Read the number of tags. + var numTags uint16 + if err := binary.Read(r, byteOrder, &numTags); err != nil { + return orientationUnspecified + } + + // Find the orientation tag. + for i := 0; i < int(numTags); i++ { + var tag uint16 + if err := binary.Read(r, byteOrder, &tag); err != nil { + return orientationUnspecified + } + if tag != orientationTag { + if _, err := io.CopyN(ioutil.Discard, r, 10); err != nil { + return orientationUnspecified + } + continue + } + if _, err := io.CopyN(ioutil.Discard, r, 6); err != nil { + return orientationUnspecified + } + var val uint16 + if err := binary.Read(r, byteOrder, &val); err != nil { + return orientationUnspecified + } + if val < 1 || val > 8 { + return orientationUnspecified // Invalid tag value. + } + return orientation(val) + } + return orientationUnspecified // Missing orientation tag. +} + +// fixOrientation applies a transform to img corresponding to the given orientation flag. +func fixOrientation(img image.Image, o orientation) image.Image { + switch o { + case orientationNormal: + case orientationFlipH: + img = FlipH(img) + case orientationFlipV: + img = FlipV(img) + case orientationRotate90: + img = Rotate90(img) + case orientationRotate180: + img = Rotate180(img) + case orientationRotate270: + img = Rotate270(img) + case orientationTranspose: + img = Transpose(img) + case orientationTransverse: + img = Transverse(img) + } + return img +} diff --git a/vendor/github.com/disintegration/imaging/resize.go b/vendor/github.com/disintegration/imaging/resize.go new file mode 100644 index 0000000000..706435e3dc --- /dev/null +++ b/vendor/github.com/disintegration/imaging/resize.go @@ -0,0 +1,595 @@ +package imaging + +import ( + "image" + "math" +) + +type indexWeight struct { + index int + weight float64 +} + +func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWeight { + du := float64(srcSize) / float64(dstSize) + scale := du + if scale < 1.0 { + scale = 1.0 + } + ru := math.Ceil(scale * filter.Support) + + out := make([][]indexWeight, dstSize) + tmp := make([]indexWeight, 0, dstSize*int(ru+2)*2) + + for v := 0; v < dstSize; v++ { + fu := (float64(v)+0.5)*du - 0.5 + + begin := int(math.Ceil(fu - ru)) + if begin < 0 { + begin = 0 + } + end := int(math.Floor(fu + ru)) + if end > srcSize-1 { + end = srcSize - 1 + } + + var sum float64 + for u := begin; u <= end; u++ { + w := filter.Kernel((float64(u) - fu) / scale) + if w != 0 { + sum += w + tmp = append(tmp, indexWeight{index: u, weight: w}) + } + } + if sum != 0 { + for i := range tmp { + tmp[i].weight /= sum + } + } + + out[v] = tmp + tmp = tmp[len(tmp):] + } + + return out +} + +// Resize resizes the image to the specified width and height using the specified resampling +// filter and returns the transformed image. If one of width or height is 0, the image aspect +// ratio is preserved. +// +// Example: +// +// dstImage := imaging.Resize(srcImage, 800, 600, imaging.Lanczos) +// +func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA { + dstW, dstH := width, height + if dstW < 0 || dstH < 0 { + return &image.NRGBA{} + } + if dstW == 0 && dstH == 0 { + return &image.NRGBA{} + } + + srcW := img.Bounds().Dx() + srcH := img.Bounds().Dy() + if srcW <= 0 || srcH <= 0 { + return &image.NRGBA{} + } + + // If new width or height is 0 then preserve aspect ratio, minimum 1px. + if dstW == 0 { + tmpW := float64(dstH) * float64(srcW) / float64(srcH) + dstW = int(math.Max(1.0, math.Floor(tmpW+0.5))) + } + if dstH == 0 { + tmpH := float64(dstW) * float64(srcH) / float64(srcW) + dstH = int(math.Max(1.0, math.Floor(tmpH+0.5))) + } + + if filter.Support <= 0 { + // Nearest-neighbor special case. + return resizeNearest(img, dstW, dstH) + } + + if srcW != dstW && srcH != dstH { + return resizeVertical(resizeHorizontal(img, dstW, filter), dstH, filter) + } + if srcW != dstW { + return resizeHorizontal(img, dstW, filter) + } + if srcH != dstH { + return resizeVertical(img, dstH, filter) + } + return Clone(img) +} + +func resizeHorizontal(img image.Image, width int, filter ResampleFilter) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, width, src.h)) + weights := precomputeWeights(width, src.w, filter) + parallel(0, src.h, func(ys <-chan int) { + scanLine := make([]uint8, src.w*4) + for y := range ys { + src.scan(0, y, src.w, y+1, scanLine) + j0 := y * dst.Stride + for x := range weights { + var r, g, b, a float64 + for _, w := range weights[x] { + i := w.index * 4 + s := scanLine[i : i+4 : i+4] + aw := float64(s[3]) * w.weight + r += float64(s[0]) * aw + g += float64(s[1]) * aw + b += float64(s[2]) * aw + a += aw + } + if a != 0 { + aInv := 1 / a + j := j0 + x*4 + d := dst.Pix[j : j+4 : j+4] + d[0] = clamp(r * aInv) + d[1] = clamp(g * aInv) + d[2] = clamp(b * aInv) + d[3] = clamp(a) + } + } + } + }) + return dst +} + +func resizeVertical(img image.Image, height int, filter ResampleFilter) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, height)) + weights := precomputeWeights(height, src.h, filter) + parallel(0, src.w, func(xs <-chan int) { + scanLine := make([]uint8, src.h*4) + for x := range xs { + src.scan(x, 0, x+1, src.h, scanLine) + for y := range weights { + var r, g, b, a float64 + for _, w := range weights[y] { + i := w.index * 4 + s := scanLine[i : i+4 : i+4] + aw := float64(s[3]) * w.weight + r += float64(s[0]) * aw + g += float64(s[1]) * aw + b += float64(s[2]) * aw + a += aw + } + if a != 0 { + aInv := 1 / a + j := y*dst.Stride + x*4 + d := dst.Pix[j : j+4 : j+4] + d[0] = clamp(r * aInv) + d[1] = clamp(g * aInv) + d[2] = clamp(b * aInv) + d[3] = clamp(a) + } + } + } + }) + return dst +} + +// resizeNearest is a fast nearest-neighbor resize, no filtering. +func resizeNearest(img image.Image, width, height int) *image.NRGBA { + dst := image.NewNRGBA(image.Rect(0, 0, width, height)) + dx := float64(img.Bounds().Dx()) / float64(width) + dy := float64(img.Bounds().Dy()) / float64(height) + + if dx > 1 && dy > 1 { + src := newScanner(img) + parallel(0, height, func(ys <-chan int) { + for y := range ys { + srcY := int((float64(y) + 0.5) * dy) + dstOff := y * dst.Stride + for x := 0; x < width; x++ { + srcX := int((float64(x) + 0.5) * dx) + src.scan(srcX, srcY, srcX+1, srcY+1, dst.Pix[dstOff:dstOff+4]) + dstOff += 4 + } + } + }) + } else { + src := toNRGBA(img) + parallel(0, height, func(ys <-chan int) { + for y := range ys { + srcY := int((float64(y) + 0.5) * dy) + srcOff0 := srcY * src.Stride + dstOff := y * dst.Stride + for x := 0; x < width; x++ { + srcX := int((float64(x) + 0.5) * dx) + srcOff := srcOff0 + srcX*4 + copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) + dstOff += 4 + } + } + }) + } + + return dst +} + +// Fit scales down the image using the specified resample filter to fit the specified +// maximum width and height and returns the transformed image. +// +// Example: +// +// dstImage := imaging.Fit(srcImage, 800, 600, imaging.Lanczos) +// +func Fit(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA { + maxW, maxH := width, height + + if maxW <= 0 || maxH <= 0 { + return &image.NRGBA{} + } + + srcBounds := img.Bounds() + srcW := srcBounds.Dx() + srcH := srcBounds.Dy() + + if srcW <= 0 || srcH <= 0 { + return &image.NRGBA{} + } + + if srcW <= maxW && srcH <= maxH { + return Clone(img) + } + + srcAspectRatio := float64(srcW) / float64(srcH) + maxAspectRatio := float64(maxW) / float64(maxH) + + var newW, newH int + if srcAspectRatio > maxAspectRatio { + newW = maxW + newH = int(float64(newW) / srcAspectRatio) + } else { + newH = maxH + newW = int(float64(newH) * srcAspectRatio) + } + + return Resize(img, newW, newH, filter) +} + +// Fill creates an image with the specified dimensions and fills it with the scaled source image. +// To achieve the correct aspect ratio without stretching, the source image will be cropped. +// +// Example: +// +// dstImage := imaging.Fill(srcImage, 800, 600, imaging.Center, imaging.Lanczos) +// +func Fill(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA { + dstW, dstH := width, height + + if dstW <= 0 || dstH <= 0 { + return &image.NRGBA{} + } + + srcBounds := img.Bounds() + srcW := srcBounds.Dx() + srcH := srcBounds.Dy() + + if srcW <= 0 || srcH <= 0 { + return &image.NRGBA{} + } + + if srcW == dstW && srcH == dstH { + return Clone(img) + } + + if srcW >= 100 && srcH >= 100 { + return cropAndResize(img, dstW, dstH, anchor, filter) + } + return resizeAndCrop(img, dstW, dstH, anchor, filter) +} + +// cropAndResize crops the image to the smallest possible size that has the required aspect ratio using +// the given anchor point, then scales it to the specified dimensions and returns the transformed image. +// +// This is generally faster than resizing first, but may result in inaccuracies when used on small source images. +func cropAndResize(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA { + dstW, dstH := width, height + + srcBounds := img.Bounds() + srcW := srcBounds.Dx() + srcH := srcBounds.Dy() + srcAspectRatio := float64(srcW) / float64(srcH) + dstAspectRatio := float64(dstW) / float64(dstH) + + var tmp *image.NRGBA + if srcAspectRatio < dstAspectRatio { + cropH := float64(srcW) * float64(dstH) / float64(dstW) + tmp = CropAnchor(img, srcW, int(math.Max(1, cropH)+0.5), anchor) + } else { + cropW := float64(srcH) * float64(dstW) / float64(dstH) + tmp = CropAnchor(img, int(math.Max(1, cropW)+0.5), srcH, anchor) + } + + return Resize(tmp, dstW, dstH, filter) +} + +// resizeAndCrop resizes the image to the smallest possible size that will cover the specified dimensions, +// crops the resized image to the specified dimensions using the given anchor point and returns +// the transformed image. +func resizeAndCrop(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA { + dstW, dstH := width, height + + srcBounds := img.Bounds() + srcW := srcBounds.Dx() + srcH := srcBounds.Dy() + srcAspectRatio := float64(srcW) / float64(srcH) + dstAspectRatio := float64(dstW) / float64(dstH) + + var tmp *image.NRGBA + if srcAspectRatio < dstAspectRatio { + tmp = Resize(img, dstW, 0, filter) + } else { + tmp = Resize(img, 0, dstH, filter) + } + + return CropAnchor(tmp, dstW, dstH, anchor) +} + +// Thumbnail scales the image up or down using the specified resample filter, crops it +// to the specified width and hight and returns the transformed image. +// +// Example: +// +// dstImage := imaging.Thumbnail(srcImage, 100, 100, imaging.Lanczos) +// +func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA { + return Fill(img, width, height, Center, filter) +} + +// ResampleFilter specifies a resampling filter to be used for image resizing. +// +// General filter recommendations: +// +// - Lanczos +// A high-quality resampling filter for photographic images yielding sharp results. +// +// - CatmullRom +// A sharp cubic filter that is faster than Lanczos filter while providing similar results. +// +// - MitchellNetravali +// A cubic filter that produces smoother results with less ringing artifacts than CatmullRom. +// +// - Linear +// Bilinear resampling filter, produces a smooth output. Faster than cubic filters. +// +// - Box +// Simple and fast averaging filter appropriate for downscaling. +// When upscaling it's similar to NearestNeighbor. +// +// - NearestNeighbor +// Fastest resampling filter, no antialiasing. +// +type ResampleFilter struct { + Support float64 + Kernel func(float64) float64 +} + +// NearestNeighbor is a nearest-neighbor filter (no anti-aliasing). +var NearestNeighbor ResampleFilter + +// Box filter (averaging pixels). +var Box ResampleFilter + +// Linear filter. +var Linear ResampleFilter + +// Hermite cubic spline filter (BC-spline; B=0; C=0). +var Hermite ResampleFilter + +// MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3). +var MitchellNetravali ResampleFilter + +// CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5). +var CatmullRom ResampleFilter + +// BSpline is a smooth cubic filter (BC-spline; B=1; C=0). +var BSpline ResampleFilter + +// Gaussian is a Gaussian blurring filter. +var Gaussian ResampleFilter + +// Bartlett is a Bartlett-windowed sinc filter (3 lobes). +var Bartlett ResampleFilter + +// Lanczos filter (3 lobes). +var Lanczos ResampleFilter + +// Hann is a Hann-windowed sinc filter (3 lobes). +var Hann ResampleFilter + +// Hamming is a Hamming-windowed sinc filter (3 lobes). +var Hamming ResampleFilter + +// Blackman is a Blackman-windowed sinc filter (3 lobes). +var Blackman ResampleFilter + +// Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes). +var Welch ResampleFilter + +// Cosine is a Cosine-windowed sinc filter (3 lobes). +var Cosine ResampleFilter + +func bcspline(x, b, c float64) float64 { + var y float64 + x = math.Abs(x) + if x < 1.0 { + y = ((12-9*b-6*c)*x*x*x + (-18+12*b+6*c)*x*x + (6 - 2*b)) / 6 + } else if x < 2.0 { + y = ((-b-6*c)*x*x*x + (6*b+30*c)*x*x + (-12*b-48*c)*x + (8*b + 24*c)) / 6 + } + return y +} + +func sinc(x float64) float64 { + if x == 0 { + return 1 + } + return math.Sin(math.Pi*x) / (math.Pi * x) +} + +func init() { + NearestNeighbor = ResampleFilter{ + Support: 0.0, // special case - not applying the filter + } + + Box = ResampleFilter{ + Support: 0.5, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x <= 0.5 { + return 1.0 + } + return 0 + }, + } + + Linear = ResampleFilter{ + Support: 1.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 1.0 { + return 1.0 - x + } + return 0 + }, + } + + Hermite = ResampleFilter{ + Support: 1.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 1.0 { + return bcspline(x, 0.0, 0.0) + } + return 0 + }, + } + + MitchellNetravali = ResampleFilter{ + Support: 2.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 2.0 { + return bcspline(x, 1.0/3.0, 1.0/3.0) + } + return 0 + }, + } + + CatmullRom = ResampleFilter{ + Support: 2.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 2.0 { + return bcspline(x, 0.0, 0.5) + } + return 0 + }, + } + + BSpline = ResampleFilter{ + Support: 2.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 2.0 { + return bcspline(x, 1.0, 0.0) + } + return 0 + }, + } + + Gaussian = ResampleFilter{ + Support: 2.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 2.0 { + return math.Exp(-2 * x * x) + } + return 0 + }, + } + + Bartlett = ResampleFilter{ + Support: 3.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 3.0 { + return sinc(x) * (3.0 - x) / 3.0 + } + return 0 + }, + } + + Lanczos = ResampleFilter{ + Support: 3.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 3.0 { + return sinc(x) * sinc(x/3.0) + } + return 0 + }, + } + + Hann = ResampleFilter{ + Support: 3.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 3.0 { + return sinc(x) * (0.5 + 0.5*math.Cos(math.Pi*x/3.0)) + } + return 0 + }, + } + + Hamming = ResampleFilter{ + Support: 3.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 3.0 { + return sinc(x) * (0.54 + 0.46*math.Cos(math.Pi*x/3.0)) + } + return 0 + }, + } + + Blackman = ResampleFilter{ + Support: 3.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 3.0 { + return sinc(x) * (0.42 - 0.5*math.Cos(math.Pi*x/3.0+math.Pi) + 0.08*math.Cos(2.0*math.Pi*x/3.0)) + } + return 0 + }, + } + + Welch = ResampleFilter{ + Support: 3.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 3.0 { + return sinc(x) * (1.0 - (x * x / 9.0)) + } + return 0 + }, + } + + Cosine = ResampleFilter{ + Support: 3.0, + Kernel: func(x float64) float64 { + x = math.Abs(x) + if x < 3.0 { + return sinc(x) * math.Cos((math.Pi/2.0)*(x/3.0)) + } + return 0 + }, + } +} diff --git a/vendor/github.com/disintegration/imaging/scanner.go b/vendor/github.com/disintegration/imaging/scanner.go new file mode 100644 index 0000000000..37d92cef88 --- /dev/null +++ b/vendor/github.com/disintegration/imaging/scanner.go @@ -0,0 +1,285 @@ +package imaging + +import ( + "image" + "image/color" +) + +type scanner struct { + image image.Image + w, h int + palette []color.NRGBA +} + +func newScanner(img image.Image) *scanner { + s := &scanner{ + image: img, + w: img.Bounds().Dx(), + h: img.Bounds().Dy(), + } + if img, ok := img.(*image.Paletted); ok { + s.palette = make([]color.NRGBA, len(img.Palette)) + for i := 0; i < len(img.Palette); i++ { + s.palette[i] = color.NRGBAModel.Convert(img.Palette[i]).(color.NRGBA) + } + } + return s +} + +// scan scans the given rectangular region of the image into dst. +func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { + switch img := s.image.(type) { + case *image.NRGBA: + size := (x2 - x1) * 4 + j := 0 + i := y1*img.Stride + x1*4 + if size == 4 { + for y := y1; y < y2; y++ { + d := dst[j : j+4 : j+4] + s := img.Pix[i : i+4 : i+4] + d[0] = s[0] + d[1] = s[1] + d[2] = s[2] + d[3] = s[3] + j += size + i += img.Stride + } + } else { + for y := y1; y < y2; y++ { + copy(dst[j:j+size], img.Pix[i:i+size]) + j += size + i += img.Stride + } + } + + case *image.NRGBA64: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1*8 + for x := x1; x < x2; x++ { + s := img.Pix[i : i+8 : i+8] + d := dst[j : j+4 : j+4] + d[0] = s[0] + d[1] = s[2] + d[2] = s[4] + d[3] = s[6] + j += 4 + i += 8 + } + } + + case *image.RGBA: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1*4 + for x := x1; x < x2; x++ { + d := dst[j : j+4 : j+4] + a := img.Pix[i+3] + switch a { + case 0: + d[0] = 0 + d[1] = 0 + d[2] = 0 + d[3] = a + case 0xff: + s := img.Pix[i : i+4 : i+4] + d[0] = s[0] + d[1] = s[1] + d[2] = s[2] + d[3] = a + default: + s := img.Pix[i : i+4 : i+4] + r16 := uint16(s[0]) + g16 := uint16(s[1]) + b16 := uint16(s[2]) + a16 := uint16(a) + d[0] = uint8(r16 * 0xff / a16) + d[1] = uint8(g16 * 0xff / a16) + d[2] = uint8(b16 * 0xff / a16) + d[3] = a + } + j += 4 + i += 4 + } + } + + case *image.RGBA64: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1*8 + for x := x1; x < x2; x++ { + s := img.Pix[i : i+8 : i+8] + d := dst[j : j+4 : j+4] + a := s[6] + switch a { + case 0: + d[0] = 0 + d[1] = 0 + d[2] = 0 + case 0xff: + d[0] = s[0] + d[1] = s[2] + d[2] = s[4] + default: + r32 := uint32(s[0])<<8 | uint32(s[1]) + g32 := uint32(s[2])<<8 | uint32(s[3]) + b32 := uint32(s[4])<<8 | uint32(s[5]) + a32 := uint32(s[6])<<8 | uint32(s[7]) + d[0] = uint8((r32 * 0xffff / a32) >> 8) + d[1] = uint8((g32 * 0xffff / a32) >> 8) + d[2] = uint8((b32 * 0xffff / a32) >> 8) + } + d[3] = a + j += 4 + i += 8 + } + } + + case *image.Gray: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1 + for x := x1; x < x2; x++ { + c := img.Pix[i] + d := dst[j : j+4 : j+4] + d[0] = c + d[1] = c + d[2] = c + d[3] = 0xff + j += 4 + i++ + } + } + + case *image.Gray16: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1*2 + for x := x1; x < x2; x++ { + c := img.Pix[i] + d := dst[j : j+4 : j+4] + d[0] = c + d[1] = c + d[2] = c + d[3] = 0xff + j += 4 + i += 2 + } + } + + case *image.YCbCr: + j := 0 + x1 += img.Rect.Min.X + x2 += img.Rect.Min.X + y1 += img.Rect.Min.Y + y2 += img.Rect.Min.Y + + hy := img.Rect.Min.Y / 2 + hx := img.Rect.Min.X / 2 + for y := y1; y < y2; y++ { + iy := (y-img.Rect.Min.Y)*img.YStride + (x1 - img.Rect.Min.X) + + var yBase int + switch img.SubsampleRatio { + case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio422: + yBase = (y - img.Rect.Min.Y) * img.CStride + case image.YCbCrSubsampleRatio420, image.YCbCrSubsampleRatio440: + yBase = (y/2 - hy) * img.CStride + } + + for x := x1; x < x2; x++ { + var ic int + switch img.SubsampleRatio { + case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio440: + ic = yBase + (x - img.Rect.Min.X) + case image.YCbCrSubsampleRatio422, image.YCbCrSubsampleRatio420: + ic = yBase + (x/2 - hx) + default: + ic = img.COffset(x, y) + } + + yy1 := int32(img.Y[iy]) * 0x10101 + cb1 := int32(img.Cb[ic]) - 128 + cr1 := int32(img.Cr[ic]) - 128 + + r := yy1 + 91881*cr1 + if uint32(r)&0xff000000 == 0 { + r >>= 16 + } else { + r = ^(r >> 31) + } + + g := yy1 - 22554*cb1 - 46802*cr1 + if uint32(g)&0xff000000 == 0 { + g >>= 16 + } else { + g = ^(g >> 31) + } + + b := yy1 + 116130*cb1 + if uint32(b)&0xff000000 == 0 { + b >>= 16 + } else { + b = ^(b >> 31) + } + + d := dst[j : j+4 : j+4] + d[0] = uint8(r) + d[1] = uint8(g) + d[2] = uint8(b) + d[3] = 0xff + + iy++ + j += 4 + } + } + + case *image.Paletted: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1 + for x := x1; x < x2; x++ { + c := s.palette[img.Pix[i]] + d := dst[j : j+4 : j+4] + d[0] = c.R + d[1] = c.G + d[2] = c.B + d[3] = c.A + j += 4 + i++ + } + } + + default: + j := 0 + b := s.image.Bounds() + x1 += b.Min.X + x2 += b.Min.X + y1 += b.Min.Y + y2 += b.Min.Y + for y := y1; y < y2; y++ { + for x := x1; x < x2; x++ { + r16, g16, b16, a16 := s.image.At(x, y).RGBA() + d := dst[j : j+4 : j+4] + switch a16 { + case 0xffff: + d[0] = uint8(r16 >> 8) + d[1] = uint8(g16 >> 8) + d[2] = uint8(b16 >> 8) + d[3] = 0xff + case 0: + d[0] = 0 + d[1] = 0 + d[2] = 0 + d[3] = 0 + default: + d[0] = uint8(((r16 * 0xffff) / a16) >> 8) + d[1] = uint8(((g16 * 0xffff) / a16) >> 8) + d[2] = uint8(((b16 * 0xffff) / a16) >> 8) + d[3] = uint8(a16 >> 8) + } + j += 4 + } + } + } +} diff --git a/vendor/github.com/disintegration/imaging/tools.go b/vendor/github.com/disintegration/imaging/tools.go new file mode 100644 index 0000000000..0ec19a039c --- /dev/null +++ b/vendor/github.com/disintegration/imaging/tools.go @@ -0,0 +1,249 @@ +package imaging + +import ( + "bytes" + "image" + "image/color" + "math" +) + +// New creates a new image with the specified width and height, and fills it with the specified color. +func New(width, height int, fillColor color.Color) *image.NRGBA { + if width <= 0 || height <= 0 { + return &image.NRGBA{} + } + + c := color.NRGBAModel.Convert(fillColor).(color.NRGBA) + if (c == color.NRGBA{0, 0, 0, 0}) { + return image.NewNRGBA(image.Rect(0, 0, width, height)) + } + + return &image.NRGBA{ + Pix: bytes.Repeat([]byte{c.R, c.G, c.B, c.A}, width*height), + Stride: 4 * width, + Rect: image.Rect(0, 0, width, height), + } +} + +// Clone returns a copy of the given image. +func Clone(img image.Image) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + size := src.w * 4 + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+size]) + } + }) + return dst +} + +// Anchor is the anchor point for image alignment. +type Anchor int + +// Anchor point positions. +const ( + Center Anchor = iota + TopLeft + Top + TopRight + Left + Right + BottomLeft + Bottom + BottomRight +) + +func anchorPt(b image.Rectangle, w, h int, anchor Anchor) image.Point { + var x, y int + switch anchor { + case TopLeft: + x = b.Min.X + y = b.Min.Y + case Top: + x = b.Min.X + (b.Dx()-w)/2 + y = b.Min.Y + case TopRight: + x = b.Max.X - w + y = b.Min.Y + case Left: + x = b.Min.X + y = b.Min.Y + (b.Dy()-h)/2 + case Right: + x = b.Max.X - w + y = b.Min.Y + (b.Dy()-h)/2 + case BottomLeft: + x = b.Min.X + y = b.Max.Y - h + case Bottom: + x = b.Min.X + (b.Dx()-w)/2 + y = b.Max.Y - h + case BottomRight: + x = b.Max.X - w + y = b.Max.Y - h + default: + x = b.Min.X + (b.Dx()-w)/2 + y = b.Min.Y + (b.Dy()-h)/2 + } + return image.Pt(x, y) +} + +// Crop cuts out a rectangular region with the specified bounds +// from the image and returns the cropped image. +func Crop(img image.Image, rect image.Rectangle) *image.NRGBA { + r := rect.Intersect(img.Bounds()).Sub(img.Bounds().Min) + if r.Empty() { + return &image.NRGBA{} + } + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, r.Dx(), r.Dy())) + rowSize := r.Dx() * 4 + parallel(r.Min.Y, r.Max.Y, func(ys <-chan int) { + for y := range ys { + i := (y - r.Min.Y) * dst.Stride + src.scan(r.Min.X, y, r.Max.X, y+1, dst.Pix[i:i+rowSize]) + } + }) + return dst +} + +// CropAnchor cuts out a rectangular region with the specified size +// from the image using the specified anchor point and returns the cropped image. +func CropAnchor(img image.Image, width, height int, anchor Anchor) *image.NRGBA { + srcBounds := img.Bounds() + pt := anchorPt(srcBounds, width, height, anchor) + r := image.Rect(0, 0, width, height).Add(pt) + b := srcBounds.Intersect(r) + return Crop(img, b) +} + +// CropCenter cuts out a rectangular region with the specified size +// from the center of the image and returns the cropped image. +func CropCenter(img image.Image, width, height int) *image.NRGBA { + return CropAnchor(img, width, height, Center) +} + +// Paste pastes the img image to the background image at the specified position and returns the combined image. +func Paste(background, img image.Image, pos image.Point) *image.NRGBA { + dst := Clone(background) + pos = pos.Sub(background.Bounds().Min) + pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())} + interRect := pasteRect.Intersect(dst.Bounds()) + if interRect.Empty() { + return dst + } + src := newScanner(img) + parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) { + for y := range ys { + x1 := interRect.Min.X - pasteRect.Min.X + x2 := interRect.Max.X - pasteRect.Min.X + y1 := y - pasteRect.Min.Y + y2 := y1 + 1 + i1 := y*dst.Stride + interRect.Min.X*4 + i2 := i1 + interRect.Dx()*4 + src.scan(x1, y1, x2, y2, dst.Pix[i1:i2]) + } + }) + return dst +} + +// PasteCenter pastes the img image to the center of the background image and returns the combined image. +func PasteCenter(background, img image.Image) *image.NRGBA { + bgBounds := background.Bounds() + bgW := bgBounds.Dx() + bgH := bgBounds.Dy() + bgMinX := bgBounds.Min.X + bgMinY := bgBounds.Min.Y + + centerX := bgMinX + bgW/2 + centerY := bgMinY + bgH/2 + + x0 := centerX - img.Bounds().Dx()/2 + y0 := centerY - img.Bounds().Dy()/2 + + return Paste(background, img, image.Pt(x0, y0)) +} + +// Overlay draws the img image over the background image at given position +// and returns the combined image. Opacity parameter is the opacity of the img +// image layer, used to compose the images, it must be from 0.0 to 1.0. +// +// Examples: +// +// // Draw spriteImage over backgroundImage at the given position (x=50, y=50). +// dstImage := imaging.Overlay(backgroundImage, spriteImage, image.Pt(50, 50), 1.0) +// +// // Blend two opaque images of the same size. +// dstImage := imaging.Overlay(imageOne, imageTwo, image.Pt(0, 0), 0.5) +// +func Overlay(background, img image.Image, pos image.Point, opacity float64) *image.NRGBA { + opacity = math.Min(math.Max(opacity, 0.0), 1.0) // Ensure 0.0 <= opacity <= 1.0. + dst := Clone(background) + pos = pos.Sub(background.Bounds().Min) + pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())} + interRect := pasteRect.Intersect(dst.Bounds()) + if interRect.Empty() { + return dst + } + src := newScanner(img) + parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) { + scanLine := make([]uint8, interRect.Dx()*4) + for y := range ys { + x1 := interRect.Min.X - pasteRect.Min.X + x2 := interRect.Max.X - pasteRect.Min.X + y1 := y - pasteRect.Min.Y + y2 := y1 + 1 + src.scan(x1, y1, x2, y2, scanLine) + i := y*dst.Stride + interRect.Min.X*4 + j := 0 + for x := interRect.Min.X; x < interRect.Max.X; x++ { + d := dst.Pix[i : i+4 : i+4] + r1 := float64(d[0]) + g1 := float64(d[1]) + b1 := float64(d[2]) + a1 := float64(d[3]) + + s := scanLine[j : j+4 : j+4] + r2 := float64(s[0]) + g2 := float64(s[1]) + b2 := float64(s[2]) + a2 := float64(s[3]) + + coef2 := opacity * a2 / 255 + coef1 := (1 - coef2) * a1 / 255 + coefSum := coef1 + coef2 + coef1 /= coefSum + coef2 /= coefSum + + d[0] = uint8(r1*coef1 + r2*coef2) + d[1] = uint8(g1*coef1 + g2*coef2) + d[2] = uint8(b1*coef1 + b2*coef2) + d[3] = uint8(math.Min(a1+a2*opacity*(255-a1)/255, 255)) + + i += 4 + j += 4 + } + } + }) + return dst +} + +// OverlayCenter overlays the img image to the center of the background image and +// returns the combined image. Opacity parameter is the opacity of the img +// image layer, used to compose the images, it must be from 0.0 to 1.0. +func OverlayCenter(background, img image.Image, opacity float64) *image.NRGBA { + bgBounds := background.Bounds() + bgW := bgBounds.Dx() + bgH := bgBounds.Dy() + bgMinX := bgBounds.Min.X + bgMinY := bgBounds.Min.Y + + centerX := bgMinX + bgW/2 + centerY := bgMinY + bgH/2 + + x0 := centerX - img.Bounds().Dx()/2 + y0 := centerY - img.Bounds().Dy()/2 + + return Overlay(background, img, image.Point{x0, y0}, opacity) +} diff --git a/vendor/github.com/disintegration/imaging/transform.go b/vendor/github.com/disintegration/imaging/transform.go new file mode 100644 index 0000000000..fe4a92f9d4 --- /dev/null +++ b/vendor/github.com/disintegration/imaging/transform.go @@ -0,0 +1,268 @@ +package imaging + +import ( + "image" + "image/color" + "math" +) + +// FlipH flips the image horizontally (from left to right) and returns the transformed image. +func FlipH(img image.Image) *image.NRGBA { + src := newScanner(img) + dstW := src.w + dstH := src.h + rowSize := dstW * 4 + dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcY := dstY + src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize]) + reverse(dst.Pix[i : i+rowSize]) + } + }) + return dst +} + +// FlipV flips the image vertically (from top to bottom) and returns the transformed image. +func FlipV(img image.Image) *image.NRGBA { + src := newScanner(img) + dstW := src.w + dstH := src.h + rowSize := dstW * 4 + dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcY := dstH - dstY - 1 + src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize]) + } + }) + return dst +} + +// Transpose flips the image horizontally and rotates 90 degrees counter-clockwise. +func Transpose(img image.Image) *image.NRGBA { + src := newScanner(img) + dstW := src.h + dstH := src.w + rowSize := dstW * 4 + dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcX := dstY + src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize]) + } + }) + return dst +} + +// Transverse flips the image vertically and rotates 90 degrees counter-clockwise. +func Transverse(img image.Image) *image.NRGBA { + src := newScanner(img) + dstW := src.h + dstH := src.w + rowSize := dstW * 4 + dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcX := dstH - dstY - 1 + src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize]) + reverse(dst.Pix[i : i+rowSize]) + } + }) + return dst +} + +// Rotate90 rotates the image 90 degrees counter-clockwise and returns the transformed image. +func Rotate90(img image.Image) *image.NRGBA { + src := newScanner(img) + dstW := src.h + dstH := src.w + rowSize := dstW * 4 + dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcX := dstH - dstY - 1 + src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize]) + } + }) + return dst +} + +// Rotate180 rotates the image 180 degrees counter-clockwise and returns the transformed image. +func Rotate180(img image.Image) *image.NRGBA { + src := newScanner(img) + dstW := src.w + dstH := src.h + rowSize := dstW * 4 + dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcY := dstH - dstY - 1 + src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize]) + reverse(dst.Pix[i : i+rowSize]) + } + }) + return dst +} + +// Rotate270 rotates the image 270 degrees counter-clockwise and returns the transformed image. +func Rotate270(img image.Image) *image.NRGBA { + src := newScanner(img) + dstW := src.h + dstH := src.w + rowSize := dstW * 4 + dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcX := dstY + src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize]) + reverse(dst.Pix[i : i+rowSize]) + } + }) + return dst +} + +// Rotate rotates an image by the given angle counter-clockwise . +// The angle parameter is the rotation angle in degrees. +// The bgColor parameter specifies the color of the uncovered zone after the rotation. +func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA { + angle = angle - math.Floor(angle/360)*360 + + switch angle { + case 0: + return Clone(img) + case 90: + return Rotate90(img) + case 180: + return Rotate180(img) + case 270: + return Rotate270(img) + } + + src := toNRGBA(img) + srcW := src.Bounds().Max.X + srcH := src.Bounds().Max.Y + dstW, dstH := rotatedSize(srcW, srcH, angle) + dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) + + if dstW <= 0 || dstH <= 0 { + return dst + } + + srcXOff := float64(srcW)/2 - 0.5 + srcYOff := float64(srcH)/2 - 0.5 + dstXOff := float64(dstW)/2 - 0.5 + dstYOff := float64(dstH)/2 - 0.5 + + bgColorNRGBA := color.NRGBAModel.Convert(bgColor).(color.NRGBA) + sin, cos := math.Sincos(math.Pi * angle / 180) + + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + for dstX := 0; dstX < dstW; dstX++ { + xf, yf := rotatePoint(float64(dstX)-dstXOff, float64(dstY)-dstYOff, sin, cos) + xf, yf = xf+srcXOff, yf+srcYOff + interpolatePoint(dst, dstX, dstY, src, xf, yf, bgColorNRGBA) + } + } + }) + + return dst +} + +func rotatePoint(x, y, sin, cos float64) (float64, float64) { + return x*cos - y*sin, x*sin + y*cos +} + +func rotatedSize(w, h int, angle float64) (int, int) { + if w <= 0 || h <= 0 { + return 0, 0 + } + + sin, cos := math.Sincos(math.Pi * angle / 180) + x1, y1 := rotatePoint(float64(w-1), 0, sin, cos) + x2, y2 := rotatePoint(float64(w-1), float64(h-1), sin, cos) + x3, y3 := rotatePoint(0, float64(h-1), sin, cos) + + minx := math.Min(x1, math.Min(x2, math.Min(x3, 0))) + maxx := math.Max(x1, math.Max(x2, math.Max(x3, 0))) + miny := math.Min(y1, math.Min(y2, math.Min(y3, 0))) + maxy := math.Max(y1, math.Max(y2, math.Max(y3, 0))) + + neww := maxx - minx + 1 + if neww-math.Floor(neww) > 0.1 { + neww++ + } + newh := maxy - miny + 1 + if newh-math.Floor(newh) > 0.1 { + newh++ + } + + return int(neww), int(newh) +} + +func interpolatePoint(dst *image.NRGBA, dstX, dstY int, src *image.NRGBA, xf, yf float64, bgColor color.NRGBA) { + j := dstY*dst.Stride + dstX*4 + d := dst.Pix[j : j+4 : j+4] + + x0 := int(math.Floor(xf)) + y0 := int(math.Floor(yf)) + bounds := src.Bounds() + if !image.Pt(x0, y0).In(image.Rect(bounds.Min.X-1, bounds.Min.Y-1, bounds.Max.X, bounds.Max.Y)) { + d[0] = bgColor.R + d[1] = bgColor.G + d[2] = bgColor.B + d[3] = bgColor.A + return + } + + xq := xf - float64(x0) + yq := yf - float64(y0) + points := [4]image.Point{ + {x0, y0}, + {x0 + 1, y0}, + {x0, y0 + 1}, + {x0 + 1, y0 + 1}, + } + weights := [4]float64{ + (1 - xq) * (1 - yq), + xq * (1 - yq), + (1 - xq) * yq, + xq * yq, + } + + var r, g, b, a float64 + for i := 0; i < 4; i++ { + p := points[i] + w := weights[i] + if p.In(bounds) { + i := p.Y*src.Stride + p.X*4 + s := src.Pix[i : i+4 : i+4] + wa := float64(s[3]) * w + r += float64(s[0]) * wa + g += float64(s[1]) * wa + b += float64(s[2]) * wa + a += wa + } else { + wa := float64(bgColor.A) * w + r += float64(bgColor.R) * wa + g += float64(bgColor.G) * wa + b += float64(bgColor.B) * wa + a += wa + } + } + if a != 0 { + aInv := 1 / a + d[0] = clamp(r * aInv) + d[1] = clamp(g * aInv) + d[2] = clamp(b * aInv) + d[3] = clamp(a) + } +} diff --git a/vendor/github.com/disintegration/imaging/utils.go b/vendor/github.com/disintegration/imaging/utils.go new file mode 100644 index 0000000000..6c7af1a518 --- /dev/null +++ b/vendor/github.com/disintegration/imaging/utils.go @@ -0,0 +1,167 @@ +package imaging + +import ( + "image" + "math" + "runtime" + "sync" +) + +// parallel processes the data in separate goroutines. +func parallel(start, stop int, fn func(<-chan int)) { + count := stop - start + if count < 1 { + return + } + + procs := runtime.GOMAXPROCS(0) + if procs > count { + procs = count + } + + c := make(chan int, count) + for i := start; i < stop; i++ { + c <- i + } + close(c) + + var wg sync.WaitGroup + for i := 0; i < procs; i++ { + wg.Add(1) + go func() { + defer wg.Done() + fn(c) + }() + } + wg.Wait() +} + +// absint returns the absolute value of i. +func absint(i int) int { + if i < 0 { + return -i + } + return i +} + +// clamp rounds and clamps float64 value to fit into uint8. +func clamp(x float64) uint8 { + v := int64(x + 0.5) + if v > 255 { + return 255 + } + if v > 0 { + return uint8(v) + } + return 0 +} + +func reverse(pix []uint8) { + if len(pix) <= 4 { + return + } + i := 0 + j := len(pix) - 4 + for i < j { + pi := pix[i : i+4 : i+4] + pj := pix[j : j+4 : j+4] + pi[0], pj[0] = pj[0], pi[0] + pi[1], pj[1] = pj[1], pi[1] + pi[2], pj[2] = pj[2], pi[2] + pi[3], pj[3] = pj[3], pi[3] + i += 4 + j -= 4 + } +} + +func toNRGBA(img image.Image) *image.NRGBA { + if img, ok := img.(*image.NRGBA); ok { + return &image.NRGBA{ + Pix: img.Pix, + Stride: img.Stride, + Rect: img.Rect.Sub(img.Rect.Min), + } + } + return Clone(img) +} + +// rgbToHSL converts a color from RGB to HSL. +func rgbToHSL(r, g, b uint8) (float64, float64, float64) { + rr := float64(r) / 255 + gg := float64(g) / 255 + bb := float64(b) / 255 + + max := math.Max(rr, math.Max(gg, bb)) + min := math.Min(rr, math.Min(gg, bb)) + + l := (max + min) / 2 + + if max == min { + return 0, 0, l + } + + var h, s float64 + d := max - min + if l > 0.5 { + s = d / (2 - max - min) + } else { + s = d / (max + min) + } + + switch max { + case rr: + h = (gg - bb) / d + if g < b { + h += 6 + } + case gg: + h = (bb-rr)/d + 2 + case bb: + h = (rr-gg)/d + 4 + } + h /= 6 + + return h, s, l +} + +// hslToRGB converts a color from HSL to RGB. +func hslToRGB(h, s, l float64) (uint8, uint8, uint8) { + var r, g, b float64 + if s == 0 { + v := clamp(l * 255) + return v, v, v + } + + var q float64 + if l < 0.5 { + q = l * (1 + s) + } else { + q = l + s - l*s + } + p := 2*l - q + + r = hueToRGB(p, q, h+1/3.0) + g = hueToRGB(p, q, h) + b = hueToRGB(p, q, h-1/3.0) + + return clamp(r * 255), clamp(g * 255), clamp(b * 255) +} + +func hueToRGB(p, q, t float64) float64 { + if t < 0 { + t++ + } + if t > 1 { + t-- + } + if t < 1/6.0 { + return p + (q-p)*6*t + } + if t < 1/2.0 { + return q + } + if t < 2/3.0 { + return p + (q-p)*(2/3.0-t)*6 + } + return p +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go index 4d29814b21..c5fbc1e77e 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go @@ -58,13 +58,11 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { return nil, err } return arguments, nil - } method, exist := abi.Methods[name] if !exist { return nil, fmt.Errorf("method '%s' not found", name) } - arguments, err := method.Inputs.Pack(args...) if err != nil { return nil, err @@ -74,19 +72,39 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { } // Unpack output in v according to the abi specification -func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) { - if len(output) == 0 { +func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) { + if len(data) == 0 { + return fmt.Errorf("abi: unmarshalling empty output") + } + // since there can't be naming collisions with contracts and events, + // we need to decide whether we're calling a method or an event + if method, ok := abi.Methods[name]; ok { + if len(data)%32 != 0 { + return fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(data), data) + } + return method.Outputs.Unpack(v, data) + } + if event, ok := abi.Events[name]; ok { + return event.Inputs.Unpack(v, data) + } + return fmt.Errorf("abi: could not locate named method or event") +} + +// UnpackIntoMap unpacks a log into the provided map[string]interface{} +func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) { + if len(data) == 0 { return fmt.Errorf("abi: unmarshalling empty output") } // since there can't be naming collisions with contracts and events, // we need to decide whether we're calling a method or an event if method, ok := abi.Methods[name]; ok { - if len(output)%32 != 0 { - return fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(output), output) + if len(data)%32 != 0 { + return fmt.Errorf("abi: improperly formatted output") } - return method.Outputs.Unpack(v, output) - } else if event, ok := abi.Events[name]; ok { - return event.Inputs.Unpack(v, output) + return method.Outputs.UnpackIntoMap(v, data) + } + if event, ok := abi.Events[name]; ok { + return event.Inputs.UnpackIntoMap(v, data) } return fmt.Errorf("abi: could not locate named method or event") } @@ -138,7 +156,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { // returns nil if none found func (abi *ABI) MethodById(sigdata []byte) (*Method, error) { if len(sigdata) < 4 { - return nil, fmt.Errorf("data too short (% bytes) for abi method lookup", len(sigdata)) + return nil, fmt.Errorf("data too short (%d bytes) for abi method lookup", len(sigdata)) } for _, method := range abi.Methods { if bytes.Equal(method.Id(), sigdata[:4]) { diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go index fdc6ff1648..501cb16213 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go @@ -33,24 +33,27 @@ type Argument struct { type Arguments []Argument +type ArgumentMarshaling struct { + Name string + Type string + Components []ArgumentMarshaling + Indexed bool +} + // UnmarshalJSON implements json.Unmarshaler interface func (argument *Argument) UnmarshalJSON(data []byte) error { - var extarg struct { - Name string - Type string - Indexed bool - } - err := json.Unmarshal(data, &extarg) + var arg ArgumentMarshaling + err := json.Unmarshal(data, &arg) if err != nil { return fmt.Errorf("argument json err: %v", err) } - argument.Type, err = NewType(extarg.Type) + argument.Type, err = NewType(arg.Type, arg.Components) if err != nil { return err } - argument.Name = extarg.Name - argument.Indexed = extarg.Indexed + argument.Name = arg.Name + argument.Indexed = arg.Indexed return nil } @@ -85,7 +88,6 @@ func (arguments Arguments) isTuple() bool { // Unpack performs the operation hexdata -> Go format func (arguments Arguments) Unpack(v interface{}, data []byte) error { - // make sure the passed value is arguments pointer if reflect.Ptr != reflect.ValueOf(v).Kind() { return fmt.Errorf("abi: Unpack(non-pointer %T)", v) @@ -97,52 +99,157 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error { if arguments.isTuple() { return arguments.unpackTuple(v, marshalledValues) } - return arguments.unpackAtomic(v, marshalledValues) + return arguments.unpackAtomic(v, marshalledValues[0]) } -func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error { +// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value +func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error { + marshalledValues, err := arguments.UnpackValues(data) + if err != nil { + return err + } + + return arguments.unpackIntoMap(v, marshalledValues) +} +// unpack sets the unmarshalled value to go format. +// Note the dst here must be settable. +func unpack(t *Type, dst interface{}, src interface{}) error { + var ( + dstVal = reflect.ValueOf(dst).Elem() + srcVal = reflect.ValueOf(src) + ) + + if t.T != TupleTy && !((t.T == SliceTy || t.T == ArrayTy) && t.Elem.T == TupleTy) { + return set(dstVal, srcVal) + } + + switch t.T { + case TupleTy: + if dstVal.Kind() != reflect.Struct { + return fmt.Errorf("abi: invalid dst value for unpack, want struct, got %s", dstVal.Kind()) + } + fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, dstVal) + if err != nil { + return err + } + for i, elem := range t.TupleElems { + fname := fieldmap[t.TupleRawNames[i]] + field := dstVal.FieldByName(fname) + if !field.IsValid() { + return fmt.Errorf("abi: field %s can't found in the given value", t.TupleRawNames[i]) + } + if err := unpack(elem, field.Addr().Interface(), srcVal.Field(i).Interface()); err != nil { + return err + } + } + return nil + case SliceTy: + if dstVal.Kind() != reflect.Slice { + return fmt.Errorf("abi: invalid dst value for unpack, want slice, got %s", dstVal.Kind()) + } + slice := reflect.MakeSlice(dstVal.Type(), srcVal.Len(), srcVal.Len()) + for i := 0; i < slice.Len(); i++ { + if err := unpack(t.Elem, slice.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil { + return err + } + } + dstVal.Set(slice) + case ArrayTy: + if dstVal.Kind() != reflect.Array { + return fmt.Errorf("abi: invalid dst value for unpack, want array, got %s", dstVal.Kind()) + } + array := reflect.New(dstVal.Type()).Elem() + for i := 0; i < array.Len(); i++ { + if err := unpack(t.Elem, array.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil { + return err + } + } + dstVal.Set(array) + } + return nil +} + +// unpackIntoMap unpacks marshalledValues into the provided map[string]interface{} +func (arguments Arguments) unpackIntoMap(v map[string]interface{}, marshalledValues []interface{}) error { + // Make sure map is not nil + if v == nil { + return fmt.Errorf("abi: cannot unpack into a nil map") + } + + for i, arg := range arguments.NonIndexed() { + v[arg.Name] = marshalledValues[i] + } + return nil +} + +// unpackAtomic unpacks ( hexdata -> go ) a single value +func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error { + if arguments.LengthNonIndexed() == 0 { + return nil + } + argument := arguments.NonIndexed()[0] + elem := reflect.ValueOf(v).Elem() + + if elem.Kind() == reflect.Struct { + fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem) + if err != nil { + return err + } + field := elem.FieldByName(fieldmap[argument.Name]) + if !field.IsValid() { + return fmt.Errorf("abi: field %s can't be found in the given value", argument.Name) + } + return unpack(&argument.Type, field.Addr().Interface(), marshalledValues) + } + return unpack(&argument.Type, elem.Addr().Interface(), marshalledValues) +} + +// unpackTuple unpacks ( hexdata -> go ) a batch of values. +func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error { var ( value = reflect.ValueOf(v).Elem() typ = value.Type() kind = value.Kind() ) - if err := requireUnpackKind(value, typ, kind, arguments); err != nil { return err } // If the interface is a struct, get of abi->struct_field mapping - var abi2struct map[string]string if kind == reflect.Struct { - var err error - abi2struct, err = mapAbiToStructFields(arguments, value) + var ( + argNames []string + err error + ) + for _, arg := range arguments.NonIndexed() { + argNames = append(argNames, arg.Name) + } + abi2struct, err = mapArgNamesToStructFields(argNames, value) if err != nil { return err } } for i, arg := range arguments.NonIndexed() { - - reflectValue := reflect.ValueOf(marshalledValues[i]) - switch kind { case reflect.Struct: - if structField, ok := abi2struct[arg.Name]; ok { - if err := set(value.FieldByName(structField), reflectValue, arg); err != nil { - return err - } + field := value.FieldByName(abi2struct[arg.Name]) + if !field.IsValid() { + return fmt.Errorf("abi: field %s can't be found in the given value", arg.Name) + } + if err := unpack(&arg.Type, field.Addr().Interface(), marshalledValues[i]); err != nil { + return err } case reflect.Slice, reflect.Array: if value.Len() < i { return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len()) } v := value.Index(i) - if err := requireAssignable(v, reflectValue); err != nil { + if err := requireAssignable(v, reflect.ValueOf(marshalledValues[i])); err != nil { return err } - - if err := set(v.Elem(), reflectValue, arg); err != nil { + if err := unpack(&arg.Type, v.Addr().Interface(), marshalledValues[i]); err != nil { return err } default: @@ -150,50 +257,9 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa } } return nil -} - -// unpackAtomic unpacks ( hexdata -> go ) a single value -func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues []interface{}) error { - if len(marshalledValues) != 1 { - return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues)) - } - - elem := reflect.ValueOf(v).Elem() - kind := elem.Kind() - reflectValue := reflect.ValueOf(marshalledValues[0]) - - var abi2struct map[string]string - if kind == reflect.Struct { - var err error - if abi2struct, err = mapAbiToStructFields(arguments, elem); err != nil { - return err - } - arg := arguments.NonIndexed()[0] - if structField, ok := abi2struct[arg.Name]; ok { - return set(elem.FieldByName(structField), reflectValue, arg) - } - return nil - } - - return set(elem, reflectValue, arguments.NonIndexed()[0]) } -// Computes the full size of an array; -// i.e. counting nested arrays, which count towards size for unpacking. -func getArraySize(arr *Type) int { - size := arr.Size - // Arrays can be nested, with each element being the same size - arr = arr.Elem - for arr.T == ArrayTy { - // Keep multiplying by elem.Size while the elem is an array. - size *= arr.Size - arr = arr.Elem - } - // Now we have the full array size, including its children. - return size -} - // UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification, // without supplying a struct to unpack into. Instead, this method returns a list containing the // values. An atomic argument will be a list with one element. @@ -202,7 +268,7 @@ func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { virtualArgs := 0 for index, arg := range arguments.NonIndexed() { marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data) - if arg.Type.T == ArrayTy && (*arg.Type.Elem).T != StringTy { + if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) { // If we have a static array, like [3]uint256, these are coded as // just like uint256,uint256,uint256. // This means that we need to add two 'virtual' arguments when @@ -213,7 +279,11 @@ func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { // // Calculate the full array size to get the correct offset for the next argument. // Decrement it by 1, as the normal index increment is still applied. - virtualArgs += getArraySize(&arg.Type) - 1 + virtualArgs += getTypeSize(arg.Type)/32 - 1 + } else if arg.Type.T == TupleTy && !isDynamicType(arg.Type) { + // If we have a static tuple, like (uint256, bool, uint256), these are + // coded as just like uint256,bool,uint256 + virtualArgs += getTypeSize(arg.Type)/32 - 1 } if err != nil { return nil, err @@ -243,7 +313,7 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) { // input offset is the bytes offset for packed output inputOffset := 0 for _, abiArg := range abiArgs { - inputOffset += getDynamicTypeOffset(abiArg.Type) + inputOffset += getTypeSize(abiArg.Type) } var ret []byte for i, a := range args { diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go new file mode 100644 index 0000000000..7371dfb1f1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go @@ -0,0 +1,505 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package backends + +import ( + "context" + "errors" + "fmt" + "math/big" + "sync" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/bloombits" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/filters" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" +) + +// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend. +var _ bind.ContractBackend = (*SimulatedBackend)(nil) + +var errBlockNumberUnsupported = errors.New("SimulatedBackend cannot access blocks other than the latest block") +var errGasEstimationFailed = errors.New("gas required exceeds allowance or always failing transaction") + +// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in +// the background. Its main purpose is to allow easily testing contract bindings. +type SimulatedBackend struct { + database ethdb.Database // In memory database to store our testing data + blockchain *core.BlockChain // Ethereum blockchain to handle the consensus + + mu sync.Mutex + pendingBlock *types.Block // Currently pending block that will be imported on request + pendingState *state.StateDB // Currently pending state that will be the active on on request + + events *filters.EventSystem // Event system for filtering log events live + + config *params.ChainConfig +} + +// NewSimulatedBackend creates a new binding backend using a simulated blockchain +// for testing purposes. +func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { + database := rawdb.NewMemoryDatabase() + genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc} + genesis.MustCommit(database) + blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil) + + backend := &SimulatedBackend{ + database: database, + blockchain: blockchain, + config: genesis.Config, + events: filters.NewEventSystem(new(event.TypeMux), &filterBackend{database, blockchain}, false), + } + backend.rollback() + return backend +} + +// Commit imports all the pending transactions as a single block and starts a +// fresh new state. +func (b *SimulatedBackend) Commit() { + b.mu.Lock() + defer b.mu.Unlock() + + if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil { + panic(err) // This cannot happen unless the simulator is wrong, fail in that case + } + b.rollback() +} + +// Rollback aborts all pending transactions, reverting to the last committed state. +func (b *SimulatedBackend) Rollback() { + b.mu.Lock() + defer b.mu.Unlock() + + b.rollback() +} + +func (b *SimulatedBackend) rollback() { + blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {}) + statedb, _ := b.blockchain.State() + + b.pendingBlock = blocks[0] + b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database()) +} + +// CodeAt returns the code associated with a certain account in the blockchain. +func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { + b.mu.Lock() + defer b.mu.Unlock() + + if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { + return nil, errBlockNumberUnsupported + } + statedb, _ := b.blockchain.State() + return statedb.GetCode(contract), nil +} + +// BalanceAt returns the wei balance of a certain account in the blockchain. +func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) { + b.mu.Lock() + defer b.mu.Unlock() + + if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { + return nil, errBlockNumberUnsupported + } + statedb, _ := b.blockchain.State() + return statedb.GetBalance(contract), nil +} + +// NonceAt returns the nonce of a certain account in the blockchain. +func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (uint64, error) { + b.mu.Lock() + defer b.mu.Unlock() + + if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { + return 0, errBlockNumberUnsupported + } + statedb, _ := b.blockchain.State() + return statedb.GetNonce(contract), nil +} + +// StorageAt returns the value of key in the storage of an account in the blockchain. +func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { + b.mu.Lock() + defer b.mu.Unlock() + + if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { + return nil, errBlockNumberUnsupported + } + statedb, _ := b.blockchain.State() + val := statedb.GetState(contract, key) + return val[:], nil +} + +// TransactionReceipt returns the receipt of a transaction. +func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + receipt, _, _, _ := rawdb.ReadReceipt(b.database, txHash) + return receipt, nil +} + +// TransactionByHash checks the pool of pending transactions in addition to the +// blockchain. The isPending return value indicates whether the transaction has been +// mined yet. Note that the transaction may not be part of the canonical chain even if +// it's not pending. +func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) { + b.mu.Lock() + defer b.mu.Unlock() + + tx := b.pendingBlock.Transaction(txHash) + if tx != nil { + return tx, true, nil + } + tx, _, _, _ = rawdb.ReadTransaction(b.database, txHash) + if tx != nil { + return tx, false, nil + } + return nil, false, ethereum.NotFound +} + +// PendingCodeAt returns the code associated with an account in the pending state. +func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) { + b.mu.Lock() + defer b.mu.Unlock() + + return b.pendingState.GetCode(contract), nil +} + +// CallContract executes a contract call. +func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + b.mu.Lock() + defer b.mu.Unlock() + + if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { + return nil, errBlockNumberUnsupported + } + state, err := b.blockchain.State() + if err != nil { + return nil, err + } + rval, _, _, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), state) + return rval, err +} + +// PendingCallContract executes a contract call on the pending state. +func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) { + b.mu.Lock() + defer b.mu.Unlock() + defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot()) + + rval, _, _, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) + return rval, err +} + +// PendingNonceAt implements PendingStateReader.PendingNonceAt, retrieving +// the nonce currently pending for the account. +func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { + b.mu.Lock() + defer b.mu.Unlock() + + return b.pendingState.GetOrNewStateObject(account).Nonce(), nil +} + +// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated +// chain doesn't have miners, we just return a gas price of 1 for any call. +func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + return big.NewInt(1), nil +} + +// EstimateGas executes the requested code against the currently pending block/state and +// returns the used amount of gas. +func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { + b.mu.Lock() + defer b.mu.Unlock() + + // Determine the lowest and highest possible gas limits to binary search in between + var ( + lo uint64 = params.TxGas - 1 + hi uint64 + cap uint64 + ) + if call.Gas >= params.TxGas { + hi = call.Gas + } else { + hi = b.pendingBlock.GasLimit() + } + cap = hi + + // Create a helper to check if a gas allowance results in an executable transaction + executable := func(gas uint64) bool { + call.Gas = gas + + snapshot := b.pendingState.Snapshot() + _, _, failed, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) + b.pendingState.RevertToSnapshot(snapshot) + + if err != nil || failed { + return false + } + return true + } + // Execute the binary search and hone in on an executable gas limit + for lo+1 < hi { + mid := (hi + lo) / 2 + if !executable(mid) { + lo = mid + } else { + hi = mid + } + } + // Reject the transaction as invalid if it still fails at the highest allowance + if hi == cap { + if !executable(hi) { + return 0, errGasEstimationFailed + } + } + return hi, nil +} + +// callContract implements common code between normal and pending contract calls. +// state is modified during execution, make sure to copy it if necessary. +func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB) ([]byte, uint64, bool, error) { + // Ensure message is initialized properly. + if call.GasPrice == nil { + call.GasPrice = big.NewInt(1) + } + if call.Gas == 0 { + call.Gas = 50000000 + } + if call.Value == nil { + call.Value = new(big.Int) + } + // Set infinite balance to the fake caller account. + from := statedb.GetOrNewStateObject(call.From) + from.SetBalance(math.MaxBig256) + // Execute the call. + msg := callmsg{call} + + evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil) + // Create a new environment which holds all relevant information + // about the transaction and calling mechanisms. + vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{}) + gaspool := new(core.GasPool).AddGas(math.MaxUint64) + + return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() +} + +// SendTransaction updates the pending block to include the given transaction. +// It panics if the transaction is invalid. +func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { + b.mu.Lock() + defer b.mu.Unlock() + + sender, err := types.Sender(types.HomesteadSigner{}, tx) + if err != nil { + panic(fmt.Errorf("invalid transaction: %v", err)) + } + nonce := b.pendingState.GetNonce(sender) + if tx.Nonce() != nonce { + panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce)) + } + + blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) { + for _, tx := range b.pendingBlock.Transactions() { + block.AddTxWithChain(b.blockchain, tx) + } + block.AddTxWithChain(b.blockchain, tx) + }) + statedb, _ := b.blockchain.State() + + b.pendingBlock = blocks[0] + b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database()) + return nil +} + +// FilterLogs executes a log filter operation, blocking during execution and +// returning all the results in one batch. +// +// TODO(karalabe): Deprecate when the subscription one can return past data too. +func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) { + var filter *filters.Filter + if query.BlockHash != nil { + // Block filter requested, construct a single-shot filter + filter = filters.NewBlockFilter(&filterBackend{b.database, b.blockchain}, *query.BlockHash, query.Addresses, query.Topics) + } else { + // Initialize unset filter boundaried to run from genesis to chain head + from := int64(0) + if query.FromBlock != nil { + from = query.FromBlock.Int64() + } + to := int64(-1) + if query.ToBlock != nil { + to = query.ToBlock.Int64() + } + // Construct the range filter + filter = filters.NewRangeFilter(&filterBackend{b.database, b.blockchain}, from, to, query.Addresses, query.Topics) + } + // Run the filter and return all the logs + logs, err := filter.Logs(ctx) + if err != nil { + return nil, err + } + res := make([]types.Log, len(logs)) + for i, log := range logs { + res[i] = *log + } + return res, nil +} + +// SubscribeFilterLogs creates a background log filtering operation, returning a +// subscription immediately, which can be used to stream the found events. +func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { + // Subscribe to contract events + sink := make(chan []*types.Log) + + sub, err := b.events.SubscribeLogs(query, sink) + if err != nil { + return nil, err + } + // Since we're getting logs in batches, we need to flatten them into a plain stream + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case logs := <-sink: + for _, log := range logs { + select { + case ch <- *log: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// AdjustTime adds a time shift to the simulated clock. +func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error { + b.mu.Lock() + defer b.mu.Unlock() + blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) { + for _, tx := range b.pendingBlock.Transactions() { + block.AddTx(tx) + } + block.OffsetTime(int64(adjustment.Seconds())) + }) + statedb, _ := b.blockchain.State() + + b.pendingBlock = blocks[0] + b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database()) + + return nil +} + +// callmsg implements core.Message to allow passing it as a transaction simulator. +type callmsg struct { + ethereum.CallMsg +} + +func (m callmsg) From() common.Address { return m.CallMsg.From } +func (m callmsg) Nonce() uint64 { return 0 } +func (m callmsg) CheckNonce() bool { return false } +func (m callmsg) To() *common.Address { return m.CallMsg.To } +func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } +func (m callmsg) Gas() uint64 { return m.CallMsg.Gas } +func (m callmsg) Value() *big.Int { return m.CallMsg.Value } +func (m callmsg) Data() []byte { return m.CallMsg.Data } + +// filterBackend implements filters.Backend to support filtering for logs without +// taking bloom-bits acceleration structures into account. +type filterBackend struct { + db ethdb.Database + bc *core.BlockChain +} + +func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db } +func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") } + +func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) { + if block == rpc.LatestBlockNumber { + return fb.bc.CurrentHeader(), nil + } + return fb.bc.GetHeaderByNumber(uint64(block.Int64())), nil +} + +func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + return fb.bc.GetHeaderByHash(hash), nil +} + +func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { + number := rawdb.ReadHeaderNumber(fb.db, hash) + if number == nil { + return nil, nil + } + return rawdb.ReadReceipts(fb.db, hash, *number), nil +} + +func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { + number := rawdb.ReadHeaderNumber(fb.db, hash) + if number == nil { + return nil, nil + } + receipts := rawdb.ReadReceipts(fb.db, hash, *number) + if receipts == nil { + return nil, nil + } + logs := make([][]*types.Log, len(receipts)) + for i, receipt := range receipts { + logs[i] = receipt.Logs + } + return logs, nil +} + +func (fb *filterBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { + return event.NewSubscription(func(quit <-chan struct{}) error { + <-quit + return nil + }) +} +func (fb *filterBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { + return fb.bc.SubscribeChainEvent(ch) +} +func (fb *filterBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { + return fb.bc.SubscribeRemovedLogsEvent(ch) +} +func (fb *filterBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { + return fb.bc.SubscribeLogsEvent(ch) +} + +func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 } +func (fb *filterBackend) ServiceFilter(ctx context.Context, ms *bloombits.MatcherSession) { + panic("not supported") +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go index c37bdf11d5..f70f911d37 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go @@ -340,6 +340,22 @@ func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) return parseTopics(out, indexed, log.Topics[1:]) } +// UnpackLogIntoMap unpacks a retrieved log into the provided map. +func (c *BoundContract) UnpackLogIntoMap(out map[string]interface{}, event string, log types.Log) error { + if len(log.Data) > 0 { + if err := c.abi.UnpackIntoMap(out, event, log.Data); err != nil { + return err + } + } + var indexed abi.Arguments + for _, arg := range c.abi.Events[event].Inputs { + if arg.Indexed { + indexed = append(indexed, arg) + } + } + return parseTopicsIntoMap(out, indexed, log.Topics[1:]) +} + // ensureContext is a helper method to ensure a context is not nil, even if the // user specified it as such. func ensureContext(ctx context.Context) context.Context { diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go index 600dfcda97..c7657b4a41 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go @@ -17,6 +17,7 @@ package bind import ( + "encoding/binary" "errors" "fmt" "math/big" @@ -83,8 +84,10 @@ func makeTopics(query ...[]interface{}) ([][]common.Hash, error) { val := reflect.ValueOf(rule) switch { + + // static byte array case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8: - reflect.Copy(reflect.ValueOf(topic[common.HashLength-val.Len():]), val) + reflect.Copy(reflect.ValueOf(topic[:val.Len()]), val) default: return nil, fmt.Errorf("unsupported indexed type: %T", rule) @@ -175,8 +178,10 @@ func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) er default: // Ran out of custom types, try the crazies switch { + + // static byte array case arg.Type.T == abi.FixedBytesTy: - reflect.Copy(field, reflect.ValueOf(topics[0][common.HashLength-arg.Type.Size:])) + reflect.Copy(field, reflect.ValueOf(topics[0][:arg.Type.Size])) default: return fmt.Errorf("unsupported indexed type: %v", arg.Type) @@ -187,3 +192,50 @@ func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) er } return nil } + +// parseTopicsIntoMap converts the indexed topic field-value pairs into map key-value pairs +func parseTopicsIntoMap(out map[string]interface{}, fields abi.Arguments, topics []common.Hash) error { + // Sanity check that the fields and topics match up + if len(fields) != len(topics) { + return errors.New("topic/field count mismatch") + } + // Iterate over all the fields and reconstruct them from topics + for _, arg := range fields { + if !arg.Indexed { + return errors.New("non-indexed field in topic reconstruction") + } + + switch arg.Type.T { + case abi.BoolTy: + out[arg.Name] = topics[0][common.HashLength-1] == 1 + case abi.IntTy, abi.UintTy: + num := new(big.Int).SetBytes(topics[0][:]) + out[arg.Name] = num + case abi.AddressTy: + var addr common.Address + copy(addr[:], topics[0][common.HashLength-common.AddressLength:]) + out[arg.Name] = addr + case abi.HashTy: + out[arg.Name] = topics[0] + case abi.FixedBytesTy: + out[arg.Name] = topics[0][:] + case abi.StringTy, abi.BytesTy, abi.SliceTy, abi.ArrayTy: + // Array types (including strings and bytes) have their keccak256 hashes stored in the topic- not a hash + // whose bytes can be decoded to the actual value- so the best we can do is retrieve that hash + out[arg.Name] = topics[0] + case abi.FunctionTy: + if garbage := binary.BigEndian.Uint64(topics[0][0:8]); garbage != 0 { + return fmt.Errorf("bind: got improperly encoded function type, got %v", topics[0].Bytes()) + } + var tmp [24]byte + copy(tmp[:], topics[0][8:32]) + out[arg.Name] = tmp + default: // Not handling tuples + return fmt.Errorf("unsupported indexed type: %v", arg.Type) + } + + topics = topics[1:] + } + + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go index f541cf3bfe..ccc6a65932 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go @@ -71,18 +71,17 @@ func mustArrayToByteSlice(value reflect.Value) reflect.Value { // // set is a bit more lenient when it comes to assignment and doesn't force an as // strict ruleset as bare `reflect` does. -func set(dst, src reflect.Value, output Argument) error { - dstType := dst.Type() - srcType := src.Type() +func set(dst, src reflect.Value) error { + dstType, srcType := dst.Type(), src.Type() switch { - case dstType.AssignableTo(srcType): + case dstType.Kind() == reflect.Interface && dst.Elem().IsValid(): + return set(dst.Elem(), src) + case dstType.Kind() == reflect.Ptr && dstType.Elem() != derefbigT: + return set(dst.Elem(), src) + case srcType.AssignableTo(dstType) && dst.CanSet(): dst.Set(src) case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice: - return setSlice(dst, src, output) - case dstType.Kind() == reflect.Interface: - dst.Set(src) - case dstType.Kind() == reflect.Ptr: - return set(dst.Elem(), src, output) + return setSlice(dst, src) default: return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type()) } @@ -91,7 +90,7 @@ func set(dst, src reflect.Value, output Argument) error { // setSlice attempts to assign src to dst when slices are not assignable by default // e.g. src: [][]byte -> dst: [][15]byte -func setSlice(dst, src reflect.Value, output Argument) error { +func setSlice(dst, src reflect.Value) error { slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len()) for i := 0; i < src.Len(); i++ { v := src.Index(i) @@ -127,14 +126,14 @@ func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind, return nil } -// mapAbiToStringField maps abi to struct fields. +// mapArgNamesToStructFields maps a slice of argument names to struct fields. // first round: for each Exportable field that contains a `abi:""` tag -// and this field name exists in the arguments, pair them together. -// second round: for each argument field that has not been already linked, +// and this field name exists in the given argument name list, pair them together. +// second round: for each argument name that has not been already linked, // find what variable is expected to be mapped into, if it exists and has not been // used, pair them. -func mapAbiToStructFields(args Arguments, value reflect.Value) (map[string]string, error) { - +// Note this function assumes the given value is a struct value. +func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[string]string, error) { typ := value.Type() abi2struct := make(map[string]string) @@ -148,45 +147,39 @@ func mapAbiToStructFields(args Arguments, value reflect.Value) (map[string]strin if structFieldName[:1] != strings.ToUpper(structFieldName[:1]) { continue } - // skip fields that have no abi:"" tag. var ok bool var tagName string if tagName, ok = typ.Field(i).Tag.Lookup("abi"); !ok { continue } - // check if tag is empty. if tagName == "" { return nil, fmt.Errorf("struct: abi tag in '%s' is empty", structFieldName) } - // check which argument field matches with the abi tag. found := false - for _, abiField := range args.NonIndexed() { - if abiField.Name == tagName { - if abi2struct[abiField.Name] != "" { + for _, arg := range argNames { + if arg == tagName { + if abi2struct[arg] != "" { return nil, fmt.Errorf("struct: abi tag in '%s' already mapped", structFieldName) } // pair them - abi2struct[abiField.Name] = structFieldName - struct2abi[structFieldName] = abiField.Name + abi2struct[arg] = structFieldName + struct2abi[structFieldName] = arg found = true } } - // check if this tag has been mapped. if !found { return nil, fmt.Errorf("struct: abi tag '%s' defined but not found in abi", tagName) } - } // second round ~~~ - for _, arg := range args { + for _, argName := range argNames { - abiFieldName := arg.Name - structFieldName := ToCamelCase(abiFieldName) + structFieldName := ToCamelCase(argName) if structFieldName == "" { return nil, fmt.Errorf("abi: purely underscored output cannot unpack to struct") @@ -196,11 +189,11 @@ func mapAbiToStructFields(args Arguments, value reflect.Value) (map[string]strin // struct field with the same field name. If so, raise an error: // abi: [ { "name": "value" } ] // struct { Value *big.Int , Value1 *big.Int `abi:"value"`} - if abi2struct[abiFieldName] != "" { - if abi2struct[abiFieldName] != structFieldName && + if abi2struct[argName] != "" { + if abi2struct[argName] != structFieldName && struct2abi[structFieldName] == "" && value.FieldByName(structFieldName).IsValid() { - return nil, fmt.Errorf("abi: multiple variables maps to the same abi field '%s'", abiFieldName) + return nil, fmt.Errorf("abi: multiple variables maps to the same abi field '%s'", argName) } continue } @@ -212,16 +205,14 @@ func mapAbiToStructFields(args Arguments, value reflect.Value) (map[string]strin if value.FieldByName(structFieldName).IsValid() { // pair them - abi2struct[abiFieldName] = structFieldName - struct2abi[structFieldName] = abiFieldName + abi2struct[argName] = structFieldName + struct2abi[structFieldName] = argName } else { // not paired, but annotate as used, to detect cases like // abi : [ { "name": "value" }, { "name": "_value" } ] // struct { Value *big.Int } - struct2abi[structFieldName] = abiFieldName + struct2abi[structFieldName] = argName } - } - return abi2struct, nil } diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go index 6bfaabf5a5..1a37182353 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go @@ -17,6 +17,7 @@ package abi import ( + "errors" "fmt" "reflect" "regexp" @@ -32,6 +33,7 @@ const ( StringTy SliceTy ArrayTy + TupleTy AddressTy FixedBytesTy BytesTy @@ -43,13 +45,16 @@ const ( // Type is the reflection of the supported argument type type Type struct { Elem *Type - Kind reflect.Kind Type reflect.Type Size int T byte // Our own type checking stringKind string // holds the unparsed string for deriving signatures + + // Tuple relative fields + TupleElems []*Type // Type information of all tuple fields + TupleRawNames []string // Raw field name of all tuple fields } var ( @@ -58,7 +63,7 @@ var ( ) // NewType creates a new reflection type of abi type given in t. -func NewType(t string) (typ Type, err error) { +func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) { // check that array brackets are equal if they exist if strings.Count(t, "[") != strings.Count(t, "]") { return Type{}, fmt.Errorf("invalid arg type in abi") @@ -71,7 +76,7 @@ func NewType(t string) (typ Type, err error) { if strings.Count(t, "[") != 0 { i := strings.LastIndex(t, "[") // recursively embed the type - embeddedType, err := NewType(t[:i]) + embeddedType, err := NewType(t[:i], components) if err != nil { return Type{}, err } @@ -87,6 +92,9 @@ func NewType(t string) (typ Type, err error) { typ.Kind = reflect.Slice typ.Elem = &embeddedType typ.Type = reflect.SliceOf(embeddedType.Type) + if embeddedType.T == TupleTy { + typ.stringKind = embeddedType.stringKind + sliced + } } else if len(intz) == 1 { // is a array typ.T = ArrayTy @@ -97,6 +105,9 @@ func NewType(t string) (typ Type, err error) { return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) } typ.Type = reflect.ArrayOf(typ.Size, embeddedType.Type) + if embeddedType.T == TupleTy { + typ.stringKind = embeddedType.stringKind + sliced + } } else { return Type{}, fmt.Errorf("invalid formatting of array type") } @@ -158,6 +169,41 @@ func NewType(t string) (typ Type, err error) { typ.Size = varSize typ.Type = reflect.ArrayOf(varSize, reflect.TypeOf(byte(0))) } + case "tuple": + var ( + fields []reflect.StructField + elems []*Type + names []string + expression string // canonical parameter expression + ) + expression += "(" + for idx, c := range components { + cType, err := NewType(c.Type, c.Components) + if err != nil { + return Type{}, err + } + if ToCamelCase(c.Name) == "" { + return Type{}, errors.New("abi: purely anonymous or underscored field is not supported") + } + fields = append(fields, reflect.StructField{ + Name: ToCamelCase(c.Name), // reflect.StructOf will panic for any exported field. + Type: cType.Type, + Tag: reflect.StructTag("json:\"" + c.Name + "\""), + }) + elems = append(elems, &cType) + names = append(names, c.Name) + expression += cType.stringKind + if idx != len(components)-1 { + expression += "," + } + } + expression += ")" + typ.Kind = reflect.Struct + typ.Type = reflect.StructOf(fields) + typ.TupleElems = elems + typ.TupleRawNames = names + typ.T = TupleTy + typ.stringKind = expression case "function": typ.Kind = reflect.Array typ.T = FunctionTy @@ -178,7 +224,6 @@ func (t Type) String() (out string) { func (t Type) pack(v reflect.Value) ([]byte, error) { // dereference pointer first if it's a pointer v = indirect(v) - if err := typeCheck(t, v); err != nil { return nil, err } @@ -196,7 +241,7 @@ func (t Type) pack(v reflect.Value) ([]byte, error) { offset := 0 offsetReq := isDynamicType(*t.Elem) if offsetReq { - offset = getDynamicTypeOffset(*t.Elem) * v.Len() + offset = getTypeSize(*t.Elem) * v.Len() } var tail []byte for i := 0; i < v.Len(); i++ { @@ -213,6 +258,45 @@ func (t Type) pack(v reflect.Value) ([]byte, error) { tail = append(tail, val...) } return append(ret, tail...), nil + case TupleTy: + // (T1,...,Tk) for k >= 0 and any types T1, …, Tk + // enc(X) = head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(k)) + // where X = (X(1), ..., X(k)) and head and tail are defined for Ti being a static + // type as + // head(X(i)) = enc(X(i)) and tail(X(i)) = "" (the empty string) + // and as + // head(X(i)) = enc(len(head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(i-1)))) + // tail(X(i)) = enc(X(i)) + // otherwise, i.e. if Ti is a dynamic type. + fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, v) + if err != nil { + return nil, err + } + // Calculate prefix occupied size. + offset := 0 + for _, elem := range t.TupleElems { + offset += getTypeSize(*elem) + } + var ret, tail []byte + for i, elem := range t.TupleElems { + field := v.FieldByName(fieldmap[t.TupleRawNames[i]]) + if !field.IsValid() { + return nil, fmt.Errorf("field %s for tuple not found in the given struct", t.TupleRawNames[i]) + } + val, err := elem.pack(field) + if err != nil { + return nil, err + } + if isDynamicType(*elem) { + ret = append(ret, packNum(reflect.ValueOf(offset))...) + tail = append(tail, val...) + offset += len(val) + } else { + ret = append(ret, val...) + } + } + return append(ret, tail...), nil + default: return packElement(t, v), nil } @@ -225,25 +309,45 @@ func (t Type) requiresLengthPrefix() bool { } // isDynamicType returns true if the type is dynamic. -// StringTy, BytesTy, and SliceTy(irrespective of slice element type) are dynamic types -// ArrayTy is considered dynamic if and only if the Array element is a dynamic type. -// This function recursively checks the type for slice and array elements. +// The following types are called “dynamic”: +// * bytes +// * string +// * T[] for any T +// * T[k] for any dynamic T and any k >= 0 +// * (T1,...,Tk) if Ti is dynamic for some 1 <= i <= k func isDynamicType(t Type) bool { - // dynamic types - // array is also a dynamic type if the array type is dynamic + if t.T == TupleTy { + for _, elem := range t.TupleElems { + if isDynamicType(*elem) { + return true + } + } + return false + } return t.T == StringTy || t.T == BytesTy || t.T == SliceTy || (t.T == ArrayTy && isDynamicType(*t.Elem)) } -// getDynamicTypeOffset returns the offset for the type. -// See `isDynamicType` to know which types are considered dynamic. -// If the type t is an array and element type is not a dynamic type, then we consider it a static type and -// return 32 * size of array since length prefix is not required. -// If t is a dynamic type or element type(for slices and arrays) is dynamic, then we simply return 32 as offset. -func getDynamicTypeOffset(t Type) int { - // if it is an array and there are no dynamic types - // then the array is static type +// getTypeSize returns the size that this type needs to occupy. +// We distinguish static and dynamic types. Static types are encoded in-place +// and dynamic types are encoded at a separately allocated location after the +// current block. +// So for a static variable, the size returned represents the size that the +// variable actually occupies. +// For a dynamic variable, the returned size is fixed 32 bytes, which is used +// to store the location reference for actual value storage. +func getTypeSize(t Type) int { if t.T == ArrayTy && !isDynamicType(*t.Elem) { - return 32 * t.Size + // Recursively calculate type size if it is a nested array + if t.Elem.T == ArrayTy { + return t.Size * getTypeSize(*t.Elem) + } + return t.Size * 32 + } else if t.T == TupleTy && !isDynamicType(t) { + total := 0 + for _, elem := range t.TupleElems { + total += getTypeSize(*elem) + } + return total } return 32 } diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/unpack.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/unpack.go index 04716f7a2a..b2e61d06c4 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/unpack.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/unpack.go @@ -115,17 +115,6 @@ func readFixedBytes(t Type, word []byte) (interface{}, error) { } -func getFullElemSize(elem *Type) int { - //all other should be counted as 32 (slices have pointers to respective elements) - size := 32 - //arrays wrap it, each element being the same size - for elem.T == ArrayTy { - size *= elem.Size - elem = elem.Elem - } - return size -} - // iteratively unpack elements func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) { if size < 0 { @@ -150,13 +139,9 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) // Arrays have packed elements, resulting in longer unpack steps. // Slices have just 32 bytes per element (pointing to the contents). - elemSize := 32 - if t.T == ArrayTy || t.T == SliceTy { - elemSize = getFullElemSize(t.Elem) - } + elemSize := getTypeSize(*t.Elem) for i, j := start, 0; j < size; i, j = i+elemSize, j+1 { - inter, err := toGoType(i, *t.Elem, output) if err != nil { return nil, err @@ -170,6 +155,36 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) return refSlice.Interface(), nil } +func forTupleUnpack(t Type, output []byte) (interface{}, error) { + retval := reflect.New(t.Type).Elem() + virtualArgs := 0 + for index, elem := range t.TupleElems { + marshalledValue, err := toGoType((index+virtualArgs)*32, *elem, output) + if elem.T == ArrayTy && !isDynamicType(*elem) { + // If we have a static array, like [3]uint256, these are coded as + // just like uint256,uint256,uint256. + // This means that we need to add two 'virtual' arguments when + // we count the index from now on. + // + // Array values nested multiple levels deep are also encoded inline: + // [2][3]uint256: uint256,uint256,uint256,uint256,uint256,uint256 + // + // Calculate the full array size to get the correct offset for the next argument. + // Decrement it by 1, as the normal index increment is still applied. + virtualArgs += getTypeSize(*elem)/32 - 1 + } else if elem.T == TupleTy && !isDynamicType(*elem) { + // If we have a static tuple, like (uint256, bool, uint256), these are + // coded as just like uint256,bool,uint256 + virtualArgs += getTypeSize(*elem)/32 - 1 + } + if err != nil { + return nil, err + } + retval.Field(index).Set(reflect.ValueOf(marshalledValue)) + } + return retval.Interface(), nil +} + // toGoType parses the output bytes and recursively assigns the value of these bytes // into a go type with accordance with the ABI spec. func toGoType(index int, t Type, output []byte) (interface{}, error) { @@ -178,14 +193,14 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) { } var ( - returnOutput []byte - begin, end int - err error + returnOutput []byte + begin, length int + err error ) // if we require a length prefix, find the beginning word and size returned. if t.requiresLengthPrefix() { - begin, end, err = lengthPrefixPointsTo(index, output) + begin, length, err = lengthPrefixPointsTo(index, output) if err != nil { return nil, err } @@ -194,19 +209,26 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) { } switch t.T { - case SliceTy: - if (*t.Elem).T == StringTy { - return forEachUnpack(t, output[begin:], 0, end) + case TupleTy: + if isDynamicType(t) { + begin, err := tuplePointsTo(index, output) + if err != nil { + return nil, err + } + return forTupleUnpack(t, output[begin:]) + } else { + return forTupleUnpack(t, output[index:]) } - return forEachUnpack(t, output, begin, end) + case SliceTy: + return forEachUnpack(t, output[begin:], 0, length) case ArrayTy: - if (*t.Elem).T == StringTy { + if isDynamicType(*t.Elem) { offset := int64(binary.BigEndian.Uint64(returnOutput[len(returnOutput)-8:])) return forEachUnpack(t, output[offset:], 0, t.Size) } - return forEachUnpack(t, output, index, t.Size) + return forEachUnpack(t, output[index:], 0, t.Size) case StringTy: // variable arrays are written at the end of the return bytes - return string(output[begin : begin+end]), nil + return string(output[begin : begin+length]), nil case IntTy, UintTy: return readInteger(t.T, t.Kind, returnOutput), nil case BoolTy: @@ -216,7 +238,7 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) { case HashTy: return common.BytesToHash(returnOutput), nil case BytesTy: - return output[begin : begin+end], nil + return output[begin : begin+length], nil case FixedBytesTy: return readFixedBytes(t, returnOutput) case FunctionTy: @@ -247,7 +269,7 @@ func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err totalSize.Add(totalSize, bigOffsetEnd) totalSize.Add(totalSize, lengthBig) if totalSize.BitLen() > 63 { - return 0, 0, fmt.Errorf("abi length larger than int64: %v", totalSize) + return 0, 0, fmt.Errorf("abi: length larger than int64: %v", totalSize) } if totalSize.Cmp(outputLength) > 0 { @@ -257,3 +279,17 @@ func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err length = int(lengthBig.Uint64()) return } + +// tuplePointsTo resolves the location reference for dynamic tuple. +func tuplePointsTo(index int, output []byte) (start int, err error) { + offset := big.NewInt(0).SetBytes(output[index : index+32]) + outputLen := big.NewInt(int64(len(output))) + + if offset.Cmp(big.NewInt(int64(len(output)))) > 0 { + return 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", offset, outputLen) + } + if offset.BitLen() > 63 { + return 0, fmt.Errorf("abi offset larger than int64: %v", offset) + } + return int(offset.Uint64()), nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/accounts.go b/vendor/github.com/ethereum/go-ethereum/accounts/accounts.go index cb1eae2815..a52aa425c8 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/accounts.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/accounts.go @@ -18,12 +18,14 @@ package accounts import ( + "fmt" "math/big" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" + "golang.org/x/crypto/sha3" ) // Account represents an Ethereum account located at a specific location defined @@ -33,6 +35,13 @@ type Account struct { URL URL `json:"url"` // Optional resource locator within a backend } +const ( + MimetypeTextWithValidator = "text/validator" + MimetypeTypedData = "data/typed" + MimetypeClique = "application/x-clique-header" + MimetypeTextPlain = "text/plain" +) + // Wallet represents a software or hardware wallet that might contain one or more // accounts (derived from the same seed). type Wallet interface { @@ -87,8 +96,26 @@ type Wallet interface { // chain state reader. SelfDerive(base DerivationPath, chain ethereum.ChainStateReader) - // SignHash requests the wallet to sign the given hash. + // SignData requests the wallet to sign the hash of the given data + // It looks up the account specified either solely via its address contained within, + // or optionally with the aid of any location metadata from the embedded URL field. // + // If the wallet requires additional authentication to sign the request (e.g. + // a password to decrypt the account, or a PIN code o verify the transaction), + // an AuthNeededError instance will be returned, containing infos for the user + // about which fields or actions are needed. The user may retry by providing + // the needed details via SignDataWithPassphrase, or by other means (e.g. unlock + // the account in a keystore). + SignData(account Account, mimeType string, data []byte) ([]byte, error) + + // SignDataWithPassphrase is identical to SignData, but also takes a password + // NOTE: there's an chance that an erroneous call might mistake the two strings, and + // supply password in the mimetype field, or vice versa. Thus, an implementation + // should never echo the mimetype or return the mimetype in the error-response + SignDataWithPassphrase(account Account, passphrase, mimeType string, data []byte) ([]byte, error) + + // SignText requests the wallet to sign the hash of a given piece of data, prefixed + // by the Ethereum prefix scheme // It looks up the account specified either solely via its address contained within, // or optionally with the aid of any location metadata from the embedded URL field. // @@ -98,7 +125,10 @@ type Wallet interface { // about which fields or actions are needed. The user may retry by providing // the needed details via SignHashWithPassphrase, or by other means (e.g. unlock // the account in a keystore). - SignHash(account Account, hash []byte) ([]byte, error) + SignText(account Account, text []byte) ([]byte, error) + + // SignTextWithPassphrase is identical to Signtext, but also takes a password + SignTextWithPassphrase(account Account, passphrase string, hash []byte) ([]byte, error) // SignTx requests the wallet to sign the given transaction. // @@ -113,18 +143,7 @@ type Wallet interface { // the account in a keystore). SignTx(account Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) - // SignHashWithPassphrase requests the wallet to sign the given hash with the - // given passphrase as extra authentication information. - // - // It looks up the account specified either solely via its address contained within, - // or optionally with the aid of any location metadata from the embedded URL field. - SignHashWithPassphrase(account Account, passphrase string, hash []byte) ([]byte, error) - - // SignTxWithPassphrase requests the wallet to sign the given transaction, with the - // given passphrase as extra authentication information. - // - // It looks up the account specified either solely via its address contained within, - // or optionally with the aid of any location metadata from the embedded URL field. + // SignTxWithPassphrase is identical to SignTx, but also takes a password SignTxWithPassphrase(account Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) } @@ -148,6 +167,32 @@ type Backend interface { Subscribe(sink chan<- WalletEvent) event.Subscription } +// TextHash is a helper function that calculates a hash for the given message that can be +// safely used to calculate a signature from. +// +// The hash is calulcated as +// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}). +// +// This gives context to the signed message and prevents signing of transactions. +func TextHash(data []byte) []byte { + hash, _ := TextAndHash(data) + return hash +} + +// TextAndHash is a helper function that calculates a hash for the given message that can be +// safely used to calculate a signature from. +// +// The hash is calulcated as +// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}). +// +// This gives context to the signed message and prevents signing of transactions. +func TextAndHash(data []byte) ([]byte, string) { + msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), string(data)) + hasher := sha3.NewLegacyKeccak256() + hasher.Write([]byte(msg)) + return hasher.Sum(nil), msg +} + // WalletEventType represents the different event types that can be fired by // the wallet subscription subsystem. type WalletEventType int diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/external/backend.go b/vendor/github.com/ethereum/go-ethereum/accounts/external/backend.go new file mode 100644 index 0000000000..21a313b669 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/external/backend.go @@ -0,0 +1,228 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see . + +package external + +import ( + "fmt" + "math/big" + "sync" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/signer/core" +) + +type ExternalBackend struct { + signers []accounts.Wallet +} + +func (eb *ExternalBackend) Wallets() []accounts.Wallet { + return eb.signers +} + +func NewExternalBackend(endpoint string) (*ExternalBackend, error) { + signer, err := NewExternalSigner(endpoint) + if err != nil { + return nil, err + } + return &ExternalBackend{ + signers: []accounts.Wallet{signer}, + }, nil +} + +func (eb *ExternalBackend) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { + return event.NewSubscription(func(quit <-chan struct{}) error { + <-quit + return nil + }) +} + +// ExternalSigner provides an API to interact with an external signer (clef) +// It proxies request to the external signer while forwarding relevant +// request headers +type ExternalSigner struct { + client *rpc.Client + endpoint string + status string + cacheMu sync.RWMutex + cache []accounts.Account +} + +func NewExternalSigner(endpoint string) (*ExternalSigner, error) { + client, err := rpc.Dial(endpoint) + if err != nil { + return nil, err + } + extsigner := &ExternalSigner{ + client: client, + endpoint: endpoint, + } + // Check if reachable + version, err := extsigner.pingVersion() + if err != nil { + return nil, err + } + extsigner.status = fmt.Sprintf("ok [version=%v]", version) + return extsigner, nil +} + +func (api *ExternalSigner) URL() accounts.URL { + return accounts.URL{ + Scheme: "extapi", + Path: api.endpoint, + } +} + +func (api *ExternalSigner) Status() (string, error) { + return api.status, nil +} + +func (api *ExternalSigner) Open(passphrase string) error { + return fmt.Errorf("operation not supported on external signers") +} + +func (api *ExternalSigner) Close() error { + return fmt.Errorf("operation not supported on external signers") +} + +func (api *ExternalSigner) Accounts() []accounts.Account { + var accnts []accounts.Account + res, err := api.listAccounts() + if err != nil { + log.Error("account listing failed", "error", err) + return accnts + } + for _, addr := range res { + accnts = append(accnts, accounts.Account{ + URL: accounts.URL{ + Scheme: "extapi", + Path: api.endpoint, + }, + Address: addr, + }) + } + api.cacheMu.Lock() + api.cache = accnts + api.cacheMu.Unlock() + return accnts +} + +func (api *ExternalSigner) Contains(account accounts.Account) bool { + api.cacheMu.RLock() + defer api.cacheMu.RUnlock() + for _, a := range api.cache { + if a.Address == account.Address && (account.URL == (accounts.URL{}) || account.URL == api.URL()) { + return true + } + } + return false +} + +func (api *ExternalSigner) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { + return accounts.Account{}, fmt.Errorf("operation not supported on external signers") +} + +func (api *ExternalSigner) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) { + log.Error("operation SelfDerive not supported on external signers") +} + +func (api *ExternalSigner) signHash(account accounts.Account, hash []byte) ([]byte, error) { + return []byte{}, fmt.Errorf("operation not supported on external signers") +} + +// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed +func (api *ExternalSigner) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { + var res hexutil.Bytes + var signAddress = common.NewMixedcaseAddress(account.Address) + if err := api.client.Call(&res, "account_signData", + mimeType, + &signAddress, // Need to use the pointer here, because of how MarshalJSON is defined + hexutil.Encode(data)); err != nil { + return nil, err + } + // If V is on 27/28-form, convert to to 0/1 for Clique + if mimeType == accounts.MimetypeClique && (res[64] == 27 || res[64] == 28) { + res[64] -= 27 // Transform V from 27/28 to 0/1 for Clique use + } + return res, nil +} + +func (api *ExternalSigner) SignText(account accounts.Account, text []byte) ([]byte, error) { + var res hexutil.Bytes + var signAddress = common.NewMixedcaseAddress(account.Address) + if err := api.client.Call(&res, "account_signData", + accounts.MimetypeTextPlain, + &signAddress, // Need to use the pointer here, because of how MarshalJSON is defined + hexutil.Encode(text)); err != nil { + return nil, err + } + return res, nil +} + +func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + res := ethapi.SignTransactionResult{} + to := common.NewMixedcaseAddress(*tx.To()) + data := hexutil.Bytes(tx.Data()) + args := &core.SendTxArgs{ + Data: &data, + Nonce: hexutil.Uint64(tx.Nonce()), + Value: hexutil.Big(*tx.Value()), + Gas: hexutil.Uint64(tx.Gas()), + GasPrice: hexutil.Big(*tx.GasPrice()), + To: &to, + From: common.NewMixedcaseAddress(account.Address), + } + + if err := api.client.Call(&res, "account_signTransaction", args); err != nil { + return nil, err + } + return res.Tx, nil +} + +func (api *ExternalSigner) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { + return []byte{}, fmt.Errorf("passphrase-operations not supported on external signers") +} + +func (api *ExternalSigner) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + return nil, fmt.Errorf("passphrase-operations not supported on external signers") +} +func (api *ExternalSigner) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { + return nil, fmt.Errorf("passphrase-operations not supported on external signers") +} + +func (api *ExternalSigner) listAccounts() ([]common.Address, error) { + var res []common.Address + if err := api.client.Call(&res, "account_list"); err != nil { + return nil, err + } + return res, nil +} + +func (api *ExternalSigner) pingVersion() (string, error) { + var v string + if err := api.client.Call(&v, "account_version"); err != nil { + return "", err + } + return v, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/keystore.go b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/keystore.go index 2918047ccd..434e035048 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/keystore.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/keystore.go @@ -137,8 +137,10 @@ func (ks *KeyStore) refreshWallets() { accs := ks.cache.accounts() // Transform the current list of wallets into the new one - wallets := make([]accounts.Wallet, 0, len(accs)) - events := []accounts.WalletEvent{} + var ( + wallets = make([]accounts.Wallet, 0, len(accs)) + events []accounts.WalletEvent + ) for _, account := range accs { // Drop wallets while they were in front of the next account diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/wallet.go b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/wallet.go index 758fdfe364..1b36b6dff5 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/wallet.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/wallet.go @@ -22,6 +22,7 @@ import ( ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" ) // keystoreWallet implements the accounts.Wallet interface for the original @@ -52,8 +53,8 @@ func (w *keystoreWallet) Status() (string, error) { // is no connection or decryption step necessary to access the list of accounts. func (w *keystoreWallet) Open(passphrase string) error { return nil } -// Close implements accounts.Wallet, but is a noop for plain wallets since is no -// meaningful open operation. +// Close implements accounts.Wallet, but is a noop for plain wallets since there +// is no meaningful open operation. func (w *keystoreWallet) Close() error { return nil } // Accounts implements accounts.Wallet, returning an account list consisting of @@ -78,60 +79,67 @@ func (w *keystoreWallet) Derive(path accounts.DerivationPath, pin bool) (account // there is no notion of hierarchical account derivation for plain keystore accounts. func (w *keystoreWallet) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) {} -// SignHash implements accounts.Wallet, attempting to sign the given hash with +// signHash attempts to sign the given hash with // the given account. If the wallet does not wrap this particular account, an // error is returned to avoid account leakage (even though in theory we may be // able to sign via our shared keystore backend). -func (w *keystoreWallet) SignHash(account accounts.Account, hash []byte) ([]byte, error) { +func (w *keystoreWallet) signHash(account accounts.Account, hash []byte) ([]byte, error) { // Make sure the requested account is contained within - if account.Address != w.account.Address { - return nil, accounts.ErrUnknownAccount - } - if account.URL != (accounts.URL{}) && account.URL != w.account.URL { + if !w.Contains(account) { return nil, accounts.ErrUnknownAccount } // Account seems valid, request the keystore to sign return w.keystore.SignHash(account, hash) } -// SignTx implements accounts.Wallet, attempting to sign the given transaction -// with the given account. If the wallet does not wrap this particular account, -// an error is returned to avoid account leakage (even though in theory we may -// be able to sign via our shared keystore backend). -func (w *keystoreWallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { +// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed +func (w *keystoreWallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { + return w.signHash(account, crypto.Keccak256(data)) +} + +// SignDataWithPassphrase signs keccak256(data). The mimetype parameter describes the type of data being signed +func (w *keystoreWallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { // Make sure the requested account is contained within - if account.Address != w.account.Address { - return nil, accounts.ErrUnknownAccount - } - if account.URL != (accounts.URL{}) && account.URL != w.account.URL { + if !w.Contains(account) { return nil, accounts.ErrUnknownAccount } // Account seems valid, request the keystore to sign - return w.keystore.SignTx(account, tx, chainID) + return w.keystore.SignHashWithPassphrase(account, passphrase, crypto.Keccak256(data)) +} + +func (w *keystoreWallet) SignText(account accounts.Account, text []byte) ([]byte, error) { + return w.signHash(account, accounts.TextHash(text)) } -// SignHashWithPassphrase implements accounts.Wallet, attempting to sign the +// SignTextWithPassphrase implements accounts.Wallet, attempting to sign the // given hash with the given account using passphrase as extra authentication. -func (w *keystoreWallet) SignHashWithPassphrase(account accounts.Account, passphrase string, hash []byte) ([]byte, error) { +func (w *keystoreWallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { // Make sure the requested account is contained within - if account.Address != w.account.Address { + if !w.Contains(account) { return nil, accounts.ErrUnknownAccount } - if account.URL != (accounts.URL{}) && account.URL != w.account.URL { + // Account seems valid, request the keystore to sign + return w.keystore.SignHashWithPassphrase(account, passphrase, accounts.TextHash(text)) +} + +// SignTx implements accounts.Wallet, attempting to sign the given transaction +// with the given account. If the wallet does not wrap this particular account, +// an error is returned to avoid account leakage (even though in theory we may +// be able to sign via our shared keystore backend). +func (w *keystoreWallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + // Make sure the requested account is contained within + if !w.Contains(account) { return nil, accounts.ErrUnknownAccount } // Account seems valid, request the keystore to sign - return w.keystore.SignHashWithPassphrase(account, passphrase, hash) + return w.keystore.SignTx(account, tx, chainID) } // SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given // transaction with the given account using passphrase as extra authentication. func (w *keystoreWallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { // Make sure the requested account is contained within - if account.Address != w.account.Address { - return nil, accounts.ErrUnknownAccount - } - if account.URL != (accounts.URL{}) && account.URL != w.account.URL { + if !w.Contains(account) { return nil, accounts.ErrUnknownAccount } // Account seems valid, request the keystore to sign diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/manager.go b/vendor/github.com/ethereum/go-ethereum/accounts/manager.go index 96ca298fc5..3cf3422e77 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/manager.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/manager.go @@ -24,9 +24,18 @@ import ( "github.com/ethereum/go-ethereum/event" ) +// Config contains the settings of the global account manager. +// +// TODO(rjl493456442, karalabe, holiman): Get rid of this when account management +// is removed in favor of Clef. +type Config struct { + InsecureUnlockAllowed bool // Whether account unlocking in insecure environment is allowed +} + // Manager is an overarching account manager that can communicate with various // backends for signing transactions. type Manager struct { + config *Config // Global account manager configurations backends map[reflect.Type][]Backend // Index of backends currently registered updaters []event.Subscription // Wallet update subscriptions for all backends updates chan WalletEvent // Subscription sink for backend wallet changes @@ -40,7 +49,7 @@ type Manager struct { // NewManager creates a generic account manager to sign transaction via various // supported backends. -func NewManager(backends ...Backend) *Manager { +func NewManager(config *Config, backends ...Backend) *Manager { // Retrieve the initial list of wallets from the backends and sort by URL var wallets []Wallet for _, backend := range backends { @@ -55,6 +64,7 @@ func NewManager(backends ...Backend) *Manager { } // Assemble the account manager and return am := &Manager{ + config: config, backends: make(map[reflect.Type][]Backend), updaters: subs, updates: updates, @@ -77,6 +87,11 @@ func (am *Manager) Close() error { return <-errc } +// Config returns the configuration of account manager. +func (am *Manager) Config() *Config { + return am.config +} + // update is the wallet event loop listening for notifications from the backends // and updating the cache of wallets. func (am *Manager) update() { diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/hub.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/hub.go new file mode 100644 index 0000000000..a91340b4fc --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/hub.go @@ -0,0 +1,240 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package usbwallet + +import ( + "errors" + "runtime" + "sync" + "time" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" + "github.com/karalabe/hid" +) + +// LedgerScheme is the protocol scheme prefixing account and wallet URLs. +const LedgerScheme = "ledger" + +// TrezorScheme is the protocol scheme prefixing account and wallet URLs. +const TrezorScheme = "trezor" + +// refreshCycle is the maximum time between wallet refreshes (if USB hotplug +// notifications don't work). +const refreshCycle = time.Second + +// refreshThrottling is the minimum time between wallet refreshes to avoid USB +// trashing. +const refreshThrottling = 500 * time.Millisecond + +// Hub is a accounts.Backend that can find and handle generic USB hardware wallets. +type Hub struct { + scheme string // Protocol scheme prefixing account and wallet URLs. + vendorID uint16 // USB vendor identifier used for device discovery + productIDs []uint16 // USB product identifiers used for device discovery + usageID uint16 // USB usage page identifier used for macOS device discovery + endpointID int // USB endpoint identifier used for non-macOS device discovery + makeDriver func(log.Logger) driver // Factory method to construct a vendor specific driver + + refreshed time.Time // Time instance when the list of wallets was last refreshed + wallets []accounts.Wallet // List of USB wallet devices currently tracking + updateFeed event.Feed // Event feed to notify wallet additions/removals + updateScope event.SubscriptionScope // Subscription scope tracking current live listeners + updating bool // Whether the event notification loop is running + + quit chan chan error + + stateLock sync.RWMutex // Protects the internals of the hub from racey access + + // TODO(karalabe): remove if hotplug lands on Windows + commsPend int // Number of operations blocking enumeration + commsLock sync.Mutex // Lock protecting the pending counter and enumeration +} + +// NewLedgerHub creates a new hardware wallet manager for Ledger devices. +func NewLedgerHub() (*Hub, error) { + return newHub(LedgerScheme, 0x2c97, []uint16{0x0000 /* Ledger Blue */, 0x0001 /* Ledger Nano S */}, 0xffa0, 0, newLedgerDriver) +} + +// NewTrezorHub creates a new hardware wallet manager for Trezor devices. +func NewTrezorHub() (*Hub, error) { + return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor 1 */}, 0xff00, 0, newTrezorDriver) +} + +// newHub creates a new hardware wallet manager for generic USB devices. +func newHub(scheme string, vendorID uint16, productIDs []uint16, usageID uint16, endpointID int, makeDriver func(log.Logger) driver) (*Hub, error) { + if !hid.Supported() { + return nil, errors.New("unsupported platform") + } + hub := &Hub{ + scheme: scheme, + vendorID: vendorID, + productIDs: productIDs, + usageID: usageID, + endpointID: endpointID, + makeDriver: makeDriver, + quit: make(chan chan error), + } + hub.refreshWallets() + return hub, nil +} + +// Wallets implements accounts.Backend, returning all the currently tracked USB +// devices that appear to be hardware wallets. +func (hub *Hub) Wallets() []accounts.Wallet { + // Make sure the list of wallets is up to date + hub.refreshWallets() + + hub.stateLock.RLock() + defer hub.stateLock.RUnlock() + + cpy := make([]accounts.Wallet, len(hub.wallets)) + copy(cpy, hub.wallets) + return cpy +} + +// refreshWallets scans the USB devices attached to the machine and updates the +// list of wallets based on the found devices. +func (hub *Hub) refreshWallets() { + // Don't scan the USB like crazy it the user fetches wallets in a loop + hub.stateLock.RLock() + elapsed := time.Since(hub.refreshed) + hub.stateLock.RUnlock() + + if elapsed < refreshThrottling { + return + } + // Retrieve the current list of USB wallet devices + var devices []hid.DeviceInfo + + if runtime.GOOS == "linux" { + // hidapi on Linux opens the device during enumeration to retrieve some infos, + // breaking the Ledger protocol if that is waiting for user confirmation. This + // is a bug acknowledged at Ledger, but it won't be fixed on old devices so we + // need to prevent concurrent comms ourselves. The more elegant solution would + // be to ditch enumeration in favor of hotplug events, but that don't work yet + // on Windows so if we need to hack it anyway, this is more elegant for now. + hub.commsLock.Lock() + if hub.commsPend > 0 { // A confirmation is pending, don't refresh + hub.commsLock.Unlock() + return + } + } + for _, info := range hid.Enumerate(hub.vendorID, 0) { + for _, id := range hub.productIDs { + if info.ProductID == id && (info.UsagePage == hub.usageID || info.Interface == hub.endpointID) { + devices = append(devices, info) + break + } + } + } + if runtime.GOOS == "linux" { + // See rationale before the enumeration why this is needed and only on Linux. + hub.commsLock.Unlock() + } + // Transform the current list of wallets into the new one + hub.stateLock.Lock() + + var ( + wallets = make([]accounts.Wallet, 0, len(devices)) + events []accounts.WalletEvent + ) + + for _, device := range devices { + url := accounts.URL{Scheme: hub.scheme, Path: device.Path} + + // Drop wallets in front of the next device or those that failed for some reason + for len(hub.wallets) > 0 { + // Abort if we're past the current device and found an operational one + _, failure := hub.wallets[0].Status() + if hub.wallets[0].URL().Cmp(url) >= 0 || failure == nil { + break + } + // Drop the stale and failed devices + events = append(events, accounts.WalletEvent{Wallet: hub.wallets[0], Kind: accounts.WalletDropped}) + hub.wallets = hub.wallets[1:] + } + // If there are no more wallets or the device is before the next, wrap new wallet + if len(hub.wallets) == 0 || hub.wallets[0].URL().Cmp(url) > 0 { + logger := log.New("url", url) + wallet := &wallet{hub: hub, driver: hub.makeDriver(logger), url: &url, info: device, log: logger} + + events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived}) + wallets = append(wallets, wallet) + continue + } + // If the device is the same as the first wallet, keep it + if hub.wallets[0].URL().Cmp(url) == 0 { + wallets = append(wallets, hub.wallets[0]) + hub.wallets = hub.wallets[1:] + continue + } + } + // Drop any leftover wallets and set the new batch + for _, wallet := range hub.wallets { + events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped}) + } + hub.refreshed = time.Now() + hub.wallets = wallets + hub.stateLock.Unlock() + + // Fire all wallet events and return + for _, event := range events { + hub.updateFeed.Send(event) + } +} + +// Subscribe implements accounts.Backend, creating an async subscription to +// receive notifications on the addition or removal of USB wallets. +func (hub *Hub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { + // We need the mutex to reliably start/stop the update loop + hub.stateLock.Lock() + defer hub.stateLock.Unlock() + + // Subscribe the caller and track the subscriber count + sub := hub.updateScope.Track(hub.updateFeed.Subscribe(sink)) + + // Subscribers require an active notification loop, start it + if !hub.updating { + hub.updating = true + go hub.updater() + } + return sub +} + +// updater is responsible for maintaining an up-to-date list of wallets managed +// by the USB hub, and for firing wallet addition/removal events. +func (hub *Hub) updater() { + for { + // TODO: Wait for a USB hotplug event (not supported yet) or a refresh timeout + // <-hub.changes + time.Sleep(refreshCycle) + + // Run the wallet refresher + hub.refreshWallets() + + // If all our subscribers left, stop the updater + hub.stateLock.Lock() + if hub.updateScope.Count() == 0 { + hub.updating = false + hub.stateLock.Unlock() + return + } + hub.stateLock.Unlock() + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go new file mode 100644 index 0000000000..c30903b5b7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go @@ -0,0 +1,464 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// This file contains the implementation for interacting with the Ledger hardware +// wallets. The wire protocol spec can be found in the Ledger Blue GitHub repo: +// https://raw.githubusercontent.com/LedgerHQ/blue-app-eth/master/doc/ethapp.asc + +package usbwallet + +import ( + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "io" + "math/big" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" +) + +// ledgerOpcode is an enumeration encoding the supported Ledger opcodes. +type ledgerOpcode byte + +// ledgerParam1 is an enumeration encoding the supported Ledger parameters for +// specific opcodes. The same parameter values may be reused between opcodes. +type ledgerParam1 byte + +// ledgerParam2 is an enumeration encoding the supported Ledger parameters for +// specific opcodes. The same parameter values may be reused between opcodes. +type ledgerParam2 byte + +const ( + ledgerOpRetrieveAddress ledgerOpcode = 0x02 // Returns the public key and Ethereum address for a given BIP 32 path + ledgerOpSignTransaction ledgerOpcode = 0x04 // Signs an Ethereum transaction after having the user validate the parameters + ledgerOpGetConfiguration ledgerOpcode = 0x06 // Returns specific wallet application configuration + + ledgerP1DirectlyFetchAddress ledgerParam1 = 0x00 // Return address directly from the wallet + ledgerP1InitTransactionData ledgerParam1 = 0x00 // First transaction data block for signing + ledgerP1ContTransactionData ledgerParam1 = 0x80 // Subsequent transaction data block for signing + ledgerP2DiscardAddressChainCode ledgerParam2 = 0x00 // Do not return the chain code along with the address +) + +// errLedgerReplyInvalidHeader is the error message returned by a Ledger data exchange +// if the device replies with a mismatching header. This usually means the device +// is in browser mode. +var errLedgerReplyInvalidHeader = errors.New("ledger: invalid reply header") + +// errLedgerInvalidVersionReply is the error message returned by a Ledger version retrieval +// when a response does arrive, but it does not contain the expected data. +var errLedgerInvalidVersionReply = errors.New("ledger: invalid version reply") + +// ledgerDriver implements the communication with a Ledger hardware wallet. +type ledgerDriver struct { + device io.ReadWriter // USB device connection to communicate through + version [3]byte // Current version of the Ledger firmware (zero if app is offline) + browser bool // Flag whether the Ledger is in browser mode (reply channel mismatch) + failure error // Any failure that would make the device unusable + log log.Logger // Contextual logger to tag the ledger with its id +} + +// newLedgerDriver creates a new instance of a Ledger USB protocol driver. +func newLedgerDriver(logger log.Logger) driver { + return &ledgerDriver{ + log: logger, + } +} + +// Status implements usbwallet.driver, returning various states the Ledger can +// currently be in. +func (w *ledgerDriver) Status() (string, error) { + if w.failure != nil { + return fmt.Sprintf("Failed: %v", w.failure), w.failure + } + if w.browser { + return "Ethereum app in browser mode", w.failure + } + if w.offline() { + return "Ethereum app offline", w.failure + } + return fmt.Sprintf("Ethereum app v%d.%d.%d online", w.version[0], w.version[1], w.version[2]), w.failure +} + +// offline returns whether the wallet and the Ethereum app is offline or not. +// +// The method assumes that the state lock is held! +func (w *ledgerDriver) offline() bool { + return w.version == [3]byte{0, 0, 0} +} + +// Open implements usbwallet.driver, attempting to initialize the connection to the +// Ledger hardware wallet. The Ledger does not require a user passphrase, so that +// parameter is silently discarded. +func (w *ledgerDriver) Open(device io.ReadWriter, passphrase string) error { + w.device, w.failure = device, nil + + _, err := w.ledgerDerive(accounts.DefaultBaseDerivationPath) + if err != nil { + // Ethereum app is not running or in browser mode, nothing more to do, return + if err == errLedgerReplyInvalidHeader { + w.browser = true + } + return nil + } + // Try to resolve the Ethereum app's version, will fail prior to v1.0.2 + if w.version, err = w.ledgerVersion(); err != nil { + w.version = [3]byte{1, 0, 0} // Assume worst case, can't verify if v1.0.0 or v1.0.1 + } + return nil +} + +// Close implements usbwallet.driver, cleaning up and metadata maintained within +// the Ledger driver. +func (w *ledgerDriver) Close() error { + w.browser, w.version = false, [3]byte{} + return nil +} + +// Heartbeat implements usbwallet.driver, performing a sanity check against the +// Ledger to see if it's still online. +func (w *ledgerDriver) Heartbeat() error { + if _, err := w.ledgerVersion(); err != nil && err != errLedgerInvalidVersionReply { + w.failure = err + return err + } + return nil +} + +// Derive implements usbwallet.driver, sending a derivation request to the Ledger +// and returning the Ethereum address located on that derivation path. +func (w *ledgerDriver) Derive(path accounts.DerivationPath) (common.Address, error) { + return w.ledgerDerive(path) +} + +// SignTx implements usbwallet.driver, sending the transaction to the Ledger and +// waiting for the user to confirm or deny the transaction. +// +// Note, if the version of the Ethereum application running on the Ledger wallet is +// too old to sign EIP-155 transactions, but such is requested nonetheless, an error +// will be returned opposed to silently signing in Homestead mode. +func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) { + // If the Ethereum app doesn't run, abort + if w.offline() { + return common.Address{}, nil, accounts.ErrWalletClosed + } + // Ensure the wallet is capable of signing the given transaction + if chainID != nil && w.version[0] <= 1 && w.version[1] <= 0 && w.version[2] <= 2 { + return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2]) + } + // All infos gathered and metadata checks out, request signing + return w.ledgerSign(path, tx, chainID) +} + +// ledgerVersion retrieves the current version of the Ethereum wallet app running +// on the Ledger wallet. +// +// The version retrieval protocol is defined as follows: +// +// CLA | INS | P1 | P2 | Lc | Le +// ----+-----+----+----+----+--- +// E0 | 06 | 00 | 00 | 00 | 04 +// +// With no input data, and the output data being: +// +// Description | Length +// ---------------------------------------------------+-------- +// Flags 01: arbitrary data signature enabled by user | 1 byte +// Application major version | 1 byte +// Application minor version | 1 byte +// Application patch version | 1 byte +func (w *ledgerDriver) ledgerVersion() ([3]byte, error) { + // Send the request and wait for the response + reply, err := w.ledgerExchange(ledgerOpGetConfiguration, 0, 0, nil) + if err != nil { + return [3]byte{}, err + } + if len(reply) != 4 { + return [3]byte{}, errLedgerInvalidVersionReply + } + // Cache the version for future reference + var version [3]byte + copy(version[:], reply[1:]) + return version, nil +} + +// ledgerDerive retrieves the currently active Ethereum address from a Ledger +// wallet at the specified derivation path. +// +// The address derivation protocol is defined as follows: +// +// CLA | INS | P1 | P2 | Lc | Le +// ----+-----+----+----+-----+--- +// E0 | 02 | 00 return address +// 01 display address and confirm before returning +// | 00: do not return the chain code +// | 01: return the chain code +// | var | 00 +// +// Where the input data is: +// +// Description | Length +// -------------------------------------------------+-------- +// Number of BIP 32 derivations to perform (max 10) | 1 byte +// First derivation index (big endian) | 4 bytes +// ... | 4 bytes +// Last derivation index (big endian) | 4 bytes +// +// And the output data is: +// +// Description | Length +// ------------------------+------------------- +// Public Key length | 1 byte +// Uncompressed Public Key | arbitrary +// Ethereum address length | 1 byte +// Ethereum address | 40 bytes hex ascii +// Chain code if requested | 32 bytes +func (w *ledgerDriver) ledgerDerive(derivationPath []uint32) (common.Address, error) { + // Flatten the derivation path into the Ledger request + path := make([]byte, 1+4*len(derivationPath)) + path[0] = byte(len(derivationPath)) + for i, component := range derivationPath { + binary.BigEndian.PutUint32(path[1+4*i:], component) + } + // Send the request and wait for the response + reply, err := w.ledgerExchange(ledgerOpRetrieveAddress, ledgerP1DirectlyFetchAddress, ledgerP2DiscardAddressChainCode, path) + if err != nil { + return common.Address{}, err + } + // Discard the public key, we don't need that for now + if len(reply) < 1 || len(reply) < 1+int(reply[0]) { + return common.Address{}, errors.New("reply lacks public key entry") + } + reply = reply[1+int(reply[0]):] + + // Extract the Ethereum hex address string + if len(reply) < 1 || len(reply) < 1+int(reply[0]) { + return common.Address{}, errors.New("reply lacks address entry") + } + hexstr := reply[1 : 1+int(reply[0])] + + // Decode the hex sting into an Ethereum address and return + var address common.Address + if _, err = hex.Decode(address[:], hexstr); err != nil { + return common.Address{}, err + } + return address, nil +} + +// ledgerSign sends the transaction to the Ledger wallet, and waits for the user +// to confirm or deny the transaction. +// +// The transaction signing protocol is defined as follows: +// +// CLA | INS | P1 | P2 | Lc | Le +// ----+-----+----+----+-----+--- +// E0 | 04 | 00: first transaction data block +// 80: subsequent transaction data block +// | 00 | variable | variable +// +// Where the input for the first transaction block (first 255 bytes) is: +// +// Description | Length +// -------------------------------------------------+---------- +// Number of BIP 32 derivations to perform (max 10) | 1 byte +// First derivation index (big endian) | 4 bytes +// ... | 4 bytes +// Last derivation index (big endian) | 4 bytes +// RLP transaction chunk | arbitrary +// +// And the input for subsequent transaction blocks (first 255 bytes) are: +// +// Description | Length +// ----------------------+---------- +// RLP transaction chunk | arbitrary +// +// And the output data is: +// +// Description | Length +// ------------+--------- +// signature V | 1 byte +// signature R | 32 bytes +// signature S | 32 bytes +func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) { + // Flatten the derivation path into the Ledger request + path := make([]byte, 1+4*len(derivationPath)) + path[0] = byte(len(derivationPath)) + for i, component := range derivationPath { + binary.BigEndian.PutUint32(path[1+4*i:], component) + } + // Create the transaction RLP based on whether legacy or EIP155 signing was requested + var ( + txrlp []byte + err error + ) + if chainID == nil { + if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data()}); err != nil { + return common.Address{}, nil, err + } + } else { + if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil { + return common.Address{}, nil, err + } + } + payload := append(path, txrlp...) + + // Send the request and wait for the response + var ( + op = ledgerP1InitTransactionData + reply []byte + ) + for len(payload) > 0 { + // Calculate the size of the next data chunk + chunk := 255 + if chunk > len(payload) { + chunk = len(payload) + } + // Send the chunk over, ensuring it's processed correctly + reply, err = w.ledgerExchange(ledgerOpSignTransaction, op, 0, payload[:chunk]) + if err != nil { + return common.Address{}, nil, err + } + // Shift the payload and ensure subsequent chunks are marked as such + payload = payload[chunk:] + op = ledgerP1ContTransactionData + } + // Extract the Ethereum signature and do a sanity validation + if len(reply) != 65 { + return common.Address{}, nil, errors.New("reply lacks signature") + } + signature := append(reply[1:], reply[0]) + + // Create the correct signer and signature transform based on the chain ID + var signer types.Signer + if chainID == nil { + signer = new(types.HomesteadSigner) + } else { + signer = types.NewEIP155Signer(chainID) + signature[64] -= byte(chainID.Uint64()*2 + 35) + } + signed, err := tx.WithSignature(signer, signature) + if err != nil { + return common.Address{}, nil, err + } + sender, err := types.Sender(signer, signed) + if err != nil { + return common.Address{}, nil, err + } + return sender, signed, nil +} + +// ledgerExchange performs a data exchange with the Ledger wallet, sending it a +// message and retrieving the response. +// +// The common transport header is defined as follows: +// +// Description | Length +// --------------------------------------+---------- +// Communication channel ID (big endian) | 2 bytes +// Command tag | 1 byte +// Packet sequence index (big endian) | 2 bytes +// Payload | arbitrary +// +// The Communication channel ID allows commands multiplexing over the same +// physical link. It is not used for the time being, and should be set to 0101 +// to avoid compatibility issues with implementations ignoring a leading 00 byte. +// +// The Command tag describes the message content. Use TAG_APDU (0x05) for standard +// APDU payloads, or TAG_PING (0x02) for a simple link test. +// +// The Packet sequence index describes the current sequence for fragmented payloads. +// The first fragment index is 0x00. +// +// APDU Command payloads are encoded as follows: +// +// Description | Length +// ----------------------------------- +// APDU length (big endian) | 2 bytes +// APDU CLA | 1 byte +// APDU INS | 1 byte +// APDU P1 | 1 byte +// APDU P2 | 1 byte +// APDU length | 1 byte +// Optional APDU data | arbitrary +func (w *ledgerDriver) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 ledgerParam2, data []byte) ([]byte, error) { + // Construct the message payload, possibly split into multiple chunks + apdu := make([]byte, 2, 7+len(data)) + + binary.BigEndian.PutUint16(apdu, uint16(5+len(data))) + apdu = append(apdu, []byte{0xe0, byte(opcode), byte(p1), byte(p2), byte(len(data))}...) + apdu = append(apdu, data...) + + // Stream all the chunks to the device + header := []byte{0x01, 0x01, 0x05, 0x00, 0x00} // Channel ID and command tag appended + chunk := make([]byte, 64) + space := len(chunk) - len(header) + + for i := 0; len(apdu) > 0; i++ { + // Construct the new message to stream + chunk = append(chunk[:0], header...) + binary.BigEndian.PutUint16(chunk[3:], uint16(i)) + + if len(apdu) > space { + chunk = append(chunk, apdu[:space]...) + apdu = apdu[space:] + } else { + chunk = append(chunk, apdu...) + apdu = nil + } + // Send over to the device + w.log.Trace("Data chunk sent to the Ledger", "chunk", hexutil.Bytes(chunk)) + if _, err := w.device.Write(chunk); err != nil { + return nil, err + } + } + // Stream the reply back from the wallet in 64 byte chunks + var reply []byte + chunk = chunk[:64] // Yeah, we surely have enough space + for { + // Read the next chunk from the Ledger wallet + if _, err := io.ReadFull(w.device, chunk); err != nil { + return nil, err + } + w.log.Trace("Data chunk received from the Ledger", "chunk", hexutil.Bytes(chunk)) + + // Make sure the transport header matches + if chunk[0] != 0x01 || chunk[1] != 0x01 || chunk[2] != 0x05 { + return nil, errLedgerReplyInvalidHeader + } + // If it's the first chunk, retrieve the total message length + var payload []byte + + if chunk[3] == 0x00 && chunk[4] == 0x00 { + reply = make([]byte, 0, int(binary.BigEndian.Uint16(chunk[5:7]))) + payload = chunk[7:] + } else { + payload = chunk[5:] + } + // Append to the reply and stop when filled up + if left := cap(reply) - len(reply); left > len(payload) { + reply = append(reply, payload...) + } else { + reply = append(reply, payload[:left]...) + break + } + } + return reply[:len(reply)-2], nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor.go new file mode 100644 index 0000000000..d3e17aba10 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor.go @@ -0,0 +1,356 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// This file contains the implementation for interacting with the Trezor hardware +// wallets. The wire protocol spec can be found on the SatoshiLabs website: +// https://doc.satoshilabs.com/trezor-tech/api-protobuf.html + +package usbwallet + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/golang/protobuf/proto" +) + +// ErrTrezorPINNeeded is returned if opening the trezor requires a PIN code. In +// this case, the calling application should display a pinpad and send back the +// encoded passphrase. +var ErrTrezorPINNeeded = errors.New("trezor: pin needed") + +// ErrTrezorPassphraseNeeded is returned if opening the trezor requires a passphrase +var ErrTrezorPassphraseNeeded = errors.New("trezor: passphrase needed") + +// errTrezorReplyInvalidHeader is the error message returned by a Trezor data exchange +// if the device replies with a mismatching header. This usually means the device +// is in browser mode. +var errTrezorReplyInvalidHeader = errors.New("trezor: invalid reply header") + +// trezorDriver implements the communication with a Trezor hardware wallet. +type trezorDriver struct { + device io.ReadWriter // USB device connection to communicate through + version [3]uint32 // Current version of the Trezor firmware + label string // Current textual label of the Trezor device + pinwait bool // Flags whether the device is waiting for PIN entry + passphrasewait bool // Flags whether the device is waiting for passphrase entry + failure error // Any failure that would make the device unusable + log log.Logger // Contextual logger to tag the trezor with its id +} + +// newTrezorDriver creates a new instance of a Trezor USB protocol driver. +func newTrezorDriver(logger log.Logger) driver { + return &trezorDriver{ + log: logger, + } +} + +// Status implements accounts.Wallet, always whether the Trezor is opened, closed +// or whether the Ethereum app was not started on it. +func (w *trezorDriver) Status() (string, error) { + if w.failure != nil { + return fmt.Sprintf("Failed: %v", w.failure), w.failure + } + if w.device == nil { + return "Closed", w.failure + } + if w.pinwait { + return fmt.Sprintf("Trezor v%d.%d.%d '%s' waiting for PIN", w.version[0], w.version[1], w.version[2], w.label), w.failure + } + return fmt.Sprintf("Trezor v%d.%d.%d '%s' online", w.version[0], w.version[1], w.version[2], w.label), w.failure +} + +// Open implements usbwallet.driver, attempting to initialize the connection to +// the Trezor hardware wallet. Initializing the Trezor is a two or three phase operation: +// * The first phase is to initialize the connection and read the wallet's +// features. This phase is invoked is the provided passphrase is empty. The +// device will display the pinpad as a result and will return an appropriate +// error to notify the user that a second open phase is needed. +// * The second phase is to unlock access to the Trezor, which is done by the +// user actually providing a passphrase mapping a keyboard keypad to the pin +// number of the user (shuffled according to the pinpad displayed). +// * If needed the device will ask for passphrase which will require calling +// open again with the actual passphrase (3rd phase) +func (w *trezorDriver) Open(device io.ReadWriter, passphrase string) error { + w.device, w.failure = device, nil + + // If phase 1 is requested, init the connection and wait for user callback + if passphrase == "" && !w.passphrasewait { + // If we're already waiting for a PIN entry, insta-return + if w.pinwait { + return ErrTrezorPINNeeded + } + // Initialize a connection to the device + features := new(trezor.Features) + if _, err := w.trezorExchange(&trezor.Initialize{}, features); err != nil { + return err + } + w.version = [3]uint32{features.GetMajorVersion(), features.GetMinorVersion(), features.GetPatchVersion()} + w.label = features.GetLabel() + + // Do a manual ping, forcing the device to ask for its PIN and Passphrase + askPin := true + askPassphrase := true + res, err := w.trezorExchange(&trezor.Ping{PinProtection: &askPin, PassphraseProtection: &askPassphrase}, new(trezor.PinMatrixRequest), new(trezor.PassphraseRequest), new(trezor.Success)) + if err != nil { + return err + } + // Only return the PIN request if the device wasn't unlocked until now + switch res { + case 0: + w.pinwait = true + return ErrTrezorPINNeeded + case 1: + w.pinwait = false + w.passphrasewait = true + return ErrTrezorPassphraseNeeded + case 2: + return nil // responded with trezor.Success + } + } + // Phase 2 requested with actual PIN entry + if w.pinwait { + w.pinwait = false + res, err := w.trezorExchange(&trezor.PinMatrixAck{Pin: &passphrase}, new(trezor.Success), new(trezor.PassphraseRequest)) + if err != nil { + w.failure = err + return err + } + if res == 1 { + w.passphrasewait = true + return ErrTrezorPassphraseNeeded + } + } else if w.passphrasewait { + w.passphrasewait = false + if _, err := w.trezorExchange(&trezor.PassphraseAck{Passphrase: &passphrase}, new(trezor.Success)); err != nil { + w.failure = err + return err + } + } + + return nil +} + +// Close implements usbwallet.driver, cleaning up and metadata maintained within +// the Trezor driver. +func (w *trezorDriver) Close() error { + w.version, w.label, w.pinwait = [3]uint32{}, "", false + return nil +} + +// Heartbeat implements usbwallet.driver, performing a sanity check against the +// Trezor to see if it's still online. +func (w *trezorDriver) Heartbeat() error { + if _, err := w.trezorExchange(&trezor.Ping{}, new(trezor.Success)); err != nil { + w.failure = err + return err + } + return nil +} + +// Derive implements usbwallet.driver, sending a derivation request to the Trezor +// and returning the Ethereum address located on that derivation path. +func (w *trezorDriver) Derive(path accounts.DerivationPath) (common.Address, error) { + return w.trezorDerive(path) +} + +// SignTx implements usbwallet.driver, sending the transaction to the Trezor and +// waiting for the user to confirm or deny the transaction. +func (w *trezorDriver) SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) { + if w.device == nil { + return common.Address{}, nil, accounts.ErrWalletClosed + } + return w.trezorSign(path, tx, chainID) +} + +// trezorDerive sends a derivation request to the Trezor device and returns the +// Ethereum address located on that path. +func (w *trezorDriver) trezorDerive(derivationPath []uint32) (common.Address, error) { + address := new(trezor.EthereumAddress) + if _, err := w.trezorExchange(&trezor.EthereumGetAddress{AddressN: derivationPath}, address); err != nil { + return common.Address{}, err + } + return common.BytesToAddress(address.GetAddress()), nil +} + +// trezorSign sends the transaction to the Trezor wallet, and waits for the user +// to confirm or deny the transaction. +func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) { + // Create the transaction initiation message + data := tx.Data() + length := uint32(len(data)) + + request := &trezor.EthereumSignTx{ + AddressN: derivationPath, + Nonce: new(big.Int).SetUint64(tx.Nonce()).Bytes(), + GasPrice: tx.GasPrice().Bytes(), + GasLimit: new(big.Int).SetUint64(tx.Gas()).Bytes(), + Value: tx.Value().Bytes(), + DataLength: &length, + } + if to := tx.To(); to != nil { + request.To = (*to)[:] // Non contract deploy, set recipient explicitly + } + if length > 1024 { // Send the data chunked if that was requested + request.DataInitialChunk, data = data[:1024], data[1024:] + } else { + request.DataInitialChunk, data = data, nil + } + if chainID != nil { // EIP-155 transaction, set chain ID explicitly (only 32 bit is supported!?) + id := uint32(chainID.Int64()) + request.ChainId = &id + } + // Send the initiation message and stream content until a signature is returned + response := new(trezor.EthereumTxRequest) + if _, err := w.trezorExchange(request, response); err != nil { + return common.Address{}, nil, err + } + for response.DataLength != nil && int(*response.DataLength) <= len(data) { + chunk := data[:*response.DataLength] + data = data[*response.DataLength:] + + if _, err := w.trezorExchange(&trezor.EthereumTxAck{DataChunk: chunk}, response); err != nil { + return common.Address{}, nil, err + } + } + // Extract the Ethereum signature and do a sanity validation + if len(response.GetSignatureR()) == 0 || len(response.GetSignatureS()) == 0 || response.GetSignatureV() == 0 { + return common.Address{}, nil, errors.New("reply lacks signature") + } + signature := append(append(response.GetSignatureR(), response.GetSignatureS()...), byte(response.GetSignatureV())) + + // Create the correct signer and signature transform based on the chain ID + var signer types.Signer + if chainID == nil { + signer = new(types.HomesteadSigner) + } else { + signer = types.NewEIP155Signer(chainID) + signature[64] -= byte(chainID.Uint64()*2 + 35) + } + // Inject the final signature into the transaction and sanity check the sender + signed, err := tx.WithSignature(signer, signature) + if err != nil { + return common.Address{}, nil, err + } + sender, err := types.Sender(signer, signed) + if err != nil { + return common.Address{}, nil, err + } + return sender, signed, nil +} + +// trezorExchange performs a data exchange with the Trezor wallet, sending it a +// message and retrieving the response. If multiple responses are possible, the +// method will also return the index of the destination object used. +func (w *trezorDriver) trezorExchange(req proto.Message, results ...proto.Message) (int, error) { + // Construct the original message payload to chunk up + data, err := proto.Marshal(req) + if err != nil { + return 0, err + } + payload := make([]byte, 8+len(data)) + copy(payload, []byte{0x23, 0x23}) + binary.BigEndian.PutUint16(payload[2:], trezor.Type(req)) + binary.BigEndian.PutUint32(payload[4:], uint32(len(data))) + copy(payload[8:], data) + + // Stream all the chunks to the device + chunk := make([]byte, 64) + chunk[0] = 0x3f // Report ID magic number + + for len(payload) > 0 { + // Construct the new message to stream, padding with zeroes if needed + if len(payload) > 63 { + copy(chunk[1:], payload[:63]) + payload = payload[63:] + } else { + copy(chunk[1:], payload) + copy(chunk[1+len(payload):], make([]byte, 63-len(payload))) + payload = nil + } + // Send over to the device + w.log.Trace("Data chunk sent to the Trezor", "chunk", hexutil.Bytes(chunk)) + if _, err := w.device.Write(chunk); err != nil { + return 0, err + } + } + // Stream the reply back from the wallet in 64 byte chunks + var ( + kind uint16 + reply []byte + ) + for { + // Read the next chunk from the Trezor wallet + if _, err := io.ReadFull(w.device, chunk); err != nil { + return 0, err + } + w.log.Trace("Data chunk received from the Trezor", "chunk", hexutil.Bytes(chunk)) + + // Make sure the transport header matches + if chunk[0] != 0x3f || (len(reply) == 0 && (chunk[1] != 0x23 || chunk[2] != 0x23)) { + return 0, errTrezorReplyInvalidHeader + } + // If it's the first chunk, retrieve the reply message type and total message length + var payload []byte + + if len(reply) == 0 { + kind = binary.BigEndian.Uint16(chunk[3:5]) + reply = make([]byte, 0, int(binary.BigEndian.Uint32(chunk[5:9]))) + payload = chunk[9:] + } else { + payload = chunk[1:] + } + // Append to the reply and stop when filled up + if left := cap(reply) - len(reply); left > len(payload) { + reply = append(reply, payload...) + } else { + reply = append(reply, payload[:left]...) + break + } + } + // Try to parse the reply into the requested reply message + if kind == uint16(trezor.MessageType_MessageType_Failure) { + // Trezor returned a failure, extract and return the message + failure := new(trezor.Failure) + if err := proto.Unmarshal(reply, failure); err != nil { + return 0, err + } + return 0, errors.New("trezor: " + failure.GetMessage()) + } + if kind == uint16(trezor.MessageType_MessageType_ButtonRequest) { + // Trezor is waiting for user confirmation, ack and wait for the next message + return w.trezorExchange(&trezor.ButtonAck{}, results...) + } + for i, res := range results { + if trezor.Type(res) == kind { + return i, proto.Unmarshal(reply, res) + } + } + expected := make([]string, len(results)) + for i, res := range results { + expected[i] = trezor.Name(trezor.Type(res)) + } + return 0, fmt.Errorf("trezor: expected reply types %s, got %s", expected, trezor.Name(kind)) +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.pb.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.pb.go new file mode 100644 index 0000000000..15bb6fb73b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.pb.go @@ -0,0 +1,3081 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: messages.proto + +package trezor + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// * +// Mapping between Trezor wire identifier (uint) and a protobuf message +type MessageType int32 + +const ( + MessageType_MessageType_Initialize MessageType = 0 + MessageType_MessageType_Ping MessageType = 1 + MessageType_MessageType_Success MessageType = 2 + MessageType_MessageType_Failure MessageType = 3 + MessageType_MessageType_ChangePin MessageType = 4 + MessageType_MessageType_WipeDevice MessageType = 5 + MessageType_MessageType_FirmwareErase MessageType = 6 + MessageType_MessageType_FirmwareUpload MessageType = 7 + MessageType_MessageType_FirmwareRequest MessageType = 8 + MessageType_MessageType_GetEntropy MessageType = 9 + MessageType_MessageType_Entropy MessageType = 10 + MessageType_MessageType_GetPublicKey MessageType = 11 + MessageType_MessageType_PublicKey MessageType = 12 + MessageType_MessageType_LoadDevice MessageType = 13 + MessageType_MessageType_ResetDevice MessageType = 14 + MessageType_MessageType_SignTx MessageType = 15 + MessageType_MessageType_SimpleSignTx MessageType = 16 + MessageType_MessageType_Features MessageType = 17 + MessageType_MessageType_PinMatrixRequest MessageType = 18 + MessageType_MessageType_PinMatrixAck MessageType = 19 + MessageType_MessageType_Cancel MessageType = 20 + MessageType_MessageType_TxRequest MessageType = 21 + MessageType_MessageType_TxAck MessageType = 22 + MessageType_MessageType_CipherKeyValue MessageType = 23 + MessageType_MessageType_ClearSession MessageType = 24 + MessageType_MessageType_ApplySettings MessageType = 25 + MessageType_MessageType_ButtonRequest MessageType = 26 + MessageType_MessageType_ButtonAck MessageType = 27 + MessageType_MessageType_ApplyFlags MessageType = 28 + MessageType_MessageType_GetAddress MessageType = 29 + MessageType_MessageType_Address MessageType = 30 + MessageType_MessageType_SelfTest MessageType = 32 + MessageType_MessageType_BackupDevice MessageType = 34 + MessageType_MessageType_EntropyRequest MessageType = 35 + MessageType_MessageType_EntropyAck MessageType = 36 + MessageType_MessageType_SignMessage MessageType = 38 + MessageType_MessageType_VerifyMessage MessageType = 39 + MessageType_MessageType_MessageSignature MessageType = 40 + MessageType_MessageType_PassphraseRequest MessageType = 41 + MessageType_MessageType_PassphraseAck MessageType = 42 + MessageType_MessageType_EstimateTxSize MessageType = 43 + MessageType_MessageType_TxSize MessageType = 44 + MessageType_MessageType_RecoveryDevice MessageType = 45 + MessageType_MessageType_WordRequest MessageType = 46 + MessageType_MessageType_WordAck MessageType = 47 + MessageType_MessageType_CipheredKeyValue MessageType = 48 + MessageType_MessageType_EncryptMessage MessageType = 49 + MessageType_MessageType_EncryptedMessage MessageType = 50 + MessageType_MessageType_DecryptMessage MessageType = 51 + MessageType_MessageType_DecryptedMessage MessageType = 52 + MessageType_MessageType_SignIdentity MessageType = 53 + MessageType_MessageType_SignedIdentity MessageType = 54 + MessageType_MessageType_GetFeatures MessageType = 55 + MessageType_MessageType_EthereumGetAddress MessageType = 56 + MessageType_MessageType_EthereumAddress MessageType = 57 + MessageType_MessageType_EthereumSignTx MessageType = 58 + MessageType_MessageType_EthereumTxRequest MessageType = 59 + MessageType_MessageType_EthereumTxAck MessageType = 60 + MessageType_MessageType_GetECDHSessionKey MessageType = 61 + MessageType_MessageType_ECDHSessionKey MessageType = 62 + MessageType_MessageType_SetU2FCounter MessageType = 63 + MessageType_MessageType_EthereumSignMessage MessageType = 64 + MessageType_MessageType_EthereumVerifyMessage MessageType = 65 + MessageType_MessageType_EthereumMessageSignature MessageType = 66 + MessageType_MessageType_DebugLinkDecision MessageType = 100 + MessageType_MessageType_DebugLinkGetState MessageType = 101 + MessageType_MessageType_DebugLinkState MessageType = 102 + MessageType_MessageType_DebugLinkStop MessageType = 103 + MessageType_MessageType_DebugLinkLog MessageType = 104 + MessageType_MessageType_DebugLinkMemoryRead MessageType = 110 + MessageType_MessageType_DebugLinkMemory MessageType = 111 + MessageType_MessageType_DebugLinkMemoryWrite MessageType = 112 + MessageType_MessageType_DebugLinkFlashErase MessageType = 113 +) + +var MessageType_name = map[int32]string{ + 0: "MessageType_Initialize", + 1: "MessageType_Ping", + 2: "MessageType_Success", + 3: "MessageType_Failure", + 4: "MessageType_ChangePin", + 5: "MessageType_WipeDevice", + 6: "MessageType_FirmwareErase", + 7: "MessageType_FirmwareUpload", + 8: "MessageType_FirmwareRequest", + 9: "MessageType_GetEntropy", + 10: "MessageType_Entropy", + 11: "MessageType_GetPublicKey", + 12: "MessageType_PublicKey", + 13: "MessageType_LoadDevice", + 14: "MessageType_ResetDevice", + 15: "MessageType_SignTx", + 16: "MessageType_SimpleSignTx", + 17: "MessageType_Features", + 18: "MessageType_PinMatrixRequest", + 19: "MessageType_PinMatrixAck", + 20: "MessageType_Cancel", + 21: "MessageType_TxRequest", + 22: "MessageType_TxAck", + 23: "MessageType_CipherKeyValue", + 24: "MessageType_ClearSession", + 25: "MessageType_ApplySettings", + 26: "MessageType_ButtonRequest", + 27: "MessageType_ButtonAck", + 28: "MessageType_ApplyFlags", + 29: "MessageType_GetAddress", + 30: "MessageType_Address", + 32: "MessageType_SelfTest", + 34: "MessageType_BackupDevice", + 35: "MessageType_EntropyRequest", + 36: "MessageType_EntropyAck", + 38: "MessageType_SignMessage", + 39: "MessageType_VerifyMessage", + 40: "MessageType_MessageSignature", + 41: "MessageType_PassphraseRequest", + 42: "MessageType_PassphraseAck", + 43: "MessageType_EstimateTxSize", + 44: "MessageType_TxSize", + 45: "MessageType_RecoveryDevice", + 46: "MessageType_WordRequest", + 47: "MessageType_WordAck", + 48: "MessageType_CipheredKeyValue", + 49: "MessageType_EncryptMessage", + 50: "MessageType_EncryptedMessage", + 51: "MessageType_DecryptMessage", + 52: "MessageType_DecryptedMessage", + 53: "MessageType_SignIdentity", + 54: "MessageType_SignedIdentity", + 55: "MessageType_GetFeatures", + 56: "MessageType_EthereumGetAddress", + 57: "MessageType_EthereumAddress", + 58: "MessageType_EthereumSignTx", + 59: "MessageType_EthereumTxRequest", + 60: "MessageType_EthereumTxAck", + 61: "MessageType_GetECDHSessionKey", + 62: "MessageType_ECDHSessionKey", + 63: "MessageType_SetU2FCounter", + 64: "MessageType_EthereumSignMessage", + 65: "MessageType_EthereumVerifyMessage", + 66: "MessageType_EthereumMessageSignature", + 100: "MessageType_DebugLinkDecision", + 101: "MessageType_DebugLinkGetState", + 102: "MessageType_DebugLinkState", + 103: "MessageType_DebugLinkStop", + 104: "MessageType_DebugLinkLog", + 110: "MessageType_DebugLinkMemoryRead", + 111: "MessageType_DebugLinkMemory", + 112: "MessageType_DebugLinkMemoryWrite", + 113: "MessageType_DebugLinkFlashErase", +} +var MessageType_value = map[string]int32{ + "MessageType_Initialize": 0, + "MessageType_Ping": 1, + "MessageType_Success": 2, + "MessageType_Failure": 3, + "MessageType_ChangePin": 4, + "MessageType_WipeDevice": 5, + "MessageType_FirmwareErase": 6, + "MessageType_FirmwareUpload": 7, + "MessageType_FirmwareRequest": 8, + "MessageType_GetEntropy": 9, + "MessageType_Entropy": 10, + "MessageType_GetPublicKey": 11, + "MessageType_PublicKey": 12, + "MessageType_LoadDevice": 13, + "MessageType_ResetDevice": 14, + "MessageType_SignTx": 15, + "MessageType_SimpleSignTx": 16, + "MessageType_Features": 17, + "MessageType_PinMatrixRequest": 18, + "MessageType_PinMatrixAck": 19, + "MessageType_Cancel": 20, + "MessageType_TxRequest": 21, + "MessageType_TxAck": 22, + "MessageType_CipherKeyValue": 23, + "MessageType_ClearSession": 24, + "MessageType_ApplySettings": 25, + "MessageType_ButtonRequest": 26, + "MessageType_ButtonAck": 27, + "MessageType_ApplyFlags": 28, + "MessageType_GetAddress": 29, + "MessageType_Address": 30, + "MessageType_SelfTest": 32, + "MessageType_BackupDevice": 34, + "MessageType_EntropyRequest": 35, + "MessageType_EntropyAck": 36, + "MessageType_SignMessage": 38, + "MessageType_VerifyMessage": 39, + "MessageType_MessageSignature": 40, + "MessageType_PassphraseRequest": 41, + "MessageType_PassphraseAck": 42, + "MessageType_EstimateTxSize": 43, + "MessageType_TxSize": 44, + "MessageType_RecoveryDevice": 45, + "MessageType_WordRequest": 46, + "MessageType_WordAck": 47, + "MessageType_CipheredKeyValue": 48, + "MessageType_EncryptMessage": 49, + "MessageType_EncryptedMessage": 50, + "MessageType_DecryptMessage": 51, + "MessageType_DecryptedMessage": 52, + "MessageType_SignIdentity": 53, + "MessageType_SignedIdentity": 54, + "MessageType_GetFeatures": 55, + "MessageType_EthereumGetAddress": 56, + "MessageType_EthereumAddress": 57, + "MessageType_EthereumSignTx": 58, + "MessageType_EthereumTxRequest": 59, + "MessageType_EthereumTxAck": 60, + "MessageType_GetECDHSessionKey": 61, + "MessageType_ECDHSessionKey": 62, + "MessageType_SetU2FCounter": 63, + "MessageType_EthereumSignMessage": 64, + "MessageType_EthereumVerifyMessage": 65, + "MessageType_EthereumMessageSignature": 66, + "MessageType_DebugLinkDecision": 100, + "MessageType_DebugLinkGetState": 101, + "MessageType_DebugLinkState": 102, + "MessageType_DebugLinkStop": 103, + "MessageType_DebugLinkLog": 104, + "MessageType_DebugLinkMemoryRead": 110, + "MessageType_DebugLinkMemory": 111, + "MessageType_DebugLinkMemoryWrite": 112, + "MessageType_DebugLinkFlashErase": 113, +} + +func (x MessageType) Enum() *MessageType { + p := new(MessageType) + *p = x + return p +} +func (x MessageType) String() string { + return proto.EnumName(MessageType_name, int32(x)) +} +func (x *MessageType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MessageType_value, data, "MessageType") + if err != nil { + return err + } + *x = MessageType(value) + return nil +} +func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +// * +// Request: Reset device to default state and ask for device details +// @next Features +type Initialize struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Initialize) Reset() { *m = Initialize{} } +func (m *Initialize) String() string { return proto.CompactTextString(m) } +func (*Initialize) ProtoMessage() {} +func (*Initialize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +// * +// Request: Ask for device details (no device reset) +// @next Features +type GetFeatures struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetFeatures) Reset() { *m = GetFeatures{} } +func (m *GetFeatures) String() string { return proto.CompactTextString(m) } +func (*GetFeatures) ProtoMessage() {} +func (*GetFeatures) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } + +// * +// Response: Reports various information about the device +// @prev Initialize +// @prev GetFeatures +type Features struct { + Vendor *string `protobuf:"bytes,1,opt,name=vendor" json:"vendor,omitempty"` + MajorVersion *uint32 `protobuf:"varint,2,opt,name=major_version,json=majorVersion" json:"major_version,omitempty"` + MinorVersion *uint32 `protobuf:"varint,3,opt,name=minor_version,json=minorVersion" json:"minor_version,omitempty"` + PatchVersion *uint32 `protobuf:"varint,4,opt,name=patch_version,json=patchVersion" json:"patch_version,omitempty"` + BootloaderMode *bool `protobuf:"varint,5,opt,name=bootloader_mode,json=bootloaderMode" json:"bootloader_mode,omitempty"` + DeviceId *string `protobuf:"bytes,6,opt,name=device_id,json=deviceId" json:"device_id,omitempty"` + PinProtection *bool `protobuf:"varint,7,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` + PassphraseProtection *bool `protobuf:"varint,8,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + Language *string `protobuf:"bytes,9,opt,name=language" json:"language,omitempty"` + Label *string `protobuf:"bytes,10,opt,name=label" json:"label,omitempty"` + Coins []*CoinType `protobuf:"bytes,11,rep,name=coins" json:"coins,omitempty"` + Initialized *bool `protobuf:"varint,12,opt,name=initialized" json:"initialized,omitempty"` + Revision []byte `protobuf:"bytes,13,opt,name=revision" json:"revision,omitempty"` + BootloaderHash []byte `protobuf:"bytes,14,opt,name=bootloader_hash,json=bootloaderHash" json:"bootloader_hash,omitempty"` + Imported *bool `protobuf:"varint,15,opt,name=imported" json:"imported,omitempty"` + PinCached *bool `protobuf:"varint,16,opt,name=pin_cached,json=pinCached" json:"pin_cached,omitempty"` + PassphraseCached *bool `protobuf:"varint,17,opt,name=passphrase_cached,json=passphraseCached" json:"passphrase_cached,omitempty"` + FirmwarePresent *bool `protobuf:"varint,18,opt,name=firmware_present,json=firmwarePresent" json:"firmware_present,omitempty"` + NeedsBackup *bool `protobuf:"varint,19,opt,name=needs_backup,json=needsBackup" json:"needs_backup,omitempty"` + Flags *uint32 `protobuf:"varint,20,opt,name=flags" json:"flags,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Features) Reset() { *m = Features{} } +func (m *Features) String() string { return proto.CompactTextString(m) } +func (*Features) ProtoMessage() {} +func (*Features) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } + +func (m *Features) GetVendor() string { + if m != nil && m.Vendor != nil { + return *m.Vendor + } + return "" +} + +func (m *Features) GetMajorVersion() uint32 { + if m != nil && m.MajorVersion != nil { + return *m.MajorVersion + } + return 0 +} + +func (m *Features) GetMinorVersion() uint32 { + if m != nil && m.MinorVersion != nil { + return *m.MinorVersion + } + return 0 +} + +func (m *Features) GetPatchVersion() uint32 { + if m != nil && m.PatchVersion != nil { + return *m.PatchVersion + } + return 0 +} + +func (m *Features) GetBootloaderMode() bool { + if m != nil && m.BootloaderMode != nil { + return *m.BootloaderMode + } + return false +} + +func (m *Features) GetDeviceId() string { + if m != nil && m.DeviceId != nil { + return *m.DeviceId + } + return "" +} + +func (m *Features) GetPinProtection() bool { + if m != nil && m.PinProtection != nil { + return *m.PinProtection + } + return false +} + +func (m *Features) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +func (m *Features) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return "" +} + +func (m *Features) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *Features) GetCoins() []*CoinType { + if m != nil { + return m.Coins + } + return nil +} + +func (m *Features) GetInitialized() bool { + if m != nil && m.Initialized != nil { + return *m.Initialized + } + return false +} + +func (m *Features) GetRevision() []byte { + if m != nil { + return m.Revision + } + return nil +} + +func (m *Features) GetBootloaderHash() []byte { + if m != nil { + return m.BootloaderHash + } + return nil +} + +func (m *Features) GetImported() bool { + if m != nil && m.Imported != nil { + return *m.Imported + } + return false +} + +func (m *Features) GetPinCached() bool { + if m != nil && m.PinCached != nil { + return *m.PinCached + } + return false +} + +func (m *Features) GetPassphraseCached() bool { + if m != nil && m.PassphraseCached != nil { + return *m.PassphraseCached + } + return false +} + +func (m *Features) GetFirmwarePresent() bool { + if m != nil && m.FirmwarePresent != nil { + return *m.FirmwarePresent + } + return false +} + +func (m *Features) GetNeedsBackup() bool { + if m != nil && m.NeedsBackup != nil { + return *m.NeedsBackup + } + return false +} + +func (m *Features) GetFlags() uint32 { + if m != nil && m.Flags != nil { + return *m.Flags + } + return 0 +} + +// * +// Request: clear session (removes cached PIN, passphrase, etc). +// @next Success +type ClearSession struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ClearSession) Reset() { *m = ClearSession{} } +func (m *ClearSession) String() string { return proto.CompactTextString(m) } +func (*ClearSession) ProtoMessage() {} +func (*ClearSession) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } + +// * +// Request: change language and/or label of the device +// @next Success +// @next Failure +// @next ButtonRequest +// @next PinMatrixRequest +type ApplySettings struct { + Language *string `protobuf:"bytes,1,opt,name=language" json:"language,omitempty"` + Label *string `protobuf:"bytes,2,opt,name=label" json:"label,omitempty"` + UsePassphrase *bool `protobuf:"varint,3,opt,name=use_passphrase,json=usePassphrase" json:"use_passphrase,omitempty"` + Homescreen []byte `protobuf:"bytes,4,opt,name=homescreen" json:"homescreen,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ApplySettings) Reset() { *m = ApplySettings{} } +func (m *ApplySettings) String() string { return proto.CompactTextString(m) } +func (*ApplySettings) ProtoMessage() {} +func (*ApplySettings) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } + +func (m *ApplySettings) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return "" +} + +func (m *ApplySettings) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *ApplySettings) GetUsePassphrase() bool { + if m != nil && m.UsePassphrase != nil { + return *m.UsePassphrase + } + return false +} + +func (m *ApplySettings) GetHomescreen() []byte { + if m != nil { + return m.Homescreen + } + return nil +} + +// * +// Request: set flags of the device +// @next Success +// @next Failure +type ApplyFlags struct { + Flags *uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ApplyFlags) Reset() { *m = ApplyFlags{} } +func (m *ApplyFlags) String() string { return proto.CompactTextString(m) } +func (*ApplyFlags) ProtoMessage() {} +func (*ApplyFlags) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } + +func (m *ApplyFlags) GetFlags() uint32 { + if m != nil && m.Flags != nil { + return *m.Flags + } + return 0 +} + +// * +// Request: Starts workflow for setting/changing/removing the PIN +// @next ButtonRequest +// @next PinMatrixRequest +type ChangePin struct { + Remove *bool `protobuf:"varint,1,opt,name=remove" json:"remove,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ChangePin) Reset() { *m = ChangePin{} } +func (m *ChangePin) String() string { return proto.CompactTextString(m) } +func (*ChangePin) ProtoMessage() {} +func (*ChangePin) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } + +func (m *ChangePin) GetRemove() bool { + if m != nil && m.Remove != nil { + return *m.Remove + } + return false +} + +// * +// Request: Test if the device is alive, device sends back the message in Success response +// @next Success +type Ping struct { + Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` + ButtonProtection *bool `protobuf:"varint,2,opt,name=button_protection,json=buttonProtection" json:"button_protection,omitempty"` + PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` + PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Ping) Reset() { *m = Ping{} } +func (m *Ping) String() string { return proto.CompactTextString(m) } +func (*Ping) ProtoMessage() {} +func (*Ping) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } + +func (m *Ping) GetMessage() string { + if m != nil && m.Message != nil { + return *m.Message + } + return "" +} + +func (m *Ping) GetButtonProtection() bool { + if m != nil && m.ButtonProtection != nil { + return *m.ButtonProtection + } + return false +} + +func (m *Ping) GetPinProtection() bool { + if m != nil && m.PinProtection != nil { + return *m.PinProtection + } + return false +} + +func (m *Ping) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +// * +// Response: Success of the previous request +type Success struct { + Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Success) Reset() { *m = Success{} } +func (m *Success) String() string { return proto.CompactTextString(m) } +func (*Success) ProtoMessage() {} +func (*Success) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} } + +func (m *Success) GetMessage() string { + if m != nil && m.Message != nil { + return *m.Message + } + return "" +} + +// * +// Response: Failure of the previous request +type Failure struct { + Code *FailureType `protobuf:"varint,1,opt,name=code,enum=FailureType" json:"code,omitempty"` + Message *string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Failure) Reset() { *m = Failure{} } +func (m *Failure) String() string { return proto.CompactTextString(m) } +func (*Failure) ProtoMessage() {} +func (*Failure) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} } + +func (m *Failure) GetCode() FailureType { + if m != nil && m.Code != nil { + return *m.Code + } + return FailureType_Failure_UnexpectedMessage +} + +func (m *Failure) GetMessage() string { + if m != nil && m.Message != nil { + return *m.Message + } + return "" +} + +// * +// Response: Device is waiting for HW button press. +// @next ButtonAck +// @next Cancel +type ButtonRequest struct { + Code *ButtonRequestType `protobuf:"varint,1,opt,name=code,enum=ButtonRequestType" json:"code,omitempty"` + Data *string `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ButtonRequest) Reset() { *m = ButtonRequest{} } +func (m *ButtonRequest) String() string { return proto.CompactTextString(m) } +func (*ButtonRequest) ProtoMessage() {} +func (*ButtonRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} } + +func (m *ButtonRequest) GetCode() ButtonRequestType { + if m != nil && m.Code != nil { + return *m.Code + } + return ButtonRequestType_ButtonRequest_Other +} + +func (m *ButtonRequest) GetData() string { + if m != nil && m.Data != nil { + return *m.Data + } + return "" +} + +// * +// Request: Computer agrees to wait for HW button press +// @prev ButtonRequest +type ButtonAck struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ButtonAck) Reset() { *m = ButtonAck{} } +func (m *ButtonAck) String() string { return proto.CompactTextString(m) } +func (*ButtonAck) ProtoMessage() {} +func (*ButtonAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} } + +// * +// Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme +// @next PinMatrixAck +// @next Cancel +type PinMatrixRequest struct { + Type *PinMatrixRequestType `protobuf:"varint,1,opt,name=type,enum=PinMatrixRequestType" json:"type,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PinMatrixRequest) Reset() { *m = PinMatrixRequest{} } +func (m *PinMatrixRequest) String() string { return proto.CompactTextString(m) } +func (*PinMatrixRequest) ProtoMessage() {} +func (*PinMatrixRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{12} } + +func (m *PinMatrixRequest) GetType() PinMatrixRequestType { + if m != nil && m.Type != nil { + return *m.Type + } + return PinMatrixRequestType_PinMatrixRequestType_Current +} + +// * +// Request: Computer responds with encoded PIN +// @prev PinMatrixRequest +type PinMatrixAck struct { + Pin *string `protobuf:"bytes,1,req,name=pin" json:"pin,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PinMatrixAck) Reset() { *m = PinMatrixAck{} } +func (m *PinMatrixAck) String() string { return proto.CompactTextString(m) } +func (*PinMatrixAck) ProtoMessage() {} +func (*PinMatrixAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{13} } + +func (m *PinMatrixAck) GetPin() string { + if m != nil && m.Pin != nil { + return *m.Pin + } + return "" +} + +// * +// Request: Abort last operation that required user interaction +// @prev ButtonRequest +// @prev PinMatrixRequest +// @prev PassphraseRequest +type Cancel struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Cancel) Reset() { *m = Cancel{} } +func (m *Cancel) String() string { return proto.CompactTextString(m) } +func (*Cancel) ProtoMessage() {} +func (*Cancel) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{14} } + +// * +// Response: Device awaits encryption passphrase +// @next PassphraseAck +// @next Cancel +type PassphraseRequest struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *PassphraseRequest) Reset() { *m = PassphraseRequest{} } +func (m *PassphraseRequest) String() string { return proto.CompactTextString(m) } +func (*PassphraseRequest) ProtoMessage() {} +func (*PassphraseRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{15} } + +// * +// Request: Send passphrase back +// @prev PassphraseRequest +type PassphraseAck struct { + Passphrase *string `protobuf:"bytes,1,req,name=passphrase" json:"passphrase,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PassphraseAck) Reset() { *m = PassphraseAck{} } +func (m *PassphraseAck) String() string { return proto.CompactTextString(m) } +func (*PassphraseAck) ProtoMessage() {} +func (*PassphraseAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{16} } + +func (m *PassphraseAck) GetPassphrase() string { + if m != nil && m.Passphrase != nil { + return *m.Passphrase + } + return "" +} + +// * +// Request: Request a sample of random data generated by hardware RNG. May be used for testing. +// @next ButtonRequest +// @next Entropy +// @next Failure +type GetEntropy struct { + Size *uint32 `protobuf:"varint,1,req,name=size" json:"size,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetEntropy) Reset() { *m = GetEntropy{} } +func (m *GetEntropy) String() string { return proto.CompactTextString(m) } +func (*GetEntropy) ProtoMessage() {} +func (*GetEntropy) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{17} } + +func (m *GetEntropy) GetSize() uint32 { + if m != nil && m.Size != nil { + return *m.Size + } + return 0 +} + +// * +// Response: Reply with random data generated by internal RNG +// @prev GetEntropy +type Entropy struct { + Entropy []byte `protobuf:"bytes,1,req,name=entropy" json:"entropy,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Entropy) Reset() { *m = Entropy{} } +func (m *Entropy) String() string { return proto.CompactTextString(m) } +func (*Entropy) ProtoMessage() {} +func (*Entropy) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{18} } + +func (m *Entropy) GetEntropy() []byte { + if m != nil { + return m.Entropy + } + return nil +} + +// * +// Request: Ask device for public key corresponding to address_n path +// @next PassphraseRequest +// @next PublicKey +// @next Failure +type GetPublicKey struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + EcdsaCurveName *string `protobuf:"bytes,2,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"` + ShowDisplay *bool `protobuf:"varint,3,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` + CoinName *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetPublicKey) Reset() { *m = GetPublicKey{} } +func (m *GetPublicKey) String() string { return proto.CompactTextString(m) } +func (*GetPublicKey) ProtoMessage() {} +func (*GetPublicKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{19} } + +const Default_GetPublicKey_CoinName string = "Bitcoin" + +func (m *GetPublicKey) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *GetPublicKey) GetEcdsaCurveName() string { + if m != nil && m.EcdsaCurveName != nil { + return *m.EcdsaCurveName + } + return "" +} + +func (m *GetPublicKey) GetShowDisplay() bool { + if m != nil && m.ShowDisplay != nil { + return *m.ShowDisplay + } + return false +} + +func (m *GetPublicKey) GetCoinName() string { + if m != nil && m.CoinName != nil { + return *m.CoinName + } + return Default_GetPublicKey_CoinName +} + +// * +// Response: Contains public key derived from device private seed +// @prev GetPublicKey +type PublicKey struct { + Node *HDNodeType `protobuf:"bytes,1,req,name=node" json:"node,omitempty"` + Xpub *string `protobuf:"bytes,2,opt,name=xpub" json:"xpub,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PublicKey) Reset() { *m = PublicKey{} } +func (m *PublicKey) String() string { return proto.CompactTextString(m) } +func (*PublicKey) ProtoMessage() {} +func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{20} } + +func (m *PublicKey) GetNode() *HDNodeType { + if m != nil { + return m.Node + } + return nil +} + +func (m *PublicKey) GetXpub() string { + if m != nil && m.Xpub != nil { + return *m.Xpub + } + return "" +} + +// * +// Request: Ask device for address corresponding to address_n path +// @next PassphraseRequest +// @next Address +// @next Failure +type GetAddress struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + CoinName *string `protobuf:"bytes,2,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` + ShowDisplay *bool `protobuf:"varint,3,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` + Multisig *MultisigRedeemScriptType `protobuf:"bytes,4,opt,name=multisig" json:"multisig,omitempty"` + ScriptType *InputScriptType `protobuf:"varint,5,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetAddress) Reset() { *m = GetAddress{} } +func (m *GetAddress) String() string { return proto.CompactTextString(m) } +func (*GetAddress) ProtoMessage() {} +func (*GetAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{21} } + +const Default_GetAddress_CoinName string = "Bitcoin" +const Default_GetAddress_ScriptType InputScriptType = InputScriptType_SPENDADDRESS + +func (m *GetAddress) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *GetAddress) GetCoinName() string { + if m != nil && m.CoinName != nil { + return *m.CoinName + } + return Default_GetAddress_CoinName +} + +func (m *GetAddress) GetShowDisplay() bool { + if m != nil && m.ShowDisplay != nil { + return *m.ShowDisplay + } + return false +} + +func (m *GetAddress) GetMultisig() *MultisigRedeemScriptType { + if m != nil { + return m.Multisig + } + return nil +} + +func (m *GetAddress) GetScriptType() InputScriptType { + if m != nil && m.ScriptType != nil { + return *m.ScriptType + } + return Default_GetAddress_ScriptType +} + +// * +// Request: Ask device for Ethereum address corresponding to address_n path +// @next PassphraseRequest +// @next EthereumAddress +// @next Failure +type EthereumGetAddress struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EthereumGetAddress) Reset() { *m = EthereumGetAddress{} } +func (m *EthereumGetAddress) String() string { return proto.CompactTextString(m) } +func (*EthereumGetAddress) ProtoMessage() {} +func (*EthereumGetAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{22} } + +func (m *EthereumGetAddress) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *EthereumGetAddress) GetShowDisplay() bool { + if m != nil && m.ShowDisplay != nil { + return *m.ShowDisplay + } + return false +} + +// * +// Response: Contains address derived from device private seed +// @prev GetAddress +type Address struct { + Address *string `protobuf:"bytes,1,req,name=address" json:"address,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Address) Reset() { *m = Address{} } +func (m *Address) String() string { return proto.CompactTextString(m) } +func (*Address) ProtoMessage() {} +func (*Address) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{23} } + +func (m *Address) GetAddress() string { + if m != nil && m.Address != nil { + return *m.Address + } + return "" +} + +// * +// Response: Contains an Ethereum address derived from device private seed +// @prev EthereumGetAddress +type EthereumAddress struct { + Address []byte `protobuf:"bytes,1,req,name=address" json:"address,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EthereumAddress) Reset() { *m = EthereumAddress{} } +func (m *EthereumAddress) String() string { return proto.CompactTextString(m) } +func (*EthereumAddress) ProtoMessage() {} +func (*EthereumAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{24} } + +func (m *EthereumAddress) GetAddress() []byte { + if m != nil { + return m.Address + } + return nil +} + +// * +// Request: Request device to wipe all sensitive data and settings +// @next ButtonRequest +type WipeDevice struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *WipeDevice) Reset() { *m = WipeDevice{} } +func (m *WipeDevice) String() string { return proto.CompactTextString(m) } +func (*WipeDevice) ProtoMessage() {} +func (*WipeDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{25} } + +// * +// Request: Load seed and related internal settings from the computer +// @next ButtonRequest +// @next Success +// @next Failure +type LoadDevice struct { + Mnemonic *string `protobuf:"bytes,1,opt,name=mnemonic" json:"mnemonic,omitempty"` + Node *HDNodeType `protobuf:"bytes,2,opt,name=node" json:"node,omitempty"` + Pin *string `protobuf:"bytes,3,opt,name=pin" json:"pin,omitempty"` + PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` + Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` + SkipChecksum *bool `protobuf:"varint,7,opt,name=skip_checksum,json=skipChecksum" json:"skip_checksum,omitempty"` + U2FCounter *uint32 `protobuf:"varint,8,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LoadDevice) Reset() { *m = LoadDevice{} } +func (m *LoadDevice) String() string { return proto.CompactTextString(m) } +func (*LoadDevice) ProtoMessage() {} +func (*LoadDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{26} } + +const Default_LoadDevice_Language string = "english" + +func (m *LoadDevice) GetMnemonic() string { + if m != nil && m.Mnemonic != nil { + return *m.Mnemonic + } + return "" +} + +func (m *LoadDevice) GetNode() *HDNodeType { + if m != nil { + return m.Node + } + return nil +} + +func (m *LoadDevice) GetPin() string { + if m != nil && m.Pin != nil { + return *m.Pin + } + return "" +} + +func (m *LoadDevice) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +func (m *LoadDevice) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return Default_LoadDevice_Language +} + +func (m *LoadDevice) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *LoadDevice) GetSkipChecksum() bool { + if m != nil && m.SkipChecksum != nil { + return *m.SkipChecksum + } + return false +} + +func (m *LoadDevice) GetU2FCounter() uint32 { + if m != nil && m.U2FCounter != nil { + return *m.U2FCounter + } + return 0 +} + +// * +// Request: Ask device to do initialization involving user interaction +// @next EntropyRequest +// @next Failure +type ResetDevice struct { + DisplayRandom *bool `protobuf:"varint,1,opt,name=display_random,json=displayRandom" json:"display_random,omitempty"` + Strength *uint32 `protobuf:"varint,2,opt,name=strength,def=256" json:"strength,omitempty"` + PassphraseProtection *bool `protobuf:"varint,3,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + PinProtection *bool `protobuf:"varint,4,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` + Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` + Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` + U2FCounter *uint32 `protobuf:"varint,7,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` + SkipBackup *bool `protobuf:"varint,8,opt,name=skip_backup,json=skipBackup" json:"skip_backup,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ResetDevice) Reset() { *m = ResetDevice{} } +func (m *ResetDevice) String() string { return proto.CompactTextString(m) } +func (*ResetDevice) ProtoMessage() {} +func (*ResetDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{27} } + +const Default_ResetDevice_Strength uint32 = 256 +const Default_ResetDevice_Language string = "english" + +func (m *ResetDevice) GetDisplayRandom() bool { + if m != nil && m.DisplayRandom != nil { + return *m.DisplayRandom + } + return false +} + +func (m *ResetDevice) GetStrength() uint32 { + if m != nil && m.Strength != nil { + return *m.Strength + } + return Default_ResetDevice_Strength +} + +func (m *ResetDevice) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +func (m *ResetDevice) GetPinProtection() bool { + if m != nil && m.PinProtection != nil { + return *m.PinProtection + } + return false +} + +func (m *ResetDevice) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return Default_ResetDevice_Language +} + +func (m *ResetDevice) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *ResetDevice) GetU2FCounter() uint32 { + if m != nil && m.U2FCounter != nil { + return *m.U2FCounter + } + return 0 +} + +func (m *ResetDevice) GetSkipBackup() bool { + if m != nil && m.SkipBackup != nil { + return *m.SkipBackup + } + return false +} + +// * +// Request: Perform backup of the device seed if not backed up using ResetDevice +// @next ButtonRequest +type BackupDevice struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *BackupDevice) Reset() { *m = BackupDevice{} } +func (m *BackupDevice) String() string { return proto.CompactTextString(m) } +func (*BackupDevice) ProtoMessage() {} +func (*BackupDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{28} } + +// * +// Response: Ask for additional entropy from host computer +// @prev ResetDevice +// @next EntropyAck +type EntropyRequest struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *EntropyRequest) Reset() { *m = EntropyRequest{} } +func (m *EntropyRequest) String() string { return proto.CompactTextString(m) } +func (*EntropyRequest) ProtoMessage() {} +func (*EntropyRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{29} } + +// * +// Request: Provide additional entropy for seed generation function +// @prev EntropyRequest +// @next ButtonRequest +type EntropyAck struct { + Entropy []byte `protobuf:"bytes,1,opt,name=entropy" json:"entropy,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EntropyAck) Reset() { *m = EntropyAck{} } +func (m *EntropyAck) String() string { return proto.CompactTextString(m) } +func (*EntropyAck) ProtoMessage() {} +func (*EntropyAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{30} } + +func (m *EntropyAck) GetEntropy() []byte { + if m != nil { + return m.Entropy + } + return nil +} + +// * +// Request: Start recovery workflow asking user for specific words of mnemonic +// Used to recovery device safely even on untrusted computer. +// @next WordRequest +type RecoveryDevice struct { + WordCount *uint32 `protobuf:"varint,1,opt,name=word_count,json=wordCount" json:"word_count,omitempty"` + PassphraseProtection *bool `protobuf:"varint,2,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` + Language *string `protobuf:"bytes,4,opt,name=language,def=english" json:"language,omitempty"` + Label *string `protobuf:"bytes,5,opt,name=label" json:"label,omitempty"` + EnforceWordlist *bool `protobuf:"varint,6,opt,name=enforce_wordlist,json=enforceWordlist" json:"enforce_wordlist,omitempty"` + // 7 reserved for unused recovery method + Type *uint32 `protobuf:"varint,8,opt,name=type" json:"type,omitempty"` + U2FCounter *uint32 `protobuf:"varint,9,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` + DryRun *bool `protobuf:"varint,10,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RecoveryDevice) Reset() { *m = RecoveryDevice{} } +func (m *RecoveryDevice) String() string { return proto.CompactTextString(m) } +func (*RecoveryDevice) ProtoMessage() {} +func (*RecoveryDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{31} } + +const Default_RecoveryDevice_Language string = "english" + +func (m *RecoveryDevice) GetWordCount() uint32 { + if m != nil && m.WordCount != nil { + return *m.WordCount + } + return 0 +} + +func (m *RecoveryDevice) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +func (m *RecoveryDevice) GetPinProtection() bool { + if m != nil && m.PinProtection != nil { + return *m.PinProtection + } + return false +} + +func (m *RecoveryDevice) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return Default_RecoveryDevice_Language +} + +func (m *RecoveryDevice) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *RecoveryDevice) GetEnforceWordlist() bool { + if m != nil && m.EnforceWordlist != nil { + return *m.EnforceWordlist + } + return false +} + +func (m *RecoveryDevice) GetType() uint32 { + if m != nil && m.Type != nil { + return *m.Type + } + return 0 +} + +func (m *RecoveryDevice) GetU2FCounter() uint32 { + if m != nil && m.U2FCounter != nil { + return *m.U2FCounter + } + return 0 +} + +func (m *RecoveryDevice) GetDryRun() bool { + if m != nil && m.DryRun != nil { + return *m.DryRun + } + return false +} + +// * +// Response: Device is waiting for user to enter word of the mnemonic +// Its position is shown only on device's internal display. +// @prev RecoveryDevice +// @prev WordAck +type WordRequest struct { + Type *WordRequestType `protobuf:"varint,1,opt,name=type,enum=WordRequestType" json:"type,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *WordRequest) Reset() { *m = WordRequest{} } +func (m *WordRequest) String() string { return proto.CompactTextString(m) } +func (*WordRequest) ProtoMessage() {} +func (*WordRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{32} } + +func (m *WordRequest) GetType() WordRequestType { + if m != nil && m.Type != nil { + return *m.Type + } + return WordRequestType_WordRequestType_Plain +} + +// * +// Request: Computer replies with word from the mnemonic +// @prev WordRequest +// @next WordRequest +// @next Success +// @next Failure +type WordAck struct { + Word *string `protobuf:"bytes,1,req,name=word" json:"word,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *WordAck) Reset() { *m = WordAck{} } +func (m *WordAck) String() string { return proto.CompactTextString(m) } +func (*WordAck) ProtoMessage() {} +func (*WordAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{33} } + +func (m *WordAck) GetWord() string { + if m != nil && m.Word != nil { + return *m.Word + } + return "" +} + +// * +// Request: Ask device to sign message +// @next MessageSignature +// @next Failure +type SignMessage struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + Message []byte `protobuf:"bytes,2,req,name=message" json:"message,omitempty"` + CoinName *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` + ScriptType *InputScriptType `protobuf:"varint,4,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SignMessage) Reset() { *m = SignMessage{} } +func (m *SignMessage) String() string { return proto.CompactTextString(m) } +func (*SignMessage) ProtoMessage() {} +func (*SignMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{34} } + +const Default_SignMessage_CoinName string = "Bitcoin" +const Default_SignMessage_ScriptType InputScriptType = InputScriptType_SPENDADDRESS + +func (m *SignMessage) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *SignMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +func (m *SignMessage) GetCoinName() string { + if m != nil && m.CoinName != nil { + return *m.CoinName + } + return Default_SignMessage_CoinName +} + +func (m *SignMessage) GetScriptType() InputScriptType { + if m != nil && m.ScriptType != nil { + return *m.ScriptType + } + return Default_SignMessage_ScriptType +} + +// * +// Request: Ask device to verify message +// @next Success +// @next Failure +type VerifyMessage struct { + Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` + Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` + CoinName *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *VerifyMessage) Reset() { *m = VerifyMessage{} } +func (m *VerifyMessage) String() string { return proto.CompactTextString(m) } +func (*VerifyMessage) ProtoMessage() {} +func (*VerifyMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{35} } + +const Default_VerifyMessage_CoinName string = "Bitcoin" + +func (m *VerifyMessage) GetAddress() string { + if m != nil && m.Address != nil { + return *m.Address + } + return "" +} + +func (m *VerifyMessage) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *VerifyMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +func (m *VerifyMessage) GetCoinName() string { + if m != nil && m.CoinName != nil { + return *m.CoinName + } + return Default_VerifyMessage_CoinName +} + +// * +// Response: Signed message +// @prev SignMessage +type MessageSignature struct { + Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MessageSignature) Reset() { *m = MessageSignature{} } +func (m *MessageSignature) String() string { return proto.CompactTextString(m) } +func (*MessageSignature) ProtoMessage() {} +func (*MessageSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{36} } + +func (m *MessageSignature) GetAddress() string { + if m != nil && m.Address != nil { + return *m.Address + } + return "" +} + +func (m *MessageSignature) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +// * +// Request: Ask device to encrypt message +// @next EncryptedMessage +// @next Failure +type EncryptMessage struct { + Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` + Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` + DisplayOnly *bool `protobuf:"varint,3,opt,name=display_only,json=displayOnly" json:"display_only,omitempty"` + AddressN []uint32 `protobuf:"varint,4,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + CoinName *string `protobuf:"bytes,5,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EncryptMessage) Reset() { *m = EncryptMessage{} } +func (m *EncryptMessage) String() string { return proto.CompactTextString(m) } +func (*EncryptMessage) ProtoMessage() {} +func (*EncryptMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{37} } + +const Default_EncryptMessage_CoinName string = "Bitcoin" + +func (m *EncryptMessage) GetPubkey() []byte { + if m != nil { + return m.Pubkey + } + return nil +} + +func (m *EncryptMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +func (m *EncryptMessage) GetDisplayOnly() bool { + if m != nil && m.DisplayOnly != nil { + return *m.DisplayOnly + } + return false +} + +func (m *EncryptMessage) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *EncryptMessage) GetCoinName() string { + if m != nil && m.CoinName != nil { + return *m.CoinName + } + return Default_EncryptMessage_CoinName +} + +// * +// Response: Encrypted message +// @prev EncryptMessage +type EncryptedMessage struct { + Nonce []byte `protobuf:"bytes,1,opt,name=nonce" json:"nonce,omitempty"` + Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` + Hmac []byte `protobuf:"bytes,3,opt,name=hmac" json:"hmac,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EncryptedMessage) Reset() { *m = EncryptedMessage{} } +func (m *EncryptedMessage) String() string { return proto.CompactTextString(m) } +func (*EncryptedMessage) ProtoMessage() {} +func (*EncryptedMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{38} } + +func (m *EncryptedMessage) GetNonce() []byte { + if m != nil { + return m.Nonce + } + return nil +} + +func (m *EncryptedMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +func (m *EncryptedMessage) GetHmac() []byte { + if m != nil { + return m.Hmac + } + return nil +} + +// * +// Request: Ask device to decrypt message +// @next Success +// @next Failure +type DecryptMessage struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"` + Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` + Hmac []byte `protobuf:"bytes,4,opt,name=hmac" json:"hmac,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DecryptMessage) Reset() { *m = DecryptMessage{} } +func (m *DecryptMessage) String() string { return proto.CompactTextString(m) } +func (*DecryptMessage) ProtoMessage() {} +func (*DecryptMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{39} } + +func (m *DecryptMessage) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *DecryptMessage) GetNonce() []byte { + if m != nil { + return m.Nonce + } + return nil +} + +func (m *DecryptMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +func (m *DecryptMessage) GetHmac() []byte { + if m != nil { + return m.Hmac + } + return nil +} + +// * +// Response: Decrypted message +// @prev DecryptedMessage +type DecryptedMessage struct { + Message []byte `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` + Address *string `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DecryptedMessage) Reset() { *m = DecryptedMessage{} } +func (m *DecryptedMessage) String() string { return proto.CompactTextString(m) } +func (*DecryptedMessage) ProtoMessage() {} +func (*DecryptedMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{40} } + +func (m *DecryptedMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +func (m *DecryptedMessage) GetAddress() string { + if m != nil && m.Address != nil { + return *m.Address + } + return "" +} + +// * +// Request: Ask device to encrypt or decrypt value of given key +// @next CipheredKeyValue +// @next Failure +type CipherKeyValue struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + Key *string `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"` + Encrypt *bool `protobuf:"varint,4,opt,name=encrypt" json:"encrypt,omitempty"` + AskOnEncrypt *bool `protobuf:"varint,5,opt,name=ask_on_encrypt,json=askOnEncrypt" json:"ask_on_encrypt,omitempty"` + AskOnDecrypt *bool `protobuf:"varint,6,opt,name=ask_on_decrypt,json=askOnDecrypt" json:"ask_on_decrypt,omitempty"` + Iv []byte `protobuf:"bytes,7,opt,name=iv" json:"iv,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CipherKeyValue) Reset() { *m = CipherKeyValue{} } +func (m *CipherKeyValue) String() string { return proto.CompactTextString(m) } +func (*CipherKeyValue) ProtoMessage() {} +func (*CipherKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{41} } + +func (m *CipherKeyValue) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *CipherKeyValue) GetKey() string { + if m != nil && m.Key != nil { + return *m.Key + } + return "" +} + +func (m *CipherKeyValue) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *CipherKeyValue) GetEncrypt() bool { + if m != nil && m.Encrypt != nil { + return *m.Encrypt + } + return false +} + +func (m *CipherKeyValue) GetAskOnEncrypt() bool { + if m != nil && m.AskOnEncrypt != nil { + return *m.AskOnEncrypt + } + return false +} + +func (m *CipherKeyValue) GetAskOnDecrypt() bool { + if m != nil && m.AskOnDecrypt != nil { + return *m.AskOnDecrypt + } + return false +} + +func (m *CipherKeyValue) GetIv() []byte { + if m != nil { + return m.Iv + } + return nil +} + +// * +// Response: Return ciphered/deciphered value +// @prev CipherKeyValue +type CipheredKeyValue struct { + Value []byte `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CipheredKeyValue) Reset() { *m = CipheredKeyValue{} } +func (m *CipheredKeyValue) String() string { return proto.CompactTextString(m) } +func (*CipheredKeyValue) ProtoMessage() {} +func (*CipheredKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{42} } + +func (m *CipheredKeyValue) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +// * +// Request: Estimated size of the transaction +// This behaves exactly like SignTx, which means that it can ask using TxRequest +// This call is non-blocking (except possible PassphraseRequest to unlock the seed) +// @next TxSize +// @next Failure +type EstimateTxSize struct { + OutputsCount *uint32 `protobuf:"varint,1,req,name=outputs_count,json=outputsCount" json:"outputs_count,omitempty"` + InputsCount *uint32 `protobuf:"varint,2,req,name=inputs_count,json=inputsCount" json:"inputs_count,omitempty"` + CoinName *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EstimateTxSize) Reset() { *m = EstimateTxSize{} } +func (m *EstimateTxSize) String() string { return proto.CompactTextString(m) } +func (*EstimateTxSize) ProtoMessage() {} +func (*EstimateTxSize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{43} } + +const Default_EstimateTxSize_CoinName string = "Bitcoin" + +func (m *EstimateTxSize) GetOutputsCount() uint32 { + if m != nil && m.OutputsCount != nil { + return *m.OutputsCount + } + return 0 +} + +func (m *EstimateTxSize) GetInputsCount() uint32 { + if m != nil && m.InputsCount != nil { + return *m.InputsCount + } + return 0 +} + +func (m *EstimateTxSize) GetCoinName() string { + if m != nil && m.CoinName != nil { + return *m.CoinName + } + return Default_EstimateTxSize_CoinName +} + +// * +// Response: Estimated size of the transaction +// @prev EstimateTxSize +type TxSize struct { + TxSize *uint32 `protobuf:"varint,1,opt,name=tx_size,json=txSize" json:"tx_size,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TxSize) Reset() { *m = TxSize{} } +func (m *TxSize) String() string { return proto.CompactTextString(m) } +func (*TxSize) ProtoMessage() {} +func (*TxSize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{44} } + +func (m *TxSize) GetTxSize() uint32 { + if m != nil && m.TxSize != nil { + return *m.TxSize + } + return 0 +} + +// * +// Request: Ask device to sign transaction +// @next PassphraseRequest +// @next PinMatrixRequest +// @next TxRequest +// @next Failure +type SignTx struct { + OutputsCount *uint32 `protobuf:"varint,1,req,name=outputs_count,json=outputsCount" json:"outputs_count,omitempty"` + InputsCount *uint32 `protobuf:"varint,2,req,name=inputs_count,json=inputsCount" json:"inputs_count,omitempty"` + CoinName *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` + Version *uint32 `protobuf:"varint,4,opt,name=version,def=1" json:"version,omitempty"` + LockTime *uint32 `protobuf:"varint,5,opt,name=lock_time,json=lockTime,def=0" json:"lock_time,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SignTx) Reset() { *m = SignTx{} } +func (m *SignTx) String() string { return proto.CompactTextString(m) } +func (*SignTx) ProtoMessage() {} +func (*SignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{45} } + +const Default_SignTx_CoinName string = "Bitcoin" +const Default_SignTx_Version uint32 = 1 +const Default_SignTx_LockTime uint32 = 0 + +func (m *SignTx) GetOutputsCount() uint32 { + if m != nil && m.OutputsCount != nil { + return *m.OutputsCount + } + return 0 +} + +func (m *SignTx) GetInputsCount() uint32 { + if m != nil && m.InputsCount != nil { + return *m.InputsCount + } + return 0 +} + +func (m *SignTx) GetCoinName() string { + if m != nil && m.CoinName != nil { + return *m.CoinName + } + return Default_SignTx_CoinName +} + +func (m *SignTx) GetVersion() uint32 { + if m != nil && m.Version != nil { + return *m.Version + } + return Default_SignTx_Version +} + +func (m *SignTx) GetLockTime() uint32 { + if m != nil && m.LockTime != nil { + return *m.LockTime + } + return Default_SignTx_LockTime +} + +// * +// Request: Simplified transaction signing +// This method doesn't support streaming, so there are hardware limits in number of inputs and outputs. +// In case of success, the result is returned using TxRequest message. +// @next PassphraseRequest +// @next PinMatrixRequest +// @next TxRequest +// @next Failure +type SimpleSignTx struct { + Inputs []*TxInputType `protobuf:"bytes,1,rep,name=inputs" json:"inputs,omitempty"` + Outputs []*TxOutputType `protobuf:"bytes,2,rep,name=outputs" json:"outputs,omitempty"` + Transactions []*TransactionType `protobuf:"bytes,3,rep,name=transactions" json:"transactions,omitempty"` + CoinName *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` + Version *uint32 `protobuf:"varint,5,opt,name=version,def=1" json:"version,omitempty"` + LockTime *uint32 `protobuf:"varint,6,opt,name=lock_time,json=lockTime,def=0" json:"lock_time,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SimpleSignTx) Reset() { *m = SimpleSignTx{} } +func (m *SimpleSignTx) String() string { return proto.CompactTextString(m) } +func (*SimpleSignTx) ProtoMessage() {} +func (*SimpleSignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{46} } + +const Default_SimpleSignTx_CoinName string = "Bitcoin" +const Default_SimpleSignTx_Version uint32 = 1 +const Default_SimpleSignTx_LockTime uint32 = 0 + +func (m *SimpleSignTx) GetInputs() []*TxInputType { + if m != nil { + return m.Inputs + } + return nil +} + +func (m *SimpleSignTx) GetOutputs() []*TxOutputType { + if m != nil { + return m.Outputs + } + return nil +} + +func (m *SimpleSignTx) GetTransactions() []*TransactionType { + if m != nil { + return m.Transactions + } + return nil +} + +func (m *SimpleSignTx) GetCoinName() string { + if m != nil && m.CoinName != nil { + return *m.CoinName + } + return Default_SimpleSignTx_CoinName +} + +func (m *SimpleSignTx) GetVersion() uint32 { + if m != nil && m.Version != nil { + return *m.Version + } + return Default_SimpleSignTx_Version +} + +func (m *SimpleSignTx) GetLockTime() uint32 { + if m != nil && m.LockTime != nil { + return *m.LockTime + } + return Default_SimpleSignTx_LockTime +} + +// * +// Response: Device asks for information for signing transaction or returns the last result +// If request_index is set, device awaits TxAck message (with fields filled in according to request_type) +// If signature_index is set, 'signature' contains signed input of signature_index's input +// @prev SignTx +// @prev SimpleSignTx +// @prev TxAck +type TxRequest struct { + RequestType *RequestType `protobuf:"varint,1,opt,name=request_type,json=requestType,enum=RequestType" json:"request_type,omitempty"` + Details *TxRequestDetailsType `protobuf:"bytes,2,opt,name=details" json:"details,omitempty"` + Serialized *TxRequestSerializedType `protobuf:"bytes,3,opt,name=serialized" json:"serialized,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TxRequest) Reset() { *m = TxRequest{} } +func (m *TxRequest) String() string { return proto.CompactTextString(m) } +func (*TxRequest) ProtoMessage() {} +func (*TxRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{47} } + +func (m *TxRequest) GetRequestType() RequestType { + if m != nil && m.RequestType != nil { + return *m.RequestType + } + return RequestType_TXINPUT +} + +func (m *TxRequest) GetDetails() *TxRequestDetailsType { + if m != nil { + return m.Details + } + return nil +} + +func (m *TxRequest) GetSerialized() *TxRequestSerializedType { + if m != nil { + return m.Serialized + } + return nil +} + +// * +// Request: Reported transaction data +// @prev TxRequest +// @next TxRequest +type TxAck struct { + Tx *TransactionType `protobuf:"bytes,1,opt,name=tx" json:"tx,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TxAck) Reset() { *m = TxAck{} } +func (m *TxAck) String() string { return proto.CompactTextString(m) } +func (*TxAck) ProtoMessage() {} +func (*TxAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{48} } + +func (m *TxAck) GetTx() *TransactionType { + if m != nil { + return m.Tx + } + return nil +} + +// * +// Request: Ask device to sign transaction +// All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing. +// Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. +// @next PassphraseRequest +// @next PinMatrixRequest +// @next EthereumTxRequest +// @next Failure +type EthereumSignTx struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"` + GasPrice []byte `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice" json:"gas_price,omitempty"` + GasLimit []byte `protobuf:"bytes,4,opt,name=gas_limit,json=gasLimit" json:"gas_limit,omitempty"` + To []byte `protobuf:"bytes,5,opt,name=to" json:"to,omitempty"` + Value []byte `protobuf:"bytes,6,opt,name=value" json:"value,omitempty"` + DataInitialChunk []byte `protobuf:"bytes,7,opt,name=data_initial_chunk,json=dataInitialChunk" json:"data_initial_chunk,omitempty"` + DataLength *uint32 `protobuf:"varint,8,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` + ChainId *uint32 `protobuf:"varint,9,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EthereumSignTx) Reset() { *m = EthereumSignTx{} } +func (m *EthereumSignTx) String() string { return proto.CompactTextString(m) } +func (*EthereumSignTx) ProtoMessage() {} +func (*EthereumSignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{49} } + +func (m *EthereumSignTx) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *EthereumSignTx) GetNonce() []byte { + if m != nil { + return m.Nonce + } + return nil +} + +func (m *EthereumSignTx) GetGasPrice() []byte { + if m != nil { + return m.GasPrice + } + return nil +} + +func (m *EthereumSignTx) GetGasLimit() []byte { + if m != nil { + return m.GasLimit + } + return nil +} + +func (m *EthereumSignTx) GetTo() []byte { + if m != nil { + return m.To + } + return nil +} + +func (m *EthereumSignTx) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *EthereumSignTx) GetDataInitialChunk() []byte { + if m != nil { + return m.DataInitialChunk + } + return nil +} + +func (m *EthereumSignTx) GetDataLength() uint32 { + if m != nil && m.DataLength != nil { + return *m.DataLength + } + return 0 +} + +func (m *EthereumSignTx) GetChainId() uint32 { + if m != nil && m.ChainId != nil { + return *m.ChainId + } + return 0 +} + +// * +// Response: Device asks for more data from transaction payload, or returns the signature. +// If data_length is set, device awaits that many more bytes of payload. +// Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present. +// @prev EthereumSignTx +// @next EthereumTxAck +type EthereumTxRequest struct { + DataLength *uint32 `protobuf:"varint,1,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` + SignatureV *uint32 `protobuf:"varint,2,opt,name=signature_v,json=signatureV" json:"signature_v,omitempty"` + SignatureR []byte `protobuf:"bytes,3,opt,name=signature_r,json=signatureR" json:"signature_r,omitempty"` + SignatureS []byte `protobuf:"bytes,4,opt,name=signature_s,json=signatureS" json:"signature_s,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EthereumTxRequest) Reset() { *m = EthereumTxRequest{} } +func (m *EthereumTxRequest) String() string { return proto.CompactTextString(m) } +func (*EthereumTxRequest) ProtoMessage() {} +func (*EthereumTxRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{50} } + +func (m *EthereumTxRequest) GetDataLength() uint32 { + if m != nil && m.DataLength != nil { + return *m.DataLength + } + return 0 +} + +func (m *EthereumTxRequest) GetSignatureV() uint32 { + if m != nil && m.SignatureV != nil { + return *m.SignatureV + } + return 0 +} + +func (m *EthereumTxRequest) GetSignatureR() []byte { + if m != nil { + return m.SignatureR + } + return nil +} + +func (m *EthereumTxRequest) GetSignatureS() []byte { + if m != nil { + return m.SignatureS + } + return nil +} + +// * +// Request: Transaction payload data. +// @prev EthereumTxRequest +// @next EthereumTxRequest +type EthereumTxAck struct { + DataChunk []byte `protobuf:"bytes,1,opt,name=data_chunk,json=dataChunk" json:"data_chunk,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EthereumTxAck) Reset() { *m = EthereumTxAck{} } +func (m *EthereumTxAck) String() string { return proto.CompactTextString(m) } +func (*EthereumTxAck) ProtoMessage() {} +func (*EthereumTxAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{51} } + +func (m *EthereumTxAck) GetDataChunk() []byte { + if m != nil { + return m.DataChunk + } + return nil +} + +// * +// Request: Ask device to sign message +// @next EthereumMessageSignature +// @next Failure +type EthereumSignMessage struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + Message []byte `protobuf:"bytes,2,req,name=message" json:"message,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EthereumSignMessage) Reset() { *m = EthereumSignMessage{} } +func (m *EthereumSignMessage) String() string { return proto.CompactTextString(m) } +func (*EthereumSignMessage) ProtoMessage() {} +func (*EthereumSignMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{52} } + +func (m *EthereumSignMessage) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *EthereumSignMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +// * +// Request: Ask device to verify message +// @next Success +// @next Failure +type EthereumVerifyMessage struct { + Address []byte `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` + Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EthereumVerifyMessage) Reset() { *m = EthereumVerifyMessage{} } +func (m *EthereumVerifyMessage) String() string { return proto.CompactTextString(m) } +func (*EthereumVerifyMessage) ProtoMessage() {} +func (*EthereumVerifyMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{53} } + +func (m *EthereumVerifyMessage) GetAddress() []byte { + if m != nil { + return m.Address + } + return nil +} + +func (m *EthereumVerifyMessage) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *EthereumVerifyMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +// * +// Response: Signed message +// @prev EthereumSignMessage +type EthereumMessageSignature struct { + Address []byte `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EthereumMessageSignature) Reset() { *m = EthereumMessageSignature{} } +func (m *EthereumMessageSignature) String() string { return proto.CompactTextString(m) } +func (*EthereumMessageSignature) ProtoMessage() {} +func (*EthereumMessageSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{54} } + +func (m *EthereumMessageSignature) GetAddress() []byte { + if m != nil { + return m.Address + } + return nil +} + +func (m *EthereumMessageSignature) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +// * +// Request: Ask device to sign identity +// @next SignedIdentity +// @next Failure +type SignIdentity struct { + Identity *IdentityType `protobuf:"bytes,1,opt,name=identity" json:"identity,omitempty"` + ChallengeHidden []byte `protobuf:"bytes,2,opt,name=challenge_hidden,json=challengeHidden" json:"challenge_hidden,omitempty"` + ChallengeVisual *string `protobuf:"bytes,3,opt,name=challenge_visual,json=challengeVisual" json:"challenge_visual,omitempty"` + EcdsaCurveName *string `protobuf:"bytes,4,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SignIdentity) Reset() { *m = SignIdentity{} } +func (m *SignIdentity) String() string { return proto.CompactTextString(m) } +func (*SignIdentity) ProtoMessage() {} +func (*SignIdentity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{55} } + +func (m *SignIdentity) GetIdentity() *IdentityType { + if m != nil { + return m.Identity + } + return nil +} + +func (m *SignIdentity) GetChallengeHidden() []byte { + if m != nil { + return m.ChallengeHidden + } + return nil +} + +func (m *SignIdentity) GetChallengeVisual() string { + if m != nil && m.ChallengeVisual != nil { + return *m.ChallengeVisual + } + return "" +} + +func (m *SignIdentity) GetEcdsaCurveName() string { + if m != nil && m.EcdsaCurveName != nil { + return *m.EcdsaCurveName + } + return "" +} + +// * +// Response: Device provides signed identity +// @prev SignIdentity +type SignedIdentity struct { + Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` + PublicKey []byte `protobuf:"bytes,2,opt,name=public_key,json=publicKey" json:"public_key,omitempty"` + Signature []byte `protobuf:"bytes,3,opt,name=signature" json:"signature,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SignedIdentity) Reset() { *m = SignedIdentity{} } +func (m *SignedIdentity) String() string { return proto.CompactTextString(m) } +func (*SignedIdentity) ProtoMessage() {} +func (*SignedIdentity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{56} } + +func (m *SignedIdentity) GetAddress() string { + if m != nil && m.Address != nil { + return *m.Address + } + return "" +} + +func (m *SignedIdentity) GetPublicKey() []byte { + if m != nil { + return m.PublicKey + } + return nil +} + +func (m *SignedIdentity) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +// * +// Request: Ask device to generate ECDH session key +// @next ECDHSessionKey +// @next Failure +type GetECDHSessionKey struct { + Identity *IdentityType `protobuf:"bytes,1,opt,name=identity" json:"identity,omitempty"` + PeerPublicKey []byte `protobuf:"bytes,2,opt,name=peer_public_key,json=peerPublicKey" json:"peer_public_key,omitempty"` + EcdsaCurveName *string `protobuf:"bytes,3,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetECDHSessionKey) Reset() { *m = GetECDHSessionKey{} } +func (m *GetECDHSessionKey) String() string { return proto.CompactTextString(m) } +func (*GetECDHSessionKey) ProtoMessage() {} +func (*GetECDHSessionKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{57} } + +func (m *GetECDHSessionKey) GetIdentity() *IdentityType { + if m != nil { + return m.Identity + } + return nil +} + +func (m *GetECDHSessionKey) GetPeerPublicKey() []byte { + if m != nil { + return m.PeerPublicKey + } + return nil +} + +func (m *GetECDHSessionKey) GetEcdsaCurveName() string { + if m != nil && m.EcdsaCurveName != nil { + return *m.EcdsaCurveName + } + return "" +} + +// * +// Response: Device provides ECDH session key +// @prev GetECDHSessionKey +type ECDHSessionKey struct { + SessionKey []byte `protobuf:"bytes,1,opt,name=session_key,json=sessionKey" json:"session_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ECDHSessionKey) Reset() { *m = ECDHSessionKey{} } +func (m *ECDHSessionKey) String() string { return proto.CompactTextString(m) } +func (*ECDHSessionKey) ProtoMessage() {} +func (*ECDHSessionKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{58} } + +func (m *ECDHSessionKey) GetSessionKey() []byte { + if m != nil { + return m.SessionKey + } + return nil +} + +// * +// Request: Set U2F counter +// @next Success +type SetU2FCounter struct { + U2FCounter *uint32 `protobuf:"varint,1,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SetU2FCounter) Reset() { *m = SetU2FCounter{} } +func (m *SetU2FCounter) String() string { return proto.CompactTextString(m) } +func (*SetU2FCounter) ProtoMessage() {} +func (*SetU2FCounter) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{59} } + +func (m *SetU2FCounter) GetU2FCounter() uint32 { + if m != nil && m.U2FCounter != nil { + return *m.U2FCounter + } + return 0 +} + +// * +// Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload) +// @next Success +// @next FirmwareRequest +// @next Failure +type FirmwareErase struct { + Length *uint32 `protobuf:"varint,1,opt,name=length" json:"length,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FirmwareErase) Reset() { *m = FirmwareErase{} } +func (m *FirmwareErase) String() string { return proto.CompactTextString(m) } +func (*FirmwareErase) ProtoMessage() {} +func (*FirmwareErase) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{60} } + +func (m *FirmwareErase) GetLength() uint32 { + if m != nil && m.Length != nil { + return *m.Length + } + return 0 +} + +// * +// Response: Ask for firmware chunk +// @next FirmwareUpload +type FirmwareRequest struct { + Offset *uint32 `protobuf:"varint,1,opt,name=offset" json:"offset,omitempty"` + Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FirmwareRequest) Reset() { *m = FirmwareRequest{} } +func (m *FirmwareRequest) String() string { return proto.CompactTextString(m) } +func (*FirmwareRequest) ProtoMessage() {} +func (*FirmwareRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{61} } + +func (m *FirmwareRequest) GetOffset() uint32 { + if m != nil && m.Offset != nil { + return *m.Offset + } + return 0 +} + +func (m *FirmwareRequest) GetLength() uint32 { + if m != nil && m.Length != nil { + return *m.Length + } + return 0 +} + +// * +// Request: Send firmware in binary form to the device +// @next Success +// @next Failure +type FirmwareUpload struct { + Payload []byte `protobuf:"bytes,1,req,name=payload" json:"payload,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=hash" json:"hash,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FirmwareUpload) Reset() { *m = FirmwareUpload{} } +func (m *FirmwareUpload) String() string { return proto.CompactTextString(m) } +func (*FirmwareUpload) ProtoMessage() {} +func (*FirmwareUpload) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{62} } + +func (m *FirmwareUpload) GetPayload() []byte { + if m != nil { + return m.Payload + } + return nil +} + +func (m *FirmwareUpload) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +// * +// Request: Perform a device self-test +// @next Success +// @next Failure +type SelfTest struct { + Payload []byte `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SelfTest) Reset() { *m = SelfTest{} } +func (m *SelfTest) String() string { return proto.CompactTextString(m) } +func (*SelfTest) ProtoMessage() {} +func (*SelfTest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{63} } + +func (m *SelfTest) GetPayload() []byte { + if m != nil { + return m.Payload + } + return nil +} + +// * +// Request: "Press" the button on the device +// @next Success +type DebugLinkDecision struct { + YesNo *bool `protobuf:"varint,1,req,name=yes_no,json=yesNo" json:"yes_no,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DebugLinkDecision) Reset() { *m = DebugLinkDecision{} } +func (m *DebugLinkDecision) String() string { return proto.CompactTextString(m) } +func (*DebugLinkDecision) ProtoMessage() {} +func (*DebugLinkDecision) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{64} } + +func (m *DebugLinkDecision) GetYesNo() bool { + if m != nil && m.YesNo != nil { + return *m.YesNo + } + return false +} + +// * +// Request: Computer asks for device state +// @next DebugLinkState +type DebugLinkGetState struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *DebugLinkGetState) Reset() { *m = DebugLinkGetState{} } +func (m *DebugLinkGetState) String() string { return proto.CompactTextString(m) } +func (*DebugLinkGetState) ProtoMessage() {} +func (*DebugLinkGetState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{65} } + +// * +// Response: Device current state +// @prev DebugLinkGetState +type DebugLinkState struct { + Layout []byte `protobuf:"bytes,1,opt,name=layout" json:"layout,omitempty"` + Pin *string `protobuf:"bytes,2,opt,name=pin" json:"pin,omitempty"` + Matrix *string `protobuf:"bytes,3,opt,name=matrix" json:"matrix,omitempty"` + Mnemonic *string `protobuf:"bytes,4,opt,name=mnemonic" json:"mnemonic,omitempty"` + Node *HDNodeType `protobuf:"bytes,5,opt,name=node" json:"node,omitempty"` + PassphraseProtection *bool `protobuf:"varint,6,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + ResetWord *string `protobuf:"bytes,7,opt,name=reset_word,json=resetWord" json:"reset_word,omitempty"` + ResetEntropy []byte `protobuf:"bytes,8,opt,name=reset_entropy,json=resetEntropy" json:"reset_entropy,omitempty"` + RecoveryFakeWord *string `protobuf:"bytes,9,opt,name=recovery_fake_word,json=recoveryFakeWord" json:"recovery_fake_word,omitempty"` + RecoveryWordPos *uint32 `protobuf:"varint,10,opt,name=recovery_word_pos,json=recoveryWordPos" json:"recovery_word_pos,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DebugLinkState) Reset() { *m = DebugLinkState{} } +func (m *DebugLinkState) String() string { return proto.CompactTextString(m) } +func (*DebugLinkState) ProtoMessage() {} +func (*DebugLinkState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{66} } + +func (m *DebugLinkState) GetLayout() []byte { + if m != nil { + return m.Layout + } + return nil +} + +func (m *DebugLinkState) GetPin() string { + if m != nil && m.Pin != nil { + return *m.Pin + } + return "" +} + +func (m *DebugLinkState) GetMatrix() string { + if m != nil && m.Matrix != nil { + return *m.Matrix + } + return "" +} + +func (m *DebugLinkState) GetMnemonic() string { + if m != nil && m.Mnemonic != nil { + return *m.Mnemonic + } + return "" +} + +func (m *DebugLinkState) GetNode() *HDNodeType { + if m != nil { + return m.Node + } + return nil +} + +func (m *DebugLinkState) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +func (m *DebugLinkState) GetResetWord() string { + if m != nil && m.ResetWord != nil { + return *m.ResetWord + } + return "" +} + +func (m *DebugLinkState) GetResetEntropy() []byte { + if m != nil { + return m.ResetEntropy + } + return nil +} + +func (m *DebugLinkState) GetRecoveryFakeWord() string { + if m != nil && m.RecoveryFakeWord != nil { + return *m.RecoveryFakeWord + } + return "" +} + +func (m *DebugLinkState) GetRecoveryWordPos() uint32 { + if m != nil && m.RecoveryWordPos != nil { + return *m.RecoveryWordPos + } + return 0 +} + +// * +// Request: Ask device to restart +type DebugLinkStop struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *DebugLinkStop) Reset() { *m = DebugLinkStop{} } +func (m *DebugLinkStop) String() string { return proto.CompactTextString(m) } +func (*DebugLinkStop) ProtoMessage() {} +func (*DebugLinkStop) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{67} } + +// * +// Response: Device wants host to log event +type DebugLinkLog struct { + Level *uint32 `protobuf:"varint,1,opt,name=level" json:"level,omitempty"` + Bucket *string `protobuf:"bytes,2,opt,name=bucket" json:"bucket,omitempty"` + Text *string `protobuf:"bytes,3,opt,name=text" json:"text,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DebugLinkLog) Reset() { *m = DebugLinkLog{} } +func (m *DebugLinkLog) String() string { return proto.CompactTextString(m) } +func (*DebugLinkLog) ProtoMessage() {} +func (*DebugLinkLog) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{68} } + +func (m *DebugLinkLog) GetLevel() uint32 { + if m != nil && m.Level != nil { + return *m.Level + } + return 0 +} + +func (m *DebugLinkLog) GetBucket() string { + if m != nil && m.Bucket != nil { + return *m.Bucket + } + return "" +} + +func (m *DebugLinkLog) GetText() string { + if m != nil && m.Text != nil { + return *m.Text + } + return "" +} + +// * +// Request: Read memory from device +// @next DebugLinkMemory +type DebugLinkMemoryRead struct { + Address *uint32 `protobuf:"varint,1,opt,name=address" json:"address,omitempty"` + Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DebugLinkMemoryRead) Reset() { *m = DebugLinkMemoryRead{} } +func (m *DebugLinkMemoryRead) String() string { return proto.CompactTextString(m) } +func (*DebugLinkMemoryRead) ProtoMessage() {} +func (*DebugLinkMemoryRead) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{69} } + +func (m *DebugLinkMemoryRead) GetAddress() uint32 { + if m != nil && m.Address != nil { + return *m.Address + } + return 0 +} + +func (m *DebugLinkMemoryRead) GetLength() uint32 { + if m != nil && m.Length != nil { + return *m.Length + } + return 0 +} + +// * +// Response: Device sends memory back +// @prev DebugLinkMemoryRead +type DebugLinkMemory struct { + Memory []byte `protobuf:"bytes,1,opt,name=memory" json:"memory,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DebugLinkMemory) Reset() { *m = DebugLinkMemory{} } +func (m *DebugLinkMemory) String() string { return proto.CompactTextString(m) } +func (*DebugLinkMemory) ProtoMessage() {} +func (*DebugLinkMemory) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{70} } + +func (m *DebugLinkMemory) GetMemory() []byte { + if m != nil { + return m.Memory + } + return nil +} + +// * +// Request: Write memory to device. +// WARNING: Writing to the wrong location can irreparably break the device. +type DebugLinkMemoryWrite struct { + Address *uint32 `protobuf:"varint,1,opt,name=address" json:"address,omitempty"` + Memory []byte `protobuf:"bytes,2,opt,name=memory" json:"memory,omitempty"` + Flash *bool `protobuf:"varint,3,opt,name=flash" json:"flash,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DebugLinkMemoryWrite) Reset() { *m = DebugLinkMemoryWrite{} } +func (m *DebugLinkMemoryWrite) String() string { return proto.CompactTextString(m) } +func (*DebugLinkMemoryWrite) ProtoMessage() {} +func (*DebugLinkMemoryWrite) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{71} } + +func (m *DebugLinkMemoryWrite) GetAddress() uint32 { + if m != nil && m.Address != nil { + return *m.Address + } + return 0 +} + +func (m *DebugLinkMemoryWrite) GetMemory() []byte { + if m != nil { + return m.Memory + } + return nil +} + +func (m *DebugLinkMemoryWrite) GetFlash() bool { + if m != nil && m.Flash != nil { + return *m.Flash + } + return false +} + +// * +// Request: Erase block of flash on device +// WARNING: Writing to the wrong location can irreparably break the device. +type DebugLinkFlashErase struct { + Sector *uint32 `protobuf:"varint,1,opt,name=sector" json:"sector,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DebugLinkFlashErase) Reset() { *m = DebugLinkFlashErase{} } +func (m *DebugLinkFlashErase) String() string { return proto.CompactTextString(m) } +func (*DebugLinkFlashErase) ProtoMessage() {} +func (*DebugLinkFlashErase) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{72} } + +func (m *DebugLinkFlashErase) GetSector() uint32 { + if m != nil && m.Sector != nil { + return *m.Sector + } + return 0 +} + +func init() { + proto.RegisterType((*Initialize)(nil), "Initialize") + proto.RegisterType((*GetFeatures)(nil), "GetFeatures") + proto.RegisterType((*Features)(nil), "Features") + proto.RegisterType((*ClearSession)(nil), "ClearSession") + proto.RegisterType((*ApplySettings)(nil), "ApplySettings") + proto.RegisterType((*ApplyFlags)(nil), "ApplyFlags") + proto.RegisterType((*ChangePin)(nil), "ChangePin") + proto.RegisterType((*Ping)(nil), "Ping") + proto.RegisterType((*Success)(nil), "Success") + proto.RegisterType((*Failure)(nil), "Failure") + proto.RegisterType((*ButtonRequest)(nil), "ButtonRequest") + proto.RegisterType((*ButtonAck)(nil), "ButtonAck") + proto.RegisterType((*PinMatrixRequest)(nil), "PinMatrixRequest") + proto.RegisterType((*PinMatrixAck)(nil), "PinMatrixAck") + proto.RegisterType((*Cancel)(nil), "Cancel") + proto.RegisterType((*PassphraseRequest)(nil), "PassphraseRequest") + proto.RegisterType((*PassphraseAck)(nil), "PassphraseAck") + proto.RegisterType((*GetEntropy)(nil), "GetEntropy") + proto.RegisterType((*Entropy)(nil), "Entropy") + proto.RegisterType((*GetPublicKey)(nil), "GetPublicKey") + proto.RegisterType((*PublicKey)(nil), "PublicKey") + proto.RegisterType((*GetAddress)(nil), "GetAddress") + proto.RegisterType((*EthereumGetAddress)(nil), "EthereumGetAddress") + proto.RegisterType((*Address)(nil), "Address") + proto.RegisterType((*EthereumAddress)(nil), "EthereumAddress") + proto.RegisterType((*WipeDevice)(nil), "WipeDevice") + proto.RegisterType((*LoadDevice)(nil), "LoadDevice") + proto.RegisterType((*ResetDevice)(nil), "ResetDevice") + proto.RegisterType((*BackupDevice)(nil), "BackupDevice") + proto.RegisterType((*EntropyRequest)(nil), "EntropyRequest") + proto.RegisterType((*EntropyAck)(nil), "EntropyAck") + proto.RegisterType((*RecoveryDevice)(nil), "RecoveryDevice") + proto.RegisterType((*WordRequest)(nil), "WordRequest") + proto.RegisterType((*WordAck)(nil), "WordAck") + proto.RegisterType((*SignMessage)(nil), "SignMessage") + proto.RegisterType((*VerifyMessage)(nil), "VerifyMessage") + proto.RegisterType((*MessageSignature)(nil), "MessageSignature") + proto.RegisterType((*EncryptMessage)(nil), "EncryptMessage") + proto.RegisterType((*EncryptedMessage)(nil), "EncryptedMessage") + proto.RegisterType((*DecryptMessage)(nil), "DecryptMessage") + proto.RegisterType((*DecryptedMessage)(nil), "DecryptedMessage") + proto.RegisterType((*CipherKeyValue)(nil), "CipherKeyValue") + proto.RegisterType((*CipheredKeyValue)(nil), "CipheredKeyValue") + proto.RegisterType((*EstimateTxSize)(nil), "EstimateTxSize") + proto.RegisterType((*TxSize)(nil), "TxSize") + proto.RegisterType((*SignTx)(nil), "SignTx") + proto.RegisterType((*SimpleSignTx)(nil), "SimpleSignTx") + proto.RegisterType((*TxRequest)(nil), "TxRequest") + proto.RegisterType((*TxAck)(nil), "TxAck") + proto.RegisterType((*EthereumSignTx)(nil), "EthereumSignTx") + proto.RegisterType((*EthereumTxRequest)(nil), "EthereumTxRequest") + proto.RegisterType((*EthereumTxAck)(nil), "EthereumTxAck") + proto.RegisterType((*EthereumSignMessage)(nil), "EthereumSignMessage") + proto.RegisterType((*EthereumVerifyMessage)(nil), "EthereumVerifyMessage") + proto.RegisterType((*EthereumMessageSignature)(nil), "EthereumMessageSignature") + proto.RegisterType((*SignIdentity)(nil), "SignIdentity") + proto.RegisterType((*SignedIdentity)(nil), "SignedIdentity") + proto.RegisterType((*GetECDHSessionKey)(nil), "GetECDHSessionKey") + proto.RegisterType((*ECDHSessionKey)(nil), "ECDHSessionKey") + proto.RegisterType((*SetU2FCounter)(nil), "SetU2FCounter") + proto.RegisterType((*FirmwareErase)(nil), "FirmwareErase") + proto.RegisterType((*FirmwareRequest)(nil), "FirmwareRequest") + proto.RegisterType((*FirmwareUpload)(nil), "FirmwareUpload") + proto.RegisterType((*SelfTest)(nil), "SelfTest") + proto.RegisterType((*DebugLinkDecision)(nil), "DebugLinkDecision") + proto.RegisterType((*DebugLinkGetState)(nil), "DebugLinkGetState") + proto.RegisterType((*DebugLinkState)(nil), "DebugLinkState") + proto.RegisterType((*DebugLinkStop)(nil), "DebugLinkStop") + proto.RegisterType((*DebugLinkLog)(nil), "DebugLinkLog") + proto.RegisterType((*DebugLinkMemoryRead)(nil), "DebugLinkMemoryRead") + proto.RegisterType((*DebugLinkMemory)(nil), "DebugLinkMemory") + proto.RegisterType((*DebugLinkMemoryWrite)(nil), "DebugLinkMemoryWrite") + proto.RegisterType((*DebugLinkFlashErase)(nil), "DebugLinkFlashErase") + proto.RegisterEnum("MessageType", MessageType_name, MessageType_value) +} + +func init() { proto.RegisterFile("messages.proto", fileDescriptor1) } + +var fileDescriptor1 = []byte{ + // 3424 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5a, 0xcb, 0x6f, 0xdc, 0x46, + 0x9a, 0x5f, 0x76, 0xb7, 0xfa, 0xf1, 0x35, 0xbb, 0x55, 0xa2, 0x2d, 0xbb, 0x2d, 0x5b, 0xb6, 0x4c, + 0xc9, 0xb6, 0x64, 0x27, 0xed, 0x44, 0x79, 0x6c, 0xd6, 0xbb, 0x79, 0xc8, 0x7a, 0xd8, 0xde, 0xd8, + 0x8e, 0xc0, 0x56, 0x9c, 0xdb, 0x12, 0x14, 0x59, 0xea, 0xae, 0x55, 0x37, 0xc9, 0xf0, 0xa1, 0xa8, + 0x7d, 0xd8, 0xeb, 0xee, 0x65, 0x81, 0xec, 0x69, 0x73, 0x1a, 0xe4, 0x36, 0x19, 0x04, 0x18, 0x0c, + 0x30, 0x18, 0x60, 0x72, 0x9a, 0x3f, 0x60, 0xfe, 0x8b, 0x39, 0xce, 0x1f, 0x30, 0xe7, 0x41, 0x3d, + 0x48, 0x16, 0x29, 0xb6, 0x6c, 0x27, 0xc0, 0x5c, 0x04, 0xd6, 0x57, 0xbf, 0xfe, 0xea, 0x7b, 0xd5, + 0x57, 0x5f, 0x7d, 0x25, 0xe8, 0x4e, 0x70, 0x18, 0x5a, 0x43, 0x1c, 0xf6, 0xfd, 0xc0, 0x8b, 0xbc, + 0xa5, 0x76, 0x34, 0xf5, 0x93, 0x81, 0xae, 0x02, 0x3c, 0x71, 0x49, 0x44, 0xac, 0x31, 0x79, 0x89, + 0xf5, 0x0e, 0xb4, 0x1f, 0xe1, 0x68, 0x0f, 0x5b, 0x51, 0x1c, 0xe0, 0x50, 0xff, 0x69, 0x0e, 0x9a, + 0xc9, 0x40, 0xbb, 0x04, 0xf5, 0x13, 0xec, 0x3a, 0x5e, 0xd0, 0x53, 0x56, 0x94, 0xf5, 0x96, 0x21, + 0x46, 0xda, 0x2a, 0x74, 0x26, 0xd6, 0x7f, 0x7a, 0x81, 0x79, 0x82, 0x83, 0x90, 0x78, 0x6e, 0xaf, + 0xb2, 0xa2, 0xac, 0x77, 0x0c, 0x95, 0x11, 0x5f, 0x70, 0x1a, 0x03, 0x11, 0x57, 0x02, 0x55, 0x05, + 0x88, 0x12, 0x25, 0x90, 0x6f, 0x45, 0xf6, 0x28, 0x05, 0xd5, 0x38, 0x88, 0x11, 0x13, 0xd0, 0x1d, + 0x98, 0x3f, 0xf4, 0xbc, 0x68, 0xec, 0x59, 0x0e, 0x0e, 0xcc, 0x89, 0xe7, 0xe0, 0xde, 0xdc, 0x8a, + 0xb2, 0xde, 0x34, 0xba, 0x19, 0xf9, 0x99, 0xe7, 0x60, 0xed, 0x2a, 0xb4, 0x1c, 0x7c, 0x42, 0x6c, + 0x6c, 0x12, 0xa7, 0x57, 0x67, 0x22, 0x37, 0x39, 0xe1, 0x89, 0xa3, 0xdd, 0x82, 0xae, 0x4f, 0x5c, + 0x93, 0xda, 0x00, 0xdb, 0x11, 0x5d, 0xab, 0xc1, 0x98, 0x74, 0x7c, 0xe2, 0xee, 0xa7, 0x44, 0xed, + 0x3d, 0x58, 0xf4, 0xad, 0x30, 0xf4, 0x47, 0x81, 0x15, 0x62, 0x19, 0xdd, 0x64, 0xe8, 0x8b, 0xd9, + 0xa4, 0xf4, 0xa3, 0x25, 0x68, 0x8e, 0x2d, 0x77, 0x18, 0x5b, 0x43, 0xdc, 0x6b, 0xf1, 0x75, 0x93, + 0xb1, 0x76, 0x11, 0xe6, 0xc6, 0xd6, 0x21, 0x1e, 0xf7, 0x80, 0x4d, 0xf0, 0x81, 0x76, 0x03, 0xe6, + 0x6c, 0x8f, 0xb8, 0x61, 0xaf, 0xbd, 0x52, 0x5d, 0x6f, 0x6f, 0xb6, 0xfa, 0xdb, 0x1e, 0x71, 0x0f, + 0xa6, 0x3e, 0x36, 0x38, 0x5d, 0x5b, 0x81, 0x36, 0x49, 0xbd, 0xe4, 0xf4, 0x54, 0xb6, 0xba, 0x4c, + 0xa2, 0x8b, 0x06, 0xf8, 0x84, 0x30, 0xb3, 0x75, 0x56, 0x94, 0x75, 0xd5, 0x48, 0xc7, 0x05, 0x93, + 0x8d, 0xac, 0x70, 0xd4, 0xeb, 0x32, 0x88, 0x64, 0xb2, 0xc7, 0x56, 0x38, 0xa2, 0x4c, 0xc8, 0xc4, + 0xf7, 0x82, 0x08, 0x3b, 0xbd, 0x79, 0xb6, 0x46, 0x3a, 0xd6, 0x96, 0x01, 0xa8, 0xc5, 0x6c, 0xcb, + 0x1e, 0x61, 0xa7, 0x87, 0xd8, 0x6c, 0xcb, 0x27, 0xee, 0x36, 0x23, 0x68, 0xf7, 0x60, 0x41, 0xb2, + 0x94, 0x40, 0x2d, 0x30, 0x14, 0xca, 0x26, 0x04, 0x78, 0x03, 0xd0, 0x11, 0x09, 0x26, 0xdf, 0x58, + 0x01, 0x35, 0x2a, 0x0e, 0xb1, 0x1b, 0xf5, 0x34, 0x86, 0x9d, 0x4f, 0xe8, 0xfb, 0x9c, 0xac, 0xdd, + 0x04, 0xd5, 0xc5, 0xd8, 0x09, 0xcd, 0x43, 0xcb, 0x3e, 0x8e, 0xfd, 0xde, 0x05, 0xae, 0x3a, 0xa3, + 0x3d, 0x64, 0x24, 0x6a, 0xd3, 0xa3, 0xb1, 0x35, 0x0c, 0x7b, 0x17, 0x59, 0xb8, 0xf0, 0x81, 0xde, + 0x05, 0x75, 0x7b, 0x8c, 0xad, 0x60, 0x80, 0x43, 0x6a, 0x04, 0xfd, 0x7f, 0x14, 0xe8, 0x6c, 0xf9, + 0xfe, 0x78, 0x3a, 0xc0, 0x51, 0x44, 0xdc, 0x61, 0x98, 0xf3, 0x93, 0x32, 0xcb, 0x4f, 0x15, 0xd9, + 0x4f, 0xb7, 0xa0, 0x1b, 0xd3, 0x38, 0x48, 0xf5, 0x61, 0x61, 0xdc, 0x34, 0x3a, 0x71, 0x88, 0xf7, + 0x53, 0xa2, 0x76, 0x1d, 0x60, 0xe4, 0x4d, 0x70, 0x68, 0x07, 0x18, 0xf3, 0x20, 0x56, 0x0d, 0x89, + 0xa2, 0xeb, 0x00, 0x4c, 0x92, 0x3d, 0x2a, 0x68, 0x26, 0xbe, 0x22, 0x8b, 0xbf, 0x0a, 0xad, 0xed, + 0x91, 0xe5, 0x0e, 0xf1, 0x3e, 0x71, 0xe9, 0xd6, 0x0b, 0xf0, 0xc4, 0x3b, 0xe1, 0x72, 0x36, 0x0d, + 0x31, 0xd2, 0x7f, 0xa3, 0x40, 0x6d, 0x9f, 0xb8, 0x43, 0xad, 0x07, 0x0d, 0xb1, 0xc9, 0x85, 0x26, + 0xc9, 0x90, 0xfa, 0xe5, 0x30, 0x8e, 0x22, 0x2f, 0x17, 0xeb, 0x15, 0xee, 0x17, 0x3e, 0x21, 0x45, + 0xee, 0xd9, 0x5d, 0x51, 0x7d, 0xa3, 0x5d, 0x51, 0x9b, 0xbd, 0x2b, 0xf4, 0x55, 0x68, 0x0c, 0x62, + 0xdb, 0xc6, 0x61, 0x38, 0x5b, 0x5a, 0x7d, 0x17, 0x1a, 0x7b, 0x16, 0x19, 0xc7, 0x01, 0xd6, 0x56, + 0xa0, 0x66, 0xd3, 0xcd, 0x4d, 0x11, 0xdd, 0x4d, 0xb5, 0x2f, 0xe8, 0x6c, 0x57, 0xb0, 0x19, 0x99, + 0x4d, 0x25, 0xcf, 0xe6, 0x73, 0xe8, 0x3c, 0x64, 0xba, 0x19, 0xf8, 0xeb, 0x18, 0x87, 0x91, 0x76, + 0x3b, 0xc7, 0x4c, 0xeb, 0xe7, 0x66, 0x25, 0x96, 0x1a, 0xd4, 0x1c, 0x2b, 0xb2, 0x04, 0x3f, 0xf6, + 0xad, 0xb7, 0xa1, 0xc5, 0xe1, 0x5b, 0xf6, 0xb1, 0xfe, 0x31, 0xa0, 0x7d, 0xe2, 0x3e, 0xb3, 0xa2, + 0x80, 0x9c, 0x26, 0xcc, 0x37, 0xa0, 0x46, 0x33, 0xaa, 0x60, 0xbe, 0xd8, 0x2f, 0x02, 0x38, 0x7f, + 0x0a, 0xd1, 0x57, 0x40, 0x4d, 0x67, 0xb7, 0xec, 0x63, 0x0d, 0x41, 0xd5, 0x27, 0x6e, 0x4f, 0x59, + 0xa9, 0xac, 0xb7, 0x0c, 0xfa, 0xa9, 0x37, 0xa1, 0xbe, 0x6d, 0xb9, 0x36, 0x1e, 0xeb, 0x17, 0x60, + 0x21, 0x8b, 0x29, 0xc1, 0x4a, 0xbf, 0x0f, 0x9d, 0x8c, 0x48, 0x39, 0x5c, 0x07, 0x90, 0xc2, 0x91, + 0x33, 0x92, 0x28, 0xfa, 0x0a, 0xc0, 0x23, 0x1c, 0xed, 0xba, 0x51, 0xe0, 0xf9, 0x53, 0xaa, 0x5f, + 0x48, 0x5e, 0x72, 0x5c, 0xc7, 0x60, 0xdf, 0xd4, 0x31, 0xc9, 0x74, 0x0f, 0x1a, 0x98, 0x7f, 0x32, + 0x84, 0x6a, 0x24, 0x43, 0xfd, 0x57, 0x0a, 0xa8, 0x8f, 0x70, 0xb4, 0x1f, 0x1f, 0x8e, 0x89, 0xfd, + 0x39, 0x9e, 0xd2, 0xec, 0x6a, 0x39, 0x4e, 0x80, 0xc3, 0xd0, 0xa4, 0xf2, 0x57, 0xd7, 0x3b, 0x46, + 0x53, 0x10, 0x9e, 0x6b, 0xeb, 0x80, 0xb0, 0xed, 0x84, 0x96, 0x69, 0xc7, 0xc1, 0x09, 0x36, 0x5d, + 0x6b, 0x92, 0xb8, 0xa8, 0xcb, 0xe8, 0xdb, 0x94, 0xfc, 0xdc, 0x9a, 0x60, 0xba, 0xbd, 0xc3, 0x91, + 0xf7, 0x8d, 0xe9, 0x90, 0xd0, 0x1f, 0x5b, 0x53, 0x11, 0x6f, 0x6d, 0x4a, 0xdb, 0xe1, 0x24, 0x6d, + 0x0d, 0x5a, 0x34, 0x09, 0x72, 0x2e, 0x34, 0xc2, 0x5a, 0x0f, 0x1a, 0x0f, 0x49, 0x44, 0x69, 0x46, + 0x93, 0xfe, 0xa5, 0x8c, 0xf4, 0xcf, 0xa0, 0x95, 0x09, 0x77, 0x03, 0x6a, 0x2e, 0x77, 0x77, 0x65, + 0xbd, 0xbd, 0xd9, 0xee, 0x3f, 0xde, 0x79, 0xee, 0x39, 0x22, 0x74, 0x5c, 0xe1, 0xe7, 0x53, 0x3f, + 0x3e, 0x4c, 0xfc, 0x4c, 0xbf, 0xf5, 0xbf, 0x2a, 0xcc, 0x54, 0x5b, 0x5c, 0x89, 0xf3, 0x15, 0xcc, + 0xc9, 0x54, 0x99, 0x21, 0xd3, 0xeb, 0x28, 0xf7, 0x01, 0x34, 0x27, 0xf1, 0x38, 0x22, 0x21, 0x19, + 0x32, 0xdd, 0xda, 0x9b, 0x57, 0xfa, 0xcf, 0x04, 0xc1, 0xc0, 0x0e, 0xc6, 0x93, 0x81, 0x1d, 0x10, + 0x9f, 0xc7, 0x50, 0x0a, 0xd5, 0x3e, 0x85, 0x76, 0xc8, 0xe8, 0x26, 0x8b, 0xbc, 0x39, 0x16, 0x79, + 0xa8, 0xff, 0xc4, 0xf5, 0xe3, 0x28, 0xfb, 0xc1, 0x03, 0x75, 0xb0, 0xbf, 0xfb, 0x7c, 0x67, 0x6b, + 0x67, 0xc7, 0xd8, 0x1d, 0x0c, 0x0c, 0x08, 0xd3, 0x19, 0xfd, 0x00, 0xb4, 0xdd, 0x68, 0x84, 0x03, + 0x1c, 0x4f, 0x5e, 0x57, 0xe7, 0xa2, 0x36, 0x95, 0x33, 0xda, 0xd0, 0x50, 0x4a, 0x58, 0xf5, 0xa0, + 0x21, 0x7e, 0x29, 0x82, 0x32, 0x19, 0xea, 0xf7, 0x60, 0x3e, 0x59, 0x7a, 0x06, 0x58, 0xcd, 0xc0, + 0x2a, 0xc0, 0x57, 0xc4, 0xc7, 0x3b, 0xec, 0xdc, 0xd6, 0xff, 0xaf, 0x02, 0xf0, 0xd4, 0xb3, 0x1c, + 0x3e, 0xa4, 0x09, 0x7c, 0xe2, 0xe2, 0x89, 0xe7, 0x12, 0x3b, 0x49, 0xe0, 0xc9, 0x38, 0x0d, 0x81, + 0x0a, 0x33, 0x6a, 0x49, 0x08, 0x88, 0xad, 0x57, 0x65, 0xbf, 0xa3, 0x9f, 0x3f, 0x2b, 0xad, 0x69, + 0xab, 0xd2, 0x21, 0x32, 0xc7, 0x03, 0x01, 0xbb, 0xc3, 0x31, 0x09, 0x47, 0x65, 0xa7, 0x49, 0x5d, + 0x3e, 0x4d, 0x56, 0xa1, 0x13, 0x1e, 0x13, 0xdf, 0xb4, 0x47, 0xd8, 0x3e, 0x0e, 0xe3, 0x89, 0x28, + 0x41, 0x54, 0x4a, 0xdc, 0x16, 0x34, 0xed, 0x06, 0xb4, 0xe3, 0xcd, 0x23, 0xd3, 0xf6, 0x62, 0x37, + 0xc2, 0x01, 0xab, 0x3b, 0x3a, 0x06, 0xc4, 0x9b, 0x47, 0xdb, 0x9c, 0xa2, 0xff, 0xb6, 0x02, 0x6d, + 0x03, 0x87, 0x38, 0x12, 0x46, 0xb9, 0x05, 0x5d, 0xe1, 0x21, 0x33, 0xb0, 0x5c, 0xc7, 0x9b, 0x88, + 0x33, 0xa3, 0x23, 0xa8, 0x06, 0x23, 0x6a, 0x37, 0xa0, 0x19, 0x46, 0x01, 0x76, 0x87, 0xd1, 0x88, + 0x17, 0x6c, 0x0f, 0xaa, 0x9b, 0x1f, 0x7c, 0x68, 0xa4, 0xc4, 0xd9, 0xd6, 0xa8, 0x9e, 0x63, 0x8d, + 0xb3, 0x07, 0x48, 0xad, 0xec, 0x00, 0xf9, 0x05, 0x46, 0x2b, 0xd8, 0xa3, 0x51, 0xb4, 0x07, 0x05, + 0x30, 0xab, 0x8a, 0x7a, 0x81, 0x17, 0x6a, 0x40, 0x49, 0xbc, 0x5c, 0xa0, 0x85, 0x01, 0xff, 0x12, + 0x41, 0x85, 0xa0, 0x2b, 0xf2, 0x5f, 0x92, 0x64, 0x6f, 0x03, 0x08, 0x0a, 0xcd, 0xb0, 0xb9, 0xa4, + 0xa8, 0xc8, 0x49, 0xf1, 0x4f, 0x15, 0xe8, 0x1a, 0xd8, 0xf6, 0x4e, 0x70, 0x30, 0x15, 0xd6, 0x5f, + 0x06, 0xf8, 0xc6, 0x0b, 0x1c, 0x2e, 0x9f, 0x38, 0xd1, 0x5b, 0x94, 0xc2, 0xc4, 0x9b, 0x6d, 0xd4, + 0xca, 0x1b, 0x19, 0xb5, 0xfa, 0x2a, 0xa3, 0xd6, 0x5e, 0x69, 0xd4, 0x39, 0xd9, 0xa8, 0x1b, 0x80, + 0xb0, 0x7b, 0xe4, 0x05, 0x36, 0x36, 0xa9, 0xac, 0x63, 0x12, 0x46, 0xcc, 0xea, 0x4d, 0x63, 0x5e, + 0xd0, 0xbf, 0x12, 0x64, 0x9a, 0x39, 0x59, 0xca, 0xe1, 0x81, 0xc8, 0xbe, 0x8b, 0x3e, 0x69, 0x9d, + 0xf1, 0xc9, 0x65, 0x68, 0x38, 0xc1, 0xd4, 0x0c, 0x62, 0x97, 0xd5, 0xbd, 0x4d, 0xa3, 0xee, 0x04, + 0x53, 0x23, 0x76, 0xf5, 0xf7, 0xa0, 0x4d, 0x39, 0x27, 0x27, 0xe9, 0x5a, 0xee, 0x24, 0x45, 0x7d, + 0x69, 0x4e, 0x3a, 0x44, 0x97, 0xa1, 0x41, 0x27, 0xa8, 0x6f, 0x34, 0xa8, 0x51, 0x81, 0x45, 0x8a, + 0x61, 0xdf, 0xfa, 0x8f, 0x0a, 0xb4, 0x07, 0x64, 0xe8, 0x3e, 0x13, 0x15, 0xd0, 0xb9, 0x49, 0x2d, + 0x57, 0x43, 0xb0, 0xcc, 0x93, 0x14, 0x4e, 0xb9, 0x14, 0x5f, 0x9d, 0x95, 0xe2, 0x0b, 0x89, 0xb8, + 0xf6, 0xc6, 0x89, 0xf8, 0xbf, 0x15, 0xe8, 0xbc, 0xc0, 0x01, 0x39, 0x9a, 0x26, 0xf2, 0xe6, 0x92, + 0xa1, 0x22, 0x65, 0x4e, 0xed, 0x1a, 0xb4, 0x42, 0x32, 0x74, 0xd9, 0x7d, 0x8c, 0x45, 0x8c, 0x6a, + 0x64, 0x04, 0x59, 0x95, 0x2a, 0x8f, 0xd3, 0x52, 0x55, 0x66, 0x9e, 0xa0, 0xff, 0x0e, 0x48, 0x88, + 0x30, 0x90, 0x79, 0xfe, 0x1c, 0x59, 0xf4, 0x1f, 0x14, 0xba, 0xa9, 0xec, 0x60, 0xea, 0x47, 0x89, + 0x5a, 0x97, 0xa0, 0xee, 0xc7, 0x87, 0xc7, 0x38, 0xd9, 0x45, 0x62, 0x54, 0xac, 0xe2, 0x24, 0xb1, + 0x6f, 0x82, 0x9a, 0x64, 0x32, 0xcf, 0x1d, 0xa7, 0xc7, 0xa7, 0xa0, 0x7d, 0xe1, 0x8e, 0x0b, 0x55, + 0x48, 0xed, 0xbc, 0x43, 0x7a, 0x6e, 0x96, 0xda, 0x2f, 0x00, 0x09, 0x49, 0xb1, 0x93, 0xc8, 0x7a, + 0x11, 0xe6, 0x5c, 0xcf, 0xb5, 0xb1, 0x10, 0x95, 0x0f, 0xce, 0x91, 0x54, 0x83, 0xda, 0x68, 0x62, + 0xd9, 0xc2, 0xee, 0xec, 0x5b, 0xff, 0x1a, 0xba, 0x3b, 0x38, 0x67, 0x81, 0x73, 0x03, 0x31, 0x5d, + 0xb2, 0x32, 0x63, 0xc9, 0x6a, 0xf9, 0x92, 0x35, 0x69, 0xc9, 0x3d, 0x40, 0x62, 0xc9, 0x4c, 0x95, + 0x42, 0xad, 0x2d, 0x71, 0x90, 0x7c, 0x5b, 0xc9, 0xf9, 0x56, 0xff, 0xb3, 0x02, 0xdd, 0x6d, 0xe2, + 0x8f, 0x70, 0xf0, 0x39, 0x9e, 0xbe, 0xb0, 0xc6, 0xf1, 0x2b, 0x64, 0x47, 0x50, 0xa5, 0x7e, 0xe5, + 0x5c, 0xe8, 0x27, 0xd5, 0xe6, 0x84, 0xfe, 0x4e, 0x48, 0xcd, 0x07, 0x3c, 0x93, 0x32, 0xf9, 0xc4, + 0xb1, 0x90, 0x0c, 0xb5, 0x35, 0xe8, 0x5a, 0xe1, 0xb1, 0xe9, 0xb9, 0x66, 0x02, 0xe0, 0x77, 0x7a, + 0xd5, 0x0a, 0x8f, 0xbf, 0x70, 0x77, 0xcf, 0xa0, 0x1c, 0xae, 0xa6, 0x48, 0x52, 0x1c, 0x25, 0x54, + 0xd7, 0xba, 0x50, 0x21, 0x27, 0xec, 0x60, 0x50, 0x8d, 0x0a, 0x39, 0xd1, 0xd7, 0x01, 0x71, 0x65, + 0xb0, 0x93, 0xaa, 0x93, 0xca, 0xa7, 0x48, 0xf2, 0xe9, 0xff, 0x05, 0xdd, 0xdd, 0x30, 0x22, 0x13, + 0x2b, 0xc2, 0x07, 0xa7, 0x03, 0xf2, 0x12, 0xd3, 0x23, 0xda, 0x8b, 0x23, 0x3f, 0x8e, 0xc2, 0x34, + 0xa3, 0xd3, 0xc2, 0x59, 0x15, 0x44, 0x9e, 0xd4, 0x6f, 0x82, 0x4a, 0x5c, 0x09, 0x53, 0x61, 0x98, + 0x36, 0xa7, 0x71, 0xc8, 0x6b, 0x25, 0x13, 0xfd, 0x26, 0xd4, 0xc5, 0xba, 0x97, 0xa1, 0x11, 0x9d, + 0x9a, 0xa2, 0x54, 0xa7, 0xd9, 0xb4, 0x1e, 0xb1, 0x09, 0xfd, 0xf7, 0x0a, 0xd4, 0xe9, 0xf6, 0x3c, + 0x38, 0xfd, 0xc7, 0xca, 0xa6, 0x5d, 0x85, 0x46, 0xae, 0x2b, 0xf3, 0x40, 0x79, 0xd7, 0x48, 0x28, + 0xda, 0x75, 0x68, 0x8d, 0x3d, 0xfb, 0xd8, 0x8c, 0x88, 0xd8, 0x69, 0x9d, 0x07, 0xca, 0x3b, 0x46, + 0x93, 0xd2, 0x0e, 0xc8, 0x04, 0xeb, 0x7f, 0x53, 0x40, 0x1d, 0x90, 0x89, 0x3f, 0xc6, 0x42, 0xf6, + 0x35, 0xa8, 0x73, 0x11, 0x58, 0x2c, 0xb5, 0x37, 0xd5, 0xfe, 0xc1, 0x29, 0xcb, 0x99, 0x2c, 0xcd, + 0x8b, 0x39, 0xed, 0x0e, 0x34, 0x84, 0x32, 0xbd, 0x0a, 0x83, 0x75, 0xfa, 0x07, 0xa7, 0x5f, 0x30, + 0x0a, 0xc3, 0x25, 0xb3, 0xda, 0xfb, 0xa0, 0x46, 0x81, 0xe5, 0x86, 0x16, 0x3b, 0x09, 0xc3, 0x5e, + 0x95, 0xa1, 0x51, 0xff, 0x20, 0x23, 0xb2, 0x1f, 0xe4, 0x50, 0xaf, 0x97, 0x16, 0x65, 0xc5, 0xe7, + 0xce, 0x57, 0xbc, 0x7e, 0x56, 0xf1, 0x5f, 0x2b, 0xd0, 0x3a, 0x48, 0x2f, 0x8a, 0xf7, 0x41, 0x0d, + 0xf8, 0xa7, 0x29, 0x1d, 0x73, 0x6a, 0x5f, 0x3e, 0xe2, 0xda, 0x41, 0x36, 0xd0, 0xee, 0x43, 0xc3, + 0xc1, 0x91, 0x45, 0xc6, 0xa1, 0xa8, 0x63, 0x17, 0xfb, 0x29, 0xb7, 0x1d, 0x3e, 0xc1, 0x0d, 0x21, + 0x50, 0xda, 0x47, 0x00, 0x21, 0x0e, 0x92, 0x36, 0x51, 0x95, 0xfd, 0xa6, 0x97, 0xfd, 0x66, 0x90, + 0xce, 0xb1, 0x9f, 0x49, 0x58, 0x7d, 0x03, 0xe6, 0x0e, 0xd8, 0x95, 0x74, 0x05, 0x2a, 0xd1, 0x29, + 0x13, 0xad, 0xcc, 0x82, 0x95, 0xe8, 0x54, 0xff, 0xdf, 0x0a, 0x74, 0x93, 0x0a, 0x5e, 0xf8, 0xf3, + 0x67, 0xa4, 0xb6, 0xab, 0xd0, 0x1a, 0x5a, 0xa1, 0xe9, 0x07, 0xc4, 0x4e, 0xd2, 0x44, 0x73, 0x68, + 0x85, 0xfb, 0x74, 0x9c, 0x4c, 0x8e, 0xc9, 0x84, 0x44, 0x22, 0xc5, 0xd1, 0xc9, 0xa7, 0x74, 0x4c, + 0x37, 0x78, 0xe4, 0x31, 0x67, 0xa8, 0x46, 0x25, 0xf2, 0xb2, 0xcd, 0x5c, 0x97, 0x93, 0xcd, 0x5b, + 0xa0, 0xd1, 0xeb, 0xbb, 0x29, 0x9a, 0x64, 0xa6, 0x3d, 0x8a, 0xdd, 0x63, 0x91, 0x16, 0x10, 0x9d, + 0x11, 0x6d, 0xcf, 0x6d, 0x4a, 0xa7, 0x25, 0x0c, 0x43, 0x8f, 0x79, 0x45, 0x2c, 0xca, 0x6c, 0x4a, + 0x7a, 0xca, 0xcb, 0xe1, 0x2b, 0xd0, 0xb4, 0x47, 0x16, 0x71, 0x4d, 0xe2, 0x88, 0x02, 0xa7, 0xc1, + 0xc6, 0x4f, 0x1c, 0xfd, 0xff, 0x15, 0x58, 0x48, 0xec, 0x91, 0x39, 0xbb, 0xc0, 0x51, 0x39, 0xc3, + 0x91, 0x16, 0xaa, 0xc9, 0x81, 0x69, 0x9e, 0x88, 0xae, 0x29, 0xa4, 0xa4, 0x17, 0x79, 0x40, 0x20, + 0x6c, 0x94, 0x01, 0x8c, 0x3c, 0x20, 0x4c, 0x1a, 0x4d, 0x29, 0x69, 0xa0, 0xf7, 0xa1, 0x93, 0x09, + 0x46, 0x9d, 0xbb, 0x0c, 0x4c, 0x02, 0x61, 0x0c, 0x9e, 0xfc, 0x5a, 0x94, 0xc2, 0xac, 0xa0, 0x3f, + 0x85, 0x0b, 0xb2, 0x63, 0x7f, 0x59, 0x05, 0xa5, 0x13, 0x58, 0x4c, 0xb8, 0x9d, 0x5b, 0xe1, 0xa8, + 0xbf, 0xb8, 0xc2, 0xd1, 0x0d, 0xe8, 0x25, 0x4b, 0xbd, 0xaa, 0x86, 0x79, 0xdd, 0xd5, 0xf4, 0x9f, + 0x58, 0xd2, 0x1a, 0xba, 0x4f, 0x1c, 0xec, 0x46, 0x24, 0x9a, 0x6a, 0x1b, 0xd0, 0x24, 0xe2, 0x5b, + 0xec, 0x8f, 0x4e, 0x3f, 0x99, 0xe4, 0xf7, 0x73, 0x92, 0x41, 0x91, 0x3d, 0xb2, 0xc6, 0xd4, 0xf7, + 0xd8, 0x1c, 0x11, 0xc7, 0xc1, 0xae, 0x58, 0x60, 0x3e, 0xa5, 0x3f, 0x66, 0xe4, 0x3c, 0xf4, 0x84, + 0x84, 0xb1, 0x35, 0x16, 0x97, 0xd2, 0x0c, 0xfa, 0x82, 0x91, 0x4b, 0xdb, 0x2a, 0xb5, 0xb2, 0xb6, + 0x8a, 0x3e, 0x84, 0x2e, 0x15, 0x1d, 0x3b, 0xa9, 0xf0, 0xb3, 0x2b, 0xb9, 0x65, 0x00, 0x9f, 0x75, + 0x4e, 0xcc, 0xe4, 0x10, 0x57, 0x8d, 0x96, 0x9f, 0xf6, 0x52, 0x72, 0x46, 0xaa, 0x16, 0x8d, 0xf4, + 0xad, 0x02, 0x0b, 0x8f, 0x70, 0xb4, 0xbb, 0xbd, 0xf3, 0x58, 0x34, 0x5a, 0xe9, 0x6f, 0xde, 0xc0, + 0x52, 0xb7, 0x61, 0xde, 0xc7, 0x38, 0x30, 0xcf, 0x88, 0xd0, 0xa1, 0xe4, 0xac, 0xa5, 0x53, 0xa6, + 0x7b, 0xb5, 0x54, 0xf7, 0x77, 0xa1, 0x5b, 0x10, 0x87, 0xee, 0x13, 0x3e, 0x32, 0xb3, 0xfa, 0x13, + 0xc2, 0x14, 0xa0, 0xbf, 0x03, 0x9d, 0x01, 0x8e, 0xbe, 0xdc, 0xdc, 0x93, 0x2e, 0x91, 0xf2, 0x8d, + 0x46, 0x39, 0x73, 0xeb, 0xbe, 0x03, 0x9d, 0x3d, 0xd1, 0xa9, 0xde, 0x65, 0x3d, 0xdf, 0x4b, 0x50, + 0xcf, 0xed, 0x74, 0x31, 0xd2, 0xb7, 0x60, 0x3e, 0x01, 0x26, 0x99, 0xe1, 0x12, 0xd4, 0xbd, 0xa3, + 0xa3, 0x10, 0x27, 0xf7, 0x43, 0x31, 0x92, 0x58, 0x54, 0x72, 0x2c, 0x3e, 0x81, 0x6e, 0xc2, 0xe2, + 0x4b, 0x7f, 0xec, 0x59, 0x0e, 0x75, 0xa6, 0x6f, 0x4d, 0xe9, 0x67, 0xd2, 0x2f, 0x11, 0x43, 0x56, + 0x16, 0x5a, 0xe1, 0x48, 0xd8, 0x90, 0x7d, 0xeb, 0x6b, 0xd0, 0x1c, 0xe0, 0xf1, 0xd1, 0x01, 0x5d, + 0x3b, 0xf7, 0x4b, 0x45, 0xfa, 0xa5, 0x7e, 0x17, 0x16, 0x76, 0xf0, 0x61, 0x3c, 0x7c, 0x4a, 0xdc, + 0xe3, 0x1d, 0x6c, 0xf3, 0x97, 0x83, 0x45, 0xa8, 0x4f, 0x71, 0x68, 0xba, 0x1e, 0x5b, 0xa7, 0x69, + 0xcc, 0x4d, 0x71, 0xf8, 0xdc, 0xd3, 0x2f, 0x48, 0xd8, 0x47, 0x38, 0x1a, 0x44, 0x56, 0x84, 0xf5, + 0xbf, 0x54, 0x68, 0xc5, 0x2b, 0xa8, 0x8c, 0xc4, 0x34, 0xb2, 0xa6, 0x5e, 0x1c, 0x25, 0x35, 0x3f, + 0x1f, 0x25, 0xbd, 0x97, 0x4a, 0xd6, 0x7b, 0xb9, 0x04, 0xf5, 0x09, 0xeb, 0x8a, 0x0a, 0xa7, 0x8a, + 0x51, 0xae, 0xc5, 0x53, 0x9b, 0xd1, 0xe2, 0x99, 0x9b, 0xd5, 0xe2, 0x99, 0x79, 0xdb, 0xae, 0x9f, + 0x73, 0xdb, 0x5e, 0x06, 0x08, 0x70, 0x88, 0x23, 0x76, 0x13, 0x66, 0xe7, 0x45, 0xcb, 0x68, 0x31, + 0x0a, 0xbd, 0x74, 0xd2, 0xaa, 0x8b, 0x4f, 0x27, 0x3d, 0x81, 0x26, 0xd3, 0x4c, 0x65, 0xc4, 0xa4, + 0x8f, 0xfa, 0x16, 0x68, 0x81, 0xe8, 0x0b, 0x98, 0x47, 0xd6, 0x31, 0xbf, 0x55, 0x8b, 0xb7, 0x20, + 0x94, 0xcc, 0xec, 0x59, 0xc7, 0xec, 0x5a, 0xad, 0xdd, 0x85, 0x85, 0x14, 0xcd, 0x9a, 0x07, 0xbe, + 0x17, 0xb2, 0x7b, 0x72, 0xc7, 0x98, 0x4f, 0x26, 0x28, 0x70, 0xdf, 0x0b, 0xf5, 0x79, 0xe8, 0x48, + 0x36, 0xf6, 0x7c, 0x7d, 0x1f, 0xd4, 0x94, 0xf0, 0xd4, 0x1b, 0xb2, 0x0b, 0x3e, 0x3e, 0xc1, 0xe3, + 0xe4, 0x35, 0x81, 0x0d, 0xa8, 0x79, 0x0f, 0x63, 0xfb, 0x18, 0x47, 0xc2, 0xe6, 0x62, 0xc4, 0x6e, + 0xf3, 0xf8, 0x34, 0x12, 0x46, 0x67, 0xdf, 0xfa, 0x23, 0xb8, 0x90, 0x72, 0x7c, 0x86, 0x27, 0x5e, + 0x30, 0x35, 0x30, 0x8f, 0x39, 0x39, 0x81, 0x74, 0xb2, 0x04, 0x32, 0x2b, 0x6e, 0x37, 0x60, 0xbe, + 0xc0, 0x88, 0xb9, 0x99, 0x7d, 0x25, 0x01, 0xc1, 0x47, 0xfa, 0x7f, 0xc0, 0xc5, 0x02, 0xf4, 0xab, + 0x80, 0x44, 0xf8, 0xfc, 0x45, 0x05, 0xa7, 0x8a, 0xcc, 0x49, 0xbc, 0xa6, 0x84, 0x23, 0x71, 0x5b, + 0xe4, 0x03, 0xfd, 0x6d, 0x49, 0xa7, 0x3d, 0x4a, 0x49, 0x37, 0x6d, 0x88, 0xed, 0xc8, 0x4b, 0x76, + 0xb8, 0x18, 0xdd, 0xfd, 0x71, 0x11, 0xda, 0xe2, 0x1c, 0x61, 0x75, 0xd8, 0x0a, 0x5c, 0x92, 0x86, + 0x66, 0xf6, 0x60, 0x8a, 0xfe, 0x69, 0xa9, 0xf6, 0xed, 0x1f, 0x7a, 0x8a, 0xb6, 0x94, 0x5e, 0x9e, + 0x19, 0x62, 0x9f, 0xb8, 0x43, 0xa4, 0x88, 0xb9, 0x65, 0xb8, 0x20, 0xcf, 0x89, 0x57, 0x10, 0x54, + 0x59, 0xaa, 0x7d, 0x57, 0x32, 0x2d, 0xde, 0x39, 0x50, 0x55, 0x4c, 0xdf, 0x80, 0x45, 0x79, 0x3a, + 0x7d, 0x14, 0x42, 0x35, 0xc1, 0xbe, 0x20, 0x5c, 0xd6, 0x2e, 0x45, 0x73, 0x02, 0x71, 0x07, 0xae, + 0xe4, 0x56, 0x90, 0x13, 0x17, 0xaa, 0x2f, 0x35, 0x29, 0xe8, 0x8f, 0x14, 0xb8, 0x0e, 0x4b, 0x65, + 0x40, 0x9e, 0x75, 0x50, 0x43, 0x42, 0x6e, 0xc0, 0xd5, 0x32, 0xa4, 0x48, 0x71, 0xa8, 0xb9, 0xd4, + 0xfc, 0x2e, 0x81, 0x16, 0xe4, 0xcb, 0x5e, 0x23, 0x50, 0xab, 0xdc, 0x40, 0xc9, 0x34, 0x08, 0x0b, + 0xe8, 0xd0, 0x2b, 0x30, 0x48, 0x8f, 0x05, 0xd4, 0x16, 0x2c, 0x0a, 0x56, 0xca, 0x00, 0xaa, 0x60, + 0x52, 0x90, 0x22, 0xeb, 0x22, 0xa3, 0x8e, 0x60, 0x71, 0x13, 0x2e, 0xcb, 0x08, 0xa9, 0xa7, 0x8a, + 0xba, 0x02, 0x72, 0x0d, 0xb4, 0x9c, 0x27, 0x59, 0xf1, 0x8b, 0xe6, 0xc5, 0xec, 0x5a, 0x5e, 0x4e, + 0xf9, 0xc2, 0x83, 0xd0, 0x52, 0x9d, 0x62, 0x9a, 0x8a, 0x76, 0x1d, 0x2e, 0xe6, 0x2c, 0x27, 0x9e, + 0xd7, 0xd1, 0x82, 0x10, 0xf4, 0x36, 0x5c, 0x2b, 0x44, 0x52, 0xee, 0x31, 0x09, 0x69, 0x29, 0xae, + 0x57, 0x8a, 0xdb, 0xb2, 0x8f, 0xd1, 0x05, 0xee, 0xa9, 0xdf, 0x95, 0xc8, 0xcc, 0x1f, 0x97, 0xd0, + 0xc5, 0x72, 0xbb, 0xa5, 0xe5, 0x2b, 0x5a, 0x14, 0xcb, 0x5c, 0x85, 0x85, 0x3c, 0x80, 0xf2, 0xbf, + 0x94, 0x6a, 0x9c, 0x8b, 0x97, 0x7c, 0xcf, 0x00, 0x5d, 0x16, 0xa8, 0x82, 0xff, 0xe4, 0x57, 0x59, + 0xd4, 0x13, 0x98, 0xd5, 0x7c, 0x88, 0xe6, 0x1e, 0x6a, 0xd1, 0x95, 0x72, 0x50, 0xee, 0x11, 0x0f, + 0x2d, 0x09, 0x81, 0x57, 0xf3, 0x1a, 0xa5, 0x4f, 0x77, 0xe8, 0xaa, 0x64, 0x94, 0x42, 0x34, 0x64, + 0xaf, 0xb1, 0xe8, 0x5a, 0xf9, 0xae, 0xca, 0x1e, 0x49, 0xd0, 0x72, 0x79, 0xd4, 0x26, 0xd3, 0xd7, + 0xd3, 0xa8, 0xcd, 0xf9, 0x39, 0x39, 0x81, 0xd1, 0x8a, 0xb4, 0x8b, 0x0a, 0x96, 0x91, 0xdb, 0xd2, + 0x48, 0x2f, 0xb7, 0x71, 0xbe, 0x55, 0x8d, 0x56, 0xcb, 0xc3, 0x3b, 0x6b, 0x5f, 0xa3, 0xb5, 0xf2, + 0xf0, 0x96, 0xea, 0x7b, 0x74, 0xbb, 0xdc, 0xbe, 0xb9, 0xa2, 0x1d, 0xdd, 0x11, 0xa0, 0x42, 0x7c, + 0x16, 0xcb, 0x6d, 0xb4, 0x2e, 0x24, 0xba, 0x03, 0xcb, 0xb9, 0xf8, 0x2c, 0x3e, 0x65, 0xa2, 0x8d, + 0x14, 0x78, 0xa5, 0x1c, 0x48, 0xa5, 0xbf, 0x2b, 0x39, 0xed, 0x76, 0xc1, 0x12, 0xb9, 0x56, 0x0d, + 0xba, 0x27, 0xed, 0x30, 0x2d, 0x1f, 0xb2, 0x6c, 0xfe, 0xad, 0xa5, 0xfa, 0x77, 0x7c, 0xbe, 0x60, + 0xd1, 0x7c, 0x07, 0x1f, 0xbd, 0x5d, 0x6e, 0x2f, 0xa9, 0x15, 0x8d, 0xfa, 0xe5, 0x99, 0x5b, 0x34, + 0xa5, 0xd1, 0xfd, 0x72, 0x4b, 0x15, 0x9b, 0x50, 0xe8, 0x9d, 0x74, 0x27, 0x17, 0x3c, 0x2c, 0x77, + 0x0d, 0xd1, 0xbb, 0xa9, 0x5e, 0xeb, 0x79, 0x7e, 0xc5, 0xae, 0x25, 0xda, 0x4c, 0x35, 0x2c, 0x70, + 0xcc, 0xf7, 0x21, 0xd1, 0x7b, 0xb3, 0x38, 0x16, 0x9b, 0x87, 0xe8, 0xfd, 0x94, 0xa3, 0x5e, 0xcc, + 0x6d, 0xd9, 0xbd, 0x08, 0x7d, 0x50, 0x1e, 0xa9, 0xf9, 0x0b, 0x08, 0xfa, 0x50, 0x68, 0x5b, 0xb0, + 0xab, 0xf4, 0xef, 0x46, 0xe8, 0x9f, 0x05, 0xa3, 0x75, 0xb8, 0x9e, 0x53, 0xf4, 0xcc, 0x43, 0x25, + 0xfa, 0x48, 0x20, 0x6f, 0xe5, 0x8f, 0xa1, 0xc2, 0xbb, 0x22, 0xfa, 0x17, 0xb1, 0x66, 0x71, 0x0f, + 0xe5, 0x9a, 0x17, 0xe8, 0x41, 0x7a, 0x4c, 0x2e, 0x97, 0xa1, 0xb2, 0x9c, 0xf8, 0xaf, 0x69, 0x8a, + 0xb9, 0x52, 0x0e, 0xa4, 0xde, 0xff, 0xb7, 0x72, 0x6e, 0x67, 0x2e, 0x49, 0xe8, 0xe3, 0x19, 0x1b, + 0x3c, 0x8f, 0xfa, 0xa4, 0x7c, 0xcd, 0xdc, 0x75, 0x05, 0x7d, 0x2a, 0x58, 0x6d, 0xc0, 0x8d, 0x59, + 0x7a, 0x26, 0x2e, 0xfd, 0x4c, 0x40, 0xef, 0xc1, 0xcd, 0x32, 0x68, 0x7e, 0xcf, 0x6f, 0x09, 0x70, + 0x1f, 0xd6, 0xca, 0xc0, 0x67, 0xf6, 0xfe, 0x43, 0x21, 0xec, 0xbd, 0xbc, 0xee, 0x67, 0xee, 0x15, + 0xc8, 0x59, 0x6a, 0x7e, 0x9f, 0x6c, 0xeb, 0x3b, 0x33, 0xc0, 0xc9, 0xc5, 0x02, 0xe1, 0xa5, 0xda, + 0xf7, 0x25, 0x86, 0xca, 0xdf, 0x35, 0xd0, 0xd1, 0x52, 0xed, 0x87, 0x12, 0x43, 0xe5, 0xaa, 0x65, + 0x34, 0x14, 0xac, 0x0a, 0xe1, 0x2c, 0x57, 0xd0, 0x68, 0x24, 0x18, 0x15, 0x8c, 0x59, 0x52, 0x13, + 0x23, 0x57, 0xb0, 0x2b, 0x84, 0x61, 0x01, 0x8a, 0x3c, 0xc1, 0xf1, 0x2e, 0xac, 0x9c, 0x03, 0x63, + 0x15, 0x2f, 0xf2, 0x05, 0xcb, 0x59, 0xab, 0x67, 0xd5, 0x2b, 0xfa, 0x9a, 0x43, 0x1f, 0xbe, 0x0f, + 0xab, 0xb6, 0x37, 0xe9, 0x87, 0x56, 0xe4, 0x85, 0x23, 0x32, 0xb6, 0x0e, 0xc3, 0x7e, 0x14, 0xe0, + 0x97, 0x5e, 0xd0, 0x1f, 0x93, 0x43, 0xfe, 0x6f, 0x7e, 0x87, 0xf1, 0xd1, 0xc3, 0xce, 0x01, 0x23, + 0x0a, 0xae, 0x7f, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x2a, 0xe4, 0xc0, 0x85, 0x16, 0x28, 0x00, 0x00, +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.proto b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.proto new file mode 100644 index 0000000000..8cb9c8cc25 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.proto @@ -0,0 +1,905 @@ +// This file originates from the SatoshiLabs Trezor `common` repository at: +// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto +// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b. + +syntax = "proto2"; + +/** + * Messages for TREZOR communication + */ + +// Sugar for easier handling in Java +option java_package = "com.satoshilabs.trezor.lib.protobuf"; +option java_outer_classname = "TrezorMessage"; + +import "types.proto"; + +/** + * Mapping between Trezor wire identifier (uint) and a protobuf message + */ +enum MessageType { + MessageType_Initialize = 0 [(wire_in) = true]; + MessageType_Ping = 1 [(wire_in) = true]; + MessageType_Success = 2 [(wire_out) = true]; + MessageType_Failure = 3 [(wire_out) = true]; + MessageType_ChangePin = 4 [(wire_in) = true]; + MessageType_WipeDevice = 5 [(wire_in) = true]; + MessageType_FirmwareErase = 6 [(wire_in) = true, (wire_bootloader) = true]; + MessageType_FirmwareUpload = 7 [(wire_in) = true, (wire_bootloader) = true]; + MessageType_FirmwareRequest = 8 [(wire_out) = true, (wire_bootloader) = true]; + MessageType_GetEntropy = 9 [(wire_in) = true]; + MessageType_Entropy = 10 [(wire_out) = true]; + MessageType_GetPublicKey = 11 [(wire_in) = true]; + MessageType_PublicKey = 12 [(wire_out) = true]; + MessageType_LoadDevice = 13 [(wire_in) = true]; + MessageType_ResetDevice = 14 [(wire_in) = true]; + MessageType_SignTx = 15 [(wire_in) = true]; + MessageType_SimpleSignTx = 16 [(wire_in) = true, deprecated = true]; + MessageType_Features = 17 [(wire_out) = true]; + MessageType_PinMatrixRequest = 18 [(wire_out) = true]; + MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true]; + MessageType_Cancel = 20 [(wire_in) = true]; + MessageType_TxRequest = 21 [(wire_out) = true]; + MessageType_TxAck = 22 [(wire_in) = true]; + MessageType_CipherKeyValue = 23 [(wire_in) = true]; + MessageType_ClearSession = 24 [(wire_in) = true]; + MessageType_ApplySettings = 25 [(wire_in) = true]; + MessageType_ButtonRequest = 26 [(wire_out) = true]; + MessageType_ButtonAck = 27 [(wire_in) = true, (wire_tiny) = true]; + MessageType_ApplyFlags = 28 [(wire_in) = true]; + MessageType_GetAddress = 29 [(wire_in) = true]; + MessageType_Address = 30 [(wire_out) = true]; + MessageType_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true]; + MessageType_BackupDevice = 34 [(wire_in) = true]; + MessageType_EntropyRequest = 35 [(wire_out) = true]; + MessageType_EntropyAck = 36 [(wire_in) = true]; + MessageType_SignMessage = 38 [(wire_in) = true]; + MessageType_VerifyMessage = 39 [(wire_in) = true]; + MessageType_MessageSignature = 40 [(wire_out) = true]; + MessageType_PassphraseRequest = 41 [(wire_out) = true]; + MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true]; + MessageType_EstimateTxSize = 43 [(wire_in) = true, deprecated = true]; + MessageType_TxSize = 44 [(wire_out) = true, deprecated = true]; + MessageType_RecoveryDevice = 45 [(wire_in) = true]; + MessageType_WordRequest = 46 [(wire_out) = true]; + MessageType_WordAck = 47 [(wire_in) = true]; + MessageType_CipheredKeyValue = 48 [(wire_out) = true]; + MessageType_EncryptMessage = 49 [(wire_in) = true, deprecated = true]; + MessageType_EncryptedMessage = 50 [(wire_out) = true, deprecated = true]; + MessageType_DecryptMessage = 51 [(wire_in) = true, deprecated = true]; + MessageType_DecryptedMessage = 52 [(wire_out) = true, deprecated = true]; + MessageType_SignIdentity = 53 [(wire_in) = true]; + MessageType_SignedIdentity = 54 [(wire_out) = true]; + MessageType_GetFeatures = 55 [(wire_in) = true]; + MessageType_EthereumGetAddress = 56 [(wire_in) = true]; + MessageType_EthereumAddress = 57 [(wire_out) = true]; + MessageType_EthereumSignTx = 58 [(wire_in) = true]; + MessageType_EthereumTxRequest = 59 [(wire_out) = true]; + MessageType_EthereumTxAck = 60 [(wire_in) = true]; + MessageType_GetECDHSessionKey = 61 [(wire_in) = true]; + MessageType_ECDHSessionKey = 62 [(wire_out) = true]; + MessageType_SetU2FCounter = 63 [(wire_in) = true]; + MessageType_EthereumSignMessage = 64 [(wire_in) = true]; + MessageType_EthereumVerifyMessage = 65 [(wire_in) = true]; + MessageType_EthereumMessageSignature = 66 [(wire_out) = true]; + MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true]; + MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true]; + MessageType_DebugLinkState = 102 [(wire_debug_out) = true]; + MessageType_DebugLinkStop = 103 [(wire_debug_in) = true]; + MessageType_DebugLinkLog = 104 [(wire_debug_out) = true]; + MessageType_DebugLinkMemoryRead = 110 [(wire_debug_in) = true]; + MessageType_DebugLinkMemory = 111 [(wire_debug_out) = true]; + MessageType_DebugLinkMemoryWrite = 112 [(wire_debug_in) = true]; + MessageType_DebugLinkFlashErase = 113 [(wire_debug_in) = true]; +} + +//////////////////// +// Basic messages // +//////////////////// + +/** + * Request: Reset device to default state and ask for device details + * @next Features + */ +message Initialize { +} + +/** + * Request: Ask for device details (no device reset) + * @next Features + */ +message GetFeatures { +} + +/** + * Response: Reports various information about the device + * @prev Initialize + * @prev GetFeatures + */ +message Features { + optional string vendor = 1; // name of the manufacturer, e.g. "bitcointrezor.com" + optional uint32 major_version = 2; // major version of the device, e.g. 1 + optional uint32 minor_version = 3; // minor version of the device, e.g. 0 + optional uint32 patch_version = 4; // patch version of the device, e.g. 0 + optional bool bootloader_mode = 5; // is device in bootloader mode? + optional string device_id = 6; // device's unique identifier + optional bool pin_protection = 7; // is device protected by PIN? + optional bool passphrase_protection = 8; // is node/mnemonic encrypted using passphrase? + optional string language = 9; // device language + optional string label = 10; // device description label + repeated CoinType coins = 11; // supported coins + optional bool initialized = 12; // does device contain seed? + optional bytes revision = 13; // SCM revision of firmware + optional bytes bootloader_hash = 14; // hash of the bootloader + optional bool imported = 15; // was storage imported from an external source? + optional bool pin_cached = 16; // is PIN already cached in session? + optional bool passphrase_cached = 17; // is passphrase already cached in session? + optional bool firmware_present = 18; // is valid firmware loaded? + optional bool needs_backup = 19; // does storage need backup? (equals to Storage.needs_backup) + optional uint32 flags = 20; // device flags (equals to Storage.flags) +} + +/** + * Request: clear session (removes cached PIN, passphrase, etc). + * @next Success + */ +message ClearSession { +} + +/** + * Request: change language and/or label of the device + * @next Success + * @next Failure + * @next ButtonRequest + * @next PinMatrixRequest + */ +message ApplySettings { + optional string language = 1; + optional string label = 2; + optional bool use_passphrase = 3; + optional bytes homescreen = 4; +} + +/** + * Request: set flags of the device + * @next Success + * @next Failure + */ +message ApplyFlags { + optional uint32 flags = 1; // bitmask, can only set bits, not unset +} + +/** + * Request: Starts workflow for setting/changing/removing the PIN + * @next ButtonRequest + * @next PinMatrixRequest + */ +message ChangePin { + optional bool remove = 1; // is PIN removal requested? +} + +/** + * Request: Test if the device is alive, device sends back the message in Success response + * @next Success + */ +message Ping { + optional string message = 1; // message to send back in Success message + optional bool button_protection = 2; // ask for button press + optional bool pin_protection = 3; // ask for PIN if set in device + optional bool passphrase_protection = 4; // ask for passphrase if set in device +} + +/** + * Response: Success of the previous request + */ +message Success { + optional string message = 1; // human readable description of action or request-specific payload +} + +/** + * Response: Failure of the previous request + */ +message Failure { + optional FailureType code = 1; // computer-readable definition of the error state + optional string message = 2; // human-readable message of the error state +} + +/** + * Response: Device is waiting for HW button press. + * @next ButtonAck + * @next Cancel + */ +message ButtonRequest { + optional ButtonRequestType code = 1; + optional string data = 2; +} + +/** + * Request: Computer agrees to wait for HW button press + * @prev ButtonRequest + */ +message ButtonAck { +} + +/** + * Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme + * @next PinMatrixAck + * @next Cancel + */ +message PinMatrixRequest { + optional PinMatrixRequestType type = 1; +} + +/** + * Request: Computer responds with encoded PIN + * @prev PinMatrixRequest + */ +message PinMatrixAck { + required string pin = 1; // matrix encoded PIN entered by user +} + +/** + * Request: Abort last operation that required user interaction + * @prev ButtonRequest + * @prev PinMatrixRequest + * @prev PassphraseRequest + */ +message Cancel { +} + +/** + * Response: Device awaits encryption passphrase + * @next PassphraseAck + * @next Cancel + */ +message PassphraseRequest { +} + +/** + * Request: Send passphrase back + * @prev PassphraseRequest + */ +message PassphraseAck { + required string passphrase = 1; +} + +/** + * Request: Request a sample of random data generated by hardware RNG. May be used for testing. + * @next ButtonRequest + * @next Entropy + * @next Failure + */ +message GetEntropy { + required uint32 size = 1; // size of requested entropy +} + +/** + * Response: Reply with random data generated by internal RNG + * @prev GetEntropy + */ +message Entropy { + required bytes entropy = 1; // stream of random generated bytes +} + +/** + * Request: Ask device for public key corresponding to address_n path + * @next PassphraseRequest + * @next PublicKey + * @next Failure + */ +message GetPublicKey { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional string ecdsa_curve_name = 2; // ECDSA curve name to use + optional bool show_display = 3; // optionally show on display before sending the result + optional string coin_name = 4 [default='Bitcoin']; +} + +/** + * Response: Contains public key derived from device private seed + * @prev GetPublicKey + */ +message PublicKey { + required HDNodeType node = 1; // BIP32 public node + optional string xpub = 2; // serialized form of public node +} + +/** + * Request: Ask device for address corresponding to address_n path + * @next PassphraseRequest + * @next Address + * @next Failure + */ +message GetAddress { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional string coin_name = 2 [default='Bitcoin']; + optional bool show_display = 3 ; // optionally show on display before sending the result + optional MultisigRedeemScriptType multisig = 4; // filled if we are showing a multisig address + optional InputScriptType script_type = 5 [default=SPENDADDRESS]; // used to distinguish between various address formats (non-segwit, segwit, etc.) +} + +/** + * Request: Ask device for Ethereum address corresponding to address_n path + * @next PassphraseRequest + * @next EthereumAddress + * @next Failure + */ +message EthereumGetAddress { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional bool show_display = 2; // optionally show on display before sending the result +} + +/** + * Response: Contains address derived from device private seed + * @prev GetAddress + */ +message Address { + required string address = 1; // Coin address in Base58 encoding +} + +/** + * Response: Contains an Ethereum address derived from device private seed + * @prev EthereumGetAddress + */ +message EthereumAddress { + required bytes address = 1; // Coin address as an Ethereum 160 bit hash +} + +/** + * Request: Request device to wipe all sensitive data and settings + * @next ButtonRequest + */ +message WipeDevice { +} + +/** + * Request: Load seed and related internal settings from the computer + * @next ButtonRequest + * @next Success + * @next Failure + */ +message LoadDevice { + optional string mnemonic = 1; // seed encoded as BIP-39 mnemonic (12, 18 or 24 words) + optional HDNodeType node = 2; // BIP-32 node + optional string pin = 3; // set PIN protection + optional bool passphrase_protection = 4; // enable master node encryption using passphrase + optional string language = 5 [default='english']; // device language + optional string label = 6; // device label + optional bool skip_checksum = 7; // do not test mnemonic for valid BIP-39 checksum + optional uint32 u2f_counter = 8; // U2F counter +} + +/** + * Request: Ask device to do initialization involving user interaction + * @next EntropyRequest + * @next Failure + */ +message ResetDevice { + optional bool display_random = 1; // display entropy generated by the device before asking for additional entropy + optional uint32 strength = 2 [default=256]; // strength of seed in bits + optional bool passphrase_protection = 3; // enable master node encryption using passphrase + optional bool pin_protection = 4; // enable PIN protection + optional string language = 5 [default='english']; // device language + optional string label = 6; // device label + optional uint32 u2f_counter = 7; // U2F counter + optional bool skip_backup = 8; // postpone seed backup to BackupDevice workflow +} + +/** + * Request: Perform backup of the device seed if not backed up using ResetDevice + * @next ButtonRequest + */ +message BackupDevice { +} + +/** + * Response: Ask for additional entropy from host computer + * @prev ResetDevice + * @next EntropyAck + */ +message EntropyRequest { +} + +/** + * Request: Provide additional entropy for seed generation function + * @prev EntropyRequest + * @next ButtonRequest + */ +message EntropyAck { + optional bytes entropy = 1; // 256 bits (32 bytes) of random data +} + +/** + * Request: Start recovery workflow asking user for specific words of mnemonic + * Used to recovery device safely even on untrusted computer. + * @next WordRequest + */ +message RecoveryDevice { + optional uint32 word_count = 1; // number of words in BIP-39 mnemonic + optional bool passphrase_protection = 2; // enable master node encryption using passphrase + optional bool pin_protection = 3; // enable PIN protection + optional string language = 4 [default='english']; // device language + optional string label = 5; // device label + optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process + // 7 reserved for unused recovery method + optional uint32 type = 8; // supported recovery type (see RecoveryType) + optional uint32 u2f_counter = 9; // U2F counter + optional bool dry_run = 10; // perform dry-run recovery workflow (for safe mnemonic validation) +} + +/** + * Response: Device is waiting for user to enter word of the mnemonic + * Its position is shown only on device's internal display. + * @prev RecoveryDevice + * @prev WordAck + */ +message WordRequest { + optional WordRequestType type = 1; +} + +/** + * Request: Computer replies with word from the mnemonic + * @prev WordRequest + * @next WordRequest + * @next Success + * @next Failure + */ +message WordAck { + required string word = 1; // one word of mnemonic on asked position +} + +////////////////////////////// +// Message signing messages // +////////////////////////////// + +/** + * Request: Ask device to sign message + * @next MessageSignature + * @next Failure + */ +message SignMessage { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + required bytes message = 2; // message to be signed + optional string coin_name = 3 [default='Bitcoin']; // coin to use for signing + optional InputScriptType script_type = 4 [default=SPENDADDRESS]; // used to distinguish between various address formats (non-segwit, segwit, etc.) +} + +/** + * Request: Ask device to verify message + * @next Success + * @next Failure + */ +message VerifyMessage { + optional string address = 1; // address to verify + optional bytes signature = 2; // signature to verify + optional bytes message = 3; // message to verify + optional string coin_name = 4 [default='Bitcoin']; // coin to use for verifying +} + +/** + * Response: Signed message + * @prev SignMessage + */ +message MessageSignature { + optional string address = 1; // address used to sign the message + optional bytes signature = 2; // signature of the message +} + +/////////////////////////// +// Encryption/decryption // +/////////////////////////// + +/** + * Request: Ask device to encrypt message + * @next EncryptedMessage + * @next Failure + */ +message EncryptMessage { + optional bytes pubkey = 1; // public key + optional bytes message = 2; // message to encrypt + optional bool display_only = 3; // show just on display? (don't send back via wire) + repeated uint32 address_n = 4; // BIP-32 path to derive the signing key from master node + optional string coin_name = 5 [default='Bitcoin']; // coin to use for signing +} + +/** + * Response: Encrypted message + * @prev EncryptMessage + */ +message EncryptedMessage { + optional bytes nonce = 1; // nonce used during encryption + optional bytes message = 2; // encrypted message + optional bytes hmac = 3; // message hmac +} + +/** + * Request: Ask device to decrypt message + * @next Success + * @next Failure + */ +message DecryptMessage { + repeated uint32 address_n = 1; // BIP-32 path to derive the decryption key from master node + optional bytes nonce = 2; // nonce used during encryption + optional bytes message = 3; // message to decrypt + optional bytes hmac = 4; // message hmac +} + +/** + * Response: Decrypted message + * @prev DecryptedMessage + */ +message DecryptedMessage { + optional bytes message = 1; // decrypted message + optional string address = 2; // address used to sign the message (if used) +} + +/** + * Request: Ask device to encrypt or decrypt value of given key + * @next CipheredKeyValue + * @next Failure + */ +message CipherKeyValue { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional string key = 2; // key component of key:value + optional bytes value = 3; // value component of key:value + optional bool encrypt = 4; // are we encrypting (True) or decrypting (False)? + optional bool ask_on_encrypt = 5; // should we ask on encrypt operation? + optional bool ask_on_decrypt = 6; // should we ask on decrypt operation? + optional bytes iv = 7; // initialization vector (will be computed if not set) +} + +/** + * Response: Return ciphered/deciphered value + * @prev CipherKeyValue + */ +message CipheredKeyValue { + optional bytes value = 1; // ciphered/deciphered value +} + +////////////////////////////////// +// Transaction signing messages // +////////////////////////////////// + +/** + * Request: Estimated size of the transaction + * This behaves exactly like SignTx, which means that it can ask using TxRequest + * This call is non-blocking (except possible PassphraseRequest to unlock the seed) + * @next TxSize + * @next Failure + */ +message EstimateTxSize { + required uint32 outputs_count = 1; // number of transaction outputs + required uint32 inputs_count = 2; // number of transaction inputs + optional string coin_name = 3 [default='Bitcoin']; // coin to use +} + +/** + * Response: Estimated size of the transaction + * @prev EstimateTxSize + */ +message TxSize { + optional uint32 tx_size = 1; // estimated size of transaction in bytes +} + +/** + * Request: Ask device to sign transaction + * @next PassphraseRequest + * @next PinMatrixRequest + * @next TxRequest + * @next Failure + */ +message SignTx { + required uint32 outputs_count = 1; // number of transaction outputs + required uint32 inputs_count = 2; // number of transaction inputs + optional string coin_name = 3 [default='Bitcoin']; // coin to use + optional uint32 version = 4 [default=1]; // transaction version + optional uint32 lock_time = 5 [default=0]; // transaction lock_time +} + +/** + * Request: Simplified transaction signing + * This method doesn't support streaming, so there are hardware limits in number of inputs and outputs. + * In case of success, the result is returned using TxRequest message. + * @next PassphraseRequest + * @next PinMatrixRequest + * @next TxRequest + * @next Failure + */ +message SimpleSignTx { + repeated TxInputType inputs = 1; // transaction inputs + repeated TxOutputType outputs = 2; // transaction outputs + repeated TransactionType transactions = 3; // transactions whose outputs are used to build current inputs + optional string coin_name = 4 [default='Bitcoin']; // coin to use + optional uint32 version = 5 [default=1]; // transaction version + optional uint32 lock_time = 6 [default=0]; // transaction lock_time +} + +/** + * Response: Device asks for information for signing transaction or returns the last result + * If request_index is set, device awaits TxAck message (with fields filled in according to request_type) + * If signature_index is set, 'signature' contains signed input of signature_index's input + * @prev SignTx + * @prev SimpleSignTx + * @prev TxAck + */ +message TxRequest { + optional RequestType request_type = 1; // what should be filled in TxAck message? + optional TxRequestDetailsType details = 2; // request for tx details + optional TxRequestSerializedType serialized = 3; // serialized data and request for next +} + +/** + * Request: Reported transaction data + * @prev TxRequest + * @next TxRequest + */ +message TxAck { + optional TransactionType tx = 1; +} + +/** + * Request: Ask device to sign transaction + * All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing. + * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. + * @next PassphraseRequest + * @next PinMatrixRequest + * @next EthereumTxRequest + * @next Failure + */ +message EthereumSignTx { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional bytes nonce = 2; // <=256 bit unsigned big endian + optional bytes gas_price = 3; // <=256 bit unsigned big endian (in wei) + optional bytes gas_limit = 4; // <=256 bit unsigned big endian + optional bytes to = 5; // 160 bit address hash + optional bytes value = 6; // <=256 bit unsigned big endian (in wei) + optional bytes data_initial_chunk = 7; // The initial data chunk (<= 1024 bytes) + optional uint32 data_length = 8; // Length of transaction payload + optional uint32 chain_id = 9; // Chain Id for EIP 155 +} + +/** + * Response: Device asks for more data from transaction payload, or returns the signature. + * If data_length is set, device awaits that many more bytes of payload. + * Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present. + * @prev EthereumSignTx + * @next EthereumTxAck + */ +message EthereumTxRequest { + optional uint32 data_length = 1; // Number of bytes being requested (<= 1024) + optional uint32 signature_v = 2; // Computed signature (recovery parameter, limited to 27 or 28) + optional bytes signature_r = 3; // Computed signature R component (256 bit) + optional bytes signature_s = 4; // Computed signature S component (256 bit) +} + +/** + * Request: Transaction payload data. + * @prev EthereumTxRequest + * @next EthereumTxRequest + */ +message EthereumTxAck { + optional bytes data_chunk = 1; // Bytes from transaction payload (<= 1024 bytes) +} + +//////////////////////////////////////// +// Ethereum: Message signing messages // +//////////////////////////////////////// + +/** + * Request: Ask device to sign message + * @next EthereumMessageSignature + * @next Failure + */ +message EthereumSignMessage { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + required bytes message = 2; // message to be signed +} + +/** + * Request: Ask device to verify message + * @next Success + * @next Failure + */ +message EthereumVerifyMessage { + optional bytes address = 1; // address to verify + optional bytes signature = 2; // signature to verify + optional bytes message = 3; // message to verify +} + +/** + * Response: Signed message + * @prev EthereumSignMessage + */ +message EthereumMessageSignature { + optional bytes address = 1; // address used to sign the message + optional bytes signature = 2; // signature of the message +} + +/////////////////////// +// Identity messages // +/////////////////////// + +/** + * Request: Ask device to sign identity + * @next SignedIdentity + * @next Failure + */ +message SignIdentity { + optional IdentityType identity = 1; // identity + optional bytes challenge_hidden = 2; // non-visible challenge + optional string challenge_visual = 3; // challenge shown on display (e.g. date+time) + optional string ecdsa_curve_name = 4; // ECDSA curve name to use +} + +/** + * Response: Device provides signed identity + * @prev SignIdentity + */ +message SignedIdentity { + optional string address = 1; // identity address + optional bytes public_key = 2; // identity public key + optional bytes signature = 3; // signature of the identity data +} + +/////////////////// +// ECDH messages // +/////////////////// + +/** + * Request: Ask device to generate ECDH session key + * @next ECDHSessionKey + * @next Failure + */ +message GetECDHSessionKey { + optional IdentityType identity = 1; // identity + optional bytes peer_public_key = 2; // peer's public key + optional string ecdsa_curve_name = 3; // ECDSA curve name to use +} + +/** + * Response: Device provides ECDH session key + * @prev GetECDHSessionKey + */ +message ECDHSessionKey { + optional bytes session_key = 1; // ECDH session key +} + +/////////////////// +// U2F messages // +/////////////////// + +/** + * Request: Set U2F counter + * @next Success + */ +message SetU2FCounter { + optional uint32 u2f_counter = 1; // counter +} + +///////////////////////// +// Bootloader messages // +///////////////////////// + +/** + * Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload) + * @next Success + * @next FirmwareRequest + * @next Failure + */ +message FirmwareErase { + optional uint32 length = 1; // length of new firmware +} + +/** + * Response: Ask for firmware chunk + * @next FirmwareUpload + */ +message FirmwareRequest { + optional uint32 offset = 1; // offset of requested firmware chunk + optional uint32 length = 2; // length of requested firmware chunk +} + +/** + * Request: Send firmware in binary form to the device + * @next Success + * @next Failure + */ +message FirmwareUpload { + required bytes payload = 1; // firmware to be loaded into device + optional bytes hash = 2; // hash of the payload +} + + +/** + * Request: Perform a device self-test + * @next Success + * @next Failure + */ +message SelfTest { + optional bytes payload = 1; // payload to be used in self-test +} + +///////////////////////////////////////////////////////////// +// Debug messages (only available if DebugLink is enabled) // +///////////////////////////////////////////////////////////// + +/** + * Request: "Press" the button on the device + * @next Success + */ +message DebugLinkDecision { + required bool yes_no = 1; // true for "Confirm", false for "Cancel" +} + +/** + * Request: Computer asks for device state + * @next DebugLinkState + */ +message DebugLinkGetState { +} + +/** + * Response: Device current state + * @prev DebugLinkGetState + */ +message DebugLinkState { + optional bytes layout = 1; // raw buffer of display + optional string pin = 2; // current PIN, blank if PIN is not set/enabled + optional string matrix = 3; // current PIN matrix + optional string mnemonic = 4; // current BIP-39 mnemonic + optional HDNodeType node = 5; // current BIP-32 node + optional bool passphrase_protection = 6; // is node/mnemonic encrypted using passphrase? + optional string reset_word = 7; // word on device display during ResetDevice workflow + optional bytes reset_entropy = 8; // current entropy during ResetDevice workflow + optional string recovery_fake_word = 9; // (fake) word on display during RecoveryDevice workflow + optional uint32 recovery_word_pos = 10; // index of mnemonic word the device is expecting during RecoveryDevice workflow +} + +/** + * Request: Ask device to restart + */ +message DebugLinkStop { +} + +/** + * Response: Device wants host to log event + */ +message DebugLinkLog { + optional uint32 level = 1; + optional string bucket = 2; + optional string text = 3; +} + +/** + * Request: Read memory from device + * @next DebugLinkMemory + */ +message DebugLinkMemoryRead { + optional uint32 address = 1; + optional uint32 length = 2; +} + +/** + * Response: Device sends memory back + * @prev DebugLinkMemoryRead + */ +message DebugLinkMemory { + optional bytes memory = 1; +} + +/** + * Request: Write memory to device. + * WARNING: Writing to the wrong location can irreparably break the device. + */ +message DebugLinkMemoryWrite { + optional uint32 address = 1; + optional bytes memory = 2; + optional bool flash = 3; +} + +/** + * Request: Erase block of flash on device + * WARNING: Writing to the wrong location can irreparably break the device. + */ +message DebugLinkFlashErase { + optional uint32 sector = 1; +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/trezor.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/trezor.go new file mode 100644 index 0000000000..80cc75efc4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/trezor.go @@ -0,0 +1,46 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// This file contains the implementation for interacting with the Trezor hardware +// wallets. The wire protocol spec can be found on the SatoshiLabs website: +// https://doc.satoshilabs.com/trezor-tech/api-protobuf.html + +//go:generate protoc --go_out=import_path=trezor:. types.proto messages.proto + +// Package trezor contains the wire protocol wrapper in Go. +package trezor + +import ( + "reflect" + + "github.com/golang/protobuf/proto" +) + +// Type returns the protocol buffer type number of a specific message. If the +// message is nil, this method panics! +func Type(msg proto.Message) uint16 { + return uint16(MessageType_value["MessageType_"+reflect.TypeOf(msg).Elem().Name()]) +} + +// Name returns the friendly message type name of a specific protocol buffer +// type number. +func Name(kind uint16) string { + name := MessageType_name[int32(kind)] + if len(name) < 12 { + return name + } + return name[12:] +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/types.pb.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/types.pb.go new file mode 100644 index 0000000000..25b7672d23 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/types.pb.go @@ -0,0 +1,1333 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: types.proto + +/* +Package trezor is a generated protocol buffer package. + +It is generated from these files: + types.proto + messages.proto + +It has these top-level messages: + HDNodeType + HDNodePathType + CoinType + MultisigRedeemScriptType + TxInputType + TxOutputType + TxOutputBinType + TransactionType + TxRequestDetailsType + TxRequestSerializedType + IdentityType + Initialize + GetFeatures + Features + ClearSession + ApplySettings + ApplyFlags + ChangePin + Ping + Success + Failure + ButtonRequest + ButtonAck + PinMatrixRequest + PinMatrixAck + Cancel + PassphraseRequest + PassphraseAck + GetEntropy + Entropy + GetPublicKey + PublicKey + GetAddress + EthereumGetAddress + Address + EthereumAddress + WipeDevice + LoadDevice + ResetDevice + BackupDevice + EntropyRequest + EntropyAck + RecoveryDevice + WordRequest + WordAck + SignMessage + VerifyMessage + MessageSignature + EncryptMessage + EncryptedMessage + DecryptMessage + DecryptedMessage + CipherKeyValue + CipheredKeyValue + EstimateTxSize + TxSize + SignTx + SimpleSignTx + TxRequest + TxAck + EthereumSignTx + EthereumTxRequest + EthereumTxAck + EthereumSignMessage + EthereumVerifyMessage + EthereumMessageSignature + SignIdentity + SignedIdentity + GetECDHSessionKey + ECDHSessionKey + SetU2FCounter + FirmwareErase + FirmwareRequest + FirmwareUpload + SelfTest + DebugLinkDecision + DebugLinkGetState + DebugLinkState + DebugLinkStop + DebugLinkLog + DebugLinkMemoryRead + DebugLinkMemory + DebugLinkMemoryWrite + DebugLinkFlashErase +*/ +package trezor + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// * +// Type of failures returned by Failure message +// @used_in Failure +type FailureType int32 + +const ( + FailureType_Failure_UnexpectedMessage FailureType = 1 + FailureType_Failure_ButtonExpected FailureType = 2 + FailureType_Failure_DataError FailureType = 3 + FailureType_Failure_ActionCancelled FailureType = 4 + FailureType_Failure_PinExpected FailureType = 5 + FailureType_Failure_PinCancelled FailureType = 6 + FailureType_Failure_PinInvalid FailureType = 7 + FailureType_Failure_InvalidSignature FailureType = 8 + FailureType_Failure_ProcessError FailureType = 9 + FailureType_Failure_NotEnoughFunds FailureType = 10 + FailureType_Failure_NotInitialized FailureType = 11 + FailureType_Failure_FirmwareError FailureType = 99 +) + +var FailureType_name = map[int32]string{ + 1: "Failure_UnexpectedMessage", + 2: "Failure_ButtonExpected", + 3: "Failure_DataError", + 4: "Failure_ActionCancelled", + 5: "Failure_PinExpected", + 6: "Failure_PinCancelled", + 7: "Failure_PinInvalid", + 8: "Failure_InvalidSignature", + 9: "Failure_ProcessError", + 10: "Failure_NotEnoughFunds", + 11: "Failure_NotInitialized", + 99: "Failure_FirmwareError", +} +var FailureType_value = map[string]int32{ + "Failure_UnexpectedMessage": 1, + "Failure_ButtonExpected": 2, + "Failure_DataError": 3, + "Failure_ActionCancelled": 4, + "Failure_PinExpected": 5, + "Failure_PinCancelled": 6, + "Failure_PinInvalid": 7, + "Failure_InvalidSignature": 8, + "Failure_ProcessError": 9, + "Failure_NotEnoughFunds": 10, + "Failure_NotInitialized": 11, + "Failure_FirmwareError": 99, +} + +func (x FailureType) Enum() *FailureType { + p := new(FailureType) + *p = x + return p +} +func (x FailureType) String() string { + return proto.EnumName(FailureType_name, int32(x)) +} +func (x *FailureType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FailureType_value, data, "FailureType") + if err != nil { + return err + } + *x = FailureType(value) + return nil +} +func (FailureType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +// * +// Type of script which will be used for transaction output +// @used_in TxOutputType +type OutputScriptType int32 + +const ( + OutputScriptType_PAYTOADDRESS OutputScriptType = 0 + OutputScriptType_PAYTOSCRIPTHASH OutputScriptType = 1 + OutputScriptType_PAYTOMULTISIG OutputScriptType = 2 + OutputScriptType_PAYTOOPRETURN OutputScriptType = 3 + OutputScriptType_PAYTOWITNESS OutputScriptType = 4 + OutputScriptType_PAYTOP2SHWITNESS OutputScriptType = 5 +) + +var OutputScriptType_name = map[int32]string{ + 0: "PAYTOADDRESS", + 1: "PAYTOSCRIPTHASH", + 2: "PAYTOMULTISIG", + 3: "PAYTOOPRETURN", + 4: "PAYTOWITNESS", + 5: "PAYTOP2SHWITNESS", +} +var OutputScriptType_value = map[string]int32{ + "PAYTOADDRESS": 0, + "PAYTOSCRIPTHASH": 1, + "PAYTOMULTISIG": 2, + "PAYTOOPRETURN": 3, + "PAYTOWITNESS": 4, + "PAYTOP2SHWITNESS": 5, +} + +func (x OutputScriptType) Enum() *OutputScriptType { + p := new(OutputScriptType) + *p = x + return p +} +func (x OutputScriptType) String() string { + return proto.EnumName(OutputScriptType_name, int32(x)) +} +func (x *OutputScriptType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(OutputScriptType_value, data, "OutputScriptType") + if err != nil { + return err + } + *x = OutputScriptType(value) + return nil +} +func (OutputScriptType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +// * +// Type of script which will be used for transaction output +// @used_in TxInputType +type InputScriptType int32 + +const ( + InputScriptType_SPENDADDRESS InputScriptType = 0 + InputScriptType_SPENDMULTISIG InputScriptType = 1 + InputScriptType_EXTERNAL InputScriptType = 2 + InputScriptType_SPENDWITNESS InputScriptType = 3 + InputScriptType_SPENDP2SHWITNESS InputScriptType = 4 +) + +var InputScriptType_name = map[int32]string{ + 0: "SPENDADDRESS", + 1: "SPENDMULTISIG", + 2: "EXTERNAL", + 3: "SPENDWITNESS", + 4: "SPENDP2SHWITNESS", +} +var InputScriptType_value = map[string]int32{ + "SPENDADDRESS": 0, + "SPENDMULTISIG": 1, + "EXTERNAL": 2, + "SPENDWITNESS": 3, + "SPENDP2SHWITNESS": 4, +} + +func (x InputScriptType) Enum() *InputScriptType { + p := new(InputScriptType) + *p = x + return p +} +func (x InputScriptType) String() string { + return proto.EnumName(InputScriptType_name, int32(x)) +} +func (x *InputScriptType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(InputScriptType_value, data, "InputScriptType") + if err != nil { + return err + } + *x = InputScriptType(value) + return nil +} +func (InputScriptType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +// * +// Type of information required by transaction signing process +// @used_in TxRequest +type RequestType int32 + +const ( + RequestType_TXINPUT RequestType = 0 + RequestType_TXOUTPUT RequestType = 1 + RequestType_TXMETA RequestType = 2 + RequestType_TXFINISHED RequestType = 3 + RequestType_TXEXTRADATA RequestType = 4 +) + +var RequestType_name = map[int32]string{ + 0: "TXINPUT", + 1: "TXOUTPUT", + 2: "TXMETA", + 3: "TXFINISHED", + 4: "TXEXTRADATA", +} +var RequestType_value = map[string]int32{ + "TXINPUT": 0, + "TXOUTPUT": 1, + "TXMETA": 2, + "TXFINISHED": 3, + "TXEXTRADATA": 4, +} + +func (x RequestType) Enum() *RequestType { + p := new(RequestType) + *p = x + return p +} +func (x RequestType) String() string { + return proto.EnumName(RequestType_name, int32(x)) +} +func (x *RequestType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(RequestType_value, data, "RequestType") + if err != nil { + return err + } + *x = RequestType(value) + return nil +} +func (RequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +// * +// Type of button request +// @used_in ButtonRequest +type ButtonRequestType int32 + +const ( + ButtonRequestType_ButtonRequest_Other ButtonRequestType = 1 + ButtonRequestType_ButtonRequest_FeeOverThreshold ButtonRequestType = 2 + ButtonRequestType_ButtonRequest_ConfirmOutput ButtonRequestType = 3 + ButtonRequestType_ButtonRequest_ResetDevice ButtonRequestType = 4 + ButtonRequestType_ButtonRequest_ConfirmWord ButtonRequestType = 5 + ButtonRequestType_ButtonRequest_WipeDevice ButtonRequestType = 6 + ButtonRequestType_ButtonRequest_ProtectCall ButtonRequestType = 7 + ButtonRequestType_ButtonRequest_SignTx ButtonRequestType = 8 + ButtonRequestType_ButtonRequest_FirmwareCheck ButtonRequestType = 9 + ButtonRequestType_ButtonRequest_Address ButtonRequestType = 10 + ButtonRequestType_ButtonRequest_PublicKey ButtonRequestType = 11 +) + +var ButtonRequestType_name = map[int32]string{ + 1: "ButtonRequest_Other", + 2: "ButtonRequest_FeeOverThreshold", + 3: "ButtonRequest_ConfirmOutput", + 4: "ButtonRequest_ResetDevice", + 5: "ButtonRequest_ConfirmWord", + 6: "ButtonRequest_WipeDevice", + 7: "ButtonRequest_ProtectCall", + 8: "ButtonRequest_SignTx", + 9: "ButtonRequest_FirmwareCheck", + 10: "ButtonRequest_Address", + 11: "ButtonRequest_PublicKey", +} +var ButtonRequestType_value = map[string]int32{ + "ButtonRequest_Other": 1, + "ButtonRequest_FeeOverThreshold": 2, + "ButtonRequest_ConfirmOutput": 3, + "ButtonRequest_ResetDevice": 4, + "ButtonRequest_ConfirmWord": 5, + "ButtonRequest_WipeDevice": 6, + "ButtonRequest_ProtectCall": 7, + "ButtonRequest_SignTx": 8, + "ButtonRequest_FirmwareCheck": 9, + "ButtonRequest_Address": 10, + "ButtonRequest_PublicKey": 11, +} + +func (x ButtonRequestType) Enum() *ButtonRequestType { + p := new(ButtonRequestType) + *p = x + return p +} +func (x ButtonRequestType) String() string { + return proto.EnumName(ButtonRequestType_name, int32(x)) +} +func (x *ButtonRequestType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ButtonRequestType_value, data, "ButtonRequestType") + if err != nil { + return err + } + *x = ButtonRequestType(value) + return nil +} +func (ButtonRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +// * +// Type of PIN request +// @used_in PinMatrixRequest +type PinMatrixRequestType int32 + +const ( + PinMatrixRequestType_PinMatrixRequestType_Current PinMatrixRequestType = 1 + PinMatrixRequestType_PinMatrixRequestType_NewFirst PinMatrixRequestType = 2 + PinMatrixRequestType_PinMatrixRequestType_NewSecond PinMatrixRequestType = 3 +) + +var PinMatrixRequestType_name = map[int32]string{ + 1: "PinMatrixRequestType_Current", + 2: "PinMatrixRequestType_NewFirst", + 3: "PinMatrixRequestType_NewSecond", +} +var PinMatrixRequestType_value = map[string]int32{ + "PinMatrixRequestType_Current": 1, + "PinMatrixRequestType_NewFirst": 2, + "PinMatrixRequestType_NewSecond": 3, +} + +func (x PinMatrixRequestType) Enum() *PinMatrixRequestType { + p := new(PinMatrixRequestType) + *p = x + return p +} +func (x PinMatrixRequestType) String() string { + return proto.EnumName(PinMatrixRequestType_name, int32(x)) +} +func (x *PinMatrixRequestType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PinMatrixRequestType_value, data, "PinMatrixRequestType") + if err != nil { + return err + } + *x = PinMatrixRequestType(value) + return nil +} +func (PinMatrixRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +// * +// Type of recovery procedure. These should be used as bitmask, e.g., +// `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix` +// listing every method supported by the host computer. +// +// Note that ScrambledWords must be supported by every implementation +// for backward compatibility; there is no way to not support it. +// +// @used_in RecoveryDevice +type RecoveryDeviceType int32 + +const ( + // use powers of two when extending this field + RecoveryDeviceType_RecoveryDeviceType_ScrambledWords RecoveryDeviceType = 0 + RecoveryDeviceType_RecoveryDeviceType_Matrix RecoveryDeviceType = 1 +) + +var RecoveryDeviceType_name = map[int32]string{ + 0: "RecoveryDeviceType_ScrambledWords", + 1: "RecoveryDeviceType_Matrix", +} +var RecoveryDeviceType_value = map[string]int32{ + "RecoveryDeviceType_ScrambledWords": 0, + "RecoveryDeviceType_Matrix": 1, +} + +func (x RecoveryDeviceType) Enum() *RecoveryDeviceType { + p := new(RecoveryDeviceType) + *p = x + return p +} +func (x RecoveryDeviceType) String() string { + return proto.EnumName(RecoveryDeviceType_name, int32(x)) +} +func (x *RecoveryDeviceType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(RecoveryDeviceType_value, data, "RecoveryDeviceType") + if err != nil { + return err + } + *x = RecoveryDeviceType(value) + return nil +} +func (RecoveryDeviceType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +// * +// Type of Recovery Word request +// @used_in WordRequest +type WordRequestType int32 + +const ( + WordRequestType_WordRequestType_Plain WordRequestType = 0 + WordRequestType_WordRequestType_Matrix9 WordRequestType = 1 + WordRequestType_WordRequestType_Matrix6 WordRequestType = 2 +) + +var WordRequestType_name = map[int32]string{ + 0: "WordRequestType_Plain", + 1: "WordRequestType_Matrix9", + 2: "WordRequestType_Matrix6", +} +var WordRequestType_value = map[string]int32{ + "WordRequestType_Plain": 0, + "WordRequestType_Matrix9": 1, + "WordRequestType_Matrix6": 2, +} + +func (x WordRequestType) Enum() *WordRequestType { + p := new(WordRequestType) + *p = x + return p +} +func (x WordRequestType) String() string { + return proto.EnumName(WordRequestType_name, int32(x)) +} +func (x *WordRequestType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(WordRequestType_value, data, "WordRequestType") + if err != nil { + return err + } + *x = WordRequestType(value) + return nil +} +func (WordRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +// * +// Structure representing BIP32 (hierarchical deterministic) node +// Used for imports of private key into the device and exporting public key out of device +// @used_in PublicKey +// @used_in LoadDevice +// @used_in DebugLinkState +// @used_in Storage +type HDNodeType struct { + Depth *uint32 `protobuf:"varint,1,req,name=depth" json:"depth,omitempty"` + Fingerprint *uint32 `protobuf:"varint,2,req,name=fingerprint" json:"fingerprint,omitempty"` + ChildNum *uint32 `protobuf:"varint,3,req,name=child_num,json=childNum" json:"child_num,omitempty"` + ChainCode []byte `protobuf:"bytes,4,req,name=chain_code,json=chainCode" json:"chain_code,omitempty"` + PrivateKey []byte `protobuf:"bytes,5,opt,name=private_key,json=privateKey" json:"private_key,omitempty"` + PublicKey []byte `protobuf:"bytes,6,opt,name=public_key,json=publicKey" json:"public_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *HDNodeType) Reset() { *m = HDNodeType{} } +func (m *HDNodeType) String() string { return proto.CompactTextString(m) } +func (*HDNodeType) ProtoMessage() {} +func (*HDNodeType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *HDNodeType) GetDepth() uint32 { + if m != nil && m.Depth != nil { + return *m.Depth + } + return 0 +} + +func (m *HDNodeType) GetFingerprint() uint32 { + if m != nil && m.Fingerprint != nil { + return *m.Fingerprint + } + return 0 +} + +func (m *HDNodeType) GetChildNum() uint32 { + if m != nil && m.ChildNum != nil { + return *m.ChildNum + } + return 0 +} + +func (m *HDNodeType) GetChainCode() []byte { + if m != nil { + return m.ChainCode + } + return nil +} + +func (m *HDNodeType) GetPrivateKey() []byte { + if m != nil { + return m.PrivateKey + } + return nil +} + +func (m *HDNodeType) GetPublicKey() []byte { + if m != nil { + return m.PublicKey + } + return nil +} + +type HDNodePathType struct { + Node *HDNodeType `protobuf:"bytes,1,req,name=node" json:"node,omitempty"` + AddressN []uint32 `protobuf:"varint,2,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *HDNodePathType) Reset() { *m = HDNodePathType{} } +func (m *HDNodePathType) String() string { return proto.CompactTextString(m) } +func (*HDNodePathType) ProtoMessage() {} +func (*HDNodePathType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *HDNodePathType) GetNode() *HDNodeType { + if m != nil { + return m.Node + } + return nil +} + +func (m *HDNodePathType) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +// * +// Structure representing Coin +// @used_in Features +type CoinType struct { + CoinName *string `protobuf:"bytes,1,opt,name=coin_name,json=coinName" json:"coin_name,omitempty"` + CoinShortcut *string `protobuf:"bytes,2,opt,name=coin_shortcut,json=coinShortcut" json:"coin_shortcut,omitempty"` + AddressType *uint32 `protobuf:"varint,3,opt,name=address_type,json=addressType,def=0" json:"address_type,omitempty"` + MaxfeeKb *uint64 `protobuf:"varint,4,opt,name=maxfee_kb,json=maxfeeKb" json:"maxfee_kb,omitempty"` + AddressTypeP2Sh *uint32 `protobuf:"varint,5,opt,name=address_type_p2sh,json=addressTypeP2sh,def=5" json:"address_type_p2sh,omitempty"` + SignedMessageHeader *string `protobuf:"bytes,8,opt,name=signed_message_header,json=signedMessageHeader" json:"signed_message_header,omitempty"` + XpubMagic *uint32 `protobuf:"varint,9,opt,name=xpub_magic,json=xpubMagic,def=76067358" json:"xpub_magic,omitempty"` + XprvMagic *uint32 `protobuf:"varint,10,opt,name=xprv_magic,json=xprvMagic,def=76066276" json:"xprv_magic,omitempty"` + Segwit *bool `protobuf:"varint,11,opt,name=segwit" json:"segwit,omitempty"` + Forkid *uint32 `protobuf:"varint,12,opt,name=forkid" json:"forkid,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CoinType) Reset() { *m = CoinType{} } +func (m *CoinType) String() string { return proto.CompactTextString(m) } +func (*CoinType) ProtoMessage() {} +func (*CoinType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +const Default_CoinType_AddressType uint32 = 0 +const Default_CoinType_AddressTypeP2Sh uint32 = 5 +const Default_CoinType_XpubMagic uint32 = 76067358 +const Default_CoinType_XprvMagic uint32 = 76066276 + +func (m *CoinType) GetCoinName() string { + if m != nil && m.CoinName != nil { + return *m.CoinName + } + return "" +} + +func (m *CoinType) GetCoinShortcut() string { + if m != nil && m.CoinShortcut != nil { + return *m.CoinShortcut + } + return "" +} + +func (m *CoinType) GetAddressType() uint32 { + if m != nil && m.AddressType != nil { + return *m.AddressType + } + return Default_CoinType_AddressType +} + +func (m *CoinType) GetMaxfeeKb() uint64 { + if m != nil && m.MaxfeeKb != nil { + return *m.MaxfeeKb + } + return 0 +} + +func (m *CoinType) GetAddressTypeP2Sh() uint32 { + if m != nil && m.AddressTypeP2Sh != nil { + return *m.AddressTypeP2Sh + } + return Default_CoinType_AddressTypeP2Sh +} + +func (m *CoinType) GetSignedMessageHeader() string { + if m != nil && m.SignedMessageHeader != nil { + return *m.SignedMessageHeader + } + return "" +} + +func (m *CoinType) GetXpubMagic() uint32 { + if m != nil && m.XpubMagic != nil { + return *m.XpubMagic + } + return Default_CoinType_XpubMagic +} + +func (m *CoinType) GetXprvMagic() uint32 { + if m != nil && m.XprvMagic != nil { + return *m.XprvMagic + } + return Default_CoinType_XprvMagic +} + +func (m *CoinType) GetSegwit() bool { + if m != nil && m.Segwit != nil { + return *m.Segwit + } + return false +} + +func (m *CoinType) GetForkid() uint32 { + if m != nil && m.Forkid != nil { + return *m.Forkid + } + return 0 +} + +// * +// Type of redeem script used in input +// @used_in TxInputType +type MultisigRedeemScriptType struct { + Pubkeys []*HDNodePathType `protobuf:"bytes,1,rep,name=pubkeys" json:"pubkeys,omitempty"` + Signatures [][]byte `protobuf:"bytes,2,rep,name=signatures" json:"signatures,omitempty"` + M *uint32 `protobuf:"varint,3,opt,name=m" json:"m,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MultisigRedeemScriptType) Reset() { *m = MultisigRedeemScriptType{} } +func (m *MultisigRedeemScriptType) String() string { return proto.CompactTextString(m) } +func (*MultisigRedeemScriptType) ProtoMessage() {} +func (*MultisigRedeemScriptType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *MultisigRedeemScriptType) GetPubkeys() []*HDNodePathType { + if m != nil { + return m.Pubkeys + } + return nil +} + +func (m *MultisigRedeemScriptType) GetSignatures() [][]byte { + if m != nil { + return m.Signatures + } + return nil +} + +func (m *MultisigRedeemScriptType) GetM() uint32 { + if m != nil && m.M != nil { + return *m.M + } + return 0 +} + +// * +// Structure representing transaction input +// @used_in SimpleSignTx +// @used_in TransactionType +type TxInputType struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + PrevHash []byte `protobuf:"bytes,2,req,name=prev_hash,json=prevHash" json:"prev_hash,omitempty"` + PrevIndex *uint32 `protobuf:"varint,3,req,name=prev_index,json=prevIndex" json:"prev_index,omitempty"` + ScriptSig []byte `protobuf:"bytes,4,opt,name=script_sig,json=scriptSig" json:"script_sig,omitempty"` + Sequence *uint32 `protobuf:"varint,5,opt,name=sequence,def=4294967295" json:"sequence,omitempty"` + ScriptType *InputScriptType `protobuf:"varint,6,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"` + Multisig *MultisigRedeemScriptType `protobuf:"bytes,7,opt,name=multisig" json:"multisig,omitempty"` + Amount *uint64 `protobuf:"varint,8,opt,name=amount" json:"amount,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TxInputType) Reset() { *m = TxInputType{} } +func (m *TxInputType) String() string { return proto.CompactTextString(m) } +func (*TxInputType) ProtoMessage() {} +func (*TxInputType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +const Default_TxInputType_Sequence uint32 = 4294967295 +const Default_TxInputType_ScriptType InputScriptType = InputScriptType_SPENDADDRESS + +func (m *TxInputType) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *TxInputType) GetPrevHash() []byte { + if m != nil { + return m.PrevHash + } + return nil +} + +func (m *TxInputType) GetPrevIndex() uint32 { + if m != nil && m.PrevIndex != nil { + return *m.PrevIndex + } + return 0 +} + +func (m *TxInputType) GetScriptSig() []byte { + if m != nil { + return m.ScriptSig + } + return nil +} + +func (m *TxInputType) GetSequence() uint32 { + if m != nil && m.Sequence != nil { + return *m.Sequence + } + return Default_TxInputType_Sequence +} + +func (m *TxInputType) GetScriptType() InputScriptType { + if m != nil && m.ScriptType != nil { + return *m.ScriptType + } + return Default_TxInputType_ScriptType +} + +func (m *TxInputType) GetMultisig() *MultisigRedeemScriptType { + if m != nil { + return m.Multisig + } + return nil +} + +func (m *TxInputType) GetAmount() uint64 { + if m != nil && m.Amount != nil { + return *m.Amount + } + return 0 +} + +// * +// Structure representing transaction output +// @used_in SimpleSignTx +// @used_in TransactionType +type TxOutputType struct { + Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` + AddressN []uint32 `protobuf:"varint,2,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + Amount *uint64 `protobuf:"varint,3,req,name=amount" json:"amount,omitempty"` + ScriptType *OutputScriptType `protobuf:"varint,4,req,name=script_type,json=scriptType,enum=OutputScriptType" json:"script_type,omitempty"` + Multisig *MultisigRedeemScriptType `protobuf:"bytes,5,opt,name=multisig" json:"multisig,omitempty"` + OpReturnData []byte `protobuf:"bytes,6,opt,name=op_return_data,json=opReturnData" json:"op_return_data,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TxOutputType) Reset() { *m = TxOutputType{} } +func (m *TxOutputType) String() string { return proto.CompactTextString(m) } +func (*TxOutputType) ProtoMessage() {} +func (*TxOutputType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *TxOutputType) GetAddress() string { + if m != nil && m.Address != nil { + return *m.Address + } + return "" +} + +func (m *TxOutputType) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *TxOutputType) GetAmount() uint64 { + if m != nil && m.Amount != nil { + return *m.Amount + } + return 0 +} + +func (m *TxOutputType) GetScriptType() OutputScriptType { + if m != nil && m.ScriptType != nil { + return *m.ScriptType + } + return OutputScriptType_PAYTOADDRESS +} + +func (m *TxOutputType) GetMultisig() *MultisigRedeemScriptType { + if m != nil { + return m.Multisig + } + return nil +} + +func (m *TxOutputType) GetOpReturnData() []byte { + if m != nil { + return m.OpReturnData + } + return nil +} + +// * +// Structure representing compiled transaction output +// @used_in TransactionType +type TxOutputBinType struct { + Amount *uint64 `protobuf:"varint,1,req,name=amount" json:"amount,omitempty"` + ScriptPubkey []byte `protobuf:"bytes,2,req,name=script_pubkey,json=scriptPubkey" json:"script_pubkey,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TxOutputBinType) Reset() { *m = TxOutputBinType{} } +func (m *TxOutputBinType) String() string { return proto.CompactTextString(m) } +func (*TxOutputBinType) ProtoMessage() {} +func (*TxOutputBinType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *TxOutputBinType) GetAmount() uint64 { + if m != nil && m.Amount != nil { + return *m.Amount + } + return 0 +} + +func (m *TxOutputBinType) GetScriptPubkey() []byte { + if m != nil { + return m.ScriptPubkey + } + return nil +} + +// * +// Structure representing transaction +// @used_in SimpleSignTx +type TransactionType struct { + Version *uint32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` + Inputs []*TxInputType `protobuf:"bytes,2,rep,name=inputs" json:"inputs,omitempty"` + BinOutputs []*TxOutputBinType `protobuf:"bytes,3,rep,name=bin_outputs,json=binOutputs" json:"bin_outputs,omitempty"` + Outputs []*TxOutputType `protobuf:"bytes,5,rep,name=outputs" json:"outputs,omitempty"` + LockTime *uint32 `protobuf:"varint,4,opt,name=lock_time,json=lockTime" json:"lock_time,omitempty"` + InputsCnt *uint32 `protobuf:"varint,6,opt,name=inputs_cnt,json=inputsCnt" json:"inputs_cnt,omitempty"` + OutputsCnt *uint32 `protobuf:"varint,7,opt,name=outputs_cnt,json=outputsCnt" json:"outputs_cnt,omitempty"` + ExtraData []byte `protobuf:"bytes,8,opt,name=extra_data,json=extraData" json:"extra_data,omitempty"` + ExtraDataLen *uint32 `protobuf:"varint,9,opt,name=extra_data_len,json=extraDataLen" json:"extra_data_len,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TransactionType) Reset() { *m = TransactionType{} } +func (m *TransactionType) String() string { return proto.CompactTextString(m) } +func (*TransactionType) ProtoMessage() {} +func (*TransactionType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *TransactionType) GetVersion() uint32 { + if m != nil && m.Version != nil { + return *m.Version + } + return 0 +} + +func (m *TransactionType) GetInputs() []*TxInputType { + if m != nil { + return m.Inputs + } + return nil +} + +func (m *TransactionType) GetBinOutputs() []*TxOutputBinType { + if m != nil { + return m.BinOutputs + } + return nil +} + +func (m *TransactionType) GetOutputs() []*TxOutputType { + if m != nil { + return m.Outputs + } + return nil +} + +func (m *TransactionType) GetLockTime() uint32 { + if m != nil && m.LockTime != nil { + return *m.LockTime + } + return 0 +} + +func (m *TransactionType) GetInputsCnt() uint32 { + if m != nil && m.InputsCnt != nil { + return *m.InputsCnt + } + return 0 +} + +func (m *TransactionType) GetOutputsCnt() uint32 { + if m != nil && m.OutputsCnt != nil { + return *m.OutputsCnt + } + return 0 +} + +func (m *TransactionType) GetExtraData() []byte { + if m != nil { + return m.ExtraData + } + return nil +} + +func (m *TransactionType) GetExtraDataLen() uint32 { + if m != nil && m.ExtraDataLen != nil { + return *m.ExtraDataLen + } + return 0 +} + +// * +// Structure representing request details +// @used_in TxRequest +type TxRequestDetailsType struct { + RequestIndex *uint32 `protobuf:"varint,1,opt,name=request_index,json=requestIndex" json:"request_index,omitempty"` + TxHash []byte `protobuf:"bytes,2,opt,name=tx_hash,json=txHash" json:"tx_hash,omitempty"` + ExtraDataLen *uint32 `protobuf:"varint,3,opt,name=extra_data_len,json=extraDataLen" json:"extra_data_len,omitempty"` + ExtraDataOffset *uint32 `protobuf:"varint,4,opt,name=extra_data_offset,json=extraDataOffset" json:"extra_data_offset,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TxRequestDetailsType) Reset() { *m = TxRequestDetailsType{} } +func (m *TxRequestDetailsType) String() string { return proto.CompactTextString(m) } +func (*TxRequestDetailsType) ProtoMessage() {} +func (*TxRequestDetailsType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *TxRequestDetailsType) GetRequestIndex() uint32 { + if m != nil && m.RequestIndex != nil { + return *m.RequestIndex + } + return 0 +} + +func (m *TxRequestDetailsType) GetTxHash() []byte { + if m != nil { + return m.TxHash + } + return nil +} + +func (m *TxRequestDetailsType) GetExtraDataLen() uint32 { + if m != nil && m.ExtraDataLen != nil { + return *m.ExtraDataLen + } + return 0 +} + +func (m *TxRequestDetailsType) GetExtraDataOffset() uint32 { + if m != nil && m.ExtraDataOffset != nil { + return *m.ExtraDataOffset + } + return 0 +} + +// * +// Structure representing serialized data +// @used_in TxRequest +type TxRequestSerializedType struct { + SignatureIndex *uint32 `protobuf:"varint,1,opt,name=signature_index,json=signatureIndex" json:"signature_index,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` + SerializedTx []byte `protobuf:"bytes,3,opt,name=serialized_tx,json=serializedTx" json:"serialized_tx,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TxRequestSerializedType) Reset() { *m = TxRequestSerializedType{} } +func (m *TxRequestSerializedType) String() string { return proto.CompactTextString(m) } +func (*TxRequestSerializedType) ProtoMessage() {} +func (*TxRequestSerializedType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +func (m *TxRequestSerializedType) GetSignatureIndex() uint32 { + if m != nil && m.SignatureIndex != nil { + return *m.SignatureIndex + } + return 0 +} + +func (m *TxRequestSerializedType) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *TxRequestSerializedType) GetSerializedTx() []byte { + if m != nil { + return m.SerializedTx + } + return nil +} + +// * +// Structure representing identity data +// @used_in IdentityType +type IdentityType struct { + Proto *string `protobuf:"bytes,1,opt,name=proto" json:"proto,omitempty"` + User *string `protobuf:"bytes,2,opt,name=user" json:"user,omitempty"` + Host *string `protobuf:"bytes,3,opt,name=host" json:"host,omitempty"` + Port *string `protobuf:"bytes,4,opt,name=port" json:"port,omitempty"` + Path *string `protobuf:"bytes,5,opt,name=path" json:"path,omitempty"` + Index *uint32 `protobuf:"varint,6,opt,name=index,def=0" json:"index,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IdentityType) Reset() { *m = IdentityType{} } +func (m *IdentityType) String() string { return proto.CompactTextString(m) } +func (*IdentityType) ProtoMessage() {} +func (*IdentityType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +const Default_IdentityType_Index uint32 = 0 + +func (m *IdentityType) GetProto() string { + if m != nil && m.Proto != nil { + return *m.Proto + } + return "" +} + +func (m *IdentityType) GetUser() string { + if m != nil && m.User != nil { + return *m.User + } + return "" +} + +func (m *IdentityType) GetHost() string { + if m != nil && m.Host != nil { + return *m.Host + } + return "" +} + +func (m *IdentityType) GetPort() string { + if m != nil && m.Port != nil { + return *m.Port + } + return "" +} + +func (m *IdentityType) GetPath() string { + if m != nil && m.Path != nil { + return *m.Path + } + return "" +} + +func (m *IdentityType) GetIndex() uint32 { + if m != nil && m.Index != nil { + return *m.Index + } + return Default_IdentityType_Index +} + +var E_WireIn = &proto.ExtensionDesc{ + ExtendedType: (*google_protobuf.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50002, + Name: "wire_in", + Tag: "varint,50002,opt,name=wire_in,json=wireIn", + Filename: "types.proto", +} + +var E_WireOut = &proto.ExtensionDesc{ + ExtendedType: (*google_protobuf.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50003, + Name: "wire_out", + Tag: "varint,50003,opt,name=wire_out,json=wireOut", + Filename: "types.proto", +} + +var E_WireDebugIn = &proto.ExtensionDesc{ + ExtendedType: (*google_protobuf.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50004, + Name: "wire_debug_in", + Tag: "varint,50004,opt,name=wire_debug_in,json=wireDebugIn", + Filename: "types.proto", +} + +var E_WireDebugOut = &proto.ExtensionDesc{ + ExtendedType: (*google_protobuf.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50005, + Name: "wire_debug_out", + Tag: "varint,50005,opt,name=wire_debug_out,json=wireDebugOut", + Filename: "types.proto", +} + +var E_WireTiny = &proto.ExtensionDesc{ + ExtendedType: (*google_protobuf.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50006, + Name: "wire_tiny", + Tag: "varint,50006,opt,name=wire_tiny,json=wireTiny", + Filename: "types.proto", +} + +var E_WireBootloader = &proto.ExtensionDesc{ + ExtendedType: (*google_protobuf.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50007, + Name: "wire_bootloader", + Tag: "varint,50007,opt,name=wire_bootloader,json=wireBootloader", + Filename: "types.proto", +} + +func init() { + proto.RegisterType((*HDNodeType)(nil), "HDNodeType") + proto.RegisterType((*HDNodePathType)(nil), "HDNodePathType") + proto.RegisterType((*CoinType)(nil), "CoinType") + proto.RegisterType((*MultisigRedeemScriptType)(nil), "MultisigRedeemScriptType") + proto.RegisterType((*TxInputType)(nil), "TxInputType") + proto.RegisterType((*TxOutputType)(nil), "TxOutputType") + proto.RegisterType((*TxOutputBinType)(nil), "TxOutputBinType") + proto.RegisterType((*TransactionType)(nil), "TransactionType") + proto.RegisterType((*TxRequestDetailsType)(nil), "TxRequestDetailsType") + proto.RegisterType((*TxRequestSerializedType)(nil), "TxRequestSerializedType") + proto.RegisterType((*IdentityType)(nil), "IdentityType") + proto.RegisterEnum("FailureType", FailureType_name, FailureType_value) + proto.RegisterEnum("OutputScriptType", OutputScriptType_name, OutputScriptType_value) + proto.RegisterEnum("InputScriptType", InputScriptType_name, InputScriptType_value) + proto.RegisterEnum("RequestType", RequestType_name, RequestType_value) + proto.RegisterEnum("ButtonRequestType", ButtonRequestType_name, ButtonRequestType_value) + proto.RegisterEnum("PinMatrixRequestType", PinMatrixRequestType_name, PinMatrixRequestType_value) + proto.RegisterEnum("RecoveryDeviceType", RecoveryDeviceType_name, RecoveryDeviceType_value) + proto.RegisterEnum("WordRequestType", WordRequestType_name, WordRequestType_value) + proto.RegisterExtension(E_WireIn) + proto.RegisterExtension(E_WireOut) + proto.RegisterExtension(E_WireDebugIn) + proto.RegisterExtension(E_WireDebugOut) + proto.RegisterExtension(E_WireTiny) + proto.RegisterExtension(E_WireBootloader) +} + +func init() { proto.RegisterFile("types.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 1899 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdb, 0x72, 0x1a, 0xc9, + 0x19, 0xf6, 0x00, 0x92, 0xe0, 0x07, 0xc4, 0xa8, 0x7d, 0xd0, 0x78, 0x6d, 0xaf, 0x31, 0x76, 0x62, + 0x45, 0x55, 0x61, 0x77, 0xc9, 0x5a, 0x8e, 0x55, 0xa9, 0x24, 0x3a, 0xa0, 0x15, 0x65, 0x0b, 0x51, + 0xc3, 0x28, 0x56, 0x72, 0x33, 0x35, 0xcc, 0xb4, 0xa0, 0x4b, 0x43, 0x37, 0xe9, 0xe9, 0x91, 0xd1, + 0xde, 0xe4, 0x2a, 0xc9, 0x55, 0x5e, 0x23, 0x6f, 0x91, 0xaa, 0xbc, 0x41, 0xaa, 0x36, 0xa7, 0xcb, + 0xbc, 0x41, 0xae, 0xf2, 0x00, 0xa9, 0x3e, 0x0c, 0x02, 0xc9, 0xde, 0xd2, 0x1d, 0xfd, 0x7d, 0xff, + 0xf9, 0xd0, 0x3d, 0x40, 0x59, 0x5c, 0x4e, 0x70, 0xd2, 0x9c, 0x70, 0x26, 0xd8, 0x67, 0xf5, 0x21, + 0x63, 0xc3, 0x18, 0x7f, 0xa1, 0x4e, 0x83, 0xf4, 0xec, 0x8b, 0x08, 0x27, 0x21, 0x27, 0x13, 0xc1, + 0xb8, 0x96, 0x68, 0xfc, 0xd5, 0x02, 0x38, 0xdc, 0xef, 0xb2, 0x08, 0x7b, 0x97, 0x13, 0x8c, 0xee, + 0xc1, 0x52, 0x84, 0x27, 0x62, 0xe4, 0x58, 0xf5, 0xdc, 0x46, 0xd5, 0xd5, 0x07, 0x54, 0x87, 0xf2, + 0x19, 0xa1, 0x43, 0xcc, 0x27, 0x9c, 0x50, 0xe1, 0xe4, 0x14, 0x37, 0x0f, 0xa1, 0x47, 0x50, 0x0a, + 0x47, 0x24, 0x8e, 0x7c, 0x9a, 0x8e, 0x9d, 0xbc, 0xe2, 0x8b, 0x0a, 0xe8, 0xa6, 0x63, 0xf4, 0x04, + 0x20, 0x1c, 0x05, 0x84, 0xfa, 0x21, 0x8b, 0xb0, 0x53, 0xa8, 0xe7, 0x36, 0x2a, 0x6e, 0x49, 0x21, + 0x7b, 0x2c, 0xc2, 0xe8, 0x29, 0x94, 0x27, 0x9c, 0x5c, 0x04, 0x02, 0xfb, 0xe7, 0xf8, 0xd2, 0x59, + 0xaa, 0x5b, 0x1b, 0x15, 0x17, 0x0c, 0xf4, 0x16, 0x5f, 0x4a, 0xfd, 0x49, 0x3a, 0x88, 0x49, 0xa8, + 0xf8, 0x65, 0xc5, 0x97, 0x34, 0xf2, 0x16, 0x5f, 0x36, 0xba, 0xb0, 0xaa, 0x33, 0xe8, 0x05, 0x62, + 0xa4, 0xb2, 0x78, 0x0a, 0x05, 0x2a, 0x5d, 0xc9, 0x24, 0xca, 0xad, 0x72, 0xf3, 0x2a, 0x41, 0x57, + 0x11, 0x32, 0xdc, 0x20, 0x8a, 0x38, 0x4e, 0x12, 0x9f, 0x3a, 0xb9, 0x7a, 0x5e, 0x86, 0x6b, 0x80, + 0x6e, 0xe3, 0x7f, 0x39, 0x28, 0xee, 0x31, 0x42, 0x95, 0x29, 0x99, 0x18, 0x23, 0xd4, 0xa7, 0xc1, + 0x58, 0xda, 0xb3, 0x36, 0x4a, 0x6e, 0x51, 0x02, 0xdd, 0x60, 0x8c, 0xd1, 0x73, 0xa8, 0x2a, 0x32, + 0x19, 0x31, 0x2e, 0xc2, 0x54, 0x56, 0x46, 0x0a, 0x54, 0x24, 0xd8, 0x37, 0x18, 0x7a, 0x01, 0x95, + 0xcc, 0x97, 0x6c, 0x8d, 0x93, 0xaf, 0x5b, 0x1b, 0xd5, 0x6d, 0xeb, 0x4b, 0xb7, 0x6c, 0xe0, 0xcc, + 0xcf, 0x38, 0x98, 0x9e, 0x61, 0xec, 0x9f, 0x0f, 0x9c, 0x42, 0xdd, 0xda, 0x28, 0xb8, 0x45, 0x0d, + 0xbc, 0x1d, 0xa0, 0x1f, 0xc3, 0xda, 0xbc, 0x09, 0x7f, 0xd2, 0x4a, 0x46, 0xaa, 0x4e, 0xd5, 0x6d, + 0xeb, 0x95, 0x5b, 0x9b, 0xb3, 0xd3, 0x6b, 0x25, 0x23, 0xd4, 0x82, 0xfb, 0x09, 0x19, 0x52, 0x1c, + 0xf9, 0x63, 0x9c, 0x24, 0xc1, 0x10, 0xfb, 0x23, 0x1c, 0x44, 0x98, 0x3b, 0x45, 0x15, 0xde, 0x5d, + 0x4d, 0x1e, 0x69, 0xee, 0x50, 0x51, 0xe8, 0x25, 0xc0, 0x74, 0x92, 0x0e, 0xfc, 0x71, 0x30, 0x24, + 0xa1, 0x53, 0x52, 0xb6, 0x8b, 0xaf, 0xb7, 0xbe, 0xdc, 0x7a, 0xfd, 0x93, 0x57, 0x3f, 0x75, 0x4b, + 0x92, 0x3b, 0x92, 0x94, 0x16, 0xe4, 0x17, 0x46, 0x10, 0xae, 0x04, 0xb7, 0x5a, 0xaf, 0xb7, 0xa4, + 0x20, 0xbf, 0xd0, 0x82, 0x0f, 0x60, 0x39, 0xc1, 0xc3, 0x0f, 0x44, 0x38, 0xe5, 0xba, 0xb5, 0x51, + 0x74, 0xcd, 0x49, 0xe2, 0x67, 0x8c, 0x9f, 0x93, 0xc8, 0xa9, 0x48, 0x65, 0xd7, 0x9c, 0x1a, 0x09, + 0x38, 0x47, 0x69, 0x2c, 0x48, 0x42, 0x86, 0x2e, 0x8e, 0x30, 0x1e, 0xf7, 0xd5, 0xa4, 0xaa, 0xea, + 0xfc, 0x08, 0x56, 0x26, 0xe9, 0xe0, 0x1c, 0x5f, 0x26, 0x8e, 0x55, 0xcf, 0x6f, 0x94, 0x5b, 0xb5, + 0xe6, 0x62, 0xcb, 0xdd, 0x8c, 0x47, 0x9f, 0x03, 0xc8, 0xfc, 0x02, 0x91, 0x72, 0x9c, 0xa8, 0xde, + 0x56, 0xdc, 0x39, 0x04, 0x55, 0xc0, 0x1a, 0xeb, 0x1e, 0xb8, 0xd6, 0xb8, 0xf1, 0x97, 0x1c, 0x94, + 0xbd, 0x69, 0x87, 0x4e, 0x52, 0x91, 0xb5, 0xe1, 0x6a, 0x30, 0xac, 0xc5, 0xc1, 0x90, 0xe4, 0x84, + 0xe3, 0x0b, 0x7f, 0x14, 0x24, 0x23, 0xb5, 0x04, 0x15, 0xb7, 0x28, 0x81, 0xc3, 0x20, 0x19, 0xa9, + 0x21, 0x95, 0x24, 0xa1, 0x11, 0x9e, 0x9a, 0x15, 0x50, 0xe2, 0x1d, 0x09, 0x48, 0x5a, 0x6f, 0x9e, + 0x9f, 0x90, 0xa1, 0x6a, 0x70, 0xc5, 0x2d, 0x69, 0xa4, 0x4f, 0x86, 0xe8, 0x87, 0x50, 0x4c, 0xf0, + 0x6f, 0x53, 0x4c, 0x43, 0x6c, 0x1a, 0x0b, 0x5f, 0xb7, 0xde, 0x7c, 0xfd, 0x66, 0xeb, 0x75, 0xeb, + 0xcd, 0x2b, 0x77, 0xc6, 0xa1, 0x5f, 0x40, 0xd9, 0x98, 0x51, 0xb3, 0x24, 0x77, 0x61, 0xb5, 0x65, + 0x37, 0x55, 0x02, 0x57, 0xf5, 0xda, 0xae, 0xf4, 0x7b, 0xed, 0xee, 0xfe, 0xce, 0xfe, 0xbe, 0xdb, + 0xee, 0xf7, 0x5d, 0xe3, 0x59, 0x25, 0xf8, 0x0a, 0x8a, 0x63, 0x53, 0x65, 0x67, 0xa5, 0x6e, 0x6d, + 0x94, 0x5b, 0x0f, 0x9b, 0x9f, 0x2a, 0xbb, 0x3b, 0x13, 0x95, 0x4d, 0x0b, 0xc6, 0x2c, 0xa5, 0x42, + 0xcd, 0x50, 0xc1, 0x35, 0xa7, 0xc6, 0x7f, 0x2d, 0xa8, 0x78, 0xd3, 0xe3, 0x54, 0x64, 0x05, 0x74, + 0x60, 0xc5, 0xd4, 0xcb, 0x6c, 0x4b, 0x76, 0xfc, 0xde, 0x9d, 0x9b, 0xb3, 0x2f, 0x2b, 0x37, 0xb3, + 0x8f, 0x5a, 0x8b, 0xf9, 0xca, 0xbb, 0x63, 0xb5, 0xb5, 0xd6, 0xd4, 0x0e, 0xe7, 0x22, 0xfd, 0x54, + 0x8a, 0x4b, 0xb7, 0x4f, 0xf1, 0x05, 0xac, 0xb2, 0x89, 0xcf, 0xb1, 0x48, 0x39, 0xf5, 0xa3, 0x40, + 0x04, 0xe6, 0xa6, 0xa9, 0xb0, 0x89, 0xab, 0xc0, 0xfd, 0x40, 0x04, 0x8d, 0x2e, 0xd4, 0xb2, 0x7c, + 0x77, 0xcd, 0x15, 0x71, 0x15, 0xbb, 0xb5, 0x10, 0xfb, 0x73, 0xa8, 0x9a, 0xd8, 0xf5, 0x6c, 0x9a, + 0x91, 0xa9, 0x68, 0xb0, 0xa7, 0xb0, 0xc6, 0xdf, 0x72, 0x50, 0xf3, 0x78, 0x40, 0x93, 0x20, 0x14, + 0x84, 0xd1, 0xac, 0x86, 0x17, 0x98, 0x27, 0x84, 0x51, 0x55, 0xc3, 0xaa, 0x9b, 0x1d, 0xd1, 0x0b, + 0x58, 0x26, 0xb2, 0xd5, 0x7a, 0xb0, 0xcb, 0xad, 0x4a, 0x73, 0x6e, 0x78, 0x5d, 0xc3, 0xa1, 0xaf, + 0xa0, 0x3c, 0x20, 0xd4, 0x67, 0x2a, 0xca, 0xc4, 0xc9, 0x2b, 0x51, 0xbb, 0x79, 0x2d, 0x6e, 0x17, + 0x06, 0x84, 0x6a, 0x24, 0x41, 0x2f, 0x61, 0x25, 0x13, 0x5f, 0x52, 0xe2, 0xd5, 0xe6, 0x7c, 0x5b, + 0xdd, 0x8c, 0x95, 0x5d, 0x8c, 0x59, 0x78, 0xee, 0x0b, 0x32, 0xc6, 0x6a, 0x8c, 0xab, 0x6e, 0x51, + 0x02, 0x1e, 0x19, 0x63, 0x39, 0xe4, 0x3a, 0x04, 0x3f, 0xa4, 0x42, 0x95, 0xaf, 0xea, 0x96, 0x34, + 0xb2, 0x47, 0x85, 0xbc, 0xe8, 0x8d, 0x19, 0xc5, 0xaf, 0x28, 0x1e, 0x0c, 0x24, 0x05, 0x9e, 0x00, + 0xe0, 0xa9, 0xe0, 0x81, 0x2e, 0x7f, 0x51, 0x2f, 0x89, 0x42, 0x64, 0xed, 0x65, 0x87, 0xae, 0x68, + 0x3f, 0xc6, 0x54, 0xdf, 0x53, 0x6e, 0x65, 0x26, 0xf2, 0x0e, 0xd3, 0xc6, 0x9f, 0x2d, 0xb8, 0xe7, + 0x4d, 0x5d, 0xb9, 0x31, 0x89, 0xd8, 0xc7, 0x22, 0x20, 0xb1, 0xbe, 0x62, 0x9f, 0x43, 0x95, 0x6b, + 0xd4, 0x2c, 0xa9, 0x2e, 0x6e, 0xc5, 0x80, 0x7a, 0x4f, 0xd7, 0x61, 0x45, 0x4c, 0xb3, 0x0d, 0x97, + 0xfe, 0x97, 0xc5, 0x54, 0xed, 0xf7, 0x4d, 0xe7, 0xf9, 0x9b, 0xce, 0xd1, 0x26, 0xac, 0xcd, 0x49, + 0xb1, 0xb3, 0xb3, 0x04, 0x0b, 0x53, 0xa6, 0xda, 0x4c, 0xf0, 0x58, 0xc1, 0x8d, 0xdf, 0x5b, 0xb0, + 0x3e, 0x0b, 0xb4, 0x8f, 0x39, 0x09, 0x62, 0xf2, 0x2d, 0x8e, 0x54, 0xac, 0x2f, 0xa1, 0x36, 0xbb, + 0xb3, 0x16, 0xa2, 0x5d, 0x9d, 0xc1, 0x3a, 0xde, 0xc7, 0x50, 0x9a, 0x21, 0x26, 0xe2, 0x2b, 0x40, + 0x8d, 0xe0, 0xcc, 0xb0, 0x2f, 0xa6, 0x2a, 0x66, 0x39, 0x82, 0x57, 0xde, 0xa6, 0x8d, 0x3f, 0x59, + 0x50, 0xe9, 0x44, 0x98, 0x0a, 0x22, 0x2e, 0xb3, 0x8f, 0x00, 0xf5, 0x71, 0x60, 0x36, 0x58, 0x1f, + 0x10, 0x82, 0x42, 0x9a, 0x60, 0x6e, 0xde, 0x38, 0xf5, 0x5b, 0x62, 0x23, 0x96, 0x08, 0x65, 0xb6, + 0xe4, 0xaa, 0xdf, 0x12, 0x9b, 0x30, 0xae, 0xb3, 0x2e, 0xb9, 0xea, 0xb7, 0xc2, 0x02, 0xa1, 0xdf, + 0x2c, 0x89, 0x05, 0x62, 0x84, 0xd6, 0x61, 0x49, 0x27, 0xb6, 0x9c, 0x3d, 0x88, 0xfa, 0xbc, 0xf9, + 0x5d, 0x0e, 0xca, 0x07, 0x01, 0x89, 0x53, 0xae, 0xbf, 0x49, 0x9e, 0xc0, 0x43, 0x73, 0xf4, 0x4f, + 0x28, 0x9e, 0x4e, 0x70, 0x28, 0x66, 0xaf, 0x97, 0x6d, 0xa1, 0xcf, 0xe0, 0x41, 0x46, 0xef, 0xa6, + 0x42, 0x30, 0xda, 0x36, 0x22, 0x76, 0x0e, 0xdd, 0x87, 0xb5, 0x8c, 0x93, 0x85, 0x6f, 0x73, 0xce, + 0xb8, 0x9d, 0x47, 0x8f, 0x60, 0x3d, 0x83, 0x77, 0xd4, 0xda, 0xed, 0x05, 0x34, 0xc4, 0x71, 0x8c, + 0x23, 0xbb, 0x80, 0xd6, 0xe1, 0x6e, 0x46, 0xf6, 0xc8, 0x95, 0xb1, 0x25, 0xe4, 0xc0, 0xbd, 0x39, + 0xe2, 0x4a, 0x65, 0x19, 0x3d, 0x00, 0x34, 0xc7, 0x74, 0xe8, 0x45, 0x10, 0x93, 0xc8, 0x5e, 0x41, + 0x8f, 0xc1, 0xc9, 0x70, 0x03, 0xf6, 0xb3, 0xd6, 0xd8, 0xc5, 0x05, 0x7b, 0x9c, 0x85, 0x38, 0x49, + 0x74, 0x7c, 0xa5, 0xf9, 0x94, 0xba, 0x4c, 0xb4, 0x29, 0x4b, 0x87, 0xa3, 0x83, 0x94, 0x46, 0x89, + 0x0d, 0xd7, 0xb8, 0x0e, 0x25, 0xc2, 0x74, 0xd2, 0x2e, 0xa3, 0x87, 0x70, 0x3f, 0xe3, 0x0e, 0x08, + 0x1f, 0x7f, 0x08, 0x38, 0xd6, 0x26, 0xc3, 0xcd, 0x3f, 0x5a, 0x60, 0x5f, 0xbf, 0x35, 0x91, 0x0d, + 0x95, 0xde, 0xce, 0xaf, 0xbd, 0x63, 0xf3, 0x50, 0xd8, 0x77, 0xd0, 0x5d, 0xa8, 0x29, 0xa4, 0xbf, + 0xe7, 0x76, 0x7a, 0xde, 0xe1, 0x4e, 0xff, 0xd0, 0xb6, 0xd0, 0x1a, 0x54, 0x15, 0x78, 0x74, 0xf2, + 0xce, 0xeb, 0xf4, 0x3b, 0xdf, 0xd8, 0xb9, 0x19, 0x74, 0xdc, 0x73, 0xdb, 0xde, 0x89, 0xdb, 0xb5, + 0xf3, 0x33, 0x63, 0xef, 0x3b, 0x5e, 0x57, 0x1a, 0x2b, 0xa0, 0x7b, 0x60, 0x2b, 0xa4, 0xd7, 0xea, + 0x1f, 0x66, 0xe8, 0xd2, 0x66, 0x0c, 0xb5, 0x6b, 0xcf, 0x95, 0x54, 0x9d, 0x7f, 0xb0, 0xec, 0x3b, + 0xd2, 0xbe, 0x42, 0x66, 0x2e, 0x2d, 0x54, 0x81, 0x62, 0xfb, 0xd4, 0x6b, 0xbb, 0xdd, 0x9d, 0x77, + 0x76, 0x6e, 0xa6, 0x92, 0xd9, 0xcd, 0x4b, 0x6f, 0x0a, 0x99, 0xf7, 0x56, 0xd8, 0x3c, 0x81, 0xb2, + 0xd9, 0x30, 0xe5, 0xa9, 0x0c, 0x2b, 0xde, 0x69, 0xa7, 0xdb, 0x3b, 0xf1, 0xec, 0x3b, 0xd2, 0xa2, + 0x77, 0x7a, 0x7c, 0xe2, 0xc9, 0x93, 0x85, 0x00, 0x96, 0xbd, 0xd3, 0xa3, 0xb6, 0xb7, 0x63, 0xe7, + 0xd0, 0x2a, 0x80, 0x77, 0x7a, 0xd0, 0xe9, 0x76, 0xfa, 0x87, 0xed, 0x7d, 0x3b, 0x8f, 0x6a, 0x50, + 0xf6, 0x4e, 0xdb, 0xa7, 0x9e, 0xbb, 0xb3, 0xbf, 0xe3, 0xed, 0xd8, 0x85, 0xcd, 0xff, 0xe4, 0x60, + 0x4d, 0x4f, 0xdb, 0xbc, 0xf5, 0x75, 0xb8, 0xbb, 0x00, 0xfa, 0xc7, 0x62, 0x84, 0xb9, 0x6d, 0xa1, + 0x06, 0x7c, 0xbe, 0x48, 0x1c, 0x60, 0x7c, 0x7c, 0x81, 0xb9, 0x37, 0xe2, 0x38, 0x19, 0xb1, 0x58, + 0xce, 0xea, 0x53, 0x78, 0xb4, 0x28, 0xb3, 0xc7, 0xe8, 0x19, 0xe1, 0x63, 0xdd, 0x35, 0x3b, 0x2f, + 0xf7, 0x60, 0x51, 0xc0, 0xc5, 0x09, 0x16, 0xfb, 0xf8, 0x82, 0x84, 0xd8, 0x2e, 0xdc, 0xa4, 0x8d, + 0xfe, 0x7b, 0xc6, 0xe5, 0xf4, 0x3e, 0x06, 0x67, 0x91, 0x7e, 0x4f, 0x26, 0xd8, 0x28, 0x2f, 0xdf, + 0x54, 0xee, 0x71, 0x26, 0x70, 0x28, 0xf6, 0x82, 0x38, 0xb6, 0x57, 0xe4, 0xa8, 0x2e, 0xd2, 0x72, + 0x8e, 0xbd, 0xa9, 0x5d, 0xbc, 0x19, 0x75, 0x36, 0x78, 0x7b, 0x23, 0x1c, 0x9e, 0xdb, 0x25, 0x39, + 0x93, 0x8b, 0x02, 0x3b, 0xfa, 0xcd, 0xb7, 0x41, 0xae, 0xe1, 0x35, 0xa7, 0xd9, 0x37, 0xbd, 0x5d, + 0xde, 0xfc, 0x1d, 0xdc, 0xeb, 0x11, 0x7a, 0x14, 0x08, 0x4e, 0xa6, 0xf3, 0x35, 0xae, 0xc3, 0xe3, + 0x8f, 0xe1, 0xfe, 0x5e, 0xca, 0x39, 0xa6, 0xc2, 0xb6, 0xd0, 0x33, 0x78, 0xf2, 0x51, 0x89, 0x2e, + 0xfe, 0x70, 0x40, 0x78, 0x22, 0xec, 0x9c, 0xec, 0xc7, 0xa7, 0x44, 0xfa, 0x38, 0x64, 0x34, 0xb2, + 0xf3, 0x9b, 0xbf, 0x01, 0xe4, 0xe2, 0x90, 0x5d, 0x60, 0x7e, 0xa9, 0xcb, 0xa4, 0xdc, 0xff, 0x00, + 0x9e, 0xdd, 0x44, 0xfd, 0x7e, 0xc8, 0x83, 0xf1, 0x20, 0xc6, 0x91, 0x2c, 0x76, 0x62, 0xdf, 0x91, + 0xf5, 0xfc, 0x88, 0x98, 0x76, 0x68, 0x5b, 0x9b, 0x67, 0x50, 0x93, 0x92, 0xf3, 0x79, 0x3d, 0x84, + 0xfb, 0xd7, 0x20, 0xbf, 0x17, 0x07, 0x84, 0xda, 0x77, 0x64, 0x9d, 0xae, 0x53, 0xda, 0xd2, 0x1b, + 0xdb, 0xfa, 0x34, 0xb9, 0x65, 0xe7, 0xb6, 0x7f, 0x06, 0x2b, 0x1f, 0x88, 0x7a, 0x41, 0xd0, 0xb3, + 0xa6, 0xfe, 0x2f, 0xd8, 0xcc, 0xfe, 0x0b, 0x36, 0xdb, 0x34, 0x1d, 0xff, 0x2a, 0x88, 0x53, 0x7c, + 0x3c, 0x91, 0x77, 0x60, 0xe2, 0x7c, 0xf7, 0x87, 0xbc, 0xfe, 0x52, 0x97, 0x3a, 0x1d, 0xba, 0xfd, + 0x73, 0x28, 0x2a, 0x6d, 0x96, 0x8a, 0xdb, 0xa8, 0xff, 0xdd, 0xa8, 0x2b, 0x97, 0xc7, 0xa9, 0xd8, + 0xfe, 0x06, 0xaa, 0x4a, 0x3f, 0xc2, 0x83, 0x74, 0x78, 0xcb, 0x18, 0xfe, 0x61, 0x8c, 0x94, 0xa5, + 0xe6, 0xbe, 0x54, 0xec, 0xd0, 0xed, 0x0e, 0xac, 0xce, 0x19, 0xba, 0x65, 0x38, 0xff, 0x34, 0x96, + 0x2a, 0x33, 0x4b, 0x32, 0xa6, 0x5f, 0x42, 0x49, 0x99, 0x12, 0x84, 0x5e, 0xde, 0xc6, 0xca, 0xbf, + 0x8c, 0x15, 0x55, 0x09, 0x8f, 0xd0, 0xcb, 0xed, 0x77, 0x50, 0x53, 0x16, 0x06, 0x8c, 0x89, 0x98, + 0xa9, 0x3f, 0x4f, 0xb7, 0xb0, 0xf3, 0x6f, 0x63, 0x47, 0x25, 0xb2, 0x3b, 0x53, 0xdd, 0xfd, 0x0a, + 0x9e, 0x87, 0x6c, 0xdc, 0x4c, 0x02, 0xc1, 0x92, 0x11, 0x89, 0x83, 0x41, 0xd2, 0x14, 0x1c, 0x7f, + 0xcb, 0x78, 0x33, 0x26, 0x83, 0x99, 0xbd, 0x5d, 0xf0, 0x14, 0x28, 0xdb, 0xfb, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x70, 0x88, 0xcd, 0x71, 0xe2, 0x0f, 0x00, 0x00, +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/types.proto b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/types.proto new file mode 100644 index 0000000000..acbe79e3ff --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/types.proto @@ -0,0 +1,278 @@ +// This file originates from the SatoshiLabs Trezor `common` repository at: +// https://github.com/trezor/trezor-common/blob/master/protob/types.proto +// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b. + +syntax = "proto2"; + +/** + * Types for TREZOR communication + * + * @author Marek Palatinus + * @version 1.2 + */ + +// Sugar for easier handling in Java +option java_package = "com.satoshilabs.trezor.lib.protobuf"; +option java_outer_classname = "TrezorType"; + +import "google/protobuf/descriptor.proto"; + +/** + * Options for specifying message direction and type of wire (normal/debug) + */ +extend google.protobuf.EnumValueOptions { + optional bool wire_in = 50002; // message can be transmitted via wire from PC to TREZOR + optional bool wire_out = 50003; // message can be transmitted via wire from TREZOR to PC + optional bool wire_debug_in = 50004; // message can be transmitted via debug wire from PC to TREZOR + optional bool wire_debug_out = 50005; // message can be transmitted via debug wire from TREZOR to PC + optional bool wire_tiny = 50006; // message is handled by TREZOR when the USB stack is in tiny mode + optional bool wire_bootloader = 50007; // message is only handled by TREZOR Bootloader +} + +/** + * Type of failures returned by Failure message + * @used_in Failure + */ +enum FailureType { + Failure_UnexpectedMessage = 1; + Failure_ButtonExpected = 2; + Failure_DataError = 3; + Failure_ActionCancelled = 4; + Failure_PinExpected = 5; + Failure_PinCancelled = 6; + Failure_PinInvalid = 7; + Failure_InvalidSignature = 8; + Failure_ProcessError = 9; + Failure_NotEnoughFunds = 10; + Failure_NotInitialized = 11; + Failure_FirmwareError = 99; +} + +/** + * Type of script which will be used for transaction output + * @used_in TxOutputType + */ +enum OutputScriptType { + PAYTOADDRESS = 0; // used for all addresses (bitcoin, p2sh, witness) + PAYTOSCRIPTHASH = 1; // p2sh address (deprecated; use PAYTOADDRESS) + PAYTOMULTISIG = 2; // only for change output + PAYTOOPRETURN = 3; // op_return + PAYTOWITNESS = 4; // only for change output + PAYTOP2SHWITNESS = 5; // only for change output +} + +/** + * Type of script which will be used for transaction output + * @used_in TxInputType + */ +enum InputScriptType { + SPENDADDRESS = 0; // standard p2pkh address + SPENDMULTISIG = 1; // p2sh multisig address + EXTERNAL = 2; // reserved for external inputs (coinjoin) + SPENDWITNESS = 3; // native segwit + SPENDP2SHWITNESS = 4; // segwit over p2sh (backward compatible) +} + +/** + * Type of information required by transaction signing process + * @used_in TxRequest + */ +enum RequestType { + TXINPUT = 0; + TXOUTPUT = 1; + TXMETA = 2; + TXFINISHED = 3; + TXEXTRADATA = 4; +} + +/** + * Type of button request + * @used_in ButtonRequest + */ +enum ButtonRequestType { + ButtonRequest_Other = 1; + ButtonRequest_FeeOverThreshold = 2; + ButtonRequest_ConfirmOutput = 3; + ButtonRequest_ResetDevice = 4; + ButtonRequest_ConfirmWord = 5; + ButtonRequest_WipeDevice = 6; + ButtonRequest_ProtectCall = 7; + ButtonRequest_SignTx = 8; + ButtonRequest_FirmwareCheck = 9; + ButtonRequest_Address = 10; + ButtonRequest_PublicKey = 11; +} + +/** + * Type of PIN request + * @used_in PinMatrixRequest + */ +enum PinMatrixRequestType { + PinMatrixRequestType_Current = 1; + PinMatrixRequestType_NewFirst = 2; + PinMatrixRequestType_NewSecond = 3; +} + +/** + * Type of recovery procedure. These should be used as bitmask, e.g., + * `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix` + * listing every method supported by the host computer. + * + * Note that ScrambledWords must be supported by every implementation + * for backward compatibility; there is no way to not support it. + * + * @used_in RecoveryDevice + */ +enum RecoveryDeviceType { + // use powers of two when extending this field + RecoveryDeviceType_ScrambledWords = 0; // words in scrambled order + RecoveryDeviceType_Matrix = 1; // matrix recovery type +} + +/** + * Type of Recovery Word request + * @used_in WordRequest + */ +enum WordRequestType { + WordRequestType_Plain = 0; + WordRequestType_Matrix9 = 1; + WordRequestType_Matrix6 = 2; +} + +/** + * Structure representing BIP32 (hierarchical deterministic) node + * Used for imports of private key into the device and exporting public key out of device + * @used_in PublicKey + * @used_in LoadDevice + * @used_in DebugLinkState + * @used_in Storage + */ +message HDNodeType { + required uint32 depth = 1; + required uint32 fingerprint = 2; + required uint32 child_num = 3; + required bytes chain_code = 4; + optional bytes private_key = 5; + optional bytes public_key = 6; +} + +message HDNodePathType { + required HDNodeType node = 1; // BIP-32 node in deserialized form + repeated uint32 address_n = 2; // BIP-32 path to derive the key from node +} + +/** + * Structure representing Coin + * @used_in Features + */ +message CoinType { + optional string coin_name = 1; + optional string coin_shortcut = 2; + optional uint32 address_type = 3 [default=0]; + optional uint64 maxfee_kb = 4; + optional uint32 address_type_p2sh = 5 [default=5]; + optional string signed_message_header = 8; + optional uint32 xpub_magic = 9 [default=76067358]; // default=0x0488b21e + optional uint32 xprv_magic = 10 [default=76066276]; // default=0x0488ade4 + optional bool segwit = 11; + optional uint32 forkid = 12; +} + +/** + * Type of redeem script used in input + * @used_in TxInputType + */ +message MultisigRedeemScriptType { + repeated HDNodePathType pubkeys = 1; // pubkeys from multisig address (sorted lexicographically) + repeated bytes signatures = 2; // existing signatures for partially signed input + optional uint32 m = 3; // "m" from n, how many valid signatures is necessary for spending +} + +/** + * Structure representing transaction input + * @used_in SimpleSignTx + * @used_in TransactionType + */ +message TxInputType { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + required bytes prev_hash = 2; // hash of previous transaction output to spend by this input + required uint32 prev_index = 3; // index of previous output to spend + optional bytes script_sig = 4; // script signature, unset for tx to sign + optional uint32 sequence = 5 [default=4294967295]; // sequence (default=0xffffffff) + optional InputScriptType script_type = 6 [default=SPENDADDRESS]; // defines template of input script + optional MultisigRedeemScriptType multisig = 7; // Filled if input is going to spend multisig tx + optional uint64 amount = 8; // amount of previous transaction output (for segwit only) +} + +/** + * Structure representing transaction output + * @used_in SimpleSignTx + * @used_in TransactionType + */ +message TxOutputType { + optional string address = 1; // target coin address in Base58 encoding + repeated uint32 address_n = 2; // BIP-32 path to derive the key from master node; has higher priority than "address" + required uint64 amount = 3; // amount to spend in satoshis + required OutputScriptType script_type = 4; // output script type + optional MultisigRedeemScriptType multisig = 5; // defines multisig address; script_type must be PAYTOMULTISIG + optional bytes op_return_data = 6; // defines op_return data; script_type must be PAYTOOPRETURN, amount must be 0 +} + +/** + * Structure representing compiled transaction output + * @used_in TransactionType + */ +message TxOutputBinType { + required uint64 amount = 1; + required bytes script_pubkey = 2; +} + +/** + * Structure representing transaction + * @used_in SimpleSignTx + */ +message TransactionType { + optional uint32 version = 1; + repeated TxInputType inputs = 2; + repeated TxOutputBinType bin_outputs = 3; + repeated TxOutputType outputs = 5; + optional uint32 lock_time = 4; + optional uint32 inputs_cnt = 6; + optional uint32 outputs_cnt = 7; + optional bytes extra_data = 8; + optional uint32 extra_data_len = 9; +} + +/** + * Structure representing request details + * @used_in TxRequest + */ +message TxRequestDetailsType { + optional uint32 request_index = 1; // device expects TxAck message from the computer + optional bytes tx_hash = 2; // tx_hash of requested transaction + optional uint32 extra_data_len = 3; // length of requested extra data + optional uint32 extra_data_offset = 4; // offset of requested extra data +} + +/** + * Structure representing serialized data + * @used_in TxRequest + */ +message TxRequestSerializedType { + optional uint32 signature_index = 1; // 'signature' field contains signed input of this index + optional bytes signature = 2; // signature of the signature_index input + optional bytes serialized_tx = 3; // part of serialized and signed transaction +} + +/** + * Structure representing identity data + * @used_in IdentityType + */ +message IdentityType { + optional string proto = 1; // proto part of URI + optional string user = 2; // user part of URI + optional string host = 3; // host part of URI + optional string port = 4; // port part of URI + optional string path = 5; // path part of URI + optional uint32 index = 6 [default=0]; // identity index +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/wallet.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/wallet.go new file mode 100644 index 0000000000..2ddfa30a6c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/wallet.go @@ -0,0 +1,577 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package usbwallet implements support for USB hardware wallets. +package usbwallet + +import ( + "context" + "fmt" + "io" + "math/big" + "sync" + "time" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/karalabe/hid" +) + +// Maximum time between wallet health checks to detect USB unplugs. +const heartbeatCycle = time.Second + +// Minimum time to wait between self derivation attempts, even it the user is +// requesting accounts like crazy. +const selfDeriveThrottling = time.Second + +// driver defines the vendor specific functionality hardware wallets instances +// must implement to allow using them with the wallet lifecycle management. +type driver interface { + // Status returns a textual status to aid the user in the current state of the + // wallet. It also returns an error indicating any failure the wallet might have + // encountered. + Status() (string, error) + + // Open initializes access to a wallet instance. The passphrase parameter may + // or may not be used by the implementation of a particular wallet instance. + Open(device io.ReadWriter, passphrase string) error + + // Close releases any resources held by an open wallet instance. + Close() error + + // Heartbeat performs a sanity check against the hardware wallet to see if it + // is still online and healthy. + Heartbeat() error + + // Derive sends a derivation request to the USB device and returns the Ethereum + // address located on that path. + Derive(path accounts.DerivationPath) (common.Address, error) + + // SignTx sends the transaction to the USB device and waits for the user to confirm + // or deny the transaction. + SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) +} + +// wallet represents the common functionality shared by all USB hardware +// wallets to prevent reimplementing the same complex maintenance mechanisms +// for different vendors. +type wallet struct { + hub *Hub // USB hub scanning + driver driver // Hardware implementation of the low level device operations + url *accounts.URL // Textual URL uniquely identifying this wallet + + info hid.DeviceInfo // Known USB device infos about the wallet + device *hid.Device // USB device advertising itself as a hardware wallet + + accounts []accounts.Account // List of derive accounts pinned on the hardware wallet + paths map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations + + deriveNextPath accounts.DerivationPath // Next derivation path for account auto-discovery + deriveNextAddr common.Address // Next derived account address for auto-discovery + deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with + deriveReq chan chan struct{} // Channel to request a self-derivation on + deriveQuit chan chan error // Channel to terminate the self-deriver with + + healthQuit chan chan error + + // Locking a hardware wallet is a bit special. Since hardware devices are lower + // performing, any communication with them might take a non negligible amount of + // time. Worse still, waiting for user confirmation can take arbitrarily long, + // but exclusive communication must be upheld during. Locking the entire wallet + // in the mean time however would stall any parts of the system that don't want + // to communicate, just read some state (e.g. list the accounts). + // + // As such, a hardware wallet needs two locks to function correctly. A state + // lock can be used to protect the wallet's software-side internal state, which + // must not be held exclusively during hardware communication. A communication + // lock can be used to achieve exclusive access to the device itself, this one + // however should allow "skipping" waiting for operations that might want to + // use the device, but can live without too (e.g. account self-derivation). + // + // Since we have two locks, it's important to know how to properly use them: + // - Communication requires the `device` to not change, so obtaining the + // commsLock should be done after having a stateLock. + // - Communication must not disable read access to the wallet state, so it + // must only ever hold a *read* lock to stateLock. + commsLock chan struct{} // Mutex (buf=1) for the USB comms without keeping the state locked + stateLock sync.RWMutex // Protects read and write access to the wallet struct fields + + log log.Logger // Contextual logger to tag the base with its id +} + +// URL implements accounts.Wallet, returning the URL of the USB hardware device. +func (w *wallet) URL() accounts.URL { + return *w.url // Immutable, no need for a lock +} + +// Status implements accounts.Wallet, returning a custom status message from the +// underlying vendor-specific hardware wallet implementation. +func (w *wallet) Status() (string, error) { + w.stateLock.RLock() // No device communication, state lock is enough + defer w.stateLock.RUnlock() + + status, failure := w.driver.Status() + if w.device == nil { + return "Closed", failure + } + return status, failure +} + +// Open implements accounts.Wallet, attempting to open a USB connection to the +// hardware wallet. +func (w *wallet) Open(passphrase string) error { + w.stateLock.Lock() // State lock is enough since there's no connection yet at this point + defer w.stateLock.Unlock() + + // If the device was already opened once, refuse to try again + if w.paths != nil { + return accounts.ErrWalletAlreadyOpen + } + // Make sure the actual device connection is done only once + if w.device == nil { + device, err := w.info.Open() + if err != nil { + return err + } + w.device = device + w.commsLock = make(chan struct{}, 1) + w.commsLock <- struct{}{} // Enable lock + } + // Delegate device initialization to the underlying driver + if err := w.driver.Open(w.device, passphrase); err != nil { + return err + } + // Connection successful, start life-cycle management + w.paths = make(map[common.Address]accounts.DerivationPath) + + w.deriveReq = make(chan chan struct{}) + w.deriveQuit = make(chan chan error) + w.healthQuit = make(chan chan error) + + go w.heartbeat() + go w.selfDerive() + + // Notify anyone listening for wallet events that a new device is accessible + go w.hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened}) + + return nil +} + +// heartbeat is a health check loop for the USB wallets to periodically verify +// whether they are still present or if they malfunctioned. +func (w *wallet) heartbeat() { + w.log.Debug("USB wallet health-check started") + defer w.log.Debug("USB wallet health-check stopped") + + // Execute heartbeat checks until termination or error + var ( + errc chan error + err error + ) + for errc == nil && err == nil { + // Wait until termination is requested or the heartbeat cycle arrives + select { + case errc = <-w.healthQuit: + // Termination requested + continue + case <-time.After(heartbeatCycle): + // Heartbeat time + } + // Execute a tiny data exchange to see responsiveness + w.stateLock.RLock() + if w.device == nil { + // Terminated while waiting for the lock + w.stateLock.RUnlock() + continue + } + <-w.commsLock // Don't lock state while resolving version + err = w.driver.Heartbeat() + w.commsLock <- struct{}{} + w.stateLock.RUnlock() + + if err != nil { + w.stateLock.Lock() // Lock state to tear the wallet down + w.close() + w.stateLock.Unlock() + } + // Ignore non hardware related errors + err = nil + } + // In case of error, wait for termination + if err != nil { + w.log.Debug("USB wallet health-check failed", "err", err) + errc = <-w.healthQuit + } + errc <- err +} + +// Close implements accounts.Wallet, closing the USB connection to the device. +func (w *wallet) Close() error { + // Ensure the wallet was opened + w.stateLock.RLock() + hQuit, dQuit := w.healthQuit, w.deriveQuit + w.stateLock.RUnlock() + + // Terminate the health checks + var herr error + if hQuit != nil { + errc := make(chan error) + hQuit <- errc + herr = <-errc // Save for later, we *must* close the USB + } + // Terminate the self-derivations + var derr error + if dQuit != nil { + errc := make(chan error) + dQuit <- errc + derr = <-errc // Save for later, we *must* close the USB + } + // Terminate the device connection + w.stateLock.Lock() + defer w.stateLock.Unlock() + + w.healthQuit = nil + w.deriveQuit = nil + w.deriveReq = nil + + if err := w.close(); err != nil { + return err + } + if herr != nil { + return herr + } + return derr +} + +// close is the internal wallet closer that terminates the USB connection and +// resets all the fields to their defaults. +// +// Note, close assumes the state lock is held! +func (w *wallet) close() error { + // Allow duplicate closes, especially for health-check failures + if w.device == nil { + return nil + } + // Close the device, clear everything, then return + w.device.Close() + w.device = nil + + w.accounts, w.paths = nil, nil + return w.driver.Close() +} + +// Accounts implements accounts.Wallet, returning the list of accounts pinned to +// the USB hardware wallet. If self-derivation was enabled, the account list is +// periodically expanded based on current chain state. +func (w *wallet) Accounts() []accounts.Account { + // Attempt self-derivation if it's running + reqc := make(chan struct{}, 1) + select { + case w.deriveReq <- reqc: + // Self-derivation request accepted, wait for it + <-reqc + default: + // Self-derivation offline, throttled or busy, skip + } + // Return whatever account list we ended up with + w.stateLock.RLock() + defer w.stateLock.RUnlock() + + cpy := make([]accounts.Account, len(w.accounts)) + copy(cpy, w.accounts) + return cpy +} + +// selfDerive is an account derivation loop that upon request attempts to find +// new non-zero accounts. +func (w *wallet) selfDerive() { + w.log.Debug("USB wallet self-derivation started") + defer w.log.Debug("USB wallet self-derivation stopped") + + // Execute self-derivations until termination or error + var ( + reqc chan struct{} + errc chan error + err error + ) + for errc == nil && err == nil { + // Wait until either derivation or termination is requested + select { + case errc = <-w.deriveQuit: + // Termination requested + continue + case reqc = <-w.deriveReq: + // Account discovery requested + } + // Derivation needs a chain and device access, skip if either unavailable + w.stateLock.RLock() + if w.device == nil || w.deriveChain == nil { + w.stateLock.RUnlock() + reqc <- struct{}{} + continue + } + select { + case <-w.commsLock: + default: + w.stateLock.RUnlock() + reqc <- struct{}{} + continue + } + // Device lock obtained, derive the next batch of accounts + var ( + accs []accounts.Account + paths []accounts.DerivationPath + + nextAddr = w.deriveNextAddr + nextPath = w.deriveNextPath + + context = context.Background() + ) + for empty := false; !empty; { + // Retrieve the next derived Ethereum account + if nextAddr == (common.Address{}) { + if nextAddr, err = w.driver.Derive(nextPath); err != nil { + w.log.Warn("USB wallet account derivation failed", "err", err) + break + } + } + // Check the account's status against the current chain state + var ( + balance *big.Int + nonce uint64 + ) + balance, err = w.deriveChain.BalanceAt(context, nextAddr, nil) + if err != nil { + w.log.Warn("USB wallet balance retrieval failed", "err", err) + break + } + nonce, err = w.deriveChain.NonceAt(context, nextAddr, nil) + if err != nil { + w.log.Warn("USB wallet nonce retrieval failed", "err", err) + break + } + // If the next account is empty, stop self-derivation, but add it nonetheless + if balance.Sign() == 0 && nonce == 0 { + empty = true + } + // We've just self-derived a new account, start tracking it locally + path := make(accounts.DerivationPath, len(nextPath)) + copy(path[:], nextPath[:]) + paths = append(paths, path) + + account := accounts.Account{ + Address: nextAddr, + URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)}, + } + accs = append(accs, account) + + // Display a log message to the user for new (or previously empty accounts) + if _, known := w.paths[nextAddr]; !known || (!empty && nextAddr == w.deriveNextAddr) { + w.log.Info("USB wallet discovered new account", "address", nextAddr, "path", path, "balance", balance, "nonce", nonce) + } + // Fetch the next potential account + if !empty { + nextAddr = common.Address{} + nextPath[len(nextPath)-1]++ + } + } + // Self derivation complete, release device lock + w.commsLock <- struct{}{} + w.stateLock.RUnlock() + + // Insert any accounts successfully derived + w.stateLock.Lock() + for i := 0; i < len(accs); i++ { + if _, ok := w.paths[accs[i].Address]; !ok { + w.accounts = append(w.accounts, accs[i]) + w.paths[accs[i].Address] = paths[i] + } + } + // Shift the self-derivation forward + // TODO(karalabe): don't overwrite changes from wallet.SelfDerive + w.deriveNextAddr = nextAddr + w.deriveNextPath = nextPath + w.stateLock.Unlock() + + // Notify the user of termination and loop after a bit of time (to avoid trashing) + reqc <- struct{}{} + if err == nil { + select { + case errc = <-w.deriveQuit: + // Termination requested, abort + case <-time.After(selfDeriveThrottling): + // Waited enough, willing to self-derive again + } + } + } + // In case of error, wait for termination + if err != nil { + w.log.Debug("USB wallet self-derivation failed", "err", err) + errc = <-w.deriveQuit + } + errc <- err +} + +// Contains implements accounts.Wallet, returning whether a particular account is +// or is not pinned into this wallet instance. Although we could attempt to resolve +// unpinned accounts, that would be an non-negligible hardware operation. +func (w *wallet) Contains(account accounts.Account) bool { + w.stateLock.RLock() + defer w.stateLock.RUnlock() + + _, exists := w.paths[account.Address] + return exists +} + +// Derive implements accounts.Wallet, deriving a new account at the specific +// derivation path. If pin is set to true, the account will be added to the list +// of tracked accounts. +func (w *wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { + // Try to derive the actual account and update its URL if successful + w.stateLock.RLock() // Avoid device disappearing during derivation + + if w.device == nil { + w.stateLock.RUnlock() + return accounts.Account{}, accounts.ErrWalletClosed + } + <-w.commsLock // Avoid concurrent hardware access + address, err := w.driver.Derive(path) + w.commsLock <- struct{}{} + + w.stateLock.RUnlock() + + // If an error occurred or no pinning was requested, return + if err != nil { + return accounts.Account{}, err + } + account := accounts.Account{ + Address: address, + URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)}, + } + if !pin { + return account, nil + } + // Pinning needs to modify the state + w.stateLock.Lock() + defer w.stateLock.Unlock() + + if _, ok := w.paths[address]; !ok { + w.accounts = append(w.accounts, account) + w.paths[address] = path + } + return account, nil +} + +// SelfDerive implements accounts.Wallet, trying to discover accounts that the +// user used previously (based on the chain state), but ones that he/she did not +// explicitly pin to the wallet manually. To avoid chain head monitoring, self +// derivation only runs during account listing (and even then throttled). +func (w *wallet) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) { + w.stateLock.Lock() + defer w.stateLock.Unlock() + + w.deriveNextPath = make(accounts.DerivationPath, len(base)) + copy(w.deriveNextPath[:], base[:]) + + w.deriveNextAddr = common.Address{} + w.deriveChain = chain +} + +// signHash implements accounts.Wallet, however signing arbitrary data is not +// supported for hardware wallets, so this method will always return an error. +func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error) { + return nil, accounts.ErrNotSupported +} + +// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed +func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { + return w.signHash(account, crypto.Keccak256(data)) +} + +// SignDataWithPassphrase implements accounts.Wallet, attempting to sign the given +// data with the given account using passphrase as extra authentication. +// Since USB wallets don't rely on passphrases, these are silently ignored. +func (w *wallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { + return w.SignData(account, mimeType, data) +} + +func (w *wallet) SignText(account accounts.Account, text []byte) ([]byte, error) { + return w.signHash(account, accounts.TextHash(text)) +} + +// SignTx implements accounts.Wallet. It sends the transaction over to the Ledger +// wallet to request a confirmation from the user. It returns either the signed +// transaction or a failure if the user denied the transaction. +// +// Note, if the version of the Ethereum application running on the Ledger wallet is +// too old to sign EIP-155 transactions, but such is requested nonetheless, an error +// will be returned opposed to silently signing in Homestead mode. +func (w *wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + w.stateLock.RLock() // Comms have own mutex, this is for the state fields + defer w.stateLock.RUnlock() + + // If the wallet is closed, abort + if w.device == nil { + return nil, accounts.ErrWalletClosed + } + // Make sure the requested account is contained within + path, ok := w.paths[account.Address] + if !ok { + return nil, accounts.ErrUnknownAccount + } + // All infos gathered and metadata checks out, request signing + <-w.commsLock + defer func() { w.commsLock <- struct{}{} }() + + // Ensure the device isn't screwed with while user confirmation is pending + // TODO(karalabe): remove if hotplug lands on Windows + w.hub.commsLock.Lock() + w.hub.commsPend++ + w.hub.commsLock.Unlock() + + defer func() { + w.hub.commsLock.Lock() + w.hub.commsPend-- + w.hub.commsLock.Unlock() + }() + // Sign the transaction and verify the sender to avoid hardware fault surprises + sender, signed, err := w.driver.SignTx(path, tx, chainID) + if err != nil { + return nil, err + } + if sender != account.Address { + return nil, fmt.Errorf("signer mismatch: expected %s, got %s", account.Address.Hex(), sender.Hex()) + } + return signed, nil +} + +// SignHashWithPassphrase implements accounts.Wallet, however signing arbitrary +// data is not supported for Ledger wallets, so this method will always return +// an error. +func (w *wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { + return w.SignText(account, accounts.TextHash(text)) +} + +// SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given +// transaction with the given account using passphrase as extra authentication. +// Since USB wallets don't rely on passphrases, these are silently ignored. +func (w *wallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + return w.SignTx(account, tx, chainID) +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/bitutil/bitutil.go b/vendor/github.com/ethereum/go-ethereum/common/bitutil/bitutil.go new file mode 100644 index 0000000000..cd3e72169f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/bitutil/bitutil.go @@ -0,0 +1,188 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Adapted from: https://golang.org/src/crypto/cipher/xor.go + +// Package bitutil implements fast bitwise operations. +package bitutil + +import ( + "runtime" + "unsafe" +) + +const wordSize = int(unsafe.Sizeof(uintptr(0))) +const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" + +// XORBytes xors the bytes in a and b. The destination is assumed to have enough +// space. Returns the number of bytes xor'd. +func XORBytes(dst, a, b []byte) int { + if supportsUnaligned { + return fastXORBytes(dst, a, b) + } + return safeXORBytes(dst, a, b) +} + +// fastXORBytes xors in bulk. It only works on architectures that support +// unaligned read/writes. +func fastXORBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + w := n / wordSize + if w > 0 { + dw := *(*[]uintptr)(unsafe.Pointer(&dst)) + aw := *(*[]uintptr)(unsafe.Pointer(&a)) + bw := *(*[]uintptr)(unsafe.Pointer(&b)) + for i := 0; i < w; i++ { + dw[i] = aw[i] ^ bw[i] + } + } + for i := n - n%wordSize; i < n; i++ { + dst[i] = a[i] ^ b[i] + } + return n +} + +// safeXORBytes xors one by one. It works on all architectures, independent if +// it supports unaligned read/writes or not. +func safeXORBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + for i := 0; i < n; i++ { + dst[i] = a[i] ^ b[i] + } + return n +} + +// ANDBytes ands the bytes in a and b. The destination is assumed to have enough +// space. Returns the number of bytes and'd. +func ANDBytes(dst, a, b []byte) int { + if supportsUnaligned { + return fastANDBytes(dst, a, b) + } + return safeANDBytes(dst, a, b) +} + +// fastANDBytes ands in bulk. It only works on architectures that support +// unaligned read/writes. +func fastANDBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + w := n / wordSize + if w > 0 { + dw := *(*[]uintptr)(unsafe.Pointer(&dst)) + aw := *(*[]uintptr)(unsafe.Pointer(&a)) + bw := *(*[]uintptr)(unsafe.Pointer(&b)) + for i := 0; i < w; i++ { + dw[i] = aw[i] & bw[i] + } + } + for i := n - n%wordSize; i < n; i++ { + dst[i] = a[i] & b[i] + } + return n +} + +// safeANDBytes ands one by one. It works on all architectures, independent if +// it supports unaligned read/writes or not. +func safeANDBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + for i := 0; i < n; i++ { + dst[i] = a[i] & b[i] + } + return n +} + +// ORBytes ors the bytes in a and b. The destination is assumed to have enough +// space. Returns the number of bytes or'd. +func ORBytes(dst, a, b []byte) int { + if supportsUnaligned { + return fastORBytes(dst, a, b) + } + return safeORBytes(dst, a, b) +} + +// fastORBytes ors in bulk. It only works on architectures that support +// unaligned read/writes. +func fastORBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + w := n / wordSize + if w > 0 { + dw := *(*[]uintptr)(unsafe.Pointer(&dst)) + aw := *(*[]uintptr)(unsafe.Pointer(&a)) + bw := *(*[]uintptr)(unsafe.Pointer(&b)) + for i := 0; i < w; i++ { + dw[i] = aw[i] | bw[i] + } + } + for i := n - n%wordSize; i < n; i++ { + dst[i] = a[i] | b[i] + } + return n +} + +// safeORBytes ors one by one. It works on all architectures, independent if +// it supports unaligned read/writes or not. +func safeORBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + for i := 0; i < n; i++ { + dst[i] = a[i] | b[i] + } + return n +} + +// TestBytes tests whether any bit is set in the input byte slice. +func TestBytes(p []byte) bool { + if supportsUnaligned { + return fastTestBytes(p) + } + return safeTestBytes(p) +} + +// fastTestBytes tests for set bits in bulk. It only works on architectures that +// support unaligned read/writes. +func fastTestBytes(p []byte) bool { + n := len(p) + w := n / wordSize + if w > 0 { + pw := *(*[]uintptr)(unsafe.Pointer(&p)) + for i := 0; i < w; i++ { + if pw[i] != 0 { + return true + } + } + } + for i := n - n%wordSize; i < n; i++ { + if p[i] != 0 { + return true + } + } + return false +} + +// safeTestBytes tests for set bits one byte at a time. It works on all +// architectures, independent if it supports unaligned read/writes or not. +func safeTestBytes(p []byte) bool { + for i := 0; i < len(p); i++ { + if p[i] != 0 { + return true + } + } + return false +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/bitutil/bitutil_test.go b/vendor/github.com/ethereum/go-ethereum/common/bitutil/bitutil_test.go new file mode 100644 index 0000000000..93647031ef --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/bitutil/bitutil_test.go @@ -0,0 +1,215 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Adapted from: https://golang.org/src/crypto/cipher/xor_test.go + +package bitutil + +import ( + "bytes" + "testing" +) + +// Tests that bitwise XOR works for various alignments. +func TestXOR(t *testing.T) { + for alignP := 0; alignP < 2; alignP++ { + for alignQ := 0; alignQ < 2; alignQ++ { + for alignD := 0; alignD < 2; alignD++ { + p := make([]byte, 1023)[alignP:] + q := make([]byte, 1023)[alignQ:] + + for i := 0; i < len(p); i++ { + p[i] = byte(i) + } + for i := 0; i < len(q); i++ { + q[i] = byte(len(q) - i) + } + d1 := make([]byte, 1023+alignD)[alignD:] + d2 := make([]byte, 1023+alignD)[alignD:] + + XORBytes(d1, p, q) + safeXORBytes(d2, p, q) + if !bytes.Equal(d1, d2) { + t.Error("not equal", d1, d2) + } + } + } + } +} + +// Tests that bitwise AND works for various alignments. +func TestAND(t *testing.T) { + for alignP := 0; alignP < 2; alignP++ { + for alignQ := 0; alignQ < 2; alignQ++ { + for alignD := 0; alignD < 2; alignD++ { + p := make([]byte, 1023)[alignP:] + q := make([]byte, 1023)[alignQ:] + + for i := 0; i < len(p); i++ { + p[i] = byte(i) + } + for i := 0; i < len(q); i++ { + q[i] = byte(len(q) - i) + } + d1 := make([]byte, 1023+alignD)[alignD:] + d2 := make([]byte, 1023+alignD)[alignD:] + + ANDBytes(d1, p, q) + safeANDBytes(d2, p, q) + if !bytes.Equal(d1, d2) { + t.Error("not equal") + } + } + } + } +} + +// Tests that bitwise OR works for various alignments. +func TestOR(t *testing.T) { + for alignP := 0; alignP < 2; alignP++ { + for alignQ := 0; alignQ < 2; alignQ++ { + for alignD := 0; alignD < 2; alignD++ { + p := make([]byte, 1023)[alignP:] + q := make([]byte, 1023)[alignQ:] + + for i := 0; i < len(p); i++ { + p[i] = byte(i) + } + for i := 0; i < len(q); i++ { + q[i] = byte(len(q) - i) + } + d1 := make([]byte, 1023+alignD)[alignD:] + d2 := make([]byte, 1023+alignD)[alignD:] + + ORBytes(d1, p, q) + safeORBytes(d2, p, q) + if !bytes.Equal(d1, d2) { + t.Error("not equal") + } + } + } + } +} + +// Tests that bit testing works for various alignments. +func TestTest(t *testing.T) { + for align := 0; align < 2; align++ { + // Test for bits set in the bulk part + p := make([]byte, 1023)[align:] + p[100] = 1 + + if TestBytes(p) != safeTestBytes(p) { + t.Error("not equal") + } + // Test for bits set in the tail part + q := make([]byte, 1023)[align:] + q[len(q)-1] = 1 + + if TestBytes(q) != safeTestBytes(q) { + t.Error("not equal") + } + } +} + +// Benchmarks the potentially optimized XOR performance. +func BenchmarkFastXOR1KB(b *testing.B) { benchmarkFastXOR(b, 1024) } +func BenchmarkFastXOR2KB(b *testing.B) { benchmarkFastXOR(b, 2048) } +func BenchmarkFastXOR4KB(b *testing.B) { benchmarkFastXOR(b, 4096) } + +func benchmarkFastXOR(b *testing.B, size int) { + p, q := make([]byte, size), make([]byte, size) + + for i := 0; i < b.N; i++ { + XORBytes(p, p, q) + } +} + +// Benchmarks the baseline XOR performance. +func BenchmarkBaseXOR1KB(b *testing.B) { benchmarkBaseXOR(b, 1024) } +func BenchmarkBaseXOR2KB(b *testing.B) { benchmarkBaseXOR(b, 2048) } +func BenchmarkBaseXOR4KB(b *testing.B) { benchmarkBaseXOR(b, 4096) } + +func benchmarkBaseXOR(b *testing.B, size int) { + p, q := make([]byte, size), make([]byte, size) + + for i := 0; i < b.N; i++ { + safeXORBytes(p, p, q) + } +} + +// Benchmarks the potentially optimized AND performance. +func BenchmarkFastAND1KB(b *testing.B) { benchmarkFastAND(b, 1024) } +func BenchmarkFastAND2KB(b *testing.B) { benchmarkFastAND(b, 2048) } +func BenchmarkFastAND4KB(b *testing.B) { benchmarkFastAND(b, 4096) } + +func benchmarkFastAND(b *testing.B, size int) { + p, q := make([]byte, size), make([]byte, size) + + for i := 0; i < b.N; i++ { + ANDBytes(p, p, q) + } +} + +// Benchmarks the baseline AND performance. +func BenchmarkBaseAND1KB(b *testing.B) { benchmarkBaseAND(b, 1024) } +func BenchmarkBaseAND2KB(b *testing.B) { benchmarkBaseAND(b, 2048) } +func BenchmarkBaseAND4KB(b *testing.B) { benchmarkBaseAND(b, 4096) } + +func benchmarkBaseAND(b *testing.B, size int) { + p, q := make([]byte, size), make([]byte, size) + + for i := 0; i < b.N; i++ { + safeANDBytes(p, p, q) + } +} + +// Benchmarks the potentially optimized OR performance. +func BenchmarkFastOR1KB(b *testing.B) { benchmarkFastOR(b, 1024) } +func BenchmarkFastOR2KB(b *testing.B) { benchmarkFastOR(b, 2048) } +func BenchmarkFastOR4KB(b *testing.B) { benchmarkFastOR(b, 4096) } + +func benchmarkFastOR(b *testing.B, size int) { + p, q := make([]byte, size), make([]byte, size) + + for i := 0; i < b.N; i++ { + ORBytes(p, p, q) + } +} + +// Benchmarks the baseline OR performance. +func BenchmarkBaseOR1KB(b *testing.B) { benchmarkBaseOR(b, 1024) } +func BenchmarkBaseOR2KB(b *testing.B) { benchmarkBaseOR(b, 2048) } +func BenchmarkBaseOR4KB(b *testing.B) { benchmarkBaseOR(b, 4096) } + +func benchmarkBaseOR(b *testing.B, size int) { + p, q := make([]byte, size), make([]byte, size) + + for i := 0; i < b.N; i++ { + safeORBytes(p, p, q) + } +} + +// Benchmarks the potentially optimized bit testing performance. +func BenchmarkFastTest1KB(b *testing.B) { benchmarkFastTest(b, 1024) } +func BenchmarkFastTest2KB(b *testing.B) { benchmarkFastTest(b, 2048) } +func BenchmarkFastTest4KB(b *testing.B) { benchmarkFastTest(b, 4096) } + +func benchmarkFastTest(b *testing.B, size int) { + p := make([]byte, size) + for i := 0; i < b.N; i++ { + TestBytes(p) + } +} + +// Benchmarks the baseline bit testing performance. +func BenchmarkBaseTest1KB(b *testing.B) { benchmarkBaseTest(b, 1024) } +func BenchmarkBaseTest2KB(b *testing.B) { benchmarkBaseTest(b, 2048) } +func BenchmarkBaseTest4KB(b *testing.B) { benchmarkBaseTest(b, 4096) } + +func benchmarkBaseTest(b *testing.B, size int) { + p := make([]byte, size) + for i := 0; i < b.N; i++ { + safeTestBytes(p) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/bitutil/compress.go b/vendor/github.com/ethereum/go-ethereum/common/bitutil/compress.go new file mode 100644 index 0000000000..c057cee4a6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/bitutil/compress.go @@ -0,0 +1,170 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bitutil + +import "errors" + +var ( + // errMissingData is returned from decompression if the byte referenced by + // the bitset header overflows the input data. + errMissingData = errors.New("missing bytes on input") + + // errUnreferencedData is returned from decompression if not all bytes were used + // up from the input data after decompressing it. + errUnreferencedData = errors.New("extra bytes on input") + + // errExceededTarget is returned from decompression if the bitset header has + // more bits defined than the number of target buffer space available. + errExceededTarget = errors.New("target data size exceeded") + + // errZeroContent is returned from decompression if a data byte referenced in + // the bitset header is actually a zero byte. + errZeroContent = errors.New("zero byte in input content") +) + +// The compression algorithm implemented by CompressBytes and DecompressBytes is +// optimized for sparse input data which contains a lot of zero bytes. Decompression +// requires knowledge of the decompressed data length. +// +// Compression works as follows: +// +// if data only contains zeroes, +// CompressBytes(data) == nil +// otherwise if len(data) <= 1, +// CompressBytes(data) == data +// otherwise: +// CompressBytes(data) == append(CompressBytes(nonZeroBitset(data)), nonZeroBytes(data)...) +// where +// nonZeroBitset(data) is a bit vector with len(data) bits (MSB first): +// nonZeroBitset(data)[i/8] && (1 << (7-i%8)) != 0 if data[i] != 0 +// len(nonZeroBitset(data)) == (len(data)+7)/8 +// nonZeroBytes(data) contains the non-zero bytes of data in the same order + +// CompressBytes compresses the input byte slice according to the sparse bitset +// representation algorithm. If the result is bigger than the original input, no +// compression is done. +func CompressBytes(data []byte) []byte { + if out := bitsetEncodeBytes(data); len(out) < len(data) { + return out + } + cpy := make([]byte, len(data)) + copy(cpy, data) + return cpy +} + +// bitsetEncodeBytes compresses the input byte slice according to the sparse +// bitset representation algorithm. +func bitsetEncodeBytes(data []byte) []byte { + // Empty slices get compressed to nil + if len(data) == 0 { + return nil + } + // One byte slices compress to nil or retain the single byte + if len(data) == 1 { + if data[0] == 0 { + return nil + } + return data + } + // Calculate the bitset of set bytes, and gather the non-zero bytes + nonZeroBitset := make([]byte, (len(data)+7)/8) + nonZeroBytes := make([]byte, 0, len(data)) + + for i, b := range data { + if b != 0 { + nonZeroBytes = append(nonZeroBytes, b) + nonZeroBitset[i/8] |= 1 << byte(7-i%8) + } + } + if len(nonZeroBytes) == 0 { + return nil + } + return append(bitsetEncodeBytes(nonZeroBitset), nonZeroBytes...) +} + +// DecompressBytes decompresses data with a known target size. If the input data +// matches the size of the target, it means no compression was done in the first +// place. +func DecompressBytes(data []byte, target int) ([]byte, error) { + if len(data) > target { + return nil, errExceededTarget + } + if len(data) == target { + cpy := make([]byte, len(data)) + copy(cpy, data) + return cpy, nil + } + return bitsetDecodeBytes(data, target) +} + +// bitsetDecodeBytes decompresses data with a known target size. +func bitsetDecodeBytes(data []byte, target int) ([]byte, error) { + out, size, err := bitsetDecodePartialBytes(data, target) + if err != nil { + return nil, err + } + if size != len(data) { + return nil, errUnreferencedData + } + return out, nil +} + +// bitsetDecodePartialBytes decompresses data with a known target size, but does +// not enforce consuming all the input bytes. In addition to the decompressed +// output, the function returns the length of compressed input data corresponding +// to the output as the input slice may be longer. +func bitsetDecodePartialBytes(data []byte, target int) ([]byte, int, error) { + // Sanity check 0 targets to avoid infinite recursion + if target == 0 { + return nil, 0, nil + } + // Handle the zero and single byte corner cases + decomp := make([]byte, target) + if len(data) == 0 { + return decomp, 0, nil + } + if target == 1 { + decomp[0] = data[0] // copy to avoid referencing the input slice + if data[0] != 0 { + return decomp, 1, nil + } + return decomp, 0, nil + } + // Decompress the bitset of set bytes and distribute the non zero bytes + nonZeroBitset, ptr, err := bitsetDecodePartialBytes(data, (target+7)/8) + if err != nil { + return nil, ptr, err + } + for i := 0; i < 8*len(nonZeroBitset); i++ { + if nonZeroBitset[i/8]&(1<= len(data) { + return nil, 0, errMissingData + } + if i >= len(decomp) { + return nil, 0, errExceededTarget + } + // Make sure the data is valid and push into the slot + if data[ptr] == 0 { + return nil, 0, errZeroContent + } + decomp[i] = data[ptr] + ptr++ + } + } + return decomp, ptr, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/bitutil/compress_fuzz.go b/vendor/github.com/ethereum/go-ethereum/common/bitutil/compress_fuzz.go new file mode 100644 index 0000000000..1b87f50edc --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/bitutil/compress_fuzz.go @@ -0,0 +1,56 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build gofuzz + +package bitutil + +import "bytes" + +// Fuzz implements a go-fuzz fuzzer method to test various encoding method +// invocations. +func Fuzz(data []byte) int { + if len(data) == 0 { + return -1 + } + if data[0]%2 == 0 { + return fuzzEncode(data[1:]) + } + return fuzzDecode(data[1:]) +} + +// fuzzEncode implements a go-fuzz fuzzer method to test the bitset encoding and +// decoding algorithm. +func fuzzEncode(data []byte) int { + proc, _ := bitsetDecodeBytes(bitsetEncodeBytes(data), len(data)) + if !bytes.Equal(data, proc) { + panic("content mismatch") + } + return 0 +} + +// fuzzDecode implements a go-fuzz fuzzer method to test the bit decoding and +// reencoding algorithm. +func fuzzDecode(data []byte) int { + blob, err := bitsetDecodeBytes(data, 1024) + if err != nil { + return 0 + } + if comp := bitsetEncodeBytes(blob); !bytes.Equal(comp, data) { + panic("content mismatch") + } + return 0 +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/bitutil/compress_test.go b/vendor/github.com/ethereum/go-ethereum/common/bitutil/compress_test.go new file mode 100644 index 0000000000..13a13011dc --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/bitutil/compress_test.go @@ -0,0 +1,181 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bitutil + +import ( + "bytes" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" +) + +// Tests that data bitset encoding and decoding works and is bijective. +func TestEncodingCycle(t *testing.T) { + tests := []string{ + // Tests generated by go-fuzz to maximize code coverage + "0x000000000000000000", + "0xef0400", + "0xdf7070533534333636313639343638373532313536346c1bc33339343837313070706336343035336336346c65fefb3930393233383838ac2f65fefb", + "0x7b64000000", + "0x000034000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000000000000000", + "0x4912385c0e7b64000000", + "0x000034000000000000000000000000000000", + "0x00", + "0x000003e834ff7f0000", + "0x0000", + "0x0000000000000000000000000000000000000000000000000000000000ff00", + "0x895f0c6a020f850c6a020f85f88df88d", + "0xdf7070533534333636313639343638373432313536346c1bc3315aac2f65fefb", + "0x0000000000", + "0xdf70706336346c65fefb", + "0x00006d643634000000", + "0xdf7070533534333636313639343638373532313536346c1bc333393438373130707063363430353639343638373532313536346c1bc333393438336336346c65fe", + } + for i, tt := range tests { + data := hexutil.MustDecode(tt) + + proc, err := bitsetDecodeBytes(bitsetEncodeBytes(data), len(data)) + if err != nil { + t.Errorf("test %d: failed to decompress compressed data: %v", i, err) + continue + } + if !bytes.Equal(data, proc) { + t.Errorf("test %d: compress/decompress mismatch: have %x, want %x", i, proc, data) + } + } +} + +// Tests that data bitset decoding and rencoding works and is bijective. +func TestDecodingCycle(t *testing.T) { + tests := []struct { + size int + input string + fail error + }{ + {size: 0, input: "0x"}, + + // Crashers generated by go-fuzz + {size: 0, input: "0x0020", fail: errUnreferencedData}, + {size: 0, input: "0x30", fail: errUnreferencedData}, + {size: 1, input: "0x00", fail: errUnreferencedData}, + {size: 2, input: "0x07", fail: errMissingData}, + {size: 1024, input: "0x8000", fail: errZeroContent}, + + // Tests generated by go-fuzz to maximize code coverage + {size: 29490, input: "0x343137343733323134333839373334323073333930783e3078333930783e70706336346c65303e", fail: errMissingData}, + {size: 59395, input: "0x00", fail: errUnreferencedData}, + {size: 52574, input: "0x70706336346c65c0de", fail: errExceededTarget}, + {size: 42264, input: "0x07", fail: errMissingData}, + {size: 52, input: "0xa5045bad48f4", fail: errExceededTarget}, + {size: 52574, input: "0xc0de", fail: errMissingData}, + {size: 52574, input: "0x"}, + {size: 29490, input: "0x34313734373332313433383937333432307333393078073034333839373334323073333930783e3078333937333432307333393078073061333930783e70706336346c65303e", fail: errMissingData}, + {size: 29491, input: "0x3973333930783e30783e", fail: errMissingData}, + + {size: 1024, input: "0x808080608080"}, + {size: 1024, input: "0x808470705e3632383337363033313434303137393130306c6580ef46806380635a80"}, + {size: 1024, input: "0x8080808070"}, + {size: 1024, input: "0x808070705e36346c6580ef46806380635a80"}, + {size: 1024, input: "0x80808046802680"}, + {size: 1024, input: "0x4040404035"}, + {size: 1024, input: "0x4040bf3ba2b3f684402d353234373438373934409fe5b1e7ada94ebfd7d0505e27be4035"}, + {size: 1024, input: "0x404040bf3ba2b3f6844035"}, + {size: 1024, input: "0x40402d35323437343837393440bfd7d0505e27be4035"}, + } + for i, tt := range tests { + data := hexutil.MustDecode(tt.input) + + orig, err := bitsetDecodeBytes(data, tt.size) + if err != tt.fail { + t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.fail) + } + if err != nil { + continue + } + if comp := bitsetEncodeBytes(orig); !bytes.Equal(comp, data) { + t.Errorf("test %d: decompress/compress mismatch: have %x, want %x", i, comp, data) + } + } +} + +// TestCompression tests that compression works by returning either the bitset +// encoded input, or the actual input if the bitset version is longer. +func TestCompression(t *testing.T) { + // Check the compression returns the bitset encoding is shorter + in := hexutil.MustDecode("0x4912385c0e7b64000000") + out := hexutil.MustDecode("0x80fe4912385c0e7b64") + + if data := CompressBytes(in); !bytes.Equal(data, out) { + t.Errorf("encoding mismatch for sparse data: have %x, want %x", data, out) + } + if data, err := DecompressBytes(out, len(in)); err != nil || !bytes.Equal(data, in) { + t.Errorf("decoding mismatch for sparse data: have %x, want %x, error %v", data, in, err) + } + // Check the compression returns the input if the bitset encoding is longer + in = hexutil.MustDecode("0xdf7070533534333636313639343638373532313536346c1bc33339343837313070706336343035336336346c65fefb3930393233383838ac2f65fefb") + out = hexutil.MustDecode("0xdf7070533534333636313639343638373532313536346c1bc33339343837313070706336343035336336346c65fefb3930393233383838ac2f65fefb") + + if data := CompressBytes(in); !bytes.Equal(data, out) { + t.Errorf("encoding mismatch for dense data: have %x, want %x", data, out) + } + if data, err := DecompressBytes(out, len(in)); err != nil || !bytes.Equal(data, in) { + t.Errorf("decoding mismatch for dense data: have %x, want %x, error %v", data, in, err) + } + // Check that decompressing a longer input than the target fails + if _, err := DecompressBytes([]byte{0xc0, 0x01, 0x01}, 2); err != errExceededTarget { + t.Errorf("decoding error mismatch for long data: have %v, want %v", err, errExceededTarget) + } +} + +// Crude benchmark for compressing random slices of bytes. +func BenchmarkEncoding1KBVerySparse(b *testing.B) { benchmarkEncoding(b, 1024, 0.0001) } +func BenchmarkEncoding2KBVerySparse(b *testing.B) { benchmarkEncoding(b, 2048, 0.0001) } +func BenchmarkEncoding4KBVerySparse(b *testing.B) { benchmarkEncoding(b, 4096, 0.0001) } + +func BenchmarkEncoding1KBSparse(b *testing.B) { benchmarkEncoding(b, 1024, 0.001) } +func BenchmarkEncoding2KBSparse(b *testing.B) { benchmarkEncoding(b, 2048, 0.001) } +func BenchmarkEncoding4KBSparse(b *testing.B) { benchmarkEncoding(b, 4096, 0.001) } + +func BenchmarkEncoding1KBDense(b *testing.B) { benchmarkEncoding(b, 1024, 0.1) } +func BenchmarkEncoding2KBDense(b *testing.B) { benchmarkEncoding(b, 2048, 0.1) } +func BenchmarkEncoding4KBDense(b *testing.B) { benchmarkEncoding(b, 4096, 0.1) } + +func BenchmarkEncoding1KBSaturated(b *testing.B) { benchmarkEncoding(b, 1024, 0.5) } +func BenchmarkEncoding2KBSaturated(b *testing.B) { benchmarkEncoding(b, 2048, 0.5) } +func BenchmarkEncoding4KBSaturated(b *testing.B) { benchmarkEncoding(b, 4096, 0.5) } + +func benchmarkEncoding(b *testing.B, bytes int, fill float64) { + // Generate a random slice of bytes to compress + random := rand.NewSource(0) // reproducible and comparable + + data := make([]byte, bytes) + bits := int(float64(bytes) * 8 * fill) + + for i := 0; i < bits; i++ { + idx := random.Int63() % int64(len(data)) + bit := uint(random.Int63() % 8) + data[idx] |= 1 << bit + } + // Reset the benchmark and measure encoding/decoding + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + bitsetDecodeBytes(bitsetEncodeBytes(data), len(data)) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/compiler/helpers.go b/vendor/github.com/ethereum/go-ethereum/common/compiler/helpers.go new file mode 100644 index 0000000000..4de706f6b6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/compiler/helpers.go @@ -0,0 +1,64 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package compiler wraps the Solidity and Vyper compiler executables (solc; vyper). +package compiler + +import ( + "bytes" + "io/ioutil" + "regexp" +) + +var versionRegexp = regexp.MustCompile(`([0-9]+)\.([0-9]+)\.([0-9]+)`) + +// Contract contains information about a compiled contract, alongside its code and runtime code. +type Contract struct { + Code string `json:"code"` + RuntimeCode string `json:"runtime-code"` + Info ContractInfo `json:"info"` +} + +// ContractInfo contains information about a compiled contract, including access +// to the ABI definition, source mapping, user and developer docs, and metadata. +// +// Depending on the source, language version, compiler version, and compiler +// options will provide information about how the contract was compiled. +type ContractInfo struct { + Source string `json:"source"` + Language string `json:"language"` + LanguageVersion string `json:"languageVersion"` + CompilerVersion string `json:"compilerVersion"` + CompilerOptions string `json:"compilerOptions"` + SrcMap interface{} `json:"srcMap"` + SrcMapRuntime string `json:"srcMapRuntime"` + AbiDefinition interface{} `json:"abiDefinition"` + UserDoc interface{} `json:"userDoc"` + DeveloperDoc interface{} `json:"developerDoc"` + Metadata string `json:"metadata"` +} + +func slurpFiles(files []string) (string, error) { + var concat bytes.Buffer + for _, file := range files { + content, err := ioutil.ReadFile(file) + if err != nil { + return "", err + } + concat.Write(content) + } + return concat.String(), nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/compiler/solidity.go b/vendor/github.com/ethereum/go-ethereum/common/compiler/solidity.go new file mode 100644 index 0000000000..7ed9c2633e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/compiler/solidity.go @@ -0,0 +1,180 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package compiler wraps the Solidity and Vyper compiler executables (solc; vyper). +package compiler + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "os/exec" + "strconv" + "strings" +) + +// Solidity contains information about the solidity compiler. +type Solidity struct { + Path, Version, FullVersion string + Major, Minor, Patch int +} + +// --combined-output format +type solcOutput struct { + Contracts map[string]struct { + BinRuntime string `json:"bin-runtime"` + SrcMapRuntime string `json:"srcmap-runtime"` + Bin, SrcMap, Abi, Devdoc, Userdoc, Metadata string + } + Version string +} + +func (s *Solidity) makeArgs() []string { + p := []string{ + "--combined-json", "bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc", + "--optimize", // code optimizer switched on + } + if s.Major > 0 || s.Minor > 4 || s.Patch > 6 { + p[1] += ",metadata" + } + return p +} + +// SolidityVersion runs solc and parses its version output. +func SolidityVersion(solc string) (*Solidity, error) { + if solc == "" { + solc = "solc" + } + var out bytes.Buffer + cmd := exec.Command(solc, "--version") + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + return nil, err + } + matches := versionRegexp.FindStringSubmatch(out.String()) + if len(matches) != 4 { + return nil, fmt.Errorf("can't parse solc version %q", out.String()) + } + s := &Solidity{Path: cmd.Path, FullVersion: out.String(), Version: matches[0]} + if s.Major, err = strconv.Atoi(matches[1]); err != nil { + return nil, err + } + if s.Minor, err = strconv.Atoi(matches[2]); err != nil { + return nil, err + } + if s.Patch, err = strconv.Atoi(matches[3]); err != nil { + return nil, err + } + return s, nil +} + +// CompileSolidityString builds and returns all the contracts contained within a source string. +func CompileSolidityString(solc, source string) (map[string]*Contract, error) { + if len(source) == 0 { + return nil, errors.New("solc: empty source string") + } + s, err := SolidityVersion(solc) + if err != nil { + return nil, err + } + args := append(s.makeArgs(), "--") + cmd := exec.Command(s.Path, append(args, "-")...) + cmd.Stdin = strings.NewReader(source) + return s.run(cmd, source) +} + +// CompileSolidity compiles all given Solidity source files. +func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract, error) { + if len(sourcefiles) == 0 { + return nil, errors.New("solc: no source files") + } + source, err := slurpFiles(sourcefiles) + if err != nil { + return nil, err + } + s, err := SolidityVersion(solc) + if err != nil { + return nil, err + } + args := append(s.makeArgs(), "--") + cmd := exec.Command(s.Path, append(args, sourcefiles...)...) + return s.run(cmd, source) +} + +func (s *Solidity) run(cmd *exec.Cmd, source string) (map[string]*Contract, error) { + var stderr, stdout bytes.Buffer + cmd.Stderr = &stderr + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return nil, fmt.Errorf("solc: %v\n%s", err, stderr.Bytes()) + } + + return ParseCombinedJSON(stdout.Bytes(), source, s.Version, s.Version, strings.Join(s.makeArgs(), " ")) +} + +// ParseCombinedJSON takes the direct output of a solc --combined-output run and +// parses it into a map of string contract name to Contract structs. The +// provided source, language and compiler version, and compiler options are all +// passed through into the Contract structs. +// +// The solc output is expected to contain ABI, source mapping, user docs, and dev docs. +// +// Returns an error if the JSON is malformed or missing data, or if the JSON +// embedded within the JSON is malformed. +func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) { + var output solcOutput + if err := json.Unmarshal(combinedJSON, &output); err != nil { + return nil, err + } + + // Compilation succeeded, assemble and return the contracts. + contracts := make(map[string]*Contract) + for name, info := range output.Contracts { + // Parse the individual compilation results. + var abi interface{} + if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil { + return nil, fmt.Errorf("solc: error reading abi definition (%v)", err) + } + var userdoc interface{} + if err := json.Unmarshal([]byte(info.Userdoc), &userdoc); err != nil { + return nil, fmt.Errorf("solc: error reading user doc: %v", err) + } + var devdoc interface{} + if err := json.Unmarshal([]byte(info.Devdoc), &devdoc); err != nil { + return nil, fmt.Errorf("solc: error reading dev doc: %v", err) + } + contracts[name] = &Contract{ + Code: "0x" + info.Bin, + RuntimeCode: "0x" + info.BinRuntime, + Info: ContractInfo{ + Source: source, + Language: "Solidity", + LanguageVersion: languageVersion, + CompilerVersion: compilerVersion, + CompilerOptions: compilerOptions, + SrcMap: info.SrcMap, + SrcMapRuntime: info.SrcMapRuntime, + AbiDefinition: abi, + UserDoc: userdoc, + DeveloperDoc: devdoc, + Metadata: info.Metadata, + }, + } + } + return contracts, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/compiler/solidity_test.go b/vendor/github.com/ethereum/go-ethereum/common/compiler/solidity_test.go new file mode 100644 index 0000000000..6be2bda52c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/compiler/solidity_test.go @@ -0,0 +1,78 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package compiler + +import ( + "os/exec" + "testing" +) + +const ( + testSource = ` +pragma solidity >0.0.0; +contract test { + /// @notice Will multiply ` + "`a`" + ` by 7. + function multiply(uint a) public returns(uint d) { + return a * 7; + } +} +` +) + +func skipWithoutSolc(t *testing.T) { + if _, err := exec.LookPath("solc"); err != nil { + t.Skip(err) + } +} + +func TestSolidityCompiler(t *testing.T) { + skipWithoutSolc(t) + + contracts, err := CompileSolidityString("", testSource) + if err != nil { + t.Fatalf("error compiling source. result %v: %v", contracts, err) + } + if len(contracts) != 1 { + t.Errorf("one contract expected, got %d", len(contracts)) + } + c, ok := contracts["test"] + if !ok { + c, ok = contracts[":test"] + if !ok { + t.Fatal("info for contract 'test' not present in result") + } + } + if c.Code == "" { + t.Error("empty code") + } + if c.Info.Source != testSource { + t.Error("wrong source") + } + if c.Info.CompilerVersion == "" { + t.Error("empty version") + } +} + +func TestSolidityCompileError(t *testing.T) { + skipWithoutSolc(t) + + contracts, err := CompileSolidityString("", testSource[4:]) + if err == nil { + t.Errorf("error expected compiling source. got none. result %v", contracts) + } + t.Logf("error: %v", err) +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/compiler/test.v.py b/vendor/github.com/ethereum/go-ethereum/common/compiler/test.v.py new file mode 100644 index 0000000000..35af56c8f6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/compiler/test.v.py @@ -0,0 +1,3 @@ +@public +def test(): + hello: int128 diff --git a/vendor/github.com/ethereum/go-ethereum/common/compiler/test_bad.v.py b/vendor/github.com/ethereum/go-ethereum/common/compiler/test_bad.v.py new file mode 100644 index 0000000000..443ef78263 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/compiler/test_bad.v.py @@ -0,0 +1,3 @@ +lic +def test(): + hello: int128 diff --git a/vendor/github.com/ethereum/go-ethereum/common/compiler/vyper.go b/vendor/github.com/ethereum/go-ethereum/common/compiler/vyper.go new file mode 100644 index 0000000000..a9bca95e59 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/compiler/vyper.go @@ -0,0 +1,144 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package compiler wraps the Solidity and Vyper compiler executables (solc; vyper). +package compiler + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "os/exec" + "strconv" + "strings" +) + +// Vyper contains information about the vyper compiler. +type Vyper struct { + Path, Version, FullVersion string + Major, Minor, Patch int +} + +func (s *Vyper) makeArgs() []string { + p := []string{ + "-f", "combined_json", + } + return p +} + +// VyperVersion runs vyper and parses its version output. +func VyperVersion(vyper string) (*Vyper, error) { + if vyper == "" { + vyper = "vyper" + } + var out bytes.Buffer + cmd := exec.Command(vyper, "--version") + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + return nil, err + } + matches := versionRegexp.FindStringSubmatch(out.String()) + if len(matches) != 4 { + return nil, fmt.Errorf("can't parse vyper version %q", out.String()) + } + s := &Vyper{Path: cmd.Path, FullVersion: out.String(), Version: matches[0]} + if s.Major, err = strconv.Atoi(matches[1]); err != nil { + return nil, err + } + if s.Minor, err = strconv.Atoi(matches[2]); err != nil { + return nil, err + } + if s.Patch, err = strconv.Atoi(matches[3]); err != nil { + return nil, err + } + return s, nil +} + +// CompileVyper compiles all given Vyper source files. +func CompileVyper(vyper string, sourcefiles ...string) (map[string]*Contract, error) { + if len(sourcefiles) == 0 { + return nil, errors.New("vyper: no source files") + } + source, err := slurpFiles(sourcefiles) + if err != nil { + return nil, err + } + s, err := VyperVersion(vyper) + if err != nil { + return nil, err + } + args := s.makeArgs() + cmd := exec.Command(s.Path, append(args, sourcefiles...)...) + return s.run(cmd, source) +} + +func (s *Vyper) run(cmd *exec.Cmd, source string) (map[string]*Contract, error) { + var stderr, stdout bytes.Buffer + cmd.Stderr = &stderr + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return nil, fmt.Errorf("vyper: %v\n%s", err, stderr.Bytes()) + } + + return ParseVyperJSON(stdout.Bytes(), source, s.Version, s.Version, strings.Join(s.makeArgs(), " ")) +} + +// ParseVyperJSON takes the direct output of a vyper --f combined_json run and +// parses it into a map of string contract name to Contract structs. The +// provided source, language and compiler version, and compiler options are all +// passed through into the Contract structs. +// +// The vyper output is expected to contain ABI and source mapping. +// +// Returns an error if the JSON is malformed or missing data, or if the JSON +// embedded within the JSON is malformed. +func ParseVyperJSON(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) { + var output map[string]interface{} + if err := json.Unmarshal(combinedJSON, &output); err != nil { + return nil, err + } + + // Compilation succeeded, assemble and return the contracts. + contracts := make(map[string]*Contract) + for name, info := range output { + // Parse the individual compilation results. + if name == "version" { + continue + } + c := info.(map[string]interface{}) + + contracts[name] = &Contract{ + Code: c["bytecode"].(string), + RuntimeCode: c["bytecode_runtime"].(string), + Info: ContractInfo{ + Source: source, + Language: "Vyper", + LanguageVersion: languageVersion, + CompilerVersion: compilerVersion, + CompilerOptions: compilerOptions, + SrcMap: c["source_map"], + SrcMapRuntime: "", + AbiDefinition: c["abi"], + UserDoc: "", + DeveloperDoc: "", + Metadata: "", + }, + } + } + return contracts, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/compiler/vyper_test.go b/vendor/github.com/ethereum/go-ethereum/common/compiler/vyper_test.go new file mode 100644 index 0000000000..7761c92aff --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/compiler/vyper_test.go @@ -0,0 +1,71 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package compiler + +import ( + "os/exec" + "testing" +) + +func skipWithoutVyper(t *testing.T) { + if _, err := exec.LookPath("vyper"); err != nil { + t.Skip(err) + } +} + +func TestVyperCompiler(t *testing.T) { + skipWithoutVyper(t) + + testSource := []string{"test.v.py"} + source, err := slurpFiles(testSource) + if err != nil { + t.Error("couldn't read test files") + } + contracts, err := CompileVyper("", testSource...) + if err != nil { + t.Fatalf("error compiling test.v.py. result %v: %v", contracts, err) + } + if len(contracts) != 1 { + t.Errorf("one contract expected, got %d", len(contracts)) + } + c, ok := contracts["test.v.py"] + if !ok { + c, ok = contracts[":test"] + if !ok { + t.Fatal("info for contract 'test.v.py' not present in result") + } + } + if c.Code == "" { + t.Error("empty code") + } + if c.Info.Source != source { + t.Error("wrong source") + } + if c.Info.CompilerVersion == "" { + t.Error("empty version") + } +} + +func TestVyperCompileError(t *testing.T) { + skipWithoutVyper(t) + + contracts, err := CompileVyper("", "test_bad.v.py") + if err == nil { + t.Errorf("error expected compiling test_bad.v.py. got none. result %v", contracts) + } + t.Logf("error: %v", err) +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_darwin.go b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_darwin.go new file mode 100644 index 0000000000..88dd0f56cb --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_darwin.go @@ -0,0 +1,71 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package fdlimit + +import "syscall" + +// hardlimit is the number of file descriptors allowed at max by the kernel. +const hardlimit = 10240 + +// Raise tries to maximize the file descriptor allowance of this process +// to the maximum hard-limit allowed by the OS. +// Returns the size it was set to (may differ from the desired 'max') +func Raise(max uint64) (uint64, error) { + // Get the current limit + var limit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + // Try to update the limit to the max allowance + limit.Cur = limit.Max + if limit.Cur > max { + limit.Cur = max + } + if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + // MacOS can silently apply further caps, so retrieve the actually set limit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + return limit.Cur, nil +} + +// Current retrieves the number of file descriptors allowed to be opened by this +// process. +func Current() (int, error) { + var limit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + return int(limit.Cur), nil +} + +// Maximum retrieves the maximum number of file descriptors this process is +// allowed to request for itself. +func Maximum() (int, error) { + // Retrieve the maximum allowed by dynamic OS limits + var limit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + // Cap it to OPEN_MAX (10240) because macos is a special snowflake + if limit.Max > hardlimit { + limit.Max = hardlimit + } + return int(limit.Max), nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_freebsd.go b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_freebsd.go new file mode 100644 index 0000000000..0d8727138e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_freebsd.go @@ -0,0 +1,67 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build freebsd + +package fdlimit + +import "syscall" + +// This file is largely identical to fdlimit_unix.go, +// but Rlimit fields have type int64 on FreeBSD so it needs +// an extra conversion. + +// Raise tries to maximize the file descriptor allowance of this process +// to the maximum hard-limit allowed by the OS. +func Raise(max uint64) (uint64, error) { + // Get the current limit + var limit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + // Try to update the limit to the max allowance + limit.Cur = limit.Max + if limit.Cur > int64(max) { + limit.Cur = int64(max) + } + if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + return uint64(limit.Cur), nil +} + +// Current retrieves the number of file descriptors allowed to be opened by this +// process. +func Current() (int, error) { + var limit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + return int(limit.Cur), nil +} + +// Maximum retrieves the maximum number of file descriptors this process is +// allowed to request for itself. +func Maximum() (int, error) { + var limit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + return int(limit.Max), nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_test.go b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_test.go new file mode 100644 index 0000000000..21362b8463 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_test.go @@ -0,0 +1,45 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package fdlimit + +import ( + "fmt" + "testing" +) + +// TestFileDescriptorLimits simply tests whether the file descriptor allowance +// per this process can be retrieved. +func TestFileDescriptorLimits(t *testing.T) { + target := 4096 + hardlimit, err := Maximum() + if err != nil { + t.Fatal(err) + } + if hardlimit < target { + t.Skip(fmt.Sprintf("system limit is less than desired test target: %d < %d", hardlimit, target)) + } + + if limit, err := Current(); err != nil || limit <= 0 { + t.Fatalf("failed to retrieve file descriptor limit (%d): %v", limit, err) + } + if _, err := Raise(uint64(target)); err != nil { + t.Fatalf("failed to raise file allowance") + } + if limit, err := Current(); err != nil || limit < target { + t.Fatalf("failed to retrieve raised descriptor limit (have %v, want %v): %v", limit, target, err) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_unix.go b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_unix.go new file mode 100644 index 0000000000..e5a575f7a7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_unix.go @@ -0,0 +1,65 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build linux netbsd openbsd solaris + +package fdlimit + +import "syscall" + +// Raise tries to maximize the file descriptor allowance of this process +// to the maximum hard-limit allowed by the OS. +// Returns the size it was set to (may differ from the desired 'max') +func Raise(max uint64) (uint64, error) { + // Get the current limit + var limit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + // Try to update the limit to the max allowance + limit.Cur = limit.Max + if limit.Cur > max { + limit.Cur = max + } + if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + // MacOS can silently apply further caps, so retrieve the actually set limit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + return limit.Cur, nil +} + +// Current retrieves the number of file descriptors allowed to be opened by this +// process. +func Current() (int, error) { + var limit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + return int(limit.Cur), nil +} + +// Maximum retrieves the maximum number of file descriptors this process is +// allowed to request for itself. +func Maximum() (int, error) { + var limit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { + return 0, err + } + return int(limit.Max), nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_windows.go b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_windows.go new file mode 100644 index 0000000000..f472153662 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_windows.go @@ -0,0 +1,50 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package fdlimit + +import "fmt" + +// hardlimit is the number of file descriptors allowed at max by the kernel. +const hardlimit = 16384 + +// Raise tries to maximize the file descriptor allowance of this process +// to the maximum hard-limit allowed by the OS. +func Raise(max uint64) (uint64, error) { + // This method is NOP by design: + // * Linux/Darwin counterparts need to manually increase per process limits + // * On Windows Go uses the CreateFile API, which is limited to 16K files, non + // changeable from within a running process + // This way we can always "request" raising the limits, which will either have + // or not have effect based on the platform we're running on. + if max > hardlimit { + return hardlimit, fmt.Errorf("file descriptor limit (%d) reached", hardlimit) + } + return max, nil +} + +// Current retrieves the number of file descriptors allowed to be opened by this +// process. +func Current() (int, error) { + // Please see Raise for the reason why we use hard coded 16K as the limit + return hardlimit, nil +} + +// Maximum retrieves the maximum number of file descriptors this process is +// allowed to request for itself. +func Maximum() (int, error) { + return Current() +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go b/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go index fbc21241c8..777b08eca4 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go +++ b/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go @@ -72,6 +72,25 @@ func (b Bytes) String() string { return Encode(b) } +// ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type. +func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (b *Bytes) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + data, err := Decode(input) + if err != nil { + return err + } + *b = data + default: + err = fmt.Errorf("Unexpected type for Bytes: %v", input) + } + return err +} + // UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out // determines the required input length. This function is commonly used to implement the // UnmarshalJSON method for fixed-size types. @@ -187,6 +206,25 @@ func (b *Big) String() string { return EncodeBig(b.ToInt()) } +// ImplementsGraphQLType returns true if Big implements the provided GraphQL type. +func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (b *Big) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + return b.UnmarshalText([]byte(input)) + case int32: + var num big.Int + num.SetInt64(int64(input)) + *b = Big(num) + default: + err = fmt.Errorf("Unexpected type for BigInt: %v", input) + } + return err +} + // Uint64 marshals/unmarshals as a JSON string with 0x prefix. // The zero value marshals as "0x0". type Uint64 uint64 @@ -234,6 +272,23 @@ func (b Uint64) String() string { return EncodeUint64(uint64(b)) } +// ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type. +func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (b *Uint64) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + return b.UnmarshalText([]byte(input)) + case int32: + *b = Uint64(input) + default: + err = fmt.Errorf("Unexpected type for Long: %v", input) + } + return err +} + // Uint marshals/unmarshals as a JSON string with 0x prefix. // The zero value marshals as "0x0". type Uint uint diff --git a/vendor/github.com/ethereum/go-ethereum/common/size.go b/vendor/github.com/ethereum/go-ethereum/common/size.go index bd0fc85c7d..6381499a48 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/size.go +++ b/vendor/github.com/ethereum/go-ethereum/common/size.go @@ -26,10 +26,10 @@ type StorageSize float64 // String implements the stringer interface. func (s StorageSize) String() string { - if s > 1000000 { - return fmt.Sprintf("%.2f mB", s/1000000) - } else if s > 1000 { - return fmt.Sprintf("%.2f kB", s/1000) + if s > 1048576 { + return fmt.Sprintf("%.2f MiB", s/1048576) + } else if s > 1024 { + return fmt.Sprintf("%.2f KiB", s/1024) } else { return fmt.Sprintf("%.2f B", s) } @@ -38,10 +38,10 @@ func (s StorageSize) String() string { // TerminalString implements log.TerminalStringer, formatting a string for console // output during logging. func (s StorageSize) TerminalString() string { - if s > 1000000 { - return fmt.Sprintf("%.2fmB", s/1000000) - } else if s > 1000 { - return fmt.Sprintf("%.2fkB", s/1000) + if s > 1048576 { + return fmt.Sprintf("%.2fMiB", s/1048576) + } else if s > 1024 { + return fmt.Sprintf("%.2fKiB", s/1024) } else { return fmt.Sprintf("%.2fB", s) } diff --git a/vendor/github.com/ethereum/go-ethereum/common/types.go b/vendor/github.com/ethereum/go-ethereum/common/types.go index a4b9995267..98c83edd4f 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/types.go +++ b/vendor/github.com/ethereum/go-ethereum/common/types.go @@ -27,7 +27,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/crypto/sha3" + "golang.org/x/crypto/sha3" ) // Lengths of hashes and addresses in bytes. @@ -141,6 +141,21 @@ func (h Hash) Value() (driver.Value, error) { return h[:], nil } +// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type. +func (_ Hash) ImplementsGraphQLType(name string) bool { return name == "Bytes32" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (h *Hash) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + *h = HexToHash(input) + default: + err = fmt.Errorf("Unexpected type for Bytes32: %v", input) + } + return err +} + // UnprefixedHash allows marshaling a Hash without 0x prefix. type UnprefixedHash Hash @@ -187,16 +202,13 @@ func IsHexAddress(s string) bool { // Bytes gets the string representation of the underlying address. func (a Address) Bytes() []byte { return a[:] } -// Big converts an address to a big integer. -func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } - // Hash converts an address to a hash by left-padding it with zeros. func (a Address) Hash() Hash { return BytesToHash(a[:]) } // Hex returns an EIP55-compliant hex string representation of the address. func (a Address) Hex() string { unchecksummed := hex.EncodeToString(a[:]) - sha := sha3.NewKeccak256() + sha := sha3.NewLegacyKeccak256() sha.Write([]byte(unchecksummed)) hash := sha.Sum(nil) @@ -268,6 +280,21 @@ func (a Address) Value() (driver.Value, error) { return a[:], nil } +// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type. +func (a Address) ImplementsGraphQLType(name string) bool { return name == "Address" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (a *Address) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + *a = HexToAddress(input) + default: + err = fmt.Errorf("Unexpected type for Address: %v", input) + } + return err +} + // UnprefixedAddress allows marshaling an Address without 0x prefix. type UnprefixedAddress Address diff --git a/vendor/github.com/ethereum/go-ethereum/core/asm/asm.go b/vendor/github.com/ethereum/go-ethereum/core/asm/asm.go new file mode 100644 index 0000000000..4257198cc7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/asm/asm.go @@ -0,0 +1,136 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Provides support for dealing with EVM assembly instructions (e.g., disassembling them). +package asm + +import ( + "encoding/hex" + "fmt" + + "github.com/ethereum/go-ethereum/core/vm" +) + +// Iterator for disassembled EVM instructions +type instructionIterator struct { + code []byte + pc uint64 + arg []byte + op vm.OpCode + error error + started bool +} + +// Create a new instruction iterator. +func NewInstructionIterator(code []byte) *instructionIterator { + it := new(instructionIterator) + it.code = code + return it +} + +// Returns true if there is a next instruction and moves on. +func (it *instructionIterator) Next() bool { + if it.error != nil || uint64(len(it.code)) <= it.pc { + // We previously reached an error or the end. + return false + } + + if it.started { + // Since the iteration has been already started we move to the next instruction. + if it.arg != nil { + it.pc += uint64(len(it.arg)) + } + it.pc++ + } else { + // We start the iteration from the first instruction. + it.started = true + } + + if uint64(len(it.code)) <= it.pc { + // We reached the end. + return false + } + + it.op = vm.OpCode(it.code[it.pc]) + if it.op.IsPush() { + a := uint64(it.op) - uint64(vm.PUSH1) + 1 + u := it.pc + 1 + a + if uint64(len(it.code)) <= it.pc || uint64(len(it.code)) < u { + it.error = fmt.Errorf("incomplete push instruction at %v", it.pc) + return false + } + it.arg = it.code[it.pc+1 : u] + } else { + it.arg = nil + } + return true +} + +// Returns any error that may have been encountered. +func (it *instructionIterator) Error() error { + return it.error +} + +// Returns the PC of the current instruction. +func (it *instructionIterator) PC() uint64 { + return it.pc +} + +// Returns the opcode of the current instruction. +func (it *instructionIterator) Op() vm.OpCode { + return it.op +} + +// Returns the argument of the current instruction. +func (it *instructionIterator) Arg() []byte { + return it.arg +} + +// Pretty-print all disassembled EVM instructions to stdout. +func PrintDisassembled(code string) error { + script, err := hex.DecodeString(code) + if err != nil { + return err + } + + it := NewInstructionIterator(script) + for it.Next() { + if it.Arg() != nil && 0 < len(it.Arg()) { + fmt.Printf("%05x: %v 0x%x\n", it.PC(), it.Op(), it.Arg()) + } else { + fmt.Printf("%05x: %v\n", it.PC(), it.Op()) + } + } + return it.Error() +} + +// Return all disassembled EVM instructions in human-readable format. +func Disassemble(script []byte) ([]string, error) { + instrs := make([]string, 0) + + it := NewInstructionIterator(script) + for it.Next() { + if it.Arg() != nil && 0 < len(it.Arg()) { + instrs = append(instrs, fmt.Sprintf("%05x: %v 0x%x\n", it.PC(), it.Op(), it.Arg())) + } else { + instrs = append(instrs, fmt.Sprintf("%05x: %v\n", it.PC(), it.Op())) + } + } + if err := it.Error(); err != nil { + return nil, err + } + return instrs, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/asm/asm_test.go b/vendor/github.com/ethereum/go-ethereum/core/asm/asm_test.go new file mode 100644 index 0000000000..92b26b67a5 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/asm/asm_test.go @@ -0,0 +1,74 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package asm + +import ( + "testing" + + "encoding/hex" +) + +// Tests disassembling the instructions for valid evm code +func TestInstructionIteratorValid(t *testing.T) { + cnt := 0 + script, _ := hex.DecodeString("61000000") + + it := NewInstructionIterator(script) + for it.Next() { + cnt++ + } + + if err := it.Error(); err != nil { + t.Errorf("Expected 2, but encountered error %v instead.", err) + } + if cnt != 2 { + t.Errorf("Expected 2, but got %v instead.", cnt) + } +} + +// Tests disassembling the instructions for invalid evm code +func TestInstructionIteratorInvalid(t *testing.T) { + cnt := 0 + script, _ := hex.DecodeString("6100") + + it := NewInstructionIterator(script) + for it.Next() { + cnt++ + } + + if it.Error() == nil { + t.Errorf("Expected an error, but got %v instead.", cnt) + } +} + +// Tests disassembling the instructions for empty evm code +func TestInstructionIteratorEmpty(t *testing.T) { + cnt := 0 + script, _ := hex.DecodeString("") + + it := NewInstructionIterator(script) + for it.Next() { + cnt++ + } + + if err := it.Error(); err != nil { + t.Errorf("Expected 0, but encountered error %v instead.", err) + } + if cnt != 0 { + t.Errorf("Expected 0, but got %v instead.", cnt) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/asm/compiler.go b/vendor/github.com/ethereum/go-ethereum/core/asm/compiler.go new file mode 100644 index 0000000000..c7a5440701 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/asm/compiler.go @@ -0,0 +1,269 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package asm + +import ( + "fmt" + "math/big" + "os" + "strings" + + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/vm" +) + +// Compiler contains information about the parsed source +// and holds the tokens for the program. +type Compiler struct { + tokens []token + binary []interface{} + + labels map[string]int + + pc, pos int + + debug bool +} + +// newCompiler returns a new allocated compiler. +func NewCompiler(debug bool) *Compiler { + return &Compiler{ + labels: make(map[string]int), + debug: debug, + } +} + +// Feed feeds tokens in to ch and are interpreted by +// the compiler. +// +// feed is the first pass in the compile stage as it +// collects the used labels in the program and keeps a +// program counter which is used to determine the locations +// of the jump dests. The labels can than be used in the +// second stage to push labels and determine the right +// position. +func (c *Compiler) Feed(ch <-chan token) { + for i := range ch { + switch i.typ { + case number: + num := math.MustParseBig256(i.text).Bytes() + if len(num) == 0 { + num = []byte{0} + } + c.pc += len(num) + case stringValue: + c.pc += len(i.text) - 2 + case element: + c.pc++ + case labelDef: + c.labels[i.text] = c.pc + c.pc++ + case label: + c.pc += 5 + } + + c.tokens = append(c.tokens, i) + } + if c.debug { + fmt.Fprintln(os.Stderr, "found", len(c.labels), "labels") + } +} + +// Compile compiles the current tokens and returns a +// binary string that can be interpreted by the EVM +// and an error if it failed. +// +// compile is the second stage in the compile phase +// which compiles the tokens to EVM instructions. +func (c *Compiler) Compile() (string, []error) { + var errors []error + // continue looping over the tokens until + // the stack has been exhausted. + for c.pos < len(c.tokens) { + if err := c.compileLine(); err != nil { + errors = append(errors, err) + } + } + + // turn the binary to hex + var bin string + for _, v := range c.binary { + switch v := v.(type) { + case vm.OpCode: + bin += fmt.Sprintf("%x", []byte{byte(v)}) + case []byte: + bin += fmt.Sprintf("%x", v) + } + } + return bin, errors +} + +// next returns the next token and increments the +// position. +func (c *Compiler) next() token { + token := c.tokens[c.pos] + c.pos++ + return token +} + +// compileLine compiles a single line instruction e.g. +// "push 1", "jump @label". +func (c *Compiler) compileLine() error { + n := c.next() + if n.typ != lineStart { + return compileErr(n, n.typ.String(), lineStart.String()) + } + + lvalue := c.next() + switch lvalue.typ { + case eof: + return nil + case element: + if err := c.compileElement(lvalue); err != nil { + return err + } + case labelDef: + c.compileLabel() + case lineEnd: + return nil + default: + return compileErr(lvalue, lvalue.text, fmt.Sprintf("%v or %v", labelDef, element)) + } + + if n := c.next(); n.typ != lineEnd { + return compileErr(n, n.text, lineEnd.String()) + } + + return nil +} + +// compileNumber compiles the number to bytes +func (c *Compiler) compileNumber(element token) (int, error) { + num := math.MustParseBig256(element.text).Bytes() + if len(num) == 0 { + num = []byte{0} + } + c.pushBin(num) + return len(num), nil +} + +// compileElement compiles the element (push & label or both) +// to a binary representation and may error if incorrect statements +// where fed. +func (c *Compiler) compileElement(element token) error { + // check for a jump. jumps must be read and compiled + // from right to left. + if isJump(element.text) { + rvalue := c.next() + switch rvalue.typ { + case number: + // TODO figure out how to return the error properly + c.compileNumber(rvalue) + case stringValue: + // strings are quoted, remove them. + c.pushBin(rvalue.text[1 : len(rvalue.text)-2]) + case label: + c.pushBin(vm.PUSH4) + pos := big.NewInt(int64(c.labels[rvalue.text])).Bytes() + pos = append(make([]byte, 4-len(pos)), pos...) + c.pushBin(pos) + default: + return compileErr(rvalue, rvalue.text, "number, string or label") + } + // push the operation + c.pushBin(toBinary(element.text)) + return nil + } else if isPush(element.text) { + // handle pushes. pushes are read from left to right. + var value []byte + + rvalue := c.next() + switch rvalue.typ { + case number: + value = math.MustParseBig256(rvalue.text).Bytes() + if len(value) == 0 { + value = []byte{0} + } + case stringValue: + value = []byte(rvalue.text[1 : len(rvalue.text)-1]) + case label: + value = make([]byte, 4) + copy(value, big.NewInt(int64(c.labels[rvalue.text])).Bytes()) + default: + return compileErr(rvalue, rvalue.text, "number, string or label") + } + + if len(value) > 32 { + return fmt.Errorf("%d type error: unsupported string or number with size > 32", rvalue.lineno) + } + + c.pushBin(vm.OpCode(int(vm.PUSH1) - 1 + len(value))) + c.pushBin(value) + } else { + c.pushBin(toBinary(element.text)) + } + + return nil +} + +// compileLabel pushes a jumpdest to the binary slice. +func (c *Compiler) compileLabel() { + c.pushBin(vm.JUMPDEST) +} + +// pushBin pushes the value v to the binary stack. +func (c *Compiler) pushBin(v interface{}) { + if c.debug { + fmt.Printf("%d: %v\n", len(c.binary), v) + } + c.binary = append(c.binary, v) +} + +// isPush returns whether the string op is either any of +// push(N). +func isPush(op string) bool { + return strings.ToUpper(op) == "PUSH" +} + +// isJump returns whether the string op is jump(i) +func isJump(op string) bool { + return strings.ToUpper(op) == "JUMPI" || strings.ToUpper(op) == "JUMP" +} + +// toBinary converts text to a vm.OpCode +func toBinary(text string) vm.OpCode { + return vm.StringToOp(strings.ToUpper(text)) +} + +type compileError struct { + got string + want string + + lineno int +} + +func (err compileError) Error() string { + return fmt.Sprintf("%d syntax error: unexpected %v, expected %v", err.lineno, err.got, err.want) +} + +func compileErr(c token, got, want string) error { + return compileError{ + got: got, + want: want, + lineno: c.lineno, + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/asm/lex_test.go b/vendor/github.com/ethereum/go-ethereum/core/asm/lex_test.go new file mode 100644 index 0000000000..16e0ad458d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/asm/lex_test.go @@ -0,0 +1,71 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package asm + +import ( + "reflect" + "testing" +) + +func lexAll(src string) []token { + ch := Lex([]byte(src), false) + + var tokens []token + for i := range ch { + tokens = append(tokens, i) + } + return tokens +} + +func TestLexer(t *testing.T) { + tests := []struct { + input string + tokens []token + }{ + { + input: ";; this is a comment", + tokens: []token{{typ: lineStart}, {typ: eof}}, + }, + { + input: "0x12345678", + tokens: []token{{typ: lineStart}, {typ: number, text: "0x12345678"}, {typ: eof}}, + }, + { + input: "0x123ggg", + tokens: []token{{typ: lineStart}, {typ: number, text: "0x123"}, {typ: element, text: "ggg"}, {typ: eof}}, + }, + { + input: "12345678", + tokens: []token{{typ: lineStart}, {typ: number, text: "12345678"}, {typ: eof}}, + }, + { + input: "123abc", + tokens: []token{{typ: lineStart}, {typ: number, text: "123"}, {typ: element, text: "abc"}, {typ: eof}}, + }, + { + input: "0123abc", + tokens: []token{{typ: lineStart}, {typ: number, text: "0123"}, {typ: element, text: "abc"}, {typ: eof}}, + }, + } + + for _, test := range tests { + tokens := lexAll(test.input) + if !reflect.DeepEqual(tokens, test.tokens) { + t.Errorf("input %q\ngot: %+v\nwant: %+v", test.input, tokens, test.tokens) + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/asm/lexer.go b/vendor/github.com/ethereum/go-ethereum/core/asm/lexer.go new file mode 100644 index 0000000000..00526242e4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/asm/lexer.go @@ -0,0 +1,291 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package asm + +import ( + "fmt" + "os" + "strings" + "unicode" + "unicode/utf8" +) + +// stateFn is used through the lifetime of the +// lexer to parse the different values at the +// current state. +type stateFn func(*lexer) stateFn + +// token is emitted when the lexer has discovered +// a new parsable token. These are delivered over +// the tokens channels of the lexer +type token struct { + typ tokenType + lineno int + text string +} + +// tokenType are the different types the lexer +// is able to parse and return. +type tokenType int + +const ( + eof tokenType = iota // end of file + lineStart // emitted when a line starts + lineEnd // emitted when a line ends + invalidStatement // any invalid statement + element // any element during element parsing + label // label is emitted when a label is found + labelDef // label definition is emitted when a new label is found + number // number is emitted when a number is found + stringValue // stringValue is emitted when a string has been found + + Numbers = "1234567890" // characters representing any decimal number + HexadecimalNumbers = Numbers + "aAbBcCdDeEfF" // characters representing any hexadecimal + Alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" // characters representing alphanumeric +) + +// String implements stringer +func (it tokenType) String() string { + if int(it) > len(stringtokenTypes) { + return "invalid" + } + return stringtokenTypes[it] +} + +var stringtokenTypes = []string{ + eof: "EOF", + invalidStatement: "invalid statement", + element: "element", + lineEnd: "end of line", + lineStart: "new line", + label: "label", + labelDef: "label definition", + number: "number", + stringValue: "string", +} + +// lexer is the basic construct for parsing +// source code and turning them in to tokens. +// Tokens are interpreted by the compiler. +type lexer struct { + input string // input contains the source code of the program + + tokens chan token // tokens is used to deliver tokens to the listener + state stateFn // the current state function + + lineno int // current line number in the source file + start, pos, width int // positions for lexing and returning value + + debug bool // flag for triggering debug output +} + +// lex lexes the program by name with the given source. It returns a +// channel on which the tokens are delivered. +func Lex(source []byte, debug bool) <-chan token { + ch := make(chan token) + l := &lexer{ + input: string(source), + tokens: ch, + state: lexLine, + debug: debug, + } + go func() { + l.emit(lineStart) + for l.state != nil { + l.state = l.state(l) + } + l.emit(eof) + close(l.tokens) + }() + + return ch +} + +// next returns the next rune in the program's source. +func (l *lexer) next() (rune rune) { + if l.pos >= len(l.input) { + l.width = 0 + return 0 + } + rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:]) + l.pos += l.width + return rune +} + +// backup backsup the last parsed element (multi-character) +func (l *lexer) backup() { + l.pos -= l.width +} + +// peek returns the next rune but does not advance the seeker +func (l *lexer) peek() rune { + r := l.next() + l.backup() + return r +} + +// ignore advances the seeker and ignores the value +func (l *lexer) ignore() { + l.start = l.pos +} + +// Accepts checks whether the given input matches the next rune +func (l *lexer) accept(valid string) bool { + if strings.ContainsRune(valid, l.next()) { + return true + } + + l.backup() + + return false +} + +// acceptRun will continue to advance the seeker until valid +// can no longer be met. +func (l *lexer) acceptRun(valid string) { + for strings.ContainsRune(valid, l.next()) { + } + l.backup() +} + +// acceptRunUntil is the inverse of acceptRun and will continue +// to advance the seeker until the rune has been found. +func (l *lexer) acceptRunUntil(until rune) bool { + // Continues running until a rune is found + for i := l.next(); !strings.ContainsRune(string(until), i); i = l.next() { + if i == 0 { + return false + } + } + + return true +} + +// blob returns the current value +func (l *lexer) blob() string { + return l.input[l.start:l.pos] +} + +// Emits a new token on to token channel for processing +func (l *lexer) emit(t tokenType) { + token := token{t, l.lineno, l.blob()} + + if l.debug { + fmt.Fprintf(os.Stderr, "%04d: (%-20v) %s\n", token.lineno, token.typ, token.text) + } + + l.tokens <- token + l.start = l.pos +} + +// lexLine is state function for lexing lines +func lexLine(l *lexer) stateFn { + for { + switch r := l.next(); { + case r == '\n': + l.emit(lineEnd) + l.ignore() + l.lineno++ + + l.emit(lineStart) + case r == ';' && l.peek() == ';': + return lexComment + case isSpace(r): + l.ignore() + case isLetter(r) || r == '_': + return lexElement + case isNumber(r): + return lexNumber + case r == '@': + l.ignore() + return lexLabel + case r == '"': + return lexInsideString + default: + return nil + } + } +} + +// lexComment parses the current position until the end +// of the line and discards the text. +func lexComment(l *lexer) stateFn { + l.acceptRunUntil('\n') + l.ignore() + + return lexLine +} + +// lexLabel parses the current label, emits and returns +// the lex text state function to advance the parsing +// process. +func lexLabel(l *lexer) stateFn { + l.acceptRun(Alpha + "_") + + l.emit(label) + + return lexLine +} + +// lexInsideString lexes the inside of a string until +// the state function finds the closing quote. +// It returns the lex text state function. +func lexInsideString(l *lexer) stateFn { + if l.acceptRunUntil('"') { + l.emit(stringValue) + } + + return lexLine +} + +func lexNumber(l *lexer) stateFn { + acceptance := Numbers + if l.accept("0") || l.accept("xX") { + acceptance = HexadecimalNumbers + } + l.acceptRun(acceptance) + + l.emit(number) + + return lexLine +} + +func lexElement(l *lexer) stateFn { + l.acceptRun(Alpha + "_" + Numbers) + + if l.peek() == ':' { + l.emit(labelDef) + + l.accept(":") + l.ignore() + } else { + l.emit(element) + } + return lexLine +} + +func isLetter(t rune) bool { + return unicode.IsLetter(t) +} + +func isSpace(t rune) bool { + return unicode.IsSpace(t) +} + +func isNumber(t rune) bool { + return unicode.IsNumber(t) +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/bloombits/doc.go b/vendor/github.com/ethereum/go-ethereum/core/bloombits/doc.go new file mode 100644 index 0000000000..3d159e74f7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/bloombits/doc.go @@ -0,0 +1,18 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package bloombits implements bloom filtering on batches of data. +package bloombits diff --git a/vendor/github.com/ethereum/go-ethereum/core/bloombits/generator.go b/vendor/github.com/ethereum/go-ethereum/core/bloombits/generator.go new file mode 100644 index 0000000000..ae07481ada --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/bloombits/generator.go @@ -0,0 +1,93 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bloombits + +import ( + "errors" + + "github.com/ethereum/go-ethereum/core/types" +) + +var ( + // errSectionOutOfBounds is returned if the user tried to add more bloom filters + // to the batch than available space, or if tries to retrieve above the capacity. + errSectionOutOfBounds = errors.New("section out of bounds") + + // errBloomBitOutOfBounds is returned if the user tried to retrieve specified + // bit bloom above the capacity. + errBloomBitOutOfBounds = errors.New("bloom bit out of bounds") +) + +// Generator takes a number of bloom filters and generates the rotated bloom bits +// to be used for batched filtering. +type Generator struct { + blooms [types.BloomBitLength][]byte // Rotated blooms for per-bit matching + sections uint // Number of sections to batch together + nextSec uint // Next section to set when adding a bloom +} + +// NewGenerator creates a rotated bloom generator that can iteratively fill a +// batched bloom filter's bits. +func NewGenerator(sections uint) (*Generator, error) { + if sections%8 != 0 { + return nil, errors.New("section count not multiple of 8") + } + b := &Generator{sections: sections} + for i := 0; i < types.BloomBitLength; i++ { + b.blooms[i] = make([]byte, sections/8) + } + return b, nil +} + +// AddBloom takes a single bloom filter and sets the corresponding bit column +// in memory accordingly. +func (b *Generator) AddBloom(index uint, bloom types.Bloom) error { + // Make sure we're not adding more bloom filters than our capacity + if b.nextSec >= b.sections { + return errSectionOutOfBounds + } + if b.nextSec != index { + return errors.New("bloom filter with unexpected index") + } + // Rotate the bloom and insert into our collection + byteIndex := b.nextSec / 8 + bitMask := byte(1) << byte(7-b.nextSec%8) + + for i := 0; i < types.BloomBitLength; i++ { + bloomByteIndex := types.BloomByteLength - 1 - i/8 + bloomBitMask := byte(1) << byte(i%8) + + if (bloom[bloomByteIndex] & bloomBitMask) != 0 { + b.blooms[i][byteIndex] |= bitMask + } + } + b.nextSec++ + + return nil +} + +// Bitset returns the bit vector belonging to the given bit index after all +// blooms have been added. +func (b *Generator) Bitset(idx uint) ([]byte, error) { + if b.nextSec != b.sections { + return nil, errors.New("bloom not fully generated yet") + } + if idx >= types.BloomBitLength { + return nil, errBloomBitOutOfBounds + } + return b.blooms[idx], nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/bloombits/generator_test.go b/vendor/github.com/ethereum/go-ethereum/core/bloombits/generator_test.go new file mode 100644 index 0000000000..f9bcef96e0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/bloombits/generator_test.go @@ -0,0 +1,60 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bloombits + +import ( + "bytes" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/core/types" +) + +// Tests that batched bloom bits are correctly rotated from the input bloom +// filters. +func TestGenerator(t *testing.T) { + // Generate the input and the rotated output + var input, output [types.BloomBitLength][types.BloomByteLength]byte + + for i := 0; i < types.BloomBitLength; i++ { + for j := 0; j < types.BloomBitLength; j++ { + bit := byte(rand.Int() % 2) + + input[i][j/8] |= bit << byte(7-j%8) + output[types.BloomBitLength-1-j][i/8] |= bit << byte(7-i%8) + } + } + // Crunch the input through the generator and verify the result + gen, err := NewGenerator(types.BloomBitLength) + if err != nil { + t.Fatalf("failed to create bloombit generator: %v", err) + } + for i, bloom := range input { + if err := gen.AddBloom(uint(i), bloom); err != nil { + t.Fatalf("bloom %d: failed to add: %v", i, err) + } + } + for i, want := range output { + have, err := gen.Bitset(uint(i)) + if err != nil { + t.Fatalf("output %d: failed to retrieve bits: %v", i, err) + } + if !bytes.Equal(have, want[:]) { + t.Errorf("output %d: bit vector mismatch have %x, want %x", i, have, want) + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/bloombits/matcher.go b/vendor/github.com/ethereum/go-ethereum/core/bloombits/matcher.go new file mode 100644 index 0000000000..3ec0d5ae94 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/bloombits/matcher.go @@ -0,0 +1,650 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bloombits + +import ( + "bytes" + "context" + "errors" + "math" + "sort" + "sync" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common/bitutil" + "github.com/ethereum/go-ethereum/crypto" +) + +// bloomIndexes represents the bit indexes inside the bloom filter that belong +// to some key. +type bloomIndexes [3]uint + +// calcBloomIndexes returns the bloom filter bit indexes belonging to the given key. +func calcBloomIndexes(b []byte) bloomIndexes { + b = crypto.Keccak256(b) + + var idxs bloomIndexes + for i := 0; i < len(idxs); i++ { + idxs[i] = (uint(b[2*i])<<8)&2047 + uint(b[2*i+1]) + } + return idxs +} + +// partialMatches with a non-nil vector represents a section in which some sub- +// matchers have already found potential matches. Subsequent sub-matchers will +// binary AND their matches with this vector. If vector is nil, it represents a +// section to be processed by the first sub-matcher. +type partialMatches struct { + section uint64 + bitset []byte +} + +// Retrieval represents a request for retrieval task assignments for a given +// bit with the given number of fetch elements, or a response for such a request. +// It can also have the actual results set to be used as a delivery data struct. +// +// The contest and error fields are used by the light client to terminate matching +// early if an error is encountered on some path of the pipeline. +type Retrieval struct { + Bit uint + Sections []uint64 + Bitsets [][]byte + + Context context.Context + Error error +} + +// Matcher is a pipelined system of schedulers and logic matchers which perform +// binary AND/OR operations on the bit-streams, creating a stream of potential +// blocks to inspect for data content. +type Matcher struct { + sectionSize uint64 // Size of the data batches to filter on + + filters [][]bloomIndexes // Filter the system is matching for + schedulers map[uint]*scheduler // Retrieval schedulers for loading bloom bits + + retrievers chan chan uint // Retriever processes waiting for bit allocations + counters chan chan uint // Retriever processes waiting for task count reports + retrievals chan chan *Retrieval // Retriever processes waiting for task allocations + deliveries chan *Retrieval // Retriever processes waiting for task response deliveries + + running uint32 // Atomic flag whether a session is live or not +} + +// NewMatcher creates a new pipeline for retrieving bloom bit streams and doing +// address and topic filtering on them. Setting a filter component to `nil` is +// allowed and will result in that filter rule being skipped (OR 0x11...1). +func NewMatcher(sectionSize uint64, filters [][][]byte) *Matcher { + // Create the matcher instance + m := &Matcher{ + sectionSize: sectionSize, + schedulers: make(map[uint]*scheduler), + retrievers: make(chan chan uint), + counters: make(chan chan uint), + retrievals: make(chan chan *Retrieval), + deliveries: make(chan *Retrieval), + } + // Calculate the bloom bit indexes for the groups we're interested in + m.filters = nil + + for _, filter := range filters { + // Gather the bit indexes of the filter rule, special casing the nil filter + if len(filter) == 0 { + continue + } + bloomBits := make([]bloomIndexes, len(filter)) + for i, clause := range filter { + if clause == nil { + bloomBits = nil + break + } + bloomBits[i] = calcBloomIndexes(clause) + } + // Accumulate the filter rules if no nil rule was within + if bloomBits != nil { + m.filters = append(m.filters, bloomBits) + } + } + // For every bit, create a scheduler to load/download the bit vectors + for _, bloomIndexLists := range m.filters { + for _, bloomIndexList := range bloomIndexLists { + for _, bloomIndex := range bloomIndexList { + m.addScheduler(bloomIndex) + } + } + } + return m +} + +// addScheduler adds a bit stream retrieval scheduler for the given bit index if +// it has not existed before. If the bit is already selected for filtering, the +// existing scheduler can be used. +func (m *Matcher) addScheduler(idx uint) { + if _, ok := m.schedulers[idx]; ok { + return + } + m.schedulers[idx] = newScheduler(idx) +} + +// Start starts the matching process and returns a stream of bloom matches in +// a given range of blocks. If there are no more matches in the range, the result +// channel is closed. +func (m *Matcher) Start(ctx context.Context, begin, end uint64, results chan uint64) (*MatcherSession, error) { + // Make sure we're not creating concurrent sessions + if atomic.SwapUint32(&m.running, 1) == 1 { + return nil, errors.New("matcher already running") + } + defer atomic.StoreUint32(&m.running, 0) + + // Initiate a new matching round + session := &MatcherSession{ + matcher: m, + quit: make(chan struct{}), + kill: make(chan struct{}), + ctx: ctx, + } + for _, scheduler := range m.schedulers { + scheduler.reset() + } + sink := m.run(begin, end, cap(results), session) + + // Read the output from the result sink and deliver to the user + session.pend.Add(1) + go func() { + defer session.pend.Done() + defer close(results) + + for { + select { + case <-session.quit: + return + + case res, ok := <-sink: + // New match result found + if !ok { + return + } + // Calculate the first and last blocks of the section + sectionStart := res.section * m.sectionSize + + first := sectionStart + if begin > first { + first = begin + } + last := sectionStart + m.sectionSize - 1 + if end < last { + last = end + } + // Iterate over all the blocks in the section and return the matching ones + for i := first; i <= last; i++ { + // Skip the entire byte if no matches are found inside (and we're processing an entire byte!) + next := res.bitset[(i-sectionStart)/8] + if next == 0 { + if i%8 == 0 { + i += 7 + } + continue + } + // Some bit it set, do the actual submatching + if bit := 7 - i%8; next&(1<= req.section }) + requests[req.bit] = append(queue[:index], append([]uint64{req.section}, queue[index:]...)...) + + // If it's a new bit and we have waiting fetchers, allocate to them + if len(queue) == 0 { + assign(req.bit) + } + + case fetcher := <-retrievers: + // New retriever arrived, find the lowest section-ed bit to assign + bit, best := uint(0), uint64(math.MaxUint64) + for idx := range unallocs { + if requests[idx][0] < best { + bit, best = idx, requests[idx][0] + } + } + // Stop tracking this bit (and alloc notifications if no more work is available) + delete(unallocs, bit) + if len(unallocs) == 0 { + retrievers = nil + } + allocs++ + fetcher <- bit + + case fetcher := <-m.counters: + // New task count request arrives, return number of items + fetcher <- uint(len(requests[<-fetcher])) + + case fetcher := <-m.retrievals: + // New fetcher waiting for tasks to retrieve, assign + task := <-fetcher + if want := len(task.Sections); want >= len(requests[task.Bit]) { + task.Sections = requests[task.Bit] + delete(requests, task.Bit) + } else { + task.Sections = append(task.Sections[:0], requests[task.Bit][:want]...) + requests[task.Bit] = append(requests[task.Bit][:0], requests[task.Bit][want:]...) + } + fetcher <- task + + // If anything was left unallocated, try to assign to someone else + if len(requests[task.Bit]) > 0 { + assign(task.Bit) + } + + case result := <-m.deliveries: + // New retrieval task response from fetcher, split out missing sections and + // deliver complete ones + var ( + sections = make([]uint64, 0, len(result.Sections)) + bitsets = make([][]byte, 0, len(result.Bitsets)) + missing = make([]uint64, 0, len(result.Sections)) + ) + for i, bitset := range result.Bitsets { + if len(bitset) == 0 { + missing = append(missing, result.Sections[i]) + continue + } + sections = append(sections, result.Sections[i]) + bitsets = append(bitsets, bitset) + } + m.schedulers[result.Bit].deliver(sections, bitsets) + allocs-- + + // Reschedule missing sections and allocate bit if newly available + if len(missing) > 0 { + queue := requests[result.Bit] + for _, section := range missing { + index := sort.Search(len(queue), func(i int) bool { return queue[i] >= section }) + queue = append(queue[:index], append([]uint64{section}, queue[index:]...)...) + } + requests[result.Bit] = queue + + if len(queue) == len(missing) { + assign(result.Bit) + } + } + // If we're in the process of shutting down, terminate + if allocs == 0 && shutdown == nil { + return + } + } + } +} + +// MatcherSession is returned by a started matcher to be used as a terminator +// for the actively running matching operation. +type MatcherSession struct { + matcher *Matcher + + closer sync.Once // Sync object to ensure we only ever close once + quit chan struct{} // Quit channel to request pipeline termination + kill chan struct{} // Term channel to signal non-graceful forced shutdown + + ctx context.Context // Context used by the light client to abort filtering + err atomic.Value // Global error to track retrieval failures deep in the chain + + pend sync.WaitGroup +} + +// Close stops the matching process and waits for all subprocesses to terminate +// before returning. The timeout may be used for graceful shutdown, allowing the +// currently running retrievals to complete before this time. +func (s *MatcherSession) Close() { + s.closer.Do(func() { + // Signal termination and wait for all goroutines to tear down + close(s.quit) + time.AfterFunc(time.Second, func() { close(s.kill) }) + s.pend.Wait() + }) +} + +// Error returns any failure encountered during the matching session. +func (s *MatcherSession) Error() error { + if err := s.err.Load(); err != nil { + return err.(error) + } + return nil +} + +// AllocateRetrieval assigns a bloom bit index to a client process that can either +// immediately request and fetch the section contents assigned to this bit or wait +// a little while for more sections to be requested. +func (s *MatcherSession) AllocateRetrieval() (uint, bool) { + fetcher := make(chan uint) + + select { + case <-s.quit: + return 0, false + case s.matcher.retrievers <- fetcher: + bit, ok := <-fetcher + return bit, ok + } +} + +// PendingSections returns the number of pending section retrievals belonging to +// the given bloom bit index. +func (s *MatcherSession) PendingSections(bit uint) int { + fetcher := make(chan uint) + + select { + case <-s.quit: + return 0 + case s.matcher.counters <- fetcher: + fetcher <- bit + return int(<-fetcher) + } +} + +// AllocateSections assigns all or part of an already allocated bit-task queue +// to the requesting process. +func (s *MatcherSession) AllocateSections(bit uint, count int) []uint64 { + fetcher := make(chan *Retrieval) + + select { + case <-s.quit: + return nil + case s.matcher.retrievals <- fetcher: + task := &Retrieval{ + Bit: bit, + Sections: make([]uint64, count), + } + fetcher <- task + return (<-fetcher).Sections + } +} + +// DeliverSections delivers a batch of section bit-vectors for a specific bloom +// bit index to be injected into the processing pipeline. +func (s *MatcherSession) DeliverSections(bit uint, sections []uint64, bitsets [][]byte) { + select { + case <-s.kill: + return + case s.matcher.deliveries <- &Retrieval{Bit: bit, Sections: sections, Bitsets: bitsets}: + } +} + +// Multiplex polls the matcher session for retrieval tasks and multiplexes it into +// the requested retrieval queue to be serviced together with other sessions. +// +// This method will block for the lifetime of the session. Even after termination +// of the session, any request in-flight need to be responded to! Empty responses +// are fine though in that case. +func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan *Retrieval) { + for { + // Allocate a new bloom bit index to retrieve data for, stopping when done + bit, ok := s.AllocateRetrieval() + if !ok { + return + } + // Bit allocated, throttle a bit if we're below our batch limit + if s.PendingSections(bit) < batch { + select { + case <-s.quit: + // Session terminating, we can't meaningfully service, abort + s.AllocateSections(bit, 0) + s.DeliverSections(bit, []uint64{}, [][]byte{}) + return + + case <-time.After(wait): + // Throttling up, fetch whatever's available + } + } + // Allocate as much as we can handle and request servicing + sections := s.AllocateSections(bit, batch) + request := make(chan *Retrieval) + + select { + case <-s.quit: + // Session terminating, we can't meaningfully service, abort + s.DeliverSections(bit, sections, make([][]byte, len(sections))) + return + + case mux <- request: + // Retrieval accepted, something must arrive before we're aborting + request <- &Retrieval{Bit: bit, Sections: sections, Context: s.ctx} + + result := <-request + if result.Error != nil { + s.err.Store(result.Error) + s.Close() + } + s.DeliverSections(result.Bit, result.Sections, result.Bitsets) + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/bloombits/matcher_test.go b/vendor/github.com/ethereum/go-ethereum/core/bloombits/matcher_test.go new file mode 100644 index 0000000000..91143e525e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/bloombits/matcher_test.go @@ -0,0 +1,286 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bloombits + +import ( + "context" + "math/rand" + "sync/atomic" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" +) + +const testSectionSize = 4096 + +// Tests that wildcard filter rules (nil) can be specified and are handled well. +func TestMatcherWildcards(t *testing.T) { + matcher := NewMatcher(testSectionSize, [][][]byte{ + {common.Address{}.Bytes(), common.Address{0x01}.Bytes()}, // Default address is not a wildcard + {common.Hash{}.Bytes(), common.Hash{0x01}.Bytes()}, // Default hash is not a wildcard + {common.Hash{0x01}.Bytes()}, // Plain rule, sanity check + {common.Hash{0x01}.Bytes(), nil}, // Wildcard suffix, drop rule + {nil, common.Hash{0x01}.Bytes()}, // Wildcard prefix, drop rule + {nil, nil}, // Wildcard combo, drop rule + {}, // Inited wildcard rule, drop rule + nil, // Proper wildcard rule, drop rule + }) + if len(matcher.filters) != 3 { + t.Fatalf("filter system size mismatch: have %d, want %d", len(matcher.filters), 3) + } + if len(matcher.filters[0]) != 2 { + t.Fatalf("address clause size mismatch: have %d, want %d", len(matcher.filters[0]), 2) + } + if len(matcher.filters[1]) != 2 { + t.Fatalf("combo topic clause size mismatch: have %d, want %d", len(matcher.filters[1]), 2) + } + if len(matcher.filters[2]) != 1 { + t.Fatalf("singletone topic clause size mismatch: have %d, want %d", len(matcher.filters[2]), 1) + } +} + +// Tests the matcher pipeline on a single continuous workflow without interrupts. +func TestMatcherContinuous(t *testing.T) { + testMatcherDiffBatches(t, [][]bloomIndexes{{{10, 20, 30}}}, 0, 100000, false, 75) + testMatcherDiffBatches(t, [][]bloomIndexes{{{32, 3125, 100}}, {{40, 50, 10}}}, 0, 100000, false, 81) + testMatcherDiffBatches(t, [][]bloomIndexes{{{4, 8, 11}, {7, 8, 17}}, {{9, 9, 12}, {15, 20, 13}}, {{18, 15, 15}, {12, 10, 4}}}, 0, 10000, false, 36) +} + +// Tests the matcher pipeline on a constantly interrupted and resumed work pattern +// with the aim of ensuring data items are requested only once. +func TestMatcherIntermittent(t *testing.T) { + testMatcherDiffBatches(t, [][]bloomIndexes{{{10, 20, 30}}}, 0, 100000, true, 75) + testMatcherDiffBatches(t, [][]bloomIndexes{{{32, 3125, 100}}, {{40, 50, 10}}}, 0, 100000, true, 81) + testMatcherDiffBatches(t, [][]bloomIndexes{{{4, 8, 11}, {7, 8, 17}}, {{9, 9, 12}, {15, 20, 13}}, {{18, 15, 15}, {12, 10, 4}}}, 0, 10000, true, 36) +} + +// Tests the matcher pipeline on random input to hopefully catch anomalies. +func TestMatcherRandom(t *testing.T) { + for i := 0; i < 10; i++ { + testMatcherBothModes(t, makeRandomIndexes([]int{1}, 50), 0, 10000, 0) + testMatcherBothModes(t, makeRandomIndexes([]int{3}, 50), 0, 10000, 0) + testMatcherBothModes(t, makeRandomIndexes([]int{2, 2, 2}, 20), 0, 10000, 0) + testMatcherBothModes(t, makeRandomIndexes([]int{5, 5, 5}, 50), 0, 10000, 0) + testMatcherBothModes(t, makeRandomIndexes([]int{4, 4, 4}, 20), 0, 10000, 0) + } +} + +// Tests that the matcher can properly find matches if the starting block is +// shifter from a multiple of 8. This is needed to cover an optimisation with +// bitset matching https://github.com/ethereum/go-ethereum/issues/15309. +func TestMatcherShifted(t *testing.T) { + // Block 0 always matches in the tests, skip ahead of first 8 blocks with the + // start to get a potential zero byte in the matcher bitset. + + // To keep the second bitset byte zero, the filter must only match for the first + // time in block 16, so doing an all-16 bit filter should suffice. + + // To keep the starting block non divisible by 8, block number 9 is the first + // that would introduce a shift and not match block 0. + testMatcherBothModes(t, [][]bloomIndexes{{{16, 16, 16}}}, 9, 64, 0) +} + +// Tests that matching on everything doesn't crash (special case internally). +func TestWildcardMatcher(t *testing.T) { + testMatcherBothModes(t, nil, 0, 10000, 0) +} + +// makeRandomIndexes generates a random filter system, composed on multiple filter +// criteria, each having one bloom list component for the address and arbitrarily +// many topic bloom list components. +func makeRandomIndexes(lengths []int, max int) [][]bloomIndexes { + res := make([][]bloomIndexes, len(lengths)) + for i, topics := range lengths { + res[i] = make([]bloomIndexes, topics) + for j := 0; j < topics; j++ { + for k := 0; k < len(res[i][j]); k++ { + res[i][j][k] = uint(rand.Intn(max-1) + 2) + } + } + } + return res +} + +// testMatcherDiffBatches runs the given matches test in single-delivery and also +// in batches delivery mode, verifying that all kinds of deliveries are handled +// correctly withn. +func testMatcherDiffBatches(t *testing.T, filter [][]bloomIndexes, start, blocks uint64, intermittent bool, retrievals uint32) { + singleton := testMatcher(t, filter, start, blocks, intermittent, retrievals, 1) + batched := testMatcher(t, filter, start, blocks, intermittent, retrievals, 16) + + if singleton != batched { + t.Errorf("filter = %v blocks = %v intermittent = %v: request count mismatch, %v in signleton vs. %v in batched mode", filter, blocks, intermittent, singleton, batched) + } +} + +// testMatcherBothModes runs the given matcher test in both continuous as well as +// in intermittent mode, verifying that the request counts match each other. +func testMatcherBothModes(t *testing.T, filter [][]bloomIndexes, start, blocks uint64, retrievals uint32) { + continuous := testMatcher(t, filter, start, blocks, false, retrievals, 16) + intermittent := testMatcher(t, filter, start, blocks, true, retrievals, 16) + + if continuous != intermittent { + t.Errorf("filter = %v blocks = %v: request count mismatch, %v in continuous vs. %v in intermittent mode", filter, blocks, continuous, intermittent) + } +} + +// testMatcher is a generic tester to run the given matcher test and return the +// number of requests made for cross validation between different modes. +func testMatcher(t *testing.T, filter [][]bloomIndexes, start, blocks uint64, intermittent bool, retrievals uint32, maxReqCount int) uint32 { + // Create a new matcher an simulate our explicit random bitsets + matcher := NewMatcher(testSectionSize, nil) + matcher.filters = filter + + for _, rule := range filter { + for _, topic := range rule { + for _, bit := range topic { + matcher.addScheduler(bit) + } + } + } + // Track the number of retrieval requests made + var requested uint32 + + // Start the matching session for the filter and the retriever goroutines + quit := make(chan struct{}) + matches := make(chan uint64, 16) + + session, err := matcher.Start(context.Background(), start, blocks-1, matches) + if err != nil { + t.Fatalf("failed to stat matcher session: %v", err) + } + startRetrievers(session, quit, &requested, maxReqCount) + + // Iterate over all the blocks and verify that the pipeline produces the correct matches + for i := start; i < blocks; i++ { + if expMatch3(filter, i) { + match, ok := <-matches + if !ok { + t.Errorf("filter = %v blocks = %v intermittent = %v: expected #%v, results channel closed", filter, blocks, intermittent, i) + return 0 + } + if match != i { + t.Errorf("filter = %v blocks = %v intermittent = %v: expected #%v, got #%v", filter, blocks, intermittent, i, match) + } + // If we're testing intermittent mode, abort and restart the pipeline + if intermittent { + session.Close() + close(quit) + + quit = make(chan struct{}) + matches = make(chan uint64, 16) + + session, err = matcher.Start(context.Background(), i+1, blocks-1, matches) + if err != nil { + t.Fatalf("failed to stat matcher session: %v", err) + } + startRetrievers(session, quit, &requested, maxReqCount) + } + } + } + // Ensure the result channel is torn down after the last block + match, ok := <-matches + if ok { + t.Errorf("filter = %v blocks = %v intermittent = %v: expected closed channel, got #%v", filter, blocks, intermittent, match) + } + // Clean up the session and ensure we match the expected retrieval count + session.Close() + close(quit) + + if retrievals != 0 && requested != retrievals { + t.Errorf("filter = %v blocks = %v intermittent = %v: request count mismatch, have #%v, want #%v", filter, blocks, intermittent, requested, retrievals) + } + return requested +} + +// startRetrievers starts a batch of goroutines listening for section requests +// and serving them. +func startRetrievers(session *MatcherSession, quit chan struct{}, retrievals *uint32, batch int) { + requests := make(chan chan *Retrieval) + + for i := 0; i < 10; i++ { + // Start a multiplexer to test multiple threaded execution + go session.Multiplex(batch, 100*time.Microsecond, requests) + + // Start a services to match the above multiplexer + go func() { + for { + // Wait for a service request or a shutdown + select { + case <-quit: + return + + case request := <-requests: + task := <-request + + task.Bitsets = make([][]byte, len(task.Sections)) + for i, section := range task.Sections { + if rand.Int()%4 != 0 { // Handle occasional missing deliveries + task.Bitsets[i] = generateBitset(task.Bit, section) + atomic.AddUint32(retrievals, 1) + } + } + request <- task + } + } + }() + } +} + +// generateBitset generates the rotated bitset for the given bloom bit and section +// numbers. +func generateBitset(bit uint, section uint64) []byte { + bitset := make([]byte, testSectionSize/8) + for i := 0; i < len(bitset); i++ { + for b := 0; b < 8; b++ { + blockIdx := section*testSectionSize + uint64(i*8+b) + bitset[i] += bitset[i] + if (blockIdx % uint64(bit)) == 0 { + bitset[i]++ + } + } + } + return bitset +} + +func expMatch1(filter bloomIndexes, i uint64) bool { + for _, ii := range filter { + if (i % uint64(ii)) != 0 { + return false + } + } + return true +} + +func expMatch2(filter []bloomIndexes, i uint64) bool { + for _, ii := range filter { + if expMatch1(ii, i) { + return true + } + } + return false +} + +func expMatch3(filter [][]bloomIndexes, i uint64) bool { + for _, ii := range filter { + if !expMatch2(ii, i) { + return false + } + } + return true +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/bloombits/scheduler.go b/vendor/github.com/ethereum/go-ethereum/core/bloombits/scheduler.go new file mode 100644 index 0000000000..6449c7465a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/bloombits/scheduler.go @@ -0,0 +1,181 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bloombits + +import ( + "sync" +) + +// request represents a bloom retrieval task to prioritize and pull from the local +// database or remotely from the network. +type request struct { + section uint64 // Section index to retrieve the a bit-vector from + bit uint // Bit index within the section to retrieve the vector of +} + +// response represents the state of a requested bit-vector through a scheduler. +type response struct { + cached []byte // Cached bits to dedup multiple requests + done chan struct{} // Channel to allow waiting for completion +} + +// scheduler handles the scheduling of bloom-filter retrieval operations for +// entire section-batches belonging to a single bloom bit. Beside scheduling the +// retrieval operations, this struct also deduplicates the requests and caches +// the results to minimize network/database overhead even in complex filtering +// scenarios. +type scheduler struct { + bit uint // Index of the bit in the bloom filter this scheduler is responsible for + responses map[uint64]*response // Currently pending retrieval requests or already cached responses + lock sync.Mutex // Lock protecting the responses from concurrent access +} + +// newScheduler creates a new bloom-filter retrieval scheduler for a specific +// bit index. +func newScheduler(idx uint) *scheduler { + return &scheduler{ + bit: idx, + responses: make(map[uint64]*response), + } +} + +// run creates a retrieval pipeline, receiving section indexes from sections and +// returning the results in the same order through the done channel. Concurrent +// runs of the same scheduler are allowed, leading to retrieval task deduplication. +func (s *scheduler) run(sections chan uint64, dist chan *request, done chan []byte, quit chan struct{}, wg *sync.WaitGroup) { + // Create a forwarder channel between requests and responses of the same size as + // the distribution channel (since that will block the pipeline anyway). + pend := make(chan uint64, cap(dist)) + + // Start the pipeline schedulers to forward between user -> distributor -> user + wg.Add(2) + go s.scheduleRequests(sections, dist, pend, quit, wg) + go s.scheduleDeliveries(pend, done, quit, wg) +} + +// reset cleans up any leftovers from previous runs. This is required before a +// restart to ensure the no previously requested but never delivered state will +// cause a lockup. +func (s *scheduler) reset() { + s.lock.Lock() + defer s.lock.Unlock() + + for section, res := range s.responses { + if res.cached == nil { + delete(s.responses, section) + } + } +} + +// scheduleRequests reads section retrieval requests from the input channel, +// deduplicates the stream and pushes unique retrieval tasks into the distribution +// channel for a database or network layer to honour. +func (s *scheduler) scheduleRequests(reqs chan uint64, dist chan *request, pend chan uint64, quit chan struct{}, wg *sync.WaitGroup) { + // Clean up the goroutine and pipeline when done + defer wg.Done() + defer close(pend) + + // Keep reading and scheduling section requests + for { + select { + case <-quit: + return + + case section, ok := <-reqs: + // New section retrieval requested + if !ok { + return + } + // Deduplicate retrieval requests + unique := false + + s.lock.Lock() + if s.responses[section] == nil { + s.responses[section] = &response{ + done: make(chan struct{}), + } + unique = true + } + s.lock.Unlock() + + // Schedule the section for retrieval and notify the deliverer to expect this section + if unique { + select { + case <-quit: + return + case dist <- &request{bit: s.bit, section: section}: + } + } + select { + case <-quit: + return + case pend <- section: + } + } + } +} + +// scheduleDeliveries reads section acceptance notifications and waits for them +// to be delivered, pushing them into the output data buffer. +func (s *scheduler) scheduleDeliveries(pend chan uint64, done chan []byte, quit chan struct{}, wg *sync.WaitGroup) { + // Clean up the goroutine and pipeline when done + defer wg.Done() + defer close(done) + + // Keep reading notifications and scheduling deliveries + for { + select { + case <-quit: + return + + case idx, ok := <-pend: + // New section retrieval pending + if !ok { + return + } + // Wait until the request is honoured + s.lock.Lock() + res := s.responses[idx] + s.lock.Unlock() + + select { + case <-quit: + return + case <-res.done: + } + // Deliver the result + select { + case <-quit: + return + case done <- res.cached: + } + } + } +} + +// deliver is called by the request distributor when a reply to a request arrives. +func (s *scheduler) deliver(sections []uint64, data [][]byte) { + s.lock.Lock() + defer s.lock.Unlock() + + for i, section := range sections { + if res := s.responses[section]; res != nil && res.cached == nil { // Avoid non-requests and double deliveries + res.cached = data[i] + close(res.done) + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/bloombits/scheduler_test.go b/vendor/github.com/ethereum/go-ethereum/core/bloombits/scheduler_test.go new file mode 100644 index 0000000000..70772e4ab9 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/bloombits/scheduler_test.go @@ -0,0 +1,105 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bloombits + +import ( + "bytes" + "math/big" + "math/rand" + "sync" + "sync/atomic" + "testing" + "time" +) + +// Tests that the scheduler can deduplicate and forward retrieval requests to +// underlying fetchers and serve responses back, irrelevant of the concurrency +// of the requesting clients or serving data fetchers. +func TestSchedulerSingleClientSingleFetcher(t *testing.T) { testScheduler(t, 1, 1, 5000) } +func TestSchedulerSingleClientMultiFetcher(t *testing.T) { testScheduler(t, 1, 10, 5000) } +func TestSchedulerMultiClientSingleFetcher(t *testing.T) { testScheduler(t, 10, 1, 5000) } +func TestSchedulerMultiClientMultiFetcher(t *testing.T) { testScheduler(t, 10, 10, 5000) } + +func testScheduler(t *testing.T, clients int, fetchers int, requests int) { + f := newScheduler(0) + + // Create a batch of handler goroutines that respond to bloom bit requests and + // deliver them to the scheduler. + var fetchPend sync.WaitGroup + fetchPend.Add(fetchers) + defer fetchPend.Wait() + + fetch := make(chan *request, 16) + defer close(fetch) + + var delivered uint32 + for i := 0; i < fetchers; i++ { + go func() { + defer fetchPend.Done() + + for req := range fetch { + time.Sleep(time.Duration(rand.Intn(int(100 * time.Microsecond)))) + atomic.AddUint32(&delivered, 1) + + f.deliver([]uint64{ + req.section + uint64(requests), // Non-requested data (ensure it doesn't go out of bounds) + req.section, // Requested data + req.section, // Duplicated data (ensure it doesn't double close anything) + }, [][]byte{ + {}, + new(big.Int).SetUint64(req.section).Bytes(), + new(big.Int).SetUint64(req.section).Bytes(), + }) + } + }() + } + // Start a batch of goroutines to concurrently run scheduling tasks + quit := make(chan struct{}) + + var pend sync.WaitGroup + pend.Add(clients) + + for i := 0; i < clients; i++ { + go func() { + defer pend.Done() + + in := make(chan uint64, 16) + out := make(chan []byte, 16) + + f.run(in, fetch, out, quit, &pend) + + go func() { + for j := 0; j < requests; j++ { + in <- uint64(j) + } + close(in) + }() + + for j := 0; j < requests; j++ { + bits := <-out + if want := new(big.Int).SetUint64(uint64(j)).Bytes(); !bytes.Equal(bits, want) { + t.Errorf("vector %d: delivered content mismatch: have %x, want %x", j, bits, want) + } + } + }() + } + pend.Wait() + + if have := atomic.LoadUint32(&delivered); int(have) != requests { + t.Errorf("request count mismatch: have %v, want %v", have, requests) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain.go new file mode 100644 index 0000000000..6478399971 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain.go @@ -0,0 +1,425 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +import ( + "bytes" + "encoding/binary" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" +) + +// ReadCanonicalHash retrieves the hash assigned to a canonical block number. +func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { + data, _ := db.Get(headerHashKey(number)) + if len(data) == 0 { + return common.Hash{} + } + return common.BytesToHash(data) +} + +// WriteCanonicalHash stores the hash assigned to a canonical block number. +func WriteCanonicalHash(db ethdb.Writer, hash common.Hash, number uint64) { + if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil { + log.Crit("Failed to store number to hash mapping", "err", err) + } +} + +// DeleteCanonicalHash removes the number to hash canonical mapping. +func DeleteCanonicalHash(db ethdb.Writer, number uint64) { + if err := db.Delete(headerHashKey(number)); err != nil { + log.Crit("Failed to delete number to hash mapping", "err", err) + } +} + +// ReadHeaderNumber returns the header number assigned to a hash. +func ReadHeaderNumber(db ethdb.Reader, hash common.Hash) *uint64 { + data, _ := db.Get(headerNumberKey(hash)) + if len(data) != 8 { + return nil + } + number := binary.BigEndian.Uint64(data) + return &number +} + +// ReadHeadHeaderHash retrieves the hash of the current canonical head header. +func ReadHeadHeaderHash(db ethdb.Reader) common.Hash { + data, _ := db.Get(headHeaderKey) + if len(data) == 0 { + return common.Hash{} + } + return common.BytesToHash(data) +} + +// WriteHeadHeaderHash stores the hash of the current canonical head header. +func WriteHeadHeaderHash(db ethdb.Writer, hash common.Hash) { + if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { + log.Crit("Failed to store last header's hash", "err", err) + } +} + +// ReadHeadBlockHash retrieves the hash of the current canonical head block. +func ReadHeadBlockHash(db ethdb.Reader) common.Hash { + data, _ := db.Get(headBlockKey) + if len(data) == 0 { + return common.Hash{} + } + return common.BytesToHash(data) +} + +// WriteHeadBlockHash stores the head block's hash. +func WriteHeadBlockHash(db ethdb.Writer, hash common.Hash) { + if err := db.Put(headBlockKey, hash.Bytes()); err != nil { + log.Crit("Failed to store last block's hash", "err", err) + } +} + +// ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block. +func ReadHeadFastBlockHash(db ethdb.Reader) common.Hash { + data, _ := db.Get(headFastBlockKey) + if len(data) == 0 { + return common.Hash{} + } + return common.BytesToHash(data) +} + +// WriteHeadFastBlockHash stores the hash of the current fast-sync head block. +func WriteHeadFastBlockHash(db ethdb.Writer, hash common.Hash) { + if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil { + log.Crit("Failed to store last fast block's hash", "err", err) + } +} + +// ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow +// reporting correct numbers across restarts. +func ReadFastTrieProgress(db ethdb.Reader) uint64 { + data, _ := db.Get(fastTrieProgressKey) + if len(data) == 0 { + return 0 + } + return new(big.Int).SetBytes(data).Uint64() +} + +// WriteFastTrieProgress stores the fast sync trie process counter to support +// retrieving it across restarts. +func WriteFastTrieProgress(db ethdb.Writer, count uint64) { + if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil { + log.Crit("Failed to store fast sync trie progress", "err", err) + } +} + +// ReadHeaderRLP retrieves a block header in its raw RLP database encoding. +func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Get(headerKey(number, hash)) + return data +} + +// HasHeader verifies the existence of a block header corresponding to the hash. +func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool { + if has, err := db.Has(headerKey(number, hash)); !has || err != nil { + return false + } + return true +} + +// ReadHeader retrieves the block header corresponding to the hash. +func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header { + data := ReadHeaderRLP(db, hash, number) + if len(data) == 0 { + return nil + } + header := new(types.Header) + if err := rlp.Decode(bytes.NewReader(data), header); err != nil { + log.Error("Invalid block header RLP", "hash", hash, "err", err) + return nil + } + return header +} + +// WriteHeader stores a block header into the database and also stores the hash- +// to-number mapping. +func WriteHeader(db ethdb.Writer, header *types.Header) { + // Write the hash -> number mapping + var ( + hash = header.Hash() + number = header.Number.Uint64() + encoded = encodeBlockNumber(number) + ) + key := headerNumberKey(hash) + if err := db.Put(key, encoded); err != nil { + log.Crit("Failed to store hash to number mapping", "err", err) + } + // Write the encoded header + data, err := rlp.EncodeToBytes(header) + if err != nil { + log.Crit("Failed to RLP encode header", "err", err) + } + key = headerKey(number, hash) + if err := db.Put(key, data); err != nil { + log.Crit("Failed to store header", "err", err) + } +} + +// DeleteHeader removes all block header data associated with a hash. +func DeleteHeader(db ethdb.Writer, hash common.Hash, number uint64) { + deleteHeaderWithoutNumber(db, hash, number) + if err := db.Delete(headerNumberKey(hash)); err != nil { + log.Crit("Failed to delete hash to number mapping", "err", err) + } +} + +// deleteHeaderWithoutNumber removes only the block header but does not remove +// the hash to number mapping. +func deleteHeaderWithoutNumber(db ethdb.Writer, hash common.Hash, number uint64) { + if err := db.Delete(headerKey(number, hash)); err != nil { + log.Crit("Failed to delete header", "err", err) + } +} + +// ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. +func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Get(blockBodyKey(number, hash)) + return data +} + +// WriteBodyRLP stores an RLP encoded block body into the database. +func WriteBodyRLP(db ethdb.Writer, hash common.Hash, number uint64, rlp rlp.RawValue) { + if err := db.Put(blockBodyKey(number, hash), rlp); err != nil { + log.Crit("Failed to store block body", "err", err) + } +} + +// HasBody verifies the existence of a block body corresponding to the hash. +func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool { + if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil { + return false + } + return true +} + +// ReadBody retrieves the block body corresponding to the hash. +func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body { + data := ReadBodyRLP(db, hash, number) + if len(data) == 0 { + return nil + } + body := new(types.Body) + if err := rlp.Decode(bytes.NewReader(data), body); err != nil { + log.Error("Invalid block body RLP", "hash", hash, "err", err) + return nil + } + return body +} + +// WriteBody storea a block body into the database. +func WriteBody(db ethdb.Writer, hash common.Hash, number uint64, body *types.Body) { + data, err := rlp.EncodeToBytes(body) + if err != nil { + log.Crit("Failed to RLP encode body", "err", err) + } + WriteBodyRLP(db, hash, number, data) +} + +// DeleteBody removes all block body data associated with a hash. +func DeleteBody(db ethdb.Writer, hash common.Hash, number uint64) { + if err := db.Delete(blockBodyKey(number, hash)); err != nil { + log.Crit("Failed to delete block body", "err", err) + } +} + +// ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding. +func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Get(headerTDKey(number, hash)) + return data +} + +// ReadTd retrieves a block's total difficulty corresponding to the hash. +func ReadTd(db ethdb.Reader, hash common.Hash, number uint64) *big.Int { + data := ReadTdRLP(db, hash, number) + if len(data) == 0 { + return nil + } + td := new(big.Int) + if err := rlp.Decode(bytes.NewReader(data), td); err != nil { + log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) + return nil + } + return td +} + +// WriteTd stores the total difficulty of a block into the database. +func WriteTd(db ethdb.Writer, hash common.Hash, number uint64, td *big.Int) { + data, err := rlp.EncodeToBytes(td) + if err != nil { + log.Crit("Failed to RLP encode block total difficulty", "err", err) + } + if err := db.Put(headerTDKey(number, hash), data); err != nil { + log.Crit("Failed to store block total difficulty", "err", err) + } +} + +// DeleteTd removes all block total difficulty data associated with a hash. +func DeleteTd(db ethdb.Writer, hash common.Hash, number uint64) { + if err := db.Delete(headerTDKey(number, hash)); err != nil { + log.Crit("Failed to delete block total difficulty", "err", err) + } +} + +// HasReceipts verifies the existence of all the transaction receipts belonging +// to a block. +func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool { + if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil { + return false + } + return true +} + +// ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding. +func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Get(blockReceiptsKey(number, hash)) + return data +} + +// ReadReceipts retrieves all the transaction receipts belonging to a block. +func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts { + // Retrieve the flattened receipt slice + data := ReadReceiptsRLP(db, hash, number) + if len(data) == 0 { + return nil + } + // Convert the receipts from their storage form to their internal representation + storageReceipts := []*types.ReceiptForStorage{} + if err := rlp.DecodeBytes(data, &storageReceipts); err != nil { + log.Error("Invalid receipt array RLP", "hash", hash, "err", err) + return nil + } + receipts := make(types.Receipts, len(storageReceipts)) + logIndex := uint(0) + for i, receipt := range storageReceipts { + // Assemble deriving fields for log. + for _, log := range receipt.Logs { + log.TxHash = receipt.TxHash + log.BlockHash = hash + log.BlockNumber = number + log.TxIndex = uint(i) + log.Index = logIndex + logIndex += 1 + } + receipts[i] = (*types.Receipt)(receipt) + receipts[i].BlockHash = hash + receipts[i].BlockNumber = big.NewInt(0).SetUint64(number) + receipts[i].TransactionIndex = uint(i) + } + return receipts +} + +// WriteReceipts stores all the transaction receipts belonging to a block. +func WriteReceipts(db ethdb.Writer, hash common.Hash, number uint64, receipts types.Receipts) { + // Convert the receipts into their storage form and serialize them + storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) + for i, receipt := range receipts { + storageReceipts[i] = (*types.ReceiptForStorage)(receipt) + } + bytes, err := rlp.EncodeToBytes(storageReceipts) + if err != nil { + log.Crit("Failed to encode block receipts", "err", err) + } + // Store the flattened receipt slice + if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil { + log.Crit("Failed to store block receipts", "err", err) + } +} + +// DeleteReceipts removes all receipt data associated with a block hash. +func DeleteReceipts(db ethdb.Writer, hash common.Hash, number uint64) { + if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { + log.Crit("Failed to delete block receipts", "err", err) + } +} + +// ReadBlock retrieves an entire block corresponding to the hash, assembling it +// back from the stored header and body. If either the header or body could not +// be retrieved nil is returned. +// +// Note, due to concurrent download of header and block body the header and thus +// canonical hash can be stored in the database but the body data not (yet). +func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block { + header := ReadHeader(db, hash, number) + if header == nil { + return nil + } + body := ReadBody(db, hash, number) + if body == nil { + return nil + } + return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles) +} + +// WriteBlock serializes a block into the database, header and body separately. +func WriteBlock(db ethdb.Writer, block *types.Block) { + WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) + WriteHeader(db, block.Header()) +} + +// DeleteBlock removes all block data associated with a hash. +func DeleteBlock(db ethdb.Writer, hash common.Hash, number uint64) { + DeleteReceipts(db, hash, number) + DeleteHeader(db, hash, number) + DeleteBody(db, hash, number) + DeleteTd(db, hash, number) +} + +// deleteBlockWithoutNumber removes all block data associated with a hash, except +// the hash to number mapping. +func deleteBlockWithoutNumber(db ethdb.Writer, hash common.Hash, number uint64) { + DeleteReceipts(db, hash, number) + deleteHeaderWithoutNumber(db, hash, number) + DeleteBody(db, hash, number) + DeleteTd(db, hash, number) +} + +// FindCommonAncestor returns the last common ancestor of two block headers +func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header { + for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { + a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) + if a == nil { + return nil + } + } + for an := a.Number.Uint64(); an < b.Number.Uint64(); { + b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) + if b == nil { + return nil + } + } + for a.Hash() != b.Hash() { + a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) + if a == nil { + return nil + } + b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) + if b == nil { + return nil + } + } + return a +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain_test.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain_test.go new file mode 100644 index 0000000000..9f6e9cdb3e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain_test.go @@ -0,0 +1,320 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +import ( + "bytes" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" + "golang.org/x/crypto/sha3" +) + +// Tests block header storage and retrieval operations. +func TestHeaderStorage(t *testing.T) { + db := NewMemoryDatabase() + + // Create a test header to move around the database and make sure it's really new + header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")} + if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil { + t.Fatalf("Non existent header returned: %v", entry) + } + // Write and verify the header in the database + WriteHeader(db, header) + if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry == nil { + t.Fatalf("Stored header not found") + } else if entry.Hash() != header.Hash() { + t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, header) + } + if entry := ReadHeaderRLP(db, header.Hash(), header.Number.Uint64()); entry == nil { + t.Fatalf("Stored header RLP not found") + } else { + hasher := sha3.NewLegacyKeccak256() + hasher.Write(entry) + + if hash := common.BytesToHash(hasher.Sum(nil)); hash != header.Hash() { + t.Fatalf("Retrieved RLP header mismatch: have %v, want %v", entry, header) + } + } + // Delete the header and verify the execution + DeleteHeader(db, header.Hash(), header.Number.Uint64()) + if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil { + t.Fatalf("Deleted header returned: %v", entry) + } +} + +// Tests block body storage and retrieval operations. +func TestBodyStorage(t *testing.T) { + db := NewMemoryDatabase() + + // Create a test body to move around the database and make sure it's really new + body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}} + + hasher := sha3.NewLegacyKeccak256() + rlp.Encode(hasher, body) + hash := common.BytesToHash(hasher.Sum(nil)) + + if entry := ReadBody(db, hash, 0); entry != nil { + t.Fatalf("Non existent body returned: %v", entry) + } + // Write and verify the body in the database + WriteBody(db, hash, 0, body) + if entry := ReadBody(db, hash, 0); entry == nil { + t.Fatalf("Stored body not found") + } else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(types.Transactions(body.Transactions)) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(body.Uncles) { + t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, body) + } + if entry := ReadBodyRLP(db, hash, 0); entry == nil { + t.Fatalf("Stored body RLP not found") + } else { + hasher := sha3.NewLegacyKeccak256() + hasher.Write(entry) + + if calc := common.BytesToHash(hasher.Sum(nil)); calc != hash { + t.Fatalf("Retrieved RLP body mismatch: have %v, want %v", entry, body) + } + } + // Delete the body and verify the execution + DeleteBody(db, hash, 0) + if entry := ReadBody(db, hash, 0); entry != nil { + t.Fatalf("Deleted body returned: %v", entry) + } +} + +// Tests block storage and retrieval operations. +func TestBlockStorage(t *testing.T) { + db := NewMemoryDatabase() + + // Create a test block to move around the database and make sure it's really new + block := types.NewBlockWithHeader(&types.Header{ + Extra: []byte("test block"), + UncleHash: types.EmptyUncleHash, + TxHash: types.EmptyRootHash, + ReceiptHash: types.EmptyRootHash, + }) + if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { + t.Fatalf("Non existent block returned: %v", entry) + } + if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil { + t.Fatalf("Non existent header returned: %v", entry) + } + if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil { + t.Fatalf("Non existent body returned: %v", entry) + } + // Write and verify the block in the database + WriteBlock(db, block) + if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil { + t.Fatalf("Stored block not found") + } else if entry.Hash() != block.Hash() { + t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block) + } + if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry == nil { + t.Fatalf("Stored header not found") + } else if entry.Hash() != block.Header().Hash() { + t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, block.Header()) + } + if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry == nil { + t.Fatalf("Stored body not found") + } else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(block.Transactions()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(block.Uncles()) { + t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, block.Body()) + } + // Delete the block and verify the execution + DeleteBlock(db, block.Hash(), block.NumberU64()) + if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { + t.Fatalf("Deleted block returned: %v", entry) + } + if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil { + t.Fatalf("Deleted header returned: %v", entry) + } + if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil { + t.Fatalf("Deleted body returned: %v", entry) + } +} + +// Tests that partial block contents don't get reassembled into full blocks. +func TestPartialBlockStorage(t *testing.T) { + db := NewMemoryDatabase() + block := types.NewBlockWithHeader(&types.Header{ + Extra: []byte("test block"), + UncleHash: types.EmptyUncleHash, + TxHash: types.EmptyRootHash, + ReceiptHash: types.EmptyRootHash, + }) + // Store a header and check that it's not recognized as a block + WriteHeader(db, block.Header()) + if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { + t.Fatalf("Non existent block returned: %v", entry) + } + DeleteHeader(db, block.Hash(), block.NumberU64()) + + // Store a body and check that it's not recognized as a block + WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) + if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { + t.Fatalf("Non existent block returned: %v", entry) + } + DeleteBody(db, block.Hash(), block.NumberU64()) + + // Store a header and a body separately and check reassembly + WriteHeader(db, block.Header()) + WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) + + if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil { + t.Fatalf("Stored block not found") + } else if entry.Hash() != block.Hash() { + t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block) + } +} + +// Tests block total difficulty storage and retrieval operations. +func TestTdStorage(t *testing.T) { + db := NewMemoryDatabase() + + // Create a test TD to move around the database and make sure it's really new + hash, td := common.Hash{}, big.NewInt(314) + if entry := ReadTd(db, hash, 0); entry != nil { + t.Fatalf("Non existent TD returned: %v", entry) + } + // Write and verify the TD in the database + WriteTd(db, hash, 0, td) + if entry := ReadTd(db, hash, 0); entry == nil { + t.Fatalf("Stored TD not found") + } else if entry.Cmp(td) != 0 { + t.Fatalf("Retrieved TD mismatch: have %v, want %v", entry, td) + } + // Delete the TD and verify the execution + DeleteTd(db, hash, 0) + if entry := ReadTd(db, hash, 0); entry != nil { + t.Fatalf("Deleted TD returned: %v", entry) + } +} + +// Tests that canonical numbers can be mapped to hashes and retrieved. +func TestCanonicalMappingStorage(t *testing.T) { + db := NewMemoryDatabase() + + // Create a test canonical number and assinged hash to move around + hash, number := common.Hash{0: 0xff}, uint64(314) + if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) { + t.Fatalf("Non existent canonical mapping returned: %v", entry) + } + // Write and verify the TD in the database + WriteCanonicalHash(db, hash, number) + if entry := ReadCanonicalHash(db, number); entry == (common.Hash{}) { + t.Fatalf("Stored canonical mapping not found") + } else if entry != hash { + t.Fatalf("Retrieved canonical mapping mismatch: have %v, want %v", entry, hash) + } + // Delete the TD and verify the execution + DeleteCanonicalHash(db, number) + if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) { + t.Fatalf("Deleted canonical mapping returned: %v", entry) + } +} + +// Tests that head headers and head blocks can be assigned, individually. +func TestHeadStorage(t *testing.T) { + db := NewMemoryDatabase() + + blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")}) + blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")}) + blockFast := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block fast")}) + + // Check that no head entries are in a pristine database + if entry := ReadHeadHeaderHash(db); entry != (common.Hash{}) { + t.Fatalf("Non head header entry returned: %v", entry) + } + if entry := ReadHeadBlockHash(db); entry != (common.Hash{}) { + t.Fatalf("Non head block entry returned: %v", entry) + } + if entry := ReadHeadFastBlockHash(db); entry != (common.Hash{}) { + t.Fatalf("Non fast head block entry returned: %v", entry) + } + // Assign separate entries for the head header and block + WriteHeadHeaderHash(db, blockHead.Hash()) + WriteHeadBlockHash(db, blockFull.Hash()) + WriteHeadFastBlockHash(db, blockFast.Hash()) + + // Check that both heads are present, and different (i.e. two heads maintained) + if entry := ReadHeadHeaderHash(db); entry != blockHead.Hash() { + t.Fatalf("Head header hash mismatch: have %v, want %v", entry, blockHead.Hash()) + } + if entry := ReadHeadBlockHash(db); entry != blockFull.Hash() { + t.Fatalf("Head block hash mismatch: have %v, want %v", entry, blockFull.Hash()) + } + if entry := ReadHeadFastBlockHash(db); entry != blockFast.Hash() { + t.Fatalf("Fast head block hash mismatch: have %v, want %v", entry, blockFast.Hash()) + } +} + +// Tests that receipts associated with a single block can be stored and retrieved. +func TestBlockReceiptStorage(t *testing.T) { + db := NewMemoryDatabase() + + receipt1 := &types.Receipt{ + Status: types.ReceiptStatusFailed, + CumulativeGasUsed: 1, + Logs: []*types.Log{ + {Address: common.BytesToAddress([]byte{0x11})}, + {Address: common.BytesToAddress([]byte{0x01, 0x11})}, + }, + TxHash: common.BytesToHash([]byte{0x11, 0x11}), + ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), + GasUsed: 111111, + } + receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) + receipt2 := &types.Receipt{ + PostState: common.Hash{2}.Bytes(), + CumulativeGasUsed: 2, + Logs: []*types.Log{ + {Address: common.BytesToAddress([]byte{0x22})}, + {Address: common.BytesToAddress([]byte{0x02, 0x22})}, + }, + TxHash: common.BytesToHash([]byte{0x22, 0x22}), + ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), + GasUsed: 222222, + } + receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) + receipts := []*types.Receipt{receipt1, receipt2} + + // Check that no receipt entries are in a pristine database + hash := common.BytesToHash([]byte{0x03, 0x14}) + if rs := ReadReceipts(db, hash, 0); len(rs) != 0 { + t.Fatalf("non existent receipts returned: %v", rs) + } + // Insert the receipt slice into the database and check presence + WriteReceipts(db, hash, 0, receipts) + if rs := ReadReceipts(db, hash, 0); len(rs) == 0 { + t.Fatalf("no receipts returned") + } else { + for i := 0; i < len(receipts); i++ { + rlpHave, _ := rlp.EncodeToBytes(rs[i]) + rlpWant, _ := rlp.EncodeToBytes(receipts[i]) + + if !bytes.Equal(rlpHave, rlpWant) { + t.Fatalf("receipt #%d: receipt mismatch: have %v, want %v", i, rs[i], receipts[i]) + } + } + } + // Delete the receipt slice and check purge + DeleteReceipts(db, hash, 0) + if rs := ReadReceipts(db, hash, 0); len(rs) != 0 { + t.Fatalf("deleted receipts returned: %v", rs) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes.go new file mode 100644 index 0000000000..5c7ad69347 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes.go @@ -0,0 +1,119 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" +) + +// ReadTxLookupEntry retrieves the positional metadata associated with a transaction +// hash to allow retrieving the transaction or receipt by hash. +func ReadTxLookupEntry(db ethdb.Reader, hash common.Hash) common.Hash { + data, _ := db.Get(txLookupKey(hash)) + if len(data) == 0 { + return common.Hash{} + } + if len(data) == common.HashLength { + return common.BytesToHash(data) + } + // Probably it's legacy txlookup entry data, try to decode it. + var entry LegacyTxLookupEntry + if err := rlp.DecodeBytes(data, &entry); err != nil { + log.Error("Invalid transaction lookup entry RLP", "hash", hash, "blob", data, "err", err) + return common.Hash{} + } + return entry.BlockHash +} + +// WriteTxLookupEntries stores a positional metadata for every transaction from +// a block, enabling hash based transaction and receipt lookups. +func WriteTxLookupEntries(db ethdb.Writer, block *types.Block) { + for _, tx := range block.Transactions() { + if err := db.Put(txLookupKey(tx.Hash()), block.Hash().Bytes()); err != nil { + log.Crit("Failed to store transaction lookup entry", "err", err) + } + } +} + +// DeleteTxLookupEntry removes all transaction data associated with a hash. +func DeleteTxLookupEntry(db ethdb.Writer, hash common.Hash) { + db.Delete(txLookupKey(hash)) +} + +// ReadTransaction retrieves a specific transaction from the database, along with +// its added positional metadata. +func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { + blockHash := ReadTxLookupEntry(db, hash) + if blockHash == (common.Hash{}) { + return nil, common.Hash{}, 0, 0 + } + blockNumber := ReadHeaderNumber(db, blockHash) + if blockNumber == nil { + return nil, common.Hash{}, 0, 0 + } + body := ReadBody(db, blockHash, *blockNumber) + if body == nil { + log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash) + return nil, common.Hash{}, 0, 0 + } + for txIndex, tx := range body.Transactions { + if tx.Hash() == hash { + return tx, blockHash, *blockNumber, uint64(txIndex) + } + } + log.Error("Transaction not found", "number", blockNumber, "hash", blockHash, "txhash", hash) + return nil, common.Hash{}, 0, 0 +} + +// ReadReceipt retrieves a specific transaction receipt from the database, along with +// its added positional metadata. +func ReadReceipt(db ethdb.Reader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) { + blockHash := ReadTxLookupEntry(db, hash) + if blockHash == (common.Hash{}) { + return nil, common.Hash{}, 0, 0 + } + blockNumber := ReadHeaderNumber(db, blockHash) + if blockNumber == nil { + return nil, common.Hash{}, 0, 0 + } + receipts := ReadReceipts(db, blockHash, *blockNumber) + for receiptIndex, receipt := range receipts { + if receipt.TxHash == hash { + return receipt, blockHash, *blockNumber, uint64(receiptIndex) + } + } + log.Error("Receipt not found", "number", blockNumber, "hash", blockHash, "txhash", hash) + return nil, common.Hash{}, 0, 0 +} + +// ReadBloomBits retrieves the compressed bloom bit vector belonging to the given +// section and bit index from the. +func ReadBloomBits(db ethdb.Reader, bit uint, section uint64, head common.Hash) ([]byte, error) { + return db.Get(bloomBitsKey(bit, section, head)) +} + +// WriteBloomBits stores the compressed bloom bits vector belonging to the given +// section and bit index. +func WriteBloomBits(db ethdb.Writer, bit uint, section uint64, head common.Hash, bits []byte) { + if err := db.Put(bloomBitsKey(bit, section, head), bits); err != nil { + log.Crit("Failed to store bloom bits", "err", err) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes_test.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes_test.go new file mode 100644 index 0000000000..ca74ba6af1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes_test.go @@ -0,0 +1,90 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" +) + +// Tests that positional lookup metadata can be stored and retrieved. +func TestLookupStorage(t *testing.T) { + db := NewMemoryDatabase() + + tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) + tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22}) + tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33}) + txs := []*types.Transaction{tx1, tx2, tx3} + + block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil) + + // Check that no transactions entries are in a pristine database + for i, tx := range txs { + if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { + t.Fatalf("tx #%d [%x]: non existent transaction returned: %v", i, tx.Hash(), txn) + } + } + // Insert all the transactions into the database, and verify contents + WriteBlock(db, block) + WriteTxLookupEntries(db, block) + + for i, tx := range txs { + if txn, hash, number, index := ReadTransaction(db, tx.Hash()); txn == nil { + t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash()) + } else { + if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { + t.Fatalf("tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, tx.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i) + } + if tx.Hash() != txn.Hash() { + t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx) + } + } + } + // Delete the transactions and check purge + for i, tx := range txs { + DeleteTxLookupEntry(db, tx.Hash()) + if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { + t.Fatalf("tx #%d [%x]: deleted transaction returned: %v", i, tx.Hash(), txn) + } + } + // Insert legacy txlookup and verify the data retrieval + for index, tx := range block.Transactions() { + entry := LegacyTxLookupEntry{ + BlockHash: block.Hash(), + BlockIndex: block.NumberU64(), + Index: uint64(index), + } + data, _ := rlp.EncodeToBytes(entry) + db.Put(txLookupKey(tx.Hash()), data) + } + for i, tx := range txs { + if txn, hash, number, index := ReadTransaction(db, tx.Hash()); txn == nil { + t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash()) + } else { + if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { + t.Fatalf("tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, tx.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i) + } + if tx.Hash() != txn.Hash() { + t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx) + } + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_metadata.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_metadata.go new file mode 100644 index 0000000000..1361b0d731 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_metadata.go @@ -0,0 +1,98 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +import ( + "encoding/json" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" +) + +// ReadDatabaseVersion retrieves the version number of the database. +func ReadDatabaseVersion(db ethdb.Reader) *uint64 { + var version uint64 + + enc, _ := db.Get(databaseVerisionKey) + if len(enc) == 0 { + return nil + } + if err := rlp.DecodeBytes(enc, &version); err != nil { + return nil + } + + return &version +} + +// WriteDatabaseVersion stores the version number of the database +func WriteDatabaseVersion(db ethdb.Writer, version uint64) { + enc, err := rlp.EncodeToBytes(version) + if err != nil { + log.Crit("Failed to encode database version", "err", err) + } + if err = db.Put(databaseVerisionKey, enc); err != nil { + log.Crit("Failed to store the database version", "err", err) + } +} + +// ReadChainConfig retrieves the consensus settings based on the given genesis hash. +func ReadChainConfig(db ethdb.Reader, hash common.Hash) *params.ChainConfig { + data, _ := db.Get(configKey(hash)) + if len(data) == 0 { + return nil + } + var config params.ChainConfig + if err := json.Unmarshal(data, &config); err != nil { + log.Error("Invalid chain config JSON", "hash", hash, "err", err) + return nil + } + return &config +} + +// WriteChainConfig writes the chain config settings to the database. +func WriteChainConfig(db ethdb.Writer, hash common.Hash, cfg *params.ChainConfig) { + if cfg == nil { + return + } + data, err := json.Marshal(cfg) + if err != nil { + log.Crit("Failed to JSON encode chain config", "err", err) + } + if err := db.Put(configKey(hash), data); err != nil { + log.Crit("Failed to store chain config", "err", err) + } +} + +// ReadPreimage retrieves a single preimage of the provided hash. +func ReadPreimage(db ethdb.Reader, hash common.Hash) []byte { + data, _ := db.Get(preimageKey(hash)) + return data +} + +// WritePreimages writes the provided set of preimages to the database. +func WritePreimages(db ethdb.Writer, preimages map[common.Hash][]byte) { + for hash, preimage := range preimages { + if err := db.Put(preimageKey(hash), preimage); err != nil { + log.Crit("Failed to store trie preimage", "err", err) + } + } + preimageCounter.Inc(int64(len(preimages))) + preimageHitCounter.Inc(int64(len(preimages))) +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/database.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/database.go new file mode 100644 index 0000000000..b4c5dea708 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/database.go @@ -0,0 +1,52 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +import ( + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/leveldb" + "github.com/ethereum/go-ethereum/ethdb/memorydb" +) + +// NewDatabase creates a high level database on top of a given key-value data +// store without a freezer moving immutable chain segments into cold storage. +func NewDatabase(db ethdb.KeyValueStore) ethdb.Database { + return db +} + +// NewMemoryDatabase creates an ephemeral in-memory key-value database without a +// freezer moving immutable chain segments into cold storage. +func NewMemoryDatabase() ethdb.Database { + return NewDatabase(memorydb.New()) +} + +// NewMemoryDatabaseWithCap creates an ephemeral in-memory key-value database with +// an initial starting capacity, but without a freezer moving immutable chain +// segments into cold storage. +func NewMemoryDatabaseWithCap(size int) ethdb.Database { + return NewDatabase(memorydb.NewWithCap(size)) +} + +// NewLevelDBDatabase creates a persistent key-value database without a freezer +// moving immutable chain segments into cold storage. +func NewLevelDBDatabase(file string, cache int, handles int, namespace string) (ethdb.Database, error) { + db, err := leveldb.New(file, cache, handles, namespace) + if err != nil { + return nil, err + } + return NewDatabase(db), nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/schema.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/schema.go new file mode 100644 index 0000000000..87dbf94fc0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/schema.go @@ -0,0 +1,139 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package rawdb contains a collection of low level database accessors. +package rawdb + +import ( + "encoding/binary" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/metrics" +) + +// The fields below define the low level database schema prefixing. +var ( + // databaseVerisionKey tracks the current database version. + databaseVerisionKey = []byte("DatabaseVersion") + + // headHeaderKey tracks the latest know header's hash. + headHeaderKey = []byte("LastHeader") + + // headBlockKey tracks the latest know full block's hash. + headBlockKey = []byte("LastBlock") + + // headFastBlockKey tracks the latest known incomplete block's hash during fast sync. + headFastBlockKey = []byte("LastFast") + + // fastTrieProgressKey tracks the number of trie entries imported during fast sync. + fastTrieProgressKey = []byte("TrieSync") + + // Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes). + headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header + headerTDSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + headerTDSuffix -> td + headerHashSuffix = []byte("n") // headerPrefix + num (uint64 big endian) + headerHashSuffix -> hash + headerNumberPrefix = []byte("H") // headerNumberPrefix + hash -> num (uint64 big endian) + + blockBodyPrefix = []byte("b") // blockBodyPrefix + num (uint64 big endian) + hash -> block body + blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts + + txLookupPrefix = []byte("l") // txLookupPrefix + hash -> transaction/receipt lookup metadata + bloomBitsPrefix = []byte("B") // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits + + preimagePrefix = []byte("secure-key-") // preimagePrefix + hash -> preimage + configPrefix = []byte("ethereum-config-") // config prefix for the db + + // Chain index prefixes (use `i` + single byte to avoid mixing data types). + BloomBitsIndexPrefix = []byte("iB") // BloomBitsIndexPrefix is the data table of a chain indexer to track its progress + + preimageCounter = metrics.NewRegisteredCounter("db/preimage/total", nil) + preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) +) + +// LegacyTxLookupEntry is the legacy TxLookupEntry definition with some unnecessary +// fields. +type LegacyTxLookupEntry struct { + BlockHash common.Hash + BlockIndex uint64 + Index uint64 +} + +// encodeBlockNumber encodes a block number as big endian uint64 +func encodeBlockNumber(number uint64) []byte { + enc := make([]byte, 8) + binary.BigEndian.PutUint64(enc, number) + return enc +} + +// headerKeyPrefix = headerPrefix + num (uint64 big endian) +func headerKeyPrefix(number uint64) []byte { + return append(headerPrefix, encodeBlockNumber(number)...) +} + +// headerKey = headerPrefix + num (uint64 big endian) + hash +func headerKey(number uint64, hash common.Hash) []byte { + return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) +} + +// headerTDKey = headerPrefix + num (uint64 big endian) + hash + headerTDSuffix +func headerTDKey(number uint64, hash common.Hash) []byte { + return append(headerKey(number, hash), headerTDSuffix...) +} + +// headerHashKey = headerPrefix + num (uint64 big endian) + headerHashSuffix +func headerHashKey(number uint64) []byte { + return append(append(headerPrefix, encodeBlockNumber(number)...), headerHashSuffix...) +} + +// headerNumberKey = headerNumberPrefix + hash +func headerNumberKey(hash common.Hash) []byte { + return append(headerNumberPrefix, hash.Bytes()...) +} + +// blockBodyKey = blockBodyPrefix + num (uint64 big endian) + hash +func blockBodyKey(number uint64, hash common.Hash) []byte { + return append(append(blockBodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) +} + +// blockReceiptsKey = blockReceiptsPrefix + num (uint64 big endian) + hash +func blockReceiptsKey(number uint64, hash common.Hash) []byte { + return append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...) +} + +// txLookupKey = txLookupPrefix + hash +func txLookupKey(hash common.Hash) []byte { + return append(txLookupPrefix, hash.Bytes()...) +} + +// bloomBitsKey = bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash +func bloomBitsKey(bit uint, section uint64, hash common.Hash) []byte { + key := append(append(bloomBitsPrefix, make([]byte, 10)...), hash.Bytes()...) + + binary.BigEndian.PutUint16(key[1:], uint16(bit)) + binary.BigEndian.PutUint64(key[3:], section) + + return key +} + +// preimageKey = preimagePrefix + hash +func preimageKey(hash common.Hash) []byte { + return append(preimagePrefix, hash.Bytes()...) +} + +// configKey = configPrefix + hash +func configKey(hash common.Hash) []byte { + return append(configPrefix, hash.Bytes()...) +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/table.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/table.go new file mode 100644 index 0000000000..e19649dd46 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/table.go @@ -0,0 +1,155 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +import ( + "github.com/ethereum/go-ethereum/ethdb" +) + +// table is a wrapper around a database that prefixes each key access with a pre- +// configured string. +type table struct { + db ethdb.Database + prefix string +} + +// NewTable returns a database object that prefixes all keys with a given string. +func NewTable(db ethdb.Database, prefix string) ethdb.Database { + return &table{ + db: db, + prefix: prefix, + } +} + +// Close is a noop to implement the Database interface. +func (t *table) Close() error { + return nil +} + +// Has retrieves if a prefixed version of a key is present in the database. +func (t *table) Has(key []byte) (bool, error) { + return t.db.Has(append([]byte(t.prefix), key...)) +} + +// Get retrieves the given prefixed key if it's present in the database. +func (t *table) Get(key []byte) ([]byte, error) { + return t.db.Get(append([]byte(t.prefix), key...)) +} + +// Put inserts the given value into the database at a prefixed version of the +// provided key. +func (t *table) Put(key []byte, value []byte) error { + return t.db.Put(append([]byte(t.prefix), key...), value) +} + +// Delete removes the given prefixed key from the database. +func (t *table) Delete(key []byte) error { + return t.db.Delete(append([]byte(t.prefix), key...)) +} + +// NewIterator creates a binary-alphabetical iterator over the entire keyspace +// contained within the database. +func (t *table) NewIterator() ethdb.Iterator { + return t.NewIteratorWithPrefix(nil) +} + +// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset +// of database content with a particular key prefix. +func (t *table) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator { + return t.db.NewIteratorWithPrefix(append([]byte(t.prefix), prefix...)) +} + +// Stat returns a particular internal stat of the database. +func (t *table) Stat(property string) (string, error) { + return t.db.Stat(property) +} + +// Compact flattens the underlying data store for the given key range. In essence, +// deleted and overwritten versions are discarded, and the data is rearranged to +// reduce the cost of operations needed to access them. +// +// A nil start is treated as a key before all keys in the data store; a nil limit +// is treated as a key after all keys in the data store. If both is nil then it +// will compact entire data store. +func (t *table) Compact(start []byte, limit []byte) error { + // If no start was specified, use the table prefix as the first value + if start == nil { + start = []byte(t.prefix) + } + // If no limit was specified, use the first element not matching the prefix + // as the limit + if limit == nil { + limit = []byte(t.prefix) + for i := len(limit) - 1; i >= 0; i-- { + // Bump the current character, stopping if it doesn't overflow + limit[i]++ + if limit[i] > 0 { + break + } + // Character overflown, proceed to the next or nil if the last + if i == 0 { + limit = nil + } + } + } + // Range correctly calculated based on table prefix, delegate down + return t.db.Compact(start, limit) +} + +// NewBatch creates a write-only database that buffers changes to its host db +// until a final write is called, each operation prefixing all keys with the +// pre-configured string. +func (t *table) NewBatch() ethdb.Batch { + return &tableBatch{t.db.NewBatch(), t.prefix} +} + +// tableBatch is a wrapper around a database batch that prefixes each key access +// with a pre-configured string. +type tableBatch struct { + batch ethdb.Batch + prefix string +} + +// Put inserts the given value into the batch for later committing. +func (b *tableBatch) Put(key, value []byte) error { + return b.batch.Put(append([]byte(b.prefix), key...), value) +} + +// Delete inserts the a key removal into the batch for later committing. +func (b *tableBatch) Delete(key []byte) error { + return b.batch.Delete(append([]byte(b.prefix), key...)) +} + +// ValueSize retrieves the amount of data queued up for writing. +func (b *tableBatch) ValueSize() int { + return b.batch.ValueSize() +} + +// Write flushes any accumulated data to disk. +func (b *tableBatch) Write() error { + return b.batch.Write() +} + +// Reset resets the batch for reuse. +func (b *tableBatch) Reset() { + b.batch.Reset() +} + +// Replay replays the batch contents. +func (b *tableBatch) Replay(w ethdb.Writer) error { + return b.batch.Replay(w) +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/block.go b/vendor/github.com/ethereum/go-ethereum/core/types/block.go index 9d11f60d83..f754c3c487 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/block.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/block.go @@ -21,20 +21,20 @@ import ( "encoding/binary" "io" "math/big" + "reflect" "sort" "sync/atomic" "time" - "unsafe" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" + "golang.org/x/crypto/sha3" ) var ( EmptyRootHash = DeriveSha(Transactions{}) - EmptyUncleHash = CalcUncleHash(nil) + EmptyUncleHash = rlpHash([]*Header(nil)) ) // A BlockNonce is a 64-bit hash which proves (combined with the @@ -79,7 +79,7 @@ type Header struct { Number *big.Int `json:"number" gencodec:"required"` GasLimit uint64 `json:"gasLimit" gencodec:"required"` GasUsed uint64 `json:"gasUsed" gencodec:"required"` - Time *big.Int `json:"timestamp" gencodec:"required"` + Time uint64 `json:"timestamp" gencodec:"required"` Extra []byte `json:"extraData" gencodec:"required"` MixDigest common.Hash `json:"mixHash"` Nonce BlockNonce `json:"nonce"` @@ -91,7 +91,7 @@ type headerMarshaling struct { Number *hexutil.Big GasLimit hexutil.Uint64 GasUsed hexutil.Uint64 - Time *hexutil.Big + Time hexutil.Uint64 Extra hexutil.Bytes Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON } @@ -102,14 +102,16 @@ func (h *Header) Hash() common.Hash { return rlpHash(h) } +var headerSize = common.StorageSize(reflect.TypeOf(Header{}).Size()) + // Size returns the approximate memory used by all internal contents. It is used // to approximate and limit the memory consumption of various caches. func (h *Header) Size() common.StorageSize { - return common.StorageSize(unsafe.Sizeof(*h)) + common.StorageSize(len(h.Extra)+(h.Difficulty.BitLen()+h.Number.BitLen()+h.Time.BitLen())/8) + return headerSize + common.StorageSize(len(h.Extra)+(h.Difficulty.BitLen()+h.Number.BitLen())/8) } func rlpHash(x interface{}) (h common.Hash) { - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() rlp.Encode(hw, x) hw.Sum(h[:0]) return h @@ -221,9 +223,6 @@ func NewBlockWithHeader(header *Header) *Block { // modifying a header variable. func CopyHeader(h *Header) *Header { cpy := *h - if cpy.Time = new(big.Int); h.Time != nil { - cpy.Time.Set(h.Time) - } if cpy.Difficulty = new(big.Int); h.Difficulty != nil { cpy.Difficulty.Set(h.Difficulty) } @@ -286,7 +285,7 @@ func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) func (b *Block) GasLimit() uint64 { return b.header.GasLimit } func (b *Block) GasUsed() uint64 { return b.header.GasUsed } func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) } -func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) } +func (b *Block) Time() uint64 { return b.header.Time } func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() } func (b *Block) MixDigest() common.Hash { return b.header.MixDigest } @@ -325,6 +324,9 @@ func (c *writeCounter) Write(b []byte) (int, error) { } func CalcUncleHash(uncles []*Header) common.Hash { + if len(uncles) == 0 { + return EmptyUncleHash + } return rlpHash(uncles) } diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/gen_header_json.go b/vendor/github.com/ethereum/go-ethereum/core/types/gen_header_json.go index 59a1c9c439..4212b8d94d 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/gen_header_json.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/gen_header_json.go @@ -27,7 +27,7 @@ func (h Header) MarshalJSON() ([]byte, error) { Number *hexutil.Big `json:"number" gencodec:"required"` GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time *hexutil.Big `json:"timestamp" gencodec:"required"` + Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` Extra hexutil.Bytes `json:"extraData" gencodec:"required"` MixDigest common.Hash `json:"mixHash"` Nonce BlockNonce `json:"nonce"` @@ -45,7 +45,7 @@ func (h Header) MarshalJSON() ([]byte, error) { enc.Number = (*hexutil.Big)(h.Number) enc.GasLimit = hexutil.Uint64(h.GasLimit) enc.GasUsed = hexutil.Uint64(h.GasUsed) - enc.Time = (*hexutil.Big)(h.Time) + enc.Time = hexutil.Uint64(h.Time) enc.Extra = h.Extra enc.MixDigest = h.MixDigest enc.Nonce = h.Nonce @@ -67,7 +67,7 @@ func (h *Header) UnmarshalJSON(input []byte) error { Number *hexutil.Big `json:"number" gencodec:"required"` GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time *hexutil.Big `json:"timestamp" gencodec:"required"` + Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"` Extra *hexutil.Bytes `json:"extraData" gencodec:"required"` MixDigest *common.Hash `json:"mixHash"` Nonce *BlockNonce `json:"nonce"` @@ -123,7 +123,7 @@ func (h *Header) UnmarshalJSON(input []byte) error { if dec.Time == nil { return errors.New("missing required field 'timestamp' for Header") } - h.Time = (*big.Int)(dec.Time) + h.Time = uint64(*dec.Time) if dec.Extra == nil { return errors.New("missing required field 'extraData' for Header") } diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/gen_log_json.go b/vendor/github.com/ethereum/go-ethereum/core/types/gen_log_json.go index 1b5ae3c653..6e94339478 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/gen_log_json.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/gen_log_json.go @@ -12,6 +12,7 @@ import ( var _ = (*logMarshaling)(nil) +// MarshalJSON marshals as JSON. func (l Log) MarshalJSON() ([]byte, error) { type Log struct { Address common.Address `json:"address" gencodec:"required"` @@ -37,6 +38,7 @@ func (l Log) MarshalJSON() ([]byte, error) { return json.Marshal(&enc) } +// UnmarshalJSON unmarshals from JSON. func (l *Log) UnmarshalJSON(input []byte) error { type Log struct { Address *common.Address `json:"address" gencodec:"required"` diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/gen_receipt_json.go b/vendor/github.com/ethereum/go-ethereum/core/types/gen_receipt_json.go index 5c807a4ccb..790ed65b58 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/gen_receipt_json.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/gen_receipt_json.go @@ -5,6 +5,7 @@ package types import ( "encoding/json" "errors" + "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -23,6 +24,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) { TxHash common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress common.Address `json:"contractAddress"` GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + BlockHash common.Hash `json:"blockHash,omitempty"` + BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` + TransactionIndex hexutil.Uint `json:"transactionIndex"` } var enc Receipt enc.PostState = r.PostState @@ -33,6 +37,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) { enc.TxHash = r.TxHash enc.ContractAddress = r.ContractAddress enc.GasUsed = hexutil.Uint64(r.GasUsed) + enc.BlockHash = r.BlockHash + enc.BlockNumber = (*hexutil.Big)(r.BlockNumber) + enc.TransactionIndex = hexutil.Uint(r.TransactionIndex) return json.Marshal(&enc) } @@ -47,6 +54,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { TxHash *common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress *common.Address `json:"contractAddress"` GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + BlockHash *common.Hash `json:"blockHash,omitempty"` + BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` + TransactionIndex *hexutil.Uint `json:"transactionIndex"` } var dec Receipt if err := json.Unmarshal(input, &dec); err != nil { @@ -81,5 +91,14 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { return errors.New("missing required field 'gasUsed' for Receipt") } r.GasUsed = uint64(*dec.GasUsed) + if dec.BlockHash != nil { + r.BlockHash = *dec.BlockHash + } + if dec.BlockNumber != nil { + r.BlockNumber = (*big.Int)(dec.BlockNumber) + } + if dec.TransactionIndex != nil { + r.TransactionIndex = uint(*dec.TransactionIndex) + } return nil } diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/gen_tx_json.go b/vendor/github.com/ethereum/go-ethereum/core/types/gen_tx_json.go index c27da67096..e676058ecc 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/gen_tx_json.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/gen_tx_json.go @@ -13,6 +13,7 @@ import ( var _ = (*txdataMarshaling)(nil) +// MarshalJSON marshals as JSON. func (t txdata) MarshalJSON() ([]byte, error) { type txdata struct { AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"` @@ -40,6 +41,7 @@ func (t txdata) MarshalJSON() ([]byte, error) { return json.Marshal(&enc) } +// UnmarshalJSON unmarshals from JSON. func (t *txdata) UnmarshalJSON(input []byte) error { type txdata struct { AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"` diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/log.go b/vendor/github.com/ethereum/go-ethereum/core/types/log.go index 717cd2e5a0..864af5ef41 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/log.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/log.go @@ -68,7 +68,11 @@ type rlpLog struct { Data []byte } -type rlpStorageLog struct { +// rlpStorageLog is the storage encoding of a log. +type rlpStorageLog rlpLog + +// LegacyRlpStorageLog is the previous storage encoding of a log including some redundant fields. +type LegacyRlpStorageLog struct { Address common.Address Topics []common.Hash Data []byte @@ -101,31 +105,38 @@ type LogForStorage Log // EncodeRLP implements rlp.Encoder. func (l *LogForStorage) EncodeRLP(w io.Writer) error { return rlp.Encode(w, rlpStorageLog{ - Address: l.Address, - Topics: l.Topics, - Data: l.Data, - BlockNumber: l.BlockNumber, - TxHash: l.TxHash, - TxIndex: l.TxIndex, - BlockHash: l.BlockHash, - Index: l.Index, + Address: l.Address, + Topics: l.Topics, + Data: l.Data, }) } // DecodeRLP implements rlp.Decoder. +// +// Note some redundant fields(e.g. block number, tx hash etc) will be assembled later. func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error { + blob, err := s.Raw() + if err != nil { + return err + } var dec rlpStorageLog - err := s.Decode(&dec) + err = rlp.DecodeBytes(blob, &dec) if err == nil { *l = LogForStorage{ - Address: dec.Address, - Topics: dec.Topics, - Data: dec.Data, - BlockNumber: dec.BlockNumber, - TxHash: dec.TxHash, - TxIndex: dec.TxIndex, - BlockHash: dec.BlockHash, - Index: dec.Index, + Address: dec.Address, + Topics: dec.Topics, + Data: dec.Data, + } + } else { + // Try to decode log with previous definition. + var dec LegacyRlpStorageLog + err = rlp.DecodeBytes(blob, &dec) + if err == nil { + *l = LogForStorage{ + Address: dec.Address, + Topics: dec.Topics, + Data: dec.Data, + } } } return err diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/receipt.go b/vendor/github.com/ethereum/go-ethereum/core/types/receipt.go index 3d1fc95aab..72d85a1e82 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/receipt.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/receipt.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "io" + "math/big" "unsafe" "github.com/ethereum/go-ethereum/common" @@ -44,17 +45,24 @@ const ( // Receipt represents the results of a transaction. type Receipt struct { - // Consensus fields + // Consensus fields: These fields are defined by the Yellow Paper PostState []byte `json:"root"` Status uint64 `json:"status"` CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"` - // Implementation fields (don't reorder!) + // Implementation fields: These fields are added by geth when processing a transaction. + // They are stored in the chain database. TxHash common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress common.Address `json:"contractAddress"` GasUsed uint64 `json:"gasUsed" gencodec:"required"` + + // Inclusion information: These fields provide information about the inclusion of the + // transaction corresponding to this receipt. + BlockHash common.Hash `json:"blockHash,omitempty"` + BlockNumber *big.Int `json:"blockNumber,omitempty"` + TransactionIndex uint `json:"transactionIndex"` } type receiptMarshaling struct { @@ -62,6 +70,8 @@ type receiptMarshaling struct { Status hexutil.Uint64 CumulativeGasUsed hexutil.Uint64 GasUsed hexutil.Uint64 + BlockNumber *hexutil.Big + TransactionIndex hexutil.Uint } // receiptRLP is the consensus encoding of a receipt. @@ -72,7 +82,18 @@ type receiptRLP struct { Logs []*Log } +// receiptStorageRLP is the storage encoding of a receipt. type receiptStorageRLP struct { + PostStateOrStatus []byte + CumulativeGasUsed uint64 + TxHash common.Hash + ContractAddress common.Address + Logs []*LogForStorage + GasUsed uint64 +} + +// LegacyReceiptStorageRLP is the previous storage encoding of a receipt including some unnecessary fields. +type LegacyReceiptStorageRLP struct { PostStateOrStatus []byte CumulativeGasUsed uint64 Bloom Bloom @@ -159,7 +180,6 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { enc := &receiptStorageRLP{ PostStateOrStatus: (*Receipt)(r).statusEncoding(), CumulativeGasUsed: r.CumulativeGasUsed, - Bloom: r.Bloom, TxHash: r.TxHash, ContractAddress: r.ContractAddress, Logs: make([]*LogForStorage, len(r.Logs)), @@ -174,19 +194,34 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation // fields of a receipt from an RLP stream. func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { - var dec receiptStorageRLP - if err := s.Decode(&dec); err != nil { + blob, err := s.Raw() + if err != nil { return err } + var dec receiptStorageRLP + if err := rlp.DecodeBytes(blob, &dec); err != nil { + var sdec LegacyReceiptStorageRLP + if err := rlp.DecodeBytes(blob, &sdec); err != nil { + return err + } + dec.PostStateOrStatus = common.CopyBytes(sdec.PostStateOrStatus) + dec.CumulativeGasUsed = sdec.CumulativeGasUsed + dec.TxHash = sdec.TxHash + dec.ContractAddress = sdec.ContractAddress + dec.Logs = sdec.Logs + dec.GasUsed = sdec.GasUsed + } if err := (*Receipt)(r).setStatus(dec.PostStateOrStatus); err != nil { return err } // Assign the consensus fields - r.CumulativeGasUsed, r.Bloom = dec.CumulativeGasUsed, dec.Bloom + r.CumulativeGasUsed = dec.CumulativeGasUsed r.Logs = make([]*Log, len(dec.Logs)) for i, log := range dec.Logs { r.Logs[i] = (*Log)(log) } + + r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) // Assign the implementation fields r.TxHash, r.ContractAddress, r.GasUsed = dec.TxHash, dec.ContractAddress, dec.GasUsed return nil diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/transaction.go b/vendor/github.com/ethereum/go-ethereum/core/types/transaction.go index 7b53cac2c6..ba3d5de91d 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/transaction.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/transaction.go @@ -234,7 +234,7 @@ func (tx *Transaction) AsMessage(s Signer) (Message, error) { } // WithSignature returns a new transaction with the given signature. -// This signature needs to be formatted as described in the yellow paper (v+27). +// This signature needs to be in the [R || S || V] format where V is 0 or 1. func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) { r, s, v, err := signer.SignatureValues(tx, sig) if err != nil { diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/LICENSE b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/LICENSE new file mode 100644 index 0000000000..634e0cb2c3 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2018 Péter Szilágyi. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_fast.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_fast.go new file mode 100644 index 0000000000..5c081493b0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_fast.go @@ -0,0 +1,23 @@ +// Copyright 2018 Péter Szilágyi. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. + +// +build amd64 arm64 + +// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve. +package bn256 + +import "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" + +// G1 is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type G1 = bn256.G1 + +// G2 is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type G2 = bn256.G2 + +// PairingCheck calculates the Optimal Ate pairing for a set of points. +func PairingCheck(a []*G1, b []*G2) bool { + return bn256.PairingCheck(a, b) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_fuzz.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_fuzz.go new file mode 100644 index 0000000000..6aa1421170 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_fuzz.go @@ -0,0 +1,126 @@ +// Copyright 2018 Péter Szilágyi. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. + +// +build gofuzz + +package bn256 + +import ( + "bytes" + "math/big" + + cloudflare "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" + google "github.com/ethereum/go-ethereum/crypto/bn256/google" +) + +// FuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries. +func FuzzAdd(data []byte) int { + // Ensure we have enough data in the first place + if len(data) != 128 { + return 0 + } + // Ensure both libs can parse the first curve point + xc := new(cloudflare.G1) + _, errc := xc.Unmarshal(data[:64]) + + xg := new(google.G1) + _, errg := xg.Unmarshal(data[:64]) + + if (errc == nil) != (errg == nil) { + panic("parse mismatch") + } else if errc != nil { + return 0 + } + // Ensure both libs can parse the second curve point + yc := new(cloudflare.G1) + _, errc = yc.Unmarshal(data[64:]) + + yg := new(google.G1) + _, errg = yg.Unmarshal(data[64:]) + + if (errc == nil) != (errg == nil) { + panic("parse mismatch") + } else if errc != nil { + return 0 + } + // Add the two points and ensure they result in the same output + rc := new(cloudflare.G1) + rc.Add(xc, yc) + + rg := new(google.G1) + rg.Add(xg, yg) + + if !bytes.Equal(rc.Marshal(), rg.Marshal()) { + panic("add mismatch") + } + return 0 +} + +// FuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare +// libraries. +func FuzzMul(data []byte) int { + // Ensure we have enough data in the first place + if len(data) != 96 { + return 0 + } + // Ensure both libs can parse the curve point + pc := new(cloudflare.G1) + _, errc := pc.Unmarshal(data[:64]) + + pg := new(google.G1) + _, errg := pg.Unmarshal(data[:64]) + + if (errc == nil) != (errg == nil) { + panic("parse mismatch") + } else if errc != nil { + return 0 + } + // Add the two points and ensure they result in the same output + rc := new(cloudflare.G1) + rc.ScalarMult(pc, new(big.Int).SetBytes(data[64:])) + + rg := new(google.G1) + rg.ScalarMult(pg, new(big.Int).SetBytes(data[64:])) + + if !bytes.Equal(rc.Marshal(), rg.Marshal()) { + panic("scalar mul mismatch") + } + return 0 +} + +func FuzzPair(data []byte) int { + // Ensure we have enough data in the first place + if len(data) != 192 { + return 0 + } + // Ensure both libs can parse the curve point + pc := new(cloudflare.G1) + _, errc := pc.Unmarshal(data[:64]) + + pg := new(google.G1) + _, errg := pg.Unmarshal(data[:64]) + + if (errc == nil) != (errg == nil) { + panic("parse mismatch") + } else if errc != nil { + return 0 + } + // Ensure both libs can parse the twist point + tc := new(cloudflare.G2) + _, errc = tc.Unmarshal(data[64:]) + + tg := new(google.G2) + _, errg = tg.Unmarshal(data[64:]) + + if (errc == nil) != (errg == nil) { + panic("parse mismatch") + } else if errc != nil { + return 0 + } + // Pair the two points and ensure thet result in the same output + if cloudflare.PairingCheck([]*cloudflare.G1{pc}, []*cloudflare.G2{tc}) != google.PairingCheck([]*google.G1{pg}, []*google.G2{tg}) { + panic("pair mismatch") + } + return 0 +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_slow.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_slow.go new file mode 100644 index 0000000000..47df49d417 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_slow.go @@ -0,0 +1,23 @@ +// Copyright 2018 Péter Szilágyi. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. + +// +build !amd64,!arm64 + +// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve. +package bn256 + +import "github.com/ethereum/go-ethereum/crypto/bn256/google" + +// G1 is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type G1 = bn256.G1 + +// G2 is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type G2 = bn256.G2 + +// PairingCheck calculates the Optimal Ate pairing for a set of points. +func PairingCheck(a []*G1, b []*G2) bool { + return bn256.PairingCheck(a, b) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/LICENSE b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/LICENSE similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/LICENSE rename to vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/LICENSE diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256.go new file mode 100644 index 0000000000..c6ea2d07e0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256.go @@ -0,0 +1,481 @@ +// Package bn256 implements a particular bilinear group at the 128-bit security +// level. +// +// Bilinear groups are the basis of many of the new cryptographic protocols that +// have been proposed over the past decade. They consist of a triplet of groups +// (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ (where gₓ +// is a generator of the respective group). That function is called a pairing +// function. +// +// This package specifically implements the Optimal Ate pairing over a 256-bit +// Barreto-Naehrig curve as described in +// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible +// with the implementation described in that paper. +package bn256 + +import ( + "crypto/rand" + "errors" + "io" + "math/big" +) + +func randomK(r io.Reader) (k *big.Int, err error) { + for { + k, err = rand.Int(r, Order) + if k.Sign() > 0 || err != nil { + return + } + } +} + +// G1 is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type G1 struct { + p *curvePoint +} + +// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r. +func RandomG1(r io.Reader) (*big.Int, *G1, error) { + k, err := randomK(r) + if err != nil { + return nil, nil, err + } + + return k, new(G1).ScalarBaseMult(k), nil +} + +func (g *G1) String() string { + return "bn256.G1" + g.p.String() +} + +// ScalarBaseMult sets e to g*k where g is the generator of the group and then +// returns e. +func (e *G1) ScalarBaseMult(k *big.Int) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Mul(curveGen, k) + return e +} + +// ScalarMult sets e to a*k and then returns e. +func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Mul(a.p, k) + return e +} + +// Add sets e to a+b and then returns e. +func (e *G1) Add(a, b *G1) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Add(a.p, b.p) + return e +} + +// Neg sets e to -a and then returns e. +func (e *G1) Neg(a *G1) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Neg(a.p) + return e +} + +// Set sets e to a and then returns e. +func (e *G1) Set(a *G1) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Set(a.p) + return e +} + +// Marshal converts e to a byte slice. +func (e *G1) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + e.p.MakeAffine() + ret := make([]byte, numBytes*2) + if e.p.IsInfinity() { + return ret + } + temp := &gfP{} + + montDecode(temp, &e.p.x) + temp.Marshal(ret) + montDecode(temp, &e.p.y) + temp.Marshal(ret[numBytes:]) + + return ret +} + +// Unmarshal sets e to the result of converting the output of Marshal back into +// a group element and then returns e. +func (e *G1) Unmarshal(m []byte) ([]byte, error) { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + if len(m) < 2*numBytes { + return nil, errors.New("bn256: not enough data") + } + // Unmarshal the points and check their caps + if e.p == nil { + e.p = &curvePoint{} + } else { + e.p.x, e.p.y = gfP{0}, gfP{0} + } + var err error + if err = e.p.x.Unmarshal(m); err != nil { + return nil, err + } + if err = e.p.y.Unmarshal(m[numBytes:]); err != nil { + return nil, err + } + // Encode into Montgomery form and ensure it's on the curve + montEncode(&e.p.x, &e.p.x) + montEncode(&e.p.y, &e.p.y) + + zero := gfP{0} + if e.p.x == zero && e.p.y == zero { + // This is the point at infinity. + e.p.y = *newGFp(1) + e.p.z = gfP{0} + e.p.t = gfP{0} + } else { + e.p.z = *newGFp(1) + e.p.t = *newGFp(1) + + if !e.p.IsOnCurve() { + return nil, errors.New("bn256: malformed point") + } + } + return m[2*numBytes:], nil +} + +// G2 is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type G2 struct { + p *twistPoint +} + +// RandomG2 returns x and g₂ˣ where x is a random, non-zero number read from r. +func RandomG2(r io.Reader) (*big.Int, *G2, error) { + k, err := randomK(r) + if err != nil { + return nil, nil, err + } + + return k, new(G2).ScalarBaseMult(k), nil +} + +func (e *G2) String() string { + return "bn256.G2" + e.p.String() +} + +// ScalarBaseMult sets e to g*k where g is the generator of the group and then +// returns out. +func (e *G2) ScalarBaseMult(k *big.Int) *G2 { + if e.p == nil { + e.p = &twistPoint{} + } + e.p.Mul(twistGen, k) + return e +} + +// ScalarMult sets e to a*k and then returns e. +func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { + if e.p == nil { + e.p = &twistPoint{} + } + e.p.Mul(a.p, k) + return e +} + +// Add sets e to a+b and then returns e. +func (e *G2) Add(a, b *G2) *G2 { + if e.p == nil { + e.p = &twistPoint{} + } + e.p.Add(a.p, b.p) + return e +} + +// Neg sets e to -a and then returns e. +func (e *G2) Neg(a *G2) *G2 { + if e.p == nil { + e.p = &twistPoint{} + } + e.p.Neg(a.p) + return e +} + +// Set sets e to a and then returns e. +func (e *G2) Set(a *G2) *G2 { + if e.p == nil { + e.p = &twistPoint{} + } + e.p.Set(a.p) + return e +} + +// Marshal converts e into a byte slice. +func (e *G2) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if e.p == nil { + e.p = &twistPoint{} + } + + e.p.MakeAffine() + ret := make([]byte, numBytes*4) + if e.p.IsInfinity() { + return ret + } + temp := &gfP{} + + montDecode(temp, &e.p.x.x) + temp.Marshal(ret) + montDecode(temp, &e.p.x.y) + temp.Marshal(ret[numBytes:]) + montDecode(temp, &e.p.y.x) + temp.Marshal(ret[2*numBytes:]) + montDecode(temp, &e.p.y.y) + temp.Marshal(ret[3*numBytes:]) + + return ret +} + +// Unmarshal sets e to the result of converting the output of Marshal back into +// a group element and then returns e. +func (e *G2) Unmarshal(m []byte) ([]byte, error) { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + if len(m) < 4*numBytes { + return nil, errors.New("bn256: not enough data") + } + // Unmarshal the points and check their caps + if e.p == nil { + e.p = &twistPoint{} + } + var err error + if err = e.p.x.x.Unmarshal(m); err != nil { + return nil, err + } + if err = e.p.x.y.Unmarshal(m[numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.x.Unmarshal(m[2*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.y.Unmarshal(m[3*numBytes:]); err != nil { + return nil, err + } + // Encode into Montgomery form and ensure it's on the curve + montEncode(&e.p.x.x, &e.p.x.x) + montEncode(&e.p.x.y, &e.p.x.y) + montEncode(&e.p.y.x, &e.p.y.x) + montEncode(&e.p.y.y, &e.p.y.y) + + if e.p.x.IsZero() && e.p.y.IsZero() { + // This is the point at infinity. + e.p.y.SetOne() + e.p.z.SetZero() + e.p.t.SetZero() + } else { + e.p.z.SetOne() + e.p.t.SetOne() + + if !e.p.IsOnCurve() { + return nil, errors.New("bn256: malformed point") + } + } + return m[4*numBytes:], nil +} + +// GT is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type GT struct { + p *gfP12 +} + +// Pair calculates an Optimal Ate pairing. +func Pair(g1 *G1, g2 *G2) *GT { + return >{optimalAte(g2.p, g1.p)} +} + +// PairingCheck calculates the Optimal Ate pairing for a set of points. +func PairingCheck(a []*G1, b []*G2) bool { + acc := new(gfP12) + acc.SetOne() + + for i := 0; i < len(a); i++ { + if a[i].p.IsInfinity() || b[i].p.IsInfinity() { + continue + } + acc.Mul(acc, miller(b[i].p, a[i].p)) + } + return finalExponentiation(acc).IsOne() +} + +// Miller applies Miller's algorithm, which is a bilinear function from the +// source groups to F_p^12. Miller(g1, g2).Finalize() is equivalent to Pair(g1, +// g2). +func Miller(g1 *G1, g2 *G2) *GT { + return >{miller(g2.p, g1.p)} +} + +func (g *GT) String() string { + return "bn256.GT" + g.p.String() +} + +// ScalarMult sets e to a*k and then returns e. +func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { + if e.p == nil { + e.p = &gfP12{} + } + e.p.Exp(a.p, k) + return e +} + +// Add sets e to a+b and then returns e. +func (e *GT) Add(a, b *GT) *GT { + if e.p == nil { + e.p = &gfP12{} + } + e.p.Mul(a.p, b.p) + return e +} + +// Neg sets e to -a and then returns e. +func (e *GT) Neg(a *GT) *GT { + if e.p == nil { + e.p = &gfP12{} + } + e.p.Conjugate(a.p) + return e +} + +// Set sets e to a and then returns e. +func (e *GT) Set(a *GT) *GT { + if e.p == nil { + e.p = &gfP12{} + } + e.p.Set(a.p) + return e +} + +// Finalize is a linear function from F_p^12 to GT. +func (e *GT) Finalize() *GT { + ret := finalExponentiation(e.p) + e.p.Set(ret) + return e +} + +// Marshal converts e into a byte slice. +func (e *GT) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + ret := make([]byte, numBytes*12) + temp := &gfP{} + + montDecode(temp, &e.p.x.x.x) + temp.Marshal(ret) + montDecode(temp, &e.p.x.x.y) + temp.Marshal(ret[numBytes:]) + montDecode(temp, &e.p.x.y.x) + temp.Marshal(ret[2*numBytes:]) + montDecode(temp, &e.p.x.y.y) + temp.Marshal(ret[3*numBytes:]) + montDecode(temp, &e.p.x.z.x) + temp.Marshal(ret[4*numBytes:]) + montDecode(temp, &e.p.x.z.y) + temp.Marshal(ret[5*numBytes:]) + montDecode(temp, &e.p.y.x.x) + temp.Marshal(ret[6*numBytes:]) + montDecode(temp, &e.p.y.x.y) + temp.Marshal(ret[7*numBytes:]) + montDecode(temp, &e.p.y.y.x) + temp.Marshal(ret[8*numBytes:]) + montDecode(temp, &e.p.y.y.y) + temp.Marshal(ret[9*numBytes:]) + montDecode(temp, &e.p.y.z.x) + temp.Marshal(ret[10*numBytes:]) + montDecode(temp, &e.p.y.z.y) + temp.Marshal(ret[11*numBytes:]) + + return ret +} + +// Unmarshal sets e to the result of converting the output of Marshal back into +// a group element and then returns e. +func (e *GT) Unmarshal(m []byte) ([]byte, error) { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if len(m) < 12*numBytes { + return nil, errors.New("bn256: not enough data") + } + + if e.p == nil { + e.p = &gfP12{} + } + + var err error + if err = e.p.x.x.x.Unmarshal(m); err != nil { + return nil, err + } + if err = e.p.x.x.y.Unmarshal(m[numBytes:]); err != nil { + return nil, err + } + if err = e.p.x.y.x.Unmarshal(m[2*numBytes:]); err != nil { + return nil, err + } + if err = e.p.x.y.y.Unmarshal(m[3*numBytes:]); err != nil { + return nil, err + } + if err = e.p.x.z.x.Unmarshal(m[4*numBytes:]); err != nil { + return nil, err + } + if err = e.p.x.z.y.Unmarshal(m[5*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.x.x.Unmarshal(m[6*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.x.y.Unmarshal(m[7*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.y.x.Unmarshal(m[8*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.y.y.Unmarshal(m[9*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.z.x.Unmarshal(m[10*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.z.y.Unmarshal(m[11*numBytes:]); err != nil { + return nil, err + } + montEncode(&e.p.x.x.x, &e.p.x.x.x) + montEncode(&e.p.x.x.y, &e.p.x.x.y) + montEncode(&e.p.x.y.x, &e.p.x.y.x) + montEncode(&e.p.x.y.y, &e.p.x.y.y) + montEncode(&e.p.x.z.x, &e.p.x.z.x) + montEncode(&e.p.x.z.y, &e.p.x.z.y) + montEncode(&e.p.y.x.x, &e.p.y.x.x) + montEncode(&e.p.y.x.y, &e.p.y.x.y) + montEncode(&e.p.y.y.x, &e.p.y.y.x) + montEncode(&e.p.y.y.y, &e.p.y.y.y) + montEncode(&e.p.y.z.x, &e.p.y.z.x) + montEncode(&e.p.y.z.y, &e.p.y.z.y) + + return m[12*numBytes:], nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256_test.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256_test.go new file mode 100644 index 0000000000..0c8016d86c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256_test.go @@ -0,0 +1,116 @@ +package bn256 + +import ( + "bytes" + "crypto/rand" + "testing" +) + +func TestG1Marshal(t *testing.T) { + _, Ga, err := RandomG1(rand.Reader) + if err != nil { + t.Fatal(err) + } + ma := Ga.Marshal() + + Gb := new(G1) + _, err = Gb.Unmarshal(ma) + if err != nil { + t.Fatal(err) + } + mb := Gb.Marshal() + + if !bytes.Equal(ma, mb) { + t.Fatal("bytes are different") + } +} + +func TestG2Marshal(t *testing.T) { + _, Ga, err := RandomG2(rand.Reader) + if err != nil { + t.Fatal(err) + } + ma := Ga.Marshal() + + Gb := new(G2) + _, err = Gb.Unmarshal(ma) + if err != nil { + t.Fatal(err) + } + mb := Gb.Marshal() + + if !bytes.Equal(ma, mb) { + t.Fatal("bytes are different") + } +} + +func TestBilinearity(t *testing.T) { + for i := 0; i < 2; i++ { + a, p1, _ := RandomG1(rand.Reader) + b, p2, _ := RandomG2(rand.Reader) + e1 := Pair(p1, p2) + + e2 := Pair(&G1{curveGen}, &G2{twistGen}) + e2.ScalarMult(e2, a) + e2.ScalarMult(e2, b) + + if *e1.p != *e2.p { + t.Fatalf("bad pairing result: %s", e1) + } + } +} + +func TestTripartiteDiffieHellman(t *testing.T) { + a, _ := rand.Int(rand.Reader, Order) + b, _ := rand.Int(rand.Reader, Order) + c, _ := rand.Int(rand.Reader, Order) + + pa, pb, pc := new(G1), new(G1), new(G1) + qa, qb, qc := new(G2), new(G2), new(G2) + + pa.Unmarshal(new(G1).ScalarBaseMult(a).Marshal()) + qa.Unmarshal(new(G2).ScalarBaseMult(a).Marshal()) + pb.Unmarshal(new(G1).ScalarBaseMult(b).Marshal()) + qb.Unmarshal(new(G2).ScalarBaseMult(b).Marshal()) + pc.Unmarshal(new(G1).ScalarBaseMult(c).Marshal()) + qc.Unmarshal(new(G2).ScalarBaseMult(c).Marshal()) + + k1 := Pair(pb, qc) + k1.ScalarMult(k1, a) + k1Bytes := k1.Marshal() + + k2 := Pair(pc, qa) + k2.ScalarMult(k2, b) + k2Bytes := k2.Marshal() + + k3 := Pair(pa, qb) + k3.ScalarMult(k3, c) + k3Bytes := k3.Marshal() + + if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) { + t.Errorf("keys didn't agree") + } +} + +func BenchmarkG1(b *testing.B) { + x, _ := rand.Int(rand.Reader, Order) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + new(G1).ScalarBaseMult(x) + } +} + +func BenchmarkG2(b *testing.B) { + x, _ := rand.Int(rand.Reader, Order) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + new(G2).ScalarBaseMult(x) + } +} +func BenchmarkPairing(b *testing.B) { + for i := 0; i < b.N; i++ { + Pair(&G1{curveGen}, &G2{twistGen}) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/constants.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/constants.go new file mode 100644 index 0000000000..5122aae64f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/constants.go @@ -0,0 +1,59 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +import ( + "math/big" +) + +func bigFromBase10(s string) *big.Int { + n, _ := new(big.Int).SetString(s, 10) + return n +} + +// u is the BN parameter that determines the prime: 1868033³. +var u = bigFromBase10("4965661367192848881") + +// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1. +var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617") + +// P is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1. +var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583") + +// p2 is p, represented as little-endian 64-bit words. +var p2 = [4]uint64{0x3c208c16d87cfd47, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029} + +// np is the negative inverse of p, mod 2^256. +var np = [4]uint64{0x87d20782e4866389, 0x9ede7d651eca6ac9, 0xd8afcbd01833da80, 0xf57a22b791888c6b} + +// rN1 is R^-1 where R = 2^256 mod p. +var rN1 = &gfP{0xed84884a014afa37, 0xeb2022850278edf8, 0xcf63e9cfb74492d9, 0x2e67157159e5c639} + +// r2 is R^2 where R = 2^256 mod p. +var r2 = &gfP{0xf32cfc5b538afa89, 0xb5e71911d44501fb, 0x47ab1eff0a417ff6, 0x06d89f71cab8351f} + +// r3 is R^3 where R = 2^256 mod p. +var r3 = &gfP{0xb1cd6dafda1530df, 0x62f210e6a7283db6, 0xef7f0b0c0ada0afb, 0x20fd6e902d592544} + +// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9. +var xiToPMinus1Over6 = &gfP2{gfP{0xa222ae234c492d72, 0xd00f02a4565de15b, 0xdc2ff3a253dfc926, 0x10a75716b3899551}, gfP{0xaf9ba69633144907, 0xca6b1d7387afb78a, 0x11bded5ef08a2087, 0x02f34d751a1f3a7c}} + +// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9. +var xiToPMinus1Over3 = &gfP2{gfP{0x6e849f1ea0aa4757, 0xaa1c7b6d89f89141, 0xb6e713cdfae0ca3a, 0x26694fbb4e82ebc3}, gfP{0xb5773b104563ab30, 0x347f91c8a9aa6454, 0x7a007127242e0991, 0x1956bcd8118214ec}} + +// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9. +var xiToPMinus1Over2 = &gfP2{gfP{0xa1d77ce45ffe77c7, 0x07affd117826d1db, 0x6d16bd27bb7edc6b, 0x2c87200285defecc}, gfP{0xe4bbdd0c2936b629, 0xbb30f162e133bacb, 0x31a9d1b6f9645366, 0x253570bea500f8dd}} + +// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9. +var xiToPSquaredMinus1Over3 = &gfP{0x3350c88e13e80b9c, 0x7dce557cdb5e56b9, 0x6001b4b8b615564a, 0x2682e617020217e0} + +// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p). +var xiTo2PSquaredMinus2Over3 = &gfP{0x71930c11d782e155, 0xa6bb947cffbe3323, 0xaa303344d4741444, 0x2c3b3f0d26594943} + +// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p). +var xiToPSquaredMinus1Over6 = &gfP{0xca8d800500fa1bf2, 0xf0c5d61468b39769, 0x0e201271ad0d4418, 0x04290f65bad856e6} + +// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9. +var xiTo2PMinus2Over3 = &gfP2{gfP{0x5dddfd154bd8c949, 0x62cb29a5a4445b60, 0x37bc870a0c7dd2b9, 0x24830a9d3171f0fd}, gfP{0x7361d77f843abe92, 0xa5bb2bd3273411fb, 0x9c941f314b3e2399, 0x15df9cddbb9fd3ec}} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/curve.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/curve.go new file mode 100644 index 0000000000..18e9b38f3f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/curve.go @@ -0,0 +1,238 @@ +package bn256 + +import ( + "math/big" +) + +// curvePoint implements the elliptic curve y²=x³+3. Points are kept in Jacobian +// form and t=z² when valid. G₁ is the set of points of this curve on GF(p). +type curvePoint struct { + x, y, z, t gfP +} + +var curveB = newGFp(3) + +// curveGen is the generator of G₁. +var curveGen = &curvePoint{ + x: *newGFp(1), + y: *newGFp(2), + z: *newGFp(1), + t: *newGFp(1), +} + +func (c *curvePoint) String() string { + c.MakeAffine() + x, y := &gfP{}, &gfP{} + montDecode(x, &c.x) + montDecode(y, &c.y) + return "(" + x.String() + ", " + y.String() + ")" +} + +func (c *curvePoint) Set(a *curvePoint) { + c.x.Set(&a.x) + c.y.Set(&a.y) + c.z.Set(&a.z) + c.t.Set(&a.t) +} + +// IsOnCurve returns true iff c is on the curve. +func (c *curvePoint) IsOnCurve() bool { + c.MakeAffine() + if c.IsInfinity() { + return true + } + + y2, x3 := &gfP{}, &gfP{} + gfpMul(y2, &c.y, &c.y) + gfpMul(x3, &c.x, &c.x) + gfpMul(x3, x3, &c.x) + gfpAdd(x3, x3, curveB) + + return *y2 == *x3 +} + +func (c *curvePoint) SetInfinity() { + c.x = gfP{0} + c.y = *newGFp(1) + c.z = gfP{0} + c.t = gfP{0} +} + +func (c *curvePoint) IsInfinity() bool { + return c.z == gfP{0} +} + +func (c *curvePoint) Add(a, b *curvePoint) { + if a.IsInfinity() { + c.Set(b) + return + } + if b.IsInfinity() { + c.Set(a) + return + } + + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 + + // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] + // by [u1:s1:z1·z2] and [u2:s2:z1·z2] + // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³ + z12, z22 := &gfP{}, &gfP{} + gfpMul(z12, &a.z, &a.z) + gfpMul(z22, &b.z, &b.z) + + u1, u2 := &gfP{}, &gfP{} + gfpMul(u1, &a.x, z22) + gfpMul(u2, &b.x, z12) + + t, s1 := &gfP{}, &gfP{} + gfpMul(t, &b.z, z22) + gfpMul(s1, &a.y, t) + + s2 := &gfP{} + gfpMul(t, &a.z, z12) + gfpMul(s2, &b.y, t) + + // Compute x = (2h)²(s²-u1-u2) + // where s = (s2-s1)/(u2-u1) is the slope of the line through + // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. + // This is also: + // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1) + // = r² - j - 2v + // with the notations below. + h := &gfP{} + gfpSub(h, u2, u1) + xEqual := *h == gfP{0} + + gfpAdd(t, h, h) + // i = 4h² + i := &gfP{} + gfpMul(i, t, t) + // j = 4h³ + j := &gfP{} + gfpMul(j, h, i) + + gfpSub(t, s2, s1) + yEqual := *t == gfP{0} + if xEqual && yEqual { + c.Double(a) + return + } + r := &gfP{} + gfpAdd(r, t, t) + + v := &gfP{} + gfpMul(v, u1, i) + + // t4 = 4(s2-s1)² + t4, t6 := &gfP{}, &gfP{} + gfpMul(t4, r, r) + gfpAdd(t, v, v) + gfpSub(t6, t4, j) + + gfpSub(&c.x, t6, t) + + // Set y = -(2h)³(s1 + s*(x/4h²-u1)) + // This is also + // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j + gfpSub(t, v, &c.x) // t7 + gfpMul(t4, s1, j) // t8 + gfpAdd(t6, t4, t4) // t9 + gfpMul(t4, r, t) // t10 + gfpSub(&c.y, t4, t6) + + // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2 + gfpAdd(t, &a.z, &b.z) // t11 + gfpMul(t4, t, t) // t12 + gfpSub(t, t4, z12) // t13 + gfpSub(t4, t, z22) // t14 + gfpMul(&c.z, t4, h) +} + +func (c *curvePoint) Double(a *curvePoint) { + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 + A, B, C := &gfP{}, &gfP{}, &gfP{} + gfpMul(A, &a.x, &a.x) + gfpMul(B, &a.y, &a.y) + gfpMul(C, B, B) + + t, t2 := &gfP{}, &gfP{} + gfpAdd(t, &a.x, B) + gfpMul(t2, t, t) + gfpSub(t, t2, A) + gfpSub(t2, t, C) + + d, e, f := &gfP{}, &gfP{}, &gfP{} + gfpAdd(d, t2, t2) + gfpAdd(t, A, A) + gfpAdd(e, t, A) + gfpMul(f, e, e) + + gfpAdd(t, d, d) + gfpSub(&c.x, f, t) + + gfpAdd(t, C, C) + gfpAdd(t2, t, t) + gfpAdd(t, t2, t2) + gfpSub(&c.y, d, &c.x) + gfpMul(t2, e, &c.y) + gfpSub(&c.y, t2, t) + + gfpMul(t, &a.y, &a.z) + gfpAdd(&c.z, t, t) +} + +func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int) { + precomp := [1 << 2]*curvePoint{nil, {}, {}, {}} + precomp[1].Set(a) + precomp[2].Set(a) + gfpMul(&precomp[2].x, &precomp[2].x, xiTo2PSquaredMinus2Over3) + precomp[3].Add(precomp[1], precomp[2]) + + multiScalar := curveLattice.Multi(scalar) + + sum := &curvePoint{} + sum.SetInfinity() + t := &curvePoint{} + + for i := len(multiScalar) - 1; i >= 0; i-- { + t.Double(sum) + if multiScalar[i] == 0 { + sum.Set(t) + } else { + sum.Add(t, precomp[multiScalar[i]]) + } + } + c.Set(sum) +} + +func (c *curvePoint) MakeAffine() { + if c.z == *newGFp(1) { + return + } else if c.z == *newGFp(0) { + c.x = gfP{0} + c.y = *newGFp(1) + c.t = gfP{0} + return + } + + zInv := &gfP{} + zInv.Invert(&c.z) + + t, zInv2 := &gfP{}, &gfP{} + gfpMul(t, &c.y, zInv) + gfpMul(zInv2, zInv, zInv) + + gfpMul(&c.x, &c.x, zInv2) + gfpMul(&c.y, t, zInv2) + + c.z = *newGFp(1) + c.t = *newGFp(1) +} + +func (c *curvePoint) Neg(a *curvePoint) { + c.x.Set(&a.x) + gfpNeg(&c.y, &a.y) + c.z.Set(&a.z) + c.t = gfP{0} +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/example_test.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/example_test.go new file mode 100644 index 0000000000..6c285995cb --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/example_test.go @@ -0,0 +1,51 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +import ( + "crypto/rand" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestExamplePair(t *testing.T) { + // This implements the tripartite Diffie-Hellman algorithm from "A One + // Round Protocol for Tripartite Diffie-Hellman", A. Joux. + // http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf + + // Each of three parties, a, b and c, generate a private value. + a, _ := rand.Int(rand.Reader, Order) + b, _ := rand.Int(rand.Reader, Order) + c, _ := rand.Int(rand.Reader, Order) + + // Then each party calculates g₁ and g₂ times their private value. + pa := new(G1).ScalarBaseMult(a) + qa := new(G2).ScalarBaseMult(a) + + pb := new(G1).ScalarBaseMult(b) + qb := new(G2).ScalarBaseMult(b) + + pc := new(G1).ScalarBaseMult(c) + qc := new(G2).ScalarBaseMult(c) + + // Now each party exchanges its public values with the other two and + // all parties can calculate the shared key. + k1 := Pair(pb, qc) + k1.ScalarMult(k1, a) + + k2 := Pair(pc, qa) + k2.ScalarMult(k2, b) + + k3 := Pair(pa, qb) + k3.ScalarMult(k3, c) + + // k1, k2 and k3 will all be equal. + + require.Equal(t, k1, k2) + require.Equal(t, k1, k3) + + require.Equal(t, len(np), 4) //Avoid gometalinter varcheck err on np +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp.go new file mode 100644 index 0000000000..e8e84e7b3b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp.go @@ -0,0 +1,81 @@ +package bn256 + +import ( + "errors" + "fmt" +) + +type gfP [4]uint64 + +func newGFp(x int64) (out *gfP) { + if x >= 0 { + out = &gfP{uint64(x)} + } else { + out = &gfP{uint64(-x)} + gfpNeg(out, out) + } + + montEncode(out, out) + return out +} + +func (e *gfP) String() string { + return fmt.Sprintf("%16.16x%16.16x%16.16x%16.16x", e[3], e[2], e[1], e[0]) +} + +func (e *gfP) Set(f *gfP) { + e[0] = f[0] + e[1] = f[1] + e[2] = f[2] + e[3] = f[3] +} + +func (e *gfP) Invert(f *gfP) { + bits := [4]uint64{0x3c208c16d87cfd45, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029} + + sum, power := &gfP{}, &gfP{} + sum.Set(rN1) + power.Set(f) + + for word := 0; word < 4; word++ { + for bit := uint(0); bit < 64; bit++ { + if (bits[word]>>bit)&1 == 1 { + gfpMul(sum, sum, power) + } + gfpMul(power, power, power) + } + } + + gfpMul(sum, sum, r3) + e.Set(sum) +} + +func (e *gfP) Marshal(out []byte) { + for w := uint(0); w < 4; w++ { + for b := uint(0); b < 8; b++ { + out[8*w+b] = byte(e[3-w] >> (56 - 8*b)) + } + } +} + +func (e *gfP) Unmarshal(in []byte) error { + // Unmarshal the bytes into little endian form + for w := uint(0); w < 4; w++ { + for b := uint(0); b < 8; b++ { + e[3-w] += uint64(in[8*w+b]) << (56 - 8*b) + } + } + // Ensure the point respects the curve modulus + for i := 3; i >= 0; i-- { + if e[i] < p2[i] { + return nil + } + if e[i] > p2[i] { + return errors.New("bn256: coordinate exceeds modulus") + } + } + return errors.New("bn256: coordinate equals modulus") +} + +func montEncode(c, a *gfP) { gfpMul(c, a, r2) } +func montDecode(c, a *gfP) { gfpMul(c, a, &gfP{1}) } diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp12.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp12.go new file mode 100644 index 0000000000..93fb368a7b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp12.go @@ -0,0 +1,160 @@ +package bn256 + +// For details of the algorithms used, see "Multiplication and Squaring on +// Pairing-Friendly Fields, Devegili et al. +// http://eprint.iacr.org/2006/471.pdf. + +import ( + "math/big" +) + +// gfP12 implements the field of size p¹² as a quadratic extension of gfP6 +// where ω²=τ. +type gfP12 struct { + x, y gfP6 // value is xω + y +} + +func (e *gfP12) String() string { + return "(" + e.x.String() + "," + e.y.String() + ")" +} + +func (e *gfP12) Set(a *gfP12) *gfP12 { + e.x.Set(&a.x) + e.y.Set(&a.y) + return e +} + +func (e *gfP12) SetZero() *gfP12 { + e.x.SetZero() + e.y.SetZero() + return e +} + +func (e *gfP12) SetOne() *gfP12 { + e.x.SetZero() + e.y.SetOne() + return e +} + +func (e *gfP12) IsZero() bool { + return e.x.IsZero() && e.y.IsZero() +} + +func (e *gfP12) IsOne() bool { + return e.x.IsZero() && e.y.IsOne() +} + +func (e *gfP12) Conjugate(a *gfP12) *gfP12 { + e.x.Neg(&a.x) + e.y.Set(&a.y) + return e +} + +func (e *gfP12) Neg(a *gfP12) *gfP12 { + e.x.Neg(&a.x) + e.y.Neg(&a.y) + return e +} + +// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p +func (e *gfP12) Frobenius(a *gfP12) *gfP12 { + e.x.Frobenius(&a.x) + e.y.Frobenius(&a.y) + e.x.MulScalar(&e.x, xiToPMinus1Over6) + return e +} + +// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² +func (e *gfP12) FrobeniusP2(a *gfP12) *gfP12 { + e.x.FrobeniusP2(&a.x) + e.x.MulGFP(&e.x, xiToPSquaredMinus1Over6) + e.y.FrobeniusP2(&a.y) + return e +} + +func (e *gfP12) FrobeniusP4(a *gfP12) *gfP12 { + e.x.FrobeniusP4(&a.x) + e.x.MulGFP(&e.x, xiToPSquaredMinus1Over3) + e.y.FrobeniusP4(&a.y) + return e +} + +func (e *gfP12) Add(a, b *gfP12) *gfP12 { + e.x.Add(&a.x, &b.x) + e.y.Add(&a.y, &b.y) + return e +} + +func (e *gfP12) Sub(a, b *gfP12) *gfP12 { + e.x.Sub(&a.x, &b.x) + e.y.Sub(&a.y, &b.y) + return e +} + +func (e *gfP12) Mul(a, b *gfP12) *gfP12 { + tx := (&gfP6{}).Mul(&a.x, &b.y) + t := (&gfP6{}).Mul(&b.x, &a.y) + tx.Add(tx, t) + + ty := (&gfP6{}).Mul(&a.y, &b.y) + t.Mul(&a.x, &b.x).MulTau(t) + + e.x.Set(tx) + e.y.Add(ty, t) + return e +} + +func (e *gfP12) MulScalar(a *gfP12, b *gfP6) *gfP12 { + e.x.Mul(&e.x, b) + e.y.Mul(&e.y, b) + return e +} + +func (c *gfP12) Exp(a *gfP12, power *big.Int) *gfP12 { + sum := (&gfP12{}).SetOne() + t := &gfP12{} + + for i := power.BitLen() - 1; i >= 0; i-- { + t.Square(sum) + if power.Bit(i) != 0 { + sum.Mul(t, a) + } else { + sum.Set(t) + } + } + + c.Set(sum) + return c +} + +func (e *gfP12) Square(a *gfP12) *gfP12 { + // Complex squaring algorithm + v0 := (&gfP6{}).Mul(&a.x, &a.y) + + t := (&gfP6{}).MulTau(&a.x) + t.Add(&a.y, t) + ty := (&gfP6{}).Add(&a.x, &a.y) + ty.Mul(ty, t).Sub(ty, v0) + t.MulTau(v0) + ty.Sub(ty, t) + + e.x.Add(v0, v0) + e.y.Set(ty) + return e +} + +func (e *gfP12) Invert(a *gfP12) *gfP12 { + // See "Implementing cryptographic pairings", M. Scott, section 3.2. + // ftp://136.206.11.249/pub/crypto/pairings.pdf + t1, t2 := &gfP6{}, &gfP6{} + + t1.Square(&a.x) + t2.Square(&a.y) + t1.MulTau(t1).Sub(t2, t1) + t2.Invert(t1) + + e.x.Neg(&a.x) + e.y.Set(&a.y) + e.MulScalar(e, t2) + return e +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp2.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp2.go new file mode 100644 index 0000000000..90a89e8b47 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp2.go @@ -0,0 +1,156 @@ +package bn256 + +// For details of the algorithms used, see "Multiplication and Squaring on +// Pairing-Friendly Fields, Devegili et al. +// http://eprint.iacr.org/2006/471.pdf. + +// gfP2 implements a field of size p² as a quadratic extension of the base field +// where i²=-1. +type gfP2 struct { + x, y gfP // value is xi+y. +} + +func gfP2Decode(in *gfP2) *gfP2 { + out := &gfP2{} + montDecode(&out.x, &in.x) + montDecode(&out.y, &in.y) + return out +} + +func (e *gfP2) String() string { + return "(" + e.x.String() + ", " + e.y.String() + ")" +} + +func (e *gfP2) Set(a *gfP2) *gfP2 { + e.x.Set(&a.x) + e.y.Set(&a.y) + return e +} + +func (e *gfP2) SetZero() *gfP2 { + e.x = gfP{0} + e.y = gfP{0} + return e +} + +func (e *gfP2) SetOne() *gfP2 { + e.x = gfP{0} + e.y = *newGFp(1) + return e +} + +func (e *gfP2) IsZero() bool { + zero := gfP{0} + return e.x == zero && e.y == zero +} + +func (e *gfP2) IsOne() bool { + zero, one := gfP{0}, *newGFp(1) + return e.x == zero && e.y == one +} + +func (e *gfP2) Conjugate(a *gfP2) *gfP2 { + e.y.Set(&a.y) + gfpNeg(&e.x, &a.x) + return e +} + +func (e *gfP2) Neg(a *gfP2) *gfP2 { + gfpNeg(&e.x, &a.x) + gfpNeg(&e.y, &a.y) + return e +} + +func (e *gfP2) Add(a, b *gfP2) *gfP2 { + gfpAdd(&e.x, &a.x, &b.x) + gfpAdd(&e.y, &a.y, &b.y) + return e +} + +func (e *gfP2) Sub(a, b *gfP2) *gfP2 { + gfpSub(&e.x, &a.x, &b.x) + gfpSub(&e.y, &a.y, &b.y) + return e +} + +// See "Multiplication and Squaring in Pairing-Friendly Fields", +// http://eprint.iacr.org/2006/471.pdf +func (e *gfP2) Mul(a, b *gfP2) *gfP2 { + tx, t := &gfP{}, &gfP{} + gfpMul(tx, &a.x, &b.y) + gfpMul(t, &b.x, &a.y) + gfpAdd(tx, tx, t) + + ty := &gfP{} + gfpMul(ty, &a.y, &b.y) + gfpMul(t, &a.x, &b.x) + gfpSub(ty, ty, t) + + e.x.Set(tx) + e.y.Set(ty) + return e +} + +func (e *gfP2) MulScalar(a *gfP2, b *gfP) *gfP2 { + gfpMul(&e.x, &a.x, b) + gfpMul(&e.y, &a.y, b) + return e +} + +// MulXi sets e=ξa where ξ=i+9 and then returns e. +func (e *gfP2) MulXi(a *gfP2) *gfP2 { + // (xi+y)(i+9) = (9x+y)i+(9y-x) + tx := &gfP{} + gfpAdd(tx, &a.x, &a.x) + gfpAdd(tx, tx, tx) + gfpAdd(tx, tx, tx) + gfpAdd(tx, tx, &a.x) + + gfpAdd(tx, tx, &a.y) + + ty := &gfP{} + gfpAdd(ty, &a.y, &a.y) + gfpAdd(ty, ty, ty) + gfpAdd(ty, ty, ty) + gfpAdd(ty, ty, &a.y) + + gfpSub(ty, ty, &a.x) + + e.x.Set(tx) + e.y.Set(ty) + return e +} + +func (e *gfP2) Square(a *gfP2) *gfP2 { + // Complex squaring algorithm: + // (xi+y)² = (x+y)(y-x) + 2*i*x*y + tx, ty := &gfP{}, &gfP{} + gfpSub(tx, &a.y, &a.x) + gfpAdd(ty, &a.x, &a.y) + gfpMul(ty, tx, ty) + + gfpMul(tx, &a.x, &a.y) + gfpAdd(tx, tx, tx) + + e.x.Set(tx) + e.y.Set(ty) + return e +} + +func (e *gfP2) Invert(a *gfP2) *gfP2 { + // See "Implementing cryptographic pairings", M. Scott, section 3.2. + // ftp://136.206.11.249/pub/crypto/pairings.pdf + t1, t2 := &gfP{}, &gfP{} + gfpMul(t1, &a.x, &a.x) + gfpMul(t2, &a.y, &a.y) + gfpAdd(t1, t1, t2) + + inv := &gfP{} + inv.Invert(t1) + + gfpNeg(t1, &a.x) + + gfpMul(&e.x, t1, inv) + gfpMul(&e.y, &a.y, inv) + return e +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp6.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp6.go new file mode 100644 index 0000000000..83d61b781f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp6.go @@ -0,0 +1,213 @@ +package bn256 + +// For details of the algorithms used, see "Multiplication and Squaring on +// Pairing-Friendly Fields, Devegili et al. +// http://eprint.iacr.org/2006/471.pdf. + +// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ +// and ξ=i+3. +type gfP6 struct { + x, y, z gfP2 // value is xτ² + yτ + z +} + +func (e *gfP6) String() string { + return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")" +} + +func (e *gfP6) Set(a *gfP6) *gfP6 { + e.x.Set(&a.x) + e.y.Set(&a.y) + e.z.Set(&a.z) + return e +} + +func (e *gfP6) SetZero() *gfP6 { + e.x.SetZero() + e.y.SetZero() + e.z.SetZero() + return e +} + +func (e *gfP6) SetOne() *gfP6 { + e.x.SetZero() + e.y.SetZero() + e.z.SetOne() + return e +} + +func (e *gfP6) IsZero() bool { + return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() +} + +func (e *gfP6) IsOne() bool { + return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() +} + +func (e *gfP6) Neg(a *gfP6) *gfP6 { + e.x.Neg(&a.x) + e.y.Neg(&a.y) + e.z.Neg(&a.z) + return e +} + +func (e *gfP6) Frobenius(a *gfP6) *gfP6 { + e.x.Conjugate(&a.x) + e.y.Conjugate(&a.y) + e.z.Conjugate(&a.z) + + e.x.Mul(&e.x, xiTo2PMinus2Over3) + e.y.Mul(&e.y, xiToPMinus1Over3) + return e +} + +// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z +func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { + // τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3) + e.x.MulScalar(&a.x, xiTo2PSquaredMinus2Over3) + // τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3) + e.y.MulScalar(&a.y, xiToPSquaredMinus1Over3) + e.z.Set(&a.z) + return e +} + +func (e *gfP6) FrobeniusP4(a *gfP6) *gfP6 { + e.x.MulScalar(&a.x, xiToPSquaredMinus1Over3) + e.y.MulScalar(&a.y, xiTo2PSquaredMinus2Over3) + e.z.Set(&a.z) + return e +} + +func (e *gfP6) Add(a, b *gfP6) *gfP6 { + e.x.Add(&a.x, &b.x) + e.y.Add(&a.y, &b.y) + e.z.Add(&a.z, &b.z) + return e +} + +func (e *gfP6) Sub(a, b *gfP6) *gfP6 { + e.x.Sub(&a.x, &b.x) + e.y.Sub(&a.y, &b.y) + e.z.Sub(&a.z, &b.z) + return e +} + +func (e *gfP6) Mul(a, b *gfP6) *gfP6 { + // "Multiplication and Squaring on Pairing-Friendly Fields" + // Section 4, Karatsuba method. + // http://eprint.iacr.org/2006/471.pdf + v0 := (&gfP2{}).Mul(&a.z, &b.z) + v1 := (&gfP2{}).Mul(&a.y, &b.y) + v2 := (&gfP2{}).Mul(&a.x, &b.x) + + t0 := (&gfP2{}).Add(&a.x, &a.y) + t1 := (&gfP2{}).Add(&b.x, &b.y) + tz := (&gfP2{}).Mul(t0, t1) + tz.Sub(tz, v1).Sub(tz, v2).MulXi(tz).Add(tz, v0) + + t0.Add(&a.y, &a.z) + t1.Add(&b.y, &b.z) + ty := (&gfP2{}).Mul(t0, t1) + t0.MulXi(v2) + ty.Sub(ty, v0).Sub(ty, v1).Add(ty, t0) + + t0.Add(&a.x, &a.z) + t1.Add(&b.x, &b.z) + tx := (&gfP2{}).Mul(t0, t1) + tx.Sub(tx, v0).Add(tx, v1).Sub(tx, v2) + + e.x.Set(tx) + e.y.Set(ty) + e.z.Set(tz) + return e +} + +func (e *gfP6) MulScalar(a *gfP6, b *gfP2) *gfP6 { + e.x.Mul(&a.x, b) + e.y.Mul(&a.y, b) + e.z.Mul(&a.z, b) + return e +} + +func (e *gfP6) MulGFP(a *gfP6, b *gfP) *gfP6 { + e.x.MulScalar(&a.x, b) + e.y.MulScalar(&a.y, b) + e.z.MulScalar(&a.z, b) + return e +} + +// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ +func (e *gfP6) MulTau(a *gfP6) *gfP6 { + tz := (&gfP2{}).MulXi(&a.x) + ty := (&gfP2{}).Set(&a.y) + + e.y.Set(&a.z) + e.x.Set(ty) + e.z.Set(tz) + return e +} + +func (e *gfP6) Square(a *gfP6) *gfP6 { + v0 := (&gfP2{}).Square(&a.z) + v1 := (&gfP2{}).Square(&a.y) + v2 := (&gfP2{}).Square(&a.x) + + c0 := (&gfP2{}).Add(&a.x, &a.y) + c0.Square(c0).Sub(c0, v1).Sub(c0, v2).MulXi(c0).Add(c0, v0) + + c1 := (&gfP2{}).Add(&a.y, &a.z) + c1.Square(c1).Sub(c1, v0).Sub(c1, v1) + xiV2 := (&gfP2{}).MulXi(v2) + c1.Add(c1, xiV2) + + c2 := (&gfP2{}).Add(&a.x, &a.z) + c2.Square(c2).Sub(c2, v0).Add(c2, v1).Sub(c2, v2) + + e.x.Set(c2) + e.y.Set(c1) + e.z.Set(c0) + return e +} + +func (e *gfP6) Invert(a *gfP6) *gfP6 { + // See "Implementing cryptographic pairings", M. Scott, section 3.2. + // ftp://136.206.11.249/pub/crypto/pairings.pdf + + // Here we can give a short explanation of how it works: let j be a cubic root of + // unity in GF(p²) so that 1+j+j²=0. + // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z) + // = (xτ² + yτ + z)(Cτ²+Bτ+A) + // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). + // + // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z) + // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy) + // + // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) + t1 := (&gfP2{}).Mul(&a.x, &a.y) + t1.MulXi(t1) + + A := (&gfP2{}).Square(&a.z) + A.Sub(A, t1) + + B := (&gfP2{}).Square(&a.x) + B.MulXi(B) + t1.Mul(&a.y, &a.z) + B.Sub(B, t1) + + C := (&gfP2{}).Square(&a.y) + t1.Mul(&a.x, &a.z) + C.Sub(C, t1) + + F := (&gfP2{}).Mul(C, &a.y) + F.MulXi(F) + t1.Mul(A, &a.z) + F.Add(F, t1) + t1.Mul(B, &a.x).MulXi(t1) + F.Add(F, t1) + + F.Invert(F) + + e.x.Mul(C, F) + e.y.Mul(B, F) + e.z.Mul(A, F) + return e +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_amd64.s b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_amd64.s new file mode 100644 index 0000000000..bdb4ffb787 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_amd64.s @@ -0,0 +1,129 @@ +// +build amd64,!generic + +#define storeBlock(a0,a1,a2,a3, r) \ + MOVQ a0, 0+r \ + MOVQ a1, 8+r \ + MOVQ a2, 16+r \ + MOVQ a3, 24+r + +#define loadBlock(r, a0,a1,a2,a3) \ + MOVQ 0+r, a0 \ + MOVQ 8+r, a1 \ + MOVQ 16+r, a2 \ + MOVQ 24+r, a3 + +#define gfpCarry(a0,a1,a2,a3,a4, b0,b1,b2,b3,b4) \ + \ // b = a-p + MOVQ a0, b0 \ + MOVQ a1, b1 \ + MOVQ a2, b2 \ + MOVQ a3, b3 \ + MOVQ a4, b4 \ + \ + SUBQ ·p2+0(SB), b0 \ + SBBQ ·p2+8(SB), b1 \ + SBBQ ·p2+16(SB), b2 \ + SBBQ ·p2+24(SB), b3 \ + SBBQ $0, b4 \ + \ + \ // if b is negative then return a + \ // else return b + CMOVQCC b0, a0 \ + CMOVQCC b1, a1 \ + CMOVQCC b2, a2 \ + CMOVQCC b3, a3 + +#include "mul_amd64.h" +#include "mul_bmi2_amd64.h" + +TEXT ·gfpNeg(SB),0,$0-16 + MOVQ ·p2+0(SB), R8 + MOVQ ·p2+8(SB), R9 + MOVQ ·p2+16(SB), R10 + MOVQ ·p2+24(SB), R11 + + MOVQ a+8(FP), DI + SUBQ 0(DI), R8 + SBBQ 8(DI), R9 + SBBQ 16(DI), R10 + SBBQ 24(DI), R11 + + MOVQ $0, AX + gfpCarry(R8,R9,R10,R11,AX, R12,R13,R14,R15,BX) + + MOVQ c+0(FP), DI + storeBlock(R8,R9,R10,R11, 0(DI)) + RET + +TEXT ·gfpAdd(SB),0,$0-24 + MOVQ a+8(FP), DI + MOVQ b+16(FP), SI + + loadBlock(0(DI), R8,R9,R10,R11) + MOVQ $0, R12 + + ADDQ 0(SI), R8 + ADCQ 8(SI), R9 + ADCQ 16(SI), R10 + ADCQ 24(SI), R11 + ADCQ $0, R12 + + gfpCarry(R8,R9,R10,R11,R12, R13,R14,R15,AX,BX) + + MOVQ c+0(FP), DI + storeBlock(R8,R9,R10,R11, 0(DI)) + RET + +TEXT ·gfpSub(SB),0,$0-24 + MOVQ a+8(FP), DI + MOVQ b+16(FP), SI + + loadBlock(0(DI), R8,R9,R10,R11) + + MOVQ ·p2+0(SB), R12 + MOVQ ·p2+8(SB), R13 + MOVQ ·p2+16(SB), R14 + MOVQ ·p2+24(SB), R15 + MOVQ $0, AX + + SUBQ 0(SI), R8 + SBBQ 8(SI), R9 + SBBQ 16(SI), R10 + SBBQ 24(SI), R11 + + CMOVQCC AX, R12 + CMOVQCC AX, R13 + CMOVQCC AX, R14 + CMOVQCC AX, R15 + + ADDQ R12, R8 + ADCQ R13, R9 + ADCQ R14, R10 + ADCQ R15, R11 + + MOVQ c+0(FP), DI + storeBlock(R8,R9,R10,R11, 0(DI)) + RET + +TEXT ·gfpMul(SB),0,$160-24 + MOVQ a+8(FP), DI + MOVQ b+16(FP), SI + + // Jump to a slightly different implementation if MULX isn't supported. + CMPB ·hasBMI2(SB), $0 + JE nobmi2Mul + + mulBMI2(0(DI),8(DI),16(DI),24(DI), 0(SI)) + storeBlock( R8, R9,R10,R11, 0(SP)) + storeBlock(R12,R13,R14,R15, 32(SP)) + gfpReduceBMI2() + JMP end + +nobmi2Mul: + mul(0(DI),8(DI),16(DI),24(DI), 0(SI), 0(SP)) + gfpReduce(0(SP)) + +end: + MOVQ c+0(FP), DI + storeBlock(R12,R13,R14,R15, 0(DI)) + RET diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_arm64.s b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_arm64.s new file mode 100644 index 0000000000..c65e80168c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_arm64.s @@ -0,0 +1,113 @@ +// +build arm64,!generic + +#define storeBlock(a0,a1,a2,a3, r) \ + MOVD a0, 0+r \ + MOVD a1, 8+r \ + MOVD a2, 16+r \ + MOVD a3, 24+r + +#define loadBlock(r, a0,a1,a2,a3) \ + MOVD 0+r, a0 \ + MOVD 8+r, a1 \ + MOVD 16+r, a2 \ + MOVD 24+r, a3 + +#define loadModulus(p0,p1,p2,p3) \ + MOVD ·p2+0(SB), p0 \ + MOVD ·p2+8(SB), p1 \ + MOVD ·p2+16(SB), p2 \ + MOVD ·p2+24(SB), p3 + +#include "mul_arm64.h" + +TEXT ·gfpNeg(SB),0,$0-16 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + loadModulus(R5,R6,R7,R8) + + SUBS R1, R5, R1 + SBCS R2, R6, R2 + SBCS R3, R7, R3 + SBCS R4, R8, R4 + + SUBS R5, R1, R5 + SBCS R6, R2, R6 + SBCS R7, R3, R7 + SBCS R8, R4, R8 + + CSEL CS, R5, R1, R1 + CSEL CS, R6, R2, R2 + CSEL CS, R7, R3, R3 + CSEL CS, R8, R4, R4 + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET + +TEXT ·gfpAdd(SB),0,$0-24 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + MOVD b+16(FP), R0 + loadBlock(0(R0), R5,R6,R7,R8) + loadModulus(R9,R10,R11,R12) + MOVD ZR, R0 + + ADDS R5, R1 + ADCS R6, R2 + ADCS R7, R3 + ADCS R8, R4 + ADCS ZR, R0 + + SUBS R9, R1, R5 + SBCS R10, R2, R6 + SBCS R11, R3, R7 + SBCS R12, R4, R8 + SBCS ZR, R0, R0 + + CSEL CS, R5, R1, R1 + CSEL CS, R6, R2, R2 + CSEL CS, R7, R3, R3 + CSEL CS, R8, R4, R4 + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET + +TEXT ·gfpSub(SB),0,$0-24 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + MOVD b+16(FP), R0 + loadBlock(0(R0), R5,R6,R7,R8) + loadModulus(R9,R10,R11,R12) + + SUBS R5, R1 + SBCS R6, R2 + SBCS R7, R3 + SBCS R8, R4 + + CSEL CS, ZR, R9, R9 + CSEL CS, ZR, R10, R10 + CSEL CS, ZR, R11, R11 + CSEL CS, ZR, R12, R12 + + ADDS R9, R1 + ADCS R10, R2 + ADCS R11, R3 + ADCS R12, R4 + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET + +TEXT ·gfpMul(SB),0,$0-24 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + MOVD b+16(FP), R0 + loadBlock(0(R0), R5,R6,R7,R8) + + mul(R9,R10,R11,R12,R13,R14,R15,R16) + gfpReduce() + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_decl.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_decl.go new file mode 100644 index 0000000000..fdea5c11a5 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_decl.go @@ -0,0 +1,25 @@ +// +build amd64,!generic arm64,!generic + +package bn256 + +// This file contains forward declarations for the architecture-specific +// assembly implementations of these functions, provided that they exist. + +import ( + "golang.org/x/sys/cpu" +) + +//nolint:varcheck +var hasBMI2 = cpu.X86.HasBMI2 + +// go:noescape +func gfpNeg(c, a *gfP) + +//go:noescape +func gfpAdd(c, a, b *gfP) + +//go:noescape +func gfpSub(c, a, b *gfP) + +//go:noescape +func gfpMul(c, a, b *gfP) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_generic.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_generic.go new file mode 100644 index 0000000000..8e6be95961 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_generic.go @@ -0,0 +1,173 @@ +// +build !amd64,!arm64 generic + +package bn256 + +func gfpCarry(a *gfP, head uint64) { + b := &gfP{} + + var carry uint64 + for i, pi := range p2 { + ai := a[i] + bi := ai - pi - carry + b[i] = bi + carry = (pi&^ai | (pi|^ai)&bi) >> 63 + } + carry = carry &^ head + + // If b is negative, then return a. + // Else return b. + carry = -carry + ncarry := ^carry + for i := 0; i < 4; i++ { + a[i] = (a[i] & carry) | (b[i] & ncarry) + } +} + +func gfpNeg(c, a *gfP) { + var carry uint64 + for i, pi := range p2 { + ai := a[i] + ci := pi - ai - carry + c[i] = ci + carry = (ai&^pi | (ai|^pi)&ci) >> 63 + } + gfpCarry(c, 0) +} + +func gfpAdd(c, a, b *gfP) { + var carry uint64 + for i, ai := range a { + bi := b[i] + ci := ai + bi + carry + c[i] = ci + carry = (ai&bi | (ai|bi)&^ci) >> 63 + } + gfpCarry(c, carry) +} + +func gfpSub(c, a, b *gfP) { + t := &gfP{} + + var carry uint64 + for i, pi := range p2 { + bi := b[i] + ti := pi - bi - carry + t[i] = ti + carry = (bi&^pi | (bi|^pi)&ti) >> 63 + } + + carry = 0 + for i, ai := range a { + ti := t[i] + ci := ai + ti + carry + c[i] = ci + carry = (ai&ti | (ai|ti)&^ci) >> 63 + } + gfpCarry(c, carry) +} + +func mul(a, b [4]uint64) [8]uint64 { + const ( + mask16 uint64 = 0x0000ffff + mask32 uint64 = 0xffffffff + ) + + var buff [32]uint64 + for i, ai := range a { + a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 + + for j, bj := range b { + b0, b2 := bj&mask32, bj>>32 + + off := 4 * (i + j) + buff[off+0] += a0 * b0 + buff[off+1] += a1 * b0 + buff[off+2] += a2*b0 + a0*b2 + buff[off+3] += a3*b0 + a1*b2 + buff[off+4] += a2 * b2 + buff[off+5] += a3 * b2 + } + } + + for i := uint(1); i < 4; i++ { + shift := 16 * i + + var head, carry uint64 + for j := uint(0); j < 8; j++ { + block := 4 * j + + xi := buff[block] + yi := (buff[block+i] << shift) + head + zi := xi + yi + carry + buff[block] = zi + carry = (xi&yi | (xi|yi)&^zi) >> 63 + + head = buff[block+i] >> (64 - shift) + } + } + + return [8]uint64{buff[0], buff[4], buff[8], buff[12], buff[16], buff[20], buff[24], buff[28]} +} + +func halfMul(a, b [4]uint64) [4]uint64 { + const ( + mask16 uint64 = 0x0000ffff + mask32 uint64 = 0xffffffff + ) + + var buff [18]uint64 + for i, ai := range a { + a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 + + for j, bj := range b { + if i+j > 3 { + break + } + b0, b2 := bj&mask32, bj>>32 + + off := 4 * (i + j) + buff[off+0] += a0 * b0 + buff[off+1] += a1 * b0 + buff[off+2] += a2*b0 + a0*b2 + buff[off+3] += a3*b0 + a1*b2 + buff[off+4] += a2 * b2 + buff[off+5] += a3 * b2 + } + } + + for i := uint(1); i < 4; i++ { + shift := 16 * i + + var head, carry uint64 + for j := uint(0); j < 4; j++ { + block := 4 * j + + xi := buff[block] + yi := (buff[block+i] << shift) + head + zi := xi + yi + carry + buff[block] = zi + carry = (xi&yi | (xi|yi)&^zi) >> 63 + + head = buff[block+i] >> (64 - shift) + } + } + + return [4]uint64{buff[0], buff[4], buff[8], buff[12]} +} + +func gfpMul(c, a, b *gfP) { + T := mul(*a, *b) + m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np) + t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2) + + var carry uint64 + for i, Ti := range T { + ti := t[i] + zi := Ti + ti + carry + T[i] = zi + carry = (Ti&ti | (Ti|ti)&^zi) >> 63 + } + + *c = gfP{T[4], T[5], T[6], T[7]} + gfpCarry(c, carry) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_test.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_test.go new file mode 100644 index 0000000000..16ab2a8410 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_test.go @@ -0,0 +1,60 @@ +package bn256 + +import ( + "testing" +) + +// Tests that negation works the same way on both assembly-optimized and pure Go +// implementation. +func TestGFpNeg(t *testing.T) { + n := &gfP{0x0123456789abcdef, 0xfedcba9876543210, 0xdeadbeefdeadbeef, 0xfeebdaedfeebdaed} + w := &gfP{0xfedcba9876543211, 0x0123456789abcdef, 0x2152411021524110, 0x0114251201142512} + h := &gfP{} + + gfpNeg(h, n) + if *h != *w { + t.Errorf("negation mismatch: have %#x, want %#x", *h, *w) + } +} + +// Tests that addition works the same way on both assembly-optimized and pure Go +// implementation. +func TestGFpAdd(t *testing.T) { + a := &gfP{0x0123456789abcdef, 0xfedcba9876543210, 0xdeadbeefdeadbeef, 0xfeebdaedfeebdaed} + b := &gfP{0xfedcba9876543210, 0x0123456789abcdef, 0xfeebdaedfeebdaed, 0xdeadbeefdeadbeef} + w := &gfP{0xc3df73e9278302b8, 0x687e956e978e3572, 0x254954275c18417f, 0xad354b6afc67f9b4} + h := &gfP{} + + gfpAdd(h, a, b) + if *h != *w { + t.Errorf("addition mismatch: have %#x, want %#x", *h, *w) + } +} + +// Tests that subtraction works the same way on both assembly-optimized and pure Go +// implementation. +func TestGFpSub(t *testing.T) { + a := &gfP{0x0123456789abcdef, 0xfedcba9876543210, 0xdeadbeefdeadbeef, 0xfeebdaedfeebdaed} + b := &gfP{0xfedcba9876543210, 0x0123456789abcdef, 0xfeebdaedfeebdaed, 0xdeadbeefdeadbeef} + w := &gfP{0x02468acf13579bdf, 0xfdb97530eca86420, 0xdfc1e401dfc1e402, 0x203e1bfe203e1bfd} + h := &gfP{} + + gfpSub(h, a, b) + if *h != *w { + t.Errorf("subtraction mismatch: have %#x, want %#x", *h, *w) + } +} + +// Tests that multiplication works the same way on both assembly-optimized and pure Go +// implementation. +func TestGFpMul(t *testing.T) { + a := &gfP{0x0123456789abcdef, 0xfedcba9876543210, 0xdeadbeefdeadbeef, 0xfeebdaedfeebdaed} + b := &gfP{0xfedcba9876543210, 0x0123456789abcdef, 0xfeebdaedfeebdaed, 0xdeadbeefdeadbeef} + w := &gfP{0xcbcbd377f7ad22d3, 0x3b89ba5d849379bf, 0x87b61627bd38b6d2, 0xc44052a2a0e654b2} + h := &gfP{} + + gfpMul(h, a, b) + if *h != *w { + t.Errorf("multiplication mismatch: have %#x, want %#x", *h, *w) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/lattice.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/lattice.go new file mode 100644 index 0000000000..f9ace4d9fc --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/lattice.go @@ -0,0 +1,115 @@ +package bn256 + +import ( + "math/big" +) + +var half = new(big.Int).Rsh(Order, 1) + +var curveLattice = &lattice{ + vectors: [][]*big.Int{ + {bigFromBase10("147946756881789319000765030803803410728"), bigFromBase10("147946756881789319010696353538189108491")}, + {bigFromBase10("147946756881789319020627676272574806254"), bigFromBase10("-147946756881789318990833708069417712965")}, + }, + inverse: []*big.Int{ + bigFromBase10("147946756881789318990833708069417712965"), + bigFromBase10("147946756881789319010696353538189108491"), + }, + det: bigFromBase10("43776485743678550444492811490514550177096728800832068687396408373151616991234"), +} + +var targetLattice = &lattice{ + vectors: [][]*big.Int{ + {bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697763"), bigFromBase10("9931322734385697764")}, + {bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848882"), bigFromBase10("-9931322734385697762")}, + {bigFromBase10("-9931322734385697762"), bigFromBase10("-4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("-4965661367192848882")}, + {bigFromBase10("9931322734385697763"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881")}, + }, + inverse: []*big.Int{ + bigFromBase10("734653495049373973658254490726798021314063399421879442165"), + bigFromBase10("147946756881789319000765030803803410728"), + bigFromBase10("-147946756881789319005730692170996259609"), + bigFromBase10("1469306990098747947464455738335385361643788813749140841702"), + }, + det: new(big.Int).Set(Order), +} + +type lattice struct { + vectors [][]*big.Int + inverse []*big.Int + det *big.Int +} + +// decompose takes a scalar mod Order as input and finds a short, positive decomposition of it wrt to the lattice basis. +func (l *lattice) decompose(k *big.Int) []*big.Int { + n := len(l.inverse) + + // Calculate closest vector in lattice to with Babai's rounding. + c := make([]*big.Int, n) + for i := 0; i < n; i++ { + c[i] = new(big.Int).Mul(k, l.inverse[i]) + round(c[i], l.det) + } + + // Transform vectors according to c and subtract . + out := make([]*big.Int, n) + temp := new(big.Int) + + for i := 0; i < n; i++ { + out[i] = new(big.Int) + + for j := 0; j < n; j++ { + temp.Mul(c[j], l.vectors[j][i]) + out[i].Add(out[i], temp) + } + + out[i].Neg(out[i]) + out[i].Add(out[i], l.vectors[0][i]).Add(out[i], l.vectors[0][i]) + } + out[0].Add(out[0], k) + + return out +} + +func (l *lattice) Precompute(add func(i, j uint)) { + n := uint(len(l.vectors)) + total := uint(1) << n + + for i := uint(0); i < n; i++ { + for j := uint(0); j < total; j++ { + if (j>>i)&1 == 1 { + add(i, j) + } + } + } +} + +func (l *lattice) Multi(scalar *big.Int) []uint8 { + decomp := l.decompose(scalar) + + maxLen := 0 + for _, x := range decomp { + if x.BitLen() > maxLen { + maxLen = x.BitLen() + } + } + + out := make([]uint8, maxLen) + for j, x := range decomp { + for i := 0; i < maxLen; i++ { + out[i] += uint8(x.Bit(i)) << uint(j) + } + } + + return out +} + +// round sets num to num/denom rounded to the nearest integer. +func round(num, denom *big.Int) { + r := new(big.Int) + num.DivMod(num, denom, r) + + if r.Cmp(half) == 1 { + num.Add(num, big.NewInt(1)) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/lattice_test.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/lattice_test.go new file mode 100644 index 0000000000..4d52ad9b27 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/lattice_test.go @@ -0,0 +1,29 @@ +package bn256 + +import ( + "crypto/rand" + + "testing" +) + +func TestLatticeReduceCurve(t *testing.T) { + k, _ := rand.Int(rand.Reader, Order) + ks := curveLattice.decompose(k) + + if ks[0].BitLen() > 130 || ks[1].BitLen() > 130 { + t.Fatal("reduction too large") + } else if ks[0].Sign() < 0 || ks[1].Sign() < 0 { + t.Fatal("reduction must be positive") + } +} + +func TestLatticeReduceTarget(t *testing.T) { + k, _ := rand.Int(rand.Reader, Order) + ks := targetLattice.decompose(k) + + if ks[0].BitLen() > 66 || ks[1].BitLen() > 66 || ks[2].BitLen() > 66 || ks[3].BitLen() > 66 { + t.Fatal("reduction too large") + } else if ks[0].Sign() < 0 || ks[1].Sign() < 0 || ks[2].Sign() < 0 || ks[3].Sign() < 0 { + t.Fatal("reduction must be positive") + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/main_test.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/main_test.go new file mode 100644 index 0000000000..c0c85457be --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/main_test.go @@ -0,0 +1,71 @@ +package bn256 + +import ( + "testing" + + "crypto/rand" +) + +func TestRandomG2Marshal(t *testing.T) { + for i := 0; i < 10; i++ { + n, g2, err := RandomG2(rand.Reader) + if err != nil { + t.Error(err) + continue + } + t.Logf("%v: %x\n", n, g2.Marshal()) + } +} + +func TestPairings(t *testing.T) { + a1 := new(G1).ScalarBaseMult(bigFromBase10("1")) + a2 := new(G1).ScalarBaseMult(bigFromBase10("2")) + a37 := new(G1).ScalarBaseMult(bigFromBase10("37")) + an1 := new(G1).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) + + b0 := new(G2).ScalarBaseMult(bigFromBase10("0")) + b1 := new(G2).ScalarBaseMult(bigFromBase10("1")) + b2 := new(G2).ScalarBaseMult(bigFromBase10("2")) + b27 := new(G2).ScalarBaseMult(bigFromBase10("27")) + b999 := new(G2).ScalarBaseMult(bigFromBase10("999")) + bn1 := new(G2).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) + + p1 := Pair(a1, b1) + pn1 := Pair(a1, bn1) + np1 := Pair(an1, b1) + if pn1.String() != np1.String() { + t.Error("Pairing mismatch: e(a, -b) != e(-a, b)") + } + if !PairingCheck([]*G1{a1, an1}, []*G2{b1, b1}) { + t.Error("MultiAte check gave false negative!") + } + p0 := new(GT).Add(p1, pn1) + p0_2 := Pair(a1, b0) + if p0.String() != p0_2.String() { + t.Error("Pairing mismatch: e(a, b) * e(a, -b) != 1") + } + p0_3 := new(GT).ScalarMult(p1, bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617")) + if p0.String() != p0_3.String() { + t.Error("Pairing mismatch: e(a, b) has wrong order") + } + p2 := Pair(a2, b1) + p2_2 := Pair(a1, b2) + p2_3 := new(GT).ScalarMult(p1, bigFromBase10("2")) + if p2.String() != p2_2.String() { + t.Error("Pairing mismatch: e(a, b * 2) != e(a * 2, b)") + } + if p2.String() != p2_3.String() { + t.Error("Pairing mismatch: e(a, b * 2) != e(a, b) ** 2") + } + if p2.String() == p1.String() { + t.Error("Pairing is degenerate!") + } + if PairingCheck([]*G1{a1, a1}, []*G2{b1, b1}) { + t.Error("MultiAte check gave false positive!") + } + p999 := Pair(a37, b27) + p999_2 := Pair(a1, b999) + if p999.String() != p999_2.String() { + t.Error("Pairing mismatch: e(a * 37, b * 27) != e(a, b * 999)") + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_amd64.h b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_amd64.h new file mode 100644 index 0000000000..bab5da8313 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_amd64.h @@ -0,0 +1,181 @@ +#define mul(a0,a1,a2,a3, rb, stack) \ + MOVQ a0, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a0, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a0, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a0, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + \ + storeBlock(R8,R9,R10,R11, 0+stack) \ + MOVQ R12, 32+stack \ + \ + MOVQ a1, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a1, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a1, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a1, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + \ + ADDQ 8+stack, R8 \ + ADCQ 16+stack, R9 \ + ADCQ 24+stack, R10 \ + ADCQ 32+stack, R11 \ + ADCQ $0, R12 \ + storeBlock(R8,R9,R10,R11, 8+stack) \ + MOVQ R12, 40+stack \ + \ + MOVQ a2, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a2, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a2, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a2, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + \ + ADDQ 16+stack, R8 \ + ADCQ 24+stack, R9 \ + ADCQ 32+stack, R10 \ + ADCQ 40+stack, R11 \ + ADCQ $0, R12 \ + storeBlock(R8,R9,R10,R11, 16+stack) \ + MOVQ R12, 48+stack \ + \ + MOVQ a3, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a3, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a3, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a3, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + \ + ADDQ 24+stack, R8 \ + ADCQ 32+stack, R9 \ + ADCQ 40+stack, R10 \ + ADCQ 48+stack, R11 \ + ADCQ $0, R12 \ + storeBlock(R8,R9,R10,R11, 24+stack) \ + MOVQ R12, 56+stack + +#define gfpReduce(stack) \ + \ // m = (T * N') mod R, store m in R8:R9:R10:R11 + MOVQ ·np+0(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ ·np+0(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ ·np+0(SB), AX \ + MULQ 16+stack \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ ·np+0(SB), AX \ + MULQ 24+stack \ + ADDQ AX, R11 \ + \ + MOVQ ·np+8(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R12 \ + MOVQ DX, R13 \ + MOVQ ·np+8(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R13 \ + ADCQ $0, DX \ + MOVQ DX, R14 \ + MOVQ ·np+8(SB), AX \ + MULQ 16+stack \ + ADDQ AX, R14 \ + \ + ADDQ R12, R9 \ + ADCQ R13, R10 \ + ADCQ R14, R11 \ + \ + MOVQ ·np+16(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R12 \ + MOVQ DX, R13 \ + MOVQ ·np+16(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R13 \ + \ + ADDQ R12, R10 \ + ADCQ R13, R11 \ + \ + MOVQ ·np+24(SB), AX \ + MULQ 0+stack \ + ADDQ AX, R11 \ + \ + storeBlock(R8,R9,R10,R11, 64+stack) \ + \ + \ // m * N + mul(·p2+0(SB),·p2+8(SB),·p2+16(SB),·p2+24(SB), 64+stack, 96+stack) \ + \ + \ // Add the 512-bit intermediate to m*N + loadBlock(96+stack, R8,R9,R10,R11) \ + loadBlock(128+stack, R12,R13,R14,R15) \ + \ + MOVQ $0, AX \ + ADDQ 0+stack, R8 \ + ADCQ 8+stack, R9 \ + ADCQ 16+stack, R10 \ + ADCQ 24+stack, R11 \ + ADCQ 32+stack, R12 \ + ADCQ 40+stack, R13 \ + ADCQ 48+stack, R14 \ + ADCQ 56+stack, R15 \ + ADCQ $0, AX \ + \ + gfpCarry(R12,R13,R14,R15,AX, R8,R9,R10,R11,BX) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_arm64.h b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_arm64.h new file mode 100644 index 0000000000..d405eb8f72 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_arm64.h @@ -0,0 +1,133 @@ +#define mul(c0,c1,c2,c3,c4,c5,c6,c7) \ + MUL R1, R5, c0 \ + UMULH R1, R5, c1 \ + MUL R1, R6, R0 \ + ADDS R0, c1 \ + UMULH R1, R6, c2 \ + MUL R1, R7, R0 \ + ADCS R0, c2 \ + UMULH R1, R7, c3 \ + MUL R1, R8, R0 \ + ADCS R0, c3 \ + UMULH R1, R8, c4 \ + ADCS ZR, c4 \ + \ + MUL R2, R5, R1 \ + UMULH R2, R5, R26 \ + MUL R2, R6, R0 \ + ADDS R0, R26 \ + UMULH R2, R6, R27 \ + MUL R2, R7, R0 \ + ADCS R0, R27 \ + UMULH R2, R7, R29 \ + MUL R2, R8, R0 \ + ADCS R0, R29 \ + UMULH R2, R8, c5 \ + ADCS ZR, c5 \ + ADDS R1, c1 \ + ADCS R26, c2 \ + ADCS R27, c3 \ + ADCS R29, c4 \ + ADCS ZR, c5 \ + \ + MUL R3, R5, R1 \ + UMULH R3, R5, R26 \ + MUL R3, R6, R0 \ + ADDS R0, R26 \ + UMULH R3, R6, R27 \ + MUL R3, R7, R0 \ + ADCS R0, R27 \ + UMULH R3, R7, R29 \ + MUL R3, R8, R0 \ + ADCS R0, R29 \ + UMULH R3, R8, c6 \ + ADCS ZR, c6 \ + ADDS R1, c2 \ + ADCS R26, c3 \ + ADCS R27, c4 \ + ADCS R29, c5 \ + ADCS ZR, c6 \ + \ + MUL R4, R5, R1 \ + UMULH R4, R5, R26 \ + MUL R4, R6, R0 \ + ADDS R0, R26 \ + UMULH R4, R6, R27 \ + MUL R4, R7, R0 \ + ADCS R0, R27 \ + UMULH R4, R7, R29 \ + MUL R4, R8, R0 \ + ADCS R0, R29 \ + UMULH R4, R8, c7 \ + ADCS ZR, c7 \ + ADDS R1, c3 \ + ADCS R26, c4 \ + ADCS R27, c5 \ + ADCS R29, c6 \ + ADCS ZR, c7 + +#define gfpReduce() \ + \ // m = (T * N') mod R, store m in R1:R2:R3:R4 + MOVD ·np+0(SB), R17 \ + MOVD ·np+8(SB), R25 \ + MOVD ·np+16(SB), R19 \ + MOVD ·np+24(SB), R20 \ + \ + MUL R9, R17, R1 \ + UMULH R9, R17, R2 \ + MUL R9, R25, R0 \ + ADDS R0, R2 \ + UMULH R9, R25, R3 \ + MUL R9, R19, R0 \ + ADCS R0, R3 \ + UMULH R9, R19, R4 \ + MUL R9, R20, R0 \ + ADCS R0, R4 \ + \ + MUL R10, R17, R21 \ + UMULH R10, R17, R22 \ + MUL R10, R25, R0 \ + ADDS R0, R22 \ + UMULH R10, R25, R23 \ + MUL R10, R19, R0 \ + ADCS R0, R23 \ + ADDS R21, R2 \ + ADCS R22, R3 \ + ADCS R23, R4 \ + \ + MUL R11, R17, R21 \ + UMULH R11, R17, R22 \ + MUL R11, R25, R0 \ + ADDS R0, R22 \ + ADDS R21, R3 \ + ADCS R22, R4 \ + \ + MUL R12, R17, R21 \ + ADDS R21, R4 \ + \ + \ // m * N + loadModulus(R5,R6,R7,R8) \ + mul(R17,R25,R19,R20,R21,R22,R23,R24) \ + \ + \ // Add the 512-bit intermediate to m*N + MOVD ZR, R0 \ + ADDS R9, R17 \ + ADCS R10, R25 \ + ADCS R11, R19 \ + ADCS R12, R20 \ + ADCS R13, R21 \ + ADCS R14, R22 \ + ADCS R15, R23 \ + ADCS R16, R24 \ + ADCS ZR, R0 \ + \ + \ // Our output is R21:R22:R23:R24. Reduce mod p if necessary. + SUBS R5, R21, R10 \ + SBCS R6, R22, R11 \ + SBCS R7, R23, R12 \ + SBCS R8, R24, R13 \ + \ + CSEL CS, R10, R21, R1 \ + CSEL CS, R11, R22, R2 \ + CSEL CS, R12, R23, R3 \ + CSEL CS, R13, R24, R4 diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_bmi2_amd64.h b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_bmi2_amd64.h new file mode 100644 index 0000000000..71ad0499af --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_bmi2_amd64.h @@ -0,0 +1,112 @@ +#define mulBMI2(a0,a1,a2,a3, rb) \ + MOVQ a0, DX \ + MOVQ $0, R13 \ + MULXQ 0+rb, R8, R9 \ + MULXQ 8+rb, AX, R10 \ + ADDQ AX, R9 \ + MULXQ 16+rb, AX, R11 \ + ADCQ AX, R10 \ + MULXQ 24+rb, AX, R12 \ + ADCQ AX, R11 \ + ADCQ $0, R12 \ + ADCQ $0, R13 \ + \ + MOVQ a1, DX \ + MOVQ $0, R14 \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R9 \ + ADCQ BX, R10 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R11 \ + ADCQ BX, R12 \ + ADCQ $0, R13 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R12 \ + ADCQ BX, R13 \ + ADCQ $0, R14 \ + \ + MOVQ a2, DX \ + MOVQ $0, R15 \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R12 \ + ADCQ BX, R13 \ + ADCQ $0, R14 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R11 \ + ADCQ BX, R12 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R13 \ + ADCQ BX, R14 \ + ADCQ $0, R15 \ + \ + MOVQ a3, DX \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R11 \ + ADCQ BX, R12 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R13 \ + ADCQ BX, R14 \ + ADCQ $0, R15 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R12 \ + ADCQ BX, R13 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R14 \ + ADCQ BX, R15 + +#define gfpReduceBMI2() \ + \ // m = (T * N') mod R, store m in R8:R9:R10:R11 + MOVQ ·np+0(SB), DX \ + MULXQ 0(SP), R8, R9 \ + MULXQ 8(SP), AX, R10 \ + ADDQ AX, R9 \ + MULXQ 16(SP), AX, R11 \ + ADCQ AX, R10 \ + MULXQ 24(SP), AX, BX \ + ADCQ AX, R11 \ + \ + MOVQ ·np+8(SB), DX \ + MULXQ 0(SP), AX, BX \ + ADDQ AX, R9 \ + ADCQ BX, R10 \ + MULXQ 16(SP), AX, BX \ + ADCQ AX, R11 \ + MULXQ 8(SP), AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + \ + MOVQ ·np+16(SB), DX \ + MULXQ 0(SP), AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + MULXQ 8(SP), AX, BX \ + ADDQ AX, R11 \ + \ + MOVQ ·np+24(SB), DX \ + MULXQ 0(SP), AX, BX \ + ADDQ AX, R11 \ + \ + storeBlock(R8,R9,R10,R11, 64(SP)) \ + \ + \ // m * N + mulBMI2(·p2+0(SB),·p2+8(SB),·p2+16(SB),·p2+24(SB), 64(SP)) \ + \ + \ // Add the 512-bit intermediate to m*N + MOVQ $0, AX \ + ADDQ 0(SP), R8 \ + ADCQ 8(SP), R9 \ + ADCQ 16(SP), R10 \ + ADCQ 24(SP), R11 \ + ADCQ 32(SP), R12 \ + ADCQ 40(SP), R13 \ + ADCQ 48(SP), R14 \ + ADCQ 56(SP), R15 \ + ADCQ $0, AX \ + \ + gfpCarry(R12,R13,R14,R15,AX, R8,R9,R10,R11,BX) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/optate.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/optate.go new file mode 100644 index 0000000000..b71e50e3a2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/optate.go @@ -0,0 +1,271 @@ +package bn256 + +func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2) (a, b, c *gfP2, rOut *twistPoint) { + // See the mixed addition algorithm from "Faster Computation of the + // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf + B := (&gfP2{}).Mul(&p.x, &r.t) + + D := (&gfP2{}).Add(&p.y, &r.z) + D.Square(D).Sub(D, r2).Sub(D, &r.t).Mul(D, &r.t) + + H := (&gfP2{}).Sub(B, &r.x) + I := (&gfP2{}).Square(H) + + E := (&gfP2{}).Add(I, I) + E.Add(E, E) + + J := (&gfP2{}).Mul(H, E) + + L1 := (&gfP2{}).Sub(D, &r.y) + L1.Sub(L1, &r.y) + + V := (&gfP2{}).Mul(&r.x, E) + + rOut = &twistPoint{} + rOut.x.Square(L1).Sub(&rOut.x, J).Sub(&rOut.x, V).Sub(&rOut.x, V) + + rOut.z.Add(&r.z, H).Square(&rOut.z).Sub(&rOut.z, &r.t).Sub(&rOut.z, I) + + t := (&gfP2{}).Sub(V, &rOut.x) + t.Mul(t, L1) + t2 := (&gfP2{}).Mul(&r.y, J) + t2.Add(t2, t2) + rOut.y.Sub(t, t2) + + rOut.t.Square(&rOut.z) + + t.Add(&p.y, &rOut.z).Square(t).Sub(t, r2).Sub(t, &rOut.t) + + t2.Mul(L1, &p.x) + t2.Add(t2, t2) + a = (&gfP2{}).Sub(t2, t) + + c = (&gfP2{}).MulScalar(&rOut.z, &q.y) + c.Add(c, c) + + b = (&gfP2{}).Neg(L1) + b.MulScalar(b, &q.x).Add(b, b) + + return +} + +func lineFunctionDouble(r *twistPoint, q *curvePoint) (a, b, c *gfP2, rOut *twistPoint) { + // See the doubling algorithm for a=0 from "Faster Computation of the + // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf + A := (&gfP2{}).Square(&r.x) + B := (&gfP2{}).Square(&r.y) + C := (&gfP2{}).Square(B) + + D := (&gfP2{}).Add(&r.x, B) + D.Square(D).Sub(D, A).Sub(D, C).Add(D, D) + + E := (&gfP2{}).Add(A, A) + E.Add(E, A) + + G := (&gfP2{}).Square(E) + + rOut = &twistPoint{} + rOut.x.Sub(G, D).Sub(&rOut.x, D) + + rOut.z.Add(&r.y, &r.z).Square(&rOut.z).Sub(&rOut.z, B).Sub(&rOut.z, &r.t) + + rOut.y.Sub(D, &rOut.x).Mul(&rOut.y, E) + t := (&gfP2{}).Add(C, C) + t.Add(t, t).Add(t, t) + rOut.y.Sub(&rOut.y, t) + + rOut.t.Square(&rOut.z) + + t.Mul(E, &r.t).Add(t, t) + b = (&gfP2{}).Neg(t) + b.MulScalar(b, &q.x) + + a = (&gfP2{}).Add(&r.x, E) + a.Square(a).Sub(a, A).Sub(a, G) + t.Add(B, B).Add(t, t) + a.Sub(a, t) + + c = (&gfP2{}).Mul(&rOut.z, &r.t) + c.Add(c, c).MulScalar(c, &q.y) + + return +} + +func mulLine(ret *gfP12, a, b, c *gfP2) { + a2 := &gfP6{} + a2.y.Set(a) + a2.z.Set(b) + a2.Mul(a2, &ret.x) + t3 := (&gfP6{}).MulScalar(&ret.y, c) + + t := (&gfP2{}).Add(b, c) + t2 := &gfP6{} + t2.y.Set(a) + t2.z.Set(t) + ret.x.Add(&ret.x, &ret.y) + + ret.y.Set(t3) + + ret.x.Mul(&ret.x, t2).Sub(&ret.x, a2).Sub(&ret.x, &ret.y) + a2.MulTau(a2) + ret.y.Add(&ret.y, a2) +} + +// sixuPlus2NAF is 6u+2 in non-adjacent form. +var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, + 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1, + 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, + 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1} + +// miller implements the Miller loop for calculating the Optimal Ate pairing. +// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf +func miller(q *twistPoint, p *curvePoint) *gfP12 { + ret := (&gfP12{}).SetOne() + + aAffine := &twistPoint{} + aAffine.Set(q) + aAffine.MakeAffine() + + bAffine := &curvePoint{} + bAffine.Set(p) + bAffine.MakeAffine() + + minusA := &twistPoint{} + minusA.Neg(aAffine) + + r := &twistPoint{} + r.Set(aAffine) + + r2 := (&gfP2{}).Square(&aAffine.y) + + for i := len(sixuPlus2NAF) - 1; i > 0; i-- { + a, b, c, newR := lineFunctionDouble(r, bAffine) + if i != len(sixuPlus2NAF)-1 { + ret.Square(ret) + } + + mulLine(ret, a, b, c) + r = newR + + switch sixuPlus2NAF[i-1] { + case 1: + a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2) + case -1: + a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2) + default: + continue + } + + mulLine(ret, a, b, c) + r = newR + } + + // In order to calculate Q1 we have to convert q from the sextic twist + // to the full GF(p^12) group, apply the Frobenius there, and convert + // back. + // + // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just + // x for a moment, then after applying the Frobenius, we have x̄ω^(2p) + // where x̄ is the conjugate of x. If we are going to apply the inverse + // isomorphism we need a value with a single coefficient of ω² so we + // rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of + // p, 2p-2 is a multiple of six. Therefore we can rewrite as + // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the + // ω². + // + // A similar argument can be made for the y value. + + q1 := &twistPoint{} + q1.x.Conjugate(&aAffine.x).Mul(&q1.x, xiToPMinus1Over3) + q1.y.Conjugate(&aAffine.y).Mul(&q1.y, xiToPMinus1Over2) + q1.z.SetOne() + q1.t.SetOne() + + // For Q2 we are applying the p² Frobenius. The two conjugations cancel + // out and we are left only with the factors from the isomorphism. In + // the case of x, we end up with a pure number which is why + // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We + // ignore this to end up with -Q2. + + minusQ2 := &twistPoint{} + minusQ2.x.MulScalar(&aAffine.x, xiToPSquaredMinus1Over3) + minusQ2.y.Set(&aAffine.y) + minusQ2.z.SetOne() + minusQ2.t.SetOne() + + r2.Square(&q1.y) + a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2) + mulLine(ret, a, b, c) + r = newR + + r2.Square(&minusQ2.y) + a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2) + mulLine(ret, a, b, c) + r = newR + + return ret +} + +// finalExponentiation computes the (p¹²-1)/Order-th power of an element of +// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from +// http://cryptojedi.org/papers/dclxvi-20100714.pdf) +func finalExponentiation(in *gfP12) *gfP12 { + t1 := &gfP12{} + + // This is the p^6-Frobenius + t1.x.Neg(&in.x) + t1.y.Set(&in.y) + + inv := &gfP12{} + inv.Invert(in) + t1.Mul(t1, inv) + + t2 := (&gfP12{}).FrobeniusP2(t1) + t1.Mul(t1, t2) + + fp := (&gfP12{}).Frobenius(t1) + fp2 := (&gfP12{}).FrobeniusP2(t1) + fp3 := (&gfP12{}).Frobenius(fp2) + + fu := (&gfP12{}).Exp(t1, u) + fu2 := (&gfP12{}).Exp(fu, u) + fu3 := (&gfP12{}).Exp(fu2, u) + + y3 := (&gfP12{}).Frobenius(fu) + fu2p := (&gfP12{}).Frobenius(fu2) + fu3p := (&gfP12{}).Frobenius(fu3) + y2 := (&gfP12{}).FrobeniusP2(fu2) + + y0 := &gfP12{} + y0.Mul(fp, fp2).Mul(y0, fp3) + + y1 := (&gfP12{}).Conjugate(t1) + y5 := (&gfP12{}).Conjugate(fu2) + y3.Conjugate(y3) + y4 := (&gfP12{}).Mul(fu, fu2p) + y4.Conjugate(y4) + + y6 := (&gfP12{}).Mul(fu3, fu3p) + y6.Conjugate(y6) + + t0 := (&gfP12{}).Square(y6) + t0.Mul(t0, y4).Mul(t0, y5) + t1.Mul(y3, y5).Mul(t1, t0) + t0.Mul(t0, y2) + t1.Square(t1).Mul(t1, t0).Square(t1) + t0.Mul(t1, y1) + t1.Mul(t1, y0) + t0.Square(t0).Mul(t0, t1) + + return t0 +} + +func optimalAte(a *twistPoint, b *curvePoint) *gfP12 { + e := miller(a, b) + ret := finalExponentiation(e) + + if a.IsInfinity() || b.IsInfinity() { + ret.SetOne() + } + return ret +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/twist.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/twist.go new file mode 100644 index 0000000000..0c2f80d4ed --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/twist.go @@ -0,0 +1,204 @@ +package bn256 + +import ( + "math/big" +) + +// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are +// kept in Jacobian form and t=z² when valid. The group G₂ is the set of +// n-torsion points of this curve over GF(p²) (where n = Order) +type twistPoint struct { + x, y, z, t gfP2 +} + +var twistB = &gfP2{ + gfP{0x38e7ecccd1dcff67, 0x65f0b37d93ce0d3e, 0xd749d0dd22ac00aa, 0x0141b9ce4a688d4d}, + gfP{0x3bf938e377b802a8, 0x020b1b273633535d, 0x26b7edf049755260, 0x2514c6324384a86d}, +} + +// twistGen is the generator of group G₂. +var twistGen = &twistPoint{ + gfP2{ + gfP{0xafb4737da84c6140, 0x6043dd5a5802d8c4, 0x09e950fc52a02f86, 0x14fef0833aea7b6b}, + gfP{0x8e83b5d102bc2026, 0xdceb1935497b0172, 0xfbb8264797811adf, 0x19573841af96503b}, + }, + gfP2{ + gfP{0x64095b56c71856ee, 0xdc57f922327d3cbb, 0x55f935be33351076, 0x0da4a0e693fd6482}, + gfP{0x619dfa9d886be9f6, 0xfe7fd297f59e9b78, 0xff9e1a62231b7dfe, 0x28fd7eebae9e4206}, + }, + gfP2{*newGFp(0), *newGFp(1)}, + gfP2{*newGFp(0), *newGFp(1)}, +} + +func (c *twistPoint) String() string { + c.MakeAffine() + x, y := gfP2Decode(&c.x), gfP2Decode(&c.y) + return "(" + x.String() + ", " + y.String() + ")" +} + +func (c *twistPoint) Set(a *twistPoint) { + c.x.Set(&a.x) + c.y.Set(&a.y) + c.z.Set(&a.z) + c.t.Set(&a.t) +} + +// IsOnCurve returns true iff c is on the curve. +func (c *twistPoint) IsOnCurve() bool { + c.MakeAffine() + if c.IsInfinity() { + return true + } + + y2, x3 := &gfP2{}, &gfP2{} + y2.Square(&c.y) + x3.Square(&c.x).Mul(x3, &c.x).Add(x3, twistB) + + if *y2 != *x3 { + return false + } + cneg := &twistPoint{} + cneg.Mul(c, Order) + return cneg.z.IsZero() +} + +func (c *twistPoint) SetInfinity() { + c.x.SetZero() + c.y.SetOne() + c.z.SetZero() + c.t.SetZero() +} + +func (c *twistPoint) IsInfinity() bool { + return c.z.IsZero() +} + +func (c *twistPoint) Add(a, b *twistPoint) { + // For additional comments, see the same function in curve.go. + + if a.IsInfinity() { + c.Set(b) + return + } + if b.IsInfinity() { + c.Set(a) + return + } + + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 + z12 := (&gfP2{}).Square(&a.z) + z22 := (&gfP2{}).Square(&b.z) + u1 := (&gfP2{}).Mul(&a.x, z22) + u2 := (&gfP2{}).Mul(&b.x, z12) + + t := (&gfP2{}).Mul(&b.z, z22) + s1 := (&gfP2{}).Mul(&a.y, t) + + t.Mul(&a.z, z12) + s2 := (&gfP2{}).Mul(&b.y, t) + + h := (&gfP2{}).Sub(u2, u1) + xEqual := h.IsZero() + + t.Add(h, h) + i := (&gfP2{}).Square(t) + j := (&gfP2{}).Mul(h, i) + + t.Sub(s2, s1) + yEqual := t.IsZero() + if xEqual && yEqual { + c.Double(a) + return + } + r := (&gfP2{}).Add(t, t) + + v := (&gfP2{}).Mul(u1, i) + + t4 := (&gfP2{}).Square(r) + t.Add(v, v) + t6 := (&gfP2{}).Sub(t4, j) + c.x.Sub(t6, t) + + t.Sub(v, &c.x) // t7 + t4.Mul(s1, j) // t8 + t6.Add(t4, t4) // t9 + t4.Mul(r, t) // t10 + c.y.Sub(t4, t6) + + t.Add(&a.z, &b.z) // t11 + t4.Square(t) // t12 + t.Sub(t4, z12) // t13 + t4.Sub(t, z22) // t14 + c.z.Mul(t4, h) +} + +func (c *twistPoint) Double(a *twistPoint) { + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 + A := (&gfP2{}).Square(&a.x) + B := (&gfP2{}).Square(&a.y) + C := (&gfP2{}).Square(B) + + t := (&gfP2{}).Add(&a.x, B) + t2 := (&gfP2{}).Square(t) + t.Sub(t2, A) + t2.Sub(t, C) + d := (&gfP2{}).Add(t2, t2) + t.Add(A, A) + e := (&gfP2{}).Add(t, A) + f := (&gfP2{}).Square(e) + + t.Add(d, d) + c.x.Sub(f, t) + + t.Add(C, C) + t2.Add(t, t) + t.Add(t2, t2) + c.y.Sub(d, &c.x) + t2.Mul(e, &c.y) + c.y.Sub(t2, t) + + t.Mul(&a.y, &a.z) + c.z.Add(t, t) +} + +func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int) { + sum, t := &twistPoint{}, &twistPoint{} + + for i := scalar.BitLen(); i >= 0; i-- { + t.Double(sum) + if scalar.Bit(i) != 0 { + sum.Add(t, a) + } else { + sum.Set(t) + } + } + + c.Set(sum) +} + +func (c *twistPoint) MakeAffine() { + if c.z.IsOne() { + return + } else if c.z.IsZero() { + c.x.SetZero() + c.y.SetOne() + c.t.SetZero() + return + } + + zInv := (&gfP2{}).Invert(&c.z) + t := (&gfP2{}).Mul(&c.y, zInv) + zInv2 := (&gfP2{}).Square(zInv) + c.y.Mul(t, zInv2) + t.Mul(&c.x, zInv2) + c.x.Set(t) + c.z.SetOne() + c.t.SetOne() +} + +func (c *twistPoint) Neg(a *twistPoint) { + c.x.Set(&a.x) + c.y.Neg(&a.y) + c.z.Set(&a.z) + c.t.SetZero() +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/bn256.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/bn256.go new file mode 100644 index 0000000000..e0402e51f0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/bn256.go @@ -0,0 +1,459 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bn256 implements a particular bilinear group. +// +// Bilinear groups are the basis of many of the new cryptographic protocols +// that have been proposed over the past decade. They consist of a triplet of +// groups (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ +// (where gₓ is a generator of the respective group). That function is called +// a pairing function. +// +// This package specifically implements the Optimal Ate pairing over a 256-bit +// Barreto-Naehrig curve as described in +// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible +// with the implementation described in that paper. +// +// (This package previously claimed to operate at a 128-bit security level. +// However, recent improvements in attacks mean that is no longer true. See +// https://moderncrypto.org/mail-archive/curves/2016/000740.html.) +package bn256 + +import ( + "crypto/rand" + "errors" + "io" + "math/big" +) + +// BUG(agl): this implementation is not constant time. +// TODO(agl): keep GF(p²) elements in Mongomery form. + +// G1 is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type G1 struct { + p *curvePoint +} + +// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r. +func RandomG1(r io.Reader) (*big.Int, *G1, error) { + var k *big.Int + var err error + + for { + k, err = rand.Int(r, Order) + if err != nil { + return nil, nil, err + } + if k.Sign() > 0 { + break + } + } + + return k, new(G1).ScalarBaseMult(k), nil +} + +func (e *G1) String() string { + return "bn256.G1" + e.p.String() +} + +// CurvePoints returns p's curve points in big integer +func (e *G1) CurvePoints() (*big.Int, *big.Int, *big.Int, *big.Int) { + return e.p.x, e.p.y, e.p.z, e.p.t +} + +// ScalarBaseMult sets e to g*k where g is the generator of the group and +// then returns e. +func (e *G1) ScalarBaseMult(k *big.Int) *G1 { + if e.p == nil { + e.p = newCurvePoint(nil) + } + e.p.Mul(curveGen, k, new(bnPool)) + return e +} + +// ScalarMult sets e to a*k and then returns e. +func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { + if e.p == nil { + e.p = newCurvePoint(nil) + } + e.p.Mul(a.p, k, new(bnPool)) + return e +} + +// Add sets e to a+b and then returns e. +// BUG(agl): this function is not complete: a==b fails. +func (e *G1) Add(a, b *G1) *G1 { + if e.p == nil { + e.p = newCurvePoint(nil) + } + e.p.Add(a.p, b.p, new(bnPool)) + return e +} + +// Neg sets e to -a and then returns e. +func (e *G1) Neg(a *G1) *G1 { + if e.p == nil { + e.p = newCurvePoint(nil) + } + e.p.Negative(a.p) + return e +} + +// Marshal converts n to a byte slice. +func (e *G1) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if e.p.IsInfinity() { + return make([]byte, numBytes*2) + } + + e.p.MakeAffine(nil) + + xBytes := new(big.Int).Mod(e.p.x, P).Bytes() + yBytes := new(big.Int).Mod(e.p.y, P).Bytes() + + ret := make([]byte, numBytes*2) + copy(ret[1*numBytes-len(xBytes):], xBytes) + copy(ret[2*numBytes-len(yBytes):], yBytes) + + return ret +} + +// Unmarshal sets e to the result of converting the output of Marshal back into +// a group element and then returns e. +func (e *G1) Unmarshal(m []byte) ([]byte, error) { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + if len(m) != 2*numBytes { + return nil, errors.New("bn256: not enough data") + } + // Unmarshal the points and check their caps + if e.p == nil { + e.p = newCurvePoint(nil) + } + e.p.x.SetBytes(m[0*numBytes : 1*numBytes]) + if e.p.x.Cmp(P) >= 0 { + return nil, errors.New("bn256: coordinate exceeds modulus") + } + e.p.y.SetBytes(m[1*numBytes : 2*numBytes]) + if e.p.y.Cmp(P) >= 0 { + return nil, errors.New("bn256: coordinate exceeds modulus") + } + // Ensure the point is on the curve + if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 { + // This is the point at infinity. + e.p.y.SetInt64(1) + e.p.z.SetInt64(0) + e.p.t.SetInt64(0) + } else { + e.p.z.SetInt64(1) + e.p.t.SetInt64(1) + + if !e.p.IsOnCurve() { + return nil, errors.New("bn256: malformed point") + } + } + return m[2*numBytes:], nil +} + +// G2 is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type G2 struct { + p *twistPoint +} + +// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r. +func RandomG2(r io.Reader) (*big.Int, *G2, error) { + var k *big.Int + var err error + + for { + k, err = rand.Int(r, Order) + if err != nil { + return nil, nil, err + } + if k.Sign() > 0 { + break + } + } + + return k, new(G2).ScalarBaseMult(k), nil +} + +func (e *G2) String() string { + return "bn256.G2" + e.p.String() +} + +// CurvePoints returns the curve points of p which includes the real +// and imaginary parts of the curve point. +func (e *G2) CurvePoints() (*gfP2, *gfP2, *gfP2, *gfP2) { + return e.p.x, e.p.y, e.p.z, e.p.t +} + +// ScalarBaseMult sets e to g*k where g is the generator of the group and +// then returns out. +func (e *G2) ScalarBaseMult(k *big.Int) *G2 { + if e.p == nil { + e.p = newTwistPoint(nil) + } + e.p.Mul(twistGen, k, new(bnPool)) + return e +} + +// ScalarMult sets e to a*k and then returns e. +func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { + if e.p == nil { + e.p = newTwistPoint(nil) + } + e.p.Mul(a.p, k, new(bnPool)) + return e +} + +// Add sets e to a+b and then returns e. +// BUG(agl): this function is not complete: a==b fails. +func (e *G2) Add(a, b *G2) *G2 { + if e.p == nil { + e.p = newTwistPoint(nil) + } + e.p.Add(a.p, b.p, new(bnPool)) + return e +} + +// Marshal converts n into a byte slice. +func (n *G2) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if n.p.IsInfinity() { + return make([]byte, numBytes*4) + } + + n.p.MakeAffine(nil) + + xxBytes := new(big.Int).Mod(n.p.x.x, P).Bytes() + xyBytes := new(big.Int).Mod(n.p.x.y, P).Bytes() + yxBytes := new(big.Int).Mod(n.p.y.x, P).Bytes() + yyBytes := new(big.Int).Mod(n.p.y.y, P).Bytes() + + ret := make([]byte, numBytes*4) + copy(ret[1*numBytes-len(xxBytes):], xxBytes) + copy(ret[2*numBytes-len(xyBytes):], xyBytes) + copy(ret[3*numBytes-len(yxBytes):], yxBytes) + copy(ret[4*numBytes-len(yyBytes):], yyBytes) + + return ret +} + +// Unmarshal sets e to the result of converting the output of Marshal back into +// a group element and then returns e. +func (e *G2) Unmarshal(m []byte) ([]byte, error) { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + if len(m) != 4*numBytes { + return nil, errors.New("bn256: not enough data") + } + // Unmarshal the points and check their caps + if e.p == nil { + e.p = newTwistPoint(nil) + } + e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes]) + if e.p.x.x.Cmp(P) >= 0 { + return nil, errors.New("bn256: coordinate exceeds modulus") + } + e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes]) + if e.p.x.y.Cmp(P) >= 0 { + return nil, errors.New("bn256: coordinate exceeds modulus") + } + e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes]) + if e.p.y.x.Cmp(P) >= 0 { + return nil, errors.New("bn256: coordinate exceeds modulus") + } + e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes]) + if e.p.y.y.Cmp(P) >= 0 { + return nil, errors.New("bn256: coordinate exceeds modulus") + } + // Ensure the point is on the curve + if e.p.x.x.Sign() == 0 && + e.p.x.y.Sign() == 0 && + e.p.y.x.Sign() == 0 && + e.p.y.y.Sign() == 0 { + // This is the point at infinity. + e.p.y.SetOne() + e.p.z.SetZero() + e.p.t.SetZero() + } else { + e.p.z.SetOne() + e.p.t.SetOne() + + if !e.p.IsOnCurve() { + return nil, errors.New("bn256: malformed point") + } + } + return m[4*numBytes:], nil +} + +// GT is an abstract cyclic group. The zero value is suitable for use as the +// output of an operation, but cannot be used as an input. +type GT struct { + p *gfP12 +} + +func (g *GT) String() string { + return "bn256.GT" + g.p.String() +} + +// ScalarMult sets e to a*k and then returns e. +func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { + if e.p == nil { + e.p = newGFp12(nil) + } + e.p.Exp(a.p, k, new(bnPool)) + return e +} + +// Add sets e to a+b and then returns e. +func (e *GT) Add(a, b *GT) *GT { + if e.p == nil { + e.p = newGFp12(nil) + } + e.p.Mul(a.p, b.p, new(bnPool)) + return e +} + +// Neg sets e to -a and then returns e. +func (e *GT) Neg(a *GT) *GT { + if e.p == nil { + e.p = newGFp12(nil) + } + e.p.Invert(a.p, new(bnPool)) + return e +} + +// Marshal converts n into a byte slice. +func (n *GT) Marshal() []byte { + n.p.Minimal() + + xxxBytes := n.p.x.x.x.Bytes() + xxyBytes := n.p.x.x.y.Bytes() + xyxBytes := n.p.x.y.x.Bytes() + xyyBytes := n.p.x.y.y.Bytes() + xzxBytes := n.p.x.z.x.Bytes() + xzyBytes := n.p.x.z.y.Bytes() + yxxBytes := n.p.y.x.x.Bytes() + yxyBytes := n.p.y.x.y.Bytes() + yyxBytes := n.p.y.y.x.Bytes() + yyyBytes := n.p.y.y.y.Bytes() + yzxBytes := n.p.y.z.x.Bytes() + yzyBytes := n.p.y.z.y.Bytes() + + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + ret := make([]byte, numBytes*12) + copy(ret[1*numBytes-len(xxxBytes):], xxxBytes) + copy(ret[2*numBytes-len(xxyBytes):], xxyBytes) + copy(ret[3*numBytes-len(xyxBytes):], xyxBytes) + copy(ret[4*numBytes-len(xyyBytes):], xyyBytes) + copy(ret[5*numBytes-len(xzxBytes):], xzxBytes) + copy(ret[6*numBytes-len(xzyBytes):], xzyBytes) + copy(ret[7*numBytes-len(yxxBytes):], yxxBytes) + copy(ret[8*numBytes-len(yxyBytes):], yxyBytes) + copy(ret[9*numBytes-len(yyxBytes):], yyxBytes) + copy(ret[10*numBytes-len(yyyBytes):], yyyBytes) + copy(ret[11*numBytes-len(yzxBytes):], yzxBytes) + copy(ret[12*numBytes-len(yzyBytes):], yzyBytes) + + return ret +} + +// Unmarshal sets e to the result of converting the output of Marshal back into +// a group element and then returns e. +func (e *GT) Unmarshal(m []byte) (*GT, bool) { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if len(m) != 12*numBytes { + return nil, false + } + + if e.p == nil { + e.p = newGFp12(nil) + } + + e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes]) + e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes]) + e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes]) + e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes]) + e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes]) + e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes]) + e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes]) + e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes]) + e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes]) + e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes]) + e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes]) + e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes]) + + return e, true +} + +// Pair calculates an Optimal Ate pairing. +func Pair(g1 *G1, g2 *G2) *GT { + return >{optimalAte(g2.p, g1.p, new(bnPool))} +} + +// PairingCheck calculates the Optimal Ate pairing for a set of points. +func PairingCheck(a []*G1, b []*G2) bool { + pool := new(bnPool) + + acc := newGFp12(pool) + acc.SetOne() + + for i := 0; i < len(a); i++ { + if a[i].p.IsInfinity() || b[i].p.IsInfinity() { + continue + } + acc.Mul(acc, miller(b[i].p, a[i].p, pool), pool) + } + ret := finalExponentiation(acc, pool) + acc.Put(pool) + + return ret.IsOne() +} + +// bnPool implements a tiny cache of *big.Int objects that's used to reduce the +// number of allocations made during processing. +type bnPool struct { + bns []*big.Int + count int +} + +func (pool *bnPool) Get() *big.Int { + if pool == nil { + return new(big.Int) + } + + pool.count++ + l := len(pool.bns) + if l == 0 { + return new(big.Int) + } + + bn := pool.bns[l-1] + pool.bns = pool.bns[:l-1] + return bn +} + +func (pool *bnPool) Put(bn *big.Int) { + if pool == nil { + return + } + pool.bns = append(pool.bns, bn) + pool.count-- +} + +func (pool *bnPool) Count() int { + return pool.count +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/bn256_test.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/bn256_test.go new file mode 100644 index 0000000000..a4497ada9b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/bn256_test.go @@ -0,0 +1,311 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +import ( + "bytes" + "crypto/rand" + "math/big" + "testing" +) + +func TestGFp2Invert(t *testing.T) { + pool := new(bnPool) + + a := newGFp2(pool) + a.x.SetString("23423492374", 10) + a.y.SetString("12934872398472394827398470", 10) + + inv := newGFp2(pool) + inv.Invert(a, pool) + + b := newGFp2(pool).Mul(inv, a, pool) + if b.x.Int64() != 0 || b.y.Int64() != 1 { + t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y) + } + + a.Put(pool) + b.Put(pool) + inv.Put(pool) + + if c := pool.Count(); c > 0 { + t.Errorf("Pool count non-zero: %d\n", c) + } +} + +func isZero(n *big.Int) bool { + return new(big.Int).Mod(n, P).Int64() == 0 +} + +func isOne(n *big.Int) bool { + return new(big.Int).Mod(n, P).Int64() == 1 +} + +func TestGFp6Invert(t *testing.T) { + pool := new(bnPool) + + a := newGFp6(pool) + a.x.x.SetString("239487238491", 10) + a.x.y.SetString("2356249827341", 10) + a.y.x.SetString("082659782", 10) + a.y.y.SetString("182703523765", 10) + a.z.x.SetString("978236549263", 10) + a.z.y.SetString("64893242", 10) + + inv := newGFp6(pool) + inv.Invert(a, pool) + + b := newGFp6(pool).Mul(inv, a, pool) + if !isZero(b.x.x) || + !isZero(b.x.y) || + !isZero(b.y.x) || + !isZero(b.y.y) || + !isZero(b.z.x) || + !isOne(b.z.y) { + t.Fatalf("bad result for a^-1*a: %s", b) + } + + a.Put(pool) + b.Put(pool) + inv.Put(pool) + + if c := pool.Count(); c > 0 { + t.Errorf("Pool count non-zero: %d\n", c) + } +} + +func TestGFp12Invert(t *testing.T) { + pool := new(bnPool) + + a := newGFp12(pool) + a.x.x.x.SetString("239846234862342323958623", 10) + a.x.x.y.SetString("2359862352529835623", 10) + a.x.y.x.SetString("928836523", 10) + a.x.y.y.SetString("9856234", 10) + a.x.z.x.SetString("235635286", 10) + a.x.z.y.SetString("5628392833", 10) + a.y.x.x.SetString("252936598265329856238956532167968", 10) + a.y.x.y.SetString("23596239865236954178968", 10) + a.y.y.x.SetString("95421692834", 10) + a.y.y.y.SetString("236548", 10) + a.y.z.x.SetString("924523", 10) + a.y.z.y.SetString("12954623", 10) + + inv := newGFp12(pool) + inv.Invert(a, pool) + + b := newGFp12(pool).Mul(inv, a, pool) + if !isZero(b.x.x.x) || + !isZero(b.x.x.y) || + !isZero(b.x.y.x) || + !isZero(b.x.y.y) || + !isZero(b.x.z.x) || + !isZero(b.x.z.y) || + !isZero(b.y.x.x) || + !isZero(b.y.x.y) || + !isZero(b.y.y.x) || + !isZero(b.y.y.y) || + !isZero(b.y.z.x) || + !isOne(b.y.z.y) { + t.Fatalf("bad result for a^-1*a: %s", b) + } + + a.Put(pool) + b.Put(pool) + inv.Put(pool) + + if c := pool.Count(); c > 0 { + t.Errorf("Pool count non-zero: %d\n", c) + } +} + +func TestCurveImpl(t *testing.T) { + pool := new(bnPool) + + g := &curvePoint{ + pool.Get().SetInt64(1), + pool.Get().SetInt64(-2), + pool.Get().SetInt64(1), + pool.Get().SetInt64(0), + } + + x := pool.Get().SetInt64(32498273234) + X := newCurvePoint(pool).Mul(g, x, pool) + + y := pool.Get().SetInt64(98732423523) + Y := newCurvePoint(pool).Mul(g, y, pool) + + s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool) + s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool) + + if s1.x.Cmp(s2.x) != 0 || + s2.x.Cmp(s1.x) != 0 { + t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y) + } + + pool.Put(x) + X.Put(pool) + pool.Put(y) + Y.Put(pool) + s1.Put(pool) + s2.Put(pool) + g.Put(pool) + + if c := pool.Count(); c > 0 { + t.Errorf("Pool count non-zero: %d\n", c) + } +} + +func TestOrderG1(t *testing.T) { + g := new(G1).ScalarBaseMult(Order) + if !g.p.IsInfinity() { + t.Error("G1 has incorrect order") + } + + one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) + g.Add(g, one) + g.p.MakeAffine(nil) + if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 { + t.Errorf("1+0 != 1 in G1") + } +} + +func TestOrderG2(t *testing.T) { + g := new(G2).ScalarBaseMult(Order) + if !g.p.IsInfinity() { + t.Error("G2 has incorrect order") + } + + one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) + g.Add(g, one) + g.p.MakeAffine(nil) + if g.p.x.x.Cmp(one.p.x.x) != 0 || + g.p.x.y.Cmp(one.p.x.y) != 0 || + g.p.y.x.Cmp(one.p.y.x) != 0 || + g.p.y.y.Cmp(one.p.y.y) != 0 { + t.Errorf("1+0 != 1 in G2") + } +} + +func TestOrderGT(t *testing.T) { + gt := Pair(&G1{curveGen}, &G2{twistGen}) + g := new(GT).ScalarMult(gt, Order) + if !g.p.IsOne() { + t.Error("GT has incorrect order") + } +} + +func TestBilinearity(t *testing.T) { + for i := 0; i < 2; i++ { + a, p1, _ := RandomG1(rand.Reader) + b, p2, _ := RandomG2(rand.Reader) + e1 := Pair(p1, p2) + + e2 := Pair(&G1{curveGen}, &G2{twistGen}) + e2.ScalarMult(e2, a) + e2.ScalarMult(e2, b) + + minusE2 := new(GT).Neg(e2) + e1.Add(e1, minusE2) + + if !e1.p.IsOne() { + t.Fatalf("bad pairing result: %s", e1) + } + } +} + +func TestG1Marshal(t *testing.T) { + g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) + form := g.Marshal() + _, err := new(G1).Unmarshal(form) + if err != nil { + t.Fatalf("failed to unmarshal") + } + + g.ScalarBaseMult(Order) + form = g.Marshal() + + g2 := new(G1) + if _, err = g2.Unmarshal(form); err != nil { + t.Fatalf("failed to unmarshal ∞") + } + if !g2.p.IsInfinity() { + t.Fatalf("∞ unmarshaled incorrectly") + } +} + +func TestG2Marshal(t *testing.T) { + g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) + form := g.Marshal() + _, err := new(G2).Unmarshal(form) + if err != nil { + t.Fatalf("failed to unmarshal") + } + + g.ScalarBaseMult(Order) + form = g.Marshal() + g2 := new(G2) + if _, err = g2.Unmarshal(form); err != nil { + t.Fatalf("failed to unmarshal ∞") + } + if !g2.p.IsInfinity() { + t.Fatalf("∞ unmarshaled incorrectly") + } +} + +func TestG1Identity(t *testing.T) { + g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0)) + if !g.p.IsInfinity() { + t.Error("failure") + } +} + +func TestG2Identity(t *testing.T) { + g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0)) + if !g.p.IsInfinity() { + t.Error("failure") + } +} + +func TestTripartiteDiffieHellman(t *testing.T) { + a, _ := rand.Int(rand.Reader, Order) + b, _ := rand.Int(rand.Reader, Order) + c, _ := rand.Int(rand.Reader, Order) + + pa := new(G1) + pa.Unmarshal(new(G1).ScalarBaseMult(a).Marshal()) + qa := new(G2) + qa.Unmarshal(new(G2).ScalarBaseMult(a).Marshal()) + pb := new(G1) + pb.Unmarshal(new(G1).ScalarBaseMult(b).Marshal()) + qb := new(G2) + qb.Unmarshal(new(G2).ScalarBaseMult(b).Marshal()) + pc := new(G1) + pc.Unmarshal(new(G1).ScalarBaseMult(c).Marshal()) + qc := new(G2) + qc.Unmarshal(new(G2).ScalarBaseMult(c).Marshal()) + + k1 := Pair(pb, qc) + k1.ScalarMult(k1, a) + k1Bytes := k1.Marshal() + + k2 := Pair(pc, qa) + k2.ScalarMult(k2, b) + k2Bytes := k2.Marshal() + + k3 := Pair(pa, qb) + k3.ScalarMult(k3, c) + k3Bytes := k3.Marshal() + + if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) { + t.Errorf("keys didn't agree") + } +} + +func BenchmarkPairing(b *testing.B) { + for i := 0; i < b.N; i++ { + Pair(&G1{curveGen}, &G2{twistGen}) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/constants.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/constants.go new file mode 100644 index 0000000000..ab649d7f3f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/constants.go @@ -0,0 +1,44 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +import ( + "math/big" +) + +func bigFromBase10(s string) *big.Int { + n, _ := new(big.Int).SetString(s, 10) + return n +} + +// u is the BN parameter that determines the prime: 1868033³. +var u = bigFromBase10("4965661367192848881") + +// p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1. +var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583") + +// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1. +var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617") + +// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9. +var xiToPMinus1Over6 = &gfP2{bigFromBase10("16469823323077808223889137241176536799009286646108169935659301613961712198316"), bigFromBase10("8376118865763821496583973867626364092589906065868298776909617916018768340080")} + +// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9. +var xiToPMinus1Over3 = &gfP2{bigFromBase10("10307601595873709700152284273816112264069230130616436755625194854815875713954"), bigFromBase10("21575463638280843010398324269430826099269044274347216827212613867836435027261")} + +// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9. +var xiToPMinus1Over2 = &gfP2{bigFromBase10("3505843767911556378687030309984248845540243509899259641013678093033130930403"), bigFromBase10("2821565182194536844548159561693502659359617185244120367078079554186484126554")} + +// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9. +var xiToPSquaredMinus1Over3 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556616") + +// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p). +var xiTo2PSquaredMinus2Over3 = bigFromBase10("2203960485148121921418603742825762020974279258880205651966") + +// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p). +var xiToPSquaredMinus1Over6 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556617") + +// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9. +var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19937756971775647987995932169929341994314640652964949448313374472400716661030"), bigFromBase10("2581911344467009335267311115468803099551665605076196740867805258568234346338")} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/curve.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/curve.go new file mode 100644 index 0000000000..819cb81da7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/curve.go @@ -0,0 +1,286 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +import ( + "math/big" +) + +// curvePoint implements the elliptic curve y²=x³+3. Points are kept in +// Jacobian form and t=z² when valid. G₁ is the set of points of this curve on +// GF(p). +type curvePoint struct { + x, y, z, t *big.Int +} + +var curveB = new(big.Int).SetInt64(3) + +// curveGen is the generator of G₁. +var curveGen = &curvePoint{ + new(big.Int).SetInt64(1), + new(big.Int).SetInt64(2), + new(big.Int).SetInt64(1), + new(big.Int).SetInt64(1), +} + +func newCurvePoint(pool *bnPool) *curvePoint { + return &curvePoint{ + pool.Get(), + pool.Get(), + pool.Get(), + pool.Get(), + } +} + +func (c *curvePoint) String() string { + c.MakeAffine(new(bnPool)) + return "(" + c.x.String() + ", " + c.y.String() + ")" +} + +func (c *curvePoint) Put(pool *bnPool) { + pool.Put(c.x) + pool.Put(c.y) + pool.Put(c.z) + pool.Put(c.t) +} + +func (c *curvePoint) Set(a *curvePoint) { + c.x.Set(a.x) + c.y.Set(a.y) + c.z.Set(a.z) + c.t.Set(a.t) +} + +// IsOnCurve returns true iff c is on the curve where c must be in affine form. +func (c *curvePoint) IsOnCurve() bool { + yy := new(big.Int).Mul(c.y, c.y) + xxx := new(big.Int).Mul(c.x, c.x) + xxx.Mul(xxx, c.x) + yy.Sub(yy, xxx) + yy.Sub(yy, curveB) + if yy.Sign() < 0 || yy.Cmp(P) >= 0 { + yy.Mod(yy, P) + } + return yy.Sign() == 0 +} + +func (c *curvePoint) SetInfinity() { + c.z.SetInt64(0) +} + +func (c *curvePoint) IsInfinity() bool { + return c.z.Sign() == 0 +} + +func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) { + if a.IsInfinity() { + c.Set(b) + return + } + if b.IsInfinity() { + c.Set(a) + return + } + + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 + + // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] + // by [u1:s1:z1·z2] and [u2:s2:z1·z2] + // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³ + z1z1 := pool.Get().Mul(a.z, a.z) + z1z1.Mod(z1z1, P) + z2z2 := pool.Get().Mul(b.z, b.z) + z2z2.Mod(z2z2, P) + u1 := pool.Get().Mul(a.x, z2z2) + u1.Mod(u1, P) + u2 := pool.Get().Mul(b.x, z1z1) + u2.Mod(u2, P) + + t := pool.Get().Mul(b.z, z2z2) + t.Mod(t, P) + s1 := pool.Get().Mul(a.y, t) + s1.Mod(s1, P) + + t.Mul(a.z, z1z1) + t.Mod(t, P) + s2 := pool.Get().Mul(b.y, t) + s2.Mod(s2, P) + + // Compute x = (2h)²(s²-u1-u2) + // where s = (s2-s1)/(u2-u1) is the slope of the line through + // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. + // This is also: + // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1) + // = r² - j - 2v + // with the notations below. + h := pool.Get().Sub(u2, u1) + xEqual := h.Sign() == 0 + + t.Add(h, h) + // i = 4h² + i := pool.Get().Mul(t, t) + i.Mod(i, P) + // j = 4h³ + j := pool.Get().Mul(h, i) + j.Mod(j, P) + + t.Sub(s2, s1) + yEqual := t.Sign() == 0 + if xEqual && yEqual { + c.Double(a, pool) + return + } + r := pool.Get().Add(t, t) + + v := pool.Get().Mul(u1, i) + v.Mod(v, P) + + // t4 = 4(s2-s1)² + t4 := pool.Get().Mul(r, r) + t4.Mod(t4, P) + t.Add(v, v) + t6 := pool.Get().Sub(t4, j) + c.x.Sub(t6, t) + + // Set y = -(2h)³(s1 + s*(x/4h²-u1)) + // This is also + // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j + t.Sub(v, c.x) // t7 + t4.Mul(s1, j) // t8 + t4.Mod(t4, P) + t6.Add(t4, t4) // t9 + t4.Mul(r, t) // t10 + t4.Mod(t4, P) + c.y.Sub(t4, t6) + + // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2 + t.Add(a.z, b.z) // t11 + t4.Mul(t, t) // t12 + t4.Mod(t4, P) + t.Sub(t4, z1z1) // t13 + t4.Sub(t, z2z2) // t14 + c.z.Mul(t4, h) + c.z.Mod(c.z, P) + + pool.Put(z1z1) + pool.Put(z2z2) + pool.Put(u1) + pool.Put(u2) + pool.Put(t) + pool.Put(s1) + pool.Put(s2) + pool.Put(h) + pool.Put(i) + pool.Put(j) + pool.Put(r) + pool.Put(v) + pool.Put(t4) + pool.Put(t6) +} + +func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 + A := pool.Get().Mul(a.x, a.x) + A.Mod(A, P) + B := pool.Get().Mul(a.y, a.y) + B.Mod(B, P) + C_ := pool.Get().Mul(B, B) + C_.Mod(C_, P) + + t := pool.Get().Add(a.x, B) + t2 := pool.Get().Mul(t, t) + t2.Mod(t2, P) + t.Sub(t2, A) + t2.Sub(t, C_) + d := pool.Get().Add(t2, t2) + t.Add(A, A) + e := pool.Get().Add(t, A) + f := pool.Get().Mul(e, e) + f.Mod(f, P) + + t.Add(d, d) + c.x.Sub(f, t) + + t.Add(C_, C_) + t2.Add(t, t) + t.Add(t2, t2) + c.y.Sub(d, c.x) + t2.Mul(e, c.y) + t2.Mod(t2, P) + c.y.Sub(t2, t) + + t.Mul(a.y, a.z) + t.Mod(t, P) + c.z.Add(t, t) + + pool.Put(A) + pool.Put(B) + pool.Put(C_) + pool.Put(t) + pool.Put(t2) + pool.Put(d) + pool.Put(e) + pool.Put(f) +} + +func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint { + sum := newCurvePoint(pool) + sum.SetInfinity() + t := newCurvePoint(pool) + + for i := scalar.BitLen(); i >= 0; i-- { + t.Double(sum, pool) + if scalar.Bit(i) != 0 { + sum.Add(t, a, pool) + } else { + sum.Set(t) + } + } + + c.Set(sum) + sum.Put(pool) + t.Put(pool) + return c +} + +// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets +// c to 0 : 1 : 0. +func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { + if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { + return c + } + if c.IsInfinity() { + c.x.SetInt64(0) + c.y.SetInt64(1) + c.z.SetInt64(0) + c.t.SetInt64(0) + return c + } + zInv := pool.Get().ModInverse(c.z, P) + t := pool.Get().Mul(c.y, zInv) + t.Mod(t, P) + zInv2 := pool.Get().Mul(zInv, zInv) + zInv2.Mod(zInv2, P) + c.y.Mul(t, zInv2) + c.y.Mod(c.y, P) + t.Mul(c.x, zInv2) + t.Mod(t, P) + c.x.Set(t) + c.z.SetInt64(1) + c.t.SetInt64(1) + + pool.Put(zInv) + pool.Put(t) + pool.Put(zInv2) + + return c +} + +func (c *curvePoint) Negative(a *curvePoint) { + c.x.Set(a.x) + c.y.Neg(a.y) + c.z.Set(a.z) + c.t.SetInt64(0) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/example_test.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/example_test.go new file mode 100644 index 0000000000..b2d19807a2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/example_test.go @@ -0,0 +1,43 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +import ( + "crypto/rand" +) + +func ExamplePair() { + // This implements the tripartite Diffie-Hellman algorithm from "A One + // Round Protocol for Tripartite Diffie-Hellman", A. Joux. + // http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf + + // Each of three parties, a, b and c, generate a private value. + a, _ := rand.Int(rand.Reader, Order) + b, _ := rand.Int(rand.Reader, Order) + c, _ := rand.Int(rand.Reader, Order) + + // Then each party calculates g₁ and g₂ times their private value. + pa := new(G1).ScalarBaseMult(a) + qa := new(G2).ScalarBaseMult(a) + + pb := new(G1).ScalarBaseMult(b) + qb := new(G2).ScalarBaseMult(b) + + pc := new(G1).ScalarBaseMult(c) + qc := new(G2).ScalarBaseMult(c) + + // Now each party exchanges its public values with the other two and + // all parties can calculate the shared key. + k1 := Pair(pb, qc) + k1.ScalarMult(k1, a) + + k2 := Pair(pc, qa) + k2.ScalarMult(k2, b) + + k3 := Pair(pa, qb) + k3.ScalarMult(k3, c) + + // k1, k2 and k3 will all be equal. +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp12.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp12.go new file mode 100644 index 0000000000..f084eddf21 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp12.go @@ -0,0 +1,200 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +// For details of the algorithms used, see "Multiplication and Squaring on +// Pairing-Friendly Fields, Devegili et al. +// http://eprint.iacr.org/2006/471.pdf. + +import ( + "math/big" +) + +// gfP12 implements the field of size p¹² as a quadratic extension of gfP6 +// where ω²=τ. +type gfP12 struct { + x, y *gfP6 // value is xω + y +} + +func newGFp12(pool *bnPool) *gfP12 { + return &gfP12{newGFp6(pool), newGFp6(pool)} +} + +func (e *gfP12) String() string { + return "(" + e.x.String() + "," + e.y.String() + ")" +} + +func (e *gfP12) Put(pool *bnPool) { + e.x.Put(pool) + e.y.Put(pool) +} + +func (e *gfP12) Set(a *gfP12) *gfP12 { + e.x.Set(a.x) + e.y.Set(a.y) + return e +} + +func (e *gfP12) SetZero() *gfP12 { + e.x.SetZero() + e.y.SetZero() + return e +} + +func (e *gfP12) SetOne() *gfP12 { + e.x.SetZero() + e.y.SetOne() + return e +} + +func (e *gfP12) Minimal() { + e.x.Minimal() + e.y.Minimal() +} + +func (e *gfP12) IsZero() bool { + e.Minimal() + return e.x.IsZero() && e.y.IsZero() +} + +func (e *gfP12) IsOne() bool { + e.Minimal() + return e.x.IsZero() && e.y.IsOne() +} + +func (e *gfP12) Conjugate(a *gfP12) *gfP12 { + e.x.Negative(a.x) + e.y.Set(a.y) + return a +} + +func (e *gfP12) Negative(a *gfP12) *gfP12 { + e.x.Negative(a.x) + e.y.Negative(a.y) + return e +} + +// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p +func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 { + e.x.Frobenius(a.x, pool) + e.y.Frobenius(a.y, pool) + e.x.MulScalar(e.x, xiToPMinus1Over6, pool) + return e +} + +// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² +func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 { + e.x.FrobeniusP2(a.x) + e.x.MulGFP(e.x, xiToPSquaredMinus1Over6) + e.y.FrobeniusP2(a.y) + return e +} + +func (e *gfP12) Add(a, b *gfP12) *gfP12 { + e.x.Add(a.x, b.x) + e.y.Add(a.y, b.y) + return e +} + +func (e *gfP12) Sub(a, b *gfP12) *gfP12 { + e.x.Sub(a.x, b.x) + e.y.Sub(a.y, b.y) + return e +} + +func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 { + tx := newGFp6(pool) + tx.Mul(a.x, b.y, pool) + t := newGFp6(pool) + t.Mul(b.x, a.y, pool) + tx.Add(tx, t) + + ty := newGFp6(pool) + ty.Mul(a.y, b.y, pool) + t.Mul(a.x, b.x, pool) + t.MulTau(t, pool) + e.y.Add(ty, t) + e.x.Set(tx) + + tx.Put(pool) + ty.Put(pool) + t.Put(pool) + return e +} + +func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 { + e.x.Mul(e.x, b, pool) + e.y.Mul(e.y, b, pool) + return e +} + +func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { + sum := newGFp12(pool) + sum.SetOne() + t := newGFp12(pool) + + for i := power.BitLen() - 1; i >= 0; i-- { + t.Square(sum, pool) + if power.Bit(i) != 0 { + sum.Mul(t, a, pool) + } else { + sum.Set(t) + } + } + + c.Set(sum) + + sum.Put(pool) + t.Put(pool) + + return c +} + +func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 { + // Complex squaring algorithm + v0 := newGFp6(pool) + v0.Mul(a.x, a.y, pool) + + t := newGFp6(pool) + t.MulTau(a.x, pool) + t.Add(a.y, t) + ty := newGFp6(pool) + ty.Add(a.x, a.y) + ty.Mul(ty, t, pool) + ty.Sub(ty, v0) + t.MulTau(v0, pool) + ty.Sub(ty, t) + + e.y.Set(ty) + e.x.Double(v0) + + v0.Put(pool) + t.Put(pool) + ty.Put(pool) + + return e +} + +func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 { + // See "Implementing cryptographic pairings", M. Scott, section 3.2. + // ftp://136.206.11.249/pub/crypto/pairings.pdf + t1 := newGFp6(pool) + t2 := newGFp6(pool) + + t1.Square(a.x, pool) + t2.Square(a.y, pool) + t1.MulTau(t1, pool) + t1.Sub(t2, t1) + t2.Invert(t1, pool) + + e.x.Negative(a.x) + e.y.Set(a.y) + e.MulScalar(e, t2, pool) + + t1.Put(pool) + t2.Put(pool) + + return e +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp2.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp2.go new file mode 100644 index 0000000000..3981f6cb4f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp2.go @@ -0,0 +1,227 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +// For details of the algorithms used, see "Multiplication and Squaring on +// Pairing-Friendly Fields, Devegili et al. +// http://eprint.iacr.org/2006/471.pdf. + +import ( + "math/big" +) + +// gfP2 implements a field of size p² as a quadratic extension of the base +// field where i²=-1. +type gfP2 struct { + x, y *big.Int // value is xi+y. +} + +func newGFp2(pool *bnPool) *gfP2 { + return &gfP2{pool.Get(), pool.Get()} +} + +func (e *gfP2) String() string { + x := new(big.Int).Mod(e.x, P) + y := new(big.Int).Mod(e.y, P) + return "(" + x.String() + "," + y.String() + ")" +} + +func (e *gfP2) Put(pool *bnPool) { + pool.Put(e.x) + pool.Put(e.y) +} + +func (e *gfP2) Set(a *gfP2) *gfP2 { + e.x.Set(a.x) + e.y.Set(a.y) + return e +} + +func (e *gfP2) SetZero() *gfP2 { + e.x.SetInt64(0) + e.y.SetInt64(0) + return e +} + +func (e *gfP2) SetOne() *gfP2 { + e.x.SetInt64(0) + e.y.SetInt64(1) + return e +} + +func (e *gfP2) Minimal() { + if e.x.Sign() < 0 || e.x.Cmp(P) >= 0 { + e.x.Mod(e.x, P) + } + if e.y.Sign() < 0 || e.y.Cmp(P) >= 0 { + e.y.Mod(e.y, P) + } +} + +func (e *gfP2) IsZero() bool { + return e.x.Sign() == 0 && e.y.Sign() == 0 +} + +func (e *gfP2) IsOne() bool { + if e.x.Sign() != 0 { + return false + } + words := e.y.Bits() + return len(words) == 1 && words[0] == 1 +} + +func (e *gfP2) Conjugate(a *gfP2) *gfP2 { + e.y.Set(a.y) + e.x.Neg(a.x) + return e +} + +func (e *gfP2) Negative(a *gfP2) *gfP2 { + e.x.Neg(a.x) + e.y.Neg(a.y) + return e +} + +func (e *gfP2) Add(a, b *gfP2) *gfP2 { + e.x.Add(a.x, b.x) + e.y.Add(a.y, b.y) + return e +} + +func (e *gfP2) Sub(a, b *gfP2) *gfP2 { + e.x.Sub(a.x, b.x) + e.y.Sub(a.y, b.y) + return e +} + +func (e *gfP2) Double(a *gfP2) *gfP2 { + e.x.Lsh(a.x, 1) + e.y.Lsh(a.y, 1) + return e +} + +func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { + sum := newGFp2(pool) + sum.SetOne() + t := newGFp2(pool) + + for i := power.BitLen() - 1; i >= 0; i-- { + t.Square(sum, pool) + if power.Bit(i) != 0 { + sum.Mul(t, a, pool) + } else { + sum.Set(t) + } + } + + c.Set(sum) + + sum.Put(pool) + t.Put(pool) + + return c +} + +// See "Multiplication and Squaring in Pairing-Friendly Fields", +// http://eprint.iacr.org/2006/471.pdf +func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 { + tx := pool.Get().Mul(a.x, b.y) + t := pool.Get().Mul(b.x, a.y) + tx.Add(tx, t) + tx.Mod(tx, P) + + ty := pool.Get().Mul(a.y, b.y) + t.Mul(a.x, b.x) + ty.Sub(ty, t) + e.y.Mod(ty, P) + e.x.Set(tx) + + pool.Put(tx) + pool.Put(ty) + pool.Put(t) + + return e +} + +func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 { + e.x.Mul(a.x, b) + e.y.Mul(a.y, b) + return e +} + +// MulXi sets e=ξa where ξ=i+9 and then returns e. +func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 { + // (xi+y)(i+3) = (9x+y)i+(9y-x) + tx := pool.Get().Lsh(a.x, 3) + tx.Add(tx, a.x) + tx.Add(tx, a.y) + + ty := pool.Get().Lsh(a.y, 3) + ty.Add(ty, a.y) + ty.Sub(ty, a.x) + + e.x.Set(tx) + e.y.Set(ty) + + pool.Put(tx) + pool.Put(ty) + + return e +} + +func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 { + // Complex squaring algorithm: + // (xi+b)² = (x+y)(y-x) + 2*i*x*y + t1 := pool.Get().Sub(a.y, a.x) + t2 := pool.Get().Add(a.x, a.y) + ty := pool.Get().Mul(t1, t2) + ty.Mod(ty, P) + + t1.Mul(a.x, a.y) + t1.Lsh(t1, 1) + + e.x.Mod(t1, P) + e.y.Set(ty) + + pool.Put(t1) + pool.Put(t2) + pool.Put(ty) + + return e +} + +func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 { + // See "Implementing cryptographic pairings", M. Scott, section 3.2. + // ftp://136.206.11.249/pub/crypto/pairings.pdf + t := pool.Get() + t.Mul(a.y, a.y) + t2 := pool.Get() + t2.Mul(a.x, a.x) + t.Add(t, t2) + + inv := pool.Get() + inv.ModInverse(t, P) + + e.x.Neg(a.x) + e.x.Mul(e.x, inv) + e.x.Mod(e.x, P) + + e.y.Mul(a.y, inv) + e.y.Mod(e.y, P) + + pool.Put(t) + pool.Put(t2) + pool.Put(inv) + + return e +} + +func (e *gfP2) Real() *big.Int { + return e.x +} + +func (e *gfP2) Imag() *big.Int { + return e.y +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp6.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp6.go new file mode 100644 index 0000000000..218856617c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp6.go @@ -0,0 +1,296 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +// For details of the algorithms used, see "Multiplication and Squaring on +// Pairing-Friendly Fields, Devegili et al. +// http://eprint.iacr.org/2006/471.pdf. + +import ( + "math/big" +) + +// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ +// and ξ=i+9. +type gfP6 struct { + x, y, z *gfP2 // value is xτ² + yτ + z +} + +func newGFp6(pool *bnPool) *gfP6 { + return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)} +} + +func (e *gfP6) String() string { + return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")" +} + +func (e *gfP6) Put(pool *bnPool) { + e.x.Put(pool) + e.y.Put(pool) + e.z.Put(pool) +} + +func (e *gfP6) Set(a *gfP6) *gfP6 { + e.x.Set(a.x) + e.y.Set(a.y) + e.z.Set(a.z) + return e +} + +func (e *gfP6) SetZero() *gfP6 { + e.x.SetZero() + e.y.SetZero() + e.z.SetZero() + return e +} + +func (e *gfP6) SetOne() *gfP6 { + e.x.SetZero() + e.y.SetZero() + e.z.SetOne() + return e +} + +func (e *gfP6) Minimal() { + e.x.Minimal() + e.y.Minimal() + e.z.Minimal() +} + +func (e *gfP6) IsZero() bool { + return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() +} + +func (e *gfP6) IsOne() bool { + return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() +} + +func (e *gfP6) Negative(a *gfP6) *gfP6 { + e.x.Negative(a.x) + e.y.Negative(a.y) + e.z.Negative(a.z) + return e +} + +func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 { + e.x.Conjugate(a.x) + e.y.Conjugate(a.y) + e.z.Conjugate(a.z) + + e.x.Mul(e.x, xiTo2PMinus2Over3, pool) + e.y.Mul(e.y, xiToPMinus1Over3, pool) + return e +} + +// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z +func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { + // τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3) + e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3) + // τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3) + e.y.MulScalar(a.y, xiToPSquaredMinus1Over3) + e.z.Set(a.z) + return e +} + +func (e *gfP6) Add(a, b *gfP6) *gfP6 { + e.x.Add(a.x, b.x) + e.y.Add(a.y, b.y) + e.z.Add(a.z, b.z) + return e +} + +func (e *gfP6) Sub(a, b *gfP6) *gfP6 { + e.x.Sub(a.x, b.x) + e.y.Sub(a.y, b.y) + e.z.Sub(a.z, b.z) + return e +} + +func (e *gfP6) Double(a *gfP6) *gfP6 { + e.x.Double(a.x) + e.y.Double(a.y) + e.z.Double(a.z) + return e +} + +func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 { + // "Multiplication and Squaring on Pairing-Friendly Fields" + // Section 4, Karatsuba method. + // http://eprint.iacr.org/2006/471.pdf + + v0 := newGFp2(pool) + v0.Mul(a.z, b.z, pool) + v1 := newGFp2(pool) + v1.Mul(a.y, b.y, pool) + v2 := newGFp2(pool) + v2.Mul(a.x, b.x, pool) + + t0 := newGFp2(pool) + t0.Add(a.x, a.y) + t1 := newGFp2(pool) + t1.Add(b.x, b.y) + tz := newGFp2(pool) + tz.Mul(t0, t1, pool) + + tz.Sub(tz, v1) + tz.Sub(tz, v2) + tz.MulXi(tz, pool) + tz.Add(tz, v0) + + t0.Add(a.y, a.z) + t1.Add(b.y, b.z) + ty := newGFp2(pool) + ty.Mul(t0, t1, pool) + ty.Sub(ty, v0) + ty.Sub(ty, v1) + t0.MulXi(v2, pool) + ty.Add(ty, t0) + + t0.Add(a.x, a.z) + t1.Add(b.x, b.z) + tx := newGFp2(pool) + tx.Mul(t0, t1, pool) + tx.Sub(tx, v0) + tx.Add(tx, v1) + tx.Sub(tx, v2) + + e.x.Set(tx) + e.y.Set(ty) + e.z.Set(tz) + + t0.Put(pool) + t1.Put(pool) + tx.Put(pool) + ty.Put(pool) + tz.Put(pool) + v0.Put(pool) + v1.Put(pool) + v2.Put(pool) + return e +} + +func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 { + e.x.Mul(a.x, b, pool) + e.y.Mul(a.y, b, pool) + e.z.Mul(a.z, b, pool) + return e +} + +func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 { + e.x.MulScalar(a.x, b) + e.y.MulScalar(a.y, b) + e.z.MulScalar(a.z, b) + return e +} + +// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ +func (e *gfP6) MulTau(a *gfP6, pool *bnPool) { + tz := newGFp2(pool) + tz.MulXi(a.x, pool) + ty := newGFp2(pool) + ty.Set(a.y) + e.y.Set(a.z) + e.x.Set(ty) + e.z.Set(tz) + tz.Put(pool) + ty.Put(pool) +} + +func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 { + v0 := newGFp2(pool).Square(a.z, pool) + v1 := newGFp2(pool).Square(a.y, pool) + v2 := newGFp2(pool).Square(a.x, pool) + + c0 := newGFp2(pool).Add(a.x, a.y) + c0.Square(c0, pool) + c0.Sub(c0, v1) + c0.Sub(c0, v2) + c0.MulXi(c0, pool) + c0.Add(c0, v0) + + c1 := newGFp2(pool).Add(a.y, a.z) + c1.Square(c1, pool) + c1.Sub(c1, v0) + c1.Sub(c1, v1) + xiV2 := newGFp2(pool).MulXi(v2, pool) + c1.Add(c1, xiV2) + + c2 := newGFp2(pool).Add(a.x, a.z) + c2.Square(c2, pool) + c2.Sub(c2, v0) + c2.Add(c2, v1) + c2.Sub(c2, v2) + + e.x.Set(c2) + e.y.Set(c1) + e.z.Set(c0) + + v0.Put(pool) + v1.Put(pool) + v2.Put(pool) + c0.Put(pool) + c1.Put(pool) + c2.Put(pool) + xiV2.Put(pool) + + return e +} + +func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 { + // See "Implementing cryptographic pairings", M. Scott, section 3.2. + // ftp://136.206.11.249/pub/crypto/pairings.pdf + + // Here we can give a short explanation of how it works: let j be a cubic root of + // unity in GF(p²) so that 1+j+j²=0. + // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z) + // = (xτ² + yτ + z)(Cτ²+Bτ+A) + // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). + // + // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z) + // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy) + // + // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) + t1 := newGFp2(pool) + + A := newGFp2(pool) + A.Square(a.z, pool) + t1.Mul(a.x, a.y, pool) + t1.MulXi(t1, pool) + A.Sub(A, t1) + + B := newGFp2(pool) + B.Square(a.x, pool) + B.MulXi(B, pool) + t1.Mul(a.y, a.z, pool) + B.Sub(B, t1) + + C_ := newGFp2(pool) + C_.Square(a.y, pool) + t1.Mul(a.x, a.z, pool) + C_.Sub(C_, t1) + + F := newGFp2(pool) + F.Mul(C_, a.y, pool) + F.MulXi(F, pool) + t1.Mul(A, a.z, pool) + F.Add(F, t1) + t1.Mul(B, a.x, pool) + t1.MulXi(t1, pool) + F.Add(F, t1) + + F.Invert(F, pool) + + e.x.Mul(C_, F, pool) + e.y.Mul(B, F, pool) + e.z.Mul(A, F, pool) + + t1.Put(pool) + A.Put(pool) + B.Put(pool) + C_.Put(pool) + F.Put(pool) + + return e +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/main_test.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/main_test.go new file mode 100644 index 0000000000..c0c85457be --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/main_test.go @@ -0,0 +1,71 @@ +package bn256 + +import ( + "testing" + + "crypto/rand" +) + +func TestRandomG2Marshal(t *testing.T) { + for i := 0; i < 10; i++ { + n, g2, err := RandomG2(rand.Reader) + if err != nil { + t.Error(err) + continue + } + t.Logf("%v: %x\n", n, g2.Marshal()) + } +} + +func TestPairings(t *testing.T) { + a1 := new(G1).ScalarBaseMult(bigFromBase10("1")) + a2 := new(G1).ScalarBaseMult(bigFromBase10("2")) + a37 := new(G1).ScalarBaseMult(bigFromBase10("37")) + an1 := new(G1).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) + + b0 := new(G2).ScalarBaseMult(bigFromBase10("0")) + b1 := new(G2).ScalarBaseMult(bigFromBase10("1")) + b2 := new(G2).ScalarBaseMult(bigFromBase10("2")) + b27 := new(G2).ScalarBaseMult(bigFromBase10("27")) + b999 := new(G2).ScalarBaseMult(bigFromBase10("999")) + bn1 := new(G2).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) + + p1 := Pair(a1, b1) + pn1 := Pair(a1, bn1) + np1 := Pair(an1, b1) + if pn1.String() != np1.String() { + t.Error("Pairing mismatch: e(a, -b) != e(-a, b)") + } + if !PairingCheck([]*G1{a1, an1}, []*G2{b1, b1}) { + t.Error("MultiAte check gave false negative!") + } + p0 := new(GT).Add(p1, pn1) + p0_2 := Pair(a1, b0) + if p0.String() != p0_2.String() { + t.Error("Pairing mismatch: e(a, b) * e(a, -b) != 1") + } + p0_3 := new(GT).ScalarMult(p1, bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617")) + if p0.String() != p0_3.String() { + t.Error("Pairing mismatch: e(a, b) has wrong order") + } + p2 := Pair(a2, b1) + p2_2 := Pair(a1, b2) + p2_3 := new(GT).ScalarMult(p1, bigFromBase10("2")) + if p2.String() != p2_2.String() { + t.Error("Pairing mismatch: e(a, b * 2) != e(a * 2, b)") + } + if p2.String() != p2_3.String() { + t.Error("Pairing mismatch: e(a, b * 2) != e(a, b) ** 2") + } + if p2.String() == p1.String() { + t.Error("Pairing is degenerate!") + } + if PairingCheck([]*G1{a1, a1}, []*G2{b1, b1}) { + t.Error("MultiAte check gave false positive!") + } + p999 := Pair(a37, b27) + p999_2 := Pair(a1, b999) + if p999.String() != p999_2.String() { + t.Error("Pairing mismatch: e(a * 37, b * 27) != e(a, b * 999)") + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/optate.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/optate.go new file mode 100644 index 0000000000..9d6957062e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/optate.go @@ -0,0 +1,397 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { + // See the mixed addition algorithm from "Faster Computation of the + // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf + + B := newGFp2(pool).Mul(p.x, r.t, pool) + + D := newGFp2(pool).Add(p.y, r.z) + D.Square(D, pool) + D.Sub(D, r2) + D.Sub(D, r.t) + D.Mul(D, r.t, pool) + + H := newGFp2(pool).Sub(B, r.x) + I := newGFp2(pool).Square(H, pool) + + E := newGFp2(pool).Add(I, I) + E.Add(E, E) + + J := newGFp2(pool).Mul(H, E, pool) + + L1 := newGFp2(pool).Sub(D, r.y) + L1.Sub(L1, r.y) + + V := newGFp2(pool).Mul(r.x, E, pool) + + rOut = newTwistPoint(pool) + rOut.x.Square(L1, pool) + rOut.x.Sub(rOut.x, J) + rOut.x.Sub(rOut.x, V) + rOut.x.Sub(rOut.x, V) + + rOut.z.Add(r.z, H) + rOut.z.Square(rOut.z, pool) + rOut.z.Sub(rOut.z, r.t) + rOut.z.Sub(rOut.z, I) + + t := newGFp2(pool).Sub(V, rOut.x) + t.Mul(t, L1, pool) + t2 := newGFp2(pool).Mul(r.y, J, pool) + t2.Add(t2, t2) + rOut.y.Sub(t, t2) + + rOut.t.Square(rOut.z, pool) + + t.Add(p.y, rOut.z) + t.Square(t, pool) + t.Sub(t, r2) + t.Sub(t, rOut.t) + + t2.Mul(L1, p.x, pool) + t2.Add(t2, t2) + a = newGFp2(pool) + a.Sub(t2, t) + + c = newGFp2(pool) + c.MulScalar(rOut.z, q.y) + c.Add(c, c) + + b = newGFp2(pool) + b.SetZero() + b.Sub(b, L1) + b.MulScalar(b, q.x) + b.Add(b, b) + + B.Put(pool) + D.Put(pool) + H.Put(pool) + I.Put(pool) + E.Put(pool) + J.Put(pool) + L1.Put(pool) + V.Put(pool) + t.Put(pool) + t2.Put(pool) + + return +} + +func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { + // See the doubling algorithm for a=0 from "Faster Computation of the + // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf + + A := newGFp2(pool).Square(r.x, pool) + B := newGFp2(pool).Square(r.y, pool) + C_ := newGFp2(pool).Square(B, pool) + + D := newGFp2(pool).Add(r.x, B) + D.Square(D, pool) + D.Sub(D, A) + D.Sub(D, C_) + D.Add(D, D) + + E := newGFp2(pool).Add(A, A) + E.Add(E, A) + + G := newGFp2(pool).Square(E, pool) + + rOut = newTwistPoint(pool) + rOut.x.Sub(G, D) + rOut.x.Sub(rOut.x, D) + + rOut.z.Add(r.y, r.z) + rOut.z.Square(rOut.z, pool) + rOut.z.Sub(rOut.z, B) + rOut.z.Sub(rOut.z, r.t) + + rOut.y.Sub(D, rOut.x) + rOut.y.Mul(rOut.y, E, pool) + t := newGFp2(pool).Add(C_, C_) + t.Add(t, t) + t.Add(t, t) + rOut.y.Sub(rOut.y, t) + + rOut.t.Square(rOut.z, pool) + + t.Mul(E, r.t, pool) + t.Add(t, t) + b = newGFp2(pool) + b.SetZero() + b.Sub(b, t) + b.MulScalar(b, q.x) + + a = newGFp2(pool) + a.Add(r.x, E) + a.Square(a, pool) + a.Sub(a, A) + a.Sub(a, G) + t.Add(B, B) + t.Add(t, t) + a.Sub(a, t) + + c = newGFp2(pool) + c.Mul(rOut.z, r.t, pool) + c.Add(c, c) + c.MulScalar(c, q.y) + + A.Put(pool) + B.Put(pool) + C_.Put(pool) + D.Put(pool) + E.Put(pool) + G.Put(pool) + t.Put(pool) + + return +} + +func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) { + a2 := newGFp6(pool) + a2.x.SetZero() + a2.y.Set(a) + a2.z.Set(b) + a2.Mul(a2, ret.x, pool) + t3 := newGFp6(pool).MulScalar(ret.y, c, pool) + + t := newGFp2(pool) + t.Add(b, c) + t2 := newGFp6(pool) + t2.x.SetZero() + t2.y.Set(a) + t2.z.Set(t) + ret.x.Add(ret.x, ret.y) + + ret.y.Set(t3) + + ret.x.Mul(ret.x, t2, pool) + ret.x.Sub(ret.x, a2) + ret.x.Sub(ret.x, ret.y) + a2.MulTau(a2, pool) + ret.y.Add(ret.y, a2) + + a2.Put(pool) + t3.Put(pool) + t2.Put(pool) + t.Put(pool) +} + +// sixuPlus2NAF is 6u+2 in non-adjacent form. +var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, + 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1, + 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, + 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1} + +// miller implements the Miller loop for calculating the Optimal Ate pairing. +// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf +func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 { + ret := newGFp12(pool) + ret.SetOne() + + aAffine := newTwistPoint(pool) + aAffine.Set(q) + aAffine.MakeAffine(pool) + + bAffine := newCurvePoint(pool) + bAffine.Set(p) + bAffine.MakeAffine(pool) + + minusA := newTwistPoint(pool) + minusA.Negative(aAffine, pool) + + r := newTwistPoint(pool) + r.Set(aAffine) + + r2 := newGFp2(pool) + r2.Square(aAffine.y, pool) + + for i := len(sixuPlus2NAF) - 1; i > 0; i-- { + a, b, c, newR := lineFunctionDouble(r, bAffine, pool) + if i != len(sixuPlus2NAF)-1 { + ret.Square(ret, pool) + } + + mulLine(ret, a, b, c, pool) + a.Put(pool) + b.Put(pool) + c.Put(pool) + r.Put(pool) + r = newR + + switch sixuPlus2NAF[i-1] { + case 1: + a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool) + case -1: + a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool) + default: + continue + } + + mulLine(ret, a, b, c, pool) + a.Put(pool) + b.Put(pool) + c.Put(pool) + r.Put(pool) + r = newR + } + + // In order to calculate Q1 we have to convert q from the sextic twist + // to the full GF(p^12) group, apply the Frobenius there, and convert + // back. + // + // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just + // x for a moment, then after applying the Frobenius, we have x̄ω^(2p) + // where x̄ is the conjugate of x. If we are going to apply the inverse + // isomorphism we need a value with a single coefficient of ω² so we + // rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of + // p, 2p-2 is a multiple of six. Therefore we can rewrite as + // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the + // ω². + // + // A similar argument can be made for the y value. + + q1 := newTwistPoint(pool) + q1.x.Conjugate(aAffine.x) + q1.x.Mul(q1.x, xiToPMinus1Over3, pool) + q1.y.Conjugate(aAffine.y) + q1.y.Mul(q1.y, xiToPMinus1Over2, pool) + q1.z.SetOne() + q1.t.SetOne() + + // For Q2 we are applying the p² Frobenius. The two conjugations cancel + // out and we are left only with the factors from the isomorphism. In + // the case of x, we end up with a pure number which is why + // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We + // ignore this to end up with -Q2. + + minusQ2 := newTwistPoint(pool) + minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3) + minusQ2.y.Set(aAffine.y) + minusQ2.z.SetOne() + minusQ2.t.SetOne() + + r2.Square(q1.y, pool) + a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool) + mulLine(ret, a, b, c, pool) + a.Put(pool) + b.Put(pool) + c.Put(pool) + r.Put(pool) + r = newR + + r2.Square(minusQ2.y, pool) + a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool) + mulLine(ret, a, b, c, pool) + a.Put(pool) + b.Put(pool) + c.Put(pool) + r.Put(pool) + r = newR + + aAffine.Put(pool) + bAffine.Put(pool) + minusA.Put(pool) + r.Put(pool) + r2.Put(pool) + + return ret +} + +// finalExponentiation computes the (p¹²-1)/Order-th power of an element of +// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from +// http://cryptojedi.org/papers/dclxvi-20100714.pdf) +func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 { + t1 := newGFp12(pool) + + // This is the p^6-Frobenius + t1.x.Negative(in.x) + t1.y.Set(in.y) + + inv := newGFp12(pool) + inv.Invert(in, pool) + t1.Mul(t1, inv, pool) + + t2 := newGFp12(pool).FrobeniusP2(t1, pool) + t1.Mul(t1, t2, pool) + + fp := newGFp12(pool).Frobenius(t1, pool) + fp2 := newGFp12(pool).FrobeniusP2(t1, pool) + fp3 := newGFp12(pool).Frobenius(fp2, pool) + + fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool) + fu.Exp(t1, u, pool) + fu2.Exp(fu, u, pool) + fu3.Exp(fu2, u, pool) + + y3 := newGFp12(pool).Frobenius(fu, pool) + fu2p := newGFp12(pool).Frobenius(fu2, pool) + fu3p := newGFp12(pool).Frobenius(fu3, pool) + y2 := newGFp12(pool).FrobeniusP2(fu2, pool) + + y0 := newGFp12(pool) + y0.Mul(fp, fp2, pool) + y0.Mul(y0, fp3, pool) + + y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool) + y1.Conjugate(t1) + y5.Conjugate(fu2) + y3.Conjugate(y3) + y4.Mul(fu, fu2p, pool) + y4.Conjugate(y4) + + y6 := newGFp12(pool) + y6.Mul(fu3, fu3p, pool) + y6.Conjugate(y6) + + t0 := newGFp12(pool) + t0.Square(y6, pool) + t0.Mul(t0, y4, pool) + t0.Mul(t0, y5, pool) + t1.Mul(y3, y5, pool) + t1.Mul(t1, t0, pool) + t0.Mul(t0, y2, pool) + t1.Square(t1, pool) + t1.Mul(t1, t0, pool) + t1.Square(t1, pool) + t0.Mul(t1, y1, pool) + t1.Mul(t1, y0, pool) + t0.Square(t0, pool) + t0.Mul(t0, t1, pool) + + inv.Put(pool) + t1.Put(pool) + t2.Put(pool) + fp.Put(pool) + fp2.Put(pool) + fp3.Put(pool) + fu.Put(pool) + fu2.Put(pool) + fu3.Put(pool) + fu2p.Put(pool) + fu3p.Put(pool) + y0.Put(pool) + y1.Put(pool) + y2.Put(pool) + y3.Put(pool) + y4.Put(pool) + y5.Put(pool) + y6.Put(pool) + + return t0 +} + +func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 { + e := miller(a, b, pool) + ret := finalExponentiation(e, pool) + e.Put(pool) + + if a.IsInfinity() || b.IsInfinity() { + ret.SetOne() + } + return ret +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/twist.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/twist.go new file mode 100644 index 0000000000..43364ff5b7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/twist.go @@ -0,0 +1,263 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bn256 + +import ( + "math/big" +) + +// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are +// kept in Jacobian form and t=z² when valid. The group G₂ is the set of +// n-torsion points of this curve over GF(p²) (where n = Order) +type twistPoint struct { + x, y, z, t *gfP2 +} + +var twistB = &gfP2{ + bigFromBase10("266929791119991161246907387137283842545076965332900288569378510910307636690"), + bigFromBase10("19485874751759354771024239261021720505790618469301721065564631296452457478373"), +} + +// twistGen is the generator of group G₂. +var twistGen = &twistPoint{ + &gfP2{ + bigFromBase10("11559732032986387107991004021392285783925812861821192530917403151452391805634"), + bigFromBase10("10857046999023057135944570762232829481370756359578518086990519993285655852781"), + }, + &gfP2{ + bigFromBase10("4082367875863433681332203403145435568316851327593401208105741076214120093531"), + bigFromBase10("8495653923123431417604973247489272438418190587263600148770280649306958101930"), + }, + &gfP2{ + bigFromBase10("0"), + bigFromBase10("1"), + }, + &gfP2{ + bigFromBase10("0"), + bigFromBase10("1"), + }, +} + +func newTwistPoint(pool *bnPool) *twistPoint { + return &twistPoint{ + newGFp2(pool), + newGFp2(pool), + newGFp2(pool), + newGFp2(pool), + } +} + +func (c *twistPoint) String() string { + return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")" +} + +func (c *twistPoint) Put(pool *bnPool) { + c.x.Put(pool) + c.y.Put(pool) + c.z.Put(pool) + c.t.Put(pool) +} + +func (c *twistPoint) Set(a *twistPoint) { + c.x.Set(a.x) + c.y.Set(a.y) + c.z.Set(a.z) + c.t.Set(a.t) +} + +// IsOnCurve returns true iff c is on the curve where c must be in affine form. +func (c *twistPoint) IsOnCurve() bool { + pool := new(bnPool) + yy := newGFp2(pool).Square(c.y, pool) + xxx := newGFp2(pool).Square(c.x, pool) + xxx.Mul(xxx, c.x, pool) + yy.Sub(yy, xxx) + yy.Sub(yy, twistB) + yy.Minimal() + + if yy.x.Sign() != 0 || yy.y.Sign() != 0 { + return false + } + cneg := newTwistPoint(pool) + cneg.Mul(c, Order, pool) + return cneg.z.IsZero() +} + +func (c *twistPoint) SetInfinity() { + c.z.SetZero() +} + +func (c *twistPoint) IsInfinity() bool { + return c.z.IsZero() +} + +func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) { + // For additional comments, see the same function in curve.go. + + if a.IsInfinity() { + c.Set(b) + return + } + if b.IsInfinity() { + c.Set(a) + return + } + + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 + z1z1 := newGFp2(pool).Square(a.z, pool) + z2z2 := newGFp2(pool).Square(b.z, pool) + u1 := newGFp2(pool).Mul(a.x, z2z2, pool) + u2 := newGFp2(pool).Mul(b.x, z1z1, pool) + + t := newGFp2(pool).Mul(b.z, z2z2, pool) + s1 := newGFp2(pool).Mul(a.y, t, pool) + + t.Mul(a.z, z1z1, pool) + s2 := newGFp2(pool).Mul(b.y, t, pool) + + h := newGFp2(pool).Sub(u2, u1) + xEqual := h.IsZero() + + t.Add(h, h) + i := newGFp2(pool).Square(t, pool) + j := newGFp2(pool).Mul(h, i, pool) + + t.Sub(s2, s1) + yEqual := t.IsZero() + if xEqual && yEqual { + c.Double(a, pool) + return + } + r := newGFp2(pool).Add(t, t) + + v := newGFp2(pool).Mul(u1, i, pool) + + t4 := newGFp2(pool).Square(r, pool) + t.Add(v, v) + t6 := newGFp2(pool).Sub(t4, j) + c.x.Sub(t6, t) + + t.Sub(v, c.x) // t7 + t4.Mul(s1, j, pool) // t8 + t6.Add(t4, t4) // t9 + t4.Mul(r, t, pool) // t10 + c.y.Sub(t4, t6) + + t.Add(a.z, b.z) // t11 + t4.Square(t, pool) // t12 + t.Sub(t4, z1z1) // t13 + t4.Sub(t, z2z2) // t14 + c.z.Mul(t4, h, pool) + + z1z1.Put(pool) + z2z2.Put(pool) + u1.Put(pool) + u2.Put(pool) + t.Put(pool) + s1.Put(pool) + s2.Put(pool) + h.Put(pool) + i.Put(pool) + j.Put(pool) + r.Put(pool) + v.Put(pool) + t4.Put(pool) + t6.Put(pool) +} + +func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 + A := newGFp2(pool).Square(a.x, pool) + B := newGFp2(pool).Square(a.y, pool) + C_ := newGFp2(pool).Square(B, pool) + + t := newGFp2(pool).Add(a.x, B) + t2 := newGFp2(pool).Square(t, pool) + t.Sub(t2, A) + t2.Sub(t, C_) + d := newGFp2(pool).Add(t2, t2) + t.Add(A, A) + e := newGFp2(pool).Add(t, A) + f := newGFp2(pool).Square(e, pool) + + t.Add(d, d) + c.x.Sub(f, t) + + t.Add(C_, C_) + t2.Add(t, t) + t.Add(t2, t2) + c.y.Sub(d, c.x) + t2.Mul(e, c.y, pool) + c.y.Sub(t2, t) + + t.Mul(a.y, a.z, pool) + c.z.Add(t, t) + + A.Put(pool) + B.Put(pool) + C_.Put(pool) + t.Put(pool) + t2.Put(pool) + d.Put(pool) + e.Put(pool) + f.Put(pool) +} + +func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint { + sum := newTwistPoint(pool) + sum.SetInfinity() + t := newTwistPoint(pool) + + for i := scalar.BitLen(); i >= 0; i-- { + t.Double(sum, pool) + if scalar.Bit(i) != 0 { + sum.Add(t, a, pool) + } else { + sum.Set(t) + } + } + + c.Set(sum) + sum.Put(pool) + t.Put(pool) + return c +} + +// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets +// c to 0 : 1 : 0. +func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { + if c.z.IsOne() { + return c + } + if c.IsInfinity() { + c.x.SetZero() + c.y.SetOne() + c.z.SetZero() + c.t.SetZero() + return c + } + zInv := newGFp2(pool).Invert(c.z, pool) + t := newGFp2(pool).Mul(c.y, zInv, pool) + zInv2 := newGFp2(pool).Square(zInv, pool) + c.y.Mul(t, zInv2, pool) + t.Mul(c.x, zInv2, pool) + c.x.Set(t) + c.z.SetOne() + c.t.SetOne() + + zInv.Put(pool) + t.Put(pool) + zInv2.Put(pool) + + return c +} + +func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) { + c.x.Set(a.x) + c.y.SetZero() + c.y.Sub(c.y, a.y) + c.z.Set(a.z) + c.t.SetZero() +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go b/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go index 9b3e76d406..4567fafc72 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go @@ -30,8 +30,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" + "golang.org/x/crypto/sha3" ) var ( @@ -43,7 +43,7 @@ var errInvalidPubkey = errors.New("invalid secp256k1 public key") // Keccak256 calculates and returns the Keccak256 hash of the input data. func Keccak256(data ...[]byte) []byte { - d := sha3.NewKeccak256() + d := sha3.NewLegacyKeccak256() for _, b := range data { d.Write(b) } @@ -53,7 +53,7 @@ func Keccak256(data ...[]byte) []byte { // Keccak256Hash calculates and returns the Keccak256 hash of the input data, // converting it to an internal Hash data structure. func Keccak256Hash(data ...[]byte) (h common.Hash) { - d := sha3.NewKeccak256() + d := sha3.NewLegacyKeccak256() for _, b := range data { d.Write(b) } @@ -63,7 +63,7 @@ func Keccak256Hash(data ...[]byte) (h common.Hash) { // Keccak512 calculates and returns the Keccak512 hash of the input data. func Keccak512(data ...[]byte) []byte { - d := sha3.NewKeccak512() + d := sha3.NewLegacyKeccak512() for _, b := range data { d.Write(b) } diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/ecies/.gitignore b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/.gitignore new file mode 100644 index 0000000000..802b6744a1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe + +*~ diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/ecies/LICENSE b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/LICENSE new file mode 100644 index 0000000000..e1ed19a279 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2013 Kyle Isom +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/ecies/README b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/README new file mode 100644 index 0000000000..2650c7b9f6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/README @@ -0,0 +1,94 @@ +# NOTE + +This implementation is direct fork of Kylom's implementation. I claim no authorship over this code apart from some minor modifications. +Please be aware this code **has not yet been reviewed**. + +ecies implements the Elliptic Curve Integrated Encryption Scheme. + +The package is designed to be compliant with the appropriate NIST +standards, and therefore doesn't support the full SEC 1 algorithm set. + + +STATUS: + +ecies should be ready for use. The ASN.1 support is only complete so +far as to supported the listed algorithms before. + + +CAVEATS + +1. CMAC support is currently not present. + + +SUPPORTED ALGORITHMS + + SYMMETRIC CIPHERS HASH FUNCTIONS + AES128 SHA-1 + AES192 SHA-224 + AES256 SHA-256 + SHA-384 + ELLIPTIC CURVE SHA-512 + P256 + P384 KEY DERIVATION FUNCTION + P521 NIST SP 800-65a Concatenation KDF + +Curve P224 isn't supported because it does not provide a minimum security +level of AES128 with HMAC-SHA1. According to NIST SP 800-57, the security +level of P224 is 112 bits of security. Symmetric ciphers use CTR-mode; +message tags are computed using HMAC- function. + + +CURVE SELECTION + +According to NIST SP 800-57, the following curves should be selected: + + +----------------+-------+ + | SYMMETRIC SIZE | CURVE | + +----------------+-------+ + | 128-bit | P256 | + +----------------+-------+ + | 192-bit | P384 | + +----------------+-------+ + | 256-bit | P521 | + +----------------+-------+ + + +TODO + +1. Look at serialising the parameters with the SEC 1 ASN.1 module. +2. Validate ASN.1 formats with SEC 1. + + +TEST VECTORS + +The only test vectors I've found so far date from 1993, predating AES +and including only 163-bit curves. Therefore, there are no published +test vectors to compare to. + + +LICENSE + +ecies is released under the same license as the Go source code. See the +LICENSE file for details. + + +REFERENCES + +* SEC (Standard for Efficient Cryptography) 1, version 2.0: Elliptic + Curve Cryptography; Certicom, May 2009. + http://www.secg.org/sec1-v2.pdf +* GEC (Guidelines for Efficient Cryptography) 2, version 0.3: Test + Vectors for SEC 1; Certicom, September 1999. + http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf +* NIST SP 800-56a: Recommendation for Pair-Wise Key Establishment Schemes + Using Discrete Logarithm Cryptography. National Institute of Standards + and Technology, May 2007. + http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf +* Suite B Implementer’s Guide to NIST SP 800-56A. National Security + Agency, July 28, 2009. + http://www.nsa.gov/ia/_files/SuiteB_Implementer_G-113808.pdf +* NIST SP 800-57: Recommendation for Key Management – Part 1: General + (Revision 3). National Institute of Standards and Technology, July + 2012. + http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies.go b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies.go new file mode 100644 index 0000000000..1474181482 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies.go @@ -0,0 +1,366 @@ +// Copyright (c) 2013 Kyle Isom +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package ecies + +import ( + "crypto/cipher" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/hmac" + "crypto/subtle" + "fmt" + "hash" + "io" + "math/big" +) + +var ( + ErrImport = fmt.Errorf("ecies: failed to import key") + ErrInvalidCurve = fmt.Errorf("ecies: invalid elliptic curve") + ErrInvalidParams = fmt.Errorf("ecies: invalid ECIES parameters") + ErrInvalidPublicKey = fmt.Errorf("ecies: invalid public key") + ErrSharedKeyIsPointAtInfinity = fmt.Errorf("ecies: shared key is point at infinity") + ErrSharedKeyTooBig = fmt.Errorf("ecies: shared key params are too big") +) + +// PublicKey is a representation of an elliptic curve public key. +type PublicKey struct { + X *big.Int + Y *big.Int + elliptic.Curve + Params *ECIESParams +} + +// Export an ECIES public key as an ECDSA public key. +func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey { + return &ecdsa.PublicKey{Curve: pub.Curve, X: pub.X, Y: pub.Y} +} + +// Import an ECDSA public key as an ECIES public key. +func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey { + return &PublicKey{ + X: pub.X, + Y: pub.Y, + Curve: pub.Curve, + Params: ParamsFromCurve(pub.Curve), + } +} + +// PrivateKey is a representation of an elliptic curve private key. +type PrivateKey struct { + PublicKey + D *big.Int +} + +// Export an ECIES private key as an ECDSA private key. +func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey { + pub := &prv.PublicKey + pubECDSA := pub.ExportECDSA() + return &ecdsa.PrivateKey{PublicKey: *pubECDSA, D: prv.D} +} + +// Import an ECDSA private key as an ECIES private key. +func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey { + pub := ImportECDSAPublic(&prv.PublicKey) + return &PrivateKey{*pub, prv.D} +} + +// Generate an elliptic curve public / private keypair. If params is nil, +// the recommended default parameters for the key will be chosen. +func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) { + pb, x, y, err := elliptic.GenerateKey(curve, rand) + if err != nil { + return + } + prv = new(PrivateKey) + prv.PublicKey.X = x + prv.PublicKey.Y = y + prv.PublicKey.Curve = curve + prv.D = new(big.Int).SetBytes(pb) + if params == nil { + params = ParamsFromCurve(curve) + } + prv.PublicKey.Params = params + return +} + +// MaxSharedKeyLength returns the maximum length of the shared key the +// public key can produce. +func MaxSharedKeyLength(pub *PublicKey) int { + return (pub.Curve.Params().BitSize + 7) / 8 +} + +// ECDH key agreement method used to establish secret keys for encryption. +func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) { + if prv.PublicKey.Curve != pub.Curve { + return nil, ErrInvalidCurve + } + if skLen+macLen > MaxSharedKeyLength(pub) { + return nil, ErrSharedKeyTooBig + } + + x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes()) + if x == nil { + return nil, ErrSharedKeyIsPointAtInfinity + } + + sk = make([]byte, skLen+macLen) + skBytes := x.Bytes() + copy(sk[len(sk)-len(skBytes):], skBytes) + return sk, nil +} + +var ( + ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data") + ErrSharedTooLong = fmt.Errorf("ecies: shared secret is too long") + ErrInvalidMessage = fmt.Errorf("ecies: invalid message") +) + +var ( + big2To32 = new(big.Int).Exp(big.NewInt(2), big.NewInt(32), nil) + big2To32M1 = new(big.Int).Sub(big2To32, big.NewInt(1)) +) + +func incCounter(ctr []byte) { + if ctr[3]++; ctr[3] != 0 { + return + } + if ctr[2]++; ctr[2] != 0 { + return + } + if ctr[1]++; ctr[1] != 0 { + return + } + if ctr[0]++; ctr[0] != 0 { + return + } +} + +// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1). +func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) { + if s1 == nil { + s1 = make([]byte, 0) + } + + reps := ((kdLen + 7) * 8) / (hash.BlockSize() * 8) + if big.NewInt(int64(reps)).Cmp(big2To32M1) > 0 { + fmt.Println(big2To32M1) + return nil, ErrKeyDataTooLong + } + + counter := []byte{0, 0, 0, 1} + k = make([]byte, 0) + + for i := 0; i <= reps; i++ { + hash.Write(counter) + hash.Write(z) + hash.Write(s1) + k = append(k, hash.Sum(nil)...) + hash.Reset() + incCounter(counter) + } + + k = k[:kdLen] + return +} + +// messageTag computes the MAC of a message (called the tag) as per +// SEC 1, 3.5. +func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte { + mac := hmac.New(hash, km) + mac.Write(msg) + mac.Write(shared) + tag := mac.Sum(nil) + return tag +} + +// Generate an initialisation vector for CTR mode. +func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) { + iv = make([]byte, params.BlockSize) + _, err = io.ReadFull(rand, iv) + return +} + +// symEncrypt carries out CTR encryption using the block cipher specified in the +// parameters. +func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) { + c, err := params.Cipher(key) + if err != nil { + return + } + + iv, err := generateIV(params, rand) + if err != nil { + return + } + ctr := cipher.NewCTR(c, iv) + + ct = make([]byte, len(m)+params.BlockSize) + copy(ct, iv) + ctr.XORKeyStream(ct[params.BlockSize:], m) + return +} + +// symDecrypt carries out CTR decryption using the block cipher specified in +// the parameters +func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) { + c, err := params.Cipher(key) + if err != nil { + return + } + + ctr := cipher.NewCTR(c, ct[:params.BlockSize]) + + m = make([]byte, len(ct)-params.BlockSize) + ctr.XORKeyStream(m, ct[params.BlockSize:]) + return +} + +// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. +// +// s1 and s2 contain shared information that is not part of the resulting +// ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the +// shared information parameters aren't being used, they should be nil. +func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) { + params := pub.Params + if params == nil { + if params = ParamsFromCurve(pub.Curve); params == nil { + err = ErrUnsupportedECIESParameters + return + } + } + R, err := GenerateKey(rand, pub.Curve, params) + if err != nil { + return + } + + hash := params.Hash() + z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen) + if err != nil { + return + } + K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) + if err != nil { + return + } + Ke := K[:params.KeyLen] + Km := K[params.KeyLen:] + hash.Write(Km) + Km = hash.Sum(nil) + hash.Reset() + + em, err := symEncrypt(rand, params, Ke, m) + if err != nil || len(em) <= params.BlockSize { + return + } + + d := messageTag(params.Hash, Km, em, s2) + + Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y) + ct = make([]byte, len(Rb)+len(em)+len(d)) + copy(ct, Rb) + copy(ct[len(Rb):], em) + copy(ct[len(Rb)+len(em):], d) + return +} + +// Decrypt decrypts an ECIES ciphertext. +func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { + if len(c) == 0 { + return nil, ErrInvalidMessage + } + params := prv.PublicKey.Params + if params == nil { + if params = ParamsFromCurve(prv.PublicKey.Curve); params == nil { + err = ErrUnsupportedECIESParameters + return + } + } + hash := params.Hash() + + var ( + rLen int + hLen int = hash.Size() + mStart int + mEnd int + ) + + switch c[0] { + case 2, 3, 4: + rLen = (prv.PublicKey.Curve.Params().BitSize + 7) / 4 + if len(c) < (rLen + hLen + 1) { + err = ErrInvalidMessage + return + } + default: + err = ErrInvalidPublicKey + return + } + + mStart = rLen + mEnd = len(c) - hLen + + R := new(PublicKey) + R.Curve = prv.PublicKey.Curve + R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen]) + if R.X == nil { + err = ErrInvalidPublicKey + return + } + if !R.Curve.IsOnCurve(R.X, R.Y) { + err = ErrInvalidCurve + return + } + + z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen) + if err != nil { + return + } + + K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) + if err != nil { + return + } + + Ke := K[:params.KeyLen] + Km := K[params.KeyLen:] + hash.Write(Km) + Km = hash.Sum(nil) + hash.Reset() + + d := messageTag(params.Hash, Km, c[mStart:mEnd], s2) + if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 { + err = ErrInvalidMessage + return + } + + m, err = symDecrypt(params, Ke, c[mStart:mEnd]) + return +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies_test.go b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies_test.go new file mode 100644 index 0000000000..6bd57145db --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies_test.go @@ -0,0 +1,480 @@ +// Copyright (c) 2013 Kyle Isom +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package ecies + +import ( + "bytes" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "encoding/hex" + "flag" + "fmt" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/crypto" +) + +var dumpEnc bool + +func init() { + flDump := flag.Bool("dump", false, "write encrypted test message to file") + flag.Parse() + dumpEnc = *flDump +} + +// Ensure the KDF generates appropriately sized keys. +func TestKDF(t *testing.T) { + msg := []byte("Hello, world") + h := sha256.New() + + k, err := concatKDF(h, msg, nil, 64) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + if len(k) != 64 { + fmt.Printf("KDF: generated key is the wrong size (%d instead of 64\n", len(k)) + t.FailNow() + } +} + +var ErrBadSharedKeys = fmt.Errorf("ecies: shared keys don't match") + +// cmpParams compares a set of ECIES parameters. We assume, as per the +// docs, that AES is the only supported symmetric encryption algorithm. +func cmpParams(p1, p2 *ECIESParams) bool { + return p1.hashAlgo == p2.hashAlgo && + p1.KeyLen == p2.KeyLen && + p1.BlockSize == p2.BlockSize +} + +// cmpPublic returns true if the two public keys represent the same pojnt. +func cmpPublic(pub1, pub2 PublicKey) bool { + if pub1.X == nil || pub1.Y == nil { + fmt.Println(ErrInvalidPublicKey.Error()) + return false + } + if pub2.X == nil || pub2.Y == nil { + fmt.Println(ErrInvalidPublicKey.Error()) + return false + } + pub1Out := elliptic.Marshal(pub1.Curve, pub1.X, pub1.Y) + pub2Out := elliptic.Marshal(pub2.Curve, pub2.X, pub2.Y) + + return bytes.Equal(pub1Out, pub2Out) +} + +// Validate the ECDH component. +func TestSharedKey(t *testing.T) { + prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2 + + prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + if !bytes.Equal(sk1, sk2) { + fmt.Println(ErrBadSharedKeys.Error()) + t.FailNow() + } +} + +func TestSharedKeyPadding(t *testing.T) { + // sanity checks + prv0 := hexKey("1adf5c18167d96a1f9a0b1ef63be8aa27eaf6032c233b2b38f7850cf5b859fd9") + prv1 := hexKey("0097a076fc7fcd9208240668e31c9abee952cbb6e375d1b8febc7499d6e16f1a") + x0, _ := new(big.Int).SetString("1a8ed022ff7aec59dc1b440446bdda5ff6bcb3509a8b109077282b361efffbd8", 16) + x1, _ := new(big.Int).SetString("6ab3ac374251f638d0abb3ef596d1dc67955b507c104e5f2009724812dc027b8", 16) + y0, _ := new(big.Int).SetString("e040bd480b1deccc3bc40bd5b1fdcb7bfd352500b477cb9471366dbd4493f923", 16) + y1, _ := new(big.Int).SetString("8ad915f2b503a8be6facab6588731fefeb584fd2dfa9a77a5e0bba1ec439e4fa", 16) + + if prv0.PublicKey.X.Cmp(x0) != 0 { + t.Errorf("mismatched prv0.X:\nhave: %x\nwant: %x\n", prv0.PublicKey.X.Bytes(), x0.Bytes()) + } + if prv0.PublicKey.Y.Cmp(y0) != 0 { + t.Errorf("mismatched prv0.Y:\nhave: %x\nwant: %x\n", prv0.PublicKey.Y.Bytes(), y0.Bytes()) + } + if prv1.PublicKey.X.Cmp(x1) != 0 { + t.Errorf("mismatched prv1.X:\nhave: %x\nwant: %x\n", prv1.PublicKey.X.Bytes(), x1.Bytes()) + } + if prv1.PublicKey.Y.Cmp(y1) != 0 { + t.Errorf("mismatched prv1.Y:\nhave: %x\nwant: %x\n", prv1.PublicKey.Y.Bytes(), y1.Bytes()) + } + + // test shared secret generation + sk1, err := prv0.GenerateShared(&prv1.PublicKey, 16, 16) + if err != nil { + fmt.Println(err.Error()) + } + + sk2, err := prv1.GenerateShared(&prv0.PublicKey, 16, 16) + if err != nil { + t.Fatal(err.Error()) + } + + if !bytes.Equal(sk1, sk2) { + t.Fatal(ErrBadSharedKeys.Error()) + } +} + +// Verify that the key generation code fails when too much key data is +// requested. +func TestTooBigSharedKey(t *testing.T) { + prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + _, err = prv1.GenerateShared(&prv2.PublicKey, 32, 32) + if err != ErrSharedKeyTooBig { + fmt.Println("ecdh: shared key should be too large for curve") + t.FailNow() + } + + _, err = prv2.GenerateShared(&prv1.PublicKey, 32, 32) + if err != ErrSharedKeyTooBig { + fmt.Println("ecdh: shared key should be too large for curve") + t.FailNow() + } +} + +// Benchmark the generation of P256 keys. +func BenchmarkGenerateKeyP256(b *testing.B) { + for i := 0; i < b.N; i++ { + if _, err := GenerateKey(rand.Reader, elliptic.P256(), nil); err != nil { + fmt.Println(err.Error()) + b.FailNow() + } + } +} + +// Benchmark the generation of P256 shared keys. +func BenchmarkGenSharedKeyP256(b *testing.B) { + prv, err := GenerateKey(rand.Reader, elliptic.P256(), nil) + if err != nil { + fmt.Println(err.Error()) + b.FailNow() + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := prv.GenerateShared(&prv.PublicKey, 16, 16) + if err != nil { + fmt.Println(err.Error()) + b.FailNow() + } + } +} + +// Benchmark the generation of S256 shared keys. +func BenchmarkGenSharedKeyS256(b *testing.B) { + prv, err := GenerateKey(rand.Reader, crypto.S256(), nil) + if err != nil { + fmt.Println(err.Error()) + b.FailNow() + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := prv.GenerateShared(&prv.PublicKey, 16, 16) + if err != nil { + fmt.Println(err.Error()) + b.FailNow() + } + } +} + +// Verify that an encrypted message can be successfully decrypted. +func TestEncryptDecrypt(t *testing.T) { + prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + message := []byte("Hello, world.") + ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + pt, err := prv2.Decrypt(ct, nil, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + if !bytes.Equal(pt, message) { + fmt.Println("ecies: plaintext doesn't match message") + t.FailNow() + } + + _, err = prv1.Decrypt(ct, nil, nil) + if err == nil { + fmt.Println("ecies: encryption should not have succeeded") + t.FailNow() + } +} + +func TestDecryptShared2(t *testing.T) { + prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + t.Fatal(err) + } + message := []byte("Hello, world.") + shared2 := []byte("shared data 2") + ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, shared2) + if err != nil { + t.Fatal(err) + } + + // Check that decrypting with correct shared data works. + pt, err := prv.Decrypt(ct, nil, shared2) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(pt, message) { + t.Fatal("ecies: plaintext doesn't match message") + } + + // Decrypting without shared data or incorrect shared data fails. + if _, err = prv.Decrypt(ct, nil, nil); err == nil { + t.Fatal("ecies: decrypting without shared data didn't fail") + } + if _, err = prv.Decrypt(ct, nil, []byte("garbage")); err == nil { + t.Fatal("ecies: decrypting with incorrect shared data didn't fail") + } +} + +type testCase struct { + Curve elliptic.Curve + Name string + Expected *ECIESParams +} + +var testCases = []testCase{ + { + Curve: elliptic.P256(), + Name: "P256", + Expected: ECIES_AES128_SHA256, + }, + { + Curve: elliptic.P384(), + Name: "P384", + Expected: ECIES_AES256_SHA384, + }, + { + Curve: elliptic.P521(), + Name: "P521", + Expected: ECIES_AES256_SHA512, + }, +} + +// Test parameter selection for each curve, and that P224 fails automatic +// parameter selection (see README for a discussion of P224). Ensures that +// selecting a set of parameters automatically for the given curve works. +func TestParamSelection(t *testing.T) { + for _, c := range testCases { + testParamSelection(t, c) + } +} + +func testParamSelection(t *testing.T, c testCase) { + params := ParamsFromCurve(c.Curve) + if params == nil && c.Expected != nil { + fmt.Printf("%s (%s)\n", ErrInvalidParams.Error(), c.Name) + t.FailNow() + } else if params != nil && !cmpParams(params, c.Expected) { + fmt.Printf("ecies: parameters should be invalid (%s)\n", + c.Name) + t.FailNow() + } + + prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + fmt.Printf("%s (%s)\n", err.Error(), c.Name) + t.FailNow() + } + + prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + fmt.Printf("%s (%s)\n", err.Error(), c.Name) + t.FailNow() + } + + message := []byte("Hello, world.") + ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) + if err != nil { + fmt.Printf("%s (%s)\n", err.Error(), c.Name) + t.FailNow() + } + + pt, err := prv2.Decrypt(ct, nil, nil) + if err != nil { + fmt.Printf("%s (%s)\n", err.Error(), c.Name) + t.FailNow() + } + + if !bytes.Equal(pt, message) { + fmt.Printf("ecies: plaintext doesn't match message (%s)\n", + c.Name) + t.FailNow() + } + + _, err = prv1.Decrypt(ct, nil, nil) + if err == nil { + fmt.Printf("ecies: encryption should not have succeeded (%s)\n", + c.Name) + t.FailNow() + } + +} + +// Ensure that the basic public key validation in the decryption operation +// works. +func TestBasicKeyValidation(t *testing.T) { + badBytes := []byte{0, 1, 5, 6, 7, 8, 9} + + prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + message := []byte("Hello, world.") + ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, nil) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + for _, b := range badBytes { + ct[0] = b + _, err := prv.Decrypt(ct, nil, nil) + if err != ErrInvalidPublicKey { + fmt.Println("ecies: validated an invalid key") + t.FailNow() + } + } +} + +func TestBox(t *testing.T) { + prv1 := hexKey("4b50fa71f5c3eeb8fdc452224b2395af2fcc3d125e06c32c82e048c0559db03f") + prv2 := hexKey("d0b043b4c5d657670778242d82d68a29d25d7d711127d17b8e299f156dad361a") + pub2 := &prv2.PublicKey + + message := []byte("Hello, world.") + ct, err := Encrypt(rand.Reader, pub2, message, nil, nil) + if err != nil { + t.Fatal(err) + } + + pt, err := prv2.Decrypt(ct, nil, nil) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(pt, message) { + t.Fatal("ecies: plaintext doesn't match message") + } + if _, err = prv1.Decrypt(ct, nil, nil); err == nil { + t.Fatal("ecies: encryption should not have succeeded") + } +} + +// Verify GenerateShared against static values - useful when +// debugging changes in underlying libs +func TestSharedKeyStatic(t *testing.T) { + prv1 := hexKey("7ebbc6a8358bc76dd73ebc557056702c8cfc34e5cfcd90eb83af0347575fd2ad") + prv2 := hexKey("6a3d6396903245bba5837752b9e0348874e72db0c4e11e9c485a81b4ea4353b9") + + skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2 + + sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen) + if err != nil { + fmt.Println(err.Error()) + t.FailNow() + } + + if !bytes.Equal(sk1, sk2) { + fmt.Println(ErrBadSharedKeys.Error()) + t.FailNow() + } + + sk, _ := hex.DecodeString("167ccc13ac5e8a26b131c3446030c60fbfac6aa8e31149d0869f93626a4cdf62") + if !bytes.Equal(sk1, sk) { + t.Fatalf("shared secret mismatch: want: %x have: %x", sk, sk1) + } +} + +func hexKey(prv string) *PrivateKey { + key, err := crypto.HexToECDSA(prv) + if err != nil { + panic(err) + } + return ImportECDSA(key) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/ecies/params.go b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/params.go new file mode 100644 index 0000000000..6312daf5a1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/ecies/params.go @@ -0,0 +1,117 @@ +// Copyright (c) 2013 Kyle Isom +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package ecies + +// This file contains parameters for ECIES encryption, specifying the +// symmetric encryption and HMAC parameters. + +import ( + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/elliptic" + "crypto/sha256" + "crypto/sha512" + "fmt" + "hash" + + ethcrypto "github.com/ethereum/go-ethereum/crypto" +) + +var ( + DefaultCurve = ethcrypto.S256() + ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm") + ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters") +) + +type ECIESParams struct { + Hash func() hash.Hash // hash function + hashAlgo crypto.Hash + Cipher func([]byte) (cipher.Block, error) // symmetric cipher + BlockSize int // block size of symmetric cipher + KeyLen int // length of symmetric key +} + +// Standard ECIES parameters: +// * ECIES using AES128 and HMAC-SHA-256-16 +// * ECIES using AES256 and HMAC-SHA-256-32 +// * ECIES using AES256 and HMAC-SHA-384-48 +// * ECIES using AES256 and HMAC-SHA-512-64 + +var ( + ECIES_AES128_SHA256 = &ECIESParams{ + Hash: sha256.New, + hashAlgo: crypto.SHA256, + Cipher: aes.NewCipher, + BlockSize: aes.BlockSize, + KeyLen: 16, + } + + ECIES_AES256_SHA256 = &ECIESParams{ + Hash: sha256.New, + hashAlgo: crypto.SHA256, + Cipher: aes.NewCipher, + BlockSize: aes.BlockSize, + KeyLen: 32, + } + + ECIES_AES256_SHA384 = &ECIESParams{ + Hash: sha512.New384, + hashAlgo: crypto.SHA384, + Cipher: aes.NewCipher, + BlockSize: aes.BlockSize, + KeyLen: 32, + } + + ECIES_AES256_SHA512 = &ECIESParams{ + Hash: sha512.New, + hashAlgo: crypto.SHA512, + Cipher: aes.NewCipher, + BlockSize: aes.BlockSize, + KeyLen: 32, + } +) + +var paramsFromCurve = map[elliptic.Curve]*ECIESParams{ + ethcrypto.S256(): ECIES_AES128_SHA256, + elliptic.P256(): ECIES_AES128_SHA256, + elliptic.P384(): ECIES_AES256_SHA384, + elliptic.P521(): ECIES_AES256_SHA512, +} + +func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) { + paramsFromCurve[curve] = params +} + +// ParamsFromCurve selects parameters optimal for the selected elliptic curve. +// Only the curves P256, P384, and P512 are supported. +func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) { + return paramsFromCurve[curve] +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go b/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go index 340bfc221e..aadf028d26 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build !nacl,!js,!nocgo +// +build !nacl,!js,cgo package crypto diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go b/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go index e8fa18ed47..90d072cda7 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build nacl js nocgo +// +build nacl js !cgo package crypto diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/interface.go b/vendor/github.com/ethereum/go-ethereum/ethdb/batch.go similarity index 53% rename from vendor/github.com/ethereum/go-ethereum/ethdb/interface.go rename to vendor/github.com/ethereum/go-ethereum/ethdb/batch.go index af13557798..a9c4063546 100644 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/interface.go +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/batch.go @@ -1,4 +1,4 @@ -// Copyright 2014 The go-ethereum Authors +// Copyright 2018 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify @@ -16,37 +16,31 @@ package ethdb -// Code using batches should try to add this much data to the batch. -// The value was determined empirically. +// IdealBatchSize defines the size of the data batches should ideally add in one +// write. const IdealBatchSize = 100 * 1024 -// Putter wraps the database write operation supported by both batches and regular databases. -type Putter interface { - Put(key []byte, value []byte) error -} - -// Deleter wraps the database delete operation supported by both batches and regular databases. -type Deleter interface { - Delete(key []byte) error -} - -// Database wraps all database operations. All methods are safe for concurrent use. -type Database interface { - Putter - Deleter - Get(key []byte) ([]byte, error) - Has(key []byte) (bool, error) - Close() - NewBatch() Batch -} - // Batch is a write-only database that commits changes to its host database -// when Write is called. Batch cannot be used concurrently. +// when Write is called. A batch cannot be used concurrently. type Batch interface { - Putter - Deleter - ValueSize() int // amount of data in the batch + Writer + + // ValueSize retrieves the amount of data queued up for writing. + ValueSize() int + + // Write flushes any accumulated data to disk. Write() error - // Reset resets the batch for reuse + + // Reset resets the batch for reuse. Reset() + + // Replay replays the batch contents. + Replay(w Writer) error +} + +// Batcher wraps the NewBatch method of a backing data store. +type Batcher interface { + // NewBatch creates a write-only database that buffers changes to its host db + // until a final write is called. + NewBatch() Batch } diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/database.go b/vendor/github.com/ethereum/go-ethereum/ethdb/database.go index 6c62d6a386..bab99aed1f 100644 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/database.go +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/database.go @@ -1,4 +1,4 @@ -// Copyright 2014 The go-ethereum Authors +// Copyright 2018 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify @@ -14,371 +14,67 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build !js - +// Package ethdb defines the interfaces for an Ethereum data store. package ethdb -import ( - "fmt" - "strconv" - "strings" - "sync" - "time" - - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/syndtr/goleveldb/leveldb" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/filter" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/util" -) - -const ( - writePauseWarningThrottler = 1 * time.Minute -) - -var OpenFileLimit = 64 - -type LDBDatabase struct { - fn string // filename for reporting - db *leveldb.DB // LevelDB instance - - compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction - compReadMeter metrics.Meter // Meter for measuring the data read during compaction - compWriteMeter metrics.Meter // Meter for measuring the data written during compaction - writeDelayNMeter metrics.Meter // Meter for measuring the write delay number due to database compaction - writeDelayMeter metrics.Meter // Meter for measuring the write delay duration due to database compaction - diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read - diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written - - quitLock sync.Mutex // Mutex protecting the quit channel access - quitChan chan chan error // Quit channel to stop the metrics collection before closing the database - - log log.Logger // Contextual logger tracking the database path -} - -// NewLDBDatabase returns a LevelDB wrapped object. -func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) { - logger := log.New("database", file) - - // Ensure we have some minimal caching and file guarantees - if cache < 16 { - cache = 16 - } - if handles < 16 { - handles = 16 - } - logger.Info("Allocated cache and file handles", "cache", cache, "handles", handles) - - // Open the db and recover any potential corruptions - db, err := leveldb.OpenFile(file, &opt.Options{ - OpenFilesCacheCapacity: handles, - BlockCacheCapacity: cache / 2 * opt.MiB, - WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally - Filter: filter.NewBloomFilter(10), - }) - if _, corrupted := err.(*errors.ErrCorrupted); corrupted { - db, err = leveldb.RecoverFile(file, nil) - } - // (Re)check for errors and abort if opening of the db failed - if err != nil { - return nil, err - } - return &LDBDatabase{ - fn: file, - db: db, - log: logger, - }, nil -} - -// Path returns the path to the database directory. -func (db *LDBDatabase) Path() string { - return db.fn -} - -// Put puts the given key / value to the queue -func (db *LDBDatabase) Put(key []byte, value []byte) error { - return db.db.Put(key, value, nil) -} - -func (db *LDBDatabase) Has(key []byte) (bool, error) { - return db.db.Has(key, nil) -} - -// Get returns the given key if it's present. -func (db *LDBDatabase) Get(key []byte) ([]byte, error) { - dat, err := db.db.Get(key, nil) - if err != nil { - return nil, err - } - return dat, nil -} - -// Delete deletes the key from the queue and database -func (db *LDBDatabase) Delete(key []byte) error { - return db.db.Delete(key, nil) -} - -func (db *LDBDatabase) NewIterator() iterator.Iterator { - return db.db.NewIterator(nil, nil) -} - -// NewIteratorWithPrefix returns a iterator to iterate over subset of database content with a particular prefix. -func (db *LDBDatabase) NewIteratorWithPrefix(prefix []byte) iterator.Iterator { - return db.db.NewIterator(util.BytesPrefix(prefix), nil) -} - -func (db *LDBDatabase) Close() { - // Stop the metrics collection to avoid internal database races - db.quitLock.Lock() - defer db.quitLock.Unlock() - - if db.quitChan != nil { - errc := make(chan error) - db.quitChan <- errc - if err := <-errc; err != nil { - db.log.Error("Metrics collection failed", "err", err) - } - db.quitChan = nil - } - err := db.db.Close() - if err == nil { - db.log.Info("Database closed") - } else { - db.log.Error("Failed to close database", "err", err) - } -} - -func (db *LDBDatabase) LDB() *leveldb.DB { - return db.db -} - -// Meter configures the database metrics collectors and -func (db *LDBDatabase) Meter(prefix string) { - // Initialize all the metrics collector at the requested prefix - db.compTimeMeter = metrics.NewRegisteredMeter(prefix+"compact/time", nil) - db.compReadMeter = metrics.NewRegisteredMeter(prefix+"compact/input", nil) - db.compWriteMeter = metrics.NewRegisteredMeter(prefix+"compact/output", nil) - db.diskReadMeter = metrics.NewRegisteredMeter(prefix+"disk/read", nil) - db.diskWriteMeter = metrics.NewRegisteredMeter(prefix+"disk/write", nil) - db.writeDelayMeter = metrics.NewRegisteredMeter(prefix+"compact/writedelay/duration", nil) - db.writeDelayNMeter = metrics.NewRegisteredMeter(prefix+"compact/writedelay/counter", nil) - - // Create a quit channel for the periodic collector and run it - db.quitLock.Lock() - db.quitChan = make(chan chan error) - db.quitLock.Unlock() - - go db.meter(3 * time.Second) -} - -// meter periodically retrieves internal leveldb counters and reports them to -// the metrics subsystem. -// -// This is how a stats table look like (currently): -// Compactions -// Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB) -// -------+------------+---------------+---------------+---------------+--------------- -// 0 | 0 | 0.00000 | 1.27969 | 0.00000 | 12.31098 -// 1 | 85 | 109.27913 | 28.09293 | 213.92493 | 214.26294 -// 2 | 523 | 1000.37159 | 7.26059 | 66.86342 | 66.77884 -// 3 | 570 | 1113.18458 | 0.00000 | 0.00000 | 0.00000 -// -// This is how the write delay look like (currently): -// DelayN:5 Delay:406.604657ms Paused: false -// -// This is how the iostats look like (currently): -// Read(MB):3895.04860 Write(MB):3654.64712 -func (db *LDBDatabase) meter(refresh time.Duration) { - // Create the counters to store current and previous compaction values - compactions := make([][]float64, 2) - for i := 0; i < 2; i++ { - compactions[i] = make([]float64, 3) - } - // Create storage for iostats. - var iostats [2]float64 - - // Create storage and warning log tracer for write delay. - var ( - delaystats [2]int64 - lastWritePaused time.Time - ) - - var ( - errc chan error - merr error - ) - - // Iterate ad infinitum and collect the stats - for i := 1; errc == nil && merr == nil; i++ { - // Retrieve the database stats - stats, err := db.db.GetProperty("leveldb.stats") - if err != nil { - db.log.Error("Failed to read database stats", "err", err) - merr = err - continue - } - // Find the compaction table, skip the header - lines := strings.Split(stats, "\n") - for len(lines) > 0 && strings.TrimSpace(lines[0]) != "Compactions" { - lines = lines[1:] - } - if len(lines) <= 3 { - db.log.Error("Compaction table not found") - merr = errors.New("compaction table not found") - continue - } - lines = lines[3:] - - // Iterate over all the table rows, and accumulate the entries - for j := 0; j < len(compactions[i%2]); j++ { - compactions[i%2][j] = 0 - } - for _, line := range lines { - parts := strings.Split(line, "|") - if len(parts) != 6 { - break - } - for idx, counter := range parts[3:] { - value, err := strconv.ParseFloat(strings.TrimSpace(counter), 64) - if err != nil { - db.log.Error("Compaction entry parsing failed", "err", err) - merr = err - continue - } - compactions[i%2][idx] += value - } - } - // Update all the requested meters - if db.compTimeMeter != nil { - db.compTimeMeter.Mark(int64((compactions[i%2][0] - compactions[(i-1)%2][0]) * 1000 * 1000 * 1000)) - } - if db.compReadMeter != nil { - db.compReadMeter.Mark(int64((compactions[i%2][1] - compactions[(i-1)%2][1]) * 1024 * 1024)) - } - if db.compWriteMeter != nil { - db.compWriteMeter.Mark(int64((compactions[i%2][2] - compactions[(i-1)%2][2]) * 1024 * 1024)) - } - - // Retrieve the write delay statistic - writedelay, err := db.db.GetProperty("leveldb.writedelay") - if err != nil { - db.log.Error("Failed to read database write delay statistic", "err", err) - merr = err - continue - } - var ( - delayN int64 - delayDuration string - duration time.Duration - paused bool - ) - if n, err := fmt.Sscanf(writedelay, "DelayN:%d Delay:%s Paused:%t", &delayN, &delayDuration, &paused); n != 3 || err != nil { - db.log.Error("Write delay statistic not found") - merr = err - continue - } - duration, err = time.ParseDuration(delayDuration) - if err != nil { - db.log.Error("Failed to parse delay duration", "err", err) - merr = err - continue - } - if db.writeDelayNMeter != nil { - db.writeDelayNMeter.Mark(delayN - delaystats[0]) - } - if db.writeDelayMeter != nil { - db.writeDelayMeter.Mark(duration.Nanoseconds() - delaystats[1]) - } - // If a warning that db is performing compaction has been displayed, any subsequent - // warnings will be withheld for one minute not to overwhelm the user. - if paused && delayN-delaystats[0] == 0 && duration.Nanoseconds()-delaystats[1] == 0 && - time.Now().After(lastWritePaused.Add(writePauseWarningThrottler)) { - db.log.Warn("Database compacting, degraded performance") - lastWritePaused = time.Now() - } - delaystats[0], delaystats[1] = delayN, duration.Nanoseconds() - - // Retrieve the database iostats. - ioStats, err := db.db.GetProperty("leveldb.iostats") - if err != nil { - db.log.Error("Failed to read database iostats", "err", err) - merr = err - continue - } - var nRead, nWrite float64 - parts := strings.Split(ioStats, " ") - if len(parts) < 2 { - db.log.Error("Bad syntax of ioStats", "ioStats", ioStats) - merr = fmt.Errorf("bad syntax of ioStats %s", ioStats) - continue - } - if n, err := fmt.Sscanf(parts[0], "Read(MB):%f", &nRead); n != 1 || err != nil { - db.log.Error("Bad syntax of read entry", "entry", parts[0]) - merr = err - continue - } - if n, err := fmt.Sscanf(parts[1], "Write(MB):%f", &nWrite); n != 1 || err != nil { - db.log.Error("Bad syntax of write entry", "entry", parts[1]) - merr = err - continue - } - if db.diskReadMeter != nil { - db.diskReadMeter.Mark(int64((nRead - iostats[0]) * 1024 * 1024)) - } - if db.diskWriteMeter != nil { - db.diskWriteMeter.Mark(int64((nWrite - iostats[1]) * 1024 * 1024)) - } - iostats[0], iostats[1] = nRead, nWrite - - // Sleep a bit, then repeat the stats collection - select { - case errc = <-db.quitChan: - // Quit requesting, stop hammering the database - case <-time.After(refresh): - // Timeout, gather a new set of stats - } - } - - if errc == nil { - errc = <-db.quitChan - } - errc <- merr -} - -func (db *LDBDatabase) NewBatch() Batch { - return &ldbBatch{db: db.db, b: new(leveldb.Batch)} -} - -type ldbBatch struct { - db *leveldb.DB - b *leveldb.Batch - size int -} - -func (b *ldbBatch) Put(key, value []byte) error { - b.b.Put(key, value) - b.size += len(value) - return nil -} - -func (b *ldbBatch) Delete(key []byte) error { - b.b.Delete(key) - b.size += 1 - return nil -} - -func (b *ldbBatch) Write() error { - return b.db.Write(b.b, nil) -} - -func (b *ldbBatch) ValueSize() int { - return b.size -} - -func (b *ldbBatch) Reset() { - b.b.Reset() - b.size = 0 +import "io" + +// Reader wraps the Has and Get method of a backing data store. +type Reader interface { + // Has retrieves if a key is present in the key-value data store. + Has(key []byte) (bool, error) + + // Get retrieves the given key if it's present in the key-value data store. + Get(key []byte) ([]byte, error) +} + +// Writer wraps the Put method of a backing data store. +type Writer interface { + // Put inserts the given value into the key-value data store. + Put(key []byte, value []byte) error + + // Delete removes the key from the key-value data store. + Delete(key []byte) error +} + +// Stater wraps the Stat method of a backing data store. +type Stater interface { + // Stat returns a particular internal stat of the database. + Stat(property string) (string, error) +} + +// Compacter wraps the Compact method of a backing data store. +type Compacter interface { + // Compact flattens the underlying data store for the given key range. In essence, + // deleted and overwritten versions are discarded, and the data is rearranged to + // reduce the cost of operations needed to access them. + // + // A nil start is treated as a key before all keys in the data store; a nil limit + // is treated as a key after all keys in the data store. If both is nil then it + // will compact entire data store. + Compact(start []byte, limit []byte) error +} + +// KeyValueStore contains all the methods required to allow handling different +// key-value data stores backing the high level database. +type KeyValueStore interface { + Reader + Writer + Batcher + Iteratee + Stater + Compacter + io.Closer +} + +// Database contains all the methods required by the high level database to not +// only access the key-value data store but also the chain freezer. +type Database interface { + Reader + Writer + Batcher + Iteratee + Stater + Compacter + io.Closer } diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/database_js.go b/vendor/github.com/ethereum/go-ethereum/ethdb/database_js.go deleted file mode 100644 index ba6eeb5a23..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/database_js.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// +build js - -package ethdb - -import ( - "errors" -) - -var errNotSupported = errors.New("ethdb: not supported") - -type LDBDatabase struct { -} - -// NewLDBDatabase returns a LevelDB wrapped object. -func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) { - return nil, errNotSupported -} - -// Path returns the path to the database directory. -func (db *LDBDatabase) Path() string { - return "" -} - -// Put puts the given key / value to the queue -func (db *LDBDatabase) Put(key []byte, value []byte) error { - return errNotSupported -} - -func (db *LDBDatabase) Has(key []byte) (bool, error) { - return false, errNotSupported -} - -// Get returns the given key if it's present. -func (db *LDBDatabase) Get(key []byte) ([]byte, error) { - return nil, errNotSupported -} - -// Delete deletes the key from the queue and database -func (db *LDBDatabase) Delete(key []byte) error { - return errNotSupported -} - -func (db *LDBDatabase) Close() { -} - -// Meter configures the database metrics collectors and -func (db *LDBDatabase) Meter(prefix string) { -} - -func (db *LDBDatabase) NewBatch() Batch { - return nil -} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/iterator.go b/vendor/github.com/ethereum/go-ethereum/ethdb/iterator.go new file mode 100644 index 0000000000..f3cee7ec9c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/iterator.go @@ -0,0 +1,61 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package ethdb + +// Iterator iterates over a database's key/value pairs in ascending key order. +// +// When it encounters an error any seek will return false and will yield no key/ +// value pairs. The error can be queried by calling the Error method. Calling +// Release is still necessary. +// +// An iterator must be released after use, but it is not necessary to read an +// iterator until exhaustion. An iterator is not safe for concurrent use, but it +// is safe to use multiple iterators concurrently. +type Iterator interface { + // Next moves the iterator to the next key/value pair. It returns whether the + // iterator is exhausted. + Next() bool + + // Error returns any accumulated error. Exhausting all the key/value pairs + // is not considered to be an error. + Error() error + + // Key returns the key of the current key/value pair, or nil if done. The caller + // should not modify the contents of the returned slice, and its contents may + // change on the next call to Next. + Key() []byte + + // Value returns the value of the current key/value pair, or nil if done. The + // caller should not modify the contents of the returned slice, and its contents + // may change on the next call to Next. + Value() []byte + + // Release releases associated resources. Release should always succeed and can + // be called multiple times without causing error. + Release() +} + +// Iteratee wraps the NewIterator methods of a backing data store. +type Iteratee interface { + // NewIterator creates a binary-alphabetical iterator over the entire keyspace + // contained within the key-value database. + NewIterator() Iterator + + // NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset + // of database content with a particular key prefix. + NewIteratorWithPrefix(prefix []byte) Iterator +} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go b/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go new file mode 100644 index 0000000000..f437cb9740 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go @@ -0,0 +1,447 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build !js + +// Package leveldb implements the key-value database layer based on LevelDB. +package leveldb + +import ( + "fmt" + "strconv" + "strings" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" + "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/errors" + "github.com/syndtr/goleveldb/leveldb/filter" + "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/syndtr/goleveldb/leveldb/util" +) + +const ( + // degradationWarnInterval specifies how often warning should be printed if the + // leveldb database cannot keep up with requested writes. + degradationWarnInterval = time.Minute + + // minCache is the minimum amount of memory in megabytes to allocate to leveldb + // read and write caching, split half and half. + minCache = 16 + + // minHandles is the minimum number of files handles to allocate to the open + // database files. + minHandles = 16 + + // metricsGatheringInterval specifies the interval to retrieve leveldb database + // compaction, io and pause stats to report to the user. + metricsGatheringInterval = 3 * time.Second +) + +// Database is a persistent key-value store. Apart from basic data storage +// functionality it also supports batch writes and iterating over the keyspace in +// binary-alphabetical order. +type Database struct { + fn string // filename for reporting + db *leveldb.DB // LevelDB instance + + compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction + compReadMeter metrics.Meter // Meter for measuring the data read during compaction + compWriteMeter metrics.Meter // Meter for measuring the data written during compaction + writeDelayNMeter metrics.Meter // Meter for measuring the write delay number due to database compaction + writeDelayMeter metrics.Meter // Meter for measuring the write delay duration due to database compaction + diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read + diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written + + quitLock sync.Mutex // Mutex protecting the quit channel access + quitChan chan chan error // Quit channel to stop the metrics collection before closing the database + + log log.Logger // Contextual logger tracking the database path +} + +// New returns a wrapped LevelDB object. The namespace is the prefix that the +// metrics reporting should use for surfacing internal stats. +func New(file string, cache int, handles int, namespace string) (*Database, error) { + // Ensure we have some minimal caching and file guarantees + if cache < minCache { + cache = minCache + } + if handles < minHandles { + handles = minHandles + } + logger := log.New("database", file) + logger.Info("Allocated cache and file handles", "cache", common.StorageSize(cache*1024*1024), "handles", handles) + + // Open the db and recover any potential corruptions + db, err := leveldb.OpenFile(file, &opt.Options{ + OpenFilesCacheCapacity: handles, + BlockCacheCapacity: cache / 2 * opt.MiB, + WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally + Filter: filter.NewBloomFilter(10), + }) + if _, corrupted := err.(*errors.ErrCorrupted); corrupted { + db, err = leveldb.RecoverFile(file, nil) + } + if err != nil { + return nil, err + } + // Assemble the wrapper with all the registered metrics + ldb := &Database{ + fn: file, + db: db, + log: logger, + quitChan: make(chan chan error), + } + ldb.compTimeMeter = metrics.NewRegisteredMeter(namespace+"compact/time", nil) + ldb.compReadMeter = metrics.NewRegisteredMeter(namespace+"compact/input", nil) + ldb.compWriteMeter = metrics.NewRegisteredMeter(namespace+"compact/output", nil) + ldb.diskReadMeter = metrics.NewRegisteredMeter(namespace+"disk/read", nil) + ldb.diskWriteMeter = metrics.NewRegisteredMeter(namespace+"disk/write", nil) + ldb.writeDelayMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/duration", nil) + ldb.writeDelayNMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/counter", nil) + + // Start up the metrics gathering and return + go ldb.meter(metricsGatheringInterval) + return ldb, nil +} + +// Close stops the metrics collection, flushes any pending data to disk and closes +// all io accesses to the underlying key-value store. +func (db *Database) Close() error { + db.quitLock.Lock() + defer db.quitLock.Unlock() + + if db.quitChan != nil { + errc := make(chan error) + db.quitChan <- errc + if err := <-errc; err != nil { + db.log.Error("Metrics collection failed", "err", err) + } + db.quitChan = nil + } + return db.db.Close() +} + +// Has retrieves if a key is present in the key-value store. +func (db *Database) Has(key []byte) (bool, error) { + return db.db.Has(key, nil) +} + +// Get retrieves the given key if it's present in the key-value store. +func (db *Database) Get(key []byte) ([]byte, error) { + dat, err := db.db.Get(key, nil) + if err != nil { + return nil, err + } + return dat, nil +} + +// Put inserts the given value into the key-value store. +func (db *Database) Put(key []byte, value []byte) error { + return db.db.Put(key, value, nil) +} + +// Delete removes the key from the key-value store. +func (db *Database) Delete(key []byte) error { + return db.db.Delete(key, nil) +} + +// NewBatch creates a write-only key-value store that buffers changes to its host +// database until a final write is called. +func (db *Database) NewBatch() ethdb.Batch { + return &batch{ + db: db.db, + b: new(leveldb.Batch), + } +} + +// NewIterator creates a binary-alphabetical iterator over the entire keyspace +// contained within the leveldb database. +func (db *Database) NewIterator() ethdb.Iterator { + return db.NewIteratorWithPrefix(nil) +} + +// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset +// of database content with a particular key prefix. +func (db *Database) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator { + return db.db.NewIterator(util.BytesPrefix(prefix), nil) +} + +// Stat returns a particular internal stat of the database. +func (db *Database) Stat(property string) (string, error) { + return db.db.GetProperty(property) +} + +// Compact flattens the underlying data store for the given key range. In essence, +// deleted and overwritten versions are discarded, and the data is rearranged to +// reduce the cost of operations needed to access them. +// +// A nil start is treated as a key before all keys in the data store; a nil limit +// is treated as a key after all keys in the data store. If both is nil then it +// will compact entire data store. +func (db *Database) Compact(start []byte, limit []byte) error { + return db.db.CompactRange(util.Range{Start: start, Limit: limit}) +} + +// Path returns the path to the database directory. +func (db *Database) Path() string { + return db.fn +} + +// meter periodically retrieves internal leveldb counters and reports them to +// the metrics subsystem. +// +// This is how a LevelDB stats table looks like (currently): +// Compactions +// Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB) +// -------+------------+---------------+---------------+---------------+--------------- +// 0 | 0 | 0.00000 | 1.27969 | 0.00000 | 12.31098 +// 1 | 85 | 109.27913 | 28.09293 | 213.92493 | 214.26294 +// 2 | 523 | 1000.37159 | 7.26059 | 66.86342 | 66.77884 +// 3 | 570 | 1113.18458 | 0.00000 | 0.00000 | 0.00000 +// +// This is how the write delay look like (currently): +// DelayN:5 Delay:406.604657ms Paused: false +// +// This is how the iostats look like (currently): +// Read(MB):3895.04860 Write(MB):3654.64712 +func (db *Database) meter(refresh time.Duration) { + // Create the counters to store current and previous compaction values + compactions := make([][]float64, 2) + for i := 0; i < 2; i++ { + compactions[i] = make([]float64, 3) + } + // Create storage for iostats. + var iostats [2]float64 + + // Create storage and warning log tracer for write delay. + var ( + delaystats [2]int64 + lastWritePaused time.Time + ) + + var ( + errc chan error + merr error + ) + + // Iterate ad infinitum and collect the stats + for i := 1; errc == nil && merr == nil; i++ { + // Retrieve the database stats + stats, err := db.db.GetProperty("leveldb.stats") + if err != nil { + db.log.Error("Failed to read database stats", "err", err) + merr = err + continue + } + // Find the compaction table, skip the header + lines := strings.Split(stats, "\n") + for len(lines) > 0 && strings.TrimSpace(lines[0]) != "Compactions" { + lines = lines[1:] + } + if len(lines) <= 3 { + db.log.Error("Compaction leveldbTable not found") + merr = errors.New("compaction leveldbTable not found") + continue + } + lines = lines[3:] + + // Iterate over all the leveldbTable rows, and accumulate the entries + for j := 0; j < len(compactions[i%2]); j++ { + compactions[i%2][j] = 0 + } + for _, line := range lines { + parts := strings.Split(line, "|") + if len(parts) != 6 { + break + } + for idx, counter := range parts[3:] { + value, err := strconv.ParseFloat(strings.TrimSpace(counter), 64) + if err != nil { + db.log.Error("Compaction entry parsing failed", "err", err) + merr = err + continue + } + compactions[i%2][idx] += value + } + } + // Update all the requested meters + if db.compTimeMeter != nil { + db.compTimeMeter.Mark(int64((compactions[i%2][0] - compactions[(i-1)%2][0]) * 1000 * 1000 * 1000)) + } + if db.compReadMeter != nil { + db.compReadMeter.Mark(int64((compactions[i%2][1] - compactions[(i-1)%2][1]) * 1024 * 1024)) + } + if db.compWriteMeter != nil { + db.compWriteMeter.Mark(int64((compactions[i%2][2] - compactions[(i-1)%2][2]) * 1024 * 1024)) + } + + // Retrieve the write delay statistic + writedelay, err := db.db.GetProperty("leveldb.writedelay") + if err != nil { + db.log.Error("Failed to read database write delay statistic", "err", err) + merr = err + continue + } + var ( + delayN int64 + delayDuration string + duration time.Duration + paused bool + ) + if n, err := fmt.Sscanf(writedelay, "DelayN:%d Delay:%s Paused:%t", &delayN, &delayDuration, &paused); n != 3 || err != nil { + db.log.Error("Write delay statistic not found") + merr = err + continue + } + duration, err = time.ParseDuration(delayDuration) + if err != nil { + db.log.Error("Failed to parse delay duration", "err", err) + merr = err + continue + } + if db.writeDelayNMeter != nil { + db.writeDelayNMeter.Mark(delayN - delaystats[0]) + } + if db.writeDelayMeter != nil { + db.writeDelayMeter.Mark(duration.Nanoseconds() - delaystats[1]) + } + // If a warning that db is performing compaction has been displayed, any subsequent + // warnings will be withheld for one minute not to overwhelm the user. + if paused && delayN-delaystats[0] == 0 && duration.Nanoseconds()-delaystats[1] == 0 && + time.Now().After(lastWritePaused.Add(degradationWarnInterval)) { + db.log.Warn("Database compacting, degraded performance") + lastWritePaused = time.Now() + } + delaystats[0], delaystats[1] = delayN, duration.Nanoseconds() + + // Retrieve the database iostats. + ioStats, err := db.db.GetProperty("leveldb.iostats") + if err != nil { + db.log.Error("Failed to read database iostats", "err", err) + merr = err + continue + } + var nRead, nWrite float64 + parts := strings.Split(ioStats, " ") + if len(parts) < 2 { + db.log.Error("Bad syntax of ioStats", "ioStats", ioStats) + merr = fmt.Errorf("bad syntax of ioStats %s", ioStats) + continue + } + if n, err := fmt.Sscanf(parts[0], "Read(MB):%f", &nRead); n != 1 || err != nil { + db.log.Error("Bad syntax of read entry", "entry", parts[0]) + merr = err + continue + } + if n, err := fmt.Sscanf(parts[1], "Write(MB):%f", &nWrite); n != 1 || err != nil { + db.log.Error("Bad syntax of write entry", "entry", parts[1]) + merr = err + continue + } + if db.diskReadMeter != nil { + db.diskReadMeter.Mark(int64((nRead - iostats[0]) * 1024 * 1024)) + } + if db.diskWriteMeter != nil { + db.diskWriteMeter.Mark(int64((nWrite - iostats[1]) * 1024 * 1024)) + } + iostats[0], iostats[1] = nRead, nWrite + + // Sleep a bit, then repeat the stats collection + select { + case errc = <-db.quitChan: + // Quit requesting, stop hammering the database + case <-time.After(refresh): + // Timeout, gather a new set of stats + } + } + + if errc == nil { + errc = <-db.quitChan + } + errc <- merr +} + +// batch is a write-only leveldb batch that commits changes to its host database +// when Write is called. A batch cannot be used concurrently. +type batch struct { + db *leveldb.DB + b *leveldb.Batch + size int +} + +// Put inserts the given value into the batch for later committing. +func (b *batch) Put(key, value []byte) error { + b.b.Put(key, value) + b.size += len(value) + return nil +} + +// Delete inserts the a key removal into the batch for later committing. +func (b *batch) Delete(key []byte) error { + b.b.Delete(key) + b.size++ + return nil +} + +// ValueSize retrieves the amount of data queued up for writing. +func (b *batch) ValueSize() int { + return b.size +} + +// Write flushes any accumulated data to disk. +func (b *batch) Write() error { + return b.db.Write(b.b, nil) +} + +// Reset resets the batch for reuse. +func (b *batch) Reset() { + b.b.Reset() + b.size = 0 +} + +// Replay replays the batch contents. +func (b *batch) Replay(w ethdb.Writer) error { + return b.b.Replay(&replayer{writer: w}) +} + +// replayer is a small wrapper to implement the correct replay methods. +type replayer struct { + writer ethdb.Writer + failure error +} + +// Put inserts the given value into the key-value data store. +func (r *replayer) Put(key, value []byte) { + // If the replay already failed, stop executing ops + if r.failure != nil { + return + } + r.failure = r.writer.Put(key, value) +} + +// Delete removes the key from the key-value data store. +func (r *replayer) Delete(key []byte) { + // If the replay already failed, stop executing ops + if r.failure != nil { + return + } + r.failure = r.writer.Delete(key) +} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/memory_database.go b/vendor/github.com/ethereum/go-ethereum/ethdb/memory_database.go deleted file mode 100644 index 727f2f7ca3..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/memory_database.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package ethdb - -import ( - "errors" - "sync" - - "github.com/ethereum/go-ethereum/common" -) - -/* - * This is a test memory database. Do not use for any production it does not get persisted - */ -type MemDatabase struct { - db map[string][]byte - lock sync.RWMutex -} - -func NewMemDatabase() *MemDatabase { - return &MemDatabase{ - db: make(map[string][]byte), - } -} - -func NewMemDatabaseWithCap(size int) *MemDatabase { - return &MemDatabase{ - db: make(map[string][]byte, size), - } -} - -func (db *MemDatabase) Put(key []byte, value []byte) error { - db.lock.Lock() - defer db.lock.Unlock() - - db.db[string(key)] = common.CopyBytes(value) - return nil -} - -func (db *MemDatabase) Has(key []byte) (bool, error) { - db.lock.RLock() - defer db.lock.RUnlock() - - _, ok := db.db[string(key)] - return ok, nil -} - -func (db *MemDatabase) Get(key []byte) ([]byte, error) { - db.lock.RLock() - defer db.lock.RUnlock() - - if entry, ok := db.db[string(key)]; ok { - return common.CopyBytes(entry), nil - } - return nil, errors.New("not found") -} - -func (db *MemDatabase) Keys() [][]byte { - db.lock.RLock() - defer db.lock.RUnlock() - - keys := [][]byte{} - for key := range db.db { - keys = append(keys, []byte(key)) - } - return keys -} - -func (db *MemDatabase) Delete(key []byte) error { - db.lock.Lock() - defer db.lock.Unlock() - - delete(db.db, string(key)) - return nil -} - -func (db *MemDatabase) Close() {} - -func (db *MemDatabase) NewBatch() Batch { - return &memBatch{db: db} -} - -func (db *MemDatabase) Len() int { return len(db.db) } - -type kv struct { - k, v []byte - del bool -} - -type memBatch struct { - db *MemDatabase - writes []kv - size int -} - -func (b *memBatch) Put(key, value []byte) error { - b.writes = append(b.writes, kv{common.CopyBytes(key), common.CopyBytes(value), false}) - b.size += len(value) - return nil -} - -func (b *memBatch) Delete(key []byte) error { - b.writes = append(b.writes, kv{common.CopyBytes(key), nil, true}) - b.size += 1 - return nil -} - -func (b *memBatch) Write() error { - b.db.lock.Lock() - defer b.db.lock.Unlock() - - for _, kv := range b.writes { - if kv.del { - delete(b.db.db, string(kv.k)) - continue - } - b.db.db[string(kv.k)] = kv.v - } - return nil -} - -func (b *memBatch) ValueSize() int { - return b.size -} - -func (b *memBatch) Reset() { - b.writes = b.writes[:0] - b.size = 0 -} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/memorydb/memorydb.go b/vendor/github.com/ethereum/go-ethereum/ethdb/memorydb/memorydb.go new file mode 100644 index 0000000000..5c3f7e22a3 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/memorydb/memorydb.go @@ -0,0 +1,314 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package memorydb implements the key-value database layer based on memory maps. +package memorydb + +import ( + "errors" + "sort" + "strings" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" +) + +var ( + // errMemorydbClosed is returned if a memory database was already closed at the + // invocation of a data access operation. + errMemorydbClosed = errors.New("database closed") + + // errMemorydbNotFound is returned if a key is requested that is not found in + // the provided memory database. + errMemorydbNotFound = errors.New("not found") +) + +// Database is an ephemeral key-value store. Apart from basic data storage +// functionality it also supports batch writes and iterating over the keyspace in +// binary-alphabetical order. +type Database struct { + db map[string][]byte + lock sync.RWMutex +} + +// New returns a wrapped map with all the required database interface methods +// implemented. +func New() *Database { + return &Database{ + db: make(map[string][]byte), + } +} + +// NewWithCap returns a wrapped map pre-allocated to the provided capcity with +// all the required database interface methods implemented. +func NewWithCap(size int) *Database { + return &Database{ + db: make(map[string][]byte, size), + } +} + +// Close deallocates the internal map and ensures any consecutive data access op +// failes with an error. +func (db *Database) Close() error { + db.lock.Lock() + defer db.lock.Unlock() + + db.db = nil + return nil +} + +// Has retrieves if a key is present in the key-value store. +func (db *Database) Has(key []byte) (bool, error) { + db.lock.RLock() + defer db.lock.RUnlock() + + if db.db == nil { + return false, errMemorydbClosed + } + _, ok := db.db[string(key)] + return ok, nil +} + +// Get retrieves the given key if it's present in the key-value store. +func (db *Database) Get(key []byte) ([]byte, error) { + db.lock.RLock() + defer db.lock.RUnlock() + + if db.db == nil { + return nil, errMemorydbClosed + } + if entry, ok := db.db[string(key)]; ok { + return common.CopyBytes(entry), nil + } + return nil, errMemorydbNotFound +} + +// Put inserts the given value into the key-value store. +func (db *Database) Put(key []byte, value []byte) error { + db.lock.Lock() + defer db.lock.Unlock() + + if db.db == nil { + return errMemorydbClosed + } + db.db[string(key)] = common.CopyBytes(value) + return nil +} + +// Delete removes the key from the key-value store. +func (db *Database) Delete(key []byte) error { + db.lock.Lock() + defer db.lock.Unlock() + + if db.db == nil { + return errMemorydbClosed + } + delete(db.db, string(key)) + return nil +} + +// NewBatch creates a write-only key-value store that buffers changes to its host +// database until a final write is called. +func (db *Database) NewBatch() ethdb.Batch { + return &batch{ + db: db, + } +} + +// NewIterator creates a binary-alphabetical iterator over the entire keyspace +// contained within the memory database. +func (db *Database) NewIterator() ethdb.Iterator { + return db.NewIteratorWithPrefix(nil) +} + +// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset +// of database content with a particular key prefix. +func (db *Database) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator { + db.lock.RLock() + defer db.lock.RUnlock() + + var ( + pr = string(prefix) + keys = make([]string, 0, len(db.db)) + values = make([][]byte, 0, len(db.db)) + ) + // Collect the keys from the memory database corresponding to the given prefix + for key := range db.db { + if strings.HasPrefix(key, pr) { + keys = append(keys, key) + } + } + // Sort the items and retrieve the associated values + sort.Strings(keys) + for _, key := range keys { + values = append(values, db.db[key]) + } + return &iterator{ + keys: keys, + values: values, + } +} + +// Stat returns a particular internal stat of the database. +func (db *Database) Stat(property string) (string, error) { + return "", errors.New("unknown property") +} + +// Compact is not supported on a memory database. +func (db *Database) Compact(start []byte, limit []byte) error { + return errors.New("unsupported operation") +} + +// Len returns the number of entries currently present in the memory database. +// +// Note, this method is only used for testing (i.e. not public in general) and +// does not have explicit checks for closed-ness to allow simpler testing code. +func (db *Database) Len() int { + db.lock.RLock() + defer db.lock.RUnlock() + + return len(db.db) +} + +// keyvalue is a key-value tuple tagged with a deletion field to allow creating +// memory-database write batches. +type keyvalue struct { + key []byte + value []byte + delete bool +} + +// batch is a write-only memory batch that commits changes to its host +// database when Write is called. A batch cannot be used concurrently. +type batch struct { + db *Database + writes []keyvalue + size int +} + +// Put inserts the given value into the batch for later committing. +func (b *batch) Put(key, value []byte) error { + b.writes = append(b.writes, keyvalue{common.CopyBytes(key), common.CopyBytes(value), false}) + b.size += len(value) + return nil +} + +// Delete inserts the a key removal into the batch for later committing. +func (b *batch) Delete(key []byte) error { + b.writes = append(b.writes, keyvalue{common.CopyBytes(key), nil, true}) + b.size += 1 + return nil +} + +// ValueSize retrieves the amount of data queued up for writing. +func (b *batch) ValueSize() int { + return b.size +} + +// Write flushes any accumulated data to the memory database. +func (b *batch) Write() error { + b.db.lock.Lock() + defer b.db.lock.Unlock() + + for _, keyvalue := range b.writes { + if keyvalue.delete { + delete(b.db.db, string(keyvalue.key)) + continue + } + b.db.db[string(keyvalue.key)] = keyvalue.value + } + return nil +} + +// Reset resets the batch for reuse. +func (b *batch) Reset() { + b.writes = b.writes[:0] + b.size = 0 +} + +// Replay replays the batch contents. +func (b *batch) Replay(w ethdb.Writer) error { + for _, keyvalue := range b.writes { + if keyvalue.delete { + if err := w.Delete(keyvalue.key); err != nil { + return err + } + continue + } + if err := w.Put(keyvalue.key, keyvalue.value); err != nil { + return err + } + } + return nil +} + +// iterator can walk over the (potentially partial) keyspace of a memory key +// value store. Internally it is a deep copy of the entire iterated state, +// sorted by keys. +type iterator struct { + inited bool + keys []string + values [][]byte +} + +// Next moves the iterator to the next key/value pair. It returns whether the +// iterator is exhausted. +func (it *iterator) Next() bool { + // If the iterator was not yet initialized, do it now + if !it.inited { + it.inited = true + return len(it.keys) > 0 + } + // Iterator already initialize, advance it + if len(it.keys) > 0 { + it.keys = it.keys[1:] + it.values = it.values[1:] + } + return len(it.keys) > 0 +} + +// Error returns any accumulated error. Exhausting all the key/value pairs +// is not considered to be an error. A memory iterator cannot encounter errors. +func (it *iterator) Error() error { + return nil +} + +// Key returns the key of the current key/value pair, or nil if done. The caller +// should not modify the contents of the returned slice, and its contents may +// change on the next call to Next. +func (it *iterator) Key() []byte { + if len(it.keys) > 0 { + return []byte(it.keys[0]) + } + return nil +} + +// Value returns the value of the current key/value pair, or nil if done. The +// caller should not modify the contents of the returned slice, and its contents +// may change on the next call to Next. +func (it *iterator) Value() []byte { + if len(it.values) > 0 { + return it.values[0] + } + return nil +} + +// Release releases associated resources. Release should always succeed and can +// be called multiple times without causing error. +func (it *iterator) Release() { + it.keys, it.values = nil, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/table.go b/vendor/github.com/ethereum/go-ethereum/ethdb/table.go deleted file mode 100644 index 28069c078e..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/table.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package ethdb - -type table struct { - db Database - prefix string -} - -// NewTable returns a Database object that prefixes all keys with a given -// string. -func NewTable(db Database, prefix string) Database { - return &table{ - db: db, - prefix: prefix, - } -} - -func (dt *table) Put(key []byte, value []byte) error { - return dt.db.Put(append([]byte(dt.prefix), key...), value) -} - -func (dt *table) Has(key []byte) (bool, error) { - return dt.db.Has(append([]byte(dt.prefix), key...)) -} - -func (dt *table) Get(key []byte) ([]byte, error) { - return dt.db.Get(append([]byte(dt.prefix), key...)) -} - -func (dt *table) Delete(key []byte) error { - return dt.db.Delete(append([]byte(dt.prefix), key...)) -} - -func (dt *table) Close() { - // Do nothing; don't close the underlying DB. -} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/table_batch.go b/vendor/github.com/ethereum/go-ethereum/ethdb/table_batch.go deleted file mode 100644 index ae83e79ced..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/table_batch.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package ethdb - -type tableBatch struct { - batch Batch - prefix string -} - -// NewTableBatch returns a Batch object which prefixes all keys with a given string. -func NewTableBatch(db Database, prefix string) Batch { - return &tableBatch{db.NewBatch(), prefix} -} - -func (dt *table) NewBatch() Batch { - return &tableBatch{dt.db.NewBatch(), dt.prefix} -} - -func (tb *tableBatch) Put(key, value []byte) error { - return tb.batch.Put(append([]byte(tb.prefix), key...), value) -} - -func (tb *tableBatch) Delete(key []byte) error { - return tb.batch.Delete(append([]byte(tb.prefix), key...)) -} - -func (tb *tableBatch) Write() error { - return tb.batch.Write() -} - -func (tb *tableBatch) ValueSize() int { - return tb.batch.ValueSize() -} - -func (tb *tableBatch) Reset() { - tb.batch.Reset() -} diff --git a/vendor/github.com/ethereum/go-ethereum/interfaces.go b/vendor/github.com/ethereum/go-ethereum/interfaces.go index be78344062..1ff31f96b6 100644 --- a/vendor/github.com/ethereum/go-ethereum/interfaces.go +++ b/vendor/github.com/ethereum/go-ethereum/interfaces.go @@ -144,9 +144,9 @@ type FilterQuery struct { // Examples: // {} or nil matches any topic list // {{A}} matches topic A in first position - // {{}, {B}} matches any topic in first position, B in second position - // {{A}, {B}} matches topic A in first position, B in second position - // {{A, B}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position + // {{}, {B}} matches any topic in first position AND B in second position + // {{A}, {B}} matches topic A in first position AND B in second position + // {{A, B}, {C, D}} matches topic (A OR B) in first position AND (C OR D) in second position Topics [][]common.Hash } diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/metrics.go b/vendor/github.com/ethereum/go-ethereum/metrics/metrics.go index 2a2b804e7c..8ae7aec435 100644 --- a/vendor/github.com/ethereum/go-ethereum/metrics/metrics.go +++ b/vendor/github.com/ethereum/go-ethereum/metrics/metrics.go @@ -15,24 +15,41 @@ import ( ) // Enabled is checked by the constructor functions for all of the -// standard metrics. If it is true, the metric returned is a stub. +// standard metrics. If it is true, the metric returned is a stub. // // This global kill-switch helps quantify the observer effect and makes // for less cluttered pprof profiles. -var Enabled bool = false +var Enabled = false -// MetricsEnabledFlag is the CLI flag name to use to enable metrics collections. -const MetricsEnabledFlag = "metrics" -const DashboardEnabledFlag = "dashboard" +// EnabledExpensive is a soft-flag meant for external packages to check if costly +// metrics gathering is allowed or not. The goal is to separate standard metrics +// for health monitoring and debug metrics that might impact runtime performance. +var EnabledExpensive = false + +// enablerFlags is the CLI flag names to use to enable metrics collections. +var enablerFlags = []string{"metrics", "dashboard"} + +// expensiveEnablerFlags is the CLI flag names to use to enable metrics collections. +var expensiveEnablerFlags = []string{"metrics.expensive"} // Init enables or disables the metrics system. Since we need this to run before // any other code gets to create meters and timers, we'll actually do an ugly hack // and peek into the command line args for the metrics flag. func init() { for _, arg := range os.Args { - if flag := strings.TrimLeft(arg, "-"); flag == MetricsEnabledFlag || flag == DashboardEnabledFlag { - log.Info("Enabling metrics collection") - Enabled = true + flag := strings.TrimLeft(arg, "-") + + for _, enabler := range enablerFlags { + if !Enabled && flag == enabler { + log.Info("Enabling metrics collection") + Enabled = true + } + } + for _, enabler := range expensiveEnablerFlags { + if !EnabledExpensive && flag == enabler { + log.Info("Enabling expensive metrics collection") + EnabledExpensive = true + } } } } diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/opentsdb.go b/vendor/github.com/ethereum/go-ethereum/metrics/opentsdb.go index df7f152ed2..3fde55454b 100644 --- a/vendor/github.com/ethereum/go-ethereum/metrics/opentsdb.go +++ b/vendor/github.com/ethereum/go-ethereum/metrics/opentsdb.go @@ -10,7 +10,7 @@ import ( "time" ) -var shortHostName string = "" +var shortHostName = "" // OpenTSDBConfig provides a container with configuration parameters for // the OpenTSDB exporter diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/registry.go b/vendor/github.com/ethereum/go-ethereum/metrics/registry.go index c1cf7906ce..c5435adf24 100644 --- a/vendor/github.com/ethereum/go-ethereum/metrics/registry.go +++ b/vendor/github.com/ethereum/go-ethereum/metrics/registry.go @@ -312,8 +312,9 @@ func (r *PrefixedRegistry) UnregisterAll() { } var ( - DefaultRegistry = NewRegistry() - EphemeralRegistry = NewRegistry() + DefaultRegistry = NewRegistry() + EphemeralRegistry = NewRegistry() + AccountingRegistry = NewRegistry() // registry used in swarm ) // Call the given function for each registered metric. diff --git a/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go index c7190ae670..bdaa4a18c4 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go +++ b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go @@ -47,6 +47,20 @@ var RinkebyBootnodes = []string{ "enode://b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6@159.89.28.211:30303", // AKASHA } +// GoerliBootnodes are the enode URLs of the P2P bootstrap nodes running on the +// Görli test network. +var GoerliBootnodes = []string{ + // Upstrem bootnodes + "enode://011f758e6552d105183b1761c5e2dea0111bc20fd5f6422bc7f91e0fabbec9a6595caf6239b37feb773dddd3f87240d99d859431891e4a642cf2a0a9e6cbb98a@51.141.78.53:30303", + "enode://176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b@13.93.54.137:30303", + "enode://46add44b9f13965f7b9875ac6b85f016f341012d84f975377573800a863526f4da19ae2c620ec73d11591fa9510e992ecc03ad0751f53cc02f7c7ed6d55c7291@94.237.54.114:30313", + "enode://c1f8b7c2ac4453271fa07d8e9ecf9a2e8285aa0bd0c07df0131f47153306b0736fd3db8924e7a9bf0bed6b1d8d4f87362a71b033dc7c64547728d953e43e59b2@52.64.155.147:30303", + "enode://f4a9c6ee28586009fb5a96c8af13a58ed6d8315a9eee4772212c1d4d9cebe5a8b8a78ea4434f318726317d04a3f531a1ef0420cf9752605a562cfe858c46e263@213.186.16.82:30303", + + // Ethereum Foundation bootnode + "enode://573b6607cd59f241e30e4c4943fd50e99e2b6f42f9bd5ca111659d309c06741247f4f1e93843ad3e8c8c18b6e2d94c161b7ef67479b3938780a97134b618b5ce@52.56.136.200:30303", +} + // DiscoveryV5Bootnodes are the enode URLs of the P2P bootstrap nodes for the // experimental RLPx v5 topic-discovery network. var DiscoveryV5Bootnodes = []string{ diff --git a/vendor/github.com/ethereum/go-ethereum/params/config.go b/vendor/github.com/ethereum/go-ethereum/params/config.go index 2935ef1f3f..254508c0af 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/config.go +++ b/vendor/github.com/ethereum/go-ethereum/params/config.go @@ -28,6 +28,7 @@ var ( MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") TestnetGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") + GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") ) var ( @@ -42,17 +43,18 @@ var ( EIP155Block: big.NewInt(2675000), EIP158Block: big.NewInt(2675000), ByzantiumBlock: big.NewInt(4370000), - ConstantinopleBlock: big.NewInt(7080000), + ConstantinopleBlock: big.NewInt(7280000), + PetersburgBlock: big.NewInt(7280000), Ethash: new(EthashConfig), } // MainnetTrustedCheckpoint contains the light client trusted checkpoint for the main network. MainnetTrustedCheckpoint = &TrustedCheckpoint{ Name: "mainnet", - SectionIndex: 208, - SectionHead: common.HexToHash("0x5e9f7696c397d9df8f3b1abda857753575c6f5cff894e1a3d9e1a2af1bd9d6ac"), - CHTRoot: common.HexToHash("0x954a63134f6897f015f026387c59c98c4dae7b336610ff5a143455aac9153e9d"), - BloomRoot: common.HexToHash("0x8006c5e44b14d90d7cc9cd5fa1cb48cf53697ee3bbbf4b76fdfa70b0242500a9"), + SectionIndex: 227, + SectionHead: common.HexToHash("0xa2e0b25d72c2fc6e35a7f853cdacb193b4b4f95c606accf7f8fa8415283582c7"), + CHTRoot: common.HexToHash("0xf69bdd4053b95b61a27b106a0e86103d791edd8574950dc96aa351ab9b9f1aa0"), + BloomRoot: common.HexToHash("0xec1b454d4c6322c78ccedf76ac922a8698c3cac4d98748a84af4995b7bd3d744"), } // TestnetChainConfig contains the chain parameters to run a node on the Ropsten test network. @@ -67,16 +69,17 @@ var ( EIP158Block: big.NewInt(10), ByzantiumBlock: big.NewInt(1700000), ConstantinopleBlock: big.NewInt(4230000), + PetersburgBlock: big.NewInt(4939394), Ethash: new(EthashConfig), } // TestnetTrustedCheckpoint contains the light client trusted checkpoint for the Ropsten test network. TestnetTrustedCheckpoint = &TrustedCheckpoint{ Name: "testnet", - SectionIndex: 139, - SectionHead: common.HexToHash("0x9fad89a5e3b993c8339b9cf2cbbeb72cd08774ea6b71b105b3dd880420c618f4"), - CHTRoot: common.HexToHash("0xc815833881989c5d2035147e1a79a33d22cbc5313e104ff01e6ab405bd28b317"), - BloomRoot: common.HexToHash("0xd94ee9f3c480858f53ec5d059aebdbb2e8d904702f100875ee59ec5f366e841d"), + SectionIndex: 161, + SectionHead: common.HexToHash("0x5378afa734e1feafb34bcca1534c4d96952b754579b96a4afb23d5301ecececc"), + CHTRoot: common.HexToHash("0x1cf2b071e7443a62914362486b613ff30f60cea0d9c268ed8c545f876a3ee60c"), + BloomRoot: common.HexToHash("0x5ac25c84bd18a9cbe878d4609a80220f57f85037a112644532412ba0d498a31b"), } // RinkebyChainConfig contains the chain parameters to run a node on the Rinkeby test network. @@ -91,6 +94,7 @@ var ( EIP158Block: big.NewInt(3), ByzantiumBlock: big.NewInt(1035301), ConstantinopleBlock: big.NewInt(3660663), + PetersburgBlock: big.NewInt(4321234), Clique: &CliqueConfig{ Period: 15, Epoch: 30000, @@ -100,10 +104,37 @@ var ( // RinkebyTrustedCheckpoint contains the light client trusted checkpoint for the Rinkeby test network. RinkebyTrustedCheckpoint = &TrustedCheckpoint{ Name: "rinkeby", - SectionIndex: 105, - SectionHead: common.HexToHash("0xec8147d43f936258aaf1b9b9ec91b0a853abf7109f436a23649be809ea43d507"), - CHTRoot: common.HexToHash("0xd92703b444846a3db928e87e450770e5d5cbe193131dc8f7c4cf18b4de925a75"), - BloomRoot: common.HexToHash("0xff45a6f807138a2cde0cea0c209d9ce5ad8e43ccaae5a7c41af801bb72a1ef96"), + SectionIndex: 125, + SectionHead: common.HexToHash("0x8a738386f6bb34add15846f8f49c4c519a2f32519096e792b9f43bcb407c831c"), + CHTRoot: common.HexToHash("0xa1e5720a9bad4dce794f129e4ac6744398197b652868011486a6f89c8ec84a75"), + BloomRoot: common.HexToHash("0xa3048fe8b7e30f77f11bc755a88478363d7d3e71c2bdfe4e8ab9e269cd804ba2"), + } + + // GoerliChainConfig contains the chain parameters to run a node on the Görli test network. + GoerliChainConfig = &ChainConfig{ + ChainID: big.NewInt(5), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + Clique: &CliqueConfig{ + Period: 15, + Epoch: 30000, + }, + } + + // GoerliTrustedCheckpoint contains the light client trusted checkpoint for the Görli test network. + GoerliTrustedCheckpoint = &TrustedCheckpoint{ + Name: "goerli", + SectionIndex: 9, + SectionHead: common.HexToHash("0x8e223d827391eee53b07cb8ee057dbfa11c93e0b45352188c783affd7840a921"), + CHTRoot: common.HexToHash("0xe0a817ac69b36c1e437c5b0cff9e764853f5115702b5f66d451b665d6afb7e78"), + BloomRoot: common.HexToHash("0x50d672aeb655b723284969c7c1201fb6ca003c23ed144bcb9f2d1b30e2971c1b"), } // AllEthashProtocolChanges contains every protocol change (EIPs) introduced @@ -111,16 +142,16 @@ var ( // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} + AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}} + AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}} - TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} TestRules = TestChainConfig.Rules(new(big.Int)) ) @@ -158,6 +189,7 @@ type ChainConfig struct { ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium) ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated) + PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople) EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated) // Various consensus engines @@ -195,7 +227,7 @@ func (c *ChainConfig) String() string { default: engine = "unknown" } - return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Engine: %v}", + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v ConstantinopleFix: %v Engine: %v}", c.ChainID, c.HomesteadBlock, c.DAOForkBlock, @@ -205,6 +237,7 @@ func (c *ChainConfig) String() string { c.EIP158Block, c.ByzantiumBlock, c.ConstantinopleBlock, + c.PetersburgBlock, engine, ) } @@ -244,6 +277,13 @@ func (c *ChainConfig) IsConstantinople(num *big.Int) bool { return isForked(c.ConstantinopleBlock, num) } +// IsPetersburg returns whether num is either +// - equal to or greater than the PetersburgBlock fork block, +// - OR is nil, and Constantinople is active +func (c *ChainConfig) IsPetersburg(num *big.Int) bool { + return isForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isForked(c.ConstantinopleBlock, num) +} + // IsEWASM returns whether num represents a block number after the EWASM fork func (c *ChainConfig) IsEWASM(num *big.Int) bool { return isForked(c.EWASMBlock, num) @@ -314,6 +354,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi if isForkIncompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, head) { return newCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock) } + if isForkIncompatible(c.PetersburgBlock, newcfg.PetersburgBlock, head) { + return newCompatError("ConstantinopleFix fork block", c.PetersburgBlock, newcfg.PetersburgBlock) + } if isForkIncompatible(c.EWASMBlock, newcfg.EWASMBlock, head) { return newCompatError("ewasm fork block", c.EWASMBlock, newcfg.EWASMBlock) } @@ -381,9 +424,9 @@ func (err *ConfigCompatError) Error() string { // Rules is a one time interface meaning that it shouldn't be used in between transition // phases. type Rules struct { - ChainID *big.Int - IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool - IsByzantium, IsConstantinople bool + ChainID *big.Int + IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool + IsByzantium, IsConstantinople, IsPetersburg bool } // Rules ensures c's ChainID is not nil. @@ -400,5 +443,6 @@ func (c *ChainConfig) Rules(num *big.Int) Rules { IsEIP158: c.IsEIP158(num), IsByzantium: c.IsByzantium(num), IsConstantinople: c.IsConstantinople(num), + IsPetersburg: c.IsPetersburg(num), } } diff --git a/vendor/github.com/ethereum/go-ethereum/params/network_params.go b/vendor/github.com/ethereum/go-ethereum/params/network_params.go index f8731e8979..024c4af457 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/network_params.go +++ b/vendor/github.com/ethereum/go-ethereum/params/network_params.go @@ -32,13 +32,8 @@ const ( // considered probably final and its rotated bits are calculated. BloomConfirms = 256 - // CHTFrequencyClient is the block frequency for creating CHTs on the client side. - CHTFrequencyClient = 32768 - - // CHTFrequencyServer is the block frequency for creating CHTs on the server side. - // Eventually this can be merged back with the client version, but that requires a - // full database upgrade, so that should be left for a suitable moment. - CHTFrequencyServer = 4096 + // CHTFrequency is the block frequency for creating CHTs + CHTFrequency = 32768 // BloomTrieFrequency is the block frequency for creating BloomTrie on both // server/client sides. diff --git a/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go b/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go index c8b6609afb..14750f6a1a 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go +++ b/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go @@ -52,7 +52,7 @@ const ( NetSstoreResetRefund uint64 = 4800 // Once per SSTORE operation for resetting to the original non-zero value NetSstoreResetClearRefund uint64 = 19800 // Once per SSTORE operation for resetting to the original zero value - JumpdestGas uint64 = 1 // Refunded gas, once per SSTORE operation if the zeroness changes to zero. + JumpdestGas uint64 = 1 // Once per JUMPDEST operation. EpochDuration uint64 = 30000 // Duration between proof-of-work epochs. CallGas uint64 = 40 // Once per CALL operation & message call transaction. CreateDataGas uint64 = 200 // diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/decode.go b/vendor/github.com/ethereum/go-ethereum/rlp/decode.go index dbbe599597..e638c01eaf 100644 --- a/vendor/github.com/ethereum/go-ethereum/rlp/decode.go +++ b/vendor/github.com/ethereum/go-ethereum/rlp/decode.go @@ -26,6 +26,7 @@ import ( "math/big" "reflect" "strings" + "sync" ) var ( @@ -48,6 +49,10 @@ var ( errUintOverflow = errors.New("rlp: uint overflow") errNoPointer = errors.New("rlp: interface given to Decode must be a pointer") errDecodeIntoNil = errors.New("rlp: pointer given to Decode must not be nil") + + streamPool = sync.Pool{ + New: func() interface{} { return new(Stream) }, + } ) // Decoder is implemented by types that require custom RLP @@ -126,17 +131,24 @@ type Decoder interface { // // NewStream(r, limit).Decode(val) func Decode(r io.Reader, val interface{}) error { - // TODO: this could use a Stream from a pool. - return NewStream(r, 0).Decode(val) + stream := streamPool.Get().(*Stream) + defer streamPool.Put(stream) + + stream.Reset(r, 0) + return stream.Decode(val) } // DecodeBytes parses RLP data from b into val. // Please see the documentation of Decode for the decoding rules. // The input must contain exactly one value and no trailing data. func DecodeBytes(b []byte, val interface{}) error { - // TODO: this could use a Stream from a pool. r := bytes.NewReader(b) - if err := NewStream(r, uint64(len(b))).Decode(val); err != nil { + + stream := streamPool.Get().(*Stream) + defer streamPool.Put(stream) + + stream.Reset(r, uint64(len(b))) + if err := stream.Decode(val); err != nil { return err } if r.Len() > 0 { @@ -853,6 +865,7 @@ func (s *Stream) Reset(r io.Reader, inputLimit uint64) { if s.uintbuf == nil { s.uintbuf = make([]byte, 8) } + s.byteval = 0 } // Kind returns the kind and size of the next value in the diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/client.go b/vendor/github.com/ethereum/go-ethereum/rpc/client.go index 6254c95ffd..02029dc8f6 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/client.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/client.go @@ -18,17 +18,13 @@ package rpc import ( "bytes" - "container/list" "context" "encoding/json" "errors" "fmt" - "net" "net/url" "reflect" "strconv" - "strings" - "sync" "sync/atomic" "time" @@ -39,13 +35,14 @@ var ( ErrClientQuit = errors.New("client is closed") ErrNoResult = errors.New("no result in JSON-RPC response") ErrSubscriptionQueueOverflow = errors.New("subscription queue overflow") + errClientReconnected = errors.New("client reconnected") + errDead = errors.New("connection lost") ) const ( // Timeouts tcpKeepAliveInterval = 30 * time.Second - defaultDialTimeout = 10 * time.Second // used when dialing if the context has no deadline - defaultWriteTimeout = 10 * time.Second // used for calls if the context has no deadline + defaultDialTimeout = 10 * time.Second // used if context has no deadline subscribeTimeout = 5 * time.Second // overall timeout eth_subscribe, rpc_modules calls ) @@ -76,56 +73,57 @@ type BatchElem struct { Error error } -// A value of this type can a JSON-RPC request, notification, successful response or -// error response. Which one it is depends on the fields. -type jsonrpcMessage struct { - Version string `json:"jsonrpc"` - ID json.RawMessage `json:"id,omitempty"` - Method string `json:"method,omitempty"` - Params json.RawMessage `json:"params,omitempty"` - Error *jsonError `json:"error,omitempty"` - Result json.RawMessage `json:"result,omitempty"` -} +// Client represents a connection to an RPC server. +type Client struct { + idgen func() ID // for subscriptions + isHTTP bool + services *serviceRegistry -func (msg *jsonrpcMessage) isNotification() bool { - return msg.ID == nil && msg.Method != "" -} + idCounter uint32 -func (msg *jsonrpcMessage) isResponse() bool { - return msg.hasValidID() && msg.Method == "" && len(msg.Params) == 0 -} + // This function, if non-nil, is called when the connection is lost. + reconnectFunc reconnectFunc + + // writeConn is used for writing to the connection on the caller's goroutine. It should + // only be accessed outside of dispatch, with the write lock held. The write lock is + // taken by sending on requestOp and released by sending on sendDone. + writeConn jsonWriter -func (msg *jsonrpcMessage) hasValidID() bool { - return len(msg.ID) > 0 && msg.ID[0] != '{' && msg.ID[0] != '[' + // for dispatch + close chan struct{} + closing chan struct{} // closed when client is quitting + didClose chan struct{} // closed when client quits + reconnected chan ServerCodec // where write/reconnect sends the new connection + readOp chan readOp // read messages + readErr chan error // errors from read + reqInit chan *requestOp // register response IDs, takes write lock + reqSent chan error // signals write completion, releases write lock + reqTimeout chan *requestOp // removes response IDs when call timeout expires } -func (msg *jsonrpcMessage) String() string { - b, _ := json.Marshal(msg) - return string(b) +type reconnectFunc func(ctx context.Context) (ServerCodec, error) + +type clientContextKey struct{} + +type clientConn struct { + codec ServerCodec + handler *handler } -// Client represents a connection to an RPC server. -type Client struct { - idCounter uint32 - connectFunc func(ctx context.Context) (net.Conn, error) - isHTTP bool +func (c *Client) newClientConn(conn ServerCodec) *clientConn { + ctx := context.WithValue(context.Background(), clientContextKey{}, c) + handler := newHandler(ctx, conn, c.idgen, c.services) + return &clientConn{conn, handler} +} - // writeConn is only safe to access outside dispatch, with the - // write lock held. The write lock is taken by sending on - // requestOp and released by sending on sendDone. - writeConn net.Conn +func (cc *clientConn) close(err error, inflightReq *requestOp) { + cc.handler.close(err, inflightReq) + cc.codec.Close() +} - // for dispatch - close chan struct{} - closing chan struct{} // closed when client is quitting - didClose chan struct{} // closed when client quits - reconnected chan net.Conn // where write/reconnect sends the new connection - readErr chan error // errors from read - readResp chan []*jsonrpcMessage // valid messages from read - requestOp chan *requestOp // for registering response IDs - sendDone chan error // signals write completion, releases write lock - respWait map[string]*requestOp // active requests - subs map[string]*ClientSubscription // active subscriptions +type readOp struct { + msgs []*jsonrpcMessage + batch bool } type requestOp struct { @@ -135,9 +133,14 @@ type requestOp struct { sub *ClientSubscription // only set for EthSubscribe requests } -func (op *requestOp) wait(ctx context.Context) (*jsonrpcMessage, error) { +func (op *requestOp) wait(ctx context.Context, c *Client) (*jsonrpcMessage, error) { select { case <-ctx.Done(): + // Send the timeout to dispatch so it can remove the request IDs. + select { + case c.reqTimeout <- op: + case <-c.closing: + } return nil, ctx.Err() case resp := <-op.resp: return resp, op.err @@ -181,36 +184,57 @@ func DialContext(ctx context.Context, rawurl string) (*Client, error) { } } -func newClient(initctx context.Context, connectFunc func(context.Context) (net.Conn, error)) (*Client, error) { - conn, err := connectFunc(initctx) +// Client retrieves the client from the context, if any. This can be used to perform +// 'reverse calls' in a handler method. +func ClientFromContext(ctx context.Context) (*Client, bool) { + client, ok := ctx.Value(clientContextKey{}).(*Client) + return client, ok +} + +func newClient(initctx context.Context, connect reconnectFunc) (*Client, error) { + conn, err := connect(initctx) if err != nil { return nil, err } + c := initClient(conn, randomIDGenerator(), new(serviceRegistry)) + c.reconnectFunc = connect + return c, nil +} + +func initClient(conn ServerCodec, idgen func() ID, services *serviceRegistry) *Client { _, isHTTP := conn.(*httpConn) c := &Client{ - writeConn: conn, + idgen: idgen, isHTTP: isHTTP, - connectFunc: connectFunc, + services: services, + writeConn: conn, close: make(chan struct{}), closing: make(chan struct{}), didClose: make(chan struct{}), - reconnected: make(chan net.Conn), + reconnected: make(chan ServerCodec), + readOp: make(chan readOp), readErr: make(chan error), - readResp: make(chan []*jsonrpcMessage), - requestOp: make(chan *requestOp), - sendDone: make(chan error, 1), - respWait: make(map[string]*requestOp), - subs: make(map[string]*ClientSubscription), + reqInit: make(chan *requestOp), + reqSent: make(chan error, 1), + reqTimeout: make(chan *requestOp), } if !isHTTP { go c.dispatch(conn) } - return c, nil + return c +} + +// RegisterName creates a service for the given receiver type under the given name. When no +// methods on the given receiver match the criteria to be either a RPC method or a +// subscription an error is returned. Otherwise a new service is created and added to the +// service collection this client provides to the server. +func (c *Client) RegisterName(name string, receiver interface{}) error { + return c.services.registerName(name, receiver) } func (c *Client) nextID() json.RawMessage { id := atomic.AddUint32(&c.idCounter, 1) - return []byte(strconv.FormatUint(uint64(id), 10)) + return strconv.AppendUint(nil, uint64(id), 10) } // SupportedModules calls the rpc_modules method, retrieving the list of @@ -267,7 +291,7 @@ func (c *Client) CallContext(ctx context.Context, result interface{}, method str } // dispatch has accepted the request and will close the channel when it quits. - switch resp, err := op.wait(ctx); { + switch resp, err := op.wait(ctx, c); { case err != nil: return err case resp.Error != nil: @@ -325,7 +349,7 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error { // Wait for all responses to come back. for n := 0; n < len(b) && err == nil; n++ { var resp *jsonrpcMessage - resp, err = op.wait(ctx) + resp, err = op.wait(ctx, c) if err != nil { break } @@ -352,6 +376,22 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error { return err } +// Notify sends a notification, i.e. a method call that doesn't expect a response. +func (c *Client) Notify(ctx context.Context, method string, args ...interface{}) error { + op := new(requestOp) + msg, err := c.newMessage(method, args...) + if err != nil { + return err + } + msg.ID = nil + + if c.isHTTP { + return c.sendHTTP(ctx, op, msg) + } else { + return c.send(ctx, op, msg) + } +} + // EthSubscribe registers a subscripion under the "eth" namespace. func (c *Client) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error) { return c.Subscribe(ctx, "eth", channel, args...) @@ -402,30 +442,30 @@ func (c *Client) Subscribe(ctx context.Context, namespace string, channel interf if err := c.send(ctx, op, msg); err != nil { return nil, err } - if _, err := op.wait(ctx); err != nil { + if _, err := op.wait(ctx, c); err != nil { return nil, err } return op.sub, nil } func (c *Client) newMessage(method string, paramsIn ...interface{}) (*jsonrpcMessage, error) { - params, err := json.Marshal(paramsIn) - if err != nil { - return nil, err + msg := &jsonrpcMessage{Version: vsn, ID: c.nextID(), Method: method} + if paramsIn != nil { // prevent sending "params":null + var err error + if msg.Params, err = json.Marshal(paramsIn); err != nil { + return nil, err + } } - return &jsonrpcMessage{Version: "2.0", ID: c.nextID(), Method: method, Params: params}, nil + return msg, nil } // send registers op with the dispatch loop, then sends msg on the connection. // if sending fails, op is deregistered. func (c *Client) send(ctx context.Context, op *requestOp, msg interface{}) error { select { - case c.requestOp <- op: - log.Trace("", "msg", log.Lazy{Fn: func() string { - return fmt.Sprint("sending ", msg) - }}) + case c.reqInit <- op: err := c.write(ctx, msg) - c.sendDone <- err + c.reqSent <- err return err case <-ctx.Done(): // This can happen if the client is overloaded or unable to keep up with @@ -433,25 +473,17 @@ func (c *Client) send(ctx context.Context, op *requestOp, msg interface{}) error return ctx.Err() case <-c.closing: return ErrClientQuit - case <-c.didClose: - return ErrClientQuit } } func (c *Client) write(ctx context.Context, msg interface{}) error { - deadline, ok := ctx.Deadline() - if !ok { - deadline = time.Now().Add(defaultWriteTimeout) - } // The previous write failed. Try to establish a new connection. if c.writeConn == nil { if err := c.reconnect(ctx); err != nil { return err } } - c.writeConn.SetWriteDeadline(deadline) - err := json.NewEncoder(c.writeConn).Encode(msg) - c.writeConn.SetWriteDeadline(time.Time{}) + err := c.writeConn.Write(ctx, msg) if err != nil { c.writeConn = nil } @@ -459,9 +491,18 @@ func (c *Client) write(ctx context.Context, msg interface{}) error { } func (c *Client) reconnect(ctx context.Context) error { - newconn, err := c.connectFunc(ctx) + if c.reconnectFunc == nil { + return errDead + } + + if _, ok := ctx.Deadline(); !ok { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, defaultDialTimeout) + defer cancel() + } + newconn, err := c.reconnectFunc(ctx) if err != nil { - log.Trace(fmt.Sprintf("reconnect failed: %v", err)) + log.Trace("RPC client reconnect failed", "err", err) return err } select { @@ -477,322 +518,107 @@ func (c *Client) reconnect(ctx context.Context) error { // dispatch is the main loop of the client. // It sends read messages to waiting calls to Call and BatchCall // and subscription notifications to registered subscriptions. -func (c *Client) dispatch(conn net.Conn) { - // Spawn the initial read loop. - go c.read(conn) - +func (c *Client) dispatch(codec ServerCodec) { var ( - lastOp *requestOp // tracks last send operation - requestOpLock = c.requestOp // nil while the send lock is held - reading = true // if true, a read loop is running + lastOp *requestOp // tracks last send operation + reqInitLock = c.reqInit // nil while the send lock is held + conn = c.newClientConn(codec) + reading = true ) - defer close(c.didClose) defer func() { close(c.closing) - c.closeRequestOps(ErrClientQuit) - conn.Close() if reading { - // Empty read channels until read is dead. - for { - select { - case <-c.readResp: - case <-c.readErr: - return - } - } + conn.close(ErrClientQuit, nil) + c.drainRead() } + close(c.didClose) }() + // Spawn the initial read loop. + go c.read(codec) + for { select { case <-c.close: return - // Read path. - case batch := <-c.readResp: - for _, msg := range batch { - switch { - case msg.isNotification(): - log.Trace("", "msg", log.Lazy{Fn: func() string { - return fmt.Sprint("<-readResp: notification ", msg) - }}) - c.handleNotification(msg) - case msg.isResponse(): - log.Trace("", "msg", log.Lazy{Fn: func() string { - return fmt.Sprint("<-readResp: response ", msg) - }}) - c.handleResponse(msg) - default: - log.Debug("", "msg", log.Lazy{Fn: func() string { - return fmt.Sprint("<-readResp: dropping weird message", msg) - }}) - // TODO: maybe close - } + // Read path: + case op := <-c.readOp: + if op.batch { + conn.handler.handleBatch(op.msgs) + } else { + conn.handler.handleMsg(op.msgs[0]) } case err := <-c.readErr: - log.Debug("<-readErr", "err", err) - c.closeRequestOps(err) - conn.Close() + conn.handler.log.Debug("RPC connection read error", "err", err) + conn.close(err, lastOp) reading = false - case newconn := <-c.reconnected: - log.Debug("<-reconnected", "reading", reading, "remote", conn.RemoteAddr()) + // Reconnect: + case newcodec := <-c.reconnected: + log.Debug("RPC client reconnected", "reading", reading, "conn", newcodec.RemoteAddr()) if reading { - // Wait for the previous read loop to exit. This is a rare case. - conn.Close() - <-c.readErr + // Wait for the previous read loop to exit. This is a rare case which + // happens if this loop isn't notified in time after the connection breaks. + // In those cases the caller will notice first and reconnect. Closing the + // handler terminates all waiting requests (closing op.resp) except for + // lastOp, which will be transferred to the new handler. + conn.close(errClientReconnected, lastOp) + c.drainRead() } - go c.read(newconn) + go c.read(newcodec) reading = true - conn = newconn - - // Send path. - case op := <-requestOpLock: - // Stop listening for further send ops until the current one is done. - requestOpLock = nil + conn = c.newClientConn(newcodec) + // Re-register the in-flight request on the new handler + // because that's where it will be sent. + conn.handler.addRequestOp(lastOp) + + // Send path: + case op := <-reqInitLock: + // Stop listening for further requests until the current one has been sent. + reqInitLock = nil lastOp = op - for _, id := range op.ids { - c.respWait[string(id)] = op - } + conn.handler.addRequestOp(op) - case err := <-c.sendDone: + case err := <-c.reqSent: if err != nil { - // Remove response handlers for the last send. We remove those here - // because the error is already handled in Call or BatchCall. When the - // read loop goes down, it will signal all other current operations. - for _, id := range lastOp.ids { - delete(c.respWait, string(id)) - } + // Remove response handlers for the last send. When the read loop + // goes down, it will signal all other current operations. + conn.handler.removeRequestOp(lastOp) } - // Listen for send ops again. - requestOpLock = c.requestOp + // Let the next request in. + reqInitLock = c.reqInit lastOp = nil - } - } -} - -// closeRequestOps unblocks pending send ops and active subscriptions. -func (c *Client) closeRequestOps(err error) { - didClose := make(map[*requestOp]bool) - for id, op := range c.respWait { - // Remove the op so that later calls will not close op.resp again. - delete(c.respWait, id) - - if !didClose[op] { - op.err = err - close(op.resp) - didClose[op] = true + case op := <-c.reqTimeout: + conn.handler.removeRequestOp(op) } } - for id, sub := range c.subs { - delete(c.subs, id) - sub.quitWithError(err, false) - } -} - -func (c *Client) handleNotification(msg *jsonrpcMessage) { - if !strings.HasSuffix(msg.Method, notificationMethodSuffix) { - log.Debug("dropping non-subscription message", "msg", msg) - return - } - var subResult struct { - ID string `json:"subscription"` - Result json.RawMessage `json:"result"` - } - if err := json.Unmarshal(msg.Params, &subResult); err != nil { - log.Debug("dropping invalid subscription message", "msg", msg) - return - } - if c.subs[subResult.ID] != nil { - c.subs[subResult.ID].deliver(subResult.Result) - } -} - -func (c *Client) handleResponse(msg *jsonrpcMessage) { - op := c.respWait[string(msg.ID)] - if op == nil { - log.Debug("unsolicited response", "msg", msg) - return - } - delete(c.respWait, string(msg.ID)) - // For normal responses, just forward the reply to Call/BatchCall. - if op.sub == nil { - op.resp <- msg - return - } - // For subscription responses, start the subscription if the server - // indicates success. EthSubscribe gets unblocked in either case through - // the op.resp channel. - defer close(op.resp) - if msg.Error != nil { - op.err = msg.Error - return - } - if op.err = json.Unmarshal(msg.Result, &op.sub.subid); op.err == nil { - go op.sub.start() - c.subs[op.sub.subid] = op.sub - } } -// Reading happens on a dedicated goroutine. - -func (c *Client) read(conn net.Conn) error { - var ( - buf json.RawMessage - dec = json.NewDecoder(conn) - ) - readMessage := func() (rs []*jsonrpcMessage, err error) { - buf = buf[:0] - if err = dec.Decode(&buf); err != nil { - return nil, err - } - if isBatch(buf) { - err = json.Unmarshal(buf, &rs) - } else { - rs = make([]*jsonrpcMessage, 1) - err = json.Unmarshal(buf, &rs[0]) - } - return rs, err - } - +// drainRead drops read messages until an error occurs. +func (c *Client) drainRead() { for { - resp, err := readMessage() - if err != nil { - c.readErr <- err - return err - } - c.readResp <- resp - } -} - -// Subscriptions. - -// A ClientSubscription represents a subscription established through EthSubscribe. -type ClientSubscription struct { - client *Client - etype reflect.Type - channel reflect.Value - namespace string - subid string - in chan json.RawMessage - - quitOnce sync.Once // ensures quit is closed once - quit chan struct{} // quit is closed when the subscription exits - errOnce sync.Once // ensures err is closed once - err chan error -} - -func newClientSubscription(c *Client, namespace string, channel reflect.Value) *ClientSubscription { - sub := &ClientSubscription{ - client: c, - namespace: namespace, - etype: channel.Type().Elem(), - channel: channel, - quit: make(chan struct{}), - err: make(chan error, 1), - in: make(chan json.RawMessage), - } - return sub -} - -// Err returns the subscription error channel. The intended use of Err is to schedule -// resubscription when the client connection is closed unexpectedly. -// -// The error channel receives a value when the subscription has ended due -// to an error. The received error is nil if Close has been called -// on the underlying client and no other error has occurred. -// -// The error channel is closed when Unsubscribe is called on the subscription. -func (sub *ClientSubscription) Err() <-chan error { - return sub.err -} - -// Unsubscribe unsubscribes the notification and closes the error channel. -// It can safely be called more than once. -func (sub *ClientSubscription) Unsubscribe() { - sub.quitWithError(nil, true) - sub.errOnce.Do(func() { close(sub.err) }) -} - -func (sub *ClientSubscription) quitWithError(err error, unsubscribeServer bool) { - sub.quitOnce.Do(func() { - // The dispatch loop won't be able to execute the unsubscribe call - // if it is blocked on deliver. Close sub.quit first because it - // unblocks deliver. - close(sub.quit) - if unsubscribeServer { - sub.requestUnsubscribe() - } - if err != nil { - if err == ErrClientQuit { - err = nil // Adhere to subscription semantics. - } - sub.err <- err + select { + case <-c.readOp: + case <-c.readErr: + return } - }) -} - -func (sub *ClientSubscription) deliver(result json.RawMessage) (ok bool) { - select { - case sub.in <- result: - return true - case <-sub.quit: - return false } } -func (sub *ClientSubscription) start() { - sub.quitWithError(sub.forward()) -} - -func (sub *ClientSubscription) forward() (err error, unsubscribeServer bool) { - cases := []reflect.SelectCase{ - {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.quit)}, - {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.in)}, - {Dir: reflect.SelectSend, Chan: sub.channel}, - } - buffer := list.New() - defer buffer.Init() +// read decodes RPC messages from a codec, feeding them into dispatch. +func (c *Client) read(codec ServerCodec) { for { - var chosen int - var recv reflect.Value - if buffer.Len() == 0 { - // Idle, omit send case. - chosen, recv, _ = reflect.Select(cases[:2]) - } else { - // Non-empty buffer, send the first queued item. - cases[2].Send = reflect.ValueOf(buffer.Front().Value) - chosen, recv, _ = reflect.Select(cases) + msgs, batch, err := codec.Read() + if _, ok := err.(*json.SyntaxError); ok { + codec.Write(context.Background(), errorMessage(&parseError{err.Error()})) } - - switch chosen { - case 0: // <-sub.quit - return nil, false - case 1: // <-sub.in - val, err := sub.unmarshal(recv.Interface().(json.RawMessage)) - if err != nil { - return err, true - } - if buffer.Len() == maxClientSubscriptionBuffer { - return ErrSubscriptionQueueOverflow, true - } - buffer.PushBack(val) - case 2: // sub.channel<- - cases[2].Send = reflect.Value{} // Don't hold onto the value. - buffer.Remove(buffer.Front()) + if err != nil { + c.readErr <- err + return } + c.readOp <- readOp{msgs, batch} } } - -func (sub *ClientSubscription) unmarshal(result json.RawMessage) (interface{}, error) { - val := reflect.New(sub.etype) - err := json.Unmarshal(result, val.Interface()) - return val.Elem().Interface(), err -} - -func (sub *ClientSubscription) requestUnsubscribe() error { - var result interface{} - return sub.client.Call(&result, sub.namespace+unsubscribeMethodSuffix, sub.subid) -} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/doc.go b/vendor/github.com/ethereum/go-ethereum/rpc/doc.go index c60381b5ae..e5840c32d3 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/doc.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/doc.go @@ -15,43 +15,49 @@ // along with the go-ethereum library. If not, see . /* -Package rpc provides access to the exported methods of an object across a network -or other I/O connection. After creating a server instance objects can be registered, -making it visible from the outside. Exported methods that follow specific -conventions can be called remotely. It also has support for the publish/subscribe -pattern. + +Package rpc implements bi-directional JSON-RPC 2.0 on multiple transports. + +It provides access to the exported methods of an object across a network or other I/O +connection. After creating a server or client instance, objects can be registered to make +them visible as 'services'. Exported methods that follow specific conventions can be +called remotely. It also has support for the publish/subscribe pattern. + +RPC Methods Methods that satisfy the following criteria are made available for remote access: - - object must be exported + - method must be exported - method returns 0, 1 (response or error) or 2 (response and error) values - method argument(s) must be exported or builtin types - method returned value(s) must be exported or builtin types An example method: + func (s *CalcService) Add(a, b int) (int, error) -When the returned error isn't nil the returned integer is ignored and the error is -sent back to the client. Otherwise the returned integer is sent back to the client. +When the returned error isn't nil the returned integer is ignored and the error is sent +back to the client. Otherwise the returned integer is sent back to the client. -Optional arguments are supported by accepting pointer values as arguments. E.g. -if we want to do the addition in an optional finite field we can accept a mod -argument as pointer value. +Optional arguments are supported by accepting pointer values as arguments. E.g. if we want +to do the addition in an optional finite field we can accept a mod argument as pointer +value. - func (s *CalService) Add(a, b int, mod *int) (int, error) + func (s *CalcService) Add(a, b int, mod *int) (int, error) -This RPC method can be called with 2 integers and a null value as third argument. -In that case the mod argument will be nil. Or it can be called with 3 integers, -in that case mod will be pointing to the given third argument. Since the optional -argument is the last argument the RPC package will also accept 2 integers as -arguments. It will pass the mod argument as nil to the RPC method. +This RPC method can be called with 2 integers and a null value as third argument. In that +case the mod argument will be nil. Or it can be called with 3 integers, in that case mod +will be pointing to the given third argument. Since the optional argument is the last +argument the RPC package will also accept 2 integers as arguments. It will pass the mod +argument as nil to the RPC method. -The server offers the ServeCodec method which accepts a ServerCodec instance. It will -read requests from the codec, process the request and sends the response back to the -client using the codec. The server can execute requests concurrently. Responses -can be sent back to the client out of order. +The server offers the ServeCodec method which accepts a ServerCodec instance. It will read +requests from the codec, process the request and sends the response back to the client +using the codec. The server can execute requests concurrently. Responses can be sent back +to the client out of order. An example server which uses the JSON codec: + type CalculatorService struct {} func (s *CalculatorService) Add(a, b int) int { @@ -73,26 +79,40 @@ An example server which uses the JSON codec: for { c, _ := l.AcceptUnix() codec := v2.NewJSONCodec(c) - go server.ServeCodec(codec) + go server.ServeCodec(codec, 0) } +Subscriptions + The package also supports the publish subscribe pattern through the use of subscriptions. -A method that is considered eligible for notifications must satisfy the following criteria: - - object must be exported +A method that is considered eligible for notifications must satisfy the following +criteria: + - method must be exported - first method argument type must be context.Context - method argument(s) must be exported or builtin types - - method must return the tuple Subscription, error + - method must have return types (rpc.Subscription, error) An example method: - func (s *BlockChainService) NewBlocks(ctx context.Context) (Subscription, error) { + + func (s *BlockChainService) NewBlocks(ctx context.Context) (rpc.Subscription, error) { ... } -Subscriptions are deleted when: - - the user sends an unsubscribe request - - the connection which was used to create the subscription is closed. This can be initiated - by the client and server. The server will close the connection on a write error or when - the queue of buffered notifications gets too big. +When the service containing the subscription method is registered to the server, for +example under the "blockchain" namespace, a subscription is created by calling the +"blockchain_subscribe" method. + +Subscriptions are deleted when the user sends an unsubscribe request or when the +connection which was used to create the subscription is closed. This can be initiated by +the client and server. The server will close the connection for any write error. + +For more information about subscriptions, see https://github.com/ethereum/go-ethereum/wiki/RPC-PUB-SUB. + +Reverse Calls + +In any method handler, an instance of rpc.Client can be accessed through the +ClientFromContext method. Using this client instance, server-to-client method calls can be +performed on the RPC connection. */ package rpc diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/errors.go b/vendor/github.com/ethereum/go-ethereum/rpc/errors.go index 9cf9dc60c2..c3aa826cc8 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/errors.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/errors.go @@ -18,18 +18,31 @@ package rpc import "fmt" -// request is for an unknown service -type methodNotFoundError struct { - service string - method string -} +const defaultErrorCode = -32000 + +type methodNotFoundError struct{ method string } func (e *methodNotFoundError) ErrorCode() int { return -32601 } func (e *methodNotFoundError) Error() string { - return fmt.Sprintf("The method %s%s%s does not exist/is not available", e.service, serviceMethodSeparator, e.method) + return fmt.Sprintf("the method %s does not exist/is not available", e.method) +} + +type subscriptionNotFoundError struct{ namespace, subscription string } + +func (e *subscriptionNotFoundError) ErrorCode() int { return -32601 } + +func (e *subscriptionNotFoundError) Error() string { + return fmt.Sprintf("no %q subscription in %s namespace", e.subscription, e.namespace) } +// Invalid JSON was received by the server. +type parseError struct{ message string } + +func (e *parseError) ErrorCode() int { return -32700 } + +func (e *parseError) Error() string { return e.message } + // received message isn't a valid request type invalidRequestError struct{ message string } @@ -50,17 +63,3 @@ type invalidParamsError struct{ message string } func (e *invalidParamsError) ErrorCode() int { return -32602 } func (e *invalidParamsError) Error() string { return e.message } - -// logic error, callback returned an error -type callbackError struct{ message string } - -func (e *callbackError) ErrorCode() int { return -32000 } - -func (e *callbackError) Error() string { return e.message } - -// issued when a request is received after the server is issued to stop. -type shutdownError struct{} - -func (e *shutdownError) ErrorCode() int { return -32000 } - -func (e *shutdownError) Error() string { return "server is shutting down" } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/handler.go b/vendor/github.com/ethereum/go-ethereum/rpc/handler.go new file mode 100644 index 0000000000..92db89e2f8 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rpc/handler.go @@ -0,0 +1,397 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rpc + +import ( + "context" + "encoding/json" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/ethereum/go-ethereum/log" +) + +// handler handles JSON-RPC messages. There is one handler per connection. Note that +// handler is not safe for concurrent use. Message handling never blocks indefinitely +// because RPCs are processed on background goroutines launched by handler. +// +// The entry points for incoming messages are: +// +// h.handleMsg(message) +// h.handleBatch(message) +// +// Outgoing calls use the requestOp struct. Register the request before sending it +// on the connection: +// +// op := &requestOp{ids: ...} +// h.addRequestOp(op) +// +// Now send the request, then wait for the reply to be delivered through handleMsg: +// +// if err := op.wait(...); err != nil { +// h.removeRequestOp(op) // timeout, etc. +// } +// +type handler struct { + reg *serviceRegistry + unsubscribeCb *callback + idgen func() ID // subscription ID generator + respWait map[string]*requestOp // active client requests + clientSubs map[string]*ClientSubscription // active client subscriptions + callWG sync.WaitGroup // pending call goroutines + rootCtx context.Context // canceled by close() + cancelRoot func() // cancel function for rootCtx + conn jsonWriter // where responses will be sent + log log.Logger + allowSubscribe bool + + subLock sync.Mutex + serverSubs map[ID]*Subscription +} + +type callProc struct { + ctx context.Context + notifiers []*Notifier +} + +func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg *serviceRegistry) *handler { + rootCtx, cancelRoot := context.WithCancel(connCtx) + h := &handler{ + reg: reg, + idgen: idgen, + conn: conn, + respWait: make(map[string]*requestOp), + clientSubs: make(map[string]*ClientSubscription), + rootCtx: rootCtx, + cancelRoot: cancelRoot, + allowSubscribe: true, + serverSubs: make(map[ID]*Subscription), + log: log.Root(), + } + if conn.RemoteAddr() != "" { + h.log = h.log.New("conn", conn.RemoteAddr()) + } + h.unsubscribeCb = newCallback(reflect.Value{}, reflect.ValueOf(h.unsubscribe)) + return h +} + +// handleBatch executes all messages in a batch and returns the responses. +func (h *handler) handleBatch(msgs []*jsonrpcMessage) { + // Emit error response for empty batches: + if len(msgs) == 0 { + h.startCallProc(func(cp *callProc) { + h.conn.Write(cp.ctx, errorMessage(&invalidRequestError{"empty batch"})) + }) + return + } + + // Handle non-call messages first: + calls := make([]*jsonrpcMessage, 0, len(msgs)) + for _, msg := range msgs { + if handled := h.handleImmediate(msg); !handled { + calls = append(calls, msg) + } + } + if len(calls) == 0 { + return + } + // Process calls on a goroutine because they may block indefinitely: + h.startCallProc(func(cp *callProc) { + answers := make([]*jsonrpcMessage, 0, len(msgs)) + for _, msg := range calls { + if answer := h.handleCallMsg(cp, msg); answer != nil { + answers = append(answers, answer) + } + } + h.addSubscriptions(cp.notifiers) + if len(answers) > 0 { + h.conn.Write(cp.ctx, answers) + } + for _, n := range cp.notifiers { + n.activate() + } + }) +} + +// handleMsg handles a single message. +func (h *handler) handleMsg(msg *jsonrpcMessage) { + if ok := h.handleImmediate(msg); ok { + return + } + h.startCallProc(func(cp *callProc) { + answer := h.handleCallMsg(cp, msg) + h.addSubscriptions(cp.notifiers) + if answer != nil { + h.conn.Write(cp.ctx, answer) + } + for _, n := range cp.notifiers { + n.activate() + } + }) +} + +// close cancels all requests except for inflightReq and waits for +// call goroutines to shut down. +func (h *handler) close(err error, inflightReq *requestOp) { + h.cancelAllRequests(err, inflightReq) + h.cancelRoot() + h.callWG.Wait() + h.cancelServerSubscriptions(err) +} + +// addRequestOp registers a request operation. +func (h *handler) addRequestOp(op *requestOp) { + for _, id := range op.ids { + h.respWait[string(id)] = op + } +} + +// removeRequestOps stops waiting for the given request IDs. +func (h *handler) removeRequestOp(op *requestOp) { + for _, id := range op.ids { + delete(h.respWait, string(id)) + } +} + +// cancelAllRequests unblocks and removes pending requests and active subscriptions. +func (h *handler) cancelAllRequests(err error, inflightReq *requestOp) { + didClose := make(map[*requestOp]bool) + if inflightReq != nil { + didClose[inflightReq] = true + } + + for id, op := range h.respWait { + // Remove the op so that later calls will not close op.resp again. + delete(h.respWait, id) + + if !didClose[op] { + op.err = err + close(op.resp) + didClose[op] = true + } + } + for id, sub := range h.clientSubs { + delete(h.clientSubs, id) + sub.quitWithError(err, false) + } +} + +func (h *handler) addSubscriptions(nn []*Notifier) { + h.subLock.Lock() + defer h.subLock.Unlock() + + for _, n := range nn { + if sub := n.takeSubscription(); sub != nil { + h.serverSubs[sub.ID] = sub + } + } +} + +// cancelServerSubscriptions removes all subscriptions and closes their error channels. +func (h *handler) cancelServerSubscriptions(err error) { + h.subLock.Lock() + defer h.subLock.Unlock() + + for id, s := range h.serverSubs { + s.err <- err + close(s.err) + delete(h.serverSubs, id) + } +} + +// startCallProc runs fn in a new goroutine and starts tracking it in the h.calls wait group. +func (h *handler) startCallProc(fn func(*callProc)) { + h.callWG.Add(1) + go func() { + ctx, cancel := context.WithCancel(h.rootCtx) + defer h.callWG.Done() + defer cancel() + fn(&callProc{ctx: ctx}) + }() +} + +// handleImmediate executes non-call messages. It returns false if the message is a +// call or requires a reply. +func (h *handler) handleImmediate(msg *jsonrpcMessage) bool { + start := time.Now() + switch { + case msg.isNotification(): + if strings.HasSuffix(msg.Method, notificationMethodSuffix) { + h.handleSubscriptionResult(msg) + return true + } + return false + case msg.isResponse(): + h.handleResponse(msg) + h.log.Trace("Handled RPC response", "reqid", idForLog{msg.ID}, "t", time.Since(start)) + return true + default: + return false + } +} + +// handleSubscriptionResult processes subscription notifications. +func (h *handler) handleSubscriptionResult(msg *jsonrpcMessage) { + var result subscriptionResult + if err := json.Unmarshal(msg.Params, &result); err != nil { + h.log.Debug("Dropping invalid subscription message") + return + } + if h.clientSubs[result.ID] != nil { + h.clientSubs[result.ID].deliver(result.Result) + } +} + +// handleResponse processes method call responses. +func (h *handler) handleResponse(msg *jsonrpcMessage) { + op := h.respWait[string(msg.ID)] + if op == nil { + h.log.Debug("Unsolicited RPC response", "reqid", idForLog{msg.ID}) + return + } + delete(h.respWait, string(msg.ID)) + // For normal responses, just forward the reply to Call/BatchCall. + if op.sub == nil { + op.resp <- msg + return + } + // For subscription responses, start the subscription if the server + // indicates success. EthSubscribe gets unblocked in either case through + // the op.resp channel. + defer close(op.resp) + if msg.Error != nil { + op.err = msg.Error + return + } + if op.err = json.Unmarshal(msg.Result, &op.sub.subid); op.err == nil { + go op.sub.start() + h.clientSubs[op.sub.subid] = op.sub + } +} + +// handleCallMsg executes a call message and returns the answer. +func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMessage { + start := time.Now() + switch { + case msg.isNotification(): + h.handleCall(ctx, msg) + h.log.Debug("Served "+msg.Method, "t", time.Since(start)) + return nil + case msg.isCall(): + resp := h.handleCall(ctx, msg) + if resp.Error != nil { + h.log.Warn("Served "+msg.Method, "reqid", idForLog{msg.ID}, "t", time.Since(start), "err", resp.Error.Message) + } else { + h.log.Debug("Served "+msg.Method, "reqid", idForLog{msg.ID}, "t", time.Since(start)) + } + return resp + case msg.hasValidID(): + return msg.errorResponse(&invalidRequestError{"invalid request"}) + default: + return errorMessage(&invalidRequestError{"invalid request"}) + } +} + +// handleCall processes method calls. +func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage { + if msg.isSubscribe() { + return h.handleSubscribe(cp, msg) + } + var callb *callback + if msg.isUnsubscribe() { + callb = h.unsubscribeCb + } else { + callb = h.reg.callback(msg.Method) + } + if callb == nil { + return msg.errorResponse(&methodNotFoundError{method: msg.Method}) + } + args, err := parsePositionalArguments(msg.Params, callb.argTypes) + if err != nil { + return msg.errorResponse(&invalidParamsError{err.Error()}) + } + + return h.runMethod(cp.ctx, msg, callb, args) +} + +// handleSubscribe processes *_subscribe method calls. +func (h *handler) handleSubscribe(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage { + if !h.allowSubscribe { + return msg.errorResponse(ErrNotificationsUnsupported) + } + + // Subscription method name is first argument. + name, err := parseSubscriptionName(msg.Params) + if err != nil { + return msg.errorResponse(&invalidParamsError{err.Error()}) + } + namespace := msg.namespace() + callb := h.reg.subscription(namespace, name) + if callb == nil { + return msg.errorResponse(&subscriptionNotFoundError{namespace, name}) + } + + // Parse subscription name arg too, but remove it before calling the callback. + argTypes := append([]reflect.Type{stringType}, callb.argTypes...) + args, err := parsePositionalArguments(msg.Params, argTypes) + if err != nil { + return msg.errorResponse(&invalidParamsError{err.Error()}) + } + args = args[1:] + + // Install notifier in context so the subscription handler can find it. + n := &Notifier{h: h, namespace: namespace} + cp.notifiers = append(cp.notifiers, n) + ctx := context.WithValue(cp.ctx, notifierKey{}, n) + + return h.runMethod(ctx, msg, callb, args) +} + +// runMethod runs the Go callback for an RPC method. +func (h *handler) runMethod(ctx context.Context, msg *jsonrpcMessage, callb *callback, args []reflect.Value) *jsonrpcMessage { + result, err := callb.call(ctx, msg.Method, args) + if err != nil { + return msg.errorResponse(err) + } + return msg.response(result) +} + +// unsubscribe is the callback function for all *_unsubscribe calls. +func (h *handler) unsubscribe(ctx context.Context, id ID) (bool, error) { + h.subLock.Lock() + defer h.subLock.Unlock() + + s := h.serverSubs[id] + if s == nil { + return false, ErrSubscriptionNotFound + } + close(s.err) + delete(h.serverSubs, id) + return true, nil +} + +type idForLog struct{ json.RawMessage } + +func (id idForLog) String() string { + if s, err := strconv.Unquote(string(id.RawMessage)); err == nil { + return s + } + return string(id.RawMessage) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/http.go b/vendor/github.com/ethereum/go-ethereum/rpc/http.go index 674166fb3a..518b3b874f 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/http.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/http.go @@ -37,38 +37,39 @@ import ( const ( maxRequestContentLength = 1024 * 512 + contentType = "application/json" ) -var ( - // https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13 - acceptedContentTypes = []string{"application/json", "application/json-rpc", "application/jsonrequest"} - contentType = acceptedContentTypes[0] - nullAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:0") -) +// https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13 +var acceptedContentTypes = []string{contentType, "application/json-rpc", "application/jsonrequest"} type httpConn struct { client *http.Client req *http.Request closeOnce sync.Once - closed chan struct{} + closed chan interface{} } // httpConn is treated specially by Client. -func (hc *httpConn) LocalAddr() net.Addr { return nullAddr } -func (hc *httpConn) RemoteAddr() net.Addr { return nullAddr } -func (hc *httpConn) SetReadDeadline(time.Time) error { return nil } -func (hc *httpConn) SetWriteDeadline(time.Time) error { return nil } -func (hc *httpConn) SetDeadline(time.Time) error { return nil } -func (hc *httpConn) Write([]byte) (int, error) { panic("Write called") } - -func (hc *httpConn) Read(b []byte) (int, error) { +func (hc *httpConn) Write(context.Context, interface{}) error { + panic("Write called on httpConn") +} + +func (hc *httpConn) RemoteAddr() string { + return hc.req.URL.String() +} + +func (hc *httpConn) Read() ([]*jsonrpcMessage, bool, error) { <-hc.closed - return 0, io.EOF + return nil, false, io.EOF } -func (hc *httpConn) Close() error { +func (hc *httpConn) Close() { hc.closeOnce.Do(func() { close(hc.closed) }) - return nil +} + +func (hc *httpConn) Closed() <-chan interface{} { + return hc.closed } // HTTPTimeouts represents the configuration params for the HTTP RPC server. @@ -114,8 +115,8 @@ func DialHTTPWithClient(endpoint string, client *http.Client) (*Client, error) { req.Header.Set("Accept", contentType) initctx := context.Background() - return newClient(initctx, func(context.Context) (net.Conn, error) { - return &httpConn{client: client, req: req, closed: make(chan struct{})}, nil + return newClient(initctx, func(context.Context) (ServerCodec, error) { + return &httpConn{client: client, req: req, closed: make(chan interface{})}, nil }) } @@ -184,21 +185,34 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadClos return resp.Body, nil } -// httpReadWriteNopCloser wraps a io.Reader and io.Writer with a NOP Close method. -type httpReadWriteNopCloser struct { +// httpServerConn turns a HTTP connection into a Conn. +type httpServerConn struct { io.Reader io.Writer + r *http.Request } -// Close does nothing and returns always nil -func (t *httpReadWriteNopCloser) Close() error { - return nil +func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec { + body := io.LimitReader(r.Body, maxRequestContentLength) + conn := &httpServerConn{Reader: body, Writer: w, r: r} + return NewJSONCodec(conn) } +// Close does nothing and always returns nil. +func (t *httpServerConn) Close() error { return nil } + +// RemoteAddr returns the peer address of the underlying connection. +func (t *httpServerConn) RemoteAddr() string { + return t.r.RemoteAddr +} + +// SetWriteDeadline does nothing and always returns nil. +func (t *httpServerConn) SetWriteDeadline(time.Time) error { return nil } + // NewHTTPServer creates a new HTTP RPC server around an API provider. // // Deprecated: Server implements http.Handler -func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv *Server) *http.Server { +func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv http.Handler) *http.Server { // Wrap the CORS-handler within a host-handler handler := newCorsHandler(srv, cors) handler = newVHostHandler(vhosts, handler) @@ -226,7 +240,7 @@ func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv *S } // ServeHTTP serves JSON-RPC requests over HTTP. -func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Permit dumb empty requests for remote health-checks (AWS) if r.Method == http.MethodGet && r.ContentLength == 0 && r.URL.RawQuery == "" { return @@ -249,12 +263,10 @@ func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, "Origin", origin) } - body := io.LimitReader(r.Body, maxRequestContentLength) - codec := NewJSONCodec(&httpReadWriteNopCloser{body, w}) - defer codec.Close() - w.Header().Set("content-type", contentType) - srv.ServeSingleRequest(ctx, codec, OptionMethodInvocation) + codec := newHTTPServerConn(r, w) + defer codec.Close() + s.serveSingleRequest(ctx, codec) } // validateRequest returns a non-zero response code and error message if the @@ -284,7 +296,7 @@ func validateRequest(r *http.Request) (int, error) { return http.StatusUnsupportedMediaType, err } -func newCorsHandler(srv *Server, allowedOrigins []string) http.Handler { +func newCorsHandler(srv http.Handler, allowedOrigins []string) http.Handler { // disable CORS support if user has not specified a custom CORS configuration if len(allowedOrigins) == 0 { return srv diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/inproc.go b/vendor/github.com/ethereum/go-ethereum/rpc/inproc.go index cbe65d10e7..c4456cfc4b 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/inproc.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/inproc.go @@ -24,10 +24,10 @@ import ( // DialInProc attaches an in-process connection to the given RPC server. func DialInProc(handler *Server) *Client { initctx := context.Background() - c, _ := newClient(initctx, func(context.Context) (net.Conn, error) { + c, _ := newClient(initctx, func(context.Context) (ServerCodec, error) { p1, p2 := net.Pipe() go handler.ServeCodec(NewJSONCodec(p1), OptionMethodInvocation|OptionSubscriptions) - return p2, nil + return NewJSONCodec(p2), nil }) return c } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/ipc.go b/vendor/github.com/ethereum/go-ethereum/rpc/ipc.go index 4cce1cf74b..ad8ce03098 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/ipc.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/ipc.go @@ -25,17 +25,17 @@ import ( ) // ServeListener accepts connections on l, serving JSON-RPC on them. -func (srv *Server) ServeListener(l net.Listener) error { +func (s *Server) ServeListener(l net.Listener) error { for { conn, err := l.Accept() if netutil.IsTemporaryError(err) { - log.Warn("IPC accept error", "err", err) + log.Warn("RPC accept error", "err", err) continue } else if err != nil { return err } - log.Trace("IPC accepted connection") - go srv.ServeCodec(NewJSONCodec(conn), OptionMethodInvocation|OptionSubscriptions) + log.Trace("Accepted RPC connection", "conn", conn.RemoteAddr()) + go s.ServeCodec(NewJSONCodec(conn), OptionMethodInvocation|OptionSubscriptions) } } @@ -46,7 +46,11 @@ func (srv *Server) ServeListener(l net.Listener) error { // The context is used for the initial connection establishment. It does not // affect subsequent interactions with the client. func DialIPC(ctx context.Context, endpoint string) (*Client, error) { - return newClient(ctx, func(ctx context.Context) (net.Conn, error) { - return newIPCConnection(ctx, endpoint) + return newClient(ctx, func(ctx context.Context) (ServerCodec, error) { + conn, err := newIPCConnection(ctx, endpoint) + if err != nil { + return nil, err + } + return NewJSONCodec(conn), err }) } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/json.go b/vendor/github.com/ethereum/go-ethereum/rpc/json.go index a523eeb8ef..b2e8c7bab3 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/json.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/json.go @@ -18,71 +18,110 @@ package rpc import ( "bytes" + "context" "encoding/json" + "errors" "fmt" "io" "reflect" - "strconv" "strings" "sync" - - "github.com/ethereum/go-ethereum/log" + "time" ) const ( - jsonrpcVersion = "2.0" + vsn = "2.0" serviceMethodSeparator = "_" subscribeMethodSuffix = "_subscribe" unsubscribeMethodSuffix = "_unsubscribe" notificationMethodSuffix = "_subscription" + + defaultWriteTimeout = 10 * time.Second // used if context has no deadline ) -type jsonRequest struct { - Method string `json:"method"` - Version string `json:"jsonrpc"` - Id json.RawMessage `json:"id,omitempty"` - Payload json.RawMessage `json:"params,omitempty"` +var null = json.RawMessage("null") + +type subscriptionResult struct { + ID string `json:"subscription"` + Result json.RawMessage `json:"result,omitempty"` } -type jsonSuccessResponse struct { - Version string `json:"jsonrpc"` - Id interface{} `json:"id,omitempty"` - Result interface{} `json:"result"` +// A value of this type can a JSON-RPC request, notification, successful response or +// error response. Which one it is depends on the fields. +type jsonrpcMessage struct { + Version string `json:"jsonrpc,omitempty"` + ID json.RawMessage `json:"id,omitempty"` + Method string `json:"method,omitempty"` + Params json.RawMessage `json:"params,omitempty"` + Error *jsonError `json:"error,omitempty"` + Result json.RawMessage `json:"result,omitempty"` } -type jsonError struct { - Code int `json:"code"` - Message string `json:"message"` - Data interface{} `json:"data,omitempty"` +func (msg *jsonrpcMessage) isNotification() bool { + return msg.ID == nil && msg.Method != "" } -type jsonErrResponse struct { - Version string `json:"jsonrpc"` - Id interface{} `json:"id,omitempty"` - Error jsonError `json:"error"` +func (msg *jsonrpcMessage) isCall() bool { + return msg.hasValidID() && msg.Method != "" } -type jsonSubscription struct { - Subscription string `json:"subscription"` - Result interface{} `json:"result,omitempty"` +func (msg *jsonrpcMessage) isResponse() bool { + return msg.hasValidID() && msg.Method == "" && msg.Params == nil && (msg.Result != nil || msg.Error != nil) } -type jsonNotification struct { - Version string `json:"jsonrpc"` - Method string `json:"method"` - Params jsonSubscription `json:"params"` +func (msg *jsonrpcMessage) hasValidID() bool { + return len(msg.ID) > 0 && msg.ID[0] != '{' && msg.ID[0] != '[' } -// jsonCodec reads and writes JSON-RPC messages to the underlying connection. It -// also has support for parsing arguments and serializing (result) objects. -type jsonCodec struct { - closer sync.Once // close closed channel once - closed chan interface{} // closed on Close - decMu sync.Mutex // guards the decoder - decode func(v interface{}) error // decoder to allow multiple transports - encMu sync.Mutex // guards the encoder - encode func(v interface{}) error // encoder to allow multiple transports - rw io.ReadWriteCloser // connection +func (msg *jsonrpcMessage) isSubscribe() bool { + return strings.HasSuffix(msg.Method, subscribeMethodSuffix) +} + +func (msg *jsonrpcMessage) isUnsubscribe() bool { + return strings.HasSuffix(msg.Method, unsubscribeMethodSuffix) +} + +func (msg *jsonrpcMessage) namespace() string { + elem := strings.SplitN(msg.Method, serviceMethodSeparator, 2) + return elem[0] +} + +func (msg *jsonrpcMessage) String() string { + b, _ := json.Marshal(msg) + return string(b) +} + +func (msg *jsonrpcMessage) errorResponse(err error) *jsonrpcMessage { + resp := errorMessage(err) + resp.ID = msg.ID + return resp +} + +func (msg *jsonrpcMessage) response(result interface{}) *jsonrpcMessage { + enc, err := json.Marshal(result) + if err != nil { + // TODO: wrap with 'internal server error' + return msg.errorResponse(err) + } + return &jsonrpcMessage{Version: vsn, ID: msg.ID, Result: enc} +} + +func errorMessage(err error) *jsonrpcMessage { + msg := &jsonrpcMessage{Version: vsn, ID: null, Error: &jsonError{ + Code: defaultErrorCode, + Message: err.Error(), + }} + ec, ok := err.(Error) + if ok { + msg.Error.Code = ec.ErrorCode() + } + return msg +} + +type jsonError struct { + Code int `json:"code"` + Message string `json:"message"` + Data interface{} `json:"data,omitempty"` } func (err *jsonError) Error() string { @@ -96,268 +135,196 @@ func (err *jsonError) ErrorCode() int { return err.Code } +// Conn is a subset of the methods of net.Conn which are sufficient for ServerCodec. +type Conn interface { + io.ReadWriteCloser + SetWriteDeadline(time.Time) error +} + +// ConnRemoteAddr wraps the RemoteAddr operation, which returns a description +// of the peer address of a connection. If a Conn also implements ConnRemoteAddr, this +// description is used in log messages. +type ConnRemoteAddr interface { + RemoteAddr() string +} + +// connWithRemoteAddr overrides the remote address of a connection. +type connWithRemoteAddr struct { + Conn + addr string +} + +func (c connWithRemoteAddr) RemoteAddr() string { return c.addr } + +// jsonCodec reads and writes JSON-RPC messages to the underlying connection. It also has +// support for parsing arguments and serializing (result) objects. +type jsonCodec struct { + remoteAddr string + closer sync.Once // close closed channel once + closed chan interface{} // closed on Close + decode func(v interface{}) error // decoder to allow multiple transports + encMu sync.Mutex // guards the encoder + encode func(v interface{}) error // encoder to allow multiple transports + conn Conn +} + // NewCodec creates a new RPC server codec with support for JSON-RPC 2.0 based // on explicitly given encoding and decoding methods. -func NewCodec(rwc io.ReadWriteCloser, encode, decode func(v interface{}) error) ServerCodec { - return &jsonCodec{ +func NewCodec(conn Conn, encode, decode func(v interface{}) error) ServerCodec { + codec := &jsonCodec{ closed: make(chan interface{}), encode: encode, decode: decode, - rw: rwc, + conn: conn, } + if ra, ok := conn.(ConnRemoteAddr); ok { + codec.remoteAddr = ra.RemoteAddr() + } + return codec } // NewJSONCodec creates a new RPC server codec with support for JSON-RPC 2.0. -func NewJSONCodec(rwc io.ReadWriteCloser) ServerCodec { - enc := json.NewEncoder(rwc) - dec := json.NewDecoder(rwc) +func NewJSONCodec(conn Conn) ServerCodec { + enc := json.NewEncoder(conn) + dec := json.NewDecoder(conn) dec.UseNumber() + return NewCodec(conn, enc.Encode, dec.Decode) +} - return &jsonCodec{ - closed: make(chan interface{}), - encode: enc.Encode, - decode: dec.Decode, - rw: rwc, - } +func (c *jsonCodec) RemoteAddr() string { + return c.remoteAddr } -// isBatch returns true when the first non-whitespace characters is '[' -func isBatch(msg json.RawMessage) bool { - for _, c := range msg { - // skip insignificant whitespace (http://www.ietf.org/rfc/rfc4627.txt) - if c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0d { - continue - } - return c == '[' +func (c *jsonCodec) Read() (msg []*jsonrpcMessage, batch bool, err error) { + // Decode the next JSON object in the input stream. + // This verifies basic syntax, etc. + var rawmsg json.RawMessage + if err := c.decode(&rawmsg); err != nil { + return nil, false, err } - return false + msg, batch = parseMessage(rawmsg) + return msg, batch, nil } -// ReadRequestHeaders will read new requests without parsing the arguments. It will -// return a collection of requests, an indication if these requests are in batch -// form or an error when the incoming message could not be read/parsed. -func (c *jsonCodec) ReadRequestHeaders() ([]rpcRequest, bool, Error) { - c.decMu.Lock() - defer c.decMu.Unlock() +// Write sends a message to client. +func (c *jsonCodec) Write(ctx context.Context, v interface{}) error { + c.encMu.Lock() + defer c.encMu.Unlock() - var incomingMsg json.RawMessage - if err := c.decode(&incomingMsg); err != nil { - return nil, false, &invalidRequestError{err.Error()} - } - if isBatch(incomingMsg) { - return parseBatchRequest(incomingMsg) + deadline, ok := ctx.Deadline() + if !ok { + deadline = time.Now().Add(defaultWriteTimeout) } - return parseRequest(incomingMsg) + c.conn.SetWriteDeadline(deadline) + return c.encode(v) } -// checkReqId returns an error when the given reqId isn't valid for RPC method calls. -// valid id's are strings, numbers or null -func checkReqId(reqId json.RawMessage) error { - if len(reqId) == 0 { - return fmt.Errorf("missing request id") - } - if _, err := strconv.ParseFloat(string(reqId), 64); err == nil { - return nil - } - var str string - if err := json.Unmarshal(reqId, &str); err == nil { - return nil - } - return fmt.Errorf("invalid request id") +// Close the underlying connection +func (c *jsonCodec) Close() { + c.closer.Do(func() { + close(c.closed) + c.conn.Close() + }) } -// parseRequest will parse a single request from the given RawMessage. It will return -// the parsed request, an indication if the request was a batch or an error when -// the request could not be parsed. -func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error) { - var in jsonRequest - if err := json.Unmarshal(incomingMsg, &in); err != nil { - return nil, false, &invalidMessageError{err.Error()} - } - - if err := checkReqId(in.Id); err != nil { - return nil, false, &invalidMessageError{err.Error()} - } - - // subscribe are special, they will always use `subscribeMethod` as first param in the payload - if strings.HasSuffix(in.Method, subscribeMethodSuffix) { - reqs := []rpcRequest{{id: &in.Id, isPubSub: true}} - if len(in.Payload) > 0 { - // first param must be subscription name - var subscribeMethod [1]string - if err := json.Unmarshal(in.Payload, &subscribeMethod); err != nil { - log.Debug(fmt.Sprintf("Unable to parse subscription method: %v\n", err)) - return nil, false, &invalidRequestError{"Unable to parse subscription request"} - } - - reqs[0].service, reqs[0].method = strings.TrimSuffix(in.Method, subscribeMethodSuffix), subscribeMethod[0] - reqs[0].params = in.Payload - return reqs, false, nil - } - return nil, false, &invalidRequestError{"Unable to parse subscription request"} - } - - if strings.HasSuffix(in.Method, unsubscribeMethodSuffix) { - return []rpcRequest{{id: &in.Id, isPubSub: true, - method: in.Method, params: in.Payload}}, false, nil - } +// Closed returns a channel which will be closed when Close is called +func (c *jsonCodec) Closed() <-chan interface{} { + return c.closed +} - elems := strings.Split(in.Method, serviceMethodSeparator) - if len(elems) != 2 { - return nil, false, &methodNotFoundError{in.Method, ""} +// parseMessage parses raw bytes as a (batch of) JSON-RPC message(s). There are no error +// checks in this function because the raw message has already been syntax-checked when it +// is called. Any non-JSON-RPC messages in the input return the zero value of +// jsonrpcMessage. +func parseMessage(raw json.RawMessage) ([]*jsonrpcMessage, bool) { + if !isBatch(raw) { + msgs := []*jsonrpcMessage{{}} + json.Unmarshal(raw, &msgs[0]) + return msgs, false } - - // regular RPC call - if len(in.Payload) == 0 { - return []rpcRequest{{service: elems[0], method: elems[1], id: &in.Id}}, false, nil + dec := json.NewDecoder(bytes.NewReader(raw)) + dec.Token() // skip '[' + var msgs []*jsonrpcMessage + for dec.More() { + msgs = append(msgs, new(jsonrpcMessage)) + dec.Decode(&msgs[len(msgs)-1]) } - - return []rpcRequest{{service: elems[0], method: elems[1], id: &in.Id, params: in.Payload}}, false, nil + return msgs, true } -// parseBatchRequest will parse a batch request into a collection of requests from the given RawMessage, an indication -// if the request was a batch or an error when the request could not be read. -func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error) { - var in []jsonRequest - if err := json.Unmarshal(incomingMsg, &in); err != nil { - return nil, false, &invalidMessageError{err.Error()} - } - - requests := make([]rpcRequest, len(in)) - for i, r := range in { - if err := checkReqId(r.Id); err != nil { - return nil, false, &invalidMessageError{err.Error()} - } - - id := &in[i].Id - - // subscribe are special, they will always use `subscriptionMethod` as first param in the payload - if strings.HasSuffix(r.Method, subscribeMethodSuffix) { - requests[i] = rpcRequest{id: id, isPubSub: true} - if len(r.Payload) > 0 { - // first param must be subscription name - var subscribeMethod [1]string - if err := json.Unmarshal(r.Payload, &subscribeMethod); err != nil { - log.Debug(fmt.Sprintf("Unable to parse subscription method: %v\n", err)) - return nil, false, &invalidRequestError{"Unable to parse subscription request"} - } - - requests[i].service, requests[i].method = strings.TrimSuffix(r.Method, subscribeMethodSuffix), subscribeMethod[0] - requests[i].params = r.Payload - continue - } - - return nil, true, &invalidRequestError{"Unable to parse (un)subscribe request arguments"} - } - - if strings.HasSuffix(r.Method, unsubscribeMethodSuffix) { - requests[i] = rpcRequest{id: id, isPubSub: true, method: r.Method, params: r.Payload} +// isBatch returns true when the first non-whitespace characters is '[' +func isBatch(raw json.RawMessage) bool { + for _, c := range raw { + // skip insignificant whitespace (http://www.ietf.org/rfc/rfc4627.txt) + if c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0d { continue } - - if len(r.Payload) == 0 { - requests[i] = rpcRequest{id: id, params: nil} - } else { - requests[i] = rpcRequest{id: id, params: r.Payload} - } - if elem := strings.Split(r.Method, serviceMethodSeparator); len(elem) == 2 { - requests[i].service, requests[i].method = elem[0], elem[1] - } else { - requests[i].err = &methodNotFoundError{r.Method, ""} - } - } - - return requests, true, nil -} - -// ParseRequestArguments tries to parse the given params (json.RawMessage) with the given -// types. It returns the parsed values or an error when the parsing failed. -func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) { - if args, ok := params.(json.RawMessage); !ok { - return nil, &invalidParamsError{"Invalid params supplied"} - } else { - return parsePositionalArguments(args, argTypes) + return c == '[' } + return false } // parsePositionalArguments tries to parse the given args to an array of values with the // given types. It returns the parsed values or an error when the args could not be // parsed. Missing optional arguments are returned as reflect.Zero values. -func parsePositionalArguments(rawArgs json.RawMessage, types []reflect.Type) ([]reflect.Value, Error) { - // Read beginning of the args array. +func parsePositionalArguments(rawArgs json.RawMessage, types []reflect.Type) ([]reflect.Value, error) { dec := json.NewDecoder(bytes.NewReader(rawArgs)) - if tok, _ := dec.Token(); tok != json.Delim('[') { - return nil, &invalidParamsError{"non-array args"} + var args []reflect.Value + tok, err := dec.Token() + switch { + case err == io.EOF || tok == nil && err == nil: + // "params" is optional and may be empty. Also allow "params":null even though it's + // not in the spec because our own client used to send it. + case err != nil: + return nil, err + case tok == json.Delim('['): + // Read argument array. + if args, err = parseArgumentArray(dec, types); err != nil { + return nil, err + } + default: + return nil, errors.New("non-array args") } - // Read args. + // Set any missing args to nil. + for i := len(args); i < len(types); i++ { + if types[i].Kind() != reflect.Ptr { + return nil, fmt.Errorf("missing value for required argument %d", i) + } + args = append(args, reflect.Zero(types[i])) + } + return args, nil +} + +func parseArgumentArray(dec *json.Decoder, types []reflect.Type) ([]reflect.Value, error) { args := make([]reflect.Value, 0, len(types)) for i := 0; dec.More(); i++ { if i >= len(types) { - return nil, &invalidParamsError{fmt.Sprintf("too many arguments, want at most %d", len(types))} + return args, fmt.Errorf("too many arguments, want at most %d", len(types)) } argval := reflect.New(types[i]) if err := dec.Decode(argval.Interface()); err != nil { - return nil, &invalidParamsError{fmt.Sprintf("invalid argument %d: %v", i, err)} + return args, fmt.Errorf("invalid argument %d: %v", i, err) } if argval.IsNil() && types[i].Kind() != reflect.Ptr { - return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)} + return args, fmt.Errorf("missing value for required argument %d", i) } args = append(args, argval.Elem()) } // Read end of args array. - if _, err := dec.Token(); err != nil { - return nil, &invalidParamsError{err.Error()} - } - // Set any missing args to nil. - for i := len(args); i < len(types); i++ { - if types[i].Kind() != reflect.Ptr { - return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)} - } - args = append(args, reflect.Zero(types[i])) - } - return args, nil -} - -// CreateResponse will create a JSON-RPC success response with the given id and reply as result. -func (c *jsonCodec) CreateResponse(id interface{}, reply interface{}) interface{} { - return &jsonSuccessResponse{Version: jsonrpcVersion, Id: id, Result: reply} -} - -// CreateErrorResponse will create a JSON-RPC error response with the given id and error. -func (c *jsonCodec) CreateErrorResponse(id interface{}, err Error) interface{} { - return &jsonErrResponse{Version: jsonrpcVersion, Id: id, Error: jsonError{Code: err.ErrorCode(), Message: err.Error()}} -} - -// CreateErrorResponseWithInfo will create a JSON-RPC error response with the given id and error. -// info is optional and contains additional information about the error. When an empty string is passed it is ignored. -func (c *jsonCodec) CreateErrorResponseWithInfo(id interface{}, err Error, info interface{}) interface{} { - return &jsonErrResponse{Version: jsonrpcVersion, Id: id, - Error: jsonError{Code: err.ErrorCode(), Message: err.Error(), Data: info}} -} - -// CreateNotification will create a JSON-RPC notification with the given subscription id and event as params. -func (c *jsonCodec) CreateNotification(subid, namespace string, event interface{}) interface{} { - return &jsonNotification{Version: jsonrpcVersion, Method: namespace + notificationMethodSuffix, - Params: jsonSubscription{Subscription: subid, Result: event}} -} - -// Write message to client -func (c *jsonCodec) Write(res interface{}) error { - c.encMu.Lock() - defer c.encMu.Unlock() - - return c.encode(res) + _, err := dec.Token() + return args, err } -// Close the underlying connection -func (c *jsonCodec) Close() { - c.closer.Do(func() { - close(c.closed) - c.rw.Close() - }) -} - -// Closed returns a channel which will be closed when Close is called -func (c *jsonCodec) Closed() <-chan interface{} { - return c.closed +// parseSubscriptionName extracts the subscription name from an encoded argument array. +func parseSubscriptionName(rawArgs json.RawMessage) (string, error) { + dec := json.NewDecoder(bytes.NewReader(rawArgs)) + if tok, _ := dec.Token(); tok != json.Delim('[') { + return "", errors.New("non-array args") + } + v, _ := dec.Token() + method, ok := v.(string) + if !ok { + return "", errors.New("expected subscription name as first argument") + } + return method, nil } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/server.go b/vendor/github.com/ethereum/go-ethereum/rpc/server.go index 214e1d3ed9..5a92847f20 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/server.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/server.go @@ -18,11 +18,7 @@ package rpc import ( "context" - "fmt" - "reflect" - "runtime" - "strings" - "sync" + "io" "sync/atomic" mapset "github.com/deckarep/golang-set" @@ -31,7 +27,9 @@ import ( const MetadataApi = "rpc" -// CodecOption specifies which type of messages this codec supports +// CodecOption specifies which type of messages a codec supports. +// +// Deprecated: this option is no longer honored by Server. type CodecOption int const ( @@ -42,194 +40,87 @@ const ( OptionSubscriptions = 1 << iota // support pub sub ) -// NewServer will create a new server instance with no registered handlers. -func NewServer() *Server { - server := &Server{ - services: make(serviceRegistry), - codecs: mapset.NewSet(), - run: 1, - } +// Server is an RPC server. +type Server struct { + services serviceRegistry + idgen func() ID + run int32 + codecs mapset.Set +} - // register a default service which will provide meta information about the RPC service such as the services and - // methods it offers. +// NewServer creates a new server instance with no registered handlers. +func NewServer() *Server { + server := &Server{idgen: randomIDGenerator(), codecs: mapset.NewSet(), run: 1} + // Register the default service providing meta information about the RPC service such + // as the services and methods it offers. rpcService := &RPCService{server} server.RegisterName(MetadataApi, rpcService) - return server } -// RPCService gives meta information about the server. -// e.g. gives information about the loaded modules. -type RPCService struct { - server *Server -} - -// Modules returns the list of RPC services with their version number -func (s *RPCService) Modules() map[string]string { - modules := make(map[string]string) - for name := range s.server.services { - modules[name] = "1.0" - } - return modules +// RegisterName creates a service for the given receiver type under the given name. When no +// methods on the given receiver match the criteria to be either a RPC method or a +// subscription an error is returned. Otherwise a new service is created and added to the +// service collection this server provides to clients. +func (s *Server) RegisterName(name string, receiver interface{}) error { + return s.services.registerName(name, receiver) } -// RegisterName will create a service for the given rcvr type under the given name. When no methods on the given rcvr -// match the criteria to be either a RPC method or a subscription an error is returned. Otherwise a new service is -// created and added to the service collection this server instance serves. -func (s *Server) RegisterName(name string, rcvr interface{}) error { - if s.services == nil { - s.services = make(serviceRegistry) - } - - svc := new(service) - svc.typ = reflect.TypeOf(rcvr) - rcvrVal := reflect.ValueOf(rcvr) - - if name == "" { - return fmt.Errorf("no service name for type %s", svc.typ.String()) - } - if !isExported(reflect.Indirect(rcvrVal).Type().Name()) { - return fmt.Errorf("%s is not exported", reflect.Indirect(rcvrVal).Type().Name()) - } - - methods, subscriptions := suitableCallbacks(rcvrVal, svc.typ) +// ServeCodec reads incoming requests from codec, calls the appropriate callback and writes +// the response back using the given codec. It will block until the codec is closed or the +// server is stopped. In either case the codec is closed. +// +// Note that codec options are no longer supported. +func (s *Server) ServeCodec(codec ServerCodec, options CodecOption) { + defer codec.Close() - if len(methods) == 0 && len(subscriptions) == 0 { - return fmt.Errorf("Service %T doesn't have any suitable methods/subscriptions to expose", rcvr) + // Don't serve if server is stopped. + if atomic.LoadInt32(&s.run) == 0 { + return } - // already a previous service register under given name, merge methods/subscriptions - if regsvc, present := s.services[name]; present { - for _, m := range methods { - regsvc.callbacks[formatName(m.method.Name)] = m - } - for _, s := range subscriptions { - regsvc.subscriptions[formatName(s.method.Name)] = s - } - return nil - } - - svc.name = name - svc.callbacks, svc.subscriptions = methods, subscriptions + // Add the codec to the set so it can be closed by Stop. + s.codecs.Add(codec) + defer s.codecs.Remove(codec) - s.services[svc.name] = svc - return nil + c := initClient(codec, s.idgen, &s.services) + <-codec.Closed() + c.Close() } -// serveRequest will reads requests from the codec, calls the RPC callback and -// writes the response to the given codec. -// -// If singleShot is true it will process a single request, otherwise it will handle -// requests until the codec returns an error when reading a request (in most cases -// an EOF). It executes requests in parallel when singleShot is false. -func (s *Server) serveRequest(ctx context.Context, codec ServerCodec, singleShot bool, options CodecOption) error { - var pend sync.WaitGroup - - defer func() { - if err := recover(); err != nil { - const size = 64 << 10 - buf := make([]byte, size) - buf = buf[:runtime.Stack(buf, false)] - log.Error(string(buf)) - } - s.codecsMu.Lock() - s.codecs.Remove(codec) - s.codecsMu.Unlock() - }() - - // ctx, cancel := context.WithCancel(context.Background()) - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - // if the codec supports notification include a notifier that callbacks can use - // to send notification to clients. It is tied to the codec/connection. If the - // connection is closed the notifier will stop and cancels all active subscriptions. - if options&OptionSubscriptions == OptionSubscriptions { - ctx = context.WithValue(ctx, notifierKey{}, newNotifier(codec)) - } - s.codecsMu.Lock() - if atomic.LoadInt32(&s.run) != 1 { // server stopped - s.codecsMu.Unlock() - return &shutdownError{} +// serveSingleRequest reads and processes a single RPC request from the given codec. This +// is used to serve HTTP connections. Subscriptions and reverse calls are not allowed in +// this mode. +func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) { + // Don't serve if server is stopped. + if atomic.LoadInt32(&s.run) == 0 { + return } - s.codecs.Add(codec) - s.codecsMu.Unlock() - // test if the server is ordered to stop - for atomic.LoadInt32(&s.run) == 1 { - reqs, batch, err := s.readRequest(codec) - if err != nil { - // If a parsing error occurred, send an error - if err.Error() != "EOF" { - log.Debug(fmt.Sprintf("read error %v\n", err)) - codec.Write(codec.CreateErrorResponse(nil, err)) - } - // Error or end of stream, wait for requests and tear down - pend.Wait() - return nil - } + h := newHandler(ctx, codec, s.idgen, &s.services) + h.allowSubscribe = false + defer h.close(io.EOF, nil) - // check if server is ordered to shutdown and return an error - // telling the client that his request failed. - if atomic.LoadInt32(&s.run) != 1 { - err = &shutdownError{} - if batch { - resps := make([]interface{}, len(reqs)) - for i, r := range reqs { - resps[i] = codec.CreateErrorResponse(&r.id, err) - } - codec.Write(resps) - } else { - codec.Write(codec.CreateErrorResponse(&reqs[0].id, err)) - } - return nil - } - // If a single shot request is executing, run and return immediately - if singleShot { - if batch { - s.execBatch(ctx, codec, reqs) - } else { - s.exec(ctx, codec, reqs[0]) - } - return nil + reqs, batch, err := codec.Read() + if err != nil { + if err != io.EOF { + codec.Write(ctx, errorMessage(&invalidMessageError{"parse error"})) } - // For multi-shot connections, start a goroutine to serve and loop back - pend.Add(1) - - go func(reqs []*serverRequest, batch bool) { - defer pend.Done() - if batch { - s.execBatch(ctx, codec, reqs) - } else { - s.exec(ctx, codec, reqs[0]) - } - }(reqs, batch) + return + } + if batch { + h.handleBatch(reqs) + } else { + h.handleMsg(reqs[0]) } - return nil -} - -// ServeCodec reads incoming requests from codec, calls the appropriate callback and writes the -// response back using the given codec. It will block until the codec is closed or the server is -// stopped. In either case the codec is closed. -func (s *Server) ServeCodec(codec ServerCodec, options CodecOption) { - defer codec.Close() - s.serveRequest(context.Background(), codec, false, options) -} - -// ServeSingleRequest reads and processes a single RPC request from the given codec. It will not -// close the codec unless a non-recoverable error has occurred. Note, this method will return after -// a single request has been processed! -func (s *Server) ServeSingleRequest(ctx context.Context, codec ServerCodec, options CodecOption) { - s.serveRequest(ctx, codec, true, options) } -// Stop will stop reading new requests, wait for stopPendingRequestTimeout to allow pending requests to finish, -// close all codecs which will cancel pending requests/subscriptions. +// Stop stops reading new requests, waits for stopPendingRequestTimeout to allow pending +// requests to finish, then closes all codecs which will cancel pending requests and +// subscriptions. func (s *Server) Stop() { if atomic.CompareAndSwapInt32(&s.run, 1, 0) { - log.Debug("RPC Server shutdown initiatied") - s.codecsMu.Lock() - defer s.codecsMu.Unlock() + log.Debug("RPC server shutting down") s.codecs.Each(func(c interface{}) bool { c.(ServerCodec).Close() return true @@ -237,206 +128,20 @@ func (s *Server) Stop() { } } -// createSubscription will call the subscription callback and returns the subscription id or error. -func (s *Server) createSubscription(ctx context.Context, c ServerCodec, req *serverRequest) (ID, error) { - // subscription have as first argument the context following optional arguments - args := []reflect.Value{req.callb.rcvr, reflect.ValueOf(ctx)} - args = append(args, req.args...) - reply := req.callb.method.Func.Call(args) - - if !reply[1].IsNil() { // subscription creation failed - return "", reply[1].Interface().(error) - } - - return reply[0].Interface().(*Subscription).ID, nil -} - -// handle executes a request and returns the response from the callback. -func (s *Server) handle(ctx context.Context, codec ServerCodec, req *serverRequest) (interface{}, func()) { - if req.err != nil { - return codec.CreateErrorResponse(&req.id, req.err), nil - } - - if req.isUnsubscribe { // cancel subscription, first param must be the subscription id - if len(req.args) >= 1 && req.args[0].Kind() == reflect.String { - notifier, supported := NotifierFromContext(ctx) - if !supported { // interface doesn't support subscriptions (e.g. http) - return codec.CreateErrorResponse(&req.id, &callbackError{ErrNotificationsUnsupported.Error()}), nil - } - - subid := ID(req.args[0].String()) - if err := notifier.unsubscribe(subid); err != nil { - return codec.CreateErrorResponse(&req.id, &callbackError{err.Error()}), nil - } - - return codec.CreateResponse(req.id, true), nil - } - return codec.CreateErrorResponse(&req.id, &invalidParamsError{"Expected subscription id as first argument"}), nil - } - - if req.callb.isSubscribe { - subid, err := s.createSubscription(ctx, codec, req) - if err != nil { - return codec.CreateErrorResponse(&req.id, &callbackError{err.Error()}), nil - } - - // active the subscription after the sub id was successfully sent to the client - activateSub := func() { - notifier, _ := NotifierFromContext(ctx) - notifier.activate(subid, req.svcname) - } - - return codec.CreateResponse(req.id, subid), activateSub - } - - // regular RPC call, prepare arguments - if len(req.args) != len(req.callb.argTypes) { - rpcErr := &invalidParamsError{fmt.Sprintf("%s%s%s expects %d parameters, got %d", - req.svcname, serviceMethodSeparator, req.callb.method.Name, - len(req.callb.argTypes), len(req.args))} - return codec.CreateErrorResponse(&req.id, rpcErr), nil - } - - arguments := []reflect.Value{req.callb.rcvr} - if req.callb.hasCtx { - arguments = append(arguments, reflect.ValueOf(ctx)) - } - if len(req.args) > 0 { - arguments = append(arguments, req.args...) - } - - // execute RPC method and return result - reply := req.callb.method.Func.Call(arguments) - if len(reply) == 0 { - return codec.CreateResponse(req.id, nil), nil - } - if req.callb.errPos >= 0 { // test if method returned an error - if !reply[req.callb.errPos].IsNil() { - e := reply[req.callb.errPos].Interface().(error) - res := codec.CreateErrorResponse(&req.id, &callbackError{e.Error()}) - return res, nil - } - } - return codec.CreateResponse(req.id, reply[0].Interface()), nil -} - -// exec executes the given request and writes the result back using the codec. -func (s *Server) exec(ctx context.Context, codec ServerCodec, req *serverRequest) { - var response interface{} - var callback func() - if req.err != nil { - response = codec.CreateErrorResponse(&req.id, req.err) - } else { - response, callback = s.handle(ctx, codec, req) - } - - if err := codec.Write(response); err != nil { - log.Error(fmt.Sprintf("%v\n", err)) - codec.Close() - } - - // when request was a subscribe request this allows these subscriptions to be actived - if callback != nil { - callback() - } -} - -// execBatch executes the given requests and writes the result back using the codec. -// It will only write the response back when the last request is processed. -func (s *Server) execBatch(ctx context.Context, codec ServerCodec, requests []*serverRequest) { - responses := make([]interface{}, len(requests)) - var callbacks []func() - for i, req := range requests { - if req.err != nil { - responses[i] = codec.CreateErrorResponse(&req.id, req.err) - } else { - var callback func() - if responses[i], callback = s.handle(ctx, codec, req); callback != nil { - callbacks = append(callbacks, callback) - } - } - } - - if err := codec.Write(responses); err != nil { - log.Error(fmt.Sprintf("%v\n", err)) - codec.Close() - } - - // when request holds one of more subscribe requests this allows these subscriptions to be activated - for _, c := range callbacks { - c() - } +// RPCService gives meta information about the server. +// e.g. gives information about the loaded modules. +type RPCService struct { + server *Server } -// readRequest requests the next (batch) request from the codec. It will return the collection -// of requests, an indication if the request was a batch, the invalid request identifier and an -// error when the request could not be read/parsed. -func (s *Server) readRequest(codec ServerCodec) ([]*serverRequest, bool, Error) { - reqs, batch, err := codec.ReadRequestHeaders() - if err != nil { - return nil, batch, err - } - - requests := make([]*serverRequest, len(reqs)) - - // verify requests - for i, r := range reqs { - var ok bool - var svc *service - - if r.err != nil { - requests[i] = &serverRequest{id: r.id, err: r.err} - continue - } - - if r.isPubSub && strings.HasSuffix(r.method, unsubscribeMethodSuffix) { - requests[i] = &serverRequest{id: r.id, isUnsubscribe: true} - argTypes := []reflect.Type{reflect.TypeOf("")} // expect subscription id as first arg - if args, err := codec.ParseRequestArguments(argTypes, r.params); err == nil { - requests[i].args = args - } else { - requests[i].err = &invalidParamsError{err.Error()} - } - continue - } - - if svc, ok = s.services[r.service]; !ok { // rpc method isn't available - requests[i] = &serverRequest{id: r.id, err: &methodNotFoundError{r.service, r.method}} - continue - } - - if r.isPubSub { // eth_subscribe, r.method contains the subscription method name - if callb, ok := svc.subscriptions[r.method]; ok { - requests[i] = &serverRequest{id: r.id, svcname: svc.name, callb: callb} - if r.params != nil && len(callb.argTypes) > 0 { - argTypes := []reflect.Type{reflect.TypeOf("")} - argTypes = append(argTypes, callb.argTypes...) - if args, err := codec.ParseRequestArguments(argTypes, r.params); err == nil { - requests[i].args = args[1:] // first one is service.method name which isn't an actual argument - } else { - requests[i].err = &invalidParamsError{err.Error()} - } - } - } else { - requests[i] = &serverRequest{id: r.id, err: &methodNotFoundError{r.service, r.method}} - } - continue - } - - if callb, ok := svc.callbacks[r.method]; ok { // lookup RPC method - requests[i] = &serverRequest{id: r.id, svcname: svc.name, callb: callb} - if r.params != nil && len(callb.argTypes) > 0 { - if args, err := codec.ParseRequestArguments(callb.argTypes, r.params); err == nil { - requests[i].args = args - } else { - requests[i].err = &invalidParamsError{err.Error()} - } - } - continue - } +// Modules returns the list of RPC services with their version number +func (s *RPCService) Modules() map[string]string { + s.server.services.mu.Lock() + defer s.server.services.mu.Unlock() - requests[i] = &serverRequest{id: r.id, err: &methodNotFoundError{r.service, r.method}} + modules := make(map[string]string) + for name := range s.server.services.services { + modules[name] = "1.0" } - - return requests, batch, nil + return modules } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/service.go b/vendor/github.com/ethereum/go-ethereum/rpc/service.go new file mode 100644 index 0000000000..a9426c6b0e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rpc/service.go @@ -0,0 +1,285 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rpc + +import ( + "context" + "errors" + "fmt" + "reflect" + "runtime" + "strings" + "sync" + "unicode" + "unicode/utf8" + + "github.com/ethereum/go-ethereum/log" +) + +var ( + contextType = reflect.TypeOf((*context.Context)(nil)).Elem() + errorType = reflect.TypeOf((*error)(nil)).Elem() + subscriptionType = reflect.TypeOf(Subscription{}) + stringType = reflect.TypeOf("") +) + +type serviceRegistry struct { + mu sync.Mutex + services map[string]service +} + +// service represents a registered object. +type service struct { + name string // name for service + callbacks map[string]*callback // registered handlers + subscriptions map[string]*callback // available subscriptions/notifications +} + +// callback is a method callback which was registered in the server +type callback struct { + fn reflect.Value // the function + rcvr reflect.Value // receiver object of method, set if fn is method + argTypes []reflect.Type // input argument types + hasCtx bool // method's first argument is a context (not included in argTypes) + errPos int // err return idx, of -1 when method cannot return error + isSubscribe bool // true if this is a subscription callback +} + +func (r *serviceRegistry) registerName(name string, rcvr interface{}) error { + rcvrVal := reflect.ValueOf(rcvr) + if name == "" { + return fmt.Errorf("no service name for type %s", rcvrVal.Type().String()) + } + callbacks := suitableCallbacks(rcvrVal) + if len(callbacks) == 0 { + return fmt.Errorf("service %T doesn't have any suitable methods/subscriptions to expose", rcvr) + } + + r.mu.Lock() + defer r.mu.Unlock() + if r.services == nil { + r.services = make(map[string]service) + } + svc, ok := r.services[name] + if !ok { + svc = service{ + name: name, + callbacks: make(map[string]*callback), + subscriptions: make(map[string]*callback), + } + r.services[name] = svc + } + for name, cb := range callbacks { + if cb.isSubscribe { + svc.subscriptions[name] = cb + } else { + svc.callbacks[name] = cb + } + } + return nil +} + +// callback returns the callback corresponding to the given RPC method name. +func (r *serviceRegistry) callback(method string) *callback { + elem := strings.SplitN(method, serviceMethodSeparator, 2) + if len(elem) != 2 { + return nil + } + r.mu.Lock() + defer r.mu.Unlock() + return r.services[elem[0]].callbacks[elem[1]] +} + +// subscription returns a subscription callback in the given service. +func (r *serviceRegistry) subscription(service, name string) *callback { + r.mu.Lock() + defer r.mu.Unlock() + return r.services[service].subscriptions[name] +} + +// suitableCallbacks iterates over the methods of the given type. It determines if a method +// satisfies the criteria for a RPC callback or a subscription callback and adds it to the +// collection of callbacks. See server documentation for a summary of these criteria. +func suitableCallbacks(receiver reflect.Value) map[string]*callback { + typ := receiver.Type() + callbacks := make(map[string]*callback) + for m := 0; m < typ.NumMethod(); m++ { + method := typ.Method(m) + if method.PkgPath != "" { + continue // method not exported + } + cb := newCallback(receiver, method.Func) + if cb == nil { + continue // function invalid + } + name := formatName(method.Name) + callbacks[name] = cb + } + return callbacks +} + +// newCallback turns fn (a function) into a callback object. It returns nil if the function +// is unsuitable as an RPC callback. +func newCallback(receiver, fn reflect.Value) *callback { + fntype := fn.Type() + c := &callback{fn: fn, rcvr: receiver, errPos: -1, isSubscribe: isPubSub(fntype)} + // Determine parameter types. They must all be exported or builtin types. + c.makeArgTypes() + if !allExportedOrBuiltin(c.argTypes) { + return nil + } + // Verify return types. The function must return at most one error + // and/or one other non-error value. + outs := make([]reflect.Type, fntype.NumOut()) + for i := 0; i < fntype.NumOut(); i++ { + outs[i] = fntype.Out(i) + } + if len(outs) > 2 || !allExportedOrBuiltin(outs) { + return nil + } + // If an error is returned, it must be the last returned value. + switch { + case len(outs) == 1 && isErrorType(outs[0]): + c.errPos = 0 + case len(outs) == 2: + if isErrorType(outs[0]) || !isErrorType(outs[1]) { + return nil + } + c.errPos = 1 + } + return c +} + +// makeArgTypes composes the argTypes list. +func (c *callback) makeArgTypes() { + fntype := c.fn.Type() + // Skip receiver and context.Context parameter (if present). + firstArg := 0 + if c.rcvr.IsValid() { + firstArg++ + } + if fntype.NumIn() > firstArg && fntype.In(firstArg) == contextType { + c.hasCtx = true + firstArg++ + } + // Add all remaining parameters. + c.argTypes = make([]reflect.Type, fntype.NumIn()-firstArg) + for i := firstArg; i < fntype.NumIn(); i++ { + c.argTypes[i-firstArg] = fntype.In(i) + } +} + +// call invokes the callback. +func (c *callback) call(ctx context.Context, method string, args []reflect.Value) (res interface{}, errRes error) { + // Create the argument slice. + fullargs := make([]reflect.Value, 0, 2+len(args)) + if c.rcvr.IsValid() { + fullargs = append(fullargs, c.rcvr) + } + if c.hasCtx { + fullargs = append(fullargs, reflect.ValueOf(ctx)) + } + fullargs = append(fullargs, args...) + + // Catch panic while running the callback. + defer func() { + if err := recover(); err != nil { + const size = 64 << 10 + buf := make([]byte, size) + buf = buf[:runtime.Stack(buf, false)] + log.Error("RPC method " + method + " crashed: " + fmt.Sprintf("%v\n%s", err, buf)) + errRes = errors.New("method handler crashed") + } + }() + // Run the callback. + results := c.fn.Call(fullargs) + if len(results) == 0 { + return nil, nil + } + if c.errPos >= 0 && !results[c.errPos].IsNil() { + // Method has returned non-nil error value. + err := results[c.errPos].Interface().(error) + return reflect.Value{}, err + } + return results[0].Interface(), nil +} + +// Is this an exported - upper case - name? +func isExported(name string) bool { + rune, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(rune) +} + +// Are all those types exported or built-in? +func allExportedOrBuiltin(types []reflect.Type) bool { + for _, typ := range types { + for typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + // PkgPath will be non-empty even for an exported type, + // so we need to check the type name as well. + if !isExported(typ.Name()) && typ.PkgPath() != "" { + return false + } + } + return true +} + +// Is t context.Context or *context.Context? +func isContextType(t reflect.Type) bool { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t == contextType +} + +// Does t satisfy the error interface? +func isErrorType(t reflect.Type) bool { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t.Implements(errorType) +} + +// Is t Subscription or *Subscription? +func isSubscriptionType(t reflect.Type) bool { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t == subscriptionType +} + +// isPubSub tests whether the given method has as as first argument a context.Context and +// returns the pair (Subscription, error). +func isPubSub(methodType reflect.Type) bool { + // numIn(0) is the receiver type + if methodType.NumIn() < 2 || methodType.NumOut() != 2 { + return false + } + return isContextType(methodType.In(1)) && + isSubscriptionType(methodType.Out(0)) && + isErrorType(methodType.Out(1)) +} + +// formatName converts to first character of name to lowercase. +func formatName(name string) string { + ret := []rune(name) + if len(ret) > 0 { + ret[0] = unicode.ToLower(ret[0]) + } + return string(ret) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/stdio.go b/vendor/github.com/ethereum/go-ethereum/rpc/stdio.go index ea552cca28..d5dc066c99 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/stdio.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/stdio.go @@ -19,6 +19,7 @@ package rpc import ( "context" "errors" + "io" "net" "os" "time" @@ -26,39 +27,38 @@ import ( // DialStdIO creates a client on stdin/stdout. func DialStdIO(ctx context.Context) (*Client, error) { - return newClient(ctx, func(_ context.Context) (net.Conn, error) { - return stdioConn{}, nil + return DialIO(ctx, os.Stdin, os.Stdout) +} + +// DialIO creates a client which uses the given IO channels +func DialIO(ctx context.Context, in io.Reader, out io.Writer) (*Client, error) { + return newClient(ctx, func(_ context.Context) (ServerCodec, error) { + return NewJSONCodec(stdioConn{ + in: in, + out: out, + }), nil }) } -type stdioConn struct{} +type stdioConn struct { + in io.Reader + out io.Writer +} func (io stdioConn) Read(b []byte) (n int, err error) { - return os.Stdin.Read(b) + return io.in.Read(b) } func (io stdioConn) Write(b []byte) (n int, err error) { - return os.Stdout.Write(b) + return io.out.Write(b) } func (io stdioConn) Close() error { return nil } -func (io stdioConn) LocalAddr() net.Addr { - return &net.UnixAddr{Name: "stdio", Net: "stdio"} -} - -func (io stdioConn) RemoteAddr() net.Addr { - return &net.UnixAddr{Name: "stdio", Net: "stdio"} -} - -func (io stdioConn) SetDeadline(t time.Time) error { - return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")} -} - -func (io stdioConn) SetReadDeadline(t time.Time) error { - return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")} +func (io stdioConn) RemoteAddr() string { + return "/dev/stdin" } func (io stdioConn) SetWriteDeadline(t time.Time) error { diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/subscription.go b/vendor/github.com/ethereum/go-ethereum/rpc/subscription.go index 6bbb6f75d2..c1e869b8a3 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/subscription.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/subscription.go @@ -17,9 +17,19 @@ package rpc import ( + "bufio" + "container/list" "context" + crand "crypto/rand" + "encoding/binary" + "encoding/hex" + "encoding/json" "errors" + "math/rand" + "reflect" + "strings" "sync" + "time" ) var ( @@ -29,121 +39,289 @@ var ( ErrSubscriptionNotFound = errors.New("subscription not found") ) +var globalGen = randomIDGenerator() + // ID defines a pseudo random number that is used to identify RPC subscriptions. type ID string -// a Subscription is created by a notifier and tight to that notifier. The client can use -// this subscription to wait for an unsubscribe request for the client, see Err(). -type Subscription struct { - ID ID - namespace string - err chan error // closed on unsubscribe +// NewID returns a new, random ID. +func NewID() ID { + return globalGen() } -// Err returns a channel that is closed when the client send an unsubscribe request. -func (s *Subscription) Err() <-chan error { - return s.err +// randomIDGenerator returns a function generates a random IDs. +func randomIDGenerator() func() ID { + seed, err := binary.ReadVarint(bufio.NewReader(crand.Reader)) + if err != nil { + seed = int64(time.Now().Nanosecond()) + } + var ( + mu sync.Mutex + rng = rand.New(rand.NewSource(seed)) + ) + return func() ID { + mu.Lock() + defer mu.Unlock() + id := make([]byte, 16) + rng.Read(id) + return encodeID(id) + } } -// notifierKey is used to store a notifier within the connection context. -type notifierKey struct{} - -// Notifier is tight to a RPC connection that supports subscriptions. -// Server callbacks use the notifier to send notifications. -type Notifier struct { - codec ServerCodec - subMu sync.Mutex - active map[ID]*Subscription - inactive map[ID]*Subscription - buffer map[ID][]interface{} // unsent notifications of inactive subscriptions -} - -// newNotifier creates a new notifier that can be used to send subscription -// notifications to the client. -func newNotifier(codec ServerCodec) *Notifier { - return &Notifier{ - codec: codec, - active: make(map[ID]*Subscription), - inactive: make(map[ID]*Subscription), - buffer: make(map[ID][]interface{}), +func encodeID(b []byte) ID { + id := hex.EncodeToString(b) + id = strings.TrimLeft(id, "0") + if id == "" { + id = "0" // ID's are RPC quantities, no leading zero's and 0 is 0x0. } + return ID("0x" + id) } +type notifierKey struct{} + // NotifierFromContext returns the Notifier value stored in ctx, if any. func NotifierFromContext(ctx context.Context) (*Notifier, bool) { n, ok := ctx.Value(notifierKey{}).(*Notifier) return n, ok } +// Notifier is tied to a RPC connection that supports subscriptions. +// Server callbacks use the notifier to send notifications. +type Notifier struct { + h *handler + namespace string + + mu sync.Mutex + sub *Subscription + buffer []json.RawMessage + callReturned bool + activated bool +} + // CreateSubscription returns a new subscription that is coupled to the // RPC connection. By default subscriptions are inactive and notifications // are dropped until the subscription is marked as active. This is done // by the RPC server after the subscription ID is send to the client. func (n *Notifier) CreateSubscription() *Subscription { - s := &Subscription{ID: NewID(), err: make(chan error)} - n.subMu.Lock() - n.inactive[s.ID] = s - n.subMu.Unlock() - return s + n.mu.Lock() + defer n.mu.Unlock() + + if n.sub != nil { + panic("can't create multiple subscriptions with Notifier") + } else if n.callReturned { + panic("can't create subscription after subscribe call has returned") + } + n.sub = &Subscription{ID: n.h.idgen(), namespace: n.namespace, err: make(chan error, 1)} + return n.sub } // Notify sends a notification to the client with the given data as payload. // If an error occurs the RPC connection is closed and the error is returned. func (n *Notifier) Notify(id ID, data interface{}) error { - n.subMu.Lock() - defer n.subMu.Unlock() + enc, err := json.Marshal(data) + if err != nil { + return err + } - if sub, active := n.active[id]; active { - n.send(sub, data) - } else { - n.buffer[id] = append(n.buffer[id], data) + n.mu.Lock() + defer n.mu.Unlock() + + if n.sub == nil { + panic("can't Notify before subscription is created") + } else if n.sub.ID != id { + panic("Notify with wrong ID") + } + if n.activated { + return n.send(n.sub, enc) } + n.buffer = append(n.buffer, enc) return nil } -func (n *Notifier) send(sub *Subscription, data interface{}) error { - notification := n.codec.CreateNotification(string(sub.ID), sub.namespace, data) - err := n.codec.Write(notification) - if err != nil { - n.codec.Close() +// Closed returns a channel that is closed when the RPC connection is closed. +// Deprecated: use subscription error channel +func (n *Notifier) Closed() <-chan interface{} { + return n.h.conn.Closed() +} + +// takeSubscription returns the subscription (if one has been created). No subscription can +// be created after this call. +func (n *Notifier) takeSubscription() *Subscription { + n.mu.Lock() + defer n.mu.Unlock() + n.callReturned = true + return n.sub +} + +// acticate is called after the subscription ID was sent to client. Notifications are +// buffered before activation. This prevents notifications being sent to the client before +// the subscription ID is sent to the client. +func (n *Notifier) activate() error { + n.mu.Lock() + defer n.mu.Unlock() + + for _, data := range n.buffer { + if err := n.send(n.sub, data); err != nil { + return err + } } - return err + n.activated = true + return nil } -// Closed returns a channel that is closed when the RPC connection is closed. -func (n *Notifier) Closed() <-chan interface{} { - return n.codec.Closed() -} - -// unsubscribe a subscription. -// If the subscription could not be found ErrSubscriptionNotFound is returned. -func (n *Notifier) unsubscribe(id ID) error { - n.subMu.Lock() - defer n.subMu.Unlock() - if s, found := n.active[id]; found { - close(s.err) - delete(n.active, id) - return nil +func (n *Notifier) send(sub *Subscription, data json.RawMessage) error { + params, _ := json.Marshal(&subscriptionResult{ID: string(sub.ID), Result: data}) + ctx := context.Background() + return n.h.conn.Write(ctx, &jsonrpcMessage{ + Version: vsn, + Method: n.namespace + notificationMethodSuffix, + Params: params, + }) +} + +// A Subscription is created by a notifier and tight to that notifier. The client can use +// this subscription to wait for an unsubscribe request for the client, see Err(). +type Subscription struct { + ID ID + namespace string + err chan error // closed on unsubscribe +} + +// Err returns a channel that is closed when the client send an unsubscribe request. +func (s *Subscription) Err() <-chan error { + return s.err +} + +// MarshalJSON marshals a subscription as its ID. +func (s *Subscription) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ID) +} + +// ClientSubscription is a subscription established through the Client's Subscribe or +// EthSubscribe methods. +type ClientSubscription struct { + client *Client + etype reflect.Type + channel reflect.Value + namespace string + subid string + in chan json.RawMessage + + quitOnce sync.Once // ensures quit is closed once + quit chan struct{} // quit is closed when the subscription exits + errOnce sync.Once // ensures err is closed once + err chan error +} + +func newClientSubscription(c *Client, namespace string, channel reflect.Value) *ClientSubscription { + sub := &ClientSubscription{ + client: c, + namespace: namespace, + etype: channel.Type().Elem(), + channel: channel, + quit: make(chan struct{}), + err: make(chan error, 1), + in: make(chan json.RawMessage), } - return ErrSubscriptionNotFound -} - -// activate enables a subscription. Until a subscription is enabled all -// notifications are dropped. This method is called by the RPC server after -// the subscription ID was sent to client. This prevents notifications being -// send to the client before the subscription ID is send to the client. -func (n *Notifier) activate(id ID, namespace string) { - n.subMu.Lock() - defer n.subMu.Unlock() - - if sub, found := n.inactive[id]; found { - sub.namespace = namespace - n.active[id] = sub - delete(n.inactive, id) - // Send buffered notifications. - for _, data := range n.buffer[id] { - n.send(sub, data) + return sub +} + +// Err returns the subscription error channel. The intended use of Err is to schedule +// resubscription when the client connection is closed unexpectedly. +// +// The error channel receives a value when the subscription has ended due +// to an error. The received error is nil if Close has been called +// on the underlying client and no other error has occurred. +// +// The error channel is closed when Unsubscribe is called on the subscription. +func (sub *ClientSubscription) Err() <-chan error { + return sub.err +} + +// Unsubscribe unsubscribes the notification and closes the error channel. +// It can safely be called more than once. +func (sub *ClientSubscription) Unsubscribe() { + sub.quitWithError(nil, true) + sub.errOnce.Do(func() { close(sub.err) }) +} + +func (sub *ClientSubscription) quitWithError(err error, unsubscribeServer bool) { + sub.quitOnce.Do(func() { + // The dispatch loop won't be able to execute the unsubscribe call + // if it is blocked on deliver. Close sub.quit first because it + // unblocks deliver. + close(sub.quit) + if unsubscribeServer { + sub.requestUnsubscribe() + } + if err != nil { + if err == ErrClientQuit { + err = nil // Adhere to subscription semantics. + } + sub.err <- err } - delete(n.buffer, id) + }) +} + +func (sub *ClientSubscription) deliver(result json.RawMessage) (ok bool) { + select { + case sub.in <- result: + return true + case <-sub.quit: + return false } } + +func (sub *ClientSubscription) start() { + sub.quitWithError(sub.forward()) +} + +func (sub *ClientSubscription) forward() (err error, unsubscribeServer bool) { + cases := []reflect.SelectCase{ + {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.quit)}, + {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.in)}, + {Dir: reflect.SelectSend, Chan: sub.channel}, + } + buffer := list.New() + defer buffer.Init() + for { + var chosen int + var recv reflect.Value + if buffer.Len() == 0 { + // Idle, omit send case. + chosen, recv, _ = reflect.Select(cases[:2]) + } else { + // Non-empty buffer, send the first queued item. + cases[2].Send = reflect.ValueOf(buffer.Front().Value) + chosen, recv, _ = reflect.Select(cases) + } + + switch chosen { + case 0: // <-sub.quit + return nil, false + case 1: // <-sub.in + val, err := sub.unmarshal(recv.Interface().(json.RawMessage)) + if err != nil { + return err, true + } + if buffer.Len() == maxClientSubscriptionBuffer { + return ErrSubscriptionQueueOverflow, true + } + buffer.PushBack(val) + case 2: // sub.channel<- + cases[2].Send = reflect.Value{} // Don't hold onto the value. + buffer.Remove(buffer.Front()) + } + } +} + +func (sub *ClientSubscription) unmarshal(result json.RawMessage) (interface{}, error) { + val := reflect.New(sub.etype) + err := json.Unmarshal(result, val.Interface()) + return val.Elem().Interface(), err +} + +func (sub *ClientSubscription) requestUnsubscribe() error { + var result interface{} + return sub.client.Call(&result, sub.namespace+unsubscribeMethodSuffix, sub.subid) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/types.go b/vendor/github.com/ethereum/go-ethereum/rpc/types.go index 4252c36027..f31f09a774 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/types.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/types.go @@ -17,13 +17,11 @@ package rpc import ( + "context" "fmt" "math" - "reflect" "strings" - "sync" - mapset "github.com/deckarep/golang-set" "github.com/ethereum/go-ethereum/common/hexutil" ) @@ -35,57 +33,6 @@ type API struct { Public bool // indication if the methods must be considered safe for public use } -// callback is a method callback which was registered in the server -type callback struct { - rcvr reflect.Value // receiver of method - method reflect.Method // callback - argTypes []reflect.Type // input argument types - hasCtx bool // method's first argument is a context (not included in argTypes) - errPos int // err return idx, of -1 when method cannot return error - isSubscribe bool // indication if the callback is a subscription -} - -// service represents a registered object -type service struct { - name string // name for service - typ reflect.Type // receiver type - callbacks callbacks // registered handlers - subscriptions subscriptions // available subscriptions/notifications -} - -// serverRequest is an incoming request -type serverRequest struct { - id interface{} - svcname string - callb *callback - args []reflect.Value - isUnsubscribe bool - err Error -} - -type serviceRegistry map[string]*service // collection of services -type callbacks map[string]*callback // collection of RPC callbacks -type subscriptions map[string]*callback // collection of subscription callbacks - -// Server represents a RPC server -type Server struct { - services serviceRegistry - - run int32 - codecsMu sync.Mutex - codecs mapset.Set -} - -// rpcRequest represents a raw incoming RPC request -type rpcRequest struct { - service string - method string - id interface{} - isPubSub bool - params interface{} - err Error // invalid batch element -} - // Error wraps RPC errors, which contain an error code in addition to the message. type Error interface { Error() string // returns the message @@ -96,24 +43,19 @@ type Error interface { // a RPC session. Implementations must be go-routine safe since the codec can be called in // multiple go-routines concurrently. type ServerCodec interface { - // Read next request - ReadRequestHeaders() ([]rpcRequest, bool, Error) - // Parse request argument to the given types - ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) - // Assemble success response, expects response id and payload - CreateResponse(id interface{}, reply interface{}) interface{} - // Assemble error response, expects response id and error - CreateErrorResponse(id interface{}, err Error) interface{} - // Assemble error response with extra information about the error through info - CreateErrorResponseWithInfo(id interface{}, err Error, info interface{}) interface{} - // Create notification response - CreateNotification(id, namespace string, event interface{}) interface{} - // Write msg to client. - Write(msg interface{}) error - // Close underlying data stream + Read() (msgs []*jsonrpcMessage, isBatch bool, err error) Close() - // Closed when underlying connection is closed + jsonWriter +} + +// jsonWriter can write JSON messages to its underlying connection. +// Implementations must be safe for concurrent use. +type jsonWriter interface { + Write(context.Context, interface{}) error + // Closed returns a channel which is closed when the connection is closed. Closed() <-chan interface{} + // RemoteAddr returns the peer address of the connection. + RemoteAddr() string } type BlockNumber int64 diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/utils.go b/vendor/github.com/ethereum/go-ethereum/rpc/utils.go deleted file mode 100644 index 7f7ac4520b..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/rpc/utils.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rpc - -import ( - "bufio" - "context" - crand "crypto/rand" - "encoding/binary" - "encoding/hex" - "math/rand" - "reflect" - "strings" - "sync" - "time" - "unicode" - "unicode/utf8" -) - -var ( - subscriptionIDGenMu sync.Mutex - subscriptionIDGen = idGenerator() -) - -// Is this an exported - upper case - name? -func isExported(name string) bool { - rune, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(rune) -} - -// Is this type exported or a builtin? -func isExportedOrBuiltinType(t reflect.Type) bool { - for t.Kind() == reflect.Ptr { - t = t.Elem() - } - // PkgPath will be non-empty even for an exported type, - // so we need to check the type name as well. - return isExported(t.Name()) || t.PkgPath() == "" -} - -var contextType = reflect.TypeOf((*context.Context)(nil)).Elem() - -// isContextType returns an indication if the given t is of context.Context or *context.Context type -func isContextType(t reflect.Type) bool { - for t.Kind() == reflect.Ptr { - t = t.Elem() - } - return t == contextType -} - -var errorType = reflect.TypeOf((*error)(nil)).Elem() - -// Implements this type the error interface -func isErrorType(t reflect.Type) bool { - for t.Kind() == reflect.Ptr { - t = t.Elem() - } - return t.Implements(errorType) -} - -var subscriptionType = reflect.TypeOf((*Subscription)(nil)).Elem() - -// isSubscriptionType returns an indication if the given t is of Subscription or *Subscription type -func isSubscriptionType(t reflect.Type) bool { - for t.Kind() == reflect.Ptr { - t = t.Elem() - } - return t == subscriptionType -} - -// isPubSub tests whether the given method has as as first argument a context.Context -// and returns the pair (Subscription, error) -func isPubSub(methodType reflect.Type) bool { - // numIn(0) is the receiver type - if methodType.NumIn() < 2 || methodType.NumOut() != 2 { - return false - } - - return isContextType(methodType.In(1)) && - isSubscriptionType(methodType.Out(0)) && - isErrorType(methodType.Out(1)) -} - -// formatName will convert to first character to lower case -func formatName(name string) string { - ret := []rune(name) - if len(ret) > 0 { - ret[0] = unicode.ToLower(ret[0]) - } - return string(ret) -} - -// suitableCallbacks iterates over the methods of the given type. It will determine if a method satisfies the criteria -// for a RPC callback or a subscription callback and adds it to the collection of callbacks or subscriptions. See server -// documentation for a summary of these criteria. -func suitableCallbacks(rcvr reflect.Value, typ reflect.Type) (callbacks, subscriptions) { - callbacks := make(callbacks) - subscriptions := make(subscriptions) - -METHODS: - for m := 0; m < typ.NumMethod(); m++ { - method := typ.Method(m) - mtype := method.Type - mname := formatName(method.Name) - if method.PkgPath != "" { // method must be exported - continue - } - - var h callback - h.isSubscribe = isPubSub(mtype) - h.rcvr = rcvr - h.method = method - h.errPos = -1 - - firstArg := 1 - numIn := mtype.NumIn() - if numIn >= 2 && mtype.In(1) == contextType { - h.hasCtx = true - firstArg = 2 - } - - if h.isSubscribe { - h.argTypes = make([]reflect.Type, numIn-firstArg) // skip rcvr type - for i := firstArg; i < numIn; i++ { - argType := mtype.In(i) - if isExportedOrBuiltinType(argType) { - h.argTypes[i-firstArg] = argType - } else { - continue METHODS - } - } - - subscriptions[mname] = &h - continue METHODS - } - - // determine method arguments, ignore first arg since it's the receiver type - // Arguments must be exported or builtin types - h.argTypes = make([]reflect.Type, numIn-firstArg) - for i := firstArg; i < numIn; i++ { - argType := mtype.In(i) - if !isExportedOrBuiltinType(argType) { - continue METHODS - } - h.argTypes[i-firstArg] = argType - } - - // check that all returned values are exported or builtin types - for i := 0; i < mtype.NumOut(); i++ { - if !isExportedOrBuiltinType(mtype.Out(i)) { - continue METHODS - } - } - - // when a method returns an error it must be the last returned value - h.errPos = -1 - for i := 0; i < mtype.NumOut(); i++ { - if isErrorType(mtype.Out(i)) { - h.errPos = i - break - } - } - - if h.errPos >= 0 && h.errPos != mtype.NumOut()-1 { - continue METHODS - } - - switch mtype.NumOut() { - case 0, 1, 2: - if mtype.NumOut() == 2 && h.errPos == -1 { // method must one return value and 1 error - continue METHODS - } - callbacks[mname] = &h - } - } - - return callbacks, subscriptions -} - -// idGenerator helper utility that generates a (pseudo) random sequence of -// bytes that are used to generate identifiers. -func idGenerator() *rand.Rand { - if seed, err := binary.ReadVarint(bufio.NewReader(crand.Reader)); err == nil { - return rand.New(rand.NewSource(seed)) - } - return rand.New(rand.NewSource(int64(time.Now().Nanosecond()))) -} - -// NewID generates a identifier that can be used as an identifier in the RPC interface. -// e.g. filter and subscription identifier. -func NewID() ID { - subscriptionIDGenMu.Lock() - defer subscriptionIDGenMu.Unlock() - - id := make([]byte, 16) - for i := 0; i < len(id); i += 7 { - val := subscriptionIDGen.Int63() - for j := 0; i+j < len(id) && j < 7; j++ { - id[i+j] = byte(val) - val >>= 8 - } - } - - rpcId := hex.EncodeToString(id) - // rpc ID's are RPC quantities, no leading zero's and 0 is 0x0 - rpcId = strings.TrimLeft(rpcId, "0") - if rpcId == "" { - rpcId = "0" - } - - return ID("0x" + rpcId) -} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/websocket.go b/vendor/github.com/ethereum/go-ethereum/rpc/websocket.go index eae8320e56..c5383667d9 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/websocket.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/websocket.go @@ -22,6 +22,7 @@ import ( "crypto/tls" "encoding/base64" "encoding/json" + "errors" "fmt" "net" "net/http" @@ -56,24 +57,39 @@ var websocketJSONCodec = websocket.Codec{ // // allowedOrigins should be a comma-separated list of allowed origin URLs. // To allow connections with any origin, pass "*". -func (srv *Server) WebsocketHandler(allowedOrigins []string) http.Handler { +func (s *Server) WebsocketHandler(allowedOrigins []string) http.Handler { return websocket.Server{ Handshake: wsHandshakeValidator(allowedOrigins), Handler: func(conn *websocket.Conn) { - // Create a custom encode/decode pair to enforce payload size and number encoding - conn.MaxPayloadBytes = maxRequestContentLength - - encoder := func(v interface{}) error { - return websocketJSONCodec.Send(conn, v) - } - decoder := func(v interface{}) error { - return websocketJSONCodec.Receive(conn, v) - } - srv.ServeCodec(NewCodec(conn, encoder, decoder), OptionMethodInvocation|OptionSubscriptions) + codec := newWebsocketCodec(conn) + s.ServeCodec(codec, OptionMethodInvocation|OptionSubscriptions) }, } } +func newWebsocketCodec(conn *websocket.Conn) ServerCodec { + // Create a custom encode/decode pair to enforce payload size and number encoding + conn.MaxPayloadBytes = maxRequestContentLength + encoder := func(v interface{}) error { + return websocketJSONCodec.Send(conn, v) + } + decoder := func(v interface{}) error { + return websocketJSONCodec.Receive(conn, v) + } + rpcconn := Conn(conn) + if conn.IsServerConn() { + // Override remote address with the actual socket address because + // package websocket crashes if there is no request origin. + addr := conn.Request().RemoteAddr + if wsaddr := conn.RemoteAddr().(*websocket.Addr); wsaddr.URL != nil { + // Add origin if present. + addr += "(" + wsaddr.URL.String() + ")" + } + rpcconn = connWithRemoteAddr{conn, addr} + } + return NewCodec(rpcconn, encoder, decoder) +} + // NewWSServer creates a new websocket RPC server around an API provider. // // Deprecated: use Server.WebsocketHandler @@ -105,15 +121,23 @@ func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http } } - log.Debug(fmt.Sprintf("Allowed origin(s) for WS RPC interface %v\n", origins.ToSlice())) + log.Debug(fmt.Sprintf("Allowed origin(s) for WS RPC interface %v", origins.ToSlice())) f := func(cfg *websocket.Config, req *http.Request) error { + // Skip origin verification if no Origin header is present. The origin check + // is supposed to protect against browser based attacks. Browsers always set + // Origin. Non-browser software can put anything in origin and checking it doesn't + // provide additional security. + if _, ok := req.Header["Origin"]; !ok { + return nil + } + // Verify origin against whitelist. origin := strings.ToLower(req.Header.Get("Origin")) if allowAllOrigins || origins.Contains(origin) { return nil } - log.Warn(fmt.Sprintf("origin '%s' not allowed on WS-RPC interface\n", origin)) - return fmt.Errorf("origin %s not allowed", origin) + log.Warn("Rejected WebSocket connection", "origin", origin) + return errors.New("origin not allowed") } return f @@ -155,8 +179,12 @@ func DialWebsocket(ctx context.Context, endpoint, origin string) (*Client, error return nil, err } - return newClient(ctx, func(ctx context.Context) (net.Conn, error) { - return wsDialContext(ctx, config) + return newClient(ctx, func(ctx context.Context) (ServerCodec, error) { + conn, err := wsDialContext(ctx, config) + if err != nil { + return nil, err + } + return newWebsocketCodec(conn), nil }) } diff --git a/vendor/github.com/ethereum/go-ethereum/trie/database.go b/vendor/github.com/ethereum/go-ethereum/trie/database.go index 739a98addb..9a4c05d154 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/database.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/database.go @@ -17,6 +17,8 @@ package trie import ( + "encoding/binary" + "errors" "fmt" "io" "sync" @@ -55,20 +57,16 @@ var secureKeyPrefix = []byte("secure-key-") // secureKeyLength is the length of the above prefix + 32byte hash. const secureKeyLength = 11 + 32 -// DatabaseReader wraps the Get and Has method of a backing store for the trie. -type DatabaseReader interface { - // Get retrieves the value associated with key from the database. - Get(key []byte) (value []byte, err error) - - // Has retrieves whether a key is present in the database. - Has(key []byte) (bool, error) -} - // Database is an intermediate write layer between the trie data structures and // the disk database. The aim is to accumulate trie writes in-memory and only // periodically flush a couple tries to disk, garbage collecting the remainder. +// +// Note, the trie Database is **not** thread safe in its mutations, but it **is** +// thread safe in providing individual, independent node access. The rationale +// behind this split design is to provide read access to RPC handlers and sync +// servers even while the trie is executing expensive garbage collection. type Database struct { - diskdb ethdb.Database // Persistent storage for matured trie nodes + diskdb ethdb.KeyValueStore // Persistent storage for matured trie nodes cleans *bigcache.BigCache // GC friendly memory cache of clean node RLPs dirties map[common.Hash]*cachedNode // Data and references relationships of dirty nodes @@ -163,11 +161,11 @@ func (n *cachedNode) rlp() []byte { // obj returns the decoded and expanded trie node, either directly from the cache, // or by regenerating it from the rlp encoded blob. -func (n *cachedNode) obj(hash common.Hash, cachegen uint16) node { +func (n *cachedNode) obj(hash common.Hash) node { if node, ok := n.node.(rawNode); ok { - return mustDecodeNode(hash[:], node, cachegen) + return mustDecodeNode(hash[:], node) } - return expandNode(hash[:], n.node, cachegen) + return expandNode(hash[:], n.node) } // childs returns all the tracked children of this node, both the implicit ones @@ -232,16 +230,15 @@ func simplifyNode(n node) node { // expandNode traverses the node hierarchy of a collapsed storage node and converts // all fields and keys into expanded memory form. -func expandNode(hash hashNode, n node, cachegen uint16) node { +func expandNode(hash hashNode, n node) node { switch n := n.(type) { case *rawShortNode: // Short nodes need key and child expansion return &shortNode{ Key: compactToHex(n.Key), - Val: expandNode(nil, n.Val, cachegen), + Val: expandNode(nil, n.Val), flags: nodeFlag{ hash: hash, - gen: cachegen, }, } @@ -250,12 +247,11 @@ func expandNode(hash hashNode, n node, cachegen uint16) node { node := &fullNode{ flags: nodeFlag{ hash: hash, - gen: cachegen, }, } for i := 0; i < len(node.Children); i++ { if n[i] != nil { - node.Children[i] = expandNode(nil, n[i], cachegen) + node.Children[i] = expandNode(nil, n[i]) } } return node @@ -268,17 +264,30 @@ func expandNode(hash hashNode, n node, cachegen uint16) node { } } +// trienodeHasher is a struct to be used with BigCache, which uses a Hasher to +// determine which shard to place an entry into. It's not a cryptographic hash, +// just to provide a bit of anti-collision (default is FNV64a). +// +// Since trie keys are already hashes, we can just use the key directly to +// map shard id. +type trienodeHasher struct{} + +// Sum64 implements the bigcache.Hasher interface. +func (t trienodeHasher) Sum64(key string) uint64 { + return binary.BigEndian.Uint64([]byte(key)) +} + // NewDatabase creates a new trie database to store ephemeral trie content before // its written out to disk or garbage collected. No read cache is created, so all // data retrievals will hit the underlying disk database. -func NewDatabase(diskdb ethdb.Database) *Database { +func NewDatabase(diskdb ethdb.KeyValueStore) *Database { return NewDatabaseWithCache(diskdb, 0) } // NewDatabaseWithCache creates a new trie database to store ephemeral trie content // before its written out to disk or garbage collected. It also acts as a read cache // for nodes loaded from disk. -func NewDatabaseWithCache(diskdb ethdb.Database, cache int) *Database { +func NewDatabaseWithCache(diskdb ethdb.KeyValueStore, cache int) *Database { var cleans *bigcache.BigCache if cache > 0 { cleans, _ = bigcache.NewBigCache(bigcache.Config{ @@ -287,6 +296,7 @@ func NewDatabaseWithCache(diskdb ethdb.Database, cache int) *Database { MaxEntriesInWindow: cache * 1024, MaxEntrySize: 512, HardMaxCacheSize: cache, + Hasher: trienodeHasher{}, }) } return &Database{ @@ -298,7 +308,7 @@ func NewDatabaseWithCache(diskdb ethdb.Database, cache int) *Database { } // DiskDB retrieves the persistent storage backing the trie database. -func (db *Database) DiskDB() DatabaseReader { +func (db *Database) DiskDB() ethdb.Reader { return db.diskdb } @@ -358,13 +368,13 @@ func (db *Database) insertPreimage(hash common.Hash, preimage []byte) { // node retrieves a cached trie node from memory, or returns nil if none can be // found in the memory cache. -func (db *Database) node(hash common.Hash, cachegen uint16) node { +func (db *Database) node(hash common.Hash) node { // Retrieve the node from the clean cache if available if db.cleans != nil { if enc, err := db.cleans.Get(string(hash[:])); err == nil && enc != nil { memcacheCleanHitMeter.Mark(1) memcacheCleanReadMeter.Mark(int64(len(enc))) - return mustDecodeNode(hash[:], enc, cachegen) + return mustDecodeNode(hash[:], enc) } } // Retrieve the node from the dirty cache if available @@ -373,7 +383,7 @@ func (db *Database) node(hash common.Hash, cachegen uint16) node { db.lock.RUnlock() if dirty != nil { - return dirty.obj(hash, cachegen) + return dirty.obj(hash) } // Content unavailable in memory, attempt to retrieve from disk enc, err := db.diskdb.Get(hash[:]) @@ -385,12 +395,16 @@ func (db *Database) node(hash common.Hash, cachegen uint16) node { memcacheCleanMissMeter.Mark(1) memcacheCleanWriteMeter.Mark(int64(len(enc))) } - return mustDecodeNode(hash[:], enc, cachegen) + return mustDecodeNode(hash[:], enc) } // Node retrieves an encoded cached trie node from memory. If it cannot be found // cached, the method queries the persistent database for the content. func (db *Database) Node(hash common.Hash) ([]byte, error) { + // It doens't make sense to retrieve the metaroot + if hash == (common.Hash{}) { + return nil, errors.New("not found") + } // Retrieve the node from the clean cache if available if db.cleans != nil { if enc, err := db.cleans.Get(string(hash[:])); err == nil && enc != nil { @@ -461,8 +475,8 @@ func (db *Database) Nodes() []common.Hash { // Reference adds a new reference from a parent node to a child node. func (db *Database) Reference(child common.Hash, parent common.Hash) { - db.lock.RLock() - defer db.lock.RUnlock() + db.lock.Lock() + defer db.lock.Unlock() db.reference(child, parent) } @@ -557,13 +571,14 @@ func (db *Database) dereference(child common.Hash, parent common.Hash) { // Cap iteratively flushes old but still referenced trie nodes until the total // memory usage goes below the given threshold. +// +// Note, this method is a non-synchronized mutator. It is unsafe to call this +// concurrently with other mutators. func (db *Database) Cap(limit common.StorageSize) error { // Create a database batch to flush persistent data out. It is important that // outside code doesn't see an inconsistent state (referenced data removed from // memory cache during commit but not yet in persistent storage). This is ensured // by only uncaching existing data when the database write finalizes. - db.lock.RLock() - nodes, storage, start := len(db.dirties), db.dirtiesSize, time.Now() batch := db.diskdb.NewBatch() @@ -579,12 +594,10 @@ func (db *Database) Cap(limit common.StorageSize) error { for hash, preimage := range db.preimages { if err := batch.Put(db.secureKey(hash[:]), preimage); err != nil { log.Error("Failed to commit preimage from trie database", "err", err) - db.lock.RUnlock() return err } if batch.ValueSize() > ethdb.IdealBatchSize { if err := batch.Write(); err != nil { - db.lock.RUnlock() return err } batch.Reset() @@ -597,14 +610,12 @@ func (db *Database) Cap(limit common.StorageSize) error { // Fetch the oldest referenced node and push into the batch node := db.dirties[oldest] if err := batch.Put(oldest[:], node.rlp()); err != nil { - db.lock.RUnlock() return err } // If we exceeded the ideal batch size, commit and reset if batch.ValueSize() >= ethdb.IdealBatchSize { if err := batch.Write(); err != nil { log.Error("Failed to write flush list to disk", "err", err) - db.lock.RUnlock() return err } batch.Reset() @@ -619,11 +630,8 @@ func (db *Database) Cap(limit common.StorageSize) error { // Flush out any remainder data from the last batch if err := batch.Write(); err != nil { log.Error("Failed to write flush list to disk", "err", err) - db.lock.RUnlock() return err } - db.lock.RUnlock() - // Write successful, clear out the flushed data db.lock.Lock() defer db.lock.Unlock() @@ -657,16 +665,16 @@ func (db *Database) Cap(limit common.StorageSize) error { } // Commit iterates over all the children of a particular node, writes them out -// to disk, forcefully tearing down all references in both directions. +// to disk, forcefully tearing down all references in both directions. As a side +// effect, all pre-images accumulated up to this point are also written. // -// As a side effect, all pre-images accumulated up to this point are also written. +// Note, this method is a non-synchronized mutator. It is unsafe to call this +// concurrently with other mutators. func (db *Database) Commit(node common.Hash, report bool) error { // Create a database batch to flush persistent data out. It is important that // outside code doesn't see an inconsistent state (referenced data removed from // memory cache during commit but not yet in persistent storage). This is ensured // by only uncaching existing data when the database write finalizes. - db.lock.RLock() - start := time.Now() batch := db.diskdb.NewBatch() @@ -674,9 +682,9 @@ func (db *Database) Commit(node common.Hash, report bool) error { for hash, preimage := range db.preimages { if err := batch.Put(db.secureKey(hash[:]), preimage); err != nil { log.Error("Failed to commit preimage from trie database", "err", err) - db.lock.RUnlock() return err } + // If the batch is too large, flush to disk if batch.ValueSize() > ethdb.IdealBatchSize { if err := batch.Write(); err != nil { return err @@ -684,30 +692,37 @@ func (db *Database) Commit(node common.Hash, report bool) error { batch.Reset() } } + // Since we're going to replay trie node writes into the clean cache, flush out + // any batched pre-images before continuing. + if err := batch.Write(); err != nil { + return err + } + batch.Reset() + // Move the trie itself into the batch, flushing if enough data is accumulated nodes, storage := len(db.dirties), db.dirtiesSize - if err := db.commit(node, batch); err != nil { + + uncacher := &cleaner{db} + if err := db.commit(node, batch, uncacher); err != nil { log.Error("Failed to commit trie from trie database", "err", err) - db.lock.RUnlock() return err } - // Write batch ready, unlock for readers during persistence + // Trie mostly committed to disk, flush any batch leftovers if err := batch.Write(); err != nil { log.Error("Failed to write trie to disk", "err", err) - db.lock.RUnlock() return err } - db.lock.RUnlock() - - // Write successful, clear out the flushed data + // Uncache any leftovers in the last batch db.lock.Lock() defer db.lock.Unlock() + batch.Replay(uncacher) + batch.Reset() + + // Reset the storage counters and bumpd metrics db.preimages = make(map[common.Hash][]byte) db.preimagesSize = 0 - db.uncache(node) - memcacheCommitTimeTimer.Update(time.Since(start)) memcacheCommitSizeMeter.Mark(int64(storage - db.dirtiesSize)) memcacheCommitNodesMeter.Mark(int64(nodes - len(db.dirties))) @@ -727,14 +742,14 @@ func (db *Database) Commit(node common.Hash, report bool) error { } // commit is the private locked version of Commit. -func (db *Database) commit(hash common.Hash, batch ethdb.Batch) error { +func (db *Database) commit(hash common.Hash, batch ethdb.Batch, uncacher *cleaner) error { // If the node does not exist, it's a previously committed node node, ok := db.dirties[hash] if !ok { return nil } for _, child := range node.childs() { - if err := db.commit(child, batch); err != nil { + if err := db.commit(child, batch, uncacher); err != nil { return err } } @@ -746,39 +761,58 @@ func (db *Database) commit(hash common.Hash, batch ethdb.Batch) error { if err := batch.Write(); err != nil { return err } + db.lock.Lock() + batch.Replay(uncacher) batch.Reset() + db.lock.Unlock() } return nil } -// uncache is the post-processing step of a commit operation where the already -// persisted trie is removed from the cache. The reason behind the two-phase -// commit is to ensure consistent data availability while moving from memory -// to disk. -func (db *Database) uncache(hash common.Hash) { +// cleaner is a database batch replayer that takes a batch of write operations +// and cleans up the trie database from anything written to disk. +type cleaner struct { + db *Database +} + +// Put reacts to database writes and implements dirty data uncaching. This is the +// post-processing step of a commit operation where the already persisted trie is +// removed from the dirty cache and moved into the clean cache. The reason behind +// the two-phase commit is to ensure ensure data availability while moving from +// memory to disk. +func (c *cleaner) Put(key []byte, rlp []byte) error { + hash := common.BytesToHash(key) + // If the node does not exist, we're done on this path - node, ok := db.dirties[hash] + node, ok := c.db.dirties[hash] if !ok { - return + return nil } // Node still exists, remove it from the flush-list switch hash { - case db.oldest: - db.oldest = node.flushNext - db.dirties[node.flushNext].flushPrev = common.Hash{} - case db.newest: - db.newest = node.flushPrev - db.dirties[node.flushPrev].flushNext = common.Hash{} + case c.db.oldest: + c.db.oldest = node.flushNext + c.db.dirties[node.flushNext].flushPrev = common.Hash{} + case c.db.newest: + c.db.newest = node.flushPrev + c.db.dirties[node.flushPrev].flushNext = common.Hash{} default: - db.dirties[node.flushPrev].flushNext = node.flushNext - db.dirties[node.flushNext].flushPrev = node.flushPrev + c.db.dirties[node.flushPrev].flushNext = node.flushNext + c.db.dirties[node.flushNext].flushPrev = node.flushPrev } - // Uncache the node's subtries and remove the node itself too - for _, child := range node.childs() { - db.uncache(child) + // Remove the node from the dirty cache + delete(c.db.dirties, hash) + c.db.dirtiesSize -= common.StorageSize(common.HashLength + int(node.size)) + + // Move the flushed node into the clean cache to prevent insta-reloads + if c.db.cleans != nil { + c.db.cleans.Set(string(hash[:]), rlp) } - delete(db.dirties, hash) - db.dirtiesSize -= common.StorageSize(common.HashLength + int(node.size)) + return nil +} + +func (c *cleaner) Delete(key []byte) error { + panic("Not implemented") } // Size returns the current storage size of the memory cache in front of the @@ -808,7 +842,7 @@ func (db *Database) verifyIntegrity() { db.accumulate(child, reachable) } // Find any unreachable but cached nodes - unreachable := []string{} + var unreachable []string for hash, node := range db.dirties { if _, ok := reachable[hash]; !ok { unreachable = append(unreachable, fmt.Sprintf("%x: {Node: %v, Parents: %d, Prev: %x, Next: %x}", diff --git a/vendor/github.com/ethereum/go-ethereum/trie/encoding.go b/vendor/github.com/ethereum/go-ethereum/trie/encoding.go index 5f120de638..1955a3e664 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/encoding.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/encoding.go @@ -52,6 +52,9 @@ func hexToCompact(hex []byte) []byte { } func compactToHex(compact []byte) []byte { + if len(compact) == 0 { + return compact + } base := keybytesToHex(compact) // delete terminator flag if base[0] < 2 { diff --git a/vendor/github.com/ethereum/go-ethereum/trie/hasher.go b/vendor/github.com/ethereum/go-ethereum/trie/hasher.go index 7b1d7793fa..54f6a9de2b 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/hasher.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/hasher.go @@ -21,16 +21,14 @@ import ( "sync" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" + "golang.org/x/crypto/sha3" ) type hasher struct { - tmp sliceBuffer - sha keccakState - cachegen uint16 - cachelimit uint16 - onleaf LeafCallback + tmp sliceBuffer + sha keccakState + onleaf LeafCallback } // keccakState wraps sha3.state. In addition to the usual hash methods, it also supports @@ -57,14 +55,14 @@ var hasherPool = sync.Pool{ New: func() interface{} { return &hasher{ tmp: make(sliceBuffer, 0, 550), // cap is as large as a full fullNode. - sha: sha3.NewKeccak256().(keccakState), + sha: sha3.NewLegacyKeccak256().(keccakState), } }, } -func newHasher(cachegen, cachelimit uint16, onleaf LeafCallback) *hasher { +func newHasher(onleaf LeafCallback) *hasher { h := hasherPool.Get().(*hasher) - h.cachegen, h.cachelimit, h.onleaf = cachegen, cachelimit, onleaf + h.onleaf = onleaf return h } @@ -80,14 +78,13 @@ func (h *hasher) hash(n node, db *Database, force bool) (node, node, error) { if db == nil { return hash, n, nil } - if n.canUnload(h.cachegen, h.cachelimit) { - // Unload the node from cache. All of its subnodes will have a lower or equal - // cache generation number. - cacheUnloadCounter.Inc(1) - return hash, hash, nil - } if !dirty { - return hash, n, nil + switch n.(type) { + case *fullNode, *shortNode: + return hash, hash, nil + default: + return hash, n, nil + } } } // Trie not processed yet or needs storage, walk the children diff --git a/vendor/github.com/ethereum/go-ethereum/trie/iterator.go b/vendor/github.com/ethereum/go-ethereum/trie/iterator.go index 77f1681665..da93b2fadb 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/iterator.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/iterator.go @@ -180,7 +180,7 @@ func (it *nodeIterator) LeafBlob() []byte { func (it *nodeIterator) LeafProof() [][]byte { if len(it.stack) > 0 { if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok { - hasher := newHasher(0, 0, nil) + hasher := newHasher(nil) defer returnHasherToPool(hasher) proofs := make([][]byte, 0, len(it.stack)) diff --git a/vendor/github.com/ethereum/go-ethereum/trie/node.go b/vendor/github.com/ethereum/go-ethereum/trie/node.go index 1fafb7a538..f4055e779a 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/node.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/node.go @@ -30,7 +30,6 @@ var indices = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b type node interface { fstring(string) string cache() (hashNode, bool) - canUnload(cachegen, cachelimit uint16) bool } type ( @@ -71,20 +70,9 @@ func (n *shortNode) copy() *shortNode { copy := *n; return © } // nodeFlag contains caching-related metadata about a node. type nodeFlag struct { hash hashNode // cached hash of the node (may be nil) - gen uint16 // cache generation counter dirty bool // whether the node has changes that must be written to the database } -// canUnload tells whether a node can be unloaded. -func (n *nodeFlag) canUnload(cachegen, cachelimit uint16) bool { - return !n.dirty && cachegen-n.gen >= cachelimit -} - -func (n *fullNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) } -func (n *shortNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) } -func (n hashNode) canUnload(uint16, uint16) bool { return false } -func (n valueNode) canUnload(uint16, uint16) bool { return false } - func (n *fullNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty } func (n *shortNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty } func (n hashNode) cache() (hashNode, bool) { return nil, true } @@ -117,8 +105,8 @@ func (n valueNode) fstring(ind string) string { return fmt.Sprintf("%x ", []byte(n)) } -func mustDecodeNode(hash, buf []byte, cachegen uint16) node { - n, err := decodeNode(hash, buf, cachegen) +func mustDecodeNode(hash, buf []byte) node { + n, err := decodeNode(hash, buf) if err != nil { panic(fmt.Sprintf("node %x: %v", hash, err)) } @@ -126,7 +114,7 @@ func mustDecodeNode(hash, buf []byte, cachegen uint16) node { } // decodeNode parses the RLP encoding of a trie node. -func decodeNode(hash, buf []byte, cachegen uint16) (node, error) { +func decodeNode(hash, buf []byte) (node, error) { if len(buf) == 0 { return nil, io.ErrUnexpectedEOF } @@ -136,22 +124,22 @@ func decodeNode(hash, buf []byte, cachegen uint16) (node, error) { } switch c, _ := rlp.CountValues(elems); c { case 2: - n, err := decodeShort(hash, elems, cachegen) + n, err := decodeShort(hash, elems) return n, wrapError(err, "short") case 17: - n, err := decodeFull(hash, elems, cachegen) + n, err := decodeFull(hash, elems) return n, wrapError(err, "full") default: return nil, fmt.Errorf("invalid number of list elements: %v", c) } } -func decodeShort(hash, elems []byte, cachegen uint16) (node, error) { +func decodeShort(hash, elems []byte) (node, error) { kbuf, rest, err := rlp.SplitString(elems) if err != nil { return nil, err } - flag := nodeFlag{hash: hash, gen: cachegen} + flag := nodeFlag{hash: hash} key := compactToHex(kbuf) if hasTerm(key) { // value node @@ -161,17 +149,17 @@ func decodeShort(hash, elems []byte, cachegen uint16) (node, error) { } return &shortNode{key, append(valueNode{}, val...), flag}, nil } - r, _, err := decodeRef(rest, cachegen) + r, _, err := decodeRef(rest) if err != nil { return nil, wrapError(err, "val") } return &shortNode{key, r, flag}, nil } -func decodeFull(hash, elems []byte, cachegen uint16) (*fullNode, error) { - n := &fullNode{flags: nodeFlag{hash: hash, gen: cachegen}} +func decodeFull(hash, elems []byte) (*fullNode, error) { + n := &fullNode{flags: nodeFlag{hash: hash}} for i := 0; i < 16; i++ { - cld, rest, err := decodeRef(elems, cachegen) + cld, rest, err := decodeRef(elems) if err != nil { return n, wrapError(err, fmt.Sprintf("[%d]", i)) } @@ -189,7 +177,7 @@ func decodeFull(hash, elems []byte, cachegen uint16) (*fullNode, error) { const hashLen = len(common.Hash{}) -func decodeRef(buf []byte, cachegen uint16) (node, []byte, error) { +func decodeRef(buf []byte) (node, []byte, error) { kind, val, rest, err := rlp.Split(buf) if err != nil { return nil, buf, err @@ -202,7 +190,7 @@ func decodeRef(buf []byte, cachegen uint16) (node, []byte, error) { err := fmt.Errorf("oversized embedded node (size is %d bytes, want size < %d)", size, hashLen) return nil, buf, err } - n, err := decodeNode(nil, buf, cachegen) + n, err := decodeNode(nil, buf) return n, rest, err case kind == rlp.String && len(val) == 0: // empty node diff --git a/vendor/github.com/ethereum/go-ethereum/trie/proof.go b/vendor/github.com/ethereum/go-ethereum/trie/proof.go index f90ecd7d88..26a41ed277 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/proof.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/proof.go @@ -34,10 +34,10 @@ import ( // If the trie does not contain a value for key, the returned proof contains all // nodes of the longest existing prefix of the key (at least the root node), ending // with the node that proves the absence of the key. -func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { +func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Writer) error { // Collect all nodes on the path to key. key = keybytesToHex(key) - nodes := []node{} + var nodes []node tn := t.root for len(key) > 0 && tn != nil { switch n := tn.(type) { @@ -65,7 +65,7 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) } } - hasher := newHasher(0, 0, nil) + hasher := newHasher(nil) defer returnHasherToPool(hasher) for i, n := range nodes { @@ -97,14 +97,14 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { // If the trie does not contain a value for key, the returned proof contains all // nodes of the longest existing prefix of the key (at least the root node), ending // with the node that proves the absence of the key. -func (t *SecureTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { +func (t *SecureTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Writer) error { return t.trie.Prove(key, fromLevel, proofDb) } // VerifyProof checks merkle proofs. The given proof must contain the value for // key in a trie with the given root hash. VerifyProof returns an error if the // proof contains invalid trie nodes or the wrong value. -func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (value []byte, nodes int, err error) { +func VerifyProof(rootHash common.Hash, key []byte, proofDb ethdb.Reader) (value []byte, nodes int, err error) { key = keybytesToHex(key) wantHash := rootHash for i := 0; ; i++ { @@ -112,7 +112,7 @@ func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (valu if buf == nil { return nil, i, fmt.Errorf("proof node %d (hash %064x) missing", i, wantHash) } - n, err := decodeNode(wantHash[:], buf, 0) + n, err := decodeNode(wantHash[:], buf) if err != nil { return nil, i, fmt.Errorf("bad proof node %d: %v", i, err) } diff --git a/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go b/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go index 6a50cfd5a6..fbc591ed10 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go @@ -51,7 +51,7 @@ type SecureTrie struct { // Loaded nodes are kept around until their 'cache generation' expires. // A new cache generation is created by each call to Commit. // cachelimit sets the number of past cache generations to keep. -func NewSecure(root common.Hash, db *Database, cachelimit uint16) (*SecureTrie, error) { +func NewSecure(root common.Hash, db *Database) (*SecureTrie, error) { if db == nil { panic("trie.NewSecure called without a database") } @@ -59,7 +59,6 @@ func NewSecure(root common.Hash, db *Database, cachelimit uint16) (*SecureTrie, if err != nil { return nil, err } - trie.SetCacheLimit(cachelimit) return &SecureTrie{trie: *trie}, nil } @@ -161,12 +160,6 @@ func (t *SecureTrie) Hash() common.Hash { return t.trie.Hash() } -// Root returns the root hash of SecureTrie. -// Deprecated: use Hash instead. -func (t *SecureTrie) Root() []byte { - return t.trie.Root() -} - // Copy returns a copy of SecureTrie. func (t *SecureTrie) Copy() *SecureTrie { cpy := *t @@ -183,7 +176,7 @@ func (t *SecureTrie) NodeIterator(start []byte) NodeIterator { // The caller must not hold onto the return value because it will become // invalid on the next call to hashKey or secKey. func (t *SecureTrie) hashKey(key []byte) []byte { - h := newHasher(0, 0, nil) + h := newHasher(nil) h.sha.Reset() h.sha.Write(key) buf := h.sha.Sum(t.hashKeyBuf[:0]) diff --git a/vendor/github.com/ethereum/go-ethereum/trie/sync.go b/vendor/github.com/ethereum/go-ethereum/trie/sync.go index 67dff5a8b6..85f1b0f850 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/sync.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/sync.go @@ -72,14 +72,14 @@ func newSyncMemBatch() *syncMemBatch { // unknown trie hashes to retrieve, accepts node data associated with said hashes // and reconstructs the trie step by step until all is done. type Sync struct { - database DatabaseReader // Persistent database to check for existing entries + database ethdb.Reader // Persistent database to check for existing entries membatch *syncMemBatch // Memory buffer to avoid frequent database writes requests map[common.Hash]*request // Pending requests pertaining to a key hash queue *prque.Prque // Priority queue with the pending requests } // NewSync creates a new trie data download scheduler. -func NewSync(root common.Hash, database DatabaseReader, callback LeafCallback) *Sync { +func NewSync(root common.Hash, database ethdb.Reader, callback LeafCallback) *Sync { ts := &Sync{ database: database, membatch: newSyncMemBatch(), @@ -101,7 +101,7 @@ func (s *Sync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callb } key := root.Bytes() blob, _ := s.database.Get(key) - if local, err := decodeNode(key, blob, 0); local != nil && err == nil { + if local, err := decodeNode(key, blob); local != nil && err == nil { return } // Assemble the new sub-trie sync request @@ -157,7 +157,7 @@ func (s *Sync) AddRawEntry(hash common.Hash, depth int, parent common.Hash) { // Missing retrieves the known missing nodes from the trie for retrieval. func (s *Sync) Missing(max int) []common.Hash { - requests := []common.Hash{} + var requests []common.Hash for !s.queue.Empty() && (max == 0 || len(requests) < max) { requests = append(requests, s.queue.PopItem().(common.Hash)) } @@ -187,7 +187,7 @@ func (s *Sync) Process(results []SyncResult) (bool, int, error) { continue } // Decode the node data content and update the request - node, err := decodeNode(item.Hash[:], item.Data, 0) + node, err := decodeNode(item.Hash[:], item.Data) if err != nil { return committed, i, err } @@ -213,7 +213,7 @@ func (s *Sync) Process(results []SyncResult) (bool, int, error) { // Commit flushes the data stored in the internal membatch out to persistent // storage, returning the number of items written and any occurred error. -func (s *Sync) Commit(dbw ethdb.Putter) (int, error) { +func (s *Sync) Commit(dbw ethdb.Writer) (int, error) { // Dump the membatch into a database dbw for i, key := range s.membatch.order { if err := dbw.Put(key[:], s.membatch.batch[key]); err != nil { @@ -254,7 +254,7 @@ func (s *Sync) children(req *request, object node) ([]*request, error) { node node depth int } - children := []child{} + var children []child switch node := (object).(type) { case *shortNode: diff --git a/vendor/github.com/ethereum/go-ethereum/trie/trie.go b/vendor/github.com/ethereum/go-ethereum/trie/trie.go index af424d4ac6..920e331fd6 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/trie.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/trie.go @@ -24,7 +24,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" ) var ( @@ -35,25 +34,6 @@ var ( emptyState = crypto.Keccak256Hash(nil) ) -var ( - cacheMissCounter = metrics.NewRegisteredCounter("trie/cachemiss", nil) - cacheUnloadCounter = metrics.NewRegisteredCounter("trie/cacheunload", nil) -) - -// CacheMisses retrieves a global counter measuring the number of cache misses -// the trie had since process startup. This isn't useful for anything apart from -// trie debugging purposes. -func CacheMisses() int64 { - return cacheMissCounter.Count() -} - -// CacheUnloads retrieves a global counter measuring the number of cache unloads -// the trie did since process startup. This isn't useful for anything apart from -// trie debugging purposes. -func CacheUnloads() int64 { - return cacheUnloadCounter.Count() -} - // LeafCallback is a callback type invoked when a trie operation reaches a leaf // node. It's used by state sync and commit to allow handling external references // between account and storage tries. @@ -67,23 +47,11 @@ type LeafCallback func(leaf []byte, parent common.Hash) error type Trie struct { db *Database root node - - // Cache generation values. - // cachegen increases by one with each commit operation. - // new nodes are tagged with the current generation and unloaded - // when their generation is older than than cachegen-cachelimit. - cachegen, cachelimit uint16 -} - -// SetCacheLimit sets the number of 'cache generations' to keep. -// A cache generation is created by a call to Commit. -func (t *Trie) SetCacheLimit(l uint16) { - t.cachelimit = l } // newFlag returns the cache flag value for a newly created node. func (t *Trie) newFlag() nodeFlag { - return nodeFlag{dirty: true, gen: t.cachegen} + return nodeFlag{dirty: true} } // New creates a trie with an existing root node from db. @@ -152,14 +120,12 @@ func (t *Trie) tryGet(origNode node, key []byte, pos int) (value []byte, newnode if err == nil && didResolve { n = n.copy() n.Val = newnode - n.flags.gen = t.cachegen } return value, n, didResolve, err case *fullNode: value, newnode, didResolve, err = t.tryGet(n.Children[key[pos]], key, pos+1) if err == nil && didResolve { n = n.copy() - n.flags.gen = t.cachegen n.Children[key[pos]] = newnode } return value, n, didResolve, err @@ -428,19 +394,13 @@ func (t *Trie) resolve(n node, prefix []byte) (node, error) { } func (t *Trie) resolveHash(n hashNode, prefix []byte) (node, error) { - cacheMissCounter.Inc(1) - hash := common.BytesToHash(n) - if node := t.db.node(hash, t.cachegen); node != nil { + if node := t.db.node(hash); node != nil { return node, nil } return nil, &MissingNodeError{NodeHash: hash, Path: prefix} } -// Root returns the root hash of the trie. -// Deprecated: use Hash instead. -func (t *Trie) Root() []byte { return t.Hash().Bytes() } - // Hash returns the root hash of the trie. It does not write to the // database and can be used even if the trie doesn't have one. func (t *Trie) Hash() common.Hash { @@ -460,7 +420,6 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) { return common.Hash{}, err } t.root = cached - t.cachegen++ return common.BytesToHash(hash.(hashNode)), nil } @@ -468,7 +427,7 @@ func (t *Trie) hashRoot(db *Database, onleaf LeafCallback) (node, node, error) { if t.root == nil { return hashNode(emptyRoot.Bytes()), nil, nil } - h := newHasher(t.cachegen, t.cachelimit, onleaf) + h := newHasher(onleaf) defer returnHasherToPool(h) return h.hash(t.root, db, true) } diff --git a/vendor/github.com/golang/protobuf/descriptor/descriptor.go b/vendor/github.com/golang/protobuf/descriptor/descriptor.go new file mode 100644 index 0000000000..ac7e51bfb1 --- /dev/null +++ b/vendor/github.com/golang/protobuf/descriptor/descriptor.go @@ -0,0 +1,93 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Package descriptor provides functions for obtaining protocol buffer +// descriptors for generated Go types. +// +// These functions cannot go in package proto because they depend on the +// generated protobuf descriptor messages, which themselves depend on proto. +package descriptor + +import ( + "bytes" + "compress/gzip" + "fmt" + "io/ioutil" + + "github.com/golang/protobuf/proto" + protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" +) + +// extractFile extracts a FileDescriptorProto from a gzip'd buffer. +func extractFile(gz []byte) (*protobuf.FileDescriptorProto, error) { + r, err := gzip.NewReader(bytes.NewReader(gz)) + if err != nil { + return nil, fmt.Errorf("failed to open gzip reader: %v", err) + } + defer r.Close() + + b, err := ioutil.ReadAll(r) + if err != nil { + return nil, fmt.Errorf("failed to uncompress descriptor: %v", err) + } + + fd := new(protobuf.FileDescriptorProto) + if err := proto.Unmarshal(b, fd); err != nil { + return nil, fmt.Errorf("malformed FileDescriptorProto: %v", err) + } + + return fd, nil +} + +// Message is a proto.Message with a method to return its descriptor. +// +// Message types generated by the protocol compiler always satisfy +// the Message interface. +type Message interface { + proto.Message + Descriptor() ([]byte, []int) +} + +// ForMessage returns a FileDescriptorProto and a DescriptorProto from within it +// describing the given message. +func ForMessage(msg Message) (fd *protobuf.FileDescriptorProto, md *protobuf.DescriptorProto) { + gz, path := msg.Descriptor() + fd, err := extractFile(gz) + if err != nil { + panic(fmt.Sprintf("invalid FileDescriptorProto for %T: %v", msg, err)) + } + + md = fd.MessageType[path[0]] + for _, i := range path[1:] { + md = md.NestedType[i] + } + return fd, md +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go new file mode 100644 index 0000000000..4e4ddc77be --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go @@ -0,0 +1,1276 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Package jsonpb provides marshaling and unmarshaling between protocol buffers and JSON. +It follows the specification at https://developers.google.com/protocol-buffers/docs/proto3#json. + +This package produces a different output than the standard "encoding/json" package, +which does not operate correctly on protocol buffers. +*/ +package jsonpb + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "math" + "reflect" + "sort" + "strconv" + "strings" + "time" + + "github.com/golang/protobuf/proto" + + stpb "github.com/golang/protobuf/ptypes/struct" +) + +const secondInNanos = int64(time.Second / time.Nanosecond) + +// Marshaler is a configurable object for converting between +// protocol buffer objects and a JSON representation for them. +type Marshaler struct { + // Whether to render enum values as integers, as opposed to string values. + EnumsAsInts bool + + // Whether to render fields with zero values. + EmitDefaults bool + + // A string to indent each level by. The presence of this field will + // also cause a space to appear between the field separator and + // value, and for newlines to be appear between fields and array + // elements. + Indent string + + // Whether to use the original (.proto) name for fields. + OrigName bool + + // A custom URL resolver to use when marshaling Any messages to JSON. + // If unset, the default resolution strategy is to extract the + // fully-qualified type name from the type URL and pass that to + // proto.MessageType(string). + AnyResolver AnyResolver +} + +// AnyResolver takes a type URL, present in an Any message, and resolves it into +// an instance of the associated message. +type AnyResolver interface { + Resolve(typeUrl string) (proto.Message, error) +} + +func defaultResolveAny(typeUrl string) (proto.Message, error) { + // Only the part of typeUrl after the last slash is relevant. + mname := typeUrl + if slash := strings.LastIndex(mname, "/"); slash >= 0 { + mname = mname[slash+1:] + } + mt := proto.MessageType(mname) + if mt == nil { + return nil, fmt.Errorf("unknown message type %q", mname) + } + return reflect.New(mt.Elem()).Interface().(proto.Message), nil +} + +// JSONPBMarshaler is implemented by protobuf messages that customize the +// way they are marshaled to JSON. Messages that implement this should +// also implement JSONPBUnmarshaler so that the custom format can be +// parsed. +// +// The JSON marshaling must follow the proto to JSON specification: +// https://developers.google.com/protocol-buffers/docs/proto3#json +type JSONPBMarshaler interface { + MarshalJSONPB(*Marshaler) ([]byte, error) +} + +// JSONPBUnmarshaler is implemented by protobuf messages that customize +// the way they are unmarshaled from JSON. Messages that implement this +// should also implement JSONPBMarshaler so that the custom format can be +// produced. +// +// The JSON unmarshaling must follow the JSON to proto specification: +// https://developers.google.com/protocol-buffers/docs/proto3#json +type JSONPBUnmarshaler interface { + UnmarshalJSONPB(*Unmarshaler, []byte) error +} + +// Marshal marshals a protocol buffer into JSON. +func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error { + v := reflect.ValueOf(pb) + if pb == nil || (v.Kind() == reflect.Ptr && v.IsNil()) { + return errors.New("Marshal called with nil") + } + // Check for unset required fields first. + if err := checkRequiredFields(pb); err != nil { + return err + } + writer := &errWriter{writer: out} + return m.marshalObject(writer, pb, "", "") +} + +// MarshalToString converts a protocol buffer object to JSON string. +func (m *Marshaler) MarshalToString(pb proto.Message) (string, error) { + var buf bytes.Buffer + if err := m.Marshal(&buf, pb); err != nil { + return "", err + } + return buf.String(), nil +} + +type int32Slice []int32 + +var nonFinite = map[string]float64{ + `"NaN"`: math.NaN(), + `"Infinity"`: math.Inf(1), + `"-Infinity"`: math.Inf(-1), +} + +// For sorting extensions ids to ensure stable output. +func (s int32Slice) Len() int { return len(s) } +func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +type wkt interface { + XXX_WellKnownType() string +} + +// marshalObject writes a struct to the Writer. +func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeURL string) error { + if jsm, ok := v.(JSONPBMarshaler); ok { + b, err := jsm.MarshalJSONPB(m) + if err != nil { + return err + } + if typeURL != "" { + // we are marshaling this object to an Any type + var js map[string]*json.RawMessage + if err = json.Unmarshal(b, &js); err != nil { + return fmt.Errorf("type %T produced invalid JSON: %v", v, err) + } + turl, err := json.Marshal(typeURL) + if err != nil { + return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err) + } + js["@type"] = (*json.RawMessage)(&turl) + if m.Indent != "" { + b, err = json.MarshalIndent(js, indent, m.Indent) + } else { + b, err = json.Marshal(js) + } + if err != nil { + return err + } + } + + out.write(string(b)) + return out.err + } + + s := reflect.ValueOf(v).Elem() + + // Handle well-known types. + if wkt, ok := v.(wkt); ok { + switch wkt.XXX_WellKnownType() { + case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", + "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": + // "Wrappers use the same representation in JSON + // as the wrapped primitive type, ..." + sprop := proto.GetProperties(s.Type()) + return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent) + case "Any": + // Any is a bit more involved. + return m.marshalAny(out, v, indent) + case "Duration": + // "Generated output always contains 0, 3, 6, or 9 fractional digits, + // depending on required precision." + s, ns := s.Field(0).Int(), s.Field(1).Int() + if ns <= -secondInNanos || ns >= secondInNanos { + return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos) + } + if (s > 0 && ns < 0) || (s < 0 && ns > 0) { + return errors.New("signs of seconds and nanos do not match") + } + if s < 0 { + ns = -ns + } + x := fmt.Sprintf("%d.%09d", s, ns) + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, ".000") + out.write(`"`) + out.write(x) + out.write(`s"`) + return out.err + case "Struct", "ListValue": + // Let marshalValue handle the `Struct.fields` map or the `ListValue.values` slice. + // TODO: pass the correct Properties if needed. + return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent) + case "Timestamp": + // "RFC 3339, where generated output will always be Z-normalized + // and uses 0, 3, 6 or 9 fractional digits." + s, ns := s.Field(0).Int(), s.Field(1).Int() + if ns < 0 || ns >= secondInNanos { + return fmt.Errorf("ns out of range [0, %v)", secondInNanos) + } + t := time.Unix(s, ns).UTC() + // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). + x := t.Format("2006-01-02T15:04:05.000000000") + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, ".000") + out.write(`"`) + out.write(x) + out.write(`Z"`) + return out.err + case "Value": + // Value has a single oneof. + kind := s.Field(0) + if kind.IsNil() { + // "absence of any variant indicates an error" + return errors.New("nil Value") + } + // oneof -> *T -> T -> T.F + x := kind.Elem().Elem().Field(0) + // TODO: pass the correct Properties if needed. + return m.marshalValue(out, &proto.Properties{}, x, indent) + } + } + + out.write("{") + if m.Indent != "" { + out.write("\n") + } + + firstField := true + + if typeURL != "" { + if err := m.marshalTypeURL(out, indent, typeURL); err != nil { + return err + } + firstField = false + } + + for i := 0; i < s.NumField(); i++ { + value := s.Field(i) + valueField := s.Type().Field(i) + if strings.HasPrefix(valueField.Name, "XXX_") { + continue + } + + // IsNil will panic on most value kinds. + switch value.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface: + if value.IsNil() { + continue + } + } + + if !m.EmitDefaults { + switch value.Kind() { + case reflect.Bool: + if !value.Bool() { + continue + } + case reflect.Int32, reflect.Int64: + if value.Int() == 0 { + continue + } + case reflect.Uint32, reflect.Uint64: + if value.Uint() == 0 { + continue + } + case reflect.Float32, reflect.Float64: + if value.Float() == 0 { + continue + } + case reflect.String: + if value.Len() == 0 { + continue + } + case reflect.Map, reflect.Ptr, reflect.Slice: + if value.IsNil() { + continue + } + } + } + + // Oneof fields need special handling. + if valueField.Tag.Get("protobuf_oneof") != "" { + // value is an interface containing &T{real_value}. + sv := value.Elem().Elem() // interface -> *T -> T + value = sv.Field(0) + valueField = sv.Type().Field(0) + } + prop := jsonProperties(valueField, m.OrigName) + if !firstField { + m.writeSep(out) + } + if err := m.marshalField(out, prop, value, indent); err != nil { + return err + } + firstField = false + } + + // Handle proto2 extensions. + if ep, ok := v.(proto.Message); ok { + extensions := proto.RegisteredExtensions(v) + // Sort extensions for stable output. + ids := make([]int32, 0, len(extensions)) + for id, desc := range extensions { + if !proto.HasExtension(ep, desc) { + continue + } + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) + for _, id := range ids { + desc := extensions[id] + if desc == nil { + // unknown extension + continue + } + ext, extErr := proto.GetExtension(ep, desc) + if extErr != nil { + return extErr + } + value := reflect.ValueOf(ext) + var prop proto.Properties + prop.Parse(desc.Tag) + prop.JSONName = fmt.Sprintf("[%s]", desc.Name) + if !firstField { + m.writeSep(out) + } + if err := m.marshalField(out, &prop, value, indent); err != nil { + return err + } + firstField = false + } + + } + + if m.Indent != "" { + out.write("\n") + out.write(indent) + } + out.write("}") + return out.err +} + +func (m *Marshaler) writeSep(out *errWriter) { + if m.Indent != "" { + out.write(",\n") + } else { + out.write(",") + } +} + +func (m *Marshaler) marshalAny(out *errWriter, any proto.Message, indent string) error { + // "If the Any contains a value that has a special JSON mapping, + // it will be converted as follows: {"@type": xxx, "value": yyy}. + // Otherwise, the value will be converted into a JSON object, + // and the "@type" field will be inserted to indicate the actual data type." + v := reflect.ValueOf(any).Elem() + turl := v.Field(0).String() + val := v.Field(1).Bytes() + + var msg proto.Message + var err error + if m.AnyResolver != nil { + msg, err = m.AnyResolver.Resolve(turl) + } else { + msg, err = defaultResolveAny(turl) + } + if err != nil { + return err + } + + if err := proto.Unmarshal(val, msg); err != nil { + return err + } + + if _, ok := msg.(wkt); ok { + out.write("{") + if m.Indent != "" { + out.write("\n") + } + if err := m.marshalTypeURL(out, indent, turl); err != nil { + return err + } + m.writeSep(out) + if m.Indent != "" { + out.write(indent) + out.write(m.Indent) + out.write(`"value": `) + } else { + out.write(`"value":`) + } + if err := m.marshalObject(out, msg, indent+m.Indent, ""); err != nil { + return err + } + if m.Indent != "" { + out.write("\n") + out.write(indent) + } + out.write("}") + return out.err + } + + return m.marshalObject(out, msg, indent, turl) +} + +func (m *Marshaler) marshalTypeURL(out *errWriter, indent, typeURL string) error { + if m.Indent != "" { + out.write(indent) + out.write(m.Indent) + } + out.write(`"@type":`) + if m.Indent != "" { + out.write(" ") + } + b, err := json.Marshal(typeURL) + if err != nil { + return err + } + out.write(string(b)) + return out.err +} + +// marshalField writes field description and value to the Writer. +func (m *Marshaler) marshalField(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error { + if m.Indent != "" { + out.write(indent) + out.write(m.Indent) + } + out.write(`"`) + out.write(prop.JSONName) + out.write(`":`) + if m.Indent != "" { + out.write(" ") + } + if err := m.marshalValue(out, prop, v, indent); err != nil { + return err + } + return nil +} + +// marshalValue writes the value to the Writer. +func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error { + var err error + v = reflect.Indirect(v) + + // Handle nil pointer + if v.Kind() == reflect.Invalid { + out.write("null") + return out.err + } + + // Handle repeated elements. + if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 { + out.write("[") + comma := "" + for i := 0; i < v.Len(); i++ { + sliceVal := v.Index(i) + out.write(comma) + if m.Indent != "" { + out.write("\n") + out.write(indent) + out.write(m.Indent) + out.write(m.Indent) + } + if err := m.marshalValue(out, prop, sliceVal, indent+m.Indent); err != nil { + return err + } + comma = "," + } + if m.Indent != "" { + out.write("\n") + out.write(indent) + out.write(m.Indent) + } + out.write("]") + return out.err + } + + // Handle well-known types. + // Most are handled up in marshalObject (because 99% are messages). + if wkt, ok := v.Interface().(wkt); ok { + switch wkt.XXX_WellKnownType() { + case "NullValue": + out.write("null") + return out.err + } + } + + // Handle enumerations. + if !m.EnumsAsInts && prop.Enum != "" { + // Unknown enum values will are stringified by the proto library as their + // value. Such values should _not_ be quoted or they will be interpreted + // as an enum string instead of their value. + enumStr := v.Interface().(fmt.Stringer).String() + var valStr string + if v.Kind() == reflect.Ptr { + valStr = strconv.Itoa(int(v.Elem().Int())) + } else { + valStr = strconv.Itoa(int(v.Int())) + } + isKnownEnum := enumStr != valStr + if isKnownEnum { + out.write(`"`) + } + out.write(enumStr) + if isKnownEnum { + out.write(`"`) + } + return out.err + } + + // Handle nested messages. + if v.Kind() == reflect.Struct { + return m.marshalObject(out, v.Addr().Interface().(proto.Message), indent+m.Indent, "") + } + + // Handle maps. + // Since Go randomizes map iteration, we sort keys for stable output. + if v.Kind() == reflect.Map { + out.write(`{`) + keys := v.MapKeys() + sort.Sort(mapKeys(keys)) + for i, k := range keys { + if i > 0 { + out.write(`,`) + } + if m.Indent != "" { + out.write("\n") + out.write(indent) + out.write(m.Indent) + out.write(m.Indent) + } + + // TODO handle map key prop properly + b, err := json.Marshal(k.Interface()) + if err != nil { + return err + } + s := string(b) + + // If the JSON is not a string value, encode it again to make it one. + if !strings.HasPrefix(s, `"`) { + b, err := json.Marshal(s) + if err != nil { + return err + } + s = string(b) + } + + out.write(s) + out.write(`:`) + if m.Indent != "" { + out.write(` `) + } + + vprop := prop + if prop != nil && prop.MapValProp != nil { + vprop = prop.MapValProp + } + if err := m.marshalValue(out, vprop, v.MapIndex(k), indent+m.Indent); err != nil { + return err + } + } + if m.Indent != "" { + out.write("\n") + out.write(indent) + out.write(m.Indent) + } + out.write(`}`) + return out.err + } + + // Handle non-finite floats, e.g. NaN, Infinity and -Infinity. + if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { + f := v.Float() + var sval string + switch { + case math.IsInf(f, 1): + sval = `"Infinity"` + case math.IsInf(f, -1): + sval = `"-Infinity"` + case math.IsNaN(f): + sval = `"NaN"` + } + if sval != "" { + out.write(sval) + return out.err + } + } + + // Default handling defers to the encoding/json library. + b, err := json.Marshal(v.Interface()) + if err != nil { + return err + } + needToQuote := string(b[0]) != `"` && (v.Kind() == reflect.Int64 || v.Kind() == reflect.Uint64) + if needToQuote { + out.write(`"`) + } + out.write(string(b)) + if needToQuote { + out.write(`"`) + } + return out.err +} + +// Unmarshaler is a configurable object for converting from a JSON +// representation to a protocol buffer object. +type Unmarshaler struct { + // Whether to allow messages to contain unknown fields, as opposed to + // failing to unmarshal. + AllowUnknownFields bool + + // A custom URL resolver to use when unmarshaling Any messages from JSON. + // If unset, the default resolution strategy is to extract the + // fully-qualified type name from the type URL and pass that to + // proto.MessageType(string). + AnyResolver AnyResolver +} + +// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream. +// This function is lenient and will decode any options permutations of the +// related Marshaler. +func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error { + inputValue := json.RawMessage{} + if err := dec.Decode(&inputValue); err != nil { + return err + } + if err := u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil); err != nil { + return err + } + return checkRequiredFields(pb) +} + +// Unmarshal unmarshals a JSON object stream into a protocol +// buffer. This function is lenient and will decode any options +// permutations of the related Marshaler. +func (u *Unmarshaler) Unmarshal(r io.Reader, pb proto.Message) error { + dec := json.NewDecoder(r) + return u.UnmarshalNext(dec, pb) +} + +// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream. +// This function is lenient and will decode any options permutations of the +// related Marshaler. +func UnmarshalNext(dec *json.Decoder, pb proto.Message) error { + return new(Unmarshaler).UnmarshalNext(dec, pb) +} + +// Unmarshal unmarshals a JSON object stream into a protocol +// buffer. This function is lenient and will decode any options +// permutations of the related Marshaler. +func Unmarshal(r io.Reader, pb proto.Message) error { + return new(Unmarshaler).Unmarshal(r, pb) +} + +// UnmarshalString will populate the fields of a protocol buffer based +// on a JSON string. This function is lenient and will decode any options +// permutations of the related Marshaler. +func UnmarshalString(str string, pb proto.Message) error { + return new(Unmarshaler).Unmarshal(strings.NewReader(str), pb) +} + +// unmarshalValue converts/copies a value into the target. +// prop may be nil. +func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *proto.Properties) error { + targetType := target.Type() + + // Allocate memory for pointer fields. + if targetType.Kind() == reflect.Ptr { + // If input value is "null" and target is a pointer type, then the field should be treated as not set + // UNLESS the target is structpb.Value, in which case it should be set to structpb.NullValue. + _, isJSONPBUnmarshaler := target.Interface().(JSONPBUnmarshaler) + if string(inputValue) == "null" && targetType != reflect.TypeOf(&stpb.Value{}) && !isJSONPBUnmarshaler { + return nil + } + target.Set(reflect.New(targetType.Elem())) + + return u.unmarshalValue(target.Elem(), inputValue, prop) + } + + if jsu, ok := target.Addr().Interface().(JSONPBUnmarshaler); ok { + return jsu.UnmarshalJSONPB(u, []byte(inputValue)) + } + + // Handle well-known types that are not pointers. + if w, ok := target.Addr().Interface().(wkt); ok { + switch w.XXX_WellKnownType() { + case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", + "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": + return u.unmarshalValue(target.Field(0), inputValue, prop) + case "Any": + // Use json.RawMessage pointer type instead of value to support pre-1.8 version. + // 1.8 changed RawMessage.MarshalJSON from pointer type to value type, see + // https://github.com/golang/go/issues/14493 + var jsonFields map[string]*json.RawMessage + if err := json.Unmarshal(inputValue, &jsonFields); err != nil { + return err + } + + val, ok := jsonFields["@type"] + if !ok || val == nil { + return errors.New("Any JSON doesn't have '@type'") + } + + var turl string + if err := json.Unmarshal([]byte(*val), &turl); err != nil { + return fmt.Errorf("can't unmarshal Any's '@type': %q", *val) + } + target.Field(0).SetString(turl) + + var m proto.Message + var err error + if u.AnyResolver != nil { + m, err = u.AnyResolver.Resolve(turl) + } else { + m, err = defaultResolveAny(turl) + } + if err != nil { + return err + } + + if _, ok := m.(wkt); ok { + val, ok := jsonFields["value"] + if !ok { + return errors.New("Any JSON doesn't have 'value'") + } + + if err := u.unmarshalValue(reflect.ValueOf(m).Elem(), *val, nil); err != nil { + return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err) + } + } else { + delete(jsonFields, "@type") + nestedProto, err := json.Marshal(jsonFields) + if err != nil { + return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err) + } + + if err = u.unmarshalValue(reflect.ValueOf(m).Elem(), nestedProto, nil); err != nil { + return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err) + } + } + + b, err := proto.Marshal(m) + if err != nil { + return fmt.Errorf("can't marshal proto %T into Any.Value: %v", m, err) + } + target.Field(1).SetBytes(b) + + return nil + case "Duration": + unq, err := unquote(string(inputValue)) + if err != nil { + return err + } + + d, err := time.ParseDuration(unq) + if err != nil { + return fmt.Errorf("bad Duration: %v", err) + } + + ns := d.Nanoseconds() + s := ns / 1e9 + ns %= 1e9 + target.Field(0).SetInt(s) + target.Field(1).SetInt(ns) + return nil + case "Timestamp": + unq, err := unquote(string(inputValue)) + if err != nil { + return err + } + + t, err := time.Parse(time.RFC3339Nano, unq) + if err != nil { + return fmt.Errorf("bad Timestamp: %v", err) + } + + target.Field(0).SetInt(t.Unix()) + target.Field(1).SetInt(int64(t.Nanosecond())) + return nil + case "Struct": + var m map[string]json.RawMessage + if err := json.Unmarshal(inputValue, &m); err != nil { + return fmt.Errorf("bad StructValue: %v", err) + } + + target.Field(0).Set(reflect.ValueOf(map[string]*stpb.Value{})) + for k, jv := range m { + pv := &stpb.Value{} + if err := u.unmarshalValue(reflect.ValueOf(pv).Elem(), jv, prop); err != nil { + return fmt.Errorf("bad value in StructValue for key %q: %v", k, err) + } + target.Field(0).SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(pv)) + } + return nil + case "ListValue": + var s []json.RawMessage + if err := json.Unmarshal(inputValue, &s); err != nil { + return fmt.Errorf("bad ListValue: %v", err) + } + + target.Field(0).Set(reflect.ValueOf(make([]*stpb.Value, len(s)))) + for i, sv := range s { + if err := u.unmarshalValue(target.Field(0).Index(i), sv, prop); err != nil { + return err + } + } + return nil + case "Value": + ivStr := string(inputValue) + if ivStr == "null" { + target.Field(0).Set(reflect.ValueOf(&stpb.Value_NullValue{})) + } else if v, err := strconv.ParseFloat(ivStr, 0); err == nil { + target.Field(0).Set(reflect.ValueOf(&stpb.Value_NumberValue{v})) + } else if v, err := unquote(ivStr); err == nil { + target.Field(0).Set(reflect.ValueOf(&stpb.Value_StringValue{v})) + } else if v, err := strconv.ParseBool(ivStr); err == nil { + target.Field(0).Set(reflect.ValueOf(&stpb.Value_BoolValue{v})) + } else if err := json.Unmarshal(inputValue, &[]json.RawMessage{}); err == nil { + lv := &stpb.ListValue{} + target.Field(0).Set(reflect.ValueOf(&stpb.Value_ListValue{lv})) + return u.unmarshalValue(reflect.ValueOf(lv).Elem(), inputValue, prop) + } else if err := json.Unmarshal(inputValue, &map[string]json.RawMessage{}); err == nil { + sv := &stpb.Struct{} + target.Field(0).Set(reflect.ValueOf(&stpb.Value_StructValue{sv})) + return u.unmarshalValue(reflect.ValueOf(sv).Elem(), inputValue, prop) + } else { + return fmt.Errorf("unrecognized type for Value %q", ivStr) + } + return nil + } + } + + // Handle enums, which have an underlying type of int32, + // and may appear as strings. + // The case of an enum appearing as a number is handled + // at the bottom of this function. + if inputValue[0] == '"' && prop != nil && prop.Enum != "" { + vmap := proto.EnumValueMap(prop.Enum) + // Don't need to do unquoting; valid enum names + // are from a limited character set. + s := inputValue[1 : len(inputValue)-1] + n, ok := vmap[string(s)] + if !ok { + return fmt.Errorf("unknown value %q for enum %s", s, prop.Enum) + } + if target.Kind() == reflect.Ptr { // proto2 + target.Set(reflect.New(targetType.Elem())) + target = target.Elem() + } + if targetType.Kind() != reflect.Int32 { + return fmt.Errorf("invalid target %q for enum %s", targetType.Kind(), prop.Enum) + } + target.SetInt(int64(n)) + return nil + } + + // Handle nested messages. + if targetType.Kind() == reflect.Struct { + var jsonFields map[string]json.RawMessage + if err := json.Unmarshal(inputValue, &jsonFields); err != nil { + return err + } + + consumeField := func(prop *proto.Properties) (json.RawMessage, bool) { + // Be liberal in what names we accept; both orig_name and camelName are okay. + fieldNames := acceptedJSONFieldNames(prop) + + vOrig, okOrig := jsonFields[fieldNames.orig] + vCamel, okCamel := jsonFields[fieldNames.camel] + if !okOrig && !okCamel { + return nil, false + } + // If, for some reason, both are present in the data, favour the camelName. + var raw json.RawMessage + if okOrig { + raw = vOrig + delete(jsonFields, fieldNames.orig) + } + if okCamel { + raw = vCamel + delete(jsonFields, fieldNames.camel) + } + return raw, true + } + + sprops := proto.GetProperties(targetType) + for i := 0; i < target.NumField(); i++ { + ft := target.Type().Field(i) + if strings.HasPrefix(ft.Name, "XXX_") { + continue + } + + valueForField, ok := consumeField(sprops.Prop[i]) + if !ok { + continue + } + + if err := u.unmarshalValue(target.Field(i), valueForField, sprops.Prop[i]); err != nil { + return err + } + } + // Check for any oneof fields. + if len(jsonFields) > 0 { + for _, oop := range sprops.OneofTypes { + raw, ok := consumeField(oop.Prop) + if !ok { + continue + } + nv := reflect.New(oop.Type.Elem()) + target.Field(oop.Field).Set(nv) + if err := u.unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil { + return err + } + } + } + // Handle proto2 extensions. + if len(jsonFields) > 0 { + if ep, ok := target.Addr().Interface().(proto.Message); ok { + for _, ext := range proto.RegisteredExtensions(ep) { + name := fmt.Sprintf("[%s]", ext.Name) + raw, ok := jsonFields[name] + if !ok { + continue + } + delete(jsonFields, name) + nv := reflect.New(reflect.TypeOf(ext.ExtensionType).Elem()) + if err := u.unmarshalValue(nv.Elem(), raw, nil); err != nil { + return err + } + if err := proto.SetExtension(ep, ext, nv.Interface()); err != nil { + return err + } + } + } + } + if !u.AllowUnknownFields && len(jsonFields) > 0 { + // Pick any field to be the scapegoat. + var f string + for fname := range jsonFields { + f = fname + break + } + return fmt.Errorf("unknown field %q in %v", f, targetType) + } + return nil + } + + // Handle arrays (which aren't encoded bytes) + if targetType.Kind() == reflect.Slice && targetType.Elem().Kind() != reflect.Uint8 { + var slc []json.RawMessage + if err := json.Unmarshal(inputValue, &slc); err != nil { + return err + } + if slc != nil { + l := len(slc) + target.Set(reflect.MakeSlice(targetType, l, l)) + for i := 0; i < l; i++ { + if err := u.unmarshalValue(target.Index(i), slc[i], prop); err != nil { + return err + } + } + } + return nil + } + + // Handle maps (whose keys are always strings) + if targetType.Kind() == reflect.Map { + var mp map[string]json.RawMessage + if err := json.Unmarshal(inputValue, &mp); err != nil { + return err + } + if mp != nil { + target.Set(reflect.MakeMap(targetType)) + for ks, raw := range mp { + // Unmarshal map key. The core json library already decoded the key into a + // string, so we handle that specially. Other types were quoted post-serialization. + var k reflect.Value + if targetType.Key().Kind() == reflect.String { + k = reflect.ValueOf(ks) + } else { + k = reflect.New(targetType.Key()).Elem() + var kprop *proto.Properties + if prop != nil && prop.MapKeyProp != nil { + kprop = prop.MapKeyProp + } + if err := u.unmarshalValue(k, json.RawMessage(ks), kprop); err != nil { + return err + } + } + + // Unmarshal map value. + v := reflect.New(targetType.Elem()).Elem() + var vprop *proto.Properties + if prop != nil && prop.MapValProp != nil { + vprop = prop.MapValProp + } + if err := u.unmarshalValue(v, raw, vprop); err != nil { + return err + } + target.SetMapIndex(k, v) + } + } + return nil + } + + // Non-finite numbers can be encoded as strings. + isFloat := targetType.Kind() == reflect.Float32 || targetType.Kind() == reflect.Float64 + if isFloat { + if num, ok := nonFinite[string(inputValue)]; ok { + target.SetFloat(num) + return nil + } + } + + // integers & floats can be encoded as strings. In this case we drop + // the quotes and proceed as normal. + isNum := targetType.Kind() == reflect.Int64 || targetType.Kind() == reflect.Uint64 || + targetType.Kind() == reflect.Int32 || targetType.Kind() == reflect.Uint32 || + targetType.Kind() == reflect.Float32 || targetType.Kind() == reflect.Float64 + if isNum && strings.HasPrefix(string(inputValue), `"`) { + inputValue = inputValue[1 : len(inputValue)-1] + } + + // Use the encoding/json for parsing other value types. + return json.Unmarshal(inputValue, target.Addr().Interface()) +} + +func unquote(s string) (string, error) { + var ret string + err := json.Unmarshal([]byte(s), &ret) + return ret, err +} + +// jsonProperties returns parsed proto.Properties for the field and corrects JSONName attribute. +func jsonProperties(f reflect.StructField, origName bool) *proto.Properties { + var prop proto.Properties + prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f) + if origName || prop.JSONName == "" { + prop.JSONName = prop.OrigName + } + return &prop +} + +type fieldNames struct { + orig, camel string +} + +func acceptedJSONFieldNames(prop *proto.Properties) fieldNames { + opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName} + if prop.JSONName != "" { + opts.camel = prop.JSONName + } + return opts +} + +// Writer wrapper inspired by https://blog.golang.org/errors-are-values +type errWriter struct { + writer io.Writer + err error +} + +func (w *errWriter) write(str string) { + if w.err != nil { + return + } + _, w.err = w.writer.Write([]byte(str)) +} + +// Map fields may have key types of non-float scalars, strings and enums. +// The easiest way to sort them in some deterministic order is to use fmt. +// If this turns out to be inefficient we can always consider other options, +// such as doing a Schwartzian transform. +// +// Numeric keys are sorted in numeric order per +// https://developers.google.com/protocol-buffers/docs/proto#maps. +type mapKeys []reflect.Value + +func (s mapKeys) Len() int { return len(s) } +func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s mapKeys) Less(i, j int) bool { + if k := s[i].Kind(); k == s[j].Kind() { + switch k { + case reflect.String: + return s[i].String() < s[j].String() + case reflect.Int32, reflect.Int64: + return s[i].Int() < s[j].Int() + case reflect.Uint32, reflect.Uint64: + return s[i].Uint() < s[j].Uint() + } + } + return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface()) +} + +// checkRequiredFields returns an error if any required field in the given proto message is not set. +// This function is used by both Marshal and Unmarshal. While required fields only exist in a +// proto2 message, a proto3 message can contain proto2 message(s). +func checkRequiredFields(pb proto.Message) error { + // Most well-known type messages do not contain required fields. The "Any" type may contain + // a message that has required fields. + // + // When an Any message is being marshaled, the code will invoked proto.Unmarshal on Any.Value + // field in order to transform that into JSON, and that should have returned an error if a + // required field is not set in the embedded message. + // + // When an Any message is being unmarshaled, the code will have invoked proto.Marshal on the + // embedded message to store the serialized message in Any.Value field, and that should have + // returned an error if a required field is not set. + if _, ok := pb.(wkt); ok { + return nil + } + + v := reflect.ValueOf(pb) + // Skip message if it is not a struct pointer. + if v.Kind() != reflect.Ptr { + return nil + } + v = v.Elem() + if v.Kind() != reflect.Struct { + return nil + } + + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + sfield := v.Type().Field(i) + + if sfield.PkgPath != "" { + // blank PkgPath means the field is exported; skip if not exported + continue + } + + if strings.HasPrefix(sfield.Name, "XXX_") { + continue + } + + // Oneof field is an interface implemented by wrapper structs containing the actual oneof + // field, i.e. an interface containing &T{real_value}. + if sfield.Tag.Get("protobuf_oneof") != "" { + if field.Kind() != reflect.Interface { + continue + } + v := field.Elem() + if v.Kind() != reflect.Ptr || v.IsNil() { + continue + } + v = v.Elem() + if v.Kind() != reflect.Struct || v.NumField() < 1 { + continue + } + field = v.Field(0) + sfield = v.Type().Field(0) + } + + protoTag := sfield.Tag.Get("protobuf") + if protoTag == "" { + continue + } + var prop proto.Properties + prop.Init(sfield.Type, sfield.Name, protoTag, &sfield) + + switch field.Kind() { + case reflect.Map: + if field.IsNil() { + continue + } + // Check each map value. + keys := field.MapKeys() + for _, k := range keys { + v := field.MapIndex(k) + if err := checkRequiredFieldsInValue(v); err != nil { + return err + } + } + case reflect.Slice: + // Handle non-repeated type, e.g. bytes. + if !prop.Repeated { + if prop.Required && field.IsNil() { + return fmt.Errorf("required field %q is not set", prop.Name) + } + continue + } + + // Handle repeated type. + if field.IsNil() { + continue + } + // Check each slice item. + for i := 0; i < field.Len(); i++ { + v := field.Index(i) + if err := checkRequiredFieldsInValue(v); err != nil { + return err + } + } + case reflect.Ptr: + if field.IsNil() { + if prop.Required { + return fmt.Errorf("required field %q is not set", prop.Name) + } + continue + } + if err := checkRequiredFieldsInValue(field); err != nil { + return err + } + } + } + + // Handle proto2 extensions. + for _, ext := range proto.RegisteredExtensions(pb) { + if !proto.HasExtension(pb, ext) { + continue + } + ep, err := proto.GetExtension(pb, ext) + if err != nil { + return err + } + err = checkRequiredFieldsInValue(reflect.ValueOf(ep)) + if err != nil { + return err + } + } + + return nil +} + +func checkRequiredFieldsInValue(v reflect.Value) error { + if pm, ok := v.Interface().(proto.Message); ok { + return checkRequiredFields(pm) + } + return nil +} diff --git a/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go new file mode 100644 index 0000000000..9a754c8acd --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go @@ -0,0 +1,577 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: proto3_proto/proto3.proto + +package proto3_proto + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + test_proto "github.com/golang/protobuf/proto/test_proto" + any "github.com/golang/protobuf/ptypes/any" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type Message_Humour int32 + +const ( + Message_UNKNOWN Message_Humour = 0 + Message_PUNS Message_Humour = 1 + Message_SLAPSTICK Message_Humour = 2 + Message_BILL_BAILEY Message_Humour = 3 +) + +var Message_Humour_name = map[int32]string{ + 0: "UNKNOWN", + 1: "PUNS", + 2: "SLAPSTICK", + 3: "BILL_BAILEY", +} + +var Message_Humour_value = map[string]int32{ + "UNKNOWN": 0, + "PUNS": 1, + "SLAPSTICK": 2, + "BILL_BAILEY": 3, +} + +func (x Message_Humour) String() string { + return proto.EnumName(Message_Humour_name, int32(x)) +} + +func (Message_Humour) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_1c50d9b824d4ac38, []int{0, 0} +} + +type Message struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,proto3,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"` + HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm,proto3" json:"height_in_cm,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` + ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount,proto3" json:"result_count,omitempty"` + TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman,proto3" json:"true_scotsman,omitempty"` + Score float32 `protobuf:"fixed32,9,opt,name=score,proto3" json:"score,omitempty"` + Key []uint64 `protobuf:"varint,5,rep,packed,name=key,proto3" json:"key,omitempty"` + ShortKey []int32 `protobuf:"varint,19,rep,packed,name=short_key,json=shortKey,proto3" json:"short_key,omitempty"` + Nested *Nested `protobuf:"bytes,6,opt,name=nested,proto3" json:"nested,omitempty"` + RFunny []Message_Humour `protobuf:"varint,16,rep,packed,name=r_funny,json=rFunny,proto3,enum=proto3_proto.Message_Humour" json:"r_funny,omitempty"` + Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain,proto3" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Proto2Field *test_proto.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field,proto3" json:"proto2_field,omitempty"` + Proto2Value map[string]*test_proto.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value,proto3" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Anything *any.Any `protobuf:"bytes,14,opt,name=anything,proto3" json:"anything,omitempty"` + ManyThings []*any.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings,proto3" json:"many_things,omitempty"` + Submessage *Message `protobuf:"bytes,17,opt,name=submessage,proto3" json:"submessage,omitempty"` + Children []*Message `protobuf:"bytes,18,rep,name=children,proto3" json:"children,omitempty"` + StringMap map[string]string `protobuf:"bytes,20,rep,name=string_map,json=stringMap,proto3" json:"string_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_1c50d9b824d4ac38, []int{0} +} + +func (m *Message) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Message.Unmarshal(m, b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) +} +func (m *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(m, src) +} +func (m *Message) XXX_Size() int { + return xxx_messageInfo_Message.Size(m) +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +func (m *Message) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Message) GetHilarity() Message_Humour { + if m != nil { + return m.Hilarity + } + return Message_UNKNOWN +} + +func (m *Message) GetHeightInCm() uint32 { + if m != nil { + return m.HeightInCm + } + return 0 +} + +func (m *Message) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *Message) GetResultCount() int64 { + if m != nil { + return m.ResultCount + } + return 0 +} + +func (m *Message) GetTrueScotsman() bool { + if m != nil { + return m.TrueScotsman + } + return false +} + +func (m *Message) GetScore() float32 { + if m != nil { + return m.Score + } + return 0 +} + +func (m *Message) GetKey() []uint64 { + if m != nil { + return m.Key + } + return nil +} + +func (m *Message) GetShortKey() []int32 { + if m != nil { + return m.ShortKey + } + return nil +} + +func (m *Message) GetNested() *Nested { + if m != nil { + return m.Nested + } + return nil +} + +func (m *Message) GetRFunny() []Message_Humour { + if m != nil { + return m.RFunny + } + return nil +} + +func (m *Message) GetTerrain() map[string]*Nested { + if m != nil { + return m.Terrain + } + return nil +} + +func (m *Message) GetProto2Field() *test_proto.SubDefaults { + if m != nil { + return m.Proto2Field + } + return nil +} + +func (m *Message) GetProto2Value() map[string]*test_proto.SubDefaults { + if m != nil { + return m.Proto2Value + } + return nil +} + +func (m *Message) GetAnything() *any.Any { + if m != nil { + return m.Anything + } + return nil +} + +func (m *Message) GetManyThings() []*any.Any { + if m != nil { + return m.ManyThings + } + return nil +} + +func (m *Message) GetSubmessage() *Message { + if m != nil { + return m.Submessage + } + return nil +} + +func (m *Message) GetChildren() []*Message { + if m != nil { + return m.Children + } + return nil +} + +func (m *Message) GetStringMap() map[string]string { + if m != nil { + return m.StringMap + } + return nil +} + +type Nested struct { + Bunny string `protobuf:"bytes,1,opt,name=bunny,proto3" json:"bunny,omitempty"` + Cute bool `protobuf:"varint,2,opt,name=cute,proto3" json:"cute,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Nested) Reset() { *m = Nested{} } +func (m *Nested) String() string { return proto.CompactTextString(m) } +func (*Nested) ProtoMessage() {} +func (*Nested) Descriptor() ([]byte, []int) { + return fileDescriptor_1c50d9b824d4ac38, []int{1} +} + +func (m *Nested) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Nested.Unmarshal(m, b) +} +func (m *Nested) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Nested.Marshal(b, m, deterministic) +} +func (m *Nested) XXX_Merge(src proto.Message) { + xxx_messageInfo_Nested.Merge(m, src) +} +func (m *Nested) XXX_Size() int { + return xxx_messageInfo_Nested.Size(m) +} +func (m *Nested) XXX_DiscardUnknown() { + xxx_messageInfo_Nested.DiscardUnknown(m) +} + +var xxx_messageInfo_Nested proto.InternalMessageInfo + +func (m *Nested) GetBunny() string { + if m != nil { + return m.Bunny + } + return "" +} + +func (m *Nested) GetCute() bool { + if m != nil { + return m.Cute + } + return false +} + +type MessageWithMap struct { + ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping,proto3" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } +func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } +func (*MessageWithMap) ProtoMessage() {} +func (*MessageWithMap) Descriptor() ([]byte, []int) { + return fileDescriptor_1c50d9b824d4ac38, []int{2} +} + +func (m *MessageWithMap) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageWithMap.Unmarshal(m, b) +} +func (m *MessageWithMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageWithMap.Marshal(b, m, deterministic) +} +func (m *MessageWithMap) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageWithMap.Merge(m, src) +} +func (m *MessageWithMap) XXX_Size() int { + return xxx_messageInfo_MessageWithMap.Size(m) +} +func (m *MessageWithMap) XXX_DiscardUnknown() { + xxx_messageInfo_MessageWithMap.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageWithMap proto.InternalMessageInfo + +func (m *MessageWithMap) GetByteMapping() map[bool][]byte { + if m != nil { + return m.ByteMapping + } + return nil +} + +type IntMap struct { + Rtt map[int32]int32 `protobuf:"bytes,1,rep,name=rtt,proto3" json:"rtt,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *IntMap) Reset() { *m = IntMap{} } +func (m *IntMap) String() string { return proto.CompactTextString(m) } +func (*IntMap) ProtoMessage() {} +func (*IntMap) Descriptor() ([]byte, []int) { + return fileDescriptor_1c50d9b824d4ac38, []int{3} +} + +func (m *IntMap) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_IntMap.Unmarshal(m, b) +} +func (m *IntMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_IntMap.Marshal(b, m, deterministic) +} +func (m *IntMap) XXX_Merge(src proto.Message) { + xxx_messageInfo_IntMap.Merge(m, src) +} +func (m *IntMap) XXX_Size() int { + return xxx_messageInfo_IntMap.Size(m) +} +func (m *IntMap) XXX_DiscardUnknown() { + xxx_messageInfo_IntMap.DiscardUnknown(m) +} + +var xxx_messageInfo_IntMap proto.InternalMessageInfo + +func (m *IntMap) GetRtt() map[int32]int32 { + if m != nil { + return m.Rtt + } + return nil +} + +type IntMaps struct { + Maps []*IntMap `protobuf:"bytes,1,rep,name=maps,proto3" json:"maps,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *IntMaps) Reset() { *m = IntMaps{} } +func (m *IntMaps) String() string { return proto.CompactTextString(m) } +func (*IntMaps) ProtoMessage() {} +func (*IntMaps) Descriptor() ([]byte, []int) { + return fileDescriptor_1c50d9b824d4ac38, []int{4} +} + +func (m *IntMaps) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_IntMaps.Unmarshal(m, b) +} +func (m *IntMaps) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_IntMaps.Marshal(b, m, deterministic) +} +func (m *IntMaps) XXX_Merge(src proto.Message) { + xxx_messageInfo_IntMaps.Merge(m, src) +} +func (m *IntMaps) XXX_Size() int { + return xxx_messageInfo_IntMaps.Size(m) +} +func (m *IntMaps) XXX_DiscardUnknown() { + xxx_messageInfo_IntMaps.DiscardUnknown(m) +} + +var xxx_messageInfo_IntMaps proto.InternalMessageInfo + +func (m *IntMaps) GetMaps() []*IntMap { + if m != nil { + return m.Maps + } + return nil +} + +type TestUTF8 struct { + Scalar string `protobuf:"bytes,1,opt,name=scalar,proto3" json:"scalar,omitempty"` + Vector []string `protobuf:"bytes,2,rep,name=vector,proto3" json:"vector,omitempty"` + // Types that are valid to be assigned to Oneof: + // *TestUTF8_Field + Oneof isTestUTF8_Oneof `protobuf_oneof:"oneof"` + MapKey map[string]int64 `protobuf:"bytes,4,rep,name=map_key,json=mapKey,proto3" json:"map_key,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + MapValue map[int64]string `protobuf:"bytes,5,rep,name=map_value,json=mapValue,proto3" json:"map_value,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TestUTF8) Reset() { *m = TestUTF8{} } +func (m *TestUTF8) String() string { return proto.CompactTextString(m) } +func (*TestUTF8) ProtoMessage() {} +func (*TestUTF8) Descriptor() ([]byte, []int) { + return fileDescriptor_1c50d9b824d4ac38, []int{5} +} + +func (m *TestUTF8) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TestUTF8.Unmarshal(m, b) +} +func (m *TestUTF8) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TestUTF8.Marshal(b, m, deterministic) +} +func (m *TestUTF8) XXX_Merge(src proto.Message) { + xxx_messageInfo_TestUTF8.Merge(m, src) +} +func (m *TestUTF8) XXX_Size() int { + return xxx_messageInfo_TestUTF8.Size(m) +} +func (m *TestUTF8) XXX_DiscardUnknown() { + xxx_messageInfo_TestUTF8.DiscardUnknown(m) +} + +var xxx_messageInfo_TestUTF8 proto.InternalMessageInfo + +func (m *TestUTF8) GetScalar() string { + if m != nil { + return m.Scalar + } + return "" +} + +func (m *TestUTF8) GetVector() []string { + if m != nil { + return m.Vector + } + return nil +} + +type isTestUTF8_Oneof interface { + isTestUTF8_Oneof() +} + +type TestUTF8_Field struct { + Field string `protobuf:"bytes,3,opt,name=field,proto3,oneof"` +} + +func (*TestUTF8_Field) isTestUTF8_Oneof() {} + +func (m *TestUTF8) GetOneof() isTestUTF8_Oneof { + if m != nil { + return m.Oneof + } + return nil +} + +func (m *TestUTF8) GetField() string { + if x, ok := m.GetOneof().(*TestUTF8_Field); ok { + return x.Field + } + return "" +} + +func (m *TestUTF8) GetMapKey() map[string]int64 { + if m != nil { + return m.MapKey + } + return nil +} + +func (m *TestUTF8) GetMapValue() map[int64]string { + if m != nil { + return m.MapValue + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*TestUTF8) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*TestUTF8_Field)(nil), + } +} + +func init() { + proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value) + proto.RegisterType((*Message)(nil), "proto3_proto.Message") + proto.RegisterMapType((map[string]*test_proto.SubDefaults)(nil), "proto3_proto.Message.Proto2ValueEntry") + proto.RegisterMapType((map[string]string)(nil), "proto3_proto.Message.StringMapEntry") + proto.RegisterMapType((map[string]*Nested)(nil), "proto3_proto.Message.TerrainEntry") + proto.RegisterType((*Nested)(nil), "proto3_proto.Nested") + proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap") + proto.RegisterMapType((map[bool][]byte)(nil), "proto3_proto.MessageWithMap.ByteMappingEntry") + proto.RegisterType((*IntMap)(nil), "proto3_proto.IntMap") + proto.RegisterMapType((map[int32]int32)(nil), "proto3_proto.IntMap.RttEntry") + proto.RegisterType((*IntMaps)(nil), "proto3_proto.IntMaps") + proto.RegisterType((*TestUTF8)(nil), "proto3_proto.TestUTF8") + proto.RegisterMapType((map[string]int64)(nil), "proto3_proto.TestUTF8.MapKeyEntry") + proto.RegisterMapType((map[int64]string)(nil), "proto3_proto.TestUTF8.MapValueEntry") +} + +func init() { proto.RegisterFile("proto3_proto/proto3.proto", fileDescriptor_1c50d9b824d4ac38) } + +var fileDescriptor_1c50d9b824d4ac38 = []byte{ + // 896 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0x6f, 0x6f, 0xdb, 0xb6, + 0x13, 0xae, 0x2c, 0xff, 0x91, 0xcf, 0x76, 0xea, 0x1f, 0x7f, 0x6e, 0xc7, 0x7a, 0x1b, 0xa0, 0x79, + 0xc3, 0x20, 0x0c, 0xab, 0xb2, 0xb9, 0xc8, 0x90, 0xb5, 0xc5, 0x86, 0x24, 0x6b, 0x50, 0x23, 0xb1, + 0x67, 0xd0, 0xce, 0x82, 0xbd, 0x12, 0x68, 0x87, 0xb6, 0x85, 0x59, 0x94, 0x27, 0x52, 0x05, 0xf4, + 0x05, 0xf6, 0x41, 0xf6, 0x95, 0xf6, 0x85, 0x06, 0x92, 0x72, 0x2a, 0x17, 0xea, 0xf2, 0x4a, 0xbc, + 0x47, 0xcf, 0xdd, 0x73, 0xbc, 0x3b, 0x1e, 0x3c, 0xdb, 0x25, 0xb1, 0x8c, 0x5f, 0x04, 0xfa, 0x73, + 0x6c, 0x0c, 0x5f, 0x7f, 0x50, 0xbb, 0xf8, 0xab, 0xff, 0x6c, 0x1d, 0xc7, 0xeb, 0x2d, 0x33, 0x94, + 0x45, 0xba, 0x3a, 0xa6, 0x3c, 0x33, 0xc4, 0xfe, 0x13, 0xc9, 0x84, 0xcc, 0x23, 0xa8, 0xa3, 0x81, + 0x07, 0x7f, 0x35, 0xa1, 0x31, 0x66, 0x42, 0xd0, 0x35, 0x43, 0x08, 0xaa, 0x9c, 0x46, 0x0c, 0x5b, + 0xae, 0xe5, 0x35, 0x89, 0x3e, 0xa3, 0x53, 0x70, 0x36, 0xe1, 0x96, 0x26, 0xa1, 0xcc, 0x70, 0xc5, + 0xb5, 0xbc, 0xa3, 0xe1, 0x67, 0x7e, 0x51, 0xd2, 0xcf, 0x9d, 0xfd, 0xb7, 0x69, 0x14, 0xa7, 0x09, + 0xb9, 0x67, 0x23, 0x17, 0xda, 0x1b, 0x16, 0xae, 0x37, 0x32, 0x08, 0x79, 0xb0, 0x8c, 0xb0, 0xed, + 0x5a, 0x5e, 0x87, 0x80, 0xc1, 0x46, 0xfc, 0x22, 0x52, 0x7a, 0x77, 0x54, 0x52, 0x5c, 0x75, 0x2d, + 0xaf, 0x4d, 0xf4, 0x19, 0x7d, 0x01, 0xed, 0x84, 0x89, 0x74, 0x2b, 0x83, 0x65, 0x9c, 0x72, 0x89, + 0x1b, 0xae, 0xe5, 0xd9, 0xa4, 0x65, 0xb0, 0x0b, 0x05, 0xa1, 0x2f, 0xa1, 0x23, 0x93, 0x94, 0x05, + 0x62, 0x19, 0x4b, 0x11, 0x51, 0x8e, 0x1d, 0xd7, 0xf2, 0x1c, 0xd2, 0x56, 0xe0, 0x2c, 0xc7, 0x50, + 0x0f, 0x6a, 0x62, 0x19, 0x27, 0x0c, 0x37, 0x5d, 0xcb, 0xab, 0x10, 0x63, 0xa0, 0x2e, 0xd8, 0x7f, + 0xb0, 0x0c, 0xd7, 0x5c, 0xdb, 0xab, 0x12, 0x75, 0x44, 0x9f, 0x42, 0x53, 0x6c, 0xe2, 0x44, 0x06, + 0x0a, 0xff, 0xbf, 0x6b, 0x7b, 0x35, 0xe2, 0x68, 0xe0, 0x8a, 0x65, 0xe8, 0x5b, 0xa8, 0x73, 0x26, + 0x24, 0xbb, 0xc3, 0x75, 0xd7, 0xf2, 0x5a, 0xc3, 0xde, 0xe1, 0xd5, 0x27, 0xfa, 0x1f, 0xc9, 0x39, + 0xe8, 0x04, 0x1a, 0x49, 0xb0, 0x4a, 0x39, 0xcf, 0x70, 0xd7, 0xb5, 0x1f, 0xac, 0x54, 0x3d, 0xb9, + 0x54, 0x5c, 0xf4, 0x1a, 0x1a, 0x92, 0x25, 0x09, 0x0d, 0x39, 0x06, 0xd7, 0xf6, 0x5a, 0xc3, 0x41, + 0xb9, 0xdb, 0xdc, 0x90, 0xde, 0x70, 0x99, 0x64, 0x64, 0xef, 0x82, 0x5e, 0x82, 0x99, 0x80, 0x61, + 0xb0, 0x0a, 0xd9, 0xf6, 0x0e, 0xb7, 0x74, 0xa2, 0x9f, 0xf8, 0xef, 0xbb, 0xed, 0xcf, 0xd2, 0xc5, + 0x2f, 0x6c, 0x45, 0xd3, 0xad, 0x14, 0xa4, 0x65, 0xc8, 0x97, 0x8a, 0x8b, 0x46, 0xf7, 0xbe, 0xef, + 0xe8, 0x36, 0x65, 0xb8, 0xa3, 0xe5, 0xbf, 0x2e, 0x97, 0x9f, 0x6a, 0xe6, 0x6f, 0x8a, 0x68, 0x52, + 0xc8, 0x43, 0x69, 0x04, 0x7d, 0x07, 0x0e, 0xe5, 0x99, 0xdc, 0x84, 0x7c, 0x8d, 0x8f, 0xf2, 0x5a, + 0x99, 0x59, 0xf4, 0xf7, 0xb3, 0xe8, 0x9f, 0xf1, 0x8c, 0xdc, 0xb3, 0xd0, 0x09, 0xb4, 0x22, 0xca, + 0xb3, 0x40, 0x5b, 0x02, 0x3f, 0xd6, 0xda, 0xe5, 0x4e, 0xa0, 0x88, 0x73, 0xcd, 0x43, 0x27, 0x00, + 0x22, 0x5d, 0x44, 0x26, 0x29, 0xfc, 0x3f, 0x2d, 0xf5, 0xa4, 0x34, 0x63, 0x52, 0x20, 0xa2, 0xef, + 0xc1, 0x59, 0x6e, 0xc2, 0xed, 0x5d, 0xc2, 0x38, 0x46, 0x5a, 0xea, 0x23, 0x4e, 0xf7, 0x34, 0x74, + 0x01, 0x20, 0x64, 0x12, 0xf2, 0x75, 0x10, 0xd1, 0x1d, 0xee, 0x69, 0xa7, 0xaf, 0xca, 0x6b, 0x33, + 0xd3, 0xbc, 0x31, 0xdd, 0x99, 0xca, 0x34, 0xc5, 0xde, 0xee, 0x4f, 0xa1, 0x5d, 0xec, 0xdb, 0x7e, + 0x00, 0xcd, 0x0b, 0xd3, 0x03, 0xf8, 0x0d, 0xd4, 0x4c, 0xf5, 0x2b, 0xff, 0x31, 0x62, 0x86, 0xf2, + 0xb2, 0x72, 0x6a, 0xf5, 0x6f, 0xa1, 0xfb, 0x61, 0x2b, 0x4a, 0xa2, 0x3e, 0x3f, 0x8c, 0xfa, 0xd1, + 0x79, 0x28, 0x04, 0x7e, 0x0d, 0x47, 0x87, 0xf7, 0x28, 0x09, 0xdb, 0x2b, 0x86, 0x6d, 0x16, 0xbc, + 0x07, 0x3f, 0x43, 0xdd, 0xcc, 0x35, 0x6a, 0x41, 0xe3, 0x66, 0x72, 0x35, 0xf9, 0xf5, 0x76, 0xd2, + 0x7d, 0x84, 0x1c, 0xa8, 0x4e, 0x6f, 0x26, 0xb3, 0xae, 0x85, 0x3a, 0xd0, 0x9c, 0x5d, 0x9f, 0x4d, + 0x67, 0xf3, 0xd1, 0xc5, 0x55, 0xb7, 0x82, 0x1e, 0x43, 0xeb, 0x7c, 0x74, 0x7d, 0x1d, 0x9c, 0x9f, + 0x8d, 0xae, 0xdf, 0xfc, 0xde, 0xb5, 0x07, 0x43, 0xa8, 0x9b, 0xcb, 0x2a, 0x91, 0x85, 0x7e, 0x45, + 0x46, 0xd8, 0x18, 0x6a, 0x59, 0x2c, 0x53, 0x69, 0x94, 0x1d, 0xa2, 0xcf, 0x83, 0xbf, 0x2d, 0x38, + 0xca, 0x7b, 0x70, 0x1b, 0xca, 0xcd, 0x98, 0xee, 0xd0, 0x14, 0xda, 0x8b, 0x4c, 0x32, 0xd5, 0xb3, + 0x9d, 0x1a, 0x46, 0x4b, 0xf7, 0xed, 0x79, 0x69, 0xdf, 0x72, 0x1f, 0xff, 0x3c, 0x93, 0x6c, 0x6c, + 0xf8, 0xf9, 0x68, 0x2f, 0xde, 0x23, 0xfd, 0x9f, 0xa0, 0xfb, 0x21, 0xa1, 0x58, 0x19, 0xa7, 0xa4, + 0x32, 0xed, 0x62, 0x65, 0xfe, 0x84, 0xfa, 0x88, 0x4b, 0x95, 0xdb, 0x31, 0xd8, 0x89, 0x94, 0x79, + 0x4a, 0x9f, 0x1f, 0xa6, 0x64, 0x28, 0x3e, 0x91, 0xd2, 0xa4, 0xa0, 0x98, 0xfd, 0x1f, 0xc0, 0xd9, + 0x03, 0x45, 0xc9, 0x5a, 0x89, 0x64, 0xad, 0x28, 0xf9, 0x02, 0x1a, 0x26, 0x9e, 0x40, 0x1e, 0x54, + 0x23, 0xba, 0x13, 0xb9, 0x68, 0xaf, 0x4c, 0x94, 0x68, 0xc6, 0xe0, 0x9f, 0x0a, 0x38, 0x73, 0x26, + 0xe4, 0xcd, 0xfc, 0xf2, 0x14, 0x3d, 0x85, 0xba, 0x58, 0xd2, 0x2d, 0x4d, 0xf2, 0x26, 0xe4, 0x96, + 0xc2, 0xdf, 0xb1, 0xa5, 0x8c, 0x13, 0x5c, 0x71, 0x6d, 0x85, 0x1b, 0x0b, 0x3d, 0x85, 0x9a, 0xd9, + 0x3f, 0x6a, 0xcb, 0x37, 0xdf, 0x3e, 0x22, 0xc6, 0x44, 0xaf, 0xa0, 0x11, 0xd1, 0x9d, 0x5e, 0xae, + 0xd5, 0xb2, 0xe5, 0xb6, 0x17, 0xf4, 0xc7, 0x74, 0x77, 0xc5, 0x32, 0x73, 0xf7, 0x7a, 0xa4, 0x0d, + 0x74, 0x06, 0x4d, 0xe5, 0x6c, 0x2e, 0x59, 0x2b, 0x7b, 0x80, 0x45, 0xf7, 0xc2, 0x6a, 0x72, 0xa2, + 0xdc, 0xec, 0xff, 0x08, 0xad, 0x42, 0xe4, 0x87, 0x26, 0xda, 0x2e, 0xbe, 0x87, 0x57, 0xd0, 0x39, + 0x88, 0x5a, 0x74, 0xb6, 0x1f, 0x78, 0x0e, 0xe7, 0x0d, 0xa8, 0xc5, 0x9c, 0xc5, 0xab, 0x45, 0xdd, + 0xe4, 0xfb, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xeb, 0x74, 0x17, 0x7f, 0xc3, 0x07, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto new file mode 100644 index 0000000000..6adea22fdc --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto @@ -0,0 +1,97 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2014 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +import "google/protobuf/any.proto"; +import "test_proto/test.proto"; + +package proto3_proto; + +message Message { + enum Humour { + UNKNOWN = 0; + PUNS = 1; + SLAPSTICK = 2; + BILL_BAILEY = 3; + } + + string name = 1; + Humour hilarity = 2; + uint32 height_in_cm = 3; + bytes data = 4; + int64 result_count = 7; + bool true_scotsman = 8; + float score = 9; + + repeated uint64 key = 5; + repeated int32 short_key = 19; + Nested nested = 6; + repeated Humour r_funny = 16; + + map terrain = 10; + test_proto.SubDefaults proto2_field = 11; + map proto2_value = 13; + + google.protobuf.Any anything = 14; + repeated google.protobuf.Any many_things = 15; + + Message submessage = 17; + repeated Message children = 18; + + map string_map = 20; +} + +message Nested { + string bunny = 1; + bool cute = 2; +} + +message MessageWithMap { + map byte_mapping = 1; +} + + +message IntMap { + map rtt = 1; +} + +message IntMaps { + repeated IntMap maps = 1; +} + +message TestUTF8 { + string scalar = 1; + repeated string vector = 2; + oneof oneof { string field = 3; } + map map_key = 4; + map map_value = 5; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go new file mode 100644 index 0000000000..1ded05bbe7 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go @@ -0,0 +1,2887 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/descriptor.proto + +package descriptor + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type FieldDescriptorProto_Type int32 + +const ( + // 0 is reserved for errors. + // Order is weird for historical reasons. + FieldDescriptorProto_TYPE_DOUBLE FieldDescriptorProto_Type = 1 + FieldDescriptorProto_TYPE_FLOAT FieldDescriptorProto_Type = 2 + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + FieldDescriptorProto_TYPE_INT64 FieldDescriptorProto_Type = 3 + FieldDescriptorProto_TYPE_UINT64 FieldDescriptorProto_Type = 4 + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + FieldDescriptorProto_TYPE_INT32 FieldDescriptorProto_Type = 5 + FieldDescriptorProto_TYPE_FIXED64 FieldDescriptorProto_Type = 6 + FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7 + FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8 + FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9 + // Tag-delimited aggregate. + // Group type is deprecated and not supported in proto3. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. + FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10 + FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11 + // New in version 2. + FieldDescriptorProto_TYPE_BYTES FieldDescriptorProto_Type = 12 + FieldDescriptorProto_TYPE_UINT32 FieldDescriptorProto_Type = 13 + FieldDescriptorProto_TYPE_ENUM FieldDescriptorProto_Type = 14 + FieldDescriptorProto_TYPE_SFIXED32 FieldDescriptorProto_Type = 15 + FieldDescriptorProto_TYPE_SFIXED64 FieldDescriptorProto_Type = 16 + FieldDescriptorProto_TYPE_SINT32 FieldDescriptorProto_Type = 17 + FieldDescriptorProto_TYPE_SINT64 FieldDescriptorProto_Type = 18 +) + +var FieldDescriptorProto_Type_name = map[int32]string{ + 1: "TYPE_DOUBLE", + 2: "TYPE_FLOAT", + 3: "TYPE_INT64", + 4: "TYPE_UINT64", + 5: "TYPE_INT32", + 6: "TYPE_FIXED64", + 7: "TYPE_FIXED32", + 8: "TYPE_BOOL", + 9: "TYPE_STRING", + 10: "TYPE_GROUP", + 11: "TYPE_MESSAGE", + 12: "TYPE_BYTES", + 13: "TYPE_UINT32", + 14: "TYPE_ENUM", + 15: "TYPE_SFIXED32", + 16: "TYPE_SFIXED64", + 17: "TYPE_SINT32", + 18: "TYPE_SINT64", +} + +var FieldDescriptorProto_Type_value = map[string]int32{ + "TYPE_DOUBLE": 1, + "TYPE_FLOAT": 2, + "TYPE_INT64": 3, + "TYPE_UINT64": 4, + "TYPE_INT32": 5, + "TYPE_FIXED64": 6, + "TYPE_FIXED32": 7, + "TYPE_BOOL": 8, + "TYPE_STRING": 9, + "TYPE_GROUP": 10, + "TYPE_MESSAGE": 11, + "TYPE_BYTES": 12, + "TYPE_UINT32": 13, + "TYPE_ENUM": 14, + "TYPE_SFIXED32": 15, + "TYPE_SFIXED64": 16, + "TYPE_SINT32": 17, + "TYPE_SINT64": 18, +} + +func (x FieldDescriptorProto_Type) Enum() *FieldDescriptorProto_Type { + p := new(FieldDescriptorProto_Type) + *p = x + return p +} + +func (x FieldDescriptorProto_Type) String() string { + return proto.EnumName(FieldDescriptorProto_Type_name, int32(x)) +} + +func (x *FieldDescriptorProto_Type) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Type_value, data, "FieldDescriptorProto_Type") + if err != nil { + return err + } + *x = FieldDescriptorProto_Type(value) + return nil +} + +func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{4, 0} +} + +type FieldDescriptorProto_Label int32 + +const ( + // 0 is reserved for errors + FieldDescriptorProto_LABEL_OPTIONAL FieldDescriptorProto_Label = 1 + FieldDescriptorProto_LABEL_REQUIRED FieldDescriptorProto_Label = 2 + FieldDescriptorProto_LABEL_REPEATED FieldDescriptorProto_Label = 3 +) + +var FieldDescriptorProto_Label_name = map[int32]string{ + 1: "LABEL_OPTIONAL", + 2: "LABEL_REQUIRED", + 3: "LABEL_REPEATED", +} + +var FieldDescriptorProto_Label_value = map[string]int32{ + "LABEL_OPTIONAL": 1, + "LABEL_REQUIRED": 2, + "LABEL_REPEATED": 3, +} + +func (x FieldDescriptorProto_Label) Enum() *FieldDescriptorProto_Label { + p := new(FieldDescriptorProto_Label) + *p = x + return p +} + +func (x FieldDescriptorProto_Label) String() string { + return proto.EnumName(FieldDescriptorProto_Label_name, int32(x)) +} + +func (x *FieldDescriptorProto_Label) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Label_value, data, "FieldDescriptorProto_Label") + if err != nil { + return err + } + *x = FieldDescriptorProto_Label(value) + return nil +} + +func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{4, 1} +} + +// Generated classes can be optimized for speed or code size. +type FileOptions_OptimizeMode int32 + +const ( + FileOptions_SPEED FileOptions_OptimizeMode = 1 + // etc. + FileOptions_CODE_SIZE FileOptions_OptimizeMode = 2 + FileOptions_LITE_RUNTIME FileOptions_OptimizeMode = 3 +) + +var FileOptions_OptimizeMode_name = map[int32]string{ + 1: "SPEED", + 2: "CODE_SIZE", + 3: "LITE_RUNTIME", +} + +var FileOptions_OptimizeMode_value = map[string]int32{ + "SPEED": 1, + "CODE_SIZE": 2, + "LITE_RUNTIME": 3, +} + +func (x FileOptions_OptimizeMode) Enum() *FileOptions_OptimizeMode { + p := new(FileOptions_OptimizeMode) + *p = x + return p +} + +func (x FileOptions_OptimizeMode) String() string { + return proto.EnumName(FileOptions_OptimizeMode_name, int32(x)) +} + +func (x *FileOptions_OptimizeMode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FileOptions_OptimizeMode_value, data, "FileOptions_OptimizeMode") + if err != nil { + return err + } + *x = FileOptions_OptimizeMode(value) + return nil +} + +func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{10, 0} +} + +type FieldOptions_CType int32 + +const ( + // Default mode. + FieldOptions_STRING FieldOptions_CType = 0 + FieldOptions_CORD FieldOptions_CType = 1 + FieldOptions_STRING_PIECE FieldOptions_CType = 2 +) + +var FieldOptions_CType_name = map[int32]string{ + 0: "STRING", + 1: "CORD", + 2: "STRING_PIECE", +} + +var FieldOptions_CType_value = map[string]int32{ + "STRING": 0, + "CORD": 1, + "STRING_PIECE": 2, +} + +func (x FieldOptions_CType) Enum() *FieldOptions_CType { + p := new(FieldOptions_CType) + *p = x + return p +} + +func (x FieldOptions_CType) String() string { + return proto.EnumName(FieldOptions_CType_name, int32(x)) +} + +func (x *FieldOptions_CType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FieldOptions_CType_value, data, "FieldOptions_CType") + if err != nil { + return err + } + *x = FieldOptions_CType(value) + return nil +} + +func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{12, 0} +} + +type FieldOptions_JSType int32 + +const ( + // Use the default type. + FieldOptions_JS_NORMAL FieldOptions_JSType = 0 + // Use JavaScript strings. + FieldOptions_JS_STRING FieldOptions_JSType = 1 + // Use JavaScript numbers. + FieldOptions_JS_NUMBER FieldOptions_JSType = 2 +) + +var FieldOptions_JSType_name = map[int32]string{ + 0: "JS_NORMAL", + 1: "JS_STRING", + 2: "JS_NUMBER", +} + +var FieldOptions_JSType_value = map[string]int32{ + "JS_NORMAL": 0, + "JS_STRING": 1, + "JS_NUMBER": 2, +} + +func (x FieldOptions_JSType) Enum() *FieldOptions_JSType { + p := new(FieldOptions_JSType) + *p = x + return p +} + +func (x FieldOptions_JSType) String() string { + return proto.EnumName(FieldOptions_JSType_name, int32(x)) +} + +func (x *FieldOptions_JSType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FieldOptions_JSType_value, data, "FieldOptions_JSType") + if err != nil { + return err + } + *x = FieldOptions_JSType(value) + return nil +} + +func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{12, 1} +} + +// Is this method side-effect-free (or safe in HTTP parlance), or idempotent, +// or neither? HTTP based RPC implementation may choose GET verb for safe +// methods, and PUT verb for idempotent methods instead of the default POST. +type MethodOptions_IdempotencyLevel int32 + +const ( + MethodOptions_IDEMPOTENCY_UNKNOWN MethodOptions_IdempotencyLevel = 0 + MethodOptions_NO_SIDE_EFFECTS MethodOptions_IdempotencyLevel = 1 + MethodOptions_IDEMPOTENT MethodOptions_IdempotencyLevel = 2 +) + +var MethodOptions_IdempotencyLevel_name = map[int32]string{ + 0: "IDEMPOTENCY_UNKNOWN", + 1: "NO_SIDE_EFFECTS", + 2: "IDEMPOTENT", +} + +var MethodOptions_IdempotencyLevel_value = map[string]int32{ + "IDEMPOTENCY_UNKNOWN": 0, + "NO_SIDE_EFFECTS": 1, + "IDEMPOTENT": 2, +} + +func (x MethodOptions_IdempotencyLevel) Enum() *MethodOptions_IdempotencyLevel { + p := new(MethodOptions_IdempotencyLevel) + *p = x + return p +} + +func (x MethodOptions_IdempotencyLevel) String() string { + return proto.EnumName(MethodOptions_IdempotencyLevel_name, int32(x)) +} + +func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MethodOptions_IdempotencyLevel_value, data, "MethodOptions_IdempotencyLevel") + if err != nil { + return err + } + *x = MethodOptions_IdempotencyLevel(value) + return nil +} + +func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{17, 0} +} + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +type FileDescriptorSet struct { + File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FileDescriptorSet) Reset() { *m = FileDescriptorSet{} } +func (m *FileDescriptorSet) String() string { return proto.CompactTextString(m) } +func (*FileDescriptorSet) ProtoMessage() {} +func (*FileDescriptorSet) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{0} +} + +func (m *FileDescriptorSet) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FileDescriptorSet.Unmarshal(m, b) +} +func (m *FileDescriptorSet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FileDescriptorSet.Marshal(b, m, deterministic) +} +func (m *FileDescriptorSet) XXX_Merge(src proto.Message) { + xxx_messageInfo_FileDescriptorSet.Merge(m, src) +} +func (m *FileDescriptorSet) XXX_Size() int { + return xxx_messageInfo_FileDescriptorSet.Size(m) +} +func (m *FileDescriptorSet) XXX_DiscardUnknown() { + xxx_messageInfo_FileDescriptorSet.DiscardUnknown(m) +} + +var xxx_messageInfo_FileDescriptorSet proto.InternalMessageInfo + +func (m *FileDescriptorSet) GetFile() []*FileDescriptorProto { + if m != nil { + return m.File + } + return nil +} + +// Describes a complete .proto file. +type FileDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Package *string `protobuf:"bytes,2,opt,name=package" json:"package,omitempty"` + // Names of files imported by this file. + Dependency []string `protobuf:"bytes,3,rep,name=dependency" json:"dependency,omitempty"` + // Indexes of the public imported files in the dependency list above. + PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency,json=publicDependency" json:"public_dependency,omitempty"` + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"` + // All top-level definitions in this file. + MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"` + EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` + Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service" json:"service,omitempty"` + Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension" json:"extension,omitempty"` + Options *FileOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"` + // The syntax of the proto file. + // The supported values are "proto2" and "proto3". + Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FileDescriptorProto) Reset() { *m = FileDescriptorProto{} } +func (m *FileDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*FileDescriptorProto) ProtoMessage() {} +func (*FileDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{1} +} + +func (m *FileDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FileDescriptorProto.Unmarshal(m, b) +} +func (m *FileDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FileDescriptorProto.Marshal(b, m, deterministic) +} +func (m *FileDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_FileDescriptorProto.Merge(m, src) +} +func (m *FileDescriptorProto) XXX_Size() int { + return xxx_messageInfo_FileDescriptorProto.Size(m) +} +func (m *FileDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_FileDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_FileDescriptorProto proto.InternalMessageInfo + +func (m *FileDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FileDescriptorProto) GetPackage() string { + if m != nil && m.Package != nil { + return *m.Package + } + return "" +} + +func (m *FileDescriptorProto) GetDependency() []string { + if m != nil { + return m.Dependency + } + return nil +} + +func (m *FileDescriptorProto) GetPublicDependency() []int32 { + if m != nil { + return m.PublicDependency + } + return nil +} + +func (m *FileDescriptorProto) GetWeakDependency() []int32 { + if m != nil { + return m.WeakDependency + } + return nil +} + +func (m *FileDescriptorProto) GetMessageType() []*DescriptorProto { + if m != nil { + return m.MessageType + } + return nil +} + +func (m *FileDescriptorProto) GetEnumType() []*EnumDescriptorProto { + if m != nil { + return m.EnumType + } + return nil +} + +func (m *FileDescriptorProto) GetService() []*ServiceDescriptorProto { + if m != nil { + return m.Service + } + return nil +} + +func (m *FileDescriptorProto) GetExtension() []*FieldDescriptorProto { + if m != nil { + return m.Extension + } + return nil +} + +func (m *FileDescriptorProto) GetOptions() *FileOptions { + if m != nil { + return m.Options + } + return nil +} + +func (m *FileDescriptorProto) GetSourceCodeInfo() *SourceCodeInfo { + if m != nil { + return m.SourceCodeInfo + } + return nil +} + +func (m *FileDescriptorProto) GetSyntax() string { + if m != nil && m.Syntax != nil { + return *m.Syntax + } + return "" +} + +// Describes a message type. +type DescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field" json:"field,omitempty"` + Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension" json:"extension,omitempty"` + NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type,json=nestedType" json:"nested_type,omitempty"` + EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` + ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range,json=extensionRange" json:"extension_range,omitempty"` + OneofDecl []*OneofDescriptorProto `protobuf:"bytes,8,rep,name=oneof_decl,json=oneofDecl" json:"oneof_decl,omitempty"` + Options *MessageOptions `protobuf:"bytes,7,opt,name=options" json:"options,omitempty"` + ReservedRange []*DescriptorProto_ReservedRange `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DescriptorProto) Reset() { *m = DescriptorProto{} } +func (m *DescriptorProto) String() string { return proto.CompactTextString(m) } +func (*DescriptorProto) ProtoMessage() {} +func (*DescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{2} +} + +func (m *DescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DescriptorProto.Unmarshal(m, b) +} +func (m *DescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DescriptorProto.Marshal(b, m, deterministic) +} +func (m *DescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_DescriptorProto.Merge(m, src) +} +func (m *DescriptorProto) XXX_Size() int { + return xxx_messageInfo_DescriptorProto.Size(m) +} +func (m *DescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_DescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_DescriptorProto proto.InternalMessageInfo + +func (m *DescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *DescriptorProto) GetField() []*FieldDescriptorProto { + if m != nil { + return m.Field + } + return nil +} + +func (m *DescriptorProto) GetExtension() []*FieldDescriptorProto { + if m != nil { + return m.Extension + } + return nil +} + +func (m *DescriptorProto) GetNestedType() []*DescriptorProto { + if m != nil { + return m.NestedType + } + return nil +} + +func (m *DescriptorProto) GetEnumType() []*EnumDescriptorProto { + if m != nil { + return m.EnumType + } + return nil +} + +func (m *DescriptorProto) GetExtensionRange() []*DescriptorProto_ExtensionRange { + if m != nil { + return m.ExtensionRange + } + return nil +} + +func (m *DescriptorProto) GetOneofDecl() []*OneofDescriptorProto { + if m != nil { + return m.OneofDecl + } + return nil +} + +func (m *DescriptorProto) GetOptions() *MessageOptions { + if m != nil { + return m.Options + } + return nil +} + +func (m *DescriptorProto) GetReservedRange() []*DescriptorProto_ReservedRange { + if m != nil { + return m.ReservedRange + } + return nil +} + +func (m *DescriptorProto) GetReservedName() []string { + if m != nil { + return m.ReservedName + } + return nil +} + +type DescriptorProto_ExtensionRange struct { + Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` + Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DescriptorProto_ExtensionRange) Reset() { *m = DescriptorProto_ExtensionRange{} } +func (m *DescriptorProto_ExtensionRange) String() string { return proto.CompactTextString(m) } +func (*DescriptorProto_ExtensionRange) ProtoMessage() {} +func (*DescriptorProto_ExtensionRange) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{2, 0} +} + +func (m *DescriptorProto_ExtensionRange) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DescriptorProto_ExtensionRange.Unmarshal(m, b) +} +func (m *DescriptorProto_ExtensionRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DescriptorProto_ExtensionRange.Marshal(b, m, deterministic) +} +func (m *DescriptorProto_ExtensionRange) XXX_Merge(src proto.Message) { + xxx_messageInfo_DescriptorProto_ExtensionRange.Merge(m, src) +} +func (m *DescriptorProto_ExtensionRange) XXX_Size() int { + return xxx_messageInfo_DescriptorProto_ExtensionRange.Size(m) +} +func (m *DescriptorProto_ExtensionRange) XXX_DiscardUnknown() { + xxx_messageInfo_DescriptorProto_ExtensionRange.DiscardUnknown(m) +} + +var xxx_messageInfo_DescriptorProto_ExtensionRange proto.InternalMessageInfo + +func (m *DescriptorProto_ExtensionRange) GetStart() int32 { + if m != nil && m.Start != nil { + return *m.Start + } + return 0 +} + +func (m *DescriptorProto_ExtensionRange) GetEnd() int32 { + if m != nil && m.End != nil { + return *m.End + } + return 0 +} + +func (m *DescriptorProto_ExtensionRange) GetOptions() *ExtensionRangeOptions { + if m != nil { + return m.Options + } + return nil +} + +// Range of reserved tag numbers. Reserved tag numbers may not be used by +// fields or extension ranges in the same message. Reserved ranges may +// not overlap. +type DescriptorProto_ReservedRange struct { + Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DescriptorProto_ReservedRange) Reset() { *m = DescriptorProto_ReservedRange{} } +func (m *DescriptorProto_ReservedRange) String() string { return proto.CompactTextString(m) } +func (*DescriptorProto_ReservedRange) ProtoMessage() {} +func (*DescriptorProto_ReservedRange) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{2, 1} +} + +func (m *DescriptorProto_ReservedRange) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DescriptorProto_ReservedRange.Unmarshal(m, b) +} +func (m *DescriptorProto_ReservedRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DescriptorProto_ReservedRange.Marshal(b, m, deterministic) +} +func (m *DescriptorProto_ReservedRange) XXX_Merge(src proto.Message) { + xxx_messageInfo_DescriptorProto_ReservedRange.Merge(m, src) +} +func (m *DescriptorProto_ReservedRange) XXX_Size() int { + return xxx_messageInfo_DescriptorProto_ReservedRange.Size(m) +} +func (m *DescriptorProto_ReservedRange) XXX_DiscardUnknown() { + xxx_messageInfo_DescriptorProto_ReservedRange.DiscardUnknown(m) +} + +var xxx_messageInfo_DescriptorProto_ReservedRange proto.InternalMessageInfo + +func (m *DescriptorProto_ReservedRange) GetStart() int32 { + if m != nil && m.Start != nil { + return *m.Start + } + return 0 +} + +func (m *DescriptorProto_ReservedRange) GetEnd() int32 { + if m != nil && m.End != nil { + return *m.End + } + return 0 +} + +type ExtensionRangeOptions struct { + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ExtensionRangeOptions) Reset() { *m = ExtensionRangeOptions{} } +func (m *ExtensionRangeOptions) String() string { return proto.CompactTextString(m) } +func (*ExtensionRangeOptions) ProtoMessage() {} +func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{3} +} + +var extRange_ExtensionRangeOptions = []proto.ExtensionRange{ + {Start: 1000, End: 536870911}, +} + +func (*ExtensionRangeOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_ExtensionRangeOptions +} + +func (m *ExtensionRangeOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ExtensionRangeOptions.Unmarshal(m, b) +} +func (m *ExtensionRangeOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ExtensionRangeOptions.Marshal(b, m, deterministic) +} +func (m *ExtensionRangeOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtensionRangeOptions.Merge(m, src) +} +func (m *ExtensionRangeOptions) XXX_Size() int { + return xxx_messageInfo_ExtensionRangeOptions.Size(m) +} +func (m *ExtensionRangeOptions) XXX_DiscardUnknown() { + xxx_messageInfo_ExtensionRangeOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtensionRangeOptions proto.InternalMessageInfo + +func (m *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +// Describes a field within a message. +type FieldDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Number *int32 `protobuf:"varint,3,opt,name=number" json:"number,omitempty"` + Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google.protobuf.FieldDescriptorProto_Label" json:"label,omitempty"` + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google.protobuf.FieldDescriptorProto_Type" json:"type,omitempty"` + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + TypeName *string `protobuf:"bytes,6,opt,name=type_name,json=typeName" json:"type_name,omitempty"` + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + Extendee *string `protobuf:"bytes,2,opt,name=extendee" json:"extendee,omitempty"` + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + DefaultValue *string `protobuf:"bytes,7,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"` + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + OneofIndex *int32 `protobuf:"varint,9,opt,name=oneof_index,json=oneofIndex" json:"oneof_index,omitempty"` + // JSON name of this field. The value is set by protocol compiler. If the + // user has set a "json_name" option on this field, that option's value + // will be used. Otherwise, it's deduced from the field's name by converting + // it to camelCase. + JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"` + Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} } +func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*FieldDescriptorProto) ProtoMessage() {} +func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{4} +} + +func (m *FieldDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FieldDescriptorProto.Unmarshal(m, b) +} +func (m *FieldDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FieldDescriptorProto.Marshal(b, m, deterministic) +} +func (m *FieldDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_FieldDescriptorProto.Merge(m, src) +} +func (m *FieldDescriptorProto) XXX_Size() int { + return xxx_messageInfo_FieldDescriptorProto.Size(m) +} +func (m *FieldDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_FieldDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_FieldDescriptorProto proto.InternalMessageInfo + +func (m *FieldDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FieldDescriptorProto) GetNumber() int32 { + if m != nil && m.Number != nil { + return *m.Number + } + return 0 +} + +func (m *FieldDescriptorProto) GetLabel() FieldDescriptorProto_Label { + if m != nil && m.Label != nil { + return *m.Label + } + return FieldDescriptorProto_LABEL_OPTIONAL +} + +func (m *FieldDescriptorProto) GetType() FieldDescriptorProto_Type { + if m != nil && m.Type != nil { + return *m.Type + } + return FieldDescriptorProto_TYPE_DOUBLE +} + +func (m *FieldDescriptorProto) GetTypeName() string { + if m != nil && m.TypeName != nil { + return *m.TypeName + } + return "" +} + +func (m *FieldDescriptorProto) GetExtendee() string { + if m != nil && m.Extendee != nil { + return *m.Extendee + } + return "" +} + +func (m *FieldDescriptorProto) GetDefaultValue() string { + if m != nil && m.DefaultValue != nil { + return *m.DefaultValue + } + return "" +} + +func (m *FieldDescriptorProto) GetOneofIndex() int32 { + if m != nil && m.OneofIndex != nil { + return *m.OneofIndex + } + return 0 +} + +func (m *FieldDescriptorProto) GetJsonName() string { + if m != nil && m.JsonName != nil { + return *m.JsonName + } + return "" +} + +func (m *FieldDescriptorProto) GetOptions() *FieldOptions { + if m != nil { + return m.Options + } + return nil +} + +// Describes a oneof. +type OneofDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Options *OneofOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} } +func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*OneofDescriptorProto) ProtoMessage() {} +func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{5} +} + +func (m *OneofDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OneofDescriptorProto.Unmarshal(m, b) +} +func (m *OneofDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OneofDescriptorProto.Marshal(b, m, deterministic) +} +func (m *OneofDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_OneofDescriptorProto.Merge(m, src) +} +func (m *OneofDescriptorProto) XXX_Size() int { + return xxx_messageInfo_OneofDescriptorProto.Size(m) +} +func (m *OneofDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_OneofDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_OneofDescriptorProto proto.InternalMessageInfo + +func (m *OneofDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *OneofDescriptorProto) GetOptions() *OneofOptions { + if m != nil { + return m.Options + } + return nil +} + +// Describes an enum type. +type EnumDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` + Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} } +func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*EnumDescriptorProto) ProtoMessage() {} +func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{6} +} + +func (m *EnumDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumDescriptorProto.Unmarshal(m, b) +} +func (m *EnumDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumDescriptorProto.Marshal(b, m, deterministic) +} +func (m *EnumDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumDescriptorProto.Merge(m, src) +} +func (m *EnumDescriptorProto) XXX_Size() int { + return xxx_messageInfo_EnumDescriptorProto.Size(m) +} +func (m *EnumDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_EnumDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumDescriptorProto proto.InternalMessageInfo + +func (m *EnumDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *EnumDescriptorProto) GetValue() []*EnumValueDescriptorProto { + if m != nil { + return m.Value + } + return nil +} + +func (m *EnumDescriptorProto) GetOptions() *EnumOptions { + if m != nil { + return m.Options + } + return nil +} + +func (m *EnumDescriptorProto) GetReservedRange() []*EnumDescriptorProto_EnumReservedRange { + if m != nil { + return m.ReservedRange + } + return nil +} + +func (m *EnumDescriptorProto) GetReservedName() []string { + if m != nil { + return m.ReservedName + } + return nil +} + +// Range of reserved numeric values. Reserved values may not be used by +// entries in the same enum. Reserved ranges may not overlap. +// +// Note that this is distinct from DescriptorProto.ReservedRange in that it +// is inclusive such that it can appropriately represent the entire int32 +// domain. +type EnumDescriptorProto_EnumReservedRange struct { + Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EnumDescriptorProto_EnumReservedRange) Reset() { *m = EnumDescriptorProto_EnumReservedRange{} } +func (m *EnumDescriptorProto_EnumReservedRange) String() string { return proto.CompactTextString(m) } +func (*EnumDescriptorProto_EnumReservedRange) ProtoMessage() {} +func (*EnumDescriptorProto_EnumReservedRange) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{6, 0} +} + +func (m *EnumDescriptorProto_EnumReservedRange) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.Unmarshal(m, b) +} +func (m *EnumDescriptorProto_EnumReservedRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.Marshal(b, m, deterministic) +} +func (m *EnumDescriptorProto_EnumReservedRange) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.Merge(m, src) +} +func (m *EnumDescriptorProto_EnumReservedRange) XXX_Size() int { + return xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.Size(m) +} +func (m *EnumDescriptorProto_EnumReservedRange) XXX_DiscardUnknown() { + xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumDescriptorProto_EnumReservedRange proto.InternalMessageInfo + +func (m *EnumDescriptorProto_EnumReservedRange) GetStart() int32 { + if m != nil && m.Start != nil { + return *m.Start + } + return 0 +} + +func (m *EnumDescriptorProto_EnumReservedRange) GetEnd() int32 { + if m != nil && m.End != nil { + return *m.End + } + return 0 +} + +// Describes a value within an enum. +type EnumValueDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"` + Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} } +func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*EnumValueDescriptorProto) ProtoMessage() {} +func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{7} +} + +func (m *EnumValueDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumValueDescriptorProto.Unmarshal(m, b) +} +func (m *EnumValueDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumValueDescriptorProto.Marshal(b, m, deterministic) +} +func (m *EnumValueDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumValueDescriptorProto.Merge(m, src) +} +func (m *EnumValueDescriptorProto) XXX_Size() int { + return xxx_messageInfo_EnumValueDescriptorProto.Size(m) +} +func (m *EnumValueDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_EnumValueDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumValueDescriptorProto proto.InternalMessageInfo + +func (m *EnumValueDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *EnumValueDescriptorProto) GetNumber() int32 { + if m != nil && m.Number != nil { + return *m.Number + } + return 0 +} + +func (m *EnumValueDescriptorProto) GetOptions() *EnumValueOptions { + if m != nil { + return m.Options + } + return nil +} + +// Describes a service. +type ServiceDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"` + Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} } +func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*ServiceDescriptorProto) ProtoMessage() {} +func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{8} +} + +func (m *ServiceDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ServiceDescriptorProto.Unmarshal(m, b) +} +func (m *ServiceDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ServiceDescriptorProto.Marshal(b, m, deterministic) +} +func (m *ServiceDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_ServiceDescriptorProto.Merge(m, src) +} +func (m *ServiceDescriptorProto) XXX_Size() int { + return xxx_messageInfo_ServiceDescriptorProto.Size(m) +} +func (m *ServiceDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_ServiceDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_ServiceDescriptorProto proto.InternalMessageInfo + +func (m *ServiceDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *ServiceDescriptorProto) GetMethod() []*MethodDescriptorProto { + if m != nil { + return m.Method + } + return nil +} + +func (m *ServiceDescriptorProto) GetOptions() *ServiceOptions { + if m != nil { + return m.Options + } + return nil +} + +// Describes a method of a service. +type MethodDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + InputType *string `protobuf:"bytes,2,opt,name=input_type,json=inputType" json:"input_type,omitempty"` + OutputType *string `protobuf:"bytes,3,opt,name=output_type,json=outputType" json:"output_type,omitempty"` + Options *MethodOptions `protobuf:"bytes,4,opt,name=options" json:"options,omitempty"` + // Identifies if client streams multiple client messages + ClientStreaming *bool `protobuf:"varint,5,opt,name=client_streaming,json=clientStreaming,def=0" json:"client_streaming,omitempty"` + // Identifies if server streams multiple server messages + ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} } +func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*MethodDescriptorProto) ProtoMessage() {} +func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{9} +} + +func (m *MethodDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MethodDescriptorProto.Unmarshal(m, b) +} +func (m *MethodDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MethodDescriptorProto.Marshal(b, m, deterministic) +} +func (m *MethodDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_MethodDescriptorProto.Merge(m, src) +} +func (m *MethodDescriptorProto) XXX_Size() int { + return xxx_messageInfo_MethodDescriptorProto.Size(m) +} +func (m *MethodDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_MethodDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_MethodDescriptorProto proto.InternalMessageInfo + +const Default_MethodDescriptorProto_ClientStreaming bool = false +const Default_MethodDescriptorProto_ServerStreaming bool = false + +func (m *MethodDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *MethodDescriptorProto) GetInputType() string { + if m != nil && m.InputType != nil { + return *m.InputType + } + return "" +} + +func (m *MethodDescriptorProto) GetOutputType() string { + if m != nil && m.OutputType != nil { + return *m.OutputType + } + return "" +} + +func (m *MethodDescriptorProto) GetOptions() *MethodOptions { + if m != nil { + return m.Options + } + return nil +} + +func (m *MethodDescriptorProto) GetClientStreaming() bool { + if m != nil && m.ClientStreaming != nil { + return *m.ClientStreaming + } + return Default_MethodDescriptorProto_ClientStreaming +} + +func (m *MethodDescriptorProto) GetServerStreaming() bool { + if m != nil && m.ServerStreaming != nil { + return *m.ServerStreaming + } + return Default_MethodDescriptorProto_ServerStreaming +} + +type FileOptions struct { + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + JavaPackage *string `protobuf:"bytes,1,opt,name=java_package,json=javaPackage" json:"java_package,omitempty"` + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname,json=javaOuterClassname" json:"java_outer_classname,omitempty"` + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"` + // This option does nothing. + JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"` // Deprecated: Do not use. + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + JavaStringCheckUtf8 *bool `protobuf:"varint,27,opt,name=java_string_check_utf8,json=javaStringCheckUtf8,def=0" json:"java_string_check_utf8,omitempty"` + OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,json=optimizeFor,enum=google.protobuf.FileOptions_OptimizeMode,def=1" json:"optimize_for,omitempty"` + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + GoPackage *string `protobuf:"bytes,11,opt,name=go_package,json=goPackage" json:"go_package,omitempty"` + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"` + JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"` + PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"` + PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"` + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + Deprecated *bool `protobuf:"varint,23,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + CcEnableArenas *bool `protobuf:"varint,31,opt,name=cc_enable_arenas,json=ccEnableArenas,def=0" json:"cc_enable_arenas,omitempty"` + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"` + // Namespace for generated classes; defaults to the package. + CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"` + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + SwiftPrefix *string `protobuf:"bytes,39,opt,name=swift_prefix,json=swiftPrefix" json:"swift_prefix,omitempty"` + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + PhpClassPrefix *string `protobuf:"bytes,40,opt,name=php_class_prefix,json=phpClassPrefix" json:"php_class_prefix,omitempty"` + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + PhpNamespace *string `protobuf:"bytes,41,opt,name=php_namespace,json=phpNamespace" json:"php_namespace,omitempty"` + // Use this option to change the namespace of php generated metadata classes. + // Default is empty. When this option is empty, the proto file name will be used + // for determining the namespace. + PhpMetadataNamespace *string `protobuf:"bytes,44,opt,name=php_metadata_namespace,json=phpMetadataNamespace" json:"php_metadata_namespace,omitempty"` + // Use this option to change the package of ruby generated classes. Default + // is empty. When this option is not set, the package name will be used for + // determining the ruby package. + RubyPackage *string `protobuf:"bytes,45,opt,name=ruby_package,json=rubyPackage" json:"ruby_package,omitempty"` + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FileOptions) Reset() { *m = FileOptions{} } +func (m *FileOptions) String() string { return proto.CompactTextString(m) } +func (*FileOptions) ProtoMessage() {} +func (*FileOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{10} +} + +var extRange_FileOptions = []proto.ExtensionRange{ + {Start: 1000, End: 536870911}, +} + +func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_FileOptions +} + +func (m *FileOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FileOptions.Unmarshal(m, b) +} +func (m *FileOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FileOptions.Marshal(b, m, deterministic) +} +func (m *FileOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_FileOptions.Merge(m, src) +} +func (m *FileOptions) XXX_Size() int { + return xxx_messageInfo_FileOptions.Size(m) +} +func (m *FileOptions) XXX_DiscardUnknown() { + xxx_messageInfo_FileOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_FileOptions proto.InternalMessageInfo + +const Default_FileOptions_JavaMultipleFiles bool = false +const Default_FileOptions_JavaStringCheckUtf8 bool = false +const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED +const Default_FileOptions_CcGenericServices bool = false +const Default_FileOptions_JavaGenericServices bool = false +const Default_FileOptions_PyGenericServices bool = false +const Default_FileOptions_PhpGenericServices bool = false +const Default_FileOptions_Deprecated bool = false +const Default_FileOptions_CcEnableArenas bool = false + +func (m *FileOptions) GetJavaPackage() string { + if m != nil && m.JavaPackage != nil { + return *m.JavaPackage + } + return "" +} + +func (m *FileOptions) GetJavaOuterClassname() string { + if m != nil && m.JavaOuterClassname != nil { + return *m.JavaOuterClassname + } + return "" +} + +func (m *FileOptions) GetJavaMultipleFiles() bool { + if m != nil && m.JavaMultipleFiles != nil { + return *m.JavaMultipleFiles + } + return Default_FileOptions_JavaMultipleFiles +} + +// Deprecated: Do not use. +func (m *FileOptions) GetJavaGenerateEqualsAndHash() bool { + if m != nil && m.JavaGenerateEqualsAndHash != nil { + return *m.JavaGenerateEqualsAndHash + } + return false +} + +func (m *FileOptions) GetJavaStringCheckUtf8() bool { + if m != nil && m.JavaStringCheckUtf8 != nil { + return *m.JavaStringCheckUtf8 + } + return Default_FileOptions_JavaStringCheckUtf8 +} + +func (m *FileOptions) GetOptimizeFor() FileOptions_OptimizeMode { + if m != nil && m.OptimizeFor != nil { + return *m.OptimizeFor + } + return Default_FileOptions_OptimizeFor +} + +func (m *FileOptions) GetGoPackage() string { + if m != nil && m.GoPackage != nil { + return *m.GoPackage + } + return "" +} + +func (m *FileOptions) GetCcGenericServices() bool { + if m != nil && m.CcGenericServices != nil { + return *m.CcGenericServices + } + return Default_FileOptions_CcGenericServices +} + +func (m *FileOptions) GetJavaGenericServices() bool { + if m != nil && m.JavaGenericServices != nil { + return *m.JavaGenericServices + } + return Default_FileOptions_JavaGenericServices +} + +func (m *FileOptions) GetPyGenericServices() bool { + if m != nil && m.PyGenericServices != nil { + return *m.PyGenericServices + } + return Default_FileOptions_PyGenericServices +} + +func (m *FileOptions) GetPhpGenericServices() bool { + if m != nil && m.PhpGenericServices != nil { + return *m.PhpGenericServices + } + return Default_FileOptions_PhpGenericServices +} + +func (m *FileOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_FileOptions_Deprecated +} + +func (m *FileOptions) GetCcEnableArenas() bool { + if m != nil && m.CcEnableArenas != nil { + return *m.CcEnableArenas + } + return Default_FileOptions_CcEnableArenas +} + +func (m *FileOptions) GetObjcClassPrefix() string { + if m != nil && m.ObjcClassPrefix != nil { + return *m.ObjcClassPrefix + } + return "" +} + +func (m *FileOptions) GetCsharpNamespace() string { + if m != nil && m.CsharpNamespace != nil { + return *m.CsharpNamespace + } + return "" +} + +func (m *FileOptions) GetSwiftPrefix() string { + if m != nil && m.SwiftPrefix != nil { + return *m.SwiftPrefix + } + return "" +} + +func (m *FileOptions) GetPhpClassPrefix() string { + if m != nil && m.PhpClassPrefix != nil { + return *m.PhpClassPrefix + } + return "" +} + +func (m *FileOptions) GetPhpNamespace() string { + if m != nil && m.PhpNamespace != nil { + return *m.PhpNamespace + } + return "" +} + +func (m *FileOptions) GetPhpMetadataNamespace() string { + if m != nil && m.PhpMetadataNamespace != nil { + return *m.PhpMetadataNamespace + } + return "" +} + +func (m *FileOptions) GetRubyPackage() string { + if m != nil && m.RubyPackage != nil { + return *m.RubyPackage + } + return "" +} + +func (m *FileOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type MessageOptions struct { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,json=messageSetWireFormat,def=0" json:"message_set_wire_format,omitempty"` + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,json=noStandardDescriptorAccessor,def=0" json:"no_standard_descriptor_accessor,omitempty"` + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementions still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MessageOptions) Reset() { *m = MessageOptions{} } +func (m *MessageOptions) String() string { return proto.CompactTextString(m) } +func (*MessageOptions) ProtoMessage() {} +func (*MessageOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{11} +} + +var extRange_MessageOptions = []proto.ExtensionRange{ + {Start: 1000, End: 536870911}, +} + +func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_MessageOptions +} + +func (m *MessageOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageOptions.Unmarshal(m, b) +} +func (m *MessageOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageOptions.Marshal(b, m, deterministic) +} +func (m *MessageOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageOptions.Merge(m, src) +} +func (m *MessageOptions) XXX_Size() int { + return xxx_messageInfo_MessageOptions.Size(m) +} +func (m *MessageOptions) XXX_DiscardUnknown() { + xxx_messageInfo_MessageOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageOptions proto.InternalMessageInfo + +const Default_MessageOptions_MessageSetWireFormat bool = false +const Default_MessageOptions_NoStandardDescriptorAccessor bool = false +const Default_MessageOptions_Deprecated bool = false + +func (m *MessageOptions) GetMessageSetWireFormat() bool { + if m != nil && m.MessageSetWireFormat != nil { + return *m.MessageSetWireFormat + } + return Default_MessageOptions_MessageSetWireFormat +} + +func (m *MessageOptions) GetNoStandardDescriptorAccessor() bool { + if m != nil && m.NoStandardDescriptorAccessor != nil { + return *m.NoStandardDescriptorAccessor + } + return Default_MessageOptions_NoStandardDescriptorAccessor +} + +func (m *MessageOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_MessageOptions_Deprecated +} + +func (m *MessageOptions) GetMapEntry() bool { + if m != nil && m.MapEntry != nil { + return *m.MapEntry + } + return false +} + +func (m *MessageOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type FieldOptions struct { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google.protobuf.FieldOptions_CType,def=0" json:"ctype,omitempty"` + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. + Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"` + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. + Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"` + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outer message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"` + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // For Google-internal migration only. Do not use. + Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FieldOptions) Reset() { *m = FieldOptions{} } +func (m *FieldOptions) String() string { return proto.CompactTextString(m) } +func (*FieldOptions) ProtoMessage() {} +func (*FieldOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{12} +} + +var extRange_FieldOptions = []proto.ExtensionRange{ + {Start: 1000, End: 536870911}, +} + +func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_FieldOptions +} + +func (m *FieldOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FieldOptions.Unmarshal(m, b) +} +func (m *FieldOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FieldOptions.Marshal(b, m, deterministic) +} +func (m *FieldOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_FieldOptions.Merge(m, src) +} +func (m *FieldOptions) XXX_Size() int { + return xxx_messageInfo_FieldOptions.Size(m) +} +func (m *FieldOptions) XXX_DiscardUnknown() { + xxx_messageInfo_FieldOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_FieldOptions proto.InternalMessageInfo + +const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING +const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL +const Default_FieldOptions_Lazy bool = false +const Default_FieldOptions_Deprecated bool = false +const Default_FieldOptions_Weak bool = false + +func (m *FieldOptions) GetCtype() FieldOptions_CType { + if m != nil && m.Ctype != nil { + return *m.Ctype + } + return Default_FieldOptions_Ctype +} + +func (m *FieldOptions) GetPacked() bool { + if m != nil && m.Packed != nil { + return *m.Packed + } + return false +} + +func (m *FieldOptions) GetJstype() FieldOptions_JSType { + if m != nil && m.Jstype != nil { + return *m.Jstype + } + return Default_FieldOptions_Jstype +} + +func (m *FieldOptions) GetLazy() bool { + if m != nil && m.Lazy != nil { + return *m.Lazy + } + return Default_FieldOptions_Lazy +} + +func (m *FieldOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_FieldOptions_Deprecated +} + +func (m *FieldOptions) GetWeak() bool { + if m != nil && m.Weak != nil { + return *m.Weak + } + return Default_FieldOptions_Weak +} + +func (m *FieldOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type OneofOptions struct { + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OneofOptions) Reset() { *m = OneofOptions{} } +func (m *OneofOptions) String() string { return proto.CompactTextString(m) } +func (*OneofOptions) ProtoMessage() {} +func (*OneofOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{13} +} + +var extRange_OneofOptions = []proto.ExtensionRange{ + {Start: 1000, End: 536870911}, +} + +func (*OneofOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_OneofOptions +} + +func (m *OneofOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OneofOptions.Unmarshal(m, b) +} +func (m *OneofOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OneofOptions.Marshal(b, m, deterministic) +} +func (m *OneofOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_OneofOptions.Merge(m, src) +} +func (m *OneofOptions) XXX_Size() int { + return xxx_messageInfo_OneofOptions.Size(m) +} +func (m *OneofOptions) XXX_DiscardUnknown() { + xxx_messageInfo_OneofOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_OneofOptions proto.InternalMessageInfo + +func (m *OneofOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type EnumOptions struct { + // Set this option to true to allow mapping different tag names to the same + // value. + AllowAlias *bool `protobuf:"varint,2,opt,name=allow_alias,json=allowAlias" json:"allow_alias,omitempty"` + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EnumOptions) Reset() { *m = EnumOptions{} } +func (m *EnumOptions) String() string { return proto.CompactTextString(m) } +func (*EnumOptions) ProtoMessage() {} +func (*EnumOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{14} +} + +var extRange_EnumOptions = []proto.ExtensionRange{ + {Start: 1000, End: 536870911}, +} + +func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_EnumOptions +} + +func (m *EnumOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumOptions.Unmarshal(m, b) +} +func (m *EnumOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumOptions.Marshal(b, m, deterministic) +} +func (m *EnumOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumOptions.Merge(m, src) +} +func (m *EnumOptions) XXX_Size() int { + return xxx_messageInfo_EnumOptions.Size(m) +} +func (m *EnumOptions) XXX_DiscardUnknown() { + xxx_messageInfo_EnumOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumOptions proto.InternalMessageInfo + +const Default_EnumOptions_Deprecated bool = false + +func (m *EnumOptions) GetAllowAlias() bool { + if m != nil && m.AllowAlias != nil { + return *m.AllowAlias + } + return false +} + +func (m *EnumOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_EnumOptions_Deprecated +} + +func (m *EnumOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type EnumValueOptions struct { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} } +func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) } +func (*EnumValueOptions) ProtoMessage() {} +func (*EnumValueOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{15} +} + +var extRange_EnumValueOptions = []proto.ExtensionRange{ + {Start: 1000, End: 536870911}, +} + +func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_EnumValueOptions +} + +func (m *EnumValueOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumValueOptions.Unmarshal(m, b) +} +func (m *EnumValueOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumValueOptions.Marshal(b, m, deterministic) +} +func (m *EnumValueOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumValueOptions.Merge(m, src) +} +func (m *EnumValueOptions) XXX_Size() int { + return xxx_messageInfo_EnumValueOptions.Size(m) +} +func (m *EnumValueOptions) XXX_DiscardUnknown() { + xxx_messageInfo_EnumValueOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumValueOptions proto.InternalMessageInfo + +const Default_EnumValueOptions_Deprecated bool = false + +func (m *EnumValueOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_EnumValueOptions_Deprecated +} + +func (m *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type ServiceOptions struct { + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ServiceOptions) Reset() { *m = ServiceOptions{} } +func (m *ServiceOptions) String() string { return proto.CompactTextString(m) } +func (*ServiceOptions) ProtoMessage() {} +func (*ServiceOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{16} +} + +var extRange_ServiceOptions = []proto.ExtensionRange{ + {Start: 1000, End: 536870911}, +} + +func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_ServiceOptions +} + +func (m *ServiceOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ServiceOptions.Unmarshal(m, b) +} +func (m *ServiceOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ServiceOptions.Marshal(b, m, deterministic) +} +func (m *ServiceOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_ServiceOptions.Merge(m, src) +} +func (m *ServiceOptions) XXX_Size() int { + return xxx_messageInfo_ServiceOptions.Size(m) +} +func (m *ServiceOptions) XXX_DiscardUnknown() { + xxx_messageInfo_ServiceOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_ServiceOptions proto.InternalMessageInfo + +const Default_ServiceOptions_Deprecated bool = false + +func (m *ServiceOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_ServiceOptions_Deprecated +} + +func (m *ServiceOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type MethodOptions struct { + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + IdempotencyLevel *MethodOptions_IdempotencyLevel `protobuf:"varint,34,opt,name=idempotency_level,json=idempotencyLevel,enum=google.protobuf.MethodOptions_IdempotencyLevel,def=0" json:"idempotency_level,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MethodOptions) Reset() { *m = MethodOptions{} } +func (m *MethodOptions) String() string { return proto.CompactTextString(m) } +func (*MethodOptions) ProtoMessage() {} +func (*MethodOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{17} +} + +var extRange_MethodOptions = []proto.ExtensionRange{ + {Start: 1000, End: 536870911}, +} + +func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_MethodOptions +} + +func (m *MethodOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MethodOptions.Unmarshal(m, b) +} +func (m *MethodOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MethodOptions.Marshal(b, m, deterministic) +} +func (m *MethodOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_MethodOptions.Merge(m, src) +} +func (m *MethodOptions) XXX_Size() int { + return xxx_messageInfo_MethodOptions.Size(m) +} +func (m *MethodOptions) XXX_DiscardUnknown() { + xxx_messageInfo_MethodOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_MethodOptions proto.InternalMessageInfo + +const Default_MethodOptions_Deprecated bool = false +const Default_MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel = MethodOptions_IDEMPOTENCY_UNKNOWN + +func (m *MethodOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_MethodOptions_Deprecated +} + +func (m *MethodOptions) GetIdempotencyLevel() MethodOptions_IdempotencyLevel { + if m != nil && m.IdempotencyLevel != nil { + return *m.IdempotencyLevel + } + return Default_MethodOptions_IdempotencyLevel +} + +func (m *MethodOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +type UninterpretedOption struct { + Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name" json:"name,omitempty"` + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"` + PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"` + NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"` + DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"` + StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"` + AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} } +func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) } +func (*UninterpretedOption) ProtoMessage() {} +func (*UninterpretedOption) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{18} +} + +func (m *UninterpretedOption) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UninterpretedOption.Unmarshal(m, b) +} +func (m *UninterpretedOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UninterpretedOption.Marshal(b, m, deterministic) +} +func (m *UninterpretedOption) XXX_Merge(src proto.Message) { + xxx_messageInfo_UninterpretedOption.Merge(m, src) +} +func (m *UninterpretedOption) XXX_Size() int { + return xxx_messageInfo_UninterpretedOption.Size(m) +} +func (m *UninterpretedOption) XXX_DiscardUnknown() { + xxx_messageInfo_UninterpretedOption.DiscardUnknown(m) +} + +var xxx_messageInfo_UninterpretedOption proto.InternalMessageInfo + +func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart { + if m != nil { + return m.Name + } + return nil +} + +func (m *UninterpretedOption) GetIdentifierValue() string { + if m != nil && m.IdentifierValue != nil { + return *m.IdentifierValue + } + return "" +} + +func (m *UninterpretedOption) GetPositiveIntValue() uint64 { + if m != nil && m.PositiveIntValue != nil { + return *m.PositiveIntValue + } + return 0 +} + +func (m *UninterpretedOption) GetNegativeIntValue() int64 { + if m != nil && m.NegativeIntValue != nil { + return *m.NegativeIntValue + } + return 0 +} + +func (m *UninterpretedOption) GetDoubleValue() float64 { + if m != nil && m.DoubleValue != nil { + return *m.DoubleValue + } + return 0 +} + +func (m *UninterpretedOption) GetStringValue() []byte { + if m != nil { + return m.StringValue + } + return nil +} + +func (m *UninterpretedOption) GetAggregateValue() string { + if m != nil && m.AggregateValue != nil { + return *m.AggregateValue + } + return "" +} + +// The name of the uninterpreted option. Each string represents a segment in +// a dot-separated name. is_extension is true iff a segment represents an +// extension (denoted with parentheses in options specs in .proto files). +// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents +// "foo.(bar.baz).qux". +type UninterpretedOption_NamePart struct { + NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"` + IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UninterpretedOption_NamePart) Reset() { *m = UninterpretedOption_NamePart{} } +func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) } +func (*UninterpretedOption_NamePart) ProtoMessage() {} +func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{18, 0} +} + +func (m *UninterpretedOption_NamePart) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UninterpretedOption_NamePart.Unmarshal(m, b) +} +func (m *UninterpretedOption_NamePart) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UninterpretedOption_NamePart.Marshal(b, m, deterministic) +} +func (m *UninterpretedOption_NamePart) XXX_Merge(src proto.Message) { + xxx_messageInfo_UninterpretedOption_NamePart.Merge(m, src) +} +func (m *UninterpretedOption_NamePart) XXX_Size() int { + return xxx_messageInfo_UninterpretedOption_NamePart.Size(m) +} +func (m *UninterpretedOption_NamePart) XXX_DiscardUnknown() { + xxx_messageInfo_UninterpretedOption_NamePart.DiscardUnknown(m) +} + +var xxx_messageInfo_UninterpretedOption_NamePart proto.InternalMessageInfo + +func (m *UninterpretedOption_NamePart) GetNamePart() string { + if m != nil && m.NamePart != nil { + return *m.NamePart + } + return "" +} + +func (m *UninterpretedOption_NamePart) GetIsExtension() bool { + if m != nil && m.IsExtension != nil { + return *m.IsExtension + } + return false +} + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +type SourceCodeInfo struct { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} } +func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) } +func (*SourceCodeInfo) ProtoMessage() {} +func (*SourceCodeInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{19} +} + +func (m *SourceCodeInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SourceCodeInfo.Unmarshal(m, b) +} +func (m *SourceCodeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SourceCodeInfo.Marshal(b, m, deterministic) +} +func (m *SourceCodeInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_SourceCodeInfo.Merge(m, src) +} +func (m *SourceCodeInfo) XXX_Size() int { + return xxx_messageInfo_SourceCodeInfo.Size(m) +} +func (m *SourceCodeInfo) XXX_DiscardUnknown() { + xxx_messageInfo_SourceCodeInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_SourceCodeInfo proto.InternalMessageInfo + +func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location { + if m != nil { + return m.Location + } + return nil +} + +type SourceCodeInfo_Location struct { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + Span []int32 `protobuf:"varint,2,rep,packed,name=span" json:"span,omitempty"` + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to qux or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"` + TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"` + LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} } +func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) } +func (*SourceCodeInfo_Location) ProtoMessage() {} +func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{19, 0} +} + +func (m *SourceCodeInfo_Location) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SourceCodeInfo_Location.Unmarshal(m, b) +} +func (m *SourceCodeInfo_Location) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SourceCodeInfo_Location.Marshal(b, m, deterministic) +} +func (m *SourceCodeInfo_Location) XXX_Merge(src proto.Message) { + xxx_messageInfo_SourceCodeInfo_Location.Merge(m, src) +} +func (m *SourceCodeInfo_Location) XXX_Size() int { + return xxx_messageInfo_SourceCodeInfo_Location.Size(m) +} +func (m *SourceCodeInfo_Location) XXX_DiscardUnknown() { + xxx_messageInfo_SourceCodeInfo_Location.DiscardUnknown(m) +} + +var xxx_messageInfo_SourceCodeInfo_Location proto.InternalMessageInfo + +func (m *SourceCodeInfo_Location) GetPath() []int32 { + if m != nil { + return m.Path + } + return nil +} + +func (m *SourceCodeInfo_Location) GetSpan() []int32 { + if m != nil { + return m.Span + } + return nil +} + +func (m *SourceCodeInfo_Location) GetLeadingComments() string { + if m != nil && m.LeadingComments != nil { + return *m.LeadingComments + } + return "" +} + +func (m *SourceCodeInfo_Location) GetTrailingComments() string { + if m != nil && m.TrailingComments != nil { + return *m.TrailingComments + } + return "" +} + +func (m *SourceCodeInfo_Location) GetLeadingDetachedComments() []string { + if m != nil { + return m.LeadingDetachedComments + } + return nil +} + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +type GeneratedCodeInfo struct { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + Annotation []*GeneratedCodeInfo_Annotation `protobuf:"bytes,1,rep,name=annotation" json:"annotation,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} } +func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) } +func (*GeneratedCodeInfo) ProtoMessage() {} +func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{20} +} + +func (m *GeneratedCodeInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GeneratedCodeInfo.Unmarshal(m, b) +} +func (m *GeneratedCodeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GeneratedCodeInfo.Marshal(b, m, deterministic) +} +func (m *GeneratedCodeInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_GeneratedCodeInfo.Merge(m, src) +} +func (m *GeneratedCodeInfo) XXX_Size() int { + return xxx_messageInfo_GeneratedCodeInfo.Size(m) +} +func (m *GeneratedCodeInfo) XXX_DiscardUnknown() { + xxx_messageInfo_GeneratedCodeInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_GeneratedCodeInfo proto.InternalMessageInfo + +func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation { + if m != nil { + return m.Annotation + } + return nil +} + +type GeneratedCodeInfo_Annotation struct { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` + // Identifies the filesystem path to the original source .proto. + SourceFile *string `protobuf:"bytes,2,opt,name=source_file,json=sourceFile" json:"source_file,omitempty"` + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + Begin *int32 `protobuf:"varint,3,opt,name=begin" json:"begin,omitempty"` + // Identifies the ending offset in bytes in the generated code that + // relates to the identified offset. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GeneratedCodeInfo_Annotation) Reset() { *m = GeneratedCodeInfo_Annotation{} } +func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) } +func (*GeneratedCodeInfo_Annotation) ProtoMessage() {} +func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) { + return fileDescriptor_e5baabe45344a177, []int{20, 0} +} + +func (m *GeneratedCodeInfo_Annotation) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GeneratedCodeInfo_Annotation.Unmarshal(m, b) +} +func (m *GeneratedCodeInfo_Annotation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GeneratedCodeInfo_Annotation.Marshal(b, m, deterministic) +} +func (m *GeneratedCodeInfo_Annotation) XXX_Merge(src proto.Message) { + xxx_messageInfo_GeneratedCodeInfo_Annotation.Merge(m, src) +} +func (m *GeneratedCodeInfo_Annotation) XXX_Size() int { + return xxx_messageInfo_GeneratedCodeInfo_Annotation.Size(m) +} +func (m *GeneratedCodeInfo_Annotation) XXX_DiscardUnknown() { + xxx_messageInfo_GeneratedCodeInfo_Annotation.DiscardUnknown(m) +} + +var xxx_messageInfo_GeneratedCodeInfo_Annotation proto.InternalMessageInfo + +func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 { + if m != nil { + return m.Path + } + return nil +} + +func (m *GeneratedCodeInfo_Annotation) GetSourceFile() string { + if m != nil && m.SourceFile != nil { + return *m.SourceFile + } + return "" +} + +func (m *GeneratedCodeInfo_Annotation) GetBegin() int32 { + if m != nil && m.Begin != nil { + return *m.Begin + } + return 0 +} + +func (m *GeneratedCodeInfo_Annotation) GetEnd() int32 { + if m != nil && m.End != nil { + return *m.End + } + return 0 +} + +func init() { + proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value) + proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value) + proto.RegisterEnum("google.protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value) + proto.RegisterEnum("google.protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value) + proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value) + proto.RegisterEnum("google.protobuf.MethodOptions_IdempotencyLevel", MethodOptions_IdempotencyLevel_name, MethodOptions_IdempotencyLevel_value) + proto.RegisterType((*FileDescriptorSet)(nil), "google.protobuf.FileDescriptorSet") + proto.RegisterType((*FileDescriptorProto)(nil), "google.protobuf.FileDescriptorProto") + proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto") + proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange") + proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange") + proto.RegisterType((*ExtensionRangeOptions)(nil), "google.protobuf.ExtensionRangeOptions") + proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto") + proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto") + proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto") + proto.RegisterType((*EnumDescriptorProto_EnumReservedRange)(nil), "google.protobuf.EnumDescriptorProto.EnumReservedRange") + proto.RegisterType((*EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto") + proto.RegisterType((*ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto") + proto.RegisterType((*MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto") + proto.RegisterType((*FileOptions)(nil), "google.protobuf.FileOptions") + proto.RegisterType((*MessageOptions)(nil), "google.protobuf.MessageOptions") + proto.RegisterType((*FieldOptions)(nil), "google.protobuf.FieldOptions") + proto.RegisterType((*OneofOptions)(nil), "google.protobuf.OneofOptions") + proto.RegisterType((*EnumOptions)(nil), "google.protobuf.EnumOptions") + proto.RegisterType((*EnumValueOptions)(nil), "google.protobuf.EnumValueOptions") + proto.RegisterType((*ServiceOptions)(nil), "google.protobuf.ServiceOptions") + proto.RegisterType((*MethodOptions)(nil), "google.protobuf.MethodOptions") + proto.RegisterType((*UninterpretedOption)(nil), "google.protobuf.UninterpretedOption") + proto.RegisterType((*UninterpretedOption_NamePart)(nil), "google.protobuf.UninterpretedOption.NamePart") + proto.RegisterType((*SourceCodeInfo)(nil), "google.protobuf.SourceCodeInfo") + proto.RegisterType((*SourceCodeInfo_Location)(nil), "google.protobuf.SourceCodeInfo.Location") + proto.RegisterType((*GeneratedCodeInfo)(nil), "google.protobuf.GeneratedCodeInfo") + proto.RegisterType((*GeneratedCodeInfo_Annotation)(nil), "google.protobuf.GeneratedCodeInfo.Annotation") +} + +func init() { proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor_e5baabe45344a177) } + +var fileDescriptor_e5baabe45344a177 = []byte{ + // 2589 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x8e, 0xdb, 0xc6, + 0x15, 0x0e, 0xf5, 0xb7, 0xd2, 0x91, 0x56, 0x3b, 0x3b, 0xbb, 0xb1, 0xe9, 0xcd, 0x8f, 0xd7, 0xca, + 0x8f, 0xd7, 0x4e, 0xac, 0x0d, 0x1c, 0xdb, 0x71, 0xd6, 0x45, 0x5a, 0xad, 0x44, 0x6f, 0xe4, 0xee, + 0x4a, 0x2a, 0xa5, 0x6d, 0x7e, 0x80, 0x82, 0x98, 0x25, 0x47, 0x12, 0x6d, 0x8a, 0x64, 0x48, 0xca, + 0xf6, 0x06, 0xbd, 0x30, 0xd0, 0xab, 0x5e, 0x15, 0xe8, 0x55, 0x51, 0x14, 0xbd, 0xe8, 0x4d, 0x80, + 0x3e, 0x40, 0x81, 0xde, 0xf5, 0x09, 0x0a, 0xe4, 0x0d, 0x8a, 0xb6, 0x40, 0xfb, 0x08, 0xbd, 0x2c, + 0x66, 0x86, 0xa4, 0x48, 0x49, 0x1b, 0x6f, 0x02, 0xc4, 0xb9, 0x92, 0xe6, 0x3b, 0xdf, 0x39, 0x73, + 0xe6, 0xcc, 0x99, 0x99, 0x33, 0x43, 0xd8, 0x1e, 0x39, 0xce, 0xc8, 0xa2, 0xbb, 0xae, 0xe7, 0x04, + 0xce, 0xc9, 0x74, 0xb8, 0x6b, 0x50, 0x5f, 0xf7, 0x4c, 0x37, 0x70, 0xbc, 0x3a, 0xc7, 0xf0, 0x9a, + 0x60, 0xd4, 0x23, 0x46, 0xed, 0x08, 0xd6, 0xef, 0x9b, 0x16, 0x6d, 0xc5, 0xc4, 0x3e, 0x0d, 0xf0, + 0x5d, 0xc8, 0x0d, 0x4d, 0x8b, 0xca, 0xd2, 0x76, 0x76, 0xa7, 0x7c, 0xf3, 0xcd, 0xfa, 0x9c, 0x52, + 0x3d, 0xad, 0xd1, 0x63, 0xb0, 0xca, 0x35, 0x6a, 0xff, 0xce, 0xc1, 0xc6, 0x12, 0x29, 0xc6, 0x90, + 0xb3, 0xc9, 0x84, 0x59, 0x94, 0x76, 0x4a, 0x2a, 0xff, 0x8f, 0x65, 0x58, 0x71, 0x89, 0xfe, 0x88, + 0x8c, 0xa8, 0x9c, 0xe1, 0x70, 0xd4, 0xc4, 0xaf, 0x03, 0x18, 0xd4, 0xa5, 0xb6, 0x41, 0x6d, 0xfd, + 0x54, 0xce, 0x6e, 0x67, 0x77, 0x4a, 0x6a, 0x02, 0xc1, 0xef, 0xc0, 0xba, 0x3b, 0x3d, 0xb1, 0x4c, + 0x5d, 0x4b, 0xd0, 0x60, 0x3b, 0xbb, 0x93, 0x57, 0x91, 0x10, 0xb4, 0x66, 0xe4, 0xab, 0xb0, 0xf6, + 0x84, 0x92, 0x47, 0x49, 0x6a, 0x99, 0x53, 0xab, 0x0c, 0x4e, 0x10, 0x9b, 0x50, 0x99, 0x50, 0xdf, + 0x27, 0x23, 0xaa, 0x05, 0xa7, 0x2e, 0x95, 0x73, 0x7c, 0xf4, 0xdb, 0x0b, 0xa3, 0x9f, 0x1f, 0x79, + 0x39, 0xd4, 0x1a, 0x9c, 0xba, 0x14, 0x37, 0xa0, 0x44, 0xed, 0xe9, 0x44, 0x58, 0xc8, 0x9f, 0x11, + 0x3f, 0xc5, 0x9e, 0x4e, 0xe6, 0xad, 0x14, 0x99, 0x5a, 0x68, 0x62, 0xc5, 0xa7, 0xde, 0x63, 0x53, + 0xa7, 0x72, 0x81, 0x1b, 0xb8, 0xba, 0x60, 0xa0, 0x2f, 0xe4, 0xf3, 0x36, 0x22, 0x3d, 0xdc, 0x84, + 0x12, 0x7d, 0x1a, 0x50, 0xdb, 0x37, 0x1d, 0x5b, 0x5e, 0xe1, 0x46, 0xde, 0x5a, 0x32, 0x8b, 0xd4, + 0x32, 0xe6, 0x4d, 0xcc, 0xf4, 0xf0, 0x1d, 0x58, 0x71, 0xdc, 0xc0, 0x74, 0x6c, 0x5f, 0x2e, 0x6e, + 0x4b, 0x3b, 0xe5, 0x9b, 0xaf, 0x2e, 0x4d, 0x84, 0xae, 0xe0, 0xa8, 0x11, 0x19, 0xb7, 0x01, 0xf9, + 0xce, 0xd4, 0xd3, 0xa9, 0xa6, 0x3b, 0x06, 0xd5, 0x4c, 0x7b, 0xe8, 0xc8, 0x25, 0x6e, 0xe0, 0xf2, + 0xe2, 0x40, 0x38, 0xb1, 0xe9, 0x18, 0xb4, 0x6d, 0x0f, 0x1d, 0xb5, 0xea, 0xa7, 0xda, 0xf8, 0x02, + 0x14, 0xfc, 0x53, 0x3b, 0x20, 0x4f, 0xe5, 0x0a, 0xcf, 0x90, 0xb0, 0x55, 0xfb, 0x6b, 0x01, 0xd6, + 0xce, 0x93, 0x62, 0xf7, 0x20, 0x3f, 0x64, 0xa3, 0x94, 0x33, 0xdf, 0x26, 0x06, 0x42, 0x27, 0x1d, + 0xc4, 0xc2, 0x77, 0x0c, 0x62, 0x03, 0xca, 0x36, 0xf5, 0x03, 0x6a, 0x88, 0x8c, 0xc8, 0x9e, 0x33, + 0xa7, 0x40, 0x28, 0x2d, 0xa6, 0x54, 0xee, 0x3b, 0xa5, 0xd4, 0xa7, 0xb0, 0x16, 0xbb, 0xa4, 0x79, + 0xc4, 0x1e, 0x45, 0xb9, 0xb9, 0xfb, 0x3c, 0x4f, 0xea, 0x4a, 0xa4, 0xa7, 0x32, 0x35, 0xb5, 0x4a, + 0x53, 0x6d, 0xdc, 0x02, 0x70, 0x6c, 0xea, 0x0c, 0x35, 0x83, 0xea, 0x96, 0x5c, 0x3c, 0x23, 0x4a, + 0x5d, 0x46, 0x59, 0x88, 0x92, 0x23, 0x50, 0xdd, 0xc2, 0x1f, 0xce, 0x52, 0x6d, 0xe5, 0x8c, 0x4c, + 0x39, 0x12, 0x8b, 0x6c, 0x21, 0xdb, 0x8e, 0xa1, 0xea, 0x51, 0x96, 0xf7, 0xd4, 0x08, 0x47, 0x56, + 0xe2, 0x4e, 0xd4, 0x9f, 0x3b, 0x32, 0x35, 0x54, 0x13, 0x03, 0x5b, 0xf5, 0x92, 0x4d, 0xfc, 0x06, + 0xc4, 0x80, 0xc6, 0xd3, 0x0a, 0xf8, 0x2e, 0x54, 0x89, 0xc0, 0x0e, 0x99, 0xd0, 0xad, 0x2f, 0xa1, + 0x9a, 0x0e, 0x0f, 0xde, 0x84, 0xbc, 0x1f, 0x10, 0x2f, 0xe0, 0x59, 0x98, 0x57, 0x45, 0x03, 0x23, + 0xc8, 0x52, 0xdb, 0xe0, 0xbb, 0x5c, 0x5e, 0x65, 0x7f, 0xf1, 0x4f, 0x66, 0x03, 0xce, 0xf2, 0x01, + 0xbf, 0xbd, 0x38, 0xa3, 0x29, 0xcb, 0xf3, 0xe3, 0xde, 0xfa, 0x00, 0x56, 0x53, 0x03, 0x38, 0x6f, + 0xd7, 0xb5, 0x5f, 0xc2, 0xcb, 0x4b, 0x4d, 0xe3, 0x4f, 0x61, 0x73, 0x6a, 0x9b, 0x76, 0x40, 0x3d, + 0xd7, 0xa3, 0x2c, 0x63, 0x45, 0x57, 0xf2, 0x7f, 0x56, 0xce, 0xc8, 0xb9, 0xe3, 0x24, 0x5b, 0x58, + 0x51, 0x37, 0xa6, 0x8b, 0xe0, 0xf5, 0x52, 0xf1, 0xbf, 0x2b, 0xe8, 0xd9, 0xb3, 0x67, 0xcf, 0x32, + 0xb5, 0xdf, 0x15, 0x60, 0x73, 0xd9, 0x9a, 0x59, 0xba, 0x7c, 0x2f, 0x40, 0xc1, 0x9e, 0x4e, 0x4e, + 0xa8, 0xc7, 0x83, 0x94, 0x57, 0xc3, 0x16, 0x6e, 0x40, 0xde, 0x22, 0x27, 0xd4, 0x92, 0x73, 0xdb, + 0xd2, 0x4e, 0xf5, 0xe6, 0x3b, 0xe7, 0x5a, 0x95, 0xf5, 0x43, 0xa6, 0xa2, 0x0a, 0x4d, 0xfc, 0x11, + 0xe4, 0xc2, 0x2d, 0x9a, 0x59, 0xb8, 0x7e, 0x3e, 0x0b, 0x6c, 0x2d, 0xa9, 0x5c, 0x0f, 0xbf, 0x02, + 0x25, 0xf6, 0x2b, 0x72, 0xa3, 0xc0, 0x7d, 0x2e, 0x32, 0x80, 0xe5, 0x05, 0xde, 0x82, 0x22, 0x5f, + 0x26, 0x06, 0x8d, 0x8e, 0xb6, 0xb8, 0xcd, 0x12, 0xcb, 0xa0, 0x43, 0x32, 0xb5, 0x02, 0xed, 0x31, + 0xb1, 0xa6, 0x94, 0x27, 0x7c, 0x49, 0xad, 0x84, 0xe0, 0xcf, 0x19, 0x86, 0x2f, 0x43, 0x59, 0xac, + 0x2a, 0xd3, 0x36, 0xe8, 0x53, 0xbe, 0x7b, 0xe6, 0x55, 0xb1, 0xd0, 0xda, 0x0c, 0x61, 0xdd, 0x3f, + 0xf4, 0x1d, 0x3b, 0x4a, 0x4d, 0xde, 0x05, 0x03, 0x78, 0xf7, 0x1f, 0xcc, 0x6f, 0xdc, 0xaf, 0x2d, + 0x1f, 0xde, 0x7c, 0x4e, 0xd5, 0xfe, 0x92, 0x81, 0x1c, 0xdf, 0x2f, 0xd6, 0xa0, 0x3c, 0xf8, 0xac, + 0xa7, 0x68, 0xad, 0xee, 0xf1, 0xfe, 0xa1, 0x82, 0x24, 0x5c, 0x05, 0xe0, 0xc0, 0xfd, 0xc3, 0x6e, + 0x63, 0x80, 0x32, 0x71, 0xbb, 0xdd, 0x19, 0xdc, 0xb9, 0x85, 0xb2, 0xb1, 0xc2, 0xb1, 0x00, 0x72, + 0x49, 0xc2, 0xfb, 0x37, 0x51, 0x1e, 0x23, 0xa8, 0x08, 0x03, 0xed, 0x4f, 0x95, 0xd6, 0x9d, 0x5b, + 0xa8, 0x90, 0x46, 0xde, 0xbf, 0x89, 0x56, 0xf0, 0x2a, 0x94, 0x38, 0xb2, 0xdf, 0xed, 0x1e, 0xa2, + 0x62, 0x6c, 0xb3, 0x3f, 0x50, 0xdb, 0x9d, 0x03, 0x54, 0x8a, 0x6d, 0x1e, 0xa8, 0xdd, 0xe3, 0x1e, + 0x82, 0xd8, 0xc2, 0x91, 0xd2, 0xef, 0x37, 0x0e, 0x14, 0x54, 0x8e, 0x19, 0xfb, 0x9f, 0x0d, 0x94, + 0x3e, 0xaa, 0xa4, 0xdc, 0x7a, 0xff, 0x26, 0x5a, 0x8d, 0xbb, 0x50, 0x3a, 0xc7, 0x47, 0xa8, 0x8a, + 0xd7, 0x61, 0x55, 0x74, 0x11, 0x39, 0xb1, 0x36, 0x07, 0xdd, 0xb9, 0x85, 0xd0, 0xcc, 0x11, 0x61, + 0x65, 0x3d, 0x05, 0xdc, 0xb9, 0x85, 0x70, 0xad, 0x09, 0x79, 0x9e, 0x5d, 0x18, 0x43, 0xf5, 0xb0, + 0xb1, 0xaf, 0x1c, 0x6a, 0xdd, 0xde, 0xa0, 0xdd, 0xed, 0x34, 0x0e, 0x91, 0x34, 0xc3, 0x54, 0xe5, + 0x67, 0xc7, 0x6d, 0x55, 0x69, 0xa1, 0x4c, 0x12, 0xeb, 0x29, 0x8d, 0x81, 0xd2, 0x42, 0xd9, 0x9a, + 0x0e, 0x9b, 0xcb, 0xf6, 0xc9, 0xa5, 0x2b, 0x23, 0x31, 0xc5, 0x99, 0x33, 0xa6, 0x98, 0xdb, 0x5a, + 0x98, 0xe2, 0x7f, 0x65, 0x60, 0x63, 0xc9, 0x59, 0xb1, 0xb4, 0x93, 0x1f, 0x43, 0x5e, 0xa4, 0xa8, + 0x38, 0x3d, 0xaf, 0x2d, 0x3d, 0x74, 0x78, 0xc2, 0x2e, 0x9c, 0xa0, 0x5c, 0x2f, 0x59, 0x41, 0x64, + 0xcf, 0xa8, 0x20, 0x98, 0x89, 0x85, 0x3d, 0xfd, 0x17, 0x0b, 0x7b, 0xba, 0x38, 0xf6, 0xee, 0x9c, + 0xe7, 0xd8, 0xe3, 0xd8, 0xb7, 0xdb, 0xdb, 0xf3, 0x4b, 0xf6, 0xf6, 0x7b, 0xb0, 0xbe, 0x60, 0xe8, + 0xdc, 0x7b, 0xec, 0xaf, 0x24, 0x90, 0xcf, 0x0a, 0xce, 0x73, 0x76, 0xba, 0x4c, 0x6a, 0xa7, 0xbb, + 0x37, 0x1f, 0xc1, 0x2b, 0x67, 0x4f, 0xc2, 0xc2, 0x5c, 0x7f, 0x25, 0xc1, 0x85, 0xe5, 0x95, 0xe2, + 0x52, 0x1f, 0x3e, 0x82, 0xc2, 0x84, 0x06, 0x63, 0x27, 0xaa, 0x96, 0xde, 0x5e, 0x72, 0x06, 0x33, + 0xf1, 0xfc, 0x64, 0x87, 0x5a, 0xc9, 0x43, 0x3c, 0x7b, 0x56, 0xb9, 0x27, 0xbc, 0x59, 0xf0, 0xf4, + 0xd7, 0x19, 0x78, 0x79, 0xa9, 0xf1, 0xa5, 0x8e, 0xbe, 0x06, 0x60, 0xda, 0xee, 0x34, 0x10, 0x15, + 0x91, 0xd8, 0x60, 0x4b, 0x1c, 0xe1, 0x9b, 0x17, 0xdb, 0x3c, 0xa7, 0x41, 0x2c, 0xcf, 0x72, 0x39, + 0x08, 0x88, 0x13, 0xee, 0xce, 0x1c, 0xcd, 0x71, 0x47, 0x5f, 0x3f, 0x63, 0xa4, 0x0b, 0x89, 0xf9, + 0x1e, 0x20, 0xdd, 0x32, 0xa9, 0x1d, 0x68, 0x7e, 0xe0, 0x51, 0x32, 0x31, 0xed, 0x11, 0x3f, 0x41, + 0x8a, 0x7b, 0xf9, 0x21, 0xb1, 0x7c, 0xaa, 0xae, 0x09, 0x71, 0x3f, 0x92, 0x32, 0x0d, 0x9e, 0x40, + 0x5e, 0x42, 0xa3, 0x90, 0xd2, 0x10, 0xe2, 0x58, 0xa3, 0xf6, 0xdb, 0x12, 0x94, 0x13, 0x75, 0x35, + 0xbe, 0x02, 0x95, 0x87, 0xe4, 0x31, 0xd1, 0xa2, 0xbb, 0x92, 0x88, 0x44, 0x99, 0x61, 0xbd, 0xf0, + 0xbe, 0xf4, 0x1e, 0x6c, 0x72, 0x8a, 0x33, 0x0d, 0xa8, 0xa7, 0xe9, 0x16, 0xf1, 0x7d, 0x1e, 0xb4, + 0x22, 0xa7, 0x62, 0x26, 0xeb, 0x32, 0x51, 0x33, 0x92, 0xe0, 0xdb, 0xb0, 0xc1, 0x35, 0x26, 0x53, + 0x2b, 0x30, 0x5d, 0x8b, 0x6a, 0xec, 0xf6, 0xe6, 0xf3, 0x93, 0x24, 0xf6, 0x6c, 0x9d, 0x31, 0x8e, + 0x42, 0x02, 0xf3, 0xc8, 0xc7, 0x2d, 0x78, 0x8d, 0xab, 0x8d, 0xa8, 0x4d, 0x3d, 0x12, 0x50, 0x8d, + 0x7e, 0x31, 0x25, 0x96, 0xaf, 0x11, 0xdb, 0xd0, 0xc6, 0xc4, 0x1f, 0xcb, 0x9b, 0xcc, 0xc0, 0x7e, + 0x46, 0x96, 0xd4, 0x4b, 0x8c, 0x78, 0x10, 0xf2, 0x14, 0x4e, 0x6b, 0xd8, 0xc6, 0xc7, 0xc4, 0x1f, + 0xe3, 0x3d, 0xb8, 0xc0, 0xad, 0xf8, 0x81, 0x67, 0xda, 0x23, 0x4d, 0x1f, 0x53, 0xfd, 0x91, 0x36, + 0x0d, 0x86, 0x77, 0xe5, 0x57, 0x92, 0xfd, 0x73, 0x0f, 0xfb, 0x9c, 0xd3, 0x64, 0x94, 0xe3, 0x60, + 0x78, 0x17, 0xf7, 0xa1, 0xc2, 0x26, 0x63, 0x62, 0x7e, 0x49, 0xb5, 0xa1, 0xe3, 0xf1, 0xa3, 0xb1, + 0xba, 0x64, 0x6b, 0x4a, 0x44, 0xb0, 0xde, 0x0d, 0x15, 0x8e, 0x1c, 0x83, 0xee, 0xe5, 0xfb, 0x3d, + 0x45, 0x69, 0xa9, 0xe5, 0xc8, 0xca, 0x7d, 0xc7, 0x63, 0x09, 0x35, 0x72, 0xe2, 0x00, 0x97, 0x45, + 0x42, 0x8d, 0x9c, 0x28, 0xbc, 0xb7, 0x61, 0x43, 0xd7, 0xc5, 0x98, 0x4d, 0x5d, 0x0b, 0xef, 0x58, + 0xbe, 0x8c, 0x52, 0xc1, 0xd2, 0xf5, 0x03, 0x41, 0x08, 0x73, 0xdc, 0xc7, 0x1f, 0xc2, 0xcb, 0xb3, + 0x60, 0x25, 0x15, 0xd7, 0x17, 0x46, 0x39, 0xaf, 0x7a, 0x1b, 0x36, 0xdc, 0xd3, 0x45, 0x45, 0x9c, + 0xea, 0xd1, 0x3d, 0x9d, 0x57, 0xfb, 0x00, 0x36, 0xdd, 0xb1, 0xbb, 0xa8, 0x77, 0x3d, 0xa9, 0x87, + 0xdd, 0xb1, 0x3b, 0xaf, 0xf8, 0x16, 0xbf, 0x70, 0x7b, 0x54, 0x27, 0x01, 0x35, 0xe4, 0x8b, 0x49, + 0x7a, 0x42, 0x80, 0x77, 0x01, 0xe9, 0xba, 0x46, 0x6d, 0x72, 0x62, 0x51, 0x8d, 0x78, 0xd4, 0x26, + 0xbe, 0x7c, 0x39, 0x49, 0xae, 0xea, 0xba, 0xc2, 0xa5, 0x0d, 0x2e, 0xc4, 0xd7, 0x61, 0xdd, 0x39, + 0x79, 0xa8, 0x8b, 0x94, 0xd4, 0x5c, 0x8f, 0x0e, 0xcd, 0xa7, 0xf2, 0x9b, 0x3c, 0xbe, 0x6b, 0x4c, + 0xc0, 0x13, 0xb2, 0xc7, 0x61, 0x7c, 0x0d, 0x90, 0xee, 0x8f, 0x89, 0xe7, 0xf2, 0x3d, 0xd9, 0x77, + 0x89, 0x4e, 0xe5, 0xb7, 0x04, 0x55, 0xe0, 0x9d, 0x08, 0x66, 0x4b, 0xc2, 0x7f, 0x62, 0x0e, 0x83, + 0xc8, 0xe2, 0x55, 0xb1, 0x24, 0x38, 0x16, 0x5a, 0xdb, 0x01, 0xc4, 0x42, 0x91, 0xea, 0x78, 0x87, + 0xd3, 0xaa, 0xee, 0xd8, 0x4d, 0xf6, 0xfb, 0x06, 0xac, 0x32, 0xe6, 0xac, 0xd3, 0x6b, 0xa2, 0x20, + 0x73, 0xc7, 0x89, 0x1e, 0x6f, 0xc1, 0x05, 0x46, 0x9a, 0xd0, 0x80, 0x18, 0x24, 0x20, 0x09, 0xf6, + 0xbb, 0x9c, 0xcd, 0xe2, 0x7e, 0x14, 0x0a, 0x53, 0x7e, 0x7a, 0xd3, 0x93, 0xd3, 0x38, 0xb3, 0x6e, + 0x08, 0x3f, 0x19, 0x16, 0xe5, 0xd6, 0xf7, 0x56, 0x74, 0xd7, 0xf6, 0xa0, 0x92, 0x4c, 0x7c, 0x5c, + 0x02, 0x91, 0xfa, 0x48, 0x62, 0x55, 0x50, 0xb3, 0xdb, 0x62, 0xf5, 0xcb, 0xe7, 0x0a, 0xca, 0xb0, + 0x3a, 0xea, 0xb0, 0x3d, 0x50, 0x34, 0xf5, 0xb8, 0x33, 0x68, 0x1f, 0x29, 0x28, 0x9b, 0x28, 0xd8, + 0x1f, 0xe4, 0x8a, 0x6f, 0xa3, 0xab, 0xb5, 0xaf, 0x33, 0x50, 0x4d, 0xdf, 0xc0, 0xf0, 0x8f, 0xe0, + 0x62, 0xf4, 0x5c, 0xe2, 0xd3, 0x40, 0x7b, 0x62, 0x7a, 0x7c, 0x45, 0x4e, 0x88, 0x38, 0x1d, 0xe3, + 0x9c, 0xd8, 0x0c, 0x59, 0x7d, 0x1a, 0x7c, 0x62, 0x7a, 0x6c, 0xbd, 0x4d, 0x48, 0x80, 0x0f, 0xe1, + 0xb2, 0xed, 0x68, 0x7e, 0x40, 0x6c, 0x83, 0x78, 0x86, 0x36, 0x7b, 0xa8, 0xd2, 0x88, 0xae, 0x53, + 0xdf, 0x77, 0xc4, 0x49, 0x18, 0x5b, 0x79, 0xd5, 0x76, 0xfa, 0x21, 0x79, 0x76, 0x44, 0x34, 0x42, + 0xea, 0x5c, 0xfe, 0x66, 0xcf, 0xca, 0xdf, 0x57, 0xa0, 0x34, 0x21, 0xae, 0x46, 0xed, 0xc0, 0x3b, + 0xe5, 0x75, 0x77, 0x51, 0x2d, 0x4e, 0x88, 0xab, 0xb0, 0xf6, 0x0b, 0xb9, 0xfe, 0x3c, 0xc8, 0x15, + 0x8b, 0xa8, 0xf4, 0x20, 0x57, 0x2c, 0x21, 0xa8, 0xfd, 0x33, 0x0b, 0x95, 0x64, 0x1d, 0xce, 0xae, + 0x35, 0x3a, 0x3f, 0xb2, 0x24, 0xbe, 0xa9, 0xbd, 0xf1, 0x8d, 0x55, 0x7b, 0xbd, 0xc9, 0xce, 0xb2, + 0xbd, 0x82, 0xa8, 0x8e, 0x55, 0xa1, 0xc9, 0xea, 0x08, 0x96, 0x6c, 0x54, 0x54, 0x23, 0x45, 0x35, + 0x6c, 0xe1, 0x03, 0x28, 0x3c, 0xf4, 0xb9, 0xed, 0x02, 0xb7, 0xfd, 0xe6, 0x37, 0xdb, 0x7e, 0xd0, + 0xe7, 0xc6, 0x4b, 0x0f, 0xfa, 0x5a, 0xa7, 0xab, 0x1e, 0x35, 0x0e, 0xd5, 0x50, 0x1d, 0x5f, 0x82, + 0x9c, 0x45, 0xbe, 0x3c, 0x4d, 0x9f, 0x7a, 0x1c, 0x3a, 0xef, 0x24, 0x5c, 0x82, 0xdc, 0x13, 0x4a, + 0x1e, 0xa5, 0xcf, 0x1a, 0x0e, 0x7d, 0x8f, 0x8b, 0x61, 0x17, 0xf2, 0x3c, 0x5e, 0x18, 0x20, 0x8c, + 0x18, 0x7a, 0x09, 0x17, 0x21, 0xd7, 0xec, 0xaa, 0x6c, 0x41, 0x20, 0xa8, 0x08, 0x54, 0xeb, 0xb5, + 0x95, 0xa6, 0x82, 0x32, 0xb5, 0xdb, 0x50, 0x10, 0x41, 0x60, 0x8b, 0x25, 0x0e, 0x03, 0x7a, 0x29, + 0x6c, 0x86, 0x36, 0xa4, 0x48, 0x7a, 0x7c, 0xb4, 0xaf, 0xa8, 0x28, 0x93, 0x9e, 0xea, 0x1c, 0xca, + 0xd7, 0x7c, 0xa8, 0x24, 0x0b, 0xf1, 0x17, 0x73, 0xc9, 0xfe, 0x9b, 0x04, 0xe5, 0x44, 0x61, 0xcd, + 0x2a, 0x22, 0x62, 0x59, 0xce, 0x13, 0x8d, 0x58, 0x26, 0xf1, 0xc3, 0xd4, 0x00, 0x0e, 0x35, 0x18, + 0x72, 0xde, 0xa9, 0x7b, 0x41, 0x4b, 0x24, 0x8f, 0x0a, 0xb5, 0x3f, 0x4a, 0x80, 0xe6, 0x2b, 0xdb, + 0x39, 0x37, 0xa5, 0x1f, 0xd2, 0xcd, 0xda, 0x1f, 0x24, 0xa8, 0xa6, 0xcb, 0xd9, 0x39, 0xf7, 0xae, + 0xfc, 0xa0, 0xee, 0xfd, 0x23, 0x03, 0xab, 0xa9, 0x22, 0xf6, 0xbc, 0xde, 0x7d, 0x01, 0xeb, 0xa6, + 0x41, 0x27, 0xae, 0x13, 0x50, 0x5b, 0x3f, 0xd5, 0x2c, 0xfa, 0x98, 0x5a, 0x72, 0x8d, 0x6f, 0x1a, + 0xbb, 0xdf, 0x5c, 0x26, 0xd7, 0xdb, 0x33, 0xbd, 0x43, 0xa6, 0xb6, 0xb7, 0xd1, 0x6e, 0x29, 0x47, + 0xbd, 0xee, 0x40, 0xe9, 0x34, 0x3f, 0xd3, 0x8e, 0x3b, 0x3f, 0xed, 0x74, 0x3f, 0xe9, 0xa8, 0xc8, + 0x9c, 0xa3, 0x7d, 0x8f, 0xcb, 0xbe, 0x07, 0x68, 0xde, 0x29, 0x7c, 0x11, 0x96, 0xb9, 0x85, 0x5e, + 0xc2, 0x1b, 0xb0, 0xd6, 0xe9, 0x6a, 0xfd, 0x76, 0x4b, 0xd1, 0x94, 0xfb, 0xf7, 0x95, 0xe6, 0xa0, + 0x2f, 0x1e, 0x3e, 0x62, 0xf6, 0x20, 0xb5, 0xc0, 0x6b, 0xbf, 0xcf, 0xc2, 0xc6, 0x12, 0x4f, 0x70, + 0x23, 0xbc, 0xb2, 0x88, 0x5b, 0xd4, 0x8d, 0xf3, 0x78, 0x5f, 0x67, 0x35, 0x43, 0x8f, 0x78, 0x41, + 0x78, 0xc3, 0xb9, 0x06, 0x2c, 0x4a, 0x76, 0x60, 0x0e, 0x4d, 0xea, 0x85, 0xef, 0x44, 0xe2, 0x1e, + 0xb3, 0x36, 0xc3, 0xc5, 0x53, 0xd1, 0xbb, 0x80, 0x5d, 0xc7, 0x37, 0x03, 0xf3, 0x31, 0xd5, 0x4c, + 0x3b, 0x7a, 0x54, 0x62, 0xf7, 0x9a, 0x9c, 0x8a, 0x22, 0x49, 0xdb, 0x0e, 0x62, 0xb6, 0x4d, 0x47, + 0x64, 0x8e, 0xcd, 0x36, 0xf3, 0xac, 0x8a, 0x22, 0x49, 0xcc, 0xbe, 0x02, 0x15, 0xc3, 0x99, 0xb2, + 0x62, 0x4f, 0xf0, 0xd8, 0xd9, 0x21, 0xa9, 0x65, 0x81, 0xc5, 0x94, 0xb0, 0x8c, 0x9f, 0xbd, 0x66, + 0x55, 0xd4, 0xb2, 0xc0, 0x04, 0xe5, 0x2a, 0xac, 0x91, 0xd1, 0xc8, 0x63, 0xc6, 0x23, 0x43, 0xe2, + 0x62, 0x52, 0x8d, 0x61, 0x4e, 0xdc, 0x7a, 0x00, 0xc5, 0x28, 0x0e, 0xec, 0xa8, 0x66, 0x91, 0xd0, + 0x5c, 0x71, 0xdb, 0xce, 0xec, 0x94, 0xd4, 0xa2, 0x1d, 0x09, 0xaf, 0x40, 0xc5, 0xf4, 0xb5, 0xd9, + 0xe3, 0x7c, 0x66, 0x3b, 0xb3, 0x53, 0x54, 0xcb, 0xa6, 0x1f, 0x3f, 0x6c, 0xd6, 0xbe, 0xca, 0x40, + 0x35, 0xfd, 0x71, 0x01, 0xb7, 0xa0, 0x68, 0x39, 0x3a, 0xe1, 0xa9, 0x25, 0xbe, 0x6c, 0xed, 0x3c, + 0xe7, 0x7b, 0x44, 0xfd, 0x30, 0xe4, 0xab, 0xb1, 0xe6, 0xd6, 0xdf, 0x25, 0x28, 0x46, 0x30, 0xbe, + 0x00, 0x39, 0x97, 0x04, 0x63, 0x6e, 0x2e, 0xbf, 0x9f, 0x41, 0x92, 0xca, 0xdb, 0x0c, 0xf7, 0x5d, + 0x62, 0xf3, 0x14, 0x08, 0x71, 0xd6, 0x66, 0xf3, 0x6a, 0x51, 0x62, 0xf0, 0x5b, 0x8f, 0x33, 0x99, + 0x50, 0x3b, 0xf0, 0xa3, 0x79, 0x0d, 0xf1, 0x66, 0x08, 0xe3, 0x77, 0x60, 0x3d, 0xf0, 0x88, 0x69, + 0xa5, 0xb8, 0x39, 0xce, 0x45, 0x91, 0x20, 0x26, 0xef, 0xc1, 0xa5, 0xc8, 0xae, 0x41, 0x03, 0xa2, + 0x8f, 0xa9, 0x31, 0x53, 0x2a, 0xf0, 0xd7, 0x8d, 0x8b, 0x21, 0xa1, 0x15, 0xca, 0x23, 0xdd, 0xda, + 0xd7, 0x12, 0xac, 0x47, 0xf7, 0x34, 0x23, 0x0e, 0xd6, 0x11, 0x00, 0xb1, 0x6d, 0x27, 0x48, 0x86, + 0x6b, 0x31, 0x95, 0x17, 0xf4, 0xea, 0x8d, 0x58, 0x49, 0x4d, 0x18, 0xd8, 0x9a, 0x00, 0xcc, 0x24, + 0x67, 0x86, 0xed, 0x32, 0x94, 0xc3, 0x2f, 0x47, 0xfc, 0xf3, 0xa3, 0xb8, 0xd9, 0x83, 0x80, 0xd8, + 0x85, 0x0e, 0x6f, 0x42, 0xfe, 0x84, 0x8e, 0x4c, 0x3b, 0x7c, 0x0f, 0x16, 0x8d, 0xe8, 0xfd, 0x25, + 0x17, 0xbf, 0xbf, 0xec, 0xff, 0x46, 0x82, 0x0d, 0xdd, 0x99, 0xcc, 0xfb, 0xbb, 0x8f, 0xe6, 0x9e, + 0x17, 0xfc, 0x8f, 0xa5, 0xcf, 0x3f, 0x1a, 0x99, 0xc1, 0x78, 0x7a, 0x52, 0xd7, 0x9d, 0xc9, 0xee, + 0xc8, 0xb1, 0x88, 0x3d, 0x9a, 0x7d, 0x3f, 0xe5, 0x7f, 0xf4, 0x1b, 0x23, 0x6a, 0xdf, 0x18, 0x39, + 0x89, 0xaf, 0xa9, 0xf7, 0x66, 0x7f, 0xff, 0x27, 0x49, 0x7f, 0xca, 0x64, 0x0f, 0x7a, 0xfb, 0x7f, + 0xce, 0x6c, 0x1d, 0x88, 0xee, 0x7a, 0x51, 0x78, 0x54, 0x3a, 0xb4, 0xa8, 0xce, 0x86, 0xfc, 0xff, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x3e, 0xe8, 0xef, 0xc4, 0x9b, 0x1d, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto new file mode 100644 index 0000000000..ed08fcbc54 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto @@ -0,0 +1,883 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + +syntax = "proto2"; + +package google.protobuf; +option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.Reflection"; +option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; + + // The syntax of the proto file. + // The supported values are "proto2" and "proto3". + optional string syntax = 12; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + + optional ExtensionRangeOptions options = 3; + } + repeated ExtensionRange extension_range = 5; + + repeated OneofDescriptorProto oneof_decl = 8; + + optional MessageOptions options = 7; + + // Range of reserved tag numbers. Reserved tag numbers may not be used by + // fields or extension ranges in the same message. Reserved ranges may + // not overlap. + message ReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + repeated string reserved_name = 10; +} + +message ExtensionRangeOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + // Tag-delimited aggregate. + // Group type is deprecated and not supported in proto3. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + optional int32 oneof_index = 9; + + // JSON name of this field. The value is set by protocol compiler. If the + // user has set a "json_name" option on this field, that option's value + // will be used. Otherwise, it's deduced from the field's name by converting + // it to camelCase. + optional string json_name = 10; + + optional FieldOptions options = 8; +} + +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; + optional OneofOptions options = 2; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; + + // Range of reserved numeric values. Reserved values may not be used by + // entries in the same enum. Reserved ranges may not overlap. + // + // Note that this is distinct from DescriptorProto.ReservedRange in that it + // is inclusive such that it can appropriately represent the entire int32 + // domain. + message EnumReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Inclusive. + } + + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + repeated EnumReservedRange reserved_range = 4; + + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + repeated string reserved_name = 5; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; + + // Identifies if client streams multiple client messages + optional bool client_streaming = 5 [default=false]; + // Identifies if server streams multiple server messages + optional bool server_streaming = 6 [default=false]; +} + + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Objective-C plugin) and your project website (if available) -- there's no +// need to explain how you intend to use them. Usually you only need one +// extension number. You can declare multiple options with only one extension +// number by putting them in a sub-message. See the Custom Options section of +// the docs for examples: +// https://developers.google.com/protocol-buffers/docs/proto#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // This option does nothing. + optional bool java_generate_equals_and_hash = 20 [deprecated=true]; + + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + optional bool java_string_check_utf8 = 27 [default=false]; + + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + optional string go_package = 11; + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + optional bool php_generic_services = 42 [default=false]; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default=false]; + + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + optional bool cc_enable_arenas = 31 [default=false]; + + + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + + // Namespace for generated classes; defaults to the package. + optional string csharp_namespace = 37; + + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + optional string swift_prefix = 39; + + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + optional string php_class_prefix = 40; + + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + optional string php_namespace = 41; + + + // Use this option to change the namespace of php generated metadata classes. + // Default is empty. When this option is empty, the proto file name will be used + // for determining the namespace. + optional string php_metadata_namespace = 44; + + // Use this option to change the package of ruby generated classes. Default + // is empty. When this option is not set, the package name will be used for + // determining the ruby package. + optional string ruby_package = 45; + + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. + // See the documentation for the "Options" section above. + extensions 1000 to max; + + reserved 38; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default=false]; + + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementions still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + + reserved 8; // javalite_serializable + reserved 9; // javanano_as_lite + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. + optional bool packed = 2; + + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. + optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { + // Use the default type. + JS_NORMAL = 0; + + // Use JavaScript strings. + JS_STRING = 1; + + // Use JavaScript numbers. + JS_NUMBER = 2; + } + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outer message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + optional bool lazy = 5 [default=false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default=false]; + + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; + + reserved 4; // removed jtype +} + +message OneofOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default=false]; + + reserved 5; // javanano_as_lite + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default=false]; + + // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + // or neither? HTTP based RPC implementation may choose GET verb for safe + // methods, and PUT verb for idempotent methods instead of the default POST. + enum IdempotencyLevel { + IDEMPOTENCY_UNKNOWN = 0; + NO_SIDE_EFFECTS = 1; // implies idempotent + IDEMPOTENT = 2; // idempotent, but may have side effects + } + optional IdempotencyLevel idempotency_level = + 34 [default=IDEMPOTENCY_UNKNOWN]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to qux or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + optional string leading_comments = 3; + optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; + } +} + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +message GeneratedCodeInfo { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + repeated Annotation annotation = 1; + message Annotation { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + repeated int32 path = 1 [packed=true]; + + // Identifies the filesystem path to the original source .proto. + optional string source_file = 2; + + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + optional int32 begin = 3; + + // Identifies the ending offset in bytes in the generated code that + // relates to the identified offset. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + optional int32 end = 4; + } +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/doc.go b/vendor/github.com/golang/protobuf/protoc-gen-go/doc.go new file mode 100644 index 0000000000..0d6055d610 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/doc.go @@ -0,0 +1,51 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* + A plugin for the Google protocol buffer compiler to generate Go code. + Run it by building this program and putting it in your path with the name + protoc-gen-go + That word 'go' at the end becomes part of the option string set for the + protocol compiler, so once the protocol compiler (protoc) is installed + you can run + protoc --go_out=output_directory input_directory/file.proto + to generate Go bindings for the protocol defined by file.proto. + With that input, the output will be written to + output_directory/file.pb.go + + The generated code is documented in the package comment for + the library. + + See the README and documentation for protocol buffers to learn more: + https://developers.google.com/protocol-buffers/ + +*/ +package documentation diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go new file mode 100644 index 0000000000..6f4a902b5b --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go @@ -0,0 +1,2806 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* + The code generator for the plugin for the Google protocol buffer compiler. + It generates Go code from the protocol buffer description files read by the + main routine. +*/ +package generator + +import ( + "bufio" + "bytes" + "compress/gzip" + "crypto/sha256" + "encoding/hex" + "fmt" + "go/ast" + "go/build" + "go/parser" + "go/printer" + "go/token" + "log" + "os" + "path" + "sort" + "strconv" + "strings" + "unicode" + "unicode/utf8" + + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/protoc-gen-go/generator/internal/remap" + + "github.com/golang/protobuf/protoc-gen-go/descriptor" + plugin "github.com/golang/protobuf/protoc-gen-go/plugin" +) + +// generatedCodeVersion indicates a version of the generated code. +// It is incremented whenever an incompatibility between the generated code and +// proto package is introduced; the generated code references +// a constant, proto.ProtoPackageIsVersionN (where N is generatedCodeVersion). +const generatedCodeVersion = 3 + +// A Plugin provides functionality to add to the output during Go code generation, +// such as to produce RPC stubs. +type Plugin interface { + // Name identifies the plugin. + Name() string + // Init is called once after data structures are built but before + // code generation begins. + Init(g *Generator) + // Generate produces the code generated by the plugin for this file, + // except for the imports, by calling the generator's methods P, In, and Out. + Generate(file *FileDescriptor) + // GenerateImports produces the import declarations for this file. + // It is called after Generate. + GenerateImports(file *FileDescriptor) +} + +var plugins []Plugin + +// RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated. +// It is typically called during initialization. +func RegisterPlugin(p Plugin) { + plugins = append(plugins, p) +} + +// A GoImportPath is the import path of a Go package. e.g., "google.golang.org/genproto/protobuf". +type GoImportPath string + +func (p GoImportPath) String() string { return strconv.Quote(string(p)) } + +// A GoPackageName is the name of a Go package. e.g., "protobuf". +type GoPackageName string + +// Each type we import as a protocol buffer (other than FileDescriptorProto) needs +// a pointer to the FileDescriptorProto that represents it. These types achieve that +// wrapping by placing each Proto inside a struct with the pointer to its File. The +// structs have the same names as their contents, with "Proto" removed. +// FileDescriptor is used to store the things that it points to. + +// The file and package name method are common to messages and enums. +type common struct { + file *FileDescriptor // File this object comes from. +} + +// GoImportPath is the import path of the Go package containing the type. +func (c *common) GoImportPath() GoImportPath { + return c.file.importPath +} + +func (c *common) File() *FileDescriptor { return c.file } + +func fileIsProto3(file *descriptor.FileDescriptorProto) bool { + return file.GetSyntax() == "proto3" +} + +func (c *common) proto3() bool { return fileIsProto3(c.file.FileDescriptorProto) } + +// Descriptor represents a protocol buffer message. +type Descriptor struct { + common + *descriptor.DescriptorProto + parent *Descriptor // The containing message, if any. + nested []*Descriptor // Inner messages, if any. + enums []*EnumDescriptor // Inner enums, if any. + ext []*ExtensionDescriptor // Extensions, if any. + typename []string // Cached typename vector. + index int // The index into the container, whether the file or another message. + path string // The SourceCodeInfo path as comma-separated integers. + group bool +} + +// TypeName returns the elements of the dotted type name. +// The package name is not part of this name. +func (d *Descriptor) TypeName() []string { + if d.typename != nil { + return d.typename + } + n := 0 + for parent := d; parent != nil; parent = parent.parent { + n++ + } + s := make([]string, n) + for parent := d; parent != nil; parent = parent.parent { + n-- + s[n] = parent.GetName() + } + d.typename = s + return s +} + +// EnumDescriptor describes an enum. If it's at top level, its parent will be nil. +// Otherwise it will be the descriptor of the message in which it is defined. +type EnumDescriptor struct { + common + *descriptor.EnumDescriptorProto + parent *Descriptor // The containing message, if any. + typename []string // Cached typename vector. + index int // The index into the container, whether the file or a message. + path string // The SourceCodeInfo path as comma-separated integers. +} + +// TypeName returns the elements of the dotted type name. +// The package name is not part of this name. +func (e *EnumDescriptor) TypeName() (s []string) { + if e.typename != nil { + return e.typename + } + name := e.GetName() + if e.parent == nil { + s = make([]string, 1) + } else { + pname := e.parent.TypeName() + s = make([]string, len(pname)+1) + copy(s, pname) + } + s[len(s)-1] = name + e.typename = s + return s +} + +// Everything but the last element of the full type name, CamelCased. +// The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... . +func (e *EnumDescriptor) prefix() string { + if e.parent == nil { + // If the enum is not part of a message, the prefix is just the type name. + return CamelCase(*e.Name) + "_" + } + typeName := e.TypeName() + return CamelCaseSlice(typeName[0:len(typeName)-1]) + "_" +} + +// The integer value of the named constant in this enumerated type. +func (e *EnumDescriptor) integerValueAsString(name string) string { + for _, c := range e.Value { + if c.GetName() == name { + return fmt.Sprint(c.GetNumber()) + } + } + log.Fatal("cannot find value for enum constant") + return "" +} + +// ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil. +// Otherwise it will be the descriptor of the message in which it is defined. +type ExtensionDescriptor struct { + common + *descriptor.FieldDescriptorProto + parent *Descriptor // The containing message, if any. +} + +// TypeName returns the elements of the dotted type name. +// The package name is not part of this name. +func (e *ExtensionDescriptor) TypeName() (s []string) { + name := e.GetName() + if e.parent == nil { + // top-level extension + s = make([]string, 1) + } else { + pname := e.parent.TypeName() + s = make([]string, len(pname)+1) + copy(s, pname) + } + s[len(s)-1] = name + return s +} + +// DescName returns the variable name used for the generated descriptor. +func (e *ExtensionDescriptor) DescName() string { + // The full type name. + typeName := e.TypeName() + // Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix. + for i, s := range typeName { + typeName[i] = CamelCase(s) + } + return "E_" + strings.Join(typeName, "_") +} + +// ImportedDescriptor describes a type that has been publicly imported from another file. +type ImportedDescriptor struct { + common + o Object +} + +func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() } + +// FileDescriptor describes an protocol buffer descriptor file (.proto). +// It includes slices of all the messages and enums defined within it. +// Those slices are constructed by WrapTypes. +type FileDescriptor struct { + *descriptor.FileDescriptorProto + desc []*Descriptor // All the messages defined in this file. + enum []*EnumDescriptor // All the enums defined in this file. + ext []*ExtensionDescriptor // All the top-level extensions defined in this file. + imp []*ImportedDescriptor // All types defined in files publicly imported by this file. + + // Comments, stored as a map of path (comma-separated integers) to the comment. + comments map[string]*descriptor.SourceCodeInfo_Location + + // The full list of symbols that are exported, + // as a map from the exported object to its symbols. + // This is used for supporting public imports. + exported map[Object][]symbol + + importPath GoImportPath // Import path of this file's package. + packageName GoPackageName // Name of this file's Go package. + + proto3 bool // whether to generate proto3 code for this file +} + +// VarName is the variable name we'll use in the generated code to refer +// to the compressed bytes of this descriptor. It is not exported, so +// it is only valid inside the generated package. +func (d *FileDescriptor) VarName() string { + h := sha256.Sum256([]byte(d.GetName())) + return fmt.Sprintf("fileDescriptor_%s", hex.EncodeToString(h[:8])) +} + +// goPackageOption interprets the file's go_package option. +// If there is no go_package, it returns ("", "", false). +// If there's a simple name, it returns ("", pkg, true). +// If the option implies an import path, it returns (impPath, pkg, true). +func (d *FileDescriptor) goPackageOption() (impPath GoImportPath, pkg GoPackageName, ok bool) { + opt := d.GetOptions().GetGoPackage() + if opt == "" { + return "", "", false + } + // A semicolon-delimited suffix delimits the import path and package name. + sc := strings.Index(opt, ";") + if sc >= 0 { + return GoImportPath(opt[:sc]), cleanPackageName(opt[sc+1:]), true + } + // The presence of a slash implies there's an import path. + slash := strings.LastIndex(opt, "/") + if slash >= 0 { + return GoImportPath(opt), cleanPackageName(opt[slash+1:]), true + } + return "", cleanPackageName(opt), true +} + +// goFileName returns the output name for the generated Go file. +func (d *FileDescriptor) goFileName(pathType pathType) string { + name := *d.Name + if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" { + name = name[:len(name)-len(ext)] + } + name += ".pb.go" + + if pathType == pathTypeSourceRelative { + return name + } + + // Does the file have a "go_package" option? + // If it does, it may override the filename. + if impPath, _, ok := d.goPackageOption(); ok && impPath != "" { + // Replace the existing dirname with the declared import path. + _, name = path.Split(name) + name = path.Join(string(impPath), name) + return name + } + + return name +} + +func (d *FileDescriptor) addExport(obj Object, sym symbol) { + d.exported[obj] = append(d.exported[obj], sym) +} + +// symbol is an interface representing an exported Go symbol. +type symbol interface { + // GenerateAlias should generate an appropriate alias + // for the symbol from the named package. + GenerateAlias(g *Generator, filename string, pkg GoPackageName) +} + +type messageSymbol struct { + sym string + hasExtensions, isMessageSet bool + oneofTypes []string +} + +type getterSymbol struct { + name string + typ string + typeName string // canonical name in proto world; empty for proto.Message and similar + genType bool // whether typ contains a generated type (message/group/enum) +} + +func (ms *messageSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) { + g.P("// ", ms.sym, " from public import ", filename) + g.P("type ", ms.sym, " = ", pkg, ".", ms.sym) + for _, name := range ms.oneofTypes { + g.P("type ", name, " = ", pkg, ".", name) + } +} + +type enumSymbol struct { + name string + proto3 bool // Whether this came from a proto3 file. +} + +func (es enumSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) { + s := es.name + g.P("// ", s, " from public import ", filename) + g.P("type ", s, " = ", pkg, ".", s) + g.P("var ", s, "_name = ", pkg, ".", s, "_name") + g.P("var ", s, "_value = ", pkg, ".", s, "_value") +} + +type constOrVarSymbol struct { + sym string + typ string // either "const" or "var" + cast string // if non-empty, a type cast is required (used for enums) +} + +func (cs constOrVarSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) { + v := string(pkg) + "." + cs.sym + if cs.cast != "" { + v = cs.cast + "(" + v + ")" + } + g.P(cs.typ, " ", cs.sym, " = ", v) +} + +// Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects. +type Object interface { + GoImportPath() GoImportPath + TypeName() []string + File() *FileDescriptor +} + +// Generator is the type whose methods generate the output, stored in the associated response structure. +type Generator struct { + *bytes.Buffer + + Request *plugin.CodeGeneratorRequest // The input. + Response *plugin.CodeGeneratorResponse // The output. + + Param map[string]string // Command-line parameters. + PackageImportPath string // Go import path of the package we're generating code for + ImportPrefix string // String to prefix to imported package file names. + ImportMap map[string]string // Mapping from .proto file name to import path + + Pkg map[string]string // The names under which we import support packages + + outputImportPath GoImportPath // Package we're generating code for. + allFiles []*FileDescriptor // All files in the tree + allFilesByName map[string]*FileDescriptor // All files by filename. + genFiles []*FileDescriptor // Those files we will generate output for. + file *FileDescriptor // The file we are compiling now. + packageNames map[GoImportPath]GoPackageName // Imported package names in the current file. + usedPackages map[GoImportPath]bool // Packages used in current file. + usedPackageNames map[GoPackageName]bool // Package names used in the current file. + addedImports map[GoImportPath]bool // Additional imports to emit. + typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax. + init []string // Lines to emit in the init function. + indent string + pathType pathType // How to generate output filenames. + writeOutput bool + annotateCode bool // whether to store annotations + annotations []*descriptor.GeneratedCodeInfo_Annotation // annotations to store +} + +type pathType int + +const ( + pathTypeImport pathType = iota + pathTypeSourceRelative +) + +// New creates a new generator and allocates the request and response protobufs. +func New() *Generator { + g := new(Generator) + g.Buffer = new(bytes.Buffer) + g.Request = new(plugin.CodeGeneratorRequest) + g.Response = new(plugin.CodeGeneratorResponse) + return g +} + +// Error reports a problem, including an error, and exits the program. +func (g *Generator) Error(err error, msgs ...string) { + s := strings.Join(msgs, " ") + ":" + err.Error() + log.Print("protoc-gen-go: error:", s) + os.Exit(1) +} + +// Fail reports a problem and exits the program. +func (g *Generator) Fail(msgs ...string) { + s := strings.Join(msgs, " ") + log.Print("protoc-gen-go: error:", s) + os.Exit(1) +} + +// CommandLineParameters breaks the comma-separated list of key=value pairs +// in the parameter (a member of the request protobuf) into a key/value map. +// It then sets file name mappings defined by those entries. +func (g *Generator) CommandLineParameters(parameter string) { + g.Param = make(map[string]string) + for _, p := range strings.Split(parameter, ",") { + if i := strings.Index(p, "="); i < 0 { + g.Param[p] = "" + } else { + g.Param[p[0:i]] = p[i+1:] + } + } + + g.ImportMap = make(map[string]string) + pluginList := "none" // Default list of plugin names to enable (empty means all). + for k, v := range g.Param { + switch k { + case "import_prefix": + g.ImportPrefix = v + case "import_path": + g.PackageImportPath = v + case "paths": + switch v { + case "import": + g.pathType = pathTypeImport + case "source_relative": + g.pathType = pathTypeSourceRelative + default: + g.Fail(fmt.Sprintf(`Unknown path type %q: want "import" or "source_relative".`, v)) + } + case "plugins": + pluginList = v + case "annotate_code": + if v == "true" { + g.annotateCode = true + } + default: + if len(k) > 0 && k[0] == 'M' { + g.ImportMap[k[1:]] = v + } + } + } + if pluginList != "" { + // Amend the set of plugins. + enabled := make(map[string]bool) + for _, name := range strings.Split(pluginList, "+") { + enabled[name] = true + } + var nplugins []Plugin + for _, p := range plugins { + if enabled[p.Name()] { + nplugins = append(nplugins, p) + } + } + plugins = nplugins + } +} + +// DefaultPackageName returns the package name printed for the object. +// If its file is in a different package, it returns the package name we're using for this file, plus ".". +// Otherwise it returns the empty string. +func (g *Generator) DefaultPackageName(obj Object) string { + importPath := obj.GoImportPath() + if importPath == g.outputImportPath { + return "" + } + return string(g.GoPackageName(importPath)) + "." +} + +// GoPackageName returns the name used for a package. +func (g *Generator) GoPackageName(importPath GoImportPath) GoPackageName { + if name, ok := g.packageNames[importPath]; ok { + return name + } + name := cleanPackageName(baseName(string(importPath))) + for i, orig := 1, name; g.usedPackageNames[name] || isGoPredeclaredIdentifier[string(name)]; i++ { + name = orig + GoPackageName(strconv.Itoa(i)) + } + g.packageNames[importPath] = name + g.usedPackageNames[name] = true + return name +} + +// AddImport adds a package to the generated file's import section. +// It returns the name used for the package. +func (g *Generator) AddImport(importPath GoImportPath) GoPackageName { + g.addedImports[importPath] = true + return g.GoPackageName(importPath) +} + +var globalPackageNames = map[GoPackageName]bool{ + "fmt": true, + "math": true, + "proto": true, +} + +// Create and remember a guaranteed unique package name. Pkg is the candidate name. +// The FileDescriptor parameter is unused. +func RegisterUniquePackageName(pkg string, f *FileDescriptor) string { + name := cleanPackageName(pkg) + for i, orig := 1, name; globalPackageNames[name]; i++ { + name = orig + GoPackageName(strconv.Itoa(i)) + } + globalPackageNames[name] = true + return string(name) +} + +var isGoKeyword = map[string]bool{ + "break": true, + "case": true, + "chan": true, + "const": true, + "continue": true, + "default": true, + "else": true, + "defer": true, + "fallthrough": true, + "for": true, + "func": true, + "go": true, + "goto": true, + "if": true, + "import": true, + "interface": true, + "map": true, + "package": true, + "range": true, + "return": true, + "select": true, + "struct": true, + "switch": true, + "type": true, + "var": true, +} + +var isGoPredeclaredIdentifier = map[string]bool{ + "append": true, + "bool": true, + "byte": true, + "cap": true, + "close": true, + "complex": true, + "complex128": true, + "complex64": true, + "copy": true, + "delete": true, + "error": true, + "false": true, + "float32": true, + "float64": true, + "imag": true, + "int": true, + "int16": true, + "int32": true, + "int64": true, + "int8": true, + "iota": true, + "len": true, + "make": true, + "new": true, + "nil": true, + "panic": true, + "print": true, + "println": true, + "real": true, + "recover": true, + "rune": true, + "string": true, + "true": true, + "uint": true, + "uint16": true, + "uint32": true, + "uint64": true, + "uint8": true, + "uintptr": true, +} + +func cleanPackageName(name string) GoPackageName { + name = strings.Map(badToUnderscore, name) + // Identifier must not be keyword or predeclared identifier: insert _. + if isGoKeyword[name] { + name = "_" + name + } + // Identifier must not begin with digit: insert _. + if r, _ := utf8.DecodeRuneInString(name); unicode.IsDigit(r) { + name = "_" + name + } + return GoPackageName(name) +} + +// defaultGoPackage returns the package name to use, +// derived from the import path of the package we're building code for. +func (g *Generator) defaultGoPackage() GoPackageName { + p := g.PackageImportPath + if i := strings.LastIndex(p, "/"); i >= 0 { + p = p[i+1:] + } + return cleanPackageName(p) +} + +// SetPackageNames sets the package name for this run. +// The package name must agree across all files being generated. +// It also defines unique package names for all imported files. +func (g *Generator) SetPackageNames() { + g.outputImportPath = g.genFiles[0].importPath + + defaultPackageNames := make(map[GoImportPath]GoPackageName) + for _, f := range g.genFiles { + if _, p, ok := f.goPackageOption(); ok { + defaultPackageNames[f.importPath] = p + } + } + for _, f := range g.genFiles { + if _, p, ok := f.goPackageOption(); ok { + // Source file: option go_package = "quux/bar"; + f.packageName = p + } else if p, ok := defaultPackageNames[f.importPath]; ok { + // A go_package option in another file in the same package. + // + // This is a poor choice in general, since every source file should + // contain a go_package option. Supported mainly for historical + // compatibility. + f.packageName = p + } else if p := g.defaultGoPackage(); p != "" { + // Command-line: import_path=quux/bar. + // + // The import_path flag sets a package name for files which don't + // contain a go_package option. + f.packageName = p + } else if p := f.GetPackage(); p != "" { + // Source file: package quux.bar; + f.packageName = cleanPackageName(p) + } else { + // Source filename. + f.packageName = cleanPackageName(baseName(f.GetName())) + } + } + + // Check that all files have a consistent package name and import path. + for _, f := range g.genFiles[1:] { + if a, b := g.genFiles[0].importPath, f.importPath; a != b { + g.Fail(fmt.Sprintf("inconsistent package import paths: %v, %v", a, b)) + } + if a, b := g.genFiles[0].packageName, f.packageName; a != b { + g.Fail(fmt.Sprintf("inconsistent package names: %v, %v", a, b)) + } + } + + // Names of support packages. These never vary (if there are conflicts, + // we rename the conflicting package), so this could be removed someday. + g.Pkg = map[string]string{ + "fmt": "fmt", + "math": "math", + "proto": "proto", + } +} + +// WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos +// and FileDescriptorProtos into file-referenced objects within the Generator. +// It also creates the list of files to generate and so should be called before GenerateAllFiles. +func (g *Generator) WrapTypes() { + g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile)) + g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles)) + genFileNames := make(map[string]bool) + for _, n := range g.Request.FileToGenerate { + genFileNames[n] = true + } + for _, f := range g.Request.ProtoFile { + fd := &FileDescriptor{ + FileDescriptorProto: f, + exported: make(map[Object][]symbol), + proto3: fileIsProto3(f), + } + // The import path may be set in a number of ways. + if substitution, ok := g.ImportMap[f.GetName()]; ok { + // Command-line: M=foo.proto=quux/bar. + // + // Explicit mapping of source file to import path. + fd.importPath = GoImportPath(substitution) + } else if genFileNames[f.GetName()] && g.PackageImportPath != "" { + // Command-line: import_path=quux/bar. + // + // The import_path flag sets the import path for every file that + // we generate code for. + fd.importPath = GoImportPath(g.PackageImportPath) + } else if p, _, _ := fd.goPackageOption(); p != "" { + // Source file: option go_package = "quux/bar"; + // + // The go_package option sets the import path. Most users should use this. + fd.importPath = p + } else { + // Source filename. + // + // Last resort when nothing else is available. + fd.importPath = GoImportPath(path.Dir(f.GetName())) + } + // We must wrap the descriptors before we wrap the enums + fd.desc = wrapDescriptors(fd) + g.buildNestedDescriptors(fd.desc) + fd.enum = wrapEnumDescriptors(fd, fd.desc) + g.buildNestedEnums(fd.desc, fd.enum) + fd.ext = wrapExtensions(fd) + extractComments(fd) + g.allFiles = append(g.allFiles, fd) + g.allFilesByName[f.GetName()] = fd + } + for _, fd := range g.allFiles { + fd.imp = wrapImported(fd, g) + } + + g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate)) + for _, fileName := range g.Request.FileToGenerate { + fd := g.allFilesByName[fileName] + if fd == nil { + g.Fail("could not find file named", fileName) + } + g.genFiles = append(g.genFiles, fd) + } +} + +// Scan the descriptors in this file. For each one, build the slice of nested descriptors +func (g *Generator) buildNestedDescriptors(descs []*Descriptor) { + for _, desc := range descs { + if len(desc.NestedType) != 0 { + for _, nest := range descs { + if nest.parent == desc { + desc.nested = append(desc.nested, nest) + } + } + if len(desc.nested) != len(desc.NestedType) { + g.Fail("internal error: nesting failure for", desc.GetName()) + } + } + } +} + +func (g *Generator) buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) { + for _, desc := range descs { + if len(desc.EnumType) != 0 { + for _, enum := range enums { + if enum.parent == desc { + desc.enums = append(desc.enums, enum) + } + } + if len(desc.enums) != len(desc.EnumType) { + g.Fail("internal error: enum nesting failure for", desc.GetName()) + } + } + } +} + +// Construct the Descriptor +func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *Descriptor { + d := &Descriptor{ + common: common{file}, + DescriptorProto: desc, + parent: parent, + index: index, + } + if parent == nil { + d.path = fmt.Sprintf("%d,%d", messagePath, index) + } else { + d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index) + } + + // The only way to distinguish a group from a message is whether + // the containing message has a TYPE_GROUP field that matches. + if parent != nil { + parts := d.TypeName() + if file.Package != nil { + parts = append([]string{*file.Package}, parts...) + } + exp := "." + strings.Join(parts, ".") + for _, field := range parent.Field { + if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp { + d.group = true + break + } + } + } + + for _, field := range desc.Extension { + d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d}) + } + + return d +} + +// Return a slice of all the Descriptors defined within this file +func wrapDescriptors(file *FileDescriptor) []*Descriptor { + sl := make([]*Descriptor, 0, len(file.MessageType)+10) + for i, desc := range file.MessageType { + sl = wrapThisDescriptor(sl, desc, nil, file, i) + } + return sl +} + +// Wrap this Descriptor, recursively +func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) []*Descriptor { + sl = append(sl, newDescriptor(desc, parent, file, index)) + me := sl[len(sl)-1] + for i, nested := range desc.NestedType { + sl = wrapThisDescriptor(sl, nested, me, file, i) + } + return sl +} + +// Construct the EnumDescriptor +func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *EnumDescriptor { + ed := &EnumDescriptor{ + common: common{file}, + EnumDescriptorProto: desc, + parent: parent, + index: index, + } + if parent == nil { + ed.path = fmt.Sprintf("%d,%d", enumPath, index) + } else { + ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index) + } + return ed +} + +// Return a slice of all the EnumDescriptors defined within this file +func wrapEnumDescriptors(file *FileDescriptor, descs []*Descriptor) []*EnumDescriptor { + sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10) + // Top-level enums. + for i, enum := range file.EnumType { + sl = append(sl, newEnumDescriptor(enum, nil, file, i)) + } + // Enums within messages. Enums within embedded messages appear in the outer-most message. + for _, nested := range descs { + for i, enum := range nested.EnumType { + sl = append(sl, newEnumDescriptor(enum, nested, file, i)) + } + } + return sl +} + +// Return a slice of all the top-level ExtensionDescriptors defined within this file. +func wrapExtensions(file *FileDescriptor) []*ExtensionDescriptor { + var sl []*ExtensionDescriptor + for _, field := range file.Extension { + sl = append(sl, &ExtensionDescriptor{common{file}, field, nil}) + } + return sl +} + +// Return a slice of all the types that are publicly imported into this file. +func wrapImported(file *FileDescriptor, g *Generator) (sl []*ImportedDescriptor) { + for _, index := range file.PublicDependency { + df := g.fileByName(file.Dependency[index]) + for _, d := range df.desc { + if d.GetOptions().GetMapEntry() { + continue + } + sl = append(sl, &ImportedDescriptor{common{file}, d}) + } + for _, e := range df.enum { + sl = append(sl, &ImportedDescriptor{common{file}, e}) + } + for _, ext := range df.ext { + sl = append(sl, &ImportedDescriptor{common{file}, ext}) + } + } + return +} + +func extractComments(file *FileDescriptor) { + file.comments = make(map[string]*descriptor.SourceCodeInfo_Location) + for _, loc := range file.GetSourceCodeInfo().GetLocation() { + if loc.LeadingComments == nil { + continue + } + var p []string + for _, n := range loc.Path { + p = append(p, strconv.Itoa(int(n))) + } + file.comments[strings.Join(p, ",")] = loc + } +} + +// BuildTypeNameMap builds the map from fully qualified type names to objects. +// The key names for the map come from the input data, which puts a period at the beginning. +// It should be called after SetPackageNames and before GenerateAllFiles. +func (g *Generator) BuildTypeNameMap() { + g.typeNameToObject = make(map[string]Object) + for _, f := range g.allFiles { + // The names in this loop are defined by the proto world, not us, so the + // package name may be empty. If so, the dotted package name of X will + // be ".X"; otherwise it will be ".pkg.X". + dottedPkg := "." + f.GetPackage() + if dottedPkg != "." { + dottedPkg += "." + } + for _, enum := range f.enum { + name := dottedPkg + dottedSlice(enum.TypeName()) + g.typeNameToObject[name] = enum + } + for _, desc := range f.desc { + name := dottedPkg + dottedSlice(desc.TypeName()) + g.typeNameToObject[name] = desc + } + } +} + +// ObjectNamed, given a fully-qualified input type name as it appears in the input data, +// returns the descriptor for the message or enum with that name. +func (g *Generator) ObjectNamed(typeName string) Object { + o, ok := g.typeNameToObject[typeName] + if !ok { + g.Fail("can't find object with type", typeName) + } + return o +} + +// AnnotatedAtoms is a list of atoms (as consumed by P) that records the file name and proto AST path from which they originated. +type AnnotatedAtoms struct { + source string + path string + atoms []interface{} +} + +// Annotate records the file name and proto AST path of a list of atoms +// so that a later call to P can emit a link from each atom to its origin. +func Annotate(file *FileDescriptor, path string, atoms ...interface{}) *AnnotatedAtoms { + return &AnnotatedAtoms{source: *file.Name, path: path, atoms: atoms} +} + +// printAtom prints the (atomic, non-annotation) argument to the generated output. +func (g *Generator) printAtom(v interface{}) { + switch v := v.(type) { + case string: + g.WriteString(v) + case *string: + g.WriteString(*v) + case bool: + fmt.Fprint(g, v) + case *bool: + fmt.Fprint(g, *v) + case int: + fmt.Fprint(g, v) + case *int32: + fmt.Fprint(g, *v) + case *int64: + fmt.Fprint(g, *v) + case float64: + fmt.Fprint(g, v) + case *float64: + fmt.Fprint(g, *v) + case GoPackageName: + g.WriteString(string(v)) + case GoImportPath: + g.WriteString(strconv.Quote(string(v))) + default: + g.Fail(fmt.Sprintf("unknown type in printer: %T", v)) + } +} + +// P prints the arguments to the generated output. It handles strings and int32s, plus +// handling indirections because they may be *string, etc. Any inputs of type AnnotatedAtoms may emit +// annotations in a .meta file in addition to outputting the atoms themselves (if g.annotateCode +// is true). +func (g *Generator) P(str ...interface{}) { + if !g.writeOutput { + return + } + g.WriteString(g.indent) + for _, v := range str { + switch v := v.(type) { + case *AnnotatedAtoms: + begin := int32(g.Len()) + for _, v := range v.atoms { + g.printAtom(v) + } + if g.annotateCode { + end := int32(g.Len()) + var path []int32 + for _, token := range strings.Split(v.path, ",") { + val, err := strconv.ParseInt(token, 10, 32) + if err != nil { + g.Fail("could not parse proto AST path: ", err.Error()) + } + path = append(path, int32(val)) + } + g.annotations = append(g.annotations, &descriptor.GeneratedCodeInfo_Annotation{ + Path: path, + SourceFile: &v.source, + Begin: &begin, + End: &end, + }) + } + default: + g.printAtom(v) + } + } + g.WriteByte('\n') +} + +// addInitf stores the given statement to be printed inside the file's init function. +// The statement is given as a format specifier and arguments. +func (g *Generator) addInitf(stmt string, a ...interface{}) { + g.init = append(g.init, fmt.Sprintf(stmt, a...)) +} + +// In Indents the output one tab stop. +func (g *Generator) In() { g.indent += "\t" } + +// Out unindents the output one tab stop. +func (g *Generator) Out() { + if len(g.indent) > 0 { + g.indent = g.indent[1:] + } +} + +// GenerateAllFiles generates the output for all the files we're outputting. +func (g *Generator) GenerateAllFiles() { + // Initialize the plugins + for _, p := range plugins { + p.Init(g) + } + // Generate the output. The generator runs for every file, even the files + // that we don't generate output for, so that we can collate the full list + // of exported symbols to support public imports. + genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles)) + for _, file := range g.genFiles { + genFileMap[file] = true + } + for _, file := range g.allFiles { + g.Reset() + g.annotations = nil + g.writeOutput = genFileMap[file] + g.generate(file) + if !g.writeOutput { + continue + } + fname := file.goFileName(g.pathType) + g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{ + Name: proto.String(fname), + Content: proto.String(g.String()), + }) + if g.annotateCode { + // Store the generated code annotations in text, as the protoc plugin protocol requires that + // strings contain valid UTF-8. + g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{ + Name: proto.String(file.goFileName(g.pathType) + ".meta"), + Content: proto.String(proto.CompactTextString(&descriptor.GeneratedCodeInfo{Annotation: g.annotations})), + }) + } + } +} + +// Run all the plugins associated with the file. +func (g *Generator) runPlugins(file *FileDescriptor) { + for _, p := range plugins { + p.Generate(file) + } +} + +// Fill the response protocol buffer with the generated output for all the files we're +// supposed to generate. +func (g *Generator) generate(file *FileDescriptor) { + g.file = file + g.usedPackages = make(map[GoImportPath]bool) + g.packageNames = make(map[GoImportPath]GoPackageName) + g.usedPackageNames = make(map[GoPackageName]bool) + g.addedImports = make(map[GoImportPath]bool) + for name := range globalPackageNames { + g.usedPackageNames[name] = true + } + + g.P("// This is a compile-time assertion to ensure that this generated file") + g.P("// is compatible with the proto package it is being compiled against.") + g.P("// A compilation error at this line likely means your copy of the") + g.P("// proto package needs to be updated.") + g.P("const _ = ", g.Pkg["proto"], ".ProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package") + g.P() + + for _, td := range g.file.imp { + g.generateImported(td) + } + for _, enum := range g.file.enum { + g.generateEnum(enum) + } + for _, desc := range g.file.desc { + // Don't generate virtual messages for maps. + if desc.GetOptions().GetMapEntry() { + continue + } + g.generateMessage(desc) + } + for _, ext := range g.file.ext { + g.generateExtension(ext) + } + g.generateInitFunction() + g.generateFileDescriptor(file) + + // Run the plugins before the imports so we know which imports are necessary. + g.runPlugins(file) + + // Generate header and imports last, though they appear first in the output. + rem := g.Buffer + remAnno := g.annotations + g.Buffer = new(bytes.Buffer) + g.annotations = nil + g.generateHeader() + g.generateImports() + if !g.writeOutput { + return + } + // Adjust the offsets for annotations displaced by the header and imports. + for _, anno := range remAnno { + *anno.Begin += int32(g.Len()) + *anno.End += int32(g.Len()) + g.annotations = append(g.annotations, anno) + } + g.Write(rem.Bytes()) + + // Reformat generated code and patch annotation locations. + fset := token.NewFileSet() + original := g.Bytes() + if g.annotateCode { + // make a copy independent of g; we'll need it after Reset. + original = append([]byte(nil), original...) + } + fileAST, err := parser.ParseFile(fset, "", original, parser.ParseComments) + if err != nil { + // Print out the bad code with line numbers. + // This should never happen in practice, but it can while changing generated code, + // so consider this a debugging aid. + var src bytes.Buffer + s := bufio.NewScanner(bytes.NewReader(original)) + for line := 1; s.Scan(); line++ { + fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes()) + } + g.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String()) + } + ast.SortImports(fset, fileAST) + g.Reset() + err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, fileAST) + if err != nil { + g.Fail("generated Go source code could not be reformatted:", err.Error()) + } + if g.annotateCode { + m, err := remap.Compute(original, g.Bytes()) + if err != nil { + g.Fail("formatted generated Go source code could not be mapped back to the original code:", err.Error()) + } + for _, anno := range g.annotations { + new, ok := m.Find(int(*anno.Begin), int(*anno.End)) + if !ok { + g.Fail("span in formatted generated Go source code could not be mapped back to the original code") + } + *anno.Begin = int32(new.Pos) + *anno.End = int32(new.End) + } + } +} + +// Generate the header, including package definition +func (g *Generator) generateHeader() { + g.P("// Code generated by protoc-gen-go. DO NOT EDIT.") + if g.file.GetOptions().GetDeprecated() { + g.P("// ", g.file.Name, " is a deprecated file.") + } else { + g.P("// source: ", g.file.Name) + } + g.P() + g.PrintComments(strconv.Itoa(packagePath)) + g.P() + g.P("package ", g.file.packageName) + g.P() +} + +// deprecationComment is the standard comment added to deprecated +// messages, fields, enums, and enum values. +var deprecationComment = "// Deprecated: Do not use." + +// PrintComments prints any comments from the source .proto file. +// The path is a comma-separated list of integers. +// It returns an indication of whether any comments were printed. +// See descriptor.proto for its format. +func (g *Generator) PrintComments(path string) bool { + if !g.writeOutput { + return false + } + if c, ok := g.makeComments(path); ok { + g.P(c) + return true + } + return false +} + +// makeComments generates the comment string for the field, no "\n" at the end +func (g *Generator) makeComments(path string) (string, bool) { + loc, ok := g.file.comments[path] + if !ok { + return "", false + } + w := new(bytes.Buffer) + nl := "" + for _, line := range strings.Split(strings.TrimSuffix(loc.GetLeadingComments(), "\n"), "\n") { + fmt.Fprintf(w, "%s//%s", nl, line) + nl = "\n" + } + return w.String(), true +} + +func (g *Generator) fileByName(filename string) *FileDescriptor { + return g.allFilesByName[filename] +} + +// weak returns whether the ith import of the current file is a weak import. +func (g *Generator) weak(i int32) bool { + for _, j := range g.file.WeakDependency { + if j == i { + return true + } + } + return false +} + +// Generate the imports +func (g *Generator) generateImports() { + imports := make(map[GoImportPath]GoPackageName) + for i, s := range g.file.Dependency { + fd := g.fileByName(s) + importPath := fd.importPath + // Do not import our own package. + if importPath == g.file.importPath { + continue + } + // Do not import weak imports. + if g.weak(int32(i)) { + continue + } + // Do not import a package twice. + if _, ok := imports[importPath]; ok { + continue + } + // We need to import all the dependencies, even if we don't reference them, + // because other code and tools depend on having the full transitive closure + // of protocol buffer types in the binary. + packageName := g.GoPackageName(importPath) + if _, ok := g.usedPackages[importPath]; !ok { + packageName = "_" + } + imports[importPath] = packageName + } + for importPath := range g.addedImports { + imports[importPath] = g.GoPackageName(importPath) + } + // We almost always need a proto import. Rather than computing when we + // do, which is tricky when there's a plugin, just import it and + // reference it later. The same argument applies to the fmt and math packages. + g.P("import (") + g.P(g.Pkg["fmt"] + ` "fmt"`) + g.P(g.Pkg["math"] + ` "math"`) + g.P(g.Pkg["proto"]+" ", GoImportPath(g.ImportPrefix)+"github.com/golang/protobuf/proto") + for importPath, packageName := range imports { + g.P(packageName, " ", GoImportPath(g.ImportPrefix)+importPath) + } + g.P(")") + g.P() + // TODO: may need to worry about uniqueness across plugins + for _, p := range plugins { + p.GenerateImports(g.file) + g.P() + } + g.P("// Reference imports to suppress errors if they are not otherwise used.") + g.P("var _ = ", g.Pkg["proto"], ".Marshal") + g.P("var _ = ", g.Pkg["fmt"], ".Errorf") + g.P("var _ = ", g.Pkg["math"], ".Inf") + g.P() +} + +func (g *Generator) generateImported(id *ImportedDescriptor) { + df := id.o.File() + filename := *df.Name + if df.importPath == g.file.importPath { + // Don't generate type aliases for files in the same Go package as this one. + return + } + if !supportTypeAliases { + g.Fail(fmt.Sprintf("%s: public imports require at least go1.9", filename)) + } + g.usedPackages[df.importPath] = true + + for _, sym := range df.exported[id.o] { + sym.GenerateAlias(g, filename, g.GoPackageName(df.importPath)) + } + + g.P() +} + +// Generate the enum definitions for this EnumDescriptor. +func (g *Generator) generateEnum(enum *EnumDescriptor) { + // The full type name + typeName := enum.TypeName() + // The full type name, CamelCased. + ccTypeName := CamelCaseSlice(typeName) + ccPrefix := enum.prefix() + + deprecatedEnum := "" + if enum.GetOptions().GetDeprecated() { + deprecatedEnum = deprecationComment + } + g.PrintComments(enum.path) + g.P("type ", Annotate(enum.file, enum.path, ccTypeName), " int32", deprecatedEnum) + g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()}) + g.P("const (") + for i, e := range enum.Value { + etorPath := fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i) + g.PrintComments(etorPath) + + deprecatedValue := "" + if e.GetOptions().GetDeprecated() { + deprecatedValue = deprecationComment + } + + name := ccPrefix + *e.Name + g.P(Annotate(enum.file, etorPath, name), " ", ccTypeName, " = ", e.Number, " ", deprecatedValue) + g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName}) + } + g.P(")") + g.P() + g.P("var ", ccTypeName, "_name = map[int32]string{") + generated := make(map[int32]bool) // avoid duplicate values + for _, e := range enum.Value { + duplicate := "" + if _, present := generated[*e.Number]; present { + duplicate = "// Duplicate value: " + } + g.P(duplicate, e.Number, ": ", strconv.Quote(*e.Name), ",") + generated[*e.Number] = true + } + g.P("}") + g.P() + g.P("var ", ccTypeName, "_value = map[string]int32{") + for _, e := range enum.Value { + g.P(strconv.Quote(*e.Name), ": ", e.Number, ",") + } + g.P("}") + g.P() + + if !enum.proto3() { + g.P("func (x ", ccTypeName, ") Enum() *", ccTypeName, " {") + g.P("p := new(", ccTypeName, ")") + g.P("*p = x") + g.P("return p") + g.P("}") + g.P() + } + + g.P("func (x ", ccTypeName, ") String() string {") + g.P("return ", g.Pkg["proto"], ".EnumName(", ccTypeName, "_name, int32(x))") + g.P("}") + g.P() + + if !enum.proto3() { + g.P("func (x *", ccTypeName, ") UnmarshalJSON(data []byte) error {") + g.P("value, err := ", g.Pkg["proto"], ".UnmarshalJSONEnum(", ccTypeName, `_value, data, "`, ccTypeName, `")`) + g.P("if err != nil {") + g.P("return err") + g.P("}") + g.P("*x = ", ccTypeName, "(value)") + g.P("return nil") + g.P("}") + g.P() + } + + var indexes []string + for m := enum.parent; m != nil; m = m.parent { + // XXX: skip groups? + indexes = append([]string{strconv.Itoa(m.index)}, indexes...) + } + indexes = append(indexes, strconv.Itoa(enum.index)) + g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) {") + g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}") + g.P("}") + g.P() + if enum.file.GetPackage() == "google.protobuf" && enum.GetName() == "NullValue" { + g.P("func (", ccTypeName, `) XXX_WellKnownType() string { return "`, enum.GetName(), `" }`) + g.P() + } + + g.generateEnumRegistration(enum) +} + +// The tag is a string like "varint,2,opt,name=fieldname,def=7" that +// identifies details of the field for the protocol buffer marshaling and unmarshaling +// code. The fields are: +// wire encoding +// protocol tag number +// opt,req,rep for optional, required, or repeated +// packed whether the encoding is "packed" (optional; repeated primitives only) +// name= the original declared name +// enum= the name of the enum type if it is an enum-typed field. +// proto3 if this field is in a proto3 message +// def= string representation of the default value, if any. +// The default value must be in a representation that can be used at run-time +// to generate the default value. Thus bools become 0 and 1, for instance. +func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string { + optrepreq := "" + switch { + case isOptional(field): + optrepreq = "opt" + case isRequired(field): + optrepreq = "req" + case isRepeated(field): + optrepreq = "rep" + } + var defaultValue string + if dv := field.DefaultValue; dv != nil { // set means an explicit default + defaultValue = *dv + // Some types need tweaking. + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_BOOL: + if defaultValue == "true" { + defaultValue = "1" + } else { + defaultValue = "0" + } + case descriptor.FieldDescriptorProto_TYPE_STRING, + descriptor.FieldDescriptorProto_TYPE_BYTES: + // Nothing to do. Quoting is done for the whole tag. + case descriptor.FieldDescriptorProto_TYPE_ENUM: + // For enums we need to provide the integer constant. + obj := g.ObjectNamed(field.GetTypeName()) + if id, ok := obj.(*ImportedDescriptor); ok { + // It is an enum that was publicly imported. + // We need the underlying type. + obj = id.o + } + enum, ok := obj.(*EnumDescriptor) + if !ok { + log.Printf("obj is a %T", obj) + if id, ok := obj.(*ImportedDescriptor); ok { + log.Printf("id.o is a %T", id.o) + } + g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName())) + } + defaultValue = enum.integerValueAsString(defaultValue) + case descriptor.FieldDescriptorProto_TYPE_FLOAT: + if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" { + if f, err := strconv.ParseFloat(defaultValue, 32); err == nil { + defaultValue = fmt.Sprint(float32(f)) + } + } + case descriptor.FieldDescriptorProto_TYPE_DOUBLE: + if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" { + if f, err := strconv.ParseFloat(defaultValue, 64); err == nil { + defaultValue = fmt.Sprint(f) + } + } + } + defaultValue = ",def=" + defaultValue + } + enum := "" + if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM { + // We avoid using obj.GoPackageName(), because we want to use the + // original (proto-world) package name. + obj := g.ObjectNamed(field.GetTypeName()) + if id, ok := obj.(*ImportedDescriptor); ok { + obj = id.o + } + enum = ",enum=" + if pkg := obj.File().GetPackage(); pkg != "" { + enum += pkg + "." + } + enum += CamelCaseSlice(obj.TypeName()) + } + packed := "" + if (field.Options != nil && field.Options.GetPacked()) || + // Per https://developers.google.com/protocol-buffers/docs/proto3#simple: + // "In proto3, repeated fields of scalar numeric types use packed encoding by default." + (message.proto3() && (field.Options == nil || field.Options.Packed == nil) && + isRepeated(field) && isScalar(field)) { + packed = ",packed" + } + fieldName := field.GetName() + name := fieldName + if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP { + // We must use the type name for groups instead of + // the field name to preserve capitalization. + // type_name in FieldDescriptorProto is fully-qualified, + // but we only want the local part. + name = *field.TypeName + if i := strings.LastIndex(name, "."); i >= 0 { + name = name[i+1:] + } + } + if json := field.GetJsonName(); field.Extendee == nil && json != "" && json != name { + // TODO: escaping might be needed, in which case + // perhaps this should be in its own "json" tag. + name += ",json=" + json + } + name = ",name=" + name + if message.proto3() { + name += ",proto3" + } + oneof := "" + if field.OneofIndex != nil { + oneof = ",oneof" + } + return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s", + wiretype, + field.GetNumber(), + optrepreq, + packed, + name, + enum, + oneof, + defaultValue)) +} + +func needsStar(typ descriptor.FieldDescriptorProto_Type) bool { + switch typ { + case descriptor.FieldDescriptorProto_TYPE_GROUP: + return false + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + return false + case descriptor.FieldDescriptorProto_TYPE_BYTES: + return false + } + return true +} + +// TypeName is the printed name appropriate for an item. If the object is in the current file, +// TypeName drops the package name and underscores the rest. +// Otherwise the object is from another package; and the result is the underscored +// package name followed by the item name. +// The result always has an initial capital. +func (g *Generator) TypeName(obj Object) string { + return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName()) +} + +// GoType returns a string representing the type name, and the wire type +func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) { + // TODO: Options. + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_DOUBLE: + typ, wire = "float64", "fixed64" + case descriptor.FieldDescriptorProto_TYPE_FLOAT: + typ, wire = "float32", "fixed32" + case descriptor.FieldDescriptorProto_TYPE_INT64: + typ, wire = "int64", "varint" + case descriptor.FieldDescriptorProto_TYPE_UINT64: + typ, wire = "uint64", "varint" + case descriptor.FieldDescriptorProto_TYPE_INT32: + typ, wire = "int32", "varint" + case descriptor.FieldDescriptorProto_TYPE_UINT32: + typ, wire = "uint32", "varint" + case descriptor.FieldDescriptorProto_TYPE_FIXED64: + typ, wire = "uint64", "fixed64" + case descriptor.FieldDescriptorProto_TYPE_FIXED32: + typ, wire = "uint32", "fixed32" + case descriptor.FieldDescriptorProto_TYPE_BOOL: + typ, wire = "bool", "varint" + case descriptor.FieldDescriptorProto_TYPE_STRING: + typ, wire = "string", "bytes" + case descriptor.FieldDescriptorProto_TYPE_GROUP: + desc := g.ObjectNamed(field.GetTypeName()) + typ, wire = "*"+g.TypeName(desc), "group" + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + desc := g.ObjectNamed(field.GetTypeName()) + typ, wire = "*"+g.TypeName(desc), "bytes" + case descriptor.FieldDescriptorProto_TYPE_BYTES: + typ, wire = "[]byte", "bytes" + case descriptor.FieldDescriptorProto_TYPE_ENUM: + desc := g.ObjectNamed(field.GetTypeName()) + typ, wire = g.TypeName(desc), "varint" + case descriptor.FieldDescriptorProto_TYPE_SFIXED32: + typ, wire = "int32", "fixed32" + case descriptor.FieldDescriptorProto_TYPE_SFIXED64: + typ, wire = "int64", "fixed64" + case descriptor.FieldDescriptorProto_TYPE_SINT32: + typ, wire = "int32", "zigzag32" + case descriptor.FieldDescriptorProto_TYPE_SINT64: + typ, wire = "int64", "zigzag64" + default: + g.Fail("unknown type for", field.GetName()) + } + if isRepeated(field) { + typ = "[]" + typ + } else if message != nil && message.proto3() { + return + } else if field.OneofIndex != nil && message != nil { + return + } else if needsStar(*field.Type) { + typ = "*" + typ + } + return +} + +func (g *Generator) RecordTypeUse(t string) { + if _, ok := g.typeNameToObject[t]; !ok { + return + } + importPath := g.ObjectNamed(t).GoImportPath() + if importPath == g.outputImportPath { + // Don't record use of objects in our package. + return + } + g.AddImport(importPath) + g.usedPackages[importPath] = true +} + +// Method names that may be generated. Fields with these names get an +// underscore appended. Any change to this set is a potential incompatible +// API change because it changes generated field names. +var methodNames = [...]string{ + "Reset", + "String", + "ProtoMessage", + "Marshal", + "Unmarshal", + "ExtensionRangeArray", + "ExtensionMap", + "Descriptor", +} + +// Names of messages in the `google.protobuf` package for which +// we will generate XXX_WellKnownType methods. +var wellKnownTypes = map[string]bool{ + "Any": true, + "Duration": true, + "Empty": true, + "Struct": true, + "Timestamp": true, + + "Value": true, + "ListValue": true, + "DoubleValue": true, + "FloatValue": true, + "Int64Value": true, + "UInt64Value": true, + "Int32Value": true, + "UInt32Value": true, + "BoolValue": true, + "StringValue": true, + "BytesValue": true, +} + +// getterDefault finds the default value for the field to return from a getter, +// regardless of if it's a built in default or explicit from the source. Returns e.g. "nil", `""`, "Default_MessageType_FieldName" +func (g *Generator) getterDefault(field *descriptor.FieldDescriptorProto, goMessageType string) string { + if isRepeated(field) { + return "nil" + } + if def := field.GetDefaultValue(); def != "" { + defaultConstant := g.defaultConstantName(goMessageType, field.GetName()) + if *field.Type != descriptor.FieldDescriptorProto_TYPE_BYTES { + return defaultConstant + } + return "append([]byte(nil), " + defaultConstant + "...)" + } + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_BOOL: + return "false" + case descriptor.FieldDescriptorProto_TYPE_STRING: + return `""` + case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE, descriptor.FieldDescriptorProto_TYPE_BYTES: + return "nil" + case descriptor.FieldDescriptorProto_TYPE_ENUM: + obj := g.ObjectNamed(field.GetTypeName()) + var enum *EnumDescriptor + if id, ok := obj.(*ImportedDescriptor); ok { + // The enum type has been publicly imported. + enum, _ = id.o.(*EnumDescriptor) + } else { + enum, _ = obj.(*EnumDescriptor) + } + if enum == nil { + log.Printf("don't know how to generate getter for %s", field.GetName()) + return "nil" + } + if len(enum.Value) == 0 { + return "0 // empty enum" + } + first := enum.Value[0].GetName() + return g.DefaultPackageName(obj) + enum.prefix() + first + default: + return "0" + } +} + +// defaultConstantName builds the name of the default constant from the message +// type name and the untouched field name, e.g. "Default_MessageType_FieldName" +func (g *Generator) defaultConstantName(goMessageType, protoFieldName string) string { + return "Default_" + goMessageType + "_" + CamelCase(protoFieldName) +} + +// The different types of fields in a message and how to actually print them +// Most of the logic for generateMessage is in the methods of these types. +// +// Note that the content of the field is irrelevant, a simpleField can contain +// anything from a scalar to a group (which is just a message). +// +// Extension fields (and message sets) are however handled separately. +// +// simpleField - a field that is neiter weak nor oneof, possibly repeated +// oneofField - field containing list of subfields: +// - oneofSubField - a field within the oneof + +// msgCtx contains the context for the generator functions. +type msgCtx struct { + goName string // Go struct name of the message, e.g. MessageName + message *Descriptor // The descriptor for the message +} + +// fieldCommon contains data common to all types of fields. +type fieldCommon struct { + goName string // Go name of field, e.g. "FieldName" or "Descriptor_" + protoName string // Name of field in proto language, e.g. "field_name" or "descriptor" + getterName string // Name of the getter, e.g. "GetFieldName" or "GetDescriptor_" + goType string // The Go type as a string, e.g. "*int32" or "*OtherMessage" + tags string // The tag string/annotation for the type, e.g. `protobuf:"varint,8,opt,name=region_id,json=regionId"` + fullPath string // The full path of the field as used by Annotate etc, e.g. "4,0,2,0" +} + +// getProtoName gets the proto name of a field, e.g. "field_name" or "descriptor". +func (f *fieldCommon) getProtoName() string { + return f.protoName +} + +// getGoType returns the go type of the field as a string, e.g. "*int32". +func (f *fieldCommon) getGoType() string { + return f.goType +} + +// simpleField is not weak, not a oneof, not an extension. Can be required, optional or repeated. +type simpleField struct { + fieldCommon + protoTypeName string // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration" + protoType descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64 + deprecated string // Deprecation comment, if any, e.g. "// Deprecated: Do not use." + getterDef string // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName" + protoDef string // Default value as defined in the proto file, e.g "yoshi" or "5" + comment string // The full comment for the field, e.g. "// Useful information" +} + +// decl prints the declaration of the field in the struct (if any). +func (f *simpleField) decl(g *Generator, mc *msgCtx) { + g.P(f.comment, Annotate(mc.message.file, f.fullPath, f.goName), "\t", f.goType, "\t`", f.tags, "`", f.deprecated) +} + +// getter prints the getter for the field. +func (f *simpleField) getter(g *Generator, mc *msgCtx) { + star := "" + tname := f.goType + if needsStar(f.protoType) && tname[0] == '*' { + tname = tname[1:] + star = "*" + } + if f.deprecated != "" { + g.P(f.deprecated) + } + g.P("func (m *", mc.goName, ") ", Annotate(mc.message.file, f.fullPath, f.getterName), "() "+tname+" {") + if f.getterDef == "nil" { // Simpler getter + g.P("if m != nil {") + g.P("return m." + f.goName) + g.P("}") + g.P("return nil") + g.P("}") + g.P() + return + } + if mc.message.proto3() { + g.P("if m != nil {") + } else { + g.P("if m != nil && m." + f.goName + " != nil {") + } + g.P("return " + star + "m." + f.goName) + g.P("}") + g.P("return ", f.getterDef) + g.P("}") + g.P() +} + +// setter prints the setter method of the field. +func (f *simpleField) setter(g *Generator, mc *msgCtx) { + // No setter for regular fields yet +} + +// getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5". +func (f *simpleField) getProtoDef() string { + return f.protoDef +} + +// getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration". +func (f *simpleField) getProtoTypeName() string { + return f.protoTypeName +} + +// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64. +func (f *simpleField) getProtoType() descriptor.FieldDescriptorProto_Type { + return f.protoType +} + +// oneofSubFields are kept slize held by each oneofField. They do not appear in the top level slize of fields for the message. +type oneofSubField struct { + fieldCommon + protoTypeName string // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration" + protoType descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64 + oneofTypeName string // Type name of the enclosing struct, e.g. "MessageName_FieldName" + fieldNumber int // Actual field number, as defined in proto, e.g. 12 + getterDef string // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName" + protoDef string // Default value as defined in the proto file, e.g "yoshi" or "5" + deprecated string // Deprecation comment, if any. +} + +// typedNil prints a nil casted to the pointer to this field. +// - for XXX_OneofWrappers +func (f *oneofSubField) typedNil(g *Generator) { + g.P("(*", f.oneofTypeName, ")(nil),") +} + +// getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5". +func (f *oneofSubField) getProtoDef() string { + return f.protoDef +} + +// getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration". +func (f *oneofSubField) getProtoTypeName() string { + return f.protoTypeName +} + +// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64. +func (f *oneofSubField) getProtoType() descriptor.FieldDescriptorProto_Type { + return f.protoType +} + +// oneofField represents the oneof on top level. +// The alternative fields within the oneof are represented by oneofSubField. +type oneofField struct { + fieldCommon + subFields []*oneofSubField // All the possible oneof fields + comment string // The full comment for the field, e.g. "// Types that are valid to be assigned to MyOneof:\n\\" +} + +// decl prints the declaration of the field in the struct (if any). +func (f *oneofField) decl(g *Generator, mc *msgCtx) { + comment := f.comment + for _, sf := range f.subFields { + comment += "//\t*" + sf.oneofTypeName + "\n" + } + g.P(comment, Annotate(mc.message.file, f.fullPath, f.goName), " ", f.goType, " `", f.tags, "`") +} + +// getter for a oneof field will print additional discriminators and interfaces for the oneof, +// also it prints all the getters for the sub fields. +func (f *oneofField) getter(g *Generator, mc *msgCtx) { + // The discriminator type + g.P("type ", f.goType, " interface {") + g.P(f.goType, "()") + g.P("}") + g.P() + // The subField types, fulfilling the discriminator type contract + for _, sf := range f.subFields { + g.P("type ", Annotate(mc.message.file, sf.fullPath, sf.oneofTypeName), " struct {") + g.P(Annotate(mc.message.file, sf.fullPath, sf.goName), " ", sf.goType, " `", sf.tags, "`") + g.P("}") + g.P() + } + for _, sf := range f.subFields { + g.P("func (*", sf.oneofTypeName, ") ", f.goType, "() {}") + g.P() + } + // Getter for the oneof field + g.P("func (m *", mc.goName, ") ", Annotate(mc.message.file, f.fullPath, f.getterName), "() ", f.goType, " {") + g.P("if m != nil { return m.", f.goName, " }") + g.P("return nil") + g.P("}") + g.P() + // Getters for each oneof + for _, sf := range f.subFields { + if sf.deprecated != "" { + g.P(sf.deprecated) + } + g.P("func (m *", mc.goName, ") ", Annotate(mc.message.file, sf.fullPath, sf.getterName), "() "+sf.goType+" {") + g.P("if x, ok := m.", f.getterName, "().(*", sf.oneofTypeName, "); ok {") + g.P("return x.", sf.goName) + g.P("}") + g.P("return ", sf.getterDef) + g.P("}") + g.P() + } +} + +// setter prints the setter method of the field. +func (f *oneofField) setter(g *Generator, mc *msgCtx) { + // No setters for oneof yet +} + +// topLevelField interface implemented by all types of fields on the top level (not oneofSubField). +type topLevelField interface { + decl(g *Generator, mc *msgCtx) // print declaration within the struct + getter(g *Generator, mc *msgCtx) // print getter + setter(g *Generator, mc *msgCtx) // print setter if applicable +} + +// defField interface implemented by all types of fields that can have defaults (not oneofField, but instead oneofSubField). +type defField interface { + getProtoDef() string // default value explicitly stated in the proto file, e.g "yoshi" or "5" + getProtoName() string // proto name of a field, e.g. "field_name" or "descriptor" + getGoType() string // go type of the field as a string, e.g. "*int32" + getProtoTypeName() string // protobuf type name for the field, e.g. ".google.protobuf.Duration" + getProtoType() descriptor.FieldDescriptorProto_Type // *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64 +} + +// generateDefaultConstants adds constants for default values if needed, which is only if the default value is. +// explicit in the proto. +func (g *Generator) generateDefaultConstants(mc *msgCtx, topLevelFields []topLevelField) { + // Collect fields that can have defaults + dFields := []defField{} + for _, pf := range topLevelFields { + if f, ok := pf.(*oneofField); ok { + for _, osf := range f.subFields { + dFields = append(dFields, osf) + } + continue + } + dFields = append(dFields, pf.(defField)) + } + for _, df := range dFields { + def := df.getProtoDef() + if def == "" { + continue + } + fieldname := g.defaultConstantName(mc.goName, df.getProtoName()) + typename := df.getGoType() + if typename[0] == '*' { + typename = typename[1:] + } + kind := "const " + switch { + case typename == "bool": + case typename == "string": + def = strconv.Quote(def) + case typename == "[]byte": + def = "[]byte(" + strconv.Quote(unescape(def)) + ")" + kind = "var " + case def == "inf", def == "-inf", def == "nan": + // These names are known to, and defined by, the protocol language. + switch def { + case "inf": + def = "math.Inf(1)" + case "-inf": + def = "math.Inf(-1)" + case "nan": + def = "math.NaN()" + } + if df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_FLOAT { + def = "float32(" + def + ")" + } + kind = "var " + case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_FLOAT: + if f, err := strconv.ParseFloat(def, 32); err == nil { + def = fmt.Sprint(float32(f)) + } + case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_DOUBLE: + if f, err := strconv.ParseFloat(def, 64); err == nil { + def = fmt.Sprint(f) + } + case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_ENUM: + // Must be an enum. Need to construct the prefixed name. + obj := g.ObjectNamed(df.getProtoTypeName()) + var enum *EnumDescriptor + if id, ok := obj.(*ImportedDescriptor); ok { + // The enum type has been publicly imported. + enum, _ = id.o.(*EnumDescriptor) + } else { + enum, _ = obj.(*EnumDescriptor) + } + if enum == nil { + log.Printf("don't know how to generate constant for %s", fieldname) + continue + } + def = g.DefaultPackageName(obj) + enum.prefix() + def + } + g.P(kind, fieldname, " ", typename, " = ", def) + g.file.addExport(mc.message, constOrVarSymbol{fieldname, kind, ""}) + } + g.P() +} + +// generateInternalStructFields just adds the XXX_ fields to the message struct. +func (g *Generator) generateInternalStructFields(mc *msgCtx, topLevelFields []topLevelField) { + g.P("XXX_NoUnkeyedLiteral\tstruct{} `json:\"-\"`") // prevent unkeyed struct literals + if len(mc.message.ExtensionRange) > 0 { + messageset := "" + if opts := mc.message.Options; opts != nil && opts.GetMessageSetWireFormat() { + messageset = "protobuf_messageset:\"1\" " + } + g.P(g.Pkg["proto"], ".XXX_InternalExtensions `", messageset, "json:\"-\"`") + } + g.P("XXX_unrecognized\t[]byte `json:\"-\"`") + g.P("XXX_sizecache\tint32 `json:\"-\"`") + +} + +// generateOneofFuncs adds all the utility functions for oneof, including marshalling, unmarshalling and sizer. +func (g *Generator) generateOneofFuncs(mc *msgCtx, topLevelFields []topLevelField) { + ofields := []*oneofField{} + for _, f := range topLevelFields { + if o, ok := f.(*oneofField); ok { + ofields = append(ofields, o) + } + } + if len(ofields) == 0 { + return + } + + // OneofFuncs + g.P("// XXX_OneofWrappers is for the internal use of the proto package.") + g.P("func (*", mc.goName, ") XXX_OneofWrappers() []interface{} {") + g.P("return []interface{}{") + for _, of := range ofields { + for _, sf := range of.subFields { + sf.typedNil(g) + } + } + g.P("}") + g.P("}") + g.P() +} + +// generateMessageStruct adds the actual struct with it's members (but not methods) to the output. +func (g *Generator) generateMessageStruct(mc *msgCtx, topLevelFields []topLevelField) { + comments := g.PrintComments(mc.message.path) + + // Guarantee deprecation comments appear after user-provided comments. + if mc.message.GetOptions().GetDeprecated() { + if comments { + // Convention: Separate deprecation comments from original + // comments with an empty line. + g.P("//") + } + g.P(deprecationComment) + } + + g.P("type ", Annotate(mc.message.file, mc.message.path, mc.goName), " struct {") + for _, pf := range topLevelFields { + pf.decl(g, mc) + } + g.generateInternalStructFields(mc, topLevelFields) + g.P("}") +} + +// generateGetters adds getters for all fields, including oneofs and weak fields when applicable. +func (g *Generator) generateGetters(mc *msgCtx, topLevelFields []topLevelField) { + for _, pf := range topLevelFields { + pf.getter(g, mc) + } +} + +// generateSetters add setters for all fields, including oneofs and weak fields when applicable. +func (g *Generator) generateSetters(mc *msgCtx, topLevelFields []topLevelField) { + for _, pf := range topLevelFields { + pf.setter(g, mc) + } +} + +// generateCommonMethods adds methods to the message that are not on a per field basis. +func (g *Generator) generateCommonMethods(mc *msgCtx) { + // Reset, String and ProtoMessage methods. + g.P("func (m *", mc.goName, ") Reset() { *m = ", mc.goName, "{} }") + g.P("func (m *", mc.goName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }") + g.P("func (*", mc.goName, ") ProtoMessage() {}") + var indexes []string + for m := mc.message; m != nil; m = m.parent { + indexes = append([]string{strconv.Itoa(m.index)}, indexes...) + } + g.P("func (*", mc.goName, ") Descriptor() ([]byte, []int) {") + g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}") + g.P("}") + g.P() + // TODO: Revisit the decision to use a XXX_WellKnownType method + // if we change proto.MessageName to work with multiple equivalents. + if mc.message.file.GetPackage() == "google.protobuf" && wellKnownTypes[mc.message.GetName()] { + g.P("func (*", mc.goName, `) XXX_WellKnownType() string { return "`, mc.message.GetName(), `" }`) + g.P() + } + + // Extension support methods + if len(mc.message.ExtensionRange) > 0 { + g.P() + g.P("var extRange_", mc.goName, " = []", g.Pkg["proto"], ".ExtensionRange{") + for _, r := range mc.message.ExtensionRange { + end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends + g.P("{Start: ", r.Start, ", End: ", end, "},") + } + g.P("}") + g.P("func (*", mc.goName, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange {") + g.P("return extRange_", mc.goName) + g.P("}") + g.P() + } + + // TODO: It does not scale to keep adding another method for every + // operation on protos that we want to switch over to using the + // table-driven approach. Instead, we should only add a single method + // that allows getting access to the *InternalMessageInfo struct and then + // calling Unmarshal, Marshal, Merge, Size, and Discard directly on that. + + // Wrapper for table-driven marshaling and unmarshaling. + g.P("func (m *", mc.goName, ") XXX_Unmarshal(b []byte) error {") + g.P("return xxx_messageInfo_", mc.goName, ".Unmarshal(m, b)") + g.P("}") + + g.P("func (m *", mc.goName, ") XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {") + g.P("return xxx_messageInfo_", mc.goName, ".Marshal(b, m, deterministic)") + g.P("}") + + g.P("func (m *", mc.goName, ") XXX_Merge(src ", g.Pkg["proto"], ".Message) {") + g.P("xxx_messageInfo_", mc.goName, ".Merge(m, src)") + g.P("}") + + g.P("func (m *", mc.goName, ") XXX_Size() int {") // avoid name clash with "Size" field in some message + g.P("return xxx_messageInfo_", mc.goName, ".Size(m)") + g.P("}") + + g.P("func (m *", mc.goName, ") XXX_DiscardUnknown() {") + g.P("xxx_messageInfo_", mc.goName, ".DiscardUnknown(m)") + g.P("}") + + g.P("var xxx_messageInfo_", mc.goName, " ", g.Pkg["proto"], ".InternalMessageInfo") + g.P() +} + +// Generate the type, methods and default constant definitions for this Descriptor. +func (g *Generator) generateMessage(message *Descriptor) { + topLevelFields := []topLevelField{} + oFields := make(map[int32]*oneofField) + // The full type name + typeName := message.TypeName() + // The full type name, CamelCased. + goTypeName := CamelCaseSlice(typeName) + + usedNames := make(map[string]bool) + for _, n := range methodNames { + usedNames[n] = true + } + + // allocNames finds a conflict-free variation of the given strings, + // consistently mutating their suffixes. + // It returns the same number of strings. + allocNames := func(ns ...string) []string { + Loop: + for { + for _, n := range ns { + if usedNames[n] { + for i := range ns { + ns[i] += "_" + } + continue Loop + } + } + for _, n := range ns { + usedNames[n] = true + } + return ns + } + } + + mapFieldTypes := make(map[*descriptor.FieldDescriptorProto]string) // keep track of the map fields to be added later + + // Build a structure more suitable for generating the text in one pass + for i, field := range message.Field { + // Allocate the getter and the field at the same time so name + // collisions create field/method consistent names. + // TODO: This allocation occurs based on the order of the fields + // in the proto file, meaning that a change in the field + // ordering can change generated Method/Field names. + base := CamelCase(*field.Name) + ns := allocNames(base, "Get"+base) + fieldName, fieldGetterName := ns[0], ns[1] + typename, wiretype := g.GoType(message, field) + jsonName := *field.Name + tag := fmt.Sprintf("protobuf:%s json:%q", g.goTag(message, field, wiretype), jsonName+",omitempty") + + oneof := field.OneofIndex != nil + if oneof && oFields[*field.OneofIndex] == nil { + odp := message.OneofDecl[int(*field.OneofIndex)] + base := CamelCase(odp.GetName()) + fname := allocNames(base)[0] + + // This is the first field of a oneof we haven't seen before. + // Generate the union field. + oneofFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex) + c, ok := g.makeComments(oneofFullPath) + if ok { + c += "\n//\n" + } + c += "// Types that are valid to be assigned to " + fname + ":\n" + // Generate the rest of this comment later, + // when we've computed any disambiguation. + + dname := "is" + goTypeName + "_" + fname + tag := `protobuf_oneof:"` + odp.GetName() + `"` + of := oneofField{ + fieldCommon: fieldCommon{ + goName: fname, + getterName: "Get"+fname, + goType: dname, + tags: tag, + protoName: odp.GetName(), + fullPath: oneofFullPath, + }, + comment: c, + } + topLevelFields = append(topLevelFields, &of) + oFields[*field.OneofIndex] = &of + } + + if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE { + desc := g.ObjectNamed(field.GetTypeName()) + if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() { + // Figure out the Go types and tags for the key and value types. + keyField, valField := d.Field[0], d.Field[1] + keyType, keyWire := g.GoType(d, keyField) + valType, valWire := g.GoType(d, valField) + keyTag, valTag := g.goTag(d, keyField, keyWire), g.goTag(d, valField, valWire) + + // We don't use stars, except for message-typed values. + // Message and enum types are the only two possibly foreign types used in maps, + // so record their use. They are not permitted as map keys. + keyType = strings.TrimPrefix(keyType, "*") + switch *valField.Type { + case descriptor.FieldDescriptorProto_TYPE_ENUM: + valType = strings.TrimPrefix(valType, "*") + g.RecordTypeUse(valField.GetTypeName()) + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + g.RecordTypeUse(valField.GetTypeName()) + default: + valType = strings.TrimPrefix(valType, "*") + } + + typename = fmt.Sprintf("map[%s]%s", keyType, valType) + mapFieldTypes[field] = typename // record for the getter generation + + tag += fmt.Sprintf(" protobuf_key:%s protobuf_val:%s", keyTag, valTag) + } + } + + fieldDeprecated := "" + if field.GetOptions().GetDeprecated() { + fieldDeprecated = deprecationComment + } + + dvalue := g.getterDefault(field, goTypeName) + if oneof { + tname := goTypeName + "_" + fieldName + // It is possible for this to collide with a message or enum + // nested in this message. Check for collisions. + for { + ok := true + for _, desc := range message.nested { + if CamelCaseSlice(desc.TypeName()) == tname { + ok = false + break + } + } + for _, enum := range message.enums { + if CamelCaseSlice(enum.TypeName()) == tname { + ok = false + break + } + } + if !ok { + tname += "_" + continue + } + break + } + + oneofField := oFields[*field.OneofIndex] + tag := "protobuf:" + g.goTag(message, field, wiretype) + sf := oneofSubField{ + fieldCommon: fieldCommon{ + goName: fieldName, + getterName: fieldGetterName, + goType: typename, + tags: tag, + protoName: field.GetName(), + fullPath: fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i), + }, + protoTypeName: field.GetTypeName(), + fieldNumber: int(*field.Number), + protoType: *field.Type, + getterDef: dvalue, + protoDef: field.GetDefaultValue(), + oneofTypeName: tname, + deprecated: fieldDeprecated, + } + oneofField.subFields = append(oneofField.subFields, &sf) + g.RecordTypeUse(field.GetTypeName()) + continue + } + + fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i) + c, ok := g.makeComments(fieldFullPath) + if ok { + c += "\n" + } + rf := simpleField{ + fieldCommon: fieldCommon{ + goName: fieldName, + getterName: fieldGetterName, + goType: typename, + tags: tag, + protoName: field.GetName(), + fullPath: fieldFullPath, + }, + protoTypeName: field.GetTypeName(), + protoType: *field.Type, + deprecated: fieldDeprecated, + getterDef: dvalue, + protoDef: field.GetDefaultValue(), + comment: c, + } + var pf topLevelField = &rf + + topLevelFields = append(topLevelFields, pf) + g.RecordTypeUse(field.GetTypeName()) + } + + mc := &msgCtx{ + goName: goTypeName, + message: message, + } + + g.generateMessageStruct(mc, topLevelFields) + g.P() + g.generateCommonMethods(mc) + g.P() + g.generateDefaultConstants(mc, topLevelFields) + g.P() + g.generateGetters(mc, topLevelFields) + g.P() + g.generateSetters(mc, topLevelFields) + g.P() + g.generateOneofFuncs(mc, topLevelFields) + g.P() + + var oneofTypes []string + for _, f := range topLevelFields { + if of, ok := f.(*oneofField); ok { + for _, osf := range of.subFields { + oneofTypes = append(oneofTypes, osf.oneofTypeName) + } + } + } + + opts := message.Options + ms := &messageSymbol{ + sym: goTypeName, + hasExtensions: len(message.ExtensionRange) > 0, + isMessageSet: opts != nil && opts.GetMessageSetWireFormat(), + oneofTypes: oneofTypes, + } + g.file.addExport(message, ms) + + for _, ext := range message.ext { + g.generateExtension(ext) + } + + fullName := strings.Join(message.TypeName(), ".") + if g.file.Package != nil { + fullName = *g.file.Package + "." + fullName + } + + g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], goTypeName, fullName) + // Register types for native map types. + for _, k := range mapFieldKeys(mapFieldTypes) { + fullName := strings.TrimPrefix(*k.TypeName, ".") + g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["proto"], mapFieldTypes[k], fullName) + } + +} + +type byTypeName []*descriptor.FieldDescriptorProto + +func (a byTypeName) Len() int { return len(a) } +func (a byTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byTypeName) Less(i, j int) bool { return *a[i].TypeName < *a[j].TypeName } + +// mapFieldKeys returns the keys of m in a consistent order. +func mapFieldKeys(m map[*descriptor.FieldDescriptorProto]string) []*descriptor.FieldDescriptorProto { + keys := make([]*descriptor.FieldDescriptorProto, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + sort.Sort(byTypeName(keys)) + return keys +} + +var escapeChars = [256]byte{ + 'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v', '\\': '\\', '"': '"', '\'': '\'', '?': '?', +} + +// unescape reverses the "C" escaping that protoc does for default values of bytes fields. +// It is best effort in that it effectively ignores malformed input. Seemingly invalid escape +// sequences are conveyed, unmodified, into the decoded result. +func unescape(s string) string { + // NB: Sadly, we can't use strconv.Unquote because protoc will escape both + // single and double quotes, but strconv.Unquote only allows one or the + // other (based on actual surrounding quotes of its input argument). + + var out []byte + for len(s) > 0 { + // regular character, or too short to be valid escape + if s[0] != '\\' || len(s) < 2 { + out = append(out, s[0]) + s = s[1:] + } else if c := escapeChars[s[1]]; c != 0 { + // escape sequence + out = append(out, c) + s = s[2:] + } else if s[1] == 'x' || s[1] == 'X' { + // hex escape, e.g. "\x80 + if len(s) < 4 { + // too short to be valid + out = append(out, s[:2]...) + s = s[2:] + continue + } + v, err := strconv.ParseUint(s[2:4], 16, 8) + if err != nil { + out = append(out, s[:4]...) + } else { + out = append(out, byte(v)) + } + s = s[4:] + } else if '0' <= s[1] && s[1] <= '7' { + // octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164" + // so consume up to 2 more bytes or up to end-of-string + n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567")) + if n > 3 { + n = 3 + } + v, err := strconv.ParseUint(s[1:1+n], 8, 8) + if err != nil { + out = append(out, s[:1+n]...) + } else { + out = append(out, byte(v)) + } + s = s[1+n:] + } else { + // bad escape, just propagate the slash as-is + out = append(out, s[0]) + s = s[1:] + } + } + + return string(out) +} + +func (g *Generator) generateExtension(ext *ExtensionDescriptor) { + ccTypeName := ext.DescName() + + extObj := g.ObjectNamed(*ext.Extendee) + var extDesc *Descriptor + if id, ok := extObj.(*ImportedDescriptor); ok { + // This is extending a publicly imported message. + // We need the underlying type for goTag. + extDesc = id.o.(*Descriptor) + } else { + extDesc = extObj.(*Descriptor) + } + extendedType := "*" + g.TypeName(extObj) // always use the original + field := ext.FieldDescriptorProto + fieldType, wireType := g.GoType(ext.parent, field) + tag := g.goTag(extDesc, field, wireType) + g.RecordTypeUse(*ext.Extendee) + if n := ext.FieldDescriptorProto.TypeName; n != nil { + // foreign extension type + g.RecordTypeUse(*n) + } + + typeName := ext.TypeName() + + // Special case for proto2 message sets: If this extension is extending + // proto2.bridge.MessageSet, and its final name component is "message_set_extension", + // then drop that last component. + // + // TODO: This should be implemented in the text formatter rather than the generator. + // In addition, the situation for when to apply this special case is implemented + // differently in other languages: + // https://github.com/google/protobuf/blob/aff10976/src/google/protobuf/text_format.cc#L1560 + if extDesc.GetOptions().GetMessageSetWireFormat() && typeName[len(typeName)-1] == "message_set_extension" { + typeName = typeName[:len(typeName)-1] + } + + // For text formatting, the package must be exactly what the .proto file declares, + // ignoring overrides such as the go_package option, and with no dot/underscore mapping. + extName := strings.Join(typeName, ".") + if g.file.Package != nil { + extName = *g.file.Package + "." + extName + } + + g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{") + g.P("ExtendedType: (", extendedType, ")(nil),") + g.P("ExtensionType: (", fieldType, ")(nil),") + g.P("Field: ", field.Number, ",") + g.P(`Name: "`, extName, `",`) + g.P("Tag: ", tag, ",") + g.P(`Filename: "`, g.file.GetName(), `",`) + + g.P("}") + g.P() + + g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName()) + + g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""}) +} + +func (g *Generator) generateInitFunction() { + if len(g.init) == 0 { + return + } + g.P("func init() {") + for _, l := range g.init { + g.P(l) + } + g.P("}") + g.init = nil +} + +func (g *Generator) generateFileDescriptor(file *FileDescriptor) { + // Make a copy and trim source_code_info data. + // TODO: Trim this more when we know exactly what we need. + pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto) + pb.SourceCodeInfo = nil + + b, err := proto.Marshal(pb) + if err != nil { + g.Fail(err.Error()) + } + + var buf bytes.Buffer + w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression) + w.Write(b) + w.Close() + b = buf.Bytes() + + v := file.VarName() + g.P() + g.P("func init() { ", g.Pkg["proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }") + g.P("var ", v, " = []byte{") + g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto") + for len(b) > 0 { + n := 16 + if n > len(b) { + n = len(b) + } + + s := "" + for _, c := range b[:n] { + s += fmt.Sprintf("0x%02x,", c) + } + g.P(s) + + b = b[n:] + } + g.P("}") +} + +func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) { + // // We always print the full (proto-world) package name here. + pkg := enum.File().GetPackage() + if pkg != "" { + pkg += "." + } + // The full type name + typeName := enum.TypeName() + // The full type name, CamelCased. + ccTypeName := CamelCaseSlice(typeName) + g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["proto"], pkg+ccTypeName, ccTypeName) +} + +// And now lots of helper functions. + +// Is c an ASCII lower-case letter? +func isASCIILower(c byte) bool { + return 'a' <= c && c <= 'z' +} + +// Is c an ASCII digit? +func isASCIIDigit(c byte) bool { + return '0' <= c && c <= '9' +} + +// CamelCase returns the CamelCased name. +// If there is an interior underscore followed by a lower case letter, +// drop the underscore and convert the letter to upper case. +// There is a remote possibility of this rewrite causing a name collision, +// but it's so remote we're prepared to pretend it's nonexistent - since the +// C++ generator lowercases names, it's extremely unlikely to have two fields +// with different capitalizations. +// In short, _my_field_name_2 becomes XMyFieldName_2. +func CamelCase(s string) string { + if s == "" { + return "" + } + t := make([]byte, 0, 32) + i := 0 + if s[0] == '_' { + // Need a capital letter; drop the '_'. + t = append(t, 'X') + i++ + } + // Invariant: if the next letter is lower case, it must be converted + // to upper case. + // That is, we process a word at a time, where words are marked by _ or + // upper case letter. Digits are treated as words. + for ; i < len(s); i++ { + c := s[i] + if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) { + continue // Skip the underscore in s. + } + if isASCIIDigit(c) { + t = append(t, c) + continue + } + // Assume we have a letter now - if not, it's a bogus identifier. + // The next word is a sequence of characters that must start upper case. + if isASCIILower(c) { + c ^= ' ' // Make it a capital letter. + } + t = append(t, c) // Guaranteed not lower case. + // Accept lower case sequence that follows. + for i+1 < len(s) && isASCIILower(s[i+1]) { + i++ + t = append(t, s[i]) + } + } + return string(t) +} + +// CamelCaseSlice is like CamelCase, but the argument is a slice of strings to +// be joined with "_". +func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) } + +// dottedSlice turns a sliced name into a dotted name. +func dottedSlice(elem []string) string { return strings.Join(elem, ".") } + +// Is this field optional? +func isOptional(field *descriptor.FieldDescriptorProto) bool { + return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL +} + +// Is this field required? +func isRequired(field *descriptor.FieldDescriptorProto) bool { + return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED +} + +// Is this field repeated? +func isRepeated(field *descriptor.FieldDescriptorProto) bool { + return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED +} + +// Is this field a scalar numeric type? +func isScalar(field *descriptor.FieldDescriptorProto) bool { + if field.Type == nil { + return false + } + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_DOUBLE, + descriptor.FieldDescriptorProto_TYPE_FLOAT, + descriptor.FieldDescriptorProto_TYPE_INT64, + descriptor.FieldDescriptorProto_TYPE_UINT64, + descriptor.FieldDescriptorProto_TYPE_INT32, + descriptor.FieldDescriptorProto_TYPE_FIXED64, + descriptor.FieldDescriptorProto_TYPE_FIXED32, + descriptor.FieldDescriptorProto_TYPE_BOOL, + descriptor.FieldDescriptorProto_TYPE_UINT32, + descriptor.FieldDescriptorProto_TYPE_ENUM, + descriptor.FieldDescriptorProto_TYPE_SFIXED32, + descriptor.FieldDescriptorProto_TYPE_SFIXED64, + descriptor.FieldDescriptorProto_TYPE_SINT32, + descriptor.FieldDescriptorProto_TYPE_SINT64: + return true + default: + return false + } +} + +// badToUnderscore is the mapping function used to generate Go names from package names, +// which can be dotted in the input .proto file. It replaces non-identifier characters such as +// dot or dash with underscore. +func badToUnderscore(r rune) rune { + if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' { + return r + } + return '_' +} + +// baseName returns the last path element of the name, with the last dotted suffix removed. +func baseName(name string) string { + // First, find the last element + if i := strings.LastIndex(name, "/"); i >= 0 { + name = name[i+1:] + } + // Now drop the suffix + if i := strings.LastIndex(name, "."); i >= 0 { + name = name[0:i] + } + return name +} + +// The SourceCodeInfo message describes the location of elements of a parsed +// .proto file by way of a "path", which is a sequence of integers that +// describe the route from a FileDescriptorProto to the relevant submessage. +// The path alternates between a field number of a repeated field, and an index +// into that repeated field. The constants below define the field numbers that +// are used. +// +// See descriptor.proto for more information about this. +const ( + // tag numbers in FileDescriptorProto + packagePath = 2 // package + messagePath = 4 // message_type + enumPath = 5 // enum_type + // tag numbers in DescriptorProto + messageFieldPath = 2 // field + messageMessagePath = 3 // nested_type + messageEnumPath = 4 // enum_type + messageOneofPath = 8 // oneof_decl + // tag numbers in EnumDescriptorProto + enumValuePath = 2 // value +) + +var supportTypeAliases bool + +func init() { + for _, tag := range build.Default.ReleaseTags { + if tag == "go1.9" { + supportTypeAliases = true + return + } + } +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/generator/internal/remap/remap.go b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/internal/remap/remap.go new file mode 100644 index 0000000000..a9b61036cc --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/internal/remap/remap.go @@ -0,0 +1,117 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2017 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Package remap handles tracking the locations of Go tokens in a source text +across a rewrite by the Go formatter. +*/ +package remap + +import ( + "fmt" + "go/scanner" + "go/token" +) + +// A Location represents a span of byte offsets in the source text. +type Location struct { + Pos, End int // End is exclusive +} + +// A Map represents a mapping between token locations in an input source text +// and locations in the correspnding output text. +type Map map[Location]Location + +// Find reports whether the specified span is recorded by m, and if so returns +// the new location it was mapped to. If the input span was not found, the +// returned location is the same as the input. +func (m Map) Find(pos, end int) (Location, bool) { + key := Location{ + Pos: pos, + End: end, + } + if loc, ok := m[key]; ok { + return loc, true + } + return key, false +} + +func (m Map) add(opos, oend, npos, nend int) { + m[Location{Pos: opos, End: oend}] = Location{Pos: npos, End: nend} +} + +// Compute constructs a location mapping from input to output. An error is +// reported if any of the tokens of output cannot be mapped. +func Compute(input, output []byte) (Map, error) { + itok := tokenize(input) + otok := tokenize(output) + if len(itok) != len(otok) { + return nil, fmt.Errorf("wrong number of tokens, %d ≠ %d", len(itok), len(otok)) + } + m := make(Map) + for i, ti := range itok { + to := otok[i] + if ti.Token != to.Token { + return nil, fmt.Errorf("token %d type mismatch: %s ≠ %s", i+1, ti, to) + } + m.add(ti.pos, ti.end, to.pos, to.end) + } + return m, nil +} + +// tokinfo records the span and type of a source token. +type tokinfo struct { + pos, end int + token.Token +} + +func tokenize(src []byte) []tokinfo { + fs := token.NewFileSet() + var s scanner.Scanner + s.Init(fs.AddFile("src", fs.Base(), len(src)), src, nil, scanner.ScanComments) + var info []tokinfo + for { + pos, next, lit := s.Scan() + switch next { + case token.SEMICOLON: + continue + } + info = append(info, tokinfo{ + pos: int(pos - 1), + end: int(pos + token.Pos(len(lit)) - 1), + Token: next, + }) + if next == token.EOF { + break + } + } + return info +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go b/vendor/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go new file mode 100644 index 0000000000..5d1e3f0f61 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go @@ -0,0 +1,537 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Package grpc outputs gRPC service descriptions in Go code. +// It runs as a plugin for the Go protocol buffer compiler plugin. +// It is linked in to protoc-gen-go. +package grpc + +import ( + "fmt" + "strconv" + "strings" + + pb "github.com/golang/protobuf/protoc-gen-go/descriptor" + "github.com/golang/protobuf/protoc-gen-go/generator" +) + +// generatedCodeVersion indicates a version of the generated code. +// It is incremented whenever an incompatibility between the generated code and +// the grpc package is introduced; the generated code references +// a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion). +const generatedCodeVersion = 4 + +// Paths for packages used by code generated in this file, +// relative to the import_prefix of the generator.Generator. +const ( + contextPkgPath = "context" + grpcPkgPath = "google.golang.org/grpc" + codePkgPath = "google.golang.org/grpc/codes" + statusPkgPath = "google.golang.org/grpc/status" +) + +func init() { + generator.RegisterPlugin(new(grpc)) +} + +// grpc is an implementation of the Go protocol buffer compiler's +// plugin architecture. It generates bindings for gRPC support. +type grpc struct { + gen *generator.Generator +} + +// Name returns the name of this plugin, "grpc". +func (g *grpc) Name() string { + return "grpc" +} + +// The names for packages imported in the generated code. +// They may vary from the final path component of the import path +// if the name is used by other packages. +var ( + contextPkg string + grpcPkg string +) + +// Init initializes the plugin. +func (g *grpc) Init(gen *generator.Generator) { + g.gen = gen +} + +// Given a type name defined in a .proto, return its object. +// Also record that we're using it, to guarantee the associated import. +func (g *grpc) objectNamed(name string) generator.Object { + g.gen.RecordTypeUse(name) + return g.gen.ObjectNamed(name) +} + +// Given a type name defined in a .proto, return its name as we will print it. +func (g *grpc) typeName(str string) string { + return g.gen.TypeName(g.objectNamed(str)) +} + +// P forwards to g.gen.P. +func (g *grpc) P(args ...interface{}) { g.gen.P(args...) } + +// Generate generates code for the services in the given file. +func (g *grpc) Generate(file *generator.FileDescriptor) { + if len(file.FileDescriptorProto.Service) == 0 { + return + } + + contextPkg = string(g.gen.AddImport(contextPkgPath)) + grpcPkg = string(g.gen.AddImport(grpcPkgPath)) + + g.P("// Reference imports to suppress errors if they are not otherwise used.") + g.P("var _ ", contextPkg, ".Context") + g.P("var _ ", grpcPkg, ".ClientConn") + g.P() + + // Assert version compatibility. + g.P("// This is a compile-time assertion to ensure that this generated file") + g.P("// is compatible with the grpc package it is being compiled against.") + g.P("const _ = ", grpcPkg, ".SupportPackageIsVersion", generatedCodeVersion) + g.P() + + for i, service := range file.FileDescriptorProto.Service { + g.generateService(file, service, i) + } +} + +// GenerateImports generates the import declaration for this file. +func (g *grpc) GenerateImports(file *generator.FileDescriptor) { +} + +// reservedClientName records whether a client name is reserved on the client side. +var reservedClientName = map[string]bool{ + // TODO: do we need any in gRPC? +} + +func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] } + +// deprecationComment is the standard comment added to deprecated +// messages, fields, enums, and enum values. +var deprecationComment = "// Deprecated: Do not use." + +// generateService generates all the code for the named service. +func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) { + path := fmt.Sprintf("6,%d", index) // 6 means service. + + origServName := service.GetName() + fullServName := origServName + if pkg := file.GetPackage(); pkg != "" { + fullServName = pkg + "." + fullServName + } + servName := generator.CamelCase(origServName) + deprecated := service.GetOptions().GetDeprecated() + + g.P() + g.P(fmt.Sprintf(`// %sClient is the client API for %s service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.`, servName, servName)) + + // Client interface. + if deprecated { + g.P("//") + g.P(deprecationComment) + } + g.P("type ", servName, "Client interface {") + for i, method := range service.Method { + g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service. + g.P(g.generateClientSignature(servName, method)) + } + g.P("}") + g.P() + + // Client structure. + g.P("type ", unexport(servName), "Client struct {") + g.P("cc *", grpcPkg, ".ClientConn") + g.P("}") + g.P() + + // NewClient factory. + if deprecated { + g.P(deprecationComment) + } + g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {") + g.P("return &", unexport(servName), "Client{cc}") + g.P("}") + g.P() + + var methodIndex, streamIndex int + serviceDescVar := "_" + servName + "_serviceDesc" + // Client method implementations. + for _, method := range service.Method { + var descExpr string + if !method.GetServerStreaming() && !method.GetClientStreaming() { + // Unary RPC method + descExpr = fmt.Sprintf("&%s.Methods[%d]", serviceDescVar, methodIndex) + methodIndex++ + } else { + // Streaming RPC method + descExpr = fmt.Sprintf("&%s.Streams[%d]", serviceDescVar, streamIndex) + streamIndex++ + } + g.generateClientMethod(servName, fullServName, serviceDescVar, method, descExpr) + } + + // Server interface. + serverType := servName + "Server" + g.P("// ", serverType, " is the server API for ", servName, " service.") + if deprecated { + g.P("//") + g.P(deprecationComment) + } + g.P("type ", serverType, " interface {") + for i, method := range service.Method { + g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service. + g.P(g.generateServerSignature(servName, method)) + } + g.P("}") + g.P() + + // Server Unimplemented struct for forward compatability. + if deprecated { + g.P(deprecationComment) + } + g.generateUnimplementedServer(servName, service) + + // Server registration. + if deprecated { + g.P(deprecationComment) + } + g.P("func Register", servName, "Server(s *", grpcPkg, ".Server, srv ", serverType, ") {") + g.P("s.RegisterService(&", serviceDescVar, `, srv)`) + g.P("}") + g.P() + + // Server handler implementations. + var handlerNames []string + for _, method := range service.Method { + hname := g.generateServerMethod(servName, fullServName, method) + handlerNames = append(handlerNames, hname) + } + + // Service descriptor. + g.P("var ", serviceDescVar, " = ", grpcPkg, ".ServiceDesc {") + g.P("ServiceName: ", strconv.Quote(fullServName), ",") + g.P("HandlerType: (*", serverType, ")(nil),") + g.P("Methods: []", grpcPkg, ".MethodDesc{") + for i, method := range service.Method { + if method.GetServerStreaming() || method.GetClientStreaming() { + continue + } + g.P("{") + g.P("MethodName: ", strconv.Quote(method.GetName()), ",") + g.P("Handler: ", handlerNames[i], ",") + g.P("},") + } + g.P("},") + g.P("Streams: []", grpcPkg, ".StreamDesc{") + for i, method := range service.Method { + if !method.GetServerStreaming() && !method.GetClientStreaming() { + continue + } + g.P("{") + g.P("StreamName: ", strconv.Quote(method.GetName()), ",") + g.P("Handler: ", handlerNames[i], ",") + if method.GetServerStreaming() { + g.P("ServerStreams: true,") + } + if method.GetClientStreaming() { + g.P("ClientStreams: true,") + } + g.P("},") + } + g.P("},") + g.P("Metadata: \"", file.GetName(), "\",") + g.P("}") + g.P() +} + +// generateUnimplementedServer creates the unimplemented server struct +func (g *grpc) generateUnimplementedServer(servName string, service *pb.ServiceDescriptorProto) { + serverType := servName + "Server" + g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.") + g.P("type Unimplemented", serverType, " struct {") + g.P("}") + g.P() + // UnimplementedServer's concrete methods + for _, method := range service.Method { + g.generateServerMethodConcrete(servName, method) + } + g.P() +} + +// generateServerMethodConcrete returns unimplemented methods which ensure forward compatibility +func (g *grpc) generateServerMethodConcrete(servName string, method *pb.MethodDescriptorProto) { + header := g.generateServerSignatureWithParamNames(servName, method) + g.P("func (*Unimplemented", servName, "Server) ", header, " {") + var nilArg string + if !method.GetServerStreaming() && !method.GetClientStreaming() { + nilArg = "nil, " + } + methName := generator.CamelCase(method.GetName()) + statusPkg := string(g.gen.AddImport(statusPkgPath)) + codePkg := string(g.gen.AddImport(codePkgPath)) + g.P("return ", nilArg, statusPkg, `.Errorf(`, codePkg, `.Unimplemented, "method `, methName, ` not implemented")`) + g.P("}") +} + +// generateClientSignature returns the client-side signature for a method. +func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string { + origMethName := method.GetName() + methName := generator.CamelCase(origMethName) + if reservedClientName[methName] { + methName += "_" + } + reqArg := ", in *" + g.typeName(method.GetInputType()) + if method.GetClientStreaming() { + reqArg = "" + } + respName := "*" + g.typeName(method.GetOutputType()) + if method.GetServerStreaming() || method.GetClientStreaming() { + respName = servName + "_" + generator.CamelCase(origMethName) + "Client" + } + return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, grpcPkg, respName) +} + +func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) { + sname := fmt.Sprintf("/%s/%s", fullServName, method.GetName()) + methName := generator.CamelCase(method.GetName()) + inType := g.typeName(method.GetInputType()) + outType := g.typeName(method.GetOutputType()) + + if method.GetOptions().GetDeprecated() { + g.P(deprecationComment) + } + g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{") + if !method.GetServerStreaming() && !method.GetClientStreaming() { + g.P("out := new(", outType, ")") + // TODO: Pass descExpr to Invoke. + g.P(`err := c.cc.Invoke(ctx, "`, sname, `", in, out, opts...)`) + g.P("if err != nil { return nil, err }") + g.P("return out, nil") + g.P("}") + g.P() + return + } + streamType := unexport(servName) + methName + "Client" + g.P("stream, err := c.cc.NewStream(ctx, ", descExpr, `, "`, sname, `", opts...)`) + g.P("if err != nil { return nil, err }") + g.P("x := &", streamType, "{stream}") + if !method.GetClientStreaming() { + g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }") + g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }") + } + g.P("return x, nil") + g.P("}") + g.P() + + genSend := method.GetClientStreaming() + genRecv := method.GetServerStreaming() + genCloseAndRecv := !method.GetServerStreaming() + + // Stream auxiliary types and methods. + g.P("type ", servName, "_", methName, "Client interface {") + if genSend { + g.P("Send(*", inType, ") error") + } + if genRecv { + g.P("Recv() (*", outType, ", error)") + } + if genCloseAndRecv { + g.P("CloseAndRecv() (*", outType, ", error)") + } + g.P(grpcPkg, ".ClientStream") + g.P("}") + g.P() + + g.P("type ", streamType, " struct {") + g.P(grpcPkg, ".ClientStream") + g.P("}") + g.P() + + if genSend { + g.P("func (x *", streamType, ") Send(m *", inType, ") error {") + g.P("return x.ClientStream.SendMsg(m)") + g.P("}") + g.P() + } + if genRecv { + g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {") + g.P("m := new(", outType, ")") + g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }") + g.P("return m, nil") + g.P("}") + g.P() + } + if genCloseAndRecv { + g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {") + g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }") + g.P("m := new(", outType, ")") + g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }") + g.P("return m, nil") + g.P("}") + g.P() + } +} + +// generateServerSignatureWithParamNames returns the server-side signature for a method with parameter names. +func (g *grpc) generateServerSignatureWithParamNames(servName string, method *pb.MethodDescriptorProto) string { + origMethName := method.GetName() + methName := generator.CamelCase(origMethName) + if reservedClientName[methName] { + methName += "_" + } + + var reqArgs []string + ret := "error" + if !method.GetServerStreaming() && !method.GetClientStreaming() { + reqArgs = append(reqArgs, "ctx "+contextPkg+".Context") + ret = "(*" + g.typeName(method.GetOutputType()) + ", error)" + } + if !method.GetClientStreaming() { + reqArgs = append(reqArgs, "req *"+g.typeName(method.GetInputType())) + } + if method.GetServerStreaming() || method.GetClientStreaming() { + reqArgs = append(reqArgs, "srv "+servName+"_"+generator.CamelCase(origMethName)+"Server") + } + + return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret +} + +// generateServerSignature returns the server-side signature for a method. +func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string { + origMethName := method.GetName() + methName := generator.CamelCase(origMethName) + if reservedClientName[methName] { + methName += "_" + } + + var reqArgs []string + ret := "error" + if !method.GetServerStreaming() && !method.GetClientStreaming() { + reqArgs = append(reqArgs, contextPkg+".Context") + ret = "(*" + g.typeName(method.GetOutputType()) + ", error)" + } + if !method.GetClientStreaming() { + reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType())) + } + if method.GetServerStreaming() || method.GetClientStreaming() { + reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Server") + } + + return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret +} + +func (g *grpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string { + methName := generator.CamelCase(method.GetName()) + hname := fmt.Sprintf("_%s_%s_Handler", servName, methName) + inType := g.typeName(method.GetInputType()) + outType := g.typeName(method.GetOutputType()) + + if !method.GetServerStreaming() && !method.GetClientStreaming() { + g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {") + g.P("in := new(", inType, ")") + g.P("if err := dec(in); err != nil { return nil, err }") + g.P("if interceptor == nil { return srv.(", servName, "Server).", methName, "(ctx, in) }") + g.P("info := &", grpcPkg, ".UnaryServerInfo{") + g.P("Server: srv,") + g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",") + g.P("}") + g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {") + g.P("return srv.(", servName, "Server).", methName, "(ctx, req.(*", inType, "))") + g.P("}") + g.P("return interceptor(ctx, in, info, handler)") + g.P("}") + g.P() + return hname + } + streamType := unexport(servName) + methName + "Server" + g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {") + if !method.GetClientStreaming() { + g.P("m := new(", inType, ")") + g.P("if err := stream.RecvMsg(m); err != nil { return err }") + g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})") + } else { + g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})") + } + g.P("}") + g.P() + + genSend := method.GetServerStreaming() + genSendAndClose := !method.GetServerStreaming() + genRecv := method.GetClientStreaming() + + // Stream auxiliary types and methods. + g.P("type ", servName, "_", methName, "Server interface {") + if genSend { + g.P("Send(*", outType, ") error") + } + if genSendAndClose { + g.P("SendAndClose(*", outType, ") error") + } + if genRecv { + g.P("Recv() (*", inType, ", error)") + } + g.P(grpcPkg, ".ServerStream") + g.P("}") + g.P() + + g.P("type ", streamType, " struct {") + g.P(grpcPkg, ".ServerStream") + g.P("}") + g.P() + + if genSend { + g.P("func (x *", streamType, ") Send(m *", outType, ") error {") + g.P("return x.ServerStream.SendMsg(m)") + g.P("}") + g.P() + } + if genSendAndClose { + g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {") + g.P("return x.ServerStream.SendMsg(m)") + g.P("}") + g.P() + } + if genRecv { + g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {") + g.P("m := new(", inType, ")") + g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }") + g.P("return m, nil") + g.P("}") + g.P() + } + + return hname +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go b/vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go new file mode 100644 index 0000000000..532a550050 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go @@ -0,0 +1,34 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package main + +import _ "github.com/golang/protobuf/protoc-gen-go/grpc" diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/main.go b/vendor/github.com/golang/protobuf/protoc-gen-go/main.go new file mode 100644 index 0000000000..8e2486de0b --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/main.go @@ -0,0 +1,98 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// protoc-gen-go is a plugin for the Google protocol buffer compiler to generate +// Go code. Run it by building this program and putting it in your path with +// the name +// protoc-gen-go +// That word 'go' at the end becomes part of the option string set for the +// protocol compiler, so once the protocol compiler (protoc) is installed +// you can run +// protoc --go_out=output_directory input_directory/file.proto +// to generate Go bindings for the protocol defined by file.proto. +// With that input, the output will be written to +// output_directory/file.pb.go +// +// The generated code is documented in the package comment for +// the library. +// +// See the README and documentation for protocol buffers to learn more: +// https://developers.google.com/protocol-buffers/ +package main + +import ( + "io/ioutil" + "os" + + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/protoc-gen-go/generator" +) + +func main() { + // Begin by allocating a generator. The request and response structures are stored there + // so we can do error handling easily - the response structure contains the field to + // report failure. + g := generator.New() + + data, err := ioutil.ReadAll(os.Stdin) + if err != nil { + g.Error(err, "reading input") + } + + if err := proto.Unmarshal(data, g.Request); err != nil { + g.Error(err, "parsing input proto") + } + + if len(g.Request.FileToGenerate) == 0 { + g.Fail("no files to generate") + } + + g.CommandLineParameters(g.Request.GetParameter()) + + // Create a wrapped version of the Descriptors and EnumDescriptors that + // point to the file that defines them. + g.WrapTypes() + + g.SetPackageNames() + g.BuildTypeNameMap() + + g.GenerateAllFiles() + + // Send back the results. + data, err = proto.Marshal(g.Response) + if err != nil { + g.Error(err, "failed to marshal output proto") + } + _, err = os.Stdout.Write(data) + if err != nil { + g.Error(err, "failed to write output proto") + } +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go new file mode 100644 index 0000000000..61bfc10e02 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go @@ -0,0 +1,369 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/compiler/plugin.proto + +/* +Package plugin_go is a generated protocol buffer package. + +It is generated from these files: + google/protobuf/compiler/plugin.proto + +It has these top-level messages: + Version + CodeGeneratorRequest + CodeGeneratorResponse +*/ +package plugin_go + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// The version number of protocol compiler. +type Version struct { + Major *int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"` + Minor *int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"` + Patch *int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"` + // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should + // be empty for mainline stable releases. + Suffix *string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Version) Reset() { *m = Version{} } +func (m *Version) String() string { return proto.CompactTextString(m) } +func (*Version) ProtoMessage() {} +func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *Version) Unmarshal(b []byte) error { + return xxx_messageInfo_Version.Unmarshal(m, b) +} +func (m *Version) Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Version.Marshal(b, m, deterministic) +} +func (dst *Version) XXX_Merge(src proto.Message) { + xxx_messageInfo_Version.Merge(dst, src) +} +func (m *Version) XXX_Size() int { + return xxx_messageInfo_Version.Size(m) +} +func (m *Version) XXX_DiscardUnknown() { + xxx_messageInfo_Version.DiscardUnknown(m) +} + +var xxx_messageInfo_Version proto.InternalMessageInfo + +func (m *Version) GetMajor() int32 { + if m != nil && m.Major != nil { + return *m.Major + } + return 0 +} + +func (m *Version) GetMinor() int32 { + if m != nil && m.Minor != nil { + return *m.Minor + } + return 0 +} + +func (m *Version) GetPatch() int32 { + if m != nil && m.Patch != nil { + return *m.Patch + } + return 0 +} + +func (m *Version) GetSuffix() string { + if m != nil && m.Suffix != nil { + return *m.Suffix + } + return "" +} + +// An encoded CodeGeneratorRequest is written to the plugin's stdin. +type CodeGeneratorRequest struct { + // The .proto files that were explicitly listed on the command-line. The + // code generator should generate code only for these files. Each file's + // descriptor will be included in proto_file, below. + FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"` + // The generator parameter passed on the command-line. + Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"` + // FileDescriptorProtos for all files in files_to_generate and everything + // they import. The files will appear in topological order, so each file + // appears before any file that imports it. + // + // protoc guarantees that all proto_files will be written after + // the fields above, even though this is not technically guaranteed by the + // protobuf wire format. This theoretically could allow a plugin to stream + // in the FileDescriptorProtos and handle them one by one rather than read + // the entire set into memory at once. However, as of this writing, this + // is not similarly optimized on protoc's end -- it will store all fields in + // memory at once before sending them to the plugin. + // + // Type names of fields and extensions in the FileDescriptorProto are always + // fully qualified. + ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"` + // The version number of protocol compiler. + CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CodeGeneratorRequest) Reset() { *m = CodeGeneratorRequest{} } +func (m *CodeGeneratorRequest) String() string { return proto.CompactTextString(m) } +func (*CodeGeneratorRequest) ProtoMessage() {} +func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (m *CodeGeneratorRequest) Unmarshal(b []byte) error { + return xxx_messageInfo_CodeGeneratorRequest.Unmarshal(m, b) +} +func (m *CodeGeneratorRequest) Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CodeGeneratorRequest.Marshal(b, m, deterministic) +} +func (dst *CodeGeneratorRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CodeGeneratorRequest.Merge(dst, src) +} +func (m *CodeGeneratorRequest) XXX_Size() int { + return xxx_messageInfo_CodeGeneratorRequest.Size(m) +} +func (m *CodeGeneratorRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CodeGeneratorRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_CodeGeneratorRequest proto.InternalMessageInfo + +func (m *CodeGeneratorRequest) GetFileToGenerate() []string { + if m != nil { + return m.FileToGenerate + } + return nil +} + +func (m *CodeGeneratorRequest) GetParameter() string { + if m != nil && m.Parameter != nil { + return *m.Parameter + } + return "" +} + +func (m *CodeGeneratorRequest) GetProtoFile() []*google_protobuf.FileDescriptorProto { + if m != nil { + return m.ProtoFile + } + return nil +} + +func (m *CodeGeneratorRequest) GetCompilerVersion() *Version { + if m != nil { + return m.CompilerVersion + } + return nil +} + +// The plugin writes an encoded CodeGeneratorResponse to stdout. +type CodeGeneratorResponse struct { + // Error message. If non-empty, code generation failed. The plugin process + // should exit with status code zero even if it reports an error in this way. + // + // This should be used to indicate errors in .proto files which prevent the + // code generator from generating correct code. Errors which indicate a + // problem in protoc itself -- such as the input CodeGeneratorRequest being + // unparseable -- should be reported by writing a message to stderr and + // exiting with a non-zero status code. + Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` + File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CodeGeneratorResponse) Reset() { *m = CodeGeneratorResponse{} } +func (m *CodeGeneratorResponse) String() string { return proto.CompactTextString(m) } +func (*CodeGeneratorResponse) ProtoMessage() {} +func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (m *CodeGeneratorResponse) Unmarshal(b []byte) error { + return xxx_messageInfo_CodeGeneratorResponse.Unmarshal(m, b) +} +func (m *CodeGeneratorResponse) Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CodeGeneratorResponse.Marshal(b, m, deterministic) +} +func (dst *CodeGeneratorResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_CodeGeneratorResponse.Merge(dst, src) +} +func (m *CodeGeneratorResponse) XXX_Size() int { + return xxx_messageInfo_CodeGeneratorResponse.Size(m) +} +func (m *CodeGeneratorResponse) XXX_DiscardUnknown() { + xxx_messageInfo_CodeGeneratorResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_CodeGeneratorResponse proto.InternalMessageInfo + +func (m *CodeGeneratorResponse) GetError() string { + if m != nil && m.Error != nil { + return *m.Error + } + return "" +} + +func (m *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File { + if m != nil { + return m.File + } + return nil +} + +// Represents a single generated file. +type CodeGeneratorResponse_File struct { + // The file name, relative to the output directory. The name must not + // contain "." or ".." components and must be relative, not be absolute (so, + // the file cannot lie outside the output directory). "/" must be used as + // the path separator, not "\". + // + // If the name is omitted, the content will be appended to the previous + // file. This allows the generator to break large files into small chunks, + // and allows the generated text to be streamed back to protoc so that large + // files need not reside completely in memory at one time. Note that as of + // this writing protoc does not optimize for this -- it will read the entire + // CodeGeneratorResponse before writing files to disk. + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // If non-empty, indicates that the named file should already exist, and the + // content here is to be inserted into that file at a defined insertion + // point. This feature allows a code generator to extend the output + // produced by another code generator. The original generator may provide + // insertion points by placing special annotations in the file that look + // like: + // @@protoc_insertion_point(NAME) + // The annotation can have arbitrary text before and after it on the line, + // which allows it to be placed in a comment. NAME should be replaced with + // an identifier naming the point -- this is what other generators will use + // as the insertion_point. Code inserted at this point will be placed + // immediately above the line containing the insertion point (thus multiple + // insertions to the same point will come out in the order they were added). + // The double-@ is intended to make it unlikely that the generated code + // could contain things that look like insertion points by accident. + // + // For example, the C++ code generator places the following line in the + // .pb.h files that it generates: + // // @@protoc_insertion_point(namespace_scope) + // This line appears within the scope of the file's package namespace, but + // outside of any particular class. Another plugin can then specify the + // insertion_point "namespace_scope" to generate additional classes or + // other declarations that should be placed in this scope. + // + // Note that if the line containing the insertion point begins with + // whitespace, the same whitespace will be added to every line of the + // inserted text. This is useful for languages like Python, where + // indentation matters. In these languages, the insertion point comment + // should be indented the same amount as any inserted code will need to be + // in order to work correctly in that context. + // + // The code generator that generates the initial file and the one which + // inserts into it must both run as part of a single invocation of protoc. + // Code generators are executed in the order in which they appear on the + // command line. + // + // If |insertion_point| is present, |name| must also be present. + InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"` + // The file contents. + Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CodeGeneratorResponse_File) Reset() { *m = CodeGeneratorResponse_File{} } +func (m *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(m) } +func (*CodeGeneratorResponse_File) ProtoMessage() {} +func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } +func (m *CodeGeneratorResponse_File) Unmarshal(b []byte) error { + return xxx_messageInfo_CodeGeneratorResponse_File.Unmarshal(m, b) +} +func (m *CodeGeneratorResponse_File) Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CodeGeneratorResponse_File.Marshal(b, m, deterministic) +} +func (dst *CodeGeneratorResponse_File) XXX_Merge(src proto.Message) { + xxx_messageInfo_CodeGeneratorResponse_File.Merge(dst, src) +} +func (m *CodeGeneratorResponse_File) XXX_Size() int { + return xxx_messageInfo_CodeGeneratorResponse_File.Size(m) +} +func (m *CodeGeneratorResponse_File) XXX_DiscardUnknown() { + xxx_messageInfo_CodeGeneratorResponse_File.DiscardUnknown(m) +} + +var xxx_messageInfo_CodeGeneratorResponse_File proto.InternalMessageInfo + +func (m *CodeGeneratorResponse_File) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *CodeGeneratorResponse_File) GetInsertionPoint() string { + if m != nil && m.InsertionPoint != nil { + return *m.InsertionPoint + } + return "" +} + +func (m *CodeGeneratorResponse_File) GetContent() string { + if m != nil && m.Content != nil { + return *m.Content + } + return "" +} + +func init() { + proto.RegisterType((*Version)(nil), "google.protobuf.compiler.Version") + proto.RegisterType((*CodeGeneratorRequest)(nil), "google.protobuf.compiler.CodeGeneratorRequest") + proto.RegisterType((*CodeGeneratorResponse)(nil), "google.protobuf.compiler.CodeGeneratorResponse") + proto.RegisterType((*CodeGeneratorResponse_File)(nil), "google.protobuf.compiler.CodeGeneratorResponse.File") +} + +func init() { proto.RegisterFile("google/protobuf/compiler/plugin.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 417 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcf, 0x6a, 0x14, 0x41, + 0x10, 0xc6, 0x19, 0x77, 0x63, 0x98, 0x8a, 0x64, 0x43, 0x13, 0xa5, 0x09, 0x39, 0x8c, 0x8b, 0xe2, + 0x5c, 0x32, 0x0b, 0xc1, 0x8b, 0x78, 0x4b, 0x44, 0x3d, 0x78, 0x58, 0x1a, 0xf1, 0x20, 0xc8, 0x30, + 0x99, 0xd4, 0x74, 0x5a, 0x66, 0xba, 0xc6, 0xee, 0x1e, 0xf1, 0x49, 0x7d, 0x0f, 0xdf, 0x40, 0xfa, + 0xcf, 0x24, 0xb2, 0xb8, 0xa7, 0xee, 0xef, 0x57, 0xd5, 0xd5, 0x55, 0x1f, 0x05, 0x2f, 0x25, 0x91, + 0xec, 0x71, 0x33, 0x1a, 0x72, 0x74, 0x33, 0x75, 0x9b, 0x96, 0x86, 0x51, 0xf5, 0x68, 0x36, 0x63, + 0x3f, 0x49, 0xa5, 0xab, 0x10, 0x60, 0x3c, 0xa6, 0x55, 0x73, 0x5a, 0x35, 0xa7, 0x9d, 0x15, 0xbb, + 0x05, 0x6e, 0xd1, 0xb6, 0x46, 0x8d, 0x8e, 0x4c, 0xcc, 0x5e, 0xb7, 0x70, 0xf8, 0x05, 0x8d, 0x55, + 0xa4, 0xd9, 0x29, 0x1c, 0x0c, 0xcd, 0x77, 0x32, 0x3c, 0x2b, 0xb2, 0xf2, 0x40, 0x44, 0x11, 0xa8, + 0xd2, 0x64, 0xf8, 0xa3, 0x44, 0xbd, 0xf0, 0x74, 0x6c, 0x5c, 0x7b, 0xc7, 0x17, 0x91, 0x06, 0xc1, + 0x9e, 0xc1, 0x63, 0x3b, 0x75, 0x9d, 0xfa, 0xc5, 0x97, 0x45, 0x56, 0xe6, 0x22, 0xa9, 0xf5, 0x9f, + 0x0c, 0x4e, 0xaf, 0xe9, 0x16, 0x3f, 0xa0, 0x46, 0xd3, 0x38, 0x32, 0x02, 0x7f, 0x4c, 0x68, 0x1d, + 0x2b, 0xe1, 0xa4, 0x53, 0x3d, 0xd6, 0x8e, 0x6a, 0x19, 0x63, 0xc8, 0xb3, 0x62, 0x51, 0xe6, 0xe2, + 0xd8, 0xf3, 0xcf, 0x94, 0x5e, 0x20, 0x3b, 0x87, 0x7c, 0x6c, 0x4c, 0x33, 0xa0, 0xc3, 0xd8, 0x4a, + 0x2e, 0x1e, 0x00, 0xbb, 0x06, 0x08, 0xe3, 0xd4, 0xfe, 0x15, 0x5f, 0x15, 0x8b, 0xf2, 0xe8, 0xf2, + 0x45, 0xb5, 0x6b, 0xcb, 0x7b, 0xd5, 0xe3, 0xbb, 0x7b, 0x03, 0xb6, 0x1e, 0x8b, 0x3c, 0x44, 0x7d, + 0x84, 0x7d, 0x82, 0x93, 0xd9, 0xb8, 0xfa, 0x67, 0xf4, 0x24, 0x8c, 0x77, 0x74, 0xf9, 0xbc, 0xda, + 0xe7, 0x70, 0x95, 0xcc, 0x13, 0xab, 0x99, 0x24, 0xb0, 0xfe, 0x9d, 0xc1, 0xd3, 0x9d, 0x99, 0xed, + 0x48, 0xda, 0xa2, 0xf7, 0x0e, 0x8d, 0x49, 0x3e, 0xe7, 0x22, 0x0a, 0xf6, 0x11, 0x96, 0xff, 0x34, + 0xff, 0x7a, 0xff, 0x8f, 0xff, 0x2d, 0x1a, 0x66, 0x13, 0xa1, 0xc2, 0xd9, 0x37, 0x58, 0x86, 0x79, + 0x18, 0x2c, 0x75, 0x33, 0x60, 0xfa, 0x26, 0xdc, 0xd9, 0x2b, 0x58, 0x29, 0x6d, 0xd1, 0x38, 0x45, + 0xba, 0x1e, 0x49, 0x69, 0x97, 0xcc, 0x3c, 0xbe, 0xc7, 0x5b, 0x4f, 0x19, 0x87, 0xc3, 0x96, 0xb4, + 0x43, 0xed, 0xf8, 0x2a, 0x24, 0xcc, 0xf2, 0x4a, 0xc2, 0x79, 0x4b, 0xc3, 0xde, 0xfe, 0xae, 0x9e, + 0x6c, 0xc3, 0x6e, 0x06, 0x7b, 0xed, 0xd7, 0x37, 0x52, 0xb9, 0xbb, 0xe9, 0xc6, 0x87, 0x37, 0x92, + 0xfa, 0x46, 0xcb, 0x87, 0x65, 0x0c, 0x97, 0xf6, 0x42, 0xa2, 0xbe, 0x90, 0x94, 0x56, 0xfa, 0x6d, + 0x3c, 0x6a, 0x49, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x15, 0x40, 0xc5, 0xfe, 0x02, 0x00, + 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden new file mode 100644 index 0000000000..8953d0ff82 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden @@ -0,0 +1,83 @@ +// Code generated by protoc-gen-go. +// source: google/protobuf/compiler/plugin.proto +// DO NOT EDIT! + +package google_protobuf_compiler + +import proto "github.com/golang/protobuf/proto" +import "math" +import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" + +// Reference proto and math imports to suppress error if they are not otherwise used. +var _ = proto.GetString +var _ = math.Inf + +type CodeGeneratorRequest struct { + FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate" json:"file_to_generate,omitempty"` + Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"` + ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file" json:"proto_file,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (this *CodeGeneratorRequest) Reset() { *this = CodeGeneratorRequest{} } +func (this *CodeGeneratorRequest) String() string { return proto.CompactTextString(this) } +func (*CodeGeneratorRequest) ProtoMessage() {} + +func (this *CodeGeneratorRequest) GetParameter() string { + if this != nil && this.Parameter != nil { + return *this.Parameter + } + return "" +} + +type CodeGeneratorResponse struct { + Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` + File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (this *CodeGeneratorResponse) Reset() { *this = CodeGeneratorResponse{} } +func (this *CodeGeneratorResponse) String() string { return proto.CompactTextString(this) } +func (*CodeGeneratorResponse) ProtoMessage() {} + +func (this *CodeGeneratorResponse) GetError() string { + if this != nil && this.Error != nil { + return *this.Error + } + return "" +} + +type CodeGeneratorResponse_File struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point" json:"insertion_point,omitempty"` + Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (this *CodeGeneratorResponse_File) Reset() { *this = CodeGeneratorResponse_File{} } +func (this *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(this) } +func (*CodeGeneratorResponse_File) ProtoMessage() {} + +func (this *CodeGeneratorResponse_File) GetName() string { + if this != nil && this.Name != nil { + return *this.Name + } + return "" +} + +func (this *CodeGeneratorResponse_File) GetInsertionPoint() string { + if this != nil && this.InsertionPoint != nil { + return *this.InsertionPoint + } + return "" +} + +func (this *CodeGeneratorResponse_File) GetContent() string { + if this != nil && this.Content != nil { + return *this.Content + } + return "" +} + +func init() { +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.proto new file mode 100644 index 0000000000..5b5574529e --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.proto @@ -0,0 +1,167 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// +// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to +// change. +// +// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is +// just a program that reads a CodeGeneratorRequest from stdin and writes a +// CodeGeneratorResponse to stdout. +// +// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead +// of dealing with the raw protocol defined here. +// +// A plugin executable needs only to be placed somewhere in the path. The +// plugin should be named "protoc-gen-$NAME", and will then be used when the +// flag "--${NAME}_out" is passed to protoc. + +syntax = "proto2"; +package google.protobuf.compiler; +option java_package = "com.google.protobuf.compiler"; +option java_outer_classname = "PluginProtos"; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/plugin;plugin_go"; + +import "google/protobuf/descriptor.proto"; + +// The version number of protocol compiler. +message Version { + optional int32 major = 1; + optional int32 minor = 2; + optional int32 patch = 3; + // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should + // be empty for mainline stable releases. + optional string suffix = 4; +} + +// An encoded CodeGeneratorRequest is written to the plugin's stdin. +message CodeGeneratorRequest { + // The .proto files that were explicitly listed on the command-line. The + // code generator should generate code only for these files. Each file's + // descriptor will be included in proto_file, below. + repeated string file_to_generate = 1; + + // The generator parameter passed on the command-line. + optional string parameter = 2; + + // FileDescriptorProtos for all files in files_to_generate and everything + // they import. The files will appear in topological order, so each file + // appears before any file that imports it. + // + // protoc guarantees that all proto_files will be written after + // the fields above, even though this is not technically guaranteed by the + // protobuf wire format. This theoretically could allow a plugin to stream + // in the FileDescriptorProtos and handle them one by one rather than read + // the entire set into memory at once. However, as of this writing, this + // is not similarly optimized on protoc's end -- it will store all fields in + // memory at once before sending them to the plugin. + // + // Type names of fields and extensions in the FileDescriptorProto are always + // fully qualified. + repeated FileDescriptorProto proto_file = 15; + + // The version number of protocol compiler. + optional Version compiler_version = 3; + +} + +// The plugin writes an encoded CodeGeneratorResponse to stdout. +message CodeGeneratorResponse { + // Error message. If non-empty, code generation failed. The plugin process + // should exit with status code zero even if it reports an error in this way. + // + // This should be used to indicate errors in .proto files which prevent the + // code generator from generating correct code. Errors which indicate a + // problem in protoc itself -- such as the input CodeGeneratorRequest being + // unparseable -- should be reported by writing a message to stderr and + // exiting with a non-zero status code. + optional string error = 1; + + // Represents a single generated file. + message File { + // The file name, relative to the output directory. The name must not + // contain "." or ".." components and must be relative, not be absolute (so, + // the file cannot lie outside the output directory). "/" must be used as + // the path separator, not "\". + // + // If the name is omitted, the content will be appended to the previous + // file. This allows the generator to break large files into small chunks, + // and allows the generated text to be streamed back to protoc so that large + // files need not reside completely in memory at one time. Note that as of + // this writing protoc does not optimize for this -- it will read the entire + // CodeGeneratorResponse before writing files to disk. + optional string name = 1; + + // If non-empty, indicates that the named file should already exist, and the + // content here is to be inserted into that file at a defined insertion + // point. This feature allows a code generator to extend the output + // produced by another code generator. The original generator may provide + // insertion points by placing special annotations in the file that look + // like: + // @@protoc_insertion_point(NAME) + // The annotation can have arbitrary text before and after it on the line, + // which allows it to be placed in a comment. NAME should be replaced with + // an identifier naming the point -- this is what other generators will use + // as the insertion_point. Code inserted at this point will be placed + // immediately above the line containing the insertion point (thus multiple + // insertions to the same point will come out in the order they were added). + // The double-@ is intended to make it unlikely that the generated code + // could contain things that look like insertion points by accident. + // + // For example, the C++ code generator places the following line in the + // .pb.h files that it generates: + // // @@protoc_insertion_point(namespace_scope) + // This line appears within the scope of the file's package namespace, but + // outside of any particular class. Another plugin can then specify the + // insertion_point "namespace_scope" to generate additional classes or + // other declarations that should be placed in this scope. + // + // Note that if the line containing the insertion point begins with + // whitespace, the same whitespace will be added to every line of the + // inserted text. This is useful for languages like Python, where + // indentation matters. In these languages, the insertion point comment + // should be indented the same amount as any inserted code will need to be + // in order to work correctly in that context. + // + // The code generator that generates the initial file and the one which + // inserts into it must both run as part of a single invocation of protoc. + // Code generators are executed in the order in which they appear on the + // command line. + // + // If |insertion_point| is present, |name| must also be present. + optional string insertion_point = 2; + + // The file contents. + optional string content = 15; + } + repeated File file = 15; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/deprecated/deprecated.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/deprecated/deprecated.pb.go new file mode 100644 index 0000000000..2515c99eb9 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/deprecated/deprecated.pb.go @@ -0,0 +1,283 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// deprecated/deprecated.proto is a deprecated file. + +// package deprecated contains only deprecated messages and services. + +package deprecated + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// DeprecatedEnum contains deprecated values. +type DeprecatedEnum int32 // Deprecated: Do not use. +const ( + // DEPRECATED is the iota value of this enum. + DeprecatedEnum_DEPRECATED DeprecatedEnum = 0 // Deprecated: Do not use. +) + +var DeprecatedEnum_name = map[int32]string{ + 0: "DEPRECATED", +} + +var DeprecatedEnum_value = map[string]int32{ + "DEPRECATED": 0, +} + +func (x DeprecatedEnum) String() string { + return proto.EnumName(DeprecatedEnum_name, int32(x)) +} + +func (DeprecatedEnum) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_f64ba265cd7eae3f, []int{0} +} + +// DeprecatedRequest is a request to DeprecatedCall. +// +// Deprecated: Do not use. +type DeprecatedRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeprecatedRequest) Reset() { *m = DeprecatedRequest{} } +func (m *DeprecatedRequest) String() string { return proto.CompactTextString(m) } +func (*DeprecatedRequest) ProtoMessage() {} +func (*DeprecatedRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f64ba265cd7eae3f, []int{0} +} + +func (m *DeprecatedRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeprecatedRequest.Unmarshal(m, b) +} +func (m *DeprecatedRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeprecatedRequest.Marshal(b, m, deterministic) +} +func (m *DeprecatedRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeprecatedRequest.Merge(m, src) +} +func (m *DeprecatedRequest) XXX_Size() int { + return xxx_messageInfo_DeprecatedRequest.Size(m) +} +func (m *DeprecatedRequest) XXX_DiscardUnknown() { + xxx_messageInfo_DeprecatedRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_DeprecatedRequest proto.InternalMessageInfo + +// Deprecated: Do not use. +type DeprecatedResponse struct { + // DeprecatedField contains a DeprecatedEnum. + DeprecatedField DeprecatedEnum `protobuf:"varint,1,opt,name=deprecated_field,json=deprecatedField,proto3,enum=deprecated.DeprecatedEnum" json:"deprecated_field,omitempty"` // Deprecated: Do not use. + // DeprecatedOneof contains a deprecated field. + // + // Types that are valid to be assigned to DeprecatedOneof: + // *DeprecatedResponse_DeprecatedOneofField + DeprecatedOneof isDeprecatedResponse_DeprecatedOneof `protobuf_oneof:"deprecated_oneof"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeprecatedResponse) Reset() { *m = DeprecatedResponse{} } +func (m *DeprecatedResponse) String() string { return proto.CompactTextString(m) } +func (*DeprecatedResponse) ProtoMessage() {} +func (*DeprecatedResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f64ba265cd7eae3f, []int{1} +} + +func (m *DeprecatedResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeprecatedResponse.Unmarshal(m, b) +} +func (m *DeprecatedResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeprecatedResponse.Marshal(b, m, deterministic) +} +func (m *DeprecatedResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeprecatedResponse.Merge(m, src) +} +func (m *DeprecatedResponse) XXX_Size() int { + return xxx_messageInfo_DeprecatedResponse.Size(m) +} +func (m *DeprecatedResponse) XXX_DiscardUnknown() { + xxx_messageInfo_DeprecatedResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_DeprecatedResponse proto.InternalMessageInfo + +// Deprecated: Do not use. +func (m *DeprecatedResponse) GetDeprecatedField() DeprecatedEnum { + if m != nil { + return m.DeprecatedField + } + return DeprecatedEnum_DEPRECATED +} + +type isDeprecatedResponse_DeprecatedOneof interface { + isDeprecatedResponse_DeprecatedOneof() +} + +type DeprecatedResponse_DeprecatedOneofField struct { + DeprecatedOneofField string `protobuf:"bytes,2,opt,name=deprecated_oneof_field,json=deprecatedOneofField,proto3,oneof"` +} + +func (*DeprecatedResponse_DeprecatedOneofField) isDeprecatedResponse_DeprecatedOneof() {} + +func (m *DeprecatedResponse) GetDeprecatedOneof() isDeprecatedResponse_DeprecatedOneof { + if m != nil { + return m.DeprecatedOneof + } + return nil +} + +// Deprecated: Do not use. +func (m *DeprecatedResponse) GetDeprecatedOneofField() string { + if x, ok := m.GetDeprecatedOneof().(*DeprecatedResponse_DeprecatedOneofField); ok { + return x.DeprecatedOneofField + } + return "" +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*DeprecatedResponse) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*DeprecatedResponse_DeprecatedOneofField)(nil), + } +} + +func init() { + proto.RegisterEnum("deprecated.DeprecatedEnum", DeprecatedEnum_name, DeprecatedEnum_value) + proto.RegisterType((*DeprecatedRequest)(nil), "deprecated.DeprecatedRequest") + proto.RegisterType((*DeprecatedResponse)(nil), "deprecated.DeprecatedResponse") +} + +func init() { proto.RegisterFile("deprecated/deprecated.proto", fileDescriptor_f64ba265cd7eae3f) } + +var fileDescriptor_f64ba265cd7eae3f = []byte{ + // 287 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xcd, 0x4a, 0xf3, 0x40, + 0x14, 0x86, 0x7b, 0xe6, 0x83, 0x0f, 0x9d, 0x45, 0xad, 0x83, 0x68, 0x88, 0x28, 0x25, 0xab, 0x20, + 0x34, 0x81, 0xba, 0x2b, 0x6e, 0x9a, 0x26, 0xa2, 0x2b, 0x25, 0x76, 0xe5, 0x46, 0xf2, 0x73, 0x12, + 0x03, 0xe9, 0x4c, 0x4c, 0x26, 0x5e, 0x83, 0xf7, 0xe3, 0xc6, 0xcb, 0x93, 0x49, 0x8b, 0x33, 0x05, + 0xdd, 0x84, 0x93, 0x79, 0xdf, 0xe7, 0xfc, 0xd2, 0xf3, 0x1c, 0x9b, 0x16, 0xb3, 0x44, 0x62, 0xee, + 0xeb, 0xd0, 0x6b, 0x5a, 0x21, 0x05, 0xa3, 0xfa, 0xc5, 0x39, 0xa3, 0xc7, 0xe1, 0xcf, 0x5f, 0x8c, + 0x6f, 0x3d, 0x76, 0x72, 0x41, 0x2c, 0x70, 0x3e, 0x81, 0x32, 0x53, 0xe9, 0x1a, 0xc1, 0x3b, 0x64, + 0xf7, 0x74, 0xa2, 0xe9, 0x97, 0xa2, 0xc2, 0x3a, 0xb7, 0x60, 0x0a, 0xee, 0x78, 0x6e, 0x7b, 0x46, + 0x21, 0x4d, 0x46, 0xbc, 0xdf, 0x04, 0xc4, 0x82, 0xf8, 0x48, 0xcb, 0xb7, 0x0a, 0x63, 0x0b, 0x7a, + 0x6a, 0xa4, 0x12, 0x1c, 0x45, 0xb1, 0x4b, 0x48, 0xa6, 0xe0, 0x1e, 0x2a, 0xe8, 0x6e, 0x14, 0x9f, + 0x68, 0xcf, 0x83, 0xb2, 0x0c, 0xac, 0xea, 0x30, 0x60, 0x7b, 0xad, 0x0c, 0xfc, 0x95, 0x4b, 0xc7, + 0xfb, 0xa5, 0x19, 0xa3, 0x34, 0x8c, 0x1e, 0xe3, 0x68, 0xb5, 0x5c, 0x47, 0xe1, 0x64, 0x64, 0x93, + 0x03, 0xb0, 0x89, 0x05, 0x73, 0x6e, 0x0e, 0xfe, 0x84, 0xed, 0x7b, 0x95, 0x21, 0x5b, 0x9b, 0xf8, + 0x2a, 0xa9, 0x6b, 0x76, 0xf1, 0xfb, 0x54, 0xbb, 0x4d, 0xd9, 0x97, 0x7f, 0xc9, 0xdb, 0x75, 0x39, + 0xff, 0x3e, 0x08, 0xd8, 0xea, 0x13, 0x2c, 0x9f, 0x6f, 0xca, 0x4a, 0xbe, 0xf6, 0xa9, 0x97, 0x89, + 0x8d, 0x5f, 0x8a, 0x3a, 0xe1, 0xa5, 0x3f, 0xdc, 0x23, 0xed, 0x8b, 0x6d, 0x90, 0xcd, 0x4a, 0xe4, + 0xb3, 0x52, 0xf8, 0x12, 0x3b, 0x99, 0x27, 0x32, 0x31, 0x4e, 0xf7, 0x05, 0x90, 0xfe, 0x1f, 0x5c, + 0xd7, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x08, 0xd5, 0xa0, 0x89, 0xdd, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// DeprecatedServiceClient is the client API for DeprecatedService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +// +// Deprecated: Do not use. +type DeprecatedServiceClient interface { + // DeprecatedCall takes a DeprecatedRequest and returns a DeprecatedResponse. + DeprecatedCall(ctx context.Context, in *DeprecatedRequest, opts ...grpc.CallOption) (*DeprecatedResponse, error) +} + +type deprecatedServiceClient struct { + cc *grpc.ClientConn +} + +// Deprecated: Do not use. +func NewDeprecatedServiceClient(cc *grpc.ClientConn) DeprecatedServiceClient { + return &deprecatedServiceClient{cc} +} + +// Deprecated: Do not use. +func (c *deprecatedServiceClient) DeprecatedCall(ctx context.Context, in *DeprecatedRequest, opts ...grpc.CallOption) (*DeprecatedResponse, error) { + out := new(DeprecatedResponse) + err := c.cc.Invoke(ctx, "/deprecated.DeprecatedService/DeprecatedCall", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// DeprecatedServiceServer is the server API for DeprecatedService service. +// +// Deprecated: Do not use. +type DeprecatedServiceServer interface { + // DeprecatedCall takes a DeprecatedRequest and returns a DeprecatedResponse. + DeprecatedCall(context.Context, *DeprecatedRequest) (*DeprecatedResponse, error) +} + +// Deprecated: Do not use. +// UnimplementedDeprecatedServiceServer can be embedded to have forward compatible implementations. +type UnimplementedDeprecatedServiceServer struct { +} + +func (*UnimplementedDeprecatedServiceServer) DeprecatedCall(ctx context.Context, req *DeprecatedRequest) (*DeprecatedResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeprecatedCall not implemented") +} + +// Deprecated: Do not use. +func RegisterDeprecatedServiceServer(s *grpc.Server, srv DeprecatedServiceServer) { + s.RegisterService(&_DeprecatedService_serviceDesc, srv) +} + +func _DeprecatedService_DeprecatedCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeprecatedRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DeprecatedServiceServer).DeprecatedCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/deprecated.DeprecatedService/DeprecatedCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DeprecatedServiceServer).DeprecatedCall(ctx, req.(*DeprecatedRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _DeprecatedService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "deprecated.DeprecatedService", + HandlerType: (*DeprecatedServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "DeprecatedCall", + Handler: _DeprecatedService_DeprecatedCall_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "deprecated/deprecated.proto", +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/deprecated/deprecated.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/deprecated/deprecated.proto new file mode 100644 index 0000000000..192b15822a --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/deprecated/deprecated.proto @@ -0,0 +1,74 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2018 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +// package deprecated contains only deprecated messages and services. +package deprecated; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/deprecated"; + +option deprecated = true; // file-level deprecation + +// DeprecatedRequest is a request to DeprecatedCall. +message DeprecatedRequest { + option deprecated = true; +} + +message DeprecatedResponse { + // comment for DeprecatedResponse is omitted to guarantee deprecation + // message doesn't append unnecessary comments. + option deprecated = true; + // DeprecatedField contains a DeprecatedEnum. + DeprecatedEnum deprecated_field = 1 [deprecated=true]; + // DeprecatedOneof contains a deprecated field. + oneof deprecated_oneof { + // DeprecatedOneofField is a deprecated field. + string deprecated_oneof_field = 2 [deprecated=true]; + } +} + +// DeprecatedEnum contains deprecated values. +enum DeprecatedEnum { + option deprecated = true; + // DEPRECATED is the iota value of this enum. + DEPRECATED = 0 [deprecated=true]; +} + +// DeprecatedService is for making DeprecatedCalls +service DeprecatedService { + option deprecated = true; + + // DeprecatedCall takes a DeprecatedRequest and returns a DeprecatedResponse. + rpc DeprecatedCall(DeprecatedRequest) returns (DeprecatedResponse) { + option deprecated = true; + } +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base/extension_base.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base/extension_base.pb.go new file mode 100644 index 0000000000..b5d4aa6693 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base/extension_base.pb.go @@ -0,0 +1,136 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: extension_base/extension_base.proto + +package extension_base + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type BaseMessage struct { + Height *int32 `protobuf:"varint,1,opt,name=height" json:"height,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BaseMessage) Reset() { *m = BaseMessage{} } +func (m *BaseMessage) String() string { return proto.CompactTextString(m) } +func (*BaseMessage) ProtoMessage() {} +func (*BaseMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_2fbd53bac0b7ca8a, []int{0} +} + +var extRange_BaseMessage = []proto.ExtensionRange{ + {Start: 4, End: 9}, + {Start: 16, End: 536870911}, +} + +func (*BaseMessage) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_BaseMessage +} + +func (m *BaseMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BaseMessage.Unmarshal(m, b) +} +func (m *BaseMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BaseMessage.Marshal(b, m, deterministic) +} +func (m *BaseMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_BaseMessage.Merge(m, src) +} +func (m *BaseMessage) XXX_Size() int { + return xxx_messageInfo_BaseMessage.Size(m) +} +func (m *BaseMessage) XXX_DiscardUnknown() { + xxx_messageInfo_BaseMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_BaseMessage proto.InternalMessageInfo + +func (m *BaseMessage) GetHeight() int32 { + if m != nil && m.Height != nil { + return *m.Height + } + return 0 +} + +// Another message that may be extended, using message_set_wire_format. +type OldStyleMessage struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `protobuf_messageset:"1" json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OldStyleMessage) Reset() { *m = OldStyleMessage{} } +func (m *OldStyleMessage) String() string { return proto.CompactTextString(m) } +func (*OldStyleMessage) ProtoMessage() {} +func (*OldStyleMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_2fbd53bac0b7ca8a, []int{1} +} + +var extRange_OldStyleMessage = []proto.ExtensionRange{ + {Start: 100, End: 2147483646}, +} + +func (*OldStyleMessage) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_OldStyleMessage +} + +func (m *OldStyleMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OldStyleMessage.Unmarshal(m, b) +} +func (m *OldStyleMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OldStyleMessage.Marshal(b, m, deterministic) +} +func (m *OldStyleMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_OldStyleMessage.Merge(m, src) +} +func (m *OldStyleMessage) XXX_Size() int { + return xxx_messageInfo_OldStyleMessage.Size(m) +} +func (m *OldStyleMessage) XXX_DiscardUnknown() { + xxx_messageInfo_OldStyleMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_OldStyleMessage proto.InternalMessageInfo + +func init() { + proto.RegisterType((*BaseMessage)(nil), "extension_base.BaseMessage") + proto.RegisterType((*OldStyleMessage)(nil), "extension_base.OldStyleMessage") +} + +func init() { + proto.RegisterFile("extension_base/extension_base.proto", fileDescriptor_2fbd53bac0b7ca8a) +} + +var fileDescriptor_2fbd53bac0b7ca8a = []byte{ + // 179 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4e, 0xad, 0x28, 0x49, + 0xcd, 0x2b, 0xce, 0xcc, 0xcf, 0x8b, 0x4f, 0x4a, 0x2c, 0x4e, 0xd5, 0x47, 0xe5, 0xea, 0x15, 0x14, + 0xe5, 0x97, 0xe4, 0x0b, 0xf1, 0xa1, 0x8a, 0x2a, 0x99, 0x72, 0x71, 0x3b, 0x25, 0x16, 0xa7, 0xfa, + 0xa6, 0x16, 0x17, 0x27, 0xa6, 0xa7, 0x0a, 0x89, 0x71, 0xb1, 0x65, 0xa4, 0x66, 0xa6, 0x67, 0x94, + 0x48, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, 0x41, 0x79, 0x5a, 0x2c, 0x1c, 0x2c, 0x02, 0x5c, 0x5a, + 0x1c, 0x1c, 0x02, 0x02, 0x0d, 0x0d, 0x0d, 0x0d, 0x4c, 0x4a, 0xf2, 0x5c, 0xfc, 0xfe, 0x39, 0x29, + 0xc1, 0x25, 0x95, 0x39, 0x30, 0xad, 0x5a, 0x1c, 0x1c, 0x29, 0x02, 0xff, 0xff, 0xff, 0xff, 0xcf, + 0x6e, 0xc5, 0xc4, 0xc1, 0xe8, 0xe4, 0x14, 0xe5, 0x90, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, + 0x9c, 0x9f, 0xab, 0x9f, 0x9e, 0x9f, 0x93, 0x98, 0x97, 0xae, 0x0f, 0x76, 0x42, 0x52, 0x69, 0x1a, + 0x84, 0x91, 0xac, 0x9b, 0x9e, 0x9a, 0xa7, 0x9b, 0x9e, 0xaf, 0x5f, 0x92, 0x5a, 0x5c, 0x92, 0x92, + 0x58, 0x92, 0x88, 0xe6, 0x62, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x7f, 0xb7, 0x2a, 0xd1, + 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base/extension_base.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base/extension_base.proto new file mode 100644 index 0000000000..0ba74def8b --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base/extension_base.proto @@ -0,0 +1,48 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package extension_base; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/extension_base"; + +message BaseMessage { + optional int32 height = 1; + extensions 4 to 9; + extensions 16 to max; +} + +// Another message that may be extended, using message_set_wire_format. +message OldStyleMessage { + option message_set_wire_format = true; + extensions 100 to max; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra/extension_extra.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra/extension_extra.pb.go new file mode 100644 index 0000000000..fd82a253b8 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra/extension_extra.pb.go @@ -0,0 +1,81 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: extension_extra/extension_extra.proto + +package extension_extra + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type ExtraMessage struct { + Width *int32 `protobuf:"varint,1,opt,name=width" json:"width,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ExtraMessage) Reset() { *m = ExtraMessage{} } +func (m *ExtraMessage) String() string { return proto.CompactTextString(m) } +func (*ExtraMessage) ProtoMessage() {} +func (*ExtraMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_fce75f5a63502cd5, []int{0} +} + +func (m *ExtraMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ExtraMessage.Unmarshal(m, b) +} +func (m *ExtraMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ExtraMessage.Marshal(b, m, deterministic) +} +func (m *ExtraMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtraMessage.Merge(m, src) +} +func (m *ExtraMessage) XXX_Size() int { + return xxx_messageInfo_ExtraMessage.Size(m) +} +func (m *ExtraMessage) XXX_DiscardUnknown() { + xxx_messageInfo_ExtraMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtraMessage proto.InternalMessageInfo + +func (m *ExtraMessage) GetWidth() int32 { + if m != nil && m.Width != nil { + return *m.Width + } + return 0 +} + +func init() { + proto.RegisterType((*ExtraMessage)(nil), "extension_extra.ExtraMessage") +} + +func init() { + proto.RegisterFile("extension_extra/extension_extra.proto", fileDescriptor_fce75f5a63502cd5) +} + +var fileDescriptor_fce75f5a63502cd5 = []byte{ + // 133 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0xad, 0x28, 0x49, + 0xcd, 0x2b, 0xce, 0xcc, 0xcf, 0x8b, 0x4f, 0xad, 0x28, 0x29, 0x4a, 0xd4, 0x47, 0xe3, 0xeb, 0x15, + 0x14, 0xe5, 0x97, 0xe4, 0x0b, 0xf1, 0xa3, 0x09, 0x2b, 0xa9, 0x70, 0xf1, 0xb8, 0x82, 0x18, 0xbe, + 0xa9, 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0x42, 0x22, 0x5c, 0xac, 0xe5, 0x99, 0x29, 0x25, 0x19, 0x12, + 0x8c, 0x0a, 0x8c, 0x1a, 0xac, 0x41, 0x10, 0x8e, 0x93, 0x73, 0x94, 0x63, 0x7a, 0x66, 0x49, 0x46, + 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x7a, 0x7e, 0x4e, 0x62, 0x5e, 0xba, 0x3e, 0xd8, 0xc4, + 0xa4, 0xd2, 0x34, 0x08, 0x23, 0x59, 0x37, 0x3d, 0x35, 0x4f, 0x37, 0x3d, 0x5f, 0xbf, 0x24, 0xb5, + 0xb8, 0x24, 0x25, 0xb1, 0x04, 0xc3, 0x05, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf1, 0xec, 0xe3, + 0xb7, 0xa3, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra/extension_extra.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra/extension_extra.proto new file mode 100644 index 0000000000..1dd03e70b9 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra/extension_extra.proto @@ -0,0 +1,40 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package extension_extra; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra"; + +message ExtraMessage { + optional int32 width = 1; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user/extension_user.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user/extension_user.pb.go new file mode 100644 index 0000000000..d7849be2b6 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user/extension_user.pb.go @@ -0,0 +1,408 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: extension_user/extension_user.proto + +package extension_user + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + extension_base "github.com/golang/protobuf/protoc-gen-go/testdata/extension_base" + extension_extra "github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type UserMessage struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Rank *string `protobuf:"bytes,2,opt,name=rank" json:"rank,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UserMessage) Reset() { *m = UserMessage{} } +func (m *UserMessage) String() string { return proto.CompactTextString(m) } +func (*UserMessage) ProtoMessage() {} +func (*UserMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_359ba8abf543ca10, []int{0} +} + +func (m *UserMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UserMessage.Unmarshal(m, b) +} +func (m *UserMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UserMessage.Marshal(b, m, deterministic) +} +func (m *UserMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_UserMessage.Merge(m, src) +} +func (m *UserMessage) XXX_Size() int { + return xxx_messageInfo_UserMessage.Size(m) +} +func (m *UserMessage) XXX_DiscardUnknown() { + xxx_messageInfo_UserMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_UserMessage proto.InternalMessageInfo + +func (m *UserMessage) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *UserMessage) GetRank() string { + if m != nil && m.Rank != nil { + return *m.Rank + } + return "" +} + +// Extend inside the scope of another type +type LoudMessage struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LoudMessage) Reset() { *m = LoudMessage{} } +func (m *LoudMessage) String() string { return proto.CompactTextString(m) } +func (*LoudMessage) ProtoMessage() {} +func (*LoudMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_359ba8abf543ca10, []int{1} +} + +var extRange_LoudMessage = []proto.ExtensionRange{ + {Start: 100, End: 536870911}, +} + +func (*LoudMessage) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_LoudMessage +} + +func (m *LoudMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LoudMessage.Unmarshal(m, b) +} +func (m *LoudMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LoudMessage.Marshal(b, m, deterministic) +} +func (m *LoudMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_LoudMessage.Merge(m, src) +} +func (m *LoudMessage) XXX_Size() int { + return xxx_messageInfo_LoudMessage.Size(m) +} +func (m *LoudMessage) XXX_DiscardUnknown() { + xxx_messageInfo_LoudMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_LoudMessage proto.InternalMessageInfo + +var E_LoudMessage_Volume = &proto.ExtensionDesc{ + ExtendedType: (*extension_base.BaseMessage)(nil), + ExtensionType: (*uint32)(nil), + Field: 8, + Name: "extension_user.LoudMessage.volume", + Tag: "varint,8,opt,name=volume", + Filename: "extension_user/extension_user.proto", +} + +// Extend inside the scope of another type, using a message. +type LoginMessage struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LoginMessage) Reset() { *m = LoginMessage{} } +func (m *LoginMessage) String() string { return proto.CompactTextString(m) } +func (*LoginMessage) ProtoMessage() {} +func (*LoginMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_359ba8abf543ca10, []int{2} +} + +func (m *LoginMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LoginMessage.Unmarshal(m, b) +} +func (m *LoginMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LoginMessage.Marshal(b, m, deterministic) +} +func (m *LoginMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_LoginMessage.Merge(m, src) +} +func (m *LoginMessage) XXX_Size() int { + return xxx_messageInfo_LoginMessage.Size(m) +} +func (m *LoginMessage) XXX_DiscardUnknown() { + xxx_messageInfo_LoginMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_LoginMessage proto.InternalMessageInfo + +var E_LoginMessage_UserMessage = &proto.ExtensionDesc{ + ExtendedType: (*extension_base.BaseMessage)(nil), + ExtensionType: (*UserMessage)(nil), + Field: 16, + Name: "extension_user.LoginMessage.user_message", + Tag: "bytes,16,opt,name=user_message", + Filename: "extension_user/extension_user.proto", +} + +type Detail struct { + Color *string `protobuf:"bytes,1,opt,name=color" json:"color,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Detail) Reset() { *m = Detail{} } +func (m *Detail) String() string { return proto.CompactTextString(m) } +func (*Detail) ProtoMessage() {} +func (*Detail) Descriptor() ([]byte, []int) { + return fileDescriptor_359ba8abf543ca10, []int{3} +} + +func (m *Detail) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Detail.Unmarshal(m, b) +} +func (m *Detail) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Detail.Marshal(b, m, deterministic) +} +func (m *Detail) XXX_Merge(src proto.Message) { + xxx_messageInfo_Detail.Merge(m, src) +} +func (m *Detail) XXX_Size() int { + return xxx_messageInfo_Detail.Size(m) +} +func (m *Detail) XXX_DiscardUnknown() { + xxx_messageInfo_Detail.DiscardUnknown(m) +} + +var xxx_messageInfo_Detail proto.InternalMessageInfo + +func (m *Detail) GetColor() string { + if m != nil && m.Color != nil { + return *m.Color + } + return "" +} + +// An extension of an extension +type Announcement struct { + Words *string `protobuf:"bytes,1,opt,name=words" json:"words,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Announcement) Reset() { *m = Announcement{} } +func (m *Announcement) String() string { return proto.CompactTextString(m) } +func (*Announcement) ProtoMessage() {} +func (*Announcement) Descriptor() ([]byte, []int) { + return fileDescriptor_359ba8abf543ca10, []int{4} +} + +func (m *Announcement) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Announcement.Unmarshal(m, b) +} +func (m *Announcement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Announcement.Marshal(b, m, deterministic) +} +func (m *Announcement) XXX_Merge(src proto.Message) { + xxx_messageInfo_Announcement.Merge(m, src) +} +func (m *Announcement) XXX_Size() int { + return xxx_messageInfo_Announcement.Size(m) +} +func (m *Announcement) XXX_DiscardUnknown() { + xxx_messageInfo_Announcement.DiscardUnknown(m) +} + +var xxx_messageInfo_Announcement proto.InternalMessageInfo + +func (m *Announcement) GetWords() string { + if m != nil && m.Words != nil { + return *m.Words + } + return "" +} + +var E_Announcement_LoudExt = &proto.ExtensionDesc{ + ExtendedType: (*LoudMessage)(nil), + ExtensionType: (*Announcement)(nil), + Field: 100, + Name: "extension_user.Announcement.loud_ext", + Tag: "bytes,100,opt,name=loud_ext", + Filename: "extension_user/extension_user.proto", +} + +// Something that can be put in a message set. +type OldStyleParcel struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Height *int32 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OldStyleParcel) Reset() { *m = OldStyleParcel{} } +func (m *OldStyleParcel) String() string { return proto.CompactTextString(m) } +func (*OldStyleParcel) ProtoMessage() {} +func (*OldStyleParcel) Descriptor() ([]byte, []int) { + return fileDescriptor_359ba8abf543ca10, []int{5} +} + +func (m *OldStyleParcel) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OldStyleParcel.Unmarshal(m, b) +} +func (m *OldStyleParcel) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OldStyleParcel.Marshal(b, m, deterministic) +} +func (m *OldStyleParcel) XXX_Merge(src proto.Message) { + xxx_messageInfo_OldStyleParcel.Merge(m, src) +} +func (m *OldStyleParcel) XXX_Size() int { + return xxx_messageInfo_OldStyleParcel.Size(m) +} +func (m *OldStyleParcel) XXX_DiscardUnknown() { + xxx_messageInfo_OldStyleParcel.DiscardUnknown(m) +} + +var xxx_messageInfo_OldStyleParcel proto.InternalMessageInfo + +func (m *OldStyleParcel) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *OldStyleParcel) GetHeight() int32 { + if m != nil && m.Height != nil { + return *m.Height + } + return 0 +} + +var E_OldStyleParcel_MessageSetExtension = &proto.ExtensionDesc{ + ExtendedType: (*extension_base.OldStyleMessage)(nil), + ExtensionType: (*OldStyleParcel)(nil), + Field: 2001, + Name: "extension_user.OldStyleParcel", + Tag: "bytes,2001,opt,name=message_set_extension", + Filename: "extension_user/extension_user.proto", +} + +var E_UserMessage = &proto.ExtensionDesc{ + ExtendedType: (*extension_base.BaseMessage)(nil), + ExtensionType: (*UserMessage)(nil), + Field: 5, + Name: "extension_user.user_message", + Tag: "bytes,5,opt,name=user_message", + Filename: "extension_user/extension_user.proto", +} + +var E_ExtraMessage = &proto.ExtensionDesc{ + ExtendedType: (*extension_base.BaseMessage)(nil), + ExtensionType: (*extension_extra.ExtraMessage)(nil), + Field: 9, + Name: "extension_user.extra_message", + Tag: "bytes,9,opt,name=extra_message", + Filename: "extension_user/extension_user.proto", +} + +var E_Width = &proto.ExtensionDesc{ + ExtendedType: (*extension_base.BaseMessage)(nil), + ExtensionType: (*int32)(nil), + Field: 6, + Name: "extension_user.width", + Tag: "varint,6,opt,name=width", + Filename: "extension_user/extension_user.proto", +} + +var E_Area = &proto.ExtensionDesc{ + ExtendedType: (*extension_base.BaseMessage)(nil), + ExtensionType: (*int64)(nil), + Field: 7, + Name: "extension_user.area", + Tag: "varint,7,opt,name=area", + Filename: "extension_user/extension_user.proto", +} + +var E_Detail = &proto.ExtensionDesc{ + ExtendedType: (*extension_base.BaseMessage)(nil), + ExtensionType: ([]*Detail)(nil), + Field: 17, + Name: "extension_user.detail", + Tag: "bytes,17,rep,name=detail", + Filename: "extension_user/extension_user.proto", +} + +func init() { + proto.RegisterType((*UserMessage)(nil), "extension_user.UserMessage") + proto.RegisterExtension(E_LoudMessage_Volume) + proto.RegisterType((*LoudMessage)(nil), "extension_user.LoudMessage") + proto.RegisterExtension(E_LoginMessage_UserMessage) + proto.RegisterType((*LoginMessage)(nil), "extension_user.LoginMessage") + proto.RegisterType((*Detail)(nil), "extension_user.Detail") + proto.RegisterExtension(E_Announcement_LoudExt) + proto.RegisterType((*Announcement)(nil), "extension_user.Announcement") + proto.RegisterExtension(E_OldStyleParcel_MessageSetExtension) + proto.RegisterType((*OldStyleParcel)(nil), "extension_user.OldStyleParcel") + proto.RegisterExtension(E_UserMessage) + proto.RegisterExtension(E_ExtraMessage) + proto.RegisterExtension(E_Width) + proto.RegisterExtension(E_Area) + proto.RegisterExtension(E_Detail) +} + +func init() { + proto.RegisterFile("extension_user/extension_user.proto", fileDescriptor_359ba8abf543ca10) +} + +var fileDescriptor_359ba8abf543ca10 = []byte{ + // 492 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x51, 0x6f, 0x94, 0x40, + 0x10, 0x0e, 0x6d, 0x8f, 0x5e, 0x87, 0x6b, 0xad, 0xa8, 0xcd, 0xa5, 0x6a, 0x25, 0x18, 0x13, 0x62, + 0xd2, 0x23, 0x62, 0x7c, 0xe1, 0x49, 0x2f, 0xde, 0x93, 0x67, 0x34, 0x54, 0x5f, 0xf4, 0x81, 0xec, + 0xc1, 0xc8, 0x91, 0xc2, 0xae, 0xd9, 0x5d, 0xec, 0xe9, 0xd3, 0xfd, 0x26, 0xff, 0x89, 0xff, 0xc8, + 0xb0, 0x2c, 0x2d, 0x87, 0xc9, 0xc5, 0xbe, 0x90, 0xfd, 0x86, 0x6f, 0xbe, 0x99, 0xfd, 0x66, 0x00, + 0x9e, 0xe2, 0x4a, 0x22, 0x15, 0x39, 0xa3, 0x71, 0x25, 0x90, 0xfb, 0x9b, 0x70, 0xf2, 0x9d, 0x33, + 0xc9, 0xec, 0xa3, 0xcd, 0xe8, 0x69, 0x27, 0x69, 0x41, 0x04, 0xfa, 0x9b, 0xb0, 0x49, 0x3a, 0x7d, + 0x76, 0x13, 0xc5, 0x95, 0xe4, 0xc4, 0xef, 0xe1, 0x86, 0xe6, 0xbe, 0x02, 0xeb, 0xb3, 0x40, 0xfe, + 0x1e, 0x85, 0x20, 0x19, 0xda, 0x36, 0xec, 0x51, 0x52, 0xe2, 0xd8, 0x70, 0x0c, 0xef, 0x20, 0x52, + 0xe7, 0x3a, 0xc6, 0x09, 0xbd, 0x1c, 0xef, 0x34, 0xb1, 0xfa, 0xec, 0xce, 0xc1, 0x9a, 0xb3, 0x2a, + 0xd5, 0x69, 0xcf, 0x87, 0xc3, 0xf4, 0x78, 0xbd, 0x5e, 0xaf, 0x77, 0x82, 0x97, 0x60, 0xfe, 0x60, + 0x45, 0x55, 0xa2, 0xfd, 0x70, 0xd2, 0xeb, 0x6b, 0x4a, 0x04, 0xea, 0x84, 0xf1, 0xd0, 0x31, 0xbc, + 0xc3, 0x48, 0x53, 0xdd, 0x4b, 0x18, 0xcd, 0x59, 0x96, 0x53, 0xfd, 0x36, 0xf8, 0x0a, 0xa3, 0xfa, + 0xa2, 0x71, 0xa9, 0xbb, 0xda, 0x2a, 0x75, 0xec, 0x18, 0x9e, 0x15, 0x74, 0x29, 0xca, 0xba, 0xce, + 0xad, 0x22, 0xab, 0xba, 0x01, 0xee, 0x19, 0x98, 0x6f, 0x51, 0x92, 0xbc, 0xb0, 0xef, 0xc3, 0x20, + 0x61, 0x05, 0xe3, 0xfa, 0xb6, 0x0d, 0x70, 0x7f, 0xc1, 0xe8, 0x0d, 0xa5, 0xac, 0xa2, 0x09, 0x96, + 0x48, 0x65, 0xcd, 0xba, 0x62, 0x3c, 0x15, 0x2d, 0x4b, 0x81, 0xe0, 0x13, 0x0c, 0x0b, 0x56, 0xa5, + 0xb5, 0x97, 0xf6, 0x3f, 0xb5, 0x3b, 0xd6, 0x8c, 0x53, 0xd5, 0xde, 0xa3, 0x3e, 0xa5, 0x5b, 0x22, + 0xda, 0xaf, 0xa5, 0x66, 0x2b, 0xe9, 0xfe, 0x36, 0xe0, 0xe8, 0x43, 0x91, 0x5e, 0xc8, 0x9f, 0x05, + 0x7e, 0x24, 0x3c, 0xc1, 0xa2, 0x33, 0x91, 0x9d, 0xeb, 0x89, 0x9c, 0x80, 0xb9, 0xc4, 0x3c, 0x5b, + 0x4a, 0x35, 0x93, 0x41, 0xa4, 0x51, 0x20, 0xe1, 0x81, 0xb6, 0x2c, 0x16, 0x28, 0xe3, 0xeb, 0x92, + 0xf6, 0x93, 0xbe, 0x81, 0x6d, 0x91, 0xb6, 0xcb, 0x3f, 0x77, 0x54, 0x9b, 0x67, 0xfd, 0x36, 0x37, + 0x9b, 0x89, 0xee, 0x69, 0xf9, 0x0b, 0x94, 0xb3, 0x96, 0x18, 0xde, 0x6a, 0x5a, 0x83, 0xdb, 0x4d, + 0x2b, 0x8c, 0xe1, 0x50, 0xad, 0xeb, 0xff, 0xa9, 0x1f, 0x28, 0xf5, 0xc7, 0x93, 0xfe, 0xae, 0xcf, + 0xea, 0x67, 0xab, 0x3f, 0xc2, 0x0e, 0x0a, 0x5f, 0xc0, 0xe0, 0x2a, 0x4f, 0xe5, 0x72, 0xbb, 0xb0, + 0xa9, 0x7c, 0x6e, 0x98, 0xa1, 0x0f, 0x7b, 0x84, 0x23, 0xd9, 0x9e, 0xb1, 0xef, 0x18, 0xde, 0x6e, + 0xa4, 0x88, 0xe1, 0x3b, 0x30, 0xd3, 0x66, 0xe5, 0xb6, 0xa6, 0xdc, 0x75, 0x76, 0x3d, 0x2b, 0x38, + 0xe9, 0x7b, 0xd3, 0x6c, 0x6b, 0xa4, 0x25, 0xa6, 0xd3, 0x2f, 0xaf, 0xb3, 0x5c, 0x2e, 0xab, 0xc5, + 0x24, 0x61, 0xa5, 0x9f, 0xb1, 0x82, 0xd0, 0xcc, 0x57, 0x1f, 0xf3, 0xa2, 0xfa, 0xd6, 0x1c, 0x92, + 0xf3, 0x0c, 0xe9, 0x79, 0xc6, 0x7c, 0x89, 0x42, 0xa6, 0x44, 0x92, 0xde, 0x7f, 0xe5, 0x6f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xdf, 0x18, 0x64, 0x15, 0x77, 0x04, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user/extension_user.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user/extension_user.proto new file mode 100644 index 0000000000..033c186c03 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user/extension_user.proto @@ -0,0 +1,102 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +import "extension_base/extension_base.proto"; +import "extension_extra/extension_extra.proto"; + +package extension_user; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/extension_user"; + +message UserMessage { + optional string name = 1; + optional string rank = 2; +} + +// Extend with a message +extend extension_base.BaseMessage { + optional UserMessage user_message = 5; +} + +// Extend with a foreign message +extend extension_base.BaseMessage { + optional extension_extra.ExtraMessage extra_message = 9; +} + +// Extend with some primitive types +extend extension_base.BaseMessage { + optional int32 width = 6; + optional int64 area = 7; +} + +// Extend inside the scope of another type +message LoudMessage { + extend extension_base.BaseMessage { + optional uint32 volume = 8; + } + extensions 100 to max; +} + +// Extend inside the scope of another type, using a message. +message LoginMessage { + extend extension_base.BaseMessage { + optional UserMessage user_message = 16; + } +} + +// Extend with a repeated field +extend extension_base.BaseMessage { + repeated Detail detail = 17; +} + +message Detail { + optional string color = 1; +} + +// An extension of an extension +message Announcement { + optional string words = 1; + extend LoudMessage { + optional Announcement loud_ext = 100; + } +} + +// Something that can be put in a message set. +message OldStyleParcel { + extend extension_base.OldStyleMessage { + optional OldStyleParcel message_set_extension = 2001; + } + + required string name = 1; + optional int32 height = 2; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc.pb.go new file mode 100644 index 0000000000..76c9a20a11 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc.pb.go @@ -0,0 +1,466 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: grpc/grpc.proto + +package testing + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type SimpleRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SimpleRequest) Reset() { *m = SimpleRequest{} } +func (m *SimpleRequest) String() string { return proto.CompactTextString(m) } +func (*SimpleRequest) ProtoMessage() {} +func (*SimpleRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_81ea47a3f88c2082, []int{0} +} + +func (m *SimpleRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SimpleRequest.Unmarshal(m, b) +} +func (m *SimpleRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SimpleRequest.Marshal(b, m, deterministic) +} +func (m *SimpleRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SimpleRequest.Merge(m, src) +} +func (m *SimpleRequest) XXX_Size() int { + return xxx_messageInfo_SimpleRequest.Size(m) +} +func (m *SimpleRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SimpleRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SimpleRequest proto.InternalMessageInfo + +type SimpleResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SimpleResponse) Reset() { *m = SimpleResponse{} } +func (m *SimpleResponse) String() string { return proto.CompactTextString(m) } +func (*SimpleResponse) ProtoMessage() {} +func (*SimpleResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_81ea47a3f88c2082, []int{1} +} + +func (m *SimpleResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SimpleResponse.Unmarshal(m, b) +} +func (m *SimpleResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SimpleResponse.Marshal(b, m, deterministic) +} +func (m *SimpleResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SimpleResponse.Merge(m, src) +} +func (m *SimpleResponse) XXX_Size() int { + return xxx_messageInfo_SimpleResponse.Size(m) +} +func (m *SimpleResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SimpleResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SimpleResponse proto.InternalMessageInfo + +type StreamMsg struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StreamMsg) Reset() { *m = StreamMsg{} } +func (m *StreamMsg) String() string { return proto.CompactTextString(m) } +func (*StreamMsg) ProtoMessage() {} +func (*StreamMsg) Descriptor() ([]byte, []int) { + return fileDescriptor_81ea47a3f88c2082, []int{2} +} + +func (m *StreamMsg) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StreamMsg.Unmarshal(m, b) +} +func (m *StreamMsg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StreamMsg.Marshal(b, m, deterministic) +} +func (m *StreamMsg) XXX_Merge(src proto.Message) { + xxx_messageInfo_StreamMsg.Merge(m, src) +} +func (m *StreamMsg) XXX_Size() int { + return xxx_messageInfo_StreamMsg.Size(m) +} +func (m *StreamMsg) XXX_DiscardUnknown() { + xxx_messageInfo_StreamMsg.DiscardUnknown(m) +} + +var xxx_messageInfo_StreamMsg proto.InternalMessageInfo + +type StreamMsg2 struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StreamMsg2) Reset() { *m = StreamMsg2{} } +func (m *StreamMsg2) String() string { return proto.CompactTextString(m) } +func (*StreamMsg2) ProtoMessage() {} +func (*StreamMsg2) Descriptor() ([]byte, []int) { + return fileDescriptor_81ea47a3f88c2082, []int{3} +} + +func (m *StreamMsg2) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StreamMsg2.Unmarshal(m, b) +} +func (m *StreamMsg2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StreamMsg2.Marshal(b, m, deterministic) +} +func (m *StreamMsg2) XXX_Merge(src proto.Message) { + xxx_messageInfo_StreamMsg2.Merge(m, src) +} +func (m *StreamMsg2) XXX_Size() int { + return xxx_messageInfo_StreamMsg2.Size(m) +} +func (m *StreamMsg2) XXX_DiscardUnknown() { + xxx_messageInfo_StreamMsg2.DiscardUnknown(m) +} + +var xxx_messageInfo_StreamMsg2 proto.InternalMessageInfo + +func init() { + proto.RegisterType((*SimpleRequest)(nil), "grpc.testing.SimpleRequest") + proto.RegisterType((*SimpleResponse)(nil), "grpc.testing.SimpleResponse") + proto.RegisterType((*StreamMsg)(nil), "grpc.testing.StreamMsg") + proto.RegisterType((*StreamMsg2)(nil), "grpc.testing.StreamMsg2") +} + +func init() { proto.RegisterFile("grpc/grpc.proto", fileDescriptor_81ea47a3f88c2082) } + +var fileDescriptor_81ea47a3f88c2082 = []byte{ + // 244 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4f, 0x2f, 0x2a, 0x48, + 0xd6, 0x07, 0x11, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x3c, 0x60, 0x76, 0x49, 0x6a, 0x71, + 0x49, 0x66, 0x5e, 0xba, 0x12, 0x3f, 0x17, 0x6f, 0x70, 0x66, 0x6e, 0x41, 0x4e, 0x6a, 0x50, 0x6a, + 0x61, 0x69, 0x6a, 0x71, 0x89, 0x92, 0x00, 0x17, 0x1f, 0x4c, 0xa0, 0xb8, 0x20, 0x3f, 0xaf, 0x38, + 0x55, 0x89, 0x9b, 0x8b, 0x33, 0xb8, 0xa4, 0x28, 0x35, 0x31, 0xd7, 0xb7, 0x38, 0x5d, 0x89, 0x87, + 0x8b, 0x0b, 0xce, 0x31, 0x32, 0x9a, 0xc1, 0xc4, 0xc5, 0x12, 0x92, 0x5a, 0x5c, 0x22, 0xe4, 0xc6, + 0xc5, 0x19, 0x9a, 0x97, 0x58, 0x54, 0xe9, 0x9c, 0x98, 0x93, 0x23, 0x24, 0xad, 0x87, 0x6c, 0x85, + 0x1e, 0x8a, 0xf9, 0x52, 0x32, 0xd8, 0x25, 0x21, 0x76, 0x09, 0xb9, 0x70, 0x71, 0xb9, 0xe4, 0x97, + 0xe7, 0x15, 0x83, 0xad, 0xc0, 0x6f, 0x90, 0x38, 0x9a, 0x24, 0xcc, 0x55, 0x06, 0x8c, 0x42, 0xce, + 0x5c, 0x1c, 0xa1, 0x05, 0x50, 0x33, 0x70, 0x29, 0xc3, 0xef, 0x10, 0x0d, 0x46, 0x21, 0x5b, 0x2e, + 0x16, 0xa7, 0xcc, 0x94, 0x4c, 0xdc, 0x06, 0x48, 0xe0, 0x90, 0x30, 0xd2, 0x60, 0x34, 0x60, 0x74, + 0x72, 0x88, 0xb2, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, + 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x07, 0xc7, 0x40, 0x52, 0x69, 0x1a, 0x84, 0x91, 0xac, 0x9b, 0x9e, + 0x9a, 0xa7, 0x9b, 0x9e, 0xaf, 0x0f, 0x32, 0x22, 0x25, 0xb1, 0x24, 0x11, 0x1c, 0x4d, 0xd6, 0x50, + 0x03, 0x93, 0xd8, 0xc0, 0x8a, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x90, 0xb9, 0x95, 0x42, + 0xc2, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// TestClient is the client API for Test service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type TestClient interface { + UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) + // This RPC streams from the server only. + Downstream(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (Test_DownstreamClient, error) + // This RPC streams from the client. + Upstream(ctx context.Context, opts ...grpc.CallOption) (Test_UpstreamClient, error) + // This one streams in both directions. + Bidi(ctx context.Context, opts ...grpc.CallOption) (Test_BidiClient, error) +} + +type testClient struct { + cc *grpc.ClientConn +} + +func NewTestClient(cc *grpc.ClientConn) TestClient { + return &testClient{cc} +} + +func (c *testClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) { + out := new(SimpleResponse) + err := c.cc.Invoke(ctx, "/grpc.testing.Test/UnaryCall", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testClient) Downstream(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (Test_DownstreamClient, error) { + stream, err := c.cc.NewStream(ctx, &_Test_serviceDesc.Streams[0], "/grpc.testing.Test/Downstream", opts...) + if err != nil { + return nil, err + } + x := &testDownstreamClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Test_DownstreamClient interface { + Recv() (*StreamMsg, error) + grpc.ClientStream +} + +type testDownstreamClient struct { + grpc.ClientStream +} + +func (x *testDownstreamClient) Recv() (*StreamMsg, error) { + m := new(StreamMsg) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *testClient) Upstream(ctx context.Context, opts ...grpc.CallOption) (Test_UpstreamClient, error) { + stream, err := c.cc.NewStream(ctx, &_Test_serviceDesc.Streams[1], "/grpc.testing.Test/Upstream", opts...) + if err != nil { + return nil, err + } + x := &testUpstreamClient{stream} + return x, nil +} + +type Test_UpstreamClient interface { + Send(*StreamMsg) error + CloseAndRecv() (*SimpleResponse, error) + grpc.ClientStream +} + +type testUpstreamClient struct { + grpc.ClientStream +} + +func (x *testUpstreamClient) Send(m *StreamMsg) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testUpstreamClient) CloseAndRecv() (*SimpleResponse, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(SimpleResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *testClient) Bidi(ctx context.Context, opts ...grpc.CallOption) (Test_BidiClient, error) { + stream, err := c.cc.NewStream(ctx, &_Test_serviceDesc.Streams[2], "/grpc.testing.Test/Bidi", opts...) + if err != nil { + return nil, err + } + x := &testBidiClient{stream} + return x, nil +} + +type Test_BidiClient interface { + Send(*StreamMsg) error + Recv() (*StreamMsg2, error) + grpc.ClientStream +} + +type testBidiClient struct { + grpc.ClientStream +} + +func (x *testBidiClient) Send(m *StreamMsg) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testBidiClient) Recv() (*StreamMsg2, error) { + m := new(StreamMsg2) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// TestServer is the server API for Test service. +type TestServer interface { + UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) + // This RPC streams from the server only. + Downstream(*SimpleRequest, Test_DownstreamServer) error + // This RPC streams from the client. + Upstream(Test_UpstreamServer) error + // This one streams in both directions. + Bidi(Test_BidiServer) error +} + +// UnimplementedTestServer can be embedded to have forward compatible implementations. +type UnimplementedTestServer struct { +} + +func (*UnimplementedTestServer) UnaryCall(ctx context.Context, req *SimpleRequest) (*SimpleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UnaryCall not implemented") +} +func (*UnimplementedTestServer) Downstream(req *SimpleRequest, srv Test_DownstreamServer) error { + return status.Errorf(codes.Unimplemented, "method Downstream not implemented") +} +func (*UnimplementedTestServer) Upstream(srv Test_UpstreamServer) error { + return status.Errorf(codes.Unimplemented, "method Upstream not implemented") +} +func (*UnimplementedTestServer) Bidi(srv Test_BidiServer) error { + return status.Errorf(codes.Unimplemented, "method Bidi not implemented") +} + +func RegisterTestServer(s *grpc.Server, srv TestServer) { + s.RegisterService(&_Test_serviceDesc, srv) +} + +func _Test_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SimpleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServer).UnaryCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.Test/UnaryCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServer).UnaryCall(ctx, req.(*SimpleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Test_Downstream_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SimpleRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(TestServer).Downstream(m, &testDownstreamServer{stream}) +} + +type Test_DownstreamServer interface { + Send(*StreamMsg) error + grpc.ServerStream +} + +type testDownstreamServer struct { + grpc.ServerStream +} + +func (x *testDownstreamServer) Send(m *StreamMsg) error { + return x.ServerStream.SendMsg(m) +} + +func _Test_Upstream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestServer).Upstream(&testUpstreamServer{stream}) +} + +type Test_UpstreamServer interface { + SendAndClose(*SimpleResponse) error + Recv() (*StreamMsg, error) + grpc.ServerStream +} + +type testUpstreamServer struct { + grpc.ServerStream +} + +func (x *testUpstreamServer) SendAndClose(m *SimpleResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testUpstreamServer) Recv() (*StreamMsg, error) { + m := new(StreamMsg) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _Test_Bidi_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestServer).Bidi(&testBidiServer{stream}) +} + +type Test_BidiServer interface { + Send(*StreamMsg2) error + Recv() (*StreamMsg, error) + grpc.ServerStream +} + +type testBidiServer struct { + grpc.ServerStream +} + +func (x *testBidiServer) Send(m *StreamMsg2) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testBidiServer) Recv() (*StreamMsg, error) { + m := new(StreamMsg) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _Test_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.testing.Test", + HandlerType: (*TestServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "UnaryCall", + Handler: _Test_UnaryCall_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Downstream", + Handler: _Test_Downstream_Handler, + ServerStreams: true, + }, + { + StreamName: "Upstream", + Handler: _Test_Upstream_Handler, + ClientStreams: true, + }, + { + StreamName: "Bidi", + Handler: _Test_Bidi_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "grpc/grpc.proto", +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc.proto new file mode 100644 index 0000000000..0e5c64a91e --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc.proto @@ -0,0 +1,61 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package grpc.testing; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/grpc;testing"; + +message SimpleRequest { +} + +message SimpleResponse { +} + +message StreamMsg { +} + +message StreamMsg2 { +} + +service Test { + rpc UnaryCall(SimpleRequest) returns (SimpleResponse); + + // This RPC streams from the server only. + rpc Downstream(SimpleRequest) returns (stream StreamMsg); + + // This RPC streams from the client. + rpc Upstream(stream StreamMsg) returns (SimpleResponse); + + // This one streams in both directions. + rpc Bidi(stream StreamMsg) returns (stream StreamMsg2); +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc_empty.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc_empty.pb.go new file mode 100644 index 0000000000..9c6244bc7a --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc_empty.pb.go @@ -0,0 +1,79 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: grpc/grpc_empty.proto + +package testing + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +func init() { proto.RegisterFile("grpc/grpc_empty.proto", fileDescriptor_c580a37f1c90e9b1) } + +var fileDescriptor_c580a37f1c90e9b1 = []byte{ + // 125 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4d, 0x2f, 0x2a, 0x48, + 0xd6, 0x07, 0x11, 0xf1, 0xa9, 0xb9, 0x05, 0x25, 0x95, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, + 0x3c, 0x20, 0x11, 0xbd, 0x92, 0xd4, 0xe2, 0x92, 0xcc, 0xbc, 0x74, 0x23, 0x3e, 0x2e, 0x1e, 0x57, + 0x90, 0x64, 0x70, 0x6a, 0x51, 0x59, 0x66, 0x72, 0xaa, 0x93, 0x43, 0x94, 0x5d, 0x7a, 0x66, 0x49, + 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x7a, 0x7e, 0x4e, 0x62, 0x5e, 0xba, 0x3e, 0x58, + 0x63, 0x52, 0x69, 0x1a, 0x84, 0x91, 0xac, 0x9b, 0x9e, 0x9a, 0xa7, 0x9b, 0x9e, 0xaf, 0x0f, 0x32, + 0x23, 0x25, 0xb1, 0x24, 0x11, 0x6c, 0x87, 0x35, 0xd4, 0xc4, 0x24, 0x36, 0xb0, 0x22, 0x63, 0x40, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x93, 0x1d, 0xf2, 0x47, 0x7f, 0x00, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// EmptyServiceClient is the client API for EmptyService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type EmptyServiceClient interface { +} + +type emptyServiceClient struct { + cc *grpc.ClientConn +} + +func NewEmptyServiceClient(cc *grpc.ClientConn) EmptyServiceClient { + return &emptyServiceClient{cc} +} + +// EmptyServiceServer is the server API for EmptyService service. +type EmptyServiceServer interface { +} + +// UnimplementedEmptyServiceServer can be embedded to have forward compatible implementations. +type UnimplementedEmptyServiceServer struct { +} + +func RegisterEmptyServiceServer(s *grpc.Server, srv EmptyServiceServer) { + s.RegisterService(&_EmptyService_serviceDesc, srv) +} + +var _EmptyService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.testing.EmptyService", + HandlerType: (*EmptyServiceServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: "grpc/grpc_empty.proto", +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc_empty.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc_empty.proto new file mode 100644 index 0000000000..ae07b81caa --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc/grpc_empty.proto @@ -0,0 +1,38 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2019 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package grpc.testing; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/grpc;testing"; + +service EmptyService {} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/a.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/a.pb.go new file mode 100644 index 0000000000..fa511fcbef --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/a.pb.go @@ -0,0 +1,141 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: import_public/a.proto + +package import_public + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + sub "github.com/golang/protobuf/protoc-gen-go/testdata/import_public/sub" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +const Default_M_DefaultField = sub.Default_M_DefaultField + +// M from public import import_public/sub/a.proto +type M = sub.M +type M_OneofInt32 = sub.M_OneofInt32 +type M_OneofInt64 = sub.M_OneofInt64 + +// M_Grouping from public import import_public/sub/a.proto +type M_Grouping = sub.M_Grouping + +// M_Submessage from public import import_public/sub/a.proto +type M_Submessage = sub.M_Submessage +type M_Submessage_SubmessageOneofInt32 = sub.M_Submessage_SubmessageOneofInt32 +type M_Submessage_SubmessageOneofInt64 = sub.M_Submessage_SubmessageOneofInt64 + +// E from public import import_public/sub/a.proto +type E = sub.E + +var E_name = sub.E_name +var E_value = sub.E_value + +const E_ZERO = E(sub.E_ZERO) + +// M_Subenum from public import import_public/sub/a.proto +type M_Subenum = sub.M_Subenum + +var M_Subenum_name = sub.M_Subenum_name +var M_Subenum_value = sub.M_Subenum_value + +const M_M_ZERO = M_Subenum(sub.M_M_ZERO) + +// M_Submessage_Submessage_Subenum from public import import_public/sub/a.proto +type M_Submessage_Submessage_Subenum = sub.M_Submessage_Submessage_Subenum + +var M_Submessage_Submessage_Subenum_name = sub.M_Submessage_Submessage_Subenum_name +var M_Submessage_Submessage_Subenum_value = sub.M_Submessage_Submessage_Subenum_value + +const M_Submessage_M_SUBMESSAGE_ZERO = M_Submessage_Submessage_Subenum(sub.M_Submessage_M_SUBMESSAGE_ZERO) + +var E_ExtensionField = sub.E_ExtensionField + +type Public struct { + M *sub.M `protobuf:"bytes,1,opt,name=m" json:"m,omitempty"` + E *sub.E `protobuf:"varint,2,opt,name=e,enum=goproto.test.import_public.sub.E" json:"e,omitempty"` + Local *Local `protobuf:"bytes,3,opt,name=local" json:"local,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Public) Reset() { *m = Public{} } +func (m *Public) String() string { return proto.CompactTextString(m) } +func (*Public) ProtoMessage() {} +func (*Public) Descriptor() ([]byte, []int) { + return fileDescriptor_73b7577c95fa6b70, []int{0} +} + +func (m *Public) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Public.Unmarshal(m, b) +} +func (m *Public) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Public.Marshal(b, m, deterministic) +} +func (m *Public) XXX_Merge(src proto.Message) { + xxx_messageInfo_Public.Merge(m, src) +} +func (m *Public) XXX_Size() int { + return xxx_messageInfo_Public.Size(m) +} +func (m *Public) XXX_DiscardUnknown() { + xxx_messageInfo_Public.DiscardUnknown(m) +} + +var xxx_messageInfo_Public proto.InternalMessageInfo + +func (m *Public) GetM() *sub.M { + if m != nil { + return m.M + } + return nil +} + +func (m *Public) GetE() sub.E { + if m != nil && m.E != nil { + return *m.E + } + return sub.E_ZERO +} + +func (m *Public) GetLocal() *Local { + if m != nil { + return m.Local + } + return nil +} + +func init() { + proto.RegisterType((*Public)(nil), "goproto.test.import_public.Public") +} + +func init() { proto.RegisterFile("import_public/a.proto", fileDescriptor_73b7577c95fa6b70) } + +var fileDescriptor_73b7577c95fa6b70 = []byte{ + // 195 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcd, 0xcc, 0x2d, 0xc8, + 0x2f, 0x2a, 0x89, 0x2f, 0x28, 0x4d, 0xca, 0xc9, 0x4c, 0xd6, 0x4f, 0xd4, 0x2b, 0x28, 0xca, 0x2f, + 0xc9, 0x17, 0x92, 0x4a, 0xcf, 0x07, 0x33, 0xf4, 0x4a, 0x52, 0x8b, 0x4b, 0xf4, 0x50, 0xd4, 0x48, + 0x49, 0xa2, 0x6a, 0x29, 0x2e, 0x4d, 0x82, 0x69, 0x93, 0x42, 0x33, 0x2d, 0x09, 0x22, 0xac, 0xb4, + 0x98, 0x91, 0x8b, 0x2d, 0x00, 0x2c, 0x24, 0xa4, 0xcf, 0xc5, 0x98, 0x2b, 0xc1, 0xa8, 0xc0, 0xa8, + 0xc1, 0x6d, 0xa4, 0xa8, 0x87, 0xdb, 0x12, 0xbd, 0xe2, 0xd2, 0x24, 0x3d, 0xdf, 0x20, 0xc6, 0x5c, + 0x90, 0x86, 0x54, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x3e, 0xc2, 0x1a, 0x5c, 0x83, 0x18, 0x53, 0x85, + 0xcc, 0xb9, 0x58, 0x73, 0xf2, 0x93, 0x13, 0x73, 0x24, 0x98, 0x09, 0xdb, 0xe2, 0x03, 0x52, 0x18, + 0x04, 0x51, 0xef, 0xe4, 0x18, 0x65, 0x9f, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, + 0xab, 0x9f, 0x9e, 0x9f, 0x93, 0x98, 0x97, 0xae, 0x0f, 0xd6, 0x9a, 0x54, 0x9a, 0x06, 0x61, 0x24, + 0xeb, 0xa6, 0xa7, 0xe6, 0xe9, 0xa6, 0xe7, 0xeb, 0x83, 0xcc, 0x4a, 0x49, 0x2c, 0x49, 0xd4, 0x47, + 0x31, 0x2f, 0x80, 0x21, 0x80, 0x11, 0x10, 0x00, 0x00, 0xff, 0xff, 0x17, 0x83, 0x2d, 0xd4, 0x52, + 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/a.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/a.proto new file mode 100644 index 0000000000..9a4e7c0234 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/a.proto @@ -0,0 +1,45 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2018 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package goproto.test.import_public; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/import_public"; + +import public "import_public/sub/a.proto"; // Different Go package. +import public "import_public/b.proto"; // Same Go package. + +message Public { + optional goproto.test.import_public.sub.M m = 1; + optional goproto.test.import_public.sub.E e = 2; + optional Local local = 3; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/b.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/b.pb.go new file mode 100644 index 0000000000..522f215ca2 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/b.pb.go @@ -0,0 +1,90 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: import_public/b.proto + +package import_public + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + sub "github.com/golang/protobuf/protoc-gen-go/testdata/import_public/sub" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type Local struct { + M *sub.M `protobuf:"bytes,1,opt,name=m" json:"m,omitempty"` + E *sub.E `protobuf:"varint,2,opt,name=e,enum=goproto.test.import_public.sub.E" json:"e,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Local) Reset() { *m = Local{} } +func (m *Local) String() string { return proto.CompactTextString(m) } +func (*Local) ProtoMessage() {} +func (*Local) Descriptor() ([]byte, []int) { + return fileDescriptor_84995586b3d09710, []int{0} +} + +func (m *Local) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Local.Unmarshal(m, b) +} +func (m *Local) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Local.Marshal(b, m, deterministic) +} +func (m *Local) XXX_Merge(src proto.Message) { + xxx_messageInfo_Local.Merge(m, src) +} +func (m *Local) XXX_Size() int { + return xxx_messageInfo_Local.Size(m) +} +func (m *Local) XXX_DiscardUnknown() { + xxx_messageInfo_Local.DiscardUnknown(m) +} + +var xxx_messageInfo_Local proto.InternalMessageInfo + +func (m *Local) GetM() *sub.M { + if m != nil { + return m.M + } + return nil +} + +func (m *Local) GetE() sub.E { + if m != nil && m.E != nil { + return *m.E + } + return sub.E_ZERO +} + +func init() { + proto.RegisterType((*Local)(nil), "goproto.test.import_public.Local") +} + +func init() { proto.RegisterFile("import_public/b.proto", fileDescriptor_84995586b3d09710) } + +var fileDescriptor_84995586b3d09710 = []byte{ + // 169 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcd, 0xcc, 0x2d, 0xc8, + 0x2f, 0x2a, 0x89, 0x2f, 0x28, 0x4d, 0xca, 0xc9, 0x4c, 0xd6, 0x4f, 0xd2, 0x2b, 0x28, 0xca, 0x2f, + 0xc9, 0x17, 0x92, 0x4a, 0xcf, 0x07, 0x33, 0xf4, 0x4a, 0x52, 0x8b, 0x4b, 0xf4, 0x50, 0xd4, 0x48, + 0x49, 0xa2, 0x6a, 0x29, 0x2e, 0x4d, 0xd2, 0x4f, 0x84, 0x68, 0x53, 0xca, 0xe4, 0x62, 0xf5, 0xc9, + 0x4f, 0x4e, 0xcc, 0x11, 0xd2, 0xe7, 0x62, 0xcc, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x36, 0x52, + 0xd4, 0xc3, 0x6d, 0x96, 0x5e, 0x71, 0x69, 0x92, 0x9e, 0x6f, 0x10, 0x63, 0x2e, 0x48, 0x43, 0xaa, + 0x04, 0x93, 0x02, 0xa3, 0x06, 0x1f, 0x61, 0x0d, 0xae, 0x41, 0x8c, 0xa9, 0x4e, 0x8e, 0x51, 0xf6, + 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xe9, 0xf9, 0x39, 0x89, 0x79, + 0xe9, 0xfa, 0x60, 0x6d, 0x49, 0xa5, 0x69, 0x10, 0x46, 0xb2, 0x6e, 0x7a, 0x6a, 0x9e, 0x6e, 0x7a, + 0xbe, 0x3e, 0xc8, 0x9c, 0x94, 0xc4, 0x92, 0x44, 0x7d, 0x14, 0xb3, 0x00, 0x01, 0x00, 0x00, 0xff, + 0xff, 0x35, 0x0e, 0x6a, 0x82, 0xfc, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/b.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/b.proto new file mode 100644 index 0000000000..424306ebd6 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/b.proto @@ -0,0 +1,43 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2018 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package goproto.test.import_public; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/import_public"; + +import "import_public/sub/a.proto"; + +message Local { + optional goproto.test.import_public.sub.M m = 1; + optional goproto.test.import_public.sub.E e = 2; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/importing/importing.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/importing/importing.pb.go new file mode 100644 index 0000000000..3f0f37e9a4 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/importing/importing.pb.go @@ -0,0 +1,85 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: import_public/importing/importing.proto + +package importing + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + _ "github.com/golang/protobuf/protoc-gen-go/testdata/import_public" + sub "github.com/golang/protobuf/protoc-gen-go/testdata/import_public/sub" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type M struct { + // Message type defined in a file publicly imported by a file we import. + M *sub.M `protobuf:"bytes,1,opt,name=m" json:"m,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *M) Reset() { *m = M{} } +func (m *M) String() string { return proto.CompactTextString(m) } +func (*M) ProtoMessage() {} +func (*M) Descriptor() ([]byte, []int) { + return fileDescriptor_36b835b3b8f6171a, []int{0} +} + +func (m *M) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_M.Unmarshal(m, b) +} +func (m *M) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_M.Marshal(b, m, deterministic) +} +func (m *M) XXX_Merge(src proto.Message) { + xxx_messageInfo_M.Merge(m, src) +} +func (m *M) XXX_Size() int { + return xxx_messageInfo_M.Size(m) +} +func (m *M) XXX_DiscardUnknown() { + xxx_messageInfo_M.DiscardUnknown(m) +} + +var xxx_messageInfo_M proto.InternalMessageInfo + +func (m *M) GetM() *sub.M { + if m != nil { + return m.M + } + return nil +} + +func init() { + proto.RegisterType((*M)(nil), "goproto.test.import_public.importing.M") +} + +func init() { + proto.RegisterFile("import_public/importing/importing.proto", fileDescriptor_36b835b3b8f6171a) +} + +var fileDescriptor_36b835b3b8f6171a = []byte{ + // 153 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xcf, 0xcc, 0x2d, 0xc8, + 0x2f, 0x2a, 0x89, 0x2f, 0x28, 0x4d, 0xca, 0xc9, 0x4c, 0xd6, 0x87, 0xf0, 0x32, 0xf3, 0xd2, 0x11, + 0x2c, 0xbd, 0x82, 0xa2, 0xfc, 0x92, 0x7c, 0x21, 0x95, 0xf4, 0x7c, 0x30, 0x43, 0xaf, 0x24, 0xb5, + 0xb8, 0x44, 0x0f, 0x45, 0x97, 0x1e, 0x5c, 0xad, 0x94, 0x28, 0xaa, 0x71, 0x89, 0x10, 0xcd, 0x4a, + 0x26, 0x5c, 0x8c, 0xbe, 0x42, 0xfa, 0x5c, 0x8c, 0xb9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, + 0x8a, 0x7a, 0x78, 0x4c, 0x2b, 0x2e, 0x4d, 0xd2, 0xf3, 0x0d, 0x62, 0xcc, 0x75, 0xf2, 0x8e, 0xf2, + 0x4c, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, + 0x4b, 0xd7, 0x07, 0x6b, 0x4b, 0x2a, 0x4d, 0x83, 0x30, 0x92, 0x75, 0xd3, 0x53, 0xf3, 0x74, 0xd3, + 0xf3, 0xf5, 0x41, 0xe6, 0xa4, 0x24, 0x96, 0x24, 0xea, 0xe3, 0xf0, 0x0f, 0x20, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0x7e, 0x58, 0x1c, 0xe9, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/importing/importing.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/importing/importing.proto new file mode 100644 index 0000000000..fc78f5f100 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/import_public/importing/importing.proto @@ -0,0 +1,43 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2018 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package goproto.test.import_public.importing; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/import_public/importing"; + +import "import_public/a.proto"; + +message M { + // Message type defined in a file publicly imported by a file we import. + optional goproto.test.import_public.sub.M m = 1; +} diff --git a/vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go b/vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go new file mode 100644 index 0000000000..b4eb03eccf --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go @@ -0,0 +1,83 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/empty.proto + +package empty + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +// +// The JSON representation for `Empty` is empty JSON object `{}`. +type Empty struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Empty) Reset() { *m = Empty{} } +func (m *Empty) String() string { return proto.CompactTextString(m) } +func (*Empty) ProtoMessage() {} +func (*Empty) Descriptor() ([]byte, []int) { + return fileDescriptor_900544acb223d5b8, []int{0} +} + +func (*Empty) XXX_WellKnownType() string { return "Empty" } + +func (m *Empty) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Empty.Unmarshal(m, b) +} +func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Empty.Marshal(b, m, deterministic) +} +func (m *Empty) XXX_Merge(src proto.Message) { + xxx_messageInfo_Empty.Merge(m, src) +} +func (m *Empty) XXX_Size() int { + return xxx_messageInfo_Empty.Size(m) +} +func (m *Empty) XXX_DiscardUnknown() { + xxx_messageInfo_Empty.DiscardUnknown(m) +} + +var xxx_messageInfo_Empty proto.InternalMessageInfo + +func init() { + proto.RegisterType((*Empty)(nil), "google.protobuf.Empty") +} + +func init() { proto.RegisterFile("google/protobuf/empty.proto", fileDescriptor_900544acb223d5b8) } + +var fileDescriptor_900544acb223d5b8 = []byte{ + // 148 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4e, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcd, 0x2d, 0x28, + 0xa9, 0xd4, 0x03, 0x73, 0x85, 0xf8, 0x21, 0x92, 0x7a, 0x30, 0x49, 0x25, 0x76, 0x2e, 0x56, 0x57, + 0x90, 0xbc, 0x53, 0x19, 0x97, 0x70, 0x72, 0x7e, 0xae, 0x1e, 0x9a, 0xbc, 0x13, 0x17, 0x58, 0x36, + 0x00, 0xc4, 0x0d, 0x60, 0x8c, 0x52, 0x4f, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, + 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0x47, 0x58, 0x53, 0x50, 0x52, 0x59, 0x90, 0x5a, 0x0c, + 0xb1, 0xed, 0x07, 0x23, 0xe3, 0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7, 0x55, 0x4c, 0x72, 0xee, 0x10, + 0x13, 0x03, 0xa0, 0xea, 0xf4, 0xc2, 0x53, 0x73, 0x72, 0xbc, 0xf3, 0xf2, 0xcb, 0xf3, 0x42, 0x40, + 0xea, 0x93, 0xd8, 0xc0, 0x06, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x64, 0xd4, 0xb3, 0xa6, + 0xb7, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/empty/empty.proto b/vendor/github.com/golang/protobuf/ptypes/empty/empty.proto new file mode 100644 index 0000000000..03cacd2330 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/empty/empty.proto @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "github.com/golang/protobuf/ptypes/empty"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "EmptyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +// +// The JSON representation for `Empty` is empty JSON object `{}`. +message Empty {} diff --git a/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go b/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go new file mode 100644 index 0000000000..33daa73dd2 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go @@ -0,0 +1,336 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/struct.proto + +package structpb + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// `NullValue` is a singleton enumeration to represent the null value for the +// `Value` type union. +// +// The JSON representation for `NullValue` is JSON `null`. +type NullValue int32 + +const ( + // Null value. + NullValue_NULL_VALUE NullValue = 0 +) + +var NullValue_name = map[int32]string{ + 0: "NULL_VALUE", +} + +var NullValue_value = map[string]int32{ + "NULL_VALUE": 0, +} + +func (x NullValue) String() string { + return proto.EnumName(NullValue_name, int32(x)) +} + +func (NullValue) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_df322afd6c9fb402, []int{0} +} + +func (NullValue) XXX_WellKnownType() string { return "NullValue" } + +// `Struct` represents a structured data value, consisting of fields +// which map to dynamically typed values. In some languages, `Struct` +// might be supported by a native representation. For example, in +// scripting languages like JS a struct is represented as an +// object. The details of that representation are described together +// with the proto support for the language. +// +// The JSON representation for `Struct` is JSON object. +type Struct struct { + // Unordered map of dynamically typed values. + Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields,proto3" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Struct) Reset() { *m = Struct{} } +func (m *Struct) String() string { return proto.CompactTextString(m) } +func (*Struct) ProtoMessage() {} +func (*Struct) Descriptor() ([]byte, []int) { + return fileDescriptor_df322afd6c9fb402, []int{0} +} + +func (*Struct) XXX_WellKnownType() string { return "Struct" } + +func (m *Struct) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Struct.Unmarshal(m, b) +} +func (m *Struct) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Struct.Marshal(b, m, deterministic) +} +func (m *Struct) XXX_Merge(src proto.Message) { + xxx_messageInfo_Struct.Merge(m, src) +} +func (m *Struct) XXX_Size() int { + return xxx_messageInfo_Struct.Size(m) +} +func (m *Struct) XXX_DiscardUnknown() { + xxx_messageInfo_Struct.DiscardUnknown(m) +} + +var xxx_messageInfo_Struct proto.InternalMessageInfo + +func (m *Struct) GetFields() map[string]*Value { + if m != nil { + return m.Fields + } + return nil +} + +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of that +// variants, absence of any variant indicates an error. +// +// The JSON representation for `Value` is JSON value. +type Value struct { + // The kind of value. + // + // Types that are valid to be assigned to Kind: + // *Value_NullValue + // *Value_NumberValue + // *Value_StringValue + // *Value_BoolValue + // *Value_StructValue + // *Value_ListValue + Kind isValue_Kind `protobuf_oneof:"kind"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Value) Reset() { *m = Value{} } +func (m *Value) String() string { return proto.CompactTextString(m) } +func (*Value) ProtoMessage() {} +func (*Value) Descriptor() ([]byte, []int) { + return fileDescriptor_df322afd6c9fb402, []int{1} +} + +func (*Value) XXX_WellKnownType() string { return "Value" } + +func (m *Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Value.Unmarshal(m, b) +} +func (m *Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Value.Marshal(b, m, deterministic) +} +func (m *Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_Value.Merge(m, src) +} +func (m *Value) XXX_Size() int { + return xxx_messageInfo_Value.Size(m) +} +func (m *Value) XXX_DiscardUnknown() { + xxx_messageInfo_Value.DiscardUnknown(m) +} + +var xxx_messageInfo_Value proto.InternalMessageInfo + +type isValue_Kind interface { + isValue_Kind() +} + +type Value_NullValue struct { + NullValue NullValue `protobuf:"varint,1,opt,name=null_value,json=nullValue,proto3,enum=google.protobuf.NullValue,oneof"` +} + +type Value_NumberValue struct { + NumberValue float64 `protobuf:"fixed64,2,opt,name=number_value,json=numberValue,proto3,oneof"` +} + +type Value_StringValue struct { + StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,proto3,oneof"` +} + +type Value_BoolValue struct { + BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,proto3,oneof"` +} + +type Value_StructValue struct { + StructValue *Struct `protobuf:"bytes,5,opt,name=struct_value,json=structValue,proto3,oneof"` +} + +type Value_ListValue struct { + ListValue *ListValue `protobuf:"bytes,6,opt,name=list_value,json=listValue,proto3,oneof"` +} + +func (*Value_NullValue) isValue_Kind() {} + +func (*Value_NumberValue) isValue_Kind() {} + +func (*Value_StringValue) isValue_Kind() {} + +func (*Value_BoolValue) isValue_Kind() {} + +func (*Value_StructValue) isValue_Kind() {} + +func (*Value_ListValue) isValue_Kind() {} + +func (m *Value) GetKind() isValue_Kind { + if m != nil { + return m.Kind + } + return nil +} + +func (m *Value) GetNullValue() NullValue { + if x, ok := m.GetKind().(*Value_NullValue); ok { + return x.NullValue + } + return NullValue_NULL_VALUE +} + +func (m *Value) GetNumberValue() float64 { + if x, ok := m.GetKind().(*Value_NumberValue); ok { + return x.NumberValue + } + return 0 +} + +func (m *Value) GetStringValue() string { + if x, ok := m.GetKind().(*Value_StringValue); ok { + return x.StringValue + } + return "" +} + +func (m *Value) GetBoolValue() bool { + if x, ok := m.GetKind().(*Value_BoolValue); ok { + return x.BoolValue + } + return false +} + +func (m *Value) GetStructValue() *Struct { + if x, ok := m.GetKind().(*Value_StructValue); ok { + return x.StructValue + } + return nil +} + +func (m *Value) GetListValue() *ListValue { + if x, ok := m.GetKind().(*Value_ListValue); ok { + return x.ListValue + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Value) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Value_NullValue)(nil), + (*Value_NumberValue)(nil), + (*Value_StringValue)(nil), + (*Value_BoolValue)(nil), + (*Value_StructValue)(nil), + (*Value_ListValue)(nil), + } +} + +// `ListValue` is a wrapper around a repeated field of values. +// +// The JSON representation for `ListValue` is JSON array. +type ListValue struct { + // Repeated field of dynamically typed values. + Values []*Value `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListValue) Reset() { *m = ListValue{} } +func (m *ListValue) String() string { return proto.CompactTextString(m) } +func (*ListValue) ProtoMessage() {} +func (*ListValue) Descriptor() ([]byte, []int) { + return fileDescriptor_df322afd6c9fb402, []int{2} +} + +func (*ListValue) XXX_WellKnownType() string { return "ListValue" } + +func (m *ListValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListValue.Unmarshal(m, b) +} +func (m *ListValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListValue.Marshal(b, m, deterministic) +} +func (m *ListValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListValue.Merge(m, src) +} +func (m *ListValue) XXX_Size() int { + return xxx_messageInfo_ListValue.Size(m) +} +func (m *ListValue) XXX_DiscardUnknown() { + xxx_messageInfo_ListValue.DiscardUnknown(m) +} + +var xxx_messageInfo_ListValue proto.InternalMessageInfo + +func (m *ListValue) GetValues() []*Value { + if m != nil { + return m.Values + } + return nil +} + +func init() { + proto.RegisterEnum("google.protobuf.NullValue", NullValue_name, NullValue_value) + proto.RegisterType((*Struct)(nil), "google.protobuf.Struct") + proto.RegisterMapType((map[string]*Value)(nil), "google.protobuf.Struct.FieldsEntry") + proto.RegisterType((*Value)(nil), "google.protobuf.Value") + proto.RegisterType((*ListValue)(nil), "google.protobuf.ListValue") +} + +func init() { proto.RegisterFile("google/protobuf/struct.proto", fileDescriptor_df322afd6c9fb402) } + +var fileDescriptor_df322afd6c9fb402 = []byte{ + // 417 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0x41, 0x8b, 0xd3, 0x40, + 0x14, 0xc7, 0x3b, 0xc9, 0x36, 0x98, 0x17, 0x59, 0x97, 0x11, 0xb4, 0xac, 0xa2, 0xa1, 0x7b, 0x09, + 0x22, 0x29, 0xd6, 0x8b, 0x18, 0x2f, 0x06, 0xd6, 0x5d, 0x30, 0x2c, 0x31, 0xba, 0x15, 0xbc, 0x94, + 0x26, 0x4d, 0x63, 0xe8, 0x74, 0x26, 0x24, 0x33, 0x4a, 0x8f, 0x7e, 0x0b, 0xcf, 0x1e, 0x3d, 0xfa, + 0xe9, 0x3c, 0xca, 0xcc, 0x24, 0xa9, 0xb4, 0xf4, 0x94, 0xbc, 0xf7, 0x7e, 0xef, 0x3f, 0xef, 0xff, + 0x66, 0xe0, 0x71, 0xc1, 0x58, 0x41, 0xf2, 0x49, 0x55, 0x33, 0xce, 0x52, 0xb1, 0x9a, 0x34, 0xbc, + 0x16, 0x19, 0xf7, 0x55, 0x8c, 0xef, 0xe9, 0xaa, 0xdf, 0x55, 0xc7, 0x3f, 0x11, 0x58, 0x1f, 0x15, + 0x81, 0x03, 0xb0, 0x56, 0x65, 0x4e, 0x96, 0xcd, 0x08, 0xb9, 0xa6, 0xe7, 0x4c, 0x2f, 0xfc, 0x3d, + 0xd8, 0xd7, 0xa0, 0xff, 0x4e, 0x51, 0x97, 0x94, 0xd7, 0xdb, 0xa4, 0x6d, 0x39, 0xff, 0x00, 0xce, + 0x7f, 0x69, 0x7c, 0x06, 0xe6, 0x3a, 0xdf, 0x8e, 0x90, 0x8b, 0x3c, 0x3b, 0x91, 0xbf, 0xf8, 0x39, + 0x0c, 0xbf, 0x2d, 0x88, 0xc8, 0x47, 0x86, 0x8b, 0x3c, 0x67, 0xfa, 0xe0, 0x40, 0x7c, 0x26, 0xab, + 0x89, 0x86, 0x5e, 0x1b, 0xaf, 0xd0, 0xf8, 0x8f, 0x01, 0x43, 0x95, 0xc4, 0x01, 0x00, 0x15, 0x84, + 0xcc, 0xb5, 0x80, 0x14, 0x3d, 0x9d, 0x9e, 0x1f, 0x08, 0xdc, 0x08, 0x42, 0x14, 0x7f, 0x3d, 0x48, + 0x6c, 0xda, 0x05, 0xf8, 0x02, 0xee, 0x52, 0xb1, 0x49, 0xf3, 0x7a, 0xbe, 0x3b, 0x1f, 0x5d, 0x0f, + 0x12, 0x47, 0x67, 0x7b, 0xa8, 0xe1, 0x75, 0x49, 0x8b, 0x16, 0x32, 0xe5, 0xe0, 0x12, 0xd2, 0x59, + 0x0d, 0x3d, 0x05, 0x48, 0x19, 0xeb, 0xc6, 0x38, 0x71, 0x91, 0x77, 0x47, 0x1e, 0x25, 0x73, 0x1a, + 0x78, 0xa3, 0x54, 0x44, 0xc6, 0x5b, 0x64, 0xa8, 0xac, 0x3e, 0x3c, 0xb2, 0xc7, 0x56, 0x5e, 0x64, + 0xbc, 0x77, 0x49, 0xca, 0xa6, 0xeb, 0xb5, 0x54, 0xef, 0xa1, 0xcb, 0xa8, 0x6c, 0x78, 0xef, 0x92, + 0x74, 0x41, 0x68, 0xc1, 0xc9, 0xba, 0xa4, 0xcb, 0x71, 0x00, 0x76, 0x4f, 0x60, 0x1f, 0x2c, 0x25, + 0xd6, 0xdd, 0xe8, 0xb1, 0xa5, 0xb7, 0xd4, 0xb3, 0x47, 0x60, 0xf7, 0x4b, 0xc4, 0xa7, 0x00, 0x37, + 0xb7, 0x51, 0x34, 0x9f, 0xbd, 0x8d, 0x6e, 0x2f, 0xcf, 0x06, 0xe1, 0x0f, 0x04, 0xf7, 0x33, 0xb6, + 0xd9, 0x97, 0x08, 0x1d, 0xed, 0x26, 0x96, 0x71, 0x8c, 0xbe, 0xbc, 0x28, 0x4a, 0xfe, 0x55, 0xa4, + 0x7e, 0xc6, 0x36, 0x93, 0x82, 0x91, 0x05, 0x2d, 0x76, 0x4f, 0xb1, 0xe2, 0xdb, 0x2a, 0x6f, 0xda, + 0x17, 0x19, 0xe8, 0x4f, 0x95, 0xfe, 0x45, 0xe8, 0x97, 0x61, 0x5e, 0xc5, 0xe1, 0x6f, 0xe3, 0xc9, + 0x95, 0x16, 0x8f, 0xbb, 0xf9, 0x3e, 0xe7, 0x84, 0xbc, 0xa7, 0xec, 0x3b, 0xfd, 0x24, 0x3b, 0x53, + 0x4b, 0x49, 0xbd, 0xfc, 0x17, 0x00, 0x00, 0xff, 0xff, 0xe8, 0x1b, 0x59, 0xf8, 0xe5, 0x02, 0x00, + 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto b/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto new file mode 100644 index 0000000000..7d7808e7fb --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto @@ -0,0 +1,96 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/struct;structpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "StructProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + + +// `Struct` represents a structured data value, consisting of fields +// which map to dynamically typed values. In some languages, `Struct` +// might be supported by a native representation. For example, in +// scripting languages like JS a struct is represented as an +// object. The details of that representation are described together +// with the proto support for the language. +// +// The JSON representation for `Struct` is JSON object. +message Struct { + // Unordered map of dynamically typed values. + map fields = 1; +} + +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of that +// variants, absence of any variant indicates an error. +// +// The JSON representation for `Value` is JSON value. +message Value { + // The kind of value. + oneof kind { + // Represents a null value. + NullValue null_value = 1; + // Represents a double value. + double number_value = 2; + // Represents a string value. + string string_value = 3; + // Represents a boolean value. + bool bool_value = 4; + // Represents a structured value. + Struct struct_value = 5; + // Represents a repeated `Value`. + ListValue list_value = 6; + } +} + +// `NullValue` is a singleton enumeration to represent the null value for the +// `Value` type union. +// +// The JSON representation for `NullValue` is JSON `null`. +enum NullValue { + // Null value. + NULL_VALUE = 0; +} + +// `ListValue` is a wrapper around a repeated field of values. +// +// The JSON representation for `ListValue` is JSON array. +message ListValue { + // Repeated field of dynamically typed values. + repeated Value values = 1; +} diff --git a/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go new file mode 100644 index 0000000000..add19a1adb --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go @@ -0,0 +1,461 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/wrappers.proto + +package wrappers + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// Wrapper message for `double`. +// +// The JSON representation for `DoubleValue` is JSON number. +type DoubleValue struct { + // The double value. + Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DoubleValue) Reset() { *m = DoubleValue{} } +func (m *DoubleValue) String() string { return proto.CompactTextString(m) } +func (*DoubleValue) ProtoMessage() {} +func (*DoubleValue) Descriptor() ([]byte, []int) { + return fileDescriptor_5377b62bda767935, []int{0} +} + +func (*DoubleValue) XXX_WellKnownType() string { return "DoubleValue" } + +func (m *DoubleValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DoubleValue.Unmarshal(m, b) +} +func (m *DoubleValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DoubleValue.Marshal(b, m, deterministic) +} +func (m *DoubleValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_DoubleValue.Merge(m, src) +} +func (m *DoubleValue) XXX_Size() int { + return xxx_messageInfo_DoubleValue.Size(m) +} +func (m *DoubleValue) XXX_DiscardUnknown() { + xxx_messageInfo_DoubleValue.DiscardUnknown(m) +} + +var xxx_messageInfo_DoubleValue proto.InternalMessageInfo + +func (m *DoubleValue) GetValue() float64 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `float`. +// +// The JSON representation for `FloatValue` is JSON number. +type FloatValue struct { + // The float value. + Value float32 `protobuf:"fixed32,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FloatValue) Reset() { *m = FloatValue{} } +func (m *FloatValue) String() string { return proto.CompactTextString(m) } +func (*FloatValue) ProtoMessage() {} +func (*FloatValue) Descriptor() ([]byte, []int) { + return fileDescriptor_5377b62bda767935, []int{1} +} + +func (*FloatValue) XXX_WellKnownType() string { return "FloatValue" } + +func (m *FloatValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FloatValue.Unmarshal(m, b) +} +func (m *FloatValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FloatValue.Marshal(b, m, deterministic) +} +func (m *FloatValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_FloatValue.Merge(m, src) +} +func (m *FloatValue) XXX_Size() int { + return xxx_messageInfo_FloatValue.Size(m) +} +func (m *FloatValue) XXX_DiscardUnknown() { + xxx_messageInfo_FloatValue.DiscardUnknown(m) +} + +var xxx_messageInfo_FloatValue proto.InternalMessageInfo + +func (m *FloatValue) GetValue() float32 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `int64`. +// +// The JSON representation for `Int64Value` is JSON string. +type Int64Value struct { + // The int64 value. + Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Int64Value) Reset() { *m = Int64Value{} } +func (m *Int64Value) String() string { return proto.CompactTextString(m) } +func (*Int64Value) ProtoMessage() {} +func (*Int64Value) Descriptor() ([]byte, []int) { + return fileDescriptor_5377b62bda767935, []int{2} +} + +func (*Int64Value) XXX_WellKnownType() string { return "Int64Value" } + +func (m *Int64Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Int64Value.Unmarshal(m, b) +} +func (m *Int64Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Int64Value.Marshal(b, m, deterministic) +} +func (m *Int64Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_Int64Value.Merge(m, src) +} +func (m *Int64Value) XXX_Size() int { + return xxx_messageInfo_Int64Value.Size(m) +} +func (m *Int64Value) XXX_DiscardUnknown() { + xxx_messageInfo_Int64Value.DiscardUnknown(m) +} + +var xxx_messageInfo_Int64Value proto.InternalMessageInfo + +func (m *Int64Value) GetValue() int64 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `uint64`. +// +// The JSON representation for `UInt64Value` is JSON string. +type UInt64Value struct { + // The uint64 value. + Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UInt64Value) Reset() { *m = UInt64Value{} } +func (m *UInt64Value) String() string { return proto.CompactTextString(m) } +func (*UInt64Value) ProtoMessage() {} +func (*UInt64Value) Descriptor() ([]byte, []int) { + return fileDescriptor_5377b62bda767935, []int{3} +} + +func (*UInt64Value) XXX_WellKnownType() string { return "UInt64Value" } + +func (m *UInt64Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UInt64Value.Unmarshal(m, b) +} +func (m *UInt64Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UInt64Value.Marshal(b, m, deterministic) +} +func (m *UInt64Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_UInt64Value.Merge(m, src) +} +func (m *UInt64Value) XXX_Size() int { + return xxx_messageInfo_UInt64Value.Size(m) +} +func (m *UInt64Value) XXX_DiscardUnknown() { + xxx_messageInfo_UInt64Value.DiscardUnknown(m) +} + +var xxx_messageInfo_UInt64Value proto.InternalMessageInfo + +func (m *UInt64Value) GetValue() uint64 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +type Int32Value struct { + // The int32 value. + Value int32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Int32Value) Reset() { *m = Int32Value{} } +func (m *Int32Value) String() string { return proto.CompactTextString(m) } +func (*Int32Value) ProtoMessage() {} +func (*Int32Value) Descriptor() ([]byte, []int) { + return fileDescriptor_5377b62bda767935, []int{4} +} + +func (*Int32Value) XXX_WellKnownType() string { return "Int32Value" } + +func (m *Int32Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Int32Value.Unmarshal(m, b) +} +func (m *Int32Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Int32Value.Marshal(b, m, deterministic) +} +func (m *Int32Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_Int32Value.Merge(m, src) +} +func (m *Int32Value) XXX_Size() int { + return xxx_messageInfo_Int32Value.Size(m) +} +func (m *Int32Value) XXX_DiscardUnknown() { + xxx_messageInfo_Int32Value.DiscardUnknown(m) +} + +var xxx_messageInfo_Int32Value proto.InternalMessageInfo + +func (m *Int32Value) GetValue() int32 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `uint32`. +// +// The JSON representation for `UInt32Value` is JSON number. +type UInt32Value struct { + // The uint32 value. + Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UInt32Value) Reset() { *m = UInt32Value{} } +func (m *UInt32Value) String() string { return proto.CompactTextString(m) } +func (*UInt32Value) ProtoMessage() {} +func (*UInt32Value) Descriptor() ([]byte, []int) { + return fileDescriptor_5377b62bda767935, []int{5} +} + +func (*UInt32Value) XXX_WellKnownType() string { return "UInt32Value" } + +func (m *UInt32Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UInt32Value.Unmarshal(m, b) +} +func (m *UInt32Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UInt32Value.Marshal(b, m, deterministic) +} +func (m *UInt32Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_UInt32Value.Merge(m, src) +} +func (m *UInt32Value) XXX_Size() int { + return xxx_messageInfo_UInt32Value.Size(m) +} +func (m *UInt32Value) XXX_DiscardUnknown() { + xxx_messageInfo_UInt32Value.DiscardUnknown(m) +} + +var xxx_messageInfo_UInt32Value proto.InternalMessageInfo + +func (m *UInt32Value) GetValue() uint32 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `bool`. +// +// The JSON representation for `BoolValue` is JSON `true` and `false`. +type BoolValue struct { + // The bool value. + Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BoolValue) Reset() { *m = BoolValue{} } +func (m *BoolValue) String() string { return proto.CompactTextString(m) } +func (*BoolValue) ProtoMessage() {} +func (*BoolValue) Descriptor() ([]byte, []int) { + return fileDescriptor_5377b62bda767935, []int{6} +} + +func (*BoolValue) XXX_WellKnownType() string { return "BoolValue" } + +func (m *BoolValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BoolValue.Unmarshal(m, b) +} +func (m *BoolValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BoolValue.Marshal(b, m, deterministic) +} +func (m *BoolValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_BoolValue.Merge(m, src) +} +func (m *BoolValue) XXX_Size() int { + return xxx_messageInfo_BoolValue.Size(m) +} +func (m *BoolValue) XXX_DiscardUnknown() { + xxx_messageInfo_BoolValue.DiscardUnknown(m) +} + +var xxx_messageInfo_BoolValue proto.InternalMessageInfo + +func (m *BoolValue) GetValue() bool { + if m != nil { + return m.Value + } + return false +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +type StringValue struct { + // The string value. + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StringValue) Reset() { *m = StringValue{} } +func (m *StringValue) String() string { return proto.CompactTextString(m) } +func (*StringValue) ProtoMessage() {} +func (*StringValue) Descriptor() ([]byte, []int) { + return fileDescriptor_5377b62bda767935, []int{7} +} + +func (*StringValue) XXX_WellKnownType() string { return "StringValue" } + +func (m *StringValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StringValue.Unmarshal(m, b) +} +func (m *StringValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StringValue.Marshal(b, m, deterministic) +} +func (m *StringValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_StringValue.Merge(m, src) +} +func (m *StringValue) XXX_Size() int { + return xxx_messageInfo_StringValue.Size(m) +} +func (m *StringValue) XXX_DiscardUnknown() { + xxx_messageInfo_StringValue.DiscardUnknown(m) +} + +var xxx_messageInfo_StringValue proto.InternalMessageInfo + +func (m *StringValue) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +// Wrapper message for `bytes`. +// +// The JSON representation for `BytesValue` is JSON string. +type BytesValue struct { + // The bytes value. + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BytesValue) Reset() { *m = BytesValue{} } +func (m *BytesValue) String() string { return proto.CompactTextString(m) } +func (*BytesValue) ProtoMessage() {} +func (*BytesValue) Descriptor() ([]byte, []int) { + return fileDescriptor_5377b62bda767935, []int{8} +} + +func (*BytesValue) XXX_WellKnownType() string { return "BytesValue" } + +func (m *BytesValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BytesValue.Unmarshal(m, b) +} +func (m *BytesValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BytesValue.Marshal(b, m, deterministic) +} +func (m *BytesValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_BytesValue.Merge(m, src) +} +func (m *BytesValue) XXX_Size() int { + return xxx_messageInfo_BytesValue.Size(m) +} +func (m *BytesValue) XXX_DiscardUnknown() { + xxx_messageInfo_BytesValue.DiscardUnknown(m) +} + +var xxx_messageInfo_BytesValue proto.InternalMessageInfo + +func (m *BytesValue) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func init() { + proto.RegisterType((*DoubleValue)(nil), "google.protobuf.DoubleValue") + proto.RegisterType((*FloatValue)(nil), "google.protobuf.FloatValue") + proto.RegisterType((*Int64Value)(nil), "google.protobuf.Int64Value") + proto.RegisterType((*UInt64Value)(nil), "google.protobuf.UInt64Value") + proto.RegisterType((*Int32Value)(nil), "google.protobuf.Int32Value") + proto.RegisterType((*UInt32Value)(nil), "google.protobuf.UInt32Value") + proto.RegisterType((*BoolValue)(nil), "google.protobuf.BoolValue") + proto.RegisterType((*StringValue)(nil), "google.protobuf.StringValue") + proto.RegisterType((*BytesValue)(nil), "google.protobuf.BytesValue") +} + +func init() { proto.RegisterFile("google/protobuf/wrappers.proto", fileDescriptor_5377b62bda767935) } + +var fileDescriptor_5377b62bda767935 = []byte{ + // 259 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x2f, 0x4a, 0x2c, + 0x28, 0x48, 0x2d, 0x2a, 0xd6, 0x03, 0x8b, 0x08, 0xf1, 0x43, 0xe4, 0xf5, 0x60, 0xf2, 0x4a, 0xca, + 0x5c, 0xdc, 0x2e, 0xf9, 0xa5, 0x49, 0x39, 0xa9, 0x61, 0x89, 0x39, 0xa5, 0xa9, 0x42, 0x22, 0x5c, + 0xac, 0x65, 0x20, 0x86, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x63, 0x10, 0x84, 0xa3, 0xa4, 0xc4, 0xc5, + 0xe5, 0x96, 0x93, 0x9f, 0x58, 0x82, 0x45, 0x0d, 0x13, 0x92, 0x1a, 0xcf, 0xbc, 0x12, 0x33, 0x13, + 0x2c, 0x6a, 0x98, 0x61, 0x6a, 0x94, 0xb9, 0xb8, 0x43, 0x71, 0x29, 0x62, 0x41, 0x35, 0xc8, 0xd8, + 0x08, 0x8b, 0x1a, 0x56, 0x34, 0x83, 0xb0, 0x2a, 0xe2, 0x85, 0x29, 0x52, 0xe4, 0xe2, 0x74, 0xca, + 0xcf, 0xcf, 0xc1, 0xa2, 0x84, 0x03, 0xc9, 0x9c, 0xe0, 0x92, 0xa2, 0xcc, 0xbc, 0x74, 0x2c, 0x8a, + 0x38, 0x91, 0x1c, 0xe4, 0x54, 0x59, 0x92, 0x5a, 0x8c, 0x45, 0x0d, 0x0f, 0x54, 0x8d, 0x53, 0x0d, + 0x97, 0x70, 0x72, 0x7e, 0xae, 0x1e, 0x5a, 0xe8, 0x3a, 0xf1, 0x86, 0x43, 0x83, 0x3f, 0x00, 0x24, + 0x12, 0xc0, 0x18, 0xa5, 0x95, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x9f, + 0x9e, 0x9f, 0x93, 0x98, 0x97, 0x8e, 0x88, 0xaa, 0x82, 0x92, 0xca, 0x82, 0xd4, 0x62, 0x78, 0x8c, + 0xfd, 0x60, 0x64, 0x5c, 0xc4, 0xc4, 0xec, 0x1e, 0xe0, 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0x62, 0x6e, + 0x00, 0x54, 0xa9, 0x5e, 0x78, 0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0x48, 0x4b, + 0x12, 0x1b, 0xd8, 0x0c, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x19, 0x6c, 0xb9, 0xb8, 0xfe, + 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto new file mode 100644 index 0000000000..01947639ac --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto @@ -0,0 +1,118 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/wrappers"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "WrappersProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// Wrapper message for `double`. +// +// The JSON representation for `DoubleValue` is JSON number. +message DoubleValue { + // The double value. + double value = 1; +} + +// Wrapper message for `float`. +// +// The JSON representation for `FloatValue` is JSON number. +message FloatValue { + // The float value. + float value = 1; +} + +// Wrapper message for `int64`. +// +// The JSON representation for `Int64Value` is JSON string. +message Int64Value { + // The int64 value. + int64 value = 1; +} + +// Wrapper message for `uint64`. +// +// The JSON representation for `UInt64Value` is JSON string. +message UInt64Value { + // The uint64 value. + uint64 value = 1; +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +message Int32Value { + // The int32 value. + int32 value = 1; +} + +// Wrapper message for `uint32`. +// +// The JSON representation for `UInt32Value` is JSON number. +message UInt32Value { + // The uint32 value. + uint32 value = 1; +} + +// Wrapper message for `bool`. +// +// The JSON representation for `BoolValue` is JSON `true` and `false`. +message BoolValue { + // The bool value. + bool value = 1; +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +message StringValue { + // The string value. + string value = 1; +} + +// Wrapper message for `bytes`. +// +// The JSON representation for `BytesValue` is JSON string. +message BytesValue { + // The bytes value. + bytes value = 1; +} diff --git a/vendor/github.com/google/uuid/uuid_test.go b/vendor/github.com/google/uuid/uuid_test.go index e7876f151a..cf072b826d 100644 --- a/vendor/github.com/google/uuid/uuid_test.go +++ b/vendor/github.com/google/uuid/uuid_test.go @@ -59,7 +59,6 @@ var tests = []test{ {"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true}, {"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true}, - {"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false}, {"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false}, {"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false}, @@ -67,7 +66,6 @@ var tests = []test{ {"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false}, {"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false}, - {"{f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, RFC4122, true}, {"{f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, Invalid, false}, {"f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, Invalid, false}, diff --git a/vendor/github.com/gorilla/websocket/.travis.yml b/vendor/github.com/gorilla/websocket/.travis.yml deleted file mode 100644 index a49db51c43..0000000000 --- a/vendor/github.com/gorilla/websocket/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: go -sudo: false - -matrix: - include: - - go: 1.7.x - - go: 1.8.x - - go: 1.9.x - - go: 1.10.x - - go: 1.11.x - - go: tip - allow_failures: - - go: tip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go vet $(go list ./... | grep -v /vendor/) - - go test -v -race ./... diff --git a/vendor/github.com/gorilla/websocket/README.md b/vendor/github.com/gorilla/websocket/README.md index 20e391f865..0827d059c1 100644 --- a/vendor/github.com/gorilla/websocket/README.md +++ b/vendor/github.com/gorilla/websocket/README.md @@ -1,11 +1,11 @@ # Gorilla WebSocket +[![GoDoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket) +[![CircleCI](https://circleci.com/gh/gorilla/websocket.svg?style=svg)](https://circleci.com/gh/gorilla/websocket) + Gorilla WebSocket is a [Go](http://golang.org/) implementation of the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. -[![Build Status](https://travis-ci.org/gorilla/websocket.svg?branch=master)](https://travis-ci.org/gorilla/websocket) -[![GoDoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket) - ### Documentation * [API Reference](http://godoc.org/github.com/gorilla/websocket) @@ -27,7 +27,7 @@ package API is stable. ### Protocol Compliance The Gorilla WebSocket package passes the server tests in the [Autobahn Test -Suite](http://autobahn.ws/testsuite) using the application in the [examples/autobahn +Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn). ### Gorilla WebSocket compared with other packages @@ -40,7 +40,7 @@ subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn RFC 6455 Features -Passes Autobahn Test SuiteYesNo +Passes Autobahn Test SuiteYesNo Receive fragmented messageYesNo, see note 1 Send close messageYesNo Send pings and receive pongsYesNo diff --git a/vendor/github.com/gorilla/websocket/conn.go b/vendor/github.com/gorilla/websocket/conn.go index 3848ab4a9e..6f17cd2998 100644 --- a/vendor/github.com/gorilla/websocket/conn.go +++ b/vendor/github.com/gorilla/websocket/conn.go @@ -260,10 +260,12 @@ type Conn struct { newCompressionWriter func(io.WriteCloser, int) io.WriteCloser // Read fields - reader io.ReadCloser // the current reader returned to the application - readErr error - br *bufio.Reader - readRemaining int64 // bytes remaining in current frame. + reader io.ReadCloser // the current reader returned to the application + readErr error + br *bufio.Reader + // bytes remaining in current frame. + // set setReadRemaining to safely update this value and prevent overflow + readRemaining int64 readFinal bool // true the current message has more frames. readLength int64 // Message size. readLimit int64 // Maximum message size. @@ -320,6 +322,17 @@ func newConn(conn net.Conn, isServer bool, readBufferSize, writeBufferSize int, return c } +// setReadRemaining tracks the number of bytes remaining on the connection. If n +// overflows, an ErrReadLimit is returned. +func (c *Conn) setReadRemaining(n int64) error { + if n < 0 { + return ErrReadLimit + } + + c.readRemaining = n + return nil +} + // Subprotocol returns the negotiated protocol for the connection. func (c *Conn) Subprotocol() string { return c.subprotocol @@ -708,10 +721,7 @@ func (w *messageWriter) Close() error { if w.err != nil { return w.err } - if err := w.flushFrame(true, nil); err != nil { - return err - } - return nil + return w.flushFrame(true, nil) } // WritePreparedMessage writes prepared message into connection. @@ -793,7 +803,7 @@ func (c *Conn) advanceFrame() (int, error) { final := p[0]&finalBit != 0 frameType := int(p[0] & 0xf) mask := p[1]&maskBit != 0 - c.readRemaining = int64(p[1] & 0x7f) + c.setReadRemaining(int64(p[1] & 0x7f)) c.readDecompress = false if c.newDecompressionReader != nil && (p[0]&rsv1Bit) != 0 { @@ -827,7 +837,17 @@ func (c *Conn) advanceFrame() (int, error) { return noFrame, c.handleProtocolError("unknown opcode " + strconv.Itoa(frameType)) } - // 3. Read and parse frame length. + // 3. Read and parse frame length as per + // https://tools.ietf.org/html/rfc6455#section-5.2 + // + // The length of the "Payload data", in bytes: if 0-125, that is the payload + // length. + // - If 126, the following 2 bytes interpreted as a 16-bit unsigned + // integer are the payload length. + // - If 127, the following 8 bytes interpreted as + // a 64-bit unsigned integer (the most significant bit MUST be 0) are the + // payload length. Multibyte length quantities are expressed in network byte + // order. switch c.readRemaining { case 126: @@ -835,13 +855,19 @@ func (c *Conn) advanceFrame() (int, error) { if err != nil { return noFrame, err } - c.readRemaining = int64(binary.BigEndian.Uint16(p)) + + if err := c.setReadRemaining(int64(binary.BigEndian.Uint16(p))); err != nil { + return noFrame, err + } case 127: p, err := c.read(8) if err != nil { return noFrame, err } - c.readRemaining = int64(binary.BigEndian.Uint64(p)) + + if err := c.setReadRemaining(int64(binary.BigEndian.Uint64(p))); err != nil { + return noFrame, err + } } // 4. Handle frame masking. @@ -864,6 +890,12 @@ func (c *Conn) advanceFrame() (int, error) { if frameType == continuationFrame || frameType == TextMessage || frameType == BinaryMessage { c.readLength += c.readRemaining + // Don't allow readLength to overflow in the presence of a large readRemaining + // counter. + if c.readLength < 0 { + return noFrame, ErrReadLimit + } + if c.readLimit > 0 && c.readLength > c.readLimit { c.WriteControl(CloseMessage, FormatCloseMessage(CloseMessageTooBig, ""), time.Now().Add(writeWait)) return noFrame, ErrReadLimit @@ -877,7 +909,7 @@ func (c *Conn) advanceFrame() (int, error) { var payload []byte if c.readRemaining > 0 { payload, err = c.read(int(c.readRemaining)) - c.readRemaining = 0 + c.setReadRemaining(0) if err != nil { return noFrame, err } @@ -950,6 +982,7 @@ func (c *Conn) NextReader() (messageType int, r io.Reader, err error) { c.readErr = hideTempErr(err) break } + if frameType == TextMessage || frameType == BinaryMessage { c.messageReader = &messageReader{c} c.reader = c.messageReader @@ -990,7 +1023,9 @@ func (r *messageReader) Read(b []byte) (int, error) { if c.isServer { c.readMaskPos = maskBytes(c.readMaskKey, c.readMaskPos, b[:n]) } - c.readRemaining -= int64(n) + rem := c.readRemaining + rem -= int64(n) + c.setReadRemaining(rem) if c.readRemaining > 0 && c.readErr == io.EOF { c.readErr = errUnexpectedEOF } diff --git a/vendor/github.com/gorilla/websocket/doc.go b/vendor/github.com/gorilla/websocket/doc.go index dcce1a63c0..c6f4df8960 100644 --- a/vendor/github.com/gorilla/websocket/doc.go +++ b/vendor/github.com/gorilla/websocket/doc.go @@ -151,6 +151,53 @@ // checking. The application is responsible for checking the Origin header // before calling the Upgrade function. // +// Buffers +// +// Connections buffer network input and output to reduce the number +// of system calls when reading or writing messages. +// +// Write buffers are also used for constructing WebSocket frames. See RFC 6455, +// Section 5 for a discussion of message framing. A WebSocket frame header is +// written to the network each time a write buffer is flushed to the network. +// Decreasing the size of the write buffer can increase the amount of framing +// overhead on the connection. +// +// The buffer sizes in bytes are specified by the ReadBufferSize and +// WriteBufferSize fields in the Dialer and Upgrader. The Dialer uses a default +// size of 4096 when a buffer size field is set to zero. The Upgrader reuses +// buffers created by the HTTP server when a buffer size field is set to zero. +// The HTTP server buffers have a size of 4096 at the time of this writing. +// +// The buffer sizes do not limit the size of a message that can be read or +// written by a connection. +// +// Buffers are held for the lifetime of the connection by default. If the +// Dialer or Upgrader WriteBufferPool field is set, then a connection holds the +// write buffer only when writing a message. +// +// Applications should tune the buffer sizes to balance memory use and +// performance. Increasing the buffer size uses more memory, but can reduce the +// number of system calls to read or write the network. In the case of writing, +// increasing the buffer size can reduce the number of frame headers written to +// the network. +// +// Some guidelines for setting buffer parameters are: +// +// Limit the buffer sizes to the maximum expected message size. Buffers larger +// than the largest message do not provide any benefit. +// +// Depending on the distribution of message sizes, setting the buffer size to +// to a value less than the maximum expected message size can greatly reduce +// memory use with a small impact on performance. Here's an example: If 99% of +// the messages are smaller than 256 bytes and the maximum message size is 512 +// bytes, then a buffer size of 256 bytes will result in 1.01 more system calls +// than a buffer size of 512 bytes. The memory savings is 50%. +// +// A write buffer pool is useful when the application has a modest number +// writes over a large number of connections. when buffers are pooled, a larger +// buffer size has a reduced impact on total memory use and has the benefit of +// reducing system calls and frame overhead. +// // Compression EXPERIMENTAL // // Per message compression extensions (RFC 7692) are experimentally supported diff --git a/vendor/github.com/gorilla/websocket/go.mod b/vendor/github.com/gorilla/websocket/go.mod new file mode 100644 index 0000000000..1a7afd5028 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/go.mod @@ -0,0 +1,3 @@ +module github.com/gorilla/websocket + +go 1.12 diff --git a/vendor/github.com/gorilla/websocket/go.sum b/vendor/github.com/gorilla/websocket/go.sum new file mode 100644 index 0000000000..cf4fbbaa07 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/go.sum @@ -0,0 +1,2 @@ +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= diff --git a/vendor/github.com/gorilla/websocket/join.go b/vendor/github.com/gorilla/websocket/join.go new file mode 100644 index 0000000000..c64f8c8290 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/join.go @@ -0,0 +1,42 @@ +// Copyright 2019 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "io" + "strings" +) + +// JoinMessages concatenates received messages to create a single io.Reader. +// The string term is appended to each message. The returned reader does not +// support concurrent calls to the Read method. +func JoinMessages(c *Conn, term string) io.Reader { + return &joinReader{c: c, term: term} +} + +type joinReader struct { + c *Conn + term string + r io.Reader +} + +func (r *joinReader) Read(p []byte) (int, error) { + if r.r == nil { + var err error + _, r.r, err = r.c.NextReader() + if err != nil { + return 0, err + } + if r.term != "" { + r.r = io.MultiReader(r.r, strings.NewReader(r.term)) + } + } + n, err := r.r.Read(p) + if err == io.EOF { + err = nil + r.r = nil + } + return n, err +} diff --git a/vendor/github.com/gorilla/websocket/proxy.go b/vendor/github.com/gorilla/websocket/proxy.go index bf2478e430..e87a8c9f0c 100644 --- a/vendor/github.com/gorilla/websocket/proxy.go +++ b/vendor/github.com/gorilla/websocket/proxy.go @@ -22,18 +22,18 @@ func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) { func init() { proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) { - return &httpProxyDialer{proxyURL: proxyURL, fowardDial: forwardDialer.Dial}, nil + return &httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDialer.Dial}, nil }) } type httpProxyDialer struct { - proxyURL *url.URL - fowardDial func(network, addr string) (net.Conn, error) + proxyURL *url.URL + forwardDial func(network, addr string) (net.Conn, error) } func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) { hostPort, _ := hostPortNoPort(hpd.proxyURL) - conn, err := hpd.fowardDial(network, hostPort) + conn, err := hpd.forwardDial(network, hostPort) if err != nil { return nil, err } diff --git a/vendor/github.com/gorilla/websocket/server.go b/vendor/github.com/gorilla/websocket/server.go index 3d4480a477..887d558918 100644 --- a/vendor/github.com/gorilla/websocket/server.go +++ b/vendor/github.com/gorilla/websocket/server.go @@ -153,7 +153,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade challengeKey := r.Header.Get("Sec-Websocket-Key") if challengeKey == "" { - return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: `Sec-WebSocket-Key' header is missing or blank") + return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header is missing or blank") } subprotocol := u.selectSubprotocol(r, responseHeader) diff --git a/vendor/github.com/ipfs/go-ipfs/namesys/routing.go b/vendor/github.com/ipfs/go-ipfs/namesys/routing.go index e06d6f1b9c..0fa48e6b5e 100644 --- a/vendor/github.com/ipfs/go-ipfs/namesys/routing.go +++ b/vendor/github.com/ipfs/go-ipfs/namesys/routing.go @@ -6,6 +6,7 @@ import ( "time" path "gx/ipfs/QmQAgv6Gaoe2tQpcabqwKXKChp2MZ7i3UXv9DqTTaxCaTR/go-path" + dht "gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht" // OpenBazaar: this is updated to OpenBazaar fork because of go-ipfs issue #5957 cid "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid" ipns "gx/ipfs/QmUwMnKKjH3JwGKNVZ3TcP37W93xzqNA4ECFFiMo6sXkkc/go-ipns" pb "gx/ipfs/QmUwMnKKjH3JwGKNVZ3TcP37W93xzqNA4ECFFiMo6sXkkc/go-ipns/pb" @@ -13,7 +14,6 @@ import ( peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" routing "gx/ipfs/QmYxUdYY9S6yg5tSPVin5GFTvtfsLauVcr7reHDD3dM8xf/go-libp2p-routing" logging "gx/ipfs/QmbkT7eMTyXfpeyB3ZMxxcxg7XH8t6uXp49jqzz4HB7BGF/go-log" - dht "gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht" // OpenBazaar: this is updated to OpenBazaar fork because of go-ipfs issue #5957 proto "gx/ipfs/QmddjPSGZb3ieihSseFeCfVRpZzcqczPNsD2DvarSwnjJB/gogo-protobuf/proto" mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" ) diff --git a/vendor/github.com/joho/godotenv/.gitignore b/vendor/github.com/joho/godotenv/.gitignore new file mode 100644 index 0000000000..e43b0f9889 --- /dev/null +++ b/vendor/github.com/joho/godotenv/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/vendor/github.com/joho/godotenv/.travis.yml b/vendor/github.com/joho/godotenv/.travis.yml new file mode 100644 index 0000000000..f0db1adcdb --- /dev/null +++ b/vendor/github.com/joho/godotenv/.travis.yml @@ -0,0 +1,8 @@ +language: go + +go: + - 1.x + +os: + - linux + - osx diff --git a/vendor/github.com/joho/godotenv/LICENCE b/vendor/github.com/joho/godotenv/LICENCE new file mode 100644 index 0000000000..e7ddd51be9 --- /dev/null +++ b/vendor/github.com/joho/godotenv/LICENCE @@ -0,0 +1,23 @@ +Copyright (c) 2013 John Barton + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/vendor/github.com/joho/godotenv/README.md b/vendor/github.com/joho/godotenv/README.md new file mode 100644 index 0000000000..d5370ec790 --- /dev/null +++ b/vendor/github.com/joho/godotenv/README.md @@ -0,0 +1,188 @@ +# GoDotEnv [![Build Status](https://travis-ci.org/joho/godotenv.svg?branch=master)](https://travis-ci.org/joho/godotenv) [![Build status](https://ci.appveyor.com/api/projects/status/9v40vnfvvgde64u4?svg=true)](https://ci.appveyor.com/project/joho/godotenv) [![Go Report Card](https://goreportcard.com/badge/github.com/joho/godotenv)](https://goreportcard.com/report/github.com/joho/godotenv) + +A Go (golang) port of the Ruby dotenv project (which loads env vars from a .env file) + +From the original Library: + +> Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environments–such as resource handles for databases or credentials for external services–should be extracted from the code into environment variables. +> +> But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped. + +It can be used as a library (for loading in env for your own daemons etc) or as a bin command. + +There is test coverage and CI for both linuxish and windows environments, but I make no guarantees about the bin version working on windows. + +## Installation + +As a library + +```shell +go get github.com/joho/godotenv +``` + +or if you want to use it as a bin command +```shell +go get github.com/joho/godotenv/cmd/godotenv +``` + +## Usage + +Add your application configuration to your `.env` file in the root of your project: + +```shell +S3_BUCKET=YOURS3BUCKET +SECRET_KEY=YOURSECRETKEYGOESHERE +``` + +Then in your Go app you can do something like + +```go +package main + +import ( + "github.com/joho/godotenv" + "log" + "os" +) + +func main() { + err := godotenv.Load() + if err != nil { + log.Fatal("Error loading .env file") + } + + s3Bucket := os.Getenv("S3_BUCKET") + secretKey := os.Getenv("SECRET_KEY") + + // now do something with s3 or whatever +} +``` + +If you're even lazier than that, you can just take advantage of the autoload package which will read in `.env` on import + +```go +import _ "github.com/joho/godotenv/autoload" +``` + +While `.env` in the project root is the default, you don't have to be constrained, both examples below are 100% legit + +```go +_ = godotenv.Load("somerandomfile") +_ = godotenv.Load("filenumberone.env", "filenumbertwo.env") +``` + +If you want to be really fancy with your env file you can do comments and exports (below is a valid env file) + +```shell +# I am a comment and that is OK +SOME_VAR=someval +FOO=BAR # comments at line end are OK too +export BAR=BAZ +``` + +Or finally you can do YAML(ish) style + +```yaml +FOO: bar +BAR: baz +``` + +as a final aside, if you don't want godotenv munging your env you can just get a map back instead + +```go +var myEnv map[string]string +myEnv, err := godotenv.Read() + +s3Bucket := myEnv["S3_BUCKET"] +``` + +... or from an `io.Reader` instead of a local file + +```go +reader := getRemoteFile() +myEnv, err := godotenv.Parse(reader) +``` + +... or from a `string` if you so desire + +```go +content := getRemoteFileContent() +myEnv, err := godotenv.Unmarshal(content) +``` + +### Precendence & Conventions + +Existing envs take precendence of envs that are loaded later. + +The [convention](https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use) +for managing multiple environments (i.e. development, test, production) +is to create an env named `{YOURAPP}_ENV` and load envs in this order: + +```go +env := os.Getenv("FOO_ENV") +if "" == env { + env = "development" +} + +godotenv.Load(".env." + env + ".local") +if "test" != env { + godotenv.Load(".env.local") +} +godotenv.Load(".env." + env) +godotenv.Load() // The Original .env +``` + +If you need to, you can also use `godotenv.Overload()` to defy this convention +and overwrite existing envs instead of only supplanting them. Use with caution. + +### Command Mode + +Assuming you've installed the command as above and you've got `$GOPATH/bin` in your `$PATH` + +``` +godotenv -f /some/path/to/.env some_command with some args +``` + +If you don't specify `-f` it will fall back on the default of loading `.env` in `PWD` + +### Writing Env Files + +Godotenv can also write a map representing the environment to a correctly-formatted and escaped file + +```go +env, err := godotenv.Unmarshal("KEY=value") +err := godotenv.Write(env, "./.env") +``` + +... or to a string + +```go +env, err := godotenv.Unmarshal("KEY=value") +content, err := godotenv.Marshal(env) +``` + +## Contributing + +Contributions are most welcome! The parser itself is pretty stupidly naive and I wouldn't be surprised if it breaks with edge cases. + +*code changes without tests will not be accepted* + +1. Fork it +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Added some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create new Pull Request + +## Releases + +Releases should follow [Semver](http://semver.org/) though the first couple of releases are `v1` and `v1.1`. + +Use [annotated tags for all releases](https://github.com/joho/godotenv/issues/30). Example `git tag -a v1.2.1` + +## CI + +Linux: [![Build Status](https://travis-ci.org/joho/godotenv.svg?branch=master)](https://travis-ci.org/joho/godotenv) Windows: [![Build status](https://ci.appveyor.com/api/projects/status/9v40vnfvvgde64u4)](https://ci.appveyor.com/project/joho/godotenv) + +## Who? + +The original library [dotenv](https://github.com/bkeepers/dotenv) was written by [Brandon Keepers](http://opensoul.org/), and this port was done by [John Barton](https://johnbarton.co/) based off the tests/fixtures in the original library. diff --git a/vendor/github.com/joho/godotenv/autoload/autoload.go b/vendor/github.com/joho/godotenv/autoload/autoload.go new file mode 100644 index 0000000000..fbcd2bdf8e --- /dev/null +++ b/vendor/github.com/joho/godotenv/autoload/autoload.go @@ -0,0 +1,15 @@ +package autoload + +/* + You can just read the .env file on import just by doing + + import _ "github.com/joho/godotenv/autoload" + + And bob's your mother's brother +*/ + +import "github.com/joho/godotenv" + +func init() { + godotenv.Load() +} diff --git a/vendor/github.com/joho/godotenv/godotenv.go b/vendor/github.com/joho/godotenv/godotenv.go new file mode 100644 index 0000000000..330f1c2fca --- /dev/null +++ b/vendor/github.com/joho/godotenv/godotenv.go @@ -0,0 +1,353 @@ +// Package godotenv is a go port of the ruby dotenv library (https://github.com/bkeepers/dotenv) +// +// Examples/readme can be found on the github page at https://github.com/joho/godotenv +// +// The TL;DR is that you make a .env file that looks something like +// +// SOME_ENV_VAR=somevalue +// +// and then in your go code you can call +// +// godotenv.Load() +// +// and all the env vars declared in .env will be available through os.Getenv("SOME_ENV_VAR") +package godotenv + +import ( + "bufio" + "errors" + "fmt" + "io" + "os" + "os/exec" + "regexp" + "sort" + "strings" +) + +const doubleQuoteSpecialChars = "\\\n\r\"!$`" + +// Load will read your env file(s) and load them into ENV for this process. +// +// Call this function as close as possible to the start of your program (ideally in main) +// +// If you call Load without any args it will default to loading .env in the current path +// +// You can otherwise tell it which files to load (there can be more than one) like +// +// godotenv.Load("fileone", "filetwo") +// +// It's important to note that it WILL NOT OVERRIDE an env variable that already exists - consider the .env file to set dev vars or sensible defaults +func Load(filenames ...string) (err error) { + filenames = filenamesOrDefault(filenames) + + for _, filename := range filenames { + err = loadFile(filename, false) + if err != nil { + return // return early on a spazout + } + } + return +} + +// Overload will read your env file(s) and load them into ENV for this process. +// +// Call this function as close as possible to the start of your program (ideally in main) +// +// If you call Overload without any args it will default to loading .env in the current path +// +// You can otherwise tell it which files to load (there can be more than one) like +// +// godotenv.Overload("fileone", "filetwo") +// +// It's important to note this WILL OVERRIDE an env variable that already exists - consider the .env file to forcefilly set all vars. +func Overload(filenames ...string) (err error) { + filenames = filenamesOrDefault(filenames) + + for _, filename := range filenames { + err = loadFile(filename, true) + if err != nil { + return // return early on a spazout + } + } + return +} + +// Read all env (with same file loading semantics as Load) but return values as +// a map rather than automatically writing values into env +func Read(filenames ...string) (envMap map[string]string, err error) { + filenames = filenamesOrDefault(filenames) + envMap = make(map[string]string) + + for _, filename := range filenames { + individualEnvMap, individualErr := readFile(filename) + + if individualErr != nil { + err = individualErr + return // return early on a spazout + } + + for key, value := range individualEnvMap { + envMap[key] = value + } + } + + return +} + +// Parse reads an env file from io.Reader, returning a map of keys and values. +func Parse(r io.Reader) (envMap map[string]string, err error) { + envMap = make(map[string]string) + + var lines []string + scanner := bufio.NewScanner(r) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + + if err = scanner.Err(); err != nil { + return + } + + for _, fullLine := range lines { + if !isIgnoredLine(fullLine) { + var key, value string + key, value, err = parseLine(fullLine, envMap) + + if err != nil { + return + } + envMap[key] = value + } + } + return +} + +//Unmarshal reads an env file from a string, returning a map of keys and values. +func Unmarshal(str string) (envMap map[string]string, err error) { + return Parse(strings.NewReader(str)) +} + +// Exec loads env vars from the specified filenames (empty map falls back to default) +// then executes the cmd specified. +// +// Simply hooks up os.Stdin/err/out to the command and calls Run() +// +// If you want more fine grained control over your command it's recommended +// that you use `Load()` or `Read()` and the `os/exec` package yourself. +func Exec(filenames []string, cmd string, cmdArgs []string) error { + Load(filenames...) + + command := exec.Command(cmd, cmdArgs...) + command.Stdin = os.Stdin + command.Stdout = os.Stdout + command.Stderr = os.Stderr + return command.Run() +} + +// Write serializes the given environment and writes it to a file +func Write(envMap map[string]string, filename string) error { + content, error := Marshal(envMap) + if error != nil { + return error + } + file, error := os.Create(filename) + if error != nil { + return error + } + _, err := file.WriteString(content) + return err +} + +// Marshal outputs the given environment as a dotenv-formatted environment file. +// Each line is in the format: KEY="VALUE" where VALUE is backslash-escaped. +func Marshal(envMap map[string]string) (string, error) { + lines := make([]string, 0, len(envMap)) + for k, v := range envMap { + lines = append(lines, fmt.Sprintf(`%s="%s"`, k, doubleQuoteEscape(v))) + } + sort.Strings(lines) + return strings.Join(lines, "\n"), nil +} + +func filenamesOrDefault(filenames []string) []string { + if len(filenames) == 0 { + return []string{".env"} + } + return filenames +} + +func loadFile(filename string, overload bool) error { + envMap, err := readFile(filename) + if err != nil { + return err + } + + currentEnv := map[string]bool{} + rawEnv := os.Environ() + for _, rawEnvLine := range rawEnv { + key := strings.Split(rawEnvLine, "=")[0] + currentEnv[key] = true + } + + for key, value := range envMap { + if !currentEnv[key] || overload { + os.Setenv(key, value) + } + } + + return nil +} + +func readFile(filename string) (envMap map[string]string, err error) { + file, err := os.Open(filename) + if err != nil { + return + } + defer file.Close() + + return Parse(file) +} + +var exportRegex = regexp.MustCompile(`^\s*(?:export\s+)?(.*?)\s*$`) + +func parseLine(line string, envMap map[string]string) (key string, value string, err error) { + if len(line) == 0 { + err = errors.New("zero length string") + return + } + + // ditch the comments (but keep quoted hashes) + if strings.Contains(line, "#") { + segmentsBetweenHashes := strings.Split(line, "#") + quotesAreOpen := false + var segmentsToKeep []string + for _, segment := range segmentsBetweenHashes { + if strings.Count(segment, "\"") == 1 || strings.Count(segment, "'") == 1 { + if quotesAreOpen { + quotesAreOpen = false + segmentsToKeep = append(segmentsToKeep, segment) + } else { + quotesAreOpen = true + } + } + + if len(segmentsToKeep) == 0 || quotesAreOpen { + segmentsToKeep = append(segmentsToKeep, segment) + } + } + + line = strings.Join(segmentsToKeep, "#") + } + + firstEquals := strings.Index(line, "=") + firstColon := strings.Index(line, ":") + splitString := strings.SplitN(line, "=", 2) + if firstColon != -1 && (firstColon < firstEquals || firstEquals == -1) { + //this is a yaml-style line + splitString = strings.SplitN(line, ":", 2) + } + + if len(splitString) != 2 { + err = errors.New("Can't separate key from value") + return + } + + // Parse the key + key = splitString[0] + if strings.HasPrefix(key, "export") { + key = strings.TrimPrefix(key, "export") + } + key = strings.TrimSpace(key) + + key = exportRegex.ReplaceAllString(splitString[0], "$1") + + // Parse the value + value = parseValue(splitString[1], envMap) + return +} + +var ( + singleQuotesRegex = regexp.MustCompile(`\A'(.*)'\z`) + doubleQuotesRegex = regexp.MustCompile(`\A"(.*)"\z`) + escapeRegex = regexp.MustCompile(`\\.`) + unescapeCharsRegex = regexp.MustCompile(`\\([^$])`) +) + +func parseValue(value string, envMap map[string]string) string { + + // trim + value = strings.Trim(value, " ") + + // check if we've got quoted values or possible escapes + if len(value) > 1 { + singleQuotes := singleQuotesRegex.FindStringSubmatch(value) + + doubleQuotes := doubleQuotesRegex.FindStringSubmatch(value) + + if singleQuotes != nil || doubleQuotes != nil { + // pull the quotes off the edges + value = value[1 : len(value)-1] + } + + if doubleQuotes != nil { + // expand newlines + value = escapeRegex.ReplaceAllStringFunc(value, func(match string) string { + c := strings.TrimPrefix(match, `\`) + switch c { + case "n": + return "\n" + case "r": + return "\r" + default: + return match + } + }) + // unescape characters + value = unescapeCharsRegex.ReplaceAllString(value, "$1") + } + + if singleQuotes == nil { + value = expandVariables(value, envMap) + } + } + + return value +} + +var expandVarRegex = regexp.MustCompile(`(\\)?(\$)(\()?\{?([A-Z0-9_]+)?\}?`) + +func expandVariables(v string, m map[string]string) string { + return expandVarRegex.ReplaceAllStringFunc(v, func(s string) string { + submatch := expandVarRegex.FindStringSubmatch(s) + + if submatch == nil { + return s + } + if submatch[1] == "\\" || submatch[2] == "(" { + return submatch[0][1:] + } else if submatch[4] != "" { + return m[submatch[4]] + } + return s + }) +} + +func isIgnoredLine(line string) bool { + trimmedLine := strings.TrimSpace(line) + return len(trimmedLine) == 0 || strings.HasPrefix(trimmedLine, "#") +} + +func doubleQuoteEscape(line string) string { + for _, c := range doubleQuoteSpecialChars { + toReplace := "\\" + string(c) + if c == '\n' { + toReplace = `\n` + } + if c == '\r' { + toReplace = `\r` + } + line = strings.Replace(line, string(c), toReplace, -1) + } + return line +} diff --git a/vendor/github.com/ltcsuite/ltcutil/certgen.go b/vendor/github.com/ltcsuite/ltcutil/certgen.go index 9a19c7e819..f8af92ce45 100644 --- a/vendor/github.com/ltcsuite/ltcutil/certgen.go +++ b/vendor/github.com/ltcsuite/ltcutil/certgen.go @@ -110,7 +110,7 @@ func NewTLSCertPair(organization string, validUntil time.Time, extraHosts []stri KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - IsCA: true, // so can sign self. + IsCA: true, // so can sign self. BasicConstraintsValid: true, DNSNames: dnsNames, diff --git a/vendor/github.com/nanmu42/etherscan-api/.gitignore b/vendor/github.com/nanmu42/etherscan-api/.gitignore new file mode 100644 index 0000000000..e0ab53c997 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# IDEs +/.idea + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out diff --git a/vendor/github.com/nanmu42/etherscan-api/.travis.yml b/vendor/github.com/nanmu42/etherscan-api/.travis.yml new file mode 100644 index 0000000000..297a5cc4c6 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/.travis.yml @@ -0,0 +1,10 @@ +language: go + +env: + - GO111MODULE=on + +script: + - go test -v -coverprofile=coverage.txt -covermode=count ./... + +after_success: + - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/vendor/github.com/nanmu42/etherscan-api/LICENSE b/vendor/github.com/nanmu42/etherscan-api/LICENSE new file mode 100644 index 0000000000..d46d7e7cf7 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 LI Zhennan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/nanmu42/etherscan-api/README.md b/vendor/github.com/nanmu42/etherscan-api/README.md new file mode 100644 index 0000000000..4087c3a60c --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/README.md @@ -0,0 +1,66 @@ +# etherscan-api + +[![Build Status](https://travis-ci.org/nanmu42/etherscan-api.svg?branch=master)](https://travis-ci.org/nanmu42/etherscan-api) +[![Go Report Card](https://goreportcard.com/badge/github.com/nanmu42/etherscan-api)](https://goreportcard.com/report/github.com/nanmu42/etherscan-api) +[![codecov](https://codecov.io/gh/nanmu42/etherscan-api/branch/master/graph/badge.svg)](https://codecov.io/gh/nanmu42/etherscan-api) +[![GoDoc](https://godoc.org/github.com/nanmu42/etherscan-api?status.svg)](https://godoc.org/github.com/nanmu42/etherscan-api) +[中文文档](https://github.com/nanmu42/etherscan-api/blob/master/README_ZH.md) + +Go bindings to the Etherscan.io API, with nearly Full implementation(accounts, transactions, tokens, contracts, blocks, stats), full network support(Mainnet, Ropsten, Kovan, Rinkby, Tobalaba), and only depending on standard library. :wink: + +# Usage + +Create a API instance and off you go. :rocket: + +```go +import ( + "github.com/nanmu42/etherscan-api" + "fmt" +) + +func main() { + // create a API client for specified ethereum net + // there are many pre-defined network in package + client := etherscan.New(etherscan.Mainnet, "[your API key]") + + // (optional) add hooks, e.g. for rate limit + client.BeforeRequest = func(module, action string, param map[string]interface{}) error { + // ... + } + client.AfterRequest = func(module, action string, param map[string]interface{}, outcome interface{}, requestErr error) { + // ... + } + + // check account balance + balance, err := client.AccountBalance("0x281055afc982d96fab65b3a49cac8b878184cb16") + if err != nil { + panic(err) + } + // balance in wei, in *big.Int type + fmt.Println(balance.Int()) + + // check token balance + tokenBalance, err := client.TokenBalance("contractAddress", "holderAddress") + + // check ERC20 transactions from/to a specified address + transfers, err := client.ERC20Transfers("contractAddress", "address", startBlock, endBlock, page, offset) +} +``` + +You may find full method list at [GoDoc](https://godoc.org/github.com/nanmu42/etherscan-api). + +# Etherscan API Key + +You may apply for an API key on [etherscan](https://etherscan.io/apis). + +> The Etherscan Ethereum Developer APIs are provided as a community service and without warranty, so please just use what you need and no more. They support both GET/POST requests and a rate limit of 5 requests/sec (exceed and you will be blocked). + +# Paperwork Things + +I am not from Etherscan and I just find their service really useful, so I implement this. :smile: + +# License + +Use of this work is governed by a MIT License. + +You may find a license copy in project root. diff --git a/vendor/github.com/nanmu42/etherscan-api/README_ZH.md b/vendor/github.com/nanmu42/etherscan-api/README_ZH.md new file mode 100644 index 0000000000..1e38dae310 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/README_ZH.md @@ -0,0 +1,69 @@ +# etherscan-api + +[![Build Status](https://travis-ci.org/nanmu42/etherscan-api.svg?branch=master)](https://travis-ci.org/nanmu42/etherscan-api) +[![Go Report Card](https://goreportcard.com/badge/github.com/nanmu42/etherscan-api)](https://goreportcard.com/report/github.com/nanmu42/etherscan-api) +[![codecov](https://codecov.io/gh/nanmu42/etherscan-api/branch/master/graph/badge.svg)](https://codecov.io/gh/nanmu42/etherscan-api) +[![GoDoc](https://godoc.org/github.com/nanmu42/etherscan-api?status.svg)](https://godoc.org/github.com/nanmu42/etherscan-api) +[English Readme](https://github.com/nanmu42/etherscan-api/blob/master/README.md) + +Etherscan.io的Golang实现, +支持几乎所有功能(accounts, transactions, tokens, contracts, blocks, stats), +所有公共网络(Mainnet, Ropsten, Kovan, Rinkby, Tobalaba)。 +本项目只依赖于官方库。 :wink: + +# Usage + +填入网络选项和API Key即可开始使用。 :rocket: + +```go +import ( + "github.com/nanmu42/etherscan-api" + "fmt" +) + +func main() { + // 创建连接指定网络的客户端 + client := etherscan.New(etherscan.Mainnet, "[your API key]") + + // (可选)按需注册钩子函数,例如用于速率控制 + client.BeforeRequest = func(module, action string, param map[string]interface{}) error { + // ... + } + client.AfterRequest = func(module, action string, param map[string]interface{}, outcome interface{}, requestErr error) { + // ... + } + + // 查询账户以太坊余额 + balance, err := client.AccountBalance("0x281055afc982d96fab65b3a49cac8b878184cb16") + if err != nil { + panic(err) + } + // 余额以 *big.Int 的类型呈现,单位为 wei + fmt.Println(balance.Int()) + + // 查询token余额 + tokenBalance, err := client.TokenBalance("contractAddress", "holderAddress") + + // 查询出入指定地址的ERC20转账列表 + transfers, err := client.ERC20Transfers("contractAddress", "address", startBlock, endBlock, page, offset) +} +``` + +客户端方法列表可在[GoDoc](https://godoc.org/github.com/nanmu42/etherscan-api)查询。 + +# Etherscan API Key + +API Key可以在[etherscan](https://etherscan.io/apis)申请。 + +Etherscan的API服务是一个公开的社区无偿服务,请避免滥用。 +API的调用速率不能高于5次/秒,否则会遭到封禁。 + +# 利益声明 + +我和Etherscan没有任何联系。我仅仅是觉得他们的服务很棒,而自己又恰好需要这样一个库。 :smile: + +# 许可证 + +MIT + +请自由享受开源,欢迎贡献开源。 \ No newline at end of file diff --git a/vendor/github.com/nanmu42/etherscan-api/account.go b/vendor/github.com/nanmu42/etherscan-api/account.go new file mode 100644 index 0000000000..48c149b969 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/account.go @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +// AccountBalance gets ether balance for a single address +func (c *Client) AccountBalance(address string) (balance *BigInt, err error) { + param := M{ + "tag": "latest", + "address": address, + } + balance = new(BigInt) + err = c.call("account", "balance", param, balance) + return +} + +// MultiAccountBalance gets ether balance for multiple addresses in a single call +func (c *Client) MultiAccountBalance(addresses ...string) (balances []AccountBalance, err error) { + param := M{ + "tag": "latest", + "address": addresses, + } + balances = make([]AccountBalance, 0, len(addresses)) + err = c.call("account", "balancemulti", param, &balances) + return +} + +// NormalTxByAddress gets a list of "normal" transactions by address +// +// startBlock and endBlock can be nil +// +// if desc is true, result will be sorted in blockNum descendant order. +func (c *Client) NormalTxByAddress(address string, startBlock *int, endBlock *int, page int, offset int, desc bool) (txs []NormalTx, err error) { + param := M{ + "address": address, + "page": page, + "offset": offset, + } + compose(param, "startblock", startBlock) + compose(param, "endblock", endBlock) + if desc { + param["sort"] = "desc" + } else { + param["sort"] = "asc" + } + + err = c.call("account", "txlist", param, &txs) + return +} + +// InternalTxByAddress gets a list of "internal" transactions by address +// +// startBlock and endBlock can be nil +// +// if desc is true, result will be sorted in descendant order. +func (c *Client) InternalTxByAddress(address string, startBlock *int, endBlock *int, page int, offset int, desc bool) (txs []InternalTx, err error) { + param := M{ + "address": address, + "page": page, + "offset": offset, + } + compose(param, "startblock", startBlock) + compose(param, "endblock", endBlock) + if desc { + param["sort"] = "desc" + } else { + param["sort"] = "asc" + } + + err = c.call("account", "txlistinternal", param, &txs) + return +} + +// ERC20Transfers get a list of "erc20 - token transfer events" by +// contract address and/or from/to address. +// +// leave undesired condition to nil. +// +// Note on a Etherscan bug: +// Some ERC20 contract does not have valid decimals information in Etherscan. +// When that happens, TokenName, TokenSymbol are empty strings, +// and TokenDecimal is 0. +// +// More information can be found at: +// https://github.com/nanmu42/etherscan-api/issues/8 +func (c *Client) ERC20Transfers(contractAddress, address *string, startBlock *int, endBlock *int, page int, offset int, desc bool) (txs []ERC20Transfer, err error) { + param := M{ + "page": page, + "offset": offset, + } + compose(param, "contractaddress", contractAddress) + compose(param, "address", address) + compose(param, "startblock", startBlock) + compose(param, "endblock", endBlock) + + if desc { + param["sort"] = "desc" + } else { + param["sort"] = "asc" + } + + err = c.call("account", "tokentx", param, &txs) + return +} + +// BlocksMinedByAddress gets list of blocks mined by address +func (c *Client) BlocksMinedByAddress(address string, page int, offset int) (mined []MinedBlock, err error) { + param := M{ + "address": address, + "blocktype": "blocks", + "page": page, + "offset": offset, + } + + err = c.call("account", "getminedblocks", param, &mined) + return +} + +// UnclesMinedByAddress gets list of uncles mined by address +func (c *Client) UnclesMinedByAddress(address string, page int, offset int) (mined []MinedBlock, err error) { + param := M{ + "address": address, + "blocktype": "uncles", + "page": page, + "offset": offset, + } + + err = c.call("account", "getminedblocks", param, &mined) + return +} + +// TokenBalance get erc20-token account balance of address for contractAddress +func (c *Client) TokenBalance(contractAddress, address string) (balance *BigInt, err error) { + param := M{ + "contractaddress": contractAddress, + "address": address, + "tag": "latest", + } + + err = c.call("account", "tokenbalance", param, &balance) + return +} diff --git a/vendor/github.com/nanmu42/etherscan-api/block.go b/vendor/github.com/nanmu42/etherscan-api/block.go new file mode 100644 index 0000000000..8c3736b700 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/block.go @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +// BlockReward gets block and uncle rewards by block number +func (c *Client) BlockReward(blockNum int) (rewards BlockRewards, err error) { + param := M{ + "blockno": blockNum, + } + + err = c.call("block", "getblockreward", param, &rewards) + return +} diff --git a/vendor/github.com/nanmu42/etherscan-api/client.go b/vendor/github.com/nanmu42/etherscan-api/client.go new file mode 100644 index 0000000000..b981d59309 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/client.go @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httputil" + "net/url" + "time" +) + +// Client etherscan API client +// Clients are safe for concurrent use by multiple goroutines. +type Client struct { + coon *http.Client + network Network + key string + baseURL string + + // Verbose when true, talks a lot + Verbose bool + + // BeforeRequest runs before every client request, in the same goroutine. + // May be used in rate limit. + // Request will be aborted, if BeforeRequest returns non-nil err. + BeforeRequest func(module, action string, param map[string]interface{}) error + + // AfterRequest runs after every client request, even when there is an error. + AfterRequest func(module, action string, param map[string]interface{}, outcome interface{}, requestErr error) +} + +// New initialize a new etherscan API client +// please use pre-defined network value +func New(network Network, APIKey string) *Client { + return &Client{ + coon: &http.Client{ + Timeout: 30 * time.Second, + }, + network: network, + key: APIKey, + baseURL: fmt.Sprintf(`https://%s.etherscan.io/api?`, network.SubDomain()), + } +} + +// call does almost all the dirty work. +func (c *Client) call(module, action string, param map[string]interface{}, outcome interface{}) (err error) { + // fire hooks if in need + if c.BeforeRequest != nil { + err = c.BeforeRequest(module, action, param) + if err != nil { + err = wrapErr(err, "beforeRequest") + return + } + } + if c.AfterRequest != nil { + defer c.AfterRequest(module, action, param, outcome, err) + } + + // recover if there shall be an panic + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("[ouch! panic recovered] please report this with what you did and what you expected, panic detail: %v", r) + } + }() + + req, err := http.NewRequest(http.MethodGet, c.craftURL(module, action, param), http.NoBody) + if err != nil { + err = wrapErr(err, "http.NewRequest") + return + } + req.Header.Set("User-Agent", "etherscan-api(Go)") + req.Header.Set("Content-Type", "application/json; charset=utf-8") + + if c.Verbose { + var reqDump []byte + reqDump, err = httputil.DumpRequestOut(req, false) + if err != nil { + err = wrapErr(err, "verbose mode req dump failed") + return + } + + fmt.Printf("\n%s\n", reqDump) + + defer func() { + if err != nil { + fmt.Printf("[Error] %v\n", err) + } + }() + } + + res, err := c.coon.Do(req) + if err != nil { + err = wrapErr(err, "sending request") + return + } + defer res.Body.Close() + + if c.Verbose { + var resDump []byte + resDump, err = httputil.DumpResponse(res, true) + if err != nil { + err = wrapErr(err, "verbose mode res dump failed") + return + } + + fmt.Printf("%s\n", resDump) + } + + var content bytes.Buffer + if _, err = io.Copy(&content, res.Body); err != nil { + err = wrapErr(err, "reading response") + return + } + + if res.StatusCode != http.StatusOK { + err = fmt.Errorf("response status %v %s, response body: %s", res.StatusCode, res.Status, content.String()) + return + } + + var envelope Envelope + err = json.Unmarshal(content.Bytes(), &envelope) + if err != nil { + err = wrapErr(err, "json unmarshal envelope") + return + } + if envelope.Status != 1 { + err = fmt.Errorf("etherscan server: %s", envelope.Message) + return + } + + // workaround for missing tokenDecimal for some tokentx calls + if action == "tokentx" { + err = json.Unmarshal(bytes.Replace(envelope.Result, []byte(`"tokenDecimal":""`), []byte(`"tokenDecimal":"0"`), -1), outcome) + } else { + err = json.Unmarshal(envelope.Result, outcome) + } + if err != nil { + err = wrapErr(err, "json unmarshal outcome") + return + } + + return +} + +// craftURL returns desired URL via param provided +func (c *Client) craftURL(module, action string, param map[string]interface{}) (URL string) { + q := url.Values{ + "module": []string{module}, + "action": []string{action}, + "apikey": []string{c.key}, + } + + for k, v := range param { + q[k] = extractValue(v) + } + + URL = c.baseURL + q.Encode() + return +} diff --git a/vendor/github.com/nanmu42/etherscan-api/contract.go b/vendor/github.com/nanmu42/etherscan-api/contract.go new file mode 100644 index 0000000000..11e9e35b2c --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/contract.go @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +// ContractABI gets contract abi for verified contract source codes +func (c *Client) ContractABI(address string) (abi string, err error) { + param := M{ + "address": address, + } + + err = c.call("contract", "getabi", param, &abi) + return +} + +// ContractSource gets contract source code for verified contract source codes +func (c *Client) ContractSource(address string) (source []ContractSource, err error) { + param := M{ + "address": address, + } + + err = c.call("contract", "getsourcecode", param, &source) + return +} diff --git a/vendor/github.com/nanmu42/etherscan-api/doc.go b/vendor/github.com/nanmu42/etherscan-api/doc.go new file mode 100644 index 0000000000..d345cab2b9 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/doc.go @@ -0,0 +1,9 @@ +// Package etherscan provides Go bindings to the Etherscan.io API. +// +// This work is a nearly Full implementation +// (accounts, transactions, tokens, contracts, blocks, stats), +// with full network support(Mainnet, Ropsten, Kovan, Rinkby, Tobalaba), +// and only depending on standard library. +// +// Example can be found at https://github.com/nanmu42/etherscan-api +package etherscan diff --git a/vendor/github.com/nanmu42/etherscan-api/error_wrap.go b/vendor/github.com/nanmu42/etherscan-api/error_wrap.go new file mode 100644 index 0000000000..36ea869be0 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/error_wrap.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +import ( + "fmt" +) + +// wrapErr gives error some context msg +// returns nil if err is nil +func wrapErr(err error, msg string) (errWithContext error) { + if err == nil { + return + } + + errWithContext = fmt.Errorf("%s: %v", msg, err) + return +} + +// wrapfErr gives error some context msg +// with desired format and content +// returns nil if err is nil +func wrapfErr(err error, format string, a ...interface{}) (errWithContext error) { + if err == nil { + return + } + + errWithContext = wrapErr(err, fmt.Sprintf(format, a...)) + return +} diff --git a/vendor/github.com/nanmu42/etherscan-api/go.mod b/vendor/github.com/nanmu42/etherscan-api/go.mod new file mode 100644 index 0000000000..0a301348e8 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/go.mod @@ -0,0 +1,3 @@ +module github.com/nanmu42/etherscan-api + +go 1.13 diff --git a/vendor/github.com/nanmu42/etherscan-api/helper.go b/vendor/github.com/nanmu42/etherscan-api/helper.go new file mode 100644 index 0000000000..89649709e9 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/helper.go @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +import ( + "math/big" + "reflect" + "strconv" + "time" +) + +// compose adds input to param, whose key is tag +// if input is nil or nil of some type, compose is a no-op. +func compose(param map[string]interface{}, tag string, input interface{}) { + // simple situation + if input == nil { + return + } + + // needs dig further + v := reflect.ValueOf(input) + switch v.Kind() { + case reflect.Ptr, reflect.Slice, reflect.Interface: + if v.IsNil() { + return + } + } + + param[tag] = input +} + +// M is a type shorthand for param input +type M map[string]interface{} + +// BigInt is a wrapper over big.Int to implement only unmarshalText +// for json decoding. +type BigInt big.Int + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +func (b *BigInt) UnmarshalText(text []byte) (err error) { + var bigInt = new(big.Int) + err = bigInt.UnmarshalText(text) + if err != nil { + return + } + + *b = BigInt(*bigInt) + return nil +} + +// MarshalText implements the encoding.TextMarshaler +func (b *BigInt) MarshalText() (text []byte, err error) { + return []byte(b.Int().String()), nil +} + +// Int returns b's *big.Int form +func (b *BigInt) Int() *big.Int { + return (*big.Int)(b) +} + +// Time is a wrapper over big.Int to implement only unmarshalText +// for json decoding. +type Time time.Time + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +func (t *Time) UnmarshalText(text []byte) (err error) { + input, err := strconv.ParseInt(string(text), 10, 64) + if err != nil { + err = wrapErr(err, "strconv.ParseInt") + return + } + + var timestamp = time.Unix(input, 0) + *t = Time(timestamp) + + return nil +} + +// Time returns t's time.Time form +func (t Time) Time() time.Time { + return time.Time(t) +} + +// MarshalText implements the encoding.TextMarshaler +func (t Time) MarshalText() (text []byte, err error) { + return []byte(strconv.FormatInt(t.Time().Unix(), 10)), nil +} diff --git a/vendor/github.com/nanmu42/etherscan-api/network.go b/vendor/github.com/nanmu42/etherscan-api/network.go new file mode 100644 index 0000000000..718e20770c --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/network.go @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +const ( + //// Ethereum public networks + + // Mainnet Ethereum mainnet for production + Mainnet Network = "api" + // Ropsten Testnet(POW) + Ropsten Network = "api-ropsten" + // Kovan Testnet(POA) + Kovan Network = "api-kovan" + // Rinkby Testnet(CLIQUE) + Rinkby Network = "api-rinkeby" + // Tobalaba Testnet + Tobalaba Network = "api-tobalaba" +) + +// Network is ethereum network type (mainnet, ropsten, etc) +type Network string + +// SubDomain returns the subdomain of etherscan API +// via n provided. +func (n Network) SubDomain() (sub string) { + return string(n) +} diff --git a/vendor/github.com/nanmu42/etherscan-api/reflect.go b/vendor/github.com/nanmu42/etherscan-api/reflect.go new file mode 100644 index 0000000000..328684aaf9 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/reflect.go @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +import ( + "fmt" + "reflect" + "strconv" +) + +// extractValue obtains string-formed slice representation via +// input. It only handles string, int, and their slice form, and +// panics otherwise. +func extractValue(input interface{}) (output []string) { + v := direct(reflect.ValueOf(input)) + + if v.Kind() == reflect.Slice { + length := v.Len() + output = make([]string, length) + + for i := 0; i < length; i++ { + output[i] = valueToStr(v.Index(i)) + } + } else { + output = make([]string, 1, 1) + output[0] = valueToStr(v) + } + + return +} + +// valueToStr convert v into proper string representation +// Only handles int and string, panic otherwise. +func valueToStr(v reflect.Value) (str string) { + switch v.Kind() { + case reflect.String: + str = v.String() + case reflect.Int: + str = strconv.FormatInt(v.Int(), 10) + default: + panic(fmt.Sprintf("valueToStr: %v is of unexpected kind %q", v, v.Kind())) + } + return +} + +// direct traverses the pointer chain to fetch +// the solid value +func direct(v reflect.Value) reflect.Value { + for ; v.Kind() == reflect.Ptr; v = v.Elem() { + // relax + } + return v +} diff --git a/vendor/github.com/nanmu42/etherscan-api/response.go b/vendor/github.com/nanmu42/etherscan-api/response.go new file mode 100644 index 0000000000..b1338d3f5a --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/response.go @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +import "encoding/json" + +// Envelope is the carrier of nearly every response +type Envelope struct { + // 1 for good, 0 for error + Status int `json:"status,string"` + // OK for good, other words when Status equals 0 + Message string `json:"message"` + // where response lies + Result json.RawMessage `json:"result"` +} + +// AccountBalance account and its balance in pair +type AccountBalance struct { + Account string `json:"account"` + Balance *BigInt `json:"balance"` +} + +// NormalTx holds info from normal tx query +type NormalTx struct { + BlockNumber int `json:"blockNumber,string"` + TimeStamp Time `json:"timeStamp"` + Hash string `json:"hash"` + Nonce int `json:"nonce,string"` + BlockHash string `json:"blockHash"` + TransactionIndex int `json:"transactionIndex,string"` + From string `json:"from"` + To string `json:"to"` + Value *BigInt `json:"value"` + Gas int `json:"gas,string"` + GasPrice *BigInt `json:"gasPrice"` + IsError int `json:"isError,string"` + TxReceiptStatus string `json:"txreceipt_status"` + Input string `json:"input"` + ContractAddress string `json:"contractAddress"` + CumulativeGasUsed int `json:"cumulativeGasUsed,string"` + GasUsed int `json:"gasUsed,string"` + Confirmations int `json:"confirmations,string"` +} + +// InternalTx holds info from internal tx query +type InternalTx struct { + BlockNumber int `json:"blockNumber,string"` + TimeStamp Time `json:"timeStamp"` + Hash string `json:"hash"` + From string `json:"from"` + To string `json:"to"` + Value *BigInt `json:"value"` + ContractAddress string `json:"contractAddress"` + Input string `json:"input"` + Type string `json:"type"` + Gas int `json:"gas,string"` + GasUsed int `json:"gasUsed,string"` + TraceID string `json:"traceId"` + IsError int `json:"isError,string"` + ErrCode string `json:"errCode"` +} + +// ERC20Transfer holds info from ERC20 token transfer event query +type ERC20Transfer struct { + BlockNumber int `json:"blockNumber,string"` + TimeStamp Time `json:"timeStamp"` + Hash string `json:"hash"` + Nonce int `json:"nonce,string"` + BlockHash string `json:"blockHash"` + From string `json:"from"` + ContractAddress string `json:"contractAddress"` + To string `json:"to"` + Value *BigInt `json:"value"` + TokenName string `json:"tokenName"` + TokenSymbol string `json:"tokenSymbol"` + TokenDecimal uint8 `json:"tokenDecimal,string"` + TransactionIndex int `json:"transactionIndex,string"` + Gas int `json:"gas,string"` + GasPrice *BigInt `json:"gasPrice"` + GasUsed int `json:"gasUsed,string"` + CumulativeGasUsed int `json:"cumulativeGasUsed,string"` + Input string `json:"input"` + Confirmations int `json:"confirmations,string"` +} + +// MinedBlock holds info from query for mined block by address +type MinedBlock struct { + BlockNumber int `json:"blockNumber,string"` + TimeStamp Time `json:"timeStamp"` + BlockReward *BigInt `json:"blockReward"` +} + +// ContractSource holds info from query for contract source code +type ContractSource struct { + SourceCode string `json:"SourceCode"` + ABI string `json:"ABI"` + ContractName string `json:"ContractName"` + CompilerVersion string `json:"CompilerVersion"` + OptimizationUsed int `json:"OptimizationUsed,string"` + Runs int `json:"Runs,string"` + ConstructorArguments string `json:"ConstructorArguments"` + Library string `json:"Library"` + SwarmSource string `json:"SwarmSource"` +} + +// ExecutionStatus holds info from query for transaction execution status +type ExecutionStatus struct { + // 0 = pass, 1 = error + IsError int `json:"isError,string"` + ErrDescription string `json:"errDescription"` +} + +// BlockRewards holds info from query for block and uncle rewards +type BlockRewards struct { + BlockNumber int `json:"blockNumber,string"` + TimeStamp Time `json:"timeStamp"` + BlockMiner string `json:"blockMiner"` + BlockReward *BigInt `json:"blockReward"` + Uncles []struct { + Miner string `json:"miner"` + UnclePosition int `json:"unclePosition,string"` + BlockReward *BigInt `json:"blockreward"` + } `json:"uncles"` + UncleInclusionReward *BigInt `json:"uncleInclusionReward"` +} + +// LatestPrice holds info from query for latest ether price +type LatestPrice struct { + ETHBTC float64 `json:"ethbtc,string"` + ETHBTCTimestamp Time `json:"ethbtc_timestamp"` + ETHUSD float64 `json:"ethusd,string"` + ETHUSDTimestamp Time `json:"ethusd_timestamp"` +} diff --git a/vendor/github.com/nanmu42/etherscan-api/stat.go b/vendor/github.com/nanmu42/etherscan-api/stat.go new file mode 100644 index 0000000000..d3dc156c73 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/stat.go @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +// EtherTotalSupply gets total supply of ether +func (c *Client) EtherTotalSupply() (totalSupply *BigInt, err error) { + err = c.call("stats", "ethsupply", nil, &totalSupply) + return +} + +// EtherLatestPrice gets the latest ether price, in BTC and USD +func (c *Client) EtherLatestPrice() (price LatestPrice, err error) { + err = c.call("stats", "ethprice", nil, &price) + return +} + +// TokenTotalSupply gets total supply of token on specified contract address +func (c *Client) TokenTotalSupply(contractAddress string) (totalSupply *BigInt, err error) { + param := M{ + "contractaddress": contractAddress, + } + + err = c.call("stats", "tokensupply", param, &totalSupply) + return +} diff --git a/vendor/github.com/nanmu42/etherscan-api/transaction.go b/vendor/github.com/nanmu42/etherscan-api/transaction.go new file mode 100644 index 0000000000..8461342fe4 --- /dev/null +++ b/vendor/github.com/nanmu42/etherscan-api/transaction.go @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018 LI Zhennan + * + * Use of this work is governed by a MIT License. + * You may find a license copy in project root. + */ + +package etherscan + +import "errors" + +// ErrPreByzantiumTx transaction before 4,370,000 does not support receipt status check +var ErrPreByzantiumTx = errors.New("pre-byzantium transaction does not support receipt status check") + +// ExecutionStatus checks contract execution status (if there was an error during contract execution) +// +// note on IsError: 0 = pass, 1 = error +func (c *Client) ExecutionStatus(txHash string) (status ExecutionStatus, err error) { + param := M{ + "txhash": txHash, + } + + err = c.call("transaction", "getstatus", param, &status) + return +} + +// ReceiptStatus checks transaction receipt status +// +// only applicable for post byzantium fork transactions, i.e. after block 4,370,000 +// +// An special err ErrPreByzantiumTx raises for the transaction before byzantium fork. +// +// Note: receiptStatus: 0 = Fail, 1 = Pass. +func (c *Client) ReceiptStatus(txHash string) (receiptStatus int, err error) { + param := M{ + "txhash": txHash, + } + + var rawStatus = struct { + Status string `json:"status"` + }{} + + err = c.call("transaction", "gettxreceiptstatus", param, &rawStatus) + if err != nil { + return + } + + switch rawStatus.Status { + case "0": + receiptStatus = 0 + case "1": + receiptStatus = 1 + default: + receiptStatus = -1 + err = ErrPreByzantiumTx + } + + return +} diff --git a/vendor/github.com/nfnt/resize/.travis.yml b/vendor/github.com/nfnt/resize/.travis.yml deleted file mode 100644 index 57bd4a76e8..0000000000 --- a/vendor/github.com/nfnt/resize/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: go - -go: - - 1.1 - - 1.2 - - 1.3 - - tip diff --git a/vendor/github.com/nfnt/resize/LICENSE b/vendor/github.com/nfnt/resize/LICENSE deleted file mode 100644 index 7836cad5ff..0000000000 --- a/vendor/github.com/nfnt/resize/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. diff --git a/vendor/github.com/nfnt/resize/README.md b/vendor/github.com/nfnt/resize/README.md deleted file mode 100644 index 2aefa75c94..0000000000 --- a/vendor/github.com/nfnt/resize/README.md +++ /dev/null @@ -1,149 +0,0 @@ -Resize -====== - -Image resizing for the [Go programming language](http://golang.org) with common interpolation methods. - -[![Build Status](https://travis-ci.org/nfnt/resize.svg)](https://travis-ci.org/nfnt/resize) - -Installation ------------- - -```bash -$ go get github.com/nfnt/resize -``` - -It's that easy! - -Usage ------ - -This package needs at least Go 1.1. Import package with - -```go -import "github.com/nfnt/resize" -``` - -The resize package provides 2 functions: - -* `resize.Resize` creates a scaled image with new dimensions (`width`, `height`) using the interpolation function `interp`. - If either `width` or `height` is set to 0, it will be set to an aspect ratio preserving value. -* `resize.Thumbnail` downscales an image preserving its aspect ratio to the maximum dimensions (`maxWidth`, `maxHeight`). - It will return the original image if original sizes are smaller than the provided dimensions. - -```go -resize.Resize(width, height uint, img image.Image, interp resize.InterpolationFunction) image.Image -resize.Thumbnail(maxWidth, maxHeight uint, img image.Image, interp resize.InterpolationFunction) image.Image -``` - -The provided interpolation functions are (from fast to slow execution time) - -- `NearestNeighbor`: [Nearest-neighbor interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation) -- `Bilinear`: [Bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation) -- `Bicubic`: [Bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) -- `MitchellNetravali`: [Mitchell-Netravali interpolation](http://dl.acm.org/citation.cfm?id=378514) -- `Lanczos2`: [Lanczos resampling](http://en.wikipedia.org/wiki/Lanczos_resampling) with a=2 -- `Lanczos3`: [Lanczos resampling](http://en.wikipedia.org/wiki/Lanczos_resampling) with a=3 - -Which of these methods gives the best results depends on your use case. - -Sample usage: - -```go -package main - -import ( - "github.com/nfnt/resize" - "image/jpeg" - "log" - "os" -) - -func main() { - // open "test.jpg" - file, err := os.Open("test.jpg") - if err != nil { - log.Fatal(err) - } - - // decode jpeg into image.Image - img, err := jpeg.Decode(file) - if err != nil { - log.Fatal(err) - } - file.Close() - - // resize to width 1000 using Lanczos resampling - // and preserve aspect ratio - m := resize.Resize(1000, 0, img, resize.Lanczos3) - - out, err := os.Create("test_resized.jpg") - if err != nil { - log.Fatal(err) - } - defer out.Close() - - // write new image to file - jpeg.Encode(out, m, nil) -} -``` - -Caveats -------- - -* Optimized access routines are used for `image.RGBA`, `image.NRGBA`, `image.RGBA64`, `image.NRGBA64`, `image.YCbCr`, `image.Gray`, and `image.Gray16` types. All other image types are accessed in a generic way that will result in slow processing speed. -* JPEG images are stored in `image.YCbCr`. This image format stores data in a way that will decrease processing speed. A resize may be up to 2 times slower than with `image.RGBA`. - - -Downsizing Samples -------- - -Downsizing is not as simple as it might look like. Images have to be filtered before they are scaled down, otherwise aliasing might occur. -Filtering is highly subjective: Applying too much will blur the whole image, too little will make aliasing become apparent. -Resize tries to provide sane defaults that should suffice in most cases. - -### Artificial sample - -Original image -![Rings](http://nfnt.github.com/img/rings_lg_orig.png) - - - - - - - - - - - - - - -

Nearest-Neighbor

Bilinear

Bicubic

Mitchell-Netravali

Lanczos2

Lanczos3
- -### Real-Life sample - -Original image -![Original](http://nfnt.github.com/img/IMG_3694_720.jpg) - - - - - - - - - - - - - - -

Nearest-Neighbor

Bilinear

Bicubic

Mitchell-Netravali

Lanczos2

Lanczos3
- - -License -------- - -Copyright (c) 2012 Jan Schlicht -Resize is released under a MIT style license. diff --git a/vendor/github.com/nfnt/resize/converter.go b/vendor/github.com/nfnt/resize/converter.go deleted file mode 100644 index f9c520d097..0000000000 --- a/vendor/github.com/nfnt/resize/converter.go +++ /dev/null @@ -1,438 +0,0 @@ -/* -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import "image" - -// Keep value in [0,255] range. -func clampUint8(in int32) uint8 { - // casting a negative int to an uint will result in an overflown - // large uint. this behavior will be exploited here and in other functions - // to achieve a higher performance. - if uint32(in) < 256 { - return uint8(in) - } - if in > 255 { - return 255 - } - return 0 -} - -// Keep value in [0,65535] range. -func clampUint16(in int64) uint16 { - if uint64(in) < 65536 { - return uint16(in) - } - if in > 65535 { - return 65535 - } - return 0 -} - -func resizeGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int64 - var sum int64 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case xi < 0: - xi = 0 - case xi >= maxX: - xi = maxX - } - - r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA() - - rgba[0] += int64(coeff) * int64(r) - rgba[1] += int64(coeff) * int64(g) - rgba[2] += int64(coeff) * int64(b) - rgba[3] += int64(coeff) * int64(a) - sum += int64(coeff) - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - - value := clampUint16(rgba[0] / sum) - out.Pix[offset+0] = uint8(value >> 8) - out.Pix[offset+1] = uint8(value) - value = clampUint16(rgba[1] / sum) - out.Pix[offset+2] = uint8(value >> 8) - out.Pix[offset+3] = uint8(value) - value = clampUint16(rgba[2] / sum) - out.Pix[offset+4] = uint8(value >> 8) - out.Pix[offset+5] = uint8(value) - value = clampUint16(rgba[3] / sum) - out.Pix[offset+6] = uint8(value >> 8) - out.Pix[offset+7] = uint8(value) - } - } -} - -func resizeRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []int16, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int32 - var sum int32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 4 - case xi >= maxX: - xi = 4 * maxX - default: - xi = 0 - } - - rgba[0] += int32(coeff) * int32(row[xi+0]) - rgba[1] += int32(coeff) * int32(row[xi+1]) - rgba[2] += int32(coeff) * int32(row[xi+2]) - rgba[3] += int32(coeff) * int32(row[xi+3]) - sum += int32(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - - out.Pix[xo+0] = clampUint8(rgba[0] / sum) - out.Pix[xo+1] = clampUint8(rgba[1] / sum) - out.Pix[xo+2] = clampUint8(rgba[2] / sum) - out.Pix[xo+3] = clampUint8(rgba[3] / sum) - } - } -} - -func resizeNRGBA(in *image.NRGBA, out *image.RGBA, scale float64, coeffs []int16, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int32 - var sum int32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 4 - case xi >= maxX: - xi = 4 * maxX - default: - xi = 0 - } - - // Forward alpha-premultiplication - a := int32(row[xi+3]) - r := int32(row[xi+0]) * a - r /= 0xff - g := int32(row[xi+1]) * a - g /= 0xff - b := int32(row[xi+2]) * a - b /= 0xff - - rgba[0] += int32(coeff) * r - rgba[1] += int32(coeff) * g - rgba[2] += int32(coeff) * b - rgba[3] += int32(coeff) * a - sum += int32(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - - out.Pix[xo+0] = clampUint8(rgba[0] / sum) - out.Pix[xo+1] = clampUint8(rgba[1] / sum) - out.Pix[xo+2] = clampUint8(rgba[2] / sum) - out.Pix[xo+3] = clampUint8(rgba[3] / sum) - } - } -} - -func resizeRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int64 - var sum int64 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 8 - case xi >= maxX: - xi = 8 * maxX - default: - xi = 0 - } - - rgba[0] += int64(coeff) * (int64(row[xi+0])<<8 | int64(row[xi+1])) - rgba[1] += int64(coeff) * (int64(row[xi+2])<<8 | int64(row[xi+3])) - rgba[2] += int64(coeff) * (int64(row[xi+4])<<8 | int64(row[xi+5])) - rgba[3] += int64(coeff) * (int64(row[xi+6])<<8 | int64(row[xi+7])) - sum += int64(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - - value := clampUint16(rgba[0] / sum) - out.Pix[xo+0] = uint8(value >> 8) - out.Pix[xo+1] = uint8(value) - value = clampUint16(rgba[1] / sum) - out.Pix[xo+2] = uint8(value >> 8) - out.Pix[xo+3] = uint8(value) - value = clampUint16(rgba[2] / sum) - out.Pix[xo+4] = uint8(value >> 8) - out.Pix[xo+5] = uint8(value) - value = clampUint16(rgba[3] / sum) - out.Pix[xo+6] = uint8(value >> 8) - out.Pix[xo+7] = uint8(value) - } - } -} - -func resizeNRGBA64(in *image.NRGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int64 - var sum int64 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 8 - case xi >= maxX: - xi = 8 * maxX - default: - xi = 0 - } - - // Forward alpha-premultiplication - a := int64(uint16(row[xi+6])<<8 | uint16(row[xi+7])) - r := int64(uint16(row[xi+0])<<8|uint16(row[xi+1])) * a - r /= 0xffff - g := int64(uint16(row[xi+2])<<8|uint16(row[xi+3])) * a - g /= 0xffff - b := int64(uint16(row[xi+4])<<8|uint16(row[xi+5])) * a - b /= 0xffff - - rgba[0] += int64(coeff) * r - rgba[1] += int64(coeff) * g - rgba[2] += int64(coeff) * b - rgba[3] += int64(coeff) * a - sum += int64(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - - value := clampUint16(rgba[0] / sum) - out.Pix[xo+0] = uint8(value >> 8) - out.Pix[xo+1] = uint8(value) - value = clampUint16(rgba[1] / sum) - out.Pix[xo+2] = uint8(value >> 8) - out.Pix[xo+3] = uint8(value) - value = clampUint16(rgba[2] / sum) - out.Pix[xo+4] = uint8(value >> 8) - out.Pix[xo+5] = uint8(value) - value = clampUint16(rgba[3] / sum) - out.Pix[xo+6] = uint8(value >> 8) - out.Pix[xo+7] = uint8(value) - } - } -} - -func resizeGray(in *image.Gray, out *image.Gray, scale float64, coeffs []int16, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[(x-newBounds.Min.X)*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var gray int32 - var sum int32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case xi < 0: - xi = 0 - case xi >= maxX: - xi = maxX - } - gray += int32(coeff) * int32(row[xi]) - sum += int32(coeff) - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x - newBounds.Min.X) - out.Pix[offset] = clampUint8(gray / sum) - } - } -} - -func resizeGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []int32, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var gray int64 - var sum int64 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 2 - case xi >= maxX: - xi = 2 * maxX - default: - xi = 0 - } - gray += int64(coeff) * int64(uint16(row[xi+0])<<8|uint16(row[xi+1])) - sum += int64(coeff) - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*2 - value := clampUint16(gray / sum) - out.Pix[offset+0] = uint8(value >> 8) - out.Pix[offset+1] = uint8(value) - } - } -} - -func resizeYCbCr(in *ycc, out *ycc, scale float64, coeffs []int16, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var p [3]int32 - var sum int32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 3 - case xi >= maxX: - xi = 3 * maxX - default: - xi = 0 - } - p[0] += int32(coeff) * int32(row[xi+0]) - p[1] += int32(coeff) * int32(row[xi+1]) - p[2] += int32(coeff) * int32(row[xi+2]) - sum += int32(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*3 - out.Pix[xo+0] = clampUint8(p[0] / sum) - out.Pix[xo+1] = clampUint8(p[1] / sum) - out.Pix[xo+2] = clampUint8(p[2] / sum) - } - } -} - -func nearestYCbCr(in *ycc, out *ycc, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var p [3]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 3 - case xi >= maxX: - xi = 3 * maxX - default: - xi = 0 - } - p[0] += float32(row[xi+0]) - p[1] += float32(row[xi+1]) - p[2] += float32(row[xi+2]) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*3 - out.Pix[xo+0] = floatToUint8(p[0] / sum) - out.Pix[xo+1] = floatToUint8(p[1] / sum) - out.Pix[xo+2] = floatToUint8(p[2] / sum) - } - } -} diff --git a/vendor/github.com/nfnt/resize/filters.go b/vendor/github.com/nfnt/resize/filters.go deleted file mode 100644 index 4ce04e389f..0000000000 --- a/vendor/github.com/nfnt/resize/filters.go +++ /dev/null @@ -1,143 +0,0 @@ -/* -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import ( - "math" -) - -func nearest(in float64) float64 { - if in >= -0.5 && in < 0.5 { - return 1 - } - return 0 -} - -func linear(in float64) float64 { - in = math.Abs(in) - if in <= 1 { - return 1 - in - } - return 0 -} - -func cubic(in float64) float64 { - in = math.Abs(in) - if in <= 1 { - return in*in*(1.5*in-2.5) + 1.0 - } - if in <= 2 { - return in*(in*(2.5-0.5*in)-4.0) + 2.0 - } - return 0 -} - -func mitchellnetravali(in float64) float64 { - in = math.Abs(in) - if in <= 1 { - return (7.0*in*in*in - 12.0*in*in + 5.33333333333) * 0.16666666666 - } - if in <= 2 { - return (-2.33333333333*in*in*in + 12.0*in*in - 20.0*in + 10.6666666667) * 0.16666666666 - } - return 0 -} - -func sinc(x float64) float64 { - x = math.Abs(x) * math.Pi - if x >= 1.220703e-4 { - return math.Sin(x) / x - } - return 1 -} - -func lanczos2(in float64) float64 { - if in > -2 && in < 2 { - return sinc(in) * sinc(in*0.5) - } - return 0 -} - -func lanczos3(in float64) float64 { - if in > -3 && in < 3 { - return sinc(in) * sinc(in*0.3333333333333333) - } - return 0 -} - -// range [-256,256] -func createWeights8(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int16, []int, int) { - filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1)) - filterFactor := math.Min(1./(blur*scale), 1) - - coeffs := make([]int16, dy*filterLength) - start := make([]int, dy) - for y := 0; y < dy; y++ { - interpX := scale*(float64(y)+0.5) - 0.5 - start[y] = int(interpX) - filterLength/2 + 1 - interpX -= float64(start[y]) - for i := 0; i < filterLength; i++ { - in := (interpX - float64(i)) * filterFactor - coeffs[y*filterLength+i] = int16(kernel(in) * 256) - } - } - - return coeffs, start, filterLength -} - -// range [-65536,65536] -func createWeights16(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int32, []int, int) { - filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1)) - filterFactor := math.Min(1./(blur*scale), 1) - - coeffs := make([]int32, dy*filterLength) - start := make([]int, dy) - for y := 0; y < dy; y++ { - interpX := scale*(float64(y)+0.5) - 0.5 - start[y] = int(interpX) - filterLength/2 + 1 - interpX -= float64(start[y]) - for i := 0; i < filterLength; i++ { - in := (interpX - float64(i)) * filterFactor - coeffs[y*filterLength+i] = int32(kernel(in) * 65536) - } - } - - return coeffs, start, filterLength -} - -func createWeightsNearest(dy, filterLength int, blur, scale float64) ([]bool, []int, int) { - filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1)) - filterFactor := math.Min(1./(blur*scale), 1) - - coeffs := make([]bool, dy*filterLength) - start := make([]int, dy) - for y := 0; y < dy; y++ { - interpX := scale*(float64(y)+0.5) - 0.5 - start[y] = int(interpX) - filterLength/2 + 1 - interpX -= float64(start[y]) - for i := 0; i < filterLength; i++ { - in := (interpX - float64(i)) * filterFactor - if in >= -0.5 && in < 0.5 { - coeffs[y*filterLength+i] = true - } else { - coeffs[y*filterLength+i] = false - } - } - } - - return coeffs, start, filterLength -} diff --git a/vendor/github.com/nfnt/resize/nearest.go b/vendor/github.com/nfnt/resize/nearest.go deleted file mode 100644 index 888039d852..0000000000 --- a/vendor/github.com/nfnt/resize/nearest.go +++ /dev/null @@ -1,318 +0,0 @@ -/* -Copyright (c) 2014, Charlie Vieth - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import "image" - -func floatToUint8(x float32) uint8 { - // Nearest-neighbor values are always - // positive no need to check lower-bound. - if x > 0xfe { - return 0xff - } - return uint8(x) -} - -func floatToUint16(x float32) uint16 { - if x > 0xfffe { - return 0xffff - } - return uint16(x) -} - -func nearestGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case xi < 0: - xi = 0 - case xi >= maxX: - xi = maxX - } - r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA() - rgba[0] += float32(r) - rgba[1] += float32(g) - rgba[2] += float32(b) - rgba[3] += float32(a) - sum++ - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - value := floatToUint16(rgba[0] / sum) - out.Pix[offset+0] = uint8(value >> 8) - out.Pix[offset+1] = uint8(value) - value = floatToUint16(rgba[1] / sum) - out.Pix[offset+2] = uint8(value >> 8) - out.Pix[offset+3] = uint8(value) - value = floatToUint16(rgba[2] / sum) - out.Pix[offset+4] = uint8(value >> 8) - out.Pix[offset+5] = uint8(value) - value = floatToUint16(rgba[3] / sum) - out.Pix[offset+6] = uint8(value >> 8) - out.Pix[offset+7] = uint8(value) - } - } -} - -func nearestRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 4 - case xi >= maxX: - xi = 4 * maxX - default: - xi = 0 - } - rgba[0] += float32(row[xi+0]) - rgba[1] += float32(row[xi+1]) - rgba[2] += float32(row[xi+2]) - rgba[3] += float32(row[xi+3]) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - out.Pix[xo+0] = floatToUint8(rgba[0] / sum) - out.Pix[xo+1] = floatToUint8(rgba[1] / sum) - out.Pix[xo+2] = floatToUint8(rgba[2] / sum) - out.Pix[xo+3] = floatToUint8(rgba[3] / sum) - } - } -} - -func nearestNRGBA(in *image.NRGBA, out *image.NRGBA, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 4 - case xi >= maxX: - xi = 4 * maxX - default: - xi = 0 - } - rgba[0] += float32(row[xi+0]) - rgba[1] += float32(row[xi+1]) - rgba[2] += float32(row[xi+2]) - rgba[3] += float32(row[xi+3]) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - out.Pix[xo+0] = floatToUint8(rgba[0] / sum) - out.Pix[xo+1] = floatToUint8(rgba[1] / sum) - out.Pix[xo+2] = floatToUint8(rgba[2] / sum) - out.Pix[xo+3] = floatToUint8(rgba[3] / sum) - } - } -} - -func nearestRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 8 - case xi >= maxX: - xi = 8 * maxX - default: - xi = 0 - } - rgba[0] += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) - rgba[1] += float32(uint16(row[xi+2])<<8 | uint16(row[xi+3])) - rgba[2] += float32(uint16(row[xi+4])<<8 | uint16(row[xi+5])) - rgba[3] += float32(uint16(row[xi+6])<<8 | uint16(row[xi+7])) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - value := floatToUint16(rgba[0] / sum) - out.Pix[xo+0] = uint8(value >> 8) - out.Pix[xo+1] = uint8(value) - value = floatToUint16(rgba[1] / sum) - out.Pix[xo+2] = uint8(value >> 8) - out.Pix[xo+3] = uint8(value) - value = floatToUint16(rgba[2] / sum) - out.Pix[xo+4] = uint8(value >> 8) - out.Pix[xo+5] = uint8(value) - value = floatToUint16(rgba[3] / sum) - out.Pix[xo+6] = uint8(value >> 8) - out.Pix[xo+7] = uint8(value) - } - } -} - -func nearestNRGBA64(in *image.NRGBA64, out *image.NRGBA64, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 8 - case xi >= maxX: - xi = 8 * maxX - default: - xi = 0 - } - rgba[0] += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) - rgba[1] += float32(uint16(row[xi+2])<<8 | uint16(row[xi+3])) - rgba[2] += float32(uint16(row[xi+4])<<8 | uint16(row[xi+5])) - rgba[3] += float32(uint16(row[xi+6])<<8 | uint16(row[xi+7])) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - value := floatToUint16(rgba[0] / sum) - out.Pix[xo+0] = uint8(value >> 8) - out.Pix[xo+1] = uint8(value) - value = floatToUint16(rgba[1] / sum) - out.Pix[xo+2] = uint8(value >> 8) - out.Pix[xo+3] = uint8(value) - value = floatToUint16(rgba[2] / sum) - out.Pix[xo+4] = uint8(value >> 8) - out.Pix[xo+5] = uint8(value) - value = floatToUint16(rgba[3] / sum) - out.Pix[xo+6] = uint8(value >> 8) - out.Pix[xo+7] = uint8(value) - } - } -} - -func nearestGray(in *image.Gray, out *image.Gray, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var gray float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case xi < 0: - xi = 0 - case xi >= maxX: - xi = maxX - } - gray += float32(row[xi]) - sum++ - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x - newBounds.Min.X) - out.Pix[offset] = floatToUint8(gray / sum) - } - } -} - -func nearestGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var gray float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 2 - case xi >= maxX: - xi = 2 * maxX - default: - xi = 0 - } - gray += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) - sum++ - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*2 - value := floatToUint16(gray / sum) - out.Pix[offset+0] = uint8(value >> 8) - out.Pix[offset+1] = uint8(value) - } - } -} diff --git a/vendor/github.com/nfnt/resize/resize.go b/vendor/github.com/nfnt/resize/resize.go deleted file mode 100644 index 57bd1fcd03..0000000000 --- a/vendor/github.com/nfnt/resize/resize.go +++ /dev/null @@ -1,614 +0,0 @@ -/* -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -// Package resize implements various image resizing methods. -// -// The package works with the Image interface described in the image package. -// Various interpolation methods are provided and multiple processors may be -// utilized in the computations. -// -// Example: -// imgResized := resize.Resize(1000, 0, imgOld, resize.MitchellNetravali) -package resize - -import ( - "image" - "runtime" - "sync" -) - -// An InterpolationFunction provides the parameters that describe an -// interpolation kernel. It returns the number of samples to take -// and the kernel function to use for sampling. -type InterpolationFunction int - -// InterpolationFunction constants -const ( - // Nearest-neighbor interpolation - NearestNeighbor InterpolationFunction = iota - // Bilinear interpolation - Bilinear - // Bicubic interpolation (with cubic hermite spline) - Bicubic - // Mitchell-Netravali interpolation - MitchellNetravali - // Lanczos interpolation (a=2) - Lanczos2 - // Lanczos interpolation (a=3) - Lanczos3 -) - -// kernal, returns an InterpolationFunctions taps and kernel. -func (i InterpolationFunction) kernel() (int, func(float64) float64) { - switch i { - case Bilinear: - return 2, linear - case Bicubic: - return 4, cubic - case MitchellNetravali: - return 4, mitchellnetravali - case Lanczos2: - return 4, lanczos2 - case Lanczos3: - return 6, lanczos3 - default: - // Default to NearestNeighbor. - return 2, nearest - } -} - -// values <1 will sharpen the image -var blur = 1.0 - -// Resize scales an image to new width and height using the interpolation function interp. -// A new image with the given dimensions will be returned. -// If one of the parameters width or height is set to 0, its size will be calculated so that -// the aspect ratio is that of the originating image. -// The resizing algorithm uses channels for parallel computation. -func Resize(width, height uint, img image.Image, interp InterpolationFunction) image.Image { - scaleX, scaleY := calcFactors(width, height, float64(img.Bounds().Dx()), float64(img.Bounds().Dy())) - if width == 0 { - width = uint(0.7 + float64(img.Bounds().Dx())/scaleX) - } - if height == 0 { - height = uint(0.7 + float64(img.Bounds().Dy())/scaleY) - } - - // Trivial case: return input image - if int(width) == img.Bounds().Dx() && int(height) == img.Bounds().Dy() { - return img - } - - if interp == NearestNeighbor { - return resizeNearest(width, height, scaleX, scaleY, img, interp) - } - - taps, kernel := interp.kernel() - cpus := runtime.GOMAXPROCS(0) - wg := sync.WaitGroup{} - - // Generic access to image.Image is slow in tight loops. - // The optimal access has to be determined from the concrete image type. - switch input := img.(type) { - case *image.RGBA: - // 8-bit precision - temp := image.NewRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewRGBA(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA) - go func() { - defer wg.Done() - resizeRGBA(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA) - go func() { - defer wg.Done() - resizeRGBA(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.NRGBA: - // 8-bit precision - temp := image.NewRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewRGBA(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA) - go func() { - defer wg.Done() - resizeNRGBA(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA) - go func() { - defer wg.Done() - resizeRGBA(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - - case *image.YCbCr: - // 8-bit precision - // accessing the YCbCr arrays in a tight loop is slow. - // converting the image to ycc increases performance by 2x. - temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio) - result := newYCC(image.Rect(0, 0, int(width), int(height)), image.YCbCrSubsampleRatio444) - - coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - in := imageYCbCrToYCC(input) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*ycc) - go func() { - defer wg.Done() - resizeYCbCr(in, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*ycc) - go func() { - defer wg.Done() - resizeYCbCr(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result.YCbCr() - case *image.RGBA64: - // 16-bit precision - temp := image.NewRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - resizeRGBA64(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - resizeRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.NRGBA64: - // 16-bit precision - temp := image.NewRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - resizeNRGBA64(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - resizeRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.Gray: - // 8-bit precision - temp := image.NewGray(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewGray(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.Gray) - go func() { - defer wg.Done() - resizeGray(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.Gray) - go func() { - defer wg.Done() - resizeGray(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.Gray16: - // 16-bit precision - temp := image.NewGray16(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewGray16(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.Gray16) - go func() { - defer wg.Done() - resizeGray16(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.Gray16) - go func() { - defer wg.Done() - resizeGray16(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - default: - // 16-bit precision - temp := image.NewRGBA64(image.Rect(0, 0, img.Bounds().Dy(), int(width))) - result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - resizeGeneric(img, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - resizeRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - } -} - -func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image, interp InterpolationFunction) image.Image { - taps, _ := interp.kernel() - cpus := runtime.GOMAXPROCS(0) - wg := sync.WaitGroup{} - - switch input := img.(type) { - case *image.RGBA: - // 8-bit precision - temp := image.NewRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewRGBA(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA) - go func() { - defer wg.Done() - nearestRGBA(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA) - go func() { - defer wg.Done() - nearestRGBA(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.NRGBA: - // 8-bit precision - temp := image.NewNRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA) - go func() { - defer wg.Done() - nearestNRGBA(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.NRGBA) - go func() { - defer wg.Done() - nearestNRGBA(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.YCbCr: - // 8-bit precision - // accessing the YCbCr arrays in a tight loop is slow. - // converting the image to ycc increases performance by 2x. - temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio) - result := newYCC(image.Rect(0, 0, int(width), int(height)), image.YCbCrSubsampleRatio444) - - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - in := imageYCbCrToYCC(input) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*ycc) - go func() { - defer wg.Done() - nearestYCbCr(in, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*ycc) - go func() { - defer wg.Done() - nearestYCbCr(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result.YCbCr() - case *image.RGBA64: - // 16-bit precision - temp := image.NewRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - nearestRGBA64(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - nearestRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.NRGBA64: - // 16-bit precision - temp := image.NewNRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - nearestNRGBA64(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - nearestNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.Gray: - // 8-bit precision - temp := image.NewGray(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewGray(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.Gray) - go func() { - defer wg.Done() - nearestGray(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.Gray) - go func() { - defer wg.Done() - nearestGray(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.Gray16: - // 16-bit precision - temp := image.NewGray16(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewGray16(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.Gray16) - go func() { - defer wg.Done() - nearestGray16(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.Gray16) - go func() { - defer wg.Done() - nearestGray16(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - default: - // 16-bit precision - temp := image.NewRGBA64(image.Rect(0, 0, img.Bounds().Dy(), int(width))) - result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - nearestGeneric(img, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - nearestRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - } - -} - -// Calculates scaling factors using old and new image dimensions. -func calcFactors(width, height uint, oldWidth, oldHeight float64) (scaleX, scaleY float64) { - if width == 0 { - if height == 0 { - scaleX = 1.0 - scaleY = 1.0 - } else { - scaleY = oldHeight / float64(height) - scaleX = scaleY - } - } else { - scaleX = oldWidth / float64(width) - if height == 0 { - scaleY = scaleX - } else { - scaleY = oldHeight / float64(height) - } - } - return -} - -type imageWithSubImage interface { - image.Image - SubImage(image.Rectangle) image.Image -} - -func makeSlice(img imageWithSubImage, i, n int) image.Image { - return img.SubImage(image.Rect(img.Bounds().Min.X, img.Bounds().Min.Y+i*img.Bounds().Dy()/n, img.Bounds().Max.X, img.Bounds().Min.Y+(i+1)*img.Bounds().Dy()/n)) -} diff --git a/vendor/github.com/nfnt/resize/thumbnail.go b/vendor/github.com/nfnt/resize/thumbnail.go deleted file mode 100644 index 9efc246bee..0000000000 --- a/vendor/github.com/nfnt/resize/thumbnail.go +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import ( - "image" -) - -// Thumbnail will downscale provided image to max width and height preserving -// original aspect ratio and using the interpolation function interp. -// It will return original image, without processing it, if original sizes -// are already smaller than provided constraints. -func Thumbnail(maxWidth, maxHeight uint, img image.Image, interp InterpolationFunction) image.Image { - origBounds := img.Bounds() - origWidth := uint(origBounds.Dx()) - origHeight := uint(origBounds.Dy()) - newWidth, newHeight := origWidth, origHeight - - // Return original image if it have same or smaller size as constraints - if maxWidth >= origWidth && maxHeight >= origHeight { - return img - } - - // Preserve aspect ratio - if origWidth > maxWidth { - newHeight = uint(origHeight * maxWidth / origWidth) - if newHeight < 1 { - newHeight = 1 - } - newWidth = maxWidth - } - - if newHeight > maxHeight { - newWidth = uint(newWidth * maxHeight / newHeight) - if newWidth < 1 { - newWidth = 1 - } - newHeight = maxHeight - } - return Resize(newWidth, newHeight, img, interp) -} diff --git a/vendor/github.com/nfnt/resize/ycc.go b/vendor/github.com/nfnt/resize/ycc.go deleted file mode 100644 index 104159955e..0000000000 --- a/vendor/github.com/nfnt/resize/ycc.go +++ /dev/null @@ -1,227 +0,0 @@ -/* -Copyright (c) 2014, Charlie Vieth - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import ( - "image" - "image/color" -) - -// ycc is an in memory YCbCr image. The Y, Cb and Cr samples are held in a -// single slice to increase resizing performance. -type ycc struct { - // Pix holds the image's pixels, in Y, Cb, Cr order. The pixel at - // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*3]. - Pix []uint8 - // Stride is the Pix stride (in bytes) between vertically adjacent pixels. - Stride int - // Rect is the image's bounds. - Rect image.Rectangle - // SubsampleRatio is the subsample ratio of the original YCbCr image. - SubsampleRatio image.YCbCrSubsampleRatio -} - -// PixOffset returns the index of the first element of Pix that corresponds to -// the pixel at (x, y). -func (p *ycc) PixOffset(x, y int) int { - return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*3 -} - -func (p *ycc) Bounds() image.Rectangle { - return p.Rect -} - -func (p *ycc) ColorModel() color.Model { - return color.YCbCrModel -} - -func (p *ycc) At(x, y int) color.Color { - if !(image.Point{x, y}.In(p.Rect)) { - return color.YCbCr{} - } - i := p.PixOffset(x, y) - return color.YCbCr{ - p.Pix[i+0], - p.Pix[i+1], - p.Pix[i+2], - } -} - -func (p *ycc) Opaque() bool { - return true -} - -// SubImage returns an image representing the portion of the image p visible -// through r. The returned value shares pixels with the original image. -func (p *ycc) SubImage(r image.Rectangle) image.Image { - r = r.Intersect(p.Rect) - if r.Empty() { - return &ycc{SubsampleRatio: p.SubsampleRatio} - } - i := p.PixOffset(r.Min.X, r.Min.Y) - return &ycc{ - Pix: p.Pix[i:], - Stride: p.Stride, - Rect: r, - SubsampleRatio: p.SubsampleRatio, - } -} - -// newYCC returns a new ycc with the given bounds and subsample ratio. -func newYCC(r image.Rectangle, s image.YCbCrSubsampleRatio) *ycc { - w, h := r.Dx(), r.Dy() - buf := make([]uint8, 3*w*h) - return &ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: s} -} - -// YCbCr converts ycc to a YCbCr image with the same subsample ratio -// as the YCbCr image that ycc was generated from. -func (p *ycc) YCbCr() *image.YCbCr { - ycbcr := image.NewYCbCr(p.Rect, p.SubsampleRatio) - var off int - - switch ycbcr.SubsampleRatio { - case image.YCbCrSubsampleRatio422: - for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { - yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride - cy := (y - ycbcr.Rect.Min.Y) * ycbcr.CStride - for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { - xx := (x - ycbcr.Rect.Min.X) - yi := yy + xx - ci := cy + xx/2 - ycbcr.Y[yi] = p.Pix[off+0] - ycbcr.Cb[ci] = p.Pix[off+1] - ycbcr.Cr[ci] = p.Pix[off+2] - off += 3 - } - } - case image.YCbCrSubsampleRatio420: - for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { - yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride - cy := (y/2 - ycbcr.Rect.Min.Y/2) * ycbcr.CStride - for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { - xx := (x - ycbcr.Rect.Min.X) - yi := yy + xx - ci := cy + xx/2 - ycbcr.Y[yi] = p.Pix[off+0] - ycbcr.Cb[ci] = p.Pix[off+1] - ycbcr.Cr[ci] = p.Pix[off+2] - off += 3 - } - } - case image.YCbCrSubsampleRatio440: - for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { - yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride - cy := (y/2 - ycbcr.Rect.Min.Y/2) * ycbcr.CStride - for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { - xx := (x - ycbcr.Rect.Min.X) - yi := yy + xx - ci := cy + xx - ycbcr.Y[yi] = p.Pix[off+0] - ycbcr.Cb[ci] = p.Pix[off+1] - ycbcr.Cr[ci] = p.Pix[off+2] - off += 3 - } - } - default: - // Default to 4:4:4 subsampling. - for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { - yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride - cy := (y - ycbcr.Rect.Min.Y) * ycbcr.CStride - for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { - xx := (x - ycbcr.Rect.Min.X) - yi := yy + xx - ci := cy + xx - ycbcr.Y[yi] = p.Pix[off+0] - ycbcr.Cb[ci] = p.Pix[off+1] - ycbcr.Cr[ci] = p.Pix[off+2] - off += 3 - } - } - } - return ycbcr -} - -// imageYCbCrToYCC converts a YCbCr image to a ycc image for resizing. -func imageYCbCrToYCC(in *image.YCbCr) *ycc { - w, h := in.Rect.Dx(), in.Rect.Dy() - r := image.Rect(0, 0, w, h) - buf := make([]uint8, 3*w*h) - p := ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: in.SubsampleRatio} - var off int - - switch in.SubsampleRatio { - case image.YCbCrSubsampleRatio422: - for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { - yy := (y - in.Rect.Min.Y) * in.YStride - cy := (y - in.Rect.Min.Y) * in.CStride - for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { - xx := (x - in.Rect.Min.X) - yi := yy + xx - ci := cy + xx/2 - p.Pix[off+0] = in.Y[yi] - p.Pix[off+1] = in.Cb[ci] - p.Pix[off+2] = in.Cr[ci] - off += 3 - } - } - case image.YCbCrSubsampleRatio420: - for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { - yy := (y - in.Rect.Min.Y) * in.YStride - cy := (y/2 - in.Rect.Min.Y/2) * in.CStride - for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { - xx := (x - in.Rect.Min.X) - yi := yy + xx - ci := cy + xx/2 - p.Pix[off+0] = in.Y[yi] - p.Pix[off+1] = in.Cb[ci] - p.Pix[off+2] = in.Cr[ci] - off += 3 - } - } - case image.YCbCrSubsampleRatio440: - for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { - yy := (y - in.Rect.Min.Y) * in.YStride - cy := (y/2 - in.Rect.Min.Y/2) * in.CStride - for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { - xx := (x - in.Rect.Min.X) - yi := yy + xx - ci := cy + xx - p.Pix[off+0] = in.Y[yi] - p.Pix[off+1] = in.Cb[ci] - p.Pix[off+2] = in.Cr[ci] - off += 3 - } - } - default: - // Default to 4:4:4 subsampling. - for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { - yy := (y - in.Rect.Min.Y) * in.YStride - cy := (y - in.Rect.Min.Y) * in.CStride - for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { - xx := (x - in.Rect.Min.X) - yi := yy + xx - ci := cy + xx - p.Pix[off+0] = in.Y[yi] - p.Pix[off+1] = in.Cb[ci] - p.Pix[off+2] = in.Cr[ci] - off += 3 - } - } - } - return &p -} diff --git a/vendor/github.com/phoreproject/go-ethwallet/LICENSE b/vendor/github.com/phoreproject/go-ethwallet/LICENSE new file mode 100644 index 0000000000..54c962577b --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 OpenBazaar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/phoreproject/go-ethwallet/README.md b/vendor/github.com/phoreproject/go-ethwallet/README.md new file mode 100644 index 0000000000..7be8073cf1 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/README.md @@ -0,0 +1,28 @@ +# go-ethwallet +![banner](https://i.imgur.com/iOnXDXK.png) +OpenBazaar Ethereum Wallet in Go + +[![Build Status](https://travis-ci.org/phoreproject/go-ethwallet.svg?branch=master)](https://travis-ci.org/phoreproject/go-ethwallet) +[![Coverage Status](https://coveralls.io/repos/github/phoreproject/go-ethwallet/badge.svg?branch=master)](https://coveralls.io/github/phoreproject/go-ethwallet?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/phoreproject/go-ethwallet)](https://goreportcard.com/report/github.com/phoreproject/go-ethwallet) + + +This is an Ethereum wallet implementation which uses the Infura API. + +Your Infura API key is required as an environment variable. Refer to the +env-sample for adding a `.env` file to the project root. + +To use this, you need to have an existing Ethereum JSON keystore. + +There is an option of creating one but it has not been integrated yet. + +To execute the wallet: + +>$ go run cmd/main.go -p < wallet_password > -f < path-to-keystore-file > + +eg: + +>$ go run cmd/main.go -p odetojoy -f ./UTC--2018-06-16T18-41-19.615987160Z--c0b4ef9e6d2806f643be94b2434f5c3d6cecd255 + +Where the wallet password is odetojoy and the keystore file is in the same directory +as the code. \ No newline at end of file diff --git a/vendor/github.com/phoreproject/go-ethwallet/abi/PaymentProtectionv2.abi b/vendor/github.com/phoreproject/go-ethwallet/abi/PaymentProtectionv2.abi new file mode 100644 index 0000000000..cc81180361 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/abi/PaymentProtectionv2.abi @@ -0,0 +1,4 @@ +[{"constant":false,"inputs":[{"name":"scriptHash","type":"bytes32"}],"name":"addFundsToTransaction","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"transactions","outputs":[{"name":"scriptHash","type":"bytes32"},{"name":"buyer","type":"address"},{"name":"seller","type":"address"},{"name":"value","type":"uint256"},{"name":"status","type":"uint8"},{"name":"ipfsHash","type":"string"},{"name":"lastFunded","type":"uint256"},{"name":"timeoutHours","type":"uint32"},{"name":"threshold","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"transactionCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_buyer","type":"address"},{"name":"_seller","type":"address"},{"name":"_moderators","type":"address[]"},{"name":"threshold","type":"uint8"},{"name":"timeoutHours","type":"uint32"},{"name":"scriptHash","type":"bytes32"}],"name":"addTransaction","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_partyAddress","type":"address"}],"name":"getAllTransactionsForParty","outputs":[{"name":"scriptHashes","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sigV","type":"uint8[]"},{"name":"sigR","type":"bytes32[]"},{"name":"sigS","type":"bytes32[]"},{"name":"scriptHash","type":"bytes32"},{"name":"uniqueId","type":"bytes20"},{"name":"destinations","type":"address[]"},{"name":"amounts","type":"uint256[]"}],"name":"execute","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"scriptHash","type":"bytes32"},{"indexed":false,"name":"destinations","type":"address[]"},{"indexed":false,"name":"amounts","type":"uint256[]"}],"name":"Executed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"scriptHash","type":"bytes32"},{"indexed":true,"name":"from","type":"address"},{"indexed":false,"name":"valueAdded","type":"uint256"}],"name":"FundAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"scriptHash","type":"bytes32"},{"indexed":true,"name":"from","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Funded","type":"event"}] + +======= openzeppelin-solidity/contracts/math/SafeMath.sol:SafeMath ======= +[] diff --git a/vendor/github.com/phoreproject/go-ethwallet/abi/PaymentProtectionv2.bin b/vendor/github.com/phoreproject/go-ethwallet/abi/PaymentProtectionv2.bin new file mode 100644 index 0000000000..226f69fe98 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/abi/PaymentProtectionv2.bin @@ -0,0 +1,4 @@ +6080604052600060015534801561001557600080fd5b5061219d806100256000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632d9ef96e1461007d578063642f2eaf146100a1578063b77bf60014610203578063b8310cac1461022e578063be84ceaf146102f2578063c8331de61461038a575b600080fd5b61009f6004803603810190808035600019169060200190929190505050610523565b005b3480156100ad57600080fd5b506100d0600480360381019080803560001916906020019092919050505061071b565b604051808a600019166000191681526020018973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200186600181111561015857fe5b60ff168152602001806020018581526020018463ffffffff1663ffffffff1681526020018360ff1660ff168152602001828103825286818151815260200191508051906020019080838360005b838110156101c05780820151818401526020810190506101a5565b50505050905090810190601f1680156101ed5780820380516001836020036101000a031916815260200191505b509a505050505050505050505060405180910390f35b34801561020f57600080fd5b5061021861086b565b6040518082815260200191505060405180910390f35b6102f0600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803560ff169060200190929190803563ffffffff1690602001909291908035600019169060200190929190505050610871565b005b3480156102fe57600080fd5b50610333600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611076565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561037657808201518184015260208101905061035b565b505050509050019250505060405180910390f35b34801561039657600080fd5b50610521600480360381019080803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803560001916906020019092919080356bffffffffffffffffffffffff191690602001909291908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050611111565b005b60008160008060008360001916600019168152602001908152602001600020600401541415151561055357600080fd5b826000600181111561056157fe5b600080836000191660001916815260200190815260200160002060050160009054906101000a900460ff16600181111561059757fe5b141515610632576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001807f5472616e73616374696f6e2069732065697468657220696e206469737075746581526020017f206f722072656c6561736564207374617465000000000000000000000000000081525060400191505060405180910390fd5b34925060008311151561064457600080fd5b6106748360008087600019166000191681526020019081526020016000206004015461199490919063ffffffff16565b600080866000191660001916815260200190815260200160002060040181905550426000808660001916600019168152602001908152602001600020600701819055503373ffffffffffffffffffffffffffffffffffffffff167ff66fd2ae9e24a6a24b02e1b5b7512ffde5149a4176085fc0298ae228c9b9d72985856040518083600019166000191681526020018281526020019250505060405180910390a250505050565b60006020528060005260406000206000915090508060000154908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060040154908060050160009054906101000a900460ff1690806006018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108325780601f1061080757610100808354040283529160200191610832565b820191906000526020600020905b81548152906001019060200180831161081557829003601f168201915b5050505050908060070154908060080160009054906101000a900463ffffffff16908060080160049054906101000a900460ff16905089565b60015481565b6000808260008060008360001916600019168152602001908152602001600020600401541415156108a157600080fd5b34925060008311151561091c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f56616c756520706173736564206973203000000000000000000000000000000081525060200191505060405180910390fd5b600087511115156109bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f54686572652073686f756c642062652061746c656173742031206d6f6465726181526020017f746f72000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60028751018660ff1611151515610a60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001807f5468726573686f6c642069732067726561746572207468616e20746f74616c2081526020017f6f776e657273000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b61014060405190810160405280856000191681526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff16815260200188815260200184815260200160006001811115610ac857fe5b8152602001602060405190810160405280600081525081526020014281526020018663ffffffff1681526020018760ff1681525060008086600019166000191681526020019081526020016000206000820151816000019060001916905560208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816003019080519060200190610bd0929190611fff565b506080820151816004015560a08201518160050160006101000a81548160ff02191690836001811115610bff57fe5b021790555060c0820151816006019080519060200190610c20929190612089565b5060e082015181600701556101008201518160080160006101000a81548163ffffffff021916908363ffffffff1602179055506101208201518160080160046101000a81548160ff021916908360ff1602179055509050506001600080866000191660001916815260200190815260200160002060090160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600080866000191660001916815260200190815260200160002060090160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b86518260ff161015610f005760008085600019166000191681526020019081526020016000206009016000888460ff16815181101515610d9f57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610e66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f4d6f64657261746f7220697320626569676e207265706561746564000000000081525060200191505060405180910390fd5b600160008086600019166000191681526020019081526020016000206009016000898560ff16815181101515610e9857fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508180600101925050610d63565b600160008154809291906001019190505550600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020849080600181540180825580915050906001820390600052602060002001600090919290919091509060001916905550600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208490806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055503373ffffffffffffffffffffffffffffffffffffffff167fce7089d0668849fb9ca29778c0cbf1e764d9efb048d81fd71fb34c94f26db368600080876000191660001916815260200190815260200160002060000154856040518083600019166000191681526020018281526020019250505060405180910390a2505050505050505050565b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110557602002820191906000526020600020905b815460001916815260200190600101908083116110ed575b50505050509050919050565b6000806000806000808960008060008360001916600019168152602001908152602001600020600401541415151561114857600080fd5b8a6000600181111561115657fe5b600080836000191660001916815260200190815260200160002060050160009054906101000a900460ff16600181111561118c57fe5b141515611227576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001807f5472616e73616374696f6e2069732065697468657220696e206469737075746581526020017f206f722072656c6561736564207374617465000000000000000000000000000081525060400191505060405180910390fd5b60008a51118015611239575088518a51145b151561124457600080fd5b6000808d6000191660001916815260200190815260200160002097508a8860080160049054906101000a900460ff168960080160009054906101000a900463ffffffff168a60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b60020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c60030160008154811015156112e457fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405160200180876bffffffffffffffffffffffff19166bffffffffffffffffffffffff191681526014018660ff1660ff167f01000000000000000000000000000000000000000000000000000000000000000281526001018563ffffffff1663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140196505050505050506040516020818303038152906040526040518082805190602001908083835b6020831015156114a85780518252602082019150602081019050602083039250611483565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020965086600019168c6000191614151561157c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001807f43616c63756c6174656420736372697074206861736820646f6573206e6f742081526020017f6d6174636820706173736564207363726970742068617368000000000000000081525060400191505060405180910390fd5b61158a8f8f8f8f8e8e6119b0565b95506115ae8860080160009054906101000a900463ffffffff168960070154611fb8565b94508760080160049054906101000a900460ff1660ff168f511080156115d2575084155b156115dc57600080fd5b60018f511480156115ea5750845b801561164657508760020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614155b1561165057600080fd5b8760080160049054906101000a900460ff1660ff168f51101561167257600080fd5b60016000808e6000191660001916815260200190815260200160002060050160006101000a81548160ff021916908360018111156116ac57fe5b021790555060009350600092505b89518360ff16101561188657600073ffffffffffffffffffffffffffffffffffffffff168a8460ff168151811015156116ef57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff161415801561179b57506000808d6000191660001916815260200190815260200160002060090160008b8560ff1681518110151561174857fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b15156117a657600080fd5b6000898460ff168151811015156117b957fe5b906020019060200201511115156117cf57600080fd5b6117fc898460ff168151811015156117e357fe5b906020019060200201518561199490919063ffffffff16565b9350898360ff1681518110151561180f57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff166108fc8a8560ff1681518110151561184357fe5b906020019060200201519081150290604051600060405180830381858888f19350505050158015611878573d6000803e3d6000fd5b5082806001019350506116ba565b6000808d600019166000191681526020019081526020016000206004015484111515156118b257600080fd5b7f688e2a1b34445bcd47b0e11ba2a9c8c4d850a1831b64199b59d1c70e297015458c8b8b6040518084600019166000191681526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561192b578082015181840152602081019050611910565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561196d578082015181840152602081019050611952565b505050509050019550505050505060405180910390a1505050505050505050505050505050565b600081830190508281101515156119a757fe5b80905092915050565b600080600080875189511480156119c8575089518951145b15156119d357600080fd5b60197f01000000000000000000000000000000000000000000000000000000000000000260007f0100000000000000000000000000000000000000000000000000000000000000023088888b60405160200180877effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101867effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c01000000000000000000000000028152601401848051906020019060200280838360005b83811015611b27578082015181840152602081019050611b0c565b50505050905001838051906020019060200280838360005b83811015611b5a578082015181840152602081019050611b3f565b50505050905001826000191660001916815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b602083101515611bbb5780518252602082019150602081019050602083039250611b96565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083101515611c6c5780518252602082019150602081019050602083039250611c47565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209250600091505b8851821015611fab576001838b84815181101515611cba57fe5b906020019060200201518b85815181101515611cd257fe5b906020019060200201518b86815181101515611cea57fe5b90602001906020020151604051600081526020016040526040518085600019166000191681526020018460ff1660ff168152602001836000191660001916815260200182600019166000191681526020019450505050506020604051602081039080840390855afa158015611d63573d6000803e3d6000fd5b505050602060405103519050600080886000191660001916815260200190815260200160002060090160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611e4b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b6000808860001916600019168152602001908152602001600020600a0160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515611f28576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f53616d65207369676e61747572652073656e742074776963650000000000000081525060200191505060405180910390fd5b60016000808960001916600019168152602001908152602001600020600a0160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508093508180600101925050611ca0565b5050509695505050505050565b600080611fce8342611fe690919063ffffffff16565b9050610e10840263ffffffff16811191505092915050565b6000828211151515611ff457fe5b818303905092915050565b828054828255906000526020600020908101928215612078579160200282015b828111156120775782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061201f565b5b5090506120859190612109565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106120ca57805160ff19168380011785556120f8565b828001600101855582156120f8579182015b828111156120f75782518255916020019190600101906120dc565b5b509050612105919061214c565b5090565b61214991905b8082111561214557600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555060010161210f565b5090565b90565b61216e91905b8082111561216a576000816000905550600101612152565b5090565b905600a165627a7a7230582028c6a45a5a30ac8978c682848de6ff562f486e5a22b8e9e882164ab016e1f6480029 + +======= openzeppelin-solidity/contracts/math/SafeMath.sol:SafeMath ======= +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a723058201f11c3b9646e4f7d728669bbc871ca0f5ca20db4a8a9ff4bb95c01848b9cc2620029 diff --git a/vendor/github.com/phoreproject/go-ethwallet/cmd/main.go b/vendor/github.com/phoreproject/go-ethwallet/cmd/main.go new file mode 100644 index 0000000000..e706515d27 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/cmd/main.go @@ -0,0 +1,117 @@ +package main + +import ( + "context" + "flag" + "fmt" + "math/big" + "os" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + _ "github.com/joho/godotenv/autoload" + log "github.com/sirupsen/logrus" + + "github.com/phoreproject/go-ethwallet/wallet" +) + +var ( + password string + keyDir string + keyFile string +) + +const ethToWei = 1 << 17 + +// InfuraRopstenBase is the base URL for Infura Ropsten network +const InfuraRopstenBase string = "https://ropsten.infura.io/" + +func init() { + flag.StringVar(&password, "p", "", "password for keystore") + flag.StringVar(&keyDir, "d", "", "key dir to generate key") + flag.StringVar(&keyFile, "f", "", "key file path") +} + +func main() { + fmt.Println(os.Getenv("INFURA_KEY")) + + ropstenURL := InfuraRopstenBase + os.Getenv("INFURA_KEY") + + flag.Parse() + + fmt.Println("Password is : ", password) + fmt.Println("keydir is: ", keyDir) + fmt.Println("keyfile is : ", keyFile) + + client, err := ethclient.Dial("https://mainnet.infura.io") + if err != nil { + log.Fatal(err) + } + fmt.Println("we have a connection") + _ = client + + address := common.HexToAddress("0x71c7656ec7ab88b098defb751b7401b5f6d8976f") + fmt.Println(address.Hex()) + // 0x71C7656EC7ab88b098defB751B7401B5f6d8976F + fmt.Println(address.Hash().Hex()) + // 0x00000000000000000000000071c7656ec7ab88b098defb751b7401b5f6d8976f + fmt.Println(address.Bytes()) + + account := common.HexToAddress("0x71c7656ec7ab88b098defb751b7401b5f6d8976f") + balance, err := client.BalanceAt(context.Background(), account, nil) + if err != nil { + log.Fatal(err) + } + fmt.Println(balance) + + // Get the balance at a particular instance of time expressed as block number + blockNumber := big.NewInt(5532993) + balance, err = client.BalanceAt(context.Background(), account, blockNumber) + if err != nil { + log.Fatal(err) + } + fmt.Println(balance) + + //wallet.GenWallet() + + //wallet.GenDefaultKeyStore(password) + var myAccount *wallet.Account + myAccount, err = wallet.NewAccountFromKeyfile(keyFile, password) + if err != nil { + log.Fatal("key file validation failed:%s", err.Error()) + } + fmt.Println(myAccount.Address().String()) + + // create the source wallet obj for Infura Ropsten + myWallet := wallet.NewEthereumWalletWithKeyfile(ropstenURL, keyFile, password) + fmt.Println(myWallet.GetBalance()) + + // create dest account + //wallet.GenDefaultKeyStore(password) + var destAccount *wallet.Account + destKeyFile := "./UTC--2018-06-16T20-09-33.726552102Z--cecb952de5b23950b15bfd49302d1bdd25f9ee67" + destAccount, err = wallet.NewAccountFromKeyfile(destKeyFile, password) + if err != nil { + log.Fatal("key file validation failed:%s", err.Error()) + } + fmt.Println(destAccount.Address().String()) + + // create the destination wallet obj for Infura Ropsten + destWallet := wallet.NewEthereumWalletWithKeyfile(ropstenURL, destKeyFile, password) + fmt.Println(destWallet.GetBalance()) + + // lets transfer + //err = myWallet.Transfer(destAccount.Address().String(), big.NewInt(3344556677)) + //if err != nil { + // fmt.Println("what happened here : ", err) + //} + fmt.Println("after transfer : ") + fmt.Println("Dest balance ") + fmt.Println(destWallet.GetBalance()) + fmt.Println(destWallet.Balance()) + fmt.Println("Source balance ") + fmt.Println(myWallet.GetBalance()) + fmt.Println(myWallet.Balance()) + + fmt.Println(myWallet.CreateAddress()) +} diff --git a/vendor/github.com/phoreproject/go-ethwallet/configuration.yaml b/vendor/github.com/phoreproject/go-ethwallet/configuration.yaml new file mode 100644 index 0000000000..734ea60a2f --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/configuration.yaml @@ -0,0 +1,2 @@ +ROPSTEN_PPv2_ADDRESS : 0x0b944d65dc9f06d756ee2845061c0948eb938129 +ROPSTEN_REGISTRY : 0x029d6a0cd4ce98315690f4ea52945545d9c0f460 diff --git a/vendor/github.com/phoreproject/go-ethwallet/env-sample b/vendor/github.com/phoreproject/go-ethwallet/env-sample new file mode 100644 index 0000000000..dc7e57a798 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/env-sample @@ -0,0 +1 @@ +INFURA_KEY=YOUR_INFURA_KEY \ No newline at end of file diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/util/util.go b/vendor/github.com/phoreproject/go-ethwallet/util/util.go similarity index 77% rename from vendor/github.com/OpenBazaar/go-ethwallet/util/util.go rename to vendor/github.com/phoreproject/go-ethwallet/util/util.go index eb27515cbe..f9c70ff517 100644 --- a/vendor/github.com/OpenBazaar/go-ethwallet/util/util.go +++ b/vendor/github.com/phoreproject/go-ethwallet/util/util.go @@ -5,14 +5,19 @@ import ( "reflect" "regexp" "strconv" + "strings" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcutil/base58" "github.com/btcsuite/btcutil/hdkeychain" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/op/go-logging" "github.com/shopspring/decimal" ) +var log = logging.MustGetLogger("ethwallet-util") + // ExtractChaincode used to get the chaincode out of extended key func ExtractChaincode(key *hdkeychain.ExtendedKey) []byte { return base58.Decode(key.String())[13:45] @@ -119,3 +124,26 @@ func SigRSV(isig interface{}) ([32]byte, [32]byte, uint8) { return R, S, V } + +// EnsureCorrectPrefix ensures we have 0x prefix +func EnsureCorrectPrefix(str string) string { + if strings.HasPrefix(str, "0x") { + return str + } + return "0x" + str +} + +// CreateChainHash is a wrapper to the chainhash.new hash function +// this allows for a cleaner way to check if we are not in any way +// letting the 0x prefix hinder the chainhash generation +func CreateChainHash(str string) (*chainhash.Hash, error) { + hash, err := chainhash.NewHashFromStr(str) + if err == chainhash.ErrHashStrSize { + hash, err = chainhash.NewHashFromStr(strings.TrimPrefix(str, "0x")) + if err != nil { + log.Errorf("err creating chainhash : %v", err) + return nil, err + } + } + return hash, nil +} diff --git a/vendor/github.com/phoreproject/go-ethwallet/util/util_test.go b/vendor/github.com/phoreproject/go-ethwallet/util/util_test.go new file mode 100644 index 0000000000..b42cd2d506 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/util/util_test.go @@ -0,0 +1,163 @@ +package util + +import ( + "fmt" + "math/big" + "testing" + + "github.com/btcsuite/btcutil/hdkeychain" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/shopspring/decimal" +) + +func TestIsValidAddress(t *testing.T) { + t.Parallel() + validAddress := "0x323b5d4c32345ced77393b3530b1eed0f346429d" + invalidAddress := "0xabc" + invalidAddress2 := "323b5d4c32345ced77393b3530b1eed0f346429d" + { + got := IsValidAddress(validAddress) + expected := true + + if got != expected { + t.Errorf("Expected %v, got %v", expected, got) + } + } + + { + got := IsValidAddress(invalidAddress) + expected := false + + if got != expected { + t.Errorf("Expected %v, got %v", expected, got) + } + } + + { + got := IsValidAddress(invalidAddress2) + expected := false + + if got != expected { + t.Errorf("Expected %v, got %v", expected, got) + } + } +} + +func TestIsZeroAddress(t *testing.T) { + t.Parallel() + validAddress := common.HexToAddress("0x323b5d4c32345ced77393b3530b1eed0f346429d") + zeroAddress := common.HexToAddress("0x0000000000000000000000000000000000000000") + + { + isZeroAddress := IsZeroAddress(validAddress) + + if isZeroAddress { + t.Error("Expected to be false") + } + } + + { + isZeroAddress := IsZeroAddress(zeroAddress) + + if !isZeroAddress { + t.Error("Expected to be true") + } + } + + { + isZeroAddress := IsZeroAddress(validAddress.Hex()) + + if isZeroAddress { + t.Error("Expected to be false") + } + } + + { + isZeroAddress := IsZeroAddress(zeroAddress.Hex()) + + if !isZeroAddress { + t.Error("Expected to be true") + } + } +} + +func TestToWei(t *testing.T) { + t.Parallel() + amount := decimal.NewFromFloat(0.02) + got := ToWei(amount, 18) + expected := new(big.Int) + expected.SetString("20000000000000000", 10) + if got.Cmp(expected) != 0 { + t.Errorf("Expected %s, got %s", expected, got) + } +} + +func TestToDecimal(t *testing.T) { + t.Parallel() + weiAmount := big.NewInt(0) + weiAmount.SetString("20000000000000000", 10) + ethAmount := ToDecimal(weiAmount, 18) + f64, _ := ethAmount.Float64() + expected := 0.02 + if f64 != expected { + t.Errorf("%v does not equal expected %v", ethAmount, expected) + } +} + +func TestCalcGasLimit(t *testing.T) { + t.Parallel() + gasPrice := big.NewInt(0) + gasPrice.SetString("2000000000", 10) + gasLimit := uint64(21000) + expected := big.NewInt(0) + expected.SetString("42000000000000", 10) + gasCost := CalcGasCost(gasLimit, gasPrice) + if gasCost.Cmp(expected) != 0 { + t.Errorf("expected %s, got %s", gasCost, expected) + } +} + +func TestSigRSV(t *testing.T) { + t.Parallel() + + sig := "0x789a80053e4927d0a898db8e065e948f5cf086e32f9ccaa54c1908e22ac430c62621578113ddbb62d509bf6049b8fb544ab06d36f916685a2eb8e57ffadde02301" + r, s, v := SigRSV(sig) + expectedR := "789a80053e4927d0a898db8e065e948f5cf086e32f9ccaa54c1908e22ac430c6" + expectedS := "2621578113ddbb62d509bf6049b8fb544ab06d36f916685a2eb8e57ffadde023" + expectedV := uint8(28) + if hexutil.Encode(r[:])[2:] != expectedR { + t.FailNow() + } + if hexutil.Encode(s[:])[2:] != expectedS { + t.FailNow() + } + if v != expectedV { + t.FailNow() + } +} + +func TestExtractChaincode(t *testing.T) { + t.Parallel() + + version := []byte{0x05, 0x06, 0x07, 0x08} + validAddress := []byte("323b5d4c32345ced77393b3530b1eed0f346429d") + chaincode := []byte("423b5d4c32345ced77393b3530b1eed1") + parentFP := []byte{0x00, 0x00, 0x00, 0x00} + + fmt.Println(version, validAddress, chaincode) + + key := hdkeychain.NewExtendedKey(version, validAddress, chaincode[:32], parentFP, 0, 0, false) + + actualChaincode := ExtractChaincode(key) + + fmt.Println(actualChaincode) + + fmt.Println("Org Chaincode : ", string(chaincode[:32])) + fmt.Println("Extracted Chaincode : ", string(actualChaincode)) + + if string(chaincode[:32]) != string(actualChaincode) { + t.Error("chaincodes dont match") + } + +} diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/account.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/account.go similarity index 83% rename from vendor/github.com/OpenBazaar/go-ethwallet/wallet/account.go rename to vendor/github.com/phoreproject/go-ethwallet/wallet/account.go index 1b3d1b41ee..92ec721b64 100644 --- a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/account.go +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/account.go @@ -6,6 +6,7 @@ import ( "os" "github.com/btcsuite/btcd/chaincfg" + hd "github.com/btcsuite/btcutil/hdkeychain" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -20,12 +21,12 @@ type EthAddress struct { // String representation of eth address func (addr EthAddress) String() string { - return addr.address.String() + return addr.address.Hex() // [2:] //String()[2:] } // EncodeAddress returns hex representation of the address func (addr EthAddress) EncodeAddress() string { - return addr.address.Hex() + return addr.address.Hex() // [2:] } // ScriptAddress returns byte representation of address @@ -59,7 +60,7 @@ func NewAccountFromKeyfile(keyFile, password string) (*Account, error) { } // NewAccountFromMnemonic returns generated account -func NewAccountFromMnemonic(mnemonic, password string) (*Account, error) { +func NewAccountFromMnemonic(mnemonic, password string, params *chaincfg.Params) (*Account, error) { seed := bip39.NewSeed(mnemonic, password) /* @@ -76,11 +77,28 @@ func NewAccountFromMnemonic(mnemonic, password string) (*Account, error) { */ - privateKeyECDSA, err := crypto.ToECDSA(seed[:32]) + // This is no longer used. 31 Dec 2018 + /* + privateKeyECDSA, err := crypto.ToECDSA(seed[:32]) + if err != nil { + return nil, err + } + */ + + mPrivKey, err := hd.NewMaster(seed, params) if err != nil { + log.Errorf("err initializing btc priv key : %v", err) return nil, err } + exPrivKey, err := mPrivKey.ECPrivKey() + if err != nil { + log.Errorf("err extracting btcec priv key : %v", err) + return nil, err + } + + privateKeyECDSA := exPrivKey.ToECDSA() + /* fmt.Println(privateKeyECDSA) fmt.Println(privateKeyECDSA.Public()) diff --git a/vendor/github.com/phoreproject/go-ethwallet/wallet/account_test.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/account_test.go new file mode 100644 index 0000000000..2f792d71ac --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/account_test.go @@ -0,0 +1,101 @@ +package wallet + +import ( + "bytes" + "testing" + + "github.com/ethereum/go-ethereum/common" + + "github.com/phoreproject/go-ethwallet/util" +) + +const ( + validKeyFile = "../test/UTC--2018-06-16T18-41-19.615987160Z--c0b4ef9e9d2806f643be94d2434e5c3d5cecd255" + validPassword = "hotpotato" + invalidKeyFile = "../test/UTC--IDontExist" + invalidPassword = "lookout" + mnemonicStr = "soup arch join universe table nasty fiber solve hotel luggage double clean tell oppose hurry weather isolate decline quick dune song enforce curious menu" // "wolf dragon lion stage rose snow sand snake kingdom hand daring flower foot walk sword" + mnemonicStrAddress = "0x44Ae1C0955C7ad96700088Fb96906C72102c51E3" +) + +var validEthAddr EthAddress + +func setupAddr() { + addr := common.HexToAddress(validSourceAddress) + validEthAddr = EthAddress{ + address: &addr, + } +} + +func TestNewAccountWithValidCredentials(t *testing.T) { + account, err := NewAccountFromKeyfile(validKeyFile, validPassword) + if err != nil { + t.Errorf("valid keyfile should open properly") + } + if account.Address().String() == "" { + t.Errorf("the account should have a valid address") + } + if account.Address().String() != validSourceAddress { + t.Errorf("the account address is wrong") + } +} + +func TestNewAccountWithInValidKeyFile(t *testing.T) { + account, err := NewAccountFromKeyfile(invalidKeyFile, validPassword) + if err == nil { + t.Errorf("invalid keyfile should not open properly") + } + if account != nil { + t.Errorf("the account should not be returned") + } +} + +func TestNewAccountWithInValidPassword(t *testing.T) { + account, err := NewAccountFromKeyfile(validKeyFile, invalidPassword) + if err == nil { + t.Errorf("invalid keyfile should not open properly") + } + if account != nil { + t.Errorf("the account should not be returned") + } +} + +func TestNewAccountWithInValidCredentials(t *testing.T) { + account, err := NewAccountFromKeyfile(invalidKeyFile, invalidPassword) + if err == nil { + t.Errorf("invalid keyfile should not open properly") + } + if account != nil { + t.Errorf("the account should not be returned") + } +} + +func TestNewAccountWithMnemonic(t *testing.T) { + account, err := NewAccountFromMnemonic(mnemonicStr, "", nil) + if err != nil { + t.Errorf("failed to open account from mnemonic: %v", err) + } + //fmt.Println(account.key.PrivateKey) + //fmt.Println(account.Address()) + //fmt.Println("account address : ", account.Address().String()) + if account.Address().String() != mnemonicStrAddress { + t.Errorf("failed to gen correct address from mnemonic: %v", err) + } + if !util.IsValidAddress(account.Address()) { + t.Errorf("failed to gen valid address from mnemonic: %v", err) + } +} + +func TestEthAddress(t *testing.T) { + setupAddr() + //fmt.Println(validEthAddr.String()) + if validEthAddr.String() != validSourceAddress { + t.Errorf("address not initialized correctly") + } + if !bytes.Equal(validEthAddr.ScriptAddress(), []byte{192, 180, 239, 158, 157, 40, 6, 246, 67, 190, 148, 210, 67, 78, 92, 61, 92, 236, 210, 85}) { + t.Errorf("address not initialized correctly") + } + if validEthAddr.EncodeAddress() != validSourceAddress[2:] { + t.Errorf("address not initialized correctly") + } +} diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/client.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/client.go similarity index 72% rename from vendor/github.com/OpenBazaar/go-ethwallet/wallet/client.go rename to vendor/github.com/phoreproject/go-ethwallet/wallet/client.go index 3c27d060aa..c7009ccc94 100644 --- a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/client.go +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/client.go @@ -8,46 +8,86 @@ import ( "io/ioutil" "math/big" "net/http" + "strings" "sync" "time" wi "github.com/OpenBazaar/wallet-interface" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto/sha3" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" + "github.com/gorilla/websocket" "github.com/hunterlong/tokenbalance" + "github.com/nanmu42/etherscan-api" - "github.com/OpenBazaar/go-ethwallet/util" + "github.com/phoreproject/go-ethwallet/util" ) +/* + !! Important URL information from Infura + Mainnet JSON-RPC over HTTPs https://mainnet.infura.io/v3/YOUR-PROJECT-ID + Mainnet JSON-RPC over websockets wss://mainnet.infura.io/ws/v3/YOUR-PROJECT-ID + Ropsten JSON-RPC over HTTPS https://ropsten.infura.io/v3/YOUR-PROJECT-ID + Ropsten JSON-RPC over websockets wss://ropsten.infura.io/ws/v3/YOUR-PROJECT-ID + Rinkeby JSON-RPC over HTTPS https://rinkeby.infura.io/v3/YOUR-PROJECT-ID + Rinkeby JSON-RPC over websockets wss://rinkeby.infura.io/ws/v3/YOUR-PROJECT-ID + Kovan JSON-RPC over HTTPS https://kovan.infura.io/v3/YOUR-PROJECT-ID + Kovan JSON-RPC over websockets wss://kovan.infura.io/ws/v3/YOUR-PROJECT-ID + Görli JSON-RPC over HTTPS https://goerli.infura.io/v3/YOUR-PROJECT-ID + Görli JSON-RPC over websockets wss://goerli.infura.io/ws/v3/YOUR-PROJECT-ID +*/ + +var wsURLTemplate = "wss://%s.infura.io/ws/%s" + // EthClient represents the eth client type EthClient struct { *ethclient.Client - url string + eClient *etherscan.Client + ws *websocket.Conn + url string } var txns []wi.Txn var txnsLock sync.RWMutex // NewEthClient returns a new eth client +// wss://mainnet.infura.io/ws/v3/YOUR-PROJECT-ID func NewEthClient(url string) (*EthClient, error) { var conn *ethclient.Client + var econn *etherscan.Client + var wsURL string + if strings.Contains(url, "rinkeby") { + econn = etherscan.New(etherscan.Rinkby, EtherScanAPIKey) + wsURL = fmt.Sprintf(wsURLTemplate, "rinkeby", InfuraAPIKey) + } else if strings.Contains(url, "ropsten") { + econn = etherscan.New(etherscan.Ropsten, EtherScanAPIKey) + wsURL = fmt.Sprintf(wsURLTemplate, "ropsten", InfuraAPIKey) + } else { + econn = etherscan.New(etherscan.Mainnet, EtherScanAPIKey) + wsURL = fmt.Sprintf(wsURLTemplate, "mainnet", InfuraAPIKey) + } var err error if conn, err = ethclient.Dial(url); err != nil { return nil, err } + ws, _, err := websocket.DefaultDialer.Dial(wsURL, nil) + if err != nil { + log.Errorf("eth wallet unable to open ws conn: %v", err) + ws = nil + } return &EthClient{ - Client: conn, - url: url, + Client: conn, + eClient: econn, + url: url, + ws: ws, }, nil } // Transfer will transfer eth from this user account to dest address -func (client *EthClient) Transfer(from *Account, destAccount common.Address, value *big.Int) (common.Hash, error) { +func (client *EthClient) Transfer(from *Account, destAccount common.Address, value *big.Int, spendAll bool, fee big.Int) (common.Hash, error) { var err error fromAddress := from.Address() nonce, err := client.PendingNonceAt(context.Background(), fromAddress) @@ -60,28 +100,44 @@ func (client *EthClient) Transfer(from *Account, destAccount common.Address, val return common.BytesToHash([]byte{}), err } - msg := ethereum.CallMsg{From: fromAddress, Value: value} + if gasPrice.Int64() < fee.Int64() { + gasPrice = &fee + } + + tvalue := value + + msg := ethereum.CallMsg{From: fromAddress, Value: tvalue} gasLimit, err := client.EstimateGas(context.Background(), msg) if err != nil { return common.BytesToHash([]byte{}), err } - rawTx := types.NewTransaction(nonce, destAccount, value, gasLimit, gasPrice, nil) + // if spend all then we need to set the value = confirmedBalance - gas + if spendAll { + currentBalance, err := client.GetBalance(fromAddress) + if err != nil { + //currentBalance = big.NewInt(0) + return common.BytesToHash([]byte{}), err + } + gas := new(big.Int).Mul(gasPrice, big.NewInt(int64(gasLimit))) + + if currentBalance.Cmp(gas) >= 0 { + tvalue = new(big.Int).Sub(currentBalance, gas) + } + } + + rawTx := types.NewTransaction(nonce, destAccount, tvalue, gasLimit, gasPrice, nil) signedTx, err := from.SignTransaction(types.HomesteadSigner{}, rawTx) if err != nil { return common.BytesToHash([]byte{}), err } txns = append(txns, wi.Txn{ Txid: signedTx.Hash().Hex(), - Value: value.Int64(), + Value: tvalue.String(), Height: int32(nonce), Timestamp: time.Now(), WatchOnly: false, Bytes: rawTx.Data()}) - - // this for debug only - fmt.Println("Txn ID : ", signedTx.Hash().Hex()) - return signedTx.Hash(), client.SendTransaction(context.Background(), signedTx) } @@ -100,17 +156,9 @@ func (client *EthClient) TransferToken(from *Account, toAddress common.Address, } transferFnSignature := []byte("transfer(address,uint256)") - hash := sha3.NewKeccak256() - hash.Write(transferFnSignature) - methodID := hash.Sum(nil)[:4] - - fmt.Printf("Method ID: %s\n", hexutil.Encode(methodID)) - + methodID := crypto.Keccak256(transferFnSignature)[:4] paddedAddress := common.LeftPadBytes(toAddress.Bytes(), 32) - fmt.Printf("To address: %s\n", hexutil.Encode(paddedAddress)) - paddedAmount := common.LeftPadBytes(value.Bytes(), 32) - fmt.Printf("Token amount: %s", hexutil.Encode(paddedAmount)) var data []byte data = append(data, methodID...) @@ -124,25 +172,18 @@ func (client *EthClient) TransferToken(from *Account, toAddress common.Address, if err != nil { return common.BytesToHash([]byte{}), err } - fmt.Printf("Gas limit: %d", gasLimit) - rawTx := types.NewTransaction(nonce, tokenAddress, value, gasLimit, gasPrice, data) signedTx, err := from.SignTransaction(types.HomesteadSigner{}, rawTx) //types.SignTx(tx, types.HomesteadSigner{}, privateKey) if err != nil { return common.BytesToHash([]byte{}), err } - txns = append(txns, wi.Txn{ Txid: signedTx.Hash().Hex(), - Value: value.Int64(), + Value: value.String(), Height: int32(nonce), Timestamp: time.Now(), WatchOnly: false, Bytes: rawTx.Data()}) - - // this for debug only - fmt.Println("Txn ID : ", signedTx.Hash().Hex()) - return signedTx.Hash(), client.SendTransaction(context.Background(), signedTx) } @@ -157,7 +198,9 @@ func (client *EthClient) GetTokenBalance(destAccount, tokenAddress common.Addres GethLocation: client.url, Logs: true, } - configs.Connect() + if err := configs.Connect(); err != nil { + return nil, err + } // insert a Token Contract address and Wallet address contract := tokenAddress.String() @@ -179,12 +222,12 @@ func (client *EthClient) GetTransaction(hash common.Hash) (*types.Transaction, b } // GetLatestBlock - returns the latest block -func (client *EthClient) GetLatestBlock() (uint32, string, error) { +func (client *EthClient) GetLatestBlock() (uint32, common.Hash, error) { header, err := client.HeaderByNumber(context.Background(), nil) if err != nil { - return 0, "", err + return 0, common.BytesToHash([]byte{}), err } - return uint32(header.Number.Int64()), header.Hash().String(), nil + return uint32(header.Number.Int64()), header.Hash(), nil } // EstimateTxnGas - returns estimated gas @@ -224,6 +267,7 @@ func (client *EthClient) EstimateGasSpend(from common.Address, value *big.Int) ( // GetTxnNonce - used to fetch nonce for a submitted txn func (client *EthClient) GetTxnNonce(txID string) (int32, error) { txnsLock.Lock() + defer txnsLock.Unlock() for _, txn := range txns { if txn.Txid == txID { return txn.Height, nil diff --git a/vendor/github.com/phoreproject/go-ethwallet/wallet/client_test.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/client_test.go new file mode 100644 index 0000000000..b59c0cfce3 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/client_test.go @@ -0,0 +1,494 @@ +package wallet + +import ( + "context" + "fmt" + "math/big" + "testing" + "time" + + "github.com/davecgh/go-spew/spew" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/joho/godotenv" + log "github.com/sirupsen/logrus" +) + +const invalidInfuraKey = "IAMNOTREAL" +const validSourceAddress = "0xc0B4ef9E9d2806F643be94d2434e5C3d5cEcd255" +const validDestinationAddress = "0xcecb952de5b23950b15bfd49302d1bdd25f9ee67" + +const validTxn1 = "0xae818b782ce2d5ef8160de1d022440fdaf92cf91d4cd444eb23c6b6a55240c5b" + +var client *EthClient +var err error + +var validInfuraKey string +var validurlsTest map[string]bool +var invalidurlsTest map[string]bool +var logicallyinvalidurlsTest map[string]bool +var plainurlsTest map[string]bool + +var n uint32 +var bal *big.Int +var ropstenURL string + +var validRopstenTxn types.Transaction + +func init() { + err := godotenv.Load("../.env") + if err != nil { + log.Fatal("Error loading .env file") + } + validInfuraKey = InfuraAPIKey // os.Getenv("INFURA_KEY") + fmt.Println("valid infura key is : ", validInfuraKey) + + ropstenURL = fmt.Sprintf("https://ropsten.infura.io/%s", validInfuraKey) + + validRopstenTxn = *types.NewTransaction(0, common.HexToAddress(validDestinationAddress), + big.NewInt(3344556677), 53000, big.NewInt(1000000000), + []byte("f86780843b9aca0082cf0894cecb952de5b23950b15bfd49302d1bdd25f9ee6784c759e285801ca056dfa0ed4e028d2f2307c421bbe0ebe7516e5fdd140ff080091cb03137a885f8a03197486094c53edb2aaefb6ba5059dd6c82fc709134c93c0c422cb671a139352")) +} + +func setup() { + + validurlsTest = map[string]bool{ + fmt.Sprintf("https://ropsten.infura.io/%s", validInfuraKey): true, + fmt.Sprintf("https://rinkeby.infura.io/%s", validInfuraKey): true, + fmt.Sprintf("https://mainnet.infura.io/%s", validInfuraKey): true, + fmt.Sprintf("https://ropsten.infura.io/%s", invalidInfuraKey): false, + fmt.Sprintf("https://rinkeby.infura.io/%s", invalidInfuraKey): false, + fmt.Sprintf("https://mainnet.infura.io/%s", invalidInfuraKey): false, + } + + invalidurlsTest = map[string]bool{ + fmt.Sprintf("innet.infura.io/%s", invalidInfuraKey): false, + "innet.infura.io/": false, + } + + logicallyinvalidurlsTest = map[string]bool{ + fmt.Sprintf("https://ropstenFTW.infura.io/%s", validInfuraKey): true, + } + + plainurlsTest = map[string]bool{ + "https://ropsten.infura.io/": false, + "https://rinkeby.infura.io/": false, + "https://mainnet.infura.io/": false, + } + + n = 0 + +} + +func TestNewClient(t *testing.T) { + setup() + t.Parallel() + + if validInfuraKey == "" { + t.Error("no infura key specified") + } + + for baseURL := range validurlsTest { + _, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + } + + for baseURL := range plainurlsTest { + _, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + } + + for baseURL := range logicallyinvalidurlsTest { + _, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + } + + for baseURL := range invalidurlsTest { + _, err = NewEthClient(baseURL) + if err == nil { + t.Errorf(baseURL + " client should not have initialized") + } + } +} + +func TestGetLatestBlock(t *testing.T) { + setup() + t.Parallel() + + for baseURL := range validurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + n, _, err = client.GetLatestBlock() + if err != nil || n <= 0 { + t.Errorf("client should have fetched block number") + } + } + + for baseURL := range plainurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + n, _, err = client.GetLatestBlock() + if err != nil || n <= 0 { + t.Errorf("client should have fetched block number") + } + } + + for baseURL := range logicallyinvalidurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + n, _, err = client.GetLatestBlock() + if err == nil || n > 0 { + t.Errorf("client should not have fetched block number") + } + } +} + +func TestGetBalance(t *testing.T) { + setup() + t.Parallel() + + addr := common.HexToAddress(validSourceAddress) + + for baseURL := range validurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.GetBalance(addr) + if err != nil || bal == nil { + t.Errorf("client should have fetched balance") + } + } + + for baseURL := range plainurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.GetBalance(addr) + if err != nil || bal == nil { + t.Errorf("client should have fetched balance") + } + } + + for baseURL := range logicallyinvalidurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.GetBalance(addr) + if err == nil && bal != nil { + t.Errorf("client should not have fetched balance") + } + } +} + +func TestGetUnconfirmedBalance(t *testing.T) { + setup() + t.Parallel() + + addr := common.HexToAddress(validSourceAddress) + + for baseURL := range validurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.GetUnconfirmedBalance(addr) + if err != nil || bal == nil { + t.Errorf("client should have fetched unconfirmed balance") + } + } + + for baseURL := range plainurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.GetUnconfirmedBalance(addr) + if err != nil || bal == nil { + t.Errorf("client should have fetched unconfirmed balance") + } + } + + for baseURL := range logicallyinvalidurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.GetUnconfirmedBalance(addr) + if err == nil && bal != nil { + t.Errorf("client should not have fetched unconfirmed balance") + } + } +} + +func TestEstimateTxnGas(t *testing.T) { + setup() + t.Parallel() + + addr := common.HexToAddress(validSourceAddress) + dest := common.HexToAddress(validDestinationAddress) + value := big.NewInt(200000) + + for baseURL := range validurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.EstimateTxnGas(addr, dest, value) + if err != nil || bal == nil { + t.Errorf("client should have estimated txn gas") + } + } + + for baseURL := range plainurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.EstimateTxnGas(addr, dest, value) + if err != nil || bal == nil { + t.Errorf("client should have estimated txn gas") + } + } + + for baseURL := range logicallyinvalidurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.EstimateTxnGas(addr, dest, value) + if err == nil && bal != nil { + t.Errorf("client should not have estimated txn gas") + } + } +} + +func TestEstimateGasSpend(t *testing.T) { + setup() + t.Parallel() + + addr := common.HexToAddress(validSourceAddress) + value := big.NewInt(200000) + + for baseURL := range validurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.EstimateGasSpend(addr, value) + if err != nil || bal == nil { + t.Errorf("client should have estimated txn gas") + } + } + + for baseURL := range plainurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.EstimateGasSpend(addr, value) + if err != nil || bal == nil { + t.Errorf("client should have estimated txn gas") + } + } + + for baseURL := range logicallyinvalidurlsTest { + client, err = NewEthClient(baseURL) + if err != nil { + t.Errorf("client should have initialized") + } + bal, err = client.EstimateGasSpend(addr, value) + if err == nil && bal != nil { + t.Errorf("client should not have estimated txn gas") + } + } +} + +func TestValidGetTransaction(t *testing.T) { + t.Parallel() + + client, err := NewEthClient(ropstenURL) + if err != nil { + t.Errorf("client should have initialized") + } + txn, isPending, err := client.GetTransaction(common.HexToHash(validTxn1)) + spew.Println(txn) + + if err != nil { + t.Errorf("txn should have been correctly fetched") + } + + if isPending { + t.Errorf("non pending txn should have been correctly fetched") + } + + if validRopstenTxn.Nonce() != txn.Nonce() { + t.Errorf("txn should have been correctly fetched") + } + + if validRopstenTxn.Gas() != txn.Gas() { + t.Errorf("txn should have been correctly fetched") + } + + if validRopstenTxn.GasPrice().Cmp(txn.GasPrice()) != 0 { + t.Errorf("txn should have been correctly fetched") + } + +} + +func TestInvalidGetTransaction(t *testing.T) { + t.Parallel() + + client, err := NewEthClient(ropstenURL) + if err != nil { + t.Errorf("client should have initialized") + } + txn, _, err := client.GetTransaction(common.HexToHash("ooommm")) + if err == nil || txn != nil { + t.Errorf("invalid txn should not have been fetched") + } +} + +func TestTransfer(t *testing.T) { + //t.SkipNow() + client, err := NewEthClient(ropstenURL) + if err != nil { + t.Errorf("client should have initialized") + } + addr := common.HexToAddress(validSourceAddress) + account, err := NewAccountFromKeyfile("../test/UTC--2018-06-16T18-41-19.615987160Z--c0b4ef9e9d2806f643be94d2434e5c3d5cecd255", "hotpotato") + if err != nil { + t.Errorf("account should have initialized") + } + dest := common.HexToAddress(validDestinationAddress) + value := big.NewInt(20000000000000) + + var bal1, bal2, sbal1, dbal1, sbal2, dbal2, val *big.Int + var txn *types.Transaction + + bal1, err = client.GetBalance(addr) + if err != nil || bal1 == nil { + t.Errorf("client should have fetched balance") + } + + bal2, err = client.GetUnconfirmedBalance(addr) + if err != nil || bal2 == nil { + t.Errorf("client should have fetched balance") + } + + sbal1 = big.NewInt(0) + + // get the source balance + sbal1.Add(bal1, big.NewInt(0)) + + bal1, err = client.GetBalance(dest) + if err != nil { + t.Errorf("client should have fetched balance") + } + + bal2, err = client.GetUnconfirmedBalance(dest) + if err != nil { + t.Errorf("client should have fetched balance") + } + + dbal1 = big.NewInt(0) + + // get the dest balance + dbal1.Add(bal1, big.NewInt(0)) + + hash, err := client.Transfer(account, dest, value, false) + if err != nil { + t.Errorf("client should transfer : %v", err) + } + + txn, _, err = client.GetTransaction(hash) + if err != nil { + t.Errorf("txn should have been correctly fetched") + } + + if txn.Value().Cmp(value) != 0 { + t.Errorf("client should transfer correct amount") + } + + bal1, err = client.GetBalance(addr) + if err != nil { + t.Errorf("client should have fetched balance") + } + + bal2, err = client.GetUnconfirmedBalance(addr) + if err != nil { + t.Errorf("client should have fetched balance") + } + + time.Sleep(2 * time.Minute) + + sbal2 = big.NewInt(0) + + // get the source balance + sbal2.Add(bal1, big.NewInt(0)) + + bal1, err = client.GetBalance(dest) + if err != nil { + t.Errorf("client should have fetched balance") + } + + bal2, err = client.GetUnconfirmedBalance(dest) + if err != nil { + t.Errorf("client should have fetched balance") + } + + dbal2 = big.NewInt(0) + val = big.NewInt(0) + + // get the dest balance + dbal2.Add(bal1, big.NewInt(0)) + + val.Sub(dbal2, dbal1) + + fmt.Println("before : ", dbal1.Int64(), " after : ", dbal2.Int64(), " value : ", value.Int64()) + + if val.Cmp(value) != 0 { + t.Errorf("client should have transferred balance") + } +} + +func TestEthGasStationFetch(t *testing.T) { + client, err := NewEthClient(validRinkebyURL) + if err != nil { + t.Errorf("client should have initialized") + } + + data, err := client.GetEthGasStationEstimate() + + if err != nil { + fmt.Println(err) + return + } + + spew.Dump(data) + fmt.Println("avg : ", int64(data.Average*1000000000)) + + est, err := client.SuggestGasPrice(context.Background()) + + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(est.Int64()) + +} diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/contract_manager.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/contract_manager.go similarity index 51% rename from vendor/github.com/OpenBazaar/go-ethwallet/wallet/contract_manager.go rename to vendor/github.com/phoreproject/go-ethwallet/wallet/contract_manager.go index fce63cd82d..bf5862e0fe 100644 --- a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/contract_manager.go +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/contract_manager.go @@ -15,17 +15,29 @@ import ( "github.com/ethereum/go-ethereum/event" ) +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = abi.U256 + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + // RegistryABI is the input ABI used to generate the binding from. -const RegistryABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"uint8\"},{\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"addVersion\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"}],\"name\":\"markVersionAudited\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"changeStatus\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"},{\"name\":\"bugLevel\",\"type\":\"uint8\"}],\"name\":\"changeBugLevel\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getTotalContractCount\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"}],\"name\":\"getRecommendedVersion\",\"outputs\":[{\"name\":\"versionName\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"uint8\"},{\"name\":\"bugLevel\",\"type\":\"uint8\"},{\"name\":\"implementation\",\"type\":\"address\"},{\"name\":\"audited\",\"type\":\"bool\"},{\"name\":\"dateAdded\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"}],\"name\":\"getVersionDetails\",\"outputs\":[{\"name\":\"versionString\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"uint8\"},{\"name\":\"bugLevel\",\"type\":\"uint8\"},{\"name\":\"implementation\",\"type\":\"address\"},{\"name\":\"audited\",\"type\":\"bool\"},{\"name\":\"dateAdded\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getContractAtIndex\",\"outputs\":[{\"name\":\"contractName\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"}],\"name\":\"removeRecommendedVersion\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getVersionAtIndex\",\"outputs\":[{\"name\":\"versionName\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"}],\"name\":\"markRecommendedVersion\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"}],\"name\":\"getVersionCountForContract\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"versionName\",\"type\":\"string\"},{\"indexed\":true,\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"VersionAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"versionName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"StatusChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"versionName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"bugLevel\",\"type\":\"uint8\"}],\"name\":\"BugLevelChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"versionName\",\"type\":\"string\"}],\"name\":\"VersionAudited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"versionName\",\"type\":\"string\"}],\"name\":\"VersionRecommended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"}],\"name\":\"RecommendedVersionRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"}],\"name\":\"OwnershipRenounced\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"}]=======openzeppelin-solidity/contracts/AddressUtils.sol:AddressUtils=======[]=======openzeppelin-solidity/contracts/ownership/Ownable.sol:Ownable=======[{\"constant\":false,\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"}],\"name\":\"OwnershipRenounced\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"}]" +const RegistryABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"uint8\"},{\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"addVersion\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"uint8\"},{\"name\":\"bugLevel\",\"type\":\"uint8\"}],\"name\":\"updateVersion\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getTotalContractCount\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"}],\"name\":\"getRecommendedVersion\",\"outputs\":[{\"name\":\"versionName\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"uint8\"},{\"name\":\"bugLevel\",\"type\":\"uint8\"},{\"name\":\"implementation\",\"type\":\"address\"},{\"name\":\"dateAdded\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"}],\"name\":\"getVersionDetails\",\"outputs\":[{\"name\":\"versionString\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"uint8\"},{\"name\":\"bugLevel\",\"type\":\"uint8\"},{\"name\":\"implementation\",\"type\":\"address\"},{\"name\":\"dateAdded\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getContractAtIndex\",\"outputs\":[{\"name\":\"contractName\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"}],\"name\":\"removeRecommendedVersion\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getVersionAtIndex\",\"outputs\":[{\"name\":\"versionName\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"},{\"name\":\"versionName\",\"type\":\"string\"}],\"name\":\"markRecommendedVersion\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"contractName\",\"type\":\"string\"}],\"name\":\"getVersionCountForContract\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"versionName\",\"type\":\"string\"},{\"indexed\":true,\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"VersionAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"versionName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"status\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"bugLevel\",\"type\":\"uint8\"}],\"name\":\"VersionUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"versionName\",\"type\":\"string\"}],\"name\":\"VersionRecommended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"contractName\",\"type\":\"string\"}],\"name\":\"RecommendedVersionRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"}],\"name\":\"OwnershipRenounced\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"}]=======openzeppelin-solidity/contracts/ownership/Ownable.sol:Ownable=======[{\"constant\":false,\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"}],\"name\":\"OwnershipRenounced\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"}]=======openzeppelin-solidity/contracts/utils/Address.sol:Address=======[]" // RegistryBin is the compiled bytecode used for deploying new contracts. -const RegistryBin = `6080604052336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506135fd806100536000396000f3006080604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633de5311a146100e0578063437fe3a3146101605780634890b0c5146101b3578063568d1ee814610213578063715018a614610273578063751f592b1461028a5780637e27634e146102b55780638ad030c1146103d85780638da5cb5b146105135780639b534f181461056a578063acd820a814610610578063af2c7fa314610679578063ca2e7cf314610737578063f2fde38b1461078a578063ff93dab4146107cd575b600080fd5b3480156100ec57600080fd5b5061015e600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061081c565b005b34801561016c57600080fd5b506101b1600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390505050610fa4565b005b3480156101bf57600080fd5b50610211600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803560ff1690602001909291905050506114f5565b005b34801561021f57600080fd5b50610271600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803560ff169060200190929190505050611b89565b005b34801561027f57600080fd5b5061028861221e565b005b34801561029657600080fd5b5061029f612320565b6040518082815260200191505060405180910390f35b3480156102c157600080fd5b506102ee60048036038101908080359060200190820180359060200191909192939192939050505061232d565b604051808060200187600381111561030257fe5b60ff16815260200186600481111561031657fe5b60ff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184151515158152602001838152602001828103825288818151815260200191508051906020019080838360005b8381101561039857808201518184015260208101905061037d565b50505050905090810190601f1680156103c55780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b3480156103e457600080fd5b5061042960048036038101908080359060200190820180359060200191909192939192939080359060200190820180359060200191909192939192939050505061261e565b604051808060200187600381111561043d57fe5b60ff16815260200186600481111561045157fe5b60ff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184151515158152602001838152602001828103825288818151815260200191508051906020019080838360005b838110156104d35780820151818401526020810190506104b8565b50505050905090810190601f1680156105005780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b34801561051f57600080fd5b5061052861278a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561057657600080fd5b50610595600480360381019080803590602001909291905050506127af565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156105d55780820151818401526020810190506105ba565b50505050905090810190601f1680156106025780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561061c57600080fd5b50610677600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061286a565b005b34801561068557600080fd5b506106bc60048036038101908080359060200190820180359060200191909192939192939080359060200190929190505050612aca565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106fc5780820151818401526020810190506106e1565b50505050905090810190601f1680156107295780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561074357600080fd5b50610788600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390505050612baa565b005b34801561079657600080fd5b506107cb600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506132bd565b005b3480156107d957600080fd5b50610806600480360381019080803590602001908201803590602001919091929391929390505050613324565b6040518082815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561087757600080fd5b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515610943576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f5468652070726f7669646564206164647265737320697320612030206164647281526020017f657373000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6000858590501115156109be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f456d70747920737472696e67207061737365642061732076657273696f6e000081525060200191505060405180910390fd5b600087879050111515610a5f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f456d70747920737472696e672070617373656420617320636f6e74726163742081526020017f6e616d650000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b610a6882613357565b1515610b02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260358152602001807f43616e6e6f7420736574206120696d706c656d656e746174696f6e20746f206181526020017f206e6f6e2d636f6e74726163742061646472657373000000000000000000000081525060400191505060405180910390fd5b6002878760405180838380828437820191505092505050908152602001604051809103902060009054906101000a900460ff161515610bbc576001878790918060018154018082558091505090600182039060005260206000200160009091929390919293909192909192509190610b7b929190613464565b505060016002888860405180838380828437820191505092505050908152602001604051809103902060006101000a81548160ff0219169083151502179055505b600073ffffffffffffffffffffffffffffffffffffffff1660048888604051808383808284378201915050925050509081526020016040518091039020868660405180838380828437820191505092505050908152602001604051809103902060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610cf1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f56657273696f6e20616c72656164792065786973747320666f7220636f6e747281526020017f616374000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60038787604051808383808284378201915050925050509081526020016040518091039020858590918060018154018082558091505090600182039060005260206000200160009091929390919293909192909192509190610d54929190613464565b505060c06040519081016040528086868080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050508152602001846003811115610da657fe5b815260200160006004811115610db857fe5b81526020018373ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001428152506004888860405180838380828437820191505092505050908152602001604051809103902086866040518083838082843782019150509250505090815260200160405180910390206000820151816000019080519060200190610e4a9291906134e4565b5060208201518160010160006101000a81548160ff02191690836003811115610e6f57fe5b021790555060408201518160010160016101000a81548160ff02191690836004811115610e9857fe5b021790555060608201518160010160026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160010160166101000a81548160ff02191690831515021790555060a082015181600201559050508173ffffffffffffffffffffffffffffffffffffffff167f337b109e3f497728f2bdd27545c9ed1cb52ed4a4103cc94da88b868879c982e2888888886040518080602001806020018381038352878782818152602001925080828437820191505083810382528585828181526020019250808284378201915050965050505050505060405180910390a250505050505050565b83838080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506002816040518082805190602001908083835b60208310151561100f5780518252602082019150602081019050602083039250610fea565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff1615156110c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505083838080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050600073ffffffffffffffffffffffffffffffffffffffff166004836040518082805190602001908083835b60208310151561117a5780518252602082019150602081019050602083039250611155565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020826040518082805190602001908083835b6020831015156111e357805182526020820191506020810190506020830392506111be565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515156112ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f56657273696f6e20646f6573206e6f742065786973747320666f7220636f6e7481526020017f726163740000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561134757600080fd5b60048787604051808383808284378201915050925050509081526020016040518091039020858560405180838380828437820191505092505050908152602001604051809103902060010160169054906101000a900460ff16151515611415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f56657273696f6e20697320616c7265616479206175646974656400000000000081525060200191505060405180910390fd5b600160048888604051808383808284378201915050925050509081526020016040518091039020868660405180838380828437820191505092505050908152602001604051809103902060010160166101000a81548160ff0219169083151502179055507fdd2996df4158c05ae76d843c929d03eadde75cf3580d1d2f996375ea6cbe9625878787876040518080602001806020018381038352878782818152602001925080828437820191505083810382528585828181526020019250808284378201915050965050505050505060405180910390a150505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561155257600080fd5b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506002816040518082805190602001908083835b6020831015156115bd5780518252602082019150602081019050602083039250611598565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff161515611672576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b86868080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505085858080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050600073ffffffffffffffffffffffffffffffffffffffff166004836040518082805190602001908083835b6020831015156117285780518252602082019150602081019050602083039250611703565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020826040518082805190602001908083835b602083101515611791578051825260208201915060208101905060208303925061176c565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561189a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f56657273696f6e20646f6573206e6f742065786973747320666f7220636f6e7481526020017f726163740000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6005898960405180838380828437820191505092505050908152602001604051809103902093508686604051602001808383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b60208310151561191d57805182526020820191506020810190506020830392506118f8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019168460405160200180828054600181600116156101000203166002900480156119ad5780601f1061198b5761010080835404028352918201916119ad565b820191906000526020600020905b815481529060010190602001808311611999575b50509150506040516020818303038152906040526040518082805190602001908083835b6020831015156119f657805182526020820191506020810190506020830392506119d1565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916148015611a495750600380811115611a3b57fe5b856003811115611a4757fe5b145b15611a8a57611a8989898080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061286a565b5b8460048a8a604051808383808284378201915050925050509081526020016040518091039020888860405180838380828437820191505092505050908152602001604051809103902060010160006101000a81548160ff02191690836003811115611af157fe5b02179055507ea1d2d212fdb196f10c2b940b5f032473f79d8fcf0739ae900d5767500213878989898989604051808060200180602001846003811115611b3357fe5b60ff168152602001838103835288888281815260200192508082843782019150508381038252868682818152602001925080828437820191505097505050505050505060405180910390a1505050505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611be657600080fd5b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506002816040518082805190602001908083835b602083101515611c515780518252602082019150602081019050602083039250611c2c565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff161515611d06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b86868080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505085858080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050600073ffffffffffffffffffffffffffffffffffffffff166004836040518082805190602001908083835b602083101515611dbc5780518252602082019150602081019050602083039250611d97565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020826040518082805190602001908083835b602083101515611e255780518252602082019150602081019050602083039250611e00565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515611f2e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f56657273696f6e20646f6573206e6f742065786973747320666f7220636f6e7481526020017f726163740000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6005898960405180838380828437820191505092505050908152602001604051809103902093508686604051602001808383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b602083101515611fb15780518252602082019150602081019050602083039250611f8c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019168460405160200180828054600181600116156101000203166002900480156120415780601f1061201f576101008083540402835291820191612041565b820191906000526020600020905b81548152906001019060200180831161202d575b50509150506040516020818303038152906040526040518082805190602001908083835b60208310151561208a5780518252602082019150602081019050602083039250612065565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019161480156120dd57506004808111156120cf57fe5b8560048111156120db57fe5b145b1561211e5761211d89898080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061286a565b5b8460048a8a604051808383808284378201915050925050509081526020016040518091039020888860405180838380828437820191505092505050908152602001604051809103902060010160016101000a81548160ff0219169083600481111561218557fe5b02179055507f92d0e6a4dfcd933ffb179b251aa0d734eb16556c0813246989fddaf08a7d009d89898989896040518080602001806020018460048111156121c857fe5b60ff168152602001838103835288888281815260200192508082843782019150508381038252868682818152602001925080828437820191505097505050505050505060405180910390a1505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561227957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482060405160405180910390a260008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600180549050905090565b606060008060008060008088888080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506002816040518082805190602001908083835b6020831015156123a3578051825260208201915060208101905060208303925061237e565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff161515612458576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b60058a8a6040518083838082843782019150509250505090815260200160405180910390208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156125115780601f106124e657610100808354040283529160200191612511565b820191906000526020600020905b8154815290600101906020018083116124f457829003601f168201915b5050505050975060048a8a604051808383808284378201915050925050509081526020016040518091039020886040518082805190602001908083835b602083101515612573578051825260208201915060208101905060208303925061254e565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902091508160010160009054906101000a900460ff1696508160010160019054906101000a900460ff1695508160010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1694508160010160169054906101000a900460ff1693508160020154925050509295509295509295565b606060008060008060008060048b8b60405180838380828437820191505092505050908152602001604051809103902089896040518083838082843782019150509250505090815260200160405180910390209050806000018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561270b5780601f106126e05761010080835404028352916020019161270b565b820191906000526020600020905b8154815290600101906020018083116126ee57829003601f168201915b505050505096508060010160009054906101000a900460ff1695508060010160019054906101000a900460ff1694508060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508060010160169054906101000a900460ff16925080600201549150509499939850945094509450565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606001828154811015156127c057fe5b906000526020600020018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561285e5780601f106128335761010080835404028352916020019161285e565b820191906000526020600020905b81548152906001019060200180831161284157829003601f168201915b50505050509050919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156128c557600080fd5b806002816040518082805190602001908083835b6020831015156128fe57805182526020820191506020810190506020830392506128d9565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff1615156129b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b6005826040518082805190602001908083835b6020831015156129eb57805182526020820191506020810190506020830392506129c6565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390206000612a2a9190613564565b7f07b20feb74e0118ee3c73d4cb8d0eb4da169604c68aa233293b094cedcd225f2826040518080602001828103825283818151815260200191508051906020019080838360005b83811015612a8c578082015181840152602081019050612a71565b50505050905090810190601f168015612ab95780820380516001836020036101000a031916815260200191505b509250505060405180910390a15050565b60606003848460405180838380828437820191505092505050908152602001604051809103902082815481101515612afe57fe5b906000526020600020018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015612b9c5780601f10612b7157610100808354040283529160200191612b9c565b820191906000526020600020905b815481529060010190602001808311612b7f57829003601f168201915b505050505090509392505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612c0557600080fd5b83838080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506002816040518082805190602001908083835b602083101515612c705780518252602082019150602081019050602083039250612c4b565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff161515612d25576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505083838080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050600073ffffffffffffffffffffffffffffffffffffffff166004836040518082805190602001908083835b602083101515612ddb5780518252602082019150602081019050602083039250612db6565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020826040518082805190602001908083835b602083101515612e445780518252602082019150602081019050602083039250612e1f565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515612f4d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f56657273696f6e20646f6573206e6f742065786973747320666f7220636f6e7481526020017f726163740000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60026003811115612f5a57fe5b60048888604051808383808284378201915050925050509081526020016040518091039020868660405180838380828437820191505092505050908152602001604051809103902060010160009054906101000a900460ff166003811115612fbe57fe5b141515613033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f56657273696f6e206e6f7420696e2070726f64756374696f6e2073746174650081525060200191505060405180910390fd5b60048787604051808383808284378201915050925050509081526020016040518091039020858560405180838380828437820191505092505050908152602001604051809103902060010160169054906101000a900460ff161515613100576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f56657273696f6e206973206e6f7420617564697465640000000000000000000081525060200191505060405180910390fd5b6003600481111561310d57fe5b60048888604051808383808284378201915050925050509081526020016040518091039020868660405180838380828437820191505092505050908152602001604051809103902060010160019054906101000a900460ff16600481111561317157fe5b10151561320c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f56657273696f6e20627567206c6576656c206973206e6f74206c6f776572207481526020017f68616e204849474800000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b8484600589896040518083838082843782019150509250505090815260200160405180910390209190613240929190613464565b507fb318550bf93edf51de4bae84db3deabd2a866cc407435a72317ca2503e2a07a6878787876040518080602001806020018381038352878782818152602001925080828437820191505083810382528585828181526020019250808284378201915050965050505050505060405180910390a150505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561331857600080fd5b6133218161336a565b50565b60006003838360405180838380828437820191505092505050908152602001604051809103902080549050905092915050565b600080823b905060008111915050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156133a657600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106134a557803560ff19168380011785556134d3565b828001600101855582156134d3579182015b828111156134d25782358255916020019190600101906134b7565b5b5090506134e091906135ac565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061352557805160ff1916838001178555613553565b82800160010185558215613553579182015b82811115613552578251825591602001919060010190613537565b5b50905061356091906135ac565b5090565b50805460018160011615610100020316600290046000825580601f1061358a57506135a9565b601f0160209004906000526020600020908101906135a891906135ac565b5b50565b6135ce91905b808211156135ca5760008160009055506001016135b2565b5090565b905600a165627a7a7230582043411908fd47ba5100d08696f88c2559a9f9c245c1d1214333c3824d4527f6250029 - -======= openzeppelin-solidity/contracts/AddressUtils.sol:AddressUtils ======= -604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820b82b9f028858f246861a7afebcfd2e199244bb9fb4819d8b1fa3d058c41b125e0029 +const RegistryBin = `6080604052336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612460806100536000396000f3006080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633de5311a146100ca5780635c047fa21461014a578063715018a6146101b7578063751f592b146101ce5780637e27634e146101f95780638ad030c1146103115780638da5cb5b146104415780639b534f1814610498578063acd820a81461053e578063af2c7fa314610579578063ca2e7cf314610637578063f2fde38b1461068a578063ff93dab4146106cd575b600080fd5b3480156100d657600080fd5b50610148600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061071c565b005b34801561015657600080fd5b506101b5600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803560ff169060200190929190803560ff169060200190929190505050610e7b565b005b3480156101c357600080fd5b506101cc6113a0565b005b3480156101da57600080fd5b506101e36114a2565b6040518082815260200191505060405180910390f35b34801561020557600080fd5b506102326004803603810190808035906020019082018035906020019190919293919293905050506114b2565b604051808060200186600381111561024657fe5b60ff16815260200185600481111561025a57fe5b60ff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828103825287818151815260200191508051906020019080838360005b838110156102d25780820151818401526020810190506102b7565b50505050905090810190601f1680156102ff5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b34801561031d57600080fd5b5061036260048036038101908080359060200190820180359060200191909192939192939080359060200190820180359060200191909192939192939050505061179d565b604051808060200186600381111561037657fe5b60ff16815260200185600481111561038a57fe5b60ff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828103825287818151815260200191508051906020019080838360005b838110156104025780820151818401526020810190506103e7565b50505050905090810190601f16801561042f5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b34801561044d57600080fd5b50610456611901565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104a457600080fd5b506104c360048036038101908080359060200190929190505050611926565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156105035780820151818401526020810190506104e8565b50505050905090810190601f1680156105305780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561054a57600080fd5b506105776004803603810190808035906020019082018035906020019190919293919293905050506119e4565b005b34801561058557600080fd5b506105bc60048036038101908080359060200190820180359060200191909192939192939080359060200190929190505050611be6565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156105fc5780820151818401526020810190506105e1565b50505050905090810190601f1680156106295780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561064357600080fd5b50610688600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390505050611cc9565b005b34801561069657600080fd5b506106cb600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061211d565b005b3480156106d957600080fd5b50610706600480360381019080803590602001908201803590602001919091929391929390505050612184565b6040518082815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561077757600080fd5b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515610843576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f5468652070726f7669646564206164647265737320697320746865203020616481526020017f647265737300000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6000858590501115156108be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f456d70747920737472696e67207061737365642061732076657273696f6e000081525060200191505060405180910390fd5b60008787905011151561095f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f456d70747920737472696e672070617373656420617320636f6e74726163742081526020017f6e616d650000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b610968826121ba565b1515610a02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001807f43616e6e6f742073657420616e20696d706c656d656e746174696f6e20746f2081526020017f61206e6f6e2d636f6e747261637420616464726573730000000000000000000081525060400191505060405180910390fd5b6002878760405180838380828437820191505092505050908152602001604051809103902060009054906101000a900460ff161515610abc576001878790918060018154018082558091505090600182039060005260206000200160009091929390919293909192909192509190610a7b9291906122c7565b505060016002888860405180838380828437820191505092505050908152602001604051809103902060006101000a81548160ff0219169083151502179055505b600073ffffffffffffffffffffffffffffffffffffffff1660048888604051808383808284378201915050925050509081526020016040518091039020868660405180838380828437820191505092505050908152602001604051809103902060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610bf1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f56657273696f6e20616c72656164792065786973747320666f7220636f6e747281526020017f616374000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60038787604051808383808284378201915050925050509081526020016040518091039020858590918060018154018082558091505090600182039060005260206000200160009091929390919293909192909192509190610c549291906122c7565b505060a06040519081016040528086868080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050508152602001846003811115610ca657fe5b815260200160006004811115610cb857fe5b81526020018373ffffffffffffffffffffffffffffffffffffffff168152602001428152506004888860405180838380828437820191505092505050908152602001604051809103902086866040518083838082843782019150509250505090815260200160405180910390206000820151816000019080519060200190610d41929190612347565b5060208201518160010160006101000a81548160ff02191690836003811115610d6657fe5b021790555060408201518160010160016101000a81548160ff02191690836004811115610d8f57fe5b021790555060608201518160010160026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550608082015181600201559050508173ffffffffffffffffffffffffffffffffffffffff167f337b109e3f497728f2bdd27545c9ed1cb52ed4a4103cc94da88b868879c982e2888888886040518080602001806020018381038352878782818152602001925080828437820191505083810382528585828181526020019250808284378201915050965050505050505060405180910390a250505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ed657600080fd5b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506002816040518082805190602001908083835b602083101515610f415780518252602082019150602081019050602083039250610f1c565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff161515610ff6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b86868080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505085858080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050600073ffffffffffffffffffffffffffffffffffffffff166004836040518082805190602001908083835b6020831015156110ac5780518252602082019150602081019050602083039250611087565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020826040518082805190602001908083835b60208310151561111557805182526020820191506020810190506020830392506110f0565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561121e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f56657273696f6e20646f6573206e6f742065786973747320666f7220636f6e7481526020017f726163740000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b8460048a8a604051808383808284378201915050925050509081526020016040518091039020888860405180838380828437820191505092505050908152602001604051809103902060010160006101000a81548160ff0219169083600381111561128557fe5b02179055508360048a8a604051808383808284378201915050925050509081526020016040518091039020888860405180838380828437820191505092505050908152602001604051809103902060010160016101000a81548160ff021916908360048111156112f157fe5b02179055507f0acf3e1a00b57bfc05ebf65957f42293847dc0938bfa1744660d6df56036d75189898989898960405180806020018060200185600381111561133557fe5b60ff16815260200184600481111561134957fe5b60ff16815260200183810383528989828181526020019250808284378201915050838103825287878281815260200192508082843782019150509850505050505050505060405180910390a1505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113fb57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482060405160405180910390a260008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600180549050905080905090565b6060600080600080600087878080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506002816040518082805190602001908083835b6020831015156115275780518252602082019150602081019050602083039250611502565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff1615156115dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b600589896040518083838082843782019150509250505090815260200160405180910390208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156116955780601f1061166a57610100808354040283529160200191611695565b820191906000526020600020905b81548152906001019060200180831161167857829003601f168201915b5050505050965060048989604051808383808284378201915050925050509081526020016040518091039020876040518082805190602001908083835b6020831015156116f757805182526020820191506020810190506020830392506116d2565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902091508160010160009054906101000a900460ff1695508160010160019054906101000a900460ff1694508160010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508160020154925086868686869650965096509650965050509295509295909350565b6060600080600080600060048a8a60405180838380828437820191505092505050908152602001604051809103902088886040518083838082843782019150509250505090815260200160405180910390209050806000018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156118895780601f1061185e57610100808354040283529160200191611889565b820191906000526020600020905b81548152906001019060200180831161186c57829003601f168201915b505050505095508060010160009054906101000a900460ff1694508060010160019054906101000a900460ff1693508060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692508060020154915085858585859550955095509550955050945094509450945094565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606060018281548110151561193757fe5b906000526020600020018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156119d55780601f106119aa576101008083540402835291602001916119d5565b820191906000526020600020905b8154815290600101906020018083116119b857829003601f168201915b50505050509050809050919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611a3f57600080fd5b81818080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506002816040518082805190602001908083835b602083101515611aaa5780518252602082019150602081019050602083039250611a85565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff161515611b5f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b600583836040518083838082843782019150509250505090815260200160405180910390206000611b9091906123c7565b7f07b20feb74e0118ee3c73d4cb8d0eb4da169604c68aa233293b094cedcd225f28383604051808060200182810382528484828181526020019250808284378201915050935050505060405180910390a1505050565b60606003848460405180838380828437820191505092505050908152602001604051809103902082815481101515611c1a57fe5b906000526020600020018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611cb85780601f10611c8d57610100808354040283529160200191611cb8565b820191906000526020600020905b815481529060010190602001808311611c9b57829003601f168201915b505050505090508090509392505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611d2457600080fd5b83838080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506002816040518082805190602001908083835b602083101515611d8f5780518252602082019150602081019050602083039250611d6a565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a900460ff161515611e44576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f436f6e747261637420646f6573206e6f7420657869737473000000000000000081525060200191505060405180910390fd5b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505083838080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050600073ffffffffffffffffffffffffffffffffffffffff166004836040518082805190602001908083835b602083101515611efa5780518252602082019150602081019050602083039250611ed5565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020826040518082805190602001908083835b602083101515611f635780518252602082019150602081019050602083039250611f3e565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561206c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f56657273696f6e20646f6573206e6f742065786973747320666f7220636f6e7481526020017f726163740000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b84846005898960405180838380828437820191505092505050908152602001604051809103902091906120a09291906122c7565b507fb318550bf93edf51de4bae84db3deabd2a866cc407435a72317ca2503e2a07a6878787876040518080602001806020018381038352878782818152602001925080828437820191505083810382528585828181526020019250808284378201915050965050505050505060405180910390a150505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561217857600080fd5b612181816121cd565b50565b60006003838360405180838380828437820191505092505050908152602001604051809103902080549050905080905092915050565b600080823b905060008111915050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561220957600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061230857803560ff1916838001178555612336565b82800160010185558215612336579182015b8281111561233557823582559160200191906001019061231a565b5b509050612343919061240f565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061238857805160ff19168380011785556123b6565b828001600101855582156123b6579182015b828111156123b557825182559160200191906001019061239a565b5b5090506123c3919061240f565b5090565b50805460018160011615610100020316600290046000825580601f106123ed575061240c565b601f01602090049060005260206000209081019061240b919061240f565b5b50565b61243191905b8082111561242d576000816000905550600101612415565b5090565b905600a165627a7a723058202e2b25c5a471a67687142064b12a7bce9573e8ae12b645365a9c6215707bc07d0029 ======= openzeppelin-solidity/contracts/ownership/Ownable.sol:Ownable ======= -608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506103c1806100606000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063715018a61461005c5780638da5cb5b14610073578063f2fde38b146100ca575b600080fd5b34801561006857600080fd5b5061007161010d565b005b34801561007f57600080fd5b5061008861020f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100d657600080fd5b5061010b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610234565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561016857600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482060405160405180910390a260008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561028f57600080fd5b6102988161029b565b50565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156102d757600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505600a165627a7a7230582077e73d4b401459c2c062401742582a44912b8b235987c864fea6d190a5b48b600029` +608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506103c1806100606000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063715018a61461005c5780638da5cb5b14610073578063f2fde38b146100ca575b600080fd5b34801561006857600080fd5b5061007161010d565b005b34801561007f57600080fd5b5061008861020f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100d657600080fd5b5061010b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610234565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561016857600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482060405160405180910390a260008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561028f57600080fd5b6102988161029b565b50565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156102d757600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505600a165627a7a7230582077e73d4b401459c2c062401742582a44912b8b235987c864fea6d190a5b48b600029 + +======= openzeppelin-solidity/contracts/utils/Address.sol:Address ======= +604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a7230582083c43d1ee71d56e3cc73e85663e5bb2db836c108d53796dbcefd5ffb60903be10029` // DeployRegistry deploys a new Ethereum contract, binding an instance of Registry to it. func DeployRegistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Registry, error) { @@ -184,7 +196,7 @@ func (_Registry *RegistryTransactorRaw) Transact(opts *bind.TransactOpts, method // GetContractAtIndex is a free data retrieval call binding the contract method 0x9b534f18. // -// Solidity: function getContractAtIndex(index uint256) constant returns(contractName string) +// Solidity: function getContractAtIndex(uint256 index) constant returns(string contractName) func (_Registry *RegistryCaller) GetContractAtIndex(opts *bind.CallOpts, index *big.Int) (string, error) { var ( ret0 = new(string) @@ -196,27 +208,26 @@ func (_Registry *RegistryCaller) GetContractAtIndex(opts *bind.CallOpts, index * // GetContractAtIndex is a free data retrieval call binding the contract method 0x9b534f18. // -// Solidity: function getContractAtIndex(index uint256) constant returns(contractName string) +// Solidity: function getContractAtIndex(uint256 index) constant returns(string contractName) func (_Registry *RegistrySession) GetContractAtIndex(index *big.Int) (string, error) { return _Registry.Contract.GetContractAtIndex(&_Registry.CallOpts, index) } // GetContractAtIndex is a free data retrieval call binding the contract method 0x9b534f18. // -// Solidity: function getContractAtIndex(index uint256) constant returns(contractName string) +// Solidity: function getContractAtIndex(uint256 index) constant returns(string contractName) func (_Registry *RegistryCallerSession) GetContractAtIndex(index *big.Int) (string, error) { return _Registry.Contract.GetContractAtIndex(&_Registry.CallOpts, index) } // GetRecommendedVersion is a free data retrieval call binding the contract method 0x7e27634e. // -// Solidity: function getRecommendedVersion(contractName string) constant returns(versionName string, status uint8, bugLevel uint8, implementation address, audited bool, dateAdded uint256) +// Solidity: function getRecommendedVersion(string contractName) constant returns(string versionName, uint8 status, uint8 bugLevel, address implementation, uint256 dateAdded) func (_Registry *RegistryCaller) GetRecommendedVersion(opts *bind.CallOpts, contractName string) (struct { VersionName string Status uint8 BugLevel uint8 Implementation common.Address - Audited bool DateAdded *big.Int }, error) { ret := new(struct { @@ -224,7 +235,6 @@ func (_Registry *RegistryCaller) GetRecommendedVersion(opts *bind.CallOpts, cont Status uint8 BugLevel uint8 Implementation common.Address - Audited bool DateAdded *big.Int }) out := ret @@ -234,13 +244,12 @@ func (_Registry *RegistryCaller) GetRecommendedVersion(opts *bind.CallOpts, cont // GetRecommendedVersion is a free data retrieval call binding the contract method 0x7e27634e. // -// Solidity: function getRecommendedVersion(contractName string) constant returns(versionName string, status uint8, bugLevel uint8, implementation address, audited bool, dateAdded uint256) +// Solidity: function getRecommendedVersion(string contractName) constant returns(string versionName, uint8 status, uint8 bugLevel, address implementation, uint256 dateAdded) func (_Registry *RegistrySession) GetRecommendedVersion(contractName string) (struct { VersionName string Status uint8 BugLevel uint8 Implementation common.Address - Audited bool DateAdded *big.Int }, error) { return _Registry.Contract.GetRecommendedVersion(&_Registry.CallOpts, contractName) @@ -248,13 +257,12 @@ func (_Registry *RegistrySession) GetRecommendedVersion(contractName string) (st // GetRecommendedVersion is a free data retrieval call binding the contract method 0x7e27634e. // -// Solidity: function getRecommendedVersion(contractName string) constant returns(versionName string, status uint8, bugLevel uint8, implementation address, audited bool, dateAdded uint256) +// Solidity: function getRecommendedVersion(string contractName) constant returns(string versionName, uint8 status, uint8 bugLevel, address implementation, uint256 dateAdded) func (_Registry *RegistryCallerSession) GetRecommendedVersion(contractName string) (struct { VersionName string Status uint8 BugLevel uint8 Implementation common.Address - Audited bool DateAdded *big.Int }, error) { return _Registry.Contract.GetRecommendedVersion(&_Registry.CallOpts, contractName) @@ -262,7 +270,7 @@ func (_Registry *RegistryCallerSession) GetRecommendedVersion(contractName strin // GetTotalContractCount is a free data retrieval call binding the contract method 0x751f592b. // -// Solidity: function getTotalContractCount() constant returns(count uint256) +// Solidity: function getTotalContractCount() constant returns(uint256 count) func (_Registry *RegistryCaller) GetTotalContractCount(opts *bind.CallOpts) (*big.Int, error) { var ( ret0 = new(*big.Int) @@ -274,21 +282,21 @@ func (_Registry *RegistryCaller) GetTotalContractCount(opts *bind.CallOpts) (*bi // GetTotalContractCount is a free data retrieval call binding the contract method 0x751f592b. // -// Solidity: function getTotalContractCount() constant returns(count uint256) +// Solidity: function getTotalContractCount() constant returns(uint256 count) func (_Registry *RegistrySession) GetTotalContractCount() (*big.Int, error) { return _Registry.Contract.GetTotalContractCount(&_Registry.CallOpts) } // GetTotalContractCount is a free data retrieval call binding the contract method 0x751f592b. // -// Solidity: function getTotalContractCount() constant returns(count uint256) +// Solidity: function getTotalContractCount() constant returns(uint256 count) func (_Registry *RegistryCallerSession) GetTotalContractCount() (*big.Int, error) { return _Registry.Contract.GetTotalContractCount(&_Registry.CallOpts) } // GetVersionAtIndex is a free data retrieval call binding the contract method 0xaf2c7fa3. // -// Solidity: function getVersionAtIndex(contractName string, index uint256) constant returns(versionName string) +// Solidity: function getVersionAtIndex(string contractName, uint256 index) constant returns(string versionName) func (_Registry *RegistryCaller) GetVersionAtIndex(opts *bind.CallOpts, contractName string, index *big.Int) (string, error) { var ( ret0 = new(string) @@ -300,21 +308,21 @@ func (_Registry *RegistryCaller) GetVersionAtIndex(opts *bind.CallOpts, contract // GetVersionAtIndex is a free data retrieval call binding the contract method 0xaf2c7fa3. // -// Solidity: function getVersionAtIndex(contractName string, index uint256) constant returns(versionName string) +// Solidity: function getVersionAtIndex(string contractName, uint256 index) constant returns(string versionName) func (_Registry *RegistrySession) GetVersionAtIndex(contractName string, index *big.Int) (string, error) { return _Registry.Contract.GetVersionAtIndex(&_Registry.CallOpts, contractName, index) } // GetVersionAtIndex is a free data retrieval call binding the contract method 0xaf2c7fa3. // -// Solidity: function getVersionAtIndex(contractName string, index uint256) constant returns(versionName string) +// Solidity: function getVersionAtIndex(string contractName, uint256 index) constant returns(string versionName) func (_Registry *RegistryCallerSession) GetVersionAtIndex(contractName string, index *big.Int) (string, error) { return _Registry.Contract.GetVersionAtIndex(&_Registry.CallOpts, contractName, index) } // GetVersionCountForContract is a free data retrieval call binding the contract method 0xff93dab4. // -// Solidity: function getVersionCountForContract(contractName string) constant returns(count uint256) +// Solidity: function getVersionCountForContract(string contractName) constant returns(uint256 count) func (_Registry *RegistryCaller) GetVersionCountForContract(opts *bind.CallOpts, contractName string) (*big.Int, error) { var ( ret0 = new(*big.Int) @@ -326,27 +334,26 @@ func (_Registry *RegistryCaller) GetVersionCountForContract(opts *bind.CallOpts, // GetVersionCountForContract is a free data retrieval call binding the contract method 0xff93dab4. // -// Solidity: function getVersionCountForContract(contractName string) constant returns(count uint256) +// Solidity: function getVersionCountForContract(string contractName) constant returns(uint256 count) func (_Registry *RegistrySession) GetVersionCountForContract(contractName string) (*big.Int, error) { return _Registry.Contract.GetVersionCountForContract(&_Registry.CallOpts, contractName) } // GetVersionCountForContract is a free data retrieval call binding the contract method 0xff93dab4. // -// Solidity: function getVersionCountForContract(contractName string) constant returns(count uint256) +// Solidity: function getVersionCountForContract(string contractName) constant returns(uint256 count) func (_Registry *RegistryCallerSession) GetVersionCountForContract(contractName string) (*big.Int, error) { return _Registry.Contract.GetVersionCountForContract(&_Registry.CallOpts, contractName) } // GetVersionDetails is a free data retrieval call binding the contract method 0x8ad030c1. // -// Solidity: function getVersionDetails(contractName string, versionName string) constant returns(versionString string, status uint8, bugLevel uint8, implementation address, audited bool, dateAdded uint256) +// Solidity: function getVersionDetails(string contractName, string versionName) constant returns(string versionString, uint8 status, uint8 bugLevel, address implementation, uint256 dateAdded) func (_Registry *RegistryCaller) GetVersionDetails(opts *bind.CallOpts, contractName string, versionName string) (struct { VersionString string Status uint8 BugLevel uint8 Implementation common.Address - Audited bool DateAdded *big.Int }, error) { ret := new(struct { @@ -354,7 +361,6 @@ func (_Registry *RegistryCaller) GetVersionDetails(opts *bind.CallOpts, contract Status uint8 BugLevel uint8 Implementation common.Address - Audited bool DateAdded *big.Int }) out := ret @@ -364,13 +370,12 @@ func (_Registry *RegistryCaller) GetVersionDetails(opts *bind.CallOpts, contract // GetVersionDetails is a free data retrieval call binding the contract method 0x8ad030c1. // -// Solidity: function getVersionDetails(contractName string, versionName string) constant returns(versionString string, status uint8, bugLevel uint8, implementation address, audited bool, dateAdded uint256) +// Solidity: function getVersionDetails(string contractName, string versionName) constant returns(string versionString, uint8 status, uint8 bugLevel, address implementation, uint256 dateAdded) func (_Registry *RegistrySession) GetVersionDetails(contractName string, versionName string) (struct { VersionString string Status uint8 BugLevel uint8 Implementation common.Address - Audited bool DateAdded *big.Int }, error) { return _Registry.Contract.GetVersionDetails(&_Registry.CallOpts, contractName, versionName) @@ -378,13 +383,12 @@ func (_Registry *RegistrySession) GetVersionDetails(contractName string, version // GetVersionDetails is a free data retrieval call binding the contract method 0x8ad030c1. // -// Solidity: function getVersionDetails(contractName string, versionName string) constant returns(versionString string, status uint8, bugLevel uint8, implementation address, audited bool, dateAdded uint256) +// Solidity: function getVersionDetails(string contractName, string versionName) constant returns(string versionString, uint8 status, uint8 bugLevel, address implementation, uint256 dateAdded) func (_Registry *RegistryCallerSession) GetVersionDetails(contractName string, versionName string) (struct { VersionString string Status uint8 BugLevel uint8 Implementation common.Address - Audited bool DateAdded *big.Int }, error) { return _Registry.Contract.GetVersionDetails(&_Registry.CallOpts, contractName, versionName) @@ -418,126 +422,63 @@ func (_Registry *RegistryCallerSession) Owner() (common.Address, error) { // AddVersion is a paid mutator transaction binding the contract method 0x3de5311a. // -// Solidity: function addVersion(contractName string, versionName string, status uint8, _implementation address) returns() -func (_Registry *RegistryTransactor) AddVersion(opts *bind.TransactOpts, contractName string, versionName string, status uint8, _implementation common.Address) (*types.Transaction, error) { - return _Registry.contract.Transact(opts, "addVersion", contractName, versionName, status, _implementation) +// Solidity: function addVersion(string contractName, string versionName, uint8 status, address implementation) returns() +func (_Registry *RegistryTransactor) AddVersion(opts *bind.TransactOpts, contractName string, versionName string, status uint8, implementation common.Address) (*types.Transaction, error) { + return _Registry.contract.Transact(opts, "addVersion", contractName, versionName, status, implementation) } // AddVersion is a paid mutator transaction binding the contract method 0x3de5311a. // -// Solidity: function addVersion(contractName string, versionName string, status uint8, _implementation address) returns() -func (_Registry *RegistrySession) AddVersion(contractName string, versionName string, status uint8, _implementation common.Address) (*types.Transaction, error) { - return _Registry.Contract.AddVersion(&_Registry.TransactOpts, contractName, versionName, status, _implementation) +// Solidity: function addVersion(string contractName, string versionName, uint8 status, address implementation) returns() +func (_Registry *RegistrySession) AddVersion(contractName string, versionName string, status uint8, implementation common.Address) (*types.Transaction, error) { + return _Registry.Contract.AddVersion(&_Registry.TransactOpts, contractName, versionName, status, implementation) } // AddVersion is a paid mutator transaction binding the contract method 0x3de5311a. // -// Solidity: function addVersion(contractName string, versionName string, status uint8, _implementation address) returns() -func (_Registry *RegistryTransactorSession) AddVersion(contractName string, versionName string, status uint8, _implementation common.Address) (*types.Transaction, error) { - return _Registry.Contract.AddVersion(&_Registry.TransactOpts, contractName, versionName, status, _implementation) -} - -// ChangeBugLevel is a paid mutator transaction binding the contract method 0x568d1ee8. -// -// Solidity: function changeBugLevel(contractName string, versionName string, bugLevel uint8) returns() -func (_Registry *RegistryTransactor) ChangeBugLevel(opts *bind.TransactOpts, contractName string, versionName string, bugLevel uint8) (*types.Transaction, error) { - return _Registry.contract.Transact(opts, "changeBugLevel", contractName, versionName, bugLevel) -} - -// ChangeBugLevel is a paid mutator transaction binding the contract method 0x568d1ee8. -// -// Solidity: function changeBugLevel(contractName string, versionName string, bugLevel uint8) returns() -func (_Registry *RegistrySession) ChangeBugLevel(contractName string, versionName string, bugLevel uint8) (*types.Transaction, error) { - return _Registry.Contract.ChangeBugLevel(&_Registry.TransactOpts, contractName, versionName, bugLevel) -} - -// ChangeBugLevel is a paid mutator transaction binding the contract method 0x568d1ee8. -// -// Solidity: function changeBugLevel(contractName string, versionName string, bugLevel uint8) returns() -func (_Registry *RegistryTransactorSession) ChangeBugLevel(contractName string, versionName string, bugLevel uint8) (*types.Transaction, error) { - return _Registry.Contract.ChangeBugLevel(&_Registry.TransactOpts, contractName, versionName, bugLevel) -} - -// ChangeStatus is a paid mutator transaction binding the contract method 0x4890b0c5. -// -// Solidity: function changeStatus(contractName string, versionName string, status uint8) returns() -func (_Registry *RegistryTransactor) ChangeStatus(opts *bind.TransactOpts, contractName string, versionName string, status uint8) (*types.Transaction, error) { - return _Registry.contract.Transact(opts, "changeStatus", contractName, versionName, status) -} - -// ChangeStatus is a paid mutator transaction binding the contract method 0x4890b0c5. -// -// Solidity: function changeStatus(contractName string, versionName string, status uint8) returns() -func (_Registry *RegistrySession) ChangeStatus(contractName string, versionName string, status uint8) (*types.Transaction, error) { - return _Registry.Contract.ChangeStatus(&_Registry.TransactOpts, contractName, versionName, status) -} - -// ChangeStatus is a paid mutator transaction binding the contract method 0x4890b0c5. -// -// Solidity: function changeStatus(contractName string, versionName string, status uint8) returns() -func (_Registry *RegistryTransactorSession) ChangeStatus(contractName string, versionName string, status uint8) (*types.Transaction, error) { - return _Registry.Contract.ChangeStatus(&_Registry.TransactOpts, contractName, versionName, status) +// Solidity: function addVersion(string contractName, string versionName, uint8 status, address implementation) returns() +func (_Registry *RegistryTransactorSession) AddVersion(contractName string, versionName string, status uint8, implementation common.Address) (*types.Transaction, error) { + return _Registry.Contract.AddVersion(&_Registry.TransactOpts, contractName, versionName, status, implementation) } // MarkRecommendedVersion is a paid mutator transaction binding the contract method 0xca2e7cf3. // -// Solidity: function markRecommendedVersion(contractName string, versionName string) returns() +// Solidity: function markRecommendedVersion(string contractName, string versionName) returns() func (_Registry *RegistryTransactor) MarkRecommendedVersion(opts *bind.TransactOpts, contractName string, versionName string) (*types.Transaction, error) { return _Registry.contract.Transact(opts, "markRecommendedVersion", contractName, versionName) } // MarkRecommendedVersion is a paid mutator transaction binding the contract method 0xca2e7cf3. // -// Solidity: function markRecommendedVersion(contractName string, versionName string) returns() +// Solidity: function markRecommendedVersion(string contractName, string versionName) returns() func (_Registry *RegistrySession) MarkRecommendedVersion(contractName string, versionName string) (*types.Transaction, error) { return _Registry.Contract.MarkRecommendedVersion(&_Registry.TransactOpts, contractName, versionName) } // MarkRecommendedVersion is a paid mutator transaction binding the contract method 0xca2e7cf3. // -// Solidity: function markRecommendedVersion(contractName string, versionName string) returns() +// Solidity: function markRecommendedVersion(string contractName, string versionName) returns() func (_Registry *RegistryTransactorSession) MarkRecommendedVersion(contractName string, versionName string) (*types.Transaction, error) { return _Registry.Contract.MarkRecommendedVersion(&_Registry.TransactOpts, contractName, versionName) } -// MarkVersionAudited is a paid mutator transaction binding the contract method 0x437fe3a3. -// -// Solidity: function markVersionAudited(contractName string, versionName string) returns() -func (_Registry *RegistryTransactor) MarkVersionAudited(opts *bind.TransactOpts, contractName string, versionName string) (*types.Transaction, error) { - return _Registry.contract.Transact(opts, "markVersionAudited", contractName, versionName) -} - -// MarkVersionAudited is a paid mutator transaction binding the contract method 0x437fe3a3. -// -// Solidity: function markVersionAudited(contractName string, versionName string) returns() -func (_Registry *RegistrySession) MarkVersionAudited(contractName string, versionName string) (*types.Transaction, error) { - return _Registry.Contract.MarkVersionAudited(&_Registry.TransactOpts, contractName, versionName) -} - -// MarkVersionAudited is a paid mutator transaction binding the contract method 0x437fe3a3. -// -// Solidity: function markVersionAudited(contractName string, versionName string) returns() -func (_Registry *RegistryTransactorSession) MarkVersionAudited(contractName string, versionName string) (*types.Transaction, error) { - return _Registry.Contract.MarkVersionAudited(&_Registry.TransactOpts, contractName, versionName) -} - // RemoveRecommendedVersion is a paid mutator transaction binding the contract method 0xacd820a8. // -// Solidity: function removeRecommendedVersion(contractName string) returns() +// Solidity: function removeRecommendedVersion(string contractName) returns() func (_Registry *RegistryTransactor) RemoveRecommendedVersion(opts *bind.TransactOpts, contractName string) (*types.Transaction, error) { return _Registry.contract.Transact(opts, "removeRecommendedVersion", contractName) } // RemoveRecommendedVersion is a paid mutator transaction binding the contract method 0xacd820a8. // -// Solidity: function removeRecommendedVersion(contractName string) returns() +// Solidity: function removeRecommendedVersion(string contractName) returns() func (_Registry *RegistrySession) RemoveRecommendedVersion(contractName string) (*types.Transaction, error) { return _Registry.Contract.RemoveRecommendedVersion(&_Registry.TransactOpts, contractName) } // RemoveRecommendedVersion is a paid mutator transaction binding the contract method 0xacd820a8. // -// Solidity: function removeRecommendedVersion(contractName string) returns() +// Solidity: function removeRecommendedVersion(string contractName) returns() func (_Registry *RegistryTransactorSession) RemoveRecommendedVersion(contractName string) (*types.Transaction, error) { return _Registry.Contract.RemoveRecommendedVersion(&_Registry.TransactOpts, contractName) } @@ -565,147 +506,44 @@ func (_Registry *RegistryTransactorSession) RenounceOwnership() (*types.Transact // TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. // -// Solidity: function transferOwnership(_newOwner address) returns() +// Solidity: function transferOwnership(address _newOwner) returns() func (_Registry *RegistryTransactor) TransferOwnership(opts *bind.TransactOpts, _newOwner common.Address) (*types.Transaction, error) { return _Registry.contract.Transact(opts, "transferOwnership", _newOwner) } // TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. // -// Solidity: function transferOwnership(_newOwner address) returns() +// Solidity: function transferOwnership(address _newOwner) returns() func (_Registry *RegistrySession) TransferOwnership(_newOwner common.Address) (*types.Transaction, error) { return _Registry.Contract.TransferOwnership(&_Registry.TransactOpts, _newOwner) } // TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. // -// Solidity: function transferOwnership(_newOwner address) returns() +// Solidity: function transferOwnership(address _newOwner) returns() func (_Registry *RegistryTransactorSession) TransferOwnership(_newOwner common.Address) (*types.Transaction, error) { return _Registry.Contract.TransferOwnership(&_Registry.TransactOpts, _newOwner) } -// RegistryBugLevelChangedIterator is returned from FilterBugLevelChanged and is used to iterate over the raw logs and unpacked data for BugLevelChanged events raised by the Registry contract. -type RegistryBugLevelChangedIterator struct { - Event *RegistryBugLevelChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *RegistryBugLevelChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(RegistryBugLevelChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(RegistryBugLevelChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *RegistryBugLevelChangedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *RegistryBugLevelChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// RegistryBugLevelChanged represents a BugLevelChanged event raised by the Registry contract. -type RegistryBugLevelChanged struct { - ContractName string - VersionName string - BugLevel uint8 - Raw types.Log // Blockchain specific contextual infos +// UpdateVersion is a paid mutator transaction binding the contract method 0x5c047fa2. +// +// Solidity: function updateVersion(string contractName, string versionName, uint8 status, uint8 bugLevel) returns() +func (_Registry *RegistryTransactor) UpdateVersion(opts *bind.TransactOpts, contractName string, versionName string, status uint8, bugLevel uint8) (*types.Transaction, error) { + return _Registry.contract.Transact(opts, "updateVersion", contractName, versionName, status, bugLevel) } -// FilterBugLevelChanged is a free log retrieval operation binding the contract event 0x92d0e6a4dfcd933ffb179b251aa0d734eb16556c0813246989fddaf08a7d009d. +// UpdateVersion is a paid mutator transaction binding the contract method 0x5c047fa2. // -// Solidity: e BugLevelChanged(contractName string, versionName string, bugLevel uint8) -func (_Registry *RegistryFilterer) FilterBugLevelChanged(opts *bind.FilterOpts) (*RegistryBugLevelChangedIterator, error) { - - logs, sub, err := _Registry.contract.FilterLogs(opts, "BugLevelChanged") - if err != nil { - return nil, err - } - return &RegistryBugLevelChangedIterator{contract: _Registry.contract, event: "BugLevelChanged", logs: logs, sub: sub}, nil +// Solidity: function updateVersion(string contractName, string versionName, uint8 status, uint8 bugLevel) returns() +func (_Registry *RegistrySession) UpdateVersion(contractName string, versionName string, status uint8, bugLevel uint8) (*types.Transaction, error) { + return _Registry.Contract.UpdateVersion(&_Registry.TransactOpts, contractName, versionName, status, bugLevel) } -// WatchBugLevelChanged is a free log subscription operation binding the contract event 0x92d0e6a4dfcd933ffb179b251aa0d734eb16556c0813246989fddaf08a7d009d. +// UpdateVersion is a paid mutator transaction binding the contract method 0x5c047fa2. // -// Solidity: e BugLevelChanged(contractName string, versionName string, bugLevel uint8) -func (_Registry *RegistryFilterer) WatchBugLevelChanged(opts *bind.WatchOpts, sink chan<- *RegistryBugLevelChanged) (event.Subscription, error) { - - logs, sub, err := _Registry.contract.WatchLogs(opts, "BugLevelChanged") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(RegistryBugLevelChanged) - if err := _Registry.contract.UnpackLog(event, "BugLevelChanged", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// Solidity: function updateVersion(string contractName, string versionName, uint8 status, uint8 bugLevel) returns() +func (_Registry *RegistryTransactorSession) UpdateVersion(contractName string, versionName string, status uint8, bugLevel uint8) (*types.Transaction, error) { + return _Registry.Contract.UpdateVersion(&_Registry.TransactOpts, contractName, versionName, status, bugLevel) } // RegistryOwnershipRenouncedIterator is returned from FilterOwnershipRenounced and is used to iterate over the raw logs and unpacked data for OwnershipRenounced events raised by the Registry contract. @@ -783,7 +621,7 @@ type RegistryOwnershipRenounced struct { // FilterOwnershipRenounced is a free log retrieval operation binding the contract event 0xf8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c64820. // -// Solidity: e OwnershipRenounced(previousOwner indexed address) +// Solidity: event OwnershipRenounced(address indexed previousOwner) func (_Registry *RegistryFilterer) FilterOwnershipRenounced(opts *bind.FilterOpts, previousOwner []common.Address) (*RegistryOwnershipRenouncedIterator, error) { var previousOwnerRule []interface{} @@ -800,7 +638,7 @@ func (_Registry *RegistryFilterer) FilterOwnershipRenounced(opts *bind.FilterOpt // WatchOwnershipRenounced is a free log subscription operation binding the contract event 0xf8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c64820. // -// Solidity: e OwnershipRenounced(previousOwner indexed address) +// Solidity: event OwnershipRenounced(address indexed previousOwner) func (_Registry *RegistryFilterer) WatchOwnershipRenounced(opts *bind.WatchOpts, sink chan<- *RegistryOwnershipRenounced, previousOwner []common.Address) (event.Subscription, error) { var previousOwnerRule []interface{} @@ -916,7 +754,7 @@ type RegistryOwnershipTransferred struct { // FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. // -// Solidity: e OwnershipTransferred(previousOwner indexed address, newOwner indexed address) +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) func (_Registry *RegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*RegistryOwnershipTransferredIterator, error) { var previousOwnerRule []interface{} @@ -937,7 +775,7 @@ func (_Registry *RegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterO // WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. // -// Solidity: e OwnershipTransferred(previousOwner indexed address, newOwner indexed address) +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) func (_Registry *RegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RegistryOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { var previousOwnerRule []interface{} @@ -1056,7 +894,7 @@ type RegistryRecommendedVersionRemoved struct { // FilterRecommendedVersionRemoved is a free log retrieval operation binding the contract event 0x07b20feb74e0118ee3c73d4cb8d0eb4da169604c68aa233293b094cedcd225f2. // -// Solidity: e RecommendedVersionRemoved(contractName string) +// Solidity: event RecommendedVersionRemoved(string contractName) func (_Registry *RegistryFilterer) FilterRecommendedVersionRemoved(opts *bind.FilterOpts) (*RegistryRecommendedVersionRemovedIterator, error) { logs, sub, err := _Registry.contract.FilterLogs(opts, "RecommendedVersionRemoved") @@ -1068,7 +906,7 @@ func (_Registry *RegistryFilterer) FilterRecommendedVersionRemoved(opts *bind.Fi // WatchRecommendedVersionRemoved is a free log subscription operation binding the contract event 0x07b20feb74e0118ee3c73d4cb8d0eb4da169604c68aa233293b094cedcd225f2. // -// Solidity: e RecommendedVersionRemoved(contractName string) +// Solidity: event RecommendedVersionRemoved(string contractName) func (_Registry *RegistryFilterer) WatchRecommendedVersionRemoved(opts *bind.WatchOpts, sink chan<- *RegistryRecommendedVersionRemoved) (event.Subscription, error) { logs, sub, err := _Registry.contract.WatchLogs(opts, "RecommendedVersionRemoved") @@ -1103,130 +941,6 @@ func (_Registry *RegistryFilterer) WatchRecommendedVersionRemoved(opts *bind.Wat }), nil } -// RegistryStatusChangedIterator is returned from FilterStatusChanged and is used to iterate over the raw logs and unpacked data for StatusChanged events raised by the Registry contract. -type RegistryStatusChangedIterator struct { - Event *RegistryStatusChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *RegistryStatusChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(RegistryStatusChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(RegistryStatusChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *RegistryStatusChangedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *RegistryStatusChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// RegistryStatusChanged represents a StatusChanged event raised by the Registry contract. -type RegistryStatusChanged struct { - ContractName string - VersionName string - Status uint8 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterStatusChanged is a free log retrieval operation binding the contract event 0x00a1d2d212fdb196f10c2b940b5f032473f79d8fcf0739ae900d576750021387. -// -// Solidity: e StatusChanged(contractName string, versionName string, status uint8) -func (_Registry *RegistryFilterer) FilterStatusChanged(opts *bind.FilterOpts) (*RegistryStatusChangedIterator, error) { - - logs, sub, err := _Registry.contract.FilterLogs(opts, "StatusChanged") - if err != nil { - return nil, err - } - return &RegistryStatusChangedIterator{contract: _Registry.contract, event: "StatusChanged", logs: logs, sub: sub}, nil -} - -// WatchStatusChanged is a free log subscription operation binding the contract event 0x00a1d2d212fdb196f10c2b940b5f032473f79d8fcf0739ae900d576750021387. -// -// Solidity: e StatusChanged(contractName string, versionName string, status uint8) -func (_Registry *RegistryFilterer) WatchStatusChanged(opts *bind.WatchOpts, sink chan<- *RegistryStatusChanged) (event.Subscription, error) { - - logs, sub, err := _Registry.contract.WatchLogs(opts, "StatusChanged") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(RegistryStatusChanged) - if err := _Registry.contract.UnpackLog(event, "StatusChanged", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - // RegistryVersionAddedIterator is returned from FilterVersionAdded and is used to iterate over the raw logs and unpacked data for VersionAdded events raised by the Registry contract. type RegistryVersionAddedIterator struct { Event *RegistryVersionAdded // Event containing the contract specifics and raw log @@ -1304,7 +1018,7 @@ type RegistryVersionAdded struct { // FilterVersionAdded is a free log retrieval operation binding the contract event 0x337b109e3f497728f2bdd27545c9ed1cb52ed4a4103cc94da88b868879c982e2. // -// Solidity: e VersionAdded(contractName string, versionName string, implementation indexed address) +// Solidity: event VersionAdded(string contractName, string versionName, address indexed implementation) func (_Registry *RegistryFilterer) FilterVersionAdded(opts *bind.FilterOpts, implementation []common.Address) (*RegistryVersionAddedIterator, error) { var implementationRule []interface{} @@ -1321,7 +1035,7 @@ func (_Registry *RegistryFilterer) FilterVersionAdded(opts *bind.FilterOpts, imp // WatchVersionAdded is a free log subscription operation binding the contract event 0x337b109e3f497728f2bdd27545c9ed1cb52ed4a4103cc94da88b868879c982e2. // -// Solidity: e VersionAdded(contractName string, versionName string, implementation indexed address) +// Solidity: event VersionAdded(string contractName, string versionName, address indexed implementation) func (_Registry *RegistryFilterer) WatchVersionAdded(opts *bind.WatchOpts, sink chan<- *RegistryVersionAdded, implementation []common.Address) (event.Subscription, error) { var implementationRule []interface{} @@ -1361,9 +1075,9 @@ func (_Registry *RegistryFilterer) WatchVersionAdded(opts *bind.WatchOpts, sink }), nil } -// RegistryVersionAuditedIterator is returned from FilterVersionAudited and is used to iterate over the raw logs and unpacked data for VersionAudited events raised by the Registry contract. -type RegistryVersionAuditedIterator struct { - Event *RegistryVersionAudited // Event containing the contract specifics and raw log +// RegistryVersionRecommendedIterator is returned from FilterVersionRecommended and is used to iterate over the raw logs and unpacked data for VersionRecommended events raised by the Registry contract. +type RegistryVersionRecommendedIterator struct { + Event *RegistryVersionRecommended // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -1377,7 +1091,7 @@ type RegistryVersionAuditedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *RegistryVersionAuditedIterator) Next() bool { +func (it *RegistryVersionRecommendedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -1386,7 +1100,7 @@ func (it *RegistryVersionAuditedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(RegistryVersionAudited) + it.Event = new(RegistryVersionRecommended) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1401,7 +1115,7 @@ func (it *RegistryVersionAuditedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(RegistryVersionAudited) + it.Event = new(RegistryVersionRecommended) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1417,42 +1131,42 @@ func (it *RegistryVersionAuditedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *RegistryVersionAuditedIterator) Error() error { +func (it *RegistryVersionRecommendedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *RegistryVersionAuditedIterator) Close() error { +func (it *RegistryVersionRecommendedIterator) Close() error { it.sub.Unsubscribe() return nil } -// RegistryVersionAudited represents a VersionAudited event raised by the Registry contract. -type RegistryVersionAudited struct { +// RegistryVersionRecommended represents a VersionRecommended event raised by the Registry contract. +type RegistryVersionRecommended struct { ContractName string VersionName string Raw types.Log // Blockchain specific contextual infos } -// FilterVersionAudited is a free log retrieval operation binding the contract event 0xdd2996df4158c05ae76d843c929d03eadde75cf3580d1d2f996375ea6cbe9625. +// FilterVersionRecommended is a free log retrieval operation binding the contract event 0xb318550bf93edf51de4bae84db3deabd2a866cc407435a72317ca2503e2a07a6. // -// Solidity: e VersionAudited(contractName string, versionName string) -func (_Registry *RegistryFilterer) FilterVersionAudited(opts *bind.FilterOpts) (*RegistryVersionAuditedIterator, error) { +// Solidity: event VersionRecommended(string contractName, string versionName) +func (_Registry *RegistryFilterer) FilterVersionRecommended(opts *bind.FilterOpts) (*RegistryVersionRecommendedIterator, error) { - logs, sub, err := _Registry.contract.FilterLogs(opts, "VersionAudited") + logs, sub, err := _Registry.contract.FilterLogs(opts, "VersionRecommended") if err != nil { return nil, err } - return &RegistryVersionAuditedIterator{contract: _Registry.contract, event: "VersionAudited", logs: logs, sub: sub}, nil + return &RegistryVersionRecommendedIterator{contract: _Registry.contract, event: "VersionRecommended", logs: logs, sub: sub}, nil } -// WatchVersionAudited is a free log subscription operation binding the contract event 0xdd2996df4158c05ae76d843c929d03eadde75cf3580d1d2f996375ea6cbe9625. +// WatchVersionRecommended is a free log subscription operation binding the contract event 0xb318550bf93edf51de4bae84db3deabd2a866cc407435a72317ca2503e2a07a6. // -// Solidity: e VersionAudited(contractName string, versionName string) -func (_Registry *RegistryFilterer) WatchVersionAudited(opts *bind.WatchOpts, sink chan<- *RegistryVersionAudited) (event.Subscription, error) { +// Solidity: event VersionRecommended(string contractName, string versionName) +func (_Registry *RegistryFilterer) WatchVersionRecommended(opts *bind.WatchOpts, sink chan<- *RegistryVersionRecommended) (event.Subscription, error) { - logs, sub, err := _Registry.contract.WatchLogs(opts, "VersionAudited") + logs, sub, err := _Registry.contract.WatchLogs(opts, "VersionRecommended") if err != nil { return nil, err } @@ -1462,8 +1176,8 @@ func (_Registry *RegistryFilterer) WatchVersionAudited(opts *bind.WatchOpts, sin select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(RegistryVersionAudited) - if err := _Registry.contract.UnpackLog(event, "VersionAudited", log); err != nil { + event := new(RegistryVersionRecommended) + if err := _Registry.contract.UnpackLog(event, "VersionRecommended", log); err != nil { return err } event.Raw = log @@ -1484,9 +1198,9 @@ func (_Registry *RegistryFilterer) WatchVersionAudited(opts *bind.WatchOpts, sin }), nil } -// RegistryVersionRecommendedIterator is returned from FilterVersionRecommended and is used to iterate over the raw logs and unpacked data for VersionRecommended events raised by the Registry contract. -type RegistryVersionRecommendedIterator struct { - Event *RegistryVersionRecommended // Event containing the contract specifics and raw log +// RegistryVersionUpdatedIterator is returned from FilterVersionUpdated and is used to iterate over the raw logs and unpacked data for VersionUpdated events raised by the Registry contract. +type RegistryVersionUpdatedIterator struct { + Event *RegistryVersionUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -1500,7 +1214,7 @@ type RegistryVersionRecommendedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *RegistryVersionRecommendedIterator) Next() bool { +func (it *RegistryVersionUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -1509,7 +1223,7 @@ func (it *RegistryVersionRecommendedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(RegistryVersionRecommended) + it.Event = new(RegistryVersionUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1524,7 +1238,7 @@ func (it *RegistryVersionRecommendedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(RegistryVersionRecommended) + it.Event = new(RegistryVersionUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1540,42 +1254,44 @@ func (it *RegistryVersionRecommendedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *RegistryVersionRecommendedIterator) Error() error { +func (it *RegistryVersionUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *RegistryVersionRecommendedIterator) Close() error { +func (it *RegistryVersionUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// RegistryVersionRecommended represents a VersionRecommended event raised by the Registry contract. -type RegistryVersionRecommended struct { +// RegistryVersionUpdated represents a VersionUpdated event raised by the Registry contract. +type RegistryVersionUpdated struct { ContractName string VersionName string + Status uint8 + BugLevel uint8 Raw types.Log // Blockchain specific contextual infos } -// FilterVersionRecommended is a free log retrieval operation binding the contract event 0xb318550bf93edf51de4bae84db3deabd2a866cc407435a72317ca2503e2a07a6. +// FilterVersionUpdated is a free log retrieval operation binding the contract event 0x0acf3e1a00b57bfc05ebf65957f42293847dc0938bfa1744660d6df56036d751. // -// Solidity: e VersionRecommended(contractName string, versionName string) -func (_Registry *RegistryFilterer) FilterVersionRecommended(opts *bind.FilterOpts) (*RegistryVersionRecommendedIterator, error) { +// Solidity: event VersionUpdated(string contractName, string versionName, uint8 status, uint8 bugLevel) +func (_Registry *RegistryFilterer) FilterVersionUpdated(opts *bind.FilterOpts) (*RegistryVersionUpdatedIterator, error) { - logs, sub, err := _Registry.contract.FilterLogs(opts, "VersionRecommended") + logs, sub, err := _Registry.contract.FilterLogs(opts, "VersionUpdated") if err != nil { return nil, err } - return &RegistryVersionRecommendedIterator{contract: _Registry.contract, event: "VersionRecommended", logs: logs, sub: sub}, nil + return &RegistryVersionUpdatedIterator{contract: _Registry.contract, event: "VersionUpdated", logs: logs, sub: sub}, nil } -// WatchVersionRecommended is a free log subscription operation binding the contract event 0xb318550bf93edf51de4bae84db3deabd2a866cc407435a72317ca2503e2a07a6. +// WatchVersionUpdated is a free log subscription operation binding the contract event 0x0acf3e1a00b57bfc05ebf65957f42293847dc0938bfa1744660d6df56036d751. // -// Solidity: e VersionRecommended(contractName string, versionName string) -func (_Registry *RegistryFilterer) WatchVersionRecommended(opts *bind.WatchOpts, sink chan<- *RegistryVersionRecommended) (event.Subscription, error) { +// Solidity: event VersionUpdated(string contractName, string versionName, uint8 status, uint8 bugLevel) +func (_Registry *RegistryFilterer) WatchVersionUpdated(opts *bind.WatchOpts, sink chan<- *RegistryVersionUpdated) (event.Subscription, error) { - logs, sub, err := _Registry.contract.WatchLogs(opts, "VersionRecommended") + logs, sub, err := _Registry.contract.WatchLogs(opts, "VersionUpdated") if err != nil { return nil, err } @@ -1585,8 +1301,8 @@ func (_Registry *RegistryFilterer) WatchVersionRecommended(opts *bind.WatchOpts, select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(RegistryVersionRecommended) - if err := _Registry.contract.UnpackLog(event, "VersionRecommended", log); err != nil { + event := new(RegistryVersionUpdated) + if err := _Registry.contract.UnpackLog(event, "VersionUpdated", log); err != nil { return err } event.Raw = log diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/erc20.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/erc20.go similarity index 100% rename from vendor/github.com/OpenBazaar/go-ethwallet/wallet/erc20.go rename to vendor/github.com/phoreproject/go-ethwallet/wallet/erc20.go diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/erc20_wallet.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/erc20_wallet.go similarity index 88% rename from vendor/github.com/OpenBazaar/go-ethwallet/wallet/erc20_wallet.go rename to vendor/github.com/phoreproject/go-ethwallet/wallet/erc20_wallet.go index db406a320e..871c12821b 100644 --- a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/erc20_wallet.go +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/erc20_wallet.go @@ -10,25 +10,23 @@ import ( "math/big" "time" - "github.com/OpenBazaar/multiwallet/config" wi "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcutil" hd "github.com/btcsuite/btcutil/hdkeychain" "github.com/davecgh/go-spew/spew" - ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/ethclient" - log "github.com/sirupsen/logrus" + "github.com/phoreproject/multiwallet/config" "golang.org/x/net/proxy" - "github.com/OpenBazaar/go-ethwallet/util" + "github.com/phoreproject/go-ethwallet/util" ) // ERC20Wallet is the wallet implementation for ethereum @@ -53,7 +51,7 @@ type ERC20Wallet struct { // GenTokenScriptHash - used to generate script hash for erc20 token as per // escrow smart contract func GenTokenScriptHash(script EthRedeemScript) ([32]byte, string, error) { - ahash := sha3.NewKeccak256() + //ahash := sha3.NewKeccak256() a := make([]byte, 4) binary.BigEndian.PutUint32(a, script.Timeout) arr := append(script.TxnID.Bytes(), append([]byte{script.Threshold}, @@ -61,10 +59,11 @@ func GenTokenScriptHash(script EthRedeemScript) ([32]byte, string, error) { append(script.Seller.Bytes(), append(script.Moderator.Bytes(), append(script.MultisigAddress.Bytes(), script.TokenAddress.Bytes()...)...)...)...)...)...)...) - ahash.Write(arr) + //ahash.Write(arr) var retHash [32]byte - copy(retHash[:], ahash.Sum(nil)[:]) + //copy(retHash[:], ahash.Sum(nil)[:]) + copy(retHash[:], crypto.Keccak256(arr)) ahashStr := hexutil.Encode(retHash[:]) return retHash, ahashStr, nil @@ -80,7 +79,7 @@ type TokenDetail struct { } // NewERC20Wallet will return a reference to the ERC20 Wallet -func NewERC20Wallet(cfg config.CoinConfig, mnemonic string, proxy proxy.Dialer) (*ERC20Wallet, error) { +func NewERC20Wallet(cfg config.CoinConfig, params *chaincfg.Params, mnemonic string, proxy proxy.Dialer) (*ERC20Wallet, error) { client, err := NewEthClient(cfg.ClientAPIs[0] + "/" + InfuraAPIKey) if err != nil { log.Errorf("error initializing wallet: %v", err) @@ -88,7 +87,7 @@ func NewERC20Wallet(cfg config.CoinConfig, mnemonic string, proxy proxy.Dialer) } var myAccount *Account - myAccount, err = NewAccountFromMnemonic(mnemonic, "") + myAccount, err = NewAccountFromMnemonic(mnemonic, "", params) if err != nil { log.Errorf("mnemonic based pk generation failed: %s", err.Error()) return nil, err @@ -100,7 +99,7 @@ func NewERC20Wallet(cfg config.CoinConfig, mnemonic string, proxy proxy.Dialer) var regAddr interface{} var ok bool if regAddr, ok = cfg.Options["RegistryAddress"]; !ok { - log.Errorf("ethereum registry not found: %s", err.Error()) + log.Errorf("ethereum registry not found: %s", cfg.Options["RegistryAddress"]) return nil, err } @@ -118,21 +117,21 @@ func NewERC20Wallet(cfg config.CoinConfig, mnemonic string, proxy proxy.Dialer) var name, symbol, deployAddrMain, deployAddrRopsten, deployAddrRinkeby interface{} if name, ok = cfg.Options["Name"]; !ok { - log.Errorf("erc20 token name not found: %s", err.Error()) + log.Errorf("erc20 token name not found: %s", cfg.Options["Name"]) return nil, err } token.name = name.(string) if symbol, ok = cfg.Options["Symbol"]; !ok { - log.Errorf("erc20 token symbol not found: %s", err.Error()) + log.Errorf("erc20 token symbol not found: %s", cfg.Options["Symbol"]) return nil, err } token.symbol = symbol.(string) if deployAddrMain, ok = cfg.Options["MainNetAddress"]; !ok { - log.Errorf("erc20 token address not found: %s", err.Error()) + log.Errorf("erc20 token address not found: %s", cfg.Options["MainNetAddress"]) return nil, err } @@ -249,10 +248,7 @@ func (wallet *ERC20Wallet) NewAddress(purpose wi.KeyPurpose) btcutil.Address { // DecodeAddress - Parse the address string and return an address interface func (wallet *ERC20Wallet) DecodeAddress(addr string) (btcutil.Address, error) { ethAddr := common.HexToAddress(addr) - if wallet.HasKey(EthAddress{ðAddr}) { - return *wallet.address, nil - } - return EthAddress{}, errors.New("invalid or unknown address") + return EthAddress{ðAddr}, nil } // ScriptToAddress - ? @@ -279,12 +275,41 @@ func (wallet *ERC20Wallet) Balance() (confirmed, unconfirmed int64) { if err == nil { ucbalance = ucbal.Int64() } - return balance, ucbalance + ucb := int64(0) + if ucbalance > balance { + ucb = ucbalance - balance + } + return balance, ucb } // Transactions - Returns a list of transactions for this wallet func (wallet *ERC20Wallet) Transactions() ([]wi.Txn, error) { - return txns, nil + txns, err := wallet.client.eClient.NormalTxByAddress(wallet.account.Address().String(), nil, nil, + 1, 0, true) + if err != nil { + return []wi.Txn{}, err + } + + ret := []wi.Txn{} + for _, t := range txns { + status := wi.StatusConfirmed + if t.IsError != 0 { + status = wi.StatusError + } + tnew := wi.Txn{ + Txid: t.Hash, + Value: t.Value.Int().String(), + Height: int32(t.BlockNumber), + Timestamp: t.TimeStamp.Time(), + WatchOnly: false, + Confirmations: int64(t.Confirmations), + Status: wi.StatusCode(status), + Bytes: []byte(t.Input), + } + ret = append(ret, tnew) + } + + return ret, nil } // GetTransaction - Get info on a specific transaction @@ -295,7 +320,7 @@ func (wallet *ERC20Wallet) GetTransaction(txid chainhash.Hash) (wi.Txn, error) { } return wi.Txn{ Txid: tx.Hash().String(), - Value: tx.Value().Int64(), + Value: tx.Value().String(), Height: 0, Timestamp: time.Now(), WatchOnly: false, @@ -310,7 +335,7 @@ func (wallet *ERC20Wallet) ChainTip() (uint32, chainhash.Hash) { if err != nil { return 0, *h } - h, _ = chainhash.NewHashFromStr(hash) + h, _ = chainhash.NewHashFromStr(hash.Hex()[2:]) return num, *h } @@ -320,7 +345,7 @@ func (wallet *ERC20Wallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { } // Spend - Send ether to an external wallet -func (wallet *ERC20Wallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string) (*chainhash.Hash, error) { +func (wallet *ERC20Wallet) Spend(amount big.Int, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string) (*chainhash.Hash, error) { var hash common.Hash var h *chainhash.Hash var err error @@ -347,9 +372,12 @@ func (wallet *ERC20Wallet) Spend(amount int64, addr btcutil.Address, feeLevel wi if err != nil { return nil, err } - hash, err = wallet.callAddTokenTransaction(ethScript, big.NewInt(amount)) + hash, err = wallet.callAddTokenTransaction(ethScript, &amount) + if err != nil { + log.Errorf("error call add token txn: %v", err) + } } else { - hash, err = wallet.Transfer(addr.String(), big.NewInt(amount)) + hash, err = wallet.Transfer(addr.String(), &amount) } if err != nil { @@ -372,7 +400,7 @@ func (wallet *ERC20Wallet) Spend(amount int64, addr btcutil.Address, feeLevel wi // but valid txn like some contract condition causing revert if rcpt.Status > 0 { // all good to update order state - go wallet.callListeners(wallet.createTxnCallback(hash.String(), referenceID, amount, time.Now())) + go wallet.callListeners(wallet.createTxnCallback(hash.String(), referenceID, addr, amount, time.Now())) } else { // there was some error processing this txn return nil, errors.New("problem processing this transaction") @@ -380,23 +408,31 @@ func (wallet *ERC20Wallet) Spend(amount int64, addr btcutil.Address, feeLevel wi } if err == nil { - h, err = chainhash.NewHashFromStr(hash.String()) + h, err = chainhash.NewHashFromStr(hash.Hex()[2:]) } return h, err } -func (wallet *ERC20Wallet) createTxnCallback(txID, orderID string, value int64, bTime time.Time) wi.TransactionCallback { +func (wallet *ERC20Wallet) createTxnCallback(txID, orderID string, toAddress btcutil.Address, value big.Int, bTime time.Time) wi.TransactionCallback { output := wi.TransactionOutput{ - Address: wallet.address, + Address: toAddress, Value: value, Index: 1, OrderID: orderID, } + input := wi.TransactionInput{ + OutpointHash: []byte(txID), + OutpointIndex: 1, + LinkedAddress: wallet.address, + Value: value, + OrderID: orderID, + } + return wi.TransactionCallback{ - Txid: txID, + Txid: txID[2:], Outputs: []wi.TransactionOutput{output}, - Inputs: []wi.TransactionInput{}, + Inputs: []wi.TransactionInput{input}, Height: 1, Timestamp: time.Now(), Value: value, @@ -421,7 +457,7 @@ func (wallet *ERC20Wallet) EstimateFee(ins []wi.TransactionInput, outs []wi.Tran sum := big.NewInt(0) for _, out := range outs { gas, err := wallet.client.EstimateTxnGas(wallet.account.Address(), - common.HexToAddress(out.Address.String()), big.NewInt(out.Value)) + common.HexToAddress(out.Address.String()), &out.Value) if err != nil { return sum.Uint64() } @@ -487,7 +523,13 @@ func (wallet *ERC20Wallet) callAddTokenTransaction(script EthRedeemScript, value //time.Sleep(2 * time.Minute) header, err := wallet.client.HeaderByNumber(context.Background(), nil) + if err != nil { + log.Errorf("error fetching latest blk: %v", err) + } tclient, err := ethclient.Dial("wss://rinkeby.infura.io/ws") + if err != nil { + log.Errorf("error establishing ws conn: %v", err) + } query := ethereum.FilterQuery{ Addresses: []common.Address{script.TokenAddress}, @@ -621,9 +663,9 @@ func (wallet *ERC20Wallet) GenerateMultisigScript(keys []hd.ExtendedKey, thresho return nil, nil, err } - hash := sha3.NewKeccak256() - hash.Write(redeemScript) - addr := common.HexToAddress(hexutil.Encode(hash.Sum(nil)[:])) + //hash := sha3.NewKeccak256() + //hash.Write(redeemScript) + addr := common.HexToAddress(hexutil.Encode(crypto.Keccak256(redeemScript))) retAddr := EthAddress{&addr} scriptKey := append(addr.Bytes(), redeemScript...) @@ -639,10 +681,10 @@ func (wallet *ERC20Wallet) CreateMultisigSignature(ins []wi.TransactionInput, ou payables := make(map[string]*big.Int) for _, out := range outs { - if out.Value <= 0 { + if out.Value.Cmp(big.NewInt(0)) <= 0 { continue } - val := big.NewInt(out.Value) + val := &out.Value if p, ok := payables[out.Address.String()]; ok { sum := big.NewInt(0) sum.Add(val, p) @@ -732,10 +774,10 @@ func (wallet *ERC20Wallet) Multisign(ins []wi.TransactionInput, outs []wi.Transa payables := make(map[string]*big.Int) for _, out := range outs { - if out.Value <= 0 { + if out.Value.Cmp(big.NewInt(0)) <= 0 { continue } - val := big.NewInt(out.Value) + val := &out.Value if p, ok := payables[out.Address.String()]; ok { sum := big.NewInt(0) sum.Add(val, p) @@ -749,9 +791,9 @@ func (wallet *ERC20Wallet) Multisign(ins []wi.TransactionInput, outs []wi.Transa sSlice := [][32]byte{} //, 2) vSlice := []uint8{} //, 2) - r := [32]byte{} - s := [32]byte{} - v := uint8(0) + var r [32]byte + var s [32]byte + var v uint8 if len(sigs1[0].Signature) > 0 { r, s, v = util.SigRSV(sigs1[0].Signature) @@ -760,9 +802,9 @@ func (wallet *ERC20Wallet) Multisign(ins []wi.TransactionInput, outs []wi.Transa vSlice = append(vSlice, v) } - r = [32]byte{} - s = [32]byte{} - v = uint8(0) + //r = [32]byte{} + //s = [32]byte{} + //v = uint8(0) if len(sigs2[0].Signature) > 0 { r, s, v = util.SigRSV(sigs2[0].Signature) @@ -826,14 +868,10 @@ func (wallet *ERC20Wallet) Multisign(ins []wi.TransactionInput, outs []wi.Transa return ret, err } -// AddWatchedAddress - Add a script to the wallet and get notifications back when coins are received or spent from it -func (wallet *ERC20Wallet) AddWatchedAddress(address btcutil.Address) error { - return nil -} - // AddTransactionListener - add a txn listener func (wallet *ERC20Wallet) AddTransactionListener(callback func(wi.TransactionCallback)) { // add incoming txn listener using service + wallet.listeners = append(wallet.listeners, callback) } // ReSyncBlockchain - Use this to re-download merkle blocks in case of missed transactions diff --git a/vendor/github.com/phoreproject/go-ethwallet/wallet/erc20_wallet_test.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/erc20_wallet_test.go new file mode 100644 index 0000000000..f420f2f632 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/erc20_wallet_test.go @@ -0,0 +1,460 @@ +package wallet + +import ( + "context" + "crypto/rand" + "encoding/binary" + "fmt" + "math/big" + "net/url" + "testing" + "time" + + wi "github.com/OpenBazaar/wallet-interface" + "github.com/btcsuite/btcd/chaincfg/chainhash" + hd "github.com/btcsuite/btcutil/hdkeychain" + "github.com/davecgh/go-spew/spew" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/phoreproject/multiwallet/config" + log "github.com/sirupsen/logrus" + + "github.com/phoreproject/go-ethwallet/util" +) + +var validTokenWallet *ERC20Wallet +var destTokenWallet *ERC20Wallet + +var tokenCfg config.CoinConfig +var tscript EthRedeemScript + +func setupTokenConfigRinkeby() { + clientURL, _ := url.Parse("https://rinkeby.infura.io") + tokenCfg.ClientAPIs = []string{(*clientURL).String()} + tokenCfg.CoinType = wi.Ethereum + tokenCfg.Options = make(map[string]interface{}) + tokenCfg.Options["RegistryAddress"] = "0x403d907982474cdd51687b09a8968346159378f3" + tokenCfg.Options["Name"] = "OBToken" + tokenCfg.Options["Symbol"] = "OBT" + tokenCfg.Options["MainNetAddress"] = "0xe46ea07736e68df951df7b987dda453962ba7d5a" +} + +func setupERCTokenRedeemScript(timeout time.Duration, threshold int) { + + chaincode := make([]byte, 32) + _, err := rand.Read(chaincode) + fmt.Println("chiancode : ", chaincode) + if err != nil { + fmt.Println(err) + chaincode = []byte("423b5d4c32345ced77393b3530b1eed1") + } + tscript.TxnID = common.BytesToAddress(chaincode) + tscript.Timeout = uint32(timeout.Hours()) + tscript.Threshold = uint8(threshold) + tscript.Buyer = common.HexToAddress(mnemonicStrAddress) + tscript.Seller = common.HexToAddress(validDestinationAddress) + tscript.Moderator = common.BigToAddress(big.NewInt(0)) + //tscript.Moderator = common.HexToAddress("0xa6Ac51BB2593e833C629A3352c4c432267714385") + tscript.MultisigAddress = common.HexToAddress("0x36e19e91DFFCA4251f4fB541f5c3a596252eA4BB") + tscript.TokenAddress = common.HexToAddress("0xe46ea07736e68df951df7b987dda453962ba7d5a") + + //fmt.Println("in setup tscript: ") + //spew.Dump(tscript) +} + +func setupSourceErc20Wallet() { + setupTokenConfigRinkeby() + validTokenWallet, _ = NewERC20Wallet(tokenCfg, nil, mnemonicStr, nil) +} + +func TestNewErc20WalletWithValidCoinConfigValues(t *testing.T) { + setupTokenConfigRinkeby() + wallet, err := NewERC20Wallet(tokenCfg, nil, mnemonicStr, nil) + if err != nil || wallet == nil { + t.Errorf("valid credentials should return a wallet") + } + fmt.Println(wallet.address.String()) + fmt.Println(validSourceAddress) + if wallet.address.String() != mnemonicStrAddress { + t.Errorf("valid credentials should return a wallet with proper initialization") + } +} + +func TestTokenWalletChainTip(t *testing.T) { + setupSourceErc20Wallet() + + emptyHash, _ := chainhash.NewHashFromStr("") + + tip, hash := validTokenWallet.ChainTip() + + if hash.String() == emptyHash.String() { + t.Errorf("valid wallet should return chaintip") + } + fmt.Println("Chaintip is : ", tip) +} + +func TestWalletGetTokenBalance(t *testing.T) { + setupSourceErc20Wallet() + + if _, err := validTokenWallet.GetBalance(); err != nil { + t.Errorf("valid wallet should return balance") + } +} + +func TestWalletGetTokenUnconfirmedBalance(t *testing.T) { + setupSourceErc20Wallet() + + if _, err := validTokenWallet.GetUnconfirmedBalance(); err != nil { + t.Errorf("valid wallet should return unconfirmed balance") + } +} + +func TestTokenWalletCurrencyCode(t *testing.T) { + setupSourceErc20Wallet() + + if validTokenWallet.CurrencyCode() != "OBT" { + t.Errorf("wallet should return proper currency code") + } +} + +func TestTokenWalletIsDust(t *testing.T) { + setupSourceErc20Wallet() + + if validTokenWallet.IsDust(int64(10000 + 10000)) { + t.Errorf("wallet should not indicate wrong dust") + } + + if !validTokenWallet.IsDust(int64(10000 - 100)) { + t.Errorf("wallet should not indicate wrong dust") + } +} + +func TestTokenWalletCurrentAddress(t *testing.T) { + setupSourceErc20Wallet() + + addr := validTokenWallet.CurrentAddress(wi.EXTERNAL) + + if addr.String() != mnemonicStrAddress { + t.Errorf("wallet should return correct current address") + } +} + +func TestTokenWalletNewAddress(t *testing.T) { + setupSourceErc20Wallet() + + addr := validTokenWallet.NewAddress(wi.EXTERNAL) + + if addr.String() != mnemonicStrAddress { + t.Errorf("wallet should return correct new address") + } +} + +func TestTokenWalletContractAddTransaction(t *testing.T) { + setupSourceErc20Wallet() + + ver, err := validTokenWallet.registry.GetRecommendedVersion(nil, "escrow") + if err != nil { + t.Error("error fetching escrow from registry") + } + + if util.IsZeroAddress(ver.Implementation) { + log.Infof("escrow not available") + return + } + + d, _ := time.ParseDuration("1h") + setupERCTokenRedeemScript(d, 1) + + tscript.MultisigAddress = ver.Implementation + + redeemScript, err := SerializeEthScript(tscript) + if err != nil { + t.Error("error serializing redeem script") + } + + fmt.Println(redeemScript) + + spew.Dump(tscript) + + orderValue := big.NewInt(345678123478789123) + + hash, err := validTokenWallet.callAddTokenTransaction(tscript, orderValue) + + fmt.Println("returned hash : ", hash) + fmt.Println(err) + + chash, err := chainhash.NewHashFromStr(hash.String()) + + fmt.Println("err : ", err) + + if err == nil { + txn, err := validTokenWallet.GetTransaction(*chash) + + spew.Dump(txn) + fmt.Println(err) + } + + output := wi.TransactionOutput{ + Address: EthAddress{&tscript.Seller}, + Value: *orderValue, + Index: 1, + } + + hkey := hd.NewExtendedKey([]byte{}, []byte{}, []byte{}, []byte{}, 0, 0, false) + + sig, err := validTokenWallet.CreateMultisigSignature([]wi.TransactionInput{}, []wi.TransactionOutput{output}, + hkey, redeemScript, 2000) + + if err != nil { + fmt.Println(err) + } + + fmt.Println(sig) + + time.Sleep(5 * time.Minute) + + txBytes, err := validTokenWallet.Multisign([]wi.TransactionInput{}, + []wi.TransactionOutput{output}, + sig, []wi.Signature{wi.Signature{InputIndex: 1, Signature: []byte{}}}, redeemScript, + 20000, true) + //fmt.Println("after multisign") + //fmt.Println(txBytes) + fmt.Println("err : ", err) + + mtx := &types.Transaction{} + + mtx.UnmarshalJSON(txBytes) + + spew.Dump(mtx) + + sshh, sshhstr, _ := GenTokenScriptHash(tscript) + + fmt.Println("script hash for ct : ", sshh) + fmt.Println(sshhstr) + +} + +func TestTokenWalletContractApproveEvent(t *testing.T) { + setupSourceErc20Wallet() + + ver, err := validTokenWallet.registry.GetRecommendedVersion(nil, "escrow") + if err != nil { + t.Error("error fetching escrow from registry") + } + + if util.IsZeroAddress(ver.Implementation) { + log.Infof("escrow not available") + return + } + + d, _ := time.ParseDuration("1h") + setupERCTokenRedeemScript(d, 1) + + tscript.MultisigAddress = ver.Implementation + + redeemScript, err := SerializeEthScript(tscript) + if err != nil { + t.Error("error serializing redeem script") + } + + fmt.Println(redeemScript) + + spew.Dump(tscript) + + orderValue := big.NewInt(34567812347878) + + fromAddress := validTokenWallet.account.Address() + nonce, err := validTokenWallet.client.PendingNonceAt(context.Background(), fromAddress) + if err != nil { + log.Fatal(err) + } + gasPrice, err := validTokenWallet.client.SuggestGasPrice(context.Background()) + if err != nil { + log.Fatal(err) + } + auth := bind.NewKeyedTransactor(validTokenWallet.account.privateKey) + + auth.Nonce = big.NewInt(int64(nonce)) + auth.Value = big.NewInt(0) // in wei + auth.GasLimit = 4000000 // in units + auth.GasPrice = gasPrice + + header, err := validTokenWallet.client.HeaderByNumber(context.Background(), nil) + fmt.Println("current header no : ", header.Number.Int64()) + + var tx *types.Transaction + + tx, err = validTokenWallet.token.Approve(auth, script.MultisigAddress, orderValue) + + if err != nil { + log.Error(err) + return + } + + spew.Dump(tx) + + tclient, err := ethclient.Dial("wss://rinkeby.infura.io/ws") + if err != nil { + log.Error(err) + } + + //tchan := make(chan *TokenApproval) + + validTokenWallet.client, _ = NewEthClient("wss://rinkeby.infura.io/ws") // &EthClient{tclient, ""} + + //var startBlock *uint64 + startBlock := new(uint64) //(*uint64)(unsafe.Pointer(&uint64(0))) + + *startBlock = header.Number.Uint64() + + /* + wopts := &bind.WatchOpts{ + Start: startBlock, + Context: context.Background(), + } + + sub, err := validTokenWallet.token.WatchApproval(wopts, tchan, + []common.Address{validTokenWallet.account.Address()}, + []common.Address{script.MultisigAddress}) + if err != nil { + fmt.Println("cannot watch") + log.Error(err) + return + } + + for { + select { + case err := <-sub.Err(): + log.Error(err) + break + case tlog := <-tchan: + fmt.Println("yyyyyyyyyyy") + fmt.Println(tlog) + } + } + */ + + validTokenWallet.token.FilterApproval(nil, + []common.Address{validTokenWallet.account.Address()}, + []common.Address{script.MultisigAddress}) + + query := ethereum.FilterQuery{ + Addresses: []common.Address{tscript.TokenAddress}, + FromBlock: header.Number, + Topics: [][]common.Hash{{common.HexToHash("0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925")}}, + } + logs := make(chan types.Log) + sub1, err := tclient.SubscribeFilterLogs(context.Background(), query, logs) + if err != nil { + log.Fatal(err) + } + defer sub1.Unsubscribe() + flag := false + for !flag { + select { + case err := <-sub1.Err(): + log.Fatal(err) + case vLog := <-logs: + //fmt.Println(vLog) // pointer to event log + //spew.Dump(vLog) + //fmt.Println(vLog.Topics[0]) + fmt.Println(vLog.Address.String()) + if tx.Hash() == vLog.TxHash { + fmt.Println("we have found the approval ...") + spew.Dump(vLog) + flag = true + break + } + } + } + +} + +func TestTokenWalletContractScriptHash(t *testing.T) { + setupSourceErc20Wallet() + + ver, err := validTokenWallet.registry.GetRecommendedVersion(nil, "escrow") + if err != nil { + t.Error("error fetching escrow from registry") + } + + if util.IsZeroAddress(ver.Implementation) { + log.Infof("escrow not available") + return + } + + d, _ := time.ParseDuration("1h") + setupERCTokenRedeemScript(d, 1) + + chaincode := []byte("423b5d4c32345ced77393b3530b1eed1") + + tscript.TxnID = common.BytesToAddress(chaincode) + + tscript.MultisigAddress = ver.Implementation + + /* + fmt.Println("buyer : ", script.Buyer) + fmt.Println("seller : ", script.Seller) + fmt.Println("moderator : ", script.Moderator) + fmt.Println("threshold : ", script.Threshold) + fmt.Println("timeout : ", script.Timeout) + fmt.Println("scrptHash : ", shash) + */ + + spew.Dump(tscript) + + fmt.Println("escrow address : ", ver.Implementation.String()) + + smtct, err := NewEscrow(ver.Implementation, validTokenWallet.client) + if err != nil { + t.Errorf("error initilaizing contract failed: %s", err.Error()) + } + + retHash, err := smtct.CalculateRedeemScriptHash(nil, tscript.TxnID, tscript.Threshold, + tscript.Timeout, tscript.Buyer, tscript.Seller, tscript.Moderator, tscript.TokenAddress) + + fmt.Println(err) + fmt.Println("from smtct : ", retHash) + + rethash1Str := hexutil.Encode(retHash[:]) + fmt.Println("rethash1Str : ", rethash1Str) + + ahash := crypto.NewKeccak256() + a := make([]byte, 4) + binary.BigEndian.PutUint32(a, tscript.Timeout) + arr := append(tscript.TxnID.Bytes(), append([]byte{tscript.Threshold}, + append(a[:], append(tscript.Buyer.Bytes(), + append(tscript.Seller.Bytes(), append(tscript.Moderator.Bytes(), + append(tscript.MultisigAddress.Bytes(), + append(tscript.TokenAddress.Bytes())...)...)...)...)...)...)...) + ahash.Write(arr) + ahashStr := hexutil.Encode(ahash.Sum(nil)[:]) + + fmt.Println("computed : ", ahashStr) + + if rethash1Str == ahashStr { + fmt.Println("yay!!!!!!!!!!!!") + } + + fmt.Println("priv key : ", validTokenWallet.account.privateKey) + + b := []byte{161, 162, 209, 139, 227, 101, 186, 196, 93, 247, 64, 186, 79, 166, 235, 225, 191, 123, 139, 89, 247, 48, 49, 71, 46, 130, 125, 221, 137, 35, 41, 51} + + fmt.Println(hexutil.Encode(b)) + + privateKeyBytes := crypto.FromECDSA(validTokenWallet.account.privateKey) + fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) + + fmt.Println("dest : ", tscript.MultisigAddress.String()[2:]) + fmt.Println("dest : ", string(tscript.MultisigAddress.Bytes())) + fmt.Println("dest : ", tscript.MultisigAddress.Hex()) + fmt.Println("dest : ", []byte(tscript.MultisigAddress.String())[2:]) + + a1, b1, c1 := GenTokenScriptHash(tscript) + fmt.Println("scrpt hash : ", a1, " ", b1[2:], " ", c1) +} diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/escrow_v1.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/escrow_v1.go similarity index 100% rename from vendor/github.com/OpenBazaar/go-ethwallet/wallet/escrow_v1.go rename to vendor/github.com/phoreproject/go-ethwallet/wallet/escrow_v1.go diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/exchange_rates.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/exchange_rates.go similarity index 98% rename from vendor/github.com/OpenBazaar/go-ethwallet/wallet/exchange_rates.go rename to vendor/github.com/phoreproject/go-ethwallet/wallet/exchange_rates.go index e60f04f039..6a99336310 100644 --- a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/exchange_rates.go +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/exchange_rates.go @@ -115,9 +115,9 @@ func (z *EthereumPriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, er return copy, nil } -// UnitsPerCoin - return satoshis in 1 BTC -func (z *EthereumPriceFetcher) UnitsPerCoin() int { - return exchange.SatoshiPerBTC +// UnitsPerCoin - return weis in 1 ETH +func (z *EthereumPriceFetcher) UnitsPerCoin() int64 { + return 1000000000000000000 } func (z *EthereumPriceFetcher) fetchCurrentRates() error { @@ -135,6 +135,7 @@ func (z *EthereumPriceFetcher) fetchCurrentRates() error { func (z *EthereumPriceFetcher) run() { z.fetchCurrentRates() ticker := time.NewTicker(time.Minute * 15) + defer ticker.Stop() for range ticker.C { z.fetchCurrentRates() } diff --git a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/service.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/service.go similarity index 96% rename from vendor/github.com/OpenBazaar/go-ethwallet/wallet/service.go rename to vendor/github.com/phoreproject/go-ethwallet/wallet/service.go index 8068e9d2f9..29c8b2046f 100644 --- a/vendor/github.com/OpenBazaar/go-ethwallet/wallet/service.go +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/service.go @@ -7,7 +7,6 @@ import ( "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/ethereum/go-ethereum/ethclient" - log "github.com/sirupsen/logrus" ) // Service - used to represent WalletService @@ -47,7 +46,7 @@ func (ws *Service) ChainTip() (uint32, chainhash.Hash) { ws.lock.RLock() defer ws.lock.RUnlock() ch, _ := chainhash.NewHashFromStr(ws.bestBlock) - return uint32(ws.chainHeight), *ch + return ws.chainHeight, *ch } // UpdateState - updates state diff --git a/vendor/github.com/phoreproject/go-ethwallet/wallet/wallet.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/wallet.go new file mode 100644 index 0000000000..8ba6c42550 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/wallet.go @@ -0,0 +1,1518 @@ +package wallet + +import ( + "bytes" + "context" + "crypto/ecdsa" + "encoding/binary" + "encoding/gob" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "math/big" + "net/http" + "path" + "runtime" + "sort" + "strconv" + "strings" + "time" + + wi "github.com/OpenBazaar/wallet-interface" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcutil" + hd "github.com/btcsuite/btcutil/hdkeychain" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/nanmu42/etherscan-api" + "github.com/op/go-logging" + "github.com/phoreproject/multiwallet/config" + "golang.org/x/net/proxy" + "gopkg.in/yaml.v2" + + "github.com/phoreproject/go-ethwallet/util" + ut "github.com/phoreproject/pm-go/util" +) + +var _ = wi.Wallet(&EthereumWallet{}) +var done, doneBalanceTicker chan bool + +const ( + // InfuraAPIKey is the hard coded Infura API key + InfuraAPIKey = "v3/c95691970130492db6f2c920659e3f37" + // EtherScanAPIKey is needed for all Eherscan requests + EtherScanAPIKey = "B2U2U4NYY97ER6XWQD51TTRH2DCXT4MRUC" + maxGasLimit = 400000 +) + +var ( + emptyChainHash *chainhash.Hash + + // EthCurrencyDefinition is eth defaults + EthCurrencyDefinition = wi.CurrencyDefinition{ + Code: "ETH", + Divisibility: 18, + } + log = logging.MustGetLogger("ethwallet") +) + +func init() { + mustInitEmptyChainHash() +} + +func mustInitEmptyChainHash() { + hash, err := chainhash.NewHashFromStr("") + if err != nil { + panic(fmt.Sprintf("creating emptyChainHash: %s", err.Error())) + } + emptyChainHash = hash +} + +// EthConfiguration - used for eth specific configuration +type EthConfiguration struct { + RopstenPPAddress string `yaml:"ROPSTEN_PPv2_ADDRESS"` + RegistryAddress string `yaml:"ROPSTEN_REGISTRY"` +} + +// EthRedeemScript - used to represent redeem script for eth wallet +// +// +type EthRedeemScript struct { + TxnID common.Address + Threshold uint8 + Timeout uint32 + Buyer common.Address + Seller common.Address + Moderator common.Address + MultisigAddress common.Address + TokenAddress common.Address +} + +// SerializeEthScript - used to serialize eth redeem script +func SerializeEthScript(scrpt EthRedeemScript) ([]byte, error) { + b := bytes.Buffer{} + e := gob.NewEncoder(&b) + err := e.Encode(scrpt) + return b.Bytes(), err +} + +// DeserializeEthScript - used to deserialize eth redeem script +func DeserializeEthScript(b []byte) (EthRedeemScript, error) { + scrpt := EthRedeemScript{} + buf := bytes.NewBuffer(b) + d := gob.NewDecoder(buf) + err := d.Decode(&scrpt) + return scrpt, err +} + +// PendingTxn used to record a pending eth txn +type PendingTxn struct { + TxnID common.Hash + OrderID string + Amount string + Nonce int32 + From string + To string + WithInput bool +} + +// SerializePendingTxn - used to serialize eth pending txn +func SerializePendingTxn(pTxn PendingTxn) ([]byte, error) { + b := bytes.Buffer{} + e := gob.NewEncoder(&b) + err := e.Encode(pTxn) + return b.Bytes(), err +} + +// DeserializePendingTxn - used to deserialize eth pending txn +func DeserializePendingTxn(b []byte) (PendingTxn, error) { + pTxn := PendingTxn{} + buf := bytes.NewBuffer(b) + d := gob.NewDecoder(buf) + err := d.Decode(&pTxn) + return pTxn, err +} + +// GenScriptHash - used to generate script hash for eth as per +// escrow smart contract +func GenScriptHash(script EthRedeemScript) ([32]byte, string, error) { + a := make([]byte, 4) + binary.BigEndian.PutUint32(a, script.Timeout) + arr := append(script.TxnID.Bytes(), append([]byte{script.Threshold}, + append(a[:], append(script.Buyer.Bytes(), + append(script.Seller.Bytes(), append(script.Moderator.Bytes(), + append(script.MultisigAddress.Bytes())...)...)...)...)...)...) + var retHash [32]byte + + copy(retHash[:], crypto.Keccak256(arr)[:]) + ahashStr := hexutil.Encode(retHash[:]) + + return retHash, ahashStr, nil +} + +// EthereumWallet is the wallet implementation for ethereum +type EthereumWallet struct { + client *EthClient + account *Account + address *EthAddress + service *Service + registry *Registry + ppsct *Escrow + db wi.Datastore + exchangeRates wi.ExchangeRates + params *chaincfg.Params + listeners []func(wi.TransactionCallback) +} + +// NewEthereumWalletWithKeyfile will return a reference to the Eth Wallet +func NewEthereumWalletWithKeyfile(url, keyFile, passwd string) *EthereumWallet { + client, err := NewEthClient(url) + if err != nil { + log.Fatalf("error initializing wallet: %v", err) + } + var myAccount *Account + myAccount, err = NewAccountFromKeyfile(keyFile, passwd) + if err != nil { + log.Fatalf("key file validation failed: %s", err.Error()) + } + addr := myAccount.Address() + + _, filename, _, _ := runtime.Caller(0) + conf, err := ioutil.ReadFile(path.Join(path.Dir(filename), "../configuration.yaml")) + + if err != nil { + log.Fatalf("ethereum config not found: %s", err.Error()) + } + ethConfig := EthConfiguration{} + err = yaml.Unmarshal(conf, ðConfig) + if err != nil { + log.Fatalf("ethereum config not valid: %s", err.Error()) + } + + reg, err := NewRegistry(common.HexToAddress(ethConfig.RegistryAddress), client) + if err != nil { + log.Fatalf("error initilaizing contract failed: %s", err.Error()) + } + + return &EthereumWallet{client, myAccount, &EthAddress{&addr}, &Service{}, reg, nil, nil, nil, nil, []func(wi.TransactionCallback){}} +} + +// NewEthereumWallet will return a reference to the Eth Wallet +func NewEthereumWallet(cfg config.CoinConfig, params *chaincfg.Params, mnemonic string, proxy proxy.Dialer) (*EthereumWallet, error) { + client, err := NewEthClient(cfg.ClientAPIs[0] + "/" + InfuraAPIKey) + if err != nil { + log.Errorf("error initializing wallet: %v", err) + return nil, err + } + var myAccount *Account + myAccount, err = NewAccountFromMnemonic(mnemonic, "", params) + if err != nil { + log.Errorf("mnemonic based pk generation failed: %s", err.Error()) + return nil, err + } + addr := myAccount.Address() + + ethConfig := EthConfiguration{} + + var regAddr interface{} + var ok bool + registryKey := "RegistryAddress" + if strings.Contains(cfg.ClientAPIs[0], "rinkeby") { + registryKey = "RinkebyRegistryAddress" + } else if strings.Contains(cfg.ClientAPIs[0], "ropsten") { + registryKey = "RopstenRegistryAddress" + } + if regAddr, ok = cfg.Options[registryKey]; !ok { + log.Errorf("ethereum registry not found: %s", cfg.Options[registryKey]) + return nil, err + } + + ethConfig.RegistryAddress = regAddr.(string) + + reg, err := NewRegistry(common.HexToAddress(ethConfig.RegistryAddress), client) + if err != nil { + log.Errorf("error initilaizing contract failed: %s", err.Error()) + return nil, err + } + er := NewEthereumPriceFetcher(proxy) + + return &EthereumWallet{client, myAccount, &EthAddress{&addr}, &Service{}, reg, nil, cfg.DB, er, params, []func(wi.TransactionCallback){}}, nil +} + +// Params - return nil to comply +func (wallet *EthereumWallet) Params() *chaincfg.Params { + return wallet.params +} + +// GetBalance returns the balance for the wallet +func (wallet *EthereumWallet) GetBalance() (*big.Int, error) { + return wallet.client.GetBalance(wallet.account.Address()) +} + +// GetUnconfirmedBalance returns the unconfirmed balance for the wallet +func (wallet *EthereumWallet) GetUnconfirmedBalance() (*big.Int, error) { + return wallet.client.GetUnconfirmedBalance(wallet.account.Address()) +} + +// Transfer will transfer the amount from this wallet to the spec address +func (wallet *EthereumWallet) Transfer(to string, value *big.Int, spendAll bool, fee big.Int) (common.Hash, error) { + toAddress := common.HexToAddress(to) + return wallet.client.Transfer(wallet.account, toAddress, value, spendAll, fee) +} + +// Start will start the wallet daemon +func (wallet *EthereumWallet) Start() { + done = make(chan bool) + doneBalanceTicker = make(chan bool) + // start the ticker to check for pending txn rcpts + go func(wallet *EthereumWallet) { + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + + for { + select { + case <-done: + return + case <-ticker.C: + // get the pending txns + txns, err := wallet.db.Txns().GetAll(true) + if err != nil { + continue + } + for _, txn := range txns { + hash := common.HexToHash(txn.Txid) + go func(txnData []byte) { + _, err := wallet.checkTxnRcpt(&hash, txnData) + if err != nil { + log.Errorf(err.Error()) + } + }(txn.Bytes) + } + } + } + }(wallet) + + // start the ticker to check for balance + go func(wallet *EthereumWallet) { + ticker := time.NewTicker(15 * time.Second) + defer ticker.Stop() + + currentBalance, err := wallet.GetBalance() + if err != nil { + log.Infof("err fetching initial balance: %v", err) + } + currentTip, _ := wallet.ChainTip() + + for { + select { + case <-doneBalanceTicker: + return + case <-ticker.C: + // fetch the current balance + fetchedBalance, err := wallet.GetBalance() + if err != nil { + log.Infof("err fetching balance at %v: %v", time.Now(), err) + continue + } + if fetchedBalance.Cmp(currentBalance) != 0 { + // process balance change + go wallet.processBalanceChange(currentBalance, fetchedBalance, currentTip) + currentTip, _ = wallet.ChainTip() + currentBalance = fetchedBalance + } + } + } + }(wallet) +} + +func (wallet *EthereumWallet) processBalanceChange(previousBalance, currentBalance *big.Int, currentHead uint32) { + count := 0 + cTip := int(currentHead) + value := new(big.Int).Sub(currentBalance, previousBalance) + for count < 30 { + txns, err := wallet.TransactionsFromBlock(&cTip) + if err == nil && len(txns) > 0 { + count = 30 + txncb := wi.TransactionCallback{ + Txid: util.EnsureCorrectPrefix(txns[0].Txid), + Outputs: []wi.TransactionOutput{}, + Inputs: []wi.TransactionInput{}, + Height: txns[0].Height, + Timestamp: time.Now(), + Value: *value, + WatchOnly: false, + } + for _, l := range wallet.listeners { + go l(txncb) + } + continue + } + + time.Sleep(2 * time.Second) + count++ + } +} + +func (wallet *EthereumWallet) invokeTxnCB(txnID string, value *big.Int) { + txncb := wi.TransactionCallback{ + Txid: util.EnsureCorrectPrefix(txnID), + Outputs: []wi.TransactionOutput{}, + Inputs: []wi.TransactionInput{}, + Height: 0, + Timestamp: time.Now(), + Value: *value, + WatchOnly: false, + } + for _, l := range wallet.listeners { + go l(txncb) + } +} + +// CurrencyCode returns ETH +func (wallet *EthereumWallet) CurrencyCode() string { + if wallet.params == nil { + return "ETH" + } + if wallet.params.Name == chaincfg.MainNetParams.Name { + return "ETH" + } else { + return "TETH" + } + //return "ETH" +} + +// IsDust Check if this amount is considered dust - 10000 wei +func (wallet *EthereumWallet) IsDust(amount big.Int) bool { + return amount.Cmp(big.NewInt(10000)) <= 0 +} + +// MasterPrivateKey - Get the master private key +func (wallet *EthereumWallet) MasterPrivateKey() *hd.ExtendedKey { + return hd.NewExtendedKey([]byte{0x00, 0x00, 0x00, 0x00}, wallet.account.privateKey.D.Bytes(), + wallet.account.address.Bytes(), wallet.account.address.Bytes(), 0, 0, true) +} + +// MasterPublicKey - Get the master public key +func (wallet *EthereumWallet) MasterPublicKey() *hd.ExtendedKey { + publicKey := wallet.account.privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + log.Fatal("error casting public key to ECDSA") + } + + publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA) + return hd.NewExtendedKey([]byte{0x00, 0x00, 0x00, 0x00}, publicKeyBytes, + wallet.account.address.Bytes(), wallet.account.address.Bytes(), 0, 0, false) +} + +// ChildKey Generate a child key using the given chaincode. The key is used in multisig transactions. +// For most implementations this should just be child key 0. +func (wallet *EthereumWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) { + + parentFP := []byte{0x00, 0x00, 0x00, 0x00} + version := []byte{0x04, 0x88, 0xad, 0xe4} // starts with xprv + if !isPrivateKey { + version = []byte{0x04, 0x88, 0xb2, 0x1e} + } + /* + hdKey := hd.NewExtendedKey( + version, + keyBytes, + chaincode, + parentFP, + 0, + 0, + isPrivateKey) + return hdKey.Child(0) + */ + + return hd.NewExtendedKey(version, keyBytes, chaincode, parentFP, 0, 0, isPrivateKey), nil +} + +// CurrentAddress - Get the current address for the given purpose +func (wallet *EthereumWallet) CurrentAddress(purpose wi.KeyPurpose) btcutil.Address { + return *wallet.address +} + +// NewAddress - Returns a fresh address that has never been returned by this function +func (wallet *EthereumWallet) NewAddress(purpose wi.KeyPurpose) btcutil.Address { + return *wallet.address +} + +// DecodeAddress - Parse the address string and return an address interface +func (wallet *EthereumWallet) DecodeAddress(addr string) (btcutil.Address, error) { + var ( + ethAddr common.Address + err error + ) + if len(addr) > 64 { + ethAddr, err = ethScriptToAddr(addr) + if err != nil { + log.Error(err.Error()) + } + } else { + ethAddr = common.HexToAddress(addr) + } + + return EthAddress{ðAddr}, err +} + +func ethScriptToAddr(addr string) (common.Address, error) { + rScriptBytes, err := hex.DecodeString(addr) + if err != nil { + return common.Address{}, err + } + rScript, err := DeserializeEthScript(rScriptBytes) + if err != nil { + return common.Address{}, err + } + _, sHash, err := GenScriptHash(rScript) + if err != nil { + return common.Address{}, err + } + return common.HexToAddress(sHash), nil +} + +// ScriptToAddress - ? +func (wallet *EthereumWallet) ScriptToAddress(script []byte) (btcutil.Address, error) { + return wallet.address, nil +} + +// HasKey - Returns if the wallet has the key for the given address +func (wallet *EthereumWallet) HasKey(addr btcutil.Address) bool { + if !util.IsValidAddress(addr.String()) { + return false + } + return wallet.account.Address().String() == addr.String() +} + +// Balance - Get the confirmed and unconfirmed balances +func (wallet *EthereumWallet) Balance() (confirmed, unconfirmed wi.CurrencyValue) { + var balance, ucbalance wi.CurrencyValue + bal, err := wallet.GetBalance() + if err == nil { + balance = wi.CurrencyValue{ + Value: *bal, + Currency: EthCurrencyDefinition, + } + } + ucbal, err := wallet.GetUnconfirmedBalance() + ucb := big.NewInt(0) + if err == nil { + if ucbal.Cmp(bal) > 0 { + ucb.Sub(ucbal, bal) + } + } + ucbalance = wi.CurrencyValue{ + Value: *ucb, + Currency: EthCurrencyDefinition, + } + return balance, ucbalance +} + +// TransactionsFromBlock - Returns a list of transactions for this wallet begining from the specified block +func (wallet *EthereumWallet) TransactionsFromBlock(startBlock *int) ([]wi.Txn, error) { + txns, err := wallet.client.eClient.NormalTxByAddress(util.EnsureCorrectPrefix(wallet.account.Address().String()), startBlock, nil, + 1, 0, false) + if err != nil { + log.Error("err fetching transactions : ", err) + return []wi.Txn{}, nil + } + + ret := []wi.Txn{} + for _, t := range txns { + status := wi.StatusConfirmed + prefix := "" + if t.IsError != 0 { + status = wi.StatusError + } + if strings.ToLower(t.From) == strings.ToLower(wallet.address.String()) { + prefix = "-" + } + tnew := wi.Txn{ + Txid: util.EnsureCorrectPrefix(t.Hash), + Value: prefix + t.Value.Int().String(), + Height: int32(t.BlockNumber), + Timestamp: t.TimeStamp.Time(), + WatchOnly: false, + Confirmations: int64(t.Confirmations), + Status: wi.StatusCode(status), + Bytes: []byte(t.Input), + } + ret = append(ret, tnew) + } + + return ret, nil +} + +// Transactions - Returns a list of transactions for this wallet +func (wallet *EthereumWallet) Transactions() ([]wi.Txn, error) { + return wallet.TransactionsFromBlock(nil) +} + +// GetTransaction - Get info on a specific transaction +func (wallet *EthereumWallet) GetTransaction(txid chainhash.Hash) (wi.Txn, error) { + tx, _, err := wallet.client.GetTransaction(common.HexToHash(util.EnsureCorrectPrefix(txid.String()))) + if err != nil { + return wi.Txn{}, err + } + + chainID, err := wallet.client.NetworkID(context.Background()) + if err != nil { + return wi.Txn{}, err + } + + msg, err := tx.AsMessage(types.NewEIP155Signer(chainID)) // HomesteadSigner{}) + if err != nil { + return wi.Txn{}, err + } + + //value := tx.Value().String() + fromAddr := msg.From() + toAddr := msg.To() + valueSub := big.NewInt(5000000) + + v, err := wallet.registry.GetRecommendedVersion(nil, "escrow") + if err == nil { + if tx.To().String() == v.Implementation.String() { + toAddr = wallet.address.address + } + if msg.Value().Cmp(valueSub) > 0 { + valueSub = msg.Value() + } + } + + return wi.Txn{ + Txid: util.EnsureCorrectPrefix(tx.Hash().Hex()), + Value: tx.Value().String(), + Height: 0, + Timestamp: time.Now(), + WatchOnly: false, + Bytes: tx.Data(), + ToAddress: util.EnsureCorrectPrefix(tx.To().String()), + FromAddress: util.EnsureCorrectPrefix(msg.From().Hex()), + Outputs: []wi.TransactionOutput{ + { + Address: EthAddress{toAddr}, + Value: *valueSub, + Index: 0, + }, + { + Address: EthAddress{&fromAddr}, + Value: *valueSub, + Index: 1, + }, + { + Address: EthAddress{msg.To()}, + Value: *valueSub, + Index: 2, + }, + }, + }, nil +} + +// ChainTip - Get the height and best hash of the blockchain +func (wallet *EthereumWallet) ChainTip() (uint32, chainhash.Hash) { + num, hash, err := wallet.client.GetLatestBlock() + if err != nil { + return 0, *emptyChainHash + } + h, err := util.CreateChainHash(hash.Hex()) + if err != nil { + log.Error(err.Error()) + h = emptyChainHash + } + return num, *h +} + +// GetFeePerByte - Get the current fee per byte +func (wallet *EthereumWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + est, err := wallet.client.GetEthGasStationEstimate() + ret := big.NewInt(0) + if err != nil { + log.Errorf("err fetching ethgas station data: %v", err) + return *ret + } + switch feeLevel { + case wi.NORMAL: + ret, _ = big.NewFloat(est.Average * 100000000).Int(nil) + case wi.ECONOMIC, wi.SUPER_ECONOMIC: + ret, _ = big.NewFloat(est.SafeLow * 100000000).Int(nil) + case wi.PRIORITY, wi.FEE_BUMP: + ret, _ = big.NewFloat(est.Fast * 100000000).Int(nil) + } + return *ret +} + +// Spend - Send ether to an external wallet +func (wallet *EthereumWallet) Spend(amount big.Int, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { + var hash common.Hash + var h *chainhash.Hash + var err error + actualRecipient := addr + + if referenceID == "" { + // no referenceID means this is a direct transfer + hash, err = wallet.Transfer(util.EnsureCorrectPrefix(addr.String()), &amount, spendAll, wallet.GetFeePerByte(feeLevel)) + } else { + // this is a spend which means it has to be linked to an order + // specified using the referenceID + + // check if the addr is a multisig addr + scripts, err := wallet.db.WatchedScripts().GetAll() + if err != nil { + return nil, err + } + isScript := false + addrEth := common.HexToAddress(addr.String()) + key := addrEth.Bytes() + redeemScript := []byte{} + + for _, script := range scripts { + if bytes.Equal(key, script[:common.AddressLength]) { + isScript = true + redeemScript = script[common.AddressLength:] + break + } + } + + if isScript { + ethScript, err := DeserializeEthScript(redeemScript) + if err != nil { + return nil, err + } + _, scrHash, err := GenScriptHash(ethScript) + if err != nil { + log.Error(err.Error()) + } + addrScrHash := common.HexToAddress(scrHash) + actualRecipient = EthAddress{address: &addrScrHash} + hash, _, err = wallet.callAddTransaction(ethScript, &amount, feeLevel) + if err != nil { + log.Errorf("error call add txn: %v", err) + return nil, wi.ErrInsufficientFunds + } + } else { + if !wallet.balanceCheck(feeLevel, amount) { + return nil, wi.ErrInsufficientFunds + } + hash, err = wallet.Transfer(util.EnsureCorrectPrefix(addr.String()), &amount, spendAll, wallet.GetFeePerByte(feeLevel)) + } + if err != nil { + return nil, err + } + + // txn is pending + nonce, err := wallet.client.GetTxnNonce(util.EnsureCorrectPrefix(hash.Hex())) + if err == nil { + data, err := SerializePendingTxn(PendingTxn{ + TxnID: hash, + Amount: amount.String(), + OrderID: referenceID, + Nonce: nonce, + From: wallet.address.EncodeAddress(), + To: actualRecipient.EncodeAddress(), + WithInput: false, + }) + if err == nil { + err0 := wallet.db.Txns().Put(data, ut.NormalizeAddress(hash.Hex()), "0", 0, time.Now(), true) + if err0 != nil { + log.Error(err0.Error()) + } + } + } + } + + if err == nil { + h, err = util.CreateChainHash(hash.Hex()) + if err == nil { + wallet.invokeTxnCB(h.String(), &amount) + } + } + return h, err +} + +func (wallet *EthereumWallet) createTxnCallback(txID, orderID string, toAddress btcutil.Address, value big.Int, bTime time.Time, withInput bool) wi.TransactionCallback { + output := wi.TransactionOutput{ + Address: toAddress, + Value: value, + Index: 1, + OrderID: orderID, + } + + input := wi.TransactionInput{} + + if withInput { + input = wi.TransactionInput{ + OutpointHash: []byte(util.EnsureCorrectPrefix(txID)), + OutpointIndex: 1, + LinkedAddress: toAddress, + Value: value, + OrderID: orderID, + } + + } + + return wi.TransactionCallback{ + Txid: util.EnsureCorrectPrefix(txID), + Outputs: []wi.TransactionOutput{output}, + Inputs: []wi.TransactionInput{input}, + Height: 1, + Timestamp: time.Now(), + Value: value, + WatchOnly: false, + BlockTime: bTime, + } +} + +func (wallet *EthereumWallet) AssociateTransactionWithOrder(txnCB wi.TransactionCallback) { + for _, l := range wallet.listeners { + go l(txnCB) + } +} + +// checkTxnRcpt check the txn rcpt status +func (wallet *EthereumWallet) checkTxnRcpt(hash *common.Hash, data []byte) (*common.Hash, error) { + var rcpt *types.Receipt + pTxn, err := DeserializePendingTxn(data) + if err != nil { + return nil, err + } + + rcpt, err = wallet.client.TransactionReceipt(context.Background(), *hash) + if err != nil { + log.Infof("fetching txn rcpt: %v", err) + } + + if rcpt != nil { + // good. so the txn has been processed but we have to account for failed + // but valid txn like some contract condition causing revert + if rcpt.Status > 0 { + // all good to update order state + chash, err := util.CreateChainHash((*hash).Hex()) + if err != nil { + return nil, err + } + err = wallet.db.Txns().Delete(chash) + if err != nil { + log.Errorf("err deleting the pending txn : %v", err) + } + n := new(big.Int) + n, _ = n.SetString(pTxn.Amount, 10) + toAddr := common.HexToAddress(pTxn.To) + withInput := true + if pTxn.Amount != "0" { + toAddr = common.HexToAddress(util.EnsureCorrectPrefix(pTxn.To)) + withInput = pTxn.WithInput + } + go wallet.AssociateTransactionWithOrder( + wallet.createTxnCallback(util.EnsureCorrectPrefix(hash.Hex()), pTxn.OrderID, EthAddress{&toAddr}, + *n, time.Now(), withInput)) + } + } + return hash, nil + +} + +// BumpFee - Bump the fee for the given transaction +func (wallet *EthereumWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { + return util.CreateChainHash(txid.String()) +} + +// EstimateFee - Calculates the estimated size of the transaction and returns the total fee for the given feePerByte +func (wallet *EthereumWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { + sum := big.NewInt(0) + for _, out := range outs { + gas, err := wallet.client.EstimateTxnGas(wallet.account.Address(), + common.HexToAddress(out.Address.String()), &out.Value) + if err != nil { + return *sum + } + sum.Add(sum, gas) + } + return *sum +} + +func (wallet *EthereumWallet) balanceCheck(feeLevel wi.FeeLevel, amount big.Int) bool { + fee := wallet.GetFeePerByte(feeLevel) + if fee.Int64() == 0 { + return false + } + // lets check if the caller has enough balance to make the + // multisign call + requiredBalance := new(big.Int).Mul(&fee, big.NewInt(maxGasLimit)) + requiredBalance = new(big.Int).Add(requiredBalance, &amount) + currentBalance, err := wallet.GetBalance() + if err != nil { + log.Error("err fetching eth wallet balance") + currentBalance = big.NewInt(0) + } + if requiredBalance.Cmp(currentBalance) > 0 { + // the wallet does not have the required balance + return false + } + return true +} + +// EstimateSpendFee - Build a spend transaction for the amount and return the transaction fee +func (wallet *EthereumWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + if !wallet.balanceCheck(feeLevel, amount) { + return *big.NewInt(0), wi.ErrInsufficientFunds + } + gas, err := wallet.client.EstimateGasSpend(wallet.account.Address(), &amount) + return *gas, err +} + +// SweepAddress - Build and broadcast a transaction that sweeps all coins from an address. If it is a p2sh multisig, the redeemScript must be included +func (wallet *EthereumWallet) SweepAddress(utxos []wi.TransactionInput, address *btcutil.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { + + outs := []wi.TransactionOutput{} + for i, in := range utxos { + out := wi.TransactionOutput{ + Address: wallet.address, + Value: in.Value, + Index: uint32(i), + OrderID: in.OrderID, + } + outs = append(outs, out) + } + + sigs, err := wallet.CreateMultisigSignature([]wi.TransactionInput{}, outs, key, *redeemScript, *big.NewInt(1)) + if err != nil { + return nil, err + } + + data, err := wallet.Multisign([]wi.TransactionInput{}, outs, sigs, []wi.Signature{}, *redeemScript, *big.NewInt(1), false) + if err != nil { + return nil, err + } + hash := common.BytesToHash(data) + + return util.CreateChainHash(hash.Hex()) +} + +// ExchangeRates - return the exchangerates +func (wallet *EthereumWallet) ExchangeRates() wi.ExchangeRates { + return wallet.exchangeRates +} + +func (wallet *EthereumWallet) callAddTransaction(script EthRedeemScript, value *big.Int, feeLevel wi.FeeLevel) (common.Hash, uint64, error) { + + h := common.BigToHash(big.NewInt(0)) + + // call registry to get the deployed address for the escrow ct + fromAddress := wallet.account.Address() + nonce, err := wallet.client.PendingNonceAt(context.Background(), fromAddress) + if err != nil { + log.Fatal(err) + } + gasPrice, err := wallet.client.SuggestGasPrice(context.Background()) + if err != nil { + log.Fatal(err) + } + gasPriceETHGAS := wallet.GetFeePerByte(feeLevel) + if gasPriceETHGAS.Int64() < gasPrice.Int64() { + gasPriceETHGAS = *gasPrice + } + auth := bind.NewKeyedTransactor(wallet.account.privateKey) + + auth.Nonce = big.NewInt(int64(nonce)) + auth.Value = value // in wei + auth.GasLimit = maxGasLimit // in units + auth.GasPrice = gasPrice + + // lets check if the caller has enough balance to make the + // multisign call + if !wallet.balanceCheck(feeLevel, *big.NewInt(0)) { + // the wallet does not have the required balance + return h, nonce, wi.ErrInsufficientFunds + } + + shash, _, err := GenScriptHash(script) + if err != nil { + return h, nonce, err + } + + smtct, err := NewEscrow(script.MultisigAddress, wallet.client) + if err != nil { + log.Fatalf("error initilaizing contract failed: %s", err.Error()) + } + + var tx *types.Transaction + tx, err = smtct.AddTransaction(auth, script.Buyer, script.Seller, + script.Moderator, script.Threshold, script.Timeout, shash, script.TxnID) + if err == nil { + h = tx.Hash() + } else { + return h, 0, err + } + + txns = append(txns, wi.Txn{ + Txid: tx.Hash().Hex(), + Value: value.String(), + Height: int32(nonce), + Timestamp: time.Now(), + WatchOnly: false, + Bytes: tx.Data()}) + + return h, nonce, err + +} + +// GenerateMultisigScript - Generate a multisig script from public keys. If a timeout is included the returned script should be a timelocked escrow which releases using the timeoutKey. +func (wallet *EthereumWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (btcutil.Address, []byte, error) { + if uint32(timeout.Hours()) > 0 && timeoutKey == nil { + return nil, nil, errors.New("timeout key must be non nil when using an escrow timeout") + } + + if len(keys) < threshold { + return nil, nil, fmt.Errorf("unable to generate multisig script with "+ + "%d required signatures when there are only %d public "+ + "keys available", threshold, len(keys)) + } + + if len(keys) < 2 { + return nil, nil, fmt.Errorf("unable to generate multisig script with "+ + "%d required signatures when there are only %d public "+ + "keys available", threshold, len(keys)) + } + + var ecKeys []common.Address + for _, key := range keys { + ecKey, err := key.ECPubKey() + if err != nil { + return nil, nil, err + } + ePubkey := ecKey.ToECDSA() + ecKeys = append(ecKeys, crypto.PubkeyToAddress(*ePubkey)) + } + + ver, err := wallet.registry.GetRecommendedVersion(nil, "escrow") + if err != nil { + log.Fatal(err) + } + + if util.IsZeroAddress(ver.Implementation) { + return nil, nil, errors.New("no escrow contract available") + } + + builder := EthRedeemScript{} + + builder.TxnID = common.BytesToAddress(util.ExtractChaincode(&keys[0])) + builder.Timeout = uint32(timeout.Hours()) + builder.Threshold = uint8(threshold) + builder.Buyer = ecKeys[0] + builder.Seller = ecKeys[1] + builder.MultisigAddress = ver.Implementation + + if threshold > 1 { + builder.Moderator = ecKeys[2] + } + switch threshold { + case 1: + { + // Seller is offline + } + case 2: + { + // Moderated payment + } + default: + { + // handle this + } + } + + redeemScript, err := SerializeEthScript(builder) + if err != nil { + return nil, nil, err + } + + addr := common.HexToAddress(hexutil.Encode(crypto.Keccak256(redeemScript))) //hash.Sum(nil)[:])) + retAddr := EthAddress{&addr} + + scriptKey := append(addr.Bytes(), redeemScript...) + err = wallet.db.WatchedScripts().Put(scriptKey) + if err != nil { + log.Errorf("err saving the redeemscript: %v", err) + } + + return retAddr, redeemScript, nil +} + +// CreateMultisigSignature - Create a signature for a multisig transaction +func (wallet *EthereumWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + + payouts := []wi.TransactionOutput{} + difference := new(big.Int) + + if len(ins) > 0 { + totalVal := ins[0].Value + outVal := new(big.Int) + for _, out := range outs { + outVal = new(big.Int).Add(outVal, &out.Value) + } + if totalVal.Cmp(outVal) != 0 { + if totalVal.Cmp(outVal) < 0 { + return nil, errors.New("payout greater than initial amount") + } + difference = new(big.Int).Sub(&totalVal, outVal) + } + } + + rScript, err := DeserializeEthScript(redeemScript) + if err != nil { + return nil, err + } + + indx := []int{} + mbvAddresses := make([]string, 3) + + for i, out := range outs { + if out.Value.Cmp(new(big.Int)) > 0 { + indx = append(indx, i) + } + if out.Address.String() == rScript.Moderator.Hex() { + mbvAddresses[0] = out.Address.String() + } else if out.Address.String() == rScript.Buyer.Hex() && (out.Value.Cmp(new(big.Int)) > 0) { + mbvAddresses[1] = out.Address.String() + } else { + mbvAddresses[2] = out.Address.String() + } + p := wi.TransactionOutput{ + Address: out.Address, + Value: out.Value, + Index: out.Index, + OrderID: out.OrderID, + } + payouts = append(payouts, p) + } + + if len(indx) > 0 { + diff := new(big.Int) + delta := new(big.Int) + diff.DivMod(difference, big.NewInt(int64(len(indx))), delta) + for _, i := range indx { + payouts[i].Value.Add(&payouts[i].Value, diff) + } + payouts[indx[0]].Value.Add(&payouts[indx[0]].Value, delta) + } + + sort.Slice(payouts, func(i, j int) bool { + return strings.Compare(payouts[i].Address.String(), payouts[j].Address.String()) == -1 + }) + + var sigs []wi.Signature + + payables := make(map[string]big.Int) + addresses := []string{} + for _, out := range payouts { + if out.Value.Cmp(big.NewInt(0)) <= 0 { + continue + } + val := new(big.Int).SetBytes(out.Value.Bytes()) // &out.Value + if p, ok := payables[out.Address.String()]; ok { + sum := new(big.Int).Add(val, &p) + payables[out.Address.String()] = *sum + } else { + payables[out.Address.String()] = *val + addresses = append(addresses, out.Address.String()) + } + } + + sort.Strings(addresses) + destArr := []byte{} + amountArr := []byte{} + + for _, k := range mbvAddresses { + v := payables[k] + if v.Cmp(big.NewInt(0)) != 1 { + continue + } + addr := common.HexToAddress(k) + sample := [32]byte{} + sampleDest := [32]byte{} + copy(sampleDest[12:], addr.Bytes()) + val := v.Bytes() + l := len(val) + + copy(sample[32-l:], val) + destArr = append(destArr, sampleDest[:]...) + amountArr = append(amountArr, sample[:]...) + } + + shash, _, err := GenScriptHash(rScript) + if err != nil { + return nil, err + } + + var txHash [32]byte + var payloadHash [32]byte + + /* + // Follows ERC191 signature scheme: https://github.com/ethereum/EIPs/issues/191 + bytes32 txHash = keccak256( + abi.encodePacked( + "\x19Ethereum Signed Message:\n32", + keccak256( + abi.encodePacked( + byte(0x19), + byte(0), + this, + destinations, + amounts, + scriptHash + ) + ) + ) + ); + + */ + + payload := []byte{byte(0x19), byte(0)} + payload = append(payload, rScript.MultisigAddress.Bytes()...) + payload = append(payload, destArr...) + payload = append(payload, amountArr...) + payload = append(payload, shash[:]...) + + pHash := crypto.Keccak256(payload) + copy(payloadHash[:], pHash) + + txData := []byte{byte(0x19)} + txData = append(txData, []byte("Ethereum Signed Message:\n32")...) + txData = append(txData, payloadHash[:]...) + txnHash := crypto.Keccak256(txData) + log.Debugf("txnHash : %s", hexutil.Encode(txnHash)) + log.Debugf("phash : %s", hexutil.Encode(payloadHash[:])) + copy(txHash[:], txnHash) + + sig, err := crypto.Sign(txHash[:], wallet.account.privateKey) + if err != nil { + log.Errorf("error signing in createmultisig : %v", err) + } + sigs = append(sigs, wi.Signature{InputIndex: 1, Signature: sig}) + + return sigs, err +} + +// Multisign - Combine signatures and optionally broadcast +func (wallet *EthereumWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + + payouts := []wi.TransactionOutput{} + difference := new(big.Int) + + if len(ins) > 0 { + totalVal := &ins[0].Value + outVal := new(big.Int) + for _, out := range outs { + outVal.Add(outVal, &out.Value) + } + if totalVal.Cmp(outVal) != 0 { + if totalVal.Cmp(outVal) < 0 { + return nil, errors.New("payout greater than initial amount") + } + difference.Sub(totalVal, outVal) + } + } + + rScript, err := DeserializeEthScript(redeemScript) + if err != nil { + return nil, err + } + + indx := []int{} + referenceID := "" + mbvAddresses := make([]string, 3) + + for i, out := range outs { + if out.Value.Cmp(new(big.Int)) > 0 { + indx = append(indx, i) + } + if out.Address.String() == rScript.Moderator.Hex() { + indx = append(indx, i) + mbvAddresses[0] = out.Address.String() + } else if out.Address.String() == rScript.Buyer.Hex() { + mbvAddresses[1] = out.Address.String() + } else { + mbvAddresses[2] = out.Address.String() + } + p := wi.TransactionOutput{ + Address: out.Address, + Value: out.Value, + Index: out.Index, + OrderID: out.OrderID, + } + referenceID = out.OrderID + payouts = append(payouts, p) + } + + if len(indx) > 0 { + diff := new(big.Int) + delta := new(big.Int) + diff.DivMod(difference, big.NewInt(int64(len(indx))), delta) + for _, i := range indx { + payouts[i].Value.Add(&payouts[i].Value, diff) + } + payouts[indx[0]].Value.Add(&payouts[indx[0]].Value, delta) + } + + sort.Slice(payouts, func(i, j int) bool { + return strings.Compare(payouts[i].Address.String(), payouts[j].Address.String()) == -1 + }) + + payables := make(map[string]big.Int) + for _, out := range payouts { + if out.Value.Cmp(big.NewInt(0)) <= 0 { + continue + } + val := new(big.Int).SetBytes(out.Value.Bytes()) // &out.Value + if p, ok := payables[out.Address.String()]; ok { + sum := new(big.Int).Add(val, &p) + payables[out.Address.String()] = *sum + } else { + payables[out.Address.String()] = *val + } + } + + rSlice := [][32]byte{} + sSlice := [][32]byte{} + vSlice := []uint8{} + + var r [32]byte + var s [32]byte + var v uint8 + + if len(sigs1) > 0 && len(sigs1[0].Signature) > 0 { + r, s, v = util.SigRSV(sigs1[0].Signature) + rSlice = append(rSlice, r) + sSlice = append(sSlice, s) + vSlice = append(vSlice, v) + } + + if len(sigs2) > 0 && len(sigs2[0].Signature) > 0 { + r, s, v = util.SigRSV(sigs2[0].Signature) + rSlice = append(rSlice, r) + sSlice = append(sSlice, s) + vSlice = append(vSlice, v) + } + + shash, _, err := GenScriptHash(rScript) + if err != nil { + return nil, err + } + + smtct, err := NewEscrow(rScript.MultisigAddress, wallet.client) + if err != nil { + log.Fatalf("error initializing contract failed: %s", err.Error()) + } + + destinations := []common.Address{} + amounts := []*big.Int{} + + for _, k := range mbvAddresses { + v := payables[k] + if v.Cmp(big.NewInt(0)) == 1 { + destinations = append(destinations, common.HexToAddress(k)) + amounts = append(amounts, new(big.Int).SetBytes(v.Bytes())) + } + } + + fromAddress := wallet.account.Address() + nonce, err := wallet.client.PendingNonceAt(context.Background(), fromAddress) + if err != nil { + log.Fatal(err) + } + gasPrice, err := wallet.client.SuggestGasPrice(context.Background()) + if err != nil { + log.Fatal(err) + } + auth := bind.NewKeyedTransactor(wallet.account.privateKey) + + auth.Nonce = big.NewInt(int64(nonce)) + auth.Value = big.NewInt(0) // in wei + auth.GasLimit = maxGasLimit // in units + auth.GasPrice = gasPrice + + // lets check if the caller has enough balance to make the + // multisign call + requiredBalance := new(big.Int).Mul(gasPrice, big.NewInt(maxGasLimit)) + currentBalance, err := wallet.GetBalance() + if err != nil { + log.Error("err fetching eth wallet balance") + currentBalance = big.NewInt(0) + } + + if requiredBalance.Cmp(currentBalance) > 0 { + // the wallet does not have the required balance + return nil, wi.ErrInsufficientFunds + } + + tx, txnErr := smtct.Execute(auth, vSlice, rSlice, sSlice, shash, destinations, amounts) + + if txnErr != nil { + return nil, txnErr + } + + txns = append(txns, wi.Txn{ + Txid: tx.Hash().Hex(), + Value: "0", + Height: int32(nonce), + Timestamp: time.Now(), + WatchOnly: false, + Bytes: tx.Data()}) + + // this is a pending txn + _, scrHash, err := GenScriptHash(rScript) + if err != nil { + log.Error(err.Error()) + } + data, err := SerializePendingTxn(PendingTxn{ + TxnID: tx.Hash(), + Amount: "0", + OrderID: referenceID, + Nonce: int32(nonce), + From: wallet.address.EncodeAddress(), + To: scrHash, + }) + if err == nil { + err0 := wallet.db.Txns().Put(data, ut.NormalizeAddress(tx.Hash().Hex()), "0", 0, time.Now(), true) + if err0 != nil { + log.Error(err0.Error()) + } + } + + return tx.Hash().Bytes(), nil +} + +// AddWatchedAddresses - Add a script to the wallet and get notifications back when coins are received or spent from it +func (wallet *EthereumWallet) AddWatchedAddresses(addrs ...btcutil.Address) error { + // the reason eth wallet cannot use this as of now is because only the address + // is insufficient, the redeemScript is also required + return nil +} + +// AddTransactionListener will call the function callback when new transactions are discovered +func (wallet *EthereumWallet) AddTransactionListener(callback func(wi.TransactionCallback)) { + // add incoming txn listener using service + wallet.listeners = append(wallet.listeners, callback) +} + +// ReSyncBlockchain - Use this to re-download merkle blocks in case of missed transactions +func (wallet *EthereumWallet) ReSyncBlockchain(fromTime time.Time) { + // use service here +} + +// GetConfirmations - Return the number of confirmations and the height for a transaction +func (wallet *EthereumWallet) GetConfirmations(txid chainhash.Hash) (confirms, atHeight uint32, err error) { + // TODO: etherscan api is being used + // when mainnet is activated we may need a way to set the + // url correctly - done 6 April 2019 + hash := common.HexToHash(util.EnsureCorrectPrefix(txid.String())) + network := etherscan.Rinkby + if strings.Contains(wallet.client.url, "mainnet") { + network = etherscan.Mainnet + } + urlStr := fmt.Sprintf("https://%s.etherscan.io/api?module=proxy&action=eth_getTransactionByHash&txhash=%s&apikey=%s", + network, hash.String(), EtherScanAPIKey) + res, err := http.Get(urlStr) + if err != nil { + return 0, 0, err + } + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return 0, 0, err + } + if len(body) == 0 { + return 0, 0, errors.New("invalid txn hash") + } + var s map[string]interface{} + err = json.Unmarshal(body, &s) + if err != nil { + return 0, 0, err + } + + if s["result"] == nil { + return 0, 0, errors.New("invalid txn hash") + } + + if s["message"] != nil { + return 0, 0, nil + } + + result := s["result"].(map[string]interface{}) + + var d, conf int64 + if result["blockNumber"] != nil { + d, _ = strconv.ParseInt(result["blockNumber"].(string), 0, 64) + } else { + d = 0 + } + + n, err := wallet.client.HeaderByNumber(context.Background(), nil) + if err != nil { + return 0, 0, err + } + + if d != 0 { + conf = n.Number.Int64() - d + 1 + } else { + conf = 0 + } + + return uint32(conf), uint32(d), nil +} + +// Close will stop the wallet daemon +func (wallet *EthereumWallet) Close() { + // stop the wallet daemon + done <- true + doneBalanceTicker <- true +} + +// CreateAddress - used to generate a new address +func (wallet *EthereumWallet) CreateAddress() (common.Address, error) { + fromAddress := wallet.account.Address() + nonce, err := wallet.client.PendingNonceAt(context.Background(), fromAddress) + if err != nil { + log.Error(err.Error()) + } + addr := crypto.CreateAddress(fromAddress, nonce) + return addr, err +} + +// PrintKeys - used to print the keys for this wallet +func (wallet *EthereumWallet) PrintKeys() { + privateKeyBytes := crypto.FromECDSA(wallet.account.privateKey) + log.Debug(string(privateKeyBytes)) + publicKey := wallet.account.privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + log.Fatal("error casting public key to ECDSA") + } + + publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA) + address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex() + log.Debug(address) + log.Debug(string(publicKeyBytes)) +} + +// GenWallet creates a wallet +func GenWallet() { +} + +// GenDefaultKeyStore will generate a default keystore +func GenDefaultKeyStore(passwd string) (*Account, error) { + ks := keystore.NewKeyStore("./", keystore.StandardScryptN, keystore.StandardScryptP) + account, err := ks.NewAccount(passwd) + if err != nil { + return nil, err + } + return NewAccountFromKeyfile(account.URL.Path, passwd) +} diff --git a/vendor/github.com/phoreproject/go-ethwallet/wallet/wallet_test.go b/vendor/github.com/phoreproject/go-ethwallet/wallet/wallet_test.go new file mode 100644 index 0000000000..628cd9b413 --- /dev/null +++ b/vendor/github.com/phoreproject/go-ethwallet/wallet/wallet_test.go @@ -0,0 +1,707 @@ +package wallet + +import ( + "bytes" + "context" + "crypto/rand" + "encoding/binary" + "fmt" + "math/big" + "net/url" + "testing" + "time" + + wi "github.com/OpenBazaar/wallet-interface" + "github.com/btcsuite/btcd/chaincfg/chainhash" + hd "github.com/btcsuite/btcutil/hdkeychain" + "github.com/davecgh/go-spew/spew" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/phoreproject/multiwallet/config" + log "github.com/sirupsen/logrus" + + "github.com/phoreproject/go-ethwallet/util" +) + +const ( + magicOrderID = "iamanorderid" +) + +var validRopstenURL = fmt.Sprintf("https://ropsten.infura.io/%s", validInfuraKey) +var validRinkebyURL = fmt.Sprintf("https://rinkeby.infura.io/%s", validInfuraKey) + +var validSampleWallet *EthereumWallet +var destWallet *EthereumWallet + +var script EthRedeemScript + +var cfg config.CoinConfig + +func setupSourceWallet() { + //validRopstenWallet = NewEthereumWalletWithKeyfile(validRopstenURL, validKeyFile, validPassword) + setupCoinConfigRinkeby() + validSampleWallet, _ = NewEthereumWallet(cfg, mnemonicStr, nil) +} + +func setupDestWallet() { + destWallet = NewEthereumWalletWithKeyfile(validRinkebyURL, + "../test/UTC--2018-06-16T20-09-33.726552102Z--cecb952de5b23950b15bfd49302d1bdd25f9ee67", validPassword) +} + +func setupEthRedeemScript(timeout time.Duration, threshold int) { + + chaincode := make([]byte, 32) + _, err := rand.Read(chaincode) + fmt.Println("chiancode : ", chaincode) + if err != nil { + fmt.Println(err) + chaincode = []byte("423b5d4c32345ced77393b3530b1eed1") + } + //chaincode := []byte("423b5d4c32345ced77393b3530b1eed1") + script.TxnID = common.BytesToAddress(chaincode) // .HexToAddress(string(chaincode)) // common.HexToAddress(xid.New().String() + xid.New().String()) + script.Timeout = uint32(timeout.Hours()) + script.Threshold = uint8(threshold) + script.Buyer = common.HexToAddress(mnemonicStrAddress) + script.Seller = common.HexToAddress(validDestinationAddress) + script.Moderator = common.BigToAddress(big.NewInt(0)) + script.MultisigAddress = common.HexToAddress("0x36e19e91DFFCA4251f4fB541f5c3a596252eA4BB") + + //fmt.Println("in setup script: ") + //spew.Dump(script) +} + +func setupCoinConfigRopsten() { + clientURL, _ := url.Parse("https://ropsten.infura.io") + cfg.ClientAPIs = []string{(*clientURL).String()} + cfg.CoinType = wi.Ethereum + cfg.Options = make(map[string]interface{}) + //cfg.Options["RegistryAddress"] = "0x029d6a0cd4ce98315690f4ea52945545d9c0f460" + cfg.Options["RegistryAddress"] = "0x403d907982474cdd51687b09a8968346159378f3" +} + +func setupCoinConfigRinkeby() { + clientURL, _ := url.Parse("https://rinkeby.infura.io") + cfg.ClientAPIs = []string{(*clientURL).String()} + cfg.CoinType = wi.Ethereum + cfg.Options = make(map[string]interface{}) + cfg.Options["RegistryAddress"] = "0x403d907982474cdd51687b09a8968346159378f3" //"0xab8dd0e05b73529b440d9c9df00b5f490c8596ff" +} + +type MockWatchedScripts struct { + Name string +} + +func (m MockWatchedScripts) Put(script []byte) error { + return nil +} + +func (m MockWatchedScripts) GetAll() ([][]byte, error) { + return [][]byte{}, nil +} + +func (m MockWatchedScripts) Delete([]byte) error { + return nil +} + +type MockDatastore struct { + keys wi.Keys + utxos wi.Utxos + stxos wi.Stxos + txns wi.Txns + watchedScripts wi.WatchedScripts +} + +func (m MockDatastore) Keys() wi.Keys { + return m.keys +} + +func (m MockDatastore) Utxos() wi.Utxos { + return m.utxos +} + +func (m MockDatastore) Stxos() wi.Stxos { + return m.stxos +} + +func (m MockDatastore) Txns() wi.Txns { + return m.txns +} + +func (m MockDatastore) WatchedScripts() wi.WatchedScripts { + return m.watchedScripts +} + +func TestNewWalletWithValidKeyfileValues(t *testing.T) { + wallet := NewEthereumWalletWithKeyfile(validRopstenURL, validKeyFile, validPassword) + if wallet == nil { + t.Errorf("valid credentials should return a wallet") + } + if wallet.address.String() != validSourceAddress { + t.Errorf("valid credentials should return a wallet with proper initialization") + } +} + +func TestNewWalletWithInValidValues(t *testing.T) { + t.SkipNow() + wallet := NewEthereumWalletWithKeyfile(validRopstenURL, validKeyFile, invalidPassword) + if wallet != nil { + t.Errorf("invalid credentials should return a wallet") + } +} + +func TestNewWalletWithValidCoinConfigValues(t *testing.T) { + setupCoinConfigRinkeby() + wallet, err := NewEthereumWallet(cfg, mnemonicStr, nil) + if err != nil || wallet == nil { + t.Errorf("valid credentials should return a wallet") + } + fmt.Println(wallet.address.String()) + fmt.Println(validSourceAddress) + if wallet.address.String() != mnemonicStrAddress { + t.Errorf("valid credentials should return a wallet with proper initialization") + } +} + +func TestWalletChainTip(t *testing.T) { + setupSourceWallet() + + emptyHash, _ := chainhash.NewHashFromStr("") + + tip, hash := validSampleWallet.ChainTip() + + if hash.String() == emptyHash.String() { + t.Errorf("valid wallet should return chaintip") + } + fmt.Println("Chaintip is : ", tip) +} + +func TestWalletGetBalance(t *testing.T) { + setupSourceWallet() + + if _, err := validSampleWallet.GetBalance(); err != nil { + t.Errorf("valid wallet should return balance") + } +} + +func TestWalletGetUnconfirmedBalance(t *testing.T) { + setupSourceWallet() + + if _, err := validSampleWallet.GetUnconfirmedBalance(); err != nil { + t.Errorf("valid wallet should return unconfirmed balance") + } +} + +//$ GOCACHE=off go test -v ./... -run TestWalletGetTransaction -count=1 +func TestWalletGetTransaction(t *testing.T) { + setupSourceWallet() + + txID := "8a0f98762bd7be13a7a17ce45540110f2ca7cf7bda7397daff1532028a9bbe4d" + cHash, err := chainhash.NewHashFromStr(txID) + + if err != nil { + t.Errorf("chainhash should be created froma 32 byte string") + } + + txn, err := validSampleWallet.GetTransaction(*cHash) + if err != nil { + t.Errorf("wallet should fetch a txn from valid chainhash") + } + + spew.Dump(txn) + +} + +func TestWalletTransfer(t *testing.T) { + //t.SkipNow() + setupSourceWallet() + setupDestWallet() + + value := big.NewInt(99999000000) + + sbal1 := big.NewInt(0) + dbal1 := big.NewInt(0) + + cbal1, _ := validSampleWallet.GetBalance() + ucbal1, _ := validSampleWallet.GetUnconfirmedBalance() + + cbal2, _ := destWallet.GetBalance() + ucbal2, _ := destWallet.GetUnconfirmedBalance() + + sbal1.Add(cbal1, ucbal1) + dbal1.Add(cbal2, ucbal2) + + h, err := validSampleWallet.Transfer(validDestinationAddress, value) + + if err != nil { + fmt.Println("err in transfer : ", err) + return + } + + flag := false + var rcpt *types.Receipt + for !flag { + rcpt, err = validSampleWallet.client.TransactionReceipt(context.Background(), h) + if rcpt != nil { + flag = true + } + } + + if err != nil { + t.Errorf("valid wallet should allow transfer : %v", err) + } + + fmt.Println("rcpt") + spew.Dump(rcpt) + + //_, err = chainhash.NewHashFromStr(hash.Hex()[2:]) + + //if err != nil { + // t.Errorf("wallet should return a valid transaction") + //} + + //txn, err := validRopstenWallet.GetTransaction(*chash) + + //if err != nil { + // t.Errorf("wallet should return a valid transaction") + //} + + //if txn.Value != value.Int64() { + // t.Errorf("wallet is not forming the correct txn") + //} + + sbal2 := big.NewInt(0) + dbal2 := big.NewInt(0) + + cbal1, _ = validSampleWallet.GetBalance() + ucbal1, _ = validSampleWallet.GetUnconfirmedBalance() + + cbal2, _ = destWallet.GetBalance() + ucbal2, _ = destWallet.GetUnconfirmedBalance() + + sbal2.Add(cbal1, ucbal1) + dbal2.Add(cbal2, ucbal2) + + val := big.NewInt(0) + + val.Sub(dbal2, dbal1) + + if val.Cmp(value) != 0 && rcpt.Status == 0 { + t.Errorf("client should have transferred balance") + } + +} + +func TestWalletCurrencyCode(t *testing.T) { + setupSourceWallet() + + if validSampleWallet.CurrencyCode() != "ETH" { + t.Errorf("wallet should return proper currency code") + } +} + +func TestWalletIsDust(t *testing.T) { + setupSourceWallet() + + if validSampleWallet.IsDust(int64(10000 + 10000)) { + t.Errorf("wallet should not indicate wrong dust") + } + + if !validSampleWallet.IsDust(int64(10000 - 100)) { + t.Errorf("wallet should not indicate wrong dust") + } +} + +func TestWalletCurrentAddress(t *testing.T) { + setupSourceWallet() + + addr := validSampleWallet.CurrentAddress(wi.EXTERNAL) + + if addr.String() != mnemonicStrAddress { + t.Errorf("wallet should return correct current address") + } +} + +func TestWalletNewAddress(t *testing.T) { + setupSourceWallet() + + addr := validSampleWallet.NewAddress(wi.EXTERNAL) + + if addr.String() != mnemonicStrAddress { + t.Errorf("wallet should return correct new address") + } +} + +func TestWalletContractAddTransaction(t *testing.T) { + setupSourceWallet() + + ver, err := validSampleWallet.registry.GetRecommendedVersion(nil, "escrow") + if err != nil { + t.Error("error fetching escrow from registry") + } + + if util.IsZeroAddress(ver.Implementation) { + log.Infof("escrow not available") + return + } + + d, _ := time.ParseDuration("1h") + setupEthRedeemScript(d, 1) + + script.MultisigAddress = ver.Implementation + + redeemScript, err := SerializeEthScript(script) + if err != nil { + t.Error("error serializing redeem script") + } + + fmt.Println(redeemScript) + + spew.Dump(script) + + orderValue := big.NewInt(34567812347878) + + hash, err := validSampleWallet.callAddTransaction(script, orderValue) + + fmt.Println("returned hash : ", hash) + fmt.Println(err) + + chash, err := chainhash.NewHashFromStr(hash.Hex()[2:]) + + fmt.Println("err : ", err) + + if err == nil { + txn, err := validSampleWallet.GetTransaction(*chash) + + spew.Dump(txn) + fmt.Println(err) + } + + output := wi.TransactionOutput{ + Address: EthAddress{&script.Seller}, + Value: orderValue.Int64(), + Index: 1, + } + + hkey := hd.NewExtendedKey([]byte{}, []byte{}, []byte{}, []byte{}, 0, 0, false) + + sig, err := validSampleWallet.CreateMultisigSignature([]wi.TransactionInput{}, []wi.TransactionOutput{output}, + hkey, redeemScript, 2000) + + if err != nil { + fmt.Println(err) + } + + fmt.Println(sig) + + time.Sleep(5 * time.Minute) + + txBytes, err := validSampleWallet.Multisign([]wi.TransactionInput{}, + []wi.TransactionOutput{output}, + sig, []wi.Signature{wi.Signature{InputIndex: 1, Signature: []byte{}}}, redeemScript, + 20000, true) + //fmt.Println("after multisign") + //fmt.Println(txBytes) + fmt.Println("err : ", err) + + mtx := &types.Transaction{} + + mtx.UnmarshalJSON(txBytes) + + spew.Dump(mtx) + + sshh, sshhstr, _ := GenScriptHash(script) + + fmt.Println("script hash for ct : ", sshh) + fmt.Println(sshhstr) + +} + +func TestWalletContractScriptHash(t *testing.T) { + setupSourceWallet() + + ver, err := validSampleWallet.registry.GetRecommendedVersion(nil, "escrow") + if err != nil { + t.Error("error fetching escrow from registry") + } + + if util.IsZeroAddress(ver.Implementation) { + log.Infof("escrow not available") + return + } + + d, _ := time.ParseDuration("1h") + setupEthRedeemScript(d, 1) + + chaincode := []byte("423b5d4c32345ced77393b3530b1eed1") + + script.TxnID = common.BytesToAddress(chaincode) + + script.MultisigAddress = ver.Implementation + + /* + fmt.Println("buyer : ", script.Buyer) + fmt.Println("seller : ", script.Seller) + fmt.Println("moderator : ", script.Moderator) + fmt.Println("threshold : ", script.Threshold) + fmt.Println("timeout : ", script.Timeout) + fmt.Println("scrptHash : ", shash) + */ + + spew.Dump(script) + + smtct, err := NewEscrow(ver.Implementation, validSampleWallet.client) + if err != nil { + t.Errorf("error initilaizing contract failed: %s", err.Error()) + } + + retHash, err := smtct.CalculateRedeemScriptHash(nil, script.TxnID, script.Threshold, script.Timeout, script.Buyer, + script.Seller, script.Moderator, script.TokenAddress) + + fmt.Println(err) + fmt.Println("from smtct : ", retHash) + + rethash1Str := hexutil.Encode(retHash[:]) + fmt.Println("rethash1Str : ", rethash1Str) + + ahash := crypto.NewKeccak256() + a := make([]byte, 4) + binary.BigEndian.PutUint32(a, script.Timeout) + arr := append(script.TxnID.Bytes(), append([]byte{script.Threshold}, + append(a[:], append(script.Buyer.Bytes(), + append(script.Seller.Bytes(), append(script.Moderator.Bytes(), + append(script.MultisigAddress.Bytes())...)...)...)...)...)...) + ahash.Write(arr) + ahashStr := hexutil.Encode(ahash.Sum(nil)[:]) + + fmt.Println("computed : ", ahashStr) + + fmt.Println("priv key : ", validSampleWallet.account.privateKey) + + b := []byte{161, 162, 209, 139, 227, 101, 186, 196, 93, 247, 64, 186, 79, 166, 235, 225, 191, 123, 139, 89, 247, 48, 49, 71, 46, 130, 125, 221, 137, 35, 41, 51} + + fmt.Println(hexutil.Encode(b)) + + privateKeyBytes := crypto.FromECDSA(validSampleWallet.account.privateKey) + fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) + + fmt.Println("dest : ", script.MultisigAddress.String()[2:]) + fmt.Println("dest : ", string(script.MultisigAddress.Bytes())) + fmt.Println("dest : ", script.MultisigAddress.Hex()) + fmt.Println("dest : ", []byte(script.MultisigAddress.String())[2:]) + + a1, b1, c1 := GenScriptHash(script) + fmt.Println("scrpt hash : ", a1, " ", b1[2:], " ", c1) +} + +func TestWalletContractTxnHash(t *testing.T) { + t.Parallel() + + val := uint64(34567812347878) + //destStr := fmt.Sprintf("%064s", validDestinationAddress[2:]) + destAddress := common.HexToAddress(validDestinationAddress) + + orderValue := big.NewInt(34567812347878) + sample := [32]byte{} + sampleDest := [32]byte{} + atq := make([]byte, 8) + binary.BigEndian.PutUint64(atq, orderValue.Uint64()) + copy(sample[24:], atq) + + fmt.Println("sample : ", sample) + fmt.Println("val : ", orderValue.Bytes()) + fmt.Println("val2 : ", atq) + fmt.Println("dest : ", destAddress.Bytes()) + fmt.Println("len dest : ", len(destAddress.Bytes())) + copy(sampleDest[12:], destAddress.Bytes()) + + fmt.Println("sdest : ", sampleDest) + + var amountStr string + amountStr = fmt.Sprintf("%064s", fmt.Sprintf("%x", orderValue.Int64())) + + //fmt.Println("dest str : ", destStr) + fmt.Println("amnt str : ", amountStr) + + setupSourceWallet() + + d, _ := time.ParseDuration("1h") + setupEthRedeemScript(d, 1) + + //a1, b1, c1 := GenScriptHash(script) + //fmt.Println("scrpt hash : ", a1, " ", b1[2:], " ", c1) + + b1, err := hexutil.Decode("0x66cfea37109f1240d9d2f88643be076dc757883113a00a65ae8cd53d1e8411b4") + + b2 := byte(0x19) + b3 := byte(0) + + //payloadStr := string(b2) + string(b3) + script.MultisigAddress.String()[2:] + destStr + amountStr + + // b1[2:] + + //trialPayloadStr := "0x190036e19e91dffca4251f4fb541f5c3a596252ea4bb000000000000000000000000cecb952de5b23950b15bfd49302d1bdd25f9ee6700000000000000000000000000000000000000000000000000001f70722cf7e666cfea37109f1240d9d2f88643be076dc757883113a00a65ae8cd53d1e8411b4" + + //fmt.Println("payload str : ", payloadStr) + //fmt.Println("trial payload str : ", trialPayloadStr) + + at := make([]byte, 8) + binary.BigEndian.PutUint64(at, orderValue.Uint64()) + + at1 := make([]byte, 8) + binary.LittleEndian.PutUint64(at1, val) + + at2 := make([]byte, 8) + binary.BigEndian.PutUint64(at2, val) + + p1 := []byte{b2, b3} + p1 = append(p1, script.MultisigAddress.Bytes()...) + p1 = append(p1, sampleDest[:]...) + p1 = append(p1, sample[:]...) + //p1 = append(p1, destAddress.Bytes()...) + //p1 = append(p1, orderValue.Bytes()...) + //p1 = append(p1, at...) + //p1 = append(p1, []byte(amountStr)...) + //p1 = append(p1, at1...) + //p1 = append(p1, at2...) + p1 = append(p1, b1...) + + ahash := crypto.NewKeccak256() + //a := make([]byte, 4) + //binary.BigEndian.PutUint32(a, script.Timeout) + //arr := append(script.TxnID.Bytes(), append([]byte{script.Threshold}, + // append(a[:], append(script.Buyer.Bytes(), + // append(script.Seller.Bytes(), append(script.Moderator.Bytes(), + // append(script.MultisigAddress.Bytes())...)...)...)...)...)...) + + p11 := append([]byte{b2}, append([]byte{b3}, append(script.MultisigAddress.Bytes(), + append(destAddress.Bytes(), append(orderValue.Bytes(), + append(b1)...)...)...)...)...) + + ahash.Write(p11) + p11hash := ahash.Sum(nil)[:] + fmt.Println("www aaa : ", hexutil.Encode(p11hash)) + + pHash := crypto.Keccak256(p1) + var payloadHash [32]byte + copy(payloadHash[:], pHash) + + phash2, err := hexutil.Decode("0x7037f184ba846ff842222df065da84f5de500ad7ba0f996a4c7cdeff3520f4be") + + //phash2, err := hexutil.Decode("0x3a0312b6d025a3d21a257ad0a501a75026f9a3180c6d8c4fa2e92f7c12097310") + + if bytes.Equal(phash2, payloadHash[:]) { + fmt.Println("yes .... sssssssss .......") + } else { + fmt.Println("still not there yet ....") + fmt.Println("got payloadHash : ", hexutil.Encode(pHash)) + fmt.Println("wanted : ", "0x7037f184ba846ff842222df065da84f5de500ad7ba0f996a4c7cdeff3520f4be") + } + + //phash2 := []byte("7037f184ba846ff842222df065da84f5de500ad7ba0f996a4c7cdeff3520f4be") + + txData := []byte{byte(0x19)} + txData = append(txData, []byte("Ethereum Signed Message:\n32")...) + //txData = append(txData, byte(32)) + txData = append(txData, phash2...) + txnHash := crypto.Keccak256(txData) + fmt.Println("txnHash : ", hexutil.Encode(txnHash)) + var txHash [32]byte + copy(txHash[:], txnHash) + + sig, err := crypto.Sign(txHash[:], validSampleWallet.account.privateKey) + if err != nil { + log.Errorf("error signing in createmultisig : %v", err) + } + + spew.Dump(sig) + + r, s, v := util.SigRSV(sig) + + fmt.Println("r : ", hexutil.Encode(r[:])) + fmt.Println("s : ", hexutil.Encode(s[:])) + fmt.Println("v : ", v) + +} + +var listenerCallbackFlag bool + +func sampleListener(cb wi.TransactionCallback) { + fmt.Println("in sample listener ....") + spew.Dump(cb) + if len(cb.Outputs) > 0 && cb.Outputs[0].OrderID == magicOrderID { + listenerCallbackFlag = true + } +} + +func TestWalletSpend(t *testing.T) { + //t.SkipNow() + setupSourceWallet() + setupDestWallet() + + value := big.NewInt(99999000000) + + validSampleWallet.AddTransactionListener(sampleListener) + validSampleWallet.db = MockDatastore{watchedScripts: MockWatchedScripts{}} + listenerCallbackFlag = false + + h, err := validSampleWallet.Spend(value.Int64(), destWallet.address, 1, magicOrderID) + + if err != nil { + fmt.Println("err in transfer : ", err) + return + } + + spew.Dump(h) + + time.Sleep(1 * time.Minute) + + if !listenerCallbackFlag { + t.Errorf("spend is not calling back correctly") + } + +} + +// GOCACHE=off go test -v ./... -run TestWalletGetConfirmations -count=1 +func TestWalletGetConfirmations(t *testing.T) { + setupSourceWallet() + thash := "0x5315bbdb8b6370244ffb6fc41bf275e785355e567759fb15e85df6508eff9b35" + chainHash, err := chainhash.NewHashFromStr(thash[2:]) + if err != nil { + t.Error("chainhash not initialized properly") + } + conf, ht, err := validSampleWallet.GetConfirmations(*chainHash) + if err != nil { + t.Error("chainhash not initialized properly") + } + fmt.Println("confs : ", conf, " height : ", ht) + +} + +func TestWalletDecodeAddress(t *testing.T) { + setupSourceWallet() + d, _ := time.ParseDuration("1h") + setupEthRedeemScript(d, 1) + + script.MultisigAddress = ver.Implementation + + redeemScript, err := SerializeEthScript(script) + if err != nil { + t.Error("error serializing redeem script") + } + _, sHash, err := GenScriptHash(script) + if err != nil { + t.Error("error generating script hash for redeem script") + } + + addr, err := validSampleWallet.DecodeAddress(validDestinationAddress) + if err != nil || addr.String() != validDestinationAddress { + t.Error("error decoding valid address") + } + + notAddr, err := validSampleWallet.DecodeAddress(string(redeemScript)) + if err != nil || notAddr.String() != sHash { + t.Error("error decoding redeem script hash address") + } + +} diff --git a/vendor/github.com/phoreproject/multiwallet/.travis.yml b/vendor/github.com/phoreproject/multiwallet/.travis.yml deleted file mode 100644 index cf81ad5677..0000000000 --- a/vendor/github.com/phoreproject/multiwallet/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: go -go: - - "1.11" -sudo: required -services: - - docker -env: - - "PATH=/home/travis/gopath/bin:$PATH" -before_install: - - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - - go get github.com/tcnksm/ghr - - go get github.com/axw/gocov/gocov - - go get github.com/mattn/goveralls - - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.15.0 -install: - - dep ensure -script: - - $GOPATH/bin/golangci-lint run --deadline 10m --new - - cd $TRAVIS_BUILD_DIR && chmod a+x test_compile.sh && ./test_compile.sh - - goveralls -coverprofile=coverage.out -service travis-ci diff --git a/vendor/github.com/phoreproject/multiwallet/Gopkg.lock b/vendor/github.com/phoreproject/multiwallet/Gopkg.lock index cfbe5b5c32..77046299cd 100644 --- a/vendor/github.com/phoreproject/multiwallet/Gopkg.lock +++ b/vendor/github.com/phoreproject/multiwallet/Gopkg.lock @@ -3,7 +3,7 @@ [[projects]] branch = "master" - digest = "1:139894af9fdf6ed3836003686ddc34d0e2cc018f34d2beb26107841ea410b2b5" + digest = "1:12249c9e5740e17587799c25425a8058cb942da38e8226998cccc99a16dd9fe5" name = "github.com/OpenBazaar/golang-socketio" packages = [ ".", @@ -11,26 +11,58 @@ "transport", ] pruneopts = "UT" - revision = "909b73d947ae79609bc2c5b03cb480f35180c564" + revision = "4147b5f0d29491b7cacd6bf58d825f54fe2b24af" [[projects]] - branch = "master" - digest = "1:3861bd7ece0e78ea465eb4c2ee12391a2759755220c89729a7033b4af98b42e3" + digest = "1:e21227e72cf4f8bae158b4e99e4a02b794a3b0a2f7944120e5741f1e06d44f9a" + name = "github.com/OpenBazaar/openbazaar-go" + packages = ["util"] + pruneopts = "UT" + revision = "611749271ccdcc0e543d8f29076c5c76a5afab84" + version = "v0.14.4" + +[[projects]] + branch = "ethereum-master" + digest = "1:86e0f1a42b9747455720f88363ababc86ee61c66176a357ca2806e3353ce31a1" name = "github.com/OpenBazaar/spvwallet" packages = [ ".", "exchangerates", ] pruneopts = "UT" - revision = "a32d41681bf3a75473498711710d0123f1625ec8" + revision = "41f07b1fdcf5084530526cbf469e79437fbdc5dd" [[projects]] - branch = "master" - digest = "1:cdb20ba34409b4eb78ff013e71eafce40e49b42485dafcfb675b64c5cb3cdaca" + branch = "ethereum-master" + digest = "1:c411c1051b3ab7c823786bf82887580f2d93898be2504e145a67419afef5ba2d" name = "github.com/OpenBazaar/wallet-interface" packages = ["."] pruneopts = "UT" - revision = "aa8e214acd9b86f0c7a190d2eaf269070f5b5f3c" + revision = "cbbb40466dcfe7d299f685fd0aa9a4fe9ea49147" + +[[projects]] + digest = "1:9909e0a06cff3bd88841c9d2e0cc91b0a431676009018c74c3315f33b49b0046" + name = "github.com/StackExchange/wmi" + packages = ["."] + pruneopts = "UT" + revision = "cbe66965904dbe8a6cd589e2298e5d8b986bd7dd" + version = "1.1.0" + +[[projects]] + digest = "1:ef98291cf6c2dd0f53949a1899e9a58d3159ad44d20f74b62467bd2a807b01ce" + name = "github.com/VictoriaMetrics/fastcache" + packages = ["."] + pruneopts = "UT" + revision = "4d94f266cd3cecbcd97eaebee9e3d6d8cf918643" + version = "v1.4.6" + +[[projects]] + branch = "master" + digest = "1:7d191fd0c54ff370eaf6116a14dafe2a328df487baea280699f597aae858d00d" + name = "github.com/aristanetworks/goarista" + packages = ["monotime"] + pruneopts = "UT" + revision = "4cb0e71f3c0e159af0380c30a883d90ce3981df6" [[projects]] digest = "1:0f98f59e9a2f4070d66f0c9c39561f68fcd1dc837b22a852d28d0003aebd1b1e" @@ -41,25 +73,23 @@ version = "v1.3.1" [[projects]] - branch = "master" - digest = "1:9ea121968c59b51fd90167594e8dab47e89635b1749ec790d816929fd1a87699" + digest = "1:38e337477887a8935559e3042ce53f14fcc24fd66635b57f423965c8297ccc90" name = "github.com/btcsuite/btcd" packages = [ "addrmgr", "blockchain", "btcec", - "btcjson", "chaincfg", "chaincfg/chainhash", "connmgr", "database", "peer", - "rpcclient", "txscript", "wire", ] pruneopts = "UT" - revision = "5bda5314ca9549a589e63d7b2e6104492a0d5328" + revision = "f3ec13030e4e828869954472cbc51ac36bee5c1d" + version = "v0.20.1-beta" [[projects]] branch = "master" @@ -71,7 +101,7 @@ [[projects]] branch = "master" - digest = "1:43190b35675926c93f392feed190b2056efd1f4f1b247b559f2a63cc164fa104" + digest = "1:a6216bf9651ae303ea96fd94170333834a89fa2d9250114062a69b73f47bf1c6" name = "github.com/btcsuite/btcutil" packages = [ ".", @@ -83,20 +113,19 @@ "txsort", ] pruneopts = "UT" - revision = "ab6388e0c60ae4834a1f57511e20c17b5f78be4b" + revision = "4649e4b73b34090724fff8a302751260c20551fd" [[projects]] - branch = "master" - digest = "1:69e5357e344f35f1d3da320bf85271b5d5d758a826a52f132a3da29d6112fcc2" + digest = "1:7ffc24d91a12c173c18fe9ada86a05fc476f8943f4acffeddc6ec87a4f32bdef" name = "github.com/btcsuite/btcwallet" packages = [ - "internal/helpers", - "wallet/internal/txsizes", "wallet/txauthor", "wallet/txrules", + "wallet/txsizes", ] pruneopts = "UT" - revision = "177e31c0b3273c5f7422102cc65be55cbcfde957" + revision = "b19df70dddb66b27902f48cc48e69741909ef2e9" + version = "v0.11.0" [[projects]] branch = "master" @@ -127,20 +156,28 @@ version = "v1.0.0" [[projects]] - branch = "master" - digest = "1:0b2242fd2f4f51fb491e97e204464f75da680897a0db10ec7554c87b71b5afc3" - name = "github.com/btcsuite/websocket" + digest = "1:fe9b15f080d19c215514056bae7589d6958821766fb5f5fceb9402ec9df2f736" + name = "github.com/cenkalti/backoff" + packages = ["."] + pruneopts = "UT" + revision = "18fe4ce5a8550e0d0919b680ad3c080a5455bddf" + version = "v4.0.2" + +[[projects]] + digest = "1:61406f6571eeb97717bdfaac37fa0bc5260621c4cbf3ce7635e9828dcbb5258a" + name = "github.com/cespare/xxhash" packages = ["."] pruneopts = "UT" - revision = "31079b6807923eb23992c421b114992b95131b55" + revision = "d7df74196a9e781ede915320c11c378c1b2f3a1f" + version = "v2.1.1" [[projects]] branch = "master" - digest = "1:78097abc20f73ec968b3f67bf74deda55009caa4b801d0d04f36145c869ab3c3" + digest = "1:9d61b5ca59d3db0b1f1c1e9f5930b4f7c7fd954f54b70c1d83802b8805db918f" name = "github.com/cevaris/ordered_map" packages = ["."] pruneopts = "UT" - revision = "0efaee1733e3399a3cb88fc7d2ce340bf2e863d7" + revision = "3adeae072e730f1919a936e13b4923706d3f60fe" [[projects]] branch = "master" @@ -167,7 +204,98 @@ version = "v1.2.1" [[projects]] - digest = "1:700f82416846a964010b86fddeada0e1ceb1c96fa65acc4f234811a7d3e4fded" + digest = "1:e47d51dab652d26c3fba6f8cba403f922d02757a82abdc77e90df7948daf296e" + name = "github.com/deckarep/golang-set" + packages = ["."] + pruneopts = "UT" + revision = "cbaa98ba5575e67703b32b4b19f73c91f3c4159e" + version = "v1.7.1" + +[[projects]] + digest = "1:edb569dd02419a41ddd98768cc0e7aec922ef19dae139731e5ca750afcf6f4c5" + name = "github.com/edsrzf/mmap-go" + packages = ["."] + pruneopts = "UT" + revision = "188cc3b666ba704534fa4f96e9e61f21f1e1ba7c" + version = "v1.0.0" + +[[projects]] + digest = "1:63a46ee0ff674e15e7b72b276a79a001a8182b19ea493efae821ce3ee45465d5" + name = "github.com/ethereum/go-ethereum" + packages = [ + ".", + "accounts", + "accounts/abi", + "accounts/abi/bind", + "accounts/external", + "accounts/keystore", + "accounts/scwallet", + "accounts/usbwallet", + "accounts/usbwallet/trezor", + "common", + "common/bitutil", + "common/hexutil", + "common/math", + "common/mclock", + "common/prque", + "consensus", + "consensus/clique", + "consensus/ethash", + "consensus/misc", + "console/prompt", + "core", + "core/bloombits", + "core/rawdb", + "core/state", + "core/state/snapshot", + "core/types", + "core/vm", + "crypto", + "crypto/blake2b", + "crypto/bls12381", + "crypto/bn256", + "crypto/bn256/cloudflare", + "crypto/bn256/google", + "crypto/ecies", + "crypto/secp256k1", + "eth/downloader", + "ethclient", + "ethdb", + "ethdb/leveldb", + "ethdb/memorydb", + "event", + "internal/ethapi", + "log", + "metrics", + "p2p", + "p2p/discover", + "p2p/discover/v4wire", + "p2p/discv5", + "p2p/enode", + "p2p/enr", + "p2p/nat", + "p2p/netutil", + "params", + "rlp", + "rpc", + "signer/core", + "signer/storage", + "trie", + ] + pruneopts = "T" + revision = "3e0641923d78bf1905e596a3a41a54277540bec7" + version = "v1.9.19" + +[[projects]] + branch = "master" + digest = "1:fedce3f87da3944ec15789ff4d1d17e77554148626d079a9ffd2cae6112fdc8b" + name = "github.com/gballet/go-libpcsclite" + packages = ["."] + pruneopts = "UT" + revision = "4678299bea08415f0ca8bd71da9610625cc86e86" + +[[projects]] + digest = "1:3f445cedf6096f2686814dc4efe5cb81887a919997e33f3dcfebf2f1d4471a35" name = "github.com/gcash/bchd" packages = [ "bchec", @@ -177,8 +305,8 @@ "wire", ] pruneopts = "UT" - revision = "34d8b67e58c8487e08cc2b8130398ec4f4bc6df5" - version = "v0.14.6" + revision = "bbd130da6c02450131ddbc1c89cc8825b5e4dfb9" + version = "v0.16.5" [[projects]] branch = "master" @@ -190,18 +318,37 @@ [[projects]] branch = "master" - digest = "1:2538b5efd7d3d7ac9efdfef955f5bcda82cbec4d6f8aef4d388f1c70e6318fc5" + digest = "1:164e5db5eec3f48442a08de471a0fa272707b9bd857d75b923b56252b0e27c80" name = "github.com/gcash/bchutil" packages = [ ".", "base58", ] pruneopts = "UT" - revision = "800e62fe9aff291db8909a5dbf35c23cff8d1a62" + revision = "c2894cd54b332380c5821d22663eea1a677474ec" + +[[projects]] + digest = "1:440028f55cb322d8cb5b9d5ebec298a00b7d74690a658fe6b1c0c0b44341bfae" + name = "github.com/go-ole/go-ole" + packages = [ + ".", + "oleutil", + ] + pruneopts = "UT" + revision = "97b6244175ae18ea6eef668034fd6565847501c9" + version = "v1.2.4" + +[[projects]] + digest = "1:586ea76dbd0374d6fb649a91d70d652b7fe0ccffb8910a77468e7702e7901f3d" + name = "github.com/go-stack/stack" + packages = ["."] + pruneopts = "UT" + revision = "2fee6af1a9795aafbe0253a0cfbdf668e1fb8a9a" + version = "v1.8.0" [[projects]] branch = "master" - digest = "1:a54f931f516df9f3b2401e3cfa47482be79397d20fcbe838b7da6c63d5b8e615" + digest = "1:b32fff55ac1981dcd585dc0ecbf94f58aae01ce6698dd6496bb35cd66084f357" name = "github.com/golang/protobuf" packages = [ "proto", @@ -212,27 +359,102 @@ "ptypes/timestamp", ] pruneopts = "UT" - revision = "347cf4a86c1cb8d262994d8ef5924d4576c5b331" + revision = "d04d7b157bb510b1e0c10132224b616ac0e26b17" + +[[projects]] + digest = "1:e4f5819333ac698d294fe04dbf640f84719658d5c7ce195b10060cc37292ce79" + name = "github.com/golang/snappy" + packages = ["."] + pruneopts = "UT" + revision = "2a8bb927dd31d8daada140a5d09578521ce5c36a" + version = "v0.0.1" + +[[projects]] + digest = "1:582b704bebaa06b48c29b0cec224a6058a09c86883aaddabde889cd1a5f73e1b" + name = "github.com/google/uuid" + packages = ["."] + pruneopts = "UT" + revision = "0cd6bf5da1e1c83f8b45653022c74f71af0538a4" + version = "v1.1.1" [[projects]] branch = "master" - digest = "1:521455a43b348afa7e4deb79c471f3ed8ff04a71d7d9b88ab0d149b9eb905fe2" + digest = "1:6d29f02f0f01c627c2be40fb7347669a9ff2aa215cb97747294c1d13ffa74bdd" name = "github.com/gorilla/websocket" packages = ["."] pruneopts = "UT" - revision = "95ba29eb981bbb27d92e1f70bf8a1949452d926b" + revision = "b65e62901fc1c0d968042419e74789f6af455eb9" + +[[projects]] + digest = "1:e631368e174090a276fc00b48283f92ac4ccfbbb1945bcfcee083f5f9210dc00" + name = "github.com/hashicorp/golang-lru" + packages = [ + ".", + "simplelru", + ] + pruneopts = "UT" + revision = "14eae340515388ca95aa8e7b86f0de668e981f54" + version = "v0.5.4" + +[[projects]] + digest = "1:34cf99c4b2280251f09035ed0fbe6da4f05de37a26f425c7aab50f0d2731da92" + name = "github.com/holiman/uint256" + packages = ["."] + pruneopts = "UT" + revision = "99b79c80738390408ef1a47f0e26812ef5506c02" + version = "v1.1.1" + +[[projects]] + digest = "1:c00cc6d95a674b4b923ac069d364445043bc67836e9bd8aeff8440cfbe6a2cc7" + name = "github.com/huin/goupnp" + packages = [ + ".", + "dcps/internetgateway1", + "dcps/internetgateway2", + "httpu", + "scpd", + "soap", + "ssdp", + ] + pruneopts = "UT" + revision = "656e61dfadd241c7cbdd22a023fa81ecb6860ea8" + version = "v1.0.0" + +[[projects]] + digest = "1:94d189f7124eba234224e1a3d28b943d826d480cf71cc71d53c2eac8132f31ed" + name = "github.com/hunterlong/tokenbalance" + packages = ["."] + pruneopts = "UT" + revision = "1fcaffaac40cf0559ccba1276d90757bdf1284e9" + version = "v1.72" + +[[projects]] + digest = "1:71193da2829127d2cd7d2045175a65ef04d79176de5f1ebb185d331daa53b5c9" + name = "github.com/jackpal/go-nat-pmp" + packages = ["."] + pruneopts = "UT" + revision = "059203efa1edd7130293a583541b8308e7c640c4" + version = "v1.0.2" [[projects]] branch = "master" - digest = "1:459271b8268fe541549b299f65160b1df5abe9ffef0426cc38607f771dbc6bb4" + digest = "1:80291363a11a19e81a98fcca0185f7c4ba08f73d126082ce02fdc1ae72051b17" name = "github.com/jessevdk/go-flags" packages = ["."] pruneopts = "UT" - revision = "c0795c8afcf41dd1d786bebce68636c199b3bb45" + revision = "c17162fe8fd74f119ff938c5c67af63e3bac5ded" + +[[projects]] + branch = "master" + digest = "1:f275e994e11f9bec072885d81a8aaa1a95bdd0ebca4cd78f1d37d3d84f88f3b8" + name = "github.com/karalabe/usb" + packages = ["."] + pruneopts = "T" + revision = "911d15fe12a9c411cf5d0dd5635231c759399bed" [[projects]] branch = "master" - digest = "1:1d509f3d4933044d1416d2537d98a7caf11c4ddbbff2c466d5ebe8a7cea80b54" + digest = "1:f3622fddf3960b7789148414cc27c3a63ded5b51a8f9ddd9bc8475d358d7342c" name = "github.com/ltcsuite/ltcd" packages = [ "btcec", @@ -242,11 +464,11 @@ "wire", ] pruneopts = "UT" - revision = "f37f8bf35796325487af28e0e01c2528dd97ea95" + revision = "81094527da29ad5dd9e76d4d93bf9318608bfb6c" [[projects]] branch = "master" - digest = "1:61c97cb69387bafe67d376d09eb4059096f45343f5ba87a70ed217bfabb81a56" + digest = "1:4a8f4ed5c67d3c0fc545937fe6f219ccef71647fff5896a2ced32059986b11e5" name = "github.com/ltcsuite/ltcutil" packages = [ ".", @@ -254,15 +476,23 @@ "bech32", ] pruneopts = "UT" - revision = "17f3b04680b6521349067fb99d9f7495a9e96d60" + revision = "b11902d0cdac0b152b59fe015a1cbaadae459940" [[projects]] branch = "master" - digest = "1:a302d142a103687a0dc12e2c1fffc4128011b6ed27dbc969c549799b23f57b8d" + digest = "1:9e00f68fb323c190a11b0cbb41d4ad85855419b9c022f8d37d83243e51004b8b" name = "github.com/ltcsuite/ltcwallet" packages = ["wallet/txrules"] pruneopts = "UT" - revision = "3fa612e326e5f0f1cfa460711fd563d79bc2ef49" + revision = "8fab723115a21c5f07bf3536b8a580f7bb6b453b" + +[[projects]] + digest = "1:38286a6220cf5b85bae83d5754bbfd7218c833b4fc8b56f5d168ea4bc073ad27" + name = "github.com/mattn/go-runewidth" + packages = ["."] + pruneopts = "UT" + revision = "14e809f6d78fcf9f48ff9b70981472b64c05f754" + version = "v0.0.9" [[projects]] branch = "master" @@ -273,50 +503,194 @@ revision = "3f5f724cb5b182a5c278d6d3d55b40e7f8c2efb4" [[projects]] - digest = "1:78bbb1ba5b7c3f2ed0ea1eab57bdd3859aec7e177811563edc41198a760b06af" + digest = "1:5d231480e1c64a726869bc4142d270184c419749d34f167646baa21008eb0a79" name = "github.com/mitchellh/go-homedir" packages = ["."] pruneopts = "UT" - revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4" - version = "v1.0.0" + revision = "af06845cf3004701891bf4fdb884bfe4920b3727" + version = "v1.1.0" [[projects]] - branch = "master" - digest = "1:41f3b549dbb8216e490c27926c09dc055aa509b3476e7cbc3317103990b13aeb" + digest = "1:485c3634d6ad086bb117043863ed056bc46ad4cb60f4df2da9c78b4de4eeeb37" + name = "github.com/nanmu42/etherscan-api" + packages = ["."] + pruneopts = "UT" + revision = "42ada40c3d24212dba086b1ed6a4a7cccb7327a7" + version = "v1.1.1" + +[[projects]] + digest = "1:b8261a46d75566ebf5b4fb6bb762f54f47e6633e0995118393afc80bb1f428f5" + name = "github.com/olekukonko/tablewriter" + packages = ["."] + pruneopts = "UT" + revision = "876dd0e0227ec99c0243b639b92139915b65331a" + version = "v0.0.4" + +[[projects]] + digest = "1:5b3b29ce0e569f62935d9541dff2e16cc09df981ebde48e82259076a73a3d0c7" name = "github.com/op/go-logging" packages = ["."] pruneopts = "UT" - revision = "970db520ece77730c7e4724c61121037378659d9" + revision = "b2cb9fa56473e98db8caba80237377e83fe44db5" + version = "v1" + +[[projects]] + digest = "1:1d058aa6a019fff0f0d9478bac268d820a693662caca2a5fc3f716d6637a7bfa" + name = "github.com/pborman/uuid" + packages = ["."] + pruneopts = "UT" + revision = "5b6091a6a160ee5ce12917b21ab96acec2a4fdc0" + version = "v1.2.1" + +[[projects]] + digest = "1:c90172176f72788b5e68aadb116d3e2f4d2bae757fa11cd6807967e0a38aeec1" + name = "github.com/peterh/liner" + packages = ["."] + pruneopts = "UT" + revision = "f01956e11ba4dc7eb4d2de9c7dc621f825dcc9c9" + version = "v1.2.0" [[projects]] branch = "master" - digest = "1:6bae001f7c4cddc9ebf2b47bd5ff1bd3978a84b422c468d6037dad284c8c8e9d" + digest = "1:ebb5488a22ceb1036ab5f5c2747de6f3de9d61e9e7c8287f081721636e67fdfb" + name = "github.com/phoreproject/go-ethwallet" + packages = [ + "util", + "wallet", + ] + pruneopts = "UT" + revision = "d370330a5102d2e757ba54c4fc29301adc130767" + +[[projects]] + digest = "1:9e1d37b58d17113ec3cb5608ac0382313c5b59470b94ed97d0976e69c7022314" + name = "github.com/pkg/errors" + packages = ["."] + pruneopts = "UT" + revision = "614d223910a179a466c1767a985424175c39b465" + version = "v0.9.1" + +[[projects]] + digest = "1:19a227084137c73d7a519ff90acc9fa69855c2ba134bb9c7dfe94e9ad2949c64" + name = "github.com/prometheus/tsdb" + packages = ["fileutil"] + pruneopts = "UT" + revision = "7762249358193da791ec62e72b080d908f96e776" + version = "v0.10.0" + +[[projects]] + digest = "1:31d83d1b1c288073c91abadee3caec87de2a1fb5dbe589039264a802e67a26b8" + name = "github.com/rjeczalik/notify" + packages = ["."] + pruneopts = "UT" + revision = "69d839f37b13a8cb7a78366f7633a4071cb43be7" + version = "v0.9.2" + +[[projects]] + digest = "1:4f9cfcfafc40fccdf883330ebed0d4bc02b98b5285aa0e7c32fd0800c7abf5c2" + name = "github.com/shirou/gopsutil" + packages = [ + "cpu", + "internal/common", + ] + pruneopts = "UT" + revision = "7e94bb8bcde053b6d6c98bda5145e9742c913c39" + version = "v2.20.7" + +[[projects]] + digest = "1:ae3c4c486b4de2c71f6e1b9e53d125d13c80aaecc549e9a93342e8274ec761f4" + name = "github.com/shopspring/decimal" + packages = ["."] + pruneopts = "UT" + revision = "2568a29459476f824f35433dfbef158d6ad8618c" + version = "v1.2.0" + +[[projects]] + branch = "develop" + digest = "1:6deccaba5762377091f2e5b26dba70e630e01edb3f95d1a6a59d9b098bd4358f" + name = "github.com/status-im/keycard-go" + packages = ["derivationpath"] + pruneopts = "UT" + revision = "957c095369694cc23ce9f2bca4acd325764860eb" + +[[projects]] + digest = "1:266e2f508feb9a9a765bfeb74d116a88514248b2f8428788dcce574bd026b9c0" + name = "github.com/steakknife/bloomfilter" + packages = ["."] + pruneopts = "UT" + revision = "99ee86d9200fcc2ffde62f508329bd6627c0a307" + version = "1.0.4" + +[[projects]] + digest = "1:5ca4bdccd72e66aaba5b52f9c4a21f1021102f0919432fe138ad5d48abf06833" + name = "github.com/steakknife/hamming" + packages = ["."] + pruneopts = "UT" + revision = "003c143a81c25ea5e263d692919c611c7122ae6b" + version = "0.2.5" + +[[projects]] + digest = "1:c345767003e0d53971e0f409a42b875dab3fee7ec269557c863ebbb194341420" + name = "github.com/syndtr/goleveldb" + packages = [ + "leveldb", + "leveldb/cache", + "leveldb/comparer", + "leveldb/errors", + "leveldb/filter", + "leveldb/iterator", + "leveldb/journal", + "leveldb/memdb", + "leveldb/opt", + "leveldb/storage", + "leveldb/table", + "leveldb/util", + ] + pruneopts = "UT" + revision = "758128399b1df3a87e92df6c26c1d2063da8fabe" + +[[projects]] + digest = "1:91b40a2adb6b4ccd51b1dfb306edfa76139e1599b01666346085472b386f5447" name = "github.com/tyler-smith/go-bip39" packages = [ ".", "wordlists", ] pruneopts = "UT" - revision = "dbb3b84ba2ef14e894f5e33d6c6e43641e665738" + revision = "5e3853c3f4e1a44df487c7efeb064ee8b43755de" + version = "1.0.2" [[projects]] branch = "master" - digest = "1:734c27157144367f37acd13536569700f61f01576c4a5e9665ccb76f79966d97" + digest = "1:7dca0da64f5937af74f21618cdb812c8f16a7d042316dd5bf2f1dfd086be3fc6" + name = "github.com/wsddn/go-ecdh" + packages = ["."] + pruneopts = "UT" + revision = "48726bab92085232373de4ec5c51ce7b441c63a0" + +[[projects]] + branch = "master" + digest = "1:434b3274736ab56fd637404db559ada3659c9a6f504bb6ff34a780fee5b2b5b1" name = "golang.org/x/crypto" packages = [ + "curve25519", + "hkdf", "pbkdf2", "ripemd160", "scrypt", + "sha3", ] pruneopts = "UT" - revision = "ff983b9c42bc9fbf91556e191cc8efb585c16908" + revision = "123391ffb6de907695e1066dc40c1ff09322aeb6" [[projects]] branch = "master" - digest = "1:f38eb85ef192e7499628544cc186b5e5c42ca7e967f87e18730bcdbbf424f191" + digest = "1:38de2dd84fc46a6ea409b2e51f9f1162bbe3e957218a5cfc350b942f44e76246" name = "golang.org/x/net" packages = [ "context", + "html", + "html/atom", + "html/charset", "http/httpguts", "http2", "http2/hpack", @@ -327,28 +701,47 @@ "trace", ] pruneopts = "UT" - revision = "1e06a53dbb7e2ed46e91183f219db23c6943c532" + revision = "3edf25e44fccea9e11b919341e952fca722ef460" [[projects]] branch = "master" - digest = "1:91137b48dc3eb34409f731b49f63a5ebf73218168a065e1a93af24eb5b2f99e8" + digest = "1:7c09dae2f622decf68933485c97e1bca022ed85e3b918e7ab56805328f630441" name = "golang.org/x/sys" - packages = ["unix"] + packages = [ + "cpu", + "internal/unsafeheader", + "unix", + "windows", + ] pruneopts = "UT" - revision = "48ac38b7c8cbedd50b1613c0fccacfc7d88dfcdf" + revision = "9781c653f44323e2079cb1123720c32f9626be2c" [[projects]] - digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" + digest = "1:4e215023f245ee44676ce94f5031f41a7ba2089adf2d9c0175f36eeb6dd62f46" name = "golang.org/x/text" packages = [ "collate", "collate/build", + "encoding", + "encoding/charmap", + "encoding/htmlindex", + "encoding/internal", + "encoding/internal/identifier", + "encoding/japanese", + "encoding/korean", + "encoding/simplifiedchinese", + "encoding/traditionalchinese", + "encoding/unicode", "internal/colltab", "internal/gen", + "internal/language", + "internal/language/compact", "internal/tag", "internal/triegen", "internal/ucd", + "internal/utf8internal", "language", + "runes", "secure/bidirule", "transform", "unicode/bidi", @@ -357,66 +750,130 @@ "unicode/rangetable", ] pruneopts = "UT" - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" + revision = "23ae387dee1f90d29a23c0e87ee0b46038fbed0e" + version = "v0.3.3" [[projects]] branch = "master" - digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" + digest = "1:61acf1a73c474a424301a4012b7166be337af81a14540f4b58f6ad6304af1f49" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "ae2f86662275e140f395167f1dab7081a5bd5fa8" + revision = "f69a88009b70a94c67e3910bf1663f5df9fbfc6d" [[projects]] branch = "master" - digest = "1:574a2035852ef91df91535fe0eba7d0f7ab01d49bdf6f0398f70153093c047a2" + digest = "1:3037e6fdbd2b0f3a6af19f5479dfb886da11e15f1469c2b4f464ec30e35e2ccd" name = "google.golang.org/grpc" packages = [ ".", + "attributes", + "backoff", "balancer", "balancer/base", + "balancer/grpclb/state", "balancer/roundrobin", "binarylog/grpc_binarylog_v1", "codes", "connectivity", "credentials", - "credentials/internal", "encoding", "encoding/proto", "grpclog", "internal", "internal/backoff", + "internal/balancerload", "internal/binarylog", + "internal/buffer", "internal/channelz", + "internal/credentials", "internal/envconfig", + "internal/grpclog", "internal/grpcrand", "internal/grpcsync", + "internal/grpcutil", + "internal/resolver/dns", + "internal/resolver/passthrough", + "internal/serviceconfig", + "internal/status", "internal/syscall", "internal/transport", "keepalive", "metadata", - "naming", "peer", "reflection", "reflection/grpc_reflection_v1alpha", "resolver", - "resolver/dns", - "resolver/passthrough", + "serviceconfig", "stats", "status", "tap", ] pruneopts = "UT" - revision = "b6f0a0f3fc650f4977c0b6869f5e4e717c1c0f24" + revision = "a3740e5ed326410515aa921bbfe5688595732b77" + +[[projects]] + digest = "1:9df1b78c83a222d85523cd1033ae6755d0331488d09ae4ee83e5624c939452c8" + name = "google.golang.org/protobuf" + packages = [ + "encoding/prototext", + "encoding/protowire", + "internal/descfmt", + "internal/descopts", + "internal/detrand", + "internal/encoding/defval", + "internal/encoding/messageset", + "internal/encoding/tag", + "internal/encoding/text", + "internal/errors", + "internal/fieldsort", + "internal/filedesc", + "internal/filetype", + "internal/flags", + "internal/genid", + "internal/impl", + "internal/mapsort", + "internal/pragma", + "internal/set", + "internal/strs", + "internal/version", + "proto", + "reflect/protoreflect", + "reflect/protoregistry", + "runtime/protoiface", + "runtime/protoimpl", + "types/descriptorpb", + "types/known/anypb", + "types/known/durationpb", + "types/known/timestamppb", + ] + pruneopts = "UT" + revision = "3f7a61f89bb6813f89d981d1870ed68da0b3c3f1" + version = "v1.25.0" [[projects]] branch = "v1" - digest = "1:6c802dcce0c717e7fc42d788ee1e2c1393c64b60339d908c0585c32dc5dec994" + digest = "1:cf60ad1a28c3376d2edcf2b43a1ed84303be1bb3088d15de6e49555837a72534" name = "gopkg.in/jarcoal/httpmock.v1" packages = ["."] pruneopts = "UT" - revision = "275e9df93516fc27a998eca24c8f1cca277ce5bf" + revision = "6becb3fd2ca4059885c7ff3df931ba62937278fd" + +[[projects]] + branch = "v2" + digest = "1:3d3f9391ab615be8655ae0d686a1564f3fec413979bb1aaf018bac1ec1bb1cc7" + name = "gopkg.in/natefinch/npipe.v2" + packages = ["."] + pruneopts = "UT" + revision = "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6" + +[[projects]] + digest = "1:d7f1bd887dc650737a421b872ca883059580e9f8314d601f88025df4f4802dce" + name = "gopkg.in/yaml.v2" + packages = ["."] + pruneopts = "UT" + revision = "0b1645d91e851e735d3e23330303ce81f70adbe3" + version = "v2.3.0" [solve-meta] analyzer-name = "dep" @@ -430,22 +887,20 @@ "github.com/OpenBazaar/wallet-interface", "github.com/btcsuite/btcd/blockchain", "github.com/btcsuite/btcd/btcec", - "github.com/btcsuite/btcd/btcjson", "github.com/btcsuite/btcd/chaincfg", "github.com/btcsuite/btcd/chaincfg/chainhash", - "github.com/btcsuite/btcd/rpcclient", "github.com/btcsuite/btcd/txscript", "github.com/btcsuite/btcd/wire", "github.com/btcsuite/btcutil", "github.com/btcsuite/btcutil/base58", "github.com/btcsuite/btcutil/bech32", - "github.com/btcsuite/btcutil/bloom", "github.com/btcsuite/btcutil/coinset", "github.com/btcsuite/btcutil/hdkeychain", "github.com/btcsuite/btcutil/txsort", "github.com/btcsuite/btcwallet/wallet/txauthor", "github.com/btcsuite/btcwallet/wallet/txrules", "github.com/btcsuite/golangcrypto/ripemd160", + "github.com/cenkalti/backoff", "github.com/cpacia/bchutil", "github.com/gcash/bchd/chaincfg/chainhash", "github.com/gcash/bchd/txscript", @@ -461,6 +916,7 @@ "github.com/ltcsuite/ltcwallet/wallet/txrules", "github.com/minio/blake2b-simd", "github.com/op/go-logging", + "github.com/phoreproject/go-ethwallet/wallet", "github.com/tyler-smith/go-bip39", "golang.org/x/crypto/ripemd160", "golang.org/x/net/context", diff --git a/vendor/github.com/phoreproject/multiwallet/Gopkg.toml b/vendor/github.com/phoreproject/multiwallet/Gopkg.toml index 68f89ca479..9dc79358a9 100644 --- a/vendor/github.com/phoreproject/multiwallet/Gopkg.toml +++ b/vendor/github.com/phoreproject/multiwallet/Gopkg.toml @@ -30,15 +30,15 @@ name = "github.com/OpenBazaar/golang-socketio" [[constraint]] - branch = "master" + branch = "ethereum-master" name = "github.com/OpenBazaar/spvwallet" [[constraint]] - branch = "master" + branch = "ethereum-master" name = "github.com/OpenBazaar/wallet-interface" [[constraint]] - branch = "master" + version = "v0.20.1-beta" name = "github.com/btcsuite/btcd" [[constraint]] @@ -46,7 +46,7 @@ name = "github.com/btcsuite/btcutil" [[constraint]] - branch = "master" + version = "v0.11.0" name = "github.com/btcsuite/btcwallet" [[constraint]] @@ -86,11 +86,11 @@ name = "github.com/minio/blake2b-simd" [[constraint]] - branch = "master" + version = "v1.0" name = "github.com/op/go-logging" [[constraint]] - branch = "master" + version = "v1.0.2" name = "github.com/tyler-smith/go-bip39" [[constraint]] @@ -109,6 +109,22 @@ branch = "v1" name = "gopkg.in/jarcoal/httpmock.v1" +[[constraint]] + branch = "master" + name = "github.com/phoreproject/go-ethwallet" + +[[override]] + revision = "758128399b1df3a87e92df6c26c1d2063da8fabe" + name = "github.com/syndtr/goleveldb" + [prune] go-tests = true unused-packages = true + +[[prune.project]] + name = "github.com/ethereum/go-ethereum" + unused-packages = false + +[[prune.project]] + name = "github.com/karalabe/usb" + unused-packages = false diff --git a/vendor/github.com/phoreproject/multiwallet/bitcoin/sign.go b/vendor/github.com/phoreproject/multiwallet/bitcoin/sign.go index 4095f4850f..ce04971b26 100644 --- a/vendor/github.com/phoreproject/multiwallet/bitcoin/sign.go +++ b/vendor/github.com/phoreproject/multiwallet/bitcoin/sign.go @@ -6,6 +6,8 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" "time" "github.com/btcsuite/btcd/chaincfg" @@ -53,7 +55,7 @@ func (w *BitcoinWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeL coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)} coins, err := coinSelector.CoinSelect(target, coins) if err != nil { - return total, inputs, inputValues, scripts, wi.ErrorInsuffientFunds + return total, inputs, inputValues, scripts, wi.ErrInsufficientFunds } additionalPrevScripts = make(map[wire.OutPoint][]byte) additionalKeysByAddress = make(map[string]*btc.WIF) @@ -80,7 +82,8 @@ func (w *BitcoinWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeL } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -149,7 +152,8 @@ func (w *BitcoinWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + fee0 := w.GetFeePerByte(feeLevel) + feePerByte := fee0.Int64() estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) fee := int64(estimatedSize) * feePerByte @@ -278,11 +282,13 @@ func (w *BitcoinWallet) bumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { if err != nil { return nil, err } + n := new(big.Int) + n, _ = n.SetString(u.Value, 10) in := wi.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: int64(u.Value), + Value: *n, } transactionID, err := w.sweepAddress([]wi.TransactionInput{in}, nil, key, nil, wi.FEE_BUMP) if err != nil { @@ -310,7 +316,7 @@ func (w *BitcoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Add var inputs []*wire.TxIn additionalPrevScripts := make(map[wire.OutPoint][]byte) for _, in := range ins { - val += in.Value + val += in.Value.Int64() ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -337,7 +343,8 @@ func (w *BitcoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Add estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -413,7 +420,7 @@ func (w *BitcoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Add } txIn.SignatureScript = script } else { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, *redeemScript, txscript.SigHashAll, privKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), *redeemScript, txscript.SigHashAll, privKey) if err != nil { return nil, err } @@ -453,7 +460,7 @@ func (w *BitcoinWallet) createMultisigSignature(ins []wi.TransactionInput, outs if err != nil { return sigs, err } - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } @@ -482,7 +489,7 @@ func (w *BitcoinWallet) createMultisigSignature(ins []wi.TransactionInput, outs hashes := txscript.NewTxSigHashes(tx) for i := range tx.TxIn { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, redeemScript, txscript.SigHashAll, signingKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), redeemScript, txscript.SigHashAll, signingKey) if err != nil { continue } @@ -508,7 +515,7 @@ func (w *BitcoinWallet) multisign(ins []wi.TransactionInput, outs []wi.Transacti if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } @@ -658,7 +665,8 @@ func (w *BitcoinWallet) estimateSpendFee(amount int64, feeLevel wi.FeeLevel) (ui for _, input := range tx.TxIn { for _, utxo := range utxos { if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + val, _ := strconv.ParseInt(utxo.Value, 10, 64) + inval += val break } } diff --git a/vendor/github.com/phoreproject/multiwallet/bitcoin/sign_test.go b/vendor/github.com/phoreproject/multiwallet/bitcoin/sign_test.go index e7b426da92..3c48c1acb7 100644 --- a/vendor/github.com/phoreproject/multiwallet/bitcoin/sign_test.go +++ b/vendor/github.com/phoreproject/multiwallet/bitcoin/sign_test.go @@ -70,6 +70,60 @@ func newMockWallet() (*BitcoinWallet, error) { return bw, nil } +func TestWalletService_VerifyWatchScriptFilter(t *testing.T) { + // Verify that AddWatchedAddress should never add a script which already represents a key from its own wallet + w, err := newMockWallet() + if err != nil { + t.Fatal(err) + } + keys := w.km.GetKeys() + + addr, err := w.km.KeyToAddress(keys[0]) + if err != nil { + t.Fatal(err) + } + err = w.AddWatchedAddresses(addr) + if err != nil { + t.Fatal(err) + } + + watchScripts, err := w.db.WatchedScripts().GetAll() + if err != nil { + t.Fatal(err) + } + + if len(watchScripts) != 0 { + t.Error("Put watched scripts fails on key manager owned key") + } +} + +func TestWalletService_VerifyWatchScriptPut(t *testing.T) { + // Verify that AddWatchedAddress should add a script which does not represent a key from its own wallet + w, err := newMockWallet() + if err != nil { + t.Fatal(err) + } + + addr, err := w.DecodeAddress("16E4rWXEDcDRfmuMmJ6tTvL2uwHNgWF4yR") + if err != nil { + t.Fatal(err) + } + + err = w.AddWatchedAddresses(addr) + if err != nil { + t.Fatal(err) + } + + watchScripts, err := w.db.WatchedScripts().GetAll() + if err != nil { + t.Fatal(err) + } + + if len(watchScripts) == 0 { + t.Error("Put watched scripts fails on non-key manager owned key") + } +} + func waitForTxnSync(t *testing.T, txnStore wallet.Txns) { // Look for a known txn, this sucks a bit. It would be better to check if the // number of stored txns matched the expected, but not all the mock diff --git a/vendor/github.com/phoreproject/multiwallet/bitcoin/wallet.go b/vendor/github.com/phoreproject/multiwallet/bitcoin/wallet.go index 1ef0997221..e81e35e7ab 100644 --- a/vendor/github.com/phoreproject/multiwallet/bitcoin/wallet.go +++ b/vendor/github.com/phoreproject/multiwallet/bitcoin/wallet.go @@ -6,6 +6,8 @@ import ( "errors" "fmt" "io" + "math/big" + "strconv" "time" "github.com/OpenBazaar/spvwallet" @@ -45,6 +47,14 @@ type BitcoinWallet struct { log *logging.Logger } +var ( + _ = wi.Wallet(&BitcoinWallet{}) + BitcoinCurrencyDefinition = wi.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + } +) + func NewBitcoinWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*BitcoinWallet, error) { seed := bip39.NewSeed(mnemonic, "") @@ -75,7 +85,7 @@ func NewBitcoinWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.P return nil, err } - fp := spvwallet.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, cfg.FeeAPI, proxy) + fp := spvwallet.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, cfg.SuperLowFee, cfg.FeeAPI, proxy) return &BitcoinWallet{ db: cfg.DB, @@ -112,8 +122,11 @@ func (w *BitcoinWallet) CurrencyCode() string { } } -func (w *BitcoinWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btc.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *BitcoinWallet) IsDust(amount big.Int) bool { + if !amount.IsInt64() || amount.Cmp(big.NewInt(0)) <= 0 { + return false + } + return txrules.IsDustAmount(btc.Amount(amount.Int64()), 25, txrules.DefaultRelayFeePerKb) } func (w *BitcoinWallet) MasterPrivateKey() *hd.ExtendedKey { @@ -144,17 +157,30 @@ func (w *BitcoinWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey } func (w *BitcoinWallet) CurrentAddress(purpose wi.KeyPurpose) btc.Address { - key, _ := w.km.GetCurrentKey(purpose) - addr, _ := key.Address(w.params) - return btc.Address(addr) + key, err := w.km.GetCurrentKey(purpose) + if err != nil { + w.log.Errorf("Error generating current key: %s", err) + } + addr, err := w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } + return addr } func (w *BitcoinWallet) NewAddress(purpose wi.KeyPurpose) btc.Address { - i, _ := w.db.Keys().GetUnused(purpose) - key, _ := w.km.GenerateChildKey(purpose, uint32(i[1])) - addr, _ := key.Address(w.params) - w.db.Keys().MarkKeyAsUsed(addr.ScriptAddress()) - return btc.Address(addr) + key, err := w.km.GetNextUnused(purpose) + if err != nil { + w.log.Errorf("Error generating next unused key: %s", err) + } + addr, err := w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } + if err := w.db.Keys().MarkKeyAsUsed(addr.ScriptAddress()); err != nil { + w.log.Errorf("Error marking key as used: %s", err) + } + return addr } func (w *BitcoinWallet) DecodeAddress(addr string) (btc.Address, error) { @@ -184,10 +210,12 @@ func (w *BitcoinWallet) HasKey(addr btc.Address) bool { return true } -func (w *BitcoinWallet) Balance() (confirmed, unconfirmed int64) { +func (w *BitcoinWallet) Balance() (wi.CurrencyValue, wi.CurrencyValue) { utxos, _ := w.db.Utxos().GetAll() txns, _ := w.db.Txns().GetAll(false) - return util.CalcBalance(utxos, txns) + c, u := util.CalcBalance(utxos, txns) + return wi.CurrencyValue{Value: *big.NewInt(c), Currency: BitcoinCurrencyDefinition}, + wi.CurrencyValue{Value: *big.NewInt(u), Currency: BitcoinCurrencyDefinition} } func (w *BitcoinWallet) Transactions() ([]wi.Txn, error) { @@ -247,7 +275,7 @@ func (w *BitcoinWallet) GetTransaction(txid chainhash.Hash) (wi.Txn, error) { } tout := wi.TransactionOutput{ Address: addr, - Value: out.Value, + Value: *big.NewInt(out.Value), Index: uint32(i), } outs = append(outs, tout) @@ -261,11 +289,11 @@ func (w *BitcoinWallet) ChainTip() (uint32, chainhash.Hash) { return w.ws.ChainTip() } -func (w *BitcoinWallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { - return w.fp.GetFeePerByte(feeLevel) +func (w *BitcoinWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + return *big.NewInt(int64(w.fp.GetFeePerByte(feeLevel))) } -func (w *BitcoinWallet) Spend(amount int64, addr btc.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *BitcoinWallet) Spend(amount big.Int, addr btc.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -276,7 +304,7 @@ func (w *BitcoinWallet) Spend(amount int64, addr btc.Address, feeLevel wi.FeeLev return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -293,48 +321,58 @@ func (w *BitcoinWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { return w.bumpFee(txid) } -func (w *BitcoinWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte uint64) uint64 { +func (w *BitcoinWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := txscript.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Int64()) + return *big.NewInt(int64(fee)) } -func (w *BitcoinWallet) EstimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { - return w.estimateSpendFee(amount, feeLevel) +func (w *BitcoinWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + val, err := w.estimateSpendFee(amount.Int64(), feeLevel) + return *big.NewInt(int64(val)), err } func (w *BitcoinWallet) SweepAddress(ins []wi.TransactionInput, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { return w.sweepAddress(ins, address, key, redeemScript, feeLevel) } -func (w *BitcoinWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { - return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte) +func (w *BitcoinWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte.Uint64()) } -func (w *BitcoinWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte, broadcast) +func (w *BitcoinWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte.Uint64(), broadcast) } func (w *BitcoinWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) { return w.generateMultisigScript(keys, threshold, timeout, timeoutKey) } -func (w *BitcoinWallet) AddWatchedAddress(addr btc.Address) error { - script, err := w.AddressToScript(addr) - if err != nil { - return err +func (w *BitcoinWallet) AddWatchedAddresses(addrs ...btc.Address) error { + + var watchedScripts [][]byte + for _, addr := range addrs { + if !w.HasKey(addr) { + script, err := w.AddressToScript(addr) + if err != nil { + return err + } + watchedScripts = append(watchedScripts, script) + } } - err = w.db.WatchedScripts().Put(script) + + err := w.db.WatchedScripts().PutAll(watchedScripts) if err != nil { return err } - w.client.ListenAddress(addr) + + w.client.ListenAddresses(addrs...) return nil } @@ -371,12 +409,12 @@ func (w *BitcoinWallet) DumpTables(wr io.Writer) { fmt.Fprintln(wr, "Transactions-----") txns, _ := w.db.Txns().GetAll(true) for _, tx := range txns { - fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), int(tx.Value), tx.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %s, WatchOnly: %t\n", tx.Txid, int(tx.Height), tx.Value, tx.WatchOnly) } fmt.Fprintln(wr, "\nUtxos-----") utxos, _ := w.db.Utxos().GetAll() for _, u := range utxos { - fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), int(u.Value), u.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %s, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), u.Value, u.WatchOnly) } } @@ -408,6 +446,7 @@ func (w *BitcoinWallet) Broadcast(tx *wire.MsgTx) error { if err != nil { return err } + val, _ := strconv.ParseInt(u.Value, 10, 64) input := model.Input{ Txid: in.PreviousOutPoint.Hash.String(), Vout: int(in.PreviousOutPoint.Index), @@ -417,8 +456,8 @@ func (w *BitcoinWallet) Broadcast(tx *wire.MsgTx) error { Sequence: uint32(in.Sequence), N: n, Addr: addr.String(), - Satoshis: u.Value, - Value: float64(u.Value) / util.SatoshisPerCoin(wi.Bitcoin), + Satoshis: val, + Value: float64(val) / util.SatoshisPerCoin(wi.Bitcoin), } cTxn.Inputs = append(cTxn.Inputs, input) } diff --git a/vendor/github.com/phoreproject/multiwallet/bitcoincash/exchange_rates.go b/vendor/github.com/phoreproject/multiwallet/bitcoincash/exchange_rates.go index 1575d086bc..6eae7554fb 100644 --- a/vendor/github.com/phoreproject/multiwallet/bitcoincash/exchange_rates.go +++ b/vendor/github.com/phoreproject/multiwallet/bitcoincash/exchange_rates.go @@ -4,13 +4,13 @@ import ( "encoding/json" "errors" "fmt" - "github.com/phoreproject/multiwallet/util" - "golang.org/x/net/proxy" - "net" "net/http" "reflect" "sync" "time" + + "github.com/phoreproject/multiwallet/util" + "golang.org/x/net/proxy" ) type ExchangeRateProvider struct { @@ -36,12 +36,14 @@ func NewBitcoinCashPriceFetcher(dialer proxy.Dialer) *BitcoinCashPriceFetcher { b := BitcoinCashPriceFetcher{ cache: make(map[string]float64), } - dial := net.Dial + var client *http.Client if dialer != nil { - dial = dialer.Dial + dial := dialer.Dial + tbTransport := &http.Transport{Dial: dial} + client = &http.Client{Transport: tbTransport, Timeout: time.Minute} + } else { + client = &http.Client{Timeout: time.Minute} } - tbTransport := &http.Transport{Dial: dial} - client := &http.Client{Transport: tbTransport, Timeout: time.Minute} b.providers = []*ExchangeRateProvider{ {"https://ticker.openbazaar.org/api", b.cache, client, OpenBazaarDecoder{}}, @@ -86,7 +88,7 @@ func (b *BitcoinCashPriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, return b.cache, nil } -func (b *BitcoinCashPriceFetcher) UnitsPerCoin() int { +func (b *BitcoinCashPriceFetcher) UnitsPerCoin() int64 { return 100000000 } diff --git a/vendor/github.com/phoreproject/multiwallet/bitcoincash/sign.go b/vendor/github.com/phoreproject/multiwallet/bitcoincash/sign.go index 821ba965ca..a3ad70d682 100644 --- a/vendor/github.com/phoreproject/multiwallet/bitcoincash/sign.go +++ b/vendor/github.com/phoreproject/multiwallet/bitcoincash/sign.go @@ -5,6 +5,8 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" "time" "github.com/btcsuite/btcd/chaincfg" @@ -55,7 +57,7 @@ func (w *BitcoinCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi. coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)} coins, err := coinSelector.CoinSelect(target, coins) if err != nil { - return total, inputs, inputValues, scripts, wi.ErrorInsuffientFunds + return total, inputs, inputValues, scripts, wi.ErrInsufficientFunds } additionalPrevScripts = make(map[wire.OutPoint][]byte) additionalKeysByAddress = make(map[string]*btc.WIF) @@ -86,7 +88,8 @@ func (w *BitcoinCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi. } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -155,7 +158,8 @@ func (w *BitcoinCashWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLev } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + fee0 := w.GetFeePerByte(feeLevel) + feePerByte := fee0.Int64() estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) fee := int64(estimatedSize) * feePerByte @@ -284,11 +288,13 @@ func (w *BitcoinCashWallet) bumpFee(txid chainhash.Hash) (*chainhash.Hash, error if err != nil { return nil, err } + n := new(big.Int) + n, _ = n.SetString(u.Value, 10) in := wi.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: u.Value, + Value: *n, } transactionID, err := w.sweepAddress([]wi.TransactionInput{in}, nil, key, nil, wi.FEE_BUMP) if err != nil { @@ -316,7 +322,7 @@ func (w *BitcoinCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc var inputs []*wire.TxIn additionalPrevScripts := make(map[wire.OutPoint][]byte) for _, in := range ins { - val += in.Value + val += in.Value.Int64() ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -343,7 +349,8 @@ func (w *BitcoinCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -412,7 +419,7 @@ func (w *BitcoinCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] script, err := bchutil.SignTxOutput(w.params, tx, i, prevOutScript, txscript.SigHashAll, getKey, - getScript, txIn.SignatureScript, ins[i].Value) + getScript, txIn.SignatureScript, ins[i].Value.Int64()) if err != nil { return nil, errors.New("Failed to sign transaction") } @@ -422,7 +429,7 @@ func (w *BitcoinCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc if err != nil { return nil, err } - script, err := bchutil.RawTxInSignature(tx, i, *redeemScript, txscript.SigHashAll, priv, ins[i].Value) + script, err := bchutil.RawTxInSignature(tx, i, *redeemScript, txscript.SigHashAll, priv, ins[i].Value.Int64()) if err != nil { return nil, err } @@ -460,7 +467,7 @@ func (w *BitcoinCashWallet) createMultisigSignature(ins []wi.TransactionInput, o if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -488,7 +495,7 @@ func (w *BitcoinCashWallet) createMultisigSignature(ins []wi.TransactionInput, o } for i := range tx.TxIn { - sig, err := bchutil.RawTxInSignature(tx, i, redeemScript, txscript.SigHashAll, signingKey, ins[i].Value) + sig, err := bchutil.RawTxInSignature(tx, i, redeemScript, txscript.SigHashAll, signingKey, ins[i].Value.Int64()) if err != nil { continue } @@ -514,7 +521,7 @@ func (w *BitcoinCashWallet) multisign(ins []wi.TransactionInput, outs []wi.Trans if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -666,7 +673,8 @@ func (w *BitcoinCashWallet) estimateSpendFee(amount int64, feeLevel wi.FeeLevel) for _, input := range tx.TxIn { for _, utxo := range utxos { if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + val, _ := strconv.ParseInt(utxo.Value, 10, 64) + inval += val break } } diff --git a/vendor/github.com/phoreproject/multiwallet/bitcoincash/sign_test.go b/vendor/github.com/phoreproject/multiwallet/bitcoincash/sign_test.go index 126b7dcba7..3f78f1029d 100644 --- a/vendor/github.com/phoreproject/multiwallet/bitcoincash/sign_test.go +++ b/vendor/github.com/phoreproject/multiwallet/bitcoincash/sign_test.go @@ -71,6 +71,61 @@ func newMockWallet() (*BitcoinCashWallet, error) { return bw, nil } +func TestWalletService_VerifyWatchScriptFilter(t *testing.T) { + // Verify that AddWatchedAddress should never add a script which already represents a key from its own wallet + w, err := newMockWallet() + if err != nil { + t.Fatal(err) + } + keys := w.km.GetKeys() + + addr, err := w.km.KeyToAddress(keys[0]) + if err != nil { + t.Fatal(err) + } + err = w.AddWatchedAddresses(addr) + if err != nil { + t.Fatal(err) + } + + watchScripts, err := w.db.WatchedScripts().GetAll() + if err != nil { + t.Fatal(err) + } + + if len(watchScripts) != 0 { + t.Error("Put watched scripts fails on key manager owned key") + } +} + +func TestWalletService_VerifyWatchScriptPut(t *testing.T) { + // Verify that AddWatchedAddress should add a script which does not represent a key from its own wallet + w, err := newMockWallet() + if err != nil { + t.Fatal(err) + } + + addr, err := w.DecodeAddress("qqx0p0ja3xddkvwldaqwcvrkkgrzx6rjwuzla4ca90") + if err != nil { + t.Fatal(err) + } + + err = w.AddWatchedAddresses(addr) + if err != nil { + t.Fatal(err) + } + + watchScripts, err := w.db.WatchedScripts().GetAll() + if err != nil { + t.Fatal(err) + } + + if len(watchScripts) == 0 { + t.Error("Put watched scripts fails on non-key manager owned key") + } + +} + func waitForTxnSync(t *testing.T, txnStore wallet.Txns) { // Look for a known txn, this sucks a bit. It would be better to check if the // number of stored txns matched the expected, but not all the mock diff --git a/vendor/github.com/phoreproject/multiwallet/bitcoincash/wallet.go b/vendor/github.com/phoreproject/multiwallet/bitcoincash/wallet.go index 35f57bbb0d..b4d313e6c3 100644 --- a/vendor/github.com/phoreproject/multiwallet/bitcoincash/wallet.go +++ b/vendor/github.com/phoreproject/multiwallet/bitcoincash/wallet.go @@ -4,8 +4,11 @@ import ( "bytes" "encoding/hex" "fmt" + "github.com/op/go-logging" "io" "log" + "math/big" + "strconv" "time" wi "github.com/OpenBazaar/wallet-interface" @@ -39,8 +42,17 @@ type BitcoinCashWallet struct { mPubKey *hd.ExtendedKey exchangeRates wi.ExchangeRates + log *logging.Logger } +var ( + _ = wi.Wallet(&BitcoinCashWallet{}) + BitcoinCashCurrencyDefinition = wi.CurrencyDefinition{ + Code: "BCH", + Divisibility: 8, + } +) + func NewBitcoinCashWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*BitcoinCashWallet, error) { seed := bip39.NewSeed(mnemonic, "") @@ -71,9 +83,20 @@ func NewBitcoinCashWallet(cfg config.CoinConfig, mnemonic string, params *chainc go exchangeRates.Run() } - fp := util.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, exchangeRates) + fp := util.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, cfg.SuperLowFee, exchangeRates) - return &BitcoinCashWallet{cfg.DB, km, params, c, wm, fp, mPrivKey, mPubKey, exchangeRates}, nil + return &BitcoinCashWallet{ + db: cfg.DB, + km: km, + params: params, + client: c, + ws: wm, + fp: fp, + mPrivKey: mPrivKey, + mPubKey: mPubKey, + exchangeRates: exchangeRates, + log: logging.MustGetLogger("bitcoin-cash-wallet"), + }, nil } func bitcoinCashAddress(key *hd.ExtendedKey, params *chaincfg.Params) (btcutil.Address, error) { @@ -101,8 +124,11 @@ func (w *BitcoinCashWallet) CurrencyCode() string { } } -func (w *BitcoinCashWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btcutil.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *BitcoinCashWallet) IsDust(amount big.Int) bool { + if !amount.IsInt64() || amount.Cmp(big.NewInt(0)) <= 0 { + return false + } + return txrules.IsDustAmount(btcutil.Amount(amount.Int64()), 25, txrules.DefaultRelayFeePerKb) } func (w *BitcoinCashWallet) MasterPrivateKey() *hd.ExtendedKey { @@ -133,17 +159,30 @@ func (w *BitcoinCashWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivat } func (w *BitcoinCashWallet) CurrentAddress(purpose wi.KeyPurpose) btcutil.Address { - key, _ := w.km.GetCurrentKey(purpose) - addr, _ := w.km.KeyToAddress(key) - return btcutil.Address(addr) + key, err := w.km.GetCurrentKey(purpose) + if err != nil { + w.log.Errorf("Error generating current key: %s", err) + } + addr, err := w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } + return addr } func (w *BitcoinCashWallet) NewAddress(purpose wi.KeyPurpose) btcutil.Address { - i, _ := w.db.Keys().GetUnused(purpose) - key, _ := w.km.GenerateChildKey(purpose, uint32(i[1])) - addr, _ := w.km.KeyToAddress(key) - w.db.Keys().MarkKeyAsUsed(addr.ScriptAddress()) - return btcutil.Address(addr) + key, err := w.km.GetNextUnused(purpose) + if err != nil { + w.log.Errorf("Error generating next unused key: %s", err) + } + addr, err := w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } + if err := w.db.Keys().MarkKeyAsUsed(addr.ScriptAddress()); err != nil { + w.log.Errorf("Error marking key as used: %s", err) + } + return addr } func (w *BitcoinCashWallet) DecodeAddress(addr string) (btcutil.Address, error) { @@ -166,10 +205,12 @@ func (w *BitcoinCashWallet) HasKey(addr btcutil.Address) bool { return true } -func (w *BitcoinCashWallet) Balance() (confirmed, unconfirmed int64) { +func (w *BitcoinCashWallet) Balance() (wi.CurrencyValue, wi.CurrencyValue) { utxos, _ := w.db.Utxos().GetAll() txns, _ := w.db.Txns().GetAll(false) - return util.CalcBalance(utxos, txns) + c, u := util.CalcBalance(utxos, txns) + return wi.CurrencyValue{Value: *big.NewInt(c), Currency: BitcoinCashCurrencyDefinition}, + wi.CurrencyValue{Value: *big.NewInt(u), Currency: BitcoinCashCurrencyDefinition} } func (w *BitcoinCashWallet) Transactions() ([]wi.Txn, error) { @@ -223,7 +264,7 @@ func (w *BitcoinCashWallet) GetTransaction(txid chainhash.Hash) (wi.Txn, error) } tout := wi.TransactionOutput{ Address: addr, - Value: out.Value, + Value: *big.NewInt(out.Value), Index: uint32(i), } outs = append(outs, tout) @@ -237,11 +278,11 @@ func (w *BitcoinCashWallet) ChainTip() (uint32, chainhash.Hash) { return w.ws.ChainTip() } -func (w *BitcoinCashWallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { - return w.fp.GetFeePerByte(feeLevel) +func (w *BitcoinCashWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + return *big.NewInt(int64(w.fp.GetFeePerByte(feeLevel))) } -func (w *BitcoinCashWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *BitcoinCashWallet) Spend(amount big.Int, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -252,7 +293,7 @@ func (w *BitcoinCashWallet) Spend(amount int64, addr btcutil.Address, feeLevel w return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -271,48 +312,58 @@ func (w *BitcoinCashWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error return w.bumpFee(txid) } -func (w *BitcoinCashWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte uint64) uint64 { +func (w *BitcoinCashWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := bchutil.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Int64()) + return *big.NewInt(int64(fee)) } -func (w *BitcoinCashWallet) EstimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { - return w.estimateSpendFee(amount, feeLevel) +func (w *BitcoinCashWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + val, err := w.estimateSpendFee(amount.Int64(), feeLevel) + return *big.NewInt(int64(val)), err } func (w *BitcoinCashWallet) SweepAddress(ins []wi.TransactionInput, address *btcutil.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { return w.sweepAddress(ins, address, key, redeemScript, feeLevel) } -func (w *BitcoinCashWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { - return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte) +func (w *BitcoinCashWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte.Uint64()) } -func (w *BitcoinCashWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte, broadcast) +func (w *BitcoinCashWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte.Uint64(), broadcast) } func (w *BitcoinCashWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btcutil.Address, redeemScript []byte, err error) { return w.generateMultisigScript(keys, threshold, timeout, timeoutKey) } -func (w *BitcoinCashWallet) AddWatchedAddress(addr btcutil.Address) error { - script, err := w.AddressToScript(addr) - if err != nil { - return err +func (w *BitcoinCashWallet) AddWatchedAddresses(addrs ...btcutil.Address) error { + + var watchedScripts [][]byte + for _, addr := range addrs { + if !w.HasKey(addr) { + script, err := w.AddressToScript(addr) + if err != nil { + return err + } + watchedScripts = append(watchedScripts, script) + } } - err = w.db.WatchedScripts().Put(script) + + err := w.db.WatchedScripts().PutAll(watchedScripts) if err != nil { return err } - w.client.ListenAddress(addr) + + w.client.ListenAddresses(addrs...) return nil } @@ -325,7 +376,7 @@ func (w *BitcoinCashWallet) AddWatchedScript(script []byte) error { if err != nil { return err } - w.client.ListenAddress(addr) + w.client.ListenAddresses(addr) return nil } @@ -362,12 +413,12 @@ func (w *BitcoinCashWallet) DumpTables(wr io.Writer) { fmt.Fprintln(wr, "Transactions-----") txns, _ := w.db.Txns().GetAll(true) for _, tx := range txns { - fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), int(tx.Value), tx.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %s, WatchOnly: %t\n", tx.Txid, int(tx.Height), tx.Value, tx.WatchOnly) } fmt.Fprintln(wr, "\nUtxos-----") utxos, _ := w.db.Utxos().GetAll() for _, u := range utxos { - fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), int(u.Value), u.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %s, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), u.Value, u.WatchOnly) } } @@ -399,6 +450,7 @@ func (w *BitcoinCashWallet) Broadcast(tx *wire.MsgTx) error { if err != nil { return err } + val, _ := strconv.ParseInt(u.Value, 10, 64) input := model.Input{ Txid: in.PreviousOutPoint.Hash.String(), Vout: int(in.PreviousOutPoint.Index), @@ -408,8 +460,8 @@ func (w *BitcoinCashWallet) Broadcast(tx *wire.MsgTx) error { Sequence: uint32(in.Sequence), N: n, Addr: addr.String(), - Satoshis: u.Value, - Value: float64(u.Value) / util.SatoshisPerCoin(wi.BitcoinCash), + Satoshis: val, + Value: float64(val) / util.SatoshisPerCoin(wi.BitcoinCash), } cTxn.Inputs = append(cTxn.Inputs, input) } diff --git a/vendor/github.com/phoreproject/multiwallet/client/blockbook/client.go b/vendor/github.com/phoreproject/multiwallet/client/blockbook/client.go index e212160aa4..03badf359e 100644 --- a/vendor/github.com/phoreproject/multiwallet/client/blockbook/client.go +++ b/vendor/github.com/phoreproject/multiwallet/client/blockbook/client.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "io/ioutil" - "net" "net/http" "net/url" "path" @@ -21,6 +20,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcutil" + "github.com/cenkalti/backoff" "github.com/cpacia/bchutil" "github.com/op/go-logging" clientErr "github.com/phoreproject/multiwallet/client/errors" @@ -29,6 +29,8 @@ import ( "golang.org/x/net/proxy" ) +const maxInfightQueries = 25 + var Log = logging.MustGetLogger("client") type wsWatchdog struct { @@ -122,16 +124,20 @@ func NewBlockBookClient(apiUrl string, proxyDialer proxy.Dialer) (*BlockBookClie return nil, err } - dial := net.Dial + var customClient http.Client if proxyDialer != nil { - dial = proxyDialer.Dial + dial := proxyDialer.Dial + tbTransport := &http.Transport{Dial: dial} + customClient = http.Client{Timeout: time.Second * 30, Transport: tbTransport} + } else { + customClient = http.Client{Timeout: time.Second * 30} } bch := make(chan model.Block) tch := make(chan model.Transaction) - tbTransport := &http.Transport{Dial: dial} + ic := &BlockBookClient{ - HTTPClient: http.Client{Timeout: time.Second * 30, Transport: tbTransport}, + HTTPClient: customClient, apiUrl: u, proxyDialer: proxyDialer, blockNotifyChan: bch, @@ -338,20 +344,28 @@ func (i *BlockBookClient) GetRawTransaction(txid string) ([]byte, error) { return nil, nil } +// GetTransactions returns the transactions for a given address. If a single address +// query fails this method will not return an error. Instead it will log the error +// and returns the transactions for the other addresses. func (i *BlockBookClient) GetTransactions(addrs []btcutil.Address) ([]model.Transaction, error) { var txs []model.Transaction type txsOrError struct { Txs []model.Transaction Err error } - txChan := make(chan txsOrError) + var ( + txChan = make(chan txsOrError) + queryChan = make(chan struct{}, maxInfightQueries) + wg sync.WaitGroup + ) + wg.Add(len(addrs)) go func() { - var wg sync.WaitGroup - wg.Add(len(addrs)) for _, addr := range addrs { + queryChan <- struct{}{} go func(a btcutil.Address) { txs, err := i.getTransactions(maybeConvertCashAddress(a)) txChan <- txsOrError{txs, err} + <-queryChan wg.Done() }(addr) } @@ -360,6 +374,7 @@ func (i *BlockBookClient) GetTransactions(addrs []btcutil.Address) ([]model.Tran }() for toe := range txChan { if toe.Err != nil { + Log.Errorf("Error querying address from blockbook: %s", toe.Err.Error()) return nil, toe.Err } txs = append(txs, toe.Txs...) @@ -423,19 +438,29 @@ func (i *BlockBookClient) getTransactions(addr string) ([]model.Transaction, err return ret, nil } +// GetUtxos returns the utxos for a given address. If a single address +// query fails this method will not return an error. Instead it will log the error +// and returns the transactions for the other addresses. func (i *BlockBookClient) GetUtxos(addrs []btcutil.Address) ([]model.Utxo, error) { var ret []model.Utxo type utxoOrError struct { Utxo *model.Utxo Err error } - utxoChan := make(chan utxoOrError) - var wg sync.WaitGroup + var ( + wg sync.WaitGroup + queryChan = make(chan struct{}, maxInfightQueries) + utxoChan = make(chan utxoOrError) + ) wg.Add(len(addrs)) go func() { for _, addr := range addrs { + queryChan <- struct{}{} go func(addr btcutil.Address) { defer wg.Done() + defer func() { + <-queryChan + }() resp, err := i.RequestFunc("/utxo/"+maybeConvertCashAddress(addr), http.MethodGet, nil, nil) if err != nil { utxoChan <- utxoOrError{nil, err} @@ -486,6 +511,7 @@ func (i *BlockBookClient) GetUtxos(addrs []btcutil.Address) ([]model.Utxo, error }() for toe := range utxoChan { if toe.Err != nil { + Log.Errorf("Error querying utxos from blockbook: %s", toe.Err.Error()) return nil, toe.Err } if toe.Utxo != nil { @@ -503,18 +529,25 @@ func (i *BlockBookClient) TransactionNotify() <-chan model.Transaction { return i.txNotifyChan } -func (i *BlockBookClient) ListenAddress(addr btcutil.Address) { +func (i *BlockBookClient) ListenAddresses(addrs ...btcutil.Address) { + if len(addrs) == 0 { + return + } + i.listenLock.Lock() defer i.listenLock.Unlock() - var args []interface{} - args = append(args, "bitcoind/addresstxid") - args = append(args, []string{maybeConvertCashAddress(addr)}) i.socketMutex.RLock() defer i.socketMutex.RUnlock() + + var convertedAddrs []string + for _, addr := range addrs { + convertedAddrs = append(convertedAddrs, maybeConvertCashAddress(addr)) + } + if i.SocketClient != nil { - i.SocketClient.Emit("subscribe", args) + i.SocketClient.Emit("subscribe", []interface{}{"bitcoind/addresstxid", convertedAddrs}) } else { - i.listenQueue = append(i.listenQueue, maybeConvertCashAddress(addr)) + i.listenQueue = append(i.listenQueue, convertedAddrs...) } } @@ -544,31 +577,36 @@ func connectSocket(u *url.URL, proxyDialer proxy.Dialer) (model.SocketClient, er } func (i *BlockBookClient) setupListeners() error { + i.listenLock.Lock() + defer i.listenLock.Unlock() + if i.SocketClient != nil { return nil } - i.listenLock.Lock() - defer i.listenLock.Unlock() - client, err := connectSocket(i.apiUrl, i.proxyDialer) if err != nil { Log.Errorf("reconnect websocket (%s): %s", i.String(), err.Error()) - var ( - setupTimeoutAt = time.Now().Add(10 * time.Second) - t = time.NewTicker(2 * time.Second) - ) - defer t.Stop() - for range t.C { - if time.Now().After(setupTimeoutAt) { - return fmt.Errorf("websocket reconnection timeout (%s)", i.String()) - } - client, err = connectSocket(i.apiUrl, i.proxyDialer) - if err != nil { - Log.Errorf("reconnect websocket (%s): %s", i.String(), err.Error()) - continue - } - break + var setupTimeoutAt = time.Now().Add(10 * time.Second) + + b := backoff.NewExponentialBackOff() + b.MaxElapsedTime = 7 * 24 * time.Hour + + err = backoff.Retry( + func() error { + if time.Now().After(setupTimeoutAt) { + return fmt.Errorf("websocket reconnection timeout (%s)", i.String()) + } + client, err = connectSocket(i.apiUrl, i.proxyDialer) + if err != nil { + Log.Errorf("reconnect websocket (%s): %s", i.String(), err.Error()) + Log.Warningf("reconnecting in: %s", b.NextBackOff()) + return err + } + return nil + }, b) + if err != nil { + Log.Fatalf("error after retrying: %v", err) } } i.SocketClient = client @@ -617,13 +655,13 @@ func (i *BlockBookClient) setupListeners() error { } } }) - for _, addr := range i.listenQueue { - var args []interface{} - args = append(args, "bitcoind/addresstxid") - args = append(args, []string{addr}) - i.SocketClient.Emit("subscribe", args) + + // Subscribe to queued addresses + if len(i.listenQueue) != 0 { + i.SocketClient.Emit("subscribe", []interface{}{"bitcoind/addresstxid", i.listenQueue}) + i.listenQueue = []string{} } - i.listenQueue = []string{} + Log.Infof("websocket connected (%s)", i.String()) return nil } diff --git a/vendor/github.com/phoreproject/multiwallet/client/pool.go b/vendor/github.com/phoreproject/multiwallet/client/pool.go index 1cc089034d..7c39b2e038 100644 --- a/vendor/github.com/phoreproject/multiwallet/client/pool.go +++ b/vendor/github.com/phoreproject/multiwallet/client/pool.go @@ -370,14 +370,15 @@ func (p *ClientPool) GetUtxos(addrs []btcutil.Address) ([]model.Utxo, error) { return utxos, err } -// ListenAddress proxies the same request to the active client -func (p *ClientPool) ListenAddress(addr btcutil.Address) { +// ListenAddresses proxies the same request to the active client +func (p *ClientPool) ListenAddresses(addrs ...btcutil.Address) { p.listenAddrsLock.Lock() defer p.listenAddrsLock.Unlock() var client = p.poolManager.AcquireCurrentWhenReady() defer p.poolManager.ReleaseCurrent() - p.listenAddrs = append(p.listenAddrs, addr) - client.ListenAddress(addr) + + p.listenAddrs = append(p.listenAddrs, addrs...) + client.ListenAddresses(addrs...) } func (p *ClientPool) replayListenAddresses() { @@ -385,9 +386,7 @@ func (p *ClientPool) replayListenAddresses() { defer p.listenAddrsLock.Unlock() var client = p.poolManager.AcquireCurrent() defer p.poolManager.ReleaseCurrent() - for _, addr := range p.listenAddrs { - client.ListenAddress(addr) - } + client.ListenAddresses(p.listenAddrs...) } // TransactionNotify proxies the active client's tx channel diff --git a/vendor/github.com/phoreproject/multiwallet/config/config.go b/vendor/github.com/phoreproject/multiwallet/config/config.go index d2a80f1720..a6a1fa1728 100644 --- a/vendor/github.com/phoreproject/multiwallet/config/config.go +++ b/vendor/github.com/phoreproject/multiwallet/config/config.go @@ -15,8 +15,8 @@ import ( ) const ( - EthereumRegistryAddressMainnet = "0x403d907982474cdd51687b09a8968346159378f3" - EthereumRegistryAddressRinkeby = "0x403d907982474cdd51687b09a8968346159378f3" + EthereumRegistryAddressMainnet = "0x5c69ccf91eab4ef80d9929b3c1b4d5bc03eb0981" + EthereumRegistryAddressRinkeby = "0x5cEF053c7b383f430FC4F4e1ea2F7D31d8e2D16C" EthereumRegistryAddressRopsten = "0x403d907982474cdd51687b09a8968346159378f3" ) @@ -53,9 +53,10 @@ type CoinConfig struct { CoinType util.ExtCoinType // The default fee-per-byte for each level - LowFee uint64 - MediumFee uint64 - HighFee uint64 + SuperLowFee uint64 + LowFee uint64 + MediumFee uint64 + HighFee uint64 // The highest allowable fee-per-byte MaxFee uint64 @@ -100,14 +101,15 @@ func NewDefaultConfig(coinTypes map[wallet.CoinType]bool, params *chaincfg.Param } db, _ := mockDB.GetDatastoreForWallet(util.CoinTypePhore.ToCoinType()) phrCfg := CoinConfig{ - CoinType: util.CoinTypePhore, - FeeAPI: "", - LowFee: 140, - MediumFee: 160, - HighFee: 180, - MaxFee: 2000, - ClientAPIs: apiEndpoints, - DB: db, + CoinType: util.CoinTypePhore, + FeeAPI: "", + SuperLowFee: 70, + LowFee: 140, + MediumFee: 160, + HighFee: 180, + MaxFee: 2000, + ClientAPIs: apiEndpoints, + DB: db, } cfg.Coins = append(cfg.Coins, phrCfg) } @@ -115,14 +117,14 @@ func NewDefaultConfig(coinTypes map[wallet.CoinType]bool, params *chaincfg.Param var apiEndpoints []string if !testnet { apiEndpoints = []string{ - "https://btc.blockbook.api.openbazaar.org/api", + "https://btc.api.openbazaar.org/api", // temporarily deprecated Insight endpoints //"https://btc.bloqapi.net/insight-api", //"https://btc.insight.openbazaar.org/insight-api", } } else { apiEndpoints = []string{ - "https://tbtc.blockbook.api.openbazaar.org/api", + "https://tbtc.api.openbazaar.org/api", // temporarily deprecated Insight endpoints //"https://test-insight.bitpay.com/api", } @@ -130,14 +132,15 @@ func NewDefaultConfig(coinTypes map[wallet.CoinType]bool, params *chaincfg.Param feeApi := "https://btc.fees.openbazaar.org" db, _ := mockDB.GetDatastoreForWallet(wallet.Bitcoin) btcCfg := CoinConfig{ - CoinType: util.ExtendCoinType(wallet.Bitcoin), - FeeAPI: feeApi, - LowFee: 140, - MediumFee: 160, - HighFee: 180, - MaxFee: 2000, - ClientAPIs: apiEndpoints, - DB: db, + CoinType: util.ExtendCoinType(wallet.Bitcoin), + FeeAPI: feeApi, + SuperLowFee: 70, + LowFee: 140, + MediumFee: 160, + HighFee: 180, + MaxFee: 2000, + ClientAPIs: apiEndpoints, + DB: db, } cfg.Coins = append(cfg.Coins, btcCfg) } @@ -145,27 +148,28 @@ func NewDefaultConfig(coinTypes map[wallet.CoinType]bool, params *chaincfg.Param var apiEndpoints []string if !testnet { apiEndpoints = []string{ - "https://bch.blockbook.api.openbazaar.org/api", + "https://bch.api.openbazaar.org/api", // temporarily deprecated Insight endpoints //"https://bitcoincash.blockexplorer.com/api", } } else { apiEndpoints = []string{ - "https://tbch.blockbook.api.openbazaar.org/api", + "https://tbch.api.openbazaar.org/api", // temporarily deprecated Insight endpoints //"https://test-bch-insight.bitpay.com/api", } } db, _ := mockDB.GetDatastoreForWallet(wallet.BitcoinCash) bchCfg := CoinConfig{ - CoinType: wallet.BitcoinCash, - FeeAPI: "", - LowFee: 140, - MediumFee: 160, - HighFee: 180, - MaxFee: 2000, - ClientAPIs: apiEndpoints, - DB: db, + CoinType: wallet.BitcoinCash, + FeeAPI: "", + SuperLowFee: 70, + LowFee: 140, + MediumFee: 160, + HighFee: 180, + MaxFee: 2000, + ClientAPIs: apiEndpoints, + DB: db, } cfg.Coins = append(cfg.Coins, bchCfg) } @@ -173,27 +177,28 @@ func NewDefaultConfig(coinTypes map[wallet.CoinType]bool, params *chaincfg.Param var apiEndpoints []string if !testnet { apiEndpoints = []string{ - "https://zec.blockbook.api.openbazaar.org/api", + "https://zec.api.openbazaar.org/api", // temporarily deprecated Insight endpoints //"https://zcashnetwork.info/api", } } else { apiEndpoints = []string{ - "https://tzec.blockbook.api.openbazaar.org/api", + "https://tzec.api.openbazaar.org/api", // temporarily deprecated Insight endpoints //"https://explorer.testnet.z.cash/api", } } db, _ := mockDB.GetDatastoreForWallet(wallet.Zcash) zecCfg := CoinConfig{ - CoinType: wallet.Zcash, - FeeAPI: "", - LowFee: 140, - MediumFee: 160, - HighFee: 180, - MaxFee: 2000, - ClientAPIs: apiEndpoints, - DB: db, + CoinType: wallet.Zcash, + FeeAPI: "", + SuperLowFee: 70, + LowFee: 140, + MediumFee: 160, + HighFee: 180, + MaxFee: 2000, + ClientAPIs: apiEndpoints, + DB: db, } cfg.Coins = append(cfg.Coins, zecCfg) } @@ -201,28 +206,29 @@ func NewDefaultConfig(coinTypes map[wallet.CoinType]bool, params *chaincfg.Param var apiEndpoints []string if !testnet { apiEndpoints = []string{ - "https://ltc.blockbook.api.openbazaar.org/api", + "https://ltc.api.openbazaar.org/api", // temporarily deprecated Insight endpoints //"https://ltc.coin.space/api", //"https://ltc.insight.openbazaar.org/insight-lite-api", } } else { apiEndpoints = []string{ - "https://tltc.blockbook.api.openbazaar.org/api", + "https://tltc.api.openbazaar.org/api", // temporarily deprecated Insight endpoints //"https://testnet.litecore.io/api", } } db, _ := mockDB.GetDatastoreForWallet(wallet.Litecoin) ltcCfg := CoinConfig{ - CoinType: wallet.Litecoin, - FeeAPI: "", - LowFee: 140, - MediumFee: 160, - HighFee: 180, - MaxFee: 2000, - ClientAPIs: apiEndpoints, - DB: db, + CoinType: wallet.Litecoin, + FeeAPI: "", + SuperLowFee: 70, + LowFee: 140, + MediumFee: 160, + HighFee: 180, + MaxFee: 2000, + ClientAPIs: apiEndpoints, + DB: db, } cfg.Coins = append(cfg.Coins, ltcCfg) } @@ -230,7 +236,7 @@ func NewDefaultConfig(coinTypes map[wallet.CoinType]bool, params *chaincfg.Param var apiEndpoints []string if !testnet { apiEndpoints = []string{ - "https://rinkeby.infura.io", + "https://mainnet.infura.io", } } else { apiEndpoints = []string{ @@ -239,14 +245,15 @@ func NewDefaultConfig(coinTypes map[wallet.CoinType]bool, params *chaincfg.Param } db, _ := mockDB.GetDatastoreForWallet(wallet.Ethereum) ethCfg := CoinConfig{ - CoinType: wallet.Ethereum, - FeeAPI: "", - LowFee: 140, - MediumFee: 160, - HighFee: 180, - MaxFee: 2000, - ClientAPIs: apiEndpoints, - DB: db, + CoinType: wallet.Ethereum, + FeeAPI: "", + SuperLowFee: 70, + LowFee: 140, + MediumFee: 160, + HighFee: 180, + MaxFee: 2000, + ClientAPIs: apiEndpoints, + DB: db, Options: map[string]interface{}{ "RegistryAddress": EthereumRegistryAddressMainnet, "RinkebyRegistryAddress": EthereumRegistryAddressRinkeby, diff --git a/vendor/github.com/phoreproject/multiwallet/datastore/mock.go b/vendor/github.com/phoreproject/multiwallet/datastore/mock.go index 72ca6208db..8a5fd71d3a 100644 --- a/vendor/github.com/phoreproject/multiwallet/datastore/mock.go +++ b/vendor/github.com/phoreproject/multiwallet/datastore/mock.go @@ -327,7 +327,7 @@ func (m *MockStxoStore) Delete(stxo wallet.Stxo) error { type txnStoreEntry struct { txn []byte - value int + value string height int timestamp time.Time watchOnly bool @@ -338,7 +338,7 @@ type MockTxnStore struct { sync.Mutex } -func (m *MockTxnStore) Put(tx []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error { +func (m *MockTxnStore) Put(tx []byte, txid, value string, height int, timestamp time.Time, watchOnly bool) error { m.Lock() defer m.Unlock() m.txns[txid] = &txnStoreEntry{ @@ -360,7 +360,7 @@ func (m *MockTxnStore) Get(txid chainhash.Hash) (wallet.Txn, error) { } return wallet.Txn{ Txid: txid.String(), - Value: int64(t.value), + Value: t.value, Height: int32(t.height), Timestamp: t.timestamp, WatchOnly: t.watchOnly, @@ -375,7 +375,7 @@ func (m *MockTxnStore) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) { for txid, t := range m.txns { txn := wallet.Txn{ Txid: txid, - Value: int64(t.value), + Value: t.value, Height: int32(t.height), Timestamp: t.timestamp, WatchOnly: t.watchOnly, @@ -415,6 +415,15 @@ type MockWatchedScriptsStore struct { sync.Mutex } +func (m *MockWatchedScriptsStore) PutAll(scriptPubKeys [][]byte) error { + m.Lock() + defer m.Unlock() + for _, scriptPubKey := range scriptPubKeys { + m.scripts[hex.EncodeToString(scriptPubKey)] = scriptPubKey + } + return nil +} + func (m *MockWatchedScriptsStore) Put(scriptPubKey []byte) error { m.Lock() defer m.Unlock() diff --git a/vendor/github.com/phoreproject/multiwallet/keys/keys.go b/vendor/github.com/phoreproject/multiwallet/keys/keys.go index b9f94b15e6..23ec77d88c 100644 --- a/vendor/github.com/phoreproject/multiwallet/keys/keys.go +++ b/vendor/github.com/phoreproject/multiwallet/keys/keys.go @@ -79,7 +79,7 @@ func (km *KeyManager) GetCurrentKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, return nil, err } if len(i) == 0 { - return nil, errors.New("No unused keys in database") + return nil, errors.New("no unused keys in database") } return km.GenerateChildKey(purpose, uint32(i[0])) } @@ -106,7 +106,7 @@ func (km *KeyManager) GetFreshKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, e if err != nil { return nil, err } - p := wallet.KeyPath{wallet.KeyPurpose(purpose), index} + p := wallet.KeyPath{Purpose: purpose, Index: index} err = km.datastore.Put(addr.ScriptAddress(), p) if err != nil { return nil, err @@ -114,6 +114,21 @@ func (km *KeyManager) GetFreshKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, e return childKey, nil } +func (km *KeyManager) GetNextUnused(purpose wallet.KeyPurpose) (*hd.ExtendedKey, error) { + if err := km.lookahead(); err != nil { + return nil, err + } + i, err := km.datastore.GetUnused(purpose) + if err != nil { + return nil, err + } + key, err := km.GenerateChildKey(purpose, uint32(i[1])) + if err != nil { + return nil, err + } + return key, nil +} + func (km *KeyManager) GetKeys() []*hd.ExtendedKey { var keys []*hd.ExtendedKey keyPaths, err := km.datastore.GetAll() @@ -164,7 +179,7 @@ func (km *KeyManager) GenerateChildKey(purpose wallet.KeyPurpose, index uint32) } else if purpose == wallet.INTERNAL { return km.internalKey.Child(index) } - return nil, errors.New("Unknown key purpose") + return nil, errors.New("unknown key purpose") } func (km *KeyManager) lookahead() error { diff --git a/vendor/github.com/phoreproject/multiwallet/keys/keys_test.go b/vendor/github.com/phoreproject/multiwallet/keys/keys_test.go index acb8f9dee4..9e0dd58d8f 100644 --- a/vendor/github.com/phoreproject/multiwallet/keys/keys_test.go +++ b/vendor/github.com/phoreproject/multiwallet/keys/keys_test.go @@ -218,6 +218,56 @@ func TestKeyManager_GetFreshKey(t *testing.T) { } } +func TestKeyManager_GetNextUnused(t *testing.T) { + km, err := createKeyManager() + if err != nil { + t.Fatal(err) + } + + // Since the lookahead window has already been generated, GetNextUnused + // should return the key with index 1. + key, err := km.GetNextUnused(wallet.EXTERNAL) + if err != nil { + t.Fatal(err) + } + + nextUnused, err := km.GenerateChildKey(wallet.EXTERNAL, uint32(1)) + if err != nil { + t.Fatal(err) + } + + if key.String() != nextUnused.String() { + t.Errorf("Derived incorrect key. Expected %s got %s", nextUnused.String(), key.String()) + } + + // Next let's mark all the keys as used and make sure GetNextUnused still + // generates a lookahead window and returns the next unused key. + allKeys := km.GetKeys() + for _, key := range allKeys { + addr, err := key.Address(&chaincfg.MainNetParams) + if err != nil { + t.Fatal(err) + } + if err := km.datastore.MarkKeyAsUsed(addr.ScriptAddress()); err != nil { + t.Fatal(err) + } + } + + key, err = km.GetNextUnused(wallet.EXTERNAL) + if err != nil { + t.Fatal(err) + } + + nextUnused, err = km.GenerateChildKey(wallet.EXTERNAL, uint32(21)) + if err != nil { + t.Fatal(err) + } + + if key.String() != nextUnused.String() { + t.Errorf("Derived incorrect key. Expected %s got %s", nextUnused.String(), key.String()) + } +} + func TestKeyManager_GetKeys(t *testing.T) { km, err := createKeyManager() if err != nil { diff --git a/vendor/github.com/phoreproject/multiwallet/litecoin/address/address.go b/vendor/github.com/phoreproject/multiwallet/litecoin/address/address.go index c9fbb85326..1edb973c19 100644 --- a/vendor/github.com/phoreproject/multiwallet/litecoin/address/address.go +++ b/vendor/github.com/phoreproject/multiwallet/litecoin/address/address.go @@ -160,26 +160,24 @@ func DecodeAddress(addr string, defaultNet *chaincfg.Params) (Address, error) { prefix := addr[:oneIndex+1] if IsBech32SegwitPrefix(prefix) { witnessVer, witnessProg, err := decodeSegWitAddress(addr) - if err != nil { - return nil, err - } - - // We currently only support P2WPKH and P2WSH, which is - // witness version 0. - if witnessVer != 0 { - return nil, UnsupportedWitnessVerError(witnessVer) - } - - // The HRP is everything before the found '1'. - hrp := prefix[:len(prefix)-1] - - switch len(witnessProg) { - case 20: - return newAddressWitnessPubKeyHash(hrp, witnessProg) - case 32: - return newAddressWitnessScriptHash(hrp, witnessProg) - default: - return nil, UnsupportedWitnessProgLenError(len(witnessProg)) + if err == nil { + // We currently only support P2WPKH and P2WSH, which is + // witness version 0. + if witnessVer != 0 { + return nil, UnsupportedWitnessVerError(witnessVer) + } + + // The HRP is everything before the found '1'. + hrp := prefix[:len(prefix)-1] + + switch len(witnessProg) { + case 20: + return newAddressWitnessPubKeyHash(hrp, witnessProg) + case 32: + return newAddressWitnessScriptHash(hrp, witnessProg) + default: + return nil, UnsupportedWitnessProgLenError(len(witnessProg)) + } } } } diff --git a/vendor/github.com/phoreproject/multiwallet/litecoin/exchange_rates.go b/vendor/github.com/phoreproject/multiwallet/litecoin/exchange_rates.go index 5d58d2cc28..4a0e98f224 100644 --- a/vendor/github.com/phoreproject/multiwallet/litecoin/exchange_rates.go +++ b/vendor/github.com/phoreproject/multiwallet/litecoin/exchange_rates.go @@ -3,16 +3,15 @@ package litecoin import ( "encoding/json" "errors" - "net" "net/http" "reflect" "strconv" + "strings" "sync" "time" exchange "github.com/OpenBazaar/spvwallet/exchangerates" "golang.org/x/net/proxy" - "strings" ) type ExchangeRateProvider struct { @@ -44,18 +43,21 @@ func NewLitecoinPriceFetcher(dialer proxy.Dialer) *LitecoinPriceFetcher { z := LitecoinPriceFetcher{ cache: make(map[string]float64), } - dial := net.Dial + + var client *http.Client if dialer != nil { - dial = dialer.Dial + dial := dialer.Dial + tbTransport := &http.Transport{Dial: dial} + client = &http.Client{Transport: tbTransport, Timeout: time.Minute} + } else { + client = &http.Client{Timeout: time.Minute} } - tbTransport := &http.Transport{Dial: dial} - client := &http.Client{Transport: tbTransport, Timeout: time.Minute} z.providers = []*ExchangeRateProvider{ - //{"https://ticker.openbazaar.org/api", z.cache, client, OpenBazaarDecoder{}, nil}, - //{"https://bittrex.com/api/v1.1/public/getticker?market=btc-ltc", z.cache, client, BittrexDecoder{}, bp}, - //{"https://api.bitfinex.com/v1/pubticker/ltcbtc", z.cache, client, BitfinexDecoder{}, bp}, - //{"https://poloniex.com/public?command=returnTicker", z.cache, client, PoloniexDecoder{}, bp}, + {"https://ticker.openbazaar.org/api", z.cache, client, OpenBazaarDecoder{}, nil}, + {"https://bittrex.com/api/v1.1/public/getticker?market=btc-ltc", z.cache, client, BittrexDecoder{}, bp}, + {"https://api.bitfinex.com/v1/pubticker/ltcbtc", z.cache, client, BitfinexDecoder{}, bp}, + {"https://poloniex.com/public?command=returnTicker", z.cache, client, PoloniexDecoder{}, bp}, {"https://api.kraken.com/0/public/Ticker?pair=LTCXBT", z.cache, client, KrakenDecoder{}, bp}, } go z.run() @@ -103,7 +105,7 @@ func (z *LitecoinPriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, er return copy, nil } -func (z *LitecoinPriceFetcher) UnitsPerCoin() int { +func (z *LitecoinPriceFetcher) UnitsPerCoin() int64 { return exchange.SatoshiPerBTC } diff --git a/vendor/github.com/phoreproject/multiwallet/litecoin/sign.go b/vendor/github.com/phoreproject/multiwallet/litecoin/sign.go index f9b2a41ff4..387c3a04e1 100644 --- a/vendor/github.com/phoreproject/multiwallet/litecoin/sign.go +++ b/vendor/github.com/phoreproject/multiwallet/litecoin/sign.go @@ -6,6 +6,8 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" "time" "github.com/btcsuite/btcd/chaincfg" @@ -55,7 +57,7 @@ func (w *LitecoinWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.Fee coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)} coins, err := coinSelector.CoinSelect(target, coins) if err != nil { - return total, inputs, inputValues, scripts, wi.ErrorInsuffientFunds + return total, inputs, inputValues, scripts, wi.ErrInsufficientFunds } additionalPrevScripts = make(map[wire.OutPoint][]byte) additionalKeysByAddress = make(map[string]*btc.WIF) @@ -82,7 +84,8 @@ func (w *LitecoinWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.Fee } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -154,7 +157,8 @@ func (w *LitecoinWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + fee0 := w.GetFeePerByte(feeLevel) + feePerByte := fee0.Int64() estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) fee := int64(estimatedSize) * feePerByte @@ -283,11 +287,13 @@ func (w *LitecoinWallet) bumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { if err != nil { return nil, err } + n := new(big.Int) + n, _ = n.SetString(u.Value, 10) in := wi.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: int64(u.Value), + Value: *n, } transactionID, err := w.sweepAddress([]wi.TransactionInput{in}, nil, key, nil, wi.FEE_BUMP) if err != nil { @@ -315,7 +321,7 @@ func (w *LitecoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Ad var inputs []*wire.TxIn additionalPrevScripts := make(map[wire.OutPoint][]byte) for _, in := range ins { - val += in.Value + val += in.Value.Int64() ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -342,7 +348,8 @@ func (w *LitecoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Ad estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -418,7 +425,7 @@ func (w *LitecoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Ad } txIn.SignatureScript = script } else { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, *redeemScript, txscript.SigHashAll, privKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), *redeemScript, txscript.SigHashAll, privKey) if err != nil { return nil, err } @@ -458,7 +465,7 @@ func (w *LitecoinWallet) createMultisigSignature(ins []wi.TransactionInput, outs if err != nil { return sigs, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -487,7 +494,7 @@ func (w *LitecoinWallet) createMultisigSignature(ins []wi.TransactionInput, outs hashes := txscript.NewTxSigHashes(tx) for i := range tx.TxIn { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, redeemScript, txscript.SigHashAll, signingKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), redeemScript, txscript.SigHashAll, signingKey) if err != nil { continue } @@ -513,7 +520,7 @@ func (w *LitecoinWallet) multisign(ins []wi.TransactionInput, outs []wi.Transact if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -663,7 +670,8 @@ func (w *LitecoinWallet) estimateSpendFee(amount int64, feeLevel wi.FeeLevel) (u for _, input := range tx.TxIn { for _, utxo := range utxos { if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + val, _ := strconv.ParseInt(utxo.Value, 10, 64) + inval += val break } } diff --git a/vendor/github.com/phoreproject/multiwallet/litecoin/sign_test.go b/vendor/github.com/phoreproject/multiwallet/litecoin/sign_test.go index 095097a41e..acf99e35b6 100644 --- a/vendor/github.com/phoreproject/multiwallet/litecoin/sign_test.go +++ b/vendor/github.com/phoreproject/multiwallet/litecoin/sign_test.go @@ -69,6 +69,60 @@ func newMockWallet() (*LitecoinWallet, error) { return bw, nil } +func TestWalletService_VerifyWatchScriptFilter(t *testing.T) { + // Verify that AddWatchedAddress should never add a script which already represents a key from its own wallet + w, err := newMockWallet() + if err != nil { + t.Fatal(err) + } + keys := w.km.GetKeys() + + addr, err := w.km.KeyToAddress(keys[0]) + if err != nil { + t.Fatal(err) + } + err = w.AddWatchedAddresses(addr) + if err != nil { + t.Fatal(err) + } + + watchScripts, err := w.db.WatchedScripts().GetAll() + if err != nil { + t.Fatal(err) + } + + if len(watchScripts) != 0 { + t.Error("Put watched scripts fails on key manager owned key") + } +} + +func TestWalletService_VerifyWatchScriptPut(t *testing.T) { + // Verify that AddWatchedAddress should add a script which does not represent a key from its own wallet + w, err := newMockWallet() + if err != nil { + t.Fatal(err) + } + + addr, err := w.DecodeAddress("LhyLNfBkoKshT7R8Pce6vkB9T2cP2o84hx") + if err != nil { + t.Fatal(err) + } + + err = w.AddWatchedAddresses(addr) + if err != nil { + t.Fatal(err) + } + + watchScripts, err := w.db.WatchedScripts().GetAll() + if err != nil { + t.Fatal(err) + } + + if len(watchScripts) == 0 { + t.Error("Put watched scripts fails on non-key manager owned key") + } +} + func waitForTxnSync(t *testing.T, txnStore wallet.Txns) { // Look for a known txn, this sucks a bit. It would be better to check if the // number of stored txns matched the expected, but not all the mock diff --git a/vendor/github.com/phoreproject/multiwallet/litecoin/wallet.go b/vendor/github.com/phoreproject/multiwallet/litecoin/wallet.go index a763e3db31..52cb4f9718 100644 --- a/vendor/github.com/phoreproject/multiwallet/litecoin/wallet.go +++ b/vendor/github.com/phoreproject/multiwallet/litecoin/wallet.go @@ -5,6 +5,8 @@ import ( "encoding/hex" "fmt" "io" + "math/big" + "strconv" "strings" "time" @@ -44,6 +46,14 @@ type LitecoinWallet struct { log *logging.Logger } +var ( + _ = wi.Wallet(&LitecoinWallet{}) + LitecoinCurrencyDefinition = wi.CurrencyDefinition{ + Code: "LTC", + Divisibility: 8, + } +) + func NewLitecoinWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*LitecoinWallet, error) { seed := bip39.NewSeed(mnemonic, "") @@ -74,7 +84,7 @@ func NewLitecoinWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg. er = NewLitecoinPriceFetcher(proxy) } - fp := util.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, er) + fp := util.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, cfg.SuperLowFee, er) return &LitecoinWallet{ db: cfg.DB, @@ -114,8 +124,11 @@ func (w *LitecoinWallet) CurrencyCode() string { } } -func (w *LitecoinWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(ltcutil.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *LitecoinWallet) IsDust(amount big.Int) bool { + if !amount.IsInt64() || amount.Cmp(big.NewInt(0)) <= 0 { + return false + } + return txrules.IsDustAmount(ltcutil.Amount(amount.Int64()), 25, txrules.DefaultRelayFeePerKb) } func (w *LitecoinWallet) MasterPrivateKey() *hd.ExtendedKey { @@ -148,8 +161,14 @@ func (w *LitecoinWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKe func (w *LitecoinWallet) CurrentAddress(purpose wi.KeyPurpose) btcutil.Address { var addr btcutil.Address for { - key, _ := w.km.GetCurrentKey(purpose) - addr, _ = litecoinAddress(key, w.params) + key, err := w.km.GetCurrentKey(purpose) + if err != nil { + w.log.Errorf("Error generating current key: %s", err) + } + addr, err = w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } if !strings.HasPrefix(strings.ToLower(addr.String()), "ltc1") { break @@ -158,23 +177,28 @@ func (w *LitecoinWallet) CurrentAddress(purpose wi.KeyPurpose) btcutil.Address { w.log.Errorf("Error marking key as used: %s", err) } } - return btcutil.Address(addr) + return addr } func (w *LitecoinWallet) NewAddress(purpose wi.KeyPurpose) btcutil.Address { var addr btcutil.Address for { - i, _ := w.db.Keys().GetUnused(purpose) - key, _ := w.km.GenerateChildKey(purpose, uint32(i[1])) - addr, _ = litecoinAddress(key, w.params) + key, err := w.km.GetNextUnused(purpose) + if err != nil { + w.log.Errorf("Error generating next unused key: %s", err) + } + addr, err = w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } if err := w.db.Keys().MarkKeyAsUsed(addr.ScriptAddress()); err != nil { - w.log.Error("Error marking key as used: %s", err) + w.log.Errorf("Error marking key as used: %s", err) } if !strings.HasPrefix(strings.ToLower(addr.String()), "ltc1") { break } } - return btcutil.Address(addr) + return addr } func (w *LitecoinWallet) DecodeAddress(addr string) (btcutil.Address, error) { @@ -194,10 +218,12 @@ func (w *LitecoinWallet) HasKey(addr btcutil.Address) bool { return err == nil } -func (w *LitecoinWallet) Balance() (confirmed, unconfirmed int64) { +func (w *LitecoinWallet) Balance() (wi.CurrencyValue, wi.CurrencyValue) { utxos, _ := w.db.Utxos().GetAll() txns, _ := w.db.Txns().GetAll(false) - return util.CalcBalance(utxos, txns) + c, u := util.CalcBalance(utxos, txns) + return wi.CurrencyValue{Value: *big.NewInt(c), Currency: LitecoinCurrencyDefinition}, + wi.CurrencyValue{Value: *big.NewInt(u), Currency: LitecoinCurrencyDefinition} } func (w *LitecoinWallet) Transactions() ([]wi.Txn, error) { @@ -251,7 +277,7 @@ func (w *LitecoinWallet) GetTransaction(txid chainhash.Hash) (wi.Txn, error) { } tout := wi.TransactionOutput{ Address: addr, - Value: out.Value, + Value: *big.NewInt(out.Value), Index: uint32(i), } outs = append(outs, tout) @@ -265,11 +291,11 @@ func (w *LitecoinWallet) ChainTip() (uint32, chainhash.Hash) { return w.ws.ChainTip() } -func (w *LitecoinWallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { - return w.fp.GetFeePerByte(feeLevel) +func (w *LitecoinWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + return *big.NewInt(int64(w.fp.GetFeePerByte(feeLevel))) } -func (w *LitecoinWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *LitecoinWallet) Spend(amount big.Int, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -280,7 +306,7 @@ func (w *LitecoinWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.F return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -299,48 +325,58 @@ func (w *LitecoinWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { return w.bumpFee(txid) } -func (w *LitecoinWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte uint64) uint64 { +func (w *LitecoinWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := laddr.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Int64()) + return *big.NewInt(int64(fee)) } -func (w *LitecoinWallet) EstimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { - return w.estimateSpendFee(amount, feeLevel) +func (w *LitecoinWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + val, err := w.estimateSpendFee(amount.Int64(), feeLevel) + return *big.NewInt(int64(val)), err } func (w *LitecoinWallet) SweepAddress(ins []wi.TransactionInput, address *btcutil.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { return w.sweepAddress(ins, address, key, redeemScript, feeLevel) } -func (w *LitecoinWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { - return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte) +func (w *LitecoinWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte.Uint64()) } -func (w *LitecoinWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte, broadcast) +func (w *LitecoinWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte.Uint64(), broadcast) } func (w *LitecoinWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btcutil.Address, redeemScript []byte, err error) { return w.generateMultisigScript(keys, threshold, timeout, timeoutKey) } -func (w *LitecoinWallet) AddWatchedAddress(addr btcutil.Address) error { - script, err := w.AddressToScript(addr) - if err != nil { - return err +func (w *LitecoinWallet) AddWatchedAddresses(addrs ...btcutil.Address) error { + + var watchedScripts [][]byte + for _, addr := range addrs { + if !w.HasKey(addr) { + script, err := w.AddressToScript(addr) + if err != nil { + return err + } + watchedScripts = append(watchedScripts, script) + } } - err = w.db.WatchedScripts().Put(script) + + err := w.db.WatchedScripts().PutAll(watchedScripts) if err != nil { return err } - w.client.ListenAddress(addr) + + w.client.ListenAddresses(addrs...) return nil } @@ -353,7 +389,7 @@ func (w *LitecoinWallet) AddWatchedScript(script []byte) error { if err != nil { return err } - w.client.ListenAddress(addr) + w.client.ListenAddresses(addr) return nil } @@ -390,12 +426,12 @@ func (w *LitecoinWallet) DumpTables(wr io.Writer) { fmt.Fprintln(wr, "Transactions-----") txns, _ := w.db.Txns().GetAll(true) for _, tx := range txns { - fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), int(tx.Value), tx.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %s, WatchOnly: %t\n", tx.Txid, int(tx.Height), tx.Value, tx.WatchOnly) } fmt.Fprintln(wr, "\nUtxos-----") utxos, _ := w.db.Utxos().GetAll() for _, u := range utxos { - fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), int(u.Value), u.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %s, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), u.Value, u.WatchOnly) } fmt.Fprintln(wr, "\nKeys-----") keys, _ := w.db.Keys().GetAll() @@ -449,6 +485,7 @@ func (w *LitecoinWallet) Broadcast(tx *wire.MsgTx) error { if err != nil { return err } + val, _ := strconv.ParseInt(u.Value, 10, 64) input := model.Input{ Txid: in.PreviousOutPoint.Hash.String(), Vout: int(in.PreviousOutPoint.Index), @@ -458,8 +495,8 @@ func (w *LitecoinWallet) Broadcast(tx *wire.MsgTx) error { Sequence: uint32(in.Sequence), N: n, Addr: addr.String(), - Satoshis: u.Value, - Value: float64(u.Value) / util.SatoshisPerCoin(wi.Litecoin), + Satoshis: val, + Value: float64(val) / util.SatoshisPerCoin(wi.Litecoin), } cTxn.Inputs = append(cTxn.Inputs, input) } diff --git a/vendor/github.com/phoreproject/multiwallet/model/interfaces.go b/vendor/github.com/phoreproject/multiwallet/model/interfaces.go index 7932beb6f0..0ec9ec1a74 100644 --- a/vendor/github.com/phoreproject/multiwallet/model/interfaces.go +++ b/vendor/github.com/phoreproject/multiwallet/model/interfaces.go @@ -29,8 +29,8 @@ type APIClient interface { // when an existing transaction confirms for all addresses the API is listening on. TransactionNotify() <-chan Transaction - // Listen for events on this addresses. Results are returned to TransactionNotify() - ListenAddress(addr btcutil.Address) + // Listen for events on these addresses. Results are returned to TransactionNotify() + ListenAddresses(addrs ...btcutil.Address) // Broadcast a transaction to the network Broadcast(tx []byte) (string, error) diff --git a/vendor/github.com/phoreproject/multiwallet/model/mock/interfaces.go b/vendor/github.com/phoreproject/multiwallet/model/mock/interfaces.go index 009ce6f9c6..e5554bbc22 100644 --- a/vendor/github.com/phoreproject/multiwallet/model/mock/interfaces.go +++ b/vendor/github.com/phoreproject/multiwallet/model/mock/interfaces.go @@ -88,8 +88,8 @@ func (m *MockAPIClient) TransactionNotify() <-chan model.Transaction { return m.txChan } -func (m *MockAPIClient) ListenAddress(addr btcutil.Address) { - m.listeningAddrs = append(m.listeningAddrs, addr) +func (m *MockAPIClient) ListenAddresses(addrs ...btcutil.Address) { + m.listeningAddrs = append(m.listeningAddrs, addrs...) } func (m *MockAPIClient) Broadcast(tx []byte) (string, error) { diff --git a/vendor/github.com/phoreproject/multiwallet/multiwallet.go b/vendor/github.com/phoreproject/multiwallet/multiwallet.go index 807f94d4de..e0f034f27a 100644 --- a/vendor/github.com/phoreproject/multiwallet/multiwallet.go +++ b/vendor/github.com/phoreproject/multiwallet/multiwallet.go @@ -9,6 +9,7 @@ import ( "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg" "github.com/op/go-logging" + eth "github.com/phoreproject/go-ethwallet/wallet" "github.com/phoreproject/multiwallet/bitcoin" "github.com/phoreproject/multiwallet/bitcoincash" "github.com/phoreproject/multiwallet/client/blockbook" @@ -32,7 +33,7 @@ func NewMultiWallet(cfg *config.Config) (MultiWallet, error) { blockbook.Log = log if cfg.Mnemonic == "" { - ent, err := bip39.NewEntropy(128) + ent, err := bip39.NewEntropy(256) if err != nil { return nil, err } @@ -105,12 +106,16 @@ func NewMultiWallet(cfg *config.Config) (MultiWallet, error) { } else { multiwallet[util.ExtendCoinType(wallet.TestnetLitecoin)] = w } - //case wallet.Ethereum: - //w, err = eth.NewEthereumWallet(coin, cfg.Mnemonic, cfg.Proxy) - //if err != nil { - //return nil, err - //} - //multiwallet[coin.CoinType] = w + case util.ExtendCoinType(wallet.Ethereum): + w, err = eth.NewEthereumWallet(coin, cfg.Params, cfg.Mnemonic, cfg.Proxy) + if err != nil { + return nil, err + } + if cfg.Params.Name == chaincfg.MainNetParams.Name { + multiwallet[util.ExtendCoinType(wallet.Ethereum)] = w + } else { + multiwallet[util.ExtendCoinType(wallet.TestnetEthereum)] = w + } } } return multiwallet, nil diff --git a/vendor/github.com/phoreproject/multiwallet/phore/phoreprices.go b/vendor/github.com/phoreproject/multiwallet/phore/phoreprices.go index cb1dd3b3e5..596375406c 100644 --- a/vendor/github.com/phoreproject/multiwallet/phore/phoreprices.go +++ b/vendor/github.com/phoreproject/multiwallet/phore/phoreprices.go @@ -13,7 +13,7 @@ import ( "strings" ) -const SatoshiPerPHR = 100000000 +const SatoshiPerPHR int64 = 100000000 var log = logging.MustGetLogger("PhoreExchangeRates") @@ -97,7 +97,7 @@ func (b *PriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, error) { return copy, nil } -func (b *PriceFetcher) UnitsPerCoin() int { +func (b *PriceFetcher) UnitsPerCoin() int64 { return SatoshiPerPHR } diff --git a/vendor/github.com/phoreproject/multiwallet/phore/sign.go b/vendor/github.com/phoreproject/multiwallet/phore/sign.go index aadf25e8e6..9c25f10197 100644 --- a/vendor/github.com/phoreproject/multiwallet/phore/sign.go +++ b/vendor/github.com/phoreproject/multiwallet/phore/sign.go @@ -13,7 +13,7 @@ import ( "github.com/phoreproject/multiwallet/util" ) -func (w *RPCWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) (*wire.MsgTx, error) { +func (w *PhoreWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) (*wire.MsgTx, error) { tx := wire.NewMsgTx(1) height, _ := w.ws.ChainTip() @@ -32,7 +32,8 @@ func (w *RPCWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) (*wi } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + fee0 := w.GetFeePerByte(feeLevel) + feePerByte := fee0.Int64() estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) fee := int64(estimatedSize) * feePerByte diff --git a/vendor/github.com/phoreproject/multiwallet/phore/wallet.go b/vendor/github.com/phoreproject/multiwallet/phore/wallet.go index 8d6eb4ad5c..39a47459c0 100644 --- a/vendor/github.com/phoreproject/multiwallet/phore/wallet.go +++ b/vendor/github.com/phoreproject/multiwallet/phore/wallet.go @@ -10,6 +10,8 @@ import ( "github.com/phoreproject/multiwallet/model" "github.com/phoreproject/multiwallet/service" "io" + "math/big" + "strconv" "time" "github.com/OpenBazaar/spvwallet" @@ -34,8 +36,8 @@ import ( "golang.org/x/net/proxy" ) -// RPCWallet represents a wallet based on JSON-RPC and Bitcoind -type RPCWallet struct { +// PhoreWallet represents a wallet based on JSON-RPC and Bitcoind +type PhoreWallet struct { db wi.Datastore km *keys.KeyManager params *chaincfg.Params @@ -50,8 +52,16 @@ type RPCWallet struct { log *logging.Logger } +var ( + _ = wi.Wallet(&PhoreWallet{}) + PhoreCurrencyDefinition = wi.CurrencyDefinition{ + Code: "PHR", + Divisibility: 8, + } +) + // NewPhoreWallet creates a new wallet given -func NewPhoreWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*RPCWallet, error) { +func NewPhoreWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*PhoreWallet, error) { seed, err := b39.NewSeedWithErrorChecking(mnemonic, "") if err != nil { return nil, err @@ -85,9 +95,9 @@ func NewPhoreWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Par return nil, err } - fp := spvwallet.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, cfg.FeeAPI, proxy) + fp := spvwallet.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, cfg.SuperLowFee, cfg.FeeAPI, proxy) - return &RPCWallet{ + return &PhoreWallet{ db: cfg.DB, km: km, params: params, @@ -106,17 +116,17 @@ func keyToAddress(key *hd.ExtendedKey, params *chaincfg.Params) (btc.Address, er } // Start sets up the rpc wallet -func (w *RPCWallet) Start() { +func (w *PhoreWallet) Start() { w.client.Start() w.ws.Start() } -func (w *RPCWallet) Params() *chaincfg.Params { +func (w *PhoreWallet) Params() *chaincfg.Params { return w.params } // CurrencyCode returns the currency code of the wallet -func (w *RPCWallet) CurrencyCode() string { +func (w *PhoreWallet) CurrencyCode() string { if w.params.Name == PhoreMainNetParams.Name { return "phr" } else { @@ -125,21 +135,24 @@ func (w *RPCWallet) CurrencyCode() string { } // IsDust determines if an amount is considered dust -func (w *RPCWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btc.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *PhoreWallet) IsDust(amount big.Int) bool { + if !amount.IsInt64() || amount.Cmp(big.NewInt(0)) <= 0 { + return false + } + return txrules.IsDustAmount(btc.Amount(amount.Int64()), 25, txrules.DefaultRelayFeePerKb) } // MasterPrivateKey returns the wallet's master private key -func (w *RPCWallet) MasterPrivateKey() *hd.ExtendedKey { +func (w *PhoreWallet) MasterPrivateKey() *hd.ExtendedKey { return w.mPrivKey } // MasterPublicKey returns the wallet's key used to derive public keys -func (w *RPCWallet) MasterPublicKey() *hd.ExtendedKey { +func (w *PhoreWallet) MasterPublicKey() *hd.ExtendedKey { return w.mPubKey } -func (w *RPCWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) { +func (w *PhoreWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) { parentFP := []byte{0x00, 0x00, 0x00, 0x00} var id []byte if isPrivateKey { @@ -159,28 +172,41 @@ func (w *RPCWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey boo } // CurrentAddress returns an unused address -func (w *RPCWallet) CurrentAddress(purpose wallet.KeyPurpose) btc.Address { - key, _ := w.km.GetCurrentKey(purpose) - addr, _ := key.Address(w.params) - return btc.Address(addr) +func (w *PhoreWallet) CurrentAddress(purpose wallet.KeyPurpose) btc.Address { + key, err := w.km.GetCurrentKey(purpose) + if err != nil { + w.log.Errorf("Error generating current key: %s", err) + } + addr, err := w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } + return addr } // NewAddress creates a new address -func (w *RPCWallet) NewAddress(purpose wallet.KeyPurpose) btc.Address { - i, _ := w.db.Keys().GetUnused(purpose) - key, _ := w.km.GenerateChildKey(purpose, uint32(i[1])) - addr, _ := key.Address(w.params) - w.db.Keys().MarkKeyAsUsed(addr.ScriptAddress()) - return btc.Address(addr) +func (w *PhoreWallet) NewAddress(purpose wallet.KeyPurpose) btc.Address { + key, err := w.km.GetNextUnused(purpose) + if err != nil { + w.log.Errorf("Error generating next unused key: %s", err) + } + addr, err := w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } + if err := w.db.Keys().MarkKeyAsUsed(addr.ScriptAddress()); err != nil { + w.log.Errorf("Error marking key as used: %s", err) + } + return addr } // DecodeAddress decodes an address string to an address using the wallet's chain parameters -func (w *RPCWallet) DecodeAddress(addr string) (btc.Address, error) { +func (w *PhoreWallet) DecodeAddress(addr string) (btc.Address, error) { return btc.DecodeAddress(addr, w.params) } // ScriptToAddress converts a script to an address -func (w *RPCWallet) ScriptToAddress(script []byte) (btc.Address, error) { +func (w *PhoreWallet) ScriptToAddress(script []byte) (btc.Address, error) { return scriptToAddress(script, w.params) } @@ -196,12 +222,12 @@ func scriptToAddress(script []byte, params *chaincfg.Params) (btc.Address, error } // AddressToScript returns the script for a given address -func (w *RPCWallet) AddressToScript(addr btc.Address) ([]byte, error) { +func (w *PhoreWallet) AddressToScript(addr btc.Address) ([]byte, error) { return txscript.PayToAddrScript(addr) } // HasKey returns true if we have the private key for a given address -func (w *RPCWallet) HasKey(addr btc.Address) bool { +func (w *PhoreWallet) HasKey(addr btc.Address) bool { _, err := w.km.GetKeyForScript(addr.ScriptAddress()) if err != nil { return false @@ -210,14 +236,16 @@ func (w *RPCWallet) HasKey(addr btc.Address) bool { } // Balance returns the total balance of our addresses -func (w *RPCWallet) Balance() (confirmed, unconfirmed int64) { +func (w *PhoreWallet) Balance() (wi.CurrencyValue, wi.CurrencyValue) { utxos, _ := w.db.Utxos().GetAll() txns, _ := w.db.Txns().GetAll(false) - return util.CalcBalance(utxos, txns) + c, u := util.CalcBalance(utxos, txns) + return wi.CurrencyValue{Value: *big.NewInt(c), Currency: PhoreCurrencyDefinition}, + wi.CurrencyValue{Value: *big.NewInt(u), Currency: PhoreCurrencyDefinition} } // Transactions returns all of the transactions relating to any of our addresses -func (w *RPCWallet) Transactions() ([]wallet.Txn, error) { +func (w *PhoreWallet) Transactions() ([]wallet.Txn, error) { height, _ := w.ChainTip() txns, err := w.db.Txns().GetAll(false) if err != nil { @@ -252,7 +280,7 @@ func (w *RPCWallet) Transactions() ([]wallet.Txn, error) { } // GetTransaction returns the transaction given by a transaction hash -func (w *RPCWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) { +func (w *PhoreWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) { txn, err := w.db.Txns().Get(txid) if err == nil { tx := wire.NewMsgTx(1) @@ -275,7 +303,7 @@ func (w *RPCWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) { } tout := wi.TransactionOutput{ Address: addr, - Value: out.Value, + Value: *big.NewInt(out.Value), Index: uint32(i), } outs = append(outs, tout) @@ -286,17 +314,17 @@ func (w *RPCWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) { } // ChainTip returns the tip of the active blockchain -func (w *RPCWallet) ChainTip() (uint32, chainhash.Hash) { +func (w *PhoreWallet) ChainTip() (uint32, chainhash.Hash) { return w.ws.ChainTip() } // GetFeePerByte gets the fee in pSAT per byte -func (w *RPCWallet) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 { - return w.fp.GetFeePerByte(feeLevel) +func (w *PhoreWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + return *big.NewInt(int64(w.fp.GetFeePerByte(feeLevel))) } // Spend spends an amount from an address with a given fee level -func (w *RPCWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *PhoreWallet) Spend(amount big.Int, addr btc.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -307,7 +335,7 @@ func (w *RPCWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLev return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -321,7 +349,7 @@ func (w *RPCWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLev } // BumpFee attempts to bump the fee for a transaction -func (w *RPCWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { +func (w *PhoreWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { txn, err := w.db.Txns().Get(txid) if err != nil { return nil, err @@ -348,11 +376,13 @@ func (w *RPCWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { if err != nil { return nil, err } + n := new(big.Int) + n, _ = n.SetString(u.Value, 10) in := wi.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: int64(u.Value), + Value: *n, } transactionID, err := w.SweepAddress([]wi.TransactionInput{in}, nil, key, nil, wi.FEE_BUMP) if err != nil { @@ -365,20 +395,20 @@ func (w *RPCWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { } // EstimateFee estimates the fee of a transaction -func (w *RPCWallet) EstimateFee(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, feePerByte uint64) uint64 { +func (w *PhoreWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := txscript.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Int64()) + return *big.NewInt(int64(fee)) } // EstimateSpendFee builds a spend transaction for the amount and return the transaction fee -func (w *RPCWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (uint64, error) { +func (w *PhoreWallet) estimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { // Since this is an estimate we can use a dummy output address. Let's use a long one so we don't under estimate. addr, err := btc.DecodeAddress("PARPpSkk5wpji6kE2y9YxHGZ9k96wZPfin", w.params) if err != nil { @@ -400,7 +430,8 @@ func (w *RPCWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (ui for _, input := range tx.TxIn { for _, utxo := range utxos { if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + val, _ := strconv.ParseInt(utxo.Value, 10, 64) + inval += val break } } @@ -411,7 +442,12 @@ func (w *RPCWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (ui return uint64(inval - outval), err } -func (w *RPCWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, optionalOutput *wire.TxOut) (*wire.MsgTx, error) { +func (w *PhoreWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + val, err := w.estimateSpendFee(amount.Int64(), feeLevel) + return *big.NewInt(int64(val)), err +} + +func (w *PhoreWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, optionalOutput *wire.TxOut) (*wire.MsgTx, error) { // Check for dust script, _ := txscript.PayToAddrScript(addr) if txrules.IsDustAmount(btc.Amount(amount), len(script), txrules.DefaultRelayFeePerKb) { @@ -437,7 +473,7 @@ func (w *RPCWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeL coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)} coins, err := coinSelector.CoinSelect(target, coins) if err != nil { - return total, inputs, inputValues, scripts, wi.ErrorInsuffientFunds + return total, inputs, inputValues, scripts, wi.ErrInsufficientFunds } additionalPrevScripts = make(map[wire.OutPoint][]byte) additionalKeysByAddress = make(map[string]*btc.WIF) @@ -464,7 +500,8 @@ func (w *RPCWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeL } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -515,7 +552,7 @@ func (w *RPCWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeL } // SweepAddress sweeps any UTXOs from an address in a single transaction -func (w *RPCWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wallet.FeeLevel) (*chainhash.Hash, error) { +func (w *PhoreWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wallet.FeeLevel) (*chainhash.Hash, error) { var internalAddr btc.Address if address != nil { internalAddr = *address @@ -531,7 +568,7 @@ func (w *RPCWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Add var inputs []*wire.TxIn additionalPrevScripts := make(map[wire.OutPoint][]byte) for _, in := range ins { - val += in.Value + val += in.Value.Int64() ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -558,7 +595,8 @@ func (w *RPCWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Add estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -639,8 +677,12 @@ func (w *RPCWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Add return &txid, nil } +func (w *PhoreWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte.Uint64()) +} + // CreateMultisigSignature creates a multisig signature given the transaction inputs and outputs and the keys -func (w *RPCWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wallet.Signature, error) { +func (w *PhoreWallet) createMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { var sigs []wallet.Signature tx := wire.NewMsgTx(1) for _, in := range ins { @@ -658,7 +700,7 @@ func (w *RPCWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs return sigs, err } - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } @@ -697,7 +739,7 @@ func (w *RPCWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs } // Multisign signs a multisig transaction -func (w *RPCWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, sigs1 []wallet.Signature, sigs2 []wallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { +func (w *PhoreWallet) multisign(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, sigs1 []wallet.Signature, sigs2 []wallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { tx := wire.NewMsgTx(1) for _, in := range ins { ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) @@ -713,7 +755,7 @@ func (w *RPCWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.Trans if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } @@ -783,8 +825,12 @@ func (w *RPCWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.Trans return buf.Bytes(), nil } +func (w *PhoreWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte.Uint64(), broadcast) +} + // GenerateMultisigScript generates a script representing a multisig wallet -func (w *RPCWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) { +func (w *PhoreWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) { if uint32(timeout.Hours()) > 0 && timeoutKey == nil { return nil, nil, errors.New("Timeout key must be non nil when using an escrow timeout") } @@ -847,31 +893,40 @@ func (w *RPCWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, return addr, redeemScript, nil } -func (w *RPCWallet) AddWatchedAddress(addr btc.Address) error { - script, err := w.AddressToScript(addr) - if err != nil { - return err +func (w *PhoreWallet) AddWatchedAddresses(addrs ...btc.Address) error { + + var watchedScripts [][]byte + for _, addr := range addrs { + if !w.HasKey(addr) { + script, err := w.AddressToScript(addr) + if err != nil { + return err + } + watchedScripts = append(watchedScripts, script) + } } - err = w.db.WatchedScripts().Put(script) + + err := w.db.WatchedScripts().PutAll(watchedScripts) if err != nil { return err } - w.client.ListenAddress(addr) + + w.client.ListenAddresses(addrs...) return nil } // AddTransactionListener adds a listener for any wallet transactions -func (w *RPCWallet) AddTransactionListener(callback func(wallet.TransactionCallback)) { +func (w *PhoreWallet) AddTransactionListener(callback func(wallet.TransactionCallback)) { w.ws.AddTransactionListener(callback) } // ReSyncBlockchain resyncs the addresses used by the SPV wallet -func (w *RPCWallet) ReSyncBlockchain(fromDate time.Time) { +func (w *PhoreWallet) ReSyncBlockchain(fromDate time.Time) { go w.ws.UpdateState() } // GetConfirmations returns the number of confirmations and the block number where the transaction was confirmed -func (w *RPCWallet) GetConfirmations(txid chainhash.Hash) (uint32, uint32, error) { +func (w *PhoreWallet) GetConfirmations(txid chainhash.Hash) (uint32, uint32, error) { txn, err := w.db.Txns().Get(txid) if err != nil { return 0, 0, err @@ -884,30 +939,30 @@ func (w *RPCWallet) GetConfirmations(txid chainhash.Hash) (uint32, uint32, error } // Close closes the rpc wallet connection -func (w *RPCWallet) Close() { +func (w *PhoreWallet) Close() { w.ws.Stop() w.client.Close() } -func (w *RPCWallet) ExchangeRates() wallet.ExchangeRates { +func (w *PhoreWallet) ExchangeRates() wallet.ExchangeRates { return w.exchangeRates } -func (w *RPCWallet) DumpTables(wr io.Writer) { +func (w *PhoreWallet) DumpTables(wr io.Writer) { fmt.Fprintln(wr, "Transactions-----") txns, _ := w.db.Txns().GetAll(true) for _, tx := range txns { - fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), int(tx.Value), tx.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), tx.Value, tx.WatchOnly) } fmt.Fprintln(wr, "\nUtxos-----") utxos, _ := w.db.Utxos().GetAll() for _, u := range utxos { - fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), int(u.Value), u.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), u.Value, u.WatchOnly) } } // Broadcast a transaction to the network -func (w *RPCWallet) Broadcast(tx *wire.MsgTx) error { +func (w *PhoreWallet) Broadcast(tx *wire.MsgTx) error { var buf bytes.Buffer tx.BtcEncode(&buf, wire.ProtocolVersion, wire.BaseEncoding) cTxn := model.Transaction{ @@ -936,6 +991,7 @@ func (w *RPCWallet) Broadcast(tx *wire.MsgTx) error { if err != nil { return err } + val, _ := strconv.ParseInt(u.Value, 10, 64) input := model.Input{ Txid: in.PreviousOutPoint.Hash.String(), Vout: int(in.PreviousOutPoint.Index), @@ -945,8 +1001,8 @@ func (w *RPCWallet) Broadcast(tx *wire.MsgTx) error { Sequence: uint32(in.Sequence), N: n, Addr: addr.String(), - Satoshis: u.Value, - Value: float64(u.Value) / util.SatoshisPerCoin(util.CoinTypePhore.ToCoinType()), + Satoshis: val, + Value: float64(val) / util.SatoshisPerCoin(wi.Bitcoin), } cTxn.Inputs = append(cTxn.Inputs, input) } @@ -976,6 +1032,6 @@ func (w *RPCWallet) Broadcast(tx *wire.MsgTx) error { } // AssociateTransactionWithOrder used for ORDER_PAYMENT message -func (w *RPCWallet) AssociateTransactionWithOrder(cb wi.TransactionCallback) { +func (w *PhoreWallet) AssociateTransactionWithOrder(cb wi.TransactionCallback) { w.ws.InvokeTransactionListeners(cb) } diff --git a/vendor/github.com/phoreproject/multiwallet/service/wallet_service.go b/vendor/github.com/phoreproject/multiwallet/service/wallet_service.go index d6ec93b510..ac5d2b6c7c 100644 --- a/vendor/github.com/phoreproject/multiwallet/service/wallet_service.go +++ b/vendor/github.com/phoreproject/multiwallet/service/wallet_service.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "math" + "math/big" "strconv" "sync" "time" @@ -124,9 +125,12 @@ func (ws *WalletService) listen() { txChan = ws.client.TransactionNotify() blockChan = ws.client.BlockNotify() ) + + var listenAddrs []btcutil.Address for _, sa := range addrs { - ws.client.ListenAddress(sa.Addr) + listenAddrs = append(listenAddrs, sa.Addr) } + ws.client.ListenAddresses(listenAddrs...) for { select { @@ -359,7 +363,7 @@ func (ws *WalletService) saveSingleUtxoToDB(u model.Utxo, addrs map[string]store newU := wallet.Utxo{ Op: *wire.NewOutPoint(ch, uint32(u.Vout)), - Value: u.Satoshis, + Value: strconv.FormatInt(u.Satoshis, 10), WatchOnly: watchOnly, ScriptPubkey: scriptBytes, AtHeight: height, @@ -413,7 +417,7 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 msgTx := wire.NewMsgTx(int32(u.Version)) msgTx.LockTime = uint32(u.Locktime) hits := 0 - value := int64(0) + value := new(big.Int) height := int32(0) if u.Confirmations > 0 { @@ -453,12 +457,12 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 Log.Errorf("error converting outpoint hash for %s: %s", ws.coinType.String(), err.Error()) return } - v := int64(math.Round(in.Value * float64(util.SatoshisPerCoin(ws.coinType.ToCoinType())))) + v := big.NewInt(int64(math.Round(in.Value * float64(util.SatoshisPerCoin(ws.coinType.ToCoinType()))))) cbin := wallet.TransactionInput{ OutpointHash: h, OutpointIndex: op.Index, LinkedAddress: addr, - Value: v, + Value: *v, } cb.Inputs = append(cb.Inputs, cbin) @@ -467,7 +471,7 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 continue } if !sa.WatchOnly { - value -= v + value.Sub(value, v) // -= v hits++ } relevant = true @@ -491,11 +495,11 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 continue } - v := int64(math.Round(out.Value * float64(util.SatoshisPerCoin(ws.coinType.ToCoinType())))) + v := big.NewInt(int64(math.Round(out.Value * float64(util.SatoshisPerCoin(ws.coinType.ToCoinType()))))) - txout := wire.NewTxOut(v, script) + txout := wire.NewTxOut(v.Int64(), script) msgTx.TxOut = append(msgTx.TxOut, txout) - cbout := wallet.TransactionOutput{Address: addr, Value: v, Index: uint32(i)} + cbout := wallet.TransactionOutput{Address: addr, Value: *v, Index: uint32(i)} cb.Outputs = append(cb.Outputs, cbout) sa, ok := addrs[out.ScriptPubKey.Addresses[0]] @@ -503,7 +507,7 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 continue } if !sa.WatchOnly { - value += v + value.Add(value, v) // += v hits++ // Mark the key we received coins to as used err = ws.km.MarkKeyAsUsed(sa.Addr.ScriptAddress()) @@ -519,10 +523,10 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 return } - cb.Value = value + cb.Value = *value cb.WatchOnly = (hits == 0) saved, err := ws.db.Txns().Get(*txHash) - if err != nil { + if err != nil || saved.WatchOnly != cb.WatchOnly { ts := time.Now() if u.Confirmations > 0 { ts = time.Unix(u.BlockTime, 0) @@ -535,7 +539,7 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 msgTx.BtcEncode(&buf, wire.ProtocolVersion, wire.BaseEncoding) txBytes = buf.Bytes() } - err = ws.db.Txns().Put(txBytes, txHash.String(), int(value), int(height), ts, hits == 0) + err = ws.db.Txns().Put(txBytes, txHash.String(), value.String(), int(height), ts, hits == 0) if err != nil { Log.Errorf("putting txid (%s): %s", txHash.String(), err.Error()) return @@ -630,7 +634,9 @@ func (ws *WalletService) getStoredAddresses() map[string]storedAddress { } addr = addrSlice[0] } - addrs[addr.String()] = storedAddress{addr, true} + if _, ok := addrs[addr.String()]; !ok { + addrs[addr.String()] = storedAddress{addr, true} + } } return addrs diff --git a/vendor/github.com/phoreproject/multiwallet/util/balance.go b/vendor/github.com/phoreproject/multiwallet/util/balance.go index ca40b7479c..8202a0ae09 100644 --- a/vendor/github.com/phoreproject/multiwallet/util/balance.go +++ b/vendor/github.com/phoreproject/multiwallet/util/balance.go @@ -2,6 +2,8 @@ package util import ( "bytes" + "strconv" + wi "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/wire" ) @@ -13,14 +15,15 @@ func CalcBalance(utxos []wi.Utxo, txns []wi.Txn) (confirmed, unconfirmed int64) } for _, utxo := range utxos { + val, _ := strconv.ParseInt(utxo.Value, 10, 64) if !utxo.WatchOnly { if utxo.AtHeight > 0 { - confirmed += utxo.Value + confirmed += val } else { if checkIfStxoIsConfirmed(utxo.Op.Hash.String(), txmap) { - confirmed += utxo.Value + confirmed += val } else { - unconfirmed += utxo.Value + unconfirmed += val } } } diff --git a/vendor/github.com/phoreproject/multiwallet/util/coin.go b/vendor/github.com/phoreproject/multiwallet/util/coin.go index 57ec5b70f2..f25e45e71e 100644 --- a/vendor/github.com/phoreproject/multiwallet/util/coin.go +++ b/vendor/github.com/phoreproject/multiwallet/util/coin.go @@ -1,6 +1,8 @@ package util import ( + "strconv" + "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -46,7 +48,8 @@ func GatherCoins(height uint32, utxos []wallet.Utxo, scriptToAddress func(script if u.AtHeight > 0 { confirmations = int32(height) - u.AtHeight } - c, err := NewCoin(u.Op.Hash, u.Op.Index, btcutil.Amount(u.Value), int64(confirmations), u.ScriptPubkey) + val, _ := strconv.ParseInt(u.Value, 10, 64) + c, err := NewCoin(u.Op.Hash, u.Op.Index, btcutil.Amount(val), int64(confirmations), u.ScriptPubkey) if err != nil { continue } diff --git a/vendor/github.com/phoreproject/multiwallet/util/fees.go b/vendor/github.com/phoreproject/multiwallet/util/fees.go index ffaffbfc8a..b55be9afc7 100644 --- a/vendor/github.com/phoreproject/multiwallet/util/fees.go +++ b/vendor/github.com/phoreproject/multiwallet/util/fees.go @@ -18,10 +18,11 @@ type Fees struct { } type FeeProvider struct { - maxFee uint64 - priorityFee uint64 - normalFee uint64 - economicFee uint64 + maxFee uint64 + priorityFee uint64 + normalFee uint64 + economicFee uint64 + superEconomicFee uint64 exchangeRates wallet.ExchangeRates } @@ -39,20 +40,21 @@ const ( AverageTransactionSize = 226 ) -func NewFeeProvider(maxFee, priorityFee, normalFee, economicFee uint64, exchangeRates wallet.ExchangeRates) *FeeProvider { +func NewFeeProvider(maxFee, priorityFee, normalFee, economicFee, superEconomicFee uint64, exchangeRates wallet.ExchangeRates) *FeeProvider { return &FeeProvider{ - maxFee: maxFee, - priorityFee: priorityFee, - normalFee: normalFee, - economicFee: economicFee, - exchangeRates: exchangeRates, + maxFee: maxFee, + priorityFee: priorityFee, + normalFee: normalFee, + economicFee: economicFee, + superEconomicFee: superEconomicFee, + exchangeRates: exchangeRates, } } func (fp *FeeProvider) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 { defaultFee := func() uint64 { switch feeLevel { - case wallet.PRIOIRTY: + case wallet.PRIORITY: return fp.priorityFee case wallet.NORMAL: return fp.normalFee @@ -75,12 +77,14 @@ func (fp *FeeProvider) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 { var target FeeTargetInUSDCents switch feeLevel { - case wallet.PRIOIRTY: + case wallet.PRIORITY: target = PriorityTarget case wallet.NORMAL: target = NormalTarget case wallet.ECONOMIC: target = EconomicTarget + case wallet.SUPER_ECONOMIC: + return fp.superEconomicFee case wallet.FEE_BUMP: target = PriorityTarget * 2 default: diff --git a/vendor/github.com/phoreproject/multiwallet/zcash/address/address.go b/vendor/github.com/phoreproject/multiwallet/zcash/address/address.go index f9f77f457a..8f7350226f 100644 --- a/vendor/github.com/phoreproject/multiwallet/zcash/address/address.go +++ b/vendor/github.com/phoreproject/multiwallet/zcash/address/address.go @@ -1,10 +1,9 @@ package address import ( - "errors" - "bytes" "crypto/sha256" + "errors" "fmt" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" diff --git a/vendor/github.com/phoreproject/multiwallet/zcash/exchange_rates.go b/vendor/github.com/phoreproject/multiwallet/zcash/exchange_rates.go index cd11add28b..1faf0fc99c 100644 --- a/vendor/github.com/phoreproject/multiwallet/zcash/exchange_rates.go +++ b/vendor/github.com/phoreproject/multiwallet/zcash/exchange_rates.go @@ -3,14 +3,13 @@ package zcash import ( "encoding/json" "errors" - "github.com/phoreproject/multiwallet/util" - "net" "net/http" "reflect" "strconv" "sync" "time" + "github.com/phoreproject/multiwallet/util" exchange "github.com/OpenBazaar/spvwallet/exchangerates" "golang.org/x/net/proxy" ) @@ -44,12 +43,15 @@ func NewZcashPriceFetcher(dialer proxy.Dialer) *ZcashPriceFetcher { z := ZcashPriceFetcher{ cache: make(map[string]float64), } - dial := net.Dial + + var client *http.Client if dialer != nil { - dial = dialer.Dial + dial := dialer.Dial + tbTransport := &http.Transport{Dial: dial} + client = &http.Client{Transport: tbTransport, Timeout: time.Minute} + } else { + client = &http.Client{Timeout: time.Minute} } - tbTransport := &http.Transport{Dial: dial} - client := &http.Client{Transport: tbTransport, Timeout: time.Minute} z.providers = []*ExchangeRateProvider{ {"https://ticker.openbazaar.org/api", z.cache, client, OpenBazaarDecoder{}, nil}, @@ -99,7 +101,7 @@ func (z *ZcashPriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, error return z.cache, nil } -func (z *ZcashPriceFetcher) UnitsPerCoin() int { +func (z *ZcashPriceFetcher) UnitsPerCoin() int64 { return exchange.SatoshiPerBTC } diff --git a/vendor/github.com/phoreproject/multiwallet/zcash/sign.go b/vendor/github.com/phoreproject/multiwallet/zcash/sign.go index 040a497e87..ec74fecaa0 100644 --- a/vendor/github.com/phoreproject/multiwallet/zcash/sign.go +++ b/vendor/github.com/phoreproject/multiwallet/zcash/sign.go @@ -6,9 +6,12 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" + "time" + "github.com/btcsuite/btcd/chaincfg" "github.com/minio/blake2b-simd" - "time" "github.com/OpenBazaar/spvwallet" wi "github.com/OpenBazaar/wallet-interface" @@ -38,8 +41,8 @@ var ( ) const ( - sigHashMask = 0x1f - saplingBranchID = 1991772603 + sigHashMask = 0x1f + branchID = 0xe9ff75a6 ) func (w *ZCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeLevel, optionalOutput *wire.TxOut) (*wire.MsgTx, error) { @@ -52,8 +55,11 @@ func (w *ZCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeLev return nil, wi.ErrorDustAmount } - var additionalPrevScripts map[wire.OutPoint][]byte - var additionalKeysByAddress map[string]*btc.WIF + var ( + additionalPrevScripts map[wire.OutPoint][]byte + additionalKeysByAddress map[string]*btc.WIF + inVals map[wire.OutPoint]btc.Amount + ) // Create input source height, _ := w.ws.ChainTip() @@ -71,10 +77,11 @@ func (w *ZCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeLev coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)} coins, err := coinSelector.CoinSelect(target, coins) if err != nil { - return total, inputs, inputValues, scripts, wi.ErrorInsuffientFunds + return total, inputs, inputValues, scripts, wi.ErrInsufficientFunds } additionalPrevScripts = make(map[wire.OutPoint][]byte) additionalKeysByAddress = make(map[string]*btc.WIF) + inVals = make(map[wire.OutPoint]btc.Amount) for _, c := range coins.Coins() { total += c.Value() outpoint := wire.NewOutPoint(c.Hash(), c.Index()) @@ -93,13 +100,14 @@ func (w *ZCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeLev } wif, _ := btc.NewWIF(privKey, w.params, true) additionalKeysByAddress[addr.EncodeAddress()] = wif - inputValues = append(inputValues, c.Value()) + inVals[*outpoint] = c.Value() } return total, inputs, inputValues, scripts, nil } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -118,7 +126,7 @@ func (w *ZCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeLev if optionalOutput != nil { outputs = append(outputs, optionalOutput) } - authoredTx, inputValues, err := newUnsignedTransaction(outputs, btc.Amount(feePerKB), inputSource, changeSource) + authoredTx, err := newUnsignedTransaction(outputs, btc.Amount(feePerKB), inputSource, changeSource) if err != nil { return nil, err } @@ -142,7 +150,7 @@ func (w *ZCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeLev if err != nil { return nil, err } - val := int64(inputValues[i].ToUnit(btc.AmountSatoshi)) + val := int64(inVals[txIn.PreviousOutPoint].ToUnit(btc.AmountSatoshi)) sig, err := rawTxInSignature(authoredTx.Tx, i, prevOutScript, txscript.SigHashAll, key, val) if err != nil { return nil, errors.New("failed to sign transaction") @@ -178,7 +186,8 @@ func (w *ZCashWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) (* } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + fee0 := w.GetFeePerByte(feeLevel) + feePerByte := fee0.Int64() estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) fee := int64(estimatedSize) * feePerByte @@ -229,7 +238,7 @@ func (w *ZCashWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) (* return tx, nil } -func newUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInputs txauthor.InputSource, fetchChange txauthor.ChangeSource) (*txauthor.AuthoredTx, []btc.Amount, error) { +func newUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInputs txauthor.InputSource, fetchChange txauthor.ChangeSource) (*txauthor.AuthoredTx, error) { var targetAmount btc.Amount for _, txOut := range outputs { @@ -238,15 +247,13 @@ func newUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInp estimatedSize := EstimateSerializeSize(1, outputs, true, P2PKH) targetFee := txrules.FeeForSerializeSize(feePerKb, estimatedSize) - var inputValues []btc.Amount for { - inputAmount, inputs, vals, scripts, err := fetchInputs(targetAmount + targetFee) - inputValues = vals + inputAmount, inputs, _, scripts, err := fetchInputs(targetAmount + targetFee) if err != nil { - return nil, nil, err + return nil, err } if inputAmount < targetAmount+targetFee { - return nil, nil, errors.New("insufficient funds available to construct transaction") + return nil, errors.New("insufficient funds available to construct transaction") } maxSignedSize := EstimateSerializeSize(len(inputs), outputs, true, P2PKH) @@ -269,10 +276,10 @@ func newUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInp P2PKHOutputSize, txrules.DefaultRelayFeePerKb) { changeScript, err := fetchChange() if err != nil { - return nil, nil, err + return nil, err } if len(changeScript) > P2PKHPkScriptSize { - return nil, nil, errors.New("fee estimation requires change " + + return nil, errors.New("fee estimation requires change " + "scripts no larger than P2PKH output scripts") } change := wire.NewTxOut(int64(changeAmount), changeScript) @@ -286,7 +293,7 @@ func newUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInp PrevScripts: scripts, TotalInput: inputAmount, ChangeIndex: changeIndex, - }, inputValues, nil + }, nil } } @@ -317,11 +324,13 @@ func (w *ZCashWallet) bumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { if err != nil { return nil, err } + n := new(big.Int) + n, _ = n.SetString(u.Value, 10) in := wi.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: int64(u.Value), + Value: *n, } transactionID, err := w.sweepAddress([]wi.TransactionInput{in}, nil, key, nil, wi.FEE_BUMP) if err != nil { @@ -350,8 +359,8 @@ func (w *ZCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Addre additionalPrevScripts := make(map[wire.OutPoint][]byte) var values []int64 for _, in := range ins { - val += in.Value - values = append(values, in.Value) + val += in.Value.Int64() + values = append(values, in.Value.Int64()) ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -380,7 +389,8 @@ func (w *ZCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Addre estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -440,7 +450,7 @@ func (w *ZCashWallet) createMultisigSignature(ins []wi.TransactionInput, outs [] if err != nil { return sigs, err } - values = append(values, in.Value) + values = append(values, in.Value.Int64()) outpoint := wire.NewOutPoint(ch, in.OutpointIndex) input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) tx.TxIn = append(tx.TxIn, input) @@ -450,7 +460,7 @@ func (w *ZCashWallet) createMultisigSignature(ins []wi.TransactionInput, outs [] if err != nil { return sigs, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -499,7 +509,7 @@ func (w *ZCashWallet) multisign(ins []wi.TransactionInput, outs []wi.Transaction if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -613,8 +623,9 @@ func (w *ZCashWallet) estimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint } for _, input := range tx.TxIn { for _, utxo := range utxos { + val, _ := strconv.ParseInt(utxo.Value, 10, 64) if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + inval += val break } } @@ -752,7 +763,7 @@ func calcSignatureHash(prevScriptBytes []byte, hashType txscript.SigHashType, tx sigHash.Write(bSequence[:]) leBranchID := make([]byte, 4) - binary.LittleEndian.PutUint32(leBranchID, saplingBranchID) + binary.LittleEndian.PutUint32(leBranchID, branchID) bl, _ := blake2b.New(&blake2b.Config{ Size: 32, Person: append(sigHashPersonalization, leBranchID...), diff --git a/vendor/github.com/phoreproject/multiwallet/zcash/sign_test.go b/vendor/github.com/phoreproject/multiwallet/zcash/sign_test.go index 832b7f6f9f..bb9c4a795e 100644 --- a/vendor/github.com/phoreproject/multiwallet/zcash/sign_test.go +++ b/vendor/github.com/phoreproject/multiwallet/zcash/sign_test.go @@ -32,7 +32,7 @@ type FeeResponse struct { func newMockWallet() (*ZCashWallet, error) { mockDb := datastore.NewMockMultiwalletDatastore() - db, err := mockDb.GetDatastoreForWallet(wallet.BitcoinCash) + db, err := mockDb.GetDatastoreForWallet(wallet.Zcash) if err != nil { return nil, err } @@ -46,7 +46,7 @@ func newMockWallet() (*ZCashWallet, error) { if err != nil { return nil, err } - km, err := keys.NewKeyManager(db.Keys(), params, master, wallet.BitcoinCash, zcashCashAddress) + km, err := keys.NewKeyManager(db.Keys(), params, master, wallet.Zcash, zcashAddress) if err != nil { return nil, err } @@ -60,7 +60,7 @@ func newMockWallet() (*ZCashWallet, error) { fp: fp, } cli := mock.NewMockApiClient(bw.AddressToScript) - ws, err := service.NewWalletService(db, km, cli, params, wallet.BitcoinCash, cache.NewMockCacher()) + ws, err := service.NewWalletService(db, km, cli, params, wallet.Zcash, cache.NewMockCacher()) if err != nil { return nil, err } @@ -69,6 +69,60 @@ func newMockWallet() (*ZCashWallet, error) { return bw, nil } +func TestWalletService_VerifyWatchScriptFilter(t *testing.T) { + // Verify that AddWatchedAddress should never add a script which already represents a key from its own wallet + w, err := newMockWallet() + if err != nil { + t.Fatal(err) + } + keys := w.km.GetKeys() + + addr, err := w.km.KeyToAddress(keys[0]) + if err != nil { + t.Fatal(err) + } + err = w.AddWatchedAddresses(addr) + if err != nil { + t.Fatal(err) + } + + watchScripts, err := w.db.WatchedScripts().GetAll() + if err != nil { + t.Fatal(err) + } + + if len(watchScripts) != 0 { + t.Error("Put watched scripts fails on key manager owned key") + } +} + +func TestWalletService_VerifyWatchScriptPut(t *testing.T) { + // Verify that AddWatchedAddress should add a script which does not represent a key from its own wallet + w, err := newMockWallet() + if err != nil { + t.Fatal(err) + } + + addr, err := w.DecodeAddress("t1aZvxRLCGVeMPFXvqfnBgHVEbi4c6g8MVa") + if err != nil { + t.Fatal(err) + } + + err = w.AddWatchedAddresses(addr) + if err != nil { + t.Fatal(err) + } + + watchScripts, err := w.db.WatchedScripts().GetAll() + if err != nil { + t.Fatal(err) + } + + if len(watchScripts) == 0 { + t.Error("Put watched scripts fails on non-key manager owned key") + } +} + func waitForTxnSync(t *testing.T, txnStore wallet.Txns) { // Look for a known txn, this sucks a bit. It would be better to check if the // number of stored txns matched the expected, but not all the mock @@ -251,7 +305,7 @@ func TestZCashWallet_GenerateMultisigScript(t *testing.T) { if err != nil { t.Error(err) } - if addr.String() != "t3ZZqETXWTohq3xXHxD9yzfq4UxpcACLkVc" { + if addr.String() != "t3S5yuHPzajqHcaJ6WDTGAwTuK9VDvWYj7r" { t.Error("Returned invalid address") } @@ -311,7 +365,7 @@ func TestZCashWallet_newUnsignedTransaction(t *testing.T) { } // Regular transaction - authoredTx, _, err := newUnsignedTransaction(outputs, btcutil.Amount(1000), inputSource, changeSource) + authoredTx, err := newUnsignedTransaction(outputs, btcutil.Amount(1000), inputSource, changeSource) if err != nil { t.Error(err) } @@ -324,7 +378,7 @@ func TestZCashWallet_newUnsignedTransaction(t *testing.T) { // Insufficient funds outputs[0].Value = 1000000000 - _, _, err = newUnsignedTransaction(outputs, btcutil.Amount(1000), inputSource, changeSource) + _, err = newUnsignedTransaction(outputs, btcutil.Amount(1000), inputSource, changeSource) if err == nil { t.Error("Failed to return insuffient funds error") } @@ -653,7 +707,7 @@ func TestCalcSignatureHash(t *testing.T) { if err != nil { t.Fatal(err) } - expected, err := hex.DecodeString("f3148f80dfab5e573d5edfe7a850f5fd39234f80b5429d3a57edcc11e34c585b") + expected, err := hex.DecodeString("8df91420215909927be677a978c36b528e1e7b4ba343acefdd259fe57f3f1f85") if err != nil { t.Fatal(err) } diff --git a/vendor/github.com/phoreproject/multiwallet/zcash/wallet.go b/vendor/github.com/phoreproject/multiwallet/zcash/wallet.go index 8f699c545c..5c07ec4405 100644 --- a/vendor/github.com/phoreproject/multiwallet/zcash/wallet.go +++ b/vendor/github.com/phoreproject/multiwallet/zcash/wallet.go @@ -1,9 +1,12 @@ package zcash import ( + "bytes" "encoding/hex" "fmt" "io" + "math/big" + "strconv" "time" wi "github.com/OpenBazaar/wallet-interface" @@ -41,6 +44,14 @@ type ZCashWallet struct { log *logging.Logger } +var ( + _ = wi.Wallet(&ZCashWallet{}) + ZcashCurrencyDefinition = wi.CurrencyDefinition{ + Code: "ZEC", + Divisibility: 8, + } +) + func NewZCashWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*ZCashWallet, error) { seed := bip39.NewSeed(mnemonic, "") @@ -52,7 +63,7 @@ func NewZCashWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Par if err != nil { return nil, err } - km, err := keys.NewKeyManager(cfg.DB.Keys(), params, mPrivKey, wi.Zcash, zcashCashAddress) + km, err := keys.NewKeyManager(cfg.DB.Keys(), params, mPrivKey, wi.Zcash, zcashAddress) if err != nil { return nil, err } @@ -72,7 +83,7 @@ func NewZCashWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Par er = NewZcashPriceFetcher(proxy) } - fp := util.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, er) + fp := util.NewFeeProvider(cfg.MaxFee, cfg.HighFee, cfg.MediumFee, cfg.LowFee, cfg.SuperLowFee, er) return &ZCashWallet{ db: cfg.DB, @@ -88,7 +99,7 @@ func NewZCashWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Par }, nil } -func zcashCashAddress(key *hd.ExtendedKey, params *chaincfg.Params) (btcutil.Address, error) { +func zcashAddress(key *hd.ExtendedKey, params *chaincfg.Params) (btcutil.Address, error) { addr, err := key.Address(params) if err != nil { return nil, err @@ -113,8 +124,11 @@ func (w *ZCashWallet) CurrencyCode() string { } } -func (w *ZCashWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btcutil.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *ZCashWallet) IsDust(amount big.Int) bool { + if !amount.IsInt64() || amount.Cmp(big.NewInt(0)) <= 0 { + return false + } + return txrules.IsDustAmount(btcutil.Amount(amount.Int64()), 25, txrules.DefaultRelayFeePerKb) } func (w *ZCashWallet) MasterPrivateKey() *hd.ExtendedKey { @@ -145,17 +159,30 @@ func (w *ZCashWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey b } func (w *ZCashWallet) CurrentAddress(purpose wi.KeyPurpose) btcutil.Address { - key, _ := w.km.GetCurrentKey(purpose) - addr, _ := zcashCashAddress(key, w.params) - return btcutil.Address(addr) + key, err := w.km.GetCurrentKey(purpose) + if err != nil { + w.log.Errorf("Error generating current key: %s", err) + } + addr, err := w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } + return addr } func (w *ZCashWallet) NewAddress(purpose wi.KeyPurpose) btcutil.Address { - i, _ := w.db.Keys().GetUnused(purpose) - key, _ := w.km.GenerateChildKey(purpose, uint32(i[1])) - addr, _ := zcashCashAddress(key, w.params) - w.db.Keys().MarkKeyAsUsed(addr.ScriptAddress()) - return btcutil.Address(addr) + key, err := w.km.GetNextUnused(purpose) + if err != nil { + w.log.Errorf("Error generating next unused key: %s", err) + } + addr, err := w.km.KeyToAddress(key) + if err != nil { + w.log.Errorf("Error converting key to address: %s", err) + } + if err := w.db.Keys().MarkKeyAsUsed(addr.ScriptAddress()); err != nil { + w.log.Errorf("Error marking key as used: %s", err) + } + return addr } func (w *ZCashWallet) DecodeAddress(addr string) (btcutil.Address, error) { @@ -182,10 +209,21 @@ func (w *ZCashWallet) HasKey(addr btcutil.Address) bool { return true } -func (w *ZCashWallet) Balance() (confirmed, unconfirmed int64) { +func (w *ZCashWallet) Balance() (wi.CurrencyValue, wi.CurrencyValue) { utxos, _ := w.db.Utxos().GetAll() txns, _ := w.db.Txns().GetAll(false) - return util.CalcBalance(utxos, txns) + + // Zcash transactions have additional data embedded in them + // that is not expected by the BtcDecode deserialize function. + // We strip off the extra data here so the derserialize function + // does not error. This will have no affect on the balance calculation + // as the metadata is not used in the calculation. + for i, tx := range txns { + txns[i].Bytes = trimTxForDeserialization(tx.Bytes) + } + c, u := util.CalcBalance(utxos, txns) + return wi.CurrencyValue{Value: *big.NewInt(c), Currency: ZcashCurrencyDefinition}, + wi.CurrencyValue{Value: *big.NewInt(u), Currency: ZcashCurrencyDefinition} } func (w *ZCashWallet) Transactions() ([]wi.Txn, error) { @@ -224,6 +262,28 @@ func (w *ZCashWallet) Transactions() ([]wi.Txn, error) { func (w *ZCashWallet) GetTransaction(txid chainhash.Hash) (wi.Txn, error) { txn, err := w.db.Txns().Get(txid) + if err == nil { + tx := wire.NewMsgTx(1) + rbuf := bytes.NewReader(trimTxForDeserialization(txn.Bytes)) + err := tx.BtcDecode(rbuf, wire.ProtocolVersion, wire.WitnessEncoding) + if err != nil { + return txn, err + } + outs := []wi.TransactionOutput{} + for i, out := range tx.TxOut { + addr, err := zaddr.ExtractPkScriptAddrs(out.PkScript, w.params) + if err != nil { + w.log.Errorf("error extracting address from txn pkscript: %v\n", err) + } + tout := wi.TransactionOutput{ + Address: addr, + Value: *big.NewInt(out.Value), + Index: uint32(i), + } + outs = append(outs, tout) + } + txn.Outputs = outs + } return txn, err } @@ -231,11 +291,11 @@ func (w *ZCashWallet) ChainTip() (uint32, chainhash.Hash) { return w.ws.ChainTip() } -func (w *ZCashWallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { - return w.fp.GetFeePerByte(feeLevel) +func (w *ZCashWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + return *big.NewInt(int64(w.fp.GetFeePerByte(feeLevel))) } -func (w *ZCashWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *ZCashWallet) Spend(amount big.Int, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -246,7 +306,7 @@ func (w *ZCashWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeL return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -264,48 +324,58 @@ func (w *ZCashWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { return w.bumpFee(txid) } -func (w *ZCashWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte uint64) uint64 { +func (w *ZCashWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := zaddr.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Int64()) + return *big.NewInt(int64(fee)) } -func (w *ZCashWallet) EstimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { - return w.estimateSpendFee(amount, feeLevel) +func (w *ZCashWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + val, err := w.estimateSpendFee(amount.Int64(), feeLevel) + return *big.NewInt(int64(val)), err } func (w *ZCashWallet) SweepAddress(ins []wi.TransactionInput, address *btcutil.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { return w.sweepAddress(ins, address, key, redeemScript, feeLevel) } -func (w *ZCashWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { - return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte) +func (w *ZCashWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte.Uint64()) } -func (w *ZCashWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte, broadcast) +func (w *ZCashWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte.Uint64(), broadcast) } func (w *ZCashWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btcutil.Address, redeemScript []byte, err error) { return w.generateMultisigScript(keys, threshold, timeout, timeoutKey) } -func (w *ZCashWallet) AddWatchedAddress(addr btcutil.Address) error { - script, err := w.AddressToScript(addr) - if err != nil { - return err +func (w *ZCashWallet) AddWatchedAddresses(addrs ...btcutil.Address) error { + + var watchedScripts [][]byte + for _, addr := range addrs { + if !w.HasKey(addr) { + script, err := w.AddressToScript(addr) + if err != nil { + return err + } + watchedScripts = append(watchedScripts, script) + } } - err = w.db.WatchedScripts().Put(script) + + err := w.db.WatchedScripts().PutAll(watchedScripts) if err != nil { return err } - w.client.ListenAddress(addr) + + w.client.ListenAddresses(addrs...) return nil } @@ -318,7 +388,7 @@ func (w *ZCashWallet) AddWatchedScript(script []byte) error { if err != nil { return err } - w.client.ListenAddress(addr) + w.client.ListenAddresses(addr) return nil } @@ -355,12 +425,12 @@ func (w *ZCashWallet) DumpTables(wr io.Writer) { fmt.Fprintln(wr, "Transactions-----") txns, _ := w.db.Txns().GetAll(true) for _, tx := range txns { - fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), int(tx.Value), tx.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %s, WatchOnly: %t\n", tx.Txid, int(tx.Height), tx.Value, tx.WatchOnly) } fmt.Fprintln(wr, "\nUtxos-----") utxos, _ := w.db.Utxos().GetAll() for _, u := range utxos { - fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), int(u.Value), u.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %s, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), u.Value, u.WatchOnly) } } @@ -394,6 +464,7 @@ func (w *ZCashWallet) Broadcast(tx *wire.MsgTx) (string, error) { if err != nil { return "", err } + val, _ := strconv.ParseInt(u.Value, 10, 64) input := model.Input{ Txid: in.PreviousOutPoint.Hash.String(), Vout: int(in.PreviousOutPoint.Index), @@ -403,8 +474,8 @@ func (w *ZCashWallet) Broadcast(tx *wire.MsgTx) (string, error) { Sequence: uint32(in.Sequence), N: n, Addr: addr.String(), - Satoshis: u.Value, - Value: float64(u.Value) / util.SatoshisPerCoin(wi.Zcash), + Satoshis: val, + Value: float64(val) / util.SatoshisPerCoin(wi.Zcash), } cTxn.Inputs = append(cTxn.Inputs, input) } @@ -432,3 +503,7 @@ func (w *ZCashWallet) Broadcast(tx *wire.MsgTx) (string, error) { w.ws.ProcessIncomingTransaction(cTxn) return cTxn.Txid, nil } + +func trimTxForDeserialization(txBytes []byte) []byte { + return txBytes[4 : len(txBytes)-15] +} \ No newline at end of file diff --git a/vendor/github.com/phoreproject/spvwallet/keys.go b/vendor/github.com/phoreproject/spvwallet/keys.go deleted file mode 100644 index 962c05a7d8..0000000000 --- a/vendor/github.com/phoreproject/spvwallet/keys.go +++ /dev/null @@ -1,174 +0,0 @@ -package spvwallet - -import ( - "github.com/btcsuite/goleveldb/leveldb/errors" - "github.com/phoreproject/btcd/chaincfg" - hd "github.com/phoreproject/btcutil/hdkeychain" - "github.com/phoreproject/wallet-interface" -) - -const LOOKAHEADWINDOW = 100 - -type KeyManager struct { - datastore wallet.Keys - params *chaincfg.Params - - internalKey *hd.ExtendedKey - externalKey *hd.ExtendedKey -} - -func NewKeyManager(db wallet.Keys, params *chaincfg.Params, masterPrivKey *hd.ExtendedKey, coinType wallet.CoinType) (*KeyManager, error) { - internal, external, err := Bip44Derivation(masterPrivKey, coinType) - if err != nil { - return nil, err - } - km := &KeyManager{ - datastore: db, - params: params, - internalKey: internal, - externalKey: external, - } - if err := km.lookahead(); err != nil { - return nil, err - } - return km, nil -} - -// m / purpose' / coin_type' / account' / change / address_index -func Bip44Derivation(masterPrivKey *hd.ExtendedKey, coinType wallet.CoinType) (internal, external *hd.ExtendedKey, err error) { - // Purpose = bip44 - fourtyFour, err := masterPrivKey.Child(hd.HardenedKeyStart + 44) - if err != nil { - return nil, nil, err - } - // Cointype - bitcoin, err := fourtyFour.Child(hd.HardenedKeyStart + uint32(coinType)) - if err != nil { - return nil, nil, err - } - // Account = 0 - account, err := bitcoin.Child(hd.HardenedKeyStart + 0) - if err != nil { - return nil, nil, err - } - // Change(0) = external - external, err = account.Child(0) - if err != nil { - return nil, nil, err - } - // Change(1) = internal - internal, err = account.Child(1) - if err != nil { - return nil, nil, err - } - return internal, external, nil -} - -func (km *KeyManager) GetCurrentKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, error) { - i, err := km.datastore.GetUnused(purpose) - if err != nil { - return nil, err - } - if len(i) == 0 { - return nil, errors.New("No unused keys in database") - } - return km.GenerateChildKey(purpose, uint32(i[0])) -} - -func (km *KeyManager) GetFreshKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, error) { - index, _, err := km.datastore.GetLastKeyIndex(purpose) - var childKey *hd.ExtendedKey - if err != nil { - index = 0 - } else { - index += 1 - } - for { - // There is a small possibility bip32 keys can be invalid. The procedure in such cases - // is to discard the key and derive the next one. This loop will continue until a valid key - // is derived. - childKey, err = km.GenerateChildKey(purpose, uint32(index)) - if err == nil { - break - } - index += 1 - } - addr, err := childKey.Address(km.params) - if err != nil { - return nil, err - } - p := wallet.KeyPath{wallet.KeyPurpose(purpose), index} - err = km.datastore.Put(addr.ScriptAddress(), p) - if err != nil { - return nil, err - } - return childKey, nil -} - -func (km *KeyManager) GetKeys() []*hd.ExtendedKey { - var keys []*hd.ExtendedKey - keyPaths, err := km.datastore.GetAll() - if err != nil { - return keys - } - for _, path := range keyPaths { - k, err := km.GenerateChildKey(path.Purpose, uint32(path.Index)) - if err != nil { - continue - } - keys = append(keys, k) - } - return keys -} - -func (km *KeyManager) GetKeyForScript(scriptAddress []byte) (*hd.ExtendedKey, error) { - keyPath, err := km.datastore.GetPathForKey(scriptAddress) - if err != nil { - key, err := km.datastore.GetKey(scriptAddress) - if err != nil { - return nil, err - } - hdKey := hd.NewExtendedKey( - km.params.HDPrivateKeyID[:], - key.Serialize(), - make([]byte, 32), - []byte{0x00, 0x00, 0x00, 0x00}, - 0, - 0, - true) - return hdKey, nil - } - return km.GenerateChildKey(keyPath.Purpose, uint32(keyPath.Index)) -} - -// Mark the given key as used and extend the lookahead window -func (km *KeyManager) MarkKeyAsUsed(scriptAddress []byte) error { - if err := km.datastore.MarkKeyAsUsed(scriptAddress); err != nil { - return err - } - return km.lookahead() -} - -func (km *KeyManager) GenerateChildKey(purpose wallet.KeyPurpose, index uint32) (*hd.ExtendedKey, error) { - if purpose == wallet.EXTERNAL { - return km.externalKey.Child(index) - } else if purpose == wallet.INTERNAL { - return km.internalKey.Child(index) - } - return nil, errors.New("Unknown key purpose") -} - -func (km *KeyManager) lookahead() error { - lookaheadWindows := km.datastore.GetLookaheadWindows() - for purpose, size := range lookaheadWindows { - if size < LOOKAHEADWINDOW { - for i := 0; i < (LOOKAHEADWINDOW - size); i++ { - _, err := km.GetFreshKey(purpose) - if err != nil { - return err - } - } - } - } - return nil -} diff --git a/vendor/github.com/phoreproject/spvwallet/wallet.go b/vendor/github.com/phoreproject/spvwallet/wallet.go deleted file mode 100644 index 5fe4ca111d..0000000000 --- a/vendor/github.com/phoreproject/spvwallet/wallet.go +++ /dev/null @@ -1,435 +0,0 @@ -package spvwallet - -import ( - "errors" - "io" - "sync" - "time" - - "github.com/op/go-logging" - "github.com/phoreproject/btcd/btcec" - "github.com/phoreproject/btcd/chaincfg" - "github.com/phoreproject/btcd/chaincfg/chainhash" - "github.com/phoreproject/btcd/peer" - "github.com/phoreproject/btcd/txscript" - btc "github.com/phoreproject/btcutil" - hd "github.com/phoreproject/btcutil/hdkeychain" - "github.com/phoreproject/btcwallet/wallet/txrules" - "github.com/phoreproject/wallet-interface" - b39 "github.com/tyler-smith/go-bip39" -) - -type SPVWallet struct { - params *chaincfg.Params - - masterPrivateKey *hd.ExtendedKey - masterPublicKey *hd.ExtendedKey - - mnemonic string - - feeProvider *FeeProvider - - repoPath string - - blockchain *Blockchain - txstore *TxStore - peerManager *PeerManager - keyManager *KeyManager - wireService *WireService - - fPositives chan *peer.Peer - fpAccumulator map[int32]int32 - mutex *sync.RWMutex - - creationDate time.Time - - running bool - - config *PeerManagerConfig -} - -var log = logging.MustGetLogger("bitcoin") - -const WALLET_VERSION = "0.1.0" - -func NewSPVWallet(config *Config) (*SPVWallet, error) { - - log.SetBackend(logging.AddModuleLevel(config.Logger)) - - if config.Mnemonic == "" { - ent, err := b39.NewEntropy(256) - if err != nil { - return nil, err - } - mnemonic, err := b39.NewMnemonic(ent) - if err != nil { - return nil, err - } - config.Mnemonic = mnemonic - config.CreationDate = time.Now() - } - seed := b39.NewSeed(config.Mnemonic, "") - - mPrivKey, err := hd.NewMaster(seed, config.Params) - if err != nil { - return nil, err - } - mPubKey, err := mPrivKey.Neuter() - if err != nil { - return nil, err - } - w := &SPVWallet{ - repoPath: config.RepoPath, - masterPrivateKey: mPrivKey, - masterPublicKey: mPubKey, - mnemonic: config.Mnemonic, - params: config.Params, - creationDate: config.CreationDate, - feeProvider: NewFeeProvider( - config.MaxFee, - config.HighFee, - config.MediumFee, - config.LowFee, - config.FeeAPI.String(), - config.Proxy, - ), - fPositives: make(chan *peer.Peer), - fpAccumulator: make(map[int32]int32), - mutex: new(sync.RWMutex), - } - - w.keyManager, err = NewKeyManager(config.DB.Keys(), w.params, w.masterPrivateKey, wallet.Phore) - - w.txstore, err = NewTxStore(w.params, config.DB, w.keyManager) - if err != nil { - return nil, err - } - - w.blockchain, err = NewBlockchain(w.repoPath, w.creationDate, w.params) - if err != nil { - return nil, err - } - minSync := 5 - if config.TrustedPeer != nil { - minSync = 1 - } - wireConfig := &WireServiceConfig{ - txStore: w.txstore, - chain: w.blockchain, - walletCreationDate: w.creationDate, - minPeersForSync: minSync, - params: w.params, - } - - ws := NewWireService(wireConfig) - w.wireService = ws - - getNewestBlock := func() (*chainhash.Hash, int32, error) { - sh, err := w.blockchain.BestBlock() - if err != nil { - return nil, 0, err - } - h := sh.header.BlockHash() - return &h, int32(sh.height), nil - } - - w.config = &PeerManagerConfig{ - UserAgentName: config.UserAgent, - UserAgentVersion: WALLET_VERSION, - Params: w.params, - AddressCacheDir: config.RepoPath, - Proxy: config.Proxy, - GetNewestBlock: getNewestBlock, - MsgChan: ws.MsgChan(), - } - - if config.TrustedPeer != nil { - w.config.TrustedPeer = config.TrustedPeer - } - - w.peerManager, err = NewPeerManager(w.config) - if err != nil { - return nil, err - } - - return w, nil -} - -func (w *SPVWallet) Start() { - w.running = true - go w.wireService.Start() - go w.peerManager.Start() -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// API -// -////////////// - -func (w *SPVWallet) CurrencyCode() string { - if w.params.Name == chaincfg.MainNetParams.Name { - return "btc" - } else { - return "tbtc" - } -} - -func (w *SPVWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btc.Amount(amount), 25, txrules.DefaultRelayFeePerKb) -} - -func (w *SPVWallet) MasterPrivateKey() *hd.ExtendedKey { - return w.masterPrivateKey -} - -func (w *SPVWallet) MasterPublicKey() *hd.ExtendedKey { - return w.masterPublicKey -} - -func (w *SPVWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) { - parentFP := []byte{0x00, 0x00, 0x00, 0x00} - var id []byte - if isPrivateKey { - id = w.params.HDPrivateKeyID[:] - } else { - id = w.params.HDPublicKeyID[:] - } - hdKey := hd.NewExtendedKey( - id, - keyBytes, - chaincode, - parentFP, - 0, - 0, - isPrivateKey) - return hdKey.Child(0) -} - -func (w *SPVWallet) Mnemonic() string { - return w.mnemonic -} - -func (w *SPVWallet) ConnectedPeers() []*peer.Peer { - return w.peerManager.ConnectedPeers() -} - -func (w *SPVWallet) CurrentAddress(purpose wallet.KeyPurpose) btc.Address { - key, _ := w.keyManager.GetCurrentKey(purpose) - addr, _ := key.Address(w.params) - return btc.Address(addr) -} - -func (w *SPVWallet) NewAddress(purpose wallet.KeyPurpose) btc.Address { - i, _ := w.txstore.Keys().GetUnused(purpose) - key, _ := w.keyManager.GenerateChildKey(purpose, uint32(i[1])) - addr, _ := key.Address(w.params) - w.txstore.Keys().MarkKeyAsUsed(addr.ScriptAddress()) - w.txstore.PopulateAdrs() - return btc.Address(addr) -} - -func (w *SPVWallet) DecodeAddress(addr string) (btc.Address, error) { - return btc.DecodeAddress(addr, w.params) -} - -func (w *SPVWallet) ScriptToAddress(script []byte) (btc.Address, error) { - return scriptToAddress(script, w.params) -} - -func scriptToAddress(script []byte, params *chaincfg.Params) (btc.Address, error) { - _, addrs, _, err := txscript.ExtractPkScriptAddrs(script, params) - if err != nil { - return &btc.AddressPubKeyHash{}, err - } - if len(addrs) == 0 { - return &btc.AddressPubKeyHash{}, errors.New("unknown script") - } - return addrs[0], nil -} - -func (w *SPVWallet) AddressToScript(addr btc.Address) ([]byte, error) { - return txscript.PayToAddrScript(addr) -} - -func (w *SPVWallet) HasKey(addr btc.Address) bool { - _, err := w.keyManager.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - return false - } - return true -} - -func (w *SPVWallet) GetKey(addr btc.Address) (*btcec.PrivateKey, error) { - key, err := w.keyManager.GetKeyForScript(addr.ScriptAddress()) - if err != nil { - return nil, err - } - return key.ECPrivKey() -} - -func (w *SPVWallet) ListAddresses() []btc.Address { - keys := w.keyManager.GetKeys() - addrs := []btc.Address{} - for _, k := range keys { - addr, err := k.Address(w.params) - if err != nil { - continue - } - addrs = append(addrs, addr) - } - return addrs -} - -func (w *SPVWallet) ListKeys() []btcec.PrivateKey { - keys := w.keyManager.GetKeys() - list := []btcec.PrivateKey{} - for _, k := range keys { - priv, err := k.ECPrivKey() - if err != nil { - continue - } - list = append(list, *priv) - } - return list -} - -func (w *SPVWallet) Balance() (confirmed, unconfirmed int64) { - utxos, _ := w.txstore.Utxos().GetAll() - stxos, _ := w.txstore.Stxos().GetAll() - for _, utxo := range utxos { - if !utxo.WatchOnly { - if utxo.AtHeight > 0 { - confirmed += utxo.Value - } else { - if w.checkIfStxoIsConfirmed(utxo, stxos) { - confirmed += utxo.Value - } else { - unconfirmed += utxo.Value - } - } - } - } - return confirmed, unconfirmed -} - -func (w *SPVWallet) Transactions() ([]wallet.Txn, error) { - height, _ := w.ChainTip() - txns, err := w.txstore.Txns().GetAll(false) - if err != nil { - return txns, err - } - for i, tx := range txns { - var confirmations int32 - var status wallet.StatusCode - confs := int32(height) - tx.Height + 1 - if tx.Height <= 0 { - confs = tx.Height - } - switch { - case confs < 0: - status = wallet.StatusDead - case confs == 0 && time.Since(tx.Timestamp) <= time.Hour*6: - status = wallet.StatusUnconfirmed - case confs == 0 && time.Since(tx.Timestamp) > time.Hour*6: - status = wallet.StatusDead - case confs > 0 && confs < 6: - status = wallet.StatusPending - confirmations = confs - case confs > 5: - status = wallet.StatusConfirmed - confirmations = confs - } - tx.Confirmations = int64(confirmations) - tx.Status = status - txns[i] = tx - } - return txns, nil -} - -func (w *SPVWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) { - txn, err := w.txstore.Txns().Get(txid) - return txn, err -} - -func (w *SPVWallet) GetConfirmations(txid chainhash.Hash) (uint32, uint32, error) { - txn, err := w.txstore.Txns().Get(txid) - if err != nil { - return 0, 0, err - } - if txn.Height == 0 { - return 0, 0, nil - } - chainTip, _ := w.ChainTip() - return chainTip - uint32(txn.Height) + 1, uint32(txn.Height), nil -} - -func (w *SPVWallet) checkIfStxoIsConfirmed(utxo wallet.Utxo, stxos []wallet.Stxo) bool { - for _, stxo := range stxos { - if !stxo.Utxo.WatchOnly { - if stxo.SpendTxid.IsEqual(&utxo.Op.Hash) { - if stxo.SpendHeight > 0 { - return true - } else { - return w.checkIfStxoIsConfirmed(stxo.Utxo, stxos) - } - } else if stxo.Utxo.IsEqual(&utxo) { - if stxo.Utxo.AtHeight > 0 { - return true - } else { - return false - } - } - } - } - return false -} - -func (w *SPVWallet) Params() *chaincfg.Params { - return w.params -} - -func (w *SPVWallet) AddTransactionListener(callback func(wallet.TransactionCallback)) { - w.txstore.listeners = append(w.txstore.listeners, callback) -} - -func (w *SPVWallet) ChainTip() (uint32, chainhash.Hash) { - var ch chainhash.Hash - sh, err := w.blockchain.db.GetBestHeader() - if err != nil { - return 0, ch - } - return sh.height, sh.header.BlockHash() -} - -func (w *SPVWallet) AddWatchedAddress(addr btc.Address) error { - script, err := w.AddressToScript(addr) - if err != nil { - return err - } - err = w.txstore.WatchedScripts().Put(script) - w.txstore.PopulateAdrs() - - w.wireService.MsgChan() <- updateFiltersMsg{} - return err -} - -func (w *SPVWallet) DumpHeaders(writer io.Writer) { - w.blockchain.db.Print(writer) -} - -func (w *SPVWallet) Close() { - if w.running { - log.Info("Disconnecting from peers and shutting down") - w.peerManager.Stop() - w.blockchain.Close() - w.wireService.Stop() - w.running = false - } -} - -func (w *SPVWallet) ReSyncBlockchain(fromDate time.Time) { - w.blockchain.Rollback(fromDate) - w.txstore.PopulateAdrs() - w.wireService.Resync() -} diff --git a/vendor/github.com/phoreproject/wallet-interface/datastore.go b/vendor/github.com/phoreproject/wallet-interface/datastore.go deleted file mode 100644 index 132e03d941..0000000000 --- a/vendor/github.com/phoreproject/wallet-interface/datastore.go +++ /dev/null @@ -1,317 +0,0 @@ -package wallet - -import ( - "bytes" - "github.com/phoreproject/btcd/btcec" - "github.com/phoreproject/btcd/chaincfg/chainhash" - "github.com/phoreproject/btcd/wire" - "time" -) - -type Coin interface { - String() string - CurrencyCode() string -} - -type CoinType uint32 - -const ( - Bitcoin CoinType = 0 - Litecoin = 1 - Zcash = 133 - BitcoinCash = 145 - Ethereum = 60 - Phore = 444 - - TestnetBitcoin = 1000000 - TestnetLitecoin = 1000001 - TestnetZcash = 1000133 - TestnetBitcoinCash = 1000145 - TestnetEthereum = 1000060 - TestnetPhore = 1000444 -) - -func (c *CoinType) String() string { - switch *c { - case Bitcoin: - return "Bitcoin" - case BitcoinCash: - return "Bitcoin Cash" - case Zcash: - return "Zcash" - case Litecoin: - return "Litecoin" - case Ethereum: - return "Ethereum" - case Phore: - return "Phore" - case TestnetBitcoin: - return "Testnet Bitcoin" - case TestnetBitcoinCash: - return "Testnet Bitcoin Cash" - case TestnetZcash: - return "Testnet Zcash" - case TestnetLitecoin: - return "Testnet Litecoin" - case TestnetEthereum: - return "Testnet Ethereum" - case TestnetPhore: - return "Testnet Phore" - default: - return "" - } -} - -func (c *CoinType) CurrencyCode() string { - switch *c { - case Bitcoin: - return "BTC" - case BitcoinCash: - return "BCH" - case Zcash: - return "ZEC" - case Litecoin: - return "LTC" - case Ethereum: - return "ETH" - case Phore: - return "PHR" - case TestnetBitcoin: - return "TBTC" - case TestnetBitcoinCash: - return "TBCH" - case TestnetZcash: - return "TZEC" - case TestnetLitecoin: - return "TLTC" - case TestnetEthereum: - return "TETH" - case TestnetPhore: - return "TPHR" - default: - return "" - } -} - -type Datastore interface { - Utxos() Utxos - Stxos() Stxos - Txns() Txns - Keys() Keys - WatchedScripts() WatchedScripts -} - -type Utxos interface { - // Put a utxo to the database - Put(utxo Utxo) error - - // Fetch all utxos from the db - GetAll() ([]Utxo, error) - - // Make a utxo unspendable - SetWatchOnly(utxo Utxo) error - - // Delete a utxo from the db - Delete(utxo Utxo) error -} - -type Stxos interface { - // Put a stxo to the database - Put(stxo Stxo) error - - // Fetch all stxos from the db - GetAll() ([]Stxo, error) - - // Delete a stxo from the db - Delete(stxo Stxo) error -} - -type Txns interface { - // Put a new transaction to the database - Put(raw []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error - - // Fetch a tx and it's metadata given a hash - Get(txid chainhash.Hash) (Txn, error) - - // Fetch all transactions from the db - GetAll(includeWatchOnly bool) ([]Txn, error) - - // Update the height of a transaction - UpdateHeight(txid chainhash.Hash, height int, timestamp time.Time) error - - // Delete a transactions from the db - Delete(txid *chainhash.Hash) error -} - -// Keys provides a database interface for the wallet to save key material, track -// used keys, and manage the look ahead window. -type Keys interface { - // Put a bip32 key to the database - Put(hash160 []byte, keyPath KeyPath) error - - // Import a loose private key not part of the keychain - ImportKey(scriptAddress []byte, key *btcec.PrivateKey) error - - // Mark the script as used - MarkKeyAsUsed(scriptAddress []byte) error - - // Fetch the last index for the given key purpose - // The bool should state whether the key has been used or not - GetLastKeyIndex(purpose KeyPurpose) (int, bool, error) - - // Returns the first unused path for the given purpose - GetPathForKey(scriptAddress []byte) (KeyPath, error) - - // Returns an imported private key given a script address - GetKey(scriptAddress []byte) (*btcec.PrivateKey, error) - - // Returns all imported keys - GetImported() ([]*btcec.PrivateKey, error) - - // Get a list of unused key indexes for the given purpose - GetUnused(purpose KeyPurpose) ([]int, error) - - // Fetch all key paths - GetAll() ([]KeyPath, error) - - // Get the number of unused keys following the last used key - // for each key purpose. - GetLookaheadWindows() map[KeyPurpose]int -} - -type WatchedScripts interface { - // Add a script to watch - Put(scriptPubKey []byte) error - - // Return all watched scripts - GetAll() ([][]byte, error) - - // Delete a watched script - Delete(scriptPubKey []byte) error -} - -type Utxo struct { - // Previous txid and output index - Op wire.OutPoint - - // Block height where this tx was confirmed, 0 for unconfirmed - AtHeight int32 - - // The higher the better - Value int64 - - // Output script - ScriptPubkey []byte - - // If true this utxo will not be selected for spending. The primary - // purpose is track multisig UTXOs which must have separate handling - // to spend. - WatchOnly bool -} - -func (utxo *Utxo) IsEqual(alt *Utxo) bool { - if alt == nil { - return utxo == nil - } - - if !utxo.Op.Hash.IsEqual(&alt.Op.Hash) { - return false - } - - if utxo.Op.Index != alt.Op.Index { - return false - } - - if utxo.AtHeight != alt.AtHeight { - return false - } - - if utxo.Value != alt.Value { - return false - } - - if bytes.Compare(utxo.ScriptPubkey, alt.ScriptPubkey) != 0 { - return false - } - - return true -} - -type Stxo struct { - // When it used to be a UTXO - Utxo Utxo - - // The height at which it met its demise - SpendHeight int32 - - // The tx that consumed it - SpendTxid chainhash.Hash -} - -func (stxo *Stxo) IsEqual(alt *Stxo) bool { - if alt == nil { - return stxo == nil - } - - if !stxo.Utxo.IsEqual(&alt.Utxo) { - return false - } - - if stxo.SpendHeight != alt.SpendHeight { - return false - } - - if !stxo.SpendTxid.IsEqual(&alt.SpendTxid) { - return false - } - - return true -} - -type Txn struct { - // Transaction ID - Txid string - - // The value relevant to the wallet - Value int64 - - // The height at which it was mined - Height int32 - - // The time the transaction was first seen - Timestamp time.Time - - // This transaction only involves a watch only address - WatchOnly bool - - // The number of confirmations on a transaction. This does not need to be saved in - // the database but should be calculated when the Transactions() method is called. - Confirmations int64 - - // The state of the transaction (confirmed, unconfirmed, dead, etc). Implementations - // have some flexibility in describing their transactions. Like confirmations, this - // is best calculated when the Transactions() method is called. - Status StatusCode - - // If the Status is Error the ErrorMessage should describe the problem - ErrorMessage string - - // Raw transaction bytes - Bytes []byte -} - -type StatusCode string - -const ( - StatusUnconfirmed StatusCode = "UNCONFIRMED" - StatusPending = "PENDING" - StatusConfirmed = "CONFIRMED" - StatusStuck = "STUCK" - StatusDead = "DEAD" - StatusError = "ERROR" -) - -type KeyPath struct { - Purpose KeyPurpose - Index int -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/doc.go b/vendor/golang.org/x/crypto/sha3/doc.go similarity index 96% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/doc.go rename to vendor/golang.org/x/crypto/sha3/doc.go index 3dab530f86..c2fef30aff 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/doc.go +++ b/vendor/golang.org/x/crypto/sha3/doc.go @@ -43,7 +43,7 @@ // is then "full" and the permutation is applied to "empty" it. This process is // repeated until all the input has been "absorbed". The input is then padded. // The digest is "squeezed" from the sponge in the same way, except that output -// output is copied out instead of input being XORed in. +// is copied out instead of input being XORed in. // // A sponge is parameterized by its generic security strength, which is equal // to half its capacity; capacity + rate is equal to the permutation's width. @@ -63,4 +63,4 @@ // They produce output of the same length, with the same security strengths // against all attacks. This means, in particular, that SHA3-256 only has // 128-bit collision resistance, because its output length is 32 bytes. -package sha3 +package sha3 // import "golang.org/x/crypto/sha3" diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/hashes.go b/vendor/golang.org/x/crypto/sha3/hashes.go similarity index 58% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/hashes.go rename to vendor/golang.org/x/crypto/sha3/hashes.go index fa0d7b4362..0d8043fd2a 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/hashes.go +++ b/vendor/golang.org/x/crypto/sha3/hashes.go @@ -12,31 +12,57 @@ import ( "hash" ) -// NewKeccak256 creates a new Keccak-256 hash. -func NewKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } - -// NewKeccak512 creates a new Keccak-512 hash. -func NewKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } - // New224 creates a new SHA3-224 hash. // Its generic security strength is 224 bits against preimage attacks, // and 112 bits against collision attacks. -func New224() hash.Hash { return &state{rate: 144, outputLen: 28, dsbyte: 0x06} } +func New224() hash.Hash { + if h := new224Asm(); h != nil { + return h + } + return &state{rate: 144, outputLen: 28, dsbyte: 0x06} +} // New256 creates a new SHA3-256 hash. // Its generic security strength is 256 bits against preimage attacks, // and 128 bits against collision attacks. -func New256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x06} } +func New256() hash.Hash { + if h := new256Asm(); h != nil { + return h + } + return &state{rate: 136, outputLen: 32, dsbyte: 0x06} +} // New384 creates a new SHA3-384 hash. // Its generic security strength is 384 bits against preimage attacks, // and 192 bits against collision attacks. -func New384() hash.Hash { return &state{rate: 104, outputLen: 48, dsbyte: 0x06} } +func New384() hash.Hash { + if h := new384Asm(); h != nil { + return h + } + return &state{rate: 104, outputLen: 48, dsbyte: 0x06} +} // New512 creates a new SHA3-512 hash. // Its generic security strength is 512 bits against preimage attacks, // and 256 bits against collision attacks. -func New512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x06} } +func New512() hash.Hash { + if h := new512Asm(); h != nil { + return h + } + return &state{rate: 72, outputLen: 64, dsbyte: 0x06} +} + +// NewLegacyKeccak256 creates a new Keccak-256 hash. +// +// Only use this function if you require compatibility with an existing cryptosystem +// that uses non-standard padding. All other users should use New256 instead. +func NewLegacyKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } + +// NewLegacyKeccak512 creates a new Keccak-512 hash. +// +// Only use this function if you require compatibility with an existing cryptosystem +// that uses non-standard padding. All other users should use New512 instead. +func NewLegacyKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } // Sum224 returns the SHA3-224 digest of the data. func Sum224(data []byte) (digest [28]byte) { diff --git a/vendor/golang.org/x/crypto/sha3/hashes_generic.go b/vendor/golang.org/x/crypto/sha3/hashes_generic.go new file mode 100644 index 0000000000..c4ff3f6e66 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/hashes_generic.go @@ -0,0 +1,27 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build gccgo appengine !s390x + +package sha3 + +import ( + "hash" +) + +// new224Asm returns an assembly implementation of SHA3-224 if available, +// otherwise it returns nil. +func new224Asm() hash.Hash { return nil } + +// new256Asm returns an assembly implementation of SHA3-256 if available, +// otherwise it returns nil. +func new256Asm() hash.Hash { return nil } + +// new384Asm returns an assembly implementation of SHA3-384 if available, +// otherwise it returns nil. +func new384Asm() hash.Hash { return nil } + +// new512Asm returns an assembly implementation of SHA3-512 if available, +// otherwise it returns nil. +func new512Asm() hash.Hash { return nil } diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go b/vendor/golang.org/x/crypto/sha3/keccakf.go similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go rename to vendor/golang.org/x/crypto/sha3/keccakf.go diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go similarity index 88% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go rename to vendor/golang.org/x/crypto/sha3/keccakf_amd64.go index de035c550f..7886795850 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go +++ b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go @@ -10,4 +10,4 @@ package sha3 //go:noescape -func keccakF1600(state *[25]uint64) +func keccakF1600(a *[25]uint64) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.s b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.s rename to vendor/golang.org/x/crypto/sha3/keccakf_amd64.s diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/register.go b/vendor/golang.org/x/crypto/sha3/register.go similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/register.go rename to vendor/golang.org/x/crypto/sha3/register.go diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go b/vendor/golang.org/x/crypto/sha3/sha3.go similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go rename to vendor/golang.org/x/crypto/sha3/sha3.go diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go new file mode 100644 index 0000000000..f1fb79cc39 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go @@ -0,0 +1,289 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !gccgo,!appengine + +package sha3 + +// This file contains code for using the 'compute intermediate +// message digest' (KIMD) and 'compute last message digest' (KLMD) +// instructions to compute SHA-3 and SHAKE hashes on IBM Z. + +import ( + "hash" +) + +// codes represent 7-bit KIMD/KLMD function codes as defined in +// the Principles of Operation. +type code uint64 + +const ( + // function codes for KIMD/KLMD + sha3_224 code = 32 + sha3_256 = 33 + sha3_384 = 34 + sha3_512 = 35 + shake_128 = 36 + shake_256 = 37 + nopad = 0x100 +) + +// hasMSA6 reports whether the machine supports the SHA-3 and SHAKE function +// codes, as defined in message-security-assist extension 6. +func hasMSA6() bool + +// hasAsm caches the result of hasMSA6 (which might be expensive to call). +var hasAsm = hasMSA6() + +// kimd is a wrapper for the 'compute intermediate message digest' instruction. +// src must be a multiple of the rate for the given function code. +//go:noescape +func kimd(function code, chain *[200]byte, src []byte) + +// klmd is a wrapper for the 'compute last message digest' instruction. +// src padding is handled by the instruction. +//go:noescape +func klmd(function code, chain *[200]byte, dst, src []byte) + +type asmState struct { + a [200]byte // 1600 bit state + buf []byte // care must be taken to ensure cap(buf) is a multiple of rate + rate int // equivalent to block size + storage [3072]byte // underlying storage for buf + outputLen int // output length if fixed, 0 if not + function code // KIMD/KLMD function code + state spongeDirection // whether the sponge is absorbing or squeezing +} + +func newAsmState(function code) *asmState { + var s asmState + s.function = function + switch function { + case sha3_224: + s.rate = 144 + s.outputLen = 28 + case sha3_256: + s.rate = 136 + s.outputLen = 32 + case sha3_384: + s.rate = 104 + s.outputLen = 48 + case sha3_512: + s.rate = 72 + s.outputLen = 64 + case shake_128: + s.rate = 168 + case shake_256: + s.rate = 136 + default: + panic("sha3: unrecognized function code") + } + + // limit s.buf size to a multiple of s.rate + s.resetBuf() + return &s +} + +func (s *asmState) clone() *asmState { + c := *s + c.buf = c.storage[:len(s.buf):cap(s.buf)] + return &c +} + +// copyIntoBuf copies b into buf. It will panic if there is not enough space to +// store all of b. +func (s *asmState) copyIntoBuf(b []byte) { + bufLen := len(s.buf) + s.buf = s.buf[:len(s.buf)+len(b)] + copy(s.buf[bufLen:], b) +} + +// resetBuf points buf at storage, sets the length to 0 and sets cap to be a +// multiple of the rate. +func (s *asmState) resetBuf() { + max := (cap(s.storage) / s.rate) * s.rate + s.buf = s.storage[:0:max] +} + +// Write (via the embedded io.Writer interface) adds more data to the running hash. +// It never returns an error. +func (s *asmState) Write(b []byte) (int, error) { + if s.state != spongeAbsorbing { + panic("sha3: write to sponge after read") + } + length := len(b) + for len(b) > 0 { + if len(s.buf) == 0 && len(b) >= cap(s.buf) { + // Hash the data directly and push any remaining bytes + // into the buffer. + remainder := len(s.buf) % s.rate + kimd(s.function, &s.a, b[:len(b)-remainder]) + if remainder != 0 { + s.copyIntoBuf(b[len(b)-remainder:]) + } + return length, nil + } + + if len(s.buf) == cap(s.buf) { + // flush the buffer + kimd(s.function, &s.a, s.buf) + s.buf = s.buf[:0] + } + + // copy as much as we can into the buffer + n := len(b) + if len(b) > cap(s.buf)-len(s.buf) { + n = cap(s.buf) - len(s.buf) + } + s.copyIntoBuf(b[:n]) + b = b[n:] + } + return length, nil +} + +// Read squeezes an arbitrary number of bytes from the sponge. +func (s *asmState) Read(out []byte) (n int, err error) { + n = len(out) + + // need to pad if we were absorbing + if s.state == spongeAbsorbing { + s.state = spongeSqueezing + + // write hash directly into out if possible + if len(out)%s.rate == 0 { + klmd(s.function, &s.a, out, s.buf) // len(out) may be 0 + s.buf = s.buf[:0] + return + } + + // write hash into buffer + max := cap(s.buf) + if max > len(out) { + max = (len(out)/s.rate)*s.rate + s.rate + } + klmd(s.function, &s.a, s.buf[:max], s.buf) + s.buf = s.buf[:max] + } + + for len(out) > 0 { + // flush the buffer + if len(s.buf) != 0 { + c := copy(out, s.buf) + out = out[c:] + s.buf = s.buf[c:] + continue + } + + // write hash directly into out if possible + if len(out)%s.rate == 0 { + klmd(s.function|nopad, &s.a, out, nil) + return + } + + // write hash into buffer + s.resetBuf() + if cap(s.buf) > len(out) { + s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate] + } + klmd(s.function|nopad, &s.a, s.buf, nil) + } + return +} + +// Sum appends the current hash to b and returns the resulting slice. +// It does not change the underlying hash state. +func (s *asmState) Sum(b []byte) []byte { + if s.outputLen == 0 { + panic("sha3: cannot call Sum on SHAKE functions") + } + + // Copy the state to preserve the original. + a := s.a + + // Hash the buffer. Note that we don't clear it because we + // aren't updating the state. + klmd(s.function, &a, nil, s.buf) + return append(b, a[:s.outputLen]...) +} + +// Reset resets the Hash to its initial state. +func (s *asmState) Reset() { + for i := range s.a { + s.a[i] = 0 + } + s.resetBuf() + s.state = spongeAbsorbing +} + +// Size returns the number of bytes Sum will return. +func (s *asmState) Size() int { + return s.outputLen +} + +// BlockSize returns the hash's underlying block size. +// The Write method must be able to accept any amount +// of data, but it may operate more efficiently if all writes +// are a multiple of the block size. +func (s *asmState) BlockSize() int { + return s.rate +} + +// Clone returns a copy of the ShakeHash in its current state. +func (s *asmState) Clone() ShakeHash { + return s.clone() +} + +// new224Asm returns an assembly implementation of SHA3-224 if available, +// otherwise it returns nil. +func new224Asm() hash.Hash { + if hasAsm { + return newAsmState(sha3_224) + } + return nil +} + +// new256Asm returns an assembly implementation of SHA3-256 if available, +// otherwise it returns nil. +func new256Asm() hash.Hash { + if hasAsm { + return newAsmState(sha3_256) + } + return nil +} + +// new384Asm returns an assembly implementation of SHA3-384 if available, +// otherwise it returns nil. +func new384Asm() hash.Hash { + if hasAsm { + return newAsmState(sha3_384) + } + return nil +} + +// new512Asm returns an assembly implementation of SHA3-512 if available, +// otherwise it returns nil. +func new512Asm() hash.Hash { + if hasAsm { + return newAsmState(sha3_512) + } + return nil +} + +// newShake128Asm returns an assembly implementation of SHAKE-128 if available, +// otherwise it returns nil. +func newShake128Asm() ShakeHash { + if hasAsm { + return newAsmState(shake_128) + } + return nil +} + +// newShake256Asm returns an assembly implementation of SHAKE-256 if available, +// otherwise it returns nil. +func newShake256Asm() ShakeHash { + if hasAsm { + return newAsmState(shake_256) + } + return nil +} diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.s b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s new file mode 100644 index 0000000000..20978fc713 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s @@ -0,0 +1,49 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !gccgo,!appengine + +#include "textflag.h" + +TEXT ·hasMSA6(SB), NOSPLIT, $16-1 + MOVD $0, R0 // KIMD-Query function code + MOVD $tmp-16(SP), R1 // parameter block + XC $16, (R1), (R1) // clear the parameter block + WORD $0xB93E0002 // KIMD --, -- + WORD $0x91FC1004 // TM 4(R1), 0xFC (test bits [32-37]) + BVS yes + +no: + MOVB $0, ret+0(FP) + RET + +yes: + MOVB $1, ret+0(FP) + RET + +// func kimd(function code, params *[200]byte, src []byte) +TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40 + MOVD function+0(FP), R0 + MOVD params+8(FP), R1 + LMG src+16(FP), R2, R3 // R2=base, R3=len + +continue: + WORD $0xB93E0002 // KIMD --, R2 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET + +// func klmd(function code, params *[200]byte, dst, src []byte) +TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64 + // TODO: SHAKE support + MOVD function+0(FP), R0 + MOVD params+8(FP), R1 + LMG dst+16(FP), R2, R3 // R2=base, R3=len + LMG src+40(FP), R4, R5 // R4=base, R5=len + +continue: + WORD $0xB93F0024 // KLMD R2, R4 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/shake.go b/vendor/golang.org/x/crypto/sha3/shake.go similarity index 83% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/shake.go rename to vendor/golang.org/x/crypto/sha3/shake.go index 841f9860f0..97c9b0624a 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/shake.go +++ b/vendor/golang.org/x/crypto/sha3/shake.go @@ -38,12 +38,22 @@ func (d *state) Clone() ShakeHash { // NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. // Its generic security strength is 128 bits against all attacks if at // least 32 bytes of its output are used. -func NewShake128() ShakeHash { return &state{rate: 168, dsbyte: 0x1f} } +func NewShake128() ShakeHash { + if h := newShake128Asm(); h != nil { + return h + } + return &state{rate: 168, dsbyte: 0x1f} +} -// NewShake256 creates a new SHAKE128 variable-output-length ShakeHash. +// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. // Its generic security strength is 256 bits against all attacks if // at least 64 bytes of its output are used. -func NewShake256() ShakeHash { return &state{rate: 136, dsbyte: 0x1f} } +func NewShake256() ShakeHash { + if h := newShake256Asm(); h != nil { + return h + } + return &state{rate: 136, dsbyte: 0x1f} +} // ShakeSum128 writes an arbitrary-length digest of data into hash. func ShakeSum128(hash, data []byte) { diff --git a/vendor/golang.org/x/crypto/sha3/shake_generic.go b/vendor/golang.org/x/crypto/sha3/shake_generic.go new file mode 100644 index 0000000000..73d0c90bf5 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/shake_generic.go @@ -0,0 +1,19 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build gccgo appengine !s390x + +package sha3 + +// newShake128Asm returns an assembly implementation of SHAKE-128 if available, +// otherwise it returns nil. +func newShake128Asm() ShakeHash { + return nil +} + +// newShake256Asm returns an assembly implementation of SHAKE-256 if available, +// otherwise it returns nil. +func newShake256Asm() ShakeHash { + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go b/vendor/golang.org/x/crypto/sha3/xor.go similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go rename to vendor/golang.org/x/crypto/sha3/xor.go diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_generic.go b/vendor/golang.org/x/crypto/sha3/xor_generic.go similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_generic.go rename to vendor/golang.org/x/crypto/sha3/xor_generic.go diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go rename to vendor/golang.org/x/crypto/sha3/xor_unaligned.go diff --git a/vendor/golang.org/x/image/AUTHORS b/vendor/golang.org/x/image/AUTHORS new file mode 100644 index 0000000000..15167cd746 --- /dev/null +++ b/vendor/golang.org/x/image/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/image/CONTRIBUTORS b/vendor/golang.org/x/image/CONTRIBUTORS new file mode 100644 index 0000000000..1c4577e968 --- /dev/null +++ b/vendor/golang.org/x/image/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/image/LICENSE b/vendor/golang.org/x/image/LICENSE new file mode 100644 index 0000000000..6a66aea5ea --- /dev/null +++ b/vendor/golang.org/x/image/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/PATENTS b/vendor/golang.org/x/image/PATENTS similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/crypto/sha3/PATENTS rename to vendor/golang.org/x/image/PATENTS diff --git a/vendor/golang.org/x/image/bmp/reader.go b/vendor/golang.org/x/image/bmp/reader.go new file mode 100644 index 0000000000..589b9a5777 --- /dev/null +++ b/vendor/golang.org/x/image/bmp/reader.go @@ -0,0 +1,213 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bmp implements a BMP image decoder and encoder. +// +// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html. +package bmp + +import ( + "errors" + "image" + "image/color" + "io" +) + +// ErrUnsupported means that the input BMP image uses a valid but unsupported +// feature. +var ErrUnsupported = errors.New("bmp: unsupported BMP image") + +func readUint16(b []byte) uint16 { + return uint16(b[0]) | uint16(b[1])<<8 +} + +func readUint32(b []byte) uint32 { + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +// decodePaletted reads an 8 bit-per-pixel BMP image from r. +// If topDown is false, the image rows will be read bottom-up. +func decodePaletted(r io.Reader, c image.Config, topDown bool) (image.Image, error) { + paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette)) + if c.Width == 0 || c.Height == 0 { + return paletted, nil + } + var tmp [4]byte + y0, y1, yDelta := c.Height-1, -1, -1 + if topDown { + y0, y1, yDelta = 0, c.Height, +1 + } + for y := y0; y != y1; y += yDelta { + p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width] + if _, err := io.ReadFull(r, p); err != nil { + return nil, err + } + // Each row is 4-byte aligned. + if c.Width%4 != 0 { + _, err := io.ReadFull(r, tmp[:4-c.Width%4]) + if err != nil { + return nil, err + } + } + } + return paletted, nil +} + +// decodeRGB reads a 24 bit-per-pixel BMP image from r. +// If topDown is false, the image rows will be read bottom-up. +func decodeRGB(r io.Reader, c image.Config, topDown bool) (image.Image, error) { + rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height)) + if c.Width == 0 || c.Height == 0 { + return rgba, nil + } + // There are 3 bytes per pixel, and each row is 4-byte aligned. + b := make([]byte, (3*c.Width+3)&^3) + y0, y1, yDelta := c.Height-1, -1, -1 + if topDown { + y0, y1, yDelta = 0, c.Height, +1 + } + for y := y0; y != y1; y += yDelta { + if _, err := io.ReadFull(r, b); err != nil { + return nil, err + } + p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4] + for i, j := 0, 0; i < len(p); i, j = i+4, j+3 { + // BMP images are stored in BGR order rather than RGB order. + p[i+0] = b[j+2] + p[i+1] = b[j+1] + p[i+2] = b[j+0] + p[i+3] = 0xFF + } + } + return rgba, nil +} + +// decodeNRGBA reads a 32 bit-per-pixel BMP image from r. +// If topDown is false, the image rows will be read bottom-up. +func decodeNRGBA(r io.Reader, c image.Config, topDown bool) (image.Image, error) { + rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height)) + if c.Width == 0 || c.Height == 0 { + return rgba, nil + } + y0, y1, yDelta := c.Height-1, -1, -1 + if topDown { + y0, y1, yDelta = 0, c.Height, +1 + } + for y := y0; y != y1; y += yDelta { + p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4] + if _, err := io.ReadFull(r, p); err != nil { + return nil, err + } + for i := 0; i < len(p); i += 4 { + // BMP images are stored in BGRA order rather than RGBA order. + p[i+0], p[i+2] = p[i+2], p[i+0] + } + } + return rgba, nil +} + +// Decode reads a BMP image from r and returns it as an image.Image. +// Limitation: The file must be 8, 24 or 32 bits per pixel. +func Decode(r io.Reader) (image.Image, error) { + c, bpp, topDown, err := decodeConfig(r) + if err != nil { + return nil, err + } + switch bpp { + case 8: + return decodePaletted(r, c, topDown) + case 24: + return decodeRGB(r, c, topDown) + case 32: + return decodeNRGBA(r, c, topDown) + } + panic("unreachable") +} + +// DecodeConfig returns the color model and dimensions of a BMP image without +// decoding the entire image. +// Limitation: The file must be 8, 24 or 32 bits per pixel. +func DecodeConfig(r io.Reader) (image.Config, error) { + config, _, _, err := decodeConfig(r) + return config, err +} + +func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, err error) { + // We only support those BMP images that are a BITMAPFILEHEADER + // immediately followed by a BITMAPINFOHEADER. + const ( + fileHeaderLen = 14 + infoHeaderLen = 40 + v4InfoHeaderLen = 108 + v5InfoHeaderLen = 124 + ) + var b [1024]byte + if _, err := io.ReadFull(r, b[:fileHeaderLen+4]); err != nil { + return image.Config{}, 0, false, err + } + if string(b[:2]) != "BM" { + return image.Config{}, 0, false, errors.New("bmp: invalid format") + } + offset := readUint32(b[10:14]) + infoLen := readUint32(b[14:18]) + if infoLen != infoHeaderLen && infoLen != v4InfoHeaderLen && infoLen != v5InfoHeaderLen { + return image.Config{}, 0, false, ErrUnsupported + } + if _, err := io.ReadFull(r, b[fileHeaderLen+4:fileHeaderLen+infoLen]); err != nil { + return image.Config{}, 0, false, err + } + width := int(int32(readUint32(b[18:22]))) + height := int(int32(readUint32(b[22:26]))) + if height < 0 { + height, topDown = -height, true + } + if width < 0 || height < 0 { + return image.Config{}, 0, false, ErrUnsupported + } + // We only support 1 plane and 8, 24 or 32 bits per pixel and no + // compression. + planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34]) + // if compression is set to BITFIELDS, but the bitmask is set to the default bitmask + // that would be used if compression was set to 0, we can continue as if compression was 0 + if compression == 3 && infoLen > infoHeaderLen && + readUint32(b[54:58]) == 0xff0000 && readUint32(b[58:62]) == 0xff00 && + readUint32(b[62:66]) == 0xff && readUint32(b[66:70]) == 0xff000000 { + compression = 0 + } + if planes != 1 || compression != 0 { + return image.Config{}, 0, false, ErrUnsupported + } + switch bpp { + case 8: + if offset != fileHeaderLen+infoLen+256*4 { + return image.Config{}, 0, false, ErrUnsupported + } + _, err = io.ReadFull(r, b[:256*4]) + if err != nil { + return image.Config{}, 0, false, err + } + pcm := make(color.Palette, 256) + for i := range pcm { + // BMP images are stored in BGR order rather than RGB order. + // Every 4th byte is padding. + pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF} + } + return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, nil + case 24: + if offset != fileHeaderLen+infoLen { + return image.Config{}, 0, false, ErrUnsupported + } + return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, nil + case 32: + if offset != fileHeaderLen+infoLen { + return image.Config{}, 0, false, ErrUnsupported + } + return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, nil + } + return image.Config{}, 0, false, ErrUnsupported +} + +func init() { + image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig) +} diff --git a/vendor/golang.org/x/image/bmp/writer.go b/vendor/golang.org/x/image/bmp/writer.go new file mode 100644 index 0000000000..f07b39dba1 --- /dev/null +++ b/vendor/golang.org/x/image/bmp/writer.go @@ -0,0 +1,262 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bmp + +import ( + "encoding/binary" + "errors" + "image" + "io" +) + +type header struct { + sigBM [2]byte + fileSize uint32 + resverved [2]uint16 + pixOffset uint32 + dibHeaderSize uint32 + width uint32 + height uint32 + colorPlane uint16 + bpp uint16 + compression uint32 + imageSize uint32 + xPixelsPerMeter uint32 + yPixelsPerMeter uint32 + colorUse uint32 + colorImportant uint32 +} + +func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error { + var padding []byte + if dx < step { + padding = make([]byte, step-dx) + } + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx + if _, err := w.Write(pix[min:max]); err != nil { + return err + } + if padding != nil { + if _, err := w.Write(padding); err != nil { + return err + } + } + } + return nil +} + +func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error { + buf := make([]byte, step) + if opaque { + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx*4 + off := 0 + for i := min; i < max; i += 4 { + buf[off+2] = pix[i+0] + buf[off+1] = pix[i+1] + buf[off+0] = pix[i+2] + off += 3 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + } else { + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx*4 + off := 0 + for i := min; i < max; i += 4 { + a := uint32(pix[i+3]) + if a == 0 { + buf[off+2] = 0 + buf[off+1] = 0 + buf[off+0] = 0 + buf[off+3] = 0 + off += 4 + continue + } else if a == 0xff { + buf[off+2] = pix[i+0] + buf[off+1] = pix[i+1] + buf[off+0] = pix[i+2] + buf[off+3] = 0xff + off += 4 + continue + } + buf[off+2] = uint8(((uint32(pix[i+0]) * 0xffff) / a) >> 8) + buf[off+1] = uint8(((uint32(pix[i+1]) * 0xffff) / a) >> 8) + buf[off+0] = uint8(((uint32(pix[i+2]) * 0xffff) / a) >> 8) + buf[off+3] = uint8(a) + off += 4 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + } + return nil +} + +func encodeNRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error { + buf := make([]byte, step) + if opaque { + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx*4 + off := 0 + for i := min; i < max; i += 4 { + buf[off+2] = pix[i+0] + buf[off+1] = pix[i+1] + buf[off+0] = pix[i+2] + off += 3 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + } else { + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx*4 + off := 0 + for i := min; i < max; i += 4 { + buf[off+2] = pix[i+0] + buf[off+1] = pix[i+1] + buf[off+0] = pix[i+2] + buf[off+3] = pix[i+3] + off += 4 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + } + return nil +} + +func encode(w io.Writer, m image.Image, step int) error { + b := m.Bounds() + buf := make([]byte, step) + for y := b.Max.Y - 1; y >= b.Min.Y; y-- { + off := 0 + for x := b.Min.X; x < b.Max.X; x++ { + r, g, b, _ := m.At(x, y).RGBA() + buf[off+2] = byte(r >> 8) + buf[off+1] = byte(g >> 8) + buf[off+0] = byte(b >> 8) + off += 3 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + return nil +} + +// Encode writes the image m to w in BMP format. +func Encode(w io.Writer, m image.Image) error { + d := m.Bounds().Size() + if d.X < 0 || d.Y < 0 { + return errors.New("bmp: negative bounds") + } + h := &header{ + sigBM: [2]byte{'B', 'M'}, + fileSize: 14 + 40, + pixOffset: 14 + 40, + dibHeaderSize: 40, + width: uint32(d.X), + height: uint32(d.Y), + colorPlane: 1, + } + + var step int + var palette []byte + var opaque bool + switch m := m.(type) { + case *image.Gray: + step = (d.X + 3) &^ 3 + palette = make([]byte, 1024) + for i := 0; i < 256; i++ { + palette[i*4+0] = uint8(i) + palette[i*4+1] = uint8(i) + palette[i*4+2] = uint8(i) + palette[i*4+3] = 0xFF + } + h.imageSize = uint32(d.Y * step) + h.fileSize += uint32(len(palette)) + h.imageSize + h.pixOffset += uint32(len(palette)) + h.bpp = 8 + + case *image.Paletted: + step = (d.X + 3) &^ 3 + palette = make([]byte, 1024) + for i := 0; i < len(m.Palette) && i < 256; i++ { + r, g, b, _ := m.Palette[i].RGBA() + palette[i*4+0] = uint8(b >> 8) + palette[i*4+1] = uint8(g >> 8) + palette[i*4+2] = uint8(r >> 8) + palette[i*4+3] = 0xFF + } + h.imageSize = uint32(d.Y * step) + h.fileSize += uint32(len(palette)) + h.imageSize + h.pixOffset += uint32(len(palette)) + h.bpp = 8 + case *image.RGBA: + opaque = m.Opaque() + if opaque { + step = (3*d.X + 3) &^ 3 + h.bpp = 24 + } else { + step = 4 * d.X + h.bpp = 32 + } + h.imageSize = uint32(d.Y * step) + h.fileSize += h.imageSize + case *image.NRGBA: + opaque = m.Opaque() + if opaque { + step = (3*d.X + 3) &^ 3 + h.bpp = 24 + } else { + step = 4 * d.X + h.bpp = 32 + } + h.imageSize = uint32(d.Y * step) + h.fileSize += h.imageSize + default: + step = (3*d.X + 3) &^ 3 + h.imageSize = uint32(d.Y * step) + h.fileSize += h.imageSize + h.bpp = 24 + } + + if err := binary.Write(w, binary.LittleEndian, h); err != nil { + return err + } + if palette != nil { + if err := binary.Write(w, binary.LittleEndian, palette); err != nil { + return err + } + } + + if d.X == 0 || d.Y == 0 { + return nil + } + + switch m := m.(type) { + case *image.Gray: + return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step) + case *image.Paletted: + return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step) + case *image.RGBA: + return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque) + case *image.NRGBA: + return encodeNRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque) + } + return encode(w, m, step) +} diff --git a/vendor/golang.org/x/image/tiff/buffer.go b/vendor/golang.org/x/image/tiff/buffer.go new file mode 100644 index 0000000000..d1801be48e --- /dev/null +++ b/vendor/golang.org/x/image/tiff/buffer.go @@ -0,0 +1,69 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tiff + +import "io" + +// buffer buffers an io.Reader to satisfy io.ReaderAt. +type buffer struct { + r io.Reader + buf []byte +} + +// fill reads data from b.r until the buffer contains at least end bytes. +func (b *buffer) fill(end int) error { + m := len(b.buf) + if end > m { + if end > cap(b.buf) { + newcap := 1024 + for newcap < end { + newcap *= 2 + } + newbuf := make([]byte, end, newcap) + copy(newbuf, b.buf) + b.buf = newbuf + } else { + b.buf = b.buf[:end] + } + if n, err := io.ReadFull(b.r, b.buf[m:end]); err != nil { + end = m + n + b.buf = b.buf[:end] + return err + } + } + return nil +} + +func (b *buffer) ReadAt(p []byte, off int64) (int, error) { + o := int(off) + end := o + len(p) + if int64(end) != off+int64(len(p)) { + return 0, io.ErrUnexpectedEOF + } + + err := b.fill(end) + return copy(p, b.buf[o:end]), err +} + +// Slice returns a slice of the underlying buffer. The slice contains +// n bytes starting at offset off. +func (b *buffer) Slice(off, n int) ([]byte, error) { + end := off + n + if err := b.fill(end); err != nil { + return nil, err + } + return b.buf[off:end], nil +} + +// newReaderAt converts an io.Reader into an io.ReaderAt. +func newReaderAt(r io.Reader) io.ReaderAt { + if ra, ok := r.(io.ReaderAt); ok { + return ra + } + return &buffer{ + r: r, + buf: make([]byte, 0, 1024), + } +} diff --git a/vendor/golang.org/x/image/tiff/compress.go b/vendor/golang.org/x/image/tiff/compress.go new file mode 100644 index 0000000000..3f176f00a9 --- /dev/null +++ b/vendor/golang.org/x/image/tiff/compress.go @@ -0,0 +1,58 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tiff + +import ( + "bufio" + "io" +) + +type byteReader interface { + io.Reader + io.ByteReader +} + +// unpackBits decodes the PackBits-compressed data in src and returns the +// uncompressed data. +// +// The PackBits compression format is described in section 9 (p. 42) +// of the TIFF spec. +func unpackBits(r io.Reader) ([]byte, error) { + buf := make([]byte, 128) + dst := make([]byte, 0, 1024) + br, ok := r.(byteReader) + if !ok { + br = bufio.NewReader(r) + } + + for { + b, err := br.ReadByte() + if err != nil { + if err == io.EOF { + return dst, nil + } + return nil, err + } + code := int(int8(b)) + switch { + case code >= 0: + n, err := io.ReadFull(br, buf[:code+1]) + if err != nil { + return nil, err + } + dst = append(dst, buf[:n]...) + case code == -128: + // No-op. + default: + if b, err = br.ReadByte(); err != nil { + return nil, err + } + for j := 0; j < 1-code; j++ { + buf[j] = b + } + dst = append(dst, buf[:1-code]...) + } + } +} diff --git a/vendor/golang.org/x/image/tiff/consts.go b/vendor/golang.org/x/image/tiff/consts.go new file mode 100644 index 0000000000..3c51a70bef --- /dev/null +++ b/vendor/golang.org/x/image/tiff/consts.go @@ -0,0 +1,133 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tiff + +// A tiff image file contains one or more images. The metadata +// of each image is contained in an Image File Directory (IFD), +// which contains entries of 12 bytes each and is described +// on page 14-16 of the specification. An IFD entry consists of +// +// - a tag, which describes the signification of the entry, +// - the data type and length of the entry, +// - the data itself or a pointer to it if it is more than 4 bytes. +// +// The presence of a length means that each IFD is effectively an array. + +const ( + leHeader = "II\x2A\x00" // Header for little-endian files. + beHeader = "MM\x00\x2A" // Header for big-endian files. + + ifdLen = 12 // Length of an IFD entry in bytes. +) + +// Data types (p. 14-16 of the spec). +const ( + dtByte = 1 + dtASCII = 2 + dtShort = 3 + dtLong = 4 + dtRational = 5 +) + +// The length of one instance of each data type in bytes. +var lengths = [...]uint32{0, 1, 1, 2, 4, 8} + +// Tags (see p. 28-41 of the spec). +const ( + tImageWidth = 256 + tImageLength = 257 + tBitsPerSample = 258 + tCompression = 259 + tPhotometricInterpretation = 262 + + tStripOffsets = 273 + tSamplesPerPixel = 277 + tRowsPerStrip = 278 + tStripByteCounts = 279 + + tTileWidth = 322 + tTileLength = 323 + tTileOffsets = 324 + tTileByteCounts = 325 + + tXResolution = 282 + tYResolution = 283 + tResolutionUnit = 296 + + tPredictor = 317 + tColorMap = 320 + tExtraSamples = 338 + tSampleFormat = 339 +) + +// Compression types (defined in various places in the spec and supplements). +const ( + cNone = 1 + cCCITT = 2 + cG3 = 3 // Group 3 Fax. + cG4 = 4 // Group 4 Fax. + cLZW = 5 + cJPEGOld = 6 // Superseded by cJPEG. + cJPEG = 7 + cDeflate = 8 // zlib compression. + cPackBits = 32773 + cDeflateOld = 32946 // Superseded by cDeflate. +) + +// Photometric interpretation values (see p. 37 of the spec). +const ( + pWhiteIsZero = 0 + pBlackIsZero = 1 + pRGB = 2 + pPaletted = 3 + pTransMask = 4 // transparency mask + pCMYK = 5 + pYCbCr = 6 + pCIELab = 8 +) + +// Values for the tPredictor tag (page 64-65 of the spec). +const ( + prNone = 1 + prHorizontal = 2 +) + +// Values for the tResolutionUnit tag (page 18). +const ( + resNone = 1 + resPerInch = 2 // Dots per inch. + resPerCM = 3 // Dots per centimeter. +) + +// imageMode represents the mode of the image. +type imageMode int + +const ( + mBilevel imageMode = iota + mPaletted + mGray + mGrayInvert + mRGB + mRGBA + mNRGBA +) + +// CompressionType describes the type of compression used in Options. +type CompressionType int + +const ( + Uncompressed CompressionType = iota + Deflate +) + +// specValue returns the compression type constant from the TIFF spec that +// is equivalent to c. +func (c CompressionType) specValue() uint32 { + switch c { + case Deflate: + return cDeflate + } + return cNone +} diff --git a/vendor/golang.org/x/image/tiff/fuzz.go b/vendor/golang.org/x/image/tiff/fuzz.go new file mode 100644 index 0000000000..ec52c7882e --- /dev/null +++ b/vendor/golang.org/x/image/tiff/fuzz.go @@ -0,0 +1,29 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build gofuzz + +package tiff + +import "bytes" + +func Fuzz(data []byte) int { + cfg, err := DecodeConfig(bytes.NewReader(data)) + if err != nil { + return 0 + } + if cfg.Width*cfg.Height > 1e6 { + return 0 + } + img, err := Decode(bytes.NewReader(data)) + if err != nil { + return 0 + } + var w bytes.Buffer + err = Encode(&w, img, nil) + if err != nil { + panic(err) + } + return 1 +} diff --git a/vendor/golang.org/x/image/tiff/lzw/reader.go b/vendor/golang.org/x/image/tiff/lzw/reader.go new file mode 100644 index 0000000000..1e98a19fda --- /dev/null +++ b/vendor/golang.org/x/image/tiff/lzw/reader.go @@ -0,0 +1,272 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package lzw implements the Lempel-Ziv-Welch compressed data format, +// described in T. A. Welch, ``A Technique for High-Performance Data +// Compression'', Computer, 17(6) (June 1984), pp 8-19. +// +// In particular, it implements LZW as used by the TIFF file format, including +// an "off by one" algorithmic difference when compared to standard LZW. +package lzw + +/* +This file was branched from src/pkg/compress/lzw/reader.go in the +standard library. Differences from the original are marked with "NOTE". + +The tif_lzw.c file in the libtiff C library has this comment: + +---- +The 5.0 spec describes a different algorithm than Aldus +implements. Specifically, Aldus does code length transitions +one code earlier than should be done (for real LZW). +Earlier versions of this library implemented the correct +LZW algorithm, but emitted codes in a bit order opposite +to the TIFF spec. Thus, to maintain compatibility w/ Aldus +we interpret MSB-LSB ordered codes to be images written w/ +old versions of this library, but otherwise adhere to the +Aldus "off by one" algorithm. +---- + +The Go code doesn't read (invalid) TIFF files written by old versions of +libtiff, but the LZW algorithm in this package still differs from the one in +Go's standard package library to accomodate this "off by one" in valid TIFFs. +*/ + +import ( + "bufio" + "errors" + "fmt" + "io" +) + +// Order specifies the bit ordering in an LZW data stream. +type Order int + +const ( + // LSB means Least Significant Bits first, as used in the GIF file format. + LSB Order = iota + // MSB means Most Significant Bits first, as used in the TIFF and PDF + // file formats. + MSB +) + +const ( + maxWidth = 12 + decoderInvalidCode = 0xffff + flushBuffer = 1 << maxWidth +) + +// decoder is the state from which the readXxx method converts a byte +// stream into a code stream. +type decoder struct { + r io.ByteReader + bits uint32 + nBits uint + width uint + read func(*decoder) (uint16, error) // readLSB or readMSB + litWidth int // width in bits of literal codes + err error + + // The first 1<= 1<>= d.width + d.nBits -= d.width + return code, nil +} + +// readMSB returns the next code for "Most Significant Bits first" data. +func (d *decoder) readMSB() (uint16, error) { + for d.nBits < d.width { + x, err := d.r.ReadByte() + if err != nil { + return 0, err + } + d.bits |= uint32(x) << (24 - d.nBits) + d.nBits += 8 + } + code := uint16(d.bits >> (32 - d.width)) + d.bits <<= d.width + d.nBits -= d.width + return code, nil +} + +func (d *decoder) Read(b []byte) (int, error) { + for { + if len(d.toRead) > 0 { + n := copy(b, d.toRead) + d.toRead = d.toRead[n:] + return n, nil + } + if d.err != nil { + return 0, d.err + } + d.decode() + } +} + +// decode decompresses bytes from r and leaves them in d.toRead. +// read specifies how to decode bytes into codes. +// litWidth is the width in bits of literal codes. +func (d *decoder) decode() { + // Loop over the code stream, converting codes into decompressed bytes. +loop: + for { + code, err := d.read(d) + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + d.err = err + break + } + switch { + case code < d.clear: + // We have a literal code. + d.output[d.o] = uint8(code) + d.o++ + if d.last != decoderInvalidCode { + // Save what the hi code expands to. + d.suffix[d.hi] = uint8(code) + d.prefix[d.hi] = d.last + } + case code == d.clear: + d.width = 1 + uint(d.litWidth) + d.hi = d.eof + d.overflow = 1 << d.width + d.last = decoderInvalidCode + continue + case code == d.eof: + d.err = io.EOF + break loop + case code <= d.hi: + c, i := code, len(d.output)-1 + if code == d.hi { + // code == hi is a special case which expands to the last expansion + // followed by the head of the last expansion. To find the head, we walk + // the prefix chain until we find a literal code. + c = d.last + for c >= d.clear { + c = d.prefix[c] + } + d.output[i] = uint8(c) + i-- + c = d.last + } + // Copy the suffix chain into output and then write that to w. + for c >= d.clear { + d.output[i] = d.suffix[c] + i-- + c = d.prefix[c] + } + d.output[i] = uint8(c) + d.o += copy(d.output[d.o:], d.output[i:]) + if d.last != decoderInvalidCode { + // Save what the hi code expands to. + d.suffix[d.hi] = uint8(c) + d.prefix[d.hi] = d.last + } + default: + d.err = errors.New("lzw: invalid code") + break loop + } + d.last, d.hi = code, d.hi+1 + if d.hi+1 >= d.overflow { // NOTE: the "+1" is where TIFF's LZW differs from the standard algorithm. + if d.width == maxWidth { + d.last = decoderInvalidCode + } else { + d.width++ + d.overflow <<= 1 + } + } + if d.o >= flushBuffer { + break + } + } + // Flush pending output. + d.toRead = d.output[:d.o] + d.o = 0 +} + +var errClosed = errors.New("lzw: reader/writer is closed") + +func (d *decoder) Close() error { + d.err = errClosed // in case any Reads come along + return nil +} + +// NewReader creates a new io.ReadCloser. +// Reads from the returned io.ReadCloser read and decompress data from r. +// If r does not also implement io.ByteReader, +// the decompressor may read more data than necessary from r. +// It is the caller's responsibility to call Close on the ReadCloser when +// finished reading. +// The number of bits to use for literal codes, litWidth, must be in the +// range [2,8] and is typically 8. It must equal the litWidth +// used during compression. +func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser { + d := new(decoder) + switch order { + case LSB: + d.read = (*decoder).readLSB + case MSB: + d.read = (*decoder).readMSB + default: + d.err = errors.New("lzw: unknown order") + return d + } + if litWidth < 2 || 8 < litWidth { + d.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth) + return d + } + if br, ok := r.(io.ByteReader); ok { + d.r = br + } else { + d.r = bufio.NewReader(r) + } + d.litWidth = litWidth + d.width = 1 + uint(litWidth) + d.clear = uint16(1) << uint(litWidth) + d.eof, d.hi = d.clear+1, d.clear+1 + d.overflow = uint16(1) << d.width + d.last = decoderInvalidCode + + return d +} diff --git a/vendor/golang.org/x/image/tiff/reader.go b/vendor/golang.org/x/image/tiff/reader.go new file mode 100644 index 0000000000..6585b15cba --- /dev/null +++ b/vendor/golang.org/x/image/tiff/reader.go @@ -0,0 +1,684 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package tiff implements a TIFF image decoder and encoder. +// +// The TIFF specification is at http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf +package tiff + +import ( + "compress/zlib" + "encoding/binary" + "fmt" + "image" + "image/color" + "io" + "io/ioutil" + "math" + + "golang.org/x/image/tiff/lzw" +) + +// A FormatError reports that the input is not a valid TIFF image. +type FormatError string + +func (e FormatError) Error() string { + return "tiff: invalid format: " + string(e) +} + +// An UnsupportedError reports that the input uses a valid but +// unimplemented feature. +type UnsupportedError string + +func (e UnsupportedError) Error() string { + return "tiff: unsupported feature: " + string(e) +} + +var errNoPixels = FormatError("not enough pixel data") + +type decoder struct { + r io.ReaderAt + byteOrder binary.ByteOrder + config image.Config + mode imageMode + bpp uint + features map[int][]uint + palette []color.Color + + buf []byte + off int // Current offset in buf. + v uint32 // Buffer value for reading with arbitrary bit depths. + nbits uint // Remaining number of bits in v. +} + +// firstVal returns the first uint of the features entry with the given tag, +// or 0 if the tag does not exist. +func (d *decoder) firstVal(tag int) uint { + f := d.features[tag] + if len(f) == 0 { + return 0 + } + return f[0] +} + +// ifdUint decodes the IFD entry in p, which must be of the Byte, Short +// or Long type, and returns the decoded uint values. +func (d *decoder) ifdUint(p []byte) (u []uint, err error) { + var raw []byte + if len(p) < ifdLen { + return nil, FormatError("bad IFD entry") + } + + datatype := d.byteOrder.Uint16(p[2:4]) + if dt := int(datatype); dt <= 0 || dt >= len(lengths) { + return nil, UnsupportedError("IFD entry datatype") + } + + count := d.byteOrder.Uint32(p[4:8]) + if count > math.MaxInt32/lengths[datatype] { + return nil, FormatError("IFD data too large") + } + if datalen := lengths[datatype] * count; datalen > 4 { + // The IFD contains a pointer to the real value. + raw = make([]byte, datalen) + _, err = d.r.ReadAt(raw, int64(d.byteOrder.Uint32(p[8:12]))) + } else { + raw = p[8 : 8+datalen] + } + if err != nil { + return nil, err + } + + u = make([]uint, count) + switch datatype { + case dtByte: + for i := uint32(0); i < count; i++ { + u[i] = uint(raw[i]) + } + case dtShort: + for i := uint32(0); i < count; i++ { + u[i] = uint(d.byteOrder.Uint16(raw[2*i : 2*(i+1)])) + } + case dtLong: + for i := uint32(0); i < count; i++ { + u[i] = uint(d.byteOrder.Uint32(raw[4*i : 4*(i+1)])) + } + default: + return nil, UnsupportedError("data type") + } + return u, nil +} + +// parseIFD decides whether the IFD entry in p is "interesting" and +// stows away the data in the decoder. It returns the tag number of the +// entry and an error, if any. +func (d *decoder) parseIFD(p []byte) (int, error) { + tag := d.byteOrder.Uint16(p[0:2]) + switch tag { + case tBitsPerSample, + tExtraSamples, + tPhotometricInterpretation, + tCompression, + tPredictor, + tStripOffsets, + tStripByteCounts, + tRowsPerStrip, + tTileWidth, + tTileLength, + tTileOffsets, + tTileByteCounts, + tImageLength, + tImageWidth: + val, err := d.ifdUint(p) + if err != nil { + return 0, err + } + d.features[int(tag)] = val + case tColorMap: + val, err := d.ifdUint(p) + if err != nil { + return 0, err + } + numcolors := len(val) / 3 + if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 { + return 0, FormatError("bad ColorMap length") + } + d.palette = make([]color.Color, numcolors) + for i := 0; i < numcolors; i++ { + d.palette[i] = color.RGBA64{ + uint16(val[i]), + uint16(val[i+numcolors]), + uint16(val[i+2*numcolors]), + 0xffff, + } + } + case tSampleFormat: + // Page 27 of the spec: If the SampleFormat is present and + // the value is not 1 [= unsigned integer data], a Baseline + // TIFF reader that cannot handle the SampleFormat value + // must terminate the import process gracefully. + val, err := d.ifdUint(p) + if err != nil { + return 0, err + } + for _, v := range val { + if v != 1 { + return 0, UnsupportedError("sample format") + } + } + } + return int(tag), nil +} + +// readBits reads n bits from the internal buffer starting at the current offset. +func (d *decoder) readBits(n uint) (v uint32, ok bool) { + for d.nbits < n { + d.v <<= 8 + if d.off >= len(d.buf) { + return 0, false + } + d.v |= uint32(d.buf[d.off]) + d.off++ + d.nbits += 8 + } + d.nbits -= n + rv := d.v >> d.nbits + d.v &^= rv << d.nbits + return rv, true +} + +// flushBits discards the unread bits in the buffer used by readBits. +// It is used at the end of a line. +func (d *decoder) flushBits() { + d.v = 0 + d.nbits = 0 +} + +// minInt returns the smaller of x or y. +func minInt(a, b int) int { + if a <= b { + return a + } + return b +} + +// decode decodes the raw data of an image. +// It reads from d.buf and writes the strip or tile into dst. +func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error { + d.off = 0 + + // Apply horizontal predictor if necessary. + // In this case, p contains the color difference to the preceding pixel. + // See page 64-65 of the spec. + if d.firstVal(tPredictor) == prHorizontal { + switch d.bpp { + case 16: + var off int + n := 2 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel + for y := ymin; y < ymax; y++ { + off += n + for x := 0; x < (xmax-xmin-1)*n; x += 2 { + if off+2 > len(d.buf) { + return errNoPixels + } + v0 := d.byteOrder.Uint16(d.buf[off-n : off-n+2]) + v1 := d.byteOrder.Uint16(d.buf[off : off+2]) + d.byteOrder.PutUint16(d.buf[off:off+2], v1+v0) + off += 2 + } + } + case 8: + var off int + n := 1 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel + for y := ymin; y < ymax; y++ { + off += n + for x := 0; x < (xmax-xmin-1)*n; x++ { + if off >= len(d.buf) { + return errNoPixels + } + d.buf[off] += d.buf[off-n] + off++ + } + } + case 1: + return UnsupportedError("horizontal predictor with 1 BitsPerSample") + } + } + + rMaxX := minInt(xmax, dst.Bounds().Max.X) + rMaxY := minInt(ymax, dst.Bounds().Max.Y) + switch d.mode { + case mGray, mGrayInvert: + if d.bpp == 16 { + img := dst.(*image.Gray16) + for y := ymin; y < rMaxY; y++ { + for x := xmin; x < rMaxX; x++ { + if d.off+2 > len(d.buf) { + return errNoPixels + } + v := d.byteOrder.Uint16(d.buf[d.off : d.off+2]) + d.off += 2 + if d.mode == mGrayInvert { + v = 0xffff - v + } + img.SetGray16(x, y, color.Gray16{v}) + } + if rMaxX == img.Bounds().Max.X { + d.off += 2 * (xmax - img.Bounds().Max.X) + } + } + } else { + img := dst.(*image.Gray) + max := uint32((1 << d.bpp) - 1) + for y := ymin; y < rMaxY; y++ { + for x := xmin; x < rMaxX; x++ { + v, ok := d.readBits(d.bpp) + if !ok { + return errNoPixels + } + v = v * 0xff / max + if d.mode == mGrayInvert { + v = 0xff - v + } + img.SetGray(x, y, color.Gray{uint8(v)}) + } + d.flushBits() + } + } + case mPaletted: + img := dst.(*image.Paletted) + for y := ymin; y < rMaxY; y++ { + for x := xmin; x < rMaxX; x++ { + v, ok := d.readBits(d.bpp) + if !ok { + return errNoPixels + } + img.SetColorIndex(x, y, uint8(v)) + } + d.flushBits() + } + case mRGB: + if d.bpp == 16 { + img := dst.(*image.RGBA64) + for y := ymin; y < rMaxY; y++ { + for x := xmin; x < rMaxX; x++ { + if d.off+6 > len(d.buf) { + return errNoPixels + } + r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2]) + g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4]) + b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6]) + d.off += 6 + img.SetRGBA64(x, y, color.RGBA64{r, g, b, 0xffff}) + } + } + } else { + img := dst.(*image.RGBA) + for y := ymin; y < rMaxY; y++ { + min := img.PixOffset(xmin, y) + max := img.PixOffset(rMaxX, y) + off := (y - ymin) * (xmax - xmin) * 3 + for i := min; i < max; i += 4 { + if off+3 > len(d.buf) { + return errNoPixels + } + img.Pix[i+0] = d.buf[off+0] + img.Pix[i+1] = d.buf[off+1] + img.Pix[i+2] = d.buf[off+2] + img.Pix[i+3] = 0xff + off += 3 + } + } + } + case mNRGBA: + if d.bpp == 16 { + img := dst.(*image.NRGBA64) + for y := ymin; y < rMaxY; y++ { + for x := xmin; x < rMaxX; x++ { + if d.off+8 > len(d.buf) { + return errNoPixels + } + r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2]) + g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4]) + b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6]) + a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8]) + d.off += 8 + img.SetNRGBA64(x, y, color.NRGBA64{r, g, b, a}) + } + } + } else { + img := dst.(*image.NRGBA) + for y := ymin; y < rMaxY; y++ { + min := img.PixOffset(xmin, y) + max := img.PixOffset(rMaxX, y) + i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4 + if i1 > len(d.buf) { + return errNoPixels + } + copy(img.Pix[min:max], d.buf[i0:i1]) + } + } + case mRGBA: + if d.bpp == 16 { + img := dst.(*image.RGBA64) + for y := ymin; y < rMaxY; y++ { + for x := xmin; x < rMaxX; x++ { + if d.off+8 > len(d.buf) { + return errNoPixels + } + r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2]) + g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4]) + b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6]) + a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8]) + d.off += 8 + img.SetRGBA64(x, y, color.RGBA64{r, g, b, a}) + } + } + } else { + img := dst.(*image.RGBA) + for y := ymin; y < rMaxY; y++ { + min := img.PixOffset(xmin, y) + max := img.PixOffset(rMaxX, y) + i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4 + if i1 > len(d.buf) { + return errNoPixels + } + copy(img.Pix[min:max], d.buf[i0:i1]) + } + } + } + + return nil +} + +func newDecoder(r io.Reader) (*decoder, error) { + d := &decoder{ + r: newReaderAt(r), + features: make(map[int][]uint), + } + + p := make([]byte, 8) + if _, err := d.r.ReadAt(p, 0); err != nil { + return nil, err + } + switch string(p[0:4]) { + case leHeader: + d.byteOrder = binary.LittleEndian + case beHeader: + d.byteOrder = binary.BigEndian + default: + return nil, FormatError("malformed header") + } + + ifdOffset := int64(d.byteOrder.Uint32(p[4:8])) + + // The first two bytes contain the number of entries (12 bytes each). + if _, err := d.r.ReadAt(p[0:2], ifdOffset); err != nil { + return nil, err + } + numItems := int(d.byteOrder.Uint16(p[0:2])) + + // All IFD entries are read in one chunk. + p = make([]byte, ifdLen*numItems) + if _, err := d.r.ReadAt(p, ifdOffset+2); err != nil { + return nil, err + } + + prevTag := -1 + for i := 0; i < len(p); i += ifdLen { + tag, err := d.parseIFD(p[i : i+ifdLen]) + if err != nil { + return nil, err + } + if tag <= prevTag { + return nil, FormatError("tags are not sorted in ascending order") + } + prevTag = tag + } + + d.config.Width = int(d.firstVal(tImageWidth)) + d.config.Height = int(d.firstVal(tImageLength)) + + if _, ok := d.features[tBitsPerSample]; !ok { + return nil, FormatError("BitsPerSample tag missing") + } + d.bpp = d.firstVal(tBitsPerSample) + switch d.bpp { + case 0: + return nil, FormatError("BitsPerSample must not be 0") + case 1, 8, 16: + // Nothing to do, these are accepted by this implementation. + default: + return nil, UnsupportedError(fmt.Sprintf("BitsPerSample of %v", d.bpp)) + } + + // Determine the image mode. + switch d.firstVal(tPhotometricInterpretation) { + case pRGB: + if d.bpp == 16 { + for _, b := range d.features[tBitsPerSample] { + if b != 16 { + return nil, FormatError("wrong number of samples for 16bit RGB") + } + } + } else { + for _, b := range d.features[tBitsPerSample] { + if b != 8 { + return nil, FormatError("wrong number of samples for 8bit RGB") + } + } + } + // RGB images normally have 3 samples per pixel. + // If there are more, ExtraSamples (p. 31-32 of the spec) + // gives their meaning (usually an alpha channel). + // + // This implementation does not support extra samples + // of an unspecified type. + switch len(d.features[tBitsPerSample]) { + case 3: + d.mode = mRGB + if d.bpp == 16 { + d.config.ColorModel = color.RGBA64Model + } else { + d.config.ColorModel = color.RGBAModel + } + case 4: + switch d.firstVal(tExtraSamples) { + case 1: + d.mode = mRGBA + if d.bpp == 16 { + d.config.ColorModel = color.RGBA64Model + } else { + d.config.ColorModel = color.RGBAModel + } + case 2: + d.mode = mNRGBA + if d.bpp == 16 { + d.config.ColorModel = color.NRGBA64Model + } else { + d.config.ColorModel = color.NRGBAModel + } + default: + return nil, FormatError("wrong number of samples for RGB") + } + default: + return nil, FormatError("wrong number of samples for RGB") + } + case pPaletted: + d.mode = mPaletted + d.config.ColorModel = color.Palette(d.palette) + case pWhiteIsZero: + d.mode = mGrayInvert + if d.bpp == 16 { + d.config.ColorModel = color.Gray16Model + } else { + d.config.ColorModel = color.GrayModel + } + case pBlackIsZero: + d.mode = mGray + if d.bpp == 16 { + d.config.ColorModel = color.Gray16Model + } else { + d.config.ColorModel = color.GrayModel + } + default: + return nil, UnsupportedError("color model") + } + + return d, nil +} + +// DecodeConfig returns the color model and dimensions of a TIFF image without +// decoding the entire image. +func DecodeConfig(r io.Reader) (image.Config, error) { + d, err := newDecoder(r) + if err != nil { + return image.Config{}, err + } + return d.config, nil +} + +// Decode reads a TIFF image from r and returns it as an image.Image. +// The type of Image returned depends on the contents of the TIFF. +func Decode(r io.Reader) (img image.Image, err error) { + d, err := newDecoder(r) + if err != nil { + return + } + + blockPadding := false + blockWidth := d.config.Width + blockHeight := d.config.Height + blocksAcross := 1 + blocksDown := 1 + + if d.config.Width == 0 { + blocksAcross = 0 + } + if d.config.Height == 0 { + blocksDown = 0 + } + + var blockOffsets, blockCounts []uint + + if int(d.firstVal(tTileWidth)) != 0 { + blockPadding = true + + blockWidth = int(d.firstVal(tTileWidth)) + blockHeight = int(d.firstVal(tTileLength)) + + if blockWidth != 0 { + blocksAcross = (d.config.Width + blockWidth - 1) / blockWidth + } + if blockHeight != 0 { + blocksDown = (d.config.Height + blockHeight - 1) / blockHeight + } + + blockCounts = d.features[tTileByteCounts] + blockOffsets = d.features[tTileOffsets] + + } else { + if int(d.firstVal(tRowsPerStrip)) != 0 { + blockHeight = int(d.firstVal(tRowsPerStrip)) + } + + if blockHeight != 0 { + blocksDown = (d.config.Height + blockHeight - 1) / blockHeight + } + + blockOffsets = d.features[tStripOffsets] + blockCounts = d.features[tStripByteCounts] + } + + // Check if we have the right number of strips/tiles, offsets and counts. + if n := blocksAcross * blocksDown; len(blockOffsets) < n || len(blockCounts) < n { + return nil, FormatError("inconsistent header") + } + + imgRect := image.Rect(0, 0, d.config.Width, d.config.Height) + switch d.mode { + case mGray, mGrayInvert: + if d.bpp == 16 { + img = image.NewGray16(imgRect) + } else { + img = image.NewGray(imgRect) + } + case mPaletted: + img = image.NewPaletted(imgRect, d.palette) + case mNRGBA: + if d.bpp == 16 { + img = image.NewNRGBA64(imgRect) + } else { + img = image.NewNRGBA(imgRect) + } + case mRGB, mRGBA: + if d.bpp == 16 { + img = image.NewRGBA64(imgRect) + } else { + img = image.NewRGBA(imgRect) + } + } + + for i := 0; i < blocksAcross; i++ { + blkW := blockWidth + if !blockPadding && i == blocksAcross-1 && d.config.Width%blockWidth != 0 { + blkW = d.config.Width % blockWidth + } + for j := 0; j < blocksDown; j++ { + blkH := blockHeight + if !blockPadding && j == blocksDown-1 && d.config.Height%blockHeight != 0 { + blkH = d.config.Height % blockHeight + } + offset := int64(blockOffsets[j*blocksAcross+i]) + n := int64(blockCounts[j*blocksAcross+i]) + switch d.firstVal(tCompression) { + + // According to the spec, Compression does not have a default value, + // but some tools interpret a missing Compression value as none so we do + // the same. + case cNone, 0: + if b, ok := d.r.(*buffer); ok { + d.buf, err = b.Slice(int(offset), int(n)) + } else { + d.buf = make([]byte, n) + _, err = d.r.ReadAt(d.buf, offset) + } + case cLZW: + r := lzw.NewReader(io.NewSectionReader(d.r, offset, n), lzw.MSB, 8) + d.buf, err = ioutil.ReadAll(r) + r.Close() + case cDeflate, cDeflateOld: + var r io.ReadCloser + r, err = zlib.NewReader(io.NewSectionReader(d.r, offset, n)) + if err != nil { + return nil, err + } + d.buf, err = ioutil.ReadAll(r) + r.Close() + case cPackBits: + d.buf, err = unpackBits(io.NewSectionReader(d.r, offset, n)) + default: + err = UnsupportedError(fmt.Sprintf("compression value %d", d.firstVal(tCompression))) + } + if err != nil { + return nil, err + } + + xmin := i * blockWidth + ymin := j * blockHeight + xmax := xmin + blkW + ymax := ymin + blkH + err = d.decode(img, xmin, ymin, xmax, ymax) + if err != nil { + return nil, err + } + } + } + return +} + +func init() { + image.RegisterFormat("tiff", leHeader, Decode, DecodeConfig) + image.RegisterFormat("tiff", beHeader, Decode, DecodeConfig) +} diff --git a/vendor/golang.org/x/image/tiff/writer.go b/vendor/golang.org/x/image/tiff/writer.go new file mode 100644 index 0000000000..c8a01cea71 --- /dev/null +++ b/vendor/golang.org/x/image/tiff/writer.go @@ -0,0 +1,438 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tiff + +import ( + "bytes" + "compress/zlib" + "encoding/binary" + "image" + "io" + "sort" +) + +// The TIFF format allows to choose the order of the different elements freely. +// The basic structure of a TIFF file written by this package is: +// +// 1. Header (8 bytes). +// 2. Image data. +// 3. Image File Directory (IFD). +// 4. "Pointer area" for larger entries in the IFD. + +// We only write little-endian TIFF files. +var enc = binary.LittleEndian + +// An ifdEntry is a single entry in an Image File Directory. +// A value of type dtRational is composed of two 32-bit values, +// thus data contains two uints (numerator and denominator) for a single number. +type ifdEntry struct { + tag int + datatype int + data []uint32 +} + +func (e ifdEntry) putData(p []byte) { + for _, d := range e.data { + switch e.datatype { + case dtByte, dtASCII: + p[0] = byte(d) + p = p[1:] + case dtShort: + enc.PutUint16(p, uint16(d)) + p = p[2:] + case dtLong, dtRational: + enc.PutUint32(p, uint32(d)) + p = p[4:] + } + } +} + +type byTag []ifdEntry + +func (d byTag) Len() int { return len(d) } +func (d byTag) Less(i, j int) bool { return d[i].tag < d[j].tag } +func (d byTag) Swap(i, j int) { d[i], d[j] = d[j], d[i] } + +func encodeGray(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { + if !predictor { + return writePix(w, pix, dy, dx, stride) + } + buf := make([]byte, dx) + for y := 0; y < dy; y++ { + min := y*stride + 0 + max := y*stride + dx + off := 0 + var v0 uint8 + for i := min; i < max; i++ { + v1 := pix[i] + buf[off] = v1 - v0 + v0 = v1 + off++ + } + if _, err := w.Write(buf); err != nil { + return err + } + } + return nil +} + +func encodeGray16(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { + buf := make([]byte, dx*2) + for y := 0; y < dy; y++ { + min := y*stride + 0 + max := y*stride + dx*2 + off := 0 + var v0 uint16 + for i := min; i < max; i += 2 { + // An image.Gray16's Pix is in big-endian order. + v1 := uint16(pix[i])<<8 | uint16(pix[i+1]) + if predictor { + v0, v1 = v1, v1-v0 + } + // We only write little-endian TIFF files. + buf[off+0] = byte(v1) + buf[off+1] = byte(v1 >> 8) + off += 2 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + return nil +} + +func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { + if !predictor { + return writePix(w, pix, dy, dx*4, stride) + } + buf := make([]byte, dx*4) + for y := 0; y < dy; y++ { + min := y*stride + 0 + max := y*stride + dx*4 + off := 0 + var r0, g0, b0, a0 uint8 + for i := min; i < max; i += 4 { + r1, g1, b1, a1 := pix[i+0], pix[i+1], pix[i+2], pix[i+3] + buf[off+0] = r1 - r0 + buf[off+1] = g1 - g0 + buf[off+2] = b1 - b0 + buf[off+3] = a1 - a0 + off += 4 + r0, g0, b0, a0 = r1, g1, b1, a1 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + return nil +} + +func encodeRGBA64(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { + buf := make([]byte, dx*8) + for y := 0; y < dy; y++ { + min := y*stride + 0 + max := y*stride + dx*8 + off := 0 + var r0, g0, b0, a0 uint16 + for i := min; i < max; i += 8 { + // An image.RGBA64's Pix is in big-endian order. + r1 := uint16(pix[i+0])<<8 | uint16(pix[i+1]) + g1 := uint16(pix[i+2])<<8 | uint16(pix[i+3]) + b1 := uint16(pix[i+4])<<8 | uint16(pix[i+5]) + a1 := uint16(pix[i+6])<<8 | uint16(pix[i+7]) + if predictor { + r0, r1 = r1, r1-r0 + g0, g1 = g1, g1-g0 + b0, b1 = b1, b1-b0 + a0, a1 = a1, a1-a0 + } + // We only write little-endian TIFF files. + buf[off+0] = byte(r1) + buf[off+1] = byte(r1 >> 8) + buf[off+2] = byte(g1) + buf[off+3] = byte(g1 >> 8) + buf[off+4] = byte(b1) + buf[off+5] = byte(b1 >> 8) + buf[off+6] = byte(a1) + buf[off+7] = byte(a1 >> 8) + off += 8 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + return nil +} + +func encode(w io.Writer, m image.Image, predictor bool) error { + bounds := m.Bounds() + buf := make([]byte, 4*bounds.Dx()) + for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + off := 0 + if predictor { + var r0, g0, b0, a0 uint8 + for x := bounds.Min.X; x < bounds.Max.X; x++ { + r, g, b, a := m.At(x, y).RGBA() + r1 := uint8(r >> 8) + g1 := uint8(g >> 8) + b1 := uint8(b >> 8) + a1 := uint8(a >> 8) + buf[off+0] = r1 - r0 + buf[off+1] = g1 - g0 + buf[off+2] = b1 - b0 + buf[off+3] = a1 - a0 + off += 4 + r0, g0, b0, a0 = r1, g1, b1, a1 + } + } else { + for x := bounds.Min.X; x < bounds.Max.X; x++ { + r, g, b, a := m.At(x, y).RGBA() + buf[off+0] = uint8(r >> 8) + buf[off+1] = uint8(g >> 8) + buf[off+2] = uint8(b >> 8) + buf[off+3] = uint8(a >> 8) + off += 4 + } + } + if _, err := w.Write(buf); err != nil { + return err + } + } + return nil +} + +// writePix writes the internal byte array of an image to w. It is less general +// but much faster then encode. writePix is used when pix directly +// corresponds to one of the TIFF image types. +func writePix(w io.Writer, pix []byte, nrows, length, stride int) error { + if length == stride { + _, err := w.Write(pix[:nrows*length]) + return err + } + for ; nrows > 0; nrows-- { + if _, err := w.Write(pix[:length]); err != nil { + return err + } + pix = pix[stride:] + } + return nil +} + +func writeIFD(w io.Writer, ifdOffset int, d []ifdEntry) error { + var buf [ifdLen]byte + // Make space for "pointer area" containing IFD entry data + // longer than 4 bytes. + parea := make([]byte, 1024) + pstart := ifdOffset + ifdLen*len(d) + 6 + var o int // Current offset in parea. + + // The IFD has to be written with the tags in ascending order. + sort.Sort(byTag(d)) + + // Write the number of entries in this IFD. + if err := binary.Write(w, enc, uint16(len(d))); err != nil { + return err + } + for _, ent := range d { + enc.PutUint16(buf[0:2], uint16(ent.tag)) + enc.PutUint16(buf[2:4], uint16(ent.datatype)) + count := uint32(len(ent.data)) + if ent.datatype == dtRational { + count /= 2 + } + enc.PutUint32(buf[4:8], count) + datalen := int(count * lengths[ent.datatype]) + if datalen <= 4 { + ent.putData(buf[8:12]) + } else { + if (o + datalen) > len(parea) { + newlen := len(parea) + 1024 + for (o + datalen) > newlen { + newlen += 1024 + } + newarea := make([]byte, newlen) + copy(newarea, parea) + parea = newarea + } + ent.putData(parea[o : o+datalen]) + enc.PutUint32(buf[8:12], uint32(pstart+o)) + o += datalen + } + if _, err := w.Write(buf[:]); err != nil { + return err + } + } + // The IFD ends with the offset of the next IFD in the file, + // or zero if it is the last one (page 14). + if err := binary.Write(w, enc, uint32(0)); err != nil { + return err + } + _, err := w.Write(parea[:o]) + return err +} + +// Options are the encoding parameters. +type Options struct { + // Compression is the type of compression used. + Compression CompressionType + // Predictor determines whether a differencing predictor is used; + // if true, instead of each pixel's color, the color difference to the + // preceding one is saved. This improves the compression for certain + // types of images and compressors. For example, it works well for + // photos with Deflate compression. + Predictor bool +} + +// Encode writes the image m to w. opt determines the options used for +// encoding, such as the compression type. If opt is nil, an uncompressed +// image is written. +func Encode(w io.Writer, m image.Image, opt *Options) error { + d := m.Bounds().Size() + + compression := uint32(cNone) + predictor := false + if opt != nil { + compression = opt.Compression.specValue() + // The predictor field is only used with LZW. See page 64 of the spec. + predictor = opt.Predictor && compression == cLZW + } + + _, err := io.WriteString(w, leHeader) + if err != nil { + return err + } + + // Compressed data is written into a buffer first, so that we + // know the compressed size. + var buf bytes.Buffer + // dst holds the destination for the pixel data of the image -- + // either w or a writer to buf. + var dst io.Writer + // imageLen is the length of the pixel data in bytes. + // The offset of the IFD is imageLen + 8 header bytes. + var imageLen int + + switch compression { + case cNone: + dst = w + // Write IFD offset before outputting pixel data. + switch m.(type) { + case *image.Paletted: + imageLen = d.X * d.Y * 1 + case *image.Gray: + imageLen = d.X * d.Y * 1 + case *image.Gray16: + imageLen = d.X * d.Y * 2 + case *image.RGBA64: + imageLen = d.X * d.Y * 8 + case *image.NRGBA64: + imageLen = d.X * d.Y * 8 + default: + imageLen = d.X * d.Y * 4 + } + err = binary.Write(w, enc, uint32(imageLen+8)) + if err != nil { + return err + } + case cDeflate: + dst = zlib.NewWriter(&buf) + } + + pr := uint32(prNone) + photometricInterpretation := uint32(pRGB) + samplesPerPixel := uint32(4) + bitsPerSample := []uint32{8, 8, 8, 8} + extraSamples := uint32(0) + colorMap := []uint32{} + + if predictor { + pr = prHorizontal + } + switch m := m.(type) { + case *image.Paletted: + photometricInterpretation = pPaletted + samplesPerPixel = 1 + bitsPerSample = []uint32{8} + colorMap = make([]uint32, 256*3) + for i := 0; i < 256 && i < len(m.Palette); i++ { + r, g, b, _ := m.Palette[i].RGBA() + colorMap[i+0*256] = uint32(r) + colorMap[i+1*256] = uint32(g) + colorMap[i+2*256] = uint32(b) + } + err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor) + case *image.Gray: + photometricInterpretation = pBlackIsZero + samplesPerPixel = 1 + bitsPerSample = []uint32{8} + err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor) + case *image.Gray16: + photometricInterpretation = pBlackIsZero + samplesPerPixel = 1 + bitsPerSample = []uint32{16} + err = encodeGray16(dst, m.Pix, d.X, d.Y, m.Stride, predictor) + case *image.NRGBA: + extraSamples = 2 // Unassociated alpha. + err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor) + case *image.NRGBA64: + extraSamples = 2 // Unassociated alpha. + bitsPerSample = []uint32{16, 16, 16, 16} + err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor) + case *image.RGBA: + extraSamples = 1 // Associated alpha. + err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor) + case *image.RGBA64: + extraSamples = 1 // Associated alpha. + bitsPerSample = []uint32{16, 16, 16, 16} + err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor) + default: + extraSamples = 1 // Associated alpha. + err = encode(dst, m, predictor) + } + if err != nil { + return err + } + + if compression != cNone { + if err = dst.(io.Closer).Close(); err != nil { + return err + } + imageLen = buf.Len() + if err = binary.Write(w, enc, uint32(imageLen+8)); err != nil { + return err + } + if _, err = buf.WriteTo(w); err != nil { + return err + } + } + + ifd := []ifdEntry{ + {tImageWidth, dtShort, []uint32{uint32(d.X)}}, + {tImageLength, dtShort, []uint32{uint32(d.Y)}}, + {tBitsPerSample, dtShort, bitsPerSample}, + {tCompression, dtShort, []uint32{compression}}, + {tPhotometricInterpretation, dtShort, []uint32{photometricInterpretation}}, + {tStripOffsets, dtLong, []uint32{8}}, + {tSamplesPerPixel, dtShort, []uint32{samplesPerPixel}}, + {tRowsPerStrip, dtShort, []uint32{uint32(d.Y)}}, + {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}}, + // There is currently no support for storing the image + // resolution, so give a bogus value of 72x72 dpi. + {tXResolution, dtRational, []uint32{72, 1}}, + {tYResolution, dtRational, []uint32{72, 1}}, + {tResolutionUnit, dtShort, []uint32{resPerInch}}, + } + if pr != prNone { + ifd = append(ifd, ifdEntry{tPredictor, dtShort, []uint32{pr}}) + } + if len(colorMap) != 0 { + ifd = append(ifd, ifdEntry{tColorMap, dtShort, colorMap}) + } + if extraSamples > 0 { + ifd = append(ifd, ifdEntry{tExtraSamples, dtShort, []uint32{extraSamples}}) + } + + return writeIFD(w, imageLen+8, ifd) +} diff --git a/vendor/golang.org/x/net/html/entity.go b/vendor/golang.org/x/net/html/entity.go index a50c04c60e..b628880a01 100644 --- a/vendor/golang.org/x/net/html/entity.go +++ b/vendor/golang.org/x/net/html/entity.go @@ -75,2083 +75,2083 @@ var entity = map[string]rune{ "Copf;": '\U00002102', "Coproduct;": '\U00002210', "CounterClockwiseContourIntegral;": '\U00002233', - "Cross;": '\U00002A2F', - "Cscr;": '\U0001D49E', - "Cup;": '\U000022D3', - "CupCap;": '\U0000224D', - "DD;": '\U00002145', - "DDotrahd;": '\U00002911', - "DJcy;": '\U00000402', - "DScy;": '\U00000405', - "DZcy;": '\U0000040F', - "Dagger;": '\U00002021', - "Darr;": '\U000021A1', - "Dashv;": '\U00002AE4', - "Dcaron;": '\U0000010E', - "Dcy;": '\U00000414', - "Del;": '\U00002207', - "Delta;": '\U00000394', - "Dfr;": '\U0001D507', - "DiacriticalAcute;": '\U000000B4', - "DiacriticalDot;": '\U000002D9', - "DiacriticalDoubleAcute;": '\U000002DD', - "DiacriticalGrave;": '\U00000060', - "DiacriticalTilde;": '\U000002DC', - "Diamond;": '\U000022C4', - "DifferentialD;": '\U00002146', - "Dopf;": '\U0001D53B', - "Dot;": '\U000000A8', - "DotDot;": '\U000020DC', - "DotEqual;": '\U00002250', - "DoubleContourIntegral;": '\U0000222F', - "DoubleDot;": '\U000000A8', - "DoubleDownArrow;": '\U000021D3', - "DoubleLeftArrow;": '\U000021D0', - "DoubleLeftRightArrow;": '\U000021D4', - "DoubleLeftTee;": '\U00002AE4', - "DoubleLongLeftArrow;": '\U000027F8', - "DoubleLongLeftRightArrow;": '\U000027FA', - "DoubleLongRightArrow;": '\U000027F9', - "DoubleRightArrow;": '\U000021D2', - "DoubleRightTee;": '\U000022A8', - "DoubleUpArrow;": '\U000021D1', - "DoubleUpDownArrow;": '\U000021D5', - "DoubleVerticalBar;": '\U00002225', - "DownArrow;": '\U00002193', - "DownArrowBar;": '\U00002913', - "DownArrowUpArrow;": '\U000021F5', - "DownBreve;": '\U00000311', - "DownLeftRightVector;": '\U00002950', - "DownLeftTeeVector;": '\U0000295E', - "DownLeftVector;": '\U000021BD', - "DownLeftVectorBar;": '\U00002956', - "DownRightTeeVector;": '\U0000295F', - "DownRightVector;": '\U000021C1', - "DownRightVectorBar;": '\U00002957', - "DownTee;": '\U000022A4', - "DownTeeArrow;": '\U000021A7', - "Downarrow;": '\U000021D3', - "Dscr;": '\U0001D49F', - "Dstrok;": '\U00000110', - "ENG;": '\U0000014A', - "ETH;": '\U000000D0', - "Eacute;": '\U000000C9', - "Ecaron;": '\U0000011A', - "Ecirc;": '\U000000CA', - "Ecy;": '\U0000042D', - "Edot;": '\U00000116', - "Efr;": '\U0001D508', - "Egrave;": '\U000000C8', - "Element;": '\U00002208', - "Emacr;": '\U00000112', - "EmptySmallSquare;": '\U000025FB', - "EmptyVerySmallSquare;": '\U000025AB', - "Eogon;": '\U00000118', - "Eopf;": '\U0001D53C', - "Epsilon;": '\U00000395', - "Equal;": '\U00002A75', - "EqualTilde;": '\U00002242', - "Equilibrium;": '\U000021CC', - "Escr;": '\U00002130', - "Esim;": '\U00002A73', - "Eta;": '\U00000397', - "Euml;": '\U000000CB', - "Exists;": '\U00002203', - "ExponentialE;": '\U00002147', - "Fcy;": '\U00000424', - "Ffr;": '\U0001D509', - "FilledSmallSquare;": '\U000025FC', - "FilledVerySmallSquare;": '\U000025AA', - "Fopf;": '\U0001D53D', - "ForAll;": '\U00002200', - "Fouriertrf;": '\U00002131', - "Fscr;": '\U00002131', - "GJcy;": '\U00000403', - "GT;": '\U0000003E', - "Gamma;": '\U00000393', - "Gammad;": '\U000003DC', - "Gbreve;": '\U0000011E', - "Gcedil;": '\U00000122', - "Gcirc;": '\U0000011C', - "Gcy;": '\U00000413', - "Gdot;": '\U00000120', - "Gfr;": '\U0001D50A', - "Gg;": '\U000022D9', - "Gopf;": '\U0001D53E', - "GreaterEqual;": '\U00002265', - "GreaterEqualLess;": '\U000022DB', - "GreaterFullEqual;": '\U00002267', - "GreaterGreater;": '\U00002AA2', - "GreaterLess;": '\U00002277', - "GreaterSlantEqual;": '\U00002A7E', - "GreaterTilde;": '\U00002273', - "Gscr;": '\U0001D4A2', - "Gt;": '\U0000226B', - "HARDcy;": '\U0000042A', - "Hacek;": '\U000002C7', - "Hat;": '\U0000005E', - "Hcirc;": '\U00000124', - "Hfr;": '\U0000210C', - "HilbertSpace;": '\U0000210B', - "Hopf;": '\U0000210D', - "HorizontalLine;": '\U00002500', - "Hscr;": '\U0000210B', - "Hstrok;": '\U00000126', - "HumpDownHump;": '\U0000224E', - "HumpEqual;": '\U0000224F', - "IEcy;": '\U00000415', - "IJlig;": '\U00000132', - "IOcy;": '\U00000401', - "Iacute;": '\U000000CD', - "Icirc;": '\U000000CE', - "Icy;": '\U00000418', - "Idot;": '\U00000130', - "Ifr;": '\U00002111', - "Igrave;": '\U000000CC', - "Im;": '\U00002111', - "Imacr;": '\U0000012A', - "ImaginaryI;": '\U00002148', - "Implies;": '\U000021D2', - "Int;": '\U0000222C', - "Integral;": '\U0000222B', - "Intersection;": '\U000022C2', - "InvisibleComma;": '\U00002063', - "InvisibleTimes;": '\U00002062', - "Iogon;": '\U0000012E', - "Iopf;": '\U0001D540', - "Iota;": '\U00000399', - "Iscr;": '\U00002110', - "Itilde;": '\U00000128', - "Iukcy;": '\U00000406', - "Iuml;": '\U000000CF', - "Jcirc;": '\U00000134', - "Jcy;": '\U00000419', - "Jfr;": '\U0001D50D', - "Jopf;": '\U0001D541', - "Jscr;": '\U0001D4A5', - "Jsercy;": '\U00000408', - "Jukcy;": '\U00000404', - "KHcy;": '\U00000425', - "KJcy;": '\U0000040C', - "Kappa;": '\U0000039A', - "Kcedil;": '\U00000136', - "Kcy;": '\U0000041A', - "Kfr;": '\U0001D50E', - "Kopf;": '\U0001D542', - "Kscr;": '\U0001D4A6', - "LJcy;": '\U00000409', - "LT;": '\U0000003C', - "Lacute;": '\U00000139', - "Lambda;": '\U0000039B', - "Lang;": '\U000027EA', - "Laplacetrf;": '\U00002112', - "Larr;": '\U0000219E', - "Lcaron;": '\U0000013D', - "Lcedil;": '\U0000013B', - "Lcy;": '\U0000041B', - "LeftAngleBracket;": '\U000027E8', - "LeftArrow;": '\U00002190', - "LeftArrowBar;": '\U000021E4', - "LeftArrowRightArrow;": '\U000021C6', - "LeftCeiling;": '\U00002308', - "LeftDoubleBracket;": '\U000027E6', - "LeftDownTeeVector;": '\U00002961', - "LeftDownVector;": '\U000021C3', - "LeftDownVectorBar;": '\U00002959', - "LeftFloor;": '\U0000230A', - "LeftRightArrow;": '\U00002194', - "LeftRightVector;": '\U0000294E', - "LeftTee;": '\U000022A3', - "LeftTeeArrow;": '\U000021A4', - "LeftTeeVector;": '\U0000295A', - "LeftTriangle;": '\U000022B2', - "LeftTriangleBar;": '\U000029CF', - "LeftTriangleEqual;": '\U000022B4', - "LeftUpDownVector;": '\U00002951', - "LeftUpTeeVector;": '\U00002960', - "LeftUpVector;": '\U000021BF', - "LeftUpVectorBar;": '\U00002958', - "LeftVector;": '\U000021BC', - "LeftVectorBar;": '\U00002952', - "Leftarrow;": '\U000021D0', - "Leftrightarrow;": '\U000021D4', - "LessEqualGreater;": '\U000022DA', - "LessFullEqual;": '\U00002266', - "LessGreater;": '\U00002276', - "LessLess;": '\U00002AA1', - "LessSlantEqual;": '\U00002A7D', - "LessTilde;": '\U00002272', - "Lfr;": '\U0001D50F', - "Ll;": '\U000022D8', - "Lleftarrow;": '\U000021DA', - "Lmidot;": '\U0000013F', - "LongLeftArrow;": '\U000027F5', - "LongLeftRightArrow;": '\U000027F7', - "LongRightArrow;": '\U000027F6', - "Longleftarrow;": '\U000027F8', - "Longleftrightarrow;": '\U000027FA', - "Longrightarrow;": '\U000027F9', - "Lopf;": '\U0001D543', - "LowerLeftArrow;": '\U00002199', - "LowerRightArrow;": '\U00002198', - "Lscr;": '\U00002112', - "Lsh;": '\U000021B0', - "Lstrok;": '\U00000141', - "Lt;": '\U0000226A', - "Map;": '\U00002905', - "Mcy;": '\U0000041C', - "MediumSpace;": '\U0000205F', - "Mellintrf;": '\U00002133', - "Mfr;": '\U0001D510', - "MinusPlus;": '\U00002213', - "Mopf;": '\U0001D544', - "Mscr;": '\U00002133', - "Mu;": '\U0000039C', - "NJcy;": '\U0000040A', - "Nacute;": '\U00000143', - "Ncaron;": '\U00000147', - "Ncedil;": '\U00000145', - "Ncy;": '\U0000041D', - "NegativeMediumSpace;": '\U0000200B', - "NegativeThickSpace;": '\U0000200B', - "NegativeThinSpace;": '\U0000200B', - "NegativeVeryThinSpace;": '\U0000200B', - "NestedGreaterGreater;": '\U0000226B', - "NestedLessLess;": '\U0000226A', - "NewLine;": '\U0000000A', - "Nfr;": '\U0001D511', - "NoBreak;": '\U00002060', - "NonBreakingSpace;": '\U000000A0', - "Nopf;": '\U00002115', - "Not;": '\U00002AEC', - "NotCongruent;": '\U00002262', - "NotCupCap;": '\U0000226D', - "NotDoubleVerticalBar;": '\U00002226', - "NotElement;": '\U00002209', - "NotEqual;": '\U00002260', - "NotExists;": '\U00002204', - "NotGreater;": '\U0000226F', - "NotGreaterEqual;": '\U00002271', - "NotGreaterLess;": '\U00002279', - "NotGreaterTilde;": '\U00002275', - "NotLeftTriangle;": '\U000022EA', - "NotLeftTriangleEqual;": '\U000022EC', - "NotLess;": '\U0000226E', - "NotLessEqual;": '\U00002270', - "NotLessGreater;": '\U00002278', - "NotLessTilde;": '\U00002274', - "NotPrecedes;": '\U00002280', - "NotPrecedesSlantEqual;": '\U000022E0', - "NotReverseElement;": '\U0000220C', - "NotRightTriangle;": '\U000022EB', - "NotRightTriangleEqual;": '\U000022ED', - "NotSquareSubsetEqual;": '\U000022E2', - "NotSquareSupersetEqual;": '\U000022E3', - "NotSubsetEqual;": '\U00002288', - "NotSucceeds;": '\U00002281', - "NotSucceedsSlantEqual;": '\U000022E1', - "NotSupersetEqual;": '\U00002289', - "NotTilde;": '\U00002241', - "NotTildeEqual;": '\U00002244', - "NotTildeFullEqual;": '\U00002247', - "NotTildeTilde;": '\U00002249', - "NotVerticalBar;": '\U00002224', - "Nscr;": '\U0001D4A9', - "Ntilde;": '\U000000D1', - "Nu;": '\U0000039D', - "OElig;": '\U00000152', - "Oacute;": '\U000000D3', - "Ocirc;": '\U000000D4', - "Ocy;": '\U0000041E', - "Odblac;": '\U00000150', - "Ofr;": '\U0001D512', - "Ograve;": '\U000000D2', - "Omacr;": '\U0000014C', - "Omega;": '\U000003A9', - "Omicron;": '\U0000039F', - "Oopf;": '\U0001D546', - "OpenCurlyDoubleQuote;": '\U0000201C', - "OpenCurlyQuote;": '\U00002018', - "Or;": '\U00002A54', - "Oscr;": '\U0001D4AA', - "Oslash;": '\U000000D8', - "Otilde;": '\U000000D5', - "Otimes;": '\U00002A37', - "Ouml;": '\U000000D6', - "OverBar;": '\U0000203E', - "OverBrace;": '\U000023DE', - "OverBracket;": '\U000023B4', - "OverParenthesis;": '\U000023DC', - "PartialD;": '\U00002202', - "Pcy;": '\U0000041F', - "Pfr;": '\U0001D513', - "Phi;": '\U000003A6', - "Pi;": '\U000003A0', - "PlusMinus;": '\U000000B1', - "Poincareplane;": '\U0000210C', - "Popf;": '\U00002119', - "Pr;": '\U00002ABB', - "Precedes;": '\U0000227A', - "PrecedesEqual;": '\U00002AAF', - "PrecedesSlantEqual;": '\U0000227C', - "PrecedesTilde;": '\U0000227E', - "Prime;": '\U00002033', - "Product;": '\U0000220F', - "Proportion;": '\U00002237', - "Proportional;": '\U0000221D', - "Pscr;": '\U0001D4AB', - "Psi;": '\U000003A8', - "QUOT;": '\U00000022', - "Qfr;": '\U0001D514', - "Qopf;": '\U0000211A', - "Qscr;": '\U0001D4AC', - "RBarr;": '\U00002910', - "REG;": '\U000000AE', - "Racute;": '\U00000154', - "Rang;": '\U000027EB', - "Rarr;": '\U000021A0', - "Rarrtl;": '\U00002916', - "Rcaron;": '\U00000158', - "Rcedil;": '\U00000156', - "Rcy;": '\U00000420', - "Re;": '\U0000211C', - "ReverseElement;": '\U0000220B', - "ReverseEquilibrium;": '\U000021CB', - "ReverseUpEquilibrium;": '\U0000296F', - "Rfr;": '\U0000211C', - "Rho;": '\U000003A1', - "RightAngleBracket;": '\U000027E9', - "RightArrow;": '\U00002192', - "RightArrowBar;": '\U000021E5', - "RightArrowLeftArrow;": '\U000021C4', - "RightCeiling;": '\U00002309', - "RightDoubleBracket;": '\U000027E7', - "RightDownTeeVector;": '\U0000295D', - "RightDownVector;": '\U000021C2', - "RightDownVectorBar;": '\U00002955', - "RightFloor;": '\U0000230B', - "RightTee;": '\U000022A2', - "RightTeeArrow;": '\U000021A6', - "RightTeeVector;": '\U0000295B', - "RightTriangle;": '\U000022B3', - "RightTriangleBar;": '\U000029D0', - "RightTriangleEqual;": '\U000022B5', - "RightUpDownVector;": '\U0000294F', - "RightUpTeeVector;": '\U0000295C', - "RightUpVector;": '\U000021BE', - "RightUpVectorBar;": '\U00002954', - "RightVector;": '\U000021C0', - "RightVectorBar;": '\U00002953', - "Rightarrow;": '\U000021D2', - "Ropf;": '\U0000211D', - "RoundImplies;": '\U00002970', - "Rrightarrow;": '\U000021DB', - "Rscr;": '\U0000211B', - "Rsh;": '\U000021B1', - "RuleDelayed;": '\U000029F4', - "SHCHcy;": '\U00000429', - "SHcy;": '\U00000428', - "SOFTcy;": '\U0000042C', - "Sacute;": '\U0000015A', - "Sc;": '\U00002ABC', - "Scaron;": '\U00000160', - "Scedil;": '\U0000015E', - "Scirc;": '\U0000015C', - "Scy;": '\U00000421', - "Sfr;": '\U0001D516', - "ShortDownArrow;": '\U00002193', - "ShortLeftArrow;": '\U00002190', - "ShortRightArrow;": '\U00002192', - "ShortUpArrow;": '\U00002191', - "Sigma;": '\U000003A3', - "SmallCircle;": '\U00002218', - "Sopf;": '\U0001D54A', - "Sqrt;": '\U0000221A', - "Square;": '\U000025A1', - "SquareIntersection;": '\U00002293', - "SquareSubset;": '\U0000228F', - "SquareSubsetEqual;": '\U00002291', - "SquareSuperset;": '\U00002290', - "SquareSupersetEqual;": '\U00002292', - "SquareUnion;": '\U00002294', - "Sscr;": '\U0001D4AE', - "Star;": '\U000022C6', - "Sub;": '\U000022D0', - "Subset;": '\U000022D0', - "SubsetEqual;": '\U00002286', - "Succeeds;": '\U0000227B', - "SucceedsEqual;": '\U00002AB0', - "SucceedsSlantEqual;": '\U0000227D', - "SucceedsTilde;": '\U0000227F', - "SuchThat;": '\U0000220B', - "Sum;": '\U00002211', - "Sup;": '\U000022D1', - "Superset;": '\U00002283', - "SupersetEqual;": '\U00002287', - "Supset;": '\U000022D1', - "THORN;": '\U000000DE', - "TRADE;": '\U00002122', - "TSHcy;": '\U0000040B', - "TScy;": '\U00000426', - "Tab;": '\U00000009', - "Tau;": '\U000003A4', - "Tcaron;": '\U00000164', - "Tcedil;": '\U00000162', - "Tcy;": '\U00000422', - "Tfr;": '\U0001D517', - "Therefore;": '\U00002234', - "Theta;": '\U00000398', - "ThinSpace;": '\U00002009', - "Tilde;": '\U0000223C', - "TildeEqual;": '\U00002243', - "TildeFullEqual;": '\U00002245', - "TildeTilde;": '\U00002248', - "Topf;": '\U0001D54B', - "TripleDot;": '\U000020DB', - "Tscr;": '\U0001D4AF', - "Tstrok;": '\U00000166', - "Uacute;": '\U000000DA', - "Uarr;": '\U0000219F', - "Uarrocir;": '\U00002949', - "Ubrcy;": '\U0000040E', - "Ubreve;": '\U0000016C', - "Ucirc;": '\U000000DB', - "Ucy;": '\U00000423', - "Udblac;": '\U00000170', - "Ufr;": '\U0001D518', - "Ugrave;": '\U000000D9', - "Umacr;": '\U0000016A', - "UnderBar;": '\U0000005F', - "UnderBrace;": '\U000023DF', - "UnderBracket;": '\U000023B5', - "UnderParenthesis;": '\U000023DD', - "Union;": '\U000022C3', - "UnionPlus;": '\U0000228E', - "Uogon;": '\U00000172', - "Uopf;": '\U0001D54C', - "UpArrow;": '\U00002191', - "UpArrowBar;": '\U00002912', - "UpArrowDownArrow;": '\U000021C5', - "UpDownArrow;": '\U00002195', - "UpEquilibrium;": '\U0000296E', - "UpTee;": '\U000022A5', - "UpTeeArrow;": '\U000021A5', - "Uparrow;": '\U000021D1', - "Updownarrow;": '\U000021D5', - "UpperLeftArrow;": '\U00002196', - "UpperRightArrow;": '\U00002197', - "Upsi;": '\U000003D2', - "Upsilon;": '\U000003A5', - "Uring;": '\U0000016E', - "Uscr;": '\U0001D4B0', - "Utilde;": '\U00000168', - "Uuml;": '\U000000DC', - "VDash;": '\U000022AB', - "Vbar;": '\U00002AEB', - "Vcy;": '\U00000412', - "Vdash;": '\U000022A9', - "Vdashl;": '\U00002AE6', - "Vee;": '\U000022C1', - "Verbar;": '\U00002016', - "Vert;": '\U00002016', - "VerticalBar;": '\U00002223', - "VerticalLine;": '\U0000007C', - "VerticalSeparator;": '\U00002758', - "VerticalTilde;": '\U00002240', - "VeryThinSpace;": '\U0000200A', - "Vfr;": '\U0001D519', - "Vopf;": '\U0001D54D', - "Vscr;": '\U0001D4B1', - "Vvdash;": '\U000022AA', - "Wcirc;": '\U00000174', - "Wedge;": '\U000022C0', - "Wfr;": '\U0001D51A', - "Wopf;": '\U0001D54E', - "Wscr;": '\U0001D4B2', - "Xfr;": '\U0001D51B', - "Xi;": '\U0000039E', - "Xopf;": '\U0001D54F', - "Xscr;": '\U0001D4B3', - "YAcy;": '\U0000042F', - "YIcy;": '\U00000407', - "YUcy;": '\U0000042E', - "Yacute;": '\U000000DD', - "Ycirc;": '\U00000176', - "Ycy;": '\U0000042B', - "Yfr;": '\U0001D51C', - "Yopf;": '\U0001D550', - "Yscr;": '\U0001D4B4', - "Yuml;": '\U00000178', - "ZHcy;": '\U00000416', - "Zacute;": '\U00000179', - "Zcaron;": '\U0000017D', - "Zcy;": '\U00000417', - "Zdot;": '\U0000017B', - "ZeroWidthSpace;": '\U0000200B', - "Zeta;": '\U00000396', - "Zfr;": '\U00002128', - "Zopf;": '\U00002124', - "Zscr;": '\U0001D4B5', - "aacute;": '\U000000E1', - "abreve;": '\U00000103', - "ac;": '\U0000223E', - "acd;": '\U0000223F', - "acirc;": '\U000000E2', - "acute;": '\U000000B4', - "acy;": '\U00000430', - "aelig;": '\U000000E6', - "af;": '\U00002061', - "afr;": '\U0001D51E', - "agrave;": '\U000000E0', - "alefsym;": '\U00002135', - "aleph;": '\U00002135', - "alpha;": '\U000003B1', - "amacr;": '\U00000101', - "amalg;": '\U00002A3F', - "amp;": '\U00000026', - "and;": '\U00002227', - "andand;": '\U00002A55', - "andd;": '\U00002A5C', - "andslope;": '\U00002A58', - "andv;": '\U00002A5A', - "ang;": '\U00002220', - "ange;": '\U000029A4', - "angle;": '\U00002220', - "angmsd;": '\U00002221', - "angmsdaa;": '\U000029A8', - "angmsdab;": '\U000029A9', - "angmsdac;": '\U000029AA', - "angmsdad;": '\U000029AB', - "angmsdae;": '\U000029AC', - "angmsdaf;": '\U000029AD', - "angmsdag;": '\U000029AE', - "angmsdah;": '\U000029AF', - "angrt;": '\U0000221F', - "angrtvb;": '\U000022BE', - "angrtvbd;": '\U0000299D', - "angsph;": '\U00002222', - "angst;": '\U000000C5', - "angzarr;": '\U0000237C', - "aogon;": '\U00000105', - "aopf;": '\U0001D552', - "ap;": '\U00002248', - "apE;": '\U00002A70', - "apacir;": '\U00002A6F', - "ape;": '\U0000224A', - "apid;": '\U0000224B', - "apos;": '\U00000027', - "approx;": '\U00002248', - "approxeq;": '\U0000224A', - "aring;": '\U000000E5', - "ascr;": '\U0001D4B6', - "ast;": '\U0000002A', - "asymp;": '\U00002248', - "asympeq;": '\U0000224D', - "atilde;": '\U000000E3', - "auml;": '\U000000E4', - "awconint;": '\U00002233', - "awint;": '\U00002A11', - "bNot;": '\U00002AED', - "backcong;": '\U0000224C', - "backepsilon;": '\U000003F6', - "backprime;": '\U00002035', - "backsim;": '\U0000223D', - "backsimeq;": '\U000022CD', - "barvee;": '\U000022BD', - "barwed;": '\U00002305', - "barwedge;": '\U00002305', - "bbrk;": '\U000023B5', - "bbrktbrk;": '\U000023B6', - "bcong;": '\U0000224C', - "bcy;": '\U00000431', - "bdquo;": '\U0000201E', - "becaus;": '\U00002235', - "because;": '\U00002235', - "bemptyv;": '\U000029B0', - "bepsi;": '\U000003F6', - "bernou;": '\U0000212C', - "beta;": '\U000003B2', - "beth;": '\U00002136', - "between;": '\U0000226C', - "bfr;": '\U0001D51F', - "bigcap;": '\U000022C2', - "bigcirc;": '\U000025EF', - "bigcup;": '\U000022C3', - "bigodot;": '\U00002A00', - "bigoplus;": '\U00002A01', - "bigotimes;": '\U00002A02', - "bigsqcup;": '\U00002A06', - "bigstar;": '\U00002605', - "bigtriangledown;": '\U000025BD', - "bigtriangleup;": '\U000025B3', - "biguplus;": '\U00002A04', - "bigvee;": '\U000022C1', - "bigwedge;": '\U000022C0', - "bkarow;": '\U0000290D', - "blacklozenge;": '\U000029EB', - "blacksquare;": '\U000025AA', - "blacktriangle;": '\U000025B4', - "blacktriangledown;": '\U000025BE', - "blacktriangleleft;": '\U000025C2', - "blacktriangleright;": '\U000025B8', - "blank;": '\U00002423', - "blk12;": '\U00002592', - "blk14;": '\U00002591', - "blk34;": '\U00002593', - "block;": '\U00002588', - "bnot;": '\U00002310', - "bopf;": '\U0001D553', - "bot;": '\U000022A5', - "bottom;": '\U000022A5', - "bowtie;": '\U000022C8', - "boxDL;": '\U00002557', - "boxDR;": '\U00002554', - "boxDl;": '\U00002556', - "boxDr;": '\U00002553', - "boxH;": '\U00002550', - "boxHD;": '\U00002566', - "boxHU;": '\U00002569', - "boxHd;": '\U00002564', - "boxHu;": '\U00002567', - "boxUL;": '\U0000255D', - "boxUR;": '\U0000255A', - "boxUl;": '\U0000255C', - "boxUr;": '\U00002559', - "boxV;": '\U00002551', - "boxVH;": '\U0000256C', - "boxVL;": '\U00002563', - "boxVR;": '\U00002560', - "boxVh;": '\U0000256B', - "boxVl;": '\U00002562', - "boxVr;": '\U0000255F', - "boxbox;": '\U000029C9', - "boxdL;": '\U00002555', - "boxdR;": '\U00002552', - "boxdl;": '\U00002510', - "boxdr;": '\U0000250C', - "boxh;": '\U00002500', - "boxhD;": '\U00002565', - "boxhU;": '\U00002568', - "boxhd;": '\U0000252C', - "boxhu;": '\U00002534', - "boxminus;": '\U0000229F', - "boxplus;": '\U0000229E', - "boxtimes;": '\U000022A0', - "boxuL;": '\U0000255B', - "boxuR;": '\U00002558', - "boxul;": '\U00002518', - "boxur;": '\U00002514', - "boxv;": '\U00002502', - "boxvH;": '\U0000256A', - "boxvL;": '\U00002561', - "boxvR;": '\U0000255E', - "boxvh;": '\U0000253C', - "boxvl;": '\U00002524', - "boxvr;": '\U0000251C', - "bprime;": '\U00002035', - "breve;": '\U000002D8', - "brvbar;": '\U000000A6', - "bscr;": '\U0001D4B7', - "bsemi;": '\U0000204F', - "bsim;": '\U0000223D', - "bsime;": '\U000022CD', - "bsol;": '\U0000005C', - "bsolb;": '\U000029C5', - "bsolhsub;": '\U000027C8', - "bull;": '\U00002022', - "bullet;": '\U00002022', - "bump;": '\U0000224E', - "bumpE;": '\U00002AAE', - "bumpe;": '\U0000224F', - "bumpeq;": '\U0000224F', - "cacute;": '\U00000107', - "cap;": '\U00002229', - "capand;": '\U00002A44', - "capbrcup;": '\U00002A49', - "capcap;": '\U00002A4B', - "capcup;": '\U00002A47', - "capdot;": '\U00002A40', - "caret;": '\U00002041', - "caron;": '\U000002C7', - "ccaps;": '\U00002A4D', - "ccaron;": '\U0000010D', - "ccedil;": '\U000000E7', - "ccirc;": '\U00000109', - "ccups;": '\U00002A4C', - "ccupssm;": '\U00002A50', - "cdot;": '\U0000010B', - "cedil;": '\U000000B8', - "cemptyv;": '\U000029B2', - "cent;": '\U000000A2', - "centerdot;": '\U000000B7', - "cfr;": '\U0001D520', - "chcy;": '\U00000447', - "check;": '\U00002713', - "checkmark;": '\U00002713', - "chi;": '\U000003C7', - "cir;": '\U000025CB', - "cirE;": '\U000029C3', - "circ;": '\U000002C6', - "circeq;": '\U00002257', - "circlearrowleft;": '\U000021BA', - "circlearrowright;": '\U000021BB', - "circledR;": '\U000000AE', - "circledS;": '\U000024C8', - "circledast;": '\U0000229B', - "circledcirc;": '\U0000229A', - "circleddash;": '\U0000229D', - "cire;": '\U00002257', - "cirfnint;": '\U00002A10', - "cirmid;": '\U00002AEF', - "cirscir;": '\U000029C2', - "clubs;": '\U00002663', - "clubsuit;": '\U00002663', - "colon;": '\U0000003A', - "colone;": '\U00002254', - "coloneq;": '\U00002254', - "comma;": '\U0000002C', - "commat;": '\U00000040', - "comp;": '\U00002201', - "compfn;": '\U00002218', - "complement;": '\U00002201', - "complexes;": '\U00002102', - "cong;": '\U00002245', - "congdot;": '\U00002A6D', - "conint;": '\U0000222E', - "copf;": '\U0001D554', - "coprod;": '\U00002210', - "copy;": '\U000000A9', - "copysr;": '\U00002117', - "crarr;": '\U000021B5', - "cross;": '\U00002717', - "cscr;": '\U0001D4B8', - "csub;": '\U00002ACF', - "csube;": '\U00002AD1', - "csup;": '\U00002AD0', - "csupe;": '\U00002AD2', - "ctdot;": '\U000022EF', - "cudarrl;": '\U00002938', - "cudarrr;": '\U00002935', - "cuepr;": '\U000022DE', - "cuesc;": '\U000022DF', - "cularr;": '\U000021B6', - "cularrp;": '\U0000293D', - "cup;": '\U0000222A', - "cupbrcap;": '\U00002A48', - "cupcap;": '\U00002A46', - "cupcup;": '\U00002A4A', - "cupdot;": '\U0000228D', - "cupor;": '\U00002A45', - "curarr;": '\U000021B7', - "curarrm;": '\U0000293C', - "curlyeqprec;": '\U000022DE', - "curlyeqsucc;": '\U000022DF', - "curlyvee;": '\U000022CE', - "curlywedge;": '\U000022CF', - "curren;": '\U000000A4', - "curvearrowleft;": '\U000021B6', - "curvearrowright;": '\U000021B7', - "cuvee;": '\U000022CE', - "cuwed;": '\U000022CF', - "cwconint;": '\U00002232', - "cwint;": '\U00002231', - "cylcty;": '\U0000232D', - "dArr;": '\U000021D3', - "dHar;": '\U00002965', - "dagger;": '\U00002020', - "daleth;": '\U00002138', - "darr;": '\U00002193', - "dash;": '\U00002010', - "dashv;": '\U000022A3', - "dbkarow;": '\U0000290F', - "dblac;": '\U000002DD', - "dcaron;": '\U0000010F', - "dcy;": '\U00000434', - "dd;": '\U00002146', - "ddagger;": '\U00002021', - "ddarr;": '\U000021CA', - "ddotseq;": '\U00002A77', - "deg;": '\U000000B0', - "delta;": '\U000003B4', - "demptyv;": '\U000029B1', - "dfisht;": '\U0000297F', - "dfr;": '\U0001D521', - "dharl;": '\U000021C3', - "dharr;": '\U000021C2', - "diam;": '\U000022C4', - "diamond;": '\U000022C4', - "diamondsuit;": '\U00002666', - "diams;": '\U00002666', - "die;": '\U000000A8', - "digamma;": '\U000003DD', - "disin;": '\U000022F2', - "div;": '\U000000F7', - "divide;": '\U000000F7', - "divideontimes;": '\U000022C7', - "divonx;": '\U000022C7', - "djcy;": '\U00000452', - "dlcorn;": '\U0000231E', - "dlcrop;": '\U0000230D', - "dollar;": '\U00000024', - "dopf;": '\U0001D555', - "dot;": '\U000002D9', - "doteq;": '\U00002250', - "doteqdot;": '\U00002251', - "dotminus;": '\U00002238', - "dotplus;": '\U00002214', - "dotsquare;": '\U000022A1', - "doublebarwedge;": '\U00002306', - "downarrow;": '\U00002193', - "downdownarrows;": '\U000021CA', - "downharpoonleft;": '\U000021C3', - "downharpoonright;": '\U000021C2', - "drbkarow;": '\U00002910', - "drcorn;": '\U0000231F', - "drcrop;": '\U0000230C', - "dscr;": '\U0001D4B9', - "dscy;": '\U00000455', - "dsol;": '\U000029F6', - "dstrok;": '\U00000111', - "dtdot;": '\U000022F1', - "dtri;": '\U000025BF', - "dtrif;": '\U000025BE', - "duarr;": '\U000021F5', - "duhar;": '\U0000296F', - "dwangle;": '\U000029A6', - "dzcy;": '\U0000045F', - "dzigrarr;": '\U000027FF', - "eDDot;": '\U00002A77', - "eDot;": '\U00002251', - "eacute;": '\U000000E9', - "easter;": '\U00002A6E', - "ecaron;": '\U0000011B', - "ecir;": '\U00002256', - "ecirc;": '\U000000EA', - "ecolon;": '\U00002255', - "ecy;": '\U0000044D', - "edot;": '\U00000117', - "ee;": '\U00002147', - "efDot;": '\U00002252', - "efr;": '\U0001D522', - "eg;": '\U00002A9A', - "egrave;": '\U000000E8', - "egs;": '\U00002A96', - "egsdot;": '\U00002A98', - "el;": '\U00002A99', - "elinters;": '\U000023E7', - "ell;": '\U00002113', - "els;": '\U00002A95', - "elsdot;": '\U00002A97', - "emacr;": '\U00000113', - "empty;": '\U00002205', - "emptyset;": '\U00002205', - "emptyv;": '\U00002205', - "emsp;": '\U00002003', - "emsp13;": '\U00002004', - "emsp14;": '\U00002005', - "eng;": '\U0000014B', - "ensp;": '\U00002002', - "eogon;": '\U00000119', - "eopf;": '\U0001D556', - "epar;": '\U000022D5', - "eparsl;": '\U000029E3', - "eplus;": '\U00002A71', - "epsi;": '\U000003B5', - "epsilon;": '\U000003B5', - "epsiv;": '\U000003F5', - "eqcirc;": '\U00002256', - "eqcolon;": '\U00002255', - "eqsim;": '\U00002242', - "eqslantgtr;": '\U00002A96', - "eqslantless;": '\U00002A95', - "equals;": '\U0000003D', - "equest;": '\U0000225F', - "equiv;": '\U00002261', - "equivDD;": '\U00002A78', - "eqvparsl;": '\U000029E5', - "erDot;": '\U00002253', - "erarr;": '\U00002971', - "escr;": '\U0000212F', - "esdot;": '\U00002250', - "esim;": '\U00002242', - "eta;": '\U000003B7', - "eth;": '\U000000F0', - "euml;": '\U000000EB', - "euro;": '\U000020AC', - "excl;": '\U00000021', - "exist;": '\U00002203', - "expectation;": '\U00002130', - "exponentiale;": '\U00002147', - "fallingdotseq;": '\U00002252', - "fcy;": '\U00000444', - "female;": '\U00002640', - "ffilig;": '\U0000FB03', - "fflig;": '\U0000FB00', - "ffllig;": '\U0000FB04', - "ffr;": '\U0001D523', - "filig;": '\U0000FB01', - "flat;": '\U0000266D', - "fllig;": '\U0000FB02', - "fltns;": '\U000025B1', - "fnof;": '\U00000192', - "fopf;": '\U0001D557', - "forall;": '\U00002200', - "fork;": '\U000022D4', - "forkv;": '\U00002AD9', - "fpartint;": '\U00002A0D', - "frac12;": '\U000000BD', - "frac13;": '\U00002153', - "frac14;": '\U000000BC', - "frac15;": '\U00002155', - "frac16;": '\U00002159', - "frac18;": '\U0000215B', - "frac23;": '\U00002154', - "frac25;": '\U00002156', - "frac34;": '\U000000BE', - "frac35;": '\U00002157', - "frac38;": '\U0000215C', - "frac45;": '\U00002158', - "frac56;": '\U0000215A', - "frac58;": '\U0000215D', - "frac78;": '\U0000215E', - "frasl;": '\U00002044', - "frown;": '\U00002322', - "fscr;": '\U0001D4BB', - "gE;": '\U00002267', - "gEl;": '\U00002A8C', - "gacute;": '\U000001F5', - "gamma;": '\U000003B3', - "gammad;": '\U000003DD', - "gap;": '\U00002A86', - "gbreve;": '\U0000011F', - "gcirc;": '\U0000011D', - "gcy;": '\U00000433', - "gdot;": '\U00000121', - "ge;": '\U00002265', - "gel;": '\U000022DB', - "geq;": '\U00002265', - "geqq;": '\U00002267', - "geqslant;": '\U00002A7E', - "ges;": '\U00002A7E', - "gescc;": '\U00002AA9', - "gesdot;": '\U00002A80', - "gesdoto;": '\U00002A82', - "gesdotol;": '\U00002A84', - "gesles;": '\U00002A94', - "gfr;": '\U0001D524', - "gg;": '\U0000226B', - "ggg;": '\U000022D9', - "gimel;": '\U00002137', - "gjcy;": '\U00000453', - "gl;": '\U00002277', - "glE;": '\U00002A92', - "gla;": '\U00002AA5', - "glj;": '\U00002AA4', - "gnE;": '\U00002269', - "gnap;": '\U00002A8A', - "gnapprox;": '\U00002A8A', - "gne;": '\U00002A88', - "gneq;": '\U00002A88', - "gneqq;": '\U00002269', - "gnsim;": '\U000022E7', - "gopf;": '\U0001D558', - "grave;": '\U00000060', - "gscr;": '\U0000210A', - "gsim;": '\U00002273', - "gsime;": '\U00002A8E', - "gsiml;": '\U00002A90', - "gt;": '\U0000003E', - "gtcc;": '\U00002AA7', - "gtcir;": '\U00002A7A', - "gtdot;": '\U000022D7', - "gtlPar;": '\U00002995', - "gtquest;": '\U00002A7C', - "gtrapprox;": '\U00002A86', - "gtrarr;": '\U00002978', - "gtrdot;": '\U000022D7', - "gtreqless;": '\U000022DB', - "gtreqqless;": '\U00002A8C', - "gtrless;": '\U00002277', - "gtrsim;": '\U00002273', - "hArr;": '\U000021D4', - "hairsp;": '\U0000200A', - "half;": '\U000000BD', - "hamilt;": '\U0000210B', - "hardcy;": '\U0000044A', - "harr;": '\U00002194', - "harrcir;": '\U00002948', - "harrw;": '\U000021AD', - "hbar;": '\U0000210F', - "hcirc;": '\U00000125', - "hearts;": '\U00002665', - "heartsuit;": '\U00002665', - "hellip;": '\U00002026', - "hercon;": '\U000022B9', - "hfr;": '\U0001D525', - "hksearow;": '\U00002925', - "hkswarow;": '\U00002926', - "hoarr;": '\U000021FF', - "homtht;": '\U0000223B', - "hookleftarrow;": '\U000021A9', - "hookrightarrow;": '\U000021AA', - "hopf;": '\U0001D559', - "horbar;": '\U00002015', - "hscr;": '\U0001D4BD', - "hslash;": '\U0000210F', - "hstrok;": '\U00000127', - "hybull;": '\U00002043', - "hyphen;": '\U00002010', - "iacute;": '\U000000ED', - "ic;": '\U00002063', - "icirc;": '\U000000EE', - "icy;": '\U00000438', - "iecy;": '\U00000435', - "iexcl;": '\U000000A1', - "iff;": '\U000021D4', - "ifr;": '\U0001D526', - "igrave;": '\U000000EC', - "ii;": '\U00002148', - "iiiint;": '\U00002A0C', - "iiint;": '\U0000222D', - "iinfin;": '\U000029DC', - "iiota;": '\U00002129', - "ijlig;": '\U00000133', - "imacr;": '\U0000012B', - "image;": '\U00002111', - "imagline;": '\U00002110', - "imagpart;": '\U00002111', - "imath;": '\U00000131', - "imof;": '\U000022B7', - "imped;": '\U000001B5', - "in;": '\U00002208', - "incare;": '\U00002105', - "infin;": '\U0000221E', - "infintie;": '\U000029DD', - "inodot;": '\U00000131', - "int;": '\U0000222B', - "intcal;": '\U000022BA', - "integers;": '\U00002124', - "intercal;": '\U000022BA', - "intlarhk;": '\U00002A17', - "intprod;": '\U00002A3C', - "iocy;": '\U00000451', - "iogon;": '\U0000012F', - "iopf;": '\U0001D55A', - "iota;": '\U000003B9', - "iprod;": '\U00002A3C', - "iquest;": '\U000000BF', - "iscr;": '\U0001D4BE', - "isin;": '\U00002208', - "isinE;": '\U000022F9', - "isindot;": '\U000022F5', - "isins;": '\U000022F4', - "isinsv;": '\U000022F3', - "isinv;": '\U00002208', - "it;": '\U00002062', - "itilde;": '\U00000129', - "iukcy;": '\U00000456', - "iuml;": '\U000000EF', - "jcirc;": '\U00000135', - "jcy;": '\U00000439', - "jfr;": '\U0001D527', - "jmath;": '\U00000237', - "jopf;": '\U0001D55B', - "jscr;": '\U0001D4BF', - "jsercy;": '\U00000458', - "jukcy;": '\U00000454', - "kappa;": '\U000003BA', - "kappav;": '\U000003F0', - "kcedil;": '\U00000137', - "kcy;": '\U0000043A', - "kfr;": '\U0001D528', - "kgreen;": '\U00000138', - "khcy;": '\U00000445', - "kjcy;": '\U0000045C', - "kopf;": '\U0001D55C', - "kscr;": '\U0001D4C0', - "lAarr;": '\U000021DA', - "lArr;": '\U000021D0', - "lAtail;": '\U0000291B', - "lBarr;": '\U0000290E', - "lE;": '\U00002266', - "lEg;": '\U00002A8B', - "lHar;": '\U00002962', - "lacute;": '\U0000013A', - "laemptyv;": '\U000029B4', - "lagran;": '\U00002112', - "lambda;": '\U000003BB', - "lang;": '\U000027E8', - "langd;": '\U00002991', - "langle;": '\U000027E8', - "lap;": '\U00002A85', - "laquo;": '\U000000AB', - "larr;": '\U00002190', - "larrb;": '\U000021E4', - "larrbfs;": '\U0000291F', - "larrfs;": '\U0000291D', - "larrhk;": '\U000021A9', - "larrlp;": '\U000021AB', - "larrpl;": '\U00002939', - "larrsim;": '\U00002973', - "larrtl;": '\U000021A2', - "lat;": '\U00002AAB', - "latail;": '\U00002919', - "late;": '\U00002AAD', - "lbarr;": '\U0000290C', - "lbbrk;": '\U00002772', - "lbrace;": '\U0000007B', - "lbrack;": '\U0000005B', - "lbrke;": '\U0000298B', - "lbrksld;": '\U0000298F', - "lbrkslu;": '\U0000298D', - "lcaron;": '\U0000013E', - "lcedil;": '\U0000013C', - "lceil;": '\U00002308', - "lcub;": '\U0000007B', - "lcy;": '\U0000043B', - "ldca;": '\U00002936', - "ldquo;": '\U0000201C', - "ldquor;": '\U0000201E', - "ldrdhar;": '\U00002967', - "ldrushar;": '\U0000294B', - "ldsh;": '\U000021B2', - "le;": '\U00002264', - "leftarrow;": '\U00002190', - "leftarrowtail;": '\U000021A2', - "leftharpoondown;": '\U000021BD', - "leftharpoonup;": '\U000021BC', - "leftleftarrows;": '\U000021C7', - "leftrightarrow;": '\U00002194', - "leftrightarrows;": '\U000021C6', - "leftrightharpoons;": '\U000021CB', - "leftrightsquigarrow;": '\U000021AD', - "leftthreetimes;": '\U000022CB', - "leg;": '\U000022DA', - "leq;": '\U00002264', - "leqq;": '\U00002266', - "leqslant;": '\U00002A7D', - "les;": '\U00002A7D', - "lescc;": '\U00002AA8', - "lesdot;": '\U00002A7F', - "lesdoto;": '\U00002A81', - "lesdotor;": '\U00002A83', - "lesges;": '\U00002A93', - "lessapprox;": '\U00002A85', - "lessdot;": '\U000022D6', - "lesseqgtr;": '\U000022DA', - "lesseqqgtr;": '\U00002A8B', - "lessgtr;": '\U00002276', - "lesssim;": '\U00002272', - "lfisht;": '\U0000297C', - "lfloor;": '\U0000230A', - "lfr;": '\U0001D529', - "lg;": '\U00002276', - "lgE;": '\U00002A91', - "lhard;": '\U000021BD', - "lharu;": '\U000021BC', - "lharul;": '\U0000296A', - "lhblk;": '\U00002584', - "ljcy;": '\U00000459', - "ll;": '\U0000226A', - "llarr;": '\U000021C7', - "llcorner;": '\U0000231E', - "llhard;": '\U0000296B', - "lltri;": '\U000025FA', - "lmidot;": '\U00000140', - "lmoust;": '\U000023B0', - "lmoustache;": '\U000023B0', - "lnE;": '\U00002268', - "lnap;": '\U00002A89', - "lnapprox;": '\U00002A89', - "lne;": '\U00002A87', - "lneq;": '\U00002A87', - "lneqq;": '\U00002268', - "lnsim;": '\U000022E6', - "loang;": '\U000027EC', - "loarr;": '\U000021FD', - "lobrk;": '\U000027E6', - "longleftarrow;": '\U000027F5', - "longleftrightarrow;": '\U000027F7', - "longmapsto;": '\U000027FC', - "longrightarrow;": '\U000027F6', - "looparrowleft;": '\U000021AB', - "looparrowright;": '\U000021AC', - "lopar;": '\U00002985', - "lopf;": '\U0001D55D', - "loplus;": '\U00002A2D', - "lotimes;": '\U00002A34', - "lowast;": '\U00002217', - "lowbar;": '\U0000005F', - "loz;": '\U000025CA', - "lozenge;": '\U000025CA', - "lozf;": '\U000029EB', - "lpar;": '\U00000028', - "lparlt;": '\U00002993', - "lrarr;": '\U000021C6', - "lrcorner;": '\U0000231F', - "lrhar;": '\U000021CB', - "lrhard;": '\U0000296D', - "lrm;": '\U0000200E', - "lrtri;": '\U000022BF', - "lsaquo;": '\U00002039', - "lscr;": '\U0001D4C1', - "lsh;": '\U000021B0', - "lsim;": '\U00002272', - "lsime;": '\U00002A8D', - "lsimg;": '\U00002A8F', - "lsqb;": '\U0000005B', - "lsquo;": '\U00002018', - "lsquor;": '\U0000201A', - "lstrok;": '\U00000142', - "lt;": '\U0000003C', - "ltcc;": '\U00002AA6', - "ltcir;": '\U00002A79', - "ltdot;": '\U000022D6', - "lthree;": '\U000022CB', - "ltimes;": '\U000022C9', - "ltlarr;": '\U00002976', - "ltquest;": '\U00002A7B', - "ltrPar;": '\U00002996', - "ltri;": '\U000025C3', - "ltrie;": '\U000022B4', - "ltrif;": '\U000025C2', - "lurdshar;": '\U0000294A', - "luruhar;": '\U00002966', - "mDDot;": '\U0000223A', - "macr;": '\U000000AF', - "male;": '\U00002642', - "malt;": '\U00002720', - "maltese;": '\U00002720', - "map;": '\U000021A6', - "mapsto;": '\U000021A6', - "mapstodown;": '\U000021A7', - "mapstoleft;": '\U000021A4', - "mapstoup;": '\U000021A5', - "marker;": '\U000025AE', - "mcomma;": '\U00002A29', - "mcy;": '\U0000043C', - "mdash;": '\U00002014', - "measuredangle;": '\U00002221', - "mfr;": '\U0001D52A', - "mho;": '\U00002127', - "micro;": '\U000000B5', - "mid;": '\U00002223', - "midast;": '\U0000002A', - "midcir;": '\U00002AF0', - "middot;": '\U000000B7', - "minus;": '\U00002212', - "minusb;": '\U0000229F', - "minusd;": '\U00002238', - "minusdu;": '\U00002A2A', - "mlcp;": '\U00002ADB', - "mldr;": '\U00002026', - "mnplus;": '\U00002213', - "models;": '\U000022A7', - "mopf;": '\U0001D55E', - "mp;": '\U00002213', - "mscr;": '\U0001D4C2', - "mstpos;": '\U0000223E', - "mu;": '\U000003BC', - "multimap;": '\U000022B8', - "mumap;": '\U000022B8', - "nLeftarrow;": '\U000021CD', - "nLeftrightarrow;": '\U000021CE', - "nRightarrow;": '\U000021CF', - "nVDash;": '\U000022AF', - "nVdash;": '\U000022AE', - "nabla;": '\U00002207', - "nacute;": '\U00000144', - "nap;": '\U00002249', - "napos;": '\U00000149', - "napprox;": '\U00002249', - "natur;": '\U0000266E', - "natural;": '\U0000266E', - "naturals;": '\U00002115', - "nbsp;": '\U000000A0', - "ncap;": '\U00002A43', - "ncaron;": '\U00000148', - "ncedil;": '\U00000146', - "ncong;": '\U00002247', - "ncup;": '\U00002A42', - "ncy;": '\U0000043D', - "ndash;": '\U00002013', - "ne;": '\U00002260', - "neArr;": '\U000021D7', - "nearhk;": '\U00002924', - "nearr;": '\U00002197', - "nearrow;": '\U00002197', - "nequiv;": '\U00002262', - "nesear;": '\U00002928', - "nexist;": '\U00002204', - "nexists;": '\U00002204', - "nfr;": '\U0001D52B', - "nge;": '\U00002271', - "ngeq;": '\U00002271', - "ngsim;": '\U00002275', - "ngt;": '\U0000226F', - "ngtr;": '\U0000226F', - "nhArr;": '\U000021CE', - "nharr;": '\U000021AE', - "nhpar;": '\U00002AF2', - "ni;": '\U0000220B', - "nis;": '\U000022FC', - "nisd;": '\U000022FA', - "niv;": '\U0000220B', - "njcy;": '\U0000045A', - "nlArr;": '\U000021CD', - "nlarr;": '\U0000219A', - "nldr;": '\U00002025', - "nle;": '\U00002270', - "nleftarrow;": '\U0000219A', - "nleftrightarrow;": '\U000021AE', - "nleq;": '\U00002270', - "nless;": '\U0000226E', - "nlsim;": '\U00002274', - "nlt;": '\U0000226E', - "nltri;": '\U000022EA', - "nltrie;": '\U000022EC', - "nmid;": '\U00002224', - "nopf;": '\U0001D55F', - "not;": '\U000000AC', - "notin;": '\U00002209', - "notinva;": '\U00002209', - "notinvb;": '\U000022F7', - "notinvc;": '\U000022F6', - "notni;": '\U0000220C', - "notniva;": '\U0000220C', - "notnivb;": '\U000022FE', - "notnivc;": '\U000022FD', - "npar;": '\U00002226', - "nparallel;": '\U00002226', - "npolint;": '\U00002A14', - "npr;": '\U00002280', - "nprcue;": '\U000022E0', - "nprec;": '\U00002280', - "nrArr;": '\U000021CF', - "nrarr;": '\U0000219B', - "nrightarrow;": '\U0000219B', - "nrtri;": '\U000022EB', - "nrtrie;": '\U000022ED', - "nsc;": '\U00002281', - "nsccue;": '\U000022E1', - "nscr;": '\U0001D4C3', - "nshortmid;": '\U00002224', - "nshortparallel;": '\U00002226', - "nsim;": '\U00002241', - "nsime;": '\U00002244', - "nsimeq;": '\U00002244', - "nsmid;": '\U00002224', - "nspar;": '\U00002226', - "nsqsube;": '\U000022E2', - "nsqsupe;": '\U000022E3', - "nsub;": '\U00002284', - "nsube;": '\U00002288', - "nsubseteq;": '\U00002288', - "nsucc;": '\U00002281', - "nsup;": '\U00002285', - "nsupe;": '\U00002289', - "nsupseteq;": '\U00002289', - "ntgl;": '\U00002279', - "ntilde;": '\U000000F1', - "ntlg;": '\U00002278', - "ntriangleleft;": '\U000022EA', - "ntrianglelefteq;": '\U000022EC', - "ntriangleright;": '\U000022EB', - "ntrianglerighteq;": '\U000022ED', - "nu;": '\U000003BD', - "num;": '\U00000023', - "numero;": '\U00002116', - "numsp;": '\U00002007', - "nvDash;": '\U000022AD', - "nvHarr;": '\U00002904', - "nvdash;": '\U000022AC', - "nvinfin;": '\U000029DE', - "nvlArr;": '\U00002902', - "nvrArr;": '\U00002903', - "nwArr;": '\U000021D6', - "nwarhk;": '\U00002923', - "nwarr;": '\U00002196', - "nwarrow;": '\U00002196', - "nwnear;": '\U00002927', - "oS;": '\U000024C8', - "oacute;": '\U000000F3', - "oast;": '\U0000229B', - "ocir;": '\U0000229A', - "ocirc;": '\U000000F4', - "ocy;": '\U0000043E', - "odash;": '\U0000229D', - "odblac;": '\U00000151', - "odiv;": '\U00002A38', - "odot;": '\U00002299', - "odsold;": '\U000029BC', - "oelig;": '\U00000153', - "ofcir;": '\U000029BF', - "ofr;": '\U0001D52C', - "ogon;": '\U000002DB', - "ograve;": '\U000000F2', - "ogt;": '\U000029C1', - "ohbar;": '\U000029B5', - "ohm;": '\U000003A9', - "oint;": '\U0000222E', - "olarr;": '\U000021BA', - "olcir;": '\U000029BE', - "olcross;": '\U000029BB', - "oline;": '\U0000203E', - "olt;": '\U000029C0', - "omacr;": '\U0000014D', - "omega;": '\U000003C9', - "omicron;": '\U000003BF', - "omid;": '\U000029B6', - "ominus;": '\U00002296', - "oopf;": '\U0001D560', - "opar;": '\U000029B7', - "operp;": '\U000029B9', - "oplus;": '\U00002295', - "or;": '\U00002228', - "orarr;": '\U000021BB', - "ord;": '\U00002A5D', - "order;": '\U00002134', - "orderof;": '\U00002134', - "ordf;": '\U000000AA', - "ordm;": '\U000000BA', - "origof;": '\U000022B6', - "oror;": '\U00002A56', - "orslope;": '\U00002A57', - "orv;": '\U00002A5B', - "oscr;": '\U00002134', - "oslash;": '\U000000F8', - "osol;": '\U00002298', - "otilde;": '\U000000F5', - "otimes;": '\U00002297', - "otimesas;": '\U00002A36', - "ouml;": '\U000000F6', - "ovbar;": '\U0000233D', - "par;": '\U00002225', - "para;": '\U000000B6', - "parallel;": '\U00002225', - "parsim;": '\U00002AF3', - "parsl;": '\U00002AFD', - "part;": '\U00002202', - "pcy;": '\U0000043F', - "percnt;": '\U00000025', - "period;": '\U0000002E', - "permil;": '\U00002030', - "perp;": '\U000022A5', - "pertenk;": '\U00002031', - "pfr;": '\U0001D52D', - "phi;": '\U000003C6', - "phiv;": '\U000003D5', - "phmmat;": '\U00002133', - "phone;": '\U0000260E', - "pi;": '\U000003C0', - "pitchfork;": '\U000022D4', - "piv;": '\U000003D6', - "planck;": '\U0000210F', - "planckh;": '\U0000210E', - "plankv;": '\U0000210F', - "plus;": '\U0000002B', - "plusacir;": '\U00002A23', - "plusb;": '\U0000229E', - "pluscir;": '\U00002A22', - "plusdo;": '\U00002214', - "plusdu;": '\U00002A25', - "pluse;": '\U00002A72', - "plusmn;": '\U000000B1', - "plussim;": '\U00002A26', - "plustwo;": '\U00002A27', - "pm;": '\U000000B1', - "pointint;": '\U00002A15', - "popf;": '\U0001D561', - "pound;": '\U000000A3', - "pr;": '\U0000227A', - "prE;": '\U00002AB3', - "prap;": '\U00002AB7', - "prcue;": '\U0000227C', - "pre;": '\U00002AAF', - "prec;": '\U0000227A', - "precapprox;": '\U00002AB7', - "preccurlyeq;": '\U0000227C', - "preceq;": '\U00002AAF', - "precnapprox;": '\U00002AB9', - "precneqq;": '\U00002AB5', - "precnsim;": '\U000022E8', - "precsim;": '\U0000227E', - "prime;": '\U00002032', - "primes;": '\U00002119', - "prnE;": '\U00002AB5', - "prnap;": '\U00002AB9', - "prnsim;": '\U000022E8', - "prod;": '\U0000220F', - "profalar;": '\U0000232E', - "profline;": '\U00002312', - "profsurf;": '\U00002313', - "prop;": '\U0000221D', - "propto;": '\U0000221D', - "prsim;": '\U0000227E', - "prurel;": '\U000022B0', - "pscr;": '\U0001D4C5', - "psi;": '\U000003C8', - "puncsp;": '\U00002008', - "qfr;": '\U0001D52E', - "qint;": '\U00002A0C', - "qopf;": '\U0001D562', - "qprime;": '\U00002057', - "qscr;": '\U0001D4C6', - "quaternions;": '\U0000210D', - "quatint;": '\U00002A16', - "quest;": '\U0000003F', - "questeq;": '\U0000225F', - "quot;": '\U00000022', - "rAarr;": '\U000021DB', - "rArr;": '\U000021D2', - "rAtail;": '\U0000291C', - "rBarr;": '\U0000290F', - "rHar;": '\U00002964', - "racute;": '\U00000155', - "radic;": '\U0000221A', - "raemptyv;": '\U000029B3', - "rang;": '\U000027E9', - "rangd;": '\U00002992', - "range;": '\U000029A5', - "rangle;": '\U000027E9', - "raquo;": '\U000000BB', - "rarr;": '\U00002192', - "rarrap;": '\U00002975', - "rarrb;": '\U000021E5', - "rarrbfs;": '\U00002920', - "rarrc;": '\U00002933', - "rarrfs;": '\U0000291E', - "rarrhk;": '\U000021AA', - "rarrlp;": '\U000021AC', - "rarrpl;": '\U00002945', - "rarrsim;": '\U00002974', - "rarrtl;": '\U000021A3', - "rarrw;": '\U0000219D', - "ratail;": '\U0000291A', - "ratio;": '\U00002236', - "rationals;": '\U0000211A', - "rbarr;": '\U0000290D', - "rbbrk;": '\U00002773', - "rbrace;": '\U0000007D', - "rbrack;": '\U0000005D', - "rbrke;": '\U0000298C', - "rbrksld;": '\U0000298E', - "rbrkslu;": '\U00002990', - "rcaron;": '\U00000159', - "rcedil;": '\U00000157', - "rceil;": '\U00002309', - "rcub;": '\U0000007D', - "rcy;": '\U00000440', - "rdca;": '\U00002937', - "rdldhar;": '\U00002969', - "rdquo;": '\U0000201D', - "rdquor;": '\U0000201D', - "rdsh;": '\U000021B3', - "real;": '\U0000211C', - "realine;": '\U0000211B', - "realpart;": '\U0000211C', - "reals;": '\U0000211D', - "rect;": '\U000025AD', - "reg;": '\U000000AE', - "rfisht;": '\U0000297D', - "rfloor;": '\U0000230B', - "rfr;": '\U0001D52F', - "rhard;": '\U000021C1', - "rharu;": '\U000021C0', - "rharul;": '\U0000296C', - "rho;": '\U000003C1', - "rhov;": '\U000003F1', - "rightarrow;": '\U00002192', - "rightarrowtail;": '\U000021A3', - "rightharpoondown;": '\U000021C1', - "rightharpoonup;": '\U000021C0', - "rightleftarrows;": '\U000021C4', - "rightleftharpoons;": '\U000021CC', - "rightrightarrows;": '\U000021C9', - "rightsquigarrow;": '\U0000219D', - "rightthreetimes;": '\U000022CC', - "ring;": '\U000002DA', - "risingdotseq;": '\U00002253', - "rlarr;": '\U000021C4', - "rlhar;": '\U000021CC', - "rlm;": '\U0000200F', - "rmoust;": '\U000023B1', - "rmoustache;": '\U000023B1', - "rnmid;": '\U00002AEE', - "roang;": '\U000027ED', - "roarr;": '\U000021FE', - "robrk;": '\U000027E7', - "ropar;": '\U00002986', - "ropf;": '\U0001D563', - "roplus;": '\U00002A2E', - "rotimes;": '\U00002A35', - "rpar;": '\U00000029', - "rpargt;": '\U00002994', - "rppolint;": '\U00002A12', - "rrarr;": '\U000021C9', - "rsaquo;": '\U0000203A', - "rscr;": '\U0001D4C7', - "rsh;": '\U000021B1', - "rsqb;": '\U0000005D', - "rsquo;": '\U00002019', - "rsquor;": '\U00002019', - "rthree;": '\U000022CC', - "rtimes;": '\U000022CA', - "rtri;": '\U000025B9', - "rtrie;": '\U000022B5', - "rtrif;": '\U000025B8', - "rtriltri;": '\U000029CE', - "ruluhar;": '\U00002968', - "rx;": '\U0000211E', - "sacute;": '\U0000015B', - "sbquo;": '\U0000201A', - "sc;": '\U0000227B', - "scE;": '\U00002AB4', - "scap;": '\U00002AB8', - "scaron;": '\U00000161', - "sccue;": '\U0000227D', - "sce;": '\U00002AB0', - "scedil;": '\U0000015F', - "scirc;": '\U0000015D', - "scnE;": '\U00002AB6', - "scnap;": '\U00002ABA', - "scnsim;": '\U000022E9', - "scpolint;": '\U00002A13', - "scsim;": '\U0000227F', - "scy;": '\U00000441', - "sdot;": '\U000022C5', - "sdotb;": '\U000022A1', - "sdote;": '\U00002A66', - "seArr;": '\U000021D8', - "searhk;": '\U00002925', - "searr;": '\U00002198', - "searrow;": '\U00002198', - "sect;": '\U000000A7', - "semi;": '\U0000003B', - "seswar;": '\U00002929', - "setminus;": '\U00002216', - "setmn;": '\U00002216', - "sext;": '\U00002736', - "sfr;": '\U0001D530', - "sfrown;": '\U00002322', - "sharp;": '\U0000266F', - "shchcy;": '\U00000449', - "shcy;": '\U00000448', - "shortmid;": '\U00002223', - "shortparallel;": '\U00002225', - "shy;": '\U000000AD', - "sigma;": '\U000003C3', - "sigmaf;": '\U000003C2', - "sigmav;": '\U000003C2', - "sim;": '\U0000223C', - "simdot;": '\U00002A6A', - "sime;": '\U00002243', - "simeq;": '\U00002243', - "simg;": '\U00002A9E', - "simgE;": '\U00002AA0', - "siml;": '\U00002A9D', - "simlE;": '\U00002A9F', - "simne;": '\U00002246', - "simplus;": '\U00002A24', - "simrarr;": '\U00002972', - "slarr;": '\U00002190', - "smallsetminus;": '\U00002216', - "smashp;": '\U00002A33', - "smeparsl;": '\U000029E4', - "smid;": '\U00002223', - "smile;": '\U00002323', - "smt;": '\U00002AAA', - "smte;": '\U00002AAC', - "softcy;": '\U0000044C', - "sol;": '\U0000002F', - "solb;": '\U000029C4', - "solbar;": '\U0000233F', - "sopf;": '\U0001D564', - "spades;": '\U00002660', - "spadesuit;": '\U00002660', - "spar;": '\U00002225', - "sqcap;": '\U00002293', - "sqcup;": '\U00002294', - "sqsub;": '\U0000228F', - "sqsube;": '\U00002291', - "sqsubset;": '\U0000228F', - "sqsubseteq;": '\U00002291', - "sqsup;": '\U00002290', - "sqsupe;": '\U00002292', - "sqsupset;": '\U00002290', - "sqsupseteq;": '\U00002292', - "squ;": '\U000025A1', - "square;": '\U000025A1', - "squarf;": '\U000025AA', - "squf;": '\U000025AA', - "srarr;": '\U00002192', - "sscr;": '\U0001D4C8', - "ssetmn;": '\U00002216', - "ssmile;": '\U00002323', - "sstarf;": '\U000022C6', - "star;": '\U00002606', - "starf;": '\U00002605', - "straightepsilon;": '\U000003F5', - "straightphi;": '\U000003D5', - "strns;": '\U000000AF', - "sub;": '\U00002282', - "subE;": '\U00002AC5', - "subdot;": '\U00002ABD', - "sube;": '\U00002286', - "subedot;": '\U00002AC3', - "submult;": '\U00002AC1', - "subnE;": '\U00002ACB', - "subne;": '\U0000228A', - "subplus;": '\U00002ABF', - "subrarr;": '\U00002979', - "subset;": '\U00002282', - "subseteq;": '\U00002286', - "subseteqq;": '\U00002AC5', - "subsetneq;": '\U0000228A', - "subsetneqq;": '\U00002ACB', - "subsim;": '\U00002AC7', - "subsub;": '\U00002AD5', - "subsup;": '\U00002AD3', - "succ;": '\U0000227B', - "succapprox;": '\U00002AB8', - "succcurlyeq;": '\U0000227D', - "succeq;": '\U00002AB0', - "succnapprox;": '\U00002ABA', - "succneqq;": '\U00002AB6', - "succnsim;": '\U000022E9', - "succsim;": '\U0000227F', - "sum;": '\U00002211', - "sung;": '\U0000266A', - "sup;": '\U00002283', - "sup1;": '\U000000B9', - "sup2;": '\U000000B2', - "sup3;": '\U000000B3', - "supE;": '\U00002AC6', - "supdot;": '\U00002ABE', - "supdsub;": '\U00002AD8', - "supe;": '\U00002287', - "supedot;": '\U00002AC4', - "suphsol;": '\U000027C9', - "suphsub;": '\U00002AD7', - "suplarr;": '\U0000297B', - "supmult;": '\U00002AC2', - "supnE;": '\U00002ACC', - "supne;": '\U0000228B', - "supplus;": '\U00002AC0', - "supset;": '\U00002283', - "supseteq;": '\U00002287', - "supseteqq;": '\U00002AC6', - "supsetneq;": '\U0000228B', - "supsetneqq;": '\U00002ACC', - "supsim;": '\U00002AC8', - "supsub;": '\U00002AD4', - "supsup;": '\U00002AD6', - "swArr;": '\U000021D9', - "swarhk;": '\U00002926', - "swarr;": '\U00002199', - "swarrow;": '\U00002199', - "swnwar;": '\U0000292A', - "szlig;": '\U000000DF', - "target;": '\U00002316', - "tau;": '\U000003C4', - "tbrk;": '\U000023B4', - "tcaron;": '\U00000165', - "tcedil;": '\U00000163', - "tcy;": '\U00000442', - "tdot;": '\U000020DB', - "telrec;": '\U00002315', - "tfr;": '\U0001D531', - "there4;": '\U00002234', - "therefore;": '\U00002234', - "theta;": '\U000003B8', - "thetasym;": '\U000003D1', - "thetav;": '\U000003D1', - "thickapprox;": '\U00002248', - "thicksim;": '\U0000223C', - "thinsp;": '\U00002009', - "thkap;": '\U00002248', - "thksim;": '\U0000223C', - "thorn;": '\U000000FE', - "tilde;": '\U000002DC', - "times;": '\U000000D7', - "timesb;": '\U000022A0', - "timesbar;": '\U00002A31', - "timesd;": '\U00002A30', - "tint;": '\U0000222D', - "toea;": '\U00002928', - "top;": '\U000022A4', - "topbot;": '\U00002336', - "topcir;": '\U00002AF1', - "topf;": '\U0001D565', - "topfork;": '\U00002ADA', - "tosa;": '\U00002929', - "tprime;": '\U00002034', - "trade;": '\U00002122', - "triangle;": '\U000025B5', - "triangledown;": '\U000025BF', - "triangleleft;": '\U000025C3', - "trianglelefteq;": '\U000022B4', - "triangleq;": '\U0000225C', - "triangleright;": '\U000025B9', - "trianglerighteq;": '\U000022B5', - "tridot;": '\U000025EC', - "trie;": '\U0000225C', - "triminus;": '\U00002A3A', - "triplus;": '\U00002A39', - "trisb;": '\U000029CD', - "tritime;": '\U00002A3B', - "trpezium;": '\U000023E2', - "tscr;": '\U0001D4C9', - "tscy;": '\U00000446', - "tshcy;": '\U0000045B', - "tstrok;": '\U00000167', - "twixt;": '\U0000226C', - "twoheadleftarrow;": '\U0000219E', - "twoheadrightarrow;": '\U000021A0', - "uArr;": '\U000021D1', - "uHar;": '\U00002963', - "uacute;": '\U000000FA', - "uarr;": '\U00002191', - "ubrcy;": '\U0000045E', - "ubreve;": '\U0000016D', - "ucirc;": '\U000000FB', - "ucy;": '\U00000443', - "udarr;": '\U000021C5', - "udblac;": '\U00000171', - "udhar;": '\U0000296E', - "ufisht;": '\U0000297E', - "ufr;": '\U0001D532', - "ugrave;": '\U000000F9', - "uharl;": '\U000021BF', - "uharr;": '\U000021BE', - "uhblk;": '\U00002580', - "ulcorn;": '\U0000231C', - "ulcorner;": '\U0000231C', - "ulcrop;": '\U0000230F', - "ultri;": '\U000025F8', - "umacr;": '\U0000016B', - "uml;": '\U000000A8', - "uogon;": '\U00000173', - "uopf;": '\U0001D566', - "uparrow;": '\U00002191', - "updownarrow;": '\U00002195', - "upharpoonleft;": '\U000021BF', - "upharpoonright;": '\U000021BE', - "uplus;": '\U0000228E', - "upsi;": '\U000003C5', - "upsih;": '\U000003D2', - "upsilon;": '\U000003C5', - "upuparrows;": '\U000021C8', - "urcorn;": '\U0000231D', - "urcorner;": '\U0000231D', - "urcrop;": '\U0000230E', - "uring;": '\U0000016F', - "urtri;": '\U000025F9', - "uscr;": '\U0001D4CA', - "utdot;": '\U000022F0', - "utilde;": '\U00000169', - "utri;": '\U000025B5', - "utrif;": '\U000025B4', - "uuarr;": '\U000021C8', - "uuml;": '\U000000FC', - "uwangle;": '\U000029A7', - "vArr;": '\U000021D5', - "vBar;": '\U00002AE8', - "vBarv;": '\U00002AE9', - "vDash;": '\U000022A8', - "vangrt;": '\U0000299C', - "varepsilon;": '\U000003F5', - "varkappa;": '\U000003F0', - "varnothing;": '\U00002205', - "varphi;": '\U000003D5', - "varpi;": '\U000003D6', - "varpropto;": '\U0000221D', - "varr;": '\U00002195', - "varrho;": '\U000003F1', - "varsigma;": '\U000003C2', - "vartheta;": '\U000003D1', - "vartriangleleft;": '\U000022B2', - "vartriangleright;": '\U000022B3', - "vcy;": '\U00000432', - "vdash;": '\U000022A2', - "vee;": '\U00002228', - "veebar;": '\U000022BB', - "veeeq;": '\U0000225A', - "vellip;": '\U000022EE', - "verbar;": '\U0000007C', - "vert;": '\U0000007C', - "vfr;": '\U0001D533', - "vltri;": '\U000022B2', - "vopf;": '\U0001D567', - "vprop;": '\U0000221D', - "vrtri;": '\U000022B3', - "vscr;": '\U0001D4CB', - "vzigzag;": '\U0000299A', - "wcirc;": '\U00000175', - "wedbar;": '\U00002A5F', - "wedge;": '\U00002227', - "wedgeq;": '\U00002259', - "weierp;": '\U00002118', - "wfr;": '\U0001D534', - "wopf;": '\U0001D568', - "wp;": '\U00002118', - "wr;": '\U00002240', - "wreath;": '\U00002240', - "wscr;": '\U0001D4CC', - "xcap;": '\U000022C2', - "xcirc;": '\U000025EF', - "xcup;": '\U000022C3', - "xdtri;": '\U000025BD', - "xfr;": '\U0001D535', - "xhArr;": '\U000027FA', - "xharr;": '\U000027F7', - "xi;": '\U000003BE', - "xlArr;": '\U000027F8', - "xlarr;": '\U000027F5', - "xmap;": '\U000027FC', - "xnis;": '\U000022FB', - "xodot;": '\U00002A00', - "xopf;": '\U0001D569', - "xoplus;": '\U00002A01', - "xotime;": '\U00002A02', - "xrArr;": '\U000027F9', - "xrarr;": '\U000027F6', - "xscr;": '\U0001D4CD', - "xsqcup;": '\U00002A06', - "xuplus;": '\U00002A04', - "xutri;": '\U000025B3', - "xvee;": '\U000022C1', - "xwedge;": '\U000022C0', - "yacute;": '\U000000FD', - "yacy;": '\U0000044F', - "ycirc;": '\U00000177', - "ycy;": '\U0000044B', - "yen;": '\U000000A5', - "yfr;": '\U0001D536', - "yicy;": '\U00000457', - "yopf;": '\U0001D56A', - "yscr;": '\U0001D4CE', - "yucy;": '\U0000044E', - "yuml;": '\U000000FF', - "zacute;": '\U0000017A', - "zcaron;": '\U0000017E', - "zcy;": '\U00000437', - "zdot;": '\U0000017C', - "zeetrf;": '\U00002128', - "zeta;": '\U000003B6', - "zfr;": '\U0001D537', - "zhcy;": '\U00000436', - "zigrarr;": '\U000021DD', - "zopf;": '\U0001D56B', - "zscr;": '\U0001D4CF', - "zwj;": '\U0000200D', - "zwnj;": '\U0000200C', - "AElig": '\U000000C6', - "AMP": '\U00000026', - "Aacute": '\U000000C1', - "Acirc": '\U000000C2', - "Agrave": '\U000000C0', - "Aring": '\U000000C5', - "Atilde": '\U000000C3', - "Auml": '\U000000C4', - "COPY": '\U000000A9', - "Ccedil": '\U000000C7', - "ETH": '\U000000D0', - "Eacute": '\U000000C9', - "Ecirc": '\U000000CA', - "Egrave": '\U000000C8', - "Euml": '\U000000CB', - "GT": '\U0000003E', - "Iacute": '\U000000CD', - "Icirc": '\U000000CE', - "Igrave": '\U000000CC', - "Iuml": '\U000000CF', - "LT": '\U0000003C', - "Ntilde": '\U000000D1', - "Oacute": '\U000000D3', - "Ocirc": '\U000000D4', - "Ograve": '\U000000D2', - "Oslash": '\U000000D8', - "Otilde": '\U000000D5', - "Ouml": '\U000000D6', - "QUOT": '\U00000022', - "REG": '\U000000AE', - "THORN": '\U000000DE', - "Uacute": '\U000000DA', - "Ucirc": '\U000000DB', - "Ugrave": '\U000000D9', - "Uuml": '\U000000DC', - "Yacute": '\U000000DD', - "aacute": '\U000000E1', - "acirc": '\U000000E2', - "acute": '\U000000B4', - "aelig": '\U000000E6', - "agrave": '\U000000E0', - "amp": '\U00000026', - "aring": '\U000000E5', - "atilde": '\U000000E3', - "auml": '\U000000E4', - "brvbar": '\U000000A6', - "ccedil": '\U000000E7', - "cedil": '\U000000B8', - "cent": '\U000000A2', - "copy": '\U000000A9', - "curren": '\U000000A4', - "deg": '\U000000B0', - "divide": '\U000000F7', - "eacute": '\U000000E9', - "ecirc": '\U000000EA', - "egrave": '\U000000E8', - "eth": '\U000000F0', - "euml": '\U000000EB', - "frac12": '\U000000BD', - "frac14": '\U000000BC', - "frac34": '\U000000BE', - "gt": '\U0000003E', - "iacute": '\U000000ED', - "icirc": '\U000000EE', - "iexcl": '\U000000A1', - "igrave": '\U000000EC', - "iquest": '\U000000BF', - "iuml": '\U000000EF', - "laquo": '\U000000AB', - "lt": '\U0000003C', - "macr": '\U000000AF', - "micro": '\U000000B5', - "middot": '\U000000B7', - "nbsp": '\U000000A0', - "not": '\U000000AC', - "ntilde": '\U000000F1', - "oacute": '\U000000F3', - "ocirc": '\U000000F4', - "ograve": '\U000000F2', - "ordf": '\U000000AA', - "ordm": '\U000000BA', - "oslash": '\U000000F8', - "otilde": '\U000000F5', - "ouml": '\U000000F6', - "para": '\U000000B6', - "plusmn": '\U000000B1', - "pound": '\U000000A3', - "quot": '\U00000022', - "raquo": '\U000000BB', - "reg": '\U000000AE', - "sect": '\U000000A7', - "shy": '\U000000AD', - "sup1": '\U000000B9', - "sup2": '\U000000B2', - "sup3": '\U000000B3', - "szlig": '\U000000DF', - "thorn": '\U000000FE', - "times": '\U000000D7', - "uacute": '\U000000FA', - "ucirc": '\U000000FB', - "ugrave": '\U000000F9', - "uml": '\U000000A8', - "uuml": '\U000000FC', - "yacute": '\U000000FD', - "yen": '\U000000A5', - "yuml": '\U000000FF', + "Cross;": '\U00002A2F', + "Cscr;": '\U0001D49E', + "Cup;": '\U000022D3', + "CupCap;": '\U0000224D', + "DD;": '\U00002145', + "DDotrahd;": '\U00002911', + "DJcy;": '\U00000402', + "DScy;": '\U00000405', + "DZcy;": '\U0000040F', + "Dagger;": '\U00002021', + "Darr;": '\U000021A1', + "Dashv;": '\U00002AE4', + "Dcaron;": '\U0000010E', + "Dcy;": '\U00000414', + "Del;": '\U00002207', + "Delta;": '\U00000394', + "Dfr;": '\U0001D507', + "DiacriticalAcute;": '\U000000B4', + "DiacriticalDot;": '\U000002D9', + "DiacriticalDoubleAcute;": '\U000002DD', + "DiacriticalGrave;": '\U00000060', + "DiacriticalTilde;": '\U000002DC', + "Diamond;": '\U000022C4', + "DifferentialD;": '\U00002146', + "Dopf;": '\U0001D53B', + "Dot;": '\U000000A8', + "DotDot;": '\U000020DC', + "DotEqual;": '\U00002250', + "DoubleContourIntegral;": '\U0000222F', + "DoubleDot;": '\U000000A8', + "DoubleDownArrow;": '\U000021D3', + "DoubleLeftArrow;": '\U000021D0', + "DoubleLeftRightArrow;": '\U000021D4', + "DoubleLeftTee;": '\U00002AE4', + "DoubleLongLeftArrow;": '\U000027F8', + "DoubleLongLeftRightArrow;": '\U000027FA', + "DoubleLongRightArrow;": '\U000027F9', + "DoubleRightArrow;": '\U000021D2', + "DoubleRightTee;": '\U000022A8', + "DoubleUpArrow;": '\U000021D1', + "DoubleUpDownArrow;": '\U000021D5', + "DoubleVerticalBar;": '\U00002225', + "DownArrow;": '\U00002193', + "DownArrowBar;": '\U00002913', + "DownArrowUpArrow;": '\U000021F5', + "DownBreve;": '\U00000311', + "DownLeftRightVector;": '\U00002950', + "DownLeftTeeVector;": '\U0000295E', + "DownLeftVector;": '\U000021BD', + "DownLeftVectorBar;": '\U00002956', + "DownRightTeeVector;": '\U0000295F', + "DownRightVector;": '\U000021C1', + "DownRightVectorBar;": '\U00002957', + "DownTee;": '\U000022A4', + "DownTeeArrow;": '\U000021A7', + "Downarrow;": '\U000021D3', + "Dscr;": '\U0001D49F', + "Dstrok;": '\U00000110', + "ENG;": '\U0000014A', + "ETH;": '\U000000D0', + "Eacute;": '\U000000C9', + "Ecaron;": '\U0000011A', + "Ecirc;": '\U000000CA', + "Ecy;": '\U0000042D', + "Edot;": '\U00000116', + "Efr;": '\U0001D508', + "Egrave;": '\U000000C8', + "Element;": '\U00002208', + "Emacr;": '\U00000112', + "EmptySmallSquare;": '\U000025FB', + "EmptyVerySmallSquare;": '\U000025AB', + "Eogon;": '\U00000118', + "Eopf;": '\U0001D53C', + "Epsilon;": '\U00000395', + "Equal;": '\U00002A75', + "EqualTilde;": '\U00002242', + "Equilibrium;": '\U000021CC', + "Escr;": '\U00002130', + "Esim;": '\U00002A73', + "Eta;": '\U00000397', + "Euml;": '\U000000CB', + "Exists;": '\U00002203', + "ExponentialE;": '\U00002147', + "Fcy;": '\U00000424', + "Ffr;": '\U0001D509', + "FilledSmallSquare;": '\U000025FC', + "FilledVerySmallSquare;": '\U000025AA', + "Fopf;": '\U0001D53D', + "ForAll;": '\U00002200', + "Fouriertrf;": '\U00002131', + "Fscr;": '\U00002131', + "GJcy;": '\U00000403', + "GT;": '\U0000003E', + "Gamma;": '\U00000393', + "Gammad;": '\U000003DC', + "Gbreve;": '\U0000011E', + "Gcedil;": '\U00000122', + "Gcirc;": '\U0000011C', + "Gcy;": '\U00000413', + "Gdot;": '\U00000120', + "Gfr;": '\U0001D50A', + "Gg;": '\U000022D9', + "Gopf;": '\U0001D53E', + "GreaterEqual;": '\U00002265', + "GreaterEqualLess;": '\U000022DB', + "GreaterFullEqual;": '\U00002267', + "GreaterGreater;": '\U00002AA2', + "GreaterLess;": '\U00002277', + "GreaterSlantEqual;": '\U00002A7E', + "GreaterTilde;": '\U00002273', + "Gscr;": '\U0001D4A2', + "Gt;": '\U0000226B', + "HARDcy;": '\U0000042A', + "Hacek;": '\U000002C7', + "Hat;": '\U0000005E', + "Hcirc;": '\U00000124', + "Hfr;": '\U0000210C', + "HilbertSpace;": '\U0000210B', + "Hopf;": '\U0000210D', + "HorizontalLine;": '\U00002500', + "Hscr;": '\U0000210B', + "Hstrok;": '\U00000126', + "HumpDownHump;": '\U0000224E', + "HumpEqual;": '\U0000224F', + "IEcy;": '\U00000415', + "IJlig;": '\U00000132', + "IOcy;": '\U00000401', + "Iacute;": '\U000000CD', + "Icirc;": '\U000000CE', + "Icy;": '\U00000418', + "Idot;": '\U00000130', + "Ifr;": '\U00002111', + "Igrave;": '\U000000CC', + "Im;": '\U00002111', + "Imacr;": '\U0000012A', + "ImaginaryI;": '\U00002148', + "Implies;": '\U000021D2', + "Int;": '\U0000222C', + "Integral;": '\U0000222B', + "Intersection;": '\U000022C2', + "InvisibleComma;": '\U00002063', + "InvisibleTimes;": '\U00002062', + "Iogon;": '\U0000012E', + "Iopf;": '\U0001D540', + "Iota;": '\U00000399', + "Iscr;": '\U00002110', + "Itilde;": '\U00000128', + "Iukcy;": '\U00000406', + "Iuml;": '\U000000CF', + "Jcirc;": '\U00000134', + "Jcy;": '\U00000419', + "Jfr;": '\U0001D50D', + "Jopf;": '\U0001D541', + "Jscr;": '\U0001D4A5', + "Jsercy;": '\U00000408', + "Jukcy;": '\U00000404', + "KHcy;": '\U00000425', + "KJcy;": '\U0000040C', + "Kappa;": '\U0000039A', + "Kcedil;": '\U00000136', + "Kcy;": '\U0000041A', + "Kfr;": '\U0001D50E', + "Kopf;": '\U0001D542', + "Kscr;": '\U0001D4A6', + "LJcy;": '\U00000409', + "LT;": '\U0000003C', + "Lacute;": '\U00000139', + "Lambda;": '\U0000039B', + "Lang;": '\U000027EA', + "Laplacetrf;": '\U00002112', + "Larr;": '\U0000219E', + "Lcaron;": '\U0000013D', + "Lcedil;": '\U0000013B', + "Lcy;": '\U0000041B', + "LeftAngleBracket;": '\U000027E8', + "LeftArrow;": '\U00002190', + "LeftArrowBar;": '\U000021E4', + "LeftArrowRightArrow;": '\U000021C6', + "LeftCeiling;": '\U00002308', + "LeftDoubleBracket;": '\U000027E6', + "LeftDownTeeVector;": '\U00002961', + "LeftDownVector;": '\U000021C3', + "LeftDownVectorBar;": '\U00002959', + "LeftFloor;": '\U0000230A', + "LeftRightArrow;": '\U00002194', + "LeftRightVector;": '\U0000294E', + "LeftTee;": '\U000022A3', + "LeftTeeArrow;": '\U000021A4', + "LeftTeeVector;": '\U0000295A', + "LeftTriangle;": '\U000022B2', + "LeftTriangleBar;": '\U000029CF', + "LeftTriangleEqual;": '\U000022B4', + "LeftUpDownVector;": '\U00002951', + "LeftUpTeeVector;": '\U00002960', + "LeftUpVector;": '\U000021BF', + "LeftUpVectorBar;": '\U00002958', + "LeftVector;": '\U000021BC', + "LeftVectorBar;": '\U00002952', + "Leftarrow;": '\U000021D0', + "Leftrightarrow;": '\U000021D4', + "LessEqualGreater;": '\U000022DA', + "LessFullEqual;": '\U00002266', + "LessGreater;": '\U00002276', + "LessLess;": '\U00002AA1', + "LessSlantEqual;": '\U00002A7D', + "LessTilde;": '\U00002272', + "Lfr;": '\U0001D50F', + "Ll;": '\U000022D8', + "Lleftarrow;": '\U000021DA', + "Lmidot;": '\U0000013F', + "LongLeftArrow;": '\U000027F5', + "LongLeftRightArrow;": '\U000027F7', + "LongRightArrow;": '\U000027F6', + "Longleftarrow;": '\U000027F8', + "Longleftrightarrow;": '\U000027FA', + "Longrightarrow;": '\U000027F9', + "Lopf;": '\U0001D543', + "LowerLeftArrow;": '\U00002199', + "LowerRightArrow;": '\U00002198', + "Lscr;": '\U00002112', + "Lsh;": '\U000021B0', + "Lstrok;": '\U00000141', + "Lt;": '\U0000226A', + "Map;": '\U00002905', + "Mcy;": '\U0000041C', + "MediumSpace;": '\U0000205F', + "Mellintrf;": '\U00002133', + "Mfr;": '\U0001D510', + "MinusPlus;": '\U00002213', + "Mopf;": '\U0001D544', + "Mscr;": '\U00002133', + "Mu;": '\U0000039C', + "NJcy;": '\U0000040A', + "Nacute;": '\U00000143', + "Ncaron;": '\U00000147', + "Ncedil;": '\U00000145', + "Ncy;": '\U0000041D', + "NegativeMediumSpace;": '\U0000200B', + "NegativeThickSpace;": '\U0000200B', + "NegativeThinSpace;": '\U0000200B', + "NegativeVeryThinSpace;": '\U0000200B', + "NestedGreaterGreater;": '\U0000226B', + "NestedLessLess;": '\U0000226A', + "NewLine;": '\U0000000A', + "Nfr;": '\U0001D511', + "NoBreak;": '\U00002060', + "NonBreakingSpace;": '\U000000A0', + "Nopf;": '\U00002115', + "Not;": '\U00002AEC', + "NotCongruent;": '\U00002262', + "NotCupCap;": '\U0000226D', + "NotDoubleVerticalBar;": '\U00002226', + "NotElement;": '\U00002209', + "NotEqual;": '\U00002260', + "NotExists;": '\U00002204', + "NotGreater;": '\U0000226F', + "NotGreaterEqual;": '\U00002271', + "NotGreaterLess;": '\U00002279', + "NotGreaterTilde;": '\U00002275', + "NotLeftTriangle;": '\U000022EA', + "NotLeftTriangleEqual;": '\U000022EC', + "NotLess;": '\U0000226E', + "NotLessEqual;": '\U00002270', + "NotLessGreater;": '\U00002278', + "NotLessTilde;": '\U00002274', + "NotPrecedes;": '\U00002280', + "NotPrecedesSlantEqual;": '\U000022E0', + "NotReverseElement;": '\U0000220C', + "NotRightTriangle;": '\U000022EB', + "NotRightTriangleEqual;": '\U000022ED', + "NotSquareSubsetEqual;": '\U000022E2', + "NotSquareSupersetEqual;": '\U000022E3', + "NotSubsetEqual;": '\U00002288', + "NotSucceeds;": '\U00002281', + "NotSucceedsSlantEqual;": '\U000022E1', + "NotSupersetEqual;": '\U00002289', + "NotTilde;": '\U00002241', + "NotTildeEqual;": '\U00002244', + "NotTildeFullEqual;": '\U00002247', + "NotTildeTilde;": '\U00002249', + "NotVerticalBar;": '\U00002224', + "Nscr;": '\U0001D4A9', + "Ntilde;": '\U000000D1', + "Nu;": '\U0000039D', + "OElig;": '\U00000152', + "Oacute;": '\U000000D3', + "Ocirc;": '\U000000D4', + "Ocy;": '\U0000041E', + "Odblac;": '\U00000150', + "Ofr;": '\U0001D512', + "Ograve;": '\U000000D2', + "Omacr;": '\U0000014C', + "Omega;": '\U000003A9', + "Omicron;": '\U0000039F', + "Oopf;": '\U0001D546', + "OpenCurlyDoubleQuote;": '\U0000201C', + "OpenCurlyQuote;": '\U00002018', + "Or;": '\U00002A54', + "Oscr;": '\U0001D4AA', + "Oslash;": '\U000000D8', + "Otilde;": '\U000000D5', + "Otimes;": '\U00002A37', + "Ouml;": '\U000000D6', + "OverBar;": '\U0000203E', + "OverBrace;": '\U000023DE', + "OverBracket;": '\U000023B4', + "OverParenthesis;": '\U000023DC', + "PartialD;": '\U00002202', + "Pcy;": '\U0000041F', + "Pfr;": '\U0001D513', + "Phi;": '\U000003A6', + "Pi;": '\U000003A0', + "PlusMinus;": '\U000000B1', + "Poincareplane;": '\U0000210C', + "Popf;": '\U00002119', + "Pr;": '\U00002ABB', + "Precedes;": '\U0000227A', + "PrecedesEqual;": '\U00002AAF', + "PrecedesSlantEqual;": '\U0000227C', + "PrecedesTilde;": '\U0000227E', + "Prime;": '\U00002033', + "Product;": '\U0000220F', + "Proportion;": '\U00002237', + "Proportional;": '\U0000221D', + "Pscr;": '\U0001D4AB', + "Psi;": '\U000003A8', + "QUOT;": '\U00000022', + "Qfr;": '\U0001D514', + "Qopf;": '\U0000211A', + "Qscr;": '\U0001D4AC', + "RBarr;": '\U00002910', + "REG;": '\U000000AE', + "Racute;": '\U00000154', + "Rang;": '\U000027EB', + "Rarr;": '\U000021A0', + "Rarrtl;": '\U00002916', + "Rcaron;": '\U00000158', + "Rcedil;": '\U00000156', + "Rcy;": '\U00000420', + "Re;": '\U0000211C', + "ReverseElement;": '\U0000220B', + "ReverseEquilibrium;": '\U000021CB', + "ReverseUpEquilibrium;": '\U0000296F', + "Rfr;": '\U0000211C', + "Rho;": '\U000003A1', + "RightAngleBracket;": '\U000027E9', + "RightArrow;": '\U00002192', + "RightArrowBar;": '\U000021E5', + "RightArrowLeftArrow;": '\U000021C4', + "RightCeiling;": '\U00002309', + "RightDoubleBracket;": '\U000027E7', + "RightDownTeeVector;": '\U0000295D', + "RightDownVector;": '\U000021C2', + "RightDownVectorBar;": '\U00002955', + "RightFloor;": '\U0000230B', + "RightTee;": '\U000022A2', + "RightTeeArrow;": '\U000021A6', + "RightTeeVector;": '\U0000295B', + "RightTriangle;": '\U000022B3', + "RightTriangleBar;": '\U000029D0', + "RightTriangleEqual;": '\U000022B5', + "RightUpDownVector;": '\U0000294F', + "RightUpTeeVector;": '\U0000295C', + "RightUpVector;": '\U000021BE', + "RightUpVectorBar;": '\U00002954', + "RightVector;": '\U000021C0', + "RightVectorBar;": '\U00002953', + "Rightarrow;": '\U000021D2', + "Ropf;": '\U0000211D', + "RoundImplies;": '\U00002970', + "Rrightarrow;": '\U000021DB', + "Rscr;": '\U0000211B', + "Rsh;": '\U000021B1', + "RuleDelayed;": '\U000029F4', + "SHCHcy;": '\U00000429', + "SHcy;": '\U00000428', + "SOFTcy;": '\U0000042C', + "Sacute;": '\U0000015A', + "Sc;": '\U00002ABC', + "Scaron;": '\U00000160', + "Scedil;": '\U0000015E', + "Scirc;": '\U0000015C', + "Scy;": '\U00000421', + "Sfr;": '\U0001D516', + "ShortDownArrow;": '\U00002193', + "ShortLeftArrow;": '\U00002190', + "ShortRightArrow;": '\U00002192', + "ShortUpArrow;": '\U00002191', + "Sigma;": '\U000003A3', + "SmallCircle;": '\U00002218', + "Sopf;": '\U0001D54A', + "Sqrt;": '\U0000221A', + "Square;": '\U000025A1', + "SquareIntersection;": '\U00002293', + "SquareSubset;": '\U0000228F', + "SquareSubsetEqual;": '\U00002291', + "SquareSuperset;": '\U00002290', + "SquareSupersetEqual;": '\U00002292', + "SquareUnion;": '\U00002294', + "Sscr;": '\U0001D4AE', + "Star;": '\U000022C6', + "Sub;": '\U000022D0', + "Subset;": '\U000022D0', + "SubsetEqual;": '\U00002286', + "Succeeds;": '\U0000227B', + "SucceedsEqual;": '\U00002AB0', + "SucceedsSlantEqual;": '\U0000227D', + "SucceedsTilde;": '\U0000227F', + "SuchThat;": '\U0000220B', + "Sum;": '\U00002211', + "Sup;": '\U000022D1', + "Superset;": '\U00002283', + "SupersetEqual;": '\U00002287', + "Supset;": '\U000022D1', + "THORN;": '\U000000DE', + "TRADE;": '\U00002122', + "TSHcy;": '\U0000040B', + "TScy;": '\U00000426', + "Tab;": '\U00000009', + "Tau;": '\U000003A4', + "Tcaron;": '\U00000164', + "Tcedil;": '\U00000162', + "Tcy;": '\U00000422', + "Tfr;": '\U0001D517', + "Therefore;": '\U00002234', + "Theta;": '\U00000398', + "ThinSpace;": '\U00002009', + "Tilde;": '\U0000223C', + "TildeEqual;": '\U00002243', + "TildeFullEqual;": '\U00002245', + "TildeTilde;": '\U00002248', + "Topf;": '\U0001D54B', + "TripleDot;": '\U000020DB', + "Tscr;": '\U0001D4AF', + "Tstrok;": '\U00000166', + "Uacute;": '\U000000DA', + "Uarr;": '\U0000219F', + "Uarrocir;": '\U00002949', + "Ubrcy;": '\U0000040E', + "Ubreve;": '\U0000016C', + "Ucirc;": '\U000000DB', + "Ucy;": '\U00000423', + "Udblac;": '\U00000170', + "Ufr;": '\U0001D518', + "Ugrave;": '\U000000D9', + "Umacr;": '\U0000016A', + "UnderBar;": '\U0000005F', + "UnderBrace;": '\U000023DF', + "UnderBracket;": '\U000023B5', + "UnderParenthesis;": '\U000023DD', + "Union;": '\U000022C3', + "UnionPlus;": '\U0000228E', + "Uogon;": '\U00000172', + "Uopf;": '\U0001D54C', + "UpArrow;": '\U00002191', + "UpArrowBar;": '\U00002912', + "UpArrowDownArrow;": '\U000021C5', + "UpDownArrow;": '\U00002195', + "UpEquilibrium;": '\U0000296E', + "UpTee;": '\U000022A5', + "UpTeeArrow;": '\U000021A5', + "Uparrow;": '\U000021D1', + "Updownarrow;": '\U000021D5', + "UpperLeftArrow;": '\U00002196', + "UpperRightArrow;": '\U00002197', + "Upsi;": '\U000003D2', + "Upsilon;": '\U000003A5', + "Uring;": '\U0000016E', + "Uscr;": '\U0001D4B0', + "Utilde;": '\U00000168', + "Uuml;": '\U000000DC', + "VDash;": '\U000022AB', + "Vbar;": '\U00002AEB', + "Vcy;": '\U00000412', + "Vdash;": '\U000022A9', + "Vdashl;": '\U00002AE6', + "Vee;": '\U000022C1', + "Verbar;": '\U00002016', + "Vert;": '\U00002016', + "VerticalBar;": '\U00002223', + "VerticalLine;": '\U0000007C', + "VerticalSeparator;": '\U00002758', + "VerticalTilde;": '\U00002240', + "VeryThinSpace;": '\U0000200A', + "Vfr;": '\U0001D519', + "Vopf;": '\U0001D54D', + "Vscr;": '\U0001D4B1', + "Vvdash;": '\U000022AA', + "Wcirc;": '\U00000174', + "Wedge;": '\U000022C0', + "Wfr;": '\U0001D51A', + "Wopf;": '\U0001D54E', + "Wscr;": '\U0001D4B2', + "Xfr;": '\U0001D51B', + "Xi;": '\U0000039E', + "Xopf;": '\U0001D54F', + "Xscr;": '\U0001D4B3', + "YAcy;": '\U0000042F', + "YIcy;": '\U00000407', + "YUcy;": '\U0000042E', + "Yacute;": '\U000000DD', + "Ycirc;": '\U00000176', + "Ycy;": '\U0000042B', + "Yfr;": '\U0001D51C', + "Yopf;": '\U0001D550', + "Yscr;": '\U0001D4B4', + "Yuml;": '\U00000178', + "ZHcy;": '\U00000416', + "Zacute;": '\U00000179', + "Zcaron;": '\U0000017D', + "Zcy;": '\U00000417', + "Zdot;": '\U0000017B', + "ZeroWidthSpace;": '\U0000200B', + "Zeta;": '\U00000396', + "Zfr;": '\U00002128', + "Zopf;": '\U00002124', + "Zscr;": '\U0001D4B5', + "aacute;": '\U000000E1', + "abreve;": '\U00000103', + "ac;": '\U0000223E', + "acd;": '\U0000223F', + "acirc;": '\U000000E2', + "acute;": '\U000000B4', + "acy;": '\U00000430', + "aelig;": '\U000000E6', + "af;": '\U00002061', + "afr;": '\U0001D51E', + "agrave;": '\U000000E0', + "alefsym;": '\U00002135', + "aleph;": '\U00002135', + "alpha;": '\U000003B1', + "amacr;": '\U00000101', + "amalg;": '\U00002A3F', + "amp;": '\U00000026', + "and;": '\U00002227', + "andand;": '\U00002A55', + "andd;": '\U00002A5C', + "andslope;": '\U00002A58', + "andv;": '\U00002A5A', + "ang;": '\U00002220', + "ange;": '\U000029A4', + "angle;": '\U00002220', + "angmsd;": '\U00002221', + "angmsdaa;": '\U000029A8', + "angmsdab;": '\U000029A9', + "angmsdac;": '\U000029AA', + "angmsdad;": '\U000029AB', + "angmsdae;": '\U000029AC', + "angmsdaf;": '\U000029AD', + "angmsdag;": '\U000029AE', + "angmsdah;": '\U000029AF', + "angrt;": '\U0000221F', + "angrtvb;": '\U000022BE', + "angrtvbd;": '\U0000299D', + "angsph;": '\U00002222', + "angst;": '\U000000C5', + "angzarr;": '\U0000237C', + "aogon;": '\U00000105', + "aopf;": '\U0001D552', + "ap;": '\U00002248', + "apE;": '\U00002A70', + "apacir;": '\U00002A6F', + "ape;": '\U0000224A', + "apid;": '\U0000224B', + "apos;": '\U00000027', + "approx;": '\U00002248', + "approxeq;": '\U0000224A', + "aring;": '\U000000E5', + "ascr;": '\U0001D4B6', + "ast;": '\U0000002A', + "asymp;": '\U00002248', + "asympeq;": '\U0000224D', + "atilde;": '\U000000E3', + "auml;": '\U000000E4', + "awconint;": '\U00002233', + "awint;": '\U00002A11', + "bNot;": '\U00002AED', + "backcong;": '\U0000224C', + "backepsilon;": '\U000003F6', + "backprime;": '\U00002035', + "backsim;": '\U0000223D', + "backsimeq;": '\U000022CD', + "barvee;": '\U000022BD', + "barwed;": '\U00002305', + "barwedge;": '\U00002305', + "bbrk;": '\U000023B5', + "bbrktbrk;": '\U000023B6', + "bcong;": '\U0000224C', + "bcy;": '\U00000431', + "bdquo;": '\U0000201E', + "becaus;": '\U00002235', + "because;": '\U00002235', + "bemptyv;": '\U000029B0', + "bepsi;": '\U000003F6', + "bernou;": '\U0000212C', + "beta;": '\U000003B2', + "beth;": '\U00002136', + "between;": '\U0000226C', + "bfr;": '\U0001D51F', + "bigcap;": '\U000022C2', + "bigcirc;": '\U000025EF', + "bigcup;": '\U000022C3', + "bigodot;": '\U00002A00', + "bigoplus;": '\U00002A01', + "bigotimes;": '\U00002A02', + "bigsqcup;": '\U00002A06', + "bigstar;": '\U00002605', + "bigtriangledown;": '\U000025BD', + "bigtriangleup;": '\U000025B3', + "biguplus;": '\U00002A04', + "bigvee;": '\U000022C1', + "bigwedge;": '\U000022C0', + "bkarow;": '\U0000290D', + "blacklozenge;": '\U000029EB', + "blacksquare;": '\U000025AA', + "blacktriangle;": '\U000025B4', + "blacktriangledown;": '\U000025BE', + "blacktriangleleft;": '\U000025C2', + "blacktriangleright;": '\U000025B8', + "blank;": '\U00002423', + "blk12;": '\U00002592', + "blk14;": '\U00002591', + "blk34;": '\U00002593', + "block;": '\U00002588', + "bnot;": '\U00002310', + "bopf;": '\U0001D553', + "bot;": '\U000022A5', + "bottom;": '\U000022A5', + "bowtie;": '\U000022C8', + "boxDL;": '\U00002557', + "boxDR;": '\U00002554', + "boxDl;": '\U00002556', + "boxDr;": '\U00002553', + "boxH;": '\U00002550', + "boxHD;": '\U00002566', + "boxHU;": '\U00002569', + "boxHd;": '\U00002564', + "boxHu;": '\U00002567', + "boxUL;": '\U0000255D', + "boxUR;": '\U0000255A', + "boxUl;": '\U0000255C', + "boxUr;": '\U00002559', + "boxV;": '\U00002551', + "boxVH;": '\U0000256C', + "boxVL;": '\U00002563', + "boxVR;": '\U00002560', + "boxVh;": '\U0000256B', + "boxVl;": '\U00002562', + "boxVr;": '\U0000255F', + "boxbox;": '\U000029C9', + "boxdL;": '\U00002555', + "boxdR;": '\U00002552', + "boxdl;": '\U00002510', + "boxdr;": '\U0000250C', + "boxh;": '\U00002500', + "boxhD;": '\U00002565', + "boxhU;": '\U00002568', + "boxhd;": '\U0000252C', + "boxhu;": '\U00002534', + "boxminus;": '\U0000229F', + "boxplus;": '\U0000229E', + "boxtimes;": '\U000022A0', + "boxuL;": '\U0000255B', + "boxuR;": '\U00002558', + "boxul;": '\U00002518', + "boxur;": '\U00002514', + "boxv;": '\U00002502', + "boxvH;": '\U0000256A', + "boxvL;": '\U00002561', + "boxvR;": '\U0000255E', + "boxvh;": '\U0000253C', + "boxvl;": '\U00002524', + "boxvr;": '\U0000251C', + "bprime;": '\U00002035', + "breve;": '\U000002D8', + "brvbar;": '\U000000A6', + "bscr;": '\U0001D4B7', + "bsemi;": '\U0000204F', + "bsim;": '\U0000223D', + "bsime;": '\U000022CD', + "bsol;": '\U0000005C', + "bsolb;": '\U000029C5', + "bsolhsub;": '\U000027C8', + "bull;": '\U00002022', + "bullet;": '\U00002022', + "bump;": '\U0000224E', + "bumpE;": '\U00002AAE', + "bumpe;": '\U0000224F', + "bumpeq;": '\U0000224F', + "cacute;": '\U00000107', + "cap;": '\U00002229', + "capand;": '\U00002A44', + "capbrcup;": '\U00002A49', + "capcap;": '\U00002A4B', + "capcup;": '\U00002A47', + "capdot;": '\U00002A40', + "caret;": '\U00002041', + "caron;": '\U000002C7', + "ccaps;": '\U00002A4D', + "ccaron;": '\U0000010D', + "ccedil;": '\U000000E7', + "ccirc;": '\U00000109', + "ccups;": '\U00002A4C', + "ccupssm;": '\U00002A50', + "cdot;": '\U0000010B', + "cedil;": '\U000000B8', + "cemptyv;": '\U000029B2', + "cent;": '\U000000A2', + "centerdot;": '\U000000B7', + "cfr;": '\U0001D520', + "chcy;": '\U00000447', + "check;": '\U00002713', + "checkmark;": '\U00002713', + "chi;": '\U000003C7', + "cir;": '\U000025CB', + "cirE;": '\U000029C3', + "circ;": '\U000002C6', + "circeq;": '\U00002257', + "circlearrowleft;": '\U000021BA', + "circlearrowright;": '\U000021BB', + "circledR;": '\U000000AE', + "circledS;": '\U000024C8', + "circledast;": '\U0000229B', + "circledcirc;": '\U0000229A', + "circleddash;": '\U0000229D', + "cire;": '\U00002257', + "cirfnint;": '\U00002A10', + "cirmid;": '\U00002AEF', + "cirscir;": '\U000029C2', + "clubs;": '\U00002663', + "clubsuit;": '\U00002663', + "colon;": '\U0000003A', + "colone;": '\U00002254', + "coloneq;": '\U00002254', + "comma;": '\U0000002C', + "commat;": '\U00000040', + "comp;": '\U00002201', + "compfn;": '\U00002218', + "complement;": '\U00002201', + "complexes;": '\U00002102', + "cong;": '\U00002245', + "congdot;": '\U00002A6D', + "conint;": '\U0000222E', + "copf;": '\U0001D554', + "coprod;": '\U00002210', + "copy;": '\U000000A9', + "copysr;": '\U00002117', + "crarr;": '\U000021B5', + "cross;": '\U00002717', + "cscr;": '\U0001D4B8', + "csub;": '\U00002ACF', + "csube;": '\U00002AD1', + "csup;": '\U00002AD0', + "csupe;": '\U00002AD2', + "ctdot;": '\U000022EF', + "cudarrl;": '\U00002938', + "cudarrr;": '\U00002935', + "cuepr;": '\U000022DE', + "cuesc;": '\U000022DF', + "cularr;": '\U000021B6', + "cularrp;": '\U0000293D', + "cup;": '\U0000222A', + "cupbrcap;": '\U00002A48', + "cupcap;": '\U00002A46', + "cupcup;": '\U00002A4A', + "cupdot;": '\U0000228D', + "cupor;": '\U00002A45', + "curarr;": '\U000021B7', + "curarrm;": '\U0000293C', + "curlyeqprec;": '\U000022DE', + "curlyeqsucc;": '\U000022DF', + "curlyvee;": '\U000022CE', + "curlywedge;": '\U000022CF', + "curren;": '\U000000A4', + "curvearrowleft;": '\U000021B6', + "curvearrowright;": '\U000021B7', + "cuvee;": '\U000022CE', + "cuwed;": '\U000022CF', + "cwconint;": '\U00002232', + "cwint;": '\U00002231', + "cylcty;": '\U0000232D', + "dArr;": '\U000021D3', + "dHar;": '\U00002965', + "dagger;": '\U00002020', + "daleth;": '\U00002138', + "darr;": '\U00002193', + "dash;": '\U00002010', + "dashv;": '\U000022A3', + "dbkarow;": '\U0000290F', + "dblac;": '\U000002DD', + "dcaron;": '\U0000010F', + "dcy;": '\U00000434', + "dd;": '\U00002146', + "ddagger;": '\U00002021', + "ddarr;": '\U000021CA', + "ddotseq;": '\U00002A77', + "deg;": '\U000000B0', + "delta;": '\U000003B4', + "demptyv;": '\U000029B1', + "dfisht;": '\U0000297F', + "dfr;": '\U0001D521', + "dharl;": '\U000021C3', + "dharr;": '\U000021C2', + "diam;": '\U000022C4', + "diamond;": '\U000022C4', + "diamondsuit;": '\U00002666', + "diams;": '\U00002666', + "die;": '\U000000A8', + "digamma;": '\U000003DD', + "disin;": '\U000022F2', + "div;": '\U000000F7', + "divide;": '\U000000F7', + "divideontimes;": '\U000022C7', + "divonx;": '\U000022C7', + "djcy;": '\U00000452', + "dlcorn;": '\U0000231E', + "dlcrop;": '\U0000230D', + "dollar;": '\U00000024', + "dopf;": '\U0001D555', + "dot;": '\U000002D9', + "doteq;": '\U00002250', + "doteqdot;": '\U00002251', + "dotminus;": '\U00002238', + "dotplus;": '\U00002214', + "dotsquare;": '\U000022A1', + "doublebarwedge;": '\U00002306', + "downarrow;": '\U00002193', + "downdownarrows;": '\U000021CA', + "downharpoonleft;": '\U000021C3', + "downharpoonright;": '\U000021C2', + "drbkarow;": '\U00002910', + "drcorn;": '\U0000231F', + "drcrop;": '\U0000230C', + "dscr;": '\U0001D4B9', + "dscy;": '\U00000455', + "dsol;": '\U000029F6', + "dstrok;": '\U00000111', + "dtdot;": '\U000022F1', + "dtri;": '\U000025BF', + "dtrif;": '\U000025BE', + "duarr;": '\U000021F5', + "duhar;": '\U0000296F', + "dwangle;": '\U000029A6', + "dzcy;": '\U0000045F', + "dzigrarr;": '\U000027FF', + "eDDot;": '\U00002A77', + "eDot;": '\U00002251', + "eacute;": '\U000000E9', + "easter;": '\U00002A6E', + "ecaron;": '\U0000011B', + "ecir;": '\U00002256', + "ecirc;": '\U000000EA', + "ecolon;": '\U00002255', + "ecy;": '\U0000044D', + "edot;": '\U00000117', + "ee;": '\U00002147', + "efDot;": '\U00002252', + "efr;": '\U0001D522', + "eg;": '\U00002A9A', + "egrave;": '\U000000E8', + "egs;": '\U00002A96', + "egsdot;": '\U00002A98', + "el;": '\U00002A99', + "elinters;": '\U000023E7', + "ell;": '\U00002113', + "els;": '\U00002A95', + "elsdot;": '\U00002A97', + "emacr;": '\U00000113', + "empty;": '\U00002205', + "emptyset;": '\U00002205', + "emptyv;": '\U00002205', + "emsp;": '\U00002003', + "emsp13;": '\U00002004', + "emsp14;": '\U00002005', + "eng;": '\U0000014B', + "ensp;": '\U00002002', + "eogon;": '\U00000119', + "eopf;": '\U0001D556', + "epar;": '\U000022D5', + "eparsl;": '\U000029E3', + "eplus;": '\U00002A71', + "epsi;": '\U000003B5', + "epsilon;": '\U000003B5', + "epsiv;": '\U000003F5', + "eqcirc;": '\U00002256', + "eqcolon;": '\U00002255', + "eqsim;": '\U00002242', + "eqslantgtr;": '\U00002A96', + "eqslantless;": '\U00002A95', + "equals;": '\U0000003D', + "equest;": '\U0000225F', + "equiv;": '\U00002261', + "equivDD;": '\U00002A78', + "eqvparsl;": '\U000029E5', + "erDot;": '\U00002253', + "erarr;": '\U00002971', + "escr;": '\U0000212F', + "esdot;": '\U00002250', + "esim;": '\U00002242', + "eta;": '\U000003B7', + "eth;": '\U000000F0', + "euml;": '\U000000EB', + "euro;": '\U000020AC', + "excl;": '\U00000021', + "exist;": '\U00002203', + "expectation;": '\U00002130', + "exponentiale;": '\U00002147', + "fallingdotseq;": '\U00002252', + "fcy;": '\U00000444', + "female;": '\U00002640', + "ffilig;": '\U0000FB03', + "fflig;": '\U0000FB00', + "ffllig;": '\U0000FB04', + "ffr;": '\U0001D523', + "filig;": '\U0000FB01', + "flat;": '\U0000266D', + "fllig;": '\U0000FB02', + "fltns;": '\U000025B1', + "fnof;": '\U00000192', + "fopf;": '\U0001D557', + "forall;": '\U00002200', + "fork;": '\U000022D4', + "forkv;": '\U00002AD9', + "fpartint;": '\U00002A0D', + "frac12;": '\U000000BD', + "frac13;": '\U00002153', + "frac14;": '\U000000BC', + "frac15;": '\U00002155', + "frac16;": '\U00002159', + "frac18;": '\U0000215B', + "frac23;": '\U00002154', + "frac25;": '\U00002156', + "frac34;": '\U000000BE', + "frac35;": '\U00002157', + "frac38;": '\U0000215C', + "frac45;": '\U00002158', + "frac56;": '\U0000215A', + "frac58;": '\U0000215D', + "frac78;": '\U0000215E', + "frasl;": '\U00002044', + "frown;": '\U00002322', + "fscr;": '\U0001D4BB', + "gE;": '\U00002267', + "gEl;": '\U00002A8C', + "gacute;": '\U000001F5', + "gamma;": '\U000003B3', + "gammad;": '\U000003DD', + "gap;": '\U00002A86', + "gbreve;": '\U0000011F', + "gcirc;": '\U0000011D', + "gcy;": '\U00000433', + "gdot;": '\U00000121', + "ge;": '\U00002265', + "gel;": '\U000022DB', + "geq;": '\U00002265', + "geqq;": '\U00002267', + "geqslant;": '\U00002A7E', + "ges;": '\U00002A7E', + "gescc;": '\U00002AA9', + "gesdot;": '\U00002A80', + "gesdoto;": '\U00002A82', + "gesdotol;": '\U00002A84', + "gesles;": '\U00002A94', + "gfr;": '\U0001D524', + "gg;": '\U0000226B', + "ggg;": '\U000022D9', + "gimel;": '\U00002137', + "gjcy;": '\U00000453', + "gl;": '\U00002277', + "glE;": '\U00002A92', + "gla;": '\U00002AA5', + "glj;": '\U00002AA4', + "gnE;": '\U00002269', + "gnap;": '\U00002A8A', + "gnapprox;": '\U00002A8A', + "gne;": '\U00002A88', + "gneq;": '\U00002A88', + "gneqq;": '\U00002269', + "gnsim;": '\U000022E7', + "gopf;": '\U0001D558', + "grave;": '\U00000060', + "gscr;": '\U0000210A', + "gsim;": '\U00002273', + "gsime;": '\U00002A8E', + "gsiml;": '\U00002A90', + "gt;": '\U0000003E', + "gtcc;": '\U00002AA7', + "gtcir;": '\U00002A7A', + "gtdot;": '\U000022D7', + "gtlPar;": '\U00002995', + "gtquest;": '\U00002A7C', + "gtrapprox;": '\U00002A86', + "gtrarr;": '\U00002978', + "gtrdot;": '\U000022D7', + "gtreqless;": '\U000022DB', + "gtreqqless;": '\U00002A8C', + "gtrless;": '\U00002277', + "gtrsim;": '\U00002273', + "hArr;": '\U000021D4', + "hairsp;": '\U0000200A', + "half;": '\U000000BD', + "hamilt;": '\U0000210B', + "hardcy;": '\U0000044A', + "harr;": '\U00002194', + "harrcir;": '\U00002948', + "harrw;": '\U000021AD', + "hbar;": '\U0000210F', + "hcirc;": '\U00000125', + "hearts;": '\U00002665', + "heartsuit;": '\U00002665', + "hellip;": '\U00002026', + "hercon;": '\U000022B9', + "hfr;": '\U0001D525', + "hksearow;": '\U00002925', + "hkswarow;": '\U00002926', + "hoarr;": '\U000021FF', + "homtht;": '\U0000223B', + "hookleftarrow;": '\U000021A9', + "hookrightarrow;": '\U000021AA', + "hopf;": '\U0001D559', + "horbar;": '\U00002015', + "hscr;": '\U0001D4BD', + "hslash;": '\U0000210F', + "hstrok;": '\U00000127', + "hybull;": '\U00002043', + "hyphen;": '\U00002010', + "iacute;": '\U000000ED', + "ic;": '\U00002063', + "icirc;": '\U000000EE', + "icy;": '\U00000438', + "iecy;": '\U00000435', + "iexcl;": '\U000000A1', + "iff;": '\U000021D4', + "ifr;": '\U0001D526', + "igrave;": '\U000000EC', + "ii;": '\U00002148', + "iiiint;": '\U00002A0C', + "iiint;": '\U0000222D', + "iinfin;": '\U000029DC', + "iiota;": '\U00002129', + "ijlig;": '\U00000133', + "imacr;": '\U0000012B', + "image;": '\U00002111', + "imagline;": '\U00002110', + "imagpart;": '\U00002111', + "imath;": '\U00000131', + "imof;": '\U000022B7', + "imped;": '\U000001B5', + "in;": '\U00002208', + "incare;": '\U00002105', + "infin;": '\U0000221E', + "infintie;": '\U000029DD', + "inodot;": '\U00000131', + "int;": '\U0000222B', + "intcal;": '\U000022BA', + "integers;": '\U00002124', + "intercal;": '\U000022BA', + "intlarhk;": '\U00002A17', + "intprod;": '\U00002A3C', + "iocy;": '\U00000451', + "iogon;": '\U0000012F', + "iopf;": '\U0001D55A', + "iota;": '\U000003B9', + "iprod;": '\U00002A3C', + "iquest;": '\U000000BF', + "iscr;": '\U0001D4BE', + "isin;": '\U00002208', + "isinE;": '\U000022F9', + "isindot;": '\U000022F5', + "isins;": '\U000022F4', + "isinsv;": '\U000022F3', + "isinv;": '\U00002208', + "it;": '\U00002062', + "itilde;": '\U00000129', + "iukcy;": '\U00000456', + "iuml;": '\U000000EF', + "jcirc;": '\U00000135', + "jcy;": '\U00000439', + "jfr;": '\U0001D527', + "jmath;": '\U00000237', + "jopf;": '\U0001D55B', + "jscr;": '\U0001D4BF', + "jsercy;": '\U00000458', + "jukcy;": '\U00000454', + "kappa;": '\U000003BA', + "kappav;": '\U000003F0', + "kcedil;": '\U00000137', + "kcy;": '\U0000043A', + "kfr;": '\U0001D528', + "kgreen;": '\U00000138', + "khcy;": '\U00000445', + "kjcy;": '\U0000045C', + "kopf;": '\U0001D55C', + "kscr;": '\U0001D4C0', + "lAarr;": '\U000021DA', + "lArr;": '\U000021D0', + "lAtail;": '\U0000291B', + "lBarr;": '\U0000290E', + "lE;": '\U00002266', + "lEg;": '\U00002A8B', + "lHar;": '\U00002962', + "lacute;": '\U0000013A', + "laemptyv;": '\U000029B4', + "lagran;": '\U00002112', + "lambda;": '\U000003BB', + "lang;": '\U000027E8', + "langd;": '\U00002991', + "langle;": '\U000027E8', + "lap;": '\U00002A85', + "laquo;": '\U000000AB', + "larr;": '\U00002190', + "larrb;": '\U000021E4', + "larrbfs;": '\U0000291F', + "larrfs;": '\U0000291D', + "larrhk;": '\U000021A9', + "larrlp;": '\U000021AB', + "larrpl;": '\U00002939', + "larrsim;": '\U00002973', + "larrtl;": '\U000021A2', + "lat;": '\U00002AAB', + "latail;": '\U00002919', + "late;": '\U00002AAD', + "lbarr;": '\U0000290C', + "lbbrk;": '\U00002772', + "lbrace;": '\U0000007B', + "lbrack;": '\U0000005B', + "lbrke;": '\U0000298B', + "lbrksld;": '\U0000298F', + "lbrkslu;": '\U0000298D', + "lcaron;": '\U0000013E', + "lcedil;": '\U0000013C', + "lceil;": '\U00002308', + "lcub;": '\U0000007B', + "lcy;": '\U0000043B', + "ldca;": '\U00002936', + "ldquo;": '\U0000201C', + "ldquor;": '\U0000201E', + "ldrdhar;": '\U00002967', + "ldrushar;": '\U0000294B', + "ldsh;": '\U000021B2', + "le;": '\U00002264', + "leftarrow;": '\U00002190', + "leftarrowtail;": '\U000021A2', + "leftharpoondown;": '\U000021BD', + "leftharpoonup;": '\U000021BC', + "leftleftarrows;": '\U000021C7', + "leftrightarrow;": '\U00002194', + "leftrightarrows;": '\U000021C6', + "leftrightharpoons;": '\U000021CB', + "leftrightsquigarrow;": '\U000021AD', + "leftthreetimes;": '\U000022CB', + "leg;": '\U000022DA', + "leq;": '\U00002264', + "leqq;": '\U00002266', + "leqslant;": '\U00002A7D', + "les;": '\U00002A7D', + "lescc;": '\U00002AA8', + "lesdot;": '\U00002A7F', + "lesdoto;": '\U00002A81', + "lesdotor;": '\U00002A83', + "lesges;": '\U00002A93', + "lessapprox;": '\U00002A85', + "lessdot;": '\U000022D6', + "lesseqgtr;": '\U000022DA', + "lesseqqgtr;": '\U00002A8B', + "lessgtr;": '\U00002276', + "lesssim;": '\U00002272', + "lfisht;": '\U0000297C', + "lfloor;": '\U0000230A', + "lfr;": '\U0001D529', + "lg;": '\U00002276', + "lgE;": '\U00002A91', + "lhard;": '\U000021BD', + "lharu;": '\U000021BC', + "lharul;": '\U0000296A', + "lhblk;": '\U00002584', + "ljcy;": '\U00000459', + "ll;": '\U0000226A', + "llarr;": '\U000021C7', + "llcorner;": '\U0000231E', + "llhard;": '\U0000296B', + "lltri;": '\U000025FA', + "lmidot;": '\U00000140', + "lmoust;": '\U000023B0', + "lmoustache;": '\U000023B0', + "lnE;": '\U00002268', + "lnap;": '\U00002A89', + "lnapprox;": '\U00002A89', + "lne;": '\U00002A87', + "lneq;": '\U00002A87', + "lneqq;": '\U00002268', + "lnsim;": '\U000022E6', + "loang;": '\U000027EC', + "loarr;": '\U000021FD', + "lobrk;": '\U000027E6', + "longleftarrow;": '\U000027F5', + "longleftrightarrow;": '\U000027F7', + "longmapsto;": '\U000027FC', + "longrightarrow;": '\U000027F6', + "looparrowleft;": '\U000021AB', + "looparrowright;": '\U000021AC', + "lopar;": '\U00002985', + "lopf;": '\U0001D55D', + "loplus;": '\U00002A2D', + "lotimes;": '\U00002A34', + "lowast;": '\U00002217', + "lowbar;": '\U0000005F', + "loz;": '\U000025CA', + "lozenge;": '\U000025CA', + "lozf;": '\U000029EB', + "lpar;": '\U00000028', + "lparlt;": '\U00002993', + "lrarr;": '\U000021C6', + "lrcorner;": '\U0000231F', + "lrhar;": '\U000021CB', + "lrhard;": '\U0000296D', + "lrm;": '\U0000200E', + "lrtri;": '\U000022BF', + "lsaquo;": '\U00002039', + "lscr;": '\U0001D4C1', + "lsh;": '\U000021B0', + "lsim;": '\U00002272', + "lsime;": '\U00002A8D', + "lsimg;": '\U00002A8F', + "lsqb;": '\U0000005B', + "lsquo;": '\U00002018', + "lsquor;": '\U0000201A', + "lstrok;": '\U00000142', + "lt;": '\U0000003C', + "ltcc;": '\U00002AA6', + "ltcir;": '\U00002A79', + "ltdot;": '\U000022D6', + "lthree;": '\U000022CB', + "ltimes;": '\U000022C9', + "ltlarr;": '\U00002976', + "ltquest;": '\U00002A7B', + "ltrPar;": '\U00002996', + "ltri;": '\U000025C3', + "ltrie;": '\U000022B4', + "ltrif;": '\U000025C2', + "lurdshar;": '\U0000294A', + "luruhar;": '\U00002966', + "mDDot;": '\U0000223A', + "macr;": '\U000000AF', + "male;": '\U00002642', + "malt;": '\U00002720', + "maltese;": '\U00002720', + "map;": '\U000021A6', + "mapsto;": '\U000021A6', + "mapstodown;": '\U000021A7', + "mapstoleft;": '\U000021A4', + "mapstoup;": '\U000021A5', + "marker;": '\U000025AE', + "mcomma;": '\U00002A29', + "mcy;": '\U0000043C', + "mdash;": '\U00002014', + "measuredangle;": '\U00002221', + "mfr;": '\U0001D52A', + "mho;": '\U00002127', + "micro;": '\U000000B5', + "mid;": '\U00002223', + "midast;": '\U0000002A', + "midcir;": '\U00002AF0', + "middot;": '\U000000B7', + "minus;": '\U00002212', + "minusb;": '\U0000229F', + "minusd;": '\U00002238', + "minusdu;": '\U00002A2A', + "mlcp;": '\U00002ADB', + "mldr;": '\U00002026', + "mnplus;": '\U00002213', + "models;": '\U000022A7', + "mopf;": '\U0001D55E', + "mp;": '\U00002213', + "mscr;": '\U0001D4C2', + "mstpos;": '\U0000223E', + "mu;": '\U000003BC', + "multimap;": '\U000022B8', + "mumap;": '\U000022B8', + "nLeftarrow;": '\U000021CD', + "nLeftrightarrow;": '\U000021CE', + "nRightarrow;": '\U000021CF', + "nVDash;": '\U000022AF', + "nVdash;": '\U000022AE', + "nabla;": '\U00002207', + "nacute;": '\U00000144', + "nap;": '\U00002249', + "napos;": '\U00000149', + "napprox;": '\U00002249', + "natur;": '\U0000266E', + "natural;": '\U0000266E', + "naturals;": '\U00002115', + "nbsp;": '\U000000A0', + "ncap;": '\U00002A43', + "ncaron;": '\U00000148', + "ncedil;": '\U00000146', + "ncong;": '\U00002247', + "ncup;": '\U00002A42', + "ncy;": '\U0000043D', + "ndash;": '\U00002013', + "ne;": '\U00002260', + "neArr;": '\U000021D7', + "nearhk;": '\U00002924', + "nearr;": '\U00002197', + "nearrow;": '\U00002197', + "nequiv;": '\U00002262', + "nesear;": '\U00002928', + "nexist;": '\U00002204', + "nexists;": '\U00002204', + "nfr;": '\U0001D52B', + "nge;": '\U00002271', + "ngeq;": '\U00002271', + "ngsim;": '\U00002275', + "ngt;": '\U0000226F', + "ngtr;": '\U0000226F', + "nhArr;": '\U000021CE', + "nharr;": '\U000021AE', + "nhpar;": '\U00002AF2', + "ni;": '\U0000220B', + "nis;": '\U000022FC', + "nisd;": '\U000022FA', + "niv;": '\U0000220B', + "njcy;": '\U0000045A', + "nlArr;": '\U000021CD', + "nlarr;": '\U0000219A', + "nldr;": '\U00002025', + "nle;": '\U00002270', + "nleftarrow;": '\U0000219A', + "nleftrightarrow;": '\U000021AE', + "nleq;": '\U00002270', + "nless;": '\U0000226E', + "nlsim;": '\U00002274', + "nlt;": '\U0000226E', + "nltri;": '\U000022EA', + "nltrie;": '\U000022EC', + "nmid;": '\U00002224', + "nopf;": '\U0001D55F', + "not;": '\U000000AC', + "notin;": '\U00002209', + "notinva;": '\U00002209', + "notinvb;": '\U000022F7', + "notinvc;": '\U000022F6', + "notni;": '\U0000220C', + "notniva;": '\U0000220C', + "notnivb;": '\U000022FE', + "notnivc;": '\U000022FD', + "npar;": '\U00002226', + "nparallel;": '\U00002226', + "npolint;": '\U00002A14', + "npr;": '\U00002280', + "nprcue;": '\U000022E0', + "nprec;": '\U00002280', + "nrArr;": '\U000021CF', + "nrarr;": '\U0000219B', + "nrightarrow;": '\U0000219B', + "nrtri;": '\U000022EB', + "nrtrie;": '\U000022ED', + "nsc;": '\U00002281', + "nsccue;": '\U000022E1', + "nscr;": '\U0001D4C3', + "nshortmid;": '\U00002224', + "nshortparallel;": '\U00002226', + "nsim;": '\U00002241', + "nsime;": '\U00002244', + "nsimeq;": '\U00002244', + "nsmid;": '\U00002224', + "nspar;": '\U00002226', + "nsqsube;": '\U000022E2', + "nsqsupe;": '\U000022E3', + "nsub;": '\U00002284', + "nsube;": '\U00002288', + "nsubseteq;": '\U00002288', + "nsucc;": '\U00002281', + "nsup;": '\U00002285', + "nsupe;": '\U00002289', + "nsupseteq;": '\U00002289', + "ntgl;": '\U00002279', + "ntilde;": '\U000000F1', + "ntlg;": '\U00002278', + "ntriangleleft;": '\U000022EA', + "ntrianglelefteq;": '\U000022EC', + "ntriangleright;": '\U000022EB', + "ntrianglerighteq;": '\U000022ED', + "nu;": '\U000003BD', + "num;": '\U00000023', + "numero;": '\U00002116', + "numsp;": '\U00002007', + "nvDash;": '\U000022AD', + "nvHarr;": '\U00002904', + "nvdash;": '\U000022AC', + "nvinfin;": '\U000029DE', + "nvlArr;": '\U00002902', + "nvrArr;": '\U00002903', + "nwArr;": '\U000021D6', + "nwarhk;": '\U00002923', + "nwarr;": '\U00002196', + "nwarrow;": '\U00002196', + "nwnear;": '\U00002927', + "oS;": '\U000024C8', + "oacute;": '\U000000F3', + "oast;": '\U0000229B', + "ocir;": '\U0000229A', + "ocirc;": '\U000000F4', + "ocy;": '\U0000043E', + "odash;": '\U0000229D', + "odblac;": '\U00000151', + "odiv;": '\U00002A38', + "odot;": '\U00002299', + "odsold;": '\U000029BC', + "oelig;": '\U00000153', + "ofcir;": '\U000029BF', + "ofr;": '\U0001D52C', + "ogon;": '\U000002DB', + "ograve;": '\U000000F2', + "ogt;": '\U000029C1', + "ohbar;": '\U000029B5', + "ohm;": '\U000003A9', + "oint;": '\U0000222E', + "olarr;": '\U000021BA', + "olcir;": '\U000029BE', + "olcross;": '\U000029BB', + "oline;": '\U0000203E', + "olt;": '\U000029C0', + "omacr;": '\U0000014D', + "omega;": '\U000003C9', + "omicron;": '\U000003BF', + "omid;": '\U000029B6', + "ominus;": '\U00002296', + "oopf;": '\U0001D560', + "opar;": '\U000029B7', + "operp;": '\U000029B9', + "oplus;": '\U00002295', + "or;": '\U00002228', + "orarr;": '\U000021BB', + "ord;": '\U00002A5D', + "order;": '\U00002134', + "orderof;": '\U00002134', + "ordf;": '\U000000AA', + "ordm;": '\U000000BA', + "origof;": '\U000022B6', + "oror;": '\U00002A56', + "orslope;": '\U00002A57', + "orv;": '\U00002A5B', + "oscr;": '\U00002134', + "oslash;": '\U000000F8', + "osol;": '\U00002298', + "otilde;": '\U000000F5', + "otimes;": '\U00002297', + "otimesas;": '\U00002A36', + "ouml;": '\U000000F6', + "ovbar;": '\U0000233D', + "par;": '\U00002225', + "para;": '\U000000B6', + "parallel;": '\U00002225', + "parsim;": '\U00002AF3', + "parsl;": '\U00002AFD', + "part;": '\U00002202', + "pcy;": '\U0000043F', + "percnt;": '\U00000025', + "period;": '\U0000002E', + "permil;": '\U00002030', + "perp;": '\U000022A5', + "pertenk;": '\U00002031', + "pfr;": '\U0001D52D', + "phi;": '\U000003C6', + "phiv;": '\U000003D5', + "phmmat;": '\U00002133', + "phone;": '\U0000260E', + "pi;": '\U000003C0', + "pitchfork;": '\U000022D4', + "piv;": '\U000003D6', + "planck;": '\U0000210F', + "planckh;": '\U0000210E', + "plankv;": '\U0000210F', + "plus;": '\U0000002B', + "plusacir;": '\U00002A23', + "plusb;": '\U0000229E', + "pluscir;": '\U00002A22', + "plusdo;": '\U00002214', + "plusdu;": '\U00002A25', + "pluse;": '\U00002A72', + "plusmn;": '\U000000B1', + "plussim;": '\U00002A26', + "plustwo;": '\U00002A27', + "pm;": '\U000000B1', + "pointint;": '\U00002A15', + "popf;": '\U0001D561', + "pound;": '\U000000A3', + "pr;": '\U0000227A', + "prE;": '\U00002AB3', + "prap;": '\U00002AB7', + "prcue;": '\U0000227C', + "pre;": '\U00002AAF', + "prec;": '\U0000227A', + "precapprox;": '\U00002AB7', + "preccurlyeq;": '\U0000227C', + "preceq;": '\U00002AAF', + "precnapprox;": '\U00002AB9', + "precneqq;": '\U00002AB5', + "precnsim;": '\U000022E8', + "precsim;": '\U0000227E', + "prime;": '\U00002032', + "primes;": '\U00002119', + "prnE;": '\U00002AB5', + "prnap;": '\U00002AB9', + "prnsim;": '\U000022E8', + "prod;": '\U0000220F', + "profalar;": '\U0000232E', + "profline;": '\U00002312', + "profsurf;": '\U00002313', + "prop;": '\U0000221D', + "propto;": '\U0000221D', + "prsim;": '\U0000227E', + "prurel;": '\U000022B0', + "pscr;": '\U0001D4C5', + "psi;": '\U000003C8', + "puncsp;": '\U00002008', + "qfr;": '\U0001D52E', + "qint;": '\U00002A0C', + "qopf;": '\U0001D562', + "qprime;": '\U00002057', + "qscr;": '\U0001D4C6', + "quaternions;": '\U0000210D', + "quatint;": '\U00002A16', + "quest;": '\U0000003F', + "questeq;": '\U0000225F', + "quot;": '\U00000022', + "rAarr;": '\U000021DB', + "rArr;": '\U000021D2', + "rAtail;": '\U0000291C', + "rBarr;": '\U0000290F', + "rHar;": '\U00002964', + "racute;": '\U00000155', + "radic;": '\U0000221A', + "raemptyv;": '\U000029B3', + "rang;": '\U000027E9', + "rangd;": '\U00002992', + "range;": '\U000029A5', + "rangle;": '\U000027E9', + "raquo;": '\U000000BB', + "rarr;": '\U00002192', + "rarrap;": '\U00002975', + "rarrb;": '\U000021E5', + "rarrbfs;": '\U00002920', + "rarrc;": '\U00002933', + "rarrfs;": '\U0000291E', + "rarrhk;": '\U000021AA', + "rarrlp;": '\U000021AC', + "rarrpl;": '\U00002945', + "rarrsim;": '\U00002974', + "rarrtl;": '\U000021A3', + "rarrw;": '\U0000219D', + "ratail;": '\U0000291A', + "ratio;": '\U00002236', + "rationals;": '\U0000211A', + "rbarr;": '\U0000290D', + "rbbrk;": '\U00002773', + "rbrace;": '\U0000007D', + "rbrack;": '\U0000005D', + "rbrke;": '\U0000298C', + "rbrksld;": '\U0000298E', + "rbrkslu;": '\U00002990', + "rcaron;": '\U00000159', + "rcedil;": '\U00000157', + "rceil;": '\U00002309', + "rcub;": '\U0000007D', + "rcy;": '\U00000440', + "rdca;": '\U00002937', + "rdldhar;": '\U00002969', + "rdquo;": '\U0000201D', + "rdquor;": '\U0000201D', + "rdsh;": '\U000021B3', + "real;": '\U0000211C', + "realine;": '\U0000211B', + "realpart;": '\U0000211C', + "reals;": '\U0000211D', + "rect;": '\U000025AD', + "reg;": '\U000000AE', + "rfisht;": '\U0000297D', + "rfloor;": '\U0000230B', + "rfr;": '\U0001D52F', + "rhard;": '\U000021C1', + "rharu;": '\U000021C0', + "rharul;": '\U0000296C', + "rho;": '\U000003C1', + "rhov;": '\U000003F1', + "rightarrow;": '\U00002192', + "rightarrowtail;": '\U000021A3', + "rightharpoondown;": '\U000021C1', + "rightharpoonup;": '\U000021C0', + "rightleftarrows;": '\U000021C4', + "rightleftharpoons;": '\U000021CC', + "rightrightarrows;": '\U000021C9', + "rightsquigarrow;": '\U0000219D', + "rightthreetimes;": '\U000022CC', + "ring;": '\U000002DA', + "risingdotseq;": '\U00002253', + "rlarr;": '\U000021C4', + "rlhar;": '\U000021CC', + "rlm;": '\U0000200F', + "rmoust;": '\U000023B1', + "rmoustache;": '\U000023B1', + "rnmid;": '\U00002AEE', + "roang;": '\U000027ED', + "roarr;": '\U000021FE', + "robrk;": '\U000027E7', + "ropar;": '\U00002986', + "ropf;": '\U0001D563', + "roplus;": '\U00002A2E', + "rotimes;": '\U00002A35', + "rpar;": '\U00000029', + "rpargt;": '\U00002994', + "rppolint;": '\U00002A12', + "rrarr;": '\U000021C9', + "rsaquo;": '\U0000203A', + "rscr;": '\U0001D4C7', + "rsh;": '\U000021B1', + "rsqb;": '\U0000005D', + "rsquo;": '\U00002019', + "rsquor;": '\U00002019', + "rthree;": '\U000022CC', + "rtimes;": '\U000022CA', + "rtri;": '\U000025B9', + "rtrie;": '\U000022B5', + "rtrif;": '\U000025B8', + "rtriltri;": '\U000029CE', + "ruluhar;": '\U00002968', + "rx;": '\U0000211E', + "sacute;": '\U0000015B', + "sbquo;": '\U0000201A', + "sc;": '\U0000227B', + "scE;": '\U00002AB4', + "scap;": '\U00002AB8', + "scaron;": '\U00000161', + "sccue;": '\U0000227D', + "sce;": '\U00002AB0', + "scedil;": '\U0000015F', + "scirc;": '\U0000015D', + "scnE;": '\U00002AB6', + "scnap;": '\U00002ABA', + "scnsim;": '\U000022E9', + "scpolint;": '\U00002A13', + "scsim;": '\U0000227F', + "scy;": '\U00000441', + "sdot;": '\U000022C5', + "sdotb;": '\U000022A1', + "sdote;": '\U00002A66', + "seArr;": '\U000021D8', + "searhk;": '\U00002925', + "searr;": '\U00002198', + "searrow;": '\U00002198', + "sect;": '\U000000A7', + "semi;": '\U0000003B', + "seswar;": '\U00002929', + "setminus;": '\U00002216', + "setmn;": '\U00002216', + "sext;": '\U00002736', + "sfr;": '\U0001D530', + "sfrown;": '\U00002322', + "sharp;": '\U0000266F', + "shchcy;": '\U00000449', + "shcy;": '\U00000448', + "shortmid;": '\U00002223', + "shortparallel;": '\U00002225', + "shy;": '\U000000AD', + "sigma;": '\U000003C3', + "sigmaf;": '\U000003C2', + "sigmav;": '\U000003C2', + "sim;": '\U0000223C', + "simdot;": '\U00002A6A', + "sime;": '\U00002243', + "simeq;": '\U00002243', + "simg;": '\U00002A9E', + "simgE;": '\U00002AA0', + "siml;": '\U00002A9D', + "simlE;": '\U00002A9F', + "simne;": '\U00002246', + "simplus;": '\U00002A24', + "simrarr;": '\U00002972', + "slarr;": '\U00002190', + "smallsetminus;": '\U00002216', + "smashp;": '\U00002A33', + "smeparsl;": '\U000029E4', + "smid;": '\U00002223', + "smile;": '\U00002323', + "smt;": '\U00002AAA', + "smte;": '\U00002AAC', + "softcy;": '\U0000044C', + "sol;": '\U0000002F', + "solb;": '\U000029C4', + "solbar;": '\U0000233F', + "sopf;": '\U0001D564', + "spades;": '\U00002660', + "spadesuit;": '\U00002660', + "spar;": '\U00002225', + "sqcap;": '\U00002293', + "sqcup;": '\U00002294', + "sqsub;": '\U0000228F', + "sqsube;": '\U00002291', + "sqsubset;": '\U0000228F', + "sqsubseteq;": '\U00002291', + "sqsup;": '\U00002290', + "sqsupe;": '\U00002292', + "sqsupset;": '\U00002290', + "sqsupseteq;": '\U00002292', + "squ;": '\U000025A1', + "square;": '\U000025A1', + "squarf;": '\U000025AA', + "squf;": '\U000025AA', + "srarr;": '\U00002192', + "sscr;": '\U0001D4C8', + "ssetmn;": '\U00002216', + "ssmile;": '\U00002323', + "sstarf;": '\U000022C6', + "star;": '\U00002606', + "starf;": '\U00002605', + "straightepsilon;": '\U000003F5', + "straightphi;": '\U000003D5', + "strns;": '\U000000AF', + "sub;": '\U00002282', + "subE;": '\U00002AC5', + "subdot;": '\U00002ABD', + "sube;": '\U00002286', + "subedot;": '\U00002AC3', + "submult;": '\U00002AC1', + "subnE;": '\U00002ACB', + "subne;": '\U0000228A', + "subplus;": '\U00002ABF', + "subrarr;": '\U00002979', + "subset;": '\U00002282', + "subseteq;": '\U00002286', + "subseteqq;": '\U00002AC5', + "subsetneq;": '\U0000228A', + "subsetneqq;": '\U00002ACB', + "subsim;": '\U00002AC7', + "subsub;": '\U00002AD5', + "subsup;": '\U00002AD3', + "succ;": '\U0000227B', + "succapprox;": '\U00002AB8', + "succcurlyeq;": '\U0000227D', + "succeq;": '\U00002AB0', + "succnapprox;": '\U00002ABA', + "succneqq;": '\U00002AB6', + "succnsim;": '\U000022E9', + "succsim;": '\U0000227F', + "sum;": '\U00002211', + "sung;": '\U0000266A', + "sup;": '\U00002283', + "sup1;": '\U000000B9', + "sup2;": '\U000000B2', + "sup3;": '\U000000B3', + "supE;": '\U00002AC6', + "supdot;": '\U00002ABE', + "supdsub;": '\U00002AD8', + "supe;": '\U00002287', + "supedot;": '\U00002AC4', + "suphsol;": '\U000027C9', + "suphsub;": '\U00002AD7', + "suplarr;": '\U0000297B', + "supmult;": '\U00002AC2', + "supnE;": '\U00002ACC', + "supne;": '\U0000228B', + "supplus;": '\U00002AC0', + "supset;": '\U00002283', + "supseteq;": '\U00002287', + "supseteqq;": '\U00002AC6', + "supsetneq;": '\U0000228B', + "supsetneqq;": '\U00002ACC', + "supsim;": '\U00002AC8', + "supsub;": '\U00002AD4', + "supsup;": '\U00002AD6', + "swArr;": '\U000021D9', + "swarhk;": '\U00002926', + "swarr;": '\U00002199', + "swarrow;": '\U00002199', + "swnwar;": '\U0000292A', + "szlig;": '\U000000DF', + "target;": '\U00002316', + "tau;": '\U000003C4', + "tbrk;": '\U000023B4', + "tcaron;": '\U00000165', + "tcedil;": '\U00000163', + "tcy;": '\U00000442', + "tdot;": '\U000020DB', + "telrec;": '\U00002315', + "tfr;": '\U0001D531', + "there4;": '\U00002234', + "therefore;": '\U00002234', + "theta;": '\U000003B8', + "thetasym;": '\U000003D1', + "thetav;": '\U000003D1', + "thickapprox;": '\U00002248', + "thicksim;": '\U0000223C', + "thinsp;": '\U00002009', + "thkap;": '\U00002248', + "thksim;": '\U0000223C', + "thorn;": '\U000000FE', + "tilde;": '\U000002DC', + "times;": '\U000000D7', + "timesb;": '\U000022A0', + "timesbar;": '\U00002A31', + "timesd;": '\U00002A30', + "tint;": '\U0000222D', + "toea;": '\U00002928', + "top;": '\U000022A4', + "topbot;": '\U00002336', + "topcir;": '\U00002AF1', + "topf;": '\U0001D565', + "topfork;": '\U00002ADA', + "tosa;": '\U00002929', + "tprime;": '\U00002034', + "trade;": '\U00002122', + "triangle;": '\U000025B5', + "triangledown;": '\U000025BF', + "triangleleft;": '\U000025C3', + "trianglelefteq;": '\U000022B4', + "triangleq;": '\U0000225C', + "triangleright;": '\U000025B9', + "trianglerighteq;": '\U000022B5', + "tridot;": '\U000025EC', + "trie;": '\U0000225C', + "triminus;": '\U00002A3A', + "triplus;": '\U00002A39', + "trisb;": '\U000029CD', + "tritime;": '\U00002A3B', + "trpezium;": '\U000023E2', + "tscr;": '\U0001D4C9', + "tscy;": '\U00000446', + "tshcy;": '\U0000045B', + "tstrok;": '\U00000167', + "twixt;": '\U0000226C', + "twoheadleftarrow;": '\U0000219E', + "twoheadrightarrow;": '\U000021A0', + "uArr;": '\U000021D1', + "uHar;": '\U00002963', + "uacute;": '\U000000FA', + "uarr;": '\U00002191', + "ubrcy;": '\U0000045E', + "ubreve;": '\U0000016D', + "ucirc;": '\U000000FB', + "ucy;": '\U00000443', + "udarr;": '\U000021C5', + "udblac;": '\U00000171', + "udhar;": '\U0000296E', + "ufisht;": '\U0000297E', + "ufr;": '\U0001D532', + "ugrave;": '\U000000F9', + "uharl;": '\U000021BF', + "uharr;": '\U000021BE', + "uhblk;": '\U00002580', + "ulcorn;": '\U0000231C', + "ulcorner;": '\U0000231C', + "ulcrop;": '\U0000230F', + "ultri;": '\U000025F8', + "umacr;": '\U0000016B', + "uml;": '\U000000A8', + "uogon;": '\U00000173', + "uopf;": '\U0001D566', + "uparrow;": '\U00002191', + "updownarrow;": '\U00002195', + "upharpoonleft;": '\U000021BF', + "upharpoonright;": '\U000021BE', + "uplus;": '\U0000228E', + "upsi;": '\U000003C5', + "upsih;": '\U000003D2', + "upsilon;": '\U000003C5', + "upuparrows;": '\U000021C8', + "urcorn;": '\U0000231D', + "urcorner;": '\U0000231D', + "urcrop;": '\U0000230E', + "uring;": '\U0000016F', + "urtri;": '\U000025F9', + "uscr;": '\U0001D4CA', + "utdot;": '\U000022F0', + "utilde;": '\U00000169', + "utri;": '\U000025B5', + "utrif;": '\U000025B4', + "uuarr;": '\U000021C8', + "uuml;": '\U000000FC', + "uwangle;": '\U000029A7', + "vArr;": '\U000021D5', + "vBar;": '\U00002AE8', + "vBarv;": '\U00002AE9', + "vDash;": '\U000022A8', + "vangrt;": '\U0000299C', + "varepsilon;": '\U000003F5', + "varkappa;": '\U000003F0', + "varnothing;": '\U00002205', + "varphi;": '\U000003D5', + "varpi;": '\U000003D6', + "varpropto;": '\U0000221D', + "varr;": '\U00002195', + "varrho;": '\U000003F1', + "varsigma;": '\U000003C2', + "vartheta;": '\U000003D1', + "vartriangleleft;": '\U000022B2', + "vartriangleright;": '\U000022B3', + "vcy;": '\U00000432', + "vdash;": '\U000022A2', + "vee;": '\U00002228', + "veebar;": '\U000022BB', + "veeeq;": '\U0000225A', + "vellip;": '\U000022EE', + "verbar;": '\U0000007C', + "vert;": '\U0000007C', + "vfr;": '\U0001D533', + "vltri;": '\U000022B2', + "vopf;": '\U0001D567', + "vprop;": '\U0000221D', + "vrtri;": '\U000022B3', + "vscr;": '\U0001D4CB', + "vzigzag;": '\U0000299A', + "wcirc;": '\U00000175', + "wedbar;": '\U00002A5F', + "wedge;": '\U00002227', + "wedgeq;": '\U00002259', + "weierp;": '\U00002118', + "wfr;": '\U0001D534', + "wopf;": '\U0001D568', + "wp;": '\U00002118', + "wr;": '\U00002240', + "wreath;": '\U00002240', + "wscr;": '\U0001D4CC', + "xcap;": '\U000022C2', + "xcirc;": '\U000025EF', + "xcup;": '\U000022C3', + "xdtri;": '\U000025BD', + "xfr;": '\U0001D535', + "xhArr;": '\U000027FA', + "xharr;": '\U000027F7', + "xi;": '\U000003BE', + "xlArr;": '\U000027F8', + "xlarr;": '\U000027F5', + "xmap;": '\U000027FC', + "xnis;": '\U000022FB', + "xodot;": '\U00002A00', + "xopf;": '\U0001D569', + "xoplus;": '\U00002A01', + "xotime;": '\U00002A02', + "xrArr;": '\U000027F9', + "xrarr;": '\U000027F6', + "xscr;": '\U0001D4CD', + "xsqcup;": '\U00002A06', + "xuplus;": '\U00002A04', + "xutri;": '\U000025B3', + "xvee;": '\U000022C1', + "xwedge;": '\U000022C0', + "yacute;": '\U000000FD', + "yacy;": '\U0000044F', + "ycirc;": '\U00000177', + "ycy;": '\U0000044B', + "yen;": '\U000000A5', + "yfr;": '\U0001D536', + "yicy;": '\U00000457', + "yopf;": '\U0001D56A', + "yscr;": '\U0001D4CE', + "yucy;": '\U0000044E', + "yuml;": '\U000000FF', + "zacute;": '\U0000017A', + "zcaron;": '\U0000017E', + "zcy;": '\U00000437', + "zdot;": '\U0000017C', + "zeetrf;": '\U00002128', + "zeta;": '\U000003B6', + "zfr;": '\U0001D537', + "zhcy;": '\U00000436', + "zigrarr;": '\U000021DD', + "zopf;": '\U0001D56B', + "zscr;": '\U0001D4CF', + "zwj;": '\U0000200D', + "zwnj;": '\U0000200C', + "AElig": '\U000000C6', + "AMP": '\U00000026', + "Aacute": '\U000000C1', + "Acirc": '\U000000C2', + "Agrave": '\U000000C0', + "Aring": '\U000000C5', + "Atilde": '\U000000C3', + "Auml": '\U000000C4', + "COPY": '\U000000A9', + "Ccedil": '\U000000C7', + "ETH": '\U000000D0', + "Eacute": '\U000000C9', + "Ecirc": '\U000000CA', + "Egrave": '\U000000C8', + "Euml": '\U000000CB', + "GT": '\U0000003E', + "Iacute": '\U000000CD', + "Icirc": '\U000000CE', + "Igrave": '\U000000CC', + "Iuml": '\U000000CF', + "LT": '\U0000003C', + "Ntilde": '\U000000D1', + "Oacute": '\U000000D3', + "Ocirc": '\U000000D4', + "Ograve": '\U000000D2', + "Oslash": '\U000000D8', + "Otilde": '\U000000D5', + "Ouml": '\U000000D6', + "QUOT": '\U00000022', + "REG": '\U000000AE', + "THORN": '\U000000DE', + "Uacute": '\U000000DA', + "Ucirc": '\U000000DB', + "Ugrave": '\U000000D9', + "Uuml": '\U000000DC', + "Yacute": '\U000000DD', + "aacute": '\U000000E1', + "acirc": '\U000000E2', + "acute": '\U000000B4', + "aelig": '\U000000E6', + "agrave": '\U000000E0', + "amp": '\U00000026', + "aring": '\U000000E5', + "atilde": '\U000000E3', + "auml": '\U000000E4', + "brvbar": '\U000000A6', + "ccedil": '\U000000E7', + "cedil": '\U000000B8', + "cent": '\U000000A2', + "copy": '\U000000A9', + "curren": '\U000000A4', + "deg": '\U000000B0', + "divide": '\U000000F7', + "eacute": '\U000000E9', + "ecirc": '\U000000EA', + "egrave": '\U000000E8', + "eth": '\U000000F0', + "euml": '\U000000EB', + "frac12": '\U000000BD', + "frac14": '\U000000BC', + "frac34": '\U000000BE', + "gt": '\U0000003E', + "iacute": '\U000000ED', + "icirc": '\U000000EE', + "iexcl": '\U000000A1', + "igrave": '\U000000EC', + "iquest": '\U000000BF', + "iuml": '\U000000EF', + "laquo": '\U000000AB', + "lt": '\U0000003C', + "macr": '\U000000AF', + "micro": '\U000000B5', + "middot": '\U000000B7', + "nbsp": '\U000000A0', + "not": '\U000000AC', + "ntilde": '\U000000F1', + "oacute": '\U000000F3', + "ocirc": '\U000000F4', + "ograve": '\U000000F2', + "ordf": '\U000000AA', + "ordm": '\U000000BA', + "oslash": '\U000000F8', + "otilde": '\U000000F5', + "ouml": '\U000000F6', + "para": '\U000000B6', + "plusmn": '\U000000B1', + "pound": '\U000000A3', + "quot": '\U00000022', + "raquo": '\U000000BB', + "reg": '\U000000AE', + "sect": '\U000000A7', + "shy": '\U000000AD', + "sup1": '\U000000B9', + "sup2": '\U000000B2', + "sup3": '\U000000B3', + "szlig": '\U000000DF', + "thorn": '\U000000FE', + "times": '\U000000D7', + "uacute": '\U000000FA', + "ucirc": '\U000000FB', + "ugrave": '\U000000F9', + "uml": '\U000000A8', + "uuml": '\U000000FC', + "yacute": '\U000000FD', + "yen": '\U000000A5', + "yuml": '\U000000FF', } // HTML entities that are two unicode codepoints. diff --git a/vendor/gx/ipfs/QmQ4hhhYzrEoyPxcVQyBqhf3sshsATKX3D3VJUAGuHzaSD/go-libp2p-quic-transport/crypto.go b/vendor/gx/ipfs/QmQ4hhhYzrEoyPxcVQyBqhf3sshsATKX3D3VJUAGuHzaSD/go-libp2p-quic-transport/crypto.go index d821cf2ab1..255ed57fe9 100644 --- a/vendor/gx/ipfs/QmQ4hhhYzrEoyPxcVQyBqhf3sshsATKX3D3VJUAGuHzaSD/go-libp2p-quic-transport/crypto.go +++ b/vendor/gx/ipfs/QmQ4hhhYzrEoyPxcVQyBqhf3sshsATKX3D3VJUAGuHzaSD/go-libp2p-quic-transport/crypto.go @@ -80,10 +80,10 @@ func keyToCertificate(sk ic.PrivKey) (interface{}, *x509.Certificate, error) { return nil, nil, err } tmpl := &x509.Certificate{ - SerialNumber: sn, - NotBefore: time.Now().Add(-24 * time.Hour), - NotAfter: time.Now().Add(certValidityPeriod), - IsCA: true, + SerialNumber: sn, + NotBefore: time.Now().Add(-24 * time.Hour), + NotAfter: time.Now().Add(certValidityPeriod), + IsCA: true, BasicConstraintsValid: true, } diff --git a/vendor/gx/ipfs/QmRvYNctevGUW52urgmoFZscT6buMKqhHezLUS64WepGWn/go-net/html/entity.go b/vendor/gx/ipfs/QmRvYNctevGUW52urgmoFZscT6buMKqhHezLUS64WepGWn/go-net/html/entity.go index a50c04c60e..b628880a01 100644 --- a/vendor/gx/ipfs/QmRvYNctevGUW52urgmoFZscT6buMKqhHezLUS64WepGWn/go-net/html/entity.go +++ b/vendor/gx/ipfs/QmRvYNctevGUW52urgmoFZscT6buMKqhHezLUS64WepGWn/go-net/html/entity.go @@ -75,2083 +75,2083 @@ var entity = map[string]rune{ "Copf;": '\U00002102', "Coproduct;": '\U00002210', "CounterClockwiseContourIntegral;": '\U00002233', - "Cross;": '\U00002A2F', - "Cscr;": '\U0001D49E', - "Cup;": '\U000022D3', - "CupCap;": '\U0000224D', - "DD;": '\U00002145', - "DDotrahd;": '\U00002911', - "DJcy;": '\U00000402', - "DScy;": '\U00000405', - "DZcy;": '\U0000040F', - "Dagger;": '\U00002021', - "Darr;": '\U000021A1', - "Dashv;": '\U00002AE4', - "Dcaron;": '\U0000010E', - "Dcy;": '\U00000414', - "Del;": '\U00002207', - "Delta;": '\U00000394', - "Dfr;": '\U0001D507', - "DiacriticalAcute;": '\U000000B4', - "DiacriticalDot;": '\U000002D9', - "DiacriticalDoubleAcute;": '\U000002DD', - "DiacriticalGrave;": '\U00000060', - "DiacriticalTilde;": '\U000002DC', - "Diamond;": '\U000022C4', - "DifferentialD;": '\U00002146', - "Dopf;": '\U0001D53B', - "Dot;": '\U000000A8', - "DotDot;": '\U000020DC', - "DotEqual;": '\U00002250', - "DoubleContourIntegral;": '\U0000222F', - "DoubleDot;": '\U000000A8', - "DoubleDownArrow;": '\U000021D3', - "DoubleLeftArrow;": '\U000021D0', - "DoubleLeftRightArrow;": '\U000021D4', - "DoubleLeftTee;": '\U00002AE4', - "DoubleLongLeftArrow;": '\U000027F8', - "DoubleLongLeftRightArrow;": '\U000027FA', - "DoubleLongRightArrow;": '\U000027F9', - "DoubleRightArrow;": '\U000021D2', - "DoubleRightTee;": '\U000022A8', - "DoubleUpArrow;": '\U000021D1', - "DoubleUpDownArrow;": '\U000021D5', - "DoubleVerticalBar;": '\U00002225', - "DownArrow;": '\U00002193', - "DownArrowBar;": '\U00002913', - "DownArrowUpArrow;": '\U000021F5', - "DownBreve;": '\U00000311', - "DownLeftRightVector;": '\U00002950', - "DownLeftTeeVector;": '\U0000295E', - "DownLeftVector;": '\U000021BD', - "DownLeftVectorBar;": '\U00002956', - "DownRightTeeVector;": '\U0000295F', - "DownRightVector;": '\U000021C1', - "DownRightVectorBar;": '\U00002957', - "DownTee;": '\U000022A4', - "DownTeeArrow;": '\U000021A7', - "Downarrow;": '\U000021D3', - "Dscr;": '\U0001D49F', - "Dstrok;": '\U00000110', - "ENG;": '\U0000014A', - "ETH;": '\U000000D0', - "Eacute;": '\U000000C9', - "Ecaron;": '\U0000011A', - "Ecirc;": '\U000000CA', - "Ecy;": '\U0000042D', - "Edot;": '\U00000116', - "Efr;": '\U0001D508', - "Egrave;": '\U000000C8', - "Element;": '\U00002208', - "Emacr;": '\U00000112', - "EmptySmallSquare;": '\U000025FB', - "EmptyVerySmallSquare;": '\U000025AB', - "Eogon;": '\U00000118', - "Eopf;": '\U0001D53C', - "Epsilon;": '\U00000395', - "Equal;": '\U00002A75', - "EqualTilde;": '\U00002242', - "Equilibrium;": '\U000021CC', - "Escr;": '\U00002130', - "Esim;": '\U00002A73', - "Eta;": '\U00000397', - "Euml;": '\U000000CB', - "Exists;": '\U00002203', - "ExponentialE;": '\U00002147', - "Fcy;": '\U00000424', - "Ffr;": '\U0001D509', - "FilledSmallSquare;": '\U000025FC', - "FilledVerySmallSquare;": '\U000025AA', - "Fopf;": '\U0001D53D', - "ForAll;": '\U00002200', - "Fouriertrf;": '\U00002131', - "Fscr;": '\U00002131', - "GJcy;": '\U00000403', - "GT;": '\U0000003E', - "Gamma;": '\U00000393', - "Gammad;": '\U000003DC', - "Gbreve;": '\U0000011E', - "Gcedil;": '\U00000122', - "Gcirc;": '\U0000011C', - "Gcy;": '\U00000413', - "Gdot;": '\U00000120', - "Gfr;": '\U0001D50A', - "Gg;": '\U000022D9', - "Gopf;": '\U0001D53E', - "GreaterEqual;": '\U00002265', - "GreaterEqualLess;": '\U000022DB', - "GreaterFullEqual;": '\U00002267', - "GreaterGreater;": '\U00002AA2', - "GreaterLess;": '\U00002277', - "GreaterSlantEqual;": '\U00002A7E', - "GreaterTilde;": '\U00002273', - "Gscr;": '\U0001D4A2', - "Gt;": '\U0000226B', - "HARDcy;": '\U0000042A', - "Hacek;": '\U000002C7', - "Hat;": '\U0000005E', - "Hcirc;": '\U00000124', - "Hfr;": '\U0000210C', - "HilbertSpace;": '\U0000210B', - "Hopf;": '\U0000210D', - "HorizontalLine;": '\U00002500', - "Hscr;": '\U0000210B', - "Hstrok;": '\U00000126', - "HumpDownHump;": '\U0000224E', - "HumpEqual;": '\U0000224F', - "IEcy;": '\U00000415', - "IJlig;": '\U00000132', - "IOcy;": '\U00000401', - "Iacute;": '\U000000CD', - "Icirc;": '\U000000CE', - "Icy;": '\U00000418', - "Idot;": '\U00000130', - "Ifr;": '\U00002111', - "Igrave;": '\U000000CC', - "Im;": '\U00002111', - "Imacr;": '\U0000012A', - "ImaginaryI;": '\U00002148', - "Implies;": '\U000021D2', - "Int;": '\U0000222C', - "Integral;": '\U0000222B', - "Intersection;": '\U000022C2', - "InvisibleComma;": '\U00002063', - "InvisibleTimes;": '\U00002062', - "Iogon;": '\U0000012E', - "Iopf;": '\U0001D540', - "Iota;": '\U00000399', - "Iscr;": '\U00002110', - "Itilde;": '\U00000128', - "Iukcy;": '\U00000406', - "Iuml;": '\U000000CF', - "Jcirc;": '\U00000134', - "Jcy;": '\U00000419', - "Jfr;": '\U0001D50D', - "Jopf;": '\U0001D541', - "Jscr;": '\U0001D4A5', - "Jsercy;": '\U00000408', - "Jukcy;": '\U00000404', - "KHcy;": '\U00000425', - "KJcy;": '\U0000040C', - "Kappa;": '\U0000039A', - "Kcedil;": '\U00000136', - "Kcy;": '\U0000041A', - "Kfr;": '\U0001D50E', - "Kopf;": '\U0001D542', - "Kscr;": '\U0001D4A6', - "LJcy;": '\U00000409', - "LT;": '\U0000003C', - "Lacute;": '\U00000139', - "Lambda;": '\U0000039B', - "Lang;": '\U000027EA', - "Laplacetrf;": '\U00002112', - "Larr;": '\U0000219E', - "Lcaron;": '\U0000013D', - "Lcedil;": '\U0000013B', - "Lcy;": '\U0000041B', - "LeftAngleBracket;": '\U000027E8', - "LeftArrow;": '\U00002190', - "LeftArrowBar;": '\U000021E4', - "LeftArrowRightArrow;": '\U000021C6', - "LeftCeiling;": '\U00002308', - "LeftDoubleBracket;": '\U000027E6', - "LeftDownTeeVector;": '\U00002961', - "LeftDownVector;": '\U000021C3', - "LeftDownVectorBar;": '\U00002959', - "LeftFloor;": '\U0000230A', - "LeftRightArrow;": '\U00002194', - "LeftRightVector;": '\U0000294E', - "LeftTee;": '\U000022A3', - "LeftTeeArrow;": '\U000021A4', - "LeftTeeVector;": '\U0000295A', - "LeftTriangle;": '\U000022B2', - "LeftTriangleBar;": '\U000029CF', - "LeftTriangleEqual;": '\U000022B4', - "LeftUpDownVector;": '\U00002951', - "LeftUpTeeVector;": '\U00002960', - "LeftUpVector;": '\U000021BF', - "LeftUpVectorBar;": '\U00002958', - "LeftVector;": '\U000021BC', - "LeftVectorBar;": '\U00002952', - "Leftarrow;": '\U000021D0', - "Leftrightarrow;": '\U000021D4', - "LessEqualGreater;": '\U000022DA', - "LessFullEqual;": '\U00002266', - "LessGreater;": '\U00002276', - "LessLess;": '\U00002AA1', - "LessSlantEqual;": '\U00002A7D', - "LessTilde;": '\U00002272', - "Lfr;": '\U0001D50F', - "Ll;": '\U000022D8', - "Lleftarrow;": '\U000021DA', - "Lmidot;": '\U0000013F', - "LongLeftArrow;": '\U000027F5', - "LongLeftRightArrow;": '\U000027F7', - "LongRightArrow;": '\U000027F6', - "Longleftarrow;": '\U000027F8', - "Longleftrightarrow;": '\U000027FA', - "Longrightarrow;": '\U000027F9', - "Lopf;": '\U0001D543', - "LowerLeftArrow;": '\U00002199', - "LowerRightArrow;": '\U00002198', - "Lscr;": '\U00002112', - "Lsh;": '\U000021B0', - "Lstrok;": '\U00000141', - "Lt;": '\U0000226A', - "Map;": '\U00002905', - "Mcy;": '\U0000041C', - "MediumSpace;": '\U0000205F', - "Mellintrf;": '\U00002133', - "Mfr;": '\U0001D510', - "MinusPlus;": '\U00002213', - "Mopf;": '\U0001D544', - "Mscr;": '\U00002133', - "Mu;": '\U0000039C', - "NJcy;": '\U0000040A', - "Nacute;": '\U00000143', - "Ncaron;": '\U00000147', - "Ncedil;": '\U00000145', - "Ncy;": '\U0000041D', - "NegativeMediumSpace;": '\U0000200B', - "NegativeThickSpace;": '\U0000200B', - "NegativeThinSpace;": '\U0000200B', - "NegativeVeryThinSpace;": '\U0000200B', - "NestedGreaterGreater;": '\U0000226B', - "NestedLessLess;": '\U0000226A', - "NewLine;": '\U0000000A', - "Nfr;": '\U0001D511', - "NoBreak;": '\U00002060', - "NonBreakingSpace;": '\U000000A0', - "Nopf;": '\U00002115', - "Not;": '\U00002AEC', - "NotCongruent;": '\U00002262', - "NotCupCap;": '\U0000226D', - "NotDoubleVerticalBar;": '\U00002226', - "NotElement;": '\U00002209', - "NotEqual;": '\U00002260', - "NotExists;": '\U00002204', - "NotGreater;": '\U0000226F', - "NotGreaterEqual;": '\U00002271', - "NotGreaterLess;": '\U00002279', - "NotGreaterTilde;": '\U00002275', - "NotLeftTriangle;": '\U000022EA', - "NotLeftTriangleEqual;": '\U000022EC', - "NotLess;": '\U0000226E', - "NotLessEqual;": '\U00002270', - "NotLessGreater;": '\U00002278', - "NotLessTilde;": '\U00002274', - "NotPrecedes;": '\U00002280', - "NotPrecedesSlantEqual;": '\U000022E0', - "NotReverseElement;": '\U0000220C', - "NotRightTriangle;": '\U000022EB', - "NotRightTriangleEqual;": '\U000022ED', - "NotSquareSubsetEqual;": '\U000022E2', - "NotSquareSupersetEqual;": '\U000022E3', - "NotSubsetEqual;": '\U00002288', - "NotSucceeds;": '\U00002281', - "NotSucceedsSlantEqual;": '\U000022E1', - "NotSupersetEqual;": '\U00002289', - "NotTilde;": '\U00002241', - "NotTildeEqual;": '\U00002244', - "NotTildeFullEqual;": '\U00002247', - "NotTildeTilde;": '\U00002249', - "NotVerticalBar;": '\U00002224', - "Nscr;": '\U0001D4A9', - "Ntilde;": '\U000000D1', - "Nu;": '\U0000039D', - "OElig;": '\U00000152', - "Oacute;": '\U000000D3', - "Ocirc;": '\U000000D4', - "Ocy;": '\U0000041E', - "Odblac;": '\U00000150', - "Ofr;": '\U0001D512', - "Ograve;": '\U000000D2', - "Omacr;": '\U0000014C', - "Omega;": '\U000003A9', - "Omicron;": '\U0000039F', - "Oopf;": '\U0001D546', - "OpenCurlyDoubleQuote;": '\U0000201C', - "OpenCurlyQuote;": '\U00002018', - "Or;": '\U00002A54', - "Oscr;": '\U0001D4AA', - "Oslash;": '\U000000D8', - "Otilde;": '\U000000D5', - "Otimes;": '\U00002A37', - "Ouml;": '\U000000D6', - "OverBar;": '\U0000203E', - "OverBrace;": '\U000023DE', - "OverBracket;": '\U000023B4', - "OverParenthesis;": '\U000023DC', - "PartialD;": '\U00002202', - "Pcy;": '\U0000041F', - "Pfr;": '\U0001D513', - "Phi;": '\U000003A6', - "Pi;": '\U000003A0', - "PlusMinus;": '\U000000B1', - "Poincareplane;": '\U0000210C', - "Popf;": '\U00002119', - "Pr;": '\U00002ABB', - "Precedes;": '\U0000227A', - "PrecedesEqual;": '\U00002AAF', - "PrecedesSlantEqual;": '\U0000227C', - "PrecedesTilde;": '\U0000227E', - "Prime;": '\U00002033', - "Product;": '\U0000220F', - "Proportion;": '\U00002237', - "Proportional;": '\U0000221D', - "Pscr;": '\U0001D4AB', - "Psi;": '\U000003A8', - "QUOT;": '\U00000022', - "Qfr;": '\U0001D514', - "Qopf;": '\U0000211A', - "Qscr;": '\U0001D4AC', - "RBarr;": '\U00002910', - "REG;": '\U000000AE', - "Racute;": '\U00000154', - "Rang;": '\U000027EB', - "Rarr;": '\U000021A0', - "Rarrtl;": '\U00002916', - "Rcaron;": '\U00000158', - "Rcedil;": '\U00000156', - "Rcy;": '\U00000420', - "Re;": '\U0000211C', - "ReverseElement;": '\U0000220B', - "ReverseEquilibrium;": '\U000021CB', - "ReverseUpEquilibrium;": '\U0000296F', - "Rfr;": '\U0000211C', - "Rho;": '\U000003A1', - "RightAngleBracket;": '\U000027E9', - "RightArrow;": '\U00002192', - "RightArrowBar;": '\U000021E5', - "RightArrowLeftArrow;": '\U000021C4', - "RightCeiling;": '\U00002309', - "RightDoubleBracket;": '\U000027E7', - "RightDownTeeVector;": '\U0000295D', - "RightDownVector;": '\U000021C2', - "RightDownVectorBar;": '\U00002955', - "RightFloor;": '\U0000230B', - "RightTee;": '\U000022A2', - "RightTeeArrow;": '\U000021A6', - "RightTeeVector;": '\U0000295B', - "RightTriangle;": '\U000022B3', - "RightTriangleBar;": '\U000029D0', - "RightTriangleEqual;": '\U000022B5', - "RightUpDownVector;": '\U0000294F', - "RightUpTeeVector;": '\U0000295C', - "RightUpVector;": '\U000021BE', - "RightUpVectorBar;": '\U00002954', - "RightVector;": '\U000021C0', - "RightVectorBar;": '\U00002953', - "Rightarrow;": '\U000021D2', - "Ropf;": '\U0000211D', - "RoundImplies;": '\U00002970', - "Rrightarrow;": '\U000021DB', - "Rscr;": '\U0000211B', - "Rsh;": '\U000021B1', - "RuleDelayed;": '\U000029F4', - "SHCHcy;": '\U00000429', - "SHcy;": '\U00000428', - "SOFTcy;": '\U0000042C', - "Sacute;": '\U0000015A', - "Sc;": '\U00002ABC', - "Scaron;": '\U00000160', - "Scedil;": '\U0000015E', - "Scirc;": '\U0000015C', - "Scy;": '\U00000421', - "Sfr;": '\U0001D516', - "ShortDownArrow;": '\U00002193', - "ShortLeftArrow;": '\U00002190', - "ShortRightArrow;": '\U00002192', - "ShortUpArrow;": '\U00002191', - "Sigma;": '\U000003A3', - "SmallCircle;": '\U00002218', - "Sopf;": '\U0001D54A', - "Sqrt;": '\U0000221A', - "Square;": '\U000025A1', - "SquareIntersection;": '\U00002293', - "SquareSubset;": '\U0000228F', - "SquareSubsetEqual;": '\U00002291', - "SquareSuperset;": '\U00002290', - "SquareSupersetEqual;": '\U00002292', - "SquareUnion;": '\U00002294', - "Sscr;": '\U0001D4AE', - "Star;": '\U000022C6', - "Sub;": '\U000022D0', - "Subset;": '\U000022D0', - "SubsetEqual;": '\U00002286', - "Succeeds;": '\U0000227B', - "SucceedsEqual;": '\U00002AB0', - "SucceedsSlantEqual;": '\U0000227D', - "SucceedsTilde;": '\U0000227F', - "SuchThat;": '\U0000220B', - "Sum;": '\U00002211', - "Sup;": '\U000022D1', - "Superset;": '\U00002283', - "SupersetEqual;": '\U00002287', - "Supset;": '\U000022D1', - "THORN;": '\U000000DE', - "TRADE;": '\U00002122', - "TSHcy;": '\U0000040B', - "TScy;": '\U00000426', - "Tab;": '\U00000009', - "Tau;": '\U000003A4', - "Tcaron;": '\U00000164', - "Tcedil;": '\U00000162', - "Tcy;": '\U00000422', - "Tfr;": '\U0001D517', - "Therefore;": '\U00002234', - "Theta;": '\U00000398', - "ThinSpace;": '\U00002009', - "Tilde;": '\U0000223C', - "TildeEqual;": '\U00002243', - "TildeFullEqual;": '\U00002245', - "TildeTilde;": '\U00002248', - "Topf;": '\U0001D54B', - "TripleDot;": '\U000020DB', - "Tscr;": '\U0001D4AF', - "Tstrok;": '\U00000166', - "Uacute;": '\U000000DA', - "Uarr;": '\U0000219F', - "Uarrocir;": '\U00002949', - "Ubrcy;": '\U0000040E', - "Ubreve;": '\U0000016C', - "Ucirc;": '\U000000DB', - "Ucy;": '\U00000423', - "Udblac;": '\U00000170', - "Ufr;": '\U0001D518', - "Ugrave;": '\U000000D9', - "Umacr;": '\U0000016A', - "UnderBar;": '\U0000005F', - "UnderBrace;": '\U000023DF', - "UnderBracket;": '\U000023B5', - "UnderParenthesis;": '\U000023DD', - "Union;": '\U000022C3', - "UnionPlus;": '\U0000228E', - "Uogon;": '\U00000172', - "Uopf;": '\U0001D54C', - "UpArrow;": '\U00002191', - "UpArrowBar;": '\U00002912', - "UpArrowDownArrow;": '\U000021C5', - "UpDownArrow;": '\U00002195', - "UpEquilibrium;": '\U0000296E', - "UpTee;": '\U000022A5', - "UpTeeArrow;": '\U000021A5', - "Uparrow;": '\U000021D1', - "Updownarrow;": '\U000021D5', - "UpperLeftArrow;": '\U00002196', - "UpperRightArrow;": '\U00002197', - "Upsi;": '\U000003D2', - "Upsilon;": '\U000003A5', - "Uring;": '\U0000016E', - "Uscr;": '\U0001D4B0', - "Utilde;": '\U00000168', - "Uuml;": '\U000000DC', - "VDash;": '\U000022AB', - "Vbar;": '\U00002AEB', - "Vcy;": '\U00000412', - "Vdash;": '\U000022A9', - "Vdashl;": '\U00002AE6', - "Vee;": '\U000022C1', - "Verbar;": '\U00002016', - "Vert;": '\U00002016', - "VerticalBar;": '\U00002223', - "VerticalLine;": '\U0000007C', - "VerticalSeparator;": '\U00002758', - "VerticalTilde;": '\U00002240', - "VeryThinSpace;": '\U0000200A', - "Vfr;": '\U0001D519', - "Vopf;": '\U0001D54D', - "Vscr;": '\U0001D4B1', - "Vvdash;": '\U000022AA', - "Wcirc;": '\U00000174', - "Wedge;": '\U000022C0', - "Wfr;": '\U0001D51A', - "Wopf;": '\U0001D54E', - "Wscr;": '\U0001D4B2', - "Xfr;": '\U0001D51B', - "Xi;": '\U0000039E', - "Xopf;": '\U0001D54F', - "Xscr;": '\U0001D4B3', - "YAcy;": '\U0000042F', - "YIcy;": '\U00000407', - "YUcy;": '\U0000042E', - "Yacute;": '\U000000DD', - "Ycirc;": '\U00000176', - "Ycy;": '\U0000042B', - "Yfr;": '\U0001D51C', - "Yopf;": '\U0001D550', - "Yscr;": '\U0001D4B4', - "Yuml;": '\U00000178', - "ZHcy;": '\U00000416', - "Zacute;": '\U00000179', - "Zcaron;": '\U0000017D', - "Zcy;": '\U00000417', - "Zdot;": '\U0000017B', - "ZeroWidthSpace;": '\U0000200B', - "Zeta;": '\U00000396', - "Zfr;": '\U00002128', - "Zopf;": '\U00002124', - "Zscr;": '\U0001D4B5', - "aacute;": '\U000000E1', - "abreve;": '\U00000103', - "ac;": '\U0000223E', - "acd;": '\U0000223F', - "acirc;": '\U000000E2', - "acute;": '\U000000B4', - "acy;": '\U00000430', - "aelig;": '\U000000E6', - "af;": '\U00002061', - "afr;": '\U0001D51E', - "agrave;": '\U000000E0', - "alefsym;": '\U00002135', - "aleph;": '\U00002135', - "alpha;": '\U000003B1', - "amacr;": '\U00000101', - "amalg;": '\U00002A3F', - "amp;": '\U00000026', - "and;": '\U00002227', - "andand;": '\U00002A55', - "andd;": '\U00002A5C', - "andslope;": '\U00002A58', - "andv;": '\U00002A5A', - "ang;": '\U00002220', - "ange;": '\U000029A4', - "angle;": '\U00002220', - "angmsd;": '\U00002221', - "angmsdaa;": '\U000029A8', - "angmsdab;": '\U000029A9', - "angmsdac;": '\U000029AA', - "angmsdad;": '\U000029AB', - "angmsdae;": '\U000029AC', - "angmsdaf;": '\U000029AD', - "angmsdag;": '\U000029AE', - "angmsdah;": '\U000029AF', - "angrt;": '\U0000221F', - "angrtvb;": '\U000022BE', - "angrtvbd;": '\U0000299D', - "angsph;": '\U00002222', - "angst;": '\U000000C5', - "angzarr;": '\U0000237C', - "aogon;": '\U00000105', - "aopf;": '\U0001D552', - "ap;": '\U00002248', - "apE;": '\U00002A70', - "apacir;": '\U00002A6F', - "ape;": '\U0000224A', - "apid;": '\U0000224B', - "apos;": '\U00000027', - "approx;": '\U00002248', - "approxeq;": '\U0000224A', - "aring;": '\U000000E5', - "ascr;": '\U0001D4B6', - "ast;": '\U0000002A', - "asymp;": '\U00002248', - "asympeq;": '\U0000224D', - "atilde;": '\U000000E3', - "auml;": '\U000000E4', - "awconint;": '\U00002233', - "awint;": '\U00002A11', - "bNot;": '\U00002AED', - "backcong;": '\U0000224C', - "backepsilon;": '\U000003F6', - "backprime;": '\U00002035', - "backsim;": '\U0000223D', - "backsimeq;": '\U000022CD', - "barvee;": '\U000022BD', - "barwed;": '\U00002305', - "barwedge;": '\U00002305', - "bbrk;": '\U000023B5', - "bbrktbrk;": '\U000023B6', - "bcong;": '\U0000224C', - "bcy;": '\U00000431', - "bdquo;": '\U0000201E', - "becaus;": '\U00002235', - "because;": '\U00002235', - "bemptyv;": '\U000029B0', - "bepsi;": '\U000003F6', - "bernou;": '\U0000212C', - "beta;": '\U000003B2', - "beth;": '\U00002136', - "between;": '\U0000226C', - "bfr;": '\U0001D51F', - "bigcap;": '\U000022C2', - "bigcirc;": '\U000025EF', - "bigcup;": '\U000022C3', - "bigodot;": '\U00002A00', - "bigoplus;": '\U00002A01', - "bigotimes;": '\U00002A02', - "bigsqcup;": '\U00002A06', - "bigstar;": '\U00002605', - "bigtriangledown;": '\U000025BD', - "bigtriangleup;": '\U000025B3', - "biguplus;": '\U00002A04', - "bigvee;": '\U000022C1', - "bigwedge;": '\U000022C0', - "bkarow;": '\U0000290D', - "blacklozenge;": '\U000029EB', - "blacksquare;": '\U000025AA', - "blacktriangle;": '\U000025B4', - "blacktriangledown;": '\U000025BE', - "blacktriangleleft;": '\U000025C2', - "blacktriangleright;": '\U000025B8', - "blank;": '\U00002423', - "blk12;": '\U00002592', - "blk14;": '\U00002591', - "blk34;": '\U00002593', - "block;": '\U00002588', - "bnot;": '\U00002310', - "bopf;": '\U0001D553', - "bot;": '\U000022A5', - "bottom;": '\U000022A5', - "bowtie;": '\U000022C8', - "boxDL;": '\U00002557', - "boxDR;": '\U00002554', - "boxDl;": '\U00002556', - "boxDr;": '\U00002553', - "boxH;": '\U00002550', - "boxHD;": '\U00002566', - "boxHU;": '\U00002569', - "boxHd;": '\U00002564', - "boxHu;": '\U00002567', - "boxUL;": '\U0000255D', - "boxUR;": '\U0000255A', - "boxUl;": '\U0000255C', - "boxUr;": '\U00002559', - "boxV;": '\U00002551', - "boxVH;": '\U0000256C', - "boxVL;": '\U00002563', - "boxVR;": '\U00002560', - "boxVh;": '\U0000256B', - "boxVl;": '\U00002562', - "boxVr;": '\U0000255F', - "boxbox;": '\U000029C9', - "boxdL;": '\U00002555', - "boxdR;": '\U00002552', - "boxdl;": '\U00002510', - "boxdr;": '\U0000250C', - "boxh;": '\U00002500', - "boxhD;": '\U00002565', - "boxhU;": '\U00002568', - "boxhd;": '\U0000252C', - "boxhu;": '\U00002534', - "boxminus;": '\U0000229F', - "boxplus;": '\U0000229E', - "boxtimes;": '\U000022A0', - "boxuL;": '\U0000255B', - "boxuR;": '\U00002558', - "boxul;": '\U00002518', - "boxur;": '\U00002514', - "boxv;": '\U00002502', - "boxvH;": '\U0000256A', - "boxvL;": '\U00002561', - "boxvR;": '\U0000255E', - "boxvh;": '\U0000253C', - "boxvl;": '\U00002524', - "boxvr;": '\U0000251C', - "bprime;": '\U00002035', - "breve;": '\U000002D8', - "brvbar;": '\U000000A6', - "bscr;": '\U0001D4B7', - "bsemi;": '\U0000204F', - "bsim;": '\U0000223D', - "bsime;": '\U000022CD', - "bsol;": '\U0000005C', - "bsolb;": '\U000029C5', - "bsolhsub;": '\U000027C8', - "bull;": '\U00002022', - "bullet;": '\U00002022', - "bump;": '\U0000224E', - "bumpE;": '\U00002AAE', - "bumpe;": '\U0000224F', - "bumpeq;": '\U0000224F', - "cacute;": '\U00000107', - "cap;": '\U00002229', - "capand;": '\U00002A44', - "capbrcup;": '\U00002A49', - "capcap;": '\U00002A4B', - "capcup;": '\U00002A47', - "capdot;": '\U00002A40', - "caret;": '\U00002041', - "caron;": '\U000002C7', - "ccaps;": '\U00002A4D', - "ccaron;": '\U0000010D', - "ccedil;": '\U000000E7', - "ccirc;": '\U00000109', - "ccups;": '\U00002A4C', - "ccupssm;": '\U00002A50', - "cdot;": '\U0000010B', - "cedil;": '\U000000B8', - "cemptyv;": '\U000029B2', - "cent;": '\U000000A2', - "centerdot;": '\U000000B7', - "cfr;": '\U0001D520', - "chcy;": '\U00000447', - "check;": '\U00002713', - "checkmark;": '\U00002713', - "chi;": '\U000003C7', - "cir;": '\U000025CB', - "cirE;": '\U000029C3', - "circ;": '\U000002C6', - "circeq;": '\U00002257', - "circlearrowleft;": '\U000021BA', - "circlearrowright;": '\U000021BB', - "circledR;": '\U000000AE', - "circledS;": '\U000024C8', - "circledast;": '\U0000229B', - "circledcirc;": '\U0000229A', - "circleddash;": '\U0000229D', - "cire;": '\U00002257', - "cirfnint;": '\U00002A10', - "cirmid;": '\U00002AEF', - "cirscir;": '\U000029C2', - "clubs;": '\U00002663', - "clubsuit;": '\U00002663', - "colon;": '\U0000003A', - "colone;": '\U00002254', - "coloneq;": '\U00002254', - "comma;": '\U0000002C', - "commat;": '\U00000040', - "comp;": '\U00002201', - "compfn;": '\U00002218', - "complement;": '\U00002201', - "complexes;": '\U00002102', - "cong;": '\U00002245', - "congdot;": '\U00002A6D', - "conint;": '\U0000222E', - "copf;": '\U0001D554', - "coprod;": '\U00002210', - "copy;": '\U000000A9', - "copysr;": '\U00002117', - "crarr;": '\U000021B5', - "cross;": '\U00002717', - "cscr;": '\U0001D4B8', - "csub;": '\U00002ACF', - "csube;": '\U00002AD1', - "csup;": '\U00002AD0', - "csupe;": '\U00002AD2', - "ctdot;": '\U000022EF', - "cudarrl;": '\U00002938', - "cudarrr;": '\U00002935', - "cuepr;": '\U000022DE', - "cuesc;": '\U000022DF', - "cularr;": '\U000021B6', - "cularrp;": '\U0000293D', - "cup;": '\U0000222A', - "cupbrcap;": '\U00002A48', - "cupcap;": '\U00002A46', - "cupcup;": '\U00002A4A', - "cupdot;": '\U0000228D', - "cupor;": '\U00002A45', - "curarr;": '\U000021B7', - "curarrm;": '\U0000293C', - "curlyeqprec;": '\U000022DE', - "curlyeqsucc;": '\U000022DF', - "curlyvee;": '\U000022CE', - "curlywedge;": '\U000022CF', - "curren;": '\U000000A4', - "curvearrowleft;": '\U000021B6', - "curvearrowright;": '\U000021B7', - "cuvee;": '\U000022CE', - "cuwed;": '\U000022CF', - "cwconint;": '\U00002232', - "cwint;": '\U00002231', - "cylcty;": '\U0000232D', - "dArr;": '\U000021D3', - "dHar;": '\U00002965', - "dagger;": '\U00002020', - "daleth;": '\U00002138', - "darr;": '\U00002193', - "dash;": '\U00002010', - "dashv;": '\U000022A3', - "dbkarow;": '\U0000290F', - "dblac;": '\U000002DD', - "dcaron;": '\U0000010F', - "dcy;": '\U00000434', - "dd;": '\U00002146', - "ddagger;": '\U00002021', - "ddarr;": '\U000021CA', - "ddotseq;": '\U00002A77', - "deg;": '\U000000B0', - "delta;": '\U000003B4', - "demptyv;": '\U000029B1', - "dfisht;": '\U0000297F', - "dfr;": '\U0001D521', - "dharl;": '\U000021C3', - "dharr;": '\U000021C2', - "diam;": '\U000022C4', - "diamond;": '\U000022C4', - "diamondsuit;": '\U00002666', - "diams;": '\U00002666', - "die;": '\U000000A8', - "digamma;": '\U000003DD', - "disin;": '\U000022F2', - "div;": '\U000000F7', - "divide;": '\U000000F7', - "divideontimes;": '\U000022C7', - "divonx;": '\U000022C7', - "djcy;": '\U00000452', - "dlcorn;": '\U0000231E', - "dlcrop;": '\U0000230D', - "dollar;": '\U00000024', - "dopf;": '\U0001D555', - "dot;": '\U000002D9', - "doteq;": '\U00002250', - "doteqdot;": '\U00002251', - "dotminus;": '\U00002238', - "dotplus;": '\U00002214', - "dotsquare;": '\U000022A1', - "doublebarwedge;": '\U00002306', - "downarrow;": '\U00002193', - "downdownarrows;": '\U000021CA', - "downharpoonleft;": '\U000021C3', - "downharpoonright;": '\U000021C2', - "drbkarow;": '\U00002910', - "drcorn;": '\U0000231F', - "drcrop;": '\U0000230C', - "dscr;": '\U0001D4B9', - "dscy;": '\U00000455', - "dsol;": '\U000029F6', - "dstrok;": '\U00000111', - "dtdot;": '\U000022F1', - "dtri;": '\U000025BF', - "dtrif;": '\U000025BE', - "duarr;": '\U000021F5', - "duhar;": '\U0000296F', - "dwangle;": '\U000029A6', - "dzcy;": '\U0000045F', - "dzigrarr;": '\U000027FF', - "eDDot;": '\U00002A77', - "eDot;": '\U00002251', - "eacute;": '\U000000E9', - "easter;": '\U00002A6E', - "ecaron;": '\U0000011B', - "ecir;": '\U00002256', - "ecirc;": '\U000000EA', - "ecolon;": '\U00002255', - "ecy;": '\U0000044D', - "edot;": '\U00000117', - "ee;": '\U00002147', - "efDot;": '\U00002252', - "efr;": '\U0001D522', - "eg;": '\U00002A9A', - "egrave;": '\U000000E8', - "egs;": '\U00002A96', - "egsdot;": '\U00002A98', - "el;": '\U00002A99', - "elinters;": '\U000023E7', - "ell;": '\U00002113', - "els;": '\U00002A95', - "elsdot;": '\U00002A97', - "emacr;": '\U00000113', - "empty;": '\U00002205', - "emptyset;": '\U00002205', - "emptyv;": '\U00002205', - "emsp;": '\U00002003', - "emsp13;": '\U00002004', - "emsp14;": '\U00002005', - "eng;": '\U0000014B', - "ensp;": '\U00002002', - "eogon;": '\U00000119', - "eopf;": '\U0001D556', - "epar;": '\U000022D5', - "eparsl;": '\U000029E3', - "eplus;": '\U00002A71', - "epsi;": '\U000003B5', - "epsilon;": '\U000003B5', - "epsiv;": '\U000003F5', - "eqcirc;": '\U00002256', - "eqcolon;": '\U00002255', - "eqsim;": '\U00002242', - "eqslantgtr;": '\U00002A96', - "eqslantless;": '\U00002A95', - "equals;": '\U0000003D', - "equest;": '\U0000225F', - "equiv;": '\U00002261', - "equivDD;": '\U00002A78', - "eqvparsl;": '\U000029E5', - "erDot;": '\U00002253', - "erarr;": '\U00002971', - "escr;": '\U0000212F', - "esdot;": '\U00002250', - "esim;": '\U00002242', - "eta;": '\U000003B7', - "eth;": '\U000000F0', - "euml;": '\U000000EB', - "euro;": '\U000020AC', - "excl;": '\U00000021', - "exist;": '\U00002203', - "expectation;": '\U00002130', - "exponentiale;": '\U00002147', - "fallingdotseq;": '\U00002252', - "fcy;": '\U00000444', - "female;": '\U00002640', - "ffilig;": '\U0000FB03', - "fflig;": '\U0000FB00', - "ffllig;": '\U0000FB04', - "ffr;": '\U0001D523', - "filig;": '\U0000FB01', - "flat;": '\U0000266D', - "fllig;": '\U0000FB02', - "fltns;": '\U000025B1', - "fnof;": '\U00000192', - "fopf;": '\U0001D557', - "forall;": '\U00002200', - "fork;": '\U000022D4', - "forkv;": '\U00002AD9', - "fpartint;": '\U00002A0D', - "frac12;": '\U000000BD', - "frac13;": '\U00002153', - "frac14;": '\U000000BC', - "frac15;": '\U00002155', - "frac16;": '\U00002159', - "frac18;": '\U0000215B', - "frac23;": '\U00002154', - "frac25;": '\U00002156', - "frac34;": '\U000000BE', - "frac35;": '\U00002157', - "frac38;": '\U0000215C', - "frac45;": '\U00002158', - "frac56;": '\U0000215A', - "frac58;": '\U0000215D', - "frac78;": '\U0000215E', - "frasl;": '\U00002044', - "frown;": '\U00002322', - "fscr;": '\U0001D4BB', - "gE;": '\U00002267', - "gEl;": '\U00002A8C', - "gacute;": '\U000001F5', - "gamma;": '\U000003B3', - "gammad;": '\U000003DD', - "gap;": '\U00002A86', - "gbreve;": '\U0000011F', - "gcirc;": '\U0000011D', - "gcy;": '\U00000433', - "gdot;": '\U00000121', - "ge;": '\U00002265', - "gel;": '\U000022DB', - "geq;": '\U00002265', - "geqq;": '\U00002267', - "geqslant;": '\U00002A7E', - "ges;": '\U00002A7E', - "gescc;": '\U00002AA9', - "gesdot;": '\U00002A80', - "gesdoto;": '\U00002A82', - "gesdotol;": '\U00002A84', - "gesles;": '\U00002A94', - "gfr;": '\U0001D524', - "gg;": '\U0000226B', - "ggg;": '\U000022D9', - "gimel;": '\U00002137', - "gjcy;": '\U00000453', - "gl;": '\U00002277', - "glE;": '\U00002A92', - "gla;": '\U00002AA5', - "glj;": '\U00002AA4', - "gnE;": '\U00002269', - "gnap;": '\U00002A8A', - "gnapprox;": '\U00002A8A', - "gne;": '\U00002A88', - "gneq;": '\U00002A88', - "gneqq;": '\U00002269', - "gnsim;": '\U000022E7', - "gopf;": '\U0001D558', - "grave;": '\U00000060', - "gscr;": '\U0000210A', - "gsim;": '\U00002273', - "gsime;": '\U00002A8E', - "gsiml;": '\U00002A90', - "gt;": '\U0000003E', - "gtcc;": '\U00002AA7', - "gtcir;": '\U00002A7A', - "gtdot;": '\U000022D7', - "gtlPar;": '\U00002995', - "gtquest;": '\U00002A7C', - "gtrapprox;": '\U00002A86', - "gtrarr;": '\U00002978', - "gtrdot;": '\U000022D7', - "gtreqless;": '\U000022DB', - "gtreqqless;": '\U00002A8C', - "gtrless;": '\U00002277', - "gtrsim;": '\U00002273', - "hArr;": '\U000021D4', - "hairsp;": '\U0000200A', - "half;": '\U000000BD', - "hamilt;": '\U0000210B', - "hardcy;": '\U0000044A', - "harr;": '\U00002194', - "harrcir;": '\U00002948', - "harrw;": '\U000021AD', - "hbar;": '\U0000210F', - "hcirc;": '\U00000125', - "hearts;": '\U00002665', - "heartsuit;": '\U00002665', - "hellip;": '\U00002026', - "hercon;": '\U000022B9', - "hfr;": '\U0001D525', - "hksearow;": '\U00002925', - "hkswarow;": '\U00002926', - "hoarr;": '\U000021FF', - "homtht;": '\U0000223B', - "hookleftarrow;": '\U000021A9', - "hookrightarrow;": '\U000021AA', - "hopf;": '\U0001D559', - "horbar;": '\U00002015', - "hscr;": '\U0001D4BD', - "hslash;": '\U0000210F', - "hstrok;": '\U00000127', - "hybull;": '\U00002043', - "hyphen;": '\U00002010', - "iacute;": '\U000000ED', - "ic;": '\U00002063', - "icirc;": '\U000000EE', - "icy;": '\U00000438', - "iecy;": '\U00000435', - "iexcl;": '\U000000A1', - "iff;": '\U000021D4', - "ifr;": '\U0001D526', - "igrave;": '\U000000EC', - "ii;": '\U00002148', - "iiiint;": '\U00002A0C', - "iiint;": '\U0000222D', - "iinfin;": '\U000029DC', - "iiota;": '\U00002129', - "ijlig;": '\U00000133', - "imacr;": '\U0000012B', - "image;": '\U00002111', - "imagline;": '\U00002110', - "imagpart;": '\U00002111', - "imath;": '\U00000131', - "imof;": '\U000022B7', - "imped;": '\U000001B5', - "in;": '\U00002208', - "incare;": '\U00002105', - "infin;": '\U0000221E', - "infintie;": '\U000029DD', - "inodot;": '\U00000131', - "int;": '\U0000222B', - "intcal;": '\U000022BA', - "integers;": '\U00002124', - "intercal;": '\U000022BA', - "intlarhk;": '\U00002A17', - "intprod;": '\U00002A3C', - "iocy;": '\U00000451', - "iogon;": '\U0000012F', - "iopf;": '\U0001D55A', - "iota;": '\U000003B9', - "iprod;": '\U00002A3C', - "iquest;": '\U000000BF', - "iscr;": '\U0001D4BE', - "isin;": '\U00002208', - "isinE;": '\U000022F9', - "isindot;": '\U000022F5', - "isins;": '\U000022F4', - "isinsv;": '\U000022F3', - "isinv;": '\U00002208', - "it;": '\U00002062', - "itilde;": '\U00000129', - "iukcy;": '\U00000456', - "iuml;": '\U000000EF', - "jcirc;": '\U00000135', - "jcy;": '\U00000439', - "jfr;": '\U0001D527', - "jmath;": '\U00000237', - "jopf;": '\U0001D55B', - "jscr;": '\U0001D4BF', - "jsercy;": '\U00000458', - "jukcy;": '\U00000454', - "kappa;": '\U000003BA', - "kappav;": '\U000003F0', - "kcedil;": '\U00000137', - "kcy;": '\U0000043A', - "kfr;": '\U0001D528', - "kgreen;": '\U00000138', - "khcy;": '\U00000445', - "kjcy;": '\U0000045C', - "kopf;": '\U0001D55C', - "kscr;": '\U0001D4C0', - "lAarr;": '\U000021DA', - "lArr;": '\U000021D0', - "lAtail;": '\U0000291B', - "lBarr;": '\U0000290E', - "lE;": '\U00002266', - "lEg;": '\U00002A8B', - "lHar;": '\U00002962', - "lacute;": '\U0000013A', - "laemptyv;": '\U000029B4', - "lagran;": '\U00002112', - "lambda;": '\U000003BB', - "lang;": '\U000027E8', - "langd;": '\U00002991', - "langle;": '\U000027E8', - "lap;": '\U00002A85', - "laquo;": '\U000000AB', - "larr;": '\U00002190', - "larrb;": '\U000021E4', - "larrbfs;": '\U0000291F', - "larrfs;": '\U0000291D', - "larrhk;": '\U000021A9', - "larrlp;": '\U000021AB', - "larrpl;": '\U00002939', - "larrsim;": '\U00002973', - "larrtl;": '\U000021A2', - "lat;": '\U00002AAB', - "latail;": '\U00002919', - "late;": '\U00002AAD', - "lbarr;": '\U0000290C', - "lbbrk;": '\U00002772', - "lbrace;": '\U0000007B', - "lbrack;": '\U0000005B', - "lbrke;": '\U0000298B', - "lbrksld;": '\U0000298F', - "lbrkslu;": '\U0000298D', - "lcaron;": '\U0000013E', - "lcedil;": '\U0000013C', - "lceil;": '\U00002308', - "lcub;": '\U0000007B', - "lcy;": '\U0000043B', - "ldca;": '\U00002936', - "ldquo;": '\U0000201C', - "ldquor;": '\U0000201E', - "ldrdhar;": '\U00002967', - "ldrushar;": '\U0000294B', - "ldsh;": '\U000021B2', - "le;": '\U00002264', - "leftarrow;": '\U00002190', - "leftarrowtail;": '\U000021A2', - "leftharpoondown;": '\U000021BD', - "leftharpoonup;": '\U000021BC', - "leftleftarrows;": '\U000021C7', - "leftrightarrow;": '\U00002194', - "leftrightarrows;": '\U000021C6', - "leftrightharpoons;": '\U000021CB', - "leftrightsquigarrow;": '\U000021AD', - "leftthreetimes;": '\U000022CB', - "leg;": '\U000022DA', - "leq;": '\U00002264', - "leqq;": '\U00002266', - "leqslant;": '\U00002A7D', - "les;": '\U00002A7D', - "lescc;": '\U00002AA8', - "lesdot;": '\U00002A7F', - "lesdoto;": '\U00002A81', - "lesdotor;": '\U00002A83', - "lesges;": '\U00002A93', - "lessapprox;": '\U00002A85', - "lessdot;": '\U000022D6', - "lesseqgtr;": '\U000022DA', - "lesseqqgtr;": '\U00002A8B', - "lessgtr;": '\U00002276', - "lesssim;": '\U00002272', - "lfisht;": '\U0000297C', - "lfloor;": '\U0000230A', - "lfr;": '\U0001D529', - "lg;": '\U00002276', - "lgE;": '\U00002A91', - "lhard;": '\U000021BD', - "lharu;": '\U000021BC', - "lharul;": '\U0000296A', - "lhblk;": '\U00002584', - "ljcy;": '\U00000459', - "ll;": '\U0000226A', - "llarr;": '\U000021C7', - "llcorner;": '\U0000231E', - "llhard;": '\U0000296B', - "lltri;": '\U000025FA', - "lmidot;": '\U00000140', - "lmoust;": '\U000023B0', - "lmoustache;": '\U000023B0', - "lnE;": '\U00002268', - "lnap;": '\U00002A89', - "lnapprox;": '\U00002A89', - "lne;": '\U00002A87', - "lneq;": '\U00002A87', - "lneqq;": '\U00002268', - "lnsim;": '\U000022E6', - "loang;": '\U000027EC', - "loarr;": '\U000021FD', - "lobrk;": '\U000027E6', - "longleftarrow;": '\U000027F5', - "longleftrightarrow;": '\U000027F7', - "longmapsto;": '\U000027FC', - "longrightarrow;": '\U000027F6', - "looparrowleft;": '\U000021AB', - "looparrowright;": '\U000021AC', - "lopar;": '\U00002985', - "lopf;": '\U0001D55D', - "loplus;": '\U00002A2D', - "lotimes;": '\U00002A34', - "lowast;": '\U00002217', - "lowbar;": '\U0000005F', - "loz;": '\U000025CA', - "lozenge;": '\U000025CA', - "lozf;": '\U000029EB', - "lpar;": '\U00000028', - "lparlt;": '\U00002993', - "lrarr;": '\U000021C6', - "lrcorner;": '\U0000231F', - "lrhar;": '\U000021CB', - "lrhard;": '\U0000296D', - "lrm;": '\U0000200E', - "lrtri;": '\U000022BF', - "lsaquo;": '\U00002039', - "lscr;": '\U0001D4C1', - "lsh;": '\U000021B0', - "lsim;": '\U00002272', - "lsime;": '\U00002A8D', - "lsimg;": '\U00002A8F', - "lsqb;": '\U0000005B', - "lsquo;": '\U00002018', - "lsquor;": '\U0000201A', - "lstrok;": '\U00000142', - "lt;": '\U0000003C', - "ltcc;": '\U00002AA6', - "ltcir;": '\U00002A79', - "ltdot;": '\U000022D6', - "lthree;": '\U000022CB', - "ltimes;": '\U000022C9', - "ltlarr;": '\U00002976', - "ltquest;": '\U00002A7B', - "ltrPar;": '\U00002996', - "ltri;": '\U000025C3', - "ltrie;": '\U000022B4', - "ltrif;": '\U000025C2', - "lurdshar;": '\U0000294A', - "luruhar;": '\U00002966', - "mDDot;": '\U0000223A', - "macr;": '\U000000AF', - "male;": '\U00002642', - "malt;": '\U00002720', - "maltese;": '\U00002720', - "map;": '\U000021A6', - "mapsto;": '\U000021A6', - "mapstodown;": '\U000021A7', - "mapstoleft;": '\U000021A4', - "mapstoup;": '\U000021A5', - "marker;": '\U000025AE', - "mcomma;": '\U00002A29', - "mcy;": '\U0000043C', - "mdash;": '\U00002014', - "measuredangle;": '\U00002221', - "mfr;": '\U0001D52A', - "mho;": '\U00002127', - "micro;": '\U000000B5', - "mid;": '\U00002223', - "midast;": '\U0000002A', - "midcir;": '\U00002AF0', - "middot;": '\U000000B7', - "minus;": '\U00002212', - "minusb;": '\U0000229F', - "minusd;": '\U00002238', - "minusdu;": '\U00002A2A', - "mlcp;": '\U00002ADB', - "mldr;": '\U00002026', - "mnplus;": '\U00002213', - "models;": '\U000022A7', - "mopf;": '\U0001D55E', - "mp;": '\U00002213', - "mscr;": '\U0001D4C2', - "mstpos;": '\U0000223E', - "mu;": '\U000003BC', - "multimap;": '\U000022B8', - "mumap;": '\U000022B8', - "nLeftarrow;": '\U000021CD', - "nLeftrightarrow;": '\U000021CE', - "nRightarrow;": '\U000021CF', - "nVDash;": '\U000022AF', - "nVdash;": '\U000022AE', - "nabla;": '\U00002207', - "nacute;": '\U00000144', - "nap;": '\U00002249', - "napos;": '\U00000149', - "napprox;": '\U00002249', - "natur;": '\U0000266E', - "natural;": '\U0000266E', - "naturals;": '\U00002115', - "nbsp;": '\U000000A0', - "ncap;": '\U00002A43', - "ncaron;": '\U00000148', - "ncedil;": '\U00000146', - "ncong;": '\U00002247', - "ncup;": '\U00002A42', - "ncy;": '\U0000043D', - "ndash;": '\U00002013', - "ne;": '\U00002260', - "neArr;": '\U000021D7', - "nearhk;": '\U00002924', - "nearr;": '\U00002197', - "nearrow;": '\U00002197', - "nequiv;": '\U00002262', - "nesear;": '\U00002928', - "nexist;": '\U00002204', - "nexists;": '\U00002204', - "nfr;": '\U0001D52B', - "nge;": '\U00002271', - "ngeq;": '\U00002271', - "ngsim;": '\U00002275', - "ngt;": '\U0000226F', - "ngtr;": '\U0000226F', - "nhArr;": '\U000021CE', - "nharr;": '\U000021AE', - "nhpar;": '\U00002AF2', - "ni;": '\U0000220B', - "nis;": '\U000022FC', - "nisd;": '\U000022FA', - "niv;": '\U0000220B', - "njcy;": '\U0000045A', - "nlArr;": '\U000021CD', - "nlarr;": '\U0000219A', - "nldr;": '\U00002025', - "nle;": '\U00002270', - "nleftarrow;": '\U0000219A', - "nleftrightarrow;": '\U000021AE', - "nleq;": '\U00002270', - "nless;": '\U0000226E', - "nlsim;": '\U00002274', - "nlt;": '\U0000226E', - "nltri;": '\U000022EA', - "nltrie;": '\U000022EC', - "nmid;": '\U00002224', - "nopf;": '\U0001D55F', - "not;": '\U000000AC', - "notin;": '\U00002209', - "notinva;": '\U00002209', - "notinvb;": '\U000022F7', - "notinvc;": '\U000022F6', - "notni;": '\U0000220C', - "notniva;": '\U0000220C', - "notnivb;": '\U000022FE', - "notnivc;": '\U000022FD', - "npar;": '\U00002226', - "nparallel;": '\U00002226', - "npolint;": '\U00002A14', - "npr;": '\U00002280', - "nprcue;": '\U000022E0', - "nprec;": '\U00002280', - "nrArr;": '\U000021CF', - "nrarr;": '\U0000219B', - "nrightarrow;": '\U0000219B', - "nrtri;": '\U000022EB', - "nrtrie;": '\U000022ED', - "nsc;": '\U00002281', - "nsccue;": '\U000022E1', - "nscr;": '\U0001D4C3', - "nshortmid;": '\U00002224', - "nshortparallel;": '\U00002226', - "nsim;": '\U00002241', - "nsime;": '\U00002244', - "nsimeq;": '\U00002244', - "nsmid;": '\U00002224', - "nspar;": '\U00002226', - "nsqsube;": '\U000022E2', - "nsqsupe;": '\U000022E3', - "nsub;": '\U00002284', - "nsube;": '\U00002288', - "nsubseteq;": '\U00002288', - "nsucc;": '\U00002281', - "nsup;": '\U00002285', - "nsupe;": '\U00002289', - "nsupseteq;": '\U00002289', - "ntgl;": '\U00002279', - "ntilde;": '\U000000F1', - "ntlg;": '\U00002278', - "ntriangleleft;": '\U000022EA', - "ntrianglelefteq;": '\U000022EC', - "ntriangleright;": '\U000022EB', - "ntrianglerighteq;": '\U000022ED', - "nu;": '\U000003BD', - "num;": '\U00000023', - "numero;": '\U00002116', - "numsp;": '\U00002007', - "nvDash;": '\U000022AD', - "nvHarr;": '\U00002904', - "nvdash;": '\U000022AC', - "nvinfin;": '\U000029DE', - "nvlArr;": '\U00002902', - "nvrArr;": '\U00002903', - "nwArr;": '\U000021D6', - "nwarhk;": '\U00002923', - "nwarr;": '\U00002196', - "nwarrow;": '\U00002196', - "nwnear;": '\U00002927', - "oS;": '\U000024C8', - "oacute;": '\U000000F3', - "oast;": '\U0000229B', - "ocir;": '\U0000229A', - "ocirc;": '\U000000F4', - "ocy;": '\U0000043E', - "odash;": '\U0000229D', - "odblac;": '\U00000151', - "odiv;": '\U00002A38', - "odot;": '\U00002299', - "odsold;": '\U000029BC', - "oelig;": '\U00000153', - "ofcir;": '\U000029BF', - "ofr;": '\U0001D52C', - "ogon;": '\U000002DB', - "ograve;": '\U000000F2', - "ogt;": '\U000029C1', - "ohbar;": '\U000029B5', - "ohm;": '\U000003A9', - "oint;": '\U0000222E', - "olarr;": '\U000021BA', - "olcir;": '\U000029BE', - "olcross;": '\U000029BB', - "oline;": '\U0000203E', - "olt;": '\U000029C0', - "omacr;": '\U0000014D', - "omega;": '\U000003C9', - "omicron;": '\U000003BF', - "omid;": '\U000029B6', - "ominus;": '\U00002296', - "oopf;": '\U0001D560', - "opar;": '\U000029B7', - "operp;": '\U000029B9', - "oplus;": '\U00002295', - "or;": '\U00002228', - "orarr;": '\U000021BB', - "ord;": '\U00002A5D', - "order;": '\U00002134', - "orderof;": '\U00002134', - "ordf;": '\U000000AA', - "ordm;": '\U000000BA', - "origof;": '\U000022B6', - "oror;": '\U00002A56', - "orslope;": '\U00002A57', - "orv;": '\U00002A5B', - "oscr;": '\U00002134', - "oslash;": '\U000000F8', - "osol;": '\U00002298', - "otilde;": '\U000000F5', - "otimes;": '\U00002297', - "otimesas;": '\U00002A36', - "ouml;": '\U000000F6', - "ovbar;": '\U0000233D', - "par;": '\U00002225', - "para;": '\U000000B6', - "parallel;": '\U00002225', - "parsim;": '\U00002AF3', - "parsl;": '\U00002AFD', - "part;": '\U00002202', - "pcy;": '\U0000043F', - "percnt;": '\U00000025', - "period;": '\U0000002E', - "permil;": '\U00002030', - "perp;": '\U000022A5', - "pertenk;": '\U00002031', - "pfr;": '\U0001D52D', - "phi;": '\U000003C6', - "phiv;": '\U000003D5', - "phmmat;": '\U00002133', - "phone;": '\U0000260E', - "pi;": '\U000003C0', - "pitchfork;": '\U000022D4', - "piv;": '\U000003D6', - "planck;": '\U0000210F', - "planckh;": '\U0000210E', - "plankv;": '\U0000210F', - "plus;": '\U0000002B', - "plusacir;": '\U00002A23', - "plusb;": '\U0000229E', - "pluscir;": '\U00002A22', - "plusdo;": '\U00002214', - "plusdu;": '\U00002A25', - "pluse;": '\U00002A72', - "plusmn;": '\U000000B1', - "plussim;": '\U00002A26', - "plustwo;": '\U00002A27', - "pm;": '\U000000B1', - "pointint;": '\U00002A15', - "popf;": '\U0001D561', - "pound;": '\U000000A3', - "pr;": '\U0000227A', - "prE;": '\U00002AB3', - "prap;": '\U00002AB7', - "prcue;": '\U0000227C', - "pre;": '\U00002AAF', - "prec;": '\U0000227A', - "precapprox;": '\U00002AB7', - "preccurlyeq;": '\U0000227C', - "preceq;": '\U00002AAF', - "precnapprox;": '\U00002AB9', - "precneqq;": '\U00002AB5', - "precnsim;": '\U000022E8', - "precsim;": '\U0000227E', - "prime;": '\U00002032', - "primes;": '\U00002119', - "prnE;": '\U00002AB5', - "prnap;": '\U00002AB9', - "prnsim;": '\U000022E8', - "prod;": '\U0000220F', - "profalar;": '\U0000232E', - "profline;": '\U00002312', - "profsurf;": '\U00002313', - "prop;": '\U0000221D', - "propto;": '\U0000221D', - "prsim;": '\U0000227E', - "prurel;": '\U000022B0', - "pscr;": '\U0001D4C5', - "psi;": '\U000003C8', - "puncsp;": '\U00002008', - "qfr;": '\U0001D52E', - "qint;": '\U00002A0C', - "qopf;": '\U0001D562', - "qprime;": '\U00002057', - "qscr;": '\U0001D4C6', - "quaternions;": '\U0000210D', - "quatint;": '\U00002A16', - "quest;": '\U0000003F', - "questeq;": '\U0000225F', - "quot;": '\U00000022', - "rAarr;": '\U000021DB', - "rArr;": '\U000021D2', - "rAtail;": '\U0000291C', - "rBarr;": '\U0000290F', - "rHar;": '\U00002964', - "racute;": '\U00000155', - "radic;": '\U0000221A', - "raemptyv;": '\U000029B3', - "rang;": '\U000027E9', - "rangd;": '\U00002992', - "range;": '\U000029A5', - "rangle;": '\U000027E9', - "raquo;": '\U000000BB', - "rarr;": '\U00002192', - "rarrap;": '\U00002975', - "rarrb;": '\U000021E5', - "rarrbfs;": '\U00002920', - "rarrc;": '\U00002933', - "rarrfs;": '\U0000291E', - "rarrhk;": '\U000021AA', - "rarrlp;": '\U000021AC', - "rarrpl;": '\U00002945', - "rarrsim;": '\U00002974', - "rarrtl;": '\U000021A3', - "rarrw;": '\U0000219D', - "ratail;": '\U0000291A', - "ratio;": '\U00002236', - "rationals;": '\U0000211A', - "rbarr;": '\U0000290D', - "rbbrk;": '\U00002773', - "rbrace;": '\U0000007D', - "rbrack;": '\U0000005D', - "rbrke;": '\U0000298C', - "rbrksld;": '\U0000298E', - "rbrkslu;": '\U00002990', - "rcaron;": '\U00000159', - "rcedil;": '\U00000157', - "rceil;": '\U00002309', - "rcub;": '\U0000007D', - "rcy;": '\U00000440', - "rdca;": '\U00002937', - "rdldhar;": '\U00002969', - "rdquo;": '\U0000201D', - "rdquor;": '\U0000201D', - "rdsh;": '\U000021B3', - "real;": '\U0000211C', - "realine;": '\U0000211B', - "realpart;": '\U0000211C', - "reals;": '\U0000211D', - "rect;": '\U000025AD', - "reg;": '\U000000AE', - "rfisht;": '\U0000297D', - "rfloor;": '\U0000230B', - "rfr;": '\U0001D52F', - "rhard;": '\U000021C1', - "rharu;": '\U000021C0', - "rharul;": '\U0000296C', - "rho;": '\U000003C1', - "rhov;": '\U000003F1', - "rightarrow;": '\U00002192', - "rightarrowtail;": '\U000021A3', - "rightharpoondown;": '\U000021C1', - "rightharpoonup;": '\U000021C0', - "rightleftarrows;": '\U000021C4', - "rightleftharpoons;": '\U000021CC', - "rightrightarrows;": '\U000021C9', - "rightsquigarrow;": '\U0000219D', - "rightthreetimes;": '\U000022CC', - "ring;": '\U000002DA', - "risingdotseq;": '\U00002253', - "rlarr;": '\U000021C4', - "rlhar;": '\U000021CC', - "rlm;": '\U0000200F', - "rmoust;": '\U000023B1', - "rmoustache;": '\U000023B1', - "rnmid;": '\U00002AEE', - "roang;": '\U000027ED', - "roarr;": '\U000021FE', - "robrk;": '\U000027E7', - "ropar;": '\U00002986', - "ropf;": '\U0001D563', - "roplus;": '\U00002A2E', - "rotimes;": '\U00002A35', - "rpar;": '\U00000029', - "rpargt;": '\U00002994', - "rppolint;": '\U00002A12', - "rrarr;": '\U000021C9', - "rsaquo;": '\U0000203A', - "rscr;": '\U0001D4C7', - "rsh;": '\U000021B1', - "rsqb;": '\U0000005D', - "rsquo;": '\U00002019', - "rsquor;": '\U00002019', - "rthree;": '\U000022CC', - "rtimes;": '\U000022CA', - "rtri;": '\U000025B9', - "rtrie;": '\U000022B5', - "rtrif;": '\U000025B8', - "rtriltri;": '\U000029CE', - "ruluhar;": '\U00002968', - "rx;": '\U0000211E', - "sacute;": '\U0000015B', - "sbquo;": '\U0000201A', - "sc;": '\U0000227B', - "scE;": '\U00002AB4', - "scap;": '\U00002AB8', - "scaron;": '\U00000161', - "sccue;": '\U0000227D', - "sce;": '\U00002AB0', - "scedil;": '\U0000015F', - "scirc;": '\U0000015D', - "scnE;": '\U00002AB6', - "scnap;": '\U00002ABA', - "scnsim;": '\U000022E9', - "scpolint;": '\U00002A13', - "scsim;": '\U0000227F', - "scy;": '\U00000441', - "sdot;": '\U000022C5', - "sdotb;": '\U000022A1', - "sdote;": '\U00002A66', - "seArr;": '\U000021D8', - "searhk;": '\U00002925', - "searr;": '\U00002198', - "searrow;": '\U00002198', - "sect;": '\U000000A7', - "semi;": '\U0000003B', - "seswar;": '\U00002929', - "setminus;": '\U00002216', - "setmn;": '\U00002216', - "sext;": '\U00002736', - "sfr;": '\U0001D530', - "sfrown;": '\U00002322', - "sharp;": '\U0000266F', - "shchcy;": '\U00000449', - "shcy;": '\U00000448', - "shortmid;": '\U00002223', - "shortparallel;": '\U00002225', - "shy;": '\U000000AD', - "sigma;": '\U000003C3', - "sigmaf;": '\U000003C2', - "sigmav;": '\U000003C2', - "sim;": '\U0000223C', - "simdot;": '\U00002A6A', - "sime;": '\U00002243', - "simeq;": '\U00002243', - "simg;": '\U00002A9E', - "simgE;": '\U00002AA0', - "siml;": '\U00002A9D', - "simlE;": '\U00002A9F', - "simne;": '\U00002246', - "simplus;": '\U00002A24', - "simrarr;": '\U00002972', - "slarr;": '\U00002190', - "smallsetminus;": '\U00002216', - "smashp;": '\U00002A33', - "smeparsl;": '\U000029E4', - "smid;": '\U00002223', - "smile;": '\U00002323', - "smt;": '\U00002AAA', - "smte;": '\U00002AAC', - "softcy;": '\U0000044C', - "sol;": '\U0000002F', - "solb;": '\U000029C4', - "solbar;": '\U0000233F', - "sopf;": '\U0001D564', - "spades;": '\U00002660', - "spadesuit;": '\U00002660', - "spar;": '\U00002225', - "sqcap;": '\U00002293', - "sqcup;": '\U00002294', - "sqsub;": '\U0000228F', - "sqsube;": '\U00002291', - "sqsubset;": '\U0000228F', - "sqsubseteq;": '\U00002291', - "sqsup;": '\U00002290', - "sqsupe;": '\U00002292', - "sqsupset;": '\U00002290', - "sqsupseteq;": '\U00002292', - "squ;": '\U000025A1', - "square;": '\U000025A1', - "squarf;": '\U000025AA', - "squf;": '\U000025AA', - "srarr;": '\U00002192', - "sscr;": '\U0001D4C8', - "ssetmn;": '\U00002216', - "ssmile;": '\U00002323', - "sstarf;": '\U000022C6', - "star;": '\U00002606', - "starf;": '\U00002605', - "straightepsilon;": '\U000003F5', - "straightphi;": '\U000003D5', - "strns;": '\U000000AF', - "sub;": '\U00002282', - "subE;": '\U00002AC5', - "subdot;": '\U00002ABD', - "sube;": '\U00002286', - "subedot;": '\U00002AC3', - "submult;": '\U00002AC1', - "subnE;": '\U00002ACB', - "subne;": '\U0000228A', - "subplus;": '\U00002ABF', - "subrarr;": '\U00002979', - "subset;": '\U00002282', - "subseteq;": '\U00002286', - "subseteqq;": '\U00002AC5', - "subsetneq;": '\U0000228A', - "subsetneqq;": '\U00002ACB', - "subsim;": '\U00002AC7', - "subsub;": '\U00002AD5', - "subsup;": '\U00002AD3', - "succ;": '\U0000227B', - "succapprox;": '\U00002AB8', - "succcurlyeq;": '\U0000227D', - "succeq;": '\U00002AB0', - "succnapprox;": '\U00002ABA', - "succneqq;": '\U00002AB6', - "succnsim;": '\U000022E9', - "succsim;": '\U0000227F', - "sum;": '\U00002211', - "sung;": '\U0000266A', - "sup;": '\U00002283', - "sup1;": '\U000000B9', - "sup2;": '\U000000B2', - "sup3;": '\U000000B3', - "supE;": '\U00002AC6', - "supdot;": '\U00002ABE', - "supdsub;": '\U00002AD8', - "supe;": '\U00002287', - "supedot;": '\U00002AC4', - "suphsol;": '\U000027C9', - "suphsub;": '\U00002AD7', - "suplarr;": '\U0000297B', - "supmult;": '\U00002AC2', - "supnE;": '\U00002ACC', - "supne;": '\U0000228B', - "supplus;": '\U00002AC0', - "supset;": '\U00002283', - "supseteq;": '\U00002287', - "supseteqq;": '\U00002AC6', - "supsetneq;": '\U0000228B', - "supsetneqq;": '\U00002ACC', - "supsim;": '\U00002AC8', - "supsub;": '\U00002AD4', - "supsup;": '\U00002AD6', - "swArr;": '\U000021D9', - "swarhk;": '\U00002926', - "swarr;": '\U00002199', - "swarrow;": '\U00002199', - "swnwar;": '\U0000292A', - "szlig;": '\U000000DF', - "target;": '\U00002316', - "tau;": '\U000003C4', - "tbrk;": '\U000023B4', - "tcaron;": '\U00000165', - "tcedil;": '\U00000163', - "tcy;": '\U00000442', - "tdot;": '\U000020DB', - "telrec;": '\U00002315', - "tfr;": '\U0001D531', - "there4;": '\U00002234', - "therefore;": '\U00002234', - "theta;": '\U000003B8', - "thetasym;": '\U000003D1', - "thetav;": '\U000003D1', - "thickapprox;": '\U00002248', - "thicksim;": '\U0000223C', - "thinsp;": '\U00002009', - "thkap;": '\U00002248', - "thksim;": '\U0000223C', - "thorn;": '\U000000FE', - "tilde;": '\U000002DC', - "times;": '\U000000D7', - "timesb;": '\U000022A0', - "timesbar;": '\U00002A31', - "timesd;": '\U00002A30', - "tint;": '\U0000222D', - "toea;": '\U00002928', - "top;": '\U000022A4', - "topbot;": '\U00002336', - "topcir;": '\U00002AF1', - "topf;": '\U0001D565', - "topfork;": '\U00002ADA', - "tosa;": '\U00002929', - "tprime;": '\U00002034', - "trade;": '\U00002122', - "triangle;": '\U000025B5', - "triangledown;": '\U000025BF', - "triangleleft;": '\U000025C3', - "trianglelefteq;": '\U000022B4', - "triangleq;": '\U0000225C', - "triangleright;": '\U000025B9', - "trianglerighteq;": '\U000022B5', - "tridot;": '\U000025EC', - "trie;": '\U0000225C', - "triminus;": '\U00002A3A', - "triplus;": '\U00002A39', - "trisb;": '\U000029CD', - "tritime;": '\U00002A3B', - "trpezium;": '\U000023E2', - "tscr;": '\U0001D4C9', - "tscy;": '\U00000446', - "tshcy;": '\U0000045B', - "tstrok;": '\U00000167', - "twixt;": '\U0000226C', - "twoheadleftarrow;": '\U0000219E', - "twoheadrightarrow;": '\U000021A0', - "uArr;": '\U000021D1', - "uHar;": '\U00002963', - "uacute;": '\U000000FA', - "uarr;": '\U00002191', - "ubrcy;": '\U0000045E', - "ubreve;": '\U0000016D', - "ucirc;": '\U000000FB', - "ucy;": '\U00000443', - "udarr;": '\U000021C5', - "udblac;": '\U00000171', - "udhar;": '\U0000296E', - "ufisht;": '\U0000297E', - "ufr;": '\U0001D532', - "ugrave;": '\U000000F9', - "uharl;": '\U000021BF', - "uharr;": '\U000021BE', - "uhblk;": '\U00002580', - "ulcorn;": '\U0000231C', - "ulcorner;": '\U0000231C', - "ulcrop;": '\U0000230F', - "ultri;": '\U000025F8', - "umacr;": '\U0000016B', - "uml;": '\U000000A8', - "uogon;": '\U00000173', - "uopf;": '\U0001D566', - "uparrow;": '\U00002191', - "updownarrow;": '\U00002195', - "upharpoonleft;": '\U000021BF', - "upharpoonright;": '\U000021BE', - "uplus;": '\U0000228E', - "upsi;": '\U000003C5', - "upsih;": '\U000003D2', - "upsilon;": '\U000003C5', - "upuparrows;": '\U000021C8', - "urcorn;": '\U0000231D', - "urcorner;": '\U0000231D', - "urcrop;": '\U0000230E', - "uring;": '\U0000016F', - "urtri;": '\U000025F9', - "uscr;": '\U0001D4CA', - "utdot;": '\U000022F0', - "utilde;": '\U00000169', - "utri;": '\U000025B5', - "utrif;": '\U000025B4', - "uuarr;": '\U000021C8', - "uuml;": '\U000000FC', - "uwangle;": '\U000029A7', - "vArr;": '\U000021D5', - "vBar;": '\U00002AE8', - "vBarv;": '\U00002AE9', - "vDash;": '\U000022A8', - "vangrt;": '\U0000299C', - "varepsilon;": '\U000003F5', - "varkappa;": '\U000003F0', - "varnothing;": '\U00002205', - "varphi;": '\U000003D5', - "varpi;": '\U000003D6', - "varpropto;": '\U0000221D', - "varr;": '\U00002195', - "varrho;": '\U000003F1', - "varsigma;": '\U000003C2', - "vartheta;": '\U000003D1', - "vartriangleleft;": '\U000022B2', - "vartriangleright;": '\U000022B3', - "vcy;": '\U00000432', - "vdash;": '\U000022A2', - "vee;": '\U00002228', - "veebar;": '\U000022BB', - "veeeq;": '\U0000225A', - "vellip;": '\U000022EE', - "verbar;": '\U0000007C', - "vert;": '\U0000007C', - "vfr;": '\U0001D533', - "vltri;": '\U000022B2', - "vopf;": '\U0001D567', - "vprop;": '\U0000221D', - "vrtri;": '\U000022B3', - "vscr;": '\U0001D4CB', - "vzigzag;": '\U0000299A', - "wcirc;": '\U00000175', - "wedbar;": '\U00002A5F', - "wedge;": '\U00002227', - "wedgeq;": '\U00002259', - "weierp;": '\U00002118', - "wfr;": '\U0001D534', - "wopf;": '\U0001D568', - "wp;": '\U00002118', - "wr;": '\U00002240', - "wreath;": '\U00002240', - "wscr;": '\U0001D4CC', - "xcap;": '\U000022C2', - "xcirc;": '\U000025EF', - "xcup;": '\U000022C3', - "xdtri;": '\U000025BD', - "xfr;": '\U0001D535', - "xhArr;": '\U000027FA', - "xharr;": '\U000027F7', - "xi;": '\U000003BE', - "xlArr;": '\U000027F8', - "xlarr;": '\U000027F5', - "xmap;": '\U000027FC', - "xnis;": '\U000022FB', - "xodot;": '\U00002A00', - "xopf;": '\U0001D569', - "xoplus;": '\U00002A01', - "xotime;": '\U00002A02', - "xrArr;": '\U000027F9', - "xrarr;": '\U000027F6', - "xscr;": '\U0001D4CD', - "xsqcup;": '\U00002A06', - "xuplus;": '\U00002A04', - "xutri;": '\U000025B3', - "xvee;": '\U000022C1', - "xwedge;": '\U000022C0', - "yacute;": '\U000000FD', - "yacy;": '\U0000044F', - "ycirc;": '\U00000177', - "ycy;": '\U0000044B', - "yen;": '\U000000A5', - "yfr;": '\U0001D536', - "yicy;": '\U00000457', - "yopf;": '\U0001D56A', - "yscr;": '\U0001D4CE', - "yucy;": '\U0000044E', - "yuml;": '\U000000FF', - "zacute;": '\U0000017A', - "zcaron;": '\U0000017E', - "zcy;": '\U00000437', - "zdot;": '\U0000017C', - "zeetrf;": '\U00002128', - "zeta;": '\U000003B6', - "zfr;": '\U0001D537', - "zhcy;": '\U00000436', - "zigrarr;": '\U000021DD', - "zopf;": '\U0001D56B', - "zscr;": '\U0001D4CF', - "zwj;": '\U0000200D', - "zwnj;": '\U0000200C', - "AElig": '\U000000C6', - "AMP": '\U00000026', - "Aacute": '\U000000C1', - "Acirc": '\U000000C2', - "Agrave": '\U000000C0', - "Aring": '\U000000C5', - "Atilde": '\U000000C3', - "Auml": '\U000000C4', - "COPY": '\U000000A9', - "Ccedil": '\U000000C7', - "ETH": '\U000000D0', - "Eacute": '\U000000C9', - "Ecirc": '\U000000CA', - "Egrave": '\U000000C8', - "Euml": '\U000000CB', - "GT": '\U0000003E', - "Iacute": '\U000000CD', - "Icirc": '\U000000CE', - "Igrave": '\U000000CC', - "Iuml": '\U000000CF', - "LT": '\U0000003C', - "Ntilde": '\U000000D1', - "Oacute": '\U000000D3', - "Ocirc": '\U000000D4', - "Ograve": '\U000000D2', - "Oslash": '\U000000D8', - "Otilde": '\U000000D5', - "Ouml": '\U000000D6', - "QUOT": '\U00000022', - "REG": '\U000000AE', - "THORN": '\U000000DE', - "Uacute": '\U000000DA', - "Ucirc": '\U000000DB', - "Ugrave": '\U000000D9', - "Uuml": '\U000000DC', - "Yacute": '\U000000DD', - "aacute": '\U000000E1', - "acirc": '\U000000E2', - "acute": '\U000000B4', - "aelig": '\U000000E6', - "agrave": '\U000000E0', - "amp": '\U00000026', - "aring": '\U000000E5', - "atilde": '\U000000E3', - "auml": '\U000000E4', - "brvbar": '\U000000A6', - "ccedil": '\U000000E7', - "cedil": '\U000000B8', - "cent": '\U000000A2', - "copy": '\U000000A9', - "curren": '\U000000A4', - "deg": '\U000000B0', - "divide": '\U000000F7', - "eacute": '\U000000E9', - "ecirc": '\U000000EA', - "egrave": '\U000000E8', - "eth": '\U000000F0', - "euml": '\U000000EB', - "frac12": '\U000000BD', - "frac14": '\U000000BC', - "frac34": '\U000000BE', - "gt": '\U0000003E', - "iacute": '\U000000ED', - "icirc": '\U000000EE', - "iexcl": '\U000000A1', - "igrave": '\U000000EC', - "iquest": '\U000000BF', - "iuml": '\U000000EF', - "laquo": '\U000000AB', - "lt": '\U0000003C', - "macr": '\U000000AF', - "micro": '\U000000B5', - "middot": '\U000000B7', - "nbsp": '\U000000A0', - "not": '\U000000AC', - "ntilde": '\U000000F1', - "oacute": '\U000000F3', - "ocirc": '\U000000F4', - "ograve": '\U000000F2', - "ordf": '\U000000AA', - "ordm": '\U000000BA', - "oslash": '\U000000F8', - "otilde": '\U000000F5', - "ouml": '\U000000F6', - "para": '\U000000B6', - "plusmn": '\U000000B1', - "pound": '\U000000A3', - "quot": '\U00000022', - "raquo": '\U000000BB', - "reg": '\U000000AE', - "sect": '\U000000A7', - "shy": '\U000000AD', - "sup1": '\U000000B9', - "sup2": '\U000000B2', - "sup3": '\U000000B3', - "szlig": '\U000000DF', - "thorn": '\U000000FE', - "times": '\U000000D7', - "uacute": '\U000000FA', - "ucirc": '\U000000FB', - "ugrave": '\U000000F9', - "uml": '\U000000A8', - "uuml": '\U000000FC', - "yacute": '\U000000FD', - "yen": '\U000000A5', - "yuml": '\U000000FF', + "Cross;": '\U00002A2F', + "Cscr;": '\U0001D49E', + "Cup;": '\U000022D3', + "CupCap;": '\U0000224D', + "DD;": '\U00002145', + "DDotrahd;": '\U00002911', + "DJcy;": '\U00000402', + "DScy;": '\U00000405', + "DZcy;": '\U0000040F', + "Dagger;": '\U00002021', + "Darr;": '\U000021A1', + "Dashv;": '\U00002AE4', + "Dcaron;": '\U0000010E', + "Dcy;": '\U00000414', + "Del;": '\U00002207', + "Delta;": '\U00000394', + "Dfr;": '\U0001D507', + "DiacriticalAcute;": '\U000000B4', + "DiacriticalDot;": '\U000002D9', + "DiacriticalDoubleAcute;": '\U000002DD', + "DiacriticalGrave;": '\U00000060', + "DiacriticalTilde;": '\U000002DC', + "Diamond;": '\U000022C4', + "DifferentialD;": '\U00002146', + "Dopf;": '\U0001D53B', + "Dot;": '\U000000A8', + "DotDot;": '\U000020DC', + "DotEqual;": '\U00002250', + "DoubleContourIntegral;": '\U0000222F', + "DoubleDot;": '\U000000A8', + "DoubleDownArrow;": '\U000021D3', + "DoubleLeftArrow;": '\U000021D0', + "DoubleLeftRightArrow;": '\U000021D4', + "DoubleLeftTee;": '\U00002AE4', + "DoubleLongLeftArrow;": '\U000027F8', + "DoubleLongLeftRightArrow;": '\U000027FA', + "DoubleLongRightArrow;": '\U000027F9', + "DoubleRightArrow;": '\U000021D2', + "DoubleRightTee;": '\U000022A8', + "DoubleUpArrow;": '\U000021D1', + "DoubleUpDownArrow;": '\U000021D5', + "DoubleVerticalBar;": '\U00002225', + "DownArrow;": '\U00002193', + "DownArrowBar;": '\U00002913', + "DownArrowUpArrow;": '\U000021F5', + "DownBreve;": '\U00000311', + "DownLeftRightVector;": '\U00002950', + "DownLeftTeeVector;": '\U0000295E', + "DownLeftVector;": '\U000021BD', + "DownLeftVectorBar;": '\U00002956', + "DownRightTeeVector;": '\U0000295F', + "DownRightVector;": '\U000021C1', + "DownRightVectorBar;": '\U00002957', + "DownTee;": '\U000022A4', + "DownTeeArrow;": '\U000021A7', + "Downarrow;": '\U000021D3', + "Dscr;": '\U0001D49F', + "Dstrok;": '\U00000110', + "ENG;": '\U0000014A', + "ETH;": '\U000000D0', + "Eacute;": '\U000000C9', + "Ecaron;": '\U0000011A', + "Ecirc;": '\U000000CA', + "Ecy;": '\U0000042D', + "Edot;": '\U00000116', + "Efr;": '\U0001D508', + "Egrave;": '\U000000C8', + "Element;": '\U00002208', + "Emacr;": '\U00000112', + "EmptySmallSquare;": '\U000025FB', + "EmptyVerySmallSquare;": '\U000025AB', + "Eogon;": '\U00000118', + "Eopf;": '\U0001D53C', + "Epsilon;": '\U00000395', + "Equal;": '\U00002A75', + "EqualTilde;": '\U00002242', + "Equilibrium;": '\U000021CC', + "Escr;": '\U00002130', + "Esim;": '\U00002A73', + "Eta;": '\U00000397', + "Euml;": '\U000000CB', + "Exists;": '\U00002203', + "ExponentialE;": '\U00002147', + "Fcy;": '\U00000424', + "Ffr;": '\U0001D509', + "FilledSmallSquare;": '\U000025FC', + "FilledVerySmallSquare;": '\U000025AA', + "Fopf;": '\U0001D53D', + "ForAll;": '\U00002200', + "Fouriertrf;": '\U00002131', + "Fscr;": '\U00002131', + "GJcy;": '\U00000403', + "GT;": '\U0000003E', + "Gamma;": '\U00000393', + "Gammad;": '\U000003DC', + "Gbreve;": '\U0000011E', + "Gcedil;": '\U00000122', + "Gcirc;": '\U0000011C', + "Gcy;": '\U00000413', + "Gdot;": '\U00000120', + "Gfr;": '\U0001D50A', + "Gg;": '\U000022D9', + "Gopf;": '\U0001D53E', + "GreaterEqual;": '\U00002265', + "GreaterEqualLess;": '\U000022DB', + "GreaterFullEqual;": '\U00002267', + "GreaterGreater;": '\U00002AA2', + "GreaterLess;": '\U00002277', + "GreaterSlantEqual;": '\U00002A7E', + "GreaterTilde;": '\U00002273', + "Gscr;": '\U0001D4A2', + "Gt;": '\U0000226B', + "HARDcy;": '\U0000042A', + "Hacek;": '\U000002C7', + "Hat;": '\U0000005E', + "Hcirc;": '\U00000124', + "Hfr;": '\U0000210C', + "HilbertSpace;": '\U0000210B', + "Hopf;": '\U0000210D', + "HorizontalLine;": '\U00002500', + "Hscr;": '\U0000210B', + "Hstrok;": '\U00000126', + "HumpDownHump;": '\U0000224E', + "HumpEqual;": '\U0000224F', + "IEcy;": '\U00000415', + "IJlig;": '\U00000132', + "IOcy;": '\U00000401', + "Iacute;": '\U000000CD', + "Icirc;": '\U000000CE', + "Icy;": '\U00000418', + "Idot;": '\U00000130', + "Ifr;": '\U00002111', + "Igrave;": '\U000000CC', + "Im;": '\U00002111', + "Imacr;": '\U0000012A', + "ImaginaryI;": '\U00002148', + "Implies;": '\U000021D2', + "Int;": '\U0000222C', + "Integral;": '\U0000222B', + "Intersection;": '\U000022C2', + "InvisibleComma;": '\U00002063', + "InvisibleTimes;": '\U00002062', + "Iogon;": '\U0000012E', + "Iopf;": '\U0001D540', + "Iota;": '\U00000399', + "Iscr;": '\U00002110', + "Itilde;": '\U00000128', + "Iukcy;": '\U00000406', + "Iuml;": '\U000000CF', + "Jcirc;": '\U00000134', + "Jcy;": '\U00000419', + "Jfr;": '\U0001D50D', + "Jopf;": '\U0001D541', + "Jscr;": '\U0001D4A5', + "Jsercy;": '\U00000408', + "Jukcy;": '\U00000404', + "KHcy;": '\U00000425', + "KJcy;": '\U0000040C', + "Kappa;": '\U0000039A', + "Kcedil;": '\U00000136', + "Kcy;": '\U0000041A', + "Kfr;": '\U0001D50E', + "Kopf;": '\U0001D542', + "Kscr;": '\U0001D4A6', + "LJcy;": '\U00000409', + "LT;": '\U0000003C', + "Lacute;": '\U00000139', + "Lambda;": '\U0000039B', + "Lang;": '\U000027EA', + "Laplacetrf;": '\U00002112', + "Larr;": '\U0000219E', + "Lcaron;": '\U0000013D', + "Lcedil;": '\U0000013B', + "Lcy;": '\U0000041B', + "LeftAngleBracket;": '\U000027E8', + "LeftArrow;": '\U00002190', + "LeftArrowBar;": '\U000021E4', + "LeftArrowRightArrow;": '\U000021C6', + "LeftCeiling;": '\U00002308', + "LeftDoubleBracket;": '\U000027E6', + "LeftDownTeeVector;": '\U00002961', + "LeftDownVector;": '\U000021C3', + "LeftDownVectorBar;": '\U00002959', + "LeftFloor;": '\U0000230A', + "LeftRightArrow;": '\U00002194', + "LeftRightVector;": '\U0000294E', + "LeftTee;": '\U000022A3', + "LeftTeeArrow;": '\U000021A4', + "LeftTeeVector;": '\U0000295A', + "LeftTriangle;": '\U000022B2', + "LeftTriangleBar;": '\U000029CF', + "LeftTriangleEqual;": '\U000022B4', + "LeftUpDownVector;": '\U00002951', + "LeftUpTeeVector;": '\U00002960', + "LeftUpVector;": '\U000021BF', + "LeftUpVectorBar;": '\U00002958', + "LeftVector;": '\U000021BC', + "LeftVectorBar;": '\U00002952', + "Leftarrow;": '\U000021D0', + "Leftrightarrow;": '\U000021D4', + "LessEqualGreater;": '\U000022DA', + "LessFullEqual;": '\U00002266', + "LessGreater;": '\U00002276', + "LessLess;": '\U00002AA1', + "LessSlantEqual;": '\U00002A7D', + "LessTilde;": '\U00002272', + "Lfr;": '\U0001D50F', + "Ll;": '\U000022D8', + "Lleftarrow;": '\U000021DA', + "Lmidot;": '\U0000013F', + "LongLeftArrow;": '\U000027F5', + "LongLeftRightArrow;": '\U000027F7', + "LongRightArrow;": '\U000027F6', + "Longleftarrow;": '\U000027F8', + "Longleftrightarrow;": '\U000027FA', + "Longrightarrow;": '\U000027F9', + "Lopf;": '\U0001D543', + "LowerLeftArrow;": '\U00002199', + "LowerRightArrow;": '\U00002198', + "Lscr;": '\U00002112', + "Lsh;": '\U000021B0', + "Lstrok;": '\U00000141', + "Lt;": '\U0000226A', + "Map;": '\U00002905', + "Mcy;": '\U0000041C', + "MediumSpace;": '\U0000205F', + "Mellintrf;": '\U00002133', + "Mfr;": '\U0001D510', + "MinusPlus;": '\U00002213', + "Mopf;": '\U0001D544', + "Mscr;": '\U00002133', + "Mu;": '\U0000039C', + "NJcy;": '\U0000040A', + "Nacute;": '\U00000143', + "Ncaron;": '\U00000147', + "Ncedil;": '\U00000145', + "Ncy;": '\U0000041D', + "NegativeMediumSpace;": '\U0000200B', + "NegativeThickSpace;": '\U0000200B', + "NegativeThinSpace;": '\U0000200B', + "NegativeVeryThinSpace;": '\U0000200B', + "NestedGreaterGreater;": '\U0000226B', + "NestedLessLess;": '\U0000226A', + "NewLine;": '\U0000000A', + "Nfr;": '\U0001D511', + "NoBreak;": '\U00002060', + "NonBreakingSpace;": '\U000000A0', + "Nopf;": '\U00002115', + "Not;": '\U00002AEC', + "NotCongruent;": '\U00002262', + "NotCupCap;": '\U0000226D', + "NotDoubleVerticalBar;": '\U00002226', + "NotElement;": '\U00002209', + "NotEqual;": '\U00002260', + "NotExists;": '\U00002204', + "NotGreater;": '\U0000226F', + "NotGreaterEqual;": '\U00002271', + "NotGreaterLess;": '\U00002279', + "NotGreaterTilde;": '\U00002275', + "NotLeftTriangle;": '\U000022EA', + "NotLeftTriangleEqual;": '\U000022EC', + "NotLess;": '\U0000226E', + "NotLessEqual;": '\U00002270', + "NotLessGreater;": '\U00002278', + "NotLessTilde;": '\U00002274', + "NotPrecedes;": '\U00002280', + "NotPrecedesSlantEqual;": '\U000022E0', + "NotReverseElement;": '\U0000220C', + "NotRightTriangle;": '\U000022EB', + "NotRightTriangleEqual;": '\U000022ED', + "NotSquareSubsetEqual;": '\U000022E2', + "NotSquareSupersetEqual;": '\U000022E3', + "NotSubsetEqual;": '\U00002288', + "NotSucceeds;": '\U00002281', + "NotSucceedsSlantEqual;": '\U000022E1', + "NotSupersetEqual;": '\U00002289', + "NotTilde;": '\U00002241', + "NotTildeEqual;": '\U00002244', + "NotTildeFullEqual;": '\U00002247', + "NotTildeTilde;": '\U00002249', + "NotVerticalBar;": '\U00002224', + "Nscr;": '\U0001D4A9', + "Ntilde;": '\U000000D1', + "Nu;": '\U0000039D', + "OElig;": '\U00000152', + "Oacute;": '\U000000D3', + "Ocirc;": '\U000000D4', + "Ocy;": '\U0000041E', + "Odblac;": '\U00000150', + "Ofr;": '\U0001D512', + "Ograve;": '\U000000D2', + "Omacr;": '\U0000014C', + "Omega;": '\U000003A9', + "Omicron;": '\U0000039F', + "Oopf;": '\U0001D546', + "OpenCurlyDoubleQuote;": '\U0000201C', + "OpenCurlyQuote;": '\U00002018', + "Or;": '\U00002A54', + "Oscr;": '\U0001D4AA', + "Oslash;": '\U000000D8', + "Otilde;": '\U000000D5', + "Otimes;": '\U00002A37', + "Ouml;": '\U000000D6', + "OverBar;": '\U0000203E', + "OverBrace;": '\U000023DE', + "OverBracket;": '\U000023B4', + "OverParenthesis;": '\U000023DC', + "PartialD;": '\U00002202', + "Pcy;": '\U0000041F', + "Pfr;": '\U0001D513', + "Phi;": '\U000003A6', + "Pi;": '\U000003A0', + "PlusMinus;": '\U000000B1', + "Poincareplane;": '\U0000210C', + "Popf;": '\U00002119', + "Pr;": '\U00002ABB', + "Precedes;": '\U0000227A', + "PrecedesEqual;": '\U00002AAF', + "PrecedesSlantEqual;": '\U0000227C', + "PrecedesTilde;": '\U0000227E', + "Prime;": '\U00002033', + "Product;": '\U0000220F', + "Proportion;": '\U00002237', + "Proportional;": '\U0000221D', + "Pscr;": '\U0001D4AB', + "Psi;": '\U000003A8', + "QUOT;": '\U00000022', + "Qfr;": '\U0001D514', + "Qopf;": '\U0000211A', + "Qscr;": '\U0001D4AC', + "RBarr;": '\U00002910', + "REG;": '\U000000AE', + "Racute;": '\U00000154', + "Rang;": '\U000027EB', + "Rarr;": '\U000021A0', + "Rarrtl;": '\U00002916', + "Rcaron;": '\U00000158', + "Rcedil;": '\U00000156', + "Rcy;": '\U00000420', + "Re;": '\U0000211C', + "ReverseElement;": '\U0000220B', + "ReverseEquilibrium;": '\U000021CB', + "ReverseUpEquilibrium;": '\U0000296F', + "Rfr;": '\U0000211C', + "Rho;": '\U000003A1', + "RightAngleBracket;": '\U000027E9', + "RightArrow;": '\U00002192', + "RightArrowBar;": '\U000021E5', + "RightArrowLeftArrow;": '\U000021C4', + "RightCeiling;": '\U00002309', + "RightDoubleBracket;": '\U000027E7', + "RightDownTeeVector;": '\U0000295D', + "RightDownVector;": '\U000021C2', + "RightDownVectorBar;": '\U00002955', + "RightFloor;": '\U0000230B', + "RightTee;": '\U000022A2', + "RightTeeArrow;": '\U000021A6', + "RightTeeVector;": '\U0000295B', + "RightTriangle;": '\U000022B3', + "RightTriangleBar;": '\U000029D0', + "RightTriangleEqual;": '\U000022B5', + "RightUpDownVector;": '\U0000294F', + "RightUpTeeVector;": '\U0000295C', + "RightUpVector;": '\U000021BE', + "RightUpVectorBar;": '\U00002954', + "RightVector;": '\U000021C0', + "RightVectorBar;": '\U00002953', + "Rightarrow;": '\U000021D2', + "Ropf;": '\U0000211D', + "RoundImplies;": '\U00002970', + "Rrightarrow;": '\U000021DB', + "Rscr;": '\U0000211B', + "Rsh;": '\U000021B1', + "RuleDelayed;": '\U000029F4', + "SHCHcy;": '\U00000429', + "SHcy;": '\U00000428', + "SOFTcy;": '\U0000042C', + "Sacute;": '\U0000015A', + "Sc;": '\U00002ABC', + "Scaron;": '\U00000160', + "Scedil;": '\U0000015E', + "Scirc;": '\U0000015C', + "Scy;": '\U00000421', + "Sfr;": '\U0001D516', + "ShortDownArrow;": '\U00002193', + "ShortLeftArrow;": '\U00002190', + "ShortRightArrow;": '\U00002192', + "ShortUpArrow;": '\U00002191', + "Sigma;": '\U000003A3', + "SmallCircle;": '\U00002218', + "Sopf;": '\U0001D54A', + "Sqrt;": '\U0000221A', + "Square;": '\U000025A1', + "SquareIntersection;": '\U00002293', + "SquareSubset;": '\U0000228F', + "SquareSubsetEqual;": '\U00002291', + "SquareSuperset;": '\U00002290', + "SquareSupersetEqual;": '\U00002292', + "SquareUnion;": '\U00002294', + "Sscr;": '\U0001D4AE', + "Star;": '\U000022C6', + "Sub;": '\U000022D0', + "Subset;": '\U000022D0', + "SubsetEqual;": '\U00002286', + "Succeeds;": '\U0000227B', + "SucceedsEqual;": '\U00002AB0', + "SucceedsSlantEqual;": '\U0000227D', + "SucceedsTilde;": '\U0000227F', + "SuchThat;": '\U0000220B', + "Sum;": '\U00002211', + "Sup;": '\U000022D1', + "Superset;": '\U00002283', + "SupersetEqual;": '\U00002287', + "Supset;": '\U000022D1', + "THORN;": '\U000000DE', + "TRADE;": '\U00002122', + "TSHcy;": '\U0000040B', + "TScy;": '\U00000426', + "Tab;": '\U00000009', + "Tau;": '\U000003A4', + "Tcaron;": '\U00000164', + "Tcedil;": '\U00000162', + "Tcy;": '\U00000422', + "Tfr;": '\U0001D517', + "Therefore;": '\U00002234', + "Theta;": '\U00000398', + "ThinSpace;": '\U00002009', + "Tilde;": '\U0000223C', + "TildeEqual;": '\U00002243', + "TildeFullEqual;": '\U00002245', + "TildeTilde;": '\U00002248', + "Topf;": '\U0001D54B', + "TripleDot;": '\U000020DB', + "Tscr;": '\U0001D4AF', + "Tstrok;": '\U00000166', + "Uacute;": '\U000000DA', + "Uarr;": '\U0000219F', + "Uarrocir;": '\U00002949', + "Ubrcy;": '\U0000040E', + "Ubreve;": '\U0000016C', + "Ucirc;": '\U000000DB', + "Ucy;": '\U00000423', + "Udblac;": '\U00000170', + "Ufr;": '\U0001D518', + "Ugrave;": '\U000000D9', + "Umacr;": '\U0000016A', + "UnderBar;": '\U0000005F', + "UnderBrace;": '\U000023DF', + "UnderBracket;": '\U000023B5', + "UnderParenthesis;": '\U000023DD', + "Union;": '\U000022C3', + "UnionPlus;": '\U0000228E', + "Uogon;": '\U00000172', + "Uopf;": '\U0001D54C', + "UpArrow;": '\U00002191', + "UpArrowBar;": '\U00002912', + "UpArrowDownArrow;": '\U000021C5', + "UpDownArrow;": '\U00002195', + "UpEquilibrium;": '\U0000296E', + "UpTee;": '\U000022A5', + "UpTeeArrow;": '\U000021A5', + "Uparrow;": '\U000021D1', + "Updownarrow;": '\U000021D5', + "UpperLeftArrow;": '\U00002196', + "UpperRightArrow;": '\U00002197', + "Upsi;": '\U000003D2', + "Upsilon;": '\U000003A5', + "Uring;": '\U0000016E', + "Uscr;": '\U0001D4B0', + "Utilde;": '\U00000168', + "Uuml;": '\U000000DC', + "VDash;": '\U000022AB', + "Vbar;": '\U00002AEB', + "Vcy;": '\U00000412', + "Vdash;": '\U000022A9', + "Vdashl;": '\U00002AE6', + "Vee;": '\U000022C1', + "Verbar;": '\U00002016', + "Vert;": '\U00002016', + "VerticalBar;": '\U00002223', + "VerticalLine;": '\U0000007C', + "VerticalSeparator;": '\U00002758', + "VerticalTilde;": '\U00002240', + "VeryThinSpace;": '\U0000200A', + "Vfr;": '\U0001D519', + "Vopf;": '\U0001D54D', + "Vscr;": '\U0001D4B1', + "Vvdash;": '\U000022AA', + "Wcirc;": '\U00000174', + "Wedge;": '\U000022C0', + "Wfr;": '\U0001D51A', + "Wopf;": '\U0001D54E', + "Wscr;": '\U0001D4B2', + "Xfr;": '\U0001D51B', + "Xi;": '\U0000039E', + "Xopf;": '\U0001D54F', + "Xscr;": '\U0001D4B3', + "YAcy;": '\U0000042F', + "YIcy;": '\U00000407', + "YUcy;": '\U0000042E', + "Yacute;": '\U000000DD', + "Ycirc;": '\U00000176', + "Ycy;": '\U0000042B', + "Yfr;": '\U0001D51C', + "Yopf;": '\U0001D550', + "Yscr;": '\U0001D4B4', + "Yuml;": '\U00000178', + "ZHcy;": '\U00000416', + "Zacute;": '\U00000179', + "Zcaron;": '\U0000017D', + "Zcy;": '\U00000417', + "Zdot;": '\U0000017B', + "ZeroWidthSpace;": '\U0000200B', + "Zeta;": '\U00000396', + "Zfr;": '\U00002128', + "Zopf;": '\U00002124', + "Zscr;": '\U0001D4B5', + "aacute;": '\U000000E1', + "abreve;": '\U00000103', + "ac;": '\U0000223E', + "acd;": '\U0000223F', + "acirc;": '\U000000E2', + "acute;": '\U000000B4', + "acy;": '\U00000430', + "aelig;": '\U000000E6', + "af;": '\U00002061', + "afr;": '\U0001D51E', + "agrave;": '\U000000E0', + "alefsym;": '\U00002135', + "aleph;": '\U00002135', + "alpha;": '\U000003B1', + "amacr;": '\U00000101', + "amalg;": '\U00002A3F', + "amp;": '\U00000026', + "and;": '\U00002227', + "andand;": '\U00002A55', + "andd;": '\U00002A5C', + "andslope;": '\U00002A58', + "andv;": '\U00002A5A', + "ang;": '\U00002220', + "ange;": '\U000029A4', + "angle;": '\U00002220', + "angmsd;": '\U00002221', + "angmsdaa;": '\U000029A8', + "angmsdab;": '\U000029A9', + "angmsdac;": '\U000029AA', + "angmsdad;": '\U000029AB', + "angmsdae;": '\U000029AC', + "angmsdaf;": '\U000029AD', + "angmsdag;": '\U000029AE', + "angmsdah;": '\U000029AF', + "angrt;": '\U0000221F', + "angrtvb;": '\U000022BE', + "angrtvbd;": '\U0000299D', + "angsph;": '\U00002222', + "angst;": '\U000000C5', + "angzarr;": '\U0000237C', + "aogon;": '\U00000105', + "aopf;": '\U0001D552', + "ap;": '\U00002248', + "apE;": '\U00002A70', + "apacir;": '\U00002A6F', + "ape;": '\U0000224A', + "apid;": '\U0000224B', + "apos;": '\U00000027', + "approx;": '\U00002248', + "approxeq;": '\U0000224A', + "aring;": '\U000000E5', + "ascr;": '\U0001D4B6', + "ast;": '\U0000002A', + "asymp;": '\U00002248', + "asympeq;": '\U0000224D', + "atilde;": '\U000000E3', + "auml;": '\U000000E4', + "awconint;": '\U00002233', + "awint;": '\U00002A11', + "bNot;": '\U00002AED', + "backcong;": '\U0000224C', + "backepsilon;": '\U000003F6', + "backprime;": '\U00002035', + "backsim;": '\U0000223D', + "backsimeq;": '\U000022CD', + "barvee;": '\U000022BD', + "barwed;": '\U00002305', + "barwedge;": '\U00002305', + "bbrk;": '\U000023B5', + "bbrktbrk;": '\U000023B6', + "bcong;": '\U0000224C', + "bcy;": '\U00000431', + "bdquo;": '\U0000201E', + "becaus;": '\U00002235', + "because;": '\U00002235', + "bemptyv;": '\U000029B0', + "bepsi;": '\U000003F6', + "bernou;": '\U0000212C', + "beta;": '\U000003B2', + "beth;": '\U00002136', + "between;": '\U0000226C', + "bfr;": '\U0001D51F', + "bigcap;": '\U000022C2', + "bigcirc;": '\U000025EF', + "bigcup;": '\U000022C3', + "bigodot;": '\U00002A00', + "bigoplus;": '\U00002A01', + "bigotimes;": '\U00002A02', + "bigsqcup;": '\U00002A06', + "bigstar;": '\U00002605', + "bigtriangledown;": '\U000025BD', + "bigtriangleup;": '\U000025B3', + "biguplus;": '\U00002A04', + "bigvee;": '\U000022C1', + "bigwedge;": '\U000022C0', + "bkarow;": '\U0000290D', + "blacklozenge;": '\U000029EB', + "blacksquare;": '\U000025AA', + "blacktriangle;": '\U000025B4', + "blacktriangledown;": '\U000025BE', + "blacktriangleleft;": '\U000025C2', + "blacktriangleright;": '\U000025B8', + "blank;": '\U00002423', + "blk12;": '\U00002592', + "blk14;": '\U00002591', + "blk34;": '\U00002593', + "block;": '\U00002588', + "bnot;": '\U00002310', + "bopf;": '\U0001D553', + "bot;": '\U000022A5', + "bottom;": '\U000022A5', + "bowtie;": '\U000022C8', + "boxDL;": '\U00002557', + "boxDR;": '\U00002554', + "boxDl;": '\U00002556', + "boxDr;": '\U00002553', + "boxH;": '\U00002550', + "boxHD;": '\U00002566', + "boxHU;": '\U00002569', + "boxHd;": '\U00002564', + "boxHu;": '\U00002567', + "boxUL;": '\U0000255D', + "boxUR;": '\U0000255A', + "boxUl;": '\U0000255C', + "boxUr;": '\U00002559', + "boxV;": '\U00002551', + "boxVH;": '\U0000256C', + "boxVL;": '\U00002563', + "boxVR;": '\U00002560', + "boxVh;": '\U0000256B', + "boxVl;": '\U00002562', + "boxVr;": '\U0000255F', + "boxbox;": '\U000029C9', + "boxdL;": '\U00002555', + "boxdR;": '\U00002552', + "boxdl;": '\U00002510', + "boxdr;": '\U0000250C', + "boxh;": '\U00002500', + "boxhD;": '\U00002565', + "boxhU;": '\U00002568', + "boxhd;": '\U0000252C', + "boxhu;": '\U00002534', + "boxminus;": '\U0000229F', + "boxplus;": '\U0000229E', + "boxtimes;": '\U000022A0', + "boxuL;": '\U0000255B', + "boxuR;": '\U00002558', + "boxul;": '\U00002518', + "boxur;": '\U00002514', + "boxv;": '\U00002502', + "boxvH;": '\U0000256A', + "boxvL;": '\U00002561', + "boxvR;": '\U0000255E', + "boxvh;": '\U0000253C', + "boxvl;": '\U00002524', + "boxvr;": '\U0000251C', + "bprime;": '\U00002035', + "breve;": '\U000002D8', + "brvbar;": '\U000000A6', + "bscr;": '\U0001D4B7', + "bsemi;": '\U0000204F', + "bsim;": '\U0000223D', + "bsime;": '\U000022CD', + "bsol;": '\U0000005C', + "bsolb;": '\U000029C5', + "bsolhsub;": '\U000027C8', + "bull;": '\U00002022', + "bullet;": '\U00002022', + "bump;": '\U0000224E', + "bumpE;": '\U00002AAE', + "bumpe;": '\U0000224F', + "bumpeq;": '\U0000224F', + "cacute;": '\U00000107', + "cap;": '\U00002229', + "capand;": '\U00002A44', + "capbrcup;": '\U00002A49', + "capcap;": '\U00002A4B', + "capcup;": '\U00002A47', + "capdot;": '\U00002A40', + "caret;": '\U00002041', + "caron;": '\U000002C7', + "ccaps;": '\U00002A4D', + "ccaron;": '\U0000010D', + "ccedil;": '\U000000E7', + "ccirc;": '\U00000109', + "ccups;": '\U00002A4C', + "ccupssm;": '\U00002A50', + "cdot;": '\U0000010B', + "cedil;": '\U000000B8', + "cemptyv;": '\U000029B2', + "cent;": '\U000000A2', + "centerdot;": '\U000000B7', + "cfr;": '\U0001D520', + "chcy;": '\U00000447', + "check;": '\U00002713', + "checkmark;": '\U00002713', + "chi;": '\U000003C7', + "cir;": '\U000025CB', + "cirE;": '\U000029C3', + "circ;": '\U000002C6', + "circeq;": '\U00002257', + "circlearrowleft;": '\U000021BA', + "circlearrowright;": '\U000021BB', + "circledR;": '\U000000AE', + "circledS;": '\U000024C8', + "circledast;": '\U0000229B', + "circledcirc;": '\U0000229A', + "circleddash;": '\U0000229D', + "cire;": '\U00002257', + "cirfnint;": '\U00002A10', + "cirmid;": '\U00002AEF', + "cirscir;": '\U000029C2', + "clubs;": '\U00002663', + "clubsuit;": '\U00002663', + "colon;": '\U0000003A', + "colone;": '\U00002254', + "coloneq;": '\U00002254', + "comma;": '\U0000002C', + "commat;": '\U00000040', + "comp;": '\U00002201', + "compfn;": '\U00002218', + "complement;": '\U00002201', + "complexes;": '\U00002102', + "cong;": '\U00002245', + "congdot;": '\U00002A6D', + "conint;": '\U0000222E', + "copf;": '\U0001D554', + "coprod;": '\U00002210', + "copy;": '\U000000A9', + "copysr;": '\U00002117', + "crarr;": '\U000021B5', + "cross;": '\U00002717', + "cscr;": '\U0001D4B8', + "csub;": '\U00002ACF', + "csube;": '\U00002AD1', + "csup;": '\U00002AD0', + "csupe;": '\U00002AD2', + "ctdot;": '\U000022EF', + "cudarrl;": '\U00002938', + "cudarrr;": '\U00002935', + "cuepr;": '\U000022DE', + "cuesc;": '\U000022DF', + "cularr;": '\U000021B6', + "cularrp;": '\U0000293D', + "cup;": '\U0000222A', + "cupbrcap;": '\U00002A48', + "cupcap;": '\U00002A46', + "cupcup;": '\U00002A4A', + "cupdot;": '\U0000228D', + "cupor;": '\U00002A45', + "curarr;": '\U000021B7', + "curarrm;": '\U0000293C', + "curlyeqprec;": '\U000022DE', + "curlyeqsucc;": '\U000022DF', + "curlyvee;": '\U000022CE', + "curlywedge;": '\U000022CF', + "curren;": '\U000000A4', + "curvearrowleft;": '\U000021B6', + "curvearrowright;": '\U000021B7', + "cuvee;": '\U000022CE', + "cuwed;": '\U000022CF', + "cwconint;": '\U00002232', + "cwint;": '\U00002231', + "cylcty;": '\U0000232D', + "dArr;": '\U000021D3', + "dHar;": '\U00002965', + "dagger;": '\U00002020', + "daleth;": '\U00002138', + "darr;": '\U00002193', + "dash;": '\U00002010', + "dashv;": '\U000022A3', + "dbkarow;": '\U0000290F', + "dblac;": '\U000002DD', + "dcaron;": '\U0000010F', + "dcy;": '\U00000434', + "dd;": '\U00002146', + "ddagger;": '\U00002021', + "ddarr;": '\U000021CA', + "ddotseq;": '\U00002A77', + "deg;": '\U000000B0', + "delta;": '\U000003B4', + "demptyv;": '\U000029B1', + "dfisht;": '\U0000297F', + "dfr;": '\U0001D521', + "dharl;": '\U000021C3', + "dharr;": '\U000021C2', + "diam;": '\U000022C4', + "diamond;": '\U000022C4', + "diamondsuit;": '\U00002666', + "diams;": '\U00002666', + "die;": '\U000000A8', + "digamma;": '\U000003DD', + "disin;": '\U000022F2', + "div;": '\U000000F7', + "divide;": '\U000000F7', + "divideontimes;": '\U000022C7', + "divonx;": '\U000022C7', + "djcy;": '\U00000452', + "dlcorn;": '\U0000231E', + "dlcrop;": '\U0000230D', + "dollar;": '\U00000024', + "dopf;": '\U0001D555', + "dot;": '\U000002D9', + "doteq;": '\U00002250', + "doteqdot;": '\U00002251', + "dotminus;": '\U00002238', + "dotplus;": '\U00002214', + "dotsquare;": '\U000022A1', + "doublebarwedge;": '\U00002306', + "downarrow;": '\U00002193', + "downdownarrows;": '\U000021CA', + "downharpoonleft;": '\U000021C3', + "downharpoonright;": '\U000021C2', + "drbkarow;": '\U00002910', + "drcorn;": '\U0000231F', + "drcrop;": '\U0000230C', + "dscr;": '\U0001D4B9', + "dscy;": '\U00000455', + "dsol;": '\U000029F6', + "dstrok;": '\U00000111', + "dtdot;": '\U000022F1', + "dtri;": '\U000025BF', + "dtrif;": '\U000025BE', + "duarr;": '\U000021F5', + "duhar;": '\U0000296F', + "dwangle;": '\U000029A6', + "dzcy;": '\U0000045F', + "dzigrarr;": '\U000027FF', + "eDDot;": '\U00002A77', + "eDot;": '\U00002251', + "eacute;": '\U000000E9', + "easter;": '\U00002A6E', + "ecaron;": '\U0000011B', + "ecir;": '\U00002256', + "ecirc;": '\U000000EA', + "ecolon;": '\U00002255', + "ecy;": '\U0000044D', + "edot;": '\U00000117', + "ee;": '\U00002147', + "efDot;": '\U00002252', + "efr;": '\U0001D522', + "eg;": '\U00002A9A', + "egrave;": '\U000000E8', + "egs;": '\U00002A96', + "egsdot;": '\U00002A98', + "el;": '\U00002A99', + "elinters;": '\U000023E7', + "ell;": '\U00002113', + "els;": '\U00002A95', + "elsdot;": '\U00002A97', + "emacr;": '\U00000113', + "empty;": '\U00002205', + "emptyset;": '\U00002205', + "emptyv;": '\U00002205', + "emsp;": '\U00002003', + "emsp13;": '\U00002004', + "emsp14;": '\U00002005', + "eng;": '\U0000014B', + "ensp;": '\U00002002', + "eogon;": '\U00000119', + "eopf;": '\U0001D556', + "epar;": '\U000022D5', + "eparsl;": '\U000029E3', + "eplus;": '\U00002A71', + "epsi;": '\U000003B5', + "epsilon;": '\U000003B5', + "epsiv;": '\U000003F5', + "eqcirc;": '\U00002256', + "eqcolon;": '\U00002255', + "eqsim;": '\U00002242', + "eqslantgtr;": '\U00002A96', + "eqslantless;": '\U00002A95', + "equals;": '\U0000003D', + "equest;": '\U0000225F', + "equiv;": '\U00002261', + "equivDD;": '\U00002A78', + "eqvparsl;": '\U000029E5', + "erDot;": '\U00002253', + "erarr;": '\U00002971', + "escr;": '\U0000212F', + "esdot;": '\U00002250', + "esim;": '\U00002242', + "eta;": '\U000003B7', + "eth;": '\U000000F0', + "euml;": '\U000000EB', + "euro;": '\U000020AC', + "excl;": '\U00000021', + "exist;": '\U00002203', + "expectation;": '\U00002130', + "exponentiale;": '\U00002147', + "fallingdotseq;": '\U00002252', + "fcy;": '\U00000444', + "female;": '\U00002640', + "ffilig;": '\U0000FB03', + "fflig;": '\U0000FB00', + "ffllig;": '\U0000FB04', + "ffr;": '\U0001D523', + "filig;": '\U0000FB01', + "flat;": '\U0000266D', + "fllig;": '\U0000FB02', + "fltns;": '\U000025B1', + "fnof;": '\U00000192', + "fopf;": '\U0001D557', + "forall;": '\U00002200', + "fork;": '\U000022D4', + "forkv;": '\U00002AD9', + "fpartint;": '\U00002A0D', + "frac12;": '\U000000BD', + "frac13;": '\U00002153', + "frac14;": '\U000000BC', + "frac15;": '\U00002155', + "frac16;": '\U00002159', + "frac18;": '\U0000215B', + "frac23;": '\U00002154', + "frac25;": '\U00002156', + "frac34;": '\U000000BE', + "frac35;": '\U00002157', + "frac38;": '\U0000215C', + "frac45;": '\U00002158', + "frac56;": '\U0000215A', + "frac58;": '\U0000215D', + "frac78;": '\U0000215E', + "frasl;": '\U00002044', + "frown;": '\U00002322', + "fscr;": '\U0001D4BB', + "gE;": '\U00002267', + "gEl;": '\U00002A8C', + "gacute;": '\U000001F5', + "gamma;": '\U000003B3', + "gammad;": '\U000003DD', + "gap;": '\U00002A86', + "gbreve;": '\U0000011F', + "gcirc;": '\U0000011D', + "gcy;": '\U00000433', + "gdot;": '\U00000121', + "ge;": '\U00002265', + "gel;": '\U000022DB', + "geq;": '\U00002265', + "geqq;": '\U00002267', + "geqslant;": '\U00002A7E', + "ges;": '\U00002A7E', + "gescc;": '\U00002AA9', + "gesdot;": '\U00002A80', + "gesdoto;": '\U00002A82', + "gesdotol;": '\U00002A84', + "gesles;": '\U00002A94', + "gfr;": '\U0001D524', + "gg;": '\U0000226B', + "ggg;": '\U000022D9', + "gimel;": '\U00002137', + "gjcy;": '\U00000453', + "gl;": '\U00002277', + "glE;": '\U00002A92', + "gla;": '\U00002AA5', + "glj;": '\U00002AA4', + "gnE;": '\U00002269', + "gnap;": '\U00002A8A', + "gnapprox;": '\U00002A8A', + "gne;": '\U00002A88', + "gneq;": '\U00002A88', + "gneqq;": '\U00002269', + "gnsim;": '\U000022E7', + "gopf;": '\U0001D558', + "grave;": '\U00000060', + "gscr;": '\U0000210A', + "gsim;": '\U00002273', + "gsime;": '\U00002A8E', + "gsiml;": '\U00002A90', + "gt;": '\U0000003E', + "gtcc;": '\U00002AA7', + "gtcir;": '\U00002A7A', + "gtdot;": '\U000022D7', + "gtlPar;": '\U00002995', + "gtquest;": '\U00002A7C', + "gtrapprox;": '\U00002A86', + "gtrarr;": '\U00002978', + "gtrdot;": '\U000022D7', + "gtreqless;": '\U000022DB', + "gtreqqless;": '\U00002A8C', + "gtrless;": '\U00002277', + "gtrsim;": '\U00002273', + "hArr;": '\U000021D4', + "hairsp;": '\U0000200A', + "half;": '\U000000BD', + "hamilt;": '\U0000210B', + "hardcy;": '\U0000044A', + "harr;": '\U00002194', + "harrcir;": '\U00002948', + "harrw;": '\U000021AD', + "hbar;": '\U0000210F', + "hcirc;": '\U00000125', + "hearts;": '\U00002665', + "heartsuit;": '\U00002665', + "hellip;": '\U00002026', + "hercon;": '\U000022B9', + "hfr;": '\U0001D525', + "hksearow;": '\U00002925', + "hkswarow;": '\U00002926', + "hoarr;": '\U000021FF', + "homtht;": '\U0000223B', + "hookleftarrow;": '\U000021A9', + "hookrightarrow;": '\U000021AA', + "hopf;": '\U0001D559', + "horbar;": '\U00002015', + "hscr;": '\U0001D4BD', + "hslash;": '\U0000210F', + "hstrok;": '\U00000127', + "hybull;": '\U00002043', + "hyphen;": '\U00002010', + "iacute;": '\U000000ED', + "ic;": '\U00002063', + "icirc;": '\U000000EE', + "icy;": '\U00000438', + "iecy;": '\U00000435', + "iexcl;": '\U000000A1', + "iff;": '\U000021D4', + "ifr;": '\U0001D526', + "igrave;": '\U000000EC', + "ii;": '\U00002148', + "iiiint;": '\U00002A0C', + "iiint;": '\U0000222D', + "iinfin;": '\U000029DC', + "iiota;": '\U00002129', + "ijlig;": '\U00000133', + "imacr;": '\U0000012B', + "image;": '\U00002111', + "imagline;": '\U00002110', + "imagpart;": '\U00002111', + "imath;": '\U00000131', + "imof;": '\U000022B7', + "imped;": '\U000001B5', + "in;": '\U00002208', + "incare;": '\U00002105', + "infin;": '\U0000221E', + "infintie;": '\U000029DD', + "inodot;": '\U00000131', + "int;": '\U0000222B', + "intcal;": '\U000022BA', + "integers;": '\U00002124', + "intercal;": '\U000022BA', + "intlarhk;": '\U00002A17', + "intprod;": '\U00002A3C', + "iocy;": '\U00000451', + "iogon;": '\U0000012F', + "iopf;": '\U0001D55A', + "iota;": '\U000003B9', + "iprod;": '\U00002A3C', + "iquest;": '\U000000BF', + "iscr;": '\U0001D4BE', + "isin;": '\U00002208', + "isinE;": '\U000022F9', + "isindot;": '\U000022F5', + "isins;": '\U000022F4', + "isinsv;": '\U000022F3', + "isinv;": '\U00002208', + "it;": '\U00002062', + "itilde;": '\U00000129', + "iukcy;": '\U00000456', + "iuml;": '\U000000EF', + "jcirc;": '\U00000135', + "jcy;": '\U00000439', + "jfr;": '\U0001D527', + "jmath;": '\U00000237', + "jopf;": '\U0001D55B', + "jscr;": '\U0001D4BF', + "jsercy;": '\U00000458', + "jukcy;": '\U00000454', + "kappa;": '\U000003BA', + "kappav;": '\U000003F0', + "kcedil;": '\U00000137', + "kcy;": '\U0000043A', + "kfr;": '\U0001D528', + "kgreen;": '\U00000138', + "khcy;": '\U00000445', + "kjcy;": '\U0000045C', + "kopf;": '\U0001D55C', + "kscr;": '\U0001D4C0', + "lAarr;": '\U000021DA', + "lArr;": '\U000021D0', + "lAtail;": '\U0000291B', + "lBarr;": '\U0000290E', + "lE;": '\U00002266', + "lEg;": '\U00002A8B', + "lHar;": '\U00002962', + "lacute;": '\U0000013A', + "laemptyv;": '\U000029B4', + "lagran;": '\U00002112', + "lambda;": '\U000003BB', + "lang;": '\U000027E8', + "langd;": '\U00002991', + "langle;": '\U000027E8', + "lap;": '\U00002A85', + "laquo;": '\U000000AB', + "larr;": '\U00002190', + "larrb;": '\U000021E4', + "larrbfs;": '\U0000291F', + "larrfs;": '\U0000291D', + "larrhk;": '\U000021A9', + "larrlp;": '\U000021AB', + "larrpl;": '\U00002939', + "larrsim;": '\U00002973', + "larrtl;": '\U000021A2', + "lat;": '\U00002AAB', + "latail;": '\U00002919', + "late;": '\U00002AAD', + "lbarr;": '\U0000290C', + "lbbrk;": '\U00002772', + "lbrace;": '\U0000007B', + "lbrack;": '\U0000005B', + "lbrke;": '\U0000298B', + "lbrksld;": '\U0000298F', + "lbrkslu;": '\U0000298D', + "lcaron;": '\U0000013E', + "lcedil;": '\U0000013C', + "lceil;": '\U00002308', + "lcub;": '\U0000007B', + "lcy;": '\U0000043B', + "ldca;": '\U00002936', + "ldquo;": '\U0000201C', + "ldquor;": '\U0000201E', + "ldrdhar;": '\U00002967', + "ldrushar;": '\U0000294B', + "ldsh;": '\U000021B2', + "le;": '\U00002264', + "leftarrow;": '\U00002190', + "leftarrowtail;": '\U000021A2', + "leftharpoondown;": '\U000021BD', + "leftharpoonup;": '\U000021BC', + "leftleftarrows;": '\U000021C7', + "leftrightarrow;": '\U00002194', + "leftrightarrows;": '\U000021C6', + "leftrightharpoons;": '\U000021CB', + "leftrightsquigarrow;": '\U000021AD', + "leftthreetimes;": '\U000022CB', + "leg;": '\U000022DA', + "leq;": '\U00002264', + "leqq;": '\U00002266', + "leqslant;": '\U00002A7D', + "les;": '\U00002A7D', + "lescc;": '\U00002AA8', + "lesdot;": '\U00002A7F', + "lesdoto;": '\U00002A81', + "lesdotor;": '\U00002A83', + "lesges;": '\U00002A93', + "lessapprox;": '\U00002A85', + "lessdot;": '\U000022D6', + "lesseqgtr;": '\U000022DA', + "lesseqqgtr;": '\U00002A8B', + "lessgtr;": '\U00002276', + "lesssim;": '\U00002272', + "lfisht;": '\U0000297C', + "lfloor;": '\U0000230A', + "lfr;": '\U0001D529', + "lg;": '\U00002276', + "lgE;": '\U00002A91', + "lhard;": '\U000021BD', + "lharu;": '\U000021BC', + "lharul;": '\U0000296A', + "lhblk;": '\U00002584', + "ljcy;": '\U00000459', + "ll;": '\U0000226A', + "llarr;": '\U000021C7', + "llcorner;": '\U0000231E', + "llhard;": '\U0000296B', + "lltri;": '\U000025FA', + "lmidot;": '\U00000140', + "lmoust;": '\U000023B0', + "lmoustache;": '\U000023B0', + "lnE;": '\U00002268', + "lnap;": '\U00002A89', + "lnapprox;": '\U00002A89', + "lne;": '\U00002A87', + "lneq;": '\U00002A87', + "lneqq;": '\U00002268', + "lnsim;": '\U000022E6', + "loang;": '\U000027EC', + "loarr;": '\U000021FD', + "lobrk;": '\U000027E6', + "longleftarrow;": '\U000027F5', + "longleftrightarrow;": '\U000027F7', + "longmapsto;": '\U000027FC', + "longrightarrow;": '\U000027F6', + "looparrowleft;": '\U000021AB', + "looparrowright;": '\U000021AC', + "lopar;": '\U00002985', + "lopf;": '\U0001D55D', + "loplus;": '\U00002A2D', + "lotimes;": '\U00002A34', + "lowast;": '\U00002217', + "lowbar;": '\U0000005F', + "loz;": '\U000025CA', + "lozenge;": '\U000025CA', + "lozf;": '\U000029EB', + "lpar;": '\U00000028', + "lparlt;": '\U00002993', + "lrarr;": '\U000021C6', + "lrcorner;": '\U0000231F', + "lrhar;": '\U000021CB', + "lrhard;": '\U0000296D', + "lrm;": '\U0000200E', + "lrtri;": '\U000022BF', + "lsaquo;": '\U00002039', + "lscr;": '\U0001D4C1', + "lsh;": '\U000021B0', + "lsim;": '\U00002272', + "lsime;": '\U00002A8D', + "lsimg;": '\U00002A8F', + "lsqb;": '\U0000005B', + "lsquo;": '\U00002018', + "lsquor;": '\U0000201A', + "lstrok;": '\U00000142', + "lt;": '\U0000003C', + "ltcc;": '\U00002AA6', + "ltcir;": '\U00002A79', + "ltdot;": '\U000022D6', + "lthree;": '\U000022CB', + "ltimes;": '\U000022C9', + "ltlarr;": '\U00002976', + "ltquest;": '\U00002A7B', + "ltrPar;": '\U00002996', + "ltri;": '\U000025C3', + "ltrie;": '\U000022B4', + "ltrif;": '\U000025C2', + "lurdshar;": '\U0000294A', + "luruhar;": '\U00002966', + "mDDot;": '\U0000223A', + "macr;": '\U000000AF', + "male;": '\U00002642', + "malt;": '\U00002720', + "maltese;": '\U00002720', + "map;": '\U000021A6', + "mapsto;": '\U000021A6', + "mapstodown;": '\U000021A7', + "mapstoleft;": '\U000021A4', + "mapstoup;": '\U000021A5', + "marker;": '\U000025AE', + "mcomma;": '\U00002A29', + "mcy;": '\U0000043C', + "mdash;": '\U00002014', + "measuredangle;": '\U00002221', + "mfr;": '\U0001D52A', + "mho;": '\U00002127', + "micro;": '\U000000B5', + "mid;": '\U00002223', + "midast;": '\U0000002A', + "midcir;": '\U00002AF0', + "middot;": '\U000000B7', + "minus;": '\U00002212', + "minusb;": '\U0000229F', + "minusd;": '\U00002238', + "minusdu;": '\U00002A2A', + "mlcp;": '\U00002ADB', + "mldr;": '\U00002026', + "mnplus;": '\U00002213', + "models;": '\U000022A7', + "mopf;": '\U0001D55E', + "mp;": '\U00002213', + "mscr;": '\U0001D4C2', + "mstpos;": '\U0000223E', + "mu;": '\U000003BC', + "multimap;": '\U000022B8', + "mumap;": '\U000022B8', + "nLeftarrow;": '\U000021CD', + "nLeftrightarrow;": '\U000021CE', + "nRightarrow;": '\U000021CF', + "nVDash;": '\U000022AF', + "nVdash;": '\U000022AE', + "nabla;": '\U00002207', + "nacute;": '\U00000144', + "nap;": '\U00002249', + "napos;": '\U00000149', + "napprox;": '\U00002249', + "natur;": '\U0000266E', + "natural;": '\U0000266E', + "naturals;": '\U00002115', + "nbsp;": '\U000000A0', + "ncap;": '\U00002A43', + "ncaron;": '\U00000148', + "ncedil;": '\U00000146', + "ncong;": '\U00002247', + "ncup;": '\U00002A42', + "ncy;": '\U0000043D', + "ndash;": '\U00002013', + "ne;": '\U00002260', + "neArr;": '\U000021D7', + "nearhk;": '\U00002924', + "nearr;": '\U00002197', + "nearrow;": '\U00002197', + "nequiv;": '\U00002262', + "nesear;": '\U00002928', + "nexist;": '\U00002204', + "nexists;": '\U00002204', + "nfr;": '\U0001D52B', + "nge;": '\U00002271', + "ngeq;": '\U00002271', + "ngsim;": '\U00002275', + "ngt;": '\U0000226F', + "ngtr;": '\U0000226F', + "nhArr;": '\U000021CE', + "nharr;": '\U000021AE', + "nhpar;": '\U00002AF2', + "ni;": '\U0000220B', + "nis;": '\U000022FC', + "nisd;": '\U000022FA', + "niv;": '\U0000220B', + "njcy;": '\U0000045A', + "nlArr;": '\U000021CD', + "nlarr;": '\U0000219A', + "nldr;": '\U00002025', + "nle;": '\U00002270', + "nleftarrow;": '\U0000219A', + "nleftrightarrow;": '\U000021AE', + "nleq;": '\U00002270', + "nless;": '\U0000226E', + "nlsim;": '\U00002274', + "nlt;": '\U0000226E', + "nltri;": '\U000022EA', + "nltrie;": '\U000022EC', + "nmid;": '\U00002224', + "nopf;": '\U0001D55F', + "not;": '\U000000AC', + "notin;": '\U00002209', + "notinva;": '\U00002209', + "notinvb;": '\U000022F7', + "notinvc;": '\U000022F6', + "notni;": '\U0000220C', + "notniva;": '\U0000220C', + "notnivb;": '\U000022FE', + "notnivc;": '\U000022FD', + "npar;": '\U00002226', + "nparallel;": '\U00002226', + "npolint;": '\U00002A14', + "npr;": '\U00002280', + "nprcue;": '\U000022E0', + "nprec;": '\U00002280', + "nrArr;": '\U000021CF', + "nrarr;": '\U0000219B', + "nrightarrow;": '\U0000219B', + "nrtri;": '\U000022EB', + "nrtrie;": '\U000022ED', + "nsc;": '\U00002281', + "nsccue;": '\U000022E1', + "nscr;": '\U0001D4C3', + "nshortmid;": '\U00002224', + "nshortparallel;": '\U00002226', + "nsim;": '\U00002241', + "nsime;": '\U00002244', + "nsimeq;": '\U00002244', + "nsmid;": '\U00002224', + "nspar;": '\U00002226', + "nsqsube;": '\U000022E2', + "nsqsupe;": '\U000022E3', + "nsub;": '\U00002284', + "nsube;": '\U00002288', + "nsubseteq;": '\U00002288', + "nsucc;": '\U00002281', + "nsup;": '\U00002285', + "nsupe;": '\U00002289', + "nsupseteq;": '\U00002289', + "ntgl;": '\U00002279', + "ntilde;": '\U000000F1', + "ntlg;": '\U00002278', + "ntriangleleft;": '\U000022EA', + "ntrianglelefteq;": '\U000022EC', + "ntriangleright;": '\U000022EB', + "ntrianglerighteq;": '\U000022ED', + "nu;": '\U000003BD', + "num;": '\U00000023', + "numero;": '\U00002116', + "numsp;": '\U00002007', + "nvDash;": '\U000022AD', + "nvHarr;": '\U00002904', + "nvdash;": '\U000022AC', + "nvinfin;": '\U000029DE', + "nvlArr;": '\U00002902', + "nvrArr;": '\U00002903', + "nwArr;": '\U000021D6', + "nwarhk;": '\U00002923', + "nwarr;": '\U00002196', + "nwarrow;": '\U00002196', + "nwnear;": '\U00002927', + "oS;": '\U000024C8', + "oacute;": '\U000000F3', + "oast;": '\U0000229B', + "ocir;": '\U0000229A', + "ocirc;": '\U000000F4', + "ocy;": '\U0000043E', + "odash;": '\U0000229D', + "odblac;": '\U00000151', + "odiv;": '\U00002A38', + "odot;": '\U00002299', + "odsold;": '\U000029BC', + "oelig;": '\U00000153', + "ofcir;": '\U000029BF', + "ofr;": '\U0001D52C', + "ogon;": '\U000002DB', + "ograve;": '\U000000F2', + "ogt;": '\U000029C1', + "ohbar;": '\U000029B5', + "ohm;": '\U000003A9', + "oint;": '\U0000222E', + "olarr;": '\U000021BA', + "olcir;": '\U000029BE', + "olcross;": '\U000029BB', + "oline;": '\U0000203E', + "olt;": '\U000029C0', + "omacr;": '\U0000014D', + "omega;": '\U000003C9', + "omicron;": '\U000003BF', + "omid;": '\U000029B6', + "ominus;": '\U00002296', + "oopf;": '\U0001D560', + "opar;": '\U000029B7', + "operp;": '\U000029B9', + "oplus;": '\U00002295', + "or;": '\U00002228', + "orarr;": '\U000021BB', + "ord;": '\U00002A5D', + "order;": '\U00002134', + "orderof;": '\U00002134', + "ordf;": '\U000000AA', + "ordm;": '\U000000BA', + "origof;": '\U000022B6', + "oror;": '\U00002A56', + "orslope;": '\U00002A57', + "orv;": '\U00002A5B', + "oscr;": '\U00002134', + "oslash;": '\U000000F8', + "osol;": '\U00002298', + "otilde;": '\U000000F5', + "otimes;": '\U00002297', + "otimesas;": '\U00002A36', + "ouml;": '\U000000F6', + "ovbar;": '\U0000233D', + "par;": '\U00002225', + "para;": '\U000000B6', + "parallel;": '\U00002225', + "parsim;": '\U00002AF3', + "parsl;": '\U00002AFD', + "part;": '\U00002202', + "pcy;": '\U0000043F', + "percnt;": '\U00000025', + "period;": '\U0000002E', + "permil;": '\U00002030', + "perp;": '\U000022A5', + "pertenk;": '\U00002031', + "pfr;": '\U0001D52D', + "phi;": '\U000003C6', + "phiv;": '\U000003D5', + "phmmat;": '\U00002133', + "phone;": '\U0000260E', + "pi;": '\U000003C0', + "pitchfork;": '\U000022D4', + "piv;": '\U000003D6', + "planck;": '\U0000210F', + "planckh;": '\U0000210E', + "plankv;": '\U0000210F', + "plus;": '\U0000002B', + "plusacir;": '\U00002A23', + "plusb;": '\U0000229E', + "pluscir;": '\U00002A22', + "plusdo;": '\U00002214', + "plusdu;": '\U00002A25', + "pluse;": '\U00002A72', + "plusmn;": '\U000000B1', + "plussim;": '\U00002A26', + "plustwo;": '\U00002A27', + "pm;": '\U000000B1', + "pointint;": '\U00002A15', + "popf;": '\U0001D561', + "pound;": '\U000000A3', + "pr;": '\U0000227A', + "prE;": '\U00002AB3', + "prap;": '\U00002AB7', + "prcue;": '\U0000227C', + "pre;": '\U00002AAF', + "prec;": '\U0000227A', + "precapprox;": '\U00002AB7', + "preccurlyeq;": '\U0000227C', + "preceq;": '\U00002AAF', + "precnapprox;": '\U00002AB9', + "precneqq;": '\U00002AB5', + "precnsim;": '\U000022E8', + "precsim;": '\U0000227E', + "prime;": '\U00002032', + "primes;": '\U00002119', + "prnE;": '\U00002AB5', + "prnap;": '\U00002AB9', + "prnsim;": '\U000022E8', + "prod;": '\U0000220F', + "profalar;": '\U0000232E', + "profline;": '\U00002312', + "profsurf;": '\U00002313', + "prop;": '\U0000221D', + "propto;": '\U0000221D', + "prsim;": '\U0000227E', + "prurel;": '\U000022B0', + "pscr;": '\U0001D4C5', + "psi;": '\U000003C8', + "puncsp;": '\U00002008', + "qfr;": '\U0001D52E', + "qint;": '\U00002A0C', + "qopf;": '\U0001D562', + "qprime;": '\U00002057', + "qscr;": '\U0001D4C6', + "quaternions;": '\U0000210D', + "quatint;": '\U00002A16', + "quest;": '\U0000003F', + "questeq;": '\U0000225F', + "quot;": '\U00000022', + "rAarr;": '\U000021DB', + "rArr;": '\U000021D2', + "rAtail;": '\U0000291C', + "rBarr;": '\U0000290F', + "rHar;": '\U00002964', + "racute;": '\U00000155', + "radic;": '\U0000221A', + "raemptyv;": '\U000029B3', + "rang;": '\U000027E9', + "rangd;": '\U00002992', + "range;": '\U000029A5', + "rangle;": '\U000027E9', + "raquo;": '\U000000BB', + "rarr;": '\U00002192', + "rarrap;": '\U00002975', + "rarrb;": '\U000021E5', + "rarrbfs;": '\U00002920', + "rarrc;": '\U00002933', + "rarrfs;": '\U0000291E', + "rarrhk;": '\U000021AA', + "rarrlp;": '\U000021AC', + "rarrpl;": '\U00002945', + "rarrsim;": '\U00002974', + "rarrtl;": '\U000021A3', + "rarrw;": '\U0000219D', + "ratail;": '\U0000291A', + "ratio;": '\U00002236', + "rationals;": '\U0000211A', + "rbarr;": '\U0000290D', + "rbbrk;": '\U00002773', + "rbrace;": '\U0000007D', + "rbrack;": '\U0000005D', + "rbrke;": '\U0000298C', + "rbrksld;": '\U0000298E', + "rbrkslu;": '\U00002990', + "rcaron;": '\U00000159', + "rcedil;": '\U00000157', + "rceil;": '\U00002309', + "rcub;": '\U0000007D', + "rcy;": '\U00000440', + "rdca;": '\U00002937', + "rdldhar;": '\U00002969', + "rdquo;": '\U0000201D', + "rdquor;": '\U0000201D', + "rdsh;": '\U000021B3', + "real;": '\U0000211C', + "realine;": '\U0000211B', + "realpart;": '\U0000211C', + "reals;": '\U0000211D', + "rect;": '\U000025AD', + "reg;": '\U000000AE', + "rfisht;": '\U0000297D', + "rfloor;": '\U0000230B', + "rfr;": '\U0001D52F', + "rhard;": '\U000021C1', + "rharu;": '\U000021C0', + "rharul;": '\U0000296C', + "rho;": '\U000003C1', + "rhov;": '\U000003F1', + "rightarrow;": '\U00002192', + "rightarrowtail;": '\U000021A3', + "rightharpoondown;": '\U000021C1', + "rightharpoonup;": '\U000021C0', + "rightleftarrows;": '\U000021C4', + "rightleftharpoons;": '\U000021CC', + "rightrightarrows;": '\U000021C9', + "rightsquigarrow;": '\U0000219D', + "rightthreetimes;": '\U000022CC', + "ring;": '\U000002DA', + "risingdotseq;": '\U00002253', + "rlarr;": '\U000021C4', + "rlhar;": '\U000021CC', + "rlm;": '\U0000200F', + "rmoust;": '\U000023B1', + "rmoustache;": '\U000023B1', + "rnmid;": '\U00002AEE', + "roang;": '\U000027ED', + "roarr;": '\U000021FE', + "robrk;": '\U000027E7', + "ropar;": '\U00002986', + "ropf;": '\U0001D563', + "roplus;": '\U00002A2E', + "rotimes;": '\U00002A35', + "rpar;": '\U00000029', + "rpargt;": '\U00002994', + "rppolint;": '\U00002A12', + "rrarr;": '\U000021C9', + "rsaquo;": '\U0000203A', + "rscr;": '\U0001D4C7', + "rsh;": '\U000021B1', + "rsqb;": '\U0000005D', + "rsquo;": '\U00002019', + "rsquor;": '\U00002019', + "rthree;": '\U000022CC', + "rtimes;": '\U000022CA', + "rtri;": '\U000025B9', + "rtrie;": '\U000022B5', + "rtrif;": '\U000025B8', + "rtriltri;": '\U000029CE', + "ruluhar;": '\U00002968', + "rx;": '\U0000211E', + "sacute;": '\U0000015B', + "sbquo;": '\U0000201A', + "sc;": '\U0000227B', + "scE;": '\U00002AB4', + "scap;": '\U00002AB8', + "scaron;": '\U00000161', + "sccue;": '\U0000227D', + "sce;": '\U00002AB0', + "scedil;": '\U0000015F', + "scirc;": '\U0000015D', + "scnE;": '\U00002AB6', + "scnap;": '\U00002ABA', + "scnsim;": '\U000022E9', + "scpolint;": '\U00002A13', + "scsim;": '\U0000227F', + "scy;": '\U00000441', + "sdot;": '\U000022C5', + "sdotb;": '\U000022A1', + "sdote;": '\U00002A66', + "seArr;": '\U000021D8', + "searhk;": '\U00002925', + "searr;": '\U00002198', + "searrow;": '\U00002198', + "sect;": '\U000000A7', + "semi;": '\U0000003B', + "seswar;": '\U00002929', + "setminus;": '\U00002216', + "setmn;": '\U00002216', + "sext;": '\U00002736', + "sfr;": '\U0001D530', + "sfrown;": '\U00002322', + "sharp;": '\U0000266F', + "shchcy;": '\U00000449', + "shcy;": '\U00000448', + "shortmid;": '\U00002223', + "shortparallel;": '\U00002225', + "shy;": '\U000000AD', + "sigma;": '\U000003C3', + "sigmaf;": '\U000003C2', + "sigmav;": '\U000003C2', + "sim;": '\U0000223C', + "simdot;": '\U00002A6A', + "sime;": '\U00002243', + "simeq;": '\U00002243', + "simg;": '\U00002A9E', + "simgE;": '\U00002AA0', + "siml;": '\U00002A9D', + "simlE;": '\U00002A9F', + "simne;": '\U00002246', + "simplus;": '\U00002A24', + "simrarr;": '\U00002972', + "slarr;": '\U00002190', + "smallsetminus;": '\U00002216', + "smashp;": '\U00002A33', + "smeparsl;": '\U000029E4', + "smid;": '\U00002223', + "smile;": '\U00002323', + "smt;": '\U00002AAA', + "smte;": '\U00002AAC', + "softcy;": '\U0000044C', + "sol;": '\U0000002F', + "solb;": '\U000029C4', + "solbar;": '\U0000233F', + "sopf;": '\U0001D564', + "spades;": '\U00002660', + "spadesuit;": '\U00002660', + "spar;": '\U00002225', + "sqcap;": '\U00002293', + "sqcup;": '\U00002294', + "sqsub;": '\U0000228F', + "sqsube;": '\U00002291', + "sqsubset;": '\U0000228F', + "sqsubseteq;": '\U00002291', + "sqsup;": '\U00002290', + "sqsupe;": '\U00002292', + "sqsupset;": '\U00002290', + "sqsupseteq;": '\U00002292', + "squ;": '\U000025A1', + "square;": '\U000025A1', + "squarf;": '\U000025AA', + "squf;": '\U000025AA', + "srarr;": '\U00002192', + "sscr;": '\U0001D4C8', + "ssetmn;": '\U00002216', + "ssmile;": '\U00002323', + "sstarf;": '\U000022C6', + "star;": '\U00002606', + "starf;": '\U00002605', + "straightepsilon;": '\U000003F5', + "straightphi;": '\U000003D5', + "strns;": '\U000000AF', + "sub;": '\U00002282', + "subE;": '\U00002AC5', + "subdot;": '\U00002ABD', + "sube;": '\U00002286', + "subedot;": '\U00002AC3', + "submult;": '\U00002AC1', + "subnE;": '\U00002ACB', + "subne;": '\U0000228A', + "subplus;": '\U00002ABF', + "subrarr;": '\U00002979', + "subset;": '\U00002282', + "subseteq;": '\U00002286', + "subseteqq;": '\U00002AC5', + "subsetneq;": '\U0000228A', + "subsetneqq;": '\U00002ACB', + "subsim;": '\U00002AC7', + "subsub;": '\U00002AD5', + "subsup;": '\U00002AD3', + "succ;": '\U0000227B', + "succapprox;": '\U00002AB8', + "succcurlyeq;": '\U0000227D', + "succeq;": '\U00002AB0', + "succnapprox;": '\U00002ABA', + "succneqq;": '\U00002AB6', + "succnsim;": '\U000022E9', + "succsim;": '\U0000227F', + "sum;": '\U00002211', + "sung;": '\U0000266A', + "sup;": '\U00002283', + "sup1;": '\U000000B9', + "sup2;": '\U000000B2', + "sup3;": '\U000000B3', + "supE;": '\U00002AC6', + "supdot;": '\U00002ABE', + "supdsub;": '\U00002AD8', + "supe;": '\U00002287', + "supedot;": '\U00002AC4', + "suphsol;": '\U000027C9', + "suphsub;": '\U00002AD7', + "suplarr;": '\U0000297B', + "supmult;": '\U00002AC2', + "supnE;": '\U00002ACC', + "supne;": '\U0000228B', + "supplus;": '\U00002AC0', + "supset;": '\U00002283', + "supseteq;": '\U00002287', + "supseteqq;": '\U00002AC6', + "supsetneq;": '\U0000228B', + "supsetneqq;": '\U00002ACC', + "supsim;": '\U00002AC8', + "supsub;": '\U00002AD4', + "supsup;": '\U00002AD6', + "swArr;": '\U000021D9', + "swarhk;": '\U00002926', + "swarr;": '\U00002199', + "swarrow;": '\U00002199', + "swnwar;": '\U0000292A', + "szlig;": '\U000000DF', + "target;": '\U00002316', + "tau;": '\U000003C4', + "tbrk;": '\U000023B4', + "tcaron;": '\U00000165', + "tcedil;": '\U00000163', + "tcy;": '\U00000442', + "tdot;": '\U000020DB', + "telrec;": '\U00002315', + "tfr;": '\U0001D531', + "there4;": '\U00002234', + "therefore;": '\U00002234', + "theta;": '\U000003B8', + "thetasym;": '\U000003D1', + "thetav;": '\U000003D1', + "thickapprox;": '\U00002248', + "thicksim;": '\U0000223C', + "thinsp;": '\U00002009', + "thkap;": '\U00002248', + "thksim;": '\U0000223C', + "thorn;": '\U000000FE', + "tilde;": '\U000002DC', + "times;": '\U000000D7', + "timesb;": '\U000022A0', + "timesbar;": '\U00002A31', + "timesd;": '\U00002A30', + "tint;": '\U0000222D', + "toea;": '\U00002928', + "top;": '\U000022A4', + "topbot;": '\U00002336', + "topcir;": '\U00002AF1', + "topf;": '\U0001D565', + "topfork;": '\U00002ADA', + "tosa;": '\U00002929', + "tprime;": '\U00002034', + "trade;": '\U00002122', + "triangle;": '\U000025B5', + "triangledown;": '\U000025BF', + "triangleleft;": '\U000025C3', + "trianglelefteq;": '\U000022B4', + "triangleq;": '\U0000225C', + "triangleright;": '\U000025B9', + "trianglerighteq;": '\U000022B5', + "tridot;": '\U000025EC', + "trie;": '\U0000225C', + "triminus;": '\U00002A3A', + "triplus;": '\U00002A39', + "trisb;": '\U000029CD', + "tritime;": '\U00002A3B', + "trpezium;": '\U000023E2', + "tscr;": '\U0001D4C9', + "tscy;": '\U00000446', + "tshcy;": '\U0000045B', + "tstrok;": '\U00000167', + "twixt;": '\U0000226C', + "twoheadleftarrow;": '\U0000219E', + "twoheadrightarrow;": '\U000021A0', + "uArr;": '\U000021D1', + "uHar;": '\U00002963', + "uacute;": '\U000000FA', + "uarr;": '\U00002191', + "ubrcy;": '\U0000045E', + "ubreve;": '\U0000016D', + "ucirc;": '\U000000FB', + "ucy;": '\U00000443', + "udarr;": '\U000021C5', + "udblac;": '\U00000171', + "udhar;": '\U0000296E', + "ufisht;": '\U0000297E', + "ufr;": '\U0001D532', + "ugrave;": '\U000000F9', + "uharl;": '\U000021BF', + "uharr;": '\U000021BE', + "uhblk;": '\U00002580', + "ulcorn;": '\U0000231C', + "ulcorner;": '\U0000231C', + "ulcrop;": '\U0000230F', + "ultri;": '\U000025F8', + "umacr;": '\U0000016B', + "uml;": '\U000000A8', + "uogon;": '\U00000173', + "uopf;": '\U0001D566', + "uparrow;": '\U00002191', + "updownarrow;": '\U00002195', + "upharpoonleft;": '\U000021BF', + "upharpoonright;": '\U000021BE', + "uplus;": '\U0000228E', + "upsi;": '\U000003C5', + "upsih;": '\U000003D2', + "upsilon;": '\U000003C5', + "upuparrows;": '\U000021C8', + "urcorn;": '\U0000231D', + "urcorner;": '\U0000231D', + "urcrop;": '\U0000230E', + "uring;": '\U0000016F', + "urtri;": '\U000025F9', + "uscr;": '\U0001D4CA', + "utdot;": '\U000022F0', + "utilde;": '\U00000169', + "utri;": '\U000025B5', + "utrif;": '\U000025B4', + "uuarr;": '\U000021C8', + "uuml;": '\U000000FC', + "uwangle;": '\U000029A7', + "vArr;": '\U000021D5', + "vBar;": '\U00002AE8', + "vBarv;": '\U00002AE9', + "vDash;": '\U000022A8', + "vangrt;": '\U0000299C', + "varepsilon;": '\U000003F5', + "varkappa;": '\U000003F0', + "varnothing;": '\U00002205', + "varphi;": '\U000003D5', + "varpi;": '\U000003D6', + "varpropto;": '\U0000221D', + "varr;": '\U00002195', + "varrho;": '\U000003F1', + "varsigma;": '\U000003C2', + "vartheta;": '\U000003D1', + "vartriangleleft;": '\U000022B2', + "vartriangleright;": '\U000022B3', + "vcy;": '\U00000432', + "vdash;": '\U000022A2', + "vee;": '\U00002228', + "veebar;": '\U000022BB', + "veeeq;": '\U0000225A', + "vellip;": '\U000022EE', + "verbar;": '\U0000007C', + "vert;": '\U0000007C', + "vfr;": '\U0001D533', + "vltri;": '\U000022B2', + "vopf;": '\U0001D567', + "vprop;": '\U0000221D', + "vrtri;": '\U000022B3', + "vscr;": '\U0001D4CB', + "vzigzag;": '\U0000299A', + "wcirc;": '\U00000175', + "wedbar;": '\U00002A5F', + "wedge;": '\U00002227', + "wedgeq;": '\U00002259', + "weierp;": '\U00002118', + "wfr;": '\U0001D534', + "wopf;": '\U0001D568', + "wp;": '\U00002118', + "wr;": '\U00002240', + "wreath;": '\U00002240', + "wscr;": '\U0001D4CC', + "xcap;": '\U000022C2', + "xcirc;": '\U000025EF', + "xcup;": '\U000022C3', + "xdtri;": '\U000025BD', + "xfr;": '\U0001D535', + "xhArr;": '\U000027FA', + "xharr;": '\U000027F7', + "xi;": '\U000003BE', + "xlArr;": '\U000027F8', + "xlarr;": '\U000027F5', + "xmap;": '\U000027FC', + "xnis;": '\U000022FB', + "xodot;": '\U00002A00', + "xopf;": '\U0001D569', + "xoplus;": '\U00002A01', + "xotime;": '\U00002A02', + "xrArr;": '\U000027F9', + "xrarr;": '\U000027F6', + "xscr;": '\U0001D4CD', + "xsqcup;": '\U00002A06', + "xuplus;": '\U00002A04', + "xutri;": '\U000025B3', + "xvee;": '\U000022C1', + "xwedge;": '\U000022C0', + "yacute;": '\U000000FD', + "yacy;": '\U0000044F', + "ycirc;": '\U00000177', + "ycy;": '\U0000044B', + "yen;": '\U000000A5', + "yfr;": '\U0001D536', + "yicy;": '\U00000457', + "yopf;": '\U0001D56A', + "yscr;": '\U0001D4CE', + "yucy;": '\U0000044E', + "yuml;": '\U000000FF', + "zacute;": '\U0000017A', + "zcaron;": '\U0000017E', + "zcy;": '\U00000437', + "zdot;": '\U0000017C', + "zeetrf;": '\U00002128', + "zeta;": '\U000003B6', + "zfr;": '\U0001D537', + "zhcy;": '\U00000436', + "zigrarr;": '\U000021DD', + "zopf;": '\U0001D56B', + "zscr;": '\U0001D4CF', + "zwj;": '\U0000200D', + "zwnj;": '\U0000200C', + "AElig": '\U000000C6', + "AMP": '\U00000026', + "Aacute": '\U000000C1', + "Acirc": '\U000000C2', + "Agrave": '\U000000C0', + "Aring": '\U000000C5', + "Atilde": '\U000000C3', + "Auml": '\U000000C4', + "COPY": '\U000000A9', + "Ccedil": '\U000000C7', + "ETH": '\U000000D0', + "Eacute": '\U000000C9', + "Ecirc": '\U000000CA', + "Egrave": '\U000000C8', + "Euml": '\U000000CB', + "GT": '\U0000003E', + "Iacute": '\U000000CD', + "Icirc": '\U000000CE', + "Igrave": '\U000000CC', + "Iuml": '\U000000CF', + "LT": '\U0000003C', + "Ntilde": '\U000000D1', + "Oacute": '\U000000D3', + "Ocirc": '\U000000D4', + "Ograve": '\U000000D2', + "Oslash": '\U000000D8', + "Otilde": '\U000000D5', + "Ouml": '\U000000D6', + "QUOT": '\U00000022', + "REG": '\U000000AE', + "THORN": '\U000000DE', + "Uacute": '\U000000DA', + "Ucirc": '\U000000DB', + "Ugrave": '\U000000D9', + "Uuml": '\U000000DC', + "Yacute": '\U000000DD', + "aacute": '\U000000E1', + "acirc": '\U000000E2', + "acute": '\U000000B4', + "aelig": '\U000000E6', + "agrave": '\U000000E0', + "amp": '\U00000026', + "aring": '\U000000E5', + "atilde": '\U000000E3', + "auml": '\U000000E4', + "brvbar": '\U000000A6', + "ccedil": '\U000000E7', + "cedil": '\U000000B8', + "cent": '\U000000A2', + "copy": '\U000000A9', + "curren": '\U000000A4', + "deg": '\U000000B0', + "divide": '\U000000F7', + "eacute": '\U000000E9', + "ecirc": '\U000000EA', + "egrave": '\U000000E8', + "eth": '\U000000F0', + "euml": '\U000000EB', + "frac12": '\U000000BD', + "frac14": '\U000000BC', + "frac34": '\U000000BE', + "gt": '\U0000003E', + "iacute": '\U000000ED', + "icirc": '\U000000EE', + "iexcl": '\U000000A1', + "igrave": '\U000000EC', + "iquest": '\U000000BF', + "iuml": '\U000000EF', + "laquo": '\U000000AB', + "lt": '\U0000003C', + "macr": '\U000000AF', + "micro": '\U000000B5', + "middot": '\U000000B7', + "nbsp": '\U000000A0', + "not": '\U000000AC', + "ntilde": '\U000000F1', + "oacute": '\U000000F3', + "ocirc": '\U000000F4', + "ograve": '\U000000F2', + "ordf": '\U000000AA', + "ordm": '\U000000BA', + "oslash": '\U000000F8', + "otilde": '\U000000F5', + "ouml": '\U000000F6', + "para": '\U000000B6', + "plusmn": '\U000000B1', + "pound": '\U000000A3', + "quot": '\U00000022', + "raquo": '\U000000BB', + "reg": '\U000000AE', + "sect": '\U000000A7', + "shy": '\U000000AD', + "sup1": '\U000000B9', + "sup2": '\U000000B2', + "sup3": '\U000000B3', + "szlig": '\U000000DF', + "thorn": '\U000000FE', + "times": '\U000000D7', + "uacute": '\U000000FA', + "ucirc": '\U000000FB', + "ugrave": '\U000000F9', + "uml": '\U000000A8', + "uuml": '\U000000FC', + "yacute": '\U000000FD', + "yen": '\U000000A5', + "yuml": '\U000000FF', } // HTML entities that are two unicode codepoints. diff --git a/vendor/gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht/dht.go b/vendor/gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht/dht.go index 4c1569251d..3712b885cc 100644 --- a/vendor/gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht/dht.go +++ b/vendor/gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht/dht.go @@ -66,6 +66,7 @@ type IpfsDHT struct { // OpenBazaar: this chan is added which is closed when the bootstrap finished // this is used to flag ob-go that the DHT is ready for use. BootstrapChan chan struct{} + bootstrapOnce sync.Once } // Assert that IPFS assumptions about interfaces aren't broken. These aren't a diff --git a/vendor/gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht/dht_bootstrap.go b/vendor/gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht/dht_bootstrap.go index 8047edda92..180435ae0d 100644 --- a/vendor/gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht/dht_bootstrap.go +++ b/vendor/gx/ipfs/QmSY3nkMNLzh9GdbFKK5tT7YMfLpf52iUZ8ZRkr29MJaa5/go-libp2p-kad-dht/dht_bootstrap.go @@ -4,7 +4,6 @@ import ( "context" "crypto/rand" "fmt" - "sync" "time" u "gx/ipfs/QmNohiVssaPw3KVLZik59DBVGTSm2dGvYT9eoXt5DQ36Yz/go-ipfs-util" @@ -137,14 +136,10 @@ func (dht *IpfsDHT) randomWalk(ctx context.Context) error { } } -// OpenBazaar: this once is used to guard the closing of the bootstrap chan so that -// it is only closed after the first bootstrap round completes. -var bootstrapOnce sync.Once - // runBootstrap builds up list of peers by requesting random peer IDs func (dht *IpfsDHT) runBootstrap(ctx context.Context, cfg BootstrapConfig) error { // OpenBazaar: close bootstrap chan - defer bootstrapOnce.Do(func() { + defer dht.bootstrapOnce.Do(func() { close(dht.BootstrapChan) }) @@ -180,6 +175,5 @@ func (dht *IpfsDHT) runBootstrap(ctx context.Context, cfg BootstrapConfig) error return err }) - return err } diff --git a/vendor/gx/ipfs/QmU44KWVkSHno7sNDTeUcL4FBgxgoidkFuTUyTXWJPXXFJ/quic-go/packet_handler_map.go b/vendor/gx/ipfs/QmU44KWVkSHno7sNDTeUcL4FBgxgoidkFuTUyTXWJPXXFJ/quic-go/packet_handler_map.go index 3786d723b4..0a07f94314 100644 --- a/vendor/gx/ipfs/QmU44KWVkSHno7sNDTeUcL4FBgxgoidkFuTUyTXWJPXXFJ/quic-go/packet_handler_map.go +++ b/vendor/gx/ipfs/QmU44KWVkSHno7sNDTeUcL4FBgxgoidkFuTUyTXWJPXXFJ/quic-go/packet_handler_map.go @@ -39,7 +39,7 @@ func newPacketHandlerMap(conn net.PacketConn, connIDLen int, logger utils.Logger connIDLen: connIDLen, handlers: make(map[string]packetHandler), deleteClosedSessionsAfter: protocol.ClosedSessionDeleteTimeout, - logger: logger, + logger: logger, } go m.listen() return m diff --git a/vendor/gx/ipfs/QmVcxhXDbXjNoAdmYBWbY1eU67kQ8eZUHjG4mAYZUtZZu3/go-text/internal/language/lookup.go b/vendor/gx/ipfs/QmVcxhXDbXjNoAdmYBWbY1eU67kQ8eZUHjG4mAYZUtZZu3/go-text/internal/language/lookup.go index 16b70782f6..de39062015 100644 --- a/vendor/gx/ipfs/QmVcxhXDbXjNoAdmYBWbY1eU67kQ8eZUHjG4mAYZUtZZu3/go-text/internal/language/lookup.go +++ b/vendor/gx/ipfs/QmVcxhXDbXjNoAdmYBWbY1eU67kQ8eZUHjG4mAYZUtZZu3/go-text/internal/language/lookup.go @@ -391,7 +391,7 @@ var ( {'z', 'h', '-', 'm', 'i', 'n'}: -6, // zh-min // CLDR-specific tag. - {'r', 'o', 'o', 't'}: 0, // root + {'r', 'o', 'o', 't'}: 0, // root {'e', 'n', '-', 'u', 's', '-', 'p', 'o', 's', 'i', 'x'}: -7, // en_US_POSIX" } diff --git a/vendor/gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer/peer.go b/vendor/gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer/peer.go index 46d494925a..ff094bfefc 100644 --- a/vendor/gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer/peer.go +++ b/vendor/gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer/peer.go @@ -84,7 +84,7 @@ func (id ID) MatchesPublicKey(pk ic.PubKey) bool { // ExtractPublicKey attempts to extract the public key from an ID // // This method returns ErrNoPublicKey if the peer ID looks valid but it can't extract -// the public key. +// the public key.PATH func (id ID) ExtractPublicKey() (ic.PubKey, error) { decoded, err := mh.Decode([]byte(id)) if err != nil { diff --git a/vendor/gx/ipfs/QmcSPuzpSbVLU6UHU4e5PwZpm4fHbCn5SbNR5ZNL6Mj63G/go-bitswap/providerquerymanager/providerquerymanager.go b/vendor/gx/ipfs/QmcSPuzpSbVLU6UHU4e5PwZpm4fHbCn5SbNR5ZNL6Mj63G/go-bitswap/providerquerymanager/providerquerymanager.go index 53a445244e..ae2c80e6d7 100644 --- a/vendor/gx/ipfs/QmcSPuzpSbVLU6UHU4e5PwZpm4fHbCn5SbNR5ZNL6Mj63G/go-bitswap/providerquerymanager/providerquerymanager.go +++ b/vendor/gx/ipfs/QmcSPuzpSbVLU6UHU4e5PwZpm4fHbCn5SbNR5ZNL6Mj63G/go-bitswap/providerquerymanager/providerquerymanager.go @@ -120,7 +120,7 @@ func (pqm *ProviderQueryManager) FindProvidersAsync(sessionCtx context.Context, select { case pqm.providerQueryMessages <- &newProvideQueryMessage{ - k: k, + k: k, inProgressRequestChan: inProgressRequestChan, }: case <-pqm.ctx.Done(): diff --git a/wallet/builder.go b/wallet/builder.go index 75c61d418e..3ed416cf67 100644 --- a/wallet/builder.go +++ b/wallet/builder.go @@ -10,28 +10,24 @@ import ( "strings" "time" - "github.com/phoreproject/multiwallet/phore" - "github.com/phoreproject/multiwallet/util" - - //eth "github.com/OpenBazaar/go-ethwallet/wallet" + "github.com/OpenBazaar/spvwallet" + "github.com/OpenBazaar/wallet-interface" + "github.com/btcsuite/btcd/chaincfg" + eth "github.com/phoreproject/go-ethwallet/wallet" "github.com/phoreproject/multiwallet" "github.com/phoreproject/multiwallet/bitcoin" "github.com/phoreproject/multiwallet/bitcoincash" "github.com/phoreproject/multiwallet/cache" mwConfig "github.com/phoreproject/multiwallet/config" "github.com/phoreproject/multiwallet/litecoin" + "github.com/phoreproject/multiwallet/phore" + "github.com/phoreproject/multiwallet/util" "github.com/phoreproject/multiwallet/zcash" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/repo/db" + "github.com/phoreproject/pm-go/schema" - bchspv "github.com/cpacia/BitcoinCash-Wallet" "github.com/op/go-logging" - - "github.com/btcsuite/btcd/chaincfg" - "github.com/phoreproject/openbazaar-go/repo" - "github.com/phoreproject/openbazaar-go/repo/db" - "github.com/phoreproject/openbazaar-go/schema" - - "github.com/OpenBazaar/spvwallet" - "github.com/OpenBazaar/wallet-interface" "golang.org/x/net/proxy" ) @@ -103,7 +99,7 @@ func NewMultiWallet(cfg *WalletConfig) (multiwallet.MultiWallet, error) { if cfg.ConfigFile.LTC != nil && cfg.ConfigFile.LTC.Type == "API" { enableAPIWallet[util.ExtendCoinType(wallet.Litecoin)] = cfg.ConfigFile.LTC } - enableAPIWallet[util.ExtendCoinType(wallet.Ethereum)] = nil + enableAPIWallet[util.ExtendCoinType(wallet.Ethereum)] = cfg.ConfigFile.ETH var newMultiwallet = make(multiwallet.MultiWallet) for coin, coinConfig := range enableAPIWallet { @@ -203,13 +199,17 @@ func createAPIWallet(coin util.ExtCoinType, coinConfigOverrides *schema.CoinConf return InvalidCoinType, nil, err } return actualCoin, w, nil - //case wallet.Ethereum: - // actualCoin = wallet.Ethereum - // w, err := eth.NewEthereumWallet(*coinConfig, cfg.Mnemonic, cfg.Proxy) - // if err != nil { - // return InvalidCoinType, nil, err - // } - // return actualCoin, w, nil + case wallet.Ethereum: + if testnet { + actualCoin = wallet.TestnetEthereum + } else { + actualCoin = wallet.Ethereum + } + w, err := eth.NewEthereumWallet(*coinConfig, cfg.Params, cfg.Mnemonic, cfg.Proxy) + if err != nil { + return InvalidCoinType, nil, err + } + return actualCoin, w, nil } return InvalidCoinType, nil, fmt.Errorf("unable to create wallet for unknown coin %s", coin.String()) } @@ -247,6 +247,7 @@ func createSPVWallet(coin util.ExtCoinType, coinConfigOverrides *schema.CoinConf Mnemonic: cfg.Mnemonic, Params: cfg.Params, MaxFee: coinConfigOverrides.MaxFee, + SuperLowFee: coinConfigOverrides.SuperLowFeeDefault, LowFee: coinConfigOverrides.LowFeeDefault, MediumFee: coinConfigOverrides.MediumFeeDefault, HighFee: coinConfigOverrides.HighFeeDefault, @@ -284,49 +285,6 @@ func createSPVWallet(coin util.ExtCoinType, coinConfigOverrides *schema.CoinConf actualCoin = util.ExtendCoinType(wallet.Bitcoin) } return actualCoin, newSPVWallet, nil - case util.ExtendCoinType(wallet.BitcoinCash): - defaultConfig := defaultConfigSet.BCH - preparedConfig := &bchspv.Config{ - Mnemonic: cfg.Mnemonic, - Params: cfg.Params, - MaxFee: coinConfigOverrides.MaxFee, - LowFee: coinConfigOverrides.LowFeeDefault, - MediumFee: coinConfigOverrides.MediumFeeDefault, - HighFee: coinConfigOverrides.HighFeeDefault, - FeeAPI: *feeAPI, - RepoPath: walletRepoPath, - CreationDate: cfg.WalletCreationDate, - DB: CreateWalletDB(cfg.DB, coin), - UserAgent: "OpenBazaar", - TrustedPeer: trustedPeer, - Proxy: cfg.Proxy, - Logger: cfg.Logger, - DisableExchangeRates: cfg.DisableExchangeRates, - } - if preparedConfig.HighFee == 0 { - preparedConfig.HighFee = defaultConfig.HighFeeDefault - } - if preparedConfig.MediumFee == 0 { - preparedConfig.MediumFee = defaultConfig.MediumFeeDefault - } - if preparedConfig.LowFee == 0 { - preparedConfig.LowFee = defaultConfig.LowFeeDefault - } - if preparedConfig.MaxFee == 0 { - preparedConfig.MaxFee = defaultConfig.MaxFee - } - - newSPVWallet, err := bchspv.NewSPVWallet(preparedConfig) - if err != nil { - return InvalidCoinType, nil, err - } - - if notMainnet { - actualCoin = util.ExtendCoinType(wallet.TestnetBitcoinCash) - } else { - actualCoin = util.ExtendCoinType(wallet.BitcoinCash) - } - return actualCoin, newSPVWallet, nil } return InvalidCoinType, nil, fmt.Errorf("unable to create wallet for unknown coin %s", coin.String()) } @@ -387,15 +345,16 @@ func prepareAPICoinConfig(coin util.ExtCoinType, override *schema.CoinConfig, wa } var preparedConfig = &mwConfig.CoinConfig{ - ClientAPIs: overrideWalletEndpoints, - CoinType: coin, - DB: CreateWalletDB(walletConfig.DB, coin), - FeeAPI: override.FeeAPI, - HighFee: override.HighFeeDefault, - LowFee: override.LowFeeDefault, - MaxFee: override.MaxFee, - MediumFee: override.MediumFeeDefault, - Options: override.WalletOptions, + ClientAPIs: overrideWalletEndpoints, + CoinType: coin, + DB: CreateWalletDB(walletConfig.DB, coin), + FeeAPI: override.FeeAPI, + HighFee: override.HighFeeDefault, + SuperLowFee: override.SuperLowFeeDefault, + LowFee: override.LowFeeDefault, + MaxFee: override.MaxFee, + MediumFee: override.MediumFeeDefault, + Options: override.WalletOptions, } if preparedConfig.HighFee == 0 { diff --git a/wallet/listeners/transaction_listener.go b/wallet/listeners/transaction_listener.go index ab0e24054f..1bdb57faca 100644 --- a/wallet/listeners/transaction_listener.go +++ b/wallet/listeners/transaction_listener.go @@ -1,6 +1,7 @@ package bitcoin import ( + "math/big" "sync" "time" @@ -9,10 +10,13 @@ import ( "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" "github.com/op/go-logging" + "github.com/phoreproject/multiwallet" - "github.com/phoreproject/openbazaar-go/core" - "github.com/phoreproject/openbazaar-go/pb" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/core" + "github.com/phoreproject/pm-go/ipfs" + "github.com/phoreproject/pm-go/pb" + "github.com/phoreproject/pm-go/repo" + "github.com/phoreproject/pm-go/util" ) var log = logging.MustGetLogger("transaction-listener") @@ -51,6 +55,40 @@ func (l *TransactionListener) getOrderDetails(orderID string, address btc.Addres return contract, state, funded, records, err } +// cleanupOrderState - scan each order to ensure the state in the db matches the state of the contract stored +func (l *TransactionListener) cleanupOrderState(isSale bool, contract *pb.RicardianContract, state pb.OrderState) { + + orderId, err := calcOrderId(contract.BuyerOrder) + if err != nil { + return + } + log.Debugf("Cleaning up order state for: #%s\n", orderId) + + if contract.DisputeResolution != nil && state != pb.OrderState_DECIDED && state != pb.OrderState_RESOLVED { + log.Infof("Out of sync order. Found %s and should either DECIDED be %s\n", state, pb.OrderState_RESOLVED) + if isSale { + err = l.db.Sales().Put(orderId, *contract, pb.OrderState_RESOLVED, false) + } else { + err = l.db.Purchases().Put(orderId, *contract, pb.OrderState_RESOLVED, false) + } + if err != nil { + log.Errorf("Error saving new order state: %s", err) + } + } + + if contract.DisputeAcceptance != nil && state == pb.OrderState_DISPUTED { + log.Infof("Out of sync order. Found %s and should be %s\n", state, pb.OrderState_RESOLVED) + if isSale { + err = l.db.Sales().Put(orderId, *contract, pb.OrderState_RESOLVED, false) + } else { + err = l.db.Purchases().Put(orderId, *contract, pb.OrderState_RESOLVED, false) + } + if err != nil { + log.Errorf("Error saving new order state: %s", err) + } + } +} + func (l *TransactionListener) OnTransactionReceived(cb wallet.TransactionCallback) { l.Lock() defer l.Unlock() @@ -69,11 +107,13 @@ func (l *TransactionListener) OnTransactionReceived(cb wallet.TransactionCallbac //contract, state, funded, records, err := l.db.Sales().GetByPaymentAddress(output.Address) if err == nil && state != pb.OrderState_PROCESSING_ERROR { l.processSalePayment(cb.Txid, output, contract, state, funded, records) + l.cleanupOrderState(true, contract, state) continue } contract, state, funded, records, err = l.getOrderDetails(output.OrderID, output.Address, false) if err == nil { l.processPurchasePayment(cb.Txid, output, contract, state, funded, records) + l.cleanupOrderState(false, contract, state) continue } } @@ -99,29 +139,41 @@ func (l *TransactionListener) OnTransactionReceived(cb wallet.TransactionCallbac continue } - fundsReleased := true + var ( + fundsReleased = true + unseenTx = true + ) for i, r := range records { - if input.LinkedAddress.String() == r.Address { + if util.AreAddressesEqual(input.LinkedAddress.String(), r.Address) { records[i].Spent = true } - if records[i].Value > 0 && !records[i].Spent { + if records[i].Value.Cmp(big.NewInt(0)) > 0 && !records[i].Spent { fundsReleased = false } + if r.Txid == cb.Txid { + unseenTx = false + } } - - record := &wallet.TransactionRecord{ - Timestamp: time.Now(), - Txid: cb.Txid, - Index: input.OutpointIndex, - Value: -input.Value, - Address: input.LinkedAddress.String(), + val := new(big.Int).Mul(&input.Value, big.NewInt(-1)) + if unseenTx { + record := &wallet.TransactionRecord{ + Timestamp: time.Now(), + Txid: cb.Txid, + Index: input.OutpointIndex, + Value: *val, + Address: input.LinkedAddress.String(), + } + records = append(records, record) } - records = append(records, record) + records = removeDuplicateRecords(records) if isForSale { - l.db.Sales().UpdateFunding(orderId, funded, records) + err = l.db.Sales().UpdateFunding(orderId, funded, records) + if err != nil { + log.Errorf("update funding for sale (%s): %s", orderId, err) + } // This is a dispute payout. We should set the order state. - if state == pb.OrderState_DECIDED && len(records) > 0 && fundsReleased { - if contract.DisputeAcceptance == nil && contract != nil && contract.BuyerOrder != nil && contract.BuyerOrder.BuyerID != nil { + if len(records) > 0 && fundsReleased && contract != nil && contract.Dispute != nil { + if contract.DisputeAcceptance == nil && contract.BuyerOrder.BuyerID != nil { accept := new(pb.DisputeAcceptance) ts, _ := ptypes.TimestampProto(time.Now()) accept.Timestamp = ts @@ -130,24 +182,38 @@ func (l *TransactionListener) OnTransactionReceived(cb wallet.TransactionCallbac buyerHandle := contract.BuyerOrder.BuyerID.Handle n := repo.DisputeAcceptedNotification{ - repo.NewNotificationID(), - "disputeAccepted", - orderId, - repo.Thumbnail{contract.VendorListings[0].Item.Images[0].Tiny, contract.VendorListings[0].Item.Images[0].Small}, - accept.ClosedBy, - buyerHandle, - accept.ClosedBy, + ID: repo.NewNotificationID(), + Type: "disputeAccepted", + OrderId: orderId, + Thumbnail: repo.Thumbnail{Tiny: contract.VendorListings[0].Item.Images[0].Tiny, Small: contract.VendorListings[0].Item.Images[0].Small}, + OherPartyID: accept.ClosedBy, + OtherPartyHandle: buyerHandle, + Buyer: accept.ClosedBy, } l.broadcast <- n - l.db.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + err = l.db.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Errorf("persist dispute acceptance notification for order (%s): %s", orderId, err) + } + } + if state == pb.OrderState_DECIDED { + if err := l.db.Sales().Put(orderId, *contract, pb.OrderState_RESOLVED, false); err != nil { + log.Errorf("failed updating order (%s) to RESOLVED: %s", orderId, err.Error()) + } + } else { + if err := l.db.Sales().Put(orderId, *contract, state, !unseenTx); err != nil { + log.Errorf("failed updating order (%s) with DisputeAcceptance: %s", orderId, err.Error()) + } } - l.db.Sales().Put(orderId, *contract, pb.OrderState_RESOLVED, false) } } else { - l.db.Purchases().UpdateFunding(orderId, funded, records) - if state == pb.OrderState_DECIDED && len(records) > 0 && fundsReleased { - if contract.DisputeAcceptance == nil && contract != nil && len(contract.VendorListings) > 0 && contract.VendorListings[0].VendorID != nil { + err = l.db.Purchases().UpdateFunding(orderId, funded, records) + if err != nil { + log.Errorf("update funding for purchase (%s): %s", orderId, err) + } + if len(records) > 0 && fundsReleased && contract != nil && contract.Dispute != nil { + if contract.DisputeAcceptance == nil && len(contract.VendorListings) > 0 && contract.VendorListings[0].VendorID != nil { accept := new(pb.DisputeAcceptance) ts, _ := ptypes.TimestampProto(time.Now()) accept.Timestamp = ts @@ -160,153 +226,219 @@ func (l *TransactionListener) OnTransactionReceived(cb wallet.TransactionCallbac } n := repo.DisputeAcceptedNotification{ - repo.NewNotificationID(), - "disputeAccepted", - orderId, - repo.Thumbnail{contract.VendorListings[0].Item.Images[0].Tiny, contract.VendorListings[0].Item.Images[0].Small}, - accept.ClosedBy, - vendorHandle, - buyer, + ID: repo.NewNotificationID(), + Type: "disputeAccepted", + OrderId: orderId, + Thumbnail: repo.Thumbnail{Tiny: contract.VendorListings[0].Item.Images[0].Tiny, Small: contract.VendorListings[0].Item.Images[0].Small}, + OherPartyID: accept.ClosedBy, + OtherPartyHandle: vendorHandle, + Buyer: buyer, } l.broadcast <- n - l.db.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + err = l.db.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Errorf("persist dispute acceptance notification for order (%s): %s", orderId, err) + } + } + if state == pb.OrderState_DECIDED { + if err := l.db.Purchases().Put(orderId, *contract, pb.OrderState_RESOLVED, false); err != nil { + log.Errorf("failed updating order (%s) to RESOLVED: %s", orderId, err.Error()) + } + } else { + if err := l.db.Purchases().Put(orderId, *contract, state, !unseenTx); err != nil { + log.Errorf("failed updating order (%s) with DisputeAcceptance: %s", orderId, err.Error()) + } } - l.db.Purchases().Put(orderId, *contract, pb.OrderState_RESOLVED, false) } } } } func (l *TransactionListener) processSalePayment(txid string, output wallet.TransactionOutput, contract *pb.RicardianContract, state pb.OrderState, funded bool, records []*wallet.TransactionRecord) { - var funding = output.Value + var ( + funding = output.Value + unseenTx = true + ) for _, r := range records { - funding += r.Value - // If we have already seen this transaction for some reason, just return - if r.Txid == txid { - return + if r.Txid != txid { + funding = *new(big.Int).Add(&funding, &r.Value) + } else { + unseenTx = false } } orderId, err := calcOrderId(contract.BuyerOrder) if err != nil { return } - if !funded { - requestedAmount := int64(contract.BuyerOrder.Payment.Amount) - if funding >= requestedAmount { + order, err := repo.ToV5Order(contract.BuyerOrder, nil) + if err != nil { + log.Error(err) + return + } + + if !funded || (funded && state == pb.OrderState_AWAITING_PAYMENT) { + currencyValue, err := repo.NewCurrencyValueWithLookup(order.Payment.BigAmount, order.Payment.AmountCurrency.Code) + if err != nil { + log.Errorf("Failed parsing CurrencyValue for (%s, %s): %s", + order.Payment.BigAmount, + order.Payment.AmountCurrency.Code, + err.Error(), + ) + return + } + + if funding.Cmp(currencyValue.Amount) >= 0 { log.Debugf("Received payment for order %s", orderId) funded = true if state == pb.OrderState_AWAITING_PAYMENT && contract.VendorOrderConfirmation != nil { // Confirmed orders go to AWAITING_FULFILLMENT - l.db.Sales().Put(orderId, *contract, pb.OrderState_AWAITING_FULFILLMENT, false) + if err := l.db.Sales().Put(orderId, *contract, pb.OrderState_AWAITING_FULFILLMENT, false); err != nil { + log.Errorf("failed updating order (%s) to AWAITING_FULFILLMENT: %s", orderId, err.Error()) + } } else if state == pb.OrderState_AWAITING_PAYMENT && contract.VendorOrderConfirmation == nil { // Unconfirmed orders go into PENDING - l.db.Sales().Put(orderId, *contract, pb.OrderState_PENDING, false) + if err := l.db.Sales().Put(orderId, *contract, pb.OrderState_PENDING, false); err != nil { + log.Errorf("failed updating order (%s) to PENDING: %s", orderId, err.Error()) + } } l.adjustInventory(contract) n := repo.OrderNotification{ - BuyerHandle: contract.BuyerOrder.BuyerID.Handle, - BuyerID: contract.BuyerOrder.BuyerID.PeerID, - ID: repo.NewNotificationID(), - ListingType: contract.VendorListings[0].Metadata.ContractType.String(), - OrderId: orderId, - Price: repo.ListingPrice{ - Amount: contract.BuyerOrder.Payment.Amount, - CoinDivisibility: currencyDivisibilityFromContract(l.multiwallet, contract), - CurrencyCode: contract.BuyerOrder.Payment.Coin, - PriceModifier: contract.VendorListings[0].Metadata.PriceModifier, - }, - Slug: contract.VendorListings[0].Slug, - Thumbnail: repo.Thumbnail{contract.VendorListings[0].Item.Images[0].Tiny, contract.VendorListings[0].Item.Images[0].Small}, - Title: contract.VendorListings[0].Item.Title, - Type: "order", + BuyerHandle: contract.BuyerOrder.BuyerID.Handle, + BuyerID: contract.BuyerOrder.BuyerID.PeerID, + ID: repo.NewNotificationID(), + ListingType: contract.VendorListings[0].Metadata.ContractType.String(), + OrderId: orderId, + Price: currencyValue, + PriceModifier: contract.VendorListings[0].Metadata.PriceModifier, + Slug: contract.VendorListings[0].Slug, + Thumbnail: repo.Thumbnail{Tiny: contract.VendorListings[0].Item.Images[0].Tiny, Small: contract.VendorListings[0].Item.Images[0].Small}, + Title: contract.VendorListings[0].Item.Title, + Type: "order", } l.broadcast <- n - l.db.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + err = l.db.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } } } - record := &wallet.TransactionRecord{ - Timestamp: time.Now(), - Txid: txid, - Index: output.Index, - Value: output.Value, - Address: output.Address.String(), - } - records = append(records, record) - l.db.Sales().UpdateFunding(orderId, funded, records) - - // Save tx metadata - var thumbnail string - var title string - if contract.VendorListings[0].Item != nil && len(contract.VendorListings[0].Item.Images) > 0 { - thumbnail = contract.VendorListings[0].Item.Images[0].Tiny - title = contract.VendorListings[0].Item.Title - } - bumpable := false - if contract.BuyerOrder.Payment.Method != pb.Order_Payment_MODERATED { - bumpable = true - } - l.db.TxMetadata().Put(repo.Metadata{txid, "", title, orderId, thumbnail, bumpable}) -} + if unseenTx { + record := &wallet.TransactionRecord{ + Timestamp: time.Now(), + Txid: txid, + Index: output.Index, + Value: output.Value, + Address: output.Address.String(), + } + records = removeDuplicateRecords(append(records, record)) + err = l.db.Sales().UpdateFunding(orderId, funded, records) + if err != nil { + log.Error(err) + } -func currencyDivisibilityFromContract(mw multiwallet.MultiWallet, contract *pb.RicardianContract) uint32 { - var currencyDivisibility = contract.VendorListings[0].Metadata.CoinDivisibility - if currencyDivisibility != 0 { - return currencyDivisibility - } - wallet, err := mw.WalletForCurrencyCode(contract.BuyerOrder.Payment.Coin) - if err == nil { - return uint32(wallet.ExchangeRates().UnitsPerCoin()) + // Save tx metadata + var thumbnail string + var title string + if contract.VendorListings[0].Item != nil && len(contract.VendorListings[0].Item.Images) > 0 { + thumbnail = contract.VendorListings[0].Item.Images[0].Tiny + title = contract.VendorListings[0].Item.Title + } + bumpable := false + if contract.BuyerOrder.Payment.Method != pb.Order_Payment_MODERATED { + bumpable = true + } + if err := l.db.TxMetadata().Put(repo.Metadata{ + Txid: txid, + Address: "", + Memo: title, + OrderId: orderId, + Thumbnail: thumbnail, + CanBumpFee: bumpable, + }); err != nil { + log.Errorf("failed updating tx metadata (%s): %s", txid, err.Error()) + } } - return core.DefaultCurrencyDivisibility } func (l *TransactionListener) processPurchasePayment(txid string, output wallet.TransactionOutput, contract *pb.RicardianContract, state pb.OrderState, funded bool, records []*wallet.TransactionRecord) { - funding := output.Value + var ( + funding = output.Value + unseenTx = true + ) + for _, r := range records { - funding += r.Value - // If we have already seen this transaction for some reason, just return - if r.Txid == txid { - return + if r.Txid != txid { + funding = *new(big.Int).Add(&funding, &r.Value) + } else { + unseenTx = false } } orderId, err := calcOrderId(contract.BuyerOrder) if err != nil { return } - if !funded { - requestedAmount := int64(contract.BuyerOrder.Payment.Amount) - if funding >= requestedAmount { + + order, err := repo.ToV5Order(contract.BuyerOrder, nil) + if err != nil { + log.Error(err) + return + } + if !funded || (funded && state == pb.OrderState_AWAITING_PAYMENT) { + requestedAmount, _ := new(big.Int).SetString(order.Payment.BigAmount, 10) + if funding.Cmp(requestedAmount) >= 0 { log.Debugf("Payment for purchase %s detected", orderId) funded = true if state == pb.OrderState_AWAITING_PAYMENT && contract.VendorOrderConfirmation != nil { // Confirmed orders go to AWAITING_FULFILLMENT - l.db.Purchases().Put(orderId, *contract, pb.OrderState_AWAITING_FULFILLMENT, false) + if err := l.db.Purchases().Put(orderId, *contract, pb.OrderState_AWAITING_FULFILLMENT, false); err != nil { + log.Errorf("failed updating order (%s) to AWAITING_FULFILLMENT: %s", orderId, err.Error()) + } } else if state == pb.OrderState_AWAITING_PAYMENT && contract.VendorOrderConfirmation == nil { // Unconfirmed go into PENDING - l.db.Purchases().Put(orderId, *contract, pb.OrderState_PENDING, false) + if err := l.db.Purchases().Put(orderId, *contract, pb.OrderState_PENDING, false); err != nil { + log.Errorf("failed updating order (%s) to PENDING: %s", orderId, err.Error()) + } } } + def, err := repo.AllCurrencies().Lookup(order.Payment.AmountCurrency.Code) + if err != nil { + log.Errorf("Error looking up currency: %s", err) + return + } + cv, err := repo.NewCurrencyValue(funding.String(), def) + if err != nil { + log.Errorf("Error creating currency value: %s", err) + return + } n := repo.PaymentNotification{ - repo.NewNotificationID(), - "payment", - orderId, - uint64(funding), - contract.BuyerOrder.Payment.Coin, + ID: repo.NewNotificationID(), + Type: "payment", + OrderId: orderId, + FundingTotal: cv, + CoinType: order.Payment.AmountCurrency.Code, } l.broadcast <- n - l.db.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + err = l.db.Notifications().PutRecord(repo.NewNotification(n, time.Now(), false)) + if err != nil { + log.Error(err) + } } - record := &wallet.TransactionRecord{ - Txid: txid, - Index: output.Index, - Value: output.Value, - Address: output.Address.String(), - Timestamp: time.Now(), + if unseenTx { + record := &wallet.TransactionRecord{ + Txid: txid, + Index: output.Index, + Value: output.Value, + Address: output.Address.String(), + Timestamp: time.Now(), + } + records = removeDuplicateRecords(append(records, record)) + err = l.db.Purchases().UpdateFunding(orderId, funded, records) + if err != nil { + log.Error(err) + } } - records = append(records, record) - l.db.Purchases().UpdateFunding(orderId, funded, records) } func (l *TransactionListener) adjustInventory(contract *pb.RicardianContract) { @@ -324,30 +456,39 @@ func (l *TransactionListener) adjustInventory(contract *pb.RicardianContract) { if err != nil { continue } - q := int64(core.GetOrderQuantity(listing, item)) - newCount := c - q - if c < 0 { - newCount = -1 - } else if newCount < 0 { - newCount = 0 + itemQty := core.GetOrderQuantity(listing, item) + if itemQty.Cmp(big.NewInt(0)) <= 0 || !itemQty.IsInt64() { + // TODO: https://github.com/phoreproject/pm-go/issues/1739 + log.Errorf("unable to update inventory with invalid quantity") + continue + } + newCount := new(big.Int).Sub(c, itemQty) + if c.Cmp(big.NewInt(0)) < 0 { + newCount = big.NewInt(-1) + } else if newCount.Cmp(big.NewInt(0)) < 0 { + newCount = big.NewInt(0) } - if (c == 0) || (c > 0 && c-q < 0) { + if (c.Cmp(big.NewInt(0)) == 0) || (c.Cmp(big.NewInt(0)) > 0 && new(big.Int).Sub(c, itemQty).Cmp(big.NewInt(0)) < 0) { orderId, err := calcOrderId(contract.BuyerOrder) if err != nil { continue } log.Warningf("Order %s purchased more inventory for %s than we have on hand", orderId, listing.Slug) - l.broadcast <- repo.PremarshalledNotifier{[]byte(`{"warning": "order ` + orderId + ` exceeded on hand inventory for ` + listing.Slug + `"`)} + l.broadcast <- repo.PremarshalledNotifier{Payload: []byte(`{"warning": "order ` + orderId + ` exceeded on hand inventory for ` + listing.Slug + `"`)} + } + if err := l.db.Inventory().Put(listing.Slug, variant, newCount); err != nil { + log.Errorf("failed updating inventory for listing (%s, %d): %s", listing.Slug, variant, err.Error()) } - l.db.Inventory().Put(listing.Slug, variant, newCount) inventoryUpdated = true - if newCount >= 0 { + if newCount.Cmp(big.NewInt(0)) >= 0 { log.Debugf("Adjusting inventory for %s:%d to %d\n", listing.Slug, variant, newCount) } } if inventoryUpdated && core.Node != nil { - core.Node.PublishInventory() + if err := core.Node.PublishInventory(); err != nil { + log.Errorf("failed publishing inventory updates: %s", err.Error()) + } } } @@ -356,9 +497,21 @@ func calcOrderId(order *pb.Order) (string, error) { if err != nil { return "", err } - id, err := core.EncodeMultihash(ser) + id, err := ipfs.EncodeMultihash(ser) if err != nil { return "", err } return id.B58String(), nil } + +func removeDuplicateRecords(recs []*wallet.TransactionRecord) []*wallet.TransactionRecord { + keys := make(map[string]bool) + list := []*wallet.TransactionRecord{} + for _, entry := range recs { + if _, value := keys[entry.Txid]; !value { + keys[entry.Txid] = true + list = append(list, entry) + } + } + return list +} diff --git a/wallet/listeners/wallet_listener.go b/wallet/listeners/wallet_listener.go index c21874dd45..80a4095dfa 100644 --- a/wallet/listeners/wallet_listener.go +++ b/wallet/listeners/wallet_listener.go @@ -1,9 +1,11 @@ package bitcoin import ( + "math/big" + "github.com/OpenBazaar/wallet-interface" "github.com/phoreproject/multiwallet/util" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type WalletListener struct { @@ -19,27 +21,36 @@ func NewWalletListener(db repo.Datastore, broadcast chan repo.Notifier, coinType func (l *WalletListener) OnTransactionReceived(cb wallet.TransactionCallback) { if !cb.WatchOnly { - metadata, _ := l.db.TxMetadata().Get(cb.Txid) + metadata, err := l.db.TxMetadata().Get(cb.Txid) + if err != nil { + log.Debugf("tx metadata not found for id (%s): %s", cb.Txid, err.Error()) + } + status := "UNCONFIRMED" confirmations := 0 if cb.Height > 0 { status = "PENDING" confirmations = 1 } - n := repo.IncomingTransaction{ - Wallet: l.coinType.CurrencyCode(), + + txValue, err := repo.NewCurrencyValueWithLookup(cb.Value.String(), l.coinType.CurrencyCode()) + if err != nil { + log.Errorf("failed parsing currency value (%s %s): %s", cb.Value.String(), l.coinType.CurrencyCode(), err.Error()) + return + } + + l.broadcast <- repo.IncomingTransaction{ Txid: cb.Txid, - Value: cb.Value, + Value: txValue, Address: metadata.Address, Status: status, Memo: metadata.Memo, Timestamp: cb.Timestamp, Confirmations: int32(confirmations), - OrderId: metadata.OrderID, + OrderId: metadata.OrderId, Thumbnail: metadata.Thumbnail, Height: cb.Height, - CanBumpFee: cb.Value > 0, + CanBumpFee: cb.Value.Cmp(big.NewInt(0)) > 0, } - l.broadcast <- n } } diff --git a/wallet/resync/resync_manager.go b/wallet/resync/resync_manager.go index ba2e9b31f3..7f6259ca79 100644 --- a/wallet/resync/resync_manager.go +++ b/wallet/resync/resync_manager.go @@ -4,22 +4,25 @@ import ( "strings" "time" + "github.com/btcsuite/btcutil" + "github.com/op/go-logging" "github.com/phoreproject/multiwallet" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) var log = logging.MustGetLogger("ResyncManager") -var ResyncInterval = time.Hour +var ResyncInterval = time.Minute * 15 type ResyncManager struct { - sales repo.SaleStore - mw multiwallet.MultiWallet + sales repo.SaleStore + purchases repo.PurchaseStore + mw multiwallet.MultiWallet } -func NewResyncManager(salesDB repo.SaleStore, mw multiwallet.MultiWallet) *ResyncManager { - return &ResyncManager{salesDB, mw} +func NewResyncManager(salesDB repo.SaleStore, purchaseDB repo.PurchaseStore, mw multiwallet.MultiWallet) *ResyncManager { + return &ResyncManager{sales: salesDB, purchases: purchaseDB, mw: mw} } func (r *ResyncManager) Start() { @@ -30,42 +33,56 @@ func (r *ResyncManager) Start() { } func (r *ResyncManager) CheckUnfunded() { - unfunded, err := r.sales.GetNeedsResync() + unfundedSales, err := r.sales.GetUnfunded() if err != nil { - log.Error(err) + log.Errorf("get unfunded sales: %s", err) return } - if len(unfunded) == 0 { + unfundedPurchases, err := r.purchases.GetUnfunded() + if err != nil { + log.Errorf("get unfunded purchases: %s", err) return } - wallets := make(map[string]time.Time) - rollbackTime := time.Unix(2147483647, 0) - if r.mw != nil { - for cc := range r.mw { - wallets[strings.ToUpper(cc.CurrencyCode())] = rollbackTime - } + unfunded := append(unfundedSales, unfundedPurchases...) + if len(unfunded) == 0 { + return } + wallets := make(map[string][]string) for _, uf := range unfunded { - t, ok := wallets[strings.ToUpper(uf.PaymentCoin)] + addrs, ok := wallets[strings.ToUpper(uf.PaymentCoin)] if !ok { - log.Warningf("ResyncManager: no wallet for sale with payment coin %s", uf.PaymentCoin) - continue - } - if uf.Timestamp.Before(t) { - t = uf.Timestamp.Add(-time.Hour * 24) - wallets[strings.ToUpper(uf.PaymentCoin)] = t + addrs = []string{} } - r.sales.SetNeedsResync(uf.OrderId, false) + addrs = append(addrs, uf.PaymentAddress) + wallets[strings.ToUpper(uf.PaymentCoin)] = addrs } if r.mw != nil { - for cc, rbt := range wallets { + for cc, addrs := range wallets { wal, err := r.mw.WalletForCurrencyCode(cc) if err != nil { log.Warningf("ResyncManager: no wallet for sale with payment coin %s", cc) continue } - log.Infof("Rolling back %s blockchain %s looking for payments for %d orders\n", cc, time.Since(rbt), len(unfunded)) - wal.ReSyncBlockchain(rbt) + + var decodedAddresses []btcutil.Address + for _, addr := range addrs { + iaddr, err := wal.DecodeAddress(addr) + if err != nil { + log.Errorf("Error decoding unfunded payment address(%s): %s", addr, err) + continue + } + + decodedAddresses = append(decodedAddresses, iaddr) + } + + err = wal.AddWatchedAddresses(decodedAddresses...) + if err != nil { + log.Warningf("ResyncManager: couldn't add watched addresses for coin: %s", cc) + continue + } + + log.Infof("Rescanning %s wallet looking for %d orders", cc, len(unfunded)) + wal.ReSyncBlockchain(time.Time{}) } } } diff --git a/wallet/status.go b/wallet/status.go index de9eedec5b..22011937d6 100644 --- a/wallet/status.go +++ b/wallet/status.go @@ -5,14 +5,16 @@ import ( "encoding/json" "time" + "github.com/op/go-logging" "github.com/phoreproject/multiwallet" - "github.com/phoreproject/openbazaar-go/repo" + "github.com/phoreproject/pm-go/repo" ) type StatusUpdater struct { mw multiwallet.MultiWallet c chan repo.Notifier ctx context.Context + log *logging.Logger } type walletUpdateWrapper struct { @@ -20,17 +22,27 @@ type walletUpdateWrapper struct { } type walletUpdate struct { - Height uint32 `json:"height"` - Unconfirmed int64 `json:"unconfirmed"` - Confirmed int64 `json:"confirmed"` + Height uint32 `json:"height"` + Unconfirmed string `json:"unconfirmed"` + Confirmed string `json:"confirmed"` + Currency *repo.CurrencyDefinition `json:"currency"` } func NewStatusUpdater(mw multiwallet.MultiWallet, c chan repo.Notifier, ctx context.Context) *StatusUpdater { - return &StatusUpdater{mw, c, ctx} + var log = logging.MustGetLogger("walletStatus") + return &StatusUpdater{ + mw: mw, + c: c, + ctx: ctx, + log: log, + } } func (s *StatusUpdater) Start() { - t := time.NewTicker(time.Second * 15) + var ( + t = time.NewTicker(time.Second * 15) + ) + for { select { case <-t.C: @@ -38,15 +50,25 @@ func (s *StatusUpdater) Start() { for ct, wal := range s.mw { confirmed, unconfirmed := wal.Balance() height, _ := wal.ChainTip() + def, err := repo.MainnetCurrencies().Lookup(ct.CurrencyCode()) + if err != nil { + def, err = repo.TestnetCurrencies().Lookup(ct.CurrencyCode()) + if err != nil { + s.log.Errorf("unable to find definition (%s): %s", ct.CurrencyCode(), err.Error()) + continue + } + } u := walletUpdate{ Height: height, - Unconfirmed: unconfirmed, - Confirmed: confirmed, + Unconfirmed: unconfirmed.Value.String(), + Confirmed: confirmed.Value.String(), + Currency: &def, } - ret[ct.CurrencyCode()] = u + ret[def.CurrencyCode().String()] = u } ser, err := json.MarshalIndent(walletUpdateWrapper{ret}, "", " ") if err != nil { + s.log.Errorf("unable to marhsal wallet update: %s", err.Error()) continue } s.c <- repo.PremarshalledNotifier{ser}